local_audio_visualizer.js | |
|---|---|
window.onload = function() {
var element = document.getElementById('container')
dropAndLoad(element, init, "ArrayBuffer")
} | |
| Reusable dropAndLoad function: it reads a local file dropped on a
| function dropAndLoad(dropElement, callback, readFormat) {
var readFormat = readFormat || "DataUrl"
dropElement.addEventListener('dragover', function(e) {
e.stopPropagation()
e.preventDefault()
e.dataTransfer.dropEffect = 'copy'
}, false)
dropElement.addEventListener('drop', function(e) {
e.stopPropagation()
e.preventDefault()
loadFile(e.dataTransfer.files[0])
}, false)
function loadFile(files) {
var file = files
var reader = new FileReader()
reader.onload = function(e) {
callback(e.target.result)
}
reader['readAs'+readFormat](file)
}
} |
| Once the file is loaded, we start getting our hands dirty. | function init(arrayBuffer) {
document.getElementById('instructions').innerHTML = 'Loading ...' |
| Create a new | window.audioCtx = new webkitAudioContext()
window.analyser = audioCtx.createAnalyser() |
| If a sound is still playing, stop it. | if (window.source)
source.noteOff(0) |
| Decode the data in our array into an audio buffer | audioCtx.decodeAudioData(arrayBuffer, function(buffer) { |
| Use the audio buffer with as our audio source | window.source = audioCtx.createBufferSource()
source.buffer = buffer |
| Connect to the analyser ... | source.connect(analyser) |
| and back to the destination, to play the sound after the analysis. | analyser.connect(audioCtx.destination) |
| Start playing the buffer. | source.noteOn(0) |
| Initialize a visualizer object | var viz = new simpleViz() |
| Finally, initialize the visualizer. | new visualizer(viz['update'], analyser)
document.getElementById('instructions').innerHTML = ''
})
} |
| The visualizer object.
Calls the | function visualizer(visualization, analyser) {
var self = this
this.visualization = visualization
var last = Date.now()
var loop = function() {
var dt = Date.now() - last |
| we get the current byteFreq data from our analyser | var byteFreq = new Uint8Array(analyser.frequencyBinCount)
analyser.getByteFrequencyData(byteFreq)
last = Date.now() |
| We might want to use a delta time ( | self.visualization(byteFreq, dt)
webkitRequestAnimationFrame(loop)
}
webkitRequestAnimationFrame(loop)
} |
| A simple visualization. Its update function illustrates how to use the byte frequency data from an audioContext analyser. | function simpleViz(canvas) {
var self = this
this.canvas = document.getElementById('canvas')
this.ctx = this.canvas.getContext("2d")
this.copyCtx = document.getElementById('canvas-copy').getContext("2d")
this.ctx.fillStyle = '#fff'
this.barWidth = 10
this.barGap = 4 |
| We get the total number of bars to display | this.bars = Math.floor(this.canvas.width / (this.barWidth + this.barGap)) |
| This function is launched for each frame, together with the byte frequency data. | this.update = function(byteFreq) {
self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height) |
| We take an element from the byteFreq array for each of the bars. Let's pretend our byteFreq contains 20 elements, and we have five bars... | var step = Math.floor(byteFreq.length / self.bars) |
|
| for (var i = 0; i < self.bars; i ++) { |
| Draw each bar | var barHeight = byteFreq[i*step]
self.ctx.fillRect(
i * (self.barWidth + self.barGap),
self.canvas.height - barHeight,
self.barWidth,
barHeight)
self.copyCtx.clearRect(0, 0, self.canvas.width, self.canvas.height)
self.copyCtx.drawImage(self.canvas, 0, 0)
}
}
}
|