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.

369 lines
8.8KB

  1. #include "audio.hpp"
  2. #include "util/common.hpp"
  3. #include "bridge.hpp"
  4. #define BRIDGE_DRIVER -5000
  5. namespace rack {
  6. AudioIO::AudioIO() {
  7. setDriver(RtAudio::UNSPECIFIED);
  8. }
  9. AudioIO::~AudioIO() {
  10. closeStream();
  11. }
  12. std::vector<int> AudioIO::getDrivers() {
  13. std::vector<RtAudio::Api> apis;
  14. RtAudio::getCompiledApi(apis);
  15. std::vector<int> drivers;
  16. for (RtAudio::Api api : apis)
  17. drivers.push_back((int) api);
  18. // Add fake Bridge driver
  19. drivers.push_back(BRIDGE_DRIVER);
  20. return drivers;
  21. }
  22. std::string AudioIO::getDriverName(int driver) {
  23. switch (driver) {
  24. case RtAudio::UNSPECIFIED: return "Unspecified";
  25. case RtAudio::LINUX_ALSA: return "ALSA";
  26. case RtAudio::LINUX_PULSE: return "PulseAudio";
  27. case RtAudio::LINUX_OSS: return "OSS";
  28. case RtAudio::UNIX_JACK: return "JACK";
  29. case RtAudio::MACOSX_CORE: return "Core Audio";
  30. case RtAudio::WINDOWS_WASAPI: return "WASAPI";
  31. case RtAudio::WINDOWS_ASIO: return "ASIO";
  32. case RtAudio::WINDOWS_DS: return "DirectSound";
  33. case RtAudio::RTAUDIO_DUMMY: return "Dummy Audio";
  34. case BRIDGE_DRIVER: return "Bridge";
  35. default: return "Unknown";
  36. }
  37. }
  38. void AudioIO::setDriver(int driver) {
  39. // Close device
  40. setDevice(-1, 0);
  41. // Close driver
  42. if (rtAudio) {
  43. delete rtAudio;
  44. rtAudio = NULL;
  45. }
  46. this->driver = 0;
  47. // Open driver
  48. if (driver >= 0) {
  49. rtAudio = new RtAudio((RtAudio::Api) driver);
  50. this->driver = (int) rtAudio->getCurrentApi();
  51. }
  52. else if (driver == BRIDGE_DRIVER) {
  53. this->driver = BRIDGE_DRIVER;
  54. }
  55. }
  56. int AudioIO::getDeviceCount() {
  57. if (rtAudio) {
  58. return rtAudio->getDeviceCount();
  59. }
  60. if (driver == BRIDGE_DRIVER) {
  61. return BRIDGE_NUM_PORTS;
  62. }
  63. return 0;
  64. }
  65. bool AudioIO::getDeviceInfo(int device, RtAudio::DeviceInfo *deviceInfo) {
  66. if (!deviceInfo)
  67. return false;
  68. if (rtAudio) {
  69. if (device == this->device) {
  70. *deviceInfo = this->deviceInfo;
  71. return true;
  72. }
  73. else {
  74. try {
  75. *deviceInfo = rtAudio->getDeviceInfo(device);
  76. return true;
  77. }
  78. catch (RtAudioError &e) {
  79. warn("Failed to query RtAudio device: %s", e.what());
  80. }
  81. }
  82. }
  83. return false;
  84. }
  85. int AudioIO::getDeviceChannels(int device) {
  86. if (device < 0)
  87. return 0;
  88. if (rtAudio) {
  89. RtAudio::DeviceInfo deviceInfo;
  90. if (getDeviceInfo(device, &deviceInfo))
  91. return max((int) deviceInfo.inputChannels, (int) deviceInfo.outputChannels);
  92. }
  93. if (driver == BRIDGE_DRIVER) {
  94. return 2;
  95. }
  96. return 0;
  97. }
  98. std::string AudioIO::getDeviceName(int device) {
  99. if (device < 0)
  100. return "";
  101. if (rtAudio) {
  102. RtAudio::DeviceInfo deviceInfo;
  103. if (getDeviceInfo(device, &deviceInfo))
  104. return deviceInfo.name;
  105. }
  106. if (driver == BRIDGE_DRIVER) {
  107. return stringf("%d", device + 1);
  108. }
  109. return "";
  110. }
  111. std::string AudioIO::getDeviceDetail(int device, int offset) {
  112. if (device < 0)
  113. return "";
  114. if (rtAudio) {
  115. RtAudio::DeviceInfo deviceInfo;
  116. if (getDeviceInfo(device, &deviceInfo)) {
  117. std::string deviceDetail = stringf("%s (", deviceInfo.name.c_str());
  118. if (offset < (int) deviceInfo.inputChannels)
  119. deviceDetail += stringf("%d-%d in", offset + 1, min(offset + maxChannels, (int) deviceInfo.inputChannels));
  120. if (offset < (int) deviceInfo.inputChannels && offset < (int) deviceInfo.outputChannels)
  121. deviceDetail += ", ";
  122. if (offset < (int) deviceInfo.outputChannels)
  123. deviceDetail += stringf("%d-%d out", offset + 1, min(offset + maxChannels, (int) deviceInfo.outputChannels));
  124. deviceDetail += ")";
  125. return deviceDetail;
  126. }
  127. }
  128. if (driver == BRIDGE_DRIVER) {
  129. return stringf("Port %d", device + 1);
  130. }
  131. return "";
  132. }
  133. void AudioIO::setDevice(int device, int offset) {
  134. closeStream();
  135. this->device = device;
  136. this->offset = offset;
  137. openStream();
  138. }
  139. void AudioIO::setSampleRate(int sampleRate) {
  140. closeStream();
  141. this->sampleRate = sampleRate;
  142. openStream();
  143. }
  144. void AudioIO::setBlockSize(int blockSize) {
  145. closeStream();
  146. this->blockSize = blockSize;
  147. openStream();
  148. }
  149. void AudioIO::setChannels(int numOutputs, int numInputs) {
  150. this->numOutputs = numOutputs;
  151. this->numInputs = numInputs;
  152. onChannelsChange();
  153. }
  154. static int rtCallback(void *outputBuffer, void *inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status, void *userData) {
  155. AudioIO *audioIO = (AudioIO*) userData;
  156. assert(audioIO);
  157. audioIO->processStream((const float *) inputBuffer, (float *) outputBuffer, nFrames);
  158. return 0;
  159. }
  160. void AudioIO::openStream() {
  161. if (device < 0)
  162. return;
  163. if (rtAudio) {
  164. // Open new device
  165. try {
  166. deviceInfo = rtAudio->getDeviceInfo(device);
  167. }
  168. catch (RtAudioError &e) {
  169. warn("Failed to query RtAudio device: %s", e.what());
  170. return;
  171. }
  172. if (rtAudio->isStreamOpen())
  173. return;
  174. setChannels(clamp((int) deviceInfo.outputChannels - offset, 0, maxChannels), clamp((int) deviceInfo.inputChannels - offset, 0, maxChannels));
  175. if (numOutputs == 0 && numInputs == 0) {
  176. warn("RtAudio device %d has 0 inputs and 0 outputs", device);
  177. return;
  178. }
  179. RtAudio::StreamParameters outParameters;
  180. outParameters.deviceId = device;
  181. outParameters.nChannels = numOutputs;
  182. outParameters.firstChannel = offset;
  183. RtAudio::StreamParameters inParameters;
  184. inParameters.deviceId = device;
  185. inParameters.nChannels = numInputs;
  186. inParameters.firstChannel = offset;
  187. RtAudio::StreamOptions options;
  188. options.flags |= RTAUDIO_JACK_DONT_CONNECT;
  189. int closestSampleRate = deviceInfo.preferredSampleRate;
  190. for (int sr : deviceInfo.sampleRates) {
  191. if (abs(sr - sampleRate) < abs(closestSampleRate - sampleRate)) {
  192. closestSampleRate = sr;
  193. }
  194. }
  195. try {
  196. info("Opening audio RtAudio device %d with %d in %d out", device, numInputs, numOutputs);
  197. rtAudio->openStream(
  198. numOutputs == 0 ? NULL : &outParameters,
  199. numInputs == 0 ? NULL : &inParameters,
  200. RTAUDIO_FLOAT32, closestSampleRate, (unsigned int*) &blockSize,
  201. &rtCallback, this, &options, NULL);
  202. }
  203. catch (RtAudioError &e) {
  204. warn("Failed to open RtAudio stream: %s", e.what());
  205. return;
  206. }
  207. try {
  208. info("Starting RtAudio stream %d", device);
  209. rtAudio->startStream();
  210. }
  211. catch (RtAudioError &e) {
  212. warn("Failed to start RtAudio stream: %s", e.what());
  213. return;
  214. }
  215. // Update sample rate because this may have changed
  216. this->sampleRate = rtAudio->getStreamSampleRate();
  217. onOpenStream();
  218. }
  219. if (driver == BRIDGE_DRIVER) {
  220. setChannels(0, 0);
  221. // TEMP
  222. sampleRate = 44100;
  223. blockSize = 256;
  224. bridgeAudioSubscribe(device, this);
  225. }
  226. }
  227. void AudioIO::closeStream() {
  228. setChannels(0, 0);
  229. if (rtAudio) {
  230. if (rtAudio->isStreamRunning()) {
  231. info("Stopping RtAudio stream %d", device);
  232. try {
  233. rtAudio->stopStream();
  234. }
  235. catch (RtAudioError &e) {
  236. warn("Failed to stop RtAudio stream %s", e.what());
  237. }
  238. }
  239. if (rtAudio->isStreamOpen()) {
  240. info("Closing RtAudio stream %d", device);
  241. try {
  242. rtAudio->closeStream();
  243. }
  244. catch (RtAudioError &e) {
  245. warn("Failed to close RtAudio stream %s", e.what());
  246. }
  247. }
  248. deviceInfo = RtAudio::DeviceInfo();
  249. }
  250. if (driver == BRIDGE_DRIVER) {
  251. bridgeAudioUnsubscribe(device, this);
  252. }
  253. onCloseStream();
  254. }
  255. std::vector<int> AudioIO::getSampleRates() {
  256. if (rtAudio) {
  257. try {
  258. RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(device);
  259. std::vector<int> sampleRates(deviceInfo.sampleRates.begin(), deviceInfo.sampleRates.end());
  260. return sampleRates;
  261. }
  262. catch (RtAudioError &e) {
  263. warn("Failed to query RtAudio device: %s", e.what());
  264. }
  265. }
  266. if (driver == BRIDGE_DRIVER) {
  267. return {44100, 48000, 88200, 96000, 176400, 192000};
  268. }
  269. return {};
  270. }
  271. json_t *AudioIO::toJson() {
  272. json_t *rootJ = json_object();
  273. json_object_set_new(rootJ, "driver", json_integer(driver));
  274. std::string deviceName = getDeviceName(device);
  275. json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
  276. json_object_set_new(rootJ, "offset", json_integer(offset));
  277. json_object_set_new(rootJ, "maxChannels", json_integer(maxChannels));
  278. json_object_set_new(rootJ, "sampleRate", json_integer(sampleRate));
  279. json_object_set_new(rootJ, "blockSize", json_integer(blockSize));
  280. return rootJ;
  281. }
  282. void AudioIO::fromJson(json_t *rootJ) {
  283. closeStream();
  284. json_t *driverJ = json_object_get(rootJ, "driver");
  285. if (driverJ)
  286. setDriver(json_number_value(driverJ));
  287. json_t *deviceNameJ = json_object_get(rootJ, "deviceName");
  288. if (deviceNameJ) {
  289. std::string deviceName = json_string_value(deviceNameJ);
  290. // Search for device ID with equal name
  291. for (int device = 0; device < getDeviceCount(); device++) {
  292. if (getDeviceName(device) == deviceName) {
  293. this->device = device;
  294. break;
  295. }
  296. }
  297. }
  298. json_t *offsetJ = json_object_get(rootJ, "offset");
  299. if (offsetJ)
  300. offset = json_integer_value(offsetJ);
  301. json_t *maxChannelsJ = json_object_get(rootJ, "maxChannels");
  302. if (maxChannelsJ)
  303. maxChannels = json_integer_value(maxChannelsJ);
  304. json_t *sampleRateJ = json_object_get(rootJ, "sampleRate");
  305. if (sampleRateJ)
  306. sampleRate = json_integer_value(sampleRateJ);
  307. json_t *blockSizeJ = json_object_get(rootJ, "blockSize");
  308. if (blockSizeJ)
  309. blockSize = json_integer_value(blockSizeJ);
  310. openStream();
  311. }
  312. } // namespace rack