Gamma  0.9.5
Generic Synthesis Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
/Users/ljp/code/gamma/trunk/Gamma/Strategy.h
00001 #ifndef GAMMA_STRATEGY_H_INC
00002 #define GAMMA_STRATEGY_H_INC
00003 
00004 /*  Gamma - Generic processing library
00005     See COPYRIGHT file for authors and license information */
00006 
00007 #include "Gamma/Access.h"
00008 #include "Gamma/Containers.h"
00009 #include "Gamma/ipl.h"
00010 #include "Gamma/scl.h"
00011 
00012 namespace gam{
00013 namespace ipl{
00014 
00016 template <class T>
00017 struct Trunc{
00018 
00019     ipl::Type type() const { return TRUNC; }
00020     void type(ipl::Type v){}
00021 
00023     T operator()(const ArrayPow2<T>& a, uint32_t phase) const{
00024         return a.atPhase(phase);
00025     }
00026 
00027     template <class AccessStrategy>
00028     T operator()(const AccessStrategy& s, const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{
00029         return a[iInt];
00030     }
00031 
00032     T operator()(const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{
00033         return (*this)(acc::Wrap(), a,iInt,iFrac, max,min);
00034     }
00035 };
00036 
00037 
00039 template <class T>
00040 struct Round{
00041 
00042     ipl::Type type() const { return ROUND; }
00043     void type(ipl::Type v){}
00044 
00046     T operator()(const ArrayPow2<T>& a, uint32_t phase) const{
00047 
00048         // accessing normally truncates, so add half fraction to round
00049         return a.atPhase(phase + (a.oneIndex()>>1));
00050     }
00051     
00052     template <class AccessStrategy>
00053     T operator()(const AccessStrategy& s, const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{
00054         return ipl::nearest(
00055             iFrac,
00056             a[iInt],
00057             a[s.mapP1(iInt+1, max, min)]
00058         );
00059     }
00060 
00061     T operator()(const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{
00062         return (*this)(acc::Wrap(), a, iInt, iFrac, max, min);
00063     }
00064 };
00065 
00066 
00068 template <class T>
00069 struct Linear{
00070 
00071     ipl::Type type() const { return LINEAR; }
00072     void type(ipl::Type v){}
00073 
00075     T operator()(const ArrayPow2<T>& a, uint32_t phase) const{
00076         return ipl::linear(
00077             a.fraction(phase),
00078             a.atPhase(phase),
00079             a.atPhase(phase + a.oneIndex())
00080         );
00081     }
00082 
00083     template <class AccessStrategy>
00084     T operator()(const AccessStrategy& s, const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{     
00085         return ipl::linear(
00086             iFrac,
00087             a[iInt],
00088             a[s.mapP1(iInt+1, max, min)]
00089         );
00090     }
00091 
00092     T operator()(const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{
00093         return (*this)(acc::Wrap(), a, iInt, iFrac, max, min);
00094     }   
00095 
00096 };
00097 
00098 
00100 template <class T>
00101 struct Cubic{
00102 
00103     ipl::Type type() const { return CUBIC; }
00104     void type(ipl::Type v){}
00105 
00107     T operator()(const ArrayPow2<T>& a, uint32_t phase) const{
00108         uint32_t one = a.oneIndex();
00109         return ipl::cubic(
00110             a.fraction(phase),
00111             a.atPhase(phase - one),
00112             a.atPhase(phase),
00113             a.atPhase(phase + one),
00114             a.atPhase(phase + (one<<1))
00115         );
00116     }
00117     
00118     template <class AccessStrategy>
00119     T operator()(const AccessStrategy& s, const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{     
00120         return ipl::cubic(
00121             iFrac,
00122             a[s.mapM1(iInt-1, max, min)],
00123             a[iInt],
00124             a[s.mapP1(iInt+1, max, min)],
00125             a[s.map  (iInt+2, max, min)]
00126         );
00127     }
00128 
00129     T operator()(const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{
00130         return (*this)(acc::Wrap(), a, iInt,iFrac, max,min);
00131     }
00132 
00133 /*
00134     // TODO: is it worth trying to support strided arrays?
00135     template <class AccessStrategy>
00136     T operator()(const AccessStrategy& s, const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min, index_t str) const{      
00137         return ipl::cubic(
00138             iFrac,
00139             a[s.map(iInt-str, max, min)],
00140             a[iInt],
00141             a[s.map(iInt+str, max, min)],
00142             a[s.map(iInt+(str<<1), max, min)]
00143         );
00144     }
00145 
00146     T operator()(const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min, index_t str) const{
00147         return (*this)(acc::Wrap(), a, iInt,iFrac, max,min,str);
00148     }
00149 */
00150 };
00151 
00152 
00154 template <class T>
00155 struct AllPass{
00156 
00157     AllPass(T prev=0): prev(prev){}
00158 
00159     ipl::Type type() const { return ALLPASS; }
00160     void type(ipl::Type v){}
00161 
00163     T operator()(const ArrayPow2<T>& a, uint32_t phase) const{
00164         return ipl::allpass(
00165             a.fraction(phase), 
00166             a.atPhase(phase), 
00167             a.atPhase(phase + a.oneIndex()),
00168             prev
00169         );
00170     }
00171     
00172     template <class AccessStrategy>
00173     T operator()(const AccessStrategy& s, const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{     
00174         return ipl::allpass(
00175             iFrac,
00176             a[iInt],
00177             a[s.mapP1(iInt+1, max, min)],
00178             prev
00179         );
00180     }
00181 
00182     T operator()(const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{
00183         return (*this)(acc::Wrap(), a, iInt,iFrac, max,min);
00184     }
00185     
00186     mutable T prev;
00187 };
00188 
00189 
00191 template <class T>
00192 struct Any{
00193 
00194     Any(): mType(TRUNC){}
00195     
00196     ipl::Type type() const { return mType; }
00197     void type(ipl::Type v){ mType=v; }
00198 
00200     T operator()(const ArrayPow2<T>& a, uint32_t phase) const{      
00201         switch(mType){
00202             case ROUND:     return round    (a, phase);
00203             case LINEAR:    return linear   (a, phase);
00204             case CUBIC:     return cubic    (a, phase);
00205             case ALLPASS:   return allpass  (a, phase);
00206             default:        return trunc    (a, phase);
00207         }
00208     }
00209 
00210     template <class AccessStrategy>
00211     T operator()(const AccessStrategy& s, const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{
00212         switch(mType){
00213             case ROUND:     return round    (s,a,iInt,iFrac,max,min);
00214             case LINEAR:    return linear   (s,a,iInt,iFrac,max,min);
00215             case CUBIC:     return cubic    (s,a,iInt,iFrac,max,min);
00216             case ALLPASS:   return allpass  (s,a,iInt,iFrac,max,min);
00217             default:        return trunc    (s,a,iInt,iFrac,max,min);
00218         }
00219     }
00220 
00221     T operator()(const Array<T>& a, index_t iInt, double iFrac, index_t max, index_t min=0) const{
00222         switch(mType){
00223             case ROUND:     return round    (a,iInt,iFrac,max,min);
00224             case LINEAR:    return linear   (a,iInt,iFrac,max,min);
00225             case CUBIC:     return cubic    (a,iInt,iFrac,max,min);
00226             case ALLPASS:   return allpass  (a,iInt,iFrac,max,min);
00227             default:        return trunc    (a,iInt,iFrac,max,min);
00228         }
00229     }
00230 
00231 protected:
00232     ipl::Type mType;
00233     Trunc<T> trunc;
00234     Round<T> round;
00235     Linear<T> linear;
00236     Cubic<T> cubic;
00237     AllPass<T> allpass;
00238 };
00239 
00240 } // ipl::
00241 
00242 
00243 
00245 
00246 // interface:
00247 // 
00248 // method       desc
00249 // ()           return value at fraction
00250 // push         push new value into interpolation window 
00251 namespace iplSeq{
00252 
00254     template <uint32_t N, class T>
00255     struct Base{
00256         Base(const T& v=0){ set(v); }
00257     
00259         void push(T va){ for(uint32_t i=N-1; i>0; --i) v[i]=v[i-1]; v[0]=va; }
00260         
00262         void set(T va){ for(uint32_t i=0; i<N; ++i) v[i]=va; }  
00263         
00265         T val() const { return v[0]; }
00266         
00268         void val(const T& va){ v[0]=va; }
00269             
00270         T v[N]; 
00271     };
00272 
00274     template <class T>
00275     struct Trunc : public Base<1,T>{
00276         using Base<1,T>::v;
00277         Trunc(const T& v=0): Base<1,T>(v){}
00278         T operator()(float f) const { return v[0]; }
00279     };
00280     
00282     template <class T>
00283     struct Linear : public Base<2,T>{
00284         using Base<2,T>::v;
00285         Linear(const T& v=0): Base<2,T>(v){}
00286         T operator()(float f) const { return ipl::linear(f, v[1], v[0]); }
00287     };
00288 
00290     template <class T>
00291     struct Cubic : public Base<4,T>{
00292         using Base<4,T>::v;
00293         Cubic(const T& v=0): Base<4,T>(v){}
00294         T operator()(float f) const { return ipl::cubic(f, v[3], v[2], v[1], v[0]); }
00295         T val() const { return v[1]; }
00296         void val(const T& va){ v[1]=va; }
00297     };
00298 
00300     template <class T>
00301     struct Cosine : public Base<2,T>{
00302         using Base<2,T>::v;
00303         Cosine(const T& v=0): Base<2,T>(v){}
00304         T operator()(float f) const { return ipl::linear(scl::mapSinUU(f), v[1], v[0]); }
00305     };
00306 
00307 } // iplSeq::
00308 
00309 
00310 
00312 
00313 // The expected interface is:
00314 //  void operator()(uint32_t& pos, uint32_t inc);   // fixed-point tap increment
00315 //  bool done(uint32_t pos);                        // fixed-point tap done reading
00316 //  T operator()(T v, T max, T min);                // float tap post increment check
00317 //  void reset();                                   // reset internal state, if any
00318 namespace tap{
00319 
00321     struct Clip{
00322         void reset(){}
00323     
00324         uint32_t& operator()(uint32_t& pos, uint32_t inc){
00325             uint32_t prev = pos;
00326             pos += inc;
00327             if(~pos & prev & 0x80000000) pos = 0xffffffff;
00328             // pos3:    1101    inc = 0001
00329             // pos2:    1110
00330             // pos1:    1111
00331             // pos0:    0000    msb goes from 1 to 0
00332             return pos;
00333         }
00334         bool done(uint32_t pos) const { return pos == 0xffffffff; }
00335         
00336         template <class T>
00337         T operator()(T v, T inc, T max, T min){ return scl::clip(v+inc, max, min); }
00338     };
00339 
00341     struct Fold{
00342         Fold(): dir(0){}
00343     
00344         void reset(){ dir=0; }
00345     
00346         uint32_t& operator()(uint32_t& pos, uint32_t inc){
00347             uint32_t prev = pos;
00348             pos += dir ? -inc : inc;
00349             if(~pos & prev & 0x80000000) dir^=1;
00350             return pos;
00351         }
00352 
00353         bool done(uint32_t pos) const { return false; }
00354         
00355         template <class T>
00356         T operator()(T v, T inc, T max, T min){     
00357             v += dir ? -inc : inc;
00358             long n;
00359             v = scl::fold(v, n, max, min);
00360             dir ^= n!=0;
00361             return v;
00362         }
00363         
00364         uint32_t dir;
00365     };
00366 
00367 
00369     struct Pat{
00370     
00371         Pat(){
00372             pattern(0,0);
00373             reset();
00374         }
00375     
00376         void reset(){ mPhase=0; mIndex=0; }
00377 
00378         uint32_t& operator()(uint32_t& pos, uint32_t inc){
00379             uint32_t prev = mPhase;
00380             mPhase += inc;
00381 
00382             // Check MSB goes from 1 to 0
00383             // TODO: works only for positive increments
00384             if((~mPhase & prev) & 0x80000000){
00385                 if(++mIndex >= mSize) mIndex=0;
00386             }
00387 
00388             uint32_t bit = (mPattern >> (mSize-1 - mIndex)) & 1UL;
00389             if(bit){
00390                 pos = mPhase;
00391             }
00392             return pos;
00393         }
00394         
00395         Pat& pattern(uint32_t bits, uint16_t size){
00396             mPattern=bits;
00397             mSize=size;
00398             return *this;
00399         }
00400         
00401         Pat& pattern(const char* bits){
00402             mSize = strlen(bits);
00403             mPattern = 0;
00404             for(int i=0; i<mSize; ++i){
00405                 mPattern |= (bits[i]!='.') << (mSize-1-i);
00406             }
00407             return *this;
00408         }
00409         
00410     private:
00411         uint32_t mPhase;
00412         uint32_t mPattern;
00413         uint16_t mIndex;
00414         uint16_t mSize;
00415     };
00416 
00417 
00419     struct Rep{
00420         Rep(){ number(1); reset(); }
00421         
00422         void reset(){ mCount=0; }
00423 
00424         uint32_t& operator()(uint32_t& pos, uint32_t inc){
00425             uint32_t prev = pos;
00426             pos += inc;
00427             
00428             // Check MSB goes from 1 to 0
00429             // TODO: works only for positive increments and non-zero mNumber
00430             if((~pos & prev) & 0x80000000){
00431                 if(++mCount >= mNumber) pos = 0xffffffff;
00432             }
00433             return pos;
00434         }
00435         
00436         bool done(uint32_t pos) const { return (mCount >= mNumber) && (pos == 0xffffffff); }
00437         
00438         template <class T>
00439         T operator()(T v, T inc, T max, T min){
00440             v += inc;
00441             if(v >= max || v < min) ++mCount;
00442             return mCount < mNumber ? scl::wrap(v, max, min) : scl::clip(v, max, min);
00443         }
00444         
00445         // Set number of repetitions
00446         Rep& number(uint32_t v){ mNumber=v; return *this; }
00447 
00448     private:
00449         uint32_t mNumber;
00450         uint32_t mCount;
00451     };
00452 
00453 
00455     struct Wrap{
00456         void reset(){}
00457     
00458         uint32_t& operator()(uint32_t& pos, uint32_t inc){ return pos+=inc; }
00459         bool done(uint32_t pos) const { return false; }
00460         
00461         template <class T>
00462         T operator()(T v, T inc, T max, T min){ return scl::wrap(v+inc, max, min); }
00463     };
00464 
00465 } // tap::
00466 
00467 } // gam::
00468 #endif