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.

5002 lines
160KB

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