From da8d0035ab293f5e10bef611465c446e35a6b31e Mon Sep 17 00:00:00 2001 From: athomas Date: Sun, 29 Jun 2003 04:07:03 +0000 Subject: check-in of lesson 3 git-svn-id: file:///home/mbien/NetBeansProjects/JOGAMP/joal-sync/svn-server-sync-demos/joal-demos/trunk@25 235fdd13-0e8c-4fed-b5ee-0a390d04b286 --- www/devmaster/lesson3.html | 294 +++++++++++++++++++++++++++++++++++++++++++++ www/devmaster/lesson3.zip | Bin 0 -> 313641 bytes www/index.html | 2 + 3 files changed, 296 insertions(+) create mode 100644 www/devmaster/lesson3.html create mode 100644 www/devmaster/lesson3.zip diff --git a/www/devmaster/lesson3.html b/www/devmaster/lesson3.html new file mode 100644 index 0000000..e3a6d90 --- /dev/null +++ b/www/devmaster/lesson3.html @@ -0,0 +1,294 @@ + + + + DevMaster.net Game Development + +
+ +
+ +Wiki +Weblogs +Forums +JavaGames Home +www.java.net + +
+OpenAL Tutorials from DevMaster.net. Reprinted with Permission.
+
+ + + + + + +

OpenAL + Tutorials

DevMaster.net

+ +

Multiple Sources
+
Lesson 3

+ +

Author: Jesse + Maurais
+ Adapted for Java by: Athomas Goldberg

+

Hello. It's been a while since my last tutorial. But better + late than never I guess. Since I'm sure your all impatient to read the latest + tutorial, I'll just jump right into it. What we hope to accomplish with this + one is to be able to play more that one audio sample at a time. Very intense + games have all kinds of stuff going on usually involving different sound clips. + It won't be hard to implement any of this though. Doing multiple sounds is similar + to doing just one.

+ +
+
+import java.nio.ByteBuffer;
+import java.util.Random;
+
+import net.java.games.joal.AL;
+import net.java.games.joal.ALFactory;
+import net.java.games.joal.util.ALut;
+  
+public class MultipleSources {
+
+    static AL al;
+
+    // Maximum number of buffers we will need.
+    static final int NUM_BUFFERS = 3;
+
+    // Maximum emissions we will need.
+    static final int NUM_SOURCES = 3;
+
+    // These index the buffers and sources
+    static final int BATTLE = 0;
+    static final int GUN1   = 1;
+    static final int GUN2   = 2;
+
+    // Buffers hold sound data
+    static int[] buffers = new int[NUM_BUFFERS];
+
+    // Sources are points of emitting sound
+    static int[] sources = new int[NUM_SOURCES];
+
+    // Position of the source sounds.
+    static float[][] sourcePos = new float[NUM_SOURCES][3];
+
+    // Velocity of the source sounds
+    static float[][] sourceVel = new float[NUM_SOURCES][3];
+
+    // 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 };
+
+

I guess this little piece of source code will be familiar to + a lot of you who've read the first two tutorials. The only difference is that + we now have 3 different sound effects that we are going to load into the OpenAL + sound system.

+ +
+
+    static int loadALData() {
+
+        //variables to load into
+
+        int[] format = new int[1];
+        int[] size = new int[1];
+        ByteBuffer[] data = new ByteBuffer[1];
+        int[] freq = new int[1];
+        int[] loop = new int[1];
+        
+        // load wav data into buffers
+
+        al.alGenBuffers(NUM_BUFFERS, buffers);
+        if (al.alGetError() != AL.AL_NO_ERROR) {
+            return AL.AL_FALSE;
+        }
+
+        ALut.alutLoadWAVFile(
+            "wavdata/Battle.wav",
+            format,
+            data,
+            size,
+            freq,
+            loop);
+        al.alBufferData(
+            buffers[BATTLE],
+            format[0],
+            data[0],
+            size[0],
+            freq[0]);
+        ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]);
+
+        ALut.alutLoadWAVFile(
+            "wavdata/Gun1.wav",
+            format,
+            data,
+            size,
+            freq,
+            loop);
+        al.alBufferData(
+            buffers[GUN1],
+            format[0],
+            data[0],
+            size[0],
+            freq[0]);
+        ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]);
+
+        ALut.alutLoadWAVFile(
+            "wavdata/Gun2.wav",
+            format,
+            data,
+            size,
+            freq,
+            loop);
+        al.alBufferData(
+            buffers[GUN2],
+            format[0],
+            data[0],
+            size[0],
+            freq[0]);
+        ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]);
+
+        // bind buffers into audio sources
+        al.alGenSources(NUM_SOURCES, sources);
+
+        al.alSourcei(sources[BATTLE], AL.AL_BUFFER, buffers[BATTLE]);
+        al.alSourcef(sources[BATTLE], AL.AL_PITCH, 1.0f);
+        al.alSourcef(sources[BATTLE], AL.AL_GAIN, 1.0f);
+        al.alSourcefv(sources[BATTLE], AL.AL_POSITION, sourcePos[BATTLE]);
+        al.alSourcefv(sources[BATTLE], AL.AL_POSITION, sourceVel[BATTLE]);
+        al.alSourcei(sources[BATTLE], AL.AL_LOOPING, AL.AL_TRUE);
+
+        al.alSourcei(sources[GUN1], AL.AL_BUFFER, buffers[GUN1]);
+        al.alSourcef(sources[GUN1], AL.AL_PITCH, 1.0f);
+        al.alSourcef(sources[GUN1], AL.AL_GAIN, 1.0f);
+        al.alSourcefv(sources[GUN1], AL.AL_POSITION, sourcePos[GUN1]);
+        al.alSourcefv(sources[GUN1], AL.AL_POSITION, sourceVel[GUN1]);
+        al.alSourcei(sources[GUN1], AL.AL_LOOPING, AL.AL_FALSE);
+
+        al.alSourcei(sources[GUN2], AL.AL_BUFFER, buffers[GUN2]);
+        al.alSourcef(sources[GUN2], AL.AL_PITCH, 1.0f);
+        al.alSourcef(sources[GUN2], AL.AL_GAIN, 1.0f);
+        al.alSourcefv(sources[GUN2], AL.AL_POSITION, sourcePos[GUN2]);
+        al.alSourcefv(sources[GUN2], AL.AL_POSITION, sourceVel[GUN2]);
+        al.alSourcei(sources[GUN2], AL.AL_LOOPING, AL.AL_FALSE);
+
+        // do another error check and return
+        if (al.alGetError() != AL.AL_NO_ERROR) {
+            return AL.AL_FALSE;
+        }
+
+        return AL.AL_TRUE;
+    }
+
+
+

This code looks quite a bit different at first, but it isn't + really. Basically we load the file data into our 3 buffers, then lock the 3 + buffers to our 3 sources relatively. The only other difference is that the "Battle.wav" + (Source index 0) is looping while the rest are not.

+
+
+    static void setListenerValues() {
+        al.alListenerfv(AL.AL_POSITION, listenerPos);
+        al.alListenerfv(AL.AL_VELOCITY, listenerVel);
+        al.alListenerfv(AL.AL_ORIENTATION, listenerOri);
+    }
+
+    static void killAllData() {
+        al.alDeleteBuffers(NUM_BUFFERS, buffers);
+        al.alDeleteSources(NUM_SOURCES, sources);
+        ALut.alutExit();
+    }
+
+

I don't think we changed anything in this code.

+ +
    public static void main(String[] args) {
+        al = ALFactory.getAL();
+
+		// Initialize OpenAL and clear the error bit
+
+        ALut.alutInit();
+        al.alGetError();
+        
+		// Load the wav data.
+
+        if(loadALData() == AL.AL_FALSE) {
+            System.exit(1);    
+        }
+        setListenerValues();
+
+		// begin the battle sample to play
+
+        al.alSourcePlay(sources[BATTLE]);
+        long startTime = System.currentTimeMillis();
+        long elapsed = 0;
+        long totalElapsed = 0;
+        Random rand = new Random();
+        int[] state = new int[1];
+        while (totalElapsed < 10000) {
+            elapsed = System.currentTimeMillis() - startTime;
+            if (elapsed > 50) {
+                totalElapsed += elapsed;
+                startTime = System.currentTimeMillis();
+				
+                // pick one of the sources at random and check to see if it is playing.
+                // Skip the first source because it is looping anyway (will always be playing).
+                
+				 int pick = Math.abs((rand.nextInt()) % 2) + 1;
+                al.alGetSourcei(sources[pick], AL.AL_SOURCE_STATE, state);
+				
+                if (state[0] != AL.AL_PLAYING) {
+				
+				    // pick a random position around the listener to play the source.
+				
+                    double theta = (rand.nextInt() % 360) * 3.14 / 180.0;
+                    sourcePos[pick][0] = - ((float) Math.cos(theta));
+                    sourcePos[pick][1] = - ((float) (rand.nextInt() % 2));
+                    sourcePos[pick][2] = - ((float) Math.sin(theta));
+
+                    al.alSourcefv(
+                        sources[pick],
+                        AL.AL_POSITION,
+                        sourcePos[pick]);
+
+                    al.alSourcePlay(sources[pick]);
+                }
+            }
+        }
+        killAllData();
+    }
+}
+
+ +

Here is the interesting part of this tutorial. We go through + each of the sources to make sure it's playing. If it is not then we set it to + play but we select a new point in 3D space for it to play (just for kicks). +

+

And bang! We are done. As most of you have probably seen, you + don't have to do anything special to play more than one source at a time. OpenAL + will handle all the mixing features to get the sounds right for their respective + distances and velocities. And when it comes right down to it, isn't that the + beauty of OpenAL?

+

You know that was a lot easier than I thought. I don't know + why I waited so long to write it. Anyway, if anyone reading wants to see something + specific in future tutorials (not necessarily pertaining to OpenAL, I have quite + an extensive knowledge base) drop me a line at lightonthewater@hotmail.com + I plan to do tutorials on sharing buffers and the Doppler effect in some later + tutorial unless there is request for something else. Have fun with the code!

+

Download the Java + source and Ant build file

+ + + + + +

© 2003 DevMaster.net. + All rights reserved.

+ Contact us if you + want to write for us or for any comments, suggestions, or feedback.

+ + \ No newline at end of file diff --git a/www/devmaster/lesson3.zip b/www/devmaster/lesson3.zip new file mode 100644 index 0000000..ae81626 Binary files /dev/null and b/www/devmaster/lesson3.zip differ diff --git a/www/index.html b/www/index.html index c003aab..76b55e3 100644 --- a/www/index.html +++ b/www/index.html @@ -98,6 +98,8 @@ Static Source
  • lesson 2: Looping and Fadeaway
  • +
  • lesson 3: Multiple + Sources
  • -- cgit v1.2.3