| 
							- /*
 -   ZynAddSubFX - a software synthesizer
 - 
 -   Envelope.cpp - Envelope implementation
 -   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 <cmath>
 - #include "Envelope.h"
 - #include "../Params/EnvelopeParams.h"
 - 
 - Envelope::Envelope(EnvelopeParams *envpars, float basefreq)
 - {
 -     int i;
 -     envpoints = envpars->Penvpoints;
 -     if(envpoints > MAX_ENVELOPE_POINTS)
 -         envpoints = MAX_ENVELOPE_POINTS;
 -     envsustain     = (envpars->Penvsustain == 0) ? -1 : envpars->Penvsustain;
 -     forcedrelase   = envpars->Pforcedrelease;
 -     envstretch     = powf(440.0f / basefreq, envpars->Penvstretch / 64.0f);
 -     linearenvelope = envpars->Plinearenvelope;
 - 
 -     if(envpars->Pfreemode == 0)
 -         envpars->converttofree();
 - 
 -     float bufferdt = synth->buffersize_f / synth->samplerate_f;
 - 
 -     int mode = envpars->Envmode;
 - 
 -     //for amplitude envelopes
 -     if((mode == 1) && (linearenvelope == 0))
 -         mode = 2;                              //change to log envelope
 -     if((mode == 2) && (linearenvelope != 0))
 -         mode = 1;                              //change to linear
 - 
 -     for(i = 0; i < MAX_ENVELOPE_POINTS; ++i) {
 -         float tmp = envpars->getdt(i) / 1000.0f * envstretch;
 -         if(tmp > bufferdt)
 -             envdt[i] = bufferdt / tmp;
 -         else
 -             envdt[i] = 2.0f;  //any value larger than 1
 - 
 -         switch(mode) {
 -             case 2:
 -                 envval[i] = (1.0f - envpars->Penvval[i] / 127.0f) * -40;
 -                 break;
 -             case 3:
 -                 envval[i] =
 -                     (powf(2, 6.0f
 -                           * fabs(envpars->Penvval[i]
 -                                  - 64.0f) / 64.0f) - 1.0f) * 100.0f;
 -                 if(envpars->Penvval[i] < 64)
 -                     envval[i] = -envval[i];
 -                 break;
 -             case 4:
 -                 envval[i] = (envpars->Penvval[i] - 64.0f) / 64.0f * 6.0f; //6 octaves (filtru)
 -                 break;
 -             case 5:
 -                 envval[i] = (envpars->Penvval[i] - 64.0f) / 64.0f * 10;
 -                 break;
 -             default:
 -                 envval[i] = envpars->Penvval[i] / 127.0f;
 -         }
 -     }
 - 
 -     envdt[0] = 1.0f;
 - 
 -     currentpoint = 1; //the envelope starts from 1
 -     keyreleased  = false;
 -     t = 0.0f;
 -     envfinish = false;
 -     inct      = envdt[1];
 -     envoutval = 0.0f;
 - }
 - 
 - Envelope::~Envelope()
 - {}
 - 
 - 
 - /*
 -  * Relase the key (note envelope)
 -  */
 - void Envelope::relasekey()
 - {
 -     if(keyreleased)
 -         return;
 -     keyreleased = true;
 -     if(forcedrelase != 0)
 -         t = 0.0f;
 - }
 - 
 - /*
 -  * Envelope Output
 -  */
 - float Envelope::envout()
 - {
 -     float out;
 - 
 -     if(envfinish) { //if the envelope is finished
 -         envoutval = envval[envpoints - 1];
 -         return envoutval;
 -     }
 -     if((currentpoint == envsustain + 1) && !keyreleased) { //if it is sustaining now
 -         envoutval = envval[envsustain];
 -         return envoutval;
 -     }
 - 
 -     if(keyreleased && (forcedrelase != 0)) { //do the forced release
 -         int tmp = (envsustain < 0) ? (envpoints - 1) : (envsustain + 1); //if there is no sustain point, use the last point for release
 - 
 -         if(envdt[tmp] < 0.00000001f)
 -             out = envval[tmp];
 -         else
 -             out = envoutval + (envval[tmp] - envoutval) * t;
 -         t += envdt[tmp] * envstretch;
 - 
 -         if(t >= 1.0f) {
 -             currentpoint = envsustain + 2;
 -             forcedrelase = 0;
 -             t    = 0.0f;
 -             inct = envdt[currentpoint];
 -             if((currentpoint >= envpoints) || (envsustain < 0))
 -                 envfinish = true;
 -         }
 -         return out;
 -     }
 -     if(inct >= 1.0f)
 -         out = envval[currentpoint];
 -     else
 -         out = envval[currentpoint - 1]
 -               + (envval[currentpoint] - envval[currentpoint - 1]) * t;
 - 
 -     t += inct;
 -     if(t >= 1.0f) {
 -         if(currentpoint >= envpoints - 1)
 -             envfinish = true;
 -         else
 -             currentpoint++;
 -         t    = 0.0f;
 -         inct = envdt[currentpoint];
 -     }
 - 
 -     envoutval = out;
 -     return out;
 - }
 - 
 - inline float Envelope::env_dB2rap(float db) {
 -     return (powf(10.0f, db / 20.0f) - 0.01)/.99f;
 - }
 - 
 - inline float Envelope::env_rap2dB(float rap) {
 -     return 20.0f * log10f(rap * 0.99f + 0.01);
 - }
 - 
 - /*
 -  * Envelope Output (dB)
 -  */
 - float Envelope::envout_dB()
 - {
 -     float out;
 -     if(linearenvelope != 0)
 -         return envout();
 - 
 -     if((currentpoint == 1) && (!keyreleased || (forcedrelase == 0))) { //first point is always lineary interpolated
 -         float v1 = env_dB2rap(envval[0]);
 -         float v2 = env_dB2rap(envval[1]);
 -         out = v1 + (v2 - v1) * t;
 - 
 -         t += inct;
 -         if(t >= 1.0f) {
 -             t    = 0.0f;
 -             inct = envdt[2];
 -             currentpoint++;
 -             out = v2;
 -         }
 - 
 -         if(out > 0.001f)
 -             envoutval = env_rap2dB(out);
 -         else
 -             envoutval = MIN_ENVELOPE_DB;
 -     }
 -     else
 -         out = env_dB2rap(envout());
 - 
 -     return out;
 - }
 - 
 - bool Envelope::finished() const
 - {
 -     return envfinish;
 - }
 
 
  |