From 06a3aaa5fd38097a4644921a269d6ca282fb31eb Mon Sep 17 00:00:00 2001
From: Xerxes Rånby
Well, here we go. I've decided to only go over bits of the +
Well, here we go.
++import java.io.*; +import java.nio.*; +import java.util.*; + +import com.jogamp.openal.*; +import com.jogamp.openal.util.*; + +public class SourceSharingBuffers { + +static ALC alc; static AL al; // These index the buffers. @@ -57,9 +67,24 @@ tutorial from DevMaster.net to JOAL. // Buffers hold sound data. static int[] buffers = new int[NUM_BUFFERS]; -// A vector list of sources for multiple emissions. -Vector sources = new Vector(); +// A list of sources for multiple emissions. +static List sources = new ArrayList(); + +// Position of the source sounds. +static float[] sourcePos = { 0.0f, 0.0f, 0.0f }; + +// Velocity of the source sounds. +static float[] sourceVel = { 0.0f, 0.0f, 0.0f }; + +// Position of the listener. +static float[] listenerPos = { 0.0f, 0.0f, 0.0f }; + +// Velocity of the listener. +static float[] listenerVel = { 0.0f, 0.0f, 0.0f }; + +// Orientation of the listener. (first 3 elements are "at", second 3 are "up") +static float[] listenerOri = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
First I've written out a few macros that we can use to index the buffer array. We will be using several wav files so we need quite a few @@ -69,11 +94,13 @@ Vector sources = new Vector(); of them. This is also the first tutorial where we will deal with sources as being a resource that will run out. And yes, they will run out; they are finite.
static int initOpenAL() { - - ALC.Device device; - ALC.Context context; + al = ALFactory.getAL(); + alc = ALFactory.getALC(); + ALCdevice device; + ALCcontext context; String deviceSpecifier; - String deviceName = "DirectSound3D"; + String deviceName = "DirectSound3D"; // You may choose to open a specific OpenAL device if you know its name. + deviceName = null; // Passing a null String to alcOpenDevice will open the default device on your system! // Get handle to device. device = alc.alcOpenDevice(deviceName); @@ -81,7 +108,7 @@ Vector sources = new Vector(); // Get the device specifier. deviceSpecifier = alc.alcGetString(device, ALC.ALC_DEVICE_SPECIFIER); - System.out.println("Using device " + deviceSpecifier); + System.out.println("Using device " + deviceSpecifier); // Create audio context. context = alc.alcCreateContext(device, null); @@ -90,7 +117,7 @@ Vector sources = new Vector(); alc.alcMakeContextCurrent(context); // Check for an error. - if (alc.alcGetError() != ALC.ALC_NO_ERROR) + if (alc.alcGetError(device) != ALC.ALC_NO_ERROR) return AL.AL_FALSE; return AL.AL_TRUE; @@ -101,8 +128,8 @@ Vector sources = new Vector(); context for our application. This context is set to current and the function will check if everything went smoothly before we return success.static void exitOpenAL() { - ALC.Context curContext; - ALC.Device curDevice; + ALCcontext curContext; + ALCdevice curDevice; // Get the current context. curContext = alc.alcGetCurrentContext(); @@ -137,34 +164,34 @@ Vector sources = new Vector(); int[] loop = new int[1]; // Load wav data into buffers. - al.alGenBuffers(NUM_BUFFERS, buffers); + al.alGenBuffers(NUM_BUFFERS, buffers, 0); if(al.alGetError() != AL.AL_NO_ERROR) return AL.AL_FALSE; ALut.alutLoadWAVFile("wavdata/thunder.wav", format, data, size, freq, loop); al.alBufferData(buffers[THUNDER], format[0], data[0], size[0], freq[0]); - ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]); + ALut.alutLoadWAVFile("wavdata/waterdrop.wav", format, data, size, freq, loop); al.alBufferData(buffers[WATERDROP], format[0], data[0], size[0], freq[0]); - ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]); + ALut.alutLoadWAVFile("wavdata/stream.wav", format, data, size, freq, loop); al.alBufferData(buffers[STREAM], format[0], data[0], size[0], freq[0]); - ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]); + ALut.alutLoadWAVFile("wavdata/rain.wav", format, data, size, freq, loop); al.alBufferData(buffers[RAIN], format[0], data[0], size[0], freq[0]); - ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]); + ALut.alutLoadWAVFile("wavdata/ocean.wav", format, data, size, freq, loop); al.alBufferData(buffers[OCEAN], format[0], data[0], size[0], freq[0]); - ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]); + ALut.alutLoadWAVFile("wavdata/chimes.wav", format, data, size, freq, loop); al.alBufferData(buffers[CHIMES], format[0], data[0], size[0], freq[0]); - ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]); + // Do another error check and return. if (al.alGetError() != AL.AL_NO_ERROR) @@ -178,7 +205,7 @@ Vector sources = new Vector();-static void addSource(int type) { int[] source = new int[1]; - al.alGenSources(1, source); + al.alGenSources(1, source, 0); if (al.alGetError() != AL.AL_NO_ERROR) { System.err.println("Error generating audio source."); @@ -186,17 +213,22 @@ Vector sources = new Vector(); } al.alSourcei (source[0], AL.AL_BUFFER, buffers[type]); - al.alSourcef (source[0], AL.AL_PITCH, 1.0 ); - al.alSourcef (source[0], AL.AL_GAIN, 1.0 ); - al.alSourcefv(source[0], AL.AL_POSITION, sourcePos ); - al.alSourcefv(source[0], AL.AL_VELOCITY, sourceVel ); + al.alSourcef (source[0], AL.AL_PITCH, 1.0f ); + al.alSourcef (source[0], AL.AL_GAIN, 1.0f ); + al.alSourcefv(source[0], AL.AL_POSITION, sourcePos , 0); + al.alSourcefv(source[0], AL.AL_VELOCITY, sourceVel , 0); al.alSourcei (source[0], AL.AL_LOOPING, AL.AL_TRUE ); - al.alSourcePlay(source); + al.alSourcePlay(source[0]); - sources.put(new Integer(source[0])); + sources.add(new Integer(source[0])); } +static void setListenerValues() { + al.alListenerfv(AL.AL_POSITION, listenerPos, 0); + al.alListenerfv(AL.AL_VELOCITY, listenerVel, 0); + al.alListenerfv(AL.AL_ORIENTATION, listenerOri, 0); +}Here's the function that will generate the sources for us. This function will generate a single source for any one of the loaded buffers @@ -208,17 +240,29 @@ Vector sources = new Vector(); Iterator iter = sources.iterator(); while(iter.hasNext()) { - al.alDeleteSources(1, new int[] { ((Integer)iter.next()).intValue() }); + al.alDeleteSources(1, new int[] { ((Integer)iter.next()).intValue() }, 0); } sources.clear(); - al.alDeleteBuffers(NUM_BUFFERS, buffers); + al.alDeleteBuffers(NUM_BUFFERS, buffers, 0); exitOpenAL(); }
This function has been modified a bit to accommodate the Vector. +
This function has been modified a bit to accommodate the List. We have to delete each source in the list individually and then clear the list which will effectively destroy it.
-char[] c = new char[1]; +++ public static void main(String[] args) { + try { + initOpenAL(); + } catch (ALException e) { + e.printStackTrace(); + System.exit(1); + } + if (loadALData() == AL.AL_FALSE) + System.exit(1); + setListenerValues(); + + char[] c = new char[1]; while(c[0] != 'q') { try { @@ -240,12 +284,15 @@ Vector sources = new Vector(); case 'r': addSource(RAIN); break; case 'o': addSource(OCEAN); break; case 'c': addSource(CHIMES); break; -} + } } catch (IOException e) { System.exit(1); } - }-Here is the programs inner loop taken straight out of our main. + } + killALData(); + } // main +} // class
Here is the programs inner loop. Basically it waits for some keyboard input and on certain key hits it will create a new source of a certain type and add it to the audio scene. Essentially what we have created here is something like one of those nature tapes that people -- cgit v1.2.3