/* ZynAddSubFX - a software synthesizer EnvelopeParams.cpp - Parameters for Envelope Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (version 2 or later) for more details. You should have received a copy of the GNU General Public License (version 2) along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "EnvelopeParams.h" #include "../Misc/Util.h" #define rObject EnvelopeParams using namespace rtosc; static const rtosc::Ports localPorts = { rSelf(EnvelopeParams), rPaste, #undef rChangeCb #define rChangeCb if(!obj->Pfreemode) obj->converttofree(); rToggle(Pfreemode, "Complex Envelope Definitions"), #undef rChangeCb #define rChangeCb rParamZyn(Penvpoints, rProp(internal), "Number of points in complex definition"), rParamZyn(Penvsustain, rProp(internal), "Location of the sustain point"), rParams(Penvdt, MAX_ENVELOPE_POINTS, "Envelope Delay Times"), rParams(Penvval, MAX_ENVELOPE_POINTS, "Envelope Values"), rParamZyn(Penvstretch, "Stretch with respect to frequency"), rToggle(Pforcedrelease, "Force Envelope to fully evaluate"), rToggle(Plinearenvelope, "Linear or Logarithmic Envelopes"), rParamZyn(PA_dt, "Attack Time"), rParamZyn(PA_val, "Attack Value"), rParamZyn(PD_dt, "Decay Time"), rParamZyn(PD_val, "Decay Value"), rParamZyn(PS_val, "Sustain Value"), rParamZyn(PR_dt, "Release Time"), rParamZyn(PR_val, "Release Value"), {"addPoint:i", rProp(internal) rDoc("Add point to envelope"), NULL, [](const char *msg, RtData &d) { EnvelopeParams *env = (rObject*) d.obj; const int curpoint = rtosc_argument(msg, 0).i; //int curpoint=freeedit->lastpoint; if (curpoint<0 || curpoint>env->Penvpoints || env->Penvpoints>=MAX_ENVELOPE_POINTS) return; for (int i=env->Penvpoints; i>=curpoint+1; i--) { env->Penvdt[i]=env->Penvdt[i-1]; env->Penvval[i]=env->Penvval[i-1]; } if (curpoint==0) { env->Penvdt[1]=64; } env->Penvpoints++; if (curpoint<=env->Penvsustain) env->Penvsustain++; }}, {"delPoint:i", rProp(internal) rDoc("Delete Envelope Point"), NULL, [](const char *msg, RtData &d) { EnvelopeParams *env = (rObject*) d.obj; const int curpoint=rtosc_argument(msg, 0).i; if(curpoint<1 || curpoint>=env->Penvpoints-1 || env->Penvpoints<=3) return; for (int i=curpoint+1;iPenvpoints;i++){ env->Penvdt[i-1]=env->Penvdt[i]; env->Penvval[i-1]=env->Penvval[i]; }; env->Penvpoints--; if (curpoint<=env->Penvsustain) env->Penvsustain--; }}, }; const rtosc::Ports &EnvelopeParams::ports = localPorts; EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_, unsigned char Pforcedrelease_) { PA_dt = 10; PD_dt = 10; PR_dt = 10; PA_val = 64; PD_val = 64; PS_val = 64; PR_val = 64; for(int i = 0; i < MAX_ENVELOPE_POINTS; ++i) { Penvdt[i] = 32; Penvval[i] = 64; } Penvdt[0] = 0; //no used Penvsustain = 1; Penvpoints = 1; Envmode = 1; Penvstretch = Penvstretch_; Pforcedrelease = Pforcedrelease_; Pfreemode = 1; Plinearenvelope = 0; store2defaults(); } EnvelopeParams::~EnvelopeParams() {} void EnvelopeParams::paste(const EnvelopeParams &ep) { //Avoid undefined behavior if(&ep == this) return; char *base = (char*)&this->Pfreemode; char *end = (char*)&this->DR_val; assert(end-base > 0); memcpy((char*)&this->Pfreemode, (const char*)&ep.Pfreemode, 1+end-base); } float EnvelopeParams::getdt(char i) const { return EnvelopeParams::dt(Penvdt[(int)i]); } float EnvelopeParams::dt(char val) { return (powf(2.0f, val / 127.0f * 12.0f) - 1.0f) * 10.0f; //miliseconds } /* * ADSR/ASR... initialisations */ void EnvelopeParams::ADSRinit(char A_dt, char D_dt, char S_val, char R_dt) { setpresettype("Penvamplitude"); Envmode = 1; PA_dt = A_dt; PD_dt = D_dt; PS_val = S_val; PR_dt = R_dt; Pfreemode = 0; converttofree(); store2defaults(); } void EnvelopeParams::ADSRinit_dB(char A_dt, char D_dt, char S_val, char R_dt) { setpresettype("Penvamplitude"); Envmode = 2; PA_dt = A_dt; PD_dt = D_dt; PS_val = S_val; PR_dt = R_dt; Pfreemode = 0; converttofree(); store2defaults(); } void EnvelopeParams::ASRinit(char A_val, char A_dt, char R_val, char R_dt) { setpresettype("Penvfrequency"); Envmode = 3; PA_val = A_val; PA_dt = A_dt; PR_val = R_val; PR_dt = R_dt; Pfreemode = 0; converttofree(); store2defaults(); } void EnvelopeParams::ADSRinit_filter(char A_val, char A_dt, char D_val, char D_dt, char R_dt, char R_val) { setpresettype("Penvfilter"); Envmode = 4; PA_val = A_val; PA_dt = A_dt; PD_val = D_val; PD_dt = D_dt; PR_dt = R_dt; PR_val = R_val; Pfreemode = 0; converttofree(); store2defaults(); } void EnvelopeParams::ASRinit_bw(char A_val, char A_dt, char R_val, char R_dt) { setpresettype("Penvbandwidth"); Envmode = 5; PA_val = A_val; PA_dt = A_dt; PR_val = R_val; PR_dt = R_dt; Pfreemode = 0; converttofree(); store2defaults(); } /* * Convert the Envelope to freemode */ void EnvelopeParams::converttofree() { switch(Envmode) { case 1: Penvpoints = 4; Penvsustain = 2; Penvval[0] = 0; Penvdt[1] = PA_dt; Penvval[1] = 127; Penvdt[2] = PD_dt; Penvval[2] = PS_val; Penvdt[3] = PR_dt; Penvval[3] = 0; break; case 2: Penvpoints = 4; Penvsustain = 2; Penvval[0] = 0; Penvdt[1] = PA_dt; Penvval[1] = 127; Penvdt[2] = PD_dt; Penvval[2] = PS_val; Penvdt[3] = PR_dt; Penvval[3] = 0; break; case 3: Penvpoints = 3; Penvsustain = 1; Penvval[0] = PA_val; Penvdt[1] = PA_dt; Penvval[1] = 64; Penvdt[2] = PR_dt; Penvval[2] = PR_val; break; case 4: Penvpoints = 4; Penvsustain = 2; Penvval[0] = PA_val; Penvdt[1] = PA_dt; Penvval[1] = PD_val; Penvdt[2] = PD_dt; Penvval[2] = 64; Penvdt[3] = PR_dt; Penvval[3] = PR_val; break; case 5: Penvpoints = 3; Penvsustain = 1; Penvval[0] = PA_val; Penvdt[1] = PA_dt; Penvval[1] = 64; Penvdt[2] = PR_dt; Penvval[2] = PR_val; break; } } void EnvelopeParams::add2XML(XMLwrapper *xml) { xml->addparbool("free_mode", Pfreemode); xml->addpar("env_points", Penvpoints); xml->addpar("env_sustain", Penvsustain); xml->addpar("env_stretch", Penvstretch); xml->addparbool("forced_release", Pforcedrelease); xml->addparbool("linear_envelope", Plinearenvelope); xml->addpar("A_dt", PA_dt); xml->addpar("D_dt", PD_dt); xml->addpar("R_dt", PR_dt); xml->addpar("A_val", PA_val); xml->addpar("D_val", PD_val); xml->addpar("S_val", PS_val); xml->addpar("R_val", PR_val); if((Pfreemode != 0) || (!xml->minimal)) for(int i = 0; i < Penvpoints; ++i) { xml->beginbranch("POINT", i); if(i != 0) xml->addpar("dt", Penvdt[i]); xml->addpar("val", Penvval[i]); xml->endbranch(); } } void EnvelopeParams::getfromXML(XMLwrapper *xml) { Pfreemode = xml->getparbool("free_mode", Pfreemode); Penvpoints = xml->getpar127("env_points", Penvpoints); Penvsustain = xml->getpar127("env_sustain", Penvsustain); Penvstretch = xml->getpar127("env_stretch", Penvstretch); Pforcedrelease = xml->getparbool("forced_release", Pforcedrelease); Plinearenvelope = xml->getparbool("linear_envelope", Plinearenvelope); PA_dt = xml->getpar127("A_dt", PA_dt); PD_dt = xml->getpar127("D_dt", PD_dt); PR_dt = xml->getpar127("R_dt", PR_dt); PA_val = xml->getpar127("A_val", PA_val); PD_val = xml->getpar127("D_val", PD_val); PS_val = xml->getpar127("S_val", PS_val); PR_val = xml->getpar127("R_val", PR_val); for(int i = 0; i < Penvpoints; ++i) { if(xml->enterbranch("POINT", i) == 0) continue; if(i != 0) Penvdt[i] = xml->getpar127("dt", Penvdt[i]); Penvval[i] = xml->getpar127("val", Penvval[i]); xml->exitbranch(); } if(!Pfreemode) converttofree(); } void EnvelopeParams::defaults() { Penvstretch = Denvstretch; Pforcedrelease = Dforcedrelease; Plinearenvelope = Dlinearenvelope; PA_dt = DA_dt; PD_dt = DD_dt; PR_dt = DR_dt; PA_val = DA_val; PD_val = DD_val; PS_val = DS_val; PR_val = DR_val; Pfreemode = 0; converttofree(); } void EnvelopeParams::store2defaults() { Denvstretch = Penvstretch; Dforcedrelease = Pforcedrelease; Dlinearenvelope = Plinearenvelope; DA_dt = PA_dt; DD_dt = PD_dt; DR_dt = PR_dt; DA_val = PA_val; DD_val = PD_val; DS_val = PS_val; DR_val = PR_val; }