annotate data/model/PowerOfSqrtTwoZoomConstraint.cpp @ 1794:71e97de5053f

Merge from branch time-frequency-boxes
author Chris Cannam
date Wed, 25 Sep 2019 13:47:46 +0100
parents 05c3fbaec8ea
children
rev   line source
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@1324 24 ZoomLevel
Chris@1324 25 PowerOfSqrtTwoZoomConstraint::getNearestZoomLevel(ZoomLevel requested,
Chris@1429 26 RoundingDirection dir) const
Chris@147 27 {
Chris@147 28 int type, power;
Chris@1324 29 int blockSize;
Chris@1324 30
Chris@1324 31 if (requested.zone == ZoomLevel::FramesPerPixel) {
Chris@1324 32 blockSize = getNearestBlockSize(requested.level, type, power, dir);
Chris@1324 33 return { requested.zone, blockSize };
Chris@1324 34 } else {
Chris@1324 35 RoundingDirection opposite = dir;
Chris@1324 36 if (dir == RoundUp) opposite = RoundDown;
Chris@1324 37 else if (dir == RoundDown) opposite = RoundUp;
Chris@1324 38 blockSize = getNearestBlockSize(requested.level, type, power, opposite);
Chris@1324 39 if (blockSize > getMinZoomLevel().level) {
Chris@1324 40 blockSize = getMinZoomLevel().level;
Chris@1324 41 }
Chris@1324 42 if (blockSize == 1) {
Chris@1324 43 return { ZoomLevel::FramesPerPixel, 1 };
Chris@1324 44 } else {
Chris@1324 45 return { requested.zone, blockSize };
Chris@1324 46 }
Chris@1324 47 }
Chris@147 48 }
Chris@147 49
Chris@929 50 int
Chris@929 51 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(int blockSize,
Chris@1429 52 int &type,
Chris@1429 53 int &power,
Chris@1429 54 RoundingDirection dir) const
Chris@147 55 {
Chris@1528 56 // SVCERR << "given " << blockSize << endl;
Chris@147 57
Chris@929 58 int minCachePower = getMinCachePower();
Chris@147 59
Chris@929 60 if (blockSize < (1 << minCachePower)) {
Chris@1429 61 type = -1;
Chris@1429 62 power = 0;
Chris@1429 63 float val = 1.0, prevVal = 1.0;
Chris@1429 64 while (val + 0.01 < blockSize) {
Chris@1429 65 prevVal = val;
Chris@1429 66 val *= sqrtf(2.f);
Chris@1429 67 }
Chris@1528 68 int rval = int(val + 0.01f);
Chris@1528 69 // SVCERR << "got val = " << val << ", rval = " << rval << ", prevVal = " << prevVal << endl;
Chris@1528 70 if (rval != blockSize && dir != RoundUp) {
Chris@1528 71 if (dir == RoundDown) {
Chris@1528 72 rval = int(prevVal + 0.01f);
Chris@1528 73 } else if (val - float(blockSize) < float(blockSize) - prevVal) {
Chris@1528 74 rval = int(val + 0.01f);
Chris@1528 75 } else {
Chris@1528 76 rval = int(prevVal + 0.01);
Chris@1528 77 }
Chris@1528 78 }
Chris@1528 79 // SVCERR << "returning " << rval << endl;
Chris@1429 80 return rval;
Chris@147 81 }
Chris@147 82
Chris@929 83 int prevBase = (1 << minCachePower);
Chris@929 84 int prevPower = minCachePower;
Chris@929 85 int prevType = 0;
Chris@147 86
Chris@929 87 int result = 0;
Chris@147 88
Chris@147 89 for (unsigned int i = 0; ; ++i) {
Chris@147 90
Chris@1429 91 power = minCachePower + i/2;
Chris@1429 92 type = i % 2;
Chris@147 93
Chris@1429 94 int base;
Chris@1429 95 if (type == 0) {
Chris@1429 96 base = (1 << power);
Chris@1429 97 } else {
Chris@1429 98 base = (((unsigned int)((1 << minCachePower) * sqrt(2.) + 0.01))
Chris@1429 99 << (power - minCachePower));
Chris@1429 100 }
Chris@147 101
Chris@1528 102 // SVCERR << "Testing base " << base << " (i = " << i << ", power = " << power << ", type = " << type << ")" << endl;
Chris@377 103
Chris@377 104 if (base == blockSize) {
Chris@377 105 result = base;
Chris@1552 106 // SVCERR << "Equal, accepting" << endl;
Chris@377 107 break;
Chris@377 108 }
Chris@377 109
Chris@1429 110 if (base > blockSize) {
Chris@1429 111 if (dir == RoundNearest) {
Chris@1429 112 if (base - blockSize < blockSize - prevBase) {
Chris@1429 113 dir = RoundUp;
Chris@1552 114 // SVCERR << "Closer to " << base << " than " << prevBase
Chris@1552 115 // << ", rounding up" << endl;
Chris@1429 116 } else {
Chris@1429 117 dir = RoundDown;
Chris@1552 118 // SVCERR << "Closer to " << prevBase << " than " << base
Chris@1552 119 // << ", rounding down" << endl;
Chris@1429 120 }
Chris@1429 121 }
Chris@1429 122 if (dir == RoundUp) {
Chris@1429 123 result = base;
Chris@1429 124 break;
Chris@1429 125 } else {
Chris@1429 126 type = prevType;
Chris@1429 127 power = prevPower;
Chris@1429 128 result = prevBase;
Chris@1429 129 break;
Chris@1429 130 }
Chris@1429 131 }
Chris@147 132
Chris@1429 133 prevType = type;
Chris@1429 134 prevPower = power;
Chris@1429 135 prevBase = base;
Chris@147 136 }
Chris@147 137
Chris@1324 138 if (result > getMaxZoomLevel().level) {
Chris@1324 139 result = getMaxZoomLevel().level;
Chris@1324 140 }
Chris@1324 141
Chris@1552 142 // SVCERR << "Returning result " << result << endl;
Chris@1552 143
Chris@147 144 return result;
Chris@147 145 }