【问题标题】:OfflineAudioContext and FFT in SafariSafari 中的 OfflineAudioContext 和 FFT
【发布时间】:2018-03-19 05:12:53
【问题描述】:

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

【问题讨论】:

  • windows 10 firefox“读取2878个样本”
  • @headmax,太好了,越多越好! ;) Safari Mac 是个问题。
  • 这个web api不能在safari上运行的原因,因为这个api比较年轻,你需要做一个polyfill才能跨浏览器使用这里polyfill github.com/jonathantneal/AudioContext
  • @headmax 你在 Mac 上试过 Codepen 了吗?这个 API 确实有效。可能比使用 4 年的 polyfill 更好。
  • 我不知道有 mac ;) 所以你自己试试吧。是的,我想这个链接是旧的,但你的问题并没有过时;)试试看,如果没有运行,试着理解这个 polyfill 的含义并适应你的上下文。

标签: safari web-audio-api audiocontext webkitaudiocontext


【解决方案1】:

我认为,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

【讨论】:

  • 非常感谢您的反馈!将尝试消化它并找到一种将其与analyzer.getByteFrequencyData 一起使用的方法。这最终是我 FFT 所需要的。
  • 你觉得这合适吗? code.i-harness.com/en/q/7b33a8 getByteFrequencyData 只调用一次,不对!?!
  • 评论已有 2 年历史,此时它可能工作正常(显然不是在 Safari 中)。话虽如此,您可以使用库来分析渲染的缓冲区。如果您将 getChannelData 与离线一起使用,您将获得与 getFloatTimeData 与 on 进程相同的信息,这是用于获取 getByteFrequencyData 的信息。但似乎 API 没有公开从时间数据到频率的函数,除了通过 onprocess 事件。但这可以通过图书馆来完成。
  • 为什么图书馆会这样做而不是我?
猜你喜欢
  • 2019-07-28
  • 2022-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-28
  • 2012-04-30
  • 1970-01-01
  • 2015-11-16
相关资源
最近更新 更多