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