LWJGL Forum

Programming => OpenAL => Topic started by: paulscode on March 31, 2008, 21:45:40

Title: Differences between appletloader natives and dll natives?
Post by: paulscode on March 31, 2008, 21:45:40
Hello, all!

I've noticed that on 3 of my test machines, sounds do not play if I am using the AppletLoader.  Also, no error message show up on the Java console.

However, if I copy and paste the same code into an application, the sounds play fine on those same test machines.

My conclusion is that the appletloader natives are compatible with fewer soundcards than the dll natives used in applications.

Therefore, I have the following questions:

1) Is my assumption true - is the appletloader less compatible, or am I doing something incorrectly?

2) How common is this incompatibility?  Is there a list of soundcards that the AppletLoader can not play sound on?

3) Is there a way to detect when a soundcard in incompatible with the appletloader?  I could not see a way to do this, since I am not getting any exceptions or error messages - just no sound.

4) Is this incompatibility likely to persist in future versions of lwjgl?

For reference, here is the source code for my applet:
Code: [Select]
import javax.swing.JApplet;
import java.awt.Graphics;

import java.net.URL;
import java.nio.IntBuffer;
import java.nio.FloatBuffer;

// From the lwjgl library, http://www.lwjgl.org
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;
import org.lwjgl.util.WaveData;

public class lwjglSoundTestApplet extends JApplet
{
    @Override
    public void init()
    {
        // Initialize:
        initOpenAL();
        initListener();
    }

    @Override
    public void paint( Graphics g )
    {
        //create a source, and play it:
        newSource( "tada.wav", 0, 0, 0, false );
        // Sleep a while to let the sound play:
        try
        {
            Thread.sleep( 3000 );
        }
        catch(Exception e){}
        System.exit( 0 );
    }
   
    // Initialize the Open AL stuff:
    private void initOpenAL()
    {
        try
        {
            AL.create();
        }
        catch( LWJGLException e )
        {
            e.printStackTrace();
            return;
        }
        AL10.alGetError();
    }
   
    // Position the listener:
    private void initListener()
    {
        FloatBuffer listenerPosition = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { 0.0f, 0.0f, 0.0f } );
        listenerPosition.flip();
       
        FloatBuffer listenerOrientation = BufferUtils.createFloatBuffer( 6 ).put (
            new float[] { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f } );
        listenerOrientation.flip();
       
        FloatBuffer listenerVelocity = BufferUtils.createFloatBuffer( 3 ).put (
            new float[] { 0.0f, 0.0f, 0.0f } );
        listenerVelocity.flip();
       
        AL10.alListener( AL10.AL_POSITION, listenerPosition );
        AL10.alListener( AL10.AL_VELOCITY, listenerVelocity );
        AL10.alListener( AL10.AL_ORIENTATION, listenerOrientation );
    }
   
    // Create a sound buffer and source, and play it:
    private void newSource( String filename, float x, float y, float z, boolean toLoop )
    {
        System.out.println( "Creating new source for " + filename );
        IntBuffer buffer = null;
       
        URL fileURL = getClass().getClassLoader().getResource( filename );
        if( fileURL == null )
        {
            System.err.println( "    Resource handle null after loading: " + filename );
            return;
        }
        WaveData waveFile = WaveData.create( fileURL );

        buffer = BufferUtils.createIntBuffer( 1 );
        AL10.alGenBuffers( buffer );
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    alGenBuffers error when loading: " + filename );
            return;
        }
       
        AL10.alBufferData( buffer.get( 0 ), waveFile.format, waveFile.data, waveFile.samplerate );
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    alBufferData error when loading: " + filename );
            return;
        }
       
        IntBuffer source = BufferUtils.createIntBuffer( 1 );
        try
        {
            AL10.alGenSources( source );
        }
        catch( Exception e )
        {
            System.err.println( "    Soundcard is out of voices" );
            return;
        }
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    alGenSources error when generating source for: " + filename );
            return;
        }       

        FloatBuffer sourcePosition = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { x, y, z } );
        sourcePosition.flip();
       
        FloatBuffer sourceVelocity = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { 0.0f, 0.0f, 0.0f } );
        sourceVelocity.flip();

        AL10.alSourcei( source.get( 0 ), AL10.AL_BUFFER, buffer.get(0) );
        AL10.alSourcef( source.get( 0 ), AL10.AL_PITCH, 1.0f );
        AL10.alSourcef( source.get( 0 ), AL10.AL_GAIN, 1.0f );
        AL10.alSource( source.get( 0 ), AL10.AL_POSITION, sourcePosition );
        AL10.alSource( source.get( 0 ), AL10.AL_VELOCITY, sourceVelocity );
       
        if( toLoop )
            AL10.alSourcei( source.get( 0 ), AL10.AL_LOOPING, AL10.AL_TRUE );  // looping
        else
            AL10.alSourcei( source.get( 0 ), AL10.AL_LOOPING, AL10.AL_FALSE );  // non-looping
       
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    Error creating a source for: " + filename );
            return;
        }
       
        AL10.alSourcePlay( source.get( 0 ) );
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    Error playing: " + filename );
            return;
        }
       
        System.out.println( "    Playing!" );
    }
}

And the application:
Code: [Select]
import java.net.URL;
import java.nio.IntBuffer;
import java.nio.FloatBuffer;

// From the lwjgl library, http://www.lwjgl.org
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;
import org.lwjgl.util.WaveData;

public class lwjglSoundTest
{
    // Constructor
    public lwjglSoundTest()
    {
        // Initialize, create a source, and play it:
        initOpenAL();
        initListener();
        newSource( "tada.wav", 0, 0, 0, false );
    }
    public static void main( String[] args )
    {
        // Create an instance of the lwjglSoundTest class:
        lwjglSoundTest myInstance = new lwjglSoundTest();
        // Sleep a while to let the sound play:
        try
        {
            Thread.sleep( 3000 );
        }
        catch(Exception e){}
    }
   
    // Initialize the Open AL stuff:
    private void initOpenAL()
    {
        try
        {
            AL.create();
        }
        catch( LWJGLException e )
        {
            e.printStackTrace();
            return;
        }
        AL10.alGetError();
    }
   
    // Position the listener:
    private void initListener()
    {
        FloatBuffer listenerPosition = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { 0.0f, 0.0f, 0.0f } );
        listenerPosition.flip();
       
        FloatBuffer listenerOrientation = BufferUtils.createFloatBuffer( 6 ).put (
            new float[] { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f } );
        listenerOrientation.flip();
       
        FloatBuffer listenerVelocity = BufferUtils.createFloatBuffer( 3 ).put (
            new float[] { 0.0f, 0.0f, 0.0f } );
        listenerVelocity.flip();
       
        AL10.alListener( AL10.AL_POSITION, listenerPosition );
        AL10.alListener( AL10.AL_VELOCITY, listenerVelocity );
        AL10.alListener( AL10.AL_ORIENTATION, listenerOrientation );
    }
   
    // Create a sound buffer and source, and play it:
    private void newSource( String filename, float x, float y, float z, boolean toLoop )
    {
        System.out.println( "Creating new source for " + filename );
        IntBuffer buffer = null;
       
        URL fileURL = getClass().getClassLoader().getResource( filename );
        if( fileURL == null )
        {
            System.err.println( "    Resource handle null after loading: " + filename );
            return;
        }
        WaveData waveFile = WaveData.create( fileURL );

        buffer = BufferUtils.createIntBuffer( 1 );
        AL10.alGenBuffers( buffer );
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    alGenBuffers error when loading: " + filename );
            return;
        }
       
        AL10.alBufferData( buffer.get( 0 ), waveFile.format, waveFile.data, waveFile.samplerate );
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    alBufferData error when loading: " + filename );
            return;
        }
       
        IntBuffer source = BufferUtils.createIntBuffer( 1 );
        try
        {
            AL10.alGenSources( source );
        }
        catch( Exception e )
        {
            System.err.println( "    Soundcard is out of voices" );
            return;
        }
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    alGenSources error when generating source for: " + filename );
            return;
        }       

        FloatBuffer sourcePosition = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { x, y, z } );
        sourcePosition.flip();
       
        FloatBuffer sourceVelocity = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { 0.0f, 0.0f, 0.0f } );
        sourceVelocity.flip();

        AL10.alSourcei( source.get( 0 ), AL10.AL_BUFFER, buffer.get(0) );
        AL10.alSourcef( source.get( 0 ), AL10.AL_PITCH, 1.0f );
        AL10.alSourcef( source.get( 0 ), AL10.AL_GAIN, 1.0f );
        AL10.alSource( source.get( 0 ), AL10.AL_POSITION, sourcePosition );
        AL10.alSource( source.get( 0 ), AL10.AL_VELOCITY, sourceVelocity );
       
        if( toLoop )
            AL10.alSourcei( source.get( 0 ), AL10.AL_LOOPING, AL10.AL_TRUE );  // looping
        else
            AL10.alSourcei( source.get( 0 ), AL10.AL_LOOPING, AL10.AL_FALSE );  // non-looping
       
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    Error creating a source for: " + filename );
            return;
        }
       
        AL10.alSourcePlay( source.get( 0 ) );
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.err.println( "    Error playing: " + filename );
            return;
        }
       
        System.out.println( "    Playing!" );
    }
}
Title: Re: Differences between appletloader natives and dll natives?
Post by: Matzon on March 31, 2008, 21:52:20
try playing your sound in another method than paint! - it might get called a gazillion times.
Title: Re: Differences between appletloader natives and dll natives?
Post by: paulscode on March 31, 2008, 22:14:20
try playing your sound in another method than paint! - it might get called a gazillion times.

This is just a demonstration applet, not the one I am actually using.  If you notice, I stuck in a sleep there to wait for the sound to play.  Obviously an ugly applet, but it works well enough to demonstrate my point.

This applet works all my test machines except the three I mentioned before, and all my original questions apply.
Title: Re: Differences between appletloader natives and dll natives?
Post by: kappa on April 01, 2008, 18:41:59
You can run your the applet without using the appletloader, as just a normal applet (note you'll have to add the natives to the class path though), if it does not work as a normal applet then it probably won't work with appletloader.

Quote
1) Is my assumption true - is the appletloader less compatible, or am I doing something incorrectly?

you should blame your own code before the library you are using  ;D

Quote
2) How common is this incompatibility?  Is there a list of soundcards that the AppletLoader can not play sound on?

appletloader uses no sound files or does not access any sound resource, so its unlikely to be caused by the appletloader.

Quote
4) Is this incompatibility likely to persist in future versions of lwjgl?

remember appletloader isn't a way to easily convert your application into an applet, you still need to make a normal applet, appletloader is just a class to help deploy your LWJGL applet more smoothly and should be used once your normal applet is running and working.

can you try as a normal applet without the appletloader and see if it works?
Title: Re: Differences between appletloader natives and dll natives?
Post by: paulscode on April 01, 2008, 19:49:30
Ok, I am having trouble running the applet without the appletloader.  Java Console is showing the following message:
Code: [Select]
java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path
        at java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.lang.Runtime.loadLibrary0(Unknown Source)
        at java.lang.System.loadLibrary(Unknown Source)
        at org.lwjgl.Sys$1.run(Sys.java:75)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.lwjgl.Sys.doLoadLibrary(Sys.java:68)
        at org.lwjgl.Sys.loadLibrary(Sys.java:84)
        at org.lwjgl.Sys.<clinit>(Sys.java:101)
        at org.lwjgl.openal.AL.<clinit>(AL.java:59)
        at lwjglSoundTestApplet.initOpenAL(lwjglSoundTestApplet.java:44)
        at lwjglSoundTestApplet.init(lwjglSoundTestApplet.java:23)
        at sun.applet.AppletPanel.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

I am including the following for both compile- and run-time libraries:
Code: [Select]
jinput.jar
linux_natives.jar
lwjgl.jar
lwjgl_applet.jar
lwjgl_util.jar
lwjgl_util_applet.jar
macosx_natives.jar
natives.jar
res.jar
windows_natives.jar

And my HTML file looks like this:
Code: [Select]
<html>
    <head>
        <title>lwjgl Sound Test Applet</title>
    </head>
    <body>
        <applet code="lwjglSoundTestApplet"
                archive="jinput.jar,
                        linux_natives.jar,
                        lwjgl.jar,
                        lwjgl_applet.jar,
                        lwjgl_util.jar,
                        lwjgl_util_applet.jar,
                        lwjglSoundTestApplet.jar,
                        macosx_natives.jar,
                        natives.jar,
                        res.jar,
                        windows_natives.jar"
                width=640
                height=480
                MAYSCRIPT>
        </applet>
    </body>
</html>

So what am I doing wrong?

you should blame your own code before the library you are using  ;D
I tend to agree (which is why my first question was "Am I doing something incorrectly"), but you have to admit that the fact the applet works fine on certain soundcards but not others, seems more like an issue with the library, than with my code (especially in an applet as simple as the one I listed here).
Title: Re: Differences between appletloader natives and dll natives?
Post by: kappa on April 01, 2008, 20:08:08
(note you'll have to add the natives to the class path though)

you have to add

Quote
-Djava.library.path=c:\lwjgl\native\win32

as a vm argument to get it working
Title: Re: Differences between appletloader natives and dll natives?
Post by: paulscode on April 01, 2008, 20:14:03
you have to add

-Djava.library.path=c:\lwjgl\native\win32

as a vm argument to get it working

How is that done in an applet?  My understanding of Java was that you can't control how the browser itself starts up the JVM?
Title: Re: Differences between appletloader natives and dll natives?
Post by: kappa on April 01, 2008, 21:04:08
you can do it in eclipse for example but putting the argument in the vm argument box.
Title: Re: Differences between appletloader natives and dll natives?
Post by: paulscode on April 01, 2008, 21:45:34
Ok, figured out how to do it in NetBeans, and it plays fine on the three problem test machines.  However, since in this case we are using the .dll's, that's what I expected.  This adds more support to my original conclusion, that using the native .dll's is compatible with more soundcards than when using the appletloader.  So at this point is it safe to assume that question #1 is answered, and there is not a problem with my code?

Now, let me rephrase my remaining questions, so I don't get flamed by people who don't understand what I am trying to ask:

2) How common is this issue?  Is there a list of soundcards that sound will not play on, when running an applet using the AppletLoader?

3) Is there a way to detect when sounds are not playing, when running an applet using the appletloader?  I could not see a way to do this, since I am not getting any exceptions or error messages (and AL_SOURCE_STATE equals AL_PLAYING)

4) Is this issue likely to persist in future versions of lwjgl?

Title: Re: Differences between appletloader natives and dll natives?
Post by: kappa on April 01, 2008, 22:12:10
are you including OpenAL.dll when using appletloader?
Title: Re: Differences between appletloader natives and dll natives?
Post by: paulscode on April 01, 2008, 22:27:37
are you including OpenAL.dll when using appletloader?

No I am not.  I do not see any option for including the dll when using the appletloader.

Are you asking if the native OpenAL32.dll file is located on the test machines?  If so, yes I believe so (I installed the latest version of OpenAL on them, which I assume added OpenAL32.dll).  I would expect to see a runtime error if this were the problem, but I will go double check to be sure OpenAL32.dll is on those machines.
Title: Re: Differences between appletloader natives and dll natives?
Post by: paulscode on April 01, 2008, 22:40:12
Ok, I made sure OpenAL32.dll was in C:\Windows\System32.  It was already there, but I replaced it just in case it was corrupt or something.
No effect.

I also tried opening the html file locally on the test machine with the OpenAL32.dll file in the same directory, but that did not help either.

That was a good suggestion, though.  Thanks.
Title: Re: Differences between appletloader natives and dll natives?
Post by: paulscode on April 02, 2008, 00:29:15
I had a couple of ideas I would like to try.

First, does anybody have links to applets using OpenAL sound that are loading with the appletloader?  It would be helpful to see if this problem is happening for every OpenAL applet.

Second, could some people try out my applet and let me know if the sound works for them, and what soundcard they are using?  If I could get more tests done, I could determine how common this problem is, or if it is only isolated to the three test machines I mentioned above.  Link to the real applet is:
http://www.paulscode.com/source/SoundManager/25MAR2008/SoundApplet.html (http://www.paulscode.com/source/SoundManager/25MAR2008/SoundApplet.html)

I'll try and get testers from other forums and chatrooms as well.  In a couple of days, I'll post the results of these tests.

Thanks in advance for helping me out with this!
Title: Re: Differences between appletloader natives and dll natives?
Post by: kappa on April 02, 2008, 09:13:47
Usually when using lwjgl theres an OpenAL.dll that comes with lwjgl and is usually kept in the same place as the lwjgl.dll, so when using lwjgl applet if your using openal you should put opengl.dll that comes with lwjgl with the other lwjgl native (i.e. in the same jar as lwjgl.dll). I have tested your app and do not get any sound.

I have a really old applet that i did, you can try and see if you get sound with it http://kappa.javaunlimited.net/betashot/betashot.html
Title: Re: Differences between appletloader natives and dll natives?
Post by: paulscode on April 02, 2008, 23:36:45
The sound works fine on the test machines for that applet.  Since I am not putting any dll's into any new jar's, this may be the source of my problem.  Actually, if this is a requirement for the appletloader, I'm not sure why the applet works on ANY computer at all ???  I had assumed since the applet works fine on most of my computers, I must have created the applet correctly.  If the dll's, etc were not there, why would the applet work on any computer?

I now just have to figure out what you did differently with your applet than I am doing with mine.  I looked at your html, and it appears to be the same as mine, so I do not think there is any problem there (but I will go over it again with a fine-tooth comb to be sure).

So now I have some new questions:

1)  I thought the natives dll's, so's, jnlib's, and dylib's were already compiled into the natives jar's (linux_natives.jar, macosx_natives.jar, windows_natives.jar, which were included with the appletloader).  Is this assumption incorrect?

2)  In your applet above, did you compile the natives dll's, etc. into new jar's, or did you use the natives jar's I mentioned above, which came with the appletloader?

The rest of my questions are for if I must compile the natives dll's, etc. into a new jar.  These are not question's about how to use the natives jar's that came with the appletloader, or about the appletloader's OS compatability (the demo applet that comes with the appletloader is pretty self-explanatory)

3)  Am I only able to run my applet on a single operating system? (eg, if I only put in the windows natives dll's, then it will only run on a computer running windows.)

4)  Is there a way to include all three types of natives?

5)  What package/subdirectory do the dll's, etc. go into inside the jar?

Thank you very much for your help!
Title: Re: Differences between appletloader natives and dll natives?
Post by: paulscode on April 05, 2008, 00:16:05
I solved the problem.  I was WAY off track with the whole natives discussion.

SOLUTION (IMPORTANT FOR ANYONE USING SOUND IN THEIR APPLET!):
Sound must not be initialized in an applet's init() method!

Simply moving the code out of the init() method fixed it.  Yes ... it was that simple.  Probably a thread issue, couldn't say.


you should blame your own code before the library you are using  ;D

Sound advice, oh wise javalwjgl ...