[SCM] calf/master: Replace allpass vibrato in Calf Organ with a simulation of scanner vibrato.
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:40:35 UTC 2013
The following commit has been merged in the master branch:
commit d1ef2162983bdf24459be71cfd6065416d6aadad
Author: Krzysztof Foltman <wdev at foltman.com>
Date: Sun Jan 16 15:18:54 2011 +0000
Replace allpass vibrato in Calf Organ with a simulation of scanner vibrato.
This is unfinished: I should add the way to switch to the old mode and to
choose between scanner topologies (C1/C2/C3/full).
diff --git a/src/calf/organ.h b/src/calf/organ.h
index ac41599..969bd6d 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -174,6 +174,7 @@ public:
void perc_reset();
};
+/// A simple (and bad) simulation of scanner vibrato based on a series of modulated allpass filters
class organ_vibrato
{
protected:
@@ -186,6 +187,30 @@ public:
void process(organ_parameters *parameters, float (*data)[2], unsigned int len, float sample_rate);
};
+/// A more sophisticated simulation of scanner vibrato. Simulates a line box
+/// and an interpolating scanner. The line box is a series of 18 2nd order
+/// lowpass filters with cutoff frequency ~4kHz, with loss compensation.
+/// The interpolating scanner uses linear interpolation to "slide" between
+/// selected outputs of the line box.
+///
+/// @note
+/// This is a true CPU hog, and it should be optimised some day.
+/// @note
+/// The line box is mono. 36 lowpass filters might be an overkill.
+/// @note
+/// See also: http://www.jhaible.de/interpolating_scanner_and_scanvib/jh_interpolating_scanner_and_scanvib.html
+/// (though it's a very loose adaptation of that version)
+class scanner_vibrato
+{
+protected:
+ enum { ScannerSize = 18 };
+ float lfo_phase;
+ dsp::biquad_d2<float> scanner[ScannerSize];
+public:
+ void reset();
+ void process(organ_parameters *parameters, float (*data)[2], unsigned int len, float sample_rate);
+};
+
class organ_voice: public dsp::voice, public organ_voice_base {
protected:
enum { Channels = 2, BlockSize = 64, EnvCount = organ_parameters::EnvCount, FilterCount = organ_parameters::FilterCount };
@@ -197,7 +222,7 @@ protected:
dsp::biquad_d1<float> filterL[2], filterR[2];
adsr envs[EnvCount];
dsp::inertia<dsp::linear_ramp> expression;
- organ_vibrato vibrato;
+ scanner_vibrato vibrato;
float velocity;
bool perc_released;
/// The envelopes have ended and the voice is in final fadeout stage
@@ -260,7 +285,7 @@ public:
struct drawbar_organ: public dsp::basic_synth, public calf_plugins::organ_enums {
organ_parameters *parameters;
percussion_voice percussion;
- organ_vibrato global_vibrato;
+ scanner_vibrato global_vibrato;
two_band_eq eq_l, eq_r;
drawbar_organ(organ_parameters *_parameters)
diff --git a/src/metadata.cpp b/src/metadata.cpp
index e6d5d36..b83e43c 100644
--- a/src/metadata.cpp
+++ b/src/metadata.cpp
@@ -987,8 +987,8 @@ CALF_PORT_PROPS(organ) = {
{ 0, 0, organ_enums::ampctl_count - 1,
0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "eg3_amp_ctl", "EG3 To Amp"},
- { 6.6, 0.01, 80, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "vib_rate", "Vib Rate" },
- { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_amt", "Vib Mod Amt" },
+ { 6.6, 0.01, 240, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "vib_rate", "Vib Rate" },
+ { 1.0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_amt", "Vib Mod Amt" },
{ 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "vib_wet", "Vib Wet" },
{ 180, 0, 360, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "vib_phase", "Vib Stereo" },
{ organ_enums::lfomode_global, 0, organ_enums::lfomode_count - 1, 0, PF_ENUM | PF_CTL_COMBO, organ_vibrato_mode_names, "vib_mode", "Vib Mode" },
diff --git a/src/organ.cpp b/src/organ.cpp
index 3435607..e592e4f 100644
--- a/src/organ.cpp
+++ b/src/organ.cpp
@@ -611,6 +611,76 @@ void organ_vibrato::process(organ_parameters *parameters, float (*data)[2], unsi
}
}
+void scanner_vibrato::reset()
+{
+ for (int i = 0; i < ScannerSize; i++)
+ scanner[i].reset();
+ lfo_phase = 0.f;
+}
+
+void scanner_vibrato::process(organ_parameters *parameters, float (*data)[2], unsigned int len, float sample_rate)
+{
+ if (!len)
+ return;
+
+ // I bet the original components of the line box had some tolerance,
+ // hence two different values of cutoff frequency
+ scanner[0].set_lp_rbj(4000, 0.707, sample_rate);
+ scanner[1].set_lp_rbj(4200, 0.707, sample_rate);
+ for (int t = 2; t < ScannerSize; t ++)
+ {
+ scanner[t].copy_coeffs(scanner[t & 1]);
+ }
+
+ float lfo_phase2 = lfo_phase + parameters->lfo_phase * (1.0 / 360.0);
+ if (lfo_phase2 >= 1.0)
+ lfo_phase2 -= 1.0;
+ float vib_wet = parameters->lfo_wet;
+ float dphase = parameters->lfo_rate / sample_rate;
+ static const int v1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8 };
+ static const int v2[] = { 0, 1, 2, 4, 6, 8, 9, 10, 12 };
+ static const int v3[] = { 0, 1, 3, 6, 11, 12, 15, 17, 18, 18, 18 };
+ const int *vib = v1;
+ static int sums[9];
+ float vibamt = 8 * parameters->lfo_amt;
+ for (unsigned int i = 0; i < len; i++)
+ {
+ float line[ScannerSize + 1];
+ float v0 = (data[i][0] + data[i][1]) * 0.5;
+
+ line[0] = v0;
+ for (int t = 0; t < ScannerSize; t++)
+ line[t + 1] = scanner[t].process(line[t]) * 1.06;
+
+ float lfo1 = lfo_phase < 0.5 ? 2 * lfo_phase : 2 - 2 * lfo_phase;
+ float lfo2 = lfo_phase2 < 0.5 ? 2 * lfo_phase2 : 2 - 2 * lfo_phase2;
+
+ float pos = vibamt * lfo1;
+ int ipos = (int)pos;
+ float vl = lerp(line[vib[ipos]], line[vib[ipos + 1]], pos - ipos);
+
+ pos = vibamt * lfo2;
+ ipos = (int)pos;
+ float vr = lerp(line[vib[ipos]], line[vib[ipos + 1]], pos - ipos);
+
+ for (int t = 0; t < 9; t++)
+ sums[t] += fabs(line[vib[t]]);
+
+ lfo_phase += dphase;
+ if (lfo_phase >= 1.0)
+ lfo_phase -= 1.0;
+ lfo_phase2 += dphase;
+ if (lfo_phase2 >= 1.0)
+ lfo_phase2 -= 1.0;
+
+ data[i][0] += (vl - v0) * vib_wet;
+ data[i][1] += (vr - v0) * vib_wet;
+ }
+ for (int t = 0; t < ScannerSize; t++)
+ {
+ scanner[t].sanitize();
+ }
+}
//////////////////////////////////////////////////////////////////////////////////////////////////////
void organ_voice::update_pitch()
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list