ITAPortaudioInterface.cpp 12.6 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
11
#include <ITAStreamInfo.h>

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

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


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

28
	if( m_iBufferSize == 0 )
Jonas Stienen's avatar
Jonas Stienen committed
29
30
31
32
33
34
35
36
37
38
39
40
		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;
41

Jonas Stienen's avatar
Jonas Stienen committed
42
43
44
	m_iError = ITA_PA_NO_ERROR;
}

45
46
ITAPortaudioInterface::~ITAPortaudioInterface()
{
Jonas Stienen's avatar
Jonas Stienen committed
47
}
48

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

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

59
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
60
61
		return ITA_PA_IS_OPEN;

62
	if( m_bStreaming )
Jonas Stienen's avatar
Jonas Stienen committed
63
64
		return ITA_PA_IS_STARTED;

65
	m_iError = ( ITA_PA_ERRORCODE ) Pa_Initialize();
Jonas Stienen's avatar
Jonas Stienen committed
66

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

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

	m_bInitialized = true;

	m_iDriverID = iDriverID;

80
81
82
	m_iNumInputChannels = GetNumInputChannels( m_iDriverID );
	m_iNumOutputChannels = GetNumOutputChannels( m_iDriverID );

Jonas Stienen's avatar
Jonas Stienen committed
83
84
85
86

	return ITA_PA_NO_ERROR;
}

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

92
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
93
94
		return ITA_PA_IS_OPEN;

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

	m_iError = ( ITA_PA_ERRORCODE ) Pa_Initialize();

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

	m_bInitialized = true;

	m_iDriverID = Pa_GetDefaultOutputDevice();

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


	return ITA_PA_NO_ERROR;
}

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

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

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

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

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

141
	if( m_bStreaming )
Jonas Stienen's avatar
Jonas Stienen committed
142
		return ITA_PA_IS_STARTED;
143
144

	m_iError = ( ITA_PA_ERRORCODE ) Pa_Terminate();
Jonas Stienen's avatar
Jonas Stienen committed
145
146
147

	m_iDriverID = -1;

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

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

	return m_iError;
}


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

165
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
166
167
		return ITA_PA_IS_OPEN;

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

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


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

		m_oUserData.bRecord = true;
	}

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

		m_oUserData.bPlayback = true;
	}

	PaStream* stream;
190

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

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

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

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

213
	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
214

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

	return m_iError;
}

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

233
	if( !m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
234
235
		return ITA_PA_IS_NOT_OPEN;

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

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

	return m_iError;
}

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

252
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
253
254
		return ITA_PA_NOT_INITIALIZED;

255
	if( !m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
256
257
		return ITA_PA_IS_NOT_OPEN;

258
	if( !m_vpPaStream )
Jonas Stienen's avatar
Jonas Stienen committed
259
260
		return ITA_PA_INTERNAL_ERROR;

261
262
263
264
	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
265
266
267
		m_bStreaming = true;
	else
		m_bStreaming = false;
268
269

	return m_iError;
Jonas Stienen's avatar
Jonas Stienen committed
270
271
}

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

277
	if( !m_bInitialized )
Jonas Stienen's avatar
Jonas Stienen committed
278
279
		return ITA_PA_NOT_INITIALIZED;

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

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

	return m_iError;
}

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

	return Pa_GetDeviceCount();

}

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

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

	return info->maxInputChannels;
}

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

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

	return info->maxOutputChannels;
}

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

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

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

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

	dSampleRate = info->defaultSampleRate;

	return ITA_PA_NO_ERROR;
}

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

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

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

	return info->name;
}

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

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

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

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

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

	return iDefaultInputDevice;
}

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

	return iDefaultOutputDevice;
}

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

406
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
407
408
		return ITA_PA_IS_OPEN;

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

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

	m_oUserData.pdsPlaybackDatasource = pidsDatasource;

	m_bPlayback = true;

	return ITA_PA_NO_ERROR;
}

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

427
	if( m_bOpen )
Jonas Stienen's avatar
Jonas Stienen committed
428
429
		return NULL;

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

	m_bRecord = true;

	return m_oUserData.pdsRecordDatasource;
}

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

	return;
}

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

	return "Unkown error code";
}

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

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

	// --= User data =--

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


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

	ITAStreamInfo oStreamInfo; // DICKES TODO HIER
494

Jonas Stienen's avatar
Jonas Stienen committed
495
496
	// --= Input device =--

497
	float* in = ( float* ) pInBuffer;
Jonas Stienen's avatar
Jonas Stienen committed
498

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


	// --= Output device =--

520
	float* out = ( float* ) pOutBuffer;
Jonas Stienen's avatar
Jonas Stienen committed
521

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

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

	return 0;
}