annotate data/model/PowerOfSqrtTwoZoomConstraint.cpp @ 458:f60360209e5c

* Fix race condition in FFTFileCache when reading from the same FFT model from multiple threads (e.g. when applying more than one plugin at once)
author Chris Cannam
date Wed, 15 Oct 2008 12:08:02 +0000
parents 166c22eff678
children d7f3dfe6f9a4
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@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@377 78
Chris@377 79 if (base == blockSize) {
Chris@377 80 result = base;
Chris@377 81 break;
Chris@377 82 }
Chris@377 83
Chris@377 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 }