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.

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