DPF Plugin examples
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.

299 lines
8.7KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "DistrhoPlugin.hpp"
  17. START_NAMESPACE_DISTRHO
  18. // -----------------------------------------------------------------------------------------------------------
  19. class ArtyFxPluginDucka : public Plugin
  20. {
  21. public:
  22. ArtyFxPluginDucka()
  23. : Plugin(4, 0, 0), // 4 parameters, 0 programs, 0 states
  24. // parameters init
  25. controlThreshold(0.25f),
  26. controlReduction(1.0f),
  27. controlReleaseTime(0.5f),
  28. controlSidechainAmp(0.0f),
  29. // filter state init
  30. w(10.0f / (d_getSampleRate() * 0.02)),
  31. a(0.07f),
  32. b(1.0f / (1.0f - a)),
  33. g1(0.0f),
  34. g2(0.0f),
  35. samplerate( d_getSampleRate() ),
  36. peakFrameCounter(0),
  37. peakCountDuration( samplerate / 4 ),
  38. currentTarget(0)
  39. {
  40. }
  41. protected:
  42. /* --------------------------------------------------------------------------------------------------------
  43. * Information */
  44. /**
  45. Get the plugin label.
  46. A plugin label follows the same rules as Parameter::symbol, with the exception that it can start with numbers.
  47. */
  48. const char* d_getLabel() const override
  49. {
  50. return "ducka";
  51. }
  52. /**
  53. Get the plugin author/maker.
  54. */
  55. const char* d_getMaker() const override
  56. {
  57. return "OpenAV Productions";
  58. }
  59. /**
  60. Get the plugin license name (a single line of text).
  61. */
  62. const char* d_getLicense() const override
  63. {
  64. return "ISC";
  65. }
  66. /**
  67. Get the plugin version, in hexadecimal.
  68. TODO format to be defined
  69. */
  70. uint32_t d_getVersion() const override
  71. {
  72. return 0x1000;
  73. }
  74. /**
  75. Get the plugin unique Id.
  76. This value is used by LADSPA, DSSI and VST plugin formats.
  77. */
  78. int64_t d_getUniqueId() const override
  79. {
  80. return d_cconst('O', 'V', 'd', 'k');
  81. }
  82. /* --------------------------------------------------------------------------------------------------------
  83. * Init */
  84. /**
  85. Initialize the parameter @a index.
  86. This function will be called once, shortly after the plugin is created.
  87. */
  88. void d_initParameter(uint32_t index, Parameter& parameter) override
  89. {
  90. parameter.hints = kParameterIsAutomable;
  91. parameter.ranges.min = 0.0f;
  92. parameter.ranges.max = 1.0f;
  93. switch (index)
  94. {
  95. case 0:
  96. parameter.name = "Threshold";
  97. parameter.symbol = "threshold";
  98. parameter.ranges.def = 0.25f;
  99. break;
  100. case 1:
  101. parameter.name = "Reduction";
  102. parameter.symbol = "reduction";
  103. parameter.ranges.def = 1.0f;
  104. break;
  105. case 2:
  106. parameter.name = "Release Time";
  107. parameter.symbol = "release_time";
  108. parameter.ranges.def = 0.5f;
  109. break;
  110. case 3:
  111. parameter.hints |= kParameterIsOutput;
  112. parameter.name = "Sidechain Amplitude";
  113. parameter.symbol = "sidechain_amp";
  114. parameter.ranges.def = 0.0f;
  115. break;
  116. }
  117. }
  118. /* --------------------------------------------------------------------------------------------------------
  119. * Internal data */
  120. /**
  121. Get the current value of a parameter.
  122. */
  123. float d_getParameterValue(uint32_t index) const override
  124. {
  125. switch (index)
  126. {
  127. case 0: return controlThreshold;
  128. case 1: return controlReduction;
  129. case 2: return controlReleaseTime;
  130. case 3: return controlSidechainAmp;
  131. }
  132. return 0.0f;
  133. }
  134. /**
  135. Change a parameter value.
  136. */
  137. void d_setParameterValue(uint32_t index, float value) override
  138. {
  139. switch (index)
  140. {
  141. case 0:
  142. controlThreshold = value;
  143. break;
  144. case 1:
  145. controlReduction = value;
  146. break;
  147. case 2:
  148. controlReleaseTime = value;
  149. break;
  150. }
  151. // outputs can't be changed by the host
  152. }
  153. /* --------------------------------------------------------------------------------------------------------
  154. * Process */
  155. /**
  156. Run/process function for plugins without MIDI input.
  157. */
  158. void d_run(const float** inputs, float** outputs, uint32_t frames) override
  159. {
  160. const float* inL = inputs[0];
  161. const float* inR = inputs[1];
  162. const float* side = inputs[2];
  163. float* outL = outputs[0];
  164. float* outR = outputs[1];
  165. const TimePosition& timePos(d_getTimePosition());
  166. if (timePos.bbt.valid)
  167. peakCountDuration = samplerate / ( timePos.bbt.beatsPerMinute / 60.0);
  168. else
  169. peakCountDuration = samplerate / 2.0f;
  170. /// analyse sidechain input for peak
  171. float sum = 0.f;
  172. for( uint32_t i = 0; i < frames; i++ )
  173. {
  174. if ( *side > 0.000001 )
  175. sum += *side++;
  176. else
  177. sum += -*side++;
  178. }
  179. currentTarget = 0.f;
  180. /// check for peak level (offset to avoid "always on" peak)
  181. if ( sum / frames > controlThreshold + 0.05 )
  182. {
  183. peakFrameCounter = peakCountDuration * controlReleaseTime;
  184. currentTarget = 1.f - controlReduction;
  185. }
  186. else if ( peakFrameCounter < 0 )
  187. {
  188. currentTarget = 1.f;
  189. }
  190. else
  191. {
  192. currentTarget = 1.f - controlReduction;
  193. }
  194. if ( currentTarget < 0.f )
  195. currentTarget = 0.f;
  196. peakFrameCounter -= frames;
  197. for( uint32_t i = 0; i < frames; i++ )
  198. {
  199. /// smoothing algo is a lowpass, to de-zip the fades
  200. /// x^^4 approximates linear volume increase for human ears
  201. g1 += w * ( std::pow ( currentTarget, 4.f ) - g1 - a * g2 - 1e-20f);
  202. g2 += w * (b * g1 - g2 + 1e-20f);
  203. float gain = g2;
  204. *outL++ = *inL++ * gain;
  205. *outR++ = *inR++ * gain;
  206. }
  207. /// update output value
  208. controlSidechainAmp = 1-currentTarget;
  209. }
  210. /* --------------------------------------------------------------------------------------------------------
  211. * Callbacks */
  212. /**
  213. Optional callback to inform the plugin about a sample rate change.
  214. This function will only be called when the plugin is deactivated.
  215. */
  216. void d_sampleRateChanged(double newSampleRate) override
  217. {
  218. // reinit filter
  219. w = 10.0f / (newSampleRate * 0.02);
  220. a = 0.07f;
  221. b = 1.0f / (1.0f - a);
  222. g1 = 0.0f;
  223. g2 = 0.0f;
  224. samplerate = newSampleRate;
  225. peakFrameCounter = 0;
  226. peakCountDuration = samplerate / 4;
  227. currentTarget = 0;
  228. }
  229. // -------------------------------------------------------------------------------------------------------
  230. private:
  231. /// control signals
  232. float controlThreshold;
  233. float controlReduction;
  234. float controlReleaseTime;
  235. float controlSidechainAmp;
  236. /// filter state
  237. float w, a, b, g1, g2;
  238. /// last peak history
  239. long samplerate;
  240. bool nowIsAPeak;
  241. long peakFrameCounter;
  242. /// nframes available for countdown
  243. long peakCountDuration;
  244. /// control output
  245. float currentTarget;
  246. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ArtyFxPluginDucka)
  247. };
  248. /* ------------------------------------------------------------------------------------------------------------
  249. * Plugin entry point, called by DPF to create a new plugin instance. */
  250. Plugin* createPlugin()
  251. {
  252. return new ArtyFxPluginDucka();
  253. }
  254. // -----------------------------------------------------------------------------------------------------------
  255. END_NAMESPACE_DISTRHO