diff layer/SpectrogramLayer.h @ 1216:dc2af6616c83

Merge from branch 3.0-integration
author Chris Cannam
date Fri, 13 Jan 2017 10:29:50 +0000
parents a1ee3108d1d3
children de1792daae07
line wrap: on
line diff
--- a/layer/SpectrogramLayer.h	Fri Mar 04 12:23:31 2016 +0000
+++ b/layer/SpectrogramLayer.h	Fri Jan 13 10:29:50 2017 +0000
@@ -13,11 +13,12 @@
     COPYING included with this distribution for more information.
 */
 
-#ifndef _SPECTROGRAM_LAYER_H_
-#define _SPECTROGRAM_LAYER_H_
+#ifndef SPECTROGRAM_LAYER_H
+#define SPECTROGRAM_LAYER_H
 
 #include "SliceableLayer.h"
 #include "base/Window.h"
+#include "base/MagnitudeRange.h"
 #include "base/RealTime.h"
 #include "base/Thread.h"
 #include "base/PropertyContainer.h"
@@ -25,6 +26,10 @@
 #include "data/model/DenseTimeValueModel.h"
 #include "data/model/FFTModel.h"
 
+#include "VerticalBinLayer.h"
+#include "ColourScale.h"
+#include "Colour3DPlotRenderer.h"
+
 #include <QMutex>
 #include <QWaitCondition>
 #include <QImage>
@@ -38,13 +43,12 @@
 class FFTModel;
 class Dense3DModelPeakCache;
 
-
 /**
  * SpectrogramLayer represents waveform data (obtained from a
  * DenseTimeValueModel) in spectrogram form.
  */
 
-class SpectrogramLayer : public SliceableLayer,
+class SpectrogramLayer : public VerticalBinLayer,
 			 public PowerOfSqrtTwoZoomConstraint
 {
     Q_OBJECT
@@ -57,23 +61,23 @@
 
     virtual const ZoomConstraint *getZoomConstraint() const { return this; }
     virtual const Model *getModel() const { return m_model; }
-    virtual void paint(View *v, QPainter &paint, QRect rect) const;
+    virtual void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const;
     virtual void setSynchronousPainting(bool synchronous);
 
-    virtual int getVerticalScaleWidth(View *v, bool detailed, QPainter &) const;
-    virtual void paintVerticalScale(View *v, bool detailed, QPainter &paint, QRect rect) const;
+    virtual int getVerticalScaleWidth(LayerGeometryProvider *v, bool detailed, QPainter &) const;
+    virtual void paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const;
 
-    virtual bool getCrosshairExtents(View *, QPainter &, QPoint cursorPos,
+    virtual bool getCrosshairExtents(LayerGeometryProvider *, QPainter &, QPoint cursorPos,
                                      std::vector<QRect> &extents) const;
-    virtual void paintCrosshairs(View *, QPainter &, QPoint) const;
+    virtual void paintCrosshairs(LayerGeometryProvider *, QPainter &, QPoint) const;
 
-    virtual QString getFeatureDescription(View *v, QPoint &) const;
+    virtual QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const;
 
-    virtual bool snapToFeatureFrame(View *v, sv_frame_t &frame,
+    virtual bool snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
 				    int &resolution,
 				    SnapType snap) const;
 
-    virtual void measureDoubleClick(View *, QMouseEvent *);
+    virtual void measureDoubleClick(LayerGeometryProvider *, QMouseEvent *);
 
     virtual bool hasLightBackground() const;
 
@@ -88,6 +92,8 @@
                                          int *min, int *max, int *deflt) const;
     virtual QString getPropertyValueLabel(const PropertyName &,
 					  int value) const;
+    virtual QString getPropertyValueIconName(const PropertyName &,
+                                             int value) const;
     virtual RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const;
     virtual void setProperty(const PropertyName &, int value);
 
@@ -108,9 +114,6 @@
     void setWindowType(WindowType type);
     WindowType getWindowType() const;
 
-    void setZeroPadLevel(int level);
-    int getZeroPadLevel() const;
-
     /**
      * Set the gain multiplier for sample values in this view.
      * The default is 1.0.
@@ -122,7 +125,7 @@
      * Set the threshold for sample values to qualify for being shown
      * in the FFT, in voltage units.
      *
-     * The default is 0.0.
+     * The default is 10^-8 (-80dB).
      */
     void setThreshold(float threshold);
     float getThreshold() const;
@@ -133,64 +136,49 @@
     void setMaxFrequency(int); // 0 -> no maximum
     int getMaxFrequency() const;
 
-    enum ColourScale {
-	LinearColourScale,
-	MeterColourScale,
-        dBSquaredColourScale,
-	dBColourScale,
-	PhaseColourScale
-    };
+    /**
+     * Specify the scale for sample levels.  See ColourScale and
+     * WaveformLayer for comparison and details of meter and dB
+     * scaling.  The default is LogColourScale.
+     */
+    void setColourScale(ColourScaleType);
+    ColourScaleType getColourScale() const;
 
     /**
-     * Specify the scale for sample levels.  See WaveformLayer for
-     * details of meter and dB scaling.  The default is dBColourScale.
+     * Specify multiple factor for colour scale. This is 2.0 for
+     * log-power spectrogram and 1.0 otherwise.
      */
-    void setColourScale(ColourScale);
-    ColourScale getColourScale() const;
-
-    enum FrequencyScale {
-	LinearFrequencyScale,
-	LogFrequencyScale
-    };
+    void setColourScaleMultiple(double);
+    double getColourScaleMultiple() const;
     
     /**
      * Specify the scale for the y axis.
      */
-    void setFrequencyScale(FrequencyScale);
-    FrequencyScale getFrequencyScale() const;
+    void setBinScale(BinScale);
+    BinScale getBinScale() const;
 
-    enum BinDisplay {
-	AllBins,
-	PeakBins,
-	PeakFrequencies
-    };
-    
     /**
      * Specify the processing of frequency bins for the y axis.
      */
     void setBinDisplay(BinDisplay);
     BinDisplay getBinDisplay() const;
- 
-    /**
-     * Normalize each column to its maximum value, independent of its
-     * neighbours.
-     */
-    void setNormalizeColumns(bool n);
-    bool getNormalizeColumns() const;
 
     /**
-     * Normalize each value against the maximum in the visible region.
+     * Specify the normalization mode for individual columns.
      */
-    void setNormalizeVisibleArea(bool n);
+    void setNormalization(ColumnNormalization);
+    ColumnNormalization getNormalization() const;
+
+    /**
+     * Specify whether to normalize the visible area.
+     */
+    void setNormalizeVisibleArea(bool);
     bool getNormalizeVisibleArea() const;
 
     /**
-     * Normalize each column to its maximum value, and then scale by
-     * the log of the (absolute) maximum value.
+     * Specify the colour map. See ColourMapper for the colour map
+     * values.
      */
-    void setNormalizeHybrid(bool n);
-    bool getNormalizeHybrid() const;
-    
     void setColourMap(int map);
     int getColourMap() const;
 
@@ -210,11 +198,15 @@
         return ColourHasMeaningfulValue;
     }
 
-    double getYForFrequency(const View *v, double frequency) const;
-    double getFrequencyForY(const View *v, int y) const;
+    double getYForFrequency(const LayerGeometryProvider *v, double frequency) const;
+    double getFrequencyForY(const LayerGeometryProvider *v, int y) const;
 
-    virtual int getCompletion(View *v) const;
-    virtual QString getError(View *v) const;
+    //!!! VerticalBinLayer methods. Note overlap with get*BinRange()
+    double getYForBin(const LayerGeometryProvider *, double bin) const;
+    double getBinForY(const LayerGeometryProvider *, double y) const;
+    
+    virtual int getCompletion(LayerGeometryProvider *v) const;
+    virtual QString getError(LayerGeometryProvider *v) const;
 
     virtual bool getValueExtents(double &min, double &max,
                                  bool &logarithmic, QString &unit) const;
@@ -223,16 +215,16 @@
 
     virtual bool setDisplayExtents(double min, double max);
 
-    virtual bool getYScaleValue(const View *, int, double &, QString &) const;
+    virtual bool getYScaleValue(const LayerGeometryProvider *, int, double &, QString &) const;
 
     virtual void toXml(QTextStream &stream, QString indent = "",
                        QString extraAttributes = "") const;
 
     void setProperties(const QXmlAttributes &attributes);
 
-    virtual void setLayerDormant(const View *v, bool dormant);
+    virtual void setLayerDormant(const LayerGeometryProvider *v, bool dormant);
 
-    virtual bool isLayerScrollable(const View *) const { return false; }
+    virtual bool isLayerScrollable(const LayerGeometryProvider *) const { return false; }
 
     virtual int getVerticalZoomSteps(int &defaultStep) const;
     virtual int getCurrentVerticalZoomStep() const;
@@ -247,118 +239,58 @@
     
     void preferenceChanged(PropertyContainer::PropertyName name);
 
-    void fillTimerTimedOut();
-
 protected:
     const DenseTimeValueModel *m_model; // I do not own this
 
     int                 m_channel;
-    int              m_windowSize;
+    int                 m_windowSize;
     WindowType          m_windowType;
-    int              m_windowHopLevel;
-    int              m_zeroPadLevel;
-    int              m_fftSize;
+    int                 m_windowHopLevel;
     float               m_gain;
     float               m_initialGain;
     float               m_threshold;
     float               m_initialThreshold;
     int                 m_colourRotation;
     int                 m_initialRotation;
-    int              m_minFrequency;
-    int              m_maxFrequency;
-    int              m_initialMaxFrequency;
-    ColourScale         m_colourScale;
+    int                 m_minFrequency;
+    int                 m_maxFrequency;
+    int                 m_initialMaxFrequency;
+    ColourScaleType     m_colourScale;
+    double              m_colourScaleMultiple;
     int                 m_colourMap;
     QColor              m_crosshairColour;
-    FrequencyScale      m_frequencyScale;
+    BinScale            m_binScale;
     BinDisplay          m_binDisplay;
-    bool                m_normalizeColumns;
+    ColumnNormalization m_normalization; // of individual columns
     bool                m_normalizeVisibleArea;
-    bool                m_normalizeHybrid;
     int                 m_lastEmittedZoomStep;
     bool                m_synchronous;
 
     mutable bool        m_haveDetailedScale;
-    mutable int         m_lastPaintBlockWidth;
-    mutable RealTime    m_lastPaintTime;
 
-    enum { NO_VALUE = 0 }; // colour index for unused pixels
+    static std::pair<ColourScaleType, double> convertToColourScale(int value);
+    static int convertFromColourScale(ColourScaleType type, double multiple);
+    static std::pair<ColumnNormalization, bool> convertToColumnNorm(int value);
+    static int convertFromColumnNorm(ColumnNormalization norm, bool visible);
 
-    class Palette
-    {
-    public:
-        QColor getColour(unsigned char index) const {
-            return m_colours[index];
-        }
-    
-        void setColour(unsigned char index, QColor colour) {
-            m_colours[index] = colour;
-        }
-
-    private:
-        QColor m_colours[256];
-    };
-
-    Palette m_palette;
-
-    /**
-     * ImageCache covers the area of the view, at view resolution.
-     * Not all of it is necessarily valid at once (it is refreshed
-     * in parts when scrolling, for example).
-     */
-    struct ImageCache
-    {
-        QImage image;
-        QRect validArea;
-        sv_frame_t startFrame;
-        int zoomLevel;
-    };
-    typedef std::map<const View *, ImageCache> ViewImageCache;
-    void invalidateImageCaches();
-    void invalidateImageCaches(sv_frame_t startFrame, sv_frame_t endFrame);
-    mutable ViewImageCache m_imageCaches;
-
-    /**
-     * When painting, we draw directly onto the draw buffer and then
-     * copy this to the part of the image cache that needed refreshing
-     * before copying the image cache onto the window.  (Remind me why
-     * we don't draw directly onto the cache?)
-     */
-    mutable QImage m_drawBuffer;
-
-    mutable QTimer *m_updateTimer;
-
-    mutable sv_frame_t m_candidateFillStartFrame;
     bool m_exiting;
 
-    void initialisePalette();
-    void rotatePalette(int distance);
-
-    unsigned char getDisplayValue(View *v, double input) const;
-
     int getColourScaleWidth(QPainter &) const;
 
-    void illuminateLocalFeatures(View *v, QPainter &painter) const;
+    void illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &painter) const;
 
     double getEffectiveMinFrequency() const;
     double getEffectiveMaxFrequency() const;
 
-    // Note that the getYBin... methods return the nominal bin in the
-    // un-smoothed spectrogram.  This is not necessarily the same bin
-    // as is pulled from the spectrogram and drawn at the given
-    // position, if the spectrogram has oversampling smoothing.  Use
-    // getSmoothedYBinRange to obtain that.
+    bool getXBinRange(LayerGeometryProvider *v, int x, double &windowMin, double &windowMax) const;
+    bool getYBinRange(LayerGeometryProvider *v, int y, double &freqBinMin, double &freqBinMax) const;
 
-    bool getXBinRange(View *v, int x, double &windowMin, double &windowMax) const;
-    bool getYBinRange(View *v, int y, double &freqBinMin, double &freqBinMax) const;
-    bool getSmoothedYBinRange(View *v, int y, double &freqBinMin, double &freqBinMax) const;
-
-    bool getYBinSourceRange(View *v, int y, double &freqMin, double &freqMax) const;
-    bool getAdjustedYBinSourceRange(View *v, int x, int y,
+    bool getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax) const;
+    bool getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y,
 				    double &freqMin, double &freqMax,
 				    double &adjFreqMin, double &adjFreqMax) const;
-    bool getXBinSourceRange(View *v, int x, RealTime &timeMin, RealTime &timeMax) const;
-    bool getXYBinSourceRange(View *v, int x, int y, double &min, double &max,
+    bool getXBinSourceRange(LayerGeometryProvider *v, int x, RealTime &timeMin, RealTime &timeMax) const;
+    bool getXYBinSourceRange(LayerGeometryProvider *v, int x, int y, double &min, double &max,
 			     double &phaseMin, double &phaseMax) const;
 
     int getWindowIncrement() const {
@@ -367,84 +299,39 @@
         else return m_windowSize / (1 << (m_windowHopLevel - 1));
     }
 
-    int getZeroPadLevel(const View *v) const;
-    int getFFTSize(const View *v) const;
-    FFTModel *getFFTModel(const View *v) const;
-    Dense3DModelPeakCache *getPeakCache(const View *v) const;
-    void invalidateFFTModels();
+    int getFFTOversampling() const;
+    int getFFTSize() const; // m_windowSize * getFFTOversampling()
 
-    typedef std::pair<FFTModel *, sv_frame_t> FFTFillPair; // model, last fill
-    typedef std::map<const View *, FFTFillPair> ViewFFTMap;
-    typedef std::map<const View *, Dense3DModelPeakCache *> PeakCacheMap;
-    mutable ViewFFTMap m_fftModels;
-    mutable PeakCacheMap m_peakCaches;
-    mutable Model *m_sliceableModel;
+    FFTModel *m_fftModel;
+    FFTModel *getFFTModel() const { return m_fftModel; }
+    Dense3DModelPeakCache *m_wholeCache;
+    Dense3DModelPeakCache *m_peakCache;
+    Dense3DModelPeakCache *getPeakCache() const { return m_peakCache; }
+    const int m_peakCacheDivisor;
+    bool canStoreWholeCache() const;
+    void recreateFFTModel();
 
-    class MagnitudeRange {
-    public:
-        MagnitudeRange() : m_min(0), m_max(0) { }
-        bool operator==(const MagnitudeRange &r) {
-            return r.m_min == m_min && r.m_max == m_max;
-        }
-        bool isSet() const { return (m_min != 0.f || m_max != 0.f); }
-        void set(float min, float max) {
-            m_min = min;
-            m_max = max;
-            if (m_max < m_min) m_max = m_min;
-        }
-        bool sample(float f) {
-            bool changed = false;
-            if (isSet()) {
-                if (f < m_min) { m_min = f; changed = true; }
-                if (f > m_max) { m_max = f; changed = true; }
-            } else {
-                m_max = m_min = f;
-                changed = true;
-            }
-            return changed;
-        }            
-        bool sample(const MagnitudeRange &r) {
-            bool changed = false;
-            if (isSet()) {
-                if (r.m_min < m_min) { m_min = r.m_min; changed = true; }
-                if (r.m_max > m_max) { m_max = r.m_max; changed = true; }
-            } else {
-                m_min = r.m_min;
-                m_max = r.m_max;
-                changed = true;
-            }
-            return changed;
-        }            
-        float getMin() const { return m_min; }
-        float getMax() const { return m_max; }
-    private:
-        float m_min;
-        float m_max;
-    };
+    typedef std::map<int, MagnitudeRange> ViewMagMap; // key is view id
+    mutable ViewMagMap m_viewMags;
+    mutable ViewMagMap m_lastRenderedMags; // when in normalizeVisibleArea mode
+    void invalidateMagnitudes();
 
-    typedef std::map<const View *, MagnitudeRange> ViewMagMap;
-    mutable ViewMagMap m_viewMags;
-    mutable std::vector<MagnitudeRange> m_columnMags;
-    void invalidateMagnitudes();
-    bool updateViewMagnitudes(View *v) const;
-    bool paintDrawBuffer(View *v, int w, int h,
-                         const std::vector<int> &binforx,
-                         const std::vector<double> &binfory,
-                         bool usePeaksCache,
-                         MagnitudeRange &overallMag,
-                         bool &overallMagChanged) const;
-    bool paintDrawBufferPeakFrequencies(View *v, int w, int h,
-                                        const std::vector<int> &binforx,
-                                        int minbin,
-                                        int maxbin,
-                                        double displayMinFreq,
-                                        double displayMaxFreq,
-                                        bool logarithmic,
-                                        MagnitudeRange &overallMag,
-                                        bool &overallMagChanged) const;
+    typedef std::map<int, Colour3DPlotRenderer *> ViewRendererMap; // key is view id
+    mutable ViewRendererMap m_renderers;
+    Colour3DPlotRenderer *getRenderer(LayerGeometryProvider *) const;
+    void invalidateRenderers();
+    
+    void paintWithRenderer(LayerGeometryProvider *v, QPainter &paint, QRect rect) const;
 
-    virtual void updateMeasureRectYCoords(View *v, const MeasureRect &r) const;
-    virtual void setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const;
+    void paintDetailedScale(LayerGeometryProvider *v,
+                            QPainter &paint, QRect rect) const;
+    void paintDetailedScalePhase(LayerGeometryProvider *v,
+                                 QPainter &paint, QRect rect) const;
+    
+    virtual void updateMeasureRectYCoords(LayerGeometryProvider *v,
+                                          const MeasureRect &r) const;
+    virtual void setMeasureRectYCoord(LayerGeometryProvider *v,
+                                      MeasureRect &r, bool start, int y) const;
 };
 
 #endif