00001 #ifndef GAMMA_ENVELOPE_H_INC
00002 #define GAMMA_ENVELOPE_H_INC
00003
00004
00005
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)();
00135 }
00136 }
00137 return mLevels[mStage];
00138 }
00139
00141 void release(){
00142 mSustain = -scl::abs(mSustain);
00143
00144
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
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];
00301 Tp mCurves[N];
00302 Tv mLevels[N+1];
00303
00304 uint32_t mPos, mLen;
00305 int mStage;
00306 int mSustain;
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
00623
00624 #define TEM template <class Tv,class Tp>
00625
00626
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
00639 TEM inline Curve<Tv,Tp>& Curve<Tv,Tp>::reset(Tv start){ mB = (mA-start) / mMul; return *this; }
00640
00641
00642
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)){
00654 mEnd = end;
00655 mMul = maxReal<Tp>();
00656 mA = end;
00657 mB = Tv(0);
00658 return *this;
00659 }
00660
00661
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
00675
00676
00677
00678
00679
00680
00681
00682
00683
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
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 }
00736 #endif