35 Glib::RefPtr<Gtk::AccelGroup> accels,
int nchan) {
36 Glib::RefPtr<gx_gui::GxBuilder> bld = gx_gui::GxBuilder::create_from_file(
40 bld->find_widget(
"file_selector_box", w);
47 return new IRWindow(bld, jcp, icon, machine, accels, nchan);
54 void IRWindow::init_connect() {
55 builder->find_widget(
"iredit", wIredit);
57 &IRWindow::on_delay_changed));
59 &IRWindow::on_offset_changed));
61 &IRWindow::on_length_changed));
63 &IRWindow::on_max_scale_reached));
65 &IRWindow::on_min_scale_reached));
67 builder->find_widget(
"file_combo:rack_button", wcombo);
68 wcombo->signal_changed().connect(
69 sigc::mem_fun(*
this, &IRWindow::on_combo_changed));
70 wcombo->set_model(model);
72 builder->find_widget(
"dir_combo:rack_button", dircombo);
73 if (dircombo->is_visible()) {
74 Gtk::TreeModelColumnRecord rec;
75 Gtk::TreeModelColumn<std::string> fname_col;
77 Gtk::TreeModelColumn<Glib::ustring> dname_col;
79 Glib::RefPtr<Gtk::ListStore> st = Gtk::ListStore::create(rec);
80 std::vector<gx_system::FileName> dirs;
82 for (std::vector<gx_system::FileName>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
83 Gtk::TreeIter j = st->append();
84 j->set_value(0, i->displayname);
85 j->set_value(1, i->filename);
87 dircombo->set_model(st);
88 dircombo->signal_changed().connect(
89 sigc::mem_fun(*
this, &IRWindow::on_dircombo_changed));
93 builder->find_widget(
"left", wLeft);
94 wLeft->signal_toggled().connect(sigc::mem_fun(*
this, &IRWindow::on_left));
95 builder->find_widget(
"right", wRight);
96 wRight->signal_toggled().connect(sigc::mem_fun(*
this, &IRWindow::on_right));
97 builder->find_widget(
"sum", wSum);
98 wSum->set_active(
true);
99 wSum->signal_toggled().connect(sigc::mem_fun(*
this, &IRWindow::on_sum));
101 wLeft = wRight = wSum = 0;
104 builder->find_widget(
"log", wLog);
105 wLog->set_active(
true);
106 builder->find_widget(
"linear", wLinear);
107 wLinear->signal_toggled().connect(sigc::mem_fun(*
this, &IRWindow::on_linear));
109 builder->find_widget(
"delay:show_always", wDelay);
110 wDelay->signal_value_changed().connect(sigc::mem_fun(*
this,
111 &IRWindow::on_m_delay_changed));
112 builder->find_widget(
"offset:show_always", wOffset);
113 wOffset->signal_value_changed().connect(sigc::mem_fun(*
this,
114 &IRWindow::on_m_offset_changed));
115 builder->find_widget(
"irlength:show_always", wLength);
116 wLength->signal_value_changed().connect(sigc::mem_fun(*
this,
117 &IRWindow::on_m_length_changed));
118 builder->find_widget(
"delay_ms:show_always", wDelay_ms);
119 wDelay_ms->signal_value_changed().connect(sigc::mem_fun(*
this,
120 &IRWindow::on_ms_delay_changed));
121 builder->find_widget(
"offset_ms:show_always", wOffset_ms);
122 wOffset_ms->signal_value_changed().connect(sigc::mem_fun(*
this,
123 &IRWindow::on_ms_offset_changed));
124 builder->find_widget(
"irlength_ms:show_always", wLength_ms);
125 wLength_ms->signal_value_changed().connect(sigc::mem_fun(*
this,
126 &IRWindow::on_ms_length_changed));
129 builder->find_widget(
"delay_delta", wDelay_delta);
131 &IRWindow::on_delay_delta_format_value));
134 builder->find_widget(
"home", wHome);
135 wHome->signal_clicked().connect(sigc::mem_fun(*
this, &IRWindow::on_home));
136 builder->find_widget(
"jump_zoom_mark", wJump_zoom_mark);
137 wJump_zoom_mark->signal_clicked().connect(sigc::mem_fun(*
this,
138 &IRWindow::on_jump_zoom_mark));
139 builder->find_widget(
"incr", wIncr);
140 wIncr->signal_clicked().connect(sigc::mem_fun(*
this, &IRWindow::on_incr));
141 builder->find_widget(
"decr", wDecr);
142 wDecr->signal_clicked().connect(sigc::mem_fun(*
this, &IRWindow::on_decr));
144 builder->find_widget(
"reset_button", wReset);
145 wReset->signal_clicked().connect(sigc::mem_fun(*
this, &IRWindow::on_reset_clicked));
146 builder->find_widget(
"open_button", wOpen);
147 wOpen->signal_clicked().connect(sigc::mem_fun(*
this, &IRWindow::on_open));
149 builder->find_widget(
"apply_button", wApply);
150 wApply->signal_clicked().connect(sigc::mem_fun(*
this,
151 &IRWindow::on_apply_button_clicked));
153 builder->find_widget(
"cancel_button", wCancel);
154 wCancel->signal_clicked().connect(sigc::mem_fun(*
this,
155 &IRWindow::on_cancel_button_clicked));
156 builder->find_widget(
"ok_button", wOk);
157 wOk->signal_clicked().connect(sigc::mem_fun(*
this,
158 &IRWindow::on_ok_button_clicked));
160 builder->find_widget(
"gain_button", wGain_correction);
161 autogain_conn = wGain_correction->signal_toggled().connect(
162 sigc::mem_fun(*
this, &IRWindow::on_gain_button_toggled));
164 builder->find_widget(
"length", wSamples);
165 builder->find_widget(
"samplerate", wSampleRate);
166 builder->find_widget(
"format", wFormat);
167 builder->find_widget(
"channels", wChan);
168 builder->find_widget(
"filename", wFilename);
173 builder->find_widget(
"channelbox", wChannelbox);
176 builder->find_widget(
"help_button", button);
177 button->signal_clicked().connect(sigc::mem_fun(*
this, &IRWindow::on_help_clicked));
178 builder->find_widget(
"HelpIR", wHelp);
179 builder->find_widget(
"close_irhelp", button);
180 button->signal_clicked().connect(sigc::mem_fun(wHelp, &Gtk::Widget::hide));
182 builder->find_widget(
"preset_button", button);
183 button->signal_clicked().connect(
184 sigc::mem_fun(
this, &IRWindow::on_preset_popup_clicked));
186 gtk_window->signal_key_press_event().connect(
187 sigc::mem_fun(
this, &IRWindow::on_key_press_event));
192 Glib::RefPtr<Gtk::AccelGroup> accels,
int nchan_)
206 model(Gtk::TreeStore::create(columns)),
207 current_combo_dir() {
208 bld->get_toplevel(
"DisplayIR", gtk_window);
211 gtk_window->set_icon(icon);
212 gtk_window->add_accel_group(accels);
214 sigc::mem_fun(
this, &IRWindow::load_state));
216 sigc::mem_fun(
this, &IRWindow::on_enumerate));
219 file_changed(
"", 0, 0, 0,
"");
220 on_delay_changed(0, 0);
221 on_offset_changed(0, 0);
222 on_length_changed(0, 0);
225 IRWindow::~IRWindow() {
236 double value,
int fs) {
240 s2 = (value*1000.0)/fs;
250 void IRWindow::file_changed(Glib::ustring filename,
int rate,
int length,
251 int channels, Glib::ustring format) {
252 Glib::ustring s_rate, s_length, s_channels;
253 if (filename.empty()) {
254 filename =
"no file selected";
255 s_length = s_rate = format = s_channels =
"--";
258 wDelay->set_range(0, 5*rate);
259 wDelay_ms->set_range(0, 5*1000);
260 wOffset->set_range(0, length-1);
261 wOffset_ms->set_range(0, (length-1)*1000.0/rate);
262 wLength->set_range(0, length);
263 wLength_ms->set_range(0, (length)*1000.0/rate);
264 s_length = (boost::format(
"%1%") % length).str();
265 s_rate = (boost::format(
"%1%") % rate).str();
266 s_channels = (boost::format(
"%1%") % channels).str();
268 wSamples->set_text(s_length);
269 wSampleRate->set_text(s_rate);
270 wFormat->set_text(format);
271 wChan->set_text(s_channels);
273 wChannelbox->set_sensitive(channels >= 2);
275 wFilename->set_text(Glib::path_get_dirname(filename));
289 autogain_conn.block();
290 wGain_correction->set_active(jcs->
getGainCor());
291 autogain_conn.unblock();
293 reload_impresp_list();
296 Gainline IRWindow::gain0 = Gainline();
298 bool IRWindow::load_data(Glib::ustring f,
int offset,
int delay,
int length,
const Gainline& gain) {
300 int audio_type, audio_form, audio_rate;
302 if (!machine.
read_audio(filename, &audio_size, &audio_chan, &audio_type, &audio_form, &audio_rate, &buffer)) {
306 switch (audio_type) {
314 switch (audio_form) {
321 delete[] audio_buffer;
322 audio_buffer = buffer;
323 file_changed(filename, audio_rate, audio_size, audio_chan, enc);
327 wIredit->
set_state(audio_buffer, audio_chan, audio_size, audio_rate, offset, offset+length, delay-offset, gain);
329 wSum->set_active(
true);
331 wLog->set_active(
true);
335 double IRWindow::calc_normalized_gain(
int offset,
int length,
const Gainline& points) {
336 if (audio_chan == 0) {
340 unsigned int idx = 0;
341 double gp = 0.0, fct = 0.0;
343 while (points[idx].i < offset) {
345 assert(idx < points.size());
347 if (points[idx].i > offset) {
352 for (
int i = offset; i < offset+length; i++) {
353 if (idx+1 < points.size() && points[idx].i == i) {
356 double g = pow(10, gp + i*fct);
357 for (
int j = 0; j < audio_chan; j++) {
358 double v = audio_buffer[i*audio_chan+j] * g;
362 gain = sqrt(gain / audio_chan);
370 Gainline gainline = wIredit->
get_gain();
373 double gain = calc_normalized_gain(offset, length, gainline);
380 jc.
setGainCor(wGain_correction->get_active());
383 void IRWindow::save_state() {
393 void IRWindow::on_combo_changed() {
394 Gtk::TreeModel::iterator iter = wcombo->get_active();
396 Gtk::TreeModel::Row row = *iter;
398 std::string fname = row[columns.filename];
400 load_data(Glib::build_filename(current_combo_dir, fname));
407 void IRWindow::on_dircombo_changed() {
408 Gtk::TreeModel::iterator iter = dircombo->get_active();
411 iter->get_value(1, dir);
412 if (dir != current_combo_dir) {
418 void IRWindow::reload_impresp_list() {
421 path = getenv(
"HOME");
424 if (current_combo_dir == path) {
425 Gtk::TreeNodeChildren ch = model->children();
426 for (Gtk::TreeIter i = ch.begin(); i != ch.end(); ++i) {
427 if (i->get_value(columns.filename) == irfile) {
428 wcombo->set_active(i);
437 void IRWindow::on_enumerate(
const std::string& path,
const std::vector<gx_system::FileName>& l) {
438 if (current_combo_dir == path) {
441 current_combo_dir = path;
445 wcombo->unset_model();
446 model->set_sort_column(Gtk::TreeSortable::DEFAULT_UNSORTED_COLUMN_ID, Gtk::SORT_ASCENDING);
447 for (std::vector<gx_system::FileName>::const_iterator f = l.begin(); f != l.end(); ++f) {
448 Gtk::TreeIter i = model->append();
449 i->set_value(columns.displayname, f->displayname);
450 i->set_value(columns.filename, f->filename);
451 if (f->filename == irfile) {
455 model->set_sort_column(columns.displayname, Gtk::SORT_ASCENDING);
456 wcombo->set_model(model);
458 wcombo->set_active(j);
460 if (dircombo->is_visible()) {
461 Gtk::TreeNodeChildren ch = dircombo->get_model()->children();
462 for (Gtk::TreeIter di = ch.begin(); di != ch.end(); ++di) {
465 if (p == current_combo_dir) {
466 dircombo->set_active(di);
473 void IRWindow::on_linear() {
474 wIredit->
set_log(not wLinear->get_active());
477 void IRWindow::on_left() {
478 if (wLeft->get_active()) {
483 void IRWindow::on_right() {
484 if (wRight->get_active()) {
489 void IRWindow::on_sum() {
490 if (wSum->get_active()) {
495 void IRWindow::on_delay_changed(
int delay,
int fs) {
496 int d =
static_cast<int>(round(set_val(wDelay, wDelay_ms, delay, fs)));
502 void IRWindow::on_offset_changed(
int offset,
int fs) {
503 set_val(wOffset, wOffset_ms, offset, fs);
506 void IRWindow::on_length_changed(
int length,
int fs) {
507 set_val(wLength, wLength_ms, length, fs);
510 void IRWindow::on_reset_clicked() {
517 jc.
setGain(calc_normalized_gain(0, audio_size, gain0));
520 const char *params[] = {
"jconv.balance",
"jconv.diff_delay",
"jconv.gain",
"jconv.wet_dry", 0};
521 for (
const char **p = params; *p; ++p) {
528 Glib::ustring IRWindow::on_delay_delta_format_value(
double v) {
529 Glib::ustring s =
"";
533 }
else if (v > 0.0) {
537 Glib::ustring fmt = (boost::format(
"%%.%df%%s") % wDelay_delta->property_digits()).str();
538 return (boost::format(fmt) % v % s).str();
541 void IRWindow::on_max_scale_reached(
bool v) {
542 wIncr->set_sensitive(not v);
545 void IRWindow::on_min_scale_reached(
bool v) {
546 wDecr->set_sensitive(not v);
549 void IRWindow::on_open() {
550 static Glib::ustring hostname =
"localhost";
552 hostname = Gio::Resolver::get_default()->lookup_by_address
555 Glib::ustring title = hostname +
": Select Impulse Response";
556 Gtk::FileChooserDialog d(*gtk_window, title);
557 d.set_local_only(
false);
558 d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
559 d.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
560 d.add_shortcut_folder_uri(Glib::filename_to_uri(GX_SOUND_BPA_DIR, hostname));
561 d.add_shortcut_folder_uri(Glib::filename_to_uri(GX_SOUND_BPB_DIR, hostname));
562 d.add_shortcut_folder_uri(Glib::filename_to_uri(
string(getenv(
"HOME")) +
string(
"/.config/guitarix/IR"), hostname));
564 wav.set_name(
"WAV Files");
565 wav.add_mime_type(
"audio/x-wav");
566 wav.add_mime_type(
"audio/x-aiff");
568 Gtk::FileFilter audio;
569 audio.set_name(
"Audio Files");
570 audio.add_mime_type(
"audio/*");
573 all.add_pattern(
"*");
574 all.set_name(
"All Files");
576 if (!filename.empty()) {
577 d.set_uri(Glib::filename_to_uri (filename, hostname));
579 d.set_current_folder_uri(Glib::filename_to_uri (
string(getenv(
"HOME")) +
string(
"/"), hostname));
581 if (d.run() != Gtk::RESPONSE_OK) {
584 filename = Glib::filename_from_uri(d.get_uri(), hostname);
585 Gtk::RecentManager::Data data;
586 bool result_uncertain;
587 data.mime_type = Gio::content_type_guess(filename,
"", result_uncertain);
588 data.app_name =
"guitarix";
589 data.groups.push_back(
"impulseresponse");
590 Gtk::RecentManager::get_default()->add_item(d.get_uri(), data);
593 reload_impresp_list();
596 void IRWindow::on_home() {
600 void IRWindow::on_jump_zoom_mark() {
604 void IRWindow::on_decr() {
608 void IRWindow::on_incr() {
612 void IRWindow::on_m_delay_changed() {
616 void IRWindow::on_ms_delay_changed() {
620 void IRWindow::on_m_offset_changed() {
624 void IRWindow::on_ms_offset_changed() {
628 void IRWindow::on_m_length_changed() {
632 void IRWindow::on_ms_length_changed() {
636 void IRWindow::on_apply_button_clicked() {
641 void IRWindow::destroy_self() {
645 void IRWindow::on_window_hide() {
646 Glib::signal_idle().connect(
647 sigc::bind_return(sigc::mem_fun(*
this, &IRWindow::destroy_self),
false));
650 void IRWindow::on_cancel_button_clicked() {
654 void IRWindow::on_ok_button_clicked() {
659 void IRWindow::on_preset_popup_clicked() {
660 Glib::ustring name = Glib::path_get_basename(filename);
661 Glib::ustring::size_type n = name.find_last_of(
'.');
662 if (n != Glib::ustring::npos) {
669 void IRWindow::on_help_clicked() {
673 void IRWindow::on_gain_button_toggled() {
677 bool IRWindow::on_key_press_event(GdkEventKey *event) {
678 if (event->keyval ==
GDK_KEY_Escape && (event->state & Gtk::AccelGroup::get_default_mod_mask()) == 0) {
686 if (gtk_window->get_visible() && !(gtk_window->get_window()->get_state() & Gdk::WINDOW_STATE_ICONIFIED)) {
690 gtk_window->present();
Glib::SignalProxy2< void, int, int > signal_length_changed()
std::string get_builder_filepath(const std::string &basename) const
const Gainline & getGainline() const
virtual Parameter & get_parameter(const std::string &id)=0
void set_ir_data(float *p1, int p2, int p3, int p4)
bool set(const GxJConvSettings &val) const
Glib::SignalProxy2< void, int, int > signal_delay_changed()
std::string getFullIRPath() const
static IRWindow * create(const std::string &unit_id, Glib::RefPtr< Gdk::Pixbuf > icon, gx_engine::GxMachineBase &machine, Glib::RefPtr< Gtk::AccelGroup > accels, int nchan)
const std::string & getIRDir() const
virtual gx_jack::GxJack * get_jack()=0
sigc::signal< void, const GxJConvSettings * > & signal_changed()
const Glib::ustring & get_rpcaddress()
void decr_scale(double p1)
sigc::signal< void, const std::string &, std::vector< gx_system::FileName > > & signal_impresp_list()
std::string group_id() const
void cp_set_value(double value)
void setGainCor(bool gain)
Glib::SignalProxy1< void, bool > signal_scale_max_reached()
const std::string & getIRFile() const
void setFullIRPath(string name)
Glib::SignalProxy1< Glib::ustring, double > signal_format_value()
virtual gx_system::CmdlineOptions & get_options() const =0
Glib::SignalProxy1< void, bool > signal_scale_min_reached()
void setOffset(guint offs)
const GxJConvSettings & get_value() const
Glib::SignalProxy2< void, int, int > signal_offset_changed()
virtual void stdJSON_value()=0
void setGainline(const Gainline &gain)
void set_state(float *data, int chan, int data_len, int samplerate, int cutoff_low, int cutoff_high, int offset, const Gainline &gain)
virtual Plugin * pluginlist_lookup_plugin(const std::string &id) const =0
void incr_scale(double p1)
virtual void load_impresp_dirs(std::vector< gx_system::FileName > &dirs)=0
virtual void setJSON_value()=0
virtual bool read_audio(const std::string &filename, unsigned int *audio_size, int *audio_chan, int *audio_type, int *audio_form, int *audio_rate, float **buffer)=0
void setLength(guint leng)
virtual void reload_impresp_list(const std::string &path)=0
static void compute_interpolation(double &fct, double &gp, unsigned int &idx, const Gainline &points, int offset)