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 SPECTROGRAM_LAYER_H
17 #define SPECTROGRAM_LAYER_H
18 
19 #include "SliceableLayer.h"
20 #include "base/Window.h"
21 #include "base/MagnitudeRange.h"
22 #include "base/RealTime.h"
23 #include "base/Thread.h"
24 #include "base/PropertyContainer.h"
25 #include "data/model/PowerOfSqrtTwoZoomConstraint.h"
26 #include "data/model/DenseTimeValueModel.h"
27 #include "data/model/FFTModel.h"
28 
29 #include "VerticalBinLayer.h"
30 #include "ColourScale.h"
31 #include "Colour3DPlotRenderer.h"
32 
33 #include <QMutex>
34 #include <QWaitCondition>
35 #include <QImage>
36 #include <QPixmap>
37 
38 class View;
39 class QPainter;
40 class QImage;
41 class QPixmap;
42 class QTimer;
43 class FFTModel;
44 class Dense3DModelPeakCache;
45 
46 /**
47  * SpectrogramLayer represents waveform data (obtained from a
48  * DenseTimeValueModel) in spectrogram form.
49  */
50 
51 class SpectrogramLayer : public VerticalBinLayer,
52                          public PowerOfSqrtTwoZoomConstraint
53 {
54     Q_OBJECT
55 
56 public:
57     enum Configuration { FullRangeDb, MelodicRange, MelodicPeaks };
58 
59     /**
60      * Construct a SpectrogramLayer with default parameters
61      * appropriate for the given configuration.
62      */
63     SpectrogramLayer(Configuration = FullRangeDb);
64     ~SpectrogramLayer();
65 
getZoomConstraint()66     const ZoomConstraint *getZoomConstraint() const override { return this; }
getModel()67     ModelId getModel() const override { return m_model; }
68     void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override;
69     void setSynchronousPainting(bool synchronous) override;
70 
71     int getVerticalScaleWidth(LayerGeometryProvider *v, bool detailed, QPainter &) const override;
72     void paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const override;
73 
74     bool getCrosshairExtents(LayerGeometryProvider *, QPainter &, QPoint cursorPos,
75                                      std::vector<QRect> &extents) const override;
76     void paintCrosshairs(LayerGeometryProvider *, QPainter &, QPoint) const override;
77 
78     QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const override;
79 
80     bool snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
81                             int &resolution,
82                             SnapType snap, int ycoord) const override;
83 
84     void measureDoubleClick(LayerGeometryProvider *, QMouseEvent *) override;
85 
86     bool hasLightBackground() const override;
87 
88     void setModel(ModelId model); // a DenseTimeValueModel
89 
90     PropertyList getProperties() const override;
91     QString getPropertyLabel(const PropertyName &) const override;
92     QString getPropertyIconName(const PropertyName &) const override;
93     PropertyType getPropertyType(const PropertyName &) const override;
94     QString getPropertyGroupName(const PropertyName &) const override;
95     int getPropertyRangeAndValue(const PropertyName &,
96                                  int *min, int *max, int *deflt) const override;
97     QString getPropertyValueLabel(const PropertyName &,
98                                           int value) const override;
99     QString getPropertyValueIconName(const PropertyName &,
100                                              int value) const override;
101     RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const override;
102     void setProperty(const PropertyName &, int value) override;
103 
104     /**
105      * Specify the channel to use from the source model.
106      * A value of -1 means to mix all available channels.
107      * The default is channel 0.
108      */
109     void setChannel(int);
110     int getChannel() const;
111 
112     void setWindowSize(int);
113     int getWindowSize() const;
114 
115     void setWindowHopLevel(int level);
116     int getWindowHopLevel() const;
117 
118     void setOversampling(int oversampling);
119     int getOversampling() const;
120 
121     void setWindowType(WindowType type);
122     WindowType getWindowType() const;
123 
124     /**
125      * Set the gain multiplier for sample values in this view.
126      * The default is 1.0.
127      */
128     void setGain(float gain);
129     float getGain() const;
130 
131     /**
132      * Set the threshold for sample values to qualify for being shown
133      * in the FFT, in voltage units.
134      *
135      * The default is 10^-8 (-80dB).
136      */
137     void setThreshold(float threshold);
138     float getThreshold() const;
139 
140     /**
141      * Mark the spectrogram layer as having a fixed range in the
142      * vertical axis. This indicates that the visible frequency range
143      * is determined entirely by the configuration requested on
144      * construction, and that setMinFrequency, setMaxFrequency, and
145      * setDisplayExtents will never be called. This may allow some
146      * cache-size-related optimisations. It should be called
147      * immediately after construction, if at all.
148      *
149      * Note that this cannot be reversed on a given object (this call
150      * takes no argument and there is no inverse call).
151      */
152     void setVerticallyFixed();
153 
154     void setMinFrequency(int);
155     int getMinFrequency() const;
156 
157     void setMaxFrequency(int); // 0 -> no maximum
158     int getMaxFrequency() const;
159 
160     /**
161      * Specify the scale for sample levels.  See ColourScale and
162      * WaveformLayer for comparison and details of meter and dB
163      * scaling.  The default is LogColourScale.
164      */
165     void setColourScale(ColourScaleType);
166     ColourScaleType getColourScale() const;
167 
168     /**
169      * Specify multiple factor for colour scale. This is 2.0 for
170      * log-power spectrogram and 1.0 otherwise.
171      */
172     void setColourScaleMultiple(double);
173     double getColourScaleMultiple() const;
174 
175     /**
176      * Specify the scale for the y axis.
177      */
178     void setBinScale(BinScale);
179     BinScale getBinScale() const;
180 
181     /**
182      * Specify the processing of frequency bins for the y axis.
183      */
184     void setBinDisplay(BinDisplay);
185     BinDisplay getBinDisplay() const;
186 
187     /**
188      * Specify the normalization mode for individual columns.
189      */
190     void setNormalization(ColumnNormalization);
191     ColumnNormalization getNormalization() const;
192 
193     /**
194      * Specify whether to normalize the visible area.
195      */
196     void setNormalizeVisibleArea(bool);
197     bool getNormalizeVisibleArea() const;
198 
199     /**
200      * Specify the colour map. See ColourMapper for the colour map
201      * values.
202      */
203     void setColourMap(int map);
204     int getColourMap() const;
205 
206     /**
207      * Specify the colourmap rotation for the colour scale.
208      */
209     void setColourRotation(int);
210     int getColourRotation() const;
211 
getPreferredFrameCountPosition()212     VerticalPosition getPreferredFrameCountPosition() const override {
213         return PositionTop;
214     }
215 
isLayerOpaque()216     bool isLayerOpaque() const override { return true; }
217 
getLayerColourSignificance()218     ColourSignificance getLayerColourSignificance() const override {
219         return ColourHasMeaningfulValue;
220     }
221 
222     double getYForFrequency(const LayerGeometryProvider *v, double frequency) const;
223     double getFrequencyForY(const LayerGeometryProvider *v, int y) const;
224 
225     //!!! VerticalBinLayer methods. Note overlap with get*BinRange()
226     double getYForBin(const LayerGeometryProvider *, double bin) const override;
227     double getBinForY(const LayerGeometryProvider *, double y) const override;
228 
229     int getCompletion(LayerGeometryProvider *v) const override;
230     QString getError(LayerGeometryProvider *v) const override;
231 
232     bool getValueExtents(double &min, double &max,
233                          bool &logarithmic, QString &unit) const override;
234 
235     bool getDisplayExtents(double &min, double &max) const override;
236 
237     bool setDisplayExtents(double min, double max) override;
238 
239     bool getYScaleValue(const LayerGeometryProvider *, int, double &, QString &) const override;
240 
241     void toXml(QTextStream &stream, QString indent = "",
242                        QString extraAttributes = "") const override;
243 
244     void setProperties(const QXmlAttributes &attributes) override;
245 
246     void setLayerDormant(const LayerGeometryProvider *v, bool dormant) override;
247 
248     bool isLayerScrollable(const LayerGeometryProvider *) const override;
249 
250     int getVerticalZoomSteps(int &defaultStep) const override;
251     int getCurrentVerticalZoomStep() const override;
252     void setVerticalZoomStep(int) override;
253     RangeMapper *getNewVerticalZoomRangeMapper() const override;
254 
255     ModelId getSliceableModel() const override;
256 
257 protected slots:
258     void cacheInvalid(ModelId);
259     void cacheInvalid(ModelId, sv_frame_t startFrame, sv_frame_t endFrame);
260 
261     void preferenceChanged(PropertyContainer::PropertyName name);
262 
263 protected:
264     ModelId m_model; // a DenseTimeValueModel
265 
266     int                 m_channel;
267     int                 m_windowSize;
268     WindowType          m_windowType;
269     int                 m_windowHopLevel;
270     int                 m_oversampling;
271     float               m_gain;
272     float               m_initialGain;
273     float               m_threshold;
274     float               m_initialThreshold;
275     int                 m_colourRotation;
276     int                 m_initialRotation;
277     int                 m_minFrequency;
278     int                 m_maxFrequency;
279     int                 m_initialMaxFrequency;
280     bool                m_verticallyFixed;
281     ColourScaleType     m_colourScale;
282     double              m_colourScaleMultiple;
283     int                 m_colourMap;
284     bool                m_colourInverted;
285     mutable QColor      m_crosshairColour;
286     BinScale            m_binScale;
287     BinDisplay          m_binDisplay;
288     ColumnNormalization m_normalization; // of individual columns
289     bool                m_normalizeVisibleArea;
290     int                 m_lastEmittedZoomStep;
291     bool                m_synchronous;
292 
293     mutable bool        m_haveDetailedScale;
294 
295     static std::pair<ColourScaleType, double> convertToColourScale(int value);
296     static int convertFromColourScale(ColourScaleType type, double multiple);
297     static std::pair<ColumnNormalization, bool> convertToColumnNorm(int value);
298     static int convertFromColumnNorm(ColumnNormalization norm, bool visible);
299 
300     bool m_exiting;
301 
302     int getColourScaleWidth(QPainter &) const;
303 
304     void illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &painter) const;
305 
306     double getEffectiveMinFrequency() const;
307     double getEffectiveMaxFrequency() const;
308 
309     bool getXBinRange(LayerGeometryProvider *v, int x, double &windowMin, double &windowMax) const;
310     bool getYBinRange(LayerGeometryProvider *v, int y, double &freqBinMin, double &freqBinMax) const;
311 
312     bool getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax) const;
313     bool getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y,
314                                     double &freqMin, double &freqMax,
315                                     double &adjFreqMin, double &adjFreqMax) const;
316     bool getXBinSourceRange(LayerGeometryProvider *v, int x, RealTime &timeMin, RealTime &timeMax) const;
317     bool getXYBinSourceRange(LayerGeometryProvider *v, int x, int y, double &min, double &max,
318                              double &phaseMin, double &phaseMax) const;
319 
getWindowIncrement()320     int getWindowIncrement() const {
321         if (m_windowHopLevel == 0) return m_windowSize;
322         else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4;
323         else return m_windowSize / (1 << (m_windowHopLevel - 1));
324     }
325 
326     int getFFTSize() const; // m_windowSize * getOversampling()
327 
328     // We take responsibility for registering/deregistering these
329     // models and caches with ModelById
330     ModelId m_fftModel; // an FFTModel
331     ModelId m_wholeCache; // a Dense3DModelPeakCache
332     ModelId m_peakCache; // a Dense3DModelPeakCache
333     int m_peakCacheDivisor;
334     void checkCacheSpace(int *suggestedPeakDivisor,
335                          bool *createWholeCache) const;
336     void recreateFFTModel();
337 
338     typedef std::map<int, MagnitudeRange> ViewMagMap; // key is view id
339     mutable ViewMagMap m_viewMags;
340     mutable ViewMagMap m_lastRenderedMags; // when in normalizeVisibleArea mode
341     void invalidateMagnitudes();
342 
343     typedef std::map<int, Colour3DPlotRenderer *> ViewRendererMap; // key is view id
344     mutable ViewRendererMap m_renderers;
345     Colour3DPlotRenderer *getRenderer(LayerGeometryProvider *) const;
346     void invalidateRenderers();
347 
348     void deleteDerivedModels();
349 
350     void paintWithRenderer(LayerGeometryProvider *v, QPainter &paint, QRect rect) const;
351 
352     void paintDetailedScale(LayerGeometryProvider *v,
353                             QPainter &paint, QRect rect) const;
354     void paintDetailedScalePhase(LayerGeometryProvider *v,
355                                  QPainter &paint, QRect rect) const;
356 
357     void updateMeasureRectYCoords(LayerGeometryProvider *v,
358                                           const MeasureRect &r) const override;
359     void setMeasureRectYCoord(LayerGeometryProvider *v,
360                                       MeasureRect &r, bool start, int y) const override;
361 };
362 
363 #endif
364