Beginner at OpenAL

Started by Andrew_3ds, April 16, 2015, 23:03:09

Previous topic - Next topic

Andrew_3ds

I am trying to use OpenAL in my game, but I can't figure it out at all. I have tried several tutorials and none of them worked, I either got errors or no sound at all. Can someone show some example code of loading a sound and playing it?

abcdef

Here is how I see OpenAL


  • It's input is raw header-less PCM data
  • There are 2 ways to pass in data, 1) everything at once 2) stream it in a packet of audio data at a time
  • When you tell OpenAL to play data you are effectively telling it to play the next packet of audio data so to get a constant sound you need to constantly call the play command in your render loop
  • OpenAL provides methods for you to buffer up these packets so that there is always data ready to go (for the streaming method)

Here is how I load the sound

Loading the sound

        if (!soundStream.hasStreamData())
        {
            // load all the data
            int buffer = alGenBuffers();
            ByteBuffer sample = soundStream.getAllSamples();
            alBufferData(buffer, AL_FORMAT_STEREO16, sample, soundStream.getSampleRate());
            alSourcei(soundStream.getSoundId(), AL_BUFFER, buffer);

        } else
        {
            // upfront load some buffered data
            for (int i = 0; i < numberSoundBuffers; i++)
            {
                int buffer = alGenBuffers();
                ByteBuffer sample = soundStream.readNextSample();
                alBufferData(buffer, AL_FORMAT_STEREO16, sample, soundStream.getSampleRate());
                alSourceQueueBuffers(soundStream.getSoundId(), buffer);
            }
        }


This is the code I call each cycle in my game loop

        if (soundStream.hasStreamData())
        {
            // remove any buffers already played and replace with new ones
            int currentBuffersProcessed = alGetSourcei(soundStream.getSoundId(), AL_BUFFERS_PROCESSED);

            for (int i = 0; i < currentBuffersProcessed; i++)
            {
                int buffer = alSourceUnqueueBuffers(soundStream.getSoundId());
                alDeleteBuffers(buffer);
                buffer = alGenBuffers();
                ByteBuffer sample = soundStream.readNextSample();
                if (sample == null)
                {
                    return;
                }
                alBufferData(buffer, AL_FORMAT_STEREO16, sample, soundStream.getSampleRate());
                alSourceQueueBuffers(soundStream.getSoundId(), buffer);
            }
        }

        if (alGetSourcei(soundStream.getSoundId(), AL_SOURCE_STATE) != AL_PLAYING)
        {
            alSourcePlay(soundStream.getSoundId());
        }


The old LWJGL 2 wiki uses some LWJGL code to load in a WAV file, this might be an easy way to get started. I have posted some code from the wiki to help you load WAV files.

    java.io.FileInputStream fin = null;
    try {
      fin = new java.io.FileInputStream("FancyPants.wav");
    } catch (java.io.FileNotFoundException ex) {
      ex.printStackTrace();
      return AL10.AL_FALSE;
    }
    WaveData waveFile = WaveData.create(fin);
    try {
      fin.close();
    } catch (java.io.IOException ex) {
    }*/
 
    //Loads the wave file from this class's package in your classpath
    WaveData waveFile = WaveData.create("FancyPants.wav");
 
    AL10.alBufferData(buffer.get(0), waveFile.format, waveFile.data, waveFile.samplerate);
    waveFile.dispose();

Andrew_3ds

Thank you, its working now, but can you explain the streaming part a little bit more? I don't quite understand the streaming part, but I can play pre-loaded files just fine

abcdef

You either load the entire file upfront or you just load the headers and load chunks of the data as you need it.

For a long playing song you might want to load the data on demand but for small sound effects you will probably want to load everything in to memory and play them as needed