我正在尝试使用Web Audio API瞬间(不是实时)从URL加载的声音中提取振幅信息,这可能需要OfflineAudioContext
。我希望在声音的持续时间内每隔t
秒获得一个包含声音幅度的数组线(大小取决于声音的持续时间除以t
) 。不幸的是,此时文档很少,我不确定如何继续。如何加载声音并每隔t
秒提取振幅?
答案 0 :(得分:2)
这很快就完成了,所以数学可能搞砸了。但希望它能让你开始......
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
秒这些任意块的振幅。