Chris@58: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@0: A waveform viewer and audio annotation editor. Chris@5: Chris Cannam, Queen Mary University of London, 2005-2006 Chris@0: Chris@0: This is experimental software. Not for distribution. Chris@0: */ Chris@0: Chris@30: #ifndef _WAVEFORM_LAYER_H_ Chris@30: #define _WAVEFORM_LAYER_H_ Chris@0: Chris@0: #include Chris@0: #include Chris@0: Chris@0: #include "base/Layer.h" Chris@0: Chris@0: #include "model/RangeSummarisableTimeValueModel.h" Chris@0: Chris@0: class View; Chris@0: class QPainter; Chris@0: class QPixmap; Chris@0: Chris@0: class WaveformLayer : public Layer Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: public: Chris@44: WaveformLayer(); Chris@0: ~WaveformLayer(); Chris@0: Chris@0: virtual const ZoomConstraint *getZoomConstraint() const { return m_model; } Chris@0: virtual const Model *getModel() const { return m_model; } Chris@44: virtual void paint(View *v, QPainter &paint, QRect rect) const; Chris@0: Chris@44: virtual QString getFeatureDescription(View *v, QPoint &) const; Chris@25: Chris@44: virtual int getVerticalScaleWidth(View *v, QPainter &) const; Chris@44: virtual void paintVerticalScale(View *v, QPainter &paint, QRect rect) const; Chris@0: Chris@0: void setModel(const RangeSummarisableTimeValueModel *model); Chris@0: Chris@0: virtual PropertyList getProperties() const; Chris@0: virtual PropertyType getPropertyType(const PropertyName &) const; Chris@0: virtual QString getPropertyGroupName(const PropertyName &) const; Chris@0: virtual int getPropertyRangeAndValue(const PropertyName &, Chris@0: int *min, int *max) const; Chris@0: virtual QString getPropertyValueLabel(const PropertyName &, Chris@0: int value) const; Chris@0: virtual void setProperty(const PropertyName &, int value); Chris@0: Chris@0: /** Chris@0: * Set the gain multiplier for sample values in this view. Chris@0: * Chris@0: * The default is 1.0. Chris@0: */ Chris@0: void setGain(float gain); Chris@0: float getGain() const { return m_gain; } Chris@0: Chris@0: /** Chris@0: * Set the basic display colour for waveforms. Chris@0: * Chris@0: * The default is black. Chris@0: *!!! NB should default to white if the associated View !hasLightBackground() Chris@0: */ Chris@0: void setBaseColour(QColor); Chris@0: QColor getBaseColour() const { return m_colour; } Chris@0: Chris@0: /** Chris@0: * Set whether to display mean values as a lighter-coloured area Chris@0: * beneath the peaks. Rendering will be slightly faster without Chris@0: * but arguably prettier with. Chris@0: * Chris@0: * The default is to display means. Chris@0: */ Chris@0: void setShowMeans(bool); Chris@0: bool getShowMeans() const { return m_showMeans; } Chris@0: Chris@0: /** Chris@0: * Set whether to use shades of grey (or of the base colour) to Chris@0: * provide additional perceived vertical resolution (i.e. using Chris@0: * half-filled pixels to represent levels that only just meet the Chris@0: * pixel unit boundary). This provides a small improvement in Chris@0: * waveform quality at a small cost in rendering speed. Chris@0: * Chris@0: * The default is to use greyscale. Chris@0: */ Chris@0: void setUseGreyscale(bool); Chris@0: bool getUseGreyscale() const { return m_greyscale; } Chris@0: Chris@0: Chris@0: enum ChannelMode { SeparateChannels, MergeChannels }; Chris@0: Chris@0: /** Chris@0: * Specify whether multi-channel audio data should be displayed Chris@0: * with a separate axis per channel (SeparateChannels), or with a Chris@0: * single synthetic axis showing channel 0 above the axis and Chris@0: * channel 1 below (MergeChannels). Chris@0: * Chris@0: * MergeChannels does not work for files with more than 2 Chris@0: * channels. Chris@0: * Chris@0: * The default is SeparateChannels. Chris@0: */ Chris@0: void setChannelMode(ChannelMode); Chris@0: ChannelMode getChannelMode() const { return m_channelMode; } Chris@0: Chris@0: Chris@0: /** Chris@0: * Specify the channel to use from the source model. A value of Chris@0: * -1 means to show all available channels (laid out to the Chris@0: * channel mode). The default is -1. Chris@0: */ Chris@0: void setChannel(int); Chris@0: int getChannel() const { return m_channel; } Chris@0: Chris@0: Chris@0: enum Scale { LinearScale, MeterScale, dBScale }; Chris@0: Chris@0: /** Chris@0: * Specify the vertical scale for sample levels. With LinearScale, Chris@0: * the scale is directly proportional to the raw [-1, +1) Chris@0: * floating-point audio sample values. With dBScale the Chris@0: * vertical scale is proportional to dB level (truncated at Chris@0: * -50dB). MeterScale provides a hybrid variable scale based on Chris@0: * IEC meter scale, intended to provide a clear overview at Chris@0: * relatively small heights. Chris@0: * Chris@0: * Note that the effective gain (see setGain()) is applied before Chris@0: * vertical scaling. Chris@0: * Chris@0: * The default is LinearScale. Chris@0: */ Chris@0: void setScale(Scale); Chris@0: Scale getScale() const { return m_scale; } Chris@0: Chris@0: /** Chris@0: * Enable or disable aggressive pixmap cacheing. If enabled, Chris@0: * waveforms will be rendered to an off-screen pixmap and Chris@0: * refreshed from there instead of being redrawn from the peak Chris@0: * data each time. This may be faster if the data and zoom level Chris@0: * do not change often, but it may be slower for frequently zoomed Chris@0: * data and it will only work if the waveform is the "bottom" Chris@0: * layer on the displayed widget, as each refresh will erase Chris@0: * anything beneath the waveform. Chris@0: * Chris@0: * This is intended specifically for a panner widget display in Chris@0: * which the waveform never moves, zooms, or changes, but some Chris@0: * graphic such as a panner outline is frequently redrawn over the Chris@0: * waveform. This situation would necessitate a lot of waveform Chris@0: * refresh if the default cacheing strategy was used. Chris@0: * Chris@0: * The default is not to use aggressive cacheing. Chris@0: */ Chris@0: void setAggressiveCacheing(bool); Chris@0: bool getAggressiveCacheing() const { return m_aggressive; } Chris@0: Chris@0: virtual int getCompletion() const; Chris@0: Chris@6: virtual QString toXmlString(QString indent = "", Chris@6: QString extraAttributes = "") const; Chris@6: Chris@11: void setProperties(const QXmlAttributes &attributes); Chris@11: Chris@0: protected: Chris@0: int dBscale(float sample, int m) const; Chris@0: Chris@0: const RangeSummarisableTimeValueModel *m_model; // I do not own this Chris@0: Chris@0: /// Return value is number of channels displayed Chris@0: size_t getChannelArrangement(size_t &min, size_t &max, bool &merging) const; Chris@0: Chris@6: float m_gain; Chris@6: QColor m_colour; Chris@6: bool m_showMeans; Chris@6: bool m_greyscale; Chris@6: ChannelMode m_channelMode; Chris@6: int m_channel; Chris@6: Scale m_scale; Chris@6: bool m_aggressive; Chris@0: Chris@0: mutable QPixmap *m_cache; Chris@0: mutable bool m_cacheValid; Chris@0: mutable int m_cacheZoomLevel; Chris@0: }; Chris@0: Chris@0: #endif