]> git.sesse.net Git - nageru/blobdiff - nonlinear_fader.cpp
Write 1.4.0 changelog.
[nageru] / nonlinear_fader.cpp
index 7c26434aac743faeda9e29434758a78543e68b13..06a929c39259c037a0d6bf27c9a0a36c0ea8efcd 100644 (file)
@@ -1,79 +1,45 @@
+#include "nonlinear_fader.h"
+
 #include <assert.h>
 #include <math.h>
-#include <stdio.h>
-#include <vector>
-#include <utility>
-
-#include <QResizeEvent>
 #include <QPainter>
+#include <QPoint>
+#include <QRect>
 #include <QStyle>
-#include <QStyleOptionSlider>
+#include <QStyleOption>
+#include <memory>
+#include <utility>
+#include <vector>
 
-#include "nonlinear_fader.h"
+#include "piecewise_interpolator.h"
+
+class QPaintEvent;
+class QWidget;
 
 using namespace std;
 
 namespace {
 
-vector<pair<double, double>> fader_control_points = {
+PiecewiseInterpolator interpolator({
        // The main area is from +6 to -12 dB (18 dB), and we use half the slider range for it.
-       { 6.0, 0.0 },
-       { -12.0, 0.5 },
+       // Adjust slightly so that the MIDI controller value of 106 becomes exactly 0.0 dB
+       // (cf. map_controller_to_float()); otherwise, we'd miss ever so slightly, which is
+       // really frustrating.
+       { 6.0, 1.0 },
+       { -12.0, 1.0 - (1.0 - 106.5/127.0) * 3.0 },  // About 0.492.
 
        // -12 to -21 is half the range (9 dB). Halve.
-       { -21.0, 0.625 },
+       { -21.0, 0.325 },
 
        // -21 to -30 (9 dB) gets the same range as the previous one.
-       { -30.0, 0.75 },
+       { -30.0, 0.25 },
 
        // -30 to -48 (18 dB) gets half of half.
-       { -48.0, 0.875 },
+       { -48.0, 0.125 },
 
        // -48 to -84 (36 dB) gets half of half of half.
-       { -84.0, 1.0 },
-};
-
-double slider_fraction_to_db(double db)
-{
-       if (db <= fader_control_points[0].second) {
-               return fader_control_points[0].first;
-       }
-       if (db >= fader_control_points.back().second) {
-               return fader_control_points.back().first;
-       }
-       for (unsigned i = 1; i < fader_control_points.size(); ++i) {
-               const double x0 = fader_control_points[i - 1].second;
-               const double x1 = fader_control_points[i].second;
-               const double y0 = fader_control_points[i - 1].first;
-               const double y1 = fader_control_points[i].first;
-               if (db >= x0 && db <= x1) {
-                       const double t = (db - x0) / (x1 - x0);
-                       return y0 + t * (y1 - y0);
-               }
-       }
-       assert(false);
-}
-
-double db_to_slider_fraction(double x)
-{
-       if (x >= fader_control_points[0].first) {
-               return fader_control_points[0].second;
-       }
-       if (x <= fader_control_points.back().first) {
-               return fader_control_points.back().second;
-       }
-       for (unsigned i = 1; i < fader_control_points.size(); ++i) {
-               const double x0 = fader_control_points[i].first;
-               const double x1 = fader_control_points[i - 1].first;
-               const double y0 = fader_control_points[i].second;
-               const double y1 = fader_control_points[i - 1].second;
-               if (x >= x0 && x <= x1) {
-                       const double t = (x - x0) / (x1 - x0);
-                       return y0 + t * (y1 - y0);
-               }
-       }
-       assert(false);
-}
+       { -84.0, 0.0 },
+});
 
 }  // namespace
 
@@ -100,8 +66,8 @@ void NonLinearFader::paintEvent(QPaintEvent *event)
        // FIXME: Where does the slider_length / 2 come from? I can't really find it
        // in the Qt code, but it seems to match up with reality.
        int slider_length = sr.height();
-       int slider_min = gr.top() + (slider_length / 2);
-       int slider_max = gr.bottom() + (slider_length / 2) - slider_length + 1;
+       int slider_max = gr.top() + (slider_length / 2);
+       int slider_min = gr.bottom() + (slider_length / 2) - slider_length + 1;
 
        QPainter p(this);
 
@@ -111,7 +77,7 @@ void NonLinearFader::paintEvent(QPaintEvent *event)
        int x_margin = 5;
        p.setPen(Qt::darkGray);
        for (int db = -84; db <= 6; db += 6) {
-               int y = slider_min + lrint(db_to_slider_fraction(db) * (slider_max - slider_min));
+               int y = slider_min + lrint(interpolator.db_to_fraction(db) * (slider_max - slider_min));
                p.drawLine(QPoint(0, y), QPoint(gr.left() - x_margin, y));
                p.drawLine(QPoint(gr.right() + x_margin, y), QPoint(width() - 1, y));
        }
@@ -119,15 +85,6 @@ void NonLinearFader::paintEvent(QPaintEvent *event)
        QSlider::paintEvent(event);
 }
 
-void NonLinearFader::resizeEvent(QResizeEvent *event)
-{
-       QSlider::resizeEvent(event);
-       inhibit_updates = true;
-       setRange(0, event->size().height() - 1);
-       inhibit_updates = false;
-       update_slider_position();
-}
-
 void NonLinearFader::sliderChange(SliderChange change)
 {
        QSlider::sliderChange(change);
@@ -135,8 +92,8 @@ void NonLinearFader::sliderChange(SliderChange change)
                if (value() == 0) {
                        db_value = -HUGE_VAL;
                } else {
-                       double frac = 1.0 - value() / (height() - 1.0);
-                       db_value = slider_fraction_to_db(frac);
+                       double frac = double(value() - minimum()) / (maximum() - minimum());
+                       db_value = interpolator.fraction_to_db(frac);
                }
                emit dbValueChanged(db_value);
        }
@@ -145,6 +102,7 @@ void NonLinearFader::sliderChange(SliderChange change)
 void NonLinearFader::update_slider_position()
 {
        inhibit_updates = true;
-       setValue(lrint((1.0 - db_to_slider_fraction(db_value)) * (height() - 1.0)));
+       double val = interpolator.db_to_fraction(db_value) * (maximum() - minimum()) + minimum();
+       setValue(lrint(val));
        inhibit_updates = false;
 }