播放生成的声音

Posted

技术标签:

【中文标题】播放生成的声音【英文标题】:play back generated sounds 【发布时间】:2012-10-29 19:11:39 【问题描述】:

我想捕获音频(在我的情况下来自getUserMedia)并播放它。我可以像这样将一堆 AudioBuffers 推送到一个数组中:

var recorder = audio_context.createjavascriptNode(256, 2, 2);
recorder.onaudioprocess = function(e) 
  recorded.push(e.inputBuffer.getChannelData(0));
  // or just:
  // recorded.push(e.inputBuffer);
;
recorder.connect(audio_context.destination);

那么我该如何播放recorded 数组中的缓冲区呢?

一种将这些合并到一个缓冲区并与createBufferSource一起播放的方法?

完全不同的方法?

【问题讨论】:

您是否尝试从 getUserMedia 录制单声道或立体声音频? 任何事情都会做 :) 我得到了一些工作 [1] 多亏了这个导出到 wav 的录音迷你库 [2]。但是为了播放而导出到 wav 感觉有点矫枉过正 [1] phpied.com/files/webaudio/record.html [2] github.com/mattdiamond/Recorderjs 哦,是的,我看到你找到了我的 Recorderjs 库。也许我会添加一个功能来导出为 AudioBuffer,嗯... 【参考方案1】:

录制完音频后,您应该能够执行以下操作:

var bufferIndex = 0;
recorder.onaudioprocess = function (e) 
  var outputData = e.outputbuffer.getChannelData(0);
  var recordedData = recorded[bufferIndex];
  for (var i = 0; i < recordedData.length; i++) 
    outputData[i] = recordedData[i];
  );
  bufferIndex++;

(您可能可以让它更简单/更干净;这只是为了说明目的)

【讨论】:

我试过了,但它不适合我,会再试一次,也许我在其他地方有问题:) 谢谢! 这很奇怪。我没有测试它,所以我可能是错的。您的录音机是否连接到目的地?如果是这样,我稍后会测试它,看看我是否做错了。 使用此解决方案要记住的是,您需要不断循环访问存储在 recorded 中的 Float32Arrays。因此,每次调用onaudioprocess 时,您都需要移动到下一个缓冲区并将其用作recordedData。此外,您可能可以使用 .set 方法而不是手动迭代输出缓冲区数组。 感谢您对 set 的引用——这可能会使这更快(更短)。 @Stoyan 顺便问一下,您在控制台中看到任何错误吗?或者有任何迹象表明可能出了什么问题?【参考方案2】:

在我看来,最简单的方法是按照您的建议将它们合并到单个 AudioBuffer 中并通过 AudioBufferSourceNode 播放。我将首先通过context.createBuffer 方法创建一个新的AudioBuffer 对象,特别是使用numberOfChannels、长度和sampleRate 作为参数的版本。要计算长度(以秒为单位),您需要知道所有样本数组组合的大小......您可能希望在捕获它们时简单地保持运行总计(类似于recLength += currentBuffer.length)。然后,您可以通过将样本总数除以采样率来确定长度。采样率可以通过context.sampleRate确定。

一旦您创建了具有正确参数的新 AudioBuffer 对象,您只需将保存的数组(您的 recorded 数组)复制到 AudioBuffer 的通道数据数组中。这是一个相当简单的两步过程:

    通过 AudioBuffer 的 getChannelData(channel) 方法检索底层通道数据 遍历您的recorded 数组,并通过.set(array, offset) 方法将保存的数据复制到通道数据数组中(有关更多信息,请参阅the MDN Float32Array docs)。您的代码看起来类似于 channelData.set(currArray, currOffset),其中 currOffset 会随着每个存储数组的长度而增加。

注意:如果您正在录制两个音频通道,您将拥有两个录制样本数组,并且您必须为每个通道(0 和 1)执行上述两个步骤, 复制对应的数组。

如果操作正确,您将拥有一个 AudioBuffer,您可以将其插入 AudioBufferSourceNode 并按您认为合适的方式播放。

【讨论】:

如果你没有太长的录音,这很有效。但是,API 不鼓励将它们用于长声音(因为您对样本数量也有限制......)。不过,我可能误解了一些东西。

以上是关于播放生成的声音的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 上播放声音?

AS3 加色合成。播放多个生成的声音

在 iOS 中立即开始播放简短的自制声音

在 C# 中播放动态创建的简单声音,无需外部库

使用 AVAudioPlayer 播放声音后恢复背景音频

如何在 UILocalNotification 中播放录制的声音