SpectrogramLayer.h

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #ifndef _SPECTROGRAM_LAYER_H_
00017 #define _SPECTROGRAM_LAYER_H_
00018 
00019 #include "SliceableLayer.h"
00020 #include "base/Window.h"
00021 #include "base/RealTime.h"
00022 #include "base/Thread.h"
00023 #include "base/PropertyContainer.h"
00024 #include "data/model/PowerOfSqrtTwoZoomConstraint.h"
00025 #include "data/model/DenseTimeValueModel.h"
00026 #include "data/model/FFTModel.h"
00027 
00028 #include <QMutex>
00029 #include <QWaitCondition>
00030 #include <QImage>
00031 #include <QPixmap>
00032 
00033 class View;
00034 class QPainter;
00035 class QImage;
00036 class QPixmap;
00037 class QTimer;
00038 class FFTModel;
00039 
00040 
00046 class SpectrogramLayer : public SliceableLayer,
00047                          public PowerOfSqrtTwoZoomConstraint
00048 {
00049     Q_OBJECT
00050 
00051 public:
00052     enum Configuration { FullRangeDb, MelodicRange, MelodicPeaks };
00053     
00054     SpectrogramLayer(Configuration = FullRangeDb);
00055     ~SpectrogramLayer();
00056 
00057     virtual const ZoomConstraint *getZoomConstraint() const { return this; }
00058     virtual const Model *getModel() const { return m_model; }
00059     virtual void paint(View *v, QPainter &paint, QRect rect) const;
00060 
00061     virtual int getVerticalScaleWidth(View *v, QPainter &) const;
00062     virtual void paintVerticalScale(View *v, QPainter &paint, QRect rect) const;
00063 
00064     virtual bool getCrosshairExtents(View *, QPainter &, QPoint cursorPos,
00065                                      std::vector<QRect> &extents) const;
00066     virtual void paintCrosshairs(View *, QPainter &, QPoint) const;
00067 
00068     virtual QString getFeatureDescription(View *v, QPoint &) const;
00069 
00070     virtual bool snapToFeatureFrame(View *v, int &frame,
00071                                     size_t &resolution,
00072                                     SnapType snap) const;
00073 
00074     virtual void measureDoubleClick(View *, QMouseEvent *);
00075 
00076     virtual bool hasLightBackground() const;
00077 
00078     void setModel(const DenseTimeValueModel *model);
00079 
00080     virtual PropertyList getProperties() const;
00081     virtual QString getPropertyLabel(const PropertyName &) const;
00082     virtual QString getPropertyIconName(const PropertyName &) const;
00083     virtual PropertyType getPropertyType(const PropertyName &) const;
00084     virtual QString getPropertyGroupName(const PropertyName &) const;
00085     virtual int getPropertyRangeAndValue(const PropertyName &,
00086                                          int *min, int *max, int *deflt) const;
00087     virtual QString getPropertyValueLabel(const PropertyName &,
00088                                           int value) const;
00089     virtual RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const;
00090     virtual void setProperty(const PropertyName &, int value);
00091 
00097     void setChannel(int);
00098     int getChannel() const;
00099 
00100     void setWindowSize(size_t);
00101     size_t getWindowSize() const;
00102     
00103     void setWindowHopLevel(size_t level);
00104     size_t getWindowHopLevel() const;
00105 
00106     void setWindowType(WindowType type);
00107     WindowType getWindowType() const;
00108 
00109     void setZeroPadLevel(size_t level);
00110     size_t getZeroPadLevel() const;
00111 
00116     void setGain(float gain);
00117     float getGain() const;
00118 
00125     void setThreshold(float threshold);
00126     float getThreshold() const;
00127 
00128     void setMinFrequency(size_t);
00129     size_t getMinFrequency() const;
00130 
00131     void setMaxFrequency(size_t); // 0 -> no maximum
00132     size_t getMaxFrequency() const;
00133 
00134     enum ColourScale {
00135         LinearColourScale,
00136         MeterColourScale,
00137         dBSquaredColourScale,
00138         dBColourScale,
00139         PhaseColourScale
00140     };
00141 
00146     void setColourScale(ColourScale);
00147     ColourScale getColourScale() const;
00148 
00149     enum FrequencyScale {
00150         LinearFrequencyScale,
00151         LogFrequencyScale
00152     };
00153     
00157     void setFrequencyScale(FrequencyScale);
00158     FrequencyScale getFrequencyScale() const;
00159 
00160     enum BinDisplay {
00161         AllBins,
00162         PeakBins,
00163         PeakFrequencies
00164     };
00165     
00169     void setBinDisplay(BinDisplay);
00170     BinDisplay getBinDisplay() const;
00171 
00172     void setNormalizeColumns(bool n);
00173     bool getNormalizeColumns() const;
00174 
00175     void setNormalizeVisibleArea(bool n);
00176     bool getNormalizeVisibleArea() const;
00177 
00178     void setColourMap(int map);
00179     int getColourMap() const;
00180 
00184     void setColourRotation(int);
00185     int getColourRotation() const;
00186 
00187     virtual VerticalPosition getPreferredFrameCountPosition() const {
00188         return PositionTop;
00189     }
00190 
00191     virtual bool isLayerOpaque() const { return true; }
00192 
00193     virtual ColourSignificance getLayerColourSignificance() const {
00194         return ColourHasMeaningfulValue;
00195     }
00196 
00197     float getYForFrequency(const View *v, float frequency) const;
00198     float getFrequencyForY(const View *v, int y) const;
00199 
00200     virtual int getCompletion(View *v) const;
00201 
00202     virtual bool getValueExtents(float &min, float &max,
00203                                  bool &logarithmic, QString &unit) const;
00204 
00205     virtual bool getDisplayExtents(float &min, float &max) const;
00206 
00207     virtual bool setDisplayExtents(float min, float max);
00208 
00209     virtual bool getYScaleValue(const View *, int, float &, QString &) const;
00210 
00211     virtual void toXml(QTextStream &stream, QString indent = "",
00212                        QString extraAttributes = "") const;
00213 
00214     void setProperties(const QXmlAttributes &attributes);
00215 
00216     virtual void setLayerDormant(const View *v, bool dormant);
00217 
00218     virtual bool isLayerScrollable(const View *) const { return false; }
00219 
00220     virtual int getVerticalZoomSteps(int &defaultStep) const;
00221     virtual int getCurrentVerticalZoomStep() const;
00222     virtual void setVerticalZoomStep(int);
00223     virtual RangeMapper *getNewVerticalZoomRangeMapper() const;
00224 
00225     virtual const Model *getSliceableModel() const;
00226 
00227 protected slots:
00228     void cacheInvalid();
00229     void cacheInvalid(size_t startFrame, size_t endFrame);
00230     
00231     void preferenceChanged(PropertyContainer::PropertyName name);
00232 
00233     void fillTimerTimedOut();
00234 
00235 protected:
00236     const DenseTimeValueModel *m_model; // I do not own this
00237     
00238     int                 m_channel;
00239     size_t              m_windowSize;
00240     WindowType          m_windowType;
00241     size_t              m_windowHopLevel;
00242     size_t              m_zeroPadLevel;
00243     size_t              m_fftSize;
00244     float               m_gain;
00245     float               m_initialGain;
00246     float               m_threshold;
00247     float               m_initialThreshold;
00248     int                 m_colourRotation;
00249     int                 m_initialRotation;
00250     size_t              m_minFrequency;
00251     size_t              m_maxFrequency;
00252     size_t              m_initialMaxFrequency;
00253     ColourScale         m_colourScale;
00254     int                 m_colourMap;
00255     QColor              m_crosshairColour;
00256     FrequencyScale      m_frequencyScale;
00257     BinDisplay          m_binDisplay;
00258     bool                m_normalizeColumns;
00259     bool                m_normalizeVisibleArea;
00260     int                 m_lastEmittedZoomStep;
00261 
00262     mutable int         m_lastPaintBlockWidth;
00263     mutable RealTime    m_lastPaintTime;
00264 
00265     enum { NO_VALUE = 0 }; // colour index for unused pixels
00266 
00267     class Palette
00268     {
00269     public:
00270         QColor getColour(unsigned char index) const {
00271             return m_colours[index];
00272         }
00273     
00274         void setColour(unsigned char index, QColor colour) {
00275             m_colours[index] = colour;
00276         }
00277 
00278     private:
00279         QColor m_colours[256];
00280     };
00281 
00282     Palette m_palette;
00283 
00284     struct PixmapCache
00285     {
00286         QPixmap pixmap;
00287         QRect validArea;
00288         long startFrame;
00289         size_t zoomLevel;
00290     };
00291     typedef std::map<const View *, PixmapCache> ViewPixmapCache;
00292     void invalidatePixmapCaches();
00293     void invalidatePixmapCaches(size_t startFrame, size_t endFrame);
00294     mutable ViewPixmapCache m_pixmapCaches;
00295     mutable QImage m_drawBuffer;
00296 
00297     mutable QTimer *m_updateTimer;
00298 
00299     mutable size_t m_candidateFillStartFrame;
00300     bool m_exiting;
00301 
00302     void initialisePalette();
00303     void rotatePalette(int distance);
00304 
00305     unsigned char getDisplayValue(View *v, float input) const;
00306     float getInputForDisplayValue(unsigned char uc) const;
00307 
00308     int getColourScaleWidth(QPainter &) const;
00309 
00310     void illuminateLocalFeatures(View *v, QPainter &painter) const;
00311 
00312     float getEffectiveMinFrequency() const;
00313     float getEffectiveMaxFrequency() const;
00314 
00315     struct LayerRange {
00316         long   startFrame;
00317         int    zoomLevel;
00318         size_t modelStart;
00319         size_t modelEnd;
00320     };
00321     bool getXBinRange(View *v, int x, float &windowMin, float &windowMax) const;
00322     bool getYBinRange(View *v, int y, float &freqBinMin, float &freqBinMax) const;
00323 
00324     bool getYBinSourceRange(View *v, int y, float &freqMin, float &freqMax) const;
00325     bool getAdjustedYBinSourceRange(View *v, int x, int y,
00326                                     float &freqMin, float &freqMax,
00327                                     float &adjFreqMin, float &adjFreqMax) const;
00328     bool getXBinSourceRange(View *v, int x, RealTime &timeMin, RealTime &timeMax) const;
00329     bool getXYBinSourceRange(View *v, int x, int y, float &min, float &max,
00330                              float &phaseMin, float &phaseMax) const;
00331 
00332     size_t getWindowIncrement() const {
00333         if (m_windowHopLevel == 0) return m_windowSize;
00334         else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4;
00335         else return m_windowSize / (1 << (m_windowHopLevel - 1));
00336     }
00337 
00338     size_t getZeroPadLevel(const View *v) const;
00339     size_t getFFTSize(const View *v) const;
00340     FFTModel *getFFTModel(const View *v) const;
00341     void invalidateFFTModels();
00342 
00343     typedef std::pair<FFTModel *, int> FFTFillPair; // model, last fill
00344     typedef std::map<const View *, FFTFillPair> ViewFFTMap;
00345     typedef std::vector<float> FloatVector;
00346     mutable ViewFFTMap m_fftModels;
00347     mutable Model *m_sliceableModel;
00348 
00349     class MagnitudeRange {
00350     public:
00351         MagnitudeRange() : m_min(0), m_max(0) { }
00352         bool operator==(const MagnitudeRange &r) {
00353             return r.m_min == m_min && r.m_max == m_max;
00354         }
00355         bool isSet() const { return (m_min != 0 || m_max != 0); }
00356         void set(float min, float max) {
00357             m_min = convert(min);
00358             m_max = convert(max);
00359             if (m_max < m_min) m_max = m_min;
00360         }
00361         bool sample(float f) {
00362             unsigned int ui = convert(f);
00363             bool changed = false;
00364             if (isSet()) {
00365                 if (ui < m_min) { m_min = ui; changed = true; }
00366                 if (ui > m_max) { m_max = ui; changed = true; }
00367             } else {
00368                 m_max = m_min = ui;
00369                 changed = true;
00370             }
00371             return changed;
00372         }            
00373         bool sample(const MagnitudeRange &r) {
00374             bool changed = false;
00375             if (isSet()) {
00376                 if (r.m_min < m_min) { m_min = r.m_min; changed = true; }
00377                 if (r.m_max > m_max) { m_max = r.m_max; changed = true; }
00378             } else {
00379                 m_min = r.m_min;
00380                 m_max = r.m_max;
00381                 changed = true;
00382             }
00383             return changed;
00384         }            
00385         float getMin() const { return float(m_min) / UINT_MAX; }
00386         float getMax() const { return float(m_max) / UINT_MAX; }
00387     private:
00388         unsigned int m_min;
00389         unsigned int m_max;
00390         unsigned int convert(float f) {
00391             if (f < 0.f) f = 0.f;
00392             if (f > 1.f) f = 1.f;
00393             return (unsigned int)(f * UINT_MAX);
00394         }
00395     };
00396 
00397     typedef std::map<const View *, MagnitudeRange> ViewMagMap;
00398     mutable ViewMagMap m_viewMags;
00399     mutable std::vector<MagnitudeRange> m_columnMags;
00400     void invalidateMagnitudes();
00401     bool updateViewMagnitudes(View *v) const;
00402 
00403     virtual void updateMeasureRectYCoords(View *v, const MeasureRect &r) const;
00404     virtual void setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const;
00405 };
00406 
00407 #endif

Generated on Wed Feb 20 15:45:28 2008 for SonicVisualiser by  doxygen 1.5.1