JavaScriptで音を鳴らしてみよう

id:Voluntasのおかげで自分的に再燃したブックマークレット熱。まあブックマークレットというと実用的な感があるけど、まったくそんなことはなく、要はワンライナーのこと。

いろいろ作ってみた中で、ちょっと汎用化できそうなものがあったので若干体裁を整えてみたのがこれ。仕組みは単純で、16KHz 8bitのwavファイルをオンザフライで生成して、それをdata:スキーム化した上で隠しiframeのsrcに突っ込んでいるだけ。なので、ブラウザ側にaudio/wavを再生できて、しかも自動再生してくれるプラグインが必須というところに注意。

追記1: undefinedとNaNの扱いでバグがあったので修正。
追記2: generateして余った分を切り取るspliceで符号が逆になっていたのを修正。ほんとすみません。

var SoundPlayer = {
    HEADER: "WAVEfmt\x20\x10\x00\x00\x00\x01\x00\x01\x00\x80\x3e\x00\x00\x80\x3e\x00\x00\x01\x00\x08\x00data",

    packToUInt32LE: function(l) {
        var f = String.fromCharCode;
        return f(l & 255) + f((l >> 8) & 255) + f((l >> 16) & 255) + f((l >> 24) & 255);
    },

    packToBytes: function(a, len) {
        var tmp = new Array(len);
        for (var i = len; --i >= 0;) {
            var v = 0;
            for (var j = a.length, d; --j >= 0;)
                d = a[j][i] + 0, v = Math.max(v, isNaN(d) ? 0: d);
            tmp[i] = String.fromCharCode(v);
        }
        return tmp.join('');
    },

    generateWavURI: function(a) {
        var len = 0;
        for (var i = a.length; --i >= 0;)
            len = Math.max(len, a[i].length);
        return "data:audio/wav,"
            + escape(
                "RIFF" + this.packToUInt32LE(len + this.HEADER.length + 4)
                + this.HEADER
                + this.packToUInt32LE(len)
                + this.packToBytes(a, len));
    },

    play: function() {
        var n = document.createElement('iframe');
        n.style.visibility = "hidden";
        n.setAttribute("src", this.generateWavURI(arguments));
        document.body.appendChild(n);
    }
};

var SoundGenerator = function() { this.initialize.apply(this, arguments); };
SoundGenerator.prototype = {
    initialize: function() {
        this.data = [];
        this.volume = 0xcf;
        this.duty = 0.5;
        this.waveForm = false;
        this.envelopeGenerator = function(t) {
            return Math.max((9000 - t) / 9000, 0);
        };
    },

    generatePulseWave: function(pitch, duration) {
        var on, off;
        on = Math.max(Math.floor(pitch * this.duty), 1);
        off = pitch - on;

        var t = 0, d = this.data, v = this.volume,
            eg = this.envelopeGenerator;

        while (t < duration) {
            for (var j = on; (j -= 32) > 0; ) {
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++));
            }
            j += 32;
            switch (j) {
            case 0:
                break;
            case 1:
                d.push(v * eg(t++));
                break;
            case 2:
                d.push(v * eg(t++), v * eg(t++));
                break;
            case 3:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 4:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 5:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++));
                break;
            case 6:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++));
                break;
            case 7:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 8:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 9:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++));
                break;
            case 10:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++));
                break;
            case 11:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 12:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 13:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++));
                break;
            case 14:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++));
                break;
            case 15:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 16:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 17:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++));
                break;
            case 18:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++));
                break;
            case 19:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 20:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 21:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++));
                break;
            case 22:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++));
                break;
            case 23:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 24:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 25:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++));
                break;
            case 26:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++));
                break;
            case 27:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 28:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            case 29:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++));
                break;
            case 30:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++));
                break;
            case 31:
                d.push(v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++), v * eg(t++),
                       v * eg(t++), v * eg(t++), v * eg(t++));
                break;
            }

            for (var j = off; (j -= 32) > 0; ) {
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
            }
            j += 32;
            switch (j) {
            case 0:
                break;
            case 1:
                d.push(0x00);
                break;
            case 2:
                d.push(0x00, 0x00);
                break;
            case 3:
                d.push(0x00, 0x00, 0x00);
                break;
            case 4:
                d.push(0x00, 0x00, 0x00, 0x00);
                break;
            case 5:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 6:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 7:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 8:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 9:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00);
                break;
            case 10:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00);
                break;
            case 11:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00);
                break;
            case 12:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00);
                break;
            case 13:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 14:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 15:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 16:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 17:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00);
                break;
            case 18:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00);
                break;
            case 19:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00);
                break;
            case 20:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00);
                break;
            case 21:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 22:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 23:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 24:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 25:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00);
                break;
            case 26:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00);
                break;
            case 27:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00);
                break;
            case 28:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00);
                break;
            case 29:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 30:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            case 31:
                d.push(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
                break;
            }

            t += off;
        }

        var j = t - duration;
        d.splice(d.length - j, j);
    },

    generateSawWave: function(pitch, duration) {
        var t = 0, d = this.data, vol = this.volume,
            eg = this.envelopeGenerator,
            v = function() { return vol * (t % pitch) * eg(t++) / pitch; };

        while (t < duration) {
            for (var j = pitch; (j -= 32) > 0; ) {
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v());
            }
            j += 32;
            switch (j) {
            case 0:
                break;
            case 1:
                d.push(v());
                break;
            case 2:
                d.push(v(), v());
                break;
            case 3:
                d.push(v(), v(), v());
                break;
            case 4:
                d.push(v(), v(), v(), v());
                break;
            case 5:
                d.push(v(), v(), v(), v(), v());
                break;
            case 6:
                d.push(v(), v(), v(), v(), v(), v());
                break;
            case 7:
                d.push(v(), v(), v(), v(), v(), v(), v());
                break;
            case 8:
                d.push(v(), v(), v(), v(), v(), v(), v(), v());
                break;
            case 9:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v());
                break;
            case 10:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v());
                break;
            case 11:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v());
                break;
            case 12:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v());
                break;
            case 13:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v());
                break;
            case 14:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v());
                break;
            case 15:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v());
                break;
            case 16:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v());
                break;
            case 17:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v());
                break;
            case 18:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v());
                break;
            case 19:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v());
                break;
            case 20:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v());
                break;
            case 21:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v());
                break;
            case 22:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v());
                break;
            case 23:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v());
                break;
            case 24:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v());
                break;
            case 25:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v());
                break;
            case 26:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v());
                break;
            case 27:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v());
                break;
            case 28:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v());
                break;
            case 29:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v());
                break;
            case 30:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v());
                break;
            case 31:
                d.push(v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v(), v(),
                       v(), v(), v(), v(), v(), v(), v());
                break;
            }
        }

        var j = t - duration;
        d.splice(d.length - j, j);
    }
};

使い方は、
1. SoundGeneratorクラスをインスタンス化し、音量やエンベロープジェネレータを設定する。

var sg = new SoundGenerator();
sg.volume = 100;
sg.envelopeGenerator = function(t) { return Math.min(t, 1000) / 1000; }

2. generatePulseWave() もしくは generateSawWave() で音を合成する。

// 第1引数は音の高低 (周波数=16000 / n) で、第2引数は持続時間 (サンプル数)
sg.generatePulseWave(28, 3000);

3. SoundPlayerクラスの静的メソッドplay()で音を出す。

SoundPlayer.play(sg.data);

サンプルコード:

<html>
<head>
  <script type="text/javascript" src="sound.js"></script>
  <script type="text/javascript">
window.onload = function() {
var sg1 = new SoundGenerator();
sg1.generatePulseWave(15, 50000);

var sg2 = new SoundGenerator();
sg2.generatePulseWave(20, 50000);

SoundPlayer.play(sg1.data, sg2.data);
};
  </script>
</head>
<body>
</body>
</html>