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.

401 lines
8.1KB

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