(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;
if (document.getElementById(tableid).parentNode.previousElementSibling !== null) {
document.getElementById(tableid).parentNode.previousElementSibling.style.display = 'block';
}
};
// for legacy browsers
context.createScriptProcessor = context.createScriptProcessor || context.createJavaScriptNode;
// for selecting optimized buffer size
var getBufferSize = function() {
if (/(Win(dows )?NT 6\.2)/.test(navigator.userAgent)) {
return 1024; // Windows 8
} else if (/(Win(dows )?NT 6\.1)/.test(navigator.userAgent)) {
return 1024; // Windows 7
} else if (/(Win(dows )?NT 6\.0)/.test(navigator.userAgent)) {
return 2048; // Windows Vista
} else if (/Win(dows )?(NT 5\.1|XP)/.test(navigator.userAgent)) {
return 4096; // Windows XP
} else if (/Mac|PPC/.test(navigator.userAgent)) {
return 1024; // Mac OS X
} else if (/Linux/.test(navigator.userAgent)) {
return 8192; // Linux
} else if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
return 2048; // iOS
} else {
return 16384; // Otherwise
}
};
// Create the instance of ScriptProcessorNode
var processor = context.createScriptProcessor(getBufferSize(), 2, 2);
// for the instance of OscillatorNode
var oscillator = null;
var volume = document.getElementById('range-volume').valueAsNumber;
// Flag for starting or stopping sound
var isStop = true;
// for processed buffer size
var count = 0;
// Get DOM for displaying processed buffer size
var outputBufferSize = document.querySelector('[type="number"]');
/*
* Event Listener
*/
// Start or Stop sound
document.querySelector('button').addEventListener(EventWrapper.CLICK, function() {
if (isStop) {
// Start onaudioprocess event
// Create the instance of OscillatorNode for input
oscillator = context.createOscillator();
// for legacy browsers
oscillator.start = oscillator.start || oscillator.noteOn;
oscillator.stop = oscillator.stop || oscillator.noteOff;
// OscillatorNode (Input) -> ScriptProcessorNode (Volume) -> AudioDestinationNode (Output);
oscillator.connect(processor);
processor.connect(context.destination);
// Important !!
oscillator.start(0);
processor.onaudioprocess = function(event) {
// Get the instance of Float32Array for input data (Array size equals buffer size)
var inputLs = event.inputBuffer.getChannelData(0); // Left channel
var inputRs = event.inputBuffer.getChannelData(1); // Right channel
// Get the instance of Float32Array for output data (Array size equals buffer size)
var outputLs = event.outputBuffer.getChannelData(0); // Left channel
var outputRs = event.outputBuffer.getChannelData(1); // Right channel
for (var i = 0; i < this.bufferSize; i++) {
outputLs[i] = volume * inputLs[i];
outputRs[i] = volume * inputRs[i];
}
displayProperties(event, 'audioprocessingevent-properties', 'AudioProcessingEvent');
outputBufferSize.valueAsNumber = count * this.bufferSize;
count++;
};
isStop = false;
this.innerHTML = '<span class="icon-pause"></span>';
} else {
// Stop onaudioprocess event
processor.disconnect();
processor.onaudioprocess = null;
oscillator.stop(0);
isStop = true;
this.innerHTML = '<span class="icon-start"></span>';
isCreateTable = false;
window.alert('Execute "disconnect" and Clear "onaudioprocess" event handler !!');
}
}, false);
// Control Volume (without GainNode)
document.getElementById('range-volume').addEventListener('input', function() {
var min = 0;
var max = 1;
if ((this.valueAsNumber >= min) && (this.valueAsNumber <= max)) {
volume = this.valueAsNumber;
document.getElementById('output-volume').textContent = this.value;
}
}, false);
/*
* Display properties
*/
// Prototype chain
var prototypes = {};
// Prototype chain
prototypes.ScriptProcessorNode = Object.getPrototypeOf(processor); // ScriptProcessorNode instance -> ScriptProcessorNode
prototypes.AudioNode = Object.getPrototypeOf(prototypes.ScriptProcessorNode); // ScriptProcessorNode -> AudioNode
displayProperties(processor, 'scriptprocessornode-properties', 'ScriptProcessorNode');
// displayProperties(prototypes.AudioNode, 'audionode-properties', 'AudioNode');
};
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;
})();