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@147
|
21
|
Chris@147
|
22 size_t
|
Chris@147
|
23 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(size_t blockSize,
|
Chris@147
|
24 RoundingDirection dir) const
|
Chris@147
|
25 {
|
Chris@147
|
26 int type, power;
|
Chris@147
|
27 size_t rv = getNearestBlockSize(blockSize, type, power, dir);
|
Chris@147
|
28 return rv;
|
Chris@147
|
29 }
|
Chris@147
|
30
|
Chris@147
|
31 size_t
|
Chris@147
|
32 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(size_t blockSize,
|
Chris@147
|
33 int &type,
|
Chris@147
|
34 int &power,
|
Chris@147
|
35 RoundingDirection dir) const
|
Chris@147
|
36 {
|
Chris@147
|
37 // std::cerr << "given " << blockSize << std::endl;
|
Chris@147
|
38
|
Chris@147
|
39 size_t minCachePower = getMinCachePower();
|
Chris@147
|
40
|
Chris@147
|
41 if (blockSize < (1U << minCachePower)) {
|
Chris@147
|
42 type = -1;
|
Chris@147
|
43 power = 0;
|
Chris@147
|
44 float val = 1.0, prevVal = 1.0;
|
Chris@147
|
45 while (val + 0.01 < blockSize) {
|
Chris@147
|
46 prevVal = val;
|
Chris@147
|
47 val *= sqrt(2);
|
Chris@147
|
48 }
|
Chris@147
|
49 size_t rval;
|
Chris@147
|
50 if (dir == RoundUp) rval = size_t(val + 0.01);
|
Chris@147
|
51 else if (dir == RoundDown) rval = size_t(prevVal + 0.01);
|
Chris@147
|
52 else if (val - blockSize < blockSize - prevVal) rval = size_t(val + 0.01);
|
Chris@147
|
53 else rval = size_t(prevVal + 0.01);
|
Chris@147
|
54 // std::cerr << "returning " << rval << std::endl;
|
Chris@147
|
55 return rval;
|
Chris@147
|
56 }
|
Chris@147
|
57
|
Chris@147
|
58 unsigned int prevBase = (1 << minCachePower);
|
Chris@147
|
59 unsigned int prevPower = minCachePower;
|
Chris@147
|
60 unsigned int prevType = 0;
|
Chris@147
|
61
|
Chris@147
|
62 size_t result = 0;
|
Chris@147
|
63
|
Chris@147
|
64 for (unsigned int i = 0; ; ++i) {
|
Chris@147
|
65
|
Chris@147
|
66 power = minCachePower + i/2;
|
Chris@147
|
67 type = i % 2;
|
Chris@147
|
68
|
Chris@147
|
69 unsigned int base;
|
Chris@147
|
70 if (type == 0) {
|
Chris@147
|
71 base = (1 << power);
|
Chris@147
|
72 } else {
|
Chris@147
|
73 base = (((unsigned int)((1 << minCachePower) * sqrt(2) + 0.01))
|
Chris@147
|
74 << (power - minCachePower));
|
Chris@147
|
75 }
|
Chris@147
|
76
|
Chris@147
|
77 // std::cerr << "Testing base " << base << std::endl;
|
Chris@383
|
78
|
Chris@383
|
79 if (base == blockSize) {
|
Chris@383
|
80 result = base;
|
Chris@383
|
81 break;
|
Chris@383
|
82 }
|
Chris@383
|
83
|
Chris@383
|
84 if (base > blockSize) {
|
Chris@147
|
85 if (dir == RoundNearest) {
|
Chris@147
|
86 if (base - blockSize < blockSize - prevBase) {
|
Chris@147
|
87 dir = RoundUp;
|
Chris@147
|
88 } else {
|
Chris@147
|
89 dir = RoundDown;
|
Chris@147
|
90 }
|
Chris@147
|
91 }
|
Chris@147
|
92 if (dir == RoundUp) {
|
Chris@147
|
93 result = base;
|
Chris@147
|
94 break;
|
Chris@147
|
95 } else {
|
Chris@147
|
96 type = prevType;
|
Chris@147
|
97 power = prevPower;
|
Chris@147
|
98 result = prevBase;
|
Chris@147
|
99 break;
|
Chris@147
|
100 }
|
Chris@147
|
101 }
|
Chris@147
|
102
|
Chris@147
|
103 prevType = type;
|
Chris@147
|
104 prevPower = power;
|
Chris@147
|
105 prevBase = base;
|
Chris@147
|
106 }
|
Chris@147
|
107
|
Chris@147
|
108 if (result > getMaxZoomLevel()) result = getMaxZoomLevel();
|
Chris@147
|
109 return result;
|
Chris@147
|
110 }
|