aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2009-10-20 08:31:44 -0700
committerChris Robinson <[email protected]>2009-10-20 08:31:44 -0700
commitf14cf8289eae832b090c4067ae66a19be08b7029 (patch)
tree72429089a328f49f494f9234bad41cf23d99a534
parent790aa686214559377c4ec398762c1e7cd655f8a5 (diff)
Add a method to update device-dependant effect parameters.
The effect state's update method will be called afterwards
-rw-r--r--Alc/alcEcho.c51
-rw-r--r--Alc/alcReverb.c102
-rw-r--r--OpenAL32/Include/alAuxEffectSlot.h2
-rw-r--r--OpenAL32/alAuxEffectSlot.c7
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);