ITANUPCInputBuffer1.cpp 4.42 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
#include "ITANUPCInputBuffer1.h"

#include "ITANUPCHelpers.h"
#include "ITANUPCUtils.h"

#include <ITANUPConvolution.h>
#include <ITAFastMath.h>

#include <cassert>

CInputBuffer1::CInputBuffer1( unsigned int m_uiBlocklength, unsigned int m_uiSize )
	: m_uiBlocklength( m_uiBlocklength ),
	m_uiSize( m_uiSize ),
	m_pfData( nullptr )
{
	// WICHTIG: Gre muss Vielfaches der Blocklnge sein
	assert( ( m_uiSize % m_uiBlocklength ) == 0 );

	/* Hinweis: Das erste Cursor-Inkrement geschieht bereits beim ersten
				Eintritt in GetBlockPointer, dann wenn noch gar keine Daten
				gelesen wurden. Wrde der Cursor mit 0 initialisiert, so wrden
				die ersten Eingabedaten an den Offset Blocklnge geschrieben
				werden. Damit mglich wenig zweiteilige Kopieraktionen ntig sind,
				wir der Cursor daher mit m_uiSize - m_uiBlocklength initialisiert,
				so dass die ersten Eingangsdaten am Offset 0 zu finden sind. */

	uiCursor = m_uiSize - m_uiBlocklength;
	m_pfData = fm_falloc( m_uiSize, true );
	m_vbSilence.resize( m_uiSize / m_uiBlocklength, true );
}

CInputBuffer1::~CInputBuffer1() {
	fm_free( m_pfData );
}

void CInputBuffer1::reset() {
	fm_zero( m_pfData, m_uiSize );
	for( unsigned int i = 0; i < ( m_uiSize / m_uiBlocklength ); i++ ) m_vbSilence[ i ] = true;
	uiCursor = m_uiSize - m_uiBlocklength;
}

bool CInputBuffer1::get( float* pfDest, unsigned int uiOffset, unsigned int uiLength ) {
#ifdef _INPUTBUFFER_DEBUG_MESSAGES
	printf("[InputBuffer1::get] Offset = %d, Length = %d\n", uiOffset, uiLength);
#endif
	assert( uiOffset < m_uiSize );

	// Zunchst prfen, ob die angeforderten Daten Stille sind:
	bool bSilence = true;
	unsigned int c = uiOffset;
	for( unsigned int i = 0; i < uiLength / m_uiBlocklength; i++ ) {
		c %= m_uiSize;
		if( !m_vbSilence[ c / m_uiBlocklength ] ) {
			bSilence = false;
			break;
		}
		c += m_uiBlocklength;
	}

	// Stille? Dann nichts kopieren... Sondern direkt mit Nullen initialisieren
	if( bSilence ) {
		fm_zero( pfDest, uiLength );
		return false;
	}

	unsigned int r = m_uiSize - uiOffset;
	if( uiLength <= r )
		// Kopieren in einem Schritt
		fm_copy( pfDest, m_pfData + uiOffset, uiLength );
	else {
		// Buffer-wrapping: Kopieren in zwei Schritten
		fm_copy( pfDest, m_pfData + uiOffset, r );
		fm_copy( pfDest + r, m_pfData, uiLength - r );
	}

	return true;
}

void CInputBuffer1::put( const float* pfSource, float fGain ) {
#ifdef _INPUTBUFFER_DEBUG_MESSAGES
	printf("[InputBuffer1::put] Cursor = %d\n", uiCursor);
#endif
	// Nullzeiger = Stille
	if( pfSource && ( fGain != 0 ) ) {
		/* fwe: Bugfix. Frher mittels fm_copy kopiert. Allerdings mu pfSource nicht SIMD-Aligned
				sein und die Spezifikation von FastMath legt nicht exakt fest, ob dies erfllt sein muss. */
		if( fGain == 1.0 )
			memcpy( m_pfData + uiCursor, pfSource, m_uiBlocklength * sizeof( float ) );
		else
			for( unsigned int i = 0; i < m_uiBlocklength; i++ )
				m_pfData[ uiCursor + i ] = pfSource[ i ] * fGain;

		// Auf Stille testen
		m_vbSilence[ uiCursor / m_uiBlocklength ] = ITANUPCFCheckZero( m_pfData + uiCursor, m_uiBlocklength );
	}
	else {
		fm_zero( m_pfData + uiCursor, m_uiBlocklength );
		m_vbSilence[ uiCursor / m_uiBlocklength ] = true;
	}

	// DEBUG: if (m_vbSilence[uiCursor/m_uiBlocklength]) printf("Silence!\n");
}

void CInputBuffer1::mix( const float* pfSource, float fGain ) {
#ifdef _INPUTBUFFER_DEBUG_MESSAGES
	printf("[InputBuffer1::mix] Cursor = %d\n", uiCursor);
#endif
	// Nullzeiger = Stille
	if( pfSource && ( fGain != 0 ) ) {
		// fwe: Bugfix. Frher mittels fm_add gemischt. Allerdings mu pfSource nicht SIMD-Aligned sein!
		if( fGain == 1.0 )
			for( unsigned int i = 0; i < m_uiBlocklength; i++ ) m_pfData[ uiCursor + i ] += pfSource[ i ];
		else
			for( unsigned int i = 0; i < m_uiBlocklength; i++ ) m_pfData[ uiCursor + i ] += pfSource[ i ] * fGain;

		// Durch das Einmischen kann vorhandene Stille aufgehoben wurden sein:
		if( m_vbSilence[ uiCursor / m_uiBlocklength ] ) {
			// Erneut auf Stille testen:
			for( unsigned int i = 0; i < m_uiBlocklength; i++ ) {
				if( m_pfData[ uiCursor + i ] != 0 ) {
					m_vbSilence[ uiCursor / m_uiBlocklength ] = false;
					return;
				}
			}
		}
	}
}

void CInputBuffer1::incrementCursor() {
	uiCursor += m_uiBlocklength;
	uiCursor %= m_uiSize;

#ifdef _INPUTBUFFER_DEBUG_MESSAGES
	printf("[InputBuffer1::incrementCursor] Cursor = %d\n", uiCursor);
#endif
}

unsigned int CInputBuffer1::getOffset( unsigned int uiLength ) {
	return ( m_uiSize + uiCursor - uiLength + m_uiBlocklength ) % m_uiSize;
}