JSFiddle - React, Tailwind, and code Playground
HTML
<input type="text" class="note" value="200">
<input type="text" class="note" value="220">
<input type="text" class="note" value="230">
<input type="text" class="note" value="240">
<input type="button" id="start" value="start">
<input type="button" id="stop" value="stop">
<input type="text" id="step_ms" value="250">
CSS
input[type="text"] {
display: block;
}
JavaScript
// Comments wrt chrome Chrome 20.0.1132.57, Ubuntu 12.04
var ctx = new webkitAudioContext();
//var node = ctx.createJavaScriptNode(512); // Timing wanders
//var node = ctx.createJavaScriptNode(1024); // Timing wanders
var node = ctx.createJavaScriptNode(4096); // Won't init faster than ~250ms step
var node = ctx.createJavaScriptNode(2048); // Seems to keep timing-accuracy
var osc = ctx.createOscillator();
var notes = [];
var step_ms = $('#step_ms')[0].value;
var elapsed = 0;
var step = 0;
osc.frequency.value = $('.note')[0].value;
node.onaudioprocess = function(evt) {
osc.frequency.value = notes[step];
if (elapsed >= step_ms) {
elapsed = 0;
osc.disconnect();
step = (step + 1) % notes.length;
osc.frequency.value = notes[step];
osc.connect(ctx.destination);
}
elapsed += evt.outputBuffer.duration * 1000;
};
$('.note').each(function(idx, el) {
notes[idx] = this.value;
$(this).on('change', function(evt) {
notes[idx] = this.value;
});
});
$('#start').on('click', function(evt) {
node.connect(ctx.destination);
osc.connect(ctx.destination);
});
$('#stop').on('click', function(evt) {
osc.disconnect();
node.disconnect();
});
$('#step_ms').on('change', function(evt) {
step_ms = this.value;
});