| Chris@147 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@147 | 2 | 
| Chris@147 | 3 /* | 
| Chris@147 | 4     Sonic Visualiser | 
| Chris@147 | 5     An audio file viewer and annotation editor. | 
| Chris@147 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@147 | 7     This file copyright 2006 Chris Cannam. | 
| Chris@147 | 8 | 
| Chris@147 | 9     This program is free software; you can redistribute it and/or | 
| Chris@147 | 10     modify it under the terms of the GNU General Public License as | 
| Chris@147 | 11     published by the Free Software Foundation; either version 2 of the | 
| Chris@147 | 12     License, or (at your option) any later version.  See the file | 
| Chris@147 | 13     COPYING included with this distribution for more information. | 
| Chris@147 | 14 */ | 
| Chris@147 | 15 | 
| Chris@147 | 16 #include "PowerOfSqrtTwoZoomConstraint.h" | 
| Chris@147 | 17 | 
| Chris@147 | 18 #include <iostream> | 
| Chris@147 | 19 #include <cmath> | 
| Chris@147 | 20 | 
| Chris@1528 | 21 #include "base/Debug.h" | 
| Chris@1528 | 22 | 
| Chris@147 | 23 | 
| Chris@929 | 24 int | 
| Chris@929 | 25 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(int blockSize, | 
| Chris@1429 | 26                                                   RoundingDirection dir) const | 
| Chris@147 | 27 { | 
| Chris@147 | 28     int type, power; | 
| Chris@929 | 29     int rv = getNearestBlockSize(blockSize, type, power, dir); | 
| Chris@147 | 30     return rv; | 
| Chris@147 | 31 } | 
| Chris@147 | 32 | 
| Chris@929 | 33 int | 
| Chris@929 | 34 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(int blockSize, | 
| Chris@1429 | 35                                                   int &type, | 
| Chris@1429 | 36                                                   int &power, | 
| Chris@1429 | 37                                                   RoundingDirection dir) const | 
| Chris@147 | 38 { | 
| Chris@1528 | 39 //    SVCERR << "given " << blockSize << endl; | 
| Chris@147 | 40 | 
| Chris@929 | 41     int minCachePower = getMinCachePower(); | 
| Chris@147 | 42 | 
| Chris@929 | 43     if (blockSize < (1 << minCachePower)) { | 
| Chris@1429 | 44         type = -1; | 
| Chris@1429 | 45         power = 0; | 
| Chris@1429 | 46         float val = 1.0, prevVal = 1.0; | 
| Chris@1429 | 47         while (val + 0.01 < blockSize) { | 
| Chris@1429 | 48             prevVal = val; | 
| Chris@1429 | 49             val *= sqrtf(2.f); | 
| Chris@1429 | 50         } | 
| Chris@1528 | 51         int rval = int(val + 0.01f); | 
| Chris@1528 | 52 //        SVCERR << "got val = " << val << ", rval = " << rval << ", prevVal = " << prevVal << endl; | 
| Chris@1528 | 53         if (rval != blockSize && dir != RoundUp) { | 
| Chris@1528 | 54             if (dir == RoundDown) { | 
| Chris@1528 | 55                 rval = int(prevVal + 0.01f); | 
| Chris@1528 | 56             } else if (val - float(blockSize) < float(blockSize) - prevVal) { | 
| Chris@1528 | 57                 rval = int(val + 0.01f); | 
| Chris@1528 | 58             } else { | 
| Chris@1528 | 59                 rval = int(prevVal + 0.01); | 
| Chris@1528 | 60             } | 
| Chris@1528 | 61         } | 
| Chris@1528 | 62 //        SVCERR << "returning " << rval << endl; | 
| Chris@1429 | 63         return rval; | 
| Chris@147 | 64     } | 
| Chris@147 | 65 | 
| Chris@929 | 66     int prevBase = (1 << minCachePower); | 
| Chris@929 | 67     int prevPower = minCachePower; | 
| Chris@929 | 68     int prevType = 0; | 
| Chris@147 | 69 | 
| Chris@929 | 70     int result = 0; | 
| Chris@147 | 71 | 
| Chris@147 | 72     for (unsigned int i = 0; ; ++i) { | 
| Chris@147 | 73 | 
| Chris@1429 | 74         power = minCachePower + i/2; | 
| Chris@1429 | 75         type = i % 2; | 
| Chris@147 | 76 | 
| Chris@1429 | 77         int base; | 
| Chris@1429 | 78         if (type == 0) { | 
| Chris@1429 | 79             base = (1 << power); | 
| Chris@1429 | 80         } else { | 
| Chris@1429 | 81             base = (((unsigned int)((1 << minCachePower) * sqrt(2.) + 0.01)) | 
| Chris@1429 | 82                     << (power - minCachePower)); | 
| Chris@1429 | 83         } | 
| Chris@147 | 84 | 
| Chris@1528 | 85 //        SVCERR << "Testing base " << base << " (i = " << i << ", power = " << power << ", type = " << type << ")" << endl; | 
| Chris@377 | 86 | 
| Chris@377 | 87         if (base == blockSize) { | 
| Chris@377 | 88             result = base; | 
| Chris@377 | 89             break; | 
| Chris@377 | 90         } | 
| Chris@377 | 91 | 
| Chris@1429 | 92         if (base > blockSize) { | 
| Chris@1429 | 93             if (dir == RoundNearest) { | 
| Chris@1429 | 94                 if (base - blockSize < blockSize - prevBase) { | 
| Chris@1429 | 95                     dir = RoundUp; | 
| Chris@1429 | 96                 } else { | 
| Chris@1429 | 97                     dir = RoundDown; | 
| Chris@1429 | 98                 } | 
| Chris@1429 | 99             } | 
| Chris@1429 | 100             if (dir == RoundUp) { | 
| Chris@1429 | 101                 result = base; | 
| Chris@1429 | 102                 break; | 
| Chris@1429 | 103             } else { | 
| Chris@1429 | 104                 type = prevType; | 
| Chris@1429 | 105                 power = prevPower; | 
| Chris@1429 | 106                 result = prevBase; | 
| Chris@1429 | 107                 break; | 
| Chris@1429 | 108             } | 
| Chris@1429 | 109         } | 
| Chris@147 | 110 | 
| Chris@1429 | 111         prevType = type; | 
| Chris@1429 | 112         prevPower = power; | 
| Chris@1429 | 113         prevBase = base; | 
| Chris@147 | 114     } | 
| Chris@147 | 115 | 
| Chris@147 | 116     if (result > getMaxZoomLevel()) result = getMaxZoomLevel(); | 
| Chris@147 | 117     return result; | 
| Chris@147 | 118 } |