From bf8537f35000b8385ae806c15d8524c20f9c6fda Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Tue, 23 Aug 2016 22:18:46 +0200 Subject: [PATCH] Make min/max level of VUMeter and LRAMeter adjustable. --- lrameter.cpp | 27 ++++++++++++++++----------- lrameter.h | 21 +++++++++++++++++++++ vu_common.cpp | 21 ++++++++++----------- vu_common.h | 4 ++-- vumeter.cpp | 19 ++++++++++++------- vumeter.h | 21 +++++++++++++++++++++ 6 files changed, 82 insertions(+), 31 deletions(-) diff --git a/lrameter.cpp b/lrameter.cpp index f4395be..7b0f691 100644 --- a/lrameter.cpp +++ b/lrameter.cpp @@ -16,17 +16,7 @@ LRAMeter::LRAMeter(QWidget *parent) void LRAMeter::resizeEvent(QResizeEvent *event) { - const int margin = 5; - - on_pixmap = QPixmap(width(), height()); - QPainter on_painter(&on_pixmap); - on_painter.fillRect(0, 0, width(), height(), parentWidget()->palette().window()); - draw_vu_meter(on_painter, width(), height(), margin, true); - - off_pixmap = QPixmap(width(), height()); - QPainter off_painter(&off_pixmap); - off_painter.fillRect(0, 0, width(), height(), parentWidget()->palette().window()); - draw_vu_meter(off_painter, width(), height(), margin, false); + recalculate_pixmaps(); } void LRAMeter::paintEvent(QPaintEvent *event) @@ -101,3 +91,18 @@ void LRAMeter::paintEvent(QPaintEvent *event) painter.drawRect(2, y, width() - 5, 1); } } + +void LRAMeter::recalculate_pixmaps() +{ + const int margin = 5; + + on_pixmap = QPixmap(width(), height()); + QPainter on_painter(&on_pixmap); + on_painter.fillRect(0, 0, width(), height(), parentWidget()->palette().window()); + draw_vu_meter(on_painter, width(), height(), margin, true, min_level, max_level); + + off_pixmap = QPixmap(width(), height()); + QPainter off_painter(&off_pixmap); + off_painter.fillRect(0, 0, width(), height(), parentWidget()->palette().window()); + draw_vu_meter(off_painter, width(), height(), margin, false, min_level, max_level); +} diff --git a/lrameter.h b/lrameter.h index 03d872f..e2e63ad 100644 --- a/lrameter.h +++ b/lrameter.h @@ -7,6 +7,8 @@ #include #include +#include "vu_common.h" + class LRAMeter : public QWidget { Q_OBJECT @@ -22,14 +24,33 @@ public: QMetaObject::invokeMethod(this, "update", Qt::AutoConnection); } + double lufs_to_pos(float level_lu, int height) + { + return ::lufs_to_pos(level_lu, height, min_level, max_level); + } + + void set_min_level(float min_level) + { + this->min_level = min_level; + recalculate_pixmaps(); + } + + void set_max_level(float max_level) + { + this->max_level = max_level; + recalculate_pixmaps(); + } + private: void resizeEvent(QResizeEvent *event) override; void paintEvent(QPaintEvent *event) override; + void recalculate_pixmaps(); std::mutex level_mutex; float level_lufs = -HUGE_VAL; float range_low_lufs = -HUGE_VAL; float range_high_lufs = -HUGE_VAL; + float min_level = -18.0f, max_level = 9.0f; QPixmap on_pixmap, off_pixmap; }; diff --git a/vu_common.cpp b/vu_common.cpp index f1a0619..38aba4c 100644 --- a/vu_common.cpp +++ b/vu_common.cpp @@ -9,23 +9,22 @@ using namespace std; -double lufs_to_pos(float level_lu, int height) -{ - const float min_level = 9.0f; // y=0 is top of screen, so “min” is the loudest level. - const float max_level = -18.0f; +double lufs_to_pos(float level_lu, int height, float min_level, float max_level) +{ + // Note: “max” is the loudest level, but y=0 is top of screen. // Handle -inf. - if (level_lu < max_level) { + if (level_lu < min_level) { return height - 1; } - double y = height * (level_lu - min_level) / (max_level - min_level); + double y = height * (level_lu - max_level) / (min_level - max_level); y = max(y, 0); y = min(y, height - 1); // If we are big enough, snap to pixel grid instead of antialiasing // the edges; the unevenness will be less noticeable than the blurriness. - double height_per_level = height / (min_level - max_level) - 2.0; + double height_per_level = height / (max_level - min_level) - 2.0; if (height_per_level >= 10.0) { y = round(y); } @@ -33,16 +32,16 @@ double lufs_to_pos(float level_lu, int height) return y; } -void draw_vu_meter(QPainter &painter, int width, int height, int margin, bool is_on) +void draw_vu_meter(QPainter &painter, int width, int height, int margin, bool is_on, float min_level, float max_level) { painter.fillRect(margin, 0, width - 2 * margin, height, Qt::black); for (int y = 0; y < height; ++y) { // Find coverage of “on” rectangles in this pixel row. double coverage = 0.0; - for (int level = -18; level < 9; ++level) { - double min_y = lufs_to_pos(level + 1.0, height) + 1.0; - double max_y = lufs_to_pos(level, height) - 1.0; + for (int level = floor(min_level); level <= ceil(max_level); ++level) { + double min_y = lufs_to_pos(level + 1.0, height, min_level, max_level) + 1.0; + double max_y = lufs_to_pos(level, height, min_level, max_level) - 1.0; min_y = std::max(min_y, y); min_y = std::min(min_y, y + 1); max_y = std::max(max_y, y); diff --git a/vu_common.h b/vu_common.h index 118eed8..f065fcf 100644 --- a/vu_common.h +++ b/vu_common.h @@ -3,8 +3,8 @@ #include -double lufs_to_pos(float level_lu, int height); +double lufs_to_pos(float level_lu, int height, float min_level, float max_level); -void draw_vu_meter(QPainter &painter, int width, int height, int margin, bool is_on); +void draw_vu_meter(QPainter &painter, int width, int height, int margin, bool is_on, float min_level, float max_level); #endif // !defined(_VU_COMMON_H) diff --git a/vumeter.cpp b/vumeter.cpp index 15240b4..c08e9dc 100644 --- a/vumeter.cpp +++ b/vumeter.cpp @@ -12,13 +12,7 @@ VUMeter::VUMeter(QWidget *parent) void VUMeter::resizeEvent(QResizeEvent *event) { - on_pixmap = QPixmap(width(), height()); - QPainter on_painter(&on_pixmap); - draw_vu_meter(on_painter, width(), height(), 0, true); - - off_pixmap = QPixmap(width(), height()); - QPainter off_painter(&off_pixmap); - draw_vu_meter(off_painter, width(), height(), 0, false); + recalculate_pixmaps(); } void VUMeter::paintEvent(QPaintEvent *event) @@ -39,3 +33,14 @@ void VUMeter::paintEvent(QPaintEvent *event) painter.drawPixmap(off_rect, off_pixmap, off_rect); painter.drawPixmap(on_rect, on_pixmap, on_rect); } + +void VUMeter::recalculate_pixmaps() +{ + on_pixmap = QPixmap(width(), height()); + QPainter on_painter(&on_pixmap); + draw_vu_meter(on_painter, width(), height(), 0, true, min_level, max_level); + + off_pixmap = QPixmap(width(), height()); + QPainter off_painter(&off_pixmap); + draw_vu_meter(off_painter, width(), height(), 0, false, min_level, max_level); +} diff --git a/vumeter.h b/vumeter.h index 7015091..33f8df1 100644 --- a/vumeter.h +++ b/vumeter.h @@ -7,6 +7,8 @@ #include #include +#include "vu_common.h" + class VUMeter : public QWidget { Q_OBJECT @@ -20,12 +22,31 @@ public: QMetaObject::invokeMethod(this, "update", Qt::AutoConnection); } + double lufs_to_pos(float level_lu, int height) + { + return ::lufs_to_pos(level_lu, height, min_level, max_level); + } + + void set_min_level(float min_level) + { + this->min_level = min_level; + recalculate_pixmaps(); + } + + void set_max_level(float max_level) + { + this->max_level = max_level; + recalculate_pixmaps(); + } + private: void resizeEvent(QResizeEvent *event) override; void paintEvent(QPaintEvent *event) override; + void recalculate_pixmaps(); std::mutex level_mutex; float level_lufs = -HUGE_VAL; + float min_level = -18.0f, max_level = 9.0f; QPixmap on_pixmap, off_pixmap; }; -- 2.39.2