【问题标题】:Web Audio to visualize and interact with waveforms用于可视化波形并与波形交互的 Web 音频
【发布时间】:2012-03-19 22:54:20
【问题描述】:

如何编写 JavaScript 程序来显示音频文件中的波形?我想使用网络音频和画布。

我试过这段代码:

(new window.AudioContext).decodeAudioData(audioFile, function (data) {
   var channel = data.getChannelData(0);
   for (var i = 0; i < channel; i++) {
       canvas.getContext('2d').fillRect(i, 1, 40 - channel[i], 40);
   }
});

但结果与我想要的相差甚远(即图像不平滑,因为我正在使用矩形进行绘制)。我希望它看起来像这张图片一样平滑:

关于如何实现波形的任何提示?

【问题讨论】:

标签: javascript html canvas web-audio-api


【解决方案1】:

您可能对AudioJedit 感兴趣。这是一个开源项目hosted at GitHub。它有用于加载音频文件的小型服务器端 node.js 脚本,但所有与音频的交互都是在客户端 JavaScript 中实现的。我认为这与您正在寻找的相似。

【讨论】:

  • Vadim,这几乎就是我想要的。它们不生成波形图形(它是从 SoundCloud 加载的),但使用 RealtimeAnalyserNode 添加很容易。非常感谢!
【解决方案2】:

毕竟推出了我自己的库:wavesurfer.js

它从 PCM 数据中绘制一个波形,并通过点击它来寻找音频区域。

【讨论】:

  • 如何绘制本地音频文件的波形(这些文件不在服务器上,但在我电脑的其他目录中可用)。你的js可以吗?
  • @madLokesh,是的,可以使用 File API (dev.w3.org/2006/webapi/FileAPI) 绘制文件。
  • 我正在使用 Cordova,所以我想我必须使用 Cordova 的 File API 来访问文件,但是我应该如何传递音频文件。作为 base64 编码的 URl 或作为数组缓冲区
  • 非常感谢。我会尝试一下,让你知道。我建议你在你的 GitHub 上也记录同样的内容
  • 由于某些奇怪的原因,我无法让演示在页面加载时加载音频文件,但是当它作为 blob 拖放时它可以工作
【解决方案3】:

为了(希望)简单地使用波形并将波形与您的应用程序集成,您可能需要检查我们在 IRCAM 所做的工作,特别是在这种特殊情况下的波形可视化。

它都是开源的,旨在实现模块化(并且正在进行中)

您可以找到demo over here
以及对应的githug repository

【讨论】:

  • 两个链接都是404。
【解决方案4】:

您的渲染代码效率极低,因为它将为每秒的音频渲染 44100 像素。您希望最好使用减少的数据集渲染最多视口宽度。

可以使用 audioDurationSeconds * samplerate / viewPortWidthPx 计算适合视口中波形所需的每像素采样范围。因此,对于 1000 像素的视口和 2 秒的音频文件,采样率为 44100,每个像素的样本数 = (2 * 44100) / 1000 = ~88。 对于屏幕上的每个像素,您可以从该样本范围中获取最小值和最大值,然后使用这些数据来绘制波形。

这是一个示例算法,它允许您将每个像素的样本作为参数以及滚动位置以允许虚拟滚动和缩放。它包括一个可以调整性能的分辨率参数,这表明每个像素样本范围应该采用多少样本: Drawing zoomable audio waveform timeline in Javascript

那里的draw方法和你的类似,为了平滑它你需要使用lineTo而不是fillRect。这个差异实际上不应该那么大,我想你可能忘记设置宽度和高度属性画布。在css中设置这个会导致绘制模糊,需要设置属性。

let drawWaveform = function(canvas, drawData, width, height) {
   let ctx = canvas.getContext('2d');
   let drawHeight = height / 2;

   // clear canvas incase there is already something drawn
   ctx.clearRect(0, 0, width, height);

   ctx.beginPath();
   ctx.moveTo(0, drawHeight);
   for(let i = 0; i < width; i++) {
      // transform data points to pixel height and move to centre
      let minPixel = drawData[i][0] * drawHeigth + drawHeight;
      ctx.lineTo(i, minPixel);
   }
   ctx.lineTo(width, drawHeight);
   ctx.moveTo(0, drawHeight);
   for(let i = 0; i < width; i++) {
      // transform data points to pixel height and move to centre
      let maxPixel = drawData[i][1] * drawHeigth + drawHeight;
      ctx.lineTo(i, maxPixel);
   }
   ctx.lineTo(width, drawHeight);
   ctx.closePath();
   ctx.fill(); // can do ctx.stroke() for an outline of the waveform
} 

【讨论】:

    猜你喜欢
    • 2019-07-02
    • 2011-05-31
    • 1970-01-01
    • 2011-03-18
    • 2012-11-16
    • 2016-09-07
    • 2016-12-09
    • 2017-07-08
    • 2023-03-31
    相关资源
    最近更新 更多