[SCM] calf/master: + Framework: unbreak plugins, documentation and functionality enhancements ("undersampling") in inertia class + Small modules: code cleanup(?), new modules: linear and exp inertia (exp is untested), square and saw LFOs
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:37:36 UTC 2013
The following commit has been merged in the master branch:
commit 6851dfb4ce9532077824b04bcb2692422128f279
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Wed Sep 24 21:27:04 2008 +0000
+ Framework: unbreak plugins, documentation and functionality enhancements ("undersampling") in inertia class
+ Small modules: code cleanup(?), new modules: linear and exp inertia (exp is untested), square and saw LFOs
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@294 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/src/calf/inertia.h b/src/calf/inertia.h
index 70270e5..b67fb63 100644
--- a/src/calf/inertia.h
+++ b/src/calf/inertia.h
@@ -31,10 +31,12 @@ public:
int ramp_len;
float mul, delta;
public:
+ /// Construct for given ramp length
linear_ramp(int _ramp_len) {
ramp_len = _ramp_len;
mul = (float)(1.0f / ramp_len);
}
+ /// Change ramp length
inline void set_length(int _ramp_len) {
ramp_len = _ramp_len;
mul = (float)(1.0f / ramp_len);
@@ -47,10 +49,16 @@ public:
{
delta = mul * (end - start);
}
+ /// Return value after single step
inline float ramp(float value)
{
return value + delta;
}
+ /// Return value after many steps
+ inline float ramp_many(float value, int count)
+ {
+ return value + delta * count;
+ }
};
/// Algorithm for a constant time linear ramp
@@ -76,20 +84,30 @@ public:
{
delta = pow(end / start, root);
}
+ /// Return value after single step
inline float ramp(float value)
{
return value * delta;
}
+ /// Return value after many steps
+ inline float ramp_many(float value, float count)
+ {
+ return value * pow(delta, count);
+ }
};
-/// Generic inertia using algorithm specified as template argument
+/// Generic inertia using ramping algorithm specified as template argument. The basic idea
+/// is producing smooth(ish) output for discrete input, using specified algorithm to go from
+/// last output value to input value. It is not the same as classic running average lowpass
+/// filter, because ramping time is finite and pre-determined (it calls ramp algorithm's length()
+/// function to obtain the expected ramp length)
template<class Ramp>
class inertia
{
public:
float old_value;
float value;
- int count;
+ unsigned int count;
Ramp ramp;
public:
@@ -141,7 +159,7 @@ public:
value = old_value;
return value;
}
- /// Do one inertia step, without returning the new value and without changing inertia
+ /// Do one inertia step, without returning the new value and without changing destination value
inline void step()
{
if (count) {
@@ -151,12 +169,30 @@ public:
value = old_value;
}
}
+ /// Do many inertia steps, without returning the new value and without changing destination value
+ inline void step_many(unsigned int steps)
+ {
+ if (steps < count) {
+ // Skip only a part of the current ramping period
+ value = ramp.ramp_many(value, steps);
+ count -= steps;
+ if (!count) // finished ramping, set to desired value to get rid of accumulated rounding errors
+ value = old_value;
+ }
+ else
+ {
+ // The whole ramping period has been skipped, just go to destination
+ value = old_value;
+ count = 0;
+ }
+ }
/// Get last smoothed value, without affecting anything
inline float get_last() const
{
return value;
}
- inline bool active()
+ /// Is it still ramping?
+ inline bool active() const
{
return count > 0;
}
diff --git a/src/calf/modulelist.h b/src/calf/modulelist.h
index 2ce31e7..f8c2998 100644
--- a/src/calf/modulelist.h
+++ b/src/calf/modulelist.h
@@ -22,10 +22,14 @@
PER_SMALL_MODULE_ITEM(map_lin2exp, "lin2exp")
PER_SMALL_MODULE_ITEM(square_osc, "square_osc")
PER_SMALL_MODULE_ITEM(saw_osc, "saw_osc")
+ PER_SMALL_MODULE_ITEM(square_lfo, "square_lfo")
+ PER_SMALL_MODULE_ITEM(saw_lfo, "saw_lfo")
PER_SMALL_MODULE_ITEM(print, "print")
PER_SMALL_MODULE_ITEM(print2, "print2")
PER_SMALL_MODULE_ITEM(quadpower_a, "quadpower_a")
PER_SMALL_MODULE_ITEM(quadpower_c, "quadpower_c")
+ PER_SMALL_MODULE_ITEM(linear_inertia_c, "linear_inertia_c")
+ PER_SMALL_MODULE_ITEM(exp_inertia_c, "exp_inertia_c")
#endif
#undef PER_MODULE_ITEM
#undef PER_SMALL_MODULE_ITEM
diff --git a/src/calf/modules_small.h b/src/calf/modules_small.h
index f7a7587..474a22c 100644
--- a/src/calf/modules_small.h
+++ b/src/calf/modules_small.h
@@ -26,11 +26,25 @@
class null_small_audio_module
{
public:
+ uint32_t srate;
+ double odsr;
/// LADSPA-esque activate function, except it is called after ports are connected, not before
inline void activate() {}
/// LADSPA-esque deactivate function
inline void deactivate() {}
/// Set sample rate for the plugin
- inline void set_sample_rate(uint32_t sr) { }
+ inline void set_sample_rate(uint32_t sr) { srate = sr; odsr = 1.0 / sr; }
+};
+
+/// Templatized version useful when the number of inputs and outputs is small
+template<unsigned int Inputs, unsigned int Outputs>
+class small_audio_module_base: public null_small_audio_module
+{
+public:
+ enum { in_count = Inputs, out_count = Outputs };
+ /// Input pointers
+ float *ins[in_count];
+ /// Output pointers
+ float *outs[out_count];
};
#endif
diff --git a/src/calf/plugininfo.h b/src/calf/plugininfo.h
index 7e41c9b..0658dfa 100644
--- a/src/calf/plugininfo.h
+++ b/src/calf/plugininfo.h
@@ -47,6 +47,9 @@ struct control_port_info_iface
virtual control_port_info_iface& lin_range(double from, double to) { return *this; }
/// Called to mark the port as using log range [from, to]
virtual control_port_info_iface& log_range(double from, double to) { return *this; }
+ virtual control_port_info_iface& toggle() { return *this; }
+ virtual control_port_info_iface& trigger() { return *this; }
+ virtual control_port_info_iface& integer() { return *this; }
virtual ~control_port_info_iface() {}
};
diff --git a/src/makerdf.cpp b/src/makerdf.cpp
index 7e68846..ac811b9 100644
--- a/src/makerdf.cpp
+++ b/src/makerdf.cpp
@@ -212,7 +212,7 @@ struct lv2_control_port_info: public lv2_port_base, public control_port_info_ifa
{
int index;
string symbol, name;
- bool is_input, is_log, is_bool;
+ bool is_input, is_log, is_toggle, is_trigger, is_integer;
double min, max, def_value;
bool has_min, has_max;
@@ -223,8 +223,7 @@ struct lv2_control_port_info: public lv2_port_base, public control_port_info_ifa
, is_input(true)
, def_value(_default)
{
- has_min = has_max = is_log = is_bool = false;
-
+ has_min = has_max = is_log = is_toggle = is_trigger = is_integer = false;
}
/// Called if it's an input port
virtual control_port_info_iface& input() { is_input = true; return *this; }
@@ -234,7 +233,9 @@ struct lv2_control_port_info: public lv2_port_base, public control_port_info_ifa
virtual control_port_info_iface& lin_range(double from, double to) { min = from, max = to, has_min = true, has_max = true, is_log = false; return *this; }
/// Called to mark the port as using log range [from, to]
virtual control_port_info_iface& log_range(double from, double to) { min = from, max = to, has_min = true, has_max = true, is_log = true; return *this; }
-
+ virtual control_port_info_iface& toggle() { is_toggle = true; return *this; }
+ virtual control_port_info_iface& trigger() { is_trigger = true; return *this; }
+ virtual control_port_info_iface& integer() { is_integer = true; return *this; }
std::string to_string() {
stringstream ss;
const char *ind = " ";
@@ -244,6 +245,10 @@ struct lv2_control_port_info: public lv2_port_base, public control_port_info_ifa
ss << ind << "lv2:index " << index << " ;\n";
ss << ind << "lv2:symbol \"" << symbol << "\" ;\n";
ss << ind << "lv2:name \"" << name << "\" ;\n";
+ if (is_toggle)
+ ss << ind << ":portProperty lv2:toggled ;\n";
+ if (is_integer)
+ ss << ind << ":portProperty lv2:integer ;\n";
if (is_input)
ss << ind << "lv2:default " << def_value << " ;\n";
if (has_min)
diff --git a/src/modules_small.cpp b/src/modules_small.cpp
index ff77f08..c20c651 100644
--- a/src/modules_small.cpp
+++ b/src/modules_small.cpp
@@ -34,7 +34,7 @@
#ifdef ENABLE_EXPERIMENTAL
#if USE_LV2
-#define LV2_SMALL_WRAPPER(mod, name) static synth::lv2_small_wrapper<small_##mod##_audio_module> lv2_small_##mod(name);
+#define LV2_SMALL_WRAPPER(mod, name) static synth::lv2_small_wrapper<small_plugins::mod##_audio_module> lv2_small_##mod(name);
#else
#define LV2_SMALL_WRAPPER(...)
#endif
@@ -49,7 +49,10 @@ using namespace std;
template<class Module> LV2_Descriptor lv2_small_wrapper<Module>::descriptor;
-class small_filter_audio_module: public null_small_audio_module
+namespace small_plugins
+{
+
+class filter_base: public null_small_audio_module
{
public:
enum { in_signal, in_cutoff, in_resonance, in_count };
@@ -64,14 +67,10 @@ public:
pii->audio_port("out", "Out").output();
}
dsp::biquad<float> filter;
- uint32_t srate;
void activate() {
filter.reset_d1();
}
- void set_sample_rate(uint32_t sr) {
- srate = sr;
- }
inline void process_inner(uint32_t count) {
for (uint32_t i = 0; i < count; i++)
outs[out_signal][i] = filter.process_d1(ins[in_signal][i]);
@@ -79,7 +78,7 @@ public:
}
};
-class small_lp_filter_audio_module: public small_filter_audio_module
+class lp_filter_audio_module: public filter_base
{
public:
inline void process(uint32_t count) {
@@ -93,7 +92,7 @@ public:
}
};
-class small_hp_filter_audio_module: public small_filter_audio_module
+class hp_filter_audio_module: public filter_base
{
public:
inline void process(uint32_t count) {
@@ -107,7 +106,7 @@ public:
}
};
-class small_bp_filter_audio_module: public small_filter_audio_module
+class bp_filter_audio_module: public filter_base
{
public:
inline void process(uint32_t count) {
@@ -121,7 +120,7 @@ public:
}
};
-class small_br_filter_audio_module: public small_filter_audio_module
+class br_filter_audio_module: public filter_base
{
public:
inline void process(uint32_t count) {
@@ -135,7 +134,7 @@ public:
}
};
-class small_onepole_filter_audio_module: public null_small_audio_module
+class onepole_filter_base: public null_small_audio_module
{
public:
enum { in_signal, in_cutoff, in_count };
@@ -143,12 +142,8 @@ public:
float *ins[in_count];
float *outs[out_count];
dsp::onepole<float> filter;
- uint32_t srate;
static parameter_properties param_props[];
- void set_sample_rate(uint32_t sr) {
- srate = sr;
- }
static void port_info(plugin_info_iface *pii)
{
pii->audio_port("In", "in").input();
@@ -161,7 +156,7 @@ public:
}
};
-class small_onepole_lp_filter_audio_module: public small_onepole_filter_audio_module
+class onepole_lp_filter_audio_module: public onepole_filter_base
{
public:
void process(uint32_t count) {
@@ -177,7 +172,7 @@ public:
}
};
-class small_onepole_hp_filter_audio_module: public small_onepole_filter_audio_module
+class onepole_hp_filter_audio_module: public onepole_filter_base
{
public:
void process(uint32_t count) {
@@ -193,7 +188,7 @@ public:
}
};
-class small_onepole_ap_filter_audio_module: public small_onepole_filter_audio_module
+class onepole_ap_filter_audio_module: public onepole_filter_base
{
public:
void process(uint32_t count) {
@@ -211,14 +206,9 @@ public:
/// This works for 1 or 2 operands only...
template<int Inputs>
-class audio_operator_audio_module: public null_small_audio_module
+class audio_operator_audio_module: public small_audio_module_base<Inputs, 1>
{
public:
- enum { in_count = Inputs, out_count = 1 };
- float *ins[in_count];
- float *outs[out_count];
- uint32_t srate;
-
static void port_info(plugin_info_iface *pii)
{
if (Inputs == 1)
@@ -230,12 +220,9 @@ public:
}
pii->audio_port("out", "Out").output();
}
- void set_sample_rate(uint32_t sr) {
- srate = sr;
- }
};
-class small_min_audio_module: public audio_operator_audio_module<2>
+class min_audio_module: public audio_operator_audio_module<2>
{
public:
void process(uint32_t count) {
@@ -249,7 +236,7 @@ public:
}
};
-class small_max_audio_module: public audio_operator_audio_module<2>
+class max_audio_module: public audio_operator_audio_module<2>
{
public:
void process(uint32_t count) {
@@ -263,7 +250,7 @@ public:
}
};
-class small_minus_audio_module: public audio_operator_audio_module<2>
+class minus_audio_module: public audio_operator_audio_module<2>
{
public:
void process(uint32_t count) {
@@ -277,7 +264,7 @@ public:
}
};
-class small_mul_audio_module: public audio_operator_audio_module<2>
+class mul_audio_module: public audio_operator_audio_module<2>
{
public:
void process(uint32_t count) {
@@ -291,7 +278,7 @@ public:
}
};
-class small_neg_audio_module: public audio_operator_audio_module<1>
+class neg_audio_module: public audio_operator_audio_module<1>
{
public:
void process(uint32_t count) {
@@ -305,14 +292,13 @@ public:
}
};
-class small_map_lin2exp_audio_module: public null_small_audio_module
+class map_lin2exp_audio_module: public null_small_audio_module
{
public:
enum { in_signal, in_from_min, in_from_max, in_to_min, in_to_max, in_count };
enum { out_signal, out_count };
float *ins[in_count];
float *outs[out_count];
- uint32_t srate;
static void plugin_info(plugin_info_iface *pii)
{
@@ -324,18 +310,75 @@ public:
pii->control_port("to_max", "Max (to)", 20000).input();
pii->control_port("out", "Out", 0.f).output();
}
- void set_sample_rate(uint32_t sr) {
- srate = sr;
- }
void process(uint32_t count) {
float normalized = (*ins[in_signal] - *ins[in_from_min]) / (*ins[in_from_max] - *ins[in_from_min]);
*outs[out_signal] = *ins[in_to_min] * pow(*ins[in_to_max] / *ins[in_to_min], normalized);
}
};
+class freq_phase_lfo_base: public small_audio_module_base<2, 1>
+{
+public:
+ enum { in_freq, in_reset };
+ double phase;
+ inline void activate()
+ {
+ phase = 0;
+ }
+ static void port_info(plugin_info_iface *pii)
+ {
+ pii->control_port("freq", "Frequency", 1).input().log_range(0.02, 100);
+ pii->control_port("reset", "Reset", 0).input().toggle();
+ pii->control_port("out", "Out", 0).output();
+ }
+ inline void check_inputs()
+ {
+ if (*ins[in_reset])
+ phase = 0;
+ }
+ inline void advance(uint32_t count)
+ {
+ phase += count * *ins[in_freq] * odsr;
+ if (phase >= 1.0)
+ phase = fmod(phase, 1.0);
+ }
+};
+
+class square_lfo_audio_module: public freq_phase_lfo_base
+{
+public:
+ void process(uint32_t count)
+ {
+ check_inputs();
+ *outs[0] = (phase < 0.5) ? -1 : +1;
+ advance(count);
+ }
+ static void plugin_info(plugin_info_iface *pii)
+ {
+ pii->names("square_lfo", "Square LFO", "lv2:OscillatorPlugin");
+ port_info(pii);
+ }
+};
+
+class saw_lfo_audio_module: public freq_phase_lfo_base
+{
+public:
+ void process(uint32_t count)
+ {
+ check_inputs();
+ *outs[0] = -1 + 2 * phase;
+ advance(count);
+ }
+ static void plugin_info(plugin_info_iface *pii)
+ {
+ pii->names("saw_lfo", "Saw LFO", "lv2:OscillatorPlugin");
+ port_info(pii);
+ }
+};
+
#define SMALL_OSC_TABLE_BITS 12
-class small_freq_only_osc_audio_module: public null_small_audio_module
+class freq_only_osc_base: public null_small_audio_module
{
public:
typedef waveform_family<SMALL_OSC_TABLE_BITS> waves_type;
@@ -346,8 +389,6 @@ public:
float *outs[out_count];
waves_type *waves;
waveform_oscillator<SMALL_OSC_TABLE_BITS> osc;
- uint32_t srate;
- double odsr;
/// Fill the array with the original, non-bandlimited, waveform
virtual void get_original_waveform(float data[wave_size]) = 0;
@@ -356,10 +397,6 @@ public:
void activate() {
waves = get_waves();
}
- void set_sample_rate(uint32_t sr) {
- srate = sr;
- odsr = 1.0 / sr;
- }
void process(uint32_t count)
{
osc.set_freq_odsr(*ins[in_freq], odsr);
@@ -396,7 +433,7 @@ public:
return waves; \
}
-class small_square_osc_audio_module: public small_freq_only_osc_audio_module
+class square_osc_audio_module: public freq_only_osc_base
{
public:
OSC_MODULE_GET_WAVES()
@@ -412,7 +449,7 @@ public:
}
};
-class small_saw_osc_audio_module: public small_freq_only_osc_audio_module
+class saw_osc_audio_module: public freq_only_osc_base
{
public:
OSC_MODULE_GET_WAVES()
@@ -428,44 +465,28 @@ public:
}
};
-class small_print_audio_module: public null_small_audio_module
+class print_audio_module: public small_audio_module_base<1, 0>
{
public:
- enum { in_count = 1, out_count = 0 };
- float *ins[in_count];
- float *outs[out_count];
- uint32_t srate;
-
static void plugin_info(plugin_info_iface *pii)
{
pii->names("print", "Print To Console (C)", "lv2:UtilityPlugin");
pii->control_port("in", "In", 0).input();
}
- void set_sample_rate(uint32_t sr) {
- srate = sr;
- }
void process(uint32_t)
{
printf("%f\n", *ins[0]);
}
};
-class small_print2_audio_module: public null_small_audio_module
+class print2_audio_module: public small_audio_module_base<1, 0>
{
public:
- enum { in_count = 1, out_count = 0 };
- float *ins[in_count];
- float *outs[out_count];
- uint32_t srate;
-
static void plugin_info(plugin_info_iface *pii)
{
pii->names("print2", "Print To Console (A)", "lv2:UtilityPlugin");
pii->audio_port("in", "In").input();
}
- void set_sample_rate(uint32_t sr) {
- srate = sr;
- }
void process(uint32_t)
{
printf("%f\n", *ins[0]);
@@ -473,7 +494,7 @@ public:
};
template<bool audio>
-class small_quadpower_audio_module: public null_small_audio_module
+class quadpower_base: public null_small_audio_module
{
public:
enum { in_value, in_factor, in_count , out_count = 4 };
@@ -500,7 +521,7 @@ public:
}
};
-class small_quadpower_a_audio_module: public small_quadpower_audio_module<true>
+class quadpower_a_audio_module: public quadpower_base<true>
{
public:
void process(uint32_t count)
@@ -517,7 +538,7 @@ public:
}
};
-class small_quadpower_c_audio_module: public small_quadpower_audio_module<false>
+class quadpower_c_audio_module: public quadpower_base<false>
{
public:
void process(uint32_t)
@@ -531,6 +552,73 @@ public:
}
};
+template<class Ramp>
+class inertia_c_module_base: public small_audio_module_base<3, 1>
+{
+public:
+ enum { in_value, in_inertia, in_immediate };
+ bool reset;
+ inertia<Ramp> state;
+ inertia_c_module_base()
+ : state(Ramp(1))
+ {}
+ void activate()
+ {
+ reset = true;
+ }
+ static void port_info(plugin_info_iface *pii)
+ {
+ pii->names("linear_inertia_c", "Linear Inertia (C)", "lv2:UtilityPlugin");
+ pii->control_port("in", "In", 0).input();
+ pii->control_port("time", "Inertia time", 100).input();
+ pii->control_port("reset", "Reset", 0).input().toggle();
+ pii->control_port("out", "Out", 0).output();
+ }
+ void process(uint32_t count)
+ {
+ float value = *ins[in_value];
+ if (reset || *ins[in_immediate] != 0)
+ {
+ *outs[0] = value;
+ state.set_now(value);
+ reset = false;
+ }
+ else
+ {
+ if (value != state.get_last())
+ {
+ state.ramp.set_length(dsp::clip((int)(srate * 0.001 * *ins[in_inertia]), 1, 10000000));
+ }
+ state.set_inertia(value);
+ *outs[0] = state.get_last();
+ if (count)
+ state.step_many(count);
+ }
+ }
+};
+
+class linear_inertia_c_audio_module: public inertia_c_module_base<linear_ramp>
+{
+public:
+ static void plugin_info(plugin_info_iface *pii)
+ {
+ pii->names("linear_inertia_c", "Linear Inertia (C)", "lv2:UtilityPlugin");
+ port_info(pii);
+ }
+};
+
+class exp_inertia_c_audio_module: public inertia_c_module_base<exponential_ramp>
+{
+public:
+ static void plugin_info(plugin_info_iface *pii)
+ {
+ pii->names("exp_inertia_c", "Exponential Inertia (C)", "lv2:UtilityPlugin");
+ port_info(pii);
+ }
+};
+
+};
+
#define PER_MODULE_ITEM(...)
#define PER_SMALL_MODULE_ITEM(name, id) SMALL_WRAPPERS(name, id)
#include <calf/modulelist.h>
@@ -548,7 +636,7 @@ const LV2_Descriptor *synth::lv2_small_descriptor(uint32_t index)
void synth::get_all_small_plugins(plugin_list_info_iface *iface)
{
#define PER_MODULE_ITEM(name, isSynth, jackname)
- #define PER_SMALL_MODULE_ITEM(name, id) { plugin_info_iface *pii = &iface->plugin(id); small_##name##_audio_module::plugin_info(pii); pii->finalize(); }
+ #define PER_SMALL_MODULE_ITEM(name, id) { plugin_info_iface *pii = &iface->plugin(id); small_plugins::name##_audio_module::plugin_info(pii); pii->finalize(); }
#include <calf/modulelist.h>
}
diff --git a/src/plugin.cpp b/src/plugin.cpp
index f27e4cd..7923038 100644
--- a/src/plugin.cpp
+++ b/src/plugin.cpp
@@ -18,8 +18,12 @@
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
+#include <config.h>
+#include <calf/lv2wrap.h>
#include <calf/modules.h>
+using namespace synth;
+
#if USE_LADSPA
#define LADSPA_WRAPPER(mod) static synth::ladspa_wrapper<mod##_audio_module> ladspa_##mod(mod##_audio_module::plugin_info);
#else
@@ -34,6 +38,10 @@
#define ALL_WRAPPERS(mod) LADSPA_WRAPPER(mod) LV2_WRAPPER(mod)
+#define PER_MODULE_ITEM(name, isSynth, jackname) ALL_WRAPPERS(name)
+#define PER_SMALL_MODULE_ITEM(...)
+#include <calf/modulelist.h>
+
#if USE_LV2
// instantiate descriptor templates
template<class Module> LV2_Descriptor synth::lv2_wrapper<Module>::descriptor;
@@ -55,6 +63,7 @@ const LV2_Descriptor *lv2_descriptor(uint32_t index)
};
#endif
+
#if USE_LADSPA
extern "C" {
@@ -84,7 +93,3 @@ const DSSI_Descriptor *dssi_descriptor(unsigned long Index)
#endif
-#define PER_MODULE_ITEM(name, isSynth, jackname) ALL_WRAPPERS(name)
-#define PER_SMALL_MODULE_ITEM(...)
-#include <calf/modulelist.h>
-
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list