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.

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