[SCM] calf/master: + Removed configure script and other autogenerated files + Added preliminary jack MIDI support (no support in effects so far) + Started a new plugin - monosynth

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:36:42 UTC 2013


The following commit has been merged in the master branch:
commit a48d78df5965b3fc595c6eb375cbc6ac10b21371
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Fri Dec 7 22:01:42 2007 +0000

    + Removed configure script and other autogenerated files
    + Added preliminary jack MIDI support (no support in effects so far)
    + Started a new plugin - monosynth
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@7 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/configure.in b/configure.in
index 99c48a4..04c52a0 100644
--- a/configure.in
+++ b/configure.in
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT([calf],[0.0.5],[wdev at foltman.com])
+AC_INIT([calf],[0.0.6],[wdev at foltman.com])
 AC_CONFIG_SRCDIR([config.h.in])
 AC_CONFIG_HEADER([config.h])
 
diff --git a/src/benchmark.cpp b/src/benchmark.cpp
index 1ac2dee..edc1eea 100644
--- a/src/benchmark.cpp
+++ b/src/benchmark.cpp
@@ -1,3 +1,22 @@
+/* Calf DSP Library
+ * Benchmark for selected parts of the library.
+ * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
 #include <getopt.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -248,7 +267,7 @@ public:
     void run()
     {
         effect.params_changed();
-        effect.process(bufsize, 3, 3);
+        effect.process(0, bufsize, 3, 3);
     }
     void cleanup()
     {
diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am
index ae715da..7f98730 100644
--- a/src/calf/Makefile.am
+++ b/src/calf/Makefile.am
@@ -1,3 +1,3 @@
 calfdir = $(includedir)/calf
 
-calf_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h delay.h fixed_point.h giface.h inertia.h modules.h modules_dev.h onepole.h primitives.h wave.h
+calf_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h delay.h fixed_point.h giface.h inertia.h jackhost.h modules.h modules_dev.h onepole.h primitives.h wave.h
diff --git a/src/calf/biquad.h b/src/calf/biquad.h
index 2b747fb..ae26b94 100644
--- a/src/calf/biquad.h
+++ b/src/calf/biquad.h
@@ -44,6 +44,11 @@ public:
     T w1, w2;
     // filter coefficients
     Coeff a0, a1, a2, b1, b2;
+
+    biquad()
+    {
+        reset();
+    }
     
     /** Lowpass filter based on Robert Bristow-Johnson's equations
      * Perhaps every synth code that doesn't use SVF uses these
diff --git a/src/calf/buffer.h b/src/calf/buffer.h
index b2a2fba..943317b 100644
--- a/src/calf/buffer.h
+++ b/src/calf/buffer.h
@@ -60,14 +60,6 @@ void fill(T *data, int size, T value) {
         *data++ = value;
 }
 
-template<class T>
-void zero(T *data, unsigned int size) {
-    T value;
-    dsp::zero(value);
-    for (unsigned int i=0; i<size; i++)
-        *data++ = value;
-}
-
 template<class T, class U>
 void copy(T *dest, U *src, int size, T scale = 1, T add = 0) {
     for (int i=0; i<size; i++) 
diff --git a/src/calf/giface.h b/src/calf/giface.h
index 84dc4e1..5597f2a 100644
--- a/src/calf/giface.h
+++ b/src/calf/giface.h
@@ -1,5 +1,6 @@
 /* Calf DSP Library
- * API wrappers for Linux audio standards
+ * API wrappers for Linux audio standards (apart from JACK, which is
+ * a separate file now!)
  *
  * Copyright (C) 2007 Krzysztof Foltman
  *
@@ -18,8 +19,8 @@
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-#ifndef __GIFACE_H
-#define __GIFACE_H
+#ifndef __CALF_GIFACE_H
+#define __CALF_GIFACE_H
 
 #include <stdint.h>
 #include <stdlib.h>
@@ -28,9 +29,11 @@
 #endif
 #if USE_JACK
 #include <jack/jack.h>
+#include <jack/midiport.h>
 #endif
 #include <exception>
 #include <string>
+#include "primitives.h"
 
 namespace synth {
 
@@ -68,6 +71,7 @@ enum parameter_flags
   PF_UNIT_HZ = 0x03000000,
   PF_UNIT_SEC = 0x04000000,
   PF_UNIT_MSEC = 0x05000000,
+  PF_UNIT_CENTS = 0x06000000,
 };
 
 struct parameter_properties
@@ -224,7 +228,7 @@ 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(SampleCount, -1, -1);
+        uint32_t out_mask = mod->process(0, SampleCount, -1, -1);
         for (int i=0; i<Module::out_count; i++) {
           if ((out_mask & (1 << i)) == 0) {
             if (mod->outs[i])
@@ -261,176 +265,6 @@ public:
     virtual ~audio_exception() throw () {}
 };
 
-#if USE_JACK
-
-class jack_host_base {
-public:
-    typedef int (*process_func)(jack_nframes_t nframes, void *p);
-    struct port {
-        jack_port_t *handle;
-        float *data;
-        port() : handle(NULL), data(NULL) {}
-        ~port() { }
-    };
-    jack_client_t *client;
-    jack_status_t status;
-    int sample_rate;
-    bool changed;
-    virtual int get_input_count()=0;
-    virtual int get_output_count()=0;
-    virtual int get_param_count()=0;
-    virtual port *get_inputs()=0;
-    virtual port *get_outputs()=0;
-    virtual float *get_params()=0;
-    virtual void init_module()=0;
-    virtual void cache_ports()=0;
-    virtual process_func get_process_func()=0;
-    virtual const char ** get_param_names()=0;
-    virtual parameter_properties* get_param_props()=0;
-    
-    jack_host_base() {
-        client = NULL;
-        sample_rate = 0;
-        changed = true;
-    }
-    
-    void set_params(const float *params) {
-        memcpy(get_params(), params, get_param_count() * sizeof(float));
-        changed = true;
-    }
-
-    void set_params() {
-        changed = true;
-    }
-    
-    void open(const char *client_name, const char *in_prefix, const char *out_prefix)
-    {
-        client = jack_client_open(client_name, JackNullOption, &status);
-        
-        if (!client)
-            throw audio_exception("Could not initialize Jack subsystem");
-        
-        sample_rate = jack_get_sample_rate(client);
-        
-        create_ports(in_prefix, out_prefix);
-        
-        cache_ports();
-        
-        jack_set_process_callback(client, get_process_func(), this);
-        jack_set_buffer_size_callback(client, do_jack_bufsize, this);
-
-        init_module();
-        changed = false;
-
-        jack_activate(client);        
-    }
-    
-    virtual void create_ports(const char *in_prefix, const char *out_prefix) {
-        char buf[32];
-        port *inputs = get_inputs();
-        port *outputs = get_outputs();
-        int in_count = get_input_count(), out_count = get_output_count();
-        for (int i=0; i<in_count; i++) {
-            sprintf(buf, "%s%d", in_prefix, i+1);
-            inputs[i].handle = jack_port_register(client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
-            inputs[i].data = NULL;
-        }
-        for (int i=0; i<out_count; i++) {
-            sprintf(buf, "%s%d", out_prefix, i+1);
-            outputs[i].handle = jack_port_register(client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0);
-            outputs[i].data = NULL;
-        }
-    }
-    
-    static int do_jack_bufsize(jack_nframes_t numsamples, void *p) {
-        jack_host_base *app = (jack_host_base *)p;
-        app->cache_ports();
-        return 0;
-    }
-    
-    void close() {
-        jack_client_close(client);
-        client = NULL;
-        port *inputs = get_inputs(), *outputs = get_outputs();
-        int input_count = get_input_count(), output_count = get_output_count();
-        for (int i = 0; i < input_count; i++)
-            inputs[i].data = NULL;
-        for (int i = 0; i < output_count; i++)
-            outputs[i].data = NULL;
-    }
-    
-    virtual ~jack_host_base() {
-        if (client)
-            close();
-    }
-};
-
-template<class Module>
-class jack_host: public jack_host_base {
-public:
-    Module module;
-    port inputs[Module::in_count], outputs[Module::out_count];
-    float params[Module::param_count];
-    
-    jack_host()
-    {
-        for (int i = 0; i < Module::param_count; i++) {
-            module.params[i] = &params[i];
-            params[i] = Module::param_props[i].def_value;
-        }
-    }
-    
-    virtual void init_module() {
-        module.set_sample_rate(sample_rate);
-        module.params_changed();
-    }
-    
-    static int do_jack_process(jack_nframes_t nframes, void *p) {
-        jack_host *host = (jack_host *)p;
-        Module *module = &host->module;
-        for (int i=0; i<Module::in_count; i++) {
-            module->ins[i] = host->inputs[i].data = (float *)jack_port_get_buffer(host->inputs[i].handle, 0);
-        }
-        if (host->changed) {
-            module->params_changed();
-            host->changed = false;
-        }
-
-        int mask = module->process(nframes, -1, -1);
-        for (int i = 0; i < Module::out_count; i++) {
-            // zero unfilled outputs
-            if (!(mask & (1 << i))) {
-                memset(module->outs[i], 0, sizeof(float) * nframes);
-            }
-        }
-        return 0;
-    }
-    
-    void cache_ports()
-    {
-        for (int i=0; i<Module::out_count; i++) {
-            module.outs[i] = outputs[i].data = (float *)jack_port_get_buffer(outputs[i].handle, 0);
-        }
-    }
-    
-    virtual void zero_io() {
-        memset(inputs, 0, sizeof(inputs));
-        memset(outputs, 0, sizeof(outputs));
-    }
-    
-    virtual port *get_inputs() { return inputs; }
-    virtual port *get_outputs() { return outputs; }
-    virtual float *get_params() { return params; }
-    virtual int get_input_count() { return Module::in_count; }
-    virtual int get_output_count() { return Module::out_count; }
-    virtual int get_param_count() { return Module::param_count; }
-    virtual process_func get_process_func() { return do_jack_process; }
-    virtual const char ** get_param_names() { return Module::param_names; }
-    virtual parameter_properties* get_param_props() { return Module::param_props; }
-};
-
-#endif
-
 };
 
 #endif
diff --git a/src/calf/jackhost.h b/src/calf/jackhost.h
new file mode 100644
index 0000000..d10ab9a
--- /dev/null
+++ b/src/calf/jackhost.h
@@ -0,0 +1,224 @@
+/* Calf DSP Library
+ * API wrapper for JACK Audio Connection Kit
+ *
+ * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __CALF_JACKHOST_H
+#define __CALF_JACKHOST_H
+
+#if USE_JACK
+
+namespace synth {
+
+class jack_host_base {
+public:
+    typedef int (*process_func)(jack_nframes_t nframes, void *p);
+    struct port {
+        jack_port_t *handle;
+        float *data;
+        port() : handle(NULL), data(NULL) {}
+        ~port() { }
+    };
+    jack_client_t *client;
+    jack_status_t status;
+    int sample_rate;
+    bool changed;
+    port midi_port;
+    virtual int get_input_count()=0;
+    virtual int get_output_count()=0;
+    virtual int get_param_count()=0;
+    virtual port *get_inputs()=0;
+    virtual port *get_outputs()=0;
+    virtual float *get_params()=0;
+    virtual void init_module()=0;
+    virtual void cache_ports()=0;
+    virtual process_func get_process_func()=0;
+    virtual const char ** get_param_names()=0;
+    virtual parameter_properties* get_param_props()=0;
+    virtual bool get_midi()=0;
+    
+    jack_host_base() {
+        client = NULL;
+        sample_rate = 0;
+        changed = true;
+    }
+    
+    void set_params(const float *params) {
+        memcpy(get_params(), params, get_param_count() * sizeof(float));
+        changed = true;
+    }
+
+    void set_params() {
+        changed = true;
+    }
+    
+    void open(const char *client_name, const char *in_prefix, const char *out_prefix, const char *midi_name)
+    {
+        client = jack_client_open(client_name, JackNullOption, &status);
+        
+        if (!client)
+            throw audio_exception("Could not initialize Jack subsystem");
+        
+        sample_rate = jack_get_sample_rate(client);
+        
+        create_ports(in_prefix, out_prefix, midi_name);
+        
+        cache_ports();
+        
+        jack_set_process_callback(client, get_process_func(), this);
+        jack_set_buffer_size_callback(client, do_jack_bufsize, this);
+
+        init_module();
+        changed = false;
+
+        jack_activate(client);        
+    }
+    
+    virtual void create_ports(const char *in_prefix, const char *out_prefix, const char *midi_name) {
+        char buf[32];
+        port *inputs = get_inputs();
+        port *outputs = get_outputs();
+        int in_count = get_input_count(), out_count = get_output_count();
+        for (int i=0; i<in_count; i++) {
+            sprintf(buf, "%s%d", in_prefix, i+1);
+            inputs[i].handle = jack_port_register(client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
+            inputs[i].data = NULL;
+        }
+        for (int i=0; i<out_count; i++) {
+            sprintf(buf, "%s%d", out_prefix, i+1);
+            outputs[i].handle = jack_port_register(client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0);
+            outputs[i].data = NULL;
+        }
+        if (get_midi())
+            midi_port.handle = jack_port_register(client, midi_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
+    }
+    
+    static int do_jack_bufsize(jack_nframes_t numsamples, void *p) {
+        jack_host_base *app = (jack_host_base *)p;
+        app->cache_ports();
+        return 0;
+    }
+    
+    void close() {
+        jack_client_close(client);
+        client = NULL;
+        port *inputs = get_inputs(), *outputs = get_outputs();
+        int input_count = get_input_count(), output_count = get_output_count();
+        for (int i = 0; i < input_count; i++)
+            inputs[i].data = NULL;
+        for (int i = 0; i < output_count; i++)
+            outputs[i].data = NULL;
+    }
+    
+    virtual ~jack_host_base() {
+        if (client)
+            close();
+    }
+};
+
+template<class Module>
+class jack_host: public jack_host_base {
+public:
+    Module module;
+    port inputs[Module::in_count], outputs[Module::out_count];
+    float params[Module::param_count];
+    
+    jack_host()
+    {
+        for (int i = 0; i < Module::param_count; i++) {
+            module.params[i] = &params[i];
+            params[i] = Module::param_props[i].def_value;
+        }
+    }
+    
+    virtual void init_module() {
+        module.set_sample_rate(sample_rate);
+        module.params_changed();
+    }
+    
+    static int do_jack_process(jack_nframes_t nframes, void *p) {
+        jack_host *host = (jack_host *)p;
+        Module *module = &host->module;
+        for (int i=0; i<Module::in_count; i++) {
+            module->ins[i] = host->inputs[i].data = (float *)jack_port_get_buffer(host->inputs[i].handle, 0);
+        }
+        if (Module::support_midi)
+            host->midi_port.data = (float *)jack_port_get_buffer(host->midi_port.handle, 0);
+        if (host->changed) {
+            module->params_changed();
+            host->changed = false;
+        }
+
+        unsigned int time = 0;
+        unsigned int mask = 0;
+        if (Module::support_midi)
+        {
+            jack_midi_event_t event;
+            int count = jack_midi_get_event_count(host->midi_port.data);
+            for (int i = 0; i < count; i++)
+            {
+                jack_midi_event_get(&event, host->midi_port.data, i);
+                mask = module->process(time, event.time - time, -1, -1);
+                for (int i = 0; i < Module::out_count; i++) {
+                    if (!(mask & (1 << i)))
+                        dsp::zero(module->outs[i] + time, event.time - time);
+                }
+                
+                module->handle_event(event.buffer, event.size);
+                
+                time = event.time;
+            }
+        }
+        mask = module->process(time, nframes - time, -1, -1);
+        for (int i = 0; i < Module::out_count; i++) {
+            // zero unfilled outputs
+            if (!(mask & (1 << i)))
+                dsp::zero(module->outs[i] + time, nframes - time);
+        }
+        return 0;
+    }
+    
+    void cache_ports()
+    {
+        for (int i=0; i<Module::out_count; i++) {
+            module.outs[i] = outputs[i].data = (float *)jack_port_get_buffer(outputs[i].handle, 0);
+        }
+    }
+    
+    virtual void zero_io() {
+        memset(inputs, 0, sizeof(inputs));
+        memset(outputs, 0, sizeof(outputs));
+    }
+    
+    virtual port *get_inputs() { return inputs; }
+    virtual port *get_outputs() { return outputs; }
+    virtual float *get_params() { return params; }
+    virtual int get_input_count() { return Module::in_count; }
+    virtual int get_output_count() { return Module::out_count; }
+    virtual int get_param_count() { return Module::param_count; }
+    virtual process_func get_process_func() { return do_jack_process; }
+    virtual const char ** get_param_names() { return Module::param_names; }
+    virtual parameter_properties* get_param_props() { return Module::param_props; }
+    virtual bool get_midi() { return Module::support_midi; }
+};
+
+#endif
+
+};
+
+#endif
diff --git a/src/calf/modules.h b/src/calf/modules.h
index f1410a2..eb9e8cf 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -33,7 +33,7 @@ using namespace dsp;
 class amp_audio_module
 {
 public:
-    enum { in_count = 2, out_count = 2, param_count = 1, rt_capable = true };
+    enum { in_count = 2, out_count = 2, param_count = 1, support_midi = false, rt_capable = true };
     float *ins[2]; 
     float *outs[2];
     float *params[1];
@@ -50,11 +50,12 @@ public:
     }
     void deactivate() {
     }
-    uint32_t process(uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
         if (!inputs_mask)
             return 0;
         float gain = *params[0];
-        for (uint32_t i=0; i<nsamples; i++) {
+        numsamples += offset;
+        for (uint32_t i = offset; i < numsamples; i++) {
             outs[0][i] = ins[0][i] * gain;
             outs[1][i] = ins[1][i] * gain;
         }
@@ -75,7 +76,7 @@ class flanger_audio_module
 {
 public:
     enum { par_delay, par_depth, par_rate, par_fb, par_amount, param_count };
-    enum { in_count = 2, out_count = 2, rt_capable = true };
+    enum { in_count = 2, out_count = 2, support_midi = false, rt_capable = true };
     static const char *param_names[];
     dsp::simple_flanger<float, 2048> left, right;
     float *ins[in_count]; 
@@ -111,9 +112,9 @@ public:
     }
     void deactivate() {
     }
-    uint32_t process(uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
-        left.process(outs[0], ins[0], nsamples);
-        right.process(outs[1], ins[1], nsamples);
+    uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
+        left.process(outs[0] + offset, ins[0] + offset, nsamples);
+        right.process(outs[1] + offset, ins[1] + offset, nsamples);
         return outputs_mask; // XXXKF allow some delay after input going blank
     }
 };
@@ -122,7 +123,7 @@ class reverb_audio_module
 {
 public:    
     enum { par_decay, par_hfdamp, par_amount, param_count };
-    enum { in_count = 2, out_count = 2, rt_capable = true };
+    enum { in_count = 2, out_count = 2, support_midi = false, rt_capable = true };
     static const char *param_names[];
     dsp::reverb<float> reverb;
     uint32_t srate;
@@ -149,9 +150,10 @@ public:
         srate = sr;
         reverb.setup(sr);
     }
-    uint32_t process(uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
         float wet = *params[par_amount];
-        for (uint32_t i=0; i<nsamples; i++) {
+        numsamples += offset;
+        for (uint32_t i = offset; i < numsamples; i++) {
             float l = ins[0][i], r = ins[1][i];
             float rl = l, rr = r;
             reverb.process(rl, rr);
@@ -166,7 +168,7 @@ class filter_audio_module
 {
 public:    
     enum { par_cutoff, par_resonance, par_mode, par_inertia, param_count };
-    enum { in_count = 2, out_count = 2, rt_capable = true };
+    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];
@@ -285,9 +287,9 @@ public:
             filter[i].sanitize_d1();
         return filter[order - 1].empty_d1() ? 0 : inmask;
     }
-    uint32_t process(uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
         uint32_t ostate = 0;
-        uint32_t offset = 0;
+        numsamples += offset;
         while(offset < numsamples) {
             uint32_t numnow = numsamples - offset;
             // if inertia's inactive, we can calculate the whole buffer at once
diff --git a/src/calf/modules_dev.h b/src/calf/modules_dev.h
new file mode 100644
index 0000000..da2a2ea
--- /dev/null
+++ b/src/calf/modules_dev.h
@@ -0,0 +1,174 @@
+/* Calf DSP Library
+ * Prototype audio modules
+ *
+ * Copyright (C) 2001-2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __CALF_MODULES_DEV_H
+#define __CALF_MODULES_DEV_H
+
+#if ENABLE_EXPERIMENTAL
+
+#include <assert.h>
+#include "biquad.h"
+#include "audio_fx.h"
+#include "inertia.h"
+
+namespace synth {
+
+using namespace dsp;
+    
+/// Very simple, non-bandlimited saw oscillator. Should not be used for anything
+/// else than testing/prototyping.
+struct simple_oscillator
+{
+    uint32_t phase, phasedelta;
+    void reset()
+    {
+        phase = 0;
+    }
+    void set_freq(float freq, float sr)
+    {
+        phasedelta = (int)(freq * 65536.0 * 256.0 * 16.0 / sr) << 4;
+    }
+    inline float get()
+    {
+        float value = (phase >> 16 ) / 65535.0 - 0.5;
+        phase += phasedelta;
+        return value;
+    }
+};
+    
+/// Monosynth-in-making. Parameters may change at any point, so don't make songs with it!
+class monosynth_audio_module
+{
+public:
+    enum { par_cutoff, par_resonance, par_envmod, par_decay, param_count };
+    enum { in_count = 0, out_count = 2, support_midi = true, rt_capable = true };
+    enum { step_size = 64 };
+    static const char *param_names[];
+    float *ins[in_count]; 
+    float *outs[out_count];
+    float *params[param_count];
+    uint32_t srate, crate;
+    simple_oscillator osc1, osc2;
+    bool running;
+    int last_key;
+    
+    float buffer[step_size];
+    uint32_t output_pos;
+    biquad<float> filter;
+    biquad<float> filter2;
+    float cutoff, decay_factor;
+    int voice_age;
+    float odcr;
+    
+    static parameter_properties param_props[];
+    void set_sample_rate(uint32_t sr) {
+        srate = sr;
+        crate = sr / step_size;
+        odcr = (float)(1.0 / crate);
+    }
+    void handle_event(uint8_t *data, int len) {
+        switch(*data >> 4)
+        {
+        case 9:
+            if (data[2]) {
+                last_key = data[1];
+                float freq = 440 * pow(2.0, (last_key - 69) / 12.0);
+                osc1.set_freq(freq*0.995, srate);
+                osc2.set_freq(freq*1.005, srate);
+                if (!running)
+                {
+                    osc1.reset();
+                    osc2.reset();
+                    filter.reset();
+                    filter2.reset();
+                    cutoff = 16000;
+                    voice_age = 0;
+                    running = true;
+                }
+            }
+            // printf("note on %d %d\n", data[1], data[2]);
+            break;
+        case 8:
+            // printf("note off %d %d\n", data[1], data[2]);
+            if (data[1] == last_key)
+                running = false;
+            break;
+        }
+        default_handle_event(data, len, params, param_count);
+    }
+    void params_changed() {
+        decay_factor = odcr * 1000.0 / *params[par_decay];
+    }
+    void activate() {
+        running = false;
+        output_pos = 0;
+        filter.reset();
+        filter2.reset();
+    }
+    void deactivate() {
+    }
+    void calculate_step() {
+        float env = max(0.f, 1.f - voice_age * decay_factor);
+        cutoff = *params[par_cutoff] * pow(2.0f, env * *params[par_envmod] * (1.f / 1200.f));
+        if (cutoff < 33.f)
+            cutoff = 33.f;
+        if (cutoff > 16000.f)
+            cutoff = 16000.f;
+        filter.set_lp_rbj(cutoff, *params[par_resonance], srate);
+        filter2.copy_coeffs(filter);
+        for (uint32_t i = 0; i < step_size; i++) 
+        {
+            float wave = 0.2f * (osc1.get() + osc2.get());
+            wave = filter.process_d1(wave);
+            wave = filter2.process_d1(wave);
+            buffer[i] = dsp::clip(wave, -1.f, +1.f);
+        }
+
+        voice_age++;
+    }
+    uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
+        if (!running)
+            return 0;
+        uint32_t op = offset;
+        uint32_t op_end = offset + nsamples;
+        while(op < op_end) {
+            if (output_pos == 0)
+                calculate_step();
+            if(op < op_end) {
+                uint32_t ip = output_pos;
+                uint32_t len = std::min(step_size - output_pos, op_end - op);
+                for(uint32_t i = 0 ; i < len; i++)
+                    outs[0][op + i] = outs[1][op + i] = buffer[ip + i];
+                op += len;
+                output_pos += len;
+                if (output_pos == step_size)
+                    output_pos = 0;
+            }
+        }
+            
+        return 3;
+    }
+};
+    
+};
+
+#endif
+
+#endif
diff --git a/src/calf/primitives.h b/src/calf/primitives.h
index b4f8fc1..9969a4b 100644
--- a/src/calf/primitives.h
+++ b/src/calf/primitives.h
@@ -44,6 +44,14 @@ inline void zero(int32_t &v) { v = 0; };
 inline void zero(int16_t &v) { v = 0; };
 inline void zero(int8_t &v) { v = 0; };
 
+template<class T>
+void zero(T *data, unsigned int size) {
+    T value;
+    dsp::zero(value);
+    for (unsigned int i=0; i<size; i++)
+        *data++ = value;
+}
+
 const double PI = 4.0 * atan(1.0);
     
 template<class T = float>struct stereo_sample {
diff --git a/src/giface.cpp b/src/giface.cpp
index 3eddd2d..7603b45 100644
--- a/src/giface.cpp
+++ b/src/giface.cpp
@@ -81,6 +81,7 @@ std::string parameter_properties::to_string(float value) const
     case PF_UNIT_HZ: return string(buf) + " Hz";
     case PF_UNIT_SEC: return string(buf) + " s";
     case PF_UNIT_MSEC: return string(buf) + " ms";
+    case PF_UNIT_CENTS: return string(buf) + " ct";
     }
     return string(buf);
 }
diff --git a/src/jackhost.cpp b/src/jackhost.cpp
index 91e52a6..e0271a6 100644
--- a/src/jackhost.cpp
+++ b/src/jackhost.cpp
@@ -23,6 +23,7 @@
 #include <config.h>
 #include <jack/jack.h>
 #include <calf/giface.h>
+#include <calf/jackhost.h>
 #include <calf/modules.h>
 #include <calf/modules_dev.h>
 #include <gtk/gtk.h>
@@ -175,8 +176,6 @@ void jack_host_gui::create(synth::jack_host_base *_host, const char *title)
 // I don't need anyone to tell me this is stupid. I already know that :)
 jack_host_gui *gui;
 
-//float par_values[1] = { 0.3 };
-
 void destroy(GtkWindow *window, gpointer data)
 {
     gtk_main_quit();
@@ -209,20 +208,22 @@ const char *effect_name = "flanger";
 const char *client_name = "calfhost";
 const char *input_name = "input";
 const char *output_name = "output";
+const char *midi_name = "midi";
 
 int main(int argc, char *argv[])
 {
     gtk_init(&argc, &argv);
     while(1) {
         int option_index;
-        int c = getopt_long(argc, argv, "c:e:i:o:hv", long_options, &option_index);
+        int c = getopt_long(argc, argv, "c:e:i:o:m:hv", long_options, &option_index);
         if (c == -1)
             break;
         switch(c) {
             case 'h':
             case '?':
                 printf("JACK host for Calf effects\n"
-                    "Syntax: %s [--effect reverb|flanger|filter] [--client <name>] [--input <name>] [--output <name>] [--help] [--version]\n", 
+                    "Syntax: %s [--effect reverb|flanger|filter] [--client <name>] [--input <name>]"
+                    "       [--output <name>] [--midi <name>] [--help] [--version]\n", 
                     argv[0]);
                 return 0;
             case 'v':
@@ -240,6 +241,9 @@ int main(int argc, char *argv[])
             case 'o':
                 output_name = optarg;
                 break;
+            case 'm':
+                midi_name = optarg;
+                break;
         }
     }
     try {
@@ -250,11 +254,15 @@ int main(int argc, char *argv[])
             jh = new jack_host<flanger_audio_module>();
         else if (!strcmp(effect_name, "filter"))
             jh = new jack_host<filter_audio_module>();
+#ifdef ENABLE_EXPERIMENTAL
+        else if (!strcmp(effect_name, "monosynth"))
+            jh = new jack_host<monosynth_audio_module>();
+#endif
         else {
-            fprintf(stderr, "Unknown filter name; allowed are: reverb, fastverb, flanger, filter\n");
+            fprintf(stderr, "Unknown filter name; allowed are: reverb, flanger, filter\n");
             return 1;
         }
-        jh->open(client_name, input_name, output_name);
+        jh->open(client_name, input_name, output_name, midi_name);
         make_gui(jh, client_name, effect_name);
         gtk_main();
         delete gui;
diff --git a/src/makerdf.cpp b/src/makerdf.cpp
index 729a622..c9be32f 100644
--- a/src/makerdf.cpp
+++ b/src/makerdf.cpp
@@ -1,3 +1,22 @@
+/* Calf DSP Library
+ * RDF file generator for LADSPA plugins.
+ * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
 #include <getopt.h>
 #include <stdint.h>
 #include <stdlib.h>
diff --git a/src/modules.cpp b/src/modules.cpp
index a25dcee..08c649a 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -104,6 +104,25 @@ synth::ladspa_wrapper<filter_audio_module> filter(filter_info);
 #endif
 
 ////////////////////////////////////////////////////////////////////////////
+#ifdef ENABLE_EXPERIMENTAL
+const char *monosynth_audio_module::param_names[] = {"Out L", "Out R", "Cutoff", "Resonance", "Filter Env", "Decay"};
+
+parameter_properties monosynth_audio_module::param_props[] = {
+    { 33,        10,16000, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL },
+    { 3,        0.7,    4, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB, NULL },
+    { 6000,       0,10800, 1.01, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL },
+    { 2000,      10,20000, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL },
+};
+
+static synth::ladspa_info monosynth_info = { 0x8480, "Monosynth", "Calf Monosynth", "Krzysztof Foltman", copyright, "SynthesizerPlugin" };
+
+#if USE_LADSPA
+synth::ladspa_wrapper<monosynth_audio_module> monosynth(monosynth_info);
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////
 
 #if USE_LADSPA
 extern "C" {

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list