ExamplePluginCVPort.cpp (8494B)
1 /* 2 * DISTRHO Plugin Framework (DPF) 3 * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> 4 * Copyright (C) 2020 Takamitsu Endo 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any purpose with 7 * or without fee is hereby granted, provided that the above copyright notice and this 8 * permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD 11 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN 12 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 14 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "DistrhoPlugin.hpp" 19 20 START_NAMESPACE_DISTRHO 21 22 // ----------------------------------------------------------------------------------------------------------- 23 24 static constexpr const float kMaxHoldTime = 1.0f; 25 26 /** 27 Simple plugin to demonstrate how to modify input/output port type in DPF. 28 The plugin outputs sample & hold (S&H) value of input signal. 29 User can specify hold time via parameter and/or Hold Time CV port. 30 */ 31 class ExamplePluginCVPort : public Plugin 32 { 33 public: 34 ExamplePluginCVPort() 35 : Plugin(1, 0, 0), // 1 parameters, 0 programs, 0 states 36 counter(0), 37 holdTime(0.0f), 38 holdValue(0.0f), 39 sampleRate(getSampleRate()) {} 40 41 protected: 42 /* -------------------------------------------------------------------------------------------------------- 43 * Information */ 44 45 /** 46 Get the plugin label. 47 A plugin label follows the same rules as Parameter::symbol, with the exception that it can start with numbers. 48 */ 49 const char* getLabel() const override 50 { 51 return "CVPort"; 52 } 53 54 /** 55 Get an extensive comment/description about the plugin. 56 */ 57 const char* getDescription() const override 58 { 59 return "Simple plugin with CVPort.\nThe plugin does sample & hold processing."; 60 } 61 62 /** 63 Get the plugin author/maker. 64 */ 65 const char* getMaker() const override 66 { 67 return "DISTRHO"; 68 } 69 70 /** 71 Get the plugin homepage. 72 */ 73 const char* getHomePage() const override 74 { 75 return "https://github.com/DISTRHO/DPF"; 76 } 77 78 /** 79 Get the plugin license name (a single line of text). 80 For commercial plugins this should return some short copyright information. 81 */ 82 const char* getLicense() const override 83 { 84 return "ISC"; 85 } 86 87 /** 88 Get the plugin version, in hexadecimal. 89 */ 90 uint32_t getVersion() const override 91 { 92 return d_version(1, 0, 0); 93 } 94 95 /** 96 Get the plugin unique Id. 97 This value is used by LADSPA, DSSI and VST plugin formats. 98 */ 99 int64_t getUniqueId() const override 100 { 101 return d_cconst('d', 'C', 'V', 'P'); 102 } 103 104 /* -------------------------------------------------------------------------------------------------------- 105 * Init */ 106 107 /** 108 Initialize the audio port @a index.@n 109 This function will be called once, shortly after the plugin is created. 110 */ 111 void initAudioPort(bool input, uint32_t index, AudioPort& port) override 112 { 113 /** 114 Note that index is independent for input and output. 115 In other words, input port index starts from 0 and output port index also starts from 0. 116 */ 117 if (input) 118 { 119 switch (index) 120 { 121 case 0: 122 // Audio port doesn't need to specify port.hints. 123 port.name = "Audio Input"; 124 port.symbol = "audio_in"; 125 return; 126 case 1: 127 port.hints = kAudioPortIsCV; 128 port.name = "Hold Time"; 129 port.symbol = "hold_time"; 130 return; 131 } 132 // Add more conditions here when increasing DISTRHO_PLUGIN_NUM_INPUTS. 133 } 134 else 135 { 136 switch (index) 137 { 138 case 0: 139 port.hints = kAudioPortIsCV; 140 port.name = "CV Output"; 141 port.symbol = "cv_out"; 142 return; 143 } 144 // Add more conditions here when increasing DISTRHO_PLUGIN_NUM_OUTPUTS. 145 } 146 147 // It shouldn't reach here, but just in case if index is greater than 0. 148 Plugin::initAudioPort(input, index, port); 149 } 150 151 /** 152 Initialize the parameter @a index. 153 This function will be called once, shortly after the plugin is created. 154 */ 155 void initParameter(uint32_t index, Parameter& parameter) override 156 { 157 if (index != 0) 158 return; 159 160 parameter.name = "Hold Time"; 161 parameter.symbol = "hold_time"; 162 parameter.hints = kParameterIsAutomatable|kParameterIsLogarithmic; 163 parameter.ranges.min = 0.0f; 164 parameter.ranges.max = kMaxHoldTime; 165 parameter.ranges.def = 0.1f; 166 } 167 168 /* -------------------------------------------------------------------------------------------------------- 169 * Internal data */ 170 171 /** 172 Get the current value of a parameter. 173 */ 174 float getParameterValue(uint32_t index) const override 175 { 176 if (index != 0) 177 return 0.0f; 178 179 return holdTime; 180 } 181 182 /** 183 Change a parameter value. 184 */ 185 void setParameterValue(uint32_t index, float value) override 186 { 187 if (index != 0) 188 return; 189 190 holdTime = value; 191 counter = uint32_t(holdTime * sampleRate); 192 } 193 194 /* -------------------------------------------------------------------------------------------------------- 195 * Process */ 196 197 /** 198 Run/process function for plugins without MIDI input. 199 */ 200 void run(const float** inputs, float** outputs, uint32_t frames) override 201 { 202 float cv, time; 203 204 /** 205 - inputs[0] is input audio port. 206 - inputs[1] is hold time CV port. 207 - outputs[0] is output CV port. 208 */ 209 const float* const audioIn = inputs[0]; 210 const float* const holdCV = inputs[1]; 211 float* const cvOut = outputs[0]; 212 213 for (uint32_t i = 0; i < frames; ++i) 214 { 215 if (counter == 0) 216 { 217 cv = holdCV[i] > 0.0f ? holdCV[i] : 0.0f; 218 219 time = holdTime + cv; 220 if (time > kMaxHoldTime) 221 time = kMaxHoldTime; 222 223 counter = static_cast<uint32_t>(time * sampleRate + 0.5f); 224 225 holdValue = audioIn[i]; // Refresh hold value. 226 } 227 else 228 { 229 --counter; 230 } 231 232 cvOut[i] = holdValue; 233 } 234 } 235 236 /* -------------------------------------------------------------------------------------------------------- 237 * Callbacks (optional) */ 238 239 /** 240 Optional callback to inform the plugin about a sample rate change.@n 241 This function will only be called when the plugin is deactivated. 242 */ 243 void sampleRateChanged(double newSampleRate) override 244 { 245 sampleRate = newSampleRate; 246 counter = static_cast<uint32_t>(holdTime * sampleRate + 0.5f); 247 } 248 249 // ------------------------------------------------------------------------------------------------------- 250 251 private: 252 uint32_t counter; // Hold time in samples. Used to count hold time. 253 float holdTime; // Hold time in seconds. 254 float holdValue; 255 float sampleRate; 256 257 /** 258 Set our plugin class as non-copyable and add a leak detector just in case. 259 */ 260 DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExamplePluginCVPort) 261 }; 262 263 /* ------------------------------------------------------------------------------------------------------------ 264 * Plugin entry point, called by DPF to create a new plugin instance. */ 265 266 Plugin* createPlugin() 267 { 268 return new ExamplePluginCVPort(); 269 } 270 271 // ----------------------------------------------------------------------------------------------------------- 272 273 END_NAMESPACE_DISTRHO