You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7086 lines
226KB

  1. /************************************************************************/
  2. /*! \class RtAudio
  3. \brief Realtime audio i/o C++ class.
  4. RtAudio provides a common API (Application Programming Interface)
  5. for realtime audio input/output across Linux (native ALSA and
  6. OSS), SGI, Macintosh OS X (CoreAudio), and Windows (DirectSound
  7. and ASIO) operating systems.
  8. RtAudio WWW site: http://www-ccrma.stanford.edu/~gary/rtaudio/
  9. RtAudio: a realtime audio i/o C++ class
  10. Copyright (c) 2001-2002 Gary P. Scavone
  11. Permission is hereby granted, free of charge, to any person
  12. obtaining a copy of this software and associated documentation files
  13. (the "Software"), to deal in the Software without restriction,
  14. including without limitation the rights to use, copy, modify, merge,
  15. publish, distribute, sublicense, and/or sell copies of the Software,
  16. and to permit persons to whom the Software is furnished to do so,
  17. subject to the following conditions:
  18. The above copyright notice and this permission notice shall be
  19. included in all copies or substantial portions of the Software.
  20. Any person wishing to distribute modifications to the Software is
  21. requested to send the modifications to the original developer so that
  22. they can be incorporated into the canonical version.
  23. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  26. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  27. ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  28. CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. */
  31. /************************************************************************/
  32. // RtAudio: Version 2.1.1, 24 October 2002
  33. #include "RtAudio.h"
  34. #include <vector>
  35. #include <stdio.h>
  36. #include <iostream.h>
  37. // Static variable definitions.
  38. const unsigned int RtAudio :: SAMPLE_RATES[] = {
  39. 4000, 5512, 8000, 9600, 11025, 16000, 22050,
  40. 32000, 44100, 48000, 88200, 96000, 176400, 192000
  41. };
  42. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_SINT8 = 1;
  43. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_SINT16 = 2;
  44. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_SINT24 = 4;
  45. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_SINT32 = 8;
  46. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_FLOAT32 = 16;
  47. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_FLOAT64 = 32;
  48. #if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)
  49. #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A)
  50. #define MUTEX_LOCK(A) EnterCriticalSection(A)
  51. #define MUTEX_UNLOCK(A) LeaveCriticalSection(A)
  52. #else // pthread API
  53. #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL)
  54. #define MUTEX_LOCK(A) pthread_mutex_lock(A)
  55. #define MUTEX_UNLOCK(A) pthread_mutex_unlock(A)
  56. #endif
  57. // *************************************************** //
  58. //
  59. // Public common (OS-independent) methods.
  60. //
  61. // *************************************************** //
  62. RtAudio :: RtAudio()
  63. {
  64. initialize();
  65. if (nDevices <= 0) {
  66. sprintf(message, "RtAudio: no audio devices found!");
  67. error(RtError::NO_DEVICES_FOUND);
  68. }
  69. }
  70. RtAudio :: RtAudio(int *streamId,
  71. int outputDevice, int outputChannels,
  72. int inputDevice, int inputChannels,
  73. RTAUDIO_FORMAT format, int sampleRate,
  74. int *bufferSize, int numberOfBuffers)
  75. {
  76. initialize();
  77. if (nDevices <= 0) {
  78. sprintf(message, "RtAudio: no audio devices found!");
  79. error(RtError::NO_DEVICES_FOUND);
  80. }
  81. try {
  82. *streamId = openStream(outputDevice, outputChannels, inputDevice, inputChannels,
  83. format, sampleRate, bufferSize, numberOfBuffers);
  84. }
  85. catch (RtError &exception) {
  86. // deallocate the RTAUDIO_DEVICE structures
  87. if (devices) free(devices);
  88. throw exception;
  89. }
  90. }
  91. RtAudio :: ~RtAudio()
  92. {
  93. // close any existing streams
  94. while ( streams.size() )
  95. closeStream( streams.begin()->first );
  96. // deallocate the RTAUDIO_DEVICE structures
  97. if (devices) free(devices);
  98. }
  99. int RtAudio :: openStream(int outputDevice, int outputChannels,
  100. int inputDevice, int inputChannels,
  101. RTAUDIO_FORMAT format, int sampleRate,
  102. int *bufferSize, int numberOfBuffers)
  103. {
  104. static int streamKey = 0; // Unique stream identifier ... OK for multiple instances.
  105. if (outputChannels < 1 && inputChannels < 1) {
  106. sprintf(message,"RtAudio: one or both 'channel' parameters must be greater than zero.");
  107. error(RtError::INVALID_PARAMETER);
  108. }
  109. if ( formatBytes(format) == 0 ) {
  110. sprintf(message,"RtAudio: 'format' parameter value is undefined.");
  111. error(RtError::INVALID_PARAMETER);
  112. }
  113. if ( outputChannels > 0 ) {
  114. if (outputDevice > nDevices || outputDevice < 0) {
  115. sprintf(message,"RtAudio: 'outputDevice' parameter value (%d) is invalid.", outputDevice);
  116. error(RtError::INVALID_PARAMETER);
  117. }
  118. }
  119. if ( inputChannels > 0 ) {
  120. if (inputDevice > nDevices || inputDevice < 0) {
  121. sprintf(message,"RtAudio: 'inputDevice' parameter value (%d) is invalid.", inputDevice);
  122. error(RtError::INVALID_PARAMETER);
  123. }
  124. }
  125. // Allocate a new stream structure.
  126. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) calloc(1, sizeof(RTAUDIO_STREAM));
  127. if (stream == NULL) {
  128. sprintf(message, "RtAudio: memory allocation error!");
  129. error(RtError::MEMORY_ERROR);
  130. }
  131. stream->mode = UNINITIALIZED;
  132. MUTEX_INITIALIZE(&stream->mutex);
  133. bool result = FAILURE;
  134. int device, defaultDevice = 0;
  135. STREAM_MODE mode;
  136. int channels;
  137. if ( outputChannels > 0 ) {
  138. mode = OUTPUT;
  139. channels = outputChannels;
  140. if ( outputDevice == 0 ) { // Try default device first.
  141. defaultDevice = getDefaultOutputDevice();
  142. device = defaultDevice;
  143. }
  144. else
  145. device = outputDevice - 1;
  146. for (int i=-1; i<nDevices; i++) {
  147. if (i >= 0 ) {
  148. if ( i == defaultDevice ) continue;
  149. device = i;
  150. }
  151. if (devices[device].probed == false) {
  152. // If the device wasn't successfully probed before, try it
  153. // again now.
  154. clearDeviceInfo(&devices[device]);
  155. probeDeviceInfo(&devices[device]);
  156. }
  157. if ( devices[device].probed )
  158. result = probeDeviceOpen(device, stream, mode, channels, sampleRate,
  159. format, bufferSize, numberOfBuffers);
  160. if (result == SUCCESS) break;
  161. if ( outputDevice > 0 ) break;
  162. }
  163. }
  164. if ( inputChannels > 0 && ( result == SUCCESS || outputChannels <= 0 ) ) {
  165. mode = INPUT;
  166. channels = inputChannels;
  167. if ( inputDevice == 0 ) { // Try default device first.
  168. defaultDevice = getDefaultInputDevice();
  169. device = defaultDevice;
  170. }
  171. else
  172. device = inputDevice - 1;
  173. for (int i=-1; i<nDevices; i++) {
  174. if (i >= 0 ) {
  175. if ( i == defaultDevice ) continue;
  176. device = i;
  177. }
  178. if (devices[device].probed == false) {
  179. // If the device wasn't successfully probed before, try it
  180. // again now.
  181. clearDeviceInfo(&devices[device]);
  182. probeDeviceInfo(&devices[device]);
  183. }
  184. if ( devices[device].probed )
  185. result = probeDeviceOpen(device, stream, mode, channels, sampleRate,
  186. format, bufferSize, numberOfBuffers);
  187. if (result == SUCCESS) break;
  188. if ( outputDevice > 0 ) break;
  189. }
  190. }
  191. streams[++streamKey] = (void *) stream;
  192. if ( result == SUCCESS )
  193. return streamKey;
  194. // If we get here, all attempted probes failed. Close any opened
  195. // devices and delete the allocated stream.
  196. closeStream(streamKey);
  197. if ( ( outputDevice == 0 && outputChannels > 0 )
  198. || ( inputDevice == 0 && inputChannels > 0 ) )
  199. sprintf(message,"RtAudio: no devices found for given parameters.");
  200. else
  201. sprintf(message,"RtAudio: unable to open specified device(s) with given stream parameters.");
  202. error(RtError::INVALID_PARAMETER);
  203. return -1;
  204. }
  205. int RtAudio :: getDeviceCount(void)
  206. {
  207. return nDevices;
  208. }
  209. void RtAudio :: getDeviceInfo(int device, RTAUDIO_DEVICE *info)
  210. {
  211. if (device > nDevices || device < 1) {
  212. sprintf(message, "RtAudio: invalid device specifier (%d)!", device);
  213. error(RtError::INVALID_DEVICE);
  214. }
  215. int deviceIndex = device - 1;
  216. // If the device wasn't successfully probed before, try it now (or again).
  217. if (devices[deviceIndex].probed == false) {
  218. clearDeviceInfo(&devices[deviceIndex]);
  219. probeDeviceInfo(&devices[deviceIndex]);
  220. }
  221. // Clear the info structure.
  222. memset(info, 0, sizeof(RTAUDIO_DEVICE));
  223. strncpy(info->name, devices[deviceIndex].name, 128);
  224. info->probed = devices[deviceIndex].probed;
  225. if ( info->probed == true ) {
  226. info->maxOutputChannels = devices[deviceIndex].maxOutputChannels;
  227. info->maxInputChannels = devices[deviceIndex].maxInputChannels;
  228. info->maxDuplexChannels = devices[deviceIndex].maxDuplexChannels;
  229. info->minOutputChannels = devices[deviceIndex].minOutputChannels;
  230. info->minInputChannels = devices[deviceIndex].minInputChannels;
  231. info->minDuplexChannels = devices[deviceIndex].minDuplexChannels;
  232. info->hasDuplexSupport = devices[deviceIndex].hasDuplexSupport;
  233. info->nSampleRates = devices[deviceIndex].nSampleRates;
  234. if (info->nSampleRates == -1) {
  235. info->sampleRates[0] = devices[deviceIndex].sampleRates[0];
  236. info->sampleRates[1] = devices[deviceIndex].sampleRates[1];
  237. }
  238. else {
  239. for (int i=0; i<info->nSampleRates; i++)
  240. info->sampleRates[i] = devices[deviceIndex].sampleRates[i];
  241. }
  242. info->nativeFormats = devices[deviceIndex].nativeFormats;
  243. if ( deviceIndex == getDefaultOutputDevice() ||
  244. deviceIndex == getDefaultInputDevice() )
  245. info->isDefault = true;
  246. }
  247. return;
  248. }
  249. char * const RtAudio :: getStreamBuffer(int streamId)
  250. {
  251. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  252. return stream->userBuffer;
  253. }
  254. #if defined(__LINUX_ALSA__) || defined(__LINUX_OSS__) || defined(__IRIX_AL__)
  255. extern "C" void *callbackHandler(void * ptr);
  256. void RtAudio :: setStreamCallback(int streamId, RTAUDIO_CALLBACK callback, void *userData)
  257. {
  258. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  259. CALLBACK_INFO *info = (CALLBACK_INFO *) &stream->callbackInfo;
  260. if ( info->usingCallback ) {
  261. sprintf(message, "RtAudio: A callback is already set for this stream!");
  262. error(RtError::WARNING);
  263. return;
  264. }
  265. info->callback = (void *) callback;
  266. info->userData = userData;
  267. info->usingCallback = true;
  268. info->object = (void *) this;
  269. info->streamId = streamId;
  270. int err = pthread_create(&info->thread, NULL, callbackHandler, &stream->callbackInfo);
  271. if (err) {
  272. info->usingCallback = false;
  273. sprintf(message, "RtAudio: error starting callback thread!");
  274. error(RtError::THREAD_ERROR);
  275. }
  276. }
  277. void RtAudio :: cancelStreamCallback(int streamId)
  278. {
  279. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  280. if (stream->callbackInfo.usingCallback) {
  281. if (stream->state == STREAM_RUNNING)
  282. stopStream( streamId );
  283. MUTEX_LOCK(&stream->mutex);
  284. stream->callbackInfo.usingCallback = false;
  285. pthread_cancel(stream->callbackInfo.thread);
  286. pthread_join(stream->callbackInfo.thread, NULL);
  287. stream->callbackInfo.thread = 0;
  288. stream->callbackInfo.callback = NULL;
  289. stream->callbackInfo.userData = NULL;
  290. MUTEX_UNLOCK(&stream->mutex);
  291. }
  292. }
  293. #endif
  294. // *************************************************** //
  295. //
  296. // OS/API-specific methods.
  297. //
  298. // *************************************************** //
  299. #if defined(__MACOSX_CORE__)
  300. // The OS X CoreAudio API is designed to use a separate callback
  301. // procedure for each of its audio devices. A single RtAudio duplex
  302. // stream using two different devices is supported here, though it
  303. // cannot be guaranteed to always behave correctly because we cannot
  304. // synchronize these two callbacks. This same functionality can be
  305. // achieved with better synchrony by opening two separate streams for
  306. // the devices and using RtAudio blocking calls (i.e. tickStream()).
  307. //
  308. // The possibility of having multiple RtAudio streams accessing the
  309. // same CoreAudio device is not currently supported. The problem
  310. // involves the inability to install our callbackHandler function for
  311. // the same device more than once. I experimented with a workaround
  312. // for this, but it requires an additional buffer for mixing output
  313. // data before filling the CoreAudio device buffer. In the end, I
  314. // decided it wasn't worth supporting.
  315. //
  316. // Property listeners are currently not used. The issue is what could
  317. // be done if a critical stream parameter (buffer size, sample rate,
  318. // device disconnect) notification arrived. The listeners entail
  319. // quite a bit of extra code and most likely, a user program wouldn't
  320. // be prepared for the result anyway. Some initial listener code is
  321. // commented out.
  322. void RtAudio :: initialize(void)
  323. {
  324. OSStatus err = noErr;
  325. UInt32 dataSize;
  326. AudioDeviceID *deviceList = NULL;
  327. nDevices = 0;
  328. // Find out how many audio devices there are, if any.
  329. err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &dataSize, NULL);
  330. if (err != noErr) {
  331. sprintf(message, "RtAudio: OSX error getting device info!");
  332. error(RtError::SYSTEM_ERROR);
  333. }
  334. nDevices = dataSize / sizeof(AudioDeviceID);
  335. if (nDevices == 0) return;
  336. // Allocate the RTAUDIO_DEVICE structures.
  337. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  338. if (devices == NULL) {
  339. sprintf(message, "RtAudio: memory allocation error!");
  340. error(RtError::MEMORY_ERROR);
  341. }
  342. // Make space for the devices we are about to get.
  343. deviceList = (AudioDeviceID *) malloc( dataSize );
  344. if (deviceList == NULL) {
  345. sprintf(message, "RtAudio: memory allocation error!");
  346. error(RtError::MEMORY_ERROR);
  347. }
  348. // Get the array of AudioDeviceIDs.
  349. err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &dataSize, (void *) deviceList);
  350. if (err != noErr) {
  351. free(deviceList);
  352. sprintf(message, "RtAudio: OSX error getting device properties!");
  353. error(RtError::SYSTEM_ERROR);
  354. }
  355. // Write device identifiers to device structures and then
  356. // probe the device capabilities.
  357. for (int i=0; i<nDevices; i++) {
  358. devices[i].id[0] = deviceList[i];
  359. //probeDeviceInfo(&devices[i]);
  360. }
  361. free(deviceList);
  362. }
  363. int RtAudio :: getDefaultInputDevice(void)
  364. {
  365. AudioDeviceID id;
  366. UInt32 dataSize = sizeof( AudioDeviceID );
  367. OSStatus result = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultInputDevice,
  368. &dataSize, &id );
  369. if (result != noErr) {
  370. sprintf( message, "RtAudio: OSX error getting default input device." );
  371. error(RtError::WARNING);
  372. return 0;
  373. }
  374. for ( int i=0; i<nDevices; i++ ) {
  375. if ( id == devices[i].id[0] ) return i;
  376. }
  377. return 0;
  378. }
  379. int RtAudio :: getDefaultOutputDevice(void)
  380. {
  381. AudioDeviceID id;
  382. UInt32 dataSize = sizeof( AudioDeviceID );
  383. OSStatus result = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice,
  384. &dataSize, &id );
  385. if (result != noErr) {
  386. sprintf( message, "RtAudio: OSX error getting default output device." );
  387. error(RtError::WARNING);
  388. return 0;
  389. }
  390. for ( int i=0; i<nDevices; i++ ) {
  391. if ( id == devices[i].id[0] ) return i;
  392. }
  393. return 0;
  394. }
  395. static bool deviceSupportsFormat( AudioDeviceID id, bool isInput,
  396. AudioStreamBasicDescription *desc, bool isDuplex )
  397. {
  398. OSStatus result = noErr;
  399. UInt32 dataSize = sizeof( AudioStreamBasicDescription );
  400. result = AudioDeviceGetProperty( id, 0, isInput,
  401. kAudioDevicePropertyStreamFormatSupported,
  402. &dataSize, desc );
  403. if (result == kAudioHardwareNoError) {
  404. if ( isDuplex ) {
  405. result = AudioDeviceGetProperty( id, 0, true,
  406. kAudioDevicePropertyStreamFormatSupported,
  407. &dataSize, desc );
  408. if (result != kAudioHardwareNoError)
  409. return false;
  410. }
  411. return true;
  412. }
  413. return false;
  414. }
  415. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  416. {
  417. OSStatus err = noErr;
  418. // Get the device manufacturer and name.
  419. char name[256];
  420. char fullname[512];
  421. UInt32 dataSize = 256;
  422. err = AudioDeviceGetProperty( info->id[0], 0, false,
  423. kAudioDevicePropertyDeviceManufacturer,
  424. &dataSize, name );
  425. if (err != noErr) {
  426. sprintf( message, "RtAudio: OSX error getting device manufacturer." );
  427. error(RtError::DEBUG_WARNING);
  428. return;
  429. }
  430. strncpy(fullname, name, 256);
  431. strcat(fullname, ": " );
  432. dataSize = 256;
  433. err = AudioDeviceGetProperty( info->id[0], 0, false,
  434. kAudioDevicePropertyDeviceName,
  435. &dataSize, name );
  436. if (err != noErr) {
  437. sprintf( message, "RtAudio: OSX error getting device name." );
  438. error(RtError::DEBUG_WARNING);
  439. return;
  440. }
  441. strncat(fullname, name, 254);
  442. strncat(info->name, fullname, 128);
  443. // Get output channel information.
  444. unsigned int i, minChannels, maxChannels, nStreams = 0;
  445. AudioBufferList *bufferList = nil;
  446. err = AudioDeviceGetPropertyInfo( info->id[0], 0, false,
  447. kAudioDevicePropertyStreamConfiguration,
  448. &dataSize, NULL );
  449. if (err == noErr && dataSize > 0) {
  450. bufferList = (AudioBufferList *) malloc( dataSize );
  451. if (bufferList == NULL) {
  452. sprintf(message, "RtAudio: memory allocation error!");
  453. error(RtError::DEBUG_WARNING);
  454. return;
  455. }
  456. err = AudioDeviceGetProperty( info->id[0], 0, false,
  457. kAudioDevicePropertyStreamConfiguration,
  458. &dataSize, bufferList );
  459. if (err == noErr) {
  460. maxChannels = 0;
  461. minChannels = 1000;
  462. nStreams = bufferList->mNumberBuffers;
  463. for ( i=0; i<nStreams; i++ ) {
  464. maxChannels += bufferList->mBuffers[i].mNumberChannels;
  465. if ( bufferList->mBuffers[i].mNumberChannels < minChannels )
  466. minChannels = bufferList->mBuffers[i].mNumberChannels;
  467. }
  468. }
  469. }
  470. if (err != noErr || dataSize <= 0) {
  471. sprintf( message, "RtAudio: OSX error getting output channels for device (%s).", info->name );
  472. error(RtError::DEBUG_WARNING);
  473. return;
  474. }
  475. free (bufferList);
  476. if ( nStreams ) {
  477. if ( maxChannels > 0 )
  478. info->maxOutputChannels = maxChannels;
  479. if ( minChannels > 0 )
  480. info->minOutputChannels = minChannels;
  481. }
  482. // Get input channel information.
  483. bufferList = nil;
  484. err = AudioDeviceGetPropertyInfo( info->id[0], 0, true,
  485. kAudioDevicePropertyStreamConfiguration,
  486. &dataSize, NULL );
  487. if (err == noErr && dataSize > 0) {
  488. bufferList = (AudioBufferList *) malloc( dataSize );
  489. if (bufferList == NULL) {
  490. sprintf(message, "RtAudio: memory allocation error!");
  491. error(RtError::DEBUG_WARNING);
  492. return;
  493. }
  494. err = AudioDeviceGetProperty( info->id[0], 0, true,
  495. kAudioDevicePropertyStreamConfiguration,
  496. &dataSize, bufferList );
  497. if (err == noErr) {
  498. maxChannels = 0;
  499. minChannels = 1000;
  500. nStreams = bufferList->mNumberBuffers;
  501. for ( i=0; i<nStreams; i++ ) {
  502. if ( bufferList->mBuffers[i].mNumberChannels < minChannels )
  503. minChannels = bufferList->mBuffers[i].mNumberChannels;
  504. maxChannels += bufferList->mBuffers[i].mNumberChannels;
  505. }
  506. }
  507. }
  508. if (err != noErr || dataSize <= 0) {
  509. sprintf( message, "RtAudio: OSX error getting input channels for device (%s).", info->name );
  510. error(RtError::DEBUG_WARNING);
  511. return;
  512. }
  513. free (bufferList);
  514. if ( nStreams ) {
  515. if ( maxChannels > 0 )
  516. info->maxInputChannels = maxChannels;
  517. if ( minChannels > 0 )
  518. info->minInputChannels = minChannels;
  519. }
  520. // If device opens for both playback and capture, we determine the channels.
  521. if (info->maxOutputChannels > 0 && info->maxInputChannels > 0) {
  522. info->hasDuplexSupport = true;
  523. info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ?
  524. info->maxInputChannels : info->maxOutputChannels;
  525. info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ?
  526. info->minInputChannels : info->minOutputChannels;
  527. }
  528. // Probe the device sample rate and data format parameters. The
  529. // core audio query mechanism is performed on a "stream"
  530. // description, which can have a variable number of channels and
  531. // apply to input or output only.
  532. // Create a stream description structure.
  533. AudioStreamBasicDescription description;
  534. dataSize = sizeof( AudioStreamBasicDescription );
  535. memset(&description, 0, sizeof(AudioStreamBasicDescription));
  536. bool isInput = false;
  537. if ( info->maxOutputChannels == 0 ) isInput = true;
  538. bool isDuplex = false;
  539. if ( info->maxDuplexChannels > 0 ) isDuplex = true;
  540. // Determine the supported sample rates.
  541. info->nSampleRates = 0;
  542. for (i=0; i<MAX_SAMPLE_RATES; i++) {
  543. description.mSampleRate = (double) SAMPLE_RATES[i];
  544. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  545. info->sampleRates[info->nSampleRates++] = SAMPLE_RATES[i];
  546. }
  547. if (info->nSampleRates == 0) {
  548. sprintf( message, "RtAudio: No supported sample rates found for OSX device (%s).", info->name );
  549. error(RtError::DEBUG_WARNING);
  550. return;
  551. }
  552. // Check for continuous sample rate support.
  553. description.mSampleRate = kAudioStreamAnyRate;
  554. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) ) {
  555. info->sampleRates[1] = info->sampleRates[info->nSampleRates-1];
  556. info->nSampleRates = -1;
  557. }
  558. // Determine the supported data formats.
  559. info->nativeFormats = 0;
  560. description.mFormatID = kAudioFormatLinearPCM;
  561. description.mBitsPerChannel = 8;
  562. description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsBigEndian;
  563. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  564. info->nativeFormats |= RTAUDIO_SINT8;
  565. else {
  566. description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
  567. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  568. info->nativeFormats |= RTAUDIO_SINT8;
  569. }
  570. description.mBitsPerChannel = 16;
  571. description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
  572. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  573. info->nativeFormats |= RTAUDIO_SINT16;
  574. else {
  575. description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
  576. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  577. info->nativeFormats |= RTAUDIO_SINT16;
  578. }
  579. description.mBitsPerChannel = 32;
  580. description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
  581. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  582. info->nativeFormats |= RTAUDIO_SINT32;
  583. else {
  584. description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
  585. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  586. info->nativeFormats |= RTAUDIO_SINT32;
  587. }
  588. description.mBitsPerChannel = 24;
  589. description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsAlignedHigh | kLinearPCMFormatFlagIsBigEndian;
  590. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  591. info->nativeFormats |= RTAUDIO_SINT24;
  592. else {
  593. description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
  594. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  595. info->nativeFormats |= RTAUDIO_SINT24;
  596. }
  597. description.mBitsPerChannel = 32;
  598. description.mFormatFlags = kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsBigEndian;
  599. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  600. info->nativeFormats |= RTAUDIO_FLOAT32;
  601. else {
  602. description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
  603. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  604. info->nativeFormats |= RTAUDIO_FLOAT32;
  605. }
  606. description.mBitsPerChannel = 64;
  607. description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
  608. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  609. info->nativeFormats |= RTAUDIO_FLOAT64;
  610. else {
  611. description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian;
  612. if ( deviceSupportsFormat( info->id[0], isInput, &description, isDuplex ) )
  613. info->nativeFormats |= RTAUDIO_FLOAT64;
  614. }
  615. // Check that we have at least one supported format.
  616. if (info->nativeFormats == 0) {
  617. sprintf(message, "RtAudio: OSX PCM device (%s) data format not supported by RtAudio.",
  618. info->name);
  619. error(RtError::DEBUG_WARNING);
  620. return;
  621. }
  622. info->probed = true;
  623. }
  624. OSStatus callbackHandler(AudioDeviceID inDevice,
  625. const AudioTimeStamp* inNow,
  626. const AudioBufferList* inInputData,
  627. const AudioTimeStamp* inInputTime,
  628. AudioBufferList* outOutputData,
  629. const AudioTimeStamp* inOutputTime,
  630. void* infoPointer)
  631. {
  632. CALLBACK_INFO *info = (CALLBACK_INFO *) infoPointer;
  633. RtAudio *object = (RtAudio *) info->object;
  634. try {
  635. object->callbackEvent( info->streamId, inDevice, (void *)inInputData, (void *)outOutputData );
  636. }
  637. catch (RtError &exception) {
  638. fprintf(stderr, "\nCallback handler error (%s)!\n\n", exception.getMessage());
  639. return kAudioHardwareUnspecifiedError;
  640. }
  641. return kAudioHardwareNoError;
  642. }
  643. /*
  644. OSStatus deviceListener(AudioDeviceID inDevice,
  645. UInt32 channel,
  646. Boolean isInput,
  647. AudioDevicePropertyID propertyID,
  648. void* infoPointer)
  649. {
  650. CALLBACK_INFO *info = (CALLBACK_INFO *) infoPointer;
  651. RtAudio *object = (RtAudio *) info->object;
  652. try {
  653. object->settingChange( info->streamId );
  654. }
  655. catch (RtError &exception) {
  656. fprintf(stderr, "\nDevice listener error (%s)!\n\n", exception.getMessage());
  657. return kAudioHardwareUnspecifiedError;
  658. }
  659. return kAudioHardwareNoError;
  660. }
  661. */
  662. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  663. STREAM_MODE mode, int channels,
  664. int sampleRate, RTAUDIO_FORMAT format,
  665. int *bufferSize, int numberOfBuffers)
  666. {
  667. // Check to make sure we don't already have a stream accessing this device.
  668. RTAUDIO_STREAM *streamPtr;
  669. std::map<int, void *>::const_iterator i;
  670. for ( i=streams.begin(); i!=streams.end(); ++i ) {
  671. streamPtr = (RTAUDIO_STREAM *) i->second;
  672. if ( streamPtr->device[0] == device || streamPtr->device[1] == device ) {
  673. sprintf(message, "RtAudio: no current OS X support for multiple streams accessing the same device!");
  674. error(RtError::WARNING);
  675. return FAILURE;
  676. }
  677. }
  678. // Setup for stream mode.
  679. bool isInput = false;
  680. AudioDeviceID id = devices[device].id[0];
  681. if ( mode == INPUT ) isInput = true;
  682. // Search for a stream which contains the desired number of channels.
  683. OSStatus err = noErr;
  684. UInt32 dataSize;
  685. unsigned int deviceChannels, nStreams;
  686. UInt32 iChannel = 0, iStream = 0;
  687. AudioBufferList *bufferList = nil;
  688. err = AudioDeviceGetPropertyInfo( id, 0, isInput,
  689. kAudioDevicePropertyStreamConfiguration,
  690. &dataSize, NULL );
  691. if (err == noErr && dataSize > 0) {
  692. bufferList = (AudioBufferList *) malloc( dataSize );
  693. if (bufferList == NULL) {
  694. sprintf(message, "RtAudio: memory allocation error!");
  695. error(RtError::DEBUG_WARNING);
  696. return FAILURE;
  697. }
  698. err = AudioDeviceGetProperty( id, 0, isInput,
  699. kAudioDevicePropertyStreamConfiguration,
  700. &dataSize, bufferList );
  701. if (err == noErr) {
  702. stream->deInterleave[mode] = false;
  703. nStreams = bufferList->mNumberBuffers;
  704. for ( iStream=0; iStream<nStreams; iStream++ ) {
  705. if ( bufferList->mBuffers[iStream].mNumberChannels >= (unsigned int) channels ) break;
  706. iChannel += bufferList->mBuffers[iStream].mNumberChannels;
  707. }
  708. // If we didn't find a single stream above, see if we can meet
  709. // the channel specification in mono mode (i.e. using separate
  710. // non-interleaved buffers). This can only work if there are N
  711. // consecutive one-channel streams, where N is the number of
  712. // desired channels.
  713. iChannel = 0;
  714. if ( iStream >= nStreams && nStreams >= (unsigned int) channels ) {
  715. int counter = 0;
  716. for ( iStream=0; iStream<nStreams; iStream++ ) {
  717. if ( bufferList->mBuffers[iStream].mNumberChannels == 1 )
  718. counter++;
  719. else
  720. counter = 0;
  721. if ( counter == channels ) {
  722. iStream -= channels - 1;
  723. iChannel -= channels - 1;
  724. stream->deInterleave[mode] = true;
  725. break;
  726. }
  727. iChannel += bufferList->mBuffers[iStream].mNumberChannels;
  728. }
  729. }
  730. }
  731. }
  732. if (err != noErr || dataSize <= 0) {
  733. if ( bufferList ) free( bufferList );
  734. sprintf( message, "RtAudio: OSX error getting channels for device (%s).", devices[device].name );
  735. error(RtError::DEBUG_WARNING);
  736. return FAILURE;
  737. }
  738. if (iStream >= nStreams) {
  739. free (bufferList);
  740. sprintf( message, "RtAudio: unable to find OSX audio stream on device (%s) for requested channels (%d).",
  741. devices[device].name, channels );
  742. error(RtError::DEBUG_WARNING);
  743. return FAILURE;
  744. }
  745. // This is ok even for mono mode ... it gets updated later.
  746. deviceChannels = bufferList->mBuffers[iStream].mNumberChannels;
  747. free (bufferList);
  748. // Determine the buffer size.
  749. AudioValueRange bufferRange;
  750. dataSize = sizeof(AudioValueRange);
  751. err = AudioDeviceGetProperty( id, 0, isInput,
  752. kAudioDevicePropertyBufferSizeRange,
  753. &dataSize, &bufferRange);
  754. if (err != noErr) {
  755. sprintf( message, "RtAudio: OSX error getting buffer size range for device (%s).",
  756. devices[device].name );
  757. error(RtError::DEBUG_WARNING);
  758. return FAILURE;
  759. }
  760. long bufferBytes = *bufferSize * deviceChannels * formatBytes(RTAUDIO_FLOAT32);
  761. if (bufferRange.mMinimum > bufferBytes) bufferBytes = (int) bufferRange.mMinimum;
  762. else if (bufferRange.mMaximum < bufferBytes) bufferBytes = (int) bufferRange.mMaximum;
  763. // Set the buffer size. For mono mode, I'm assuming we only need to
  764. // make this setting for the first channel.
  765. UInt32 theSize = (UInt32) bufferBytes;
  766. dataSize = sizeof( UInt32);
  767. err = AudioDeviceSetProperty(id, NULL, 0, isInput,
  768. kAudioDevicePropertyBufferSize,
  769. dataSize, &theSize);
  770. if (err != noErr) {
  771. sprintf( message, "RtAudio: OSX error setting the buffer size for device (%s).",
  772. devices[device].name );
  773. error(RtError::DEBUG_WARNING);
  774. return FAILURE;
  775. }
  776. // If attempting to setup a duplex stream, the bufferSize parameter
  777. // MUST be the same in both directions!
  778. *bufferSize = bufferBytes / ( deviceChannels * formatBytes(RTAUDIO_FLOAT32) );
  779. if ( stream->mode == OUTPUT && mode == INPUT && *bufferSize != stream->bufferSize ) {
  780. sprintf( message, "RtAudio: OSX error setting buffer size for duplex stream on device (%s).",
  781. devices[device].name );
  782. error(RtError::DEBUG_WARNING);
  783. return FAILURE;
  784. }
  785. stream->bufferSize = *bufferSize;
  786. stream->nBuffers = 1;
  787. // Set the stream format description. Do for each channel in mono mode.
  788. AudioStreamBasicDescription description;
  789. dataSize = sizeof( AudioStreamBasicDescription );
  790. if ( stream->deInterleave[mode] ) nStreams = channels;
  791. else nStreams = 1;
  792. for ( unsigned int i=0; i<nStreams; i++, iChannel++ ) {
  793. err = AudioDeviceGetProperty( id, iChannel, isInput,
  794. kAudioDevicePropertyStreamFormat,
  795. &dataSize, &description );
  796. if (err != noErr) {
  797. sprintf( message, "RtAudio: OSX error getting stream format for device (%s).", devices[device].name );
  798. error(RtError::DEBUG_WARNING);
  799. return FAILURE;
  800. }
  801. // Set the sample rate and data format id.
  802. description.mSampleRate = (double) sampleRate;
  803. description.mFormatID = kAudioFormatLinearPCM;
  804. err = AudioDeviceSetProperty( id, NULL, iChannel, isInput,
  805. kAudioDevicePropertyStreamFormat,
  806. dataSize, &description );
  807. if (err != noErr) {
  808. sprintf( message, "RtAudio: OSX error setting sample rate or data format for device (%s).", devices[device].name );
  809. error(RtError::DEBUG_WARNING);
  810. return FAILURE;
  811. }
  812. }
  813. // Check whether we need byte-swapping (assuming OS X host is big-endian).
  814. iChannel -= nStreams;
  815. err = AudioDeviceGetProperty( id, iChannel, isInput,
  816. kAudioDevicePropertyStreamFormat,
  817. &dataSize, &description );
  818. if (err != noErr) {
  819. sprintf( message, "RtAudio: OSX error getting stream format for device (%s).", devices[device].name );
  820. error(RtError::DEBUG_WARNING);
  821. return FAILURE;
  822. }
  823. stream->doByteSwap[mode] = false;
  824. if ( !description.mFormatFlags & kLinearPCMFormatFlagIsBigEndian )
  825. stream->doByteSwap[mode] = true;
  826. // From the CoreAudio documentation, PCM data must be supplied as
  827. // 32-bit floats.
  828. stream->userFormat = format;
  829. stream->deviceFormat[mode] = RTAUDIO_FLOAT32;
  830. if ( stream->deInterleave[mode] )
  831. stream->nDeviceChannels[mode] = channels;
  832. else
  833. stream->nDeviceChannels[mode] = description.mChannelsPerFrame;
  834. stream->nUserChannels[mode] = channels;
  835. // Set handle and flags for buffer conversion.
  836. stream->handle[mode] = iStream;
  837. stream->doConvertBuffer[mode] = false;
  838. if (stream->userFormat != stream->deviceFormat[mode])
  839. stream->doConvertBuffer[mode] = true;
  840. if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
  841. stream->doConvertBuffer[mode] = true;
  842. if (stream->nUserChannels[mode] > 1 && stream->deInterleave[mode])
  843. stream->doConvertBuffer[mode] = true;
  844. // Allocate necessary internal buffers.
  845. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  846. long buffer_bytes;
  847. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  848. buffer_bytes = stream->nUserChannels[0];
  849. else
  850. buffer_bytes = stream->nUserChannels[1];
  851. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  852. if (stream->userBuffer) free(stream->userBuffer);
  853. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  854. if (stream->userBuffer == NULL)
  855. goto memory_error;
  856. }
  857. if ( stream->deInterleave[mode] ) {
  858. long buffer_bytes;
  859. bool makeBuffer = true;
  860. if ( mode == OUTPUT )
  861. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  862. else { // mode == INPUT
  863. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  864. if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
  865. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  866. if ( buffer_bytes < bytes_out ) makeBuffer = false;
  867. }
  868. }
  869. if ( makeBuffer ) {
  870. buffer_bytes *= *bufferSize;
  871. if (stream->deviceBuffer) free(stream->deviceBuffer);
  872. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  873. if (stream->deviceBuffer == NULL)
  874. goto memory_error;
  875. // If not de-interleaving, we point stream->deviceBuffer to the
  876. // OS X supplied device buffer before doing any necessary data
  877. // conversions. This presents a problem if we have a duplex
  878. // stream using one device which needs de-interleaving and
  879. // another device which doesn't. So, save a pointer to our own
  880. // device buffer in the CALLBACK_INFO structure.
  881. stream->callbackInfo.buffers = stream->deviceBuffer;
  882. }
  883. }
  884. stream->sampleRate = sampleRate;
  885. stream->device[mode] = device;
  886. stream->state = STREAM_STOPPED;
  887. stream->callbackInfo.object = (void *) this;
  888. stream->callbackInfo.waitTime = (unsigned long) (200000.0 * stream->bufferSize / stream->sampleRate);
  889. stream->callbackInfo.device[mode] = id;
  890. if ( stream->mode == OUTPUT && mode == INPUT && stream->device[0] == device )
  891. // Only one callback procedure per device.
  892. stream->mode = DUPLEX;
  893. else {
  894. err = AudioDeviceAddIOProc( id, callbackHandler, (void *) &stream->callbackInfo );
  895. if (err != noErr) {
  896. sprintf( message, "RtAudio: OSX error setting callback for device (%s).", devices[device].name );
  897. error(RtError::DEBUG_WARNING);
  898. return FAILURE;
  899. }
  900. if ( stream->mode == OUTPUT && mode == INPUT )
  901. stream->mode = DUPLEX;
  902. else
  903. stream->mode = mode;
  904. }
  905. // If we wanted to use property listeners, they would be setup here.
  906. return SUCCESS;
  907. memory_error:
  908. if (stream->userBuffer) {
  909. free(stream->userBuffer);
  910. stream->userBuffer = 0;
  911. }
  912. sprintf(message, "RtAudio: OSX error allocating buffer memory (%s).", devices[device].name);
  913. error(RtError::WARNING);
  914. return FAILURE;
  915. }
  916. void RtAudio :: cancelStreamCallback(int streamId)
  917. {
  918. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  919. if (stream->callbackInfo.usingCallback) {
  920. if (stream->state == STREAM_RUNNING)
  921. stopStream( streamId );
  922. MUTEX_LOCK(&stream->mutex);
  923. stream->callbackInfo.usingCallback = false;
  924. stream->callbackInfo.userData = NULL;
  925. stream->state = STREAM_STOPPED;
  926. stream->callbackInfo.callback = NULL;
  927. MUTEX_UNLOCK(&stream->mutex);
  928. }
  929. }
  930. void RtAudio :: closeStream(int streamId)
  931. {
  932. // We don't want an exception to be thrown here because this
  933. // function is called by our class destructor. So, do our own
  934. // streamId check.
  935. if ( streams.find( streamId ) == streams.end() ) {
  936. sprintf(message, "RtAudio: invalid stream identifier!");
  937. error(RtError::WARNING);
  938. return;
  939. }
  940. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
  941. AudioDeviceID id;
  942. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  943. id = devices[stream->device[0]].id[0];
  944. if (stream->state == STREAM_RUNNING)
  945. AudioDeviceStop( id, callbackHandler );
  946. AudioDeviceRemoveIOProc( id, callbackHandler );
  947. }
  948. if (stream->mode == INPUT || ( stream->mode == DUPLEX && stream->device[0] != stream->device[1]) ) {
  949. id = devices[stream->device[1]].id[0];
  950. if (stream->state == STREAM_RUNNING)
  951. AudioDeviceStop( id, callbackHandler );
  952. AudioDeviceRemoveIOProc( id, callbackHandler );
  953. }
  954. pthread_mutex_destroy(&stream->mutex);
  955. if (stream->userBuffer)
  956. free(stream->userBuffer);
  957. if ( stream->deInterleave[0] || stream->deInterleave[1] )
  958. free(stream->callbackInfo.buffers);
  959. free(stream);
  960. streams.erase(streamId);
  961. }
  962. void RtAudio :: startStream(int streamId)
  963. {
  964. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  965. MUTEX_LOCK(&stream->mutex);
  966. if (stream->state == STREAM_RUNNING)
  967. goto unlock;
  968. OSStatus err;
  969. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  970. err = AudioDeviceStart(devices[stream->device[0]].id[0], callbackHandler);
  971. if (err != noErr) {
  972. sprintf(message, "RtAudio: OSX error starting callback procedure on device (%s).",
  973. devices[stream->device[0]].name);
  974. MUTEX_UNLOCK(&stream->mutex);
  975. error(RtError::DRIVER_ERROR);
  976. }
  977. }
  978. if (stream->mode == INPUT || ( stream->mode == DUPLEX && stream->device[0] != stream->device[1]) ) {
  979. err = AudioDeviceStart(devices[stream->device[1]].id[0], callbackHandler);
  980. if (err != noErr) {
  981. sprintf(message, "RtAudio: OSX error starting input callback procedure on device (%s).",
  982. devices[stream->device[0]].name);
  983. MUTEX_UNLOCK(&stream->mutex);
  984. error(RtError::DRIVER_ERROR);
  985. }
  986. }
  987. stream->callbackInfo.streamId = streamId;
  988. stream->state = STREAM_RUNNING;
  989. stream->callbackInfo.blockTick = true;
  990. stream->callbackInfo.stopStream = false;
  991. unlock:
  992. MUTEX_UNLOCK(&stream->mutex);
  993. }
  994. void RtAudio :: stopStream(int streamId)
  995. {
  996. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  997. MUTEX_LOCK(&stream->mutex);
  998. if (stream->state == STREAM_STOPPED)
  999. goto unlock;
  1000. OSStatus err;
  1001. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  1002. err = AudioDeviceStop(devices[stream->device[0]].id[0], callbackHandler);
  1003. if (err != noErr) {
  1004. sprintf(message, "RtAudio: OSX error stopping callback procedure on device (%s).",
  1005. devices[stream->device[0]].name);
  1006. MUTEX_UNLOCK(&stream->mutex);
  1007. error(RtError::DRIVER_ERROR);
  1008. }
  1009. }
  1010. if (stream->mode == INPUT || ( stream->mode == DUPLEX && stream->device[0] != stream->device[1]) ) {
  1011. err = AudioDeviceStop(devices[stream->device[1]].id[0], callbackHandler);
  1012. if (err != noErr) {
  1013. sprintf(message, "RtAudio: OSX error stopping input callback procedure on device (%s).",
  1014. devices[stream->device[0]].name);
  1015. MUTEX_UNLOCK(&stream->mutex);
  1016. error(RtError::DRIVER_ERROR);
  1017. }
  1018. }
  1019. stream->state = STREAM_STOPPED;
  1020. unlock:
  1021. MUTEX_UNLOCK(&stream->mutex);
  1022. }
  1023. void RtAudio :: abortStream(int streamId)
  1024. {
  1025. stopStream( streamId );
  1026. }
  1027. // I don't know how this function can be implemented.
  1028. int RtAudio :: streamWillBlock(int streamId)
  1029. {
  1030. sprintf(message, "RtAudio: streamWillBlock() cannot be implemented for OS X.");
  1031. error(RtError::WARNING);
  1032. return 0;
  1033. }
  1034. void RtAudio :: tickStream(int streamId)
  1035. {
  1036. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  1037. if (stream->state == STREAM_STOPPED)
  1038. return;
  1039. if (stream->callbackInfo.usingCallback) {
  1040. sprintf(message, "RtAudio: tickStream() should not be used when a callback function is set!");
  1041. error(RtError::WARNING);
  1042. return;
  1043. }
  1044. // Block waiting here until the user data is processed in callbackEvent().
  1045. while ( stream->callbackInfo.blockTick )
  1046. usleep(stream->callbackInfo.waitTime);
  1047. MUTEX_LOCK(&stream->mutex);
  1048. stream->callbackInfo.blockTick = true;
  1049. MUTEX_UNLOCK(&stream->mutex);
  1050. }
  1051. void RtAudio :: callbackEvent( int streamId, DEVICE_ID deviceId, void *inData, void *outData )
  1052. {
  1053. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  1054. CALLBACK_INFO *info;
  1055. AudioBufferList *inBufferList = (AudioBufferList *) inData;
  1056. AudioBufferList *outBufferList = (AudioBufferList *) outData;
  1057. if (stream->state == STREAM_STOPPED) return;
  1058. info = (CALLBACK_INFO *) &stream->callbackInfo;
  1059. if ( !info->usingCallback ) {
  1060. // Block waiting here until we get new user data in tickStream().
  1061. while ( !info->blockTick )
  1062. usleep(info->waitTime);
  1063. }
  1064. else if ( info->stopStream ) {
  1065. // Check if the stream should be stopped (via the previous user
  1066. // callback return value). We stop the stream here, rather than
  1067. // after the function call, so that output data can first be
  1068. // processed.
  1069. this->stopStream(info->streamId);
  1070. return;
  1071. }
  1072. MUTEX_LOCK(&stream->mutex);
  1073. // Invoke user callback first, to get fresh output data. Don't
  1074. // invoke the user callback if duplex mode, the input/output devices
  1075. // are different, and this function is called for the input device.
  1076. if ( info->usingCallback && (stream->mode != DUPLEX || deviceId == info->device[0] ) ) {
  1077. RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) info->callback;
  1078. info->stopStream = callback(stream->userBuffer, stream->bufferSize, info->userData);
  1079. }
  1080. if ( stream->mode == OUTPUT || ( stream->mode == DUPLEX && deviceId == info->device[0] ) ) {
  1081. if (stream->doConvertBuffer[0]) {
  1082. if ( !stream->deInterleave[0] )
  1083. stream->deviceBuffer = (char *) outBufferList->mBuffers[stream->handle[0]].mData;
  1084. else
  1085. stream->deviceBuffer = (char *) stream->callbackInfo.buffers;
  1086. convertStreamBuffer(stream, OUTPUT);
  1087. if ( stream->doByteSwap[0] )
  1088. byteSwapBuffer(stream->deviceBuffer,
  1089. stream->bufferSize * stream->nDeviceChannels[0],
  1090. stream->deviceFormat[0]);
  1091. if ( stream->deInterleave[0] ) {
  1092. int bufferBytes = outBufferList->mBuffers[stream->handle[0]].mDataByteSize;
  1093. for ( int i=0; i<stream->nDeviceChannels[0]; i++ ) {
  1094. memcpy(outBufferList->mBuffers[stream->handle[0]+i].mData,
  1095. &stream->deviceBuffer[i*bufferBytes], bufferBytes );
  1096. }
  1097. }
  1098. }
  1099. else {
  1100. if (stream->doByteSwap[0])
  1101. byteSwapBuffer(stream->userBuffer,
  1102. stream->bufferSize * stream->nUserChannels[0],
  1103. stream->userFormat);
  1104. memcpy(outBufferList->mBuffers[stream->handle[0]].mData,
  1105. stream->userBuffer,
  1106. outBufferList->mBuffers[stream->handle[0]].mDataByteSize );
  1107. }
  1108. }
  1109. if ( stream->mode == INPUT || ( stream->mode == DUPLEX && deviceId == info->device[1] ) ) {
  1110. if (stream->doConvertBuffer[1]) {
  1111. if ( stream->deInterleave[1] ) {
  1112. stream->deviceBuffer = (char *) stream->callbackInfo.buffers;
  1113. int bufferBytes = inBufferList->mBuffers[stream->handle[1]].mDataByteSize;
  1114. for ( int i=0; i<stream->nDeviceChannels[1]; i++ ) {
  1115. memcpy(&stream->deviceBuffer[i*bufferBytes],
  1116. inBufferList->mBuffers[stream->handle[1]+i].mData, bufferBytes );
  1117. }
  1118. }
  1119. else
  1120. stream->deviceBuffer = (char *) inBufferList->mBuffers[stream->handle[1]].mData;
  1121. if ( stream->doByteSwap[1] )
  1122. byteSwapBuffer(stream->deviceBuffer,
  1123. stream->bufferSize * stream->nDeviceChannels[1],
  1124. stream->deviceFormat[1]);
  1125. convertStreamBuffer(stream, INPUT);
  1126. }
  1127. else {
  1128. memcpy(stream->userBuffer,
  1129. inBufferList->mBuffers[stream->handle[1]].mData,
  1130. inBufferList->mBuffers[stream->handle[1]].mDataByteSize );
  1131. if (stream->doByteSwap[1])
  1132. byteSwapBuffer(stream->userBuffer,
  1133. stream->bufferSize * stream->nUserChannels[1],
  1134. stream->userFormat);
  1135. }
  1136. }
  1137. if ( !info->usingCallback && (stream->mode != DUPLEX || deviceId == info->device[1] ) )
  1138. info->blockTick = false;
  1139. MUTEX_UNLOCK(&stream->mutex);
  1140. }
  1141. void RtAudio :: setStreamCallback(int streamId, RTAUDIO_CALLBACK callback, void *userData)
  1142. {
  1143. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  1144. stream->callbackInfo.callback = (void *) callback;
  1145. stream->callbackInfo.userData = userData;
  1146. stream->callbackInfo.usingCallback = true;
  1147. }
  1148. //******************** End of __MACOSX_CORE__ *********************//
  1149. #elif defined(__LINUX_ALSA__)
  1150. #define MAX_DEVICES 16
  1151. void RtAudio :: initialize(void)
  1152. {
  1153. int card, result, device;
  1154. char name[32];
  1155. const char *cardId;
  1156. char deviceNames[MAX_DEVICES][32];
  1157. snd_ctl_t *handle;
  1158. snd_ctl_card_info_t *info;
  1159. snd_ctl_card_info_alloca(&info);
  1160. // Count cards and devices
  1161. nDevices = 0;
  1162. card = -1;
  1163. snd_card_next(&card);
  1164. while ( card >= 0 ) {
  1165. sprintf(name, "hw:%d", card);
  1166. result = snd_ctl_open(&handle, name, 0);
  1167. if (result < 0) {
  1168. sprintf(message, "RtAudio: ALSA control open (%i): %s.", card, snd_strerror(result));
  1169. error(RtError::DEBUG_WARNING);
  1170. goto next_card;
  1171. }
  1172. result = snd_ctl_card_info(handle, info);
  1173. if (result < 0) {
  1174. sprintf(message, "RtAudio: ALSA control hardware info (%i): %s.", card, snd_strerror(result));
  1175. error(RtError::DEBUG_WARNING);
  1176. goto next_card;
  1177. }
  1178. cardId = snd_ctl_card_info_get_id(info);
  1179. device = -1;
  1180. while (1) {
  1181. result = snd_ctl_pcm_next_device(handle, &device);
  1182. if (result < 0) {
  1183. sprintf(message, "RtAudio: ALSA control next device (%i): %s.", card, snd_strerror(result));
  1184. error(RtError::DEBUG_WARNING);
  1185. break;
  1186. }
  1187. if (device < 0)
  1188. break;
  1189. if ( strlen(cardId) )
  1190. sprintf( deviceNames[nDevices++], "hw:%s,%d", cardId, device );
  1191. else
  1192. sprintf( deviceNames[nDevices++], "hw:%d,%d", card, device );
  1193. if ( nDevices > MAX_DEVICES ) break;
  1194. }
  1195. if ( nDevices > MAX_DEVICES ) break;
  1196. next_card:
  1197. snd_ctl_close(handle);
  1198. snd_card_next(&card);
  1199. }
  1200. if (nDevices == 0) return;
  1201. // Allocate the RTAUDIO_DEVICE structures.
  1202. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  1203. if (devices == NULL) {
  1204. sprintf(message, "RtAudio: memory allocation error!");
  1205. error(RtError::MEMORY_ERROR);
  1206. }
  1207. // Write device ascii identifiers to device structures and then
  1208. // probe the device capabilities.
  1209. for (int i=0; i<nDevices; i++) {
  1210. strncpy(devices[i].name, deviceNames[i], 32);
  1211. //probeDeviceInfo(&devices[i]);
  1212. }
  1213. }
  1214. int RtAudio :: getDefaultInputDevice(void)
  1215. {
  1216. // No ALSA API functions for default devices.
  1217. return 0;
  1218. }
  1219. int RtAudio :: getDefaultOutputDevice(void)
  1220. {
  1221. // No ALSA API functions for default devices.
  1222. return 0;
  1223. }
  1224. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  1225. {
  1226. int err;
  1227. int open_mode = SND_PCM_ASYNC;
  1228. snd_pcm_t *handle;
  1229. snd_ctl_t *chandle;
  1230. snd_pcm_stream_t stream;
  1231. snd_pcm_info_t *pcminfo;
  1232. snd_pcm_info_alloca(&pcminfo);
  1233. snd_pcm_hw_params_t *params;
  1234. snd_pcm_hw_params_alloca(&params);
  1235. char name[32];
  1236. char *card;
  1237. // Open the control interface for this card.
  1238. strncpy( name, info->name, 32 );
  1239. card = strtok(name, ",");
  1240. err = snd_ctl_open(&chandle, card, 0);
  1241. if (err < 0) {
  1242. sprintf(message, "RtAudio: ALSA control open (%s): %s.", card, snd_strerror(err));
  1243. error(RtError::DEBUG_WARNING);
  1244. return;
  1245. }
  1246. unsigned int dev = (unsigned int) atoi( strtok(NULL, ",") );
  1247. // First try for playback
  1248. stream = SND_PCM_STREAM_PLAYBACK;
  1249. snd_pcm_info_set_device(pcminfo, dev);
  1250. snd_pcm_info_set_subdevice(pcminfo, 0);
  1251. snd_pcm_info_set_stream(pcminfo, stream);
  1252. if ((err = snd_ctl_pcm_info(chandle, pcminfo)) < 0) {
  1253. if (err == -ENOENT) {
  1254. sprintf(message, "RtAudio: ALSA pcm device (%s) doesn't handle output!", info->name);
  1255. error(RtError::DEBUG_WARNING);
  1256. }
  1257. else {
  1258. sprintf(message, "RtAudio: ALSA snd_ctl_pcm_info error for device (%s) output: %s",
  1259. info->name, snd_strerror(err));
  1260. error(RtError::DEBUG_WARNING);
  1261. }
  1262. goto capture_probe;
  1263. }
  1264. err = snd_pcm_open(&handle, info->name, stream, open_mode | SND_PCM_NONBLOCK );
  1265. if (err < 0) {
  1266. if ( err == EBUSY )
  1267. sprintf(message, "RtAudio: ALSA pcm playback device (%s) is busy: %s.",
  1268. info->name, snd_strerror(err));
  1269. else
  1270. sprintf(message, "RtAudio: ALSA pcm playback open (%s) error: %s.",
  1271. info->name, snd_strerror(err));
  1272. error(RtError::DEBUG_WARNING);
  1273. goto capture_probe;
  1274. }
  1275. // We have an open device ... allocate the parameter structure.
  1276. err = snd_pcm_hw_params_any(handle, params);
  1277. if (err < 0) {
  1278. snd_pcm_close(handle);
  1279. sprintf(message, "RtAudio: ALSA hardware probe error (%s): %s.",
  1280. info->name, snd_strerror(err));
  1281. error(RtError::WARNING);
  1282. goto capture_probe;
  1283. }
  1284. // Get output channel information.
  1285. info->minOutputChannels = snd_pcm_hw_params_get_channels_min(params);
  1286. info->maxOutputChannels = snd_pcm_hw_params_get_channels_max(params);
  1287. snd_pcm_close(handle);
  1288. capture_probe:
  1289. // Now try for capture
  1290. stream = SND_PCM_STREAM_CAPTURE;
  1291. snd_pcm_info_set_stream(pcminfo, stream);
  1292. err = snd_ctl_pcm_info(chandle, pcminfo);
  1293. snd_ctl_close(chandle);
  1294. if ( err < 0 ) {
  1295. if (err == -ENOENT) {
  1296. sprintf(message, "RtAudio: ALSA pcm device (%s) doesn't handle input!", info->name);
  1297. error(RtError::DEBUG_WARNING);
  1298. }
  1299. else {
  1300. sprintf(message, "RtAudio: ALSA snd_ctl_pcm_info error for device (%s) input: %s",
  1301. info->name, snd_strerror(err));
  1302. error(RtError::DEBUG_WARNING);
  1303. }
  1304. if (info->maxOutputChannels == 0)
  1305. // didn't open for playback either ... device invalid
  1306. return;
  1307. goto probe_parameters;
  1308. }
  1309. err = snd_pcm_open(&handle, info->name, stream, open_mode | SND_PCM_NONBLOCK);
  1310. if (err < 0) {
  1311. if ( err == EBUSY )
  1312. sprintf(message, "RtAudio: ALSA pcm capture device (%s) is busy: %s.",
  1313. info->name, snd_strerror(err));
  1314. else
  1315. sprintf(message, "RtAudio: ALSA pcm capture open (%s) error: %s.",
  1316. info->name, snd_strerror(err));
  1317. error(RtError::DEBUG_WARNING);
  1318. if (info->maxOutputChannels == 0)
  1319. // didn't open for playback either ... device invalid
  1320. return;
  1321. goto probe_parameters;
  1322. }
  1323. // We have an open capture device ... allocate the parameter structure.
  1324. err = snd_pcm_hw_params_any(handle, params);
  1325. if (err < 0) {
  1326. snd_pcm_close(handle);
  1327. sprintf(message, "RtAudio: ALSA hardware probe error (%s): %s.",
  1328. info->name, snd_strerror(err));
  1329. error(RtError::WARNING);
  1330. if (info->maxOutputChannels > 0)
  1331. goto probe_parameters;
  1332. else
  1333. return;
  1334. }
  1335. // Get input channel information.
  1336. info->minInputChannels = snd_pcm_hw_params_get_channels_min(params);
  1337. info->maxInputChannels = snd_pcm_hw_params_get_channels_max(params);
  1338. snd_pcm_close(handle);
  1339. // If device opens for both playback and capture, we determine the channels.
  1340. if (info->maxOutputChannels == 0 || info->maxInputChannels == 0)
  1341. goto probe_parameters;
  1342. info->hasDuplexSupport = true;
  1343. info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ?
  1344. info->maxInputChannels : info->maxOutputChannels;
  1345. info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ?
  1346. info->minInputChannels : info->minOutputChannels;
  1347. probe_parameters:
  1348. // At this point, we just need to figure out the supported data
  1349. // formats and sample rates. We'll proceed by opening the device in
  1350. // the direction with the maximum number of channels, or playback if
  1351. // they are equal. This might limit our sample rate options, but so
  1352. // be it.
  1353. if (info->maxOutputChannels >= info->maxInputChannels)
  1354. stream = SND_PCM_STREAM_PLAYBACK;
  1355. else
  1356. stream = SND_PCM_STREAM_CAPTURE;
  1357. err = snd_pcm_open(&handle, info->name, stream, open_mode);
  1358. if (err < 0) {
  1359. sprintf(message, "RtAudio: ALSA pcm (%s) won't reopen during probe: %s.",
  1360. info->name, snd_strerror(err));
  1361. error(RtError::WARNING);
  1362. return;
  1363. }
  1364. // We have an open device ... allocate the parameter structure.
  1365. err = snd_pcm_hw_params_any(handle, params);
  1366. if (err < 0) {
  1367. snd_pcm_close(handle);
  1368. sprintf(message, "RtAudio: ALSA hardware reopen probe error (%s): %s.",
  1369. info->name, snd_strerror(err));
  1370. error(RtError::WARNING);
  1371. return;
  1372. }
  1373. // Test a non-standard sample rate to see if continuous rate is supported.
  1374. int dir = 0;
  1375. if (snd_pcm_hw_params_test_rate(handle, params, 35500, dir) == 0) {
  1376. // It appears that continuous sample rate support is available.
  1377. info->nSampleRates = -1;
  1378. info->sampleRates[0] = snd_pcm_hw_params_get_rate_min(params, &dir);
  1379. info->sampleRates[1] = snd_pcm_hw_params_get_rate_max(params, &dir);
  1380. }
  1381. else {
  1382. // No continuous rate support ... test our discrete set of sample rate values.
  1383. info->nSampleRates = 0;
  1384. for (int i=0; i<MAX_SAMPLE_RATES; i++) {
  1385. if (snd_pcm_hw_params_test_rate(handle, params, SAMPLE_RATES[i], dir) == 0) {
  1386. info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
  1387. info->nSampleRates++;
  1388. }
  1389. }
  1390. if (info->nSampleRates == 0) {
  1391. snd_pcm_close(handle);
  1392. return;
  1393. }
  1394. }
  1395. // Probe the supported data formats ... we don't care about endian-ness just yet
  1396. snd_pcm_format_t format;
  1397. info->nativeFormats = 0;
  1398. format = SND_PCM_FORMAT_S8;
  1399. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  1400. info->nativeFormats |= RTAUDIO_SINT8;
  1401. format = SND_PCM_FORMAT_S16;
  1402. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  1403. info->nativeFormats |= RTAUDIO_SINT16;
  1404. format = SND_PCM_FORMAT_S24;
  1405. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  1406. info->nativeFormats |= RTAUDIO_SINT24;
  1407. format = SND_PCM_FORMAT_S32;
  1408. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  1409. info->nativeFormats |= RTAUDIO_SINT32;
  1410. format = SND_PCM_FORMAT_FLOAT;
  1411. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  1412. info->nativeFormats |= RTAUDIO_FLOAT32;
  1413. format = SND_PCM_FORMAT_FLOAT64;
  1414. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  1415. info->nativeFormats |= RTAUDIO_FLOAT64;
  1416. // Check that we have at least one supported format
  1417. if (info->nativeFormats == 0) {
  1418. snd_pcm_close(handle);
  1419. sprintf(message, "RtAudio: ALSA PCM device (%s) data format not supported by RtAudio.",
  1420. info->name);
  1421. error(RtError::WARNING);
  1422. return;
  1423. }
  1424. // That's all ... close the device and return
  1425. snd_pcm_close(handle);
  1426. info->probed = true;
  1427. return;
  1428. }
  1429. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  1430. STREAM_MODE mode, int channels,
  1431. int sampleRate, RTAUDIO_FORMAT format,
  1432. int *bufferSize, int numberOfBuffers)
  1433. {
  1434. #if defined(__RTAUDIO_DEBUG__)
  1435. snd_output_t *out;
  1436. snd_output_stdio_attach(&out, stderr, 0);
  1437. #endif
  1438. // I'm not using the "plug" interface ... too much inconsistent behavior.
  1439. const char *name = devices[device].name;
  1440. snd_pcm_stream_t alsa_stream;
  1441. if (mode == OUTPUT)
  1442. alsa_stream = SND_PCM_STREAM_PLAYBACK;
  1443. else
  1444. alsa_stream = SND_PCM_STREAM_CAPTURE;
  1445. int err;
  1446. snd_pcm_t *handle;
  1447. int alsa_open_mode = SND_PCM_ASYNC;
  1448. err = snd_pcm_open(&handle, name, alsa_stream, alsa_open_mode);
  1449. if (err < 0) {
  1450. sprintf(message,"RtAudio: ALSA pcm device (%s) won't open: %s.",
  1451. name, snd_strerror(err));
  1452. error(RtError::WARNING);
  1453. return FAILURE;
  1454. }
  1455. // Fill the parameter structure.
  1456. snd_pcm_hw_params_t *hw_params;
  1457. snd_pcm_hw_params_alloca(&hw_params);
  1458. err = snd_pcm_hw_params_any(handle, hw_params);
  1459. if (err < 0) {
  1460. snd_pcm_close(handle);
  1461. sprintf(message, "RtAudio: ALSA error getting parameter handle (%s): %s.",
  1462. name, snd_strerror(err));
  1463. error(RtError::WARNING);
  1464. return FAILURE;
  1465. }
  1466. #if defined(__RTAUDIO_DEBUG__)
  1467. fprintf(stderr, "\nRtAudio: ALSA dump hardware params just after device open:\n\n");
  1468. snd_pcm_hw_params_dump(hw_params, out);
  1469. #endif
  1470. // Set access ... try interleaved access first, then non-interleaved
  1471. if ( !snd_pcm_hw_params_test_access( handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) ) {
  1472. err = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
  1473. }
  1474. else if ( !snd_pcm_hw_params_test_access( handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED) ) {
  1475. err = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED);
  1476. stream->deInterleave[mode] = true;
  1477. }
  1478. else {
  1479. snd_pcm_close(handle);
  1480. sprintf(message, "RtAudio: ALSA device (%s) access not supported by RtAudio.", name);
  1481. error(RtError::WARNING);
  1482. return FAILURE;
  1483. }
  1484. if (err < 0) {
  1485. snd_pcm_close(handle);
  1486. sprintf(message, "RtAudio: ALSA error setting access ( (%s): %s.", name, snd_strerror(err));
  1487. error(RtError::WARNING);
  1488. return FAILURE;
  1489. }
  1490. // Determine how to set the device format.
  1491. stream->userFormat = format;
  1492. snd_pcm_format_t device_format;
  1493. if (format == RTAUDIO_SINT8)
  1494. device_format = SND_PCM_FORMAT_S8;
  1495. else if (format == RTAUDIO_SINT16)
  1496. device_format = SND_PCM_FORMAT_S16;
  1497. else if (format == RTAUDIO_SINT24)
  1498. device_format = SND_PCM_FORMAT_S24;
  1499. else if (format == RTAUDIO_SINT32)
  1500. device_format = SND_PCM_FORMAT_S32;
  1501. else if (format == RTAUDIO_FLOAT32)
  1502. device_format = SND_PCM_FORMAT_FLOAT;
  1503. else if (format == RTAUDIO_FLOAT64)
  1504. device_format = SND_PCM_FORMAT_FLOAT64;
  1505. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  1506. stream->deviceFormat[mode] = format;
  1507. goto set_format;
  1508. }
  1509. // The user requested format is not natively supported by the device.
  1510. device_format = SND_PCM_FORMAT_FLOAT64;
  1511. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  1512. stream->deviceFormat[mode] = RTAUDIO_FLOAT64;
  1513. goto set_format;
  1514. }
  1515. device_format = SND_PCM_FORMAT_FLOAT;
  1516. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  1517. stream->deviceFormat[mode] = RTAUDIO_FLOAT32;
  1518. goto set_format;
  1519. }
  1520. device_format = SND_PCM_FORMAT_S32;
  1521. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  1522. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  1523. goto set_format;
  1524. }
  1525. device_format = SND_PCM_FORMAT_S24;
  1526. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  1527. stream->deviceFormat[mode] = RTAUDIO_SINT24;
  1528. goto set_format;
  1529. }
  1530. device_format = SND_PCM_FORMAT_S16;
  1531. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  1532. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  1533. goto set_format;
  1534. }
  1535. device_format = SND_PCM_FORMAT_S8;
  1536. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  1537. stream->deviceFormat[mode] = RTAUDIO_SINT8;
  1538. goto set_format;
  1539. }
  1540. // If we get here, no supported format was found.
  1541. sprintf(message,"RtAudio: ALSA pcm device (%s) data format not supported by RtAudio.", name);
  1542. snd_pcm_close(handle);
  1543. error(RtError::WARNING);
  1544. return FAILURE;
  1545. set_format:
  1546. err = snd_pcm_hw_params_set_format(handle, hw_params, device_format);
  1547. if (err < 0) {
  1548. snd_pcm_close(handle);
  1549. sprintf(message, "RtAudio: ALSA error setting format (%s): %s.",
  1550. name, snd_strerror(err));
  1551. error(RtError::WARNING);
  1552. return FAILURE;
  1553. }
  1554. // Determine whether byte-swaping is necessary.
  1555. stream->doByteSwap[mode] = false;
  1556. if (device_format != SND_PCM_FORMAT_S8) {
  1557. err = snd_pcm_format_cpu_endian(device_format);
  1558. if (err == 0)
  1559. stream->doByteSwap[mode] = true;
  1560. else if (err < 0) {
  1561. snd_pcm_close(handle);
  1562. sprintf(message, "RtAudio: ALSA error getting format endian-ness (%s): %s.",
  1563. name, snd_strerror(err));
  1564. error(RtError::WARNING);
  1565. return FAILURE;
  1566. }
  1567. }
  1568. // Set the sample rate.
  1569. err = snd_pcm_hw_params_set_rate(handle, hw_params, (unsigned int)sampleRate, 0);
  1570. if (err < 0) {
  1571. snd_pcm_close(handle);
  1572. sprintf(message, "RtAudio: ALSA error setting sample rate (%d) on device (%s): %s.",
  1573. sampleRate, name, snd_strerror(err));
  1574. error(RtError::WARNING);
  1575. return FAILURE;
  1576. }
  1577. // Determine the number of channels for this device. We support a possible
  1578. // minimum device channel number > than the value requested by the user.
  1579. stream->nUserChannels[mode] = channels;
  1580. int device_channels = snd_pcm_hw_params_get_channels_max(hw_params);
  1581. if (device_channels < channels) {
  1582. snd_pcm_close(handle);
  1583. sprintf(message, "RtAudio: channels (%d) not supported by device (%s).",
  1584. channels, name);
  1585. error(RtError::WARNING);
  1586. return FAILURE;
  1587. }
  1588. device_channels = snd_pcm_hw_params_get_channels_min(hw_params);
  1589. if (device_channels < channels) device_channels = channels;
  1590. stream->nDeviceChannels[mode] = device_channels;
  1591. // Set the device channels.
  1592. err = snd_pcm_hw_params_set_channels(handle, hw_params, device_channels);
  1593. if (err < 0) {
  1594. snd_pcm_close(handle);
  1595. sprintf(message, "RtAudio: ALSA error setting channels (%d) on device (%s): %s.",
  1596. device_channels, name, snd_strerror(err));
  1597. error(RtError::WARNING);
  1598. return FAILURE;
  1599. }
  1600. // Set the buffer number, which in ALSA is referred to as the "period".
  1601. int dir;
  1602. int periods = numberOfBuffers;
  1603. // Even though the hardware might allow 1 buffer, it won't work reliably.
  1604. if (periods < 2) periods = 2;
  1605. err = snd_pcm_hw_params_get_periods_min(hw_params, &dir);
  1606. if (err > periods) periods = err;
  1607. err = snd_pcm_hw_params_get_periods_max(hw_params, &dir);
  1608. if (err < periods) periods = err;
  1609. err = snd_pcm_hw_params_set_periods(handle, hw_params, periods, 0);
  1610. if (err < 0) {
  1611. snd_pcm_close(handle);
  1612. sprintf(message, "RtAudio: ALSA error setting periods (%s): %s.",
  1613. name, snd_strerror(err));
  1614. error(RtError::WARNING);
  1615. return FAILURE;
  1616. }
  1617. // Set the buffer (or period) size.
  1618. err = snd_pcm_hw_params_get_period_size_min(hw_params, &dir);
  1619. if (err > *bufferSize) *bufferSize = err;
  1620. err = snd_pcm_hw_params_set_period_size(handle, hw_params, *bufferSize, 0);
  1621. if (err < 0) {
  1622. snd_pcm_close(handle);
  1623. sprintf(message, "RtAudio: ALSA error setting period size (%s): %s.",
  1624. name, snd_strerror(err));
  1625. error(RtError::WARNING);
  1626. return FAILURE;
  1627. }
  1628. // If attempting to setup a duplex stream, the bufferSize parameter
  1629. // MUST be the same in both directions!
  1630. if ( stream->mode == OUTPUT && mode == INPUT && *bufferSize != stream->bufferSize ) {
  1631. sprintf( message, "RtAudio: ALSA error setting buffer size for duplex stream on device (%s).",
  1632. name );
  1633. error(RtError::DEBUG_WARNING);
  1634. return FAILURE;
  1635. }
  1636. stream->bufferSize = *bufferSize;
  1637. // Install the hardware configuration
  1638. err = snd_pcm_hw_params(handle, hw_params);
  1639. if (err < 0) {
  1640. snd_pcm_close(handle);
  1641. sprintf(message, "RtAudio: ALSA error installing hardware configuration (%s): %s.",
  1642. name, snd_strerror(err));
  1643. error(RtError::WARNING);
  1644. return FAILURE;
  1645. }
  1646. #if defined(__RTAUDIO_DEBUG__)
  1647. fprintf(stderr, "\nRtAudio: ALSA dump hardware params after installation:\n\n");
  1648. snd_pcm_hw_params_dump(hw_params, out);
  1649. #endif
  1650. /*
  1651. // Install the software configuration
  1652. snd_pcm_sw_params_t *sw_params = NULL;
  1653. snd_pcm_sw_params_alloca(&sw_params);
  1654. snd_pcm_sw_params_current(handle, sw_params);
  1655. err = snd_pcm_sw_params(handle, sw_params);
  1656. if (err < 0) {
  1657. snd_pcm_close(handle);
  1658. sprintf(message, "RtAudio: ALSA error installing software configuration (%s): %s.",
  1659. name, snd_strerror(err));
  1660. error(RtError::WARNING);
  1661. return FAILURE;
  1662. }
  1663. */
  1664. // Set handle and flags for buffer conversion
  1665. stream->handle[mode] = handle;
  1666. stream->doConvertBuffer[mode] = false;
  1667. if (stream->userFormat != stream->deviceFormat[mode])
  1668. stream->doConvertBuffer[mode] = true;
  1669. if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
  1670. stream->doConvertBuffer[mode] = true;
  1671. if (stream->nUserChannels[mode] > 1 && stream->deInterleave[mode])
  1672. stream->doConvertBuffer[mode] = true;
  1673. // Allocate necessary internal buffers
  1674. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  1675. long buffer_bytes;
  1676. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  1677. buffer_bytes = stream->nUserChannels[0];
  1678. else
  1679. buffer_bytes = stream->nUserChannels[1];
  1680. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  1681. if (stream->userBuffer) free(stream->userBuffer);
  1682. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  1683. if (stream->userBuffer == NULL)
  1684. goto memory_error;
  1685. }
  1686. if ( stream->doConvertBuffer[mode] ) {
  1687. long buffer_bytes;
  1688. bool makeBuffer = true;
  1689. if ( mode == OUTPUT )
  1690. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  1691. else { // mode == INPUT
  1692. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  1693. if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
  1694. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  1695. if ( buffer_bytes < bytes_out ) makeBuffer = false;
  1696. }
  1697. }
  1698. if ( makeBuffer ) {
  1699. buffer_bytes *= *bufferSize;
  1700. if (stream->deviceBuffer) free(stream->deviceBuffer);
  1701. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  1702. if (stream->deviceBuffer == NULL)
  1703. goto memory_error;
  1704. }
  1705. }
  1706. stream->device[mode] = device;
  1707. stream->state = STREAM_STOPPED;
  1708. if ( stream->mode == OUTPUT && mode == INPUT )
  1709. // We had already set up an output stream.
  1710. stream->mode = DUPLEX;
  1711. else
  1712. stream->mode = mode;
  1713. stream->nBuffers = periods;
  1714. stream->sampleRate = sampleRate;
  1715. return SUCCESS;
  1716. memory_error:
  1717. if (stream->handle[0]) {
  1718. snd_pcm_close(stream->handle[0]);
  1719. stream->handle[0] = 0;
  1720. }
  1721. if (stream->handle[1]) {
  1722. snd_pcm_close(stream->handle[1]);
  1723. stream->handle[1] = 0;
  1724. }
  1725. if (stream->userBuffer) {
  1726. free(stream->userBuffer);
  1727. stream->userBuffer = 0;
  1728. }
  1729. sprintf(message, "RtAudio: ALSA error allocating buffer memory (%s).", name);
  1730. error(RtError::WARNING);
  1731. return FAILURE;
  1732. }
  1733. void RtAudio :: closeStream(int streamId)
  1734. {
  1735. // We don't want an exception to be thrown here because this
  1736. // function is called by our class destructor. So, do our own
  1737. // streamId check.
  1738. if ( streams.find( streamId ) == streams.end() ) {
  1739. sprintf(message, "RtAudio: invalid stream identifier!");
  1740. error(RtError::WARNING);
  1741. return;
  1742. }
  1743. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
  1744. if (stream->callbackInfo.usingCallback) {
  1745. pthread_cancel(stream->callbackInfo.thread);
  1746. pthread_join(stream->callbackInfo.thread, NULL);
  1747. }
  1748. if (stream->state == STREAM_RUNNING) {
  1749. if (stream->mode == OUTPUT || stream->mode == DUPLEX)
  1750. snd_pcm_drop(stream->handle[0]);
  1751. if (stream->mode == INPUT || stream->mode == DUPLEX)
  1752. snd_pcm_drop(stream->handle[1]);
  1753. }
  1754. pthread_mutex_destroy(&stream->mutex);
  1755. if (stream->handle[0])
  1756. snd_pcm_close(stream->handle[0]);
  1757. if (stream->handle[1])
  1758. snd_pcm_close(stream->handle[1]);
  1759. if (stream->userBuffer)
  1760. free(stream->userBuffer);
  1761. if (stream->deviceBuffer)
  1762. free(stream->deviceBuffer);
  1763. free(stream);
  1764. streams.erase(streamId);
  1765. }
  1766. void RtAudio :: startStream(int streamId)
  1767. {
  1768. // This method calls snd_pcm_prepare if the device isn't already in that state.
  1769. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  1770. MUTEX_LOCK(&stream->mutex);
  1771. if (stream->state == STREAM_RUNNING)
  1772. goto unlock;
  1773. int err;
  1774. snd_pcm_state_t state;
  1775. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  1776. state = snd_pcm_state(stream->handle[0]);
  1777. if (state != SND_PCM_STATE_PREPARED) {
  1778. err = snd_pcm_prepare(stream->handle[0]);
  1779. if (err < 0) {
  1780. sprintf(message, "RtAudio: ALSA error preparing pcm device (%s): %s.",
  1781. devices[stream->device[0]].name, snd_strerror(err));
  1782. MUTEX_UNLOCK(&stream->mutex);
  1783. error(RtError::DRIVER_ERROR);
  1784. }
  1785. }
  1786. }
  1787. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  1788. state = snd_pcm_state(stream->handle[1]);
  1789. if (state != SND_PCM_STATE_PREPARED) {
  1790. err = snd_pcm_prepare(stream->handle[1]);
  1791. if (err < 0) {
  1792. sprintf(message, "RtAudio: ALSA error preparing pcm device (%s): %s.",
  1793. devices[stream->device[1]].name, snd_strerror(err));
  1794. MUTEX_UNLOCK(&stream->mutex);
  1795. error(RtError::DRIVER_ERROR);
  1796. }
  1797. }
  1798. }
  1799. stream->state = STREAM_RUNNING;
  1800. unlock:
  1801. MUTEX_UNLOCK(&stream->mutex);
  1802. }
  1803. void RtAudio :: stopStream(int streamId)
  1804. {
  1805. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  1806. MUTEX_LOCK(&stream->mutex);
  1807. if (stream->state == STREAM_STOPPED)
  1808. goto unlock;
  1809. int err;
  1810. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  1811. err = snd_pcm_drain(stream->handle[0]);
  1812. if (err < 0) {
  1813. sprintf(message, "RtAudio: ALSA error draining pcm device (%s): %s.",
  1814. devices[stream->device[0]].name, snd_strerror(err));
  1815. MUTEX_UNLOCK(&stream->mutex);
  1816. error(RtError::DRIVER_ERROR);
  1817. }
  1818. }
  1819. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  1820. err = snd_pcm_drain(stream->handle[1]);
  1821. if (err < 0) {
  1822. sprintf(message, "RtAudio: ALSA error draining pcm device (%s): %s.",
  1823. devices[stream->device[1]].name, snd_strerror(err));
  1824. MUTEX_UNLOCK(&stream->mutex);
  1825. error(RtError::DRIVER_ERROR);
  1826. }
  1827. }
  1828. stream->state = STREAM_STOPPED;
  1829. unlock:
  1830. MUTEX_UNLOCK(&stream->mutex);
  1831. }
  1832. void RtAudio :: abortStream(int streamId)
  1833. {
  1834. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  1835. MUTEX_LOCK(&stream->mutex);
  1836. if (stream->state == STREAM_STOPPED)
  1837. goto unlock;
  1838. int err;
  1839. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  1840. err = snd_pcm_drop(stream->handle[0]);
  1841. if (err < 0) {
  1842. sprintf(message, "RtAudio: ALSA error draining pcm device (%s): %s.",
  1843. devices[stream->device[0]].name, snd_strerror(err));
  1844. MUTEX_UNLOCK(&stream->mutex);
  1845. error(RtError::DRIVER_ERROR);
  1846. }
  1847. }
  1848. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  1849. err = snd_pcm_drop(stream->handle[1]);
  1850. if (err < 0) {
  1851. sprintf(message, "RtAudio: ALSA error draining pcm device (%s): %s.",
  1852. devices[stream->device[1]].name, snd_strerror(err));
  1853. MUTEX_UNLOCK(&stream->mutex);
  1854. error(RtError::DRIVER_ERROR);
  1855. }
  1856. }
  1857. stream->state = STREAM_STOPPED;
  1858. unlock:
  1859. MUTEX_UNLOCK(&stream->mutex);
  1860. }
  1861. int RtAudio :: streamWillBlock(int streamId)
  1862. {
  1863. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  1864. MUTEX_LOCK(&stream->mutex);
  1865. int err = 0, frames = 0;
  1866. if (stream->state == STREAM_STOPPED)
  1867. goto unlock;
  1868. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  1869. err = snd_pcm_avail_update(stream->handle[0]);
  1870. if (err < 0) {
  1871. sprintf(message, "RtAudio: ALSA error getting available frames for device (%s): %s.",
  1872. devices[stream->device[0]].name, snd_strerror(err));
  1873. MUTEX_UNLOCK(&stream->mutex);
  1874. error(RtError::DRIVER_ERROR);
  1875. }
  1876. }
  1877. frames = err;
  1878. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  1879. err = snd_pcm_avail_update(stream->handle[1]);
  1880. if (err < 0) {
  1881. sprintf(message, "RtAudio: ALSA error getting available frames for device (%s): %s.",
  1882. devices[stream->device[1]].name, snd_strerror(err));
  1883. MUTEX_UNLOCK(&stream->mutex);
  1884. error(RtError::DRIVER_ERROR);
  1885. }
  1886. if (frames > err) frames = err;
  1887. }
  1888. frames = stream->bufferSize - frames;
  1889. if (frames < 0) frames = 0;
  1890. unlock:
  1891. MUTEX_UNLOCK(&stream->mutex);
  1892. return frames;
  1893. }
  1894. void RtAudio :: tickStream(int streamId)
  1895. {
  1896. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  1897. int stopStream = 0;
  1898. if (stream->state == STREAM_STOPPED) {
  1899. if (stream->callbackInfo.usingCallback) usleep(50000); // sleep 50 milliseconds
  1900. return;
  1901. }
  1902. else if (stream->callbackInfo.usingCallback) {
  1903. RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) stream->callbackInfo.callback;
  1904. stopStream = callback(stream->userBuffer, stream->bufferSize, stream->callbackInfo.userData);
  1905. }
  1906. MUTEX_LOCK(&stream->mutex);
  1907. // The state might change while waiting on a mutex.
  1908. if (stream->state == STREAM_STOPPED)
  1909. goto unlock;
  1910. int err;
  1911. char *buffer;
  1912. int channels;
  1913. RTAUDIO_FORMAT format;
  1914. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  1915. // Setup parameters and do buffer conversion if necessary.
  1916. if (stream->doConvertBuffer[0]) {
  1917. convertStreamBuffer(stream, OUTPUT);
  1918. buffer = stream->deviceBuffer;
  1919. channels = stream->nDeviceChannels[0];
  1920. format = stream->deviceFormat[0];
  1921. }
  1922. else {
  1923. buffer = stream->userBuffer;
  1924. channels = stream->nUserChannels[0];
  1925. format = stream->userFormat;
  1926. }
  1927. // Do byte swapping if necessary.
  1928. if (stream->doByteSwap[0])
  1929. byteSwapBuffer(buffer, stream->bufferSize * channels, format);
  1930. // Write samples to device in interleaved/non-interleaved format.
  1931. if (stream->deInterleave[0]) {
  1932. void *bufs[channels];
  1933. size_t offset = stream->bufferSize * formatBytes(format);
  1934. for (int i=0; i<channels; i++)
  1935. bufs[i] = (void *) (buffer + (i * offset));
  1936. err = snd_pcm_writen(stream->handle[0], bufs, stream->bufferSize);
  1937. }
  1938. else
  1939. err = snd_pcm_writei(stream->handle[0], buffer, stream->bufferSize);
  1940. if (err < stream->bufferSize) {
  1941. // Either an error or underrun occured.
  1942. if (err == -EPIPE) {
  1943. snd_pcm_state_t state = snd_pcm_state(stream->handle[0]);
  1944. if (state == SND_PCM_STATE_XRUN) {
  1945. sprintf(message, "RtAudio: ALSA underrun detected.");
  1946. error(RtError::WARNING);
  1947. err = snd_pcm_prepare(stream->handle[0]);
  1948. if (err < 0) {
  1949. sprintf(message, "RtAudio: ALSA error preparing handle after underrun: %s.",
  1950. snd_strerror(err));
  1951. MUTEX_UNLOCK(&stream->mutex);
  1952. error(RtError::DRIVER_ERROR);
  1953. }
  1954. }
  1955. else {
  1956. sprintf(message, "RtAudio: ALSA error, current state is %s.",
  1957. snd_pcm_state_name(state));
  1958. MUTEX_UNLOCK(&stream->mutex);
  1959. error(RtError::DRIVER_ERROR);
  1960. }
  1961. goto unlock;
  1962. }
  1963. else {
  1964. sprintf(message, "RtAudio: ALSA audio write error for device (%s): %s.",
  1965. devices[stream->device[0]].name, snd_strerror(err));
  1966. MUTEX_UNLOCK(&stream->mutex);
  1967. error(RtError::DRIVER_ERROR);
  1968. }
  1969. }
  1970. }
  1971. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  1972. // Setup parameters.
  1973. if (stream->doConvertBuffer[1]) {
  1974. buffer = stream->deviceBuffer;
  1975. channels = stream->nDeviceChannels[1];
  1976. format = stream->deviceFormat[1];
  1977. }
  1978. else {
  1979. buffer = stream->userBuffer;
  1980. channels = stream->nUserChannels[1];
  1981. format = stream->userFormat;
  1982. }
  1983. // Read samples from device in interleaved/non-interleaved format.
  1984. if (stream->deInterleave[1]) {
  1985. void *bufs[channels];
  1986. size_t offset = stream->bufferSize * formatBytes(format);
  1987. for (int i=0; i<channels; i++)
  1988. bufs[i] = (void *) (buffer + (i * offset));
  1989. err = snd_pcm_readn(stream->handle[1], bufs, stream->bufferSize);
  1990. }
  1991. else
  1992. err = snd_pcm_readi(stream->handle[1], buffer, stream->bufferSize);
  1993. if (err < stream->bufferSize) {
  1994. // Either an error or underrun occured.
  1995. if (err == -EPIPE) {
  1996. snd_pcm_state_t state = snd_pcm_state(stream->handle[1]);
  1997. if (state == SND_PCM_STATE_XRUN) {
  1998. sprintf(message, "RtAudio: ALSA overrun detected.");
  1999. error(RtError::WARNING);
  2000. err = snd_pcm_prepare(stream->handle[1]);
  2001. if (err < 0) {
  2002. sprintf(message, "RtAudio: ALSA error preparing handle after overrun: %s.",
  2003. snd_strerror(err));
  2004. MUTEX_UNLOCK(&stream->mutex);
  2005. error(RtError::DRIVER_ERROR);
  2006. }
  2007. }
  2008. else {
  2009. sprintf(message, "RtAudio: ALSA error, current state is %s.",
  2010. snd_pcm_state_name(state));
  2011. MUTEX_UNLOCK(&stream->mutex);
  2012. error(RtError::DRIVER_ERROR);
  2013. }
  2014. goto unlock;
  2015. }
  2016. else {
  2017. sprintf(message, "RtAudio: ALSA audio read error for device (%s): %s.",
  2018. devices[stream->device[1]].name, snd_strerror(err));
  2019. MUTEX_UNLOCK(&stream->mutex);
  2020. error(RtError::DRIVER_ERROR);
  2021. }
  2022. }
  2023. // Do byte swapping if necessary.
  2024. if (stream->doByteSwap[1])
  2025. byteSwapBuffer(buffer, stream->bufferSize * channels, format);
  2026. // Do buffer conversion if necessary.
  2027. if (stream->doConvertBuffer[1])
  2028. convertStreamBuffer(stream, INPUT);
  2029. }
  2030. unlock:
  2031. MUTEX_UNLOCK(&stream->mutex);
  2032. if (stream->callbackInfo.usingCallback && stopStream)
  2033. this->stopStream(streamId);
  2034. }
  2035. extern "C" void *callbackHandler(void *ptr)
  2036. {
  2037. CALLBACK_INFO *info = (CALLBACK_INFO *) ptr;
  2038. RtAudio *object = (RtAudio *) info->object;
  2039. int stream = info->streamId;
  2040. bool *usingCallback = &info->usingCallback;
  2041. while ( *usingCallback ) {
  2042. pthread_testcancel();
  2043. try {
  2044. object->tickStream(stream);
  2045. }
  2046. catch (RtError &exception) {
  2047. fprintf(stderr, "\nRtAudio: Callback thread error (%s) ... closing thread.\n\n",
  2048. exception.getMessage());
  2049. break;
  2050. }
  2051. }
  2052. return 0;
  2053. }
  2054. //******************** End of __LINUX_ALSA__ *********************//
  2055. #elif defined(__LINUX_OSS__)
  2056. #include <sys/stat.h>
  2057. #include <sys/types.h>
  2058. #include <sys/ioctl.h>
  2059. #include <unistd.h>
  2060. #include <fcntl.h>
  2061. #include <sys/soundcard.h>
  2062. #include <errno.h>
  2063. #include <math.h>
  2064. #define DAC_NAME "/dev/dsp"
  2065. #define MAX_DEVICES 16
  2066. #define MAX_CHANNELS 16
  2067. void RtAudio :: initialize(void)
  2068. {
  2069. // Count cards and devices
  2070. nDevices = 0;
  2071. // We check /dev/dsp before probing devices. /dev/dsp is supposed to
  2072. // be a link to the "default" audio device, of the form /dev/dsp0,
  2073. // /dev/dsp1, etc... However, I've seen many cases where /dev/dsp was a
  2074. // real device, so we need to check for that. Also, sometimes the
  2075. // link is to /dev/dspx and other times just dspx. I'm not sure how
  2076. // the latter works, but it does.
  2077. char device_name[16];
  2078. struct stat dspstat;
  2079. int dsplink = -1;
  2080. int i = 0;
  2081. if (lstat(DAC_NAME, &dspstat) == 0) {
  2082. if (S_ISLNK(dspstat.st_mode)) {
  2083. i = readlink(DAC_NAME, device_name, sizeof(device_name));
  2084. if (i > 0) {
  2085. device_name[i] = '\0';
  2086. if (i > 8) { // check for "/dev/dspx"
  2087. if (!strncmp(DAC_NAME, device_name, 8))
  2088. dsplink = atoi(&device_name[8]);
  2089. }
  2090. else if (i > 3) { // check for "dspx"
  2091. if (!strncmp("dsp", device_name, 3))
  2092. dsplink = atoi(&device_name[3]);
  2093. }
  2094. }
  2095. else {
  2096. sprintf(message, "RtAudio: cannot read value of symbolic link %s.", DAC_NAME);
  2097. error(RtError::SYSTEM_ERROR);
  2098. }
  2099. }
  2100. }
  2101. else {
  2102. sprintf(message, "RtAudio: cannot stat %s.", DAC_NAME);
  2103. error(RtError::SYSTEM_ERROR);
  2104. }
  2105. // The OSS API doesn't provide a routine for determining the number
  2106. // of devices. Thus, we'll just pursue a brute force method. The
  2107. // idea is to start with /dev/dsp(0) and continue with higher device
  2108. // numbers until we reach MAX_DSP_DEVICES. This should tell us how
  2109. // many devices we have ... it is not a fullproof scheme, but hopefully
  2110. // it will work most of the time.
  2111. int fd = 0;
  2112. char names[MAX_DEVICES][16];
  2113. for (i=-1; i<MAX_DEVICES; i++) {
  2114. // Probe /dev/dsp first, since it is supposed to be the default device.
  2115. if (i == -1)
  2116. sprintf(device_name, "%s", DAC_NAME);
  2117. else if (i == dsplink)
  2118. continue; // We've aready probed this device via /dev/dsp link ... try next device.
  2119. else
  2120. sprintf(device_name, "%s%d", DAC_NAME, i);
  2121. // First try to open the device for playback, then record mode.
  2122. fd = open(device_name, O_WRONLY | O_NONBLOCK);
  2123. if (fd == -1) {
  2124. // Open device for playback failed ... either busy or doesn't exist.
  2125. if (errno != EBUSY && errno != EAGAIN) {
  2126. // Try to open for capture
  2127. fd = open(device_name, O_RDONLY | O_NONBLOCK);
  2128. if (fd == -1) {
  2129. // Open device for record failed.
  2130. if (errno != EBUSY && errno != EAGAIN)
  2131. continue;
  2132. else {
  2133. sprintf(message, "RtAudio: OSS record device (%s) is busy.", device_name);
  2134. error(RtError::WARNING);
  2135. // still count it for now
  2136. }
  2137. }
  2138. }
  2139. else {
  2140. sprintf(message, "RtAudio: OSS playback device (%s) is busy.", device_name);
  2141. error(RtError::WARNING);
  2142. // still count it for now
  2143. }
  2144. }
  2145. if (fd >= 0) close(fd);
  2146. strncpy(names[nDevices], device_name, 16);
  2147. nDevices++;
  2148. }
  2149. if (nDevices == 0) return;
  2150. // Allocate the RTAUDIO_DEVICE structures.
  2151. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  2152. if (devices == NULL) {
  2153. sprintf(message, "RtAudio: memory allocation error!");
  2154. error(RtError::MEMORY_ERROR);
  2155. }
  2156. // Write device ascii identifiers to device control structure and then probe capabilities.
  2157. for (i=0; i<nDevices; i++) {
  2158. strncpy(devices[i].name, names[i], 16);
  2159. //probeDeviceInfo(&devices[i]);
  2160. }
  2161. return;
  2162. }
  2163. int RtAudio :: getDefaultInputDevice(void)
  2164. {
  2165. // No OSS API functions for default devices.
  2166. return 0;
  2167. }
  2168. int RtAudio :: getDefaultOutputDevice(void)
  2169. {
  2170. // No OSS API functions for default devices.
  2171. return 0;
  2172. }
  2173. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  2174. {
  2175. int i, fd, channels, mask;
  2176. // The OSS API doesn't provide a means for probing the capabilities
  2177. // of devices. Thus, we'll just pursue a brute force method.
  2178. // First try for playback
  2179. fd = open(info->name, O_WRONLY | O_NONBLOCK);
  2180. if (fd == -1) {
  2181. // Open device failed ... either busy or doesn't exist
  2182. if (errno == EBUSY || errno == EAGAIN)
  2183. sprintf(message, "RtAudio: OSS playback device (%s) is busy and cannot be probed.",
  2184. info->name);
  2185. else
  2186. sprintf(message, "RtAudio: OSS playback device (%s) open error.", info->name);
  2187. error(RtError::DEBUG_WARNING);
  2188. goto capture_probe;
  2189. }
  2190. // We have an open device ... see how many channels it can handle
  2191. for (i=MAX_CHANNELS; i>0; i--) {
  2192. channels = i;
  2193. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
  2194. // This would normally indicate some sort of hardware error, but under ALSA's
  2195. // OSS emulation, it sometimes indicates an invalid channel value. Further,
  2196. // the returned channel value is not changed. So, we'll ignore the possible
  2197. // hardware error.
  2198. continue; // try next channel number
  2199. }
  2200. // Check to see whether the device supports the requested number of channels
  2201. if (channels != i ) continue; // try next channel number
  2202. // If here, we found the largest working channel value
  2203. break;
  2204. }
  2205. info->maxOutputChannels = i;
  2206. // Now find the minimum number of channels it can handle
  2207. for (i=1; i<=info->maxOutputChannels; i++) {
  2208. channels = i;
  2209. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
  2210. continue; // try next channel number
  2211. // If here, we found the smallest working channel value
  2212. break;
  2213. }
  2214. info->minOutputChannels = i;
  2215. close(fd);
  2216. capture_probe:
  2217. // Now try for capture
  2218. fd = open(info->name, O_RDONLY | O_NONBLOCK);
  2219. if (fd == -1) {
  2220. // Open device for capture failed ... either busy or doesn't exist
  2221. if (errno == EBUSY || errno == EAGAIN)
  2222. sprintf(message, "RtAudio: OSS capture device (%s) is busy and cannot be probed.",
  2223. info->name);
  2224. else
  2225. sprintf(message, "RtAudio: OSS capture device (%s) open error.", info->name);
  2226. error(RtError::DEBUG_WARNING);
  2227. if (info->maxOutputChannels == 0)
  2228. // didn't open for playback either ... device invalid
  2229. return;
  2230. goto probe_parameters;
  2231. }
  2232. // We have the device open for capture ... see how many channels it can handle
  2233. for (i=MAX_CHANNELS; i>0; i--) {
  2234. channels = i;
  2235. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) {
  2236. continue; // as above
  2237. }
  2238. // If here, we found a working channel value
  2239. break;
  2240. }
  2241. info->maxInputChannels = i;
  2242. // Now find the minimum number of channels it can handle
  2243. for (i=1; i<=info->maxInputChannels; i++) {
  2244. channels = i;
  2245. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
  2246. continue; // try next channel number
  2247. // If here, we found the smallest working channel value
  2248. break;
  2249. }
  2250. info->minInputChannels = i;
  2251. close(fd);
  2252. if (info->maxOutputChannels == 0 && info->maxInputChannels == 0) {
  2253. sprintf(message, "RtAudio: OSS device (%s) reports zero channels for input and output.",
  2254. info->name);
  2255. error(RtError::DEBUG_WARNING);
  2256. return;
  2257. }
  2258. // If device opens for both playback and capture, we determine the channels.
  2259. if (info->maxOutputChannels == 0 || info->maxInputChannels == 0)
  2260. goto probe_parameters;
  2261. fd = open(info->name, O_RDWR | O_NONBLOCK);
  2262. if (fd == -1)
  2263. goto probe_parameters;
  2264. ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
  2265. ioctl(fd, SNDCTL_DSP_GETCAPS, &mask);
  2266. if (mask & DSP_CAP_DUPLEX) {
  2267. info->hasDuplexSupport = true;
  2268. // We have the device open for duplex ... see how many channels it can handle
  2269. for (i=MAX_CHANNELS; i>0; i--) {
  2270. channels = i;
  2271. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
  2272. continue; // as above
  2273. // If here, we found a working channel value
  2274. break;
  2275. }
  2276. info->maxDuplexChannels = i;
  2277. // Now find the minimum number of channels it can handle
  2278. for (i=1; i<=info->maxDuplexChannels; i++) {
  2279. channels = i;
  2280. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
  2281. continue; // try next channel number
  2282. // If here, we found the smallest working channel value
  2283. break;
  2284. }
  2285. info->minDuplexChannels = i;
  2286. }
  2287. close(fd);
  2288. probe_parameters:
  2289. // At this point, we need to figure out the supported data formats
  2290. // and sample rates. We'll proceed by openning the device in the
  2291. // direction with the maximum number of channels, or playback if
  2292. // they are equal. This might limit our sample rate options, but so
  2293. // be it.
  2294. if (info->maxOutputChannels >= info->maxInputChannels) {
  2295. fd = open(info->name, O_WRONLY | O_NONBLOCK);
  2296. channels = info->maxOutputChannels;
  2297. }
  2298. else {
  2299. fd = open(info->name, O_RDONLY | O_NONBLOCK);
  2300. channels = info->maxInputChannels;
  2301. }
  2302. if (fd == -1) {
  2303. // We've got some sort of conflict ... abort
  2304. sprintf(message, "RtAudio: OSS device (%s) won't reopen during probe.",
  2305. info->name);
  2306. error(RtError::DEBUG_WARNING);
  2307. return;
  2308. }
  2309. // We have an open device ... set to maximum channels.
  2310. i = channels;
  2311. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) {
  2312. // We've got some sort of conflict ... abort
  2313. close(fd);
  2314. sprintf(message, "RtAudio: OSS device (%s) won't revert to previous channel setting.",
  2315. info->name);
  2316. error(RtError::DEBUG_WARNING);
  2317. return;
  2318. }
  2319. if (ioctl(fd, SNDCTL_DSP_GETFMTS, &mask) == -1) {
  2320. close(fd);
  2321. sprintf(message, "RtAudio: OSS device (%s) can't get supported audio formats.",
  2322. info->name);
  2323. error(RtError::DEBUG_WARNING);
  2324. return;
  2325. }
  2326. // Probe the supported data formats ... we don't care about endian-ness just yet.
  2327. int format;
  2328. info->nativeFormats = 0;
  2329. #if defined (AFMT_S32_BE)
  2330. // This format does not seem to be in the 2.4 kernel version of OSS soundcard.h
  2331. if (mask & AFMT_S32_BE) {
  2332. format = AFMT_S32_BE;
  2333. info->nativeFormats |= RTAUDIO_SINT32;
  2334. }
  2335. #endif
  2336. #if defined (AFMT_S32_LE)
  2337. /* This format is not in the 2.4.4 kernel version of OSS soundcard.h */
  2338. if (mask & AFMT_S32_LE) {
  2339. format = AFMT_S32_LE;
  2340. info->nativeFormats |= RTAUDIO_SINT32;
  2341. }
  2342. #endif
  2343. if (mask & AFMT_S8) {
  2344. format = AFMT_S8;
  2345. info->nativeFormats |= RTAUDIO_SINT8;
  2346. }
  2347. if (mask & AFMT_S16_BE) {
  2348. format = AFMT_S16_BE;
  2349. info->nativeFormats |= RTAUDIO_SINT16;
  2350. }
  2351. if (mask & AFMT_S16_LE) {
  2352. format = AFMT_S16_LE;
  2353. info->nativeFormats |= RTAUDIO_SINT16;
  2354. }
  2355. // Check that we have at least one supported format
  2356. if (info->nativeFormats == 0) {
  2357. close(fd);
  2358. sprintf(message, "RtAudio: OSS device (%s) data format not supported by RtAudio.",
  2359. info->name);
  2360. error(RtError::DEBUG_WARNING);
  2361. return;
  2362. }
  2363. // Set the format
  2364. i = format;
  2365. if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) == -1 || format != i) {
  2366. close(fd);
  2367. sprintf(message, "RtAudio: OSS device (%s) error setting data format.",
  2368. info->name);
  2369. error(RtError::DEBUG_WARNING);
  2370. return;
  2371. }
  2372. // Probe the supported sample rates ... first get lower limit
  2373. int speed = 1;
  2374. if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) == -1) {
  2375. // If we get here, we're probably using an ALSA driver with OSS-emulation,
  2376. // which doesn't conform to the OSS specification. In this case,
  2377. // we'll probe our predefined list of sample rates for working values.
  2378. info->nSampleRates = 0;
  2379. for (i=0; i<MAX_SAMPLE_RATES; i++) {
  2380. speed = SAMPLE_RATES[i];
  2381. if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) != -1) {
  2382. info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
  2383. info->nSampleRates++;
  2384. }
  2385. }
  2386. if (info->nSampleRates == 0) {
  2387. close(fd);
  2388. return;
  2389. }
  2390. goto finished;
  2391. }
  2392. info->sampleRates[0] = speed;
  2393. // Now get upper limit
  2394. speed = 1000000;
  2395. if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) == -1) {
  2396. close(fd);
  2397. sprintf(message, "RtAudio: OSS device (%s) error setting sample rate.",
  2398. info->name);
  2399. error(RtError::DEBUG_WARNING);
  2400. return;
  2401. }
  2402. info->sampleRates[1] = speed;
  2403. info->nSampleRates = -1;
  2404. finished: // That's all ... close the device and return
  2405. close(fd);
  2406. info->probed = true;
  2407. return;
  2408. }
  2409. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  2410. STREAM_MODE mode, int channels,
  2411. int sampleRate, RTAUDIO_FORMAT format,
  2412. int *bufferSize, int numberOfBuffers)
  2413. {
  2414. int buffers, buffer_bytes, device_channels, device_format;
  2415. int srate, temp, fd;
  2416. const char *name = devices[device].name;
  2417. if (mode == OUTPUT)
  2418. fd = open(name, O_WRONLY | O_NONBLOCK);
  2419. else { // mode == INPUT
  2420. if (stream->mode == OUTPUT && stream->device[0] == device) {
  2421. // We just set the same device for playback ... close and reopen for duplex (OSS only).
  2422. close(stream->handle[0]);
  2423. stream->handle[0] = 0;
  2424. // First check that the number previously set channels is the same.
  2425. if (stream->nUserChannels[0] != channels) {
  2426. sprintf(message, "RtAudio: input/output channels must be equal for OSS duplex device (%s).", name);
  2427. goto error;
  2428. }
  2429. fd = open(name, O_RDWR | O_NONBLOCK);
  2430. }
  2431. else
  2432. fd = open(name, O_RDONLY | O_NONBLOCK);
  2433. }
  2434. if (fd == -1) {
  2435. if (errno == EBUSY || errno == EAGAIN)
  2436. sprintf(message, "RtAudio: OSS device (%s) is busy and cannot be opened.",
  2437. name);
  2438. else
  2439. sprintf(message, "RtAudio: OSS device (%s) cannot be opened.", name);
  2440. goto error;
  2441. }
  2442. // Now reopen in blocking mode.
  2443. close(fd);
  2444. if (mode == OUTPUT)
  2445. fd = open(name, O_WRONLY | O_SYNC);
  2446. else { // mode == INPUT
  2447. if (stream->mode == OUTPUT && stream->device[0] == device)
  2448. fd = open(name, O_RDWR | O_SYNC);
  2449. else
  2450. fd = open(name, O_RDONLY | O_SYNC);
  2451. }
  2452. if (fd == -1) {
  2453. sprintf(message, "RtAudio: OSS device (%s) cannot be opened.", name);
  2454. goto error;
  2455. }
  2456. // Get the sample format mask
  2457. int mask;
  2458. if (ioctl(fd, SNDCTL_DSP_GETFMTS, &mask) == -1) {
  2459. close(fd);
  2460. sprintf(message, "RtAudio: OSS device (%s) can't get supported audio formats.",
  2461. name);
  2462. goto error;
  2463. }
  2464. // Determine how to set the device format.
  2465. stream->userFormat = format;
  2466. device_format = -1;
  2467. stream->doByteSwap[mode] = false;
  2468. if (format == RTAUDIO_SINT8) {
  2469. if (mask & AFMT_S8) {
  2470. device_format = AFMT_S8;
  2471. stream->deviceFormat[mode] = RTAUDIO_SINT8;
  2472. }
  2473. }
  2474. else if (format == RTAUDIO_SINT16) {
  2475. if (mask & AFMT_S16_NE) {
  2476. device_format = AFMT_S16_NE;
  2477. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  2478. }
  2479. #if BYTE_ORDER == LITTLE_ENDIAN
  2480. else if (mask & AFMT_S16_BE) {
  2481. device_format = AFMT_S16_BE;
  2482. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  2483. stream->doByteSwap[mode] = true;
  2484. }
  2485. #else
  2486. else if (mask & AFMT_S16_LE) {
  2487. device_format = AFMT_S16_LE;
  2488. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  2489. stream->doByteSwap[mode] = true;
  2490. }
  2491. #endif
  2492. }
  2493. #if defined (AFMT_S32_NE) && defined (AFMT_S32_LE) && defined (AFMT_S32_BE)
  2494. else if (format == RTAUDIO_SINT32) {
  2495. if (mask & AFMT_S32_NE) {
  2496. device_format = AFMT_S32_NE;
  2497. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  2498. }
  2499. #if BYTE_ORDER == LITTLE_ENDIAN
  2500. else if (mask & AFMT_S32_BE) {
  2501. device_format = AFMT_S32_BE;
  2502. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  2503. stream->doByteSwap[mode] = true;
  2504. }
  2505. #else
  2506. else if (mask & AFMT_S32_LE) {
  2507. device_format = AFMT_S32_LE;
  2508. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  2509. stream->doByteSwap[mode] = true;
  2510. }
  2511. #endif
  2512. }
  2513. #endif
  2514. if (device_format == -1) {
  2515. // The user requested format is not natively supported by the device.
  2516. if (mask & AFMT_S16_NE) {
  2517. device_format = AFMT_S16_NE;
  2518. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  2519. }
  2520. #if BYTE_ORDER == LITTLE_ENDIAN
  2521. else if (mask & AFMT_S16_BE) {
  2522. device_format = AFMT_S16_BE;
  2523. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  2524. stream->doByteSwap[mode] = true;
  2525. }
  2526. #else
  2527. else if (mask & AFMT_S16_LE) {
  2528. device_format = AFMT_S16_LE;
  2529. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  2530. stream->doByteSwap[mode] = true;
  2531. }
  2532. #endif
  2533. #if defined (AFMT_S32_NE) && defined (AFMT_S32_LE) && defined (AFMT_S32_BE)
  2534. else if (mask & AFMT_S32_NE) {
  2535. device_format = AFMT_S32_NE;
  2536. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  2537. }
  2538. #if BYTE_ORDER == LITTLE_ENDIAN
  2539. else if (mask & AFMT_S32_BE) {
  2540. device_format = AFMT_S32_BE;
  2541. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  2542. stream->doByteSwap[mode] = true;
  2543. }
  2544. #else
  2545. else if (mask & AFMT_S32_LE) {
  2546. device_format = AFMT_S32_LE;
  2547. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  2548. stream->doByteSwap[mode] = true;
  2549. }
  2550. #endif
  2551. #endif
  2552. else if (mask & AFMT_S8) {
  2553. device_format = AFMT_S8;
  2554. stream->deviceFormat[mode] = RTAUDIO_SINT8;
  2555. }
  2556. }
  2557. if (stream->deviceFormat[mode] == 0) {
  2558. // This really shouldn't happen ...
  2559. close(fd);
  2560. sprintf(message, "RtAudio: OSS device (%s) data format not supported by RtAudio.",
  2561. name);
  2562. goto error;
  2563. }
  2564. // Determine the number of channels for this device. Note that the
  2565. // channel value requested by the user might be < min_X_Channels.
  2566. stream->nUserChannels[mode] = channels;
  2567. device_channels = channels;
  2568. if (mode == OUTPUT) {
  2569. if (channels < devices[device].minOutputChannels)
  2570. device_channels = devices[device].minOutputChannels;
  2571. }
  2572. else { // mode == INPUT
  2573. if (stream->mode == OUTPUT && stream->device[0] == device) {
  2574. // We're doing duplex setup here.
  2575. if (channels < devices[device].minDuplexChannels)
  2576. device_channels = devices[device].minDuplexChannels;
  2577. }
  2578. else {
  2579. if (channels < devices[device].minInputChannels)
  2580. device_channels = devices[device].minInputChannels;
  2581. }
  2582. }
  2583. stream->nDeviceChannels[mode] = device_channels;
  2584. // Attempt to set the buffer size. According to OSS, the minimum
  2585. // number of buffers is two. The supposed minimum buffer size is 16
  2586. // bytes, so that will be our lower bound. The argument to this
  2587. // call is in the form 0xMMMMSSSS (hex), where the buffer size (in
  2588. // bytes) is given as 2^SSSS and the number of buffers as 2^MMMM.
  2589. // We'll check the actual value used near the end of the setup
  2590. // procedure.
  2591. buffer_bytes = *bufferSize * formatBytes(stream->deviceFormat[mode]) * device_channels;
  2592. if (buffer_bytes < 16) buffer_bytes = 16;
  2593. buffers = numberOfBuffers;
  2594. if (buffers < 2) buffers = 2;
  2595. temp = ((int) buffers << 16) + (int)(log10((double)buffer_bytes)/log10(2.0));
  2596. if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &temp)) {
  2597. close(fd);
  2598. sprintf(message, "RtAudio: OSS error setting fragment size for device (%s).",
  2599. name);
  2600. goto error;
  2601. }
  2602. stream->nBuffers = buffers;
  2603. // Set the data format.
  2604. temp = device_format;
  2605. if (ioctl(fd, SNDCTL_DSP_SETFMT, &device_format) == -1 || device_format != temp) {
  2606. close(fd);
  2607. sprintf(message, "RtAudio: OSS error setting data format for device (%s).",
  2608. name);
  2609. goto error;
  2610. }
  2611. // Set the number of channels.
  2612. temp = device_channels;
  2613. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &device_channels) == -1 || device_channels != temp) {
  2614. close(fd);
  2615. sprintf(message, "RtAudio: OSS error setting %d channels on device (%s).",
  2616. temp, name);
  2617. goto error;
  2618. }
  2619. // Set the sample rate.
  2620. srate = sampleRate;
  2621. temp = srate;
  2622. if (ioctl(fd, SNDCTL_DSP_SPEED, &srate) == -1) {
  2623. close(fd);
  2624. sprintf(message, "RtAudio: OSS error setting sample rate = %d on device (%s).",
  2625. temp, name);
  2626. goto error;
  2627. }
  2628. // Verify the sample rate setup worked.
  2629. if (abs(srate - temp) > 100) {
  2630. close(fd);
  2631. sprintf(message, "RtAudio: OSS error ... audio device (%s) doesn't support sample rate of %d.",
  2632. name, temp);
  2633. goto error;
  2634. }
  2635. stream->sampleRate = sampleRate;
  2636. if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &buffer_bytes) == -1) {
  2637. close(fd);
  2638. sprintf(message, "RtAudio: OSS error getting buffer size for device (%s).",
  2639. name);
  2640. goto error;
  2641. }
  2642. // Save buffer size (in sample frames).
  2643. *bufferSize = buffer_bytes / (formatBytes(stream->deviceFormat[mode]) * device_channels);
  2644. stream->bufferSize = *bufferSize;
  2645. if (mode == INPUT && stream->mode == OUTPUT &&
  2646. stream->device[0] == device) {
  2647. // We're doing duplex setup here.
  2648. stream->deviceFormat[0] = stream->deviceFormat[1];
  2649. stream->nDeviceChannels[0] = device_channels;
  2650. }
  2651. // Set flags for buffer conversion
  2652. stream->doConvertBuffer[mode] = false;
  2653. if (stream->userFormat != stream->deviceFormat[mode])
  2654. stream->doConvertBuffer[mode] = true;
  2655. if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
  2656. stream->doConvertBuffer[mode] = true;
  2657. // Allocate necessary internal buffers
  2658. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  2659. long buffer_bytes;
  2660. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  2661. buffer_bytes = stream->nUserChannels[0];
  2662. else
  2663. buffer_bytes = stream->nUserChannels[1];
  2664. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  2665. if (stream->userBuffer) free(stream->userBuffer);
  2666. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  2667. if (stream->userBuffer == NULL) {
  2668. close(fd);
  2669. sprintf(message, "RtAudio: OSS error allocating user buffer memory (%s).",
  2670. name);
  2671. goto error;
  2672. }
  2673. }
  2674. if ( stream->doConvertBuffer[mode] ) {
  2675. long buffer_bytes;
  2676. bool makeBuffer = true;
  2677. if ( mode == OUTPUT )
  2678. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  2679. else { // mode == INPUT
  2680. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  2681. if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
  2682. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  2683. if ( buffer_bytes < bytes_out ) makeBuffer = false;
  2684. }
  2685. }
  2686. if ( makeBuffer ) {
  2687. buffer_bytes *= *bufferSize;
  2688. if (stream->deviceBuffer) free(stream->deviceBuffer);
  2689. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  2690. if (stream->deviceBuffer == NULL) {
  2691. close(fd);
  2692. free(stream->userBuffer);
  2693. sprintf(message, "RtAudio: OSS error allocating device buffer memory (%s).",
  2694. name);
  2695. goto error;
  2696. }
  2697. }
  2698. }
  2699. stream->device[mode] = device;
  2700. stream->handle[mode] = fd;
  2701. stream->state = STREAM_STOPPED;
  2702. if ( stream->mode == OUTPUT && mode == INPUT ) {
  2703. stream->mode = DUPLEX;
  2704. if (stream->device[0] == device)
  2705. stream->handle[0] = fd;
  2706. }
  2707. else
  2708. stream->mode = mode;
  2709. return SUCCESS;
  2710. error:
  2711. if (stream->handle[0]) {
  2712. close(stream->handle[0]);
  2713. stream->handle[0] = 0;
  2714. }
  2715. error(RtError::WARNING);
  2716. return FAILURE;
  2717. }
  2718. void RtAudio :: closeStream(int streamId)
  2719. {
  2720. // We don't want an exception to be thrown here because this
  2721. // function is called by our class destructor. So, do our own
  2722. // streamId check.
  2723. if ( streams.find( streamId ) == streams.end() ) {
  2724. sprintf(message, "RtAudio: invalid stream identifier!");
  2725. error(RtError::WARNING);
  2726. return;
  2727. }
  2728. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
  2729. if (stream->callbackInfo.usingCallback) {
  2730. pthread_cancel(stream->callbackInfo.thread);
  2731. pthread_join(stream->callbackInfo.thread, NULL);
  2732. }
  2733. if (stream->state == STREAM_RUNNING) {
  2734. if (stream->mode == OUTPUT || stream->mode == DUPLEX)
  2735. ioctl(stream->handle[0], SNDCTL_DSP_RESET, 0);
  2736. if (stream->mode == INPUT || stream->mode == DUPLEX)
  2737. ioctl(stream->handle[1], SNDCTL_DSP_RESET, 0);
  2738. }
  2739. pthread_mutex_destroy(&stream->mutex);
  2740. if (stream->handle[0])
  2741. close(stream->handle[0]);
  2742. if (stream->handle[1])
  2743. close(stream->handle[1]);
  2744. if (stream->userBuffer)
  2745. free(stream->userBuffer);
  2746. if (stream->deviceBuffer)
  2747. free(stream->deviceBuffer);
  2748. free(stream);
  2749. streams.erase(streamId);
  2750. }
  2751. void RtAudio :: startStream(int streamId)
  2752. {
  2753. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  2754. MUTEX_LOCK(&stream->mutex);
  2755. stream->state = STREAM_RUNNING;
  2756. // No need to do anything else here ... OSS automatically starts
  2757. // when fed samples.
  2758. MUTEX_UNLOCK(&stream->mutex);
  2759. }
  2760. void RtAudio :: stopStream(int streamId)
  2761. {
  2762. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  2763. MUTEX_LOCK(&stream->mutex);
  2764. if (stream->state == STREAM_STOPPED)
  2765. goto unlock;
  2766. int err;
  2767. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  2768. err = ioctl(stream->handle[0], SNDCTL_DSP_SYNC, 0);
  2769. if (err < -1) {
  2770. sprintf(message, "RtAudio: OSS error stopping device (%s).",
  2771. devices[stream->device[0]].name);
  2772. error(RtError::DRIVER_ERROR);
  2773. }
  2774. }
  2775. else {
  2776. err = ioctl(stream->handle[1], SNDCTL_DSP_SYNC, 0);
  2777. if (err < -1) {
  2778. sprintf(message, "RtAudio: OSS error stopping device (%s).",
  2779. devices[stream->device[1]].name);
  2780. error(RtError::DRIVER_ERROR);
  2781. }
  2782. }
  2783. stream->state = STREAM_STOPPED;
  2784. unlock:
  2785. MUTEX_UNLOCK(&stream->mutex);
  2786. }
  2787. void RtAudio :: abortStream(int streamId)
  2788. {
  2789. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  2790. MUTEX_LOCK(&stream->mutex);
  2791. if (stream->state == STREAM_STOPPED)
  2792. goto unlock;
  2793. int err;
  2794. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  2795. err = ioctl(stream->handle[0], SNDCTL_DSP_RESET, 0);
  2796. if (err < -1) {
  2797. sprintf(message, "RtAudio: OSS error aborting device (%s).",
  2798. devices[stream->device[0]].name);
  2799. error(RtError::DRIVER_ERROR);
  2800. }
  2801. }
  2802. else {
  2803. err = ioctl(stream->handle[1], SNDCTL_DSP_RESET, 0);
  2804. if (err < -1) {
  2805. sprintf(message, "RtAudio: OSS error aborting device (%s).",
  2806. devices[stream->device[1]].name);
  2807. error(RtError::DRIVER_ERROR);
  2808. }
  2809. }
  2810. stream->state = STREAM_STOPPED;
  2811. unlock:
  2812. MUTEX_UNLOCK(&stream->mutex);
  2813. }
  2814. int RtAudio :: streamWillBlock(int streamId)
  2815. {
  2816. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  2817. MUTEX_LOCK(&stream->mutex);
  2818. int bytes = 0, channels = 0, frames = 0;
  2819. if (stream->state == STREAM_STOPPED)
  2820. goto unlock;
  2821. audio_buf_info info;
  2822. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  2823. ioctl(stream->handle[0], SNDCTL_DSP_GETOSPACE, &info);
  2824. bytes = info.bytes;
  2825. channels = stream->nDeviceChannels[0];
  2826. }
  2827. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  2828. ioctl(stream->handle[1], SNDCTL_DSP_GETISPACE, &info);
  2829. if (stream->mode == DUPLEX ) {
  2830. bytes = (bytes < info.bytes) ? bytes : info.bytes;
  2831. channels = stream->nDeviceChannels[0];
  2832. }
  2833. else {
  2834. bytes = info.bytes;
  2835. channels = stream->nDeviceChannels[1];
  2836. }
  2837. }
  2838. frames = (int) (bytes / (channels * formatBytes(stream->deviceFormat[0])));
  2839. frames -= stream->bufferSize;
  2840. if (frames < 0) frames = 0;
  2841. unlock:
  2842. MUTEX_UNLOCK(&stream->mutex);
  2843. return frames;
  2844. }
  2845. void RtAudio :: tickStream(int streamId)
  2846. {
  2847. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  2848. int stopStream = 0;
  2849. if (stream->state == STREAM_STOPPED) {
  2850. if (stream->callbackInfo.usingCallback) usleep(50000); // sleep 50 milliseconds
  2851. return;
  2852. }
  2853. else if (stream->callbackInfo.usingCallback) {
  2854. RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) stream->callbackInfo.callback;
  2855. stopStream = callback(stream->userBuffer, stream->bufferSize, stream->callbackInfo.userData);
  2856. }
  2857. MUTEX_LOCK(&stream->mutex);
  2858. // The state might change while waiting on a mutex.
  2859. if (stream->state == STREAM_STOPPED)
  2860. goto unlock;
  2861. int result;
  2862. char *buffer;
  2863. int samples;
  2864. RTAUDIO_FORMAT format;
  2865. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  2866. // Setup parameters and do buffer conversion if necessary.
  2867. if (stream->doConvertBuffer[0]) {
  2868. convertStreamBuffer(stream, OUTPUT);
  2869. buffer = stream->deviceBuffer;
  2870. samples = stream->bufferSize * stream->nDeviceChannels[0];
  2871. format = stream->deviceFormat[0];
  2872. }
  2873. else {
  2874. buffer = stream->userBuffer;
  2875. samples = stream->bufferSize * stream->nUserChannels[0];
  2876. format = stream->userFormat;
  2877. }
  2878. // Do byte swapping if necessary.
  2879. if (stream->doByteSwap[0])
  2880. byteSwapBuffer(buffer, samples, format);
  2881. // Write samples to device.
  2882. result = write(stream->handle[0], buffer, samples * formatBytes(format));
  2883. if (result == -1) {
  2884. // This could be an underrun, but the basic OSS API doesn't provide a means for determining that.
  2885. sprintf(message, "RtAudio: OSS audio write error for device (%s).",
  2886. devices[stream->device[0]].name);
  2887. error(RtError::DRIVER_ERROR);
  2888. }
  2889. }
  2890. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  2891. // Setup parameters.
  2892. if (stream->doConvertBuffer[1]) {
  2893. buffer = stream->deviceBuffer;
  2894. samples = stream->bufferSize * stream->nDeviceChannels[1];
  2895. format = stream->deviceFormat[1];
  2896. }
  2897. else {
  2898. buffer = stream->userBuffer;
  2899. samples = stream->bufferSize * stream->nUserChannels[1];
  2900. format = stream->userFormat;
  2901. }
  2902. // Read samples from device.
  2903. result = read(stream->handle[1], buffer, samples * formatBytes(format));
  2904. if (result == -1) {
  2905. // This could be an overrun, but the basic OSS API doesn't provide a means for determining that.
  2906. sprintf(message, "RtAudio: OSS audio read error for device (%s).",
  2907. devices[stream->device[1]].name);
  2908. error(RtError::DRIVER_ERROR);
  2909. }
  2910. // Do byte swapping if necessary.
  2911. if (stream->doByteSwap[1])
  2912. byteSwapBuffer(buffer, samples, format);
  2913. // Do buffer conversion if necessary.
  2914. if (stream->doConvertBuffer[1])
  2915. convertStreamBuffer(stream, INPUT);
  2916. }
  2917. unlock:
  2918. MUTEX_UNLOCK(&stream->mutex);
  2919. if (stream->callbackInfo.usingCallback && stopStream)
  2920. this->stopStream(streamId);
  2921. }
  2922. extern "C" void *callbackHandler(void *ptr)
  2923. {
  2924. CALLBACK_INFO *info = (CALLBACK_INFO *) ptr;
  2925. RtAudio *object = (RtAudio *) info->object;
  2926. int stream = info->streamId;
  2927. bool *usingCallback = &info->usingCallback;
  2928. while ( *usingCallback ) {
  2929. pthread_testcancel();
  2930. try {
  2931. object->tickStream(stream);
  2932. }
  2933. catch (RtError &exception) {
  2934. fprintf(stderr, "\nRtAudio: Callback thread error (%s) ... closing thread.\n\n",
  2935. exception.getMessage());
  2936. break;
  2937. }
  2938. }
  2939. return 0;
  2940. }
  2941. //******************** End of __LINUX_OSS__ *********************//
  2942. #elif defined(__WINDOWS_ASIO__) // ASIO API on Windows
  2943. // The ASIO API is designed around a callback scheme, so this
  2944. // implementation is similar to that used for OS X CoreAudio. The
  2945. // primary constraint with ASIO is that it only allows access to a
  2946. // single driver at a time. Thus, it is not possible to have more
  2947. // than one simultaneous RtAudio stream.
  2948. //
  2949. // This implementation also requires a number of external ASIO files
  2950. // and a few global variables. The ASIO callback scheme does not
  2951. // allow for the passing of user data, so we must create a global
  2952. // pointer to our callbackInfo structure.
  2953. #include "asio/asiosys.h"
  2954. #include "asio/asio.h"
  2955. #include "asio/asiodrivers.h"
  2956. #include <math.h>
  2957. AsioDrivers drivers;
  2958. ASIOCallbacks asioCallbacks;
  2959. CALLBACK_INFO *asioCallbackInfo;
  2960. ASIODriverInfo driverInfo;
  2961. void RtAudio :: initialize(void)
  2962. {
  2963. nDevices = drivers.asioGetNumDev();
  2964. if (nDevices <= 0) return;
  2965. // Allocate the RTAUDIO_DEVICE structures.
  2966. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  2967. if (devices == NULL) {
  2968. sprintf(message, "RtAudio: memory allocation error!");
  2969. error(RtError::MEMORY_ERROR);
  2970. }
  2971. // Write device driver names to device structures and then probe the
  2972. // device capabilities.
  2973. for (int i=0; i<nDevices; i++) {
  2974. if ( drivers.asioGetDriverName( i, devices[i].name, 128 ) == 0 )
  2975. //probeDeviceInfo(&devices[i]);
  2976. ;
  2977. else {
  2978. sprintf(message, "RtAudio: error getting ASIO driver name for device index %d!", i);
  2979. error(RtError::WARNING);
  2980. }
  2981. }
  2982. drivers.removeCurrentDriver();
  2983. driverInfo.asioVersion = 2;
  2984. // See note in DirectSound implementation about GetDesktopWindow().
  2985. driverInfo.sysRef = GetForegroundWindow();
  2986. }
  2987. int RtAudio :: getDefaultInputDevice(void)
  2988. {
  2989. return 0;
  2990. }
  2991. int RtAudio :: getDefaultOutputDevice(void)
  2992. {
  2993. return 0;
  2994. }
  2995. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  2996. {
  2997. // Don't probe if a stream is already open.
  2998. if ( streams.size() > 0 ) {
  2999. sprintf(message, "RtAudio: unable to probe ASIO driver while a stream is open.");
  3000. error(RtError::DEBUG_WARNING);
  3001. return;
  3002. }
  3003. if ( !drivers.loadDriver( info->name ) ) {
  3004. sprintf(message, "RtAudio: ASIO error loading driver (%s).", info->name);
  3005. error(RtError::DEBUG_WARNING);
  3006. return;
  3007. }
  3008. ASIOError result = ASIOInit( &driverInfo );
  3009. if ( result != ASE_OK ) {
  3010. char details[32];
  3011. if ( result == ASE_HWMalfunction )
  3012. sprintf(details, "hardware malfunction");
  3013. else if ( result == ASE_NoMemory )
  3014. sprintf(details, "no memory");
  3015. else if ( result == ASE_NotPresent )
  3016. sprintf(details, "driver/hardware not present");
  3017. else
  3018. sprintf(details, "unspecified");
  3019. sprintf(message, "RtAudio: ASIO error (%s) initializing driver (%s).", details, info->name);
  3020. error(RtError::DEBUG_WARNING);
  3021. return;
  3022. }
  3023. // Determine the device channel information.
  3024. long inputChannels, outputChannels;
  3025. result = ASIOGetChannels( &inputChannels, &outputChannels );
  3026. if ( result != ASE_OK ) {
  3027. drivers.removeCurrentDriver();
  3028. sprintf(message, "RtAudio: ASIO error getting input/output channel count (%s).", info->name);
  3029. error(RtError::DEBUG_WARNING);
  3030. return;
  3031. }
  3032. info->maxOutputChannels = outputChannels;
  3033. if ( outputChannels > 0 ) info->minOutputChannels = 1;
  3034. info->maxInputChannels = inputChannels;
  3035. if ( inputChannels > 0 ) info->minInputChannels = 1;
  3036. // If device opens for both playback and capture, we determine the channels.
  3037. if (info->maxOutputChannels > 0 && info->maxInputChannels > 0) {
  3038. info->hasDuplexSupport = true;
  3039. info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ?
  3040. info->maxInputChannels : info->maxOutputChannels;
  3041. info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ?
  3042. info->minInputChannels : info->minOutputChannels;
  3043. }
  3044. // Determine the supported sample rates.
  3045. info->nSampleRates = 0;
  3046. for (int i=0; i<MAX_SAMPLE_RATES; i++) {
  3047. result = ASIOCanSampleRate( (ASIOSampleRate) SAMPLE_RATES[i] );
  3048. if ( result == ASE_OK )
  3049. info->sampleRates[info->nSampleRates++] = SAMPLE_RATES[i];
  3050. }
  3051. if (info->nSampleRates == 0) {
  3052. drivers.removeCurrentDriver();
  3053. sprintf( message, "RtAudio: No supported sample rates found for ASIO driver (%s).", info->name );
  3054. error(RtError::DEBUG_WARNING);
  3055. return;
  3056. }
  3057. // Determine supported data types ... just check first channel and assume rest are the same.
  3058. ASIOChannelInfo channelInfo;
  3059. channelInfo.channel = 0;
  3060. channelInfo.isInput = true;
  3061. if ( info->maxInputChannels <= 0 ) channelInfo.isInput = false;
  3062. result = ASIOGetChannelInfo( &channelInfo );
  3063. if ( result != ASE_OK ) {
  3064. drivers.removeCurrentDriver();
  3065. sprintf(message, "RtAudio: ASIO error getting driver (%s) channel information.", info->name);
  3066. error(RtError::DEBUG_WARNING);
  3067. return;
  3068. }
  3069. if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB )
  3070. info->nativeFormats |= RTAUDIO_SINT16;
  3071. else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB )
  3072. info->nativeFormats |= RTAUDIO_SINT32;
  3073. else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB )
  3074. info->nativeFormats |= RTAUDIO_FLOAT32;
  3075. else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB )
  3076. info->nativeFormats |= RTAUDIO_FLOAT64;
  3077. // Check that we have at least one supported format.
  3078. if (info->nativeFormats == 0) {
  3079. drivers.removeCurrentDriver();
  3080. sprintf(message, "RtAudio: ASIO driver (%s) data format not supported by RtAudio.",
  3081. info->name);
  3082. error(RtError::DEBUG_WARNING);
  3083. return;
  3084. }
  3085. info->probed = true;
  3086. drivers.removeCurrentDriver();
  3087. }
  3088. void bufferSwitch(long index, ASIOBool processNow)
  3089. {
  3090. RtAudio *object = (RtAudio *) asioCallbackInfo->object;
  3091. try {
  3092. object->callbackEvent( asioCallbackInfo->streamId, index, (void *)NULL, (void *)NULL );
  3093. }
  3094. catch (RtError &exception) {
  3095. fprintf(stderr, "\nCallback handler error (%s)!\n\n", exception.getMessage());
  3096. return;
  3097. }
  3098. return;
  3099. }
  3100. void sampleRateChanged(ASIOSampleRate sRate)
  3101. {
  3102. // The ASIO documentation says that this usually only happens during
  3103. // external sync. Audio processing is not stopped by the driver,
  3104. // actual sample rate might not have even changed, maybe only the
  3105. // sample rate status of an AES/EBU or S/PDIF digital input at the
  3106. // audio device.
  3107. RtAudio *object = (RtAudio *) asioCallbackInfo->object;
  3108. try {
  3109. object->stopStream( asioCallbackInfo->streamId );
  3110. }
  3111. catch (RtError &exception) {
  3112. fprintf(stderr, "\nRtAudio: sampleRateChanged() error (%s)!\n\n", exception.getMessage());
  3113. return;
  3114. }
  3115. fprintf(stderr, "\nRtAudio: ASIO driver reports sample rate changed to %d ... stream stopped!!!", (int) sRate);
  3116. }
  3117. long asioMessages(long selector, long value, void* message, double* opt)
  3118. {
  3119. long ret = 0;
  3120. switch(selector) {
  3121. case kAsioSelectorSupported:
  3122. if(value == kAsioResetRequest
  3123. || value == kAsioEngineVersion
  3124. || value == kAsioResyncRequest
  3125. || value == kAsioLatenciesChanged
  3126. // The following three were added for ASIO 2.0, you don't
  3127. // necessarily have to support them.
  3128. || value == kAsioSupportsTimeInfo
  3129. || value == kAsioSupportsTimeCode
  3130. || value == kAsioSupportsInputMonitor)
  3131. ret = 1L;
  3132. break;
  3133. case kAsioResetRequest:
  3134. // Defer the task and perform the reset of the driver during the
  3135. // next "safe" situation. You cannot reset the driver right now,
  3136. // as this code is called from the driver. Reset the driver is
  3137. // done by completely destruct is. I.e. ASIOStop(),
  3138. // ASIODisposeBuffers(), Destruction Afterwards you initialize the
  3139. // driver again.
  3140. fprintf(stderr, "\nRtAudio: ASIO driver reset requested!!!");
  3141. ret = 1L;
  3142. break;
  3143. case kAsioResyncRequest:
  3144. // This informs the application that the driver encountered some
  3145. // non-fatal data loss. It is used for synchronization purposes
  3146. // of different media. Added mainly to work around the Win16Mutex
  3147. // problems in Windows 95/98 with the Windows Multimedia system,
  3148. // which could lose data because the Mutex was held too long by
  3149. // another thread. However a driver can issue it in other
  3150. // situations, too.
  3151. fprintf(stderr, "\nRtAudio: ASIO driver resync requested!!!");
  3152. ret = 1L;
  3153. break;
  3154. case kAsioLatenciesChanged:
  3155. // This will inform the host application that the drivers were
  3156. // latencies changed. Beware, it this does not mean that the
  3157. // buffer sizes have changed! You might need to update internal
  3158. // delay data.
  3159. fprintf(stderr, "\nRtAudio: ASIO driver latency may have changed!!!");
  3160. ret = 1L;
  3161. break;
  3162. case kAsioEngineVersion:
  3163. // Return the supported ASIO version of the host application. If
  3164. // a host application does not implement this selector, ASIO 1.0
  3165. // is assumed by the driver.
  3166. ret = 2L;
  3167. break;
  3168. case kAsioSupportsTimeInfo:
  3169. // Informs the driver whether the
  3170. // asioCallbacks.bufferSwitchTimeInfo() callback is supported.
  3171. // For compatibility with ASIO 1.0 drivers the host application
  3172. // should always support the "old" bufferSwitch method, too.
  3173. ret = 0;
  3174. break;
  3175. case kAsioSupportsTimeCode:
  3176. // Informs the driver wether application is interested in time
  3177. // code info. If an application does not need to know about time
  3178. // code, the driver has less work to do.
  3179. ret = 0;
  3180. break;
  3181. }
  3182. return ret;
  3183. }
  3184. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  3185. STREAM_MODE mode, int channels,
  3186. int sampleRate, RTAUDIO_FORMAT format,
  3187. int *bufferSize, int numberOfBuffers)
  3188. {
  3189. // Don't attempt to load another driver if a stream is already open.
  3190. if ( streams.size() > 0 ) {
  3191. sprintf(message, "RtAudio: unable to load ASIO driver while a stream is open.");
  3192. error(RtError::WARNING);
  3193. return FAILURE;
  3194. }
  3195. // For ASIO, a duplex stream MUST use the same driver.
  3196. if ( mode == INPUT && stream->mode == OUTPUT && stream->device[0] != device ) {
  3197. sprintf(message, "RtAudio: ASIO duplex stream must use the same device for input and output.");
  3198. error(RtError::WARNING);
  3199. return FAILURE;
  3200. }
  3201. // Only load the driver once for duplex stream.
  3202. ASIOError result;
  3203. if ( mode != INPUT || stream->mode != OUTPUT ) {
  3204. if ( !drivers.loadDriver( devices[device].name ) ) {
  3205. sprintf(message, "RtAudio: ASIO error loading driver (%s).", devices[device].name);
  3206. error(RtError::DEBUG_WARNING);
  3207. return FAILURE;
  3208. }
  3209. result = ASIOInit( &driverInfo );
  3210. if ( result != ASE_OK ) {
  3211. char details[32];
  3212. if ( result == ASE_HWMalfunction )
  3213. sprintf(details, "hardware malfunction");
  3214. else if ( result == ASE_NoMemory )
  3215. sprintf(details, "no memory");
  3216. else if ( result == ASE_NotPresent )
  3217. sprintf(details, "driver/hardware not present");
  3218. else
  3219. sprintf(details, "unspecified");
  3220. sprintf(message, "RtAudio: ASIO error (%s) initializing driver (%s).", details, devices[device].name);
  3221. error(RtError::DEBUG_WARNING);
  3222. return FAILURE;
  3223. }
  3224. }
  3225. // Check the device channel count.
  3226. long inputChannels, outputChannels;
  3227. result = ASIOGetChannels( &inputChannels, &outputChannels );
  3228. if ( result != ASE_OK ) {
  3229. drivers.removeCurrentDriver();
  3230. sprintf(message, "RtAudio: ASIO error getting input/output channel count (%s).",
  3231. devices[device].name);
  3232. error(RtError::DEBUG_WARNING);
  3233. return FAILURE;
  3234. }
  3235. if ( ( mode == OUTPUT && channels > outputChannels) ||
  3236. ( mode == INPUT && channels > inputChannels) ) {
  3237. drivers.removeCurrentDriver();
  3238. sprintf(message, "RtAudio: ASIO driver (%s) does not support requested channel count (%d).",
  3239. devices[device].name, channels);
  3240. error(RtError::DEBUG_WARNING);
  3241. return FAILURE;
  3242. }
  3243. stream->nDeviceChannels[mode] = channels;
  3244. stream->nUserChannels[mode] = channels;
  3245. // Verify the sample rate is supported.
  3246. result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate );
  3247. if ( result != ASE_OK ) {
  3248. drivers.removeCurrentDriver();
  3249. sprintf(message, "RtAudio: ASIO driver (%s) does not support requested sample rate (%d).",
  3250. devices[device].name, sampleRate);
  3251. error(RtError::DEBUG_WARNING);
  3252. return FAILURE;
  3253. }
  3254. // Set the sample rate.
  3255. result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate );
  3256. if ( result != ASE_OK ) {
  3257. drivers.removeCurrentDriver();
  3258. sprintf(message, "RtAudio: ASIO driver (%s) error setting sample rate (%d).",
  3259. devices[device].name, sampleRate);
  3260. error(RtError::DEBUG_WARNING);
  3261. return FAILURE;
  3262. }
  3263. // Determine the driver data type.
  3264. ASIOChannelInfo channelInfo;
  3265. channelInfo.channel = 0;
  3266. if ( mode == OUTPUT ) channelInfo.isInput = false;
  3267. else channelInfo.isInput = true;
  3268. result = ASIOGetChannelInfo( &channelInfo );
  3269. if ( result != ASE_OK ) {
  3270. drivers.removeCurrentDriver();
  3271. sprintf(message, "RtAudio: ASIO driver (%s) error getting data format.",
  3272. devices[device].name);
  3273. error(RtError::DEBUG_WARNING);
  3274. return FAILURE;
  3275. }
  3276. // Assuming WINDOWS host is always little-endian.
  3277. stream->doByteSwap[mode] = false;
  3278. stream->userFormat = format;
  3279. stream->deviceFormat[mode] = 0;
  3280. if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) {
  3281. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  3282. if ( channelInfo.type == ASIOSTInt16MSB ) stream->doByteSwap[mode] = true;
  3283. }
  3284. else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) {
  3285. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  3286. if ( channelInfo.type == ASIOSTInt32MSB ) stream->doByteSwap[mode] = true;
  3287. }
  3288. else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) {
  3289. stream->deviceFormat[mode] = RTAUDIO_FLOAT32;
  3290. if ( channelInfo.type == ASIOSTFloat32MSB ) stream->doByteSwap[mode] = true;
  3291. }
  3292. else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) {
  3293. stream->deviceFormat[mode] = RTAUDIO_FLOAT64;
  3294. if ( channelInfo.type == ASIOSTFloat64MSB ) stream->doByteSwap[mode] = true;
  3295. }
  3296. if ( stream->deviceFormat[mode] == 0 ) {
  3297. drivers.removeCurrentDriver();
  3298. sprintf(message, "RtAudio: ASIO driver (%s) data format not supported by RtAudio.",
  3299. devices[device].name);
  3300. error(RtError::DEBUG_WARNING);
  3301. return FAILURE;
  3302. }
  3303. // Set the buffer size. For a duplex stream, this will end up
  3304. // setting the buffer size based on the input constraints, which
  3305. // should be ok.
  3306. long minSize, maxSize, preferSize, granularity;
  3307. result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity );
  3308. if ( result != ASE_OK ) {
  3309. drivers.removeCurrentDriver();
  3310. sprintf(message, "RtAudio: ASIO driver (%s) error getting buffer size.",
  3311. devices[device].name);
  3312. error(RtError::DEBUG_WARNING);
  3313. return FAILURE;
  3314. }
  3315. if ( *bufferSize < minSize ) *bufferSize = minSize;
  3316. else if ( *bufferSize > maxSize ) *bufferSize = maxSize;
  3317. else if ( granularity == -1 ) {
  3318. // Make sure bufferSize is a power of two.
  3319. double power = log10( *bufferSize ) / log10( 2.0 );
  3320. *bufferSize = pow( 2.0, floor(power+0.5) );
  3321. if ( *bufferSize < minSize ) *bufferSize = minSize;
  3322. else if ( *bufferSize > maxSize ) *bufferSize = maxSize;
  3323. else *bufferSize = preferSize;
  3324. }
  3325. if ( mode == INPUT && stream->mode == OUTPUT && stream->bufferSize != *bufferSize )
  3326. cout << "possible input/output buffersize discrepancy" << endl;
  3327. stream->bufferSize = *bufferSize;
  3328. stream->nBuffers = 2;
  3329. // ASIO always uses deinterleaved channels.
  3330. stream->deInterleave[mode] = true;
  3331. // Create the ASIO internal buffers. Since RtAudio sets up input
  3332. // and output separately, we'll have to dispose of previously
  3333. // created output buffers for a duplex stream.
  3334. if ( mode == INPUT && stream->mode == OUTPUT ) {
  3335. free(stream->callbackInfo.buffers);
  3336. result = ASIODisposeBuffers();
  3337. if ( result != ASE_OK ) {
  3338. drivers.removeCurrentDriver();
  3339. sprintf(message, "RtAudio: ASIO driver (%s) error disposing previously allocated buffers.",
  3340. devices[device].name);
  3341. error(RtError::DEBUG_WARNING);
  3342. return FAILURE;
  3343. }
  3344. }
  3345. // Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure.
  3346. int i, nChannels = stream->nDeviceChannels[0] + stream->nDeviceChannels[1];
  3347. stream->callbackInfo.buffers = 0;
  3348. ASIOBufferInfo *bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) );
  3349. stream->callbackInfo.buffers = (void *) bufferInfos;
  3350. ASIOBufferInfo *infos = bufferInfos;
  3351. for ( i=0; i<stream->nDeviceChannels[1]; i++, infos++ ) {
  3352. infos->isInput = ASIOTrue;
  3353. infos->channelNum = i;
  3354. infos->buffers[0] = infos->buffers[1] = 0;
  3355. }
  3356. for ( i=0; i<stream->nDeviceChannels[0]; i++, infos++ ) {
  3357. infos->isInput = ASIOFalse;
  3358. infos->channelNum = i;
  3359. infos->buffers[0] = infos->buffers[1] = 0;
  3360. }
  3361. // Set up the ASIO callback structure and create the ASIO data buffers.
  3362. asioCallbacks.bufferSwitch = &bufferSwitch;
  3363. asioCallbacks.sampleRateDidChange = &sampleRateChanged;
  3364. asioCallbacks.asioMessage = &asioMessages;
  3365. asioCallbacks.bufferSwitchTimeInfo = NULL;
  3366. result = ASIOCreateBuffers( bufferInfos, nChannels, stream->bufferSize, &asioCallbacks);
  3367. if ( result != ASE_OK ) {
  3368. drivers.removeCurrentDriver();
  3369. sprintf(message, "RtAudio: ASIO driver (%s) error creating buffers.",
  3370. devices[device].name);
  3371. error(RtError::DEBUG_WARNING);
  3372. return FAILURE;
  3373. }
  3374. // Set flags for buffer conversion.
  3375. stream->doConvertBuffer[mode] = false;
  3376. if (stream->userFormat != stream->deviceFormat[mode])
  3377. stream->doConvertBuffer[mode] = true;
  3378. if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
  3379. stream->doConvertBuffer[mode] = true;
  3380. if (stream->nUserChannels[mode] > 1 && stream->deInterleave[mode])
  3381. stream->doConvertBuffer[mode] = true;
  3382. // Allocate necessary internal buffers
  3383. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  3384. long buffer_bytes;
  3385. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  3386. buffer_bytes = stream->nUserChannels[0];
  3387. else
  3388. buffer_bytes = stream->nUserChannels[1];
  3389. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  3390. if (stream->userBuffer) free(stream->userBuffer);
  3391. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  3392. if (stream->userBuffer == NULL)
  3393. goto memory_error;
  3394. }
  3395. if ( stream->doConvertBuffer[mode] ) {
  3396. long buffer_bytes;
  3397. bool makeBuffer = true;
  3398. if ( mode == OUTPUT )
  3399. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  3400. else { // mode == INPUT
  3401. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  3402. if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
  3403. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  3404. if ( buffer_bytes < bytes_out ) makeBuffer = false;
  3405. }
  3406. }
  3407. if ( makeBuffer ) {
  3408. buffer_bytes *= *bufferSize;
  3409. if (stream->deviceBuffer) free(stream->deviceBuffer);
  3410. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  3411. if (stream->deviceBuffer == NULL)
  3412. goto memory_error;
  3413. }
  3414. }
  3415. stream->device[mode] = device;
  3416. stream->state = STREAM_STOPPED;
  3417. if ( stream->mode == OUTPUT && mode == INPUT )
  3418. // We had already set up an output stream.
  3419. stream->mode = DUPLEX;
  3420. else
  3421. stream->mode = mode;
  3422. stream->sampleRate = sampleRate;
  3423. asioCallbackInfo = &stream->callbackInfo;
  3424. stream->callbackInfo.object = (void *) this;
  3425. stream->callbackInfo.waitTime = (unsigned long) (200.0 * stream->bufferSize / stream->sampleRate);
  3426. return SUCCESS;
  3427. memory_error:
  3428. ASIODisposeBuffers();
  3429. drivers.removeCurrentDriver();
  3430. if (stream->callbackInfo.buffers)
  3431. free(stream->callbackInfo.buffers);
  3432. stream->callbackInfo.buffers = 0;
  3433. if (stream->userBuffer) {
  3434. free(stream->userBuffer);
  3435. stream->userBuffer = 0;
  3436. }
  3437. sprintf(message, "RtAudio: error allocating buffer memory (%s).",
  3438. devices[device].name);
  3439. error(RtError::WARNING);
  3440. return FAILURE;
  3441. }
  3442. void RtAudio :: cancelStreamCallback(int streamId)
  3443. {
  3444. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  3445. if (stream->callbackInfo.usingCallback) {
  3446. if (stream->state == STREAM_RUNNING)
  3447. stopStream( streamId );
  3448. MUTEX_LOCK(&stream->mutex);
  3449. stream->callbackInfo.usingCallback = false;
  3450. stream->callbackInfo.userData = NULL;
  3451. stream->state = STREAM_STOPPED;
  3452. stream->callbackInfo.callback = NULL;
  3453. MUTEX_UNLOCK(&stream->mutex);
  3454. }
  3455. }
  3456. void RtAudio :: closeStream(int streamId)
  3457. {
  3458. // We don't want an exception to be thrown here because this
  3459. // function is called by our class destructor. So, do our own
  3460. // streamId check.
  3461. if ( streams.find( streamId ) == streams.end() ) {
  3462. sprintf(message, "RtAudio: invalid stream identifier!");
  3463. error(RtError::WARNING);
  3464. return;
  3465. }
  3466. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
  3467. if (stream->state == STREAM_RUNNING)
  3468. ASIOStop();
  3469. ASIODisposeBuffers();
  3470. //ASIOExit();
  3471. drivers.removeCurrentDriver();
  3472. DeleteCriticalSection(&stream->mutex);
  3473. if (stream->callbackInfo.buffers)
  3474. free(stream->callbackInfo.buffers);
  3475. if (stream->userBuffer)
  3476. free(stream->userBuffer);
  3477. if (stream->deviceBuffer)
  3478. free(stream->deviceBuffer);
  3479. free(stream);
  3480. streams.erase(streamId);
  3481. }
  3482. void RtAudio :: startStream(int streamId)
  3483. {
  3484. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  3485. MUTEX_LOCK(&stream->mutex);
  3486. if (stream->state == STREAM_RUNNING) {
  3487. MUTEX_UNLOCK(&stream->mutex);
  3488. return;
  3489. }
  3490. stream->callbackInfo.blockTick = true;
  3491. stream->callbackInfo.stopStream = false;
  3492. stream->callbackInfo.streamId = streamId;
  3493. ASIOError result = ASIOStart();
  3494. if ( result != ASE_OK ) {
  3495. sprintf(message, "RtAudio: ASIO error starting device (%s).",
  3496. devices[stream->device[0]].name);
  3497. MUTEX_UNLOCK(&stream->mutex);
  3498. error(RtError::DRIVER_ERROR);
  3499. }
  3500. stream->state = STREAM_RUNNING;
  3501. MUTEX_UNLOCK(&stream->mutex);
  3502. }
  3503. void RtAudio :: stopStream(int streamId)
  3504. {
  3505. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  3506. MUTEX_LOCK(&stream->mutex);
  3507. if (stream->state == STREAM_STOPPED) {
  3508. MUTEX_UNLOCK(&stream->mutex);
  3509. return;
  3510. }
  3511. ASIOError result = ASIOStop();
  3512. if ( result != ASE_OK ) {
  3513. sprintf(message, "RtAudio: ASIO error stopping device (%s).",
  3514. devices[stream->device[0]].name);
  3515. MUTEX_UNLOCK(&stream->mutex);
  3516. error(RtError::DRIVER_ERROR);
  3517. }
  3518. stream->state = STREAM_STOPPED;
  3519. MUTEX_UNLOCK(&stream->mutex);
  3520. }
  3521. void RtAudio :: abortStream(int streamId)
  3522. {
  3523. stopStream( streamId );
  3524. }
  3525. // I don't know how this function can be implemented.
  3526. int RtAudio :: streamWillBlock(int streamId)
  3527. {
  3528. sprintf(message, "RtAudio: streamWillBlock() cannot be implemented for ASIO.");
  3529. error(RtError::WARNING);
  3530. return 0;
  3531. }
  3532. void RtAudio :: tickStream(int streamId)
  3533. {
  3534. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  3535. if (stream->state == STREAM_STOPPED)
  3536. return;
  3537. if (stream->callbackInfo.usingCallback) {
  3538. sprintf(message, "RtAudio: tickStream() should not be used when a callback function is set!");
  3539. error(RtError::WARNING);
  3540. return;
  3541. }
  3542. // Block waiting here until the user data is processed in callbackEvent().
  3543. while ( stream->callbackInfo.blockTick )
  3544. Sleep(stream->callbackInfo.waitTime);
  3545. MUTEX_LOCK(&stream->mutex);
  3546. stream->callbackInfo.blockTick = true;
  3547. MUTEX_UNLOCK(&stream->mutex);
  3548. }
  3549. void RtAudio :: callbackEvent(int streamId, int bufferIndex, void *inData, void *outData)
  3550. {
  3551. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  3552. CALLBACK_INFO *info = asioCallbackInfo;
  3553. if ( !info->usingCallback ) {
  3554. // Block waiting here until we get new user data in tickStream().
  3555. while ( !info->blockTick )
  3556. Sleep(info->waitTime);
  3557. }
  3558. else if ( info->stopStream ) {
  3559. // Check if the stream should be stopped (via the previous user
  3560. // callback return value). We stop the stream here, rather than
  3561. // after the function call, so that output data can first be
  3562. // processed.
  3563. this->stopStream(asioCallbackInfo->streamId);
  3564. return;
  3565. }
  3566. MUTEX_LOCK(&stream->mutex);
  3567. // Invoke user callback first, to get fresh output data.
  3568. if ( info->usingCallback ) {
  3569. RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) info->callback;
  3570. if ( callback(stream->userBuffer, stream->bufferSize, info->userData) )
  3571. info->stopStream = true;
  3572. }
  3573. int nChannels = stream->nDeviceChannels[0] + stream->nDeviceChannels[1];
  3574. int bufferBytes;
  3575. ASIOBufferInfo *bufferInfos = (ASIOBufferInfo *) info->buffers;
  3576. if ( stream->mode == OUTPUT || stream->mode == DUPLEX ) {
  3577. bufferBytes = stream->bufferSize * formatBytes(stream->deviceFormat[0]);
  3578. if (stream->doConvertBuffer[0]) {
  3579. convertStreamBuffer(stream, OUTPUT);
  3580. if ( stream->doByteSwap[0] )
  3581. byteSwapBuffer(stream->deviceBuffer,
  3582. stream->bufferSize * stream->nDeviceChannels[0],
  3583. stream->deviceFormat[0]);
  3584. // Always de-interleave ASIO output data.
  3585. for ( int i=0; i<stream->nDeviceChannels[0]; i++, bufferInfos++ ) {
  3586. memcpy(bufferInfos->buffers[bufferIndex],
  3587. &stream->deviceBuffer[i*bufferBytes], bufferBytes );
  3588. }
  3589. }
  3590. else { // single channel only
  3591. if (stream->doByteSwap[0])
  3592. byteSwapBuffer(stream->userBuffer,
  3593. stream->bufferSize * stream->nUserChannels[0],
  3594. stream->userFormat);
  3595. memcpy(bufferInfos->buffers[bufferIndex], stream->userBuffer, bufferBytes );
  3596. }
  3597. }
  3598. if ( stream->mode == INPUT || stream->mode == DUPLEX ) {
  3599. bufferBytes = stream->bufferSize * formatBytes(stream->deviceFormat[1]);
  3600. if (stream->doConvertBuffer[1]) {
  3601. // Always interleave ASIO input data.
  3602. for ( int i=0; i<stream->nDeviceChannels[1]; i++, bufferInfos++ )
  3603. memcpy(&stream->deviceBuffer[i*bufferBytes], bufferInfos->buffers[bufferIndex], bufferBytes );
  3604. if ( stream->doByteSwap[1] )
  3605. byteSwapBuffer(stream->deviceBuffer,
  3606. stream->bufferSize * stream->nDeviceChannels[1],
  3607. stream->deviceFormat[1]);
  3608. convertStreamBuffer(stream, INPUT);
  3609. }
  3610. else { // single channel only
  3611. memcpy(stream->userBuffer, bufferInfos->buffers[bufferIndex], bufferBytes );
  3612. if (stream->doByteSwap[1])
  3613. byteSwapBuffer(stream->userBuffer,
  3614. stream->bufferSize * stream->nUserChannels[1],
  3615. stream->userFormat);
  3616. }
  3617. }
  3618. if ( !info->usingCallback )
  3619. info->blockTick = false;
  3620. MUTEX_UNLOCK(&stream->mutex);
  3621. }
  3622. void RtAudio :: setStreamCallback(int streamId, RTAUDIO_CALLBACK callback, void *userData)
  3623. {
  3624. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  3625. stream->callbackInfo.callback = (void *) callback;
  3626. stream->callbackInfo.userData = userData;
  3627. stream->callbackInfo.usingCallback = true;
  3628. }
  3629. //******************** End of __WINDOWS_ASIO__ *********************//
  3630. #elif defined(__WINDOWS_DS__) // Windows DirectSound API
  3631. #include <dsound.h>
  3632. // Declarations for utility functions, callbacks, and structures
  3633. // specific to the DirectSound implementation.
  3634. static bool CALLBACK deviceCountCallback(LPGUID lpguid,
  3635. LPCSTR lpcstrDescription,
  3636. LPCSTR lpcstrModule,
  3637. LPVOID lpContext);
  3638. static bool CALLBACK deviceInfoCallback(LPGUID lpguid,
  3639. LPCSTR lpcstrDescription,
  3640. LPCSTR lpcstrModule,
  3641. LPVOID lpContext);
  3642. static bool CALLBACK defaultDeviceCallback(LPGUID lpguid,
  3643. LPCSTR lpcstrDescription,
  3644. LPCSTR lpcstrModule,
  3645. LPVOID lpContext);
  3646. static bool CALLBACK deviceIdCallback(LPGUID lpguid,
  3647. LPCSTR lpcstrDescription,
  3648. LPCSTR lpcstrModule,
  3649. LPVOID lpContext);
  3650. static char* getErrorString(int code);
  3651. struct enum_info {
  3652. char name[64];
  3653. LPGUID id;
  3654. bool isInput;
  3655. bool isValid;
  3656. };
  3657. int RtAudio :: getDefaultInputDevice(void)
  3658. {
  3659. enum_info info;
  3660. info.name[0] = '\0';
  3661. // Enumerate through devices to find the default output.
  3662. HRESULT result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)defaultDeviceCallback, &info);
  3663. if ( FAILED(result) ) {
  3664. sprintf(message, "RtAudio: Error performing default input device enumeration: %s.",
  3665. getErrorString(result));
  3666. error(RtError::WARNING);
  3667. return 0;
  3668. }
  3669. for ( int i=0; i<nDevices; i++ )
  3670. if ( strncmp( devices[i].name, info.name, 64 ) == 0 ) return i;
  3671. return 0;
  3672. }
  3673. int RtAudio :: getDefaultOutputDevice(void)
  3674. {
  3675. enum_info info;
  3676. info.name[0] = '\0';
  3677. // Enumerate through devices to find the default output.
  3678. HRESULT result = DirectSoundEnumerate((LPDSENUMCALLBACK)defaultDeviceCallback, &info);
  3679. if ( FAILED(result) ) {
  3680. sprintf(message, "RtAudio: Error performing default output device enumeration: %s.",
  3681. getErrorString(result));
  3682. error(RtError::WARNING);
  3683. return 0;
  3684. }
  3685. for ( int i=0; i<nDevices; i++ )
  3686. if ( strncmp(devices[i].name, info.name, 64 ) == 0 ) return i;
  3687. return 0;
  3688. }
  3689. void RtAudio :: initialize(void)
  3690. {
  3691. int i, ins = 0, outs = 0, count = 0;
  3692. HRESULT result;
  3693. nDevices = 0;
  3694. // Count DirectSound devices.
  3695. result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceCountCallback, &outs);
  3696. if ( FAILED(result) ) {
  3697. sprintf(message, "RtAudio: Unable to enumerate through sound playback devices: %s.",
  3698. getErrorString(result));
  3699. error(RtError::DRIVER_ERROR);
  3700. }
  3701. // Count DirectSoundCapture devices.
  3702. result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceCountCallback, &ins);
  3703. if ( FAILED(result) ) {
  3704. sprintf(message, "RtAudio: Unable to enumerate through sound capture devices: %s.",
  3705. getErrorString(result));
  3706. error(RtError::DRIVER_ERROR);
  3707. }
  3708. count = ins + outs;
  3709. if (count == 0) return;
  3710. std::vector<enum_info> info(count);
  3711. for (i=0; i<count; i++) {
  3712. info[i].name[0] = '\0';
  3713. if (i < outs) info[i].isInput = false;
  3714. else info[i].isInput = true;
  3715. }
  3716. // Get playback device info and check capabilities.
  3717. result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceInfoCallback, &info[0]);
  3718. if ( FAILED(result) ) {
  3719. sprintf(message, "RtAudio: Unable to enumerate through sound playback devices: %s.",
  3720. getErrorString(result));
  3721. error(RtError::DRIVER_ERROR);
  3722. }
  3723. // Get capture device info and check capabilities.
  3724. result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceInfoCallback, &info[0]);
  3725. if ( FAILED(result) ) {
  3726. sprintf(message, "RtAudio: Unable to enumerate through sound capture devices: %s.",
  3727. getErrorString(result));
  3728. error(RtError::DRIVER_ERROR);
  3729. }
  3730. // Parse the devices and check validity. Devices are considered
  3731. // invalid if they cannot be opened, they report < 1 supported
  3732. // channels, or they report no supported data (capture only).
  3733. for (i=0; i<count; i++)
  3734. if ( info[i].isValid ) nDevices++;
  3735. if (nDevices == 0) return;
  3736. // Allocate the RTAUDIO_DEVICE structures.
  3737. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  3738. if (devices == NULL) {
  3739. sprintf(message, "RtAudio: memory allocation error!");
  3740. error(RtError::MEMORY_ERROR);
  3741. }
  3742. // Copy the names to our devices structures.
  3743. int index = 0;
  3744. for (i=0; i<count; i++) {
  3745. if ( info[i].isValid )
  3746. strncpy(devices[index++].name, info[i].name, 64);
  3747. }
  3748. //for (i=0;i<nDevices; i++)
  3749. //probeDeviceInfo(&devices[i]);
  3750. return;
  3751. }
  3752. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  3753. {
  3754. enum_info dsinfo;
  3755. strncpy( dsinfo.name, info->name, 64 );
  3756. dsinfo.isValid = false;
  3757. // Enumerate through input devices to find the id (if it exists).
  3758. HRESULT result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo);
  3759. if ( FAILED(result) ) {
  3760. sprintf(message, "RtAudio: Error performing input device id enumeration: %s.",
  3761. getErrorString(result));
  3762. error(RtError::WARNING);
  3763. return;
  3764. }
  3765. // Do capture probe first.
  3766. if ( dsinfo.isValid == false )
  3767. goto playback_probe;
  3768. LPDIRECTSOUNDCAPTURE input;
  3769. result = DirectSoundCaptureCreate( dsinfo.id, &input, NULL );
  3770. if ( FAILED(result) ) {
  3771. sprintf(message, "RtAudio: Could not create DirectSound capture object (%s): %s.",
  3772. info->name, getErrorString(result));
  3773. error(RtError::WARNING);
  3774. goto playback_probe;
  3775. }
  3776. DSCCAPS in_caps;
  3777. in_caps.dwSize = sizeof(in_caps);
  3778. result = input->GetCaps( &in_caps );
  3779. if ( FAILED(result) ) {
  3780. input->Release();
  3781. sprintf(message, "RtAudio: Could not get DirectSound capture capabilities (%s): %s.",
  3782. info->name, getErrorString(result));
  3783. error(RtError::WARNING);
  3784. goto playback_probe;
  3785. }
  3786. // Get input channel information.
  3787. info->minInputChannels = 1;
  3788. info->maxInputChannels = in_caps.dwChannels;
  3789. // Get sample rate and format information.
  3790. if( in_caps.dwChannels == 2 ) {
  3791. if( in_caps.dwFormats & WAVE_FORMAT_1S16 ) info->nativeFormats |= RTAUDIO_SINT16;
  3792. if( in_caps.dwFormats & WAVE_FORMAT_2S16 ) info->nativeFormats |= RTAUDIO_SINT16;
  3793. if( in_caps.dwFormats & WAVE_FORMAT_4S16 ) info->nativeFormats |= RTAUDIO_SINT16;
  3794. if( in_caps.dwFormats & WAVE_FORMAT_1S08 ) info->nativeFormats |= RTAUDIO_SINT8;
  3795. if( in_caps.dwFormats & WAVE_FORMAT_2S08 ) info->nativeFormats |= RTAUDIO_SINT8;
  3796. if( in_caps.dwFormats & WAVE_FORMAT_4S08 ) info->nativeFormats |= RTAUDIO_SINT8;
  3797. if ( info->nativeFormats & RTAUDIO_SINT16 ) {
  3798. if( in_caps.dwFormats & WAVE_FORMAT_1S16 ) info->sampleRates[info->nSampleRates++] = 11025;
  3799. if( in_caps.dwFormats & WAVE_FORMAT_2S16 ) info->sampleRates[info->nSampleRates++] = 22050;
  3800. if( in_caps.dwFormats & WAVE_FORMAT_4S16 ) info->sampleRates[info->nSampleRates++] = 44100;
  3801. }
  3802. else if ( info->nativeFormats & RTAUDIO_SINT8 ) {
  3803. if( in_caps.dwFormats & WAVE_FORMAT_1S08 ) info->sampleRates[info->nSampleRates++] = 11025;
  3804. if( in_caps.dwFormats & WAVE_FORMAT_2S08 ) info->sampleRates[info->nSampleRates++] = 22050;
  3805. if( in_caps.dwFormats & WAVE_FORMAT_4S08 ) info->sampleRates[info->nSampleRates++] = 44100;
  3806. }
  3807. }
  3808. else if ( in_caps.dwChannels == 1 ) {
  3809. if( in_caps.dwFormats & WAVE_FORMAT_1M16 ) info->nativeFormats |= RTAUDIO_SINT16;
  3810. if( in_caps.dwFormats & WAVE_FORMAT_2M16 ) info->nativeFormats |= RTAUDIO_SINT16;
  3811. if( in_caps.dwFormats & WAVE_FORMAT_4M16 ) info->nativeFormats |= RTAUDIO_SINT16;
  3812. if( in_caps.dwFormats & WAVE_FORMAT_1M08 ) info->nativeFormats |= RTAUDIO_SINT8;
  3813. if( in_caps.dwFormats & WAVE_FORMAT_2M08 ) info->nativeFormats |= RTAUDIO_SINT8;
  3814. if( in_caps.dwFormats & WAVE_FORMAT_4M08 ) info->nativeFormats |= RTAUDIO_SINT8;
  3815. if ( info->nativeFormats & RTAUDIO_SINT16 ) {
  3816. if( in_caps.dwFormats & WAVE_FORMAT_1M16 ) info->sampleRates[info->nSampleRates++] = 11025;
  3817. if( in_caps.dwFormats & WAVE_FORMAT_2M16 ) info->sampleRates[info->nSampleRates++] = 22050;
  3818. if( in_caps.dwFormats & WAVE_FORMAT_4M16 ) info->sampleRates[info->nSampleRates++] = 44100;
  3819. }
  3820. else if ( info->nativeFormats & RTAUDIO_SINT8 ) {
  3821. if( in_caps.dwFormats & WAVE_FORMAT_1M08 ) info->sampleRates[info->nSampleRates++] = 11025;
  3822. if( in_caps.dwFormats & WAVE_FORMAT_2M08 ) info->sampleRates[info->nSampleRates++] = 22050;
  3823. if( in_caps.dwFormats & WAVE_FORMAT_4M08 ) info->sampleRates[info->nSampleRates++] = 44100;
  3824. }
  3825. }
  3826. else info->minInputChannels = 0; // technically, this would be an error
  3827. input->Release();
  3828. playback_probe:
  3829. dsinfo.isValid = false;
  3830. // Enumerate through output devices to find the id (if it exists).
  3831. result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo);
  3832. if ( FAILED(result) ) {
  3833. sprintf(message, "RtAudio: Error performing output device id enumeration: %s.",
  3834. getErrorString(result));
  3835. error(RtError::WARNING);
  3836. return;
  3837. }
  3838. // Now do playback probe.
  3839. if ( dsinfo.isValid == false )
  3840. goto check_parameters;
  3841. LPDIRECTSOUND output;
  3842. DSCAPS out_caps;
  3843. result = DirectSoundCreate( dsinfo.id, &output, NULL );
  3844. if ( FAILED(result) ) {
  3845. sprintf(message, "RtAudio: Could not create DirectSound playback object (%s): %s.",
  3846. info->name, getErrorString(result));
  3847. error(RtError::WARNING);
  3848. goto check_parameters;
  3849. }
  3850. out_caps.dwSize = sizeof(out_caps);
  3851. result = output->GetCaps( &out_caps );
  3852. if ( FAILED(result) ) {
  3853. output->Release();
  3854. sprintf(message, "RtAudio: Could not get DirectSound playback capabilities (%s): %s.",
  3855. info->name, getErrorString(result));
  3856. error(RtError::WARNING);
  3857. goto check_parameters;
  3858. }
  3859. // Get output channel information.
  3860. info->minOutputChannels = 1;
  3861. info->maxOutputChannels = ( out_caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1;
  3862. // Get sample rate information. Use capture device rate information
  3863. // if it exists.
  3864. if ( info->nSampleRates == 0 ) {
  3865. info->sampleRates[0] = (int) out_caps.dwMinSecondarySampleRate;
  3866. info->sampleRates[1] = (int) out_caps.dwMaxSecondarySampleRate;
  3867. if ( out_caps.dwFlags & DSCAPS_CONTINUOUSRATE )
  3868. info->nSampleRates = -1;
  3869. else if ( out_caps.dwMinSecondarySampleRate == out_caps.dwMaxSecondarySampleRate ) {
  3870. if ( out_caps.dwMinSecondarySampleRate == 0 ) {
  3871. // This is a bogus driver report ... fake the range and cross
  3872. // your fingers.
  3873. info->sampleRates[0] = 11025;
  3874. info->sampleRates[1] = 48000;
  3875. info->nSampleRates = -1; /* continuous range */
  3876. sprintf(message, "RtAudio: bogus sample rates reported by DirectSound driver ... using defaults (%s).",
  3877. info->name);
  3878. error(RtError::DEBUG_WARNING);
  3879. }
  3880. else {
  3881. info->nSampleRates = 1;
  3882. }
  3883. }
  3884. else if ( (out_caps.dwMinSecondarySampleRate < 1000.0) &&
  3885. (out_caps.dwMaxSecondarySampleRate > 50000.0) ) {
  3886. // This is a bogus driver report ... support for only two
  3887. // distant rates. We'll assume this is a range.
  3888. info->nSampleRates = -1;
  3889. sprintf(message, "RtAudio: bogus sample rates reported by DirectSound driver ... using range (%s).",
  3890. info->name);
  3891. error(RtError::WARNING);
  3892. }
  3893. else info->nSampleRates = 2;
  3894. }
  3895. else {
  3896. // Check input rates against output rate range
  3897. for ( int i=info->nSampleRates-1; i>=0; i-- ) {
  3898. if ( info->sampleRates[i] <= out_caps.dwMaxSecondarySampleRate )
  3899. break;
  3900. info->nSampleRates--;
  3901. }
  3902. while ( info->sampleRates[0] < out_caps.dwMinSecondarySampleRate ) {
  3903. info->nSampleRates--;
  3904. for ( int i=0; i<info->nSampleRates; i++)
  3905. info->sampleRates[i] = info->sampleRates[i+1];
  3906. if ( info->nSampleRates <= 0 ) break;
  3907. }
  3908. }
  3909. // Get format information.
  3910. if ( out_caps.dwFlags & DSCAPS_PRIMARY16BIT ) info->nativeFormats |= RTAUDIO_SINT16;
  3911. if ( out_caps.dwFlags & DSCAPS_PRIMARY8BIT ) info->nativeFormats |= RTAUDIO_SINT8;
  3912. output->Release();
  3913. check_parameters:
  3914. if ( info->maxInputChannels == 0 && info->maxOutputChannels == 0 )
  3915. return;
  3916. if ( info->nSampleRates == 0 || info->nativeFormats == 0 )
  3917. return;
  3918. // Determine duplex status.
  3919. if (info->maxInputChannels < info->maxOutputChannels)
  3920. info->maxDuplexChannels = info->maxInputChannels;
  3921. else
  3922. info->maxDuplexChannels = info->maxOutputChannels;
  3923. if (info->minInputChannels < info->minOutputChannels)
  3924. info->minDuplexChannels = info->minInputChannels;
  3925. else
  3926. info->minDuplexChannels = info->minOutputChannels;
  3927. if ( info->maxDuplexChannels > 0 ) info->hasDuplexSupport = true;
  3928. else info->hasDuplexSupport = false;
  3929. info->probed = true;
  3930. return;
  3931. }
  3932. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  3933. STREAM_MODE mode, int channels,
  3934. int sampleRate, RTAUDIO_FORMAT format,
  3935. int *bufferSize, int numberOfBuffers)
  3936. {
  3937. HRESULT result;
  3938. HWND hWnd = GetForegroundWindow();
  3939. // According to a note in PortAudio, using GetDesktopWindow()
  3940. // instead of GetForegroundWindow() is supposed to avoid problems
  3941. // that occur when the application's window is not the foreground
  3942. // window. Also, if the application window closes before the
  3943. // DirectSound buffer, DirectSound can crash. However, for console
  3944. // applications, no sound was produced when using GetDesktopWindow().
  3945. long buffer_size;
  3946. LPVOID audioPtr;
  3947. DWORD dataLen;
  3948. int nBuffers;
  3949. // Check the numberOfBuffers parameter and limit the lowest value to
  3950. // two. This is a judgement call and a value of two is probably too
  3951. // low for capture, but it should work for playback.
  3952. if (numberOfBuffers < 2)
  3953. nBuffers = 2;
  3954. else
  3955. nBuffers = numberOfBuffers;
  3956. // Define the wave format structure (16-bit PCM, srate, channels)
  3957. WAVEFORMATEX waveFormat;
  3958. ZeroMemory(&waveFormat, sizeof(WAVEFORMATEX));
  3959. waveFormat.wFormatTag = WAVE_FORMAT_PCM;
  3960. waveFormat.nChannels = channels;
  3961. waveFormat.nSamplesPerSec = (unsigned long) sampleRate;
  3962. // Determine the data format.
  3963. if ( devices[device].nativeFormats ) { // 8-bit and/or 16-bit support
  3964. if ( format == RTAUDIO_SINT8 ) {
  3965. if ( devices[device].nativeFormats & RTAUDIO_SINT8 )
  3966. waveFormat.wBitsPerSample = 8;
  3967. else
  3968. waveFormat.wBitsPerSample = 16;
  3969. }
  3970. else {
  3971. if ( devices[device].nativeFormats & RTAUDIO_SINT16 )
  3972. waveFormat.wBitsPerSample = 16;
  3973. else
  3974. waveFormat.wBitsPerSample = 8;
  3975. }
  3976. }
  3977. else {
  3978. sprintf(message, "RtAudio: no reported data formats for DirectSound device (%s).",
  3979. devices[device].name);
  3980. error(RtError::DEBUG_WARNING);
  3981. return FAILURE;
  3982. }
  3983. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
  3984. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  3985. enum_info dsinfo;
  3986. strncpy( dsinfo.name, devices[device].name, 64 );
  3987. dsinfo.isValid = false;
  3988. if ( mode == OUTPUT ) {
  3989. if ( devices[device].maxOutputChannels < channels )
  3990. return FAILURE;
  3991. // Enumerate through output devices to find the id (if it exists).
  3992. result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo);
  3993. if ( FAILED(result) ) {
  3994. sprintf(message, "RtAudio: Error performing output device id enumeration: %s.",
  3995. getErrorString(result));
  3996. error(RtError::DEBUG_WARNING);
  3997. return FAILURE;
  3998. }
  3999. if ( dsinfo.isValid == false ) {
  4000. sprintf(message, "RtAudio: DS output device (%s) id not found!", devices[device].name);
  4001. error(RtError::DEBUG_WARNING);
  4002. return FAILURE;
  4003. }
  4004. LPGUID id = dsinfo.id;
  4005. LPDIRECTSOUND object;
  4006. LPDIRECTSOUNDBUFFER buffer;
  4007. DSBUFFERDESC bufferDescription;
  4008. result = DirectSoundCreate( id, &object, NULL );
  4009. if ( FAILED(result) ) {
  4010. sprintf(message, "RtAudio: Could not create DirectSound playback object (%s): %s.",
  4011. devices[device].name, getErrorString(result));
  4012. error(RtError::DEBUG_WARNING);
  4013. return FAILURE;
  4014. }
  4015. // Set cooperative level to DSSCL_EXCLUSIVE
  4016. result = object->SetCooperativeLevel(hWnd, DSSCL_EXCLUSIVE);
  4017. if ( FAILED(result) ) {
  4018. object->Release();
  4019. sprintf(message, "RtAudio: Unable to set DirectSound cooperative level (%s): %s.",
  4020. devices[device].name, getErrorString(result));
  4021. error(RtError::WARNING);
  4022. return FAILURE;
  4023. }
  4024. // Even though we will write to the secondary buffer, we need to
  4025. // access the primary buffer to set the correct output format.
  4026. // The default is 8-bit, 22 kHz!
  4027. // Setup the DS primary buffer description.
  4028. ZeroMemory(&bufferDescription, sizeof(DSBUFFERDESC));
  4029. bufferDescription.dwSize = sizeof(DSBUFFERDESC);
  4030. bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;
  4031. // Obtain the primary buffer
  4032. result = object->CreateSoundBuffer(&bufferDescription, &buffer, NULL);
  4033. if ( FAILED(result) ) {
  4034. object->Release();
  4035. sprintf(message, "RtAudio: Unable to access DS primary buffer (%s): %s.",
  4036. devices[device].name, getErrorString(result));
  4037. error(RtError::WARNING);
  4038. return FAILURE;
  4039. }
  4040. // Set the primary DS buffer sound format.
  4041. result = buffer->SetFormat(&waveFormat);
  4042. if ( FAILED(result) ) {
  4043. object->Release();
  4044. sprintf(message, "RtAudio: Unable to set DS primary buffer format (%s): %s.",
  4045. devices[device].name, getErrorString(result));
  4046. error(RtError::WARNING);
  4047. return FAILURE;
  4048. }
  4049. // Setup the secondary DS buffer description.
  4050. buffer_size = channels * *bufferSize * nBuffers * waveFormat.wBitsPerSample / 8;
  4051. ZeroMemory(&bufferDescription, sizeof(DSBUFFERDESC));
  4052. bufferDescription.dwSize = sizeof(DSBUFFERDESC);
  4053. bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
  4054. DSBCAPS_GETCURRENTPOSITION2 |
  4055. DSBCAPS_LOCHARDWARE ); // Force hardware mixing
  4056. bufferDescription.dwBufferBytes = buffer_size;
  4057. bufferDescription.lpwfxFormat = &waveFormat;
  4058. // Try to create the secondary DS buffer. If that doesn't work,
  4059. // try to use software mixing. Otherwise, there's a problem.
  4060. result = object->CreateSoundBuffer(&bufferDescription, &buffer, NULL);
  4061. if ( FAILED(result) ) {
  4062. bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
  4063. DSBCAPS_GETCURRENTPOSITION2 |
  4064. DSBCAPS_LOCSOFTWARE ); // Force software mixing
  4065. result = object->CreateSoundBuffer(&bufferDescription, &buffer, NULL);
  4066. if ( FAILED(result) ) {
  4067. object->Release();
  4068. sprintf(message, "RtAudio: Unable to create secondary DS buffer (%s): %s.",
  4069. devices[device].name, getErrorString(result));
  4070. error(RtError::WARNING);
  4071. return FAILURE;
  4072. }
  4073. }
  4074. // Get the buffer size ... might be different from what we specified.
  4075. DSBCAPS dsbcaps;
  4076. dsbcaps.dwSize = sizeof(DSBCAPS);
  4077. buffer->GetCaps(&dsbcaps);
  4078. buffer_size = dsbcaps.dwBufferBytes;
  4079. // Lock the DS buffer
  4080. result = buffer->Lock(0, buffer_size, &audioPtr, &dataLen, NULL, NULL, 0);
  4081. if ( FAILED(result) ) {
  4082. object->Release();
  4083. sprintf(message, "RtAudio: Unable to lock DS buffer (%s): %s.",
  4084. devices[device].name, getErrorString(result));
  4085. error(RtError::WARNING);
  4086. return FAILURE;
  4087. }
  4088. // Zero the DS buffer
  4089. ZeroMemory(audioPtr, dataLen);
  4090. // Unlock the DS buffer
  4091. result = buffer->Unlock(audioPtr, dataLen, NULL, 0);
  4092. if ( FAILED(result) ) {
  4093. object->Release();
  4094. sprintf(message, "RtAudio: Unable to unlock DS buffer(%s): %s.",
  4095. devices[device].name, getErrorString(result));
  4096. error(RtError::WARNING);
  4097. return FAILURE;
  4098. }
  4099. stream->handle[0].object = (void *) object;
  4100. stream->handle[0].buffer = (void *) buffer;
  4101. stream->nDeviceChannels[0] = channels;
  4102. }
  4103. if ( mode == INPUT ) {
  4104. if ( devices[device].maxInputChannels < channels )
  4105. return FAILURE;
  4106. // Enumerate through input devices to find the id (if it exists).
  4107. result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo);
  4108. if ( FAILED(result) ) {
  4109. sprintf(message, "RtAudio: Error performing input device id enumeration: %s.",
  4110. getErrorString(result));
  4111. error(RtError::DEBUG_WARNING);
  4112. return FAILURE;
  4113. }
  4114. if ( dsinfo.isValid == false ) {
  4115. sprintf(message, "RtAudio: DS input device (%s) id not found!", devices[device].name);
  4116. error(RtError::DEBUG_WARNING);
  4117. return FAILURE;
  4118. }
  4119. LPGUID id = dsinfo.id;
  4120. LPDIRECTSOUNDCAPTURE object;
  4121. LPDIRECTSOUNDCAPTUREBUFFER buffer;
  4122. DSCBUFFERDESC bufferDescription;
  4123. result = DirectSoundCaptureCreate( id, &object, NULL );
  4124. if ( FAILED(result) ) {
  4125. sprintf(message, "RtAudio: Could not create DirectSound capture object (%s): %s.",
  4126. devices[device].name, getErrorString(result));
  4127. error(RtError::WARNING);
  4128. return FAILURE;
  4129. }
  4130. // Setup the secondary DS buffer description.
  4131. buffer_size = channels * *bufferSize * nBuffers * waveFormat.wBitsPerSample / 8;
  4132. ZeroMemory(&bufferDescription, sizeof(DSCBUFFERDESC));
  4133. bufferDescription.dwSize = sizeof(DSCBUFFERDESC);
  4134. bufferDescription.dwFlags = 0;
  4135. bufferDescription.dwReserved = 0;
  4136. bufferDescription.dwBufferBytes = buffer_size;
  4137. bufferDescription.lpwfxFormat = &waveFormat;
  4138. // Create the capture buffer.
  4139. result = object->CreateCaptureBuffer(&bufferDescription, &buffer, NULL);
  4140. if ( FAILED(result) ) {
  4141. object->Release();
  4142. sprintf(message, "RtAudio: Unable to create DS capture buffer (%s): %s.",
  4143. devices[device].name, getErrorString(result));
  4144. error(RtError::WARNING);
  4145. return FAILURE;
  4146. }
  4147. // Lock the capture buffer
  4148. result = buffer->Lock(0, buffer_size, &audioPtr, &dataLen, NULL, NULL, 0);
  4149. if ( FAILED(result) ) {
  4150. object->Release();
  4151. sprintf(message, "RtAudio: Unable to lock DS capture buffer (%s): %s.",
  4152. devices[device].name, getErrorString(result));
  4153. error(RtError::WARNING);
  4154. return FAILURE;
  4155. }
  4156. // Zero the buffer
  4157. ZeroMemory(audioPtr, dataLen);
  4158. // Unlock the buffer
  4159. result = buffer->Unlock(audioPtr, dataLen, NULL, 0);
  4160. if ( FAILED(result) ) {
  4161. object->Release();
  4162. sprintf(message, "RtAudio: Unable to unlock DS capture buffer (%s): %s.",
  4163. devices[device].name, getErrorString(result));
  4164. error(RtError::WARNING);
  4165. return FAILURE;
  4166. }
  4167. stream->handle[1].object = (void *) object;
  4168. stream->handle[1].buffer = (void *) buffer;
  4169. stream->nDeviceChannels[1] = channels;
  4170. }
  4171. stream->userFormat = format;
  4172. if ( waveFormat.wBitsPerSample == 8 )
  4173. stream->deviceFormat[mode] = RTAUDIO_SINT8;
  4174. else
  4175. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  4176. stream->nUserChannels[mode] = channels;
  4177. *bufferSize = buffer_size / (channels * nBuffers * waveFormat.wBitsPerSample / 8);
  4178. stream->bufferSize = *bufferSize;
  4179. // Set flags for buffer conversion
  4180. stream->doConvertBuffer[mode] = false;
  4181. if (stream->userFormat != stream->deviceFormat[mode])
  4182. stream->doConvertBuffer[mode] = true;
  4183. if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
  4184. stream->doConvertBuffer[mode] = true;
  4185. // Allocate necessary internal buffers
  4186. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  4187. long buffer_bytes;
  4188. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  4189. buffer_bytes = stream->nUserChannels[0];
  4190. else
  4191. buffer_bytes = stream->nUserChannels[1];
  4192. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  4193. if (stream->userBuffer) free(stream->userBuffer);
  4194. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  4195. if (stream->userBuffer == NULL)
  4196. goto memory_error;
  4197. }
  4198. if ( stream->doConvertBuffer[mode] ) {
  4199. long buffer_bytes;
  4200. bool makeBuffer = true;
  4201. if ( mode == OUTPUT )
  4202. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  4203. else { // mode == INPUT
  4204. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  4205. if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
  4206. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  4207. if ( buffer_bytes < bytes_out ) makeBuffer = false;
  4208. }
  4209. }
  4210. if ( makeBuffer ) {
  4211. buffer_bytes *= *bufferSize;
  4212. if (stream->deviceBuffer) free(stream->deviceBuffer);
  4213. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  4214. if (stream->deviceBuffer == NULL)
  4215. goto memory_error;
  4216. }
  4217. }
  4218. stream->device[mode] = device;
  4219. stream->state = STREAM_STOPPED;
  4220. if ( stream->mode == OUTPUT && mode == INPUT )
  4221. // We had already set up an output stream.
  4222. stream->mode = DUPLEX;
  4223. else
  4224. stream->mode = mode;
  4225. stream->nBuffers = nBuffers;
  4226. stream->sampleRate = sampleRate;
  4227. return SUCCESS;
  4228. memory_error:
  4229. if (stream->handle[0].object) {
  4230. LPDIRECTSOUND object = (LPDIRECTSOUND) stream->handle[0].object;
  4231. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  4232. if (buffer) {
  4233. buffer->Release();
  4234. stream->handle[0].buffer = NULL;
  4235. }
  4236. object->Release();
  4237. stream->handle[0].object = NULL;
  4238. }
  4239. if (stream->handle[1].object) {
  4240. LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) stream->handle[1].object;
  4241. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  4242. if (buffer) {
  4243. buffer->Release();
  4244. stream->handle[1].buffer = NULL;
  4245. }
  4246. object->Release();
  4247. stream->handle[1].object = NULL;
  4248. }
  4249. if (stream->userBuffer) {
  4250. free(stream->userBuffer);
  4251. stream->userBuffer = 0;
  4252. }
  4253. sprintf(message, "RtAudio: error allocating buffer memory (%s).",
  4254. devices[device].name);
  4255. error(RtError::WARNING);
  4256. return FAILURE;
  4257. }
  4258. void RtAudio :: cancelStreamCallback(int streamId)
  4259. {
  4260. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  4261. if (stream->callbackInfo.usingCallback) {
  4262. if (stream->state == STREAM_RUNNING)
  4263. stopStream( streamId );
  4264. MUTEX_LOCK(&stream->mutex);
  4265. stream->callbackInfo.usingCallback = false;
  4266. WaitForSingleObject( (HANDLE)stream->callbackInfo.thread, INFINITE );
  4267. CloseHandle( (HANDLE)stream->callbackInfo.thread );
  4268. stream->callbackInfo.thread = 0;
  4269. stream->callbackInfo.callback = NULL;
  4270. stream->callbackInfo.userData = NULL;
  4271. MUTEX_UNLOCK(&stream->mutex);
  4272. }
  4273. }
  4274. void RtAudio :: closeStream(int streamId)
  4275. {
  4276. // We don't want an exception to be thrown here because this
  4277. // function is called by our class destructor. So, do our own
  4278. // streamId check.
  4279. if ( streams.find( streamId ) == streams.end() ) {
  4280. sprintf(message, "RtAudio: invalid stream identifier!");
  4281. error(RtError::WARNING);
  4282. return;
  4283. }
  4284. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
  4285. if (stream->callbackInfo.usingCallback) {
  4286. stream->callbackInfo.usingCallback = false;
  4287. WaitForSingleObject( (HANDLE)stream->callbackInfo.thread, INFINITE );
  4288. CloseHandle( (HANDLE)stream->callbackInfo.thread );
  4289. }
  4290. DeleteCriticalSection(&stream->mutex);
  4291. if (stream->handle[0].object) {
  4292. LPDIRECTSOUND object = (LPDIRECTSOUND) stream->handle[0].object;
  4293. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  4294. if (buffer) {
  4295. buffer->Stop();
  4296. buffer->Release();
  4297. }
  4298. object->Release();
  4299. }
  4300. if (stream->handle[1].object) {
  4301. LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) stream->handle[1].object;
  4302. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  4303. if (buffer) {
  4304. buffer->Stop();
  4305. buffer->Release();
  4306. }
  4307. object->Release();
  4308. }
  4309. if (stream->userBuffer)
  4310. free(stream->userBuffer);
  4311. if (stream->deviceBuffer)
  4312. free(stream->deviceBuffer);
  4313. free(stream);
  4314. streams.erase(streamId);
  4315. }
  4316. void RtAudio :: startStream(int streamId)
  4317. {
  4318. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  4319. MUTEX_LOCK(&stream->mutex);
  4320. if (stream->state == STREAM_RUNNING)
  4321. goto unlock;
  4322. HRESULT result;
  4323. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  4324. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  4325. result = buffer->Play(0, 0, DSBPLAY_LOOPING );
  4326. if ( FAILED(result) ) {
  4327. sprintf(message, "RtAudio: Unable to start DS buffer (%s): %s.",
  4328. devices[stream->device[0]].name, getErrorString(result));
  4329. error(RtError::DRIVER_ERROR);
  4330. }
  4331. }
  4332. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  4333. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  4334. result = buffer->Start(DSCBSTART_LOOPING );
  4335. if ( FAILED(result) ) {
  4336. sprintf(message, "RtAudio: Unable to start DS capture buffer (%s): %s.",
  4337. devices[stream->device[1]].name, getErrorString(result));
  4338. error(RtError::DRIVER_ERROR);
  4339. }
  4340. }
  4341. stream->state = STREAM_RUNNING;
  4342. unlock:
  4343. MUTEX_UNLOCK(&stream->mutex);
  4344. }
  4345. void RtAudio :: stopStream(int streamId)
  4346. {
  4347. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  4348. MUTEX_LOCK(&stream->mutex);
  4349. if (stream->state == STREAM_STOPPED) {
  4350. MUTEX_UNLOCK(&stream->mutex);
  4351. return;
  4352. }
  4353. // There is no specific DirectSound API call to "drain" a buffer
  4354. // before stopping. We can hack this for playback by writing zeroes
  4355. // for another bufferSize * nBuffers frames. For capture, the
  4356. // concept is less clear so we'll repeat what we do in the
  4357. // abortStream() case.
  4358. HRESULT result;
  4359. DWORD dsBufferSize;
  4360. LPVOID buffer1 = NULL;
  4361. LPVOID buffer2 = NULL;
  4362. DWORD bufferSize1 = 0;
  4363. DWORD bufferSize2 = 0;
  4364. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  4365. DWORD currentPos, safePos;
  4366. long buffer_bytes = stream->bufferSize * stream->nDeviceChannels[0];
  4367. buffer_bytes *= formatBytes(stream->deviceFormat[0]);
  4368. LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  4369. UINT nextWritePos = stream->handle[0].bufferPointer;
  4370. dsBufferSize = buffer_bytes * stream->nBuffers;
  4371. // Write zeroes for nBuffer counts.
  4372. for (int i=0; i<stream->nBuffers; i++) {
  4373. // Find out where the read and "safe write" pointers are.
  4374. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  4375. if ( FAILED(result) ) {
  4376. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  4377. devices[stream->device[0]].name, getErrorString(result));
  4378. error(RtError::DRIVER_ERROR);
  4379. }
  4380. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  4381. DWORD endWrite = nextWritePos + buffer_bytes;
  4382. // Check whether the entire write region is behind the play pointer.
  4383. while ( currentPos < endWrite ) {
  4384. float millis = (endWrite - currentPos) * 900.0;
  4385. millis /= ( formatBytes(stream->deviceFormat[0]) * stream->sampleRate);
  4386. if ( millis < 1.0 ) millis = 1.0;
  4387. Sleep( (DWORD) millis );
  4388. // Wake up, find out where we are now
  4389. result = dsBuffer->GetCurrentPosition( &currentPos, &safePos );
  4390. if ( FAILED(result) ) {
  4391. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  4392. devices[stream->device[0]].name, getErrorString(result));
  4393. error(RtError::DRIVER_ERROR);
  4394. }
  4395. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  4396. }
  4397. // Lock free space in the buffer
  4398. result = dsBuffer->Lock (nextWritePos, buffer_bytes, &buffer1,
  4399. &bufferSize1, &buffer2, &bufferSize2, 0);
  4400. if ( FAILED(result) ) {
  4401. sprintf(message, "RtAudio: Unable to lock DS buffer during playback (%s): %s.",
  4402. devices[stream->device[0]].name, getErrorString(result));
  4403. error(RtError::DRIVER_ERROR);
  4404. }
  4405. // Zero the free space
  4406. ZeroMemory(buffer1, bufferSize1);
  4407. if (buffer2 != NULL) ZeroMemory(buffer2, bufferSize2);
  4408. // Update our buffer offset and unlock sound buffer
  4409. dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2);
  4410. if ( FAILED(result) ) {
  4411. sprintf(message, "RtAudio: Unable to unlock DS buffer during playback (%s): %s.",
  4412. devices[stream->device[0]].name, getErrorString(result));
  4413. error(RtError::DRIVER_ERROR);
  4414. }
  4415. nextWritePos = (nextWritePos + bufferSize1 + bufferSize2) % dsBufferSize;
  4416. stream->handle[0].bufferPointer = nextWritePos;
  4417. }
  4418. // If we play again, start at the beginning of the buffer.
  4419. stream->handle[0].bufferPointer = 0;
  4420. }
  4421. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  4422. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  4423. buffer1 = NULL;
  4424. bufferSize1 = 0;
  4425. result = buffer->Stop();
  4426. if ( FAILED(result) ) {
  4427. sprintf(message, "RtAudio: Unable to stop DS capture buffer (%s): %s",
  4428. devices[stream->device[1]].name, getErrorString(result));
  4429. error(RtError::DRIVER_ERROR);
  4430. }
  4431. dsBufferSize = stream->bufferSize * stream->nDeviceChannels[1];
  4432. dsBufferSize *= formatBytes(stream->deviceFormat[1]) * stream->nBuffers;
  4433. // Lock the buffer and clear it so that if we start to play again,
  4434. // we won't have old data playing.
  4435. result = buffer->Lock(0, dsBufferSize, &buffer1, &bufferSize1, NULL, NULL, 0);
  4436. if ( FAILED(result) ) {
  4437. sprintf(message, "RtAudio: Unable to lock DS capture buffer (%s): %s.",
  4438. devices[stream->device[1]].name, getErrorString(result));
  4439. error(RtError::DRIVER_ERROR);
  4440. }
  4441. // Zero the DS buffer
  4442. ZeroMemory(buffer1, bufferSize1);
  4443. // Unlock the DS buffer
  4444. result = buffer->Unlock(buffer1, bufferSize1, NULL, 0);
  4445. if ( FAILED(result) ) {
  4446. sprintf(message, "RtAudio: Unable to unlock DS capture buffer (%s): %s.",
  4447. devices[stream->device[1]].name, getErrorString(result));
  4448. error(RtError::DRIVER_ERROR);
  4449. }
  4450. // If we start recording again, we must begin at beginning of buffer.
  4451. stream->handle[1].bufferPointer = 0;
  4452. }
  4453. stream->state = STREAM_STOPPED;
  4454. MUTEX_UNLOCK(&stream->mutex);
  4455. }
  4456. void RtAudio :: abortStream(int streamId)
  4457. {
  4458. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  4459. MUTEX_LOCK(&stream->mutex);
  4460. if (stream->state == STREAM_STOPPED)
  4461. goto unlock;
  4462. HRESULT result;
  4463. long dsBufferSize;
  4464. LPVOID audioPtr;
  4465. DWORD dataLen;
  4466. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  4467. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  4468. result = buffer->Stop();
  4469. if ( FAILED(result) ) {
  4470. sprintf(message, "RtAudio: Unable to stop DS buffer (%s): %s",
  4471. devices[stream->device[0]].name, getErrorString(result));
  4472. error(RtError::DRIVER_ERROR);
  4473. }
  4474. dsBufferSize = stream->bufferSize * stream->nDeviceChannels[0];
  4475. dsBufferSize *= formatBytes(stream->deviceFormat[0]) * stream->nBuffers;
  4476. // Lock the buffer and clear it so that if we start to play again,
  4477. // we won't have old data playing.
  4478. result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0);
  4479. if ( FAILED(result) ) {
  4480. sprintf(message, "RtAudio: Unable to lock DS buffer (%s): %s.",
  4481. devices[stream->device[0]].name, getErrorString(result));
  4482. error(RtError::DRIVER_ERROR);
  4483. }
  4484. // Zero the DS buffer
  4485. ZeroMemory(audioPtr, dataLen);
  4486. // Unlock the DS buffer
  4487. result = buffer->Unlock(audioPtr, dataLen, NULL, 0);
  4488. if ( FAILED(result) ) {
  4489. sprintf(message, "RtAudio: Unable to unlock DS buffer (%s): %s.",
  4490. devices[stream->device[0]].name, getErrorString(result));
  4491. error(RtError::DRIVER_ERROR);
  4492. }
  4493. // If we start playing again, we must begin at beginning of buffer.
  4494. stream->handle[0].bufferPointer = 0;
  4495. }
  4496. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  4497. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  4498. audioPtr = NULL;
  4499. dataLen = 0;
  4500. result = buffer->Stop();
  4501. if ( FAILED(result) ) {
  4502. sprintf(message, "RtAudio: Unable to stop DS capture buffer (%s): %s",
  4503. devices[stream->device[1]].name, getErrorString(result));
  4504. error(RtError::DRIVER_ERROR);
  4505. }
  4506. dsBufferSize = stream->bufferSize * stream->nDeviceChannels[1];
  4507. dsBufferSize *= formatBytes(stream->deviceFormat[1]) * stream->nBuffers;
  4508. // Lock the buffer and clear it so that if we start to play again,
  4509. // we won't have old data playing.
  4510. result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0);
  4511. if ( FAILED(result) ) {
  4512. sprintf(message, "RtAudio: Unable to lock DS capture buffer (%s): %s.",
  4513. devices[stream->device[1]].name, getErrorString(result));
  4514. error(RtError::DRIVER_ERROR);
  4515. }
  4516. // Zero the DS buffer
  4517. ZeroMemory(audioPtr, dataLen);
  4518. // Unlock the DS buffer
  4519. result = buffer->Unlock(audioPtr, dataLen, NULL, 0);
  4520. if ( FAILED(result) ) {
  4521. sprintf(message, "RtAudio: Unable to unlock DS capture buffer (%s): %s.",
  4522. devices[stream->device[1]].name, getErrorString(result));
  4523. error(RtError::DRIVER_ERROR);
  4524. }
  4525. // If we start recording again, we must begin at beginning of buffer.
  4526. stream->handle[1].bufferPointer = 0;
  4527. }
  4528. stream->state = STREAM_STOPPED;
  4529. unlock:
  4530. MUTEX_UNLOCK(&stream->mutex);
  4531. }
  4532. int RtAudio :: streamWillBlock(int streamId)
  4533. {
  4534. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  4535. MUTEX_LOCK(&stream->mutex);
  4536. int channels;
  4537. int frames = 0;
  4538. if (stream->state == STREAM_STOPPED)
  4539. goto unlock;
  4540. HRESULT result;
  4541. DWORD currentPos, safePos;
  4542. channels = 1;
  4543. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  4544. LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  4545. UINT nextWritePos = stream->handle[0].bufferPointer;
  4546. channels = stream->nDeviceChannels[0];
  4547. DWORD dsBufferSize = stream->bufferSize * channels;
  4548. dsBufferSize *= formatBytes(stream->deviceFormat[0]) * stream->nBuffers;
  4549. // Find out where the read and "safe write" pointers are.
  4550. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  4551. if ( FAILED(result) ) {
  4552. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  4553. devices[stream->device[0]].name, getErrorString(result));
  4554. error(RtError::DRIVER_ERROR);
  4555. }
  4556. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  4557. frames = currentPos - nextWritePos;
  4558. frames /= channels * formatBytes(stream->deviceFormat[0]);
  4559. }
  4560. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  4561. LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  4562. UINT nextReadPos = stream->handle[1].bufferPointer;
  4563. channels = stream->nDeviceChannels[1];
  4564. DWORD dsBufferSize = stream->bufferSize * channels;
  4565. dsBufferSize *= formatBytes(stream->deviceFormat[1]) * stream->nBuffers;
  4566. // Find out where the write and "safe read" pointers are.
  4567. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  4568. if ( FAILED(result) ) {
  4569. sprintf(message, "RtAudio: Unable to get current DS capture position (%s): %s.",
  4570. devices[stream->device[1]].name, getErrorString(result));
  4571. error(RtError::DRIVER_ERROR);
  4572. }
  4573. if ( safePos < nextReadPos ) safePos += dsBufferSize; // unwrap offset
  4574. if (stream->mode == DUPLEX ) {
  4575. // Take largest value of the two.
  4576. int temp = safePos - nextReadPos;
  4577. temp /= channels * formatBytes(stream->deviceFormat[1]);
  4578. frames = ( temp > frames ) ? temp : frames;
  4579. }
  4580. else {
  4581. frames = safePos - nextReadPos;
  4582. frames /= channels * formatBytes(stream->deviceFormat[1]);
  4583. }
  4584. }
  4585. frames = stream->bufferSize - frames;
  4586. if (frames < 0) frames = 0;
  4587. unlock:
  4588. MUTEX_UNLOCK(&stream->mutex);
  4589. return frames;
  4590. }
  4591. void RtAudio :: tickStream(int streamId)
  4592. {
  4593. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  4594. int stopStream = 0;
  4595. if (stream->state == STREAM_STOPPED) {
  4596. if (stream->callbackInfo.usingCallback) Sleep(50); // sleep 50 milliseconds
  4597. return;
  4598. }
  4599. else if (stream->callbackInfo.usingCallback) {
  4600. RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) stream->callbackInfo.callback;
  4601. stopStream = callback(stream->userBuffer, stream->bufferSize, stream->callbackInfo.userData);
  4602. }
  4603. MUTEX_LOCK(&stream->mutex);
  4604. // The state might change while waiting on a mutex.
  4605. if (stream->state == STREAM_STOPPED) {
  4606. MUTEX_UNLOCK(&stream->mutex);
  4607. return;
  4608. }
  4609. HRESULT result;
  4610. DWORD currentPos, safePos;
  4611. LPVOID buffer1 = NULL;
  4612. LPVOID buffer2 = NULL;
  4613. DWORD bufferSize1 = 0;
  4614. DWORD bufferSize2 = 0;
  4615. char *buffer;
  4616. long buffer_bytes;
  4617. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  4618. // Setup parameters and do buffer conversion if necessary.
  4619. if (stream->doConvertBuffer[0]) {
  4620. convertStreamBuffer(stream, OUTPUT);
  4621. buffer = stream->deviceBuffer;
  4622. buffer_bytes = stream->bufferSize * stream->nDeviceChannels[0];
  4623. buffer_bytes *= formatBytes(stream->deviceFormat[0]);
  4624. }
  4625. else {
  4626. buffer = stream->userBuffer;
  4627. buffer_bytes = stream->bufferSize * stream->nUserChannels[0];
  4628. buffer_bytes *= formatBytes(stream->userFormat);
  4629. }
  4630. // No byte swapping necessary in DirectSound implementation.
  4631. LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  4632. UINT nextWritePos = stream->handle[0].bufferPointer;
  4633. DWORD dsBufferSize = buffer_bytes * stream->nBuffers;
  4634. // Find out where the read and "safe write" pointers are.
  4635. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  4636. if ( FAILED(result) ) {
  4637. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  4638. devices[stream->device[0]].name, getErrorString(result));
  4639. error(RtError::DRIVER_ERROR);
  4640. }
  4641. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  4642. DWORD endWrite = nextWritePos + buffer_bytes;
  4643. // Check whether the entire write region is behind the play pointer.
  4644. while ( currentPos < endWrite ) {
  4645. // If we are here, then we must wait until the play pointer gets
  4646. // beyond the write region. The approach here is to use the
  4647. // Sleep() function to suspend operation until safePos catches
  4648. // up. Calculate number of milliseconds to wait as:
  4649. // time = distance * (milliseconds/second) * fudgefactor /
  4650. // ((bytes/sample) * (samples/second))
  4651. // A "fudgefactor" less than 1 is used because it was found
  4652. // that sleeping too long was MUCH worse than sleeping for
  4653. // several shorter periods.
  4654. float millis = (endWrite - currentPos) * 900.0;
  4655. millis /= ( formatBytes(stream->deviceFormat[0]) * stream->sampleRate);
  4656. if ( millis < 1.0 ) millis = 1.0;
  4657. Sleep( (DWORD) millis );
  4658. // Wake up, find out where we are now
  4659. result = dsBuffer->GetCurrentPosition( &currentPos, &safePos );
  4660. if ( FAILED(result) ) {
  4661. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  4662. devices[stream->device[0]].name, getErrorString(result));
  4663. error(RtError::DRIVER_ERROR);
  4664. }
  4665. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  4666. }
  4667. // Lock free space in the buffer
  4668. result = dsBuffer->Lock (nextWritePos, buffer_bytes, &buffer1,
  4669. &bufferSize1, &buffer2, &bufferSize2, 0);
  4670. if ( FAILED(result) ) {
  4671. sprintf(message, "RtAudio: Unable to lock DS buffer during playback (%s): %s.",
  4672. devices[stream->device[0]].name, getErrorString(result));
  4673. error(RtError::DRIVER_ERROR);
  4674. }
  4675. // Copy our buffer into the DS buffer
  4676. CopyMemory(buffer1, buffer, bufferSize1);
  4677. if (buffer2 != NULL) CopyMemory(buffer2, buffer+bufferSize1, bufferSize2);
  4678. // Update our buffer offset and unlock sound buffer
  4679. dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2);
  4680. if ( FAILED(result) ) {
  4681. sprintf(message, "RtAudio: Unable to unlock DS buffer during playback (%s): %s.",
  4682. devices[stream->device[0]].name, getErrorString(result));
  4683. error(RtError::DRIVER_ERROR);
  4684. }
  4685. nextWritePos = (nextWritePos + bufferSize1 + bufferSize2) % dsBufferSize;
  4686. stream->handle[0].bufferPointer = nextWritePos;
  4687. }
  4688. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  4689. // Setup parameters.
  4690. if (stream->doConvertBuffer[1]) {
  4691. buffer = stream->deviceBuffer;
  4692. buffer_bytes = stream->bufferSize * stream->nDeviceChannels[1];
  4693. buffer_bytes *= formatBytes(stream->deviceFormat[1]);
  4694. }
  4695. else {
  4696. buffer = stream->userBuffer;
  4697. buffer_bytes = stream->bufferSize * stream->nUserChannels[1];
  4698. buffer_bytes *= formatBytes(stream->userFormat);
  4699. }
  4700. LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  4701. UINT nextReadPos = stream->handle[1].bufferPointer;
  4702. DWORD dsBufferSize = buffer_bytes * stream->nBuffers;
  4703. // Find out where the write and "safe read" pointers are.
  4704. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  4705. if ( FAILED(result) ) {
  4706. sprintf(message, "RtAudio: Unable to get current DS capture position (%s): %s.",
  4707. devices[stream->device[1]].name, getErrorString(result));
  4708. error(RtError::DRIVER_ERROR);
  4709. }
  4710. if ( safePos < nextReadPos ) safePos += dsBufferSize; // unwrap offset
  4711. DWORD endRead = nextReadPos + buffer_bytes;
  4712. // Check whether the entire write region is behind the play pointer.
  4713. while ( safePos < endRead ) {
  4714. // See comments for playback.
  4715. float millis = (endRead - safePos) * 900.0;
  4716. millis /= ( formatBytes(stream->deviceFormat[1]) * stream->sampleRate);
  4717. if ( millis < 1.0 ) millis = 1.0;
  4718. Sleep( (DWORD) millis );
  4719. // Wake up, find out where we are now
  4720. result = dsBuffer->GetCurrentPosition( &currentPos, &safePos );
  4721. if ( FAILED(result) ) {
  4722. sprintf(message, "RtAudio: Unable to get current DS capture position (%s): %s.",
  4723. devices[stream->device[1]].name, getErrorString(result));
  4724. error(RtError::DRIVER_ERROR);
  4725. }
  4726. if ( safePos < nextReadPos ) safePos += dsBufferSize; // unwrap offset
  4727. }
  4728. // Lock free space in the buffer
  4729. result = dsBuffer->Lock (nextReadPos, buffer_bytes, &buffer1,
  4730. &bufferSize1, &buffer2, &bufferSize2, 0);
  4731. if ( FAILED(result) ) {
  4732. sprintf(message, "RtAudio: Unable to lock DS buffer during capture (%s): %s.",
  4733. devices[stream->device[1]].name, getErrorString(result));
  4734. error(RtError::DRIVER_ERROR);
  4735. }
  4736. // Copy our buffer into the DS buffer
  4737. CopyMemory(buffer, buffer1, bufferSize1);
  4738. if (buffer2 != NULL) CopyMemory(buffer+bufferSize1, buffer2, bufferSize2);
  4739. // Update our buffer offset and unlock sound buffer
  4740. nextReadPos = (nextReadPos + bufferSize1 + bufferSize2) % dsBufferSize;
  4741. dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2);
  4742. if ( FAILED(result) ) {
  4743. sprintf(message, "RtAudio: Unable to unlock DS buffer during capture (%s): %s.",
  4744. devices[stream->device[1]].name, getErrorString(result));
  4745. error(RtError::DRIVER_ERROR);
  4746. }
  4747. stream->handle[1].bufferPointer = nextReadPos;
  4748. // No byte swapping necessary in DirectSound implementation.
  4749. // Do buffer conversion if necessary.
  4750. if (stream->doConvertBuffer[1])
  4751. convertStreamBuffer(stream, INPUT);
  4752. }
  4753. MUTEX_UNLOCK(&stream->mutex);
  4754. if (stream->callbackInfo.usingCallback && stopStream)
  4755. this->stopStream(streamId);
  4756. }
  4757. // Definitions for utility functions and callbacks
  4758. // specific to the DirectSound implementation.
  4759. extern "C" unsigned __stdcall callbackHandler(void *ptr)
  4760. {
  4761. CALLBACK_INFO *info = (CALLBACK_INFO *) ptr;
  4762. RtAudio *object = (RtAudio *) info->object;
  4763. int stream = info->streamId;
  4764. bool *usingCallback = &info->usingCallback;
  4765. while ( *usingCallback ) {
  4766. try {
  4767. object->tickStream(stream);
  4768. }
  4769. catch (RtError &exception) {
  4770. fprintf(stderr, "\nRtAudio: Callback thread error (%s) ... closing thread.\n\n",
  4771. exception.getMessage());
  4772. break;
  4773. }
  4774. }
  4775. _endthreadex( 0 );
  4776. return 0;
  4777. }
  4778. void RtAudio :: setStreamCallback(int streamId, RTAUDIO_CALLBACK callback, void *userData)
  4779. {
  4780. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  4781. CALLBACK_INFO *info = (CALLBACK_INFO *) &stream->callbackInfo;
  4782. if ( info->usingCallback ) {
  4783. sprintf(message, "RtAudio: A callback is already set for this stream!");
  4784. error(RtError::WARNING);
  4785. return;
  4786. }
  4787. info->callback = (void *) callback;
  4788. info->userData = userData;
  4789. info->usingCallback = true;
  4790. info->object = (void *) this;
  4791. info->streamId = streamId;
  4792. unsigned thread_id;
  4793. info->thread = _beginthreadex(NULL, 0, &callbackHandler,
  4794. &stream->callbackInfo, 0, &thread_id);
  4795. if (info->thread == 0) {
  4796. info->usingCallback = false;
  4797. sprintf(message, "RtAudio: error starting callback thread!");
  4798. error(RtError::THREAD_ERROR);
  4799. }
  4800. // When spawning multiple threads in quick succession, it appears to be
  4801. // necessary to wait a bit for each to initialize ... another windoism!
  4802. Sleep(1);
  4803. }
  4804. static bool CALLBACK deviceCountCallback(LPGUID lpguid,
  4805. LPCSTR lpcstrDescription,
  4806. LPCSTR lpcstrModule,
  4807. LPVOID lpContext)
  4808. {
  4809. int *pointer = ((int *) lpContext);
  4810. (*pointer)++;
  4811. return true;
  4812. }
  4813. static bool CALLBACK deviceInfoCallback(LPGUID lpguid,
  4814. LPCSTR lpcstrDescription,
  4815. LPCSTR lpcstrModule,
  4816. LPVOID lpContext)
  4817. {
  4818. enum_info *info = ((enum_info *) lpContext);
  4819. while (strlen(info->name) > 0) info++;
  4820. strncpy(info->name, lpcstrDescription, 64);
  4821. info->id = lpguid;
  4822. HRESULT hr;
  4823. info->isValid = false;
  4824. if (info->isInput == true) {
  4825. DSCCAPS caps;
  4826. LPDIRECTSOUNDCAPTURE object;
  4827. hr = DirectSoundCaptureCreate( lpguid, &object, NULL );
  4828. if( hr != DS_OK ) return true;
  4829. caps.dwSize = sizeof(caps);
  4830. hr = object->GetCaps( &caps );
  4831. if( hr == DS_OK ) {
  4832. if (caps.dwChannels > 0 && caps.dwFormats > 0)
  4833. info->isValid = true;
  4834. }
  4835. object->Release();
  4836. }
  4837. else {
  4838. DSCAPS caps;
  4839. LPDIRECTSOUND object;
  4840. hr = DirectSoundCreate( lpguid, &object, NULL );
  4841. if( hr != DS_OK ) return true;
  4842. caps.dwSize = sizeof(caps);
  4843. hr = object->GetCaps( &caps );
  4844. if( hr == DS_OK ) {
  4845. if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO )
  4846. info->isValid = true;
  4847. }
  4848. object->Release();
  4849. }
  4850. return true;
  4851. }
  4852. static bool CALLBACK defaultDeviceCallback(LPGUID lpguid,
  4853. LPCSTR lpcstrDescription,
  4854. LPCSTR lpcstrModule,
  4855. LPVOID lpContext)
  4856. {
  4857. enum_info *info = ((enum_info *) lpContext);
  4858. if ( lpguid == NULL ) {
  4859. strncpy(info->name, lpcstrDescription, 64);
  4860. return false;
  4861. }
  4862. return true;
  4863. }
  4864. static bool CALLBACK deviceIdCallback(LPGUID lpguid,
  4865. LPCSTR lpcstrDescription,
  4866. LPCSTR lpcstrModule,
  4867. LPVOID lpContext)
  4868. {
  4869. enum_info *info = ((enum_info *) lpContext);
  4870. if ( strncmp( info->name, lpcstrDescription, 64 ) == 0 ) {
  4871. info->id = lpguid;
  4872. info->isValid = true;
  4873. return false;
  4874. }
  4875. return true;
  4876. }
  4877. static char* getErrorString(int code)
  4878. {
  4879. switch (code) {
  4880. case DSERR_ALLOCATED:
  4881. return "Direct Sound already allocated";
  4882. case DSERR_CONTROLUNAVAIL:
  4883. return "Direct Sound control unavailable";
  4884. case DSERR_INVALIDPARAM:
  4885. return "Direct Sound invalid parameter";
  4886. case DSERR_INVALIDCALL:
  4887. return "Direct Sound invalid call";
  4888. case DSERR_GENERIC:
  4889. return "Direct Sound generic error";
  4890. case DSERR_PRIOLEVELNEEDED:
  4891. return "Direct Sound Priority level needed";
  4892. case DSERR_OUTOFMEMORY:
  4893. return "Direct Sound out of memory";
  4894. case DSERR_BADFORMAT:
  4895. return "Direct Sound bad format";
  4896. case DSERR_UNSUPPORTED:
  4897. return "Direct Sound unsupported error";
  4898. case DSERR_NODRIVER:
  4899. return "Direct Sound no driver error";
  4900. case DSERR_ALREADYINITIALIZED:
  4901. return "Direct Sound already initialized";
  4902. case DSERR_NOAGGREGATION:
  4903. return "Direct Sound no aggregation";
  4904. case DSERR_BUFFERLOST:
  4905. return "Direct Sound buffer lost";
  4906. case DSERR_OTHERAPPHASPRIO:
  4907. return "Direct Sound other app has priority";
  4908. case DSERR_UNINITIALIZED:
  4909. return "Direct Sound uninitialized";
  4910. default:
  4911. return "Direct Sound unknown error";
  4912. }
  4913. }
  4914. //******************** End of __WINDOWS_DS__ *********************//
  4915. #elif defined(__IRIX_AL__) // SGI's AL API for IRIX
  4916. #include <unistd.h>
  4917. #include <errno.h>
  4918. void RtAudio :: initialize(void)
  4919. {
  4920. // Count cards and devices
  4921. nDevices = 0;
  4922. // Determine the total number of input and output devices.
  4923. nDevices = alQueryValues(AL_SYSTEM, AL_DEVICES, 0, 0, 0, 0);
  4924. if (nDevices < 0) {
  4925. sprintf(message, "RtAudio: AL error counting devices: %s.",
  4926. alGetErrorString(oserror()));
  4927. error(RtError::DRIVER_ERROR);
  4928. }
  4929. if (nDevices <= 0) return;
  4930. ALvalue *vls = (ALvalue *) new ALvalue[nDevices];
  4931. // Allocate the RTAUDIO_DEVICE structures.
  4932. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  4933. if (devices == NULL) {
  4934. sprintf(message, "RtAudio: memory allocation error!");
  4935. error(RtError::MEMORY_ERROR);
  4936. }
  4937. // Write device ascii identifiers and resource ids to device info
  4938. // structure.
  4939. char name[32];
  4940. int outs, ins, i;
  4941. ALpv pvs[1];
  4942. pvs[0].param = AL_NAME;
  4943. pvs[0].value.ptr = name;
  4944. pvs[0].sizeIn = 32;
  4945. outs = alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, vls, nDevices, 0, 0);
  4946. if (outs < 0) {
  4947. sprintf(message, "RtAudio: AL error getting output devices: %s.",
  4948. alGetErrorString(oserror()));
  4949. error(RtError::DRIVER_ERROR);
  4950. }
  4951. for (i=0; i<outs; i++) {
  4952. if (alGetParams(vls[i].i, pvs, 1) < 0) {
  4953. sprintf(message, "RtAudio: AL error querying output devices: %s.",
  4954. alGetErrorString(oserror()));
  4955. error(RtError::DRIVER_ERROR);
  4956. }
  4957. strncpy(devices[i].name, name, 32);
  4958. devices[i].id[0] = vls[i].i;
  4959. }
  4960. ins = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, &vls[outs], nDevices-outs, 0, 0);
  4961. if (ins < 0) {
  4962. sprintf(message, "RtAudio: AL error getting input devices: %s.",
  4963. alGetErrorString(oserror()));
  4964. error(RtError::DRIVER_ERROR);
  4965. }
  4966. for (i=outs; i<ins+outs; i++) {
  4967. if (alGetParams(vls[i].i, pvs, 1) < 0) {
  4968. sprintf(message, "RtAudio: AL error querying input devices: %s.",
  4969. alGetErrorString(oserror()));
  4970. error(RtError::DRIVER_ERROR);
  4971. }
  4972. strncpy(devices[i].name, name, 32);
  4973. devices[i].id[1] = vls[i].i;
  4974. }
  4975. delete [] vls;
  4976. return;
  4977. }
  4978. int RtAudio :: getDefaultInputDevice(void)
  4979. {
  4980. ALvalue value;
  4981. int result = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, &value, 1, 0, 0);
  4982. if (result < 0) {
  4983. sprintf(message, "RtAudio: AL error getting default input device id: %s.",
  4984. alGetErrorString(oserror()));
  4985. error(RtError::WARNING);
  4986. }
  4987. else {
  4988. for ( int i=0; i<nDevices; i++ )
  4989. if ( devices[i].id[1] == value.i ) return i;
  4990. }
  4991. return 0;
  4992. }
  4993. int RtAudio :: getDefaultOutputDevice(void)
  4994. {
  4995. ALvalue value;
  4996. int result = alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, &value, 1, 0, 0);
  4997. if (result < 0) {
  4998. sprintf(message, "RtAudio: AL error getting default output device id: %s.",
  4999. alGetErrorString(oserror()));
  5000. error(RtError::WARNING);
  5001. }
  5002. else {
  5003. for ( int i=0; i<nDevices; i++ )
  5004. if ( devices[i].id[0] == value.i ) return i;
  5005. }
  5006. return 0;
  5007. }
  5008. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  5009. {
  5010. int resource, result, i;
  5011. ALvalue value;
  5012. ALparamInfo pinfo;
  5013. // Get output resource ID if it exists.
  5014. resource = info->id[0];
  5015. if (resource > 0) {
  5016. // Probe output device parameters.
  5017. result = alQueryValues(resource, AL_CHANNELS, &value, 1, 0, 0);
  5018. if (result < 0) {
  5019. sprintf(message, "RtAudio: AL error getting device (%s) channels: %s.",
  5020. info->name, alGetErrorString(oserror()));
  5021. error(RtError::WARNING);
  5022. }
  5023. else {
  5024. info->maxOutputChannels = value.i;
  5025. info->minOutputChannels = 1;
  5026. }
  5027. result = alGetParamInfo(resource, AL_RATE, &pinfo);
  5028. if (result < 0) {
  5029. sprintf(message, "RtAudio: AL error getting device (%s) rates: %s.",
  5030. info->name, alGetErrorString(oserror()));
  5031. error(RtError::WARNING);
  5032. }
  5033. else {
  5034. info->nSampleRates = 0;
  5035. for (i=0; i<MAX_SAMPLE_RATES; i++) {
  5036. if ( SAMPLE_RATES[i] >= pinfo.min.i && SAMPLE_RATES[i] <= pinfo.max.i ) {
  5037. info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
  5038. info->nSampleRates++;
  5039. }
  5040. }
  5041. }
  5042. // The AL library supports all our formats, except 24-bit and 32-bit ints.
  5043. info->nativeFormats = (RTAUDIO_FORMAT) 51;
  5044. }
  5045. // Now get input resource ID if it exists.
  5046. resource = info->id[1];
  5047. if (resource > 0) {
  5048. // Probe input device parameters.
  5049. result = alQueryValues(resource, AL_CHANNELS, &value, 1, 0, 0);
  5050. if (result < 0) {
  5051. sprintf(message, "RtAudio: AL error getting device (%s) channels: %s.",
  5052. info->name, alGetErrorString(oserror()));
  5053. error(RtError::WARNING);
  5054. }
  5055. else {
  5056. info->maxInputChannels = value.i;
  5057. info->minInputChannels = 1;
  5058. }
  5059. result = alGetParamInfo(resource, AL_RATE, &pinfo);
  5060. if (result < 0) {
  5061. sprintf(message, "RtAudio: AL error getting device (%s) rates: %s.",
  5062. info->name, alGetErrorString(oserror()));
  5063. error(RtError::WARNING);
  5064. }
  5065. else {
  5066. // In the case of the default device, these values will
  5067. // overwrite the rates determined for the output device. Since
  5068. // the input device is most likely to be more limited than the
  5069. // output device, this is ok.
  5070. info->nSampleRates = 0;
  5071. for (i=0; i<MAX_SAMPLE_RATES; i++) {
  5072. if ( SAMPLE_RATES[i] >= pinfo.min.i && SAMPLE_RATES[i] <= pinfo.max.i ) {
  5073. info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
  5074. info->nSampleRates++;
  5075. }
  5076. }
  5077. }
  5078. // The AL library supports all our formats, except 24-bit and 32-bit ints.
  5079. info->nativeFormats = (RTAUDIO_FORMAT) 51;
  5080. }
  5081. if ( info->maxInputChannels == 0 && info->maxOutputChannels == 0 )
  5082. return;
  5083. if ( info->nSampleRates == 0 )
  5084. return;
  5085. // Determine duplex status.
  5086. if (info->maxInputChannels < info->maxOutputChannels)
  5087. info->maxDuplexChannels = info->maxInputChannels;
  5088. else
  5089. info->maxDuplexChannels = info->maxOutputChannels;
  5090. if (info->minInputChannels < info->minOutputChannels)
  5091. info->minDuplexChannels = info->minInputChannels;
  5092. else
  5093. info->minDuplexChannels = info->minOutputChannels;
  5094. if ( info->maxDuplexChannels > 0 ) info->hasDuplexSupport = true;
  5095. else info->hasDuplexSupport = false;
  5096. info->probed = true;
  5097. return;
  5098. }
  5099. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  5100. STREAM_MODE mode, int channels,
  5101. int sampleRate, RTAUDIO_FORMAT format,
  5102. int *bufferSize, int numberOfBuffers)
  5103. {
  5104. int result, resource, nBuffers;
  5105. ALconfig al_config;
  5106. ALport port;
  5107. ALpv pvs[2];
  5108. // Get a new ALconfig structure.
  5109. al_config = alNewConfig();
  5110. if ( !al_config ) {
  5111. sprintf(message,"RtAudio: can't get AL config: %s.",
  5112. alGetErrorString(oserror()));
  5113. error(RtError::WARNING);
  5114. return FAILURE;
  5115. }
  5116. // Set the channels.
  5117. result = alSetChannels(al_config, channels);
  5118. if ( result < 0 ) {
  5119. sprintf(message,"RtAudio: can't set %d channels in AL config: %s.",
  5120. channels, alGetErrorString(oserror()));
  5121. error(RtError::WARNING);
  5122. return FAILURE;
  5123. }
  5124. // Attempt to set the queue size. The al API doesn't provide a
  5125. // means for querying the minimum/maximum buffer size of a device,
  5126. // so if the specified size doesn't work, take whatever the
  5127. // al_config structure returns.
  5128. if ( numberOfBuffers < 1 )
  5129. nBuffers = 1;
  5130. else
  5131. nBuffers = numberOfBuffers;
  5132. long buffer_size = *bufferSize * nBuffers;
  5133. result = alSetQueueSize(al_config, buffer_size); // in sample frames
  5134. if ( result < 0 ) {
  5135. // Get the buffer size specified by the al_config and try that.
  5136. buffer_size = alGetQueueSize(al_config);
  5137. result = alSetQueueSize(al_config, buffer_size);
  5138. if ( result < 0 ) {
  5139. sprintf(message,"RtAudio: can't set buffer size (%ld) in AL config: %s.",
  5140. buffer_size, alGetErrorString(oserror()));
  5141. error(RtError::WARNING);
  5142. return FAILURE;
  5143. }
  5144. *bufferSize = buffer_size / nBuffers;
  5145. }
  5146. // Set the data format.
  5147. stream->userFormat = format;
  5148. stream->deviceFormat[mode] = format;
  5149. if (format == RTAUDIO_SINT8) {
  5150. result = alSetSampFmt(al_config, AL_SAMPFMT_TWOSCOMP);
  5151. result = alSetWidth(al_config, AL_SAMPLE_8);
  5152. }
  5153. else if (format == RTAUDIO_SINT16) {
  5154. result = alSetSampFmt(al_config, AL_SAMPFMT_TWOSCOMP);
  5155. result = alSetWidth(al_config, AL_SAMPLE_16);
  5156. }
  5157. else if (format == RTAUDIO_SINT24) {
  5158. // Our 24-bit format assumes the upper 3 bytes of a 4 byte word.
  5159. // The AL library uses the lower 3 bytes, so we'll need to do our
  5160. // own conversion.
  5161. result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT);
  5162. stream->deviceFormat[mode] = RTAUDIO_FLOAT32;
  5163. }
  5164. else if (format == RTAUDIO_SINT32) {
  5165. // The AL library doesn't seem to support the 32-bit integer
  5166. // format, so we'll need to do our own conversion.
  5167. result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT);
  5168. stream->deviceFormat[mode] = RTAUDIO_FLOAT32;
  5169. }
  5170. else if (format == RTAUDIO_FLOAT32)
  5171. result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT);
  5172. else if (format == RTAUDIO_FLOAT64)
  5173. result = alSetSampFmt(al_config, AL_SAMPFMT_DOUBLE);
  5174. if ( result == -1 ) {
  5175. sprintf(message,"RtAudio: AL error setting sample format in AL config: %s.",
  5176. alGetErrorString(oserror()));
  5177. error(RtError::WARNING);
  5178. return FAILURE;
  5179. }
  5180. if (mode == OUTPUT) {
  5181. // Set our device.
  5182. if (device == 0)
  5183. resource = AL_DEFAULT_OUTPUT;
  5184. else
  5185. resource = devices[device].id[0];
  5186. result = alSetDevice(al_config, resource);
  5187. if ( result == -1 ) {
  5188. sprintf(message,"RtAudio: AL error setting device (%s) in AL config: %s.",
  5189. devices[device].name, alGetErrorString(oserror()));
  5190. error(RtError::WARNING);
  5191. return FAILURE;
  5192. }
  5193. // Open the port.
  5194. port = alOpenPort("RtAudio Output Port", "w", al_config);
  5195. if( !port ) {
  5196. sprintf(message,"RtAudio: AL error opening output port: %s.",
  5197. alGetErrorString(oserror()));
  5198. error(RtError::WARNING);
  5199. return FAILURE;
  5200. }
  5201. // Set the sample rate
  5202. pvs[0].param = AL_MASTER_CLOCK;
  5203. pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE;
  5204. pvs[1].param = AL_RATE;
  5205. pvs[1].value.ll = alDoubleToFixed((double)sampleRate);
  5206. result = alSetParams(resource, pvs, 2);
  5207. if ( result < 0 ) {
  5208. alClosePort(port);
  5209. sprintf(message,"RtAudio: AL error setting sample rate (%d) for device (%s): %s.",
  5210. sampleRate, devices[device].name, alGetErrorString(oserror()));
  5211. error(RtError::WARNING);
  5212. return FAILURE;
  5213. }
  5214. }
  5215. else { // mode == INPUT
  5216. // Set our device.
  5217. if (device == 0)
  5218. resource = AL_DEFAULT_INPUT;
  5219. else
  5220. resource = devices[device].id[1];
  5221. result = alSetDevice(al_config, resource);
  5222. if ( result == -1 ) {
  5223. sprintf(message,"RtAudio: AL error setting device (%s) in AL config: %s.",
  5224. devices[device].name, alGetErrorString(oserror()));
  5225. error(RtError::WARNING);
  5226. return FAILURE;
  5227. }
  5228. // Open the port.
  5229. port = alOpenPort("RtAudio Output Port", "r", al_config);
  5230. if( !port ) {
  5231. sprintf(message,"RtAudio: AL error opening input port: %s.",
  5232. alGetErrorString(oserror()));
  5233. error(RtError::WARNING);
  5234. return FAILURE;
  5235. }
  5236. // Set the sample rate
  5237. pvs[0].param = AL_MASTER_CLOCK;
  5238. pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE;
  5239. pvs[1].param = AL_RATE;
  5240. pvs[1].value.ll = alDoubleToFixed((double)sampleRate);
  5241. result = alSetParams(resource, pvs, 2);
  5242. if ( result < 0 ) {
  5243. alClosePort(port);
  5244. sprintf(message,"RtAudio: AL error setting sample rate (%d) for device (%s): %s.",
  5245. sampleRate, devices[device].name, alGetErrorString(oserror()));
  5246. error(RtError::WARNING);
  5247. return FAILURE;
  5248. }
  5249. }
  5250. alFreeConfig(al_config);
  5251. stream->nUserChannels[mode] = channels;
  5252. stream->nDeviceChannels[mode] = channels;
  5253. // Set handle and flags for buffer conversion
  5254. stream->handle[mode] = port;
  5255. stream->doConvertBuffer[mode] = false;
  5256. if (stream->userFormat != stream->deviceFormat[mode])
  5257. stream->doConvertBuffer[mode] = true;
  5258. // Allocate necessary internal buffers
  5259. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  5260. long buffer_bytes;
  5261. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  5262. buffer_bytes = stream->nUserChannels[0];
  5263. else
  5264. buffer_bytes = stream->nUserChannels[1];
  5265. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  5266. if (stream->userBuffer) free(stream->userBuffer);
  5267. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  5268. if (stream->userBuffer == NULL)
  5269. goto memory_error;
  5270. }
  5271. if ( stream->doConvertBuffer[mode] ) {
  5272. long buffer_bytes;
  5273. bool makeBuffer = true;
  5274. if ( mode == OUTPUT )
  5275. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  5276. else { // mode == INPUT
  5277. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  5278. if ( stream->mode == OUTPUT && stream->deviceBuffer ) {
  5279. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  5280. if ( buffer_bytes < bytes_out ) makeBuffer = false;
  5281. }
  5282. }
  5283. if ( makeBuffer ) {
  5284. buffer_bytes *= *bufferSize;
  5285. if (stream->deviceBuffer) free(stream->deviceBuffer);
  5286. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  5287. if (stream->deviceBuffer == NULL)
  5288. goto memory_error;
  5289. }
  5290. }
  5291. stream->device[mode] = device;
  5292. stream->state = STREAM_STOPPED;
  5293. if ( stream->mode == OUTPUT && mode == INPUT )
  5294. // We had already set up an output stream.
  5295. stream->mode = DUPLEX;
  5296. else
  5297. stream->mode = mode;
  5298. stream->nBuffers = nBuffers;
  5299. stream->bufferSize = *bufferSize;
  5300. stream->sampleRate = sampleRate;
  5301. return SUCCESS;
  5302. memory_error:
  5303. if (stream->handle[0]) {
  5304. alClosePort(stream->handle[0]);
  5305. stream->handle[0] = 0;
  5306. }
  5307. if (stream->handle[1]) {
  5308. alClosePort(stream->handle[1]);
  5309. stream->handle[1] = 0;
  5310. }
  5311. if (stream->userBuffer) {
  5312. free(stream->userBuffer);
  5313. stream->userBuffer = 0;
  5314. }
  5315. sprintf(message, "RtAudio: ALSA error allocating buffer memory for device (%s).",
  5316. devices[device].name);
  5317. error(RtError::WARNING);
  5318. return FAILURE;
  5319. }
  5320. void RtAudio :: closeStream(int streamId)
  5321. {
  5322. // We don't want an exception to be thrown here because this
  5323. // function is called by our class destructor. So, do our own
  5324. // streamId check.
  5325. if ( streams.find( streamId ) == streams.end() ) {
  5326. sprintf(message, "RtAudio: invalid stream identifier!");
  5327. error(RtError::WARNING);
  5328. return;
  5329. }
  5330. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamId];
  5331. if (stream->callbackInfo.usingCallback) {
  5332. pthread_cancel(stream->callbackInfo.thread);
  5333. pthread_join(stream->callbackInfo.thread, NULL);
  5334. }
  5335. pthread_mutex_destroy(&stream->mutex);
  5336. if (stream->handle[0])
  5337. alClosePort(stream->handle[0]);
  5338. if (stream->handle[1])
  5339. alClosePort(stream->handle[1]);
  5340. if (stream->userBuffer)
  5341. free(stream->userBuffer);
  5342. if (stream->deviceBuffer)
  5343. free(stream->deviceBuffer);
  5344. free(stream);
  5345. streams.erase(streamId);
  5346. }
  5347. void RtAudio :: startStream(int streamId)
  5348. {
  5349. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  5350. if (stream->state == STREAM_RUNNING)
  5351. return;
  5352. // The AL port is ready as soon as it is opened.
  5353. stream->state = STREAM_RUNNING;
  5354. }
  5355. void RtAudio :: stopStream(int streamId)
  5356. {
  5357. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  5358. MUTEX_LOCK(&stream->mutex);
  5359. if (stream->state == STREAM_STOPPED)
  5360. goto unlock;
  5361. int result;
  5362. int buffer_size = stream->bufferSize * stream->nBuffers;
  5363. if (stream->mode == OUTPUT || stream->mode == DUPLEX)
  5364. alZeroFrames(stream->handle[0], buffer_size);
  5365. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  5366. result = alDiscardFrames(stream->handle[1], buffer_size);
  5367. if (result == -1) {
  5368. sprintf(message, "RtAudio: AL error draining stream device (%s): %s.",
  5369. devices[stream->device[1]].name, alGetErrorString(oserror()));
  5370. error(RtError::DRIVER_ERROR);
  5371. }
  5372. }
  5373. stream->state = STREAM_STOPPED;
  5374. unlock:
  5375. MUTEX_UNLOCK(&stream->mutex);
  5376. }
  5377. void RtAudio :: abortStream(int streamId)
  5378. {
  5379. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  5380. MUTEX_LOCK(&stream->mutex);
  5381. if (stream->state == STREAM_STOPPED)
  5382. goto unlock;
  5383. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  5384. int buffer_size = stream->bufferSize * stream->nBuffers;
  5385. int result = alDiscardFrames(stream->handle[0], buffer_size);
  5386. if (result == -1) {
  5387. sprintf(message, "RtAudio: AL error aborting stream device (%s): %s.",
  5388. devices[stream->device[0]].name, alGetErrorString(oserror()));
  5389. error(RtError::DRIVER_ERROR);
  5390. }
  5391. }
  5392. // There is no clear action to take on the input stream, since the
  5393. // port will continue to run in any event.
  5394. stream->state = STREAM_STOPPED;
  5395. unlock:
  5396. MUTEX_UNLOCK(&stream->mutex);
  5397. }
  5398. int RtAudio :: streamWillBlock(int streamId)
  5399. {
  5400. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  5401. MUTEX_LOCK(&stream->mutex);
  5402. int frames = 0;
  5403. if (stream->state == STREAM_STOPPED)
  5404. goto unlock;
  5405. int err = 0;
  5406. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  5407. err = alGetFillable(stream->handle[0]);
  5408. if (err < 0) {
  5409. sprintf(message, "RtAudio: AL error getting available frames for stream (%s): %s.",
  5410. devices[stream->device[0]].name, alGetErrorString(oserror()));
  5411. error(RtError::DRIVER_ERROR);
  5412. }
  5413. }
  5414. frames = err;
  5415. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  5416. err = alGetFilled(stream->handle[1]);
  5417. if (err < 0) {
  5418. sprintf(message, "RtAudio: AL error getting available frames for stream (%s): %s.",
  5419. devices[stream->device[1]].name, alGetErrorString(oserror()));
  5420. error(RtError::DRIVER_ERROR);
  5421. }
  5422. if (frames > err) frames = err;
  5423. }
  5424. frames = stream->bufferSize - frames;
  5425. if (frames < 0) frames = 0;
  5426. unlock:
  5427. MUTEX_UNLOCK(&stream->mutex);
  5428. return frames;
  5429. }
  5430. void RtAudio :: tickStream(int streamId)
  5431. {
  5432. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamId);
  5433. int stopStream = 0;
  5434. if (stream->state == STREAM_STOPPED) {
  5435. if (stream->callbackInfo.usingCallback) usleep(50000); // sleep 50 milliseconds
  5436. return;
  5437. }
  5438. else if (stream->callbackInfo.usingCallback) {
  5439. RTAUDIO_CALLBACK callback = (RTAUDIO_CALLBACK) stream->callbackInfo.callback;
  5440. stopStream = callback(stream->userBuffer, stream->bufferSize, stream->callbackInfo.userData);
  5441. }
  5442. MUTEX_LOCK(&stream->mutex);
  5443. // The state might change while waiting on a mutex.
  5444. if (stream->state == STREAM_STOPPED)
  5445. goto unlock;
  5446. char *buffer;
  5447. int channels;
  5448. RTAUDIO_FORMAT format;
  5449. if (stream->mode == OUTPUT || stream->mode == DUPLEX) {
  5450. // Setup parameters and do buffer conversion if necessary.
  5451. if (stream->doConvertBuffer[0]) {
  5452. convertStreamBuffer(stream, OUTPUT);
  5453. buffer = stream->deviceBuffer;
  5454. channels = stream->nDeviceChannels[0];
  5455. format = stream->deviceFormat[0];
  5456. }
  5457. else {
  5458. buffer = stream->userBuffer;
  5459. channels = stream->nUserChannels[0];
  5460. format = stream->userFormat;
  5461. }
  5462. // Do byte swapping if necessary.
  5463. if (stream->doByteSwap[0])
  5464. byteSwapBuffer(buffer, stream->bufferSize * channels, format);
  5465. // Write interleaved samples to device.
  5466. alWriteFrames(stream->handle[0], buffer, stream->bufferSize);
  5467. }
  5468. if (stream->mode == INPUT || stream->mode == DUPLEX) {
  5469. // Setup parameters.
  5470. if (stream->doConvertBuffer[1]) {
  5471. buffer = stream->deviceBuffer;
  5472. channels = stream->nDeviceChannels[1];
  5473. format = stream->deviceFormat[1];
  5474. }
  5475. else {
  5476. buffer = stream->userBuffer;
  5477. channels = stream->nUserChannels[1];
  5478. format = stream->userFormat;
  5479. }
  5480. // Read interleaved samples from device.
  5481. alReadFrames(stream->handle[1], buffer, stream->bufferSize);
  5482. // Do byte swapping if necessary.
  5483. if (stream->doByteSwap[1])
  5484. byteSwapBuffer(buffer, stream->bufferSize * channels, format);
  5485. // Do buffer conversion if necessary.
  5486. if (stream->doConvertBuffer[1])
  5487. convertStreamBuffer(stream, INPUT);
  5488. }
  5489. unlock:
  5490. MUTEX_UNLOCK(&stream->mutex);
  5491. if (stream->callbackInfo.usingCallback && stopStream)
  5492. this->stopStream(streamId);
  5493. }
  5494. extern "C" void *callbackHandler(void *ptr)
  5495. {
  5496. CALLBACK_INFO *info = (CALLBACK_INFO *) ptr;
  5497. RtAudio *object = (RtAudio *) info->object;
  5498. int stream = info->streamId;
  5499. bool *usingCallback = &info->usingCallback;
  5500. while ( *usingCallback ) {
  5501. pthread_testcancel();
  5502. try {
  5503. object->tickStream(stream);
  5504. }
  5505. catch (RtError &exception) {
  5506. fprintf(stderr, "\nRtAudio: Callback thread error (%s) ... closing thread.\n\n",
  5507. exception.getMessage());
  5508. break;
  5509. }
  5510. }
  5511. return 0;
  5512. }
  5513. //******************** End of __IRIX_AL__ *********************//
  5514. #endif
  5515. // *************************************************** //
  5516. //
  5517. // Private common (OS-independent) RtAudio methods.
  5518. //
  5519. // *************************************************** //
  5520. // This method can be modified to control the behavior of error
  5521. // message reporting and throwing.
  5522. void RtAudio :: error(RtError::TYPE type)
  5523. {
  5524. if (type == RtError::WARNING) {
  5525. fprintf(stderr, "\n%s\n\n", message);
  5526. }
  5527. else if (type == RtError::DEBUG_WARNING) {
  5528. #if defined(__RTAUDIO_DEBUG__)
  5529. fprintf(stderr, "\n%s\n\n", message);
  5530. #endif
  5531. }
  5532. else {
  5533. fprintf(stderr, "\n%s\n\n", message);
  5534. throw RtError(message, type);
  5535. }
  5536. }
  5537. void *RtAudio :: verifyStream(int streamId)
  5538. {
  5539. // Verify the stream key.
  5540. if ( streams.find( streamId ) == streams.end() ) {
  5541. sprintf(message, "RtAudio: invalid stream identifier!");
  5542. error(RtError::INVALID_STREAM);
  5543. }
  5544. return streams[streamId];
  5545. }
  5546. void RtAudio :: clearDeviceInfo(RTAUDIO_DEVICE *info)
  5547. {
  5548. // Don't clear the name or DEVICE_ID fields here ... they are
  5549. // typically set prior to a call of this function.
  5550. info->probed = false;
  5551. info->maxOutputChannels = 0;
  5552. info->maxInputChannels = 0;
  5553. info->maxDuplexChannels = 0;
  5554. info->minOutputChannels = 0;
  5555. info->minInputChannels = 0;
  5556. info->minDuplexChannels = 0;
  5557. info->hasDuplexSupport = false;
  5558. info->nSampleRates = 0;
  5559. for (int i=0; i<MAX_SAMPLE_RATES; i++)
  5560. info->sampleRates[i] = 0;
  5561. info->nativeFormats = 0;
  5562. }
  5563. int RtAudio :: formatBytes(RTAUDIO_FORMAT format)
  5564. {
  5565. if (format == RTAUDIO_SINT16)
  5566. return 2;
  5567. else if (format == RTAUDIO_SINT24 || format == RTAUDIO_SINT32 ||
  5568. format == RTAUDIO_FLOAT32)
  5569. return 4;
  5570. else if (format == RTAUDIO_FLOAT64)
  5571. return 8;
  5572. else if (format == RTAUDIO_SINT8)
  5573. return 1;
  5574. sprintf(message,"RtAudio: undefined format in formatBytes().");
  5575. error(RtError::WARNING);
  5576. return 0;
  5577. }
  5578. void RtAudio :: convertStreamBuffer(RTAUDIO_STREAM *stream, STREAM_MODE mode)
  5579. {
  5580. // This method does format conversion, input/output channel compensation, and
  5581. // data interleaving/deinterleaving. 24-bit integers are assumed to occupy
  5582. // the upper three bytes of a 32-bit integer.
  5583. int j, jump_in, jump_out, channels;
  5584. RTAUDIO_FORMAT format_in, format_out;
  5585. char *input, *output;
  5586. if (mode == INPUT) { // convert device to user buffer
  5587. input = stream->deviceBuffer;
  5588. output = stream->userBuffer;
  5589. jump_in = stream->nDeviceChannels[1];
  5590. jump_out = stream->nUserChannels[1];
  5591. format_in = stream->deviceFormat[1];
  5592. format_out = stream->userFormat;
  5593. }
  5594. else { // convert user to device buffer
  5595. input = stream->userBuffer;
  5596. output = stream->deviceBuffer;
  5597. jump_in = stream->nUserChannels[0];
  5598. jump_out = stream->nDeviceChannels[0];
  5599. format_in = stream->userFormat;
  5600. format_out = stream->deviceFormat[0];
  5601. // clear our device buffer when in/out duplex device channels are different
  5602. if ( stream->mode == DUPLEX &&
  5603. stream->nDeviceChannels[0] != stream->nDeviceChannels[1] )
  5604. memset(output, 0, stream->bufferSize * jump_out * formatBytes(format_out));
  5605. }
  5606. channels = (jump_in < jump_out) ? jump_in : jump_out;
  5607. // Set up the interleave/deinterleave offsets
  5608. std::vector<int> offset_in(channels);
  5609. std::vector<int> offset_out(channels);
  5610. if (mode == INPUT && stream->deInterleave[1]) {
  5611. for (int k=0; k<channels; k++) {
  5612. offset_in[k] = k * stream->bufferSize;
  5613. offset_out[k] = k;
  5614. jump_in = 1;
  5615. }
  5616. }
  5617. else if (mode == OUTPUT && stream->deInterleave[0]) {
  5618. for (int k=0; k<channels; k++) {
  5619. offset_in[k] = k;
  5620. offset_out[k] = k * stream->bufferSize;
  5621. jump_out = 1;
  5622. }
  5623. }
  5624. else {
  5625. for (int k=0; k<channels; k++) {
  5626. offset_in[k] = k;
  5627. offset_out[k] = k;
  5628. }
  5629. }
  5630. if (format_out == RTAUDIO_FLOAT64) {
  5631. FLOAT64 scale;
  5632. FLOAT64 *out = (FLOAT64 *)output;
  5633. if (format_in == RTAUDIO_SINT8) {
  5634. signed char *in = (signed char *)input;
  5635. scale = 1.0 / 128.0;
  5636. for (int i=0; i<stream->bufferSize; i++) {
  5637. for (j=0; j<channels; j++) {
  5638. out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
  5639. out[offset_out[j]] *= scale;
  5640. }
  5641. in += jump_in;
  5642. out += jump_out;
  5643. }
  5644. }
  5645. else if (format_in == RTAUDIO_SINT16) {
  5646. INT16 *in = (INT16 *)input;
  5647. scale = 1.0 / 32768.0;
  5648. for (int i=0; i<stream->bufferSize; i++) {
  5649. for (j=0; j<channels; j++) {
  5650. out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
  5651. out[offset_out[j]] *= scale;
  5652. }
  5653. in += jump_in;
  5654. out += jump_out;
  5655. }
  5656. }
  5657. else if (format_in == RTAUDIO_SINT24) {
  5658. INT32 *in = (INT32 *)input;
  5659. scale = 1.0 / 2147483648.0;
  5660. for (int i=0; i<stream->bufferSize; i++) {
  5661. for (j=0; j<channels; j++) {
  5662. out[offset_out[j]] = (FLOAT64) (in[offset_in[j]] & 0xffffff00);
  5663. out[offset_out[j]] *= scale;
  5664. }
  5665. in += jump_in;
  5666. out += jump_out;
  5667. }
  5668. }
  5669. else if (format_in == RTAUDIO_SINT32) {
  5670. INT32 *in = (INT32 *)input;
  5671. scale = 1.0 / 2147483648.0;
  5672. for (int i=0; i<stream->bufferSize; i++) {
  5673. for (j=0; j<channels; j++) {
  5674. out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
  5675. out[offset_out[j]] *= scale;
  5676. }
  5677. in += jump_in;
  5678. out += jump_out;
  5679. }
  5680. }
  5681. else if (format_in == RTAUDIO_FLOAT32) {
  5682. FLOAT32 *in = (FLOAT32 *)input;
  5683. for (int i=0; i<stream->bufferSize; i++) {
  5684. for (j=0; j<channels; j++) {
  5685. out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
  5686. }
  5687. in += jump_in;
  5688. out += jump_out;
  5689. }
  5690. }
  5691. else if (format_in == RTAUDIO_FLOAT64) {
  5692. // Channel compensation and/or (de)interleaving only.
  5693. FLOAT64 *in = (FLOAT64 *)input;
  5694. for (int i=0; i<stream->bufferSize; i++) {
  5695. for (j=0; j<channels; j++) {
  5696. out[offset_out[j]] = in[offset_in[j]];
  5697. }
  5698. in += jump_in;
  5699. out += jump_out;
  5700. }
  5701. }
  5702. }
  5703. else if (format_out == RTAUDIO_FLOAT32) {
  5704. FLOAT32 scale;
  5705. FLOAT32 *out = (FLOAT32 *)output;
  5706. if (format_in == RTAUDIO_SINT8) {
  5707. signed char *in = (signed char *)input;
  5708. scale = 1.0 / 128.0;
  5709. for (int i=0; i<stream->bufferSize; i++) {
  5710. for (j=0; j<channels; j++) {
  5711. out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
  5712. out[offset_out[j]] *= scale;
  5713. }
  5714. in += jump_in;
  5715. out += jump_out;
  5716. }
  5717. }
  5718. else if (format_in == RTAUDIO_SINT16) {
  5719. INT16 *in = (INT16 *)input;
  5720. scale = 1.0 / 32768.0;
  5721. for (int i=0; i<stream->bufferSize; i++) {
  5722. for (j=0; j<channels; j++) {
  5723. out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
  5724. out[offset_out[j]] *= scale;
  5725. }
  5726. in += jump_in;
  5727. out += jump_out;
  5728. }
  5729. }
  5730. else if (format_in == RTAUDIO_SINT24) {
  5731. INT32 *in = (INT32 *)input;
  5732. scale = 1.0 / 2147483648.0;
  5733. for (int i=0; i<stream->bufferSize; i++) {
  5734. for (j=0; j<channels; j++) {
  5735. out[offset_out[j]] = (FLOAT32) (in[offset_in[j]] & 0xffffff00);
  5736. out[offset_out[j]] *= scale;
  5737. }
  5738. in += jump_in;
  5739. out += jump_out;
  5740. }
  5741. }
  5742. else if (format_in == RTAUDIO_SINT32) {
  5743. INT32 *in = (INT32 *)input;
  5744. scale = 1.0 / 2147483648.0;
  5745. for (int i=0; i<stream->bufferSize; i++) {
  5746. for (j=0; j<channels; j++) {
  5747. out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
  5748. out[offset_out[j]] *= scale;
  5749. }
  5750. in += jump_in;
  5751. out += jump_out;
  5752. }
  5753. }
  5754. else if (format_in == RTAUDIO_FLOAT32) {
  5755. // Channel compensation and/or (de)interleaving only.
  5756. FLOAT32 *in = (FLOAT32 *)input;
  5757. for (int i=0; i<stream->bufferSize; i++) {
  5758. for (j=0; j<channels; j++) {
  5759. out[offset_out[j]] = in[offset_in[j]];
  5760. }
  5761. in += jump_in;
  5762. out += jump_out;
  5763. }
  5764. }
  5765. else if (format_in == RTAUDIO_FLOAT64) {
  5766. FLOAT64 *in = (FLOAT64 *)input;
  5767. for (int i=0; i<stream->bufferSize; i++) {
  5768. for (j=0; j<channels; j++) {
  5769. out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
  5770. }
  5771. in += jump_in;
  5772. out += jump_out;
  5773. }
  5774. }
  5775. }
  5776. else if (format_out == RTAUDIO_SINT32) {
  5777. INT32 *out = (INT32 *)output;
  5778. if (format_in == RTAUDIO_SINT8) {
  5779. signed char *in = (signed char *)input;
  5780. for (int i=0; i<stream->bufferSize; i++) {
  5781. for (j=0; j<channels; j++) {
  5782. out[offset_out[j]] = (INT32) in[offset_in[j]];
  5783. out[offset_out[j]] <<= 24;
  5784. }
  5785. in += jump_in;
  5786. out += jump_out;
  5787. }
  5788. }
  5789. else if (format_in == RTAUDIO_SINT16) {
  5790. INT16 *in = (INT16 *)input;
  5791. for (int i=0; i<stream->bufferSize; i++) {
  5792. for (j=0; j<channels; j++) {
  5793. out[offset_out[j]] = (INT32) in[offset_in[j]];
  5794. out[offset_out[j]] <<= 16;
  5795. }
  5796. in += jump_in;
  5797. out += jump_out;
  5798. }
  5799. }
  5800. else if (format_in == RTAUDIO_SINT24) {
  5801. INT32 *in = (INT32 *)input;
  5802. for (int i=0; i<stream->bufferSize; i++) {
  5803. for (j=0; j<channels; j++) {
  5804. out[offset_out[j]] = (INT32) in[offset_in[j]];
  5805. }
  5806. in += jump_in;
  5807. out += jump_out;
  5808. }
  5809. }
  5810. else if (format_in == RTAUDIO_SINT32) {
  5811. // Channel compensation and/or (de)interleaving only.
  5812. INT32 *in = (INT32 *)input;
  5813. for (int i=0; i<stream->bufferSize; i++) {
  5814. for (j=0; j<channels; j++) {
  5815. out[offset_out[j]] = in[offset_in[j]];
  5816. }
  5817. in += jump_in;
  5818. out += jump_out;
  5819. }
  5820. }
  5821. else if (format_in == RTAUDIO_FLOAT32) {
  5822. FLOAT32 *in = (FLOAT32 *)input;
  5823. for (int i=0; i<stream->bufferSize; i++) {
  5824. for (j=0; j<channels; j++) {
  5825. out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
  5826. }
  5827. in += jump_in;
  5828. out += jump_out;
  5829. }
  5830. }
  5831. else if (format_in == RTAUDIO_FLOAT64) {
  5832. FLOAT64 *in = (FLOAT64 *)input;
  5833. for (int i=0; i<stream->bufferSize; i++) {
  5834. for (j=0; j<channels; j++) {
  5835. out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
  5836. }
  5837. in += jump_in;
  5838. out += jump_out;
  5839. }
  5840. }
  5841. }
  5842. else if (format_out == RTAUDIO_SINT24) {
  5843. INT32 *out = (INT32 *)output;
  5844. if (format_in == RTAUDIO_SINT8) {
  5845. signed char *in = (signed char *)input;
  5846. for (int i=0; i<stream->bufferSize; i++) {
  5847. for (j=0; j<channels; j++) {
  5848. out[offset_out[j]] = (INT32) in[offset_in[j]];
  5849. out[offset_out[j]] <<= 24;
  5850. }
  5851. in += jump_in;
  5852. out += jump_out;
  5853. }
  5854. }
  5855. else if (format_in == RTAUDIO_SINT16) {
  5856. INT16 *in = (INT16 *)input;
  5857. for (int i=0; i<stream->bufferSize; i++) {
  5858. for (j=0; j<channels; j++) {
  5859. out[offset_out[j]] = (INT32) in[offset_in[j]];
  5860. out[offset_out[j]] <<= 16;
  5861. }
  5862. in += jump_in;
  5863. out += jump_out;
  5864. }
  5865. }
  5866. else if (format_in == RTAUDIO_SINT24) {
  5867. // Channel compensation and/or (de)interleaving only.
  5868. INT32 *in = (INT32 *)input;
  5869. for (int i=0; i<stream->bufferSize; i++) {
  5870. for (j=0; j<channels; j++) {
  5871. out[offset_out[j]] = in[offset_in[j]];
  5872. }
  5873. in += jump_in;
  5874. out += jump_out;
  5875. }
  5876. }
  5877. else if (format_in == RTAUDIO_SINT32) {
  5878. INT32 *in = (INT32 *)input;
  5879. for (int i=0; i<stream->bufferSize; i++) {
  5880. for (j=0; j<channels; j++) {
  5881. out[offset_out[j]] = (INT32) (in[offset_in[j]] & 0xffffff00);
  5882. }
  5883. in += jump_in;
  5884. out += jump_out;
  5885. }
  5886. }
  5887. else if (format_in == RTAUDIO_FLOAT32) {
  5888. FLOAT32 *in = (FLOAT32 *)input;
  5889. for (int i=0; i<stream->bufferSize; i++) {
  5890. for (j=0; j<channels; j++) {
  5891. out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
  5892. }
  5893. in += jump_in;
  5894. out += jump_out;
  5895. }
  5896. }
  5897. else if (format_in == RTAUDIO_FLOAT64) {
  5898. FLOAT64 *in = (FLOAT64 *)input;
  5899. for (int i=0; i<stream->bufferSize; i++) {
  5900. for (j=0; j<channels; j++) {
  5901. out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
  5902. }
  5903. in += jump_in;
  5904. out += jump_out;
  5905. }
  5906. }
  5907. }
  5908. else if (format_out == RTAUDIO_SINT16) {
  5909. INT16 *out = (INT16 *)output;
  5910. if (format_in == RTAUDIO_SINT8) {
  5911. signed char *in = (signed char *)input;
  5912. for (int i=0; i<stream->bufferSize; i++) {
  5913. for (j=0; j<channels; j++) {
  5914. out[offset_out[j]] = (INT16) in[offset_in[j]];
  5915. out[offset_out[j]] <<= 8;
  5916. }
  5917. in += jump_in;
  5918. out += jump_out;
  5919. }
  5920. }
  5921. else if (format_in == RTAUDIO_SINT16) {
  5922. // Channel compensation and/or (de)interleaving only.
  5923. INT16 *in = (INT16 *)input;
  5924. for (int i=0; i<stream->bufferSize; i++) {
  5925. for (j=0; j<channels; j++) {
  5926. out[offset_out[j]] = in[offset_in[j]];
  5927. }
  5928. in += jump_in;
  5929. out += jump_out;
  5930. }
  5931. }
  5932. else if (format_in == RTAUDIO_SINT24) {
  5933. INT32 *in = (INT32 *)input;
  5934. for (int i=0; i<stream->bufferSize; i++) {
  5935. for (j=0; j<channels; j++) {
  5936. out[offset_out[j]] = (INT16) ((in[offset_in[j]] >> 16) & 0x0000ffff);
  5937. }
  5938. in += jump_in;
  5939. out += jump_out;
  5940. }
  5941. }
  5942. else if (format_in == RTAUDIO_SINT32) {
  5943. INT32 *in = (INT32 *)input;
  5944. for (int i=0; i<stream->bufferSize; i++) {
  5945. for (j=0; j<channels; j++) {
  5946. out[offset_out[j]] = (INT16) ((in[offset_in[j]] >> 16) & 0x0000ffff);
  5947. }
  5948. in += jump_in;
  5949. out += jump_out;
  5950. }
  5951. }
  5952. else if (format_in == RTAUDIO_FLOAT32) {
  5953. FLOAT32 *in = (FLOAT32 *)input;
  5954. for (int i=0; i<stream->bufferSize; i++) {
  5955. for (j=0; j<channels; j++) {
  5956. out[offset_out[j]] = (INT16) (in[offset_in[j]] * 32767.0);
  5957. }
  5958. in += jump_in;
  5959. out += jump_out;
  5960. }
  5961. }
  5962. else if (format_in == RTAUDIO_FLOAT64) {
  5963. FLOAT64 *in = (FLOAT64 *)input;
  5964. for (int i=0; i<stream->bufferSize; i++) {
  5965. for (j=0; j<channels; j++) {
  5966. out[offset_out[j]] = (INT16) (in[offset_in[j]] * 32767.0);
  5967. }
  5968. in += jump_in;
  5969. out += jump_out;
  5970. }
  5971. }
  5972. }
  5973. else if (format_out == RTAUDIO_SINT8) {
  5974. signed char *out = (signed char *)output;
  5975. if (format_in == RTAUDIO_SINT8) {
  5976. // Channel compensation and/or (de)interleaving only.
  5977. signed char *in = (signed char *)input;
  5978. for (int i=0; i<stream->bufferSize; i++) {
  5979. for (j=0; j<channels; j++) {
  5980. out[offset_out[j]] = in[offset_in[j]];
  5981. }
  5982. in += jump_in;
  5983. out += jump_out;
  5984. }
  5985. }
  5986. if (format_in == RTAUDIO_SINT16) {
  5987. INT16 *in = (INT16 *)input;
  5988. for (int i=0; i<stream->bufferSize; i++) {
  5989. for (j=0; j<channels; j++) {
  5990. out[offset_out[j]] = (signed char) ((in[offset_in[j]] >> 8) & 0x00ff);
  5991. }
  5992. in += jump_in;
  5993. out += jump_out;
  5994. }
  5995. }
  5996. else if (format_in == RTAUDIO_SINT24) {
  5997. INT32 *in = (INT32 *)input;
  5998. for (int i=0; i<stream->bufferSize; i++) {
  5999. for (j=0; j<channels; j++) {
  6000. out[offset_out[j]] = (signed char) ((in[offset_in[j]] >> 24) & 0x000000ff);
  6001. }
  6002. in += jump_in;
  6003. out += jump_out;
  6004. }
  6005. }
  6006. else if (format_in == RTAUDIO_SINT32) {
  6007. INT32 *in = (INT32 *)input;
  6008. for (int i=0; i<stream->bufferSize; i++) {
  6009. for (j=0; j<channels; j++) {
  6010. out[offset_out[j]] = (signed char) ((in[offset_in[j]] >> 24) & 0x000000ff);
  6011. }
  6012. in += jump_in;
  6013. out += jump_out;
  6014. }
  6015. }
  6016. else if (format_in == RTAUDIO_FLOAT32) {
  6017. FLOAT32 *in = (FLOAT32 *)input;
  6018. for (int i=0; i<stream->bufferSize; i++) {
  6019. for (j=0; j<channels; j++) {
  6020. out[offset_out[j]] = (signed char) (in[offset_in[j]] * 127.0);
  6021. }
  6022. in += jump_in;
  6023. out += jump_out;
  6024. }
  6025. }
  6026. else if (format_in == RTAUDIO_FLOAT64) {
  6027. FLOAT64 *in = (FLOAT64 *)input;
  6028. for (int i=0; i<stream->bufferSize; i++) {
  6029. for (j=0; j<channels; j++) {
  6030. out[offset_out[j]] = (signed char) (in[offset_in[j]] * 127.0);
  6031. }
  6032. in += jump_in;
  6033. out += jump_out;
  6034. }
  6035. }
  6036. }
  6037. }
  6038. void RtAudio :: byteSwapBuffer(char *buffer, int samples, RTAUDIO_FORMAT format)
  6039. {
  6040. register char val;
  6041. register char *ptr;
  6042. ptr = buffer;
  6043. if (format == RTAUDIO_SINT16) {
  6044. for (int i=0; i<samples; i++) {
  6045. // Swap 1st and 2nd bytes.
  6046. val = *(ptr);
  6047. *(ptr) = *(ptr+1);
  6048. *(ptr+1) = val;
  6049. // Increment 2 bytes.
  6050. ptr += 2;
  6051. }
  6052. }
  6053. else if (format == RTAUDIO_SINT24 ||
  6054. format == RTAUDIO_SINT32 ||
  6055. format == RTAUDIO_FLOAT32) {
  6056. for (int i=0; i<samples; i++) {
  6057. // Swap 1st and 4th bytes.
  6058. val = *(ptr);
  6059. *(ptr) = *(ptr+3);
  6060. *(ptr+3) = val;
  6061. // Swap 2nd and 3rd bytes.
  6062. ptr += 1;
  6063. val = *(ptr);
  6064. *(ptr) = *(ptr+1);
  6065. *(ptr+1) = val;
  6066. // Increment 4 bytes.
  6067. ptr += 4;
  6068. }
  6069. }
  6070. else if (format == RTAUDIO_FLOAT64) {
  6071. for (int i=0; i<samples; i++) {
  6072. // Swap 1st and 8th bytes
  6073. val = *(ptr);
  6074. *(ptr) = *(ptr+7);
  6075. *(ptr+7) = val;
  6076. // Swap 2nd and 7th bytes
  6077. ptr += 1;
  6078. val = *(ptr);
  6079. *(ptr) = *(ptr+5);
  6080. *(ptr+5) = val;
  6081. // Swap 3rd and 6th bytes
  6082. ptr += 1;
  6083. val = *(ptr);
  6084. *(ptr) = *(ptr+3);
  6085. *(ptr+3) = val;
  6086. // Swap 4th and 5th bytes
  6087. ptr += 1;
  6088. val = *(ptr);
  6089. *(ptr) = *(ptr+1);
  6090. *(ptr+1) = val;
  6091. // Increment 8 bytes.
  6092. ptr += 8;
  6093. }
  6094. }
  6095. }
  6096. // *************************************************** //
  6097. //
  6098. // RtError class definition.
  6099. //
  6100. // *************************************************** //
  6101. RtError :: RtError(const char *p, TYPE tipe)
  6102. {
  6103. type = tipe;
  6104. strncpy(error_message, p, 256);
  6105. }
  6106. RtError :: ~RtError()
  6107. {
  6108. }
  6109. void RtError :: printMessage()
  6110. {
  6111. printf("\n%s\n\n", error_message);
  6112. }