ditty.bpm = 500; const xenakisTone = synth.def((phase, env, tick, options) => { let freq = midi_to_hz(options.note); freq *= 1 + 0.01 * Math.sin(tick * 0.5); return Math.sin(phase * 2 * Math.PI * freq) * env.value; }, { attack: 0.02, release: 0.4, duration: 2 }); const xenakisSnare = synth.def((phase, env, tick, options) => { return (Math.random() * 2 - 1) * env.value; }, { attack: 0.005, release: 0.15, duration: 0, amp: 0.4 }); const xenakisNoise = synth.def((phase, env, tick, options) => { return (Math.random() * 2 - 1) * env.value; }, { attack: 0.001, release: 0.05, duration: 0, amp: 0.3 }); loop(() => { const clusterSize = Math.floor(Math.random() * 3) + 1; for (let i = 0; i < clusterSize; i++) { xenakisTone.play(Math.floor(Math.random() * 36) + 40, { pan: (tick, opts) => Math.random() * 2 - 1 }); sleep(Math.random() * 0.3); } sleep(1 + Math.random() * 0.5); }, { name: 'Random Clusters' }); loop((loopCount) => { const s = xenakisTone.play((tick, opts) => opts.note, { duration: 8, note: Math.floor(Math.random() * 36) + 40, amp: 0.5 }); for (let i = 0; i < 8; i++) { s.options.note = Math.floor(Math.random() * 36) + 40; sleep(1); } }, { name: 'Glissandi' }); loop(() => { if (Math.random() < 0.3) xenakisSnare.play(); if (Math.random() < 0.2) xenakisNoise.play(); sleep(0.25); }, { name: 'Percussion' });