[SCM] calf/master: Cleanups/bugfixes in Monosynth.
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:40:18 UTC 2013
The following commit has been merged in the master branch:
commit 404e1a0861e9b7a79f3b0175f40b427c06945adc
Author: Krzysztof Foltman <wdev at foltman.com>
Date: Tue May 25 00:05:24 2010 +0100
Cleanups/bugfixes in Monosynth.
diff --git a/src/calf/envelope.h b/src/calf/envelope.h
index 94f87ed..302e4c0 100644
--- a/src/calf/envelope.h
+++ b/src/calf/envelope.h
@@ -207,6 +207,74 @@ public:
}
};
+/// Simple linear fade out for note tails
+struct fadeout
+{
+ float value;
+ float step, step_orig;
+ bool done, undoing;
+
+ fadeout(int steps = 256)
+ {
+ step_orig = (float)(1.f / steps);
+ value = 1.f;
+ reset();
+ }
+
+ /// Prepare fade out
+ void reset()
+ {
+ value = 1.f;
+ step = -step_orig;
+ done = false;
+ undoing = false;
+ }
+
+ /// Fade back in with double speed (to prevent click on note restart)
+ void undo()
+ {
+ step = step_orig;
+ done = false;
+ undoing = true;
+ }
+
+ /// Reset if fully faded out; fade back in if in the middle of fading out
+ void reset_soft()
+ {
+ if (value <= 0.f || value >= 1.f)
+ reset();
+ else
+ undo();
+ }
+
+ void process(float *buffer, int len)
+ {
+ int i = 0;
+ if (!done)
+ {
+ for (; value > 0 && value <= 1.0 && i < len; i++)
+ {
+ buffer[i] *= value;
+ value += step;
+ }
+ if (value <= 0 || value > 1)
+ done = true;
+ }
+ if (done && value <= 0)
+ {
+ while (i < len)
+ buffer[i++] = 0.f;
+ }
+ if (done && undoing && value >= 1)
+ {
+ undoing = false;
+ done = false;
+ // prepare for the next fade-out
+ value = 1.f;
+ }
+ }
+};
+
};
#endif
diff --git a/src/calf/inertia.h b/src/calf/inertia.h
index aca1fbf..d6bbd29 100644
--- a/src/calf/inertia.h
+++ b/src/calf/inertia.h
@@ -245,7 +245,7 @@ public:
}
void set_sample_rate(int sr)
{
- ramp = linear_ramp(sr / 441);
+ ramp = linear_ramp(sr / 100);
}
// to change param, use set_inertia(value)
// to read param, use get()
diff --git a/src/calf/modules_synths.h b/src/calf/modules_synths.h
index 3b7ca83..8cd1c0b 100644
--- a/src/calf/modules_synths.h
+++ b/src/calf/modules_synths.h
@@ -45,14 +45,22 @@ public:
static dsp::waveform_family<MONOSYNTH_WAVE_BITS> *waves;
dsp::waveform_oscillator<MONOSYNTH_WAVE_BITS> osc1, osc2;
dsp::triangle_lfo lfo1, lfo2;
- bool running, stopping, gate, force_fadeout;
+ dsp::biquad_d1_lerp<float> filter, filter2;
+ /// The step code is producing non-zero values
+ bool running;
+ /// This is the last non-zero buffer (set on calculate_step after fadeout is complete, the next calculate_step will zero running)
+ bool stopping;
+ /// A key is kept pressed
+ bool gate;
+ /// All notes off fadeout
+ bool force_fadeout;
+ /// Last triggered note
int last_key;
+ /// Output buffers, used to ensure updates are done every step_size regardless of process buffer size
float buffer[step_size], buffer2[step_size];
+ /// Read position within the buffers, on each '0' the buffers are being filled with new data by calculate_step
uint32_t output_pos;
- dsp::onepole<float> phaseshifter;
- dsp::biquad_d1_lerp<float> filter;
- dsp::biquad_d1_lerp<float> filter2;
/// Waveform number - OSC1
int wave1;
/// Waveform number - OSC2
@@ -61,10 +69,15 @@ public:
int prev_wave1;
/// Last used waveform number - OSC2
int prev_wave2;
- int filter_type, last_filter_type;
+ /// Filter type
+ int filter_type;
+ /// Filter type on the last calculate_step
+ int last_filter_type;
float freq, start_freq, target_freq, cutoff, fgain, fgain_delta, separation;
- float detune, xpose, xfade, ampctl, fltctl, queue_vel;
- float odcr, porta_time, lfo_bend, lfo1_clock, lfo2_clock, modwheel_value;
+ float detune, xpose, xfade, ampctl, fltctl;
+ float odcr, porta_time, lfo_bend;
+ /// Modulation wheel position (0.f-1.f)
+ float modwheel_value;
/// Delay counter for LFOs
float lfo_clock;
/// Last value of phase shift for pulse width emulation for OSC1
@@ -73,11 +86,23 @@ public:
int32_t last_pwshift2;
/// Last value of stretch for osc sync emulation for OSC1
int32_t last_stretch1;
- int queue_note_on, stop_count, modwheel_value_int;
+ /// Next note to play on the next calculate_step
+ int queue_note_on;
+ /// Velocity of the next note to play
+ float queue_vel;
+ /// Integer value for modwheel (0-16383, read from CC1 - MSBs and CC33 - LSBs)
+ int modwheel_value_int;
+ /// Legato mode (bitmask)
int legato;
+ /// Envelope Generators
dsp::adsr envelope1, envelope2;
dsp::keystack stack;
+ /// Smoothing for master volume
dsp::gain_smoothing master;
+ /// Fadeout for buffer 1
+ dsp::fadeout fadeout;
+ /// Fadeout for buffer 2
+ dsp::fadeout fadeout2;
/// Smoothed cutoff value
dsp::inertia<dsp::exponential_ramp> inertia_cutoff;
/// Smoothed pitch bend value
@@ -145,6 +170,8 @@ public:
bool is_noisy(int param_no) const { return param_no != par_cutoff; }
/// Calculate control signals and produce step_size samples of output.
void calculate_step();
+ /// Apply anti-click'n'pop fadeout (used at the end of the sound)
+ void apply_fadeout();
/// Main processing function
uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask);
};
diff --git a/src/monosynth.cpp b/src/monosynth.cpp
index a2d1248..5120eab 100644
--- a/src/monosynth.cpp
+++ b/src/monosynth.cpp
@@ -65,7 +65,6 @@ void monosynth_audio_module::activate() {
running = false;
output_pos = 0;
queue_note_on = -1;
- stop_count = 0;
inertia_pitchbend.set_now(1.f);
lfo_bend = 1.0;
modwheel_value = 0.f;
@@ -329,9 +328,8 @@ void monosynth_audio_module::calculate_buffer_stereo()
for (uint32_t i = 0; i < step_size; i++)
{
float wave1 = buffer[i] * fgain;
- float wave2 = phaseshifter.process_ap(wave1);
buffer[i] = fgain * filter.process(wave1);
- buffer2[i] = fgain * filter2.process(wave2);
+ buffer2[i] = fgain * filter2.process(wave1);
fgain += fgain_delta;
}
}
@@ -349,7 +347,8 @@ void monosynth_audio_module::lookup_waveforms()
void monosynth_audio_module::delayed_note_on()
{
force_fadeout = false;
- stop_count = 0;
+ fadeout.reset_soft();
+ fadeout2.reset_soft();
porta_time = 0.f;
start_freq = freq;
target_freq = freq = 440 * pow(2.0, (queue_note_on - 69) / 12.0);
@@ -358,9 +357,11 @@ void monosynth_audio_module::delayed_note_on()
fltctl = 1.0 + (queue_vel - 1.0) * *params[par_vel2filter];
set_frequency();
lookup_waveforms();
+ bool starting = false;
if (!running)
{
+ starting = true;
if (legato >= 2)
porta_time = -1.f;
last_xfade = xfade;
@@ -369,15 +370,9 @@ void monosynth_audio_module::delayed_note_on()
filter.reset();
filter2.reset();
if (*params[par_lfo1trig] <= 0)
- {
lfo1.reset();
- lfo1_clock = 0.f;
- }
if (*params[par_lfo2trig] <= 0)
- {
lfo2.reset();
- lfo2_clock = 0.f;
- }
switch((int)*params[par_oscmode])
{
case 1:
@@ -401,22 +396,20 @@ void monosynth_audio_module::delayed_note_on()
default:
break;
}
- envelope1.note_on();
- envelope2.note_on();
running = true;
}
if (legato >= 2 && !gate)
porta_time = -1.f;
gate = true;
stopping = false;
- if (!(legato & 1) || (envelope1.released() && envelope2.released())) {
+ if (starting || !(legato & 1) || envelope1.released())
envelope1.note_on();
+ if (starting || !(legato & 1) || envelope2.released())
envelope2.note_on();
- }
envelope1.advance();
envelope2.advance();
queue_note_on = -1;
- float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get_last(), modwheel_value, 0, 0.5+0.5*lfo1.last, 0.5+0.5*lfo2.last};
+ float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get_last(), modwheel_value, envelope1.value, envelope2.value, 0.5+0.5*lfo1.last, 0.5+0.5*lfo2.last};
calculate_modmatrix(moddest, moddest_count, modsrc);
}
@@ -424,25 +417,25 @@ void monosynth_audio_module::set_sample_rate(uint32_t sr) {
srate = sr;
crate = sr / step_size;
odcr = (float)(1.0 / crate);
- phaseshifter.set_ap(1000.f, sr);
fgain = 0.f;
fgain_delta = 0.f;
inertia_cutoff.ramp.set_length(crate / 30); // 1/30s
inertia_pitchbend.ramp.set_length(crate / 30); // 1/30s
+ master.set_sample_rate(sr);
}
void monosynth_audio_module::calculate_step()
{
if (queue_note_on != -1)
delayed_note_on();
- else if (stopping)
+ else
+ if (stopping || !running)
{
running = false;
- dsp::zero(buffer, step_size);
- if (is_stereo_filter())
- dsp::zero(buffer2, step_size);
envelope1.advance();
envelope2.advance();
+ lfo1.get();
+ lfo2.get();
return;
}
lfo1.set_freq(*params[par_lforate], crate);
@@ -543,9 +536,9 @@ void monosynth_audio_module::calculate_step()
float e2a1 = *params[par_env1toamp];
float e2a2 = *params[par_env2toamp];
if (e2a1 > 0.f)
- newfgain *= 1.0 - (1.0 - aenv1) * e2a1;
+ newfgain *= aenv1;
if (e2a2 > 0.f)
- newfgain *= 1.0 - (1.0 - aenv2) * e2a2;
+ newfgain *= aenv2;
if (moddest[moddest_attenuation] != 0.f)
newfgain *= dsp::clip<float>(1 - moddest[moddest_attenuation] * moddest[moddest_attenuation], 0.f, 1.f);
fgain_delta = (newfgain - fgain) * (1.0 / step_size);
@@ -569,18 +562,42 @@ void monosynth_audio_module::calculate_step()
calculate_buffer_stereo();
break;
}
- bool no_amp_env = *params[par_env1toamp] <= 0.f && *params[par_env2toamp] <= 0.f;
- if ((envelope1.state == adsr::STOP && envelope2.state == adsr::STOP && !gate) || force_fadeout || (envelope1.state == adsr::RELEASE && no_amp_env) || (envelope2.state == adsr::RELEASE && no_amp_env))
+ apply_fadeout();
+}
+
+void monosynth_audio_module::apply_fadeout()
+{
+ if (fadeout.undoing)
{
- enum { ramp = step_size * 4 };
- for (int i = 0; i < step_size; i++)
- buffer[i] *= (ramp - i - stop_count) * (1.0f / ramp);
+ fadeout.process(buffer2, step_size);
if (is_stereo_filter())
- for (int i = 0; i < step_size; i++)
- buffer2[i] *= (ramp - i - stop_count) * (1.0f / ramp);
- stop_count += step_size;
- if (stop_count >= ramp)
- stopping = true;
+ fadeout2.process(buffer2, step_size);
+ }
+ else
+ {
+ // stop the sound if the amplitude envelope is not running (if there's any)
+ bool aenv1_on = *params[par_env1toamp] > 0.f, aenv2_on = *params[par_env2toamp] > 0.f;
+
+ bool do_fadeout = force_fadeout;
+
+ // if there's no amplitude envelope at all, the fadeout starts at key release
+ if (!aenv1_on && !aenv2_on && !gate)
+ do_fadeout = true;
+ // if ENV1 modulates amplitude, the fadeout will start on ENV1 end too
+ if (aenv1_on && envelope1.state == adsr::STOP)
+ do_fadeout = true;
+ // if ENV2 modulates amplitude, the fadeout will start on ENV2 end too
+ if (aenv2_on && envelope2.state == adsr::STOP)
+ do_fadeout = true;
+
+ if (do_fadeout || fadeout.undoing || fadeout2.undoing)
+ {
+ fadeout.process(buffer, step_size);
+ if (is_stereo_filter())
+ fadeout2.process(buffer2, step_size);
+ if (fadeout.done)
+ stopping = true;
+ }
}
}
@@ -695,38 +712,33 @@ void monosynth_audio_module::params_changed()
uint32_t monosynth_audio_module::process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask)
{
- if (!running && queue_note_on == -1) {
- for (uint32_t i = 0; i < nsamples / step_size; i++)
- {
- envelope1.advance();
- envelope2.advance();
- }
- return 0;
- }
uint32_t op = offset;
uint32_t op_end = offset + nsamples;
+ int had_data = 0;
while(op < op_end) {
- if (output_pos == 0) {
- if (running || queue_note_on != -1)
- calculate_step();
- else {
- envelope1.advance();
- envelope2.advance();
- dsp::zero(buffer, step_size);
- }
- }
+ if (output_pos == 0)
+ calculate_step();
if(op < op_end) {
uint32_t ip = output_pos;
uint32_t len = std::min(step_size - output_pos, op_end - op);
- if (is_stereo_filter())
- for(uint32_t i = 0 ; i < len; i++) {
- float vol = master.get();
- outs[0][op + i] = buffer[ip + i] * vol,
- outs[1][op + i] = buffer2[ip + i] * vol;
- }
- else
- for(uint32_t i = 0 ; i < len; i++)
- outs[0][op + i] = outs[1][op + i] = buffer[ip + i] * master.get();
+ if (running)
+ {
+ had_data = 3;
+ if (is_stereo_filter())
+ for(uint32_t i = 0 ; i < len; i++) {
+ float vol = master.get();
+ outs[0][op + i] = buffer[ip + i] * vol;
+ outs[1][op + i] = buffer2[ip + i] * vol;
+ }
+ else
+ for(uint32_t i = 0 ; i < len; i++)
+ outs[0][op + i] = outs[1][op + i] = buffer[ip + i] * master.get();
+ }
+ else
+ {
+ dsp::zero(&outs[0][op], len);
+ dsp::zero(&outs[1][op], len);
+ }
op += len;
output_pos += len;
if (output_pos == step_size)
@@ -734,6 +746,6 @@ uint32_t monosynth_audio_module::process(uint32_t offset, uint32_t nsamples, uin
}
}
- return 3;
+ return had_data;
}
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list