Gamma  0.9.5
Generic Synthesis Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
/Users/ljp/code/gamma/trunk/Gamma/Envelope.h
00001 #ifndef GAMMA_ENVELOPE_H_INC
00002 #define GAMMA_ENVELOPE_H_INC
00003 
00004 /*  Gamma - Generic processing library
00005     See COPYRIGHT file for authors and license information */
00006 
00007 #include <math.h>
00008 #include <float.h>
00009 
00010 #include "Gamma/Types.h"
00011 #include "Gamma/gen.h"
00012 #include "Gamma/ipl.h"
00013 #include "Gamma/scl.h"
00014 #include "Gamma/Strategy.h"
00015 #include "Gamma/Sync.h"
00016 
00017 namespace gam{
00018 
00020 
00028 template <class Tv=real, class Tp=real>
00029 class Curve{
00030 public:
00031     Curve();
00032     
00040     Curve(Tp length, Tp curve, Tv end=Tv(1), Tv start=Tv(0));
00041 
00042     bool done() const;              
00043     Tv end() const { return mEnd; } 
00044     Tv value() const;               
00045 
00046     Tv operator()();                
00047     Curve& reset(Tv start=Tv(0));   
00048     Curve& value(const Tv& v);      
00049 
00051     
00056     Curve& set(Tp length, Tp curve, Tv end=Tv(1), Tv start=Tv(0));
00057 
00058 protected:
00059     Tv mEnd, mA, mB;
00060     Tp mMul;
00061 };
00062 
00063 
00064 
00066 
00078 template <int N, class Tv=real, class Tp=real, class Ts=Synced>
00079 class Env : public Ts{
00080 public:
00081 
00082     Env()
00083     :   mSustain(N), mLoop(0)
00084     {
00085         for(int i=0; i<N; ++i){
00086             mLengths[i]= 1e-8;
00087             mCurves[i] =-4;
00088             mLevels[i] = 1e-8;
00089         }   mLevels[N] = 1e-8;
00090         reset();
00091     }
00092 
00094     int size() const { return N; }
00095     
00097     int position() const { return mPos; }
00098     
00100     int sustainPoint() const { return mSustain; }
00101     
00103     int stage() const { return mStage; }
00104     
00106     Tv value() const { return mCurve.value(); }
00107 
00109     bool done() const { return mStage == size(); }
00110     
00112     bool released() const { return mSustain < 0; }
00113     
00115     bool sustained() const { return (mStage == mSustain); }
00116 
00117 
00119     Tv operator()(){
00120         if(sustained()){
00121             return mLevels[mStage];
00122         }
00123         else if(mPos < mLen){
00124             ++mPos;
00125             return mCurve();
00126         }
00127         else if(mStage < size()){
00128             ++mStage;
00129             if(mLoop && done()) mStage=0;
00130             if(!done()){
00131                 mPos = 0;
00132                 setLen(mStage);
00133                 mCurve.set(mLen, mCurves[mStage], mLevels[mStage+1], mLevels[mStage]);
00134                 return (*this)(); // return level of new stage
00135             }
00136         }
00137         return mLevels[mStage];
00138     }   
00139 
00141     void release(){
00142         mSustain = -scl::abs(mSustain);
00143 
00144         // begin release portion immediately starting at current level
00145         Tv curVal = value();
00146         mStage = -mSustain;
00147         if(!done()){
00148             mPos = 0;
00149             setLen(mStage);
00150             mCurve.set(mLen, mCurves[mStage], mLevels[mStage+1], curVal);
00151         }
00152     }
00153 
00154 
00156     Env& loop(bool v){ mLoop=v; return *this; }
00157 
00159     Env& sustainPoint(int v){ mSustain=v; return *this; }
00160 
00162     Env& sustainDisable(){ return sustainPoint(N); }
00163 
00165     void reset(){
00166         // this forces a stage increment upon first iteration
00167         mPos = 0xFFFFFFFF;
00168         mLen = 0;
00169         mStage = -1;
00170         mSustain = scl::abs(mSustain);
00171     }
00172 
00173     
00175     Tp * lengths(){ return mLengths; }
00176 
00178     template <class V>
00179     Env& lengths(const V* vals, int len){
00180         int n = len <= size() ? len : size();
00181         for(int i=0; i<n; ++i) lengths()[i] = vals[i];
00182         return *this;
00183     }
00184     
00186     Env& lengths(Tp a, Tp b){ Tp v[]={a,b}; return lengths(v,2); }
00187 
00189     Env& lengths(Tp a, Tp b, Tp c){ Tp v[]={a,b,c}; return lengths(v,3); }
00190 
00192     Env& lengths(Tp a, Tp b, Tp c, Tp d){ Tp v[]={a,b,c,d}; return lengths(v,4); }
00193 
00195     Env& lengths(Tp a, Tp b, Tp c, Tp d, Tp e){ Tp v[]={a,b,c,d,e}; return lengths(v,5); }
00196 
00198     Tp totalLength() const {
00199         Tp sum=Tp(0);
00200         for(int i=0;i<size();++i) sum += mLengths[i];
00201         return sum;
00202     }
00203     
00205     
00208     Env& totalLength(Tp length, int modSegment){
00209         mLengths[modSegment] = Tp(0);
00210         mLengths[modSegment] = length - totalLength();
00211         return *this;
00212     }
00213 
00215     Env& totalLength(Tp length){
00216         Tp mul = length / totalLength();
00217         for(int i=0; i<size(); ++i){
00218             lengths()[i] *= mul;
00219         }
00220         return *this;
00221     }
00222 
00223 
00225     Tp * curves(){ return mCurves; }
00226     
00228     Env& curve(Tp v){
00229         for(int i=0; i<N; ++i) curves()[i]=v;
00230         return *this;
00231     }
00232 
00233 
00235     Env& segment(int i, Tp len, Tp crv){
00236         mLengths[i]=len;
00237         mCurves [i]=crv;
00238         return *this;
00239     }
00240 
00242     template <class V>
00243     Env& segments(const V* lens, const V* crvs, int len, int begin=0){
00244         int max = size() - begin;
00245         int n = len < max ? len : max;
00246         for(int i=0; i<n; ++i){
00247             segment(i+begin, lens[i], crvs[i]);
00248         }
00249         return *this;
00250     }
00251     
00253     Env& segments(Tp la, Tp ca, Tp lb, Tp cb){
00254         Tp l[]={la,lb}; Tp c[]={ca,cb}; return segments(l,c,2); }
00255 
00257     Env& segments(Tp la, Tp ca, Tp lb, Tp cb, Tp lc, Tp cc){
00258         Tp l[]={la,lb,lc}; Tp c[]={ca,cb,cc}; return segments(l,c,3); }
00259     
00261     Env& segments(Tp la, Tp ca, Tp lb, Tp cb, Tp lc, Tp cc, Tp ld, Tp cd){
00262         Tp l[]={la,lb,lc,ld}; Tp c[]={ca,cb,cc,cd}; return segments(l,c,4); }
00263 
00264 
00266     Tv * levels(){ return mLevels; }
00267 
00269     template <class V>
00270     Env& levels(const V* vals, int len){
00271         int n = len <= size() ? len : size()+1;
00272         for(int i=0; i<n; ++i) levels()[i] = vals[i];
00273         return *this;
00274     }
00275     
00277     Env& levels(Tv a, Tv b){ Tv v[]={a,b}; return levels(v,2); }
00278 
00280     Env& levels(Tv a, Tv b, Tv c){ Tv v[]={a,b,c}; return levels(v,3); }
00281 
00283     Env& levels(Tv a, Tv b, Tv c, Tv d){ Tv v[]={a,b,c,d}; return levels(v,4); }
00284 
00286     Env& levels(Tv a, Tv b, Tv c, Tv d, Tv e){ Tv v[]={a,b,c,d,e}; return levels(v,5); }
00287 
00288 
00289     Env& maxLevel(Tv v){
00290         using namespace gam::scl;
00291         Tv mx(0);
00292         for(int i=0; i<N+1; ++i) mx = max(abs(mLevels[i]), mx);
00293         v = v/mx;
00294         for(int i=0; i<N+1; ++i) mLevels[i] *= v;
00295         return *this;
00296     }
00297 
00298 protected:
00299     Curve<Tv,Tp> mCurve;
00300     Tp mLengths[N];         // segment lengths, in samples
00301     Tp mCurves[N];          // segment curvatures
00302     Tv mLevels[N+1];        // break-point levels
00303 
00304     uint32_t mPos, mLen;    // position in and length of current segment, in samples
00305     int mStage;             // the current curve segment
00306     int mSustain;           // index of sustain point
00307     int mLoop;
00308 
00309     void setLen(int i){ mLen=mLengths[i]*Ts::spu(); }
00310 };
00311 
00312 
00313 
00315 
00319 template <class Tv=real, class Tp=real, class Ts=Synced>
00320 class AD : public Env<2,Tv,Tp,Ts>{
00321 public:
00322     using Env<2,Tv,Tp,Ts>::release;
00323 
00328     AD(Tp att =Tp(0.01), Tp dec =Tp(0.1), Tv amp = Tv(1), Tp crv =Tp(-4))
00329     {
00330         attack(att).decay(dec);
00331         levels(0,amp,0);
00332         curve(crv);
00333     }
00334 
00336     AD& attack(Tp len){ return setLen(0,len); }
00337 
00339     AD& decay(Tp len){ return setLen(1,len); }
00340 
00342     AD& amp(Tv v){ this->levels()[1]=v; return *this; }
00343     
00344 protected:
00345     AD& setLen(int i, Tp v){
00346         this->lengths()[i] = v; return *this;
00347     }
00348 };
00349 
00350 
00352 
00365 template <class Tv=real, class Tp=real, class Ts=Synced>
00366 class ADSR : public Env<3,Tv,Tp,Ts>{
00367 public:
00368     using Env<3,Tv,Tp,Ts>::release;
00369 
00376     ADSR(
00377         Tp att =Tp(0.01), Tp dec =Tp(0.1), Tv sus =Tv(0.7), Tp rel =Tp(1.),
00378         Tv amp =Tv( 1),
00379         Tp crv =Tp(-4)
00380     )
00381     {
00382         this->sustainPoint(2);
00383         levels(0,amp,sus*amp,0);
00384         attack(att).decay(dec).release(rel);
00385         curve(crv);
00386     }
00387 
00389     ADSR& attack(Tp len){ return setLen(0,len); }
00390 
00392     ADSR& decay(Tp len){ return setLen(1,len); }
00393 
00395     ADSR& sustain(Tv val){
00396         this->levels()[2] = val * this->levels()[1];
00397         return *this;
00398     }
00399 
00401     ADSR& release(Tp len){ return setLen(2,len); }
00402     
00404     ADSR& amp(Tv v){ return this->maxLevel(v); }
00405     
00406 protected:
00407     ADSR& setLen(int i, Tp v){
00408         this->lengths()[i] = v; return *this;
00409     }
00410 };
00411 
00412 
00413 
00415 
00421 template <class T=real, class Ts=Synced>
00422 class Decay : public Ts{
00423 public:
00424 
00427     Decay(T decay=T(1), T val=T(1));
00428 
00429     T decay() const;        
00430     bool done(T thresh=T(0.001)) const; 
00431     T value() const;        
00432 
00433     T operator()();         
00434     
00435     void decay(T val);      
00436     void reset();           
00437     void value(T val);      
00438     
00439 protected:
00440     T mVal, mMul, mDcy;
00441 
00442     virtual void onResync(double r);
00443 };
00444 
00445 
00446 
00448 template <class T=real, class Ts=Synced>
00449 class Gate : public Ts{
00450 public:
00451 
00454     Gate(double closingDelay=0, double threshold=0.001)
00455     :   mDelay(closingDelay), mRemain(closingDelay), mThresh(threshold), mClosed(0)
00456     {}
00457 
00459     bool done() const { return mClosed; }
00460 
00462     T operator()(const T& v){       
00463         if(gam::norm(v) < mThresh){
00464             mRemain -= Synced::ups();
00465             if(mRemain <= 0) return close();
00466         }
00467         else{
00468             mRemain = mDelay;
00469         }
00470         return open();
00471     }
00472     
00474     Gate& delay(double v){ mDelay=mRemain=v; return *this; }
00475 
00476 protected:
00477     double mDelay, mRemain;
00478     double mThresh;
00479     int mClosed;
00480     T close(){ mClosed=1; return T(0); }
00481     T  open(){ mClosed=0; return T(1); }
00482 };
00483 
00484 
00485 
00487 template <
00488     class Tv=real,
00489     template <class> class Si=iplSeq::Linear,
00490     class Tp=real,
00491     class Ts=Synced
00492 >
00493 class Seg : public Ts{
00494 public:
00495 
00500     Seg(Tp len=0.5, Tv start=1, Tv end=0, Tp phase=0):
00501         mFreq((Tp)1/len), mAcc(0, phase), mIpl(start)
00502     {
00503         mIpl.push(end);
00504         Ts::initSynced();
00505     }
00506     
00508     bool done() const { return mAcc.val >= Tp(1); }
00509     
00511     Tv operator()(){
00512         Tp f = mAcc.val;
00513         if(done()) return mIpl.val();
00514         mAcc();
00515         return mIpl(scl::min(f, Tp(1)));
00516     }
00517     
00519     void operator= (Tv v){
00520         mIpl.val(mIpl(scl::min(mAcc.val, Tp(1))));
00521         mIpl.push(v);
00522         reset();
00523     }
00524 
00526     
00529     template <class G>
00530     Tv operator()(G& g){
00531         Tp f = mAcc.val;
00532         Tv v;
00533         if(f >= Tp(1)){ v = mIpl.val(); (*this) = g(); }
00534         else{           v = val(); }
00535         mAcc();
00536         return v;
00537     }
00538     
00540     void freq(Tp v){ mFreq = v; mAcc.add = v * Ts::ups(); }
00541     
00543     void period(Tp v){ freq((Tp)1/v); }
00544 
00546     void phase(Tp v){ mAcc = v; }
00547 
00549     void reset(){ phase((Tp)0); }
00550     
00551     Tv val() const { return mIpl(scl::min(mAcc.val, Tp(1))); }
00552     
00553     Si<Tv>& ipol(){ return mIpl; }
00554     
00555 protected:
00556     Tp mFreq;
00557     gen::RAdd<Tp> mAcc;
00558     Si<Tv> mIpl;
00559     
00560     virtual void onResync(double r){ freq(mFreq); }
00561 };
00562 
00563 
00564 
00565 
00567 template <class T=gam::real, class Ts=Synced>
00568 class SegExp : public Ts{
00569 public:
00570 
00575     SegExp(T len, T crv=-3, T start=1, T end=0):
00576         mLen(len), mCrv(crv), mVal1(start), mVal0(end)
00577     {
00578         Ts::initSynced();
00579     }
00580     
00582     bool done() const { return mFnc.value() >= T(1); }
00583     
00585     T operator()(){
00586         if(done()) return mVal0;
00587         return ipl::linear(scl::min(mFnc(), T(1)), mVal1, mVal0);
00588     }
00589     
00591     void operator= (T v){
00592         mVal1 = ipl::linear(scl::min(mFnc.value(), T(1)), mVal1, mVal0);
00593         mVal0 = v;
00594         mFnc.reset();
00595     }
00596     
00598     void curve(T v){ set(mLen, v); }
00599     
00601     void period(T v){ set(v, mCrv); }
00602 
00603     void reset(){ mFnc.reset(); }
00604 
00606     void set(T len, T crv){
00607         mLen = len; mCrv = crv;
00608         mFnc.set(len * Ts::spu(), crv);
00609     }
00610     
00611     virtual void onResync(double r){ set(mLen, mCrv); }
00612     
00613 protected:
00614     T mLen, mCrv, mVal1, mVal0;
00615     Curve<T,T> mFnc;
00616 };
00617 
00618 
00619 
00620 
00621 
00622 // Implementation_______________________________________________________________
00623 
00624 #define TEM template <class Tv,class Tp>
00625 
00626 //---- Curve
00627 TEM Curve<Tv,Tp>::Curve(): mEnd(Tv(1)), mA(Tv(0)), mB(Tv(0)), mMul(Tp(1))
00628 {}
00629 
00630 TEM Curve<Tv,Tp>::Curve(Tp length, Tp curve, Tv end, Tv start){
00631     set(length, curve, end, start);
00632 }
00633 
00634 TEM inline bool Curve<Tv,Tp>::done() const { return scl::abs(mA - mB*mMul) >= scl::abs(end()); }
00635 
00636 TEM inline Tv Curve<Tv,Tp>::value() const { return mA - mB; }
00637 
00638 // dividing by mMul goes back one step
00639 TEM inline Curve<Tv,Tp>& Curve<Tv,Tp>::reset(Tv start){ mB = (mA-start) / mMul; return *this; }
00640 
00641 
00642 // hack to get proper max floating point value
00643 namespace{
00644     template<class T> inline T  eps(){ return T(0.00001  ); }
00645     template<> inline double    eps(){ return   0.00000001; }
00646     template<class T> inline T  maxReal(){ return DBL_MAX; }
00647     template<> inline float     maxReal<float>(){ return FLT_MAX; }
00648 }
00649 
00650 TEM Curve<Tv,Tp>& Curve<Tv,Tp>::set(Tp len, Tp crv, Tv end, Tv start){
00651     static const Tp EPS = eps<Tp>();
00652 
00653     if(len == Tp(0)){ // if length is 0, return end value immediately
00654         mEnd = end;
00655         mMul = maxReal<Tp>();
00656         mA = end;
00657         mB = Tv(0);
00658         return *this;
00659     }
00660 
00661     // Avoid discontinuity when curve = 0 (a line)
00662     if(crv < EPS && crv > -EPS){
00663         crv = crv < Tp(0) ? -EPS : EPS;
00664     }
00665     
00666     Tp crvOverLen = crv / len;
00667     
00668     if(crvOverLen < EPS && crvOverLen > -EPS){
00669         crvOverLen = crvOverLen < Tp(0) ? -EPS : EPS;
00670         crv = crvOverLen * len;
00671     }
00672 
00673     /*
00674     This algorithm uses an exponential curve in [0,1] to linearly interpolate
00675     between the start and end values.
00676     
00677         1 - e^(cx)
00678     y = ---------- * (end-start) + start
00679          1 - e^c
00680 
00681          delta             delta
00682       = ------- + start - ------- e^(cx) 
00683         1 - e^c           1 - e^c
00684     */
00685 
00686     mEnd = end;
00687     mMul = ::exp(crvOverLen);
00688     mA = (end-start) / (Tp(1) - ::exp(crv));
00689     mB = mA / mMul;
00690     mA+= start;
00691     return *this;
00692 }
00693 
00694 TEM inline Curve<Tv,Tp>& Curve<Tv,Tp>::value(const Tv& v){ mB = mA-v; return *this; }
00695 
00696 TEM inline Tv Curve<Tv,Tp>::operator()(){
00697     mB *= mMul;
00698     return value();
00699 }
00700 #undef TEM
00701 
00702 
00703 
00704 #define TM1 template <class T, class Ts>
00705 #define TM2 T,Ts
00706 //---- Decay
00707 
00708 TM1 Decay<TM2>::Decay(T decay_, T val)
00709 :   mVal(val)
00710 {
00711     Ts::initSynced();
00712     decay(decay_);
00713 }
00714 
00715 TM1 inline T Decay<TM2>::operator()(){ T o = mVal; mVal *= mMul; return o; }
00716 
00717 TM1 inline void Decay<TM2>::decay(T v){
00718     mDcy = v;
00719     mMul = scl::t60(v * Ts::spu());
00720 }
00721 
00722 TM1 inline void Decay<TM2>::reset(){ mVal = 1; }
00723 TM1 inline void Decay<TM2>::value(T v){ mVal = v; }
00724 
00725 TM1 inline T Decay<TM2>::decay() const { return mDcy; }
00726 TM1 inline bool Decay<TM2>::done(T thr) const { return mVal < thr; }
00727 TM1 inline T Decay<TM2>::value() const { return mVal; }
00728 
00729 TM1 void Decay<TM2>::onResync(double r){ decay(mDcy); }
00730 
00731 #undef TM1
00732 #undef TM2
00733 
00734 
00735 } // gam::
00736 #endif