Merge branch 'calf-updates'

* calf-updates:
  Cleanups/bugfixes in Monosynth.
This commit is contained in:
Tobias Doerffel
2010-05-26 12:38:22 +02:00
4 changed files with 175 additions and 68 deletions

View File

@@ -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

View File

@@ -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()

View File

@@ -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);
};

View File

@@ -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;
}