Gamma  0.9.5
Generic Synthesis Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
/Users/ljp/code/gamma/trunk/Gamma/Delay.h
00001 #ifndef GAMMA_DELAY_H_INC
00002 #define GAMMA_DELAY_H_INC
00003 
00004 /*  Gamma - Generic processing library
00005     See COPYRIGHT file for authors and license information */
00006 
00007 //#include "Gamma/arr.h"
00008 #include "Gamma/ipl.h"
00009 #include "Gamma/mem.h"
00010 #include "Gamma/scl.h"
00011 //#include "Gamma/tbl.h"
00012 
00013 #include "Gamma/Containers.h"
00014 #include "Gamma/Strategy.h"
00015 #include "Gamma/Sync.h"
00016 #include "Gamma/Types.h"
00017 
00018 namespace gam{
00019 
00020 
00022 
00027 template <class Tv=gam::real, template<class> class Si=ipl::Linear, class Ts=Synced>
00028 class Delay : public ArrayPow2<Tv>, Ts{
00029 public:
00030 
00032     Delay();
00033 
00036     Delay(float delay);
00037 
00041     Delay(float maxDelay, float delay);
00042 
00043 
00044     void delay(float v);                        
00045     void delayUnit(float u);                    
00046     void freq(float v);                         
00047     void ipolType(ipl::Type v){ mIpol.type(v); }
00048     void maxDelay(float v);                     
00049     void zero();                                
00050 
00051     Tv operator()(const Tv& v);                 
00052     Tv operator()() const;                      
00053     Tv read(float ago);                         
00054     void write(const Tv& v);                    
00055     void writePre(const Tv& v);                 
00056     
00057     float delay() const;                        
00058     uint32_t delayIndex(uint32_t delay) const;  
00059     float delayUnit() const;                    
00060     float freq() const { return 1.f/delay(); }  
00061     uint32_t indexBack() const;                 
00062     float maxDelay() const;                     
00063 
00064     virtual void onResize();
00065     virtual void onResync(double r);
00066 
00067     void print();
00068 
00069 protected:
00070     Si<Tv> mIpol;
00071 
00072     float mMaxDelay;                // maximum delay length
00073     float mDelayFactor;             // multiplication factor when setting delay
00074     float mDelayLength;             // current delay length
00075     uint32_t mPhase;                // write tap
00076     uint32_t mPhaseInc;             // phase increment
00077     uint32_t mDelay;                // read tap as delay from write tap
00078 
00079     void incPhase();                // increment phase
00080     void refreshDelayFactor();
00081     uint32_t delayFToI(float v);    // convert f.p. delay to fixed-point
00082 };
00083 
00084 
00085 
00087 template <class Tv=gam::real, template <class> class Si=ipl::Linear, class Ts=Synced>
00088 class Delays : public Delay<Tv,Si,Ts> {
00089 public:
00090 
00094     Delays(float delay, uint32_t numTaps)
00095     :   Delay<Tv,Si,Ts>(delay)
00096     {   taps(numTaps); }
00097 
00099     uint32_t taps() const { return mDelays.size(); }    
00100 
00102     Tv read(uint32_t tap) const {
00103         return mIpol(*this, this->mPhase - mDelays[tap]);
00104     }
00105 
00107     void delay(float length, uint32_t tap){
00108         mDelays[tap] = this->delayFToI(length);
00109     }
00110 
00112     void taps(uint32_t numTaps){ mDelays.resize(numTaps); }
00113 
00114 protected:
00115     std::vector<uint32_t> mDelays;
00116 };
00117 
00118 
00119 
00121 
00124 template <uint32_t N, class T>
00125 class DelayShift{
00126 public:
00127     #define IT for(uint32_t i=0; i<N; ++i)
00128 
00130     DelayShift(const T& v=T()){ IT mElems[i]=v; }
00131 
00133     T& operator[](uint32_t i){ return mElems[i]; }
00134     
00136     const T& operator[](uint32_t i) const { return mElems[i]; }
00137 
00139     T * elems(){ return mElems; }
00140     const T * elems() const { return mElems; }
00141 
00142 
00144     T operator()(const T& v) const {
00145         const T r = mElems[N-1];
00146         for(uint32_t i=N-1; i>0; --i) mElems[i] = mElems[i-1];
00147         mElems[0]=v;
00148         return r;
00149     }
00150 
00152     static uint32_t size(){ return N; }
00153 
00154     #undef IT
00155 
00156 protected:
00157     mutable T mElems[N];
00158 };
00159 
00160 
00162 template<class T=gam::real> 
00163 class Delay1 : public DelayShift<1,T>{
00164 public:
00165 
00167     Delay1(const T& v=T()): DelayShift<1,T>(v){}
00168 };
00169 
00170 
00172 template<class T=gam::real> 
00173 class Delay2 : public DelayShift<2,T>{
00174 public:
00175 
00177     Delay2(const T& v=T()): DelayShift<2,T>(v){}
00178     
00181     Delay2(const T& v2, const T& v1){ (*this)[1]=v2; (*this)[0]=v1; }
00182 };
00183 
00184 
00185 
00187 
00199 // H(z) = (ffd + z^-m) / (1 - fbk z^-m)
00200 // y[n] = ffd x[n] + x[n-m] + fbk y[n-m]
00201 template<
00202     class Tv=gam::real,
00203     template <class> class Si=ipl::Linear,
00204     class Tp=gam::real,
00205     class Ts=Synced
00206 >
00207 class Comb : public Delay<Tv,Si,Ts> {
00208 
00209 private:
00210     typedef Delay<Tv,Si,Ts> Base;
00211 
00212 public:
00213     using Base::operator();
00214 
00216     Comb();
00217 
00222     Comb(float delay, const Tp& ffd = Tp(0), const Tp& fbk = Tp(0));
00223     
00229     Comb(float maxDelay, float delay, const Tp& ffd, const Tp& fbk);
00230 
00231     
00233     
00238     void decay(float units, float end = 0.001f);
00239 
00241     void allPass(const Tp& v);
00242 
00243     void fbk(const Tp& v);                  
00244     void ffd(const Tp& v);                  
00245     void feeds(const Tp& fwd, const Tp& bwd){ ffd(fwd); fbk(bwd); }
00246 
00247     void set(float delay, const Tp& ffd, const Tp& fbk); 
00248 
00249     Tv operator()(const Tv& i0);                
00250     Tv operator()(const Tv& i0, const Tv& oN);  
00251     Tv circulateFbk(const Tv& i0, const Tv& oN);
00252 
00254     Tv nextFbk(const Tv& i0);
00255     
00256     float norm() const;             
00257     float normFbk() const;          
00258     float normFfd() const;          
00259     Tp ffd() const;                 
00260     Tp fbk() const;                 
00261 
00262 protected:
00263     Tp mFFD, mFBK;
00264 };
00265 
00266 
00267 
00268 
00269 // Implementation_______________________________________________________________
00270 
00271 #define TM1 template <class Tv, template <class> class Ti, class Ts>
00272 #define TM2 Tv,Ti,Ts
00273 
00274 #define DELAY_INIT mMaxDelay(0), mDelayFactor(0), mDelayLength(0), mPhase(0), mPhaseInc(0), mDelay(0)
00275 
00276 TM1 Delay<TM2>::Delay()
00277 :   ArrayPow2<Tv>(), DELAY_INIT
00278 {   Ts::initSynced(); }
00279 
00280 TM1 Delay<TM2>::Delay(float maxDelay, float delay)
00281 :   ArrayPow2<Tv>(), DELAY_INIT
00282 {
00283     Ts::initSynced();
00284     this->maxDelay(maxDelay);
00285     this->delay(delay);
00286 }
00287 
00288 TM1 Delay<TM2>::Delay(float delay)
00289 :   ArrayPow2<Tv>(), DELAY_INIT
00290 {   //printf("Delay::Delay(float)\n");
00291     Ts::initSynced();
00292     this->maxDelay(delay);
00293     this->delay(delay);
00294 }
00295 
00296 #undef DELAY_INIT
00297 
00298 TM1 void Delay<TM2>::maxDelay(float length){ //printf("Delay::maxDelay(%f)\n", length);
00299     mMaxDelay = length;
00300     if(Ts::sync() && Ts::sync()->hasBeenSet()){
00301         //printf("Delay::maxDelay(): resize to %d\n", (uint32_t)(mMaxDelay * spu()));
00302         
00303         // This will only trigger onResize() -> onResync(double r) calls if
00304         // the size changes, thereby preventing infinite recursion.
00305         this->resize((uint32_t)(mMaxDelay * Ts::spu()));
00306     }
00307 }
00308 
00309 TM1 void Delay<TM2>::zero(){ this->assign(Tv(0)); }
00310 
00311 TM1 inline Tv Delay<TM2>::operator()() const{ return mIpol(*this, mPhase - mDelay); }
00312 
00313 TM1 inline Tv Delay<TM2>::operator()(const Tv& i0){
00314 //  writePre(i0);
00315 //  return (*this)();
00316     Tv o0 = (*this)();  // read delayed element
00317     write(i0);          // write input element
00318     return o0;
00319 }
00320 
00321 TM1 inline uint32_t Delay<TM2>::delayFToI(float v){
00322     return castIntRound((v * mDelayFactor) * 4294967296.);
00323     //return scl::unitToUInt(v * mDelayFactor);
00324 }
00325 
00326 TM1 inline void Delay<TM2>::incPhase(){ mPhase += mPhaseInc; }
00327 
00328 TM1 void Delay<TM2>::onResize(){ //printf("Delay::onResize %d elements\n", this->size());
00329     mPhaseInc = this->oneIndex();
00330     //for(uint32_t i=0; i<this->size(); ++i) (*this)[i] = Tv(0);
00331     if(this->isSoleOwner()) zero();
00332     onResync(1);
00333 }
00334 
00335 TM1 void Delay<TM2>::onResync(double r){ //printf("Delay::onSyncChange\n");
00336     if(this->usingExternalSource()){
00337         mMaxDelay = this->size() * Ts::ups();
00338     }
00339     else{
00340         maxDelay(mMaxDelay);
00341     }
00342     refreshDelayFactor();
00343     delay(mDelayLength);
00344 }
00345 
00346 TM1 inline Tv Delay<TM2>::read(float ago){ return mIpol(*this, mPhase - delayFToI(ago)); }
00347 
00348 TM1 void Delay<TM2>::refreshDelayFactor(){ mDelayFactor = 1. / maxDelay(); }
00349 
00350 TM1 inline void Delay<TM2>::write(const Tv& v){
00351     mem::put(this->elems(), this->fracBits(), mPhase, v);
00352     incPhase();
00353 }
00354 
00355 TM1 inline void Delay<TM2>::writePre(const Tv& v){
00356     incPhase();
00357     mem::put(this->elems(), this->fracBits(), mPhase, v);
00358 }
00359 
00360 TM1 inline void Delay<TM2>::delay(float v){
00361     mDelayLength = v;
00362     mDelay = delayFToI(v);
00363 }
00364 
00365 TM1 inline float Delay<TM2>::delay() const { return mDelayLength; }
00366 
00367 TM1 inline float Delay<TM2>::delayUnit() const {
00368     return uintToUnit<float>(mDelay);
00369 }
00370 
00371 TM1 inline void Delay<TM2>::delayUnit(float n){ mDelay = unitToUInt(n); }
00372 
00373 TM1 inline uint32_t Delay<TM2>::delayIndex(uint32_t delay) const {
00374     return this->index(mPhase - (delay << this->fracBits()));
00375 }
00376 
00377 TM1 inline void Delay<TM2>::freq(float v){ delay(1.f/v); }
00378 
00379 TM1 inline uint32_t Delay<TM2>::indexBack() const {
00380     return this->index(mPhase + this->oneIndex());
00381 }
00382 
00383 TM1 inline float Delay<TM2>::maxDelay() const { return this->size() * Ts::ups(); }
00384 
00385 TM1 void Delay<TM2>::print(){
00386     printf("SPU:       %f\n", Ts::spu());
00387     printf("Buffer:    %p\n", this->elems());
00388     printf("BufBits:   %d\n", this->log2Size());
00389     printf("FracBits:  %d\n", this->fracBits());
00390     printf("Phase:     %d\n", mPhase);
00391     printf("PhaseInc:  %d\n", mPhaseInc);
00392     printf("Delay:     %d, %f\n", mDelay, mDelayLength);
00393     printf("Max Delay: %f\n",  mMaxDelay);
00394     printf("DlyFactor: %f\n",  mDelayFactor);
00395 }
00396 
00397 #undef TM1
00398 #undef TM2
00399 
00400 
00401 
00402 
00403 #define TM1 template<class Tv, template<class> class Si, class Tp, class Ts>
00404 #define TM2 Tv,Si,Tp,Ts
00405 TM1 Comb<TM2>::Comb(): Delay<Tv,Si,Ts>(), mFFD(0), mFBK(0){}
00406 
00407 TM1 Comb<TM2>::Comb(float delay, const Tp& ffd, const Tp& fbk)
00408 :   Delay<Tv,Si,Ts>(delay), mFFD(ffd), mFBK(fbk)
00409 {}
00410 
00411 TM1 Comb<TM2>::Comb(float delayMax, float delay, const Tp& ffd, const Tp& fbk)
00412 :   Delay<Tv,Si,Ts>(delayMax, delay), mFFD(ffd), mFBK(fbk)
00413 {}
00414 
00415 TM1 inline Tv Comb<TM2>::operator()(const Tv& i0){
00416     return (*this)(i0, (*this)()); }
00417 
00418 TM1 inline Tv Comb<TM2>::operator()(const Tv& i0, const Tv& oN){
00419     Tv t = i0 + oN * mFBK;
00420     this->write(t);
00421     return oN + t * mFFD;
00422 }
00423 
00424 TM1 inline Tv Comb<TM2>::circulateFbk(const Tv& i0, const Tv& oN){
00425     this->write(i0 + oN * mFBK);
00426     return oN;
00427 }
00428 
00429 TM1 inline Tv Comb<TM2>::nextFbk(const Tv& i0){
00430     return circulateFbk(i0, (*this)()); }
00431 
00432 TM1 inline void Comb<TM2>::decay(float units, float end){
00433     mFBK = ::pow(end, this->delay() / scl::abs(units));
00434     if(units < 0.f) mFBK = -mFBK;
00435 }
00436 
00437 TM1 inline void Comb<TM2>::allPass(const Tp& v){ fbk(v); ffd(-v); }
00438 TM1 inline void Comb<TM2>::fbk(const Tp& v){ mFBK=v; }
00439 TM1 inline void Comb<TM2>::ffd(const Tp& v){ mFFD=v; }
00440 TM1 inline void Comb<TM2>::set(float d, const Tp& ff, const Tp& fb){ this->delay(d); ffd(ff); fbk(fb); }
00441 
00442 TM1 inline Tp Comb<TM2>::fbk() const { return mFBK; }
00443 TM1 inline Tp Comb<TM2>::ffd() const { return mFFD; }
00444 TM1 inline float Comb<TM2>::norm() const { return (1.f - scl::abs(fbk()))/(1.f + scl::abs(ffd())); }
00445 TM1 inline float Comb<TM2>::normFbk() const { return 1.f - scl::abs(fbk()); }
00446 TM1 inline float Comb<TM2>::normFfd() const { return 1.f/(1.f + scl::abs(ffd())); }
00447 
00448 #undef TM1
00449 #undef TM2
00450 
00451 } // gam::
00452 #endif