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.

409 lines
8.3KB

  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. int defaultDeviceId = driver->getDefaultDeviceId();
  91. if (defaultDeviceId >= 0)
  92. setDeviceId(defaultDeviceId);
  93. }
  94. std::string Port::getDriverName() {
  95. if (!driver)
  96. return "";
  97. try {
  98. return driver->getName();
  99. }
  100. catch (Exception& e) {
  101. WARN("Audio port could not get driver name: %s", e.what());
  102. return "";
  103. }
  104. }
  105. Device* Port::getDevice() {
  106. return device;
  107. }
  108. std::vector<int> Port::getDeviceIds() {
  109. if (!driver)
  110. return {};
  111. try {
  112. return driver->getDeviceIds();
  113. }
  114. catch (Exception& e) {
  115. WARN("Audio port could not get device IDs: %s", e.what());
  116. return {};
  117. }
  118. }
  119. int Port::getDeviceId() {
  120. return deviceId;
  121. }
  122. void Port::setDeviceId(int deviceId) {
  123. if (!driver)
  124. return;
  125. if (deviceId == this->deviceId)
  126. return;
  127. // Destroy device
  128. if (this->deviceId >= 0) {
  129. try {
  130. driver->unsubscribe(this->deviceId, this);
  131. onStopStream();
  132. }
  133. catch (Exception& e) {
  134. WARN("Audio port could not unsubscribe from device: %s", e.what());
  135. }
  136. }
  137. device = NULL;
  138. this->deviceId = -1;
  139. // Create device
  140. if (deviceId >= 0) {
  141. try {
  142. device = driver->subscribe(deviceId, this);
  143. if (device) {
  144. this->deviceId = deviceId;
  145. onStartStream();
  146. }
  147. }
  148. catch (Exception& e) {
  149. WARN("Audio port could not subscribe to device: %s", e.what());
  150. }
  151. }
  152. }
  153. int Port::getDeviceNumInputs(int deviceId) {
  154. if (!driver)
  155. return 0;
  156. try {
  157. return driver->getDeviceNumInputs(deviceId);
  158. }
  159. catch (Exception& e) {
  160. WARN("Audio port could not get device number of inputs: %s", e.what());
  161. return 0;
  162. }
  163. }
  164. int Port::getDeviceNumOutputs(int deviceId) {
  165. if (!driver)
  166. return 0;
  167. try {
  168. return driver->getDeviceNumOutputs(deviceId);
  169. }
  170. catch (Exception& e) {
  171. WARN("Audio port could not get device number of outputs: %s", e.what());
  172. return 0;
  173. }
  174. }
  175. std::string Port::getDeviceName(int deviceId) {
  176. if (!driver)
  177. return "";
  178. try {
  179. return driver->getDeviceName(deviceId);
  180. }
  181. catch (Exception& e) {
  182. WARN("Audio port could not get device name: %s", e.what());
  183. return 0;
  184. }
  185. }
  186. std::set<float> Port::getSampleRates() {
  187. if (!device)
  188. return {};
  189. try {
  190. return device->getSampleRates();
  191. }
  192. catch (Exception& e) {
  193. WARN("Audio port could not get device sample rates: %s", e.what());
  194. return {};
  195. }
  196. }
  197. float Port::getSampleRate() {
  198. if (!device)
  199. return 0;
  200. try {
  201. return device->getSampleRate();
  202. }
  203. catch (Exception& e) {
  204. WARN("Audio port could not get device sample rate: %s", e.what());
  205. return 0;
  206. }
  207. }
  208. void Port::setSampleRate(float sampleRate) {
  209. if (!device)
  210. return;
  211. try {
  212. device->setSampleRate(sampleRate);
  213. }
  214. catch (Exception& e) {
  215. WARN("Audio port could not set device sample rate: %s", e.what());
  216. }
  217. }
  218. std::set<int> Port::getBlockSizes() {
  219. if (!device)
  220. return {};
  221. try {
  222. return device->getBlockSizes();
  223. }
  224. catch (Exception& e) {
  225. WARN("Audio port could not get device block sizes: %s", e.what());
  226. return {};
  227. }
  228. }
  229. int Port::getBlockSize() {
  230. if (!device)
  231. return 0;
  232. try {
  233. return device->getBlockSize();
  234. }
  235. catch (Exception& e) {
  236. WARN("Audio port could not get device block size: %s", e.what());
  237. return 0;
  238. }
  239. }
  240. void Port::setBlockSize(int blockSize) {
  241. if (!device)
  242. return;
  243. try {
  244. device->setBlockSize(blockSize);
  245. }
  246. catch (Exception& e) {
  247. WARN("Audio port could not set device block size: %s", e.what());
  248. }
  249. }
  250. int Port::getNumInputs() {
  251. if (!device)
  252. return 0;
  253. try {
  254. return math::clamp(device->getNumInputs() - inputOffset, 0, maxInputs);
  255. }
  256. catch (Exception& e) {
  257. WARN("Audio port could not get device number of inputs: %s", e.what());
  258. return 0;
  259. }
  260. }
  261. int Port::getNumOutputs() {
  262. if (!device)
  263. return 0;
  264. try {
  265. return math::clamp(device->getNumOutputs() - outputOffset, 0, maxOutputs);
  266. }
  267. catch (Exception& e) {
  268. WARN("Audio port could not get device number of outputs: %s", e.what());
  269. return 0;
  270. }
  271. }
  272. json_t* Port::toJson() {
  273. json_t* rootJ = json_object();
  274. json_object_set_new(rootJ, "driver", json_integer(getDriverId()));
  275. if (device) {
  276. std::string deviceName = device->getName();
  277. json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
  278. }
  279. json_object_set_new(rootJ, "sampleRate", json_real(getSampleRate()));
  280. json_object_set_new(rootJ, "blockSize", json_integer(getBlockSize()));
  281. json_object_set_new(rootJ, "inputOffset", json_integer(inputOffset));
  282. json_object_set_new(rootJ, "outputOffset", json_integer(outputOffset));
  283. return rootJ;
  284. }
  285. void Port::fromJson(json_t* rootJ) {
  286. setDriverId(-1);
  287. json_t* driverJ = json_object_get(rootJ, "driver");
  288. if (driverJ)
  289. setDriverId(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 deviceId : getDeviceIds()) {
  295. std::string deviceNameCurr = getDeviceName(deviceId);
  296. if (deviceNameCurr == "")
  297. continue;
  298. if (deviceNameCurr == deviceName) {
  299. setDeviceId(deviceId);
  300. break;
  301. }
  302. }
  303. }
  304. json_t* sampleRateJ = json_object_get(rootJ, "sampleRate");
  305. if (sampleRateJ)
  306. setSampleRate(json_number_value(sampleRateJ));
  307. json_t* blockSizeJ = json_object_get(rootJ, "blockSize");
  308. if (blockSizeJ)
  309. setBlockSize(json_integer_value(blockSizeJ));
  310. json_t* inputOffsetJ = json_object_get(rootJ, "inputOffset");
  311. if (inputOffsetJ)
  312. inputOffset = json_integer_value(inputOffsetJ);
  313. json_t* outputOffsetJ = json_object_get(rootJ, "outputOffset");
  314. if (outputOffsetJ)
  315. outputOffset = json_integer_value(outputOffsetJ);
  316. }
  317. ////////////////////
  318. // audio
  319. ////////////////////
  320. void init() {
  321. }
  322. void destroy() {
  323. for (auto& pair : drivers) {
  324. delete pair.second;
  325. }
  326. drivers.clear();
  327. }
  328. void addDriver(int driverId, Driver* driver) {
  329. assert(driver);
  330. assert(driverId != -1);
  331. drivers.push_back(std::make_pair(driverId, driver));
  332. }
  333. std::vector<int> getDriverIds() {
  334. std::vector<int> driverIds;
  335. for (auto& pair : drivers) {
  336. driverIds.push_back(pair.first);
  337. }
  338. return driverIds;
  339. }
  340. Driver* getDriver(int driverId) {
  341. if (driverId == -1)
  342. return NULL;
  343. // Search for driver by ID
  344. for (auto& pair : drivers) {
  345. if (pair.first == driverId)
  346. return pair.second;
  347. }
  348. return NULL;
  349. }
  350. } // namespace audio
  351. } // namespace rack