Mercurial > hg > svgui
comparison layer/SpectrogramLayer.h @ 1148:c0d841cb8ab9 tony-2.0-integration
Merge latest SV 3.0 branch code
author | Chris Cannam |
---|---|
date | Fri, 19 Aug 2016 15:58:57 +0100 |
parents | c53ed1a6fcbd |
children | 7a19738b9762 |
comparison
equal
deleted
inserted
replaced
1009:96cf499fad62 | 1148:c0d841cb8ab9 |
---|---|
11 published by the Free Software Foundation; either version 2 of the | 11 published by the Free Software Foundation; either version 2 of the |
12 License, or (at your option) any later version. See the file | 12 License, or (at your option) any later version. See the file |
13 COPYING included with this distribution for more information. | 13 COPYING included with this distribution for more information. |
14 */ | 14 */ |
15 | 15 |
16 #ifndef _SPECTROGRAM_LAYER_H_ | 16 #ifndef SPECTROGRAM_LAYER_H |
17 #define _SPECTROGRAM_LAYER_H_ | 17 #define SPECTROGRAM_LAYER_H |
18 | 18 |
19 #include "SliceableLayer.h" | 19 #include "SliceableLayer.h" |
20 #include "base/Window.h" | 20 #include "base/Window.h" |
21 #include "base/MagnitudeRange.h" | |
21 #include "base/RealTime.h" | 22 #include "base/RealTime.h" |
22 #include "base/Thread.h" | 23 #include "base/Thread.h" |
23 #include "base/PropertyContainer.h" | 24 #include "base/PropertyContainer.h" |
24 #include "data/model/PowerOfSqrtTwoZoomConstraint.h" | 25 #include "data/model/PowerOfSqrtTwoZoomConstraint.h" |
25 #include "data/model/DenseTimeValueModel.h" | 26 #include "data/model/DenseTimeValueModel.h" |
26 #include "data/model/FFTModel.h" | 27 #include "data/model/FFTModel.h" |
28 | |
29 #include "VerticalBinLayer.h" | |
30 #include "ColourScale.h" | |
31 #include "Colour3DPlotRenderer.h" | |
27 | 32 |
28 #include <QMutex> | 33 #include <QMutex> |
29 #include <QWaitCondition> | 34 #include <QWaitCondition> |
30 #include <QImage> | 35 #include <QImage> |
31 #include <QPixmap> | 36 #include <QPixmap> |
36 class QPixmap; | 41 class QPixmap; |
37 class QTimer; | 42 class QTimer; |
38 class FFTModel; | 43 class FFTModel; |
39 class Dense3DModelPeakCache; | 44 class Dense3DModelPeakCache; |
40 | 45 |
41 | |
42 /** | 46 /** |
43 * SpectrogramLayer represents waveform data (obtained from a | 47 * SpectrogramLayer represents waveform data (obtained from a |
44 * DenseTimeValueModel) in spectrogram form. | 48 * DenseTimeValueModel) in spectrogram form. |
45 */ | 49 */ |
46 | 50 |
47 class SpectrogramLayer : public SliceableLayer, | 51 class SpectrogramLayer : public VerticalBinLayer, |
48 public PowerOfSqrtTwoZoomConstraint | 52 public PowerOfSqrtTwoZoomConstraint |
49 { | 53 { |
50 Q_OBJECT | 54 Q_OBJECT |
51 | 55 |
52 public: | 56 public: |
108 int getWindowHopLevel() const; | 112 int getWindowHopLevel() const; |
109 | 113 |
110 void setWindowType(WindowType type); | 114 void setWindowType(WindowType type); |
111 WindowType getWindowType() const; | 115 WindowType getWindowType() const; |
112 | 116 |
113 void setZeroPadLevel(int level); | |
114 int getZeroPadLevel() const; | |
115 | |
116 /** | 117 /** |
117 * Set the gain multiplier for sample values in this view. | 118 * Set the gain multiplier for sample values in this view. |
118 * The default is 1.0. | 119 * The default is 1.0. |
119 */ | 120 */ |
120 void setGain(float gain); | 121 void setGain(float gain); |
122 | 123 |
123 /** | 124 /** |
124 * Set the threshold for sample values to qualify for being shown | 125 * Set the threshold for sample values to qualify for being shown |
125 * in the FFT, in voltage units. | 126 * in the FFT, in voltage units. |
126 * | 127 * |
127 * The default is 0.0. | 128 * The default is 10^-8 (-80dB). |
128 */ | 129 */ |
129 void setThreshold(float threshold); | 130 void setThreshold(float threshold); |
130 float getThreshold() const; | 131 float getThreshold() const; |
131 | 132 |
132 void setMinFrequency(int); | 133 void setMinFrequency(int); |
133 int getMinFrequency() const; | 134 int getMinFrequency() const; |
134 | 135 |
135 void setMaxFrequency(int); // 0 -> no maximum | 136 void setMaxFrequency(int); // 0 -> no maximum |
136 int getMaxFrequency() const; | 137 int getMaxFrequency() const; |
137 | 138 |
138 enum ColourScale { | 139 /** |
139 LinearColourScale, | 140 * Specify the scale for sample levels. See ColourScale and |
140 MeterColourScale, | 141 * WaveformLayer for comparison and details of meter and dB |
141 dBSquaredColourScale, | 142 * scaling. The default is LogColourScale. |
142 dBColourScale, | 143 */ |
143 PhaseColourScale | 144 void setColourScale(ColourScaleType); |
144 }; | 145 ColourScaleType getColourScale() const; |
145 | 146 |
146 /** | 147 /** |
147 * Specify the scale for sample levels. See WaveformLayer for | 148 * Specify multiple factor for colour scale. This is 2.0 for |
148 * details of meter and dB scaling. The default is dBColourScale. | 149 * log-power spectrogram and 1.0 otherwise. |
149 */ | 150 */ |
150 void setColourScale(ColourScale); | 151 void setColourScaleMultiple(double); |
151 ColourScale getColourScale() const; | 152 double getColourScaleMultiple() const; |
152 | |
153 enum FrequencyScale { | |
154 LinearFrequencyScale, | |
155 LogFrequencyScale | |
156 }; | |
157 | 153 |
158 /** | 154 /** |
159 * Specify the scale for the y axis. | 155 * Specify the scale for the y axis. |
160 */ | 156 */ |
161 void setFrequencyScale(FrequencyScale); | 157 void setBinScale(BinScale); |
162 FrequencyScale getFrequencyScale() const; | 158 BinScale getBinScale() const; |
163 | 159 |
164 enum BinDisplay { | |
165 AllBins, | |
166 PeakBins, | |
167 PeakFrequencies | |
168 }; | |
169 | |
170 /** | 160 /** |
171 * Specify the processing of frequency bins for the y axis. | 161 * Specify the processing of frequency bins for the y axis. |
172 */ | 162 */ |
173 void setBinDisplay(BinDisplay); | 163 void setBinDisplay(BinDisplay); |
174 BinDisplay getBinDisplay() const; | 164 BinDisplay getBinDisplay() const; |
175 | 165 |
176 enum Normalization { | 166 /** |
177 NoNormalization, | 167 * Specify the normalization mode for individual columns. |
178 NormalizeColumns, | 168 */ |
179 NormalizeVisibleArea, | 169 void setNormalization(ColumnNormalization); |
180 NormalizeHybrid | 170 ColumnNormalization getNormalization() const; |
181 }; | 171 |
182 | 172 /** |
183 /** | 173 * Specify whether to normalize the visible area. |
184 * Specify the normalization mode for bin values. | 174 */ |
185 */ | 175 void setNormalizeVisibleArea(bool); |
186 void setNormalization(Normalization); | 176 bool getNormalizeVisibleArea() const; |
187 Normalization getNormalization() const; | |
188 | 177 |
189 /** | 178 /** |
190 * Specify the colour map. See ColourMapper for the colour map | 179 * Specify the colour map. See ColourMapper for the colour map |
191 * values. | 180 * values. |
192 */ | 181 */ |
210 } | 199 } |
211 | 200 |
212 double getYForFrequency(const LayerGeometryProvider *v, double frequency) const; | 201 double getYForFrequency(const LayerGeometryProvider *v, double frequency) const; |
213 double getFrequencyForY(const LayerGeometryProvider *v, int y) const; | 202 double getFrequencyForY(const LayerGeometryProvider *v, int y) const; |
214 | 203 |
204 //!!! VerticalBinLayer methods. Note overlap with get*BinRange() | |
205 double getYForBin(const LayerGeometryProvider *, double bin) const; | |
206 double getBinForY(const LayerGeometryProvider *, double y) const; | |
207 | |
215 virtual int getCompletion(LayerGeometryProvider *v) const; | 208 virtual int getCompletion(LayerGeometryProvider *v) const; |
216 virtual QString getError(LayerGeometryProvider *v) const; | 209 virtual QString getError(LayerGeometryProvider *v) const; |
217 | 210 |
218 virtual bool getValueExtents(double &min, double &max, | 211 virtual bool getValueExtents(double &min, double &max, |
219 bool &logarithmic, QString &unit) const; | 212 bool &logarithmic, QString &unit) const; |
248 | 241 |
249 protected: | 242 protected: |
250 const DenseTimeValueModel *m_model; // I do not own this | 243 const DenseTimeValueModel *m_model; // I do not own this |
251 | 244 |
252 int m_channel; | 245 int m_channel; |
253 int m_windowSize; | 246 int m_windowSize; |
254 WindowType m_windowType; | 247 WindowType m_windowType; |
255 int m_windowHopLevel; | 248 int m_windowHopLevel; |
256 int m_zeroPadLevel; | |
257 int m_fftSize; | |
258 float m_gain; | 249 float m_gain; |
259 float m_initialGain; | 250 float m_initialGain; |
260 float m_threshold; | 251 float m_threshold; |
261 float m_initialThreshold; | 252 float m_initialThreshold; |
262 int m_colourRotation; | 253 int m_colourRotation; |
263 int m_initialRotation; | 254 int m_initialRotation; |
264 int m_minFrequency; | 255 int m_minFrequency; |
265 int m_maxFrequency; | 256 int m_maxFrequency; |
266 int m_initialMaxFrequency; | 257 int m_initialMaxFrequency; |
267 ColourScale m_colourScale; | 258 ColourScaleType m_colourScale; |
259 double m_colourScaleMultiple; | |
268 int m_colourMap; | 260 int m_colourMap; |
269 QColor m_crosshairColour; | 261 QColor m_crosshairColour; |
270 FrequencyScale m_frequencyScale; | 262 BinScale m_binScale; |
271 BinDisplay m_binDisplay; | 263 BinDisplay m_binDisplay; |
272 Normalization m_normalization; | 264 ColumnNormalization m_normalization; // of individual columns |
265 bool m_normalizeVisibleArea; | |
273 int m_lastEmittedZoomStep; | 266 int m_lastEmittedZoomStep; |
274 bool m_synchronous; | 267 bool m_synchronous; |
275 | 268 |
276 mutable bool m_haveDetailedScale; | 269 mutable bool m_haveDetailedScale; |
277 mutable int m_lastPaintBlockWidth; | 270 |
278 mutable RealTime m_lastPaintTime; | 271 static std::pair<ColourScaleType, double> convertToColourScale(int value); |
279 | 272 static int convertFromColourScale(ColourScaleType type, double multiple); |
280 enum { NO_VALUE = 0 }; // colour index for unused pixels | 273 static std::pair<ColumnNormalization, bool> convertToColumnNorm(int value); |
281 | 274 static int convertFromColumnNorm(ColumnNormalization norm, bool visible); |
282 class Palette | |
283 { | |
284 public: | |
285 QColor getColour(unsigned char index) const { | |
286 return m_colours[index]; | |
287 } | |
288 | |
289 void setColour(unsigned char index, QColor colour) { | |
290 m_colours[index] = colour; | |
291 } | |
292 | |
293 private: | |
294 QColor m_colours[256]; | |
295 }; | |
296 | |
297 Palette m_palette; | |
298 | |
299 /** | |
300 * ImageCache covers the area of the view, at view resolution. | |
301 * Not all of it is necessarily valid at once (it is refreshed | |
302 * in parts when scrolling, for example). | |
303 */ | |
304 struct ImageCache | |
305 { | |
306 QImage image; | |
307 QRect validArea; | |
308 sv_frame_t startFrame; | |
309 int zoomLevel; | |
310 }; | |
311 typedef std::map<const View *, ImageCache> ViewImageCache; | |
312 void invalidateImageCaches(); | |
313 void invalidateImageCaches(sv_frame_t startFrame, sv_frame_t endFrame); | |
314 mutable ViewImageCache m_imageCaches; | |
315 | |
316 /** | |
317 * When painting, we draw directly onto the draw buffer and then | |
318 * copy this to the part of the image cache that needed refreshing | |
319 * before copying the image cache onto the window. (Remind me why | |
320 * we don't draw directly onto the cache?) | |
321 */ | |
322 mutable QImage m_drawBuffer; | |
323 | 275 |
324 bool m_exiting; | 276 bool m_exiting; |
325 | |
326 void initialisePalette(); | |
327 void rotatePalette(int distance); | |
328 | |
329 unsigned char getDisplayValue(LayerGeometryProvider *v, double input) const; | |
330 | 277 |
331 int getColourScaleWidth(QPainter &) const; | 278 int getColourScaleWidth(QPainter &) const; |
332 | 279 |
333 void illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &painter) const; | 280 void illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &painter) const; |
334 | 281 |
335 double getEffectiveMinFrequency() const; | 282 double getEffectiveMinFrequency() const; |
336 double getEffectiveMaxFrequency() const; | 283 double getEffectiveMaxFrequency() const; |
337 | 284 |
338 // Note that the getYBin... methods return the nominal bin in the | |
339 // un-smoothed spectrogram. This is not necessarily the same bin | |
340 // as is pulled from the spectrogram and drawn at the given | |
341 // position, if the spectrogram has oversampling smoothing. Use | |
342 // getSmoothedYBinRange to obtain that. | |
343 | |
344 bool getXBinRange(LayerGeometryProvider *v, int x, double &windowMin, double &windowMax) const; | 285 bool getXBinRange(LayerGeometryProvider *v, int x, double &windowMin, double &windowMax) const; |
345 bool getYBinRange(LayerGeometryProvider *v, int y, double &freqBinMin, double &freqBinMax) const; | 286 bool getYBinRange(LayerGeometryProvider *v, int y, double &freqBinMin, double &freqBinMax) const; |
346 bool getSmoothedYBinRange(LayerGeometryProvider *v, int y, double &freqBinMin, double &freqBinMax) const; | |
347 | 287 |
348 bool getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax) const; | 288 bool getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax) const; |
349 bool getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y, | 289 bool getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y, |
350 double &freqMin, double &freqMax, | 290 double &freqMin, double &freqMax, |
351 double &adjFreqMin, double &adjFreqMax) const; | 291 double &adjFreqMin, double &adjFreqMax) const; |
357 if (m_windowHopLevel == 0) return m_windowSize; | 297 if (m_windowHopLevel == 0) return m_windowSize; |
358 else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4; | 298 else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4; |
359 else return m_windowSize / (1 << (m_windowHopLevel - 1)); | 299 else return m_windowSize / (1 << (m_windowHopLevel - 1)); |
360 } | 300 } |
361 | 301 |
362 int getZeroPadLevel(const LayerGeometryProvider *v) const; | 302 int getFFTOversampling() const; |
363 int getFFTSize(const LayerGeometryProvider *v) const; | 303 int getFFTSize() const; // m_windowSize * getFFTOversampling() |
364 FFTModel *getFFTModel(const LayerGeometryProvider *v) const; | 304 |
365 Dense3DModelPeakCache *getPeakCache(const LayerGeometryProvider *v) const; | 305 mutable FFTModel *m_fftModel; //!!! should not be mutable, see getFFTModel()? |
366 void invalidateFFTModels(); | 306 mutable Dense3DModelPeakCache *m_peakCache; |
367 | 307 const int m_peakCacheDivisor; |
368 typedef std::map<const View *, FFTModel *> ViewFFTMap; | 308 |
369 typedef std::map<const View *, Dense3DModelPeakCache *> PeakCacheMap; | 309 typedef std::map<int, MagnitudeRange> ViewMagMap; // key is view id |
370 mutable ViewFFTMap m_fftModels; | |
371 mutable PeakCacheMap m_peakCaches; | |
372 mutable Model *m_sliceableModel; | |
373 | |
374 class MagnitudeRange { | |
375 public: | |
376 MagnitudeRange() : m_min(0), m_max(0) { } | |
377 bool operator==(const MagnitudeRange &r) { | |
378 return r.m_min == m_min && r.m_max == m_max; | |
379 } | |
380 bool isSet() const { return (m_min != 0.f || m_max != 0.f); } | |
381 void set(float min, float max) { | |
382 m_min = min; | |
383 m_max = max; | |
384 if (m_max < m_min) m_max = m_min; | |
385 } | |
386 bool sample(float f) { | |
387 bool changed = false; | |
388 if (isSet()) { | |
389 if (f < m_min) { m_min = f; changed = true; } | |
390 if (f > m_max) { m_max = f; changed = true; } | |
391 } else { | |
392 m_max = m_min = f; | |
393 changed = true; | |
394 } | |
395 return changed; | |
396 } | |
397 bool sample(const MagnitudeRange &r) { | |
398 bool changed = false; | |
399 if (isSet()) { | |
400 if (r.m_min < m_min) { m_min = r.m_min; changed = true; } | |
401 if (r.m_max > m_max) { m_max = r.m_max; changed = true; } | |
402 } else { | |
403 m_min = r.m_min; | |
404 m_max = r.m_max; | |
405 changed = true; | |
406 } | |
407 return changed; | |
408 } | |
409 float getMin() const { return m_min; } | |
410 float getMax() const { return m_max; } | |
411 private: | |
412 float m_min; | |
413 float m_max; | |
414 }; | |
415 | |
416 typedef std::map<const LayerGeometryProvider *, MagnitudeRange> ViewMagMap; | |
417 mutable ViewMagMap m_viewMags; | 310 mutable ViewMagMap m_viewMags; |
418 mutable std::vector<MagnitudeRange> m_columnMags; | 311 mutable ViewMagMap m_lastRenderedMags; // when in normalizeVisibleArea mode |
419 void invalidateMagnitudes(); | 312 void invalidateMagnitudes(); |
420 bool updateViewMagnitudes(LayerGeometryProvider *v) const; | 313 |
421 bool paintDrawBuffer(LayerGeometryProvider *v, int w, int h, | 314 typedef std::map<int, Colour3DPlotRenderer *> ViewRendererMap; // key is view id |
422 const std::vector<int> &binforx, | 315 mutable ViewRendererMap m_renderers; |
423 const std::vector<double> &binfory, | 316 Colour3DPlotRenderer *getRenderer(LayerGeometryProvider *) const; |
424 bool usePeaksCache, | 317 void invalidateRenderers(); |
425 MagnitudeRange &overallMag, | 318 |
426 bool &overallMagChanged) const; | 319 FFTModel *getFFTModel() const; |
427 bool paintDrawBufferPeakFrequencies(LayerGeometryProvider *v, int w, int h, | 320 Dense3DModelPeakCache *getPeakCache() const; |
428 const std::vector<int> &binforx, | 321 void invalidateFFTModel(); |
429 int minbin, | 322 |
430 int maxbin, | 323 void paintWithRenderer(LayerGeometryProvider *v, QPainter &paint, QRect rect) const; |
431 double displayMinFreq, | 324 |
432 double displayMaxFreq, | 325 void paintDetailedScale(LayerGeometryProvider *v, |
433 bool logarithmic, | 326 QPainter &paint, QRect rect) const; |
434 MagnitudeRange &overallMag, | 327 void paintDetailedScalePhase(LayerGeometryProvider *v, |
435 bool &overallMagChanged) const; | 328 QPainter &paint, QRect rect) const; |
436 | 329 |
437 virtual void updateMeasureRectYCoords(LayerGeometryProvider *v, const MeasureRect &r) const; | 330 virtual void updateMeasureRectYCoords(LayerGeometryProvider *v, |
438 virtual void setMeasureRectYCoord(LayerGeometryProvider *v, MeasureRect &r, bool start, int y) const; | 331 const MeasureRect &r) const; |
332 virtual void setMeasureRectYCoord(LayerGeometryProvider *v, | |
333 MeasureRect &r, bool start, int y) const; | |
439 }; | 334 }; |
440 | 335 |
441 #endif | 336 #endif |