16
16
import pl .asie .computronics .reference .Config ;
17
17
18
18
import java .nio .ByteBuffer ;
19
+ import java .nio .IntBuffer ;
20
+ import java .util .ArrayDeque ;
19
21
import java .util .HashSet ;
22
+ import java .util .Queue ;
20
23
import java .util .Set ;
21
24
22
25
/**
@@ -148,16 +151,18 @@ public void play(float x, float y, float z, String pattern, AudioType type, int
148
151
}
149
152
}
150
153
154
+ private final Set <Source > toRemove = new HashSet <Source >();
155
+
151
156
private void update () {
152
157
if (!disableAudio ) {
153
158
synchronized (sources ) {
154
- Set <Source > toRemove = new HashSet <Source >();
155
159
for (Source source : sources ) {
156
160
if (source .checkFinished ()) {
157
161
toRemove .add (source );
158
162
}
159
163
}
160
164
sources .removeAll (toRemove );
165
+ toRemove .clear ();
161
166
}
162
167
163
168
// Clear error stack.
@@ -175,26 +180,51 @@ private void update() {
175
180
private class Source {
176
181
177
182
private int source ;
178
- private int buffer ;
183
+ private IntBuffer [] buffers ;
184
+ private final Queue <ByteBuffer > bufferData ;
179
185
180
186
Source (float x , float y , float z , ByteBuffer data , float gain ) {
181
187
182
188
// Clear error stack.
183
189
AL10 .alGetError ();
184
190
185
- int buffer = AL10 .alGenBuffers ();
191
+ buffers = new IntBuffer [2 ];
192
+ buffers [0 ] = BufferUtils .createIntBuffer (1 );
193
+ buffers [1 ] = BufferUtils .createIntBuffer (1 );
194
+ AL10 .alGenBuffers (buffers [0 ]);
186
195
checkALError ();
187
196
197
+ bufferData = new ArrayDeque <ByteBuffer >(data .capacity () / (2 * sampleRate ));
198
+ for (int i = 0 ; i * 2 * sampleRate < data .capacity (); i ++) {
199
+ /*ByteBuffer buf = ByteBuffer.allocateDirect(Math.min(2 * sampleRate, bytes.length - (i * 2 * sampleRate)));
200
+ buf.put(bytes, i * 2 * sampleRate, buf.capacity());
201
+ buf.rewind();
202
+ bufferData.add(buf);*/
203
+ data .limit (i * 2 * sampleRate + Math .min (2 * sampleRate , data .capacity () - (i * 2 * sampleRate )));
204
+ data .position (i * 2 * sampleRate );
205
+ bufferData .add (data .slice ());
206
+ }
207
+
188
208
try {
189
- AL10 .alBufferData (buffer , AL10 .AL_FORMAT_MONO8 , data , sampleRate );
209
+ AL10 .alBufferData (buffers [ 0 ]. get ( 0 ) , AL10 .AL_FORMAT_MONO8 , bufferData . poll () , sampleRate );
190
210
checkALError ();
211
+ if (!bufferData .isEmpty ()) {
212
+ AL10 .alGenBuffers (buffers [1 ]);
213
+ checkALError ();
214
+ AL10 .alBufferData (buffers [1 ].get (0 ), AL10 .AL_FORMAT_MONO8 , bufferData .poll (), sampleRate );
215
+ checkALError ();
216
+ }
191
217
192
218
int source = AL10 .alGenSources ();
193
219
checkALError ();
194
220
195
221
try {
196
- AL10 .alSourceQueueBuffers (source , buffer );
222
+ AL10 .alSourceQueueBuffers (source , buffers [ 0 ] );
197
223
checkALError ();
224
+ if (AL10 .alIsBuffer (buffers [1 ].get (0 ))) {
225
+ AL10 .alSourceQueueBuffers (source , buffers [1 ]);
226
+ checkALError ();
227
+ }
198
228
199
229
AL10 .alSource3f (source , AL10 .AL_POSITION , x , y , z );
200
230
AL10 .alSourcef (source , AL10 .AL_REFERENCE_DISTANCE , maxDistance );
@@ -206,21 +236,44 @@ private class Source {
206
236
checkALError ();
207
237
208
238
this .source = source ;
209
- this .buffer = buffer ;
239
+ // this.buffers = buffer;
210
240
} catch (Throwable t ) {
211
241
AL10 .alDeleteSources (source );
212
242
Throwables .propagate (t );
213
243
}
214
244
} catch (Throwable t ) {
215
- AL10 .alDeleteBuffers (buffer );
245
+ for (IntBuffer b : buffers ) {
246
+ if (AL10 .alIsBuffer (b .get (0 ))) {
247
+ AL10 .alDeleteBuffers (b );
248
+ }
249
+ }
216
250
Throwables .propagate (t );
217
251
}
218
252
}
219
253
254
+ private int index = 0 ;
255
+
220
256
public boolean checkFinished () {
257
+ if (AL10 .alGetSourcei (source , AL10 .AL_BUFFERS_PROCESSED ) > 0 ) {
258
+ int oldIndex = index ;
259
+ AL10 .alSourceUnqueueBuffers (source , buffers [oldIndex ]);
260
+ checkALError ();
261
+ ByteBuffer buf = bufferData .poll ();
262
+ if (buf != null ) {
263
+ AL10 .alBufferData (buffers [oldIndex ].get (0 ), AL10 .AL_FORMAT_MONO8 , buf , sampleRate );
264
+ AL10 .alSourceQueueBuffers (source , buffers [oldIndex ]);
265
+ checkALError ();
266
+ index = (index + 1 ) % 2 ;
267
+ }
268
+ return false ;
269
+ }
221
270
if (AL10 .alGetSourcei (source , AL10 .AL_SOURCE_STATE ) != AL10 .AL_PLAYING ) {
222
271
AL10 .alDeleteSources (source );
223
- AL10 .alDeleteBuffers (buffer );
272
+ for (IntBuffer buffer : buffers ) {
273
+ if (AL10 .alIsBuffer (buffer .get (0 ))) {
274
+ AL10 .alDeleteBuffers (buffer );
275
+ }
276
+ }
224
277
return true ;
225
278
}
226
279
return false ;
0 commit comments