3

我正在使用 OfflineAudioContext 在后台进行波形分析。

在 Chrome、Firefox 和 Opera 中一切正常,但在 Safari 中我得到了一个非常狡猾的行为。波形应该由许多样本(329)组成,但在 Safari 中,样本只有 ~38。

window.AudioContext = window.AudioContext || window.webkitAudioContext;
window.OfflineAudioContext = window.OfflineAudioContext || 
window.webkitOfflineAudioContext;

const sharedAudioContext = new AudioContext();

const audioURL = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1141585/song.mp3';

const audioDidLoad = ( buffer ) =>
{
  console.log("audio decoded");
  var samplesCount = 0;
  const context = new OfflineAudioContext(1, buffer.length, 44100);
  const source = context.createBufferSource();
  const processor = context.createScriptProcessor(2048, 1, 1);

  const analyser = context.createAnalyser();
  analyser.fftSize = 2048;
  analyser.smoothingTimeConstant = 0.25;

  source.buffer = buffer;

  source.connect(analyser);
  analyser.connect(processor);
  processor.connect(context.destination);

  var freqData = new Uint8Array(analyser.frequencyBinCount);
  processor.onaudioprocess = () =>
  {
    analyser.getByteFrequencyData(freqData);
    samplesCount++;
  };

  source.start(0);
  context.startRendering();

  context.oncomplete = (e) => {
    document.getElementById('result').innerHTML = 'Read ' + samplesCount + ' samples';

   source.disconnect( analyser );
    processor.disconnect( context.destination );
  };
};

var request = new XMLHttpRequest();
request.open('GET', audioURL, true);
request.responseType = 'arraybuffer';
request.onload = () => {
  var audioData = request.response;
  sharedAudioContext.decodeAudioData(
    audioData,
    audioDidLoad,
    e => { console.log("Error with decoding audio data" + e.err); }
  );
};
request.send();

请参阅Codepen

4

1 回答 1

2

我认为在这里,Safari 具有正确的行为,而不是其他行为。onaudioprocess的工作方式是这样的:你给一个缓冲区大小(创建scriptProcessor时的第一个参数,这里是 2048 个样本),每次处理这个缓冲区时,都会触发事件。所以你取你的采样率(默认为 44.1 kHz,意味着每秒 44100 个样本),然后除以缓冲区大小,即每次处理的样本数,你得到每秒的时间数将触发 audioprocess 事件。见https://webaudio.github.io/web-audio-api/#OfflineAudioContext-methods

该值控制 onaudioprocess 事件的调度频率以及每次调用需要处理多少样本帧。

当您实际播放声音时,情况确实如此。您需要在适当的时间处理适当的数量,以便正确播放声音。但是offlineAudioContext 处理音频而不关心真正的播放时间。

它不会渲染到音频硬件,而是尽可能快地渲染,将渲染结果作为 AudioBuffer 履行返回的承诺

因此,使用 OfflineAudioContext,无需计算时间。每次处理缓冲区时,Chrome 和其他人似乎都会触发 onaudioprocess,但对于离线音频上下文,它应该不是必需的。

话虽如此,通常也不需要将onaudioprocessofflineAudioContext一起使用,除非可能对性能有所了解。所有数据都可以从上下文中获得。此外,329 个样本并没有多大意义,它基本上只是样本数除以缓冲区大小。在您的示例中,您有 673830 个样本的来源,每秒 44100 个样本。所以你的音频是 15,279 秒。如果您一次处理 2048 个样本,您处理音频大约 329 次,这是您使用 Chrome 获得的 329。无需使用onaudioprocess来获取此号码。

而且由于您使用离线音频上下文,因此无需实时处理这些样本,甚至无需在每 2048 个样本处调用onaudioprocess 。

于 2018-05-18T15:45:37.983 回答