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