| 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@31 | 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@0 | 58 | 
| Chris@44 | 59     SpectrogramLayer(Configuration = FullRangeDb); | 
| Chris@0 | 60     ~SpectrogramLayer(); | 
| Chris@0 | 61 | 
| Chris@0 | 62     virtual const ZoomConstraint *getZoomConstraint() const { return this; } | 
| Chris@0 | 63     virtual const Model *getModel() const { return m_model; } | 
| Chris@916 | 64     virtual void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const; | 
| Chris@389 | 65     virtual void setSynchronousPainting(bool synchronous); | 
| Chris@0 | 66 | 
| Chris@918 | 67     virtual int getVerticalScaleWidth(LayerGeometryProvider *v, bool detailed, QPainter &) const; | 
| Chris@918 | 68     virtual void paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const; | 
| Chris@0 | 69 | 
| Chris@918 | 70     virtual bool getCrosshairExtents(LayerGeometryProvider *, QPainter &, QPoint cursorPos, | 
| Chris@77 | 71                                      std::vector<QRect> &extents) const; | 
| Chris@918 | 72     virtual void paintCrosshairs(LayerGeometryProvider *, QPainter &, QPoint) const; | 
| Chris@77 | 73 | 
| Chris@918 | 74     virtual QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const; | 
| Chris@0 | 75 | 
| Chris@918 | 76     virtual bool snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, | 
| Chris@805 | 77 				    int &resolution, | 
| Chris@28 | 78 				    SnapType snap) const; | 
| Chris@13 | 79 | 
| Chris@918 | 80     virtual void measureDoubleClick(LayerGeometryProvider *, QMouseEvent *); | 
| Chris@283 | 81 | 
| Chris@224 | 82     virtual bool hasLightBackground() const; | 
| Chris@224 | 83 | 
| Chris@0 | 84     void setModel(const DenseTimeValueModel *model); | 
| Chris@0 | 85 | 
| Chris@0 | 86     virtual PropertyList getProperties() const; | 
| Chris@87 | 87     virtual QString getPropertyLabel(const PropertyName &) const; | 
| Chris@335 | 88     virtual QString getPropertyIconName(const PropertyName &) const; | 
| Chris@0 | 89     virtual PropertyType getPropertyType(const PropertyName &) const; | 
| Chris@0 | 90     virtual QString getPropertyGroupName(const PropertyName &) const; | 
| Chris@0 | 91     virtual int getPropertyRangeAndValue(const PropertyName &, | 
| Chris@216 | 92                                          int *min, int *max, int *deflt) const; | 
| Chris@0 | 93     virtual QString getPropertyValueLabel(const PropertyName &, | 
| Chris@0 | 94 					  int value) const; | 
| Chris@862 | 95     virtual QString getPropertyValueIconName(const PropertyName &, | 
| Chris@862 | 96                                              int value) const; | 
| Chris@167 | 97     virtual RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const; | 
| Chris@0 | 98     virtual void setProperty(const PropertyName &, int value); | 
| Chris@0 | 99 | 
| Chris@0 | 100     /** | 
| Chris@0 | 101      * Specify the channel to use from the source model. | 
| Chris@0 | 102      * A value of -1 means to mix all available channels. | 
| Chris@0 | 103      * The default is channel 0. | 
| Chris@0 | 104      */ | 
| Chris@0 | 105     void setChannel(int); | 
| Chris@0 | 106     int getChannel() const; | 
| Chris@0 | 107 | 
| Chris@805 | 108     void setWindowSize(int); | 
| Chris@805 | 109     int getWindowSize() const; | 
| Chris@0 | 110 | 
| Chris@805 | 111     void setWindowHopLevel(int level); | 
| Chris@805 | 112     int getWindowHopLevel() const; | 
| Chris@0 | 113 | 
| Chris@0 | 114     void setWindowType(WindowType type); | 
| Chris@0 | 115     WindowType getWindowType() const; | 
| Chris@0 | 116 | 
| Chris@0 | 117     /** | 
| Chris@110 | 118      * Set the gain multiplier for sample values in this view. | 
| Chris@0 | 119      * The default is 1.0. | 
| Chris@0 | 120      */ | 
| Chris@0 | 121     void setGain(float gain); | 
| Chris@0 | 122     float getGain() const; | 
| Chris@0 | 123 | 
| Chris@37 | 124     /** | 
| Chris@110 | 125      * Set the threshold for sample values to qualify for being shown | 
| Chris@110 | 126      * in the FFT, in voltage units. | 
| Chris@37 | 127      * | 
| Chris@1127 | 128      * The default is 10^-8 (-80dB). | 
| Chris@37 | 129      */ | 
| Chris@37 | 130     void setThreshold(float threshold); | 
| Chris@37 | 131     float getThreshold() const; | 
| Chris@37 | 132 | 
| Chris@805 | 133     void setMinFrequency(int); | 
| Chris@805 | 134     int getMinFrequency() const; | 
| Chris@37 | 135 | 
| Chris@805 | 136     void setMaxFrequency(int); // 0 -> no maximum | 
| Chris@805 | 137     int getMaxFrequency() const; | 
| Chris@0 | 138 | 
| Chris@0 | 139     /** | 
| Chris@1092 | 140      * Specify the scale for sample levels.  See ColourScale and | 
| Chris@1092 | 141      * WaveformLayer for comparison and details of meter and dB | 
| Chris@1092 | 142      * scaling.  The default is LogColourScale. | 
| Chris@0 | 143      */ | 
| Chris@1105 | 144     void setColourScale(ColourScaleType); | 
| Chris@1105 | 145     ColourScaleType getColourScale() const; | 
| Chris@0 | 146 | 
| Chris@0 | 147     /** | 
| Chris@1137 | 148      * Specify multiple factor for colour scale. This is 2.0 for | 
| Chris@1137 | 149      * log-power spectrogram and 1.0 otherwise. | 
| Chris@1137 | 150      */ | 
| Chris@1137 | 151     void setColourScaleMultiple(double); | 
| Chris@1137 | 152     double getColourScaleMultiple() const; | 
| Chris@1137 | 153 | 
| Chris@1137 | 154     /** | 
| Chris@0 | 155      * Specify the scale for the y axis. | 
| Chris@0 | 156      */ | 
| Chris@1103 | 157     void setBinScale(BinScale); | 
| Chris@1103 | 158     BinScale getBinScale() const; | 
| Chris@0 | 159 | 
| Chris@35 | 160     /** | 
| Chris@35 | 161      * Specify the processing of frequency bins for the y axis. | 
| Chris@35 | 162      */ | 
| Chris@1103 | 163     void setBinDisplay(BinDisplay); | 
| Chris@1103 | 164     BinDisplay getBinDisplay() const; | 
| Chris@862 | 165 | 
| Chris@719 | 166     /** | 
| Chris@1104 | 167      * Specify the normalization mode for individual columns. | 
| Chris@719 | 168      */ | 
| Chris@1104 | 169     void setNormalization(ColumnNormalization); | 
| Chris@1104 | 170     ColumnNormalization getNormalization() const; | 
| Chris@1104 | 171 | 
| Chris@1104 | 172     /** | 
| Chris@1104 | 173      * Specify whether to normalize the visible area. | 
| Chris@1104 | 174      */ | 
| Chris@1104 | 175     void setNormalizeVisibleArea(bool); | 
| Chris@1104 | 176     bool getNormalizeVisibleArea() const; | 
| Chris@120 | 177 | 
| Chris@719 | 178     /** | 
| Chris@862 | 179      * Specify the colour map. See ColourMapper for the colour map | 
| Chris@862 | 180      * values. | 
| Chris@719 | 181      */ | 
| Chris@197 | 182     void setColourMap(int map); | 
| Chris@197 | 183     int getColourMap() const; | 
| Chris@0 | 184 | 
| Chris@9 | 185     /** | 
| Chris@9 | 186      * Specify the colourmap rotation for the colour scale. | 
| Chris@9 | 187      */ | 
| Chris@9 | 188     void setColourRotation(int); | 
| Chris@9 | 189     int getColourRotation() const; | 
| Chris@9 | 190 | 
| Chris@0 | 191     virtual VerticalPosition getPreferredFrameCountPosition() const { | 
| Chris@0 | 192 	return PositionTop; | 
| Chris@0 | 193     } | 
| Chris@0 | 194 | 
| Chris@15 | 195     virtual bool isLayerOpaque() const { return true; } | 
| Chris@287 | 196 | 
| Chris@287 | 197     virtual ColourSignificance getLayerColourSignificance() const { | 
| Chris@287 | 198         return ColourHasMeaningfulValue; | 
| Chris@287 | 199     } | 
| Chris@15 | 200 | 
| Chris@918 | 201     double getYForFrequency(const LayerGeometryProvider *v, double frequency) const; | 
| Chris@918 | 202     double getFrequencyForY(const LayerGeometryProvider *v, int y) const; | 
| Chris@42 | 203 | 
| Chris@1085 | 204     //!!! VerticalBinLayer methods. Note overlap with get*BinRange() | 
| Chris@1113 | 205     double getYForBin(const LayerGeometryProvider *, double bin) const; | 
| Chris@1113 | 206     double getBinForY(const LayerGeometryProvider *, double y) const; | 
| Chris@1085 | 207 | 
| Chris@918 | 208     virtual int getCompletion(LayerGeometryProvider *v) const; | 
| Chris@918 | 209     virtual QString getError(LayerGeometryProvider *v) const; | 
| Chris@0 | 210 | 
| Chris@905 | 211     virtual bool getValueExtents(double &min, double &max, | 
| Chris@101 | 212                                  bool &logarithmic, QString &unit) const; | 
| Chris@101 | 213 | 
| Chris@905 | 214     virtual bool getDisplayExtents(double &min, double &max) const; | 
| Chris@79 | 215 | 
| Chris@905 | 216     virtual bool setDisplayExtents(double min, double max); | 
| Chris@120 | 217 | 
| Chris@918 | 218     virtual bool getYScaleValue(const LayerGeometryProvider *, int, double &, QString &) const; | 
| Chris@261 | 219 | 
| Chris@316 | 220     virtual void toXml(QTextStream &stream, QString indent = "", | 
| Chris@316 | 221                        QString extraAttributes = "") const; | 
| Chris@6 | 222 | 
| Chris@11 | 223     void setProperties(const QXmlAttributes &attributes); | 
| Chris@11 | 224 | 
| Chris@918 | 225     virtual void setLayerDormant(const LayerGeometryProvider *v, bool dormant); | 
| Chris@29 | 226 | 
| Chris@918 | 227     virtual bool isLayerScrollable(const LayerGeometryProvider *) const { return false; } | 
| Chris@94 | 228 | 
| Chris@133 | 229     virtual int getVerticalZoomSteps(int &defaultStep) const; | 
| Chris@133 | 230     virtual int getCurrentVerticalZoomStep() const; | 
| Chris@133 | 231     virtual void setVerticalZoomStep(int); | 
| Chris@187 | 232     virtual RangeMapper *getNewVerticalZoomRangeMapper() const; | 
| Chris@133 | 233 | 
| Chris@193 | 234     virtual const Model *getSliceableModel() const; | 
| Chris@193 | 235 | 
| Chris@0 | 236 protected slots: | 
| Chris@0 | 237     void cacheInvalid(); | 
| Chris@906 | 238     void cacheInvalid(sv_frame_t startFrame, sv_frame_t endFrame); | 
| Chris@122 | 239 | 
| Chris@122 | 240     void preferenceChanged(PropertyContainer::PropertyName name); | 
| Chris@0 | 241 | 
| Chris@0 | 242 protected: | 
| Chris@0 | 243     const DenseTimeValueModel *m_model; // I do not own this | 
| Chris@484 | 244 | 
| Chris@35 | 245     int                 m_channel; | 
| Chris@1023 | 246     int                 m_windowSize; | 
| Chris@35 | 247     WindowType          m_windowType; | 
| Chris@1023 | 248     int                 m_windowHopLevel; | 
| Chris@35 | 249     float               m_gain; | 
| Chris@215 | 250     float               m_initialGain; | 
| Chris@37 | 251     float               m_threshold; | 
| Chris@215 | 252     float               m_initialThreshold; | 
| Chris@35 | 253     int                 m_colourRotation; | 
| Chris@215 | 254     int                 m_initialRotation; | 
| Chris@1023 | 255     int                 m_minFrequency; | 
| Chris@1023 | 256     int                 m_maxFrequency; | 
| Chris@1023 | 257     int                 m_initialMaxFrequency; | 
| Chris@1106 | 258     ColourScaleType     m_colourScale; | 
| Chris@1137 | 259     double              m_colourScaleMultiple; | 
| Chris@197 | 260     int                 m_colourMap; | 
| Chris@77 | 261     QColor              m_crosshairColour; | 
| Chris@1104 | 262     BinScale            m_binScale; | 
| Chris@1104 | 263     BinDisplay          m_binDisplay; | 
| Chris@1104 | 264     ColumnNormalization m_normalization; // of individual columns | 
| Chris@1104 | 265     bool                m_normalizeVisibleArea; | 
| Chris@133 | 266     int                 m_lastEmittedZoomStep; | 
| Chris@389 | 267     bool                m_synchronous; | 
| Chris@0 | 268 | 
| Chris@608 | 269     mutable bool        m_haveDetailedScale; | 
| Chris@215 | 270 | 
| Chris@1137 | 271     static std::pair<ColourScaleType, double> convertToColourScale(int value); | 
| Chris@1137 | 272     static int convertFromColourScale(ColourScaleType type, double multiple); | 
| Chris@1104 | 273     static std::pair<ColumnNormalization, bool> convertToColumnNorm(int value); | 
| Chris@1104 | 274     static int convertFromColumnNorm(ColumnNormalization norm, bool visible); | 
| Chris@1104 | 275 | 
| Chris@0 | 276     bool m_exiting; | 
| Chris@0 | 277 | 
| Chris@40 | 278     int getColourScaleWidth(QPainter &) const; | 
| Chris@40 | 279 | 
| Chris@918 | 280     void illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &painter) const; | 
| Chris@121 | 281 | 
| Chris@905 | 282     double getEffectiveMinFrequency() const; | 
| Chris@905 | 283     double getEffectiveMaxFrequency() const; | 
| Chris@38 | 284 | 
| Chris@918 | 285     bool getXBinRange(LayerGeometryProvider *v, int x, double &windowMin, double &windowMax) const; | 
| Chris@918 | 286     bool getYBinRange(LayerGeometryProvider *v, int y, double &freqBinMin, double &freqBinMax) const; | 
| Chris@0 | 287 | 
| Chris@918 | 288     bool getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax) const; | 
| Chris@918 | 289     bool getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y, | 
| Chris@905 | 290 				    double &freqMin, double &freqMax, | 
| Chris@905 | 291 				    double &adjFreqMin, double &adjFreqMax) const; | 
| Chris@918 | 292     bool getXBinSourceRange(LayerGeometryProvider *v, int x, RealTime &timeMin, RealTime &timeMax) const; | 
| Chris@918 | 293     bool getXYBinSourceRange(LayerGeometryProvider *v, int x, int y, double &min, double &max, | 
| Chris@905 | 294 			     double &phaseMin, double &phaseMax) const; | 
| Chris@0 | 295 | 
| Chris@805 | 296     int getWindowIncrement() const { | 
| Chris@97 | 297         if (m_windowHopLevel == 0) return m_windowSize; | 
| Chris@97 | 298         else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4; | 
| Chris@97 | 299         else return m_windowSize / (1 << (m_windowHopLevel - 1)); | 
| Chris@0 | 300     } | 
| Chris@113 | 301 | 
| Chris@1086 | 302     int getFFTOversampling() const; | 
| Chris@1087 | 303     int getFFTSize() const; // m_windowSize * getFFTOversampling() | 
| Chris@115 | 304 | 
| Chris@1089 | 305     mutable FFTModel *m_fftModel; //!!! should not be mutable, see getFFTModel()? | 
| Chris@1088 | 306     mutable Dense3DModelPeakCache *m_peakCache; | 
| Chris@1054 | 307     const int m_peakCacheDivisor; | 
| Chris@119 | 308 | 
| Chris@1030 | 309     typedef std::map<int, MagnitudeRange> ViewMagMap; // key is view id | 
| Chris@119 | 310     mutable ViewMagMap m_viewMags; | 
| Chris@1136 | 311     mutable ViewMagMap m_lastRenderedMags; // when in normalizeVisibleArea mode | 
| Chris@119 | 312     void invalidateMagnitudes(); | 
| Chris@1089 | 313 | 
| Chris@1089 | 314     typedef std::map<int, Colour3DPlotRenderer *> ViewRendererMap; // key is view id | 
| Chris@1089 | 315     mutable ViewRendererMap m_renderers; | 
| Chris@1089 | 316     Colour3DPlotRenderer *getRenderer(LayerGeometryProvider *) const; | 
| Chris@1106 | 317     void invalidateRenderers(); | 
| Chris@1058 | 318 | 
| Chris@1088 | 319     FFTModel *getFFTModel() const; | 
| Chris@1088 | 320     Dense3DModelPeakCache *getPeakCache() const; | 
| Chris@1088 | 321     void invalidateFFTModel(); | 
| Chris@1089 | 322 | 
| Chris@1106 | 323     void paintWithRenderer(LayerGeometryProvider *v, QPainter &paint, QRect rect) const; | 
| Chris@1142 | 324 | 
| Chris@1143 | 325     void paintDetailedScale(LayerGeometryProvider *v, | 
| Chris@1143 | 326                             QPainter &paint, QRect rect) const; | 
| Chris@1143 | 327     void paintDetailedScalePhase(LayerGeometryProvider *v, | 
| Chris@1143 | 328                                  QPainter &paint, QRect rect) const; | 
| Chris@1058 | 329 | 
| Chris@1058 | 330     virtual void updateMeasureRectYCoords(LayerGeometryProvider *v, | 
| Chris@1058 | 331                                           const MeasureRect &r) const; | 
| Chris@1058 | 332     virtual void setMeasureRectYCoord(LayerGeometryProvider *v, | 
| Chris@1058 | 333                                       MeasureRect &r, bool start, int y) const; | 
| Chris@0 | 334 }; | 
| Chris@0 | 335 | 
| Chris@0 | 336 #endif |