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.