annotate layer/ScrollableMagRangeCache.h @ 1386:fc3d89f88690 spectrogramparam

Use log-frequency rather than log-bin for calculating x coord in spectrum. This has the advantage that frequency positions don't move when we change the window size or oversampling ratio, but it does give us an unhelpfully large amount of space for very low frequencies - to be considered
author Chris Cannam
date Mon, 12 Nov 2018 11:34:34 +0000
parents bc2cb82050a0
children
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 #ifndef SCROLLABLE_MAG_RANGE_CACHE_H
Chris@1118 16 #define SCROLLABLE_MAG_RANGE_CACHE_H
Chris@1118 17
Chris@1118 18 #include "base/BaseTypes.h"
Chris@1118 19 #include "base/MagnitudeRange.h"
Chris@1118 20
Chris@1118 21 #include "LayerGeometryProvider.h"
Chris@1118 22
Chris@1118 23 /**
Chris@1118 24 * A cached set of magnitude range records for a view that scrolls
Chris@1118 25 * horizontally, such as a spectrogram. The cache object holds a
Chris@1118 26 * magnitude range per column of the view, can report width (likely
Chris@1118 27 * the same as the underlying view, but it's the caller's
Chris@1118 28 * responsibility to set the size appropriately), can scroll the set
Chris@1118 29 * of ranges, and can report and update which columns have had a range
Chris@1118 30 * specified.
Chris@1118 31 *
Chris@1118 32 * The only way to *update* the valid area in a cache is to update the
Chris@1118 33 * magnitude range for a column using the sampleColumn call.
Chris@1118 34 */
Chris@1118 35 class ScrollableMagRangeCache
Chris@1118 36 {
Chris@1118 37 public:
Chris@1118 38 ScrollableMagRangeCache() :
Chris@1325 39 m_startFrame(0)
Chris@1118 40 {}
Chris@1118 41
Chris@1118 42 void invalidate() {
Chris@1266 43 m_ranges = std::vector<MagnitudeRange>(m_ranges.size());
Chris@1118 44 }
Chris@1118 45
Chris@1118 46 int getWidth() const {
Chris@1266 47 return int(m_ranges.size());
Chris@1118 48 }
Chris@1118 49
Chris@1118 50 /**
Chris@1118 51 * Set the width of the cache in columns. If the new size differs
Chris@1118 52 * from the current size, the cache is invalidated.
Chris@1118 53 */
Chris@1118 54 void resize(int newWidth) {
Chris@1118 55 if (getWidth() != newWidth) {
Chris@1266 56 m_ranges = std::vector<MagnitudeRange>(newWidth);
Chris@1118 57 }
Chris@1118 58 }
Chris@1266 59
Chris@1325 60 ZoomLevel getZoomLevel() const {
Chris@1266 61 return m_zoomLevel;
Chris@1118 62 }
Chris@1118 63
Chris@1118 64 /**
Chris@1118 65 * Set the zoom level. If the new zoom level differs from the
Chris@1118 66 * current one, the cache is invalidated. (Determining whether to
Chris@1118 67 * invalidate the cache here is the only thing the zoom level is
Chris@1118 68 * used for.)
Chris@1118 69 */
Chris@1325 70 void setZoomLevel(ZoomLevel zoom) {
Chris@1325 71 using namespace std::rel_ops;
Chris@1118 72 if (m_zoomLevel != zoom) {
Chris@1118 73 m_zoomLevel = zoom;
Chris@1118 74 invalidate();
Chris@1118 75 }
Chris@1118 76 }
Chris@1118 77
Chris@1118 78 sv_frame_t getStartFrame() const {
Chris@1266 79 return m_startFrame;
Chris@1118 80 }
Chris@1118 81
Chris@1118 82 /**
Chris@1118 83 * Set the start frame. If the new start frame differs from the
Chris@1118 84 * current one, the cache is invalidated. To scroll, i.e. to set
Chris@1118 85 * the start frame while retaining cache validity where possible,
Chris@1118 86 * use scrollTo() instead.
Chris@1118 87 */
Chris@1118 88 void setStartFrame(sv_frame_t frame) {
Chris@1118 89 if (m_startFrame != frame) {
Chris@1118 90 m_startFrame = frame;
Chris@1118 91 invalidate();
Chris@1118 92 }
Chris@1118 93 }
Chris@1118 94
Chris@1118 95 bool isColumnSet(int column) const {
Chris@1266 96 return in_range_for(m_ranges, column) && m_ranges.at(column).isSet();
Chris@1118 97 }
Chris@1119 98
Chris@1119 99 bool areColumnsSet(int x, int count) const {
Chris@1266 100 for (int i = 0; i < count; ++i) {
Chris@1266 101 if (!isColumnSet(x + i)) return false;
Chris@1266 102 }
Chris@1266 103 return true;
Chris@1119 104 }
Chris@1118 105
Chris@1119 106 /**
Chris@1119 107 * Get the magnitude range for a single column.
Chris@1119 108 */
Chris@1119 109 MagnitudeRange getRange(int column) const {
Chris@1266 110 return m_ranges.at(column);
Chris@1118 111 }
Chris@1118 112
Chris@1118 113 /**
Chris@1119 114 * Get the magnitude range for a range of columns.
Chris@1119 115 */
Chris@1122 116 MagnitudeRange getRange(int x, int count) const;
Chris@1119 117
Chris@1119 118 /**
Chris@1118 119 * Set the new start frame for the cache, according to the
Chris@1118 120 * geometry of the supplied LayerGeometryProvider, if possible
Chris@1118 121 * also moving along any existing valid data within the cache so
Chris@1118 122 * that it continues to be valid for the new start frame.
Chris@1118 123 */
Chris@1118 124 void scrollTo(const LayerGeometryProvider *v, sv_frame_t newStartFrame);
Chris@1118 125
Chris@1118 126 /**
Chris@1120 127 * Update a column in the cache, by column index. (Column zero is
Chris@1120 128 * the first column in the cache, it has nothing to do with any
Chris@1120 129 * underlying model that the cache may be used with.)
Chris@1118 130 */
Chris@1120 131 void sampleColumn(int column, const MagnitudeRange &r);
Chris@1118 132
Chris@1118 133 private:
Chris@1118 134 std::vector<MagnitudeRange> m_ranges;
Chris@1118 135 sv_frame_t m_startFrame;
Chris@1325 136 ZoomLevel m_zoomLevel;
Chris@1118 137 };
Chris@1118 138
Chris@1118 139 #endif