]> git.sesse.net Git - nageru/blob - compression_reduction_meter.cpp
Release Nageru 1.7.2.
[nageru] / compression_reduction_meter.cpp
1 #include "compression_reduction_meter.h"
2
3 #include <QPainter>
4 #include <QRect>
5 #include "piecewise_interpolator.h"
6 #include "vu_common.h"
7
8 class QPaintEvent;
9 class QResizeEvent;
10
11 using namespace std;
12
13 namespace {
14
15 vector<PiecewiseInterpolator::ControlPoint> control_points = {
16         { 60.0f, 6.0f },
17         { 30.0f, 5.0f },
18         { 18.0f, 4.0f },
19         { 12.0f, 3.0f },
20         { 6.0f, 2.0f },
21         { 3.0f, 1.0f },
22         { 0.0f, 0.0f }
23 };
24 PiecewiseInterpolator interpolator(control_points);
25
26 }  // namespace
27
28 CompressionReductionMeter::CompressionReductionMeter(QWidget *parent)
29         : QWidget(parent)
30 {
31 }
32
33 void CompressionReductionMeter::resizeEvent(QResizeEvent *event)
34 {
35         recalculate_pixmaps();
36 }
37
38 void CompressionReductionMeter::paintEvent(QPaintEvent *event)
39 {
40         QPainter painter(this);
41
42         float level_db;
43         {
44                 unique_lock<mutex> lock(level_mutex);
45                 level_db = this->level_db;
46         }
47
48         int on_pos = lrint(db_to_pos(level_db));
49
50         QRect on_rect(0, 0, width(), on_pos);
51         QRect off_rect(0, on_pos, width(), height());
52
53         painter.drawPixmap(on_rect, on_pixmap, on_rect);
54         painter.drawPixmap(off_rect, off_pixmap, off_rect);
55 }
56
57 void CompressionReductionMeter::recalculate_pixmaps()
58 {
59         constexpr int y_offset = text_box_height / 2;
60         constexpr int text_margin = 5;
61         float margin = 0.5 * (width() - meter_width);
62
63         on_pixmap = QPixmap(width(), height());
64         QPainter on_painter(&on_pixmap);
65         on_painter.fillRect(0, 0, width(), height(), parentWidget()->palette().window());
66         draw_vu_meter(on_painter, width(), meter_height(), margin, 2.0, true, min_level, max_level, /*flip=*/true, y_offset);
67         draw_scale(&on_painter, 0.5 * width() + 0.5 * meter_width + text_margin);
68
69         off_pixmap = QPixmap(width(), height());
70         QPainter off_painter(&off_pixmap);
71         off_painter.fillRect(0, 0, width(), height(), parentWidget()->palette().window());
72         draw_vu_meter(off_painter, width(), meter_height(), margin, 2.0, false, min_level, max_level, /*flip=*/true, y_offset);
73         draw_scale(&off_painter, 0.5 * width() + 0.5 * meter_width + text_margin);
74 }
75
76 void CompressionReductionMeter::draw_scale(QPainter *painter, int x_pos)
77 {
78         QFont font;
79         font.setPointSize(8);
80         painter->setPen(Qt::black);
81         painter->setFont(font);
82         for (size_t i = 0; i < control_points.size(); ++i) {
83                 char buf[256];
84                 snprintf(buf, 256, "%.0f", control_points[i].db_value);
85                 double y = db_to_pos(control_points[i].db_value);
86                 painter->drawText(QRect(x_pos, y - text_box_height / 2, text_box_width, text_box_height),
87                         Qt::AlignCenter | Qt::AlignVCenter, buf);
88         }
89 }
90
91 double CompressionReductionMeter::db_to_pos(double level_db) const
92 {
93         float value = interpolator.db_to_fraction(level_db);
94         return height() - lufs_to_pos(value, meter_height(), min_level, max_level) - text_box_height / 2;
95 }
96
97 int CompressionReductionMeter::meter_height() const
98 {
99         return height() - text_box_height;
100 }