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

#include <math.h>
#include <portaudio.h>
#include <vector>

Anne's avatar
Anne committed
7 8
#include <ITADataSource.h>
#include <ITADataSourceRealization.h>
Jonas Stienen's avatar
Jonas Stienen committed
9 10
#include <ITAStreamInfo.h>

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
11 12
class PaStreamCallbackTimeInfo;

Jonas Stienen's avatar
Jonas Stienen committed
13
// Portaudio Callback Function
14
static int PortaudioCallbackFunction( const void*, void*, unsigned long, const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags, void* );
Jonas Stienen's avatar
Jonas Stienen committed
15

16 17
class ITAPortaudioSource : public ITADatasourceRealization
{
Jonas Stienen's avatar
Jonas Stienen committed
18
public:
19
	inline ITAPortaudioSource( int iChannels, double dSampleRate, int iBufferSize )
20
		: ITADatasourceRealization( ( unsigned int ) iChannels, dSampleRate, ( unsigned int ) iBufferSize, 16 ) {};
Jonas Stienen's avatar
Jonas Stienen committed
21 22 23
};


24
ITAPortaudioInterface::ITAPortaudioInterface( double dSampleRate, int iBufferSize )
25
	: m_vpPaStream( NULL )
Jonas Stienen's avatar
Jonas Stienen committed
26 27 28 29
{
	m_dSampleRate = dSampleRate;
	m_iBufferSize = iBufferSize; // Darf 0 sein

30
	if( m_iBufferSize == 0 )
Jonas Stienen's avatar
Jonas Stienen committed
31 32 33 34 35 36 37 38 39 40 41 42
		m_iBufferSize = GetPreferredBufferSize();

	m_iNumInputChannels = -1;
	m_iNumOutputChannels = -1;
	m_sConfigFile.clear();

	m_bInitialized = false;
	m_bOpen = false;
	m_bStreaming = false;

	m_bRecord = false;
	m_bPlayback = false;
43

Jonas Stienen's avatar
Jonas Stienen committed
44 45 46
	m_iError = ITA_PA_NO_ERROR;
}

47 48
ITAPortaudioInterface::~ITAPortaudioInterface()
{
Jonas Stienen's avatar
Jonas Stienen committed
49
}
50

51
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::Initialize( const std::string& )
52
{
Jonas Stienen's avatar
Jonas Stienen committed
53 54 55
	return ITA_PA_INVALID_DEVICE;
}

56 57
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::Initialize( int iDriverID )
{
58
	if( m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
59 60
		return ITA_PA_IS_INITIALIZED;

61
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
62 63
		return ITA_PA_IS_OPEN;

64
	if( m_bStreaming )
Jonas Stienen's avatar
Jonas Stienen committed
65 66
		return ITA_PA_IS_STARTED;

67
	m_iError = ( ITA_PA_ERRORCODE ) Pa_Initialize();
Jonas Stienen's avatar
Jonas Stienen committed
68

69
	if( m_iError != ITA_PA_NO_ERROR )
Jonas Stienen's avatar
Jonas Stienen committed
70 71
		return m_iError;

72
	if( iDriverID < 0 || iDriverID >= Pa_GetDeviceCount() ) {
Jonas Stienen's avatar
Jonas Stienen committed
73 74 75 76 77 78 79 80 81
		Pa_Terminate();
		m_bInitialized = false;
		return ITA_PA_INVALID_DEVICE;
	}

	m_bInitialized = true;

	m_iDriverID = iDriverID;

82 83 84
	m_iNumInputChannels = GetNumInputChannels( m_iDriverID );
	m_iNumOutputChannels = GetNumOutputChannels( m_iDriverID );

Jonas Stienen's avatar
Jonas Stienen committed
85 86 87 88

	return ITA_PA_NO_ERROR;
}

89 90
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::Initialize()
{
91
	if( m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
92 93
		return ITA_PA_IS_INITIALIZED;

94
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
95 96
		return ITA_PA_IS_OPEN;

97
	if( m_bStreaming )
Jonas Stienen's avatar
Jonas Stienen committed
98
		return ITA_PA_IS_STARTED;
99 100 101 102

	m_iError = ( ITA_PA_ERRORCODE ) Pa_Initialize();

	if( m_iError != ITA_PA_NO_ERROR ) {
Jonas Stienen's avatar
Jonas Stienen committed
103 104 105 106 107 108 109 110 111
		Pa_Terminate();
		m_bInitialized = false;
		return m_iError;
	}

	m_bInitialized = true;

	m_iDriverID = Pa_GetDefaultOutputDevice();

112 113
	m_iNumOutputChannels = GetNumOutputChannels( m_iDriverID );
	m_iNumInputChannels = GetNumInputChannels( m_iDriverID );
Jonas Stienen's avatar
Jonas Stienen committed
114 115 116 117 118


	return ITA_PA_NO_ERROR;
}

119 120
bool ITAPortaudioInterface::IsPlaybackEnabled() const
{
Jonas Stienen's avatar
Jonas Stienen committed
121 122 123
	return m_bPlayback;
}

124 125
void ITAPortaudioInterface::SetPlaybackEnabled( bool bEnabled )
{
Jonas Stienen's avatar
Jonas Stienen committed
126 127 128 129 130 131 132
	m_bPlayback = bEnabled;
}

bool ITAPortaudioInterface::IsRecordEnabled() const {
	return m_bRecord;
}

133 134
void ITAPortaudioInterface::SetRecordEnabled( bool bEnabled )
{
Jonas Stienen's avatar
Jonas Stienen committed
135 136 137
	m_bRecord = bEnabled;
}

138 139
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::Finalize()
{
140
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
141 142
		return ITA_PA_NOT_INITIALIZED;

143
	if( m_bStreaming )
Jonas Stienen's avatar
Jonas Stienen committed
144
		return ITA_PA_IS_STARTED;
145 146

	m_iError = ( ITA_PA_ERRORCODE ) Pa_Terminate();
Jonas Stienen's avatar
Jonas Stienen committed
147 148 149

	m_iDriverID = -1;

150
	if( m_iError == ITA_PA_NO_ERROR )
Jonas Stienen's avatar
Jonas Stienen committed
151 152
		m_bInitialized = false;

153
	if( m_oUserData.pdsRecordDatasource != NULL ) {
Jonas Stienen's avatar
Jonas Stienen committed
154 155 156 157 158 159 160 161
		delete m_oUserData.pdsRecordDatasource;
		m_oUserData.pdsRecordDatasource = NULL;
	}

	return m_iError;
}


162 163
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::Open()
{
164
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
165 166
		return ITA_PA_NOT_INITIALIZED;

167
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
168 169
		return ITA_PA_IS_OPEN;

170
	if( m_oUserData.pdsPlaybackDatasource == NULL && m_bPlayback )
Jonas Stienen's avatar
Jonas Stienen committed
171 172
		return ITA_PA_NO_PLAYBACK_DATASOURCE;

173
	if( m_oUserData.pdsRecordDatasource == NULL && m_bRecord )
Jonas Stienen's avatar
Jonas Stienen committed
174 175 176
		return ITA_PA_NO_RECORD_DATASOURCE;


177 178
	if( m_bRecord ) {
		if( ( int ) m_oUserData.pdsRecordDatasource->GetNumberOfChannels() > m_iNumInputChannels )
Jonas Stienen's avatar
Jonas Stienen committed
179 180 181 182 183
			return ITA_PA_UNMATCHED_CHANNELS;

		m_oUserData.bRecord = true;
	}

184 185
	if( m_bPlayback ) {
		if( ( int ) m_oUserData.pdsPlaybackDatasource->GetNumberOfChannels() > m_iNumOutputChannels )
Jonas Stienen's avatar
Jonas Stienen committed
186 187 188 189 190 191
			return ITA_PA_UNMATCHED_CHANNELS;

		m_oUserData.bPlayback = true;
	}

	PaStream* stream;
192

Jonas Stienen's avatar
Jonas Stienen committed
193
	PaStreamParameters inparams;
194
	inparams.channelCount = GetNumInputChannels( m_iDriverID );
Jonas Stienen's avatar
Jonas Stienen committed
195 196
	inparams.device = m_iDriverID;
	inparams.sampleFormat = paFloat32;
197
	inparams.suggestedLatency = Pa_GetDeviceInfo( inparams.device )->defaultLowInputLatency;
Jonas Stienen's avatar
Jonas Stienen committed
198 199 200
	inparams.hostApiSpecificStreamInfo = NULL;

	PaStreamParameters* pInParams = NULL;
201
	if( inparams.channelCount > 0 )
Jonas Stienen's avatar
Jonas Stienen committed
202 203 204
		pInParams = &inparams;

	PaStreamParameters outparams;
205
	outparams.channelCount = GetNumOutputChannels( m_iDriverID );
Jonas Stienen's avatar
Jonas Stienen committed
206 207
	outparams.device = m_iDriverID;
	outparams.sampleFormat = paFloat32;
208
	outparams.suggestedLatency = Pa_GetDeviceInfo( outparams.device )->defaultLowOutputLatency;
Jonas Stienen's avatar
Jonas Stienen committed
209 210 211
	outparams.hostApiSpecificStreamInfo = NULL;

	PaStreamParameters* pOutParams = NULL;
212
	if( outparams.channelCount > 0 )
Jonas Stienen's avatar
Jonas Stienen committed
213 214
		pOutParams = &outparams;

215
	m_iError = ( ITA_PA_ERRORCODE ) Pa_OpenStream( &stream, pInParams, pOutParams, m_dSampleRate, m_iBufferSize, paNoFlag, PortaudioCallbackFunction, &m_oUserData );
Jonas Stienen's avatar
Jonas Stienen committed
216

217 218
	if( m_iError == ITA_PA_NO_ERROR )
	{
219
		m_vpPaStream = ( void* ) stream;
Jonas Stienen's avatar
Jonas Stienen committed
220
		m_bOpen = true;
221
	}
222 223
	else
	{
Jonas Stienen's avatar
Jonas Stienen committed
224 225 226 227 228 229
		m_vpPaStream = NULL;
	}

	return m_iError;
}

230 231
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::Close()
{
232
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
233 234
		return ITA_PA_NOT_INITIALIZED;

235
	if( !m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
236 237
		return ITA_PA_IS_NOT_OPEN;

238 239
	PaStream* stream = ( PaStream* ) m_vpPaStream;
	m_iError = ( ITA_PA_ERRORCODE ) Pa_CloseStream( stream );
Jonas Stienen's avatar
Jonas Stienen committed
240

241
	if( m_iError == ITA_PA_NO_ERROR ) {
Jonas Stienen's avatar
Jonas Stienen committed
242 243 244 245 246 247 248
		m_vpPaStream = NULL;
		m_bOpen = false;
	}

	return m_iError;
}

249 250
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::Start()
{
251
	if( m_bStreaming )
Jonas Stienen's avatar
Jonas Stienen committed
252 253
		return ITA_PA_IS_STARTED;

254
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
255 256
		return ITA_PA_NOT_INITIALIZED;

257
	if( !m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
258 259
		return ITA_PA_IS_NOT_OPEN;

260
	if( !m_vpPaStream )
Jonas Stienen's avatar
Jonas Stienen committed
261 262
		return ITA_PA_INTERNAL_ERROR;

263 264 265 266
	PaStream* stream = ( PaStream* ) m_vpPaStream;
	m_iError = ( ITA_PA_ERRORCODE ) Pa_StartStream( stream );

	if( m_iError == ITA_PA_NO_ERROR )
Jonas Stienen's avatar
Jonas Stienen committed
267 268 269
		m_bStreaming = true;
	else
		m_bStreaming = false;
270 271

	return m_iError;
Jonas Stienen's avatar
Jonas Stienen committed
272 273
}

274 275
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::Stop()
{
276
	if( !m_bStreaming )
Jonas Stienen's avatar
Jonas Stienen committed
277 278
		return ITA_PA_STREAM_IS_STOPPED;

279
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
280 281
		return ITA_PA_NOT_INITIALIZED;

282 283
	PaStream* stream = ( PaStream* ) m_vpPaStream;
	m_iError = ( ITA_PA_ERRORCODE ) Pa_StopStream( stream );
Jonas Stienen's avatar
Jonas Stienen committed
284

285
	if( m_iError == ITA_PA_NO_ERROR )
Jonas Stienen's avatar
Jonas Stienen committed
286 287 288 289 290 291
		m_bStreaming = false;

	return m_iError;
}

int ITAPortaudioInterface::GetNumDevices() const {
292
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
293 294 295 296 297 298
		return -1;

	return Pa_GetDeviceCount();

}

299 300
int ITAPortaudioInterface::GetNumInputChannels( int iDeviceID ) const
{
301
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
302 303 304
		return ITA_PA_NOT_INITIALIZED;

	const PaDeviceInfo* info;
305
	info = Pa_GetDeviceInfo( iDeviceID );
Jonas Stienen's avatar
Jonas Stienen committed
306 307 308 309

	return info->maxInputChannels;
}

310 311
int ITAPortaudioInterface::GetNumOutputChannels( int iDeviceID ) const
{
312
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
313 314 315
		return ITA_PA_NOT_INITIALIZED;

	const PaDeviceInfo* info;
316
	info = Pa_GetDeviceInfo( iDeviceID );
Jonas Stienen's avatar
Jonas Stienen committed
317 318 319 320

	return info->maxOutputChannels;
}

321 322
double ITAPortaudioInterface::GetSampleRate() const
{
Jonas Stienen's avatar
Jonas Stienen committed
323 324 325
	return m_dSampleRate;
}

326 327
void ITAPortaudioInterface::GetNumChannels( int iDeviceID, int& iNumInputChannels, int& iNumOutputChannels ) const
{
328 329
	iNumInputChannels = GetNumInputChannels( iDeviceID );
	iNumOutputChannels = GetNumOutputChannels( iDeviceID );
Jonas Stienen's avatar
Jonas Stienen committed
330 331
}

332 333
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::GetDriverSampleRate( int iDeviceID, double& dSampleRate ) const
{
334
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
335 336 337
		return ITA_PA_NOT_INITIALIZED;

	const PaDeviceInfo* info;
338
	info = Pa_GetDeviceInfo( iDeviceID );
Jonas Stienen's avatar
Jonas Stienen committed
339 340 341 342 343 344

	dSampleRate = info->defaultSampleRate;

	return ITA_PA_NO_ERROR;
}

345 346
std::string ITAPortaudioInterface::GetDeviceName( int iDriverID ) const
{
347
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
348 349 350
		return "Portaudio not initialized";

	const PaDeviceInfo* info;
351
	info = Pa_GetDeviceInfo( iDriverID );
Jonas Stienen's avatar
Jonas Stienen committed
352

353
	if( info == NULL )
Jonas Stienen's avatar
Jonas Stienen committed
354 355 356 357 358
		return "";

	return info->name;
}

359 360
float ITAPortaudioInterface::GetDeviceLatency( int iDriverID ) const
{
361
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
362 363 364
		return -1;

	const PaDeviceInfo* info;
365
	info = Pa_GetDeviceInfo( iDriverID );
Jonas Stienen's avatar
Jonas Stienen committed
366

367
	if( info == NULL )
Jonas Stienen's avatar
Jonas Stienen committed
368 369
		return -1;

370
	return ( float ) info->defaultLowOutputLatency;
Jonas Stienen's avatar
Jonas Stienen committed
371 372
}

373 374
int ITAPortaudioInterface::GetDefaultInputDevice() const
{
Jonas Stienen's avatar
Jonas Stienen committed
375
	int iDefaultInputDevice;
376
	if( !m_bInitialized ) {
Jonas Stienen's avatar
Jonas Stienen committed
377
		Pa_Initialize();
378
		iDefaultInputDevice = ( int ) Pa_GetDefaultInputDevice();
Jonas Stienen's avatar
Jonas Stienen committed
379
		Pa_Terminate();
380 381 382
	}
	else {
		iDefaultInputDevice = ( int ) Pa_GetDefaultInputDevice();
Jonas Stienen's avatar
Jonas Stienen committed
383 384 385 386 387
	}

	return iDefaultInputDevice;
}

388 389
int ITAPortaudioInterface::GetDefaultOutputDevice() const
{
Jonas Stienen's avatar
Jonas Stienen committed
390
	int iDefaultOutputDevice;
391
	if( !m_bInitialized ) {
Jonas Stienen's avatar
Jonas Stienen committed
392
		Pa_Initialize();
393
		iDefaultOutputDevice = ( int ) Pa_GetDefaultOutputDevice();
Jonas Stienen's avatar
Jonas Stienen committed
394
		Pa_Terminate();
395 396 397
	}
	else {
		iDefaultOutputDevice = ( int ) Pa_GetDefaultOutputDevice();
Jonas Stienen's avatar
Jonas Stienen committed
398 399 400 401 402
	}

	return iDefaultOutputDevice;
}

403 404
ITAPortaudioInterface::ITA_PA_ERRORCODE ITAPortaudioInterface::SetPlaybackDatasource( ITADatasource* pidsDatasource )
{
405
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
406 407
		return ITA_PA_NOT_INITIALIZED;

408
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
409 410
		return ITA_PA_IS_OPEN;

411
	if( int( pidsDatasource->GetBlocklength() ) != m_iBufferSize )
Jonas Stienen's avatar
Jonas Stienen committed
412 413
		return ITA_PA_UNMATCHED_BUFFER_SIZE;

414
	if( pidsDatasource->GetSampleRate() != m_dSampleRate )
Jonas Stienen's avatar
Jonas Stienen committed
415 416 417 418 419 420 421 422 423
		return ITA_PA_UNMATCHED_SAMPLE_RATE;

	m_oUserData.pdsPlaybackDatasource = pidsDatasource;

	m_bPlayback = true;

	return ITA_PA_NO_ERROR;
}

424 425
ITADatasource* ITAPortaudioInterface::GetRecordDatasource()
{
426
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
427 428
		return NULL;

429
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
430 431
		return NULL;

432 433
	if( m_oUserData.pdsRecordDatasource == NULL )
		m_oUserData.pdsRecordDatasource = new ITAPortaudioSource( m_iNumInputChannels, m_dSampleRate, m_iBufferSize );
Jonas Stienen's avatar
Jonas Stienen committed
434 435 436 437 438 439

	m_bRecord = true;

	return m_oUserData.pdsRecordDatasource;
}

440 441
void ITAPortaudioInterface::Sleep( float fSeconds ) const
{
442
	Pa_Sleep( ( long ) fSeconds * 1000 );
Jonas Stienen's avatar
Jonas Stienen committed
443 444 445 446

	return;
}

447 448
std::string ITAPortaudioInterface::GetErrorCodeString( ITA_PA_ERRORCODE err )
{
449
	if( err == ITA_PA_NOT_INITIALIZED )
Jonas Stienen's avatar
Jonas Stienen committed
450
		return "Portaudio not initialized";
451
	if( err == ITA_PA_INVALID_CHANNEL_COUNT )
Jonas Stienen's avatar
Jonas Stienen committed
452
		return "Portaudio invalid channel count";
453
	if( err == ITA_PA_UNMATCHED_CHANNELS )
Jonas Stienen's avatar
Jonas Stienen committed
454
		return "Portaudio channels are not matching";
455
	if( err == ITA_PA_SAMPLE_FORMAT_NOT_SUPPORTED )
Jonas Stienen's avatar
Jonas Stienen committed
456
		return "Portaudio sample format not supported";
457
	if( err == ITA_PA_UNANTICIPATED_HOST_ERROR )
Jonas Stienen's avatar
Jonas Stienen committed
458
		return "Portaudio unanticipated host error";
459
	if( err == ITA_PA_INVALID_DEVICE )
Jonas Stienen's avatar
Jonas Stienen committed
460
		return "Portaudio invalid device";
461
	if( err == ITA_PA_NO_PLAYBACK_DATASOURCE )
Jonas Stienen's avatar
Jonas Stienen committed
462
		return "Portaudio no datasource for playback available";
463
	if( err == ITA_PA_NO_PLAYBACK_DATASOURCE )
Jonas Stienen's avatar
Jonas Stienen committed
464
		return "Portaudio no datasource for recording available";
465
	if( err == ITA_PA_DEVICE_UNAVAILABLE )
Jonas Stienen's avatar
Jonas Stienen committed
466 467 468 469 470 471 472 473 474 475 476
		return "Portaudio device not available";

	return "Unkown error code";
}

int ITAPortaudioInterface::GetPreferredBufferSize()
{
	return 256;
}

// Portaudio streaming callback function
477 478
static int PortaudioCallbackFunction( const void* pInBuffer, void* pOutBuffer, unsigned long ulBuffersize,
	const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags, void* pUserData )
Jonas Stienen's avatar
Jonas Stienen committed
479 480 481 482 483
{

	// --= User data =--

	ITAPortaudioInterface::ITAPortaudioUserData* pipudDatasource;
484
	if( pUserData == NULL )
Jonas Stienen's avatar
Jonas Stienen committed
485
		return -1;
486 487
	else
		pipudDatasource = ( ITAPortaudioInterface::ITAPortaudioUserData* ) pUserData;
Jonas Stienen's avatar
Jonas Stienen committed
488 489


490
	ITAPortaudioSource* pipdsRecordDatasource = ( ITAPortaudioSource* ) pipudDatasource->pdsRecordDatasource;
Jonas Stienen's avatar
Jonas Stienen committed
491 492 493 494 495
	ITADatasource* pipdsPlaybackDatasource = pipudDatasource->pdsPlaybackDatasource;
	bool bRecord = pipudDatasource->bRecord;
	bool bPlayback = pipudDatasource->bPlayback;

	ITAStreamInfo oStreamInfo; // DICKES TODO HIER
496

Jonas Stienen's avatar
Jonas Stienen committed
497 498
	// --= Input device =--

499
	float* in = ( float* ) pInBuffer;
Jonas Stienen's avatar
Jonas Stienen committed
500

501 502
	if( bRecord )
	{
Jonas Stienen's avatar
Jonas Stienen committed
503
		int iNumInputChannels = pipdsRecordDatasource->GetNumberOfChannels();
504 505 506 507 508
		float* pInDataBlock;
		for( unsigned int i = 0; i < ulBuffersize; i++ )
		{
			for( int j = 0; j < iNumInputChannels; j++ )
			{
Jonas Stienen's avatar
Jonas Stienen committed
509
				int index = i*iNumInputChannels + j;
510 511 512 513
				pInDataBlock = pipdsRecordDatasource->GetWritePointer( j );
				float fValue = in[ index ];
				if( pInDataBlock )
					pInDataBlock[ i ] = fValue;
Jonas Stienen's avatar
Jonas Stienen committed
514 515 516 517 518 519 520 521
			}
		}
		pipdsRecordDatasource->IncrementWritePointer();
	}


	// --= Output device =--

522
	float* out = ( float* ) pOutBuffer;
Jonas Stienen's avatar
Jonas Stienen committed
523

524 525
	if( bPlayback )
	{
Jonas Stienen's avatar
Jonas Stienen committed
526
		int iNumOutputChannels = pipdsPlaybackDatasource->GetNumberOfChannels();
527
		const float* pOutDataBlock;
528 529 530 531
		std::vector< const float* > vpBlockPointer( iNumOutputChannels );
		for( int j = 0; j < iNumOutputChannels; j++ )
			vpBlockPointer[ j ] = pipdsPlaybackDatasource->GetBlockPointer( j, &oStreamInfo );

532 533 534 535
		for( unsigned int i = 0; i < ulBuffersize; i++ )
		{
			for( int j = 0; j < iNumOutputChannels; j++ )
			{
Jonas Stienen's avatar
Jonas Stienen committed
536
				int index = i*iNumOutputChannels + j;
537
				pOutDataBlock = vpBlockPointer[ j ];
538 539
				float fValue = pOutDataBlock ? pOutDataBlock[ i ] : 0.0f;
				out[ index ] = fValue;
Jonas Stienen's avatar
Jonas Stienen committed
540 541 542 543 544 545 546
			}
		}
		pipdsPlaybackDatasource->IncrementBlockPointer();
	}

	return 0;
}