[SCM] calf/master: + Organ: new waveforms, ability to select waveforms for each drawbar + Phaser: new effect, up to 12 1st order allpass stages
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:37:05 UTC 2013
The following commit has been merged in the master branch:
commit 6673230192d416d8a5acce42524f9096c8854b1b
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Sun Mar 23 23:14:17 2008 +0000
+ Organ: new waveforms, ability to select waveforms for each drawbar
+ Phaser: new effect, up to 12 1st order allpass stages
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@135 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/src/calf/audio_fx.h b/src/calf/audio_fx.h
index fad34aa..26ed93c 100644
--- a/src/calf/audio_fx.h
+++ b/src/calf/audio_fx.h
@@ -41,18 +41,12 @@ public:
virtual ~audio_effect() {}
};
-/**
- * Base class for chorus and flanger. Wouldn't be needed if it wasn't
- * for odd behaviour of GCC when deriving templates from template
- * base classes (not seeing fields from base classes!).
- */
-class chorus_base: public audio_effect
+class modulation_effect: public audio_effect
{
protected:
- int sample_rate, min_delay_samples, mod_depth_samples;
- float rate, wet, dry, min_delay, mod_depth, odsr;
+ int sample_rate;
+ float rate, wet, dry, odsr;
gain_smoothing gs_wet, gs_dry;
- sine_table<int, 4096, 65536> sine;
public:
fixed_point<unsigned int, 20> phase, dphase;
float get_rate() {
@@ -74,8 +68,133 @@ public:
}
void set_dry(float dry) {
this->dry = dry;
- gs_dry.set_inertia(wet);
+ gs_dry.set_inertia(dry);
+ }
+ void reset_phase(float req_phase)
+ {
+ phase = req_phase * 4096.0;
+ }
+ void inc_phase(float req_phase)
+ {
+ phase += fixed_point<unsigned int, 20>(req_phase * 4096.0);
+ }
+ void setup(int sample_rate)
+ {
+ this->sample_rate = sample_rate;
+ this->odsr = 1.0 / sample_rate;
+ phase = 0;
+ set_rate(get_rate());
+ }
+};
+
+/**
+ * A monophonic phaser. If you want stereo, combine two :)
+ * Also, gave up on using template args for signal type.
+ */
+template<int MaxStages>
+class simple_phaser: public modulation_effect
+{
+protected:
+ float base_frq, mod_depth, resonance, fb;
+ float state;
+ int cnt, stages;
+ dsp::onepole<float, float> stage1;
+ float x1[MaxStages], y1[MaxStages];
+public:
+ float get_base_frq() {
+ return base_frq;
+ }
+ void set_base_frq(float _base_frq) {
+ base_frq = _base_frq;
+ }
+ int get_stages() {
+ return stages;
+ }
+ void set_stages(int _stages) {
+ if (_stages > stages)
+ {
+ for (int i = stages; i < _stages; i++)
+ {
+ x1[i] = x1[stages-1];
+ y1[i] = y1[stages-1];
+ }
+ }
+ stages = _stages;
+ }
+ float get_mod_depth() {
+ return mod_depth;
+ }
+ void set_mod_depth(float _mod_depth) {
+ mod_depth = _mod_depth;
+ }
+ float get_fb() {
+ return fb;
+ }
+ void set_fb(float fb) {
+ this->fb = fb;
+ }
+ virtual void setup(int sample_rate) {
+ modulation_effect::setup(sample_rate);
+ reset();
+ }
+ void reset()
+ {
+ cnt = 0;
+ state = 0;
+ for (int i = 0; i < MaxStages; i++)
+ x1[i] = y1[i] = 0;
+ control_step();
+ }
+ inline void control_step()
+ {
+ cnt = 0;
+ int v = phase.get() + 0x40000000;
+ int sign = v >> 31;
+ v ^= sign;
+ // triangle wave, range from 0 to INT_MAX
+ double vf = (double)((v >> 16) * (1.0 / 16384.0) - 1);
+
+ float freq = base_frq * pow(2.0, vf * mod_depth / 1200.0);
+ freq = dsp::clip<float>(freq, 10.0, 0.49 * sample_rate);
+ stage1.set_ap_w(freq * (M_PI / 2.0) * odsr);
+ phase += dphase * 16;
+ }
+ void process(float *buf_out, float *buf_in, int nsamples) {
+ for (int i=0; i<nsamples; i++) {
+ cnt++;
+ if (cnt == 16)
+ control_step();
+ float in = *buf_in++;
+ float fd = in + state * fb;
+ for (int j = 0; j < stages; j++)
+ fd = stage1.process_ap(fd, x1[j], y1[j]);
+ state = fd;
+
+ float sdry = in * gs_dry.get();
+ float swet = fd * gs_wet.get();
+ *buf_out++ = sdry + swet;
+ }
+ for (int i = 0; i < stages; i++)
+ {
+ dsp::sanitize(x1[i]);
+ dsp::sanitize(y1[i]);
+ }
}
+};
+
+/**
+ * Base class for chorus and flanger. Wouldn't be needed if it wasn't
+ * for odd behaviour of GCC when deriving templates from template
+ * base classes (not seeing fields from base classes!).
+ */
+class chorus_base: public modulation_effect
+{
+protected:
+ int sample_rate, min_delay_samples, mod_depth_samples;
+ float min_delay, mod_depth;
+ sine_table<int, 4096, 65536> sine;
+public:
+ fixed_point<unsigned int, 20> phase, dphase;
float get_min_delay() {
return min_delay;
}
@@ -91,14 +210,6 @@ public:
// 128 because it's then multiplied by (hopefully) a value of 32768..-32767
this->mod_depth_samples = (int)(mod_depth * 32.0 * sample_rate);
}
- void reset_phase(float req_phase)
- {
- phase = req_phase * 4096.0;
- }
- void inc_phase(float req_phase)
- {
- phase += fixed_point<unsigned int, 20>(req_phase * 4096.0);
- }
};
/**
@@ -123,11 +234,8 @@ public:
delay.reset();
}
virtual void setup(int sample_rate) {
- this->sample_rate = sample_rate;
- this->odsr = 1.0 / sample_rate;
+ modulation_effect::setup(sample_rate);
delay.reset();
- phase = 0;
- set_rate(get_rate());
set_min_delay(get_min_delay());
set_mod_depth(get_mod_depth());
}
diff --git a/src/calf/modules.h b/src/calf/modules.h
index 720c020..524cbaa 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -146,6 +146,80 @@ public:
static const char *get_label() { return "Flanger"; }
};
+class phaser_audio_module: public null_audio_module
+{
+public:
+ enum { par_freq, par_depth, par_rate, par_fb, par_stages, par_stereo, par_reset, par_amount, param_count };
+ enum { in_count = 2, out_count = 2, support_midi = false, rt_capable = true };
+ static const char *port_names[];
+ float *ins[in_count];
+ float *outs[out_count];
+ float *params[param_count];
+ uint32_t srate;
+ bool clear_reset;
+ float last_r_phase;
+ dsp::simple_phaser<12> left, right;
+ static parameter_properties param_props[];
+ void set_sample_rate(uint32_t sr) {
+ srate = sr;
+ left.setup(sr);
+ right.setup(sr);
+ }
+ void params_changed() {
+ float dry = 1.0;
+ float wet = *params[par_amount];
+ float rate = *params[par_rate]; // 0.01*pow(1000.0f,*params[par_rate]);
+ float base_frq = *params[par_freq];
+ float mod_depth = *params[par_depth];
+ float fb = *params[par_fb];
+ int stages = (int)*params[par_stages];
+ left.set_dry(dry); right.set_dry(dry);
+ left.set_wet(wet); right.set_wet(wet);
+ left.set_rate(rate); right.set_rate(rate);
+ left.set_base_frq(base_frq); right.set_base_frq(base_frq);
+ left.set_mod_depth(mod_depth); right.set_mod_depth(mod_depth);
+ left.set_fb(fb); right.set_fb(fb);
+ left.set_stages(stages); right.set_stages(stages);
+ float r_phase = *params[par_stereo] * (1.f / 360.f);
+ clear_reset = false;
+ if (*params[par_reset] >= 0.5) {
+ clear_reset = true;
+ left.reset_phase(0.f);
+ right.reset_phase(r_phase);
+ } else {
+ if (fabs(r_phase - last_r_phase) > 0.0001f) {
+ right.phase = left.phase;
+ right.inc_phase(r_phase);
+ last_r_phase = r_phase;
+ }
+ }
+ }
+ void params_reset()
+ {
+ if (clear_reset) {
+ *params[par_reset] = 0.f;
+ clear_reset = false;
+ }
+ }
+ void activate() {
+ left.reset();
+ right.reset();
+ last_r_phase = *params[par_stereo] * (1.f / 360.f);
+ left.reset_phase(0.f);
+ right.reset_phase(last_r_phase);
+ }
+ void deactivate() {
+ }
+ 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
+ }
+ static const char *get_name() { return "phaser"; }
+ static const char *get_id() { return "phaser"; }
+ static const char *get_label() { return "Phaser"; }
+};
+
class reverb_audio_module: public null_audio_module
{
public:
diff --git a/src/calf/onepole.h b/src/calf/onepole.h
index 3b794fb..790b318 100644
--- a/src/calf/onepole.h
+++ b/src/calf/onepole.h
@@ -37,6 +37,7 @@ public:
T x1, y1;
Coeff a0, a1, b1;
+ /// Set coefficients for a lowpass filter
void set_lp(float fc, float sr)
{
// x x
@@ -47,6 +48,7 @@ public:
b1 = (x-1)*q;
}
+ /// Set coefficients for an allpass filter
void set_ap(float fc, float sr)
{
// x-1 x+1
@@ -57,6 +59,19 @@ public:
a1 = 1;
}
+ /// Set coefficients for an allpass filter, using omega instead of fc and sr
+ /// omega = (PI / 2) * fc / sr
+ void set_ap_w(float w)
+ {
+ // x-1 x+1
+ // x+1 x-1
+ Coeff x = tan (w);
+ Coeff q = 1/(1+x);
+ b1 = a0 = (x-1)*q;
+ a1 = 1;
+ }
+
+ /// Set coefficients for a highpass filter
void set_hp(float fc, float sr)
{
// x -x
@@ -68,6 +83,7 @@ public:
b1 = (x-1)*q;
}
+ /// Process one sample
inline T process(T in)
{
T out = in * a0 + x1 * a1 - y1 * b1;
@@ -76,6 +92,7 @@ public:
return out;
}
+ /// Process one sample, assuming it's a lowpass filter (optimized special case)
inline T process_lp(T in)
{
T out = (in + x1) * a0 - y1 * b1;
@@ -84,6 +101,7 @@ public:
return out;
}
+ /// Process one sample, assuming it's a highpass filter (optimized special case)
inline T process_hp(T in)
{
T out = (in - x1) * a0 - y1 * b1;
@@ -92,6 +110,7 @@ public:
return out;
}
+ /// Process one sample, assuming it's an allpass filter (optimized special case)
inline T process_ap(T in)
{
T out = (in - y1) * a0 + x1;
@@ -100,6 +119,15 @@ public:
return out;
}
+ /// Process one sample using external state variables
+ inline T process_ap(T in, float &x1, float &y1)
+ {
+ T out = (in - y1) * a0 + x1;
+ x1 = in;
+ y1 = out;
+ return out;
+ }
+
inline void sanitize()
{
dsp::sanitize(x1);
@@ -111,6 +139,14 @@ public:
dsp::zero(x1);
dsp::zero(y1);
}
+
+ template<class U>
+ inline void copy_coeffs(const onepole<U> &src)
+ {
+ a0 = src.a0;
+ a1 = src.a1;
+ b1 = src.b1;
+ }
};
};
diff --git a/src/calf/organ.h b/src/calf/organ.h
index 594de2d..5cc0296 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -49,7 +49,7 @@ struct organ_parameters {
class organ_voice_base
{
protected:
- enum { wave_sine, wave_pulse, wave_stretchsine, wave_count };
+ enum { wave_sine, wave_pulse, wave_sinepl1, wave_sinepl2, wave_sinepl3, wave_saw, wave_sqr, wave_ssaw, wave_ssqr, wave_count };
static waveform_family<ORGAN_WAVE_BITS> waves[wave_count];
// dsp::sine_table<float, ORGAN_WAVE_SIZE, 1> sine_wave;
dsp::fixed_point<int, 20> phase, dphase;
diff --git a/src/calf/osc.h b/src/calf/osc.h
index 4f89a6f..b124d55 100644
--- a/src/calf/osc.h
+++ b/src/calf/osc.h
@@ -65,6 +65,14 @@ struct bandlimiter
fft.calculate(data, spectrum, false);
}
+ void compute_waveform(float output[SIZE])
+ {
+ std::complex<float> data[SIZE];
+ fft.calculate(spectrum, data, true);
+ for (int i = 0; i < SIZE; i++)
+ output[i] = data[i].real();
+ }
+
/// remove DC offset of the spectrum (it usually does more harm than good!)
void remove_dc()
{
diff --git a/src/jackhost.cpp b/src/jackhost.cpp
index b62ee6b..0ba0ad2 100644
--- a/src/jackhost.cpp
+++ b/src/jackhost.cpp
@@ -60,6 +60,8 @@ jack_host_base *synth::create_jack_host(const char *effect_name)
return new jack_host<organ_audio_module>();
else if (!strcasecmp(effect_name, "rotaryspeaker"))
return new jack_host<rotary_speaker_audio_module>();
+ else if (!strcasecmp(effect_name, "phaser"))
+ return new jack_host<phaser_audio_module>();
#ifdef ENABLE_EXPERIMENTAL
#endif
else
@@ -191,10 +193,9 @@ void host_session::open()
jack_host_base *jh = create_jack_host(plugin_names[i].c_str());
if (!jh) {
#ifdef ENABLE_EXPERIMENTAL
- throw audio_exception("Unknown plugin name; allowed are: reverb, flanger, filter, vintagedelay, monosynth, organ, rotaryspeaker\n");
#else
- throw audio_exception("Unknown plugin name; allowed are: reverb, flanger, filter, vintagedelay, monosynth\n");
#endif
+ throw audio_exception("Unknown plugin name; allowed are: reverb, flanger, filter, vintagedelay, monosynth, organ, rotaryspeaker, phaser\n");
}
jh->open(&client);
diff --git a/src/modules.cpp b/src/modules.cpp
index 18dea2d..5e6907c 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -67,6 +67,25 @@ ALL_WRAPPERS(flanger)
////////////////////////////////////////////////////////////////////////////
+const char *phaser_audio_module::port_names[] = {"In L", "In R", "Out L", "Out R"};
+
+parameter_properties phaser_audio_module::param_props[] = {
+ { 1000, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "base_freq", "Center Freq" },
+ { 4000, 0, 10800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "mod_depth", "Modulation depth" },
+ { 0.25, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "mod_rate", "Modulation rate" },
+ { 0.25, -0.99, 0.99, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "feedback", "Feedback" },
+ { 6, 1, 12, 12, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "stages", "# Stages" },
+ { 180, 0, 360, 10, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "stereo", "Stereo phase" },
+ { 0, 0, 1, 2, PF_BOOL | PF_CTL_BUTTON , NULL, "reset", "Reset" },
+ { 1, 0, 2, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "amount", "Amount" },
+};
+
+static synth::ladspa_info phaser_info = { 0x847d, "phaser", "Calf Phaser", "Krzysztof Foltman", copyright, "PhaserPlugin" };
+
+ALL_WRAPPERS(phaser)
+
+////////////////////////////////////////////////////////////////////////////
+
const char *reverb_audio_module::port_names[] = {"In L", "In R", "Out L", "Out R"};
const char *reverb_room_sizes[] = { "Small", "Medium", "Large", "Tunnel-like" };
@@ -172,6 +191,7 @@ const LV2_Descriptor *lv2_descriptor(uint32_t index)
case 4: return &::lv2_monosynth.descriptor;
case 5: return &::lv2_organ.descriptor;
case 6: return &::lv2_rotary_speaker.descriptor;
+ case 7: return &::lv2_phaser.descriptor;
#ifdef ENABLE_EXPERIMENTAL
#endif
default: return NULL;
@@ -192,6 +212,7 @@ const LADSPA_Descriptor *ladspa_descriptor(unsigned long Index)
case 2: return &::ladspa_reverb.descriptor;
case 3: return &::ladspa_vintage_delay.descriptor;
case 4: return &::ladspa_rotary_speaker.descriptor;
+ case 5: return &::ladspa_phaser.descriptor;
#ifdef ENABLE_EXPERIMENTAL
#endif
default: return NULL;
@@ -213,6 +234,7 @@ const DSSI_Descriptor *dssi_descriptor(unsigned long Index)
case 4: return &::ladspa_vintage_delay.dssi_descriptor;
case 5: return &::ladspa_organ.dssi_descriptor;
case 6: return &::ladspa_rotary_speaker.dssi_descriptor;
+ case 7: return &::ladspa_phaser.dssi_descriptor;
#ifdef ENABLE_EXPERIMENTAL
#endif
default: return NULL;
@@ -259,4 +281,5 @@ void synth::get_all_plugins(std::vector<giface_plugin_info> &plugins)
plugins.push_back(create_plugin_info<vintage_delay_audio_module>(vintage_delay_info));
plugins.push_back(create_plugin_info<organ_audio_module>(organ_info));
plugins.push_back(create_plugin_info<rotary_speaker_audio_module>(rotary_speaker_info));
+ plugins.push_back(create_plugin_info<phaser_audio_module>(phaser_info));
}
diff --git a/src/organ.cpp b/src/organ.cpp
index 08f88d1..5ff5685 100644
--- a/src/organ.cpp
+++ b/src/organ.cpp
@@ -62,60 +62,69 @@ const char *organ_audio_module::get_gui_xml()
"<value param=\"master\"/>"
"</vbox>"
"</hbox>"
- "<table rows=\"5\" cols=\"9\">"
+ "<table rows=\"6\" cols=\"9\">"
"<label attach-x=\"0\" attach-y=\"0\" param=\"h1\"/>"
"<vscale attach-x=\"0\" attach-y=\"1\" param=\"h1\"/>"
"<value attach-x=\"0\" attach-y=\"2\" param=\"h1\"/>"
"<knob attach-x=\"0\" attach-y=\"3\" param=\"f1\"/>"
"<value attach-x=\"0\" attach-y=\"4\" param=\"f1\"/>"
+ "<combo attach-x=\"0\" attach-y=\"5\" param=\"w1\"/>"
"<label attach-x=\"1\" attach-y=\"0\" param=\"h3\"/>"
"<vscale attach-x=\"1\" attach-y=\"1\" param=\"h3\"/>"
"<value attach-x=\"1\" attach-y=\"2\" param=\"h3\"/>"
"<knob attach-x=\"1\" attach-y=\"3\" param=\"f2\"/>"
"<value attach-x=\"1\" attach-y=\"4\" param=\"f2\"/>"
+ "<combo attach-x=\"1\" attach-y=\"5\" param=\"w2\"/>"
"<label attach-x=\"2\" attach-y=\"0\" param=\"h2\"/>"
"<vscale attach-x=\"2\" attach-y=\"1\" param=\"h2\"/>"
"<value attach-x=\"2\" attach-y=\"2\" param=\"h2\"/>"
"<knob attach-x=\"2\" attach-y=\"3\" param=\"f3\"/>"
"<value attach-x=\"2\" attach-y=\"4\" param=\"f3\"/>"
+ "<combo attach-x=\"2\" attach-y=\"5\" param=\"w3\"/>"
"<label attach-x=\"3\" attach-y=\"0\" param=\"h4\"/>"
"<vscale attach-x=\"3\" attach-y=\"1\" param=\"h4\"/>"
"<value attach-x=\"3\" attach-y=\"2\" param=\"h4\"/>"
"<knob attach-x=\"3\" attach-y=\"3\" param=\"f4\"/>"
"<value attach-x=\"3\" attach-y=\"4\" param=\"f4\"/>"
+ "<combo attach-x=\"3\" attach-y=\"5\" param=\"w4\"/>"
"<label attach-x=\"4\" attach-y=\"0\" param=\"h6\"/>"
"<vscale attach-x=\"4\" attach-y=\"1\" param=\"h6\"/>"
"<value attach-x=\"4\" attach-y=\"2\" param=\"h6\"/>"
"<knob attach-x=\"4\" attach-y=\"3\" param=\"f5\"/>"
"<value attach-x=\"4\" attach-y=\"4\" param=\"f5\"/>"
+ "<combo attach-x=\"4\" attach-y=\"5\" param=\"w5\"/>"
"<label attach-x=\"5\" attach-y=\"0\" param=\"h8\"/>"
"<vscale attach-x=\"5\" attach-y=\"1\" param=\"h8\"/>"
"<value attach-x=\"5\" attach-y=\"2\" param=\"h8\"/>"
"<knob attach-x=\"5\" attach-y=\"3\" param=\"f6\"/>"
"<value attach-x=\"5\" attach-y=\"4\" param=\"f6\"/>"
+ "<combo attach-x=\"5\" attach-y=\"5\" param=\"w6\"/>"
"<label attach-x=\"6\" attach-y=\"0\" param=\"h10\"/>"
"<vscale attach-x=\"6\" attach-y=\"1\" param=\"h10\"/>"
"<value attach-x=\"6\" attach-y=\"2\" param=\"h10\"/>"
"<knob attach-x=\"6\" attach-y=\"3\" param=\"f7\"/>"
"<value attach-x=\"6\" attach-y=\"4\" param=\"f7\"/>"
+ "<combo attach-x=\"6\" attach-y=\"5\" param=\"w7\"/>"
"<label attach-x=\"7\" attach-y=\"0\" param=\"h12\"/>"
"<vscale attach-x=\"7\" attach-y=\"1\" param=\"h12\"/>"
"<value attach-x=\"7\" attach-y=\"2\" param=\"h12\"/>"
"<knob attach-x=\"7\" attach-y=\"3\" param=\"f8\"/>"
"<value attach-x=\"7\" attach-y=\"4\" param=\"f8\"/>"
+ "<combo attach-x=\"7\" attach-y=\"5\" param=\"w8\"/>"
"<label attach-x=\"8\" attach-y=\"0\" param=\"h16\"/>"
"<vscale attach-x=\"8\" attach-y=\"1\" param=\"h16\"/>"
"<value attach-x=\"8\" attach-y=\"2\" param=\"h16\"/>"
"<knob attach-x=\"8\" attach-y=\"3\" param=\"f9\"/>"
"<value attach-x=\"8\" attach-y=\"4\" param=\"f9\"/>"
+ "<combo attach-x=\"8\" attach-y=\"5\" param=\"w9\"/>"
"</table>"
"</vbox>"
;
@@ -125,6 +134,8 @@ const char *organ_audio_module::port_names[] = {"Out L", "Out R"};
const char *organ_percussion_harmonic_names[] = { "2nd", "3rd" };
+const char *organ_wave_names[] = { "Sin", "Pls", "S+1", "S+2", "S+3", "Saw", "Sqr", "SSaw", "SSqr" };
+
parameter_properties organ_audio_module::param_props[] = {
{ 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h1", "16'" },
{ 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h3", "5 1/3'" },
@@ -136,25 +147,25 @@ parameter_properties organ_audio_module::param_props[] = {
{ 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h12", "1 1/3'" },
{ 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h16", "1'" },
- { 1, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f1", "Freq 1" },
- { 3, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f2", "Freq 2" },
- { 2, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f3", "Freq 3" },
- { 4, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f4", "Freq 4" },
- { 6, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f5", "Freq 5" },
- { 8, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f6", "Freq 6" },
- { 10, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f7", "Freq 7" },
- { 12, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f8", "Freq 8" },
- { 16, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f9", "Freq 9" },
-
- { 2, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w1", "Wave 1" },
- { 2, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w2", "Wave 2" },
- { 1, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w3", "Wave 3" },
- { 1, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w4", "Wave 4" },
- { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w5", "Wave 5" },
- { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w6", "Wave 6" },
- { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w7", "Wave 7" },
- { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w8", "Wave 8" },
- { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w9", "Wave 9" },
+ { 1, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f1", "Freq 1" },
+ { 3, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f2", "Freq 2" },
+ { 2, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f3", "Freq 3" },
+ { 4, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f4", "Freq 4" },
+ { 6, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f5", "Freq 5" },
+ { 8, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f6", "Freq 6" },
+ { 10, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f7", "Freq 7" },
+ { 12, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f8", "Freq 8" },
+ { 16, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "f9", "Freq 9" },
+
+ { 0, 0, 8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w1", "Wave 1" },
+ { 0, 0, 8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w2", "Wave 2" },
+ { 0, 0, 8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w3", "Wave 3" },
+ { 0, 0, 8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w4", "Wave 4" },
+ { 0, 0, 8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w5", "Wave 5" },
+ { 0, 0, 8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w6", "Wave 6" },
+ { 0, 0, 8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w7", "Wave 7" },
+ { 0, 0, 8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w8", "Wave 8" },
+ { 0, 0, 8, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_wave_names, "w9", "Wave 9" },
{ 1, 0, 1, 2, PF_BOOL | PF_CTL_TOGGLE, NULL, "foldover", "Foldover" },
{ 200, 10, 3000, 100, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "perc_decay", "Perc. decay" },
@@ -194,7 +205,43 @@ organ_voice_base::organ_voice_base(organ_parameters *_parameters)
normalize_waveform(tmp, ORGAN_WAVE_SIZE);
waves[wave_pulse].make(bl, tmp);
for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+ tmp[i] = i < (ORGAN_WAVE_SIZE / 2) ? sin(i * 2 * 2 * M_PI / ORGAN_WAVE_SIZE) : 0;
+ waves[wave_sinepl1].make(bl, tmp);
+ for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+ tmp[i] = i < (ORGAN_WAVE_SIZE / 3) ? sin(i * 3 * 2 * M_PI / ORGAN_WAVE_SIZE) : 0;
+ waves[wave_sinepl2].make(bl, tmp);
+ for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
tmp[i] = i < (ORGAN_WAVE_SIZE / 4) ? sin(i * 4 * 2 * M_PI / ORGAN_WAVE_SIZE) : 0;
- waves[wave_stretchsine].make(bl, tmp);
+ waves[wave_sinepl3].make(bl, tmp);
+ for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+ tmp[i] = (i < (ORGAN_WAVE_SIZE / 2)) ? 1 : -1;
+ normalize_waveform(tmp, ORGAN_WAVE_SIZE);
+ waves[wave_sqr].make(bl, tmp);
+ for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+ tmp[i] = -1 + (i * 2.0 / ORGAN_WAVE_SIZE);
+ normalize_waveform(tmp, ORGAN_WAVE_SIZE);
+ waves[wave_saw].make(bl, tmp);
+
+ for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+ tmp[i] = (i < (ORGAN_WAVE_SIZE / 2)) ? 1 : -1;
+ bl.compute_spectrum(tmp);
+ for (int i = 1; i <= ORGAN_WAVE_SIZE / 2; i++) {
+ bl.spectrum[i] *= 1.0 / sqrt(i);
+ bl.spectrum[ORGAN_WAVE_SIZE - i] *= 1.0 / sqrt(i);
+ }
+ bl.compute_waveform(tmp);
+ normalize_waveform(tmp, ORGAN_WAVE_SIZE);
+ waves[wave_ssqr].make(bl, tmp);
+
+ for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+ tmp[i] = -1 + (i * 2.0 / ORGAN_WAVE_SIZE);
+ bl.compute_spectrum(tmp);
+ for (int i = 1; i <= ORGAN_WAVE_SIZE / 2; i++) {
+ bl.spectrum[i] *= 1.0 / sqrt(i);
+ bl.spectrum[ORGAN_WAVE_SIZE - i] *= 1.0 / sqrt(i);
+ }
+ bl.compute_waveform(tmp);
+ normalize_waveform(tmp, ORGAN_WAVE_SIZE);
+ waves[wave_ssaw].make(bl, tmp);
}
}
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list