annotate layer/ScrollableMagRangeCache.cpp @ 1212:a1ee3108d1d3 3.0-integration

Make the colour 3d plot renderer able to support more than one level of peak cache; introduce a second "peak" cache for the spectrogram layer that actually has a 1-1 column relationship with the underlying FFT model, and use it in addition to the existing peak cache if memory is plentiful. Makes spectrograms appear much faster in many common situations.
author Chris Cannam
date Thu, 05 Jan 2017 14:02:54 +0000
parents f2f43802718b
children a34a2a25907c
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@1118 26 sv_frame_t newStartFrame)
Chris@1122 27 {
Chris@1164 28 static HitCount count("ScrollableMagRangeCache: scrolling");
Chris@1164 29
Chris@1118 30 int dx = (v->getXForFrame(m_startFrame) -
Chris@1118 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@1118 35 << " -> " << newStartFrame << ", dx = " << dx << endl;
Chris@1118 36 #endif
Chris@1122 37
Chris@1122 38 if (m_startFrame == newStartFrame) {
Chris@1122 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@1118 47 // haven't moved visibly (even though start frame may have changed)
Chris@1164 48 count.hit();
Chris@1118 49 return;
Chris@1118 50 }
Chris@1118 51
Chris@1118 52 int w = int(m_ranges.size());
Chris@1118 53
Chris@1118 54 if (dx <= -w || dx >= w) {
Chris@1118 55 // scrolled entirely off
Chris@1118 56 invalidate();
Chris@1164 57 count.miss();
Chris@1118 58 return;
Chris@1118 59 }
Chris@1164 60
Chris@1164 61 count.partial();
Chris@1118 62
Chris@1118 63 // dx is in range, cache is scrollable
Chris@1118 64
Chris@1118 65 if (dx < 0) {
Chris@1118 66 // The new start frame is to the left of the old start
Chris@1118 67 // frame. We need to add some empty ranges at the left (start)
Chris@1118 68 // end and clip the right end. Assemble -dx new values, then
Chris@1118 69 // w+dx old values starting at index 0.
Chris@1118 70
Chris@1118 71 auto newRanges = vector<MagnitudeRange>(-dx);
Chris@1118 72 newRanges.insert(newRanges.end(),
Chris@1122 73 m_ranges.begin(), m_ranges.begin() + (w + dx));
Chris@1118 74 m_ranges = newRanges;
Chris@1118 75
Chris@1118 76 } else {
Chris@1118 77 // The new start frame is to the right of the old start
Chris@1118 78 // frame. We want to clip the left (start) end and add some
Chris@1118 79 // empty ranges at the right end. Assemble w-dx old values
Chris@1118 80 // starting at index dx, then dx new values.
Chris@1118 81
Chris@1118 82 auto newRanges = vector<MagnitudeRange>(dx);
Chris@1118 83 newRanges.insert(newRanges.begin(),
Chris@1118 84 m_ranges.begin() + dx, m_ranges.end());
Chris@1118 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@1136 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@1122 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@1120 114 cerr << "ERROR: ScrollableMagRangeCache::sampleColumn: column " << column
Chris@1120 115 << " is out of range for cache of width " << m_ranges.size()
Chris@1120 116 << " (with start frame " << m_startFrame << ")" << endl;
Chris@1120 117 throw logic_error("column out of range");
Chris@1120 118 } else {
Chris@1120 119 m_ranges[column].sample(r);
Chris@1120 120 }
Chris@1120 121 }
Chris@1120 122