The (start of the) intro to Master of Puppets with some kind of electric guitar synth.
Inspired by Fork: Smoke on the water (loud!).
Log in to post a comment.
const sin = Math.sin;
const exp = Math.exp;
const PI = Math.PI;
const melody = [
220 / 4, // bpm
// notes, duration, pause, stop_at_end
[[e3, b3], 0.25, 1, true],
[[d4, a4], 0.15, 0.25, true],
[[db4, ab4], 0.15, 0.25, true],
[[c4, g4], 4.0, 3.5, false],
0.9 * 220 / 2,
[[e3, b3], 0.20, 0.25, true],
[[e3], 0.20, 0.25, true],
[[e4], 0.25, 0.25, true],
[[e3], 0.20, 0.25, true],
[[e3], 0.20, 0.25, true],
[[eb4], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[d4, a4], 0.15, 0.5, true],
[[db4, ab4], 0.15, 0.5, true],
[[c4, g4], 0.6, 1, false],
[[e3], 0.20, 0.25, true],
[[e3], 0.20, 0.25, true],
[[b3], 0.25, 0.25, true],
[[e3], 0.20, 0.25, true],
[[e3], 0.20, 0.25, true],
[[bb3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[a3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[ab3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[g3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[f3, eb4, bb4], 0.25, 0.25, true],
[[e3], 0.25, 0.25, false],
[[e3, b3], 0.20, 0.25, true],
[[e3], 0.20, 0.25, true],
[[e4], 0.25, 0.25, true],
[[e3], 0.20, 0.25, true],
[[e3], 0.20, 0.25, true],
[[eb4], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[d4, a4], 0.15, 0.5, true],
[[db4, ab4], 0.15, 0.5, true],
[[c4, g4], 0.6, 1, false],
[[e3], 0.20, 0.25, true],
[[e3], 0.20, 0.25, true],
[[b3], 0.25, 0.25, true],
[[e3], 0.20, 0.25, true],
[[e3], 0.20, 0.25, true],
[[bb3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[a3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[ab3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[g3], 0.25, 0.25, true],
[[e3], 0.25, 0.25, true],
[[f3, eb4, bb4], 0.25, 0.25, true],
[[e3], 1.25, 0.25, false],
[[], 0, 4, false] // pause for a bit
];
const tri = x => ((x / 2 / PI) % 1) * 2 - 1;
const guitar = synth.def(class {
constructor(options) {
this.phase = Math.random();
this.prev = 0;
this.vibe = Math.random();
}
process(note, env, tick, options) {
this.phase += ditty.dt;
const hit = exp(tick * -50);
const freq = midi_to_hz(note) + hit * 3;
const mod = sin(2 * PI * this.phase * freq * 0.251 + 0.01 * sin(2 * PI * 100 * this.phase)); // why does 0.251 just work?
const val = sin(2 * PI * this.phase * freq + (10 + 6 * this.vibe) * mod) * env.value * 20 +
sin(2 * (2 * PI * this.phase * freq)) * env.value * 20 * 0.5 +
sin(3 * (2 * PI * this.phase * freq + 1 * (10 + 6 * this.vibe) * mod)) * env.value * 50 * 0.25 +
sin(4 * (2 * PI * this.phase * freq)) * env.value * 50 * 0.125;
this.prev += (val - this.prev) * (0.3 + hit * 1);
const out = clamp(this.prev, -1, 1) * 0.5 * 0.2;
return [out, out];
}
});
const bass = synth.def(class {
constructor(options) {
this.phase = Math.random();
}
process(note, env, tick, options) {
this.phase += ditty.dt;
const freq = midi_to_hz(note);
const val = sin(2 * PI * this.phase * freq) * env.value;
const out = clamp(val, -1, 1) * 0.7 + clamp(3 * val, -1, 1) * 0.3;
return [out, out];
}
});
loop(loopcount => {
const pos = loopcount % melody.length;
if (typeof melody[pos] == "number") {
ditty.bpm = melody[pos];
} else {
const [notes, dur, pause, stop] = melody[pos];
const atk = () => 0.005 + Math.random() * 0.005;
for (const note of notes) {
guitar.play(note, {attack: atk(), decay: 0.05, duration: stop? dur : 0, release: stop? 0.05 : second_to_tick(dur), curve: [4, 0, -4], pan: -1});
guitar.play(note, {attack: atk(), decay: 0.05, duration: stop? dur : 0, release: stop? 0.05 : second_to_tick(dur), curve: [4, 0, -4], pan: 1});
bass.play(note - 24, {attack: 0.005, duration: stop? dur : 0, release: second_to_tick(dur), curve: [4, 0, -4], pan: -1});
bass.play(note - 24, {attack: 0.005, duration: stop? dur : 0, release: second_to_tick(dur), curve: [4, 0, -4], pan: 1});
}
sleep(pause);
}
}, {name: "eguitar"});