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:
parent
1adf833d48
commit
9fcb83882a
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ private:
|
||||
int mFilterSubtype; // lowpass, highpass
|
||||
int mOrder;
|
||||
int mOrderIndex;
|
||||
ArrayOf<BiquadStruct> mpBiquad;
|
||||
ArrayOf<Biquad> mpBiquad;
|
||||
|
||||
double mdBMax;
|
||||
double mdBMin;
|
||||
|
Loading…
x
Reference in New Issue
Block a user