From a56f3590a119c1ba8cd224ecbb4e1768926fd8ef Mon Sep 17 00:00:00 2001 From: terminatorX <> Date: Thu, 29 Jan 2004 22:41:00 +0000 Subject: [PATCH] Adding Dry/Wet controls - Alex --- ChangeLog | 6 +++ src/tX_global.h | 8 ++++ src/tX_mastergui.cc | 4 +- src/tX_vtt.cc | 16 ++----- src/tX_vttfx.cc | 108 ++++++++++++++++++++++++++++++++++++-------- src/tX_vttfx.h | 20 +++++++- src/tX_vttgui.cc | 48 ++++++++++++++++++-- 7 files changed, 173 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1a3fbcd..c008e39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,12 @@ All changes were done by me (Alexander K This is not a GNU-style ChangeLog but you sort of get the idea what was changed. +[v3.82] (pre-release) +- applied a fix from Juha Erkkila that makes tX work on + systems that don't have procfs mounted. +- added an optional Dry/Wet control for all LADSPA plugins. Simply click on the + plugin's label to add or remove the additional control. + [v3.81] - JACK doesn't seem to like SCHED_FIFO clients so I added a little test that will set SCHED_OTHER when jack output was selected. This will work for true diff --git a/src/tX_global.h b/src/tX_global.h index 121ca60..11a79f2 100644 --- a/src/tX_global.h +++ b/src/tX_global.h @@ -60,6 +60,14 @@ extern "C" { #define tX_error(fmt, args...); { fprintf(stderr, "* tX_error: "); fprintf(stderr, fmt , ## args); fprintf(stderr, "\n"); } #define tX_warning(fmt, args...); { fprintf(stderr, "+ tX_warning: "); fprintf(stderr, fmt , ## args); fprintf(stderr, "\n"); } +#ifdef MEM_DEBUG +#define tX_freemem(ptr, varname, comment); fprintf(stderr, "** free() [%s] at %08x. %s.\n", varname, ptr, comment); free(ptr); +#define tX_malloc(ptr, varname, comment, size, type); fprintf(stderr, "**[1/2] malloc() [%s]. Size: %i. %s.\n", varname, size, comment); ptr=type malloc(size); fprintf(stderr, "**[2/2] malloc() [%s]. ptr: %08x.\n", varname, ptr); +#else +#define tX_freemem(ptr, varname, comment); free(ptr); +#define tX_malloc(ptr, varname, comment, size, type); ptr=type malloc(size); +#endif + typedef enum { OSS =0, ALSA = 1, diff --git a/src/tX_mastergui.cc b/src/tX_mastergui.cc index 3895901..30bdbc2 100644 --- a/src/tX_mastergui.cc +++ b/src/tX_mastergui.cc @@ -222,8 +222,10 @@ void mg_update_status() gtk_label_set_text(GTK_LABEL(used_mem), buffer); } } + fclose(procfs); + } else { + gtk_label_set_text(GTK_LABEL(used_mem), ""); } - fclose(procfs); sprintf(buffer, "%i", vtt_class::vtt_amount); gtk_label_set_text(GTK_LABEL(no_of_vtts), buffer); diff --git a/src/tX_vtt.cc b/src/tX_vtt.cc index da78b37..44e1c11 100644 --- a/src/tX_vtt.cc +++ b/src/tX_vtt.cc @@ -39,14 +39,6 @@ #include #endif -#ifdef DEBUG -#define tX_freemem(ptr, varname, comment); fprintf(stderr, "** free() [%s] at %08x. %s.\n", varname, ptr, comment); free(ptr); -#define tX_malloc(ptr, varname, comment, size, type); fprintf(stderr, "**[1/2] malloc() [%s]. Size: %i. %s.\n", varname, size, comment); ptr=type malloc(size); fprintf(stderr, "**[2/2] malloc() [%s]. ptr: %08x.\n", varname, ptr); -#else -#define tX_freemem(ptr, varname, comment); free(ptr); -#define tX_malloc(ptr, varname, comment, size, type); ptr=type malloc(size); -#endif - #include "tX_loaddlg.h" #define USE_PREFETCH 1 @@ -514,12 +506,14 @@ void vtt_class :: ec_set_volume(f_prec volume) void vtt_class :: ec_clear_buffer() { - f_prec *ptr; +/* f_prec *ptr; for (ptr=ec_buffer; ptr<=ec_delay; ptr++) { *ptr=0.0; - } - ec_ptr=ec_buffer; + } */ + + memset(ec_buffer, 0, sizeof(ec_buffer)); + ec_ptr=ec_buffer; } void vtt_class :: render() diff --git a/src/tX_vttfx.cc b/src/tX_vttfx.cc index a34f3e5..08c1b6b 100644 --- a/src/tX_vttfx.cc +++ b/src/tX_vttfx.cc @@ -37,6 +37,8 @@ void vtt_fx :: reconnect_buffer() } vtt_fx :: ~vtt_fx() {} +void vtt_fx::toggle_drywet() {} +tX_drywet_type vtt_fx::has_drywet_feature() { return NOT_DRYWET_CAPABLE; } /******************* builtin fx ***/ @@ -50,6 +52,7 @@ void vtt_fx_lp :: save (FILE *rc, gzFile rz, char *indent) { tX_store("%s\n", indent); } + const char *vtt_fx_lp :: get_info_string() { return "TerminatorX built-in resonant lowpass filter."; @@ -71,7 +74,6 @@ const char *vtt_fx_ec :: get_info_string() return "TerminatorX built-in echo effect."; } - /******************** LADSPA fx ***/ /* short cut "cpd" macro to current port descriptor */ @@ -81,8 +83,12 @@ const char *vtt_fx_ec :: get_info_string() void vtt_fx_ladspa :: reconnect_buffer() { - plugin->getDescriptor()->connect_port(instance, input_port, myvtt->output_buffer); - plugin->getDescriptor()->connect_port(instance, output_port, myvtt->output_buffer); + plugin->getDescriptor()->connect_port(instance, input_port, myvtt->output_buffer); + if (wet_buffer) { + plugin->getDescriptor()->connect_port(instance, output_port, wet_buffer); + } else { + plugin->getDescriptor()->connect_port(instance, output_port, myvtt->output_buffer); + } } static void wrapstr(char *str) @@ -154,18 +160,8 @@ vtt_fx_ladspa :: vtt_fx_ladspa(LADSPA_Plugin *p, void *v) sp->set_vtt(vtt); controls.push_back(sp); - /* if (plugin->getDescriptor()->run_adding && plugin->getDescriptor()->set_run_adding_gain) { - sp = sp_outgain = new tX_seqpar_vttfx_float(); - sp->set_mapping_parameters(3, 0, 0.01, 1); - sprintf(buffer, "%s: Out Gain", plugin->getName()); - sp->set_name(buffer, "Out Gain"); - sp->set_vtt(vtt); - controls.push_back(sp); - } else { - sp_outgain = NULL; - } */ - - sp_outgain=NULL; + sp_wet=NULL; + wet_buffer=NULL; /* connecting ports */ for (port=0; port < plugin->getPortCount(); port++) { @@ -209,23 +205,47 @@ vtt_fx_ladspa :: vtt_fx_ladspa(LADSPA_Plugin *p, void *v) reconnect_buffer(); } +void vtt_fx_ladspa :: realloc_drywet() +{ + free_drywet(); + wet_buffer=(f_prec *) malloc(sizeof(float)*vtt_class::samples_in_mix_buffer); +} + +void vtt_fx_ladspa :: free_drywet() +{ + if (wet_buffer) { + free(wet_buffer); + wet_buffer=NULL; + } +} + void vtt_fx_ladspa :: activate() { + if (sp_wet) { + realloc_drywet(); + } + reconnect_buffer(); // we always have to reconnect... if (plugin->getDescriptor()->activate) plugin->getDescriptor()->activate(instance); } void vtt_fx_ladspa :: deactivate() { if (plugin->getDescriptor()->deactivate) plugin->getDescriptor()->deactivate(instance); + + free_drywet(); } void vtt_fx_ladspa :: run() { - if (sp_outgain) { - plugin->getDescriptor()->set_run_adding_gain(instance, sp_outgain->get_value()); - plugin->getDescriptor()->run_adding(instance, (vtt_class :: samples_in_mix_buffer)>>1); - } else { - plugin->getDescriptor()->run(instance, (vtt_class :: samples_in_mix_buffer)>>1); + plugin->getDescriptor()->run(instance, (vtt_class::samples_in_mix_buffer)>>1); + + if (wet_buffer) { + f_prec wet=sp_wet->get_value(); + f_prec dry=1.0-wet; + + for (int sample=0; sample < (vtt_class::samples_in_mix_buffer)>>1; sample++) { + myvtt->output_buffer[sample]=dry*myvtt->output_buffer[sample]+wet*wet_buffer[sample]; + } } } @@ -250,6 +270,8 @@ vtt_fx_ladspa :: ~vtt_fx_ladspa() delete (*sp); } plugin->getDescriptor()->cleanup(instance); + + if (wet_buffer) free(wet_buffer); delete panel; } @@ -262,6 +284,7 @@ void vtt_fx_ladspa :: save (FILE *rc, gzFile rz, char *indent) { strcat (indent, "\t"); store_int("ladspa_id", ID); + store_bool("has_drywet", (sp_wet!=NULL)); for (sp=controls.begin(); sp!=controls.end(); sp++) { store_float_sp("param", (*sp)->get_value(), (*(*sp))); @@ -279,6 +302,7 @@ void vtt_fx_ladspa :: load(xmlDocPtr doc, xmlNodePtr node) { list :: iterator sp=controls.begin(); int elementFound; double val; + bool bdummy; for (xmlNodePtr cur=node->xmlChildrenNode; cur!=NULL; cur=cur->next) { if (cur->type == XML_ELEMENT_NODE) { @@ -286,6 +310,7 @@ void vtt_fx_ladspa :: load(xmlDocPtr doc, xmlNodePtr node) { restore_int("ladspa_id", dummy); restore_bool("panel_hidden", hidden); + restore_bool_ac("has_drywet", bdummy, add_drywet()); if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "param")==0)) { val=0; @@ -309,3 +334,46 @@ void vtt_fx_ladspa :: load(xmlDocPtr doc, xmlNodePtr node) { panel->hide(hidden); } + +void vtt_fx_ladspa :: toggle_drywet() { + if (sp_wet) { + remove_drywet(); + } else { + add_drywet(); + } +} + +void vtt_fx_ladspa :: add_drywet() { + char buffer[1024]; + + sp_wet=new tX_seqpar_vttfx_float(); + sp_wet->set_mapping_parameters(1.0, 0, 0.01, 1); + sprintf(buffer, "%s: Dry/Wet", plugin->getLabel()); + sp_wet->set_name(buffer, "Dry/Wet"); + sp_wet->set_vtt(vtt); + panel->add_client_widget(sp_wet->get_widget()); + + pthread_mutex_lock(&vtt_class::render_lock); + controls.push_back(sp_wet); + deactivate(); + activate(); + pthread_mutex_unlock(&vtt_class::render_lock); +} + +void vtt_fx_ladspa :: remove_drywet() { + pthread_mutex_lock(&vtt_class::render_lock); + deactivate(); + + controls.remove(sp_wet); + delete sp_wet; + sp_wet=NULL; + + activate(); + pthread_mutex_unlock(&vtt_class::render_lock); +} + +tX_drywet_type vtt_fx_ladspa::has_drywet_feature() +{ + if (sp_wet) return DRYWET_ACTIVE; + else return DRYWET_AVAILABLE; +} diff --git a/src/tX_vttfx.h b/src/tX_vttfx.h index c0d22c3..3db5cdc 100644 --- a/src/tX_vttfx.h +++ b/src/tX_vttfx.h @@ -43,6 +43,12 @@ /* abstract super class vtt_fx */ +typedef enum { + NOT_DRYWET_CAPABLE, + DRYWET_AVAILABLE, + DRYWET_ACTIVE +} tX_drywet_type; + class vtt_fx { protected: @@ -61,6 +67,8 @@ class vtt_fx virtual void run()=NULL; virtual int isEnabled()=NULL; virtual void reconnect_buffer(); + virtual void toggle_drywet(); + virtual tX_drywet_type has_drywet_feature(); virtual const char *get_info_string()=NULL; @@ -111,7 +119,8 @@ class vtt_fx_ladspa : public vtt_fx list controls; private: tX_seqpar_vttfx *sp_enable; - tX_seqpar_vttfx *sp_outgain; + tX_seqpar_vttfx *sp_wet; + f_prec *wet_buffer; int input_port, output_port; LADSPA_Handle *instance; LADSPA_Plugin *plugin; @@ -126,7 +135,14 @@ class vtt_fx_ladspa : public vtt_fx virtual void run(); virtual int isEnabled(); virtual void reconnect_buffer(); - virtual const char *get_info_string(); + virtual const char *get_info_string(); + void realloc_drywet(); + void free_drywet(); + virtual void toggle_drywet(); + void add_drywet(); + void remove_drywet(); + virtual tX_drywet_type has_drywet_feature(); + virtual void save(FILE *rc, gzFile rz, char *indent); #ifdef ENABLE_TX_LEGACY virtual void load(FILE *); diff --git a/src/tX_vttgui.cc b/src/tX_vttgui.cc index e093c88..b0a0eab 100644 --- a/src/tX_vttgui.cc +++ b/src/tX_vttgui.cc @@ -743,7 +743,9 @@ void gui_connect_signals(vtt_class *vtt) G_CALLBACK(drop_file), (void *) vtt); } - + +void vg_show_fx_menu(GtkWidget *, vtt_fx *effect); + void build_vtt_gui(vtt_class *vtt) { GtkWidget *tempbox; @@ -935,6 +937,7 @@ void build_vtt_gui(vtt_class *vtt) /* Lowpass Panel */ p=new tX_panel("Lowpass", g->control_subbox); + g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", G_CALLBACK(vg_show_fx_menu), vtt->lp_fx); g->lp_panel=p; g->lp_enable=gtk_check_button_new_with_label("Enable"); @@ -966,6 +969,7 @@ void build_vtt_gui(vtt_class *vtt) /* Echo Panel */ p=new tX_panel("Echo", g->control_subbox); + g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", G_CALLBACK(vg_show_fx_menu), vtt->ec_fx); g->ec_panel=p; p->add_client_widget(vg_create_fx_bar(vtt, vtt->ec_fx, 0)); @@ -1170,6 +1174,44 @@ void vg_show_fx_info(GtkWidget *wid, vtt_fx *effect) tx_l_note(effect->get_info_string()); } +void vg_toggle_drywet(GtkWidget *wid, vtt_fx *effect) +{ + effect->toggle_drywet(); +} + +void vg_show_fx_menu(GtkWidget *wid, vtt_fx *effect) +{ + GtkWidget *menu=gtk_menu_new(); + GtkWidget *item=gtk_menu_item_new_with_label("Show Info"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_set_sensitive(item, (effect->has_drywet_feature()!=NOT_DRYWET_CAPABLE)); + gtk_widget_show(item); + g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_show_fx_info), effect); + + switch (effect->has_drywet_feature()) { + case (NOT_DRYWET_CAPABLE): + item=gtk_menu_item_new_with_label("Add Dry/Wet Control"); + gtk_widget_set_sensitive(item, FALSE); + break; + case (DRYWET_ACTIVE): + item=gtk_menu_item_new_with_label("Remove Dry/Wet Control"); + break; + case (DRYWET_AVAILABLE): + item=gtk_menu_item_new_with_label("Add Dry/Wet Control"); + break; + } + + g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_toggle_drywet), effect); + + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show(item); + + gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0); + + /* gtk+ is really waiting for this.. */ + g_signal_emit_by_name(G_OBJECT(wid), "released", effect); +} + void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin) { char buffer[1024]; @@ -1197,8 +1239,8 @@ void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plug p->add_client_widget((*sp)->get_widget()); } - g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", (GtkSignalFunc) vg_show_fx_info, (void *) effect); - gui_set_tooltip(p->get_labelbutton(), "Click here to learn more about this plugin."); + g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", (GtkSignalFunc) vg_show_fx_menu, (void *) effect); + gui_set_tooltip(p->get_labelbutton(), "Click here for menu"); effect->set_panel_widget(p->get_widget()); effect->set_panel(p); -- 2.25.4