rlm@0: /** rlm@0: * OpenAL cross platform audio library rlm@0: * Copyright (C) 2010 by Chris Robinson rlm@0: * This library is free software; you can redistribute it and/or rlm@0: * modify it under the terms of the GNU Library General Public rlm@0: * License as published by the Free Software Foundation; either rlm@0: * version 2 of the License, or (at your option) any later version. rlm@0: * rlm@0: * This library is distributed in the hope that it will be useful, rlm@0: * but WITHOUT ANY WARRANTY; without even the implied warranty of rlm@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU rlm@0: * Library General Public License for more details. rlm@0: * rlm@0: * You should have received a copy of the GNU Library General Public rlm@0: * License along with this library; if not, write to the rlm@0: * Free Software Foundation, Inc., 59 Temple Place - Suite 330, rlm@0: * Boston, MA 02111-1307, USA. rlm@0: * Or go to http://www.gnu.org/copyleft/lgpl.html rlm@0: */ rlm@0: rlm@0: #include "config.h" rlm@0: #include rlm@0: #include "alMain.h" rlm@0: #include "AL/al.h" rlm@0: #include "AL/alc.h" rlm@0: #include "alSource.h" rlm@0: #include rlm@0: rlm@0: rlm@0: typedef struct record_data { rlm@0: volatile int killNow; rlm@0: ALvoid *thread; rlm@0: ALuint robert; rlm@0: rlm@0: ALvoid *mainBuffer; rlm@0: ALvoid *auxBuffer; rlm@0: ALuint size; rlm@0: rlm@0: ALuint *unPauseIDs; rlm@0: int unPauseCount; rlm@0: ALboolean mainFull; rlm@0: ALboolean auxFull; rlm@0: ALboolean auxReady; rlm@0: ALboolean mainReady; rlm@0: rlm@0: } record_data; rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: #define UNUSED(x) (void)(x) rlm@0: #define RUNONLY(n) \ rlm@0: {static int __runonce = n; \ rlm@0: if (__runonce-- <= 0){return;}} rlm@0: rlm@0: #define RUNAT(n) \ rlm@0: {static int __runat = n; \ rlm@0: if (0 != __runat--){return;}} rlm@0: rlm@0: /// al error handling code prototypes rlm@0: rlm@0: char* GetALErrorString(ALenum err); rlm@0: char* GetALCErrorString(ALenum err); rlm@0: void printError(void); rlm@0: void init(ALCdevice *); rlm@0: void init2(ALCdevice *); rlm@0: void later(ALCdevice *); rlm@0: void every(ALCdevice *); rlm@0: void every2(ALCdevice *); rlm@0: void step(ALCdevice *); rlm@0: rlm@0: rlm@0: //synchronization rlm@0: struct record_data; rlm@0: void syncContexts(ALCcontext *, ALCcontext *); rlm@0: void syncSources(ALsource *, ALsource *, ALCcontext *, ALCcontext *); rlm@0: void pauseMainContext(struct record_data *); rlm@0: void unPauseMainContext(struct record_data *); rlm@0: void pauseAllSources(ALCcontext *); rlm@0: static void saveAux(ALCdevice *); rlm@0: static void swapInAux(ALCdevice *); rlm@0: static void saveMain(ALCdevice *); rlm@0: static void swapInMain(ALCdevice *); rlm@0: void aux_alListenerf(ALenum param, ALfloat value); rlm@0: void aux_alListener3f(ALenum param, ALfloat v1, ALfloat v2, ALfloat v3); rlm@0: rlm@0: rlm@0: ////////////// rlm@0: rlm@0: rlm@0: rlm@0: // remove all the sources from all the auxContexts rlm@0: // take the mainContext and for each context, COPY rlm@0: // the sources from the main context. rlm@0: rlm@0: // render each context and make their data available. rlm@0: rlm@0: // =alGenSources= (and =alGetError=) rlm@0: // attach each source to the shared buffer using =alSourcei= rlm@0: rlm@0: rlm@0: // need to make sure in the AudioRender class that we don't do rlm@0: // anything to sources while the audio is being rendered, so make sure rlm@0: // to maintain an "isDone" state as well. rlm@0: rlm@0: // Special device which allows simulation of multiple listeners rlm@0: // hearing the same set of sources. Provides access to the rendered rlm@0: // data for each listener. Designed to work with LWJGL. rlm@0: rlm@0: // first, the mainContext is the only context that is controlled by rlm@0: // LWJGL. rlm@0: rlm@0: // One context will be created for each listener that we want. rlm@0: rlm@0: // Then, at the start of each render loop, first PAUSE the sources on rlm@0: // all other contexts except the mainContext (this takes care of rlm@0: // sources in the mainContext being shut down.) rlm@0: // we will iterate through all rlm@0: // the active sources in our mainContext (the one which is controlled rlm@0: // through LWJGL), and take their sourceIDs. For each of these IDs rlm@0: // and for each other context, we'll check some internal structure to rlm@0: // see if we've already created a corresponding source. If that rlm@0: // source exits, we will SYNCH it with the source which belongs to the rlm@0: // mainContext. If it DOESN'T exist, we will CLONE the source from the rlm@0: // main context and establish it in the other context. rlm@0: rlm@0: // Each render loop consists of noting all of the active sources in rlm@0: // the mainContext and storing their IDs. Then, for each context, rlm@0: // the correspondig sources to the active sources in the mainContext rlm@0: // will be set to PLAY, and all sources in all other contexts will be rlm@0: // set to PAUSE. aluMixData will be called for each context in this rlm@0: // way. rlm@0: rlm@0: // approved by KittyCat rlm@0: rlm@0: rlm@0: // CAN get id appropiate for us in the sorce-repated openal functions rlm@0: // by quering *source->source rlm@0: rlm@0: // first, do it with only two listeners, two contexts, automatically rlm@0: // created. rlm@0: rlm@0: static ALCcontext* mainContext = NULL; rlm@0: static ALCcontext* auxContext = NULL; rlm@0: rlm@0: rlm@0: void aux_alListenerf(ALenum param, ALfloat value){ rlm@0: ALCcontext *current = alcGetCurrentContext(); rlm@0: alcMakeContextCurrent(auxContext); rlm@0: alListenerf(param, value); rlm@0: alcMakeContextCurrent(current); rlm@0: } rlm@0: rlm@0: void aux_alListener3f(ALenum param, ALfloat v1, ALfloat v2, ALfloat v3){ rlm@0: ALCcontext *current = alcGetCurrentContext(); rlm@0: alcMakeContextCurrent(auxContext); rlm@0: alListener3f(param, v1, v2, v3); rlm@0: alcMakeContextCurrent(current); rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: void pauseAllSources(ALCcontext *ctx){ rlm@0: ALCcontext *current = alcGetCurrentContext(); rlm@0: alcMakeContextCurrent(ctx); rlm@0: ALsource **src, **src_end; rlm@0: src = ctx->ActiveSources; rlm@0: src_end = src + ctx->ActiveSourceCount; rlm@0: while(src != src_end){ rlm@0: if (AL_PLAYING == (*src)->state){ rlm@0: //if (AL_TRUE){ rlm@0: ALuint source_id = (*src)->source; rlm@0: //printf("pausing ONE source\n"); rlm@0: alSourcePause(source_id); rlm@0: } rlm@0: src++; rlm@0: } rlm@0: alcMakeContextCurrent(current); rlm@0: } rlm@0: rlm@0: rlm@0: void init2(ALCdevice *Device){ rlm@0: UNUSED(Device); rlm@0: RUNONLY(1) rlm@0: // the mainContext only ever has a FIXED number of sources! rlm@0: // duplicate them ALL into auxContext! rlm@0: alcMakeContextCurrent(auxContext);{ rlm@0: UIntMap source_map= mainContext->SourceMap; rlm@0: ALuint num_sources = source_map.size; rlm@0: ALuint newSources[num_sources]; rlm@0: alGenSources(num_sources, newSources);} rlm@0: alcMakeContextCurrent(mainContext); rlm@0: rlm@0: rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: /* rlm@0: void syncSourcei(ALuint sourceID1, ALuint sourceID2, rlm@0: ALCcontext *ctx1, ALCcontext *ctx2, rlm@0: int numParams, ALenum *params){ rlm@0: ALint values[numParams]; rlm@0: ALCcontext current = alcGetCurrentContext(); rlm@0: // get values rlm@0: printf("getting values from source1\n"); rlm@0: alcMakeContextCurrent(ctx1); rlm@0: int i; rlm@0: for(i=0; isource; rlm@0: ALuint ID2 = source2->source; rlm@0: ALCcontext *current = alcGetCurrentContext(); rlm@0: //printf("***************\n"); rlm@0: //printf("SYNCHING source %d with source %d\n", ID1, ID2); rlm@0: rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_PITCH); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_GAIN); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_MAX_DISTANCE); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_ROLLOFF_FACTOR); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_REFERENCE_DISTANCE); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_MIN_GAIN); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_MAX_GAIN); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_CONE_OUTER_GAIN); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_CONE_INNER_ANGLE); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_CONE_OUTER_ANGLE); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_SEC_OFFSET); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_SAMPLE_OFFSET); rlm@0: DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_BYTE_OFFSET); rlm@0: rlm@0: DsyncSource3f(ID1,ID2,ctx1,ctx2,AL_POSITION); rlm@0: DsyncSource3f(ID1,ID2,ctx1,ctx2,AL_VELOCITY); rlm@0: DsyncSource3f(ID1,ID2,ctx1,ctx2,AL_DIRECTION); rlm@0: rlm@0: DsyncSourcei(ID1,ID2,ctx1,ctx2,AL_SOURCE_RELATIVE); rlm@0: DsyncSourcei(ID1,ID2,ctx1,ctx2,AL_LOOPING); rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: // first, copy buffer patterns over. rlm@0: rlm@0: //source2->lSourceType = source1->lSourceType; rlm@0: //source2->NumChannels = source1->NumChannels; rlm@0: //source2->SampleSize = source1->SampleSize; rlm@0: //source2->Buffer = source1->Buffer; rlm@0: // source2->queue = source1->queue; rlm@0: // source2->BuffersInQueue = source1-> BuffersInQueue; rlm@0: // source2->BuffersPlayed = source1 -> BuffersPlayed; rlm@0: rlm@0: // then, duplicate the state. rlm@0: rlm@0: // handle static sources rlm@0: //printf("handling Buffers\n"); rlm@0: alcMakeContextCurrent(ctx1); rlm@0: ALint source_type; rlm@0: alGetSourcei(ID1, AL_SOURCE_TYPE, &source_type); rlm@0: //printError(); rlm@0: rlm@0: if (AL_STATIC == source_type){ rlm@0: //printf("setting STATIC source\n"); rlm@0: ALint buffer_id1; rlm@0: ALint buffer_id2; rlm@0: alGetSourcei(ID1, AL_BUFFER, &buffer_id1); rlm@0: alcMakeContextCurrent(ctx2); rlm@0: alGetSourcei(ID2, AL_BUFFER, &buffer_id2); rlm@0: if (buffer_id1 != buffer_id2){ rlm@0: //printf("setting source2's buffer from %d to %d\n", buffer_id2, buffer_id1); rlm@0: alSourcei(ID2, AL_BUFFER, buffer_id1); rlm@0: //printError(); rlm@0: } rlm@0: else { rlm@0: //printf("Buffers are already the same, doing nothing.\n"); rlm@0: } rlm@0: } rlm@0: else { rlm@0: // printf("not a static source!\n"); rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: alcMakeContextCurrent(ctx2); rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: //printf("setting STATE\n"); rlm@0: alcMakeContextCurrent(ctx1); rlm@0: ALint state1; rlm@0: alGetSourcei(ID1, AL_SOURCE_STATE, &state1); rlm@0: //printError(); rlm@0: rlm@0: alcMakeContextCurrent(ctx2); rlm@0: ALint state2; rlm@0: alGetSourcei(ID2, AL_SOURCE_STATE, &state2); rlm@0: //printError(); rlm@0: if (state1 != state2){ rlm@0: switch (state1){ rlm@0: case AL_INITIAL : /*printf("INITIAL\n")*/;alSourceRewind(ID2);break; rlm@0: case AL_PLAYING : /*printf("PLAYING\n")*/;alSourcePlay(ID2);break; rlm@0: case AL_PAUSED : /*printf("PAUSED\n")*/;alSourcePause(ID2);break; rlm@0: case AL_STOPPED : /*printf("STOPPED\n")*/;alSourceStop(ID2);break; rlm@0: } rlm@0: } rlm@0: //printError(); rlm@0: rlm@0: rlm@0: rlm@0: alcMakeContextCurrent(current); rlm@0: rlm@0: } rlm@0: rlm@0: rlm@0: void syncContexts(ALCcontext *ctx1, ALCcontext *ctx2){ rlm@0: // if there aren't sufficient sources in ctx2 to mirror the sources rlm@0: // in ctx1, create them. rlm@0: ALCcontext *current = alcGetCurrentContext(); rlm@0: rlm@0: UIntMap *sourceMap1 = &(ctx1->SourceMap); rlm@0: UIntMap *sourceMap2 = &(ctx2->SourceMap); rlm@0: rlm@0: rlm@0: ALuint sources1 = sourceMap1->size; rlm@0: ALuint sources2 = sourceMap2->size; rlm@0: rlm@0: //printf("ctx1 has %d sources; ctx2 has %d sources\n", sources1, sources2); rlm@0: rlm@0: alcMakeContextCurrent(ctx2); rlm@0: if (sources2 < sources1){ rlm@0: ALuint numSources = sources1 - sources2; rlm@0: ALuint newSources[numSources]; rlm@0: alGenSources(numSources, newSources); rlm@0: printf("adjusting...\n"); rlm@0: printf("now ctx1 has %d sources; ctx2 has %d sources\n", rlm@0: sourceMap1->size, sourceMap2->size); rlm@0: } rlm@0: //printError(); rlm@0: rlm@0: rlm@0: alcMakeContextCurrent(current); rlm@0: rlm@0: rlm@0: // after this, ctx2 is gauranteed to have at least as many sources rlm@0: // as ctx1. Now, sync each source from ctx1 to the corresponding rlm@0: // source in ctx2. rlm@0: rlm@0: int i; rlm@0: rlm@0: rlm@0: rlm@0: for(i = 0; i < sourceMap1->size; i++){ rlm@0: syncSources((ALsource*)sourceMap1->array[i].value, rlm@0: (ALsource*)sourceMap2->array[i].value, rlm@0: ctx1, ctx2); rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: void pauseMainContext(record_data *data){ rlm@0: //printf("pausing MainContext\n"); rlm@0: data->unPauseCount = 0; rlm@0: data->unPauseIDs = rlm@0: (ALuint*)realloc(data->unPauseIDs, rlm@0: sizeof(ALuint) * mainContext->ActiveSourceCount); rlm@0: rlm@0: ALsource **src, **src_end; rlm@0: src = mainContext->ActiveSources; rlm@0: src_end = src + mainContext->ActiveSourceCount; rlm@0: rlm@0: while(src != src_end){ rlm@0: rlm@0: if (AL_PLAYING == (*src)->state){ rlm@0: ALuint source_id = (*src)->source; rlm@0: data->unPauseIDs[data->unPauseCount++] = source_id; rlm@0: alSourcePause(source_id); rlm@0: } rlm@0: src++; rlm@0: } rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: void unPauseMainContext(record_data *data){ rlm@0: int i; rlm@0: for(i=0;iunPauseCount;i++){ rlm@0: alSourcePlay(data->unPauseIDs[i]); rlm@0: } rlm@0: } rlm@0: rlm@0: rlm@0: // a device brings along with it multiple pieces of state rlm@0: // which have to be swapped in and out with each context. rlm@0: rlm@0: //static ALfloat DryBufferMain[BUFFERSIZE][MAXCHANNELS]; rlm@0: //static ALfloat DryBufferAux[BUFFERSIZE][MAXCHANNELS]; rlm@0: //static ALfloat PanningLUTMain[LUT_NUM][MAXCHANNELS]; rlm@0: //static ALfloat PanningLUTAux[LUT_NUM][MAXCHANNELS]; rlm@0: static ALfloat ClickRemovalMain[MAXCHANNELS]; rlm@0: static ALfloat ClickRemovalAux[MAXCHANNELS]; rlm@0: static ALfloat PendingClicksMain[MAXCHANNELS]; rlm@0: static ALfloat PendingClicksAux[MAXCHANNELS]; rlm@0: rlm@0: rlm@0: rlm@0: static void saveAux(ALCdevice *Device){ rlm@0: //memcpy(DryBufferAux, Device->DryBuffer, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); rlm@0: //memcpy(PanningLUTAux, Device->PanningLUT, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); rlm@0: memcpy(ClickRemovalAux, Device->ClickRemoval, sizeof(ALfloat)*MAXCHANNELS); rlm@0: memcpy(PendingClicksAux, Device->PendingClicks, sizeof(ALfloat)*MAXCHANNELS); rlm@0: } rlm@0: static void swapInAux(ALCdevice *Device){ rlm@0: //memcpy(Device->DryBuffer, DryBufferAux, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); rlm@0: //memcpy(Device->PanningLUT, PanningLUTAux, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); rlm@0: memcpy(Device->ClickRemoval, ClickRemovalAux, sizeof(ALfloat)*MAXCHANNELS); rlm@0: memcpy(Device->PendingClicks, PendingClicksAux, sizeof(ALfloat)*MAXCHANNELS); rlm@0: } rlm@0: rlm@0: rlm@0: static void saveMain(ALCdevice *Device){ rlm@0: //memcpy(DryBufferMain, Device->DryBuffer, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); rlm@0: //memcpy(PanningLUTMain, Device->PanningLUT, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); rlm@0: memcpy(ClickRemovalMain, Device->ClickRemoval, sizeof(ALfloat)*MAXCHANNELS); rlm@0: memcpy(PendingClicksMain, Device->PendingClicks, sizeof(ALfloat)*MAXCHANNELS); rlm@0: } rlm@0: static void swapInMain(ALCdevice *Device){ rlm@0: //memcpy(Device->DryBuffer, DryBufferMain, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); rlm@0: //memcpy(Device->PanningLUT, PanningLUTMain, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); rlm@0: memcpy(Device->ClickRemoval, ClickRemovalMain, sizeof(ALfloat)*MAXCHANNELS); rlm@0: memcpy(Device->PendingClicks, PendingClicksMain, sizeof(ALfloat)*MAXCHANNELS); rlm@0: } rlm@0: rlm@0: rlm@0: static ALCcontext **currentContext; rlm@0: static ALuint currentNumContext; rlm@0: static void unLimitContext(ALCdevice *Device){ rlm@0: Device->Contexts = currentContext; rlm@0: Device->NumContexts = currentNumContext; rlm@0: } rlm@0: rlm@0: static void limitContext(ALCdevice *Device, ALCcontext *ctx){ rlm@0: currentContext = Device->Contexts; rlm@0: currentNumContext = Device->NumContexts; rlm@0: Device->Contexts = &ctx; rlm@0: Device->NumContexts = 1; rlm@0: } rlm@0: rlm@0: rlm@0: void every2(ALCdevice *Device){ rlm@0: rlm@0: record_data *data = (record_data*)Device->ExtraData; rlm@0: rlm@0: if (data->mainFull){ rlm@0: printf("data has not yet been extracted!\n"); rlm@0: return; rlm@0: } rlm@0: rlm@0: rlm@0: syncContexts(mainContext , auxContext); rlm@0: rlm@0: alcMakeContextCurrent(auxContext); rlm@0: limitContext(Device, auxContext); rlm@0: swapInAux(Device); rlm@0: aluMixData(Device, data->auxBuffer, Device->UpdateSize); rlm@0: saveAux(Device); rlm@0: unLimitContext(Device); rlm@0: rlm@0: rlm@0: alcMakeContextCurrent(mainContext); rlm@0: limitContext(Device, mainContext); rlm@0: swapInMain(Device); rlm@0: aluMixData(Device, data->mainBuffer, Device->UpdateSize); rlm@0: saveMain(Device); rlm@0: unLimitContext(Device); rlm@0: rlm@0: data->mainFull = AL_TRUE; rlm@0: data->auxFull = AL_TRUE; rlm@0: rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: void every(ALCdevice *Device){ rlm@0: UNUSED(Device); rlm@0: // by the time every() is called, mainContext and auxContext will rlm@0: // have been initiliazed. rlm@0: printf("+++++++\nevery is called\n"); rlm@0: // print sourceid for all sources. rlm@0: ALsource **src, **src_end; rlm@0: // LockDevice(Device); rlm@0: // pauseAllSources(auxContext); rlm@0: src = mainContext->ActiveSources; rlm@0: src_end = src + mainContext->ActiveSourceCount; rlm@0: UIntMap source_map ; rlm@0: int i; rlm@0: rlm@0: source_map= mainContext->SourceMap; rlm@0: printf("max sources in the mainContext is %d\n", source_map.maxsize); rlm@0: printf("current sources: %d\n", source_map.size); rlm@0: rlm@0: printf("their ID's are:\n"); rlm@0: for(i = 0; i < source_map.size; i++){ rlm@0: printf("%d, ",source_map.array[i].key); rlm@0: } rlm@0: printf("\n"); rlm@0: source_map= auxContext->SourceMap; rlm@0: printf("max sources in the auxContext is %d\n", source_map.maxsize); rlm@0: printf("current sources: %d\n", source_map.size); rlm@0: rlm@0: printf("their ID's are:\n"); rlm@0: for(i = 0; i < source_map.size; i++){ rlm@0: printf("%d, ",source_map.array[i].key); rlm@0: } rlm@0: printf("\n"); rlm@0: rlm@0: while(src != src_end){ rlm@0: rlm@0: if (AL_PLAYING == (*src)->state){ rlm@0: ALuint source_id = (*src)->source; rlm@0: printf("source %d is AL_PLAYING\n",source_id); rlm@0: } rlm@0: src++; rlm@0: rlm@0: } rlm@0: rlm@0: rlm@0: // UnlockDevice(Device); rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: // debug printing rlm@0: rlm@0: #define DEBUG 0 rlm@0: rlm@0: #define dprintf(expr) {if (DEBUG) {printf(expr);}} rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: static const ALCchar recordDevice[] = "Aurellem"; rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: struct ALsource * cloneSource(struct ALsource *source); rlm@0: rlm@0: //struct ALsource * cloneSource(struct ALsource *source){ rlm@0: // ALuint[1] sourceID; rlm@0: rlm@0: rlm@0: //} rlm@0: rlm@0: int lock = 0; rlm@0: rlm@0: /* rlm@0: static ALuint RecordProc() rlm@0: { rlm@0: if (0 == lock){return 0;} rlm@0: ALCdevice *Device = deviceInstance; rlm@0: dprintf("RLM: recordProc is begun!!\n"); rlm@0: printError(); rlm@0: static int MixCount = 0 ; rlm@0: if (Device->Connected) rlm@0: { rlm@0: // the device does not seem to be "ready" until this point. rlm@0: init(Device); rlm@0: //init2(Device); rlm@0: printf("\nMix Cycle %d\n", MixCount++); rlm@0: every(Device); rlm@0: every2(Device); rlm@0: //aluMixData(Device, NULL, Device->UpdateSize); rlm@0: } rlm@0: lock = 1; rlm@0: return 0; rlm@0: } rlm@0: */ rlm@0: rlm@0: rlm@0: /* rlm@0: static ALuint RecordProc(ALvoid *ptr) rlm@0: { rlm@0: rlm@0: printf("RLM: recordProc is begun!!\n"); rlm@0: ALCdevice *Device = (ALCdevice*)ptr; rlm@0: //printError(); rlm@0: record_data *data = (record_data*)Device->ExtraData; rlm@0: ALuint now, start; rlm@0: ALuint64 avail, done; rlm@0: const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 / rlm@0: Device->Frequency / 2; rlm@0: rlm@0: done = 0; rlm@0: start = timeGetTime(); rlm@0: //static int MixCount = 0 ; rlm@0: rlm@0: rlm@0: if(!data->killNow && Device->Connected) rlm@0: { rlm@0: printf("sext level breakfast manuever!\n"); rlm@0: now = timeGetTime(); rlm@0: rlm@0: avail = (ALuint64)(now-start) * Device->Frequency / 1000; rlm@0: if(avail < done) rlm@0: { rlm@0: rlm@0: avail += (ALuint64)0xFFFFFFFFu*Device->Frequency/1000 - done; rlm@0: done = 0; rlm@0: } rlm@0: if(avail-done < Device->UpdateSize) rlm@0: { rlm@0: //Sleep(restTime); rlm@0: //continue; rlm@0: } rlm@0: rlm@0: while(avail-done >= Device->UpdateSize) rlm@0: { rlm@0: // the device does not seem to be "ready" until this point. rlm@0: init(Device); rlm@0: //init2(Device); rlm@0: //printf("\nMix Cycle %d\n", MixCount++); rlm@0: //every(Device); rlm@0: every2(Device); rlm@0: //later(Device); rlm@0: //printError(); rlm@0: //aluMixData(Device, NULL, Device->UpdateSize); rlm@0: //Sleep(3000); rlm@0: done += Device->UpdateSize; rlm@0: } rlm@0: } rlm@0: else { rlm@0: printf("WARNGING\n"); rlm@0: } rlm@0: rlm@0: return 0; rlm@0: } rlm@0: */ rlm@0: rlm@0: rlm@0: rlm@0: static ALuint RecordProc(ALCdevice *Device) rlm@0: { rlm@0: rlm@0: //printf("RLM: recordProc is begun!!\n"); rlm@0: // ALCdevice *Device = (ALCdevice*)ptr; rlm@0: rlm@0: record_data *data = (record_data*)Device->ExtraData; rlm@0: rlm@0: if(!data->killNow && Device->Connected) rlm@0: { rlm@0: rlm@0: if (AL_TRUE) rlm@0: { rlm@0: // the device does not seem to be "ready" until this point. rlm@0: init(Device); rlm@0: //init2(Device); rlm@0: //printf("\nMix Cycle %d\n", MixCount++); rlm@0: //every(Device); rlm@0: every2(Device); rlm@0: //later(Device); rlm@0: //printError(); rlm@0: //aluMixData(Device, NULL, Device->UpdateSize); rlm@0: //Sleep(3000); rlm@0: } rlm@0: } rlm@0: else { rlm@0: printf("WARNGING\n"); rlm@0: } rlm@0: rlm@0: return 0; rlm@0: } rlm@0: rlm@0: rlm@0: void init(ALCdevice *Device){ rlm@0: RUNONLY(1); rlm@0: printf("one time init\n"); rlm@0: printError(); rlm@0: printf("auxContext : %p\n", auxContext); rlm@0: auxContext = alcCreateContext(Device,NULL); rlm@0: printf("auxContext : %p\n", auxContext); rlm@0: printError(); rlm@0: printf("mainContext : %p\n", mainContext); rlm@0: mainContext = alcGetCurrentContext(); rlm@0: printf("mainContext : %p\n", mainContext); rlm@0: printError(); rlm@0: printf("setting listener properties\n"); rlm@0: alcMakeContextCurrent(auxContext); rlm@0: ALfloat val1; rlm@0: ALfloat val2; rlm@0: ALfloat val3; rlm@0: alGetListener3f(AL_POSITION, &val1, &val2, &val3); rlm@0: printf("location is [%f,%f,%f]\n", val1,val2,val3); rlm@0: alGetListener3f(AL_VELOCITY, &val1, &val2, &val3); rlm@0: printf("velocity is [%f,%f,%f]\n", val1,val2,val3); rlm@0: saveAux(Device); rlm@0: saveMain(Device); rlm@0: } rlm@0: rlm@0: void later(ALCdevice *Device){ rlm@0: // run only the third time it is called rlm@0: UNUSED(Device); rlm@0: RUNAT(3); rlm@0: printf("Suspending main Context....\n"); rlm@0: alcSuspendContext(mainContext); rlm@0: printError(); rlm@0: printf("Switching to aux Context...\n"); rlm@0: alcMakeContextCurrent(auxContext); rlm@0: printError(); rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: static ALCboolean record_open_playback(ALCdevice *device, const ALCchar *deviceName) rlm@0: { rlm@0: record_data *data; rlm@0: // stop any buffering for stdout, so that I can rlm@0: // see the damm printf statements in my terminal immediatley rlm@0: setbuf(stdout, NULL); rlm@0: rlm@0: dprintf("open_playback is called.\n"); rlm@0: if(!deviceName) rlm@0: deviceName = recordDevice; rlm@0: else if(strcmp(deviceName, recordDevice) != 0) rlm@0: return ALC_FALSE; rlm@0: rlm@0: data = (record_data*)calloc(1, sizeof(*data)); rlm@0: rlm@0: device->szDeviceName = strdup(deviceName); rlm@0: data->robert = 5; rlm@0: device->ExtraData = data; rlm@0: rlm@0: return ALC_TRUE; rlm@0: } rlm@0: rlm@0: static void record_close_playback(ALCdevice *device) rlm@0: { rlm@0: record_data *data = (record_data*)device->ExtraData; rlm@0: dprintf("RLM: close playback called\n"); rlm@0: free(data); rlm@0: device->ExtraData = NULL; rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: static ALCboolean record_reset_playback(ALCdevice *device) rlm@0: { rlm@0: record_data *data = (record_data*)device->ExtraData; rlm@0: dprintf("RLM: reset playback called\n"); rlm@0: rlm@0: ALuint channels=0, bits=0; rlm@0: rlm@0: rlm@0: rlm@0: switch(device->FmtType) rlm@0: { rlm@0: case DevFmtByte: rlm@0: device->FmtType = DevFmtUByte; rlm@0: break; rlm@0: case DevFmtUShort: rlm@0: device->FmtType = DevFmtShort; rlm@0: break; rlm@0: case DevFmtUByte: rlm@0: case DevFmtShort: rlm@0: case DevFmtFloat: rlm@0: break; rlm@0: } rlm@0: bits = BytesFromDevFmt(device->FmtType) * 8; rlm@0: channels = ChannelsFromDevFmt(device->FmtChans); rlm@0: data->size = device->UpdateSize * channels * bits / 8; rlm@0: data->auxBuffer = malloc(data->size); rlm@0: data->mainBuffer = malloc(data->size); rlm@0: data->mainFull = AL_FALSE; rlm@0: data->auxFull = AL_FALSE; rlm@0: data->mainReady = AL_TRUE; rlm@0: data->auxReady = AL_TRUE; rlm@0: rlm@0: if(!data->mainBuffer || !data->auxBuffer) rlm@0: { rlm@0: ERR("Buffer malloc failed\n"); rlm@0: return ALC_FALSE; rlm@0: } rlm@0: rlm@0: //data->thread = StartThread(RecordProc, device); rlm@0: //data->thread = StartThread(noop, device); rlm@0: rlm@0: //TODO: shoudl free everything somewhere else! rlm@0: rlm@0: /* rlm@0: if(data->thread == NULL) rlm@0: { rlm@0: free(data->mainBuffer); rlm@0: free(data->auxBuffer); rlm@0: free(data->unPauseIDs); rlm@0: data->auxBuffer = NULL; rlm@0: data->mainBuffer = NULL; rlm@0: rlm@0: return ALC_FALSE; rlm@0: } rlm@0: */ rlm@0: return ALC_TRUE; rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: static void record_stop_playback(ALCdevice *device) rlm@0: { rlm@0: record_data *data = (record_data*)device->ExtraData; rlm@0: dprintf("RLM: stop playback called\n"); rlm@0: printf("szName is %s \n", device->szDeviceName); rlm@0: printf("robert is %d \n", data->robert); rlm@0: rlm@0: rlm@0: if(!data->thread) rlm@0: return; rlm@0: rlm@0: data->killNow = 1; rlm@0: StopThread(data->thread); rlm@0: data->thread = NULL; rlm@0: rlm@0: data->killNow = 0; rlm@0: } rlm@0: rlm@0: rlm@0: static const BackendFuncs record_funcs = { rlm@0: record_open_playback, rlm@0: record_close_playback, rlm@0: record_reset_playback, rlm@0: record_stop_playback, rlm@0: NULL, rlm@0: NULL, /* These would be filled with functions to */ rlm@0: NULL, /* handle capturing audio if we did that. */ rlm@0: NULL, rlm@0: NULL, rlm@0: NULL rlm@0: }; rlm@0: rlm@0: ALCboolean alc_record_init(BackendFuncs *func_list) rlm@0: { rlm@0: dprintf("RECORD: I'm InIT111\n"); rlm@0: *func_list = record_funcs; rlm@0: return ALC_TRUE; rlm@0: } rlm@0: rlm@0: void alc_record_deinit(void) rlm@0: { rlm@0: } rlm@0: rlm@0: void alc_record_probe(enum DevProbe type) rlm@0: { rlm@0: dprintf("RECORD: I'm being probed! :/\n"); rlm@0: rlm@0: switch(type) rlm@0: { rlm@0: case DEVICE_PROBE: rlm@0: AppendDeviceList(recordDevice); rlm@0: break; rlm@0: case ALL_DEVICE_PROBE: rlm@0: AppendAllDeviceList(recordDevice); rlm@0: break; rlm@0: case CAPTURE_DEVICE_PROBE: rlm@0: break; rlm@0: } rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: void printError(void){ rlm@0: ALenum error = alGetError(); rlm@0: printf("%s\n", GetALCErrorString(error)); rlm@0: printf("%s\n", GetALErrorString(error)); rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: char* GetALCErrorString(ALenum err) rlm@0: { rlm@0: switch(err) rlm@0: { rlm@0: case ALC_NO_ERROR: rlm@0: return "AL_NO_ERROR"; rlm@0: break; rlm@0: rlm@0: case ALC_INVALID_DEVICE: rlm@0: return "ALC_INVALID_DEVICE"; rlm@0: break; rlm@0: rlm@0: case ALC_INVALID_CONTEXT: rlm@0: return "ALC_INVALID_CONTEXT"; rlm@0: break; rlm@0: rlm@0: case ALC_INVALID_ENUM: rlm@0: return "ALC_INVALID_ENUM"; rlm@0: break; rlm@0: rlm@0: case ALC_INVALID_VALUE: rlm@0: return "ALC_INVALID_VALUE"; rlm@0: break; rlm@0: rlm@0: case ALC_OUT_OF_MEMORY: rlm@0: return "ALC_OUT_OF_MEMORY"; rlm@0: break; rlm@0: }; rlm@0: return "UNknown error."; rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: char* GetALErrorString(ALenum err) rlm@0: { rlm@0: switch(err) rlm@0: { rlm@0: case AL_NO_ERROR: rlm@0: return "AL_NO_ERROR"; rlm@0: break; rlm@0: rlm@0: case AL_INVALID_NAME: rlm@0: return "AL_INVALID_NAME"; rlm@0: break; rlm@0: rlm@0: case AL_INVALID_ENUM: rlm@0: return "AL_INVALID_ENUM"; rlm@0: break; rlm@0: rlm@0: case AL_INVALID_VALUE: rlm@0: return "AL_INVALID_VALUE"; rlm@0: break; rlm@0: rlm@0: case AL_INVALID_OPERATION: rlm@0: return "AL_INVALID_OPERATION"; rlm@0: break; rlm@0: rlm@0: case AL_OUT_OF_MEMORY: rlm@0: return "AL_OUT_OF_MEMORY"; rlm@0: break; rlm@0: }; rlm@0: return "UNknown error."; rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: #include "com_aurellem_audioPlay_TestCall.h" rlm@0: rlm@0: JNIEXPORT void JNICALL Java_com_aurellem_audioPlay_TestCall_nprintGarbage rlm@0: (JNIEnv *env, jclass clazz){ rlm@0: UNUSED(env);UNUSED(clazz); rlm@0: printf("Native! method* zzz\n"); rlm@0: return; rlm@0: } rlm@0: rlm@0: #include "com_aurellem_audioPlay_WavCaptureMaybe.h" rlm@0: rlm@0: JNIEXPORT void JNICALL Java_com_aurellem_audioPlay_WavCaptureMaybe_nrecord_1whatever rlm@0: (JNIEnv *env, jclass clazz){ rlm@0: UNUSED(env);UNUSED(clazz); rlm@0: printf("record_aurellem_whatever!"); rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: //////////////////////////// Real JNI stuff //////////////////////////////// rlm@0: void getMainSamples(ALCvoid *buffer){ rlm@0: UNUSED(buffer); rlm@0: // memcpy(mainBuffer, (ALubyte*) buffer, samples); rlm@0: } rlm@0: rlm@0: void getAuxSamples(ALCvoid *buffer){ rlm@0: UNUSED(buffer); rlm@0: // memcpy(auxBuffer, (ALubyte*) buffer, samples); rlm@0: } rlm@0: rlm@0: #include "com_jme3_capture_RecordAudioRenderer.h" rlm@0: rlm@0: /* rlm@0: * Class: com_jme3_capture_RecordAudioRenderer rlm@0: * Method: helloEveryone rlm@0: * Signature: ()V rlm@0: */ rlm@0: JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_helloEveryone rlm@0: (JNIEnv *env, jclass clazz){ rlm@0: UNUSED(env);UNUSED(clazz); rlm@0: printf("\n**************\nC from Java: I'm audioRecorder :)\n***********\n"); rlm@0: } rlm@0: rlm@0: rlm@0: /* rlm@0: * Class: com_jme3_capture_RecordAudioRenderer rlm@0: * Method: nstep rlm@0: * Signature: ()V rlm@0: */ rlm@0: JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_nstep rlm@0: (JNIEnv *env, jclass clazz, jlong device){ rlm@0: UNUSED(env);UNUSED(clazz);UNUSED(device); rlm@0: //printf("C from Java: I'm audioRecorder -- nstep :)\n"); rlm@0: RecordProc((ALCdevice*)((intptr_t)device)); rlm@0: } rlm@0: rlm@0: /* rlm@0: * Class: com_jme3_capture_RecordAudioRenderer rlm@0: * Method: ngetMainSamples rlm@0: * Signature: (JLjava/nio/ByteBuffer;I)V rlm@0: */ rlm@0: JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_ngetMainSamples rlm@0: (JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position){ rlm@0: UNUSED(clazz); rlm@0: rlm@0: ALvoid *buffer_address = rlm@0: ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); rlm@0: ALCdevice *recorder = (ALCdevice*) ((intptr_t)device); rlm@0: //printf("getMainSamples: device is %p\n", recorder); rlm@0: record_data *data = (record_data*)recorder->ExtraData; rlm@0: if (!data->mainFull){ rlm@0: printf("data is not ready!\n"); rlm@0: return; rlm@0: } rlm@0: memcpy(buffer_address, data->mainBuffer, data->size); rlm@0: data->mainFull = AL_FALSE; rlm@0: } rlm@0: rlm@0: /* rlm@0: * Class: com_jme3_capture_RecordAudioRenderer rlm@0: * Method: ngetAuxSamples rlm@0: * Signature: (JLjava/nio/ByteBuffer;I)V rlm@0: */ rlm@0: JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_ngetAuxSamples rlm@0: (JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position){ rlm@0: UNUSED(clazz); rlm@0: rlm@0: ALvoid *buffer_address = rlm@0: ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); rlm@0: ALCdevice *recorder = (ALCdevice*) ((intptr_t)device); rlm@0: //printf("getMainSamples: device is %p\n", recorder); rlm@0: record_data *data = (record_data*)recorder->ExtraData; rlm@0: rlm@0: memcpy(buffer_address, data->auxBuffer, data->size); rlm@0: rlm@0: } rlm@0: rlm@0: rlm@0: /* rlm@0: * Class: com_jme3_capture_RecordAudioRenderer rlm@0: * Method: nsetAuxListener3f rlm@0: * Signature: (IFFF)V rlm@0: */ rlm@0: JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_nsetAuxListener3f rlm@0: (JNIEnv *env, jclass clazz, jint pname, jfloat v1, jfloat v2, jfloat v3){ rlm@0: UNUSED(env);UNUSED(clazz); rlm@0: aux_alListener3f(pname, v1, v2, v3); rlm@0: } rlm@0: rlm@0: /* rlm@0: * Class: com_jme3_capture_RecordAudioRenderer rlm@0: * Method: nsetAuxListenerf rlm@0: * Signature: (IF)V rlm@0: */ rlm@0: JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_nsetAuxListenerf rlm@0: (JNIEnv *env, jclass clazz, jint pname, jfloat v1){ rlm@0: UNUSED(env);UNUSED(clazz); rlm@0: aux_alListenerf(pname, v1); rlm@0: } rlm@0: rlm@0: rlm@0: rlm@0: /* rlm@0: static void JNICALL Java_org_lwjgl_openal_ALC11_nalcCaptureSamples rlm@0: (JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position, jint samples) { rlm@0: ALvoid *buffer_address = rlm@0: ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); rlm@0: alcCaptureSamples((ALCdevice*) ((intptr_t)device), buffer_address, samples); rlm@0: } rlm@0: */ rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: rlm@0: