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.

262 lines
7.4KB

  1. #include "rtaudio_c.h"
  2. #include "RtAudio.h"
  3. #include <cstring>
  4. #define MAX_ERROR_MESSAGE_LENGTH 512
  5. struct rtaudio {
  6. RtAudio *audio;
  7. rtaudio_cb_t cb;
  8. void *userdata;
  9. int has_error;
  10. char errmsg[MAX_ERROR_MESSAGE_LENGTH];
  11. };
  12. const char *rtaudio_version() { return RTAUDIO_VERSION; }
  13. extern "C" const RtAudio::Api rtaudio_compiled_apis[];
  14. const rtaudio_api_t *rtaudio_compiled_api() {
  15. return (rtaudio_api_t *) &rtaudio_compiled_apis[0];
  16. }
  17. extern "C" const unsigned int rtaudio_num_compiled_apis;
  18. unsigned int rtaudio_get_num_compiled_apis(void) {
  19. return rtaudio_num_compiled_apis;
  20. }
  21. extern "C" const char* rtaudio_api_names[][2];
  22. const char *rtaudio_api_name(rtaudio_api_t api) {
  23. if (api < 0 || api >= RTAUDIO_API_NUM)
  24. return NULL;
  25. return rtaudio_api_names[api][0];
  26. }
  27. const char *rtaudio_api_display_name(rtaudio_api_t api)
  28. {
  29. if (api < 0 || api >= RTAUDIO_API_NUM)
  30. return "Unknown";
  31. return rtaudio_api_names[api][1];
  32. }
  33. rtaudio_api_t rtaudio_compiled_api_by_name(const char *name) {
  34. RtAudio::Api api = RtAudio::UNSPECIFIED;
  35. if (name) {
  36. api = RtAudio::getCompiledApiByName(name);
  37. }
  38. return (rtaudio_api_t)api;
  39. }
  40. const char *rtaudio_error(rtaudio_t audio) {
  41. if (audio->has_error) {
  42. return audio->errmsg;
  43. }
  44. return NULL;
  45. }
  46. rtaudio_t rtaudio_create(rtaudio_api_t api) {
  47. rtaudio_t audio = new struct rtaudio();
  48. try {
  49. audio->audio = new RtAudio((RtAudio::Api)api);
  50. } catch (RtAudioError &err) {
  51. audio->has_error = 1;
  52. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  53. }
  54. return audio;
  55. }
  56. void rtaudio_destroy(rtaudio_t audio) { delete audio->audio; }
  57. rtaudio_api_t rtaudio_current_api(rtaudio_t audio) {
  58. return (rtaudio_api_t)audio->audio->getCurrentApi();
  59. }
  60. int rtaudio_device_count(rtaudio_t audio) {
  61. return audio->audio->getDeviceCount();
  62. }
  63. rtaudio_device_info_t rtaudio_get_device_info(rtaudio_t audio, int i) {
  64. rtaudio_device_info_t result;
  65. std::memset(&result, 0, sizeof(result));
  66. try {
  67. audio->has_error = 0;
  68. RtAudio::DeviceInfo info = audio->audio->getDeviceInfo(i);
  69. result.probed = info.probed;
  70. result.output_channels = info.outputChannels;
  71. result.input_channels = info.inputChannels;
  72. result.duplex_channels = info.duplexChannels;
  73. result.is_default_output = info.isDefaultOutput;
  74. result.is_default_input = info.isDefaultInput;
  75. result.native_formats = info.nativeFormats;
  76. result.preferred_sample_rate = info.preferredSampleRate;
  77. strncpy(result.name, info.name.c_str(), sizeof(result.name) - 1);
  78. for (unsigned int j = 0; j < info.sampleRates.size(); j++) {
  79. if (j < sizeof(result.sample_rates) / sizeof(result.sample_rates[0])) {
  80. result.sample_rates[j] = info.sampleRates[j];
  81. }
  82. }
  83. } catch (RtAudioError &err) {
  84. audio->has_error = 1;
  85. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  86. }
  87. return result;
  88. }
  89. unsigned int rtaudio_get_default_output_device(rtaudio_t audio) {
  90. return audio->audio->getDefaultOutputDevice();
  91. }
  92. unsigned int rtaudio_get_default_input_device(rtaudio_t audio) {
  93. return audio->audio->getDefaultInputDevice();
  94. }
  95. static int proxy_cb_func(void *out, void *in, unsigned int nframes, double time,
  96. RtAudioStreamStatus status, void *userdata) {
  97. rtaudio_t audio = (rtaudio_t)userdata;
  98. return audio->cb(out, in, nframes, time, (rtaudio_stream_status_t)status,
  99. audio->userdata);
  100. }
  101. int rtaudio_open_stream(rtaudio_t audio,
  102. rtaudio_stream_parameters_t *output_params,
  103. rtaudio_stream_parameters_t *input_params,
  104. rtaudio_format_t format, unsigned int sample_rate,
  105. unsigned int *buffer_frames, rtaudio_cb_t cb,
  106. void *userdata, rtaudio_stream_options_t *options,
  107. rtaudio_error_cb_t /*errcb*/) {
  108. try {
  109. audio->has_error = 0;
  110. RtAudio::StreamParameters *in = NULL;
  111. RtAudio::StreamParameters *out = NULL;
  112. RtAudio::StreamOptions *opts = NULL;
  113. RtAudio::StreamParameters inparams;
  114. RtAudio::StreamParameters outparams;
  115. RtAudio::StreamOptions stream_opts;
  116. if (input_params != NULL) {
  117. inparams.deviceId = input_params->device_id;
  118. inparams.nChannels = input_params->num_channels;
  119. inparams.firstChannel = input_params->first_channel;
  120. in = &inparams;
  121. }
  122. if (output_params != NULL) {
  123. outparams.deviceId = output_params->device_id;
  124. outparams.nChannels = output_params->num_channels;
  125. outparams.firstChannel = output_params->first_channel;
  126. out = &outparams;
  127. }
  128. if (options != NULL) {
  129. stream_opts.flags = (RtAudioStreamFlags)options->flags;
  130. stream_opts.numberOfBuffers = options->num_buffers;
  131. stream_opts.priority = options->priority;
  132. if (strlen(options->name) > 0) {
  133. stream_opts.streamName = std::string(options->name);
  134. }
  135. opts = &stream_opts;
  136. }
  137. audio->cb = cb;
  138. audio->userdata = userdata;
  139. audio->audio->openStream(out, in, (RtAudioFormat)format, sample_rate,
  140. buffer_frames, proxy_cb_func, (void *)audio, opts,
  141. NULL);
  142. return 0;
  143. } catch (RtAudioError &err) {
  144. audio->has_error = 1;
  145. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  146. return -1;
  147. }
  148. }
  149. void rtaudio_close_stream(rtaudio_t audio) { audio->audio->closeStream(); }
  150. int rtaudio_start_stream(rtaudio_t audio) {
  151. try {
  152. audio->has_error = 0;
  153. audio->audio->startStream();
  154. } catch (RtAudioError &err) {
  155. audio->has_error = 1;
  156. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  157. }
  158. return 0;
  159. }
  160. int rtaudio_stop_stream(rtaudio_t audio) {
  161. try {
  162. audio->has_error = 0;
  163. audio->audio->stopStream();
  164. } catch (RtAudioError &err) {
  165. audio->has_error = 1;
  166. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  167. }
  168. return 0;
  169. }
  170. int rtaudio_abort_stream(rtaudio_t audio) {
  171. try {
  172. audio->has_error = 0;
  173. audio->audio->abortStream();
  174. } catch (RtAudioError &err) {
  175. audio->has_error = 1;
  176. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  177. }
  178. return 0;
  179. }
  180. int rtaudio_is_stream_open(rtaudio_t audio) {
  181. return !!audio->audio->isStreamOpen();
  182. }
  183. int rtaudio_is_stream_running(rtaudio_t audio) {
  184. return !!audio->audio->isStreamRunning();
  185. }
  186. double rtaudio_get_stream_time(rtaudio_t audio) {
  187. try {
  188. audio->has_error = 0;
  189. return audio->audio->getStreamTime();
  190. } catch (RtAudioError &err) {
  191. audio->has_error = 1;
  192. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  193. return 0;
  194. }
  195. }
  196. void rtaudio_set_stream_time(rtaudio_t audio, double time) {
  197. try {
  198. audio->has_error = 0;
  199. audio->audio->setStreamTime(time);
  200. } catch (RtAudioError &err) {
  201. audio->has_error = 1;
  202. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  203. }
  204. }
  205. int rtaudio_get_stream_latency(rtaudio_t audio) {
  206. try {
  207. audio->has_error = 0;
  208. return audio->audio->getStreamLatency();
  209. } catch (RtAudioError &err) {
  210. audio->has_error = 1;
  211. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  212. return -1;
  213. }
  214. }
  215. unsigned int rtaudio_get_stream_sample_rate(rtaudio_t audio) {
  216. try {
  217. return audio->audio->getStreamSampleRate();
  218. } catch (RtAudioError &err) {
  219. audio->has_error = 1;
  220. strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
  221. return -1;
  222. }
  223. }
  224. void rtaudio_show_warnings(rtaudio_t audio, int show) {
  225. audio->audio->showWarnings(!!show);
  226. }