Add a method to update device-dependant effect parameters.
The effect state's update method will be called afterwards
This commit is contained in:
parent
790aa68621
commit
f14cf8289e
@ -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;
|
ALechoState *state = (ALechoState*)effect;
|
||||||
ALfloat lrpan, cw, a, g;
|
|
||||||
ALuint maxlen;
|
ALuint maxlen;
|
||||||
|
|
||||||
maxlen = (ALuint)(AL_ECHO_MAX_DELAY * Context->Frequency);
|
// Use the next power of 2 for the buffer length, so the tap offsets can be
|
||||||
maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Context->Frequency);
|
// 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);
|
maxlen = NextPowerOf2(maxlen+1);
|
||||||
|
|
||||||
if(maxlen > state->BufferLength)
|
if(maxlen != state->BufferLength)
|
||||||
{
|
{
|
||||||
void *temp;
|
void *temp;
|
||||||
ALuint i;
|
ALuint i;
|
||||||
|
|
||||||
state->BufferLength = maxlen;
|
temp = realloc(state->SampleBuffer, maxlen * sizeof(ALfloat));
|
||||||
temp = realloc(state->SampleBuffer, state->BufferLength * sizeof(ALfloat));
|
|
||||||
if(!temp)
|
if(!temp)
|
||||||
{
|
{
|
||||||
AL_PRINT("Failed reallocation!");
|
alSetError(AL_OUT_OF_MEMORY);
|
||||||
abort();
|
return AL_FALSE;
|
||||||
}
|
}
|
||||||
|
state->BufferLength = maxlen;
|
||||||
for(i = 0;i < state->BufferLength;i++)
|
for(i = 0;i < state->BufferLength;i++)
|
||||||
state->SampleBuffer[i] = 0.0f;
|
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[0].delay = (ALuint)(Effect->Echo.Delay * Context->Frequency);
|
||||||
state->Tap[1].delay = (ALuint)(Effect->Echo.LRDelay * Context->Frequency);
|
state->Tap[1].delay = (ALuint)(Effect->Echo.LRDelay * Context->Frequency);
|
||||||
state->Tap[1].delay += state->Tap[0].delay;
|
state->Tap[1].delay += state->Tap[0].delay;
|
||||||
@ -173,7 +182,6 @@ ALvoid EchoProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint Sampl
|
|||||||
ALeffectState *EchoCreate(void)
|
ALeffectState *EchoCreate(void)
|
||||||
{
|
{
|
||||||
ALechoState *state;
|
ALechoState *state;
|
||||||
ALuint i, maxlen;
|
|
||||||
|
|
||||||
state = malloc(sizeof(*state));
|
state = malloc(sizeof(*state));
|
||||||
if(!state)
|
if(!state)
|
||||||
@ -183,25 +191,12 @@ ALeffectState *EchoCreate(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
state->state.Destroy = EchoDestroy;
|
state->state.Destroy = EchoDestroy;
|
||||||
|
state->state.DeviceUpdate = EchoDeviceUpdate;
|
||||||
state->state.Update = EchoUpdate;
|
state->state.Update = EchoUpdate;
|
||||||
state->state.Process = EchoProcess;
|
state->state.Process = EchoProcess;
|
||||||
|
|
||||||
maxlen = (ALuint)(AL_ECHO_MAX_DELAY * MAX_ECHO_FREQ);
|
state->BufferLength = 0;
|
||||||
maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * MAX_ECHO_FREQ);
|
state->SampleBuffer = NULL;
|
||||||
|
|
||||||
// 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->Tap[0].delay = 0;
|
state->Tap[0].delay = 0;
|
||||||
state->Tap[1].delay = 0;
|
state->Tap[1].delay = 0;
|
||||||
@ -209,9 +204,9 @@ ALeffectState *EchoCreate(void)
|
|||||||
state->GainL = 0.0f;
|
state->GainL = 0.0f;
|
||||||
state->GainR = 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.coeff = 0.0f;
|
||||||
|
state->iirFilter.history[0] = 0.0f;
|
||||||
|
state->iirFilter.history[1] = 0.0f;
|
||||||
|
|
||||||
return &state->state;
|
return &state->state;
|
||||||
}
|
}
|
||||||
|
158
Alc/alcReverb.c
158
Alc/alcReverb.c
@ -31,10 +31,6 @@
|
|||||||
#include "alError.h"
|
#include "alError.h"
|
||||||
#include "alu.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
|
typedef struct DelayLine
|
||||||
{
|
{
|
||||||
// The delay lines use sample lengths that are powers of 2 to allow
|
// The delay lines use sample lengths that are powers of 2 to allow
|
||||||
@ -412,6 +408,67 @@ static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im)
|
|||||||
return pos%LUT_NUM;
|
return pos%LUT_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
totalLength = CalcLengths(length, Device->Frequency);
|
||||||
|
if(totalLength != State->TotalLength)
|
||||||
|
{
|
||||||
|
void *temp;
|
||||||
|
|
||||||
|
temp = realloc(State->SampleBuffer, totalLength * sizeof(ALfloat));
|
||||||
|
if(!temp)
|
||||||
|
{
|
||||||
|
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 = length[0] - 1;
|
||||||
|
State->Delay.Line = &State->SampleBuffer[0];
|
||||||
|
totalLength = length[0];
|
||||||
|
for(index = 0;index < 4;index++)
|
||||||
|
{
|
||||||
|
State->Early.Delay[index].Mask = length[1 + index] - 1;
|
||||||
|
State->Early.Delay[index].Line = &State->SampleBuffer[totalLength];
|
||||||
|
totalLength += length[1 + index];
|
||||||
|
}
|
||||||
|
for(index = 0;index < 4;index++)
|
||||||
|
{
|
||||||
|
State->Late.ApDelay[index].Mask = length[5 + index] - 1;
|
||||||
|
State->Late.ApDelay[index].Line = &State->SampleBuffer[totalLength];
|
||||||
|
totalLength += length[5 + index];
|
||||||
|
}
|
||||||
|
for(index = 0;index < 4;index++)
|
||||||
|
{
|
||||||
|
State->Late.Delay[index].Mask = length[9 + index] - 1;
|
||||||
|
State->Late.Delay[index].Line = &State->SampleBuffer[totalLength];
|
||||||
|
totalLength += length[9 + index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(index = 0;index < 4;index++)
|
||||||
|
{
|
||||||
|
State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] *
|
||||||
|
Device->Frequency);
|
||||||
|
State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] *
|
||||||
|
Device->Frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
return AL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// This updates the reverb state. This is called any time the reverb effect
|
// This updates the reverb state. This is called any time the reverb effect
|
||||||
// is loaded into a slot.
|
// is loaded into a slot.
|
||||||
ALvoid VerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
|
ALvoid VerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
|
||||||
@ -420,56 +477,6 @@ ALvoid VerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Ef
|
|||||||
ALuint index;
|
ALuint index;
|
||||||
ALfloat length, mixCoeff, cw, g, coeff;
|
ALfloat length, mixCoeff, cw, g, coeff;
|
||||||
ALfloat hfRatio = Effect->Reverb.DecayHFRatio;
|
ALfloat hfRatio = Effect->Reverb.DecayHFRatio;
|
||||||
ALuint lengths[13], totalLength;
|
|
||||||
|
|
||||||
totalLength = CalcLengths(lengths, Context->Frequency);
|
|
||||||
if(totalLength > State->TotalLength)
|
|
||||||
{
|
|
||||||
void *temp;
|
|
||||||
|
|
||||||
State->TotalLength = totalLength;
|
|
||||||
temp = realloc(State->SampleBuffer, State->TotalLength * sizeof(ALfloat));
|
|
||||||
if(!temp)
|
|
||||||
{
|
|
||||||
AL_PRINT("Failed reallocation!");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
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.Line = &State->SampleBuffer[0];
|
|
||||||
totalLength = lengths[0];
|
|
||||||
for(index = 0;index < 4;index++)
|
|
||||||
{
|
|
||||||
State->Early.Delay[index].Mask = lengths[1 + index] - 1;
|
|
||||||
State->Early.Delay[index].Line = &State->SampleBuffer[totalLength];
|
|
||||||
totalLength += lengths[1 + index];
|
|
||||||
}
|
|
||||||
for(index = 0;index < 4;index++)
|
|
||||||
{
|
|
||||||
State->Late.ApDelay[index].Mask = lengths[5 + index] - 1;
|
|
||||||
State->Late.ApDelay[index].Line = &State->SampleBuffer[totalLength];
|
|
||||||
totalLength += lengths[5 + index];
|
|
||||||
}
|
|
||||||
for(index = 0;index < 4;index++)
|
|
||||||
{
|
|
||||||
State->Late.Delay[index].Mask = lengths[9 + index] - 1;
|
|
||||||
State->Late.Delay[index].Line = &State->SampleBuffer[totalLength];
|
|
||||||
totalLength += lengths[9 + index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(index = 0;index < 4;index++)
|
|
||||||
{
|
|
||||||
State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] *
|
|
||||||
Context->Frequency);
|
|
||||||
State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] *
|
|
||||||
Context->Frequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the master low-pass filter (from the master effect HF gain).
|
// Calculate the master low-pass filter (from the master effect HF gain).
|
||||||
cw = cos(2.0 * M_PI * Effect->Reverb.HFReference / Context->Frequency);
|
cw = cos(2.0 * M_PI * Effect->Reverb.HFReference / Context->Frequency);
|
||||||
@ -757,7 +764,7 @@ ALvoid EAXVerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint Sa
|
|||||||
ALeffectState *VerbCreate(void)
|
ALeffectState *VerbCreate(void)
|
||||||
{
|
{
|
||||||
ALverbState *State = NULL;
|
ALverbState *State = NULL;
|
||||||
ALuint length[13], totalLength, index;
|
ALuint index;
|
||||||
|
|
||||||
State = malloc(sizeof(ALverbState));
|
State = malloc(sizeof(ALverbState));
|
||||||
if(!State)
|
if(!State)
|
||||||
@ -767,28 +774,18 @@ ALeffectState *VerbCreate(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
State->state.Destroy = VerbDestroy;
|
State->state.Destroy = VerbDestroy;
|
||||||
|
State->state.DeviceUpdate = VerbDeviceUpdate;
|
||||||
State->state.Update = VerbUpdate;
|
State->state.Update = VerbUpdate;
|
||||||
State->state.Process = VerbProcess;
|
State->state.Process = VerbProcess;
|
||||||
|
|
||||||
totalLength = CalcLengths(length, MAX_REVERB_FREQ);
|
State->TotalLength = 0;
|
||||||
|
State->SampleBuffer = NULL;
|
||||||
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->LpFilter.coeff = 0.0f;
|
State->LpFilter.coeff = 0.0f;
|
||||||
State->LpFilter.history[0] = 0.0f;
|
State->LpFilter.history[0] = 0.0f;
|
||||||
State->LpFilter.history[1] = 0.0f;
|
State->LpFilter.history[1] = 0.0f;
|
||||||
State->Delay.Mask = length[0] - 1;
|
State->Delay.Mask = 0;
|
||||||
State->Delay.Line = &State->SampleBuffer[0];
|
State->Delay.Line = NULL;
|
||||||
totalLength = length[0];
|
|
||||||
|
|
||||||
State->Tap[0] = 0;
|
State->Tap[0] = 0;
|
||||||
State->Tap[1] = 0;
|
State->Tap[1] = 0;
|
||||||
@ -800,10 +797,8 @@ ALeffectState *VerbCreate(void)
|
|||||||
for(index = 0;index < 4;index++)
|
for(index = 0;index < 4;index++)
|
||||||
{
|
{
|
||||||
State->Early.Coeff[index] = 0.0f;
|
State->Early.Coeff[index] = 0.0f;
|
||||||
State->Early.Delay[index].Mask = length[1 + index] - 1;
|
State->Early.Delay[index].Mask = 0;
|
||||||
State->Early.Delay[index].Line = &State->SampleBuffer[totalLength];
|
State->Early.Delay[index].Line = NULL;
|
||||||
totalLength += length[1 + index];
|
|
||||||
|
|
||||||
State->Early.Offset[index] = 0;
|
State->Early.Offset[index] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,20 +810,13 @@ ALeffectState *VerbCreate(void)
|
|||||||
for(index = 0;index < 4;index++)
|
for(index = 0;index < 4;index++)
|
||||||
{
|
{
|
||||||
State->Late.ApCoeff[index] = 0.0f;
|
State->Late.ApCoeff[index] = 0.0f;
|
||||||
State->Late.ApDelay[index].Mask = length[5 + index] - 1;
|
State->Late.ApDelay[index].Mask = 0;
|
||||||
State->Late.ApDelay[index].Line = &State->SampleBuffer[totalLength];
|
State->Late.ApDelay[index].Line = NULL;
|
||||||
totalLength += length[5 + index];
|
|
||||||
|
|
||||||
State->Late.ApOffset[index] = 0;
|
State->Late.ApOffset[index] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
for(index = 0;index < 4;index++)
|
|
||||||
{
|
|
||||||
State->Late.Coeff[index] = 0.0f;
|
State->Late.Coeff[index] = 0.0f;
|
||||||
State->Late.Delay[index].Mask = length[9 + index] - 1;
|
State->Late.Delay[index].Mask = 0;
|
||||||
State->Late.Delay[index].Line = &State->SampleBuffer[totalLength];
|
State->Late.Delay[index].Line = NULL;
|
||||||
totalLength += length[9 + index];
|
|
||||||
|
|
||||||
State->Late.Offset[index] = 0;
|
State->Late.Offset[index] = 0;
|
||||||
|
|
||||||
State->Late.LpCoeff[index] = 0.0f;
|
State->Late.LpCoeff[index] = 0.0f;
|
||||||
|
@ -55,6 +55,7 @@ ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
|
|||||||
|
|
||||||
struct ALeffectState {
|
struct ALeffectState {
|
||||||
ALvoid (*Destroy)(ALeffectState *State);
|
ALvoid (*Destroy)(ALeffectState *State);
|
||||||
|
ALboolean (*DeviceUpdate)(ALeffectState *State, ALCdevice *Device);
|
||||||
ALvoid (*Update)(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect);
|
ALvoid (*Update)(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect);
|
||||||
ALvoid (*Process)(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS]);
|
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);
|
ALeffectState *EchoCreate(void);
|
||||||
|
|
||||||
#define ALEffect_Destroy(a) ((a)->Destroy((a)))
|
#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_Update(a,b,c) ((a)->Update((a),(b),(c)))
|
||||||
#define ALEffect_Process(a,b,c,d,e) ((a)->Process((a),(b),(c),(d),(e)))
|
#define ALEffect_Process(a,b,c,d,e) ((a)->Process((a),(b),(c),(d),(e)))
|
||||||
|
|
||||||
|
@ -428,8 +428,13 @@ static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot,
|
|||||||
else if(effect->type == AL_EFFECT_ECHO)
|
else if(effect->type == AL_EFFECT_ECHO)
|
||||||
NewState = EchoCreate();
|
NewState = EchoCreate();
|
||||||
/* No new state? An error occured.. */
|
/* No new state? An error occured.. */
|
||||||
if(!NewState)
|
if(NewState == NULL ||
|
||||||
|
ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
|
||||||
|
{
|
||||||
|
if(NewState)
|
||||||
|
ALEffect_Destroy(NewState);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(ALEffectSlot->EffectState)
|
if(ALEffectSlot->EffectState)
|
||||||
ALEffect_Destroy(ALEffectSlot->EffectState);
|
ALEffect_Destroy(ALEffectSlot->EffectState);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user