Style for DSMBC filter modules

parent 70c03f30
......@@ -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<float*> 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
......@@ -14,84 +14,88 @@
#include <cassert>
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; i<n; i++)
m_vpfFreqDelayLine.push_back( fm_falloc(2*m_iFreqCoeffs, true) );
for( int i = 0; i < n; i++ )
m_vpfFreqDelayLine.push_back( fm_falloc( 2 * m_iFreqCoeffs, true ) );
// Frequenzbereichs-Mischpuffer allozieren und Rücktransformation planen
m_pfFreqAuxBuffer = fm_falloc(m_iFreqCoeffs*2, false);
m_pfFreqMixdownBuffer = fm_falloc(m_iFreqCoeffs*2, false);
m_pfFreqAuxBuffer = fm_falloc( m_iFreqCoeffs * 2, false );
m_pfFreqMixdownBuffer = fm_falloc( m_iFreqCoeffs * 2, false );
// Transformationen planen
m_pFFT = new ITAFFT(ITAFFT::FFT_R2C, 2*iBlocklength, m_pfTimeInputBuffer, m_vpfFreqDelayLine[0]);
m_pIFFT = new ITAFFT(ITAFFT::IFFT_C2R, 2*iBlocklength, m_pfFreqMixdownBuffer, m_pfTimeOutputBuffer1);
m_pFFT = new ITAFFT( ITAFFT::FFT_R2C, 2 * iBlocklength, m_pfTimeInputBuffer, m_vpfFreqDelayLine[ 0 ] );
m_pIFFT = new ITAFFT( ITAFFT::IFFT_C2R, 2 * iBlocklength, m_pfFreqMixdownBuffer, m_pfTimeOutputBuffer1 );
// Eigenen Filterpool erzeugen
m_pOwnPool = new DSMBCFilterPool(m_iBlocklength, m_iMaxFilterlength, 0);
if (!m_pCurrentPool) m_pCurrentPool = m_pOwnPool;
m_pOwnPool = new DSMBCFilterPool( m_iBlocklength, m_iMaxFilterlength, 0 );
if( !m_pCurrentPool ) m_pCurrentPool = m_pOwnPool;
m_fCurrentGain = 1;
m_fNewGain = 1;
}
int DSMBCConvolver::getBlocklength() const {
int DSMBCConvolver::getBlocklength() const
{
return m_iBlocklength;
}
int DSMBCConvolver::getMaxFilterlength() const {
int DSMBCConvolver::getMaxFilterlength() const
{
return m_iMaxFilterlength;
}
const DSMBCTrigger* DSMBCConvolver::getFilterExchangeTrigger() const {
const DSMBCTrigger* DSMBCConvolver::getFilterExchangeTrigger() const
{
return m_oTriggerWatch.getWatchedTrigger();
}
void DSMBCConvolver::setFilterExchangeTrigger(const DSMBCTrigger* pTrigger) {
m_oTriggerWatch.setWatchedTrigger(pTrigger);
void DSMBCConvolver::setFilterExchangeTrigger( const DSMBCTrigger* pTrigger )
{
m_oTriggerWatch.setWatchedTrigger( pTrigger );
}
int DSMBCConvolver::getFilterExchangeMode() {
int DSMBCConvolver::getFilterExchangeMode()
{
return m_iExchangeMode;
}
void DSMBCConvolver::setFilterExchangeMode(int iMode) {
void DSMBCConvolver::setFilterExchangeMode( const int iMode )
{
m_iExchangeMode = iMode;
}
int DSMBCConvolver::getFilterCrossfadeLength() {
int DSMBCConvolver::getFilterCrossfadeLength()
{
return m_iCrossfadeLength;
}
void DSMBCConvolver::setFilterCrossfadeLength(int iLength) {
void DSMBCConvolver::setFilterCrossfadeLength( const int iLength )
{
m_iCrossfadeLength = iLength;
}
float DSMBCConvolver::getGain() const {
float DSMBCConvolver::getGain() const
{
return m_fCurrentGain;
}
void DSMBCConvolver::setGain(float fGain, bool bSetImmediately) {
void DSMBCConvolver::setGain( const float fGain, const bool bSetImmediately )
{
m_fNewGain = fGain;
if (bSetImmediately) m_fCurrentGain = fGain;
if( bSetImmediately ) m_fCurrentGain = fGain;
}
DSMBCFilterPool* DSMBCConvolver::getFilterPool() const {
DSMBCFilterPool* DSMBCConvolver::getFilterPool() const
{
m_csPool.enter();
DSMBCFilterPool* pResult = m_pCurrentPool;
m_csPool.leave();
return pResult;
}
void DSMBCConvolver::setFilterPool(DSMBCFilterPool* pFilterPool) {
if (m_iBlocklength == 0)
ITA_EXCEPT1(MODAL_EXCEPTION, "Convolver instance not initialized yet");
void DSMBCConvolver::setFilterPool( DSMBCFilterPool* pFilterPool )
{
if( m_iBlocklength == 0 )
ITA_EXCEPT1( MODAL_EXCEPTION, "Convolver instance not initialized yet" );
// Parameter prüfen
if ((pFilterPool->getBlocklength() != 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();