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;
    }
}
示例#2
0
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 );
}
示例#5
0
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;
}
示例#6
0
// 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;
        }
    }
}