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