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.

256 lines
7.0KB

  1. /*
  2. * Wobble Juice Plugin
  3. * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz
  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 "WobbleJuicePlugin.hpp"
  18. START_NAMESPACE_DISTRHO
  19. // -----------------------------------------------------------------------
  20. WobbleJuicePlugin::WobbleJuicePlugin()
  21. : Plugin(paramCount, 1, 0) // 1 program, 0 states
  22. {
  23. // set default values
  24. d_setProgram(0);
  25. // reset
  26. d_deactivate();
  27. }
  28. WobbleJuicePlugin::~WobbleJuicePlugin()
  29. {
  30. }
  31. // -----------------------------------------------------------------------
  32. // Init
  33. void WobbleJuicePlugin::d_initParameter(uint32_t index, Parameter& parameter)
  34. {
  35. switch (index)
  36. {
  37. case paramDivision:
  38. parameter.hints = PARAMETER_IS_AUTOMABLE|PARAMETER_IS_INTEGER;
  39. parameter.name = "Division";
  40. parameter.symbol = "div";
  41. parameter.unit = "times";
  42. parameter.ranges.def = 4.0f;
  43. parameter.ranges.min = 1.0f;
  44. parameter.ranges.max = 16.0f;
  45. break;
  46. case paramReso:
  47. parameter.hints = PARAMETER_IS_AUTOMABLE;
  48. parameter.name = "Resonance";
  49. parameter.symbol = "reso";
  50. parameter.unit = "amount";
  51. parameter.ranges.def = 0.1f;
  52. parameter.ranges.min = 0.0f;
  53. parameter.ranges.max = 0.2f;
  54. break;
  55. case paramRange:
  56. parameter.hints = PARAMETER_IS_AUTOMABLE;
  57. parameter.name = "Range";
  58. parameter.symbol = "rng";
  59. parameter.unit = "Hz";
  60. parameter.ranges.def = 16000.0f;
  61. parameter.ranges.min = 500.0f;
  62. parameter.ranges.max = 16000.0f;
  63. break;
  64. case paramPhase:
  65. parameter.hints = PARAMETER_IS_AUTOMABLE;
  66. parameter.name = "Phase";
  67. parameter.symbol = "phs";
  68. parameter.unit = "Deg";
  69. parameter.ranges.def = 0.0f;
  70. parameter.ranges.min = -1.0f;
  71. parameter.ranges.max = 1.0f;
  72. break;
  73. case paramWave:
  74. parameter.hints = PARAMETER_IS_AUTOMABLE;
  75. parameter.name = "Wave";
  76. parameter.symbol = "wav";
  77. parameter.unit = "";
  78. parameter.ranges.def = 2.0f;
  79. parameter.ranges.min = 1.0f;
  80. parameter.ranges.max = 4.0f;
  81. break;
  82. case paramDrive:
  83. parameter.hints = PARAMETER_IS_AUTOMABLE;
  84. parameter.name = "Drive";
  85. parameter.symbol = "drv";
  86. parameter.unit = "amount";
  87. parameter.ranges.def = 0.1f;
  88. parameter.ranges.min = 0.0f;
  89. parameter.ranges.max = 1.0f;
  90. break;
  91. }
  92. }
  93. void WobbleJuicePlugin::d_initProgramName(uint32_t index, d_string& programName)
  94. {
  95. if (index != 0)
  96. return;
  97. programName = "Default";
  98. }
  99. // -----------------------------------------------------------------------
  100. // Internal data
  101. float WobbleJuicePlugin::d_getParameterValue(uint32_t index) const
  102. {
  103. switch (index)
  104. {
  105. case paramDivision:
  106. return division;
  107. case paramReso:
  108. return reso;
  109. case paramRange:
  110. return range;
  111. case paramPhase:
  112. return phase;
  113. case paramWave:
  114. return wave;
  115. case paramDrive:
  116. return drive;
  117. default:
  118. return 0.0f;
  119. }
  120. }
  121. void WobbleJuicePlugin::d_setParameterValue(uint32_t index, float value)
  122. {
  123. switch (index)
  124. {
  125. case paramDivision:
  126. division = value;
  127. break;
  128. case paramReso:
  129. reso = value;
  130. break;
  131. case paramRange:
  132. range = value;
  133. break;
  134. case paramPhase:
  135. phase = value;
  136. break;
  137. case paramWave:
  138. wave = value;
  139. break;
  140. case paramDrive:
  141. drive = value;
  142. break;
  143. }
  144. }
  145. void WobbleJuicePlugin::d_setProgram(uint32_t index)
  146. {
  147. if (index != 0)
  148. return;
  149. /* Default parameter values */
  150. division = 4.0f;
  151. reso = 0.1f;
  152. range = 16000.0f;
  153. phase = 0.0f;
  154. wave = 2.0f;
  155. drive = 0.5f;
  156. /* Default variable values */
  157. bar=tick=tickOffset=percentage=phaseOffset=currentPhaseL=0;
  158. currentPhaseR=posL=posR=cutoffL=cutoffR=0;
  159. waveType = 2;
  160. /* reset filter values */
  161. d_activate();
  162. }
  163. // -----------------------------------------------------------------------
  164. // Process
  165. void WobbleJuicePlugin::d_activate()
  166. {
  167. sinePos = 0;
  168. }
  169. void WobbleJuicePlugin::d_deactivate()
  170. {
  171. // all values to zero
  172. }
  173. void WobbleJuicePlugin::d_run(float** inputs, float** outputs, uint32_t frames)
  174. {
  175. //fetch the timepos struct from host;
  176. const TimePos& time = d_getTimePos();
  177. /* sample count for one bar */
  178. bar = ((120.0/(time.bbt.valid ? time.bbt.beatsPerMinute : 120.0))*(d_getSampleRate())); //ONE, two, three, four
  179. tick = bar/(std::round(division)); //size of one target wob
  180. phaseOffset = phase*M_PI; //2pi = 1 whole cycle
  181. if (time.playing)
  182. {
  183. /* if rolling then sync to timepos */
  184. tickOffset = time.frame-std::floor(time.frame/tick)*tick; //how much after last tick
  185. if (tickOffset!=0) {
  186. //TODO: why do we need this??
  187. percentage = tickOffset/tick;
  188. } else {
  189. percentage = 0;
  190. }
  191. sinePos = (M_PI*2)*percentage;
  192. if (sinePos>2*M_PI) {
  193. //TODO: can this ever happen??
  194. sinePos = 0;
  195. }
  196. }
  197. else
  198. {
  199. /* else just keep on wobblin' */
  200. sinePos += (M_PI)/(tick/2000); //wtf, but works
  201. if (sinePos>2*M_PI) {
  202. sinePos = 0;
  203. }
  204. }
  205. /* phase of 0..1 filter = 500..16k */
  206. currentPhaseL = getBlendedPhase(sinePos+phaseOffset, wave);
  207. currentPhaseR = getBlendedPhase(sinePos-phaseOffset, wave);
  208. /* logarithmic */
  209. cutoffL = std::exp((std::log(range)-std::log(500))*currentPhaseL+std::log(500));
  210. cutoffR = std::exp((std::log(range)-std::log(500))*currentPhaseR+std::log(500));
  211. //output filtered signal
  212. filterL.recalc(cutoffL, reso*4, d_getSampleRate(), drive);
  213. filterR.recalc(cutoffR, reso*4, d_getSampleRate(), drive);
  214. filterL.process(frames, inputs[0], outputs[0]);
  215. filterR.process(frames, inputs[1], outputs[1]);
  216. }
  217. // -----------------------------------------------------------------------
  218. Plugin* createPlugin()
  219. {
  220. return new WobbleJuicePlugin();
  221. }
  222. // -----------------------------------------------------------------------
  223. END_NAMESPACE_DISTRHO