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