Add and use dB/linear conversion functions.
authorCarl Hetherington <cth@carlh.net>
Thu, 27 Feb 2020 21:26:57 +0000 (22:26 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 27 Feb 2020 21:26:57 +0000 (22:26 +0100)
src/lib/audio_buffers.cc
src/lib/hints.cc
src/lib/util.cc
src/lib/util.h
src/wx/audio_dialog.cc
src/wx/audio_gain_dialog.cc
src/wx/audio_mapping_view.cc
src/wx/audio_panel.cc
src/wx/audio_plot.cc
test/torture_test.cc

index cceb1267213450ed8fc6cc3c4dbc3d8c913c032c..cfe762659ebdb6d91128557b35cccb3c08c56144 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
     This file is part of DCP-o-matic.
 
@@ -18,6 +18,7 @@
 
 */
 
 
 */
 
+#include "util.h"
 #include "audio_buffers.h"
 #include "dcpomatic_assert.h"
 #include <cassert>
 #include "audio_buffers.h"
 #include "dcpomatic_assert.h"
 #include <cassert>
@@ -309,7 +310,7 @@ AudioBuffers::accumulate_frames (AudioBuffers const * from, int32_t frames, int3
 void
 AudioBuffers::apply_gain (float dB)
 {
 void
 AudioBuffers::apply_gain (float dB)
 {
-       float const linear = pow (10, dB / 20);
+       float const linear = db_to_linear (dB);
 
        for (int i = 0; i < _channels; ++i) {
                for (int j = 0; j < _frames; ++j) {
 
        for (int i = 0; i < _channels; ++i) {
                for (int j = 0; j < _frames; ++j) {
index 6cb037ed0afd2ebd6bb865734de77eebd455f33f..3edceeee371bbe4978765bf0f96b2aef14dd5102 100644 (file)
@@ -235,7 +235,7 @@ Hints::thread ()
 
                        for (size_t i = 0; i < sample_peak.size(); ++i) {
                                float const peak = max (sample_peak[i].peak, true_peak.empty() ? 0 : true_peak[i]);
 
                        for (size_t i = 0; i < sample_peak.size(); ++i) {
                                float const peak = max (sample_peak[i].peak, true_peak.empty() ? 0 : true_peak[i]);
-                               float const peak_dB = 20 * log10 (peak) + an->gain_correction (film->playlist ());
+                               float const peak_dB = linear_to_db(peak) + an->gain_correction(film->playlist());
                                if (peak_dB > -3) {
                                        ch += dcp::raw_convert<string> (short_audio_channel_name (i)) + ", ";
                                }
                                if (peak_dB > -3) {
                                        ch += dcp::raw_convert<string> (short_audio_channel_name (i)) + ", ";
                                }
index bbb44436713281d5a3a88ee0bec5a265bd2e6efa..e4f552c4d7c46177414b1db0e40352847f7bf705 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
     This file is part of DCP-o-matic.
 
@@ -1171,3 +1171,16 @@ write_swaroop_chain (shared_ptr<const dcp::CertificateChain> chain, boost::files
 }
 
 #endif
 }
 
 #endif
+
+double
+db_to_linear (double db)
+{
+       return pow(10, db / 20);
+}
+
+double
+linear_to_db (double linear)
+{
+       return 20 * log10(linear);
+}
+
index c8dcb29d6913c49ccef30bf92ee9393514824b91..12c79ea5a374cabe566d751e9f5c250db71b22ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
     This file is part of DCP-o-matic.
 
@@ -128,4 +128,7 @@ vector_to_list (std::vector<T> v)
        return l;
 }
 
        return l;
 }
 
+extern double db_to_linear (double db);
+extern double linear_to_db (double linear);
+
 #endif
 #endif
index 9b3a9376937d4c4c94cf9ec601c4d9613055c48f..2f1f1c8265f324f41cb1c2733dd0f02ad44267bc 100644 (file)
@@ -366,7 +366,7 @@ AudioDialog::setup_statistics ()
        }
 
        pair<AudioAnalysis::PeakTime, int> const peak = _analysis->overall_sample_peak ();
        }
 
        pair<AudioAnalysis::PeakTime, int> const peak = _analysis->overall_sample_peak ();
-       float const peak_dB = 20 * log10 (peak.first.peak) + _analysis->gain_correction (_playlist);
+       float const peak_dB = linear_to_db(peak.first.peak) + _analysis->gain_correction(_playlist);
        _sample_peak->SetLabel (
                wxString::Format (
                        _("Sample peak is %.2fdB at %s on %s"),
        _sample_peak->SetLabel (
                wxString::Format (
                        _("Sample peak is %.2fdB at %s on %s"),
@@ -384,7 +384,7 @@ AudioDialog::setup_statistics ()
 
        if (_analysis->overall_true_peak()) {
                float const peak = _analysis->overall_true_peak().get();
 
        if (_analysis->overall_true_peak()) {
                float const peak = _analysis->overall_true_peak().get();
-               float const peak_dB = 20 * log10 (peak) + _analysis->gain_correction (_playlist);
+               float const peak_dB = linear_to_db(peak) + _analysis->gain_correction(_playlist);
 
                _true_peak->SetLabel (wxString::Format (_("True peak is %.2fdB"), peak_dB));
 
 
                _true_peak->SetLabel (wxString::Format (_("True peak is %.2fdB"), peak_dB));
 
index 72b3f86ca94bc77f1aa551de9b66955b8395ecf7..5cd936d2439fb9bb4f0807b678cc0a0e56291a8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
     This file is part of DCP-o-matic.
 
 
 */
 
 
 */
 
-#include <cmath>
-#include <wx/spinctrl.h>
 #include "audio_gain_dialog.h"
 #include "wx_util.h"
 #include "audio_gain_dialog.h"
 #include "wx_util.h"
+#include "lib/util.h"
+#include <cmath>
+#include <wx/spinctrl.h>
 
 AudioGainDialog::AudioGainDialog (wxWindow* parent, int c, int d, float v)
        : TableDialog (parent, _("Channel gain"), 3, 1, true)
 
 AudioGainDialog::AudioGainDialog (wxWindow* parent, int c, int d, float v)
        : TableDialog (parent, _("Channel gain"), 3, 1, true)
@@ -34,7 +35,7 @@ AudioGainDialog::AudioGainDialog (wxWindow* parent, int c, int d, float v)
        _gain->SetDigits (1);
        _gain->SetIncrement (0.1);
 
        _gain->SetDigits (1);
        _gain->SetIncrement (0.1);
 
-       _gain->SetValue (20 * log10 (v));
+       _gain->SetValue (linear_to_db(v));
 
        layout ();
 }
 
        layout ();
 }
@@ -46,5 +47,5 @@ AudioGainDialog::value () const
                return 0;
        }
 
                return 0;
        }
 
-       return pow (10, _gain->GetValue () / 20);
+       return db_to_linear (_gain->GetValue());
 }
 }
index 140f18d60341207cd03ad2bdc89a4999c32e4a56..937dea5588b453e9992e9c991c4ff94f9f86441d 100644 (file)
@@ -308,7 +308,7 @@ AudioMappingView::paint_indicators (wxDC& dc)
                                        )
                                );
 
                                        )
                                );
 
-                       float const value_dB = 20 * log10 (_map.get(y, x));
+                       float const value_dB = linear_to_db(_map.get(y, x));
                        int const range = 18;
                        int height = 0;
                        if (value_dB > -range) {
                        int const range = 18;
                        int height = 0;
                        if (value_dB > -range) {
@@ -504,7 +504,7 @@ AudioMappingView::full ()
 void
 AudioMappingView::minus6dB ()
 {
 void
 AudioMappingView::minus6dB ()
 {
-       _map.set (_menu_input, _menu_output, pow (10, -6.0 / 20));
+       _map.set (_menu_input, _menu_output, db_to_linear(-6));
        map_values_changed ();
 }
 
        map_values_changed ();
 }
 
@@ -599,7 +599,7 @@ AudioMappingView::motion (wxMouseEvent& ev)
                                        safe_output_channel_name(channels->second)
                                        );
                        } else {
                                        safe_output_channel_name(channels->second)
                                        );
                        } else {
-                               float const dB = 20 * log10 (gain);
+                               float const dB = linear_to_db(gain);
                                s = wxString::Format (
                                        _("Audio will be passed from %s channel %s to %s channel %s with gain %.1fdB."),
                                        _from,
                                s = wxString::Format (
                                        _("Audio will be passed from %s channel %s to %s channel %s with gain %.1fdB."),
                                        _from,
index d6137ad9f1b122e716d889199e6d100bd3e6564a..37d6f8bb6f410525bb6b0fb37a8c13a043afe017 100644 (file)
@@ -381,7 +381,7 @@ AudioPanel::peak () const
                playlist->add (_parent->film(), sel.front());
                try {
                        shared_ptr<AudioAnalysis> analysis (new AudioAnalysis(_parent->film()->audio_analysis_path(playlist)));
                playlist->add (_parent->film(), sel.front());
                try {
                        shared_ptr<AudioAnalysis> analysis (new AudioAnalysis(_parent->film()->audio_analysis_path(playlist)));
-                       peak_dB = 20 * log10 (analysis->overall_sample_peak().first.peak) + analysis->gain_correction(playlist);
+                       peak_dB = linear_to_db(analysis->overall_sample_peak().first.peak) + analysis->gain_correction(playlist);
                } catch (...) {
 
                }
                } catch (...) {
 
                }
index 3da7a50ff2c57dfe515e8a0c16c7c66d816d3dcd..0b7b29923f45272bfb4676cff47fbd45adcce6fd 100644 (file)
@@ -267,7 +267,7 @@ AudioPlot::y_for_linear (float p, Metrics const & metrics) const
                p = 1e-4;
        }
 
                p = 1e-4;
        }
 
-       return metrics.height - (20 * log10(p) - _minimum) * metrics.y_scale - metrics.y_origin;
+       return metrics.height - (linear_to_db(p) - _minimum) * metrics.y_scale - metrics.y_origin;
 }
 
 void
 }
 
 void
@@ -294,7 +294,7 @@ AudioPlot::plot_peak (wxGraphicsPath& path, int channel, Metrics const & metrics
                        Point (
                                wxPoint (metrics.db_label_width + i * metrics.x_scale, y_for_linear (peak, metrics)),
                                DCPTime::from_frames (i * _analysis->samples_per_point(), _analysis->sample_rate()),
                        Point (
                                wxPoint (metrics.db_label_width + i * metrics.x_scale, y_for_linear (peak, metrics)),
                                DCPTime::from_frames (i * _analysis->samples_per_point(), _analysis->sample_rate()),
-                               20 * log10(peak)
+                               linear_to_db(peak)
                                )
                        );
        }
                                )
                        );
        }
@@ -363,7 +363,7 @@ AudioPlot::plot_rms (wxGraphicsPath& path, int channel, Metrics const & metrics)
                        Point (
                                wxPoint (metrics.db_label_width + i * metrics.x_scale, y_for_linear (p, metrics)),
                                DCPTime::from_frames (i * _analysis->samples_per_point(), _analysis->sample_rate()),
                        Point (
                                wxPoint (metrics.db_label_width + i * metrics.x_scale, y_for_linear (p, metrics)),
                                DCPTime::from_frames (i * _analysis->samples_per_point(), _analysis->sample_rate()),
-                               20 * log10(p)
+                               linear_to_db(p)
                                )
                        );
        }
                                )
                        );
        }
@@ -397,7 +397,7 @@ AudioPlot::get_point (int channel, int point) const
 {
        AudioPoint p = _analysis->get_point (channel, point);
        for (int i = 0; i < AudioPoint::COUNT; ++i) {
 {
        AudioPoint p = _analysis->get_point (channel, point);
        for (int i = 0; i < AudioPoint::COUNT; ++i) {
-               p[i] *= pow (10, _gain_correction / 20);
+               p[i] *= db_to_linear(_gain_correction);
        }
 
        return p;
        }
 
        return p;
index 10d343268c12520084e779627c93dd534128fe8b..8bd541ad232479addfb5cbc32873834acfa42231 100644 (file)
@@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE (torture_test1)
        staircase->set_position (film, DCPTime::from_frames (2000, film->audio_frame_rate()));
        staircase->set_trim_start (ContentTime::from_frames (12, 48000));
        staircase->set_trim_end (ContentTime::from_frames (35, 48000));
        staircase->set_position (film, DCPTime::from_frames (2000, film->audio_frame_rate()));
        staircase->set_trim_start (ContentTime::from_frames (12, 48000));
        staircase->set_trim_end (ContentTime::from_frames (35, 48000));
-       staircase->audio->set_gain (20 * log10(2));
+       staircase->audio->set_gain (linear_to_db(6));
 
        /* And again at an offset of 50000 samples, trimmed both start and end, with a gain of 6dB */
        staircase = content_factory("test/data/staircase.wav").front ();
 
        /* And again at an offset of 50000 samples, trimmed both start and end, with a gain of 6dB */
        staircase = content_factory("test/data/staircase.wav").front ();
@@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE (torture_test1)
        staircase->set_position (film, DCPTime::from_frames(50000, film->audio_frame_rate()));
        staircase->set_trim_start (ContentTime::from_frames (12, 48000));
        staircase->set_trim_end (ContentTime::from_frames (35, 48000));
        staircase->set_position (film, DCPTime::from_frames(50000, film->audio_frame_rate()));
        staircase->set_trim_start (ContentTime::from_frames (12, 48000));
        staircase->set_trim_end (ContentTime::from_frames (35, 48000));
-       staircase->audio->set_gain (20 * log10(2));
+       staircase->audio->set_gain (linear_to_db(6));
 
        /* 1s of red at 5s in */
        shared_ptr<Content> red = content_factory("test/data/flat_red.png").front ();
 
        /* 1s of red at 5s in */
        shared_ptr<Content> red = content_factory("test/data/flat_red.png").front ();