Ref T731, adjusted CLevelMeter for "our needs"

* low/high color
* peak level
This commit is contained in:
Klaus Basan
2019-09-27 02:20:42 +02:00
committed by Mat Sutcliffe
parent 80a96d37fc
commit b5ad603e55
2 changed files with 68 additions and 84 deletions

View File

@@ -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<double>(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

View File

@@ -18,70 +18,70 @@
#include <QColor>
#include <QObject>
#include <QTime>
#include <QWidget>
#include <QFrame>
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