200
200
unsigned long framesPerBuffer,
201
201
PaStreamFlags streamFlags,
202
202
PaStreamCallback *streamCallback,
204
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
204
static PaError IsFormatSupported (struct PaUtilHostApiRepresentation *hostApi,
205
205
const PaStreamParameters *inputParameters,
206
206
const PaStreamParameters *outputParameters,
208
static PaError CloseStream( PaStream* stream );
209
static PaError StartStream( PaStream *stream );
210
static PaError StopStream( PaStream *stream );
211
static PaError AbortStream( PaStream *stream );
212
static PaError IsStreamStopped( PaStream *s );
213
static PaError IsStreamActive( PaStream *stream );
214
static PaTime GetStreamTime( PaStream *stream );
215
static double GetStreamCpuLoad( PaStream* stream );
216
static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
217
static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );
218
static signed long GetStreamReadAvailable( PaStream* stream );
219
static signed long GetStreamWriteAvailable( PaStream* stream );
208
static PaError CloseStream (PaStream* stream);
209
static PaError StartStream (PaStream *stream);
210
static PaError StopStream (PaStream *stream);
211
static PaError AbortStream (PaStream *stream);
212
static PaError IsStreamStopped (PaStream *s);
213
static PaError IsStreamActive (PaStream *stream);
214
static PaTime GetStreamTime (PaStream *stream);
215
static double GetStreamCpuLoad (PaStream* stream);
216
static PaError ReadStream (PaStream* stream, void *buffer, unsigned long frames);
217
static PaError WriteStream (PaStream* stream, const void *buffer, unsigned long frames);
218
static signed long GetStreamReadAvailable (PaStream* stream);
219
static signed long GetStreamWriteAvailable (PaStream* stream);
221
221
/* Blocking i/o callback function. */
222
static int BlockingIoPaCallback(const void *inputBuffer ,
224
unsigned long framesPerBuffer,
225
const PaStreamCallbackTimeInfo *timeInfo ,
226
PaStreamCallbackFlags statusFlags ,
222
static int BlockingIoPaCallback (const void *inputBuffer ,
224
unsigned long framesPerBuffer,
225
const PaStreamCallbackTimeInfo *timeInfo ,
226
PaStreamCallbackFlags statusFlags ,
229
229
/* our ASIO callback functions */
231
static void bufferSwitch(long index, ASIOBool processNow);
232
static ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow);
233
static void sampleRateChanged(ASIOSampleRate sRate);
234
static long asioMessages(long selector, long value, void* message, double* opt);
231
static void bufferSwitch (long index, ASIOBool processNow);
232
static ASIOTime *bufferSwitchTimeInfo (ASIOTime *timeInfo, long index, ASIOBool processNow);
233
static void sampleRateChanged (ASIOSampleRate sRate);
234
static long asioMessages (long selector, long value, void* message, double* opt);
236
static ASIOCallbacks asioCallbacks_ =
237
{ bufferSwitch, sampleRateChanged, asioMessages, bufferSwitchTimeInfo };
236
static ASIOCallbacks asioCallbacks_ = { bufferSwitch, sampleRateChanged, asioMessages, bufferSwitchTimeInfo };
240
239
#define PA_ASIO_SET_LAST_HOST_ERROR( errorCode, errorText ) \
241
240
PaUtil_SetLastHostErrorInfo( paASIO, errorCode, errorText )
244
static void PaAsio_SetLastSystemError( DWORD errorCode )
243
static void PaAsio_SetLastSystemError (DWORD errorCode)
248
247
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
251
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
250
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
252
251
(LPTSTR) &lpMsgBuf,
256
PaUtil_SetLastHostErrorInfo( paASIO, errorCode, (const char*)lpMsgBuf );
257
LocalFree( lpMsgBuf );
255
PaUtil_SetLastHostErrorInfo (paASIO, errorCode, (const char*) lpMsgBuf);
256
LocalFree (lpMsgBuf);
260
259
#define PA_ASIO_SET_LAST_SYSTEM_ERROR( errorCode ) \
261
260
PaAsio_SetLastSystemError( errorCode )
264
static const char* PaAsio_GetAsioErrorText( ASIOError asioError )
263
static const char* PaAsio_GetAsioErrorText (ASIOError asioError)
266
265
const char *result;
270
case ASE_SUCCESS: result = "Success"; break;
271
case ASE_NotPresent: result = "Hardware input or output is not present or available"; break;
272
case ASE_HWMalfunction: result = "Hardware is malfunctioning"; break;
273
case ASE_InvalidParameter: result = "Input parameter invalid"; break;
274
case ASE_InvalidMode: result = "Hardware is in a bad mode or used in a bad mode"; break;
275
case ASE_SPNotAdvancing: result = "Hardware is not running when sample position is inquired"; break;
276
case ASE_NoClock: result = "Sample clock or rate cannot be determined or is not present"; break;
277
case ASE_NoMemory: result = "Not enough memory for completing the request"; break;
278
default: result = "Unknown ASIO error"; break;
273
result = "Hardware input or output is not present or available";
275
case ASE_HWMalfunction:
276
result = "Hardware is malfunctioning";
278
case ASE_InvalidParameter:
279
result = "Input parameter invalid";
281
case ASE_InvalidMode:
282
result = "Hardware is in a bad mode or used in a bad mode";
284
case ASE_SPNotAdvancing:
285
result = "Hardware is not running when sample position is inquired";
288
result = "Sample clock or rate cannot be determined or is not present";
291
result = "Not enough memory for completing the request";
294
result = "Unknown ASIO error";
344
371
Retrieve <driverCount> driver names from ASIO, returned in a char**
345
372
allocated in <group>.
347
static char **GetAsioDriverNames( PaAsioHostApiRepresentation *asioHostApi, PaUtilAllocationGroup *group, long driverCount )
374
static char **GetAsioDriverNames (PaAsioHostApiRepresentation *asioHostApi, PaUtilAllocationGroup *group, long driverCount)
349
376
char **result = 0;
352
result =(char**)PaUtil_GroupAllocateMemory(
353
group, sizeof(char*) * driverCount );
357
result[0] = (char*)PaUtil_GroupAllocateMemory(
358
group, 32 * driverCount );
362
for( i=0; i<driverCount; ++i )
379
result = (char**) PaUtil_GroupAllocateMemory (
380
group, sizeof (char*) * driverCount);
385
result[0] = (char*) PaUtil_GroupAllocateMemory (
386
group, 32 * driverCount);
391
for (i=0; i<driverCount; ++i)
363
392
result[i] = result[0] + (32 * i);
365
asioHostApi->asioDrivers->getDriverNames( result, driverCount );
394
asioHostApi->asioDrivers->getDriverNames (result, driverCount);
372
static PaSampleFormat AsioSampleTypeToPaNativeSampleFormat(ASIOSampleType type)
379
case ASIOSTFloat32MSB:
380
case ASIOSTFloat32LSB:
381
case ASIOSTFloat64MSB:
382
case ASIOSTFloat64LSB:
387
case ASIOSTInt32MSB16:
388
case ASIOSTInt32LSB16:
389
case ASIOSTInt32MSB18:
390
case ASIOSTInt32MSB20:
391
case ASIOSTInt32MSB24:
392
case ASIOSTInt32LSB18:
393
case ASIOSTInt32LSB20:
394
case ASIOSTInt32LSB24:
402
return paCustomFormat;
406
void AsioSampleTypeLOG(ASIOSampleType type)
409
case ASIOSTInt16MSB: PA_DEBUG(("ASIOSTInt16MSB\n")); break;
410
case ASIOSTInt16LSB: PA_DEBUG(("ASIOSTInt16LSB\n")); break;
411
case ASIOSTFloat32MSB:PA_DEBUG(("ASIOSTFloat32MSB\n"));break;
412
case ASIOSTFloat32LSB:PA_DEBUG(("ASIOSTFloat32LSB\n"));break;
413
case ASIOSTFloat64MSB:PA_DEBUG(("ASIOSTFloat64MSB\n"));break;
414
case ASIOSTFloat64LSB:PA_DEBUG(("ASIOSTFloat64LSB\n"));break;
415
case ASIOSTInt32MSB: PA_DEBUG(("ASIOSTInt32MSB\n")); break;
416
case ASIOSTInt32LSB: PA_DEBUG(("ASIOSTInt32LSB\n")); break;
417
case ASIOSTInt32MSB16:PA_DEBUG(("ASIOSTInt32MSB16\n"));break;
418
case ASIOSTInt32LSB16:PA_DEBUG(("ASIOSTInt32LSB16\n"));break;
419
case ASIOSTInt32MSB18:PA_DEBUG(("ASIOSTInt32MSB18\n"));break;
420
case ASIOSTInt32MSB20:PA_DEBUG(("ASIOSTInt32MSB20\n"));break;
421
case ASIOSTInt32MSB24:PA_DEBUG(("ASIOSTInt32MSB24\n"));break;
422
case ASIOSTInt32LSB18:PA_DEBUG(("ASIOSTInt32LSB18\n"));break;
423
case ASIOSTInt32LSB20:PA_DEBUG(("ASIOSTInt32LSB20\n"));break;
424
case ASIOSTInt32LSB24:PA_DEBUG(("ASIOSTInt32LSB24\n"));break;
425
case ASIOSTInt24MSB: PA_DEBUG(("ASIOSTInt24MSB\n")); break;
426
case ASIOSTInt24LSB: PA_DEBUG(("ASIOSTInt24LSB\n")); break;
427
default: PA_DEBUG(("Custom Format%d\n",type));break;
432
static int BytesPerAsioSample( ASIOSampleType sampleType )
401
static PaSampleFormat AsioSampleTypeToPaNativeSampleFormat (ASIOSampleType type)
408
case ASIOSTFloat32MSB:
409
case ASIOSTFloat32LSB:
410
case ASIOSTFloat64MSB:
411
case ASIOSTFloat64LSB:
416
case ASIOSTInt32MSB16:
417
case ASIOSTInt32LSB16:
418
case ASIOSTInt32MSB18:
419
case ASIOSTInt32MSB20:
420
case ASIOSTInt32MSB24:
421
case ASIOSTInt32LSB18:
422
case ASIOSTInt32LSB20:
423
case ASIOSTInt32LSB24:
431
return paCustomFormat;
435
void AsioSampleTypeLOG (ASIOSampleType type)
439
PA_DEBUG ( ("ASIOSTInt16MSB\n"));
442
PA_DEBUG ( ("ASIOSTInt16LSB\n"));
444
case ASIOSTFloat32MSB:
445
PA_DEBUG ( ("ASIOSTFloat32MSB\n"));
447
case ASIOSTFloat32LSB:
448
PA_DEBUG ( ("ASIOSTFloat32LSB\n"));
450
case ASIOSTFloat64MSB:
451
PA_DEBUG ( ("ASIOSTFloat64MSB\n"));
453
case ASIOSTFloat64LSB:
454
PA_DEBUG ( ("ASIOSTFloat64LSB\n"));
457
PA_DEBUG ( ("ASIOSTInt32MSB\n"));
460
PA_DEBUG ( ("ASIOSTInt32LSB\n"));
462
case ASIOSTInt32MSB16:
463
PA_DEBUG ( ("ASIOSTInt32MSB16\n"));
465
case ASIOSTInt32LSB16:
466
PA_DEBUG ( ("ASIOSTInt32LSB16\n"));
468
case ASIOSTInt32MSB18:
469
PA_DEBUG ( ("ASIOSTInt32MSB18\n"));
471
case ASIOSTInt32MSB20:
472
PA_DEBUG ( ("ASIOSTInt32MSB20\n"));
474
case ASIOSTInt32MSB24:
475
PA_DEBUG ( ("ASIOSTInt32MSB24\n"));
477
case ASIOSTInt32LSB18:
478
PA_DEBUG ( ("ASIOSTInt32LSB18\n"));
480
case ASIOSTInt32LSB20:
481
PA_DEBUG ( ("ASIOSTInt32LSB20\n"));
483
case ASIOSTInt32LSB24:
484
PA_DEBUG ( ("ASIOSTInt32LSB24\n"));
487
PA_DEBUG ( ("ASIOSTInt24MSB\n"));
490
PA_DEBUG ( ("ASIOSTInt24LSB\n"));
493
PA_DEBUG ( ("Custom Format%d\n",type));
499
static int BytesPerAsioSample (ASIOSampleType sampleType)
434
501
switch (sampleType) {
435
502
case ASIOSTInt16MSB:
467
static void Swap16( void *buffer, long shift, long count )
534
static void Swap16 (void *buffer, long shift, long count)
469
unsigned short *p = (unsigned short*)buffer;
536
unsigned short *p = (unsigned short*) buffer;
470
537
unsigned short temp;
471
538
(void) shift; /* unused parameter */
476
*p++ = (unsigned short)((temp<<8) | (temp>>8));
542
*p++ = (unsigned short) ( (temp<<8) | (temp>>8));
480
static void Swap24( void *buffer, long shift, long count )
546
static void Swap24 (void *buffer, long shift, long count)
482
unsigned char *p = (unsigned char*)buffer;
548
unsigned char *p = (unsigned char*) buffer;
483
549
unsigned char temp;
484
550
(void) shift; /* unused parameter */
495
560
#define PA_SWAP32_( x ) ((x>>24) | ((x>>8)&0xFF00) | ((x<<8)&0xFF0000) | (x<<24));
497
static void Swap32( void *buffer, long shift, long count )
562
static void Swap32 (void *buffer, long shift, long count)
499
unsigned long *p = (unsigned long*)buffer;
564
unsigned long *p = (unsigned long*) buffer;
500
565
unsigned long temp;
501
566
(void) shift; /* unused parameter */
506
*p++ = PA_SWAP32_( temp);
570
*p++ = PA_SWAP32_ (temp);
510
static void SwapShiftLeft32( void *buffer, long shift, long count )
574
static void SwapShiftLeft32 (void *buffer, long shift, long count)
512
unsigned long *p = (unsigned long*)buffer;
576
unsigned long *p = (unsigned long*) buffer;
513
577
unsigned long temp;
518
temp = PA_SWAP32_( temp);
581
temp = PA_SWAP32_ (temp);
519
582
*p++ = temp << shift;
523
static void ShiftRightSwap32( void *buffer, long shift, long count )
586
static void ShiftRightSwap32 (void *buffer, long shift, long count)
525
unsigned long *p = (unsigned long*)buffer;
588
unsigned long *p = (unsigned long*) buffer;
526
589
unsigned long temp;
530
592
temp = *p >> shift;
531
*p++ = PA_SWAP32_( temp);
593
*p++ = PA_SWAP32_ (temp);
535
static void ShiftLeft32( void *buffer, long shift, long count )
597
static void ShiftLeft32 (void *buffer, long shift, long count)
537
unsigned long *p = (unsigned long*)buffer;
599
unsigned long *p = (unsigned long*) buffer;
538
600
unsigned long temp;
543
604
*p++ = temp << shift;
547
static void ShiftRight32( void *buffer, long shift, long count )
608
static void ShiftRight32 (void *buffer, long shift, long count)
549
unsigned long *p = (unsigned long*)buffer;
610
unsigned long *p = (unsigned long*) buffer;
550
611
unsigned long temp;
555
615
*p++ = temp >> shift;
630
688
#define PA_LSB_IS_NATIVE_
633
typedef void PaAsioBufferConverter( void *, long, long );
635
static void SelectAsioToPaConverter( ASIOSampleType type, PaAsioBufferConverter **converter, long *shift )
642
/* dest: paInt16, no conversion necessary, possible byte swap*/
643
#ifdef PA_LSB_IS_NATIVE_
648
/* dest: paInt16, no conversion necessary, possible byte swap*/
649
#ifdef PA_MSB_IS_NATIVE_
653
case ASIOSTFloat32MSB:
654
/* dest: paFloat32, no conversion necessary, possible byte swap*/
655
#ifdef PA_LSB_IS_NATIVE_
659
case ASIOSTFloat32LSB:
660
/* dest: paFloat32, no conversion necessary, possible byte swap*/
661
#ifdef PA_MSB_IS_NATIVE_
665
case ASIOSTFloat64MSB:
666
/* dest: paFloat32, in-place conversion to/from float32, possible byte swap*/
667
#ifdef PA_LSB_IS_NATIVE_
668
*converter = Swap64ConvertFloat64ToFloat32;
670
*converter = ConvertFloat64ToFloat32;
673
case ASIOSTFloat64LSB:
674
/* dest: paFloat32, in-place conversion to/from float32, possible byte swap*/
675
#ifdef PA_MSB_IS_NATIVE_
676
*converter = Swap64ConvertFloat64ToFloat32;
678
*converter = ConvertFloat64ToFloat32;
682
/* dest: paInt32, no conversion necessary, possible byte swap */
683
#ifdef PA_LSB_IS_NATIVE_
688
/* dest: paInt32, no conversion necessary, possible byte swap */
689
#ifdef PA_MSB_IS_NATIVE_
693
case ASIOSTInt32MSB16:
694
/* dest: paInt32, 16 bit shift, possible byte swap */
695
#ifdef PA_LSB_IS_NATIVE_
696
*converter = SwapShiftLeft32;
698
*converter = ShiftLeft32;
702
case ASIOSTInt32MSB18:
703
/* dest: paInt32, 14 bit shift, possible byte swap */
704
#ifdef PA_LSB_IS_NATIVE_
705
*converter = SwapShiftLeft32;
707
*converter = ShiftLeft32;
711
case ASIOSTInt32MSB20:
712
/* dest: paInt32, 12 bit shift, possible byte swap */
713
#ifdef PA_LSB_IS_NATIVE_
714
*converter = SwapShiftLeft32;
716
*converter = ShiftLeft32;
720
case ASIOSTInt32MSB24:
721
/* dest: paInt32, 8 bit shift, possible byte swap */
722
#ifdef PA_LSB_IS_NATIVE_
723
*converter = SwapShiftLeft32;
725
*converter = ShiftLeft32;
729
case ASIOSTInt32LSB16:
730
/* dest: paInt32, 16 bit shift, possible byte swap */
731
#ifdef PA_MSB_IS_NATIVE_
732
*converter = SwapShiftLeft32;
734
*converter = ShiftLeft32;
738
case ASIOSTInt32LSB18:
739
/* dest: paInt32, 14 bit shift, possible byte swap */
740
#ifdef PA_MSB_IS_NATIVE_
741
*converter = SwapShiftLeft32;
743
*converter = ShiftLeft32;
747
case ASIOSTInt32LSB20:
748
/* dest: paInt32, 12 bit shift, possible byte swap */
749
#ifdef PA_MSB_IS_NATIVE_
750
*converter = SwapShiftLeft32;
752
*converter = ShiftLeft32;
756
case ASIOSTInt32LSB24:
757
/* dest: paInt32, 8 bit shift, possible byte swap */
758
#ifdef PA_MSB_IS_NATIVE_
759
*converter = SwapShiftLeft32;
761
*converter = ShiftLeft32;
766
/* dest: paInt24, no conversion necessary, possible byte swap */
767
#ifdef PA_LSB_IS_NATIVE_
772
/* dest: paInt24, no conversion necessary, possible byte swap */
773
#ifdef PA_MSB_IS_NATIVE_
781
static void SelectPaToAsioConverter( ASIOSampleType type, PaAsioBufferConverter **converter, long *shift )
788
/* src: paInt16, no conversion necessary, possible byte swap*/
789
#ifdef PA_LSB_IS_NATIVE_
794
/* src: paInt16, no conversion necessary, possible byte swap*/
795
#ifdef PA_MSB_IS_NATIVE_
799
case ASIOSTFloat32MSB:
800
/* src: paFloat32, no conversion necessary, possible byte swap*/
801
#ifdef PA_LSB_IS_NATIVE_
805
case ASIOSTFloat32LSB:
806
/* src: paFloat32, no conversion necessary, possible byte swap*/
807
#ifdef PA_MSB_IS_NATIVE_
811
case ASIOSTFloat64MSB:
812
/* src: paFloat32, in-place conversion to/from float32, possible byte swap*/
813
#ifdef PA_LSB_IS_NATIVE_
814
*converter = ConvertFloat32ToFloat64Swap64;
816
*converter = ConvertFloat32ToFloat64;
819
case ASIOSTFloat64LSB:
820
/* src: paFloat32, in-place conversion to/from float32, possible byte swap*/
821
#ifdef PA_MSB_IS_NATIVE_
822
*converter = ConvertFloat32ToFloat64Swap64;
824
*converter = ConvertFloat32ToFloat64;
828
/* src: paInt32, no conversion necessary, possible byte swap */
829
#ifdef PA_LSB_IS_NATIVE_
834
/* src: paInt32, no conversion necessary, possible byte swap */
835
#ifdef PA_MSB_IS_NATIVE_
839
case ASIOSTInt32MSB16:
840
/* src: paInt32, 16 bit shift, possible byte swap */
841
#ifdef PA_LSB_IS_NATIVE_
842
*converter = ShiftRightSwap32;
844
*converter = ShiftRight32;
848
case ASIOSTInt32MSB18:
849
/* src: paInt32, 14 bit shift, possible byte swap */
850
#ifdef PA_LSB_IS_NATIVE_
851
*converter = ShiftRightSwap32;
853
*converter = ShiftRight32;
857
case ASIOSTInt32MSB20:
858
/* src: paInt32, 12 bit shift, possible byte swap */
859
#ifdef PA_LSB_IS_NATIVE_
860
*converter = ShiftRightSwap32;
862
*converter = ShiftRight32;
866
case ASIOSTInt32MSB24:
867
/* src: paInt32, 8 bit shift, possible byte swap */
868
#ifdef PA_LSB_IS_NATIVE_
869
*converter = ShiftRightSwap32;
871
*converter = ShiftRight32;
875
case ASIOSTInt32LSB16:
876
/* src: paInt32, 16 bit shift, possible byte swap */
877
#ifdef PA_MSB_IS_NATIVE_
878
*converter = ShiftRightSwap32;
880
*converter = ShiftRight32;
884
case ASIOSTInt32LSB18:
885
/* src: paInt32, 14 bit shift, possible byte swap */
886
#ifdef PA_MSB_IS_NATIVE_
887
*converter = ShiftRightSwap32;
889
*converter = ShiftRight32;
893
case ASIOSTInt32LSB20:
894
/* src: paInt32, 12 bit shift, possible byte swap */
895
#ifdef PA_MSB_IS_NATIVE_
896
*converter = ShiftRightSwap32;
898
*converter = ShiftRight32;
902
case ASIOSTInt32LSB24:
903
/* src: paInt32, 8 bit shift, possible byte swap */
904
#ifdef PA_MSB_IS_NATIVE_
905
*converter = ShiftRightSwap32;
907
*converter = ShiftRight32;
912
/* src: paInt24, no conversion necessary, possible byte swap */
913
#ifdef PA_LSB_IS_NATIVE_
918
/* src: paInt24, no conversion necessary, possible byte swap */
919
#ifdef PA_MSB_IS_NATIVE_
927
typedef struct PaAsioDeviceInfo
691
typedef void PaAsioBufferConverter (void *, long, long);
693
static void SelectAsioToPaConverter (ASIOSampleType type, PaAsioBufferConverter **converter, long *shift)
700
/* dest: paInt16, no conversion necessary, possible byte swap*/
701
#ifdef PA_LSB_IS_NATIVE_
706
/* dest: paInt16, no conversion necessary, possible byte swap*/
707
#ifdef PA_MSB_IS_NATIVE_
711
case ASIOSTFloat32MSB:
712
/* dest: paFloat32, no conversion necessary, possible byte swap*/
713
#ifdef PA_LSB_IS_NATIVE_
717
case ASIOSTFloat32LSB:
718
/* dest: paFloat32, no conversion necessary, possible byte swap*/
719
#ifdef PA_MSB_IS_NATIVE_
723
case ASIOSTFloat64MSB:
724
/* dest: paFloat32, in-place conversion to/from float32, possible byte swap*/
725
#ifdef PA_LSB_IS_NATIVE_
726
*converter = Swap64ConvertFloat64ToFloat32;
728
*converter = ConvertFloat64ToFloat32;
731
case ASIOSTFloat64LSB:
732
/* dest: paFloat32, in-place conversion to/from float32, possible byte swap*/
733
#ifdef PA_MSB_IS_NATIVE_
734
*converter = Swap64ConvertFloat64ToFloat32;
736
*converter = ConvertFloat64ToFloat32;
740
/* dest: paInt32, no conversion necessary, possible byte swap */
741
#ifdef PA_LSB_IS_NATIVE_
746
/* dest: paInt32, no conversion necessary, possible byte swap */
747
#ifdef PA_MSB_IS_NATIVE_
751
case ASIOSTInt32MSB16:
752
/* dest: paInt32, 16 bit shift, possible byte swap */
753
#ifdef PA_LSB_IS_NATIVE_
754
*converter = SwapShiftLeft32;
756
*converter = ShiftLeft32;
760
case ASIOSTInt32MSB18:
761
/* dest: paInt32, 14 bit shift, possible byte swap */
762
#ifdef PA_LSB_IS_NATIVE_
763
*converter = SwapShiftLeft32;
765
*converter = ShiftLeft32;
769
case ASIOSTInt32MSB20:
770
/* dest: paInt32, 12 bit shift, possible byte swap */
771
#ifdef PA_LSB_IS_NATIVE_
772
*converter = SwapShiftLeft32;
774
*converter = ShiftLeft32;
778
case ASIOSTInt32MSB24:
779
/* dest: paInt32, 8 bit shift, possible byte swap */
780
#ifdef PA_LSB_IS_NATIVE_
781
*converter = SwapShiftLeft32;
783
*converter = ShiftLeft32;
787
case ASIOSTInt32LSB16:
788
/* dest: paInt32, 16 bit shift, possible byte swap */
789
#ifdef PA_MSB_IS_NATIVE_
790
*converter = SwapShiftLeft32;
792
*converter = ShiftLeft32;
796
case ASIOSTInt32LSB18:
797
/* dest: paInt32, 14 bit shift, possible byte swap */
798
#ifdef PA_MSB_IS_NATIVE_
799
*converter = SwapShiftLeft32;
801
*converter = ShiftLeft32;
805
case ASIOSTInt32LSB20:
806
/* dest: paInt32, 12 bit shift, possible byte swap */
807
#ifdef PA_MSB_IS_NATIVE_
808
*converter = SwapShiftLeft32;
810
*converter = ShiftLeft32;
814
case ASIOSTInt32LSB24:
815
/* dest: paInt32, 8 bit shift, possible byte swap */
816
#ifdef PA_MSB_IS_NATIVE_
817
*converter = SwapShiftLeft32;
819
*converter = ShiftLeft32;
824
/* dest: paInt24, no conversion necessary, possible byte swap */
825
#ifdef PA_LSB_IS_NATIVE_
830
/* dest: paInt24, no conversion necessary, possible byte swap */
831
#ifdef PA_MSB_IS_NATIVE_
839
static void SelectPaToAsioConverter (ASIOSampleType type, PaAsioBufferConverter **converter, long *shift)
846
/* src: paInt16, no conversion necessary, possible byte swap*/
847
#ifdef PA_LSB_IS_NATIVE_
852
/* src: paInt16, no conversion necessary, possible byte swap*/
853
#ifdef PA_MSB_IS_NATIVE_
857
case ASIOSTFloat32MSB:
858
/* src: paFloat32, no conversion necessary, possible byte swap*/
859
#ifdef PA_LSB_IS_NATIVE_
863
case ASIOSTFloat32LSB:
864
/* src: paFloat32, no conversion necessary, possible byte swap*/
865
#ifdef PA_MSB_IS_NATIVE_
869
case ASIOSTFloat64MSB:
870
/* src: paFloat32, in-place conversion to/from float32, possible byte swap*/
871
#ifdef PA_LSB_IS_NATIVE_
872
*converter = ConvertFloat32ToFloat64Swap64;
874
*converter = ConvertFloat32ToFloat64;
877
case ASIOSTFloat64LSB:
878
/* src: paFloat32, in-place conversion to/from float32, possible byte swap*/
879
#ifdef PA_MSB_IS_NATIVE_
880
*converter = ConvertFloat32ToFloat64Swap64;
882
*converter = ConvertFloat32ToFloat64;
886
/* src: paInt32, no conversion necessary, possible byte swap */
887
#ifdef PA_LSB_IS_NATIVE_
892
/* src: paInt32, no conversion necessary, possible byte swap */
893
#ifdef PA_MSB_IS_NATIVE_
897
case ASIOSTInt32MSB16:
898
/* src: paInt32, 16 bit shift, possible byte swap */
899
#ifdef PA_LSB_IS_NATIVE_
900
*converter = ShiftRightSwap32;
902
*converter = ShiftRight32;
906
case ASIOSTInt32MSB18:
907
/* src: paInt32, 14 bit shift, possible byte swap */
908
#ifdef PA_LSB_IS_NATIVE_
909
*converter = ShiftRightSwap32;
911
*converter = ShiftRight32;
915
case ASIOSTInt32MSB20:
916
/* src: paInt32, 12 bit shift, possible byte swap */
917
#ifdef PA_LSB_IS_NATIVE_
918
*converter = ShiftRightSwap32;
920
*converter = ShiftRight32;
924
case ASIOSTInt32MSB24:
925
/* src: paInt32, 8 bit shift, possible byte swap */
926
#ifdef PA_LSB_IS_NATIVE_
927
*converter = ShiftRightSwap32;
929
*converter = ShiftRight32;
933
case ASIOSTInt32LSB16:
934
/* src: paInt32, 16 bit shift, possible byte swap */
935
#ifdef PA_MSB_IS_NATIVE_
936
*converter = ShiftRightSwap32;
938
*converter = ShiftRight32;
942
case ASIOSTInt32LSB18:
943
/* src: paInt32, 14 bit shift, possible byte swap */
944
#ifdef PA_MSB_IS_NATIVE_
945
*converter = ShiftRightSwap32;
947
*converter = ShiftRight32;
951
case ASIOSTInt32LSB20:
952
/* src: paInt32, 12 bit shift, possible byte swap */
953
#ifdef PA_MSB_IS_NATIVE_
954
*converter = ShiftRightSwap32;
956
*converter = ShiftRight32;
960
case ASIOSTInt32LSB24:
961
/* src: paInt32, 8 bit shift, possible byte swap */
962
#ifdef PA_MSB_IS_NATIVE_
963
*converter = ShiftRightSwap32;
965
*converter = ShiftRight32;
970
/* src: paInt24, no conversion necessary, possible byte swap */
971
#ifdef PA_LSB_IS_NATIVE_
976
/* src: paInt24, no conversion necessary, possible byte swap */
977
#ifdef PA_MSB_IS_NATIVE_
985
typedef struct PaAsioDeviceInfo {
929
986
PaDeviceInfo commonDeviceInfo;
930
987
long minBufferSize;
931
988
long maxBufferSize;
980
1035
and must be closed by the called by calling UnloadAsioDriver() - if an error
981
1036
is returned the driver will already be unloaded.
983
static PaError LoadAsioDriver( PaAsioHostApiRepresentation *asioHostApi, const char *driverName,
984
PaAsioDriverInfo *driverInfo, void *systemSpecific )
1038
static PaError LoadAsioDriver (PaAsioHostApiRepresentation *asioHostApi, const char *driverName,
1039
PaAsioDriverInfo *driverInfo, void *systemSpecific)
986
1041
PaError result = paNoError;
987
1042
ASIOError asioError;
988
1043
int asioIsInitialized = 0;
991
ASIO uses CoCreateInstance() to load a driver. That requires that
992
CoInitialize(0) be called for every thread that loads a driver.
993
It is OK to call CoInitialize(0) multiple times form one thread as long
994
as it is balanced by a call to CoUninitialize(). See UnloadAsioDriver().
1046
ASIO uses CoCreateInstance() to load a driver. That requires that
1047
CoInitialize(0) be called for every thread that loads a driver.
1048
It is OK to call CoInitialize(0) multiple times form one thread as long
1049
as it is balanced by a call to CoUninitialize(). See UnloadAsioDriver().
996
The V18 version called CoInitialize() starting on 2/19/02.
997
That was removed from PA V19 for unknown reasons.
998
Phil Burk added it back on 6/27/08 so that JSyn would work.
1051
The V18 version called CoInitialize() starting on 2/19/02.
1052
That was removed from PA V19 for unknown reasons.
1053
Phil Burk added it back on 6/27/08 so that JSyn would work.
1002
if( !asioHostApi->asioDrivers->loadDriver( const_cast<char*>(driverName) ) )
1004
/* If this returns an error then it might be because CoInitialize(0) was removed.
1005
It should be called right before this.
1057
if (!asioHostApi->asioDrivers->loadDriver (const_cast<char*> (driverName))) {
1058
/* If this returns an error then it might be because CoInitialize(0) was removed.
1059
It should be called right before this.
1007
1061
result = paUnanticipatedHostError;
1008
PA_ASIO_SET_LAST_HOST_ERROR( 0, "Failed to load ASIO driver" );
1062
PA_ASIO_SET_LAST_HOST_ERROR (0, "Failed to load ASIO driver");
1012
memset( &driverInfo->asioDriverInfo, 0, sizeof(ASIODriverInfo) );
1066
memset (&driverInfo->asioDriverInfo, 0, sizeof (ASIODriverInfo));
1013
1067
driverInfo->asioDriverInfo.asioVersion = 2;
1014
1068
driverInfo->asioDriverInfo.sysRef = systemSpecific;
1015
if( (asioError = ASIOInit( &driverInfo->asioDriverInfo )) != ASE_OK )
1070
if ( (asioError = ASIOInit (&driverInfo->asioDriverInfo)) != ASE_OK) {
1017
1071
result = paUnanticipatedHostError;
1018
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
1072
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
1023
1075
asioIsInitialized = 1;
1026
if( (asioError = ASIOGetChannels(&driverInfo->inputChannelCount,
1027
&driverInfo->outputChannelCount)) != ASE_OK )
1029
result = paUnanticipatedHostError;
1030
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
1034
if( (asioError = ASIOGetBufferSize(&driverInfo->bufferMinSize,
1035
&driverInfo->bufferMaxSize, &driverInfo->bufferPreferredSize,
1036
&driverInfo->bufferGranularity)) != ASE_OK )
1038
result = paUnanticipatedHostError;
1039
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
1043
if( ASIOOutputReady() == ASE_OK )
1078
if ( (asioError = ASIOGetChannels (&driverInfo->inputChannelCount,
1079
&driverInfo->outputChannelCount)) != ASE_OK) {
1080
result = paUnanticipatedHostError;
1081
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
1085
if ( (asioError = ASIOGetBufferSize (&driverInfo->bufferMinSize,
1086
&driverInfo->bufferMaxSize, &driverInfo->bufferPreferredSize,
1087
&driverInfo->bufferGranularity)) != ASE_OK) {
1088
result = paUnanticipatedHostError;
1089
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
1093
if (ASIOOutputReady() == ASE_OK)
1044
1094
driverInfo->postOutput = true;
1046
1096
driverInfo->postOutput = false;
1148
1196
/* allocate enough space for all drivers, even if some aren't installed */
1150
(*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
1151
asioHostApi->allocations, sizeof(PaDeviceInfo*) * driverCount );
1152
if( !(*hostApi)->deviceInfos )
1198
(*hostApi)->deviceInfos = (PaDeviceInfo**) PaUtil_GroupAllocateMemory (
1199
asioHostApi->allocations, sizeof (PaDeviceInfo*) * driverCount);
1201
if (! (*hostApi)->deviceInfos) {
1154
1202
result = paInsufficientMemory;
1158
1206
/* allocate all device info structs in a contiguous block */
1159
deviceInfoArray = (PaAsioDeviceInfo*)PaUtil_GroupAllocateMemory(
1160
asioHostApi->allocations, sizeof(PaAsioDeviceInfo) * driverCount );
1161
if( !deviceInfoArray )
1207
deviceInfoArray = (PaAsioDeviceInfo*) PaUtil_GroupAllocateMemory (
1208
asioHostApi->allocations, sizeof (PaAsioDeviceInfo) * driverCount);
1210
if (!deviceInfoArray) {
1163
1211
result = paInsufficientMemory;
1167
IsDebuggerPresent_ = GetProcAddress( LoadLibrary( "Kernel32.dll" ), "IsDebuggerPresent" );
1169
for( i=0; i < driverCount; ++i )
1172
PA_DEBUG(("ASIO names[%d]:%s\n",i,names[i]));
1215
IsDebuggerPresent_ = GetProcAddress (LoadLibrary ("Kernel32.dll"), "IsDebuggerPresent");
1217
for (i=0; i < driverCount; ++i) {
1219
PA_DEBUG ( ("ASIO names[%d]:%s\n",i,names[i]));
1174
1221
// Since portaudio opens ALL ASIO drivers, and no one else does that,
1175
1222
// we face fact that some drivers were not meant for it, drivers which act
1176
1223
// like shells on top of REAL drivers, for instance.
1177
1224
// so we get duplicate handles, locks and other problems.
1178
// so lets NOT try to load any such wrappers.
1225
// so lets NOT try to load any such wrappers.
1179
1226
// The ones i [davidv] know of so far are:
1181
if ( strcmp (names[i],"ASIO DirectX Full Duplex Driver") == 0
1182
|| strcmp (names[i],"ASIO Multimedia Driver") == 0
1183
|| strncmp(names[i],"Premiere",8) == 0 //"Premiere Elements Windows Sound 1.0"
1184
|| strncmp(names[i],"Adobe",5) == 0 //"Adobe Default Windows Sound 1.5"
1187
PA_DEBUG(("BLACKLISTED!!!\n"));
1228
if (strcmp (names[i],"ASIO DirectX Full Duplex Driver") == 0
1229
|| strcmp (names[i],"ASIO Multimedia Driver") == 0
1230
|| strncmp (names[i],"Premiere",8) == 0 //"Premiere Elements Windows Sound 1.0"
1231
|| strncmp (names[i],"Adobe",5) == 0 //"Adobe Default Windows Sound 1.5"
1233
PA_DEBUG ( ("BLACKLISTED!!!\n"));
1192
if( IsDebuggerPresent_ && IsDebuggerPresent_() )
1238
if (IsDebuggerPresent_ && IsDebuggerPresent_()) {
1194
1239
/* ASIO Digidesign Driver uses PACE copy protection which quits out
1195
1240
if a debugger is running. So we don't load it if a debugger is running. */
1196
if( strcmp(names[i], "ASIO Digidesign Driver") == 0 )
1198
PA_DEBUG(("BLACKLISTED!!! ASIO Digidesign Driver would quit the debugger\n"));
1241
if (strcmp (names[i], "ASIO Digidesign Driver") == 0) {
1242
PA_DEBUG ( ("BLACKLISTED!!! ASIO Digidesign Driver would quit the debugger\n"));
1204
1248
/* Attempt to load the asio driver... */
1205
if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriverInfo, asioHostApi->systemSpecific ) == paNoError )
1249
if (LoadAsioDriver (asioHostApi, names[i], &paAsioDriverInfo, asioHostApi->systemSpecific) == paNoError) {
1207
1250
PaAsioDeviceInfo *asioDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ];
1208
1251
PaDeviceInfo *deviceInfo = &asioDeviceInfo->commonDeviceInfo;
1211
1254
deviceInfo->hostApi = hostApiIndex;
1213
1256
deviceInfo->name = names[i];
1214
PA_DEBUG(("PaAsio_Initialize: drv:%d name = %s\n", i,deviceInfo->name));
1215
PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels = %d\n", i, paAsioDriverInfo.inputChannelCount));
1216
PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", i, paAsioDriverInfo.outputChannelCount));
1217
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", i, paAsioDriverInfo.bufferMinSize));
1218
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", i, paAsioDriverInfo.bufferMaxSize));
1219
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriverInfo.bufferPreferredSize));
1220
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", i, paAsioDriverInfo.bufferGranularity));
1257
PA_DEBUG ( ("PaAsio_Initialize: drv:%d name = %s\n", i,deviceInfo->name));
1258
PA_DEBUG ( ("PaAsio_Initialize: drv:%d inputChannels = %d\n", i, paAsioDriverInfo.inputChannelCount));
1259
PA_DEBUG ( ("PaAsio_Initialize: drv:%d outputChannels = %d\n", i, paAsioDriverInfo.outputChannelCount));
1260
PA_DEBUG ( ("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", i, paAsioDriverInfo.bufferMinSize));
1261
PA_DEBUG ( ("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", i, paAsioDriverInfo.bufferMaxSize));
1262
PA_DEBUG ( ("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriverInfo.bufferPreferredSize));
1263
PA_DEBUG ( ("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", i, paAsioDriverInfo.bufferGranularity));
1222
1265
deviceInfo->maxInputChannels = paAsioDriverInfo.inputChannelCount;
1223
1266
deviceInfo->maxOutputChannels = paAsioDriverInfo.outputChannelCount;
1225
1268
deviceInfo->defaultSampleRate = 0.;
1226
1269
bool foundDefaultSampleRate = false;
1227
for( int j=0; j < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++j )
1229
ASIOError asioError = ASIOCanSampleRate( defaultSampleRateSearchOrder_[j] );
1230
if( asioError != ASE_NoClock && asioError != ASE_NotPresent )
1271
for (int j=0; j < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++j) {
1272
ASIOError asioError = ASIOCanSampleRate (defaultSampleRateSearchOrder_[j]);
1274
if (asioError != ASE_NoClock && asioError != ASE_NotPresent) {
1232
1275
deviceInfo->defaultSampleRate = defaultSampleRateSearchOrder_[j];
1233
1276
foundDefaultSampleRate = true;
1238
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultSampleRate = %f\n", i, deviceInfo->defaultSampleRate));
1281
PA_DEBUG ( ("PaAsio_Initialize: drv:%d defaultSampleRate = %f\n", i, deviceInfo->defaultSampleRate));
1240
if( foundDefaultSampleRate ){
1283
if (foundDefaultSampleRate) {
1242
1285
/* calculate default latency values from bufferPreferredSize
1243
1286
for default low latency, and bufferPreferredSize * 3
1350
1390
(*hostApi)->OpenStream = OpenStream;
1351
1391
(*hostApi)->IsFormatSupported = IsFormatSupported;
1353
PaUtil_InitializeStreamInterface( &asioHostApi->callbackStreamInterface, CloseStream, StartStream,
1393
PaUtil_InitializeStreamInterface (&asioHostApi->callbackStreamInterface, CloseStream, StartStream,
1354
1394
StopStream, AbortStream, IsStreamStopped, IsStreamActive,
1355
1395
GetStreamTime, GetStreamCpuLoad,
1356
1396
PaUtil_DummyRead, PaUtil_DummyWrite,
1357
PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
1397
PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable);
1359
PaUtil_InitializeStreamInterface( &asioHostApi->blockingStreamInterface, CloseStream, StartStream,
1399
PaUtil_InitializeStreamInterface (&asioHostApi->blockingStreamInterface, CloseStream, StartStream,
1360
1400
StopStream, AbortStream, IsStreamStopped, IsStreamActive,
1361
1401
GetStreamTime, PaUtil_DummyGetCpuLoad,
1362
ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
1402
ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable);
1372
if( asioHostApi->allocations )
1374
PaUtil_FreeAllAllocations( asioHostApi->allocations );
1375
PaUtil_DestroyAllocationGroup( asioHostApi->allocations );
1412
if (asioHostApi->allocations) {
1413
PaUtil_FreeAllAllocations (asioHostApi->allocations);
1414
PaUtil_DestroyAllocationGroup (asioHostApi->allocations);
1378
1417
delete asioHostApi->asioDrivers;
1379
1418
asioDrivers = 0; /* keep SDK global in sync until we stop depending on it */
1381
PaUtil_FreeMemory( asioHostApi );
1420
PaUtil_FreeMemory (asioHostApi);
1387
static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
1427
static void Terminate (struct PaUtilHostApiRepresentation *hostApi)
1389
PaAsioHostApiRepresentation *asioHostApi = (PaAsioHostApiRepresentation*)hostApi;
1429
PaAsioHostApiRepresentation *asioHostApi = (PaAsioHostApiRepresentation*) hostApi;
1393
1433
- clean up any resources not handled by the allocation group (need to review if there are any)
1396
if( asioHostApi->allocations )
1398
PaUtil_FreeAllAllocations( asioHostApi->allocations );
1399
PaUtil_DestroyAllocationGroup( asioHostApi->allocations );
1436
if (asioHostApi->allocations) {
1437
PaUtil_FreeAllAllocations (asioHostApi->allocations);
1438
PaUtil_DestroyAllocationGroup (asioHostApi->allocations);
1402
1441
delete asioHostApi->asioDrivers; /* calls CoUninitialize() */
1403
1442
asioDrivers = 0; /* keep SDK global in sync until we stop depending on it */
1405
PaUtil_FreeMemory( asioHostApi );
1444
PaUtil_FreeMemory (asioHostApi);
1409
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
1448
static PaError IsFormatSupported (struct PaUtilHostApiRepresentation *hostApi,
1410
1449
const PaStreamParameters *inputParameters,
1411
1450
const PaStreamParameters *outputParameters,
1414
1453
PaError result = paNoError;
1415
PaAsioHostApiRepresentation *asioHostApi = (PaAsioHostApiRepresentation*)hostApi;
1454
PaAsioHostApiRepresentation *asioHostApi = (PaAsioHostApiRepresentation*) hostApi;
1416
1455
PaAsioDriverInfo *driverInfo = &asioHostApi->openAsioDriverInfo;
1417
1456
int inputChannelCount, outputChannelCount;
1418
1457
PaSampleFormat inputSampleFormat, outputSampleFormat;
1419
PaDeviceIndex asioDeviceIndex;
1458
PaDeviceIndex asioDeviceIndex;
1420
1459
ASIOError asioError;
1422
if( inputParameters && outputParameters )
1461
if (inputParameters && outputParameters) {
1424
1462
/* full duplex ASIO stream must use the same device for input and output */
1426
if( inputParameters->device != outputParameters->device )
1464
if (inputParameters->device != outputParameters->device)
1427
1465
return paBadIODeviceCombination;
1430
if( inputParameters )
1468
if (inputParameters) {
1432
1469
inputChannelCount = inputParameters->channelCount;
1433
1470
inputSampleFormat = inputParameters->sampleFormat;
1435
1472
/* all standard sample formats are supported by the buffer adapter,
1436
1473
this implementation doesn't support any custom sample formats */
1437
if( inputSampleFormat & paCustomFormat )
1474
if (inputSampleFormat & paCustomFormat)
1438
1475
return paSampleFormatNotSupported;
1440
1477
/* unless alternate device specification is supported, reject the use of
1441
1478
paUseHostApiSpecificDeviceSpecification */
1443
if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
1480
if (inputParameters->device == paUseHostApiSpecificDeviceSpecification)
1444
1481
return paInvalidDevice;
1446
1483
asioDeviceIndex = inputParameters->device;
1635
1660
static PaAsioStream *theAsioStream = 0; /* due to ASIO sdk limitations there can be only one stream */
1638
static void ZeroOutputBuffers( PaAsioStream *stream, long index )
1663
static void ZeroOutputBuffers (PaAsioStream *stream, long index)
1642
for( i=0; i < stream->outputChannelCount; ++i )
1667
for (i=0; i < stream->outputChannelCount; ++i) {
1644
1668
void *buffer = stream->asioBufferInfos[ i + stream->inputChannelCount ].buffers[index];
1646
int bytesPerSample = BytesPerAsioSample( stream->asioChannelInfos[ i + stream->inputChannelCount ].type );
1670
int bytesPerSample = BytesPerAsioSample (stream->asioChannelInfos[ i + stream->inputChannelCount ].type);
1648
memset( buffer, 0, stream->framesPerHostCallback * bytesPerSample );
1672
memset (buffer, 0, stream->framesPerHostCallback * bytesPerSample);
1653
static unsigned long SelectHostBufferSize( unsigned long suggestedLatencyFrames,
1654
PaAsioDriverInfo *driverInfo )
1677
static unsigned long SelectHostBufferSize (unsigned long suggestedLatencyFrames,
1678
PaAsioDriverInfo *driverInfo)
1656
1680
unsigned long result;
1658
if( suggestedLatencyFrames == 0 )
1682
if (suggestedLatencyFrames == 0) {
1660
1683
result = driverInfo->bufferPreferredSize;
1663
if( suggestedLatencyFrames <= (unsigned long)driverInfo->bufferMinSize )
1685
if (suggestedLatencyFrames <= (unsigned long) driverInfo->bufferMinSize) {
1665
1686
result = driverInfo->bufferMinSize;
1667
else if( suggestedLatencyFrames >= (unsigned long)driverInfo->bufferMaxSize )
1687
} else if (suggestedLatencyFrames >= (unsigned long) driverInfo->bufferMaxSize) {
1669
1688
result = driverInfo->bufferMaxSize;
1673
if( driverInfo->bufferGranularity == -1 )
1690
if (driverInfo->bufferGranularity == -1) {
1675
1691
/* power-of-two */
1678
while( result < suggestedLatencyFrames )
1694
while (result < suggestedLatencyFrames)
1681
if( result < (unsigned long)driverInfo->bufferMinSize )
1697
if (result < (unsigned long) driverInfo->bufferMinSize)
1682
1698
result = driverInfo->bufferMinSize;
1684
if( result > (unsigned long)driverInfo->bufferMaxSize )
1700
if (result > (unsigned long) driverInfo->bufferMaxSize)
1685
1701
result = driverInfo->bufferMaxSize;
1687
else if( driverInfo->bufferGranularity == 0 )
1702
} else if (driverInfo->bufferGranularity == 0) {
1689
1703
/* the documentation states that bufferGranularity should be
1690
1704
zero when bufferMinSize, bufferMaxSize and
1691
1705
bufferPreferredSize are the same. We assume that is the case.
1694
1708
result = driverInfo->bufferPreferredSize;
1698
1710
/* modulo granularity */
1700
1712
unsigned long remainder =
1701
suggestedLatencyFrames % driverInfo->bufferGranularity;
1713
suggestedLatencyFrames % driverInfo->bufferGranularity;
1703
if( remainder == 0 )
1715
if (remainder == 0) {
1705
1716
result = suggestedLatencyFrames;
1709
1718
result = suggestedLatencyFrames
1710
+ (driverInfo->bufferGranularity - remainder);
1719
+ (driverInfo->bufferGranularity - remainder);
1712
if( result > (unsigned long)driverInfo->bufferMaxSize )
1721
if (result > (unsigned long) driverInfo->bufferMaxSize)
1713
1722
result = driverInfo->bufferMaxSize;
1893
1902
/* unless we move to using lower level ASIO calls, we can only have
1894
1903
one device open at a time */
1895
if( asioHostApi->openAsioDeviceIndex != paNoDevice )
1897
PA_DEBUG(("OpenStream paDeviceUnavailable\n"));
1904
if (asioHostApi->openAsioDeviceIndex != paNoDevice) {
1905
PA_DEBUG ( ("OpenStream paDeviceUnavailable\n"));
1898
1906
return paDeviceUnavailable;
1901
assert( theAsioStream == 0 );
1909
assert (theAsioStream == 0);
1903
if( inputParameters && outputParameters )
1911
if (inputParameters && outputParameters) {
1905
1912
/* full duplex ASIO stream must use the same device for input and output */
1907
if( inputParameters->device != outputParameters->device )
1909
PA_DEBUG(("OpenStream paBadIODeviceCombination\n"));
1914
if (inputParameters->device != outputParameters->device) {
1915
PA_DEBUG ( ("OpenStream paBadIODeviceCombination\n"));
1910
1916
return paBadIODeviceCombination;
1914
if( inputParameters )
1920
if (inputParameters) {
1916
1921
inputChannelCount = inputParameters->channelCount;
1917
1922
inputSampleFormat = inputParameters->sampleFormat;
1918
suggestedInputLatencyFrames = (unsigned long)((inputParameters->suggestedLatency * sampleRate)+0.5f);
1923
suggestedInputLatencyFrames = (unsigned long) ( (inputParameters->suggestedLatency * sampleRate) +0.5f);
1920
1925
/* unless alternate device specification is supported, reject the use of
1921
1926
paUseHostApiSpecificDeviceSpecification */
1922
if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
1927
if (inputParameters->device == paUseHostApiSpecificDeviceSpecification)
1923
1928
return paInvalidDevice;
1925
1930
asioDeviceIndex = inputParameters->device;
1927
PaAsioDeviceInfo *asioDeviceInfo = (PaAsioDeviceInfo*)hostApi->deviceInfos[asioDeviceIndex];
1932
PaAsioDeviceInfo *asioDeviceInfo = (PaAsioDeviceInfo*) hostApi->deviceInfos[asioDeviceIndex];
1929
1934
/* validate hostApiSpecificStreamInfo */
1930
inputStreamInfo = (PaAsioStreamInfo*)inputParameters->hostApiSpecificStreamInfo;
1931
result = ValidateAsioSpecificStreamInfo( inputParameters, inputStreamInfo,
1932
asioDeviceInfo->commonDeviceInfo.maxInputChannels,
1933
&inputChannelSelectors
1935
if( result != paNoError ) return result;
1935
inputStreamInfo = (PaAsioStreamInfo*) inputParameters->hostApiSpecificStreamInfo;
1936
result = ValidateAsioSpecificStreamInfo (inputParameters, inputStreamInfo,
1937
asioDeviceInfo->commonDeviceInfo.maxInputChannels,
1938
&inputChannelSelectors
1941
if (result != paNoError) return result;
1939
1943
inputChannelCount = 0;
1940
1944
inputSampleFormat = 0;
1941
1945
suggestedInputLatencyFrames = 0;
1944
if( outputParameters )
1948
if (outputParameters) {
1946
1949
outputChannelCount = outputParameters->channelCount;
1947
1950
outputSampleFormat = outputParameters->sampleFormat;
1948
suggestedOutputLatencyFrames = (unsigned long)((outputParameters->suggestedLatency * sampleRate)+0.5f);
1951
suggestedOutputLatencyFrames = (unsigned long) ( (outputParameters->suggestedLatency * sampleRate) +0.5f);
1950
1953
/* unless alternate device specification is supported, reject the use of
1951
1954
paUseHostApiSpecificDeviceSpecification */
1952
if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
1955
if (outputParameters->device == paUseHostApiSpecificDeviceSpecification)
1953
1956
return paInvalidDevice;
1955
1958
asioDeviceIndex = outputParameters->device;
1957
PaAsioDeviceInfo *asioDeviceInfo = (PaAsioDeviceInfo*)hostApi->deviceInfos[asioDeviceIndex];
1960
PaAsioDeviceInfo *asioDeviceInfo = (PaAsioDeviceInfo*) hostApi->deviceInfos[asioDeviceIndex];
1959
1962
/* validate hostApiSpecificStreamInfo */
1960
outputStreamInfo = (PaAsioStreamInfo*)outputParameters->hostApiSpecificStreamInfo;
1961
result = ValidateAsioSpecificStreamInfo( outputParameters, outputStreamInfo,
1962
asioDeviceInfo->commonDeviceInfo.maxOutputChannels,
1963
&outputChannelSelectors
1965
if( result != paNoError ) return result;
1963
outputStreamInfo = (PaAsioStreamInfo*) outputParameters->hostApiSpecificStreamInfo;
1964
result = ValidateAsioSpecificStreamInfo (outputParameters, outputStreamInfo,
1965
asioDeviceInfo->commonDeviceInfo.maxOutputChannels,
1966
&outputChannelSelectors
1969
if (result != paNoError) return result;
1969
1971
outputChannelCount = 0;
1970
1972
outputSampleFormat = 0;
1971
1973
suggestedOutputLatencyFrames = 0;
2050
2052
stream->bufferPtrs = 0; /* for deallocation in error */
2052
2054
/* Using blocking i/o interface... */
2053
if( usingBlockingIo )
2055
if (usingBlockingIo) {
2055
2056
/* Blocking i/o is implemented by running callback mode, using a special blocking i/o callback. */
2056
2057
streamCallback = BlockingIoPaCallback; /* Setup PA to use the ASIO blocking i/o callback. */
2057
2058
userData = &theAsioStream; /* The callback user data will be the PA ASIO stream. */
2058
PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
2059
&asioHostApi->blockingStreamInterface, streamCallback, userData );
2061
else /* Using callback interface... */
2063
PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
2064
&asioHostApi->callbackStreamInterface, streamCallback, userData );
2068
PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
2071
stream->asioBufferInfos = (ASIOBufferInfo*)PaUtil_AllocateMemory(
2072
sizeof(ASIOBufferInfo) * (inputChannelCount + outputChannelCount) );
2073
if( !stream->asioBufferInfos )
2059
PaUtil_InitializeStreamRepresentation (&stream->streamRepresentation,
2060
&asioHostApi->blockingStreamInterface, streamCallback, userData);
2061
} else { /* Using callback interface... */
2062
PaUtil_InitializeStreamRepresentation (&stream->streamRepresentation,
2063
&asioHostApi->callbackStreamInterface, streamCallback, userData);
2067
PaUtil_InitializeCpuLoadMeasurer (&stream->cpuLoadMeasurer, sampleRate);
2070
stream->asioBufferInfos = (ASIOBufferInfo*) PaUtil_AllocateMemory (
2071
sizeof (ASIOBufferInfo) * (inputChannelCount + outputChannelCount));
2073
if (!stream->asioBufferInfos) {
2075
2074
result = paInsufficientMemory;
2076
PA_DEBUG(("OpenStream ERROR7\n"));
2075
PA_DEBUG ( ("OpenStream ERROR7\n"));
2081
for( i=0; i < inputChannelCount; ++i )
2080
for (i=0; i < inputChannelCount; ++i) {
2083
2081
ASIOBufferInfo *info = &stream->asioBufferInfos[i];
2085
2083
info->isInput = ASIOTrue;
2087
if( inputChannelSelectors ){
2085
if (inputChannelSelectors) {
2088
2086
// inputChannelSelectors values have already been validated in
2089
2087
// ValidateAsioSpecificStreamInfo() above
2090
2088
info->channelNum = inputChannelSelectors[i];
2092
2090
info->channelNum = i;
2095
2093
info->buffers[0] = info->buffers[1] = 0;
2098
for( i=0; i < outputChannelCount; ++i ){
2096
for (i=0; i < outputChannelCount; ++i) {
2099
2097
ASIOBufferInfo *info = &stream->asioBufferInfos[inputChannelCount+i];
2101
2099
info->isInput = ASIOFalse;
2103
if( outputChannelSelectors ){
2101
if (outputChannelSelectors) {
2104
2102
// outputChannelSelectors values have already been validated in
2105
2103
// ValidateAsioSpecificStreamInfo() above
2106
2104
info->channelNum = outputChannelSelectors[i];
2108
2106
info->channelNum = i;
2111
2109
info->buffers[0] = info->buffers[1] = 0;
2115
2113
/* Using blocking i/o interface... */
2116
if( usingBlockingIo )
2118
/** @todo REVIEW selection of host buffer size for blocking i/o */
2114
if (usingBlockingIo) {
2115
/** @todo REVIEW selection of host buffer size for blocking i/o */
2119
2116
/* Use default host latency for blocking i/o. */
2120
framesPerHostBuffer = SelectHostBufferSize( 0, driverInfo );
2123
else /* Using callback interface... */
2125
framesPerHostBuffer = SelectHostBufferSize(
2126
(( suggestedInputLatencyFrames > suggestedOutputLatencyFrames )
2127
? suggestedInputLatencyFrames : suggestedOutputLatencyFrames),
2132
PA_DEBUG(("PaAsioOpenStream: framesPerHostBuffer :%d\n", framesPerHostBuffer));
2134
asioError = ASIOCreateBuffers( stream->asioBufferInfos,
2135
inputChannelCount+outputChannelCount,
2136
framesPerHostBuffer, &asioCallbacks_ );
2138
if( asioError != ASE_OK
2139
&& framesPerHostBuffer != (unsigned long)driverInfo->bufferPreferredSize )
2141
PA_DEBUG(("ERROR: ASIOCreateBuffers: %s\n", PaAsio_GetAsioErrorText(asioError) ));
2117
framesPerHostBuffer = SelectHostBufferSize (0, driverInfo);
2119
} else { /* Using callback interface... */
2120
framesPerHostBuffer = SelectHostBufferSize (
2121
( (suggestedInputLatencyFrames > suggestedOutputLatencyFrames)
2122
? suggestedInputLatencyFrames : suggestedOutputLatencyFrames),
2127
PA_DEBUG ( ("PaAsioOpenStream: framesPerHostBuffer :%d\n", framesPerHostBuffer));
2129
asioError = ASIOCreateBuffers (stream->asioBufferInfos,
2130
inputChannelCount+outputChannelCount,
2131
framesPerHostBuffer, &asioCallbacks_);
2133
if (asioError != ASE_OK
2134
&& framesPerHostBuffer != (unsigned long) driverInfo->bufferPreferredSize) {
2135
PA_DEBUG ( ("ERROR: ASIOCreateBuffers: %s\n", PaAsio_GetAsioErrorText (asioError)));
2143
2137
Some buggy drivers (like the Hoontech DSP24) give incorrect
2144
2138
[min, preferred, max] values They should work with the preferred size
2149
2143
framesPerHostBuffer = driverInfo->bufferPreferredSize;
2151
PA_DEBUG(("PaAsioOpenStream: CORRECTED framesPerHostBuffer :%d\n", framesPerHostBuffer));
2153
ASIOError asioError2 = ASIOCreateBuffers( stream->asioBufferInfos,
2154
inputChannelCount+outputChannelCount,
2155
framesPerHostBuffer, &asioCallbacks_ );
2156
if( asioError2 == ASE_OK )
2145
PA_DEBUG ( ("PaAsioOpenStream: CORRECTED framesPerHostBuffer :%d\n", framesPerHostBuffer));
2147
ASIOError asioError2 = ASIOCreateBuffers (stream->asioBufferInfos,
2148
inputChannelCount+outputChannelCount,
2149
framesPerHostBuffer, &asioCallbacks_);
2151
if (asioError2 == ASE_OK)
2157
2152
asioError = ASE_OK;
2160
if( asioError != ASE_OK )
2155
if (asioError != ASE_OK) {
2162
2156
result = paUnanticipatedHostError;
2163
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
2164
PA_DEBUG(("OpenStream ERROR9\n"));
2157
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
2158
PA_DEBUG ( ("OpenStream ERROR9\n"));
2168
2162
asioBuffersCreated = 1;
2170
stream->asioChannelInfos = (ASIOChannelInfo*)PaUtil_AllocateMemory(
2171
sizeof(ASIOChannelInfo) * (inputChannelCount + outputChannelCount) );
2172
if( !stream->asioChannelInfos )
2164
stream->asioChannelInfos = (ASIOChannelInfo*) PaUtil_AllocateMemory (
2165
sizeof (ASIOChannelInfo) * (inputChannelCount + outputChannelCount));
2167
if (!stream->asioChannelInfos) {
2174
2168
result = paInsufficientMemory;
2175
PA_DEBUG(("OpenStream ERROR10\n"));
2169
PA_DEBUG ( ("OpenStream ERROR10\n"));
2179
for( i=0; i < inputChannelCount + outputChannelCount; ++i )
2173
for (i=0; i < inputChannelCount + outputChannelCount; ++i) {
2181
2174
stream->asioChannelInfos[i].channel = stream->asioBufferInfos[i].channelNum;
2182
2175
stream->asioChannelInfos[i].isInput = stream->asioBufferInfos[i].isInput;
2183
asioError = ASIOGetChannelInfo( &stream->asioChannelInfos[i] );
2184
if( asioError != ASE_OK )
2176
asioError = ASIOGetChannelInfo (&stream->asioChannelInfos[i]);
2178
if (asioError != ASE_OK) {
2186
2179
result = paUnanticipatedHostError;
2187
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
2188
PA_DEBUG(("OpenStream ERROR11\n"));
2180
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
2181
PA_DEBUG ( ("OpenStream ERROR11\n"));
2193
stream->bufferPtrs = (void**)PaUtil_AllocateMemory(
2194
2 * sizeof(void*) * (inputChannelCount + outputChannelCount) );
2195
if( !stream->bufferPtrs )
2186
stream->bufferPtrs = (void**) PaUtil_AllocateMemory (
2187
2 * sizeof (void*) * (inputChannelCount + outputChannelCount));
2189
if (!stream->bufferPtrs) {
2197
2190
result = paInsufficientMemory;
2198
PA_DEBUG(("OpenStream ERROR12\n"));
2191
PA_DEBUG ( ("OpenStream ERROR12\n"));
2202
if( inputChannelCount > 0 )
2195
if (inputChannelCount > 0) {
2204
2196
stream->inputBufferPtrs[0] = stream-> bufferPtrs;
2205
2197
stream->inputBufferPtrs[1] = &stream->bufferPtrs[inputChannelCount];
2207
for( i=0; i<inputChannelCount; ++i )
2199
for (i=0; i<inputChannelCount; ++i) {
2209
2200
stream->inputBufferPtrs[0][i] = stream->asioBufferInfos[i].buffers[0];
2210
2201
stream->inputBufferPtrs[1][i] = stream->asioBufferInfos[i].buffers[1];
2215
2204
stream->inputBufferPtrs[0] = 0;
2216
2205
stream->inputBufferPtrs[1] = 0;
2219
if( outputChannelCount > 0 )
2208
if (outputChannelCount > 0) {
2221
2209
stream->outputBufferPtrs[0] = &stream->bufferPtrs[inputChannelCount*2];
2222
2210
stream->outputBufferPtrs[1] = &stream->bufferPtrs[inputChannelCount*2 + outputChannelCount];
2224
for( i=0; i<outputChannelCount; ++i )
2212
for (i=0; i<outputChannelCount; ++i) {
2226
2213
stream->outputBufferPtrs[0][i] = stream->asioBufferInfos[inputChannelCount+i].buffers[0];
2227
2214
stream->outputBufferPtrs[1][i] = stream->asioBufferInfos[inputChannelCount+i].buffers[1];
2232
2217
stream->outputBufferPtrs[0] = 0;
2233
2218
stream->outputBufferPtrs[1] = 0;
2236
if( inputChannelCount > 0 )
2221
if (inputChannelCount > 0) {
2238
2222
/* FIXME: assume all channels use the same type for now */
2239
2223
ASIOSampleType inputType = stream->asioChannelInfos[0].type;
2241
PA_DEBUG(("ASIO Input type:%d",inputType));
2242
AsioSampleTypeLOG(inputType);
2243
hostInputSampleFormat = AsioSampleTypeToPaNativeSampleFormat( inputType );
2225
PA_DEBUG ( ("ASIO Input type:%d",inputType));
2226
AsioSampleTypeLOG (inputType);
2227
hostInputSampleFormat = AsioSampleTypeToPaNativeSampleFormat (inputType);
2245
SelectAsioToPaConverter( inputType, &stream->inputBufferConverter, &stream->inputShift );
2229
SelectAsioToPaConverter (inputType, &stream->inputBufferConverter, &stream->inputShift);
2249
2231
hostInputSampleFormat = 0;
2250
2232
stream->inputBufferConverter = 0;
2253
if( outputChannelCount > 0 )
2235
if (outputChannelCount > 0) {
2255
2236
/* FIXME: assume all channels use the same type for now */
2256
2237
ASIOSampleType outputType = stream->asioChannelInfos[inputChannelCount].type;
2258
PA_DEBUG(("ASIO Output type:%d",outputType));
2259
AsioSampleTypeLOG(outputType);
2260
hostOutputSampleFormat = AsioSampleTypeToPaNativeSampleFormat( outputType );
2239
PA_DEBUG ( ("ASIO Output type:%d",outputType));
2240
AsioSampleTypeLOG (outputType);
2241
hostOutputSampleFormat = AsioSampleTypeToPaNativeSampleFormat (outputType);
2262
SelectPaToAsioConverter( outputType, &stream->outputBufferConverter, &stream->outputShift );
2243
SelectPaToAsioConverter (outputType, &stream->outputBufferConverter, &stream->outputShift);
2266
2245
hostOutputSampleFormat = 0;
2267
2246
stream->outputBufferConverter = 0;
2271
ASIOGetLatencies( &stream->inputLatency, &stream->outputLatency );
2250
ASIOGetLatencies (&stream->inputLatency, &stream->outputLatency);
2274
2253
/* Using blocking i/o interface... */
2275
if( usingBlockingIo )
2254
if (usingBlockingIo) {
2277
2255
/* Allocate the blocking i/o input ring buffer memory. */
2278
stream->blockingState = (PaAsioStreamBlockingState*)PaUtil_AllocateMemory( sizeof(PaAsioStreamBlockingState) );
2279
if( !stream->blockingState )
2256
stream->blockingState = (PaAsioStreamBlockingState*) PaUtil_AllocateMemory (sizeof (PaAsioStreamBlockingState));
2258
if (!stream->blockingState) {
2281
2259
result = paInsufficientMemory;
2282
PA_DEBUG(("ERROR! Blocking i/o interface struct allocation failed in OpenStream()\n"));
2260
PA_DEBUG ( ("ERROR! Blocking i/o interface struct allocation failed in OpenStream()\n"));
2296
2274
/* If the user buffer is unspecified */
2297
if( framesPerBuffer == paFramesPerBufferUnspecified )
2275
if (framesPerBuffer == paFramesPerBufferUnspecified) {
2299
2276
/* Make the user buffer the same size as the host buffer. */
2300
2277
framesPerBuffer = framesPerHostBuffer;
2304
2281
/* Initialize callback buffer processor. */
2305
result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor ,
2307
inputSampleFormat & ~paNonInterleaved , /* Ring buffer. */
2308
hostInputSampleFormat , /* Host format. */
2309
outputChannelCount ,
2310
outputSampleFormat & ~paNonInterleaved, /* Ring buffer. */
2311
hostOutputSampleFormat , /* Host format. */
2314
framesPerBuffer , /* Frames per ring buffer block. */
2315
framesPerHostBuffer , /* Frames per asio buffer. */
2316
paUtilFixedHostBufferSize ,
2319
if( result != paNoError ){
2320
PA_DEBUG(("OpenStream ERROR13\n"));
2282
result = PaUtil_InitializeBufferProcessor (&stream->bufferProcessor ,
2284
inputSampleFormat & ~paNonInterleaved , /* Ring buffer. */
2285
hostInputSampleFormat , /* Host format. */
2286
outputChannelCount ,
2287
outputSampleFormat & ~paNonInterleaved, /* Ring buffer. */
2288
hostOutputSampleFormat , /* Host format. */
2291
framesPerBuffer , /* Frames per ring buffer block. */
2292
framesPerHostBuffer , /* Frames per asio buffer. */
2293
paUtilFixedHostBufferSize ,
2297
if (result != paNoError) {
2298
PA_DEBUG ( ("OpenStream ERROR13\n"));
2323
2302
callbackBufferProcessorInited = TRUE;
2325
2304
/* Initialize the blocking i/o buffer processor. */
2326
result = PaUtil_InitializeBufferProcessor(&stream->blockingState->bufferProcessor,
2328
inputSampleFormat , /* User format. */
2329
inputSampleFormat & ~paNonInterleaved , /* Ring buffer. */
2330
outputChannelCount ,
2331
outputSampleFormat , /* User format. */
2332
outputSampleFormat & ~paNonInterleaved, /* Ring buffer. */
2334
paClipOff | paDitherOff , /* Don't use dither nor clipping. */
2335
framesPerBuffer , /* Frames per user buffer. */
2336
framesPerBuffer , /* Frames per ring buffer block. */
2337
paUtilBoundedHostBufferSize ,
2338
NULL, NULL );/* No callback! */
2339
if( result != paNoError ){
2340
PA_DEBUG(("ERROR! Blocking i/o buffer processor initialization failed in OpenStream()\n"));
2305
result = PaUtil_InitializeBufferProcessor (&stream->blockingState->bufferProcessor,
2307
inputSampleFormat , /* User format. */
2308
inputSampleFormat & ~paNonInterleaved , /* Ring buffer. */
2309
outputChannelCount ,
2310
outputSampleFormat , /* User format. */
2311
outputSampleFormat & ~paNonInterleaved, /* Ring buffer. */
2313
paClipOff | paDitherOff , /* Don't use dither nor clipping. */
2314
framesPerBuffer , /* Frames per user buffer. */
2315
framesPerBuffer , /* Frames per ring buffer block. */
2316
paUtilBoundedHostBufferSize ,
2317
NULL, NULL); /* No callback! */
2319
if (result != paNoError) {
2320
PA_DEBUG ( ("ERROR! Blocking i/o buffer processor initialization failed in OpenStream()\n"));
2343
2324
blockingBufferProcessorInited = TRUE;
2345
2326
/* If input is requested. */
2346
if( inputChannelCount )
2327
if (inputChannelCount) {
2348
2328
/* Create the callback sync-event. */
2349
stream->blockingState->readFramesReadyEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
2350
if( stream->blockingState->readFramesReadyEvent == NULL )
2329
stream->blockingState->readFramesReadyEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
2331
if (stream->blockingState->readFramesReadyEvent == NULL) {
2352
2332
result = paUnanticipatedHostError;
2353
PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
2354
PA_DEBUG(("ERROR! Blocking i/o \"read frames ready\" event creation failed in OpenStream()\n"));
2333
PA_ASIO_SET_LAST_SYSTEM_ERROR (GetLastError());
2334
PA_DEBUG ( ("ERROR! Blocking i/o \"read frames ready\" event creation failed in OpenStream()\n"));
2357
2338
blockingReadFramesReadyEventInitialized = 1;
2360
2341
/* Create pointer buffer to access non-interleaved data in ReadStream() */
2361
stream->blockingState->readStreamBuffer = (void**)PaUtil_AllocateMemory( sizeof(void*) * inputChannelCount );
2362
if( !stream->blockingState->readStreamBuffer )
2342
stream->blockingState->readStreamBuffer = (void**) PaUtil_AllocateMemory (sizeof (void*) * inputChannelCount);
2344
if (!stream->blockingState->readStreamBuffer) {
2364
2345
result = paInsufficientMemory;
2365
PA_DEBUG(("ERROR! Blocking i/o read stream buffer allocation failed in OpenStream()\n"));
2346
PA_DEBUG ( ("ERROR! Blocking i/o read stream buffer allocation failed in OpenStream()\n"));
2388
2369
/* Get the next larger or equal power-of-two buffersize. */
2389
2370
lBlockingBufferSizePow2 = 1;
2390
while( lBlockingBufferSize > (lBlockingBufferSizePow2<<=1) );
2372
while (lBlockingBufferSize > (lBlockingBufferSizePow2<<=1));
2391
2374
lBlockingBufferSize = lBlockingBufferSizePow2;
2393
2376
/* Compute total intput latency in seconds */
2394
2377
stream->streamRepresentation.streamInfo.inputLatency =
2395
(double)( PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor )
2396
+ PaUtil_GetBufferProcessorInputLatency(&stream->blockingState->bufferProcessor)
2397
+ (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer
2398
+ stream->inputLatency )
2378
(double) (PaUtil_GetBufferProcessorInputLatency (&stream->bufferProcessor)
2379
+ PaUtil_GetBufferProcessorInputLatency (&stream->blockingState->bufferProcessor)
2380
+ (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer
2381
+ stream->inputLatency)
2401
2384
/* The code below prints the ASIO latency which doesn't include
2402
2385
the buffer processor latency nor the blocking i/o latency. It
2403
2386
reports the added latency separately.
2405
PA_DEBUG(("PaAsio : ASIO InputLatency = %ld (%ld ms),\n added buffProc:%ld (%ld ms),\n added blocking:%ld (%ld ms)\n",
2406
stream->inputLatency,
2407
(long)( stream->inputLatency * (1000.0 / sampleRate) ),
2408
PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor),
2409
(long)( PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor) * (1000.0 / sampleRate) ),
2410
PaUtil_GetBufferProcessorInputLatency(&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer,
2411
(long)( (PaUtil_GetBufferProcessorInputLatency(&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer) * (1000.0 / sampleRate) )
2388
PA_DEBUG ( ("PaAsio : ASIO InputLatency = %ld (%ld ms),\n added buffProc:%ld (%ld ms),\n added blocking:%ld (%ld ms)\n",
2389
stream->inputLatency,
2390
(long) (stream->inputLatency * (1000.0 / sampleRate)),
2391
PaUtil_GetBufferProcessorInputLatency (&stream->bufferProcessor),
2392
(long) (PaUtil_GetBufferProcessorInputLatency (&stream->bufferProcessor) * (1000.0 / sampleRate)),
2393
PaUtil_GetBufferProcessorInputLatency (&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer,
2394
(long) ( (PaUtil_GetBufferProcessorInputLatency (&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer) * (1000.0 / sampleRate))
2414
2397
/* Determine the size of ring buffer in bytes. */
2415
lBytesPerFrame = inputChannelCount * Pa_GetSampleSize(inputSampleFormat );
2398
lBytesPerFrame = inputChannelCount * Pa_GetSampleSize (inputSampleFormat);
2417
2400
/* Allocate the blocking i/o input ring buffer memory. */
2418
stream->blockingState->readRingBufferData = (void*)PaUtil_AllocateMemory( lBlockingBufferSize * lBytesPerFrame );
2419
if( !stream->blockingState->readRingBufferData )
2401
stream->blockingState->readRingBufferData = (void*) PaUtil_AllocateMemory (lBlockingBufferSize * lBytesPerFrame);
2403
if (!stream->blockingState->readRingBufferData) {
2421
2404
result = paInsufficientMemory;
2422
PA_DEBUG(("ERROR! Blocking i/o input ring buffer allocation failed in OpenStream()\n"));
2405
PA_DEBUG ( ("ERROR! Blocking i/o input ring buffer allocation failed in OpenStream()\n"));
2426
2409
/* Initialize the input ring buffer struct. */
2427
PaUtil_InitializeRingBuffer( &stream->blockingState->readRingBuffer ,
2429
lBlockingBufferSize ,
2430
stream->blockingState->readRingBufferData );
2410
PaUtil_InitializeRingBuffer (&stream->blockingState->readRingBuffer ,
2412
lBlockingBufferSize ,
2413
stream->blockingState->readRingBufferData);
2433
2416
/* If output is requested. */
2434
if( outputChannelCount )
2436
stream->blockingState->writeBuffersReadyEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
2437
if( stream->blockingState->writeBuffersReadyEvent == NULL )
2417
if (outputChannelCount) {
2418
stream->blockingState->writeBuffersReadyEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
2420
if (stream->blockingState->writeBuffersReadyEvent == NULL) {
2439
2421
result = paUnanticipatedHostError;
2440
PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
2441
PA_DEBUG(("ERROR! Blocking i/o \"write buffers ready\" event creation failed in OpenStream()\n"));
2422
PA_ASIO_SET_LAST_SYSTEM_ERROR (GetLastError());
2423
PA_DEBUG ( ("ERROR! Blocking i/o \"write buffers ready\" event creation failed in OpenStream()\n"));
2444
2427
blockingWriteBuffersReadyEventInitialized = 1;
2446
2429
/* Create pointer buffer to access non-interleaved data in WriteStream() */
2447
stream->blockingState->writeStreamBuffer = (const void**)PaUtil_AllocateMemory( sizeof(const void*) * outputChannelCount );
2448
if( !stream->blockingState->writeStreamBuffer )
2430
stream->blockingState->writeStreamBuffer = (const void**) PaUtil_AllocateMemory (sizeof (const void*) * outputChannelCount);
2432
if (!stream->blockingState->writeStreamBuffer) {
2450
2433
result = paInsufficientMemory;
2451
PA_DEBUG(("ERROR! Blocking i/o write stream buffer allocation failed in OpenStream()\n"));
2434
PA_DEBUG ( ("ERROR! Blocking i/o write stream buffer allocation failed in OpenStream()\n"));
2479
2462
/* Get the next larger or equal power-of-two buffersize. */
2480
2463
lBlockingBufferSizePow2 = 1;
2481
while( lBlockingBufferSize > (lBlockingBufferSizePow2<<=1) );
2465
while (lBlockingBufferSize > (lBlockingBufferSizePow2<<=1));
2482
2467
lBlockingBufferSize = lBlockingBufferSizePow2;
2484
2469
/* Compute total output latency in seconds */
2485
2470
stream->streamRepresentation.streamInfo.outputLatency =
2486
(double)( PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor )
2487
+ PaUtil_GetBufferProcessorOutputLatency(&stream->blockingState->bufferProcessor)
2488
+ (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer
2489
+ stream->outputLatency )
2471
(double) (PaUtil_GetBufferProcessorOutputLatency (&stream->bufferProcessor)
2472
+ PaUtil_GetBufferProcessorOutputLatency (&stream->blockingState->bufferProcessor)
2473
+ (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer
2474
+ stream->outputLatency)
2492
2477
/* The code below prints the ASIO latency which doesn't include
2493
2478
the buffer processor latency nor the blocking i/o latency. It
2494
2479
reports the added latency separately.
2496
PA_DEBUG(("PaAsio : ASIO OutputLatency = %ld (%ld ms),\n added buffProc:%ld (%ld ms),\n added blocking:%ld (%ld ms)\n",
2497
stream->outputLatency,
2498
(long)( stream->inputLatency * (1000.0 / sampleRate) ),
2499
PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor),
2500
(long)( PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor) * (1000.0 / sampleRate) ),
2501
PaUtil_GetBufferProcessorOutputLatency(&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer,
2502
(long)( (PaUtil_GetBufferProcessorOutputLatency(&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer) * (1000.0 / sampleRate) )
2481
PA_DEBUG ( ("PaAsio : ASIO OutputLatency = %ld (%ld ms),\n added buffProc:%ld (%ld ms),\n added blocking:%ld (%ld ms)\n",
2482
stream->outputLatency,
2483
(long) (stream->inputLatency * (1000.0 / sampleRate)),
2484
PaUtil_GetBufferProcessorOutputLatency (&stream->bufferProcessor),
2485
(long) (PaUtil_GetBufferProcessorOutputLatency (&stream->bufferProcessor) * (1000.0 / sampleRate)),
2486
PaUtil_GetBufferProcessorOutputLatency (&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer,
2487
(long) ( (PaUtil_GetBufferProcessorOutputLatency (&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer) * (1000.0 / sampleRate))
2505
2490
/* Determine the size of ring buffer in bytes. */
2506
lBytesPerFrame = outputChannelCount * Pa_GetSampleSize(outputSampleFormat);
2491
lBytesPerFrame = outputChannelCount * Pa_GetSampleSize (outputSampleFormat);
2508
2493
/* Allocate the blocking i/o output ring buffer memory. */
2509
stream->blockingState->writeRingBufferData = (void*)PaUtil_AllocateMemory( lBlockingBufferSize * lBytesPerFrame );
2510
if( !stream->blockingState->writeRingBufferData )
2494
stream->blockingState->writeRingBufferData = (void*) PaUtil_AllocateMemory (lBlockingBufferSize * lBytesPerFrame);
2496
if (!stream->blockingState->writeRingBufferData) {
2512
2497
result = paInsufficientMemory;
2513
PA_DEBUG(("ERROR! Blocking i/o output ring buffer allocation failed in OpenStream()\n"));
2498
PA_DEBUG ( ("ERROR! Blocking i/o output ring buffer allocation failed in OpenStream()\n"));
2517
2502
/* Initialize the output ring buffer struct. */
2518
PaUtil_InitializeRingBuffer( &stream->blockingState->writeRingBuffer ,
2520
lBlockingBufferSize ,
2521
stream->blockingState->writeRingBufferData );
2503
PaUtil_InitializeRingBuffer (&stream->blockingState->writeRingBuffer ,
2505
lBlockingBufferSize ,
2506
stream->blockingState->writeRingBufferData);
2524
2509
stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
2528
else /* Using callback interface... */
2530
result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
2531
inputChannelCount, inputSampleFormat, hostInputSampleFormat,
2532
outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
2533
sampleRate, streamFlags, framesPerBuffer,
2534
framesPerHostBuffer, paUtilFixedHostBufferSize,
2535
streamCallback, userData );
2536
if( result != paNoError ){
2537
PA_DEBUG(("OpenStream ERROR13\n"));
2512
} else { /* Using callback interface... */
2513
result = PaUtil_InitializeBufferProcessor (&stream->bufferProcessor,
2514
inputChannelCount, inputSampleFormat, hostInputSampleFormat,
2515
outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
2516
sampleRate, streamFlags, framesPerBuffer,
2517
framesPerHostBuffer, paUtilFixedHostBufferSize,
2518
streamCallback, userData);
2520
if (result != paNoError) {
2521
PA_DEBUG ( ("OpenStream ERROR13\n"));
2540
2525
callbackBufferProcessorInited = TRUE;
2542
2527
stream->streamRepresentation.streamInfo.inputLatency =
2543
(double)( PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor)
2544
+ stream->inputLatency) / sampleRate; // seconds
2528
(double) (PaUtil_GetBufferProcessorInputLatency (&stream->bufferProcessor)
2529
+ stream->inputLatency) / sampleRate; // seconds
2545
2530
stream->streamRepresentation.streamInfo.outputLatency =
2546
(double)( PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor)
2547
+ stream->outputLatency) / sampleRate; // seconds
2531
(double) (PaUtil_GetBufferProcessorOutputLatency (&stream->bufferProcessor)
2532
+ stream->outputLatency) / sampleRate; // seconds
2548
2533
stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
2550
2535
// the code below prints the ASIO latency which doesn't include the
2551
2536
// buffer processor latency. it reports the added latency separately
2552
PA_DEBUG(("PaAsio : ASIO InputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n",
2553
stream->inputLatency,
2554
(long)((stream->inputLatency*1000)/ sampleRate),
2555
PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor),
2556
(long)((PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor)*1000)/ sampleRate)
2537
PA_DEBUG ( ("PaAsio : ASIO InputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n",
2538
stream->inputLatency,
2539
(long) ( (stream->inputLatency*1000) / sampleRate),
2540
PaUtil_GetBufferProcessorInputLatency (&stream->bufferProcessor),
2541
(long) ( (PaUtil_GetBufferProcessorInputLatency (&stream->bufferProcessor) *1000) / sampleRate)
2559
PA_DEBUG(("PaAsio : ASIO OuputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n",
2560
stream->outputLatency,
2561
(long)((stream->outputLatency*1000)/ sampleRate),
2562
PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor),
2563
(long)((PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor)*1000)/ sampleRate)
2544
PA_DEBUG ( ("PaAsio : ASIO OuputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n",
2545
stream->outputLatency,
2546
(long) ( (stream->outputLatency*1000) / sampleRate),
2547
PaUtil_GetBufferProcessorOutputLatency (&stream->bufferProcessor),
2548
(long) ( (PaUtil_GetBufferProcessorOutputLatency (&stream->bufferProcessor) *1000) / sampleRate)
2567
2552
stream->asioHostApi = asioHostApi;
2572
2557
stream->postOutput = driverInfo->postOutput;
2573
2558
stream->isStopped = 1;
2574
2559
stream->isActive = 0;
2576
2561
asioHostApi->openAsioDeviceIndex = asioDeviceIndex;
2578
2563
theAsioStream = stream;
2579
*s = (PaStream*)stream;
2564
*s = (PaStream*) stream;
2584
PA_DEBUG(("goto errored\n"));
2587
if( stream->blockingState )
2589
if( blockingBufferProcessorInited )
2590
PaUtil_TerminateBufferProcessor( &stream->blockingState->bufferProcessor );
2592
if( stream->blockingState->writeRingBufferData )
2593
PaUtil_FreeMemory( stream->blockingState->writeRingBufferData );
2594
if( stream->blockingState->writeStreamBuffer )
2595
PaUtil_FreeMemory( stream->blockingState->writeStreamBuffer );
2596
if( blockingWriteBuffersReadyEventInitialized )
2597
CloseHandle( stream->blockingState->writeBuffersReadyEvent );
2599
if( stream->blockingState->readRingBufferData )
2600
PaUtil_FreeMemory( stream->blockingState->readRingBufferData );
2601
if( stream->blockingState->readStreamBuffer )
2602
PaUtil_FreeMemory( stream->blockingState->readStreamBuffer );
2603
if( blockingReadFramesReadyEventInitialized )
2604
CloseHandle( stream->blockingState->readFramesReadyEvent );
2606
PaUtil_FreeMemory( stream->blockingState );
2569
PA_DEBUG ( ("goto errored\n"));
2572
if (stream->blockingState) {
2573
if (blockingBufferProcessorInited)
2574
PaUtil_TerminateBufferProcessor (&stream->blockingState->bufferProcessor);
2576
if (stream->blockingState->writeRingBufferData)
2577
PaUtil_FreeMemory (stream->blockingState->writeRingBufferData);
2579
if (stream->blockingState->writeStreamBuffer)
2580
PaUtil_FreeMemory (stream->blockingState->writeStreamBuffer);
2582
if (blockingWriteBuffersReadyEventInitialized)
2583
CloseHandle (stream->blockingState->writeBuffersReadyEvent);
2585
if (stream->blockingState->readRingBufferData)
2586
PaUtil_FreeMemory (stream->blockingState->readRingBufferData);
2588
if (stream->blockingState->readStreamBuffer)
2589
PaUtil_FreeMemory (stream->blockingState->readStreamBuffer);
2591
if (blockingReadFramesReadyEventInitialized)
2592
CloseHandle (stream->blockingState->readFramesReadyEvent);
2594
PaUtil_FreeMemory (stream->blockingState);
2609
if( callbackBufferProcessorInited )
2610
PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
2612
if( completedBuffersPlayedEventInited )
2613
CloseHandle( stream->completedBuffersPlayedEvent );
2615
if( stream->asioBufferInfos )
2616
PaUtil_FreeMemory( stream->asioBufferInfos );
2618
if( stream->asioChannelInfos )
2619
PaUtil_FreeMemory( stream->asioChannelInfos );
2621
if( stream->bufferPtrs )
2622
PaUtil_FreeMemory( stream->bufferPtrs );
2624
PaUtil_FreeMemory( stream );
2597
if (callbackBufferProcessorInited)
2598
PaUtil_TerminateBufferProcessor (&stream->bufferProcessor);
2600
if (completedBuffersPlayedEventInited)
2601
CloseHandle (stream->completedBuffersPlayedEvent);
2603
if (stream->asioBufferInfos)
2604
PaUtil_FreeMemory (stream->asioBufferInfos);
2606
if (stream->asioChannelInfos)
2607
PaUtil_FreeMemory (stream->asioChannelInfos);
2609
if (stream->bufferPtrs)
2610
PaUtil_FreeMemory (stream->bufferPtrs);
2612
PaUtil_FreeMemory (stream);
2627
if( asioBuffersCreated )
2615
if (asioBuffersCreated)
2628
2616
ASIODisposeBuffers();
2630
if( asioIsInitialized )
2618
if (asioIsInitialized) {
2639
2627
When CloseStream() is called, the multi-api layer ensures that
2640
2628
the stream has already been stopped or aborted.
2642
static PaError CloseStream( PaStream* s )
2630
static PaError CloseStream (PaStream* s)
2644
2632
PaError result = paNoError;
2645
PaAsioStream *stream = (PaAsioStream*)s;
2633
PaAsioStream *stream = (PaAsioStream*) s;
2649
2637
- additional stream closing + cleanup
2652
PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
2653
PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
2640
PaUtil_TerminateBufferProcessor (&stream->bufferProcessor);
2641
PaUtil_TerminateStreamRepresentation (&stream->streamRepresentation);
2655
2643
stream->asioHostApi->openAsioDeviceIndex = paNoDevice;
2657
CloseHandle( stream->completedBuffersPlayedEvent );
2645
CloseHandle (stream->completedBuffersPlayedEvent);
2659
2647
/* Using blocking i/o interface... */
2660
if( stream->blockingState )
2662
PaUtil_TerminateBufferProcessor( &stream->blockingState->bufferProcessor );
2664
if( stream->inputChannelCount ) {
2665
PaUtil_FreeMemory( stream->blockingState->readRingBufferData );
2666
PaUtil_FreeMemory( stream->blockingState->readStreamBuffer );
2667
CloseHandle( stream->blockingState->readFramesReadyEvent );
2669
if( stream->outputChannelCount ) {
2670
PaUtil_FreeMemory( stream->blockingState->writeRingBufferData );
2671
PaUtil_FreeMemory( stream->blockingState->writeStreamBuffer );
2672
CloseHandle( stream->blockingState->writeBuffersReadyEvent );
2675
PaUtil_FreeMemory( stream->blockingState );
2648
if (stream->blockingState) {
2649
PaUtil_TerminateBufferProcessor (&stream->blockingState->bufferProcessor);
2651
if (stream->inputChannelCount) {
2652
PaUtil_FreeMemory (stream->blockingState->readRingBufferData);
2653
PaUtil_FreeMemory (stream->blockingState->readStreamBuffer);
2654
CloseHandle (stream->blockingState->readFramesReadyEvent);
2657
if (stream->outputChannelCount) {
2658
PaUtil_FreeMemory (stream->blockingState->writeRingBufferData);
2659
PaUtil_FreeMemory (stream->blockingState->writeStreamBuffer);
2660
CloseHandle (stream->blockingState->writeBuffersReadyEvent);
2663
PaUtil_FreeMemory (stream->blockingState);
2678
PaUtil_FreeMemory( stream->asioBufferInfos );
2679
PaUtil_FreeMemory( stream->asioChannelInfos );
2680
PaUtil_FreeMemory( stream->bufferPtrs );
2681
PaUtil_FreeMemory( stream );
2666
PaUtil_FreeMemory (stream->asioBufferInfos);
2667
PaUtil_FreeMemory (stream->asioChannelInfos);
2668
PaUtil_FreeMemory (stream->bufferPtrs);
2669
PaUtil_FreeMemory (stream);
2683
2671
ASIODisposeBuffers();
2684
2672
UnloadAsioDriver();
2849
2829
// check that sample delta matches buffer size (otherwise we must have skipped
2851
static double last_samples = -512;
2831
static double last_samples = -512;
2853
2833
//if( timeInfo->timeCode.flags & kTcValid )
2854
2834
// samples = ASIO64toDouble(timeInfo->timeCode.timeCodeSamples);
2856
samples = ASIO64toDouble(timeInfo->timeInfo.samplePosition);
2857
int delta = samples - last_samples;
2836
samples = ASIO64toDouble (timeInfo->timeInfo.samplePosition);
2837
int delta = samples - last_samples;
2858
2838
//printf( "%d\n", delta);
2859
last_samples = samples;
2861
if( delta > theAsioStream->framesPerHostCallback )
2863
if( theAsioStream->inputChannelCount > 0 )
2864
theAsioStream->callbackFlags |= paInputOverflow;
2866
if( theAsioStream->outputChannelCount > 0 )
2867
theAsioStream->callbackFlags |= paOutputUnderflow;
2839
last_samples = samples;
2841
if (delta > theAsioStream->framesPerHostCallback) {
2842
if (theAsioStream->inputChannelCount > 0)
2843
theAsioStream->callbackFlags |= paInputOverflow;
2845
if (theAsioStream->outputChannelCount > 0)
2846
theAsioStream->callbackFlags |= paOutputUnderflow;
2870
2849
// check that the buffer index is not the previous index (which would indicate
2871
2850
// that a buffer was skipped.
2872
static int previousIndex = 1;
2873
if( index == previousIndex )
2875
if( theAsioStream->inputChannelCount > 0 )
2876
theAsioStream->callbackFlags |= paInputOverflow;
2878
if( theAsioStream->outputChannelCount > 0 )
2879
theAsioStream->callbackFlags |= paOutputUnderflow;
2881
previousIndex = index;
2851
static int previousIndex = 1;
2853
if (index == previousIndex) {
2854
if (theAsioStream->inputChannelCount > 0)
2855
theAsioStream->callbackFlags |= paInputOverflow;
2857
if (theAsioStream->outputChannelCount > 0)
2858
theAsioStream->callbackFlags |= paOutputUnderflow;
2861
previousIndex = index;
2886
PaUtil_BeginCpuLoadMeasurement( &theAsioStream->cpuLoadMeasurer );
2866
PaUtil_BeginCpuLoadMeasurement (&theAsioStream->cpuLoadMeasurer);
2888
2868
PaStreamCallbackTimeInfo paTimeInfo;
2890
2870
// asio systemTime is supposed to be measured according to the same
2891
2871
// clock as timeGetTime
2892
paTimeInfo.currentTime = (ASIO64toDouble( timeInfo->timeInfo.systemTime ) * .000000001);
2872
paTimeInfo.currentTime = (ASIO64toDouble (timeInfo->timeInfo.systemTime) * .000000001);
2894
2874
/* patch from Paul Boege */
2895
2875
paTimeInfo.inputBufferAdcTime = paTimeInfo.currentTime -
2896
((double)theAsioStream->inputLatency/theAsioStream->streamRepresentation.streamInfo.sampleRate);
2876
( (double) theAsioStream->inputLatency/theAsioStream->streamRepresentation.streamInfo.sampleRate);
2898
2878
paTimeInfo.outputBufferDacTime = paTimeInfo.currentTime +
2899
((double)theAsioStream->outputLatency/theAsioStream->streamRepresentation.streamInfo.sampleRate);
2879
( (double) theAsioStream->outputLatency/theAsioStream->streamRepresentation.streamInfo.sampleRate);
2901
2881
/* old version is buggy because the buffer processor also adds in its latency to the time parameters
2902
2882
paTimeInfo.inputBufferAdcTime = paTimeInfo.currentTime - theAsioStream->streamRepresentation.streamInfo.inputLatency;
2903
2883
paTimeInfo.outputBufferDacTime = paTimeInfo.currentTime + theAsioStream->streamRepresentation.streamInfo.outputLatency;
2906
/* Disabled! Stopping and re-starting the stream causes an input overflow / output undeflow. S.Fischer */
2886
/* Disabled! Stopping and re-starting the stream causes an input overflow / output undeflow. S.Fischer */
2908
2888
// detect underflows by checking inter-callback time > 2 buffer period
2909
static double previousTime = -1;
2910
if( previousTime > 0 ){
2912
double delta = paTimeInfo.currentTime - previousTime;
2914
if( delta >= 2. * (theAsioStream->framesPerHostCallback / theAsioStream->streamRepresentation.streamInfo.sampleRate) ){
2915
if( theAsioStream->inputChannelCount > 0 )
2916
theAsioStream->callbackFlags |= paInputOverflow;
2918
if( theAsioStream->outputChannelCount > 0 )
2919
theAsioStream->callbackFlags |= paOutputUnderflow;
2922
previousTime = paTimeInfo.currentTime;
2889
static double previousTime = -1;
2891
if (previousTime > 0) {
2893
double delta = paTimeInfo.currentTime - previousTime;
2895
if (delta >= 2. * (theAsioStream->framesPerHostCallback / theAsioStream->streamRepresentation.streamInfo.sampleRate)) {
2896
if (theAsioStream->inputChannelCount > 0)
2897
theAsioStream->callbackFlags |= paInputOverflow;
2899
if (theAsioStream->outputChannelCount > 0)
2900
theAsioStream->callbackFlags |= paOutputUnderflow;
2904
previousTime = paTimeInfo.currentTime;
2925
2907
// note that the above input and output times do not need to be
2926
2908
// adjusted for the latency of the buffer processor -- the buffer
2927
2909
// processor handles that.
2929
if( theAsioStream->inputBufferConverter )
2931
for( i=0; i<theAsioStream->inputChannelCount; i++ )
2933
theAsioStream->inputBufferConverter( theAsioStream->inputBufferPtrs[index][i],
2934
theAsioStream->inputShift, theAsioStream->framesPerHostCallback );
2911
if (theAsioStream->inputBufferConverter) {
2912
for (i=0; i<theAsioStream->inputChannelCount; i++) {
2913
theAsioStream->inputBufferConverter (theAsioStream->inputBufferPtrs[index][i],
2914
theAsioStream->inputShift, theAsioStream->framesPerHostCallback);
2938
PaUtil_BeginBufferProcessing( &theAsioStream->bufferProcessor, &paTimeInfo, theAsioStream->callbackFlags );
2918
PaUtil_BeginBufferProcessing (&theAsioStream->bufferProcessor, &paTimeInfo, theAsioStream->callbackFlags);
2940
2920
/* reset status flags once they've been passed to the callback */
2941
2921
theAsioStream->callbackFlags = 0;
2943
PaUtil_SetInputFrameCount( &theAsioStream->bufferProcessor, 0 /* default to host buffer size */ );
2944
for( i=0; i<theAsioStream->inputChannelCount; ++i )
2945
PaUtil_SetNonInterleavedInputChannel( &theAsioStream->bufferProcessor, i, theAsioStream->inputBufferPtrs[index][i] );
2947
PaUtil_SetOutputFrameCount( &theAsioStream->bufferProcessor, 0 /* default to host buffer size */ );
2948
for( i=0; i<theAsioStream->outputChannelCount; ++i )
2949
PaUtil_SetNonInterleavedOutputChannel( &theAsioStream->bufferProcessor, i, theAsioStream->outputBufferPtrs[index][i] );
2923
PaUtil_SetInputFrameCount (&theAsioStream->bufferProcessor, 0 /* default to host buffer size */);
2925
for (i=0; i<theAsioStream->inputChannelCount; ++i)
2926
PaUtil_SetNonInterleavedInputChannel (&theAsioStream->bufferProcessor, i, theAsioStream->inputBufferPtrs[index][i]);
2928
PaUtil_SetOutputFrameCount (&theAsioStream->bufferProcessor, 0 /* default to host buffer size */);
2930
for (i=0; i<theAsioStream->outputChannelCount; ++i)
2931
PaUtil_SetNonInterleavedOutputChannel (&theAsioStream->bufferProcessor, i, theAsioStream->outputBufferPtrs[index][i]);
2951
2933
int callbackResult;
2952
if( theAsioStream->stopProcessing )
2935
if (theAsioStream->stopProcessing)
2953
2936
callbackResult = paComplete;
2955
2938
callbackResult = paContinue;
2956
unsigned long framesProcessed = PaUtil_EndBufferProcessing( &theAsioStream->bufferProcessor, &callbackResult );
2958
if( theAsioStream->outputBufferConverter )
2960
for( i=0; i<theAsioStream->outputChannelCount; i++ )
2962
theAsioStream->outputBufferConverter( theAsioStream->outputBufferPtrs[index][i],
2963
theAsioStream->outputShift, theAsioStream->framesPerHostCallback );
2940
unsigned long framesProcessed = PaUtil_EndBufferProcessing (&theAsioStream->bufferProcessor, &callbackResult);
2942
if (theAsioStream->outputBufferConverter) {
2943
for (i=0; i<theAsioStream->outputChannelCount; i++) {
2944
theAsioStream->outputBufferConverter (theAsioStream->outputBufferPtrs[index][i],
2945
theAsioStream->outputShift, theAsioStream->framesPerHostCallback);
2967
PaUtil_EndCpuLoadMeasurement( &theAsioStream->cpuLoadMeasurer, framesProcessed );
2949
PaUtil_EndCpuLoadMeasurement (&theAsioStream->cpuLoadMeasurer, framesProcessed);
2969
2951
// Finally if the driver supports the ASIOOutputReady() optimization,
2970
2952
// do it here, all data are in place
2971
if( theAsioStream->postOutput )
2953
if (theAsioStream->postOutput)
2972
2954
ASIOOutputReady();
2974
if( callbackResult == paContinue )
2956
if (callbackResult == paContinue) {
2976
2957
/* nothing special to do */
2978
else if( callbackResult == paAbort )
2958
} else if (callbackResult == paAbort) {
2980
2959
/* finish playback immediately */
2981
2960
theAsioStream->isActive = 0;
2982
if( theAsioStream->streamRepresentation.streamFinishedCallback != 0 )
2983
theAsioStream->streamRepresentation.streamFinishedCallback( theAsioStream->streamRepresentation.userData );
2962
if (theAsioStream->streamRepresentation.streamFinishedCallback != 0)
2963
theAsioStream->streamRepresentation.streamFinishedCallback (theAsioStream->streamRepresentation.userData);
2984
2965
theAsioStream->streamFinishedCallbackCalled = true;
2985
SetEvent( theAsioStream->completedBuffersPlayedEvent );
2966
SetEvent (theAsioStream->completedBuffersPlayedEvent);
2986
2967
theAsioStream->zeroOutput = true;
2988
else /* paComplete or other non-zero value indicating complete */
2968
} else { /* paComplete or other non-zero value indicating complete */
2990
2969
/* Finish playback once currently queued audio has completed. */
2991
2970
theAsioStream->stopProcessing = true;
2993
if( PaUtil_IsBufferProcessorOutputEmpty( &theAsioStream->bufferProcessor ) )
2972
if (PaUtil_IsBufferProcessorOutputEmpty (&theAsioStream->bufferProcessor)) {
2995
2973
theAsioStream->zeroOutput = true;
2996
2974
theAsioStream->stopPlayoutCount = 0;
3003
}while( PaAsio_AtomicDecrement(&theAsioStream->reenterCount) >= 0 );
2981
} while (PaAsio_AtomicDecrement (&theAsioStream->reenterCount) >= 0);
3009
static void sampleRateChanged(ASIOSampleRate sRate)
2987
static void sampleRateChanged (ASIOSampleRate sRate)
3011
2989
// TAKEN FROM THE ASIO SDK
3012
2990
// do whatever you need to do if the sample rate changed
3128
3107
stream->callbackFlags = 0;
3130
if( ResetEvent( stream->completedBuffersPlayedEvent ) == 0 )
3109
if (ResetEvent (stream->completedBuffersPlayedEvent) == 0) {
3132
3110
result = paUnanticipatedHostError;
3133
PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
3111
PA_ASIO_SET_LAST_SYSTEM_ERROR (GetLastError());
3137
3115
/* Using blocking i/o interface... */
3116
if (blockingState) {
3140
3117
/* Reset blocking i/o buffer processor. */
3141
PaUtil_ResetBufferProcessor( &blockingState->bufferProcessor );
3118
PaUtil_ResetBufferProcessor (&blockingState->bufferProcessor);
3143
3120
/* If we're about to process some input data. */
3144
if( stream->inputChannelCount )
3121
if (stream->inputChannelCount) {
3146
3122
/* Reset callback-ReadStream sync event. */
3147
if( ResetEvent( blockingState->readFramesReadyEvent ) == 0 )
3123
if (ResetEvent (blockingState->readFramesReadyEvent) == 0) {
3149
3124
result = paUnanticipatedHostError;
3150
PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
3125
PA_ASIO_SET_LAST_SYSTEM_ERROR (GetLastError());
3153
3128
/* Flush blocking i/o ring buffer. */
3154
PaUtil_FlushRingBuffer( &blockingState->readRingBuffer );
3155
(*blockingState->bufferProcessor.inputZeroer)( blockingState->readRingBuffer.buffer, 1, blockingState->bufferProcessor.inputChannelCount * blockingState->readRingBuffer.bufferSize );
3129
PaUtil_FlushRingBuffer (&blockingState->readRingBuffer);
3130
(*blockingState->bufferProcessor.inputZeroer) (blockingState->readRingBuffer.buffer, 1, blockingState->bufferProcessor.inputChannelCount * blockingState->readRingBuffer.bufferSize);
3158
3133
/* If we're about to process some output data. */
3159
if( stream->outputChannelCount )
3134
if (stream->outputChannelCount) {
3161
3135
/* Reset callback-WriteStream sync event. */
3162
if( ResetEvent( blockingState->writeBuffersReadyEvent ) == 0 )
3136
if (ResetEvent (blockingState->writeBuffersReadyEvent) == 0) {
3164
3137
result = paUnanticipatedHostError;
3165
PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
3138
PA_ASIO_SET_LAST_SYSTEM_ERROR (GetLastError());
3168
3141
/* Flush blocking i/o ring buffer. */
3169
PaUtil_FlushRingBuffer( &blockingState->writeRingBuffer );
3170
(*blockingState->bufferProcessor.outputZeroer)( blockingState->writeRingBuffer.buffer, 1, blockingState->bufferProcessor.outputChannelCount * blockingState->writeRingBuffer.bufferSize );
3142
PaUtil_FlushRingBuffer (&blockingState->writeRingBuffer);
3143
(*blockingState->bufferProcessor.outputZeroer) (blockingState->writeRingBuffer.buffer, 1, blockingState->bufferProcessor.outputChannelCount * blockingState->writeRingBuffer.bufferSize);
3172
3145
/* Initialize the output ring buffer to "silence". */
3173
PaUtil_AdvanceRingBufferWriteIndex( &blockingState->writeRingBuffer, blockingState->writeRingBufferInitialFrames );
3146
PaUtil_AdvanceRingBufferWriteIndex (&blockingState->writeRingBuffer, blockingState->writeRingBufferInitialFrames);
3176
3149
/* Clear requested frames / buffers count. */
3269
3236
length is longer than the asio buffer size then that should
3270
3237
be taken into account.
3272
if( WaitForSingleObject( stream->completedBuffersPlayedEvent,
3273
(DWORD)(stream->streamRepresentation.streamInfo.outputLatency * 1000. * 4.) )
3276
PA_DEBUG(("WaitForSingleObject() timed out in StopStream()\n" ));
3239
if (WaitForSingleObject (stream->completedBuffersPlayedEvent,
3240
(DWORD) (stream->streamRepresentation.streamInfo.outputLatency * 1000. * 4.))
3242
PA_DEBUG ( ("WaitForSingleObject() timed out in StopStream()\n"));
3280
3246
asioError = ASIOStop();
3281
if( asioError == ASE_OK )
3283
EnsureCallbackHasCompleted( stream );
3248
if (asioError == ASE_OK) {
3249
EnsureCallbackHasCompleted (stream);
3287
3251
result = paUnanticipatedHostError;
3288
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
3252
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
3291
3255
stream->isStopped = 1;
3292
3256
stream->isActive = 0;
3294
if( !stream->streamFinishedCallbackCalled )
3296
if( stream->streamRepresentation.streamFinishedCallback != 0 )
3297
stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
3258
if (!stream->streamFinishedCallbackCalled) {
3259
if (stream->streamRepresentation.streamFinishedCallback != 0)
3260
stream->streamRepresentation.streamFinishedCallback (stream->streamRepresentation.userData);
3303
static PaError AbortStream( PaStream *s )
3266
static PaError AbortStream (PaStream *s)
3305
3268
PaError result = paNoError;
3306
PaAsioStream *stream = (PaAsioStream*)s;
3269
PaAsioStream *stream = (PaAsioStream*) s;
3307
3270
ASIOError asioError;
3309
3272
stream->zeroOutput = true;
3311
3274
asioError = ASIOStop();
3312
if( asioError == ASE_OK )
3314
EnsureCallbackHasCompleted( stream );
3276
if (asioError == ASE_OK) {
3277
EnsureCallbackHasCompleted (stream);
3318
3279
result = paUnanticipatedHostError;
3319
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
3280
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
3322
3283
stream->isStopped = 1;
3323
3284
stream->isActive = 0;
3325
if( !stream->streamFinishedCallbackCalled )
3327
if( stream->streamRepresentation.streamFinishedCallback != 0 )
3328
stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
3286
if (!stream->streamFinishedCallbackCalled) {
3287
if (stream->streamRepresentation.streamFinishedCallback != 0)
3288
stream->streamRepresentation.streamFinishedCallback (stream->streamRepresentation.userData);
3335
static PaError IsStreamStopped( PaStream *s )
3295
static PaError IsStreamStopped (PaStream *s)
3337
PaAsioStream *stream = (PaAsioStream*)s;
3297
PaAsioStream *stream = (PaAsioStream*) s;
3339
3299
return stream->isStopped;
3343
static PaError IsStreamActive( PaStream *s )
3303
static PaError IsStreamActive (PaStream *s)
3345
PaAsioStream *stream = (PaAsioStream*)s;
3305
PaAsioStream *stream = (PaAsioStream*) s;
3347
3307
return stream->isActive;
3351
static PaTime GetStreamTime( PaStream *s )
3311
static PaTime GetStreamTime (PaStream *s)
3353
3313
(void) s; /* unused parameter */
3354
return (double)timeGetTime() * .001;
3314
return (double) timeGetTime() * .001;
3358
static double GetStreamCpuLoad( PaStream* s )
3318
static double GetStreamCpuLoad (PaStream* s)
3360
PaAsioStream *stream = (PaAsioStream*)s;
3320
PaAsioStream *stream = (PaAsioStream*) s;
3362
return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
3322
return PaUtil_GetCpuLoad (&stream->cpuLoadMeasurer);
3485
3442
segment is returned. Otherwise, i.e. if the first segment
3486
3443
is large enough, the second segment's pointer will be NULL.
3488
PaUtil_GetRingBufferReadRegions(pRb ,
3490
&pRingBufferData1st,
3491
&lRingBufferSize1st,
3492
&pRingBufferData2nd,
3493
&lRingBufferSize2nd);
3445
PaUtil_GetRingBufferReadRegions (pRb ,
3447
&pRingBufferData1st,
3448
&lRingBufferSize1st,
3449
&pRingBufferData2nd,
3450
&lRingBufferSize2nd);
3495
3452
/* Set number of frames to be copied from the ring buffer. */
3496
PaUtil_SetInputFrameCount( pBp, lRingBufferSize1st );
3453
PaUtil_SetInputFrameCount (pBp, lRingBufferSize1st);
3497
3454
/* Setup ring buffer access. */
3498
PaUtil_SetInterleavedInputChannels(pBp , /* Buffer processor. */
3499
0 , /* The first channel's index. */
3500
pRingBufferData1st, /* First ring buffer segment. */
3501
0 ); /* Use all available channels. */
3455
PaUtil_SetInterleavedInputChannels (pBp , /* Buffer processor. */
3456
0 , /* The first channel's index. */
3457
pRingBufferData1st, /* First ring buffer segment. */
3458
0); /* Use all available channels. */
3503
3460
/* If a second ring buffer segment is required. */
3504
if( lRingBufferSize2nd ) {
3461
if (lRingBufferSize2nd) {
3505
3462
/* Set number of frames to be copied from the ring buffer. */
3506
PaUtil_Set2ndInputFrameCount( pBp, lRingBufferSize2nd );
3463
PaUtil_Set2ndInputFrameCount (pBp, lRingBufferSize2nd);
3507
3464
/* Setup ring buffer access. */
3508
PaUtil_Set2ndInterleavedInputChannels(pBp , /* Buffer processor. */
3509
0 , /* The first channel's index. */
3510
pRingBufferData2nd, /* Second ring buffer segment. */
3511
0 ); /* Use all available channels. */
3465
PaUtil_Set2ndInterleavedInputChannels (pBp , /* Buffer processor. */
3466
0 , /* The first channel's index. */
3467
pRingBufferData2nd, /* Second ring buffer segment. */
3468
0); /* Use all available channels. */
3514
3471
/* Let the buffer processor handle "copy and conversion" and
3515
3472
update the ring buffer indices manually. */
3516
lFramesCopied = PaUtil_CopyInput( pBp, &buffer, lFramesPerBlock );
3517
PaUtil_AdvanceRingBufferReadIndex( pRb, lFramesCopied );
3473
lFramesCopied = PaUtil_CopyInput (pBp, &buffer, lFramesPerBlock);
3474
PaUtil_AdvanceRingBufferReadIndex (pRb, lFramesCopied);
3519
3476
/* Decrease number of unprocessed frames. */
3520
3477
lFramesRemaining -= lFramesCopied;
3522
3479
} /* Continue with the next data chunk. */
3523
while( lFramesRemaining );
3481
while (lFramesRemaining);
3526
3484
/* If there has been an input overflow within the callback */
3527
if( blockingState->inputOverflowFlag )
3485
if (blockingState->inputOverflowFlag) {
3529
3486
blockingState->inputOverflowFlag = FALSE;
3531
3488
/* Return the corresponding error code. */
3657
3611
segment is returned. Otherwise, i.e. if the first segment
3658
3612
is large enough, the second segment's pointer will be NULL.
3660
PaUtil_GetRingBufferWriteRegions(pRb ,
3662
&pRingBufferData1st,
3663
&lRingBufferSize1st,
3664
&pRingBufferData2nd,
3665
&lRingBufferSize2nd);
3614
PaUtil_GetRingBufferWriteRegions (pRb ,
3616
&pRingBufferData1st,
3617
&lRingBufferSize1st,
3618
&pRingBufferData2nd,
3619
&lRingBufferSize2nd);
3667
3621
/* Set number of frames to be copied to the ring buffer. */
3668
PaUtil_SetOutputFrameCount( pBp, lRingBufferSize1st );
3622
PaUtil_SetOutputFrameCount (pBp, lRingBufferSize1st);
3669
3623
/* Setup ring buffer access. */
3670
PaUtil_SetInterleavedOutputChannels(pBp , /* Buffer processor. */
3671
0 , /* The first channel's index. */
3672
pRingBufferData1st, /* First ring buffer segment. */
3673
0 ); /* Use all available channels. */
3624
PaUtil_SetInterleavedOutputChannels (pBp , /* Buffer processor. */
3625
0 , /* The first channel's index. */
3626
pRingBufferData1st, /* First ring buffer segment. */
3627
0); /* Use all available channels. */
3675
3629
/* If a second ring buffer segment is required. */
3676
if( lRingBufferSize2nd ) {
3630
if (lRingBufferSize2nd) {
3677
3631
/* Set number of frames to be copied to the ring buffer. */
3678
PaUtil_Set2ndOutputFrameCount( pBp, lRingBufferSize2nd );
3632
PaUtil_Set2ndOutputFrameCount (pBp, lRingBufferSize2nd);
3679
3633
/* Setup ring buffer access. */
3680
PaUtil_Set2ndInterleavedOutputChannels(pBp , /* Buffer processor. */
3681
0 , /* The first channel's index. */
3682
pRingBufferData2nd, /* Second ring buffer segment. */
3683
0 ); /* Use all available channels. */
3634
PaUtil_Set2ndInterleavedOutputChannels (pBp , /* Buffer processor. */
3635
0 , /* The first channel's index. */
3636
pRingBufferData2nd, /* Second ring buffer segment. */
3637
0); /* Use all available channels. */
3686
3640
/* Let the buffer processor handle "copy and conversion" and
3687
3641
update the ring buffer indices manually. */
3688
lFramesCopied = PaUtil_CopyOutput( pBp, &userBuffer, lFramesPerBlock );
3689
PaUtil_AdvanceRingBufferWriteIndex( pRb, lFramesCopied );
3642
lFramesCopied = PaUtil_CopyOutput (pBp, &userBuffer, lFramesPerBlock);
3643
PaUtil_AdvanceRingBufferWriteIndex (pRb, lFramesCopied);
3691
3645
/* Decrease number of unprocessed frames. */
3692
3646
lFramesRemaining -= lFramesCopied;
3694
3648
} /* Continue with the next data chunk. */
3695
while( lFramesRemaining );
3650
while (lFramesRemaining);
3698
3653
/* If there has been an output underflow within the callback */
3699
if( blockingState->outputUnderflowFlag )
3654
if (blockingState->outputUnderflowFlag) {
3701
3655
blockingState->outputUnderflowFlag = FALSE;
3703
3657
/* Return the corresponding error code. */
3872
3818
done safely while a stream is open.
3875
asioHostApi = (PaAsioHostApiRepresentation*)hostApi;
3876
if( asioHostApi->openAsioDeviceIndex != paNoDevice )
3821
asioHostApi = (PaAsioHostApiRepresentation*) hostApi;
3823
if (asioHostApi->openAsioDeviceIndex != paNoDevice) {
3878
3824
result = paDeviceUnavailable;
3882
asioDeviceInfo = (PaAsioDeviceInfo*)hostApi->deviceInfos[hostApiDevice];
3828
asioDeviceInfo = (PaAsioDeviceInfo*) hostApi->deviceInfos[hostApiDevice];
3884
3830
/* See notes about CoInitialize(0) in LoadAsioDriver(). */
3887
if( !asioHostApi->asioDrivers->loadDriver( const_cast<char*>(asioDeviceInfo->commonDeviceInfo.name) ) )
3833
if (!asioHostApi->asioDrivers->loadDriver (const_cast<char*> (asioDeviceInfo->commonDeviceInfo.name))) {
3889
3834
result = paUnanticipatedHostError;
3893
3838
/* CRUCIAL!!! */
3894
memset( &asioDriverInfo, 0, sizeof(ASIODriverInfo) );
3839
memset (&asioDriverInfo, 0, sizeof (ASIODriverInfo));
3895
3840
asioDriverInfo.asioVersion = 2;
3896
3841
asioDriverInfo.sysRef = systemSpecific;
3897
asioError = ASIOInit( &asioDriverInfo );
3898
if( asioError != ASE_OK )
3842
asioError = ASIOInit (&asioDriverInfo);
3844
if (asioError != ASE_OK) {
3900
3845
result = paUnanticipatedHostError;
3901
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
3846
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
3906
3849
asioIsInitialized = 1;
3909
PA_DEBUG(("PaAsio_ShowControlPanel: ASIOInit(): %s\n", PaAsio_GetAsioErrorText(asioError) ));
3910
PA_DEBUG(("asioVersion: ASIOInit(): %ld\n", asioDriverInfo.asioVersion ));
3911
PA_DEBUG(("driverVersion: ASIOInit(): %ld\n", asioDriverInfo.driverVersion ));
3912
PA_DEBUG(("Name: ASIOInit(): %s\n", asioDriverInfo.name ));
3913
PA_DEBUG(("ErrorMessage: ASIOInit(): %s\n", asioDriverInfo.errorMessage ));
3852
PA_DEBUG ( ("PaAsio_ShowControlPanel: ASIOInit(): %s\n", PaAsio_GetAsioErrorText (asioError)));
3853
PA_DEBUG ( ("asioVersion: ASIOInit(): %ld\n", asioDriverInfo.asioVersion));
3854
PA_DEBUG ( ("driverVersion: ASIOInit(): %ld\n", asioDriverInfo.driverVersion));
3855
PA_DEBUG ( ("Name: ASIOInit(): %s\n", asioDriverInfo.name));
3856
PA_DEBUG ( ("ErrorMessage: ASIOInit(): %s\n", asioDriverInfo.errorMessage));
3915
3858
asioError = ASIOControlPanel();
3916
if( asioError != ASE_OK )
3918
PA_DEBUG(("PaAsio_ShowControlPanel: ASIOControlPanel(): %s\n", PaAsio_GetAsioErrorText(asioError) ));
3860
if (asioError != ASE_OK) {
3861
PA_DEBUG ( ("PaAsio_ShowControlPanel: ASIOControlPanel(): %s\n", PaAsio_GetAsioErrorText (asioError)));
3919
3862
result = paUnanticipatedHostError;
3920
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
3863
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
3924
PA_DEBUG(("PaAsio_ShowControlPanel: ASIOControlPanel(): %s\n", PaAsio_GetAsioErrorText(asioError) ));
3867
PA_DEBUG ( ("PaAsio_ShowControlPanel: ASIOControlPanel(): %s\n", PaAsio_GetAsioErrorText (asioError)));
3926
3869
asioError = ASIOExit();
3927
if( asioError != ASE_OK )
3871
if (asioError != ASE_OK) {
3929
3872
result = paUnanticipatedHostError;
3930
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
3873
PA_ASIO_SET_LAST_ASIO_ERROR (asioError);
3931
3874
asioIsInitialized = 0;
3936
PA_DEBUG(("PaAsio_ShowControlPanel: ASIOExit(): %s\n", PaAsio_GetAsioErrorText(asioError) ));
3879
PA_DEBUG ( ("PaAsio_ShowControlPanel: ASIOExit(): %s\n", PaAsio_GetAsioErrorText (asioError)));
3941
if( asioIsInitialized )
3885
if (asioIsInitialized) {
3951
PaError PaAsio_GetInputChannelName( PaDeviceIndex device, int channelIndex,
3952
const char** channelName )
3895
PaError PaAsio_GetInputChannelName (PaDeviceIndex device, int channelIndex,
3896
const char** channelName)
3954
3898
PaError result = paNoError;
3955
3899
PaUtilHostApiRepresentation *hostApi;