This repository has been archived by the owner on Jan 5, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdocumentation_openal_05.php
265 lines (224 loc) · 11.2 KB
/
documentation_openal_05.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
<? require('_include/header.php'); ?>
<div style="margin: 0px 0px 10px 10px; width: 240px; float: right; border: 1px solid #000000;">
<table border="0" cellpadding="3" cellspacing="0">
<tr>
<td width="100%" style="text-align: center; background-color: #cccccc; font-weight: bold; border-bottom: 1px solid #000000;" colspan="2">Other Articles in the Series</td>
</tr>
<tr>
<td valign="top">·</td>
<td width="100%" style="text-align: left;"><a href="documentation_openal_01.php">Lesson 1: Single Static Source</a></td>
</tr>
<tr>
<td valign="top">·</td>
<td width="100%" style="text-align: left;"><a href="documentation_openal_02.php">Lesson 2: Looping and Fade-away</a></td>
</tr>
<tr>
<td valign="top">·</td>
<td width="100%" style="text-align: left;"><a href="documentation_openal_03.php">Lesson 3: Multiple Sources</a></td>
</tr>
<tr>
<td valign="top">·</td>
<td width="100%" style="text-align: left;"><a href="documentation_openal_04.php">Lesson 4: A Closer Look at ALC</a></td>
</tr>
<tr>
<td valign="top">·</td>
<td width="100%" style="text-align: left;"><a href="documentation_openal_05.php">Lesson 5: Sources Sharing Buffers</a></td>
</tr>
<tr>
<td valign="top">·</td>
<td width="100%" style="text-align: left;"><a href="documentation_openal_06.php">Lesson 6: Advanced Loading and Error Handles</a></td>
</tr>
<tr>
<td valign="top">·</td>
<td width="100%" style="text-align: left;"><a href="documentation_openal_07.php">Lesson 7: The Doppler Effect</a></td>
</tr>
</table>
</div>
<h1>Sources Sharing Buffers: Lesson 5</h1>
<p>
<i>
Author: <a href="mailto:lightonthewater@hotmail.com">Jesse Maurais</a> | From: <a href="http://www.devmaster.net/articles.php?catID=6" target="_blank">devmaster.net</a><br/>
Modified for LWJGL by: <a href="mailto:brian@matzon.dk">Brian Matzon</a>
</i>
</p>
<p>
At this point in the OpenAL series I will show one method of having your
buffers be shared among many sources. This is a very logical and natural
step, and it is so easy that some of you may have already done this yourself.
If you have you may just skip this tutorial in total and move on. But for
those keeners who want to read all of the info I've got to give, you may
find this interesting.<br/>
Well, here we go. I've decided to only go over bits of the code that are
significant, since most of the code has been repeated so far in the series.
Check out the full source code in the download.
</p>
<pre class="code" style="clear: right;">
<span class="codeKeyword">import</span> java.io.IOException;
<span class="codeKeyword">import</span> java.nio.FloatBuffer;
<span class="codeKeyword">import</span> java.nio.IntBuffer;
<span class="codeKeyword">import</span> org.lwjgl.BufferUtils;
<span class="codeKeyword">import</span> org.lwjgl.LWJGLException;
<span class="codeKeyword">import</span> org.lwjgl.openal.AL;
<span class="codeKeyword">import</span> org.lwjgl.openal.AL10;
<span class="codeKeyword">import</span> org.lwjgl.util.WaveData;
<span class="codeKeyword">public class</span> Lesson5 {
<span class="codeComment">/** Index of thunder sound */</span>
<span class="codeKeyword">public static final int</span> THUNDER = 0;
<span class="codeComment">/** Index of waterdrop sound */</span>
<span class="codeKeyword">public static final int</span> WATERDROP = 1;
<span class="codeComment">/** Index of stream sound */</span>
<span class="codeKeyword">public static final int</span> STREAM = 2;
<span class="codeComment">/** Index of rain sound */</span>
<span class="codeKeyword">public static final int</span> RAIN = 2;
<span class="codeComment">/** Index of chimes sound */</span>
<span class="codeKeyword">public static final int</span> CHIMES = 2;
<span class="codeComment">/** Index of ocean sound */</span>
<span class="codeKeyword">public static final int</span> OCEAN = 2;
<span class="codeComment">/** Maximum data buffers we will need. */</span>
<span class="codeKeyword">public static final int</span> NUM_BUFFERS = 6;
<span class="codeComment"> /** Buffers hold sound data. */</span>
IntBuffer buffer = BufferUtils.createIntBuffer(NUM_BUFFERS);
<span class="codeComment"> /** Sources are points emitting sound. */</span>
IntBuffer source = BufferUtils.createIntBuffer(128);
</pre>
<p>
We will be using several wav files so we need quite a few buffers here. We
will be using at most 128 sources (typically OpenAL will stop at 32-64
sources, but you shouldn't rely on more than 16!). We can just keep adding
sources to the scene until OpenAL runs out 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.
</p>
<pre class="code">
<span class="codeComment"> /**
* boolean LoadALData()
*
* This function will load our sample data from the disk using the Alut
* utility and send the data into OpenAL as a buffer. A source is then
* also created to play that buffer.
*/</span>
<span class="codeKeyword">int</span> loadALData() {
<span class="codeComment">// Load wav data into a buffer.</span>
AL10.alGenBuffers(buffer);
<span class="codeKeyword">if</span>(AL10.alGetError() != AL10.AL_NO_ERROR)
<span class="codeKeyword">return</span> AL10.AL_FALSE;
WaveData waveFile = WaveData.create("thunder.wav");
AL10.alBufferData(buffer.get(THUNDER), waveFile.format, waveFile.data, waveFile.samplerate);
waveFile.dispose();
waveFile = WaveData.create("waterdrop.wav");
AL10.alBufferData(buffer.get(WATERDROP), waveFile.format, waveFile.data, waveFile.samplerate);
waveFile.dispose();
waveFile = WaveData.create("stream.wav");
AL10.alBufferData(buffer.get(STREAM), waveFile.format, waveFile.data, waveFile.samplerate);
waveFile.dispose();
waveFile = WaveData.create("rain.wav");
AL10.alBufferData(buffer.get(RAIN), waveFile.format, waveFile.data, waveFile.samplerate);
waveFile.dispose();
waveFile = WaveData.create("ocean.wav");
AL10.alBufferData(buffer.get(OCEAN), waveFile.format, waveFile.data, waveFile.samplerate);
waveFile.dispose();
waveFile = WaveData.create("chimes.wav");
AL10.alBufferData(buffer.get(CHIMES), waveFile.format, waveFile.data, waveFile.samplerate);
waveFile.dispose();
<span class="codeComment">// Do another error check and return.</span>
<span class="codeKeyword">if</span> (AL10.alGetError() == AL10.AL_NO_ERROR)
<span class="codeKeyword">return</span> AL10.AL_TRUE;
<span class="codeKeyword">return</span> AL10.AL_FALSE;
</pre>
<p>
We've totally removed the source generation from this function. That's
because from now on we will be initializing the sources separately.
</p>
<pre class="code">
<span class="codeComment"> /**
* void AddSource(ALint type)
*
* Will add a new water drop source to the audio scene.
*/</span>
<span class="codeKeyword">private void</span> addSource(<span class="codeKeyword">int</span> type) {
<span class="codeKeyword">int</span> position = source.position();
source.limit(position + 1);
AL10.alGenSources(source);
<span class="codeKeyword">if</span> (AL10.alGetError() != AL10.AL_NO_ERROR) {
System.out.println("Error generating audio source.");
System.exit(-1);
}
AL10.alSourcei(source.get(position), AL10.AL_BUFFER, buffer.get(type) );
AL10.alSourcef(source.get(position), AL10.AL_PITCH, 1.0f );
AL10.alSourcef(source.get(position), AL10.AL_GAIN, 1.0f );
AL10.alSource (source.get(position), AL10.AL_POSITION, sourcePos );
AL10.alSource (source.get(position), AL10.AL_VELOCITY, sourceVel );
AL10.alSourcei(source.get(position), AL10.AL_LOOPING, AL10.AL_TRUE );
AL10.alSourcePlay(source.get(position));
// next index
source.position(position+1);
}
</pre>
<p>
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 we generated
in the previous source. Given the buffer index 'type'. We do an error check
to make sure we have a source to play (like I said, they are finite). If a
source cannot be allocated then the program will exit.
</p>
<pre class="code">
<span class="codeComment">/**
* void killALData()
*
* We have allocated memory for our buffers and sources which needs
* to be returned to the system. This function frees that memory.
*/</span>
<span class="codeKeyword">void</span> killALData() {
<span class="codeComment">// set to 0, num_sources</span>
<span class="codeKeyword">int</span> position = source.position();
source.position(0).limit(position);
AL10.alDeleteSources(source);
AL10.alDeleteBuffers(buffer);
}
</pre>
<p>
This function has been modified a bit to accommodate the number of actually
created sources.
</p>
<pre class="code">
<span class="codeComment">// Loop.</span>
<span class="codeKeyword">char</span> c = ' ';
<span class="codeKeyword">while</span>(c != 'q') {
<span class="codeKeyword">try</span> {
c = (<span class="codeKeyword">char</span>) System.in.read();
} <span class="codeKeyword">catch</span> (IOException ioe) {
c = 'q';
}
<span class="codeKeyword">switch</span>(c) {
<span class="codeKeyword">case</span> 'w': addSource(WATERDROP); <span class="codeKeyword">break</span>;
<span class="codeKeyword">case</span> 't': addSource(THUNDER); <span class="codeKeyword">break</span>;
<span class="codeKeyword">case</span> 's': addSource(STREAM); <span class="codeKeyword">break</span>;
<span class="codeKeyword">case</span> 'r': addSource(RAIN); <span class="codeKeyword">break</span>;
<span class="codeKeyword">case</span> 'o': addSource(OCEAN); <span class="codeKeyword">break</span>;
<span class="codeKeyword">case</span> 'c': addSource(CHIMES); <span class="codeKeyword">break</span>;
};
}
killALData();
}
}
</pre>
<p>
Here is the programs inner loop taken straight out of our main. 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
listen to for relaxation. Ours is a little better since it allows the user
to customize which sounds that they want in the background. Pretty neat eh?
I've been listening to mine while I code. It's a Zen experience (I'm
listening to it right now).<br/><br/>
The program can be expanded for using more wav files, and have the added
feature of placing the sources around the scene in arbitrary positions. You
could even allow for sources to play with a given frequency rather than have
them loop. However this would require GUI routines that go beyond the scope
of the tutorial. A full featured "Weathering Engine" would be a nifty
program to make though. ;)
</p>
<p>
Download source code and resources for this lesson <a href="_files/tutorials/openal_devmaster_lesson5.zip">here</a>.
</p>
<? require('_include/footer.php'); ?>