annotate layer/SpectrogramLayer.h @ 1534:bfd8b22fd67c

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