web-audio-synth-1
by mohayonao
HTML
<button id="play">Play</button> : click 2..4 times
<h4>detune series</h4>
<ul>
<li>
<label><input type="radio" name="detunes" value="[ 0 ]"> [ 0 ]</label>
</li>
<li>
<label><input type="radio" name="detunes" value="[ -4, +4 ]"> [ -4, +4 ]</label>
</li>
<li>
<label><input type="radio" name="detunes" value="[ -8, +8 ]" checked> [ -8, +8 ]</label>
</li>
<li>
<label><input type="radio" name="detunes" value="[ -10, -4, +4, +10 ]"> [ -12, -4, +4, +12 ]</label>
</li>
<li>
<label><input type="radio" name="detunes" value="[ -32, -20, +20, +32 ]"> [ -32, -16, +16, +32 ]</label>
</li>
<li>
<label><input type="radio" name="detunes" value="[ -64, -48, -16, +16, +48, +64 ]"> [ -64, -48, -16, +16, +48, +64 ]</label>
</li>
<li>
<label><input type="radio" name="detunes" value="[ -128, -48, -24, +24, +48, +128 ]"> [ -128, -48, -24, +24, +48, +128 ]</label>
</li>
</ul>
JavaScript
window.AudioContext = window.AudioContext || window.webkitAudioContext;
document.getElementById("play").addEventListener("click", function() {
play(getDetuneParams());
});
var audioContext = new AudioContext();
function play(detuneParams) {
synth({
playbackTime: audioContext.currentTime,
args: {
out: audioContext.destination,
midi: sample([ 60, 62, 64, 65, 67, 69, 71, 72 ]),
detuneParams: detuneParams,
dur: 12
}
});
}
function synth(e) {
var t0 = e.playbackTime;
var t1 = t0 + e.args.dur * 0.4;
var t2 = t1 + e.args.dur * 0.6;
var gain = audioContext.createGain();
var oscs = e.args.detuneParams.map(function(detune) {
var osc = audioContext.createOscillator();
osc.frequency.value = mtof(e.args.midi);
osc.detune.setValueAtTime(detune / 8, t0);
osc.detune.linearRampToValueAtTime(detune, t2);
osc.start(t0);
osc.stop(t2);
osc.connect(gain);
return osc;
});
gain.gain.setValueAtTime(0, t0);
gain.gain.linearRampToValueAtTime(0.025, t1);
gain.gain.linearRampToValueAtTime(0.000, t2);
gain.connect(e.args.out);
oscs[0].onended = function() {
oscs.forEach(function(osc) {
osc.disconnect();
});
gain.disconnect();
oscs = gain = null;
};
}
// utilities
function sample(list) {
return list[(Math.random() * list.length)|0];
}
function mtof(midi) {
return 440 * Math.pow(2, (midi - 69) / 12);
}
function getDetuneParams() {
var detunes = [].slice.call(document.getElementsByName("detunes"));
return JSON.parse(detunes.filter(function(input) {
return input.checked;
})[0].value.replace(/\+/g, ""));
}