Audio plugin host https://kx.studio/carla
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.

1064 lines
33KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaEngineGraph.hpp"
  18. #include "CarlaEngineInternal.hpp"
  19. #include "CarlaPlugin.hpp"
  20. #include "CarlaMathUtils.hpp"
  21. #include "juce_audio_processors.h"
  22. //#include "JuceInternalFilters.hpp"
  23. using juce::jmax;
  24. using juce::AudioPluginInstance;
  25. using juce::FloatVectorOperations;
  26. using juce::PluginDescription;
  27. CARLA_BACKEND_START_NAMESPACE
  28. // -----------------------------------------------------------------------
  29. // Rack Graph stuff
  30. static inline
  31. uint getCarlaRackPortIdFromName(const char* const shortname) noexcept
  32. {
  33. if (std::strcmp(shortname, "AudioIn1") == 0 || std::strcmp(shortname, "audio-in1") == 0)
  34. return RACK_GRAPH_CARLA_PORT_AUDIO_IN1;
  35. if (std::strcmp(shortname, "AudioIn2") == 0 || std::strcmp(shortname, "audio-in2") == 0)
  36. return RACK_GRAPH_CARLA_PORT_AUDIO_IN2;
  37. if (std::strcmp(shortname, "AudioOut1") == 0 || std::strcmp(shortname, "audio-out1") == 0)
  38. return RACK_GRAPH_CARLA_PORT_AUDIO_OUT1;
  39. if (std::strcmp(shortname, "AudioOut2") == 0 || std::strcmp(shortname, "audio-out2") == 0)
  40. return RACK_GRAPH_CARLA_PORT_AUDIO_OUT2;
  41. if (std::strcmp(shortname, "MidiIn") == 0 || std::strcmp(shortname, "midi-in") == 0)
  42. return RACK_GRAPH_CARLA_PORT_MIDI_IN;
  43. if (std::strcmp(shortname, "MidiOut") == 0 || std::strcmp(shortname, "midi-out") == 0)
  44. return RACK_GRAPH_CARLA_PORT_MIDI_OUT;
  45. carla_stderr("CarlaBackend::getCarlaRackPortIdFromName(%s) - invalid short name", shortname);
  46. return RACK_GRAPH_CARLA_PORT_NULL;
  47. }
  48. static inline
  49. const char* getCarlaRackFullPortNameFromId(const /*RackGraphCarlaPortIds*/ uint portId)
  50. {
  51. switch (portId)
  52. {
  53. case RACK_GRAPH_CARLA_PORT_AUDIO_IN1:
  54. return "Carla:AudioIn1";
  55. case RACK_GRAPH_CARLA_PORT_AUDIO_IN2:
  56. return "Carla:AudioIn2";
  57. case RACK_GRAPH_CARLA_PORT_AUDIO_OUT1:
  58. return "Carla:AudioOut1";
  59. case RACK_GRAPH_CARLA_PORT_AUDIO_OUT2:
  60. return "Carla:AudioOut2";
  61. case RACK_GRAPH_CARLA_PORT_MIDI_IN:
  62. return "Carla:MidiIn";
  63. case RACK_GRAPH_CARLA_PORT_MIDI_OUT:
  64. return "Carla:MidiOut";
  65. //case RACK_GRAPH_CARLA_PORT_NULL:
  66. //case RACK_GRAPH_CARLA_PORT_MAX:
  67. // break;
  68. }
  69. carla_stderr("CarlaBackend::getCarlaRackFullPortNameFromId(%i) - invalid port id", portId);
  70. return nullptr;
  71. }
  72. // -----------------------------------------------------------------------
  73. // RackGraph MIDI
  74. const char* RackGraph::MIDI::getName(const bool isInput, const uint portId) const noexcept
  75. {
  76. for (LinkedList<PortNameToId>::Itenerator it = isInput ? ins.begin() : outs.begin(); it.valid(); it.next())
  77. {
  78. const PortNameToId& port(it.getValue());
  79. if (port.port == portId)
  80. return port.name;
  81. }
  82. return nullptr;
  83. }
  84. uint RackGraph::MIDI::getPortId(const bool isInput, const char portName[], bool* const ok) const noexcept
  85. {
  86. for (LinkedList<PortNameToId>::Itenerator it = isInput ? ins.begin() : outs.begin(); it.valid(); it.next())
  87. {
  88. const PortNameToId& port(it.getValue());
  89. if (std::strcmp(port.name, portName) == 0)
  90. {
  91. if (ok != nullptr)
  92. *ok = true;
  93. return port.port;
  94. }
  95. }
  96. if (ok != nullptr)
  97. *ok = false;
  98. return 0;
  99. }
  100. // -----------------------------------------------------------------------
  101. // RackGraph
  102. RackGraph::RackGraph(const uint32_t bufferSize, const uint32_t ins, const uint32_t outs) noexcept
  103. : inputs(ins),
  104. outputs(outs),
  105. isOffline(false)
  106. {
  107. audio.inBuf[0] = audio.inBuf[1] = nullptr;
  108. audio.inBufTmp[0] = audio.inBufTmp[1] = nullptr;
  109. audio.outBuf[0] = audio.outBuf[1] = nullptr;
  110. setBufferSize(bufferSize);
  111. }
  112. RackGraph::~RackGraph() noexcept
  113. {
  114. clearConnections();
  115. }
  116. void RackGraph::setBufferSize(const uint32_t bufferSize) noexcept
  117. {
  118. if (audio.inBuf[0] != nullptr) { delete[] audio.inBuf[0]; audio.inBuf[0] = nullptr; }
  119. if (audio.inBuf[1] != nullptr) { delete[] audio.inBuf[1]; audio.inBuf[1] = nullptr; }
  120. if (audio.inBufTmp[0] != nullptr) { delete[] audio.inBufTmp[0]; audio.inBufTmp[0] = nullptr; }
  121. if (audio.inBufTmp[1] != nullptr) { delete[] audio.inBufTmp[1]; audio.inBufTmp[1] = nullptr; }
  122. if (audio.outBuf[0] != nullptr) { delete[] audio.outBuf[0]; audio.outBuf[0] = nullptr; }
  123. if (audio.outBuf[1] != nullptr) { delete[] audio.outBuf[1]; audio.outBuf[1] = nullptr; }
  124. try {
  125. audio.inBufTmp[0] = new float[bufferSize];
  126. audio.inBufTmp[1] = new float[bufferSize];
  127. if (inputs > 0 || outputs > 0)
  128. {
  129. audio.inBuf[0] = new float[bufferSize];
  130. audio.inBuf[1] = new float[bufferSize];
  131. audio.outBuf[0] = new float[bufferSize];
  132. audio.outBuf[1] = new float[bufferSize];
  133. }
  134. }
  135. catch(...) {
  136. if (audio.inBufTmp[0] != nullptr) { delete[] audio.inBufTmp[0]; audio.inBufTmp[0] = nullptr; }
  137. if (audio.inBufTmp[1] != nullptr) { delete[] audio.inBufTmp[1]; audio.inBufTmp[1] = nullptr; }
  138. if (inputs > 0 || outputs > 0)
  139. {
  140. if (audio.inBuf[0] != nullptr) { delete[] audio.inBuf[0]; audio.inBuf[0] = nullptr; }
  141. if (audio.inBuf[1] != nullptr) { delete[] audio.inBuf[1]; audio.inBuf[1] = nullptr; }
  142. if (audio.outBuf[0] != nullptr) { delete[] audio.outBuf[0]; audio.outBuf[0] = nullptr; }
  143. if (audio.outBuf[1] != nullptr) { delete[] audio.outBuf[1]; audio.outBuf[1] = nullptr; }
  144. }
  145. return;
  146. }
  147. FloatVectorOperations::clear(audio.inBufTmp[0], bufferSize);
  148. FloatVectorOperations::clear(audio.inBufTmp[1], bufferSize);
  149. if (inputs > 0 || outputs > 0)
  150. {
  151. FloatVectorOperations::clear(audio.inBuf[0], bufferSize);
  152. FloatVectorOperations::clear(audio.inBuf[1], bufferSize);
  153. FloatVectorOperations::clear(audio.outBuf[0], bufferSize);
  154. FloatVectorOperations::clear(audio.outBuf[1], bufferSize);
  155. }
  156. }
  157. void RackGraph::setOffline(const bool offline) noexcept
  158. {
  159. isOffline = offline;
  160. }
  161. bool RackGraph::connect(CarlaEngine* const engine, const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept
  162. {
  163. CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);
  164. uint otherGroup, otherPort, carlaPort;
  165. if (groupA == RACK_GRAPH_GROUP_CARLA)
  166. {
  167. CARLA_SAFE_ASSERT_RETURN(groupB != RACK_GRAPH_GROUP_CARLA, false);
  168. carlaPort = portA;
  169. otherGroup = groupB;
  170. otherPort = portB;
  171. }
  172. else
  173. {
  174. CARLA_SAFE_ASSERT_RETURN(groupB == RACK_GRAPH_GROUP_CARLA, false);
  175. carlaPort = portB;
  176. otherGroup = groupA;
  177. otherPort = portA;
  178. }
  179. CARLA_SAFE_ASSERT_RETURN(carlaPort > RACK_GRAPH_CARLA_PORT_NULL && carlaPort < RACK_GRAPH_CARLA_PORT_MAX, false);
  180. CARLA_SAFE_ASSERT_RETURN(otherGroup > RACK_GRAPH_GROUP_CARLA && otherGroup < RACK_GRAPH_GROUP_MAX, false);
  181. bool makeConnection = false;
  182. switch (carlaPort)
  183. {
  184. case RACK_GRAPH_CARLA_PORT_AUDIO_IN1:
  185. CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_AUDIO_IN, false);
  186. audio.mutex.lock();
  187. makeConnection = audio.connectedIn1.append(otherPort);
  188. audio.mutex.unlock();
  189. break;
  190. case RACK_GRAPH_CARLA_PORT_AUDIO_IN2:
  191. CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_AUDIO_IN, false);
  192. audio.mutex.lock();
  193. makeConnection = audio.connectedIn2.append(otherPort);
  194. audio.mutex.unlock();
  195. break;
  196. case RACK_GRAPH_CARLA_PORT_AUDIO_OUT1:
  197. CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_AUDIO_OUT, false);
  198. audio.mutex.lock();
  199. makeConnection = audio.connectedOut1.append(otherPort);
  200. audio.mutex.unlock();
  201. break;
  202. case RACK_GRAPH_CARLA_PORT_AUDIO_OUT2:
  203. CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_AUDIO_OUT, false);
  204. audio.mutex.lock();
  205. makeConnection = audio.connectedOut2.append(otherPort);
  206. audio.mutex.unlock();
  207. break;
  208. case RACK_GRAPH_CARLA_PORT_MIDI_IN:
  209. CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_MIDI_IN, false);
  210. if (const char* const portName = midi.getName(true, otherPort))
  211. makeConnection = engine->connectRackMidiInPort(portName);
  212. break;
  213. case RACK_GRAPH_CARLA_PORT_MIDI_OUT:
  214. CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_MIDI_OUT, false);
  215. if (const char* const portName = midi.getName(false, otherPort))
  216. makeConnection = engine->connectRackMidiOutPort(portName);
  217. break;
  218. }
  219. if (! makeConnection)
  220. {
  221. engine->setLastError("Invalid rack connection");
  222. return false;
  223. }
  224. ConnectionToId connectionToId;
  225. connectionToId.setData(++connections.lastId, groupA, portA, groupB, portB);
  226. char strBuf[STR_MAX+1];
  227. strBuf[STR_MAX] = '\0';
  228. std::snprintf(strBuf, STR_MAX, "%u:%u:%u:%u", groupA, portA, groupB, portB);
  229. engine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);
  230. connections.list.append(connectionToId);
  231. return true;
  232. }
  233. bool RackGraph::disconnect(CarlaEngine* const engine, const uint connectionId) noexcept
  234. {
  235. CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);
  236. CARLA_SAFE_ASSERT_RETURN(connections.list.count() > 0, false);
  237. for (LinkedList<ConnectionToId>::Itenerator it=connections.list.begin(); it.valid(); it.next())
  238. {
  239. const ConnectionToId& connection(it.getValue());
  240. if (connection.id != connectionId)
  241. continue;
  242. uint otherGroup, otherPort, carlaPort;
  243. if (connection.groupA == RACK_GRAPH_GROUP_CARLA)
  244. {
  245. CARLA_SAFE_ASSERT_RETURN(connection.groupB != RACK_GRAPH_GROUP_CARLA, false);
  246. carlaPort = connection.portA;
  247. otherGroup = connection.groupB;
  248. otherPort = connection.portB;
  249. }
  250. else
  251. {
  252. CARLA_SAFE_ASSERT_RETURN(connection.groupB == RACK_GRAPH_GROUP_CARLA, false);
  253. carlaPort = connection.portB;
  254. otherGroup = connection.groupA;
  255. otherPort = connection.portA;
  256. }
  257. CARLA_SAFE_ASSERT_RETURN(carlaPort > RACK_GRAPH_CARLA_PORT_NULL && carlaPort < RACK_GRAPH_CARLA_PORT_MAX, false);
  258. CARLA_SAFE_ASSERT_RETURN(otherGroup > RACK_GRAPH_GROUP_CARLA && otherGroup < RACK_GRAPH_GROUP_MAX, false);
  259. bool makeDisconnection = false;
  260. switch (carlaPort)
  261. {
  262. case RACK_GRAPH_CARLA_PORT_AUDIO_IN1:
  263. audio.mutex.lock();
  264. makeDisconnection = audio.connectedIn1.removeOne(otherPort);
  265. audio.mutex.unlock();
  266. break;
  267. case RACK_GRAPH_CARLA_PORT_AUDIO_IN2:
  268. audio.mutex.lock();
  269. makeDisconnection = audio.connectedIn2.removeOne(otherPort);
  270. audio.mutex.unlock();
  271. break;
  272. case RACK_GRAPH_CARLA_PORT_AUDIO_OUT1:
  273. audio.mutex.lock();
  274. makeDisconnection = audio.connectedOut1.removeOne(otherPort);
  275. audio.mutex.unlock();
  276. break;
  277. case RACK_GRAPH_CARLA_PORT_AUDIO_OUT2:
  278. audio.mutex.lock();
  279. makeDisconnection = audio.connectedOut2.removeOne(otherPort);
  280. audio.mutex.unlock();
  281. break;
  282. case RACK_GRAPH_CARLA_PORT_MIDI_IN:
  283. if (const char* const portName = midi.getName(true, otherPort))
  284. makeDisconnection = engine->disconnectRackMidiInPort(portName);
  285. break;
  286. case RACK_GRAPH_CARLA_PORT_MIDI_OUT:
  287. if (const char* const portName = midi.getName(false, otherPort))
  288. makeDisconnection = engine->disconnectRackMidiOutPort(portName);
  289. break;
  290. }
  291. if (! makeDisconnection)
  292. {
  293. engine->setLastError("Invalid rack connection");
  294. return false;
  295. }
  296. engine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connection.id, 0, 0, 0.0f, nullptr);
  297. connections.list.remove(it);
  298. return true;
  299. }
  300. engine->setLastError("Failed to find connection");
  301. return false;
  302. }
  303. void RackGraph::clearConnections() noexcept
  304. {
  305. connections.clear();
  306. audio.mutex.lock();
  307. audio.connectedIn1.clear();
  308. audio.connectedIn2.clear();
  309. audio.connectedOut1.clear();
  310. audio.connectedOut2.clear();
  311. audio.mutex.unlock();
  312. midi.ins.clear();
  313. midi.outs.clear();
  314. }
  315. const char* const* RackGraph::getConnections() noexcept
  316. {
  317. if (connections.list.count() == 0)
  318. return nullptr;
  319. CarlaStringList connList;
  320. char strBuf[STR_MAX+1];
  321. strBuf[STR_MAX] = '\0';
  322. for (LinkedList<ConnectionToId>::Itenerator it=connections.list.begin(); it.valid(); it.next())
  323. {
  324. const ConnectionToId& connection(it.getValue());
  325. uint otherGroup, otherPort, carlaPort;
  326. if (connection.groupA == RACK_GRAPH_GROUP_CARLA)
  327. {
  328. CARLA_SAFE_ASSERT_CONTINUE(connection.groupB != RACK_GRAPH_GROUP_CARLA);
  329. carlaPort = connection.portA;
  330. otherGroup = connection.groupB;
  331. otherPort = connection.portB;
  332. }
  333. else
  334. {
  335. CARLA_SAFE_ASSERT_CONTINUE(connection.groupB == RACK_GRAPH_GROUP_CARLA);
  336. carlaPort = connection.portB;
  337. otherGroup = connection.groupA;
  338. otherPort = connection.portA;
  339. }
  340. CARLA_SAFE_ASSERT_CONTINUE(carlaPort > RACK_GRAPH_CARLA_PORT_NULL && carlaPort < RACK_GRAPH_CARLA_PORT_MAX);
  341. CARLA_SAFE_ASSERT_CONTINUE(otherGroup > RACK_GRAPH_GROUP_CARLA && otherGroup < RACK_GRAPH_GROUP_MAX);
  342. switch (carlaPort)
  343. {
  344. case RACK_GRAPH_CARLA_PORT_AUDIO_IN1:
  345. case RACK_GRAPH_CARLA_PORT_AUDIO_IN2:
  346. std::snprintf(strBuf, STR_MAX, "AudioIn:%i", otherPort+1);
  347. connList.append(strBuf);
  348. connList.append(getCarlaRackFullPortNameFromId(carlaPort));
  349. break;
  350. case RACK_GRAPH_CARLA_PORT_AUDIO_OUT1:
  351. case RACK_GRAPH_CARLA_PORT_AUDIO_OUT2:
  352. std::snprintf(strBuf, STR_MAX, "AudioOut:%i", otherPort+1);
  353. connList.append(getCarlaRackFullPortNameFromId(carlaPort));
  354. connList.append(strBuf);
  355. break;
  356. case RACK_GRAPH_CARLA_PORT_MIDI_IN:
  357. std::snprintf(strBuf, STR_MAX, "MidiIn:%s", midi.getName(true, otherPort));
  358. connList.append(strBuf);
  359. connList.append(getCarlaRackFullPortNameFromId(carlaPort));
  360. break;
  361. case RACK_GRAPH_CARLA_PORT_MIDI_OUT:
  362. std::snprintf(strBuf, STR_MAX, "MidiOut:%s", midi.getName(false, otherPort));
  363. connList.append(getCarlaRackFullPortNameFromId(carlaPort));
  364. connList.append(strBuf);
  365. break;
  366. }
  367. }
  368. if (connList.count() == 0)
  369. return nullptr;
  370. retCon = connList.toCharStringListPtr();
  371. return retCon;
  372. }
  373. bool RackGraph::getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const noexcept
  374. {
  375. CARLA_SAFE_ASSERT_RETURN(fullPortName != nullptr && fullPortName[0] != '\0', false);
  376. if (std::strncmp(fullPortName, "Carla:", 6) == 0)
  377. {
  378. groupId = RACK_GRAPH_GROUP_CARLA;
  379. portId = getCarlaRackPortIdFromName(fullPortName+6);
  380. if (portId > RACK_GRAPH_CARLA_PORT_NULL && portId < RACK_GRAPH_CARLA_PORT_MAX)
  381. return true;
  382. }
  383. else if (std::strncmp(fullPortName, "AudioIn:", 8) == 0)
  384. {
  385. groupId = RACK_GRAPH_GROUP_AUDIO_IN;
  386. if (const int portTest = std::atoi(fullPortName+8))
  387. {
  388. portId = static_cast<uint>(portTest-1);
  389. return true;
  390. }
  391. }
  392. else if (std::strncmp(fullPortName, "AudioOut:", 9) == 0)
  393. {
  394. groupId = RACK_GRAPH_GROUP_AUDIO_OUT;
  395. if (const int portTest = std::atoi(fullPortName+9))
  396. {
  397. portId = static_cast<uint>(portTest-1);
  398. return true;
  399. }
  400. }
  401. else if (std::strncmp(fullPortName, "MidiIn:", 7) == 0)
  402. {
  403. groupId = RACK_GRAPH_GROUP_MIDI_IN;
  404. if (const char* const portName = fullPortName+7)
  405. {
  406. bool ok;
  407. portId = midi.getPortId(true, portName, &ok);
  408. return ok;
  409. }
  410. }
  411. else if (std::strncmp(fullPortName, "MidiOut:", 8) == 0)
  412. {
  413. groupId = RACK_GRAPH_GROUP_MIDI_OUT;
  414. if (const char* const portName = fullPortName+8)
  415. {
  416. bool ok;
  417. portId = midi.getPortId(false, portName, &ok);
  418. return ok;
  419. }
  420. }
  421. return false;
  422. }
  423. void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inBufReal[2], float* outBuf[2], const uint32_t frames)
  424. {
  425. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  426. CARLA_SAFE_ASSERT_RETURN(data->events.in != nullptr,);
  427. CARLA_SAFE_ASSERT_RETURN(data->events.out != nullptr,);
  428. // safe copy
  429. float inBuf0[frames];
  430. float inBuf1[frames];
  431. float* inBuf[2] = { inBuf0, inBuf1 };
  432. // initialize audio inputs
  433. FloatVectorOperations::copy(inBuf0, inBufReal[0], frames);
  434. FloatVectorOperations::copy(inBuf1, inBufReal[1], frames);
  435. // initialize audio outputs (zero)
  436. FloatVectorOperations::clear(outBuf[0], frames);
  437. FloatVectorOperations::clear(outBuf[1], frames);
  438. // initialize event outputs (zero)
  439. carla_zeroStruct<EngineEvent>(data->events.out, kMaxEngineEventInternalCount);
  440. bool processed = false;
  441. uint32_t oldAudioInCount = 0;
  442. uint32_t oldMidiOutCount = 0;
  443. // process plugins
  444. for (uint i=0; i < data->curPluginCount; ++i)
  445. {
  446. CarlaPlugin* const plugin = data->plugins[i].plugin;
  447. if (plugin == nullptr || ! plugin->isEnabled() || ! plugin->tryLock(isOffline))
  448. continue;
  449. if (processed)
  450. {
  451. // initialize audio inputs (from previous outputs)
  452. FloatVectorOperations::copy(inBuf0, outBuf[0], frames);
  453. FloatVectorOperations::copy(inBuf1, outBuf[1], frames);
  454. // initialize audio outputs (zero)
  455. FloatVectorOperations::clear(outBuf[0], frames);
  456. FloatVectorOperations::clear(outBuf[1], frames);
  457. // if plugin has no midi out, add previous events
  458. if (oldMidiOutCount == 0 && data->events.in[0].type != kEngineEventTypeNull)
  459. {
  460. if (data->events.out[0].type != kEngineEventTypeNull)
  461. {
  462. // TODO: carefully add to input, sorted events
  463. }
  464. // else nothing needed
  465. }
  466. else
  467. {
  468. // initialize event inputs from previous outputs
  469. carla_copyStruct<EngineEvent>(data->events.in, data->events.out, kMaxEngineEventInternalCount);
  470. // initialize event outputs (zero)
  471. carla_zeroStruct<EngineEvent>(data->events.out, kMaxEngineEventInternalCount);
  472. }
  473. }
  474. oldAudioInCount = plugin->getAudioInCount();
  475. oldMidiOutCount = plugin->getMidiOutCount();
  476. // process
  477. plugin->initBuffers();
  478. plugin->process(inBuf, outBuf, frames);
  479. plugin->unlock();
  480. // if plugin has no audio inputs, add input buffer
  481. if (oldAudioInCount == 0)
  482. {
  483. FloatVectorOperations::add(outBuf[0], inBuf0, frames);
  484. FloatVectorOperations::add(outBuf[1], inBuf1, frames);
  485. }
  486. // set peaks
  487. {
  488. EnginePluginData& pluginData(data->plugins[i]);
  489. juce::Range<float> range;
  490. if (oldAudioInCount > 0)
  491. {
  492. range = FloatVectorOperations::findMinAndMax(inBuf0, static_cast<int>(frames));
  493. pluginData.insPeak[0] = carla_max<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f);
  494. range = FloatVectorOperations::findMinAndMax(inBuf1, static_cast<int>(frames));
  495. pluginData.insPeak[1] = carla_max<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f);
  496. }
  497. else
  498. {
  499. pluginData.insPeak[0] = 0.0f;
  500. pluginData.insPeak[1] = 0.0f;
  501. }
  502. if (plugin->getAudioOutCount() > 0)
  503. {
  504. range = FloatVectorOperations::findMinAndMax(outBuf[0], static_cast<int>(frames));
  505. pluginData.outsPeak[0] = carla_max<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f);
  506. range = FloatVectorOperations::findMinAndMax(outBuf[1], static_cast<int>(frames));
  507. pluginData.outsPeak[1] = carla_max<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f);
  508. }
  509. else
  510. {
  511. pluginData.outsPeak[0] = 0.0f;
  512. pluginData.outsPeak[1] = 0.0f;
  513. }
  514. }
  515. processed = true;
  516. }
  517. }
  518. void RackGraph::processHelper(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames)
  519. {
  520. CARLA_SAFE_ASSERT_RETURN(audio.outBuf[1] != nullptr,);
  521. const CarlaRecursiveMutexLocker _cml(audio.mutex);
  522. if (inBuf != nullptr && inputs > 0)
  523. {
  524. bool noConnections = true;
  525. // connect input buffers
  526. for (LinkedList<uint>::Itenerator it = audio.connectedIn1.begin(); it.valid(); it.next())
  527. {
  528. const uint& port(it.getValue());
  529. CARLA_SAFE_ASSERT_CONTINUE(port < inputs);
  530. if (noConnections)
  531. {
  532. FloatVectorOperations::copy(audio.inBuf[0], inBuf[port], frames);
  533. noConnections = false;
  534. }
  535. else
  536. {
  537. FloatVectorOperations::add(audio.inBuf[0], inBuf[port], frames);
  538. }
  539. }
  540. if (noConnections)
  541. FloatVectorOperations::clear(audio.inBuf[0], frames);
  542. noConnections = true;
  543. for (LinkedList<uint>::Itenerator it = audio.connectedIn2.begin(); it.valid(); it.next())
  544. {
  545. const uint& port(it.getValue());
  546. CARLA_SAFE_ASSERT_CONTINUE(port < inputs);
  547. if (noConnections)
  548. {
  549. FloatVectorOperations::copy(audio.inBuf[1], inBuf[port], frames);
  550. noConnections = false;
  551. }
  552. else
  553. {
  554. FloatVectorOperations::add(audio.inBuf[1], inBuf[port], frames);
  555. }
  556. }
  557. if (noConnections)
  558. FloatVectorOperations::clear(audio.inBuf[1], frames);
  559. }
  560. else
  561. {
  562. FloatVectorOperations::clear(audio.inBuf[0], frames);
  563. FloatVectorOperations::clear(audio.inBuf[1], frames);
  564. }
  565. FloatVectorOperations::clear(audio.outBuf[0], frames);
  566. FloatVectorOperations::clear(audio.outBuf[1], frames);
  567. // process
  568. process(data, const_cast<const float**>(audio.inBuf), audio.outBuf, frames);
  569. // connect output buffers
  570. if (audio.connectedOut1.count() != 0)
  571. {
  572. for (LinkedList<uint>::Itenerator it = audio.connectedOut1.begin(); it.valid(); it.next())
  573. {
  574. const uint& port(it.getValue());
  575. CARLA_SAFE_ASSERT_CONTINUE(port < outputs);
  576. FloatVectorOperations::add(outBuf[port], audio.outBuf[0], frames);
  577. }
  578. }
  579. if (audio.connectedOut2.count() != 0)
  580. {
  581. for (LinkedList<uint>::Itenerator it = audio.connectedOut2.begin(); it.valid(); it.next())
  582. {
  583. const uint& port(it.getValue());
  584. CARLA_SAFE_ASSERT_CONTINUE(port < outputs);
  585. FloatVectorOperations::add(outBuf[port], audio.outBuf[1], frames);
  586. }
  587. }
  588. }
  589. // -----------------------------------------------------------------------
  590. class CarlaPluginInstance : public AudioPluginInstance
  591. {
  592. public:
  593. CarlaPluginInstance(CarlaPlugin* const plugin)
  594. : fPlugin(plugin),
  595. fGraph(nullptr) {}
  596. ~CarlaPluginInstance() override
  597. {
  598. }
  599. AudioProcessorGraph* getParentGraph() const noexcept
  600. {
  601. return fGraph;
  602. }
  603. void setParentGraph(AudioProcessorGraph*)
  604. {
  605. }
  606. void* getPlatformSpecificData() noexcept override
  607. {
  608. return fPlugin;
  609. }
  610. void fillInPluginDescription(PluginDescription& d) const override
  611. {
  612. d.pluginFormatName = "Carla";
  613. d.category = "Carla Plugin";
  614. d.version = "1.0";
  615. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  616. char strBuf[STR_MAX+1];
  617. strBuf[STR_MAX] = '\0';
  618. fPlugin->getRealName(strBuf);
  619. d.name = strBuf;
  620. fPlugin->getLabel(strBuf);
  621. d.descriptiveName = strBuf;
  622. fPlugin->getMaker(strBuf);
  623. d.manufacturerName = strBuf;
  624. d.uid = d.name.hashCode();
  625. d.isInstrument = (fPlugin->getHints() & PLUGIN_IS_SYNTH);
  626. d.numInputChannels = fPlugin->getAudioInCount();
  627. d.numOutputChannels = fPlugin->getAudioOutCount();
  628. //d.hasSharedContainer = true;
  629. }
  630. private:
  631. CarlaPlugin* const fPlugin;
  632. AudioProcessorGraph* fGraph;
  633. };
  634. // -----------------------------------------------------------------------
  635. // PatchbayGraph
  636. // TODO
  637. PatchbayGraph::PatchbayGraph(const uint32_t bufferSize, const double sampleRate, const uint32_t inputs, const uint32_t outputs)
  638. {
  639. graph.setPlayConfigDetails(inputs, outputs, sampleRate, bufferSize);
  640. graph.prepareToPlay(sampleRate, bufferSize);
  641. audioBuffer.setSize(jmax(inputs, outputs), bufferSize);
  642. for (uint32_t i=0; i<inputs; ++i)
  643. {
  644. AudioProcessorGraph::AudioGraphIOProcessor* const proc(new AudioProcessorGraph::AudioGraphIOProcessor(AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode));
  645. graph.addNode(proc);
  646. }
  647. for (uint32_t i=0; i<outputs; ++i)
  648. {
  649. AudioProcessorGraph::AudioGraphIOProcessor* const proc(new AudioProcessorGraph::AudioGraphIOProcessor(AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode));
  650. graph.addNode(proc);
  651. }
  652. }
  653. PatchbayGraph::~PatchbayGraph()
  654. {
  655. graph.releaseResources();
  656. graph.clear();
  657. audioBuffer.clear();
  658. }
  659. void PatchbayGraph::setBufferSize(const uint32_t bufferSize)
  660. {
  661. graph.releaseResources();
  662. graph.prepareToPlay(graph.getSampleRate(), bufferSize);
  663. audioBuffer.setSize(audioBuffer.getNumChannels(), bufferSize);
  664. }
  665. void PatchbayGraph::setSampleRate(const double sampleRate)
  666. {
  667. graph.releaseResources();
  668. graph.prepareToPlay(sampleRate, graph.getBlockSize());
  669. }
  670. void PatchbayGraph::setOffline(const bool offline)
  671. {
  672. graph.setNonRealtime(offline);
  673. }
  674. #if 0
  675. bool PatchbayGraph::connect(CarlaEngine* const engine, const uint /*groupA*/, const uint /*portA*/, const uint /*groupB*/, const uint /*portB*/) noexcept
  676. {
  677. CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);
  678. return false;
  679. }
  680. bool PatchbayGraph::disconnect(CarlaEngine* const engine, const uint /*connectionId*/) noexcept
  681. {
  682. CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);
  683. return false;
  684. }
  685. const char* const* PatchbayGraph::getConnections() const noexcept
  686. {
  687. return nullptr;
  688. }
  689. bool PatchbayGraph::getPortIdFromFullName(const char* const /*fillPortName*/, uint& /*groupId*/, uint& /*portId*/) const noexcept
  690. {
  691. return false;
  692. }
  693. #endif
  694. // -----------------------------------------------------------------------
  695. // InternalGraph
  696. EngineInternalGraph::EngineInternalGraph() noexcept
  697. : fIsRack(true),
  698. fIsReady(false)
  699. {
  700. fRack = nullptr;
  701. }
  702. EngineInternalGraph::~EngineInternalGraph() noexcept
  703. {
  704. CARLA_SAFE_ASSERT(! fIsReady);
  705. CARLA_SAFE_ASSERT(fRack == nullptr);
  706. }
  707. void EngineInternalGraph::create(const bool isRack, const double sampleRate, const uint32_t bufferSize, const uint32_t inputs, const uint32_t outputs)
  708. {
  709. fIsRack = isRack;
  710. if (isRack)
  711. {
  712. CARLA_SAFE_ASSERT_RETURN(fRack == nullptr,);
  713. fRack = new RackGraph(bufferSize, inputs, outputs);
  714. }
  715. else
  716. {
  717. CARLA_SAFE_ASSERT_RETURN(fPatchbay == nullptr,);
  718. fPatchbay = new PatchbayGraph(sampleRate, bufferSize, inputs, outputs);
  719. }
  720. fIsReady = true;
  721. }
  722. void EngineInternalGraph::destroy() noexcept
  723. {
  724. if (! fIsReady)
  725. {
  726. CARLA_SAFE_ASSERT(fRack == nullptr);
  727. return;
  728. }
  729. fIsReady = false;
  730. if (fIsRack)
  731. {
  732. CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
  733. delete fRack;
  734. fRack = nullptr;
  735. }
  736. else
  737. {
  738. CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
  739. delete fPatchbay;
  740. fPatchbay = nullptr;
  741. }
  742. }
  743. void EngineInternalGraph::setBufferSize(const uint32_t bufferSize)
  744. {
  745. ScopedValueSetter<bool> svs(fIsReady, false, true);
  746. if (fIsRack)
  747. {
  748. CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
  749. fRack->setBufferSize(bufferSize);
  750. }
  751. else
  752. {
  753. CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
  754. fPatchbay->setBufferSize(bufferSize);
  755. }
  756. }
  757. void EngineInternalGraph::setSampleRate(const double sampleRate)
  758. {
  759. ScopedValueSetter<bool> svs(fIsReady, false, true);
  760. if (fIsRack)
  761. {
  762. CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
  763. }
  764. else
  765. {
  766. CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
  767. fPatchbay->setSampleRate(sampleRate);
  768. }
  769. }
  770. void EngineInternalGraph::setOffline(const bool offline)
  771. {
  772. ScopedValueSetter<bool> svs(fIsReady, false, true);
  773. if (fIsRack)
  774. {
  775. CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
  776. fRack->setOffline(offline);
  777. }
  778. else
  779. {
  780. CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
  781. fPatchbay->setOffline(offline);
  782. }
  783. }
  784. bool EngineInternalGraph::isReady() const noexcept
  785. {
  786. return fIsReady;
  787. }
  788. RackGraph* EngineInternalGraph::getRackGraph() const noexcept
  789. {
  790. CARLA_SAFE_ASSERT_RETURN(fIsRack, nullptr);
  791. return fRack;
  792. }
  793. PatchbayGraph* EngineInternalGraph::getPatchbayGraph() const noexcept
  794. {
  795. CARLA_SAFE_ASSERT_RETURN(! fIsRack, nullptr);
  796. return fPatchbay;
  797. }
  798. void EngineInternalGraph::process(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames)
  799. {
  800. if (fIsRack)
  801. {
  802. CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
  803. fRack->processHelper(data, inBuf, outBuf, frames);
  804. }
  805. else
  806. {
  807. CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
  808. //fPatchbay->process(inBuf, outBuf, frames);
  809. }
  810. }
  811. void EngineInternalGraph::processRack(CarlaEngine::ProtectedData* const data, const float* inBuf[2], float* outBuf[2], const uint32_t frames)
  812. {
  813. CARLA_SAFE_ASSERT_RETURN(fIsRack,);
  814. CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
  815. fRack->process(data, inBuf, outBuf, frames);
  816. }
  817. // -----------------------------------------------------------------------
  818. // CarlaEngine Patchbay stuff
  819. bool CarlaEngine::patchbayConnect(const uint groupA, const uint portA, const uint groupB, const uint portB)
  820. {
  821. CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY, false);
  822. //CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady, false);
  823. //CARLA_SAFE_ASSERT_RETURN(pData->graph.graph != nullptr, false);
  824. carla_stdout("CarlaEngine::patchbayConnect(%u, %u, %u, %u)", groupA, portA, groupB, portB);
  825. return false; //pData->graph.graph->connect(this, groupA, portA, groupB, portB);
  826. }
  827. bool CarlaEngine::patchbayDisconnect(const uint connectionId)
  828. {
  829. CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY, false);
  830. //CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady, false);
  831. //CARLA_SAFE_ASSERT_RETURN(pData->graph.graph != nullptr, false);
  832. carla_stdout("CarlaEngine::patchbayDisconnect(%u)", connectionId);
  833. return false; //pData->graph.graph->disconnect(this, connectionId);
  834. }
  835. bool CarlaEngine::patchbayRefresh()
  836. {
  837. setLastError("Unsupported operation");
  838. return false;
  839. }
  840. // -----------------------------------------------------------------------
  841. const char* const* CarlaEngine::getPatchbayConnections() const
  842. {
  843. //CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady, nullptr);
  844. //CARLA_SAFE_ASSERT_RETURN(pData->graph.graph != nullptr, nullptr);
  845. carla_debug("CarlaEngine::getPatchbayConnections()");
  846. return nullptr; //pData->graph.graph->getConnections();
  847. }
  848. void CarlaEngine::restorePatchbayConnection(const char* const connSource, const char* const connTarget)
  849. {
  850. //CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady,);
  851. //CARLA_SAFE_ASSERT_RETURN(pData->graph.graph != nullptr,);
  852. CARLA_SAFE_ASSERT_RETURN(connSource != nullptr && connSource[0] != '\0',);
  853. CARLA_SAFE_ASSERT_RETURN(connTarget != nullptr && connTarget[0] != '\0',);
  854. carla_debug("CarlaEngine::restorePatchbayConnection(\"%s\", \"%s\")", connSource, connTarget);
  855. // uint groupA, portA;
  856. // uint groupB, portB;
  857. //
  858. // if (! pData->graph.graph->getPortIdFromFullName(connSource, groupA, portA))
  859. // return;
  860. // if (! pData->graph.graph->getPortIdFromFullName(connTarget, groupB, portB))
  861. // return;
  862. //
  863. // patchbayConnect(groupA, portA, groupB, portB);
  864. }
  865. // -----------------------------------------------------------------------
  866. CARLA_BACKEND_END_NAMESPACE