1 #include "nonlinear_fader.h"
5 #include <QAbstractSlider>
6 #include <QPaintDevice>
12 #include <QStyleOption>
15 #include "piecewise_interpolator.h"
24 PiecewiseInterpolator interpolator({
25 // The main area is from +6 to -12 dB (18 dB), and we use half the slider range for it.
26 // Adjust slightly so that the MIDI controller value of 106 becomes exactly 0.0 dB
27 // (cf. map_controller_to_float()); otherwise, we'd miss ever so slightly, which is
28 // really frustrating.
30 { -12.0, 1.0 - (1.0 - 106.5/127.0) * 3.0 }, // About 0.492.
32 // -12 to -21 is half the range (9 dB). Halve.
35 // -21 to -30 (9 dB) gets the same range as the previous one.
38 // -30 to -48 (18 dB) gets half of half.
41 // -48 to -84 (36 dB) gets half of half of half.
47 NonLinearFader::NonLinearFader(QWidget *parent)
50 update_slider_position();
53 void NonLinearFader::setDbValue(double db)
56 update_slider_position();
57 emit dbValueChanged(db);
60 void NonLinearFader::paintEvent(QPaintEvent *event)
62 QStyleOptionSlider opt;
63 this->initStyleOption(&opt);
64 QRect gr = this->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
65 QRect sr = this->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
67 // FIXME: Where does the slider_length / 2 come from? I can't really find it
68 // in the Qt code, but it seems to match up with reality.
69 int slider_length = sr.height();
70 int slider_max = gr.top() + (slider_length / 2);
71 int slider_min = gr.bottom() + (slider_length / 2) - slider_length + 1;
75 // Draw some ticks every 6 dB.
76 // FIXME: Find a way to make the slider wider, so that we have more space for tickmarks
77 // and some dB numbering.
79 p.setPen(Qt::darkGray);
80 for (int db = -84; db <= 6; db += 6) {
81 int y = slider_min + lrint(interpolator.db_to_fraction(db) * (slider_max - slider_min));
82 p.drawLine(QPoint(0, y), QPoint(gr.left() - x_margin, y));
83 p.drawLine(QPoint(gr.right() + x_margin, y), QPoint(width() - 1, y));
86 QSlider::paintEvent(event);
89 void NonLinearFader::sliderChange(SliderChange change)
91 QSlider::sliderChange(change);
92 if (change == QAbstractSlider::SliderValueChange && !inhibit_updates) {
96 double frac = double(value() - minimum()) / (maximum() - minimum());
97 db_value = interpolator.fraction_to_db(frac);
99 emit dbValueChanged(db_value);
103 void NonLinearFader::update_slider_position()
105 inhibit_updates = true;
106 double val = interpolator.db_to_fraction(db_value) * (maximum() - minimum()) + minimum();
107 setValue(lrint(val));
108 inhibit_updates = false;