aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2009-05-29 01:32:54 -0700
committerChris Robinson <[email protected]>2009-05-29 01:32:54 -0700
commit34ea7eba9e5f750aaa18713c51da852555064d39 (patch)
treefbb4a356a02fbe508fc241ac3b31a62d5dd841d4
parent6d3ba44f55772cc6a545ca2c9407833ed85233f6 (diff)
Add preliminary support for the EAX Reverb effect
Not all parameters are supported yet, though it is a little more fuctional than standard reverb
-rw-r--r--Alc/ALc.c1
-rw-r--r--Alc/ALu.c25
-rw-r--r--Alc/alcReverb.c308
-rw-r--r--OpenAL32/Include/alEffect.h150
-rw-r--r--OpenAL32/Include/alReverb.h2
-rw-r--r--OpenAL32/alAuxEffectSlot.c27
-rw-r--r--OpenAL32/alEffect.c422
-rw-r--r--alsoftrc.sample2
8 files changed, 810 insertions, 127 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index d04b0a05..905ac6e8 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -322,6 +322,7 @@ static void InitAL(void)
const char *name;
int type;
} EffectList[] = {
+ { "eaxreverb", EAXREVERB },
{ "reverb", REVERB },
{ "echo", ECHO },
{ NULL, 0 }
diff --git a/Alc/ALu.c b/Alc/ALu.c
index f00fdafa..b36e7018 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -743,11 +743,6 @@ static ALvoid CalcSourceParams(const ALCcontext *ALContext,
wetgainhf[i] = DryGainHF;
}
- // Note that this is really applied by the effect slot. However,
- // it's easier (more optimal) to handle it here.
- if(ALSource->Send[i].Slot->effect.type == AL_EFFECT_REVERB)
- wetgainhf[i] *= ALSource->Send[0].Slot->effect.Reverb.GainHF;
-
switch(ALSource->Send[i].WetFilter.type)
{
case AL_FILTER_LOWPASS:
@@ -1025,9 +1020,9 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
if(ALSource->FirstStart && DataPosInt == 0 && DataPosFrac == 0)
{
for(i = 0;i < OUTPUTCHANNELS;i++)
- dryGainStep[i] = 0;
+ dryGainStep[i] = 0.0f;
for(i = 0;i < MAX_SENDS;i++)
- wetGainStep[i] = 0;
+ wetGainStep[i] = 0.0f;
}
else
{
@@ -1315,10 +1310,18 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
// effect slot processing
while(ALEffectSlot)
{
- if(ALEffectSlot->effect.type == AL_EFFECT_REVERB)
- VerbProcess(ALEffectSlot->ReverbState, SamplesToDo, ALEffectSlot->WetBuffer, DryBuffer);
- else if(ALEffectSlot->effect.type == AL_EFFECT_ECHO)
- EchoProcess(ALEffectSlot->EchoState, SamplesToDo, ALEffectSlot->WetBuffer, DryBuffer);
+ switch(ALEffectSlot->effect.type)
+ {
+ case AL_EFFECT_REVERB:
+ VerbProcess(ALEffectSlot->ReverbState, SamplesToDo, ALEffectSlot->WetBuffer, DryBuffer);
+ break;
+ case AL_EFFECT_ECHO:
+ EchoProcess(ALEffectSlot->EchoState, SamplesToDo, ALEffectSlot->WetBuffer, DryBuffer);
+ break;
+ case AL_EFFECT_EAXREVERB:
+ EAXVerbProcess(ALEffectSlot->ReverbState, SamplesToDo, ALEffectSlot->WetBuffer, DryBuffer);
+ break;
+ }
for(i = 0;i < SamplesToDo;i++)
ALEffectSlot->WetBuffer[i] = 0.0f;
diff --git a/Alc/alcReverb.c b/Alc/alcReverb.c
index 0516ab4f..85de4436 100644
--- a/Alc/alcReverb.c
+++ b/Alc/alcReverb.c
@@ -44,23 +44,26 @@ struct ALverbState
// All delay lines are allocated as a single buffer to reduce memory
// fragmentation and management code.
ALfloat *SampleBuffer;
- // Master effect gain.
- ALfloat Gain;
+ // Master effect low-pass filter (2 chained 1-pole filters).
+ ALfloat LpCoeff;
+ ALfloat LpSamples[2];
// Initial effect delay and decorrelation.
DelayLine Delay;
// The tap points for the initial delay. First tap goes to early
// reflections, the last four decorrelate to late reverb.
ALuint Tap[5];
struct {
- // Gain for early reflections.
+ // Total gain for early reflections.
ALfloat Gain;
// Early reflections are done with 4 delay lines.
ALfloat Coeff[4];
DelayLine Delay[4];
ALuint Offset[4];
+ // The gain for each output channel based on 3D panning.
+ ALfloat PanGain[OUTPUTCHANNELS];
} Early;
struct {
- // Gain for late reverb.
+ // Total gain for late reverb.
ALfloat Gain;
// Attenuation to compensate for modal density and decay rate.
ALfloat DensityGain;
@@ -76,9 +79,11 @@ struct ALverbState
ALfloat Coeff[4];
DelayLine Delay[4];
ALuint Offset[4];
- // The cyclical delay lines are low-pass filtered.
- ALfloat LpCoeff[4][2];
+ // The cyclical delay lines are 1-pole low-pass filtered.
+ ALfloat LpCoeff[4];
ALfloat LpSample[4];
+ // The gain for each output channel based on 3D panning.
+ ALfloat PanGain[OUTPUTCHANNELS];
} Late;
// The current read offset for all delay lines.
ALuint Offset;
@@ -194,13 +199,11 @@ static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *
DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]);
DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]);
- // To decorrelate the output for stereo separation, the two outputs are
- // obtained from the inner delay lines.
- // Output is instant by using the inputs to them instead of taking the
- // result of the two delay lines directly (f[0] and f[3] instead of d[1]
- // and d[2]).
+ // Output the results of the junction for all four lines.
out[0] = State->Early.Gain * f[0];
- out[1] = State->Early.Gain * f[3];
+ out[1] = State->Early.Gain * f[1];
+ out[2] = State->Early.Gain * f[2];
+ out[3] = State->Early.Gain * f[3];
}
// All-pass input/output routine for late reverb.
@@ -228,8 +231,8 @@ static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
// Low-pass filter input/output routine for late reverb.
static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
{
- State->Late.LpSample[index] = (State->Late.LpCoeff[index][0] * in) +
- (State->Late.LpCoeff[index][1] * State->Late.LpSample[index]);
+ State->Late.LpSample[index] = in +
+ ((State->Late.LpSample[index] - in) * State->Late.LpCoeff[index]);
return State->Late.LpSample[index];
}
@@ -291,11 +294,13 @@ static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
f[2] = d[2] + (State->Late.MixCoeff * ( d[0] - d[1] + d[3]));
f[3] = d[3] + (State->Late.MixCoeff * (-d[0] - d[1] - d[2]));
- // Output is tapped at the input to the shortest two cyclical delay
- // lines, attenuated by the late reverb gain (which is attenuated by the
- // mixing coefficient x).
+ // Output the results of the matrix for all four cyclical delay lines,
+ // attenuated by the late reverb gain (which is attenuated by the 'x'
+ // mix coefficient).
out[0] = State->Late.Gain * f[0];
out[1] = State->Late.Gain * f[1];
+ out[2] = State->Late.Gain * f[2];
+ out[3] = State->Late.Gain * f[3];
// The delay lines are fed circularly in the order:
// 0 -> 1 -> 3 -> 2 -> 0 ...
@@ -305,6 +310,36 @@ static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
DelayLineIn(&State->Late.Delay[3], State->Offset, f[1]);
}
+// Process the reverb for a given input sample, resulting in separate four-
+// channel output for both early reflections and late reverb.
+static __inline ALvoid ReverbInOut(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
+{
+ ALfloat taps[4];
+
+ // Low-pass filter the incoming sample.
+ in = in + ((State->LpSamples[0] - in) * State->LpCoeff);
+ State->LpSamples[0] = in;
+ in = in + ((State->LpSamples[1] - in) * State->LpCoeff);
+ State->LpSamples[1] = in;
+
+ // Feed the initial delay line.
+ DelayLineIn(&State->Delay, State->Offset, in);
+
+ // Calculate the early reflection from the first delay tap.
+ in = DelayLineOut(&State->Delay, State->Offset - State->Tap[0]);
+ EarlyReflection(State, in, early);
+
+ // Calculate the late reverb from the last four delay taps.
+ taps[0] = DelayLineOut(&State->Delay, State->Offset - State->Tap[1]);
+ taps[1] = DelayLineOut(&State->Delay, State->Offset - State->Tap[2]);
+ taps[2] = DelayLineOut(&State->Delay, State->Offset - State->Tap[3]);
+ taps[3] = DelayLineOut(&State->Delay, State->Offset - State->Tap[4]);
+ LateReverb(State, taps, late);
+
+ // Step all delays forward one sample.
+ State->Offset++;
+}
+
// This creates the reverb state. It should be called only when the reverb
// effect is loaded into a slot that doesn't already have a reverb effect.
ALverbState *VerbCreate(ALCcontext *Context)
@@ -349,7 +384,8 @@ ALverbState *VerbCreate(ALCcontext *Context)
totalLength += length[9 + index];
}
- // All lines share a single sample buffer.
+ // All lines share a single sample buffer and have their masks and start
+ // addresses calculated once.
State->SampleBuffer = malloc(totalLength * sizeof(ALfloat));
if(!State->SampleBuffer)
{
@@ -359,8 +395,9 @@ ALverbState *VerbCreate(ALCcontext *Context)
for(index = 0; index < totalLength;index++)
State->SampleBuffer[index] = 0.0f;
- // Each one has its mask and start address calculated one time.
- State->Gain = 0.0f;
+ State->LpCoeff = 0.0f;
+ State->LpSamples[0] = 0.0f;
+ State->LpSamples[1] = 0.0f;
State->Delay.Mask = length[0] - 1;
State->Delay.Line = &State->SampleBuffer[0];
totalLength = length[0];
@@ -410,15 +447,27 @@ ALverbState *VerbCreate(ALCcontext *Context)
State->Late.Offset[index] = 0;
- State->Late.LpCoeff[index][0] = 0.0f;
- State->Late.LpCoeff[index][1] = 0.0f;
+ State->Late.LpCoeff[index] = 0.0f;
State->Late.LpSample[index] = 0.0f;
}
+ // Panning is applied as an independent gain for each output channel.
+ for(index = 0;index < OUTPUTCHANNELS;index++)
+ {
+ State->Early.PanGain[index] = 0.0f;
+ State->Late.PanGain[index] = 0.0f;
+ }
+
State->Offset = 0;
return State;
}
+ALverbState *EAXVerbCreate(ALCcontext *Context)
+{
+ ALverbState *State = VerbCreate(Context);
+ return State;
+}
+
// This destroys the reverb state. It should be called only when the effect
// slot has a different (or no) effect loaded over the reverb effect.
ALvoid VerbDestroy(ALverbState *State)
@@ -431,17 +480,36 @@ ALvoid VerbDestroy(ALverbState *State)
}
}
+// NOTE: Temp, remove later.
+static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im)
+{
+ ALint pos = 0;
+ ALfloat denom = aluFabs(re) + aluFabs(im);
+ if(denom > 0.0f)
+ pos = (ALint)(QUADRANT_NUM*aluFabs(im) / denom + 0.5);
+
+ if(re < 0.0)
+ pos = 2 * QUADRANT_NUM - pos;
+ if(im < 0.0)
+ pos = LUT_NUM - pos;
+ return pos%LUT_NUM;
+}
+
// This updates the reverb state. This is called any time the reverb effect
// is loaded into a slot.
ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
{
ALverbState *State = Slot->ReverbState;
ALuint index;
- ALfloat length, mixCoeff, cw, g, lpCoeff;
+ ALfloat length, mixCoeff, cw, g, coeff;
ALfloat hfRatio = Effect->Reverb.DecayHFRatio;
- // Calculate the master gain (from the slot and master effect gain).
- State->Gain = Slot->Gain * Effect->Reverb.Gain;
+ // 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);
+ State->LpCoeff = 0.0f;
+ if(g < 0.9999f) // 1-epsilon
+ State->LpCoeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
// Calculate the initial delay taps.
length = Effect->Reverb.ReflectionsDelay;
@@ -465,8 +533,10 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
State->Tap[1 + index] = (ALuint)(length * Context->Frequency);
}
- // Set the early reflections gain.
- State->Early.Gain = Effect->Reverb.ReflectionsGain;
+ // Calculate the early reflections gain (from the slot gain, master
+ // effect gain, and reflections gain parameters).
+ State->Early.Gain = Slot->Gain * Effect->Reverb.Gain *
+ Effect->Reverb.ReflectionsGain;
// Calculate the gain (coefficient) for each early delay line.
for(index = 0;index < 4;index++)
@@ -477,10 +547,12 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
// Calculate the first mixing matrix coefficient (x).
mixCoeff = 1.0f - (0.5f * pow(Effect->Reverb.Diffusion, 3.0f));
- // Set the late reverb gain. Since the output is tapped prior to the
- // application of the delay line coefficients, this gain needs to be
- // attenuated by the mix coefficient from above.
- State->Late.Gain = Effect->Reverb.LateReverbGain * mixCoeff;
+ // Calculate the late reverb gain (from the slot gain, master effect
+ // gain, and late reverb gain parameters). Since the output is tapped
+ // prior to the application of the delay line coefficients, this gain
+ // needs to be attenuated by the 'x' mix coefficient from above.
+ State->Late.Gain = Slot->Gain * Effect->Reverb.Gain *
+ Effect->Reverb.LateReverbGain * mixCoeff;
/* To compensate for changes in modal density and decay time of the late
* reverb signal, the input is attenuated based on the maximal energy of
@@ -501,18 +573,17 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
* for each line individually (most likely a side effect of diffusion).
*
* The final result is the square root of the ratio bound to a maximum
- * value of 1 (no amplification) and attenuated by 1 / sqrt(2) to
- * compensate for the four decorrelated inputs.
+ * value of 1 (no amplification).
*/
length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] +
LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]);
g = length * (1.0f + LATE_LINE_MULTIPLIER) * 0.25f;
g = pow(10.0f, g * -60.0f / 20.0f);
- g = 1.0f / (1.0f - (g*g));
+ g = 1.0f / (1.0f - (g * g));
length *= 1.0f + (Effect->Reverb.Density * LATE_LINE_MULTIPLIER) * 0.25f;
length = pow(10.0f, length / Effect->Reverb.DecayTime * -60.0f / 20.0f);
- length = 1.0f / (1.0f - (length*length));
- State->Late.DensityGain = 0.707106f * __min(aluSqrt(g / length), 1.0f);
+ length = 1.0f / (1.0f - (length * length));
+ State->Late.DensityGain = __min(aluSqrt(g / length), 1.0f);
// Calculate the all-pass feed-back and feed-forward coefficient.
State->Late.ApFeedCoeff = 0.6f * pow(Effect->Reverb.Diffusion, 3.0f);
@@ -552,12 +623,8 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
hfRatio = __min(hfRatio, limitRatio);
}
- // Calculate the filter frequency for low-pass or high-pass depending on
- // whether the HF ratio is above 1.
- cw = 2.0f * M_PI * LOWPASSFREQCUTOFF / Context->Frequency;
- if(hfRatio > 1.0f)
- cw = M_PI - cw;
- cw = cos(cw);
+ // Calculate the low-pass filter frequency.
+ cw = cos(2.0f * M_PI * Effect->Reverb.HFReference / Context->Frequency);
for(index = 0;index < 4;index++)
{
@@ -571,39 +638,59 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
State->Late.Coeff[index] = pow(10.0f, length / Effect->Reverb.DecayTime *
-60.0f / 20.0f);
- // Calculate the decay equation for each low-pass filter.
- g = pow(10.0f, length / (Effect->Reverb.DecayTime * hfRatio) *
- -60.0f / 20.0f);
- if (hfRatio > 1.0f)
- g = State->Late.Coeff[index] / g;
- else
- g = g / State->Late.Coeff[index];
- g = __max(g, 0.1f);
- g *= g;
-
- // Calculate the gain (coefficient) for each low-pass filter.
- lpCoeff = 0.0f;
- if(g < 0.9999f) // 1-epsilon
- lpCoeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
-
- // Very low decay times will produce minimal output, so apply an
- // upper bound to the coefficient.
- lpCoeff = __min(lpCoeff, 0.98f);
-
- // Calculate the filter coefficients for high-pass or low-pass
- // dependent on HF ratio being above 1.
- if(hfRatio > 1.0f) {
- State->Late.LpCoeff[index][0] = 1.0f + lpCoeff;
- State->Late.LpCoeff[index][1] = -lpCoeff;
- } else {
- State->Late.LpCoeff[index][0] = 1.0f - lpCoeff;
- State->Late.LpCoeff[index][1] = lpCoeff;
+ // Eventually this should boost the high frequencies when the ratio
+ // exceeds 1.
+ coeff = 0.0f;
+ if (hfRatio < 1.0f)
+ {
+ // Calculate the decay equation for each low-pass filter.
+ g = pow(10.0f, length / (Effect->Reverb.DecayTime * hfRatio) *
+ -60.0f / 20.0f) / State->Late.Coeff[index];
+ g = __max(g, 0.1f);
+ g *= g;
+
+ // Calculate the gain (coefficient) for each low-pass filter.
+ if(g < 0.9999f) // 1-epsilon
+ coeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
+
+ // Very low decay times will produce minimal output, so apply an
+ // upper bound to the coefficient.
+ coeff = __min(coeff, 0.98f);
}
+ State->Late.LpCoeff[index] = coeff;
// Attenuate the cyclical line coefficients by the mixing coefficient
// (x).
State->Late.Coeff[index] *= mixCoeff;
}
+
+ // Calculate the 3D-panning gains for the early reflections and late
+ // reverb (for EAX mode).
+ {
+ ALfloat *earlyPan = Effect->Reverb.ReflectionsPan;
+ ALfloat *latePan = Effect->Reverb.LateReverbPan;
+ ALfloat *speakerGain, dirGain, ambientGain;
+ ALint pos;
+
+ // This code applies directional reverb just like the mixer applies
+ // directional sources. It diffuses the sound toward all speakers
+ // as the magnitude of the panning vector drops, which is only an
+ // approximation of the expansion of sound across the speakers from
+ // the panning direction.
+ pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
+ speakerGain = &Context->PanningLUT[OUTPUTCHANNELS * pos];
+ dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));
+ ambientGain = 1.0 / aluSqrt(Context->NumChan) * (1.0 - dirGain);
+ for(index = 0;index < OUTPUTCHANNELS;index++)
+ State->Early.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
+
+ pos = aluCart2LUTpos(latePan[2], latePan[0]);
+ speakerGain = &Context->PanningLUT[OUTPUTCHANNELS * pos];
+ dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));
+ ambientGain = 1.0 / aluSqrt(Context->NumChan) * (1.0 - dirGain);
+ for(index = 0;index < OUTPUTCHANNELS;index++)
+ State->Late.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
+ }
}
// This processes the reverb state, given the input samples and an output
@@ -611,37 +698,70 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
ALvoid VerbProcess(ALverbState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
{
ALuint index;
- ALfloat in[4], early[2], late[2], out[2];
+ ALfloat early[4], late[4], out[4];
for(index = 0;index < SamplesToDo;index++)
{
- // Feed the initial delay line.
- DelayLineIn(&State->Delay, State->Offset, SamplesIn[index]);
-
- // Calculate the early reflection from the first delay tap.
- in[0] = DelayLineOut(&State->Delay, State->Offset - State->Tap[0]);
- EarlyReflection(State, in[0], early);
-
- // Calculate the late reverb from the last four delay taps.
- in[0] = DelayLineOut(&State->Delay, State->Offset - State->Tap[1]);
- in[1] = DelayLineOut(&State->Delay, State->Offset - State->Tap[2]);
- in[2] = DelayLineOut(&State->Delay, State->Offset - State->Tap[3]);
- in[3] = DelayLineOut(&State->Delay, State->Offset - State->Tap[4]);
- LateReverb(State, in, late);
+ // Process reverb for this sample.
+ ReverbInOut(State, SamplesIn[index], early, late);
// Mix early reflections and late reverb.
- out[0] = State->Gain * (early[0] + late[0]);
- out[1] = State->Gain * (early[1] + late[1]);
-
- // Step all delays forward one sample.
- State->Offset++;
+ out[0] = early[0] + late[0];
+ out[1] = early[1] + late[1];
+ out[2] = early[2] + late[2];
+ out[3] = early[3] + late[3];
// Output the results.
- SamplesOut[index][FRONT_LEFT] += out[0];
- SamplesOut[index][FRONT_RIGHT] += out[1];
- SamplesOut[index][SIDE_LEFT] += out[0];
- SamplesOut[index][SIDE_RIGHT] += out[1];
- SamplesOut[index][BACK_LEFT] += out[0];
- SamplesOut[index][BACK_RIGHT] += out[1];
+ SamplesOut[index][FRONT_LEFT] += out [0];
+ SamplesOut[index][FRONT_RIGHT] += out [1];
+ SamplesOut[index][FRONT_CENTER] += out [3];
+ SamplesOut[index][SIDE_LEFT] += out [0];
+ SamplesOut[index][SIDE_RIGHT] += out [1];
+ SamplesOut[index][BACK_LEFT] += out [0];
+ SamplesOut[index][BACK_RIGHT] += out [1];
+ SamplesOut[index][BACK_CENTER] += out [2];
}
}
+
+// This processes the EAX reverb state, given the input samples and an output
+// buffer.
+ALvoid EAXVerbProcess(ALverbState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
+{
+ ALuint index;
+ ALfloat early[4], late[4];
+
+ for(index = 0;index < SamplesToDo;index++)
+ {
+ // Process reverb for this sample.
+ ReverbInOut(State, SamplesIn[index], early, late);
+
+ // Unfortunately, while the number and configuration of gains for
+ // panning adjust according to OUTPUTCHANNELS, the output from the
+ // reverb engine is not so scalable.
+ SamplesOut[index][FRONT_LEFT] +=
+ (State->Early.PanGain[FRONT_LEFT] * early[0]) +
+ (State->Late.PanGain[FRONT_LEFT] * late[0]);
+ SamplesOut[index][FRONT_RIGHT] +=
+ (State->Early.PanGain[FRONT_RIGHT] * early[1]) +
+ (State->Late.PanGain[FRONT_RIGHT] * late[1]);
+ SamplesOut[index][FRONT_CENTER] +=
+ (State->Early.PanGain[FRONT_CENTER] * early[3]) +
+ (State->Late.PanGain[FRONT_CENTER] * late[3]);
+ SamplesOut[index][SIDE_LEFT] +=
+ (State->Early.PanGain[SIDE_LEFT] * early[0]) +
+ (State->Late.PanGain[SIDE_LEFT] * late[0]);
+ SamplesOut[index][SIDE_RIGHT] +=
+ (State->Early.PanGain[SIDE_RIGHT] * early[1]) +
+ (State->Late.PanGain[SIDE_RIGHT] * late[1]);
+ SamplesOut[index][BACK_LEFT] +=
+ (State->Early.PanGain[BACK_LEFT] * early[0]) +
+ (State->Late.PanGain[BACK_LEFT] * late[0]);
+ SamplesOut[index][BACK_RIGHT] +=
+ (State->Early.PanGain[BACK_RIGHT] * early[1]) +
+ (State->Late.PanGain[BACK_RIGHT] * late[1]);
+ SamplesOut[index][BACK_CENTER] +=
+ (State->Early.PanGain[BACK_CENTER] * early[2]) +
+ (State->Late.PanGain[BACK_CENTER] * late[2]);
+ }
+}
+
diff --git a/OpenAL32/Include/alEffect.h b/OpenAL32/Include/alEffect.h
index 6dd1b766..592eb541 100644
--- a/OpenAL32/Include/alEffect.h
+++ b/OpenAL32/Include/alEffect.h
@@ -1,3 +1,5 @@
+// NOTE: The effect structure is getting too large, it may be a good idea to
+// start using a union or another form of unified storage.
#ifndef _AL_EFFECT_H_
#define _AL_EFFECT_H_
@@ -22,6 +24,7 @@ extern "C" {
#define AL_EFFECT_AUTOWAH 0x000A
#define AL_EFFECT_COMPRESSOR 0x000B
#define AL_EFFECT_EQUALIZER 0x000C
+#define AL_EFFECT_EAXREVERB 0x8000
#define AL_REVERB_DENSITY 0x0001
#define AL_REVERB_DIFFUSION 0x0002
@@ -37,6 +40,46 @@ extern "C" {
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
#define AL_REVERB_DECAY_HFLIMIT 0x000D
+#define AL_REVERB_MIN_DENSITY (0.0f)
+#define AL_REVERB_MAX_DENSITY (1.0f)
+#define AL_REVERB_DEFAULT_DENSITY (1.0f)
+#define AL_REVERB_MIN_DIFFUSION (0.0f)
+#define AL_REVERB_MAX_DIFFUSION (1.0f)
+#define AL_REVERB_DEFAULT_DIFFUSION (1.0f)
+#define AL_REVERB_MIN_GAIN (0.0f)
+#define AL_REVERB_MAX_GAIN (1.0f)
+#define AL_REVERB_DEFAULT_GAIN (0.32f)
+#define AL_REVERB_MIN_GAINHF (0.0f)
+#define AL_REVERB_MAX_GAINHF (1.0f)
+#define AL_REVERB_DEFAULT_GAINHF (0.89f)
+#define AL_REVERB_MIN_DECAY_TIME (0.1f)
+#define AL_REVERB_MAX_DECAY_TIME (20.0f)
+#define AL_REVERB_DEFAULT_DECAY_TIME (1.49f)
+#define AL_REVERB_MIN_DECAY_HFRATIO (0.1f)
+#define AL_REVERB_MAX_DECAY_HFRATIO (2.0f)
+#define AL_REVERB_DEFAULT_DECAY_HFRATIO (0.83f)
+#define AL_REVERB_MIN_REFLECTIONS_GAIN (0.0f)
+#define AL_REVERB_MAX_REFLECTIONS_GAIN (3.16f)
+#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
+#define AL_REVERB_MIN_REFLECTIONS_DELAY (0.0f)
+#define AL_REVERB_MAX_REFLECTIONS_DELAY (0.3f)
+#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
+#define AL_REVERB_MIN_LATE_REVERB_GAIN (0.0f)
+#define AL_REVERB_MAX_LATE_REVERB_GAIN (10.0f)
+#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
+#define AL_REVERB_MIN_LATE_REVERB_DELAY (0.0f)
+#define AL_REVERB_MAX_LATE_REVERB_DELAY (0.1f)
+#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
+#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
+#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
+#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
+#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
+#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
+#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
+#define AL_REVERB_MIN_DECAY_HFLIMIT (AL_FALSE)
+#define AL_REVERB_MAX_DECAY_HFLIMIT (AL_TRUE)
+#define AL_REVERB_DEFAULT_DECAY_HFLIMIT (AL_TRUE)
+
#define AL_ECHO_DELAY 0x0001
#define AL_ECHO_LRDELAY 0x0002
#define AL_ECHO_DAMPING 0x0003
@@ -59,25 +102,114 @@ extern "C" {
#define AL_ECHO_MAX_SPREAD (1.0f)
#define AL_ECHO_DEFAULT_SPREAD (-1.0f)
+#define AL_EAXREVERB_DENSITY 0x0001
+#define AL_EAXREVERB_DIFFUSION 0x0002
+#define AL_EAXREVERB_GAIN 0x0003
+#define AL_EAXREVERB_GAINHF 0x0004
+#define AL_EAXREVERB_GAINLF 0x0005
+#define AL_EAXREVERB_DECAY_TIME 0x0006
+#define AL_EAXREVERB_DECAY_HFRATIO 0x0007
+#define AL_EAXREVERB_DECAY_LFRATIO 0x0008
+#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009
+#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A
+#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B
+#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C
+#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D
+#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E
+#define AL_EAXREVERB_ECHO_TIME 0x000F
+#define AL_EAXREVERB_ECHO_DEPTH 0x0010
+#define AL_EAXREVERB_MODULATION_TIME 0x0011
+#define AL_EAXREVERB_MODULATION_DEPTH 0x0012
+#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013
+#define AL_EAXREVERB_HFREFERENCE 0x0014
+#define AL_EAXREVERB_LFREFERENCE 0x0015
+#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016
+#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017
+
+#define AL_EAXREVERB_MIN_DENSITY (0.0f)
+#define AL_EAXREVERB_MAX_DENSITY (1.0f)
+#define AL_EAXREVERB_DEFAULT_DENSITY (1.0f)
+#define AL_EAXREVERB_MIN_DIFFUSION (0.0f)
+#define AL_EAXREVERB_MAX_DIFFUSION (1.0f)
+#define AL_EAXREVERB_DEFAULT_DIFFUSION (1.0f)
+#define AL_EAXREVERB_MIN_GAIN (0.0f)
+#define AL_EAXREVERB_MAX_GAIN (1.0f)
+#define AL_EAXREVERB_DEFAULT_GAIN (0.32f)
+#define AL_EAXREVERB_MIN_GAINHF (0.0f)
+#define AL_EAXREVERB_MAX_GAINHF (1.0f)
+#define AL_EAXREVERB_DEFAULT_GAINHF (0.89f)
+#define AL_EAXREVERB_MIN_GAINLF (0.0f)
+#define AL_EAXREVERB_MAX_GAINLF (1.0f)
+#define AL_EAXREVERB_DEFAULT_GAINLF (1.0f)
+#define AL_EAXREVERB_MIN_DECAY_TIME (0.1f)
+#define AL_EAXREVERB_MAX_DECAY_TIME (20.0f)
+#define AL_EAXREVERB_DEFAULT_DECAY_TIME (1.49f)
+#define AL_EAXREVERB_MIN_DECAY_HFRATIO (0.1f)
+#define AL_EAXREVERB_MAX_DECAY_HFRATIO (2.0f)
+#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO (0.83f)
+#define AL_EAXREVERB_MIN_DECAY_LFRATIO (0.1f)
+#define AL_EAXREVERB_MAX_DECAY_LFRATIO (2.0f)
+#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO (1.0f)
+#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN (0.0f)
+#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN (3.16f)
+#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
+#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY (0.0f)
+#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f)
+#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
+#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f)
+#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN (0.0f)
+#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN (10.0f)
+#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
+#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY (0.0f)
+#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f)
+#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
+#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f)
+#define AL_EAXREVERB_MIN_ECHO_TIME (0.075f)
+#define AL_EAXREVERB_MAX_ECHO_TIME (0.25f)
+#define AL_EAXREVERB_DEFAULT_ECHO_TIME (0.25f)
+#define AL_EAXREVERB_MIN_ECHO_DEPTH (0.0f)
+#define AL_EAXREVERB_MAX_ECHO_DEPTH (1.0f)
+#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH (0.0f)
+#define AL_EAXREVERB_MIN_MODULATION_TIME (0.04f)
+#define AL_EAXREVERB_MAX_MODULATION_TIME (4.0f)
+#define AL_EAXREVERB_DEFAULT_MODULATION_TIME (0.25f)
+#define AL_EAXREVERB_MIN_MODULATION_DEPTH (0.0f)
+#define AL_EAXREVERB_MAX_MODULATION_DEPTH (1.0f)
+#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH (0.0f)
+#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
+#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
+#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
+#define AL_EAXREVERB_MIN_HFREFERENCE (1000.0f)
+#define AL_EAXREVERB_MAX_HFREFERENCE (20000.0f)
+#define AL_EAXREVERB_DEFAULT_HFREFERENCE (5000.0f)
+#define AL_EAXREVERB_MIN_LFREFERENCE (20.0f)
+#define AL_EAXREVERB_MAX_LFREFERENCE (1000.0f)
+#define AL_EAXREVERB_DEFAULT_LFREFERENCE (250.0f)
+#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
+#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
+#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
+#define AL_EAXREVERB_MIN_DECAY_HFLIMIT (AL_FALSE)
+#define AL_EAXREVERB_MAX_DECAY_HFLIMIT (AL_TRUE)
+#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT (AL_TRUE)
enum {
- REVERB = 0,
+ EAXREVERB = 0,
+ REVERB,
ECHO,
MAX_EFFECTS
};
extern ALboolean DisabledEffects[MAX_EFFECTS];
-
typedef struct ALeffect_struct
{
// Effect type (AL_EFFECT_NULL, ...)
ALenum type;
struct {
+ // Shared Reverb Properties
ALfloat Density;
ALfloat Diffusion;
-
ALfloat Gain;
ALfloat GainHF;
ALfloat DecayTime;
@@ -89,6 +221,18 @@ typedef struct ALeffect_struct
ALfloat AirAbsorptionGainHF;
ALfloat RoomRolloffFactor;
ALboolean DecayHFLimit;
+
+ // Additional EAX Reverb Properties
+ ALfloat GainLF;
+ ALfloat DecayLFRatio;
+ ALfloat ReflectionsPan[3];
+ ALfloat LateReverbPan[3];
+ ALfloat EchoTime;
+ ALfloat EchoDepth;
+ ALfloat ModulationTime;
+ ALfloat ModulationDepth;
+ ALfloat HFReference;
+ ALfloat LFReference;
} Reverb;
struct {
diff --git a/OpenAL32/Include/alReverb.h b/OpenAL32/Include/alReverb.h
index 46c7194c..95b5adb0 100644
--- a/OpenAL32/Include/alReverb.h
+++ b/OpenAL32/Include/alReverb.h
@@ -14,9 +14,11 @@ extern "C" {
typedef struct ALverbState ALverbState;
ALverbState *VerbCreate(ALCcontext *Context);
+ALverbState *EAXVerbCreate(ALCcontext *Context);
ALvoid VerbDestroy(ALverbState *State);
ALvoid VerbUpdate(ALCcontext *Context, struct ALeffectslot *Slot, ALeffect *Effect);
ALvoid VerbProcess(ALverbState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS]);
+ALvoid EAXVerbProcess(ALverbState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS]);
#ifdef __cplusplus
}
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
index 810b380e..c9b8ac62 100644
--- a/OpenAL32/alAuxEffectSlot.c
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -470,38 +470,37 @@ ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, A
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
{
- if(!effect)
+ if((!effect) || (effect->type != ALEffectSlot->effect.type))
{
- memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
VerbDestroy(ALEffectSlot->ReverbState);
ALEffectSlot->ReverbState = NULL;
EchoDestroy(ALEffectSlot->EchoState);
ALEffectSlot->EchoState = NULL;
+ }
+ if(!effect)
+ {
+ memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
return;
}
- if(effect->type == AL_EFFECT_REVERB)
+ memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
+ if(effect->type == AL_EFFECT_EAXREVERB)
+ {
+ if(!ALEffectSlot->ReverbState)
+ ALEffectSlot->ReverbState = EAXVerbCreate(Context);
+ VerbUpdate(Context, ALEffectSlot, effect);
+ }
+ else if(effect->type == AL_EFFECT_REVERB)
{
- if(ALEffectSlot->EchoState)
- {
- EchoDestroy(ALEffectSlot->EchoState);
- ALEffectSlot->EchoState = NULL;
- }
if(!ALEffectSlot->ReverbState)
ALEffectSlot->ReverbState = VerbCreate(Context);
VerbUpdate(Context, ALEffectSlot, effect);
}
else if(effect->type == AL_EFFECT_ECHO)
{
- if(ALEffectSlot->ReverbState)
- {
- VerbDestroy(ALEffectSlot->ReverbState);
- ALEffectSlot->ReverbState = NULL;
- }
if(!ALEffectSlot->EchoState)
ALEffectSlot->EchoState = EchoCreate(Context);
EchoUpdate(Context, ALEffectSlot, effect);
}
- memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
}
diff --git a/OpenAL32/alEffect.c b/OpenAL32/alEffect.c
index 4455a230..4d0e7f34 100644
--- a/OpenAL32/alEffect.c
+++ b/OpenAL32/alEffect.c
@@ -170,6 +170,7 @@ ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
if(param == AL_EFFECT_TYPE)
{
ALboolean isOk = (iValue == AL_EFFECT_NULL ||
+ (iValue == AL_EFFECT_EAXREVERB && !DisabledEffects[EAXREVERB]) ||
(iValue == AL_EFFECT_REVERB && !DisabledEffects[REVERB]) ||
(iValue == AL_EFFECT_ECHO && !DisabledEffects[ECHO]));
@@ -178,6 +179,22 @@ ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
else
alSetError(AL_INVALID_VALUE);
}
+ else if(ALEffect->type == AL_EFFECT_EAXREVERB)
+ {
+ switch(param)
+ {
+ case AL_EAXREVERB_DECAY_HFLIMIT:
+ if(iValue == AL_TRUE || iValue == AL_FALSE)
+ ALEffect->Reverb.DecayHFLimit = iValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
@@ -227,6 +244,19 @@ ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues)
{
alEffecti(effect, param, piValues[0]);
}
+ else if(ALEffect->type == AL_EFFECT_EAXREVERB)
+ {
+ switch(param)
+ {
+ case AL_EAXREVERB_DECAY_HFLIMIT:
+ alEffecti(effect, param, piValues[0]);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
@@ -269,7 +299,175 @@ ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
- if(ALEffect->type == AL_EFFECT_REVERB)
+ if(ALEffect->type == AL_EFFECT_EAXREVERB)
+ {
+ switch(param)
+ {
+ case AL_EAXREVERB_DENSITY:
+ if(flValue >= AL_EAXREVERB_MIN_DENSITY &&
+ flValue <= AL_EAXREVERB_MAX_DENSITY)
+ ALEffect->Reverb.Density = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_DIFFUSION:
+ if(flValue >= AL_EAXREVERB_MIN_DIFFUSION &&
+ flValue <= AL_EAXREVERB_MAX_DIFFUSION)
+ ALEffect->Reverb.Diffusion = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_GAIN:
+ if(flValue >= AL_EAXREVERB_MIN_GAIN &&
+ flValue <= AL_EAXREVERB_MAX_GAIN)
+ ALEffect->Reverb.Gain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_GAINHF:
+ if(flValue >= AL_EAXREVERB_MIN_GAINHF &&
+ flValue <= AL_EAXREVERB_MAX_GAIN)
+ ALEffect->Reverb.GainHF = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_GAINLF:
+ if(flValue >= AL_EAXREVERB_MIN_GAINLF &&
+ flValue <= AL_EAXREVERB_MAX_GAINLF)
+ ALEffect->Reverb.GainLF = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_DECAY_TIME:
+ if(flValue >= AL_EAXREVERB_MIN_DECAY_TIME &&
+ flValue <= AL_EAXREVERB_MAX_DECAY_TIME)
+ ALEffect->Reverb.DecayTime = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_DECAY_HFRATIO:
+ if(flValue >= AL_EAXREVERB_MIN_DECAY_HFRATIO &&
+ flValue <= AL_EAXREVERB_MAX_DECAY_HFRATIO)
+ ALEffect->Reverb.DecayHFRatio = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_DECAY_LFRATIO:
+ if(flValue >= AL_EAXREVERB_MIN_DECAY_LFRATIO &&
+ flValue <= AL_EAXREVERB_MAX_DECAY_LFRATIO)
+ ALEffect->Reverb.DecayLFRatio = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_REFLECTIONS_GAIN:
+ if(flValue >= AL_EAXREVERB_MIN_REFLECTIONS_GAIN &&
+ flValue <= AL_EAXREVERB_MAX_REFLECTIONS_GAIN)
+ ALEffect->Reverb.ReflectionsGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_REFLECTIONS_DELAY:
+ if(flValue >= AL_EAXREVERB_MIN_REFLECTIONS_DELAY &&
+ flValue <= AL_EAXREVERB_MAX_REFLECTIONS_DELAY)
+ ALEffect->Reverb.ReflectionsDelay = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_LATE_REVERB_GAIN:
+ if(flValue >= AL_EAXREVERB_MIN_LATE_REVERB_GAIN &&
+ flValue <= AL_EAXREVERB_MAX_LATE_REVERB_GAIN)
+ ALEffect->Reverb.LateReverbGain = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_LATE_REVERB_DELAY:
+ if(flValue >= AL_EAXREVERB_MIN_LATE_REVERB_DELAY &&
+ flValue <= AL_EAXREVERB_MAX_LATE_REVERB_DELAY)
+ ALEffect->Reverb.LateReverbDelay = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
+ if(flValue >= AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF &&
+ flValue <= AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF)
+ ALEffect->Reverb.AirAbsorptionGainHF = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_ECHO_TIME:
+ if(flValue >= AL_EAXREVERB_MIN_ECHO_TIME &&
+ flValue <= AL_EAXREVERB_MAX_ECHO_TIME)
+ ALEffect->Reverb.EchoTime = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_ECHO_DEPTH:
+ if(flValue >= AL_EAXREVERB_MIN_ECHO_DEPTH &&
+ flValue <= AL_EAXREVERB_MAX_ECHO_DEPTH)
+ ALEffect->Reverb.EchoDepth = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_MODULATION_TIME:
+ if(flValue >= AL_EAXREVERB_MIN_MODULATION_TIME &&
+ flValue <= AL_EAXREVERB_MAX_MODULATION_TIME)
+ ALEffect->Reverb.ModulationTime = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_MODULATION_DEPTH:
+ if(flValue >= AL_EAXREVERB_MIN_MODULATION_DEPTH &&
+ flValue <= AL_EAXREVERB_MAX_MODULATION_DEPTH)
+ ALEffect->Reverb.ModulationDepth = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_HFREFERENCE:
+ if(flValue >= AL_EAXREVERB_MIN_HFREFERENCE &&
+ flValue <= AL_EAXREVERB_MAX_HFREFERENCE)
+ ALEffect->Reverb.HFReference = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_LFREFERENCE:
+ if(flValue >= AL_EAXREVERB_MIN_LFREFERENCE &&
+ flValue <= AL_EAXREVERB_MAX_LFREFERENCE)
+ ALEffect->Reverb.LFReference = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
+ if(flValue >= 0.0f && flValue <= 10.0f)
+ ALEffect->Reverb.RoomRolloffFactor = flValue;
+ else
+ alSetError(AL_INVALID_VALUE);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
@@ -426,7 +624,50 @@ ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
- if(ALEffect->type == AL_EFFECT_REVERB)
+ if(ALEffect->type == AL_EFFECT_EAXREVERB)
+ {
+ switch(param)
+ {
+ case AL_EAXREVERB_DENSITY:
+ case AL_EAXREVERB_DIFFUSION:
+ case AL_EAXREVERB_GAIN:
+ case AL_EAXREVERB_GAINHF:
+ case AL_EAXREVERB_GAINLF:
+ case AL_EAXREVERB_DECAY_TIME:
+ case AL_EAXREVERB_DECAY_HFRATIO:
+ case AL_EAXREVERB_DECAY_LFRATIO:
+ case AL_EAXREVERB_REFLECTIONS_GAIN:
+ case AL_EAXREVERB_REFLECTIONS_DELAY:
+ case AL_EAXREVERB_LATE_REVERB_GAIN:
+ case AL_EAXREVERB_LATE_REVERB_DELAY:
+ case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
+ case AL_EAXREVERB_ECHO_TIME:
+ case AL_EAXREVERB_ECHO_DEPTH:
+ case AL_EAXREVERB_MODULATION_TIME:
+ case AL_EAXREVERB_MODULATION_DEPTH:
+ case AL_EAXREVERB_HFREFERENCE:
+ case AL_EAXREVERB_LFREFERENCE:
+ case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
+ alEffectf(effect, param, pflValues[0]);
+ break;
+
+ case AL_EAXREVERB_REFLECTIONS_PAN:
+ ALEffect->Reverb.ReflectionsPan[0] = pflValues[0];
+ ALEffect->Reverb.ReflectionsPan[1] = pflValues[1];
+ ALEffect->Reverb.ReflectionsPan[2] = pflValues[2];
+ break;
+ case AL_EAXREVERB_LATE_REVERB_PAN:
+ ALEffect->Reverb.LateReverbPan[0] = pflValues[0];
+ ALEffect->Reverb.LateReverbPan[1] = pflValues[1];
+ ALEffect->Reverb.LateReverbPan[2] = pflValues[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
@@ -491,6 +732,19 @@ ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
{
*piValue = ALEffect->type;
}
+ else if(ALEffect->type == AL_EFFECT_EAXREVERB)
+ {
+ switch(param)
+ {
+ case AL_EAXREVERB_DECAY_HFLIMIT:
+ *piValue = ALEffect->Reverb.DecayHFLimit;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
@@ -537,6 +791,19 @@ ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
{
alGetEffecti(effect, param, piValues);
}
+ else if(ALEffect->type == AL_EFFECT_EAXREVERB)
+ {
+ switch(param)
+ {
+ case AL_EAXREVERB_DECAY_HFLIMIT:
+ alGetEffecti(effect, param, piValues);
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
@@ -579,7 +846,96 @@ ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
- if(ALEffect->type == AL_EFFECT_REVERB)
+ if(ALEffect->type == AL_EFFECT_EAXREVERB)
+ {
+ switch(param)
+ {
+ case AL_EAXREVERB_DENSITY:
+ *pflValue = ALEffect->Reverb.Density;
+ break;
+
+ case AL_EAXREVERB_DIFFUSION:
+ *pflValue = ALEffect->Reverb.Diffusion;
+ break;
+
+ case AL_EAXREVERB_GAIN:
+ *pflValue = ALEffect->Reverb.Gain;
+ break;
+
+ case AL_EAXREVERB_GAINHF:
+ *pflValue = ALEffect->Reverb.GainHF;
+ break;
+
+ case AL_EAXREVERB_GAINLF:
+ *pflValue = ALEffect->Reverb.GainLF;
+ break;
+
+ case AL_EAXREVERB_DECAY_TIME:
+ *pflValue = ALEffect->Reverb.DecayTime;
+ break;
+
+ case AL_EAXREVERB_DECAY_HFRATIO:
+ *pflValue = ALEffect->Reverb.DecayHFRatio;
+ break;
+
+ case AL_EAXREVERB_DECAY_LFRATIO:
+ *pflValue = ALEffect->Reverb.DecayLFRatio;
+ break;
+
+ case AL_EAXREVERB_REFLECTIONS_GAIN:
+ *pflValue = ALEffect->Reverb.ReflectionsGain;
+ break;
+
+ case AL_EAXREVERB_REFLECTIONS_DELAY:
+ *pflValue = ALEffect->Reverb.ReflectionsDelay;
+ break;
+
+ case AL_EAXREVERB_LATE_REVERB_GAIN:
+ *pflValue = ALEffect->Reverb.LateReverbGain;
+ break;
+
+ case AL_EAXREVERB_LATE_REVERB_DELAY:
+ *pflValue = ALEffect->Reverb.LateReverbDelay;
+ break;
+
+ case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
+ *pflValue = ALEffect->Reverb.AirAbsorptionGainHF;
+ break;
+
+ case AL_EAXREVERB_ECHO_TIME:
+ *pflValue = ALEffect->Reverb.EchoTime;
+ break;
+
+ case AL_EAXREVERB_ECHO_DEPTH:
+ *pflValue = ALEffect->Reverb.EchoDepth;
+ break;
+
+ case AL_EAXREVERB_MODULATION_TIME:
+ *pflValue = ALEffect->Reverb.ModulationTime;
+ break;
+
+ case AL_EAXREVERB_MODULATION_DEPTH:
+ *pflValue = ALEffect->Reverb.ModulationDepth;
+ break;
+
+ case AL_EAXREVERB_HFREFERENCE:
+ *pflValue = ALEffect->Reverb.HFReference;
+ break;
+
+ case AL_EAXREVERB_LFREFERENCE:
+ *pflValue = ALEffect->Reverb.LFReference;
+ break;
+
+ case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
+ *pflValue = ALEffect->Reverb.RoomRolloffFactor;
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
@@ -685,7 +1041,50 @@ ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
- if(ALEffect->type == AL_EFFECT_REVERB)
+ if(ALEffect->type == AL_EFFECT_EAXREVERB)
+ {
+ switch(param)
+ {
+ case AL_EAXREVERB_DENSITY:
+ case AL_EAXREVERB_DIFFUSION:
+ case AL_EAXREVERB_GAIN:
+ case AL_EAXREVERB_GAINHF:
+ case AL_EAXREVERB_GAINLF:
+ case AL_EAXREVERB_DECAY_TIME:
+ case AL_EAXREVERB_DECAY_HFRATIO:
+ case AL_EAXREVERB_DECAY_LFRATIO:
+ case AL_EAXREVERB_REFLECTIONS_GAIN:
+ case AL_EAXREVERB_REFLECTIONS_DELAY:
+ case AL_EAXREVERB_LATE_REVERB_GAIN:
+ case AL_EAXREVERB_LATE_REVERB_DELAY:
+ case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
+ case AL_EAXREVERB_ECHO_TIME:
+ case AL_EAXREVERB_ECHO_DEPTH:
+ case AL_EAXREVERB_MODULATION_TIME:
+ case AL_EAXREVERB_MODULATION_DEPTH:
+ case AL_EAXREVERB_HFREFERENCE:
+ case AL_EAXREVERB_LFREFERENCE:
+ case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
+ alGetEffectf(effect, param, pflValues);
+ break;
+
+ case AL_EAXREVERB_REFLECTIONS_PAN:
+ pflValues[0] = ALEffect->Reverb.ReflectionsPan[0];
+ pflValues[1] = ALEffect->Reverb.ReflectionsPan[1];
+ pflValues[2] = ALEffect->Reverb.ReflectionsPan[2];
+ break;
+ case AL_EAXREVERB_LATE_REVERB_PAN:
+ pflValues[0] = ALEffect->Reverb.LateReverbPan[0];
+ pflValues[1] = ALEffect->Reverb.LateReverbPan[1];
+ pflValues[2] = ALEffect->Reverb.LateReverbPan[2];
+ break;
+
+ default:
+ alSetError(AL_INVALID_ENUM);
+ break;
+ }
+ }
+ else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
@@ -761,18 +1160,33 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
effect->type = type;
switch(type)
{
+ case AL_EFFECT_EAXREVERB:
case AL_EFFECT_REVERB:
effect->Reverb.Density = 1.0f;
effect->Reverb.Diffusion = 1.0f;
effect->Reverb.Gain = 0.32f;
effect->Reverb.GainHF = 0.89f;
+ effect->Reverb.GainLF = 1.0f;
effect->Reverb.DecayTime = 1.49f;
effect->Reverb.DecayHFRatio = 0.83f;
+ effect->Reverb.DecayLFRatio = 1.0f;
effect->Reverb.ReflectionsGain = 0.05f;
effect->Reverb.ReflectionsDelay = 0.007f;
+ effect->Reverb.ReflectionsPan[0] = 0.0f;
+ effect->Reverb.ReflectionsPan[1] = 0.0f;
+ effect->Reverb.ReflectionsPan[2] = 0.0f;
effect->Reverb.LateReverbGain = 1.26f;
effect->Reverb.LateReverbDelay = 0.011f;
+ effect->Reverb.LateReverbPan[0] = 0.0f;
+ effect->Reverb.LateReverbPan[1] = 0.0f;
+ effect->Reverb.LateReverbPan[2] = 0.0f;
+ effect->Reverb.EchoTime = 0.25f;
+ effect->Reverb.EchoDepth = 0.0f;
+ effect->Reverb.ModulationTime = 0.25f;
+ effect->Reverb.ModulationDepth = 0.0f;
effect->Reverb.AirAbsorptionGainHF = 0.994f;
+ effect->Reverb.HFReference = 5000.0f;
+ effect->Reverb.LFReference = 250.0f;
effect->Reverb.RoomRolloffFactor = 0.0f;
effect->Reverb.DecayHFLimit = AL_TRUE;
break;
diff --git a/alsoftrc.sample b/alsoftrc.sample
index e13ff814..cc04fd95 100644
--- a/alsoftrc.sample
+++ b/alsoftrc.sample
@@ -72,7 +72,7 @@
## excludefx:
# Sets which effects to exclude, preventing apps from using them. This can
# help for apps that try to use effects which are too CPU intensive for the
-# system to handle. Available effects are: reverb,echo
+# system to handle. Available effects are: eaxreverb,reverb,echo
#excludefx =
## slots: