How to slice an AudioBuffer
・1 min read
Slice out a portion of an AudioBuffer.
var audioContext = new (window.AudioContext || window.webkitAudioContext);
function AudioBufferSlice(buffer, begin, end, callback) {
if (!(this instanceof AudioBufferSlice)) {
return new AudioBufferSlice(buffer, begin, end, callback);
}
var error = null;
var duration = buffer.duration;
var channels = buffer.numberOfChannels;
var rate = buffer.sampleRate;
if (typeof end === 'function') {
callback = end;
end = duration;
}
// milliseconds to seconds
begin = begin/1000;
end = end/1000;
if (begin < 0) {
error = new RangeError('begin time must be greater than 0');
}
if (end > duration) {
error = new RangeError('end time must be less than or equal to ' + duration);
}
if (typeof callback !== 'function') {
error = new TypeError('callback must be a function');
}
var startOffset = rate * begin;
var endOffset = rate * end;
var frameCount = endOffset - startOffset;
var newArrayBuffer;
try {
newArrayBuffer = audioContext.createBuffer(channels, endOffset - startOffset, rate);
var anotherArray = new Float32Array(frameCount);
var offset = 0;
for (var channel = 0; channel < channels; channel++) {
buffer.copyFromChannel(anotherArray, channel, startOffset);
newArrayBuffer.copyToChannel(anotherArray, channel, offset);
}
} catch(e) {
error = e;
}
callback(error, newArrayBuffer);
}
Usage:
var audioContext = new AudioContext();
var analyser = audioContext.createAnalyser();
var source = audioContext.createBufferSource();
var url = 'https://example.com/audio.mp3';
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
xhr.onerror = handleError;
xhr.onload = function() {
if (xhr.status === 200) {
handleBuffer(xhr.response);
} else {
console.error(xhr.statusText);
}
};
xhr.send();
function handleError(error) {
console.error(error);
}
function handleBuffer(audioData) {
audioContext.decodeAudioData(audioData, decodeDone);
}
function decodeDone(buffer) {
var begin = 50000;
var end = begin + 20000;
AudioBufferSlice(buffer, begin, end, function(error, slicedAudioBuffer) {
if (error) {
console.error(error);
} else {
source.buffer = slicedAudioBuffer;
var gainNode = audioContext.createGain();
gainNode.gain.value = 1;
source.connect(gainNode);
gainNode.connect(audioContext.destination);
}
});
}
On github at miguelmota/audiobuffer-slice