1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-31 16:09:28 +02:00

Refactor Biquad in preparation of EBU R128 loudness normalization.

This commit is contained in:
Max Maisel 2018-07-24 17:08:47 +02:00
parent 1adf833d48
commit 9fcb83882a
4 changed files with 56 additions and 55 deletions

View File

@ -2,31 +2,30 @@
#define square(a) ((a)*(a))
void Biquad_Process (BiquadStruct* pBQ, int iNumSamples)
Biquad::Biquad()
{
pfIn = 0;
pfOut = 0;
fNumerCoeffs[B0] = 1;
fNumerCoeffs[B1] = 0;
fNumerCoeffs[B2] = 0;
fDenomCoeffs[A1] = 0;
fDenomCoeffs[A2] = 0;
Reset();
}
void Biquad::Reset()
{
fPrevIn = 0;
fPrevPrevIn = 0;
fPrevOut = 0;
fPrevPrevOut = 0;
}
void Biquad::Process(int iNumSamples)
{
float* pfIn = pBQ->pfIn;
float* pfOut = pBQ->pfOut;
float fPrevIn = pBQ->fPrevIn;
float fPrevPrevIn = pBQ->fPrevPrevIn;
float fPrevOut = pBQ->fPrevOut;
float fPrevPrevOut = pBQ->fPrevPrevOut;
for (int i = 0; i < iNumSamples; i++)
{
float fIn = *pfIn++;
*pfOut = fIn * pBQ->fNumerCoeffs [0] +
fPrevIn * pBQ->fNumerCoeffs [1] +
fPrevPrevIn * pBQ->fNumerCoeffs [2] -
fPrevOut * pBQ->fDenomCoeffs [0] -
fPrevPrevOut * pBQ->fDenomCoeffs [1];
fPrevPrevIn = fPrevIn;
fPrevIn = fIn;
fPrevPrevOut = fPrevOut;
fPrevOut = *pfOut++;
}
pBQ->fPrevIn = fPrevIn;
pBQ->fPrevPrevIn = fPrevPrevIn;
pBQ->fPrevOut = fPrevOut;
pBQ->fPrevPrevOut = fPrevPrevOut;
*pfOut++ = ProcessOne(*pfIn++);
}
void ComplexDiv (float fNumerR, float fNumerI, float fDenomR, float fDenomI, float* pfQuotientR, float* pfQuotientI)

View File

@ -1,37 +1,44 @@
#ifndef __BIQUAD_H__
#define __BIQUAD_H__
#if 0
//initialisations not supported in MSVC 2013.
//Gives error C2905
// Do not make conditional on compiler.
typedef struct {
float* pfIn {};
float* pfOut {};
float fNumerCoeffs [3] { 1.0f, 0.0f, 0.0f }; // B0 B1 B2
float fDenomCoeffs [2] { 0.0f, 0.0f }; // A1 A2
float fPrevIn {};
float fPrevPrevIn {};
float fPrevOut {};
float fPrevPrevOut {};
} BiquadStruct;
#else
// WARNING: This structure may need initialisation.
typedef struct {
struct Biquad
{
Biquad();
void Reset();
void Process(int iNumSamples);
enum
{
/// Numerator coefficient indices
B0=0, B1, B2,
/// Denominator coefficient indices
A1=0, A2
};
inline float ProcessOne(float fIn)
{
float fOut = fIn * fNumerCoeffs[B0] +
fPrevIn * fNumerCoeffs[B1] +
fPrevPrevIn * fNumerCoeffs[B2] -
fPrevOut * fDenomCoeffs[A1] -
fPrevPrevOut * fDenomCoeffs[A2];
fPrevPrevIn = fPrevIn;
fPrevIn = fIn;
fPrevPrevOut = fPrevOut;
fPrevOut = fOut;
return fOut;
}
float* pfIn;
float* pfOut;
float fNumerCoeffs [3]; // B0 B1 B2
float fDenomCoeffs [2]; // A1 A2
float fNumerCoeffs[3]; // B0 B1 B2
float fDenomCoeffs[2]; // A1 A2, A0 == 1.0
float fPrevIn;
float fPrevPrevIn;
float fPrevOut;
float fPrevPrevOut;
} BiquadStruct;
#endif
};
void Biquad_Process (BiquadStruct* pBQ, int iNumSamples);
void ComplexDiv (float fNumerR, float fNumerI, float fDenomR, float fDenomI, float* pfQuotientR, float* pfQuotientI);
bool BilinTransform (float fSX, float fSY, float* pfZX, float* pfZY);
float Calc2D_DistSqr (float fX1, float fY1, float fX2, float fY2);

View File

@ -218,12 +218,7 @@ unsigned EffectScienFilter::GetAudioOutCount()
bool EffectScienFilter::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames WXUNUSED(chanMap))
{
for (int iPair = 0; iPair < (mOrder + 1) / 2; iPair++)
{
mpBiquad[iPair].fPrevIn = 0;
mpBiquad[iPair].fPrevPrevIn = 0;
mpBiquad[iPair].fPrevOut = 0;
mpBiquad[iPair].fPrevPrevOut = 0;
}
mpBiquad[iPair].Reset();
return true;
}
@ -235,7 +230,7 @@ size_t EffectScienFilter::ProcessBlock(float **inBlock, float **outBlock, size_t
{
mpBiquad[iPair].pfIn = ibuf;
mpBiquad[iPair].pfOut = outBlock[0];
Biquad_Process(&mpBiquad[iPair], blockLen);
mpBiquad[iPair].Process(blockLen);
ibuf = outBlock[0];
}

View File

@ -102,7 +102,7 @@ private:
int mFilterSubtype; // lowpass, highpass
int mOrder;
int mOrderIndex;
ArrayOf<BiquadStruct> mpBiquad;
ArrayOf<Biquad> mpBiquad;
double mdBMax;
double mdBMin;