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.

863 lines
24KB

  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 "CarlaEngineInternal.hpp"
  18. #include "CarlaPlugin.hpp"
  19. #include "CarlaMIDI.h"
  20. #include "CarlaMathUtils.hpp"
  21. // -----------------------------------------------------------------------
  22. CARLA_BACKEND_START_NAMESPACE
  23. #if 0
  24. } // Fix editor indentation
  25. #endif
  26. // -----------------------------------------------------------------------
  27. // EngineRackBuffers
  28. EngineRackBuffers::EngineRackBuffers(const uint32_t bufferSize)
  29. : lastConnectionId(0)
  30. {
  31. resize(bufferSize);
  32. }
  33. EngineRackBuffers::~EngineRackBuffers() noexcept
  34. {
  35. clear();
  36. }
  37. void EngineRackBuffers::clear() noexcept
  38. {
  39. lastConnectionId = 0;
  40. if (in[0] != nullptr)
  41. {
  42. delete[] in[0];
  43. in[0] = nullptr;
  44. }
  45. if (in[1] != nullptr)
  46. {
  47. delete[] in[1];
  48. in[1] = nullptr;
  49. }
  50. if (out[0] != nullptr)
  51. {
  52. delete[] out[0];
  53. out[0] = nullptr;
  54. }
  55. if (out[1] != nullptr)
  56. {
  57. delete[] out[1];
  58. out[1] = nullptr;
  59. }
  60. connectedIn1.clear();
  61. connectedIn2.clear();
  62. connectedOut1.clear();
  63. connectedOut2.clear();
  64. usedConnections.clear();
  65. }
  66. void EngineRackBuffers::resize(const uint32_t bufferSize)
  67. {
  68. if (bufferSize > 0)
  69. {
  70. in[0] = new float[bufferSize];
  71. in[1] = new float[bufferSize];
  72. out[0] = new float[bufferSize];
  73. out[1] = new float[bufferSize];
  74. }
  75. else
  76. {
  77. in[0] = nullptr;
  78. in[1] = nullptr;
  79. out[0] = nullptr;
  80. out[1] = nullptr;
  81. }
  82. }
  83. bool EngineRackBuffers::connect(CarlaEngine* const engine, const int groupA, const int portA, const int groupB, const int portB) noexcept
  84. {
  85. CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);
  86. CARLA_SAFE_ASSERT_RETURN(groupA != groupB, false);
  87. CARLA_SAFE_ASSERT_RETURN(groupA >= RACK_PATCHBAY_GROUP_CARLA && groupA < RACK_PATCHBAY_GROUP_MAX, false);
  88. CARLA_SAFE_ASSERT_RETURN(groupB >= RACK_PATCHBAY_GROUP_CARLA && groupB < RACK_PATCHBAY_GROUP_MAX, false);
  89. CARLA_SAFE_ASSERT_RETURN(portA >= 0, false);
  90. CARLA_SAFE_ASSERT_RETURN(portB >= 0, false);
  91. int carlaPort, otherPort;
  92. if (groupA == RACK_PATCHBAY_GROUP_CARLA)
  93. {
  94. carlaPort = portA;
  95. otherPort = portB;
  96. }
  97. else
  98. {
  99. CARLA_SAFE_ASSERT_RETURN(groupB == RACK_PATCHBAY_GROUP_CARLA, false);
  100. carlaPort = portB;
  101. otherPort = portA;
  102. }
  103. bool makeConnection = false;
  104. switch (carlaPort)
  105. {
  106. case RACK_PATCHBAY_CARLA_PORT_AUDIO_IN1:
  107. connectLock.enter();
  108. connectedIn1.append(otherPort);
  109. connectLock.leave();
  110. makeConnection = true;
  111. break;
  112. case RACK_PATCHBAY_CARLA_PORT_AUDIO_IN2:
  113. connectLock.enter();
  114. connectedIn2.append(otherPort);
  115. connectLock.leave();
  116. makeConnection = true;
  117. break;
  118. case RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT1:
  119. connectLock.enter();
  120. connectedOut1.append(otherPort);
  121. connectLock.leave();
  122. makeConnection = true;
  123. break;
  124. case RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT2:
  125. connectLock.enter();
  126. connectedOut2.append(otherPort);
  127. connectLock.leave();
  128. makeConnection = true;
  129. break;
  130. case RACK_PATCHBAY_CARLA_PORT_MIDI_IN:
  131. makeConnection = engine->connectRackMidiInPort(otherPort);
  132. break;
  133. case RACK_PATCHBAY_CARLA_PORT_MIDI_OUT:
  134. makeConnection = engine->connectRackMidiOutPort(otherPort);
  135. break;
  136. }
  137. if (! makeConnection)
  138. {
  139. engine->setLastError("Invalid rack connection");
  140. return false;
  141. }
  142. ConnectionToId connectionToId;
  143. connectionToId.id = lastConnectionId;
  144. connectionToId.groupA = groupA;
  145. connectionToId.portA = portA;
  146. connectionToId.groupB = groupB;
  147. connectionToId.portB = portB;
  148. char strBuf[STR_MAX+1];
  149. strBuf[STR_MAX] = '\0';
  150. std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", groupA, portA, groupB, portB);
  151. engine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, lastConnectionId, 0, 0, 0.0f, strBuf);
  152. usedConnections.append(connectionToId);
  153. ++lastConnectionId;
  154. return true;
  155. }
  156. const char* const* EngineRackBuffers::getConnections() const
  157. {
  158. if (usedConnections.count() == 0)
  159. return nullptr;
  160. LinkedList<const char*> connList;
  161. char strBuf[STR_MAX+1];
  162. for (LinkedList<ConnectionToId>::Itenerator it=usedConnections.begin(); it.valid(); it.next())
  163. {
  164. const ConnectionToId& connection(it.getValue());
  165. CARLA_SAFE_ASSERT_CONTINUE(connection.groupA != connection.groupB);
  166. CARLA_SAFE_ASSERT_CONTINUE(connection.groupA >= RACK_PATCHBAY_GROUP_CARLA && connection.groupA < RACK_PATCHBAY_GROUP_MAX);
  167. CARLA_SAFE_ASSERT_CONTINUE(connection.groupB >= RACK_PATCHBAY_GROUP_CARLA && connection.groupB < RACK_PATCHBAY_GROUP_MAX);
  168. CARLA_SAFE_ASSERT_CONTINUE(connection.portA >= 0);
  169. CARLA_SAFE_ASSERT_CONTINUE(connection.portB >= 0);
  170. int carlaPort, otherPort;
  171. if (connection.groupA == RACK_PATCHBAY_GROUP_CARLA)
  172. {
  173. carlaPort = connection.portA;
  174. otherPort = connection.portB;
  175. }
  176. else
  177. {
  178. CARLA_SAFE_ASSERT_CONTINUE(connection.groupB == RACK_PATCHBAY_GROUP_CARLA);
  179. carlaPort = connection.portB;
  180. otherPort = connection.portA;
  181. }
  182. switch (carlaPort)
  183. {
  184. case RACK_PATCHBAY_CARLA_PORT_AUDIO_IN1:
  185. case RACK_PATCHBAY_CARLA_PORT_AUDIO_IN2:
  186. std::sprintf(strBuf, "AudioIn:%i", otherPort+1);
  187. connList.append(carla_strdup(strBuf));
  188. connList.append(carla_strdup((carlaPort == RACK_PATCHBAY_CARLA_PORT_AUDIO_IN1) ? "Carla:AudioIn1" : "Carla:AudioIn2"));
  189. break;
  190. case RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT1:
  191. case RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT2:
  192. connList.append(carla_strdup((carlaPort == RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT1) ? "Carla:AudioOut1" : "Carla:AudioOut2"));
  193. std::sprintf(strBuf, "AudioOut:%i", otherPort+1);
  194. connList.append(carla_strdup(strBuf));
  195. break;
  196. case RACK_PATCHBAY_CARLA_PORT_MIDI_IN:
  197. std::sprintf(strBuf, "MidiIn:%i", otherPort+1);
  198. connList.append(carla_strdup(strBuf));
  199. connList.append(carla_strdup("Carla:MidiIn"));
  200. break;
  201. case RACK_PATCHBAY_CARLA_PORT_MIDI_OUT:
  202. connList.append(carla_strdup("Carla:MidiOut"));
  203. std::sprintf(strBuf, "MidiOut:%i", otherPort+1);
  204. connList.append(carla_strdup(strBuf));
  205. break;
  206. }
  207. }
  208. const size_t connCount(connList.count());
  209. if (connCount == 0)
  210. return nullptr;
  211. const char** const retConns = new const char*[connCount+1];
  212. for (size_t i=0; i < connCount; ++i)
  213. retConns[i] = connList.getAt(i);
  214. retConns[connCount] = nullptr;
  215. connList.clear();
  216. return retConns;
  217. }
  218. // -----------------------------------------------------------------------
  219. // EnginePatchbayBuffers
  220. EnginePatchbayBuffers::EnginePatchbayBuffers(const uint32_t bufferSize)
  221. {
  222. resize(bufferSize);
  223. }
  224. EnginePatchbayBuffers::~EnginePatchbayBuffers() noexcept
  225. {
  226. clear();
  227. }
  228. void EnginePatchbayBuffers::clear() noexcept
  229. {
  230. }
  231. void EnginePatchbayBuffers::resize(const uint32_t /*bufferSize*/)
  232. {
  233. }
  234. bool EnginePatchbayBuffers::connect(CarlaEngine* const engine, const int, const int, const int, const int) noexcept
  235. {
  236. CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);
  237. return false;
  238. }
  239. const char* const* EnginePatchbayBuffers::getConnections() const
  240. {
  241. return nullptr;
  242. }
  243. // -----------------------------------------------------------------------
  244. // InternalAudio
  245. EngineInternalAudio::EngineInternalAudio() noexcept
  246. : isReady(false),
  247. usePatchbay(false),
  248. inCount(0),
  249. outCount(0)
  250. {
  251. rack = nullptr;
  252. }
  253. EngineInternalAudio::~EngineInternalAudio() noexcept
  254. {
  255. CARLA_SAFE_ASSERT(! isReady);
  256. CARLA_SAFE_ASSERT(rack == nullptr);
  257. }
  258. void EngineInternalAudio::initPatchbay() noexcept
  259. {
  260. if (usePatchbay)
  261. {
  262. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  263. // TODO
  264. }
  265. else
  266. {
  267. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  268. rack->lastConnectionId = 0;
  269. rack->usedConnections.clear();
  270. }
  271. }
  272. void EngineInternalAudio::clear() noexcept
  273. {
  274. isReady = false;
  275. inCount = 0;
  276. outCount = 0;
  277. if (usePatchbay)
  278. {
  279. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  280. delete patchbay;
  281. patchbay = nullptr;
  282. }
  283. else
  284. {
  285. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  286. delete rack;
  287. rack = nullptr;
  288. }
  289. }
  290. void EngineInternalAudio::create(const uint32_t bufferSize)
  291. {
  292. if (usePatchbay)
  293. {
  294. CARLA_SAFE_ASSERT_RETURN(patchbay == nullptr,);
  295. patchbay = new EnginePatchbayBuffers(bufferSize);
  296. }
  297. else
  298. {
  299. CARLA_SAFE_ASSERT_RETURN(rack == nullptr,);
  300. rack = new EngineRackBuffers(bufferSize);
  301. }
  302. isReady = true;
  303. }
  304. void EngineInternalAudio::resize(const uint32_t bufferSize)
  305. {
  306. if (usePatchbay)
  307. {
  308. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  309. patchbay->resize(bufferSize);
  310. }
  311. else
  312. {
  313. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  314. rack->resize(bufferSize);
  315. }
  316. }
  317. bool EngineInternalAudio::connect(CarlaEngine* const engine, const int groupA, const int portA, const int groupB, const int portB) noexcept
  318. {
  319. if (usePatchbay)
  320. {
  321. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr, nullptr);
  322. return patchbay->connect(engine, groupA, portA, groupB, portB);
  323. }
  324. else
  325. {
  326. CARLA_SAFE_ASSERT_RETURN(rack != nullptr, nullptr);
  327. return rack->connect(engine, groupA, portA, groupB, portB);
  328. }
  329. }
  330. const char* const* EngineInternalAudio::getConnections() const
  331. {
  332. if (usePatchbay)
  333. {
  334. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr, nullptr);
  335. return patchbay->getConnections();
  336. }
  337. else
  338. {
  339. CARLA_SAFE_ASSERT_RETURN(rack != nullptr, nullptr);
  340. return rack->getConnections();
  341. }
  342. }
  343. // -----------------------------------------------------------------------
  344. // InternalEvents
  345. EngineInternalEvents::EngineInternalEvents() noexcept
  346. : in(nullptr),
  347. out(nullptr) {}
  348. EngineInternalEvents::~EngineInternalEvents() noexcept
  349. {
  350. CARLA_SAFE_ASSERT(in == nullptr);
  351. CARLA_SAFE_ASSERT(out == nullptr);
  352. }
  353. // -----------------------------------------------------------------------
  354. // InternalTime
  355. EngineInternalTime::EngineInternalTime() noexcept
  356. : playing(false),
  357. frame(0) {}
  358. // -----------------------------------------------------------------------
  359. // NextAction
  360. EngineNextAction::EngineNextAction() noexcept
  361. : opcode(kEnginePostActionNull),
  362. pluginId(0),
  363. value(0) {}
  364. EngineNextAction::~EngineNextAction() noexcept
  365. {
  366. CARLA_SAFE_ASSERT(opcode == kEnginePostActionNull);
  367. }
  368. void EngineNextAction::ready() noexcept
  369. {
  370. mutex.lock();
  371. mutex.unlock();
  372. }
  373. // -----------------------------------------------------------------------
  374. // EnginePluginData
  375. void EnginePluginData::clear() noexcept
  376. {
  377. plugin = nullptr;
  378. insPeak[0] = insPeak[1] = 0.0f;
  379. outsPeak[0] = outsPeak[1] = 0.0f;
  380. }
  381. // -----------------------------------------------------------------------
  382. // CarlaEngineProtectedData
  383. CarlaEngineProtectedData::CarlaEngineProtectedData(CarlaEngine* const engine)
  384. : osc(engine),
  385. thread(engine),
  386. oscData(nullptr),
  387. callback(nullptr),
  388. callbackPtr(nullptr),
  389. fileCallback(nullptr),
  390. fileCallbackPtr(nullptr),
  391. hints(0x0),
  392. bufferSize(0),
  393. sampleRate(0.0),
  394. aboutToClose(false),
  395. curPluginCount(0),
  396. maxPluginNumber(0),
  397. nextPluginId(0),
  398. plugins(nullptr) {}
  399. CarlaEngineProtectedData::~CarlaEngineProtectedData() noexcept
  400. {
  401. CARLA_SAFE_ASSERT(curPluginCount == 0);
  402. CARLA_SAFE_ASSERT(maxPluginNumber == 0);
  403. CARLA_SAFE_ASSERT(nextPluginId == 0);
  404. CARLA_SAFE_ASSERT(plugins == nullptr);
  405. }
  406. // -----------------------------------------------------------------------
  407. void CarlaEngineProtectedData::doPluginRemove() noexcept
  408. {
  409. CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,);
  410. CARLA_SAFE_ASSERT_RETURN(nextAction.pluginId < curPluginCount,);
  411. --curPluginCount;
  412. // move all plugins 1 spot backwards
  413. for (unsigned int i=nextAction.pluginId; i < curPluginCount; ++i)
  414. {
  415. CarlaPlugin* const plugin(plugins[i+1].plugin);
  416. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  417. plugin->setId(i);
  418. plugins[i].plugin = plugin;
  419. plugins[i].insPeak[0] = 0.0f;
  420. plugins[i].insPeak[1] = 0.0f;
  421. plugins[i].outsPeak[0] = 0.0f;
  422. plugins[i].outsPeak[1] = 0.0f;
  423. }
  424. const unsigned int id(curPluginCount);
  425. // reset last plugin (now removed)
  426. plugins[id].plugin = nullptr;
  427. plugins[id].insPeak[0] = 0.0f;
  428. plugins[id].insPeak[1] = 0.0f;
  429. plugins[id].outsPeak[0] = 0.0f;
  430. plugins[id].outsPeak[1] = 0.0f;
  431. }
  432. void CarlaEngineProtectedData::doPluginsSwitch() noexcept
  433. {
  434. CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,);
  435. const unsigned int idA(nextAction.pluginId);
  436. const unsigned int idB(nextAction.value);
  437. CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,);
  438. CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,);
  439. CARLA_SAFE_ASSERT_RETURN(plugins[idA].plugin != nullptr,);
  440. CARLA_SAFE_ASSERT_RETURN(plugins[idB].plugin != nullptr,);
  441. #if 0
  442. std::swap(plugins[idA].plugin, plugins[idB].plugin);
  443. #else
  444. CarlaPlugin* const tmp(plugins[idA].plugin);
  445. plugins[idA].plugin = plugins[idB].plugin;
  446. plugins[idB].plugin = tmp;
  447. #endif
  448. }
  449. void CarlaEngineProtectedData::doNextPluginAction(const bool unlock) noexcept
  450. {
  451. switch (nextAction.opcode)
  452. {
  453. case kEnginePostActionNull:
  454. break;
  455. case kEnginePostActionZeroCount:
  456. curPluginCount = 0;
  457. break;
  458. case kEnginePostActionRemovePlugin:
  459. doPluginRemove();
  460. break;
  461. case kEnginePostActionSwitchPlugins:
  462. doPluginsSwitch();
  463. break;
  464. }
  465. nextAction.opcode = kEnginePostActionNull;
  466. nextAction.pluginId = 0;
  467. nextAction.value = 0;
  468. if (unlock)
  469. nextAction.mutex.unlock();
  470. }
  471. // -----------------------------------------------------------------------
  472. #ifndef BUILD_BRIDGE
  473. void CarlaEngineProtectedData::processRack(float* inBufReal[2], float* outBuf[2], const uint32_t frames, const bool isOffline)
  474. {
  475. CARLA_SAFE_ASSERT_RETURN(bufEvents.in != nullptr,);
  476. CARLA_SAFE_ASSERT_RETURN(bufEvents.out != nullptr,);
  477. // safe copy
  478. float inBuf0[frames];
  479. float inBuf1[frames];
  480. float* inBuf[2] = { inBuf0, inBuf1 };
  481. // initialize audio inputs
  482. FLOAT_COPY(inBuf0, inBufReal[0], frames);
  483. FLOAT_COPY(inBuf1, inBufReal[1], frames);
  484. // initialize audio outputs (zero)
  485. FLOAT_CLEAR(outBuf[0], frames);
  486. FLOAT_CLEAR(outBuf[1], frames);
  487. // initialize event outputs (zero)
  488. carla_zeroStruct<EngineEvent>(bufEvents.out, kMaxEngineEventInternalCount);
  489. bool processed = false;
  490. uint32_t oldAudioInCount = 0;
  491. uint32_t oldMidiOutCount = 0;
  492. // process plugins
  493. for (unsigned int i=0; i < curPluginCount; ++i)
  494. {
  495. CarlaPlugin* const plugin = plugins[i].plugin;
  496. if (plugin == nullptr || ! plugin->isEnabled() || ! plugin->tryLock(isOffline))
  497. continue;
  498. if (processed)
  499. {
  500. // initialize audio inputs (from previous outputs)
  501. FLOAT_COPY(inBuf0, outBuf[0], frames);
  502. FLOAT_COPY(inBuf1, outBuf[1], frames);
  503. // initialize audio outputs (zero)
  504. FLOAT_CLEAR(outBuf[0], frames);
  505. FLOAT_CLEAR(outBuf[1], frames);
  506. // if plugin has no midi out, add previous events
  507. if (oldMidiOutCount == 0 && bufEvents.in[0].type != kEngineEventTypeNull)
  508. {
  509. if (bufEvents.out[0].type != kEngineEventTypeNull)
  510. {
  511. // TODO: carefully add to input, sorted events
  512. }
  513. // else nothing needed
  514. }
  515. else
  516. {
  517. // initialize event inputs from previous outputs
  518. carla_copyStruct<EngineEvent>(bufEvents.in, bufEvents.out, kMaxEngineEventInternalCount);
  519. // initialize event outputs (zero)
  520. carla_zeroStruct<EngineEvent>(bufEvents.out, kMaxEngineEventInternalCount);
  521. }
  522. }
  523. oldAudioInCount = plugin->getAudioInCount();
  524. oldMidiOutCount = plugin->getMidiOutCount();
  525. // process
  526. plugin->initBuffers();
  527. plugin->process(inBuf, outBuf, frames);
  528. plugin->unlock();
  529. // if plugin has no audio inputs, add input buffer
  530. if (oldAudioInCount == 0)
  531. {
  532. FLOAT_ADD(outBuf[0], inBuf0, frames);
  533. FLOAT_ADD(outBuf[1], inBuf1, frames);
  534. }
  535. // set peaks
  536. {
  537. EnginePluginData& pluginData(plugins[i]);
  538. #ifdef HAVE_JUCE
  539. float tmpMin, tmpMax;
  540. if (oldAudioInCount > 0)
  541. {
  542. FloatVectorOperations::findMinAndMax(inBuf0, static_cast<int>(frames), tmpMin, tmpMax);
  543. pluginData.insPeak[0] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f);
  544. FloatVectorOperations::findMinAndMax(inBuf1, static_cast<int>(frames), tmpMin, tmpMax);
  545. pluginData.insPeak[1] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f);
  546. }
  547. else
  548. {
  549. pluginData.insPeak[0] = 0.0f;
  550. pluginData.insPeak[1] = 0.0f;
  551. }
  552. if (plugin->getAudioOutCount() > 0)
  553. {
  554. FloatVectorOperations::findMinAndMax(outBuf[0], static_cast<int>(frames), tmpMin, tmpMax);
  555. pluginData.outsPeak[0] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f);
  556. FloatVectorOperations::findMinAndMax(outBuf[1], static_cast<int>(frames), tmpMin, tmpMax);
  557. pluginData.outsPeak[1] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f);
  558. }
  559. else
  560. {
  561. pluginData.outsPeak[0] = 0.0f;
  562. pluginData.outsPeak[1] = 0.0f;
  563. }
  564. #else
  565. float peak1, peak2;
  566. if (oldAudioInCount > 0)
  567. {
  568. peak1 = peak2 = 0.0f;
  569. for (uint32_t k=0; k < frames; ++k)
  570. {
  571. peak1 = carla_max<float>(peak1, std::fabs(inBuf0[k]), 1.0f);
  572. peak2 = carla_max<float>(peak2, std::fabs(inBuf1[k]), 1.0f);
  573. }
  574. pluginData.insPeak[0] = peak1;
  575. pluginData.insPeak[1] = peak2;
  576. }
  577. else
  578. {
  579. pluginData.insPeak[0] = 0.0f;
  580. pluginData.insPeak[1] = 0.0f;
  581. }
  582. if (plugin->getAudioOutCount() > 0)
  583. {
  584. peak1 = peak2 = 0.0f;
  585. for (uint32_t k=0; k < frames; ++k)
  586. {
  587. peak1 = carla_max<float>(peak1, std::fabs(outBuf[0][k]), 1.0f);
  588. peak2 = carla_max<float>(peak2, std::fabs(outBuf[1][k]), 1.0f);
  589. }
  590. pluginData.outsPeak[0] = peak1;
  591. pluginData.outsPeak[1] = peak2;
  592. }
  593. else
  594. {
  595. pluginData.outsPeak[0] = 0.0f;
  596. pluginData.outsPeak[1] = 0.0f;
  597. }
  598. #endif
  599. }
  600. processed = true;
  601. }
  602. }
  603. void CarlaEngineProtectedData::processRackFull(float** const inBuf, const uint32_t inCount, float** const outBuf, const uint32_t outCount, const uint32_t nframes, const bool isOffline)
  604. {
  605. EngineRackBuffers* const rack(bufAudio.rack);
  606. const CarlaCriticalSectionScope _cs2(rack->connectLock);
  607. // connect input buffers
  608. if (rack->connectedIn1.count() == 0)
  609. {
  610. FLOAT_CLEAR(rack->in[0], nframes);
  611. }
  612. else
  613. {
  614. bool first = true;
  615. for (LinkedList<int>::Itenerator it = rack->connectedIn1.begin(); it.valid(); it.next())
  616. {
  617. const int& port(it.getValue());
  618. CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(inCount));
  619. if (first)
  620. {
  621. FLOAT_COPY(rack->in[0], inBuf[port], nframes);
  622. first = false;
  623. }
  624. else
  625. {
  626. FLOAT_ADD(rack->in[0], inBuf[port], nframes);
  627. }
  628. }
  629. if (first)
  630. FLOAT_CLEAR(rack->in[0], nframes);
  631. }
  632. if (rack->connectedIn2.count() == 0)
  633. {
  634. FLOAT_CLEAR(rack->in[1], nframes);
  635. }
  636. else
  637. {
  638. bool first = true;
  639. for (LinkedList<int>::Itenerator it = rack->connectedIn2.begin(); it.valid(); it.next())
  640. {
  641. const int& port(it.getValue());
  642. CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(inCount));
  643. if (first)
  644. {
  645. FLOAT_COPY(rack->in[1], inBuf[port], nframes);
  646. first = false;
  647. }
  648. else
  649. {
  650. FLOAT_ADD(rack->in[1], inBuf[port], nframes);
  651. }
  652. }
  653. if (first)
  654. FLOAT_CLEAR(rack->in[1], nframes);
  655. }
  656. FLOAT_CLEAR(rack->out[0], nframes);
  657. FLOAT_CLEAR(rack->out[1], nframes);
  658. // process
  659. processRack(rack->in, rack->out, nframes, isOffline);
  660. // connect output buffers
  661. if (rack->connectedOut1.count() != 0)
  662. {
  663. for (LinkedList<int>::Itenerator it = rack->connectedOut1.begin(); it.valid(); it.next())
  664. {
  665. const int& port(it.getValue());
  666. CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(outCount));
  667. FLOAT_ADD(outBuf[port], rack->out[0], nframes);
  668. }
  669. }
  670. if (rack->connectedOut2.count() != 0)
  671. {
  672. for (LinkedList<int>::Itenerator it = rack->connectedOut2.begin(); it.valid(); it.next())
  673. {
  674. const int& port(it.getValue());
  675. CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(outCount));
  676. FLOAT_ADD(outBuf[port], rack->out[1], nframes);
  677. }
  678. }
  679. }
  680. #endif
  681. // -----------------------------------------------------------------------
  682. // ScopedActionLock
  683. CarlaEngineProtectedData::ScopedActionLock::ScopedActionLock(CarlaEngineProtectedData* const data, const EnginePostAction action, const unsigned int pluginId, const unsigned int value, const bool lockWait) noexcept
  684. : fData(data)
  685. {
  686. fData->nextAction.mutex.lock();
  687. CARLA_SAFE_ASSERT_RETURN(fData->nextAction.opcode == kEnginePostActionNull,);
  688. fData->nextAction.opcode = action;
  689. fData->nextAction.pluginId = pluginId;
  690. fData->nextAction.value = value;
  691. if (lockWait)
  692. {
  693. // block wait for unlock on processing side
  694. carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId);
  695. fData->nextAction.mutex.lock();
  696. carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId);
  697. }
  698. else
  699. {
  700. fData->doNextPluginAction(false);
  701. }
  702. }
  703. CarlaEngineProtectedData::ScopedActionLock::~ScopedActionLock() noexcept
  704. {
  705. fData->nextAction.mutex.unlock();
  706. }
  707. // -----------------------------------------------------------------------
  708. CARLA_BACKEND_END_NAMESPACE