diff --git a/examples/CVPort/DistrhoPluginInfo.h b/examples/CVPort/DistrhoPluginInfo.h index 26a50e75..8e6b778a 100644 --- a/examples/CVPort/DistrhoPluginInfo.h +++ b/examples/CVPort/DistrhoPluginInfo.h @@ -21,8 +21,8 @@ #define DISTRHO_PLUGIN_NAME "CVPort" #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/CVPort" -#define DISTRHO_PLUGIN_IS_RT_SAFE 1 -#define DISTRHO_PLUGIN_NUM_INPUTS 1 -#define DISTRHO_PLUGIN_NUM_OUTPUTS 1 +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 +#define DISTRHO_PLUGIN_NUM_INPUTS 2 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 1 #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED diff --git a/examples/CVPort/ExamplePluginCVPort.cpp b/examples/CVPort/ExamplePluginCVPort.cpp index 3d68e1e2..fa44f764 100644 --- a/examples/CVPort/ExamplePluginCVPort.cpp +++ b/examples/CVPort/ExamplePluginCVPort.cpp @@ -21,14 +21,15 @@ START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------------------------------------------- /** - Simple plugin to demonstrate parameter usage (including UI). - The plugin will be treated as an effect, but it will not change the host audio. + Simple plugin to demonstrate how to modify input/output port type in DPF. + The plugin outputs sample & hold (S&H) value of input signal. + User can specify hold time via parameter and/or Hold Time CV port. */ -class ExamplePluginParameters : public Plugin +class ExamplePluginCVPort : public Plugin { public: - ExamplePluginParameters() - : Plugin(0, 0, 0) {} // 0 parameters, 0 programs, 0 states + ExamplePluginCVPort() + : Plugin(1, 0, 0) {} // 1 parameters, 0 programs, 0 states protected: /* -------------------------------------------------------------------------------------------------------- @@ -49,7 +50,7 @@ protected: const char* getDescription() const override { return "Simple plugin with CVPort.\n\ -The plugin will be treated as an effect, signal will bypassed."; +The plugin does sample & hold processing."; } /** @@ -110,9 +111,15 @@ The plugin will be treated as an effect, signal will bypassed."; if (input) { if (index == 0) { + // Audio port doesn't need to specify port.hints. + port.name = "Audio Input"; + port.symbol = "audio_in"; + return; + } + else if (index == 1) { port.hints = kAudioPortIsCV; - port.name = "CV Input"; - port.symbol = "cv_in"; + port.name = "Hold Time"; + port.symbol = "hold_time"; return; } // Add more condition here when increasing DISTRHO_PLUGIN_NUM_INPUTS. @@ -133,13 +140,44 @@ The plugin will be treated as an effect, signal will bypassed."; */ Plugin::initAudioPort(input, index, port); } + + /** + Initialize the parameter @a index. + This function will be called once, shortly after the plugin is created. + */ + void initParameter(uint32_t index, Parameter& parameter) override + { + if (index != 0) return; + + parameter.name = "Hold Time"; + parameter.symbol = "hold_time"; + parameter.hints = kParameterIsAutomable|kParameterIsLogarithmic; + parameter.ranges.min = 0.0f; + parameter.ranges.max = maxHoldTime; + parameter.ranges.def = 0.1f; + } /* -------------------------------------------------------------------------------------------------------- - * Init and Internal data, unused in this plugin */ + * Internal data */ + + /** + Get the current value of a parameter. + */ + inline float getParameterValue(uint32_t index) const override + { + return index == 0 ? holdTime : 0.0f; + } - void initParameter(uint32_t, Parameter&) override {} - float getParameterValue(uint32_t) const override { return 0.0f;} - void setParameterValue(uint32_t, float) override {} + /** + Change a parameter value. + */ + void setParameterValue(uint32_t index, float value) override + { + if (index != 0) return; + + holdTime = value; + counter = uint32_t(holdTime * sampleRate); + } /* -------------------------------------------------------------------------------------------------------- * Process */ @@ -150,21 +188,42 @@ The plugin will be treated as an effect, signal will bypassed."; void run(const float** inputs, float** outputs, uint32_t frames) override { /** - This plugin does nothing, it just demonstrates CVPort usage. - So here we directly copy inputs over outputs, leaving the audio untouched. - We need to be careful in case the host re-uses the same buffer for both ins and outs. + - inputs[0] is input audio port. + - inputs[1] is hold time CV port. + - outputs[0] is output CV port. */ - if (outputs[0] != inputs[0]) - std::memcpy(outputs[0], inputs[0], sizeof(float)*frames); + for (uint32_t i = 0; i < frames; ++i) { + if (counter == 0) { + float cv = inputs[1][i] > 0.0f ? inputs[1][i] : 0.0f; + + float time = holdTime + cv; + if (time > maxHoldTime) + time = maxHoldTime; + + counter = uint32_t(time * sampleRate); + + holdValue = inputs[0][i]; // Refresh hold value. + } else { + --counter; + } + outputs[0][i] = holdValue; + } } // ------------------------------------------------------------------------------------------------------- private: + const float maxHoldTime = 1.0f; + + float sampleRate = 44100.0f; + uint32_t counter = 0; // Hold time in samples. Used to count hold time. + float holdTime = 0.0f; // Hold time in seconds. + float holdValue = 0.0f; + /** Set our plugin class as non-copyable and add a leak detector just in case. */ - DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExamplePluginParameters) + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExamplePluginCVPort) }; /* ------------------------------------------------------------------------------------------------------------ @@ -172,7 +231,7 @@ private: Plugin* createPlugin() { - return new ExamplePluginParameters(); + return new ExamplePluginCVPort(); } // ----------------------------------------------------------------------------------------------------------- diff --git a/examples/CVPort/README.md b/examples/CVPort/README.md index 3f8f566c..011f20c9 100644 --- a/examples/CVPort/README.md +++ b/examples/CVPort/README.md @@ -1,6 +1,13 @@ # CVPort example This example will show how to modify input/output port type in DPF.
-The plugin will not do any audio processing.
- Take a look at `initAudioPort()` method.
+ +The plugin does sample & hold (S&H) processing.
+3 I/O ports are specified.
+ +- Input audio port. +- Input CV port to modify Hold Time. +- Output CV port. + +The plugin also has a Hold Time parameter. It mixes CV value and parameter value.