这很快就完成了,所以数学可能会搞砸。但希望它能让你开始......
var ac = new webkitAudioContext(),
url = 'path/to/audio.mp3';
function fetchAudio( url, callback ) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
callback(xhr.response);
};
xhr.send();
}
function decode( arrayBuffer, callback ) {
ac.decodeAudioData(arrayBuffer, function( audioBuffer ) {
callback(audioBuffer);
});
}
// return an array of amplitudes for the supplied `audioBuffer`
//
// each item in the array will represent the average amplitude (in dB)
// for a chunk of audio `t` seconds long
function slice( audioBuffer, t ) {
var channels = audioBuffer.numberOfChannels,
sampleRate = ac.sampleRate,
len = audioBuffer.length,
samples = sampleRate * t,
output = [],
amplitude,
values,
i = 0,
j, k;
// loop by chunks of `t` seconds
for ( ; i < len; i += samples ) {
values = [];
// loop through each sample in the chunk
for ( j = 0; j < samples && j + i < len; ++j ) {
amplitude = 0;
// sum the samples across all channels
for ( k = 0; k < channels; ++k ) {
amplitude += audioBuffer.getChannelData(k)[i + j];
}
values.push(amplitude);
}
output.push(dB(values));
}
return output;
}
// calculate the average amplitude (in dB) for an array of samples
function dB( buffer ) {
var len = buffer.length,
total = 0,
i = 0,
rms,
db;
while ( i < len ) {
total += ( buffer[i] * buffer[i++] );
}
rms = Math.sqrt( total / len );
db = 20 * ( Math.log(rms) / Math.LN10 );
return db;
}
// fetch the audio, decode it, and log an array of average
// amplitudes for each 5-second chunk
fetchAudio(url, function( arrayBuffer ) {
decode(arrayBuffer, function( audioBuffer ) {
console.log(slice(audioBuffer, 5));
});
});
基本上,如果您想比实时更快地获取整个缓冲区的数据,您甚至不需要OfflineAudioContext。您可以阅读示例,做一些数学运算,然后弄清楚。
不过,这很慢。特别是对于较大的音频文件。所以你可能想把它放在一个 Web Worker 中。
使用OfflineAudioContext 可能会更快。我真的不确定。但即使你决定走这条路,你仍然需要做很多手动工作才能获得t 秒的这些任意块的幅度。