zynaddsubfx

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

EnvelopeParams.cpp (23543B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   EnvelopeParams.cpp - Parameters for Envelope
      5   Copyright (C) 2002-2005 Nasca Octavian Paul
      6   Author: Nasca Octavian Paul
      7 
      8   This program is free software; you can redistribute it and/or
      9   modify it under the terms of the GNU General Public License
     10   as published by the Free Software Foundation; either version 2
     11   of the License, or (at your option) any later version.
     12 */
     13 
     14 #include <cmath>
     15 #include <cstdlib>
     16 #include <cassert>
     17 #include <rtosc/ports.h>
     18 #include <rtosc/port-sugar.h>
     19 
     20 #include "zyn-version.h"
     21 #include "EnvelopeParams.h"
     22 #include "../Misc/Util.h"
     23 #include "../Misc/Time.h"
     24 
     25 using namespace rtosc;
     26 
     27 namespace zyn {
     28 
     29 #define rObject EnvelopeParams
     30 #define rBegin [](const char *msg, RtData &d) { \
     31     (void)* msg; EnvelopeParams *env = (rObject*) d.obj
     32 #define rEnd }
     33 
     34 #define dT127(var) limit( (int)roundf(log2f(var*100.0f + 1.0f) * 127.0f/12.0f), 0, 127 )
     35 #define dTREAL(var) (powf(2.0f, var / 127.0f * 12.0f) - 1.0f) / 100.0f
     36 
     37 #define rParamDT(name, ...) \
     38   {"P" STRINGIFY(name) "::i", rProp(alias) rProp(parameter) DOC(__VA_ARGS__), NULL, rParamDTCb(name)}
     39 
     40 #define rParamDTCb(name) rBOIL_BEGIN \
     41         if(!strcmp("", args)) {\
     42             data.reply(loc, "i", dT127(obj->name)); \
     43         } else { \
     44             unsigned char var = rtosc_argument(msg, 0).i; \
     45             rLIMIT(var, atoi) \
     46             rCAPPLY(obj->name, "f", obj->name = dTREAL(var)) \
     47             data.broadcast(loc, "i", dT127(obj->name));\
     48             rChangeCb \
     49         } rBOIL_END
     50 
     51 #define rParamsDT(name, length, ...) \
     52 rArrayDT(name, length, __VA_ARGS__), \
     53 {"P" STRINGIFY(name) ":", rProp(alias) rDoc("get all data from aliased array"), NULL, rParamsDTCb(name, length)}
     54 
     55 #define rParamsDTCb(name, length) rBOIL_BEGIN \
     56     char varS[length]; \
     57     for (int i = 0; i < length; i++) {varS[i] = dT127(obj->name[i]);} \
     58     data.reply(loc, "b", length, varS); rBOIL_END
     59 
     60 #define rArrayDT(name, length, ...) \
     61 {"P" STRINGIFY(name) "#" STRINGIFY(length) "::i", rProp(parameter) DOC(__VA_ARGS__), NULL, rArrayDTICb(name)}
     62 
     63 #define rArrayDTICb(name) rBOILS_BEGIN \
     64         if(!strcmp("", args)) {\
     65             data.reply(loc, "i", dT127(obj->name[idx])); \
     66         } else { \
     67             char varI = rtosc_argument(msg, 0).i; \
     68             float var = dTREAL(varI); \
     69             rLIMIT(var, atoi) \
     70             rAPPLY(name[idx], f) \
     71             data.broadcast(loc, "i", dT127(obj->name[idx]));\
     72             rChangeCb \
     73         } rBOILS_END
     74 
     75 static const rtosc::Ports localPorts = {
     76     rSelf(EnvelopeParams),
     77     rPasteRt,
     78 #undef  rChangeCb
     79 #define rChangeCb if(!obj->Pfreemode) obj->converttofree(); if (obj->time) { \
     80         obj->last_update_timestamp = obj->time->time(); }
     81     rOption(loc, rProp(internal),
     82             rOptions(ad_global_amp, ad_global_freq, ad_global_filter,
     83                      ad_voice_amp, ad_voice_freq, ad_voice_filter,
     84                      ad_voice_fm_amp, ad_voice_fm_freq,
     85                      sub_freq, sub_bandwidth),
     86             "location of the envelope"),
     87     rToggle(Pfreemode, rDefault(false), "Complex Envelope Definitions"),
     88 #undef  rChangeCb
     89 #define rChangeCb if(!obj->Pfreemode) obj->converttofree(); \
     90                   if(obj->time) { obj->last_update_timestamp = obj->time->time(); }
     91     rParamZyn(Penvpoints, rProp(internal), rDefaultDepends(loc),
     92             rPresetAtMulti(3, ad_global_freq, ad_voice_freq,
     93                               ad_voice_fm_freq,
     94                               sub_freq, sub_bandwidth),
     95             rDepends(Pfreemode),
     96             rDefault(4),
     97             "Number of points in complex definition"),
     98     rParamZyn(Penvsustain, rDefaultDepends(loc),
     99             rPresetAtMulti(1, ad_global_freq, ad_voice_freq,
    100                               ad_voice_fm_freq,
    101                               sub_freq, sub_bandwidth),
    102             rDepends(Pfreemode),
    103             rDefault(2),
    104             "Location of the sustain point"),
    105     rParamZyn(Penvstretch,  rShort("stretch"), rDefaultDepends(loc),
    106             rPresetAtMulti(0, ad_global_freq, ad_global_filter,
    107                               ad_voice_freq, ad_voice_filter, ad_voice_fm_freq,
    108                               sub_filter),
    109             rDefault(64),
    110             "Stretch with respect to frequency"),
    111     rToggle(Pforcedrelease, rShort("frcr"), rDefaultDepends(loc),
    112             rPresetAtMulti(true, ad_global_amp, ad_global_filter, ad_voice_amp,
    113                                  ad_voice_fm_amp, sub_filter),
    114             rDefault(false),
    115             "Force Envelope to fully evaluate"),
    116     rToggle(Plinearenvelope, rShort("lin/log"), rDefault(false),
    117             "Linear or Logarithmic Envelopes"),
    118     rToggle(Prepeating, rShort("repeat"), rDefault(false),
    119             "Repeat the Envelope"),
    120     rParamDT(A_dt ,  rShort("a.dt"), rLinear(0,127), rDepends(Pfreemode),
    121             "Attack Time"),
    122     rParamF(A_dt,  rShort("a.dt"), rLogWithLogmin(0.f,41.0f, 0.0001f),
    123               rDefaultDepends(loc), rDepends(Pfreemode),
    124               rPreset(ad_global_freq, 0.254f),   rPreset(ad_global_filter, 0.127f),
    125               rPreset(ad_voice_freq, 0.127f),    rPreset(ad_voice_filter, 0.970f),
    126               rPreset(ad_voice_fm_freq, 3.620f), rPreset(ad_voice_fm_amp, 1.876f),
    127               rPreset(sub_freq, 0.254f),         rPreset(sub_bandwidth, 0.970f),
    128               rPreset(sub_filter, 0.13 (0x1.041894p-3)),
    129               rDefault(0.0f),
    130               "Attack Time"),
    131 
    132     rParamZyn(PA_val, rShort("a.val"),
    133               rDefaultDepends(loc), rDepends(Pfreemode),
    134               rPreset(ad_voice_freq, 30),    rPreset(ad_voice_filter, 90),
    135               rPreset(ad_voice_fm_freq, 20),
    136               rPreset(sub_freq, 30),         rPreset(sub_bandwidth, 100),
    137               rDefault(64),
    138               "Attack Value"),
    139     rParamDT(D_dt, rShort("d.dt"), rLinear(0,127), rDepends(Pfreemode),
    140               "Decay Time"),
    141     rParamF(D_dt,  rShort("d.dt"), rLogWithLogmin(0.f, 41.0f, 0.0001f),
    142               rDefaultDepends(loc), rDepends(Pfreemode),
    143               rPreset(ad_global_amp, 0.127f),    rPreset(ad_global_filter, 0.970f),
    144               rPreset(ad_voice_amp, 6.978f),    rPreset(ad_voice_filter, 0.970f),
    145               rPreset(ad_voice_fm_amp, 3.620f),
    146               rPreset(sub_filter, 0.97),
    147               rDefault(0.009f),
    148               "Decay Time"),
    149     rParamZyn(PD_val, rShort("d.val"),
    150               rDefaultDepends(loc), rDepends(Pfreemode),
    151               rDefault(64), rPreset(ad_voice_filter, 40),
    152               "Decay Value"),
    153     rParamZyn(PS_val, rShort("s.val"),
    154               rDefaultDepends(loc), rDepends(Pfreemode), rDefault(64),
    155               rPresetAtMulti(127, ad_global_amp, ad_voice_amp, ad_voice_fm_amp),
    156               "Sustain Value"),
    157     rParamDT(R_dt, rShort("r.dt"), rLinear(0,127), rDepends(Pfreemode),
    158               "Release Time"),
    159     rParamF(R_dt,  rShort("r.dt"), rLogWithLogmin(0.f,41.0f,0.009f),
    160               rDefaultDepends(loc), rDepends(Pfreemode),
    161               rPreset(ad_global_amp, 0.041f),
    162               rPreset(ad_voice_amp, 6.978f),    rPreset(ad_voice_filter, 0.009f),
    163               rPreset(ad_voice_fm_freq, 1.876f), rPreset(ad_voice_fm_amp, 6.978f),
    164               rDefault(0.499f),
    165               "Release Time"),
    166     rParamZyn(PR_val, rShort("r.val"),
    167               rDefaultDepends(loc), rDepends(Pfreemode),
    168               rPresetAtMulti(40, ad_voice_filter, ad_voice_fm_freq),
    169               rDefault(64),
    170               "Release Value"),
    171 #undef rChangeCb
    172 #define rChangeCb if(!obj->Pfreemode) obj->converttofree(); \
    173                   if(obj->time) { obj->last_update_timestamp = obj->time->time(); } \
    174                   if(idx >= obj->Penvpoints) { obj->Penvpoints = idx + 1; }
    175     rParamsDT(envdt,  MAX_ENVELOPE_POINTS, rProp(alias), "Envelope Delay Times"),
    176     rArrayF(envdt, MAX_ENVELOPE_POINTS, rProp(parameter),
    177             rEnabledBy(Pfreemode),
    178             rDefault([0.0 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    179             rPreset(ad_voice_freq, [0.00 (0x0p+0) 0.13 (0x1.041894p-3) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    180             rPreset(ad_voice_amp, [0.00 (0x0p+0) 0.00 (0x0p+0) 6.98 (0x1.be978ep+2) 6.98 (0x1.be978ep+2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    181             rPreset(ad_voice_filter, [0.00 (0x0p+0) 0.97 (0x1.f0a3d8p-1) 0.97 (0x1.f0a3d8p-1) 0.01 (0x1.26e978p-7) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    182             rPreset(ad_voice_fm_freq, [0.00 (0x0p+0) 3.62 (0x1.cf5c28p+1) 1.88 (0x1.e0418ap+0) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    183             rPreset(ad_voice_fm_amp, [0.00 (0x0p+0) 1.88 (0x1.e0418ap+0) 3.62 (0x1.cf5c28p+1) 6.98 (0x1.be978ep+2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    184             rPreset(ad_global_freq, [0.00 (0x0p+0) 0.25 (0x1.041894p-2) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    185             rPreset(ad_global_amp, [0.00 (0x0p+0) 0.00 (0x0p+0) 0.13 (0x1.041894p-3) 0.04 (0x1.4fdf3cp-5) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    186             rPreset(ad_global_filter, [0.00 (0x0p+0) 0.13 (0x1.041894p-3) 0.97 (0x1.f0a3d8p-1) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    187             rPreset(sub_freq, [0.00 (0x0p+0) 0.25 (0x1.041894p-2) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    188             rPreset(sub_bandwidth, [0.00 (0x0p+0) 0.97 (0x1.f0a3d8p-1) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    189             rPreset(sub_filter, [0.00 (0x0p+0) 0.13 (0x1.041894p-3) 0.97 (0x1.f0a3d8p-1) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]),
    190             rDefaultDepends(loc), rDepends(Pfreemode,A_dt,D_dt,R_dt),
    191             "Envelope Delay Times (ms)"),
    192     rParams(Penvval, MAX_ENVELOPE_POINTS,
    193         rEnabledBy(Pfreemode),
    194         rDefault([64 64 ...]),
    195         rPreset(ad_global_amp, [0 127 127 0 64 64 ...]),
    196         rPreset(ad_voice_amp, [0 127 127 0 64 64 ...]),
    197         rPreset(ad_voice_fm_amp, [0 127 127 0 64 64 ...]),
    198         rPreset(ad_voice_fm_freq, [20 64 40 64 64 ...]),
    199         rPreset(ad_voice_freq, [30 64 64 ...]),
    200         rPreset(ad_voice_filter, [90 40 64 40 64 64 ...]),
    201         rPreset(sub_bandwidth, [100 64 64 ...]),
    202         rPreset(sub_freq, [30 64 64 ...]),
    203         rDefaultDepends(loc) rDepends(Penvpoints,Pfreemode,PA_val,PD_val,PS_val,PR_val), "Envelope Values"),
    204 #undef rChangeCb
    205     {"Envmode:", rDoc("Envelope variant type"), NULL,
    206         rBegin;
    207         d.reply(d.loc, "i", env->Envmode);
    208         rEnd},
    209     {"envdt", rDoc("Envelope Delay Times (ms)"), NULL,
    210         rBegin;
    211         const int N = MAX_ENVELOPE_POINTS;
    212         const int M = rtosc_narguments(msg);
    213         if(M == 0) {
    214             rtosc_arg_t args[N];
    215             char arg_types[N+1] = {0};
    216             for(int i=0; i<N; ++i) {
    217                 args[i].f    = env->getdt(i)*1000; //answer milliseconds to old gui
    218                 arg_types[i] = 'f';
    219             }
    220             d.replyArray(d.loc, arg_types, args);
    221         } else {
    222             for(int i=0; i<N && i<M; ++i) {
    223                 env->envdt[i] = (rtosc_argument(msg, i).f)/1000; //store as seconds in member variable
    224             }
    225         }
    226         rEnd},
    227     {"dt", rDoc("Envelope Delay Times (sec)"), NULL,
    228         rBegin;
    229 
    230         const int N = MAX_ENVELOPE_POINTS;
    231         const int M = rtosc_narguments(msg);
    232         if(M == 0) {
    233             rtosc_arg_t args[N];
    234             char arg_types[N+1] = {};
    235             for(int i=0; i<N; ++i) {
    236                 args[i].f    = env->getdt(i);
    237                 arg_types[i] = 'f';
    238             }
    239             d.replyArray(d.loc, arg_types, args);
    240         } else {
    241             for(int i=0; i<N && i<M; ++i)
    242                 env->envdt[i] = (rtosc_argument(msg, i).f);
    243         }
    244         rEnd},
    245     {"envval", rDoc("Envelope Values"), NULL,
    246         rBegin;
    247         const int N = MAX_ENVELOPE_POINTS;
    248         const int M = rtosc_narguments(msg);
    249         if(M == 0) {
    250             rtosc_arg_t args[N];
    251             char arg_types[N+1] = {};
    252             for(int i=0; i<N; ++i) {
    253                 args[i].f    = env->Penvval[i]/127.0f;
    254                 arg_types[i] = 'f';
    255             }
    256             d.replyArray(d.loc, arg_types, args);
    257         } else {
    258             for(int i=0; i<N && i<M; ++i) {
    259                 env->Penvval[i] = limit(roundf(rtosc_argument(msg,i).f*127.0f), 0.0f, 127.0f);
    260             }
    261         }
    262         rEnd},
    263 
    264     {"addPoint:i", rProp(internal) rDoc("Add point to envelope"), NULL,
    265         rBegin;
    266         const int curpoint = rtosc_argument(msg, 0).i;
    267         //int curpoint=freeedit->lastpoint;
    268         if (curpoint<0 || curpoint>env->Penvpoints || env->Penvpoints>=MAX_ENVELOPE_POINTS)
    269             return;
    270 
    271         for (int i=env->Penvpoints; i>=curpoint+1; i--) {
    272             env->envdt[i]=env->envdt[i-1];
    273             env->Penvval[i]=env->Penvval[i-1];
    274         }
    275 
    276         if (curpoint==0)
    277             env->envdt[1]=dTREAL(64);
    278 
    279         env->Penvpoints++;
    280         if (curpoint<=env->Penvsustain)
    281             env->Penvsustain++;
    282         rEnd},
    283     {"delPoint:i", rProp(internal) rDoc("Delete Envelope Point"), NULL,
    284         rBegin;
    285         const int curpoint=rtosc_argument(msg, 0).i;
    286         if(curpoint<1 || curpoint>=env->Penvpoints-1 || env->Penvpoints<=3)
    287             return;
    288 
    289         for (int i=curpoint+1;i<env->Penvpoints;i++){
    290             env->envdt[i-1]=env->envdt[i];
    291             env->Penvval[i-1]=env->Penvval[i];
    292         };
    293 
    294         env->Penvpoints--;
    295 
    296         if (curpoint<=env->Penvsustain)
    297             env->Penvsustain--;
    298 
    299         rEnd},
    300 };
    301 
    302 const rtosc::Ports &EnvelopeParams::ports = localPorts;
    303 
    304 
    305 EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_,
    306                                unsigned char Pforcedrelease_,
    307                                const AbsTime *time_):
    308         time(time_), last_update_timestamp(0)
    309 {
    310     A_dt  = 0.009;
    311     D_dt  = 0.009;
    312     R_dt  = 0.009;
    313     PA_val = 64;
    314     PD_val = 64;
    315     PS_val = 64;
    316     PR_val = 64;
    317 
    318     for(int i = 0; i < MAX_ENVELOPE_POINTS; ++i) {
    319         envdt[i]  = dTREAL(32);
    320         Penvval[i] = 64;
    321     }
    322     envdt[0]        = 0.0f; //not used
    323     Penvsustain     = 1;
    324     Penvpoints      = 1;
    325     Envmode         = ADSR_lin;
    326     Penvstretch     = Penvstretch_;
    327     Pforcedrelease  = Pforcedrelease_;
    328     Pfreemode       = 1;
    329     Plinearenvelope = 0;
    330     Prepeating      = 0;
    331 
    332     store2defaults();
    333 }
    334 
    335 EnvelopeParams::~EnvelopeParams()
    336 {}
    337 
    338 #define COPY(y) this->y = ep.y
    339 void EnvelopeParams::paste(const EnvelopeParams &ep)
    340 {
    341 
    342     COPY(Pfreemode);
    343     COPY(Penvpoints);
    344     COPY(Penvsustain);
    345     for(int i=0; i<MAX_ENVELOPE_POINTS; ++i) {
    346         this->envdt[i]  = ep.envdt[i];
    347         this->Penvval[i] = ep.Penvval[i];
    348     }
    349     COPY(Penvstretch);
    350     COPY(Pforcedrelease);
    351     COPY(Plinearenvelope);
    352 
    353     COPY(A_dt);
    354     COPY(D_dt);
    355     COPY(R_dt);
    356     COPY(PA_val);
    357     COPY(PD_val);
    358     COPY(PS_val);
    359     COPY(PR_val);
    360 
    361     if ( time ) {
    362         last_update_timestamp = time->time();
    363     }
    364 }
    365 #undef COPY
    366 
    367 void EnvelopeParams::init(zyn::consumer_location_t _loc)
    368 {
    369     switch(loc = _loc)
    370     {
    371         case ad_global_amp:    ADSRinit_dB(0.0f, 0.127f, 127, 0.041f); break;
    372         case ad_global_freq:   ASRinit(64, 0.254f, 64, 0.499f); break;
    373         case ad_global_filter:
    374         case sub_filter:       ADSRinit_filter(64, 0.127f, 64, 0.970f, 0.499f, 64); break;
    375         case ad_voice_amp:     ADSRinit_dB(0.0f, 6.978f, 127, 6.978f); break;
    376         case ad_voice_freq:    ASRinit(30, 0.127f, 64, 0.499f); break;
    377         case ad_voice_filter:  ADSRinit_filter(90, 0.970f, 40, 0.970f, 0.009f, 40); break;
    378         case ad_voice_fm_freq: ASRinit(20, 3.620f, 40, 1.876f); break;
    379         case ad_voice_fm_amp:  ADSRinit(1.876f, 3.620f, 127, 6.978f); break;
    380         case sub_freq:         ASRinit(30, 0.254f, 64, 0.499f); break;
    381         case sub_bandwidth:    ASRinit_bw(100, 0.970f, 64, 0.499f); break;
    382         default: throw std::logic_error("Invalid envelope consumer location");
    383     };
    384 }
    385 
    386 float EnvelopeParams::getdt(char i) const
    387 {
    388     return envdt[(int)i]; //seconds
    389 }
    390 
    391 /*
    392  * ADSR/ASR... initialisations
    393  */
    394 void EnvelopeParams::ADSRinit(float a_dt, float d_dt, char s_val, float r_dt)
    395 {
    396     setpresettype("Penvamplitude");
    397     Envmode   = ADSR_lin;
    398     A_dt      = a_dt;
    399     D_dt      = d_dt;
    400     PS_val    = s_val;
    401     R_dt      = r_dt;
    402     Pfreemode = 0;
    403     converttofree();
    404 
    405     store2defaults();
    406 }
    407 
    408 void EnvelopeParams::ADSRinit_dB(float a_dt, float d_dt, char s_val, float r_dt)
    409 {
    410     setpresettype("Penvamplitude");
    411     Envmode   = ADSR_dB;
    412     A_dt      = a_dt;
    413     D_dt      = d_dt;
    414     PS_val    = s_val;
    415     R_dt      = r_dt;
    416     Pfreemode = 0;
    417     converttofree();
    418 
    419     store2defaults();
    420 }
    421 
    422 void EnvelopeParams::ASRinit(char a_val, float a_dt, char r_val, float r_dt)
    423 {
    424     setpresettype("Penvfrequency");
    425     Envmode   = ASR_freqlfo;
    426     PA_val    = a_val;
    427     A_dt      = a_dt;
    428     PR_val    = r_val;
    429     R_dt      = r_dt;
    430     Pfreemode = 0;
    431     converttofree();
    432 
    433     store2defaults();
    434 }
    435 
    436 void EnvelopeParams::ADSRinit_filter(char a_val,
    437                                      float a_dt,
    438                                      char d_val,
    439                                      float d_dt,
    440                                      float r_dt,
    441                                      char r_val)
    442 {
    443     setpresettype("Penvfilter");
    444     Envmode   = ADSR_filter;
    445     PA_val    = a_val;
    446     A_dt      = a_dt;
    447     PD_val    = d_val;
    448     D_dt      = d_dt;
    449     R_dt      = r_dt;
    450     PR_val    = r_val;
    451     Pfreemode = 0;
    452     converttofree();
    453     store2defaults();
    454 }
    455 
    456 void EnvelopeParams::ASRinit_bw(char a_val, float a_dt, char r_val, float r_dt)
    457 {
    458     setpresettype("Penvbandwidth");
    459     Envmode   = ASR_bw;
    460     PA_val    = a_val;
    461     A_dt      = a_dt;
    462     PR_val    = r_val;
    463     R_dt      = r_dt;
    464     Pfreemode = 0;
    465     converttofree();
    466     store2defaults();
    467 }
    468 
    469 /*
    470  * Convert the Envelope to freemode
    471  */
    472 void EnvelopeParams::converttofree()
    473 {
    474     switch(Envmode) {
    475         case ADSR_lin:
    476         case ADSR_dB:
    477             Penvpoints  = 4;
    478             Penvsustain = 2;
    479             Penvval[0]  = 0;
    480             envdt[1]   = A_dt;
    481             Penvval[1]  = 127;
    482             envdt[2]   = D_dt;
    483             Penvval[2]  = PS_val;
    484             envdt[3]   = R_dt;
    485             Penvval[3]  = 0;
    486             break;
    487         case ASR_freqlfo:
    488         case ASR_bw:
    489             Penvpoints  = 3;
    490             Penvsustain = 1;
    491             Penvval[0]  = PA_val;
    492             envdt[1]   = A_dt;
    493             Penvval[1]  = 64;
    494             envdt[2]   = R_dt;
    495             Penvval[2]  = PR_val;
    496             break;
    497         case ADSR_filter:
    498             Penvpoints  = 4;
    499             Penvsustain = 2;
    500             Penvval[0]  = PA_val;
    501             envdt[1]   = A_dt;
    502             Penvval[1]  = PD_val;
    503             envdt[2]   = D_dt;
    504             Penvval[2]  = 64;
    505             envdt[3]   = R_dt;
    506             Penvval[3]  = PR_val;
    507             break;
    508     }
    509 }
    510 
    511 
    512 
    513 
    514 void EnvelopeParams::add2XML(XMLwrapper& xml)
    515 {
    516     xml.addparbool("free_mode", Pfreemode);
    517     xml.addpar("env_points", Penvpoints);
    518     xml.addpar("env_sustain", Penvsustain);
    519     xml.addpar("env_stretch", Penvstretch);
    520     xml.addparbool("forced_release", Pforcedrelease);
    521     xml.addparbool("linear_envelope", Plinearenvelope);
    522     xml.addparbool("repeating_envelope", Prepeating);
    523     xml.addparreal("A_dt", A_dt);
    524     xml.addparreal("D_dt", D_dt);
    525     xml.addparreal("R_dt", R_dt);
    526     xml.addpar("A_val", PA_val);
    527     xml.addpar("D_val", PD_val);
    528     xml.addpar("S_val", PS_val);
    529     xml.addpar("R_val", PR_val);
    530 
    531     if((Pfreemode != 0) || (!xml.minimal))
    532         for(int i = 0; i < Penvpoints; ++i) {
    533             xml.beginbranch("POINT", i);
    534             if(i != 0)
    535                 xml.addparreal("dt", envdt[i]);
    536             xml.addpar("val", Penvval[i]);
    537             xml.endbranch();
    538         }
    539 }
    540 
    541 float EnvelopeParams::env_dB2rap(float db) {
    542     return (powf(10.0f, db / 20.0f) - 0.01)/.99f;
    543 }
    544 
    545 float EnvelopeParams::env_rap2dB(float rap) {
    546     return 20.0f * log10f(rap * 0.99f + 0.01);
    547 }
    548 
    549 /**
    550     since commit 5334d94283a513ae42e472aa020db571a3589fb9, i.e. between
    551     versions 2.4.3 and 2.4.4, the amplitude envelope has been converted
    552     differently from dB to rap for AmplitudeEnvelope (mode 2)
    553     this converts the values read from an XML file once
    554 */
    555 struct version_fixer_t
    556 {
    557     const bool mismatch;
    558 public:
    559     int operator()(int input) const
    560     {
    561         return (mismatch)
    562             // The errors occurred when calling env_dB2rap. Let f be the
    563             // conversion function for mode 2 (see Envelope.cpp), then we
    564             // load values with (let "o" be the function composition symbol):
    565             //   f^{-1} o (env_dB2rap^{-1}) o dB2rap o f
    566             // from the xml file. This results in the following formula:
    567             ? roundf(127.0f * (0.5f *
    568                    log10f( 0.01f + 0.99f *
    569                                        powf(100, input/127.0f - 1))
    570                                + 1))
    571             : input;
    572     }
    573     version_fixer_t(const version_type& fileversion, int env_mode) :
    574         mismatch(fileversion < version_type(2,4,4) &&
    575                  (env_mode == 2)) {}
    576 };
    577 
    578 void EnvelopeParams::getfromXML(XMLwrapper& xml)
    579 {
    580     Pfreemode       = xml.getparbool("free_mode", Pfreemode);
    581     Penvpoints      = xml.getpar127("env_points", Penvpoints);
    582     Penvsustain     = xml.getpar127("env_sustain", Penvsustain);
    583     Penvstretch     = xml.getpar127("env_stretch", Penvstretch);
    584     Pforcedrelease  = xml.getparbool("forced_release", Pforcedrelease);
    585     Plinearenvelope = xml.getparbool("linear_envelope", Plinearenvelope);
    586     Prepeating      = xml.getparbool("repeating_envelope", Prepeating);
    587 
    588     version_fixer_t version_fix(xml.fileversion(), Envmode);
    589 
    590     if(!xml.hasparreal("A_dt")) {
    591         A_dt = dTREAL(xml.getpar127("A_dt", 0));
    592         D_dt = dTREAL(xml.getpar127("D_dt", 0));
    593         R_dt = dTREAL(xml.getpar127("R_dt", 0));
    594     } else {
    595         A_dt  = xml.getparreal("A_dt", A_dt);
    596         D_dt  = xml.getparreal("D_dt", D_dt);
    597         R_dt  = xml.getparreal("R_dt", R_dt);
    598     }
    599 
    600     PA_val = version_fix(xml.getpar127("A_val", PA_val));
    601     PD_val = version_fix(xml.getpar127("D_val", PD_val));
    602     PS_val = version_fix(xml.getpar127("S_val", PS_val));
    603     PR_val = version_fix(xml.getpar127("R_val", PR_val));
    604 
    605     for(int i = 0; i < Penvpoints; ++i) {
    606         if(xml.enterbranch("POINT", i) == 0)
    607             continue;
    608         if(i != 0) {
    609             if(!xml.hasparreal("dt")) {
    610                 int dt = xml.getpar127("dt", dT127(envdt[i]));
    611                 envdt[i] = dTREAL(dt);
    612             }
    613             else {
    614                 envdt[i] = xml.getparreal("dt", envdt[i]);
    615             }
    616         }
    617         Penvval[i] = version_fix(xml.getpar127("val", Penvval[i]));
    618         xml.exitbranch();
    619     }
    620 
    621     if(!Pfreemode)
    622         converttofree();
    623 }
    624 
    625 
    626 void EnvelopeParams::defaults()
    627 {
    628     Penvstretch     = Denvstretch;
    629     Pforcedrelease  = Dforcedrelease;
    630     Plinearenvelope = Dlinearenvelope;
    631     Prepeating      = Drepeating;
    632     A_dt     = DA_dt;
    633     D_dt     = DD_dt;
    634     R_dt     = DR_dt;
    635     PA_val    = DA_val;
    636     PD_val    = DD_val;
    637     PS_val    = DS_val;
    638     PR_val    = DR_val;
    639     Pfreemode = 0;
    640     converttofree();
    641 }
    642 
    643 void EnvelopeParams::store2defaults()
    644 {
    645     Denvstretch     = Penvstretch;
    646     Dforcedrelease  = Pforcedrelease;
    647     Dlinearenvelope = Plinearenvelope;
    648     Drepeating      = Prepeating;
    649     DA_dt  = A_dt;
    650     DD_dt  = D_dt;
    651     DR_dt  = R_dt;
    652     DA_val = PA_val;
    653     DD_val = PD_val;
    654     DS_val = PS_val;
    655     DR_val = PR_val;
    656 }
    657 
    658 }