0

我正在尝试使用Web Audio API即时(非实时)从从 URL 加载的声音中提取振幅信息,这可能需要OfflineAudioContext. 我期望沿着包含声音t持续时间每秒的声音幅度的数组的线获得一些东西(大小取决于声音的持续时间,除以t)。不幸的是,此时文档很少,我不确定如何继续。如何加载声音并每秒钟提取一次幅度t

4

1 回答 1

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 中。

使用 anOfflineAudioContext可能会更快。我真的不确定。但即使你决定走那条路,你仍然需要做很多手动工作才能获得这些任意t秒数的幅度。

于 2014-03-27T02:46:58.740 回答