Exemple #1
0
static ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
{
    ALechoState *state = (ALechoState*)effect;
    ALuint frequency = Context->Device->Frequency;
    ALfp lrpan, cw, a, g;

    state->Tap[0].delay = (ALuint)ALfp2int((ALfpMult(Effect->Echo.Delay, int2ALfp(frequency)) + int2ALfp(1)));
    state->Tap[1].delay = (ALuint)ALfp2int(ALfpMult(Effect->Echo.LRDelay, int2ALfp(frequency)));
    state->Tap[1].delay += state->Tap[0].delay;

    lrpan = (ALfpMult(Effect->Echo.Spread, float2ALfp(0.5f)) + float2ALfp(0.5f));
    state->GainL = aluSqrt(     lrpan);
    state->GainR = aluSqrt((int2ALfp(1)-lrpan));

    state->FeedGain = Effect->Echo.Feedback;

    cw = __cos(ALfpDiv(float2ALfp(2.0*M_PI * LOWPASSFREQCUTOFF), int2ALfp(frequency)));
    g = (int2ALfp(1) - Effect->Echo.Damping);
    a = int2ALfp(0);
    if(g < float2ALfp(0.9999f)) { /* 1-epsilon */
        // a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
        a = ALfpDiv((int2ALfp(1) - ALfpMult(g,cw) - aluSqrt((ALfpMult(ALfpMult(int2ALfp(2),g),(int2ALfp(1)-cw)) -
                     ALfpMult(ALfpMult(g,g),(int2ALfp(1) - ALfpMult(cw,cw)))))),
                    (int2ALfp(1) - g));
    }
    state->iirFilter.coeff = a;
}
Exemple #2
0
static ALvoid ModulatorUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot)
{
    ALmodulatorState *state = (ALmodulatorState*)effect;
    ALfloat gain, cw, a = 0.0f;
    ALuint index;

    if(Slot->effect.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
        state->Waveform = SINUSOID;
    else if(Slot->effect.Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
        state->Waveform = SAWTOOTH;
    else if(Slot->effect.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)
        state->Waveform = SQUARE;

    state->step = fastf2u(Slot->effect.Modulator.Frequency*WAVEFORM_FRACONE /
                          Device->Frequency);
    if(state->step == 0) state->step = 1;

    cw = aluCos(F_PI*2.0f * Slot->effect.Modulator.HighPassCutoff /
                            Device->Frequency);
    a = (2.0f-cw) - aluSqrt(aluPow(2.0f-cw, 2.0f) - 1.0f);
    state->iirFilter.coeff = a;

    gain = aluSqrt(1.0f/Device->NumChan);
    gain *= Slot->Gain;
    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;
    }
}
static ALvoid EchoUpdate( ALeffectState* effect, ALCcontext* Context, const ALeffect* Effect )
{
	ALechoState* state = ( ALechoState* )effect;
	ALuint frequency = Context->Device->Frequency;
	ALfloat lrpan, cw, a, g;

	state->Tap[0].delay = ( ALuint )( Effect->Echo.Delay * frequency ) + 1;
	state->Tap[1].delay = ( ALuint )( Effect->Echo.LRDelay * frequency );
	state->Tap[1].delay += state->Tap[0].delay;

	lrpan = Effect->Echo.Spread * 0.5f + 0.5f;
	state->GainL = aluSqrt(     lrpan );
	state->GainR = aluSqrt( 1.0f - lrpan );

	state->FeedGain = Effect->Echo.Feedback;

	cw = cos( 2.0 * M_PI * LOWPASSFREQCUTOFF / frequency );
	g = 1.0f - Effect->Echo.Damping;
	a = 0.0f;

	if ( g < 0.9999f ) // 1-epsilon
	{
		a = ( 1 - g * cw - aluSqrt( 2 * g * ( 1 - cw ) - g * g * ( 1 - cw * cw ) ) ) / ( 1 - g );
	}

	state->iirFilter.coeff = a;
}
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;
    }
}
Exemple #5
0
static ALboolean EchoDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
{
    ALechoState *state = (ALechoState*)effect;
    ALuint maxlen, i;

    // 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) + 1;
    maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Device->Frequency) + 1;
    maxlen  = NextPowerOf2(maxlen);

    if(maxlen != state->BufferLength)
    {
        void *temp;

        temp = realloc(state->SampleBuffer, maxlen * sizeof(ALfloat));
        if(!temp)
            return AL_FALSE;
        state->SampleBuffer = temp;
        state->BufferLength = maxlen;
    }
    for(i = 0;i < state->BufferLength;i++)
        state->SampleBuffer[i] = 0.0f;

    state->Scale = aluSqrt(Device->NumChan / 6.0f);
    state->Scale = __min(state->Scale, 1.0f);

    return AL_TRUE;
}
// This updates the device-dependant reverb state.  This is called on
// initialization and any time the device parameters (eg. playback frequency,
// or format) have been changed.
static ALboolean VerbDeviceUpdate( ALeffectState* effect, ALCdevice* Device )
{
	ALverbState* State = ( ALverbState* )effect;
	ALuint frequency = Device->Frequency, index;

	// Allocate the delay lines.
	if ( !AllocLines( AL_FALSE, frequency, State ) )
	{
		return AL_FALSE;
	}

	State->Scale = aluSqrt( Device->NumChan / 8.0f );

	// The early reflection and late all-pass filter line lengths are static,
	// so their offsets only need to be calculated once.
	for ( index = 0; index < 4; index++ )
	{
		State->Early.Offset[index] = ( ALuint )( EARLY_LINE_LENGTH[index] *
		                                         frequency );
		State->Late.ApOffset[index] = ( ALuint )( ALLPASS_LINE_LENGTH[index] *
		                                          frequency );
	}

	return AL_TRUE;
}
static ALvoid ModulatorUpdate( ALeffectState* effect, ALCcontext* Context, const ALeffect* Effect )
{
	ALmodulatorState* state = ( ALmodulatorState* )effect;
	ALfloat cw, a = 0.0f;

	if ( Effect->Modulator.Waveform == AL_RING_MODULATOR_SINUSOID )
	{
		state->Waveform = SINUSOID;
	}
	else if ( Effect->Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH )
	{
		state->Waveform = SAWTOOTH;
	}
	else if ( Effect->Modulator.Waveform == AL_RING_MODULATOR_SQUARE )
	{
		state->Waveform = SQUARE;
	}

	state->step = Effect->Modulator.Frequency * ( 1 << WAVEFORM_FRACBITS ) /
	              Context->Device->Frequency;

	if ( !state->step )
	{
		state->step = 1;
	}

	cw = cos( 2.0 * M_PI * Effect->Modulator.HighPassCutoff / Context->Device->Frequency );
	a = ( 2.0f - cw ) - aluSqrt( aluPow( 2.0f - cw, 2.0f ) - 1.0f );
	state->iirFilter.coeff = a;
}
static ALboolean ModulatorDeviceUpdate( ALeffectState* effect, ALCdevice* Device )
{
	ALmodulatorState* state = ( ALmodulatorState* )effect;

	state->Scale = aluSqrt( Device->NumChan / 8.0f );

	return AL_TRUE;
}
static __inline ALvoid aluNormalize(ALfloat *inVector)
{
    ALfloat length, inverse_length;

    length = aluSqrt(aluDotproduct(inVector, inVector));
    if(length != 0.0f)
    {
        inverse_length = 1.0f/length;
        inVector[0] *= inverse_length;
        inVector[1] *= inverse_length;
        inVector[2] *= inverse_length;
    }
}
// Calculate the mixing matrix coefficients given a diffusion factor.
static __inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *y)
{
    ALfloat n, t;

    // The matrix is of order 4, so n is sqrt (4 - 1).
    n = aluSqrt(3.0f);
    t = diffusion * atan(n);

    // Calculate the first mixing matrix coefficient.
    *x = cos(t);
    // Calculate the second mixing matrix coefficient.
    *y = sin(t) / n;
}
ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
{
    ALfloat a = 0.0f;

    /* Be careful with gains < 0.01, as that causes the coefficient
     * head towards 1, which will flatten the signal */
    if(g < 0.9999f) /* 1-epsilon */
    {
        g = maxf(g, 0.01f);
        a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
            (1 - g);
    }

    return a;
}
// Calculate an attenuation to be applied to the input of any echo models to
// compensate for modal density and decay time.
static __inline ALfloat CalcDensityGain(ALfloat a)
{
    /* The energy of a signal can be obtained by finding the area under the
     * squared signal.  This takes the form of Sum(x_n^2), where x is the
     * amplitude for the sample n.
     *
     * Decaying feedback matches exponential decay of the form Sum(a^n),
     * where a is the attenuation coefficient, and n is the sample.  The area
     * under this decay curve can be calculated as:  1 / (1 - a).
     *
     * Modifying the above equation to find the squared area under the curve
     * (for energy) yields:  1 / (1 - a^2).  Input attenuation can then be
     * calculated by inverting the square root of this approximation,
     * yielding:  1 / sqrt(1 / (1 - a^2)), simplified to: sqrt(1 - a^2).
     */
    return aluSqrt(1.0f - (a * a));
}
// This updates the device-dependant EAX reverb state.  This is called on
// initialization and any time the device parameters (eg. playback frequency,
// format) have been changed.
static ALboolean EAXVerbDeviceUpdate( ALeffectState* effect, ALCdevice* Device )
{
	ALverbState* State = ( ALverbState* )effect;
	ALuint frequency = Device->Frequency, index;

	// Allocate the delay lines.
	if ( !AllocLines( AL_TRUE, frequency, State ) )
	{
		return AL_FALSE;
	}

	State->Scale = aluSqrt( Device->NumChan / 8.0f );

	// Calculate the modulation filter coefficient.  Notice that the exponent
	// is calculated given the current sample rate.  This ensures that the
	// resulting filter response over time is consistent across all sample
	// rates.
	State->Mod.Coeff = aluPow( MODULATION_FILTER_COEFF,
	                           MODULATION_FILTER_CONST / frequency );

	// The early reflection and late all-pass filter line lengths are static,
	// so their offsets only need to be calculated once.
	for ( index = 0; index < 4; index++ )
	{
		State->Early.Offset[index] = ( ALuint )( EARLY_LINE_LENGTH[index] *
		                                         frequency );
		State->Late.ApOffset[index] = ( ALuint )( ALLPASS_LINE_LENGTH[index] *
		                                          frequency );
	}

	// The echo all-pass filter line length is static, so its offset only
	// needs to be calculated once.
	State->Echo.ApOffset = ( ALuint )( ECHO_ALLPASS_LENGTH * frequency );

	return AL_TRUE;
}
Exemple #14
0
ALvoid aluInitPanning(ALCdevice *Device)
{
    ALfloat SpeakerAngle[MAXCHANNELS];
    enum Channel *Speaker2Chan;
    ALfloat Alpha, Theta;
    ALint pos;
    ALuint s;

    Speaker2Chan = Device->Speaker2Chan;
    switch(Device->FmtChans)
    {
        case DevFmtMono:
            Device->NumChan = 1;
            Speaker2Chan[0] = FRONT_CENTER;
            SpeakerAngle[0] = F_PI/180.0f * 0.0f;
            break;

        case DevFmtStereo:
            Device->NumChan = 2;
            Speaker2Chan[0] = FRONT_LEFT;
            Speaker2Chan[1] = FRONT_RIGHT;
            SpeakerAngle[0] = F_PI/180.0f * -90.0f;
            SpeakerAngle[1] = F_PI/180.0f *  90.0f;
            SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;

        case DevFmtQuad:
            Device->NumChan = 4;
            Speaker2Chan[0] = BACK_LEFT;
            Speaker2Chan[1] = FRONT_LEFT;
            Speaker2Chan[2] = FRONT_RIGHT;
            Speaker2Chan[3] = BACK_RIGHT;
            SpeakerAngle[0] = F_PI/180.0f * -135.0f;
            SpeakerAngle[1] = F_PI/180.0f *  -45.0f;
            SpeakerAngle[2] = F_PI/180.0f *   45.0f;
            SpeakerAngle[3] = F_PI/180.0f *  135.0f;
            SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;

        case DevFmtX51:
            Device->NumChan = 5;
            Speaker2Chan[0] = BACK_LEFT;
            Speaker2Chan[1] = FRONT_LEFT;
            Speaker2Chan[2] = FRONT_CENTER;
            Speaker2Chan[3] = FRONT_RIGHT;
            Speaker2Chan[4] = BACK_RIGHT;
            SpeakerAngle[0] = F_PI/180.0f * -110.0f;
            SpeakerAngle[1] = F_PI/180.0f *  -30.0f;
            SpeakerAngle[2] = F_PI/180.0f *    0.0f;
            SpeakerAngle[3] = F_PI/180.0f *   30.0f;
            SpeakerAngle[4] = F_PI/180.0f *  110.0f;
            SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;

        case DevFmtX51Side:
            Device->NumChan = 5;
            Speaker2Chan[0] = SIDE_LEFT;
            Speaker2Chan[1] = FRONT_LEFT;
            Speaker2Chan[2] = FRONT_CENTER;
            Speaker2Chan[3] = FRONT_RIGHT;
            Speaker2Chan[4] = SIDE_RIGHT;
            SpeakerAngle[0] = F_PI/180.0f * -90.0f;
            SpeakerAngle[1] = F_PI/180.0f * -30.0f;
            SpeakerAngle[2] = F_PI/180.0f *   0.0f;
            SpeakerAngle[3] = F_PI/180.0f *  30.0f;
            SpeakerAngle[4] = F_PI/180.0f *  90.0f;
            SetSpeakerArrangement("layout_51SIDECHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;

        case DevFmtX61:
            Device->NumChan = 6;
            Speaker2Chan[0] = SIDE_LEFT;
            Speaker2Chan[1] = FRONT_LEFT;
            Speaker2Chan[2] = FRONT_CENTER;
            Speaker2Chan[3] = FRONT_RIGHT;
            Speaker2Chan[4] = SIDE_RIGHT;
            Speaker2Chan[5] = BACK_CENTER;
            SpeakerAngle[0] = F_PI/180.0f * -90.0f;
            SpeakerAngle[1] = F_PI/180.0f * -30.0f;
            SpeakerAngle[2] = F_PI/180.0f *   0.0f;
            SpeakerAngle[3] = F_PI/180.0f *  30.0f;
            SpeakerAngle[4] = F_PI/180.0f *  90.0f;
            SpeakerAngle[5] = F_PI/180.0f * 180.0f;
            SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;

        case DevFmtX71:
            Device->NumChan = 7;
            Speaker2Chan[0] = BACK_LEFT;
            Speaker2Chan[1] = SIDE_LEFT;
            Speaker2Chan[2] = FRONT_LEFT;
            Speaker2Chan[3] = FRONT_CENTER;
            Speaker2Chan[4] = FRONT_RIGHT;
            Speaker2Chan[5] = SIDE_RIGHT;
            Speaker2Chan[6] = BACK_RIGHT;
            SpeakerAngle[0] = F_PI/180.0f * -150.0f;
            SpeakerAngle[1] = F_PI/180.0f *  -90.0f;
            SpeakerAngle[2] = F_PI/180.0f *  -30.0f;
            SpeakerAngle[3] = F_PI/180.0f *    0.0f;
            SpeakerAngle[4] = F_PI/180.0f *   30.0f;
            SpeakerAngle[5] = F_PI/180.0f *   90.0f;
            SpeakerAngle[6] = F_PI/180.0f *  150.0f;
            SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;
    }

    for(pos = 0; pos < LUT_NUM; pos++)
    {
        ALfloat *PanningLUT = Device->PanningLUT[pos];

        /* clear all values */
        for(s = 0; s < MAXCHANNELS; s++)
            PanningLUT[s] = 0.0f;

        if(Device->NumChan == 1)
        {
            PanningLUT[Speaker2Chan[0]] = 1.0f;
            continue;
        }

        /* source angle */
        Theta = aluLUTpos2Angle(pos);

        /* set panning values */
        for(s = 0; s < Device->NumChan - 1; s++)
        {
            if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1])
            {
                /* source between speaker s and speaker s+1 */
                Alpha = (Theta-SpeakerAngle[s]) /
                        (SpeakerAngle[s+1]-SpeakerAngle[s]);
                PanningLUT[Speaker2Chan[s]]   = aluSqrt(1.0f-Alpha);
                PanningLUT[Speaker2Chan[s+1]] = aluSqrt(     Alpha);
                break;
            }
        }
        if(s == Device->NumChan - 1)
        {
            /* source between last and first speaker */
            if(Theta < SpeakerAngle[0])
                Theta += F_PI*2.0f;
            Alpha = (Theta-SpeakerAngle[s]) /
                    (F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[s]);
            PanningLUT[Speaker2Chan[s]] = aluSqrt(1.0f-Alpha);
            PanningLUT[Speaker2Chan[0]] = aluSqrt(     Alpha);
        }
    }
}
// Update the early and late 3D panning gains.
static ALvoid Update3DPanning( const ALfloat* ReflectionsPan, const ALfloat* LateReverbPan, ALfloat* PanningLUT, ALverbState* State )
{
	ALfloat length;
	ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1],
	                        ReflectionsPan[2]
	                      };
	ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
	                       LateReverbPan[2]
	                     };
	ALint pos;
	ALfloat* speakerGain, dirGain, ambientGain;
	ALuint index;

	// Calculate the 3D-panning gains for the early reflections and late
	// reverb.
	length = earlyPan[0] * earlyPan[0] + earlyPan[1] * earlyPan[1] + earlyPan[2] * earlyPan[2];

	if ( length > 1.0f )
	{
		length = 1.0f / aluSqrt( length );
		earlyPan[0] *= length;
		earlyPan[1] *= length;
		earlyPan[2] *= length;
	}

	length = latePan[0] * latePan[0] + latePan[1] * latePan[1] + latePan[2] * latePan[2];

	if ( length > 1.0f )
	{
		length = 1.0f / aluSqrt( length );
		latePan[0] *= length;
		latePan[1] *= length;
		latePan[2] *= length;
	}

	/* 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 a rough
	 * approximation of the expansion of sound across the speakers from the
	 * panning direction.
	 */
	pos = aluCart2LUTpos( earlyPan[2], earlyPan[0] );
	speakerGain = &PanningLUT[OUTPUTCHANNELS * pos];
	dirGain = aluSqrt( ( earlyPan[0] * earlyPan[0] ) + ( earlyPan[2] * earlyPan[2] ) );
	ambientGain = ( 1.0 - dirGain );

	for ( index = 0; index < OUTPUTCHANNELS; index++ )
	{
		State->Early.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
	}

	pos = aluCart2LUTpos( latePan[2], latePan[0] );
	speakerGain = &PanningLUT[OUTPUTCHANNELS * pos];
	dirGain = aluSqrt( ( latePan[0] * latePan[0] ) + ( latePan[2] * latePan[2] ) );
	ambientGain = ( 1.0 - dirGain );

	for ( index = 0; index < OUTPUTCHANNELS; index++ )
	{
		State->Late.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
	}
}
// Update the early and late 3D panning gains.
static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALverbState *State)
{
    ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1],
                            ReflectionsPan[2] };
    ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
                           LateReverbPan[2] };
    const ALfloat *speakerGain;
    ALfloat ambientGain;
    ALfloat dirGain;
    ALfloat length;
    ALuint index;
    ALint pos;

    Gain *= ReverbBoost;

    // Attenuate non-directional reverb according to the number of channels
    ambientGain = aluSqrt(2.0f/Device->NumChan);

    // Calculate the 3D-panning gains for the early reflections and late
    // reverb.
    length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
    if(length > 1.0f)
    {
        length = 1.0f / aluSqrt(length);
        earlyPan[0] *= length;
        earlyPan[1] *= length;
        earlyPan[2] *= length;
    }
    length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
    if(length > 1.0f)
    {
        length = 1.0f / aluSqrt(length);
        latePan[0] *= length;
        latePan[1] *= length;
        latePan[2] *= length;
    }

    /* 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 a rough
     * approximation of the expansion of sound across the speakers from the
     * panning direction.
     */
    pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
    speakerGain = Device->PanningLUT[pos];
    dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));

    for(index = 0;index < MAXCHANNELS;index++)
        State->Early.PanGain[index] = 0.0f;
    for(index = 0;index < Device->NumChan;index++)
    {
        enum Channel chan = Device->Speaker2Chan[index];
        State->Early.PanGain[chan] = lerp(ambientGain, speakerGain[chan], dirGain) * Gain;
    }


    pos = aluCart2LUTpos(latePan[2], latePan[0]);
    speakerGain = Device->PanningLUT[pos];
    dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));

    for(index = 0;index < MAXCHANNELS;index++)
         State->Late.PanGain[index] = 0.0f;
    for(index = 0;index < Device->NumChan;index++)
    {
        enum Channel chan = Device->Speaker2Chan[index];
        State->Late.PanGain[chan] = lerp(ambientGain, speakerGain[chan], dirGain) * Gain;
    }
}
// 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;
        }
    }
}
Exemple #18
0
ALvoid aluInitPanning(ALCdevice *Device)
{
    ALfloat SpeakerAngle[MAXCHANNELS];
    ALfloat (*Matrix)[MAXCHANNELS];
    Channel *Speaker2Chan;
    ALfloat Alpha, Theta;
    ALfloat *PanningLUT;
    ALint pos, offset;
    ALuint s, s2;

    for(s = 0;s < MAXCHANNELS;s++)
    {
        for(s2 = 0;s2 < MAXCHANNELS;s2++)
            Device->ChannelMatrix[s][s2] = ((s==s2) ? 1.0f : 0.0f);
    }

    Speaker2Chan = Device->Speaker2Chan;
    Matrix = Device->ChannelMatrix;
    switch(Device->FmtChans)
    {
        case DevFmtMono:
            Matrix[FRONT_LEFT][FRONT_CENTER]  = aluSqrt(0.5);
            Matrix[FRONT_RIGHT][FRONT_CENTER] = aluSqrt(0.5);
            Matrix[SIDE_LEFT][FRONT_CENTER]   = aluSqrt(0.5);
            Matrix[SIDE_RIGHT][FRONT_CENTER]  = aluSqrt(0.5);
            Matrix[BACK_LEFT][FRONT_CENTER]   = aluSqrt(0.5);
            Matrix[BACK_RIGHT][FRONT_CENTER]  = aluSqrt(0.5);
            Matrix[BACK_CENTER][FRONT_CENTER] = 1.0f;
            Device->NumChan = 1;
            Speaker2Chan[0] = FRONT_CENTER;
            SpeakerAngle[0] = 0.0f * M_PI/180.0f;
            break;

        case DevFmtStereo:
            Matrix[FRONT_CENTER][FRONT_LEFT]  = aluSqrt(0.5);
            Matrix[FRONT_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
            Matrix[SIDE_LEFT][FRONT_LEFT]     = 1.0f;
            Matrix[SIDE_RIGHT][FRONT_RIGHT]   = 1.0f;
            Matrix[BACK_LEFT][FRONT_LEFT]     = 1.0f;
            Matrix[BACK_RIGHT][FRONT_RIGHT]   = 1.0f;
            Matrix[BACK_CENTER][FRONT_LEFT]   = aluSqrt(0.5);
            Matrix[BACK_CENTER][FRONT_RIGHT]  = aluSqrt(0.5);
            Device->NumChan = 2;
            Speaker2Chan[0] = FRONT_LEFT;
            Speaker2Chan[1] = FRONT_RIGHT;
            SpeakerAngle[0] = -90.0f * M_PI/180.0f;
            SpeakerAngle[1] =  90.0f * M_PI/180.0f;
            SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;

        case DevFmtQuad:
            Matrix[FRONT_CENTER][FRONT_LEFT]  = aluSqrt(0.5);
            Matrix[FRONT_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
            Matrix[SIDE_LEFT][FRONT_LEFT]     = aluSqrt(0.5);
            Matrix[SIDE_LEFT][BACK_LEFT]      = aluSqrt(0.5);
            Matrix[SIDE_RIGHT][FRONT_RIGHT]   = aluSqrt(0.5);
            Matrix[SIDE_RIGHT][BACK_RIGHT]    = aluSqrt(0.5);
            Matrix[BACK_CENTER][BACK_LEFT]    = aluSqrt(0.5);
            Matrix[BACK_CENTER][BACK_RIGHT]   = aluSqrt(0.5);
            Device->NumChan = 4;
            Speaker2Chan[0] = BACK_LEFT;
            Speaker2Chan[1] = FRONT_LEFT;
            Speaker2Chan[2] = FRONT_RIGHT;
            Speaker2Chan[3] = BACK_RIGHT;
            SpeakerAngle[0] = -135.0f * M_PI/180.0f;
            SpeakerAngle[1] =  -45.0f * M_PI/180.0f;
            SpeakerAngle[2] =   45.0f * M_PI/180.0f;
            SpeakerAngle[3] =  135.0f * M_PI/180.0f;
            SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;

        case DevFmtX51:
            Matrix[SIDE_LEFT][FRONT_LEFT]   = aluSqrt(0.5);
            Matrix[SIDE_LEFT][BACK_LEFT]    = aluSqrt(0.5);
            Matrix[SIDE_RIGHT][FRONT_RIGHT] = aluSqrt(0.5);
            Matrix[SIDE_RIGHT][BACK_RIGHT]  = aluSqrt(0.5);
            Matrix[BACK_CENTER][BACK_LEFT]  = aluSqrt(0.5);
            Matrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5);
            Device->NumChan = 5;
            Speaker2Chan[0] = BACK_LEFT;
            Speaker2Chan[1] = FRONT_LEFT;
            Speaker2Chan[2] = FRONT_CENTER;
            Speaker2Chan[3] = FRONT_RIGHT;
            Speaker2Chan[4] = BACK_RIGHT;
            SpeakerAngle[0] = -110.0f * M_PI/180.0f;
            SpeakerAngle[1] =  -30.0f * M_PI/180.0f;
            SpeakerAngle[2] =    0.0f * M_PI/180.0f;
            SpeakerAngle[3] =   30.0f * M_PI/180.0f;
            SpeakerAngle[4] =  110.0f * M_PI/180.0f;
            SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;

        case DevFmtX61:
            Matrix[BACK_LEFT][BACK_CENTER]  = aluSqrt(0.5);
            Matrix[BACK_LEFT][SIDE_LEFT]    = aluSqrt(0.5);
            Matrix[BACK_RIGHT][BACK_CENTER] = aluSqrt(0.5);
            Matrix[BACK_RIGHT][SIDE_RIGHT]  = aluSqrt(0.5);
            Device->NumChan = 6;
            Speaker2Chan[0] = SIDE_LEFT;
            Speaker2Chan[1] = FRONT_LEFT;
            Speaker2Chan[2] = FRONT_CENTER;
            Speaker2Chan[3] = FRONT_RIGHT;
            Speaker2Chan[4] = SIDE_RIGHT;
            Speaker2Chan[5] = BACK_CENTER;
            SpeakerAngle[0] = -90.0f * M_PI/180.0f;
            SpeakerAngle[1] = -30.0f * M_PI/180.0f;
            SpeakerAngle[2] =   0.0f * M_PI/180.0f;
            SpeakerAngle[3] =  30.0f * M_PI/180.0f;
            SpeakerAngle[4] =  90.0f * M_PI/180.0f;
            SpeakerAngle[5] = 180.0f * M_PI/180.0f;
            SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;

        case DevFmtX71:
            Matrix[BACK_CENTER][BACK_LEFT]  = aluSqrt(0.5);
            Matrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5);
            Device->NumChan = 7;
            Speaker2Chan[0] = BACK_LEFT;
            Speaker2Chan[1] = SIDE_LEFT;
            Speaker2Chan[2] = FRONT_LEFT;
            Speaker2Chan[3] = FRONT_CENTER;
            Speaker2Chan[4] = FRONT_RIGHT;
            Speaker2Chan[5] = SIDE_RIGHT;
            Speaker2Chan[6] = BACK_RIGHT;
            SpeakerAngle[0] = -150.0f * M_PI/180.0f;
            SpeakerAngle[1] =  -90.0f * M_PI/180.0f;
            SpeakerAngle[2] =  -30.0f * M_PI/180.0f;
            SpeakerAngle[3] =    0.0f * M_PI/180.0f;
            SpeakerAngle[4] =   30.0f * M_PI/180.0f;
            SpeakerAngle[5] =   90.0f * M_PI/180.0f;
            SpeakerAngle[6] =  150.0f * M_PI/180.0f;
            SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
            break;
    }

    if(GetConfigValueBool(NULL, "scalemix", 0))
    {
        ALfloat maxout = 1.0f;
        for(s = 0;s < MAXCHANNELS;s++)
        {
            ALfloat out = 0.0f;
            for(s2 = 0;s2 < MAXCHANNELS;s2++)
                out += Device->ChannelMatrix[s2][s];
            maxout = __max(maxout, out);
        }

        maxout = 1.0f/maxout;
        for(s = 0;s < MAXCHANNELS;s++)
        {
            for(s2 = 0;s2 < MAXCHANNELS;s2++)
                Device->ChannelMatrix[s2][s] *= maxout;
        }
    }

    PanningLUT = Device->PanningLUT;
    for(pos = 0; pos < LUT_NUM; pos++)
    {
        /* clear all values */
        offset = MAXCHANNELS * pos;
        for(s = 0; s < MAXCHANNELS; s++)
            PanningLUT[offset+s] = 0.0f;

        if(Device->NumChan == 1)
        {
            PanningLUT[offset + Speaker2Chan[0]] = 1.0f;
            continue;
        }

        /* source angle */
        Theta = aluLUTpos2Angle(pos);

        /* set panning values */
        for(s = 0; s < Device->NumChan - 1; s++)
        {
            if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1])
            {
                /* source between speaker s and speaker s+1 */
                Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) /
                                 (SpeakerAngle[s+1]-SpeakerAngle[s]);
                PanningLUT[offset + Speaker2Chan[s]]   = cos(Alpha);
                PanningLUT[offset + Speaker2Chan[s+1]] = sin(Alpha);
                break;
            }
        }
        if(s == Device->NumChan - 1)
        {
            /* source between last and first speaker */
            if(Theta < SpeakerAngle[0])
                Theta += 2.0f * M_PI;
            Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) /
                             (2.0f * M_PI + SpeakerAngle[0]-SpeakerAngle[s]);
            PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha);
            PanningLUT[offset + Speaker2Chan[0]] = sin(Alpha);
        }
    }
}