diff --git a/include/DSMBCConvolver.h b/include/DSMBCConvolver.h index 50596b3e621fcaa6485f80b7df3e8532d06f5d35..fc4ef447a2c4c333049ea0c429f308088e59f1f2 100644 --- a/include/DSMBCConvolver.h +++ b/include/DSMBCConvolver.h @@ -46,7 +46,7 @@ class ITAFFT; * Nebenlüufigkeit & Synchronisation: * * Folgende Methoden sind synchronisiert: - * + * * - getFilterPool, setFilterPool, requestFilter, releaseFilter => Blocking aber leichtgewichtig, reentrant * - getFilterExchangeMode, setFilterExchangeMode, getFilterCrossfadeLength, setFilterCrossfadeLength, * getActiveFilter, exchangeFilter => Non-blocking und wait-free, reentrant @@ -57,22 +57,25 @@ class ITAFFT; * Müchtest Du mehr zu den Details wissen? Frag mich! -> Frank.Wefers@akustik.rwth-aachen.de */ -class ITA_CONVOLUTION_API DSMBCConvolver : public ITAUncopyable { +class ITA_CONVOLUTION_API DSMBCConvolver : public ITAUncopyable +{ public: //! Austausch-Modi - enum { + enum + { SWITCH = 0, //!< Hartes Umschalten CROSSFADE_LINEAR, //!< Lineare Kreuzblende CROSSFADE_COSINE_SQUARE //!< Cosinus-Quadrat Kreuzblende }; - + //! Ausgabe-Modi - enum { + enum + { OUTPUT_OVERWRITE = 0, //!< Daten im Ausgabepuffer mit neuen Daten überschreiben OUTPUT_MIX, //!< Neue Daten in den Ausgabepuffer einmischen }; - static const int AUTO=-1; + static const int AUTO = -1; //! Standard-Konstruktor /** @@ -87,7 +90,7 @@ public: * \param iBlocklength Blocklänge [in Samples] * \param iMaxFilterlength Maximale Filterlänge [Anzahl Filterkoeffizienten] */ - DSMBCConvolver(int iBlocklength, int iMaxFilterlength, DSMBCFilterPool* pFilterPool=NULL); + DSMBCConvolver( const int iBlocklength, const int iMaxFilterlength, DSMBCFilterPool* pFilterPool = NULL ); //! Destruktor virtual ~DSMBCConvolver(); @@ -99,7 +102,7 @@ public: * \param iBlocklength Blocklänge [in Samples] * \param iMaxFilterlength Maximale Filterlänge [Anzahl Filterkoeffizienten] */ - void init(int iBlocklength, int iFilterLength); + void init( const int iBlocklength, const int iFilterLength ); //! Blocklänge zurückgeben int getBlocklength() const; @@ -111,19 +114,19 @@ public: const DSMBCTrigger* getFilterExchangeTrigger() const; //! Trigger für den Filteraustausch setzen - void setFilterExchangeTrigger(const DSMBCTrigger* pTrigger); + void setFilterExchangeTrigger( const DSMBCTrigger* pTrigger ); //! Filteraustausch-Modus zurückgeben int getFilterExchangeMode(); //! Filteraustausch-Modus setzen - void setFilterExchangeMode(int iMode); + void setFilterExchangeMode( const int iMode ); //! überblendlänge [Samples] des Filteraustauschs zurückgeben int getFilterCrossfadeLength(); //! überblendlänge [Samples] für den Filteraustausch setzen - void setFilterCrossfadeLength(int iLength); + void setFilterCrossfadeLength( const int iLength ); //! Verstärkung zurückgeben float getGain() const; @@ -131,7 +134,7 @@ public: //! Verstärkung setzen // Hinweis: Falls bSetImmediately==true gesetzt, wird die Verstärkung nicht // dynamisch angepasst, sondern hart auf den angegebenen Wert gesetzt. - void setGain(float fGain, bool bSetImmediately=false); + void setGain( const float fGain, const bool bSetImmediately = false ); //! Filterpool zurückgeben DSMBCFilterPool* getFilterPool() const; @@ -140,13 +143,13 @@ public: /** * NULL => Falter-eigenen Pool benutzen */ - void setFilterPool(DSMBCFilterPool* pFilterPool); + void setFilterPool( DSMBCFilterPool* pFilterPool ); //! Freies Filter anfordern DSMBCFilter* requestFilter(); //! Filter wieder zur anderweitigen Benutzung freigeben - void releaseFilter(DSMBCFilter* pFilter); + void releaseFilter( DSMBCFilter* pFilter ); //! Aktives Filter zurückgeben /** @@ -158,7 +161,7 @@ public: /** * Hinweis: Nullzeiger => Aktives Filter entfernen */ - void exchangeFilter(DSMBCFilter* pNewFilter, int iExchangeMode=AUTO, int iCrossfadeLength=AUTO); + void exchangeFilter( DSMBCFilter* pNewFilter, const int iExchangeMode = AUTO, const int iCrossfadeLength = AUTO ); //! Löscht alle internen Samplepuffer void clear(); @@ -174,9 +177,7 @@ public: */ // TODO: Hier wird Austausch durchgeführt! - void process(const float* pfInputData, - float* pfOutputData, - int iOutputMode=OUTPUT_OVERWRITE); + void process( const float* pfInputData, float* pfOutputData, const int iOutputMode = OUTPUT_OVERWRITE ); //! Faltungsmethode (Erweitert) /** @@ -190,15 +191,11 @@ public: * \param iOutputMode Ausgabemodus (überschreiben oder Einmischen) */ - // TODO: Hier wird Austausch durchgeführt! - void process(const float* pfInputData, - int iInputLength, - float* pfOutputData, - int iOutputLength, - int iOutputMode=OUTPUT_OVERWRITE); + void process( const float* pfInputData, const int iInputLength, float* pfOutputData, const int iOutputLength, const int iOutputMode = OUTPUT_OVERWRITE ); private: - typedef struct { + typedef struct + { DSMBCFilter* pFilter; int iExchangeMode; int iCrossfadeLength; @@ -220,7 +217,7 @@ private: float *m_pfFreqAuxBuffer; // Hilfspuffer (Frequenz-bereich) float *m_pfFreqMixdownBuffer; // Mischpuffer (Frequenz-bereich) int m_iFreqCoeffs; // Anzahl DFT-Koeffizienten (Symetrien eingerechnet) - std::vector m_vpfFreqDelayLine; // Frequency-domain delay line (FDL) + std::vector< float* > m_vpfFreqDelayLine; // Frequency-domain delay line (FDL) ITAFFT *m_pFFT, *m_pIFFT; // FFT, IFFT der Daten ITACriticalSection m_csPool; // Exklusiver Zugriff auf den Filterpool @@ -229,8 +226,8 @@ private: DSMBCTriggerWatch m_oTriggerWatch; // TriggerWatch für den Filteraustausch - void copyOutputApplyGain1(float* pfDest, const float* pfSrc, int iNumSamples, int iOutputMode); - void copyOutputApplyGain2(float* pfDest, const float* pfSrc1, const float* pfSrc2, int iOutputLength, int iCrossfadeLength, int iOutputMode); + void copyOutputApplyGain1( float* pfDest, const float* pfSrc, const int iNumSamples, const int iOutputMode ); + void copyOutputApplyGain2( float* pfDest, const float* pfSrc1, const float* pfSrc2, const int iOutputLength, const int iCrossfadeLength, const int iOutputMode ); }; #endif // INCLUDE_WATCHER_DSMBC_CONVOLVER diff --git a/src/DSMBCConvolver.cpp b/src/DSMBCConvolver.cpp index 286021744da8235fb2a7c5857af391f86a72d3ea..e43aaca183287f5d11ff4cb37175e741a0aaefa6 100644 --- a/src/DSMBCConvolver.cpp +++ b/src/DSMBCConvolver.cpp @@ -14,84 +14,88 @@ #include DSMBCConvolver::DSMBCConvolver() -: m_iBlocklength(0), - m_iMaxFilterlength(0), - m_iExchangeMode(SWITCH), - m_iCrossfadeLength(0), - m_pfTimeInputBuffer(NULL), - m_pfTimeOutputBuffer1(NULL), - m_pfTimeOutputBuffer2(NULL), - m_pfFreqAuxBuffer(NULL), - m_pfFreqMixdownBuffer(NULL), - m_pCurrentFilter(NULL), - m_pOwnPool(NULL), - m_pCurrentPool(NULL), - m_pFFT(NULL), - m_pIFFT(NULL) + : m_iBlocklength( 0 ), + m_iMaxFilterlength( 0 ), + m_iExchangeMode( SWITCH ), + m_iCrossfadeLength( 0 ), + m_pfTimeInputBuffer( NULL ), + m_pfTimeOutputBuffer1( NULL ), + m_pfTimeOutputBuffer2( NULL ), + m_pfFreqAuxBuffer( NULL ), + m_pfFreqMixdownBuffer( NULL ), + m_pCurrentFilter( NULL ), + m_pOwnPool( NULL ), + m_pCurrentPool( NULL ), + m_pFFT( NULL ), + m_pIFFT( NULL ) {} -DSMBCConvolver::DSMBCConvolver(int iBlocklength, int iMaxFilterlength, DSMBCFilterPool* pFilterPool) -: m_iBlocklength(iBlocklength), - m_iMaxFilterlength(iMaxFilterlength), - m_iExchangeMode(SWITCH), - m_iCrossfadeLength(0), - m_pfTimeInputBuffer(NULL), - m_pfTimeOutputBuffer1(NULL), - m_pfTimeOutputBuffer2(NULL), - m_pfFreqAuxBuffer(NULL), - m_pfFreqMixdownBuffer(NULL), - m_pCurrentFilter(NULL), - m_pOwnPool(NULL), - m_pCurrentPool(pFilterPool), - m_pFFT(NULL), - m_pIFFT(NULL) +DSMBCConvolver::DSMBCConvolver( const int iBlocklength, const int iMaxFilterlength, DSMBCFilterPool* pFilterPool ) + : m_iBlocklength( iBlocklength ), + m_iMaxFilterlength( iMaxFilterlength ), + m_iExchangeMode( SWITCH ), + m_iCrossfadeLength( 0 ), + m_pfTimeInputBuffer( NULL ), + m_pfTimeOutputBuffer1( NULL ), + m_pfTimeOutputBuffer2( NULL ), + m_pfFreqAuxBuffer( NULL ), + m_pfFreqMixdownBuffer( NULL ), + m_pCurrentFilter( NULL ), + m_pOwnPool( NULL ), + m_pCurrentPool( pFilterPool ), + m_pFFT( NULL ), + m_pIFFT( NULL ) { - init(iBlocklength, iMaxFilterlength); + init( iBlocklength, iMaxFilterlength ); } -DSMBCConvolver::~DSMBCConvolver() { +DSMBCConvolver::~DSMBCConvolver() +{ // Aktuelles Filter freigeben DSMBCFilter* pFilter = m_pCurrentFilter; - if( (DSMBCFilter*) m_pCurrentFilter ) - (*m_pCurrentFilter).m_oState.removeUse(); + if( ( DSMBCFilter* ) m_pCurrentFilter ) + ( *m_pCurrentFilter ).m_oState.removeUse(); // Nächste Filter in der Queue freigeben FilterUpdate oUpdate; - while (m_qExchangeFilters.try_pop(oUpdate)) - if (oUpdate.pFilter) oUpdate.pFilter->m_oState.removePrep(); + while( m_qExchangeFilters.try_pop( oUpdate ) ) + if( oUpdate.pFilter ) oUpdate.pFilter->m_oState.removePrep(); // Resourcen freigeben - std::for_each(m_vpfFreqDelayLine.begin(), m_vpfFreqDelayLine.end(), fm_free); - fm_free(m_pfTimeInputBuffer); - fm_free(m_pfTimeOutputBuffer1); - fm_free(m_pfTimeOutputBuffer2); - fm_free(m_pfFreqAuxBuffer); - fm_free(m_pfFreqMixdownBuffer); + std::for_each( m_vpfFreqDelayLine.begin(), m_vpfFreqDelayLine.end(), fm_free ); + fm_free( m_pfTimeInputBuffer ); + fm_free( m_pfTimeOutputBuffer1 ); + fm_free( m_pfTimeOutputBuffer2 ); + fm_free( m_pfFreqAuxBuffer ); + fm_free( m_pfFreqMixdownBuffer ); delete m_pOwnPool; delete m_pFFT; delete m_pIFFT; } -void DSMBCConvolver::init(int iBlocklength, int iMaxFilterlength) { +void DSMBCConvolver::init( const int iBlocklength, const int iMaxFilterlength ) +{ /* * Bemerkungen: - * + * * 1. Die Grääe des Filterkoeffizienten-Array pfFilterData muss * nicht zwingend ein Vielfaches der Puffergrääe sein * * 2. Ferner kann seine Grääe kleiner als iBlocklength sein! - */ + */ // Anzahl der Filterteile bestimmen int n = iMaxFilterlength / iBlocklength; - if ((iMaxFilterlength % iBlocklength) > 0) n++; + if( ( iMaxFilterlength % iBlocklength ) > 0 ) + n++; m_iBlocklength = iBlocklength; m_iMaxFilterlength = iBlocklength * n; // Leere Impulsantwort? Dann haben wir fertig! - if (n==0) return; + if( n == 0 ) + return; /* * Speicher fär die DFT-Koeffizienten der Filterteile allozieren @@ -100,121 +104,138 @@ void DSMBCConvolver::init(int iBlocklength, int iMaxFilterlength) { * mässen mit Nullsamples gepadded werden! */ - m_iFreqCoeffs = iBlocklength+1; - m_pfTimeInputBuffer = fm_falloc(2*iBlocklength, true); - m_pfTimeOutputBuffer1 = fm_falloc(2*iBlocklength, true); - m_pfTimeOutputBuffer2 = fm_falloc(2*iBlocklength, true); + m_iFreqCoeffs = iBlocklength + 1; + m_pfTimeInputBuffer = fm_falloc( 2 * iBlocklength, true ); + m_pfTimeOutputBuffer1 = fm_falloc( 2 * iBlocklength, true ); + m_pfTimeOutputBuffer2 = fm_falloc( 2 * iBlocklength, true ); - for (int i=0; igetBlocklength() != m_iBlocklength) || - (pFilterPool->getMaxFilterlength() != m_iMaxFilterlength)) - ITA_EXCEPT1(MODAL_EXCEPTION, "Pool does not meet the properties of the convolver"); + if( ( pFilterPool->getBlocklength() != m_iBlocklength ) || + ( pFilterPool->getMaxFilterlength() != m_iMaxFilterlength ) ) + ITA_EXCEPT1( MODAL_EXCEPTION, "Pool does not meet the properties of the convolver" ); m_csPool.enter(); - m_pCurrentPool = (pFilterPool ? pFilterPool : m_pOwnPool); + m_pCurrentPool = ( pFilterPool ? pFilterPool : m_pOwnPool ); m_csPool.leave(); } -DSMBCFilter* DSMBCConvolver::requestFilter() { +DSMBCFilter* DSMBCConvolver::requestFilter() +{ m_csPool.enter(); DSMBCFilter* pFilter = m_pCurrentPool->requestFilter(); m_csPool.leave(); return pFilter; } -void DSMBCConvolver::releaseFilter(DSMBCFilter* pFilter) { +void DSMBCConvolver::releaseFilter( DSMBCFilter* pFilter ) +{ m_csPool.enter(); - m_pCurrentPool->releaseFilter(pFilter); + m_pCurrentPool->releaseFilter( pFilter ); m_csPool.leave(); } -DSMBCFilter* DSMBCConvolver::getActiveFilter() { +DSMBCFilter* DSMBCConvolver::getActiveFilter() +{ return m_pCurrentFilter; } -void DSMBCConvolver::exchangeFilter(DSMBCFilter* pNewFilter, int iExchangeMode, int iCrossfadeLength) { +void DSMBCConvolver::exchangeFilter( DSMBCFilter* pNewFilter, const int iExchangeMode, const int iCrossfadeLength ) +{ //DEBUG_PRINTF("[DSMBCConvolver 0x%08Xh] Exchanging to filter 0x%08Xh\n", this, pNewFilter); // Platzierung des Filter vermerken - if (pNewFilter) pNewFilter->m_oState.addPrep(); + if( pNewFilter ) + pNewFilter->m_oState.addPrep(); // Nächstes Filter in die Austausch-Queue einfügen FilterUpdate oUpdate; oUpdate.pFilter = pNewFilter; - oUpdate.iExchangeMode = (iExchangeMode == AUTO ? (int) m_iExchangeMode : iExchangeMode); - oUpdate.iCrossfadeLength = (iCrossfadeLength == AUTO ? (int) m_iCrossfadeLength : iCrossfadeLength); - m_qExchangeFilters.push(oUpdate); + oUpdate.iExchangeMode = ( iExchangeMode == AUTO ? ( int ) m_iExchangeMode : iExchangeMode ); + oUpdate.iCrossfadeLength = ( iCrossfadeLength == AUTO ? ( int ) m_iCrossfadeLength : iCrossfadeLength ); + m_qExchangeFilters.push( oUpdate ); } void DSMBCConvolver::clear() @@ -223,63 +244,62 @@ void DSMBCConvolver::clear() fm_zero( m_pfTimeOutputBuffer1, 2 * m_iBlocklength ); fm_zero( m_pfTimeOutputBuffer2, 2 * m_iBlocklength ); - for( size_t i=0; i < m_vpfFreqDelayLine.size(); i++ ) - fm_zero( m_vpfFreqDelayLine[i], 2 * m_iFreqCoeffs ); + for( size_t i = 0; i < m_vpfFreqDelayLine.size(); i++ ) + fm_zero( m_vpfFreqDelayLine[ i ], 2 * m_iFreqCoeffs ); fm_zero( m_pfFreqAuxBuffer, 2 * m_iFreqCoeffs ); fm_zero( m_pfFreqMixdownBuffer, 2 * m_iFreqCoeffs ); - if( (DSMBCFilter*) m_pCurrentFilter ) + if( ( DSMBCFilter* ) m_pCurrentFilter ) { m_pCurrentPool->releaseFilter( m_pCurrentFilter ); m_pCurrentFilter = NULL; } } -void DSMBCConvolver::process(const float* pfInputData, float* pfOutputData, int iOutputMode) { - process(pfInputData, m_iBlocklength, pfOutputData, m_iBlocklength, iOutputMode); +void DSMBCConvolver::process( const float* pfInputData, float* pfOutputData, const int iOutputMode ) +{ + process( pfInputData, m_iBlocklength, pfOutputData, m_iBlocklength, iOutputMode ); } -void DSMBCConvolver::process(const float* pfInputData, - int iInputLength, - float* pfOutputData, - int iOutputLength, - int iOutputMode) +void DSMBCConvolver::process( const float* pfInputData, const int iInputLength, float* pfOutputData, const int iOutputLength, const int iOutputMode ) { - assert(iInputLength >= 0); - assert(iOutputLength >= 0); - - // Wichtig: Nullzeiger-Absicherung erfolgt ausschließlich über die Größen-Angaben - if (pfInputData == NULL) iInputLength = 0; - if (pfOutputData == NULL) iOutputLength = 0; - + assert( iInputLength >= 0 ); + assert( iOutputLength >= 0 ); + // Rechte Seite des Hilfspuffers in die linke kopieren. // Danach die neuen Eingangsdaten in den rechten Hälfte plazieren. - memcpy(m_pfTimeInputBuffer, m_pfTimeInputBuffer+m_iBlocklength, m_iBlocklength*sizeof(float)); + memcpy( m_pfTimeInputBuffer, m_pfTimeInputBuffer + m_iBlocklength, m_iBlocklength * sizeof( float ) ); - if (pfInputData) { - if (iInputLength >= m_iBlocklength) { + if( pfInputData > 0 && pfInputData != nullptr ) + { + if( iInputLength >= m_iBlocklength ) + { // Eingangsdaten am Stück kopieren - memcpy(m_pfTimeInputBuffer+m_iBlocklength, pfInputData, m_iBlocklength*sizeof(float)); - } else { + memcpy( m_pfTimeInputBuffer + m_iBlocklength, pfInputData, m_iBlocklength * sizeof( float ) ); + } + else + { // Eingabedaten kopieren und den Rest mit Nullen füllen - memcpy(m_pfTimeInputBuffer+m_iBlocklength, pfInputData, iInputLength*sizeof(float)); - memset(m_pfTimeInputBuffer+m_iBlocklength+iInputLength, 0, (m_iBlocklength-iInputLength)*sizeof(float)); + memcpy( m_pfTimeInputBuffer + m_iBlocklength, pfInputData, iInputLength * sizeof( float ) ); + memset( m_pfTimeInputBuffer + m_iBlocklength + iInputLength, 0, ( m_iBlocklength - iInputLength ) * sizeof( float ) ); } - } else { + } + else + { // Nullen setzen. - fm_zero(m_pfTimeInputBuffer+m_iBlocklength, m_iBlocklength); + fm_zero( m_pfTimeInputBuffer + m_iBlocklength, m_iBlocklength ); } - + // Elemente der Frequency-domain delay line (FDL) weiterschieben - int n = (int) m_vpfFreqDelayLine.size(); + int n = ( int ) m_vpfFreqDelayLine.size(); float* X = m_vpfFreqDelayLine.back(); - for (int i=n-1; i>0; i--) m_vpfFreqDelayLine[i] = m_vpfFreqDelayLine[i-1]; - m_vpfFreqDelayLine[0] = X; + for( int i = n - 1; i > 0; i-- ) m_vpfFreqDelayLine[ i ] = m_vpfFreqDelayLine[ i - 1 ]; + m_vpfFreqDelayLine[ 0 ] = X; // Eingangsdaten in den Frequenzbereich transformieren - m_pFFT->execute(m_pfTimeInputBuffer, X); + m_pFFT->execute( m_pfTimeInputBuffer, X ); // Globale Austausch-Parameter int xmode = m_iExchangeMode; @@ -295,10 +315,10 @@ void DSMBCConvolver::process(const float* pfInputData, // Test auf neue Filter nur dann durchführen, wenn der Trigger signalisiert wurde // oder gar kein Trigger zuordnet ist (dies wird in der TriggerWatch realisiert). - if (m_oTriggerWatch.fire()) { + if( m_oTriggerWatch.fire() ) { // Alle bis auf das letzte Filter in der Austausch-Queue freigeben - while (m_qExchangeFilters.try_pop(oUpdate)) { + while( m_qExchangeFilters.try_pop( oUpdate ) ) { bNewFilters = true; Z = oUpdate.pFilter; @@ -306,10 +326,10 @@ void DSMBCConvolver::process(const float* pfInputData, xmode = oUpdate.iExchangeMode; iCrossfadeLength = oUpdate.iCrossfadeLength; // Wichtig: Ein Switching bei den Updates ist dominant - bForceSwitch |= (xmode == SWITCH); + bForceSwitch |= ( xmode == SWITCH ); //DEBUG_PRINTF("[DSMBCConvolver 0x%08Xh] Popped next filter 0x%08Xh\n", this, Z); - if (N) N->m_oState.removePrep(); + if( N ) N->m_oState.removePrep(); N = Z; } // Hinweis: N enthält jetzt das letzte Element der Queue (kann auch NULL sein) @@ -317,32 +337,37 @@ void DSMBCConvolver::process(const float* pfInputData, } // Keine Änderung - if (!bNewFilters) N = C; - - if (bForceSwitch) { + if( !bNewFilters ) N = C; + + if( bForceSwitch ) + { xmode = SWITCH; iCrossfadeLength = 0; } // Im Fall von Umschalten das alte Filter sofort freigeben (wird nicht mehr benötigt) // Dies gilt auch falls keine Ausgabedaten ausgegeben werden sollen. - if ((xmode == SWITCH) || (!pfOutputData)) { - - if (C != N) { - if (C) C->m_oState.removeUse(); - if (N) N->m_oState.xchangePrep2Use(); + if( ( xmode == SWITCH ) || ( !pfOutputData ) ) + { + if( C != N ) + { + if( C ) C->m_oState.removeUse(); + if( N ) N->m_oState.xchangePrep2Use(); C = N; m_pCurrentFilter = N; } } - if (!pfOutputData) { - m_fCurrentGain = (float) m_fNewGain; + if( !pfOutputData ) + { + m_fCurrentGain = ( float ) m_fNewGain; return; } - int iOutputCount = (std::min)(m_iBlocklength, iOutputLength); + int iOutputCount = ( std::min )( m_iBlocklength, iOutputLength ); + if( !pfOutputData ) + iOutputCount = 0; // Legacy support /* * Austausch-Verfahrensweisen @@ -354,120 +379,150 @@ void DSMBCConvolver::process(const float* pfInputData, * hartem Unschalten wird nur ein Strang bestimmt. */ - if (C == N) { + if( C == N ) + { // Fall: Keine Austausch des Filters oder Austausch durch hartes Umschalten (siehe oben) // Aufgabe: Nur einen Strang falten. Keine Überblendung. - if (C != NULL) { + if( C != NULL ) + { // Gleiches Filter wie bisher. Normal falten. - if (C->m_iNumEffectiveFilterParts > 0) { - for (int i=0; im_iNumEffectiveFilterParts; i++) { - if (i==0) { + if( C->m_iNumEffectiveFilterParts > 0 ) { + for( int i = 0; i < C->m_iNumEffectiveFilterParts; i++ ) { + if( i == 0 ) { // Ergebnis direkt in den Misch-Puffer speichern - fm_cmul_x(m_pfFreqMixdownBuffer, m_vpfFreqDelayLine[i], C->m_vpfFreqData[i], m_iFreqCoeffs); - } else { + fm_cmul_x( m_pfFreqMixdownBuffer, m_vpfFreqDelayLine[ i ], C->m_vpfFreqData[ i ], m_iFreqCoeffs ); + } + else { // Ergebnis zwischenpuffern, danach auf den Misch-Puffer aufaddieren - fm_cmul_x(m_pfFreqAuxBuffer, m_vpfFreqDelayLine[i], C->m_vpfFreqData[i], m_iFreqCoeffs); - fm_add(m_pfFreqMixdownBuffer, m_pfFreqAuxBuffer, m_iFreqCoeffs*2); + fm_cmul_x( m_pfFreqAuxBuffer, m_vpfFreqDelayLine[ i ], C->m_vpfFreqData[ i ], m_iFreqCoeffs ); + fm_add( m_pfFreqMixdownBuffer, m_pfFreqAuxBuffer, m_iFreqCoeffs * 2 ); } } // Rücktransformation durchführen - m_pIFFT->execute(m_pfFreqMixdownBuffer, m_pfTimeOutputBuffer1); + m_pIFFT->execute( m_pfFreqMixdownBuffer, m_pfTimeOutputBuffer1 ); // Verstärkungs-Envelope anwenden - copyOutputApplyGain1(pfOutputData, m_pfTimeOutputBuffer1, iOutputCount, iOutputMode); + copyOutputApplyGain1( pfOutputData, m_pfTimeOutputBuffer1, iOutputCount, iOutputMode ); return; - } else { + } + else + { // Keine effektiven Filterteile => Ausgabe ist Null - if (iOutputMode == OUTPUT_OVERWRITE) - memset(pfOutputData, 0, iOutputCount*sizeof(float)); + if( iOutputMode == OUTPUT_OVERWRITE ) + memset( pfOutputData, 0, iOutputCount*sizeof( float ) ); return; } - } else { + } + else + { // Abkürzung: Leeres Filter -> Keine Ausgangsdaten - if (iOutputMode == OUTPUT_OVERWRITE) { - for (int i=0; im_iNumEffectiveFilterParts > 0) { + if( C != NULL ) + { + if( C->m_iNumEffectiveFilterParts > 0 ) + { // Falten mit aktuellen Filter - for (int i=0; im_iNumEffectiveFilterParts; i++) { - if (i==0) { + for( int i = 0; i < C->m_iNumEffectiveFilterParts; i++ ) + { + if( i == 0 ) + { // Ergebnis direkt in den Misch-Puffer speichern - fm_cmul_x(m_pfFreqMixdownBuffer, m_vpfFreqDelayLine[i], C->m_vpfFreqData[i], m_iFreqCoeffs); - } else { + fm_cmul_x( m_pfFreqMixdownBuffer, m_vpfFreqDelayLine[ i ], C->m_vpfFreqData[ i ], m_iFreqCoeffs ); + } + else + { // Ergebnis zwischenpuffern, danach auf den Misch-Puffer aufaddieren - fm_cmul_x(m_pfFreqAuxBuffer, m_vpfFreqDelayLine[i], C->m_vpfFreqData[i], m_iFreqCoeffs); - fm_add(m_pfFreqMixdownBuffer, m_pfFreqAuxBuffer, m_iFreqCoeffs*2); + fm_cmul_x( m_pfFreqAuxBuffer, m_vpfFreqDelayLine[ i ], C->m_vpfFreqData[ i ], m_iFreqCoeffs ); + fm_add( m_pfFreqMixdownBuffer, m_pfFreqAuxBuffer, m_iFreqCoeffs * 2 ); } } - m_pIFFT->execute(m_pfFreqMixdownBuffer, m_pfTimeOutputBuffer1); + m_pIFFT->execute( m_pfFreqMixdownBuffer, m_pfTimeOutputBuffer1 ); - int iFadeOptions = ITA_FADE_OUT | (xmode == CROSSFADE_LINEAR ? ITA_FADE_LINEAR : ITA_FADE_COSINE_SQUARE); - Fade(m_pfTimeOutputBuffer1, iCrossfadeLength, iFadeOptions, 0, iCrossfadeLength); + int iFadeOptions = ITA_FADE_OUT | ( xmode == CROSSFADE_LINEAR ? ITA_FADE_LINEAR : ITA_FADE_COSINE_SQUARE ); + Fade( m_pfTimeOutputBuffer1, iCrossfadeLength, iFadeOptions, 0, iCrossfadeLength ); - } else { + } + else + { // Keine effektiven Filterteile => Zwischenergebnis ist Null - fm_zero(m_pfTimeOutputBuffer1, m_iBlocklength); + fm_zero( m_pfTimeOutputBuffer1, m_iBlocklength ); } // Altes Filter freigeben C->m_oState.removeUse(); - } else { - fm_zero(m_pfTimeOutputBuffer1, m_iBlocklength); + } + else + { + fm_zero( m_pfTimeOutputBuffer1, m_iBlocklength ); } // Falten mit dem neuen Filter - if (N != NULL) { + if( N != NULL ) + { // Neues Filter sperren N->m_oState.xchangePrep2Use(); - if (N->m_iNumEffectiveFilterParts > 0) { - for (int i=0; im_iNumEffectiveFilterParts; i++) { - if (i==0) { + if( N->m_iNumEffectiveFilterParts > 0 ) + { + for( int i = 0; i < N->m_iNumEffectiveFilterParts; i++ ) + { + if( i == 0 ) + { // Ergebnis direkt in den Misch-Puffer speichern - fm_cmul_x(m_pfFreqMixdownBuffer, m_vpfFreqDelayLine[i], N->m_vpfFreqData[i], m_iFreqCoeffs); - } else { + fm_cmul_x( m_pfFreqMixdownBuffer, m_vpfFreqDelayLine[ i ], N->m_vpfFreqData[ i ], m_iFreqCoeffs ); + } + else + { // Ergebnis zwischenpuffern, danach auf den Misch-Puffer aufaddieren - fm_cmul_x(m_pfFreqAuxBuffer, m_vpfFreqDelayLine[i], N->m_vpfFreqData[i], m_iFreqCoeffs); - fm_add(m_pfFreqMixdownBuffer, m_pfFreqAuxBuffer, m_iFreqCoeffs*2); + fm_cmul_x( m_pfFreqAuxBuffer, m_vpfFreqDelayLine[ i ], N->m_vpfFreqData[ i ], m_iFreqCoeffs ); + fm_add( m_pfFreqMixdownBuffer, m_pfFreqAuxBuffer, m_iFreqCoeffs * 2 ); } } - m_pIFFT->execute(m_pfFreqMixdownBuffer, m_pfTimeOutputBuffer2); + m_pIFFT->execute( m_pfFreqMixdownBuffer, m_pfTimeOutputBuffer2 ); - int iFadeOptions = ITA_FADE_IN | (xmode == CROSSFADE_LINEAR ? ITA_FADE_LINEAR : ITA_FADE_COSINE_SQUARE); - Fade(m_pfTimeOutputBuffer2, iCrossfadeLength, iFadeOptions, 0, iCrossfadeLength); - } else { + int iFadeOptions = ITA_FADE_IN | ( xmode == CROSSFADE_LINEAR ? ITA_FADE_LINEAR : ITA_FADE_COSINE_SQUARE ); + Fade( m_pfTimeOutputBuffer2, iCrossfadeLength, iFadeOptions, 0, iCrossfadeLength ); + } + else + { // Keine effektiven Filterteile => Zwischenergebnis ist Null - fm_zero(m_pfTimeOutputBuffer2, m_iBlocklength); + fm_zero( m_pfTimeOutputBuffer2, m_iBlocklength ); } - } else { - fm_zero(m_pfTimeOutputBuffer2, m_iBlocklength); + } + else + { + fm_zero( m_pfTimeOutputBuffer2, m_iBlocklength ); } // Ausgabe normalisieren und im Ausgabepuffer zusammenkopieren // Linke Seite von m_pfTimeOutputBuffer enthält die Nutzdaten. - copyOutputApplyGain2(pfOutputData, m_pfTimeOutputBuffer1, m_pfTimeOutputBuffer2, iOutputCount, iCrossfadeLength, iOutputMode); + copyOutputApplyGain2( pfOutputData, m_pfTimeOutputBuffer1, m_pfTimeOutputBuffer2, iOutputCount, iCrossfadeLength, iOutputMode ); // Filteraustausch vermerken: m_pCurrentFilter = N; @@ -478,31 +533,44 @@ void DSMBCConvolver::process(const float* pfInputData, // Transferriert Samples vom den internen Puffern in die Ausgabe und wendet dabei die Gains an. // Div ist ein Skalierungsfaktor (1/x) für die unnormalisierte inverse FFT. -void DSMBCConvolver::copyOutputApplyGain1(float* pfDest, const float* pfSrc, int iOutputLength, int iOutputMode) { +void DSMBCConvolver::copyOutputApplyGain1( float* pfDest, const float* pfSrc, const int iOutputLength, const int iOutputMode ) +{ // Atomares lesen in lokale Variablen float fGain1 = m_fCurrentGain; float fGain2 = m_fNewGain; - if ((fGain1 == fGain2) && (fGain1 != 1)) { + if( ( fGain1 == fGain2 ) && ( fGain1 != 1 ) ) + { // Keine Änderung und neues Gain nicht 1 => Konstanter Gain - if (iOutputMode == OUTPUT_OVERWRITE) { + if( iOutputMode == OUTPUT_OVERWRITE ) + { // Ausgabe Überschreiben - for (int i=0; i Linear interpolierter Gain - float c = (fGain2-fGain1) / (float) m_iBlocklength; + float c = ( fGain2 - fGain1 ) / ( float ) m_iBlocklength; - if (iOutputMode == OUTPUT_OVERWRITE) { + if( iOutputMode == OUTPUT_OVERWRITE ) + { // Ausgabe Überschreiben - for (int i=0; i Konstanter Gain - if (iOutputMode == OUTPUT_OVERWRITE) { + if( iOutputMode == OUTPUT_OVERWRITE ) { // Ausgabe Überschreiben - for (int i=0; i<(std::min)(iCrossfadeLength, iOutputLength); i++) - pfDest[i] = (pfSrc1[i]+pfSrc2[i]) * fGain1; - for (int i=iCrossfadeLength; i<(std::min)(m_iBlocklength, iOutputLength); i++) - pfDest[i] = pfSrc2[i] * fGain1; - } else { + for( int i = 0; i < ( std::min )( iCrossfadeLength, iOutputLength ); i++ ) + pfDest[ i ] = ( pfSrc1[ i ] + pfSrc2[ i ] ) * fGain1; + for( int i = iCrossfadeLength; i < ( std::min )( m_iBlocklength, iOutputLength ); i++ ) + pfDest[ i ] = pfSrc2[ i ] * fGain1; + } + else + { // Ausgabe Aufaddieren - for (int i=0; i<(std::min)(iCrossfadeLength, iOutputLength); i++) - pfDest[i] += (pfSrc1[i]+pfSrc2[i]) * fGain1; - for (int i=iCrossfadeLength; i<(std::min)(m_iBlocklength, iOutputLength); i++) - pfDest[i] += pfSrc2[i] * fGain1; + for( int i = 0; i < ( std::min )( iCrossfadeLength, iOutputLength ); i++ ) + pfDest[ i ] += ( pfSrc1[ i ] + pfSrc2[ i ] ) * fGain1; + for( int i = iCrossfadeLength; i < ( std::min )( m_iBlocklength, iOutputLength ); i++ ) + pfDest[ i ] += pfSrc2[ i ] * fGain1; } - } else { + } + else + { // Verstärkung ändert sich => Linear interpolierter Gain - float c = (fGain2-fGain1) / (float) m_iBlocklength; + float c = ( fGain2 - fGain1 ) / ( float ) m_iBlocklength; - if (iOutputMode == OUTPUT_OVERWRITE) { + if( iOutputMode == OUTPUT_OVERWRITE ) + { // Ausgabe Überschreiben - for (int i=0; i<(std::min)(iCrossfadeLength, iOutputLength); i++) - pfDest[i] = (pfSrc1[i]+pfSrc2[i]) * (fGain1 + i*c); - for (int i=iCrossfadeLength; i<(std::min)(m_iBlocklength, iOutputLength); i++) - pfDest[i] = pfSrc2[i] * (fGain1 + i*c); - } else { + for( int i = 0; i < ( std::min )( iCrossfadeLength, iOutputLength ); i++ ) + pfDest[ i ] = ( pfSrc1[ i ] + pfSrc2[ i ] ) * ( fGain1 + i*c ); + for( int i = iCrossfadeLength; i < ( std::min )( m_iBlocklength, iOutputLength ); i++ ) + pfDest[ i ] = pfSrc2[ i ] * ( fGain1 + i*c ); + } + else + { // Ausgabe Aufaddieren - for (int i=0; i<(std::min)(iCrossfadeLength, iOutputLength); i++) - pfDest[i] += (pfSrc1[i]+pfSrc2[i]) * (fGain1 + i*c); - for (int i=iCrossfadeLength; i<(std::min)(m_iBlocklength, iOutputLength); i++) - pfDest[i] += pfSrc2[i] * (fGain1 + i*c); + for( int i = 0; i < ( std::min )( iCrossfadeLength, iOutputLength ); i++ ) + pfDest[ i ] += ( pfSrc1[ i ] + pfSrc2[ i ] ) * ( fGain1 + i*c ); + for( int i = iCrossfadeLength; i < ( std::min )( m_iBlocklength, iOutputLength ); i++ ) + pfDest[ i ] += pfSrc2[ i ] * ( fGain1 + i*c ); } m_fCurrentGain = fGain2;