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