ditty.bpm = 45; // Technotronic suele estar en ~124 BPM
// --- Synth: onda cuadrada simple (como en squareWave) ---
const technotronicBass = synth.def((phase, env, tick, options) => {
const wave = Math.sin(phase) >= 0 ? 1 : -1;
return wave * env.value * 0.7; // volumen equilibrado
});
// --- Notas convertidas de vec3 a array [start, midi, end] ---
// Nota: ignoramos la línea con (0.00000,0.0,0.00000) (silencio)
const notes = [
[0.00000,22.0,0.18750], [0.00000,29.0,0.18750],
[0.25000,22.0,0.43750], [0.25000,29.0,0.43750],
[0.50000,22.0,0.62500], [0.50000,29.0,0.62500],
[0.68750,19.0,0.81250], [0.68750,26.0,0.81250],
[0.87500,19.0,1.06250], [0.87500,26.0,1.06250],
[1.06250,15.0,1.18750], [1.06250,22.0,1.18750],
[1.18750,17.0,1.31250], [1.18750,24.0,1.31250],
[1.37500,17.0,1.50000], [1.37500,24.0,1.50000],
[1.56250,17.0,1.62500], [1.56250,24.0,1.62500],
[1.68750,17.0,1.87500], [1.68750,24.0,1.87500],
[1.87500,19.0,2.00000], [1.87500,26.0,2.00000],
[2.00000,22.0,2.12500], [2.00000,29.0,2.12500],
[2.12500,24.0,2.25000], [2.12500,31.0,2.25000],
[2.25000,22.0,2.43750], [2.25000,29.0,2.43750],
[2.50000,22.0,2.62500], [2.50000,29.0,2.62500],
[2.68750,22.0,2.81250], [2.68750,29.0,2.81250],
[2.81250,19.0,2.93750], [2.81250,26.0,2.93750],
[3.00000,19.0,3.18750], [3.00000,26.0,3.18750],
[3.18750,15.0,3.31250], [3.18750,22.0,3.31250],
[3.31250,17.0,3.43750], [3.31250,24.0,3.43750],
[3.50000,17.0,3.62500], [3.50000,24.0,3.62500],
[3.68750,17.0,3.75000], [3.68750,24.0,3.75000],
[3.81250,17.0,4.00000], [3.81250,24.0,4.00000],
[3.96875,19.0,4.09375], [3.96875,26.0,4.09375],
[4.09375,22.0,4.21875], [4.09375,29.0,4.21875],
[4.21875,19.0,4.34375], [4.21875,26.0,4.34375],
[4.34375,22.0,4.46875], [4.34375,29.0,4.46875],
[4.53125,22.0,4.65625], [4.53125,29.0,4.65625],
[4.71875,22.0,4.84375], [4.71875,29.0,4.84375],
[4.84375,19.0,4.96875], [4.84375,26.0,4.96875],
[5.03125,19.0,5.21875], [5.03125,26.0,5.21875],
[5.21875,15.0,5.34375], [5.21875,22.0,5.34375],
[5.34375,17.0,5.46875], [5.34375,24.0,5.46875],
[5.53125,17.0,5.65625], [5.53125,24.0,5.65625],
[5.71875,17.0,5.78125], [5.71875,24.0,5.78125],
[5.84375,17.0,6.03125], [5.84375,24.0,6.03125],
[6.00000,19.0,6.12500], [6.00000,26.0,6.12500],
[6.12500,22.0,6.25000], [6.12500,29.0,6.25000],
[6.25000,24.0,6.37500], [6.25000,31.0,6.37500],
[6.37500,22.0,6.50000], [6.37500,29.0,6.50000],
[6.56250,22.0,6.68750], [6.56250,29.0,6.68750],
[6.75000,22.0,6.87500], [6.75000,29.0,6.87500],
[6.87500,19.0,7.00000], [6.87500,26.0,7.00000],
[7.06250,19.0,7.25000], [7.06250,26.0,7.25000],
[7.25000,15.0,7.37500], [7.25000,22.0,7.37500],
[7.31250,46.0,7.37500],
[7.37500,17.0,7.50000], [7.37500,24.0,7.50000],
[7.56250,17.0,7.68750], [7.56250,24.0,7.68750],
[7.68750,46.0,7.75000],
[7.75000,17.0,7.81250], [7.75000,24.0,7.81250], [7.75000,46.0,7.81250],
[7.87500,17.0,8.06250], [7.87500,24.0,8.06250], [7.87500,46.0,8.06250],
[8.03125,19.0,8.15625], [8.03125,26.0,8.15625],
[8.15625,22.0,8.28125], [8.15625,29.0,8.28125], [8.15625,46.0,8.21875],
[8.28125,19.0,8.40625], [8.28125,26.0,8.40625],
[8.40625,22.0,8.53125], [8.40625,29.0,8.53125],
[8.40625,41.0,8.90625], [8.40625,46.0,9.40625],
[8.59375,22.0,8.71875], [8.59375,29.0,8.71875],
[8.78125,22.0,8.90625], [8.78125,29.0,8.90625], [8.78125,46.0,8.84375],
[8.90625,19.0,9.03125], [8.90625,26.0,9.03125], [8.90625,49.0,9.09375],
[9.09375,19.0,9.28125], [9.09375,26.0,9.28125], [9.09375,48.0,9.21875]
];
// Agrupar por tiempo de inicio (para reproducir acordes simultáneos)
const events = {};
notes.forEach(([start, midi, end]) => {
if (midi === 0) return; // ignorar notas silenciosas
if (!events[start]) events[start] = [];
events[start].push({ midi, duration: end - start });
});
const times = Object.keys(events)
.map(t => parseFloat(t))
.sort((a, b) => a - b);
// --- Loop principal ---
loop(() => {
let currentTime = 0;
for (const t of times) {
if (t > currentTime) {
sleep(t - currentTime);
currentTime = t;
}
events[t].forEach(note => {
technotronicBass.play(note.midi+48, {
duration: note.duration,
attack: 0.01,
release: 0.08,
amp: 0.85
});
});
}
// Completar el loop (Technotronic suele repetir cada 8 beats)
const last = times[times.length - 1] || 0;
if (last < 8) {
sleep(8 - last);
}
}, { name: "Technotronic - Move This (Bass)" });