A second building block of Dittytoy is the loop. You can use a loop to define a repeating music pattern.
Each loop runs in its own worker/thread. So by using multiple loops, you can parallelize your ditty, which makes it a convenient way to optimize your ditty if it doesn't perform well.
dittytoy.net/syntax#loops
#dittytoy #tutorial
Log in to post a comment.
// #04 Loops. DittyToy 2022.
// The MIT License.
//
// https://dittytoy.net/ditty/07455f0c58
//
// A second building block of Dittytoy is the loop. You can use a loop to define a repeating music pattern.
//
// Each loop runs in its own worker/thread. So by using multiple loops, you can parallelize your
// ditty, which makes it a convenient way to optimize your ditty if it doesn't perform well.
//
// A loop supports the following options by default:
//
// - name (optional, the name of the loop)
// - amp (volume, default: 1)
// - pan (panning, -1 to 1, default: 0)
// - sync (in ticks, optional)
//
// https://dittytoy.net/syntax#loops
//
const noise = synth.def( (phase, env, tick, options) => (Math.random() * 2 - 1) * env.value, { env: adsr2 } );
const kick = synth.def( (phase, env, tick, options) => Math.sin(phase * 2 * Math.PI * (1.5 - tick * 4)) * env.value, { attack: 0.025, release: 0.15, env: adsr2 });
ditty.bpm = 120;
loop( (loopCount) => {
if (loopCount % 4 < 3) kick.play(c3);
}, { name: 'kick', sync: 1 });
loop( (loopCount) => {
noise.play(c3, { attack: 0.0125, release: 0.075, amp: .05 + Math.random() * 0.05 });
sleep(0.25);
}, { name: 'hi-hat' });
loop( (loopCount) => {
for (let i=0; i<4; i++) {
sine.play(c4, { attack: 0.01, release: 0.25, duration: 0.125, pan: Math.random() * 2 - 1, amp: 1.0 });
sleep( 0.25 );
}
sine.play(d4, { attack: 0.01, release: 0.25, duration: 0.25 }); // attack and release in seconds, duration in ticks
sleep(0.5); // sleep in ticks
sine.play(f4, { attack: 0.01, release: 0.75, duration: 0.25 });
sleep(0.5);
}, { name: 'melody' });