69 const unsigned int RtAudio :: SAMPLE_RATES[] = {
70 4000, 5512, 8000, 9600, 11025, 16000, 22050,
71 32000, 44100, 48000, 88200, 96000, 176400, 192000
80 #if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)
81 #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A)
82 #define MUTEX_LOCK(A) EnterCriticalSection(A)
83 #define MUTEX_UNLOCK(A) LeaveCriticalSection(A)
85 #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL)
86 #define MUTEX_LOCK(A) pthread_mutex_lock(A)
87 #define MUTEX_UNLOCK(A) pthread_mutex_unlock(A)
101 sprintf(message,
"RtAudio: no audio devices found!");
107 int outputDevice,
int outputChannels,
108 int inputDevice,
int inputChannels,
110 int *bufferSize,
int numberOfBuffers)
115 sprintf(message,
"RtAudio: no audio devices found!");
120 *streamId =
openStream(outputDevice, outputChannels, inputDevice, inputChannels,
121 format, sampleRate, bufferSize, numberOfBuffers);
125 if (devices) free(devices);
133 while ( streams.size() )
137 if (devices) free(devices);
141 int inputDevice,
int inputChannels,
143 int *bufferSize,
int numberOfBuffers)
145 static int streamKey = 0;
147 if (outputChannels < 1 && inputChannels < 1) {
148 sprintf(message,
"RtAudio: one or both 'channel' parameters must be greater than zero.");
152 if ( formatBytes(format) == 0 ) {
153 sprintf(message,
"RtAudio: 'format' parameter value is undefined.");
157 if ( outputChannels > 0 ) {
158 if (outputDevice > nDevices || outputDevice < 0) {
159 sprintf(message,
"RtAudio: 'outputDevice' parameter value (%d) is invalid.", outputDevice);
164 if ( inputChannels > 0 ) {
165 if (inputDevice > nDevices || inputDevice < 0) {
166 sprintf(message,
"RtAudio: 'inputDevice' parameter value (%d) is invalid.", inputDevice);
172 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) calloc(1,
sizeof(RTAUDIO_STREAM));
173 if (stream ==
NULL) {
174 sprintf(message,
"RtAudio: memory allocation error!");
177 stream->mode = UNINITIALIZED;
180 bool result = FAILURE;
181 int device, defaultDevice = 0;
184 if ( outputChannels > 0 ) {
187 channels = outputChannels;
189 if ( outputDevice == 0 ) {
190 defaultDevice = getDefaultOutputDevice();
191 device = defaultDevice;
194 device = outputDevice - 1;
196 for (
int i=-1; i<nDevices; i++) {
198 if ( i == defaultDevice )
continue;
201 if (devices[device].probed ==
false) {
204 clearDeviceInfo(&devices[device]);
205 probeDeviceInfo(&devices[device]);
207 if ( devices[device].probed )
208 result = probeDeviceOpen(device, stream, mode, channels, sampleRate,
209 format, bufferSize, numberOfBuffers);
210 if (result == SUCCESS)
break;
211 if ( outputDevice > 0 )
break;
215 if ( inputChannels > 0 && ( result == SUCCESS || outputChannels <= 0 ) ) {
218 channels = inputChannels;
220 if ( inputDevice == 0 ) {
221 defaultDevice = getDefaultInputDevice();
222 device = defaultDevice;
225 device = inputDevice - 1;
227 for (
int i=-1; i<nDevices; i++) {
229 if ( i == defaultDevice )
continue;
232 if (devices[device].probed ==
false) {
235 clearDeviceInfo(&devices[device]);
236 probeDeviceInfo(&devices[device]);
238 if ( devices[device].probed )
239 result = probeDeviceOpen(device, stream, mode, channels, sampleRate,
240 format, bufferSize, numberOfBuffers);
241 if (result == SUCCESS)
break;
242 if ( outputDevice > 0 )
break;
246 streams[++streamKey] = (
void *) stream;
247 if ( result == SUCCESS )
253 if ( ( outputDevice == 0 && outputChannels > 0 )
254 || ( inputDevice == 0 && inputChannels > 0 ) )
255 sprintf(message,
"RtAudio: no devices found for given parameters.");
257 sprintf(message,
"RtAudio: unable to open specified device(s) with given stream parameters.");
270 if (device > nDevices || device < 1) {
271 sprintf(message,
"RtAudio: invalid device specifier (%d)!", device);
275 int deviceIndex = device - 1;
278 if (devices[deviceIndex].probed ==
false) {
279 clearDeviceInfo(&devices[deviceIndex]);
280 probeDeviceInfo(&devices[deviceIndex]);
286 strncpy(info->
name, devices[deviceIndex].
name, 128);
288 if ( info->
probed ==
true ) {
306 if ( deviceIndex == getDefaultOutputDevice() ||
307 deviceIndex == getDefaultInputDevice() )
316 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
318 return stream->userBuffer;
321 #if defined(__LINUX_ALSA__) || defined(__LINUX_OSS__) || defined(__IRIX_AL__)
323 extern "C" void *callbackHandler(
void * ptr);
327 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
331 sprintf(message,
"RtAudio: A callback is already set for this stream!");
339 info->
object = (
void *)
this;
342 int err = pthread_create(&info->
thread,
NULL, callbackHandler, &stream->callbackInfo);
346 sprintf(message,
"RtAudio: error starting callback thread!");
353 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
355 if (stream->callbackInfo.usingCallback) {
357 if (stream->state == STREAM_RUNNING)
362 stream->callbackInfo.usingCallback =
false;
363 pthread_cancel(stream->callbackInfo.thread);
364 pthread_join(stream->callbackInfo.thread,
NULL);
365 stream->callbackInfo.thread = 0;
366 stream->callbackInfo.callback =
NULL;
367 stream->callbackInfo.userData =
NULL;
381 #if defined(__MACOSX_CORE__)
406 void RtAudio :: initialize(
void)
408 OSStatus err = noErr;
410 AudioDeviceID *deviceList =
NULL;
414 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &dataSize,
NULL);
416 sprintf(message,
"RtAudio: OSX error getting device info!");
420 nDevices = dataSize /
sizeof(AudioDeviceID);
421 if (nDevices == 0)
return;
424 devices = (RTAUDIO_DEVICE *) calloc(nDevices,
sizeof(RTAUDIO_DEVICE));
425 if (devices ==
NULL) {
426 sprintf(message,
"RtAudio: memory allocation error!");
431 deviceList = (AudioDeviceID *) malloc( dataSize );
432 if (deviceList ==
NULL) {
433 sprintf(message,
"RtAudio: memory allocation error!");
438 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &dataSize, (
void *) deviceList);
441 sprintf(message,
"RtAudio: OSX error getting device properties!");
447 for (
int i=0; i<nDevices; i++) {
448 devices[i].
id[0] = deviceList[i];
455 int RtAudio :: getDefaultInputDevice(
void)
458 UInt32 dataSize =
sizeof( AudioDeviceID );
460 OSStatus result = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultInputDevice,
463 if (result != noErr) {
464 sprintf( message,
"RtAudio: OSX error getting default input device." );
469 for (
int i=0; i<nDevices; i++ ) {
470 if (
id == devices[i].
id[0] )
return i;
476 int RtAudio :: getDefaultOutputDevice(
void)
479 UInt32 dataSize =
sizeof( AudioDeviceID );
481 OSStatus result = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice,
484 if (result != noErr) {
485 sprintf( message,
"RtAudio: OSX error getting default output device." );
490 for (
int i=0; i<nDevices; i++ ) {
491 if (
id == devices[i].
id[0] )
return i;
497 static bool deviceSupportsFormat( AudioDeviceID
id,
bool isInput,
498 AudioStreamBasicDescription *desc,
bool isDuplex )
500 OSStatus result = noErr;
501 UInt32 dataSize =
sizeof( AudioStreamBasicDescription );
503 result = AudioDeviceGetProperty(
id, 0, isInput,
504 kAudioDevicePropertyStreamFormatSupported,
507 if (result == kAudioHardwareNoError) {
509 result = AudioDeviceGetProperty(
id, 0,
true,
510 kAudioDevicePropertyStreamFormatSupported,
514 if (result != kAudioHardwareNoError)
523 void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
525 OSStatus err = noErr;
530 UInt32 dataSize = 256;
531 err = AudioDeviceGetProperty( info->id[0], 0,
false,
532 kAudioDevicePropertyDeviceManufacturer,
535 sprintf( message,
"RtAudio: OSX error getting device manufacturer." );
539 strncpy(fullname, name, 256);
540 strcat(fullname,
": " );
543 err = AudioDeviceGetProperty( info->id[0], 0,
false,
544 kAudioDevicePropertyDeviceName,
547 sprintf( message,
"RtAudio: OSX error getting device name." );
551 strncat(fullname, name, 254);
552 strncat(info->name, fullname, 128);
555 unsigned int i, minChannels, maxChannels, nStreams = 0;
556 AudioBufferList *bufferList = nil;
557 err = AudioDeviceGetPropertyInfo( info->id[0], 0,
false,
558 kAudioDevicePropertyStreamConfiguration,
560 if (err == noErr && dataSize > 0) {
561 bufferList = (AudioBufferList *) malloc( dataSize );
562 if (bufferList ==
NULL) {
563 sprintf(message,
"RtAudio: memory allocation error!");
568 err = AudioDeviceGetProperty( info->id[0], 0,
false,
569 kAudioDevicePropertyStreamConfiguration,
570 &dataSize, bufferList );
574 nStreams = bufferList->mNumberBuffers;
575 for ( i=0; i<nStreams; i++ ) {
576 maxChannels += bufferList->mBuffers[i].mNumberChannels;
577 if ( bufferList->mBuffers[i].mNumberChannels < minChannels )
578 minChannels = bufferList->mBuffers[i].mNumberChannels;
582 if (err != noErr || dataSize <= 0) {
583 sprintf( message,
"RtAudio: OSX error getting output channels for device (%s).", info->name );
590 if ( maxChannels > 0 )
591 info->maxOutputChannels = maxChannels;
592 if ( minChannels > 0 )
593 info->minOutputChannels = minChannels;
598 err = AudioDeviceGetPropertyInfo( info->id[0], 0,
true,
599 kAudioDevicePropertyStreamConfiguration,
601 if (err == noErr && dataSize > 0) {
602 bufferList = (AudioBufferList *) malloc( dataSize );
603 if (bufferList ==
NULL) {
604 sprintf(message,
"RtAudio: memory allocation error!");
608 err = AudioDeviceGetProperty( info->id[0], 0,
true,
609 kAudioDevicePropertyStreamConfiguration,
610 &dataSize, bufferList );
614 nStreams = bufferList->mNumberBuffers;
615 for ( i=0; i<nStreams; i++ ) {
616 if ( bufferList->mBuffers[i].mNumberChannels < minChannels )
617 minChannels = bufferList->mBuffers[i].mNumberChannels;
618 maxChannels += bufferList->mBuffers[i].mNumberChannels;
622 if (err != noErr || dataSize <= 0) {
623 sprintf( message,
"RtAudio: OSX error getting input channels for device (%s).", info->name );
630 if ( maxChannels > 0 )
631 info->maxInputChannels = maxChannels;
632 if ( minChannels > 0 )
633 info->minInputChannels = minChannels;
637 if (info->maxOutputChannels > 0 && info->maxInputChannels > 0) {
638 info->hasDuplexSupport =
true;
639 info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ?
640 info->maxInputChannels : info->maxOutputChannels;
641 info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ?
642 info->minInputChannels : info->minOutputChannels;
651 AudioStreamBasicDescription description;
652 dataSize =
sizeof( AudioStreamBasicDescription );
653 memset(&description, 0,
sizeof(AudioStreamBasicDescription));
654 bool isInput =
false;
655 if ( info->maxOutputChannels == 0 ) isInput =
true;
656 bool isDuplex =
false;
657 if ( info->maxDuplexChannels > 0 ) isDuplex =
true;
660 info->nSampleRates = 0;
662 description.mSampleRate = (double) SAMPLE_RATES[i];
663 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
664 info->sampleRates[info->nSampleRates++] = SAMPLE_RATES[i];
667 if (info->nSampleRates == 0) {
668 sprintf( message,
"RtAudio: No supported sample rates found for OSX device (%s).", info->name );
674 description.mSampleRate = kAudioStreamAnyRate;
675 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) ) {
676 info->sampleRates[1] = info->sampleRates[info->nSampleRates-1];
677 info->nSampleRates = -1;
681 info->nativeFormats = 0;
682 description.mFormatID = kAudioFormatLinearPCM;
683 description.mBitsPerChannel = 8;
684 description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsBigEndian;
685 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
688 description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
689 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
693 description.mBitsPerChannel = 16;
694 description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
695 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
698 description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
699 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
703 description.mBitsPerChannel = 32;
704 description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
705 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
708 description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
709 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
713 description.mBitsPerChannel = 24;
714 description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsAlignedHigh | kLinearPCMFormatFlagIsBigEndian;
715 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
718 description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
719 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
723 description.mBitsPerChannel = 32;
724 description.mFormatFlags = kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsBigEndian;
725 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
728 description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
729 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
733 description.mBitsPerChannel = 64;
734 description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
735 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
738 description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
739 if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
744 if (info->nativeFormats == 0) {
745 sprintf(message,
"RtAudio: OSX PCM device (%s) data format not supported by RtAudio.",
754 OSStatus callbackHandler(AudioDeviceID inDevice,
755 const AudioTimeStamp* inNow,
756 const AudioBufferList* inInputData,
757 const AudioTimeStamp* inInputTime,
758 AudioBufferList* outOutputData,
759 const AudioTimeStamp* inOutputTime,
766 object->callbackEvent( info->
streamId, inDevice, (
void *)inInputData, (
void *)outOutputData );
769 fprintf(stderr,
"\nCallback handler error (%s)!\n\n", exception.
getMessage());
770 return kAudioHardwareUnspecifiedError;
773 return kAudioHardwareNoError;
798 bool RtAudio :: probeDeviceOpen(
int device, RTAUDIO_STREAM *stream,
799 STREAM_MODE mode,
int channels,
800 int sampleRate, RTAUDIO_FORMAT format,
801 int *bufferSize,
int numberOfBuffers)
804 RTAUDIO_STREAM *streamPtr;
805 std::map<int, void *>::const_iterator i;
806 for ( i=streams.begin(); i!=streams.end(); ++i ) {
807 streamPtr = (RTAUDIO_STREAM *) i->second;
808 if ( streamPtr->device[0] == device || streamPtr->device[1] == device ) {
809 sprintf(message,
"RtAudio: no current OS X support for multiple streams accessing the same device!");
816 bool isInput =
false;
817 AudioDeviceID
id = devices[device].
id[0];
818 if ( mode == INPUT ) isInput =
true;
821 OSStatus err = noErr;
823 unsigned int deviceChannels, nStreams;
824 UInt32 iChannel = 0, iStream = 0;
825 AudioBufferList *bufferList = nil;
826 err = AudioDeviceGetPropertyInfo(
id, 0, isInput,
827 kAudioDevicePropertyStreamConfiguration,
830 if (err == noErr && dataSize > 0) {
831 bufferList = (AudioBufferList *) malloc( dataSize );
832 if (bufferList ==
NULL) {
833 sprintf(message,
"RtAudio: memory allocation error!");
837 err = AudioDeviceGetProperty(
id, 0, isInput,
838 kAudioDevicePropertyStreamConfiguration,
839 &dataSize, bufferList );
842 stream->deInterleave[mode] =
false;
843 nStreams = bufferList->mNumberBuffers;
844 for ( iStream=0; iStream<nStreams; iStream++ ) {
845 if ( bufferList->mBuffers[iStream].mNumberChannels >= (
unsigned int) channels )
break;
846 iChannel += bufferList->mBuffers[iStream].mNumberChannels;
854 if ( iStream >= nStreams && nStreams >= (
unsigned int) channels ) {
856 for ( iStream=0; iStream<nStreams; iStream++ ) {
857 if ( bufferList->mBuffers[iStream].mNumberChannels == 1 )
861 if ( counter == channels ) {
862 iStream -= channels - 1;
863 iChannel -= channels - 1;
864 stream->deInterleave[mode] =
true;
867 iChannel += bufferList->mBuffers[iStream].mNumberChannels;
872 if (err != noErr || dataSize <= 0) {
873 if ( bufferList ) free( bufferList );
874 sprintf( message,
"RtAudio: OSX error getting channels for device (%s).", devices[device].name );
879 if (iStream >= nStreams) {
881 sprintf( message,
"RtAudio: unable to find OSX audio stream on device (%s) for requested channels (%d).",
882 devices[device].name, channels );
888 deviceChannels = bufferList->mBuffers[iStream].mNumberChannels;
892 AudioValueRange bufferRange;
893 dataSize =
sizeof(AudioValueRange);
894 err = AudioDeviceGetProperty(
id, 0, isInput,
895 kAudioDevicePropertyBufferSizeRange,
896 &dataSize, &bufferRange);
898 sprintf( message,
"RtAudio: OSX error getting buffer size range for device (%s).",
899 devices[device].name );
904 long bufferBytes = *bufferSize * deviceChannels * formatBytes(
RTAUDIO_FLOAT32);
905 if (bufferRange.mMinimum > bufferBytes) bufferBytes = (int) bufferRange.mMinimum;
906 else if (bufferRange.mMaximum < bufferBytes) bufferBytes = (int) bufferRange.mMaximum;
910 UInt32 theSize = (UInt32) bufferBytes;
911 dataSize =
sizeof( UInt32);
912 err = AudioDeviceSetProperty(
id,
NULL, 0, isInput,
913 kAudioDevicePropertyBufferSize,
916 sprintf( message,
"RtAudio: OSX error setting the buffer size for device (%s).",
917 devices[device].name );
924 *bufferSize = bufferBytes / ( deviceChannels * formatBytes(
RTAUDIO_FLOAT32) );
925 if ( stream->mode == OUTPUT && mode == INPUT && *bufferSize != stream->bufferSize ) {
926 sprintf( message,
"RtAudio: OSX error setting buffer size for duplex stream on device (%s).",
927 devices[device].name );
932 stream->bufferSize = *bufferSize;
933 stream->nBuffers = 1;
936 AudioStreamBasicDescription description;
937 dataSize =
sizeof( AudioStreamBasicDescription );
938 if ( stream->deInterleave[mode] ) nStreams = channels;
940 for (
unsigned int i=0; i<nStreams; i++, iChannel++ ) {
942 err = AudioDeviceGetProperty(
id, iChannel, isInput,
943 kAudioDevicePropertyStreamFormat,
944 &dataSize, &description );
946 sprintf( message,
"RtAudio: OSX error getting stream format for device (%s).", devices[device].name );
952 description.mSampleRate = (double) sampleRate;
953 description.mFormatID = kAudioFormatLinearPCM;
954 err = AudioDeviceSetProperty(
id,
NULL, iChannel, isInput,
955 kAudioDevicePropertyStreamFormat,
956 dataSize, &description );
958 sprintf( message,
"RtAudio: OSX error setting sample rate or data format for device (%s).", devices[device].name );
965 iChannel -= nStreams;
966 err = AudioDeviceGetProperty(
id, iChannel, isInput,
967 kAudioDevicePropertyStreamFormat,
968 &dataSize, &description );
970 sprintf( message,
"RtAudio: OSX error getting stream format for device (%s).", devices[device].name );
975 stream->doByteSwap[mode] =
false;
976 if ( !description.mFormatFlags & kLinearPCMFormatFlagIsBigEndian )
977 stream->doByteSwap[mode] =
true;
981 stream->userFormat = format;
984 if ( stream->deInterleave[mode] )
985 stream->nDeviceChannels[mode] = channels;
987 stream->nDeviceChannels[mode] = description.mChannelsPerFrame;
988 stream->nUserChannels[mode] = channels;
991 stream->handle[mode] = iStream;
992 stream->doConvertBuffer[mode] =
false;
993 if (stream->userFormat != stream->deviceFormat[mode])
994 stream->doConvertBuffer[mode] =
true;
995 if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
996 stream->doConvertBuffer[mode] =
true;
997 if (stream->nUserChannels[mode] > 1 && stream->deInterleave[mode])
998 stream->doConvertBuffer[mode] =
true;
1001 if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
1004 if (stream->nUserChannels[0] >= stream->nUserChannels[1])
1005 buffer_bytes = stream->nUserChannels[0];
1007 buffer_bytes = stream->nUserChannels[1];
1009 buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
1010 if (stream->userBuffer) free(stream->userBuffer);
1011 stream->userBuffer = (
char *) calloc(buffer_bytes, 1);
1012 if (stream->userBuffer ==
NULL)
1016 if ( stream->deInterleave[mode] ) {
1019 bool makeBuffer =
true;
1020 if ( mode == OUTPUT )
1021 buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
1023 buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
1024 if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
1025 long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
1026 if ( buffer_bytes < bytes_out ) makeBuffer =
false;
1031 buffer_bytes *= *bufferSize;
1032 if (stream->deviceBuffer) free(stream->deviceBuffer);
1033 stream->deviceBuffer = (
char *) calloc(buffer_bytes, 1);
1034 if (stream->deviceBuffer ==
NULL)
1043 stream->callbackInfo.buffers = stream->deviceBuffer;
1047 stream->sampleRate = sampleRate;
1048 stream->device[mode] = device;
1049 stream->state = STREAM_STOPPED;
1050 stream->callbackInfo.object = (
void *)
this;
1051 stream->callbackInfo.waitTime = (
unsigned long) (200000.0 * stream->bufferSize / stream->sampleRate);
1052 stream->callbackInfo.device[mode] = id;
1053 if ( stream->mode == OUTPUT && mode == INPUT && stream->device[0] == device )
1055 stream->mode = DUPLEX;
1057 err = AudioDeviceAddIOProc(
id, callbackHandler, (
void *) &stream->callbackInfo );
1059 sprintf( message,
"RtAudio: OSX error setting callback for device (%s).", devices[device].name );
1063 if ( stream->mode == OUTPUT && mode == INPUT )
1064 stream->mode = DUPLEX;
1066 stream->mode = mode;
1074 if (stream->userBuffer) {
1075 free(stream->userBuffer);
1076 stream->userBuffer = 0;
1078 sprintf(message,
"RtAudio: OSX error allocating buffer memory (%s).", devices[device].name);
1085 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
1087 if (stream->callbackInfo.usingCallback) {
1089 if (stream->state == STREAM_RUNNING)
1094 stream->callbackInfo.usingCallback =
false;
1095 stream->callbackInfo.userData =
NULL;
1096 stream->state = STREAM_STOPPED;
1097 stream->callbackInfo.callback =
NULL;
1108 if ( streams.find( streamId ) == streams.end() ) {
1109 sprintf(message,
"RtAudio: invalid stream identifier!");
1114 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
1117 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
1118 id = devices[stream->device[0]].
id[0];
1119 if (stream->state == STREAM_RUNNING)
1120 AudioDeviceStop(
id, callbackHandler );
1121 AudioDeviceRemoveIOProc(
id, callbackHandler );
1124 if (stream->mode == INPUT || ( stream->mode == DUPLEX && stream->device[0] != stream->device[1]) ) {
1125 id = devices[stream->device[1]].
id[0];
1126 if (stream->state == STREAM_RUNNING)
1127 AudioDeviceStop(
id, callbackHandler );
1128 AudioDeviceRemoveIOProc(
id, callbackHandler );
1131 pthread_mutex_destroy(&stream->mutex);
1133 if (stream->userBuffer)
1134 free(stream->userBuffer);
1136 if ( stream->deInterleave[0] || stream->deInterleave[1] )
1137 free(stream->callbackInfo.buffers);
1140 streams.erase(streamId);
1145 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
1149 if (stream->state == STREAM_RUNNING)
1153 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
1155 err = AudioDeviceStart(devices[stream->device[0]].id[0], callbackHandler);
1157 sprintf(message,
"RtAudio: OSX error starting callback procedure on device (%s).",
1158 devices[stream->device[0]].name);
1164 if (stream->mode == INPUT || ( stream->mode == DUPLEX && stream->device[0] != stream->device[1]) ) {
1166 err = AudioDeviceStart(devices[stream->device[1]].id[0], callbackHandler);
1168 sprintf(message,
"RtAudio: OSX error starting input callback procedure on device (%s).",
1169 devices[stream->device[0]].name);
1175 stream->callbackInfo.streamId = streamId;
1176 stream->state = STREAM_RUNNING;
1177 stream->callbackInfo.blockTick =
true;
1178 stream->callbackInfo.stopStream =
false;
1186 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
1190 if (stream->state == STREAM_STOPPED)
1194 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
1196 err = AudioDeviceStop(devices[stream->device[0]].id[0], callbackHandler);
1198 sprintf(message,
"RtAudio: OSX error stopping callback procedure on device (%s).",
1199 devices[stream->device[0]].name);
1205 if (stream->mode == INPUT || ( stream->mode == DUPLEX && stream->device[0] != stream->device[1]) ) {
1207 err = AudioDeviceStop(devices[stream->device[1]].id[0], callbackHandler);
1209 sprintf(message,
"RtAudio: OSX error stopping input callback procedure on device (%s).",
1210 devices[stream->device[0]].name);
1216 stream->state = STREAM_STOPPED;
1230 sprintf(message,
"RtAudio: streamWillBlock() cannot be implemented for OS X.");
1237 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
1239 if (stream->state == STREAM_STOPPED)
1242 if (stream->callbackInfo.usingCallback) {
1243 sprintf(message,
"RtAudio: tickStream() should not be used when a callback function is set!");
1249 while ( stream->callbackInfo.blockTick )
1250 usleep(stream->callbackInfo.waitTime);
1254 stream->callbackInfo.blockTick =
true;
1259 void RtAudio :: callbackEvent(
int streamId, DEVICE_ID deviceId,
void *inData,
void *outData )
1261 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
1264 AudioBufferList *inBufferList = (AudioBufferList *) inData;
1265 AudioBufferList *outBufferList = (AudioBufferList *) outData;
1267 if (stream->state == STREAM_STOPPED)
return;
1294 if ( stream->mode == OUTPUT || ( stream->mode == DUPLEX && deviceId == info->
device[0] ) ) {
1296 if (stream->doConvertBuffer[0]) {
1298 if ( !stream->deInterleave[0] )
1299 stream->deviceBuffer = (
char *) outBufferList->mBuffers[stream->handle[0]].mData;
1301 stream->deviceBuffer = (
char *) stream->callbackInfo.buffers;
1303 convertStreamBuffer(stream, OUTPUT);
1304 if ( stream->doByteSwap[0] )
1305 byteSwapBuffer(stream->deviceBuffer,
1306 stream->bufferSize * stream->nDeviceChannels[0],
1307 stream->deviceFormat[0]);
1309 if ( stream->deInterleave[0] ) {
1310 int bufferBytes = outBufferList->mBuffers[stream->handle[0]].mDataByteSize;
1311 for (
int i=0; i<stream->nDeviceChannels[0]; i++ ) {
1312 memcpy(outBufferList->mBuffers[stream->handle[0]+i].mData,
1313 &stream->deviceBuffer[i*bufferBytes], bufferBytes );
1319 if (stream->doByteSwap[0])
1320 byteSwapBuffer(stream->userBuffer,
1321 stream->bufferSize * stream->nUserChannels[0],
1322 stream->userFormat);
1324 memcpy(outBufferList->mBuffers[stream->handle[0]].mData,
1326 outBufferList->mBuffers[stream->handle[0]].mDataByteSize );
1330 if ( stream->mode == INPUT || ( stream->mode == DUPLEX && deviceId == info->
device[1] ) ) {
1332 if (stream->doConvertBuffer[1]) {
1334 if ( stream->deInterleave[1] ) {
1335 stream->deviceBuffer = (
char *) stream->callbackInfo.buffers;
1336 int bufferBytes = inBufferList->mBuffers[stream->handle[1]].mDataByteSize;
1337 for (
int i=0; i<stream->nDeviceChannels[1]; i++ ) {
1338 memcpy(&stream->deviceBuffer[i*bufferBytes],
1339 inBufferList->mBuffers[stream->handle[1]+i].mData, bufferBytes );
1343 stream->deviceBuffer = (
char *) inBufferList->mBuffers[stream->handle[1]].mData;
1345 if ( stream->doByteSwap[1] )
1346 byteSwapBuffer(stream->deviceBuffer,
1347 stream->bufferSize * stream->nDeviceChannels[1],
1348 stream->deviceFormat[1]);
1349 convertStreamBuffer(stream, INPUT);
1353 memcpy(stream->userBuffer,
1354 inBufferList->mBuffers[stream->handle[1]].mData,
1355 inBufferList->mBuffers[stream->handle[1]].mDataByteSize );
1357 if (stream->doByteSwap[1])
1358 byteSwapBuffer(stream->userBuffer,
1359 stream->bufferSize * stream->nUserChannels[1],
1360 stream->userFormat);
1373 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
1375 stream->callbackInfo.callback = (
void *) callback;
1376 stream->callbackInfo.userData = userData;
1377 stream->callbackInfo.usingCallback =
true;
1382 #elif defined(__LINUX_ALSA__)
1384 #define MAX_DEVICES 16
1386 void RtAudio :: initialize(
void)
1388 int card, result, device;
1391 char deviceNames[MAX_DEVICES][32];
1393 snd_ctl_card_info_t *info;
1394 snd_ctl_card_info_alloca(&info);
1399 snd_card_next(&card);
1400 while ( card >= 0 ) {
1401 sprintf(name,
"hw:%d", card);
1402 result = snd_ctl_open(&handle, name, 0);
1404 sprintf(message,
"RtAudio: ALSA control open (%i): %s.", card, snd_strerror(result));
1408 result = snd_ctl_card_info(handle, info);
1410 sprintf(message,
"RtAudio: ALSA control hardware info (%i): %s.", card, snd_strerror(result));
1414 cardId = snd_ctl_card_info_get_id(info);
1417 result = snd_ctl_pcm_next_device(handle, &device);
1419 sprintf(message,
"RtAudio: ALSA control next device (%i): %s.", card, snd_strerror(result));
1425 if ( strlen(cardId) )
1426 sprintf( deviceNames[nDevices++],
"hw:%s,%d", cardId, device );
1428 sprintf( deviceNames[nDevices++],
"hw:%d,%d", card, device );
1429 if ( nDevices > MAX_DEVICES )
break;
1431 if ( nDevices > MAX_DEVICES )
break;
1433 snd_ctl_close(handle);
1434 snd_card_next(&card);
1437 if (nDevices == 0)
return;
1440 devices = (RTAUDIO_DEVICE *) calloc(nDevices,
sizeof(RTAUDIO_DEVICE));
1441 if (devices ==
NULL) {
1442 sprintf(message,
"RtAudio: memory allocation error!");
1448 for (
int i=0; i<nDevices; i++) {
1449 strncpy(devices[i].name, deviceNames[i], 32);
1454 int RtAudio :: getDefaultInputDevice(
void)
1460 int RtAudio :: getDefaultOutputDevice(
void)
1466 void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
1469 int open_mode = SND_PCM_ASYNC;
1472 snd_pcm_stream_t stream;
1473 snd_pcm_info_t *pcminfo;
1474 snd_pcm_info_alloca(&pcminfo);
1475 snd_pcm_hw_params_t *params;
1476 snd_pcm_hw_params_alloca(¶ms);
1481 strncpy( name, info->name, 32 );
1482 card = strtok(name,
",");
1483 err = snd_ctl_open(&chandle, card, 0);
1485 sprintf(message,
"RtAudio: ALSA control open (%s): %s.", card, snd_strerror(err));
1489 unsigned int dev = (
unsigned int) atoi( strtok(
NULL,
",") );
1492 stream = SND_PCM_STREAM_PLAYBACK;
1493 snd_pcm_info_set_device(pcminfo, dev);
1494 snd_pcm_info_set_subdevice(pcminfo, 0);
1495 snd_pcm_info_set_stream(pcminfo, stream);
1497 if ((err = snd_ctl_pcm_info(chandle, pcminfo)) < 0) {
1498 if (err == -ENOENT) {
1499 sprintf(message,
"RtAudio: ALSA pcm device (%s) doesn't handle output!", info->name);
1503 sprintf(message,
"RtAudio: ALSA snd_ctl_pcm_info error for device (%s) output: %s",
1504 info->name, snd_strerror(err));
1510 err = snd_pcm_open(&handle, info->name, stream, open_mode | SND_PCM_NONBLOCK );
1513 sprintf(message,
"RtAudio: ALSA pcm playback device (%s) is busy: %s.",
1514 info->name, snd_strerror(err));
1516 sprintf(message,
"RtAudio: ALSA pcm playback open (%s) error: %s.",
1517 info->name, snd_strerror(err));
1523 err = snd_pcm_hw_params_any(handle, params);
1525 snd_pcm_close(handle);
1526 sprintf(message,
"RtAudio: ALSA hardware probe error (%s): %s.",
1527 info->name, snd_strerror(err));
1533 info->minOutputChannels = snd_pcm_hw_params_get_channels_min(params);
1534 info->maxOutputChannels = snd_pcm_hw_params_get_channels_max(params);
1536 snd_pcm_close(handle);
1540 stream = SND_PCM_STREAM_CAPTURE;
1541 snd_pcm_info_set_stream(pcminfo, stream);
1543 err = snd_ctl_pcm_info(chandle, pcminfo);
1544 snd_ctl_close(chandle);
1546 if (err == -ENOENT) {
1547 sprintf(message,
"RtAudio: ALSA pcm device (%s) doesn't handle input!", info->name);
1551 sprintf(message,
"RtAudio: ALSA snd_ctl_pcm_info error for device (%s) input: %s",
1552 info->name, snd_strerror(err));
1555 if (info->maxOutputChannels == 0)
1558 goto probe_parameters;
1561 err = snd_pcm_open(&handle, info->name, stream, open_mode | SND_PCM_NONBLOCK);
1564 sprintf(message,
"RtAudio: ALSA pcm capture device (%s) is busy: %s.",
1565 info->name, snd_strerror(err));
1567 sprintf(message,
"RtAudio: ALSA pcm capture open (%s) error: %s.",
1568 info->name, snd_strerror(err));
1570 if (info->maxOutputChannels == 0)
1573 goto probe_parameters;
1577 err = snd_pcm_hw_params_any(handle, params);
1579 snd_pcm_close(handle);
1580 sprintf(message,
"RtAudio: ALSA hardware probe error (%s): %s.",
1581 info->name, snd_strerror(err));
1583 if (info->maxOutputChannels > 0)
1584 goto probe_parameters;
1590 info->minInputChannels = snd_pcm_hw_params_get_channels_min(params);
1591 info->maxInputChannels = snd_pcm_hw_params_get_channels_max(params);
1593 snd_pcm_close(handle);
1596 if (info->maxOutputChannels == 0 || info->maxInputChannels == 0)
1597 goto probe_parameters;
1599 info->hasDuplexSupport =
true;
1600 info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ?
1601 info->maxInputChannels : info->maxOutputChannels;
1602 info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ?
1603 info->minInputChannels : info->minOutputChannels;
1612 if (info->maxOutputChannels >= info->maxInputChannels)
1613 stream = SND_PCM_STREAM_PLAYBACK;
1615 stream = SND_PCM_STREAM_CAPTURE;
1617 err = snd_pcm_open(&handle, info->name, stream, open_mode);
1619 sprintf(message,
"RtAudio: ALSA pcm (%s) won't reopen during probe: %s.",
1620 info->name, snd_strerror(err));
1626 err = snd_pcm_hw_params_any(handle, params);
1628 snd_pcm_close(handle);
1629 sprintf(message,
"RtAudio: ALSA hardware reopen probe error (%s): %s.",
1630 info->name, snd_strerror(err));
1637 if (snd_pcm_hw_params_test_rate(handle, params, 35500, dir) == 0) {
1639 info->nSampleRates = -1;
1640 info->sampleRates[0] = snd_pcm_hw_params_get_rate_min(params, &dir);
1641 info->sampleRates[1] = snd_pcm_hw_params_get_rate_max(params, &dir);
1645 info->nSampleRates = 0;
1647 if (snd_pcm_hw_params_test_rate(handle, params, SAMPLE_RATES[i], dir) == 0) {
1648 info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
1649 info->nSampleRates++;
1652 if (info->nSampleRates == 0) {
1653 snd_pcm_close(handle);
1659 snd_pcm_format_t format;
1660 info->nativeFormats = 0;
1661 format = SND_PCM_FORMAT_S8;
1662 if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
1664 format = SND_PCM_FORMAT_S16;
1665 if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
1667 format = SND_PCM_FORMAT_S24;
1668 if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
1670 format = SND_PCM_FORMAT_S32;
1671 if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
1673 format = SND_PCM_FORMAT_FLOAT;
1674 if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
1676 format = SND_PCM_FORMAT_FLOAT64;
1677 if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
1681 if (info->nativeFormats == 0) {
1682 snd_pcm_close(handle);
1683 sprintf(message,
"RtAudio: ALSA PCM device (%s) data format not supported by RtAudio.",
1690 snd_pcm_close(handle);
1691 info->probed =
true;
1695 bool RtAudio :: probeDeviceOpen(
int device, RTAUDIO_STREAM *stream,
1696 STREAM_MODE mode,
int channels,
1697 int sampleRate, RTAUDIO_FORMAT format,
1698 int *bufferSize,
int numberOfBuffers)
1700 #if defined(__RTAUDIO_DEBUG__)
1702 snd_output_stdio_attach(&out, stderr, 0);
1706 const char *name = devices[device].
name;
1708 snd_pcm_stream_t alsa_stream;
1710 alsa_stream = SND_PCM_STREAM_PLAYBACK;
1712 alsa_stream = SND_PCM_STREAM_CAPTURE;
1716 int alsa_open_mode = SND_PCM_ASYNC;
1717 err = snd_pcm_open(&handle, name, alsa_stream, alsa_open_mode);
1719 sprintf(message,
"RtAudio: ALSA pcm device (%s) won't open: %s.",
1720 name, snd_strerror(err));
1726 snd_pcm_hw_params_t *hw_params;
1727 snd_pcm_hw_params_alloca(&hw_params);
1728 err = snd_pcm_hw_params_any(handle, hw_params);
1730 snd_pcm_close(handle);
1731 sprintf(message,
"RtAudio: ALSA error getting parameter handle (%s): %s.",
1732 name, snd_strerror(err));
1737 #if defined(__RTAUDIO_DEBUG__)
1738 fprintf(stderr,
"\nRtAudio: ALSA dump hardware params just after device open:\n\n");
1739 snd_pcm_hw_params_dump(hw_params, out);
1744 if ( !snd_pcm_hw_params_test_access( handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) ) {
1745 err = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
1747 else if ( !snd_pcm_hw_params_test_access( handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED) ) {
1748 err = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED);
1749 stream->deInterleave[mode] =
true;
1752 snd_pcm_close(handle);
1753 sprintf(message,
"RtAudio: ALSA device (%s) access not supported by RtAudio.", name);
1759 snd_pcm_close(handle);
1760 sprintf(message,
"RtAudio: ALSA error setting access ( (%s): %s.", name, snd_strerror(err));
1766 stream->userFormat = format;
1767 snd_pcm_format_t device_format;
1770 device_format = SND_PCM_FORMAT_S8;
1772 device_format = SND_PCM_FORMAT_S16;
1774 device_format = SND_PCM_FORMAT_S24;
1776 device_format = SND_PCM_FORMAT_S32;
1778 device_format = SND_PCM_FORMAT_FLOAT;
1780 device_format = SND_PCM_FORMAT_FLOAT64;
1782 if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
1783 stream->deviceFormat[mode] = format;
1788 device_format = SND_PCM_FORMAT_FLOAT64;
1789 if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
1794 device_format = SND_PCM_FORMAT_FLOAT;
1795 if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
1800 device_format = SND_PCM_FORMAT_S32;
1801 if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
1806 device_format = SND_PCM_FORMAT_S24;
1807 if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
1812 device_format = SND_PCM_FORMAT_S16;
1813 if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
1818 device_format = SND_PCM_FORMAT_S8;
1819 if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
1825 sprintf(message,
"RtAudio: ALSA pcm device (%s) data format not supported by RtAudio.", name);
1826 snd_pcm_close(handle);
1831 err = snd_pcm_hw_params_set_format(handle, hw_params, device_format);
1833 snd_pcm_close(handle);
1834 sprintf(message,
"RtAudio: ALSA error setting format (%s): %s.",
1835 name, snd_strerror(err));
1841 stream->doByteSwap[mode] =
false;
1842 if (device_format != SND_PCM_FORMAT_S8) {
1843 err = snd_pcm_format_cpu_endian(device_format);
1845 stream->doByteSwap[mode] =
true;
1847 snd_pcm_close(handle);
1848 sprintf(message,
"RtAudio: ALSA error getting format endian-ness (%s): %s.",
1849 name, snd_strerror(err));
1856 err = snd_pcm_hw_params_set_rate(handle, hw_params, (
unsigned int)sampleRate, 0);
1858 snd_pcm_close(handle);
1859 sprintf(message,
"RtAudio: ALSA error setting sample rate (%d) on device (%s): %s.",
1860 sampleRate, name, snd_strerror(err));
1867 stream->nUserChannels[mode] = channels;
1868 int device_channels = snd_pcm_hw_params_get_channels_max(hw_params);
1869 if (device_channels < channels) {
1870 snd_pcm_close(handle);
1871 sprintf(message,
"RtAudio: channels (%d) not supported by device (%s).",
1877 device_channels = snd_pcm_hw_params_get_channels_min(hw_params);
1878 if (device_channels < channels) device_channels = channels;
1879 stream->nDeviceChannels[mode] = device_channels;
1882 err = snd_pcm_hw_params_set_channels(handle, hw_params, device_channels);
1884 snd_pcm_close(handle);
1885 sprintf(message,
"RtAudio: ALSA error setting channels (%d) on device (%s): %s.",
1886 device_channels, name, snd_strerror(err));
1893 int periods = numberOfBuffers;
1895 if (periods < 2) periods = 2;
1896 err = snd_pcm_hw_params_get_periods_min(hw_params, &dir);
1897 if (err > periods) periods = err;
1898 err = snd_pcm_hw_params_get_periods_max(hw_params, &dir);
1899 if (err < periods) periods = err;
1901 err = snd_pcm_hw_params_set_periods(handle, hw_params, periods, 0);
1903 snd_pcm_close(handle);
1904 sprintf(message,
"RtAudio: ALSA error setting periods (%s): %s.",
1905 name, snd_strerror(err));
1911 err = snd_pcm_hw_params_get_period_size_min(hw_params, &dir);
1912 if (err > *bufferSize) *bufferSize = err;
1914 err = snd_pcm_hw_params_set_period_size(handle, hw_params, *bufferSize, 0);
1916 snd_pcm_close(handle);
1917 sprintf(message,
"RtAudio: ALSA error setting period size (%s): %s.",
1918 name, snd_strerror(err));
1925 if ( stream->mode == OUTPUT && mode == INPUT && *bufferSize != stream->bufferSize ) {
1926 sprintf( message,
"RtAudio: ALSA error setting buffer size for duplex stream on device (%s).",
1932 stream->bufferSize = *bufferSize;
1935 err = snd_pcm_hw_params(handle, hw_params);
1937 snd_pcm_close(handle);
1938 sprintf(message,
"RtAudio: ALSA error installing hardware configuration (%s): %s.",
1939 name, snd_strerror(err));
1944 #if defined(__RTAUDIO_DEBUG__)
1945 fprintf(stderr,
"\nRtAudio: ALSA dump hardware params after installation:\n\n");
1946 snd_pcm_hw_params_dump(hw_params, out);
1965 stream->handle[mode] = handle;
1966 stream->doConvertBuffer[mode] =
false;
1967 if (stream->userFormat != stream->deviceFormat[mode])
1968 stream->doConvertBuffer[mode] =
true;
1969 if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
1970 stream->doConvertBuffer[mode] =
true;
1971 if (stream->nUserChannels[mode] > 1 && stream->deInterleave[mode])
1972 stream->doConvertBuffer[mode] =
true;
1975 if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
1978 if (stream->nUserChannels[0] >= stream->nUserChannels[1])
1979 buffer_bytes = stream->nUserChannels[0];
1981 buffer_bytes = stream->nUserChannels[1];
1983 buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
1984 if (stream->userBuffer) free(stream->userBuffer);
1985 stream->userBuffer = (
char *) calloc(buffer_bytes, 1);
1986 if (stream->userBuffer ==
NULL)
1990 if ( stream->doConvertBuffer[mode] ) {
1993 bool makeBuffer =
true;
1994 if ( mode == OUTPUT )
1995 buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
1997 buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
1998 if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
1999 long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
2000 if ( buffer_bytes < bytes_out ) makeBuffer =
false;
2005 buffer_bytes *= *bufferSize;
2006 if (stream->deviceBuffer) free(stream->deviceBuffer);
2007 stream->deviceBuffer = (
char *) calloc(buffer_bytes, 1);
2008 if (stream->deviceBuffer ==
NULL)
2013 stream->device[mode] = device;
2014 stream->state = STREAM_STOPPED;
2015 if ( stream->mode == OUTPUT && mode == INPUT )
2017 stream->mode = DUPLEX;
2019 stream->mode = mode;
2020 stream->nBuffers = periods;
2021 stream->sampleRate = sampleRate;
2026 if (stream->handle[0]) {
2027 snd_pcm_close(stream->handle[0]);
2028 stream->handle[0] = 0;
2030 if (stream->handle[1]) {
2031 snd_pcm_close(stream->handle[1]);
2032 stream->handle[1] = 0;
2034 if (stream->userBuffer) {
2035 free(stream->userBuffer);
2036 stream->userBuffer = 0;
2038 sprintf(message,
"RtAudio: ALSA error allocating buffer memory (%s).", name);
2048 if ( streams.find( streamId ) == streams.end() ) {
2049 sprintf(message,
"RtAudio: invalid stream identifier!");
2054 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
2056 if (stream->callbackInfo.usingCallback) {
2057 pthread_cancel(stream->callbackInfo.thread);
2058 pthread_join(stream->callbackInfo.thread,
NULL);
2061 if (stream->state == STREAM_RUNNING) {
2062 if (stream->mode == OUTPUT || stream->mode == DUPLEX)
2063 snd_pcm_drop(stream->handle[0]);
2064 if (stream->mode == INPUT || stream->mode == DUPLEX)
2065 snd_pcm_drop(stream->handle[1]);
2068 pthread_mutex_destroy(&stream->mutex);
2070 if (stream->handle[0])
2071 snd_pcm_close(stream->handle[0]);
2073 if (stream->handle[1])
2074 snd_pcm_close(stream->handle[1]);
2076 if (stream->userBuffer)
2077 free(stream->userBuffer);
2079 if (stream->deviceBuffer)
2080 free(stream->deviceBuffer);
2083 streams.erase(streamId);
2090 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
2094 if (stream->state == STREAM_RUNNING)
2098 snd_pcm_state_t state;
2099 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
2100 state = snd_pcm_state(stream->handle[0]);
2101 if (state != SND_PCM_STATE_PREPARED) {
2102 err = snd_pcm_prepare(stream->handle[0]);
2104 sprintf(message,
"RtAudio: ALSA error preparing pcm device (%s): %s.",
2105 devices[stream->device[0]].name, snd_strerror(err));
2112 if (stream->mode == INPUT || stream->mode == DUPLEX) {
2113 state = snd_pcm_state(stream->handle[1]);
2114 if (state != SND_PCM_STATE_PREPARED) {
2115 err = snd_pcm_prepare(stream->handle[1]);
2117 sprintf(message,
"RtAudio: ALSA error preparing pcm device (%s): %s.",
2118 devices[stream->device[1]].name, snd_strerror(err));
2124 stream->state = STREAM_RUNNING;
2132 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
2136 if (stream->state == STREAM_STOPPED)
2140 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
2141 err = snd_pcm_drain(stream->handle[0]);
2143 sprintf(message,
"RtAudio: ALSA error draining pcm device (%s): %s.",
2144 devices[stream->device[0]].name, snd_strerror(err));
2150 if (stream->mode == INPUT || stream->mode == DUPLEX) {
2151 err = snd_pcm_drain(stream->handle[1]);
2153 sprintf(message,
"RtAudio: ALSA error draining pcm device (%s): %s.",
2154 devices[stream->device[1]].name, snd_strerror(err));
2159 stream->state = STREAM_STOPPED;
2167 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
2171 if (stream->state == STREAM_STOPPED)
2175 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
2176 err = snd_pcm_drop(stream->handle[0]);
2178 sprintf(message,
"RtAudio: ALSA error draining pcm device (%s): %s.",
2179 devices[stream->device[0]].name, snd_strerror(err));
2185 if (stream->mode == INPUT || stream->mode == DUPLEX) {
2186 err = snd_pcm_drop(stream->handle[1]);
2188 sprintf(message,
"RtAudio: ALSA error draining pcm device (%s): %s.",
2189 devices[stream->device[1]].name, snd_strerror(err));
2194 stream->state = STREAM_STOPPED;
2202 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
2206 int err = 0, frames = 0;
2207 if (stream->state == STREAM_STOPPED)
2210 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
2211 err = snd_pcm_avail_update(stream->handle[0]);
2213 sprintf(message,
"RtAudio: ALSA error getting available frames for device (%s): %s.",
2214 devices[stream->device[0]].name, snd_strerror(err));
2222 if (stream->mode == INPUT || stream->mode == DUPLEX) {
2223 err = snd_pcm_avail_update(stream->handle[1]);
2225 sprintf(message,
"RtAudio: ALSA error getting available frames for device (%s): %s.",
2226 devices[stream->device[1]].name, snd_strerror(err));
2230 if (frames > err) frames = err;
2233 frames = stream->bufferSize - frames;
2234 if (frames < 0) frames = 0;
2243 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
2246 if (stream->state == STREAM_STOPPED) {
2247 if (stream->callbackInfo.usingCallback) usleep(50000);
2250 else if (stream->callbackInfo.usingCallback) {
2252 stopStream = callback(stream->userBuffer, stream->bufferSize, stream->callbackInfo.userData);
2258 if (stream->state == STREAM_STOPPED)
2265 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
2268 if (stream->doConvertBuffer[0]) {
2269 convertStreamBuffer(stream, OUTPUT);
2270 buffer = stream->deviceBuffer;
2271 channels = stream->nDeviceChannels[0];
2272 format = stream->deviceFormat[0];
2275 buffer = stream->userBuffer;
2276 channels = stream->nUserChannels[0];
2277 format = stream->userFormat;
2281 if (stream->doByteSwap[0])
2282 byteSwapBuffer(buffer, stream->bufferSize * channels, format);
2285 if (stream->deInterleave[0]) {
2286 void *bufs[channels];
2287 size_t offset = stream->bufferSize * formatBytes(format);
2288 for (
int i=0; i<channels; i++)
2289 bufs[i] = (
void *) (buffer + (i * offset));
2290 err = snd_pcm_writen(stream->handle[0], bufs, stream->bufferSize);
2293 err = snd_pcm_writei(stream->handle[0], buffer, stream->bufferSize);
2295 if (err < stream->bufferSize) {
2297 if (err == -EPIPE) {
2298 snd_pcm_state_t state = snd_pcm_state(stream->handle[0]);
2299 if (state == SND_PCM_STATE_XRUN) {
2300 sprintf(message,
"RtAudio: ALSA underrun detected.");
2302 err = snd_pcm_prepare(stream->handle[0]);
2304 sprintf(message,
"RtAudio: ALSA error preparing handle after underrun: %s.",
2311 sprintf(message,
"RtAudio: ALSA error, current state is %s.",
2312 snd_pcm_state_name(state));
2319 sprintf(message,
"RtAudio: ALSA audio write error for device (%s): %s.",
2320 devices[stream->device[0]].name, snd_strerror(err));
2327 if (stream->mode == INPUT || stream->mode == DUPLEX) {
2330 if (stream->doConvertBuffer[1]) {
2331 buffer = stream->deviceBuffer;
2332 channels = stream->nDeviceChannels[1];
2333 format = stream->deviceFormat[1];
2336 buffer = stream->userBuffer;
2337 channels = stream->nUserChannels[1];
2338 format = stream->userFormat;
2342 if (stream->deInterleave[1]) {
2343 void *bufs[channels];
2344 size_t offset = stream->bufferSize * formatBytes(format);
2345 for (
int i=0; i<channels; i++)
2346 bufs[i] = (
void *) (buffer + (i * offset));
2347 err = snd_pcm_readn(stream->handle[1], bufs, stream->bufferSize);
2350 err = snd_pcm_readi(stream->handle[1], buffer, stream->bufferSize);
2352 if (err < stream->bufferSize) {
2354 if (err == -EPIPE) {
2355 snd_pcm_state_t state = snd_pcm_state(stream->handle[1]);
2356 if (state == SND_PCM_STATE_XRUN) {
2357 sprintf(message,
"RtAudio: ALSA overrun detected.");
2359 err = snd_pcm_prepare(stream->handle[1]);
2361 sprintf(message,
"RtAudio: ALSA error preparing handle after overrun: %s.",
2368 sprintf(message,
"RtAudio: ALSA error, current state is %s.",
2369 snd_pcm_state_name(state));
2376 sprintf(message,
"RtAudio: ALSA audio read error for device (%s): %s.",
2377 devices[stream->device[1]].name, snd_strerror(err));
2384 if (stream->doByteSwap[1])
2385 byteSwapBuffer(buffer, stream->bufferSize * channels, format);
2388 if (stream->doConvertBuffer[1])
2389 convertStreamBuffer(stream, INPUT);
2395 if (stream->callbackInfo.usingCallback && stopStream)
2399 extern "C" void *callbackHandler(
void *ptr)
2406 while ( *usingCallback ) {
2407 pthread_testcancel();
2409 object->tickStream(stream);
2412 fprintf(stderr,
"\nRtAudio: Callback thread error (%s) ... closing thread.\n\n",
2423 #elif defined(__LINUX_OSS__)
2425 #include <sys/stat.h>
2426 #include <sys/types.h>
2427 #include <sys/ioctl.h>
2430 #include <sys/soundcard.h>
2434 #define DAC_NAME "/dev/dsp"
2435 #define MAX_DEVICES 16
2436 #define MAX_CHANNELS 16
2438 void RtAudio :: initialize(
void)
2449 char device_name[16];
2450 struct stat dspstat;
2453 if (lstat(DAC_NAME, &dspstat) == 0) {
2454 if (S_ISLNK(dspstat.st_mode)) {
2455 i = readlink(DAC_NAME, device_name,
sizeof(device_name));
2457 device_name[i] =
'\0';
2459 if (!strncmp(DAC_NAME, device_name, 8))
2460 dsplink = atoi(&device_name[8]);
2463 if (!strncmp(
"dsp", device_name, 3))
2464 dsplink = atoi(&device_name[3]);
2468 sprintf(message,
"RtAudio: cannot read value of symbolic link %s.", DAC_NAME);
2474 sprintf(message,
"RtAudio: cannot stat %s.", DAC_NAME);
2486 char names[MAX_DEVICES][16];
2487 for (i=-1; i<MAX_DEVICES; i++) {
2491 sprintf(device_name,
"%s", DAC_NAME);
2492 else if (i == dsplink)
2495 sprintf(device_name,
"%s%d", DAC_NAME, i);
2498 fd = open(device_name, O_WRONLY | O_NONBLOCK);
2501 if (errno != EBUSY && errno != EAGAIN) {
2503 fd = open(device_name, O_RDONLY | O_NONBLOCK);
2506 if (errno != EBUSY && errno != EAGAIN)
2509 sprintf(message,
"RtAudio: OSS record device (%s) is busy.", device_name);
2516 sprintf(message,
"RtAudio: OSS playback device (%s) is busy.", device_name);
2522 if (fd >= 0) close(fd);
2523 strncpy(names[nDevices], device_name, 16);
2527 if (nDevices == 0)
return;
2530 devices = (RTAUDIO_DEVICE *) calloc(nDevices,
sizeof(RTAUDIO_DEVICE));
2531 if (devices ==
NULL) {
2532 sprintf(message,
"RtAudio: memory allocation error!");
2537 for (i=0; i<nDevices; i++) {
2538 strncpy(devices[i].name, names[i], 16);
2545 int RtAudio :: getDefaultInputDevice(
void)
2551 int RtAudio :: getDefaultOutputDevice(
void)
2557 void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
2559 int i, fd, channels, mask;
2565 fd = open(info->name, O_WRONLY | O_NONBLOCK);
2568 if (errno == EBUSY || errno == EAGAIN)
2569 sprintf(message,
"RtAudio: OSS playback device (%s) is busy and cannot be probed.",
2572 sprintf(message,
"RtAudio: OSS playback device (%s) open error.", info->name);
2578 for (i=MAX_CHANNELS; i>0; i--) {
2580 if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
2588 if (channels != i )
continue;
2592 info->maxOutputChannels = i;
2595 for (i=1; i<=info->maxOutputChannels; i++) {
2597 if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
2602 info->minOutputChannels = i;
2607 fd = open(info->name, O_RDONLY | O_NONBLOCK);
2610 if (errno == EBUSY || errno == EAGAIN)
2611 sprintf(message,
"RtAudio: OSS capture device (%s) is busy and cannot be probed.",
2614 sprintf(message,
"RtAudio: OSS capture device (%s) open error.", info->name);
2616 if (info->maxOutputChannels == 0)
2619 goto probe_parameters;
2623 for (i=MAX_CHANNELS; i>0; i--) {
2625 if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) {
2631 info->maxInputChannels = i;
2634 for (i=1; i<=info->maxInputChannels; i++) {
2636 if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
2641 info->minInputChannels = i;
2644 if (info->maxOutputChannels == 0 && info->maxInputChannels == 0) {
2645 sprintf(message,
"RtAudio: OSS device (%s) reports zero channels for input and output.",
2652 if (info->maxOutputChannels == 0 || info->maxInputChannels == 0)
2653 goto probe_parameters;
2655 fd = open(info->name, O_RDWR | O_NONBLOCK);
2657 goto probe_parameters;
2659 ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
2660 ioctl(fd, SNDCTL_DSP_GETCAPS, &mask);
2661 if (mask & DSP_CAP_DUPLEX) {
2662 info->hasDuplexSupport =
true;
2664 for (i=MAX_CHANNELS; i>0; i--) {
2666 if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
2671 info->maxDuplexChannels = i;
2674 for (i=1; i<=info->maxDuplexChannels; i++) {
2676 if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
2681 info->minDuplexChannels = i;
2692 if (info->maxOutputChannels >= info->maxInputChannels) {
2693 fd = open(info->name, O_WRONLY | O_NONBLOCK);
2694 channels = info->maxOutputChannels;
2697 fd = open(info->name, O_RDONLY | O_NONBLOCK);
2698 channels = info->maxInputChannels;
2703 sprintf(message,
"RtAudio: OSS device (%s) won't reopen during probe.",
2711 if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) {
2714 sprintf(message,
"RtAudio: OSS device (%s) won't revert to previous channel setting.",
2720 if (ioctl(fd, SNDCTL_DSP_GETFMTS, &mask) == -1) {
2722 sprintf(message,
"RtAudio: OSS device (%s) can't get supported audio formats.",
2730 info->nativeFormats = 0;
2731 #if defined (AFMT_S32_BE)
2733 if (mask & AFMT_S32_BE) {
2734 format = AFMT_S32_BE;
2738 #if defined (AFMT_S32_LE)
2740 if (mask & AFMT_S32_LE) {
2741 format = AFMT_S32_LE;
2745 if (mask & AFMT_S8) {
2749 if (mask & AFMT_S16_BE) {
2750 format = AFMT_S16_BE;
2753 if (mask & AFMT_S16_LE) {
2754 format = AFMT_S16_LE;
2759 if (info->nativeFormats == 0) {
2761 sprintf(message,
"RtAudio: OSS device (%s) data format not supported by RtAudio.",
2769 if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) == -1 || format != i) {
2771 sprintf(message,
"RtAudio: OSS device (%s) error setting data format.",
2779 if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) == -1) {
2783 info->nSampleRates = 0;
2785 speed = SAMPLE_RATES[i];
2786 if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) != -1) {
2787 info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
2788 info->nSampleRates++;
2791 if (info->nSampleRates == 0) {
2797 info->sampleRates[0] = speed;
2801 if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) == -1) {
2803 sprintf(message,
"RtAudio: OSS device (%s) error setting sample rate.",
2808 info->sampleRates[1] = speed;
2809 info->nSampleRates = -1;
2813 info->probed =
true;
2817 bool RtAudio :: probeDeviceOpen(
int device, RTAUDIO_STREAM *stream,
2818 STREAM_MODE mode,
int channels,
2819 int sampleRate, RTAUDIO_FORMAT format,
2820 int *bufferSize,
int numberOfBuffers)
2822 int buffers, buffer_bytes, device_channels, device_format;
2823 int srate, temp, fd;
2825 const char *name = devices[device].
name;
2828 fd = open(name, O_WRONLY | O_NONBLOCK);
2830 if (stream->mode == OUTPUT && stream->device[0] == device) {
2832 close(stream->handle[0]);
2833 stream->handle[0] = 0;
2835 if (stream->nUserChannels[0] != channels) {
2836 sprintf(message,
"RtAudio: input/output channels must be equal for OSS duplex device (%s).", name);
2839 fd = open(name, O_RDWR | O_NONBLOCK);
2842 fd = open(name, O_RDONLY | O_NONBLOCK);
2846 if (errno == EBUSY || errno == EAGAIN)
2847 sprintf(message,
"RtAudio: OSS device (%s) is busy and cannot be opened.",
2850 sprintf(message,
"RtAudio: OSS device (%s) cannot be opened.", name);
2857 fd = open(name, O_WRONLY | O_SYNC);
2859 if (stream->mode == OUTPUT && stream->device[0] == device)
2860 fd = open(name, O_RDWR | O_SYNC);
2862 fd = open(name, O_RDONLY | O_SYNC);
2866 sprintf(message,
"RtAudio: OSS device (%s) cannot be opened.", name);
2872 if (ioctl(fd, SNDCTL_DSP_GETFMTS, &mask) == -1) {
2874 sprintf(message,
"RtAudio: OSS device (%s) can't get supported audio formats.",
2880 stream->userFormat = format;
2882 stream->doByteSwap[mode] =
false;
2884 if (mask & AFMT_S8) {
2885 device_format = AFMT_S8;
2890 if (mask & AFMT_S16_NE) {
2891 device_format = AFMT_S16_NE;
2894 #if BYTE_ORDER == LITTLE_ENDIAN
2895 else if (mask & AFMT_S16_BE) {
2896 device_format = AFMT_S16_BE;
2898 stream->doByteSwap[mode] =
true;
2901 else if (mask & AFMT_S16_LE) {
2902 device_format = AFMT_S16_LE;
2904 stream->doByteSwap[mode] =
true;
2908 #if defined (AFMT_S32_NE) && defined (AFMT_S32_LE) && defined (AFMT_S32_BE)
2910 if (mask & AFMT_S32_NE) {
2911 device_format = AFMT_S32_NE;
2914 #if BYTE_ORDER == LITTLE_ENDIAN
2915 else if (mask & AFMT_S32_BE) {
2916 device_format = AFMT_S32_BE;
2918 stream->doByteSwap[mode] =
true;
2921 else if (mask & AFMT_S32_LE) {
2922 device_format = AFMT_S32_LE;
2924 stream->doByteSwap[mode] =
true;
2930 if (device_format == -1) {
2932 if (mask & AFMT_S16_NE) {
2933 device_format = AFMT_S16_NE;
2936 #if BYTE_ORDER == LITTLE_ENDIAN
2937 else if (mask & AFMT_S16_BE) {
2938 device_format = AFMT_S16_BE;
2940 stream->doByteSwap[mode] =
true;
2943 else if (mask & AFMT_S16_LE) {
2944 device_format = AFMT_S16_LE;
2946 stream->doByteSwap[mode] =
true;
2949 #if defined (AFMT_S32_NE) && defined (AFMT_S32_LE) && defined (AFMT_S32_BE)
2950 else if (mask & AFMT_S32_NE) {
2951 device_format = AFMT_S32_NE;
2954 #if BYTE_ORDER == LITTLE_ENDIAN
2955 else if (mask & AFMT_S32_BE) {
2956 device_format = AFMT_S32_BE;
2958 stream->doByteSwap[mode] =
true;
2961 else if (mask & AFMT_S32_LE) {
2962 device_format = AFMT_S32_LE;
2964 stream->doByteSwap[mode] =
true;
2968 else if (mask & AFMT_S8) {
2969 device_format = AFMT_S8;
2974 if (stream->deviceFormat[mode] == 0) {
2977 sprintf(message,
"RtAudio: OSS device (%s) data format not supported by RtAudio.",
2984 stream->nUserChannels[mode] = channels;
2985 device_channels = channels;
2986 if (mode == OUTPUT) {
2987 if (channels < devices[device].minOutputChannels)
2991 if (stream->mode == OUTPUT && stream->device[0] == device) {
2993 if (channels < devices[device].minDuplexChannels)
2997 if (channels < devices[device].minInputChannels)
3001 stream->nDeviceChannels[mode] = device_channels;
3010 buffer_bytes = *bufferSize * formatBytes(stream->deviceFormat[mode]) * device_channels;
3011 if (buffer_bytes < 16) buffer_bytes = 16;
3012 buffers = numberOfBuffers;
3013 if (buffers < 2) buffers = 2;
3014 temp = ((int) buffers << 16) + (int)(log10((
double)buffer_bytes)/log10(2.0));
3015 if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &temp)) {
3017 sprintf(message,
"RtAudio: OSS error setting fragment size for device (%s).",
3021 stream->nBuffers = buffers;
3024 temp = device_format;
3025 if (ioctl(fd, SNDCTL_DSP_SETFMT, &device_format) == -1 || device_format != temp) {
3027 sprintf(message,
"RtAudio: OSS error setting data format for device (%s).",
3033 temp = device_channels;
3034 if (ioctl(fd, SNDCTL_DSP_CHANNELS, &device_channels) == -1 || device_channels != temp) {
3036 sprintf(message,
"RtAudio: OSS error setting %d channels on device (%s).",
3044 if (ioctl(fd, SNDCTL_DSP_SPEED, &srate) == -1) {
3046 sprintf(message,
"RtAudio: OSS error setting sample rate = %d on device (%s).",
3052 if (abs(srate - temp) > 100) {
3054 sprintf(message,
"RtAudio: OSS error ... audio device (%s) doesn't support sample rate of %d.",
3058 stream->sampleRate = sampleRate;
3060 if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &buffer_bytes) == -1) {
3062 sprintf(message,
"RtAudio: OSS error getting buffer size for device (%s).",
3068 *bufferSize = buffer_bytes / (formatBytes(stream->deviceFormat[mode]) * device_channels);
3069 stream->bufferSize = *bufferSize;
3071 if (mode == INPUT && stream->mode == OUTPUT &&
3072 stream->device[0] == device) {
3074 stream->deviceFormat[0] = stream->deviceFormat[1];
3075 stream->nDeviceChannels[0] = device_channels;
3079 stream->doConvertBuffer[mode] =
false;
3080 if (stream->userFormat != stream->deviceFormat[mode])
3081 stream->doConvertBuffer[mode] =
true;
3082 if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
3083 stream->doConvertBuffer[mode] =
true;
3086 if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
3089 if (stream->nUserChannels[0] >= stream->nUserChannels[1])
3090 buffer_bytes = stream->nUserChannels[0];
3092 buffer_bytes = stream->nUserChannels[1];
3094 buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
3095 if (stream->userBuffer) free(stream->userBuffer);
3096 stream->userBuffer = (
char *) calloc(buffer_bytes, 1);
3097 if (stream->userBuffer ==
NULL) {
3099 sprintf(message,
"RtAudio: OSS error allocating user buffer memory (%s).",
3105 if ( stream->doConvertBuffer[mode] ) {
3108 bool makeBuffer =
true;
3109 if ( mode == OUTPUT )
3110 buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
3112 buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
3113 if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
3114 long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
3115 if ( buffer_bytes < bytes_out ) makeBuffer =
false;
3120 buffer_bytes *= *bufferSize;
3121 if (stream->deviceBuffer) free(stream->deviceBuffer);
3122 stream->deviceBuffer = (
char *) calloc(buffer_bytes, 1);
3123 if (stream->deviceBuffer ==
NULL) {
3125 free(stream->userBuffer);
3126 sprintf(message,
"RtAudio: OSS error allocating device buffer memory (%s).",
3133 stream->device[mode] = device;
3134 stream->handle[mode] = fd;
3135 stream->state = STREAM_STOPPED;
3136 if ( stream->mode == OUTPUT && mode == INPUT ) {
3137 stream->mode = DUPLEX;
3138 if (stream->device[0] == device)
3139 stream->handle[0] = fd;
3142 stream->mode = mode;
3147 if (stream->handle[0]) {
3148 close(stream->handle[0]);
3149 stream->handle[0] = 0;
3160 if ( streams.find( streamId ) == streams.end() ) {
3161 sprintf(message,
"RtAudio: invalid stream identifier!");
3166 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
3168 if (stream->callbackInfo.usingCallback) {
3169 pthread_cancel(stream->callbackInfo.thread);
3170 pthread_join(stream->callbackInfo.thread,
NULL);
3173 if (stream->state == STREAM_RUNNING) {
3174 if (stream->mode == OUTPUT || stream->mode == DUPLEX)
3175 ioctl(stream->handle[0], SNDCTL_DSP_RESET, 0);
3176 if (stream->mode == INPUT || stream->mode == DUPLEX)
3177 ioctl(stream->handle[1], SNDCTL_DSP_RESET, 0);
3180 pthread_mutex_destroy(&stream->mutex);
3182 if (stream->handle[0])
3183 close(stream->handle[0]);
3185 if (stream->handle[1])
3186 close(stream->handle[1]);
3188 if (stream->userBuffer)
3189 free(stream->userBuffer);
3191 if (stream->deviceBuffer)
3192 free(stream->deviceBuffer);
3195 streams.erase(streamId);
3200 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
3204 stream->state = STREAM_RUNNING;
3214 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
3218 if (stream->state == STREAM_STOPPED)
3222 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
3223 err = ioctl(stream->handle[0], SNDCTL_DSP_SYNC, 0);
3225 sprintf(message,
"RtAudio: OSS error stopping device (%s).",
3226 devices[stream->device[0]].name);
3231 err = ioctl(stream->handle[1], SNDCTL_DSP_SYNC, 0);
3233 sprintf(message,
"RtAudio: OSS error stopping device (%s).",
3234 devices[stream->device[1]].name);
3238 stream->state = STREAM_STOPPED;
3246 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
3250 if (stream->state == STREAM_STOPPED)
3254 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
3255 err = ioctl(stream->handle[0], SNDCTL_DSP_RESET, 0);
3257 sprintf(message,
"RtAudio: OSS error aborting device (%s).",
3258 devices[stream->device[0]].name);
3263 err = ioctl(stream->handle[1], SNDCTL_DSP_RESET, 0);
3265 sprintf(message,
"RtAudio: OSS error aborting device (%s).",
3266 devices[stream->device[1]].name);
3270 stream->state = STREAM_STOPPED;
3278 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
3282 int bytes = 0, channels = 0, frames = 0;
3283 if (stream->state == STREAM_STOPPED)
3286 audio_buf_info info;
3287 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
3288 ioctl(stream->handle[0], SNDCTL_DSP_GETOSPACE, &info);
3290 channels = stream->nDeviceChannels[0];
3293 if (stream->mode == INPUT || stream->mode == DUPLEX) {
3294 ioctl(stream->handle[1], SNDCTL_DSP_GETISPACE, &info);
3295 if (stream->mode == DUPLEX ) {
3296 bytes = (bytes < info.bytes) ? bytes : info.bytes;
3297 channels = stream->nDeviceChannels[0];
3301 channels = stream->nDeviceChannels[1];
3305 frames = (int) (bytes / (channels * formatBytes(stream->deviceFormat[0])));
3306 frames -= stream->bufferSize;
3307 if (frames < 0) frames = 0;
3316 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
3319 if (stream->state == STREAM_STOPPED) {
3320 if (stream->callbackInfo.usingCallback) usleep(50000);
3323 else if (stream->callbackInfo.usingCallback) {
3325 stopStream = callback(stream->userBuffer, stream->bufferSize, stream->callbackInfo.userData);
3331 if (stream->state == STREAM_STOPPED)
3338 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
3341 if (stream->doConvertBuffer[0]) {
3342 convertStreamBuffer(stream, OUTPUT);
3343 buffer = stream->deviceBuffer;
3344 samples = stream->bufferSize * stream->nDeviceChannels[0];
3345 format = stream->deviceFormat[0];
3348 buffer = stream->userBuffer;
3349 samples = stream->bufferSize * stream->nUserChannels[0];
3350 format = stream->userFormat;
3354 if (stream->doByteSwap[0])
3355 byteSwapBuffer(buffer, samples, format);
3358 result = write(stream->handle[0], buffer, samples * formatBytes(format));
3362 sprintf(message,
"RtAudio: OSS audio write error for device (%s).",
3363 devices[stream->device[0]].name);
3368 if (stream->mode == INPUT || stream->mode == DUPLEX) {
3371 if (stream->doConvertBuffer[1]) {
3372 buffer = stream->deviceBuffer;
3373 samples = stream->bufferSize * stream->nDeviceChannels[1];
3374 format = stream->deviceFormat[1];
3377 buffer = stream->userBuffer;
3378 samples = stream->bufferSize * stream->nUserChannels[1];
3379 format = stream->userFormat;
3383 result = read(stream->handle[1], buffer, samples * formatBytes(format));
3387 sprintf(message,
"RtAudio: OSS audio read error for device (%s).",
3388 devices[stream->device[1]].name);
3393 if (stream->doByteSwap[1])
3394 byteSwapBuffer(buffer, samples, format);
3397 if (stream->doConvertBuffer[1])
3398 convertStreamBuffer(stream, INPUT);
3404 if (stream->callbackInfo.usingCallback && stopStream)
3408 extern "C" void *callbackHandler(
void *ptr)
3415 while ( *usingCallback ) {
3416 pthread_testcancel();
3418 object->tickStream(stream);
3421 fprintf(stderr,
"\nRtAudio: Callback thread error (%s) ... closing thread.\n\n",
3433 #elif defined(__WINDOWS_ASIO__) // ASIO API on Windows
3446 #include "asio/asiosys.h"
3447 #include "asio/asio.h"
3448 #include "asio/asiodrivers.h"
3451 AsioDrivers drivers;
3452 ASIOCallbacks asioCallbacks;
3454 ASIODriverInfo driverInfo;
3456 void RtAudio :: initialize(
void)
3458 nDevices = drivers.asioGetNumDev();
3459 if (nDevices <= 0)
return;
3462 devices = (RTAUDIO_DEVICE *) calloc(nDevices,
sizeof(RTAUDIO_DEVICE));
3463 if (devices ==
NULL) {
3464 sprintf(message,
"RtAudio: memory allocation error!");
3470 for (
int i=0; i<nDevices; i++) {
3471 if ( drivers.asioGetDriverName( i, devices[i].name, 128 ) == 0 )
3475 sprintf(message,
"RtAudio: error getting ASIO driver name for device index %d!", i);
3480 drivers.removeCurrentDriver();
3481 driverInfo.asioVersion = 2;
3483 driverInfo.sysRef = GetForegroundWindow();
3486 int RtAudio :: getDefaultInputDevice(
void)
3491 int RtAudio :: getDefaultOutputDevice(
void)
3496 void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
3499 if ( streams.size() > 0 ) {
3500 sprintf(message,
"RtAudio: unable to probe ASIO driver while a stream is open.");
3505 if ( !drivers.loadDriver( info->name ) ) {
3506 sprintf(message,
"RtAudio: ASIO error loading driver (%s).", info->name);
3511 ASIOError result = ASIOInit( &driverInfo );
3512 if ( result != ASE_OK ) {
3514 if ( result == ASE_HWMalfunction )
3515 sprintf(details,
"hardware malfunction");
3516 else if ( result == ASE_NoMemory )
3517 sprintf(details,
"no memory");
3518 else if ( result == ASE_NotPresent )
3519 sprintf(details,
"driver/hardware not present");
3521 sprintf(details,
"unspecified");
3522 sprintf(message,
"RtAudio: ASIO error (%s) initializing driver (%s).", details, info->name);
3528 long inputChannels, outputChannels;
3529 result = ASIOGetChannels( &inputChannels, &outputChannels );
3530 if ( result != ASE_OK ) {
3531 drivers.removeCurrentDriver();
3532 sprintf(message,
"RtAudio: ASIO error getting input/output channel count (%s).", info->name);
3537 info->maxOutputChannels = outputChannels;
3538 if ( outputChannels > 0 ) info->minOutputChannels = 1;
3540 info->maxInputChannels = inputChannels;
3541 if ( inputChannels > 0 ) info->minInputChannels = 1;
3544 if (info->maxOutputChannels > 0 && info->maxInputChannels > 0) {
3545 info->hasDuplexSupport =
true;
3546 info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ?
3547 info->maxInputChannels : info->maxOutputChannels;
3548 info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ?
3549 info->minInputChannels : info->minOutputChannels;
3553 info->nSampleRates = 0;
3555 result = ASIOCanSampleRate( (ASIOSampleRate) SAMPLE_RATES[i] );
3556 if ( result == ASE_OK )
3557 info->sampleRates[info->nSampleRates++] = SAMPLE_RATES[i];
3560 if (info->nSampleRates == 0) {
3561 drivers.removeCurrentDriver();
3562 sprintf( message,
"RtAudio: No supported sample rates found for ASIO driver (%s).", info->name );
3568 ASIOChannelInfo channelInfo;
3569 channelInfo.channel = 0;
3570 channelInfo.isInput =
true;
3571 if ( info->maxInputChannels <= 0 ) channelInfo.isInput =
false;
3572 result = ASIOGetChannelInfo( &channelInfo );
3573 if ( result != ASE_OK ) {
3574 drivers.removeCurrentDriver();
3575 sprintf(message,
"RtAudio: ASIO error getting driver (%s) channel information.", info->name);
3580 if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB )
3582 else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB )
3584 else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB )
3586 else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB )
3590 if (info->nativeFormats == 0) {
3591 drivers.removeCurrentDriver();
3592 sprintf(message,
"RtAudio: ASIO driver (%s) data format not supported by RtAudio.",
3598 info->probed =
true;
3599 drivers.removeCurrentDriver();
3602 void bufferSwitch(
long index, ASIOBool processNow)
3606 object->callbackEvent( asioCallbackInfo->
streamId, index, (
void *)
NULL, (
void *)
NULL );
3609 fprintf(stderr,
"\nCallback handler error (%s)!\n\n", exception.
getMessage());
3616 void sampleRateChanged(ASIOSampleRate sRate)
3629 fprintf(stderr,
"\nRtAudio: sampleRateChanged() error (%s)!\n\n", exception.
getMessage());
3633 fprintf(stderr,
"\nRtAudio: ASIO driver reports sample rate changed to %d ... stream stopped!!!", (
int) sRate);
3636 long asioMessages(
long selector,
long value,
void* message,
double* opt)
3640 case kAsioSelectorSupported:
3641 if(value == kAsioResetRequest
3642 || value == kAsioEngineVersion
3643 || value == kAsioResyncRequest
3644 || value == kAsioLatenciesChanged
3647 || value == kAsioSupportsTimeInfo
3648 || value == kAsioSupportsTimeCode
3649 || value == kAsioSupportsInputMonitor)
3652 case kAsioResetRequest:
3659 fprintf(stderr,
"\nRtAudio: ASIO driver reset requested!!!");
3662 case kAsioResyncRequest:
3670 fprintf(stderr,
"\nRtAudio: ASIO driver resync requested!!!");
3673 case kAsioLatenciesChanged:
3678 fprintf(stderr,
"\nRtAudio: ASIO driver latency may have changed!!!");
3681 case kAsioEngineVersion:
3687 case kAsioSupportsTimeInfo:
3694 case kAsioSupportsTimeCode:
3704 bool RtAudio :: probeDeviceOpen(
int device, RTAUDIO_STREAM *stream,
3705 STREAM_MODE mode,
int channels,
3706 int sampleRate, RTAUDIO_FORMAT format,
3707 int *bufferSize,
int numberOfBuffers)
3710 if ( streams.size() > 0 ) {
3711 sprintf(message,
"RtAudio: unable to load ASIO driver while a stream is open.");
3717 if ( mode == INPUT && stream->mode == OUTPUT && stream->device[0] != device ) {
3718 sprintf(message,
"RtAudio: ASIO duplex stream must use the same device for input and output.");
3725 if ( mode != INPUT || stream->mode != OUTPUT ) {
3726 if ( !drivers.loadDriver( devices[device].name ) ) {
3727 sprintf(message,
"RtAudio: ASIO error loading driver (%s).", devices[device].name);
3732 result = ASIOInit( &driverInfo );
3733 if ( result != ASE_OK ) {
3735 if ( result == ASE_HWMalfunction )
3736 sprintf(details,
"hardware malfunction");
3737 else if ( result == ASE_NoMemory )
3738 sprintf(details,
"no memory");
3739 else if ( result == ASE_NotPresent )
3740 sprintf(details,
"driver/hardware not present");
3742 sprintf(details,
"unspecified");
3743 sprintf(message,
"RtAudio: ASIO error (%s) initializing driver (%s).", details, devices[device].name);
3750 long inputChannels, outputChannels;
3751 result = ASIOGetChannels( &inputChannels, &outputChannels );
3752 if ( result != ASE_OK ) {
3753 drivers.removeCurrentDriver();
3754 sprintf(message,
"RtAudio: ASIO error getting input/output channel count (%s).",
3755 devices[device].name);
3760 if ( ( mode == OUTPUT && channels > outputChannels) ||
3761 ( mode == INPUT && channels > inputChannels) ) {
3762 drivers.removeCurrentDriver();
3763 sprintf(message,
"RtAudio: ASIO driver (%s) does not support requested channel count (%d).",
3764 devices[device].name, channels);
3768 stream->nDeviceChannels[mode] = channels;
3769 stream->nUserChannels[mode] = channels;
3772 result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate );
3773 if ( result != ASE_OK ) {
3774 drivers.removeCurrentDriver();
3775 sprintf(message,
"RtAudio: ASIO driver (%s) does not support requested sample rate (%d).",
3776 devices[device].name, sampleRate);
3782 result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate );
3783 if ( result != ASE_OK ) {
3784 drivers.removeCurrentDriver();
3785 sprintf(message,
"RtAudio: ASIO driver (%s) error setting sample rate (%d).",
3786 devices[device].name, sampleRate);
3792 ASIOChannelInfo channelInfo;
3793 channelInfo.channel = 0;
3794 if ( mode == OUTPUT ) channelInfo.isInput =
false;
3795 else channelInfo.isInput =
true;
3796 result = ASIOGetChannelInfo( &channelInfo );
3797 if ( result != ASE_OK ) {
3798 drivers.removeCurrentDriver();
3799 sprintf(message,
"RtAudio: ASIO driver (%s) error getting data format.",
3800 devices[device].name);
3806 stream->doByteSwap[mode] =
false;
3807 stream->userFormat = format;
3808 stream->deviceFormat[mode] = 0;
3809 if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) {
3811 if ( channelInfo.type == ASIOSTInt16MSB ) stream->doByteSwap[mode] =
true;
3813 else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) {
3815 if ( channelInfo.type == ASIOSTInt32MSB ) stream->doByteSwap[mode] =
true;
3817 else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) {
3819 if ( channelInfo.type == ASIOSTFloat32MSB ) stream->doByteSwap[mode] =
true;
3821 else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) {
3823 if ( channelInfo.type == ASIOSTFloat64MSB ) stream->doByteSwap[mode] =
true;
3826 if ( stream->deviceFormat[mode] == 0 ) {
3827 drivers.removeCurrentDriver();
3828 sprintf(message,
"RtAudio: ASIO driver (%s) data format not supported by RtAudio.",
3829 devices[device].name);
3837 long minSize, maxSize, preferSize, granularity;
3838 result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity );
3839 if ( result != ASE_OK ) {
3840 drivers.removeCurrentDriver();
3841 sprintf(message,
"RtAudio: ASIO driver (%s) error getting buffer size.",
3842 devices[device].name);
3847 if ( *bufferSize < minSize ) *bufferSize = minSize;
3848 else if ( *bufferSize > maxSize ) *bufferSize = maxSize;
3849 else if ( granularity == -1 ) {
3851 double power = log10( *bufferSize ) / log10( 2.0 );
3852 *bufferSize = pow( 2.0, floor(power+0.5) );
3853 if ( *bufferSize < minSize ) *bufferSize = minSize;
3854 else if ( *bufferSize > maxSize ) *bufferSize = maxSize;
3855 else *bufferSize = preferSize;
3858 if ( mode == INPUT && stream->mode == OUTPUT && stream->bufferSize != *bufferSize )
3859 cout <<
"possible input/output buffersize discrepancy" << endl;
3861 stream->bufferSize = *bufferSize;
3862 stream->nBuffers = 2;
3865 stream->deInterleave[mode] =
true;
3870 if ( mode == INPUT && stream->mode == OUTPUT ) {
3871 free(stream->callbackInfo.buffers);
3872 result = ASIODisposeBuffers();
3873 if ( result != ASE_OK ) {
3874 drivers.removeCurrentDriver();
3875 sprintf(message,
"RtAudio: ASIO driver (%s) error disposing previously allocated buffers.",
3876 devices[device].name);
3883 int i, nChannels = stream->nDeviceChannels[0] + stream->nDeviceChannels[1];
3884 stream->callbackInfo.buffers = 0;
3885 ASIOBufferInfo *bufferInfos = (ASIOBufferInfo *) malloc( nChannels *
sizeof(ASIOBufferInfo) );
3886 stream->callbackInfo.buffers = (
void *) bufferInfos;
3887 ASIOBufferInfo *infos = bufferInfos;
3888 for ( i=0; i<stream->nDeviceChannels[1]; i++, infos++ ) {
3889 infos->isInput = ASIOTrue;
3890 infos->channelNum = i;
3891 infos->buffers[0] = infos->buffers[1] = 0;
3894 for ( i=0; i<stream->nDeviceChannels[0]; i++, infos++ ) {
3895 infos->isInput = ASIOFalse;
3896 infos->channelNum = i;
3897 infos->buffers[0] = infos->buffers[1] = 0;
3901 asioCallbacks.bufferSwitch = &bufferSwitch;
3902 asioCallbacks.sampleRateDidChange = &sampleRateChanged;
3903 asioCallbacks.asioMessage = &asioMessages;
3904 asioCallbacks.bufferSwitchTimeInfo =
NULL;
3905 result = ASIOCreateBuffers( bufferInfos, nChannels, stream->bufferSize, &asioCallbacks);
3906 if ( result != ASE_OK ) {
3907 drivers.removeCurrentDriver();
3908 sprintf(message,
"RtAudio: ASIO driver (%s) error creating buffers.",
3909 devices[device].name);
3915 stream->doConvertBuffer[mode] =
false;
3916 if (stream->userFormat != stream->deviceFormat[mode])
3917 stream->doConvertBuffer[mode] =
true;
3918 if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
3919 stream->doConvertBuffer[mode] =
true;
3920 if (stream->nUserChannels[mode] > 1 && stream->deInterleave[mode])
3921 stream->doConvertBuffer[mode] =
true;
3924 if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
3927 if (stream->nUserChannels[0] >= stream->nUserChannels[1])
3928 buffer_bytes = stream->nUserChannels[0];
3930 buffer_bytes = stream->nUserChannels[1];
3932 buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
3933 if (stream->userBuffer) free(stream->userBuffer);
3934 stream->userBuffer = (
char *) calloc(buffer_bytes, 1);
3935 if (stream->userBuffer ==
NULL)
3939 if ( stream->doConvertBuffer[mode] ) {
3942 bool makeBuffer =
true;
3943 if ( mode == OUTPUT )
3944 buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
3946 buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
3947 if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
3948 long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
3949 if ( buffer_bytes < bytes_out ) makeBuffer =
false;
3954 buffer_bytes *= *bufferSize;
3955 if (stream->deviceBuffer) free(stream->deviceBuffer);
3956 stream->deviceBuffer = (
char *) calloc(buffer_bytes, 1);
3957 if (stream->deviceBuffer ==
NULL)
3962 stream->device[mode] = device;
3963 stream->state = STREAM_STOPPED;
3964 if ( stream->mode == OUTPUT && mode == INPUT )
3966 stream->mode = DUPLEX;
3968 stream->mode = mode;
3969 stream->sampleRate = sampleRate;
3970 asioCallbackInfo = &stream->callbackInfo;
3971 stream->callbackInfo.
object = (
void *)
this;
3972 stream->callbackInfo.waitTime = (
unsigned long) (200.0 * stream->bufferSize / stream->sampleRate);
3977 ASIODisposeBuffers();
3978 drivers.removeCurrentDriver();
3980 if (stream->callbackInfo.buffers)
3981 free(stream->callbackInfo.buffers);
3982 stream->callbackInfo.buffers = 0;
3984 if (stream->userBuffer) {
3985 free(stream->userBuffer);
3986 stream->userBuffer = 0;
3988 sprintf(message,
"RtAudio: error allocating buffer memory (%s).",
3989 devices[device].name);
3996 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
3998 if (stream->callbackInfo.usingCallback) {
4000 if (stream->state == STREAM_RUNNING)
4005 stream->callbackInfo.usingCallback =
false;
4006 stream->callbackInfo.userData =
NULL;
4007 stream->state = STREAM_STOPPED;
4008 stream->callbackInfo.callback =
NULL;
4019 if ( streams.find( streamId ) == streams.end() ) {
4020 sprintf(message,
"RtAudio: invalid stream identifier!");
4025 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
4027 if (stream->state == STREAM_RUNNING)
4030 ASIODisposeBuffers();
4032 drivers.removeCurrentDriver();
4034 DeleteCriticalSection(&stream->mutex);
4036 if (stream->callbackInfo.buffers)
4037 free(stream->callbackInfo.buffers);
4039 if (stream->userBuffer)
4040 free(stream->userBuffer);
4042 if (stream->deviceBuffer)
4043 free(stream->deviceBuffer);
4046 streams.erase(streamId);
4051 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
4055 if (stream->state == STREAM_RUNNING) {
4060 stream->callbackInfo.blockTick =
true;
4061 stream->callbackInfo.stopStream =
false;
4062 stream->callbackInfo.streamId = streamId;
4063 ASIOError result = ASIOStart();
4064 if ( result != ASE_OK ) {
4065 sprintf(message,
"RtAudio: ASIO error starting device (%s).",
4066 devices[stream->device[0]].name);
4070 stream->state = STREAM_RUNNING;
4077 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
4081 if (stream->state == STREAM_STOPPED) {
4086 ASIOError result = ASIOStop();
4087 if ( result != ASE_OK ) {
4088 sprintf(message,
"RtAudio: ASIO error stopping device (%s).",
4089 devices[stream->device[0]].name);
4093 stream->state = STREAM_STOPPED;
4106 sprintf(message,
"RtAudio: streamWillBlock() cannot be implemented for ASIO.");
4113 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
4115 if (stream->state == STREAM_STOPPED)
4118 if (stream->callbackInfo.usingCallback) {
4119 sprintf(message,
"RtAudio: tickStream() should not be used when a callback function is set!");
4125 while ( stream->callbackInfo.blockTick )
4126 Sleep(stream->callbackInfo.waitTime);
4130 stream->callbackInfo.blockTick =
true;
4135 void RtAudio :: callbackEvent(
int streamId,
int bufferIndex,
void *inData,
void *outData)
4137 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
4159 if ( callback(stream->userBuffer, stream->bufferSize, info->
userData) )
4163 int nChannels = stream->nDeviceChannels[0] + stream->nDeviceChannels[1];
4165 ASIOBufferInfo *bufferInfos = (ASIOBufferInfo *) info->
buffers;
4166 if ( stream->mode == OUTPUT || stream->mode == DUPLEX ) {
4168 bufferBytes = stream->bufferSize * formatBytes(stream->deviceFormat[0]);
4169 if (stream->doConvertBuffer[0]) {
4171 convertStreamBuffer(stream, OUTPUT);
4172 if ( stream->doByteSwap[0] )
4173 byteSwapBuffer(stream->deviceBuffer,
4174 stream->bufferSize * stream->nDeviceChannels[0],
4175 stream->deviceFormat[0]);
4178 for (
int i=0; i<stream->nDeviceChannels[0]; i++, bufferInfos++ ) {
4179 memcpy(bufferInfos->buffers[bufferIndex],
4180 &stream->deviceBuffer[i*bufferBytes], bufferBytes );
4185 if (stream->doByteSwap[0])
4186 byteSwapBuffer(stream->userBuffer,
4187 stream->bufferSize * stream->nUserChannels[0],
4188 stream->userFormat);
4190 memcpy(bufferInfos->buffers[bufferIndex], stream->userBuffer, bufferBytes );
4194 if ( stream->mode == INPUT || stream->mode == DUPLEX ) {
4196 bufferBytes = stream->bufferSize * formatBytes(stream->deviceFormat[1]);
4197 if (stream->doConvertBuffer[1]) {
4200 for (
int i=0; i<stream->nDeviceChannels[1]; i++, bufferInfos++ )
4201 memcpy(&stream->deviceBuffer[i*bufferBytes], bufferInfos->buffers[bufferIndex], bufferBytes );
4203 if ( stream->doByteSwap[1] )
4204 byteSwapBuffer(stream->deviceBuffer,
4205 stream->bufferSize * stream->nDeviceChannels[1],
4206 stream->deviceFormat[1]);
4207 convertStreamBuffer(stream, INPUT);
4211 memcpy(stream->userBuffer, bufferInfos->buffers[bufferIndex], bufferBytes );
4213 if (stream->doByteSwap[1])
4214 byteSwapBuffer(stream->userBuffer,
4215 stream->bufferSize * stream->nUserChannels[1],
4216 stream->userFormat);
4228 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
4230 stream->callbackInfo.callback = (
void *) callback;
4231 stream->callbackInfo.userData = userData;
4232 stream->callbackInfo.usingCallback =
true;
4237 #elif defined(__WINDOWS_DS__) // Windows DirectSound API
4243 static bool CALLBACK deviceCountCallback(LPGUID lpguid,
4244 LPCSTR lpcstrDescription,
4245 LPCSTR lpcstrModule,
4248 static bool CALLBACK deviceInfoCallback(LPGUID lpguid,
4249 LPCSTR lpcstrDescription,
4250 LPCSTR lpcstrModule,
4253 static bool CALLBACK defaultDeviceCallback(LPGUID lpguid,
4254 LPCSTR lpcstrDescription,
4255 LPCSTR lpcstrModule,
4258 static bool CALLBACK deviceIdCallback(LPGUID lpguid,
4259 LPCSTR lpcstrDescription,
4260 LPCSTR lpcstrModule,
4263 static char* getErrorString(
int code);
4272 int RtAudio :: getDefaultInputDevice(
void)
4275 info.name[0] =
'\0';
4278 HRESULT result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)defaultDeviceCallback, &info);
4279 if ( FAILED(result) ) {
4280 sprintf(message,
"RtAudio: Error performing default input device enumeration: %s.",
4281 getErrorString(result));
4286 for (
int i=0; i<nDevices; i++ )
4287 if ( strncmp( devices[i].name, info.name, 64 ) == 0 )
return i;
4292 int RtAudio :: getDefaultOutputDevice(
void)
4295 info.name[0] =
'\0';
4298 HRESULT result = DirectSoundEnumerate((LPDSENUMCALLBACK)defaultDeviceCallback, &info);
4299 if ( FAILED(result) ) {
4300 sprintf(message,
"RtAudio: Error performing default output device enumeration: %s.",
4301 getErrorString(result));
4306 for (
int i=0; i<nDevices; i++ )
4307 if ( strncmp(devices[i].name, info.name, 64 ) == 0 )
return i;
4312 void RtAudio :: initialize(
void)
4314 int i, ins = 0, outs = 0, count = 0;
4319 result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceCountCallback, &outs);
4320 if ( FAILED(result) ) {
4321 sprintf(message,
"RtAudio: Unable to enumerate through sound playback devices: %s.",
4322 getErrorString(result));
4327 result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceCountCallback, &ins);
4328 if ( FAILED(result) ) {
4329 sprintf(message,
"RtAudio: Unable to enumerate through sound capture devices: %s.",
4330 getErrorString(result));
4335 if (count == 0)
return;
4337 std::vector<enum_info> info(count);
4338 for (i=0; i<count; i++) {
4339 info[i].name[0] =
'\0';
4340 if (i < outs) info[i].isInput =
false;
4341 else info[i].isInput =
true;
4345 result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceInfoCallback, &info[0]);
4346 if ( FAILED(result) ) {
4347 sprintf(message,
"RtAudio: Unable to enumerate through sound playback devices: %s.",
4348 getErrorString(result));
4353 result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceInfoCallback, &info[0]);
4354 if ( FAILED(result) ) {
4355 sprintf(message,
"RtAudio: Unable to enumerate through sound capture devices: %s.",
4356 getErrorString(result));
4363 for (i=0; i<count; i++)
4364 if ( info[i].isValid ) nDevices++;
4366 if (nDevices == 0)
return;
4369 devices = (RTAUDIO_DEVICE *) calloc(nDevices,
sizeof(RTAUDIO_DEVICE));
4370 if (devices ==
NULL) {
4371 sprintf(message,
"RtAudio: memory allocation error!");
4377 for (i=0; i<count; i++) {
4378 if ( info[i].isValid )
4379 strncpy(devices[index++].name, info[i].name, 64);
4388 void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
4391 strncpy( dsinfo.name, info->name, 64 );
4392 dsinfo.isValid =
false;
4395 HRESULT result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo);
4396 if ( FAILED(result) ) {
4397 sprintf(message,
"RtAudio: Error performing input device id enumeration: %s.",
4398 getErrorString(result));
4404 if ( dsinfo.isValid ==
false )
4405 goto playback_probe;
4407 LPDIRECTSOUNDCAPTURE input;
4408 result = DirectSoundCaptureCreate( dsinfo.id, &input,
NULL );
4409 if ( FAILED(result) ) {
4410 sprintf(message,
"RtAudio: Could not create DirectSound capture object (%s): %s.",
4411 info->name, getErrorString(result));
4413 goto playback_probe;
4417 in_caps.dwSize =
sizeof(in_caps);
4418 result = input->GetCaps( &in_caps );
4419 if ( FAILED(result) ) {
4421 sprintf(message,
"RtAudio: Could not get DirectSound capture capabilities (%s): %s.",
4422 info->name, getErrorString(result));
4424 goto playback_probe;
4428 info->minInputChannels = 1;
4429 info->maxInputChannels = in_caps.dwChannels;
4432 if( in_caps.dwChannels == 2 ) {
4433 if( in_caps.dwFormats & WAVE_FORMAT_1S16 ) info->nativeFormats |=
RTAUDIO_SINT16;
4434 if( in_caps.dwFormats & WAVE_FORMAT_2S16 ) info->nativeFormats |=
RTAUDIO_SINT16;
4435 if( in_caps.dwFormats & WAVE_FORMAT_4S16 ) info->nativeFormats |=
RTAUDIO_SINT16;
4436 if( in_caps.dwFormats & WAVE_FORMAT_1S08 ) info->nativeFormats |=
RTAUDIO_SINT8;
4437 if( in_caps.dwFormats & WAVE_FORMAT_2S08 ) info->nativeFormats |=
RTAUDIO_SINT8;
4438 if( in_caps.dwFormats & WAVE_FORMAT_4S08 ) info->nativeFormats |=
RTAUDIO_SINT8;
4441 if( in_caps.dwFormats & WAVE_FORMAT_1S16 ) info->sampleRates[info->nSampleRates++] = 11025;
4442 if( in_caps.dwFormats & WAVE_FORMAT_2S16 ) info->sampleRates[info->nSampleRates++] = 22050;
4443 if( in_caps.dwFormats & WAVE_FORMAT_4S16 ) info->sampleRates[info->nSampleRates++] = 44100;
4446 if( in_caps.dwFormats & WAVE_FORMAT_1S08 ) info->sampleRates[info->nSampleRates++] = 11025;
4447 if( in_caps.dwFormats & WAVE_FORMAT_2S08 ) info->sampleRates[info->nSampleRates++] = 22050;
4448 if( in_caps.dwFormats & WAVE_FORMAT_4S08 ) info->sampleRates[info->nSampleRates++] = 44100;
4451 else if ( in_caps.dwChannels == 1 ) {
4452 if( in_caps.dwFormats & WAVE_FORMAT_1M16 ) info->nativeFormats |=
RTAUDIO_SINT16;
4453 if( in_caps.dwFormats & WAVE_FORMAT_2M16 ) info->nativeFormats |=
RTAUDIO_SINT16;
4454 if( in_caps.dwFormats & WAVE_FORMAT_4M16 ) info->nativeFormats |=
RTAUDIO_SINT16;
4455 if( in_caps.dwFormats & WAVE_FORMAT_1M08 ) info->nativeFormats |=
RTAUDIO_SINT8;
4456 if( in_caps.dwFormats & WAVE_FORMAT_2M08 ) info->nativeFormats |=
RTAUDIO_SINT8;
4457 if( in_caps.dwFormats & WAVE_FORMAT_4M08 ) info->nativeFormats |=
RTAUDIO_SINT8;
4460 if( in_caps.dwFormats & WAVE_FORMAT_1M16 ) info->sampleRates[info->nSampleRates++] = 11025;
4461 if( in_caps.dwFormats & WAVE_FORMAT_2M16 ) info->sampleRates[info->nSampleRates++] = 22050;
4462 if( in_caps.dwFormats & WAVE_FORMAT_4M16 ) info->sampleRates[info->nSampleRates++] = 44100;
4465 if( in_caps.dwFormats & WAVE_FORMAT_1M08 ) info->sampleRates[info->nSampleRates++] = 11025;
4466 if( in_caps.dwFormats & WAVE_FORMAT_2M08 ) info->sampleRates[info->nSampleRates++] = 22050;
4467 if( in_caps.dwFormats & WAVE_FORMAT_4M08 ) info->sampleRates[info->nSampleRates++] = 44100;
4470 else info->minInputChannels = 0;
4476 dsinfo.isValid =
false;
4479 result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo);
4480 if ( FAILED(result) ) {
4481 sprintf(message,
"RtAudio: Error performing output device id enumeration: %s.",
4482 getErrorString(result));
4488 if ( dsinfo.isValid ==
false )
4489 goto check_parameters;
4491 LPDIRECTSOUND output;
4493 result = DirectSoundCreate( dsinfo.id, &output,
NULL );
4494 if ( FAILED(result) ) {
4495 sprintf(message,
"RtAudio: Could not create DirectSound playback object (%s): %s.",
4496 info->name, getErrorString(result));
4498 goto check_parameters;
4501 out_caps.dwSize =
sizeof(out_caps);
4502 result = output->GetCaps( &out_caps );
4503 if ( FAILED(result) ) {
4505 sprintf(message,
"RtAudio: Could not get DirectSound playback capabilities (%s): %s.",
4506 info->name, getErrorString(result));
4508 goto check_parameters;
4512 info->minOutputChannels = 1;
4513 info->maxOutputChannels = ( out_caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1;
4517 if ( info->nSampleRates == 0 ) {
4518 info->sampleRates[0] = (int) out_caps.dwMinSecondarySampleRate;
4519 info->sampleRates[1] = (
int) out_caps.dwMaxSecondarySampleRate;
4520 if ( out_caps.dwFlags & DSCAPS_CONTINUOUSRATE )
4521 info->nSampleRates = -1;
4522 else if ( out_caps.dwMinSecondarySampleRate == out_caps.dwMaxSecondarySampleRate ) {
4523 if ( out_caps.dwMinSecondarySampleRate == 0 ) {
4526 info->sampleRates[0] = 11025;
4527 info->sampleRates[1] = 48000;
4528 info->nSampleRates = -1;
4529 sprintf(message,
"RtAudio: bogus sample rates reported by DirectSound driver ... using defaults (%s).",
4534 info->nSampleRates = 1;
4537 else if ( (out_caps.dwMinSecondarySampleRate < 1000.0) &&
4538 (out_caps.dwMaxSecondarySampleRate > 50000.0) ) {
4541 info->nSampleRates = -1;
4542 sprintf(message,
"RtAudio: bogus sample rates reported by DirectSound driver ... using range (%s).",
4546 else info->nSampleRates = 2;
4550 for (
int i=info->nSampleRates-1; i>=0; i-- ) {
4551 if ( info->sampleRates[i] <= out_caps.dwMaxSecondarySampleRate )
4553 info->nSampleRates--;
4555 while ( info->sampleRates[0] < out_caps.dwMinSecondarySampleRate ) {
4556 info->nSampleRates--;
4557 for (
int i=0; i<info->nSampleRates; i++)
4558 info->sampleRates[i] = info->sampleRates[i+1];
4559 if ( info->nSampleRates <= 0 )
break;
4564 if ( out_caps.dwFlags & DSCAPS_PRIMARY16BIT ) info->nativeFormats |=
RTAUDIO_SINT16;
4565 if ( out_caps.dwFlags & DSCAPS_PRIMARY8BIT ) info->nativeFormats |=
RTAUDIO_SINT8;
4570 if ( info->maxInputChannels == 0 && info->maxOutputChannels == 0 )
4572 if ( info->nSampleRates == 0 || info->nativeFormats == 0 )
4576 if (info->maxInputChannels < info->maxOutputChannels)
4577 info->maxDuplexChannels = info->maxInputChannels;
4579 info->maxDuplexChannels = info->maxOutputChannels;
4580 if (info->minInputChannels < info->minOutputChannels)
4581 info->minDuplexChannels = info->minInputChannels;
4583 info->minDuplexChannels = info->minOutputChannels;
4585 if ( info->maxDuplexChannels > 0 ) info->hasDuplexSupport =
true;
4586 else info->hasDuplexSupport =
false;
4588 info->probed =
true;
4593 bool RtAudio :: probeDeviceOpen(
int device, RTAUDIO_STREAM *stream,
4594 STREAM_MODE mode,
int channels,
4595 int sampleRate, RTAUDIO_FORMAT format,
4596 int *bufferSize,
int numberOfBuffers)
4599 HWND hWnd = GetForegroundWindow();
4614 if (numberOfBuffers < 2)
4617 nBuffers = numberOfBuffers;
4620 WAVEFORMATEX waveFormat;
4621 ZeroMemory(&waveFormat,
sizeof(WAVEFORMATEX));
4622 waveFormat.wFormatTag = WAVE_FORMAT_PCM;
4623 waveFormat.nChannels = channels;
4624 waveFormat.nSamplesPerSec = (
unsigned long) sampleRate;
4627 if ( devices[device].nativeFormats ) {
4630 waveFormat.wBitsPerSample = 8;
4632 waveFormat.wBitsPerSample = 16;
4636 waveFormat.wBitsPerSample = 16;
4638 waveFormat.wBitsPerSample = 8;
4642 sprintf(message,
"RtAudio: no reported data formats for DirectSound device (%s).",
4643 devices[device].name);
4648 waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
4649 waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
4652 strncpy( dsinfo.name, devices[device].name, 64 );
4653 dsinfo.isValid =
false;
4654 if ( mode == OUTPUT ) {
4656 if ( devices[device].maxOutputChannels < channels )
4660 result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo);
4661 if ( FAILED(result) ) {
4662 sprintf(message,
"RtAudio: Error performing output device id enumeration: %s.",
4663 getErrorString(result));
4668 if ( dsinfo.isValid ==
false ) {
4669 sprintf(message,
"RtAudio: DS output device (%s) id not found!", devices[device].name);
4674 LPGUID
id = dsinfo.id;
4675 LPDIRECTSOUND object;
4676 LPDIRECTSOUNDBUFFER buffer;
4677 DSBUFFERDESC bufferDescription;
4679 result = DirectSoundCreate(
id, &
object,
NULL );
4680 if ( FAILED(result) ) {
4681 sprintf(message,
"RtAudio: Could not create DirectSound playback object (%s): %s.",
4682 devices[device].name, getErrorString(result));
4688 result =
object->SetCooperativeLevel(hWnd, DSSCL_EXCLUSIVE);
4689 if ( FAILED(result) ) {
4691 sprintf(message,
"RtAudio: Unable to set DirectSound cooperative level (%s): %s.",
4692 devices[device].name, getErrorString(result));
4701 ZeroMemory(&bufferDescription,
sizeof(DSBUFFERDESC));
4702 bufferDescription.dwSize =
sizeof(DSBUFFERDESC);
4703 bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;
4705 result =
object->CreateSoundBuffer(&bufferDescription, &buffer,
NULL);
4706 if ( FAILED(result) ) {
4708 sprintf(message,
"RtAudio: Unable to access DS primary buffer (%s): %s.",
4709 devices[device].name, getErrorString(result));
4715 result = buffer->SetFormat(&waveFormat);
4716 if ( FAILED(result) ) {
4718 sprintf(message,
"RtAudio: Unable to set DS primary buffer format (%s): %s.",
4719 devices[device].name, getErrorString(result));
4725 buffer_size = channels * *bufferSize * nBuffers * waveFormat.wBitsPerSample / 8;
4726 ZeroMemory(&bufferDescription,
sizeof(DSBUFFERDESC));
4727 bufferDescription.dwSize =
sizeof(DSBUFFERDESC);
4728 bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
4729 DSBCAPS_GETCURRENTPOSITION2 |
4730 DSBCAPS_LOCHARDWARE );
4731 bufferDescription.dwBufferBytes = buffer_size;
4732 bufferDescription.lpwfxFormat = &waveFormat;
4736 result =
object->CreateSoundBuffer(&bufferDescription, &buffer,
NULL);
4737 if ( FAILED(result) ) {
4738 bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
4739 DSBCAPS_GETCURRENTPOSITION2 |
4740 DSBCAPS_LOCSOFTWARE );
4741 result =
object->CreateSoundBuffer(&bufferDescription, &buffer,
NULL);
4742 if ( FAILED(result) ) {
4744 sprintf(message,
"RtAudio: Unable to create secondary DS buffer (%s): %s.",
4745 devices[device].name, getErrorString(result));
4753 dsbcaps.dwSize =
sizeof(DSBCAPS);
4754 buffer->GetCaps(&dsbcaps);
4755 buffer_size = dsbcaps.dwBufferBytes;
4758 result = buffer->Lock(0, buffer_size, &audioPtr, &dataLen,
NULL,
NULL, 0);
4759 if ( FAILED(result) ) {
4761 sprintf(message,
"RtAudio: Unable to lock DS buffer (%s): %s.",
4762 devices[device].name, getErrorString(result));
4768 ZeroMemory(audioPtr, dataLen);
4771 result = buffer->Unlock(audioPtr, dataLen,
NULL, 0);
4772 if ( FAILED(result) ) {
4774 sprintf(message,
"RtAudio: Unable to unlock DS buffer(%s): %s.",
4775 devices[device].name, getErrorString(result));
4780 stream->handle[0].object = (
void *)
object;
4781 stream->handle[0].buffer = (
void *) buffer;
4782 stream->nDeviceChannels[0] = channels;
4785 if ( mode == INPUT ) {
4787 if ( devices[device].maxInputChannels < channels )
4791 result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo);
4792 if ( FAILED(result) ) {
4793 sprintf(message,
"RtAudio: Error performing input device id enumeration: %s.",
4794 getErrorString(result));
4799 if ( dsinfo.isValid ==
false ) {
4800 sprintf(message,
"RtAudio: DS input device (%s) id not found!", devices[device].name);
4805 LPGUID
id = dsinfo.id;
4806 LPDIRECTSOUNDCAPTURE object;
4807 LPDIRECTSOUNDCAPTUREBUFFER buffer;
4808 DSCBUFFERDESC bufferDescription;
4810 result = DirectSoundCaptureCreate(
id, &
object,
NULL );
4811 if ( FAILED(result) ) {
4812 sprintf(message,
"RtAudio: Could not create DirectSound capture object (%s): %s.",
4813 devices[device].name, getErrorString(result));
4819 buffer_size = channels * *bufferSize * nBuffers * waveFormat.wBitsPerSample / 8;
4820 ZeroMemory(&bufferDescription,
sizeof(DSCBUFFERDESC));
4821 bufferDescription.dwSize =
sizeof(DSCBUFFERDESC);
4822 bufferDescription.dwFlags = 0;
4823 bufferDescription.dwReserved = 0;
4824 bufferDescription.dwBufferBytes = buffer_size;
4825 bufferDescription.lpwfxFormat = &waveFormat;
4828 result =
object->CreateCaptureBuffer(&bufferDescription, &buffer,
NULL);
4829 if ( FAILED(result) ) {
4831 sprintf(message,
"RtAudio: Unable to create DS capture buffer (%s): %s.",
4832 devices[device].name, getErrorString(result));
4838 result = buffer->Lock(0, buffer_size, &audioPtr, &dataLen,
NULL,
NULL, 0);
4839 if ( FAILED(result) ) {
4841 sprintf(message,
"RtAudio: Unable to lock DS capture buffer (%s): %s.",
4842 devices[device].name, getErrorString(result));
4848 ZeroMemory(audioPtr, dataLen);
4851 result = buffer->Unlock(audioPtr, dataLen,
NULL, 0);
4852 if ( FAILED(result) ) {
4854 sprintf(message,
"RtAudio: Unable to unlock DS capture buffer (%s): %s.",
4855 devices[device].name, getErrorString(result));
4860 stream->handle[1].object = (
void *)
object;
4861 stream->handle[1].buffer = (
void *) buffer;
4862 stream->nDeviceChannels[1] = channels;
4865 stream->userFormat = format;
4866 if ( waveFormat.wBitsPerSample == 8 )
4870 stream->nUserChannels[mode] = channels;
4871 *bufferSize = buffer_size / (channels * nBuffers * waveFormat.wBitsPerSample / 8);
4872 stream->bufferSize = *bufferSize;
4875 stream->doConvertBuffer[mode] =
false;
4876 if (stream->userFormat != stream->deviceFormat[mode])
4877 stream->doConvertBuffer[mode] =
true;
4878 if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
4879 stream->doConvertBuffer[mode] =
true;
4882 if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
4885 if (stream->nUserChannels[0] >= stream->nUserChannels[1])
4886 buffer_bytes = stream->nUserChannels[0];
4888 buffer_bytes = stream->nUserChannels[1];
4890 buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
4891 if (stream->userBuffer) free(stream->userBuffer);
4892 stream->userBuffer = (
char *) calloc(buffer_bytes, 1);
4893 if (stream->userBuffer ==
NULL)
4897 if ( stream->doConvertBuffer[mode] ) {
4900 bool makeBuffer =
true;
4901 if ( mode == OUTPUT )
4902 buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
4904 buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
4905 if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
4906 long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
4907 if ( buffer_bytes < bytes_out ) makeBuffer =
false;
4912 buffer_bytes *= *bufferSize;
4913 if (stream->deviceBuffer) free(stream->deviceBuffer);
4914 stream->deviceBuffer = (
char *) calloc(buffer_bytes, 1);
4915 if (stream->deviceBuffer ==
NULL)
4920 stream->device[mode] = device;
4921 stream->state = STREAM_STOPPED;
4922 if ( stream->mode == OUTPUT && mode == INPUT )
4924 stream->mode = DUPLEX;
4926 stream->mode = mode;
4927 stream->nBuffers = nBuffers;
4928 stream->sampleRate = sampleRate;
4933 if (stream->handle[0].object) {
4934 LPDIRECTSOUND
object = (LPDIRECTSOUND) stream->handle[0].object;
4935 LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
4938 stream->handle[0].buffer =
NULL;
4941 stream->handle[0].object =
NULL;
4943 if (stream->handle[1].object) {
4944 LPDIRECTSOUNDCAPTURE
object = (LPDIRECTSOUNDCAPTURE) stream->handle[1].object;
4945 LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
4948 stream->handle[1].buffer =
NULL;
4951 stream->handle[1].object =
NULL;
4953 if (stream->userBuffer) {
4954 free(stream->userBuffer);
4955 stream->userBuffer = 0;
4957 sprintf(message,
"RtAudio: error allocating buffer memory (%s).",
4958 devices[device].name);
4965 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
4967 if (stream->callbackInfo.usingCallback) {
4969 if (stream->state == STREAM_RUNNING)
4974 stream->callbackInfo.usingCallback =
false;
4975 WaitForSingleObject( (HANDLE)stream->callbackInfo.thread, INFINITE );
4976 CloseHandle( (HANDLE)stream->callbackInfo.thread );
4977 stream->callbackInfo.thread = 0;
4978 stream->callbackInfo.callback =
NULL;
4979 stream->callbackInfo.userData =
NULL;
4990 if ( streams.find( streamId ) == streams.end() ) {
4991 sprintf(message,
"RtAudio: invalid stream identifier!");
4996 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
4998 if (stream->callbackInfo.usingCallback) {
4999 stream->callbackInfo.usingCallback =
false;
5000 WaitForSingleObject( (HANDLE)stream->callbackInfo.thread, INFINITE );
5001 CloseHandle( (HANDLE)stream->callbackInfo.thread );
5004 DeleteCriticalSection(&stream->mutex);
5006 if (stream->handle[0].object) {
5007 LPDIRECTSOUND
object = (LPDIRECTSOUND) stream->handle[0].object;
5008 LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
5016 if (stream->handle[1].object) {
5017 LPDIRECTSOUNDCAPTURE
object = (LPDIRECTSOUNDCAPTURE) stream->handle[1].object;
5018 LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
5026 if (stream->userBuffer)
5027 free(stream->userBuffer);
5029 if (stream->deviceBuffer)
5030 free(stream->deviceBuffer);
5033 streams.erase(streamId);
5038 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
5042 if (stream->state == STREAM_RUNNING)
5046 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
5047 LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
5048 result = buffer->Play(0, 0, DSBPLAY_LOOPING );
5049 if ( FAILED(result) ) {
5050 sprintf(message,
"RtAudio: Unable to start DS buffer (%s): %s.",
5051 devices[stream->device[0]].name, getErrorString(result));
5056 if (stream->mode == INPUT || stream->mode == DUPLEX) {
5057 LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
5058 result = buffer->Start(DSCBSTART_LOOPING );
5059 if ( FAILED(result) ) {
5060 sprintf(message,
"RtAudio: Unable to start DS capture buffer (%s): %s.",
5061 devices[stream->device[1]].name, getErrorString(result));
5065 stream->state = STREAM_RUNNING;
5073 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
5077 if (stream->state == STREAM_STOPPED) {
5089 LPVOID buffer1 =
NULL;
5090 LPVOID buffer2 =
NULL;
5091 DWORD bufferSize1 = 0;
5092 DWORD bufferSize2 = 0;
5093 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
5095 DWORD currentPos, safePos;
5096 long buffer_bytes = stream->bufferSize * stream->nDeviceChannels[0];
5097 buffer_bytes *= formatBytes(stream->deviceFormat[0]);
5099 LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
5100 UINT nextWritePos = stream->handle[0].bufferPointer;
5101 dsBufferSize = buffer_bytes * stream->nBuffers;
5104 for (
int i=0; i<stream->nBuffers; i++) {
5107 result = dsBuffer->GetCurrentPosition(¤tPos, &safePos);
5108 if ( FAILED(result) ) {
5109 sprintf(message,
"RtAudio: Unable to get current DS position (%s): %s.",
5110 devices[stream->device[0]].name, getErrorString(result));
5114 if ( currentPos < nextWritePos ) currentPos += dsBufferSize;
5115 DWORD endWrite = nextWritePos + buffer_bytes;
5118 while ( currentPos < endWrite ) {
5119 float millis = (endWrite - currentPos) * 900.0;
5120 millis /= ( formatBytes(stream->deviceFormat[0]) * stream->sampleRate);
5121 if ( millis < 1.0 ) millis = 1.0;
5122 Sleep( (DWORD) millis );
5125 result = dsBuffer->GetCurrentPosition( ¤tPos, &safePos );
5126 if ( FAILED(result) ) {
5127 sprintf(message,
"RtAudio: Unable to get current DS position (%s): %s.",
5128 devices[stream->device[0]].name, getErrorString(result));
5131 if ( currentPos < nextWritePos ) currentPos += dsBufferSize;
5135 result = dsBuffer->Lock (nextWritePos, buffer_bytes, &buffer1,
5136 &bufferSize1, &buffer2, &bufferSize2, 0);
5137 if ( FAILED(result) ) {
5138 sprintf(message,
"RtAudio: Unable to lock DS buffer during playback (%s): %s.",
5139 devices[stream->device[0]].name, getErrorString(result));
5144 ZeroMemory(buffer1, bufferSize1);
5145 if (buffer2 !=
NULL) ZeroMemory(buffer2, bufferSize2);
5148 dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2);
5149 if ( FAILED(result) ) {
5150 sprintf(message,
"RtAudio: Unable to unlock DS buffer during playback (%s): %s.",
5151 devices[stream->device[0]].name, getErrorString(result));
5154 nextWritePos = (nextWritePos + bufferSize1 + bufferSize2) % dsBufferSize;
5155 stream->handle[0].bufferPointer = nextWritePos;
5159 stream->handle[0].bufferPointer = 0;
5162 if (stream->mode == INPUT || stream->mode == DUPLEX) {
5163 LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
5167 result = buffer->Stop();
5168 if ( FAILED(result) ) {
5169 sprintf(message,
"RtAudio: Unable to stop DS capture buffer (%s): %s",
5170 devices[stream->device[1]].name, getErrorString(result));
5174 dsBufferSize = stream->bufferSize * stream->nDeviceChannels[1];
5175 dsBufferSize *= formatBytes(stream->deviceFormat[1]) * stream->nBuffers;
5179 result = buffer->Lock(0, dsBufferSize, &buffer1, &bufferSize1,
NULL,
NULL, 0);
5180 if ( FAILED(result) ) {
5181 sprintf(message,
"RtAudio: Unable to lock DS capture buffer (%s): %s.",
5182 devices[stream->device[1]].name, getErrorString(result));
5187 ZeroMemory(buffer1, bufferSize1);
5190 result = buffer->Unlock(buffer1, bufferSize1,
NULL, 0);
5191 if ( FAILED(result) ) {
5192 sprintf(message,
"RtAudio: Unable to unlock DS capture buffer (%s): %s.",
5193 devices[stream->device[1]].name, getErrorString(result));
5198 stream->handle[1].bufferPointer = 0;
5200 stream->state = STREAM_STOPPED;
5207 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
5211 if (stream->state == STREAM_STOPPED)
5218 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
5219 LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
5220 result = buffer->Stop();
5221 if ( FAILED(result) ) {
5222 sprintf(message,
"RtAudio: Unable to stop DS buffer (%s): %s",
5223 devices[stream->device[0]].name, getErrorString(result));
5227 dsBufferSize = stream->bufferSize * stream->nDeviceChannels[0];
5228 dsBufferSize *= formatBytes(stream->deviceFormat[0]) * stream->nBuffers;
5232 result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen,
NULL,
NULL, 0);
5233 if ( FAILED(result) ) {
5234 sprintf(message,
"RtAudio: Unable to lock DS buffer (%s): %s.",
5235 devices[stream->device[0]].name, getErrorString(result));
5240 ZeroMemory(audioPtr, dataLen);
5243 result = buffer->Unlock(audioPtr, dataLen,
NULL, 0);
5244 if ( FAILED(result) ) {
5245 sprintf(message,
"RtAudio: Unable to unlock DS buffer (%s): %s.",
5246 devices[stream->device[0]].name, getErrorString(result));
5251 stream->handle[0].bufferPointer = 0;
5254 if (stream->mode == INPUT || stream->mode == DUPLEX) {
5255 LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
5259 result = buffer->Stop();
5260 if ( FAILED(result) ) {
5261 sprintf(message,
"RtAudio: Unable to stop DS capture buffer (%s): %s",
5262 devices[stream->device[1]].name, getErrorString(result));
5266 dsBufferSize = stream->bufferSize * stream->nDeviceChannels[1];
5267 dsBufferSize *= formatBytes(stream->deviceFormat[1]) * stream->nBuffers;
5271 result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen,
NULL,
NULL, 0);
5272 if ( FAILED(result) ) {
5273 sprintf(message,
"RtAudio: Unable to lock DS capture buffer (%s): %s.",
5274 devices[stream->device[1]].name, getErrorString(result));
5279 ZeroMemory(audioPtr, dataLen);
5282 result = buffer->Unlock(audioPtr, dataLen,
NULL, 0);
5283 if ( FAILED(result) ) {
5284 sprintf(message,
"RtAudio: Unable to unlock DS capture buffer (%s): %s.",
5285 devices[stream->device[1]].name, getErrorString(result));
5290 stream->handle[1].bufferPointer = 0;
5292 stream->state = STREAM_STOPPED;
5300 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
5306 if (stream->state == STREAM_STOPPED)
5310 DWORD currentPos, safePos;
5312 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
5314 LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
5315 UINT nextWritePos = stream->handle[0].bufferPointer;
5316 channels = stream->nDeviceChannels[0];
5317 DWORD dsBufferSize = stream->bufferSize * channels;
5318 dsBufferSize *= formatBytes(stream->deviceFormat[0]) * stream->nBuffers;
5321 result = dsBuffer->GetCurrentPosition(¤tPos, &safePos);
5322 if ( FAILED(result) ) {
5323 sprintf(message,
"RtAudio: Unable to get current DS position (%s): %s.",
5324 devices[stream->device[0]].name, getErrorString(result));
5328 if ( currentPos < nextWritePos ) currentPos += dsBufferSize;
5329 frames = currentPos - nextWritePos;
5330 frames /= channels * formatBytes(stream->deviceFormat[0]);
5333 if (stream->mode == INPUT || stream->mode == DUPLEX) {
5335 LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
5336 UINT nextReadPos = stream->handle[1].bufferPointer;
5337 channels = stream->nDeviceChannels[1];
5338 DWORD dsBufferSize = stream->bufferSize * channels;
5339 dsBufferSize *= formatBytes(stream->deviceFormat[1]) * stream->nBuffers;
5342 result = dsBuffer->GetCurrentPosition(¤tPos, &safePos);
5343 if ( FAILED(result) ) {
5344 sprintf(message,
"RtAudio: Unable to get current DS capture position (%s): %s.",
5345 devices[stream->device[1]].name, getErrorString(result));
5349 if ( safePos < nextReadPos ) safePos += dsBufferSize;
5351 if (stream->mode == DUPLEX ) {
5353 int temp = safePos - nextReadPos;
5354 temp /= channels * formatBytes(stream->deviceFormat[1]);
5355 frames = ( temp > frames ) ? temp : frames;
5358 frames = safePos - nextReadPos;
5359 frames /= channels * formatBytes(stream->deviceFormat[1]);
5363 frames = stream->bufferSize - frames;
5364 if (frames < 0) frames = 0;
5373 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
5376 if (stream->state == STREAM_STOPPED) {
5377 if (stream->callbackInfo.usingCallback) Sleep(50);
5380 else if (stream->callbackInfo.usingCallback) {
5382 stopStream = callback(stream->userBuffer, stream->bufferSize, stream->callbackInfo.userData);
5388 if (stream->state == STREAM_STOPPED) {
5394 DWORD currentPos, safePos;
5395 LPVOID buffer1 =
NULL;
5396 LPVOID buffer2 =
NULL;
5397 DWORD bufferSize1 = 0;
5398 DWORD bufferSize2 = 0;
5401 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
5404 if (stream->doConvertBuffer[0]) {
5405 convertStreamBuffer(stream, OUTPUT);
5406 buffer = stream->deviceBuffer;
5407 buffer_bytes = stream->bufferSize * stream->nDeviceChannels[0];
5408 buffer_bytes *= formatBytes(stream->deviceFormat[0]);
5411 buffer = stream->userBuffer;
5412 buffer_bytes = stream->bufferSize * stream->nUserChannels[0];
5413 buffer_bytes *= formatBytes(stream->userFormat);
5418 LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
5419 UINT nextWritePos = stream->handle[0].bufferPointer;
5420 DWORD dsBufferSize = buffer_bytes * stream->nBuffers;
5423 result = dsBuffer->GetCurrentPosition(¤tPos, &safePos);
5424 if ( FAILED(result) ) {
5425 sprintf(message,
"RtAudio: Unable to get current DS position (%s): %s.",
5426 devices[stream->device[0]].name, getErrorString(result));
5430 if ( currentPos < nextWritePos ) currentPos += dsBufferSize;
5431 DWORD endWrite = nextWritePos + buffer_bytes;
5434 while ( currentPos < endWrite ) {
5444 float millis = (endWrite - currentPos) * 900.0;
5445 millis /= ( formatBytes(stream->deviceFormat[0]) * stream->sampleRate);
5446 if ( millis < 1.0 ) millis = 1.0;
5447 Sleep( (DWORD) millis );
5450 result = dsBuffer->GetCurrentPosition( ¤tPos, &safePos );
5451 if ( FAILED(result) ) {
5452 sprintf(message,
"RtAudio: Unable to get current DS position (%s): %s.",
5453 devices[stream->device[0]].name, getErrorString(result));
5456 if ( currentPos < nextWritePos ) currentPos += dsBufferSize;
5460 result = dsBuffer->Lock (nextWritePos, buffer_bytes, &buffer1,
5461 &bufferSize1, &buffer2, &bufferSize2, 0);
5462 if ( FAILED(result) ) {
5463 sprintf(message,
"RtAudio: Unable to lock DS buffer during playback (%s): %s.",
5464 devices[stream->device[0]].name, getErrorString(result));
5469 CopyMemory(buffer1, buffer, bufferSize1);
5470 if (buffer2 !=
NULL) CopyMemory(buffer2, buffer+bufferSize1, bufferSize2);
5473 dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2);
5474 if ( FAILED(result) ) {
5475 sprintf(message,
"RtAudio: Unable to unlock DS buffer during playback (%s): %s.",
5476 devices[stream->device[0]].name, getErrorString(result));
5479 nextWritePos = (nextWritePos + bufferSize1 + bufferSize2) % dsBufferSize;
5480 stream->handle[0].bufferPointer = nextWritePos;
5483 if (stream->mode == INPUT || stream->mode == DUPLEX) {
5486 if (stream->doConvertBuffer[1]) {
5487 buffer = stream->deviceBuffer;
5488 buffer_bytes = stream->bufferSize * stream->nDeviceChannels[1];
5489 buffer_bytes *= formatBytes(stream->deviceFormat[1]);
5492 buffer = stream->userBuffer;
5493 buffer_bytes = stream->bufferSize * stream->nUserChannels[1];
5494 buffer_bytes *= formatBytes(stream->userFormat);
5497 LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
5498 UINT nextReadPos = stream->handle[1].bufferPointer;
5499 DWORD dsBufferSize = buffer_bytes * stream->nBuffers;
5502 result = dsBuffer->GetCurrentPosition(¤tPos, &safePos);
5503 if ( FAILED(result) ) {
5504 sprintf(message,
"RtAudio: Unable to get current DS capture position (%s): %s.",
5505 devices[stream->device[1]].name, getErrorString(result));
5509 if ( safePos < nextReadPos ) safePos += dsBufferSize;
5510 DWORD endRead = nextReadPos + buffer_bytes;
5513 while ( safePos < endRead ) {
5515 float millis = (endRead - safePos) * 900.0;
5516 millis /= ( formatBytes(stream->deviceFormat[1]) * stream->sampleRate);
5517 if ( millis < 1.0 ) millis = 1.0;
5518 Sleep( (DWORD) millis );
5521 result = dsBuffer->GetCurrentPosition( ¤tPos, &safePos );
5522 if ( FAILED(result) ) {
5523 sprintf(message,
"RtAudio: Unable to get current DS capture position (%s): %s.",
5524 devices[stream->device[1]].name, getErrorString(result));
5528 if ( safePos < nextReadPos ) safePos += dsBufferSize;
5532 result = dsBuffer->Lock (nextReadPos, buffer_bytes, &buffer1,
5533 &bufferSize1, &buffer2, &bufferSize2, 0);
5534 if ( FAILED(result) ) {
5535 sprintf(message,
"RtAudio: Unable to lock DS buffer during capture (%s): %s.",
5536 devices[stream->device[1]].name, getErrorString(result));
5541 CopyMemory(buffer, buffer1, bufferSize1);
5542 if (buffer2 !=
NULL) CopyMemory(buffer+bufferSize1, buffer2, bufferSize2);
5545 nextReadPos = (nextReadPos + bufferSize1 + bufferSize2) % dsBufferSize;
5546 dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2);
5547 if ( FAILED(result) ) {
5548 sprintf(message,
"RtAudio: Unable to unlock DS buffer during capture (%s): %s.",
5549 devices[stream->device[1]].name, getErrorString(result));
5552 stream->handle[1].bufferPointer = nextReadPos;
5557 if (stream->doConvertBuffer[1])
5558 convertStreamBuffer(stream, INPUT);
5563 if (stream->callbackInfo.usingCallback && stopStream)
5570 extern "C" unsigned __stdcall callbackHandler(
void *ptr)
5577 while ( *usingCallback ) {
5579 object->tickStream(stream);
5582 fprintf(stderr,
"\nRtAudio: Callback thread error (%s) ... closing thread.\n\n",
5594 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
5598 sprintf(message,
"RtAudio: A callback is already set for this stream!");
5603 info->
callback = (
void *) callback;
5606 info->
object = (
void *)
this;
5610 info->
thread = _beginthreadex(
NULL, 0, &callbackHandler,
5611 &stream->callbackInfo, 0, &thread_id);
5614 sprintf(message,
"RtAudio: error starting callback thread!");
5623 static bool CALLBACK deviceCountCallback(LPGUID lpguid,
5624 LPCSTR lpcstrDescription,
5625 LPCSTR lpcstrModule,
5628 int *pointer = ((
int *) lpContext);
5634 static bool CALLBACK deviceInfoCallback(LPGUID lpguid,
5635 LPCSTR lpcstrDescription,
5636 LPCSTR lpcstrModule,
5639 enum_info *info = ((enum_info *) lpContext);
5640 while (strlen(info->name) > 0) info++;
5642 strncpy(info->name, lpcstrDescription, 64);
5646 info->isValid =
false;
5647 if (info->isInput ==
true) {
5649 LPDIRECTSOUNDCAPTURE object;
5651 hr = DirectSoundCaptureCreate( lpguid, &
object,
NULL );
5652 if( hr != DS_OK )
return true;
5654 caps.dwSize =
sizeof(caps);
5655 hr =
object->GetCaps( &caps );
5657 if (caps.dwChannels > 0 && caps.dwFormats > 0)
5658 info->isValid =
true;
5664 LPDIRECTSOUND object;
5665 hr = DirectSoundCreate( lpguid, &
object,
NULL );
5666 if( hr != DS_OK )
return true;
5668 caps.dwSize =
sizeof(caps);
5669 hr =
object->GetCaps( &caps );
5671 if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO )
5672 info->isValid =
true;
5680 static bool CALLBACK defaultDeviceCallback(LPGUID lpguid,
5681 LPCSTR lpcstrDescription,
5682 LPCSTR lpcstrModule,
5685 enum_info *info = ((enum_info *) lpContext);
5687 if ( lpguid ==
NULL ) {
5688 strncpy(info->name, lpcstrDescription, 64);
5695 static bool CALLBACK deviceIdCallback(LPGUID lpguid,
5696 LPCSTR lpcstrDescription,
5697 LPCSTR lpcstrModule,
5700 enum_info *info = ((enum_info *) lpContext);
5702 if ( strncmp( info->name, lpcstrDescription, 64 ) == 0 ) {
5704 info->isValid =
true;
5711 static char* getErrorString(
int code)
5715 case DSERR_ALLOCATED:
5716 return "Direct Sound already allocated";
5718 case DSERR_CONTROLUNAVAIL:
5719 return "Direct Sound control unavailable";
5721 case DSERR_INVALIDPARAM:
5722 return "Direct Sound invalid parameter";
5724 case DSERR_INVALIDCALL:
5725 return "Direct Sound invalid call";
5728 return "Direct Sound generic error";
5730 case DSERR_PRIOLEVELNEEDED:
5731 return "Direct Sound Priority level needed";
5733 case DSERR_OUTOFMEMORY:
5734 return "Direct Sound out of memory";
5736 case DSERR_BADFORMAT:
5737 return "Direct Sound bad format";
5739 case DSERR_UNSUPPORTED:
5740 return "Direct Sound unsupported error";
5742 case DSERR_NODRIVER:
5743 return "Direct Sound no driver error";
5745 case DSERR_ALREADYINITIALIZED:
5746 return "Direct Sound already initialized";
5748 case DSERR_NOAGGREGATION:
5749 return "Direct Sound no aggregation";
5751 case DSERR_BUFFERLOST:
5752 return "Direct Sound buffer lost";
5754 case DSERR_OTHERAPPHASPRIO:
5755 return "Direct Sound other app has priority";
5757 case DSERR_UNINITIALIZED:
5758 return "Direct Sound uninitialized";
5761 return "Direct Sound unknown error";
5767 #elif defined(__IRIX_AL__) // SGI's AL API for IRIX
5772 void RtAudio :: initialize(
void)
5778 nDevices = alQueryValues(AL_SYSTEM, AL_DEVICES, 0, 0, 0, 0);
5780 sprintf(message,
"RtAudio: AL error counting devices: %s.",
5781 alGetErrorString(oserror()));
5785 if (nDevices <= 0)
return;
5787 ALvalue *vls = (ALvalue *)
new ALvalue[nDevices];
5790 devices = (RTAUDIO_DEVICE *) calloc(nDevices,
sizeof(RTAUDIO_DEVICE));
5791 if (devices ==
NULL) {
5792 sprintf(message,
"RtAudio: memory allocation error!");
5801 pvs[0].param = AL_NAME;
5802 pvs[0].value.ptr = name;
5805 outs = alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, vls, nDevices, 0, 0);
5807 sprintf(message,
"RtAudio: AL error getting output devices: %s.",
5808 alGetErrorString(oserror()));
5812 for (i=0; i<outs; i++) {
5813 if (alGetParams(vls[i].i, pvs, 1) < 0) {
5814 sprintf(message,
"RtAudio: AL error querying output devices: %s.",
5815 alGetErrorString(oserror()));
5818 strncpy(devices[i].name, name, 32);
5819 devices[i].
id[0] = vls[i].i;
5822 ins = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, &vls[outs], nDevices-outs, 0, 0);
5824 sprintf(message,
"RtAudio: AL error getting input devices: %s.",
5825 alGetErrorString(oserror()));
5829 for (i=outs; i<ins+outs; i++) {
5830 if (alGetParams(vls[i].i, pvs, 1) < 0) {
5831 sprintf(message,
"RtAudio: AL error querying input devices: %s.",
5832 alGetErrorString(oserror()));
5835 strncpy(devices[i].name, name, 32);
5836 devices[i].
id[1] = vls[i].i;
5844 int RtAudio :: getDefaultInputDevice(
void)
5847 int result = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, &value, 1, 0, 0);
5849 sprintf(message,
"RtAudio: AL error getting default input device id: %s.",
5850 alGetErrorString(oserror()));
5854 for (
int i=0; i<nDevices; i++ )
5855 if ( devices[i].
id[1] == value.i )
return i;
5861 int RtAudio :: getDefaultOutputDevice(
void)
5864 int result = alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, &value, 1, 0, 0);
5866 sprintf(message,
"RtAudio: AL error getting default output device id: %s.",
5867 alGetErrorString(oserror()));
5871 for (
int i=0; i<nDevices; i++ )
5872 if ( devices[i].
id[0] == value.i )
return i;
5878 void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
5880 int resource, result, i;
5885 resource = info->id[0];
5889 result = alQueryValues(resource, AL_CHANNELS, &value, 1, 0, 0);
5891 sprintf(message,
"RtAudio: AL error getting device (%s) channels: %s.",
5892 info->name, alGetErrorString(oserror()));
5896 info->maxOutputChannels = value.i;
5897 info->minOutputChannels = 1;
5900 result = alGetParamInfo(resource, AL_RATE, &pinfo);
5902 sprintf(message,
"RtAudio: AL error getting device (%s) rates: %s.",
5903 info->name, alGetErrorString(oserror()));
5907 info->nSampleRates = 0;
5909 if ( SAMPLE_RATES[i] >= pinfo.min.i && SAMPLE_RATES[i] <= pinfo.max.i ) {
5910 info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
5911 info->nSampleRates++;
5921 resource = info->id[1];
5925 result = alQueryValues(resource, AL_CHANNELS, &value, 1, 0, 0);
5927 sprintf(message,
"RtAudio: AL error getting device (%s) channels: %s.",
5928 info->name, alGetErrorString(oserror()));
5932 info->maxInputChannels = value.i;
5933 info->minInputChannels = 1;
5936 result = alGetParamInfo(resource, AL_RATE, &pinfo);
5938 sprintf(message,
"RtAudio: AL error getting device (%s) rates: %s.",
5939 info->name, alGetErrorString(oserror()));
5947 info->nSampleRates = 0;
5949 if ( SAMPLE_RATES[i] >= pinfo.min.i && SAMPLE_RATES[i] <= pinfo.max.i ) {
5950 info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
5951 info->nSampleRates++;
5960 if ( info->maxInputChannels == 0 && info->maxOutputChannels == 0 )
5962 if ( info->nSampleRates == 0 )
5966 if (info->maxInputChannels < info->maxOutputChannels)
5967 info->maxDuplexChannels = info->maxInputChannels;
5969 info->maxDuplexChannels = info->maxOutputChannels;
5970 if (info->minInputChannels < info->minOutputChannels)
5971 info->minDuplexChannels = info->minInputChannels;
5973 info->minDuplexChannels = info->minOutputChannels;
5975 if ( info->maxDuplexChannels > 0 ) info->hasDuplexSupport =
true;
5976 else info->hasDuplexSupport =
false;
5978 info->probed =
true;
5983 bool RtAudio :: probeDeviceOpen(
int device, RTAUDIO_STREAM *stream,
5984 STREAM_MODE mode,
int channels,
5985 int sampleRate, RTAUDIO_FORMAT format,
5986 int *bufferSize,
int numberOfBuffers)
5988 int result, resource, nBuffers;
5994 al_config = alNewConfig();
5996 sprintf(message,
"RtAudio: can't get AL config: %s.",
5997 alGetErrorString(oserror()));
6003 result = alSetChannels(al_config, channels);
6005 sprintf(message,
"RtAudio: can't set %d channels in AL config: %s.",
6006 channels, alGetErrorString(oserror()));
6015 if ( numberOfBuffers < 1 )
6018 nBuffers = numberOfBuffers;
6019 long buffer_size = *bufferSize * nBuffers;
6020 result = alSetQueueSize(al_config, buffer_size);
6023 buffer_size = alGetQueueSize(al_config);
6024 result = alSetQueueSize(al_config, buffer_size);
6026 sprintf(message,
"RtAudio: can't set buffer size (%ld) in AL config: %s.",
6027 buffer_size, alGetErrorString(oserror()));
6031 *bufferSize = buffer_size / nBuffers;
6035 stream->userFormat = format;
6036 stream->deviceFormat[mode] = format;
6038 result = alSetSampFmt(al_config, AL_SAMPFMT_TWOSCOMP);
6039 result = alSetWidth(al_config, AL_SAMPLE_8);
6042 result = alSetSampFmt(al_config, AL_SAMPFMT_TWOSCOMP);
6043 result = alSetWidth(al_config, AL_SAMPLE_16);
6049 result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT);
6055 result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT);
6059 result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT);
6061 result = alSetSampFmt(al_config, AL_SAMPFMT_DOUBLE);
6063 if ( result == -1 ) {
6064 sprintf(message,
"RtAudio: AL error setting sample format in AL config: %s.",
6065 alGetErrorString(oserror()));
6070 if (mode == OUTPUT) {
6074 resource = AL_DEFAULT_OUTPUT;
6076 resource = devices[device].
id[0];
6077 result = alSetDevice(al_config, resource);
6078 if ( result == -1 ) {
6079 sprintf(message,
"RtAudio: AL error setting device (%s) in AL config: %s.",
6080 devices[device].name, alGetErrorString(oserror()));
6086 port = alOpenPort(
"RtAudio Output Port",
"w", al_config);
6088 sprintf(message,
"RtAudio: AL error opening output port: %s.",
6089 alGetErrorString(oserror()));
6095 pvs[0].param = AL_MASTER_CLOCK;
6096 pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE;
6097 pvs[1].param = AL_RATE;
6098 pvs[1].value.ll = alDoubleToFixed((
double)sampleRate);
6099 result = alSetParams(resource, pvs, 2);
6102 sprintf(message,
"RtAudio: AL error setting sample rate (%d) for device (%s): %s.",
6103 sampleRate, devices[device].name, alGetErrorString(oserror()));
6112 resource = AL_DEFAULT_INPUT;
6114 resource = devices[device].
id[1];
6115 result = alSetDevice(al_config, resource);
6116 if ( result == -1 ) {
6117 sprintf(message,
"RtAudio: AL error setting device (%s) in AL config: %s.",
6118 devices[device].name, alGetErrorString(oserror()));
6124 port = alOpenPort(
"RtAudio Output Port",
"r", al_config);
6126 sprintf(message,
"RtAudio: AL error opening input port: %s.",
6127 alGetErrorString(oserror()));
6133 pvs[0].param = AL_MASTER_CLOCK;
6134 pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE;
6135 pvs[1].param = AL_RATE;
6136 pvs[1].value.ll = alDoubleToFixed((
double)sampleRate);
6137 result = alSetParams(resource, pvs, 2);
6140 sprintf(message,
"RtAudio: AL error setting sample rate (%d) for device (%s): %s.",
6141 sampleRate, devices[device].name, alGetErrorString(oserror()));
6147 alFreeConfig(al_config);
6149 stream->nUserChannels[mode] = channels;
6150 stream->nDeviceChannels[mode] = channels;
6153 stream->handle[mode] = port;
6154 stream->doConvertBuffer[mode] =
false;
6155 if (stream->userFormat != stream->deviceFormat[mode])
6156 stream->doConvertBuffer[mode] =
true;
6159 if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
6162 if (stream->nUserChannels[0] >= stream->nUserChannels[1])
6163 buffer_bytes = stream->nUserChannels[0];
6165 buffer_bytes = stream->nUserChannels[1];
6167 buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
6168 if (stream->userBuffer) free(stream->userBuffer);
6169 stream->userBuffer = (
char *) calloc(buffer_bytes, 1);
6170 if (stream->userBuffer ==
NULL)
6174 if ( stream->doConvertBuffer[mode] ) {
6177 bool makeBuffer =
true;
6178 if ( mode == OUTPUT )
6179 buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
6181 buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
6182 if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
6183 long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
6184 if ( buffer_bytes < bytes_out ) makeBuffer =
false;
6189 buffer_bytes *= *bufferSize;
6190 if (stream->deviceBuffer) free(stream->deviceBuffer);
6191 stream->deviceBuffer = (
char *) calloc(buffer_bytes, 1);
6192 if (stream->deviceBuffer ==
NULL)
6197 stream->device[mode] = device;
6198 stream->state = STREAM_STOPPED;
6199 if ( stream->mode == OUTPUT && mode == INPUT )
6201 stream->mode = DUPLEX;
6203 stream->mode = mode;
6204 stream->nBuffers = nBuffers;
6205 stream->bufferSize = *bufferSize;
6206 stream->sampleRate = sampleRate;
6211 if (stream->handle[0]) {
6212 alClosePort(stream->handle[0]);
6213 stream->handle[0] = 0;
6215 if (stream->handle[1]) {
6216 alClosePort(stream->handle[1]);
6217 stream->handle[1] = 0;
6219 if (stream->userBuffer) {
6220 free(stream->userBuffer);
6221 stream->userBuffer = 0;
6223 sprintf(message,
"RtAudio: ALSA error allocating buffer memory for device (%s).",
6224 devices[device].name);
6234 if ( streams.find( streamId ) == streams.end() ) {
6235 sprintf(message,
"RtAudio: invalid stream identifier!");
6240 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
6242 if (stream->callbackInfo.usingCallback) {
6243 pthread_cancel(stream->callbackInfo.thread);
6244 pthread_join(stream->callbackInfo.thread,
NULL);
6247 pthread_mutex_destroy(&stream->mutex);
6249 if (stream->handle[0])
6250 alClosePort(stream->handle[0]);
6252 if (stream->handle[1])
6253 alClosePort(stream->handle[1]);
6255 if (stream->userBuffer)
6256 free(stream->userBuffer);
6258 if (stream->deviceBuffer)
6259 free(stream->deviceBuffer);
6262 streams.erase(streamId);
6267 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
6269 if (stream->state == STREAM_RUNNING)
6273 stream->state = STREAM_RUNNING;
6278 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
6282 if (stream->state == STREAM_STOPPED)
6286 int buffer_size = stream->bufferSize * stream->nBuffers;
6288 if (stream->mode == OUTPUT || stream->mode == DUPLEX)
6289 alZeroFrames(stream->handle[0], buffer_size);
6291 if (stream->mode == INPUT || stream->mode == DUPLEX) {
6292 result = alDiscardFrames(stream->handle[1], buffer_size);
6294 sprintf(message,
"RtAudio: AL error draining stream device (%s): %s.",
6295 devices[stream->device[1]].name, alGetErrorString(oserror()));
6299 stream->state = STREAM_STOPPED;
6307 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
6311 if (stream->state == STREAM_STOPPED)
6314 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
6316 int buffer_size = stream->bufferSize * stream->nBuffers;
6317 int result = alDiscardFrames(stream->handle[0], buffer_size);
6319 sprintf(message,
"RtAudio: AL error aborting stream device (%s): %s.",
6320 devices[stream->device[0]].name, alGetErrorString(oserror()));
6327 stream->state = STREAM_STOPPED;
6335 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
6340 if (stream->state == STREAM_STOPPED)
6344 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
6345 err = alGetFillable(stream->handle[0]);
6347 sprintf(message,
"RtAudio: AL error getting available frames for stream (%s): %s.",
6348 devices[stream->device[0]].name, alGetErrorString(oserror()));
6355 if (stream->mode == INPUT || stream->mode == DUPLEX) {
6356 err = alGetFilled(stream->handle[1]);
6358 sprintf(message,
"RtAudio: AL error getting available frames for stream (%s): %s.",
6359 devices[stream->device[1]].name, alGetErrorString(oserror()));
6362 if (frames > err) frames = err;
6365 frames = stream->bufferSize - frames;
6366 if (frames < 0) frames = 0;
6375 RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
6378 if (stream->state == STREAM_STOPPED) {
6379 if (stream->callbackInfo.usingCallback) usleep(50000);
6382 else if (stream->callbackInfo.usingCallback) {
6384 stopStream = callback(stream->userBuffer, stream->bufferSize, stream->callbackInfo.userData);
6390 if (stream->state == STREAM_STOPPED)
6396 if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
6399 if (stream->doConvertBuffer[0]) {
6400 convertStreamBuffer(stream, OUTPUT);
6401 buffer = stream->deviceBuffer;
6402 channels = stream->nDeviceChannels[0];
6403 format = stream->deviceFormat[0];
6406 buffer = stream->userBuffer;
6407 channels = stream->nUserChannels[0];
6408 format = stream->userFormat;
6412 if (stream->doByteSwap[0])
6413 byteSwapBuffer(buffer, stream->bufferSize * channels, format);
6416 alWriteFrames(stream->handle[0], buffer, stream->bufferSize);
6419 if (stream->mode == INPUT || stream->mode == DUPLEX) {
6422 if (stream->doConvertBuffer[1]) {
6423 buffer = stream->deviceBuffer;
6424 channels = stream->nDeviceChannels[1];
6425 format = stream->deviceFormat[1];
6428 buffer = stream->userBuffer;
6429 channels = stream->nUserChannels[1];
6430 format = stream->userFormat;
6434 alReadFrames(stream->handle[1], buffer, stream->bufferSize);
6437 if (stream->doByteSwap[1])
6438 byteSwapBuffer(buffer, stream->bufferSize * channels, format);
6441 if (stream->doConvertBuffer[1])
6442 convertStreamBuffer(stream, INPUT);
6448 if (stream->callbackInfo.usingCallback && stopStream)
6452 extern "C" void *callbackHandler(
void *ptr)
6459 while ( *usingCallback ) {
6460 pthread_testcancel();
6462 object->tickStream(stream);
6465 fprintf(stderr,
"\nRtAudio: Callback thread error (%s) ... closing thread.\n\n",
6490 fprintf(stderr,
"\n%s\n\n", message);
6493 #if defined(__RTAUDIO_DEBUG__)
6494 fprintf(stderr,
"\n%s\n\n", message);
6498 fprintf(stderr,
"\n%s\n\n", message);
6503 void *RtAudio :: verifyStream(
int streamId)
6506 if ( streams.find( streamId ) == streams.end() ) {
6507 sprintf(message,
"RtAudio: invalid stream identifier!");
6511 return streams[streamId];
6514 void RtAudio :: clearDeviceInfo(RTAUDIO_DEVICE *info)
6518 info->probed =
false;
6519 info->maxOutputChannels = 0;
6520 info->maxInputChannels = 0;
6521 info->maxDuplexChannels = 0;
6522 info->minOutputChannels = 0;
6523 info->minInputChannels = 0;
6524 info->minDuplexChannels = 0;
6525 info->hasDuplexSupport =
false;
6526 info->nSampleRates = 0;
6528 info->sampleRates[i] = 0;
6529 info->nativeFormats = 0;
6532 int RtAudio :: formatBytes(RTAUDIO_FORMAT format)
6544 sprintf(message,
"RtAudio: undefined format in formatBytes().");
6550 void RtAudio :: convertStreamBuffer(RTAUDIO_STREAM *stream, STREAM_MODE mode)
6556 int j, jump_in, jump_out, channels;
6558 char *input, *output;
6560 if (mode == INPUT) {
6561 input = stream->deviceBuffer;
6562 output = stream->userBuffer;
6563 jump_in = stream->nDeviceChannels[1];
6564 jump_out = stream->nUserChannels[1];
6565 format_in = stream->deviceFormat[1];
6566 format_out = stream->userFormat;
6569 input = stream->userBuffer;
6570 output = stream->deviceBuffer;
6571 jump_in = stream->nUserChannels[0];
6572 jump_out = stream->nDeviceChannels[0];
6573 format_in = stream->userFormat;
6574 format_out = stream->deviceFormat[0];
6577 if ( stream->mode == DUPLEX &&
6578 stream->nDeviceChannels[0] != stream->nDeviceChannels[1] )
6579 memset(output, 0, stream->bufferSize * jump_out * formatBytes(format_out));
6582 channels = (jump_in < jump_out) ? jump_in : jump_out;
6585 std::vector<int> offset_in(channels);
6586 std::vector<int> offset_out(channels);
6587 if (mode == INPUT && stream->deInterleave[1]) {
6588 for (
int k=0; k<channels; k++) {
6589 offset_in[k] = k * stream->bufferSize;
6594 else if (mode == OUTPUT && stream->deInterleave[0]) {
6595 for (
int k=0; k<channels; k++) {
6597 offset_out[k] = k * stream->bufferSize;
6602 for (
int k=0; k<channels; k++) {
6610 FLOAT64 *out = (FLOAT64 *)output;
6613 signed char *in = (
signed char *)input;
6614 scale = 1.0 / 128.0;
6615 for (
int i=0; i<stream->bufferSize; i++) {
6616 for (j=0; j<channels; j++) {
6617 out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
6618 out[offset_out[j]] *= scale;
6625 INT16 *in = (INT16 *)input;
6626 scale = 1.0 / 32768.0;
6627 for (
int i=0; i<stream->bufferSize; i++) {
6628 for (j=0; j<channels; j++) {
6629 out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
6630 out[offset_out[j]] *= scale;
6637 INT32 *in = (INT32 *)input;
6638 scale = 1.0 / 2147483648.0;
6639 for (
int i=0; i<stream->bufferSize; i++) {
6640 for (j=0; j<channels; j++) {
6641 out[offset_out[j]] = (FLOAT64) (in[offset_in[j]] & 0xffffff00);
6642 out[offset_out[j]] *= scale;
6649 INT32 *in = (INT32 *)input;
6650 scale = 1.0 / 2147483648.0;
6651 for (
int i=0; i<stream->bufferSize; i++) {
6652 for (j=0; j<channels; j++) {
6653 out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
6654 out[offset_out[j]] *= scale;
6661 FLOAT32 *in = (FLOAT32 *)input;
6662 for (
int i=0; i<stream->bufferSize; i++) {
6663 for (j=0; j<channels; j++) {
6664 out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
6672 FLOAT64 *in = (FLOAT64 *)input;
6673 for (
int i=0; i<stream->bufferSize; i++) {
6674 for (j=0; j<channels; j++) {
6675 out[offset_out[j]] = in[offset_in[j]];
6684 FLOAT32 *out = (FLOAT32 *)output;
6687 signed char *in = (
signed char *)input;
6688 scale = 1.0 / 128.0;
6689 for (
int i=0; i<stream->bufferSize; i++) {
6690 for (j=0; j<channels; j++) {
6691 out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
6692 out[offset_out[j]] *= scale;
6699 INT16 *in = (INT16 *)input;
6700 scale = 1.0 / 32768.0;
6701 for (
int i=0; i<stream->bufferSize; i++) {
6702 for (j=0; j<channels; j++) {
6703 out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
6704 out[offset_out[j]] *= scale;
6711 INT32 *in = (INT32 *)input;
6712 scale = 1.0 / 2147483648.0;
6713 for (
int i=0; i<stream->bufferSize; i++) {
6714 for (j=0; j<channels; j++) {
6715 out[offset_out[j]] = (FLOAT32) (in[offset_in[j]] & 0xffffff00);
6716 out[offset_out[j]] *= scale;
6723 INT32 *in = (INT32 *)input;
6724 scale = 1.0 / 2147483648.0;
6725 for (
int i=0; i<stream->bufferSize; i++) {
6726 for (j=0; j<channels; j++) {
6727 out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
6728 out[offset_out[j]] *= scale;
6736 FLOAT32 *in = (FLOAT32 *)input;
6737 for (
int i=0; i<stream->bufferSize; i++) {
6738 for (j=0; j<channels; j++) {
6739 out[offset_out[j]] = in[offset_in[j]];
6746 FLOAT64 *in = (FLOAT64 *)input;
6747 for (
int i=0; i<stream->bufferSize; i++) {
6748 for (j=0; j<channels; j++) {
6749 out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
6757 INT32 *out = (INT32 *)output;
6759 signed char *in = (
signed char *)input;
6760 for (
int i=0; i<stream->bufferSize; i++) {
6761 for (j=0; j<channels; j++) {
6762 out[offset_out[j]] = (INT32) in[offset_in[j]];
6763 out[offset_out[j]] <<= 24;
6770 INT16 *in = (INT16 *)input;
6771 for (
int i=0; i<stream->bufferSize; i++) {
6772 for (j=0; j<channels; j++) {
6773 out[offset_out[j]] = (INT32) in[offset_in[j]];
6774 out[offset_out[j]] <<= 16;
6781 INT32 *in = (INT32 *)input;
6782 for (
int i=0; i<stream->bufferSize; i++) {
6783 for (j=0; j<channels; j++) {
6784 out[offset_out[j]] = (INT32) in[offset_in[j]];
6792 INT32 *in = (INT32 *)input;
6793 for (
int i=0; i<stream->bufferSize; i++) {
6794 for (j=0; j<channels; j++) {
6795 out[offset_out[j]] = in[offset_in[j]];
6802 FLOAT32 *in = (FLOAT32 *)input;
6803 for (
int i=0; i<stream->bufferSize; i++) {
6804 for (j=0; j<channels; j++) {
6805 out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
6812 FLOAT64 *in = (FLOAT64 *)input;
6813 for (
int i=0; i<stream->bufferSize; i++) {
6814 for (j=0; j<channels; j++) {
6815 out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
6823 INT32 *out = (INT32 *)output;
6825 signed char *in = (
signed char *)input;
6826 for (
int i=0; i<stream->bufferSize; i++) {
6827 for (j=0; j<channels; j++) {
6828 out[offset_out[j]] = (INT32) in[offset_in[j]];
6829 out[offset_out[j]] <<= 24;
6836 INT16 *in = (INT16 *)input;
6837 for (
int i=0; i<stream->bufferSize; i++) {
6838 for (j=0; j<channels; j++) {
6839 out[offset_out[j]] = (INT32) in[offset_in[j]];
6840 out[offset_out[j]] <<= 16;
6848 INT32 *in = (INT32 *)input;
6849 for (
int i=0; i<stream->bufferSize; i++) {
6850 for (j=0; j<channels; j++) {
6851 out[offset_out[j]] = in[offset_in[j]];
6858 INT32 *in = (INT32 *)input;
6859 for (
int i=0; i<stream->bufferSize; i++) {
6860 for (j=0; j<channels; j++) {
6861 out[offset_out[j]] = (INT32) (in[offset_in[j]] & 0xffffff00);
6868 FLOAT32 *in = (FLOAT32 *)input;
6869 for (
int i=0; i<stream->bufferSize; i++) {
6870 for (j=0; j<channels; j++) {
6871 out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
6878 FLOAT64 *in = (FLOAT64 *)input;
6879 for (
int i=0; i<stream->bufferSize; i++) {
6880 for (j=0; j<channels; j++) {
6881 out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
6889 INT16 *out = (INT16 *)output;
6891 signed char *in = (
signed char *)input;
6892 for (
int i=0; i<stream->bufferSize; i++) {
6893 for (j=0; j<channels; j++) {
6894 out[offset_out[j]] = (INT16) in[offset_in[j]];
6895 out[offset_out[j]] <<= 8;
6903 INT16 *in = (INT16 *)input;
6904 for (
int i=0; i<stream->bufferSize; i++) {
6905 for (j=0; j<channels; j++) {
6906 out[offset_out[j]] = in[offset_in[j]];
6913 INT32 *in = (INT32 *)input;
6914 for (
int i=0; i<stream->bufferSize; i++) {
6915 for (j=0; j<channels; j++) {
6916 out[offset_out[j]] = (INT16) ((in[offset_in[j]] >> 16) & 0x0000ffff);
6923 INT32 *in = (INT32 *)input;
6924 for (
int i=0; i<stream->bufferSize; i++) {
6925 for (j=0; j<channels; j++) {
6926 out[offset_out[j]] = (INT16) ((in[offset_in[j]] >> 16) & 0x0000ffff);
6933 FLOAT32 *in = (FLOAT32 *)input;
6934 for (
int i=0; i<stream->bufferSize; i++) {
6935 for (j=0; j<channels; j++) {
6936 out[offset_out[j]] = (INT16) (in[offset_in[j]] * 32767.0);
6943 FLOAT64 *in = (FLOAT64 *)input;
6944 for (
int i=0; i<stream->bufferSize; i++) {
6945 for (j=0; j<channels; j++) {
6946 out[offset_out[j]] = (INT16) (in[offset_in[j]] * 32767.0);
6954 signed char *out = (
signed char *)output;
6957 signed char *in = (
signed char *)input;
6958 for (
int i=0; i<stream->bufferSize; i++) {
6959 for (j=0; j<channels; j++) {
6960 out[offset_out[j]] = in[offset_in[j]];
6967 INT16 *in = (INT16 *)input;
6968 for (
int i=0; i<stream->bufferSize; i++) {
6969 for (j=0; j<channels; j++) {
6970 out[offset_out[j]] = (
signed char) ((in[offset_in[j]] >> 8) & 0x00ff);
6977 INT32 *in = (INT32 *)input;
6978 for (
int i=0; i<stream->bufferSize; i++) {
6979 for (j=0; j<channels; j++) {
6980 out[offset_out[j]] = (
signed char) ((in[offset_in[j]] >> 24) & 0x000000ff);
6987 INT32 *in = (INT32 *)input;
6988 for (
int i=0; i<stream->bufferSize; i++) {
6989 for (j=0; j<channels; j++) {
6990 out[offset_out[j]] = (
signed char) ((in[offset_in[j]] >> 24) & 0x000000ff);
6997 FLOAT32 *in = (FLOAT32 *)input;
6998 for (
int i=0; i<stream->bufferSize; i++) {
6999 for (j=0; j<channels; j++) {
7000 out[offset_out[j]] = (
signed char) (in[offset_in[j]] * 127.0);
7007 FLOAT64 *in = (FLOAT64 *)input;
7008 for (
int i=0; i<stream->bufferSize; i++) {
7009 for (j=0; j<channels; j++) {
7010 out[offset_out[j]] = (
signed char) (in[offset_in[j]] * 127.0);
7019 void RtAudio :: byteSwapBuffer(
char *buffer,
int samples, RTAUDIO_FORMAT format)
7026 for (
int i=0; i<samples; i++) {
7039 for (
int i=0; i<samples; i++) {
7056 for (
int i=0; i<samples; i++) {