annotate layer/SpectrogramLayer.h @ 1556:ac8da42674ff spectrogram-export

Handle peaks
author Chris Cannam
date Tue, 07 Jan 2020 11:18:57 +0000
parents 745be36202aa
children 3b45788b7804
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@1555 337 mutable std::vector<ModelId> m_exporters; // used and waiting to be released
Chris@1450 338 void checkCacheSpace(int *suggestedPeakDivisor,
Chris@1450 339 bool *createWholeCache) const;
Chris@1211 340 void recreateFFTModel();
Chris@119 341
Chris@1030 342 typedef std::map<int, MagnitudeRange> ViewMagMap; // key is view id
Chris@119 343 mutable ViewMagMap m_viewMags;
Chris@1136 344 mutable ViewMagMap m_lastRenderedMags; // when in normalizeVisibleArea mode
Chris@119 345 void invalidateMagnitudes();
Chris@1089 346
Chris@1089 347 typedef std::map<int, Colour3DPlotRenderer *> ViewRendererMap; // key is view id
Chris@1089 348 mutable ViewRendererMap m_renderers;
Chris@1089 349 Colour3DPlotRenderer *getRenderer(LayerGeometryProvider *) const;
Chris@1106 350 void invalidateRenderers();
Chris@1242 351
Chris@1242 352 void deleteDerivedModels();
Chris@1058 353
Chris@1106 354 void paintWithRenderer(LayerGeometryProvider *v, QPainter &paint, QRect rect) const;
Chris@1142 355
Chris@1143 356 void paintDetailedScale(LayerGeometryProvider *v,
Chris@1143 357 QPainter &paint, QRect rect) const;
Chris@1143 358 void paintDetailedScalePhase(LayerGeometryProvider *v,
Chris@1143 359 QPainter &paint, QRect rect) const;
Chris@1058 360
Chris@1406 361 void updateMeasureRectYCoords(LayerGeometryProvider *v,
Chris@1406 362 const MeasureRect &r) const override;
Chris@1406 363 void setMeasureRectYCoord(LayerGeometryProvider *v,
Chris@1406 364 MeasureRect &r, bool start, int y) const override;
Chris@0 365 };
Chris@0 366
Chris@0 367 #endif