diff --git a/src/blackgui/levelmeter.cpp b/src/blackgui/levelmeter.cpp index 0a51990e6..9ca2c010a 100644 --- a/src/blackgui/levelmeter.cpp +++ b/src/blackgui/levelmeter.cpp @@ -21,16 +21,16 @@ namespace BlackGui { CLevelMeter::CLevelMeter(QWidget *parent) - : QWidget(parent) - , m_peakDecayRate(PeakDecayRate) - , m_redrawTimer(new QTimer(this)) - , m_rmsColor(Qt::red) - , m_peakColor(255, 200, 200, 255) + : QFrame(parent), + m_redrawTimer(new QTimer(this)), + m_lowColor(Qt::gray), + m_highColor(Qt::green), + m_peakColor(255, 200, 200, 255) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); - setMinimumWidth(30); + this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + this->setMinimumWidth(30); - connect(m_redrawTimer, &QTimer::timeout, this, &CLevelMeter::ps_redrawTimerExpired); + connect(m_redrawTimer, &QTimer::timeout, this, &CLevelMeter::redrawTimerExpired); m_redrawTimer->start(RedrawInterval); m_redrawTimer->setObjectName("CLevelMeter"); } @@ -40,52 +40,33 @@ namespace BlackGui void CLevelMeter::reset() { - m_rmsLevel = 0.0; + m_level = 0.0; m_peakLevel = 0.0; - update(); + this->update(); } - void CLevelMeter::levelChanged(double rmsLevel, double peakLevel, int numSamples) + void CLevelMeter::levelChanged(double level) { - // Smooth the RMS signal - const double smooth = pow(double(0.9), static_cast(numSamples) / 256); // TODO: remove this magic number - m_rmsLevel = (m_rmsLevel * smooth) + (rmsLevel * (1.0 - smooth)); - - if (peakLevel > m_decayedPeakLevel) + m_level = level; + if (level > m_peakLevel) { - m_peakLevel = peakLevel; - m_decayedPeakLevel = peakLevel; + m_peakLevel = level; m_peakLevelChanged.start(); } - - if (peakLevel > m_peakHoldLevel) - { - m_peakHoldLevel = peakLevel; - m_peakHoldLevelChanged.start(); - } - - update(); } - void CLevelMeter::ps_redrawTimerExpired() + void CLevelMeter::redrawTimerExpired() { - // Decay the peak signal - const int elapsedMs = m_peakLevelChanged.elapsed(); - const double decayAmount = m_peakDecayRate * elapsedMs; - if (decayAmount < m_peakLevel) + // decay + if (m_peakLevelChanged.elapsed() > PeakHoldLevelDuration) { - m_decayedPeakLevel = m_peakLevel - decayAmount; + m_peakLevel -= DecayValue; + if (m_peakLevel < m_level || m_peakLevel < 0) + { + m_peakLevel = 0.0; + } } - else - { - m_decayedPeakLevel = 0.0; - } - - // Check whether to clear the peak hold level - if (m_peakHoldLevelChanged.elapsed() > PeakHoldLevelDuration) - m_peakHoldLevel = 0.0; - - update(); + this->update(); } void CLevelMeter::paintEvent(QPaintEvent *event) @@ -93,20 +74,23 @@ namespace BlackGui Q_UNUSED(event) QPainter painter(this); - painter.fillRect(rect(), Qt::black); + QRect bar = this->contentsRect(); + painter.fillRect(bar, Qt::transparent); + const int w = bar.width(); + const int left = rect().left(); + const int level = qRound(m_level * w); - QRect bar = rect(); + bar.setLeft(left); + bar.setRight(level); + painter.fillRect(bar, m_peakLevel >= High ? m_highColor : m_lowColor); - bar.setTop(rect().top() + (1.0 - m_peakHoldLevel) * rect().height()); - bar.setBottom(bar.top() + 5); - painter.fillRect(bar, m_rmsColor); - bar.setBottom(rect().bottom()); - - bar.setTop(rect().top() + (1.0 - m_decayedPeakLevel) * rect().height()); - painter.fillRect(bar, m_peakColor); - - bar.setTop(rect().top() + (1.0 - m_rmsLevel) * rect().height()); - painter.fillRect(bar, m_rmsColor); + if (m_peakLevel > m_level) + { + const int peak = qRound(m_peakLevel * w); + bar.setLeft(level); + bar.setRight(peak); + painter.fillRect(bar, m_peakColor); + } } } // namespace diff --git a/src/blackgui/levelmeter.h b/src/blackgui/levelmeter.h index 6d2c84ceb..f6bd1e908 100644 --- a/src/blackgui/levelmeter.h +++ b/src/blackgui/levelmeter.h @@ -18,70 +18,70 @@ #include #include #include -#include +#include class QPaintEvent; class QTimer; namespace BlackGui { - //! Widget which displays a vertical audio level meter, indicating the - //! RMS and peak levels of the window of audio samples most recently analyzed - //! by the Engine. - class BLACKGUI_EXPORT CLevelMeter : public QWidget + //! Widget which displays a audio level meter, indicating the + //! level and peak levels of the window of audio samples most recently analyzed + class BLACKGUI_EXPORT CLevelMeter : public QFrame { Q_OBJECT + Q_PROPERTY(QColor lowColor READ getLowColor WRITE setLowColor) + Q_PROPERTY(QColor highColor READ getHighColor WRITE setHighColor) + Q_PROPERTY(QColor peakColor READ getPeakColor WRITE setPeakColor) + public: //! Constructor CLevelMeter(QWidget *parent = nullptr); //! Destructor - virtual ~CLevelMeter(); + virtual ~CLevelMeter() override; //! \copydoc QWidget::paintEvent void paintEvent(QPaintEvent *event) override; - public slots: //! Clean up void reset(); //! Values - void levelChanged(double rmsLevel, double peakLevel, int numSamples); + void levelChanged(double level); - private slots: - void ps_redrawTimerExpired(); + //! Color properties @{ + const QColor &getLowColor() const { return m_lowColor; } + const QColor &getHighColor() const { return m_highColor; } + const QColor &getPeakColor() const { return m_peakColor; } + void setLowColor(const QColor &color) { m_lowColor = color; } + void setHighColor(const QColor &color) { m_highColor = color; } + void setPeakColor(const QColor &color) { m_peakColor = color; } + //! @} private: - const int RedrawInterval = 100; // ms - const double PeakDecayRate = 0.001; - const int PeakHoldLevelDuration = 2000; // ms + //! Timer expired + void redrawTimerExpired(); - //! Height of RMS level bar, range 0.0 - 1.0. - double m_rmsLevel = 0.0; + const int RedrawInterval = 100; // ms + const int PeakHoldLevelDuration = 1000; // ms + + //! Range 0.0 - 1.0. + double m_level = 0.0; //! Most recent peak level, range 0.0 - 1.0. double m_peakLevel = 0.0; - //! Height of peak level bar. - //! This is calculated by decaying m_peakLevel depending on the elapsed time since m_peakLevelChanged, and the value of m_decayRate. - double m_decayedPeakLevel = 0.0; - //! Time at which m_peakLevel was last changed. QTime m_peakLevelChanged; - //! Rate at which peak level bar decays. Expressed in level units / millisecond. - double m_peakDecayRate; - - //! High watermark of peak level. Range 0.0 - 1.0. - double m_peakHoldLevel = 0.0; - - //! Time at which m_peakHoldLevel was last changed. - QTime m_peakHoldLevelChanged; - + static constexpr double High = 0.60; + static constexpr double DecayValue = 0.10; QTimer *m_redrawTimer = nullptr; - QColor m_rmsColor; + QColor m_lowColor; + QColor m_highColor; QColor m_peakColor; }; -} +} // ns #endif // guard