annotate layer/WaveformLayer.h @ 1551:e79731086b0f

Fixes to NoteLayer, particularly to calculation of vertical scale when model unit is not Hz. To avoid inconsistency we now behave as if the unit is always Hz from the point of view of the external API and display, converting at the point where we obtain values from the events themselves. Also various fixes to editing.
author Chris Cannam
date Thu, 21 Nov 2019 14:02:57 +0000
parents 10fe8124dc17
children
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@1542 177 bool getDisplayExtents(double & min, double &max) const override;
Chris@1542 178
Chris@1406 179 bool getYScaleValue(const LayerGeometryProvider *v, int y,
Chris@1406 180 double &value, QString &unit) const override;
Chris@274 181
Chris@1406 182 bool getYScaleDifference(const LayerGeometryProvider *v, int y0, int y1,
Chris@1406 183 double &diff, QString &unit) const override;
Chris@261 184
Chris@1406 185 void toXml(QTextStream &stream, QString indent = "",
Chris@1406 186 QString extraAttributes = "") const override;
Chris@6 187
Chris@1406 188 void setProperties(const QXmlAttributes &attributes) override;
Chris@11 189
Chris@1406 190 int getVerticalZoomSteps(int &defaultStep) const override;
Chris@1406 191 int getCurrentVerticalZoomStep() const override;
Chris@1406 192 void setVerticalZoomStep(int) override;
Chris@133 193
Chris@1406 194 bool canExistWithoutModel() const override { return true; }
Chris@947 195
Chris@0 196 protected:
Chris@1367 197 double dBscale(double sample, int m) const;
Chris@0 198
Chris@1470 199 ModelId m_model;
Chris@0 200
Chris@1338 201 typedef std::vector<RangeSummarisableTimeValueModel::RangeBlock> RangeVec;
Chris@1338 202
Chris@0 203 /// Return value is number of channels displayed
Chris@805 204 int getChannelArrangement(int &min, int &max,
Chris@1332 205 bool &merging, bool &mixing) const;
Chris@0 206
Chris@1338 207 void paintChannel
Chris@1336 208 (LayerGeometryProvider *, QPainter *paint, QRect rect, int channel,
Chris@1338 209 const RangeVec &ranges,
Chris@1336 210 int blockSize, sv_frame_t frame0, sv_frame_t frame1) const;
Chris@1336 211
Chris@1335 212 void paintChannelScaleGuides(LayerGeometryProvider *, QPainter *paint,
Chris@1335 213 QRect rect, int channel) const;
Chris@1338 214
Chris@1338 215 void getSummaryRanges(int minChannel, int maxChannel,
Chris@1338 216 bool mixingOrMerging,
Chris@1338 217 sv_frame_t f0, sv_frame_t f1,
Chris@1338 218 int blockSize, RangeVec &ranges) const;
Chris@1338 219
Chris@1338 220 void getOversampledRanges(int minChannel, int maxChannel,
Chris@1338 221 bool mixingOrMerging,
Chris@1338 222 sv_frame_t f0, sv_frame_t f1,
Chris@1338 223 int oversampleBy, RangeVec &ranges) const;
Chris@1332 224
Chris@918 225 int getYForValue(const LayerGeometryProvider *v, double value, int channel) const;
Chris@68 226
Chris@918 227 double getValueForY(const LayerGeometryProvider *v, int y, int &channel) const;
Chris@261 228
Chris@918 229 bool getSourceFramesForX(LayerGeometryProvider *v, int x, int modelZoomLevel,
Chris@908 230 sv_frame_t &f0, sv_frame_t &f1) const;
Chris@365 231
Chris@918 232 float getNormalizeGain(LayerGeometryProvider *v, int channel) const;
Chris@365 233
Chris@1406 234 void flagBaseColourChanged() override { m_cacheValid = false; }
Chris@287 235
Chris@6 236 float m_gain;
Chris@67 237 bool m_autoNormalize;
Chris@6 238 bool m_showMeans;
Chris@6 239 ChannelMode m_channelMode;
Chris@6 240 int m_channel;
Chris@1542 241 int m_channelCount;
Chris@6 242 Scale m_scale;
Chris@905 243 double m_middleLineHeight;
Chris@6 244 bool m_aggressive;
Chris@0 245
Chris@1542 246 static double m_dBMin;
Chris@1542 247
Chris@67 248 mutable std::vector<float> m_effectiveGains;
Chris@67 249
Chris@0 250 mutable QPixmap *m_cache;
Chris@0 251 mutable bool m_cacheValid;
Chris@1325 252 mutable ZoomLevel m_cacheZoomLevel;
Chris@0 253 };
Chris@0 254
Chris@0 255 #endif