annotate data/model/PowerOfSqrtTwoZoomConstraint.cpp @ 1527:710e6250a401 zoom

Merge from default branch
author Chris Cannam
date Mon, 17 Sep 2018 13:51:14 +0100
parents d4a28d1479a8 48e9f538e6e9
children c1c45c5146bb
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@147 21
Chris@1324 22 ZoomLevel
Chris@1324 23 PowerOfSqrtTwoZoomConstraint::getNearestZoomLevel(ZoomLevel requested,
Chris@1429 24 RoundingDirection dir) const
Chris@147 25 {
Chris@147 26 int type, power;
Chris@1324 27 int blockSize;
Chris@1324 28
Chris@1324 29 if (requested.zone == ZoomLevel::FramesPerPixel) {
Chris@1324 30 blockSize = getNearestBlockSize(requested.level, type, power, dir);
Chris@1324 31 return { requested.zone, blockSize };
Chris@1324 32 } else {
Chris@1324 33 RoundingDirection opposite = dir;
Chris@1324 34 if (dir == RoundUp) opposite = RoundDown;
Chris@1324 35 else if (dir == RoundDown) opposite = RoundUp;
Chris@1324 36 blockSize = getNearestBlockSize(requested.level, type, power, opposite);
Chris@1324 37 if (blockSize > getMinZoomLevel().level) {
Chris@1324 38 blockSize = getMinZoomLevel().level;
Chris@1324 39 }
Chris@1324 40 if (blockSize == 1) {
Chris@1324 41 return { ZoomLevel::FramesPerPixel, 1 };
Chris@1324 42 } else {
Chris@1324 43 return { requested.zone, blockSize };
Chris@1324 44 }
Chris@1324 45 }
Chris@147 46 }
Chris@147 47
Chris@929 48 int
Chris@929 49 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(int blockSize,
Chris@1429 50 int &type,
Chris@1429 51 int &power,
Chris@1429 52 RoundingDirection dir) const
Chris@147 53 {
Chris@843 54 // cerr << "given " << blockSize << endl;
Chris@147 55
Chris@929 56 int minCachePower = getMinCachePower();
Chris@147 57
Chris@929 58 if (blockSize < (1 << minCachePower)) {
Chris@1429 59 type = -1;
Chris@1429 60 power = 0;
Chris@1429 61 float val = 1.0, prevVal = 1.0;
Chris@1429 62 while (val + 0.01 < blockSize) {
Chris@1429 63 prevVal = val;
Chris@1429 64 val *= sqrtf(2.f);
Chris@1429 65 }
Chris@1429 66 int rval;
Chris@1429 67 if (dir == RoundUp) rval = int(val + 0.01f);
Chris@1429 68 else if (dir == RoundDown) rval = int(prevVal + 0.01f);
Chris@1429 69 else if (val - float(blockSize) <
Chris@1038 70 float(blockSize) - prevVal) rval = int(val + 0.01f);
Chris@1429 71 else rval = int(prevVal + 0.01);
Chris@1429 72 // SVDEBUG << "returning " << rval << endl;
Chris@1429 73 return rval;
Chris@147 74 }
Chris@147 75
Chris@929 76 int prevBase = (1 << minCachePower);
Chris@929 77 int prevPower = minCachePower;
Chris@929 78 int prevType = 0;
Chris@147 79
Chris@929 80 int result = 0;
Chris@147 81
Chris@147 82 for (unsigned int i = 0; ; ++i) {
Chris@147 83
Chris@1429 84 power = minCachePower + i/2;
Chris@1429 85 type = i % 2;
Chris@147 86
Chris@1429 87 int base;
Chris@1429 88 if (type == 0) {
Chris@1429 89 base = (1 << power);
Chris@1429 90 } else {
Chris@1429 91 base = (((unsigned int)((1 << minCachePower) * sqrt(2.) + 0.01))
Chris@1429 92 << (power - minCachePower));
Chris@1429 93 }
Chris@147 94
Chris@1429 95 // SVDEBUG << "Testing base " << base << endl;
Chris@377 96
Chris@377 97 if (base == blockSize) {
Chris@377 98 result = base;
Chris@377 99 break;
Chris@377 100 }
Chris@377 101
Chris@1429 102 if (base > blockSize) {
Chris@1429 103 if (dir == RoundNearest) {
Chris@1429 104 if (base - blockSize < blockSize - prevBase) {
Chris@1429 105 dir = RoundUp;
Chris@1429 106 } else {
Chris@1429 107 dir = RoundDown;
Chris@1429 108 }
Chris@1429 109 }
Chris@1429 110 if (dir == RoundUp) {
Chris@1429 111 result = base;
Chris@1429 112 break;
Chris@1429 113 } else {
Chris@1429 114 type = prevType;
Chris@1429 115 power = prevPower;
Chris@1429 116 result = prevBase;
Chris@1429 117 break;
Chris@1429 118 }
Chris@1429 119 }
Chris@147 120
Chris@1429 121 prevType = type;
Chris@1429 122 prevPower = power;
Chris@1429 123 prevBase = base;
Chris@147 124 }
Chris@147 125
Chris@1324 126 if (result > getMaxZoomLevel().level) {
Chris@1324 127 result = getMaxZoomLevel().level;
Chris@1324 128 }
Chris@1324 129
Chris@147 130 return result;
Chris@147 131 }