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.hpp 16KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /*
  2. * Carla Engine
  3. * Copyright (C) 2012-2013 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. #ifndef CARLA_ENGINE_INTERNAL_HPP_INCLUDED
  18. #define CARLA_ENGINE_INTERNAL_HPP_INCLUDED
  19. #include "CarlaEngine.hpp"
  20. #include "CarlaEngineOsc.hpp"
  21. #include "CarlaEngineThread.hpp"
  22. #include "CarlaPlugin.hpp"
  23. #include "CarlaMutex.hpp"
  24. #include "List.hpp"
  25. #ifdef HAVE_JUCE
  26. # include "juce_audio_basics.h"
  27. using juce::FloatVectorOperations;
  28. #endif
  29. // -----------------------------------------------------------------------
  30. // Engine helper macro, sets lastError and returns false/NULL
  31. #define CARLA_SAFE_ASSERT_RETURN_ERR(cond, err) if (cond) pass(); else { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return false; }
  32. #define CARLA_SAFE_ASSERT_RETURN_ERRN(cond, err) if (cond) pass(); else { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return nullptr; }
  33. // -----------------------------------------------------------------------
  34. // Float operations
  35. #ifdef HAVE_JUCE
  36. # define FLOAT_ADD(bufDst, bufSrc, frames) FloatVectorOperations::add(bufDst, bufSrc, frames)
  37. # define FLOAT_COPY(bufDst, bufSrc, frames) FloatVectorOperations::copy(bufDst, bufSrc, frames)
  38. # define FLOAT_CLEAR(buf, frames) FloatVectorOperations::clear(buf, frames)
  39. #else
  40. # define FLOAT_ADD(bufDst, bufSrc, frames) carla_addFloat(bufDst, bufSrc, frames)
  41. # define FLOAT_COPY(bufDst, bufSrc, frames) carla_copyFloat(bufDst, bufSrc, frames)
  42. # define FLOAT_CLEAR(buf, frames) carla_zeroFloat(buf, frames)
  43. #endif
  44. // -----------------------------------------------------------------------
  45. CARLA_BACKEND_START_NAMESPACE
  46. #if 0
  47. } // Fix editor indentation
  48. #endif
  49. // -----------------------------------------------------------------------
  50. static inline
  51. const char* EngineType2Str(const EngineType type)
  52. {
  53. switch (type)
  54. {
  55. case kEngineTypeNull:
  56. return "kEngineTypeNull";
  57. case kEngineTypeJack:
  58. return "kEngineTypeJack";
  59. case kEngineTypeJuce:
  60. return "kEngineTypeJuce";
  61. case kEngineTypeRtAudio:
  62. return "kEngineTypeRtAudio";
  63. case kEngineTypePlugin:
  64. return "kEngineTypePlugin";
  65. case kEngineTypeBridge:
  66. return "kEngineTypeBridge";
  67. }
  68. carla_stderr("CarlaBackend::EngineType2Str(%i) - invalid type", type);
  69. return nullptr;
  70. }
  71. static inline
  72. const char* EnginePortType2Str(const EnginePortType type)
  73. {
  74. switch (type)
  75. {
  76. case kEnginePortTypeNull:
  77. return "kEnginePortTypeNull";
  78. case kEnginePortTypeAudio:
  79. return "kEnginePortTypeAudio";
  80. case kEnginePortTypeCV:
  81. return "kEnginePortTypeCV";
  82. case kEnginePortTypeEvent:
  83. return "kEnginePortTypeEvent";
  84. }
  85. carla_stderr("CarlaBackend::EnginePortType2Str(%i) - invalid type", type);
  86. return nullptr;
  87. }
  88. static inline
  89. const char* EngineEventType2Str(const EngineEventType type)
  90. {
  91. switch (type)
  92. {
  93. case kEngineEventTypeNull:
  94. return "kEngineEventTypeNull";
  95. case kEngineEventTypeControl:
  96. return "kEngineEventTypeControl";
  97. case kEngineEventTypeMidi:
  98. return "kEngineEventTypeMidi";
  99. }
  100. carla_stderr("CarlaBackend::EngineEventType2Str(%i) - invalid type", type);
  101. return nullptr;
  102. }
  103. static inline
  104. const char* EngineControlEventType2Str(const EngineControlEventType type)
  105. {
  106. switch (type)
  107. {
  108. case kEngineControlEventTypeNull:
  109. return "kEngineNullEvent";
  110. case kEngineControlEventTypeParameter:
  111. return "kEngineControlEventTypeParameter";
  112. case kEngineControlEventTypeMidiBank:
  113. return "kEngineControlEventTypeMidiBank";
  114. case kEngineControlEventTypeMidiProgram:
  115. return "kEngineControlEventTypeMidiProgram";
  116. case kEngineControlEventTypeAllSoundOff:
  117. return "kEngineControlEventTypeAllSoundOff";
  118. case kEngineControlEventTypeAllNotesOff:
  119. return "kEngineControlEventTypeAllNotesOff";
  120. }
  121. carla_stderr("CarlaBackend::EngineControlEventType2Str(%i) - invalid type", type);
  122. return nullptr;
  123. }
  124. // -----------------------------------------------------------------------
  125. const unsigned short kEngineMaxInternalEventCount = 512;
  126. enum EnginePostAction {
  127. kEnginePostActionNull,
  128. kEnginePostActionZeroCount,
  129. kEnginePostActionRemovePlugin,
  130. kEnginePostActionSwitchPlugins
  131. };
  132. struct EnginePluginData {
  133. CarlaPlugin* plugin;
  134. float insPeak[2];
  135. float outsPeak[2];
  136. void clear()
  137. {
  138. plugin = nullptr;
  139. insPeak[0] = insPeak[1] = 0.0f;
  140. outsPeak[0] = outsPeak[1] = 0.0f;
  141. }
  142. };
  143. // -----------------------------------------------------------------------
  144. enum RackPatchbayGroupIds {
  145. RACK_PATCHBAY_GROUP_CARLA = -1,
  146. RACK_PATCHBAY_GROUP_AUDIO_IN = 0,
  147. RACK_PATCHBAY_GROUP_AUDIO_OUT = 1,
  148. RACK_PATCHBAY_GROUP_MIDI_IN = 2,
  149. RACK_PATCHBAY_GROUP_MIDI_OUT = 3,
  150. RACK_PATCHBAY_GROUP_MAX = 4
  151. };
  152. enum RackPatchbayPortIds {
  153. RACK_PATCHBAY_PORT_AUDIO_IN1 = -1,
  154. RACK_PATCHBAY_PORT_AUDIO_IN2 = -2,
  155. RACK_PATCHBAY_PORT_AUDIO_OUT1 = -3,
  156. RACK_PATCHBAY_PORT_AUDIO_OUT2 = -4,
  157. RACK_PATCHBAY_PORT_MIDI_IN = -5,
  158. RACK_PATCHBAY_PORT_MIDI_OUT = -6,
  159. RACK_PATCHBAY_PORT_MAX = -7
  160. };
  161. struct PortNameToId {
  162. int portId;
  163. char name[STR_MAX+1];
  164. };
  165. struct ConnectionToId {
  166. int id;
  167. int portOut;
  168. int portIn;
  169. };
  170. // -----------------------------------------------------------------------
  171. struct EngineRackBuffers {
  172. float* in[2];
  173. float* out[2];
  174. // connections stuff
  175. List<uint> connectedIns[2];
  176. List<uint> connectedOuts[2];
  177. CarlaMutex connectLock;
  178. int lastConnectionId;
  179. List<ConnectionToId> usedConnections;
  180. EngineRackBuffers(const uint32_t bufferSize)
  181. : lastConnectionId(0)
  182. {
  183. resize(bufferSize);
  184. }
  185. ~EngineRackBuffers()
  186. {
  187. clear();
  188. }
  189. void clear()
  190. {
  191. lastConnectionId = 0;
  192. if (in[0] != nullptr)
  193. {
  194. delete[] in[0];
  195. in[0] = nullptr;
  196. }
  197. if (in[1] != nullptr)
  198. {
  199. delete[] in[1];
  200. in[1] = nullptr;
  201. }
  202. if (out[0] != nullptr)
  203. {
  204. delete[] out[0];
  205. out[0] = nullptr;
  206. }
  207. if (out[1] != nullptr)
  208. {
  209. delete[] out[1];
  210. out[1] = nullptr;
  211. }
  212. connectedIns[0].clear();
  213. connectedIns[1].clear();
  214. connectedOuts[0].clear();
  215. connectedOuts[1].clear();
  216. usedConnections.clear();
  217. }
  218. void resize(const uint32_t bufferSize)
  219. {
  220. if (bufferSize > 0)
  221. {
  222. in[0] = new float[bufferSize];
  223. in[1] = new float[bufferSize];
  224. out[0] = new float[bufferSize];
  225. out[1] = new float[bufferSize];
  226. }
  227. else
  228. {
  229. in[0] = nullptr;
  230. in[1] = nullptr;
  231. out[0] = nullptr;
  232. out[1] = nullptr;
  233. }
  234. }
  235. };
  236. struct EnginePatchbayBuffers {
  237. EnginePatchbayBuffers(const uint32_t bufferSize)
  238. {
  239. resize(bufferSize);
  240. }
  241. ~EnginePatchbayBuffers()
  242. {
  243. clear();
  244. }
  245. void clear()
  246. {
  247. }
  248. void resize(const uint32_t /*bufferSize*/)
  249. {
  250. }
  251. };
  252. // -----------------------------------------------------------------------
  253. struct CarlaEngineProtectedData {
  254. CarlaEngineOsc osc;
  255. CarlaEngineThread thread;
  256. const CarlaOscData* oscData;
  257. EngineCallbackFunc callback;
  258. void* callbackPtr;
  259. unsigned int hints;
  260. uint32_t bufferSize;
  261. double sampleRate;
  262. bool aboutToClose; // don't re-activate thread if true
  263. unsigned int curPluginCount; // number of plugins loaded (0...max)
  264. unsigned int maxPluginNumber; // number of plugins allowed (0, 16, 99 or 255)
  265. unsigned int nextPluginId; // invalid if == maxPluginNumber
  266. CarlaString lastError;
  267. CarlaString name;
  268. EngineOptions options;
  269. EngineTimeInfo timeInfo;
  270. EnginePluginData* plugins;
  271. #ifndef BUILD_BRIDGE
  272. struct InternalAudio {
  273. bool isReady;
  274. bool usePatchbay;
  275. uint inCount;
  276. uint outCount;
  277. union {
  278. EngineRackBuffers* rack;
  279. EnginePatchbayBuffers* patchbay;
  280. };
  281. InternalAudio() noexcept
  282. : isReady(false),
  283. usePatchbay(false),
  284. inCount(0),
  285. outCount(0)
  286. {
  287. rack = nullptr;
  288. }
  289. ~InternalAudio()
  290. {
  291. CARLA_ASSERT(! isReady);
  292. CARLA_ASSERT(rack == nullptr);
  293. }
  294. void initPatchbay()
  295. {
  296. if (usePatchbay)
  297. {
  298. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  299. }
  300. else
  301. {
  302. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  303. rack->lastConnectionId = 0;
  304. rack->usedConnections.clear();
  305. }
  306. }
  307. void clear()
  308. {
  309. isReady = false;
  310. inCount = 0;
  311. outCount = 0;
  312. if (usePatchbay)
  313. {
  314. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  315. delete patchbay;
  316. patchbay = nullptr;
  317. }
  318. else
  319. {
  320. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  321. delete rack;
  322. rack = nullptr;
  323. }
  324. }
  325. void create(const uint32_t bufferSize)
  326. {
  327. if (usePatchbay)
  328. {
  329. CARLA_SAFE_ASSERT_RETURN(patchbay == nullptr,);
  330. patchbay = new EnginePatchbayBuffers(bufferSize);
  331. }
  332. else
  333. {
  334. CARLA_SAFE_ASSERT_RETURN(rack == nullptr,);
  335. rack = new EngineRackBuffers(bufferSize);
  336. }
  337. isReady = true;
  338. }
  339. void resize(const uint32_t bufferSize)
  340. {
  341. if (usePatchbay)
  342. {
  343. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  344. patchbay->resize(bufferSize);
  345. }
  346. else
  347. {
  348. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  349. rack->resize(bufferSize);
  350. }
  351. }
  352. } bufAudio;
  353. #endif
  354. struct InternalEvents {
  355. EngineEvent* in;
  356. EngineEvent* out;
  357. InternalEvents() noexcept
  358. : in(nullptr),
  359. out(nullptr) {}
  360. ~InternalEvents()
  361. {
  362. CARLA_ASSERT(in == nullptr);
  363. CARLA_ASSERT(out == nullptr);
  364. }
  365. } bufEvents;
  366. struct InternalTime {
  367. bool playing;
  368. uint64_t frame;
  369. InternalTime() noexcept
  370. : playing(false),
  371. frame(0) {}
  372. } time;
  373. struct NextAction {
  374. EnginePostAction opcode;
  375. unsigned int pluginId;
  376. unsigned int value;
  377. CarlaMutex mutex;
  378. NextAction() noexcept
  379. : opcode(kEnginePostActionNull),
  380. pluginId(0),
  381. value(0) {}
  382. ~NextAction()
  383. {
  384. CARLA_ASSERT(opcode == kEnginePostActionNull);
  385. }
  386. void ready() noexcept
  387. {
  388. mutex.lock();
  389. mutex.unlock();
  390. }
  391. } nextAction;
  392. CarlaEngineProtectedData(CarlaEngine* const engine)
  393. : osc(engine),
  394. thread(engine),
  395. oscData(nullptr),
  396. callback(nullptr),
  397. callbackPtr(nullptr),
  398. hints(0x0),
  399. bufferSize(0),
  400. sampleRate(0.0),
  401. aboutToClose(false),
  402. curPluginCount(0),
  403. maxPluginNumber(0),
  404. nextPluginId(0),
  405. plugins(nullptr) {}
  406. #ifdef CARLA_PROPER_CPP11_SUPPORT
  407. CarlaEngineProtectedData() = delete;
  408. CARLA_DECLARE_NON_COPY_STRUCT(CarlaEngineProtectedData)
  409. #endif
  410. ~CarlaEngineProtectedData()
  411. {
  412. CARLA_ASSERT(curPluginCount == 0);
  413. CARLA_ASSERT(maxPluginNumber == 0);
  414. CARLA_ASSERT(nextPluginId == 0);
  415. CARLA_ASSERT(plugins == nullptr);
  416. }
  417. void doPluginRemove()
  418. {
  419. CARLA_ASSERT(curPluginCount > 0);
  420. CARLA_ASSERT(nextAction.pluginId < curPluginCount);
  421. --curPluginCount;
  422. // move all plugins 1 spot backwards
  423. for (unsigned int i=nextAction.pluginId; i < curPluginCount; ++i)
  424. {
  425. CarlaPlugin* const plugin(plugins[i+1].plugin);
  426. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  427. plugin->setId(i);
  428. plugins[i].plugin = plugin;
  429. plugins[i].insPeak[0] = 0.0f;
  430. plugins[i].insPeak[1] = 0.0f;
  431. plugins[i].outsPeak[0] = 0.0f;
  432. plugins[i].outsPeak[1] = 0.0f;
  433. }
  434. const unsigned int id(curPluginCount);
  435. // reset last plugin (now removed)
  436. plugins[id].plugin = nullptr;
  437. plugins[id].insPeak[0] = 0.0f;
  438. plugins[id].insPeak[1] = 0.0f;
  439. plugins[id].outsPeak[0] = 0.0f;
  440. plugins[id].outsPeak[1] = 0.0f;
  441. }
  442. void doPluginsSwitch()
  443. {
  444. CARLA_ASSERT(curPluginCount >= 2);
  445. const unsigned int idA(nextAction.pluginId);
  446. const unsigned int idB(nextAction.value);
  447. CARLA_ASSERT(idA < curPluginCount);
  448. CARLA_ASSERT(idB < curPluginCount);
  449. CARLA_ASSERT(plugins[idA].plugin != nullptr);
  450. CARLA_ASSERT(plugins[idB].plugin != nullptr);
  451. #if 0
  452. std::swap(plugins[idA].plugin, plugins[idB].plugin);
  453. #else
  454. CarlaPlugin* const tmp(plugins[idA].plugin);
  455. plugins[idA].plugin = plugins[idB].plugin;
  456. plugins[idB].plugin = tmp;
  457. #endif
  458. }
  459. void doNextPluginAction(const bool unlock) noexcept
  460. {
  461. switch (nextAction.opcode)
  462. {
  463. case kEnginePostActionNull:
  464. break;
  465. case kEnginePostActionZeroCount:
  466. curPluginCount = 0;
  467. break;
  468. case kEnginePostActionRemovePlugin:
  469. doPluginRemove();
  470. break;
  471. case kEnginePostActionSwitchPlugins:
  472. doPluginsSwitch();
  473. break;
  474. }
  475. nextAction.opcode = kEnginePostActionNull;
  476. nextAction.pluginId = 0;
  477. nextAction.value = 0;
  478. if (unlock)
  479. nextAction.mutex.unlock();
  480. }
  481. #ifndef BUILD_BRIDGE
  482. // the base, where plugins run
  483. void processRack(float* inBufReal[2], float* outBuf[2], const uint32_t nframes, const bool isOffline);
  484. // extended, will call processRack() in the middle
  485. void processRackFull(float** const inBuf, const uint32_t inCount, float** const outBuf, const uint32_t outCount, const uint32_t nframes, const bool isOffline);
  486. #endif
  487. class ScopedActionLock
  488. {
  489. public:
  490. ScopedActionLock(CarlaEngineProtectedData* const data, const EnginePostAction action, const unsigned int pluginId, const unsigned int value, const bool lockWait)
  491. : fData(data)
  492. {
  493. fData->nextAction.mutex.lock();
  494. CARLA_ASSERT(fData->nextAction.opcode == kEnginePostActionNull);
  495. fData->nextAction.opcode = action;
  496. fData->nextAction.pluginId = pluginId;
  497. fData->nextAction.value = value;
  498. if (lockWait)
  499. {
  500. // block wait for unlock on processing side
  501. carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId);
  502. fData->nextAction.mutex.lock();
  503. carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId);
  504. }
  505. else
  506. {
  507. fData->doNextPluginAction(false);
  508. }
  509. }
  510. ~ScopedActionLock() noexcept
  511. {
  512. fData->nextAction.mutex.unlock();
  513. }
  514. private:
  515. CarlaEngineProtectedData* const fData;
  516. };
  517. };
  518. // -----------------------------------------------------------------------
  519. CARLA_BACKEND_END_NAMESPACE
  520. #endif // CARLA_ENGINE_INTERNAL_HPP_INCLUDED