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.

372 lines
9.1KB

  1. #include "rack.hpp"
  2. #include "audio.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. }
  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. else 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 std::max((int) deviceInfo.inputChannels, (int) deviceInfo.outputChannels);
  92. }
  93. else if (driver == BRIDGE_DRIVER) {
  94. return std::max(BRIDGE_OUTPUTS, BRIDGE_INPUTS);
  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. else if (driver == BRIDGE_DRIVER) {
  107. return string::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 = string::stringf("%s (", deviceInfo.name.c_str());
  118. if (offset < (int) deviceInfo.inputChannels)
  119. deviceDetail += string::stringf("%d-%d in", offset + 1, std::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 += string::stringf("%d-%d out", offset + 1, std::min(offset + maxChannels, (int) deviceInfo.outputChannels));
  124. deviceDetail += ")";
  125. return deviceDetail;
  126. }
  127. }
  128. else if (driver == BRIDGE_DRIVER) {
  129. return string::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. std::vector<int> AudioIO::getSampleRates() {
  140. if (rtAudio) {
  141. try {
  142. RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(device);
  143. std::vector<int> sampleRates(deviceInfo.sampleRates.begin(), deviceInfo.sampleRates.end());
  144. return sampleRates;
  145. }
  146. catch (RtAudioError &e) {
  147. WARN("Failed to query RtAudio device: %s", e.what());
  148. }
  149. }
  150. return {};
  151. }
  152. void AudioIO::setSampleRate(int sampleRate) {
  153. if (sampleRate == this->sampleRate)
  154. return;
  155. closeStream();
  156. this->sampleRate = sampleRate;
  157. openStream();
  158. }
  159. std::vector<int> AudioIO::getBlockSizes() {
  160. if (rtAudio) {
  161. return {64, 128, 256, 512, 1024, 2048, 4096};
  162. }
  163. return {};
  164. }
  165. void AudioIO::setBlockSize(int blockSize) {
  166. if (blockSize == this->blockSize)
  167. return;
  168. closeStream();
  169. this->blockSize = blockSize;
  170. openStream();
  171. }
  172. void AudioIO::setChannels(int numOutputs, int numInputs) {
  173. this->numOutputs = numOutputs;
  174. this->numInputs = numInputs;
  175. onChannelsChange();
  176. }
  177. static int rtCallback(void *outputBuffer, void *inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status, void *userData) {
  178. AudioIO *audioIO = (AudioIO*) userData;
  179. assert(audioIO);
  180. audioIO->processStream((const float *) inputBuffer, (float *) outputBuffer, nFrames);
  181. return 0;
  182. }
  183. void AudioIO::openStream() {
  184. if (device < 0)
  185. return;
  186. if (rtAudio) {
  187. // Open new device
  188. try {
  189. deviceInfo = rtAudio->getDeviceInfo(device);
  190. }
  191. catch (RtAudioError &e) {
  192. WARN("Failed to query RtAudio device: %s", e.what());
  193. return;
  194. }
  195. if (rtAudio->isStreamOpen())
  196. return;
  197. setChannels(math::clamp((int) deviceInfo.outputChannels - offset, 0, maxChannels), math::clamp((int) deviceInfo.inputChannels - offset, 0, maxChannels));
  198. if (numOutputs == 0 && numInputs == 0) {
  199. WARN("RtAudio device %d has 0 inputs and 0 outputs", device);
  200. return;
  201. }
  202. RtAudio::StreamParameters outParameters;
  203. outParameters.deviceId = device;
  204. outParameters.nChannels = numOutputs;
  205. outParameters.firstChannel = offset;
  206. RtAudio::StreamParameters inParameters;
  207. inParameters.deviceId = device;
  208. inParameters.nChannels = numInputs;
  209. inParameters.firstChannel = offset;
  210. RtAudio::StreamOptions options;
  211. options.flags |= RTAUDIO_JACK_DONT_CONNECT;
  212. options.streamName = "VCV Rack";
  213. int closestSampleRate = deviceInfo.preferredSampleRate;
  214. for (int sr : deviceInfo.sampleRates) {
  215. if (std::abs(sr - sampleRate) < std::abs(closestSampleRate - sampleRate)) {
  216. closestSampleRate = sr;
  217. }
  218. }
  219. try {
  220. INFO("Opening audio RtAudio device %d with %d in %d out", device, numInputs, numOutputs);
  221. rtAudio->openStream(
  222. numOutputs == 0 ? NULL : &outParameters,
  223. numInputs == 0 ? NULL : &inParameters,
  224. RTAUDIO_FLOAT32, closestSampleRate, (unsigned int*) &blockSize,
  225. &rtCallback, this, &options, NULL);
  226. }
  227. catch (RtAudioError &e) {
  228. WARN("Failed to open RtAudio stream: %s", e.what());
  229. return;
  230. }
  231. try {
  232. INFO("Starting RtAudio stream %d", device);
  233. rtAudio->startStream();
  234. }
  235. catch (RtAudioError &e) {
  236. WARN("Failed to start RtAudio stream: %s", e.what());
  237. return;
  238. }
  239. // Update sample rate because this may have changed
  240. this->sampleRate = rtAudio->getStreamSampleRate();
  241. onOpenStream();
  242. }
  243. else if (driver == BRIDGE_DRIVER) {
  244. setChannels(BRIDGE_OUTPUTS, BRIDGE_INPUTS);
  245. bridgeAudioSubscribe(device, this);
  246. }
  247. }
  248. void AudioIO::closeStream() {
  249. setChannels(0, 0);
  250. if (rtAudio) {
  251. if (rtAudio->isStreamRunning()) {
  252. INFO("Stopping RtAudio stream %d", device);
  253. try {
  254. rtAudio->stopStream();
  255. }
  256. catch (RtAudioError &e) {
  257. WARN("Failed to stop RtAudio stream %s", e.what());
  258. }
  259. }
  260. if (rtAudio->isStreamOpen()) {
  261. INFO("Closing RtAudio stream %d", device);
  262. try {
  263. rtAudio->closeStream();
  264. }
  265. catch (RtAudioError &e) {
  266. WARN("Failed to close RtAudio stream %s", e.what());
  267. }
  268. }
  269. deviceInfo = RtAudio::DeviceInfo();
  270. }
  271. else if (driver == BRIDGE_DRIVER) {
  272. bridgeAudioUnsubscribe(device, this);
  273. }
  274. onCloseStream();
  275. }
  276. json_t *AudioIO::toJson() {
  277. json_t *rootJ = json_object();
  278. json_object_set_new(rootJ, "driver", json_integer(driver));
  279. std::string deviceName = getDeviceName(device);
  280. json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
  281. json_object_set_new(rootJ, "offset", json_integer(offset));
  282. json_object_set_new(rootJ, "maxChannels", json_integer(maxChannels));
  283. json_object_set_new(rootJ, "sampleRate", json_integer(sampleRate));
  284. json_object_set_new(rootJ, "blockSize", json_integer(blockSize));
  285. return rootJ;
  286. }
  287. void AudioIO::fromJson(json_t *rootJ) {
  288. closeStream();
  289. json_t *driverJ = json_object_get(rootJ, "driver");
  290. if (driverJ)
  291. setDriver(json_number_value(driverJ));
  292. json_t *deviceNameJ = json_object_get(rootJ, "deviceName");
  293. if (deviceNameJ) {
  294. std::string deviceName = json_string_value(deviceNameJ);
  295. // Search for device ID with equal name
  296. for (int device = 0; device < getDeviceCount(); device++) {
  297. if (getDeviceName(device) == deviceName) {
  298. this->device = device;
  299. break;
  300. }
  301. }
  302. }
  303. json_t *offsetJ = json_object_get(rootJ, "offset");
  304. if (offsetJ)
  305. offset = json_integer_value(offsetJ);
  306. json_t *maxChannelsJ = json_object_get(rootJ, "maxChannels");
  307. if (maxChannelsJ)
  308. maxChannels = json_integer_value(maxChannelsJ);
  309. json_t *sampleRateJ = json_object_get(rootJ, "sampleRate");
  310. if (sampleRateJ)
  311. sampleRate = json_integer_value(sampleRateJ);
  312. json_t *blockSizeJ = json_object_get(rootJ, "blockSize");
  313. if (blockSizeJ)
  314. blockSize = json_integer_value(blockSizeJ);
  315. openStream();
  316. }
  317. } // namespace rack