diff --git a/include/ITABiquad.h b/include/ITABiquad.h index 9e505f0f041dda5cf8cc0f9f201a76a0999bd1b6..dfe37cab87b33675af68f385c003da418647a1b6 100644 --- a/include/ITABiquad.h +++ b/include/ITABiquad.h @@ -57,73 +57,64 @@ public: } oParams; - //! Überblendmodus der Ausgabe + //! Output write modes enum { - OUTPUT_OVERWRITE = 0, //!< Ausgabe überschreiben - OUTPUT_ADD = 1 //!< Ausgabe addieren - } OutputFadeMode; + OUTPUT_OVERWRITE = 0, //!< Overwrites output + OUTPUT_ADD = 1 //!< Adds to the output + }; - //! 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. - */ + //! Clears all accumulators void Clear(); - //! Filtert Samples, einfache Variante ohne Verstärkungsfaktoren + //! Filter samples, simple variant without any gain (factor) /** - * Filtert samples gemäß der Direkten Form 2 (Kanonische Form) + * Direct second canonical form. * - * \param in Eingabesamples - * \param in Ausgabesamples - * \param in Anzahl der Eingabe- und Ausgabesamples + * @param[in] pfInputData Input samples + * @param[out] pfOutputData Output samples + * @param[in] iNumSamples Number of samples to be processed * - * \note Eingabe- und Ausgabepuffer dürfen gleich sein + * @note Input and output samples must have same length */ void Process( const float* pfInputData, float* pfOutputData, const int iNumSamples ); - - //! Filtert Samples, Variante mit Überlenden zu einer vorgegebenen Ausgabeverstärkung + + //! Filter samples, simple variant with given gain (factor) /** - * \param in Eingabesamples - * \param out Ausgabesamples - * \param nsamples Anzahl der Eingabe- und Ausgabesamples - * \param outputGain Ausgabeverstärkung Ausgangsparameter - * \param outputMode Überblendmodus, eines aus #OutputFadeMode + * Direct second canonical form. + * + * @param[in] pfInputData Input samples + * @param[out] pfOutputData Output samples + * @param[in] iNumSamples Number of samples to be processed + * @param[in] fOutputGain Gain (factor) for output + * @param[in] iOutputMode Add to or overwrite output buffer * - * \note Verändern nicht den internen Verstärkungsfaktor #g (Gain) - * \note Eingabe- und Ausgabepuffer dürfen gleich sein + * @note Input and output samples must have same length */ void Process( const float* pfInputData, float* pfOutputData, const int iNumSamples, const float fOutputGain, const int iOutputMode ); - - //! Filtert Samples. Fette Variante (Ausgabemodus, Überblendung der Gains) + + + //! Filter samples, simple variant with given gain (factor) /** - * Filtert Samples und setzt gleichzeitig eine Verstärkungsänderung um. - * Interpoliert lineare zwischen Gain1 und Gain2 auf allen Samples. + * Direct second canonical form. * - * \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 + * @param[in] pfInputData Input samples + * @param[out] pfOutputData Output samples + * @param[in] iNumSamples Number of samples to be processed + * @param[in] fOutputGain1 Initial gain (factor) for output + * @param[in] fOutputGain2 Target gain (factor) for output + * @param[in] iOutputMode Add to or overwrite output buffer * - * \note Verändern nicht den internen Verstärkungsfaktor #g (Gain) - * \note Eingabe- und Ausgabepuffer dürfen gleich sein + * @note Input and output samples must have same length */ void Process( const float* pfInputData, float* pfOutputData, const int iNumSamples, const float fOutputGain1, const float fOutputGain2, const int iOutputMode ); private: - float z[ 2 ]; //!< Accumulators + float vfAccumulators[ 2 ]; //!< Accumulators }; #endif // IW_ITA_BIQUAD diff --git a/include/ITAThirdOctaveFilterbankFIR.h b/include/ITAThirdOctaveFilterbankFIR.h index 24083dfa4e9c1c3abc7148d70f6d74b6c7d74eaa..2e8757557a2e6cbfcc4866d43dae365b8a0cfd58 100644 --- a/include/ITAThirdOctaveFilterbankFIR.h +++ b/include/ITAThirdOctaveFilterbankFIR.h @@ -70,9 +70,9 @@ public: pFilter->Release(); // Auto-release } - inline virtual void SetMagnitudes( const CITAThirdOctaveMagnitudeSpectrum& oGains, const bool bSmoothChangeover = true ) + inline virtual void SetMagnitudes( const CITAThirdOctaveMagnitudeSpectrum& oMags, const bool bSmoothChangeover = true ) { - m_pGenerator->GenerateFilter( oGains, m_pfFilter ); + m_pGenerator->GenerateFilter( oMags, m_pfFilter ); ITAUPFilter* pFilter = m_pConvolver->RequestFilter(); pFilter->Load( m_pfFilter, m_iFilterLength ); m_pConvolver->ExchangeFilter( pFilter, ( bSmoothChangeover ? ITAUPConvolution::AUTO : ITAUPConvolution::SWITCH ) ); diff --git a/include/ITAThirdOctaveFilterbankIIR.h b/include/ITAThirdOctaveFilterbankIIR.h index 99125fcf9f6fb11f994c4ae219f07e86abd79ab9..cd6fb642464bc3ddf93f2fc324076b08f1a501b5 100644 --- a/include/ITAThirdOctaveFilterbankIIR.h +++ b/include/ITAThirdOctaveFilterbankIIR.h @@ -23,40 +23,38 @@ #include <ITAThirdOctaveFilterbank.h> #include <ITAAmplitudeSpectrum.h> #include <ITABiquad.h> +#include <ITASampleBuffer.h> #include <vector> #include <tbb/concurrent_queue.h> -//! Terzfilterbank mittels Biquads (IIR Filter) +//! Third octave magnitude filtering using Biquads (IIR filter) /** - * Diese Klasse realisiert eine Terzfilterbank (#CITAThirdOctaveFilterbank) mit der Methode der kaskadierten - * Biquads (#CITABiquad) für Verstärkungsfaktoren eines Terzbank-Betragsspektrums (#CITAThirdOctaveMagnitudeSpectrum). * */ class ITA_DSP_API CITAThirdOctaveFilterbankIIR : public CITAThirdOctaveFilterbank { public: - //! Konstruktor mit Samplerate und Blocklänge + //! Constructor /** - * \param dSamplerate Samplingrate - * \param iBlocklength Blocklänge + * @param[in] dSampleRate Samplingrate + * @param[in] iBlockLength Block length */ CITAThirdOctaveFilterbankIIR( const double dSampleRate, const int iBlockLength ); - //! Destruktor - virtual ~CITAThirdOctaveFilterbankIIR(); + virtual inline ~CITAThirdOctaveFilterbankIIR() {}; //! Filterlatenz in Samples zurückgeben int GetLatency() const; - //! Verstärkungen (Gains) setzen + //! Set magnitudes (in decibel) of filter bank /** - * \param oGains Verstärkungsfaktoren - * \param bSmoothChangeover Wenn true, dann überblenden (default), sonst sofort internen Gain umschalten + * @param[in] oMagnitudes Filter magnitudes (dB) + * @param[in] bSmoothChangeover If true, switching is smoothed */ - void SetMagnitudes( const CITAThirdOctaveMagnitudeSpectrum& oGains, const bool bSmoothChangeover = true ); + void SetMagnitudes( const CITAThirdOctaveMagnitudeSpectrum& oMagnitudes, const bool bSmoothChangeover = true ); - //! Alle internen Zustände zurücksetzen (Akkumulatoren der Biquads) + //! Clear all internal accumulators void Clear(); //! Verarbeite Samples (Filtern) @@ -68,7 +66,7 @@ public: private: //! Interne Datenklasse für das Verarbeiten eines neuen Gain Datensatzes - class GainUpdate + class MagnitudeUpdate { public: CITAThirdOctaveMagnitudeSpectrum oMags; //! New magnitudes @@ -79,11 +77,11 @@ private: int m_iBlockLength; //!< Blocklänge int m_nBandsInternal; //!< Anzahl der internen Bänder int m_nBiquadsPerBand; //!< Anzahl von Biqads pro Band - std::vector< CITABiquad > m_vBiquads; //!< Biquads, Zugriff: [Band][BiquadNummer] - tbb::strict_ppl::concurrent_queue< CITAThirdOctaveFilterbankIIR::GainUpdate > m_qGains; //!< Liste von neuen Verstärkungsfaktoren - CITAThirdOctaveMagnitudeSpectrum m_oGainsInternal; //!< Interne Verstärkungsfaktoren - float* m_pfTempFilterBuf; //!< Zwischenpuffer für Filter - float* m_pfTempOutputBuf; //!< Zwischenpuffer für Ausgabe + std::vector< CITABiquad > m_vBiquads; //!< Biquads, access: [Band][BiquadNummer] + tbb::strict_ppl::concurrent_queue< CITAThirdOctaveFilterbankIIR::MagnitudeUpdate > m_vMagnitudesQueue; //!< Liste von neuen Verstärkungsfaktoren + CITAThirdOctaveMagnitudeSpectrum m_oMagnitudesInternal; //!< Interne Verstärkungsfaktoren + ITASampleBuffer m_sfTempFilterBuf; //!< Intermediate buffer for filter + ITASampleBuffer m_pfTempOutputBuf; //!< Intermediate buffer for output assembly }; #endif // IW_ITA_THIRD_OCTAVE_FILTERBANK_IIR diff --git a/src/ITABiquad.cpp b/src/ITABiquad.cpp index b85594d35de3670820d8100ba3ff852de852557f..dccf0a33d7a10f8205f2fbc50500694fc608a3bc 100644 --- a/src/ITABiquad.cpp +++ b/src/ITABiquad.cpp @@ -1,4 +1,5 @@ #include <ITABiquad.h> +#include <ITAException.h> CITABiquad::CITABiquad() { @@ -7,127 +8,131 @@ CITABiquad::CITABiquad() void CITABiquad::Clear() { - z[ 0 ] = z[ 1 ] = 0; + vfAccumulators[ 0 ] = vfAccumulators[ 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] + // Local accumulators + float z0, z1, z2; - // Lokale Akkumulatoren mit gespeicherten Werten besetzen - z1 = z[ 0 ]; - z2 = z[ 1 ]; + z1 = vfAccumulators[ 0 ]; + z2 = vfAccumulators[ 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; + 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; + pfOutputData[ i ] = oParams.b0 * z0 + oParams.b1 * z1 + oParams.b2 * z2; - // Akkumulatoren schieben + // Shift accumulators z2 = z1; z1 = z0; } - // Akkumulatoren für den nächsten Filterprozess speichern - z[ 0 ] = z1; - z[ 1 ] = z2; + // Store accumulators + vfAccumulators[ 0 ] = z1; + vfAccumulators[ 1 ] = z2; return; } -void CITABiquad::Process( const float* pfInputData, float* out, const int nsamples, const float outputGain, const int outputMode ) +void CITABiquad::Process( const float* pfInputData, float* pfOutputData, const int iNumSamples, const float fOutputGain, const int iOutputMode ) { - // Lokale Akkumulatoren + // Local accumulators float z0, z1, z2; - z1 = z[ 0 ]; - z2 = z[ 1 ]; - if( outputMode == OUTPUT_ADD ) + z1 = vfAccumulators[ 0 ]; + z2 = vfAccumulators[ 1 ]; + + if( iOutputMode == CITABiquad::OUTPUT_ADD ) { - // Modus: Addieren - for( int i = 0; i < nsamples; i++ ) + for( int i = 0; i < iNumSamples; i++ ) { - z0 = oParams.g*pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2; - out[ i ] += ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * outputGain; + z0 = oParams.g * pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2; + pfOutputData[ i ] += ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * fOutputGain; - // Akkumulatoren schieben + // Shift accumulators z2 = z1; z1 = z0; } } - else + else if( iOutputMode == CITABiquad::OUTPUT_OVERWRITE ) { - // Modus: Überschreiben - for( int i = 0; i < nsamples; i++ ) + for( int i = 0; i < iNumSamples; i++ ) { z0 = oParams.g*pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2; - out[ i ] = ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * outputGain; + pfOutputData[ i ] = ( oParams.b0 * z0 + oParams.b1 * z1 + oParams.b2*z2 ) * fOutputGain; - // Akkumulatoren schieben + // Shift accumulators z2 = z1; z1 = z0; } } + else + { + ITA_EXCEPT1( INVALID_PARAMETER, "Unrecognized output write mode in CITABiquad" ); + } - // Akkumulatoren global speichern - z[ 0 ] = z1; - z[ 1 ] = z2; + // Store accumulators + vfAccumulators[ 0 ] = z1; + vfAccumulators[ 1 ] = z2; return; } -void CITABiquad::Process( const float* pfInputData, float* out, const int nsamples, const float outputGain1, const float outputGain2, const int outputMode ) +void CITABiquad::Process( const float* pfInputData, float* out, const int iNumSamples, const float fOutputGain1, const float fOutputGain2, const int iOutputWriteMode ) { - if( nsamples == 0 ) + if( iNumSamples == 0 ) return; - // Lokale Akkumulatoren + // Local accumulators float z0, z1, z2; - z1 = z[ 0 ]; - z2 = z[ 1 ]; + z1 = vfAccumulators[ 0 ]; + z2 = vfAccumulators[ 1 ]; - // Faktor für Linear-Interpolation des Gains - float c = ( outputGain2 - outputGain1 ) / nsamples; // @todo jst: integer rounding desired? + // Factor for linear gain + const float fLinearGainFactor = ( fOutputGain2 - fOutputGain1 ) / float( iNumSamples ); - if( outputMode == OUTPUT_ADD ) + if( iOutputWriteMode == OUTPUT_ADD ) { - // Modus: Addieren - for( int i = 0; i < nsamples; i++ ) + for( int i = 0; i < iNumSamples; i++ ) { - float sampleGain = outputGain1 + i*c; + const float fSampleGain = fOutputGain1 + i * fLinearGainFactor; z0 = oParams.g*pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2; - out[ i ] += ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * sampleGain; + out[ i ] += ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * fSampleGain; - // Akkumulatoren schieben + // Shift accumulators z2 = z1; z1 = z0; } } - else + else if( iOutputWriteMode == CITABiquad::OUTPUT_OVERWRITE ) { - // Modus: Überschreiben - for( int i = 0; i < nsamples; i++ ) + for( int i = 0; i < iNumSamples; i++ ) { - float sampleGain = outputGain1 + i*c; + const float fSampleGain = fOutputGain1 + i * fLinearGainFactor; z0 = oParams.g*pfInputData[ i ] - oParams.a1*z1 - oParams.a2*z2; - out[ i ] = ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * sampleGain; + out[ i ] = ( oParams.b0*z0 + oParams.b1*z1 + oParams.b2*z2 ) * fSampleGain; - // Akkumulatoren schieben + // Shift accumulators z2 = z1; z1 = z0; } } + else + { + ITA_EXCEPT1( INVALID_PARAMETER, "Unrecognized output write mode in CITABiquad" ); + } - // Akkumulatoren global speichern - z[ 0 ] = z1; - z[ 1 ] = z2; + // Store accumulators + vfAccumulators[ 0 ] = z1; + vfAccumulators[ 1 ] = z2; } CITABiquad::CParams::CParams() diff --git a/src/ITAThirdOctaveFilterbankCoefficients.h b/src/ITAThirdOctaveFilterbankCoefficients.h index 2485b3460cfd2d29cbd2829dc54a65702edfec79..3ba248b0033cc609d76f048dc89736244ef1f829 100644 --- a/src/ITAThirdOctaveFilterbankCoefficients.h +++ b/src/ITAThirdOctaveFilterbankCoefficients.h @@ -1,12 +1,12 @@ #ifndef IW_ITA_THIRD_OCTAVE_FILTERBANK_COEFFICIENTS #define IW_ITA_THIRD_OCTAVE_FILTERBANK_COEFFICIENTS -const double FB_SAMPLINGRATE = 44100; //!< Samplingrate -const int FB_NUM_BANDS = 30; //!< Anzahl Frequenzb�nder -const int FB_NUM_BIQUADS_PER_BAND = 5; //!< Anzahl Biquads pro Frequenzband +const double ITA_BIQUAD_FILTER_SAMPLINGRATE = 44100; +const int ITA_BIQUAD_FILTER_NUM_BANDS = 30; +const int ITA_BIQUAD_FILTER_NUM_BIQUADS_PER_BAND = 5; -//!< Parameters (g, b0, b1, b2, a0, a1) for biquad bandpasses, 10th order Buttworth design, Zugriff: [Band][Biquad][Param] -const float FB_BIQUAD_PARAMS[ 30 ][ 5 ][ 6 ] = +//!< Parameters (g, b0, b1, b2, a0, a1) for biquad bandpasses, 10th order Buttworth design, access: [Band][Biquad][Param] +const float ITA_BIQUAD_FILTER_PARAMS[ 30 ][ 5 ][ 6 ] = { { // Band 1, center frequency 25.1 Hz { 0.000412886359F, 1.000000000000F, 0.000000000000F, -1.000000000000F, -1.999701032925F, 0.999716977654F }, diff --git a/src/ITAThirdOctaveFilterbankIIR.cpp b/src/ITAThirdOctaveFilterbankIIR.cpp index 9db12332a35d1fb11f0f0ad82f6cb85a5acaf1d4..1b1ca6d4da4bc141c0d36ffed63223ca623fd42e 100644 --- a/src/ITAThirdOctaveFilterbankIIR.cpp +++ b/src/ITAThirdOctaveFilterbankIIR.cpp @@ -12,52 +12,40 @@ CITAThirdOctaveFilterbankIIR::CITAThirdOctaveFilterbankIIR( const double dSampleRate, const int iBlockLength ) : m_dSampleRate( dSampleRate ), m_iBlockLength( iBlockLength ), - m_nBandsInternal( FB_NUM_BANDS ), - m_nBiquadsPerBand( FB_NUM_BIQUADS_PER_BAND ), - m_pfTempFilterBuf( nullptr ), - m_pfTempOutputBuf( nullptr ) + m_nBandsInternal( ITA_BIQUAD_FILTER_NUM_BANDS ), + m_nBiquadsPerBand( ITA_BIQUAD_FILTER_NUM_BIQUADS_PER_BAND ) { - if( dSampleRate != FB_SAMPLINGRATE ) + if( dSampleRate != ITA_BIQUAD_FILTER_SAMPLINGRATE ) ITA_EXCEPT1( INVALID_PARAMETER, "Filterbank does not support this samplingrate" ); // Initialize biquads - int nBiquads = m_nBandsInternal*m_nBiquadsPerBand; + int nBiquads = m_nBandsInternal * m_nBiquadsPerBand; m_vBiquads.resize( nBiquads ); for( int i = 0; i < m_nBandsInternal; i++ ) - { for( int j = 0; j < m_nBiquadsPerBand; j++ ) - { - m_vBiquads[ i*m_nBiquadsPerBand + j ].oParams.SetParameters( FB_BIQUAD_PARAMS[ i ][ j ] ); - } - } + m_vBiquads[ i * m_nBiquadsPerBand + j ].oParams.SetParameters( ITA_BIQUAD_FILTER_PARAMS[ i ][ j ] ); - m_pfTempFilterBuf = fm_falloc( m_iBlockLength, true ); - m_pfTempOutputBuf = fm_falloc( m_iBlockLength, true ); -} - -CITAThirdOctaveFilterbankIIR::~CITAThirdOctaveFilterbankIIR() -{ - fm_free( m_pfTempFilterBuf ); - fm_free( m_pfTempOutputBuf ); + m_sfTempFilterBuf.Init( m_iBlockLength, true ); + m_pfTempOutputBuf.Init( m_iBlockLength, true ); } int CITAThirdOctaveFilterbankIIR::GetLatency() const { - return 0; // [stienen] sicher? + return 0; // @todo jst: really? } -void CITAThirdOctaveFilterbankIIR::SetMagnitudes( const CITAThirdOctaveMagnitudeSpectrum& oMagnitudes, bool bSmoothChangeover ) +void CITAThirdOctaveFilterbankIIR::SetMagnitudes( const CITAThirdOctaveMagnitudeSpectrum& oMagnitudes, const bool bSmoothChangeover ) { - CITAThirdOctaveFilterbankIIR::GainUpdate oUpdate; + CITAThirdOctaveFilterbankIIR::MagnitudeUpdate oUpdate; oUpdate.oMags = oMagnitudes; oUpdate.iBlendSamples = ( bSmoothChangeover ? 1 : 0 ); - m_qGains.push( oUpdate ); + m_vMagnitudesQueue.push( oUpdate ); } void CITAThirdOctaveFilterbankIIR::Clear() { - for( int i = 0; i < ( int ) - m_vBiquads.size(); i++ ) m_vBiquads[ i ].Clear(); + for( size_t i = 0; i < m_vBiquads.size(); i++ ) + m_vBiquads[ i ].Clear(); } void CITAThirdOctaveFilterbankIIR::Process( const float* pfInputSamples, float* pfOutputSamples ) @@ -68,38 +56,33 @@ void CITAThirdOctaveFilterbankIIR::Process( const float* pfInputSamples, float* // F�r Schleifen unten assert( m_nBiquadsPerBand >= 2 ); - // TODO: Fehler l�sen. Warum kommt aus den hohen B�ndern nix? Scheinen nicht stabil zu sein?! const int iMaxBand = m_nBandsInternal - 1; - //const int iMaxBand = 10; - const int k = m_nBiquadsPerBand - 1; // Index des letzten Biquads pro Band - - if( m_nBandsInternal == 0 ) - return; // [stienen] lieber assert? Filter ohne B�nder? - - // Gains �bernehmen - CITAThirdOctaveFilterbankIIR::GainUpdate oUpdate; + const int iLastBandIndex = m_nBiquadsPerBand - 1; + + // Empty queue and use latest magnitude update + CITAThirdOctaveFilterbankIIR::MagnitudeUpdate oLatestMagnitudeUpdate; bool bUpdateGains = false; - while( m_qGains.try_pop( oUpdate ) ) + while( m_vMagnitudesQueue.try_pop( oLatestMagnitudeUpdate ) ) bUpdateGains = true; + // Processing will first work through the biquads per band and then add samples target buffer at last biquad of band + if( bUpdateGains ) { - bool bSwitchGains = ( oUpdate.iBlendSamples == 0 ); + bool bSwitchGains = ( oLatestMagnitudeUpdate.iBlendSamples == 0 ); if( bSwitchGains ) { for( int i = 0; i < iMaxBand; i++ ) { - // Erster Biquad in der Sequenz: input => tmp - m_vBiquads[ i*m_nBiquadsPerBand + 0 ].Process( pfInputSamples, m_pfTempFilterBuf, m_iBlockLength ); + m_vBiquads[ i*m_nBiquadsPerBand + 0 ].Process( pfInputSamples, m_sfTempFilterBuf.GetData(), m_iBlockLength ); - // Biquads dazwischen: tmp => tmp - for( int j = 1; j < k; j++ ) - m_vBiquads[ i*m_nBiquadsPerBand + j ].Process( m_pfTempFilterBuf, m_pfTempFilterBuf, m_iBlockLength ); + for( int j = 1; j < iLastBandIndex; j++ ) + m_vBiquads[ i*m_nBiquadsPerBand + j ].Process( m_sfTempFilterBuf.GetData(), m_sfTempFilterBuf.GetData(), m_iBlockLength ); - // Letztes Biquad mit Gain: tmp => output - const float fGain = float( db10_to_ratio( oUpdate.oMags[ i ] ) ); - m_vBiquads[ i*m_nBiquadsPerBand + k ].Process( m_pfTempFilterBuf, m_pfTempOutputBuf, m_iBlockLength, fGain, ( i == 0 ? CITABiquad::OUTPUT_OVERWRITE : CITABiquad::OUTPUT_ADD ) ); + const float fGain = float( db10_to_ratio( oLatestMagnitudeUpdate.oMags[ i ] ) ); + const int iOutputWriteMode = ( i == 0 ? CITABiquad::OUTPUT_OVERWRITE : CITABiquad::OUTPUT_ADD ); + m_vBiquads[ i*m_nBiquadsPerBand + iLastBandIndex ].Process( m_sfTempFilterBuf.GetData(), m_pfTempOutputBuf.GetData(), m_iBlockLength, fGain, iOutputWriteMode ); } } else @@ -108,20 +91,20 @@ void CITAThirdOctaveFilterbankIIR::Process( const float* pfInputSamples, float* for( int i = 0; i < iMaxBand; i++ ) { // Erster Biquad in der Sequenz: input => tmp - m_vBiquads[ i*m_nBiquadsPerBand + 0 ].Process( pfInputSamples, m_pfTempFilterBuf, m_iBlockLength ); + m_vBiquads[ i*m_nBiquadsPerBand + 0 ].Process( pfInputSamples, m_sfTempFilterBuf, m_iBlockLength ); // Biquads dazwischen: tmp => tmp - for( int j = 1; j < k; j++ ) - m_vBiquads[ i*m_nBiquadsPerBand + j ].Process( m_pfTempFilterBuf, m_pfTempFilterBuf, m_iBlockLength ); + for( int j = 1; j < iLastBandIndex; j++ ) + m_vBiquads[ i*m_nBiquadsPerBand + j ].Process( m_sfTempFilterBuf, m_sfTempFilterBuf, m_iBlockLength ); // Letztes Biquad mit Gain: tmp => output - const float fGain1 = m_oGainsInternal[ i ]; - const float fGain2 = float( db10_to_ratio( oUpdate.oMags[ i ] ) ); - m_vBiquads[ i*m_nBiquadsPerBand + k ].Process( m_pfTempFilterBuf, m_pfTempOutputBuf, m_iBlockLength, fGain1, fGain2, ( i == 0 ? CITABiquad::OUTPUT_OVERWRITE : CITABiquad::OUTPUT_ADD ) ); + const float fGain1 = m_oMagnitudesInternal[ i ]; + const float fGain2 = float( db10_to_ratio( oLatestMagnitudeUpdate.oMags[ i ] ) ); + m_vBiquads[ i*m_nBiquadsPerBand + iLastBandIndex ].Process( m_sfTempFilterBuf.GetData(), m_pfTempOutputBuf.GetData(), m_iBlockLength, fGain1, fGain2, ( i == 0 ? CITABiquad::OUTPUT_OVERWRITE : CITABiquad::OUTPUT_ADD ) ); } } - m_oGainsInternal = oUpdate.oMags; + m_oMagnitudesInternal = oLatestMagnitudeUpdate.oMags; } else { @@ -129,17 +112,17 @@ void CITAThirdOctaveFilterbankIIR::Process( const float* pfInputSamples, float* for( int i = 0; i < iMaxBand; i++ ) { // Erster Biquad in der Sequenz: input => tmp - m_vBiquads[ i*m_nBiquadsPerBand + 0 ].Process( pfInputSamples, m_pfTempFilterBuf, m_iBlockLength ); + m_vBiquads[ i*m_nBiquadsPerBand + 0 ].Process( pfInputSamples, m_sfTempFilterBuf.GetData(), m_iBlockLength ); // Biquads dazwischen: tmp => tmp - for( int j = 1; j < k; j++ ) - m_vBiquads[ i*m_nBiquadsPerBand + j ].Process( m_pfTempFilterBuf, m_pfTempFilterBuf, m_iBlockLength ); + for( int j = 1; j < iLastBandIndex; j++ ) + m_vBiquads[ i*m_nBiquadsPerBand + j ].Process( m_sfTempFilterBuf.GetData(), m_sfTempFilterBuf.GetData(), m_iBlockLength ); // Letztes Biquad mit Gain: tmp => output - m_vBiquads[ i*m_nBiquadsPerBand + k ].Process( m_pfTempFilterBuf, m_pfTempOutputBuf, m_iBlockLength, m_oGainsInternal[ i ], ( i == 0 ? CITABiquad::OUTPUT_OVERWRITE : CITABiquad::OUTPUT_ADD ) ); + m_vBiquads[ i*m_nBiquadsPerBand + iLastBandIndex ].Process( m_sfTempFilterBuf.GetData(), m_pfTempOutputBuf.GetData(), m_iBlockLength, m_oMagnitudesInternal[ i ], ( i == 0 ? CITABiquad::OUTPUT_OVERWRITE : CITABiquad::OUTPUT_ADD ) ); } } - // Ausgabe bereitstellen - memcpy( pfOutputSamples, m_pfTempOutputBuf, m_iBlockLength*sizeof( float ) ); + // Hand over output samples + fm_copy( pfOutputSamples, m_pfTempOutputBuf.GetData(), m_iBlockLength ); } diff --git a/tests/ITADSPThirdOctaveFilterbankTest.cpp b/tests/ITADSPThirdOctaveFilterbankTest.cpp index 84e81447964d92c55e9e24147f2fc2e8eca05be0..83cca29595acf72235970e4c9113550331a734a4 100644 --- a/tests/ITADSPThirdOctaveFilterbankTest.cpp +++ b/tests/ITADSPThirdOctaveFilterbankTest.cpp @@ -31,7 +31,7 @@ void TestThirdOctaveFilterbankIIR() CITAThirdOctaveMagnitudeSpectrum oMags; oMags.SetIdentity(); - pIIRFilterbank->SetMagnitudes( oMags ); + pIIRFilterbank->SetMagnitudes( oMags, false ); ITASampleBuffer y( iSampleLength ); @@ -45,8 +45,7 @@ void TestThirdOctaveFilterbankIIR() writeAudiofile( "ITADSPThirdOctaveFilterbankTest_IIR_Identity.wav", &y, g_dSampleRate ); y.Zero(); - delete pIIRFilterbank; - pIIRFilterbank = CITAThirdOctaveFilterbank::Create( g_dSampleRate, iSampleLength, CITAThirdOctaveFilterbank::IIR_BIQUADS_ORDER10 ); + pIIRFilterbank->Clear(); oMags.SetZero(); pIIRFilterbank->SetMagnitudes( oMags ); @@ -59,8 +58,7 @@ void TestThirdOctaveFilterbankIIR() y.Normalize(); writeAudiofile( "ITADSPThirdOctaveFilterbankTest_IIR_Zeros.wav", &y, g_dSampleRate ); - delete pIIRFilterbank; - pIIRFilterbank = CITAThirdOctaveFilterbank::Create( g_dSampleRate, iSampleLength, CITAThirdOctaveFilterbank::IIR_BIQUADS_ORDER10 ); + pIIRFilterbank->Clear(); // dB values oMags[ 3 ] = 3.0f;