播放生成的声音
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 不鼓励将它们用于长声音(因为您对样本数量也有限制......)。不过,我可能误解了一些东西。以上是关于播放生成的声音的主要内容,如果未能解决你的问题,请参考以下文章