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.

329 lines
8.6KB

  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2012-2019 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 "CarlaNative.h"
  18. #include "CarlaDefines.h"
  19. #include "CarlaMIDI.h"
  20. #include <math.h>
  21. #include <stdlib.h>
  22. // -----------------------------------------------------------------------
  23. typedef enum {
  24. PARAM_MODE = 0,
  25. PARAM_SPEED,
  26. PARAM_MULTIPLIER,
  27. PARAM_BASE_START,
  28. PARAM_LFO_OUT,
  29. PARAM_COUNT
  30. } LfoParams;
  31. typedef struct {
  32. const NativeHostDescriptor* host;
  33. int mode;
  34. double speed;
  35. float multiplier;
  36. float baseStart;
  37. float value;
  38. } LfoHandle;
  39. // -----------------------------------------------------------------------
  40. static NativePluginHandle lfo_instantiate(const NativeHostDescriptor* host)
  41. {
  42. LfoHandle* const handle = (LfoHandle*)malloc(sizeof(LfoHandle));
  43. if (handle == NULL)
  44. return NULL;
  45. handle->host = host;
  46. handle->mode = 1;
  47. handle->speed = 1.0f;
  48. handle->multiplier = 1.0f;
  49. handle->baseStart = 0.0f;
  50. handle->value = 0.0f;
  51. return handle;
  52. }
  53. #define handlePtr ((LfoHandle*)handle)
  54. static void lfo_cleanup(NativePluginHandle handle)
  55. {
  56. free(handlePtr);
  57. }
  58. static uint32_t lfo_get_parameter_count(NativePluginHandle handle)
  59. {
  60. return PARAM_COUNT;
  61. // unused
  62. (void)handle;
  63. }
  64. static const NativeParameter* lfo_get_parameter_info(NativePluginHandle handle, uint32_t index)
  65. {
  66. if (index > PARAM_COUNT)
  67. return NULL;
  68. static NativeParameter param;
  69. static NativeParameterScalePoint paramModes[5];
  70. param.hints = NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_AUTOMABLE;
  71. param.scalePointCount = 0;
  72. param.scalePoints = NULL;
  73. paramModes[0].label = "Triangle";
  74. paramModes[1].label = "Sawtooth";
  75. paramModes[2].label = "Sawtooth (inverted)";
  76. paramModes[3].label = "Sine (TODO)";
  77. paramModes[4].label = "Square";
  78. paramModes[0].value = 1.0f;
  79. paramModes[1].value = 2.0f;
  80. paramModes[2].value = 3.0f;
  81. paramModes[3].value = 4.0f;
  82. paramModes[4].value = 5.0f;
  83. switch (index)
  84. {
  85. case PARAM_MODE:
  86. param.name = "Mode";
  87. param.unit = NULL;
  88. param.hints |= NATIVE_PARAMETER_IS_INTEGER|NATIVE_PARAMETER_USES_SCALEPOINTS;
  89. param.ranges.def = 1.0f;
  90. param.ranges.min = 1.0f;
  91. param.ranges.max = 5.0f;
  92. param.ranges.step = 1.0f;
  93. param.ranges.stepSmall = 1.0f;
  94. param.ranges.stepLarge = 1.0f;
  95. param.scalePointCount = 5;
  96. param.scalePoints = paramModes;
  97. break;
  98. case PARAM_SPEED:
  99. param.name = "Speed";
  100. param.unit = "(coef)";
  101. param.ranges.def = 1.0f;
  102. param.ranges.min = 0.01f;
  103. param.ranges.max = 32.0f;
  104. param.ranges.step = 0.25f;
  105. param.ranges.stepSmall = 0.1f;
  106. param.ranges.stepLarge = 0.5f;
  107. break;
  108. case PARAM_MULTIPLIER:
  109. param.name = "Multiplier";
  110. param.unit = "(coef)";
  111. param.ranges.def = 1.0f;
  112. param.ranges.min = 0.01f;
  113. param.ranges.max = 2.0f;
  114. param.ranges.step = 0.01f;
  115. param.ranges.stepSmall = 0.0001f;
  116. param.ranges.stepLarge = 0.1f;
  117. break;
  118. case PARAM_BASE_START:
  119. param.name = "Start value";
  120. param.unit = NULL;
  121. param.ranges.def = 0.0f;
  122. param.ranges.min = -1.0f;
  123. param.ranges.max = 1.0f;
  124. param.ranges.step = 0.01f;
  125. param.ranges.stepSmall = 0.0001f;
  126. param.ranges.stepLarge = 0.1f;
  127. break;
  128. case PARAM_LFO_OUT:
  129. param.name = "LFO Out";
  130. param.unit = NULL;
  131. param.hints |= NATIVE_PARAMETER_IS_OUTPUT;
  132. param.ranges.def = 0.0f;
  133. param.ranges.min = 0.0f;
  134. param.ranges.max = 1.0f;
  135. param.ranges.step = 0.01f;
  136. param.ranges.stepSmall = 0.0001f;
  137. param.ranges.stepLarge = 0.1f;
  138. break;
  139. }
  140. return &param;
  141. // unused
  142. (void)handle;
  143. }
  144. static float lfo_get_parameter_value(NativePluginHandle handle, uint32_t index)
  145. {
  146. switch (index)
  147. {
  148. case PARAM_MODE:
  149. return (float)handlePtr->mode;
  150. case PARAM_SPEED:
  151. return (float)handlePtr->speed;
  152. case PARAM_MULTIPLIER:
  153. return handlePtr->multiplier;
  154. case PARAM_BASE_START:
  155. return handlePtr->baseStart;
  156. case PARAM_LFO_OUT:
  157. return handlePtr->value;
  158. default:
  159. return 0.0f;
  160. }
  161. }
  162. static void lfo_set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  163. {
  164. switch (index)
  165. {
  166. case PARAM_MODE:
  167. handlePtr->mode = (int)value;
  168. break;
  169. case PARAM_SPEED:
  170. handlePtr->speed = value;
  171. break;
  172. case PARAM_MULTIPLIER:
  173. handlePtr->multiplier = value;
  174. break;
  175. case PARAM_BASE_START:
  176. handlePtr->baseStart = value;
  177. break;
  178. case PARAM_LFO_OUT:
  179. handlePtr->value = value;
  180. break;
  181. }
  182. }
  183. static void lfo_process(NativePluginHandle handle,
  184. const float** inBuffer, float** outBuffer, uint32_t frames,
  185. const NativeMidiEvent* midiEvents, uint32_t midiEventCount)
  186. {
  187. const NativeHostDescriptor* const host = handlePtr->host;
  188. const NativeTimeInfo* const timeInfo = host->get_time_info(host->handle);
  189. if (! timeInfo->playing)
  190. return;
  191. const double bpm = timeInfo->bbt.valid ? timeInfo->bbt.beatsPerMinute : 120.0;
  192. const double sampleRate = host->get_sample_rate(host->handle);
  193. const double speedRate = handlePtr->speed/(bpm/60.0/sampleRate);
  194. const uint speedRatei = (uint)speedRate;
  195. double value = 0.0;
  196. switch (handlePtr->mode)
  197. {
  198. case 1: // Triangle
  199. value = fabs(1.0-(double)(timeInfo->frame % speedRatei)/(speedRate/2.0));
  200. break;
  201. case 2: // Sawtooth
  202. value = (double)(timeInfo->frame % speedRatei)/speedRate;
  203. break;
  204. case 3: // Sawtooth (inverted)
  205. value = 1.0 - (double)(timeInfo->frame % speedRatei)/speedRate;
  206. break;
  207. case 4: // Sine -- TODO!
  208. value = 0.0;
  209. break;
  210. case 5: // Square
  211. value = (timeInfo->frame % speedRatei <= speedRatei/2) ? 1.0 : 0.0;
  212. break;
  213. }
  214. value *= (double)handlePtr->multiplier;
  215. value += (double)handlePtr->baseStart;
  216. if (value <= 0.0)
  217. handlePtr->value = 0.0f;
  218. else if (value >= 1.0)
  219. handlePtr->value = 1.0f;
  220. else
  221. handlePtr->value = (float)value;
  222. return;
  223. // unused
  224. (void)inBuffer;
  225. (void)outBuffer;
  226. (void)frames;
  227. (void)midiEvents;
  228. (void)midiEventCount;
  229. }
  230. #undef handlePtr
  231. // -----------------------------------------------------------------------
  232. static const NativePluginDescriptor lfoDesc = {
  233. .category = NATIVE_PLUGIN_CATEGORY_UTILITY,
  234. .hints = NATIVE_PLUGIN_IS_RTSAFE,
  235. .supports = NATIVE_PLUGIN_SUPPORTS_NOTHING,
  236. .audioIns = 0,
  237. .audioOuts = 0,
  238. .cvIns = 0,
  239. .cvOuts = 0,
  240. .midiIns = 0,
  241. .midiOuts = 0,
  242. .paramIns = PARAM_COUNT-1,
  243. .paramOuts = 1,
  244. .name = "LFO",
  245. .label = "lfo",
  246. .maker = "falkTX",
  247. .copyright = "GNU GPL v2+",
  248. .instantiate = lfo_instantiate,
  249. .cleanup = lfo_cleanup,
  250. .get_parameter_count = lfo_get_parameter_count,
  251. .get_parameter_info = lfo_get_parameter_info,
  252. .get_parameter_value = lfo_get_parameter_value,
  253. .get_midi_program_count = NULL,
  254. .get_midi_program_info = NULL,
  255. .set_parameter_value = lfo_set_parameter_value,
  256. .set_midi_program = NULL,
  257. .set_custom_data = NULL,
  258. .ui_show = NULL,
  259. .ui_idle = NULL,
  260. .ui_set_parameter_value = NULL,
  261. .ui_set_midi_program = NULL,
  262. .ui_set_custom_data = NULL,
  263. .activate = NULL,
  264. .deactivate = NULL,
  265. .process = lfo_process,
  266. .get_state = NULL,
  267. .set_state = NULL,
  268. .dispatcher = NULL,
  269. .render_inline_display = NULL
  270. };
  271. // -----------------------------------------------------------------------
  272. void carla_register_native_plugin_lfo(void);
  273. void carla_register_native_plugin_lfo(void)
  274. {
  275. carla_register_native_plugin(&lfoDesc);
  276. }
  277. // -----------------------------------------------------------------------