Jogamp
dbd582c5eeac5ddf4091bc01d3dd691571502675
[joal-demos.git] / www / devmaster / lesson5.html
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2 <html>
3 <head>
4 <title>JOAL OpenAL Tutorials from DevMaster.net Lesson 5: Sources Sharing Buffers</title>
5 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
6 <link rel="stylesheet" type="text/css" href="general.css">
7 </head>
8 <body>
9 <a href="../index.html"><img src="../../../images/jogamp_symbols/website_final_blue_joal_346x70pel.png" alt="JOAL Symbol"></a><a href="http://www.openal.org"><img src="../openal_c.gif"></a>
10 <br>
11 OpenAL Tutorials from DevMaster.net. Reprinted with Permission.<br>
12 <br>
13 <table border="0" cellspacing="0" style="border-collapse: collapse" width="100%" cellpadding="0" id="AutoNumber1" height="12" bgcolor="#666699">
14   <tr> 
15     <td width="47%" height="12" valign="middle"><p><b><font color="#FFFFFF">OpenAL 
16         Tutorials</font></b></p></td>
17     <td width="53%" height="12" align="right" valign="middle"><p align="right"><a href="http://devmaster.net/"><font color="#66FF99">DevMaster.net</font></a></p></td>
18   </tr>
19 </table>
20 <p class="ArticleTitle"><font size="5">Sources Sharing Buffers<br>
21   </font><strong><font size="4">Lesson 5</font></strong></p>
22 <p align="right" class="ArticleAuthor">Author: <a href="mailto:lightonthewater@hotmail.com">Jesse 
23   Maurais<br>
24   </a>Adapted For Java By: <a href="athomas@dev.java.net">Athomas 
25   Goldberg </a></p>
26
27 <p><a href="../../../deployment/jogamp-current/joal-demos/jnlp-files/joal-lesson5.jnlp">Launch the Demo via Java Web Start</a></p>
28 <p align="justify">This is a translation of <a href="http://devmaster.net/posts/2892/openal-lesson-5-sources-sharing-buffers">
29 OpenAL Lesson 5: Sources Sharing Buffers</a>
30 tutorial from <a href="http://devmaster.net/">DevMaster.net</a> to JOAL.
31
32 </p>
33 <p align="justify">At this point in the OpenAL series I will show one method of 
34   having your buffers be shared among many sources. This is a very logical and 
35   natural step, and it is so easy that some of you may have already done this 
36   yourself. If you have you may just skip this tutorial in total and move on. 
37   But for those keeners who want to read all of the info I've got to give, you 
38   may find this interesting. Plus, we will be implementing the Alc layer directly 
39   so that we can use some of that knowledge gained in lesson 4. On top of that 
40   we will create a program you might even use!</p>
41 <p align="justify">Well, here we go. I've decided to only go over bits of the 
42   code that are significant, since most of the code has been repeated so far in 
43   the series. Check out the full source code in the download.</p>
44 <pre class=code><span class=codeComment><font color="#0000FF">static</font> ALC alc;
45 <font color="#0000FF">static</font> AL al;<font color="#006600">
46
47 // These index the buffers.</font></span>
48 <span class=codeKeyword><font color="#0000FF">public static final int</font></span> THUNDER      = 0;
49 <span class=codeKeyword><font color="#0000FF">public static final int</font></span> WATERDROP   = 1;
50 <span class=codeKeyword><font color="#0000FF">public static final int</font></span> STREAM      = 2;
51 <span class=codeKeyword><font color="#0000FF">public static final int</font></span> RAIN        = 3;
52
53 <span class=codeKeyword><font color="#0000FF">public static final int</font></span> CHIMES      = 4;
54 <span class=codeKeyword><font color="#0000FF">public static final int</font></span> OCEAN       = 5;
55 <span class=codeKeyword><font color="#0000FF">public static final int</font></span> NUM_BUFFERS = 6;
56
57 <font color="#006600"><span class=codeComment>// Buffers hold sound data.</span>
58 </font><font color="#0000FF">static int</font>[] buffers = <font color="#0000FF">new int</font>[NUM_BUFFERS];
59
60 <span class=codeComment><font color="#006600">// A vector list of sources for multiple emissions.</font></span>
61 Vector sources = <font color="#0000FF">new </font>Vector();
62
63 </pre>
64 <p align="justify">First I've written out a few macros that we can use to index 
65   the buffer array. We will be using several wav files so we need quite a few 
66   buffers here. Instead of using an array for storing the sources we will use 
67   a Vector. We chose to do this because it allows us to have a dynamic number 
68   of sources. We can just keep adding sources to the scene until OpenAL runs out 
69   of them. This is also the first tutorial where we will deal with sources as 
70   being a resource that will run out. And yes, they will run out; they are finite.</p>
71 <pre class=code><font color="#0000FF">static int </font>initOpenAL() {
72  
73     ALC.Device device;
74     ALC.Context context;
75     String deviceSpecifier;
76     String deviceName = "DirectSound3D";
77
78     <span class=codeComment><font color="#006600">// Get handle to device.</font></span>
79     device = alc.alcOpenDevice(deviceName);
80
81     <font color="#006600"><span class=codeComment>// Get the device specifier.</span></font>
82     deviceSpecifier = alc.alcGetString(device, ALC.ALC_DEVICE_SPECIFIER);
83
84     System.out.println("Using device &quot; + deviceSpecifier);
85
86     <span class=codeComment><font color="#006600">// Create audio context.</font></span>
87     context = alc.alcCreateContext(device, <font color="#0000FF">null</font>);
88
89     <span class=codeComment><font color="#006600">// Set active context.</font></span>
90     alc.alcMakeContextCurrent(context);
91
92     <span class=codeComment><font color="#006600">// Check for an error.</font></span>
93     <span class=codeKeyword><font color="#0000FF">if </font></span>(alc.alcGetError() != ALC.ALC_NO_ERROR)
94         <span class=codeKeyword><font color="#0000FF">return</font></span> AL.AL_FALSE;
95
96     <span class=codeKeyword><font color="#0000FF">return</font></span> AL.AL_TRUE;
97 }
98 </pre>
99 <p align="justify">This is some sample code from what we learned in the last tutorial. 
100   We get a handle to the device &quot;DirectSound3D&quot;, and then obtain a rendering 
101   context for our application. This context is set to current and the function 
102   will check if everything went smoothly before we return success.</p>
103 <pre class=code><span class=codeKeyword><font color="#0000FF">static void</font></span> exitOpenAL() {
104     ALC.Context curContext;
105     ALC.Device curDevice;
106
107     <font color="#006600"><span class=codeComment>// Get the current context.</span></font>
108     curContext = alc.alcGetCurrentContext();
109
110     <span class=codeComment><font color="#006600">// Get the device used by that context.</font></span>
111     curDevice = alc.alcGetContextsDevice(curContext);
112
113 <font color="#006600">    <span class=codeComment>// Reset the current context to NULL.</span>
114 </font>    alc.alcMakeContextCurrent(<font color="#0000FF">null</font>);
115
116 <font color="#006600">    <span class=codeComment>// Release the context and the device.</span>
117 </font>    alc.alcDestroyContext(curContext);
118     alc.alcCloseDevice(curDevice);
119 }
120 </pre>
121 <p align="justify">This will do the opposite we did in the previous code. It retrieves 
122   the context and device that our application was using and releases them. It 
123   also sets the current context to null (the default) which will suspend the processing 
124   of any data sent to OpenAL. It is important to reset the current context to 
125   null or else you will have an invalid context trying to process data. The results 
126   of doing this can be unpredictable.</p>
127 <p align="justify">If you are using a multi-context application you may need to 
128   have a more advanced way of dealing with initialization and shutdown. I would 
129   recommend making all devices and contexts global and closing them individually, 
130   rather than retrieving the current context.</p>
131 <pre class=code><font color="#0000FF">static int </font>loadALData() {
132     <font color="#006600"><span class=codeComment>// Variables to load into.</span></font>
133     <font color="#0000FF">int</font>[] format = new <font color="#0000FF">int</font>[1];
134     <font color="#0000FF">int</font>[] size = new <font color="#0000FF">int</font>[1];
135     ByteBuffer[] data = new ByteBuffer[1];
136     <font color="#0000FF">int</font>[] freq = new <font color="#0000FF">int</font>[1];
137     <font color="#0000FF">int</font>[] loop = new <font color="#0000FF">int</font>[1];
138
139     <span class=codeComment><font color="#006600">// Load wav data into buffers.</font></span>
140     al.alGenBuffers(NUM_BUFFERS, buffers);
141
142     <span class=codeKeyword><font color="#0000FF">if</font></span>(al.alGetError() != AL.AL_NO_ERROR)
143         <span class=codeKeyword><font color="#0000FF">return</font></span> AL.AL_FALSE;
144
145     ALut.alutLoadWAVFile("wavdata/thunder.wav", format, data, size, freq, loop);
146     al.alBufferData(buffers[THUNDER], format[0], data[0], size[0], freq[0]);
147     ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]);
148
149     ALut.alutLoadWAVFile("wavdata/waterdrop.wav", format, data, size, freq, loop);
150     al.alBufferData(buffers[WATERDROP], format[0], data[0], size[0], freq[0]);
151     ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]);
152
153     ALut.alutLoadWAVFile("wavdata/stream.wav", format, data, size, freq, loop);
154     al.alBufferData(buffers[STREAM], format[0], data[0], size[0], freq[0]);
155     ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]);
156
157     ALut.alutLoadWAVFile("wavdata/rain.wav", format, data, size, freq, loop);
158     al.alBufferData(buffers[RAIN], format[0], data[0], size[0], freq[0]);
159     ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]);
160
161     ALut.alutLoadWAVFile("wavdata/ocean.wav", format, data, size, freq, loop);
162     al.alBufferData(buffers[OCEAN], format[0], data[0], size[0], freq[0]);
163     ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]);
164
165     ALut.alutLoadWAVFile("wavdata/chimes.wav", format, data, size, freq, loop);
166     al.alBufferData(buffers[CHIMES], format[0], data[0], size[0], freq[0]);
167     ALut.alutUnloadWAV(format[0], data[0], size[0], freq[0]);
168
169 <font color="#006600">    <span class=codeComment>// Do another error check and return.</span>
170     </font><span class=codeKeyword><font color="#0000FF">if</font> </span>(al.alGetError() != AL.AL_NO_ERROR)
171         <span class=codeKeyword><font color="#0000FF">return</font></span> AL.AL_FALSE;
172
173     <span class=codeKeyword><font color="#0000FF">return</font></span> AL.AL_TRUE;
174 }
175 </pre>
176 <p align="justify">We've totally removed the source generation from this function. 
177   That's because from now on we will be initializing the sources separately.</p>
178 <pre class=code><span class=codeKeyword><font color="#0000FF">static void</font></span><font color="#0000FF"> </font>addSource(int type) {
179     <font color="#0000FF">int[]</font> source = <font color="#0000FF">new int</font>[1];
180
181     al.alGenSources(1, source);
182
183     <span class=codeKeyword><font color="#0000FF">if</font> </span>(al.alGetError() != AL.AL_NO_ERROR) {
184         System.err.println("Error generating audio source.");
185         System.exit(1);
186     }
187
188     al.alSourcei (source[0], AL.AL_BUFFER,   buffers[type]);
189     al.alSourcef (source[0], AL.AL_PITCH,    1.0          );
190     al.alSourcef (source[0], AL.AL_GAIN,     1.0          );
191     al.alSourcefv(source[0], AL.AL_POSITION, sourcePos    );
192     al.alSourcefv(source[0], AL.AL_VELOCITY, sourceVel    );
193     al.alSourcei (source[0], AL.AL_LOOPING,  AL.AL_TRUE      );
194
195     al.alSourcePlay(source);
196
197     sources.put(new Integer(source[0]));
198 }
199
200 </pre>
201 <p align="justify">Here's the function that will generate the sources for us. 
202   This function will generate a single source for any one of the loaded buffers 
203   we generated in the previous source. Given the buffer index 'type', which is 
204   one of the macros we created right from the start of this tutorial. We do an 
205   error check to make sure we have a source to play (like I said, they are finite). 
206   If a source cannot be allocated then the program will exit.</p>
207 <pre class=code><span class=codeKeyword><font color="#0000FF">static void</font></span><font color="#0000FF"> </font>killALData() {
208
209     Iterator iter = sources.iterator();
210     <span class=codeKeyword><font color="#000000">while</font></span>(iter.hasNext()) {
211         al.alDeleteSources(1, <font color="#0000FF">new int</font>[] { ((Integer)iter.next()).intValue() });
212     }
213     sources.clear();
214     al.alDeleteBuffers(NUM_BUFFERS, buffers);
215     exitOpenAL();
216 }
217 </pre>
218 <p align="justify">This function has been modified a bit to accommodate the Vector. 
219   We have to delete each source in the list individually and then clear the list 
220   which will effectively destroy it.</p>
221 <pre class=code><font color="#0000FF">    char</font>[] c = <font color="#0000FF">new char</font>[1];
222
223 <font color="#0000FF">    </font><font color="#0000FF">while</font>(c[0] != 'q') {      
224 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">try</font> {
225 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font>BufferedReader buf =
226 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">new</font> BufferedReader(<font color="#0000FF">new</font> InputStreamReader(System.in));
227 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font>System.out.println(&quot;Press a key and hit ENTER: \n&quot; +
228 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">   </font>&quot;\t'w' for Water Drop\n&quot; +
229 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">   </font>&quot;\t't' for Thunder\n&quot; +
230 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">   </font>&quot;\t's' for Stream\n&quot; +
231 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">   </font>&quot;\t'r' for Rain\n&quot; +
232 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">   </font>&quot;\t'o' for Ocean\n&quot; +
233 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">   </font>&quot;\t'c' for Chimes\n&quot; +
234 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">   </font>&quot;\n'q' to Quit\n&quot;);
235 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font>buf.read(c);
236 <font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">    </font><font color="#0000FF">switch</font>(c[0]) {
237 <font color="#0000FF">                case</font> 'w': addSource(WATERDROP); <font color="#0000FF">break</font>;
238 <font color="#0000FF"></font><font color="#0000FF">                case</font> 't': addSource(THUNDER); <font color="#0000FF">break</font>;
239 <font color="#0000FF"></font><font color="#0000FF">                case</font> 's': addSource(STREAM); <font color="#0000FF">break</font>;
240 <font color="#0000FF"></font><font color="#0000FF">                case</font> 'r': addSource(RAIN); <font color="#0000FF">break</font>;
241 <font color="#0000FF"></font><font color="#0000FF">                case</font> 'o': addSource(OCEAN); <font color="#0000FF">break</font>;
242 <font color="#0000FF"></font><font color="#0000FF">                case</font> 'c': addSource(CHIMES); <font color="#0000FF">break</font>;
243 <font color="#0000FF"></font>}
244 <font color="#0000FF">    </font><font color="#0000FF">    </font>} <font color="#0000FF">catch</font> (IOException e) {
245                         System.exit(1);
246 <font color="#0000FF">    </font><font color="#0000FF">    </font>}
247 <font color="#0000FF">    </font>}</pre>
248 <p align="justify">Here is the programs inner loop taken straight out of our main. 
249   Basically it waits for some keyboard input and on certain key hits it will create 
250   a new source of a certain type and add it to the audio scene. Essentially what 
251   we have created here is something like one of those nature tapes that people 
252   listen to for relaxation. Ours is a little better since it allows the user to 
253   customize which sounds that they want in the background. Pretty neat eh? I've 
254   been listening to mine while I code. It's a Zen experience (I'm listening to 
255   it right now).</p>
256 <p align="justify">The program can be expanded for using more wav files, and have 
257   the added feature of placing the sources around the scene in arbitrary positions. 
258   You could even allow for sources to play with a given frequency rather than 
259   have them loop. However this would require GUI routines that go beyond the scope 
260   of the tutorial. A full featured &quot;Weathering Engine&quot; would be a nifty 
261   program to make though. ;)</p>
262 <table border="0" cellspacing="1" style="border-collapse: collapse" width="100%" id="AutoNumber2" bgcolor="#666699">
263   <tr> 
264     <td width="40%"> <p dir="ltr"><font color="#FFFFFF" size="2">© 2003 DevMaster.net. 
265         All rights reserved.</font></td>
266     <td width="60%"> <p align="right" dir="ltr"><font size="2"><a href="mailto:webmaster@devmaster.net"> 
267         <font color="#FFFFFF">Contact us</font></a><font color="#FFFFFF"> if you 
268         want to write for us or for any comments, suggestions, or feedback.</font></font></td>
269   </tr>
270 </table>
271 </body>
272 </html>
http://JogAmp.org git info: FAQ, tutorial and man pages.