DISTRHO Plugin Framework
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.

272 lines
8.1KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2022 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. /**
  20. Plugin that demonstrates the latency API in DPF.
  21. */
  22. class LatencyExamplePlugin : public Plugin
  23. {
  24. public:
  25. LatencyExamplePlugin()
  26. : Plugin(1, 0, 0), // 1 parameter
  27. fLatency(1.0f),
  28. fLatencyInFrames(0),
  29. fBuffer(nullptr),
  30. fBufferPos(0),
  31. fBufferSize(0)
  32. {
  33. // allocates buffer
  34. sampleRateChanged(getSampleRate());
  35. }
  36. ~LatencyExamplePlugin() override
  37. {
  38. delete[] fBuffer;
  39. }
  40. protected:
  41. /* --------------------------------------------------------------------------------------------------------
  42. * Information */
  43. /**
  44. Get the plugin label.
  45. This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters.
  46. */
  47. const char* getLabel() const override
  48. {
  49. return "Latency";
  50. }
  51. /**
  52. Get an extensive comment/description about the plugin.
  53. */
  54. const char* getDescription() const override
  55. {
  56. return "Plugin that demonstrates the latency API in DPF.";
  57. }
  58. /**
  59. Get the plugin author/maker.
  60. */
  61. const char* getMaker() const override
  62. {
  63. return "DISTRHO";
  64. }
  65. /**
  66. Get the plugin homepage.
  67. */
  68. const char* getHomePage() const override
  69. {
  70. return "https://github.com/DISTRHO/DPF";
  71. }
  72. /**
  73. Get the plugin license name (a single line of text).
  74. For commercial plugins this should return some short copyright information.
  75. */
  76. const char* getLicense() const override
  77. {
  78. return "ISC";
  79. }
  80. /**
  81. Get the plugin version, in hexadecimal.
  82. */
  83. uint32_t getVersion() const override
  84. {
  85. return d_version(1, 0, 0);
  86. }
  87. /**
  88. Get the plugin unique Id.
  89. This value is used by LADSPA, DSSI and VST plugin formats.
  90. */
  91. int64_t getUniqueId() const override
  92. {
  93. return d_cconst('d', 'L', 'a', 't');
  94. }
  95. /* --------------------------------------------------------------------------------------------------------
  96. * Init */
  97. /**
  98. Initialize the audio port @a index.@n
  99. This function will be called once, shortly after the plugin is created.
  100. */
  101. void initAudioPort(bool input, uint32_t index, AudioPort& port) override
  102. {
  103. // mark the (single) latency audio port as mono
  104. port.groupId = kPortGroupMono;
  105. // everything else is as default
  106. Plugin::initAudioPort(input, index, port);
  107. }
  108. /**
  109. Initialize the parameter @a index.
  110. This function will be called once, shortly after the plugin is created.
  111. */
  112. void initParameter(uint32_t index, Parameter& parameter) override
  113. {
  114. if (index != 0)
  115. return;
  116. parameter.hints = kParameterIsAutomatable;
  117. parameter.name = "Latency";
  118. parameter.symbol = "latency";
  119. parameter.unit = "s";
  120. parameter.ranges.def = 1.0f;
  121. parameter.ranges.min = 0.0f;
  122. parameter.ranges.max = 5.0f;
  123. }
  124. /* --------------------------------------------------------------------------------------------------------
  125. * Internal data */
  126. /**
  127. Get the current value of a parameter.
  128. The host may call this function from any context, including realtime processing.
  129. */
  130. float getParameterValue(uint32_t index) const override
  131. {
  132. if (index != 0)
  133. return 0.0f;
  134. return fLatency;
  135. }
  136. /**
  137. Change a parameter value.
  138. The host may call this function from any context, including realtime processing.
  139. When a parameter is marked as automatable, you must ensure no non-realtime operations are performed.
  140. @note This function will only be called for parameter inputs.
  141. */
  142. void setParameterValue(uint32_t index, float value) override
  143. {
  144. if (index != 0)
  145. return;
  146. fLatency = value;
  147. fLatencyInFrames = value*getSampleRate();
  148. setLatency(fLatencyInFrames);
  149. }
  150. /* --------------------------------------------------------------------------------------------------------
  151. * Audio/MIDI Processing */
  152. /**
  153. Activate this plugin.
  154. */
  155. void activate() override
  156. {
  157. fBufferPos = 0;
  158. std::memset(fBuffer, 0, sizeof(float)*fBufferSize);
  159. }
  160. /**
  161. Run/process function for plugins without MIDI input.
  162. @note Some parameters might be null if there are no audio inputs or outputs.
  163. */
  164. void run(const float** inputs, float** outputs, uint32_t frames) override
  165. {
  166. const float* const in = inputs[0];
  167. /* */ float* const out = outputs[0];
  168. if (fLatencyInFrames == 0)
  169. {
  170. if (out != in)
  171. std::memcpy(out, in, sizeof(float)*frames);
  172. return;
  173. }
  174. // Put the new audio in the buffer.
  175. std::memcpy(fBuffer+fBufferPos, in, sizeof(float)*frames);
  176. fBufferPos += frames;
  177. // buffer is not filled enough yet
  178. if (fBufferPos < fLatencyInFrames+frames)
  179. {
  180. // silence output
  181. std::memset(out, 0, sizeof(float)*frames);
  182. }
  183. // buffer is ready to copy
  184. else
  185. {
  186. // copy latency buffer to output
  187. const uint32_t readPos = fBufferPos-fLatencyInFrames-frames;
  188. std::memcpy(out, fBuffer+readPos, sizeof(float)*frames);
  189. // move latency buffer back by some frames
  190. std::memmove(fBuffer, fBuffer+frames, sizeof(float)*fBufferPos);
  191. fBufferPos -= frames;
  192. }
  193. }
  194. /* --------------------------------------------------------------------------------------------------------
  195. * Callbacks (optional) */
  196. /**
  197. Optional callback to inform the plugin about a sample rate change.
  198. This function will only be called when the plugin is deactivated.
  199. */
  200. void sampleRateChanged(double newSampleRate) override
  201. {
  202. fBufferSize = newSampleRate*6; // 6 seconds
  203. delete[] fBuffer;
  204. fBuffer = new float[fBufferSize];
  205. // buffer reset is done during activate()
  206. fLatencyInFrames = fLatency*newSampleRate;
  207. setLatency(fLatencyInFrames);
  208. }
  209. // -------------------------------------------------------------------------------------------------------
  210. private:
  211. // Parameters
  212. float fLatency;
  213. uint32_t fLatencyInFrames;
  214. // Buffer for previous audio, size depends on sample rate
  215. float* fBuffer;
  216. uint32_t fBufferPos, fBufferSize;
  217. /**
  218. Set our plugin class as non-copyable and add a leak detector just in case.
  219. */
  220. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LatencyExamplePlugin)
  221. };
  222. /* ------------------------------------------------------------------------------------------------------------
  223. * Plugin entry point, called by DPF to create a new plugin instance. */
  224. Plugin* createPlugin()
  225. {
  226. return new LatencyExamplePlugin();
  227. }
  228. // -----------------------------------------------------------------------------------------------------------
  229. END_NAMESPACE_DISTRHO