Pretty dumb smoothing.
authorCarl Hetherington <cth@carlh.net>
Tue, 26 Feb 2013 08:15:51 +0000 (08:15 +0000)
committerCarl Hetherington <cth@carlh.net>
Tue, 26 Feb 2013 08:15:51 +0000 (08:15 +0000)
src/lib/analyse_audio_job.cc
src/lib/audio_analysis.cc
src/lib/audio_analysis.h
src/wx/audio_dialog.cc
src/wx/audio_dialog.h
src/wx/audio_plot.cc
src/wx/audio_plot.h

index 588e9fc3d2632c645cff1fa9d2585141f3b76fdc..bcabb6c91e8697b96c3f162ff7364c77faaf193c 100644 (file)
@@ -95,8 +95,7 @@ AnalyseAudioJob::audio (shared_ptr<AudioBuffers> b)
                        _current[j][AudioPoint::PEAK] = max (_current[j][AudioPoint::PEAK], fabsf (s));
 
                        if ((_done % _samples_per_point) == 0) {
-                               _current[j][AudioPoint::RMS] = 20 * log10 (sqrt (_current[j][AudioPoint::RMS] / _samples_per_point));
-                               _current[j][AudioPoint::PEAK] = 20 * log10 (_current[j][AudioPoint::PEAK]);
+                               _current[j][AudioPoint::RMS] = sqrt (_current[j][AudioPoint::RMS] / _samples_per_point);
                                _analysis->add_point (j, _current[j]);
                                
                                _current[j] = AudioPoint ();
index b29ed1707d0e01d8d8aaa08c7ab0a27019b0c446..0cf08c5bdf1b42078f571b0b6105a99572d7e66c 100644 (file)
@@ -31,6 +31,8 @@ using std::ofstream;
 using std::ifstream;
 using std::vector;
 using std::cout;
+using std::max;
+using std::list;
 
 AudioPoint::AudioPoint ()
 {
@@ -121,3 +123,29 @@ AudioAnalysis::write (string filename)
        f.close ();
        boost::filesystem::rename (tmp, filename);
 }
+
+float
+AudioAnalysis::smooth (list<float> const & data, AudioPoint::Type t)
+{
+       float val;
+
+       switch (t) {
+       case AudioPoint::PEAK:
+               /* XXX: fall-off, or something...? */
+               val = -200;
+               for (list<float>::const_iterator i = data.begin(); i != data.end(); ++i) {
+                       val = max (val, *i);
+               }
+               return val;
+       case AudioPoint::RMS:
+               val = 0;
+               for (list<float>::const_iterator i = data.begin(); i != data.end(); ++i) {
+                       val += pow (*i, 2);
+               }
+               return sqrt (val / data.size());
+       default:
+               assert (false);
+       }
+
+       return 0;
+}
index c2d8db8760622662a59e11541dbdfbf874aa336c..a8cfbdeca81a6132afa74004c2a36dc429b2e4db 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <iostream>
 #include <vector>
+#include <list>
 
 class AudioPoint
 {
@@ -59,6 +60,7 @@ public:
 
        void write (std::string);
 
+       static float smooth (std::list<float> const &, AudioPoint::Type);
 
 private:
        std::vector<std::vector<AudioPoint> > _data;
index 701c8263a48b27e8a8391da28865eae1fb516dc1..bcec013324a2ad7149aae01a36b58e87753a6dc5 100644 (file)
@@ -61,6 +61,11 @@ AudioDialog::AudioDialog (wxWindow* parent)
                _type_checkbox[i]->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (AudioDialog::type_clicked), 0, this);
        }
 
+       _smoothing = new wxSlider (this, wxID_ANY, 1, 1, 128);
+       _smoothing->Connect (wxID_ANY, wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler (AudioDialog::smoothing_changed), 0, this);
+       table->Add (_smoothing, 1, wxEXPAND);
+       table->AddSpacer (0);
+
        sizer->Add (table, 0, wxALL, 12);
 
        SetSizer (sizer);
@@ -178,3 +183,9 @@ AudioDialog::type_clicked (wxCommandEvent& ev)
 
        _plot->set_type_visible (t, _type_checkbox[t]->GetValue ());
 }
+
+void
+AudioDialog::smoothing_changed (wxScrollEvent &)
+{
+       _plot->set_smoothing (_smoothing->GetValue ());
+}
index c3875023fa9586e8bd3654d410c7030ce2863f5d..16cb356fe4ad106b8c47782b79ab9295bf2c0df5 100644 (file)
@@ -37,6 +37,7 @@ private:
        void film_changed (Film::Property);
        void channel_clicked (wxCommandEvent &);
        void type_clicked (wxCommandEvent &);
+       void smoothing_changed (wxScrollEvent &);
        void try_to_load_analysis ();
        void setup_channels ();
 
@@ -44,6 +45,7 @@ private:
        AudioPlot* _plot;
        wxCheckBox* _channel_checkbox[MAX_AUDIO_CHANNELS];
        wxCheckBox* _type_checkbox[AudioPoint::COUNT];
+       wxSlider* _smoothing;
        boost::signals2::scoped_connection _film_changed_connection;
        boost::signals2::scoped_connection _film_audio_analysis_finished_connection;
 };
index ad69b6e1dae0d2a1b36766f65e5eaf92a6d62836..d938d0c278fbe968604fae203959cd6ec5baaf33 100644 (file)
@@ -28,6 +28,7 @@
 
 using std::cout;
 using std::vector;
+using std::list;
 using std::max;
 using std::min;
 using boost::bind;
@@ -38,6 +39,7 @@ int const AudioPlot::_minimum = -70;
 AudioPlot::AudioPlot (wxWindow* parent)
        : wxPanel (parent)
        , _gain (0)
+       , _smoothing (1)
 {
        SetDoubleBuffered (true);
 
@@ -149,21 +151,33 @@ AudioPlot::paint (wxPaintEvent &)
                        }
                        
                        path[i] = gc->CreatePath ();
+
+                       float const val = 20 * log10 (_analysis->get_point(c, 0)[i]);
+                       
                        path[i].MoveToPoint (
                                db_label_width,
-                               height - (max (_analysis->get_point(c, 0)[i], float (_minimum)) - _minimum + _gain) * ys - yo
+                               height - (max (val, float (_minimum)) - _minimum + _gain) * ys - yo
                                );
                }
 
+               list<float> smoothing[AudioPoint::COUNT];
+
                for (int i = 0; i < _analysis->points(c); ++i) {
                        for (int j = 0; j < AudioPoint::COUNT; ++j) {
                                if (!_type_visible[j]) {
                                        continue;
                                }
+
+                               smoothing[j].push_back (_analysis->get_point(c, i)[j]);
+                               if (int(smoothing[j].size()) > _smoothing) {
+                                       smoothing[j].pop_front ();
+                               }
+
+                               float const val = 20 * log10 (_analysis->smooth (smoothing[j], static_cast<AudioPoint::Type> (j)));
                                
                                path[j].AddLineToPoint (
                                        i * xs + db_label_width,
-                                       height - (max (_analysis->get_point(c, i)[j], float (_minimum)) - _minimum + _gain) * ys - yo
+                                       height - (max (val, float (_minimum)) - _minimum + _gain) * ys - yo
                                        );
                        }
                }
@@ -197,3 +211,10 @@ AudioPlot::set_gain (float g)
        _gain = g;
        Refresh ();
 }
+
+void
+AudioPlot::set_smoothing (int s)
+{
+       _smoothing = s;
+       Refresh ();
+}
index 4ac7f848c064bdf24e1fc2bcb41a1a8a7b229aa8..fe8862d5431a42aebf77122e9c4983aa4ba40797 100644 (file)
@@ -32,6 +32,7 @@ public:
        void set_channel_visible (int c, bool v);
        void set_type_visible (int t, bool v);
        void set_gain (float);
+       void set_smoothing (int);
 
 private:
        void paint (wxPaintEvent &);
@@ -41,6 +42,7 @@ private:
        bool _type_visible[AudioPoint::COUNT];
        /** gain to apply in dB */
        float _gain;
+       int _smoothing;
 
        std::vector<wxColour> _colours;