Mercurial > hg > svgui
diff layer/SpectrogramLayer.h @ 0:2a4f26e85b4c
initial import
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 16:33:16 +0000 |
parents | |
children | ab83c415a6cd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/SpectrogramLayer.h Tue Jan 10 16:33:16 2006 +0000 @@ -0,0 +1,215 @@ +/* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ + +/* + A waveform viewer and audio annotation editor. + Chris Cannam, Queen Mary University of London, 2005 + + This is experimental software. Not for distribution. +*/ + +#ifndef _SPECTROGRAM_VIEW_H_ +#define _SPECTROGRAM_VIEW_H_ + +#include "base/Layer.h" +#include "base/Window.h" +#include "model/PowerOfSqrtTwoZoomConstraint.h" +#include "model/DenseTimeValueModel.h" + +#include <QThread> +#include <QMutex> +#include <QWaitCondition> + +#include <fftw3.h> + +class View; +class QPainter; +class QImage; +class QPixmap; +class QTimer; +class RealTime; + +/** + * SpectrogramLayer represents waveform data (obtained from a + * DenseTimeValueModel) in spectrogram form. + */ + +class SpectrogramLayer : public Layer, + public PowerOfSqrtTwoZoomConstraint +{ + Q_OBJECT + +public: + enum Configuration { FullRangeDb, MelodicRange }; + + SpectrogramLayer(View *w, Configuration = FullRangeDb); + ~SpectrogramLayer(); + + virtual const ZoomConstraint *getZoomConstraint() const { return this; } + virtual const Model *getModel() const { return m_model; } + virtual void paint(QPainter &paint, QRect rect) const; + + virtual int getVerticalScaleWidth(QPainter &) const; + virtual void paintVerticalScale(QPainter &paint, QRect rect) const; + + virtual QRect getFeatureDescriptionRect(QPainter &, QPoint) const; + virtual void paintLocalFeatureDescription(QPainter &, QRect, QPoint) const; + + void setModel(const DenseTimeValueModel *model); + + virtual PropertyList getProperties() const; + virtual PropertyType getPropertyType(const PropertyName &) const; + virtual QString getPropertyGroupName(const PropertyName &) const; + virtual int getPropertyRangeAndValue(const PropertyName &, + int *min, int *max) const; + virtual QString getPropertyValueLabel(const PropertyName &, + int value) const; + virtual void setProperty(const PropertyName &, int value); + + /** + * Specify the channel to use from the source model. + * A value of -1 means to mix all available channels. + * The default is channel 0. + */ + void setChannel(int); + int getChannel() const; + + void setWindowSize(size_t); + size_t getWindowSize() const; + + void setWindowOverlap(size_t percent); + size_t getWindowOverlap() const; + + void setWindowType(WindowType type); + WindowType getWindowType() const; + + /** + * Set the gain multiplier for sample values in this view prior to + * FFT calculation. + * + * The default is 1.0. + */ + void setGain(float gain); + float getGain() const; + + void setMaxFrequency(size_t); // 0 -> no maximum + size_t getMaxFrequency() const; + + enum ColourScale { LinearColourScale, MeterColourScale, dBColourScale, + PhaseColourScale }; + + /** + * Specify the scale for sample levels. See WaveformLayer for + * details of meter and dB scaling. The default is dBColourScale. + */ + void setColourScale(ColourScale); + ColourScale getColourScale() const; + + enum FrequencyScale { LinearFrequencyScale, LogFrequencyScale }; + + /** + * Specify the scale for the y axis. + */ + void setFrequencyScale(FrequencyScale); + FrequencyScale getFrequencyScale() const; + + enum ColourScheme { DefaultColours, WhiteOnBlack, BlackOnWhite, + RedOnBlue, YellowOnBlack, RedOnBlack }; + + void setColourScheme(ColourScheme scheme); + ColourScheme getColourScheme() const; + + virtual VerticalPosition getPreferredFrameCountPosition() const { + return PositionTop; + } + + virtual int getCompletion() const; + + virtual QString getPropertyContainerIconName() const { return "spectrogram"; } + +protected slots: + void cacheInvalid(); + void cacheInvalid(size_t startFrame, size_t endFrame); + + void fillTimerTimedOut(); + +protected: + const DenseTimeValueModel *m_model; // I do not own this + + int m_channel; + size_t m_windowSize; + WindowType m_windowType; + size_t m_windowOverlap; + float m_gain; + size_t m_maxFrequency; + ColourScale m_colourScale; + ColourScheme m_colourScheme; + FrequencyScale m_frequencyScale; + + class CacheFillThread : public QThread + { + public: + CacheFillThread(SpectrogramLayer &layer) : + m_layer(layer), m_fillExtent(0) { } + + size_t getFillExtent() const { return m_fillExtent; } + size_t getFillCompletion() const { return m_fillCompletion; } + virtual void run(); + + protected: + SpectrogramLayer &m_layer; + size_t m_fillExtent; + size_t m_fillCompletion; + }; + + void fillCache(); + + QImage *m_cache; + bool m_cacheInvalid; + size_t m_maxCachedFrequency; + + mutable QPixmap *m_pixmapCache; + mutable bool m_pixmapCacheInvalid; + mutable long m_pixmapCacheStartFrame; + mutable size_t m_pixmapCacheZoomLevel; + + QWaitCondition m_condition; + mutable QMutex m_mutex; + + CacheFillThread *m_fillThread; + QTimer *m_updateTimer; + size_t m_lastFillExtent; + bool m_cachedInitialVisibleArea; + bool m_exiting; + + void setCacheColourmap(); + + bool fillCacheColumn(int column, + double *inputBuffer, + fftw_complex *outputBuffer, + fftw_plan plan, + const Window<double> &windower, + bool lock) + const; + + bool getYBinRange(int y, float &freqBinMin, float &freqBinMax) const; + + struct LayerRange { + long startFrame; + int zoomLevel; + size_t modelStart; + size_t modelEnd; + }; + /// LayerRange is only passed in to save lookup time + bool getXBinRange(int x, float &windowMin, float &windowMax, + LayerRange *range = 0) const; + + bool getYBinSourceRange(int y, float &freqMin, float &freqMax) const; + bool getXBinSourceRange(int x, RealTime &timeMin, RealTime &timeMax) const; + bool getXYBinSourceRange(int x, int y, float &dbMin, float &dbMax) const; + + size_t getWindowIncrement() const { + return m_windowSize - m_windowSize * m_windowOverlap / 100; + } +}; + +#endif