[SCM] calf/master: + Organ: added LFO mode parameter (off, direct/filter1/filter2, voice, global)
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:37:10 UTC 2013
The following commit has been merged in the master branch:
commit e803124b37ebaa8be1b602ddf7394fe6699ba7a6
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Wed Apr 30 20:33:41 2008 +0000
+ Organ: added LFO mode parameter (off, direct/filter1/filter2, voice, global)
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@165 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/src/calf/modules_synths.h b/src/calf/modules_synths.h
index 75afe40..c2a8b87 100644
--- a/src/calf/modules_synths.h
+++ b/src/calf/modules_synths.h
@@ -196,23 +196,6 @@ public:
using drawbar_organ::note_on;
using drawbar_organ::note_off;
using drawbar_organ::control_change;
- enum {
- par_drawbar1, par_drawbar2, par_drawbar3, par_drawbar4, par_drawbar5, par_drawbar6, par_drawbar7, par_drawbar8, par_drawbar9,
- par_frequency1, par_frequency2, par_frequency3, par_frequency4, par_frequency5, par_frequency6, par_frequency7, par_frequency8, par_frequency9,
- par_waveform1, par_waveform2, par_waveform3, par_waveform4, par_waveform5, par_waveform6, par_waveform7, par_waveform8, par_waveform9,
- par_detune1, par_detune2, par_detune3, par_detune4, par_detune5, par_detune6, par_detune7, par_detune8, par_detune9,
- par_phase1, par_phase2, par_phase3, par_phase4, par_phase5, par_phase6, par_phase7, par_phase8, par_phase9,
- par_pan1, par_pan2, par_pan3, par_pan4, par_pan5, par_pan6, par_pan7, par_pan8, par_pan9,
- par_routing1, par_routing2, par_routing3, par_routing4, par_routing5, par_routing6, par_routing7, par_routing8, par_routing9,
- par_foldover,
- par_percdecay, par_perclevel, par_percharm, par_master,
- par_f1cutoff, par_f1res, par_f1env1, par_f1env2, par_f1env3, par_f1keyf,
- par_f2cutoff, par_f2res, par_f2env1, par_f2env2, par_f2env3, par_f2keyf,
- par_eg1attack, par_eg1decay, par_eg1sustain, par_eg1release, par_eg1velscl, par_eg1ampctl,
- par_eg2attack, par_eg2decay, par_eg2sustain, par_eg2release, par_eg2velscl, par_eg2ampctl,
- par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3release, par_eg3velscl, par_eg3ampctl,
- par_lforate, par_lfoamt, par_lfowet, par_lfophase,
- param_count };
enum { in_count = 0, out_count = 2, support_midi = true, rt_capable = true };
static const char *port_names[];
float *ins[in_count];
@@ -243,7 +226,7 @@ public:
}
uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
float *o[2] = { outs[0] + offset, outs[1] + offset };
- render_to(o, nsamples);
+ render_separate(o, nsamples);
return 3;
}
static const char *get_name() { return "organ"; }
diff --git a/src/calf/organ.h b/src/calf/organ.h
index e4857c1..16a09fc 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -61,6 +61,7 @@ struct organ_parameters {
float lfo_amt;
float lfo_wet;
float lfo_phase;
+ float lfo_mode;
double perc_decay_const;
float multiplier[9];
@@ -92,6 +93,15 @@ public:
ampctl_all,
ampctl_count
};
+ enum {
+ lfomode_off = 0,
+ lfomode_direct,
+ lfomode_filter1,
+ lfomode_filter2,
+ lfomode_voice,
+ lfomode_global,
+ lfomode_count
+ };
protected:
static waveform_family<ORGAN_WAVE_BITS> waves[wave_count];
// dsp::sine_table<float, ORGAN_WAVE_SIZE, 1> sine_wave;
@@ -107,9 +117,21 @@ public:
organ_parameters *parameters;
};
+class organ_vibrato
+{
+protected:
+ enum { VibratoSize = 6 };
+ float vibrato_x1[VibratoSize][2], vibrato_y1[VibratoSize][2];
+ float lfo_phase;
+ onepole<float> vibrato[2];
+public:
+ void reset();
+ void process(organ_parameters *parameters, float (*data)[2], unsigned int len, float sample_rate);
+};
+
class organ_voice: public synth::voice, public organ_voice_base {
protected:
- enum { Channels = 2, BlockSize = 64, EnvCount = organ_parameters::EnvCount, FilterCount = organ_parameters::FilterCount, VibratoSize = 6 };
+ enum { Channels = 2, BlockSize = 64, EnvCount = organ_parameters::EnvCount, FilterCount = organ_parameters::FilterCount };
union {
float output_buffer[BlockSize][Channels];
float aux_buffers[3][BlockSize][Channels];
@@ -117,11 +139,10 @@ protected:
bool released;
dsp::fixed_point<int64_t, 52> phase, dphase;
biquad<float> filterL[2], filterR[2];
- onepole<float> vibrato[2];
- float vibrato_x1[VibratoSize][2], vibrato_y1[VibratoSize][2];
adsr envs[EnvCount];
inertia<linear_ramp> expression;
- float velocity, lfo_phase;
+ organ_vibrato vibrato;
+ float velocity;
public:
organ_voice()
@@ -130,19 +151,17 @@ public:
}
void reset() {
+ vibrato.reset();
phase = 0;
for (int i = 0; i < FilterCount; i++)
{
filterL[i].reset();
filterR[i].reset();
}
- for (int i = 0; i < VibratoSize; i++)
- vibrato_x1[i][0] = vibrato_y1[i][0] = vibrato_x1[i][1] = vibrato_y1[i][1] = 0.f;
}
void note_on(int note, int vel) {
reset();
- this->lfo_phase = 0.f;
this->note = note;
const float sf = 0.001f;
for (int i = 0; i < EnvCount; i++)
@@ -196,7 +215,7 @@ public:
}
// this doesn't really have a voice interface
- void render_to(float *buf[2], int nsamples) {
+ void render_to(float (*buf)[2], int nsamples) {
if (note == -1)
return;
@@ -212,8 +231,8 @@ public:
for (int i = 0; i < nsamples; i++) {
float osc = level * wave(data, percussion_harmonic * phase);
osc *= level * amp.get();
- buf[0][i] += osc;
- buf[1][i] += osc;
+ buf[i][0] += osc;
+ buf[i][1] += osc;
amp.age_exp(age_const, 1.0 / 32768.0);
phase += dphase;
}
@@ -229,23 +248,44 @@ public:
struct drawbar_organ: public synth::basic_synth {
organ_parameters *parameters;
percussion_voice percussion;
+ organ_vibrato global_vibrato;
- drawbar_organ(organ_parameters *_parameters)
+ enum {
+ par_drawbar1, par_drawbar2, par_drawbar3, par_drawbar4, par_drawbar5, par_drawbar6, par_drawbar7, par_drawbar8, par_drawbar9,
+ par_frequency1, par_frequency2, par_frequency3, par_frequency4, par_frequency5, par_frequency6, par_frequency7, par_frequency8, par_frequency9,
+ par_waveform1, par_waveform2, par_waveform3, par_waveform4, par_waveform5, par_waveform6, par_waveform7, par_waveform8, par_waveform9,
+ par_detune1, par_detune2, par_detune3, par_detune4, par_detune5, par_detune6, par_detune7, par_detune8, par_detune9,
+ par_phase1, par_phase2, par_phase3, par_phase4, par_phase5, par_phase6, par_phase7, par_phase8, par_phase9,
+ par_pan1, par_pan2, par_pan3, par_pan4, par_pan5, par_pan6, par_pan7, par_pan8, par_pan9,
+ par_routing1, par_routing2, par_routing3, par_routing4, par_routing5, par_routing6, par_routing7, par_routing8, par_routing9,
+ par_foldover,
+ par_percdecay, par_perclevel, par_percharm, par_master,
+ par_f1cutoff, par_f1res, par_f1env1, par_f1env2, par_f1env3, par_f1keyf,
+ par_f2cutoff, par_f2res, par_f2env1, par_f2env2, par_f2env3, par_f2keyf,
+ par_eg1attack, par_eg1decay, par_eg1sustain, par_eg1release, par_eg1velscl, par_eg1ampctl,
+ par_eg2attack, par_eg2decay, par_eg2sustain, par_eg2release, par_eg2velscl, par_eg2ampctl,
+ par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3release, par_eg3velscl, par_eg3ampctl,
+ par_lforate, par_lfoamt, par_lfowet, par_lfophase, par_lfomode,
+ param_count
+ };
+
+ drawbar_organ(organ_parameters *_parameters)
: parameters(_parameters)
, percussion(_parameters) {
}
- void render_to(float *output[], int nsamples)
+ void render_separate(float *output[], int nsamples)
{
- float buf[2][4096], *bufptr[] = { buf[0], buf[1] };
- dsp::zero(buf[0], nsamples);
- dsp::zero(buf[1], nsamples);
- basic_synth::render_to(bufptr, nsamples);
+ float buf[4096][2];
+ dsp::zero(&buf[0][0], 2 * nsamples);
+ basic_synth::render_to(buf, nsamples);
+ if (fastf2i_drm(parameters->lfo_mode) == organ_voice_base::lfomode_global)
+ global_vibrato.process(parameters, buf, nsamples, sample_rate);
if (percussion.get_active())
- percussion.render_to(bufptr, nsamples);
+ percussion.render_to(buf, nsamples);
float gain = parameters->master * (1.0 / (9 * 8));
for (int i=0; i<nsamples; i++) {
- output[0][i] = gain*buf[0][i];
- output[1][i] = gain*buf[1][i];
+ output[0][i] = gain*buf[i][0];
+ output[1][i] = gain*buf[i][1];
}
}
synth::voice *alloc_voice() {
diff --git a/src/calf/synth.h b/src/calf/synth.h
index 797fc05..4d74eab 100644
--- a/src/calf/synth.h
+++ b/src/calf/synth.h
@@ -118,7 +118,7 @@ public:
/// check if voice can be removed from active voice list
virtual bool get_active()=0;
/// render voice data to buffer
- virtual void render_to(float *buf[], int nsamples)=0;
+ virtual void render_to(float (*buf)[2], int nsamples)=0;
/// return the note used by this voice
virtual int get_current_note()=0;
/// empty virtual destructor
@@ -153,7 +153,7 @@ public:
Base::reset();
read_ptr = BlockSize;
}
- virtual void render_to(float *buf[], int nsamples)
+ virtual void render_to(float (*buf)[2], int nsamples)
{
int p = 0;
while(p < nsamples)
@@ -166,7 +166,7 @@ public:
int ncopy = std::min<int>(BlockSize - read_ptr, nsamples - p);
for (int i = 0; i < ncopy; i++)
for (int c = 0; c < Channels; c++)
- buf[c][p + i] += output_buffer[read_ptr + i][c];
+ buf[p + i][c] += output_buffer[read_ptr + i][c];
p += ncopy;
read_ptr += ncopy;
}
@@ -197,7 +197,7 @@ public:
}
virtual synth::voice *give_voice();
virtual synth::voice *alloc_voice()=0;
- virtual void render_to(float *output[], int nsamples);
+ virtual void render_to(float (*output)[2], int nsamples);
virtual void note_on(int note, int vel);
virtual void first_note_on(int note, int vel) {}
virtual void control_change(int ctl, int val);
diff --git a/src/organ.cpp b/src/organ.cpp
index 2a415e3..0276bc3 100644
--- a/src/organ.cpp
+++ b/src/organ.cpp
@@ -256,22 +256,26 @@ const char *organ_audio_module::get_gui_xml()
"</vbox>"
"<frame label=\"LFO\">"
"<vbox>"
- "<vbox>"
+ "<vbox expand=\"0\" fill=\"0\">"
"<label param=\"vib_rate\" />"
"<align><knob param=\"vib_rate\" expand=\"0\" fill=\"0\"/></align><value param=\"vib_rate\"/>"
"</vbox>"
- "<vbox>"
+ "<vbox expand=\"0\" fill=\"0\">"
"<label param=\"vib_amt\" />"
"<align><knob param=\"vib_amt\" expand=\"0\" fill=\"0\"/></align><value param=\"vib_amt\"/>"
"</vbox>"
- "<vbox>"
+ "<vbox expand=\"0\" fill=\"0\">"
"<label param=\"vib_wet\" />"
"<align><knob param=\"vib_wet\" expand=\"0\" fill=\"0\"/></align><value param=\"vib_wet\"/>"
"</vbox>"
- "<vbox>"
+ "<vbox expand=\"0\" fill=\"0\">"
"<label param=\"vib_phase\" />"
"<align><knob param=\"vib_phase\" expand=\"0\" fill=\"0\"/></align><value param=\"vib_phase\"/>"
"</vbox>"
+ "<vbox expand=\"0\" fill=\"0\">"
+ "<label param=\"vib_mode\" />"
+ "<combo param=\"vib_mode\" expand=\"0\" fill=\"0\"/>"
+ "</vbox>"
"</vbox>"
"</frame>"
"</hbox>"
@@ -299,6 +303,8 @@ const char *organ_routing_names[] = { "Out", "Flt 1", "Flt 2" };
const char *organ_ampctl_names[] = { "None", "Direct", "Flt 1", "Flt 2", "All" };
+const char *organ_vibrato_mode_names[] = { "None", "Direct", "Flt 1", "Flt 2", "Voice", "Global" };
+
parameter_properties organ_audio_module::param_props[] = {
{ 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l1", "16'" },
{ 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "l2", "5 1/3'" },
@@ -419,6 +425,7 @@ parameter_properties organ_audio_module::param_props[] = {
{ 0.5, 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_voice_base::lfomode_global, 0, organ_voice_base::lfomode_count - 1, 0, PF_ENUM | PF_CTL_COMBO, organ_vibrato_mode_names, "vib_mode", "Vib Mode" },
// { 0, 0, organ_voice_base::ampctl_count - 1,
// 0, PF_INT | PF_CTL_COMBO, organ_ampctl_names, "vel_amp_ctl", "Vel To Amp"},
};
@@ -443,7 +450,8 @@ static void phaseshift(bandlimiter<ORGAN_WAVE_BITS> &bl, float tmp[ORGAN_WAVE_SI
{
bl.compute_spectrum(tmp);
for (int i = 1; i <= ORGAN_WAVE_SIZE / 2; i++) {
- float phase = sin(i*i);
+ float frac = i * 2.0 / ORGAN_WAVE_SIZE;
+ float phase = 2 * M_PI * frac * frac;
complex<float> shift = complex<float>(cos(phase), sin(phase));
bl.spectrum[i] *= shift;
bl.spectrum[ORGAN_WAVE_SIZE - i] *= conj(shift);
@@ -615,6 +623,46 @@ organ_voice_base::organ_voice_base(organ_parameters *_parameters)
}
}
+void organ_vibrato::reset()
+{
+ for (int i = 0; i < VibratoSize; i++)
+ vibrato_x1[i][0] = vibrato_y1[i][0] = vibrato_x1[i][1] = vibrato_y1[i][1] = 0.f;
+ lfo_phase = 0.f;
+}
+
+void organ_vibrato::process(organ_parameters *parameters, float (*data)[2], unsigned int len, float sample_rate)
+{
+ float lfo1 = lfo_phase < 0.5 ? 2 * lfo_phase : 2 - 2 * lfo_phase;
+ float lfo_phase2 = lfo_phase + parameters->lfo_phase * (1.0 / 360.0);
+ if (lfo_phase2 >= 1.0)
+ lfo_phase2 -= 1.0;
+ float lfo2 = lfo_phase2 < 0.5 ? 2 * lfo_phase2 : 2 - 2 * lfo_phase2;
+ lfo_phase += parameters->lfo_rate * len / sample_rate;
+ if (lfo_phase >= 1.0)
+ lfo_phase -= 1.0;
+ vibrato[0].set_ap(3000 + 7000 * parameters->lfo_amt * lfo1 * lfo1, sample_rate);
+ vibrato[1].set_ap(3000 + 7000 * parameters->lfo_amt * lfo2 * lfo2, sample_rate);
+
+ float vib_wet = parameters->lfo_wet;
+ for (int c = 0; c < 2; c++)
+ {
+ for (unsigned int i = 0; i < len; i++)
+ {
+ float v = data[i][c];
+ float v0 = v;
+ for (int t = 0; t < VibratoSize; t++)
+ v = vibrato[c].process_ap(v, vibrato_x1[t][c], vibrato_y1[t][c]);
+
+ data[i][c] += (v - v0) * vib_wet;
+ }
+ for (int t = 0; t < VibratoSize; t++)
+ {
+ sanitize(vibrato_x1[t][c]);
+ sanitize(vibrato_y1[t][c]);
+ }
+ }
+}
+
void organ_voice::render_block() {
if (note == -1)
return;
@@ -626,6 +674,7 @@ void organ_voice::render_block() {
dsp::fixed_point<int, 20> tphase, tdphase;
unsigned int foldvalue = parameters->foldvalue;
+ int vibrato_mode = fastf2i_drm(parameters->lfo_mode);
int muln = 0;
for (int h = 0; h < 9; h++)
{
@@ -704,6 +753,8 @@ void organ_voice::render_block() {
amp_pre[mode - 1] *= pre;
amp_post[mode - 1] *= post;
}
+ if (vibrato_mode >= lfomode_direct && vibrato_mode <= lfomode_filter2)
+ vibrato.process(parameters, aux_buffers[vibrato_mode - lfomode_direct], BlockSize, sample_rate);
if (!any_running)
released = true;
// calculate delta from pre and post
@@ -716,36 +767,9 @@ void organ_voice::render_block() {
output_buffer[i][1] = a3 * (a0 * output_buffer[i][1] + a1 * filterR[0].process_d1(aux_buffers[1][i][1]) + a2 * filterR[1].process_d1(aux_buffers[2][i][1]));
a0 += d0, a1 += d1, a2 += d2, a3 += d3;
}
+ if (vibrato_mode == lfomode_voice)
+ vibrato.process(parameters, output_buffer, BlockSize, sample_rate);
- float lfo1 = lfo_phase < 0.5 ? 2 * lfo_phase : 2 - 2 * lfo_phase;
- float lfo_phase2 = lfo_phase + parameters->lfo_phase * (1.0 / 360.0);
- if (lfo_phase2 >= 1.0)
- lfo_phase2 -= 1.0;
- float lfo2 = lfo_phase2 < 0.5 ? 2 * lfo_phase2 : 2 - 2 * lfo_phase2;
- lfo_phase += parameters->lfo_rate * BlockSize / sample_rate;
- if (lfo_phase >= 1.0)
- lfo_phase -= 1.0;
- vibrato[0].set_ap(3000 + 7000 * parameters->lfo_amt * lfo1 * lfo1, sample_rate);
- vibrato[1].set_ap(3000 + 7000 * parameters->lfo_amt * lfo2 * lfo2, sample_rate);
-
- float vib_wet = parameters->lfo_wet;
- for (int c = 0; c < 2; c++)
- {
- for (int i = 0; i < (int) BlockSize; i++)
- {
- float v = output_buffer[i][c];
- float v0 = v;
- for (int t = 0; t < VibratoSize; t++)
- v = vibrato[c].process_ap(v, vibrato_x1[t][c], vibrato_y1[t][c]);
-
- output_buffer[i][c] += (v - v0) * vib_wet;
- }
- for (int t = 0; t < VibratoSize; t++)
- {
- sanitize(vibrato_x1[t][c]);
- sanitize(vibrato_y1[t][c]);
- }
- }
if (released)
{
for (int i = 0; i < (int) BlockSize; i++) {
diff --git a/src/synth.cpp b/src/synth.cpp
index eb137a1..682be9b 100644
--- a/src/synth.cpp
+++ b/src/synth.cpp
@@ -154,7 +154,7 @@ void basic_synth::control_change(int ctl, int val)
}
}
-void basic_synth::render_to(float *output[], int nsamples)
+void basic_synth::render_to(float (*output)[2], int nsamples)
{
// render voices, eliminate ones that aren't sounding anymore
for (list<synth::voice *>::iterator i = active_voices.begin(); i != active_voices.end();) {
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list