annotate layer/SpectrogramLayer.h @ 1552:045063dcd2bc

Merge
author Chris Cannam
date Thu, 21 Nov 2019 14:03:19 +0000
parents e6362cf5ff1d
children a0b2f3b4dd2f
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@1547 81 int &resolution,
Chris@1547 82 SnapType snap, int ycoord) 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