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.

4998 lines
156KB

  1. /******************************************/
  2. /*
  3. RtAudio - realtime sound I/O C++ class
  4. Version 2.0 by Gary P. Scavone, 2001-2002.
  5. */
  6. /******************************************/
  7. #include "RtAudio.h"
  8. #include <vector>
  9. #include <stdio.h>
  10. // Static variable definitions.
  11. const unsigned int RtAudio :: SAMPLE_RATES[] = {
  12. 4000, 5512, 8000, 9600, 11025, 16000, 22050,
  13. 32000, 44100, 48000, 88200, 96000, 176400, 192000
  14. };
  15. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_SINT8 = 1;
  16. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_SINT16 = 2;
  17. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_SINT24 = 4;
  18. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_SINT32 = 8;
  19. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_FLOAT32 = 16;
  20. const RtAudio::RTAUDIO_FORMAT RtAudio :: RTAUDIO_FLOAT64 = 32;
  21. #if defined(__WINDOWS_DS_)
  22. #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A)
  23. #define MUTEX_LOCK(A) EnterCriticalSection(A)
  24. #define MUTEX_UNLOCK(A) LeaveCriticalSection(A)
  25. typedef unsigned THREAD_RETURN;
  26. #else // pthread API
  27. #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL)
  28. #define MUTEX_LOCK(A) pthread_mutex_lock(A)
  29. #define MUTEX_UNLOCK(A) pthread_mutex_unlock(A)
  30. typedef void * THREAD_RETURN;
  31. #endif
  32. // *************************************************** //
  33. //
  34. // Public common (OS-independent) methods.
  35. //
  36. // *************************************************** //
  37. RtAudio :: RtAudio()
  38. {
  39. initialize();
  40. if (nDevices <= 0) {
  41. sprintf(message, "RtAudio: no audio devices found!");
  42. error(RtAudioError::NO_DEVICES_FOUND);
  43. }
  44. }
  45. RtAudio :: RtAudio(int *streamID,
  46. int outputDevice, int outputChannels,
  47. int inputDevice, int inputChannels,
  48. RTAUDIO_FORMAT format, int sampleRate,
  49. int *bufferSize, int numberOfBuffers)
  50. {
  51. initialize();
  52. if (nDevices <= 0) {
  53. sprintf(message, "RtAudio: no audio devices found!");
  54. error(RtAudioError::NO_DEVICES_FOUND);
  55. }
  56. try {
  57. *streamID = openStream(outputDevice, outputChannels, inputDevice, inputChannels,
  58. format, sampleRate, bufferSize, numberOfBuffers);
  59. }
  60. catch (RtAudioError &exception) {
  61. // deallocate the RTAUDIO_DEVICE structures
  62. if (devices) free(devices);
  63. error(exception.getType());
  64. }
  65. }
  66. RtAudio :: ~RtAudio()
  67. {
  68. // close any existing streams
  69. while ( streams.size() )
  70. closeStream( streams.begin()->first );
  71. // deallocate the RTAUDIO_DEVICE structures
  72. if (devices) free(devices);
  73. }
  74. int RtAudio :: openStream(int outputDevice, int outputChannels,
  75. int inputDevice, int inputChannels,
  76. RTAUDIO_FORMAT format, int sampleRate,
  77. int *bufferSize, int numberOfBuffers)
  78. {
  79. static int streamKey = 0; // Unique stream identifier ... OK for multiple instances.
  80. if (outputChannels < 1 && inputChannels < 1) {
  81. sprintf(message,"RtAudio: one or both 'channel' parameters must be greater than zero.");
  82. error(RtAudioError::INVALID_PARAMETER);
  83. }
  84. if ( formatBytes(format) == 0 ) {
  85. sprintf(message,"RtAudio: 'format' parameter value is undefined.");
  86. error(RtAudioError::INVALID_PARAMETER);
  87. }
  88. if ( outputChannels > 0 ) {
  89. if (outputDevice >= nDevices || outputDevice < 0) {
  90. sprintf(message,"RtAudio: 'outputDevice' parameter value (%d) is invalid.", outputDevice);
  91. error(RtAudioError::INVALID_PARAMETER);
  92. }
  93. }
  94. if ( inputChannels > 0 ) {
  95. if (inputDevice >= nDevices || inputDevice < 0) {
  96. sprintf(message,"RtAudio: 'inputDevice' parameter value (%d) is invalid.", inputDevice);
  97. error(RtAudioError::INVALID_PARAMETER);
  98. }
  99. }
  100. // Allocate a new stream structure.
  101. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) calloc(1, sizeof(RTAUDIO_STREAM));
  102. if (stream == NULL) {
  103. sprintf(message, "RtAudio: memory allocation error!");
  104. error(RtAudioError::MEMORY_ERROR);
  105. }
  106. streams[++streamKey] = (void *) stream;
  107. stream->mode = UNINITIALIZED;
  108. bool result = SUCCESS;
  109. int device;
  110. STREAM_MODE mode;
  111. int channels;
  112. if ( outputChannels > 0 ) {
  113. device = outputDevice;
  114. mode = PLAYBACK;
  115. channels = outputChannels;
  116. if (device == 0) { // Try default device first.
  117. for (int i=0; i<nDevices; i++) {
  118. if (devices[i].probed == false) {
  119. // If the device wasn't successfully probed before, try it
  120. // again now.
  121. clearDeviceInfo(&devices[i]);
  122. probeDeviceInfo(&devices[i]);
  123. if (devices[i].probed == false)
  124. continue;
  125. }
  126. result = probeDeviceOpen(i, stream, mode, channels, sampleRate,
  127. format, bufferSize, numberOfBuffers);
  128. if (result == SUCCESS)
  129. break;
  130. }
  131. }
  132. else {
  133. result = probeDeviceOpen(device, stream, mode, channels, sampleRate,
  134. format, bufferSize, numberOfBuffers);
  135. }
  136. }
  137. if ( inputChannels > 0 && result == SUCCESS ) {
  138. device = inputDevice;
  139. mode = RECORD;
  140. channels = inputChannels;
  141. if (device == 0) { // Try default device first.
  142. for (int i=0; i<nDevices; i++) {
  143. if (devices[i].probed == false) {
  144. // If the device wasn't successfully probed before, try it
  145. // again now.
  146. clearDeviceInfo(&devices[i]);
  147. probeDeviceInfo(&devices[i]);
  148. if (devices[i].probed == false)
  149. continue;
  150. }
  151. result = probeDeviceOpen(i, stream, mode, channels, sampleRate,
  152. format, bufferSize, numberOfBuffers);
  153. if (result == SUCCESS)
  154. break;
  155. }
  156. }
  157. else {
  158. result = probeDeviceOpen(device, stream, mode, channels, sampleRate,
  159. format, bufferSize, numberOfBuffers);
  160. }
  161. }
  162. if ( result == SUCCESS ) {
  163. MUTEX_INITIALIZE(&stream->mutex);
  164. return streamKey;
  165. }
  166. // If we get here, all attempted probes failed. Close any opened
  167. // devices and delete the allocated stream.
  168. closeStream(streamKey);
  169. sprintf(message,"RtAudio: no devices found for given parameters.");
  170. error(RtAudioError::INVALID_PARAMETER);
  171. return -1;
  172. }
  173. int RtAudio :: getDeviceCount(void)
  174. {
  175. return nDevices;
  176. }
  177. void RtAudio :: getDeviceInfo(int device, RTAUDIO_DEVICE *info)
  178. {
  179. if (device >= nDevices || device < 0) {
  180. sprintf(message, "RtAudio: invalid device specifier (%d)!", device);
  181. error(RtAudioError::INVALID_DEVICE);
  182. }
  183. // If the device wasn't successfully probed before, try it again.
  184. if (devices[device].probed == false) {
  185. clearDeviceInfo(&devices[device]);
  186. probeDeviceInfo(&devices[device]);
  187. }
  188. // Clear the info structure.
  189. memset(info, 0, sizeof(RTAUDIO_DEVICE));
  190. strncpy(info->name, devices[device].name, 128);
  191. info->probed = devices[device].probed;
  192. if ( info->probed == true ) {
  193. info->maxOutputChannels = devices[device].maxOutputChannels;
  194. info->maxInputChannels = devices[device].maxInputChannels;
  195. info->maxDuplexChannels = devices[device].maxDuplexChannels;
  196. info->minOutputChannels = devices[device].minOutputChannels;
  197. info->minInputChannels = devices[device].minInputChannels;
  198. info->minDuplexChannels = devices[device].minDuplexChannels;
  199. info->hasDuplexSupport = devices[device].hasDuplexSupport;
  200. info->nSampleRates = devices[device].nSampleRates;
  201. if (info->nSampleRates == -1) {
  202. info->sampleRates[0] = devices[device].sampleRates[0];
  203. info->sampleRates[1] = devices[device].sampleRates[1];
  204. }
  205. else {
  206. for (int i=0; i<info->nSampleRates; i++)
  207. info->sampleRates[i] = devices[device].sampleRates[i];
  208. }
  209. info->nativeFormats = devices[device].nativeFormats;
  210. }
  211. return;
  212. }
  213. char * const RtAudio :: getStreamBuffer(int streamID)
  214. {
  215. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  216. return stream->userBuffer;
  217. }
  218. // This global structure is used to pass information to the thread
  219. // function. I tried other methods but had intermittent errors due to
  220. // variable persistence during thread startup.
  221. struct {
  222. RtAudio *object;
  223. int streamID;
  224. } thread_info;
  225. #if defined(__WINDOWS_DS_)
  226. extern "C" unsigned __stdcall callbackHandler(void *ptr);
  227. #else
  228. extern "C" void *callbackHandler(void *ptr);
  229. #endif
  230. void RtAudio :: setStreamCallback(int streamID, RTAUDIO_CALLBACK callback, void *userData)
  231. {
  232. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  233. stream->callback = callback;
  234. stream->userData = userData;
  235. stream->usingCallback = true;
  236. thread_info.object = this;
  237. thread_info.streamID = streamID;
  238. int err = 0;
  239. #if defined(__WINDOWS_DS_)
  240. unsigned thread_id;
  241. stream->thread = _beginthreadex(NULL, 0, &callbackHandler,
  242. &stream->usingCallback, 0, &thread_id);
  243. if (stream->thread == 0) err = -1;
  244. // When spawning multiple threads in quick succession, it appears to be
  245. // necessary to wait a bit for each to initialize ... another windism!
  246. Sleep(1);
  247. #else
  248. err = pthread_create(&stream->thread, NULL, callbackHandler, &stream->usingCallback);
  249. #endif
  250. if (err) {
  251. stream->usingCallback = false;
  252. sprintf(message, "RtAudio: error starting callback thread!");
  253. error(RtAudioError::THREAD_ERROR);
  254. }
  255. }
  256. // *************************************************** //
  257. //
  258. // OS/API-specific methods.
  259. //
  260. // *************************************************** //
  261. #if defined(__LINUX_ALSA_)
  262. void RtAudio :: initialize(void)
  263. {
  264. int card, err, device;
  265. int devices_per_card[32] = {0};
  266. char name[32];
  267. snd_ctl_t *handle;
  268. snd_ctl_card_info_t *info;
  269. snd_ctl_card_info_alloca(&info);
  270. // Count cards and devices
  271. nDevices = 0;
  272. card = -1;
  273. snd_card_next(&card);
  274. while (card >= 0) {
  275. sprintf(name, "hw:%d", card);
  276. err = snd_ctl_open(&handle, name, 0);
  277. if (err < 0) {
  278. sprintf(message, "RtAudio: ALSA control open (%i): %s.", card, snd_strerror(err));
  279. error(RtAudioError::WARNING);
  280. goto next_card;
  281. }
  282. err = snd_ctl_card_info(handle, info);
  283. if (err < 0) {
  284. sprintf(message, "RtAudio: ALSA control hardware info (%i): %s.", card, snd_strerror(err));
  285. error(RtAudioError::WARNING);
  286. goto next_card;
  287. }
  288. device = -1;
  289. while (1) {
  290. err = snd_ctl_pcm_next_device(handle, &device);
  291. if (err < 0) {
  292. sprintf(message, "RtAudio: ALSA control next device (%i): %s.", card, snd_strerror(err));
  293. error(RtAudioError::WARNING);
  294. break;
  295. }
  296. if (device < 0)
  297. break;
  298. nDevices++;
  299. devices_per_card[card]++;
  300. }
  301. next_card:
  302. snd_ctl_close(handle);
  303. snd_card_next(&card);
  304. }
  305. if (nDevices == 0) return;
  306. // Allocate the RTAUDIO_DEVICE structures.
  307. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  308. if (devices == NULL) {
  309. sprintf(message, "RtAudio: memory allocation error!");
  310. error(RtAudioError::MEMORY_ERROR);
  311. }
  312. // Write device ascii identifiers to device structures and then
  313. // probe the device capabilities.
  314. card = 0;
  315. device = 0;
  316. for (int i=0; i<nDevices; i++) {
  317. if (devices_per_card[card])
  318. sprintf(devices[i].name, "hw:%d,%d", card, device);
  319. if (devices_per_card[card] <= device+1) {
  320. card++;
  321. device = 0;
  322. }
  323. else
  324. device++;
  325. probeDeviceInfo(&devices[i]);
  326. }
  327. return;
  328. }
  329. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  330. {
  331. int err;
  332. int open_mode = SND_PCM_ASYNC;
  333. snd_pcm_t *handle;
  334. snd_pcm_stream_t stream;
  335. // First try for playback
  336. stream = SND_PCM_STREAM_PLAYBACK;
  337. err = snd_pcm_open(&handle, info->name, stream, open_mode);
  338. if (err < 0) {
  339. sprintf(message, "RtAudio: ALSA pcm playback open (%s): %s.",
  340. info->name, snd_strerror(err));
  341. error(RtAudioError::WARNING);
  342. goto capture_probe;
  343. }
  344. snd_pcm_hw_params_t *params;
  345. snd_pcm_hw_params_alloca(&params);
  346. // We have an open device ... allocate the parameter structure.
  347. err = snd_pcm_hw_params_any(handle, params);
  348. if (err < 0) {
  349. snd_pcm_close(handle);
  350. sprintf(message, "RtAudio: ALSA hardware probe error (%s): %s.",
  351. info->name, snd_strerror(err));
  352. error(RtAudioError::WARNING);
  353. goto capture_probe;
  354. }
  355. // Get output channel information.
  356. info->minOutputChannels = snd_pcm_hw_params_get_channels_min(params);
  357. info->maxOutputChannels = snd_pcm_hw_params_get_channels_max(params);
  358. snd_pcm_close(handle);
  359. capture_probe:
  360. // Now try for capture
  361. stream = SND_PCM_STREAM_CAPTURE;
  362. err = snd_pcm_open(&handle, info->name, stream, open_mode);
  363. if (err < 0) {
  364. sprintf(message, "RtAudio: ALSA pcm capture open (%s): %s.",
  365. info->name, snd_strerror(err));
  366. error(RtAudioError::WARNING);
  367. if (info->maxOutputChannels == 0)
  368. // didn't open for playback either ... device invalid
  369. return;
  370. goto probe_parameters;
  371. }
  372. // We have an open capture device ... allocate the parameter structure.
  373. err = snd_pcm_hw_params_any(handle, params);
  374. if (err < 0) {
  375. snd_pcm_close(handle);
  376. sprintf(message, "RtAudio: ALSA hardware probe error (%s): %s.",
  377. info->name, snd_strerror(err));
  378. error(RtAudioError::WARNING);
  379. if (info->maxOutputChannels > 0)
  380. goto probe_parameters;
  381. else
  382. return;
  383. }
  384. // Get input channel information.
  385. info->minInputChannels = snd_pcm_hw_params_get_channels_min(params);
  386. info->maxInputChannels = snd_pcm_hw_params_get_channels_max(params);
  387. // If device opens for both playback and capture, we determine the channels.
  388. if (info->maxOutputChannels == 0 || info->maxInputChannels == 0)
  389. goto probe_parameters;
  390. info->hasDuplexSupport = true;
  391. info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ?
  392. info->maxInputChannels : info->maxOutputChannels;
  393. info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ?
  394. info->minInputChannels : info->minOutputChannels;
  395. snd_pcm_close(handle);
  396. probe_parameters:
  397. // At this point, we just need to figure out the supported data formats and sample rates.
  398. // We'll proceed by openning the device in the direction with the maximum number of channels,
  399. // or playback if they are equal. This might limit our sample rate options, but so be it.
  400. if (info->maxOutputChannels >= info->maxInputChannels)
  401. stream = SND_PCM_STREAM_PLAYBACK;
  402. else
  403. stream = SND_PCM_STREAM_CAPTURE;
  404. err = snd_pcm_open(&handle, info->name, stream, open_mode);
  405. if (err < 0) {
  406. sprintf(message, "RtAudio: ALSA pcm (%s) won't reopen during probe: %s.",
  407. info->name, snd_strerror(err));
  408. error(RtAudioError::WARNING);
  409. return;
  410. }
  411. // We have an open device ... allocate the parameter structure.
  412. err = snd_pcm_hw_params_any(handle, params);
  413. if (err < 0) {
  414. snd_pcm_close(handle);
  415. sprintf(message, "RtAudio: ALSA hardware reopen probe error (%s): %s.",
  416. info->name, snd_strerror(err));
  417. error(RtAudioError::WARNING);
  418. return;
  419. }
  420. // Test a non-standard sample rate to see if continuous rate is supported.
  421. int dir = 0;
  422. if (snd_pcm_hw_params_test_rate(handle, params, 35500, dir) == 0) {
  423. // It appears that continuous sample rate support is available.
  424. info->nSampleRates = -1;
  425. info->sampleRates[0] = snd_pcm_hw_params_get_rate_min(params, &dir);
  426. info->sampleRates[1] = snd_pcm_hw_params_get_rate_max(params, &dir);
  427. }
  428. else {
  429. // No continuous rate support ... test our discrete set of sample rate values.
  430. info->nSampleRates = 0;
  431. for (int i=0; i<MAX_SAMPLE_RATES; i++) {
  432. if (snd_pcm_hw_params_test_rate(handle, params, SAMPLE_RATES[i], dir) == 0) {
  433. info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
  434. info->nSampleRates++;
  435. }
  436. }
  437. if (info->nSampleRates == 0) {
  438. snd_pcm_close(handle);
  439. return;
  440. }
  441. }
  442. // Probe the supported data formats ... we don't care about endian-ness just yet
  443. snd_pcm_format_t format;
  444. info->nativeFormats = 0;
  445. format = SND_PCM_FORMAT_S8;
  446. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  447. info->nativeFormats |= RTAUDIO_SINT8;
  448. format = SND_PCM_FORMAT_S16;
  449. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  450. info->nativeFormats |= RTAUDIO_SINT16;
  451. format = SND_PCM_FORMAT_S24;
  452. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  453. info->nativeFormats |= RTAUDIO_SINT24;
  454. format = SND_PCM_FORMAT_S32;
  455. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  456. info->nativeFormats |= RTAUDIO_SINT32;
  457. format = SND_PCM_FORMAT_FLOAT;
  458. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  459. info->nativeFormats |= RTAUDIO_FLOAT32;
  460. format = SND_PCM_FORMAT_FLOAT64;
  461. if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
  462. info->nativeFormats |= RTAUDIO_FLOAT64;
  463. // Check that we have at least one supported format
  464. if (info->nativeFormats == 0) {
  465. snd_pcm_close(handle);
  466. sprintf(message, "RtAudio: ALSA PCM device (%s) data format not supported by RtAudio.",
  467. info->name);
  468. error(RtAudioError::WARNING);
  469. return;
  470. }
  471. // That's all ... close the device and return
  472. snd_pcm_close(handle);
  473. info->probed = true;
  474. return;
  475. }
  476. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  477. STREAM_MODE mode, int channels,
  478. int sampleRate, RTAUDIO_FORMAT format,
  479. int *bufferSize, int numberOfBuffers)
  480. {
  481. #if defined(RTAUDIO_DEBUG)
  482. snd_output_t *out;
  483. snd_output_stdio_attach(&out, stderr, 0);
  484. #endif
  485. // I'm not using the "plug" interface ... too much inconsistent behavior.
  486. const char *name = devices[device].name;
  487. snd_pcm_stream_t alsa_stream;
  488. if (mode == PLAYBACK)
  489. alsa_stream = SND_PCM_STREAM_PLAYBACK;
  490. else
  491. alsa_stream = SND_PCM_STREAM_CAPTURE;
  492. int err;
  493. snd_pcm_t *handle;
  494. int alsa_open_mode = SND_PCM_ASYNC;
  495. err = snd_pcm_open(&handle, name, alsa_stream, alsa_open_mode);
  496. if (err < 0) {
  497. sprintf(message,"RtAudio: ALSA pcm device (%s) won't open: %s.",
  498. name, snd_strerror(err));
  499. error(RtAudioError::WARNING);
  500. return FAILURE;
  501. }
  502. // Fill the parameter structure.
  503. snd_pcm_hw_params_t *hw_params;
  504. snd_pcm_hw_params_alloca(&hw_params);
  505. err = snd_pcm_hw_params_any(handle, hw_params);
  506. if (err < 0) {
  507. snd_pcm_close(handle);
  508. sprintf(message, "RtAudio: ALSA error getting parameter handle (%s): %s.",
  509. name, snd_strerror(err));
  510. error(RtAudioError::WARNING);
  511. return FAILURE;
  512. }
  513. #if defined(RTAUDIO_DEBUG)
  514. fprintf(stderr, "\nRtAudio: ALSA dump hardware params just after device open:\n\n");
  515. snd_pcm_hw_params_dump(hw_params, out);
  516. #endif
  517. // Set access ... try interleaved access first, then non-interleaved
  518. err = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
  519. if (err < 0) {
  520. // No interleave support ... try non-interleave.
  521. err = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED);
  522. if (err < 0) {
  523. snd_pcm_close(handle);
  524. sprintf(message, "RtAudio: ALSA error setting access ( (%s): %s.",
  525. name, snd_strerror(err));
  526. error(RtAudioError::WARNING);
  527. return FAILURE;
  528. }
  529. stream->deInterleave[mode] = true;
  530. }
  531. // Determine how to set the device format.
  532. stream->userFormat = format;
  533. snd_pcm_format_t device_format;
  534. if (format == RTAUDIO_SINT8)
  535. device_format = SND_PCM_FORMAT_S8;
  536. else if (format == RTAUDIO_SINT16)
  537. device_format = SND_PCM_FORMAT_S16;
  538. else if (format == RTAUDIO_SINT24)
  539. device_format = SND_PCM_FORMAT_S24;
  540. else if (format == RTAUDIO_SINT32)
  541. device_format = SND_PCM_FORMAT_S32;
  542. else if (format == RTAUDIO_FLOAT32)
  543. device_format = SND_PCM_FORMAT_FLOAT;
  544. else if (format == RTAUDIO_FLOAT64)
  545. device_format = SND_PCM_FORMAT_FLOAT64;
  546. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  547. stream->deviceFormat[mode] = format;
  548. goto set_format;
  549. }
  550. // The user requested format is not natively supported by the device.
  551. device_format = SND_PCM_FORMAT_FLOAT64;
  552. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  553. stream->deviceFormat[mode] = RTAUDIO_FLOAT64;
  554. goto set_format;
  555. }
  556. device_format = SND_PCM_FORMAT_FLOAT;
  557. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  558. stream->deviceFormat[mode] = RTAUDIO_FLOAT32;
  559. goto set_format;
  560. }
  561. device_format = SND_PCM_FORMAT_S32;
  562. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  563. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  564. goto set_format;
  565. }
  566. device_format = SND_PCM_FORMAT_S24;
  567. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  568. stream->deviceFormat[mode] = RTAUDIO_SINT24;
  569. goto set_format;
  570. }
  571. device_format = SND_PCM_FORMAT_S16;
  572. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  573. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  574. goto set_format;
  575. }
  576. device_format = SND_PCM_FORMAT_S8;
  577. if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) {
  578. stream->deviceFormat[mode] = RTAUDIO_SINT8;
  579. goto set_format;
  580. }
  581. // If we get here, no supported format was found.
  582. sprintf(message,"RtAudio: ALSA pcm device (%s) data format not supported by RtAudio.", name);
  583. snd_pcm_close(handle);
  584. error(RtAudioError::WARNING);
  585. return FAILURE;
  586. set_format:
  587. err = snd_pcm_hw_params_set_format(handle, hw_params, device_format);
  588. if (err < 0) {
  589. snd_pcm_close(handle);
  590. sprintf(message, "RtAudio: ALSA error setting format (%s): %s.",
  591. name, snd_strerror(err));
  592. error(RtAudioError::WARNING);
  593. return FAILURE;
  594. }
  595. // Determine whether byte-swaping is necessary.
  596. stream->doByteSwap[mode] = false;
  597. if (device_format != SND_PCM_FORMAT_S8) {
  598. err = snd_pcm_format_cpu_endian(device_format);
  599. if (err == 0)
  600. stream->doByteSwap[mode] = true;
  601. else if (err < 0) {
  602. snd_pcm_close(handle);
  603. sprintf(message, "RtAudio: ALSA error getting format endian-ness (%s): %s.",
  604. name, snd_strerror(err));
  605. error(RtAudioError::WARNING);
  606. return FAILURE;
  607. }
  608. }
  609. // Determine the number of channels for this device. We support a possible
  610. // minimum device channel number > than the value requested by the user.
  611. stream->nUserChannels[mode] = channels;
  612. int device_channels = snd_pcm_hw_params_get_channels_max(hw_params);
  613. if (device_channels < channels) {
  614. snd_pcm_close(handle);
  615. sprintf(message, "RtAudio: channels (%d) not supported by device (%s).",
  616. channels, name);
  617. error(RtAudioError::WARNING);
  618. return FAILURE;
  619. }
  620. device_channels = snd_pcm_hw_params_get_channels_min(hw_params);
  621. if (device_channels < channels) device_channels = channels;
  622. stream->nDeviceChannels[mode] = device_channels;
  623. // Set the device channels.
  624. err = snd_pcm_hw_params_set_channels(handle, hw_params, device_channels);
  625. if (err < 0) {
  626. snd_pcm_close(handle);
  627. sprintf(message, "RtAudio: ALSA error setting channels (%d) on device (%s): %s.",
  628. device_channels, name, snd_strerror(err));
  629. error(RtAudioError::WARNING);
  630. return FAILURE;
  631. }
  632. // Set the sample rate.
  633. err = snd_pcm_hw_params_set_rate(handle, hw_params, (unsigned int)sampleRate, 0);
  634. if (err < 0) {
  635. snd_pcm_close(handle);
  636. sprintf(message, "RtAudio: ALSA error setting sample rate (%d) on device (%s): %s.",
  637. sampleRate, name, snd_strerror(err));
  638. error(RtAudioError::WARNING);
  639. return FAILURE;
  640. }
  641. // Set the buffer number, which in ALSA is referred to as the "period".
  642. int dir;
  643. int periods = numberOfBuffers;
  644. // Even though the hardware might allow 1 buffer, it won't work reliably.
  645. if (periods < 2) periods = 2;
  646. err = snd_pcm_hw_params_get_periods_min(hw_params, &dir);
  647. if (err > periods) periods = err;
  648. err = snd_pcm_hw_params_set_periods(handle, hw_params, periods, 0);
  649. if (err < 0) {
  650. snd_pcm_close(handle);
  651. sprintf(message, "RtAudio: ALSA error setting periods (%s): %s.",
  652. name, snd_strerror(err));
  653. error(RtAudioError::WARNING);
  654. return FAILURE;
  655. }
  656. // Set the buffer (or period) size.
  657. err = snd_pcm_hw_params_get_period_size_min(hw_params, &dir);
  658. if (err > *bufferSize) *bufferSize = err;
  659. err = snd_pcm_hw_params_set_period_size(handle, hw_params, *bufferSize, 0);
  660. if (err < 0) {
  661. snd_pcm_close(handle);
  662. sprintf(message, "RtAudio: ALSA error setting period size (%s): %s.",
  663. name, snd_strerror(err));
  664. error(RtAudioError::WARNING);
  665. return FAILURE;
  666. }
  667. stream->bufferSize = *bufferSize;
  668. // Install the hardware configuration
  669. err = snd_pcm_hw_params(handle, hw_params);
  670. if (err < 0) {
  671. snd_pcm_close(handle);
  672. sprintf(message, "RtAudio: ALSA error installing hardware configuration (%s): %s.",
  673. name, snd_strerror(err));
  674. error(RtAudioError::WARNING);
  675. return FAILURE;
  676. }
  677. #if defined(RTAUDIO_DEBUG)
  678. fprintf(stderr, "\nRtAudio: ALSA dump hardware params after installation:\n\n");
  679. snd_pcm_hw_params_dump(hw_params, out);
  680. #endif
  681. /*
  682. // Install the software configuration
  683. snd_pcm_sw_params_t *sw_params = NULL;
  684. snd_pcm_sw_params_alloca(&sw_params);
  685. snd_pcm_sw_params_current(handle, sw_params);
  686. err = snd_pcm_sw_params(handle, sw_params);
  687. if (err < 0) {
  688. snd_pcm_close(handle);
  689. sprintf(message, "RtAudio: ALSA error installing software configuration (%s): %s.",
  690. name, snd_strerror(err));
  691. error(RtAudioError::WARNING);
  692. return FAILURE;
  693. }
  694. */
  695. // Set handle and flags for buffer conversion
  696. stream->handle[mode] = handle;
  697. stream->doConvertBuffer[mode] = false;
  698. if (stream->userFormat != stream->deviceFormat[mode])
  699. stream->doConvertBuffer[mode] = true;
  700. if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
  701. stream->doConvertBuffer[mode] = true;
  702. if (stream->nUserChannels[mode] > 1 && stream->deInterleave[mode])
  703. stream->doConvertBuffer[mode] = true;
  704. // Allocate necessary internal buffers
  705. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  706. long buffer_bytes;
  707. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  708. buffer_bytes = stream->nUserChannels[0];
  709. else
  710. buffer_bytes = stream->nUserChannels[1];
  711. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  712. if (stream->userBuffer) free(stream->userBuffer);
  713. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  714. if (stream->userBuffer == NULL)
  715. goto memory_error;
  716. }
  717. if ( stream->doConvertBuffer[mode] ) {
  718. long buffer_bytes;
  719. bool makeBuffer = true;
  720. if ( mode == PLAYBACK )
  721. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  722. else { // mode == RECORD
  723. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  724. if ( stream->mode == PLAYBACK ) {
  725. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  726. if ( buffer_bytes > bytes_out )
  727. buffer_bytes = (buffer_bytes > bytes_out) ? buffer_bytes : bytes_out;
  728. else
  729. makeBuffer = false;
  730. }
  731. }
  732. if ( makeBuffer ) {
  733. buffer_bytes *= *bufferSize;
  734. if (stream->deviceBuffer) free(stream->deviceBuffer);
  735. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  736. if (stream->deviceBuffer == NULL)
  737. goto memory_error;
  738. }
  739. }
  740. stream->device[mode] = device;
  741. stream->state = STREAM_STOPPED;
  742. if ( stream->mode == PLAYBACK && mode == RECORD )
  743. // We had already set up an output stream.
  744. stream->mode = DUPLEX;
  745. else
  746. stream->mode = mode;
  747. stream->nBuffers = periods;
  748. stream->sampleRate = sampleRate;
  749. return SUCCESS;
  750. memory_error:
  751. if (stream->handle[0]) {
  752. snd_pcm_close(stream->handle[0]);
  753. stream->handle[0] = 0;
  754. }
  755. if (stream->handle[1]) {
  756. snd_pcm_close(stream->handle[1]);
  757. stream->handle[1] = 0;
  758. }
  759. if (stream->userBuffer) {
  760. free(stream->userBuffer);
  761. stream->userBuffer = 0;
  762. }
  763. sprintf(message, "RtAudio: ALSA error allocating buffer memory (%s).", name);
  764. error(RtAudioError::WARNING);
  765. return FAILURE;
  766. }
  767. void RtAudio :: cancelStreamCallback(int streamID)
  768. {
  769. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  770. if (stream->usingCallback) {
  771. stream->usingCallback = false;
  772. pthread_cancel(stream->thread);
  773. pthread_join(stream->thread, NULL);
  774. stream->thread = 0;
  775. stream->callback = NULL;
  776. stream->userData = NULL;
  777. }
  778. }
  779. void RtAudio :: closeStream(int streamID)
  780. {
  781. // We don't want an exception to be thrown here because this
  782. // function is called by our class destructor. So, do our own
  783. // streamID check.
  784. if ( streams.find( streamID ) == streams.end() ) {
  785. sprintf(message, "RtAudio: invalid stream identifier!");
  786. error(RtAudioError::WARNING);
  787. return;
  788. }
  789. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamID];
  790. if (stream->usingCallback) {
  791. pthread_cancel(stream->thread);
  792. pthread_join(stream->thread, NULL);
  793. }
  794. if (stream->state == STREAM_RUNNING) {
  795. if (stream->mode == PLAYBACK || stream->mode == DUPLEX)
  796. snd_pcm_drop(stream->handle[0]);
  797. if (stream->mode == RECORD || stream->mode == DUPLEX)
  798. snd_pcm_drop(stream->handle[1]);
  799. }
  800. pthread_mutex_destroy(&stream->mutex);
  801. if (stream->handle[0])
  802. snd_pcm_close(stream->handle[0]);
  803. if (stream->handle[1])
  804. snd_pcm_close(stream->handle[1]);
  805. if (stream->userBuffer)
  806. free(stream->userBuffer);
  807. if (stream->deviceBuffer)
  808. free(stream->deviceBuffer);
  809. free(stream);
  810. streams.erase(streamID);
  811. }
  812. void RtAudio :: startStream(int streamID)
  813. {
  814. // This method calls snd_pcm_prepare if the device isn't already in that state.
  815. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  816. MUTEX_LOCK(&stream->mutex);
  817. if (stream->state == STREAM_RUNNING)
  818. goto unlock;
  819. int err;
  820. snd_pcm_state_t state;
  821. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  822. state = snd_pcm_state(stream->handle[0]);
  823. if (state != SND_PCM_STATE_PREPARED) {
  824. err = snd_pcm_prepare(stream->handle[0]);
  825. if (err < 0) {
  826. sprintf(message, "RtAudio: ALSA error preparing pcm device (%s): %s.",
  827. devices[stream->device[0]].name, snd_strerror(err));
  828. MUTEX_UNLOCK(&stream->mutex);
  829. error(RtAudioError::DRIVER_ERROR);
  830. }
  831. }
  832. }
  833. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  834. state = snd_pcm_state(stream->handle[1]);
  835. if (state != SND_PCM_STATE_PREPARED) {
  836. err = snd_pcm_prepare(stream->handle[1]);
  837. if (err < 0) {
  838. sprintf(message, "RtAudio: ALSA error preparing pcm device (%s): %s.",
  839. devices[stream->device[1]].name, snd_strerror(err));
  840. MUTEX_UNLOCK(&stream->mutex);
  841. error(RtAudioError::DRIVER_ERROR);
  842. }
  843. }
  844. }
  845. stream->state = STREAM_RUNNING;
  846. unlock:
  847. MUTEX_UNLOCK(&stream->mutex);
  848. }
  849. void RtAudio :: stopStream(int streamID)
  850. {
  851. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  852. MUTEX_LOCK(&stream->mutex);
  853. if (stream->state == STREAM_STOPPED)
  854. goto unlock;
  855. int err;
  856. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  857. err = snd_pcm_drain(stream->handle[0]);
  858. if (err < 0) {
  859. sprintf(message, "RtAudio: ALSA error draining pcm device (%s): %s.",
  860. devices[stream->device[0]].name, snd_strerror(err));
  861. MUTEX_UNLOCK(&stream->mutex);
  862. error(RtAudioError::DRIVER_ERROR);
  863. }
  864. }
  865. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  866. err = snd_pcm_drain(stream->handle[1]);
  867. if (err < 0) {
  868. sprintf(message, "RtAudio: ALSA error draining pcm device (%s): %s.",
  869. devices[stream->device[1]].name, snd_strerror(err));
  870. MUTEX_UNLOCK(&stream->mutex);
  871. error(RtAudioError::DRIVER_ERROR);
  872. }
  873. }
  874. stream->state = STREAM_STOPPED;
  875. unlock:
  876. MUTEX_UNLOCK(&stream->mutex);
  877. }
  878. void RtAudio :: abortStream(int streamID)
  879. {
  880. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  881. MUTEX_LOCK(&stream->mutex);
  882. if (stream->state == STREAM_STOPPED)
  883. goto unlock;
  884. int err;
  885. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  886. err = snd_pcm_drop(stream->handle[0]);
  887. if (err < 0) {
  888. sprintf(message, "RtAudio: ALSA error draining pcm device (%s): %s.",
  889. devices[stream->device[0]].name, snd_strerror(err));
  890. MUTEX_UNLOCK(&stream->mutex);
  891. error(RtAudioError::DRIVER_ERROR);
  892. }
  893. }
  894. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  895. err = snd_pcm_drop(stream->handle[1]);
  896. if (err < 0) {
  897. sprintf(message, "RtAudio: ALSA error draining pcm device (%s): %s.",
  898. devices[stream->device[1]].name, snd_strerror(err));
  899. MUTEX_UNLOCK(&stream->mutex);
  900. error(RtAudioError::DRIVER_ERROR);
  901. }
  902. }
  903. stream->state = STREAM_STOPPED;
  904. unlock:
  905. MUTEX_UNLOCK(&stream->mutex);
  906. }
  907. int RtAudio :: streamWillBlock(int streamID)
  908. {
  909. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  910. MUTEX_LOCK(&stream->mutex);
  911. int err = 0, frames = 0;
  912. if (stream->state == STREAM_STOPPED)
  913. goto unlock;
  914. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  915. err = snd_pcm_avail_update(stream->handle[0]);
  916. if (err < 0) {
  917. sprintf(message, "RtAudio: ALSA error getting available frames for device (%s): %s.",
  918. devices[stream->device[0]].name, snd_strerror(err));
  919. MUTEX_UNLOCK(&stream->mutex);
  920. error(RtAudioError::DRIVER_ERROR);
  921. }
  922. }
  923. frames = err;
  924. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  925. err = snd_pcm_avail_update(stream->handle[1]);
  926. if (err < 0) {
  927. sprintf(message, "RtAudio: ALSA error getting available frames for device (%s): %s.",
  928. devices[stream->device[1]].name, snd_strerror(err));
  929. MUTEX_UNLOCK(&stream->mutex);
  930. error(RtAudioError::DRIVER_ERROR);
  931. }
  932. if (frames > err) frames = err;
  933. }
  934. frames = stream->bufferSize - frames;
  935. if (frames < 0) frames = 0;
  936. unlock:
  937. MUTEX_UNLOCK(&stream->mutex);
  938. return frames;
  939. }
  940. void RtAudio :: tickStream(int streamID)
  941. {
  942. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  943. int stopStream = 0;
  944. if (stream->state == STREAM_STOPPED) {
  945. if (stream->usingCallback) usleep(50000); // sleep 50 milliseconds
  946. return;
  947. }
  948. else if (stream->usingCallback) {
  949. stopStream = stream->callback(stream->userBuffer, stream->bufferSize, stream->userData);
  950. }
  951. MUTEX_LOCK(&stream->mutex);
  952. // The state might change while waiting on a mutex.
  953. if (stream->state == STREAM_STOPPED)
  954. goto unlock;
  955. int err;
  956. char *buffer;
  957. int channels;
  958. RTAUDIO_FORMAT format;
  959. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  960. // Setup parameters and do buffer conversion if necessary.
  961. if (stream->doConvertBuffer[0]) {
  962. convertStreamBuffer(stream, PLAYBACK);
  963. buffer = stream->deviceBuffer;
  964. channels = stream->nDeviceChannels[0];
  965. format = stream->deviceFormat[0];
  966. }
  967. else {
  968. buffer = stream->userBuffer;
  969. channels = stream->nUserChannels[0];
  970. format = stream->userFormat;
  971. }
  972. // Do byte swapping if necessary.
  973. if (stream->doByteSwap[0])
  974. byteSwapBuffer(buffer, stream->bufferSize * channels, format);
  975. // Write samples to device in interleaved/non-interleaved format.
  976. if (stream->deInterleave[0]) {
  977. void *bufs[channels];
  978. size_t offset = stream->bufferSize * formatBytes(format);
  979. for (int i=0; i<channels; i++)
  980. bufs[i] = (void *) (buffer + (i * offset));
  981. err = snd_pcm_writen(stream->handle[0], bufs, stream->bufferSize);
  982. }
  983. else
  984. err = snd_pcm_writei(stream->handle[0], buffer, stream->bufferSize);
  985. if (err < stream->bufferSize) {
  986. // Either an error or underrun occured.
  987. if (err == -EPIPE) {
  988. snd_pcm_state_t state = snd_pcm_state(stream->handle[0]);
  989. if (state == SND_PCM_STATE_XRUN) {
  990. sprintf(message, "RtAudio: ALSA underrun detected.");
  991. error(RtAudioError::WARNING);
  992. err = snd_pcm_prepare(stream->handle[0]);
  993. if (err < 0) {
  994. sprintf(message, "RtAudio: ALSA error preparing handle after underrun: %s.",
  995. snd_strerror(err));
  996. MUTEX_UNLOCK(&stream->mutex);
  997. error(RtAudioError::DRIVER_ERROR);
  998. }
  999. }
  1000. else {
  1001. sprintf(message, "RtAudio: ALSA error, current state is %s.",
  1002. snd_pcm_state_name(state));
  1003. MUTEX_UNLOCK(&stream->mutex);
  1004. error(RtAudioError::DRIVER_ERROR);
  1005. }
  1006. goto unlock;
  1007. }
  1008. else {
  1009. sprintf(message, "RtAudio: ALSA audio write error for device (%s): %s.",
  1010. devices[stream->device[0]].name, snd_strerror(err));
  1011. MUTEX_UNLOCK(&stream->mutex);
  1012. error(RtAudioError::DRIVER_ERROR);
  1013. }
  1014. }
  1015. }
  1016. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  1017. // Setup parameters.
  1018. if (stream->doConvertBuffer[1]) {
  1019. buffer = stream->deviceBuffer;
  1020. channels = stream->nDeviceChannels[1];
  1021. format = stream->deviceFormat[1];
  1022. }
  1023. else {
  1024. buffer = stream->userBuffer;
  1025. channels = stream->nUserChannels[1];
  1026. format = stream->userFormat;
  1027. }
  1028. // Read samples from device in interleaved/non-interleaved format.
  1029. if (stream->deInterleave[1]) {
  1030. void *bufs[channels];
  1031. size_t offset = stream->bufferSize * formatBytes(format);
  1032. for (int i=0; i<channels; i++)
  1033. bufs[i] = (void *) (buffer + (i * offset));
  1034. err = snd_pcm_readn(stream->handle[1], bufs, stream->bufferSize);
  1035. }
  1036. else
  1037. err = snd_pcm_readi(stream->handle[1], buffer, stream->bufferSize);
  1038. if (err < stream->bufferSize) {
  1039. // Either an error or underrun occured.
  1040. if (err == -EPIPE) {
  1041. snd_pcm_state_t state = snd_pcm_state(stream->handle[1]);
  1042. if (state == SND_PCM_STATE_XRUN) {
  1043. sprintf(message, "RtAudio: ALSA overrun detected.");
  1044. error(RtAudioError::WARNING);
  1045. err = snd_pcm_prepare(stream->handle[1]);
  1046. if (err < 0) {
  1047. sprintf(message, "RtAudio: ALSA error preparing handle after overrun: %s.",
  1048. snd_strerror(err));
  1049. MUTEX_UNLOCK(&stream->mutex);
  1050. error(RtAudioError::DRIVER_ERROR);
  1051. }
  1052. }
  1053. else {
  1054. sprintf(message, "RtAudio: ALSA error, current state is %s.",
  1055. snd_pcm_state_name(state));
  1056. MUTEX_UNLOCK(&stream->mutex);
  1057. error(RtAudioError::DRIVER_ERROR);
  1058. }
  1059. goto unlock;
  1060. }
  1061. else {
  1062. sprintf(message, "RtAudio: ALSA audio read error for device (%s): %s.",
  1063. devices[stream->device[1]].name, snd_strerror(err));
  1064. MUTEX_UNLOCK(&stream->mutex);
  1065. error(RtAudioError::DRIVER_ERROR);
  1066. }
  1067. }
  1068. // Do byte swapping if necessary.
  1069. if (stream->doByteSwap[1])
  1070. byteSwapBuffer(buffer, stream->bufferSize * channels, format);
  1071. // Do buffer conversion if necessary.
  1072. if (stream->doConvertBuffer[1])
  1073. convertStreamBuffer(stream, RECORD);
  1074. }
  1075. unlock:
  1076. MUTEX_UNLOCK(&stream->mutex);
  1077. if (stream->usingCallback && stopStream)
  1078. this->stopStream(streamID);
  1079. }
  1080. extern "C" void *callbackHandler(void *ptr)
  1081. {
  1082. RtAudio *object = thread_info.object;
  1083. int stream = thread_info.streamID;
  1084. bool *usingCallback = (bool *) ptr;
  1085. while ( *usingCallback ) {
  1086. pthread_testcancel();
  1087. try {
  1088. object->tickStream(stream);
  1089. }
  1090. catch (RtAudioError &exception) {
  1091. fprintf(stderr, "\nCallback thread error (%s) ... closing thread.\n\n",
  1092. exception.getMessage());
  1093. break;
  1094. }
  1095. }
  1096. return 0;
  1097. }
  1098. //******************** End of __LINUX_ALSA_ *********************//
  1099. #elif defined(__LINUX_OSS_)
  1100. #include <sys/stat.h>
  1101. #include <sys/types.h>
  1102. #include <sys/ioctl.h>
  1103. #include <unistd.h>
  1104. #include <fcntl.h>
  1105. #include <sys/soundcard.h>
  1106. #include <errno.h>
  1107. #include <math.h>
  1108. #define DAC_NAME "/dev/dsp"
  1109. #define MAX_DEVICES 16
  1110. #define MAX_CHANNELS 16
  1111. void RtAudio :: initialize(void)
  1112. {
  1113. // Count cards and devices
  1114. nDevices = 0;
  1115. // We check /dev/dsp before probing devices. /dev/dsp is supposed to
  1116. // be a link to the "default" audio device, of the form /dev/dsp0,
  1117. // /dev/dsp1, etc... However, I've seen one case where /dev/dsp was a
  1118. // real device, so we need to check for that. Also, sometimes the
  1119. // link is to /dev/dspx and other times just dspx. I'm not sure how
  1120. // the latter works, but it does.
  1121. char device_name[16];
  1122. struct stat dspstat;
  1123. int dsplink = -1;
  1124. int i = 0;
  1125. if (lstat(DAC_NAME, &dspstat) == 0) {
  1126. if (S_ISLNK(dspstat.st_mode)) {
  1127. i = readlink(DAC_NAME, device_name, sizeof(device_name));
  1128. if (i > 0) {
  1129. device_name[i] = '\0';
  1130. if (i > 8) { // check for "/dev/dspx"
  1131. if (!strncmp(DAC_NAME, device_name, 8))
  1132. dsplink = atoi(&device_name[8]);
  1133. }
  1134. else if (i > 3) { // check for "dspx"
  1135. if (!strncmp("dsp", device_name, 3))
  1136. dsplink = atoi(&device_name[3]);
  1137. }
  1138. }
  1139. else {
  1140. sprintf(message, "RtAudio: cannot read value of symbolic link %s.", DAC_NAME);
  1141. error(RtAudioError::SYSTEM_ERROR);
  1142. }
  1143. }
  1144. }
  1145. else {
  1146. sprintf(message, "RtAudio: cannot stat %s.", DAC_NAME);
  1147. error(RtAudioError::SYSTEM_ERROR);
  1148. }
  1149. // The OSS API doesn't provide a routine for determining the number
  1150. // of devices. Thus, we'll just pursue a brute force method. The
  1151. // idea is to start with /dev/dsp(0) and continue with higher device
  1152. // numbers until we reach MAX_DSP_DEVICES. This should tell us how
  1153. // many devices we have ... it is not a fullproof scheme, but hopefully
  1154. // it will work most of the time.
  1155. int fd = 0;
  1156. char names[MAX_DEVICES][16];
  1157. for (i=-1; i<MAX_DEVICES; i++) {
  1158. // Probe /dev/dsp first, since it is supposed to be the default device.
  1159. if (i == -1)
  1160. sprintf(device_name, "%s", DAC_NAME);
  1161. else if (i == dsplink)
  1162. continue; // We've aready probed this device via /dev/dsp link ... try next device.
  1163. else
  1164. sprintf(device_name, "%s%d", DAC_NAME, i);
  1165. // First try to open the device for playback, then record mode.
  1166. fd = open(device_name, O_WRONLY | O_NONBLOCK);
  1167. if (fd == -1) {
  1168. // Open device for playback failed ... either busy or doesn't exist.
  1169. if (errno != EBUSY && errno != EAGAIN) {
  1170. // Try to open for capture
  1171. fd = open(device_name, O_RDONLY | O_NONBLOCK);
  1172. if (fd == -1) {
  1173. // Open device for record failed.
  1174. if (errno != EBUSY && errno != EAGAIN)
  1175. continue;
  1176. else {
  1177. sprintf(message, "RtAudio: OSS record device (%s) is busy.", device_name);
  1178. error(RtAudioError::WARNING);
  1179. // still count it for now
  1180. }
  1181. }
  1182. }
  1183. else {
  1184. sprintf(message, "RtAudio: OSS playback device (%s) is busy.", device_name);
  1185. error(RtAudioError::WARNING);
  1186. // still count it for now
  1187. }
  1188. }
  1189. if (fd >= 0) close(fd);
  1190. strncpy(names[nDevices], device_name, 16);
  1191. nDevices++;
  1192. }
  1193. if (nDevices == 0) return;
  1194. // Allocate the DEVICE_CONTROL structures.
  1195. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  1196. if (devices == NULL) {
  1197. sprintf(message, "RtAudio: memory allocation error!");
  1198. error(RtAudioError::MEMORY_ERROR);
  1199. }
  1200. // Write device ascii identifiers to device control structure and then probe capabilities.
  1201. for (i=0; i<nDevices; i++) {
  1202. strncpy(devices[i].name, names[i], 16);
  1203. probeDeviceInfo(&devices[i]);
  1204. }
  1205. return;
  1206. }
  1207. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  1208. {
  1209. int i, fd, channels, mask;
  1210. // The OSS API doesn't provide a means for probing the capabilities
  1211. // of devices. Thus, we'll just pursue a brute force method.
  1212. // First try for playback
  1213. fd = open(info->name, O_WRONLY | O_NONBLOCK);
  1214. if (fd == -1) {
  1215. // Open device failed ... either busy or doesn't exist
  1216. if (errno == EBUSY || errno == EAGAIN)
  1217. sprintf(message, "RtAudio: OSS playback device (%s) is busy and cannot be probed.",
  1218. info->name);
  1219. else
  1220. sprintf(message, "RtAudio: OSS playback device (%s) open error.", info->name);
  1221. error(RtAudioError::WARNING);
  1222. goto capture_probe;
  1223. }
  1224. // We have an open device ... see how many channels it can handle
  1225. for (i=MAX_CHANNELS; i>0; i--) {
  1226. channels = i;
  1227. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
  1228. // This would normally indicate some sort of hardware error, but under ALSA's
  1229. // OSS emulation, it sometimes indicates an invalid channel value. Further,
  1230. // the returned channel value is not changed. So, we'll ignore the possible
  1231. // hardware error.
  1232. continue; // try next channel number
  1233. }
  1234. // Check to see whether the device supports the requested number of channels
  1235. if (channels != i ) continue; // try next channel number
  1236. // If here, we found the largest working channel value
  1237. break;
  1238. }
  1239. info->maxOutputChannels = channels;
  1240. // Now find the minimum number of channels it can handle
  1241. for (i=1; i<=info->maxOutputChannels; i++) {
  1242. channels = i;
  1243. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
  1244. continue; // try next channel number
  1245. // If here, we found the smallest working channel value
  1246. break;
  1247. }
  1248. info->minOutputChannels = channels;
  1249. close(fd);
  1250. capture_probe:
  1251. // Now try for capture
  1252. fd = open(info->name, O_RDONLY | O_NONBLOCK);
  1253. if (fd == -1) {
  1254. // Open device for capture failed ... either busy or doesn't exist
  1255. if (errno == EBUSY || errno == EAGAIN)
  1256. sprintf(message, "RtAudio: OSS capture device (%s) is busy and cannot be probed.",
  1257. info->name);
  1258. else
  1259. sprintf(message, "RtAudio: OSS capture device (%s) open error.", info->name);
  1260. error(RtAudioError::WARNING);
  1261. if (info->maxOutputChannels == 0)
  1262. // didn't open for playback either ... device invalid
  1263. return;
  1264. goto probe_parameters;
  1265. }
  1266. // We have the device open for capture ... see how many channels it can handle
  1267. for (i=MAX_CHANNELS; i>0; i--) {
  1268. channels = i;
  1269. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) {
  1270. continue; // as above
  1271. }
  1272. // If here, we found a working channel value
  1273. break;
  1274. }
  1275. info->maxInputChannels = channels;
  1276. // Now find the minimum number of channels it can handle
  1277. for (i=1; i<=info->maxInputChannels; i++) {
  1278. channels = i;
  1279. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
  1280. continue; // try next channel number
  1281. // If here, we found the smallest working channel value
  1282. break;
  1283. }
  1284. info->minInputChannels = channels;
  1285. close(fd);
  1286. // If device opens for both playback and capture, we determine the channels.
  1287. if (info->maxOutputChannels == 0 || info->maxInputChannels == 0)
  1288. goto probe_parameters;
  1289. fd = open(info->name, O_RDWR | O_NONBLOCK);
  1290. if (fd == -1)
  1291. goto probe_parameters;
  1292. ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
  1293. ioctl(fd, SNDCTL_DSP_GETCAPS, &mask);
  1294. if (mask & DSP_CAP_DUPLEX) {
  1295. info->hasDuplexSupport = true;
  1296. // We have the device open for duplex ... see how many channels it can handle
  1297. for (i=MAX_CHANNELS; i>0; i--) {
  1298. channels = i;
  1299. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
  1300. continue; // as above
  1301. // If here, we found a working channel value
  1302. break;
  1303. }
  1304. info->maxDuplexChannels = channels;
  1305. // Now find the minimum number of channels it can handle
  1306. for (i=1; i<=info->maxDuplexChannels; i++) {
  1307. channels = i;
  1308. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)
  1309. continue; // try next channel number
  1310. // If here, we found the smallest working channel value
  1311. break;
  1312. }
  1313. info->minDuplexChannels = channels;
  1314. }
  1315. close(fd);
  1316. probe_parameters:
  1317. // At this point, we need to figure out the supported data formats
  1318. // and sample rates. We'll proceed by openning the device in the
  1319. // direction with the maximum number of channels, or playback if
  1320. // they are equal. This might limit our sample rate options, but so
  1321. // be it.
  1322. if (info->maxOutputChannels >= info->maxInputChannels) {
  1323. fd = open(info->name, O_WRONLY | O_NONBLOCK);
  1324. channels = info->maxOutputChannels;
  1325. }
  1326. else {
  1327. fd = open(info->name, O_RDONLY | O_NONBLOCK);
  1328. channels = info->maxInputChannels;
  1329. }
  1330. if (fd == -1) {
  1331. // We've got some sort of conflict ... abort
  1332. sprintf(message, "RtAudio: OSS device (%s) won't reopen during probe.",
  1333. info->name);
  1334. error(RtAudioError::WARNING);
  1335. return;
  1336. }
  1337. // We have an open device ... set to maximum channels.
  1338. i = channels;
  1339. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) {
  1340. // We've got some sort of conflict ... abort
  1341. close(fd);
  1342. sprintf(message, "RtAudio: OSS device (%s) won't revert to previous channel setting.",
  1343. info->name);
  1344. error(RtAudioError::WARNING);
  1345. return;
  1346. }
  1347. if (ioctl(fd, SNDCTL_DSP_GETFMTS, &mask) == -1) {
  1348. close(fd);
  1349. sprintf(message, "RtAudio: OSS device (%s) can't get supported audio formats.",
  1350. info->name);
  1351. error(RtAudioError::WARNING);
  1352. return;
  1353. }
  1354. // Probe the supported data formats ... we don't care about endian-ness just yet.
  1355. int format;
  1356. info->nativeFormats = 0;
  1357. #if defined (AFMT_S32_BE)
  1358. // This format does not seem to be in the 2.4 kernel version of OSS soundcard.h
  1359. if (mask & AFMT_S32_BE) {
  1360. format = AFMT_S32_BE;
  1361. info->nativeFormats |= RTAUDIO_SINT32;
  1362. }
  1363. #endif
  1364. #if defined (AFMT_S32_LE)
  1365. /* This format is not in the 2.4.4 kernel version of OSS soundcard.h */
  1366. if (mask & AFMT_S32_LE) {
  1367. format = AFMT_S32_LE;
  1368. info->nativeFormats |= RTAUDIO_SINT32;
  1369. }
  1370. #endif
  1371. if (mask & AFMT_S8) {
  1372. format = AFMT_S8;
  1373. info->nativeFormats |= RTAUDIO_SINT8;
  1374. }
  1375. if (mask & AFMT_S16_BE) {
  1376. format = AFMT_S16_BE;
  1377. info->nativeFormats |= RTAUDIO_SINT16;
  1378. }
  1379. if (mask & AFMT_S16_LE) {
  1380. format = AFMT_S16_LE;
  1381. info->nativeFormats |= RTAUDIO_SINT16;
  1382. }
  1383. // Check that we have at least one supported format
  1384. if (info->nativeFormats == 0) {
  1385. close(fd);
  1386. sprintf(message, "RtAudio: OSS device (%s) data format not supported by RtAudio.",
  1387. info->name);
  1388. error(RtAudioError::WARNING);
  1389. return;
  1390. }
  1391. // Set the format
  1392. i = format;
  1393. if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) == -1 || format != i) {
  1394. close(fd);
  1395. sprintf(message, "RtAudio: OSS device (%s) error setting data format.",
  1396. info->name);
  1397. error(RtAudioError::WARNING);
  1398. return;
  1399. }
  1400. // Probe the supported sample rates ... first get lower limit
  1401. int speed = 1;
  1402. if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) == -1) {
  1403. // If we get here, we're probably using an ALSA driver with OSS-emulation,
  1404. // which doesn't conform to the OSS specification. In this case,
  1405. // we'll probe our predefined list of sample rates for working values.
  1406. info->nSampleRates = 0;
  1407. for (i=0; i<MAX_SAMPLE_RATES; i++) {
  1408. speed = SAMPLE_RATES[i];
  1409. if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) != -1) {
  1410. info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
  1411. info->nSampleRates++;
  1412. }
  1413. }
  1414. if (info->nSampleRates == 0) {
  1415. close(fd);
  1416. return;
  1417. }
  1418. goto finished;
  1419. }
  1420. info->sampleRates[0] = speed;
  1421. // Now get upper limit
  1422. speed = 1000000;
  1423. if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) == -1) {
  1424. close(fd);
  1425. sprintf(message, "RtAudio: OSS device (%s) error setting sample rate.",
  1426. info->name);
  1427. error(RtAudioError::WARNING);
  1428. return;
  1429. }
  1430. info->sampleRates[1] = speed;
  1431. info->nSampleRates = -1;
  1432. finished: // That's all ... close the device and return
  1433. close(fd);
  1434. info->probed = true;
  1435. return;
  1436. }
  1437. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  1438. STREAM_MODE mode, int channels,
  1439. int sampleRate, RTAUDIO_FORMAT format,
  1440. int *bufferSize, int numberOfBuffers)
  1441. {
  1442. int buffers, buffer_bytes, device_channels, device_format;
  1443. int srate, temp, fd;
  1444. const char *name = devices[device].name;
  1445. if (mode == PLAYBACK)
  1446. fd = open(name, O_WRONLY | O_NONBLOCK);
  1447. else { // mode == RECORD
  1448. if (stream->mode == PLAYBACK && stream->device[0] == device) {
  1449. // We just set the same device for playback ... close and reopen for duplex (OSS only).
  1450. close(stream->handle[0]);
  1451. stream->handle[0] = 0;
  1452. // First check that the number previously set channels is the same.
  1453. if (stream->nUserChannels[0] != channels) {
  1454. sprintf(message, "RtAudio: input/output channels must be equal for OSS duplex device (%s).", name);
  1455. goto error;
  1456. }
  1457. fd = open(name, O_RDWR | O_NONBLOCK);
  1458. }
  1459. else
  1460. fd = open(name, O_RDONLY | O_NONBLOCK);
  1461. }
  1462. if (fd == -1) {
  1463. if (errno == EBUSY || errno == EAGAIN)
  1464. sprintf(message, "RtAudio: OSS device (%s) is busy and cannot be opened.",
  1465. name);
  1466. else
  1467. sprintf(message, "RtAudio: OSS device (%s) cannot be opened.", name);
  1468. goto error;
  1469. }
  1470. // Now reopen in blocking mode.
  1471. close(fd);
  1472. if (mode == PLAYBACK)
  1473. fd = open(name, O_WRONLY | O_SYNC);
  1474. else { // mode == RECORD
  1475. if (stream->mode == PLAYBACK && stream->device[0] == device)
  1476. fd = open(name, O_RDWR | O_SYNC);
  1477. else
  1478. fd = open(name, O_RDONLY | O_SYNC);
  1479. }
  1480. if (fd == -1) {
  1481. sprintf(message, "RtAudio: OSS device (%s) cannot be opened.", name);
  1482. goto error;
  1483. }
  1484. // Get the sample format mask
  1485. int mask;
  1486. if (ioctl(fd, SNDCTL_DSP_GETFMTS, &mask) == -1) {
  1487. close(fd);
  1488. sprintf(message, "RtAudio: OSS device (%s) can't get supported audio formats.",
  1489. name);
  1490. goto error;
  1491. }
  1492. // Determine how to set the device format.
  1493. stream->userFormat = format;
  1494. device_format = -1;
  1495. stream->doByteSwap[mode] = false;
  1496. if (format == RTAUDIO_SINT8) {
  1497. if (mask & AFMT_S8) {
  1498. device_format = AFMT_S8;
  1499. stream->deviceFormat[mode] = RTAUDIO_SINT8;
  1500. }
  1501. }
  1502. else if (format == RTAUDIO_SINT16) {
  1503. if (mask & AFMT_S16_NE) {
  1504. device_format = AFMT_S16_NE;
  1505. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  1506. }
  1507. #if BYTE_ORDER == LITTLE_ENDIAN
  1508. else if (mask & AFMT_S16_BE) {
  1509. device_format = AFMT_S16_BE;
  1510. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  1511. stream->doByteSwap[mode] = true;
  1512. }
  1513. #else
  1514. else if (mask & AFMT_S16_LE) {
  1515. device_format = AFMT_S16_LE;
  1516. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  1517. stream->doByteSwap[mode] = true;
  1518. }
  1519. #endif
  1520. }
  1521. #if defined (AFMT_S32_NE) && defined (AFMT_S32_LE) && defined (AFMT_S32_BE)
  1522. else if (format == RTAUDIO_SINT32) {
  1523. if (mask & AFMT_S32_NE) {
  1524. device_format = AFMT_S32_NE;
  1525. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  1526. }
  1527. #if BYTE_ORDER == LITTLE_ENDIAN
  1528. else if (mask & AFMT_S32_BE) {
  1529. device_format = AFMT_S32_BE;
  1530. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  1531. stream->doByteSwap[mode] = true;
  1532. }
  1533. #else
  1534. else if (mask & AFMT_S32_LE) {
  1535. device_format = AFMT_S32_LE;
  1536. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  1537. stream->doByteSwap[mode] = true;
  1538. }
  1539. #endif
  1540. }
  1541. #endif
  1542. if (device_format == -1) {
  1543. // The user requested format is not natively supported by the device.
  1544. if (mask & AFMT_S16_NE) {
  1545. device_format = AFMT_S16_NE;
  1546. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  1547. }
  1548. #if BYTE_ORDER == LITTLE_ENDIAN
  1549. else if (mask & AFMT_S16_BE) {
  1550. device_format = AFMT_S16_BE;
  1551. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  1552. stream->doByteSwap[mode] = true;
  1553. }
  1554. #else
  1555. else if (mask & AFMT_S16_LE) {
  1556. device_format = AFMT_S16_LE;
  1557. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  1558. stream->doByteSwap[mode] = true;
  1559. }
  1560. #endif
  1561. #if defined (AFMT_S32_NE) && defined (AFMT_S32_LE) && defined (AFMT_S32_BE)
  1562. else if (mask & AFMT_S32_NE) {
  1563. device_format = AFMT_S32_NE;
  1564. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  1565. }
  1566. #if BYTE_ORDER == LITTLE_ENDIAN
  1567. else if (mask & AFMT_S32_BE) {
  1568. device_format = AFMT_S32_BE;
  1569. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  1570. stream->doByteSwap[mode] = true;
  1571. }
  1572. #else
  1573. else if (mask & AFMT_S32_LE) {
  1574. device_format = AFMT_S32_LE;
  1575. stream->deviceFormat[mode] = RTAUDIO_SINT32;
  1576. stream->doByteSwap[mode] = true;
  1577. }
  1578. #endif
  1579. #endif
  1580. else if (mask & AFMT_S8) {
  1581. device_format = AFMT_S8;
  1582. stream->deviceFormat[mode] = RTAUDIO_SINT8;
  1583. }
  1584. }
  1585. if (stream->deviceFormat[mode] == 0) {
  1586. // This really shouldn't happen ...
  1587. close(fd);
  1588. sprintf(message, "RtAudio: OSS device (%s) data format not supported by RtAudio.",
  1589. name);
  1590. goto error;
  1591. }
  1592. // Determine the number of channels for this device. Note that the
  1593. // channel value requested by the user might be < min_X_Channels.
  1594. stream->nUserChannels[mode] = channels;
  1595. device_channels = channels;
  1596. if (mode == PLAYBACK) {
  1597. if (channels < devices[device].minOutputChannels)
  1598. device_channels = devices[device].minOutputChannels;
  1599. }
  1600. else { // mode == RECORD
  1601. if (stream->mode == PLAYBACK && stream->device[0] == device) {
  1602. // We're doing duplex setup here.
  1603. if (channels < devices[device].minDuplexChannels)
  1604. device_channels = devices[device].minDuplexChannels;
  1605. }
  1606. else {
  1607. if (channels < devices[device].minInputChannels)
  1608. device_channels = devices[device].minInputChannels;
  1609. }
  1610. }
  1611. stream->nDeviceChannels[mode] = device_channels;
  1612. // Attempt to set the buffer size. According to OSS, the minimum
  1613. // number of buffers is two. The supposed minimum buffer size is 16
  1614. // bytes, so that will be our lower bound. The argument to this
  1615. // call is in the form 0xMMMMSSSS (hex), where the buffer size (in
  1616. // bytes) is given as 2^SSSS and the number of buffers as 2^MMMM.
  1617. // We'll check the actual value used near the end of the setup
  1618. // procedure.
  1619. buffer_bytes = *bufferSize * formatBytes(stream->deviceFormat[mode]) * device_channels;
  1620. if (buffer_bytes < 16) buffer_bytes = 16;
  1621. buffers = numberOfBuffers;
  1622. if (buffers < 2) buffers = 2;
  1623. temp = ((int) buffers << 16) + (int)(log10((double)buffer_bytes)/log10(2.0));
  1624. if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &temp)) {
  1625. close(fd);
  1626. sprintf(message, "RtAudio: OSS error setting fragment size for device (%s).",
  1627. name);
  1628. goto error;
  1629. }
  1630. stream->nBuffers = buffers;
  1631. // Set the data format.
  1632. temp = device_format;
  1633. if (ioctl(fd, SNDCTL_DSP_SETFMT, &device_format) == -1 || device_format != temp) {
  1634. close(fd);
  1635. sprintf(message, "RtAudio: OSS error setting data format for device (%s).",
  1636. name);
  1637. goto error;
  1638. }
  1639. // Set the number of channels.
  1640. temp = device_channels;
  1641. if (ioctl(fd, SNDCTL_DSP_CHANNELS, &device_channels) == -1 || device_channels != temp) {
  1642. close(fd);
  1643. sprintf(message, "RtAudio: OSS error setting %d channels on device (%s).",
  1644. temp, name);
  1645. goto error;
  1646. }
  1647. // Set the sample rate.
  1648. srate = sampleRate;
  1649. temp = srate;
  1650. if (ioctl(fd, SNDCTL_DSP_SPEED, &srate) == -1) {
  1651. close(fd);
  1652. sprintf(message, "RtAudio: OSS error setting sample rate = %d on device (%s).",
  1653. temp, name);
  1654. goto error;
  1655. }
  1656. // Verify the sample rate setup worked.
  1657. if (abs(srate - temp) > 100) {
  1658. close(fd);
  1659. sprintf(message, "RtAudio: OSS error ... audio device (%s) doesn't support sample rate of %d.",
  1660. name, temp);
  1661. goto error;
  1662. }
  1663. stream->sampleRate = sampleRate;
  1664. if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &buffer_bytes) == -1) {
  1665. close(fd);
  1666. sprintf(message, "RtAudio: OSS error getting buffer size for device (%s).",
  1667. name);
  1668. goto error;
  1669. }
  1670. // Save buffer size (in sample frames).
  1671. *bufferSize = buffer_bytes / (formatBytes(stream->deviceFormat[mode]) * device_channels);
  1672. stream->bufferSize = *bufferSize;
  1673. if (mode == RECORD && stream->mode == PLAYBACK &&
  1674. stream->device[0] == device) {
  1675. // We're doing duplex setup here.
  1676. stream->deviceFormat[0] = stream->deviceFormat[1];
  1677. stream->nDeviceChannels[0] = device_channels;
  1678. }
  1679. // Set flags for buffer conversion
  1680. stream->doConvertBuffer[mode] = false;
  1681. if (stream->userFormat != stream->deviceFormat[mode])
  1682. stream->doConvertBuffer[mode] = true;
  1683. if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
  1684. stream->doConvertBuffer[mode] = true;
  1685. // Allocate necessary internal buffers
  1686. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  1687. long buffer_bytes;
  1688. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  1689. buffer_bytes = stream->nUserChannels[0];
  1690. else
  1691. buffer_bytes = stream->nUserChannels[1];
  1692. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  1693. if (stream->userBuffer) free(stream->userBuffer);
  1694. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  1695. if (stream->userBuffer == NULL) {
  1696. close(fd);
  1697. sprintf(message, "RtAudio: OSS error allocating user buffer memory (%s).",
  1698. name);
  1699. goto error;
  1700. }
  1701. }
  1702. if ( stream->doConvertBuffer[mode] ) {
  1703. long buffer_bytes;
  1704. bool makeBuffer = true;
  1705. if ( mode == PLAYBACK )
  1706. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  1707. else { // mode == RECORD
  1708. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  1709. if ( stream->mode == PLAYBACK ) {
  1710. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  1711. if ( buffer_bytes > bytes_out )
  1712. buffer_bytes = (buffer_bytes > bytes_out) ? buffer_bytes : bytes_out;
  1713. else
  1714. makeBuffer = false;
  1715. }
  1716. }
  1717. if ( makeBuffer ) {
  1718. buffer_bytes *= *bufferSize;
  1719. if (stream->deviceBuffer) free(stream->deviceBuffer);
  1720. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  1721. if (stream->deviceBuffer == NULL) {
  1722. close(fd);
  1723. free(stream->userBuffer);
  1724. sprintf(message, "RtAudio: OSS error allocating device buffer memory (%s).",
  1725. name);
  1726. goto error;
  1727. }
  1728. }
  1729. }
  1730. stream->device[mode] = device;
  1731. stream->handle[mode] = fd;
  1732. stream->state = STREAM_STOPPED;
  1733. if ( stream->mode == PLAYBACK && mode == RECORD ) {
  1734. stream->mode = DUPLEX;
  1735. if (stream->device[0] == device)
  1736. stream->handle[0] = fd;
  1737. }
  1738. else
  1739. stream->mode = mode;
  1740. return SUCCESS;
  1741. error:
  1742. if (stream->handle[0]) {
  1743. close(stream->handle[0]);
  1744. stream->handle[0] = 0;
  1745. }
  1746. error(RtAudioError::WARNING);
  1747. return FAILURE;
  1748. }
  1749. void RtAudio :: cancelStreamCallback(int streamID)
  1750. {
  1751. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  1752. if (stream->usingCallback) {
  1753. stream->usingCallback = false;
  1754. pthread_cancel(stream->thread);
  1755. pthread_join(stream->thread, NULL);
  1756. stream->thread = 0;
  1757. stream->callback = NULL;
  1758. stream->userData = NULL;
  1759. }
  1760. }
  1761. void RtAudio :: closeStream(int streamID)
  1762. {
  1763. // We don't want an exception to be thrown here because this
  1764. // function is called by our class destructor. So, do our own
  1765. // streamID check.
  1766. if ( streams.find( streamID ) == streams.end() ) {
  1767. sprintf(message, "RtAudio: invalid stream identifier!");
  1768. error(RtAudioError::WARNING);
  1769. return;
  1770. }
  1771. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamID];
  1772. if (stream->usingCallback) {
  1773. pthread_cancel(stream->thread);
  1774. pthread_join(stream->thread, NULL);
  1775. }
  1776. if (stream->state == STREAM_RUNNING) {
  1777. if (stream->mode == PLAYBACK || stream->mode == DUPLEX)
  1778. ioctl(stream->handle[0], SNDCTL_DSP_RESET, 0);
  1779. if (stream->mode == RECORD || stream->mode == DUPLEX)
  1780. ioctl(stream->handle[1], SNDCTL_DSP_RESET, 0);
  1781. }
  1782. pthread_mutex_destroy(&stream->mutex);
  1783. if (stream->handle[0])
  1784. close(stream->handle[0]);
  1785. if (stream->handle[1])
  1786. close(stream->handle[1]);
  1787. if (stream->userBuffer)
  1788. free(stream->userBuffer);
  1789. if (stream->deviceBuffer)
  1790. free(stream->deviceBuffer);
  1791. free(stream);
  1792. streams.erase(streamID);
  1793. }
  1794. void RtAudio :: startStream(int streamID)
  1795. {
  1796. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  1797. stream->state = STREAM_RUNNING;
  1798. // No need to do anything else here ... OSS automatically starts when fed samples.
  1799. }
  1800. void RtAudio :: stopStream(int streamID)
  1801. {
  1802. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  1803. MUTEX_LOCK(&stream->mutex);
  1804. if (stream->state == STREAM_STOPPED)
  1805. goto unlock;
  1806. int err;
  1807. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  1808. err = ioctl(stream->handle[0], SNDCTL_DSP_SYNC, 0);
  1809. if (err < -1) {
  1810. sprintf(message, "RtAudio: OSS error stopping device (%s).",
  1811. devices[stream->device[0]].name);
  1812. error(RtAudioError::DRIVER_ERROR);
  1813. }
  1814. }
  1815. else {
  1816. err = ioctl(stream->handle[1], SNDCTL_DSP_SYNC, 0);
  1817. if (err < -1) {
  1818. sprintf(message, "RtAudio: OSS error stopping device (%s).",
  1819. devices[stream->device[1]].name);
  1820. error(RtAudioError::DRIVER_ERROR);
  1821. }
  1822. }
  1823. stream->state = STREAM_STOPPED;
  1824. unlock:
  1825. MUTEX_UNLOCK(&stream->mutex);
  1826. }
  1827. void RtAudio :: abortStream(int streamID)
  1828. {
  1829. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  1830. MUTEX_LOCK(&stream->mutex);
  1831. if (stream->state == STREAM_STOPPED)
  1832. goto unlock;
  1833. int err;
  1834. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  1835. err = ioctl(stream->handle[0], SNDCTL_DSP_RESET, 0);
  1836. if (err < -1) {
  1837. sprintf(message, "RtAudio: OSS error aborting device (%s).",
  1838. devices[stream->device[0]].name);
  1839. error(RtAudioError::DRIVER_ERROR);
  1840. }
  1841. }
  1842. else {
  1843. err = ioctl(stream->handle[1], SNDCTL_DSP_RESET, 0);
  1844. if (err < -1) {
  1845. sprintf(message, "RtAudio: OSS error aborting device (%s).",
  1846. devices[stream->device[1]].name);
  1847. error(RtAudioError::DRIVER_ERROR);
  1848. }
  1849. }
  1850. stream->state = STREAM_STOPPED;
  1851. unlock:
  1852. MUTEX_UNLOCK(&stream->mutex);
  1853. }
  1854. int RtAudio :: streamWillBlock(int streamID)
  1855. {
  1856. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  1857. MUTEX_LOCK(&stream->mutex);
  1858. int bytes, channels = 0, frames = 0;
  1859. if (stream->state == STREAM_STOPPED)
  1860. goto unlock;
  1861. audio_buf_info info;
  1862. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  1863. ioctl(stream->handle[0], SNDCTL_DSP_GETOSPACE, &info);
  1864. bytes = info.bytes;
  1865. channels = stream->nDeviceChannels[0];
  1866. }
  1867. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  1868. ioctl(stream->handle[1], SNDCTL_DSP_GETISPACE, &info);
  1869. if (stream->mode == DUPLEX ) {
  1870. bytes = (bytes < info.bytes) ? bytes : info.bytes;
  1871. channels = stream->nDeviceChannels[0];
  1872. }
  1873. else {
  1874. bytes = info.bytes;
  1875. channels = stream->nDeviceChannels[1];
  1876. }
  1877. }
  1878. frames = (int) (bytes / (channels * formatBytes(stream->deviceFormat[0])));
  1879. frames -= stream->bufferSize;
  1880. if (frames < 0) frames = 0;
  1881. unlock:
  1882. MUTEX_UNLOCK(&stream->mutex);
  1883. return frames;
  1884. }
  1885. void RtAudio :: tickStream(int streamID)
  1886. {
  1887. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  1888. int stopStream = 0;
  1889. if (stream->state == STREAM_STOPPED) {
  1890. if (stream->usingCallback) usleep(50000); // sleep 50 milliseconds
  1891. return;
  1892. }
  1893. else if (stream->usingCallback) {
  1894. stopStream = stream->callback(stream->userBuffer, stream->bufferSize, stream->userData);
  1895. }
  1896. MUTEX_LOCK(&stream->mutex);
  1897. // The state might change while waiting on a mutex.
  1898. if (stream->state == STREAM_STOPPED)
  1899. goto unlock;
  1900. int result;
  1901. char *buffer;
  1902. int samples;
  1903. RTAUDIO_FORMAT format;
  1904. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  1905. // Setup parameters and do buffer conversion if necessary.
  1906. if (stream->doConvertBuffer[0]) {
  1907. convertStreamBuffer(stream, PLAYBACK);
  1908. buffer = stream->deviceBuffer;
  1909. samples = stream->bufferSize * stream->nDeviceChannels[0];
  1910. format = stream->deviceFormat[0];
  1911. }
  1912. else {
  1913. buffer = stream->userBuffer;
  1914. samples = stream->bufferSize * stream->nUserChannels[0];
  1915. format = stream->userFormat;
  1916. }
  1917. // Do byte swapping if necessary.
  1918. if (stream->doByteSwap[0])
  1919. byteSwapBuffer(buffer, samples, format);
  1920. // Write samples to device.
  1921. result = write(stream->handle[0], buffer, samples * formatBytes(format));
  1922. if (result == -1) {
  1923. // This could be an underrun, but the basic OSS API doesn't provide a means for determining that.
  1924. sprintf(message, "RtAudio: OSS audio write error for device (%s).",
  1925. devices[stream->device[0]].name);
  1926. error(RtAudioError::DRIVER_ERROR);
  1927. }
  1928. }
  1929. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  1930. // Setup parameters.
  1931. if (stream->doConvertBuffer[1]) {
  1932. buffer = stream->deviceBuffer;
  1933. samples = stream->bufferSize * stream->nDeviceChannels[1];
  1934. format = stream->deviceFormat[1];
  1935. }
  1936. else {
  1937. buffer = stream->userBuffer;
  1938. samples = stream->bufferSize * stream->nUserChannels[1];
  1939. format = stream->userFormat;
  1940. }
  1941. // Read samples from device.
  1942. result = read(stream->handle[1], buffer, samples * formatBytes(format));
  1943. if (result == -1) {
  1944. // This could be an overrun, but the basic OSS API doesn't provide a means for determining that.
  1945. sprintf(message, "RtAudio: OSS audio read error for device (%s).",
  1946. devices[stream->device[1]].name);
  1947. error(RtAudioError::DRIVER_ERROR);
  1948. }
  1949. // Do byte swapping if necessary.
  1950. if (stream->doByteSwap[1])
  1951. byteSwapBuffer(buffer, samples, format);
  1952. // Do buffer conversion if necessary.
  1953. if (stream->doConvertBuffer[1])
  1954. convertStreamBuffer(stream, RECORD);
  1955. }
  1956. unlock:
  1957. MUTEX_UNLOCK(&stream->mutex);
  1958. if (stream->usingCallback && stopStream)
  1959. this->stopStream(streamID);
  1960. }
  1961. extern "C" void *callbackHandler(void *ptr)
  1962. {
  1963. RtAudio *object = thread_info.object;
  1964. int stream = thread_info.streamID;
  1965. bool *usingCallback = (bool *) ptr;
  1966. while ( *usingCallback ) {
  1967. pthread_testcancel();
  1968. try {
  1969. object->tickStream(stream);
  1970. }
  1971. catch (RtAudioError &exception) {
  1972. fprintf(stderr, "\nCallback thread error (%s) ... closing thread.\n\n",
  1973. exception.getMessage());
  1974. break;
  1975. }
  1976. }
  1977. return 0;
  1978. }
  1979. //******************** End of __LINUX_OSS_ *********************//
  1980. #elif defined(__WINDOWS_DS_) // Windows DirectSound API
  1981. #include <dsound.h>
  1982. // Declarations for utility functions, callbacks, and structures
  1983. // specific to the DirectSound implementation.
  1984. static bool CALLBACK deviceCountCallback(LPGUID lpguid,
  1985. LPCSTR lpcstrDescription,
  1986. LPCSTR lpcstrModule,
  1987. LPVOID lpContext);
  1988. static bool CALLBACK deviceInfoCallback(LPGUID lpguid,
  1989. LPCSTR lpcstrDescription,
  1990. LPCSTR lpcstrModule,
  1991. LPVOID lpContext);
  1992. static char* getErrorString(int code);
  1993. struct enum_info {
  1994. char name[64];
  1995. LPGUID id;
  1996. bool isInput;
  1997. bool isValid;
  1998. };
  1999. // RtAudio methods for DirectSound implementation.
  2000. void RtAudio :: initialize(void)
  2001. {
  2002. int i, ins = 0, outs = 0, count = 0;
  2003. int index = 0;
  2004. HRESULT result;
  2005. nDevices = 0;
  2006. // Count DirectSound devices.
  2007. result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceCountCallback, &outs);
  2008. if ( FAILED(result) ) {
  2009. sprintf(message, "RtAudio: Unable to enumerate through sound playback devices: %s.",
  2010. getErrorString(result));
  2011. error(RtAudioError::DRIVER_ERROR);
  2012. }
  2013. // Count DirectSoundCapture devices.
  2014. result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceCountCallback, &ins);
  2015. if ( FAILED(result) ) {
  2016. sprintf(message, "RtAudio: Unable to enumerate through sound capture devices: %s.",
  2017. getErrorString(result));
  2018. error(RtAudioError::DRIVER_ERROR);
  2019. }
  2020. count = ins + outs;
  2021. if (count == 0) return;
  2022. std::vector<enum_info> info(count);
  2023. for (i=0; i<count; i++) {
  2024. info[i].name[0] = '\0';
  2025. if (i < outs) info[i].isInput = false;
  2026. else info[i].isInput = true;
  2027. }
  2028. // Get playback device info and check capabilities.
  2029. result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceInfoCallback, &info[0]);
  2030. if ( FAILED(result) ) {
  2031. sprintf(message, "RtAudio: Unable to enumerate through sound playback devices: %s.",
  2032. getErrorString(result));
  2033. error(RtAudioError::DRIVER_ERROR);
  2034. }
  2035. // Get capture device info and check capabilities.
  2036. result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceInfoCallback, &info[0]);
  2037. if ( FAILED(result) ) {
  2038. sprintf(message, "RtAudio: Unable to enumerate through sound capture devices: %s.",
  2039. getErrorString(result));
  2040. error(RtAudioError::DRIVER_ERROR);
  2041. }
  2042. // Parse the devices and check validity. Devices are considered
  2043. // invalid if they cannot be opened, they report no supported data
  2044. // formats, or they report < 1 supported channels.
  2045. for (i=0; i<count; i++) {
  2046. if (info[i].isValid && info[i].id == NULL ) // default device
  2047. nDevices++;
  2048. }
  2049. // We group the default input and output devices together (as one
  2050. // device) .
  2051. if (nDevices > 0) {
  2052. nDevices = 1;
  2053. index = 1;
  2054. }
  2055. // Non-default devices are listed separately.
  2056. for (i=0; i<count; i++) {
  2057. if (info[i].isValid && info[i].id != NULL )
  2058. nDevices++;
  2059. }
  2060. if (nDevices == 0) return;
  2061. // Allocate the RTAUDIO_DEVICE structures.
  2062. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  2063. if (devices == NULL) {
  2064. sprintf(message, "RtAudio: memory allocation error!");
  2065. error(RtAudioError::MEMORY_ERROR);
  2066. }
  2067. // Initialize the GUIDs to NULL for later validation.
  2068. for (i=0; i<nDevices; i++) {
  2069. devices[i].id[0] = NULL;
  2070. devices[i].id[1] = NULL;
  2071. }
  2072. // Rename the default device(s).
  2073. if (index)
  2074. strcpy(devices[0].name, "Default Input/Output Devices");
  2075. // Copy the names and GUIDs to our devices structures.
  2076. for (i=0; i<count; i++) {
  2077. if (info[i].isValid && info[i].id != NULL ) {
  2078. strncpy(devices[index].name, info[i].name, 64);
  2079. if (info[i].isInput)
  2080. devices[index].id[1] = info[i].id;
  2081. else
  2082. devices[index].id[0] = info[i].id;
  2083. index++;
  2084. }
  2085. }
  2086. for (i=0;i<nDevices; i++)
  2087. probeDeviceInfo(&devices[i]);
  2088. return;
  2089. }
  2090. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  2091. {
  2092. HRESULT result;
  2093. // Get the device index so that we can check the device handle.
  2094. int index;
  2095. for (index=0; index<nDevices; index++)
  2096. if ( info == &devices[index] ) break;
  2097. if ( index >= nDevices ) {
  2098. sprintf(message, "RtAudio: device (%s) indexing error in DirectSound probeDeviceInfo().",
  2099. info->name);
  2100. error(RtAudioError::WARNING);
  2101. return;
  2102. }
  2103. // Do capture probe first. If this is not the default device (index
  2104. // = 0) _and_ GUID = NULL, then the capture handle is invalid.
  2105. if ( index != 0 && info->id[1] == NULL )
  2106. goto playback_probe;
  2107. LPDIRECTSOUNDCAPTURE input;
  2108. result = DirectSoundCaptureCreate( info->id[0], &input, NULL );
  2109. if ( FAILED(result) ) {
  2110. sprintf(message, "RtAudio: Could not create DirectSound capture object (%s): %s.",
  2111. info->name, getErrorString(result));
  2112. error(RtAudioError::WARNING);
  2113. goto playback_probe;
  2114. }
  2115. DSCCAPS in_caps;
  2116. in_caps.dwSize = sizeof(in_caps);
  2117. result = input->GetCaps( &in_caps );
  2118. if ( FAILED(result) ) {
  2119. input->Release();
  2120. sprintf(message, "RtAudio: Could not get DirectSound capture capabilities (%s): %s.",
  2121. info->name, getErrorString(result));
  2122. error(RtAudioError::WARNING);
  2123. goto playback_probe;
  2124. }
  2125. // Get input channel information.
  2126. info->minInputChannels = 1;
  2127. info->maxInputChannels = in_caps.dwChannels;
  2128. // Get sample rate and format information.
  2129. if( in_caps.dwChannels == 2 ) {
  2130. if( in_caps.dwFormats & WAVE_FORMAT_1S16 ) info->nativeFormats |= RTAUDIO_SINT16;
  2131. if( in_caps.dwFormats & WAVE_FORMAT_2S16 ) info->nativeFormats |= RTAUDIO_SINT16;
  2132. if( in_caps.dwFormats & WAVE_FORMAT_4S16 ) info->nativeFormats |= RTAUDIO_SINT16;
  2133. if( in_caps.dwFormats & WAVE_FORMAT_1S08 ) info->nativeFormats |= RTAUDIO_SINT8;
  2134. if( in_caps.dwFormats & WAVE_FORMAT_2S08 ) info->nativeFormats |= RTAUDIO_SINT8;
  2135. if( in_caps.dwFormats & WAVE_FORMAT_4S08 ) info->nativeFormats |= RTAUDIO_SINT8;
  2136. if ( info->nativeFormats & RTAUDIO_SINT16 ) {
  2137. if( in_caps.dwFormats & WAVE_FORMAT_1S16 ) info->sampleRates[info->nSampleRates++] = 11025;
  2138. if( in_caps.dwFormats & WAVE_FORMAT_2S16 ) info->sampleRates[info->nSampleRates++] = 22050;
  2139. if( in_caps.dwFormats & WAVE_FORMAT_4S16 ) info->sampleRates[info->nSampleRates++] = 44100;
  2140. }
  2141. else if ( info->nativeFormats & RTAUDIO_SINT8 ) {
  2142. if( in_caps.dwFormats & WAVE_FORMAT_1S08 ) info->sampleRates[info->nSampleRates++] = 11025;
  2143. if( in_caps.dwFormats & WAVE_FORMAT_2S08 ) info->sampleRates[info->nSampleRates++] = 22050;
  2144. if( in_caps.dwFormats & WAVE_FORMAT_4S08 ) info->sampleRates[info->nSampleRates++] = 44100;
  2145. }
  2146. }
  2147. else if ( in_caps.dwChannels == 1 ) {
  2148. if( in_caps.dwFormats & WAVE_FORMAT_1M16 ) info->nativeFormats |= RTAUDIO_SINT16;
  2149. if( in_caps.dwFormats & WAVE_FORMAT_2M16 ) info->nativeFormats |= RTAUDIO_SINT16;
  2150. if( in_caps.dwFormats & WAVE_FORMAT_4M16 ) info->nativeFormats |= RTAUDIO_SINT16;
  2151. if( in_caps.dwFormats & WAVE_FORMAT_1M08 ) info->nativeFormats |= RTAUDIO_SINT8;
  2152. if( in_caps.dwFormats & WAVE_FORMAT_2M08 ) info->nativeFormats |= RTAUDIO_SINT8;
  2153. if( in_caps.dwFormats & WAVE_FORMAT_4M08 ) info->nativeFormats |= RTAUDIO_SINT8;
  2154. if ( info->nativeFormats & RTAUDIO_SINT16 ) {
  2155. if( in_caps.dwFormats & WAVE_FORMAT_1M16 ) info->sampleRates[info->nSampleRates++] = 11025;
  2156. if( in_caps.dwFormats & WAVE_FORMAT_2M16 ) info->sampleRates[info->nSampleRates++] = 22050;
  2157. if( in_caps.dwFormats & WAVE_FORMAT_4M16 ) info->sampleRates[info->nSampleRates++] = 44100;
  2158. }
  2159. else if ( info->nativeFormats & RTAUDIO_SINT8 ) {
  2160. if( in_caps.dwFormats & WAVE_FORMAT_1M08 ) info->sampleRates[info->nSampleRates++] = 11025;
  2161. if( in_caps.dwFormats & WAVE_FORMAT_2M08 ) info->sampleRates[info->nSampleRates++] = 22050;
  2162. if( in_caps.dwFormats & WAVE_FORMAT_4M08 ) info->sampleRates[info->nSampleRates++] = 44100;
  2163. }
  2164. }
  2165. else info->minInputChannels = 0; // technically, this would be an error
  2166. input->Release();
  2167. playback_probe:
  2168. LPDIRECTSOUND output;
  2169. DSCAPS out_caps;
  2170. // Now do playback probe. If this is not the default device (index
  2171. // = 0) _and_ GUID = NULL, then the playback handle is invalid.
  2172. if ( index != 0 && info->id[0] == NULL )
  2173. goto check_parameters;
  2174. result = DirectSoundCreate( info->id[0], &output, NULL );
  2175. if ( FAILED(result) ) {
  2176. sprintf(message, "RtAudio: Could not create DirectSound playback object (%s): %s.",
  2177. info->name, getErrorString(result));
  2178. error(RtAudioError::WARNING);
  2179. goto check_parameters;
  2180. }
  2181. out_caps.dwSize = sizeof(out_caps);
  2182. result = output->GetCaps( &out_caps );
  2183. if ( FAILED(result) ) {
  2184. output->Release();
  2185. sprintf(message, "RtAudio: Could not get DirectSound playback capabilities (%s): %s.",
  2186. info->name, getErrorString(result));
  2187. error(RtAudioError::WARNING);
  2188. goto check_parameters;
  2189. }
  2190. // Get output channel information.
  2191. info->minOutputChannels = 1;
  2192. info->maxOutputChannels = ( out_caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1;
  2193. // Get sample rate information. Use capture device rate information
  2194. // if it exists.
  2195. if ( info->nSampleRates == 0 ) {
  2196. info->sampleRates[0] = (int) out_caps.dwMinSecondarySampleRate;
  2197. info->sampleRates[1] = (int) out_caps.dwMaxSecondarySampleRate;
  2198. if ( out_caps.dwFlags & DSCAPS_CONTINUOUSRATE )
  2199. info->nSampleRates = -1;
  2200. else if ( out_caps.dwMinSecondarySampleRate == out_caps.dwMaxSecondarySampleRate ) {
  2201. if ( out_caps.dwMinSecondarySampleRate == 0 ) {
  2202. // This is a bogus driver report ... fake the range and cross
  2203. // your fingers.
  2204. info->sampleRates[0] = 11025;
  2205. info->sampleRates[1] = 48000;
  2206. info->nSampleRates = -1; /* continuous range */
  2207. sprintf(message, "RtAudio: bogus sample rates reported by DirectSound driver ... using defaults (%s).",
  2208. info->name);
  2209. error(RtAudioError::WARNING);
  2210. }
  2211. else {
  2212. info->nSampleRates = 1;
  2213. }
  2214. }
  2215. else if ( (out_caps.dwMinSecondarySampleRate < 1000.0) &&
  2216. (out_caps.dwMaxSecondarySampleRate > 50000.0) ) {
  2217. // This is a bogus driver report ... support for only two
  2218. // distant rates. We'll assume this is a range.
  2219. info->nSampleRates = -1;
  2220. sprintf(message, "RtAudio: bogus sample rates reported by DirectSound driver ... using range (%s).",
  2221. info->name);
  2222. error(RtAudioError::WARNING);
  2223. }
  2224. else info->nSampleRates = 2;
  2225. }
  2226. else {
  2227. // Check input rates against output rate range
  2228. for ( int i=info->nSampleRates-1; i>=0; i-- ) {
  2229. if ( info->sampleRates[i] <= out_caps.dwMaxSecondarySampleRate )
  2230. break;
  2231. info->nSampleRates--;
  2232. }
  2233. while ( info->sampleRates[0] < out_caps.dwMinSecondarySampleRate ) {
  2234. info->nSampleRates--;
  2235. for ( int i=0; i<info->nSampleRates; i++)
  2236. info->sampleRates[i] = info->sampleRates[i+1];
  2237. if ( info->nSampleRates <= 0 ) break;
  2238. }
  2239. }
  2240. // Get format information.
  2241. if ( out_caps.dwFlags & DSCAPS_PRIMARY16BIT ) info->nativeFormats |= RTAUDIO_SINT16;
  2242. if ( out_caps.dwFlags & DSCAPS_PRIMARY8BIT ) info->nativeFormats |= RTAUDIO_SINT8;
  2243. output->Release();
  2244. check_parameters:
  2245. if ( info->maxInputChannels == 0 && info->maxOutputChannels == 0 )
  2246. return;
  2247. if ( info->nSampleRates == 0 || info->nativeFormats == 0 )
  2248. return;
  2249. // Determine duplex status.
  2250. if (info->maxInputChannels < info->maxOutputChannels)
  2251. info->maxDuplexChannels = info->maxInputChannels;
  2252. else
  2253. info->maxDuplexChannels = info->maxOutputChannels;
  2254. if (info->minInputChannels < info->minOutputChannels)
  2255. info->minDuplexChannels = info->minInputChannels;
  2256. else
  2257. info->minDuplexChannels = info->minOutputChannels;
  2258. if ( info->maxDuplexChannels > 0 ) info->hasDuplexSupport = true;
  2259. else info->hasDuplexSupport = false;
  2260. info->probed = true;
  2261. return;
  2262. }
  2263. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  2264. STREAM_MODE mode, int channels,
  2265. int sampleRate, RTAUDIO_FORMAT format,
  2266. int *bufferSize, int numberOfBuffers)
  2267. {
  2268. HRESULT result;
  2269. HWND hWnd = GetForegroundWindow();
  2270. // According to a note in PortAudio, using GetDesktopWindow()
  2271. // instead of GetForegroundWindow() is supposed to avoid problems
  2272. // that occur when the application's window is not the foreground
  2273. // window. Also, if the application window closes before the
  2274. // DirectSound buffer, DirectSound can crash. However, for console
  2275. // applications, no sound was produced when using GetDesktopWindow().
  2276. long buffer_size;
  2277. LPVOID audioPtr;
  2278. DWORD dataLen;
  2279. int nBuffers;
  2280. // Check the numberOfBuffers parameter and limit the lowest value to
  2281. // two. This is a judgement call and a value of two is probably too
  2282. // low for capture, but it should work for playback.
  2283. if (numberOfBuffers < 2)
  2284. nBuffers = 2;
  2285. else
  2286. nBuffers = numberOfBuffers;
  2287. // Define the wave format structure (16-bit PCM, srate, channels)
  2288. WAVEFORMATEX waveFormat;
  2289. ZeroMemory(&waveFormat, sizeof(WAVEFORMATEX));
  2290. waveFormat.wFormatTag = WAVE_FORMAT_PCM;
  2291. waveFormat.nChannels = channels;
  2292. waveFormat.nSamplesPerSec = (unsigned long) sampleRate;
  2293. // Determine the data format.
  2294. if ( devices[device].nativeFormats ) { // 8-bit and/or 16-bit support
  2295. if ( format == RTAUDIO_SINT8 ) {
  2296. if ( devices[device].nativeFormats & RTAUDIO_SINT8 )
  2297. waveFormat.wBitsPerSample = 8;
  2298. else
  2299. waveFormat.wBitsPerSample = 16;
  2300. }
  2301. else {
  2302. if ( devices[device].nativeFormats & RTAUDIO_SINT16 )
  2303. waveFormat.wBitsPerSample = 16;
  2304. else
  2305. waveFormat.wBitsPerSample = 8;
  2306. }
  2307. }
  2308. else {
  2309. sprintf(message, "RtAudio: no reported data formats for DirectSound device (%s).",
  2310. devices[device].name);
  2311. error(RtAudioError::WARNING);
  2312. return FAILURE;
  2313. }
  2314. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
  2315. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  2316. if ( mode == PLAYBACK ) {
  2317. LPGUID id = devices[device].id[0];
  2318. LPDIRECTSOUND object;
  2319. LPDIRECTSOUNDBUFFER buffer;
  2320. DSBUFFERDESC bufferDescription;
  2321. result = DirectSoundCreate( id, &object, NULL );
  2322. if ( FAILED(result) ) {
  2323. sprintf(message, "RtAudio: Could not create DirectSound playback object (%s): %s.",
  2324. devices[device].name, getErrorString(result));
  2325. error(RtAudioError::WARNING);
  2326. return FAILURE;
  2327. }
  2328. // Set cooperative level to DSSCL_EXCLUSIVE
  2329. result = object->SetCooperativeLevel(hWnd, DSSCL_EXCLUSIVE);
  2330. if ( FAILED(result) ) {
  2331. object->Release();
  2332. sprintf(message, "RtAudio: Unable to set DirectSound cooperative level (%s): %s.",
  2333. devices[device].name, getErrorString(result));
  2334. error(RtAudioError::WARNING);
  2335. return FAILURE;
  2336. }
  2337. // Even though we will write to the secondary buffer, we need to
  2338. // access the primary buffer to set the correct output format.
  2339. // The default is 8-bit, 22 kHz!
  2340. // Setup the DS primary buffer description.
  2341. ZeroMemory(&bufferDescription, sizeof(DSBUFFERDESC));
  2342. bufferDescription.dwSize = sizeof(DSBUFFERDESC);
  2343. bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;
  2344. // Obtain the primary buffer
  2345. result = object->CreateSoundBuffer(&bufferDescription, &buffer, NULL);
  2346. if ( FAILED(result) ) {
  2347. object->Release();
  2348. sprintf(message, "RtAudio: Unable to access DS primary buffer (%s): %s.",
  2349. devices[device].name, getErrorString(result));
  2350. error(RtAudioError::WARNING);
  2351. return FAILURE;
  2352. }
  2353. // Set the primary DS buffer sound format.
  2354. result = buffer->SetFormat(&waveFormat);
  2355. if ( FAILED(result) ) {
  2356. object->Release();
  2357. sprintf(message, "RtAudio: Unable to set DS primary buffer format (%s): %s.",
  2358. devices[device].name, getErrorString(result));
  2359. error(RtAudioError::WARNING);
  2360. return FAILURE;
  2361. }
  2362. // Setup the secondary DS buffer description.
  2363. buffer_size = channels * *bufferSize * nBuffers * waveFormat.wBitsPerSample / 8;
  2364. ZeroMemory(&bufferDescription, sizeof(DSBUFFERDESC));
  2365. bufferDescription.dwSize = sizeof(DSBUFFERDESC);
  2366. bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
  2367. DSBCAPS_GETCURRENTPOSITION2 |
  2368. DSBCAPS_LOCHARDWARE ); // Force hardware mixing
  2369. bufferDescription.dwBufferBytes = buffer_size;
  2370. bufferDescription.lpwfxFormat = &waveFormat;
  2371. // Try to create the secondary DS buffer. If that doesn't work,
  2372. // try to use software mixing. Otherwise, there's a problem.
  2373. result = object->CreateSoundBuffer(&bufferDescription, &buffer, NULL);
  2374. if ( FAILED(result) ) {
  2375. bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
  2376. DSBCAPS_GETCURRENTPOSITION2 |
  2377. DSBCAPS_LOCSOFTWARE ); // Force software mixing
  2378. result = object->CreateSoundBuffer(&bufferDescription, &buffer, NULL);
  2379. if ( FAILED(result) ) {
  2380. object->Release();
  2381. sprintf(message, "RtAudio: Unable to create secondary DS buffer (%s): %s.",
  2382. devices[device].name, getErrorString(result));
  2383. error(RtAudioError::WARNING);
  2384. return FAILURE;
  2385. }
  2386. }
  2387. // Get the buffer size ... might be different from what we specified.
  2388. DSBCAPS dsbcaps;
  2389. dsbcaps.dwSize = sizeof(DSBCAPS);
  2390. buffer->GetCaps(&dsbcaps);
  2391. buffer_size = dsbcaps.dwBufferBytes;
  2392. // Lock the DS buffer
  2393. result = buffer->Lock(0, buffer_size, &audioPtr, &dataLen, NULL, NULL, 0);
  2394. if ( FAILED(result) ) {
  2395. object->Release();
  2396. sprintf(message, "RtAudio: Unable to lock DS buffer (%s): %s.",
  2397. devices[device].name, getErrorString(result));
  2398. error(RtAudioError::WARNING);
  2399. return FAILURE;
  2400. }
  2401. // Zero the DS buffer
  2402. ZeroMemory(audioPtr, dataLen);
  2403. // Unlock the DS buffer
  2404. result = buffer->Unlock(audioPtr, dataLen, NULL, 0);
  2405. if ( FAILED(result) ) {
  2406. object->Release();
  2407. sprintf(message, "RtAudio: Unable to unlock DS buffer(%s): %s.",
  2408. devices[device].name, getErrorString(result));
  2409. error(RtAudioError::WARNING);
  2410. return FAILURE;
  2411. }
  2412. stream->handle[0].object = (void *) object;
  2413. stream->handle[0].buffer = (void *) buffer;
  2414. stream->nDeviceChannels[0] = channels;
  2415. }
  2416. if ( mode == RECORD ) {
  2417. LPGUID id = devices[device].id[1];
  2418. LPDIRECTSOUNDCAPTURE object;
  2419. LPDIRECTSOUNDCAPTUREBUFFER buffer;
  2420. DSCBUFFERDESC bufferDescription;
  2421. result = DirectSoundCaptureCreate( id, &object, NULL );
  2422. if ( FAILED(result) ) {
  2423. sprintf(message, "RtAudio: Could not create DirectSound capture object (%s): %s.",
  2424. devices[device].name, getErrorString(result));
  2425. error(RtAudioError::WARNING);
  2426. return FAILURE;
  2427. }
  2428. // Setup the secondary DS buffer description.
  2429. buffer_size = channels * *bufferSize * nBuffers * waveFormat.wBitsPerSample / 8;
  2430. ZeroMemory(&bufferDescription, sizeof(DSCBUFFERDESC));
  2431. bufferDescription.dwSize = sizeof(DSCBUFFERDESC);
  2432. bufferDescription.dwFlags = 0;
  2433. bufferDescription.dwReserved = 0;
  2434. bufferDescription.dwBufferBytes = buffer_size;
  2435. bufferDescription.lpwfxFormat = &waveFormat;
  2436. // Create the capture buffer.
  2437. result = object->CreateCaptureBuffer(&bufferDescription, &buffer, NULL);
  2438. if ( FAILED(result) ) {
  2439. object->Release();
  2440. sprintf(message, "RtAudio: Unable to create DS capture buffer (%s): %s.",
  2441. devices[device].name, getErrorString(result));
  2442. error(RtAudioError::WARNING);
  2443. return FAILURE;
  2444. }
  2445. // Lock the capture buffer
  2446. result = buffer->Lock(0, buffer_size, &audioPtr, &dataLen, NULL, NULL, 0);
  2447. if ( FAILED(result) ) {
  2448. object->Release();
  2449. sprintf(message, "RtAudio: Unable to lock DS capture buffer (%s): %s.",
  2450. devices[device].name, getErrorString(result));
  2451. error(RtAudioError::WARNING);
  2452. return FAILURE;
  2453. }
  2454. // Zero the buffer
  2455. ZeroMemory(audioPtr, dataLen);
  2456. // Unlock the buffer
  2457. result = buffer->Unlock(audioPtr, dataLen, NULL, 0);
  2458. if ( FAILED(result) ) {
  2459. object->Release();
  2460. sprintf(message, "RtAudio: Unable to unlock DS capture buffer (%s): %s.",
  2461. devices[device].name, getErrorString(result));
  2462. error(RtAudioError::WARNING);
  2463. return FAILURE;
  2464. }
  2465. stream->handle[1].object = (void *) object;
  2466. stream->handle[1].buffer = (void *) buffer;
  2467. stream->nDeviceChannels[1] = channels;
  2468. }
  2469. stream->userFormat = format;
  2470. if ( waveFormat.wBitsPerSample == 8 )
  2471. stream->deviceFormat[mode] = RTAUDIO_SINT8;
  2472. else
  2473. stream->deviceFormat[mode] = RTAUDIO_SINT16;
  2474. stream->nUserChannels[mode] = channels;
  2475. *bufferSize = buffer_size / (channels * nBuffers * waveFormat.wBitsPerSample / 8);
  2476. stream->bufferSize = *bufferSize;
  2477. // Set flags for buffer conversion
  2478. stream->doConvertBuffer[mode] = false;
  2479. if (stream->userFormat != stream->deviceFormat[mode])
  2480. stream->doConvertBuffer[mode] = true;
  2481. if (stream->nUserChannels[mode] < stream->nDeviceChannels[mode])
  2482. stream->doConvertBuffer[mode] = true;
  2483. // Allocate necessary internal buffers
  2484. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  2485. long buffer_bytes;
  2486. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  2487. buffer_bytes = stream->nUserChannels[0];
  2488. else
  2489. buffer_bytes = stream->nUserChannels[1];
  2490. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  2491. if (stream->userBuffer) free(stream->userBuffer);
  2492. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  2493. if (stream->userBuffer == NULL)
  2494. goto memory_error;
  2495. }
  2496. if ( stream->doConvertBuffer[mode] ) {
  2497. long buffer_bytes;
  2498. bool makeBuffer = true;
  2499. if ( mode == PLAYBACK )
  2500. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  2501. else { // mode == RECORD
  2502. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  2503. if ( stream->mode == PLAYBACK ) {
  2504. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  2505. if ( buffer_bytes > bytes_out )
  2506. buffer_bytes = (buffer_bytes > bytes_out) ? buffer_bytes : bytes_out;
  2507. else
  2508. makeBuffer = false;
  2509. }
  2510. }
  2511. if ( makeBuffer ) {
  2512. buffer_bytes *= *bufferSize;
  2513. if (stream->deviceBuffer) free(stream->deviceBuffer);
  2514. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  2515. if (stream->deviceBuffer == NULL)
  2516. goto memory_error;
  2517. }
  2518. }
  2519. stream->device[mode] = device;
  2520. stream->state = STREAM_STOPPED;
  2521. if ( stream->mode == PLAYBACK && mode == RECORD )
  2522. // We had already set up an output stream.
  2523. stream->mode = DUPLEX;
  2524. else
  2525. stream->mode = mode;
  2526. stream->nBuffers = nBuffers;
  2527. stream->sampleRate = sampleRate;
  2528. return SUCCESS;
  2529. memory_error:
  2530. if (stream->handle[0].object) {
  2531. LPDIRECTSOUND object = (LPDIRECTSOUND) stream->handle[0].object;
  2532. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  2533. if (buffer) {
  2534. buffer->Release();
  2535. stream->handle[0].buffer = NULL;
  2536. }
  2537. object->Release();
  2538. stream->handle[0].object = NULL;
  2539. }
  2540. if (stream->handle[1].object) {
  2541. LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) stream->handle[1].object;
  2542. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  2543. if (buffer) {
  2544. buffer->Release();
  2545. stream->handle[1].buffer = NULL;
  2546. }
  2547. object->Release();
  2548. stream->handle[1].object = NULL;
  2549. }
  2550. if (stream->userBuffer) {
  2551. free(stream->userBuffer);
  2552. stream->userBuffer = 0;
  2553. }
  2554. sprintf(message, "RtAudio: error allocating buffer memory (%s).",
  2555. devices[device].name);
  2556. error(RtAudioError::WARNING);
  2557. return FAILURE;
  2558. }
  2559. void RtAudio :: cancelStreamCallback(int streamID)
  2560. {
  2561. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  2562. if (stream->usingCallback) {
  2563. stream->usingCallback = false;
  2564. WaitForSingleObject( (HANDLE)stream->thread, INFINITE );
  2565. CloseHandle( (HANDLE)stream->thread );
  2566. stream->thread = 0;
  2567. stream->callback = NULL;
  2568. stream->userData = NULL;
  2569. }
  2570. }
  2571. void RtAudio :: closeStream(int streamID)
  2572. {
  2573. // We don't want an exception to be thrown here because this
  2574. // function is called by our class destructor. So, do our own
  2575. // streamID check.
  2576. if ( streams.find( streamID ) == streams.end() ) {
  2577. sprintf(message, "RtAudio: invalid stream identifier!");
  2578. error(RtAudioError::WARNING);
  2579. return;
  2580. }
  2581. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamID];
  2582. if (stream->usingCallback) {
  2583. stream->usingCallback = false;
  2584. WaitForSingleObject( (HANDLE)stream->thread, INFINITE );
  2585. CloseHandle( (HANDLE)stream->thread );
  2586. }
  2587. DeleteCriticalSection(&stream->mutex);
  2588. if (stream->handle[0].object) {
  2589. LPDIRECTSOUND object = (LPDIRECTSOUND) stream->handle[0].object;
  2590. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  2591. if (buffer) {
  2592. buffer->Stop();
  2593. buffer->Release();
  2594. }
  2595. object->Release();
  2596. }
  2597. if (stream->handle[1].object) {
  2598. LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) stream->handle[1].object;
  2599. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  2600. if (buffer) {
  2601. buffer->Stop();
  2602. buffer->Release();
  2603. }
  2604. object->Release();
  2605. }
  2606. if (stream->userBuffer)
  2607. free(stream->userBuffer);
  2608. if (stream->deviceBuffer)
  2609. free(stream->deviceBuffer);
  2610. free(stream);
  2611. streams.erase(streamID);
  2612. }
  2613. void RtAudio :: startStream(int streamID)
  2614. {
  2615. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  2616. MUTEX_LOCK(&stream->mutex);
  2617. if (stream->state == STREAM_RUNNING)
  2618. goto unlock;
  2619. HRESULT result;
  2620. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  2621. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  2622. result = buffer->Play(0, 0, DSBPLAY_LOOPING );
  2623. if ( FAILED(result) ) {
  2624. sprintf(message, "RtAudio: Unable to start DS buffer (%s): %s.",
  2625. devices[stream->device[0]].name, getErrorString(result));
  2626. error(RtAudioError::DRIVER_ERROR);
  2627. }
  2628. }
  2629. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  2630. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  2631. result = buffer->Start(DSCBSTART_LOOPING );
  2632. if ( FAILED(result) ) {
  2633. sprintf(message, "RtAudio: Unable to start DS capture buffer (%s): %s.",
  2634. devices[stream->device[1]].name, getErrorString(result));
  2635. error(RtAudioError::DRIVER_ERROR);
  2636. }
  2637. }
  2638. stream->state = STREAM_RUNNING;
  2639. unlock:
  2640. MUTEX_UNLOCK(&stream->mutex);
  2641. }
  2642. void RtAudio :: stopStream(int streamID)
  2643. {
  2644. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  2645. MUTEX_LOCK(&stream->mutex);
  2646. if (stream->state == STREAM_STOPPED) {
  2647. MUTEX_UNLOCK(&stream->mutex);
  2648. return;
  2649. }
  2650. // There is no specific DirectSound API call to "drain" a buffer
  2651. // before stopping. We can hack this for playback by writing zeroes
  2652. // for another bufferSize * nBuffers frames. For capture, the
  2653. // concept is less clear so we'll repeat what we do in the
  2654. // abortStream() case.
  2655. HRESULT result;
  2656. DWORD dsBufferSize;
  2657. LPVOID buffer1 = NULL;
  2658. LPVOID buffer2 = NULL;
  2659. DWORD bufferSize1 = 0;
  2660. DWORD bufferSize2 = 0;
  2661. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  2662. DWORD currentPos, safePos;
  2663. long buffer_bytes = stream->bufferSize * stream->nDeviceChannels[0];
  2664. buffer_bytes *= formatBytes(stream->deviceFormat[0]);
  2665. LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  2666. UINT nextWritePos = stream->handle[0].bufferPointer;
  2667. dsBufferSize = buffer_bytes * stream->nBuffers;
  2668. // Write zeroes for nBuffer counts.
  2669. for (int i=0; i<stream->nBuffers; i++) {
  2670. // Find out where the read and "safe write" pointers are.
  2671. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  2672. if ( FAILED(result) ) {
  2673. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  2674. devices[stream->device[0]].name, getErrorString(result));
  2675. error(RtAudioError::DRIVER_ERROR);
  2676. }
  2677. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  2678. DWORD endWrite = nextWritePos + buffer_bytes;
  2679. // Check whether the entire write region is behind the play pointer.
  2680. while ( currentPos < endWrite ) {
  2681. float millis = (endWrite - currentPos) * 900.0;
  2682. millis /= ( formatBytes(stream->deviceFormat[0]) * stream->sampleRate);
  2683. if ( millis < 1.0 ) millis = 1.0;
  2684. Sleep( (DWORD) millis );
  2685. // Wake up, find out where we are now
  2686. result = dsBuffer->GetCurrentPosition( &currentPos, &safePos );
  2687. if ( FAILED(result) ) {
  2688. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  2689. devices[stream->device[0]].name, getErrorString(result));
  2690. error(RtAudioError::DRIVER_ERROR);
  2691. }
  2692. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  2693. }
  2694. // Lock free space in the buffer
  2695. result = dsBuffer->Lock (nextWritePos, buffer_bytes, &buffer1,
  2696. &bufferSize1, &buffer2, &bufferSize2, 0);
  2697. if ( FAILED(result) ) {
  2698. sprintf(message, "RtAudio: Unable to lock DS buffer during playback (%s): %s.",
  2699. devices[stream->device[0]].name, getErrorString(result));
  2700. error(RtAudioError::DRIVER_ERROR);
  2701. }
  2702. // Zero the free space
  2703. ZeroMemory(buffer1, bufferSize1);
  2704. if (buffer2 != NULL) ZeroMemory(buffer2, bufferSize2);
  2705. // Update our buffer offset and unlock sound buffer
  2706. dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2);
  2707. if ( FAILED(result) ) {
  2708. sprintf(message, "RtAudio: Unable to unlock DS buffer during playback (%s): %s.",
  2709. devices[stream->device[0]].name, getErrorString(result));
  2710. error(RtAudioError::DRIVER_ERROR);
  2711. }
  2712. nextWritePos = (nextWritePos + bufferSize1 + bufferSize2) % dsBufferSize;
  2713. stream->handle[0].bufferPointer = nextWritePos;
  2714. }
  2715. // If we play again, start at the beginning of the buffer.
  2716. stream->handle[0].bufferPointer = 0;
  2717. }
  2718. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  2719. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  2720. buffer1 = NULL;
  2721. bufferSize1 = 0;
  2722. result = buffer->Stop();
  2723. if ( FAILED(result) ) {
  2724. sprintf(message, "RtAudio: Unable to stop DS capture buffer (%s): %s",
  2725. devices[stream->device[1]].name, getErrorString(result));
  2726. error(RtAudioError::DRIVER_ERROR);
  2727. }
  2728. dsBufferSize = stream->bufferSize * stream->nDeviceChannels[1];
  2729. dsBufferSize *= formatBytes(stream->deviceFormat[1]) * stream->nBuffers;
  2730. // Lock the buffer and clear it so that if we start to play again,
  2731. // we won't have old data playing.
  2732. result = buffer->Lock(0, dsBufferSize, &buffer1, &bufferSize1, NULL, NULL, 0);
  2733. if ( FAILED(result) ) {
  2734. sprintf(message, "RtAudio: Unable to lock DS capture buffer (%s): %s.",
  2735. devices[stream->device[1]].name, getErrorString(result));
  2736. error(RtAudioError::DRIVER_ERROR);
  2737. }
  2738. // Zero the DS buffer
  2739. ZeroMemory(buffer1, bufferSize1);
  2740. // Unlock the DS buffer
  2741. result = buffer->Unlock(buffer1, bufferSize1, NULL, 0);
  2742. if ( FAILED(result) ) {
  2743. sprintf(message, "RtAudio: Unable to unlock DS capture buffer (%s): %s.",
  2744. devices[stream->device[1]].name, getErrorString(result));
  2745. error(RtAudioError::DRIVER_ERROR);
  2746. }
  2747. // If we start recording again, we must begin at beginning of buffer.
  2748. stream->handle[1].bufferPointer = 0;
  2749. }
  2750. stream->state = STREAM_STOPPED;
  2751. MUTEX_UNLOCK(&stream->mutex);
  2752. }
  2753. void RtAudio :: abortStream(int streamID)
  2754. {
  2755. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  2756. MUTEX_LOCK(&stream->mutex);
  2757. if (stream->state == STREAM_STOPPED)
  2758. goto unlock;
  2759. HRESULT result;
  2760. long dsBufferSize;
  2761. LPVOID audioPtr;
  2762. DWORD dataLen;
  2763. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  2764. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  2765. result = buffer->Stop();
  2766. if ( FAILED(result) ) {
  2767. sprintf(message, "RtAudio: Unable to stop DS buffer (%s): %s",
  2768. devices[stream->device[0]].name, getErrorString(result));
  2769. error(RtAudioError::DRIVER_ERROR);
  2770. }
  2771. dsBufferSize = stream->bufferSize * stream->nDeviceChannels[0];
  2772. dsBufferSize *= formatBytes(stream->deviceFormat[0]) * stream->nBuffers;
  2773. // Lock the buffer and clear it so that if we start to play again,
  2774. // we won't have old data playing.
  2775. result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0);
  2776. if ( FAILED(result) ) {
  2777. sprintf(message, "RtAudio: Unable to lock DS buffer (%s): %s.",
  2778. devices[stream->device[0]].name, getErrorString(result));
  2779. error(RtAudioError::DRIVER_ERROR);
  2780. }
  2781. // Zero the DS buffer
  2782. ZeroMemory(audioPtr, dataLen);
  2783. // Unlock the DS buffer
  2784. result = buffer->Unlock(audioPtr, dataLen, NULL, 0);
  2785. if ( FAILED(result) ) {
  2786. sprintf(message, "RtAudio: Unable to unlock DS buffer (%s): %s.",
  2787. devices[stream->device[0]].name, getErrorString(result));
  2788. error(RtAudioError::DRIVER_ERROR);
  2789. }
  2790. // If we start playing again, we must begin at beginning of buffer.
  2791. stream->handle[0].bufferPointer = 0;
  2792. }
  2793. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  2794. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  2795. audioPtr = NULL;
  2796. dataLen = 0;
  2797. result = buffer->Stop();
  2798. if ( FAILED(result) ) {
  2799. sprintf(message, "RtAudio: Unable to stop DS capture buffer (%s): %s",
  2800. devices[stream->device[1]].name, getErrorString(result));
  2801. error(RtAudioError::DRIVER_ERROR);
  2802. }
  2803. dsBufferSize = stream->bufferSize * stream->nDeviceChannels[1];
  2804. dsBufferSize *= formatBytes(stream->deviceFormat[1]) * stream->nBuffers;
  2805. // Lock the buffer and clear it so that if we start to play again,
  2806. // we won't have old data playing.
  2807. result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0);
  2808. if ( FAILED(result) ) {
  2809. sprintf(message, "RtAudio: Unable to lock DS capture buffer (%s): %s.",
  2810. devices[stream->device[1]].name, getErrorString(result));
  2811. error(RtAudioError::DRIVER_ERROR);
  2812. }
  2813. // Zero the DS buffer
  2814. ZeroMemory(audioPtr, dataLen);
  2815. // Unlock the DS buffer
  2816. result = buffer->Unlock(audioPtr, dataLen, NULL, 0);
  2817. if ( FAILED(result) ) {
  2818. sprintf(message, "RtAudio: Unable to unlock DS capture buffer (%s): %s.",
  2819. devices[stream->device[1]].name, getErrorString(result));
  2820. error(RtAudioError::DRIVER_ERROR);
  2821. }
  2822. // If we start recording again, we must begin at beginning of buffer.
  2823. stream->handle[1].bufferPointer = 0;
  2824. }
  2825. stream->state = STREAM_STOPPED;
  2826. unlock:
  2827. MUTEX_UNLOCK(&stream->mutex);
  2828. }
  2829. int RtAudio :: streamWillBlock(int streamID)
  2830. {
  2831. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  2832. MUTEX_LOCK(&stream->mutex);
  2833. int frames = 0;
  2834. int channels = 1;
  2835. if (stream->state == STREAM_STOPPED)
  2836. goto unlock;
  2837. HRESULT result;
  2838. DWORD currentPos, safePos;
  2839. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  2840. LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  2841. UINT nextWritePos = stream->handle[0].bufferPointer;
  2842. channels = stream->nDeviceChannels[0];
  2843. DWORD dsBufferSize = stream->bufferSize * channels;
  2844. dsBufferSize *= formatBytes(stream->deviceFormat[0]) * stream->nBuffers;
  2845. // Find out where the read and "safe write" pointers are.
  2846. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  2847. if ( FAILED(result) ) {
  2848. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  2849. devices[stream->device[0]].name, getErrorString(result));
  2850. error(RtAudioError::DRIVER_ERROR);
  2851. }
  2852. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  2853. frames = currentPos - nextWritePos;
  2854. frames /= channels * formatBytes(stream->deviceFormat[0]);
  2855. }
  2856. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  2857. LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  2858. UINT nextReadPos = stream->handle[1].bufferPointer;
  2859. channels = stream->nDeviceChannels[1];
  2860. DWORD dsBufferSize = stream->bufferSize * channels;
  2861. dsBufferSize *= formatBytes(stream->deviceFormat[1]) * stream->nBuffers;
  2862. // Find out where the write and "safe read" pointers are.
  2863. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  2864. if ( FAILED(result) ) {
  2865. sprintf(message, "RtAudio: Unable to get current DS capture position (%s): %s.",
  2866. devices[stream->device[1]].name, getErrorString(result));
  2867. error(RtAudioError::DRIVER_ERROR);
  2868. }
  2869. if ( safePos < nextReadPos ) safePos += dsBufferSize; // unwrap offset
  2870. if (stream->mode == DUPLEX ) {
  2871. // Take largest value of the two.
  2872. int temp = safePos - nextReadPos;
  2873. temp /= channels * formatBytes(stream->deviceFormat[1]);
  2874. frames = ( temp > frames ) ? temp : frames;
  2875. }
  2876. else {
  2877. frames = safePos - nextReadPos;
  2878. frames /= channels * formatBytes(stream->deviceFormat[1]);
  2879. }
  2880. }
  2881. frames = stream->bufferSize - frames;
  2882. if (frames < 0) frames = 0;
  2883. unlock:
  2884. MUTEX_UNLOCK(&stream->mutex);
  2885. return frames;
  2886. }
  2887. void RtAudio :: tickStream(int streamID)
  2888. {
  2889. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  2890. int stopStream = 0;
  2891. if (stream->state == STREAM_STOPPED) {
  2892. if (stream->usingCallback) Sleep(50); // sleep 50 milliseconds
  2893. return;
  2894. }
  2895. else if (stream->usingCallback) {
  2896. stopStream = stream->callback(stream->userBuffer, stream->bufferSize, stream->userData);
  2897. }
  2898. MUTEX_LOCK(&stream->mutex);
  2899. // The state might change while waiting on a mutex.
  2900. if (stream->state == STREAM_STOPPED)
  2901. goto unlock;
  2902. HRESULT result;
  2903. DWORD currentPos, safePos;
  2904. LPVOID buffer1, buffer2;
  2905. DWORD bufferSize1, bufferSize2;
  2906. char *buffer;
  2907. long buffer_bytes;
  2908. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  2909. // Setup parameters and do buffer conversion if necessary.
  2910. if (stream->doConvertBuffer[0]) {
  2911. convertStreamBuffer(stream, PLAYBACK);
  2912. buffer = stream->deviceBuffer;
  2913. buffer_bytes = stream->bufferSize * stream->nDeviceChannels[0];
  2914. buffer_bytes *= formatBytes(stream->deviceFormat[0]);
  2915. }
  2916. else {
  2917. buffer = stream->userBuffer;
  2918. buffer_bytes = stream->bufferSize * stream->nUserChannels[0];
  2919. buffer_bytes *= formatBytes(stream->userFormat);
  2920. }
  2921. // No byte swapping necessary in DirectSound implementation.
  2922. LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) stream->handle[0].buffer;
  2923. UINT nextWritePos = stream->handle[0].bufferPointer;
  2924. DWORD dsBufferSize = buffer_bytes * stream->nBuffers;
  2925. // Find out where the read and "safe write" pointers are.
  2926. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  2927. if ( FAILED(result) ) {
  2928. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  2929. devices[stream->device[0]].name, getErrorString(result));
  2930. error(RtAudioError::DRIVER_ERROR);
  2931. }
  2932. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  2933. DWORD endWrite = nextWritePos + buffer_bytes;
  2934. // Check whether the entire write region is behind the play pointer.
  2935. while ( currentPos < endWrite ) {
  2936. // If we are here, then we must wait until the play pointer gets
  2937. // beyond the write region. The approach here is to use the
  2938. // Sleep() function to suspend operation until safePos catches
  2939. // up. Calculate number of milliseconds to wait as:
  2940. // time = distance * (milliseconds/second) * fudgefactor /
  2941. // ((bytes/sample) * (samples/second))
  2942. // A "fudgefactor" less than 1 is used because it was found
  2943. // that sleeping too long was MUCH worse than sleeping for
  2944. // several shorter periods.
  2945. float millis = (endWrite - currentPos) * 900.0;
  2946. millis /= ( formatBytes(stream->deviceFormat[0]) * stream->sampleRate);
  2947. if ( millis < 1.0 ) millis = 1.0;
  2948. Sleep( (DWORD) millis );
  2949. // Wake up, find out where we are now
  2950. result = dsBuffer->GetCurrentPosition( &currentPos, &safePos );
  2951. if ( FAILED(result) ) {
  2952. sprintf(message, "RtAudio: Unable to get current DS position (%s): %s.",
  2953. devices[stream->device[0]].name, getErrorString(result));
  2954. error(RtAudioError::DRIVER_ERROR);
  2955. }
  2956. if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
  2957. }
  2958. // Lock free space in the buffer
  2959. result = dsBuffer->Lock (nextWritePos, buffer_bytes, &buffer1,
  2960. &bufferSize1, &buffer2, &bufferSize2, 0);
  2961. if ( FAILED(result) ) {
  2962. sprintf(message, "RtAudio: Unable to lock DS buffer during playback (%s): %s.",
  2963. devices[stream->device[0]].name, getErrorString(result));
  2964. error(RtAudioError::DRIVER_ERROR);
  2965. }
  2966. // Copy our buffer into the DS buffer
  2967. CopyMemory(buffer1, buffer, bufferSize1);
  2968. if (buffer2 != NULL) CopyMemory(buffer2, buffer+bufferSize1, bufferSize2);
  2969. // Update our buffer offset and unlock sound buffer
  2970. dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2);
  2971. if ( FAILED(result) ) {
  2972. sprintf(message, "RtAudio: Unable to unlock DS buffer during playback (%s): %s.",
  2973. devices[stream->device[0]].name, getErrorString(result));
  2974. error(RtAudioError::DRIVER_ERROR);
  2975. }
  2976. nextWritePos = (nextWritePos + bufferSize1 + bufferSize2) % dsBufferSize;
  2977. stream->handle[0].bufferPointer = nextWritePos;
  2978. }
  2979. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  2980. // Setup parameters.
  2981. if (stream->doConvertBuffer[1]) {
  2982. buffer = stream->deviceBuffer;
  2983. buffer_bytes = stream->bufferSize * stream->nDeviceChannels[1];
  2984. buffer_bytes *= formatBytes(stream->deviceFormat[1]);
  2985. }
  2986. else {
  2987. buffer = stream->userBuffer;
  2988. buffer_bytes = stream->bufferSize * stream->nUserChannels[1];
  2989. buffer_bytes *= formatBytes(stream->userFormat);
  2990. }
  2991. LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) stream->handle[1].buffer;
  2992. UINT nextReadPos = stream->handle[1].bufferPointer;
  2993. DWORD dsBufferSize = buffer_bytes * stream->nBuffers;
  2994. // Find out where the write and "safe read" pointers are.
  2995. result = dsBuffer->GetCurrentPosition(&currentPos, &safePos);
  2996. if ( FAILED(result) ) {
  2997. sprintf(message, "RtAudio: Unable to get current DS capture position (%s): %s.",
  2998. devices[stream->device[1]].name, getErrorString(result));
  2999. error(RtAudioError::DRIVER_ERROR);
  3000. }
  3001. if ( safePos < nextReadPos ) safePos += dsBufferSize; // unwrap offset
  3002. DWORD endRead = nextReadPos + buffer_bytes;
  3003. // Check whether the entire write region is behind the play pointer.
  3004. while ( safePos < endRead ) {
  3005. // See comments for playback.
  3006. float millis = (endRead - safePos) * 900.0;
  3007. millis /= ( formatBytes(stream->deviceFormat[1]) * stream->sampleRate);
  3008. if ( millis < 1.0 ) millis = 1.0;
  3009. Sleep( (DWORD) millis );
  3010. // Wake up, find out where we are now
  3011. result = dsBuffer->GetCurrentPosition( &currentPos, &safePos );
  3012. if ( FAILED(result) ) {
  3013. sprintf(message, "RtAudio: Unable to get current DS capture position (%s): %s.",
  3014. devices[stream->device[1]].name, getErrorString(result));
  3015. error(RtAudioError::DRIVER_ERROR);
  3016. }
  3017. if ( safePos < nextReadPos ) safePos += dsBufferSize; // unwrap offset
  3018. }
  3019. // Lock free space in the buffer
  3020. result = dsBuffer->Lock (nextReadPos, buffer_bytes, &buffer1,
  3021. &bufferSize1, &buffer2, &bufferSize2, 0);
  3022. if ( FAILED(result) ) {
  3023. sprintf(message, "RtAudio: Unable to lock DS buffer during capture (%s): %s.",
  3024. devices[stream->device[1]].name, getErrorString(result));
  3025. error(RtAudioError::DRIVER_ERROR);
  3026. }
  3027. // Copy our buffer into the DS buffer
  3028. CopyMemory(buffer, buffer1, bufferSize1);
  3029. if (buffer2 != NULL) CopyMemory(buffer+bufferSize1, buffer2, bufferSize2);
  3030. // Update our buffer offset and unlock sound buffer
  3031. nextReadPos = (nextReadPos + bufferSize1 + bufferSize2) % dsBufferSize;
  3032. dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2);
  3033. if ( FAILED(result) ) {
  3034. sprintf(message, "RtAudio: Unable to unlock DS buffer during capture (%s): %s.",
  3035. devices[stream->device[1]].name, getErrorString(result));
  3036. error(RtAudioError::DRIVER_ERROR);
  3037. }
  3038. stream->handle[1].bufferPointer = nextReadPos;
  3039. // No byte swapping necessary in DirectSound implementation.
  3040. // Do buffer conversion if necessary.
  3041. if (stream->doConvertBuffer[1])
  3042. convertStreamBuffer(stream, RECORD);
  3043. }
  3044. unlock:
  3045. MUTEX_UNLOCK(&stream->mutex);
  3046. if (stream->usingCallback && stopStream)
  3047. this->stopStream(streamID);
  3048. }
  3049. // Definitions for utility functions and callbacks
  3050. // specific to the DirectSound implementation.
  3051. extern "C" unsigned __stdcall callbackHandler(void *ptr)
  3052. {
  3053. RtAudio *object = thread_info.object;
  3054. int stream = thread_info.streamID;
  3055. bool *usingCallback = (bool *) ptr;
  3056. while ( *usingCallback ) {
  3057. try {
  3058. object->tickStream(stream);
  3059. }
  3060. catch (RtAudioError &exception) {
  3061. fprintf(stderr, "\nCallback thread error (%s) ... closing thread.\n\n",
  3062. exception.getMessage());
  3063. break;
  3064. }
  3065. }
  3066. _endthreadex( 0 );
  3067. return 0;
  3068. }
  3069. static bool CALLBACK deviceCountCallback(LPGUID lpguid,
  3070. LPCSTR lpcstrDescription,
  3071. LPCSTR lpcstrModule,
  3072. LPVOID lpContext)
  3073. {
  3074. int *pointer = ((int *) lpContext);
  3075. (*pointer)++;
  3076. return true;
  3077. }
  3078. static bool CALLBACK deviceInfoCallback(LPGUID lpguid,
  3079. LPCSTR lpcstrDescription,
  3080. LPCSTR lpcstrModule,
  3081. LPVOID lpContext)
  3082. {
  3083. enum_info *info = ((enum_info *) lpContext);
  3084. while (strlen(info->name) > 0) info++;
  3085. strncpy(info->name, lpcstrDescription, 64);
  3086. info->id = lpguid;
  3087. HRESULT hr;
  3088. info->isValid = false;
  3089. if (info->isInput == true) {
  3090. DSCCAPS caps;
  3091. LPDIRECTSOUNDCAPTURE object;
  3092. hr = DirectSoundCaptureCreate( lpguid, &object, NULL );
  3093. if( hr != DS_OK ) return true;
  3094. caps.dwSize = sizeof(caps);
  3095. hr = object->GetCaps( &caps );
  3096. if( hr == DS_OK ) {
  3097. if (caps.dwChannels > 0 && caps.dwFormats > 0)
  3098. info->isValid = true;
  3099. }
  3100. object->Release();
  3101. }
  3102. else {
  3103. DSCAPS caps;
  3104. LPDIRECTSOUND object;
  3105. hr = DirectSoundCreate( lpguid, &object, NULL );
  3106. if( hr != DS_OK ) return true;
  3107. caps.dwSize = sizeof(caps);
  3108. hr = object->GetCaps( &caps );
  3109. if( hr == DS_OK ) {
  3110. if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO )
  3111. info->isValid = true;
  3112. }
  3113. object->Release();
  3114. }
  3115. return true;
  3116. }
  3117. static char* getErrorString(int code)
  3118. {
  3119. switch (code) {
  3120. case DSERR_ALLOCATED:
  3121. return "Direct Sound already allocated";
  3122. case DSERR_CONTROLUNAVAIL:
  3123. return "Direct Sound control unavailable";
  3124. case DSERR_INVALIDPARAM:
  3125. return "Direct Sound invalid parameter";
  3126. case DSERR_INVALIDCALL:
  3127. return "Direct Sound invalid call";
  3128. case DSERR_GENERIC:
  3129. return "Direct Sound generic error";
  3130. case DSERR_PRIOLEVELNEEDED:
  3131. return "Direct Sound Priority level needed";
  3132. case DSERR_OUTOFMEMORY:
  3133. return "Direct Sound out of memory";
  3134. case DSERR_BADFORMAT:
  3135. return "Direct Sound bad format";
  3136. case DSERR_UNSUPPORTED:
  3137. return "Direct Sound unsupported error";
  3138. case DSERR_NODRIVER:
  3139. return "Direct Sound no driver error";
  3140. case DSERR_ALREADYINITIALIZED:
  3141. return "Direct Sound already initialized";
  3142. case DSERR_NOAGGREGATION:
  3143. return "Direct Sound no aggregation";
  3144. case DSERR_BUFFERLOST:
  3145. return "Direct Sound buffer lost";
  3146. case DSERR_OTHERAPPHASPRIO:
  3147. return "Direct Sound other app has priority";
  3148. case DSERR_UNINITIALIZED:
  3149. return "Direct Sound uninitialized";
  3150. default:
  3151. return "Direct Sound unknown error";
  3152. }
  3153. }
  3154. //******************** End of __WINDOWS_DS_ *********************//
  3155. #elif defined(__IRIX_AL_) // SGI's AL API for IRIX
  3156. #include <unistd.h>
  3157. #include <errno.h>
  3158. void RtAudio :: initialize(void)
  3159. {
  3160. // Count cards and devices
  3161. nDevices = 0;
  3162. // Determine the total number of input and output devices.
  3163. nDevices = alQueryValues(AL_SYSTEM, AL_DEVICES, 0, 0, 0, 0);
  3164. if (nDevices < 0) {
  3165. sprintf(message, "RtAudio: AL error counting devices: %s.",
  3166. alGetErrorString(oserror()));
  3167. error(RtAudioError::DRIVER_ERROR);
  3168. }
  3169. if (nDevices <= 0) return;
  3170. ALvalue *vls = (ALvalue *) new ALvalue[nDevices];
  3171. // Add one for our default input/output devices.
  3172. nDevices++;
  3173. // Allocate the DEVICE_CONTROL structures.
  3174. devices = (RTAUDIO_DEVICE *) calloc(nDevices, sizeof(RTAUDIO_DEVICE));
  3175. if (devices == NULL) {
  3176. sprintf(message, "RtAudio: memory allocation error!");
  3177. error(RtAudioError::MEMORY_ERROR);
  3178. }
  3179. // Write device ascii identifiers to device info structure.
  3180. char name[32];
  3181. int outs, ins, i;
  3182. ALpv pvs[1];
  3183. pvs[0].param = AL_NAME;
  3184. pvs[0].value.ptr = name;
  3185. pvs[0].sizeIn = 32;
  3186. strcpy(devices[0].name, "Default Input/Output Devices");
  3187. outs = alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, vls, nDevices-1, 0, 0);
  3188. if (outs < 0) {
  3189. sprintf(message, "RtAudio: AL error getting output devices: %s.",
  3190. alGetErrorString(oserror()));
  3191. error(RtAudioError::DRIVER_ERROR);
  3192. }
  3193. for (i=0; i<outs; i++) {
  3194. if (alGetParams(vls[i].i, pvs, 1) < 0) {
  3195. sprintf(message, "RtAudio: AL error querying output devices: %s.",
  3196. alGetErrorString(oserror()));
  3197. error(RtAudioError::DRIVER_ERROR);
  3198. }
  3199. strncpy(devices[i+1].name, name, 32);
  3200. devices[i+1].id[0] = vls[i].i;
  3201. }
  3202. ins = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, &vls[outs], nDevices-outs-1, 0, 0);
  3203. if (ins < 0) {
  3204. sprintf(message, "RtAudio: AL error getting input devices: %s.",
  3205. alGetErrorString(oserror()));
  3206. error(RtAudioError::DRIVER_ERROR);
  3207. }
  3208. for (i=outs; i<ins+outs; i++) {
  3209. if (alGetParams(vls[i].i, pvs, 1) < 0) {
  3210. sprintf(message, "RtAudio: AL error querying input devices: %s.",
  3211. alGetErrorString(oserror()));
  3212. error(RtAudioError::DRIVER_ERROR);
  3213. }
  3214. strncpy(devices[i+1].name, name, 32);
  3215. devices[i+1].id[1] = vls[i].i;
  3216. }
  3217. delete [] vls;
  3218. return;
  3219. }
  3220. void RtAudio :: probeDeviceInfo(RTAUDIO_DEVICE *info)
  3221. {
  3222. int resource, result, i;
  3223. ALvalue value;
  3224. ALparamInfo pinfo;
  3225. // Get output resource ID if it exists.
  3226. if ( !strncmp(info->name, "Default Input/Output Devices", 28) ) {
  3227. result = alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, &value, 1, 0, 0);
  3228. if (result < 0) {
  3229. sprintf(message, "RtAudio: AL error getting default output device id: %s.",
  3230. alGetErrorString(oserror()));
  3231. error(RtAudioError::WARNING);
  3232. }
  3233. else
  3234. resource = value.i;
  3235. }
  3236. else
  3237. resource = info->id[0];
  3238. if (resource > 0) {
  3239. // Probe output device parameters.
  3240. result = alQueryValues(resource, AL_CHANNELS, &value, 1, 0, 0);
  3241. if (result < 0) {
  3242. sprintf(message, "RtAudio: AL error getting device (%s) channels: %s.",
  3243. info->name, alGetErrorString(oserror()));
  3244. error(RtAudioError::WARNING);
  3245. }
  3246. else {
  3247. info->maxOutputChannels = value.i;
  3248. info->minOutputChannels = 1;
  3249. }
  3250. result = alGetParamInfo(resource, AL_RATE, &pinfo);
  3251. if (result < 0) {
  3252. sprintf(message, "RtAudio: AL error getting device (%s) rates: %s.",
  3253. info->name, alGetErrorString(oserror()));
  3254. error(RtAudioError::WARNING);
  3255. }
  3256. else {
  3257. info->nSampleRates = 0;
  3258. for (i=0; i<MAX_SAMPLE_RATES; i++) {
  3259. if ( SAMPLE_RATES[i] >= pinfo.min.i && SAMPLE_RATES[i] <= pinfo.max.i ) {
  3260. info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
  3261. info->nSampleRates++;
  3262. }
  3263. }
  3264. }
  3265. // The AL library supports all our formats, except 24-bit and 32-bit ints.
  3266. info->nativeFormats = (RTAUDIO_FORMAT) 51;
  3267. }
  3268. // Now get input resource ID if it exists.
  3269. if ( !strncmp(info->name, "Default Input/Output Devices", 28) ) {
  3270. result = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, &value, 1, 0, 0);
  3271. if (result < 0) {
  3272. sprintf(message, "RtAudio: AL error getting default input device id: %s.",
  3273. alGetErrorString(oserror()));
  3274. error(RtAudioError::WARNING);
  3275. }
  3276. else
  3277. resource = value.i;
  3278. }
  3279. else
  3280. resource = info->id[1];
  3281. if (resource > 0) {
  3282. // Probe input device parameters.
  3283. result = alQueryValues(resource, AL_CHANNELS, &value, 1, 0, 0);
  3284. if (result < 0) {
  3285. sprintf(message, "RtAudio: AL error getting device (%s) channels: %s.",
  3286. info->name, alGetErrorString(oserror()));
  3287. error(RtAudioError::WARNING);
  3288. }
  3289. else {
  3290. info->maxInputChannels = value.i;
  3291. info->minInputChannels = 1;
  3292. }
  3293. result = alGetParamInfo(resource, AL_RATE, &pinfo);
  3294. if (result < 0) {
  3295. sprintf(message, "RtAudio: AL error getting device (%s) rates: %s.",
  3296. info->name, alGetErrorString(oserror()));
  3297. error(RtAudioError::WARNING);
  3298. }
  3299. else {
  3300. // In the case of the default device, these values will
  3301. // overwrite the rates determined for the output device. Since
  3302. // the input device is most likely to be more limited than the
  3303. // output device, this is ok.
  3304. info->nSampleRates = 0;
  3305. for (i=0; i<MAX_SAMPLE_RATES; i++) {
  3306. if ( SAMPLE_RATES[i] >= pinfo.min.i && SAMPLE_RATES[i] <= pinfo.max.i ) {
  3307. info->sampleRates[info->nSampleRates] = SAMPLE_RATES[i];
  3308. info->nSampleRates++;
  3309. }
  3310. }
  3311. }
  3312. // The AL library supports all our formats, except 24-bit and 32-bit ints.
  3313. info->nativeFormats = (RTAUDIO_FORMAT) 51;
  3314. }
  3315. if ( info->maxInputChannels == 0 && info->maxOutputChannels == 0 )
  3316. return;
  3317. if ( info->nSampleRates == 0 )
  3318. return;
  3319. // Determine duplex status.
  3320. if (info->maxInputChannels < info->maxOutputChannels)
  3321. info->maxDuplexChannels = info->maxInputChannels;
  3322. else
  3323. info->maxDuplexChannels = info->maxOutputChannels;
  3324. if (info->minInputChannels < info->minOutputChannels)
  3325. info->minDuplexChannels = info->minInputChannels;
  3326. else
  3327. info->minDuplexChannels = info->minOutputChannels;
  3328. if ( info->maxDuplexChannels > 0 ) info->hasDuplexSupport = true;
  3329. else info->hasDuplexSupport = false;
  3330. info->probed = true;
  3331. return;
  3332. }
  3333. bool RtAudio :: probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
  3334. STREAM_MODE mode, int channels,
  3335. int sampleRate, RTAUDIO_FORMAT format,
  3336. int *bufferSize, int numberOfBuffers)
  3337. {
  3338. int result, resource, nBuffers;
  3339. ALconfig al_config;
  3340. ALport port;
  3341. ALpv pvs[2];
  3342. // Get a new ALconfig structure.
  3343. al_config = alNewConfig();
  3344. if ( !al_config ) {
  3345. sprintf(message,"RtAudio: can't get AL config: %s.",
  3346. alGetErrorString(oserror()));
  3347. error(RtAudioError::WARNING);
  3348. return FAILURE;
  3349. }
  3350. // Set the channels.
  3351. result = alSetChannels(al_config, channels);
  3352. if ( result < 0 ) {
  3353. sprintf(message,"RtAudio: can't set %d channels in AL config: %s.",
  3354. channels, alGetErrorString(oserror()));
  3355. error(RtAudioError::WARNING);
  3356. return FAILURE;
  3357. }
  3358. // Set the queue (buffer) size.
  3359. if ( numberOfBuffers < 1 )
  3360. nBuffers = 1;
  3361. else
  3362. nBuffers = numberOfBuffers;
  3363. long buffer_size = *bufferSize * nBuffers;
  3364. result = alSetQueueSize(al_config, buffer_size); // in sample frames
  3365. if ( result < 0 ) {
  3366. sprintf(message,"RtAudio: can't set buffer size (%ld) in AL config: %s.",
  3367. buffer_size, alGetErrorString(oserror()));
  3368. error(RtAudioError::WARNING);
  3369. return FAILURE;
  3370. }
  3371. // Set the data format.
  3372. stream->userFormat = format;
  3373. stream->deviceFormat[mode] = format;
  3374. if (format == RTAUDIO_SINT8) {
  3375. result = alSetSampFmt(al_config, AL_SAMPFMT_TWOSCOMP);
  3376. result = alSetWidth(al_config, AL_SAMPLE_8);
  3377. }
  3378. else if (format == RTAUDIO_SINT16) {
  3379. result = alSetSampFmt(al_config, AL_SAMPFMT_TWOSCOMP);
  3380. result = alSetWidth(al_config, AL_SAMPLE_16);
  3381. }
  3382. else if (format == RTAUDIO_SINT24) {
  3383. // Our 24-bit format assumes the upper 3 bytes of a 4 byte word.
  3384. // The AL library uses the lower 3 bytes, so we'll need to do our
  3385. // own conversion.
  3386. result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT);
  3387. stream->deviceFormat[mode] = RTAUDIO_FLOAT32;
  3388. }
  3389. else if (format == RTAUDIO_SINT32) {
  3390. // The AL library doesn't seem to support the 32-bit integer
  3391. // format, so we'll need to do our own conversion.
  3392. result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT);
  3393. stream->deviceFormat[mode] = RTAUDIO_FLOAT32;
  3394. }
  3395. else if (format == RTAUDIO_FLOAT32)
  3396. result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT);
  3397. else if (format == RTAUDIO_FLOAT64)
  3398. result = alSetSampFmt(al_config, AL_SAMPFMT_DOUBLE);
  3399. if ( result == -1 ) {
  3400. sprintf(message,"RtAudio: AL error setting sample format in AL config: %s.",
  3401. alGetErrorString(oserror()));
  3402. error(RtAudioError::WARNING);
  3403. return FAILURE;
  3404. }
  3405. if (mode == PLAYBACK) {
  3406. // Set our device.
  3407. if (device == 0)
  3408. resource = AL_DEFAULT_OUTPUT;
  3409. else
  3410. resource = devices[device].id[0];
  3411. result = alSetDevice(al_config, resource);
  3412. if ( result == -1 ) {
  3413. sprintf(message,"RtAudio: AL error setting device (%s) in AL config: %s.",
  3414. devices[device].name, alGetErrorString(oserror()));
  3415. error(RtAudioError::WARNING);
  3416. return FAILURE;
  3417. }
  3418. // Open the port.
  3419. port = alOpenPort("RtAudio Output Port", "w", al_config);
  3420. if( !port ) {
  3421. sprintf(message,"RtAudio: AL error opening output port: %s.",
  3422. alGetErrorString(oserror()));
  3423. error(RtAudioError::WARNING);
  3424. return FAILURE;
  3425. }
  3426. // Set the sample rate
  3427. pvs[0].param = AL_MASTER_CLOCK;
  3428. pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE;
  3429. pvs[1].param = AL_RATE;
  3430. pvs[1].value.ll = alDoubleToFixed((double)sampleRate);
  3431. result = alSetParams(resource, pvs, 2);
  3432. if ( result < 0 ) {
  3433. alClosePort(port);
  3434. sprintf(message,"RtAudio: AL error setting sample rate (%d) for device (%s): %s.",
  3435. sampleRate, devices[device].name, alGetErrorString(oserror()));
  3436. error(RtAudioError::WARNING);
  3437. return FAILURE;
  3438. }
  3439. }
  3440. else { // mode == RECORD
  3441. // Set our device.
  3442. if (device == 0)
  3443. resource = AL_DEFAULT_INPUT;
  3444. else
  3445. resource = devices[device].id[1];
  3446. result = alSetDevice(al_config, resource);
  3447. if ( result == -1 ) {
  3448. sprintf(message,"RtAudio: AL error setting device (%s) in AL config: %s.",
  3449. devices[device].name, alGetErrorString(oserror()));
  3450. error(RtAudioError::WARNING);
  3451. return FAILURE;
  3452. }
  3453. // Open the port.
  3454. port = alOpenPort("RtAudio Output Port", "r", al_config);
  3455. if( !port ) {
  3456. sprintf(message,"RtAudio: AL error opening input port: %s.",
  3457. alGetErrorString(oserror()));
  3458. error(RtAudioError::WARNING);
  3459. return FAILURE;
  3460. }
  3461. // Set the sample rate
  3462. pvs[0].param = AL_MASTER_CLOCK;
  3463. pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE;
  3464. pvs[1].param = AL_RATE;
  3465. pvs[1].value.ll = alDoubleToFixed((double)sampleRate);
  3466. result = alSetParams(resource, pvs, 2);
  3467. if ( result < 0 ) {
  3468. alClosePort(port);
  3469. sprintf(message,"RtAudio: AL error setting sample rate (%d) for device (%s): %s.",
  3470. sampleRate, devices[device].name, alGetErrorString(oserror()));
  3471. error(RtAudioError::WARNING);
  3472. return FAILURE;
  3473. }
  3474. }
  3475. alFreeConfig(al_config);
  3476. stream->nUserChannels[mode] = channels;
  3477. stream->nDeviceChannels[mode] = channels;
  3478. // Set handle and flags for buffer conversion
  3479. stream->handle[mode] = port;
  3480. stream->doConvertBuffer[mode] = false;
  3481. if (stream->userFormat != stream->deviceFormat[mode])
  3482. stream->doConvertBuffer[mode] = true;
  3483. // Allocate necessary internal buffers
  3484. if ( stream->nUserChannels[0] != stream->nUserChannels[1] ) {
  3485. long buffer_bytes;
  3486. if (stream->nUserChannels[0] >= stream->nUserChannels[1])
  3487. buffer_bytes = stream->nUserChannels[0];
  3488. else
  3489. buffer_bytes = stream->nUserChannels[1];
  3490. buffer_bytes *= *bufferSize * formatBytes(stream->userFormat);
  3491. if (stream->userBuffer) free(stream->userBuffer);
  3492. stream->userBuffer = (char *) calloc(buffer_bytes, 1);
  3493. if (stream->userBuffer == NULL)
  3494. goto memory_error;
  3495. }
  3496. if ( stream->doConvertBuffer[mode] ) {
  3497. long buffer_bytes;
  3498. bool makeBuffer = true;
  3499. if ( mode == PLAYBACK )
  3500. buffer_bytes = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  3501. else { // mode == RECORD
  3502. buffer_bytes = stream->nDeviceChannels[1] * formatBytes(stream->deviceFormat[1]);
  3503. if ( stream->mode == PLAYBACK ) {
  3504. long bytes_out = stream->nDeviceChannels[0] * formatBytes(stream->deviceFormat[0]);
  3505. if ( buffer_bytes > bytes_out )
  3506. buffer_bytes = (buffer_bytes > bytes_out) ? buffer_bytes : bytes_out;
  3507. else
  3508. makeBuffer = false;
  3509. }
  3510. }
  3511. if ( makeBuffer ) {
  3512. buffer_bytes *= *bufferSize;
  3513. if (stream->deviceBuffer) free(stream->deviceBuffer);
  3514. stream->deviceBuffer = (char *) calloc(buffer_bytes, 1);
  3515. if (stream->deviceBuffer == NULL)
  3516. goto memory_error;
  3517. }
  3518. }
  3519. stream->device[mode] = device;
  3520. stream->state = STREAM_STOPPED;
  3521. if ( stream->mode == PLAYBACK && mode == RECORD )
  3522. // We had already set up an output stream.
  3523. stream->mode = DUPLEX;
  3524. else
  3525. stream->mode = mode;
  3526. stream->nBuffers = nBuffers;
  3527. stream->bufferSize = *bufferSize;
  3528. stream->sampleRate = sampleRate;
  3529. return SUCCESS;
  3530. memory_error:
  3531. if (stream->handle[0]) {
  3532. alClosePort(stream->handle[0]);
  3533. stream->handle[0] = 0;
  3534. }
  3535. if (stream->handle[1]) {
  3536. alClosePort(stream->handle[1]);
  3537. stream->handle[1] = 0;
  3538. }
  3539. if (stream->userBuffer) {
  3540. free(stream->userBuffer);
  3541. stream->userBuffer = 0;
  3542. }
  3543. sprintf(message, "RtAudio: ALSA error allocating buffer memory for device (%s).",
  3544. devices[device].name);
  3545. error(RtAudioError::WARNING);
  3546. return FAILURE;
  3547. }
  3548. void RtAudio :: cancelStreamCallback(int streamID)
  3549. {
  3550. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  3551. if (stream->usingCallback) {
  3552. stream->usingCallback = false;
  3553. pthread_cancel(stream->thread);
  3554. pthread_join(stream->thread, NULL);
  3555. stream->thread = 0;
  3556. stream->callback = NULL;
  3557. stream->userData = NULL;
  3558. }
  3559. }
  3560. void RtAudio :: closeStream(int streamID)
  3561. {
  3562. // We don't want an exception to be thrown here because this
  3563. // function is called by our class destructor. So, do our own
  3564. // streamID check.
  3565. if ( streams.find( streamID ) == streams.end() ) {
  3566. sprintf(message, "RtAudio: invalid stream identifier!");
  3567. error(RtAudioError::WARNING);
  3568. return;
  3569. }
  3570. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) streams[streamID];
  3571. if (stream->usingCallback) {
  3572. pthread_cancel(stream->thread);
  3573. pthread_join(stream->thread, NULL);
  3574. }
  3575. pthread_mutex_destroy(&stream->mutex);
  3576. if (stream->handle[0])
  3577. alClosePort(stream->handle[0]);
  3578. if (stream->handle[1])
  3579. alClosePort(stream->handle[1]);
  3580. if (stream->userBuffer)
  3581. free(stream->userBuffer);
  3582. if (stream->deviceBuffer)
  3583. free(stream->deviceBuffer);
  3584. free(stream);
  3585. streams.erase(streamID);
  3586. }
  3587. void RtAudio :: startStream(int streamID)
  3588. {
  3589. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  3590. if (stream->state == STREAM_RUNNING)
  3591. return;
  3592. // The AL port is ready as soon as it is opened.
  3593. stream->state = STREAM_RUNNING;
  3594. }
  3595. void RtAudio :: stopStream(int streamID)
  3596. {
  3597. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  3598. MUTEX_LOCK(&stream->mutex);
  3599. if (stream->state == STREAM_STOPPED)
  3600. goto unlock;
  3601. int result;
  3602. int buffer_size = stream->bufferSize * stream->nBuffers;
  3603. if (stream->mode == PLAYBACK || stream->mode == DUPLEX)
  3604. alZeroFrames(stream->handle[0], buffer_size);
  3605. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  3606. result = alDiscardFrames(stream->handle[1], buffer_size);
  3607. if (result == -1) {
  3608. sprintf(message, "RtAudio: AL error draining stream device (%s): %s.",
  3609. devices[stream->device[1]].name, alGetErrorString(oserror()));
  3610. error(RtAudioError::DRIVER_ERROR);
  3611. }
  3612. }
  3613. stream->state = STREAM_STOPPED;
  3614. unlock:
  3615. MUTEX_UNLOCK(&stream->mutex);
  3616. }
  3617. void RtAudio :: abortStream(int streamID)
  3618. {
  3619. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  3620. MUTEX_LOCK(&stream->mutex);
  3621. if (stream->state == STREAM_STOPPED)
  3622. goto unlock;
  3623. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  3624. int buffer_size = stream->bufferSize * stream->nBuffers;
  3625. int result = alDiscardFrames(stream->handle[0], buffer_size);
  3626. if (result == -1) {
  3627. sprintf(message, "RtAudio: AL error aborting stream device (%s): %s.",
  3628. devices[stream->device[0]].name, alGetErrorString(oserror()));
  3629. error(RtAudioError::DRIVER_ERROR);
  3630. }
  3631. }
  3632. // There is no clear action to take on the input stream, since the
  3633. // port will continue to run in any event.
  3634. stream->state = STREAM_STOPPED;
  3635. unlock:
  3636. MUTEX_UNLOCK(&stream->mutex);
  3637. }
  3638. int RtAudio :: streamWillBlock(int streamID)
  3639. {
  3640. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  3641. MUTEX_LOCK(&stream->mutex);
  3642. int frames = 0;
  3643. if (stream->state == STREAM_STOPPED)
  3644. goto unlock;
  3645. int err = 0;
  3646. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  3647. err = alGetFillable(stream->handle[0]);
  3648. if (err < 0) {
  3649. sprintf(message, "RtAudio: AL error getting available frames for stream (%s): %s.",
  3650. devices[stream->device[0]].name, alGetErrorString(oserror()));
  3651. error(RtAudioError::DRIVER_ERROR);
  3652. }
  3653. }
  3654. frames = err;
  3655. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  3656. err = alGetFilled(stream->handle[1]);
  3657. if (err < 0) {
  3658. sprintf(message, "RtAudio: AL error getting available frames for stream (%s): %s.",
  3659. devices[stream->device[1]].name, alGetErrorString(oserror()));
  3660. error(RtAudioError::DRIVER_ERROR);
  3661. }
  3662. if (frames > err) frames = err;
  3663. }
  3664. frames = stream->bufferSize - frames;
  3665. if (frames < 0) frames = 0;
  3666. unlock:
  3667. MUTEX_UNLOCK(&stream->mutex);
  3668. return frames;
  3669. }
  3670. void RtAudio :: tickStream(int streamID)
  3671. {
  3672. RTAUDIO_STREAM *stream = (RTAUDIO_STREAM *) verifyStream(streamID);
  3673. int stopStream = 0;
  3674. if (stream->state == STREAM_STOPPED) {
  3675. if (stream->usingCallback) usleep(50000); // sleep 50 milliseconds
  3676. return;
  3677. }
  3678. else if (stream->usingCallback) {
  3679. stopStream = stream->callback(stream->userBuffer, stream->bufferSize, stream->userData);
  3680. }
  3681. MUTEX_LOCK(&stream->mutex);
  3682. // The state might change while waiting on a mutex.
  3683. if (stream->state == STREAM_STOPPED)
  3684. goto unlock;
  3685. char *buffer;
  3686. int channels;
  3687. RTAUDIO_FORMAT format;
  3688. if (stream->mode == PLAYBACK || stream->mode == DUPLEX) {
  3689. // Setup parameters and do buffer conversion if necessary.
  3690. if (stream->doConvertBuffer[0]) {
  3691. convertStreamBuffer(stream, PLAYBACK);
  3692. buffer = stream->deviceBuffer;
  3693. channels = stream->nDeviceChannels[0];
  3694. format = stream->deviceFormat[0];
  3695. }
  3696. else {
  3697. buffer = stream->userBuffer;
  3698. channels = stream->nUserChannels[0];
  3699. format = stream->userFormat;
  3700. }
  3701. // Do byte swapping if necessary.
  3702. if (stream->doByteSwap[0])
  3703. byteSwapBuffer(buffer, stream->bufferSize * channels, format);
  3704. // Write interleaved samples to device.
  3705. alWriteFrames(stream->handle[0], buffer, stream->bufferSize);
  3706. }
  3707. if (stream->mode == RECORD || stream->mode == DUPLEX) {
  3708. // Setup parameters.
  3709. if (stream->doConvertBuffer[1]) {
  3710. buffer = stream->deviceBuffer;
  3711. channels = stream->nDeviceChannels[1];
  3712. format = stream->deviceFormat[1];
  3713. }
  3714. else {
  3715. buffer = stream->userBuffer;
  3716. channels = stream->nUserChannels[1];
  3717. format = stream->userFormat;
  3718. }
  3719. // Read interleaved samples from device.
  3720. alReadFrames(stream->handle[1], buffer, stream->bufferSize);
  3721. // Do byte swapping if necessary.
  3722. if (stream->doByteSwap[1])
  3723. byteSwapBuffer(buffer, stream->bufferSize * channels, format);
  3724. // Do buffer conversion if necessary.
  3725. if (stream->doConvertBuffer[1])
  3726. convertStreamBuffer(stream, RECORD);
  3727. }
  3728. unlock:
  3729. MUTEX_UNLOCK(&stream->mutex);
  3730. if (stream->usingCallback && stopStream)
  3731. this->stopStream(streamID);
  3732. }
  3733. extern "C" void *callbackHandler(void *ptr)
  3734. {
  3735. RtAudio *object = thread_info.object;
  3736. int stream = thread_info.streamID;
  3737. bool *usingCallback = (bool *) ptr;
  3738. while ( *usingCallback ) {
  3739. pthread_testcancel();
  3740. try {
  3741. object->tickStream(stream);
  3742. }
  3743. catch (RtAudioError &exception) {
  3744. fprintf(stderr, "\nCallback thread error (%s) ... closing thread.\n\n",
  3745. exception.getMessage());
  3746. break;
  3747. }
  3748. }
  3749. return 0;
  3750. }
  3751. //******************** End of __IRIX_AL_ *********************//
  3752. #endif
  3753. // *************************************************** //
  3754. //
  3755. // Private common (OS-independent) RtAudio methods.
  3756. //
  3757. // *************************************************** //
  3758. // This method can be modified to control the behavior of error
  3759. // message reporting and throwing.
  3760. void RtAudio :: error(RtAudioError::TYPE type)
  3761. {
  3762. if (type == RtAudioError::WARNING)
  3763. fprintf(stderr, "\n%s\n\n", message);
  3764. else if (type == RtAudioError::DEBUG_WARNING) {
  3765. #if defined(RTAUDIO_DEBUG)
  3766. fprintf(stderr, "\n%s\n\n", message);
  3767. #endif
  3768. }
  3769. else
  3770. throw RtAudioError(message, type);
  3771. }
  3772. void *RtAudio :: verifyStream(int streamID)
  3773. {
  3774. // Verify the stream key.
  3775. if ( streams.find( streamID ) == streams.end() ) {
  3776. sprintf(message, "RtAudio: invalid stream identifier!");
  3777. error(RtAudioError::INVALID_STREAM);
  3778. }
  3779. return streams[streamID];
  3780. }
  3781. void RtAudio :: clearDeviceInfo(RTAUDIO_DEVICE *info)
  3782. {
  3783. // Don't clear the name or DEVICE_ID fields here ... they are
  3784. // typically set prior to a call of this function.
  3785. info->probed = false;
  3786. info->maxOutputChannels = 0;
  3787. info->maxInputChannels = 0;
  3788. info->maxDuplexChannels = 0;
  3789. info->minOutputChannels = 0;
  3790. info->minInputChannels = 0;
  3791. info->minDuplexChannels = 0;
  3792. info->hasDuplexSupport = false;
  3793. info->nSampleRates = 0;
  3794. for (int i=0; i<MAX_SAMPLE_RATES; i++)
  3795. info->sampleRates[i] = 0;
  3796. info->nativeFormats = 0;
  3797. }
  3798. int RtAudio :: formatBytes(RTAUDIO_FORMAT format)
  3799. {
  3800. if (format == RTAUDIO_SINT16)
  3801. return 2;
  3802. else if (format == RTAUDIO_SINT24 || format == RTAUDIO_SINT32 ||
  3803. format == RTAUDIO_FLOAT32)
  3804. return 4;
  3805. else if (format == RTAUDIO_FLOAT64)
  3806. return 8;
  3807. else if (format == RTAUDIO_SINT8)
  3808. return 1;
  3809. sprintf(message,"RtAudio: undefined format in formatBytes().");
  3810. error(RtAudioError::WARNING);
  3811. return 0;
  3812. }
  3813. void RtAudio :: convertStreamBuffer(RTAUDIO_STREAM *stream, STREAM_MODE mode)
  3814. {
  3815. // This method does format conversion, input/output channel compensation, and
  3816. // data interleaving/deinterleaving. 24-bit integers are assumed to occupy
  3817. // the upper three bytes of a 32-bit integer.
  3818. int j, channels_in, channels_out, channels;
  3819. RTAUDIO_FORMAT format_in, format_out;
  3820. char *input, *output;
  3821. if (mode == RECORD) { // convert device to user buffer
  3822. input = stream->deviceBuffer;
  3823. output = stream->userBuffer;
  3824. channels_in = stream->nDeviceChannels[1];
  3825. channels_out = stream->nUserChannels[1];
  3826. format_in = stream->deviceFormat[1];
  3827. format_out = stream->userFormat;
  3828. }
  3829. else { // convert user to device buffer
  3830. input = stream->userBuffer;
  3831. output = stream->deviceBuffer;
  3832. channels_in = stream->nUserChannels[0];
  3833. channels_out = stream->nDeviceChannels[0];
  3834. format_in = stream->userFormat;
  3835. format_out = stream->deviceFormat[0];
  3836. // clear our device buffer when in/out duplex device channels are different
  3837. if ( stream->mode == DUPLEX &&
  3838. stream->nDeviceChannels[0] != stream->nDeviceChannels[1] )
  3839. memset(output, 0, stream->bufferSize * channels_out * formatBytes(format_out));
  3840. }
  3841. channels = (channels_in < channels_out) ? channels_in : channels_out;
  3842. // Set up the interleave/deinterleave offsets
  3843. std::vector<int> offset_in(channels);
  3844. std::vector<int> offset_out(channels);
  3845. if (mode == RECORD && stream->deInterleave[1]) {
  3846. for (int k=0; k<channels; k++) {
  3847. offset_in[k] = k * stream->bufferSize;
  3848. offset_out[k] = k;
  3849. }
  3850. }
  3851. else if (mode == PLAYBACK && stream->deInterleave[0]) {
  3852. for (int k=0; k<channels; k++) {
  3853. offset_in[k] = k;
  3854. offset_out[k] = k * stream->bufferSize;
  3855. }
  3856. }
  3857. else {
  3858. for (int k=0; k<channels; k++) {
  3859. offset_in[k] = k;
  3860. offset_out[k] = k;
  3861. }
  3862. }
  3863. if (format_out == RTAUDIO_FLOAT64) {
  3864. FLOAT64 scale;
  3865. FLOAT64 *out = (FLOAT64 *)output;
  3866. if (format_in == RTAUDIO_SINT8) {
  3867. signed char *in = (signed char *)input;
  3868. scale = 1.0 / 128.0;
  3869. for (int i=0; i<stream->bufferSize; i++) {
  3870. for (j=0; j<channels; j++) {
  3871. out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
  3872. out[offset_out[j]] *= scale;
  3873. }
  3874. in += channels_in;
  3875. out += channels_out;
  3876. }
  3877. }
  3878. else if (format_in == RTAUDIO_SINT16) {
  3879. INT16 *in = (INT16 *)input;
  3880. scale = 1.0 / 32768.0;
  3881. for (int i=0; i<stream->bufferSize; i++) {
  3882. for (j=0; j<channels; j++) {
  3883. out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
  3884. out[offset_out[j]] *= scale;
  3885. }
  3886. in += channels_in;
  3887. out += channels_out;
  3888. }
  3889. }
  3890. else if (format_in == RTAUDIO_SINT24) {
  3891. INT32 *in = (INT32 *)input;
  3892. scale = 1.0 / 2147483648.0;
  3893. for (int i=0; i<stream->bufferSize; i++) {
  3894. for (j=0; j<channels; j++) {
  3895. out[offset_out[j]] = (FLOAT64) (in[offset_in[j]] & 0xffffff00);
  3896. out[offset_out[j]] *= scale;
  3897. }
  3898. in += channels_in;
  3899. out += channels_out;
  3900. }
  3901. }
  3902. else if (format_in == RTAUDIO_SINT32) {
  3903. INT32 *in = (INT32 *)input;
  3904. scale = 1.0 / 2147483648.0;
  3905. for (int i=0; i<stream->bufferSize; i++) {
  3906. for (j=0; j<channels; j++) {
  3907. out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
  3908. out[offset_out[j]] *= scale;
  3909. }
  3910. in += channels_in;
  3911. out += channels_out;
  3912. }
  3913. }
  3914. else if (format_in == RTAUDIO_FLOAT32) {
  3915. FLOAT32 *in = (FLOAT32 *)input;
  3916. for (int i=0; i<stream->bufferSize; i++) {
  3917. for (j=0; j<channels; j++) {
  3918. out[offset_out[j]] = (FLOAT64) in[offset_in[j]];
  3919. }
  3920. in += channels_in;
  3921. out += channels_out;
  3922. }
  3923. }
  3924. else if (format_in == RTAUDIO_FLOAT64) {
  3925. // Channel compensation and/or (de)interleaving only.
  3926. FLOAT64 *in = (FLOAT64 *)input;
  3927. for (int i=0; i<stream->bufferSize; i++) {
  3928. for (j=0; j<channels; j++) {
  3929. out[offset_out[j]] = in[offset_in[j]];
  3930. }
  3931. in += channels_in;
  3932. out += channels_out;
  3933. }
  3934. }
  3935. }
  3936. else if (format_out == RTAUDIO_FLOAT32) {
  3937. FLOAT32 scale;
  3938. FLOAT32 *out = (FLOAT32 *)output;
  3939. if (format_in == RTAUDIO_SINT8) {
  3940. signed char *in = (signed char *)input;
  3941. scale = 1.0 / 128.0;
  3942. for (int i=0; i<stream->bufferSize; i++) {
  3943. for (j=0; j<channels; j++) {
  3944. out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
  3945. out[offset_out[j]] *= scale;
  3946. }
  3947. in += channels_in;
  3948. out += channels_out;
  3949. }
  3950. }
  3951. else if (format_in == RTAUDIO_SINT16) {
  3952. INT16 *in = (INT16 *)input;
  3953. scale = 1.0 / 32768.0;
  3954. for (int i=0; i<stream->bufferSize; i++) {
  3955. for (j=0; j<channels; j++) {
  3956. out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
  3957. out[offset_out[j]] *= scale;
  3958. }
  3959. in += channels_in;
  3960. out += channels_out;
  3961. }
  3962. }
  3963. else if (format_in == RTAUDIO_SINT24) {
  3964. INT32 *in = (INT32 *)input;
  3965. scale = 1.0 / 2147483648.0;
  3966. for (int i=0; i<stream->bufferSize; i++) {
  3967. for (j=0; j<channels; j++) {
  3968. out[offset_out[j]] = (FLOAT32) (in[offset_in[j]] & 0xffffff00);
  3969. out[offset_out[j]] *= scale;
  3970. }
  3971. in += channels_in;
  3972. out += channels_out;
  3973. }
  3974. }
  3975. else if (format_in == RTAUDIO_SINT32) {
  3976. INT32 *in = (INT32 *)input;
  3977. scale = 1.0 / 2147483648.0;
  3978. for (int i=0; i<stream->bufferSize; i++) {
  3979. for (j=0; j<channels; j++) {
  3980. out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
  3981. out[offset_out[j]] *= scale;
  3982. }
  3983. in += channels_in;
  3984. out += channels_out;
  3985. }
  3986. }
  3987. else if (format_in == RTAUDIO_FLOAT32) {
  3988. // Channel compensation and/or (de)interleaving only.
  3989. FLOAT32 *in = (FLOAT32 *)input;
  3990. for (int i=0; i<stream->bufferSize; i++) {
  3991. for (j=0; j<channels; j++) {
  3992. out[offset_out[j]] = in[offset_in[j]];
  3993. }
  3994. in += channels_in;
  3995. out += channels_out;
  3996. }
  3997. }
  3998. else if (format_in == RTAUDIO_FLOAT64) {
  3999. FLOAT64 *in = (FLOAT64 *)input;
  4000. for (int i=0; i<stream->bufferSize; i++) {
  4001. for (j=0; j<channels; j++) {
  4002. out[offset_out[j]] = (FLOAT32) in[offset_in[j]];
  4003. }
  4004. in += channels_in;
  4005. out += channels_out;
  4006. }
  4007. }
  4008. }
  4009. else if (format_out == RTAUDIO_SINT32) {
  4010. INT32 *out = (INT32 *)output;
  4011. if (format_in == RTAUDIO_SINT8) {
  4012. signed char *in = (signed char *)input;
  4013. for (int i=0; i<stream->bufferSize; i++) {
  4014. for (j=0; j<channels; j++) {
  4015. out[offset_out[j]] = (INT32) in[offset_in[j]];
  4016. out[offset_out[j]] <<= 24;
  4017. }
  4018. in += channels_in;
  4019. out += channels_out;
  4020. }
  4021. }
  4022. else if (format_in == RTAUDIO_SINT16) {
  4023. INT16 *in = (INT16 *)input;
  4024. for (int i=0; i<stream->bufferSize; i++) {
  4025. for (j=0; j<channels; j++) {
  4026. out[offset_out[j]] = (INT32) in[offset_in[j]];
  4027. out[offset_out[j]] <<= 16;
  4028. }
  4029. in += channels_in;
  4030. out += channels_out;
  4031. }
  4032. }
  4033. else if (format_in == RTAUDIO_SINT24) {
  4034. INT32 *in = (INT32 *)input;
  4035. for (int i=0; i<stream->bufferSize; i++) {
  4036. for (j=0; j<channels; j++) {
  4037. out[offset_out[j]] = (INT32) in[offset_in[j]];
  4038. }
  4039. in += channels_in;
  4040. out += channels_out;
  4041. }
  4042. }
  4043. else if (format_in == RTAUDIO_SINT32) {
  4044. // Channel compensation and/or (de)interleaving only.
  4045. INT32 *in = (INT32 *)input;
  4046. for (int i=0; i<stream->bufferSize; i++) {
  4047. for (j=0; j<channels; j++) {
  4048. out[offset_out[j]] = in[offset_in[j]];
  4049. }
  4050. in += channels_in;
  4051. out += channels_out;
  4052. }
  4053. }
  4054. else if (format_in == RTAUDIO_FLOAT32) {
  4055. FLOAT32 *in = (FLOAT32 *)input;
  4056. for (int i=0; i<stream->bufferSize; i++) {
  4057. for (j=0; j<channels; j++) {
  4058. out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
  4059. }
  4060. in += channels_in;
  4061. out += channels_out;
  4062. }
  4063. }
  4064. else if (format_in == RTAUDIO_FLOAT64) {
  4065. FLOAT64 *in = (FLOAT64 *)input;
  4066. for (int i=0; i<stream->bufferSize; i++) {
  4067. for (j=0; j<channels; j++) {
  4068. out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
  4069. }
  4070. in += channels_in;
  4071. out += channels_out;
  4072. }
  4073. }
  4074. }
  4075. else if (format_out == RTAUDIO_SINT24) {
  4076. INT32 *out = (INT32 *)output;
  4077. if (format_in == RTAUDIO_SINT8) {
  4078. signed char *in = (signed char *)input;
  4079. for (int i=0; i<stream->bufferSize; i++) {
  4080. for (j=0; j<channels; j++) {
  4081. out[offset_out[j]] = (INT32) in[offset_in[j]];
  4082. out[offset_out[j]] <<= 24;
  4083. }
  4084. in += channels_in;
  4085. out += channels_out;
  4086. }
  4087. }
  4088. else if (format_in == RTAUDIO_SINT16) {
  4089. INT16 *in = (INT16 *)input;
  4090. for (int i=0; i<stream->bufferSize; i++) {
  4091. for (j=0; j<channels; j++) {
  4092. out[offset_out[j]] = (INT32) in[offset_in[j]];
  4093. out[offset_out[j]] <<= 16;
  4094. }
  4095. in += channels_in;
  4096. out += channels_out;
  4097. }
  4098. }
  4099. else if (format_in == RTAUDIO_SINT24) {
  4100. // Channel compensation and/or (de)interleaving only.
  4101. INT32 *in = (INT32 *)input;
  4102. for (int i=0; i<stream->bufferSize; i++) {
  4103. for (j=0; j<channels; j++) {
  4104. out[offset_out[j]] = in[offset_in[j]];
  4105. }
  4106. in += channels_in;
  4107. out += channels_out;
  4108. }
  4109. }
  4110. else if (format_in == RTAUDIO_SINT32) {
  4111. INT32 *in = (INT32 *)input;
  4112. for (int i=0; i<stream->bufferSize; i++) {
  4113. for (j=0; j<channels; j++) {
  4114. out[offset_out[j]] = (INT32) (in[offset_in[j]] & 0xffffff00);
  4115. }
  4116. in += channels_in;
  4117. out += channels_out;
  4118. }
  4119. }
  4120. else if (format_in == RTAUDIO_FLOAT32) {
  4121. FLOAT32 *in = (FLOAT32 *)input;
  4122. for (int i=0; i<stream->bufferSize; i++) {
  4123. for (j=0; j<channels; j++) {
  4124. out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
  4125. }
  4126. in += channels_in;
  4127. out += channels_out;
  4128. }
  4129. }
  4130. else if (format_in == RTAUDIO_FLOAT64) {
  4131. FLOAT64 *in = (FLOAT64 *)input;
  4132. for (int i=0; i<stream->bufferSize; i++) {
  4133. for (j=0; j<channels; j++) {
  4134. out[offset_out[j]] = (INT32) (in[offset_in[j]] * 2147483647.0);
  4135. }
  4136. in += channels_in;
  4137. out += channels_out;
  4138. }
  4139. }
  4140. }
  4141. else if (format_out == RTAUDIO_SINT16) {
  4142. INT16 *out = (INT16 *)output;
  4143. if (format_in == RTAUDIO_SINT8) {
  4144. signed char *in = (signed char *)input;
  4145. for (int i=0; i<stream->bufferSize; i++) {
  4146. for (j=0; j<channels; j++) {
  4147. out[offset_out[j]] = (INT16) in[offset_in[j]];
  4148. out[offset_out[j]] <<= 8;
  4149. }
  4150. in += channels_in;
  4151. out += channels_out;
  4152. }
  4153. }
  4154. else if (format_in == RTAUDIO_SINT16) {
  4155. // Channel compensation and/or (de)interleaving only.
  4156. INT16 *in = (INT16 *)input;
  4157. for (int i=0; i<stream->bufferSize; i++) {
  4158. for (j=0; j<channels; j++) {
  4159. out[offset_out[j]] = in[offset_in[j]];
  4160. }
  4161. in += channels_in;
  4162. out += channels_out;
  4163. }
  4164. }
  4165. else if (format_in == RTAUDIO_SINT24) {
  4166. INT32 *in = (INT32 *)input;
  4167. for (int i=0; i<stream->bufferSize; i++) {
  4168. for (j=0; j<channels; j++) {
  4169. out[offset_out[j]] = (INT16) ((in[offset_in[j]] >> 16) & 0x0000ffff);
  4170. }
  4171. in += channels_in;
  4172. out += channels_out;
  4173. }
  4174. }
  4175. else if (format_in == RTAUDIO_SINT32) {
  4176. INT32 *in = (INT32 *)input;
  4177. for (int i=0; i<stream->bufferSize; i++) {
  4178. for (j=0; j<channels; j++) {
  4179. out[offset_out[j]] = (INT16) ((in[offset_in[j]] >> 16) & 0x0000ffff);
  4180. }
  4181. in += channels_in;
  4182. out += channels_out;
  4183. }
  4184. }
  4185. else if (format_in == RTAUDIO_FLOAT32) {
  4186. FLOAT32 *in = (FLOAT32 *)input;
  4187. for (int i=0; i<stream->bufferSize; i++) {
  4188. for (j=0; j<channels; j++) {
  4189. out[offset_out[j]] = (INT16) (in[offset_in[j]] * 32767.0);
  4190. }
  4191. in += channels_in;
  4192. out += channels_out;
  4193. }
  4194. }
  4195. else if (format_in == RTAUDIO_FLOAT64) {
  4196. FLOAT64 *in = (FLOAT64 *)input;
  4197. for (int i=0; i<stream->bufferSize; i++) {
  4198. for (j=0; j<channels; j++) {
  4199. out[offset_out[j]] = (INT16) (in[offset_in[j]] * 32767.0);
  4200. }
  4201. in += channels_in;
  4202. out += channels_out;
  4203. }
  4204. }
  4205. }
  4206. else if (format_out == RTAUDIO_SINT8) {
  4207. signed char *out = (signed char *)output;
  4208. if (format_in == RTAUDIO_SINT8) {
  4209. // Channel compensation and/or (de)interleaving only.
  4210. signed char *in = (signed char *)input;
  4211. for (int i=0; i<stream->bufferSize; i++) {
  4212. for (j=0; j<channels; j++) {
  4213. out[offset_out[j]] = in[offset_in[j]];
  4214. }
  4215. in += channels_in;
  4216. out += channels_out;
  4217. }
  4218. }
  4219. if (format_in == RTAUDIO_SINT16) {
  4220. INT16 *in = (INT16 *)input;
  4221. for (int i=0; i<stream->bufferSize; i++) {
  4222. for (j=0; j<channels; j++) {
  4223. out[offset_out[j]] = (signed char) ((in[offset_in[j]] >> 8) & 0x00ff);
  4224. }
  4225. in += channels_in;
  4226. out += channels_out;
  4227. }
  4228. }
  4229. else if (format_in == RTAUDIO_SINT24) {
  4230. INT32 *in = (INT32 *)input;
  4231. for (int i=0; i<stream->bufferSize; i++) {
  4232. for (j=0; j<channels; j++) {
  4233. out[offset_out[j]] = (signed char) ((in[offset_in[j]] >> 24) & 0x000000ff);
  4234. }
  4235. in += channels_in;
  4236. out += channels_out;
  4237. }
  4238. }
  4239. else if (format_in == RTAUDIO_SINT32) {
  4240. INT32 *in = (INT32 *)input;
  4241. for (int i=0; i<stream->bufferSize; i++) {
  4242. for (j=0; j<channels; j++) {
  4243. out[offset_out[j]] = (signed char) ((in[offset_in[j]] >> 24) & 0x000000ff);
  4244. }
  4245. in += channels_in;
  4246. out += channels_out;
  4247. }
  4248. }
  4249. else if (format_in == RTAUDIO_FLOAT32) {
  4250. FLOAT32 *in = (FLOAT32 *)input;
  4251. for (int i=0; i<stream->bufferSize; i++) {
  4252. for (j=0; j<channels; j++) {
  4253. out[offset_out[j]] = (signed char) (in[offset_in[j]] * 127.0);
  4254. }
  4255. in += channels_in;
  4256. out += channels_out;
  4257. }
  4258. }
  4259. else if (format_in == RTAUDIO_FLOAT64) {
  4260. FLOAT64 *in = (FLOAT64 *)input;
  4261. for (int i=0; i<stream->bufferSize; i++) {
  4262. for (j=0; j<channels; j++) {
  4263. out[offset_out[j]] = (signed char) (in[offset_in[j]] * 127.0);
  4264. }
  4265. in += channels_in;
  4266. out += channels_out;
  4267. }
  4268. }
  4269. }
  4270. }
  4271. void RtAudio :: byteSwapBuffer(char *buffer, int samples, RTAUDIO_FORMAT format)
  4272. {
  4273. register char val;
  4274. register char *ptr;
  4275. ptr = buffer;
  4276. if (format == RTAUDIO_SINT16) {
  4277. for (int i=0; i<samples; i++) {
  4278. // Swap 1st and 2nd bytes.
  4279. val = *(ptr);
  4280. *(ptr) = *(ptr+1);
  4281. *(ptr+1) = val;
  4282. // Increment 2 bytes.
  4283. ptr += 2;
  4284. }
  4285. }
  4286. else if (format == RTAUDIO_SINT24 ||
  4287. format == RTAUDIO_SINT32 ||
  4288. format == RTAUDIO_FLOAT32) {
  4289. for (int i=0; i<samples; i++) {
  4290. // Swap 1st and 4th bytes.
  4291. val = *(ptr);
  4292. *(ptr) = *(ptr+3);
  4293. *(ptr+3) = val;
  4294. // Swap 2nd and 3rd bytes.
  4295. ptr += 1;
  4296. val = *(ptr);
  4297. *(ptr) = *(ptr+1);
  4298. *(ptr+1) = val;
  4299. // Increment 4 bytes.
  4300. ptr += 4;
  4301. }
  4302. }
  4303. else if (format == RTAUDIO_FLOAT64) {
  4304. for (int i=0; i<samples; i++) {
  4305. // Swap 1st and 8th bytes
  4306. val = *(ptr);
  4307. *(ptr) = *(ptr+7);
  4308. *(ptr+7) = val;
  4309. // Swap 2nd and 7th bytes
  4310. ptr += 1;
  4311. val = *(ptr);
  4312. *(ptr) = *(ptr+5);
  4313. *(ptr+5) = val;
  4314. // Swap 3rd and 6th bytes
  4315. ptr += 1;
  4316. val = *(ptr);
  4317. *(ptr) = *(ptr+3);
  4318. *(ptr+3) = val;
  4319. // Swap 4th and 5th bytes
  4320. ptr += 1;
  4321. val = *(ptr);
  4322. *(ptr) = *(ptr+1);
  4323. *(ptr+1) = val;
  4324. // Increment 8 bytes.
  4325. ptr += 8;
  4326. }
  4327. }
  4328. }
  4329. // *************************************************** //
  4330. //
  4331. // RtAudioError class definition.
  4332. //
  4333. // *************************************************** //
  4334. RtAudioError :: RtAudioError(const char *p, TYPE tipe)
  4335. {
  4336. type = tipe;
  4337. strncpy(error_message, p, 256);
  4338. }
  4339. RtAudioError :: ~RtAudioError()
  4340. {
  4341. }
  4342. void RtAudioError :: printMessage()
  4343. {
  4344. printf("\n%s\n\n", error_message);
  4345. }