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?
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();
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
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