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.

422 lines
8.6KB

  1. #include <audio.hpp>
  2. #include <string.hpp>
  3. #include <math.hpp>
  4. namespace rack {
  5. namespace audio {
  6. static std::vector<std::pair<int, Driver*>> drivers;
  7. ////////////////////
  8. // Driver
  9. ////////////////////
  10. ////////////////////
  11. // Device
  12. ////////////////////
  13. void Device::subscribe(Port* port) {
  14. std::lock_guard<std::mutex> lock(processMutex);
  15. subscribed.insert(port);
  16. }
  17. void Device::unsubscribe(Port* port) {
  18. std::lock_guard<std::mutex> lock(processMutex);
  19. auto it = subscribed.find(port);
  20. if (it != subscribed.end())
  21. subscribed.erase(it);
  22. }
  23. void Device::processBuffer(const float* input, int inputStride, float* output, int outputStride, int frames) {
  24. // Zero output since Ports might not write to all elements, or no Ports exist
  25. std::fill_n(output, frames * outputStride, 0.f);
  26. std::lock_guard<std::mutex> lock(processMutex);
  27. for (Port* port : subscribed) {
  28. // Setting the thread context should probably be the responsibility of Port, but because processInput() etc are overridden, this is the only good place for it.
  29. contextSet(port->context);
  30. port->processInput(input + port->inputOffset, inputStride, frames);
  31. }
  32. for (Port* port : subscribed) {
  33. contextSet(port->context);
  34. port->processBuffer(input + port->inputOffset, inputStride, output + port->outputOffset, outputStride, frames);
  35. }
  36. for (Port* port : subscribed) {
  37. contextSet(port->context);
  38. port->processOutput(output + port->outputOffset, outputStride, frames);
  39. }
  40. }
  41. void Device::onStartStream() {
  42. for (Port* port : subscribed) {
  43. contextSet(port->context);
  44. port->onStartStream();
  45. }
  46. }
  47. void Device::onStopStream() {
  48. for (Port* port : subscribed) {
  49. contextSet(port->context);
  50. port->onStopStream();
  51. }
  52. }
  53. ////////////////////
  54. // Port
  55. ////////////////////
  56. Port::Port() {
  57. context = contextGet();
  58. reset();
  59. }
  60. Port::~Port() {
  61. setDeviceId(-1);
  62. }
  63. void Port::reset() {
  64. // Set default driver
  65. setDriverId(-1);
  66. }
  67. Driver* Port::getDriver() {
  68. return driver;
  69. }
  70. int Port::getDriverId() {
  71. return driverId;
  72. }
  73. void Port::setDriverId(int driverId) {
  74. // Unset device and driver
  75. setDeviceId(-1);
  76. driver = NULL;
  77. this->driverId = -1;
  78. // Find driver by ID
  79. driver = audio::getDriver(driverId);
  80. if (driver) {
  81. this->driverId = driverId;
  82. }
  83. else if (!drivers.empty()) {
  84. // Set first driver as default
  85. driver = drivers[0].second;
  86. this->driverId = drivers[0].first;
  87. }
  88. else {
  89. // No fallback drivers
  90. return;
  91. }
  92. // Set default device if exists
  93. try {
  94. int defaultDeviceId = driver->getDefaultDeviceId();
  95. if (defaultDeviceId >= 0)
  96. setDeviceId(defaultDeviceId);
  97. }
  98. catch (Exception& e) {
  99. WARN("Audio port could not get default device ID: %s", e.what());
  100. }
  101. }
  102. std::string Port::getDriverName() {
  103. if (!driver)
  104. return "";
  105. try {
  106. return driver->getName();
  107. }
  108. catch (Exception& e) {
  109. WARN("Audio port could not get driver name: %s", e.what());
  110. return "";
  111. }
  112. }
  113. Device* Port::getDevice() {
  114. return device;
  115. }
  116. std::vector<int> Port::getDeviceIds() {
  117. if (!driver)
  118. return {};
  119. try {
  120. return driver->getDeviceIds();
  121. }
  122. catch (Exception& e) {
  123. WARN("Audio port could not get device IDs: %s", e.what());
  124. return {};
  125. }
  126. }
  127. int Port::getDeviceId() {
  128. return deviceId;
  129. }
  130. void Port::setDeviceId(int deviceId) {
  131. if (!driver)
  132. return;
  133. if (deviceId == this->deviceId)
  134. return;
  135. // Destroy device
  136. if (this->deviceId >= 0) {
  137. try {
  138. driver->unsubscribe(this->deviceId, this);
  139. onStopStream();
  140. }
  141. catch (Exception& e) {
  142. WARN("Audio port could not unsubscribe from device: %s", e.what());
  143. }
  144. }
  145. device = NULL;
  146. this->deviceId = -1;
  147. // Create device
  148. if (deviceId >= 0) {
  149. try {
  150. device = driver->subscribe(deviceId, this);
  151. if (device) {
  152. this->deviceId = deviceId;
  153. onStartStream();
  154. }
  155. }
  156. catch (Exception& e) {
  157. WARN("Audio port could not subscribe to device: %s", e.what());
  158. }
  159. }
  160. }
  161. int Port::getDeviceNumInputs(int deviceId) {
  162. if (!driver)
  163. return 0;
  164. try {
  165. return driver->getDeviceNumInputs(deviceId);
  166. }
  167. catch (Exception& e) {
  168. WARN("Audio port could not get device number of inputs: %s", e.what());
  169. return 0;
  170. }
  171. }
  172. int Port::getDeviceNumOutputs(int deviceId) {
  173. if (!driver)
  174. return 0;
  175. try {
  176. return driver->getDeviceNumOutputs(deviceId);
  177. }
  178. catch (Exception& e) {
  179. WARN("Audio port could not get device number of outputs: %s", e.what());
  180. return 0;
  181. }
  182. }
  183. std::string Port::getDeviceName(int deviceId) {
  184. if (!driver)
  185. return "";
  186. try {
  187. return driver->getDeviceName(deviceId);
  188. }
  189. catch (Exception& e) {
  190. WARN("Audio port could not get device name: %s", e.what());
  191. return 0;
  192. }
  193. }
  194. std::set<float> Port::getSampleRates() {
  195. if (!device)
  196. return {};
  197. try {
  198. return device->getSampleRates();
  199. }
  200. catch (Exception& e) {
  201. WARN("Audio port could not get device sample rates: %s", e.what());
  202. return {};
  203. }
  204. }
  205. float Port::getSampleRate() {
  206. if (!device)
  207. return 0;
  208. try {
  209. return device->getSampleRate();
  210. }
  211. catch (Exception& e) {
  212. WARN("Audio port could not get device sample rate: %s", e.what());
  213. return 0;
  214. }
  215. }
  216. void Port::setSampleRate(float sampleRate) {
  217. if (!device)
  218. return;
  219. try {
  220. device->setSampleRate(sampleRate);
  221. }
  222. catch (Exception& e) {
  223. WARN("Audio port could not set device sample rate: %s", e.what());
  224. }
  225. }
  226. std::set<int> Port::getBlockSizes() {
  227. if (!device)
  228. return {};
  229. try {
  230. return device->getBlockSizes();
  231. }
  232. catch (Exception& e) {
  233. WARN("Audio port could not get device block sizes: %s", e.what());
  234. return {};
  235. }
  236. }
  237. int Port::getBlockSize() {
  238. if (!device)
  239. return 0;
  240. try {
  241. return device->getBlockSize();
  242. }
  243. catch (Exception& e) {
  244. WARN("Audio port could not get device block size: %s", e.what());
  245. return 0;
  246. }
  247. }
  248. void Port::setBlockSize(int blockSize) {
  249. if (!device)
  250. return;
  251. try {
  252. device->setBlockSize(blockSize);
  253. }
  254. catch (Exception& e) {
  255. WARN("Audio port could not set device block size: %s", e.what());
  256. }
  257. }
  258. int Port::getNumInputs() {
  259. if (!device)
  260. return 0;
  261. try {
  262. return math::clamp(device->getNumInputs() - inputOffset, 0, maxInputs);
  263. }
  264. catch (Exception& e) {
  265. WARN("Audio port could not get device number of inputs: %s", e.what());
  266. return 0;
  267. }
  268. }
  269. int Port::getNumOutputs() {
  270. if (!device)
  271. return 0;
  272. try {
  273. return math::clamp(device->getNumOutputs() - outputOffset, 0, maxOutputs);
  274. }
  275. catch (Exception& e) {
  276. WARN("Audio port could not get device number of outputs: %s", e.what());
  277. return 0;
  278. }
  279. }
  280. json_t* Port::toJson() {
  281. json_t* rootJ = json_object();
  282. json_object_set_new(rootJ, "driver", json_integer(getDriverId()));
  283. if (device) {
  284. try {
  285. std::string deviceName = device->getName();
  286. json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
  287. }
  288. catch (Exception& e) {
  289. WARN("Audio port could not get device name: %s", e.what());
  290. }
  291. }
  292. json_object_set_new(rootJ, "sampleRate", json_real(getSampleRate()));
  293. json_object_set_new(rootJ, "blockSize", json_integer(getBlockSize()));
  294. json_object_set_new(rootJ, "inputOffset", json_integer(inputOffset));
  295. json_object_set_new(rootJ, "outputOffset", json_integer(outputOffset));
  296. return rootJ;
  297. }
  298. void Port::fromJson(json_t* rootJ) {
  299. setDriverId(-1);
  300. json_t* driverJ = json_object_get(rootJ, "driver");
  301. if (driverJ)
  302. setDriverId(json_number_value(driverJ));
  303. json_t* deviceNameJ = json_object_get(rootJ, "deviceName");
  304. if (deviceNameJ) {
  305. std::string deviceName = json_string_value(deviceNameJ);
  306. // Search for device ID with equal name
  307. for (int deviceId : getDeviceIds()) {
  308. std::string deviceNameCurr = getDeviceName(deviceId);
  309. if (deviceNameCurr == "")
  310. continue;
  311. if (deviceNameCurr == deviceName) {
  312. setDeviceId(deviceId);
  313. break;
  314. }
  315. }
  316. }
  317. json_t* sampleRateJ = json_object_get(rootJ, "sampleRate");
  318. if (sampleRateJ)
  319. setSampleRate(json_number_value(sampleRateJ));
  320. json_t* blockSizeJ = json_object_get(rootJ, "blockSize");
  321. if (blockSizeJ)
  322. setBlockSize(json_integer_value(blockSizeJ));
  323. json_t* inputOffsetJ = json_object_get(rootJ, "inputOffset");
  324. if (inputOffsetJ)
  325. inputOffset = json_integer_value(inputOffsetJ);
  326. json_t* outputOffsetJ = json_object_get(rootJ, "outputOffset");
  327. if (outputOffsetJ)
  328. outputOffset = json_integer_value(outputOffsetJ);
  329. }
  330. ////////////////////
  331. // audio
  332. ////////////////////
  333. void init() {
  334. }
  335. void destroy() {
  336. for (auto& pair : drivers) {
  337. delete pair.second;
  338. }
  339. drivers.clear();
  340. }
  341. void addDriver(int driverId, Driver* driver) {
  342. assert(driver);
  343. assert(driverId != -1);
  344. drivers.push_back(std::make_pair(driverId, driver));
  345. }
  346. std::vector<int> getDriverIds() {
  347. std::vector<int> driverIds;
  348. for (auto& pair : drivers) {
  349. driverIds.push_back(pair.first);
  350. }
  351. return driverIds;
  352. }
  353. Driver* getDriver(int driverId) {
  354. if (driverId == -1)
  355. return NULL;
  356. // Search for driver by ID
  357. for (auto& pair : drivers) {
  358. if (pair.first == driverId)
  359. return pair.second;
  360. }
  361. return NULL;
  362. }
  363. } // namespace audio
  364. } // namespace rack