annotate layer/WaveformLayer.h @ 1509:8145a9c4c253

The default key frame map is not working well at the moment, because its extents are not being properly updated as the models they depend on are loaded. Leave it empty for now.
author Chris Cannam
date Tue, 17 Sep 2019 12:50:34 +0100
parents 696e569ff21b
children 10fe8124dc17
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@59 9 This program is free software; you can redistribute it and/or
Chris@59 10 modify it under the terms of the GNU General Public License as
Chris@59 11 published by the Free Software Foundation; either version 2 of the
Chris@59 12 License, or (at your option) any later version. See the file
Chris@59 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@1407 16 #ifndef SV_WAVEFORM_LAYER_H
Chris@1407 17 #define SV_WAVEFORM_LAYER_H
Chris@0 18
Chris@0 19 #include <QRect>
Chris@0 20
Chris@287 21 #include "SingleColourLayer.h"
Chris@0 22
Chris@1375 23 #include "base/ZoomLevel.h"
Chris@1375 24
Chris@128 25 #include "data/model/RangeSummarisableTimeValueModel.h"
Chris@0 26
Chris@0 27 class View;
Chris@0 28 class QPainter;
Chris@0 29 class QPixmap;
Chris@0 30
Chris@287 31 class WaveformLayer : public SingleColourLayer
Chris@0 32 {
Chris@0 33 Q_OBJECT
Chris@0 34
Chris@0 35 public:
Chris@44 36 WaveformLayer();
Chris@0 37 ~WaveformLayer();
Chris@0 38
Chris@1470 39 const ZoomConstraint *getZoomConstraint() const override;
Chris@1470 40 ModelId getModel() const override { return m_model; }
Chris@1406 41 void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override;
Chris@0 42
Chris@1406 43 QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const override;
Chris@25 44
Chris@1406 45 ColourSignificance getLayerColourSignificance() const override {
Chris@287 46 return ColourAndBackgroundSignificant;
Chris@287 47 }
Chris@287 48
Chris@1406 49 int getVerticalScaleWidth(LayerGeometryProvider *v, bool detailed, QPainter &) const override;
Chris@1406 50 void paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const override;
Chris@0 51
Chris@1470 52 void setModel(ModelId model); // a RangeSummarisableTimeValueModel
Chris@0 53
Chris@1406 54 PropertyList getProperties() const override;
Chris@1406 55 QString getPropertyLabel(const PropertyName &) const override;
Chris@1406 56 QString getPropertyIconName(const PropertyName &) const override;
Chris@1406 57 PropertyType getPropertyType(const PropertyName &) const override;
Chris@1406 58 QString getPropertyGroupName(const PropertyName &) const override;
Chris@1406 59 int getPropertyRangeAndValue(const PropertyName &,
Chris@1406 60 int *min, int *max, int *deflt) const override;
Chris@1406 61 QString getPropertyValueLabel(const PropertyName &,
Chris@1406 62 int value) const override;
Chris@1406 63 RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const override;
Chris@1406 64 void setProperty(const PropertyName &, int value) override;
Chris@0 65
Chris@0 66 /**
Chris@0 67 * Set the gain multiplier for sample values in this view.
Chris@0 68 *
Chris@0 69 * The default is 1.0.
Chris@0 70 */
Chris@0 71 void setGain(float gain);
Chris@0 72 float getGain() const { return m_gain; }
Chris@0 73
Chris@0 74 /**
Chris@67 75 * Toggle automatic normalization of the currently visible waveform.
Chris@67 76 */
Chris@67 77 void setAutoNormalize(bool);
Chris@67 78 bool getAutoNormalize() const { return m_autoNormalize; }
Chris@67 79
Chris@67 80 /**
Chris@0 81 * Set whether to display mean values as a lighter-coloured area
Chris@0 82 * beneath the peaks. Rendering will be slightly faster without
Chris@0 83 * but arguably prettier with.
Chris@0 84 *
Chris@0 85 * The default is to display means.
Chris@0 86 */
Chris@0 87 void setShowMeans(bool);
Chris@0 88 bool getShowMeans() const { return m_showMeans; }
Chris@0 89
Chris@67 90 enum ChannelMode { SeparateChannels, MixChannels, MergeChannels };
Chris@0 91
Chris@0 92 /**
Chris@0 93 * Specify whether multi-channel audio data should be displayed
Chris@67 94 * with a separate axis per channel (SeparateChannels), with a
Chris@0 95 * single synthetic axis showing channel 0 above the axis and
Chris@67 96 * channel 1 below (MergeChannels), or with a single axis showing
Chris@67 97 * the average of the channels (MixChannels).
Chris@0 98 *
Chris@0 99 * MergeChannels does not work for files with more than 2
Chris@0 100 * channels.
Chris@0 101 *
Chris@0 102 * The default is SeparateChannels.
Chris@0 103 */
Chris@0 104 void setChannelMode(ChannelMode);
Chris@0 105 ChannelMode getChannelMode() const { return m_channelMode; }
Chris@0 106
Chris@0 107
Chris@0 108 /**
Chris@0 109 * Specify the channel to use from the source model. A value of
Chris@0 110 * -1 means to show all available channels (laid out to the
Chris@0 111 * channel mode). The default is -1.
Chris@0 112 */
Chris@0 113 void setChannel(int);
Chris@0 114 int getChannel() const { return m_channel; }
Chris@0 115
Chris@0 116
Chris@0 117 enum Scale { LinearScale, MeterScale, dBScale };
Chris@0 118
Chris@0 119 /**
Chris@0 120 * Specify the vertical scale for sample levels. With LinearScale,
Chris@0 121 * the scale is directly proportional to the raw [-1, +1)
Chris@0 122 * floating-point audio sample values. With dBScale the
Chris@0 123 * vertical scale is proportional to dB level (truncated at
Chris@0 124 * -50dB). MeterScale provides a hybrid variable scale based on
Chris@0 125 * IEC meter scale, intended to provide a clear overview at
Chris@0 126 * relatively small heights.
Chris@0 127 *
Chris@0 128 * Note that the effective gain (see setGain()) is applied before
Chris@0 129 * vertical scaling.
Chris@0 130 *
Chris@0 131 * The default is LinearScale.
Chris@0 132 */
Chris@0 133 void setScale(Scale);
Chris@0 134 Scale getScale() const { return m_scale; }
Chris@0 135
Chris@0 136 /**
Chris@709 137 * Specify the height of the middle of the waveform track or
Chris@709 138 * tracks within the layer, from 0.0 to 1.0.
Chris@709 139 *
Chris@709 140 * A value of 0.0 would indicate that the waveform occupies
Chris@709 141 * effectively no space at the very top of the layer; 1.0 would
Chris@709 142 * indicate that the waveform occupies no space at the very
Chris@709 143 * bottom; the default value of 0.5 indicates that it occupies the
Chris@709 144 * whole layer, centred at the middle.
Chris@709 145 */
Chris@905 146 void setMiddleLineHeight(double);
Chris@905 147 double getMiddleLineHeight() const { return m_middleLineHeight; }
Chris@709 148
Chris@709 149 /**
Chris@0 150 * Enable or disable aggressive pixmap cacheing. If enabled,
Chris@0 151 * waveforms will be rendered to an off-screen pixmap and
Chris@0 152 * refreshed from there instead of being redrawn from the peak
Chris@0 153 * data each time. This may be faster if the data and zoom level
Chris@0 154 * do not change often, but it may be slower for frequently zoomed
Chris@0 155 * data and it will only work if the waveform is the "bottom"
Chris@0 156 * layer on the displayed widget, as each refresh will erase
Chris@0 157 * anything beneath the waveform.
Chris@0 158 *
Chris@0 159 * This is intended specifically for a panner widget display in
Chris@0 160 * which the waveform never moves, zooms, or changes, but some
Chris@0 161 * graphic such as a panner outline is frequently redrawn over the
Chris@0 162 * waveform. This situation would necessitate a lot of waveform
Chris@0 163 * refresh if the default cacheing strategy was used.
Chris@0 164 *
Chris@0 165 * The default is not to use aggressive cacheing.
Chris@0 166 */
Chris@0 167 void setAggressiveCacheing(bool);
Chris@0 168 bool getAggressiveCacheing() const { return m_aggressive; }
Chris@0 169
Chris@1406 170 bool isLayerScrollable(const LayerGeometryProvider *) const override;
Chris@67 171
Chris@1406 172 int getCompletion(LayerGeometryProvider *) const override;
Chris@0 173
Chris@1406 174 bool getValueExtents(double &min, double &max,
Chris@1406 175 bool &log, QString &unit) const override;
Chris@79 176
Chris@1406 177 bool getYScaleValue(const LayerGeometryProvider *v, int y,
Chris@1406 178 double &value, QString &unit) const override;
Chris@274 179
Chris@1406 180 bool getYScaleDifference(const LayerGeometryProvider *v, int y0, int y1,
Chris@1406 181 double &diff, QString &unit) const override;
Chris@261 182
Chris@1406 183 void toXml(QTextStream &stream, QString indent = "",
Chris@1406 184 QString extraAttributes = "") const override;
Chris@6 185
Chris@1406 186 void setProperties(const QXmlAttributes &attributes) override;
Chris@11 187
Chris@1406 188 int getVerticalZoomSteps(int &defaultStep) const override;
Chris@1406 189 int getCurrentVerticalZoomStep() const override;
Chris@1406 190 void setVerticalZoomStep(int) override;
Chris@133 191
Chris@1406 192 bool canExistWithoutModel() const override { return true; }
Chris@947 193
Chris@0 194 protected:
Chris@1367 195 double dBscale(double sample, int m) const;
Chris@0 196
Chris@1470 197 ModelId m_model;
Chris@0 198
Chris@1338 199 typedef std::vector<RangeSummarisableTimeValueModel::RangeBlock> RangeVec;
Chris@1338 200
Chris@0 201 /// Return value is number of channels displayed
Chris@805 202 int getChannelArrangement(int &min, int &max,
Chris@1332 203 bool &merging, bool &mixing) const;
Chris@0 204
Chris@1338 205 void paintChannel
Chris@1336 206 (LayerGeometryProvider *, QPainter *paint, QRect rect, int channel,
Chris@1338 207 const RangeVec &ranges,
Chris@1336 208 int blockSize, sv_frame_t frame0, sv_frame_t frame1) const;
Chris@1336 209
Chris@1335 210 void paintChannelScaleGuides(LayerGeometryProvider *, QPainter *paint,
Chris@1335 211 QRect rect, int channel) const;
Chris@1338 212
Chris@1338 213 void getSummaryRanges(int minChannel, int maxChannel,
Chris@1338 214 bool mixingOrMerging,
Chris@1338 215 sv_frame_t f0, sv_frame_t f1,
Chris@1338 216 int blockSize, RangeVec &ranges) const;
Chris@1338 217
Chris@1338 218 void getOversampledRanges(int minChannel, int maxChannel,
Chris@1338 219 bool mixingOrMerging,
Chris@1338 220 sv_frame_t f0, sv_frame_t f1,
Chris@1338 221 int oversampleBy, RangeVec &ranges) const;
Chris@1332 222
Chris@918 223 int getYForValue(const LayerGeometryProvider *v, double value, int channel) const;
Chris@68 224
Chris@918 225 double getValueForY(const LayerGeometryProvider *v, int y, int &channel) const;
Chris@261 226
Chris@918 227 bool getSourceFramesForX(LayerGeometryProvider *v, int x, int modelZoomLevel,
Chris@908 228 sv_frame_t &f0, sv_frame_t &f1) const;
Chris@365 229
Chris@918 230 float getNormalizeGain(LayerGeometryProvider *v, int channel) const;
Chris@365 231
Chris@1406 232 void flagBaseColourChanged() override { m_cacheValid = false; }
Chris@287 233
Chris@6 234 float m_gain;
Chris@67 235 bool m_autoNormalize;
Chris@6 236 bool m_showMeans;
Chris@6 237 ChannelMode m_channelMode;
Chris@6 238 int m_channel;
Chris@6 239 Scale m_scale;
Chris@905 240 double m_middleLineHeight;
Chris@6 241 bool m_aggressive;
Chris@0 242
Chris@67 243 mutable std::vector<float> m_effectiveGains;
Chris@67 244
Chris@0 245 mutable QPixmap *m_cache;
Chris@0 246 mutable bool m_cacheValid;
Chris@1325 247 mutable ZoomLevel m_cacheZoomLevel;
Chris@0 248 };
Chris@0 249
Chris@0 250 #endif