ditty.bpm = 55;
const oscSaw02=(t, hz) => { let p=t*hz; return 2.0*(p-floor(p+0.5) ); }
// --- sawlead de Catzpaw, adaptado a Dittytoy ---
const sawlead = synth.def((phase, env, tick, options) => {
const norm1 = (phase / (2 * Math.PI)) % 1;
const norm2 = (phase * 2.05 / (2.0 * Math.PI)) % 1;
const norm3 = (phase * 2.01 / (2.0 * Math.PI)) % 1;
const saw1 = norm1 * 2 - 1;
const saw2 = norm2 * 2 - 1;
const saw3 = norm3 * 2 - 1;
const saw4= oscSaw02(norm1, 1.0);
return (saw1 + saw2+saw3+saw4) * env.value/4.0;
});
// --- Solo 10 notas de prueba ---
const testNotes = [
[0.00000, 42.0, 0.12500],
[0.12500, 42.0, 0.25000],
[0.25000, 38.0, 0.37500],
[0.37500, 35.0, 0.50000],
[0.68750, 35.0, 0.81250],
[1.00000, 40.0, 1.12500],
[1.31250, 40.0, 1.43750],
[1.62500, 40.0, 1.75000],
[1.78125, 44.0, 1.90625],
[1.90625, 44.0, 2.03125],
[2.03125, 45.0, 2.15625],
[2.15625, 47.0, 2.28125],
[2.28125, 45.0, 2.40625],
[2.40625, 45.0, 2.53125],
[2.53125, 45.0, 2.65625],
[2.65625, 40.0, 2.78125],
[2.96875, 38.0, 3.09375],
[3.28125, 42.0, 3.40625],
[3.59375, 42.0, 3.71875],
[3.90625, 42.0, 4.03125],
[4.03125, 40.0, 4.15625],
[4.15625, 40.0, 4.28125],
[4.28125, 42.0, 4.40625],
[4.40625, 40.0, 4.53125],
[4.53125, 42.0, 4.65625],
[4.65625, 42.0, 4.78125],
[4.78125, 38.0, 4.90625],
[5.09375, 35.0, 5.21875],
[5.40625, 35.0, 5.53125],
[5.71875, 40.0, 5.84375],
[6.03125, 40.0, 6.15625],
[6.34375, 40.0, 6.46875],
[6.46875, 44.0, 6.59375],
[6.59375, 44.0, 6.71875],
[6.71875, 45.0, 6.84375],
[6.84375, 47.0, 6.96875],
[6.96875, 45.0, 7.09375],
[7.09375, 45.0, 7.21875],
[7.21875, 45.0, 7.34375],
[7.34375, 40.0, 7.46875],
[7.65625, 38.0, 7.78125],
[7.96875, 42.0, 8.09375],
[8.28125, 42.0, 8.40625],
[8.59375, 42.0, 8.71875],
[8.71875, 40.0, 8.84375],
[8.84375, 40.0, 8.96875],
[8.96875, 42.0, 9.09375],
[9.09375, 40.0, 9.21875],
[9.21875, 23.0, 10.21875],
[9.21875, 42.0, 9.34375],
[9.34375, 42.0, 9.46875],
[9.46875, 38.0, 9.59375],
[9.59375, 35.0, 9.71875],
[9.90625, 35.0, 10.03125],
[10.15625, 40.0, 10.28125],
[10.28125, 28.0, 11.28125],
[10.40625, 40.0, 10.53125],
[10.71875, 40.0, 10.84375],
[10.84375, 44.0, 10.96875],
[10.96875, 44.0, 11.09375],
[11.09375, 45.0, 11.21875],
[11.21875, 47.0, 11.34375],
[11.34375, 21.0, 12.34375],
[11.34375, 45.0, 11.46875],
[11.46875, 45.0, 11.59375],
[11.59375, 45.0, 11.71875],
[11.71875, 40.0, 11.84375],
[12.03125, 38.0, 12.15625],
[12.28125, 42.0, 12.40625],
[12.40625, 26.0, 13.53125],
[12.59375, 42.0, 12.71875],
[12.90625, 42.0, 13.03125],
[13.03125, 40.0, 13.53125],
[13.65625, 23.0, 14.65625],
[13.65625, 50.0, 14.03125],
[14.09375, 50.0, 14.34375],
[14.40625, 49.0, 14.53125],
[14.53125, 47.0, 15.71875],
[14.71875, 28.0, 15.71875],
[15.78125, 21.0, 17.03125],
[15.78125, 49.0, 15.90625],
[15.90625, 49.0, 16.15625],
[16.21875, 49.0, 16.46875],
[16.53125, 45.0, 17.03125],
[17.09375, 26.0, 18.28125],
[17.28125, 54.0, 17.53125],
[17.59375, 54.0, 17.71875],
[17.71875, 54.0, 17.96875],
[18.03125, 52.0, 18.28125],
[18.34375, 23.0, 19.53125],
[18.34375, 50.0, 18.84375],
[18.90625, 50.0, 19.03125],
[19.03125, 50.0, 19.15625],
[19.15625, 49.0, 19.40625],
[19.46875, 47.0, 20.46875],
[19.59375, 28.0, 20.78125],
[20.71875, 47.0, 20.84375],
[20.84375, 21.0, 21.90625],
[20.84375, 49.0, 21.09375],
[21.15625, 50.0, 21.28125],
[21.28125, 49.0, 21.53125],
[21.59375, 47.0, 21.84375],
[21.90625, 45.0, 22.21875],
[22.06250, 26.0, 23.31250],
[22.25000, 47.0, 22.50000],
[22.56250, 49.0, 22.68750],
[22.68750, 47.0, 22.93750],
[23.00000, 45.0, 23.62500],
[23.37500, 23.0, 24.50000],
[23.68750, 50.0, 23.93750],
[24.00000, 50.0, 24.25000],
[24.31250, 50.0, 24.43750],
[24.43750, 50.0, 25.56250],
[24.56250, 28.0, 25.56250],
[25.62500, 30.0, 26.56250],
[25.87500, 45.0, 26.00000],
[26.00000, 45.0, 26.12500],
[26.12500, 45.0, 26.25000],
[26.25000, 45.0, 26.37500],
[26.37500, 45.0, 26.50000],
[26.50000, 45.0, 26.62500],
//[26.62500, 26.0, 26.93750],
[26.62500, 26.0, 27.62500],
[26.62500, 45.0, 26.75000],
[26.75000, 44.0, 27.12500],
[27.18750, 44.0, 27.25000],
[27.28125, 42.0, 27.65625],
[27.71875, 33.0, 28.71875],
[27.71875, 45.0, 28.71875],
[28.78125, 32.0, 29.78125],
[28.78125, 56.0, 29.78125],
[29.84375, 30.0, 30.78125],
[29.84375, 57.0, 30.78125]
];
let index = 0;
const total = testNotes[testNotes.length - 1][2];
loop(() => {
let t = 0;
const step = 0.03125;
while (t <= total) {
while (index < testNotes.length && Math.abs(testNotes[index][0] - t) < 1e-4) {
const [s, m, e] = testNotes[index];
sawlead.play(m+42, { duration: e - s, attack: 0.01, release: 0.2, amp: 0.6 });
index++;
}
sleep(step);
t += step;
}
index = 0;
}, { name: 'Take On Me - sawlead-v4' });
//referencia funciones --nabr
// utilities
const { random, PI, floor, sin, abs, max, min, exp, cos, tanh, pow, tan } = Math;
const env_d = (t, d) => exp(-t * 5.436563 / d);
const env_ad = (t, a, d) => min(t / max(1e-5, a), env_d((t - a), d));
const env_adc = (t, a, d) => clamp(min(t / max(1e-5, a), env_d((t - a), d)), 0, 1);
const msat = (x, a) => 0.5 * (abs(x + a) - abs(x - a));
const softkn = (x, kn) => x / (kn * abs(x) + 1.0);
const softkna = (x, kn, ad) => x / (kn * msat(x, ad) + 1.0);
const fract = (x) => (x - floor(x));
const mod = (x, y) => (x - floor(x / y) * y);
const tau = (PI * 2.0);
const int = (x) => (x | 0);
const smoothstep = (e0, e1, value) => {const x = max(0, min(1, (value - e0) / (e1 - e0))); return x * x * (3 - 2 * x); };
const fadein = (s, e, t) => smoothstep(s, e, t);