Skip to content

Commit

Permalink
protosynth: add 3 pulse-width modulated shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
JoepVanlier committed Sep 15, 2024
1 parent 9078441 commit 68dd96a
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,107 @@ instance(ss_factor, last_freq_ss, ph1, ph2, ph3, ph4, ph5, ph6, ph7, current_ifr
this.init_linearSVF_absolute(filter_freq - 1, 0);
);


// Thanks Tale for the polybleps!
function poly_blep(t, dt)
(
(t < dt) ? (
-sqr(t/dt - 1)
) : (t > 1 - dt) ? (
sqr((t - 1) / dt + 1)
);
);

function pulse()
instance(t, dt, idt, pw)
local(t1, t2, y)
global()
(
t2 = (t1 = t) - pw + 1;
t += dt;
t -= t|0;

y = ((t1 < pw) - pw) * 2;
t1 < dt ? y -= sqr(t1 * idt - 1) : t1 > 1 - dt ? y += sqr((t1 - 1) * idt + 1);
(t2 -= t2|0) < dt ? y += sqr(t2 * idt - 1) : t2 > 1 - dt ? y -= sqr((t2 - 1) * idt + 1);

this.eval_linearSVF_LP(y)
);

function pulse2()
instance(t, dt, idt, pw)
local(t1, t2, t3, y, pw2)
global()
(
pw2 = pw + pw;

t2 = (t1 = t) - pw2 + 1;
t3 = t - pw + 1;

t += dt;
t -= t|0;

y = ((t1 < pw2) - pw2);
y -= ((t1 < pw) - pw) * 2;

y -= 0.5 * poly_blep(t1, dt);
y += poly_blep(t3 - (t3|0), dt);
y -= 0.5 * poly_blep(t2 - (t2|0), dt);

this.eval_linearSVF_LP(y)
);

function tri()
instance(t, dt, idt, pw, lint, iconst)
local(t1, t2, t3, y, pw2)
global()
(
pw2 = pw + pw;

t2 = (t1 = t) - pw2 + 1;
t3 = t - pw + 1;

t += dt;
t -= t|0;

y = ((t1 < pw2) - pw2) * 2;
y -= ((t1 < pw) - pw) * 4;

y -= poly_blep(t1, dt);
y += 2 * poly_blep(t3 - (t3|0), dt);
y -= poly_blep(t2 - (t2|0), dt);

lint += y;
lint *= 0.998;

this.eval_linearSVF_LP(iconst * lint)
);

function update_pulse(freq, cur_spacing, attenuation)
local(filter_freq)
instance(dt, idt, pw, filter_freq)
global(srate)
(
dt = freq / srate;
idt = 1 / dt;
pw = cur_spacing;
filter_freq = min(0.5 * srate, freq * exp(7.4 * attenuation));
this.init_linearSVF_absolute(filter_freq - 1, 0);
);

function update_tri(freq, cur_spacing, attenuation)
local(filter_freq)
instance(dt, idt, pw, filter_freq, iconst)
global(srate)
(
dt = freq / srate;
iconst = 2 * dt / (0.0001 + pw);
idt = 1 / dt;
pw = cur_spacing;
filter_freq = min(0.5 * srate, freq * exp(7.4 * attenuation));
this.init_linearSVF_absolute(filter_freq - 1, 0);
);

function bspline_train(phase_advance)
instance(phase, from_phase)
local(old_phase, rel_sample)
Expand Down
28 changes: 15 additions & 13 deletions protosynth/saike_protosynth.jsfx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
desc:Saike Protosynth
options:maxmem=32000000
tags: instrument, synth, generator, synthesizer
version: 0.44
version: 0.45
author: Joep Vanlier
changelog: Add superspreader.
changelog: Add pulse width modulated square, pulse and triangle.
license: MIT
provides:
protosynth_dependencies/*
Expand Down Expand Up @@ -300,7 +300,7 @@ verb_mix_slider.init_slider_ui(249, 0, 1, 0, 0.4);
loop(i=0;8,
par = i * 6 + 1;
printf("gain_slider%d.init_slider_ui(%d, -72, 0, 0, -9);\n", i + 1, par);
printf("osc_type_slider%d.init_slider_ui(-1, 0, 4, 0, 0);\n", i + 1);
printf("osc_type_slider%d.init_slider_ui(-1, 0, 7, 0, 0);\n", i + 1);
printf("tune_slider%d.init_slider_ui(%d, 0.25, 8.0, 0, 1.0);\n", i + 1, par + 1);
printf("spacing_slider%d.init_slider_ui(%d, 0.25, 8.0, 0, 1.0);\n", i + 1, par + 2);
printf("brightness_slider%d.init_slider_ui(%d, 0.0, 0.95, 0, 0.95);\n", i + 1, par + 3);
Expand Down Expand Up @@ -490,6 +490,9 @@ function osc_type(type, sample_length)
: (type == 2) ? "peak"
: (type == 3) ? "nois"
: (type == 4) ? (sample_length > 0) ? "wt" : "[wt]"
: (type == 5) ? "sqr"
: (type == 6) ? "pul"
: (type == 7) ? "tri"
);

function filt_type(type)
Expand Down Expand Up @@ -718,9 +721,13 @@ instance(
printf(") : (osc%d_wave == 4) ? (", i);
// Don't ask :(
printf("osc%d.wt.select_mipmap(cur_freq + osc%d_hz_tune, 0.9032258064516129032258064516129 * (cur_spacing - 0.25), cur_brightness);", i, i);
printf(") : (osc%d_wave == 5) ? (", i);
printf("osc%d.sqr.update_pulse(cur_freq + osc%d_hz_tune, 0.0645161290322581 * cur_spacing, cur_brightness);", i, i);
printf(") : (osc%d_wave < 8) ? (", i);
printf("osc%d.sqr.update_tri(cur_freq + osc%d_hz_tune, 0.0625 * cur_spacing, cur_brightness);", i, i);
printf(");");
printf(") : (");
printf("g%d = 0; dg%d = 0;", i, i);
printf("g%d = 0; dg%d = 0;", i, i);
printf(");");
i += 1
);
Expand Down Expand Up @@ -888,7 +895,7 @@ instance(
<?
function gen_osc(i)
(
printf("o%d = g%d ? ((osc%d_wave == 1) ? osc%d.ssaw_step() : (osc%d_wave == 0) ? osc%d.dsf_step() : (osc%d_wave == 2) ? osc%d.peak.dsf_step_peak() : (osc%d_wave == 3) ? osc%d.noise_step() : osc%d.wt.wt_step()) * g%d;", i, i, i, i, i, i, i, i, i, i, i, i);
printf("o%d = g%d ? ((osc%d_wave == 1) ? osc%d.ssaw_step() : (osc%d_wave == 0) ? osc%d.dsf_step() : (osc%d_wave == 2) ? osc%d.peak.dsf_step_peak() : (osc%d_wave == 3) ? osc%d.noise_step() : (osc%d_wave == 4) ? osc%d.wt.wt_step() : (osc%d_wave == 5) ? osc%d.sqr.pulse() : (osc%d_wave == 6) ? osc%d.sqr.pulse2() : osc%d.sqr.tri()) * g%d;", i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i);
);
?>

Expand Down Expand Up @@ -1344,7 +1351,7 @@ global_tuning_slider1.serialize_if(version, 13);

file_var(0, has_wavetable_data);
has_wavetable_data ? (
<?loop(i2=1;8, printf("wt%d.serialize_sample(SAMPLES_PER_WT, WT_LENGTH, osc%d_type == 4, !write_mode);", i2, i2); i2 += 1;);?>
<?loop(i2=1;8, printf("wt%d.serialize_sample(SAMPLES_PER_WT, WT_LENGTH, (osc%d_type|0) == 4, !write_mode);", i2, i2); i2 += 1;);?>
);

<?
Expand Down Expand Up @@ -1942,18 +1949,13 @@ sprintf(MODULATOR_STRING, "Modulator to apply\n\nRight click to select modulator
printf("txt_blit(\"OSC%d\", cx, cy + 2); cx += 25;", i + 1);

printf("osc_type_slider%d.rounding_increment = 1;", i + 1);
printf("osc_type_slider%d.sl_max = wt%d.sample_data_length ? 4 : 3;", i + 1, i + 1, i + 1);
printf("osc_type_slider%d.current_value = osc%d_type;", i + 1, i + 1);
printf("osc_type_slider%d.text_slider_ui(%d, cx, cy, 4 * toggle_size + 4, 8, sprintf(9, \"%%s\", osc_type(osc%d_type, wt%d.sample_data_length)), \"Type\n\nHARM - Harmonic series with customizable spacing\nSSAW - SuperSaw with customizable detune\nPeak - Formant-like filtering\nNoise - Noise with customizable resonance\nWT - Wavetable (drag and drop sample here).\", \"Type\"); cx += 4 * toggle_size + 4 + 2;", i + 1, uuid(), i + 1, i + 1);

printf("(osc_type_slider%d.over && (mouse_cap == 2) && (last_cap == 0)) ? (\n", i + 1);
printf("gfx_x = mouse_x;");
printf("gfx_y = mouse_y;");
printf("wt%d.sample_data_length ? (", i + 1);
printf("ix = gfx_showmenu(\"Harmonic series|Super saw|Formant/Peak|Noise|Wavetable\");");
printf(") : (");
printf("ix = gfx_showmenu(\"Harmonic series|Super saw|Formant/Peak|Noise\");");
printf(");");
printf("ix = gfx_showmenu(\"Harmonic series|Super saw|Formant/Peak|Noise|Wavetable|Pulse|Bipolar Pulse|Triangle\");");
printf(" (ix > 0) ? (");
printf(" osc_type_slider%d.current_value = ix - 1;", i + 1);
printf(" );");
Expand Down Expand Up @@ -2008,7 +2010,7 @@ sprintf(MODULATOR_STRING, "Modulator to apply\n\nRight click to select modulator
printf("spacing_slider%d.check_text_input_defaults();", i + 1);
printf(") : (\n");
printf("spacing_slider%d.rounding_increment = 0.125;", i + 1);
printf("spacing_slider%d.text_slider_ui(%d, cx, cy, 5 * toggle_size + 4, 8, sprintf(9, \"%%\.3f\", spacing_slider%d.display_value), (floor(osc%d_type) == 3) ? \"Resonance\" : (floor(osc%d_type) == 1) ? \"Detune\" : (floor(osc%d_type) == 2) ? \"Formant\" : \"Partial spacing\", (floor(osc%d_type) == 3) ? \"Resonance\" : (floor(osc%d_type) == 1) ? \"Detune\" : (floor(osc%d_type) == 2) ? \"Formant\" : \"Freq spacing\"); cx += 5 * toggle_size + 4 + 1;", i + 1, uuid(), i + 1, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1);
printf("spacing_slider%d.text_slider_ui(%d, cx, cy, 5 * toggle_size + 4, 8, sprintf(9, \"%%\.3f\", spacing_slider%d.display_value), (floor(osc%d_type) == 3) ? \"Resonance\" : (floor(osc%d_type) == 1) ? \"Detune\" : (floor(osc%d_type) == 2) ? \"Formant\" : \"Partial spacing\", (floor(osc%d_type) == 3) ? \"Resonance\" : (floor(osc%d_type) == 1) ? \"Detune\" : (floor(osc%d_type) == 2) ? \"Formant\" : ((floor(osc%d_type) > 4) && (floor(osc%d_type) < 8)) ? \"Pulse width\" : \"Freq spacing\"); cx += 5 * toggle_size + 4 + 1;", i + 1, uuid(), i + 1, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1);
printf("spacing_slider%d.modulator_field(%d, cx, cy, 8, 1, MODULATOR_STRING, (floor(osc%d_type) == 3) ? \"Reso mod\" : (floor(osc%d_type) == 1) ? \"Detune mod\" : (floor(osc%d_type) == 2) ? \"Formant mod\" : \"Spacing Mod\", 0, N_SELECTABLE_MODULATORS, 1);\n cx += 10;", i + 1, uuid(), i + 1, i + 1, i + 1);
printf("spacing_slider%d.check_text_input_defaults();", i + 1);
printf(");\n");
Expand Down

0 comments on commit 68dd96a

Please sign in to comment.