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