Mercurial > audio-send
comparison record.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f9476ff7637e |
---|---|
1 /** | |
2 * OpenAL cross platform audio library | |
3 * Copyright (C) 2010 by Chris Robinson | |
4 * This library is free software; you can redistribute it and/or | |
5 * modify it under the terms of the GNU Library General Public | |
6 * License as published by the Free Software Foundation; either | |
7 * version 2 of the License, or (at your option) any later version. | |
8 * | |
9 * This library is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 * Library General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU Library General Public | |
15 * License along with this library; if not, write to the | |
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 * Boston, MA 02111-1307, USA. | |
18 * Or go to http://www.gnu.org/copyleft/lgpl.html | |
19 */ | |
20 | |
21 #include "config.h" | |
22 #include <stdlib.h> | |
23 #include "alMain.h" | |
24 #include "AL/al.h" | |
25 #include "AL/alc.h" | |
26 #include "alSource.h" | |
27 #include <jni.h> | |
28 | |
29 | |
30 typedef struct record_data { | |
31 volatile int killNow; | |
32 ALvoid *thread; | |
33 ALuint robert; | |
34 | |
35 ALvoid *mainBuffer; | |
36 ALvoid *auxBuffer; | |
37 ALuint size; | |
38 | |
39 ALuint *unPauseIDs; | |
40 int unPauseCount; | |
41 ALboolean mainFull; | |
42 ALboolean auxFull; | |
43 ALboolean auxReady; | |
44 ALboolean mainReady; | |
45 | |
46 } record_data; | |
47 | |
48 | |
49 | |
50 | |
51 #define UNUSED(x) (void)(x) | |
52 #define RUNONLY(n) \ | |
53 {static int __runonce = n; \ | |
54 if (__runonce-- <= 0){return;}} | |
55 | |
56 #define RUNAT(n) \ | |
57 {static int __runat = n; \ | |
58 if (0 != __runat--){return;}} | |
59 | |
60 /// al error handling code prototypes | |
61 | |
62 char* GetALErrorString(ALenum err); | |
63 char* GetALCErrorString(ALenum err); | |
64 void printError(void); | |
65 void init(ALCdevice *); | |
66 void init2(ALCdevice *); | |
67 void later(ALCdevice *); | |
68 void every(ALCdevice *); | |
69 void every2(ALCdevice *); | |
70 void step(ALCdevice *); | |
71 | |
72 | |
73 //synchronization | |
74 struct record_data; | |
75 void syncContexts(ALCcontext *, ALCcontext *); | |
76 void syncSources(ALsource *, ALsource *, ALCcontext *, ALCcontext *); | |
77 void pauseMainContext(struct record_data *); | |
78 void unPauseMainContext(struct record_data *); | |
79 void pauseAllSources(ALCcontext *); | |
80 static void saveAux(ALCdevice *); | |
81 static void swapInAux(ALCdevice *); | |
82 static void saveMain(ALCdevice *); | |
83 static void swapInMain(ALCdevice *); | |
84 void aux_alListenerf(ALenum param, ALfloat value); | |
85 void aux_alListener3f(ALenum param, ALfloat v1, ALfloat v2, ALfloat v3); | |
86 | |
87 | |
88 ////////////// | |
89 | |
90 | |
91 | |
92 // remove all the sources from all the auxContexts | |
93 // take the mainContext and for each context, COPY | |
94 // the sources from the main context. | |
95 | |
96 // render each context and make their data available. | |
97 | |
98 // =alGenSources= (and =alGetError=) | |
99 // attach each source to the shared buffer using =alSourcei= | |
100 | |
101 | |
102 // need to make sure in the AudioRender class that we don't do | |
103 // anything to sources while the audio is being rendered, so make sure | |
104 // to maintain an "isDone" state as well. | |
105 | |
106 // Special device which allows simulation of multiple listeners | |
107 // hearing the same set of sources. Provides access to the rendered | |
108 // data for each listener. Designed to work with LWJGL. | |
109 | |
110 // first, the mainContext is the only context that is controlled by | |
111 // LWJGL. | |
112 | |
113 // One context will be created for each listener that we want. | |
114 | |
115 // Then, at the start of each render loop, first PAUSE the sources on | |
116 // all other contexts except the mainContext (this takes care of | |
117 // sources in the mainContext being shut down.) | |
118 // we will iterate through all | |
119 // the active sources in our mainContext (the one which is controlled | |
120 // through LWJGL), and take their sourceIDs. For each of these IDs | |
121 // and for each other context, we'll check some internal structure to | |
122 // see if we've already created a corresponding source. If that | |
123 // source exits, we will SYNCH it with the source which belongs to the | |
124 // mainContext. If it DOESN'T exist, we will CLONE the source from the | |
125 // main context and establish it in the other context. | |
126 | |
127 // Each render loop consists of noting all of the active sources in | |
128 // the mainContext and storing their IDs. Then, for each context, | |
129 // the correspondig sources to the active sources in the mainContext | |
130 // will be set to PLAY, and all sources in all other contexts will be | |
131 // set to PAUSE. aluMixData will be called for each context in this | |
132 // way. | |
133 | |
134 // approved by KittyCat | |
135 | |
136 | |
137 // CAN get id appropiate for us in the sorce-repated openal functions | |
138 // by quering *source->source | |
139 | |
140 // first, do it with only two listeners, two contexts, automatically | |
141 // created. | |
142 | |
143 static ALCcontext* mainContext = NULL; | |
144 static ALCcontext* auxContext = NULL; | |
145 | |
146 | |
147 void aux_alListenerf(ALenum param, ALfloat value){ | |
148 ALCcontext *current = alcGetCurrentContext(); | |
149 alcMakeContextCurrent(auxContext); | |
150 alListenerf(param, value); | |
151 alcMakeContextCurrent(current); | |
152 } | |
153 | |
154 void aux_alListener3f(ALenum param, ALfloat v1, ALfloat v2, ALfloat v3){ | |
155 ALCcontext *current = alcGetCurrentContext(); | |
156 alcMakeContextCurrent(auxContext); | |
157 alListener3f(param, v1, v2, v3); | |
158 alcMakeContextCurrent(current); | |
159 } | |
160 | |
161 | |
162 | |
163 void pauseAllSources(ALCcontext *ctx){ | |
164 ALCcontext *current = alcGetCurrentContext(); | |
165 alcMakeContextCurrent(ctx); | |
166 ALsource **src, **src_end; | |
167 src = ctx->ActiveSources; | |
168 src_end = src + ctx->ActiveSourceCount; | |
169 while(src != src_end){ | |
170 if (AL_PLAYING == (*src)->state){ | |
171 //if (AL_TRUE){ | |
172 ALuint source_id = (*src)->source; | |
173 //printf("pausing ONE source\n"); | |
174 alSourcePause(source_id); | |
175 } | |
176 src++; | |
177 } | |
178 alcMakeContextCurrent(current); | |
179 } | |
180 | |
181 | |
182 void init2(ALCdevice *Device){ | |
183 UNUSED(Device); | |
184 RUNONLY(1) | |
185 // the mainContext only ever has a FIXED number of sources! | |
186 // duplicate them ALL into auxContext! | |
187 alcMakeContextCurrent(auxContext);{ | |
188 UIntMap source_map= mainContext->SourceMap; | |
189 ALuint num_sources = source_map.size; | |
190 ALuint newSources[num_sources]; | |
191 alGenSources(num_sources, newSources);} | |
192 alcMakeContextCurrent(mainContext); | |
193 | |
194 | |
195 } | |
196 | |
197 | |
198 | |
199 /* | |
200 void syncSourcei(ALuint sourceID1, ALuint sourceID2, | |
201 ALCcontext *ctx1, ALCcontext *ctx2, | |
202 int numParams, ALenum *params){ | |
203 ALint values[numParams]; | |
204 ALCcontext current = alcGetCurrentContext(); | |
205 // get values | |
206 printf("getting values from source1\n"); | |
207 alcMakeContextCurrent(ctx1); | |
208 int i; | |
209 for(i=0; i<numParams; i++){ | |
210 alGetSourcei(sourceID1, params[i], values+i); | |
211 printf("value is %d\n", values[i]); | |
212 printError(); | |
213 } | |
214 // set values | |
215 printf("setting values of source2\n"); | |
216 alcMakeContextCurrent(ctx2); | |
217 for (i=0; i<numParams; i++){ | |
218 alSourcei(sourceID2, params[i], values[i]); | |
219 printError(); | |
220 } | |
221 alcMakeContextCurrent(current); | |
222 printError(); | |
223 } | |
224 */ | |
225 | |
226 | |
227 #define _MAKE_SYNC(NAME, INIT_EXPR, GET_EXPR, SET_EXPR) \ | |
228 void NAME (ALuint sourceID1, ALuint sourceID2, \ | |
229 ALCcontext *ctx1, ALCcontext *ctx2, \ | |
230 ALenum param){ \ | |
231 INIT_EXPR; \ | |
232 ALCcontext *current = alcGetCurrentContext(); \ | |
233 alcMakeContextCurrent(ctx1); \ | |
234 GET_EXPR; \ | |
235 /*printError();*/ \ | |
236 alcMakeContextCurrent(ctx2); \ | |
237 SET_EXPR; \ | |
238 /*printError();*/ \ | |
239 alcMakeContextCurrent(current); \ | |
240 } | |
241 | |
242 #define MAKE_SYNC(NAME, TYPE, GET, SET) \ | |
243 _MAKE_SYNC(NAME, \ | |
244 TYPE value, \ | |
245 GET(sourceID1, param, &value), \ | |
246 SET(sourceID2, param, value)) | |
247 | |
248 #define MAKE_SYNC3(NAME, TYPE, GET, SET) \ | |
249 _MAKE_SYNC(NAME, \ | |
250 TYPE value1; TYPE value2; TYPE value3;, \ | |
251 GET(sourceID1, param, &value1, &value2, &value3), \ | |
252 SET(sourceID2, param, value1, value2, value3)) | |
253 | |
254 MAKE_SYNC( syncSourcei, ALint, alGetSourcei, alSourcei); | |
255 MAKE_SYNC( syncSourcef, ALfloat, alGetSourcef, alSourcef); | |
256 MAKE_SYNC3(syncSource3i, ALint, alGetSource3i, alSource3i); | |
257 MAKE_SYNC3(syncSource3f, ALfloat, alGetSource3f, alSource3f); | |
258 | |
259 | |
260 | |
261 | |
262 | |
263 | |
264 #define DsyncSourcei(sourceID1, sourceID2, ctx1, ctx2, param) \ | |
265 {/*printf("synci : " #param "\n");*/ \ | |
266 syncSourcei(sourceID1, sourceID2, ctx1, ctx2, param);} | |
267 | |
268 #define DsyncSourcef(sourceID1, sourceID2, ctx1, ctx2, param) \ | |
269 {/*printf("syncf : " #param "\n");*/ \ | |
270 syncSourcef(sourceID1, sourceID2, ctx1, ctx2, param);} | |
271 | |
272 #define DsyncSource3i(sourceID1, sourceID2, ctx1, ctx2, param) \ | |
273 {/*printf("sync3i : " #param "\n");*/ \ | |
274 syncSource3i(sourceID1, sourceID2, ctx1, ctx2, param);} | |
275 | |
276 #define DsyncSource3f(sourceID1, sourceID2, ctx1, ctx2, param) \ | |
277 {/*printf("sync3f : " #param "\n");*/ \ | |
278 syncSource3f(sourceID1, sourceID2, ctx1, ctx2, param);} | |
279 | |
280 void printValid(ALuint sourceID){ | |
281 alcMakeContextCurrent(auxContext); | |
282 printf("source%d : %s\n", sourceID, alIsSource(sourceID) ? "VALID" : "INVALID"); | |
283 alcMakeContextCurrent(mainContext); | |
284 } | |
285 | |
286 | |
287 | |
288 void syncSources(ALsource *source1, ALsource *source2, | |
289 ALCcontext *ctx1, ALCcontext *ctx2){ | |
290 | |
291 ALuint ID1 = source1->source; | |
292 ALuint ID2 = source2->source; | |
293 ALCcontext *current = alcGetCurrentContext(); | |
294 //printf("***************\n"); | |
295 //printf("SYNCHING source %d with source %d\n", ID1, ID2); | |
296 | |
297 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_PITCH); | |
298 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_GAIN); | |
299 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_MAX_DISTANCE); | |
300 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_ROLLOFF_FACTOR); | |
301 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_REFERENCE_DISTANCE); | |
302 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_MIN_GAIN); | |
303 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_MAX_GAIN); | |
304 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_CONE_OUTER_GAIN); | |
305 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_CONE_INNER_ANGLE); | |
306 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_CONE_OUTER_ANGLE); | |
307 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_SEC_OFFSET); | |
308 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_SAMPLE_OFFSET); | |
309 DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_BYTE_OFFSET); | |
310 | |
311 DsyncSource3f(ID1,ID2,ctx1,ctx2,AL_POSITION); | |
312 DsyncSource3f(ID1,ID2,ctx1,ctx2,AL_VELOCITY); | |
313 DsyncSource3f(ID1,ID2,ctx1,ctx2,AL_DIRECTION); | |
314 | |
315 DsyncSourcei(ID1,ID2,ctx1,ctx2,AL_SOURCE_RELATIVE); | |
316 DsyncSourcei(ID1,ID2,ctx1,ctx2,AL_LOOPING); | |
317 | |
318 | |
319 | |
320 | |
321 | |
322 // first, copy buffer patterns over. | |
323 | |
324 //source2->lSourceType = source1->lSourceType; | |
325 //source2->NumChannels = source1->NumChannels; | |
326 //source2->SampleSize = source1->SampleSize; | |
327 //source2->Buffer = source1->Buffer; | |
328 // source2->queue = source1->queue; | |
329 // source2->BuffersInQueue = source1-> BuffersInQueue; | |
330 // source2->BuffersPlayed = source1 -> BuffersPlayed; | |
331 | |
332 // then, duplicate the state. | |
333 | |
334 // handle static sources | |
335 //printf("handling Buffers\n"); | |
336 alcMakeContextCurrent(ctx1); | |
337 ALint source_type; | |
338 alGetSourcei(ID1, AL_SOURCE_TYPE, &source_type); | |
339 //printError(); | |
340 | |
341 if (AL_STATIC == source_type){ | |
342 //printf("setting STATIC source\n"); | |
343 ALint buffer_id1; | |
344 ALint buffer_id2; | |
345 alGetSourcei(ID1, AL_BUFFER, &buffer_id1); | |
346 alcMakeContextCurrent(ctx2); | |
347 alGetSourcei(ID2, AL_BUFFER, &buffer_id2); | |
348 if (buffer_id1 != buffer_id2){ | |
349 //printf("setting source2's buffer from %d to %d\n", buffer_id2, buffer_id1); | |
350 alSourcei(ID2, AL_BUFFER, buffer_id1); | |
351 //printError(); | |
352 } | |
353 else { | |
354 //printf("Buffers are already the same, doing nothing.\n"); | |
355 } | |
356 } | |
357 else { | |
358 // printf("not a static source!\n"); | |
359 } | |
360 | |
361 | |
362 | |
363 | |
364 | |
365 | |
366 alcMakeContextCurrent(ctx2); | |
367 | |
368 | |
369 | |
370 | |
371 //printf("setting STATE\n"); | |
372 alcMakeContextCurrent(ctx1); | |
373 ALint state1; | |
374 alGetSourcei(ID1, AL_SOURCE_STATE, &state1); | |
375 //printError(); | |
376 | |
377 alcMakeContextCurrent(ctx2); | |
378 ALint state2; | |
379 alGetSourcei(ID2, AL_SOURCE_STATE, &state2); | |
380 //printError(); | |
381 if (state1 != state2){ | |
382 switch (state1){ | |
383 case AL_INITIAL : /*printf("INITIAL\n")*/;alSourceRewind(ID2);break; | |
384 case AL_PLAYING : /*printf("PLAYING\n")*/;alSourcePlay(ID2);break; | |
385 case AL_PAUSED : /*printf("PAUSED\n")*/;alSourcePause(ID2);break; | |
386 case AL_STOPPED : /*printf("STOPPED\n")*/;alSourceStop(ID2);break; | |
387 } | |
388 } | |
389 //printError(); | |
390 | |
391 | |
392 | |
393 alcMakeContextCurrent(current); | |
394 | |
395 } | |
396 | |
397 | |
398 void syncContexts(ALCcontext *ctx1, ALCcontext *ctx2){ | |
399 // if there aren't sufficient sources in ctx2 to mirror the sources | |
400 // in ctx1, create them. | |
401 ALCcontext *current = alcGetCurrentContext(); | |
402 | |
403 UIntMap *sourceMap1 = &(ctx1->SourceMap); | |
404 UIntMap *sourceMap2 = &(ctx2->SourceMap); | |
405 | |
406 | |
407 ALuint sources1 = sourceMap1->size; | |
408 ALuint sources2 = sourceMap2->size; | |
409 | |
410 //printf("ctx1 has %d sources; ctx2 has %d sources\n", sources1, sources2); | |
411 | |
412 alcMakeContextCurrent(ctx2); | |
413 if (sources2 < sources1){ | |
414 ALuint numSources = sources1 - sources2; | |
415 ALuint newSources[numSources]; | |
416 alGenSources(numSources, newSources); | |
417 printf("adjusting...\n"); | |
418 printf("now ctx1 has %d sources; ctx2 has %d sources\n", | |
419 sourceMap1->size, sourceMap2->size); | |
420 } | |
421 //printError(); | |
422 | |
423 | |
424 alcMakeContextCurrent(current); | |
425 | |
426 | |
427 // after this, ctx2 is gauranteed to have at least as many sources | |
428 // as ctx1. Now, sync each source from ctx1 to the corresponding | |
429 // source in ctx2. | |
430 | |
431 int i; | |
432 | |
433 | |
434 | |
435 for(i = 0; i < sourceMap1->size; i++){ | |
436 syncSources((ALsource*)sourceMap1->array[i].value, | |
437 (ALsource*)sourceMap2->array[i].value, | |
438 ctx1, ctx2); | |
439 } | |
440 | |
441 | |
442 | |
443 | |
444 | |
445 } | |
446 | |
447 | |
448 | |
449 void pauseMainContext(record_data *data){ | |
450 //printf("pausing MainContext\n"); | |
451 data->unPauseCount = 0; | |
452 data->unPauseIDs = | |
453 (ALuint*)realloc(data->unPauseIDs, | |
454 sizeof(ALuint) * mainContext->ActiveSourceCount); | |
455 | |
456 ALsource **src, **src_end; | |
457 src = mainContext->ActiveSources; | |
458 src_end = src + mainContext->ActiveSourceCount; | |
459 | |
460 while(src != src_end){ | |
461 | |
462 if (AL_PLAYING == (*src)->state){ | |
463 ALuint source_id = (*src)->source; | |
464 data->unPauseIDs[data->unPauseCount++] = source_id; | |
465 alSourcePause(source_id); | |
466 } | |
467 src++; | |
468 } | |
469 } | |
470 | |
471 | |
472 | |
473 | |
474 void unPauseMainContext(record_data *data){ | |
475 int i; | |
476 for(i=0;i<data->unPauseCount;i++){ | |
477 alSourcePlay(data->unPauseIDs[i]); | |
478 } | |
479 } | |
480 | |
481 | |
482 // a device brings along with it multiple pieces of state | |
483 // which have to be swapped in and out with each context. | |
484 | |
485 //static ALfloat DryBufferMain[BUFFERSIZE][MAXCHANNELS]; | |
486 //static ALfloat DryBufferAux[BUFFERSIZE][MAXCHANNELS]; | |
487 //static ALfloat PanningLUTMain[LUT_NUM][MAXCHANNELS]; | |
488 //static ALfloat PanningLUTAux[LUT_NUM][MAXCHANNELS]; | |
489 static ALfloat ClickRemovalMain[MAXCHANNELS]; | |
490 static ALfloat ClickRemovalAux[MAXCHANNELS]; | |
491 static ALfloat PendingClicksMain[MAXCHANNELS]; | |
492 static ALfloat PendingClicksAux[MAXCHANNELS]; | |
493 | |
494 | |
495 | |
496 static void saveAux(ALCdevice *Device){ | |
497 //memcpy(DryBufferAux, Device->DryBuffer, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); | |
498 //memcpy(PanningLUTAux, Device->PanningLUT, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); | |
499 memcpy(ClickRemovalAux, Device->ClickRemoval, sizeof(ALfloat)*MAXCHANNELS); | |
500 memcpy(PendingClicksAux, Device->PendingClicks, sizeof(ALfloat)*MAXCHANNELS); | |
501 } | |
502 static void swapInAux(ALCdevice *Device){ | |
503 //memcpy(Device->DryBuffer, DryBufferAux, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); | |
504 //memcpy(Device->PanningLUT, PanningLUTAux, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); | |
505 memcpy(Device->ClickRemoval, ClickRemovalAux, sizeof(ALfloat)*MAXCHANNELS); | |
506 memcpy(Device->PendingClicks, PendingClicksAux, sizeof(ALfloat)*MAXCHANNELS); | |
507 } | |
508 | |
509 | |
510 static void saveMain(ALCdevice *Device){ | |
511 //memcpy(DryBufferMain, Device->DryBuffer, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); | |
512 //memcpy(PanningLUTMain, Device->PanningLUT, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); | |
513 memcpy(ClickRemovalMain, Device->ClickRemoval, sizeof(ALfloat)*MAXCHANNELS); | |
514 memcpy(PendingClicksMain, Device->PendingClicks, sizeof(ALfloat)*MAXCHANNELS); | |
515 } | |
516 static void swapInMain(ALCdevice *Device){ | |
517 //memcpy(Device->DryBuffer, DryBufferMain, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); | |
518 //memcpy(Device->PanningLUT, PanningLUTMain, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); | |
519 memcpy(Device->ClickRemoval, ClickRemovalMain, sizeof(ALfloat)*MAXCHANNELS); | |
520 memcpy(Device->PendingClicks, PendingClicksMain, sizeof(ALfloat)*MAXCHANNELS); | |
521 } | |
522 | |
523 | |
524 static ALCcontext **currentContext; | |
525 static ALuint currentNumContext; | |
526 static void unLimitContext(ALCdevice *Device){ | |
527 Device->Contexts = currentContext; | |
528 Device->NumContexts = currentNumContext; | |
529 } | |
530 | |
531 static void limitContext(ALCdevice *Device, ALCcontext *ctx){ | |
532 currentContext = Device->Contexts; | |
533 currentNumContext = Device->NumContexts; | |
534 Device->Contexts = &ctx; | |
535 Device->NumContexts = 1; | |
536 } | |
537 | |
538 | |
539 void every2(ALCdevice *Device){ | |
540 | |
541 record_data *data = (record_data*)Device->ExtraData; | |
542 | |
543 if (data->mainFull){ | |
544 printf("data has not yet been extracted!\n"); | |
545 return; | |
546 } | |
547 | |
548 | |
549 syncContexts(mainContext , auxContext); | |
550 | |
551 alcMakeContextCurrent(auxContext); | |
552 limitContext(Device, auxContext); | |
553 swapInAux(Device); | |
554 aluMixData(Device, data->auxBuffer, Device->UpdateSize); | |
555 saveAux(Device); | |
556 unLimitContext(Device); | |
557 | |
558 | |
559 alcMakeContextCurrent(mainContext); | |
560 limitContext(Device, mainContext); | |
561 swapInMain(Device); | |
562 aluMixData(Device, data->mainBuffer, Device->UpdateSize); | |
563 saveMain(Device); | |
564 unLimitContext(Device); | |
565 | |
566 data->mainFull = AL_TRUE; | |
567 data->auxFull = AL_TRUE; | |
568 | |
569 } | |
570 | |
571 | |
572 | |
573 | |
574 | |
575 | |
576 void every(ALCdevice *Device){ | |
577 UNUSED(Device); | |
578 // by the time every() is called, mainContext and auxContext will | |
579 // have been initiliazed. | |
580 printf("+++++++\nevery is called\n"); | |
581 // print sourceid for all sources. | |
582 ALsource **src, **src_end; | |
583 // LockDevice(Device); | |
584 // pauseAllSources(auxContext); | |
585 src = mainContext->ActiveSources; | |
586 src_end = src + mainContext->ActiveSourceCount; | |
587 UIntMap source_map ; | |
588 int i; | |
589 | |
590 source_map= mainContext->SourceMap; | |
591 printf("max sources in the mainContext is %d\n", source_map.maxsize); | |
592 printf("current sources: %d\n", source_map.size); | |
593 | |
594 printf("their ID's are:\n"); | |
595 for(i = 0; i < source_map.size; i++){ | |
596 printf("%d, ",source_map.array[i].key); | |
597 } | |
598 printf("\n"); | |
599 source_map= auxContext->SourceMap; | |
600 printf("max sources in the auxContext is %d\n", source_map.maxsize); | |
601 printf("current sources: %d\n", source_map.size); | |
602 | |
603 printf("their ID's are:\n"); | |
604 for(i = 0; i < source_map.size; i++){ | |
605 printf("%d, ",source_map.array[i].key); | |
606 } | |
607 printf("\n"); | |
608 | |
609 while(src != src_end){ | |
610 | |
611 if (AL_PLAYING == (*src)->state){ | |
612 ALuint source_id = (*src)->source; | |
613 printf("source %d is AL_PLAYING\n",source_id); | |
614 } | |
615 src++; | |
616 | |
617 } | |
618 | |
619 | |
620 // UnlockDevice(Device); | |
621 } | |
622 | |
623 | |
624 | |
625 | |
626 | |
627 | |
628 | |
629 // debug printing | |
630 | |
631 #define DEBUG 0 | |
632 | |
633 #define dprintf(expr) {if (DEBUG) {printf(expr);}} | |
634 | |
635 | |
636 | |
637 | |
638 static const ALCchar recordDevice[] = "Aurellem"; | |
639 | |
640 | |
641 | |
642 | |
643 | |
644 | |
645 struct ALsource * cloneSource(struct ALsource *source); | |
646 | |
647 //struct ALsource * cloneSource(struct ALsource *source){ | |
648 // ALuint[1] sourceID; | |
649 | |
650 | |
651 //} | |
652 | |
653 int lock = 0; | |
654 | |
655 /* | |
656 static ALuint RecordProc() | |
657 { | |
658 if (0 == lock){return 0;} | |
659 ALCdevice *Device = deviceInstance; | |
660 dprintf("RLM: recordProc is begun!!\n"); | |
661 printError(); | |
662 static int MixCount = 0 ; | |
663 if (Device->Connected) | |
664 { | |
665 // the device does not seem to be "ready" until this point. | |
666 init(Device); | |
667 //init2(Device); | |
668 printf("\nMix Cycle %d\n", MixCount++); | |
669 every(Device); | |
670 every2(Device); | |
671 //aluMixData(Device, NULL, Device->UpdateSize); | |
672 } | |
673 lock = 1; | |
674 return 0; | |
675 } | |
676 */ | |
677 | |
678 | |
679 /* | |
680 static ALuint RecordProc(ALvoid *ptr) | |
681 { | |
682 | |
683 printf("RLM: recordProc is begun!!\n"); | |
684 ALCdevice *Device = (ALCdevice*)ptr; | |
685 //printError(); | |
686 record_data *data = (record_data*)Device->ExtraData; | |
687 ALuint now, start; | |
688 ALuint64 avail, done; | |
689 const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 / | |
690 Device->Frequency / 2; | |
691 | |
692 done = 0; | |
693 start = timeGetTime(); | |
694 //static int MixCount = 0 ; | |
695 | |
696 | |
697 if(!data->killNow && Device->Connected) | |
698 { | |
699 printf("sext level breakfast manuever!\n"); | |
700 now = timeGetTime(); | |
701 | |
702 avail = (ALuint64)(now-start) * Device->Frequency / 1000; | |
703 if(avail < done) | |
704 { | |
705 | |
706 avail += (ALuint64)0xFFFFFFFFu*Device->Frequency/1000 - done; | |
707 done = 0; | |
708 } | |
709 if(avail-done < Device->UpdateSize) | |
710 { | |
711 //Sleep(restTime); | |
712 //continue; | |
713 } | |
714 | |
715 while(avail-done >= Device->UpdateSize) | |
716 { | |
717 // the device does not seem to be "ready" until this point. | |
718 init(Device); | |
719 //init2(Device); | |
720 //printf("\nMix Cycle %d\n", MixCount++); | |
721 //every(Device); | |
722 every2(Device); | |
723 //later(Device); | |
724 //printError(); | |
725 //aluMixData(Device, NULL, Device->UpdateSize); | |
726 //Sleep(3000); | |
727 done += Device->UpdateSize; | |
728 } | |
729 } | |
730 else { | |
731 printf("WARNGING\n"); | |
732 } | |
733 | |
734 return 0; | |
735 } | |
736 */ | |
737 | |
738 | |
739 | |
740 static ALuint RecordProc(ALCdevice *Device) | |
741 { | |
742 | |
743 //printf("RLM: recordProc is begun!!\n"); | |
744 // ALCdevice *Device = (ALCdevice*)ptr; | |
745 | |
746 record_data *data = (record_data*)Device->ExtraData; | |
747 | |
748 if(!data->killNow && Device->Connected) | |
749 { | |
750 | |
751 if (AL_TRUE) | |
752 { | |
753 // the device does not seem to be "ready" until this point. | |
754 init(Device); | |
755 //init2(Device); | |
756 //printf("\nMix Cycle %d\n", MixCount++); | |
757 //every(Device); | |
758 every2(Device); | |
759 //later(Device); | |
760 //printError(); | |
761 //aluMixData(Device, NULL, Device->UpdateSize); | |
762 //Sleep(3000); | |
763 } | |
764 } | |
765 else { | |
766 printf("WARNGING\n"); | |
767 } | |
768 | |
769 return 0; | |
770 } | |
771 | |
772 | |
773 void init(ALCdevice *Device){ | |
774 RUNONLY(1); | |
775 printf("one time init\n"); | |
776 printError(); | |
777 printf("auxContext : %p\n", auxContext); | |
778 auxContext = alcCreateContext(Device,NULL); | |
779 printf("auxContext : %p\n", auxContext); | |
780 printError(); | |
781 printf("mainContext : %p\n", mainContext); | |
782 mainContext = alcGetCurrentContext(); | |
783 printf("mainContext : %p\n", mainContext); | |
784 printError(); | |
785 printf("setting listener properties\n"); | |
786 alcMakeContextCurrent(auxContext); | |
787 ALfloat val1; | |
788 ALfloat val2; | |
789 ALfloat val3; | |
790 alGetListener3f(AL_POSITION, &val1, &val2, &val3); | |
791 printf("location is [%f,%f,%f]\n", val1,val2,val3); | |
792 alGetListener3f(AL_VELOCITY, &val1, &val2, &val3); | |
793 printf("velocity is [%f,%f,%f]\n", val1,val2,val3); | |
794 saveAux(Device); | |
795 saveMain(Device); | |
796 } | |
797 | |
798 void later(ALCdevice *Device){ | |
799 // run only the third time it is called | |
800 UNUSED(Device); | |
801 RUNAT(3); | |
802 printf("Suspending main Context....\n"); | |
803 alcSuspendContext(mainContext); | |
804 printError(); | |
805 printf("Switching to aux Context...\n"); | |
806 alcMakeContextCurrent(auxContext); | |
807 printError(); | |
808 } | |
809 | |
810 | |
811 | |
812 static ALCboolean record_open_playback(ALCdevice *device, const ALCchar *deviceName) | |
813 { | |
814 record_data *data; | |
815 // stop any buffering for stdout, so that I can | |
816 // see the damm printf statements in my terminal immediatley | |
817 setbuf(stdout, NULL); | |
818 | |
819 dprintf("open_playback is called.\n"); | |
820 if(!deviceName) | |
821 deviceName = recordDevice; | |
822 else if(strcmp(deviceName, recordDevice) != 0) | |
823 return ALC_FALSE; | |
824 | |
825 data = (record_data*)calloc(1, sizeof(*data)); | |
826 | |
827 device->szDeviceName = strdup(deviceName); | |
828 data->robert = 5; | |
829 device->ExtraData = data; | |
830 | |
831 return ALC_TRUE; | |
832 } | |
833 | |
834 static void record_close_playback(ALCdevice *device) | |
835 { | |
836 record_data *data = (record_data*)device->ExtraData; | |
837 dprintf("RLM: close playback called\n"); | |
838 free(data); | |
839 device->ExtraData = NULL; | |
840 } | |
841 | |
842 | |
843 | |
844 | |
845 | |
846 static ALCboolean record_reset_playback(ALCdevice *device) | |
847 { | |
848 record_data *data = (record_data*)device->ExtraData; | |
849 dprintf("RLM: reset playback called\n"); | |
850 | |
851 ALuint channels=0, bits=0; | |
852 | |
853 | |
854 | |
855 switch(device->FmtType) | |
856 { | |
857 case DevFmtByte: | |
858 device->FmtType = DevFmtUByte; | |
859 break; | |
860 case DevFmtUShort: | |
861 device->FmtType = DevFmtShort; | |
862 break; | |
863 case DevFmtUByte: | |
864 case DevFmtShort: | |
865 case DevFmtFloat: | |
866 break; | |
867 } | |
868 bits = BytesFromDevFmt(device->FmtType) * 8; | |
869 channels = ChannelsFromDevFmt(device->FmtChans); | |
870 data->size = device->UpdateSize * channels * bits / 8; | |
871 data->auxBuffer = malloc(data->size); | |
872 data->mainBuffer = malloc(data->size); | |
873 data->mainFull = AL_FALSE; | |
874 data->auxFull = AL_FALSE; | |
875 data->mainReady = AL_TRUE; | |
876 data->auxReady = AL_TRUE; | |
877 | |
878 if(!data->mainBuffer || !data->auxBuffer) | |
879 { | |
880 ERR("Buffer malloc failed\n"); | |
881 return ALC_FALSE; | |
882 } | |
883 | |
884 //data->thread = StartThread(RecordProc, device); | |
885 //data->thread = StartThread(noop, device); | |
886 | |
887 //TODO: shoudl free everything somewhere else! | |
888 | |
889 /* | |
890 if(data->thread == NULL) | |
891 { | |
892 free(data->mainBuffer); | |
893 free(data->auxBuffer); | |
894 free(data->unPauseIDs); | |
895 data->auxBuffer = NULL; | |
896 data->mainBuffer = NULL; | |
897 | |
898 return ALC_FALSE; | |
899 } | |
900 */ | |
901 return ALC_TRUE; | |
902 } | |
903 | |
904 | |
905 | |
906 static void record_stop_playback(ALCdevice *device) | |
907 { | |
908 record_data *data = (record_data*)device->ExtraData; | |
909 dprintf("RLM: stop playback called\n"); | |
910 printf("szName is %s \n", device->szDeviceName); | |
911 printf("robert is %d \n", data->robert); | |
912 | |
913 | |
914 if(!data->thread) | |
915 return; | |
916 | |
917 data->killNow = 1; | |
918 StopThread(data->thread); | |
919 data->thread = NULL; | |
920 | |
921 data->killNow = 0; | |
922 } | |
923 | |
924 | |
925 static const BackendFuncs record_funcs = { | |
926 record_open_playback, | |
927 record_close_playback, | |
928 record_reset_playback, | |
929 record_stop_playback, | |
930 NULL, | |
931 NULL, /* These would be filled with functions to */ | |
932 NULL, /* handle capturing audio if we did that. */ | |
933 NULL, | |
934 NULL, | |
935 NULL | |
936 }; | |
937 | |
938 ALCboolean alc_record_init(BackendFuncs *func_list) | |
939 { | |
940 dprintf("RECORD: I'm InIT111\n"); | |
941 *func_list = record_funcs; | |
942 return ALC_TRUE; | |
943 } | |
944 | |
945 void alc_record_deinit(void) | |
946 { | |
947 } | |
948 | |
949 void alc_record_probe(enum DevProbe type) | |
950 { | |
951 dprintf("RECORD: I'm being probed! :/\n"); | |
952 | |
953 switch(type) | |
954 { | |
955 case DEVICE_PROBE: | |
956 AppendDeviceList(recordDevice); | |
957 break; | |
958 case ALL_DEVICE_PROBE: | |
959 AppendAllDeviceList(recordDevice); | |
960 break; | |
961 case CAPTURE_DEVICE_PROBE: | |
962 break; | |
963 } | |
964 } | |
965 | |
966 | |
967 | |
968 | |
969 void printError(void){ | |
970 ALenum error = alGetError(); | |
971 printf("%s\n", GetALCErrorString(error)); | |
972 printf("%s\n", GetALErrorString(error)); | |
973 } | |
974 | |
975 | |
976 | |
977 char* GetALCErrorString(ALenum err) | |
978 { | |
979 switch(err) | |
980 { | |
981 case ALC_NO_ERROR: | |
982 return "AL_NO_ERROR"; | |
983 break; | |
984 | |
985 case ALC_INVALID_DEVICE: | |
986 return "ALC_INVALID_DEVICE"; | |
987 break; | |
988 | |
989 case ALC_INVALID_CONTEXT: | |
990 return "ALC_INVALID_CONTEXT"; | |
991 break; | |
992 | |
993 case ALC_INVALID_ENUM: | |
994 return "ALC_INVALID_ENUM"; | |
995 break; | |
996 | |
997 case ALC_INVALID_VALUE: | |
998 return "ALC_INVALID_VALUE"; | |
999 break; | |
1000 | |
1001 case ALC_OUT_OF_MEMORY: | |
1002 return "ALC_OUT_OF_MEMORY"; | |
1003 break; | |
1004 }; | |
1005 return "UNknown error."; | |
1006 } | |
1007 | |
1008 | |
1009 | |
1010 | |
1011 | |
1012 | |
1013 | |
1014 char* GetALErrorString(ALenum err) | |
1015 { | |
1016 switch(err) | |
1017 { | |
1018 case AL_NO_ERROR: | |
1019 return "AL_NO_ERROR"; | |
1020 break; | |
1021 | |
1022 case AL_INVALID_NAME: | |
1023 return "AL_INVALID_NAME"; | |
1024 break; | |
1025 | |
1026 case AL_INVALID_ENUM: | |
1027 return "AL_INVALID_ENUM"; | |
1028 break; | |
1029 | |
1030 case AL_INVALID_VALUE: | |
1031 return "AL_INVALID_VALUE"; | |
1032 break; | |
1033 | |
1034 case AL_INVALID_OPERATION: | |
1035 return "AL_INVALID_OPERATION"; | |
1036 break; | |
1037 | |
1038 case AL_OUT_OF_MEMORY: | |
1039 return "AL_OUT_OF_MEMORY"; | |
1040 break; | |
1041 }; | |
1042 return "UNknown error."; | |
1043 } | |
1044 | |
1045 | |
1046 | |
1047 | |
1048 | |
1049 | |
1050 | |
1051 #include "com_aurellem_audioPlay_TestCall.h" | |
1052 | |
1053 JNIEXPORT void JNICALL Java_com_aurellem_audioPlay_TestCall_nprintGarbage | |
1054 (JNIEnv *env, jclass clazz){ | |
1055 UNUSED(env);UNUSED(clazz); | |
1056 printf("Native! method* zzz\n"); | |
1057 return; | |
1058 } | |
1059 | |
1060 #include "com_aurellem_audioPlay_WavCaptureMaybe.h" | |
1061 | |
1062 JNIEXPORT void JNICALL Java_com_aurellem_audioPlay_WavCaptureMaybe_nrecord_1whatever | |
1063 (JNIEnv *env, jclass clazz){ | |
1064 UNUSED(env);UNUSED(clazz); | |
1065 printf("record_aurellem_whatever!"); | |
1066 } | |
1067 | |
1068 | |
1069 | |
1070 | |
1071 | |
1072 | |
1073 | |
1074 | |
1075 | |
1076 | |
1077 | |
1078 | |
1079 | |
1080 | |
1081 | |
1082 | |
1083 //////////////////////////// Real JNI stuff //////////////////////////////// | |
1084 void getMainSamples(ALCvoid *buffer){ | |
1085 UNUSED(buffer); | |
1086 // memcpy(mainBuffer, (ALubyte*) buffer, samples); | |
1087 } | |
1088 | |
1089 void getAuxSamples(ALCvoid *buffer){ | |
1090 UNUSED(buffer); | |
1091 // memcpy(auxBuffer, (ALubyte*) buffer, samples); | |
1092 } | |
1093 | |
1094 #include "com_jme3_capture_RecordAudioRenderer.h" | |
1095 | |
1096 /* | |
1097 * Class: com_jme3_capture_RecordAudioRenderer | |
1098 * Method: helloEveryone | |
1099 * Signature: ()V | |
1100 */ | |
1101 JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_helloEveryone | |
1102 (JNIEnv *env, jclass clazz){ | |
1103 UNUSED(env);UNUSED(clazz); | |
1104 printf("\n**************\nC from Java: I'm audioRecorder :)\n***********\n"); | |
1105 } | |
1106 | |
1107 | |
1108 /* | |
1109 * Class: com_jme3_capture_RecordAudioRenderer | |
1110 * Method: nstep | |
1111 * Signature: ()V | |
1112 */ | |
1113 JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_nstep | |
1114 (JNIEnv *env, jclass clazz, jlong device){ | |
1115 UNUSED(env);UNUSED(clazz);UNUSED(device); | |
1116 //printf("C from Java: I'm audioRecorder -- nstep :)\n"); | |
1117 RecordProc((ALCdevice*)((intptr_t)device)); | |
1118 } | |
1119 | |
1120 /* | |
1121 * Class: com_jme3_capture_RecordAudioRenderer | |
1122 * Method: ngetMainSamples | |
1123 * Signature: (JLjava/nio/ByteBuffer;I)V | |
1124 */ | |
1125 JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_ngetMainSamples | |
1126 (JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position){ | |
1127 UNUSED(clazz); | |
1128 | |
1129 ALvoid *buffer_address = | |
1130 ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); | |
1131 ALCdevice *recorder = (ALCdevice*) ((intptr_t)device); | |
1132 //printf("getMainSamples: device is %p\n", recorder); | |
1133 record_data *data = (record_data*)recorder->ExtraData; | |
1134 if (!data->mainFull){ | |
1135 printf("data is not ready!\n"); | |
1136 return; | |
1137 } | |
1138 memcpy(buffer_address, data->mainBuffer, data->size); | |
1139 data->mainFull = AL_FALSE; | |
1140 } | |
1141 | |
1142 /* | |
1143 * Class: com_jme3_capture_RecordAudioRenderer | |
1144 * Method: ngetAuxSamples | |
1145 * Signature: (JLjava/nio/ByteBuffer;I)V | |
1146 */ | |
1147 JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_ngetAuxSamples | |
1148 (JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position){ | |
1149 UNUSED(clazz); | |
1150 | |
1151 ALvoid *buffer_address = | |
1152 ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); | |
1153 ALCdevice *recorder = (ALCdevice*) ((intptr_t)device); | |
1154 //printf("getMainSamples: device is %p\n", recorder); | |
1155 record_data *data = (record_data*)recorder->ExtraData; | |
1156 | |
1157 memcpy(buffer_address, data->auxBuffer, data->size); | |
1158 | |
1159 } | |
1160 | |
1161 | |
1162 /* | |
1163 * Class: com_jme3_capture_RecordAudioRenderer | |
1164 * Method: nsetAuxListener3f | |
1165 * Signature: (IFFF)V | |
1166 */ | |
1167 JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_nsetAuxListener3f | |
1168 (JNIEnv *env, jclass clazz, jint pname, jfloat v1, jfloat v2, jfloat v3){ | |
1169 UNUSED(env);UNUSED(clazz); | |
1170 aux_alListener3f(pname, v1, v2, v3); | |
1171 } | |
1172 | |
1173 /* | |
1174 * Class: com_jme3_capture_RecordAudioRenderer | |
1175 * Method: nsetAuxListenerf | |
1176 * Signature: (IF)V | |
1177 */ | |
1178 JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_nsetAuxListenerf | |
1179 (JNIEnv *env, jclass clazz, jint pname, jfloat v1){ | |
1180 UNUSED(env);UNUSED(clazz); | |
1181 aux_alListenerf(pname, v1); | |
1182 } | |
1183 | |
1184 | |
1185 | |
1186 /* | |
1187 static void JNICALL Java_org_lwjgl_openal_ALC11_nalcCaptureSamples | |
1188 (JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position, jint samples) { | |
1189 ALvoid *buffer_address = | |
1190 ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); | |
1191 alcCaptureSamples((ALCdevice*) ((intptr_t)device), buffer_address, samples); | |
1192 } | |
1193 */ | |
1194 | |
1195 | |
1196 | |
1197 | |
1198 | |
1199 |