ScrollableMagRangeCache.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
16 
17 #include "base/HitCount.h"
18 #include "base/Debug.h"
19 
20 #include <iostream>
21 using namespace std;
22 
23 //#define DEBUG_SCROLLABLE_MAG_RANGE_CACHE 1
24 
25 void
27  sv_frame_t newStartFrame)
28 {
29  static HitCount count("ScrollableMagRangeCache: scrolling");
30 
31  int dx = (v->getXForFrame(m_startFrame) -
32  v->getXForFrame(newStartFrame));
33 
34 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
35  SVDEBUG << "ScrollableMagRangeCache::scrollTo: start frame " << m_startFrame
36  << " -> " << newStartFrame << ", dx = " << dx << endl;
37 #endif
38 
39  if (m_startFrame == newStartFrame) {
40  // haven't moved
41  count.hit();
42  return;
43  }
44 
45  m_startFrame = newStartFrame;
46 
47  if (dx == 0) {
48  // haven't moved visibly (even though start frame may have changed)
49  count.hit();
50  return;
51  }
52 
53  int w = int(m_ranges.size());
54 
55  if (dx <= -w || dx >= w) {
56  // scrolled entirely off
57  invalidate();
58  count.miss();
59  return;
60  }
61 
62  count.partial();
63 
64  // dx is in range, cache is scrollable
65 
66  if (dx < 0) {
67  // The new start frame is to the left of the old start
68  // frame. We need to add some empty ranges at the left (start)
69  // end and clip the right end. Assemble -dx new values, then
70  // w+dx old values starting at index 0.
71 
72  auto newRanges = vector<MagnitudeRange>(-dx);
73  newRanges.insert(newRanges.end(),
74  m_ranges.begin(), m_ranges.begin() + (w + dx));
75  m_ranges = newRanges;
76 
77  } else {
78  // The new start frame is to the right of the old start
79  // frame. We want to clip the left (start) end and add some
80  // empty ranges at the right end. Assemble w-dx old values
81  // starting at index dx, then dx new values.
82 
83  auto newRanges = vector<MagnitudeRange>(dx);
84  newRanges.insert(newRanges.begin(),
85  m_ranges.begin() + dx, m_ranges.end());
86  m_ranges = newRanges;
87  }
88 
89 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
90  SVDEBUG << "maxes (" << m_ranges.size() << ") now: ";
91  for (int i = 0; in_range_for(m_ranges, i); ++i) {
92  SVDEBUG << m_ranges[i].getMax() << " ";
93  }
94  SVDEBUG << endl;
95 #endif
96 }
97 
98 MagnitudeRange
99 ScrollableMagRangeCache::getRange(int x, int count) const
100 {
101  MagnitudeRange r;
102 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
103  SVDEBUG << "ScrollableMagRangeCache::getRange(" << x << ", " << count << ")" << endl;
104 #endif
105  for (int i = 0; i < count; ++i) {
106  const auto &cr = m_ranges.at(x + i);
107  if (cr.isSet()) {
108  r.sample(cr);
109  }
110 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
111  SVDEBUG << cr.getMin() << "->" << cr.getMax() << " ";
112 #endif
113  }
114 #ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
115  SVDEBUG << endl;
116 #endif
117  return r;
118 }
119 
120 void
121 ScrollableMagRangeCache::sampleColumn(int column, const MagnitudeRange &r)
122 {
123  if (!in_range_for(m_ranges, column)) {
124  SVCERR << "ERROR: ScrollableMagRangeCache::sampleColumn: column " << column
125  << " is out of range for cache of width " << m_ranges.size()
126  << " (with start frame " << m_startFrame << ")" << endl;
127  throw logic_error("column out of range");
128  } else {
129  m_ranges[column].sample(r);
130  }
131 }
132 
MagnitudeRange getRange(int column) const
Get the magnitude range for a single column.
Interface for classes that provide geometry information (such as size, start frame, and a large number of other properties) about the disposition of a layer.
void sampleColumn(int column, const MagnitudeRange &r)
Update a column in the cache, by column index.
virtual int getXForFrame(sv_frame_t frame) const =0
Return the pixel x-coordinate corresponding to a given sample frame (which may be negative)...
void scrollTo(const LayerGeometryProvider *v, sv_frame_t newStartFrame)
Set the new start frame for the cache, according to the geometry of the supplied LayerGeometryProvide...