Skip to content

Instantly share code, notes, and snippets.

@jussi-kalliokoski
Created September 24, 2014 16:20
Show Gist options
  • Save jussi-kalliokoski/98aba1a8d749e4b9d482 to your computer and use it in GitHub Desktop.
Save jussi-kalliokoski/98aba1a8d749e4b9d482 to your computer and use it in GitHub Desktop.
Draw waveform ahead of time (doesn't work)
function loadAudio (url, playbackRate) {
return new Promise(function (resolve, reject) {
var track = new Audio(url);
track.playbackRate = playbackRate;
track.oncanplaythrough = function () {
resolve(track);
};
track.onerror = reject;
track.load();
});
}
function collectSamples (context, track, samplesPerSecond) {
return new Promise(function (resolve, reject) {
var bufferLength = Math.ceil(track.duration * samplesPerSecond);
var buffer = new Float32Array(bufferLength);
var collector = context.createScriptProcessor(0, 1);
var audioSource = context.createMediaElementSource(track);
var samplesCollected = 0;
function cleanup () {
track.pause();
collector.disconnect(context.destination);
audioSource.disconnect(collector);
collectSamples._fixChrome82795.splice(collectSamples._fixChrome82795.indexOf(collector), 1);
}
collector.onaudioprocess = function collectAudio (event) {
document.body.innerText = (track.currentTime / track.duration * 100).toFixed(2) + "%";
var samplesToCollect = bufferLength - samplesCollected;
var inputData = event.inputBuffer.getChannelData(0).subarray(0, samplesToCollect);
buffer.set(inputData, samplesCollected);
samplesCollected += inputData.length;
if ( track.currentTime === track.duration ) {
cleanup();
buffer = buffer.subarray(0, samplesCollected);
resolve(buffer);
}
};
track.onerror = reject;
track.playbackRate = context.sampleRate / samplesPerSecond;
audioSource.connect(collector);
collector.connect(context.destination);
track.play();
// http://code.google.com/p/chromium/issues/detail?id=82795
collectSamples._fixChrome82795.push(collector);
});
}
function getAudioData (url, samplesPerSecond) {
var context = new AudioContext();
return loadAudio(url, context.sampleRate / samplesPerSecond)
.then(function (track) {
return collectSamples(context, track, samplesPerSecond);
});
}
collectSamples._fixChrome82795 = [];
function getAmplitudes (attack, decay) {
return function collectAmplitudes (buffer) {
console.log(buffer);
var previousSample = 0;
for ( var i = 0; i < buffer.length; i++ ) {
var factor = 1 + (buffer[i] > previousSample ? attack : decay);
buffer[i] = Math.abs(factor * (previousSample - buffer[i]));
}
return buffer;
};
}
function drawWaveform (width, height) {
return function drawFromBuffer (buffer) {
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
var context = canvas.getContext("2d");
var halfHeight = Math.floor(height / 2);
var middleY = halfHeight;
context.beginPath();
var x = 0;
context.moveTo(x, middleY - buffer[0] * halfHeight);
for ( x = 1; x < width; x++ ) {
context.lineTo(x, middleY - buffer[Math.round(x / width * buffer.length)] * halfHeight);
}
for ( x = width; x-- > 0; ) {
context.lineTo(x, middleY + buffer[Math.round(x / width * buffer.length)] * halfHeight);
}
context.closePath();
context.fill();
document.body.appendChild(canvas);
};
}
getAudioData("audio.mp3", 200)
.then(getAmplitudes(0.1, 0.1))
.then(drawWaveform(800, 600))
.catch(function (error) {
console.error(error);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment