mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-08 07:45:00 +01:00
Improvements to the plugin eq gui:
- 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
This commit is contained in:
parent
e09c51251f
commit
bcd217ec8e
7 changed files with 125 additions and 52 deletions
|
|
@ -50,7 +50,6 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
#include "automation_controller.h"
|
#include "automation_controller.h"
|
||||||
#include "plugin_eq_gui.h"
|
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -65,7 +64,6 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
|
||||||
: PlugUIBase (pi),
|
: PlugUIBase (pi),
|
||||||
button_table (initial_button_rows, initial_button_cols),
|
button_table (initial_button_rows, initial_button_cols),
|
||||||
output_table (initial_output_rows, initial_output_cols),
|
output_table (initial_output_rows, initial_output_cols),
|
||||||
eqgui_toggle(_("Freq Analysis")),
|
|
||||||
hAdjustment(0.0, 0.0, 0.0),
|
hAdjustment(0.0, 0.0, 0.0),
|
||||||
vAdjustment(0.0, 0.0, 0.0),
|
vAdjustment(0.0, 0.0, 0.0),
|
||||||
scroller_view(hAdjustment, vAdjustment),
|
scroller_view(hAdjustment, vAdjustment),
|
||||||
|
|
@ -99,6 +97,7 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
|
||||||
VBox* v1_box = manage (new VBox);
|
VBox* v1_box = manage (new VBox);
|
||||||
VBox* v2_box = manage (new VBox);
|
VBox* v2_box = manage (new VBox);
|
||||||
constraint_hbox->pack_start (eqgui_toggle, false, false);
|
constraint_hbox->pack_start (eqgui_toggle, false, false);
|
||||||
|
add2(plugin_eq_bin);
|
||||||
|
|
||||||
v1_box->pack_start (*smaller_hbox, false, true);
|
v1_box->pack_start (*smaller_hbox, false, true);
|
||||||
v2_box->pack_start (focus_button, 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);
|
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),
|
pi->ActiveChanged.connect (bind(mem_fun(*this, &GenericPluginUI::processor_active_changed),
|
||||||
boost::weak_ptr<Processor>(pi)));
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -246,9 +246,11 @@ PluginEqGui::set_buffer_size(uint32_t size, uint32_t signal_size)
|
||||||
// buffers for the signal analysis are ensured inside PluginInsert
|
// buffers for the signal analysis are ensured inside PluginInsert
|
||||||
uint32_t n_chans = std::max(inputs, outputs);
|
uint32_t n_chans = std::max(inputs, outputs);
|
||||||
_bufferset.ensure_buffers(ARDOUR::DataType::AUDIO, n_chans, _buffer_size);
|
_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);
|
ARDOUR::ChanCount chanCount(ARDOUR::DataType::AUDIO, n_chans);
|
||||||
_bufferset.set_count(chanCount);
|
_bufferset.set_count(chanCount);
|
||||||
|
_collect_bufferset.set_count(chanCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -313,15 +315,79 @@ PluginEqGui::run_impulse_analysis()
|
||||||
memset(d, 0, sizeof(ARDOUR::Sample)*_buffer_size);
|
memset(d, 0, sizeof(ARDOUR::Sample)*_buffer_size);
|
||||||
*d = 1.0;
|
*d = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t x,y;
|
uint32_t x,y;
|
||||||
x=y=0;
|
x=y=0;
|
||||||
|
|
||||||
_plugin->connect_and_run(_bufferset, x, y, _buffer_size, (nframes_t)0);
|
|
||||||
|
|
||||||
// Analyze all output buffers
|
|
||||||
|
_plugin->connect_and_run(_bufferset, x, y, _buffer_size, (nframes_t)0);
|
||||||
|
nframes_t f = _plugin->signal_latency();
|
||||||
|
// Adding user_latency() could be interesting
|
||||||
|
|
||||||
|
// Gather all output, taking latency into account.
|
||||||
_impulse_fft->reset();
|
_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) {
|
for (uint32_t i = 0; i < outputs; ++i) {
|
||||||
_impulse_fft->analyze(_bufferset.get_audio(i).data(_buffer_size, 0));
|
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(_collect_bufferset.get_audio(i).data(_buffer_size, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalize the output
|
// normalize the output
|
||||||
|
|
@ -329,7 +395,6 @@ PluginEqGui::run_impulse_analysis()
|
||||||
|
|
||||||
// This signals calls expose_analysis_area()
|
// This signals calls expose_analysis_area()
|
||||||
_analysis_area->queue_draw();
|
_analysis_area->queue_draw();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ class PluginEqGui : public Gtk::Table
|
||||||
|
|
||||||
// buffers
|
// buffers
|
||||||
ARDOUR::BufferSet _bufferset;
|
ARDOUR::BufferSet _bufferset;
|
||||||
|
ARDOUR::BufferSet _collect_bufferset;
|
||||||
|
|
||||||
|
|
||||||
// dimensions
|
// dimensions
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
#include "public_editor.h"
|
#include "public_editor.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
|
#include "plugin_eq_gui.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -340,7 +341,8 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
|
||||||
plugin (insert->plugin()),
|
plugin (insert->plugin()),
|
||||||
save_button(_("Add")),
|
save_button(_("Add")),
|
||||||
bypass_button (_("Bypass")),
|
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);
|
//preset_combo.set_use_arrows_always(true);
|
||||||
update_presets();
|
update_presets();
|
||||||
|
|
@ -354,6 +356,10 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
|
||||||
insert->ActiveChanged.connect (bind(
|
insert->ActiveChanged.connect (bind(
|
||||||
mem_fun(*this, &PlugUIBase::processor_active_changed),
|
mem_fun(*this, &PlugUIBase::processor_active_changed),
|
||||||
boost::weak_ptr<Processor>(insert)));
|
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());
|
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 (&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"), "");
|
ARDOUR_UI::instance()->set_tip (&bypass_button, _("Click to enable/disable this plugin"), "");
|
||||||
|
|
||||||
|
plugin_eq_bin.set_expanded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -458,6 +466,43 @@ PlugUIBase::focus_toggled (GdkEventButton* ev)
|
||||||
return true;
|
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
|
void
|
||||||
PlugUIBase::update_presets ()
|
PlugUIBase::update_presets ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,9 @@ class PlugUIBase : public virtual sigc::trackable
|
||||||
|
|
||||||
LatencyGUI latency_gui;
|
LatencyGUI latency_gui;
|
||||||
|
|
||||||
|
Gtk::Expander plugin_eq_bin;
|
||||||
|
Gtk::ToggleButton eqgui_toggle;
|
||||||
|
|
||||||
Gtk::Image* focus_out_image;
|
Gtk::Image* focus_out_image;
|
||||||
Gtk::Image* focus_in_image;
|
Gtk::Image* focus_in_image;
|
||||||
|
|
||||||
|
|
@ -100,6 +103,7 @@ class PlugUIBase : public virtual sigc::trackable
|
||||||
void save_plugin_setting (void);
|
void save_plugin_setting (void);
|
||||||
bool focus_toggled(GdkEventButton*);
|
bool focus_toggled(GdkEventButton*);
|
||||||
void bypass_toggled();
|
void bypass_toggled();
|
||||||
|
void toggle_plugin_analysis ();
|
||||||
void processor_active_changed (boost::weak_ptr<ARDOUR::Processor> p);
|
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 button_table;
|
||||||
Gtk::Table output_table;
|
Gtk::Table output_table;
|
||||||
|
|
||||||
Gtk::ToggleButton eqgui_toggle;
|
|
||||||
|
|
||||||
Gtk::ScrolledWindow scroller;
|
Gtk::ScrolledWindow scroller;
|
||||||
Gtk::Adjustment hAdjustment;
|
Gtk::Adjustment hAdjustment;
|
||||||
Gtk::Adjustment vAdjustment;
|
Gtk::Adjustment vAdjustment;
|
||||||
|
|
@ -212,8 +214,6 @@ class GenericPluginUI : public PlugUIBase, public Gtk::HPaned
|
||||||
void start_touch (ControlUI*);
|
void start_touch (ControlUI*);
|
||||||
void stop_touch (ControlUI*);
|
void stop_touch (ControlUI*);
|
||||||
|
|
||||||
void toggle_plugin_analysis ();
|
|
||||||
|
|
||||||
void print_parameter (char *buf, uint32_t len, uint32_t param);
|
void print_parameter (char *buf, uint32_t len, uint32_t param);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 (bypass_button, false, false, 10);
|
||||||
preset_box.pack_end (save_button, false, false);
|
preset_box.pack_end (save_button, false, false);
|
||||||
preset_box.pack_end (preset_combo, false, false);
|
preset_box.pack_end (preset_combo, false, false);
|
||||||
|
preset_box.pack_end (eqgui_toggle, false, false);
|
||||||
|
|
||||||
|
|
||||||
bypass_button.set_active (!insert->active());
|
bypass_button.set_active (!insert->active());
|
||||||
|
|
||||||
pack_start (preset_box, false, false);
|
pack_start (preset_box, false, false);
|
||||||
pack_start (socket, true, true);
|
pack_start (socket, true, true);
|
||||||
|
pack_start (plugin_eq_bin, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
VSTPluginUI::~VSTPluginUI ()
|
VSTPluginUI::~VSTPluginUI ()
|
||||||
|
|
|
||||||
|
|
@ -111,8 +111,8 @@ class PluginInsert : public Processor
|
||||||
_signal_analysis_input_bufferset.ensure_buffers(input_streams(), nframes);
|
_signal_analysis_input_bufferset.ensure_buffers(input_streams(), nframes);
|
||||||
_signal_analysis_output_bufferset.ensure_buffers(output_streams(), nframes);
|
_signal_analysis_output_bufferset.ensure_buffers(output_streams(), nframes);
|
||||||
|
|
||||||
_signal_analysis_collect_nframes_max = nframes;
|
|
||||||
_signal_analysis_collected_nframes = 0;
|
_signal_analysis_collected_nframes = 0;
|
||||||
|
_signal_analysis_collect_nframes_max = nframes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue