Implemented from youtube.com/watch?v=y7teskmse74&t=456s
Basic waveforms (variation)
Basic waveforms (variation)
Basic waveforms (variation)
Log in to post a comment.
input.waveForm = 2; //min=1 max=5 step=1 (Sine, Square, Triangle, Saw, Semi-circle)
input.overdriveLevel = 1 //min=1, max=100 step=.1
//
// RTFM You can find the DittyToy API Reference here: https://dittytoy.net/syntax
//
const WAVEFORM = {SINE: 1, SQUARE: 2, TRIANGLE: 3, SAW: 4, SEMICIRCLE: 5 };
const basicSynth = synth.def(class {
process(note, env, tick, options) {
switch(options.waveForm) {
case WAVEFORM.SQUARE:
return Array.from({length: options.k },
(v, i) => Math.sin(tick * midi_to_hz(note) * (2 * (i + 1) - 1) * 2 * Math.PI) / (2 * (i + 1) - 1)
).reduce((p, c) => p+c, 0) * 4 / Math.PI * env.value;
case WAVEFORM.TRIANGLE:
return Array.from({length: options.k },
(v, i) => (Math.sin(tick * midi_to_hz(note) * (2 * (i + 1) - 1) * 2 * Math.PI) / (2 * (i + 1) - 1)**2) * (-1)**(i+1)
).reduce((p, c) => p+c, 0) * 8 / Math.PI**2 * env.value;
case WAVEFORM.SAW:
return Array.from({length: options.k },
(v, i) => Math.sin(tick * midi_to_hz(note) * (i + 1) * 2 * Math.PI) / (i + 1) * (-1)**(i+1)
).reduce((p, c) => p+c, 0) * 2 / Math.PI * env.value;
case WAVEFORM.SEMICIRCLE:
// I modified the second answer from https://math.stackexchange.com/questions/44329/function-for-concatenated-semicircles
// with a reference to https://www.desmos.com/calculator/e5xncapcnp
const f = midi_to_hz(note) * Math.PI * tick * 2;
return Math.sqrt(1 - ((2 * Math.asin(Math.sin(f))) / Math.PI)**2) * (Math.cos(f)/Math.abs(Math.cos(f))) * env.value;
case WAVEFORM.SINE:
default:
return Math.sin(tick * midi_to_hz(note) * 2 * Math.PI) * env.value;
}
}
}, { name: 'basicSynth', k: 15, waveForm: WAVEFORM.SQUARE });
const overdrive = filter.def( (input, options) => [...input.map(i => clamp(i * options.level, -1, 1))], { level: 1 });
ditty.bpm = 70;
// Adapted from Bach's Cello Suite No. 1 in G Major BWV 1007, copied from https://dittytoy.net/ditty/0c920dd635
let melody = [d3,a3,fs4,e4,fs4,a3,fs4,a3,
d3,a3,fs4,e4,fs4,a3,fs4,a3,
d3,b3,g4,fs4,g4,b3,g4,b3,
d3,b3,g4,fs4,g4,b3,g4,b3,
d3,cs4,g4,fs4,g4,cs4,g4,cs4,
d3,cs4,g4,fs4,g4,cs4,g4,cs4,
d3,b3,fs4,e4,fs4,d4,cs4,d4,
b3,d4,cs4,d4,fs3,a3,gs3,fs3,
gs3,d4,e4,d4,e4,d4,e4,d4,
gs3,d4,e4,d4,e4,d4,e4,d4,
cs4,e4,a4,gs4,a4,e4,d4,e4,
cs4,e4,d4,e4,a3,cs4,b3,a3,
b2,fs3,d4,cs4,d4,fs3,d4,fs3,
b2,fs3,d4,cs4,d4,fs3,d4,fs3,
b2,gs3,a3,b3,a3,gs3,fs3,e3,
d4,cs4,b3,a4,gs4,fs4,e4,d4,
a2,b3,cs4,a4,e4,a4,cs4,e4,
g4,b3,cs4,e4,g4,e4,cs4,a3,
];
loop( (count, options) => {
melody.forEach(note => {
[note].forEach((n, i) => {
basicSynth.play(n, {amp:(Math.random() + 0.5 + (i%8==0?0.8:0)) * .5, pan:0.5 * (2*((n*0.618)%1)-1), release: .25, waveForm: () => input.waveForm });
sleep(0.25);
});
})
}, { name: 'example' } ).connect(overdrive.create({level: () => input.overdriveLevel}));