Multiple simultaneous plots.
authorCarl Hetherington <cth@carlh.net>
Mon, 25 Feb 2013 20:21:29 +0000 (20:21 +0000)
committerCarl Hetherington <cth@carlh.net>
Mon, 25 Feb 2013 20:21:29 +0000 (20:21 +0000)
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 fffafc4d4c5fe38ab4591883e160e7d0e35812cc..b29ed1707d0e01d8d8aaa08c7ab0a27019b0c446 100644 (file)
@@ -80,22 +80,27 @@ AudioAnalysis::AudioAnalysis (string filename)
 void
 AudioAnalysis::add_point (int c, AudioPoint const & p)
 {
-       assert (c < int (_data.size ()));
+       assert (c < channels ());
        _data[c].push_back (p);
 }
 
 AudioPoint
 AudioAnalysis::get_point (int c, int p) const
 {
-       assert (c < int (_data.size ()));
-       assert (p < int (_data[c].size ()));
+       assert (p < points (c));
        return _data[c][p];
 }
 
+int
+AudioAnalysis::channels () const
+{
+       return _data.size ();
+}
+
 int
 AudioAnalysis::points (int c) const
 {
-       assert (c < int (_data.size ()));
+       assert (c < channels ());
        return _data[c].size ();
 }
 
index c26c0584c14d963004b9d55245cb39f5efc287bd..c2d8db8760622662a59e11541dbdfbf874aa336c 100644 (file)
@@ -55,6 +55,7 @@ public:
        
        AudioPoint get_point (int c, int p) const;
        int points (int c) const;
+       int channels () const;
 
        void write (std::string);
 
index 89b04409a816d90899c6209844da93a094280fa6..dc297e2467327ef858062823340bd27afe3859e3 100644 (file)
@@ -38,17 +38,33 @@ AudioDialog::AudioDialog (wxWindow* parent)
 
        wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
 
-       add_label_to_sizer (table, this, _("Channel"));
-       _channel = new wxChoice (this, wxID_ANY);
-       table->Add (_channel, 1, wxEXPAND | wxALL, 6);
+       for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
+               _channel_checkbox[i] = new wxCheckBox (this, wxID_ANY, audio_channel_name (i));
+               table->Add (_channel_checkbox[i], 1, wxEXPAND);
+               table->AddSpacer (0);
+               _channel_checkbox[i]->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (AudioDialog::channel_clicked), 0, this);
+       }
+
+       table->AddSpacer (0);
+       table->AddSpacer (0);
+
+       wxString const types[] = {
+               _("Peak"),
+               _("RMS")
+       };
+
+       for (int i = 0; i < AudioPoint::COUNT; ++i) {
+               _type_checkbox[i] = new wxCheckBox (this, wxID_ANY, types[i]);
+               table->Add (_type_checkbox[i], 1, wxEXPAND);
+               table->AddSpacer (0);
+               _type_checkbox[i]->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (AudioDialog::type_clicked), 0, this);
+       }
 
        sizer->Add (table);
 
        SetSizer (sizer);
        sizer->Layout ();
        sizer->SetSizeHints (this);
-
-       _channel->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (AudioDialog::channel_changed), 0, this);
 }
 
 void
@@ -61,8 +77,7 @@ AudioDialog::set_film (boost::shared_ptr<Film> f)
 
        try_to_load_analysis ();
        setup_channels ();
-
-       _channel->SetSelection (0);
+       _plot->set_gain (_film->audio_gain ());
 
        _film_changed_connection = _film->Changed.connect (bind (&AudioDialog::film_changed, this, _1));
        _film_audio_analysis_finished_connection = _film->AudioAnalysisFinished.connect (bind (&AudioDialog::try_to_load_analysis, this));
@@ -71,14 +86,16 @@ AudioDialog::set_film (boost::shared_ptr<Film> f)
 void
 AudioDialog::setup_channels ()
 {
-       _channel->Clear ();
-
        if (!_film->audio_stream()) {
                return;
        }
        
        for (int i = 0; i < _film->audio_stream()->channels(); ++i) {
-               _channel->Append (audio_channel_name (i));
+               _channel_checkbox[i]->Show ();
+       }
+
+       for (int i = _film->audio_stream()->channels(); i < MAX_AUDIO_CHANNELS; ++i) {
+               _channel_checkbox[i]->Hide ();
        }
 }      
 
@@ -96,12 +113,26 @@ AudioDialog::try_to_load_analysis ()
        }
                
        _plot->set_analysis (a);
+       _channel_checkbox[0]->SetValue (true);
+       _plot->set_channel_visible (0, true);
+
+       for (int i = 0; i < AudioPoint::COUNT; ++i) {
+               _type_checkbox[i]->SetValue (true);
+               _plot->set_type_visible (i, true);
+       }
 }
 
 void
-AudioDialog::channel_changed (wxCommandEvent &)
+AudioDialog::channel_clicked (wxCommandEvent& ev)
 {
-       _plot->set_channel (_channel->GetSelection ());
+       int c = 0;
+       while (c < MAX_AUDIO_CHANNELS && ev.GetEventObject() != _channel_checkbox[c]) {
+               ++c;
+       }
+
+       assert (c < MAX_AUDIO_CHANNELS);
+       
+       _plot->set_channel_visible (c, _channel_checkbox[c]->GetValue ());
 }
 
 void
@@ -120,3 +151,16 @@ AudioDialog::film_changed (Film::Property p)
                break;
        }
 }
+
+void
+AudioDialog::type_clicked (wxCommandEvent& ev)
+{
+       int t = 0;
+       while (t < AudioPoint::COUNT && ev.GetEventObject() != _type_checkbox[t]) {
+               ++t;
+       }
+
+       assert (t < AudioPoint::COUNT);
+
+       _plot->set_type_visible (t, _type_checkbox[t]->GetValue ());
+}
index 623c9a067a5d633342d4e79e4f3f29251a3e6372..c3875023fa9586e8bd3654d410c7030ce2863f5d 100644 (file)
@@ -21,6 +21,7 @@
 #include <boost/signals2.hpp>
 #include <wx/wx.h>
 #include "lib/film.h"
+#include "lib/audio_analysis.h"
 
 class AudioPlot;
 class Film;
@@ -34,13 +35,15 @@ public:
 
 private:
        void film_changed (Film::Property);
-       void channel_changed (wxCommandEvent &);
+       void channel_clicked (wxCommandEvent &);
+       void type_clicked (wxCommandEvent &);
        void try_to_load_analysis ();
        void setup_channels ();
 
        boost::shared_ptr<Film> _film;
        AudioPlot* _plot;
-       wxChoice* _channel;
+       wxCheckBox* _channel_checkbox[MAX_AUDIO_CHANNELS];
+       wxCheckBox* _type_checkbox[AudioPoint::COUNT];
        boost::signals2::scoped_connection _film_changed_connection;
        boost::signals2::scoped_connection _film_audio_analysis_finished_connection;
 };
index 41d074dad485539b210ef34278fde82595a6b117..cccdaed3402611a09f10a8020f9044ab1c3df203 100644 (file)
@@ -37,11 +37,25 @@ int const AudioPlot::_minimum = -90;
 
 AudioPlot::AudioPlot (wxWindow* parent)
        : wxPanel (parent)
-       , _channel (0)
        , _gain (0)
 {
-       Connect (wxID_ANY, wxEVT_PAINT, wxPaintEventHandler (AudioPlot::paint), 0, this);
+       for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
+               _channel_visible[i] = false;
+       }
 
+       for (int i = 0; i < AudioPoint::COUNT; ++i) {
+               _type_visible[i] = false;
+       }
+
+       _colours.push_back (wxColour (  0,   0,   0));
+       _colours.push_back (wxColour (255,   0,   0));
+       _colours.push_back (wxColour (  0, 255,   0));
+       _colours.push_back (wxColour (139,   0, 204));
+       _colours.push_back (wxColour (  0,   0, 255));
+       _colours.push_back (wxColour (100, 100, 100));
+       
+       Connect (wxID_ANY, wxEVT_PAINT, wxPaintEventHandler (AudioPlot::paint), 0, this);
+       
        SetMinSize (wxSize (640, 512));
 }
 
@@ -49,14 +63,29 @@ void
 AudioPlot::set_analysis (shared_ptr<AudioAnalysis> a)
 {
        _analysis = a;
-       _channel = 0;
+
+       for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
+               _channel_visible[i] = false;
+       }
+
+       for (int i = 0; i < AudioPoint::COUNT; ++i) {
+               _type_visible[i] = false;
+       }
+       
        Refresh ();
 }
 
 void
-AudioPlot::set_channel (int c)
+AudioPlot::set_channel_visible (int c, bool v)
 {
-       _channel = c;
+       _channel_visible[c] = v;
+       Refresh ();
+}
+
+void
+AudioPlot::set_type_visible (int t, bool v)
+{
+       _type_visible[t] = v;
        Refresh ();
 }
 
@@ -77,7 +106,8 @@ AudioPlot::paint (wxPaintEvent &)
        }
        
        int const width = GetSize().GetWidth();
-       float const xs = width / float (_analysis->points (_channel));
+       /* Assume all channels have the same number of points */
+       float const xs = width / float (_analysis->points (0));
        int const height = GetSize().GetHeight ();
        float const ys = height / -_minimum;
 
@@ -92,24 +122,44 @@ AudioPlot::paint (wxPaintEvent &)
        gc->SetPen (*wxLIGHT_GREY_PEN);
        gc->StrokePath (grid);
 
-       wxGraphicsPath path[AudioPoint::COUNT];
+       for (int c = 0; c < MAX_AUDIO_CHANNELS; ++c) {
+               if (!_channel_visible[c] || c >= _analysis->channels()) {
+                       continue;
+               }
 
-       for (int i = 0; i < AudioPoint::COUNT; ++i) {
-               path[i] = gc->CreatePath ();
-               path[i].MoveToPoint (0, height - (max (_analysis->get_point(_channel, 0)[i], float (_minimum)) - _minimum + _gain) * ys);
-       }
+               wxGraphicsPath path[AudioPoint::COUNT];
+               
+               for (int i = 0; i < AudioPoint::COUNT; ++i) {
+                       if (!_type_visible[i]) {
+                               continue;
+                       }
+                       
+                       path[i] = gc->CreatePath ();
+                       path[i].MoveToPoint (0, height - (max (_analysis->get_point(c, 0)[i], float (_minimum)) - _minimum + _gain) * ys);
+               }
 
-       for (int i = 0; i < _analysis->points(_channel); ++i) {
-               for (int j = 0; j < AudioPoint::COUNT; ++j) {
-                       path[j].AddLineToPoint (i * xs, height - (max (_analysis->get_point(_channel, i)[j], float (_minimum)) - _minimum + _gain) * ys);
+               for (int i = 0; i < _analysis->points(c); ++i) {
+                       for (int j = 0; j < AudioPoint::COUNT; ++j) {
+                               if (!_type_visible[j]) {
+                                       continue;
+                               }
+                               
+                               path[j].AddLineToPoint (i * xs, height - (max (_analysis->get_point(c, i)[j], float (_minimum)) - _minimum + _gain) * ys);
+                       }
                }
-       }
 
-       gc->SetPen (*wxBLUE_PEN);
-       gc->StrokePath (path[AudioPoint::RMS]);
+               wxColour const col = _colours[c];
 
-       gc->SetPen (*wxRED_PEN);
-       gc->StrokePath (path[AudioPoint::PEAK]);
+               if (_type_visible[AudioPoint::RMS]) {
+                       gc->SetPen (*wxThePenList->FindOrCreatePen (col));
+                       gc->StrokePath (path[AudioPoint::RMS]);
+               }
+
+               if (_type_visible[AudioPoint::PEAK]) {
+                       gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (col.Red(), col.Green(), col.Blue(), col.Alpha() / 2)));
+                       gc->StrokePath (path[AudioPoint::PEAK]);
+               }
+       }
 
        delete gc;
 }
index b2ae139d1807c3f4f46ba4ec356ee22f6967df80..4ac7f848c064bdf24e1fc2bcb41a1a8a7b229aa8 100644 (file)
@@ -20,8 +20,8 @@
 #include <vector>
 #include <boost/shared_ptr.hpp>
 #include <wx/wx.h>
-
-class AudioAnalysis;
+#include "util.h"
+#include "audio_analysis.h"
 
 class AudioPlot : public wxPanel
 {
@@ -29,16 +29,20 @@ public:
        AudioPlot (wxWindow *);
 
        void set_analysis (boost::shared_ptr<AudioAnalysis>);
-       void set_channel (int c);
+       void set_channel_visible (int c, bool v);
+       void set_type_visible (int t, bool v);
        void set_gain (float);
 
 private:
        void paint (wxPaintEvent &);
 
        boost::shared_ptr<AudioAnalysis> _analysis;
-       int _channel;
+       bool _channel_visible[MAX_AUDIO_CHANNELS];
+       bool _type_visible[AudioPoint::COUNT];
        /** gain to apply in dB */
        float _gain;
 
+       std::vector<wxColour> _colours;
+
        static const int _minimum;
 };