00001 #ifndef GAMMA_EFFECTS_H_INC
00002 #define GAMMA_EFFECTS_H_INC
00003
00004
00005
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
00136 T d1 = i0;
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
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
00300
00301
00302
00303
00304
00305
00307 void pos(T v){
00308
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
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;
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 }
00429 #undef TEM
00430 #endif