diff options
-rw-r--r-- | Alc/alcEcho.c | 51 | ||||
-rw-r--r-- | Alc/alcReverb.c | 102 | ||||
-rw-r--r-- | OpenAL32/Include/alAuxEffectSlot.h | 2 | ||||
-rw-r--r-- | OpenAL32/alAuxEffectSlot.c | 7 |
4 files changed, 76 insertions, 86 deletions
diff --git a/Alc/alcEcho.c b/Alc/alcEcho.c index 8aa4d2ce..6601051d 100644 --- a/Alc/alcEcho.c +++ b/Alc/alcEcho.c @@ -85,32 +85,41 @@ ALvoid EchoDestroy(ALeffectState *effect) } } -ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect) +ALboolean EchoDeviceUpdate(ALeffectState *effect, ALCdevice *Device) { ALechoState *state = (ALechoState*)effect; - ALfloat lrpan, cw, a, g; ALuint maxlen; - maxlen = (ALuint)(AL_ECHO_MAX_DELAY * Context->Frequency); - maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Context->Frequency); + // Use the next power of 2 for the buffer length, so the tap offsets can be + // wrapped using a mask instead of a modulo + maxlen = (ALuint)(AL_ECHO_MAX_DELAY * Device->Frequency); + maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Device->Frequency); maxlen = NextPowerOf2(maxlen+1); - if(maxlen > state->BufferLength) + if(maxlen != state->BufferLength) { void *temp; ALuint i; - state->BufferLength = maxlen; - temp = realloc(state->SampleBuffer, state->BufferLength * sizeof(ALfloat)); + temp = realloc(state->SampleBuffer, maxlen * sizeof(ALfloat)); if(!temp) { - AL_PRINT("Failed reallocation!"); - abort(); + alSetError(AL_OUT_OF_MEMORY); + return AL_FALSE; } + state->BufferLength = maxlen; for(i = 0;i < state->BufferLength;i++) state->SampleBuffer[i] = 0.0f; } + return AL_TRUE; +} + +ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect) +{ + ALechoState *state = (ALechoState*)effect; + ALfloat lrpan, cw, a, g; + state->Tap[0].delay = (ALuint)(Effect->Echo.Delay * Context->Frequency); state->Tap[1].delay = (ALuint)(Effect->Echo.LRDelay * Context->Frequency); state->Tap[1].delay += state->Tap[0].delay; @@ -173,7 +182,6 @@ ALvoid EchoProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint Sampl ALeffectState *EchoCreate(void) { ALechoState *state; - ALuint i, maxlen; state = malloc(sizeof(*state)); if(!state) @@ -183,25 +191,12 @@ ALeffectState *EchoCreate(void) } state->state.Destroy = EchoDestroy; + state->state.DeviceUpdate = EchoDeviceUpdate; state->state.Update = EchoUpdate; state->state.Process = EchoProcess; - maxlen = (ALuint)(AL_ECHO_MAX_DELAY * MAX_ECHO_FREQ); - maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * MAX_ECHO_FREQ); - - // Use the next power of 2 for the buffer length, so the tap offsets can be - // wrapped using a mask instead of a modulo - state->BufferLength = NextPowerOf2(maxlen+1); - state->SampleBuffer = malloc(state->BufferLength * sizeof(ALfloat)); - if(!state->SampleBuffer) - { - free(state); - alSetError(AL_OUT_OF_MEMORY); - return NULL; - } - - for(i = 0;i < state->BufferLength;i++) - state->SampleBuffer[i] = 0.0f; + state->BufferLength = 0; + state->SampleBuffer = NULL; state->Tap[0].delay = 0; state->Tap[1].delay = 0; @@ -209,9 +204,9 @@ ALeffectState *EchoCreate(void) state->GainL = 0.0f; state->GainR = 0.0f; - for(i = 0;i < 2;i++) - state->iirFilter.history[i] = 0.0f; state->iirFilter.coeff = 0.0f; + state->iirFilter.history[0] = 0.0f; + state->iirFilter.history[1] = 0.0f; return &state->state; } diff --git a/Alc/alcReverb.c b/Alc/alcReverb.c index f0d9e0be..4126b3e4 100644 --- a/Alc/alcReverb.c +++ b/Alc/alcReverb.c @@ -31,10 +31,6 @@ #include "alError.h" #include "alu.h" -// Just a soft maximum. Being higher will cause VerbUpdate to reallocate the -// sample buffer which may cause an abort if realloc fails -#define MAX_REVERB_FREQ 192000 - typedef struct DelayLine { // The delay lines use sample lengths that are powers of 2 to allow @@ -412,65 +408,76 @@ static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im) return pos%LUT_NUM; } -// This updates the reverb state. This is called any time the reverb effect -// is loaded into a slot. -ALvoid VerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect) +// This updates the device-dependant reverb state. This is called on +// initialization and any time the device parameters (eg. playback frequency, +// format) have been changed. +ALboolean VerbDeviceUpdate(ALeffectState *effect, ALCdevice *Device) { ALverbState *State = (ALverbState*)effect; + ALuint length[13], totalLength; ALuint index; - ALfloat length, mixCoeff, cw, g, coeff; - ALfloat hfRatio = Effect->Reverb.DecayHFRatio; - ALuint lengths[13], totalLength; - totalLength = CalcLengths(lengths, Context->Frequency); - if(totalLength > State->TotalLength) + totalLength = CalcLengths(length, Device->Frequency); + if(totalLength != State->TotalLength) { void *temp; - State->TotalLength = totalLength; - temp = realloc(State->SampleBuffer, State->TotalLength * sizeof(ALfloat)); + temp = realloc(State->SampleBuffer, totalLength * sizeof(ALfloat)); if(!temp) { - AL_PRINT("Failed reallocation!"); - abort(); + alSetError(AL_OUT_OF_MEMORY); + return AL_FALSE; } + State->TotalLength = totalLength; State->SampleBuffer = temp; for(index = 0; index < totalLength;index++) State->SampleBuffer[index] = 0.0f; // All lines share a single sample buffer - State->Delay.Mask = lengths[0] - 1; + State->Delay.Mask = length[0] - 1; State->Delay.Line = &State->SampleBuffer[0]; - totalLength = lengths[0]; + totalLength = length[0]; for(index = 0;index < 4;index++) { - State->Early.Delay[index].Mask = lengths[1 + index] - 1; + State->Early.Delay[index].Mask = length[1 + index] - 1; State->Early.Delay[index].Line = &State->SampleBuffer[totalLength]; - totalLength += lengths[1 + index]; + totalLength += length[1 + index]; } for(index = 0;index < 4;index++) { - State->Late.ApDelay[index].Mask = lengths[5 + index] - 1; + State->Late.ApDelay[index].Mask = length[5 + index] - 1; State->Late.ApDelay[index].Line = &State->SampleBuffer[totalLength]; - totalLength += lengths[5 + index]; + totalLength += length[5 + index]; } for(index = 0;index < 4;index++) { - State->Late.Delay[index].Mask = lengths[9 + index] - 1; + State->Late.Delay[index].Mask = length[9 + index] - 1; State->Late.Delay[index].Line = &State->SampleBuffer[totalLength]; - totalLength += lengths[9 + index]; + totalLength += length[9 + index]; } } for(index = 0;index < 4;index++) { State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] * - Context->Frequency); + Device->Frequency); State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] * - Context->Frequency); + Device->Frequency); } + return AL_TRUE; +} + +// This updates the reverb state. This is called any time the reverb effect +// is loaded into a slot. +ALvoid VerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect) +{ + ALverbState *State = (ALverbState*)effect; + ALuint index; + ALfloat length, mixCoeff, cw, g, coeff; + ALfloat hfRatio = Effect->Reverb.DecayHFRatio; + // Calculate the master low-pass filter (from the master effect HF gain). cw = cos(2.0 * M_PI * Effect->Reverb.HFReference / Context->Frequency); g = __max(Effect->Reverb.GainHF, 0.0001f); @@ -757,7 +764,7 @@ ALvoid EAXVerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint Sa ALeffectState *VerbCreate(void) { ALverbState *State = NULL; - ALuint length[13], totalLength, index; + ALuint index; State = malloc(sizeof(ALverbState)); if(!State) @@ -767,28 +774,18 @@ ALeffectState *VerbCreate(void) } State->state.Destroy = VerbDestroy; + State->state.DeviceUpdate = VerbDeviceUpdate; State->state.Update = VerbUpdate; State->state.Process = VerbProcess; - totalLength = CalcLengths(length, MAX_REVERB_FREQ); - - State->TotalLength = totalLength; - State->SampleBuffer = malloc(State->TotalLength * sizeof(ALfloat)); - if(!State->SampleBuffer) - { - free(State); - alSetError(AL_OUT_OF_MEMORY); - return NULL; - } - for(index = 0; index < totalLength;index++) - State->SampleBuffer[index] = 0.0f; + State->TotalLength = 0; + State->SampleBuffer = NULL; State->LpFilter.coeff = 0.0f; State->LpFilter.history[0] = 0.0f; State->LpFilter.history[1] = 0.0f; - State->Delay.Mask = length[0] - 1; - State->Delay.Line = &State->SampleBuffer[0]; - totalLength = length[0]; + State->Delay.Mask = 0; + State->Delay.Line = NULL; State->Tap[0] = 0; State->Tap[1] = 0; @@ -800,10 +797,8 @@ ALeffectState *VerbCreate(void) for(index = 0;index < 4;index++) { State->Early.Coeff[index] = 0.0f; - State->Early.Delay[index].Mask = length[1 + index] - 1; - State->Early.Delay[index].Line = &State->SampleBuffer[totalLength]; - totalLength += length[1 + index]; - + State->Early.Delay[index].Mask = 0; + State->Early.Delay[index].Line = NULL; State->Early.Offset[index] = 0; } @@ -815,20 +810,13 @@ ALeffectState *VerbCreate(void) for(index = 0;index < 4;index++) { State->Late.ApCoeff[index] = 0.0f; - State->Late.ApDelay[index].Mask = length[5 + index] - 1; - State->Late.ApDelay[index].Line = &State->SampleBuffer[totalLength]; - totalLength += length[5 + index]; - + State->Late.ApDelay[index].Mask = 0; + State->Late.ApDelay[index].Line = NULL; State->Late.ApOffset[index] = 0; - } - for(index = 0;index < 4;index++) - { State->Late.Coeff[index] = 0.0f; - State->Late.Delay[index].Mask = length[9 + index] - 1; - State->Late.Delay[index].Line = &State->SampleBuffer[totalLength]; - totalLength += length[9 + index]; - + State->Late.Delay[index].Mask = 0; + State->Late.Delay[index].Line = NULL; State->Late.Offset[index] = 0; State->Late.LpCoeff[index] = 0.0f; diff --git a/OpenAL32/Include/alAuxEffectSlot.h b/OpenAL32/Include/alAuxEffectSlot.h index 667d74dd..14e3b2f9 100644 --- a/OpenAL32/Include/alAuxEffectSlot.h +++ b/OpenAL32/Include/alAuxEffectSlot.h @@ -55,6 +55,7 @@ ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context); struct ALeffectState { ALvoid (*Destroy)(ALeffectState *State); + ALboolean (*DeviceUpdate)(ALeffectState *State, ALCdevice *Device); ALvoid (*Update)(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect); ALvoid (*Process)(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS]); }; @@ -64,6 +65,7 @@ ALeffectState *VerbCreate(void); ALeffectState *EchoCreate(void); #define ALEffect_Destroy(a) ((a)->Destroy((a))) +#define ALEffect_DeviceUpdate(a,b) ((a)->DeviceUpdate((a),(b))) #define ALEffect_Update(a,b,c) ((a)->Update((a),(b),(c))) #define ALEffect_Process(a,b,c,d,e) ((a)->Process((a),(b),(c),(d),(e))) diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c index 1fd2f707..7a9c6326 100644 --- a/OpenAL32/alAuxEffectSlot.c +++ b/OpenAL32/alAuxEffectSlot.c @@ -428,8 +428,13 @@ static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, else if(effect->type == AL_EFFECT_ECHO) NewState = EchoCreate(); /* No new state? An error occured.. */ - if(!NewState) + if(NewState == NULL || + ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE) + { + if(NewState) + ALEffect_Destroy(NewState); return; + } } if(ALEffectSlot->EffectState) ALEffect_Destroy(ALEffectSlot->EffectState); |