ビブラート | エフェクター

START / STOP
WAVE TYPE
LFO WAVE TYPE
(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;
        }

        // Create the instance of OscillatorNode
        var oscillator = context.createOscillator();  // for Input
        var lfo        = context.createOscillator();  // for LFO

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

        // Create the instance of GainNode
        var gain  = context.createGain();  // for Volume
        var depth = context.createGain();  // for LFO

        // Parameters for the instance of OscillatorNode
        var type      = oscillator.type;
        var frequency = oscillator.frequency.value;
        var detune    = oscillator.detune.value;

        // Parameters for LFO
        var lfos ={
            type  : document.getElementById('form-lfo-type').elements['radio-lfo-type'][0].value,
            depth : document.getElementById('range-depth').valueAsNumber,
            rate  : document.getElementById('range-rate').valueAsNumber
        };

        // Flag for starting or stopping sound
        var isStop = true;

        /*
         * Event Listener
         */

        // Start or Stop sound
        document.querySelector('button').addEventListener(EventWrapper.CLICK, function() {
            if (isStop) {
                // Create the instance of OscillatorNode
                oscillator = context.createOscillator();
                lfo        = context.createOscillator();

                // for legacy browsers
                oscillator.start = oscillator.start || oscillator.noteOn;
                oscillator.stop  = oscillator.stop  || oscillator.noteOff;
                lfo.start        = lfo.start        || lfo.noteOn;
                lfo.stop         = lfo.stop         || lfo.noteOff;

                // OscillatorNode (Input) -> GainNode (Volume) -> AudioDestinationNode (Output)
                oscillator.connect(gain)
                gain.connect(context.destination);

                // OscillatorNode (LFO) -> GainNode (Depth) -> frequency (AudioParam)
                lfo.connect(depth);
                depth.connect(oscillator.frequency);

                // Set parameters
                oscillator.type            = type;
                oscillator.detune.value    = detune;

                // Set parameters for LFO
                lfo.type                   = lfos.type;
                oscillator.frequency.value = frequency;
                depth.gain.value           = lfos.depth;
                lfo.frequency.value        = lfos.rate;

                // Start sound
                oscillator.start(0);

                // Start LFO
                lfo.start(0);

                isStop = false;
                this.innerHTML = '<span class="icon-pause"></span>';
            } else {
                // Stop sound
                oscillator.stop(0);

                // Stop LFO
                lfo.stop(0);

                isStop = true;
                this.innerHTML = '<span class="icon-start"></span>';
            }
        }, false);

        // Control 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);

        // Select type
        document.getElementById('form-wave-type').addEventListener('change', function() {
            for (var i = 0, len = this.elements['radio-wave-type'].length; i < len; i++) {
                if (this.elements['radio-wave-type'][i].checked) {
                    oscillator.type = type = (typeof oscillator.type === 'string') ? this.elements['radio-wave-type'][i].value : i;
                    break;
                }
            }
        }, false);

        // Control frequency
        document.getElementById('range-frequency').addEventListener('input', function() {
            var min = oscillator.frequency.minValue || 0;
            var max = oscillator.frequency.maxValue || 100000;

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

        // Control detune
        document.getElementById('range-detune').addEventListener('input', function() {
            var min = oscillator.detune.minValue || -4800;
            var max = oscillator.detune.maxValue ||  4800;

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

        // Select LFO Type
        document.getElementById('form-lfo-type').addEventListener('change', function() {
            for (var i = 0, len = this.elements['radio-lfo-type'].length; i < len; i++) {
                if (this.elements['radio-lfo-type'][i].checked) {
                    lfo.type = lfos.type = (typeof lfo.type === 'string') ? this.elements['radio-lfo-type'][i].value : i;
                    break;
                }
            }
        }, false);

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

        // Control Rate
        document.getElementById('range-rate').addEventListener('input', function() {
            var min = lfo.frequency.minValue || 0;
            var max = lfo.frequency.maxValue || 100000;

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

        // Output frequency in the instance of OscillatorNode
        window.setInterval(function() {
            console.log(oscillator.frequency.value);
        }, 500);
    };

    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;
})();