MediaElementAudioSourceNode | オーディオデータの再生

START / PAUSE
MediaElementAudioSourceNode
MediaElementAudioSourceNode
PropertyValuehasOwnProperty
AudioNode
AudioNode
PropertyValuehasOwnProperty
(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;
        }

        var displayProperties = function(node, tableid, caption) {
            var html = '<caption>' + caption + '</caption>';

            html += '<thead>';
            html += '<tr>';
            html += '<th scope="col">Property</th>';
            html += '<th scope="col">Value</th>';
            html += '<th scope="col">hasOwnProperty</th>';
            html += '</tr>';
            html += '</thead>';

            html += '<tbody>';

            for (var key in node) {
                html += '<tr>';
                html += '<td>' + key + '</td>';
                html += '<td>' + node[key] + '</td>';
                html += '<td>' + node.hasOwnProperty(key) + '</td>';
                html += '</tr>';
            }

            html += '</tbody>';

            document.getElementById(tableid).innerHTML = html;
            document.getElementById(tableid).parentNode.previousElementSibling.style.display = 'block';
        };

        // for createObjectURL
        window.URL = window.URL || window.webkitURL;

        // for HTMLAudioElement
        var audio = null;

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

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

        // for playbackRate (HTMLAudioElement)
        var playbackRate = document.getElementById('range-playback-rate').valueAsNumber;

        // Start / Pause Button
        var controlButton = document.getElementById('button-control-audio');

        /*
         * Create Nodes for Effector
         */

        // Delay
        context.createDelay = context.createDelay || context.createDelayNode;  // for legacy browsers
        var delay     = context.createDelay();
        var delayIn   = context.createGain();
        var delayOut  = context.createGain();
        var dry       = context.createGain();
        var wet       = context.createGain();
        var feedback  = context.createGain();

        delayIn.gain.value  = 1.0;
        delayOut.gain.value = 1.0;
        dry.gain.value      = 1.0;
        wet.gain.value      = 0.0;
        feedback.gain.value = 0.0;

        // GainNode (Input) -> GainNode (Dry) -> GainNode (Output)
        delayIn.connect(dry);
        dry.connect(delayOut);

        // GainNode (Input) -> DelayNode (Delay) -> GainNode (Wet) -> GainNode (Output)
        delayIn.connect(delay);
        delay.connect(wet);
        wet.connect(delayOut);

        // (GainNode (Input) ->) DelayNode (Delay) -> GainNode (Feedback) -> DelayNode (Delay) ...
        delay.connect(feedback);
        feedback.connect(delay);

        // Filter
        var filter = context.createBiquadFilter();

        var setupAudio = function(src) {
            // Clear previous audio
            if (audio instanceof HTMLAudioElement) {
                audio.pause();
                audio = null;

                document.getElementById('audio-tag').removeChild(document.getElementById('audio-tag').firstChild);
                controlButton.innerHTML = '<span class="icon-start"></span>';
            }

            // Create the instance of HTMLAudioElement
            audio = new Audio(src);
            audio.setAttribute('controls', true);
            document.getElementById('audio-tag').appendChild(audio);
            audio.style.display = 'none';

            // Create the instance of MediaElementAudioSourceNode after "onloadstart" event
            audio.addEventListener('loadstart', function(event) {
                window.alert('Start "' + event.type + '" !!');

                // Create the instance of MediaElementAudioSourceNode
                var source = context.createMediaElementSource(audio);

                // MediaElementAudioSourceNode (Input) -> BiquadFilterNode (Filter) -> Delay (Delay) -> GainNode (Master Volume) -> AudioDestinationNode (Output)
                source.connect(filter)
                filter.connect(delayIn)
                delayOut.connect(gain);
                gain.connect(context.destination);

                /*
                 * Display properties
                 */

                // Prototype chain
                var prototypes = {};

                prototypes.MediaElementAudioSourceNode = Object.getPrototypeOf(source);                                  // MediaElementAudioSourceNode instance -> MediaElementAudioSourceNode
                prototypes.AudioSourceNode             = Object.getPrototypeOf(prototypes.MediaElementAudioSourceNode);  // MediaElementAudioSourceNode -> AudioSourceNode
                prototypes.AudioNode                   = Object.getPrototypeOf(prototypes.AudioSourceNode);              // AudioSourceNode -> AudioNode

                displayProperties(source,               'mediaelementaudiosourcenode-properties', 'MediaElementAudioSourceNode');
                // displayProperties(prototypes.AudioNode, 'audionode-properties',                   'AudioNode');
            }, false);

            audio.addEventListener('play', function() {
                controlButton.innerHTML = '<span class="icon-pause"></span>';
            }, false);

            audio.addEventListener('pause', function() {
                controlButton.innerHTML = '<span class="icon-start"></span>';
            }, false);
        };

        /*
         * Event Listener
         */

        // File Uploader
        document.querySelector('[type="file"] + button').addEventListener(EventWrapper.CLICK, function() {
            document.querySelector('[type="file"]').click();
        }, false);

        document.querySelector('[type="file"]').addEventListener('change', function(event) {
            var uploader     = this;
            var progressArea = document.getElementById('progress-file-upload-audio');

            // Get the instance of File (extends Blob)
            var file = event.target.files[0];

            if (!(file instanceof File)) {
                window.alert('Please upload file.');
            } else if (file.type.indexOf('audio') === -1) {
                window.alert('Please upload audio file.');
            } else {
                setupAudio(window.URL.createObjectURL(file));
            }
        }, false);

        // Audio Controller is visible ?
        document.querySelector('[type="checkbox"]').addEventListener(EventWrapper.CLICK, function() {
            if (audio instanceof HTMLAudioElement) {
                audio.style.display = this.checked ? 'block' : 'none';
            }
        }, false);

        // Start or Pause audio
        controlButton.addEventListener(EventWrapper.CLICK, function() {
            if (audio instanceof HTMLAudioElement) {
                if (audio.paused) {
                    audio.playbackRate = playbackRate;
                    audio.play();
                } else {
                    audio.pause();
                }
            }
        }, false);

        // 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() {
            if (audio instanceof HTMLAudioElement) {
                audio.playbackRate = playbackRate = this.valueAsNumber;
            } else {
                playbackRate = this.valueAsNumber;
            }

            document.getElementById('output-playback-rate').textContent = this.value;
        }, false);

        // Control Delay Time
        document.getElementById('range-delay-time').addEventListener('input', function() {
            var min = delay.delayTime.minValue || 0;
            var max = delay.delayTime.maxValue || 1;

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

        // Control Delay Dry
        document.getElementById('range-delay-dry').addEventListener('input', function() {
            var min = dry.gain.minValue || 0;
            var max = dry.gain.maxValue || 1;

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

        // Control Delay Wet
        document.getElementById('range-delay-wet').addEventListener('input', function() {
            var min = wet.gain.minValue || 0;
            var max = wet.gain.maxValue || 1;

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

        // Control Delay Feedback
        document.getElementById('range-delay-feedback').addEventListener('input', function() {
            var min = feedback.gain.minValue || 0;
            var max = feedback.gain.maxValue || 1;

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

        // Select Filte Type
        document.getElementById('select-filter').addEventListener('change', function() {
            filter.type = this.value;
        }, false);

        // Control Cutoff
        document.getElementById('range-cutoff').addEventListener('input', function() {
            var min = filter.frequency.minValue || 10;
            var max = filter.frequency.maxValue || (context.sampleRate / 2);

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

        // Control Q (Quality Factor)
        document.getElementById('range-Q').addEventListener('input', function() {
            var min = filter.Q.minValue || 0.0001;
            var max = filter.Q.maxValue || 1000;

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

        // Control Filter Gain
        document.getElementById('range-filter-gain').addEventListener('input', function() {
            var min = filter.gain.minValue || -40;
            var max = filter.gain.maxValue ||  40;

            if ((this.valueAsNumber >= min) && (this.valueAsNumber <= max)) {
                filter.gain.value = this.valueAsNumber;
                document.getElementById('output-filter-gain').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;
})();