[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