annotate layer/SpectrogramLayer.h @ 1605:ae2d5f8ff005

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