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.

257 lines
7.3KB

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