Mercurial > hg > svgui
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