Chris@58: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@59: Sonic Visualiser Chris@59: An audio file viewer and annotation editor. Chris@59: Centre for Digital Music, Queen Mary, University of London. Chris@182: This file copyright 2006 Chris Cannam and QMUL. Chris@0: Chris@59: This program is free software; you can redistribute it and/or Chris@59: modify it under the terms of the GNU General Public License as Chris@59: published by the Free Software Foundation; either version 2 of the Chris@59: License, or (at your option) any later version. See the file Chris@59: COPYING included with this distribution for more information. Chris@0: */ Chris@0: Chris@1407: #ifndef SV_WAVEFORM_LAYER_H Chris@1407: #define SV_WAVEFORM_LAYER_H Chris@0: Chris@0: #include Chris@0: Chris@287: #include "SingleColourLayer.h" Chris@0: Chris@1375: #include "base/ZoomLevel.h" Chris@1375: Chris@128: #include "data/model/RangeSummarisableTimeValueModel.h" Chris@0: Chris@0: class View; Chris@0: class QPainter; Chris@0: class QPixmap; Chris@0: Chris@287: class WaveformLayer : public SingleColourLayer Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: public: Chris@44: WaveformLayer(); Chris@0: ~WaveformLayer(); Chris@0: Chris@1470: const ZoomConstraint *getZoomConstraint() const override; Chris@1470: ModelId getModel() const override { return m_model; } Chris@1406: void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override; Chris@0: Chris@1406: QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const override; Chris@25: Chris@1406: ColourSignificance getLayerColourSignificance() const override { Chris@287: return ColourAndBackgroundSignificant; Chris@287: } Chris@287: Chris@1406: int getVerticalScaleWidth(LayerGeometryProvider *v, bool detailed, QPainter &) const override; Chris@1406: void paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const override; Chris@0: Chris@1470: void setModel(ModelId model); // a RangeSummarisableTimeValueModel Chris@0: Chris@1406: PropertyList getProperties() const override; Chris@1406: QString getPropertyLabel(const PropertyName &) const override; Chris@1406: QString getPropertyIconName(const PropertyName &) const override; Chris@1406: PropertyType getPropertyType(const PropertyName &) const override; Chris@1406: QString getPropertyGroupName(const PropertyName &) const override; Chris@1406: int getPropertyRangeAndValue(const PropertyName &, Chris@1406: int *min, int *max, int *deflt) const override; Chris@1406: QString getPropertyValueLabel(const PropertyName &, Chris@1406: int value) const override; Chris@1406: RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const override; Chris@1406: void setProperty(const PropertyName &, int value) override; 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@67: * Toggle automatic normalization of the currently visible waveform. Chris@67: */ Chris@67: void setAutoNormalize(bool); Chris@67: bool getAutoNormalize() const { return m_autoNormalize; } Chris@67: Chris@67: /** 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@67: enum ChannelMode { SeparateChannels, MixChannels, MergeChannels }; Chris@0: Chris@0: /** Chris@0: * Specify whether multi-channel audio data should be displayed Chris@67: * with a separate axis per channel (SeparateChannels), with a Chris@0: * single synthetic axis showing channel 0 above the axis and Chris@67: * channel 1 below (MergeChannels), or with a single axis showing Chris@67: * the average of the channels (MixChannels). 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@709: * Specify the height of the middle of the waveform track or Chris@709: * tracks within the layer, from 0.0 to 1.0. Chris@709: * Chris@709: * A value of 0.0 would indicate that the waveform occupies Chris@709: * effectively no space at the very top of the layer; 1.0 would Chris@709: * indicate that the waveform occupies no space at the very Chris@709: * bottom; the default value of 0.5 indicates that it occupies the Chris@709: * whole layer, centred at the middle. Chris@709: */ Chris@905: void setMiddleLineHeight(double); Chris@905: double getMiddleLineHeight() const { return m_middleLineHeight; } Chris@709: Chris@709: /** 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@1406: bool isLayerScrollable(const LayerGeometryProvider *) const override; Chris@67: Chris@1406: int getCompletion(LayerGeometryProvider *) const override; Chris@0: Chris@1406: bool getValueExtents(double &min, double &max, Chris@1406: bool &log, QString &unit) const override; Chris@79: Chris@1542: bool getDisplayExtents(double & min, double &max) const override; Chris@1542: Chris@1406: bool getYScaleValue(const LayerGeometryProvider *v, int y, Chris@1406: double &value, QString &unit) const override; Chris@274: Chris@1406: bool getYScaleDifference(const LayerGeometryProvider *v, int y0, int y1, Chris@1406: double &diff, QString &unit) const override; Chris@261: Chris@1406: void toXml(QTextStream &stream, QString indent = "", Chris@1406: QString extraAttributes = "") const override; Chris@6: Chris@1406: void setProperties(const QXmlAttributes &attributes) override; Chris@11: Chris@1406: int getVerticalZoomSteps(int &defaultStep) const override; Chris@1406: int getCurrentVerticalZoomStep() const override; Chris@1406: void setVerticalZoomStep(int) override; Chris@133: Chris@1406: bool canExistWithoutModel() const override { return true; } Chris@947: Chris@0: protected: Chris@1367: double dBscale(double sample, int m) const; Chris@0: Chris@1470: ModelId m_model; Chris@0: Chris@1338: typedef std::vector RangeVec; Chris@1338: Chris@0: /// Return value is number of channels displayed Chris@805: int getChannelArrangement(int &min, int &max, Chris@1332: bool &merging, bool &mixing) const; Chris@0: Chris@1338: void paintChannel Chris@1336: (LayerGeometryProvider *, QPainter *paint, QRect rect, int channel, Chris@1338: const RangeVec &ranges, Chris@1336: int blockSize, sv_frame_t frame0, sv_frame_t frame1) const; Chris@1336: Chris@1335: void paintChannelScaleGuides(LayerGeometryProvider *, QPainter *paint, Chris@1335: QRect rect, int channel) const; Chris@1338: Chris@1338: void getSummaryRanges(int minChannel, int maxChannel, Chris@1338: bool mixingOrMerging, Chris@1338: sv_frame_t f0, sv_frame_t f1, Chris@1338: int blockSize, RangeVec &ranges) const; Chris@1338: Chris@1338: void getOversampledRanges(int minChannel, int maxChannel, Chris@1338: bool mixingOrMerging, Chris@1338: sv_frame_t f0, sv_frame_t f1, Chris@1338: int oversampleBy, RangeVec &ranges) const; Chris@1332: Chris@918: int getYForValue(const LayerGeometryProvider *v, double value, int channel) const; Chris@68: Chris@918: double getValueForY(const LayerGeometryProvider *v, int y, int &channel) const; Chris@261: Chris@918: bool getSourceFramesForX(LayerGeometryProvider *v, int x, int modelZoomLevel, Chris@908: sv_frame_t &f0, sv_frame_t &f1) const; Chris@365: Chris@918: float getNormalizeGain(LayerGeometryProvider *v, int channel) const; Chris@365: Chris@1406: void flagBaseColourChanged() override { m_cacheValid = false; } Chris@287: Chris@6: float m_gain; Chris@67: bool m_autoNormalize; Chris@6: bool m_showMeans; Chris@6: ChannelMode m_channelMode; Chris@6: int m_channel; Chris@1542: int m_channelCount; Chris@6: Scale m_scale; Chris@905: double m_middleLineHeight; Chris@6: bool m_aggressive; Chris@0: Chris@1542: static double m_dBMin; Chris@1542: Chris@67: mutable std::vector m_effectiveGains; Chris@67: Chris@0: mutable QPixmap *m_cache; Chris@0: mutable bool m_cacheValid; Chris@1325: mutable ZoomLevel m_cacheZoomLevel; Chris@0: }; Chris@0: Chris@0: #endif