Gamma  0.9.5
Generic Synthesis Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
/Users/ljp/code/gamma/trunk/Gamma/Effects.h
00001 #ifndef GAMMA_EFFECTS_H_INC
00002 #define GAMMA_EFFECTS_H_INC
00003 
00004 /*  Gamma - Generic processing library
00005     See COPYRIGHT file for authors and license information */
00006 
00007 #include "Gamma/Delay.h"
00008 #include "Gamma/Envelope.h"
00009 #include "Gamma/Filter.h"
00010 #include "Gamma/Noise.h"
00011 #include "Gamma/Oscillator.h"
00012 
00013 #define TEM template<class T>
00014 
00015 namespace gam{
00016 
00017 
00019 template <class Tv=real, class Tp=real, class Ts=Synced>
00020 struct AmpEnv{
00021 
00023     AmpEnv(Tp freq=10)
00024     :   lpf(freq){}
00025 
00027     Tv operator()(Tv i0){ return lpf(scl::abs(i0)); }
00028 
00030     Tv value() const { return lpf.last(); }
00031     
00032     bool done(Tv eps=0.001) const { return value() < eps; }
00033 
00034     OnePole<Tv,Tp,Ts> lpf;  
00035 };
00036 
00037 
00038 
00040 struct Biquad3{
00042     Biquad3(float f0, float f1, float f2, float q=8, FilterType type=BAND_PASS):
00043         bq0(f0,q,type), bq1(f1,q,type), bq2(f2,q,type){}
00044 
00046     void freq(float f0, float f1, float f2){ bq0.freq(f0); bq1.freq(f1); bq2.freq(f2); }
00047     
00049     float operator()(float i0){ return bq0(i0) + bq1(i0) + bq2(i0); }
00050     
00051     Biquad<> bq0, bq1, bq2;
00052 };
00053 
00054 
00055 
00056 struct Burst{
00057     Burst(float frq1=20000, float frq2=4000, float dec=0.1, float res=2) : 
00058         freq1(frq1), freq2(frq2), fil(frq1, res, BAND_PASS), env(dec)
00059     {}
00060     
00061     float operator()(){
00062         if(env.done()) return 0.f;
00063         fil.freq(freq2 + (freq1-freq2)*env());
00064         return fil(src()) * env.value();
00065     }
00066     
00067     void operator()(float frq1, float frq2, float dec, bool rst=true){
00068         freq1 = frq1; freq2 = frq2; env.decay(dec); if(rst) reset();
00069     }
00070     
00071     void reset(){ env.reset(); }
00072     
00073     float freq1, freq2;
00074     NoiseWhite<RNGMulLinCon> src;
00075     Biquad<> fil;
00076     Decay<float> env;
00077 };
00078 
00079 
00080 
00082 template <class T=gam::real>
00083 struct Chirp{
00087     Chirp(T freq1=220, T freq2=0, T decay=0.2):
00088         osc(freq1), env(decay), freq1(freq1), freq2(freq2)
00089     {}
00090     
00092     T operator()(){
00093         if(env.value() > 0.0001f){
00094             T e = env();
00095             osc.freq(freq2 + (freq1 - freq2) * e);
00096             return osc() * e;
00097         }
00098         return 0.f;
00099     }
00100     
00101     void decay(T v){ env.decay(v); }
00102     void freq(T start, T end){ freq1=start; freq2=end; }
00103     
00104     void operator()(T frq1, T frq2, T dcy, bool doReset=false){
00105         freq1 = frq1; freq2 = frq2; env.decay(dcy); if(doReset) reset();
00106     }
00107     
00109     void reset(){ osc.phase(0); env.reset(); }
00110     
00111     Sine<T> osc;        
00112     Decay<T> env;       
00113     T freq1;            
00114     T freq2;            
00115 };
00116 
00117 
00118 
00120 
00124 template <unsigned N, class T=gam::real> 
00125 struct ChebyN{
00126     T c[N];         
00127     
00128     ChebyN(const T& fundAmp = T(1)){ zero(); c[0]=fundAmp; }
00129     
00131     T operator()(T i0) const { return i0*c[0] + wet(i0); }
00132     
00134     T wet(T i0) const {
00135 //      T d1 = i0 * T(2);   // Chebyshev polynomial of 2nd kind
00136         T d1 = i0;          // Chebyshev polynomial of 1st kind
00137         T d2 = T(1);
00138         T b1 = T(2) * i0;
00139         
00140         T o0 = T(0);
00141         for(unsigned i=1; i<N; ++i){
00142             T d0 = b1 * d1 - d2;
00143             d2 = d1;
00144             d1 = d0;
00145             o0 += d0 * c[i];
00146         }
00147         return o0;
00148     }
00149     
00151     unsigned size() const { return N; }
00152 
00154     T& coef(int i){ return c[i]; }
00155 
00157     template <class V>
00158     ChebyN& set(const V* weights){
00159         for(unsigned i=0; i<N; ++i) c[i] = weights[i];
00160         return *this;
00161     }
00162 
00164     ChebyN& zero(){
00165         for(unsigned i=0; i<N; ++i) c[i] = T(0);
00166         return *this;
00167     }
00168 };
00169 
00170 
00171 
00173 template <class T=gam::real>
00174 struct Chorus{
00180     Chorus(float delay=0.0021, float depth=0.002, float freq=1, float ffd=0.9, float fbk=0.1):
00181         comb1(delay + depth, delay, ffd, fbk),
00182         comb2(delay + depth, delay, ffd, fbk),
00183         mod(double(freq), double(depth)),
00184         delay(delay)
00185     {}
00186 
00187     Chorus& fbk(float v){ comb1.fbk(v); comb2.fbk(v); return *this; }
00188     Chorus& ffd(float v){ comb1.ffd(v); comb2.ffd(v); return *this; }
00189     Chorus& freq(float v){ mod.freq(v); return *this; }
00190     Chorus& depth(float v){ mod.amp(v); return *this; }
00191 
00193     T operator()(const T& v){
00194         modulate(); return (comb1(v) + comb2(v)) * 0.5f;
00195     }
00196     
00198     void operator()(const T& in, T& o1, T& o2){
00199         (*this)(in,in, o1,o2);
00200     }
00201 
00203     template <class V>
00204     Vec<2,V> operator()(const Vec<2,V>& v){
00205         modulate();
00206         return Vec<2,V>(comb1(v[0]), comb2(v[1]));
00207     }
00208     
00210     void operator()(const T& i1, const T& i2, T& o1, T& o2){
00211         modulate(); o1=comb1(i1); o2=comb2(i2);
00212     }
00213     
00215     void modulate(){
00216         comb1.delay(delay + mod.val.r); comb2.delay(delay + mod.val.i); mod();
00217     }
00218 
00219     Comb<T, ipl::Cubic> comb1, comb2;       
00220     CSine<double> mod;                      
00221     float delay;                            
00222 };
00223 
00224 
00225 
00227 template <class T=gam::real>
00228 struct FreqShift{
00229 
00230     FreqShift(float shift=1): mod(shift){}
00231 
00232     T operator()(T in){
00233         return (hil(in) * mod()).r;
00234     }
00235     
00236     void freq(T v){ mod.freq(v); }
00237 
00238     CSine<T> mod;
00239     Hilbert<T> hil;
00240 };
00241 
00242 
00243 
00244 // Saw oscillator with sweepable filter.
00245 struct MonoSynth{
00246     MonoSynth(float freq=440, float dur=0.8, float ctf1=1000, float ctf2=100, float res=3):
00247         osc(freq), filter(ctf1, res), env(dur), opEnv(100), ctf1(ctf1), ctf2(ctf2)
00248     {}
00249 
00250     float operator()(){
00251         if(env.done()) return 0.f;
00252 
00253         float e = opEnv(env());
00254         filter.freq(ctf2 + (ctf1 - ctf2) * e);
00255         float smp = osc() * e;
00256         return filter(smp);
00257     }
00258     
00259     void freq(float v){ osc.freq(v); }
00260     
00261     void reset(){ env.reset(); }
00262 
00263     Saw<float> osc;
00264     Biquad<> filter;
00265     Decay<float> env;
00266     OnePole<float> opEnv;
00267     float ctf1, ctf2;
00268 };
00269 
00270 
00271 
00273 template <class T=gam::real>
00274 class Pan{
00275 public:
00276 
00278     Pan(T pos=0){ this->pos(pos); }
00279 
00281     Vec<2,T> operator()(T in){
00282         return Vec<2,T>(in*w1, in*w2);
00283     }   
00284 
00286     template <class V>
00287     void operator()(T in, V& out1, V& out2){
00288         out1 = in*w1; out2 = in*w2;
00289     }
00290 
00292     template <class V>
00293     void operator()(T in1, T in2, V& out1, V& out2){
00294         out1 = in1*w1 + in2*w2;
00295         out2 = in1*w2 + in2*w1;
00296     }
00297 
00299 //  void pos(T v){
00300 //      v = scl::clip(v, (T)1, (T)-1);
00301 //      v = (v+T(1))*M_PI_4;    // put in [0, pi/2]
00302 //      w1 = cos(v);
00303 //      w2 = sin(v); 
00304 //  }
00305 
00307     void pos(T v){
00308         // gives correct result at -1, 0, and 1
00309         static const T c0 = 1./sqrt(2);
00310         static const T c1 = 0.5 - c0;
00311         static const T c2 =-0.5/c1;
00312         v = scl::clip(v, T(1), T(-1));
00313         //w1 = (T)-0.25 * v * (v + (T)2) + (T)0.75;
00314         w1 = c1 * v * (v + c2) + c0;
00315         w2 = w1 + v;
00316     }
00317 
00319     void posL(T v){
00320         v = scl::clip(v, T(1), T(-1));
00321         w1 = -v * T(0.5) + T(0.5);
00322         w2 = w1 + v; 
00323     }
00324 
00325 protected:
00326     T w1, w2; // channel weights
00327 };
00328 
00329 
00330 
00332 struct Pluck{
00333     Pluck(double freq=440, double decay=0.99)
00334     :   env(0.1), fil(3000, 1, LOW_PASS), comb(1./27.5, 1./freq, 1, decay)
00335     {}
00336     
00337     float operator()(){ return comb(fil(noise() * env())); }
00338     float operator()(float in){ return comb(fil(in * env())); }
00339     void reset(){ env.reset(); }
00340     void freq(float v){ comb.freq(v); }
00341     
00342     NoiseWhite<> noise;
00343     Decay<> env;
00344     Biquad<> fil;
00345     Comb<> comb;
00346 };
00347 
00348 
00349 
00351 template <class T=gam::real>
00352 class Quantizer : public Synced{
00353 public:
00356     Quantizer(double freq=2000, T step=0);
00357 
00358     void freq(double value);    
00359     void period(double value);  
00360     void step(T value);         
00361 
00362     T operator()(T input);      
00363     
00364     virtual void onResync(double r);
00365 
00366 private:
00367     T mHeld;
00368     double mCount, mSamples, mPeriod;
00369     T mStep, mStepRec;
00370     bool mDoStep;
00371 };
00372 
00373 TEM Quantizer<T>::Quantizer(double freq, T step)
00374 :   mPeriod(1./freq)
00375 {
00376     this->step(step);
00377 }
00378 
00379 TEM inline void Quantizer<T>::freq(double v){ period(1./v); }
00380 
00381 TEM inline void Quantizer<T>::period(double v){
00382     mPeriod = v;
00383     mSamples = v * spu();
00384     if(mSamples < 1.) mSamples = 1.;
00385 }
00386 
00387 TEM inline void Quantizer<T>::step(T v){
00388     mStep = v;
00389     mDoStep = mStep > 0.;
00390     if(mDoStep) mStepRec = 1./mStep;
00391 }
00392 
00393 TEM inline T Quantizer<T>::operator()(T vi){
00394     if(++mCount >= mSamples){
00395         mCount -= mSamples;
00396         mHeld = mDoStep ? scl::round(vi, mStep, mStepRec) : vi;
00397     }
00398     return mHeld;
00399 }
00400 
00401 TEM void Quantizer<T>::onResync(double r){
00402     period(mPeriod);
00403 }
00404 
00405 
00406 
00408 
00412 template <class T=gam::real>
00413 struct Threshold{
00416     Threshold(T thresh, T freq=10):lpf(freq), thresh(thresh){}
00417     
00419     T operator()(T i0){ return lpf(scl::abs(i0) > thresh ? T(1) : T(0)); }
00420     
00422     T inv(T i0){ return lpf(scl::abs(i0) > thresh ? T(0) : T(1)); }
00423     
00424     OnePole<T> lpf; 
00425     T thresh;       
00426 };
00427 
00428 } // gam::
00429 #undef TEM
00430 #endif