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 16 17 18 19 20
	: m_pParent( NULL )
	, m_iLength( 0 )
	, m_pfData( NULL )
{

}
Jonas Stienen's avatar
Jonas Stienen committed
21

22
ITASampleBuffer::ITASampleBuffer( int iLength, bool bZeroinit )
23 24 25
	: m_pParent( NULL )
	, m_iLength( 0 )
	, m_pfData( NULL )
Jonas Stienen's avatar
Jonas Stienen committed
26
{
27
	Init( iLength, bZeroinit );
Jonas Stienen's avatar
Jonas Stienen committed
28 29
}

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

38 39
ITASampleBuffer::ITASampleBuffer( const ITASampleBuffer& sbSource )
	: m_pParent( NULL ), m_iLength( 0 ), m_pfData( NULL )
Jonas Stienen's avatar
Jonas Stienen committed
40 41 42 43 44 45 46 47 48
{
	*this = sbSource;
}

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

49
void ITASampleBuffer::Init( int iLength, bool bZeroInit )
Jonas Stienen's avatar
Jonas Stienen committed
50 51
{
	if( m_pParent )
52
		ITA_EXCEPT1( MODAL_EXCEPTION, "Init impossible. This sample buffer is a channel of a parent sample frame." );
Jonas Stienen's avatar
Jonas Stienen committed
53 54 55 56 57

	assert( iLength >= 0 );

	Free();

58 59 60
	m_iLength = iLength;

	size_t iBytes = size_t( iLength * sizeof( float ) );
Jonas Stienen's avatar
Jonas Stienen committed
61 62 63 64
#ifdef __GNUC__
	// TODO: Für den g++ erstmal kein aligned malloc
	m_pfData = (float*)malloc(iBytes);
#else
65
	m_pfData = ( float* ) _aligned_malloc( iBytes, 16 );
Jonas Stienen's avatar
Jonas Stienen committed
66
#endif
67 68 69

	if( bZeroInit )
		fm_zero( m_pfData, m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
70 71 72 73 74 75 76 77
}

void ITASampleBuffer::Free()
{
#ifdef __GNUC__
	if (m_pfData)
		free(m_pfData); // unaligned
#else
78
	if( m_pfData )
Jonas Stienen's avatar
Jonas Stienen committed
79 80 81 82 83 84 85 86
		_aligned_free( m_pfData );
#endif
	m_pfData = NULL;
	m_iLength = 0;
}

bool ITASampleBuffer::IsEmpty() const
{
87
	return ( m_iLength == 0 );
Jonas Stienen's avatar
Jonas Stienen committed
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
}

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

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

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

105
void ITASampleBuffer::Fill( float fValue )
Jonas Stienen's avatar
Jonas Stienen committed
106
{
107
	fm_set( m_pfData, fValue, m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
108 109
}

110 111 112 113
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
114

115 116
	if( ( iCount < 0 ) || ( iOffset + iCount > m_iLength ) )
		ITA_EXCEPT1( INVALID_PARAMETER, "Count out of range" );
Jonas Stienen's avatar
Jonas Stienen committed
117 118

	// TODO: Schnelle Implementierung?
119 120
	for( int i = iOffset; i < iOffset + iCount; i++ )
		m_pfData[ i ] = fValue;
Jonas Stienen's avatar
Jonas Stienen committed
121 122 123 124
}

void ITASampleBuffer::Zero()
{
125
	Fill( 0.0f );
Jonas Stienen's avatar
Jonas Stienen committed
126 127
}

128
void ITASampleBuffer::Zero( int iOffset, int iCount )
Jonas Stienen's avatar
Jonas Stienen committed
129
{
130
	Fill( iOffset, iCount, 0.0f );
Jonas Stienen's avatar
Jonas Stienen committed
131 132 133 134
}

void ITASampleBuffer::Identity()
{
135 136 137 138 139 140
	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
141 142
}

143
void ITASampleBuffer::Fade( int iOffset, int iCount, int iFadeDirection, int iFadeFunction )
Jonas Stienen's avatar
Jonas Stienen committed
144 145 146
{
	assert( iOffset >= 0 );
	assert( iCount > 0 );
147
	assert( ( iOffset + iCount ) <= m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
148 149 150

	int iFlags = 0;

151
	switch( iFadeDirection )
Jonas Stienen's avatar
Jonas Stienen committed
152 153 154 155 156 157
	{
	case FADE_IN:
		iFlags |= ITA_FADE_IN;
		break;
	case FADE_OUT:
		iFlags |= ITA_FADE_OUT;
158
		break;
Jonas Stienen's avatar
Jonas Stienen committed
159 160 161 162 163
	default:
		// Ungültiger Wert
		assert( false );
	}

164
	switch( iFadeFunction ) {
Jonas Stienen's avatar
Jonas Stienen committed
165 166 167 168 169
	case LINEAR:
		iFlags |= ITA_FADE_LINEAR;
		break;
	case COSINE_SQUARE:
		iFlags |= ITA_FADE_COSINE_SQUARE;
170
		break;
Jonas Stienen's avatar
Jonas Stienen committed
171 172 173 174 175
	default:
		// Ungültiger Wert
		assert( false );
	}

176
	::Fade( m_pfData + iOffset, iCount, iFlags );
Jonas Stienen's avatar
Jonas Stienen committed
177 178
}

179
void ITASampleBuffer::Crossfade( const ITASampleBuffer* psbSrc, int iOffset, int iCount, int iFadeDirection, int iFadeFunction )
Jonas Stienen's avatar
Jonas Stienen committed
180 181 182 183
{
	assert( psbSrc );
	assert( iOffset >= 0 );
	assert( iCount >= 0 );
184 185
	assert( ( iOffset + iCount ) <= m_iLength );
	assert( ( iOffset + iCount ) <= psbSrc->m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
186 187 188

	int iFlags = 0;

189 190
	switch( iFadeFunction )
	{
Jonas Stienen's avatar
Jonas Stienen committed
191 192 193 194 195
	case LINEAR:
		iFlags |= ITA_FADE_LINEAR;
		break;
	case COSINE_SQUARE:
		iFlags |= ITA_FADE_COSINE_SQUARE;
196
		break;
Jonas Stienen's avatar
Jonas Stienen committed
197 198 199 200 201
	default:
		// Ungültiger Wert
		assert( false );
	}

202 203
	switch( iFadeDirection )
	{
Jonas Stienen's avatar
Jonas Stienen committed
204 205
	case CROSSFADE_FROM_SOURCE:
		// Samples am Anfang kopieren
206 207 208
		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
209 210 211
		return;
	case CROSSFADE_TO_SOURCE:
		assert( psbSrc->m_iLength >= m_iLength );
212
		::Crossfade( m_pfData + iOffset, psbSrc->m_pfData + iOffset, m_pfData + iOffset, iCount, iFlags );
Jonas Stienen's avatar
Jonas Stienen committed
213
		// Samples am Ende kopieren
214 215
		for( int i = iOffset + iCount; i < m_iLength; i++ )
			m_pfData[ i ] = psbSrc->m_pfData[ i ];
Jonas Stienen's avatar
Jonas Stienen committed
216 217 218 219 220 221 222 223
		return;

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

224
void ITASampleBuffer::Crossfade( const ITASampleBuffer& sbSrc, int iOffset, int iCount, int iFadeDirection, int iFadeFunction )
Jonas Stienen's avatar
Jonas Stienen committed
225
{
226
	Crossfade( &sbSrc, iOffset, iCount, iFadeDirection, iFadeFunction );
Jonas Stienen's avatar
Jonas Stienen committed
227 228
}

229
void ITASampleBuffer::Envelope( float fGain0, float fGain1 )
Jonas Stienen's avatar
Jonas Stienen committed
230
{
231
	if( IsEmpty() ) return;
Jonas Stienen's avatar
Jonas Stienen committed
232 233

	// Linear interpolation
234 235 236
	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
237 238
}

239
void ITASampleBuffer::read( float* pfDest, int iCount, int iSrcOffset ) const
Jonas Stienen's avatar
Jonas Stienen committed
240 241 242
{
	assert( pfDest != NULL );
	assert( iCount >= 0 );
243 244
	assert( ( iSrcOffset >= 0 ) );
	assert( ( iSrcOffset + iCount ) <= m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
245 246

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

250
void ITASampleBuffer::write( const float* pfSrc, int iCount, int iDestOffset )
Jonas Stienen's avatar
Jonas Stienen committed
251 252 253
{
	assert( pfSrc != NULL );
	assert( iCount >= 0 );
254 255
	assert( ( iDestOffset >= 0 ) );
	assert( ( iDestOffset + iCount ) <= m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
256 257

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

261
void ITASampleBuffer::write( const ITASampleBuffer* psbSrc, int iCount, int iSrcOffset, int iDestOffset )
Jonas Stienen's avatar
Jonas Stienen committed
262 263 264
{
	assert( psbSrc != NULL );
	assert( iCount >= 0 );
265 266 267
	assert( ( iSrcOffset >= 0 ) );
	assert( ( iSrcOffset + iCount ) <= psbSrc->GetLength() );
	assert( ( iDestOffset + iCount ) <= m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
268 269

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

273 274 275
void ITASampleBuffer::write( const ITASampleBuffer& sbSrc, int iCount, int iSrcOffset, int iDestOffset )
{
	write( &sbSrc, iCount, iSrcOffset, iDestOffset );
Jonas Stienen's avatar
Jonas Stienen committed
276 277
}

278 279
void ITASampleBuffer::cyclic_read( float* pfDest, int iCount, int iSrcOffset ) const
{
Jonas Stienen's avatar
Jonas Stienen committed
280 281
	assert( pfDest != NULL );
	assert( iCount >= 0 );
282
	assert( ( iSrcOffset >= 0 ) && ( iSrcOffset < m_iLength ) );
Jonas Stienen's avatar
Jonas Stienen committed
283 284

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

287
	while( n < iCount ) {
Jonas Stienen's avatar
Jonas Stienen committed
288
		// Verbleibende Samples berechnen
289 290 291
		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
292 293 294 295
		n += r;
	}
}

296 297
void ITASampleBuffer::cyclic_write( const float* pfSrc, int iCount, int iDestOffset )
{
Jonas Stienen's avatar
Jonas Stienen committed
298 299 300 301
	assert( pfSrc != NULL );
	assert( iCount >= 0 );

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

304 305
	while( n < iCount )
	{
Jonas Stienen's avatar
Jonas Stienen committed
306
		// Verbleibende Samples berechnen
307 308 309
		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
310 311 312 313
		n += r;
	}
}

314 315
void ITASampleBuffer::cyclic_write( const ITASampleBuffer* psbSrc, int iCount, int iSrcOffset, int iDestOffset )
{
Jonas Stienen's avatar
Jonas Stienen committed
316 317 318 319 320 321 322
	assert( psbSrc != NULL );
	assert( iCount >= 0 );

	int iSrcLength = psbSrc->GetLength();

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

326 327
	while( n < iCount )
	{
Jonas Stienen's avatar
Jonas Stienen committed
328 329 330
		// Verbleibende Samples berechnen
		int rs = iSrcLength - p;
		int rd = m_iLength - q;
331 332 333 334
		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
335
		n += r;
336
	}
Jonas Stienen's avatar
Jonas Stienen committed
337 338
}

339 340 341
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
342 343 344
}


345
void ITASampleBuffer::CyclicShift( int iCount )
Jonas Stienen's avatar
Jonas Stienen committed
346
{
347 348 349 350
	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
351 352
}

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

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

363 364
void ITASampleBuffer::sub_scalar( float fValue )
{
Jonas Stienen's avatar
Jonas Stienen committed
365
	// Invariante
366 367
	if( fValue == 0 )
		return;
Jonas Stienen's avatar
Jonas Stienen committed
368 369

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

374 375
void ITASampleBuffer::mul_scalar( float fValue )
{
Jonas Stienen's avatar
Jonas Stienen committed
376
	// Invariante
377 378
	if( fValue == 1 )
		return;
Jonas Stienen's avatar
Jonas Stienen committed
379 380

	// TODO: Schnelle Implementierung?
381 382
	for( int i = 0; i < m_iLength; i++ )
		m_pfData[ i ] *= fValue;
Jonas Stienen's avatar
Jonas Stienen committed
383 384
}

385 386 387 388
void ITASampleBuffer::div_scalar( float fValue )
{
	if( fValue == 0 ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Division by zero" );
Jonas Stienen's avatar
Jonas Stienen committed
389 390

	// Invariante
391 392
	if( fValue == 1 ) 
		return;
Jonas Stienen's avatar
Jonas Stienen committed
393 394

	// TODO: Schnelle Implementierung?
395 396
	for( int i = 0; i < m_iLength; i++ ) 
		m_pfData[ i ] /= fValue;
Jonas Stienen's avatar
Jonas Stienen committed
397 398
}

399 400 401
void ITASampleBuffer::add_buf( const ITASampleBuffer* pSource )
{
	add_buf( pSource, pSource->GetLength() );
Jonas Stienen's avatar
Jonas Stienen committed
402 403
}

404 405 406 407 408 409 410 411
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
412

413
	fm_add( m_pfData, pSource->GetData(), iCount );
Jonas Stienen's avatar
Jonas Stienen committed
414 415
}

416
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
417
{
418 419
	if( !pSource ) 
		ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
Jonas Stienen's avatar
Jonas Stienen committed
420
	//if (pSource->GetLength() < iCount)  ITA_EXCEPT1(INVALID_PARAMETER, "Lengths of source buffer too small");
421 422
	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
423

424
	fm_add( &( m_pfData[ iPos ] ), pSource->GetData(), pSource->GetLength() );
Jonas Stienen's avatar
Jonas Stienen committed
425 426
}

427
void ITASampleBuffer::add_buf_pos( float* fSource, int iSize, int iPos )
Jonas Stienen's avatar
Jonas Stienen committed
428
{
429 430 431 432
	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
433

434
	fm_add( &( m_pfData[ iPos ] ), fSource, iSize );
Jonas Stienen's avatar
Jonas Stienen committed
435 436
}

437 438 439 440 441 442
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
443

444
	fm_sub( m_pfData, pSource->GetData(), m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
445 446
}

447 448 449 450 451 452
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
453 454 455

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

460 461 462 463 464 465
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
466 467 468 469

	// TODO: Schnelle Implementierung?
	// TODO: Was wenn Division durch Null?
	const float* pfSourceData = pSource->GetData();
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
	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
497 498
}

499 500 501 502
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
503

504 505 506 507 508 509
	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
510 511

	// Test: Lesen innerhalb des Quellblockes
512 513 514 515
	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
516 517

	// Spezialfall: Count = 0 => Nichts zu tun
518 519
	if( iCount == 0 ) 
		return;
Jonas Stienen's avatar
Jonas Stienen committed
520 521

	// Spezialfall: Skalar = 0 => Nichts zu tun
522 523
	if( fScalar == 0 )
		return;
Jonas Stienen's avatar
Jonas Stienen committed
524

525 526
	for( int i = 0; i < iCount; i++ )
		m_pfData[ iDestOffset + i ] += ( pSource->m_pfData[ iSrcOffset + i ] * fScalar );
Jonas Stienen's avatar
Jonas Stienen committed
527 528
}

529 530
void ITASampleBuffer::MulAdd( const ITASampleBuffer& sbSource, float fScalar, int iSrcOffset, int iDestOffset, int iCount )
{
Jonas Stienen's avatar
Jonas Stienen committed
531 532 533
	MulAdd( &sbSource, fScalar, iSrcOffset, iDestOffset, iCount );
}

534 535 536 537 538 539
float ITASampleBuffer::FindPeak( int* piPeakIndex )
{
	if( m_iLength == 0 )
	{
		if( piPeakIndex )
			*piPeakIndex = 0;
Jonas Stienen's avatar
Jonas Stienen committed
540 541 542 543 544 545 546
		return 0;
	}

	float fPeak = 0;
	int iPeakIndex = 0;

	// TODO: Schnelle Implementierung? (SSE3?)
547 548 549 550 551
	for( int i = 0; i < m_iLength; i++ )
	{
		float x = fabs( m_pfData[ i ] );
		if( x > fPeak )
		{
Jonas Stienen's avatar
Jonas Stienen committed
552 553 554 555 556
			fPeak = x;
			iPeakIndex = i;
		}
	}

557 558 559
	if( piPeakIndex )
		*piPeakIndex = iPeakIndex;

Jonas Stienen's avatar
Jonas Stienen committed
560 561 562 563 564
	return fPeak;
}

void ITASampleBuffer::Negate()
{
565 566
	mul_scalar( -1 );
}
Jonas Stienen's avatar
Jonas Stienen committed
567

568 569 570
float& ITASampleBuffer::operator[]( int iSample )
{
	return m_pfData[ iSample ];
Jonas Stienen's avatar
Jonas Stienen committed
571 572
}

573 574 575
const float& ITASampleBuffer::operator[]( int iSample ) const
{
	return m_pfData[ iSample ];
Jonas Stienen's avatar
Jonas Stienen committed
576 577
}

578 579
ITASampleBuffer& ITASampleBuffer::operator=( const ITASampleBuffer& rhs )
{
Jonas Stienen's avatar
Jonas Stienen committed
580
	// Selbstzuweisung abfangen
581 582
	if( &rhs == this )
		return *this;
Jonas Stienen's avatar
Jonas Stienen committed
583

584 585
	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
586 587

	// Schnelle Abkürzung
588 589
	if( rhs.IsEmpty() )
	{
Jonas Stienen's avatar
Jonas Stienen committed
590 591 592 593
		Free();
		return *this;
	}

594
	if( ( m_iLength != rhs.m_iLength ) )
Jonas Stienen's avatar
Jonas Stienen committed
595 596
	{
		// Neu allozieren
597
		Init( rhs.GetLength(), false );
Jonas Stienen's avatar
Jonas Stienen committed
598 599 600
	}

	// Samples kopieren
601
	fm_copy( m_pfData, rhs.GetData(), m_iLength );
Jonas Stienen's avatar
Jonas Stienen committed
602 603 604 605

	return *this;
}

606 607 608
ITASampleBuffer& ITASampleBuffer::operator+=( float rhs )
{
	add_scalar( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
609 610 611
	return *this;
}

612 613 614
ITASampleBuffer& ITASampleBuffer::operator-=( float rhs )
{
	sub_scalar( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
615 616 617
	return *this;
}

618 619 620
ITASampleBuffer& ITASampleBuffer::operator*=( float rhs )
{
	mul_scalar( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
621 622 623
	return *this;
}

624 625 626
ITASampleBuffer& ITASampleBuffer::operator/=( float rhs )
{
	div_scalar( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
627 628 629
	return *this;
}

630 631 632
ITASampleBuffer& ITASampleBuffer::operator+=( const ITASampleBuffer& rhs )
{
	add_buf( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
633 634 635
	return *this;
}

636 637 638
ITASampleBuffer& ITASampleBuffer::operator-=( const ITASampleBuffer& rhs )
{
	sub_buf( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
639 640 641
	return *this;
}

642 643 644
ITASampleBuffer& ITASampleBuffer::operator*=( const ITASampleBuffer& rhs )
{
	mul_buf( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
645 646 647
	return *this;
}

648 649 650
ITASampleBuffer& ITASampleBuffer::operator/=( const ITASampleBuffer& rhs )
{
	div_buf( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
651 652 653
	return *this;
}

654 655
std::string ITASampleBuffer::toString() const
{
Jonas Stienen's avatar
Jonas Stienen committed
656 657
	std::stringstream ss;
	ss << "Sample buffer { ";
658
	if( IsEmpty() )
Jonas Stienen's avatar
Jonas Stienen committed
659 660 661 662 663 664
		ss << "emtpy";
	else
		ss << m_iLength << " samples";
	ss << " }";
	return ss.str();
}