[SCM] calf/master: + Monosynth: added LFO-based PWM
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:39:17 UTC 2013
The following commit has been merged in the master branch:
commit 6630872c2cc3dfeef45842eb5733efe6c56c8c2b
Author: Krzysztof Foltman <wdev at foltman.com>
Date: Tue Feb 3 23:45:41 2009 +0000
+ Monosynth: added LFO-based PWM
diff --git a/gui/gui-monosynth.xml b/gui/gui-monosynth.xml
index cf26686..f8aada4 100644
--- a/gui/gui-monosynth.xml
+++ b/gui/gui-monosynth.xml
@@ -85,14 +85,19 @@
<value param="lfo_delay"/>
</vbox>
<vbox>
- <label param="lfo_filter"/>
- <knob param="lfo_filter" type="1"/>
- <value param="lfo_filter"/>
+ <label param="lfo2filter"/>
+ <knob param="lfo2filter" type="1"/>
+ <value param="lfo2filter"/>
</vbox>
<vbox>
- <label param="lfo_pitch"/>
- <knob param="lfo_pitch"/>
- <value param="lfo_pitch"/>
+ <label param="lfo2pitch"/>
+ <knob param="lfo2pitch"/>
+ <value param="lfo2pitch"/>
+ </vbox>
+ <vbox>
+ <label param="lfo2pw"/>
+ <knob param="lfo2pw"/>
+ <value param="lfo2pw"/>
</vbox>
</hbox>
</frame>
diff --git a/src/calf/metadata.h b/src/calf/metadata.h
index 4b857bb..81bb0e6 100644
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@ -99,7 +99,7 @@ struct monosynth_metadata: public plugin_metadata<monosynth_metadata>
enum { flt_lp12, flt_lp24, flt_2lp12, flt_hp12, flt_lpbr, flt_hpbr, flt_bp6, flt_2bp6 };
enum { par_wave1, par_wave2, par_detune, par_osc2xpose, par_oscmode, par_oscmix, par_filtertype, par_cutoff, par_resonance, par_cutoffsep, par_envmod, par_envtores, par_envtoamp, par_attack, par_decay, par_sustain, par_release,
par_keyfollow, par_legato, par_portamento, par_vel2filter, par_vel2amp, par_master,
- par_lforate, par_lfodelay, par_lfofilter, par_lfopitch,
+ par_lforate, par_lfodelay, par_lfofilter, par_lfopitch, par_lfopw,
param_count };
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true };
enum { step_size = 64 };
diff --git a/src/calf/modules_synths.h b/src/calf/modules_synths.h
index 5dd6692..712434d 100644
--- a/src/calf/modules_synths.h
+++ b/src/calf/modules_synths.h
@@ -58,7 +58,7 @@ public:
int wave1, wave2, filter_type, last_filter_type;
float freq, start_freq, target_freq, cutoff, decay_factor, fgain, fgain_delta, separation;
float detune, xpose, xfade, pitchbend, ampctl, fltctl, queue_vel;
- float odcr, porta_time, lfo_bend, lfo_clock;
+ float odcr, porta_time, lfo_bend, lfo_clock, last_lfov;
int queue_note_on, stop_count;
int legato;
dsp::adsr envelope;
@@ -108,11 +108,13 @@ public:
{
precalculate_waves(progress_report);
}
- /// Run oscillators and two filters in series to produce mono output samples.
+ /// Run oscillators
+ void calculate_buffer_oscs(float lfo);
+ /// Run two filters in series to produce mono output samples.
void calculate_buffer_ser();
- /// Run oscillators and just one filter to produce mono output samples.
+ /// Run one filter to produce mono output samples.
void calculate_buffer_single();
- /// Run oscillators and two filters (one per channel) to produce stereo output samples.
+ /// Run two filters (one per channel) to produce stereo output samples.
void calculate_buffer_stereo();
/// Retrieve filter graph (which is 'live' so it cannot be generated by get_static_graph), or fall back to get_static_graph.
bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context);
diff --git a/src/calf/osc.h b/src/calf/osc.h
index dd1eb37..de47ef2 100644
--- a/src/calf/osc.h
+++ b/src/calf/osc.h
@@ -183,11 +183,19 @@ struct waveform_family: public std::map<uint32_t, float *>
for (unsigned int i = 0; i < cutoff; i++)
vmax = std::max(vmax, abs(bl.spectrum[i]));
float vthres = vmax / 1024.0; // -60dB
+ float cumul = 0.f;
while(cutoff > (SIZE / limit)) {
if (!foldover)
{
- while(cutoff > 1 && abs(bl.spectrum[cutoff - 1]) < vthres)
+ // skip harmonics too quiet to be heard, but measure their loudness cumulatively,
+ // because even if a single harmonic is too quiet, a whole bunch of them may add up
+ // to considerable amount of space
+ cumul = 0.f;
+ while(cutoff > 1 && cumul + abs(bl.spectrum[cutoff - 1]) < vthres)
+ {
+ cumul += abs(bl.spectrum[cutoff - 1]);
cutoff--;
+ }
}
float *wf = new float[SIZE+1];
bl.make_waveform(wf, cutoff, foldover);
@@ -233,6 +241,17 @@ struct waveform_oscillator: public simple_oscillator
phase += phasedelta;
return value;
}
+ /// Add/substract two phase-shifted values
+ inline float get_phaseshifted(uint32_t shift, float mix)
+ {
+ uint32_t wpos = phase >> (32 - SIZE_BITS);
+ float value1 = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], (phase & (SIZE - 1)) * (1.0f / SIZE));
+ wpos = (phase + shift) >> (32 - SIZE_BITS);
+ float value2 = dsp::lerp(waveform[wpos], waveform[(wpos + 1) & MASK], ((phase + shift) & (SIZE - 1)) * (1.0f / SIZE));
+ float value = value1 + mix * value2;
+ phase += phasedelta;
+ return value;
+ }
};
/**
diff --git a/src/modules.cpp b/src/modules.cpp
index 7d4f188..1bd0a99 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -287,8 +287,9 @@ CALF_PORT_PROPS(monosynth) = {
{ 5, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lfo_rate", "LFO Rate" },
{ 0.5, 0.1, 5, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_SEC, NULL, "lfo_delay", "LFO Delay" },
- { 0, -4800, 4800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "lfo_filter", "LFO->Filter" },
- { 0, 0, 1200, 0, PF_FLOAT | PF_SCALE_QUAD | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "lfo_pitch", "LFO->Pitch" },
+ { 0, -4800, 4800, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "lfo2filter", "LFO->Filter" },
+ { 0, 0, 1200, 0, PF_FLOAT | PF_SCALE_QUAD | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "lfo2pitch", "LFO->Pitch" },
+ { 0, 0, 1, 0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "lfo2pw", "LFO->PW" },
};
////////////////////////////////////////////////////////////////////////////
diff --git a/src/monosynth.cpp b/src/monosynth.cpp
index 77a3ccc..81b6a5c 100644
--- a/src/monosynth.cpp
+++ b/src/monosynth.cpp
@@ -72,9 +72,10 @@ void monosynth_audio_module::precalculate_waves(progress_report_iface *reporter)
data[i + HS] = (float)(i * 1.0 / HS - 1.0f);
waves[wave_saw].make(bl, data);
+ // this one is dummy, fake and sham, we're using a difference of two sawtooths for square wave due to PWM
for (int i = 0 ; i < S; i++)
data[i] = (float)(i < HS ? -1.f : 1.f);
- waves[wave_sqr].make(bl, data);
+ waves[wave_sqr].make(bl, data, 4);
for (int i = 0 ; i < S; i++)
data[i] = (float)(i < (64 * S / 2048)? -1.f : 1.f);
@@ -213,13 +214,34 @@ bool monosynth_audio_module::get_graph(int index, int subindex, float *data, int
return get_static_graph(index, subindex, *params[index], data, points, context);
}
-void monosynth_audio_module::calculate_buffer_ser()
+void monosynth_audio_module::calculate_buffer_oscs(float lfo)
{
+ uint32_t shift = (int32_t)(0x70000000 * last_lfov * *params[par_lfopw]);
+ int flag1 = (wave1 == wave_sqr);
+ int flag2 = (wave2 == wave_sqr);
+ uint32_t shift_delta = (int32_t)(0x70000000 * (lfo - last_lfov) * *params[par_lfopw] * (1.0 / step_size));
+
+ uint32_t shift1 = (flag1 << 31) + shift;
+ uint32_t shift2 = (flag2 << 31) + shift;
+ float mix1 = 1 - 2 * flag1, mix2 = 1 - 2 * flag2;
+
for (uint32_t i = 0; i < step_size; i++)
{
- float osc1val = osc1.get();
- float osc2val = osc2.get();
+ float osc1val = osc1.get_phaseshifted(shift1, mix1);
+ float osc2val = osc2.get_phaseshifted(shift2, mix2);
float wave = fgain * (osc1val + (osc2val - osc1val) * xfade);
+ buffer[i] = wave;
+ shift1 += shift_delta;
+ shift2 += shift_delta;
+ }
+ last_lfov = lfo;
+}
+
+void monosynth_audio_module::calculate_buffer_ser()
+{
+ for (uint32_t i = 0; i < step_size; i++)
+ {
+ float wave = buffer[i];
wave = filter.process(wave);
wave = filter2.process(wave);
buffer[i] = wave;
@@ -231,9 +253,7 @@ void monosynth_audio_module::calculate_buffer_single()
{
for (uint32_t i = 0; i < step_size; i++)
{
- float osc1val = osc1.get();
- float osc2val = osc2.get();
- float wave = fgain * (osc1val + (osc2val - osc1val) * xfade);
+ float wave = buffer[i];
wave = filter.process(wave);
buffer[i] = wave;
fgain += fgain_delta;
@@ -244,9 +264,7 @@ void monosynth_audio_module::calculate_buffer_stereo()
{
for (uint32_t i = 0; i < step_size; i++)
{
- float osc1val = osc1.get();
- float osc2val = osc2.get();
- float wave1 = osc1val + (osc2val - osc1val) * xfade;
+ float wave1 = buffer[i];
float wave2 = phaseshifter.process_ap(wave1);
buffer[i] = fgain * filter.process(wave1);
buffer2[i] = fgain * filter2.process(wave2);
@@ -264,8 +282,8 @@ void monosynth_audio_module::delayed_note_on()
ampctl = 1.0 + (queue_vel - 1.0) * *params[par_vel2amp];
fltctl = 1.0 + (queue_vel - 1.0) * *params[par_vel2filter];
set_frequency();
- osc1.waveform = waves[wave1].get_level(osc1.phasedelta);
- osc2.waveform = waves[wave2].get_level(osc2.phasedelta);
+ osc1.waveform = waves[wave1 == wave_sqr ? wave_saw : wave1].get_level(osc1.phasedelta);
+ osc2.waveform = waves[wave2 == wave_sqr ? wave_saw : wave2].get_level(osc2.phasedelta);
if (!osc1.waveform) osc1.waveform = silence;
if (!osc2.waveform) osc2.waveform = silence;
lfo_clock = 0.f;
@@ -423,6 +441,7 @@ void monosynth_audio_module::calculate_step()
if (*params[par_envtoamp] > 0.f)
newfgain *= 1.0 - (1.0 - aenv) * e2a;
fgain_delta = (newfgain - fgain) * (1.0 / step_size);
+ calculate_buffer_oscs(lfov);
switch(filter_type)
{
case flt_lp24:
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list