サウンドスケジューリング | オーディオデータの再生

AudioContext currentTimeプロパティ
START
(function() {

    var onDOMContentLoaded = function() {

        window.AudioContext = window.AudioContext || window.webkitAudioContext;

        try {
            // Create the instance of AudioContext
            var context = new AudioContext();
        } catch (error) {
            window.alert(error.message + ' : Please use Chrome or Safari.');
            return;
        }

        // for legacy browsers
        context.createGain = context.createGain || context.createGainNode;

        // Create the instance of GainNode
        var gain = context.createGain();

        var base = './audio-oneshot/';
        var urls = [
            (base + 'C.wav'),
            (base + 'D.wav'),
            (base + 'E.wav'),
            (base + 'F.wav'),
            (base + 'G.wav'),
            (base + 'A.wav'),
            (base + 'B.wav')
        ];

        // for the instances of AudioBuffer
        var buffers = new Array(urls.length);

        // for the instances of AudioBufferSourceNode
        var sources = new Array(urls.length);

        var interval = document.getElementById('range-interval').valueAsNumber;  // 1 sec

        // Create original event
        var event = document.createEvent('Event');
        event.initEvent('complete', true, true);

        // Get ArrayBuffer by Ajax
        var load = function(url, index) {
            var xhr = new XMLHttpRequest();

            // Timeout (1 minutes)
            xhr.timeout = 60000;

            xhr.ontimeout = function() {
                window.alert('Timeout.');
            };

            xhr.onerror = function() {
                window.alert('Ajax Error.');
            };

            xhr.onload = function() {
                if (xhr.status === 200) {
                    var arrayBuffer = xhr.response;  // Get ArrayBuffer

                    if (arrayBuffer instanceof ArrayBuffer) {
                        // The 2nd argument for decodeAudioData
                        var successCallback = function(audioBuffer) {
                            // Get the instance of AudioBuffer
                            buffers[index] = audioBuffer;

                            // The loading instances of AudioBuffer has completed ?
                            for (var i = 0, len = buffers.length; i < len; i++) {
                                if (buffers[i] === undefined) {
                                    return;
                                }
                            }

                            // dispatch 'complete' event
                            document.querySelector('button').dispatchEvent(event);
                        };

                        // The 3rd argument for decodeAudioData
                        var errorCallback = function(error) {
                            if (error instanceof Error) {
                                window.alert(error.message);
                            } else {
                                window.alert('Error : "decodeAudioData" method.');
                            }
                        };

                        // Create the instance of AudioBuffer (Asynchronously)
                        context.decodeAudioData(arrayBuffer, successCallback, errorCallback);
                    }
                }
            };

            xhr.open('GET', url, true);
            xhr.responseType = 'arraybuffer';
            xhr.send(null);
        };

        for (var i = 0, len = urls.length; i < len; i++) {
            load(urls[i], i);
        }

        document.querySelector('button').addEventListener('complete', function() {
            window.alert('The instances of AudioBuffer have just been created !!');

            this.addEventListener(EventWrapper.CLICK, function() {
                // Get base time
                var t0 = context.currentTime;

                for (var i = 0, len = buffers.length; i < len; i++) {
                    // Create the instance of AudioBufferSourceNode
                    sources[i] = context.createBufferSource();

                    // for legacy browsers
                    sources[i].start = sources[i].start || sources[i].noteGrainOn;  // noteGrainOn
                    sources[i].stop  = sources[i].stop  || sources[i].noteOff;

                    // Set the instance of AudioBuffer
                    sources[i].buffer = buffers[i];

                    // Set playBackRate
                    sources[i].playbackRate.value = document.getElementById('range-playback-rate').valueAsNumber;

                    // AudioBufferSourceNode (Input) -> GainNode (Master Volume) -> AudioDestinationNode (Output)
                    sources[i].connect(gain);
                    gain.connect(context.destination);

                    sources[i].start((t0 + (interval * i)), 0, (sources[i].buffer.duration / sources[i].playbackRate.value));
                    sources[i].stop(t0 + (interval * i) + (sources[i].buffer.duration / sources[i].playbackRate.value));
                }
            }, false);

        }, false);

        /*
         * Display currentTime
         */
        var outputCurrentTime = document.querySelector('[type="number"]');

        window.setInterval(function() {
            outputCurrentTime.valueAsNumber = Math.round(context.currentTime * 100) / 100;
        }, 0);

        /*
         * Event Listener
         */

        // Control Master Volume
        document.getElementById('range-volume').addEventListener('input', function() {
            var min = gain.gain.minValue || 0;
            var max = gain.gain.maxValue || 1;

            if ((this.valueAsNumber >= min) && (this.valueAsNumber <= max)) {
                gain.gain.value = this.valueAsNumber;
                document.getElementById('output-volume').textContent = this.value;
            }
        }, false);

        // Control playbackRate
        document.getElementById('range-playback-rate').addEventListener('input', function() {
            document.getElementById('output-playback-rate').textContent = this.value;
        }, false);

        // Control Interval
        document.getElementById('range-interval').addEventListener('input', function() {
            interval = this.valueAsNumber;
            document.getElementById('output-interval').textContent = this.value;
        }, false);
    };

    if ((document.readyState === 'interactive') || (document.readyState === 'complete')) {
        onDOMContentLoaded();
    } else {
        document.addEventListener('DOMContentLoaded', onDOMContentLoaded, true);
    }

})();
function EventWrapper(){
}

(function(){
    var click = '';
    var start = '';
    var move  = '';
    var end   = '';

    // Touch Panel ?
    if (/iPhone|iPad|iPod|Android/.test(navigator.userAgent)) {
        click = 'click';
        start = 'touchstart';
        move  = 'touchmove';
        end   = 'touchend';
    } else {
        click = 'click';
        start = 'mousedown';
        move  = 'mousemove';
        end   = 'mouseup';
    }

    EventWrapper.CLICK = click;
    EventWrapper.START = start;
    EventWrapper.MOVE  = move;
    EventWrapper.END   = end;
})();