Plugin analysis numerics

Show vertical marker-line (freq) and precise numeric data of the
transfer function (dB, deg).
This commit is contained in:
Robin Gareus 2018-10-25 04:25:15 +02:00
parent 5599cdb911
commit b68b4d10a2
2 changed files with 49 additions and 22 deletions

View File

@ -63,6 +63,7 @@ PluginEqGui::PluginEqGui(boost::shared_ptr<ARDOUR::PluginInsert> pluginInsert)
, _signal_input_fft(0)
, _signal_output_fft(0)
, _plugin_insert(pluginInsert)
, _pointer_in_area_xpos(-1)
{
_signal_analysis_running = false;
_samplerate = ARDOUR_UI::instance()->the_session()->sample_rate();
@ -84,7 +85,6 @@ PluginEqGui::PluginEqGui(boost::shared_ptr<ARDOUR::PluginInsert> pluginInsert)
_analysis_area->signal_size_allocate().connect( sigc::mem_fun (*this, &PluginEqGui::resize_analysis_area));
_analysis_area->signal_motion_notify_event().connect( sigc::mem_fun (*this, &PluginEqGui::analysis_area_mouseover));
_analysis_area->signal_leave_notify_event().connect( sigc::mem_fun (*this, &PluginEqGui::analysis_area_mouseexit));
_analysis_area->signal_button_press_event().connect( sigc::mem_fun (*this, &PluginEqGui::analysis_area_mousedown));
// dB selection
dBScaleModel = Gtk::ListStore::create(dBColumns);
@ -160,6 +160,12 @@ PluginEqGui::~PluginEqGui()
// all gui objects are *manage'd by the inherited Table object
}
static inline float
power_to_dB(float a)
{
return 10.0 * log10f(a);
}
void
PluginEqGui::start_listening ()
{
@ -448,10 +454,16 @@ PluginEqGui::run_impulse_analysis()
}
void
PluginEqGui::update_pointer_info(float x, float y)
PluginEqGui::update_pointer_info(float x)
{
const int freq = std::max(1, (int) roundf((powf(10, x / _analysis_width * _log_max) - 1) * _samplerate / 2.0 / _log_coeff));
const float dB = _max_dB - y / _analysis_height * ( _max_dB - _min_dB );
/* find the bin corresponding to x (see plot_impulse_amplitude) */
int i = roundf ((powf (10, _log_max * x / _analysis_width) - 1.0) * _impulse_fft->bins() / _log_coeff);
float dB = power_to_dB (_impulse_fft->power_at_bin (i));
/* calc freq corresponding to bin */
const int freq = std::max (1, (int) roundf((float)i / (float)_impulse_fft->bins() * _samplerate / 2.f));
_pointer_in_area_freq = round (_analysis_width * log10f(1.0 + (float)i / (float)_impulse_fft->bins() * _log_coeff) / _log_max);
std::stringstream ss;
ss << std::fixed;
if (freq >= 10000) {
@ -461,15 +473,23 @@ PluginEqGui::update_pointer_info(float x, float y)
} else {
ss << std::setprecision (0) << freq << "Hz";
}
ss << " " << std::setw(5) << std::setprecision (1) << std::showpos << dB;
ss << " " << std::setw(6) << std::setprecision (1) << std::showpos << dB;
ss << std::setw(0) << "dB";
if (_phase_button->get_active()) {
float phase = 180. * _impulse_fft->phase_at_bin (i) / M_PI;
ss << " " << std::setw(6) << std::setprecision (1) << std::showpos << phase;
ss << std::setw(0) << "\u00B0";
}
_pointer_info->set_text(ss.str());
}
bool
PluginEqGui::analysis_area_mouseover(GdkEventMotion *event)
{
update_pointer_info(event->x, event->y);
update_pointer_info(event->x);
_pointer_in_area_xpos = event->x;
_analysis_area->queue_draw();
return true;
}
@ -477,17 +497,11 @@ bool
PluginEqGui::analysis_area_mouseexit(GdkEventCrossing *)
{
_pointer_info->set_text("");
_pointer_in_area_xpos = -1;
_analysis_area->queue_draw();
return true;
}
bool
PluginEqGui::analysis_area_mousedown(GdkEventButton *event)
{
update_pointer_info(event->x, event->y);
return true;
}
bool
PluginEqGui::expose_analysis_area(GdkEventExpose *)
{
@ -535,15 +549,33 @@ PluginEqGui::redraw_analysis_area()
cairo_set_source_surface(cr, _analysis_scale_surface, 0.0, 0.0);
cairo_paint(cr);
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
if (_phase_button->get_active()) {
plot_impulse_phase(_analysis_area, cr);
}
plot_impulse_amplitude(_analysis_area, cr);
if (_pointer_in_area_xpos >= 0) {
update_pointer_info (_pointer_in_area_xpos);
}
if (_signal_button->get_active()) {
plot_signal_amplitude_difference(_analysis_area, cr);
}
if (_pointer_in_area_xpos >= 0 && _pointer_in_area_freq > 0) {
const double dashed[] = {0.0, 2.0};
cairo_set_dash (cr, dashed, 2, 0);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_set_line_width (cr, 1.0);
cairo_move_to (cr, _pointer_in_area_freq - .5, -.5);
cairo_line_to (cr, _pointer_in_area_freq - .5, _analysis_height - .5);
cairo_stroke(cr);
}
cairo_destroy(cr);
}
@ -747,12 +779,6 @@ PluginEqGui::draw_scales_power(Gtk::Widget */*w*/, cairo_t *cr)
}
inline float
power_to_dB(float a)
{
return 10.0 * log10f(a);
}
void
PluginEqGui::plot_impulse_amplitude(Gtk::Widget *w, cairo_t *cr)
{

View File

@ -79,10 +79,9 @@ private:
void plot_signal_amplitude_difference (Gtk::Widget *,cairo_t *);
void update_pointer_info(float, float);
void update_pointer_info(float);
bool analysis_area_mouseover(GdkEventMotion *);
bool analysis_area_mouseexit(GdkEventCrossing *);
bool analysis_area_mousedown(GdkEventButton *);
// Helpers
bool timeout_callback ();
@ -123,6 +122,8 @@ private:
Gtk::DrawingArea *_analysis_area;
cairo_surface_t *_analysis_scale_surface;
Gtk::Label *_pointer_info;
int _pointer_in_area_xpos;
int _pointer_in_area_freq;
// dB scale selection:
class dBSelectionColumns : public Gtk::TreeModel::ColumnRecord