Commit 909df859 authored by Dipl.-Ing. Jonas Stienen's avatar Dipl.-Ing. Jonas Stienen
Browse files

Adding ÍIR biquad filtering components

parent 6c9da095
......@@ -17,9 +17,11 @@ include_directories( "include" )
set( ITADSPHeader
"include/ITADSPDefinitions.h"
"include/ITASIMOVariableDelayLine.h"
"include/ITABiquad.h"
)
set( ITADSPSources
"src/ITASIMOVariableDelayLine.cpp"
"src/ITABiquad.cpp"
)
......
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2017
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef IW_ITA_BIQUAD
#define IW_ITA_BIQUAD
#include <ITADSPDefinitions.h>
//! Implements digital biquad component for IIR filtering
/**
* @todo jst: translate comments to English.
*
* Diese Klasse realisiert ein Biquad IIR Filter. Es hat einen globalen Verstärkungsfaktor (Gain),
* damit eine Kaskadierung vieler Biquads zur Bandfilterung benutzt werden kann.
* Die Umsetzung erfolgt in Kanonischer Form, um möglichst wenig Multiplizierer/Addierer und
* Verzögerer zu benutzen.
*/
class ITA_DSP_API CITABiquad
{
public:
// [stienen] Atomic? Lock? ... cpp Datei?
class ITA_DSP_API CParams
{
public:
float g; //!< Verstärkungsfaktor (Gain)
float a1; //!< Nenner-Koeffizient 1
float a2; //!< Nenner-Koeffizient 2
float b0; //!< Zähler-Koeffizient 0
float b1; //!< Zähler-Koeffizient 1
float b2; //!< Zähler-Koeffizient 2
CParams();
//! Parameter setzen
/**
* \param params Filterparameter/Koeffizienten, Reihenfolge: g, b0, b1, b2, a1, a2
*
* \note Reihenfolge der Parameter beachten
*/
void SetParameters( const float params[] );
} oParams;
//! Überblendmodus der Ausgabe
enum
{
OUTPUT_OVERWRITE = 0, //!< Ausgabe überschreiben
OUTPUT_ADD = 1 //!< Ausgabe addieren
} OutputFadeMode;
//! Standardkonstruktor
/**
* Setzt interne Werte und Koeffizienten für
* einen idealen Übertrager
*/
CITABiquad();
//! Destruktor
virtual inline ~CITABiquad() {};
//! Löscht alle internen Puffer
/**
* Setzt Akkumulatoren auf 0.
*/
void Clear();
//! Filtert Samples, einfache Variante ohne Verstärkungsfaktoren
/**
* Filtert samples gemäß der Direkten Form 2 (Kanonische Form)
*
* \param in Eingabesamples
* \param in Ausgabesamples
* \param in Anzahl der Eingabe- und Ausgabesamples
*
* \note Eingabe- und Ausgabepuffer dürfen gleich sein
*/
void Process( const float* pfInputData, float* pfOutputData, const int iNumSamples );
//! Filtert Samples, Variante mit Überlenden zu einer vorgegebenen Ausgabeverstärkung
/**
* \param in Eingabesamples
* \param out Ausgabesamples
* \param nsamples Anzahl der Eingabe- und Ausgabesamples
* \param outputGain Ausgabeverstärkung Ausgangsparameter
* \param outputMode Überblendmodus, eines aus #OutputFadeMode
*
* \note Verändern nicht den internen Verstärkungsfaktor #g (Gain)
* \note Eingabe- und Ausgabepuffer dürfen gleich sein
*/
void Process( const float* pfInputData, float* pfOutputData, const int iNumSamples, const float fOutputGain, const int iOutputMode );
//! Filtert Samples. Fette Variante (Ausgabemodus, Überblendung der Gains)
/**
* Filtert Samples und setzt gleichzeitig eine Verstärkungsänderung um.
* Interpoliert lineare zwischen Gain1 und Gain2 auf allen Samples.
*
* \param in Eingabesamples
* \param out Ausgabesamples
* \param nsamples Anzahl der Eingabe- und Ausgabesamples
* \param outputGain1 Ausgabeverstärkung Ausgangsparameter
* \param outputGain2 Ausgabeverstärkung Zielparameter
* \param outputMode Überblendmodus, eines aus #OutputFadeMode
*
* \note Verändern nicht den internen Verstärkungsfaktor #g (Gain)
* \note Eingabe- und Ausgabepuffer dürfen gleich sein
*/
void Process( const float* pfInputData, float* pfOutputData, const int iNumSamples, const float fOutputGain1, const float fOutputGain2, const int iOutputMode );
private:
float z[ 2 ]; //!< Accumulators
};
#endif // IW_ITA_BIQUAD
......@@ -20,7 +20,7 @@
#define INCLUDE_WATCHER_ITA_DSP_DEFINITIONS
#if ( defined WIN32 ) && !( defined ITA_BASE_STATIC )
#ifdef ITA_BASE_EXPORT
#ifdef ITA_DSP_EXPORT
#define ITA_DSP_API __declspec( dllexport )
#else
#define ITA_DSP_API __declspec( dllimport )
......
#include <ITABiquad.h>
CITABiquad::CITABiquad()
{
Clear();
}
void CITABiquad::Clear()
{
z[ 0 ] = z[ 1 ] = 0;
}
void CITABiquad::Process( const float* pfInputData, float* pfOutputData, const int iNumSamples )
{
// Lokale Akkumulatoren erzeugen
float z0, z1, z2; // w[n], w[n-1], w[n-2]
// Lokale Akkumulatoren mit gespeicherten Werten besetzen
z1 = z[ 0 ];
z2 = z[ 1 ];
for( int i = 0; i < iNumSamples; i++ )
{
// w[n] = x[n] - a_1*w[n-1] - a_2*w[n-2]
z0 = oParams.g*pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2;
// y[n] = b_0*w[n] + b_1*w[n-1] + b_2*w[n-2]
pfOutputData[ i ] = oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2;
// Akkumulatoren schieben
z2 = z1;
z1 = z0;
}
// Akkumulatoren für den nächsten Filterprozess speichern
z[ 0 ] = z1;
z[ 1 ] = z2;
return;
}
void CITABiquad::Process( const float* pfInputData, float* out, int nsamples, float outputGain, int outputMode )
{
// Lokale Akkumulatoren
float z0, z1, z2;
z1 = z[ 0 ];
z2 = z[ 1 ];
if( outputMode == OUTPUT_ADD )
{
// Modus: Addieren
for( int i = 0; i < nsamples; i++ )
{
z0 = oParams.g*pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2;
out[ i ] += ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * outputGain;
// Akkumulatoren schieben
z2 = z1;
z1 = z0;
}
}
else
{
// Modus: Überschreiben
for( int i = 0; i < nsamples; i++ )
{
z0 = oParams.g*pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2;
out[ i ] = ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * outputGain;
// Akkumulatoren schieben
z2 = z1;
z1 = z0;
}
}
// Akkumulatoren global speichern
z[ 0 ] = z1;
z[ 1 ] = z2;
return;
}
void CITABiquad::Process( const float* pfInputData, float* out, int nsamples, float outputGain1, float outputGain2, int outputMode )
{
if( nsamples == 0 )
return;
// Lokale Akkumulatoren
float z0, z1, z2;
z1 = z[ 0 ];
z2 = z[ 1 ];
// Faktor für Linear-Interpolation des Gains
float c = ( outputGain2 - outputGain1 ) / nsamples; // @todo jst: integer rounding desired?
if( outputMode == OUTPUT_ADD )
{
// Modus: Addieren
for( int i = 0; i < nsamples; i++ )
{
float sampleGain = outputGain1 + i*c;
z0 = oParams.g*pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2;
out[ i ] += ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * sampleGain;
// Akkumulatoren schieben
z2 = z1;
z1 = z0;
}
}
else
{
// Modus: Überschreiben
for( int i = 0; i < nsamples; i++ )
{
float sampleGain = outputGain1 + i*c;
z0 = oParams.g*pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2;
out[ i ] = ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * sampleGain;
// Akkumulatoren schieben
z2 = z1;
z1 = z0;
}
}
// Akkumulatoren global speichern
z[ 0 ] = z1;
z[ 1 ] = z2;
}
CITABiquad::CParams::CParams()
: g( 1 )
, a1( 0 )
, a2( 0 )
, b0( 1 )
, b1( 0 )
, b2( 0 )
{
}
void CITABiquad::CParams::SetParameters( const float params[] )
{
g = params[ 0 ];
b0 = params[ 1 ];
b1 = params[ 2 ];
b2 = params[ 3 ];
a1 = params[ 4 ];
a2 = params[ 5 ];
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment