static ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot) { ALechoState *state = (ALechoState*)effect; ALCdevice *Device = Context->Device; ALuint frequency = Device->Frequency; ALfloat lrpan, cw, g, gain; ALuint i; state->Tap[0].delay = (ALuint)(Slot->effect.Echo.Delay * frequency) + 1; state->Tap[1].delay = (ALuint)(Slot->effect.Echo.LRDelay * frequency); state->Tap[1].delay += state->Tap[0].delay; lrpan = Slot->effect.Echo.Spread*0.5f + 0.5f; state->GainL = aluSqrt( lrpan); state->GainR = aluSqrt(1.0f-lrpan); state->FeedGain = Slot->effect.Echo.Feedback; cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / frequency); g = 1.0f - Slot->effect.Echo.Damping; state->iirFilter.coeff = lpCoeffCalc(g, cw); gain = Slot->Gain; for(i = 0;i < MAXCHANNELS;i++) state->Gain[i] = 0.0f; for(i = 0;i < Device->NumChan;i++) { enum Channel chan = Device->Speaker2Chan[i]; state->Gain[chan] = gain; } }
static ALvoid EchoUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot) { ALechoState *state = (ALechoState*)effect; ALuint frequency = Device->Frequency; ALfloat lrpan, cw, g, gain; ALfloat dirGain; ALuint i; state->Tap[0].delay = fastf2u(Slot->effect.Echo.Delay * frequency) + 1; state->Tap[1].delay = fastf2u(Slot->effect.Echo.LRDelay * frequency); state->Tap[1].delay += state->Tap[0].delay; lrpan = Slot->effect.Echo.Spread; state->FeedGain = Slot->effect.Echo.Feedback; cw = aluCos(F_PI*2.0f * LOWPASSFREQREF / frequency); g = 1.0f - Slot->effect.Echo.Damping; state->iirFilter.coeff = lpCoeffCalc(g, cw); gain = Slot->Gain; for(i = 0;i < MAXCHANNELS;i++) { state->Gain[0][i] = 0.0f; state->Gain[1][i] = 0.0f; } dirGain = aluFabs(lrpan); /* First tap panning */ ComputeAngleGains(Device, aluAtan2(-lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[0]); /* Second tap panning */ ComputeAngleGains(Device, aluAtan2(+lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[1]); }
// Calculate the coefficient for a HF (and eventually LF) decay damping // filter. static __inline ALfloat CalcDampingCoeff( ALfloat hfRatio, ALfloat length, ALfloat decayTime, ALfloat decayCoeff, ALfloat cw ) { ALfloat coeff, g; // Eventually this should boost the high frequencies when the ratio // exceeds 1. coeff = 0.0f; if ( hfRatio < 1.0f ) { // Calculate the low-pass coefficient by dividing the HF decay // coefficient by the full decay coefficient. g = CalcDecayCoeff( length, decayTime * hfRatio ) / decayCoeff; // Damping is done with a 1-pole filter, so g needs to be squared. g *= g; coeff = lpCoeffCalc( g, cw ); // Very low decay times will produce minimal output, so apply an // upper bound to the coefficient. coeff = __min( coeff, 0.98f ); } return coeff; }
// This updates the EAX reverb state. This is called any time the EAX reverb // effect is loaded into a slot. static ALvoid EAXVerbUpdate( ALeffectState* effect, ALCcontext* Context, const ALeffect* Effect ) { ALverbState* State = ( ALverbState* )effect; ALuint frequency = Context->Device->Frequency; ALfloat cw, x, y, hfRatio; // Calculate the master low-pass filter (from the master effect HF gain). cw = CalcI3DL2HFreq( Effect->Reverb.HFReference, frequency ); // This is done with 2 chained 1-pole filters, so no need to square g. State->LpFilter.coeff = lpCoeffCalc( Effect->Reverb.GainHF, cw ); // Update the modulator line. UpdateModulator( Effect->Reverb.ModulationTime, Effect->Reverb.ModulationDepth, frequency, State ); // Update the initial effect delay. UpdateDelayLine( Effect->Reverb.ReflectionsDelay, Effect->Reverb.LateReverbDelay, frequency, State ); // Update the early lines. UpdateEarlyLines( Effect->Reverb.Gain, Effect->Reverb.ReflectionsGain, Effect->Reverb.LateReverbDelay, State ); // Update the decorrelator. UpdateDecorrelator( Effect->Reverb.Density, frequency, State ); // Get the mixing matrix coefficients (x and y). CalcMatrixCoeffs( Effect->Reverb.Diffusion, &x, &y ); // Then divide x into y to simplify the matrix calculation. State->Late.MixCoeff = y / x; // If the HF limit parameter is flagged, calculate an appropriate limit // based on the air absorption parameter. hfRatio = Effect->Reverb.DecayHFRatio; if ( Effect->Reverb.DecayHFLimit && Effect->Reverb.AirAbsorptionGainHF < 1.0f ) hfRatio = CalcLimitedHfRatio( hfRatio, Effect->Reverb.AirAbsorptionGainHF, Effect->Reverb.DecayTime ); // Update the late lines. UpdateLateLines( Effect->Reverb.Gain, Effect->Reverb.LateReverbGain, x, Effect->Reverb.Density, Effect->Reverb.DecayTime, Effect->Reverb.Diffusion, hfRatio, cw, frequency, State ); // Update the echo line. UpdateEchoLine( Effect->Reverb.Gain, Effect->Reverb.LateReverbGain, Effect->Reverb.EchoTime, Effect->Reverb.DecayTime, Effect->Reverb.Diffusion, Effect->Reverb.EchoDepth, hfRatio, cw, frequency, State ); // Update early and late 3D panning. Update3DPanning( Effect->Reverb.ReflectionsPan, Effect->Reverb.LateReverbPan, Context->Device->PanningLUT, State ); }
static float CalcDampingCoeff(float hfRatio, float length, float decayTime, float decayCoeff, float cw) { float coeff, g; coeff = 0.0f; if (hfRatio < 1.0f) { /* Calculate the low-pass coefficient by dividing the HF decay * coefficient by the full decay coefficient. */ g = CalcDecayCoeff(length, decayTime * hfRatio) / decayCoeff; /* Damping is done with a 1-pole filter, so g needs to be squared. */ g *= g; coeff = lpCoeffCalc(g, cw); /* Very low decay times will produce minimal output, so apply an * upper bound to the coefficient. */ if (coeff > 0.98f) coeff = 0.98f; } return coeff; }
// This updates the EAX reverb state. This is called any time the EAX reverb // effect is loaded into a slot. static ALvoid ReverbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot) { ALverbState *State = (ALverbState*)effect; ALuint frequency = Context->Device->Frequency; ALboolean isEAX = AL_FALSE; ALfloat cw, x, y, hfRatio; if(Slot->effect.type == AL_EFFECT_EAXREVERB && !EmulateEAXReverb) { State->state.Process = EAXVerbProcess; isEAX = AL_TRUE; } else if(Slot->effect.type == AL_EFFECT_REVERB || EmulateEAXReverb) { State->state.Process = VerbProcess; isEAX = AL_FALSE; } // Calculate the master low-pass filter (from the master effect HF gain). cw = CalcI3DL2HFreq(Slot->effect.Params.Reverb.HFReference, frequency); // This is done with 2 chained 1-pole filters, so no need to square g. State->LpFilter.coeff = lpCoeffCalc(Slot->effect.Params.Reverb.GainHF, cw); if(isEAX) { // Update the modulator line. UpdateModulator(Slot->effect.Params.Reverb.ModulationTime, Slot->effect.Params.Reverb.ModulationDepth, frequency, State); } // Update the initial effect delay. UpdateDelayLine(Slot->effect.Params.Reverb.ReflectionsDelay, Slot->effect.Params.Reverb.LateReverbDelay, frequency, State); // Update the early lines. UpdateEarlyLines(Slot->effect.Params.Reverb.Gain, Slot->effect.Params.Reverb.ReflectionsGain, Slot->effect.Params.Reverb.LateReverbDelay, State); // Update the decorrelator. UpdateDecorrelator(Slot->effect.Params.Reverb.Density, frequency, State); // Get the mixing matrix coefficients (x and y). CalcMatrixCoeffs(Slot->effect.Params.Reverb.Diffusion, &x, &y); // Then divide x into y to simplify the matrix calculation. State->Late.MixCoeff = y / x; // If the HF limit parameter is flagged, calculate an appropriate limit // based on the air absorption parameter. hfRatio = Slot->effect.Params.Reverb.DecayHFRatio; if(Slot->effect.Params.Reverb.DecayHFLimit && Slot->effect.Params.Reverb.AirAbsorptionGainHF < 1.0f) hfRatio = CalcLimitedHfRatio(hfRatio, Slot->effect.Params.Reverb.AirAbsorptionGainHF, Slot->effect.Params.Reverb.DecayTime); // Update the late lines. UpdateLateLines(Slot->effect.Params.Reverb.Gain, Slot->effect.Params.Reverb.LateReverbGain, x, Slot->effect.Params.Reverb.Density, Slot->effect.Params.Reverb.DecayTime, Slot->effect.Params.Reverb.Diffusion, hfRatio, cw, frequency, State); if(isEAX) { // Update the echo line. UpdateEchoLine(Slot->effect.Params.Reverb.Gain, Slot->effect.Params.Reverb.LateReverbGain, Slot->effect.Params.Reverb.EchoTime, Slot->effect.Params.Reverb.DecayTime, Slot->effect.Params.Reverb.Diffusion, Slot->effect.Params.Reverb.EchoDepth, hfRatio, cw, frequency, State); // Update early and late 3D panning. Update3DPanning(Context->Device, Slot->effect.Params.Reverb.ReflectionsPan, Slot->effect.Params.Reverb.LateReverbPan, Slot->Gain, State); } else { ALCdevice *Device = Context->Device; ALfloat gain = Slot->Gain; ALuint index; /* Update channel gains */ gain *= aluSqrt(2.0f/Device->NumChan) * ReverbBoost; for(index = 0;index < MAXCHANNELS;index++) State->Gain[index] = 0.0f; for(index = 0;index < Device->NumChan;index++) { enum Channel chan = Device->Speaker2Chan[index]; State->Gain[chan] = gain; } } }