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.

393 lines
10KB

  1. /*
  2. * Carla Internal Plugins
  3. * Copyright (C) 2012-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 "daz/daz-plugin.h"
  18. #include "CarlaDefines.h"
  19. #include "CarlaMIDI.h"
  20. #include <math.h>
  21. #include <stdlib.h>
  22. // -----------------------------------------------------------------------
  23. // Implemented by Carla
  24. extern void carla_register_daz_plugin(const PluginDescriptor* desc);
  25. // -----------------------------------------------------------------------
  26. typedef enum {
  27. PARAM_MODE = 0,
  28. PARAM_SPEED,
  29. PARAM_MULTIPLIER,
  30. PARAM_BASE_START,
  31. PARAM_LFO_OUT,
  32. PARAM_COUNT
  33. } LfoParams;
  34. typedef struct {
  35. // host struct
  36. const PluginHostDescriptor* host;
  37. // params
  38. int mode;
  39. double speed;
  40. float multiplier;
  41. float baseStart;
  42. float value;
  43. // extra
  44. bool firstRun;
  45. mapped_value_t evTypeParam;
  46. mapped_value_t evTypeTime;
  47. } LfoHandle;
  48. // -----------------------------------------------------------------------
  49. static const char* lfo_metadata[] = {
  50. "api", "1", // FIXME: should be a macro
  51. "features", PLUGIN_FEATURE_BUFFER_SIZE_CHANGES PLUGIN_FEATURE_SAMPLE_RATE_CHANGES PLUGIN_FEATURE_TIME PLUGIN_FEATURE_WRITE_EVENT DAZ_TERMINATOR,
  52. "audioIns", "0",
  53. "audioOuts", "0",
  54. "midiIns", "0",
  55. "midiOuts", "0",
  56. "paramIns", "4",
  57. "paramOuts", "1",
  58. "author", "falkTX",
  59. "name", "LFO",
  60. "label", "lfo",
  61. "copyright", "GNU GPL v2+",
  62. "version", "1.0.0",
  63. NULL
  64. };
  65. // -----------------------------------------------------------------------
  66. static PluginHandle lfo_instantiate(const PluginHostDescriptor* host)
  67. {
  68. LfoHandle* const handle = (LfoHandle*)malloc(sizeof(LfoHandle));
  69. if (handle == NULL)
  70. return NULL;
  71. handle->host = host;
  72. handle->mode = 1;
  73. handle->speed = 1.0f;
  74. handle->multiplier = 1.0f;
  75. handle->baseStart = 0.0f;
  76. handle->value = 0.0f;
  77. handle->firstRun = true;
  78. handle->evTypeParam = host->map_value(host->handle, EVENT_TYPE_PARAMETER);
  79. handle->evTypeTime = host->map_value(host->handle, EVENT_TYPE_TIME);
  80. return handle;
  81. }
  82. // -----------------------------------------------------------------------
  83. #define handlePtr ((LfoHandle*)handle)
  84. static void lfo_cleanup(PluginHandle handle)
  85. {
  86. free(handlePtr);
  87. }
  88. static uint32_t lfo_get_parameter_count(PluginHandle handle)
  89. {
  90. return PARAM_COUNT;
  91. // unused
  92. (void)handle;
  93. }
  94. const Parameter* lfo_get_parameter_info(PluginHandle handle, uint32_t index)
  95. {
  96. if (index > PARAM_COUNT)
  97. return NULL;
  98. static Parameter param;
  99. static ParameterScalePoint paramModes[5];
  100. param.scalePointCount = 0;
  101. param.scalePoints = NULL;
  102. paramModes[0].label = "Triangle";
  103. paramModes[1].label = "Sawtooth";
  104. paramModes[2].label = "Sawtooth (inverted)";
  105. paramModes[3].label = "Sine (TODO)";
  106. paramModes[4].label = "Square";
  107. paramModes[0].value = 1.0f;
  108. paramModes[1].value = 2.0f;
  109. paramModes[2].value = 3.0f;
  110. paramModes[3].value = 4.0f;
  111. paramModes[4].value = 5.0f;
  112. switch (index)
  113. {
  114. case PARAM_MODE:
  115. param.name = "Mode";
  116. param.symbol = "mode";
  117. param.unit = NULL;
  118. param.hints = PARAMETER_IS_ENABLED PARAMETER_IS_INTEGER PARAMETER_USES_SCALEPOINTS;
  119. param.ranges.def = 1.0f;
  120. param.ranges.min = 1.0f;
  121. param.ranges.max = 5.0f;
  122. param.ranges.step = 1.0f;
  123. param.ranges.stepSmall = 1.0f;
  124. param.ranges.stepLarge = 1.0f;
  125. param.scalePointCount = 5;
  126. param.scalePoints = paramModes;
  127. break;
  128. case PARAM_SPEED:
  129. param.name = "Speed";
  130. param.symbol = "speed";
  131. param.unit = "(coef)";
  132. param.hints = PARAMETER_IS_ENABLED;
  133. param.ranges.def = 1.0f;
  134. param.ranges.min = 0.01f;
  135. param.ranges.max = 2.0f;
  136. param.ranges.step = 0.25f;
  137. param.ranges.stepSmall = 0.1f;
  138. param.ranges.stepLarge = 0.5f;
  139. break;
  140. case PARAM_MULTIPLIER:
  141. param.name = "Multiplier";
  142. param.symbol = "multi";
  143. param.unit = "(coef)";
  144. param.hints = PARAMETER_IS_ENABLED;
  145. param.ranges.def = 1.0f;
  146. param.ranges.min = 0.01f;
  147. param.ranges.max = 2.0f;
  148. param.ranges.step = 0.01f;
  149. param.ranges.stepSmall = 0.0001f;
  150. param.ranges.stepLarge = 0.1f;
  151. break;
  152. case PARAM_BASE_START:
  153. param.name = "Start value";
  154. param.symbol = "start";
  155. param.unit = NULL;
  156. param.hints = PARAMETER_IS_ENABLED;
  157. param.ranges.def = 0.0f;
  158. param.ranges.min = -1.0f;
  159. param.ranges.max = 1.0f;
  160. param.ranges.step = 0.01f;
  161. param.ranges.stepSmall = 0.0001f;
  162. param.ranges.stepLarge = 0.1f;
  163. break;
  164. case PARAM_LFO_OUT:
  165. param.name = "LFO Out";
  166. param.symbol = "out";
  167. param.unit = NULL;
  168. param.hints = PARAMETER_IS_ENABLED PARAMETER_IS_OUTPUT;
  169. param.ranges.def = 0.0f;
  170. param.ranges.min = 0.0f;
  171. param.ranges.max = 1.0f;
  172. param.ranges.step = 0.01f;
  173. param.ranges.stepSmall = 0.0001f;
  174. param.ranges.stepLarge = 0.1f;
  175. break;
  176. }
  177. return &param;
  178. // unused
  179. (void)handle;
  180. }
  181. static float lfo_get_parameter_value(PluginHandle handle, uint32_t index)
  182. {
  183. LfoHandle* const lfohandle = handlePtr;
  184. switch (index)
  185. {
  186. case PARAM_MODE:
  187. return (float)lfohandle->mode;
  188. case PARAM_SPEED:
  189. return (float)lfohandle->speed;
  190. case PARAM_MULTIPLIER:
  191. return lfohandle->multiplier;
  192. case PARAM_BASE_START:
  193. return lfohandle->baseStart;
  194. case PARAM_LFO_OUT:
  195. return lfohandle->value;
  196. default:
  197. return 0.0f;
  198. }
  199. }
  200. static void lfo_parameter_changed(LfoHandle* const lfohandle, uint32_t index, float value)
  201. {
  202. switch (index)
  203. {
  204. case PARAM_MODE:
  205. lfohandle->mode = (int)value;
  206. break;
  207. case PARAM_SPEED:
  208. lfohandle->speed = value;
  209. break;
  210. case PARAM_MULTIPLIER:
  211. lfohandle->multiplier = value;
  212. break;
  213. case PARAM_BASE_START:
  214. lfohandle->baseStart = value;
  215. break;
  216. }
  217. }
  218. static float lfo_calculate_value(LfoHandle* const lfohandle, const uint64_t frame, const double bpm, const double sampleRate)
  219. {
  220. double value;
  221. double speedRate = lfohandle->speed/(bpm/60.0/sampleRate);
  222. uint speedRatei = (uint)speedRate;
  223. switch (lfohandle->mode)
  224. {
  225. case 1: // Triangle
  226. value = fabs(1.0-(double)(frame % speedRatei)/(speedRate/2.0));
  227. break;
  228. case 2: // Sawtooth
  229. value = (double)(frame % speedRatei)/speedRate;
  230. break;
  231. case 3: // Sawtooth (inverted)
  232. value = 1.0 - (double)(frame % speedRatei)/speedRate;
  233. break;
  234. case 4: // Sine -- TODO!
  235. value = 0.0;
  236. break;
  237. case 5: // Square
  238. value = (frame % speedRatei <= speedRatei/2) ? 1.0 : 0.0;
  239. break;
  240. }
  241. value *= lfohandle->multiplier;
  242. value += lfohandle->baseStart;
  243. if (value <= 0.0)
  244. {
  245. lfohandle->value = 0.0f;
  246. return 0.0f;
  247. }
  248. else if (value >= 1.0)
  249. {
  250. lfohandle->value = 1.0f;
  251. return 1.0f;
  252. }
  253. else
  254. {
  255. lfohandle->value = (float)value;
  256. return lfohandle->value;
  257. }
  258. }
  259. static void lfo_activate(PluginHandle handle)
  260. {
  261. handlePtr->firstRun = true;
  262. }
  263. static void lfo_process(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, const Event* events, uint32_t eventCount)
  264. {
  265. LfoHandle* const lfohandle = handlePtr;
  266. const PluginHostDescriptor* const host = lfohandle->host;
  267. const TimeInfo* const timeInfo = host->get_time_info(host->handle);
  268. uint64_t frame = timeInfo->frame;
  269. double bpm = timeInfo->bbt.valid ? timeInfo->bbt.beatsPerMinute : 120.0;
  270. ParameterEvent event;
  271. event.e.type = lfohandle->evTypeParam;
  272. event.e.frame = 0;
  273. event.index = PARAM_LFO_OUT;
  274. if (lfohandle->firstRun)
  275. {
  276. lfohandle->firstRun = false;
  277. event.value = lfo_calculate_value(lfohandle, frame, bpm, host->sample_rate);
  278. host->write_event(host->handle, (const Event*)&event);
  279. }
  280. for (uint32_t i=0; i < eventCount; ++i)
  281. {
  282. const mapped_value_t valType = events[i].type;
  283. if (valType == lfohandle->evTypeParam)
  284. {
  285. const ParameterEvent* const paramEvent = (const ParameterEvent*)&events[i];
  286. lfo_parameter_changed(lfohandle, paramEvent->index, paramEvent->value);
  287. event.e.frame = paramEvent->e.frame;
  288. event.value = lfo_calculate_value(lfohandle, frame, bpm, host->sample_rate);
  289. host->write_event(host->handle, (const Event*)&event);
  290. }
  291. else if (valType == lfohandle->evTypeTime)
  292. {
  293. const TimeInfoEvent* const timeEvent = (const TimeInfoEvent*)&events[i];
  294. frame = timeEvent->frame;
  295. bpm = timeEvent->bbt.valid ? timeEvent->bbt.beatsPerMinute : 120.0;
  296. }
  297. }
  298. return;
  299. // unused
  300. (void)inBuffer;
  301. (void)outBuffer;
  302. (void)frames;
  303. }
  304. #undef handlePtr
  305. // -----------------------------------------------------------------------
  306. static const PluginDescriptor lfoDesc = {
  307. .metadata = lfo_metadata,
  308. .instantiate = lfo_instantiate,
  309. .cleanup = lfo_cleanup,
  310. .get_parameter_count = lfo_get_parameter_count,
  311. .get_parameter_info = lfo_get_parameter_info,
  312. .get_parameter_value = lfo_get_parameter_value,
  313. .get_parameter_text = NULL,
  314. .get_midi_program_count = NULL,
  315. .get_midi_program_info = NULL,
  316. .idle = NULL,
  317. .non_rt_event = NULL,
  318. .get_state = NULL,
  319. .set_state = NULL,
  320. .activate = lfo_activate,
  321. .deactivate = NULL,
  322. .process = lfo_process,
  323. .dispatcher = NULL
  324. };
  325. // -----------------------------------------------------------------------
  326. void carla_register_daz_plugin_lfo()
  327. {
  328. carla_register_daz_plugin(&lfoDesc);
  329. }
  330. // -----------------------------------------------------------------------