annotate layer/ScrollableMagRangeCache.cpp @ 1135:628cd329c241 spectrogram-minor-refactor

Use a count of bins rather than min and max bins (because the name maxbin tells us nothing about whether the range is inclusive or not)
author Chris Cannam
date Wed, 03 Aug 2016 14:20:27 +0100
parents 745a868f0abf
children 9ff838a64461
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@1118 17 #include <iostream>
Chris@1118 18 using namespace std;
Chris@1118 19
Chris@1118 20 #define DEBUG_SCROLLABLE_MAG_RANGE_CACHE 1
Chris@1118 21
Chris@1118 22 void
Chris@1118 23 ScrollableMagRangeCache::scrollTo(const LayerGeometryProvider *v,
Chris@1118 24 sv_frame_t newStartFrame)
Chris@1122 25 {
Chris@1118 26 int dx = (v->getXForFrame(m_startFrame) -
Chris@1118 27 v->getXForFrame(newStartFrame));
Chris@1118 28
Chris@1118 29 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
Chris@1118 30 cerr << "ScrollableMagRangeCache::scrollTo: start frame " << m_startFrame
Chris@1118 31 << " -> " << newStartFrame << ", dx = " << dx << endl;
Chris@1118 32 #endif
Chris@1122 33
Chris@1122 34 if (m_startFrame == newStartFrame) {
Chris@1122 35 // haven't moved
Chris@1122 36 return;
Chris@1122 37 }
Chris@1118 38
Chris@1118 39 m_startFrame = newStartFrame;
Chris@1118 40
Chris@1118 41 if (dx == 0) {
Chris@1118 42 // haven't moved visibly (even though start frame may have changed)
Chris@1118 43 return;
Chris@1118 44 }
Chris@1118 45
Chris@1118 46 int w = int(m_ranges.size());
Chris@1118 47
Chris@1118 48 if (dx <= -w || dx >= w) {
Chris@1118 49 // scrolled entirely off
Chris@1118 50 invalidate();
Chris@1118 51 return;
Chris@1118 52 }
Chris@1118 53
Chris@1118 54 // dx is in range, cache is scrollable
Chris@1118 55
Chris@1118 56 if (dx < 0) {
Chris@1118 57 // The new start frame is to the left of the old start
Chris@1118 58 // frame. We need to add some empty ranges at the left (start)
Chris@1118 59 // end and clip the right end. Assemble -dx new values, then
Chris@1118 60 // w+dx old values starting at index 0.
Chris@1118 61
Chris@1118 62 auto newRanges = vector<MagnitudeRange>(-dx);
Chris@1118 63 newRanges.insert(newRanges.end(),
Chris@1122 64 m_ranges.begin(), m_ranges.begin() + (w + dx));
Chris@1118 65 m_ranges = newRanges;
Chris@1118 66
Chris@1118 67 } else {
Chris@1118 68 // The new start frame is to the right of the old start
Chris@1118 69 // frame. We want to clip the left (start) end and add some
Chris@1118 70 // empty ranges at the right end. Assemble w-dx old values
Chris@1118 71 // starting at index dx, then dx new values.
Chris@1118 72
Chris@1118 73 auto newRanges = vector<MagnitudeRange>(dx);
Chris@1118 74 newRanges.insert(newRanges.begin(),
Chris@1118 75 m_ranges.begin() + dx, m_ranges.end());
Chris@1118 76 m_ranges = newRanges;
Chris@1118 77 }
Chris@1122 78
Chris@1132 79 //!!! cerr << "maxes now: ";
Chris@1132 80 // for (int i = 0; in_range_for(m_ranges, i); ++i) {
Chris@1132 81 // cerr << m_ranges[i].getMax() << " ";
Chris@1132 82 // }
Chris@1132 83 // cerr << endl;
Chris@1122 84 }
Chris@1122 85
Chris@1122 86 MagnitudeRange
Chris@1122 87 ScrollableMagRangeCache::getRange(int x, int count) const
Chris@1122 88 {
Chris@1122 89 MagnitudeRange r;
Chris@1122 90 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
Chris@1122 91 cerr << "ScrollableMagRangeCache::getRange(" << x << ", " << count << ")" << endl;
Chris@1122 92 #endif
Chris@1122 93 for (int i = 0; i < count; ++i) {
Chris@1122 94 r.sample(m_ranges.at(x + i));
Chris@1122 95 }
Chris@1122 96 return r;
Chris@1118 97 }
Chris@1118 98
Chris@1118 99 void
Chris@1120 100 ScrollableMagRangeCache::sampleColumn(int column, const MagnitudeRange &r)
Chris@1120 101 {
Chris@1120 102 if (!in_range_for(m_ranges, column)) {
Chris@1120 103 cerr << "ERROR: ScrollableMagRangeCache::sampleColumn: column " << column
Chris@1120 104 << " is out of range for cache of width " << m_ranges.size()
Chris@1120 105 << " (with start frame " << m_startFrame << ")" << endl;
Chris@1120 106 throw logic_error("column out of range");
Chris@1120 107 } else {
Chris@1120 108 m_ranges[column].sample(r);
Chris@1120 109 }
Chris@1120 110 }
Chris@1120 111
Chris@1122 112 //!!! unneeded?
Chris@1120 113 void
Chris@1118 114 ScrollableMagRangeCache::sampleColumn(const LayerGeometryProvider *v,
Chris@1118 115 sv_frame_t frame,
Chris@1118 116 const MagnitudeRange &r)
Chris@1118 117 {
Chris@1118 118 int x = (v->getXForFrame(frame) -
Chris@1118 119 v->getXForFrame(m_startFrame));
Chris@1118 120
Chris@1118 121 if (!in_range_for(m_ranges, x)) {
Chris@1118 122 cerr << "WARNING: ScrollableMagRangeCache::sampleColumn: column " << x
Chris@1118 123 << " arising from frame " << frame << " is out of range for cache "
Chris@1120 124 << "of width " << m_ranges.size()
Chris@1120 125 << " (with start frame " << m_startFrame << ")" << endl;
Chris@1120 126 throw logic_error("column out of range");
Chris@1118 127 } else {
Chris@1118 128 sampleColumn(x, r);
Chris@1118 129 }
Chris@1118 130 }
Chris@1118 131