Collection of tools useful for audio production
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.

565 lines
15KB

  1. /*
  2. * Carla Backend
  3. * Copyright (C) 2012 Filipe Coelho <falktx@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * 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 COPYING file
  16. */
  17. #ifdef CARLA_ENGINE_VST
  18. #include "carla_engine.h"
  19. #include "carla_plugin.h"
  20. #include <QtCore/QThread>
  21. CARLA_BACKEND_START_NAMESPACE
  22. #if 0
  23. } /* adjust editor indent */
  24. #endif
  25. #ifdef CARLA_ENGINE_VST
  26. class CarlaEngineVst : public CarlaEngine
  27. {
  28. public:
  29. CarlaEngineVst(audioMasterCallback callback);
  30. ~CarlaEngineVst();
  31. // -------------------------------------
  32. bool init(const char* const name);
  33. bool close();
  34. bool isOnAudioThread();
  35. bool isOffline();
  36. bool isRunning();
  37. CarlaEngineClient* addClient(CarlaPlugin* const plugin);
  38. // -------------------------------------
  39. intptr_t callback(int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
  40. {
  41. return m_callback(&effect, opcode, index, value, ptr, opt);
  42. }
  43. const AEffect* getEffect() const
  44. {
  45. return &effect;
  46. }
  47. // -------------------------------------
  48. intptr_t handleDispatch(int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt);
  49. float handleGetParameter(int32_t index);
  50. void handleSetParameter(int32_t index, float value);
  51. void handleProcessReplacing(float** inputs, float** outputs, int32_t frames);
  52. private:
  53. AEffect effect;
  54. const audioMasterCallback m_callback;
  55. };
  56. #endif
  57. // -------------------------------------------------------------------------------------------------------------------
  58. // static VST<->Engine calls
  59. static intptr_t carla_vst_dispatcher(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
  60. {
  61. qDebug("CarlaEngineVst::dispatcher(%p, %i, %i, " P_INTPTR ", %p, %f)", effect, opcode, index, value, ptr, opt);
  62. CarlaEngineVst* const engine = (CarlaEngineVst*)effect->object;
  63. if (opcode == effClose)
  64. {
  65. delete engine;
  66. return 1;
  67. }
  68. return engine->handleDispatch(opcode, index, value, ptr, opt);
  69. }
  70. static float carla_vst_get_parameter(AEffect* effect, int32_t index)
  71. {
  72. CarlaEngineVst* const engine = (CarlaEngineVst*)effect->object;
  73. return engine->handleGetParameter(index);
  74. }
  75. static void carla_vst_set_parameter(AEffect* effect, int32_t index, float value)
  76. {
  77. CarlaEngineVst* const engine = (CarlaEngineVst*)effect->object;
  78. engine->handleSetParameter(index, value);
  79. }
  80. static void carla_vst_process_replacing(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames)
  81. {
  82. CarlaEngineVst* const engine = (CarlaEngineVst*)effect->object;
  83. engine->handleProcessReplacing(inputs, outputs, sampleFrames);
  84. }
  85. // -------------------------------------------------------------------------------------------------------------------
  86. // Carla Engine (VST)
  87. CarlaEngineVst::CarlaEngineVst(audioMasterCallback callback_) :
  88. CarlaEngine(),
  89. m_callback(callback_)
  90. {
  91. memset(&effect, 0, sizeof(AEffect));
  92. // vst fields
  93. effect.magic = kEffectMagic;
  94. effect.object = this;
  95. effect.version = kVstVersion;
  96. effect.uniqueID = CCONST('C', 'r', 'l', 'a');
  97. // plugin fields
  98. effect.numPrograms = 0;
  99. effect.numParams = 1;
  100. effect.numInputs = 2;
  101. effect.numOutputs = 2;
  102. effect.ioRatio = 1.0f;
  103. // static calls
  104. effect.dispatcher = carla_vst_dispatcher;
  105. effect.process = carla_vst_process_replacing;
  106. effect.getParameter = carla_vst_get_parameter;
  107. effect.setParameter = carla_vst_set_parameter;
  108. effect.processReplacing = carla_vst_process_replacing;
  109. // plugin flags
  110. //effect.flags |= effFlagsHasEditor;
  111. effect.flags |= effFlagsCanReplacing;
  112. //effect.flags |= effFlagsProgramChunks;
  113. // setup engine
  114. sampleRate = callback(audioMasterGetSampleRate, 0, 0, nullptr, 0.0f);
  115. bufferSize = callback(audioMasterGetBlockSize, 0, 0, nullptr, 0.0f);
  116. // set engine name
  117. char strBuf[STR_MAX];
  118. callback(audioMasterGetVendorString, 0, 0, strBuf, 0.0f);
  119. if (strBuf[0] == 0)
  120. strcpy(strBuf, "CarlaVST");
  121. init(strBuf);
  122. carla_options.bridge_lv2gtk2 = strdup("/home/falktx/Personal/FOSS/GIT/Cadence/src/carla-bridge/carla-bridge-lv2-gtk2");
  123. //carla_options.prefer_ui_bridges = true;
  124. }
  125. CarlaEngineVst::~CarlaEngineVst()
  126. {
  127. close();
  128. }
  129. // -------------------------------------------------------------------------------------------------------------------
  130. bool CarlaEngineVst::init(const char* const name_)
  131. {
  132. name = strdup(name_);
  133. osc_init(name);
  134. // TEST
  135. /*
  136. CarlaPlugin::initializer init = {
  137. this,
  138. "fake-filename-here",
  139. nullptr,
  140. "http://invadarecords.com/plugins/lv2/meter"
  141. // "http://nedko.aranaudov.org/soft/filter/2/stereo"
  142. };
  143. */
  144. //short id = CarlaPlugin::newLV2(init);
  145. //CarlaPlugins[id]->setActive(true, false, false);
  146. //CarlaPlugins[id]->showGui(true);
  147. return true;
  148. }
  149. bool CarlaEngineVst::close()
  150. {
  151. if (name)
  152. {
  153. free((void*)name);
  154. name = nullptr;
  155. }
  156. osc_close();
  157. //CarlaPlugin* plugin = CarlaPlugins[0];
  158. //carla_proc_lock();
  159. //plugin->setEnabled(false);
  160. //carla_proc_unlock();
  161. //delete plugin;
  162. return true;
  163. }
  164. bool CarlaEngineVst::isOnAudioThread()
  165. {
  166. return (callback(audioMasterGetCurrentProcessLevel, 0, 0, nullptr, 0.0f) == kVstProcessLevelRealtime);
  167. }
  168. bool CarlaEngineVst::isOffline()
  169. {
  170. return (callback(audioMasterGetCurrentProcessLevel, 0, 0, nullptr, 0.0f) == kVstProcessLevelOffline);
  171. }
  172. bool CarlaEngineVst::isRunning()
  173. {
  174. return true;
  175. }
  176. CarlaEngineClient* CarlaEngineVst::addClient(CarlaPlugin* const plugin)
  177. {
  178. bool active = true;
  179. CarlaEngineClientNativeHandle handle = {
  180. };
  181. return new CarlaEngineClient(handle, active);
  182. Q_UNUSED(plugin);
  183. }
  184. // -------------------------------------------------------------------------------------------------------------------
  185. intptr_t CarlaEngineVst::handleDispatch(int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
  186. {
  187. switch (opcode)
  188. {
  189. case effOpen:
  190. case effClose:
  191. case effSetProgram:
  192. case effGetProgram:
  193. case effSetProgramName:
  194. case effGetProgramName:
  195. case effGetParamLabel:
  196. case effGetParamDisplay:
  197. break;
  198. case effGetParamName:
  199. strncpy((char*)ptr, "Enabled", kVstMaxParamStrLen);
  200. break;
  201. case effGetVu:
  202. break;
  203. case effSetSampleRate:
  204. sampleRate = opt; // TODO - watch for changes
  205. break;
  206. case effSetBlockSize:
  207. bufferSize = value; // TODO - watch for changes
  208. break;
  209. case effMainsChanged:
  210. case effEditGetRect:
  211. case effEditOpen:
  212. case effEditClose:
  213. case effEditDraw:
  214. case effEditMouse:
  215. case effEditKey:
  216. case effEditIdle:
  217. for (unsigned short i=0; i < MAX_PLUGINS; i++)
  218. {
  219. CarlaPlugin* const plugin = getPluginByIndex(i);
  220. if (plugin && plugin->enabled())
  221. plugin->idleGui();
  222. }
  223. break;
  224. case effEditTop:
  225. case effEditSleep:
  226. case effIdentify:
  227. case effGetChunk:
  228. case effSetChunk:
  229. case effProcessEvents:
  230. case effCanBeAutomated:
  231. case effString2Parameter:
  232. case effGetNumProgramCategories:
  233. case effGetProgramNameIndexed:
  234. case effCopyProgram:
  235. case effConnectInput:
  236. case effConnectOutput:
  237. case effGetInputProperties:
  238. case effGetOutputProperties:
  239. case effGetPlugCategory:
  240. case effGetCurrentPosition:
  241. case effGetDestinationBuffer:
  242. case effOfflineNotify:
  243. case effOfflinePrepare:
  244. case effOfflineRun:
  245. case effProcessVarIo:
  246. case effSetSpeakerArrangement:
  247. case effSetBlockSizeAndSampleRate:
  248. case effSetBypass:
  249. case effGetEffectName:
  250. case effGetErrorText:
  251. break;
  252. case effGetVendorString:
  253. strncpy((char*)ptr, "falkTX", kVstMaxVendorStrLen);
  254. break;
  255. case effGetProductString:
  256. strncpy((char*)ptr, "Carla VST", kVstMaxProductStrLen);
  257. break;
  258. case effGetVendorVersion:
  259. return 0x050;
  260. case effVendorSpecific:
  261. return 0;
  262. case effCanDo:
  263. {
  264. const char* const feature = (char*)ptr;
  265. if (strcmp(feature, "sendVstEvents") == 0)
  266. return 1;
  267. if (strcmp(feature, "sendVstMidiEvent") == 0)
  268. return 1;
  269. if (strcmp(feature, "receiveVstEvents") == 0)
  270. return 1;
  271. if (strcmp(feature, "receiveVstMidiEvent") == 0)
  272. return 1;
  273. if (strcmp(feature, "receiveVstTimeInfo") == 0)
  274. return 1;
  275. return 0;
  276. }
  277. case effGetTailSize:
  278. case effIdle:
  279. case effGetIcon:
  280. case effSetViewPosition:
  281. case effGetParameterProperties:
  282. case effKeysRequired:
  283. break;
  284. case effGetVstVersion:
  285. return kVstVersion;
  286. case effEditKeyDown:
  287. case effEditKeyUp:
  288. case effSetEditKnobMode:
  289. case effGetMidiProgramName:
  290. case effGetCurrentMidiProgram:
  291. case effGetMidiProgramCategory:
  292. case effHasMidiProgramsChanged:
  293. case effGetMidiKeyName:
  294. case effBeginSetProgram:
  295. case effEndSetProgram:
  296. case effGetSpeakerArrangement:
  297. case effShellGetNextPlugin:
  298. case effStartProcess:
  299. case effStopProcess:
  300. case effSetTotalSampleToProcess:
  301. case effSetPanLaw:
  302. case effBeginLoadBank:
  303. case effBeginLoadProgram:
  304. case effSetProcessPrecision:
  305. case effGetNumMidiInputChannels:
  306. case effGetNumMidiOutputChannels:
  307. break;
  308. }
  309. return 0;
  310. Q_UNUSED(index);
  311. }
  312. float CarlaEngineVst::handleGetParameter(int32_t index)
  313. {
  314. return 0.0f;
  315. Q_UNUSED(index);
  316. }
  317. void CarlaEngineVst::handleSetParameter(int32_t index, float value)
  318. {
  319. return;
  320. Q_UNUSED(index);
  321. Q_UNUSED(value);
  322. }
  323. void CarlaEngineVst::handleProcessReplacing(float** inputs, float** outputs, int32_t frames)
  324. {
  325. //const VstTimeInfo_R* const vstTimeInfo = (VstTimeInfo_R*)callback(audioMasterGetTime, 0, kVstTransportPlaying, nullptr, 0.0f);
  326. //timeInfo.playing = bool(vstTimeInfo->flags & kVstTransportPlaying);
  327. // if (pos.unique_1 == pos.unique_2)
  328. // {
  329. // timeInfo.frame = pos.frame;
  330. // timeInfo.time = pos.usecs;
  331. // if (pos.valid & JackPositionBBT)
  332. // {
  333. // timeInfo.valid = CarlaEngineTimeBBT;
  334. // timeInfo.bbt.bar = pos.bar;
  335. // timeInfo.bbt.beat = pos.beat;
  336. // timeInfo.bbt.tick = pos.tick;
  337. // timeInfo.bbt.bar_start_tick = pos.bar_start_tick;
  338. // timeInfo.bbt.beats_per_bar = pos.beats_per_bar;
  339. // timeInfo.bbt.beat_type = pos.beat_type;
  340. // timeInfo.bbt.ticks_per_beat = pos.ticks_per_beat;
  341. // timeInfo.bbt.beats_per_minute = pos.beats_per_minute;
  342. // }
  343. // else
  344. // timeInfo.valid = 0;
  345. // }
  346. // else
  347. // {
  348. //timeInfo.frame = 0;
  349. //timeInfo.valid = 0;
  350. // }
  351. // create temporary audio buffers
  352. float ains_tmp_buf1[frames];
  353. float ains_tmp_buf2[frames];
  354. float aouts_tmp_buf1[frames];
  355. float aouts_tmp_buf2[frames];
  356. float* ains_tmp[2] = { ains_tmp_buf1, ains_tmp_buf2 };
  357. float* aouts_tmp[2] = { aouts_tmp_buf1, aouts_tmp_buf2 };
  358. // initialize audio input
  359. memcpy(ains_tmp_buf1, inputs[0], sizeof(float)*frames);
  360. memcpy(ains_tmp_buf2, inputs[1], sizeof(float)*frames);
  361. // initialize control input
  362. memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
  363. {
  364. // TODO
  365. }
  366. // initialize midi input
  367. memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  368. {
  369. // TODO
  370. }
  371. // initialize outputs (zero)
  372. memset(aouts_tmp_buf1, 0, sizeof(float)*frames);
  373. memset(aouts_tmp_buf2, 0, sizeof(float)*frames);
  374. memset(rackControlEventsOut, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
  375. memset(rackMidiEventsOut, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  376. bool processed = false;
  377. // process plugins
  378. for (unsigned short i=0; i < MAX_PLUGINS; i++)
  379. {
  380. CarlaPlugin* const plugin = getPluginByIndex(i);
  381. if (plugin && plugin->enabled())
  382. {
  383. if (processed)
  384. {
  385. // initialize inputs (from previous outputs)
  386. memcpy(ains_tmp_buf1, aouts_tmp_buf1, sizeof(float)*frames);
  387. memcpy(ains_tmp_buf2, aouts_tmp_buf2, sizeof(float)*frames);
  388. memcpy(rackMidiEventsIn, rackMidiEventsOut, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  389. // initialize outputs (zero)
  390. memset(aouts_tmp_buf1, 0, sizeof(float)*frames);
  391. memset(aouts_tmp_buf2, 0, sizeof(float)*frames);
  392. memset(rackMidiEventsOut, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  393. }
  394. // process
  395. processLock();
  396. plugin->initBuffers();
  397. if (carla_options.proccess_hq)
  398. {
  399. float* ains_buffer2[2];
  400. float* aouts_buffer2[2];
  401. for (int32_t j=0; j < frames; j += 8)
  402. {
  403. ains_buffer2[0] = ains_tmp_buf1 + j;
  404. ains_buffer2[1] = ains_tmp_buf2 + j;
  405. aouts_buffer2[0] = aouts_tmp_buf1 + j;
  406. aouts_buffer2[1] = aouts_tmp_buf2 + j;
  407. plugin->process(ains_buffer2, aouts_buffer2, 8, j);
  408. }
  409. }
  410. else
  411. plugin->process(ains_tmp, aouts_tmp, frames);
  412. processUnlock();
  413. // if plugin has no audio inputs, add previous buffers
  414. if (plugin->audioInCount() == 0)
  415. {
  416. for (int32_t j=0; j < frames; j++)
  417. {
  418. aouts_tmp_buf1[j] += ains_tmp_buf1[j];
  419. aouts_tmp_buf2[j] += ains_tmp_buf2[j];
  420. }
  421. }
  422. processed = true;
  423. }
  424. }
  425. // if no plugins in the rack, copy inputs over outputs
  426. if (! processed)
  427. {
  428. memcpy(aouts_tmp_buf1, ains_tmp_buf1, sizeof(float)*frames);
  429. memcpy(aouts_tmp_buf2, ains_tmp_buf2, sizeof(float)*frames);
  430. memcpy(rackMidiEventsOut, rackMidiEventsIn, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  431. }
  432. // output audio
  433. memcpy(outputs[0], aouts_tmp_buf1, sizeof(float)*frames);
  434. memcpy(outputs[1], aouts_tmp_buf2, sizeof(float)*frames);
  435. // output control
  436. {
  437. // TODO
  438. }
  439. // output midi
  440. {
  441. // TODO
  442. }
  443. }
  444. CARLA_BACKEND_END_NAMESPACE
  445. #if 0
  446. } /* adjust editor indent */
  447. #endif
  448. // -------------------------------------------------------------------------------------------------------------------
  449. // VST plugin entry
  450. CARLA_EXPORT
  451. const AEffect* VSTPluginMain(audioMasterCallback callback)
  452. {
  453. qDebug("VSTPluginMain(%p)", callback);
  454. using namespace CarlaBackend;
  455. CarlaEngineVst* engine = new CarlaEngineVst(callback);
  456. return engine->getEffect();
  457. }
  458. #endif // CARLA_ENGINE_VST