Improvements to the plugin eq gui:
authorSampo Savolainen <v2@iki.fi>
Sat, 7 Mar 2009 11:17:06 +0000 (11:17 +0000)
committerSampo Savolainen <v2@iki.fi>
Sat, 7 Mar 2009 11:17:06 +0000 (11:17 +0000)
 - phase correction for analysis
 - move gui elements to a more common location so that it's available for VSTs
   (needs packing in each PluginUI derived class though)

git-svn-id: svn://localhost/ardour2/branches/3.0@4745 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/generic_pluginui.cc
gtk2_ardour/plugin_eq_gui.cc
gtk2_ardour/plugin_eq_gui.h
gtk2_ardour/plugin_ui.cc
gtk2_ardour/plugin_ui.h
gtk2_ardour/vst_pluginui.cc
libs/ardour/ardour/plugin_insert.h

index 16dbba523ff302d2608c384157fb87a3674e5ebe..d276b294ed0e96314e435e61ad6c89cc76187647 100644 (file)
@@ -50,7 +50,6 @@
 #include "utils.h"
 #include "gui_thread.h"
 #include "automation_controller.h"
-#include "plugin_eq_gui.h"
 
 #include "i18n.h"
 
@@ -65,7 +64,6 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
        : PlugUIBase (pi),
          button_table (initial_button_rows, initial_button_cols),
          output_table (initial_output_rows, initial_output_cols),
-         eqgui_toggle(_("Freq Analysis")),
          hAdjustment(0.0, 0.0, 0.0),
          vAdjustment(0.0, 0.0, 0.0),
          scroller_view(hAdjustment, vAdjustment),
@@ -99,6 +97,7 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
        VBox* v1_box = manage (new VBox);
        VBox* v2_box = manage (new VBox);
        constraint_hbox->pack_start (eqgui_toggle, false, false);
+       add2(plugin_eq_bin);
 
        v1_box->pack_start (*smaller_hbox, false, true);
        v2_box->pack_start (focus_button, false, true);
@@ -124,9 +123,6 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
                main_contents.pack_start (hpacker, false, false);
        }
 
-       eqgui_toggle.set_active (false);
-       eqgui_toggle.signal_toggled().connect( mem_fun(*this, &GenericPluginUI::toggle_plugin_analysis));
-
        pi->ActiveChanged.connect (bind(mem_fun(*this, &GenericPluginUI::processor_active_changed),
                                        boost::weak_ptr<Processor>(pi)));
        
@@ -836,41 +832,4 @@ GenericPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
 }
 
 
-void
-GenericPluginUI::toggle_plugin_analysis()
-{
-
-
-
-       if (eqgui_toggle.get_active() && !get_child2()) {
-               // Create the GUI
-               PluginEqGui *foo = new PluginEqGui(insert);
-               pack2( *foo );
-               show_all();
-       } 
-       
-       Gtk::Widget *gui;
-
-       if (!eqgui_toggle.get_active() && (gui = get_child2())) {
-               // Hide & remove
-               gui->hide();
-               remove(*gui);
-
-               delete gui;
-
-               Gtk::Widget *toplevel = get_toplevel();
-               if (!toplevel) {
-                       std::cerr << "No toplevel widget?!?!" << std::endl;
-                       return;
-               }
-
-               Gtk::Container *cont = dynamic_cast<Gtk::Container *>(toplevel);
-               if (!cont) {
-                       std::cerr << "Toplevel widget is not a container?!?" << std::endl;
-                       return;
-               }
 
-               Gtk::Allocation alloc(0, 0, 50, 50); // Just make it small
-               toplevel->size_allocate(alloc);
-       }
-}
index 2b439272786546f7029a4bb3809c81af58a3f7d8..1e7d038b97c569791d26390aa60b3b70899e09d2 100644 (file)
@@ -246,9 +246,11 @@ PluginEqGui::set_buffer_size(uint32_t size, uint32_t signal_size)
        // buffers for the signal analysis are ensured inside PluginInsert
        uint32_t n_chans = std::max(inputs, outputs);
        _bufferset.ensure_buffers(ARDOUR::DataType::AUDIO, n_chans, _buffer_size);
+       _collect_bufferset.ensure_buffers(ARDOUR::DataType::AUDIO, n_chans, _buffer_size);
 
        ARDOUR::ChanCount chanCount(ARDOUR::DataType::AUDIO, n_chans);
        _bufferset.set_count(chanCount);
+       _collect_bufferset.set_count(chanCount);
 }
 
 void 
@@ -313,15 +315,79 @@ PluginEqGui::run_impulse_analysis()
                memset(d, 0, sizeof(ARDOUR::Sample)*_buffer_size);
                *d = 1.0;
        }
+
        uint32_t x,y;
        x=y=0;
 
+
+
        _plugin->connect_and_run(_bufferset, x, y, _buffer_size, (nframes_t)0);
+       nframes_t f = _plugin->signal_latency();
+       // Adding user_latency() could be interesting
 
-       // Analyze all output buffers
+       // Gather all output, taking latency into account.
        _impulse_fft->reset();
+               
+       // Silence collect buffers to copy data to, can't use silence() because consecutive calls won't work
+       for (uint32_t i = 0; i < outputs; ++i) {
+               ARDOUR::AudioBuffer &buf = _collect_bufferset.get_audio(i);
+               ARDOUR::Sample *d = buf.data(_buffer_size, 0);
+               memset(d, 0, sizeof(ARDOUR::Sample)*_buffer_size);
+       }
+
+       if (f == 0) {
+               //std::cerr << "0: no latency, copying full buffer, trivial.." << std::endl;
+               for (uint32_t i = 0; i < outputs; ++i) {
+                       memcpy(_collect_bufferset.get_audio(i).data(_buffer_size, 0),
+                              _bufferset.get_audio(i).data(_buffer_size, 0), _buffer_size * sizeof(float));
+               }
+       } else {
+               //int C = 0;
+               //std::cerr << (++C) << ": latency is " << f << " frames, doing split processing.." << std::endl;
+               nframes_t target_offset = 0;
+               nframes_t frames_left = _buffer_size; // refaktoroi
+               do {
+                       if (f >= _buffer_size) {
+                               //std::cerr << (++C) << ": f (=" << f << ") is larger than buffer_size, still trying to reach the actual output" << std::endl;
+                               // there is no data in this buffer regarding to the input!
+                               f -= _buffer_size;
+                       } else {
+                               // this buffer contains either the first, last or a whole bu the output of the impulse
+                               // first part: offset is 0, so we copy to the start of _collect_bufferset
+                               //             we start at output offset "f"
+                               //             .. and copy "buffer size" - "f" - "offset" frames
+
+                               nframes_t length = _buffer_size - f - target_offset;
+
+                               //std::cerr << (++C) << ": copying " << length << " frames to _collect_bufferset.get_audio(i)+" << target_offset << " from bufferset at offset " << f << std::endl;
+                               for (uint32_t i = 0; i < outputs; ++i) {
+                                       memcpy(_collect_bufferset.get_audio(i).data(_buffer_size, target_offset),
+                                                       _bufferset.get_audio(i).data(_buffer_size, 0) + f, 
+                                                       length * sizeof(float));
+                               }
+
+                               target_offset += length;
+                               frames_left   -= length;
+                               f = 0;
+                       }
+                       if (frames_left > 0) {
+                               // Silence the buffers
+                               for (uint32_t i = 0; i < inputs; ++i) {
+                                       ARDOUR::AudioBuffer &buf = _bufferset.get_audio(i);
+                                       ARDOUR::Sample *d = buf.data(_buffer_size, 0);
+                                       memset(d, 0, sizeof(ARDOUR::Sample)*_buffer_size);
+                               }
+
+                               x=y=0;
+                               _plugin->connect_and_run(_bufferset, x, y, _buffer_size, (nframes_t)0);
+                       }
+               } while ( frames_left > 0);
+
+       }
+
+
        for (uint32_t i = 0; i < outputs; ++i) {
-               _impulse_fft->analyze(_bufferset.get_audio(i).data(_buffer_size, 0));
+               _impulse_fft->analyze(_collect_bufferset.get_audio(i).data(_buffer_size, 0));
        }
 
        // normalize the output
@@ -329,7 +395,6 @@ PluginEqGui::run_impulse_analysis()
 
        // This signals calls expose_analysis_area()
        _analysis_area->queue_draw();   
-
 }
 
 bool
index 05e09e3214d157dc34c457153107cdb105420f16..6b1773525046d1ad6195feab87878c2e9db084a4 100644 (file)
@@ -94,6 +94,7 @@ class PluginEqGui : public Gtk::Table
 
                // buffers              
                ARDOUR::BufferSet _bufferset;
+               ARDOUR::BufferSet _collect_bufferset;
 
 
                // dimensions
index 4c7ae5b8a009464a5e2f406f38550e6234b58856..bfac04aa9b4d71c12f6b4ef46bfed1a42a79ae48 100644 (file)
@@ -57,6 +57,7 @@
 #include "gui_thread.h"
 #include "public_editor.h"
 #include "keyboard.h"
+#include "plugin_eq_gui.h"
 
 #include "i18n.h"
 
@@ -340,7 +341,8 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
          plugin (insert->plugin()),
          save_button(_("Add")),
          bypass_button (_("Bypass")),
-         latency_gui (*pi, pi->session().frame_rate(), pi->session().get_block_size())
+         latency_gui (*pi, pi->session().frame_rate(), pi->session().get_block_size()),
+         eqgui_toggle (_("Freq Analysis"))
 {
        //preset_combo.set_use_arrows_always(true);
        update_presets();
@@ -354,6 +356,10 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
        insert->ActiveChanged.connect (bind(
                        mem_fun(*this, &PlugUIBase::processor_active_changed),
                        boost::weak_ptr<Processor>(insert)));
+
+       eqgui_toggle.set_active (false);
+       eqgui_toggle.signal_toggled().connect( mem_fun(*this, &PlugUIBase::toggle_plugin_analysis));
+
        
        bypass_button.set_active (!pi->active());
 
@@ -373,6 +379,8 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
 
        ARDOUR_UI::instance()->set_tip (&focus_button, _("Click to focus all keyboard events on this plugin window"), "");
        ARDOUR_UI::instance()->set_tip (&bypass_button, _("Click to enable/disable this plugin"), "");
+
+       plugin_eq_bin.set_expanded(true);
 }
 
 void
@@ -458,6 +466,43 @@ PlugUIBase::focus_toggled (GdkEventButton* ev)
        return true;
 }
 
+void
+PlugUIBase::toggle_plugin_analysis()
+{
+       if (eqgui_toggle.get_active() && !plugin_eq_bin.get_child()) {
+               // Create the GUI
+               PluginEqGui *foo = new PluginEqGui(insert);
+               plugin_eq_bin.add( *foo );
+               plugin_eq_bin.show_all();
+       } 
+       
+       Gtk::Widget *gui;
+
+       if (!eqgui_toggle.get_active() && (gui = plugin_eq_bin.get_child())) {
+               // Hide & remove
+               gui->hide();
+               //plugin_eq_bin.remove(*gui);
+               plugin_eq_bin.remove();
+
+               delete gui;
+
+               Gtk::Widget *toplevel = plugin_eq_bin.get_toplevel();
+               if (!toplevel) {
+                       std::cerr << "No toplevel widget?!?!" << std::endl;
+                       return;
+               }
+
+               Gtk::Container *cont = dynamic_cast<Gtk::Container *>(toplevel);
+               if (!cont) {
+                       std::cerr << "Toplevel widget is not a container?!?" << std::endl;
+                       return;
+               }
+
+               Gtk::Allocation alloc(0, 0, 50, 50); // Just make it small
+               toplevel->size_allocate(alloc);
+       }
+}
+
 void
 PlugUIBase::update_presets ()
 {
index fb365409d70b1065635a4acbe90201fd272cbde9..8f00ef8201cc40302a7a8e208bd2dadeae2bc245 100644 (file)
@@ -93,6 +93,9 @@ class PlugUIBase : public virtual sigc::trackable
 
        LatencyGUI latency_gui;
 
+       Gtk::Expander plugin_eq_bin;
+       Gtk::ToggleButton eqgui_toggle;
+
        Gtk::Image* focus_out_image;
        Gtk::Image* focus_in_image;
 
@@ -100,6 +103,7 @@ class PlugUIBase : public virtual sigc::trackable
        void save_plugin_setting (void);
        bool focus_toggled(GdkEventButton*);
        void bypass_toggled();
+       void toggle_plugin_analysis ();
        void processor_active_changed (boost::weak_ptr<ARDOUR::Processor> p);
 };
 
@@ -124,8 +128,6 @@ class GenericPluginUI : public PlugUIBase, public Gtk::HPaned
        Gtk::Table button_table;
        Gtk::Table output_table;
 
-       Gtk::ToggleButton eqgui_toggle;
-
        Gtk::ScrolledWindow scroller;
        Gtk::Adjustment hAdjustment;
        Gtk::Adjustment vAdjustment;
@@ -212,8 +214,6 @@ class GenericPluginUI : public PlugUIBase, public Gtk::HPaned
        void start_touch (ControlUI*);
        void stop_touch (ControlUI*);
 
-       void toggle_plugin_analysis ();
-
        void print_parameter (char *buf, uint32_t len, uint32_t param);
 };
 
index 0ee7956f53d4804f19b1bb2c4e92dfb62f1a7b2b..99c7a1b82b094532a0ff89f3d6c34bd60bdd13f3 100644 (file)
@@ -40,11 +40,14 @@ VSTPluginUI::VSTPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<
        preset_box.pack_end (bypass_button, false, false, 10);
        preset_box.pack_end (save_button, false, false);
        preset_box.pack_end (preset_combo, false, false);
+       preset_box.pack_end (eqgui_toggle, false, false);
+
 
        bypass_button.set_active (!insert->active());
        
        pack_start (preset_box, false, false);
        pack_start (socket, true, true);
+       pack_start (plugin_eq_bin, true, true);
 }
 
 VSTPluginUI::~VSTPluginUI ()
index bc213dcb95077c9865e895f9ae43eaa70c3d005d..0d3534a2b86c839944a251a3bd1432e282d65e72 100644 (file)
@@ -111,8 +111,8 @@ class PluginInsert : public Processor
                _signal_analysis_input_bufferset.ensure_buffers(input_streams(), nframes);
                _signal_analysis_output_bufferset.ensure_buffers(output_streams(), nframes);
 
-               _signal_analysis_collect_nframes_max = nframes; 
                _signal_analysis_collected_nframes   = 0;
+               _signal_analysis_collect_nframes_max = nframes; 
        }
 
   private: