AbstractFX.hpp (8803B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 AbstractFX.hpp - DPF Abstract Effect class 5 Copyright (C) 2015 Filipe Coelho 6 Author: Filipe Coelho 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of version 2 of the GNU General Public License 10 as published by the Free Software Foundation. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License (version 2 or later) for more details. 16 17 You should have received a copy of the GNU General Public License (version 2) 18 along with this program; if not, write to the Free Software Foundation, 19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 21 */ 22 23 #ifndef ZYNADDSUBFX_ABSTRACTFX_HPP_INCLUDED 24 #define ZYNADDSUBFX_ABSTRACTFX_HPP_INCLUDED 25 26 // DPF includes 27 #include "DistrhoPlugin.hpp" 28 29 // ZynAddSubFX includes 30 #include "Params/FilterParams.h" 31 #include "Effects/Effect.h" 32 #include "Misc/Allocator.h" 33 #include "zyn-version.h" 34 35 /* ------------------------------------------------------------------------------------------------------------ 36 * Abstract plugin class */ 37 38 template<class ZynFX> 39 class AbstractPluginFX : public Plugin 40 { 41 public: 42 AbstractPluginFX(const uint32_t params, const uint32_t programs) 43 : Plugin(params-2, programs, 0), 44 paramCount(params-2), // volume and pan handled by host 45 programCount(programs), 46 bufferSize(getBufferSize()), 47 sampleRate(getSampleRate()), 48 effect(nullptr), 49 efxoutl(nullptr), 50 efxoutr(nullptr) 51 { 52 efxoutl = new float[bufferSize]; 53 efxoutr = new float[bufferSize]; 54 filterpar = new zyn::FilterParams(); 55 std::memset(efxoutl, 0, sizeof(float)*bufferSize); 56 std::memset(efxoutr, 0, sizeof(float)*bufferSize); 57 58 doReinit(true); 59 } 60 61 ~AbstractPluginFX() override 62 { 63 delete[] efxoutl; 64 delete[] efxoutr; 65 delete effect; 66 delete filterpar; 67 } 68 69 protected: 70 /* -------------------------------------------------------------------------------------------------------- 71 * Information */ 72 73 /** 74 Get the plugin author/maker. 75 */ 76 const char* getMaker() const noexcept override 77 { 78 return "ZynAddSubFX Team"; 79 } 80 81 /** 82 Get the plugin homepage. 83 Optional, returns nothing by default. 84 */ 85 const char* getHomePage() const noexcept override 86 { 87 return "http://zynaddsubfx.sourceforge.net"; 88 } 89 90 /** 91 Get the plugin license (a single line of text or a URL). 92 */ 93 const char* getLicense() const noexcept override 94 { 95 return "GPL v2"; 96 } 97 98 /** 99 Get the plugin version, in hexadecimal. 100 */ 101 uint32_t getVersion() const noexcept override 102 { 103 return d_version(zyn::version.get_major(), 104 zyn::version.get_minor(), 105 zyn::version.get_revision()); 106 } 107 108 /* -------------------------------------------------------------------------------------------------------- 109 * Internal data */ 110 111 /** 112 Get the current value of a parameter. 113 The host may call this function from any context, including realtime processing. 114 */ 115 float getParameterValue(uint32_t index) const override 116 { 117 return static_cast<float>(effect->getpar(static_cast<int>(index+2))); 118 } 119 120 /** 121 Change a parameter value. 122 The host may call this function from any context, including realtime processing. 123 When a parameter is marked as automable, you must ensure no non-realtime operations are performed. 124 @note This function will only be called for parameter inputs. 125 */ 126 void setParameterValue(uint32_t index, float value) override 127 { 128 // make sure value is in bounds for uchar conversion 129 if (value < 0.0f) 130 value = 0.0f; 131 else if (value > 127.0f) 132 value = 127.0f; 133 134 // safely cast to int 135 const int ivalue = (int)(value+0.5f); 136 137 // ok! 138 effect->changepar(static_cast<int>(index+2), static_cast<uchar>(ivalue)); 139 } 140 141 /** 142 Load a program. 143 The host may call this function from any context, including realtime processing. 144 */ 145 void loadProgram(uint32_t index) override 146 { 147 effect->setpreset(static_cast<uchar>(index)); 148 149 // reset volume and pan 150 effect->changepar(0, 127); 151 effect->changepar(1, 64); 152 } 153 154 /* -------------------------------------------------------------------------------------------------------- 155 * Audio/MIDI Processing */ 156 157 /** 158 Activate this plugin. 159 */ 160 void activate() override 161 { 162 effect->cleanup(); 163 } 164 165 /** 166 Run/process function for plugins without MIDI input. 167 @note Some parameters might be null if there are no audio inputs or outputs. 168 */ 169 void run(const float** inputs, float** outputs, uint32_t frames) override 170 { 171 if (outputs[0] != inputs[0]) 172 copyWithMultiply(outputs[0], inputs[0], 0.5f, frames); 173 else 174 multiply(outputs[0], 0.5f, frames); 175 176 if (outputs[1] != inputs[1]) 177 copyWithMultiply(outputs[1], inputs[1], 0.5f, frames); 178 else 179 multiply(outputs[1], 0.5f, frames); 180 181 // FIXME: Make Zyn use const floats 182 effect->out(zyn::Stereo<float*>((float*)inputs[0], (float*)inputs[1])); 183 184 addWithMultiply(outputs[0], efxoutl, 0.5f, frames); 185 addWithMultiply(outputs[1], efxoutr, 0.5f, frames); 186 } 187 188 /* -------------------------------------------------------------------------------------------------------- 189 * Callbacks (optional) */ 190 191 /** 192 Optional callback to inform the plugin about a buffer size change. 193 This function will only be called when the plugin is deactivated. 194 @note This value is only a hint! 195 Hosts might call run() with a higher or lower number of frames. 196 */ 197 void bufferSizeChanged(uint32_t newBufferSize) override 198 { 199 if (bufferSize == newBufferSize) 200 return; 201 202 bufferSize = newBufferSize; 203 204 delete[] efxoutl; 205 delete[] efxoutr; 206 efxoutl = new float[bufferSize]; 207 efxoutr = new float[bufferSize]; 208 std::memset(efxoutl, 0, sizeof(float)*bufferSize); 209 std::memset(efxoutr, 0, sizeof(float)*bufferSize); 210 211 doReinit(false); 212 } 213 214 /** 215 Optional callback to inform the plugin about a sample rate change. 216 This function will only be called when the plugin is deactivated. 217 */ 218 void sampleRateChanged(double newSampleRate) override 219 { 220 if (sampleRate == newSampleRate) 221 return; 222 223 sampleRate = newSampleRate; 224 225 doReinit(false); 226 } 227 228 // ------------------------------------------------------------------------------------------------------- 229 230 private: 231 const uint32_t paramCount; 232 const uint32_t programCount; 233 234 uint32_t bufferSize; 235 double sampleRate; 236 237 zyn::Effect* effect; 238 float* efxoutl; 239 float* efxoutr; 240 zyn::FilterParams* filterpar; 241 242 zyn::AllocatorClass allocator; 243 244 void doReinit(const bool firstInit) 245 { 246 // save current param values before recreating effect 247 uchar params[paramCount]; 248 249 if (effect != nullptr) 250 { 251 for (int i=0, count=static_cast<int>(paramCount); i<count; ++i) 252 params[i] = effect->getpar(i+2); 253 254 delete effect; 255 } 256 257 zyn::EffectParams pars(allocator, false, efxoutl, efxoutr, 0, static_cast<uint>(sampleRate), static_cast<int>(bufferSize), filterpar); 258 effect = new ZynFX(pars); 259 260 if (firstInit) 261 { 262 effect->setpreset(0); 263 } 264 else 265 { 266 for (int i=0, count=static_cast<int>(paramCount); i<count; ++i) 267 effect->changepar(i+2, params[i]); 268 } 269 270 // reset volume and pan 271 effect->changepar(0, 127); 272 effect->changepar(1, 64); 273 } 274 275 void addWithMultiply(float* dst, const float* src, const float multiplier, const uint32_t frames) noexcept 276 { 277 for (uint32_t i=0; i<frames; ++i) 278 dst[i] += src[i] * multiplier; 279 } 280 281 void copyWithMultiply(float* dst, const float* src, const float multiplier, const uint32_t frames) noexcept 282 { 283 for (uint32_t i=0; i<frames; ++i) 284 dst[i] = src[i] * multiplier; 285 } 286 287 void multiply(float* dst, const float multiplier, const uint32_t frames) noexcept 288 { 289 for (uint32_t i=0; i<frames; ++i) 290 dst[i] *= multiplier; 291 } 292 293 DISTRHO_DECLARE_NON_COPY_CLASS(AbstractPluginFX) 294 }; 295 296 #endif // ZYNADDSUBFX_ABSTRACTFX_HPP_INCLUDED