annotate layer/SpectrogramLayer.h @ 1082:5b4fe7bb9430 spectrogram-minor-refactor

VerticalBinLayer for vertical mapping abstraction. Not totally sure about this
author Chris Cannam
date Fri, 01 Jul 2016 09:55:48 +0100
parents cb4c9fb37ddc
children 179ea8a2f650
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@59 9 This program is free software; you can redistribute it and/or
Chris@59 10 modify it under the terms of the GNU General Public License as
Chris@59 11 published by the Free Software Foundation; either version 2 of the
Chris@59 12 License, or (at your option) any later version. See the file
Chris@59 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@1030 16 #ifndef SPECTROGRAM_LAYER_H
Chris@1030 17 #define SPECTROGRAM_LAYER_H
Chris@0 18
Chris@193 19 #include "SliceableLayer.h"
Chris@0 20 #include "base/Window.h"
Chris@1058 21 #include "base/MagnitudeRange.h"
Chris@71 22 #include "base/RealTime.h"
Chris@92 23 #include "base/Thread.h"
Chris@122 24 #include "base/PropertyContainer.h"
Chris@128 25 #include "data/model/PowerOfSqrtTwoZoomConstraint.h"
Chris@128 26 #include "data/model/DenseTimeValueModel.h"
Chris@130 27 #include "data/model/FFTModel.h"
Chris@0 28
Chris@1030 29 #include "ScrollableImageCache.h"
Chris@1030 30
Chris@0 31 #include <QMutex>
Chris@0 32 #include <QWaitCondition>
Chris@95 33 #include <QImage>
Chris@95 34 #include <QPixmap>
Chris@0 35
Chris@0 36 class View;
Chris@0 37 class QPainter;
Chris@0 38 class QImage;
Chris@0 39 class QPixmap;
Chris@0 40 class QTimer;
Chris@130 41 class FFTModel;
Chris@484 42 class Dense3DModelPeakCache;
Chris@114 43
Chris@0 44
Chris@0 45 /**
Chris@0 46 * SpectrogramLayer represents waveform data (obtained from a
Chris@0 47 * DenseTimeValueModel) in spectrogram form.
Chris@0 48 */
Chris@0 49
Chris@193 50 class SpectrogramLayer : public SliceableLayer,
Chris@31 51 public PowerOfSqrtTwoZoomConstraint
Chris@0 52 {
Chris@0 53 Q_OBJECT
Chris@0 54
Chris@0 55 public:
Chris@37 56 enum Configuration { FullRangeDb, MelodicRange, MelodicPeaks };
Chris@0 57
Chris@44 58 SpectrogramLayer(Configuration = FullRangeDb);
Chris@0 59 ~SpectrogramLayer();
Chris@0 60
Chris@0 61 virtual const ZoomConstraint *getZoomConstraint() const { return this; }
Chris@0 62 virtual const Model *getModel() const { return m_model; }
Chris@916 63 virtual void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const;
Chris@389 64 virtual void setSynchronousPainting(bool synchronous);
Chris@0 65
Chris@918 66 virtual int getVerticalScaleWidth(LayerGeometryProvider *v, bool detailed, QPainter &) const;
Chris@918 67 virtual void paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const;
Chris@0 68
Chris@918 69 virtual bool getCrosshairExtents(LayerGeometryProvider *, QPainter &, QPoint cursorPos,
Chris@77 70 std::vector<QRect> &extents) const;
Chris@918 71 virtual void paintCrosshairs(LayerGeometryProvider *, QPainter &, QPoint) const;
Chris@77 72
Chris@918 73 virtual QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const;
Chris@0 74
Chris@918 75 virtual bool snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
Chris@805 76 int &resolution,
Chris@28 77 SnapType snap) const;
Chris@13 78
Chris@918 79 virtual void measureDoubleClick(LayerGeometryProvider *, QMouseEvent *);
Chris@283 80
Chris@224 81 virtual bool hasLightBackground() const;
Chris@224 82
Chris@0 83 void setModel(const DenseTimeValueModel *model);
Chris@0 84
Chris@0 85 virtual PropertyList getProperties() const;
Chris@87 86 virtual QString getPropertyLabel(const PropertyName &) const;
Chris@335 87 virtual QString getPropertyIconName(const PropertyName &) const;
Chris@0 88 virtual PropertyType getPropertyType(const PropertyName &) const;
Chris@0 89 virtual QString getPropertyGroupName(const PropertyName &) const;
Chris@0 90 virtual int getPropertyRangeAndValue(const PropertyName &,
Chris@216 91 int *min, int *max, int *deflt) const;
Chris@0 92 virtual QString getPropertyValueLabel(const PropertyName &,
Chris@0 93 int value) const;
Chris@862 94 virtual QString getPropertyValueIconName(const PropertyName &,
Chris@862 95 int value) const;
Chris@167 96 virtual RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const;
Chris@0 97 virtual void setProperty(const PropertyName &, int value);
Chris@0 98
Chris@0 99 /**
Chris@0 100 * Specify the channel to use from the source model.
Chris@0 101 * A value of -1 means to mix all available channels.
Chris@0 102 * The default is channel 0.
Chris@0 103 */
Chris@0 104 void setChannel(int);
Chris@0 105 int getChannel() const;
Chris@0 106
Chris@805 107 void setWindowSize(int);
Chris@805 108 int getWindowSize() const;
Chris@0 109
Chris@805 110 void setWindowHopLevel(int level);
Chris@805 111 int getWindowHopLevel() const;
Chris@0 112
Chris@0 113 void setWindowType(WindowType type);
Chris@0 114 WindowType getWindowType() const;
Chris@0 115
Chris@805 116 void setZeroPadLevel(int level);
Chris@805 117 int getZeroPadLevel() const;
Chris@109 118
Chris@0 119 /**
Chris@110 120 * Set the gain multiplier for sample values in this view.
Chris@0 121 * The default is 1.0.
Chris@0 122 */
Chris@0 123 void setGain(float gain);
Chris@0 124 float getGain() const;
Chris@0 125
Chris@37 126 /**
Chris@110 127 * Set the threshold for sample values to qualify for being shown
Chris@110 128 * in the FFT, in voltage units.
Chris@37 129 *
Chris@37 130 * The default is 0.0.
Chris@37 131 */
Chris@37 132 void setThreshold(float threshold);
Chris@37 133 float getThreshold() const;
Chris@37 134
Chris@805 135 void setMinFrequency(int);
Chris@805 136 int getMinFrequency() const;
Chris@37 137
Chris@805 138 void setMaxFrequency(int); // 0 -> no maximum
Chris@805 139 int getMaxFrequency() const;
Chris@0 140
Chris@37 141 enum ColourScale {
Chris@37 142 LinearColourScale,
Chris@37 143 MeterColourScale,
Chris@215 144 dBSquaredColourScale,
Chris@37 145 dBColourScale,
Chris@37 146 PhaseColourScale
Chris@37 147 };
Chris@0 148
Chris@0 149 /**
Chris@0 150 * Specify the scale for sample levels. See WaveformLayer for
Chris@0 151 * details of meter and dB scaling. The default is dBColourScale.
Chris@0 152 */
Chris@0 153 void setColourScale(ColourScale);
Chris@0 154 ColourScale getColourScale() const;
Chris@0 155
Chris@35 156 enum FrequencyScale {
Chris@35 157 LinearFrequencyScale,
Chris@35 158 LogFrequencyScale
Chris@35 159 };
Chris@0 160
Chris@0 161 /**
Chris@0 162 * Specify the scale for the y axis.
Chris@0 163 */
Chris@0 164 void setFrequencyScale(FrequencyScale);
Chris@0 165 FrequencyScale getFrequencyScale() const;
Chris@0 166
Chris@37 167 enum BinDisplay {
Chris@37 168 AllBins,
Chris@37 169 PeakBins,
Chris@37 170 PeakFrequencies
Chris@35 171 };
Chris@35 172
Chris@35 173 /**
Chris@35 174 * Specify the processing of frequency bins for the y axis.
Chris@35 175 */
Chris@37 176 void setBinDisplay(BinDisplay);
Chris@37 177 BinDisplay getBinDisplay() const;
Chris@862 178
Chris@719 179 /**
Chris@862 180 * Specify the normalization mode for bin values.
Chris@719 181 */
Chris@1063 182 void setNormalization(ColumnOp::Normalization);
Chris@1063 183 ColumnOp::Normalization getNormalization() const;
Chris@120 184
Chris@719 185 /**
Chris@862 186 * Specify the colour map. See ColourMapper for the colour map
Chris@862 187 * values.
Chris@719 188 */
Chris@197 189 void setColourMap(int map);
Chris@197 190 int getColourMap() const;
Chris@0 191
Chris@9 192 /**
Chris@9 193 * Specify the colourmap rotation for the colour scale.
Chris@9 194 */
Chris@9 195 void setColourRotation(int);
Chris@9 196 int getColourRotation() const;
Chris@9 197
Chris@0 198 virtual VerticalPosition getPreferredFrameCountPosition() const {
Chris@0 199 return PositionTop;
Chris@0 200 }
Chris@0 201
Chris@15 202 virtual bool isLayerOpaque() const { return true; }
Chris@287 203
Chris@287 204 virtual ColourSignificance getLayerColourSignificance() const {
Chris@287 205 return ColourHasMeaningfulValue;
Chris@287 206 }
Chris@15 207
Chris@918 208 double getYForFrequency(const LayerGeometryProvider *v, double frequency) const;
Chris@918 209 double getFrequencyForY(const LayerGeometryProvider *v, int y) const;
Chris@42 210
Chris@918 211 virtual int getCompletion(LayerGeometryProvider *v) const;
Chris@918 212 virtual QString getError(LayerGeometryProvider *v) const;
Chris@0 213
Chris@905 214 virtual bool getValueExtents(double &min, double &max,
Chris@101 215 bool &logarithmic, QString &unit) const;
Chris@101 216
Chris@905 217 virtual bool getDisplayExtents(double &min, double &max) const;
Chris@79 218
Chris@905 219 virtual bool setDisplayExtents(double min, double max);
Chris@120 220
Chris@918 221 virtual bool getYScaleValue(const LayerGeometryProvider *, int, double &, QString &) const;
Chris@261 222
Chris@316 223 virtual void toXml(QTextStream &stream, QString indent = "",
Chris@316 224 QString extraAttributes = "") const;
Chris@6 225
Chris@11 226 void setProperties(const QXmlAttributes &attributes);
Chris@11 227
Chris@918 228 virtual void setLayerDormant(const LayerGeometryProvider *v, bool dormant);
Chris@29 229
Chris@918 230 virtual bool isLayerScrollable(const LayerGeometryProvider *) const { return false; }
Chris@94 231
Chris@133 232 virtual int getVerticalZoomSteps(int &defaultStep) const;
Chris@133 233 virtual int getCurrentVerticalZoomStep() const;
Chris@133 234 virtual void setVerticalZoomStep(int);
Chris@187 235 virtual RangeMapper *getNewVerticalZoomRangeMapper() const;
Chris@133 236
Chris@193 237 virtual const Model *getSliceableModel() const;
Chris@193 238
Chris@0 239 protected slots:
Chris@0 240 void cacheInvalid();
Chris@906 241 void cacheInvalid(sv_frame_t startFrame, sv_frame_t endFrame);
Chris@122 242
Chris@122 243 void preferenceChanged(PropertyContainer::PropertyName name);
Chris@0 244
Chris@0 245 protected:
Chris@0 246 const DenseTimeValueModel *m_model; // I do not own this
Chris@484 247
Chris@35 248 int m_channel;
Chris@1023 249 int m_windowSize;
Chris@35 250 WindowType m_windowType;
Chris@1023 251 int m_windowHopLevel;
Chris@1023 252 int m_zeroPadLevel;
Chris@1023 253 int m_fftSize;
Chris@35 254 float m_gain;
Chris@215 255 float m_initialGain;
Chris@37 256 float m_threshold;
Chris@215 257 float m_initialThreshold;
Chris@35 258 int m_colourRotation;
Chris@215 259 int m_initialRotation;
Chris@1023 260 int m_minFrequency;
Chris@1023 261 int m_maxFrequency;
Chris@1023 262 int m_initialMaxFrequency;
Chris@35 263 ColourScale m_colourScale;
Chris@197 264 int m_colourMap;
Chris@77 265 QColor m_crosshairColour;
Chris@35 266 FrequencyScale m_frequencyScale;
Chris@37 267 BinDisplay m_binDisplay;
Chris@1063 268 ColumnOp::Normalization m_normalization;
Chris@133 269 int m_lastEmittedZoomStep;
Chris@389 270 bool m_synchronous;
Chris@0 271
Chris@608 272 mutable bool m_haveDetailedScale;
Chris@215 273
Chris@38 274 enum { NO_VALUE = 0 }; // colour index for unused pixels
Chris@38 275
Chris@197 276 class Palette
Chris@86 277 {
Chris@86 278 public:
Chris@86 279 QColor getColour(unsigned char index) const {
Chris@86 280 return m_colours[index];
Chris@86 281 }
Chris@86 282
Chris@86 283 void setColour(unsigned char index, QColor colour) {
Chris@86 284 m_colours[index] = colour;
Chris@86 285 }
Chris@86 286
Chris@86 287 private:
Chris@86 288 QColor m_colours[256];
Chris@86 289 };
Chris@86 290
Chris@197 291 Palette m_palette;
Chris@31 292
Chris@1030 293 typedef std::map<int, ScrollableImageCache> ViewImageCache; // key is view id
Chris@478 294 void invalidateImageCaches();
Chris@478 295 mutable ViewImageCache m_imageCaches;
Chris@1030 296 ScrollableImageCache &getImageCacheReference(const LayerGeometryProvider *) const;
Chris@477 297
Chris@477 298 /**
Chris@477 299 * When painting, we draw directly onto the draw buffer and then
Chris@478 300 * copy this to the part of the image cache that needed refreshing
Chris@478 301 * before copying the image cache onto the window. (Remind me why
Chris@1073 302 * we don't draw directly onto the cache?) (Answer: it's because
Chris@1073 303 * we usually apply scaling and smoothing in the x axis when
Chris@1073 304 * copying from draw buffer to cache)
Chris@477 305 */
Chris@95 306 mutable QImage m_drawBuffer;
Chris@0 307
Chris@0 308 bool m_exiting;
Chris@0 309
Chris@197 310 void initialisePalette();
Chris@197 311 void rotatePalette(int distance);
Chris@0 312
Chris@918 313 unsigned char getDisplayValue(LayerGeometryProvider *v, double input) const;
Chris@40 314
Chris@40 315 int getColourScaleWidth(QPainter &) const;
Chris@40 316
Chris@918 317 void illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &painter) const;
Chris@121 318
Chris@905 319 double getEffectiveMinFrequency() const;
Chris@905 320 double getEffectiveMaxFrequency() const;
Chris@38 321
Chris@486 322 // Note that the getYBin... methods return the nominal bin in the
Chris@486 323 // un-smoothed spectrogram. This is not necessarily the same bin
Chris@486 324 // as is pulled from the spectrogram and drawn at the given
Chris@486 325 // position, if the spectrogram has oversampling smoothing. Use
Chris@486 326 // getSmoothedYBinRange to obtain that.
Chris@486 327
Chris@918 328 bool getXBinRange(LayerGeometryProvider *v, int x, double &windowMin, double &windowMax) const;
Chris@918 329 bool getYBinRange(LayerGeometryProvider *v, int y, double &freqBinMin, double &freqBinMax) const;
Chris@918 330 bool getSmoothedYBinRange(LayerGeometryProvider *v, int y, double &freqBinMin, double &freqBinMax) const;
Chris@0 331
Chris@918 332 bool getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax) const;
Chris@918 333 bool getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y,
Chris@905 334 double &freqMin, double &freqMax,
Chris@905 335 double &adjFreqMin, double &adjFreqMax) const;
Chris@918 336 bool getXBinSourceRange(LayerGeometryProvider *v, int x, RealTime &timeMin, RealTime &timeMax) const;
Chris@918 337 bool getXYBinSourceRange(LayerGeometryProvider *v, int x, int y, double &min, double &max,
Chris@905 338 double &phaseMin, double &phaseMax) const;
Chris@0 339
Chris@805 340 int getWindowIncrement() const {
Chris@97 341 if (m_windowHopLevel == 0) return m_windowSize;
Chris@97 342 else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4;
Chris@97 343 else return m_windowSize / (1 << (m_windowHopLevel - 1));
Chris@0 344 }
Chris@113 345
Chris@918 346 int getZeroPadLevel(const LayerGeometryProvider *v) const;
Chris@918 347 int getFFTSize(const LayerGeometryProvider *v) const;
Chris@918 348 FFTModel *getFFTModel(const LayerGeometryProvider *v) const;
Chris@918 349 Dense3DModelPeakCache *getPeakCache(const LayerGeometryProvider *v) const;
Chris@130 350 void invalidateFFTModels();
Chris@115 351
Chris@1030 352 typedef std::map<int, FFTModel *> ViewFFTMap; // key is view id
Chris@1030 353 typedef std::map<int, Dense3DModelPeakCache *> PeakCacheMap; // key is view id
Chris@130 354 mutable ViewFFTMap m_fftModels;
Chris@484 355 mutable PeakCacheMap m_peakCaches;
Chris@1054 356 const int m_peakCacheDivisor;
Chris@193 357 mutable Model *m_sliceableModel;
Chris@119 358
Chris@1030 359 typedef std::map<int, MagnitudeRange> ViewMagMap; // key is view id
Chris@119 360 mutable ViewMagMap m_viewMags;
Chris@119 361 mutable std::vector<MagnitudeRange> m_columnMags;
Chris@119 362 void invalidateMagnitudes();
Chris@918 363 bool updateViewMagnitudes(LayerGeometryProvider *v) const;
Chris@1058 364
Chris@1024 365 int paintDrawBuffer(LayerGeometryProvider *v, int w, int h,
Chris@1024 366 const std::vector<int> &binforx,
Chris@1024 367 const std::vector<double> &binfory,
Chris@1024 368 bool usePeaksCache,
Chris@1024 369 MagnitudeRange &overallMag,
Chris@1026 370 bool &overallMagChanged,
Chris@1039 371 bool rightToLeft,
Chris@1039 372 double softTimeLimit) const;
Chris@1024 373 int paintDrawBufferPeakFrequencies(LayerGeometryProvider *v, int w, int h,
Chris@1024 374 const std::vector<int> &binforx,
Chris@1024 375 int minbin,
Chris@1024 376 int maxbin,
Chris@1024 377 double displayMinFreq,
Chris@1024 378 double displayMaxFreq,
Chris@1024 379 bool logarithmic,
Chris@1024 380 MagnitudeRange &overallMag,
Chris@1026 381 bool &overallMagChanged,
Chris@1039 382 bool rightToLeft,
Chris@1039 383 double softTimeLimit) const;
Chris@273 384
Chris@1058 385 std::vector<float> getColumnFromFFTModel(FFTModel *model,
Chris@1058 386 int sx,
Chris@1058 387 int minbin,
Chris@1058 388 int bincount) const;
Chris@1058 389
Chris@1058 390 std::vector<float> getColumnFromGenericModel(DenseThreeDimensionalModel *model,
Chris@1058 391 int sx,
Chris@1058 392 int minbin,
Chris@1058 393 int bincount) const;
Chris@1058 394
Chris@1059 395 void recordColumnExtents(const std::vector<float> &col,
Chris@1059 396 int sx,
Chris@1059 397 MagnitudeRange &overallMag,
Chris@1059 398 bool &overallMagChanged) const;
Chris@1058 399
Chris@1058 400 virtual void updateMeasureRectYCoords(LayerGeometryProvider *v,
Chris@1058 401 const MeasureRect &r) const;
Chris@1058 402 virtual void setMeasureRectYCoord(LayerGeometryProvider *v,
Chris@1058 403 MeasureRect &r, bool start, int y) const;
Chris@0 404 };
Chris@0 405
Chris@0 406 #endif