Example #1
0
    void DspLimiter::Process(DspChunk& chunk)
    {
        if (chunk.IsEmpty())
            return;

        if (!m_exclusive || (chunk.GetFormat() != DspFormat::Float &&
                             chunk.GetFormat() != DspFormat::Double))
        {
            m_active = false;
            return;
        }

        m_active = true;

        // Analyze samples
        float peak;
        if (chunk.GetFormat() == DspFormat::Double)
        {
            double largePeak = GetPeak((double*)chunk.GetData(), chunk.GetSampleCount());
            peak = std::nexttoward((float)largePeak, largePeak);
        }
        else
        {
            assert(chunk.GetFormat() == DspFormat::Float);
            peak = GetPeak((float*)chunk.GetData(), chunk.GetSampleCount());
        }

        // Configure limiter
        if (peak > 1.0f)
        {
            if (m_holdWindow <= 0)
            {
                NewTreshold(std::max(peak, 1.4f));
            }
            else if (peak > m_peak)
            {
                NewTreshold(peak);
            }

            m_holdWindow = (int64_t)m_rate * m_channels * 10; // 10 seconds
        }

        // Apply limiter
        if (m_holdWindow > 0)
        {
            if (chunk.GetFormat() == DspFormat::Double)
            {
                ApplyLimiter<double>((double*)chunk.GetData(), chunk.GetSampleCount(), m_threshold);
            }
            else
            {
                assert(chunk.GetFormat() == DspFormat::Float);
                ApplyLimiter((float*)chunk.GetData(), chunk.GetSampleCount(), m_threshold);
            }

            m_holdWindow -= chunk.GetSampleCount();
        }
    }
Example #2
0
void DesignAudioBiquadIIR_q31_t(q31_t_IIR_Coefficients *C,// Pointer to the IIR Structure
                                uint8_t FilterType,
                                float Fs, //System Sample Rate
                                float f0, //("wherever it's happenin', man."  Center Frequency or
                                //Corner Frequency, or shelf midpoint frequency, depending
                                //on which filter type.  The "significant frequency".)*/
                                float Q,//(the EE kind of definition, except for peakingEQ in which A*Q is
                                // the classic EE Q.  That adjustment in definition was made so that
                                // a boost of N dB followed by a cut of N dB for identical Q and
                                // f0/Fs results in a precisely flat unity gain filter or "wire".)*/
                                float dBgain// (used only for peaking and shelving filters)
                               )
{
    A = sqrt(pow(10,(dBgain/40)));

    if(Fs == 0) Fs = 1000;

    if(Q == 0) Q = 1.0;

    w0 = 2.0*3.141592654*f0/Fs;
    alpha = sin(w0)/(2.0 * Q);

    switch(FilterType)
        {
            default:
            case BIQUAD_LOW_PASS_FILTER	:
                b0 =  (1 - cos(w0))/2;
                b1 =   1 - cos(w0);
                b2 =  (1 - cos(w0))/2;
                a0 =   1 + alpha;
                a1 =  -2*cos(w0);
                a2 =   1 - alpha;
                break;

            case   BIQUAD_HIGH_PASS_FILTER 	:
                b0 =  (1 + cos(w0))/2;
                b1 = -(1 + cos(w0));
                b2 =  (1 + cos(w0))/2;
                a0 =   1 + alpha;
                a1 =  -2*cos(w0);
                a2 =   1 - alpha;
                break;

            case         BIQUAD_BAND_PASS_FILTER_CONSTANT_SKIRT_GAIN_PEAKGAIN_Q	:
                b0 =   Q*alpha;
                b1 =   0;
                b2 =  -Q*alpha;
                a0 =   1 + alpha;
                a1 =  -2*cos(w0);
                a2 =   1 - alpha;
                break;

            case            BIQUAD_BAND_PASS_FILTER_CONSTANT_0_DB_PEAK_GAIN:
                b0 =   alpha;
                b1 =   0;
                b2 =  -alpha;
                a0 =   1 + alpha;
                a1 =  -2*cos(w0);
                a2 =   1 - alpha;
                break;

            case             BIQUAD_NOTCH_FILTER:
                b0 =   1;
                b1 =  -2*cos(w0);
                b2 =   1;
                a0 =   1 + alpha;
                a1 =  -2*cos(w0);
                a2 =   1 - alpha;
                break;

            case             BIQUAD_ALL_PASS_FILTER:
                b0 =   1 - alpha;
                b1 =  -2*cos(w0);
                b2 =   1 + alpha;
                a0 =   1 + alpha;
                a1 =  -2*cos(w0);
                a2 =   1 - alpha;
                break;

            case            BIQUAD_PEAKING_EQ:
                b0 =   1 + alpha*A;
                b1 =  -2*cos(w0);
                b2 =   1 - alpha*A;
                a0 =   1 + alpha/A;
                a1 =  -2*cos(w0);
                a2 =   1 - alpha/A;
                break;

            case            BIQUAD_LOW_SHELF:
                b0 =    A*( (A+1.0) - (A-1.0)*cos(w0) + 2.0*sqrt(A)*alpha );
                b1 =  2.0*A*( (A-1.0) - (A+1.0)*cos(w0)                   );
                b2 =    A*( (A+1.0) - (A-1.0)*cos(w0) - 2.0*sqrt(A)*alpha );
                a0 =        (A+1.0) + (A-1.0)*cos(w0) + 2.0*sqrt(A)*alpha;
                a1 =   -2.0*( (A-1.0) + (A+1.0)*cos(w0)                   );
                a2 =        (A+1.0) + (A-1.0)*cos(w0) - 2.0*sqrt(A)*alpha;
                break;

            case           BIQUAD_HIGH_SHELF:
                b0 =    A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
                b1 = -2*A*( (A-1) + (A+1)*cos(w0)                   );
                b2 =    A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
                a0 =        (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha;
                a1 =    2*( (A-1) - (A+1)*cos(w0)                   );
                a2 =        (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha;
                break;
        }

    /*
    The most straight forward implementation would be the "Direct Form 1"
    (Eq 2):

        y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2]
                            - (a1/a0)*y[n-1] - (a2/a0)*y[n-2]            (Eq 4)

    but to make things easier on the chip,  we will do all adds:

    	    y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2]
                            + (a1/a0)*y[n-1] + (a2/a0)*y[n-2]            (Eq 4)

                            THis means that 2 feedback coef. have to be inverted

      */
    b0 = b0/a0;
    b1 = b1/a0;
    b2 = b2/a0;
    a1 = a1/a0;
    a2 = a2/a0;
    a0 = 1.0;
    a1 = a1 * -1.0;
    a2 = a2 * -1.0;
    C->PostShift = 0;

    while(GetPeak(&coef[0],6) > 1.0)
        {
            C->PostShift++;
            b0 = b0/(float)(1<<C->PostShift);
            b1 = b1/(float)(1<<C->PostShift);
            b2 = b2/(float)(1<<C->PostShift);
            a1 = a1/(float)(1<<C->PostShift);
            a2 = a2/(float)(1<<C->PostShift);
            a0 = a0/(float)(1<<C->PostShift);
        }

    C->a[0] = (q31_t)(0x7FFFFFFF * a1); //a[0] in the IIR struct is actually a1
    C->a[1] = (q31_t)(0x7FFFFFFF * a2); //a[1] in the IIR struct is actually a2
    C->b[0] = (q31_t)(0x7FFFFFFF * b0);
    C->b[1] = (q31_t)(0x7FFFFFFF * b1);
    C->b[2] = (q31_t)(0x7FFFFFFF * b2);
    return;
}