zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

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