[SCM] calf/master: + Added inertia and timer (once_per_n) classes + Added adjustable inertia to filter plugin + Removed dependency on NAS (in currently used code, at least) + Namespace cleanups
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 d9b2878815d313677c05956762ce2d1891b2f97c
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Sun Dec 2 01:05:07 2007 +0000
+ Added inertia and timer (once_per_n) classes
+ Added adjustable inertia to filter plugin
+ Removed dependency on NAS (in currently used code, at least)
+ Namespace cleanups
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@4 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/configure.in b/configure.in
index 9cad532..f65ab9b 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.3],[wdev at foltman.com])
+AC_INIT([calf],[0.0.4],[wdev at foltman.com])
AC_CONFIG_SRCDIR([config.h.in])
AC_CONFIG_HEADER([config.h])
diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am
index c167bb5..2508e0f 100644
--- a/src/calf/Makefile.am
+++ b/src/calf/Makefile.am
@@ -1,3 +1,3 @@
calfdir = $(includedir)/calf
-calf_HEADERS = audio_fx.h biquad.h buffer.h delay.h fixed_point.h giface.h modules.h onepole.h primitives.h
+calf_HEADERS = audio_fx.h biquad.h buffer.h delay.h fixed_point.h giface.h inertia.h modules.h onepole.h primitives.h wave.h
diff --git a/src/calf/buffer.h b/src/calf/buffer.h
index 44ad22e..18cf101 100644
--- a/src/calf/buffer.h
+++ b/src/calf/buffer.h
@@ -21,9 +21,6 @@
#ifndef __BUFFER_H
#define __BUFFER_H
-#include <typeinfo>
-#include <audio/wave.h>
-
namespace dsp {
/// decrease by N if >= N (useful for circular buffers)
@@ -235,21 +232,6 @@ template<int N, class T = float>
class stereo_auto_buffer: public auto_buffer<N, stereo_sample<T> > {
};
-template<class T>
-bool load_wave(dsp::dynamic_buffer<T> &dest, const char *file_name) {
- WaveInfo *file = WaveOpenFileForReading(file_name);
- typedef dsp::sample_traits<T> st;
- if (file->channels == st::channels && file->bitsPerSample == st::bps) {
- dest.resize(file->numSamples);
- WaveReadFile((char *)dest.data(), dest.size()*sizeof(T), file);
- WaveCloseFile(file);
- return true;
- }
- WaveCloseFile(file);
- fprintf(stderr, "Sorry, need a %d channels and %d bps, got %d channels and %d bps\n", st::channels, st::bps, file->channels, file->bitsPerSample);
- return false;
-}
-
};
#endif
diff --git a/src/calf/inertia.h b/src/calf/inertia.h
new file mode 100644
index 0000000..8a70b40
--- /dev/null
+++ b/src/calf/inertia.h
@@ -0,0 +1,205 @@
+/* Calf DSP Library
+ * Basic "inertia" (parameter smoothing) classes.
+ * 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_INERTIA_H
+#define __CALF_INERTIA_H
+
+#include "primitives.h"
+
+namespace dsp {
+
+/// Algorithm for a constant time linear ramp
+class linear_ramp
+{
+public:
+ int ramp_len;
+ float mul, delta;
+public:
+ linear_ramp(int _ramp_len) {
+ ramp_len = _ramp_len;
+ mul = (float)(1.0f / ramp_len);
+ }
+ inline void set_length(int _ramp_len) {
+ ramp_len = _ramp_len;
+ mul = (float)(1.0f / ramp_len);
+ }
+ inline int length()
+ {
+ return ramp_len;
+ }
+ inline void start_ramp(float start, float end)
+ {
+ delta = mul * (end - start);
+ }
+ inline float ramp(float value)
+ {
+ return value + delta;
+ }
+};
+
+/// Algorithm for a constant time linear ramp
+class exponential_ramp
+{
+public:
+ int ramp_len;
+ float root, delta;
+public:
+ exponential_ramp(int _ramp_len) {
+ ramp_len = _ramp_len;
+ root = (float)(1.0f / ramp_len);
+ }
+ inline void set_length(int _ramp_len) {
+ ramp_len = _ramp_len;
+ root = (float)(1.0f / ramp_len);
+ }
+ inline int length()
+ {
+ return ramp_len;
+ }
+ inline void start_ramp(float start, float end)
+ {
+ delta = pow(end / start, root);
+ }
+ inline float ramp(float value)
+ {
+ return value * delta;
+ }
+};
+
+/// Generic inertia using algorithm specified as template argument
+template<class Ramp>
+class inertia
+{
+public:
+ float old_value;
+ float value;
+ int count;
+ Ramp ramp;
+
+public:
+ inertia(const Ramp &_ramp, float init_value = 0.f)
+ : ramp(_ramp)
+ {
+ value = old_value = init_value;
+ count = 0;
+ }
+ /// Set value immediately (no inertia)
+ void set_now(float _value)
+ {
+ value = old_value = _value;
+ count = 0;
+ }
+ /// Set with inertia
+ void set_inertia(float source)
+ {
+ if (source != old_value) {
+ ramp.start_ramp(value, source);
+ count = ramp.length();
+ old_value = source;
+ }
+ }
+ /// Get smoothed value of given source value
+ inline float get(float source)
+ {
+ if (source != old_value) {
+ ramp.start_ramp(value, source);
+ count = ramp.length();
+ old_value = source;
+ }
+ if (!count)
+ return old_value;
+ value = ramp.ramp(value);
+ count--;
+ if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
+ value = old_value;
+ return value;
+ }
+ /// Get smoothed value assuming no new input
+ inline float get()
+ {
+ if (!count)
+ return old_value;
+ value = ramp.ramp(value);
+ count--;
+ if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
+ value = old_value;
+ return value;
+ }
+ /// Do one inertia step, without returning the new value and without changing inertia
+ inline void step()
+ {
+ if (count) {
+ value = ramp.ramp(value);
+ count--;
+ if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
+ value = old_value;
+ }
+ }
+ /// Get last smoothed value, without affecting anything
+ inline float get_last() const
+ {
+ return value;
+ }
+ inline bool active()
+ {
+ return count > 0;
+ }
+};
+
+class once_per_n
+{
+public:
+ unsigned int frequency;
+ unsigned int left;
+public:
+ once_per_n(unsigned int _frequency)
+ : frequency(_frequency), left(_frequency)
+ {}
+ inline void start()
+ {
+ left = frequency;
+ }
+ /// Set timer to "elapsed" state (elapsed() will return true during next call)
+ inline void signal()
+ {
+ left = 0;
+ }
+ inline unsigned int get(unsigned int desired)
+ {
+ if (desired > left) {
+ desired = left;
+ left = 0;
+ return desired;
+ }
+ left -= desired;
+ return desired;
+ }
+ inline bool elapsed()
+ {
+ if (!left) {
+ left = frequency;
+ return true;
+ }
+ return false;
+ }
+};
+
+}
+
+#endif
diff --git a/src/calf/modules.h b/src/calf/modules.h
index fe12ba1..7c355c4 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -24,8 +24,11 @@
#include <assert.h>
#include "biquad.h"
#include "audio_fx.h"
+#include "inertia.h"
-using namespace synth;
+namespace synth {
+
+using namespace dsp;
class amp_audio_module
{
@@ -155,7 +158,7 @@ public:
class filter_audio_module
{
public:
- enum { par_cutoff, par_resonance, par_mode, param_count };
+ enum { par_cutoff, par_resonance, par_mode, par_inertia, param_count };
enum { in_count = 2, out_count = 2, rt_capable = true };
float *ins[in_count];
float *outs[out_count];
@@ -165,31 +168,59 @@ public:
uint32_t srate;
static parameter_properties param_props[];
int order;
+ inertia<exponential_ramp> inertia_cutoff;
+ once_per_n timer;
- void params_changed() {
- float freq = *params[par_cutoff];
+ filter_audio_module()
+ : inertia_cutoff(exponential_ramp(128), 20)
+ , timer(128)
+ {
+ }
+
+ void calculate_filter()
+ {
+ float freq = inertia_cutoff.get_last();
+ // printf("freq=%g inr.cnt=%d timer.left=%d\n", freq, inertia_cutoff.count, timer.left);
// XXXKF this is resonance of a single stage, obviously for three stages, resonant gain will be different
float q = *params[par_resonance];
- // XXXKF this is highly inefficient
+ // XXXKF this is highly inefficient and should be replaced as soon as I have fast f2i in primitives.h
int mode = (int)*params[par_mode];
- order = (mode < 3) ? mode + 1 : mode - 2;
// printf("freq = %f q = %f mode = %d\n", freq, q, mode);
if (mode < 3) {
left[0].set_lp_rbj(freq, q, srate);
+ order = mode + 1;
} else {
left[0].set_hp_rbj(freq, q, srate);
+ order = mode - 2;
}
+ // XXXKF this is highly inefficient and should be replaced as soon as I have fast f2i in primitives.h
+ int inertia = (int)*params[par_inertia];
+ if (inertia != inertia_cutoff.ramp.length())
+ inertia_cutoff.ramp.set_length(inertia);
+
right[0].copy_coeffs(left[0]);
for (int i = 1; i < order; i++) {
left[i].copy_coeffs(left[0]);
right[i].copy_coeffs(left[0]);
}
}
+ void params_changed()
+ {
+ inertia_cutoff.set_inertia(*params[par_cutoff]);
+ calculate_filter();
+ }
+ void on_timer()
+ {
+ inertia_cutoff.step();
+ calculate_filter();
+ }
void activate() {
for (int i=0; i < order; i++) {
left[i].reset();
right[i].reset();
}
+ timer = once_per_n(srate / 1000);
+ timer.start();
}
void deactivate() {
}
@@ -248,18 +279,30 @@ public:
return filter[order - 1].empty_d1() ? 0 : inmask;
}
uint32_t process(uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
- if (outputs_mask & 1) {
- outputs_mask &= ~1;
- outputs_mask |= process_channel(left, ins[0], outs[0], numsamples, inputs_mask & 1);
- }
- if (outputs_mask & 2) {
- outputs_mask &= ~2;
- outputs_mask |= process_channel(right, ins[1], outs[1], numsamples, inputs_mask & 2);
+ uint32_t ostate = 0;
+ uint32_t offset = 0;
+ while(offset < numsamples) {
+ uint32_t numnow = numsamples - offset;
+ // if inertia's inactive, we can calculate the whole buffer at once
+ if (inertia_cutoff.active())
+ numnow = timer.get(numnow);
+ if (outputs_mask & 1) {
+ ostate |= process_channel(left, ins[0] + offset, outs[0] + offset, numnow, inputs_mask & 1);
+ }
+ if (outputs_mask & 2) {
+ ostate |= process_channel(right, ins[1] + offset, outs[1] + offset, numnow, inputs_mask & 2);
+ }
+ if (timer.elapsed()) {
+ on_timer();
+ }
+ offset += numnow;
}
- return outputs_mask;
+ return ostate;
}
};
extern std::string get_builtin_modules_rdf();
+};
+
#endif
diff --git a/src/calf/wave.h b/src/calf/wave.h
new file mode 100644
index 0000000..55a4806
--- /dev/null
+++ b/src/calf/wave.h
@@ -0,0 +1,42 @@
+/* Calf DSP Library
+ * Primitive interface to NAS WAV file operations.
+ * Not really useful for now, I've used it for testing previously.
+ *
+ * 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 <audio/wave.h>
+
+namespace dsp {
+
+template<class T>
+bool load_wave(dsp::dynamic_buffer<T> &dest, const char *file_name) {
+ WaveInfo *file = WaveOpenFileForReading(file_name);
+ typedef dsp::sample_traits<T> st;
+ if (file->channels == st::channels && file->bitsPerSample == st::bps) {
+ dest.resize(file->numSamples);
+ WaveReadFile((char *)dest.data(), dest.size()*sizeof(T), file);
+ WaveCloseFile(file);
+ return true;
+ }
+ WaveCloseFile(file);
+ fprintf(stderr, "Sorry, need a %d channels and %d bps, got %d channels and %d bps\n", st::channels, st::bps, file->channels, file->bitsPerSample);
+ return false;
+}
+
+}
diff --git a/src/makerdf.cpp b/src/makerdf.cpp
index c7d8f58..d01b6d3 100644
--- a/src/makerdf.cpp
+++ b/src/makerdf.cpp
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
rdf += "<rdf:RDF xmlns:rdf=\"&rdf;\" xmlns:rdfs=\"&rdfs;\" xmlns:dc=\"&dc;\" xmlns:ladspa=\"&ladspa;\">\n";
- rdf += get_builtin_modules_rdf();
+ rdf += synth::get_builtin_modules_rdf();
rdf += "</rdf:RDF>\n";
diff --git a/src/modules.cpp b/src/modules.cpp
index d1ef7a5..7365502 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -24,6 +24,8 @@
#include <calf/giface.h>
#include <calf/modules.h>
+using namespace synth;
+
const char *copyright = "(C) 2001-2007 Krzysztof Foltman, license: LGPL";
const char *amp_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Gain"};
@@ -68,7 +70,7 @@ synth::ladspa_wrapper<reverb_audio_module> reverb(reverb_info);
////////////////////////////////////////////////////////////////////////////
-const char *filter_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Cutoff", "Resonance", "Mode"};
+const char *filter_audio_module::param_names[] = {"In L", "In R", "Out L", "Out R", "Cutoff", "Resonance", "Mode", "Inertia"};
const char *filter_choices[] = {
"12dB/oct Lowpass",
@@ -83,6 +85,7 @@ parameter_properties filter_audio_module::param_props[] = {
{ 2000, 10,20000, 1.01, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL },
{ 0.707, 0.707, 20, 1.1, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL },
{ 0, 0, 5, 1, PF_ENUM | PF_CTL_COMBO, filter_choices },
+ { 20, 5, 100, 1, PF_INT | PF_SCALE_LOG | PF_CTL_KNOB, NULL},
};
static synth::ladspa_info filter_info = { 0x847f, "Filter", "Calf Filter", "Krzysztof Foltman", copyright, "FilterPlugin" };
@@ -96,22 +99,22 @@ extern "C" {
const LADSPA_Descriptor *ladspa_descriptor(unsigned long Index)
{
switch (Index) {
- case 0: return &filter.descriptor;
- case 1: return &flanger.descriptor;
- case 2: return &reverb.descriptor;
+ case 0: return &::filter.descriptor;
+ case 1: return &::flanger.descriptor;
+ case 2: return &::reverb.descriptor;
default: return NULL;
}
}
};
-std::string get_builtin_modules_rdf()
+std::string synth::get_builtin_modules_rdf()
{
std::string rdf;
- rdf += flanger.generate_rdf();
- rdf += reverb.generate_rdf();
- rdf += filter.generate_rdf();
+ rdf += ::flanger.generate_rdf();
+ rdf += ::reverb.generate_rdf();
+ rdf += ::filter.generate_rdf();
return rdf;
}
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list