annotate layer/ScrollableMagRangeCache.cpp @ 1330:c1f719094c25 zoom

Ensure getFrameForX returns value on zoom blocksize boundary; take advantage of that (this is essentially reverting to the same behaviour as in the default branch, which we should probably have done all along)
author Chris Cannam
date Fri, 21 Sep 2018 11:50:05 +0100
parents a34a2a25907c
children 6dc3a36d9794
rev   line source
Chris@1118 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1118 2
Chris@1118 3 /*
Chris@1118 4 Sonic Visualiser
Chris@1118 5 An audio file viewer and annotation editor.
Chris@1118 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1118 7
Chris@1118 8 This program is free software; you can redistribute it and/or
Chris@1118 9 modify it under the terms of the GNU General Public License as
Chris@1118 10 published by the Free Software Foundation; either version 2 of the
Chris@1118 11 License, or (at your option) any later version. See the file
Chris@1118 12 COPYING included with this distribution for more information.
Chris@1118 13 */
Chris@1118 14
Chris@1118 15 #include "ScrollableMagRangeCache.h"
Chris@1118 16
Chris@1164 17 #include "base/HitCount.h"
Chris@1164 18
Chris@1118 19 #include <iostream>
Chris@1118 20 using namespace std;
Chris@1118 21
Chris@1143 22 //#define DEBUG_SCROLLABLE_MAG_RANGE_CACHE 1
Chris@1118 23
Chris@1118 24 void
Chris@1118 25 ScrollableMagRangeCache::scrollTo(const LayerGeometryProvider *v,
Chris@1266 26 sv_frame_t newStartFrame)
Chris@1266 27 {
Chris@1164 28 static HitCount count("ScrollableMagRangeCache: scrolling");
Chris@1164 29
Chris@1118 30 int dx = (v->getXForFrame(m_startFrame) -
Chris@1266 31 v->getXForFrame(newStartFrame));
Chris@1118 32
Chris@1118 33 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
Chris@1118 34 cerr << "ScrollableMagRangeCache::scrollTo: start frame " << m_startFrame
Chris@1266 35 << " -> " << newStartFrame << ", dx = " << dx << endl;
Chris@1118 36 #endif
Chris@1122 37
Chris@1122 38 if (m_startFrame == newStartFrame) {
Chris@1266 39 // haven't moved
Chris@1164 40 count.hit();
Chris@1122 41 return;
Chris@1122 42 }
Chris@1118 43
Chris@1118 44 m_startFrame = newStartFrame;
Chris@1118 45
Chris@1118 46 if (dx == 0) {
Chris@1266 47 // haven't moved visibly (even though start frame may have changed)
Chris@1164 48 count.hit();
Chris@1266 49 return;
Chris@1118 50 }
Chris@1266 51
Chris@1118 52 int w = int(m_ranges.size());
Chris@1118 53
Chris@1118 54 if (dx <= -w || dx >= w) {
Chris@1266 55 // scrolled entirely off
Chris@1266 56 invalidate();
Chris@1164 57 count.miss();
Chris@1266 58 return;
Chris@1118 59 }
Chris@1164 60
Chris@1164 61 count.partial();
Chris@1266 62
Chris@1118 63 // dx is in range, cache is scrollable
Chris@1118 64
Chris@1118 65 if (dx < 0) {
Chris@1266 66 // The new start frame is to the left of the old start
Chris@1266 67 // frame. We need to add some empty ranges at the left (start)
Chris@1266 68 // end and clip the right end. Assemble -dx new values, then
Chris@1266 69 // w+dx old values starting at index 0.
Chris@1118 70
Chris@1266 71 auto newRanges = vector<MagnitudeRange>(-dx);
Chris@1266 72 newRanges.insert(newRanges.end(),
Chris@1266 73 m_ranges.begin(), m_ranges.begin() + (w + dx));
Chris@1266 74 m_ranges = newRanges;
Chris@1266 75
Chris@1118 76 } else {
Chris@1266 77 // The new start frame is to the right of the old start
Chris@1266 78 // frame. We want to clip the left (start) end and add some
Chris@1266 79 // empty ranges at the right end. Assemble w-dx old values
Chris@1266 80 // starting at index dx, then dx new values.
Chris@1118 81
Chris@1266 82 auto newRanges = vector<MagnitudeRange>(dx);
Chris@1266 83 newRanges.insert(newRanges.begin(),
Chris@1266 84 m_ranges.begin() + dx, m_ranges.end());
Chris@1266 85 m_ranges = newRanges;
Chris@1118 86 }
Chris@1122 87
Chris@1143 88 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
Chris@1136 89 cerr << "maxes (" << m_ranges.size() << ") now: ";
Chris@1136 90 for (int i = 0; in_range_for(m_ranges, i); ++i) {
Chris@1266 91 cerr << m_ranges[i].getMax() << " ";
Chris@1136 92 }
Chris@1136 93 cerr << endl;
Chris@1143 94 #endif
Chris@1122 95 }
Chris@1122 96
Chris@1122 97 MagnitudeRange
Chris@1122 98 ScrollableMagRangeCache::getRange(int x, int count) const
Chris@1122 99 {
Chris@1122 100 MagnitudeRange r;
Chris@1122 101 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
Chris@1122 102 cerr << "ScrollableMagRangeCache::getRange(" << x << ", " << count << ")" << endl;
Chris@1122 103 #endif
Chris@1122 104 for (int i = 0; i < count; ++i) {
Chris@1266 105 r.sample(m_ranges.at(x + i));
Chris@1122 106 }
Chris@1122 107 return r;
Chris@1118 108 }
Chris@1118 109
Chris@1118 110 void
Chris@1120 111 ScrollableMagRangeCache::sampleColumn(int column, const MagnitudeRange &r)
Chris@1120 112 {
Chris@1120 113 if (!in_range_for(m_ranges, column)) {
Chris@1266 114 cerr << "ERROR: ScrollableMagRangeCache::sampleColumn: column " << column
Chris@1266 115 << " is out of range for cache of width " << m_ranges.size()
Chris@1266 116 << " (with start frame " << m_startFrame << ")" << endl;
Chris@1266 117 throw logic_error("column out of range");
Chris@1120 118 } else {
Chris@1266 119 m_ranges[column].sample(r);
Chris@1120 120 }
Chris@1120 121 }
Chris@1120 122