Oh yeah! Mario time!
Mix of all cool sounds on Dittytoy. Might change when I find new stuff :)
Piano sound from Electric Piano 1 by @athibaul
(Insane cool) Reverb from Karplus synth with reverb by @srtuss
Fat kick from Fat kick by @athibaul
Beat from d-layers beat by @reinder
Log in to post a comment.
// Forked from "Ditty Mario 🍄" by markknol
// https://dittytoy.net/ditty/3cc8ab88cd
ditty.bpm = 90;
const choose = (array) => array[Math.floor(Math.random() * array.length)];
/*
Reverb from https://dittytoy.net/ditty/827b1b3e63 by @srtuss
*/
class Delayline {
constructor(n) {
this.n = ~~n;
this.p = 0;
this.lastOut = 0;
this.data = new Float32Array(n);
}
clock(input) {
this.lastOut = this.data[this.p];
this.data[this.p] = input;
if(++this.p >= this.n) {
this.p = 0;
}
}
tap(offset) {
var x = this.p - offset - 1;
x %= this.n;
if(x < 0) {
x += this.n;
}
return this.data[x];
}
}
function allpass(delayline, x, k) {
var delayin = x - delayline.lastOut * k;
var y = delayline.lastOut + k * delayin;
delayline.clock(delayin);
return y;
}
// Simple allpass reverberator, based on this article:
// http://www.spinsemi.com/knowledge_base/effects.html
const reverb = filter.def(class {
constructor(options) {
this.lastReturn = 0;
this.krt = .68;
this.delaylines = [];
// Create several delay lines with random lengths
for(var i = 0; i < 12; ++i) {
this.delaylines.push(new Delayline(10 + Math.floor(i/12 * 5000)));
}
}
process(input, options) {
var inv = input[0] + input[1];
var v = this.lastReturn;
// Let the signal pass through the loop of delay lines. Inject input signal at multiple locations.
v = allpass(this.delaylines[0], v + inv, .5);
v = allpass(this.delaylines[1], v, .5);
this.delaylines[2].clock(v);
v = this.delaylines[2].lastOut * this.krt;
v = allpass(this.delaylines[3], v + inv, .5);
v = allpass(this.delaylines[4], v, .5);
this.delaylines[5].clock(v);
v = this.delaylines[5].lastOut * this.krt;
v = allpass(this.delaylines[6], v + inv, .5);
v = allpass(this.delaylines[7], v, .5);
this.delaylines[8].clock(v);
v = this.delaylines[8].lastOut * this.krt;
v = allpass(this.delaylines[9], v + inv, .5);
v = allpass(this.delaylines[10], v, .5);
this.delaylines[11].clock(v);
v = this.delaylines[11].lastOut * this.krt;
this.lastReturn = v;
// Tap the delay lines at randomized locations and accumulate the output signal.
var ret = [0, 0];
ret[0] += this.delaylines[2].tap(111);
ret[1] += this.delaylines[2].tap(2250);
ret[0] += this.delaylines[5].tap(311);
ret[1] += this.delaylines[5].tap(1150);
ret[0] += this.delaylines[8].tap(511);
ret[1] += this.delaylines[8].tap(50);
ret[0] += this.delaylines[11].tap(4411);
ret[1] += this.delaylines[11].tap(540);
// Mix wet + dry signal.
ret[0] = ret[0] * .1 + input[0];
ret[1] = ret[1] * .1 + input[1];
// Slight stereo widening:
var m = (ret[0] + ret[1]) * .5;
var s = (ret[1] - ret[0]) * .5;
ret[0] = m + s * 1.5;
ret[1] = m - s * 1.5;
return ret;
}
});
/*
Piano sound from https://dittytoy.net/ditty/5f66552091 by @athibaul
*/
const TAU = 2*Math.PI;
const msin = (x,m) => Math.sin(TAU*x + m);
// Electric piano using phase modulation
const ep1 = synth.def( (phase, env, tick, options) => {
let sig = msin(phase, msin(11*phase,0) * clamp01(1 - 10*tick)*options.amp);
sig = sig + msin(phase, msin(phase,0) * 2 * options.amp);
return sig * env.value;
}, {attack:0.01, release: 0.3, decay: 0.2}
);
const interval = 0.3;
loop(() => {
[
e7, e7, 0, e7, 0, c7, e7, 0, g7, 0, 0, 0, g6, 0, 0, 0,
c7, 0, 0, g6, 0, 0, e6, 0, 0, a6, 0, b6, 0, as6, a6, 0,
g6, e7, g7, a7, 0, f7, g7, 0, e7, 0, c7, d7, b6, 0, 0,
c7, 0, 0, g6, 0, 0, e6, 0, 0, a6, 0, b6, 0, as6, a6, 0,
g6, e7, g7, a7, 0, f7, g7, 0, e7, 0, c7, d7, b6, 0, 0
].forEach((note,idx) => (note ? (ep1.play(note - choose([24,36,48]), {amp: Math.random() + 0.3, decay:interval}), ep1.play(note - choose([24,36,48]), {amp: Math.random() + 0.3, decay:interval/2})) : {}, sleep(0.25)));
sleep(2);
}, {amp:0.1}).connect(reverb.create());
const linexp = (x,x0,x1,y0,y1) => y0 * (y1/y0) ** ((x-x0)/(x1-x0));
const linlin = (x,x0,x1,y0,y1) => y0 + (y1 - y0) * clamp01((x-x0)/(x1-x0));
const tri = synth.def((phase, env) => 1.22*(4.0*Math.abs(phase % 1 - 0.5) - 1.0) * env.value);
const dist = synth.def((phase, env, tick, options) => Math.atan(25*(Math.abs(phase % 1 - 0.5) - 0.25) * env.value));
/*
fat kick from https://dittytoy.net/ditty/57d4ff2921
*/
let rhythm = [1.5,1.5,1,1.5,1.5,1, 1.5,1,1.5,1.5,1,1.5]
let i = 0;
loop( () => {
// click
sine.play((tick) => linlin(tick, 0, 0.03, 127, 0), {attack:0.0005, release:0.05, amp:0.1});
// boom
sine.play(
(tick) => linlin(tick, 0, 0.3, a1, f1),
//{env: adsr2, attack:0.01, decay:0.1, decay_level:0.1, sustain:0.15, sustain_level:0.5, release:0.2, amp:2}
{env: adsr, attack:0.26, release:0.2}
);
// low thump
tri.play(
(tick) => linlin(tick, 0, 0.1, e3, f1),
{env: adsr, attack:0.005, release:0.1}
);
// high tump
tri.play(
(tick) => linlin(tick, 0, 0.03, a5, a3),
{env: adsr, attack:0.005, release:0.03, amp:0.3}
);
sleep(rhythm[i]/2);
i = (i+1)%rhythm.length;
}, {name:"kick"});
/*
beat from https://dittytoy.net/ditty/e4696ead7e by @reinder
*/
const noise = synth.def( (phase, env, tick, options) => (Math.random() * 2 - 1) * env.value, { attack: 0.0125, release: 0.15, env: adsr2 });
const delay = filter.def(class {
constructor(options) {
this.index = 0;
this.length = options.interval * ditty.sampleRate * 60 / ditty.bpm | 0;
this.left = new Float32Array(this.length);
this.right = new Float32Array(this.length);
}
process(input, options) {
if (input) {
const s = options.strength;
this.index = (this.index + 1) % this.length;
const hist = (this.index + 1) % this.length;
this.left [this.index] = input[0] + s * this.right[hist];
this.right[this.index] = input[1] + s * this.left [hist];
return [ this.left[this.index], this.right[this.index] ];
}
}
}, { interval: 1/3, strength: 0.25 });
const lowpass = filter.def(class {
constructor(options) {
this.hist0 = [0, 0];
this.hist1 = [0, 0];
}
process(input, options) {
const alpha = options.cutoff;
if (input) {
for (let i = 0; i < 2; i++) {
this.hist0[i] += alpha * (input[i] - this.hist0[i]);
this.hist1[i] += alpha * (this.hist0[i] - this.hist1[i]);
}
return this.hist1;
}
}
}, {cutoff: 1});
loop( (loopCount) => {
'--x---x---x---xx'.ring(loopCount) == 'x' && noise.play(c3, { amp: 2});
sleep(.5);
}, { name: 'snare' })
.connect( lowpass.create( { cutoff: 0.15 } ))
.connect( delay.create( { interval: 0.25, strength: 0.15 }))
loop( () => {
noise.play(c, { amp: 0.02 + 0.01 * Math.random(), pan: Math.sin(ditty.time * 8) });
sleep(0.25);
}, { name: 'hi-hat' })
.connect( lowpass.create( { cutoff: .9} ))
.connect( delay.create( { interval: 0.25, strength: 0.5 }));