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.

419 lines
8.5KB

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