Main Page | Class List | File List | Class Members | Examples

quasisampler_prototype.h

00001 /* 00002 File: quasisampler_prototype.h 00003 Quasisampler prototype. 00004 00005 This is a toy (non-optimized) implementation of the importance sampling 00006 technique proposed in the paper: 00007 "Fast Hierarchical Importance Sampling with Blue Noise Properties", 00008 by Victor Ostromoukhov, Charles Donohue and Pierre-Marc Jodoin, 00009 to be presented at SIGGRAPH 2004. 00010 00011 00012 Implementation by Charles Donohue, 00013 Based on Mathematica code by Victor Ostromoukhov. 00014 Universite de Montreal 00015 18.08.04 00016 00017 */ 00018 00019 00020 #ifndef QUASISAMPLER_PROTOTYPE_H 00021 #define QUASISAMPLER_PROTOTYPE_H 00022 00023 #include <math.h> 00024 #include <vector> 00025 00026 #define MIN(x,y) ((x)<(y)?(x):(y)) 00027 #define MAX(x,y) ((x)>(y)?(x):(y)) 00028 00029 #define LUT_SIZE 21 // Number of Importance Index entries in the Lookup table. 00030 #define NUM_STRUCT_INDEX_BITS 6 // Number of significant bits taken from F-Code. 00031 00032 #define GOLDEN_RATIO PHI // Phi is the Golden Ratio. 00033 #define PHI 1.6180339887498948482045868343656 // ( 1 + sqrt(5) ) / 2 00034 #define PHI2 2.6180339887498948482045868343656 // Phi squared 00035 #define LOG_PHI 0.48121182505960347 // log(Phi) 00036 #define SQRT5 2.2360679774997896964091736687313 // sqrt(5.0) 00037 00038 // Two-bit sequences. 00039 #define B00 0 00040 #define B10 1 00041 #define B01 2 00042 00043 /// The six tile types. 00044 enum TileType { 00045 TileTypeA,TileTypeB,TileTypeC,TileTypeD,TileTypeE,TileTypeF 00046 }; 00047 00048 /// Simple 2D point and vector type. 00049 class Point2D 00050 { 00051 public: 00052 double x,y; 00053 00054 Point2D(){}; 00055 Point2D(const double x, const double y) { this->x=x; this->y=y; } 00056 Point2D(const double vect[2]) { x=vect[0]; y=vect[1]; } 00057 00058 Point2D operator+(const Point2D& pt) const{ return Point2D(x+pt.x,y+pt.y); } 00059 Point2D operator-(const Point2D& pt) const{ return Point2D(x-pt.x,y-pt.y); } 00060 Point2D operator*(double factor) const{ return Point2D(x*factor,y*factor); } 00061 Point2D operator/(double factor) const{ return Point2D(x/factor,y/factor); } 00062 00063 /// Returns the squared distance to the origin, or the squared length of a vector. 00064 double d2() const { return x*x+y*y; } 00065 }; 00066 00067 /// This is a base class that implements the Quasi-Sampler importance sampling 00068 /// system, as presented in the paper : 00069 /// "Fast Hierarchical Importance Sampling with Blue Noise Properties", 00070 /// by Victor Ostromoukhov, Charles Donohue and Pierre-Marc Jodoin, 00071 /// to be presented at SIGGRAPH 2004. 00072 /// This is a pure-virtual class, and you must implement the "getImportanceAt()" function 00073 /// in order to use the sampling system. 00074 /// The mechanics of the system can be observed in the given source code. 00075 class Quasisampler 00076 { 00077 00078 protected: 00079 00080 // 00081 // Static tables. 00082 // 00083 00084 00085 /// Fibonacci sequence (first 32 numbers). 00086 static const unsigned fiboTable[32]; // defined at end of file. 00087 00088 /// Unit vectors rotated around origin, in \f$ \frac{\pi}{10} \f$ increments, 00089 /// counter-clockwise. 0 = North. 00090 /// This table can be used to accelerate the trigonomic operations within the tile 00091 /// subdivision process, since all angles can only take these values. 00092 static const Point2D vvect[20]; // defined at end of file. 00093 00094 /// Pre-calculated correction vectors lookup table. 00095 /// These are available in ASCII format on the web-site. 00096 static const double lut[LUT_SIZE][21][2]; // defined at end of file. 00097 00098 00099 00100 // 00101 // Static functions. 00102 // 00103 00104 /// Fibonacci number at a given position. 00105 /// The value returned is \f$ F_i = F_{i-1} + F_{i-2} \f$. 00106 static unsigned fibonacci(unsigned i) 00107 { 00108 if (i<1) return 1; 00109 if (i<=32) return fiboTable[i-1]; // pre-calculated. 00110 return fibonacci(i-1)+fibonacci(i-2); 00111 } 00112 00113 /// Returns the required level of subdivision for a given importance value. 00114 /// The value returned is \f$ \lceil{\log_{\phi^2}(importance)}\rceil \f$, 00115 /// where \f$ \phi=\frac{1 + {\sqrt{5}}}{2}\f$ is the Golden Ratio. 00116 static unsigned getReqSubdivisionLevel( unsigned importance ) 00117 { 00118 if (importance==0) return 0; 00119 unsigned nbits = (unsigned)(log( (double)importance*SQRT5 + 1.0 ) / LOG_PHI) - 1; 00120 if (nbits<1) nbits = 1; 00121 return (unsigned)ceil(0.5*nbits); 00122 } 00123 00124 /// Returns the decimal value of an F-Code, over a given number of bits. 00125 /// The value returned is \f$ \sum_{j=2}^{m} b_{j} F_{j} \f$. 00126 static unsigned calcFCodeValue(unsigned bitsequence,unsigned nbits) 00127 { 00128 unsigned i_s = 0; 00129 for (unsigned i=0; i<nbits ;i++ ) 00130 { 00131 if ( bitsequence & ( 1u<<(nbits-i-1) ) ) i_s += fibonacci(i+2); 00132 } 00133 return i_s; 00134 } 00135 00136 00137 /// Returns the Structural Index (i_s) for a given F-Code. 00138 static unsigned calcStructuralIndex(unsigned bitsequence) 00139 { 00140 return calcFCodeValue(bitsequence,NUM_STRUCT_INDEX_BITS); 00141 } 00142 00143 /// Returns the Importance Index (i_v) for a given importance value. 00144 /// The value returned is \f$ \lfloor n \cdot ({\log_{\phi^2} \sqrt{5} \cdot x}) ~ {\bf mod} ~ 1 \rfloor \f$. 00145 static unsigned calcImportanceIndex( unsigned importance ) 00146 { 00147 double t = log(1.0 + sqrt(5.0)*importance) / log(PHI2); 00148 t -= floor(t); // modulo 1.0 00149 return (unsigned)(LUT_SIZE*t); 00150 } 00151 00152 00153 /// Fetches the appropriate vector from the lookup table. 00154 static Point2D calcDisplacementVector(unsigned importance, unsigned f_code, int dir) 00155 { 00156 unsigned i_s = calcStructuralIndex(f_code); 00157 unsigned i_v = calcImportanceIndex(importance); 00158 00159 return 00160 vvect[dir] * lut[i_v][i_s][0] + // u component 00161 vvect[(dir+5)%20] * lut[i_v][i_s][1] ; // v component 00162 } 00163 00164 00165 // 00166 // Inner classes. 00167 // 00168 00169 00170 /// Individual tile elements, which also serve as nodes for the tile subdivision tree. 00171 class TileNode 00172 { 00173 00174 unsigned level; // Depth in the tree. 00175 int tileType; // Types A through F. 00176 int dir; // Tile orientation, 0=North, in Pi/10 increments, CCW. 00177 double scale; 00178 Point2D p1,p2,p3; // Three points of the triangle. Counter-clockwise. 00179 00180 /// The F-Code binary sequence. 00181 unsigned f_code; 00182 00183 // tiling tree structure 00184 TileNode* parent; 00185 unsigned parent_slot; // position in parent's list (needed for iterators) 00186 bool terminal; // true for leaf nodes 00187 std::vector<TileNode*> children; 00188 00189 public: 00190 00191 /// Builds a tile according to the given specifications. 00192 TileNode( 00193 TileNode* parent = NULL, 00194 int tileType = TileTypeF, 00195 Point2D refPt = Point2D(0,0), 00196 int dir = 15, // 15 = East. 00197 unsigned newbits = 0, 00198 int parent_slot = 0, 00199 double scale = 1.0) 00200 { 00201 this->parent = parent; 00202 this->tileType = tileType; 00203 this->p1 = refPt; 00204 this->dir = dir%20; 00205 this->parent_slot = parent_slot; 00206 this->scale = scale; 00207 this->level = parent ? parent->level + 1 : 0; // Increment the level. 00208 00209 00210 // Build triangle, according to type. 00211 switch(tileType) 00212 { 00213 case TileTypeC: 00214 case TileTypeD: 00215 // "Skinny" triangles 00216 p2 = p1 + vvect[dir%20]*scale; 00217 p3 = p1 + vvect[(dir+4)%20]*(PHI*scale); 00218 break; 00219 case TileTypeE: 00220 case TileTypeF: 00221 // "Fat" triangles 00222 p2 = p1 + vvect[dir%20]*(PHI2*scale); 00223 p3 = p1 + vvect[(dir+2)%20]*(PHI*scale); 00224 break; 00225 default: 00226 // Pentagonal tiles (triangle undefined) 00227 p2 = p1 + vvect[dir%20]*scale; 00228 p3 = p1 + vvect[(dir+5)%20]*scale; 00229 } 00230 00231 // Append 2 new bits to the F-Code. 00232 if (parent) 00233 f_code = (parent->f_code<<2)^newbits; 00234 else 00235 f_code = newbits; 00236 00237 // Set as leaf node 00238 terminal = true; 00239 children.clear(); 00240 } 00241 00242 /// Helper constructor. 00243 /// Creates an initial tile that is certain to contain the ROI. 00244 /// The starting tile is of type F (arbitrary). 00245 TileNode( double roi_width, double roi_height) 00246 { 00247 double side = MAX(roi_width,roi_height); 00248 double scale = 2.0 * side; 00249 Point2D offset(PHI*PHI/2.0-0.25,0.125); 00250 *this = TileNode(NULL, TileTypeF,offset*-scale,15,0,0,scale); 00251 } 00252 00253 ~TileNode() { collapse(); } 00254 00255 /// Splits a tile according to the given subdivision rules. 00256 /// Please refer to the code for further details. 00257 void refine() 00258 { 00259 if (!terminal) return; // Can only subdivide leaf nodes. 00260 00261 terminal=false; // The tile now has children. 00262 double newscale = scale / GOLDEN_RATIO; // The scale factor between levels is constant. 00263 00264 switch(tileType) 00265 { 00266 00267 // Each new tile is created using the following information: 00268 // A pointer to its parent, the type of the new tile (a through f), 00269 // the origin of the new tile, the change in orientation of the new tile with 00270 // respect to the parent's orientation, the two bits to be pre-pended to the F-Code, 00271 // the parent's slot (for traversal purposes), and the new linear scale of the tile, 00272 // which is always the parent's scale divided by the golden ratio. 00273 00274 case TileTypeA: 00275 children.push_back( 00276 new TileNode(this, TileTypeB, p1, dir+0, B00, 0, newscale)); 00277 break; 00278 00279 case TileTypeB: 00280 children.push_back( 00281 new TileNode(this, TileTypeA, p1, dir+10, B00, 0, newscale) ); 00282 break; 00283 00284 case TileTypeC: 00285 children.push_back( 00286 new TileNode(this, TileTypeF, p3, dir+14, B00, 0, newscale) ); 00287 children.push_back( 00288 new TileNode(this, TileTypeC, p2, dir+6, B10, 1, newscale) ); 00289 children.push_back( 00290 new TileNode(this, TileTypeA, children[0]->p3, dir+1, B10, 2, newscale) ); 00291 break; 00292 00293 case TileTypeD: 00294 children.push_back( 00295 new TileNode(this, TileTypeE, p2, dir+6, B00, 0, newscale) ); 00296 children.push_back( 00297 new TileNode(this, TileTypeD, children[0]->p3, dir+14, B10, 1, newscale) ); 00298 break; 00299 00300 case TileTypeE: 00301 children.push_back( 00302 new TileNode(this, TileTypeC, p3, dir+12, B10, 0, newscale) ); 00303 children.push_back( 00304 new TileNode(this, TileTypeE, p2, dir+8 , B01, 1, newscale) ); 00305 children.push_back( 00306 new TileNode(this, TileTypeF, p1, dir+0 , B00, 2, newscale) ); 00307 children.push_back( 00308 new TileNode(this, TileTypeA, children[0]->p2, dir+7, B10, 3, newscale) ); 00309 break; 00310 00311 case TileTypeF: 00312 children.push_back( 00313 new TileNode(this, TileTypeF, p3, dir+12, B01, 0, newscale) ); 00314 children.push_back( 00315 new TileNode(this, TileTypeE, children[0]->p3, dir+0, B00, 1, newscale) ); 00316 children.push_back( 00317 new TileNode(this, TileTypeD, children[1]->p3, dir+8, B10, 2, newscale) ); 00318 children.push_back( 00319 new TileNode(this, TileTypeA, children[0]->p3, dir+15, B01, 3, newscale) ); 00320 break; 00321 } 00322 } 00323 00324 /// Prunes the subdivision tree at this node. 00325 void collapse() 00326 { 00327 // Recursively prune the tree. 00328 for (unsigned i=0; i<children.size(); i++) delete children[i]; 00329 terminal = true; 00330 children.clear(); 00331 } 00332 00333 /// Returns the next node of the tree, in depth-first traversal. 00334 /// Returns NULL if it is at the last node. 00335 TileNode* nextNode() 00336 { 00337 if (!terminal) return children[0]; 00338 00339 if (level == 0) return NULL; // single node case. 00340 00341 if ( parent_slot < parent->children.size()-1 ) 00342 return parent->children[parent_slot+1]; 00343 00344 // last child case 00345 TileNode* tmp = this; 00346 do 00347 { 00348 tmp = tmp->parent; 00349 } 00350 while ( (tmp->level != 0) && (tmp->parent_slot == tmp->parent->children.size()-1) ); 00351 00352 if (tmp->level == 0) return NULL; // last node 00353 return tmp->parent->children[tmp->parent_slot+1]; 00354 00355 } 00356 00357 /// Returns the next closest leaf to a node. 00358 /// Returns NULL if it's the last leaf. 00359 TileNode* nextLeaf() 00360 { 00361 TileNode* tmp = this; 00362 do 00363 { 00364 tmp = tmp->nextNode(); 00365 if ( !tmp ) return NULL; 00366 if ( tmp->terminal ) return tmp; 00367 } 00368 while (1); 00369 } 00370 00371 // Public accessors 00372 00373 Point2D getP1() const { return p1; } 00374 Point2D getP2() const { return p2; } 00375 Point2D getP3() const { return p3; } 00376 Point2D getCenter() const { return (p1+p2+p3)/3.0; } 00377 unsigned getFCode() const { return f_code; } 00378 bool isSamplingType() const { 00379 return ( (tileType == TileTypeA) || (tileType == TileTypeB) ); } 00380 unsigned getLevel() { return level; } 00381 bool isTerminal() const { return terminal; } 00382 TileNode* getParent() { return parent; } 00383 TileNode* getChild(unsigned i) { return children[i]; } 00384 00385 /// Obtains the correction vector from the lookup table, 00386 /// then scales and adds it to the reference point. 00387 Point2D getDisplacedSamplingPoint(unsigned importance) 00388 { 00389 return p1 + calcDisplacementVector(importance,f_code,dir) * scale; 00390 } 00391 00392 }; // end of class TileNode. 00393 00394 /// Leaf iterator for the tile subdivision tree. 00395 /// The traversal is made in a depth-first manner. 00396 /// Warning: This does not behave like STL style iterators. 00397 class TileLeafIterator 00398 { 00399 TileNode* shape; 00400 public: 00401 TileLeafIterator() { shape=NULL; } 00402 TileLeafIterator(TileNode* s ) { begin(s); } 00403 00404 TileNode* operator*() { return shape; } 00405 TileNode* operator->() { return shape; } 00406 00407 void begin(TileNode* s) 00408 { 00409 TileNode* tmp = s; 00410 while ( ! tmp->isTerminal() ) tmp = tmp->getChild(0); // find first leaf 00411 shape = tmp; 00412 } 00413 00414 /// Subdivides the tile and moves to its 1st child. 00415 void refine() 00416 { 00417 shape->refine(); 00418 shape = shape->getChild(0); 00419 } 00420 00421 /// Prunes the subdivision tree. 00422 void collapse() 00423 { 00424 if (shape->getParent()) 00425 { 00426 shape = shape->getParent(); 00427 shape->collapse(); 00428 } 00429 } 00430 00431 /// Moves to the next node in the subdivision tree, in depth-first traversal. 00432 /// Returns false iff there is no such node. 00433 bool next() 00434 { 00435 TileNode* s = shape->nextLeaf(); 00436 if (s) 00437 { 00438 shape = s; 00439 return true; 00440 } 00441 else 00442 { 00443 shape = s; 00444 return false; 00445 } 00446 } 00447 00448 /// Checks if there is a next tile, in depth-first traversal. 00449 bool hasNext() 00450 { 00451 TileNode* s = shape->nextLeaf(); 00452 if (s) return true; 00453 else return false; 00454 } 00455 }; 00456 00457 00458 // 00459 // Instance members. 00460 // 00461 00462 /// Root node of the tile subdivision tree. 00463 TileNode *root; 00464 00465 /// Extents of the region of interest. 00466 double width, height; 00467 00468 /// Protected constructor, which initializes the Region of Interest. 00469 Quasisampler(double width=0.0, double height=0.0) 00470 { this->width=width; this->height=height; root=NULL; } 00471 00472 virtual ~Quasisampler() { if (root) delete root; } 00473 00474 00475 00476 /// This is a helper function which constrains the incoming points 00477 /// to the region of interest. 00478 unsigned getImportanceAt_bounded(Point2D pt) 00479 { 00480 if (pt.x>=0 && pt.x<width && pt.y>=0 && pt.y<height) 00481 return getImportanceAt(pt); 00482 else 00483 return 0; 00484 } 00485 00486 /// Subdivides all tiles down a level, a given number of times. 00487 void subdivideAll(int times=1) 00488 { 00489 if (!root) return; 00490 TileNode *tmp; 00491 for (int i=0;i<times;i++) 00492 { 00493 TileLeafIterator it(root); 00494 do { 00495 tmp = *it; 00496 it.next(); 00497 tmp->refine(); 00498 } 00499 while (*it); 00500 } 00501 } 00502 00503 /// Generates the hierarchical structure. 00504 void buildAdaptiveSubdivision( unsigned minSubdivisionLevel = 6 ) 00505 { 00506 root = new TileNode(width,height); 00507 00508 // Since we are approximating the MAX within each tile by the values at 00509 // a few key points, we must provide a sufficiently dense initial 00510 // tiling. This would not be necessary with a more thorough scan of each 00511 // tile. 00512 subdivideAll(minSubdivisionLevel); 00513 00514 TileLeafIterator it(root); 00515 TileNode *tmp; 00516 00517 // Recursively subdivide all triangles until each triangle's 00518 // required level is reached. 00519 unsigned level; 00520 do { 00521 level = it->getLevel(); 00522 00523 if ( it->isSamplingType() ) // Sampling tiles are infinitesimal 00524 { 00525 if ( level < getReqSubdivisionLevel(getImportanceAt_bounded(it->getP1())) ) 00526 { 00527 tmp = *it; 00528 tmp->refine(); 00529 } 00530 } 00531 else 00532 { 00533 if ( 00534 ( level < getReqSubdivisionLevel(getImportanceAt_bounded(it->getP1())) ) || 00535 ( level < getReqSubdivisionLevel(getImportanceAt_bounded(it->getP2())) ) || 00536 ( level < getReqSubdivisionLevel(getImportanceAt_bounded(it->getP3())) ) || 00537 ( level < getReqSubdivisionLevel(getImportanceAt_bounded(it->getCenter())) ) 00538 ) 00539 { 00540 tmp = *it; 00541 tmp->refine(); 00542 } 00543 } 00544 } while ( it.next() ); 00545 } 00546 00547 00548 /// Collect the resulting point set. 00549 void collectPoints( 00550 std::vector<Point2D> &pointlist, 00551 bool filterBounds = true ) 00552 { 00553 pointlist.clear(); 00554 00555 Point2D pt, pt_displaced; 00556 unsigned importance; 00557 TileLeafIterator it(root); 00558 do { 00559 pt = it->getP1(); 00560 if ( it->isSamplingType() ) // Only "pentagonal" tiles generate sampling points. 00561 { 00562 importance = getImportanceAt_bounded( pt ); 00563 00564 // Threshold the function against the F-Code value. 00565 if ( importance >= calcFCodeValue( it->getFCode() , 2*it->getLevel() ) ) 00566 { 00567 // Get the displaced point using the lookup table. 00568 pt_displaced = it->getDisplacedSamplingPoint(importance); 00569 00570 if ( !filterBounds || 00571 (pt_displaced.x>=0 && pt_displaced.x<width && 00572 pt_displaced.y>=0 && pt_displaced.y<height) ) 00573 { 00574 pointlist.push_back(pt_displaced); // collect point. 00575 } 00576 } 00577 } 00578 00579 } while ( it.next() ); 00580 00581 } 00582 00583 public: 00584 00585 /// This virtual function must be implemented in order to use the sampling system. 00586 /// It should return the value of the importance function at the given point. 00587 virtual unsigned getImportanceAt( Point2D pt ) = 0; 00588 00589 /// Builds and collects the point set generated be the sampling system, 00590 /// using the previously defined importance function. 00591 std::vector<Point2D> getSamplingPoints() 00592 { 00593 if (root) delete root; 00594 std::vector<Point2D> pointlist; 00595 00596 buildAdaptiveSubdivision(); 00597 collectPoints(pointlist); 00598 return pointlist; 00599 } 00600 00601 /// \example example.cpp 00602 /// This a simple example of how to use the Quasisampler class. 00603 00604 /// \example example2.cpp 00605 /// This another simple example of how to use the Quasisampler class. 00606 00607 /// \example example3.cpp 00608 /// This example shows how to use the system on a grayscale image. 00609 }; 00610 00611 00612 00613 /* 00614 00615 Static Member initialization 00616 00617 */ 00618 00619 const unsigned Quasisampler::fiboTable[32]= 00620 { 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987, 00621 1597,2584,4181,6765,10946,17711,28657,46368,75025, 00622 121393,196418,317811,514229,832040,1346269,2178309 }; 00623 00624 const Point2D Quasisampler::vvect[]={ 00625 Point2D(0,1), Point2D(-0.309017,0.951057), Point2D(-0.587785,0.809017), 00626 Point2D(-0.809017,0.587785), Point2D(-0.951057,0.309017), Point2D(-1,0), 00627 Point2D(-0.951057,-0.309017), Point2D(-0.809017,-0.587785), 00628 Point2D(-0.587785,-0.809017), Point2D(-0.309017,-0.951057), Point2D(0,-1), 00629 Point2D(0.309017,-0.951057), Point2D(0.587785,-0.809017), Point2D(0.809017,-0.587785), 00630 Point2D(0.951057,-0.309017), Point2D(1,0), Point2D(0.951057,0.309017), 00631 Point2D(0.809017,0.587785), Point2D(0.587785,0.809017), Point2D(0.309017,0.951057) 00632 }; 00633 00634 const double Quasisampler::lut[LUT_SIZE][21][2] = 00635 {{{0.0130357, 0.0419608}, {-0.0241936, 0.0152706}, {-0.00384601, -0.311212}, {-0.000581893, -0.129134}, 00636 {-0.0363269, 0.0127624}, {0.0999483, 0.408639}, {-0.0526517, 0.4385}, {-0.128703, 0.392}, {0.0132026, 1.0818}, 00637 {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, 00638 {{0.00793289, 0.0148063}, {0.0206067, -0.0809589}, {0.0110103, -0.430433}, {0.0000473169, -0.293185}, 00639 {-0.0593578, 0.019457}, {0.34192, 0.291714}, {-0.286696, 0.386017}, {-0.345313, 0.311961}, {0.00606029, 1.00877}, 00640 {0.04757, 0.05065}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, 00641 {{0.00454493, -0.00805726}, {0.0545058, -0.140953}, {0.00960599, -0.493483}, {0.000527191, -0.354496}, 00642 {-0.0742085, -0.0477178}, {0.436518, 0.218493}, {-0.422435, 0.275524}, {-0.425198, 0.257027}, 00643 {0.0127468, 0.979585}, {0.128363, 0.139522}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 00644 {0, 0}, {0, 0}, {0, 0}}, {{-0.0014899, -0.0438403}, {0.122261, -0.229582}, {-0.00497263, -0.580537}, 00645 {-0.00489546, -0.424237}, {-0.107601, -0.133695}, {0.526304, 0.125709}, {-0.558461, 0.0679206}, 00646 {-0.511708, 0.153397}, {0.0271526, 0.950065}, {0.298021, 0.327582}, {-0.00464701, -0.00362132}, {0, 0}, {0, 0}, 00647 {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, 00648 {{-0.0182024, -0.0837012}, {0.226792, -0.318088}, {-0.0416745, -0.663614}, {-0.0253331, -0.455424}, 00649 {-0.159087, -0.20807}, {0.552691, 0.0525824}, {-0.617244, -0.197362}, {-0.561762, 0.00314535}, 00650 {0.0522991, 0.928754}, {0.376689, 0.429912}, {-0.0180693, -0.00792235}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 00651 {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, {{-0.0308901, -0.108719}, {0.362157, -0.377329}, 00652 {-0.0918077, -0.742776}, {-0.0571567, -0.453854}, {-0.242014, -0.230347}, {0.542952, -0.00542364}, 00653 {-0.614735, -0.35591}, {-0.565238, -0.204834}, {0.084241, 0.900632}, {0.403207, 0.481046}, 00654 {-0.0459391, -0.00743248}, {0.0143212, 0.0776031}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 00655 {0, 0}, {0, 0}}, {{-0.0429758, -0.112222}, {0.470514, -0.41007}, {-0.139291, -0.797567}, {-0.0930261, -0.382258}, 00656 {-0.30831, -0.210972}, {0.504387, -0.05265}, {-0.578917, -0.4354}, {-0.545885, -0.40618}, {0.122368, 0.852639}, 00657 {0.377534, 0.476884}, {-0.0712593, 0.0238995}, {0.0349156, 0.248696}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 00658 {0, 0}, {0, 0}, {0, 0}, {0, 0}}, {{-0.0297026, -0.0818903}, {0.514634, -0.426843}, {-0.161039, -0.817284}, 00659 {-0.099245, -0.221824}, {-0.359506, -0.135015}, {0.433957, -0.0878639}, {-0.541453, -0.46714}, 00660 {-0.526484, -0.556459}, {0.1735, 0.771396}, {0.353023, 0.455358}, {-0.07854, 0.0885735}, {0.0714601, 0.591673}, 00661 {-0.0147015, 0.0839976}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, 00662 {{-0.0204607, -0.0433266}, {0.515056, -0.428386}, {-0.153717, -0.803384}, {-0.0874438, 0.032819}, 00663 {-0.370233, 0.00469937}, {0.331072, -0.0951004}, {-0.507368, -0.487422}, {-0.533403, -0.648977}, 00664 {0.243233, 0.652577}, {0.33663, 0.406983}, {-0.0624495, 0.167064}, {0.0527702, 0.808443}, {-0.0444704, 0.258347}, 00665 {0.030331, -0.00128903}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, 00666 {{-0.0184965, 0.00557424}, {0.495666, -0.40889}, {-0.136052, -0.781115}, {-0.0493628, 0.265293}, 00667 {-0.337945, 0.202038}, {0.193353, -0.0835904}, {-0.479971, -0.497456}, {-0.574003, -0.71938}, 00668 {0.32445, 0.514949}, {0.331709, 0.341565}, {-0.034108, 0.244375}, {0.0149632, 0.910353}, {-0.104428, 0.60938}, 00669 {0.0948414, -0.00216379}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, 00670 {{-0.0436899, 0.0294207}, {0.469933, -0.372015}, {-0.153852, -0.756531}, {0.00920944, 0.393625}, 00671 {-0.270292, 0.392355}, {0.0540646, -0.0473047}, {-0.466651, -0.492248}, {-0.647575, -0.793479}, 00672 {0.394352, 0.385016}, {0.330852, 0.272582}, {-0.0125759, 0.30811}, {-0.0407447, 0.902855}, {-0.136947, 0.8021}, 00673 {0.227048, -0.0014045}, {0.0261797, 0.0109521}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, 00674 {{-0.0602358, 0.0215278}, {0.43301, -0.338538}, {-0.233311, -0.71494}, {0.0916642, 0.433266}, 00675 {-0.173199, 0.474801}, {-0.0384285, 0.024931}, {-0.475596, -0.469989}, {-0.739327, -0.866143}, 00676 {0.440049, 0.277063}, {0.326099, 0.207864}, {-0.00488013, 0.365323}, {-0.0890991, 0.872087}, 00677 {-0.159106, 0.889116}, {0.311406, 0.0126425}, {0.081674, 0.0403966}, {0.01391, 0.00573611}, {0, 0}, {0, 0}, 00678 {0, 0}, {0, 0}, {0, 0}}, {{-0.0723894, -0.00927744}, {0.354855, -0.326512}, {-0.329593, -0.647058}, 00679 {0.169384, 0.42962}, {-0.0250381, 0.472328}, {-0.108748, 0.122704}, {-0.507741, -0.424372}, 00680 {-0.805866, -0.896362}, {0.48306, 0.211626}, {0.314407, 0.142681}, {-0.00348365, 0.415081}, 00681 {-0.125494, 0.836485}, {-0.183247, 0.847226}, {0.366439, 0.0391043}, {0.18978, 0.100287}, {0.0401008, 0.018797}, 00682 {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, {{-0.0748666, -0.0517059}, {0.237999, -0.333105}, 00683 {-0.391007, -0.558425}, {0.223599, 0.428175}, {0.159284, 0.420084}, {-0.17834, 0.234411}, {-0.553952, -0.353981}, 00684 {-0.821481, -0.848098}, {0.527132, 0.175271}, {0.312397, 0.0908259}, {0.00190795, 0.441568}, 00685 {-0.149358, 0.790424}, {-0.226469, 0.765995}, {0.383259, 0.0740479}, {0.243694, 0.15335}, {0.0901877, 0.0475938}, 00686 {-0.00963625, 0.00819101}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, 00687 {{-0.0862318, -0.0937052}, {0.132383, -0.310846}, {-0.420153, -0.463782}, {0.261956, 0.440763}, 00688 {0.290379, 0.392449}, {-0.264095, 0.349189}, {-0.576491, -0.274722}, {-0.797096, -0.724963}, 00689 {0.565701, 0.153393}, {0.315376, 0.0546255}, {0.0149326, 0.430477}, {-0.167772, 0.702404}, {-0.283244, 0.645617}, 00690 {0.383304, 0.0988087}, {0.248786, 0.17877}, {0.103708, 0.0729573}, {-0.0286781, 0.0298329}, 00691 {-0.00878083, 0.0189161}, {0, 0}, {0, 0}, {0, 0}}, 00692 {{-0.0911025, -0.116785}, {0.058151, -0.268943}, {-0.424486, -0.374671}, {0.288764, 0.470621}, 00693 {0.362681, 0.386055}, {-0.327219, 0.436709}, {-0.585384, -0.202215}, {-0.772145, -0.5936}, {0.580061, 0.135496}, 00694 {0.313963, 0.0305349}, {0.0109925, 0.360967}, {-0.181933, 0.552414}, {-0.300836, 0.508161}, 00695 {0.364265, 0.0976394}, {0.210088, 0.176749}, {0.096516, 0.0958074}, {-0.0658733, 0.0731591}, 00696 {-0.0280071, 0.057776}, {0.0158411, 0.00325704}, {0, 0}, {0, 0}}, 00697 {{-0.0974734, -0.0918732}, {0.0139633, -0.212455}, {-0.406371, -0.282796}, {0.296357, 0.483457}, 00698 {0.381376, 0.39536}, {-0.333854, 0.503081}, {-0.58254, -0.14516}, {-0.763625, -0.49765}, {0.567887, 0.121286}, 00699 {0.30413, 0.0127316}, {-0.00152308, 0.270083}, {-0.191895, 0.352083}, {-0.283727, 0.35145}, 00700 {0.326415, 0.0742237}, {0.163984, 0.15982}, {0.0726181, 0.108651}, {-0.0800514, 0.114725}, 00701 {-0.0673361, 0.138093}, {0.0402953, 0.00961117}, {-0.0193168, 0.0236477}, {0, 0}}, 00702 {{-0.0790912, -0.0163216}, {-0.00448123, -0.162101}, {-0.352873, -0.196134}, {0.271462, 0.449512}, 00703 {0.35836, 0.383875}, {-0.286884, 0.565229}, {-0.550438, -0.0846486}, {-0.75899, -0.42121}, {0.528606, 0.119818}, 00704 {0.280538, 0.00168322}, {-0.0349212, 0.150096}, {-0.171099, 0.193366}, {-0.250974, 0.211407}, 00705 {0.280682, 0.0548899}, {0.126017, 0.143427}, {0.0562988, 0.110436}, {-0.0785227, 0.145239}, 00706 {-0.0937526, 0.190149}, {0.0791086, 0.0227095}, {-0.0545744, 0.0707386}, {0, 0}}, 00707 {{-0.0518157, 0.0510771}, {-0.00760212, -0.128097}, {-0.253754, -0.111841}, {0.205436, 0.354864}, 00708 {0.295866, 0.325402}, {-0.192075, 0.64807}, {-0.4774, -0.00676484}, {-0.722069, -0.332801}, {0.470923, 0.131373}, 00709 {0.244358, -0.00366888}, {-0.0555535, 0.0625726}, {-0.128642, 0.0933316}, {-0.239777, 0.136585}, 00710 {0.234046, 0.0562388}, {0.105223, 0.134278}, {0.0497268, 0.106459}, {-0.0606163, 0.175207}, 00711 {-0.106271, 0.232174}, {0.0538097, 0.0296093}, {-0.122383, 0.16238}, {-0.0113815, 0.0340113}}, 00712 {{-0.0304857, 0.0883196}, {0.00193379, -0.129688}, {-0.148195, -0.0572436}, {0.128477, 0.258454}, 00713 {0.18546, 0.230594}, {-0.120249, 0.694404}, {-0.326488, 0.130702}, {-0.599671, -0.166452}, {0.371228, 0.215584}, 00714 {0.18765, -0.00862734}, {-0.0530754, 0.00501476}, {-0.0781737, 0.0495139}, {-0.215913, 0.0922068}, 00715 {0.202485, 0.0708782}, {0.103985, 0.125369}, {0.0553649, 0.1009}, {-0.0397036, 0.199708}, {-0.0966645, 0.253069}, 00716 {-0.0153489, 0.0350904}, {-0.134291, 0.193388}, {-0.0315258, 0.0780417}}, 00717 {{-0.00909437, 0.0971829}, {0.00766774, -0.145809}, {-0.0755563, -0.0337505}, {0.0700629, 0.188928}, 00718 {0.109764, 0.175155}, {-0.084045, 0.707208}, {-0.200288, 0.246694}, {-0.431284, 0.0136518}, {0.274276, 0.314326}, 00719 {0.138397, -0.0136486}, {-0.033298, -0.019655}, {-0.0429267, 0.0341841}, {-0.195447, 0.0692005}, 00720 {0.188428, 0.0886883}, {0.112392, 0.115937}, {0.0568682, 0.0920568}, {-0.0238131, 0.214855}, 00721 {-0.0754228, 0.259851}, {-0.0881413, 0.0371697}, {-0.127762, 0.194639}, {-0.0700573, 0.173426}}}; 00722 00723 00724 #endif //QUASISAMPLER_PROTOTYPE_H 00725

Generated on Wed Aug 18 12:37:51 2004 for Quasi-Sampler by doxygen 1.3.7