const sawtooth = (t) => 2 * (t % 1) - 1;
const random = () => Math.random() * 2 - 1;
const osc = synth.def(
class {
constructor(options) {
this.pan = 0;
this.phase = 0;
this.targetPan = random();
if (Math.abs(this.targetPan) < 0.5) {
this.targetPan *= 2.0;
}
this.startFreq = this.currentFreq = 300 + random() * 100;
this.detune = 1 + 0.01 * random();
this.targetFreq = midi_to_hz(options.note) * this.detune;
}
process(note, env, tick, options) {
if (tick < 8) {
// For 8 ticks, move slowly and randomly
this.currentFreq = this.startFreq * (1 + 0.1 * Math.sin(ditty.time / 1000));
} else {
// After 8 ticks, move to target
this.pan = lerp(this.pan, this.targetPan, 0.00003);
this.currentFreq = lerp(this.currentFreq, this.targetFreq, 0.00003);
}
this.phase += this.currentFreq * ditty.dt;
let boost = 1;
if (tick > 20 && this.currentFreq < 220) {
boost = 1.5;
}
return sawtooth(this.phase) * env.value * boost;
}
}, {
amp: 0.1,
attack: 8,
duration: 30,
release: 3
}
);
// THX chord
// https://twitter.com/THX/status/1000077588415447040
for (let i = 0; i < 4; i++) {
[d1, d2, a2, d3, a3, d4, a4, d5, a5, d6, fs6].forEach((n) => osc.play(n));
}