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.

324 lines
8.4KB

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