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