Aufgrund einer Störung des s3 Storage, könnten in nächster Zeit folgende GitLab Funktionen nicht zur Verfügung stehen: LFS, Container Registry, Job Artifacs, Uploads (Wiki, Bilder, Projekt-Exporte). Wir bitten um Verständnis. Es wird mit Hochdruck an der Behebung des Problems gearbeitet. Weitere Informationen zur Störung des Object Storage finden Sie hier: https://maintenance.itc.rwth-aachen.de/ticket/status/messages/59-object-storage-pilot

ITASampleBuffer.cpp 15.4 KB
Newer Older
Jonas Stienen's avatar
Jonas Stienen committed
1 2 3 4 5 6
#include <ITASampleBuffer.h>

#include <algorithm>
#include <assert.h>
#include <math.h>
#include <sstream>
js908001's avatar
js908001 committed
7
#include <memory.h>
Jonas Stienen's avatar
Jonas Stienen committed
8 9 10 11 12 13 14

#include <ITAException.h>
#include <ITAFade.h>
#include <ITAFastMath.h>


ITASampleBuffer::ITASampleBuffer()
15
	: m_pParent( NULL ), m_iLength( 0 ), m_pfData( NULL ) {}
Jonas Stienen's avatar
Jonas Stienen committed
16

17 18
ITASampleBuffer::ITASampleBuffer( int iLength, bool bZeroinit )
	: m_pParent( NULL ), m_iLength( 0 ), m_pfData( NULL )
Jonas Stienen's avatar
Jonas Stienen committed
19
{
20
	Init( iLength, bZeroinit );
Jonas Stienen's avatar
Jonas Stienen committed
21 22
}

23 24
ITASampleBuffer::ITASampleBuffer( const ITASampleBuffer* pSource )
	: m_pParent( NULL ), m_iLength( 0 ), m_pfData( NULL )
Jonas Stienen's avatar
Jonas Stienen committed
25 26 27 28
{
	*this = *pSource;
}

29 30
ITASampleBuffer::ITASampleBuffer( const ITASampleBuffer& sbSource )
	: m_pParent( NULL ), m_iLength( 0 ), m_pfData( NULL )
Jonas Stienen's avatar
Jonas Stienen committed
31 32 33 34 35 36 37 38 39
{
	*this = sbSource;
}

ITASampleBuffer::~ITASampleBuffer()
{
	Free();
}

40
void ITASampleBuffer::Init( int iLength, bool bZeroInit )
Jonas Stienen's avatar
Jonas Stienen committed
41 42
{
	if( m_pParent )
43
		ITA_EXCEPT1( MODAL_EXCEPTION, "Init impossible. This sample buffer is a channel of a parent sample frame." );
Jonas Stienen's avatar
Jonas Stienen committed
44 45 46 47 48

	assert( iLength >= 0 );

	Free();

49 50 51
	m_iLength = iLength;

	size_t iBytes = size_t( iLength * sizeof( float ) );
Jonas Stienen's avatar
Jonas Stienen committed
52 53 54 55
#ifdef __GNUC__
	// TODO: Für den g++ erstmal kein aligned malloc
	m_pfData = (float*)malloc(iBytes);
#else
56
	m_pfData = ( float* ) _aligned_malloc( iBytes, 16 );
Jonas Stienen's avatar
Jonas Stienen committed
57
#endif
58 59 60

	if( bZeroInit )
		fm_zero( m_pfData, m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
61 62 63 64 65 66 67 68
}

void ITASampleBuffer::Free()
{
#ifdef __GNUC__
	if (m_pfData)
		free(m_pfData); // unaligned
#else
69
	if( m_pfData )
Jonas Stienen's avatar
Jonas Stienen committed
70 71 72 73 74 75 76 77
		_aligned_free( m_pfData );
#endif
	m_pfData = NULL;
	m_iLength = 0;
}

bool ITASampleBuffer::IsEmpty() const
{
78
	return ( m_iLength == 0 );
Jonas Stienen's avatar
Jonas Stienen committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
}

int ITASampleBuffer::GetLength() const
{
	return m_iLength;
}

const float* ITASampleBuffer::GetData() const
{
	return m_pfData;
}

float* ITASampleBuffer::GetData()
{
	return m_pfData;
}

96
void ITASampleBuffer::Fill( float fValue )
Jonas Stienen's avatar
Jonas Stienen committed
97
{
98
	fm_set( m_pfData, fValue, m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
99 100
}

101 102 103 104
void ITASampleBuffer::Fill( int iOffset, int iCount, float fValue )
{
	if( ( iOffset < 0 ) || ( iOffset >= m_iLength ) )
		ITA_EXCEPT1( INVALID_PARAMETER, "Offset out of range" );
Jonas Stienen's avatar
Jonas Stienen committed
105

106 107
	if( ( iCount < 0 ) || ( iOffset + iCount > m_iLength ) )
		ITA_EXCEPT1( INVALID_PARAMETER, "Count out of range" );
Jonas Stienen's avatar
Jonas Stienen committed
108 109

	// TODO: Schnelle Implementierung?
110 111
	for( int i = iOffset; i < iOffset + iCount; i++ )
		m_pfData[ i ] = fValue;
Jonas Stienen's avatar
Jonas Stienen committed
112 113 114 115
}

void ITASampleBuffer::Zero()
{
116
	Fill( 0.0f );
Jonas Stienen's avatar
Jonas Stienen committed
117 118
}

119
void ITASampleBuffer::Zero( int iOffset, int iCount )
Jonas Stienen's avatar
Jonas Stienen committed
120
{
121
	Fill( iOffset, iCount, 0.0f );
Jonas Stienen's avatar
Jonas Stienen committed
122 123 124 125
}

void ITASampleBuffer::Identity()
{
126 127 128 129 130 131
	if( m_iLength == 0 )
		ITA_EXCEPT1( INVALID_PARAMETER, "Sample buffer has no length" );

	m_pfData[ 0 ] = 1;
	for( int i = 1; i < m_iLength; i++ )
		m_pfData[ i ] = 0;
Jonas Stienen's avatar
Jonas Stienen committed
132 133
}

134
void ITASampleBuffer::Fade( int iOffset, int iCount, int iFadeDirection, int iFadeFunction )
Jonas Stienen's avatar
Jonas Stienen committed
135 136 137
{
	assert( iOffset >= 0 );
	assert( iCount > 0 );
138
	assert( ( iOffset + iCount ) <= m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
139 140 141

	int iFlags = 0;

142
	switch( iFadeDirection )
Jonas Stienen's avatar
Jonas Stienen committed
143 144 145 146 147 148
	{
	case FADE_IN:
		iFlags |= ITA_FADE_IN;
		break;
	case FADE_OUT:
		iFlags |= ITA_FADE_OUT;
149
		break;
Jonas Stienen's avatar
Jonas Stienen committed
150 151 152 153 154
	default:
		// Ungültiger Wert
		assert( false );
	}

155
	switch( iFadeFunction ) {
Jonas Stienen's avatar
Jonas Stienen committed
156 157 158 159 160
	case LINEAR:
		iFlags |= ITA_FADE_LINEAR;
		break;
	case COSINE_SQUARE:
		iFlags |= ITA_FADE_COSINE_SQUARE;
161
		break;
Jonas Stienen's avatar
Jonas Stienen committed
162 163 164 165 166
	default:
		// Ungültiger Wert
		assert( false );
	}

167
	::Fade( m_pfData + iOffset, iCount, iFlags );
Jonas Stienen's avatar
Jonas Stienen committed
168 169
}

170
void ITASampleBuffer::Crossfade( const ITASampleBuffer* psbSrc, int iOffset, int iCount, int iFadeDirection, int iFadeFunction )
Jonas Stienen's avatar
Jonas Stienen committed
171 172 173 174
{
	assert( psbSrc );
	assert( iOffset >= 0 );
	assert( iCount >= 0 );
175 176
	assert( ( iOffset + iCount ) <= m_iLength );
	assert( ( iOffset + iCount ) <= psbSrc->m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
177 178 179

	int iFlags = 0;

180 181
	switch( iFadeFunction )
	{
Jonas Stienen's avatar
Jonas Stienen committed
182 183 184 185 186
	case LINEAR:
		iFlags |= ITA_FADE_LINEAR;
		break;
	case COSINE_SQUARE:
		iFlags |= ITA_FADE_COSINE_SQUARE;
187
		break;
Jonas Stienen's avatar
Jonas Stienen committed
188 189 190 191 192
	default:
		// Ungültiger Wert
		assert( false );
	}

193 194
	switch( iFadeDirection )
	{
Jonas Stienen's avatar
Jonas Stienen committed
195 196
	case CROSSFADE_FROM_SOURCE:
		// Samples am Anfang kopieren
197 198 199
		for( int i = 0; i < iOffset; i++ )
			m_pfData[ i ] = psbSrc->m_pfData[ i ];
		::Crossfade( psbSrc->m_pfData + iOffset, m_pfData + iOffset, m_pfData + iOffset, iCount, iFlags );
Jonas Stienen's avatar
Jonas Stienen committed
200 201 202
		return;
	case CROSSFADE_TO_SOURCE:
		assert( psbSrc->m_iLength >= m_iLength );
203
		::Crossfade( m_pfData + iOffset, psbSrc->m_pfData + iOffset, m_pfData + iOffset, iCount, iFlags );
Jonas Stienen's avatar
Jonas Stienen committed
204
		// Samples am Ende kopieren
205 206
		for( int i = iOffset + iCount; i < m_iLength; i++ )
			m_pfData[ i ] = psbSrc->m_pfData[ i ];
Jonas Stienen's avatar
Jonas Stienen committed
207 208 209 210 211 212 213 214
		return;

	default:
		// Ungültiger Wert
		assert( false );
	}
}

215
void ITASampleBuffer::Crossfade( const ITASampleBuffer& sbSrc, int iOffset, int iCount, int iFadeDirection, int iFadeFunction )
Jonas Stienen's avatar
Jonas Stienen committed
216
{
217
	Crossfade( &sbSrc, iOffset, iCount, iFadeDirection, iFadeFunction );
Jonas Stienen's avatar
Jonas Stienen committed
218 219
}

220
void ITASampleBuffer::Envelope( float fGain0, float fGain1 )
Jonas Stienen's avatar
Jonas Stienen committed
221
{
222
	if( IsEmpty() ) return;
Jonas Stienen's avatar
Jonas Stienen committed
223 224

	// Linear interpolation
225 226 227
	float m = ( fGain1 - fGain0 ) / float( m_iLength );
	for( int i = 0; i < m_iLength; i++ )
		m_pfData[ i ] *= ( fGain0 + m*i );
Jonas Stienen's avatar
Jonas Stienen committed
228 229
}

230
void ITASampleBuffer::read( float* pfDest, int iCount, int iSrcOffset ) const
Jonas Stienen's avatar
Jonas Stienen committed
231 232 233
{
	assert( pfDest != NULL );
	assert( iCount >= 0 );
234 235
	assert( ( iSrcOffset >= 0 ) );
	assert( ( iSrcOffset + iCount ) <= m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
236 237

	// TODO: Erkennung von MemoryAlignment und schnelle SSE-Variante?
238
	memcpy( pfDest, m_pfData + iSrcOffset, iCount * sizeof( float ) );
Jonas Stienen's avatar
Jonas Stienen committed
239 240
}

241
void ITASampleBuffer::write( const float* pfSrc, int iCount, int iDestOffset )
Jonas Stienen's avatar
Jonas Stienen committed
242 243 244
{
	assert( pfSrc != NULL );
	assert( iCount >= 0 );
245 246
	assert( ( iDestOffset >= 0 ) );
	assert( ( iDestOffset + iCount ) <= m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
247 248

	// TODO: Erkennung von MemoryAlignment und schnelle SSE-Variante?
249
	memcpy( m_pfData + iDestOffset, pfSrc, iCount * sizeof( float ) );
Jonas Stienen's avatar
Jonas Stienen committed
250 251
}

252
void ITASampleBuffer::write( const ITASampleBuffer* psbSrc, int iCount, int iSrcOffset, int iDestOffset )
Jonas Stienen's avatar
Jonas Stienen committed
253 254 255
{
	assert( psbSrc != NULL );
	assert( iCount >= 0 );
256 257 258
	assert( ( iSrcOffset >= 0 ) );
	assert( ( iSrcOffset + iCount ) <= psbSrc->GetLength() );
	assert( ( iDestOffset + iCount ) <= m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
259 260

	// TODO: Erkennung von MemoryAlignment und schnelle SSE-Variante?
261
	memcpy( m_pfData + iDestOffset, psbSrc->GetData() + iSrcOffset, iCount * sizeof( float ) );
Jonas Stienen's avatar
Jonas Stienen committed
262 263
}

264 265 266
void ITASampleBuffer::write( const ITASampleBuffer& sbSrc, int iCount, int iSrcOffset, int iDestOffset )
{
	write( &sbSrc, iCount, iSrcOffset, iDestOffset );
Jonas Stienen's avatar
Jonas Stienen committed
267 268
}

269 270
void ITASampleBuffer::cyclic_read( float* pfDest, int iCount, int iSrcOffset ) const
{
Jonas Stienen's avatar
Jonas Stienen committed
271 272
	assert( pfDest != NULL );
	assert( iCount >= 0 );
273
	assert( ( iSrcOffset >= 0 ) && ( iSrcOffset < m_iLength ) );
Jonas Stienen's avatar
Jonas Stienen committed
274 275

	int n = 0;			// Anzahl kopierter Samples
276
	int p = ( ( iSrcOffset % m_iLength ) + m_iLength ) % m_iLength; // Leseposition
Jonas Stienen's avatar
Jonas Stienen committed
277

278
	while( n < iCount ) {
Jonas Stienen's avatar
Jonas Stienen committed
279
		// Verbleibende Samples berechnen
280 281 282
		int r = std::min( iCount - n, m_iLength - p );
		read( pfDest + n, r, p );
		p = ( p + r ) % m_iLength;
Jonas Stienen's avatar
Jonas Stienen committed
283 284 285 286
		n += r;
	}
}

287 288
void ITASampleBuffer::cyclic_write( const float* pfSrc, int iCount, int iDestOffset )
{
Jonas Stienen's avatar
Jonas Stienen committed
289 290 291 292
	assert( pfSrc != NULL );
	assert( iCount >= 0 );

	int n = 0;				// Anzahl kopierter Samples
293
	int p = ( ( iDestOffset % m_iLength ) + m_iLength ) % m_iLength; // Schreibposition
Jonas Stienen's avatar
Jonas Stienen committed
294

295 296
	while( n < iCount )
	{
Jonas Stienen's avatar
Jonas Stienen committed
297
		// Verbleibende Samples berechnen
298 299 300
		int r = std::min( iCount - n, m_iLength - p );
		write( pfSrc + n, r, p );
		p = ( p + r ) % m_iLength;
Jonas Stienen's avatar
Jonas Stienen committed
301 302 303 304
		n += r;
	}
}

305 306
void ITASampleBuffer::cyclic_write( const ITASampleBuffer* psbSrc, int iCount, int iSrcOffset, int iDestOffset )
{
Jonas Stienen's avatar
Jonas Stienen committed
307 308 309 310 311 312 313
	assert( psbSrc != NULL );
	assert( iCount >= 0 );

	int iSrcLength = psbSrc->GetLength();

	int n = 0;				// Anzahl kopierter Samples
	// Beliebige Offsets werden in das positive Intervall abgebildet
314 315
	int p = ( ( iSrcOffset % iSrcLength ) + iSrcLength ) % iSrcLength; // Leseposition
	int q = ( ( iDestOffset % m_iLength ) + m_iLength ) % m_iLength; // Schreibposition
Jonas Stienen's avatar
Jonas Stienen committed
316

317 318
	while( n < iCount )
	{
Jonas Stienen's avatar
Jonas Stienen committed
319 320 321
		// Verbleibende Samples berechnen
		int rs = iSrcLength - p;
		int rd = m_iLength - q;
322 323 324 325
		int r = std::min( iCount - n, std::min( rs, rd ) );
		write( psbSrc, r, p, q );
		p = ( p + r ) % iSrcLength;
		q = ( q + r ) % m_iLength;
Jonas Stienen's avatar
Jonas Stienen committed
326
		n += r;
327
	}
Jonas Stienen's avatar
Jonas Stienen committed
328 329
}

330 331 332
void ITASampleBuffer::cyclic_write( const ITASampleBuffer& sbSrc, int iCount, int iSrcOffset, int iDestOffset )
{
	cyclic_write( &sbSrc, iCount, iSrcOffset, iDestOffset );
Jonas Stienen's avatar
Jonas Stienen committed
333 334 335
}


336
void ITASampleBuffer::CyclicShift( int iCount )
Jonas Stienen's avatar
Jonas Stienen committed
337
{
338 339 340 341
	if( iCount >= GetLength() )
		ITA_EXCEPT1( INVALID_PARAMETER, "Shifting by a count greater than buffer length not allowed" );
	ITASampleBuffer sbTemp( this );
	cyclic_write( sbTemp, GetLength(), iCount );
Jonas Stienen's avatar
Jonas Stienen committed
342 343
}

344 345
void ITASampleBuffer::add_scalar( float fValue )
{
Jonas Stienen's avatar
Jonas Stienen committed
346
	// Invariante
347
	if( fValue == 0 ) return;
Jonas Stienen's avatar
Jonas Stienen committed
348 349

	// TODO: Schnelle Implementierung?
350 351
	for( int i = 0; i < m_iLength; i++ )
		m_pfData[ i ] += fValue;
Jonas Stienen's avatar
Jonas Stienen committed
352 353
}

354 355
void ITASampleBuffer::sub_scalar( float fValue )
{
Jonas Stienen's avatar
Jonas Stienen committed
356
	// Invariante
357 358
	if( fValue == 0 )
		return;
Jonas Stienen's avatar
Jonas Stienen committed
359 360

	// TODO: Schnelle Implementierung?
361 362
	for( int i = 0; i < m_iLength; i++ )
		m_pfData[ i ] -= fValue;
Jonas Stienen's avatar
Jonas Stienen committed
363 364
}

365 366
void ITASampleBuffer::mul_scalar( float fValue )
{
Jonas Stienen's avatar
Jonas Stienen committed
367
	// Invariante
368 369
	if( fValue == 1 )
		return;
Jonas Stienen's avatar
Jonas Stienen committed
370 371

	// TODO: Schnelle Implementierung?
372 373
	for( int i = 0; i < m_iLength; i++ )
		m_pfData[ i ] *= fValue;
Jonas Stienen's avatar
Jonas Stienen committed
374 375
}

376 377 378 379
void ITASampleBuffer::div_scalar( float fValue )
{
	if( fValue == 0 ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Division by zero" );
Jonas Stienen's avatar
Jonas Stienen committed
380 381

	// Invariante
382 383
	if( fValue == 1 ) 
		return;
Jonas Stienen's avatar
Jonas Stienen committed
384 385

	// TODO: Schnelle Implementierung?
386 387
	for( int i = 0; i < m_iLength; i++ ) 
		m_pfData[ i ] /= fValue;
Jonas Stienen's avatar
Jonas Stienen committed
388 389
}

390 391 392
void ITASampleBuffer::add_buf( const ITASampleBuffer* pSource )
{
	add_buf( pSource, pSource->GetLength() );
Jonas Stienen's avatar
Jonas Stienen committed
393 394
}

395 396 397 398 399 400 401 402
void ITASampleBuffer::add_buf( const ITASampleBuffer* pSource, int iCount )
{
	if( !pSource ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
	if( pSource->GetLength() < iCount )  
		ITA_EXCEPT1( INVALID_PARAMETER, "Lengths of source buffer too small" );
	if( m_iLength < iCount ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Requested lengths of source buffer too big to fit into target buffer" );
Jonas Stienen's avatar
Jonas Stienen committed
403

404
	fm_add( m_pfData, pSource->GetData(), iCount );
Jonas Stienen's avatar
Jonas Stienen committed
405 406
}

407
void ITASampleBuffer::add_buf_pos( const ITASampleBuffer* pSource, int iPos ) // TODO: move this to add_buf(mit offset=0)
Jonas Stienen's avatar
Jonas Stienen committed
408
{
409 410
	if( !pSource ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
Jonas Stienen's avatar
Jonas Stienen committed
411
	//if (pSource->GetLength() < iCount)  ITA_EXCEPT1(INVALID_PARAMETER, "Lengths of source buffer too small");
412 413
	if( ( pSource->m_iLength + iPos ) > m_iLength )
		ITA_EXCEPT1( INVALID_PARAMETER, "Source length + delay exceed length of filter" );
Jonas Stienen's avatar
Jonas Stienen committed
414

415
	fm_add( &( m_pfData[ iPos ] ), pSource->GetData(), pSource->GetLength() );
Jonas Stienen's avatar
Jonas Stienen committed
416 417
}

418
void ITASampleBuffer::add_buf_pos( float* fSource, int iSize, int iPos )
Jonas Stienen's avatar
Jonas Stienen committed
419
{
420 421 422 423
	if( !fSource ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
	if( m_iLength < iPos + iSize )
		ITA_EXCEPT1( INVALID_PARAMETER, "Source length + delay exceed length of filter" );
Jonas Stienen's avatar
Jonas Stienen committed
424

425
	fm_add( &( m_pfData[ iPos ] ), fSource, iSize );
Jonas Stienen's avatar
Jonas Stienen committed
426 427
}

428 429 430 431 432 433
void ITASampleBuffer::sub_buf( const ITASampleBuffer* pSource )
{
	if( !pSource ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
	if( pSource->GetLength() != m_iLength )
		ITA_EXCEPT1( INVALID_PARAMETER, "Block lengths do not match" );
Jonas Stienen's avatar
Jonas Stienen committed
434

435
	fm_sub( m_pfData, pSource->GetData(), m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
436 437
}

438 439 440 441 442 443
void ITASampleBuffer::mul_buf( const ITASampleBuffer* pSource )
{
	if( !pSource )
		ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
	if( pSource->GetLength() != m_iLength )
		ITA_EXCEPT1( INVALID_PARAMETER, "Block lengths do not match" );
Jonas Stienen's avatar
Jonas Stienen committed
444 445 446

	// TODO: Schnelle Implementierung?
	const float* pfSourceData = pSource->GetData();
447 448
	for( int i = 0; i < m_iLength; i++ )
		m_pfData[ i ] *= pfSourceData[ i ];
Jonas Stienen's avatar
Jonas Stienen committed
449 450
}

451 452 453 454 455 456
void ITASampleBuffer::div_buf( const ITASampleBuffer* pSource )
{
	if( !pSource )
		ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
	if( pSource->GetLength() != m_iLength )
		ITA_EXCEPT1( INVALID_PARAMETER, "Block lengths do not match" );
Jonas Stienen's avatar
Jonas Stienen committed
457 458 459 460

	// TODO: Schnelle Implementierung?
	// TODO: Was wenn Division durch Null?
	const float* pfSourceData = pSource->GetData();
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
	for( int i = 0; i < m_iLength; i++ )
		m_pfData[ i ] /= pfSourceData[ i ];
}

void ITASampleBuffer::add_buf( const ITASampleBuffer& sbSource, int iCount )
{
	add_buf( &sbSource, iCount );
}

void ITASampleBuffer::add_buf( const ITASampleBuffer& sbSource )
{
	add_buf( &sbSource );
}

void ITASampleBuffer::sub_buf( const ITASampleBuffer& sbSource )
{ 
	sub_buf( &sbSource ); 
}

void ITASampleBuffer::mul_buf( const ITASampleBuffer& sbSource )
{ 
	mul_buf( &sbSource ); 
}

void ITASampleBuffer::div_buf( const ITASampleBuffer& sbSource )
{
	div_buf( &sbSource ); 
Jonas Stienen's avatar
Jonas Stienen committed
488 489
}

490 491 492 493
void ITASampleBuffer::MulAdd( const ITASampleBuffer* pSource, float fScalar, int iSrcOffset, int iDestOffset, int iCount ) 
{
	if( !pSource )
		ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
Jonas Stienen's avatar
Jonas Stienen committed
494

495 496 497 498 499 500
	if( iSrcOffset < 0 ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Invalid source offset" );
	if( iDestOffset < 0 ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Invalid destination offset" );
	if( iCount < 0 ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Invalid count" );
Jonas Stienen's avatar
Jonas Stienen committed
501 502

	// Test: Lesen innerhalb des Quellblockes
503 504 505 506
	if( ( iSrcOffset + iCount ) > pSource->GetLength() ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Source range exceeds source buffer" );
	if( ( iDestOffset + iCount ) > m_iLength ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Destination range exceeds destination buffer" );
Jonas Stienen's avatar
Jonas Stienen committed
507 508

	// Spezialfall: Count = 0 => Nichts zu tun
509 510
	if( iCount == 0 ) 
		return;
Jonas Stienen's avatar
Jonas Stienen committed
511 512

	// Spezialfall: Skalar = 0 => Nichts zu tun
513 514
	if( fScalar == 0 )
		return;
Jonas Stienen's avatar
Jonas Stienen committed
515

516 517
	for( int i = 0; i < iCount; i++ )
		m_pfData[ iDestOffset + i ] += ( pSource->m_pfData[ iSrcOffset + i ] * fScalar );
Jonas Stienen's avatar
Jonas Stienen committed
518 519
}

520 521
void ITASampleBuffer::MulAdd( const ITASampleBuffer& sbSource, float fScalar, int iSrcOffset, int iDestOffset, int iCount )
{
Jonas Stienen's avatar
Jonas Stienen committed
522 523 524
	MulAdd( &sbSource, fScalar, iSrcOffset, iDestOffset, iCount );
}

525 526 527 528 529 530
float ITASampleBuffer::FindPeak( int* piPeakIndex )
{
	if( m_iLength == 0 )
	{
		if( piPeakIndex )
			*piPeakIndex = 0;
Jonas Stienen's avatar
Jonas Stienen committed
531 532 533 534 535 536 537
		return 0;
	}

	float fPeak = 0;
	int iPeakIndex = 0;

	// TODO: Schnelle Implementierung? (SSE3?)
538 539 540 541 542
	for( int i = 0; i < m_iLength; i++ )
	{
		float x = fabs( m_pfData[ i ] );
		if( x > fPeak )
		{
Jonas Stienen's avatar
Jonas Stienen committed
543 544 545 546 547
			fPeak = x;
			iPeakIndex = i;
		}
	}

548 549 550
	if( piPeakIndex )
		*piPeakIndex = iPeakIndex;

Jonas Stienen's avatar
Jonas Stienen committed
551 552 553 554 555
	return fPeak;
}

void ITASampleBuffer::Negate()
{
556 557
	mul_scalar( -1 );
}
Jonas Stienen's avatar
Jonas Stienen committed
558

559 560 561
float& ITASampleBuffer::operator[]( int iSample )
{
	return m_pfData[ iSample ];
Jonas Stienen's avatar
Jonas Stienen committed
562 563
}

564 565 566
const float& ITASampleBuffer::operator[]( int iSample ) const
{
	return m_pfData[ iSample ];
Jonas Stienen's avatar
Jonas Stienen committed
567 568
}

569 570
ITASampleBuffer& ITASampleBuffer::operator=( const ITASampleBuffer& rhs )
{
Jonas Stienen's avatar
Jonas Stienen committed
571
	// Selbstzuweisung abfangen
572 573
	if( &rhs == this )
		return *this;
Jonas Stienen's avatar
Jonas Stienen committed
574

575 576
	if( m_pParent )
		ITA_EXCEPT1( MODAL_EXCEPTION, "Assignment impossible. Would change length, but sample buffer is part of a parent sample frame." );
Jonas Stienen's avatar
Jonas Stienen committed
577 578

	// Schnelle Abkürzung
579 580
	if( rhs.IsEmpty() )
	{
Jonas Stienen's avatar
Jonas Stienen committed
581 582 583 584
		Free();
		return *this;
	}

585
	if( ( m_iLength != rhs.m_iLength ) )
Jonas Stienen's avatar
Jonas Stienen committed
586 587
	{
		// Neu allozieren
588
		Init( rhs.GetLength(), false );
Jonas Stienen's avatar
Jonas Stienen committed
589 590 591
	}

	// Samples kopieren
592
	fm_copy( m_pfData, rhs.GetData(), m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
593 594 595 596

	return *this;
}

597 598 599
ITASampleBuffer& ITASampleBuffer::operator+=( float rhs )
{
	add_scalar( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
600 601 602
	return *this;
}

603 604 605
ITASampleBuffer& ITASampleBuffer::operator-=( float rhs )
{
	sub_scalar( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
606 607 608
	return *this;
}

609 610 611
ITASampleBuffer& ITASampleBuffer::operator*=( float rhs )
{
	mul_scalar( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
612 613 614
	return *this;
}

615 616 617
ITASampleBuffer& ITASampleBuffer::operator/=( float rhs )
{
	div_scalar( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
618 619 620
	return *this;
}

621 622 623
ITASampleBuffer& ITASampleBuffer::operator+=( const ITASampleBuffer& rhs )
{
	add_buf( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
624 625 626
	return *this;
}

627 628 629
ITASampleBuffer& ITASampleBuffer::operator-=( const ITASampleBuffer& rhs )
{
	sub_buf( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
630 631 632
	return *this;
}

633 634 635
ITASampleBuffer& ITASampleBuffer::operator*=( const ITASampleBuffer& rhs )
{
	mul_buf( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
636 637 638
	return *this;
}

639 640 641
ITASampleBuffer& ITASampleBuffer::operator/=( const ITASampleBuffer& rhs )
{
	div_buf( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
642 643 644
	return *this;
}

645 646
std::string ITASampleBuffer::toString() const
{
Jonas Stienen's avatar
Jonas Stienen committed
647 648
	std::stringstream ss;
	ss << "Sample buffer { ";
649
	if( IsEmpty() )
Jonas Stienen's avatar
Jonas Stienen committed
650 651 652 653 654 655
		ss << "emtpy";
	else
		ss << m_iLength << " samples";
	ss << " }";
	return ss.str();
}