[SCM] calf/master: + "Bang notation" for instant plugin connection on command-line ("calfjackhost monosynth ! reverb !" creates a chain: monosynth->reverb->sys output) + Process size for plugins restricted to some predefined value (256 samples for now, will see in the future), only for LADSPA/DSSI for now + New plugin (vintagedelay), requested by gordonjcp (also provided lots of comments, design suggestions and proposed filter frequencies to use) + Fixed typo in organ parameter (the whole rotary speaker thing will probably get dumped and replaced by separate plugin anyway) + Fixed label positioning in horizontal fader (refactoring bug)
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:36:47 UTC 2013
The following commit has been merged in the master branch:
commit da3ce7ba104fd236443777036dea98e6be770cc9
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Fri Dec 21 23:14:43 2007 +0000
+ "Bang notation" for instant plugin connection on command-line ("calfjackhost monosynth ! reverb !" creates a chain: monosynth->reverb->sys output)
+ Process size for plugins restricted to some predefined value (256 samples for now, will see in the future), only for LADSPA/DSSI for now
+ New plugin (vintagedelay), requested by gordonjcp (also provided lots of comments, design suggestions and proposed filter frequencies to use)
+ Fixed typo in organ parameter (the whole rotary speaker thing will probably get dumped and replaced by separate plugin anyway)
+ Fixed label positioning in horizontal fader (refactoring bug)
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@32 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/src/calf/giface.h b/src/calf/giface.h
index 65390aa..aa8b423 100644
--- a/src/calf/giface.h
+++ b/src/calf/giface.h
@@ -40,6 +40,10 @@
namespace synth {
+enum {
+ MAX_SAMPLE_RUN = 256
+};
+
enum parameter_flags
{
PF_TYPEMASK = 0x000F,
@@ -77,6 +81,7 @@ enum parameter_flags
PF_UNIT_MSEC = 0x05000000,
PF_UNIT_CENTS = 0x06000000,
PF_UNIT_SEMITONES = 0x07000000,
+ PF_UNIT_BPM = 0x08000000,
};
struct parameter_properties
@@ -282,8 +287,18 @@ struct ladspa_wrapper
static void cb_run(LADSPA_Handle Instance, unsigned long SampleCount) {
Module *const mod = (Module *)Instance;
mod->params_changed();
- uint32_t out_mask = mod->process(0, SampleCount, -1, -1);
- zero_by_mask(mod, out_mask, 0, SampleCount);
+ process_slice(mod, 0, SampleCount);
+ }
+
+ static inline void process_slice(Module *mod, uint32_t offset, uint32_t end)
+ {
+ while(offset < end)
+ {
+ uint32_t newend = std::min(offset + MAX_SAMPLE_RUN, end);
+ uint32_t out_mask = mod->process(offset, newend - offset, -1, -1);
+ zero_by_mask(mod, out_mask, offset, newend - offset);
+ offset = newend;
+ }
}
#if USE_DSSI
@@ -296,18 +311,13 @@ struct ladspa_wrapper
for (uint32_t e = 0; e < EventCount; e++)
{
uint32_t timestamp = Events[e].time.tick;
- if (timestamp != offset) {
- uint32_t out_mask = mod->process(offset, timestamp - offset, -1, -1);
- zero_by_mask(mod, out_mask, offset, timestamp - offset);
- }
+ if (timestamp != offset)
+ process_slice(mod, offset, timestamp);
process_dssi_event(mod, Events[e]);
offset = timestamp;
}
if (offset != SampleCount)
- {
- uint32_t out_mask = mod->process(offset, SampleCount - offset, -1, -1);
- zero_by_mask(mod, out_mask, offset, SampleCount - offset);
- }
+ process_slice(mod, offset, SampleCount);
}
static char *cb_configure(LADSPA_Handle Instance,
diff --git a/src/calf/jackhost.h b/src/calf/jackhost.h
index 17f1f3b..e87e0eb 100644
--- a/src/calf/jackhost.h
+++ b/src/calf/jackhost.h
@@ -77,6 +77,12 @@ public:
jack_deactivate(client);
}
+ void connect(const std::string &p1, const std::string &p2)
+ {
+ if (jack_connect(client, p1.c_str(), p2.c_str()) != 0)
+ throw audio_exception(("Could not connect ports "+p1+" and "+p2).c_str());
+ }
+
void close()
{
jack_client_close(client);
@@ -92,12 +98,14 @@ public:
struct port {
jack_port_t *handle;
float *data;
+ std::string name;
port() : handle(NULL), data(NULL) {}
~port() { }
};
jack_client *client;
bool changed;
port midi_port;
+ std::string name;
virtual int get_input_count()=0;
virtual int get_output_count()=0;
virtual port *get_inputs()=0;
@@ -141,16 +149,19 @@ public:
int in_count = get_input_count(), out_count = get_output_count();
for (int i=0; i<in_count; i++) {
sprintf(buf, client->input_name.c_str(), client->input_nr++);
+ inputs[i].name = buf;
inputs[i].handle = jack_port_register(client->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
inputs[i].data = NULL;
}
for (int i=0; i<out_count; i++) {
sprintf(buf, client->output_name.c_str(), client->output_nr++);
+ outputs[i].name = buf;
outputs[i].handle = jack_port_register(client->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0);
outputs[i].data = NULL;
}
if (get_midi()) {
sprintf(buf, client->midi_name.c_str(), client->midi_nr++);
+ midi_port.name = buf;
midi_port.handle = jack_port_register(client->client, buf, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
}
}
diff --git a/src/calf/modules.h b/src/calf/modules.h
index 15ceaf9..6a20e3e 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -296,6 +296,106 @@ public:
}
};
+class vintage_delay_audio_module: public null_audio_module
+{
+public:
+ // 1MB of delay memory per channel... uh, RAM is cheap
+ enum { MAX_DELAY = 262144, ADDR_MASK = MAX_DELAY - 1 };
+ enum { par_bpm, par_divide, par_time_l, par_time_r, par_feedback, par_amount, par_mixmode, par_medium, param_count };
+ enum { in_count = 2, out_count = 2, rt_capable = true, support_midi = false };
+ float *ins[in_count];
+ float *outs[out_count];
+ float *params[param_count];
+ static const char *port_names[];
+ float buffers[2][MAX_DELAY];
+ int bufptr, deltime_l, deltime_r, mixmode, medium, old_medium;
+ float amt_left, amt_right, fb_left, fb_right;
+ dsp::biquad<float> biquad_left[2], biquad_right[2];
+
+ uint32_t srate;
+ static parameter_properties param_props[];
+
+ vintage_delay_audio_module()
+ {
+ old_medium = -1;
+ }
+
+ void params_changed()
+ {
+ float unit = 60.0 * srate / (*params[par_bpm] * *params[par_divide]);
+ deltime_l = dsp::fastf2i_drm(unit * *params[par_time_l]);
+ deltime_r = dsp::fastf2i_drm(unit * *params[par_time_r]);
+ amt_left = amt_right = *params[par_amount];
+ fb_left = fb_right = *params[par_feedback];
+ mixmode = dsp::fastf2i_drm(*params[par_mixmode]);
+ medium = dsp::fastf2i_drm(*params[par_medium]);
+ if (mixmode == 0)
+ fb_right = pow(fb_left, *params[par_time_r] / *params[par_time_l]);
+ if (medium != old_medium)
+ calc_filters();
+ }
+ void activate() {
+ bufptr = 0;
+ }
+ void deactivate() {
+ }
+ void set_sample_rate(uint32_t sr) {
+ srate = sr;
+ old_medium = -1;
+ params_changed();
+ }
+ void calc_filters()
+ {
+ // parameters are heavily influenced by gordonjcp and his tape delay unit
+ // although, don't blame him if it sounds bad - I've messed with them too :)
+ biquad_left[0].set_lp_rbj(6000, 0.707, srate);
+ biquad_left[1].set_bp_rbj(4500, 0.250, srate);
+ biquad_right[0].copy_coeffs(biquad_left[0]);
+ biquad_right[1].copy_coeffs(biquad_left[1]);
+ }
+ uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
+ uint32_t ostate = 3; // XXXKF optimize!
+ uint32_t end = offset + numsamples;
+ int v = mixmode ? 1 : 0;
+ int orig_bufptr = bufptr;
+ for(uint32_t i = offset; i < end; i++)
+ {
+ float in_left = buffers[v][(bufptr - deltime_l) & ADDR_MASK], in_right = buffers[1 - v][(bufptr - deltime_r) & ADDR_MASK], out_left, out_right, del_left, del_right;
+
+ out_left = ins[0][i] + in_left * amt_left;
+ out_right = ins[1][i] + in_right * amt_right;
+ del_left = ins[0][i] + in_left * fb_left;
+ del_right = ins[1][i] + in_right * fb_right;
+
+ outs[0][i] = out_left; outs[1][i] = out_right; buffers[0][bufptr] = del_left; buffers[1][bufptr] = del_right;
+ bufptr = (bufptr + 1) & (MAX_DELAY - 1);
+ }
+ if (medium > 0) {
+ bufptr = orig_bufptr;
+ if (medium == 2)
+ {
+ for(uint32_t i = offset; i < end; i++)
+ {
+ buffers[0][bufptr] = biquad_left[0].process_d2_lp(biquad_left[1].process_d2(buffers[0][bufptr]));
+ buffers[1][bufptr] = biquad_right[0].process_d2_lp(biquad_right[1].process_d2(buffers[1][bufptr]));
+ bufptr = (bufptr + 1) & (MAX_DELAY - 1);
+ }
+ biquad_left[0].sanitize_d2();biquad_right[0].sanitize_d2();
+ } else {
+ for(uint32_t i = offset; i < end; i++)
+ {
+ buffers[0][bufptr] = biquad_left[1].process_d2(buffers[0][bufptr]);
+ buffers[1][bufptr] = biquad_right[1].process_d2(buffers[1][bufptr]);
+ bufptr = (bufptr + 1) & (MAX_DELAY - 1);
+ }
+ }
+ biquad_left[1].sanitize_d2();biquad_right[1].sanitize_d2();
+
+ }
+ return ostate;
+ }
+};
+
extern std::string get_builtin_modules_rdf();
};
diff --git a/src/giface.cpp b/src/giface.cpp
index 26fbc4f..a58bb4d 100644
--- a/src/giface.cpp
+++ b/src/giface.cpp
@@ -110,6 +110,7 @@ std::string parameter_properties::to_string(float value) const
case PF_UNIT_MSEC: return string(buf) + " ms";
case PF_UNIT_CENTS: return string(buf) + " ct";
case PF_UNIT_SEMITONES: return string(buf) + "#";
+ case PF_UNIT_BPM: return string(buf) + " bpm";
}
return string(buf);
diff --git a/src/gui.cpp b/src/gui.cpp
index 45c720e..4067047 100644
--- a/src/gui.cpp
+++ b/src/gui.cpp
@@ -85,8 +85,6 @@ GtkWidget *hscale_param_control::create(plugin_gui *_gui, int _param_no)
gui = _gui;
param_no = _param_no;
- gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
-
widget = gtk_hscale_new_with_range (0, 1, 0.01);
gtk_signal_connect (GTK_OBJECT (widget), "value-changed", G_CALLBACK (hscale_value_changed), (gpointer)this);
gtk_signal_connect (GTK_OBJECT (widget), "format-value", G_CALLBACK (hscale_format_value), (gpointer)this);
@@ -255,6 +253,7 @@ GtkWidget *plugin_gui::create(plugin_ctl_iface *_plugin, const char *title)
#endif
else
{
+ gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
params[i] = new hscale_param_control();
widget = params[i]->create(this, i);
gtk_table_attach (GTK_TABLE (table), widget, 1, 3, trow, trow + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), GTK_SHRINK, 0, 0);
diff --git a/src/jackhost.cpp b/src/jackhost.cpp
index 9ca4034..3128499 100644
--- a/src/jackhost.cpp
+++ b/src/jackhost.cpp
@@ -19,6 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <set>
#include <getopt.h>
#include <stdint.h>
#include <stdlib.h>
@@ -54,6 +55,8 @@ jack_host_base *synth::create_jack_host(const char *effect_name)
return new jack_host<filter_audio_module>();
else if (!strcmp(effect_name, "monosynth"))
return new jack_host<monosynth_audio_module>();
+ else if (!strcmp(effect_name, "vintagedelay"))
+ return new jack_host<vintage_delay_audio_module>();
#ifdef ENABLE_EXPERIMENTAL
else if (!strcmp(effect_name, "organ"))
return new jack_host<organ_audio_module>();
@@ -105,8 +108,9 @@ int jack_client::do_jack_bufsize(jack_nframes_t numsamples, void *p)
int main(int argc, char *argv[])
{
vector<string> names;
- vector<jack_host_base *> hosts;
+ vector<jack_host_base *> plugins;
vector<plugin_gui_window *> guis;
+ set<int> chains;
gtk_init(&argc, &argv);
glade_init();
while(1) {
@@ -140,8 +144,13 @@ int main(int argc, char *argv[])
break;
}
}
- while(optind < argc)
- names.push_back(argv[optind++]);
+ while(optind < argc) {
+ if (!strcmp(argv[optind], "!")) {
+ chains.insert(names.size());
+ optind++;
+ } else
+ names.push_back(argv[optind++]);
+ }
if (!names.size()) {
print_help(argv);
return 0;
@@ -154,14 +163,15 @@ int main(int argc, char *argv[])
load_presets(PKGLIBDIR "/presets.xml");
client.open(client_name);
+ string cnp = string(client_name) + ":";
for (unsigned int i = 0; i < names.size(); i++) {
jack_host_base *jh = create_jack_host(names[i].c_str());
if (!jh) {
- #ifdef ENABLE_EXPERIMENTAL
- fprintf(stderr, "Unknown plugin name; allowed are: reverb, flanger, filter, monosynth, organ\n");
- #else
- fprintf(stderr, "Unknown plugin name; allowed are: reverb, flanger, filter, monosynth\n");
- #endif
+#ifdef ENABLE_EXPERIMENTAL
+ fprintf(stderr, "Unknown plugin name; allowed are: reverb, flanger, filter, vintagedelay, monosynth, organ\n");
+#else
+ fprintf(stderr, "Unknown plugin name; allowed are: reverb, flanger, filter, vintagedelay, monosynth\n");
+#endif
return 1;
}
jh->open(&client);
@@ -169,16 +179,52 @@ int main(int argc, char *argv[])
gui_win->create(jh, (string(client_name)+" - "+names[i]).c_str(), names[i].c_str());
gtk_signal_connect(GTK_OBJECT(gui_win->toplevel), "destroy", G_CALLBACK(destroy), NULL);
guis.push_back(gui_win);
- hosts.push_back(jh);
+ plugins.push_back(jh);
client.add(jh);
}
client.activate();
+ for (unsigned int i = 0; i < plugins.size(); i++) {
+ if (chains.count(i)) {
+ if (!i)
+ {
+ if (plugins[0]->get_output_count() < 2)
+ {
+ fprintf(stderr, "Cannot connect input to plugin %s - incompatible ports\n", plugins[0]->name.c_str());
+ } else {
+ client.connect("system:capture_1", cnp + plugins[0]->get_inputs()[0].name);
+ client.connect("system:capture_2", cnp + plugins[0]->get_inputs()[1].name);
+ }
+ }
+ else
+ {
+ if (plugins[i - 1]->get_output_count() < 2 || plugins[i]->get_input_count() < 2)
+ {
+ fprintf(stderr, "Cannot connect plugins %s and %s - incompatible ports\n", plugins[i - 1]->name.c_str(), plugins[i]->name.c_str());
+ }
+ else {
+ client.connect(cnp + plugins[i - 1]->get_outputs()[0].name, cnp + plugins[i]->get_inputs()[0].name);
+ client.connect(cnp + plugins[i - 1]->get_outputs()[1].name, cnp + plugins[i]->get_inputs()[1].name);
+ }
+ }
+ }
+ }
+ if (chains.count(plugins.size()) && plugins.size())
+ {
+ int last = plugins.size() - 1;
+ if (plugins[last]->get_output_count() < 2)
+ {
+ fprintf(stderr, "Cannot connect plugin %s to output - incompatible ports\n", plugins[last]->name.c_str());
+ } else {
+ client.connect(cnp + plugins[last]->get_outputs()[0].name, "system:playback_1");
+ client.connect(cnp + plugins[last]->get_outputs()[1].name, "system:playback_2");
+ }
+ }
gtk_main();
client.deactivate();
for (unsigned int i = 0; i < names.size(); i++) {
delete guis[i];
- hosts[i]->close();
- delete hosts[i];
+ plugins[i]->close();
+ delete plugins[i];
}
client.close();
diff --git a/src/modules.cpp b/src/modules.cpp
index 620567a..8921173 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -104,6 +104,38 @@ static synth::ladspa_wrapper<filter_audio_module> filter(filter_info);
#endif
////////////////////////////////////////////////////////////////////////////
+
+const char *vintage_delay_audio_module::port_names[] = {"In L", "In R", "Out L", "Out R"};
+
+const char *vintage_delay_mixmodes[] = {
+ "Stereo",
+ "Ping-Pong",
+};
+
+const char *vintage_delay_fbmodes[] = {
+ "Plain",
+ "Tape",
+ "Old Tape",
+};
+
+parameter_properties vintage_delay_audio_module::param_props[] = {
+ { 120, 30, 300, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_BPM, NULL, "bpm", "Tempo" },
+ { 4, 1, 16, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "subdiv", "Subdivide"},
+ { 3, 1, 16, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "time_l", "Time L"},
+ { 5, 1, 16, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "time_r", "Time R"},
+ { 0.5, 0, 1, 1.01, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "feedback", "Feedback" },
+ { 0.25, 0, 2, 1.1, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "amount", "Amount" },
+ { 1, 0, 1, 1.01, PF_ENUM | PF_CTL_COMBO, vintage_delay_mixmodes, "mix_mode", "Mix mode" },
+ { 1, 0, 2, 1.01, PF_ENUM | PF_CTL_COMBO, vintage_delay_fbmodes, "medium", "Medium" },
+};
+
+static synth::ladspa_info vintage_delay_info = { 0x847f, "vintage_delay", "Calf vintage Delay", "Krzysztof Foltman", copyright, "DelayPlugin" };
+
+#if USE_LADSPA
+static synth::ladspa_wrapper<vintage_delay_audio_module> vintage_delay(vintage_delay_info);
+#endif
+
+////////////////////////////////////////////////////////////////////////////
#ifdef ENABLE_EXPERIMENTAL
const char *organ_audio_module::port_names[] = {"Out L", "Out R"};
@@ -123,7 +155,7 @@ parameter_properties organ_audio_module::param_props[] = {
{ 0, 0, 1, 1.01, PF_FLOAT | PF_SCALE_QUAD | PF_CTL_FADER, NULL, "h16", "1'" },
{ 1, 0, 1, 1.01, PF_BOOL | PF_CTL_TOGGLE, NULL, "foldover", "Foldover" },
- { 1, 0, 2, 1.01, PF_ENUM | PF_CTL_COMBO, organ_percussion_mode_names, "perc mode", "Perc. mode" },
+ { 1, 0, 2, 1.01, PF_ENUM | PF_CTL_COMBO, organ_percussion_mode_names, "perc_mode", "Perc. mode" },
{ 3, 2, 3, 1.01, PF_ENUM | PF_CTL_COMBO, organ_percussion_harmonic_names, "perc_hrm", "Perc. harmonic" },
{ 1, 0, 4, 1.01, PF_ENUM | PF_CTL_COMBO, organ_vibrato_speed_names, "vib_speed", "Vibrato mode" },
@@ -202,6 +234,7 @@ const LADSPA_Descriptor *ladspa_descriptor(unsigned long Index)
case 0: return &::filter.descriptor;
case 1: return &::flanger.descriptor;
case 2: return &::reverb.descriptor;
+ case 3: return &::vintage_delay.descriptor;
default: return NULL;
}
}
@@ -218,8 +251,9 @@ const DSSI_Descriptor *dssi_descriptor(unsigned long Index)
case 1: return &::flanger.dssi_descriptor;
case 2: return &::reverb.dssi_descriptor;
case 3: return &::monosynth.dssi_descriptor;
+ case 4: return &::vintage_delay.dssi_descriptor;
#ifdef ENABLE_EXPERIMENTAL
- case 4: return &::organ.dssi_descriptor;
+ case 5: return &::organ.dssi_descriptor;
#endif
default: return NULL;
}
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list