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.

370 lines
9.0KB

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