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.

CarlaEngineInternal.cpp 27KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  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. const char* const* EngineRackBuffers::getConnections() const
  295. {
  296. if (usedConnections.count() == 0)
  297. return nullptr;
  298. LinkedList<const char*> connList;
  299. char strBuf[STR_MAX+1];
  300. for (LinkedList<ConnectionToId>::Itenerator it=usedConnections.begin(); it.valid(); it.next())
  301. {
  302. const ConnectionToId& connection(it.getValue());
  303. const int otherPort((connection.portOut >= 0) ? connection.portOut : connection.portIn);
  304. const int carlaPort((otherPort == connection.portOut) ? connection.portIn : connection.portOut);
  305. if (otherPort >= RACK_PATCHBAY_GROUP_MIDI_OUT*1000)
  306. {
  307. CARLA_SAFE_ASSERT_CONTINUE(carlaPort == RACK_PATCHBAY_PORT_MIDI_IN);
  308. const int portId(otherPort-RACK_PATCHBAY_GROUP_MIDI_OUT*1000);
  309. std::sprintf(strBuf, "MidiOut:%i", portId+1);
  310. connList.append(carla_strdup(strBuf));
  311. connList.append(carla_strdup("Carla:MidiOut"));
  312. }
  313. else if (otherPort >= RACK_PATCHBAY_GROUP_MIDI_IN*1000)
  314. {
  315. CARLA_SAFE_ASSERT_CONTINUE(carlaPort == RACK_PATCHBAY_PORT_MIDI_OUT);
  316. const int portId(otherPort-RACK_PATCHBAY_GROUP_MIDI_IN*1000);
  317. connList.append(carla_strdup("Carla:MidiIn"));
  318. std::sprintf(strBuf, "MidiIn:%i", portId+1);
  319. connList.append(carla_strdup(strBuf));
  320. }
  321. else if (otherPort >= RACK_PATCHBAY_GROUP_AUDIO_OUT*1000)
  322. {
  323. CARLA_SAFE_ASSERT_CONTINUE(carlaPort == RACK_PATCHBAY_PORT_AUDIO_OUT1 || carlaPort == RACK_PATCHBAY_PORT_AUDIO_OUT2);
  324. const int portId(otherPort-RACK_PATCHBAY_GROUP_AUDIO_OUT*1000);
  325. std::sprintf(strBuf, "AudioOut:%i", portId+1);
  326. connList.append(carla_strdup(strBuf));
  327. connList.append(carla_strdup((carlaPort == RACK_PATCHBAY_PORT_AUDIO_OUT1) ? "Carla:AudioOut1" : "Carla:AudioOut2"));
  328. }
  329. else if (otherPort >= RACK_PATCHBAY_GROUP_AUDIO_IN*1000)
  330. {
  331. CARLA_SAFE_ASSERT_CONTINUE(carlaPort == RACK_PATCHBAY_PORT_AUDIO_IN1 || carlaPort == RACK_PATCHBAY_PORT_AUDIO_IN2);
  332. const int portId(otherPort-RACK_PATCHBAY_GROUP_AUDIO_IN*1000);
  333. connList.append(carla_strdup((carlaPort == RACK_PATCHBAY_PORT_AUDIO_IN1) ? "Carla:AudioIn1" : "Carla:AudioIn2"));
  334. std::sprintf(strBuf, "AudioIn:%i", portId+1);
  335. connList.append(carla_strdup(strBuf));
  336. }
  337. else
  338. {
  339. CARLA_SAFE_ASSERT_RETURN(false, nullptr);
  340. }
  341. }
  342. const size_t connCount(connList.count());
  343. if (connCount == 0)
  344. return nullptr;
  345. const char** const retConns = new const char*[connCount+1];
  346. for (size_t i=0; i < connCount; ++i)
  347. retConns[i] = connList.getAt(i);
  348. retConns[connCount] = nullptr;
  349. connList.clear();
  350. return retConns;
  351. }
  352. // -----------------------------------------------------------------------
  353. // EnginePatchbayBuffers
  354. EnginePatchbayBuffers::EnginePatchbayBuffers(const uint32_t bufferSize)
  355. {
  356. resize(bufferSize);
  357. }
  358. EnginePatchbayBuffers::~EnginePatchbayBuffers()
  359. {
  360. clear();
  361. }
  362. void EnginePatchbayBuffers::clear()
  363. {
  364. }
  365. void EnginePatchbayBuffers::resize(const uint32_t /*bufferSize*/)
  366. {
  367. }
  368. const char* const* EnginePatchbayBuffers::getConnections() const
  369. {
  370. return nullptr;
  371. }
  372. // -----------------------------------------------------------------------
  373. // InternalAudio
  374. EngineInternalAudio::EngineInternalAudio() noexcept
  375. : isReady(false),
  376. usePatchbay(false),
  377. inCount(0),
  378. outCount(0)
  379. {
  380. rack = nullptr;
  381. }
  382. EngineInternalAudio::~EngineInternalAudio() noexcept
  383. {
  384. CARLA_SAFE_ASSERT(! isReady);
  385. CARLA_SAFE_ASSERT(rack == nullptr);
  386. }
  387. void EngineInternalAudio::initPatchbay() noexcept
  388. {
  389. if (usePatchbay)
  390. {
  391. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  392. // TODO
  393. }
  394. else
  395. {
  396. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  397. rack->lastConnectionId = 0;
  398. rack->usedConnections.clear();
  399. }
  400. }
  401. void EngineInternalAudio::clear()
  402. {
  403. isReady = false;
  404. inCount = 0;
  405. outCount = 0;
  406. if (usePatchbay)
  407. {
  408. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  409. delete patchbay;
  410. patchbay = nullptr;
  411. }
  412. else
  413. {
  414. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  415. delete rack;
  416. rack = nullptr;
  417. }
  418. }
  419. void EngineInternalAudio::create(const uint32_t bufferSize)
  420. {
  421. if (usePatchbay)
  422. {
  423. CARLA_SAFE_ASSERT_RETURN(patchbay == nullptr,);
  424. patchbay = new EnginePatchbayBuffers(bufferSize);
  425. }
  426. else
  427. {
  428. CARLA_SAFE_ASSERT_RETURN(rack == nullptr,);
  429. rack = new EngineRackBuffers(bufferSize);
  430. }
  431. isReady = true;
  432. }
  433. void EngineInternalAudio::resize(const uint32_t bufferSize)
  434. {
  435. if (usePatchbay)
  436. {
  437. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  438. patchbay->resize(bufferSize);
  439. }
  440. else
  441. {
  442. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  443. rack->resize(bufferSize);
  444. }
  445. }
  446. // -----------------------------------------------------------------------
  447. // InternalEvents
  448. EngineInternalEvents::EngineInternalEvents() noexcept
  449. : in(nullptr),
  450. out(nullptr) {}
  451. EngineInternalEvents::~EngineInternalEvents() noexcept
  452. {
  453. CARLA_ASSERT(in == nullptr);
  454. CARLA_ASSERT(out == nullptr);
  455. }
  456. // -----------------------------------------------------------------------
  457. // InternalTime
  458. EngineInternalTime::EngineInternalTime() noexcept
  459. : playing(false),
  460. frame(0) {}
  461. // -----------------------------------------------------------------------
  462. // NextAction
  463. EngineNextAction::EngineNextAction() noexcept
  464. : opcode(kEnginePostActionNull),
  465. pluginId(0),
  466. value(0) {}
  467. EngineNextAction::~EngineNextAction() noexcept
  468. {
  469. CARLA_ASSERT(opcode == kEnginePostActionNull);
  470. }
  471. void EngineNextAction::ready() noexcept
  472. {
  473. mutex.lock();
  474. mutex.unlock();
  475. }
  476. // -----------------------------------------------------------------------
  477. // EnginePluginData
  478. void EnginePluginData::clear() noexcept
  479. {
  480. plugin = nullptr;
  481. insPeak[0] = insPeak[1] = 0.0f;
  482. outsPeak[0] = outsPeak[1] = 0.0f;
  483. }
  484. // -----------------------------------------------------------------------
  485. // CarlaEngineProtectedData
  486. CarlaEngineProtectedData::CarlaEngineProtectedData(CarlaEngine* const engine)
  487. : osc(engine),
  488. thread(engine),
  489. oscData(nullptr),
  490. callback(nullptr),
  491. callbackPtr(nullptr),
  492. hints(0x0),
  493. bufferSize(0),
  494. sampleRate(0.0),
  495. aboutToClose(false),
  496. curPluginCount(0),
  497. maxPluginNumber(0),
  498. nextPluginId(0),
  499. plugins(nullptr) {}
  500. CarlaEngineProtectedData::~CarlaEngineProtectedData() noexcept
  501. {
  502. CARLA_SAFE_ASSERT(curPluginCount == 0);
  503. CARLA_SAFE_ASSERT(maxPluginNumber == 0);
  504. CARLA_SAFE_ASSERT(nextPluginId == 0);
  505. CARLA_SAFE_ASSERT(plugins == nullptr);
  506. }
  507. // -----------------------------------------------------------------------
  508. void CarlaEngineProtectedData::doPluginRemove() noexcept
  509. {
  510. CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,);
  511. CARLA_SAFE_ASSERT_RETURN(nextAction.pluginId < curPluginCount,);
  512. --curPluginCount;
  513. // move all plugins 1 spot backwards
  514. for (unsigned int i=nextAction.pluginId; i < curPluginCount; ++i)
  515. {
  516. CarlaPlugin* const plugin(plugins[i+1].plugin);
  517. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  518. plugin->setId(i);
  519. plugins[i].plugin = plugin;
  520. plugins[i].insPeak[0] = 0.0f;
  521. plugins[i].insPeak[1] = 0.0f;
  522. plugins[i].outsPeak[0] = 0.0f;
  523. plugins[i].outsPeak[1] = 0.0f;
  524. }
  525. const unsigned int id(curPluginCount);
  526. // reset last plugin (now removed)
  527. plugins[id].plugin = nullptr;
  528. plugins[id].insPeak[0] = 0.0f;
  529. plugins[id].insPeak[1] = 0.0f;
  530. plugins[id].outsPeak[0] = 0.0f;
  531. plugins[id].outsPeak[1] = 0.0f;
  532. }
  533. void CarlaEngineProtectedData::doPluginsSwitch() noexcept
  534. {
  535. CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,);
  536. const unsigned int idA(nextAction.pluginId);
  537. const unsigned int idB(nextAction.value);
  538. CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,);
  539. CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,);
  540. CARLA_SAFE_ASSERT_RETURN(plugins[idA].plugin != nullptr,);
  541. CARLA_SAFE_ASSERT_RETURN(plugins[idB].plugin != nullptr,);
  542. #if 0
  543. std::swap(plugins[idA].plugin, plugins[idB].plugin);
  544. #else
  545. CarlaPlugin* const tmp(plugins[idA].plugin);
  546. plugins[idA].plugin = plugins[idB].plugin;
  547. plugins[idB].plugin = tmp;
  548. #endif
  549. }
  550. void CarlaEngineProtectedData::doNextPluginAction(const bool unlock) noexcept
  551. {
  552. switch (nextAction.opcode)
  553. {
  554. case kEnginePostActionNull:
  555. break;
  556. case kEnginePostActionZeroCount:
  557. curPluginCount = 0;
  558. break;
  559. case kEnginePostActionRemovePlugin:
  560. doPluginRemove();
  561. break;
  562. case kEnginePostActionSwitchPlugins:
  563. doPluginsSwitch();
  564. break;
  565. }
  566. nextAction.opcode = kEnginePostActionNull;
  567. nextAction.pluginId = 0;
  568. nextAction.value = 0;
  569. if (unlock)
  570. nextAction.mutex.unlock();
  571. }
  572. // -----------------------------------------------------------------------
  573. #ifndef BUILD_BRIDGE
  574. void CarlaEngineProtectedData::processRack(float* inBufReal[2], float* outBuf[2], const uint32_t frames, const bool isOffline)
  575. {
  576. CARLA_SAFE_ASSERT_RETURN(bufEvents.in != nullptr,);
  577. CARLA_SAFE_ASSERT_RETURN(bufEvents.out != nullptr,);
  578. // safe copy
  579. float inBuf0[frames];
  580. float inBuf1[frames];
  581. float* inBuf[2] = { inBuf0, inBuf1 };
  582. // initialize audio inputs
  583. FLOAT_COPY(inBuf0, inBufReal[0], frames);
  584. FLOAT_COPY(inBuf1, inBufReal[1], frames);
  585. // initialize audio outputs (zero)
  586. FLOAT_CLEAR(outBuf[0], frames);
  587. FLOAT_CLEAR(outBuf[1], frames);
  588. // initialize event outputs (zero)
  589. carla_zeroStruct<EngineEvent>(bufEvents.out, kMaxEngineEventInternalCount);
  590. bool processed = false;
  591. uint32_t oldAudioInCount = 0;
  592. uint32_t oldMidiOutCount = 0;
  593. // process plugins
  594. for (unsigned int i=0; i < curPluginCount; ++i)
  595. {
  596. CarlaPlugin* const plugin = plugins[i].plugin;
  597. if (plugin == nullptr || ! plugin->isEnabled() || ! plugin->tryLock(isOffline))
  598. continue;
  599. if (processed)
  600. {
  601. // initialize audio inputs (from previous outputs)
  602. FLOAT_COPY(inBuf0, outBuf[0], frames);
  603. FLOAT_COPY(inBuf1, outBuf[1], frames);
  604. // initialize audio outputs (zero)
  605. FLOAT_CLEAR(outBuf[0], frames);
  606. FLOAT_CLEAR(outBuf[1], frames);
  607. // if plugin has no midi out, add previous events
  608. if (oldMidiOutCount == 0 && bufEvents.in[0].type != kEngineEventTypeNull)
  609. {
  610. if (bufEvents.out[0].type != kEngineEventTypeNull)
  611. {
  612. // TODO: carefully add to input, sorted events
  613. }
  614. // else nothing needed
  615. }
  616. else
  617. {
  618. // initialize event inputs from previous outputs
  619. carla_copyStruct<EngineEvent>(bufEvents.in, bufEvents.out, kMaxEngineEventInternalCount);
  620. // initialize event outputs (zero)
  621. carla_zeroStruct<EngineEvent>(bufEvents.out, kMaxEngineEventInternalCount);
  622. }
  623. }
  624. oldAudioInCount = plugin->getAudioInCount();
  625. oldMidiOutCount = plugin->getMidiOutCount();
  626. // process
  627. plugin->initBuffers();
  628. plugin->process(inBuf, outBuf, frames);
  629. plugin->unlock();
  630. // if plugin has no audio inputs, add input buffer
  631. if (oldAudioInCount == 0)
  632. {
  633. FLOAT_ADD(outBuf[0], inBuf0, frames);
  634. FLOAT_ADD(outBuf[1], inBuf1, frames);
  635. }
  636. // set peaks
  637. {
  638. EnginePluginData& pluginData(plugins[i]);
  639. #ifdef HAVE_JUCE
  640. float tmpMin, tmpMax;
  641. if (oldAudioInCount > 0)
  642. {
  643. FloatVectorOperations::findMinAndMax(inBuf0, static_cast<int>(frames), tmpMin, tmpMax);
  644. pluginData.insPeak[0] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f);
  645. FloatVectorOperations::findMinAndMax(inBuf1, static_cast<int>(frames), tmpMin, tmpMax);
  646. pluginData.insPeak[1] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f);
  647. }
  648. else
  649. {
  650. pluginData.insPeak[0] = 0.0f;
  651. pluginData.insPeak[1] = 0.0f;
  652. }
  653. if (plugin->getAudioOutCount() > 0)
  654. {
  655. FloatVectorOperations::findMinAndMax(outBuf[0], static_cast<int>(frames), tmpMin, tmpMax);
  656. pluginData.outsPeak[0] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f);
  657. FloatVectorOperations::findMinAndMax(outBuf[1], static_cast<int>(frames), tmpMin, tmpMax);
  658. pluginData.outsPeak[1] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f);
  659. }
  660. else
  661. {
  662. pluginData.outsPeak[0] = 0.0f;
  663. pluginData.outsPeak[1] = 0.0f;
  664. }
  665. #else
  666. float peak1, peak2;
  667. if (oldAudioInCount > 0)
  668. {
  669. peak1 = peak2 = 0.0f;
  670. for (uint32_t k=0; k < frames; ++k)
  671. {
  672. peak1 = carla_max<float>(peak1, std::fabs(inBuf0[k]), 1.0f);
  673. peak2 = carla_max<float>(peak2, std::fabs(inBuf1[k]), 1.0f);
  674. }
  675. pluginData.insPeak[0] = peak1;
  676. pluginData.insPeak[1] = peak2;
  677. }
  678. else
  679. {
  680. pluginData.insPeak[0] = 0.0f;
  681. pluginData.insPeak[1] = 0.0f;
  682. }
  683. if (plugin->getAudioOutCount() > 0)
  684. {
  685. peak1 = peak2 = 0.0f;
  686. for (uint32_t k=0; k < frames; ++k)
  687. {
  688. peak1 = carla_max<float>(peak1, std::fabs(outBuf[0][k]), 1.0f);
  689. peak2 = carla_max<float>(peak2, std::fabs(outBuf[1][k]), 1.0f);
  690. }
  691. pluginData.outsPeak[0] = peak1;
  692. pluginData.outsPeak[1] = peak2;
  693. }
  694. else
  695. {
  696. pluginData.outsPeak[0] = 0.0f;
  697. pluginData.outsPeak[1] = 0.0f;
  698. }
  699. #endif
  700. }
  701. processed = true;
  702. }
  703. }
  704. void CarlaEngineProtectedData::processRackFull(float** const inBuf, const uint32_t inCount, float** const outBuf, const uint32_t outCount, const uint32_t nframes, const bool isOffline)
  705. {
  706. EngineRackBuffers* const rack(bufAudio.rack);
  707. const CarlaMutex::ScopedLocker sl(rack->connectLock);
  708. // connect input buffers
  709. if (rack->connectedIns[0].count() == 0)
  710. {
  711. FLOAT_CLEAR(rack->in[0], nframes);
  712. }
  713. else
  714. {
  715. bool first = true;
  716. for (LinkedList<int>::Itenerator it = rack->connectedIns[0].begin(); it.valid(); it.next())
  717. {
  718. const int& port(it.getValue());
  719. CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(inCount));
  720. if (first)
  721. {
  722. FLOAT_COPY(rack->in[0], inBuf[port], nframes);
  723. first = false;
  724. }
  725. else
  726. {
  727. FLOAT_ADD(rack->in[0], inBuf[port], nframes);
  728. }
  729. }
  730. if (first)
  731. FLOAT_CLEAR(rack->in[0], nframes);
  732. }
  733. if (rack->connectedIns[1].count() == 0)
  734. {
  735. FLOAT_CLEAR(rack->in[1], nframes);
  736. }
  737. else
  738. {
  739. bool first = true;
  740. for (LinkedList<int>::Itenerator it = rack->connectedIns[1].begin(); it.valid(); it.next())
  741. {
  742. const int& port(it.getValue());
  743. CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(inCount));
  744. if (first)
  745. {
  746. FLOAT_COPY(rack->in[1], inBuf[port], nframes);
  747. first = false;
  748. }
  749. else
  750. {
  751. FLOAT_ADD(rack->in[1], inBuf[port], nframes);
  752. }
  753. }
  754. if (first)
  755. FLOAT_CLEAR(rack->in[1], nframes);
  756. }
  757. FLOAT_CLEAR(rack->out[0], nframes);
  758. FLOAT_CLEAR(rack->out[1], nframes);
  759. // process
  760. processRack(rack->in, rack->out, nframes, isOffline);
  761. // connect output buffers
  762. if (rack->connectedOuts[0].count() != 0)
  763. {
  764. for (LinkedList<int>::Itenerator it = rack->connectedOuts[0].begin(); it.valid(); it.next())
  765. {
  766. const int& port(it.getValue());
  767. CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(outCount));
  768. FLOAT_ADD(outBuf[port], rack->out[0], nframes);
  769. }
  770. }
  771. if (rack->connectedOuts[1].count() != 0)
  772. {
  773. for (LinkedList<int>::Itenerator it = rack->connectedOuts[1].begin(); it.valid(); it.next())
  774. {
  775. const int& port(it.getValue());
  776. CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(outCount));
  777. FLOAT_ADD(outBuf[port], rack->out[1], nframes);
  778. }
  779. }
  780. }
  781. #endif
  782. // -----------------------------------------------------------------------
  783. // ScopedActionLock
  784. CarlaEngineProtectedData::ScopedActionLock::ScopedActionLock(CarlaEngineProtectedData* const data, const EnginePostAction action, const unsigned int pluginId, const unsigned int value, const bool lockWait) noexcept
  785. : fData(data)
  786. {
  787. fData->nextAction.mutex.lock();
  788. CARLA_SAFE_ASSERT_RETURN(fData->nextAction.opcode == kEnginePostActionNull,);
  789. fData->nextAction.opcode = action;
  790. fData->nextAction.pluginId = pluginId;
  791. fData->nextAction.value = value;
  792. if (lockWait)
  793. {
  794. // block wait for unlock on processing side
  795. carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId);
  796. fData->nextAction.mutex.lock();
  797. carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId);
  798. }
  799. else
  800. {
  801. fData->doNextPluginAction(false);
  802. }
  803. }
  804. CarlaEngineProtectedData::ScopedActionLock::~ScopedActionLock() noexcept
  805. {
  806. fData->nextAction.mutex.unlock();
  807. }
  808. // -----------------------------------------------------------------------
  809. CARLA_BACKEND_END_NAMESPACE