| 
							- /*
 -   ZynAddSubFX - a software synthesizer
 - 
 -   LFO.cpp - LFO 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 the GNU General Public License
 -   as published by the Free Software Foundation; either version 2
 -   of the License, or (at your option) any later version.
 - */
 - 
 - #include "LFO.h"
 - #include "../Params/LFOParams.h"
 - #include "../Misc/Util.h"
 - 
 - #include <cstdlib>
 - #include <cstdio>
 - #include <cmath>
 - 
 - LFO::LFO(const LFOParams &lfopars, float basefreq, const AbsTime &t, WatchManager *m,
 -         const char *watch_prefix)
 -     :first_half(-1),
 -     delayTime(t, lfopars.Pdelay / 127.0f * 4.0f), //0..4 sec
 -     waveShape(lfopars.PLFOtype),
 -     deterministic(!lfopars.Pfreqrand),
 -     dt_(t.dt()),
 -     lfopars_(lfopars), basefreq_(basefreq),
 -     watchOut(m, watch_prefix, "out")
 - {
 -     int stretch = lfopars.Pstretch;
 -     if(stretch == 0)
 -         stretch = 1;
 - 
 -     //max 2x/octave
 -     const float lfostretch = powf(basefreq / 440.0f, (stretch - 64.0f) / 63.0f);
 - 
 -     const float lfofreq =
 -         (powf(2, lfopars.Pfreq * 10.0f) - 1.0f) / 12.0f * lfostretch;
 -     phaseInc = fabs(lfofreq) * t.dt();
 - 
 -     if(!lfopars.Pcontinous) {
 -         if(lfopars.Pstartphase == 0)
 -             phase = RND;
 -         else
 -             phase = fmod((lfopars.Pstartphase - 64.0f) / 127.0f + 1.0f, 1.0f);
 -     }
 -     else {
 -         const float tmp = fmod(t.time() * phaseInc, 1.0f);
 -         phase = fmod((lfopars.Pstartphase - 64.0f) / 127.0f + 1.0f + tmp, 1.0f);
 -     }
 - 
 -     //Limit the Frequency(or else...)
 -     if(phaseInc > 0.49999999f)
 -         phaseInc = 0.499999999f;
 - 
 - 
 -     lfornd = limit(lfopars.Prandomness / 127.0f, 0.0f, 1.0f);
 -     lfofreqrnd = powf(lfopars.Pfreqrand / 127.0f, 2.0f) * 4.0f;
 - 
 -     switch(lfopars.fel) {
 -         case 1:
 -             lfointensity = lfopars.Pintensity / 127.0f;
 -             break;
 -         case 2:
 -             lfointensity = lfopars.Pintensity / 127.0f * 4.0f;
 -             break; //in octave
 -         default:
 -             lfointensity = powf(2, lfopars.Pintensity / 127.0f * 11.0f) - 1.0f; //in centi
 -             phase -= 0.25f; //chance the starting phase
 -             break;
 -     }
 - 
 -     amp1     = (1 - lfornd) + lfornd * RND;
 -     amp2     = (1 - lfornd) + lfornd * RND;
 -     incrnd   = nextincrnd = 1.0f;
 -     computeNextFreqRnd();
 -     computeNextFreqRnd(); //twice because I want incrnd & nextincrnd to be random
 - }
 - 
 - LFO::~LFO()
 - {}
 - 
 - float LFO::baseOut(const char waveShape, const float phase)
 - {
 -     switch(waveShape) {
 -         case LFO_TRIANGLE:
 -             if(phase >= 0.0f && phase < 0.25f)
 -                 return 4.0f * phase;
 -             else if(phase > 0.25f && phase < 0.75f)
 -                 return 2 - 4 * phase;
 -             else
 -                 return 4.0f * phase - 4.0f;
 -             break;
 -         case LFO_SQUARE:
 -             if(phase < 0.5f)
 -                 return -1;
 -             else
 -                 return  1;
 -             break;
 -         case LFO_RAMPUP:    return (phase - 0.5f) * 2.0f;
 -         case LFO_RAMPDOWN:  return (0.5f - phase) * 2.0f;
 -         case LFO_EXP_DOWN1: return powf(0.05f, phase) * 2.0f - 1.0f;
 -         case LFO_EXP_DOWN2: return powf(0.001f, phase) * 2.0f - 1.0f;
 -         case LFO_RANDOM:
 -             if ((phase < 0.5) != first_half) {
 -                 first_half = phase < 0.5;
 -                 last_random = 2*RND-1;
 -             }
 -             return last_random;
 -         default:            return cosf(phase * 2.0f * PI); //LFO_SINE
 -     }
 - }
 - 
 - 
 - float LFO::lfoout()
 - {
 -     //update internals XXX TODO cleanup
 -     if ( ! lfopars_.time || lfopars_.last_update_timestamp == lfopars_.time->time())
 -     {
 -         waveShape = lfopars_.PLFOtype;
 -         int stretch = lfopars_.Pstretch;
 -         if(stretch == 0)
 -             stretch = 1;
 -         const float lfostretch = powf(basefreq_ / 440.0f, (stretch - 64.0f) / 63.0f);
 - 
 -         float lfofreq =
 -             (powf(2, lfopars_.Pfreq * 10.0f) - 1.0f) / 12.0f * lfostretch;
 - 
 -         phaseInc = fabs(lfofreq) * dt_;
 - 
 -         switch(lfopars_.fel) {
 -             case 1:
 -                 lfointensity = lfopars_.Pintensity / 127.0f;
 -                 break;
 -             case 2:
 -                 lfointensity = lfopars_.Pintensity / 127.0f * 4.0f;
 -                 break; //in octave
 -             default:
 -                 lfointensity = powf(2, lfopars_.Pintensity / 127.0f * 11.0f) - 1.0f; //in centi
 -                 //x -= 0.25f; //chance the starting phase
 -                 break;
 -         }
 -     }
 - 
 -     float out = baseOut(waveShape, phase);
 - 
 -     if(waveShape == LFO_SINE || waveShape == LFO_TRIANGLE)
 -         out *= lfointensity * (amp1 + phase * (amp2 - amp1));
 -     else
 -         out *= lfointensity * amp2;
 - 
 -     if(delayTime.inFuture())
 -         return out;
 - 
 -     //Start oscillating
 -     if(deterministic)
 -         phase += phaseInc;
 -     else {
 -         const float tmp = (incrnd * (1.0f - phase) + nextincrnd * phase);
 -         phase += phaseInc * limit(tmp, 0.0f, 1.0f);
 -     }
 -     if(phase >= 1) {
 -         phase    = fmod(phase, 1.0f);
 -         amp1 = amp2;
 -         amp2 = (1 - lfornd) + lfornd * RND;
 - 
 -         computeNextFreqRnd();
 -     }
 - 
 -     float watch_data[2] = {phase, out};
 -     watchOut(watch_data, 2);
 - 
 -     return out;
 - }
 - 
 - /*
 -  * LFO out (for amplitude)
 -  */
 - float LFO::amplfoout()
 - {
 -     return limit(1.0f - lfointensity + lfoout(), -1.0f, 1.0f);
 - }
 - 
 - 
 - void LFO::computeNextFreqRnd()
 - {
 -     if(deterministic)
 -         return;
 -     incrnd     = nextincrnd;
 -     nextincrnd = powf(0.5f, lfofreqrnd) + RND * (powf(2.0f, lfofreqrnd) - 1.0f);
 - }
 
 
  |