[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] = ¶ms[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] = ¶ms[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