Gamma  0.9.5
Generic Synthesis Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
/Users/ljp/code/gamma/trunk/Gamma/UnitMaps.h
00001 #ifndef GAMMA_UNITMAPS_H_INC
00002 #define GAMMA_UNITMAPS_H_INC
00003 
00004 /*  Gamma - Generic processing library
00005     See COPYRIGHT file for authors and license information */
00006 
00007 #include <math.h>
00008 #include <map>
00009 #include <vector>
00010 #include "Gamma/scl.h"
00011 #include "Gamma/Access.h"
00012 #include "Gamma/Strategy.h"
00013 #include "Gamma/Types.h"
00014 
00015 namespace gam{
00016 
00017 
00019 template<
00020     class T,
00021     template<class> class Sipl=ipl::Linear,
00022     class Sacc=acc::Wrap,
00023     class A=gam::Allocator<T>
00024 >
00025 class FunctionTable : public Array<T,A>{
00026     typedef Array<T,A> Base;
00027 public:
00028     using Base::elems; using Base::size;
00029 
00030 
00032 
00035     explicit FunctionTable(uint32_t size=2048, const T& init=T(0))
00036     :   Base(size, init)
00037     {
00038         endpoints(0, size);
00039     }
00040     
00041     virtual ~FunctionTable(){}
00042     
00044     Array<T,A>& array(){ return *this; }
00045     const Array<T,A>& array() const { return *this; }
00046 
00048     T operator()(double x) const {
00049 
00050         x = scl::wrap(x);
00051         double f;
00052 //      index_t i1 = mIndMap(x, f);
00053 //      return mIpl(mAcc, *this, i1,f, size()-1);
00054         index_t i1 = mIndMap(x, f) + mInterval.min();
00055         return mIpl(mAcc, *this, i1,f, mInterval.max(), mInterval.min());
00056 
00057         //int i2 = i1+1; if(i2==size()) i2=0;
00058         //return (*this)[i1]*(1.f-f) + (*this)[i2]*f;
00059     }
00060 
00061 
00063     FunctionTable& endpoints(index_t min, index_t max){
00064         mInterval.endpoints(min, max-1); // interpolator max index is inclusive
00065         mIndMap.max(max-min, 1.);
00066         return *this;
00067     }
00068 
00069 
00071     template <class Gen>
00072     FunctionTable& operator+=(Gen& g){
00073         for(uint32_t i=0; i<size(); ++i) (*this)[i] += g();
00074         return *this;
00075     }
00076 
00077     template <class Gen>
00078     FunctionTable& operator+=(const Gen& g){
00079         for(uint32_t i=0; i<size(); ++i) (*this)[i] += g();
00080         return *this;
00081     }
00082 
00083 protected:
00084     IndexMap<double> mIndMap;
00085     Interval<index_t> mInterval;
00086     Sipl<T> mIpl;
00087     Sacc mAcc;
00088 
00089     virtual void onResize(){ mIndMap.max(size(), 1.); }
00090 };
00091 
00092 
00093 
00094 // Fixed-size power of 2 table supporting fixed point lookup
00095 
00096 // This table minimizes memory usage and table look-up speed at the expense
00097 // of having a fixed size that is a power of two.
00098 template <uint32_t B, class T>
00099 class TablePow2{
00100 public:
00101 
00102     enum{ N = 1<<B };
00103 
00104     const T& operator[](unsigned i) const { return mElems[i]; }
00105     T& operator[](unsigned i){ return mElems[i]; }
00106 
00108     
00111     const T& read(double phase) const {
00112         return read(phaseR2I(phase));
00113     }
00114 
00116     const T& read(uint32_t phase) const {
00117         return (*this)[phase >> shift()];
00118     }
00119 
00121     T readL(uint32_t phase) const {
00122         const T& lo = read(phase);
00123         const T& hi = read(phase + oneIndex());
00124         float fr = gam::fraction(bits(), phase);
00125         return lo + (hi - lo)*fr;
00126     }
00127 
00128     static uint32_t mask(){ return N-1; }
00129     static uint32_t size(){ return N; }
00130     static uint32_t bits(){ return B; }
00131     static uint32_t shift(){ return 32U-B; }
00132     static uint32_t oneIndex(){ return 1<<shift(); }
00133 
00134 protected:
00135     T mElems[N];
00136     static uint32_t phaseR2I(double v){ return static_cast<uint32_t>(v * 4294967296.); }
00137 };
00138 
00139 
00140 
00141 // Complex sinusoid table
00142 // B is the log2 size of each table
00143 // D is the number of tables
00144 // The effective table size is (2^B)^D
00145 template <unsigned B=10, unsigned D=2, class TComplex=Complex<double> >
00146 class CSinTable{
00147 public:
00148     typedef TablePow2<B, TComplex> Arc;
00149 
00150     CSinTable(){ init(); }
00151     
00153     TComplex operator()(double phase){
00154         return (*this)(uint32_t(phase * 4294967296.));
00155     }
00156     
00158     TComplex operator()(uint32_t p){
00159 
00160         p >>= shift();
00161 
00162         // start with finest sample
00163         TComplex r(arc(D-1)[p & Arc::mask()]);
00164 
00165         // iterate remaining arcs (fine to coursest)
00166         for(unsigned i=2; i<D+1; ++i){
00167             p >>= B;
00168             r *= arc(D-i)[p & Arc::mask()];
00169         }
00170         return r;
00171     }
00172     
00173     static uint32_t shift(){ return 32U - (B*D); }
00174 
00175 private:
00176     enum{ M = Arc::N };
00177 
00178     // Get pointer to complex arc tables
00179     static Arc * arcs(){
00180         static Arc tables[D]; // higher index = finer resolution
00181         return tables;
00182     }
00183     
00184     static Arc& arc(unsigned res){ return arcs()[res]; }
00185     
00186     static void init(){
00187         static bool tabulate=true;
00188         if(tabulate){
00189             tabulate=false;
00190             unsigned long long N = M;
00191             
00192             for(unsigned j=0; j<D; ++j){        // iterate resolution (course to fine)
00193                 for(unsigned i=0; i<M; ++i){    // iterate arc of unit circle
00194                     double p = (i*M_PI)/(N>>1);
00195                     arc(j)[i].real() = cos(p);
00196                     arc(j)[i].imag() = sin(p);
00197                 }
00198                 N *= M;
00199             }
00200             
00201         }
00202     }
00203 };
00204 
00205 
00206 
00208 template <class T>
00209 class UnitMapper{
00210 public:
00211 
00213     enum MapType{
00214         MAP_LIN,        
00215         MAP_POW,        
00216         MAP_EXP2        
00217     };
00218 
00219 
00220     T min, max, p1;
00221     MapType type;
00222     bool clip;
00223 
00224 
00225     UnitMapper();
00226     
00232     UnitMapper(T max, T min=0., T p1=1., MapType type = MAP_POW, bool clip=true);
00233 
00234 
00236     UnitMapper& set(T max, T min=0., T p1=1., MapType type = MAP_POW, bool clip=true);
00237     
00238     T map(T unit);          
00239     T unmap(T value);       
00240     
00241 private:
00242     T mapLin (T u);
00243     T mapPow (T u); // Map normal directly using power function
00244     T mapExp2(T u); // Map normal directly using exponentiation function
00245     
00246     // clip input normal (or not)
00247     void doClip(T& nrm){ if(clip) nrm = scl::clip(nrm); }
00248 };
00249 
00250 
00251 
00252 
00253 // Implementation ______________________________________________________________
00254 
00255 template <class T> UnitMapper<T>::UnitMapper(){
00256     set(T(1));
00257 }
00258 
00259 template <class T> UnitMapper<T>::UnitMapper(T max, T min, T p1, MapType type, bool clip){
00260     set(max, min, p1, type, clip);
00261 }
00262 
00263 template <class T> UnitMapper<T>& UnitMapper<T>::set(T max, T min, T p1, MapType type, bool clip){
00264     this->max = max;
00265     this->min = min;
00266     this->p1 = p1;
00267     this->type = type;
00268     this->clip = clip;
00269     return *this;
00270 }
00271 
00272 template <class T> inline T UnitMapper<T>::map(T u){
00273     switch(type){
00274     case MAP_LIN:   return mapLin(u);
00275     case MAP_POW:   return mapPow(u);
00276     case MAP_EXP2:  return mapExp2(u);
00277     default:;
00278     }
00279 }
00280 
00281 template <class T> T UnitMapper<T>::unmap(T v){
00282     switch(type){
00283     case MAP_LIN:
00284         return scl::mapLin(v, min, max, T(0), T(1));
00285 
00286     case MAP_POW:
00287         v = scl::mapLin(v, min, max, T(0), T(1));
00288         return pow(v, 1. / p1);
00289         //return mapPow(pow(v, 1. / p1));
00290 
00291     case MAP_EXP2:
00292         v = log2(v / p1);
00293         return scl::mapLin(v, min, max, T(0), T(1));
00294         //v = scl::mapLin(v, min, max, T(0), T(1));
00295         //return mapExp2(value);
00296     default:
00297         return 0;
00298     }
00299 }
00300 
00301 
00302 template <class T> T UnitMapper<T>::mapLin(T u){
00303     doClip(u); return min + u * (max - min);
00304 }
00305 
00306 template <class T> T UnitMapper<T>::mapPow(T u){
00307     doClip(u); return (T)scl::mapPower(u, max, min, p1);
00308 }
00309 
00310 template <class T> T UnitMapper<T>::mapExp2(T u){
00311     doClip(u);
00312     return (T)(pow(2., scl::mapPower(u, max, min, 1.)) * p1);
00313 }
00314 
00315 } // gam::
00316 
00317 #endif