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