Safari中的OfflineAudioContext和FFT

时间:2017-10-07 15:30:52

标签: safari web-audio web-audio-api audiocontext webkitaudiocontext

我正在使用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

1 个答案:

答案 0 :(得分: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,但是对于离线音频上下文,它确实不是必需的。

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

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