Web Audio Oscillator Test

by razh

HTML

<button id="play">Play</button>

JavaScript

'use strict';

var context = new webkitAudioContext();

var names = ["C", "C#", "D", "D#", "E", "E#", "F", "F#", "G", "A", "A#", "B"],
    regex = /(^[A-G])(b|\#)?([0-9]?$)/;

// Number of half steps away from A4.
function halfStepsFromA4(freq) {
    // Memoize?
    var symbols = regex.exec(freq);
    
    var name = symbols[1] || 0,
        accidental = symbols[2],
        octave = symbols[3] || 0;

    var note = names.indexOf( name );
    if (accidental === '#') {
        note++;
    } else if (accidental === 'b') {
        note--;
    }
    
    // Subtract 9 to shift center to A4.
    return note + (octave - 4) * 12 - 9;
}

console.log('Tests-----');
console.log(halfStepsFromA4('A4') === 0);
console.log(halfStepsFromA4('C3') === -21);
console.log(halfStepsFromA4('C4') === -9);

console.log(halfStepsFromA4('C5') === 3);
console.log(halfStepsFromA4('D5') === 5);
console.log(halfStepsFromA4('E5') === 7);

console.log(halfStepsFromA4('C6') === 15);

function freqFromString(freq) {
    // ( 2 ^ n / 12 ) * 440 Hz, where n is the half steps away from A4.
    return Math.pow(2, halfStepsFromA4(freq) / 12) * 440;
}

var gain = context.createGainNode();
gain.gain.value = 0;
gain.connect(context.destination);

var oscillator = context.createOscillator();

oscillator.type = 0;
oscillator.connect(gain);
oscillator.start(0);

function Note(freq, duration) {
    return {
        next: null,
        
        start: function() {
            gain.gain.value = 1;
            oscillator.frequency.value = freqFromString(freq);
   
            var that = this;

            setTimeout(function() {
                that.stop();
                if (that.next) that.next.start();
            }, duration);
            
            return this;
        },
        
        stop: function() {
            gain.gain.value = 0;
            return this;
        },
        
        then: function() {
            var args = Array.prototype.slice.call(arguments),
                callback =...