我正在使用以下功能录制来自麦克风的音频输入:
private function handleSampleData(p_sampleEvent:SampleDataEvent) :void
{
var data :Number;
while (p_sampleEvent.data.bytesAvailable)
{
data = p_sampleEvent.data.readFloat();
_buffer.writeFloat(data);
_buffer.writeFloat(data);
}
}
这似乎有效。完成录制后,我将录制的数据复制到另一个缓冲区,如下所示:
_buffer.position = 0;
_lastRecord = new ByteArray();
while (_buffer.bytesAvailable)
{
_lastRecord.writeFloat(_buffer.readFloat());
}
_lastRecord.position = 0;
之后,我在新创建的声音上使用 play() 并使用此函数将 _lastRecord 缓冲区提供给它:
public function handlePlaybackSampleData(p_sampleEvent:SampleDataEvent) :void
{
// Read data until either MAX_SAMPLES or all available samples are reached.
var i:int = 0;
var data :Number = 0;
while( i < 8192 )
{
if( _lastRecord.bytesAvailable )
{
data = _lastRecord.readFloat();
p_sampleEvent.data.writeFloat(data);
i++;
continue;
}
else
{
break;
}
}
}
虽然它基本上可以工作,但播放的结果声音太快了。
我已经从一个例子中提取了大部分代码,在这个例子中,它工作得非常好。我看不出我的代码和这个代码之间有什么重要的区别:http://labs.makemachine.net/2011/04/record-visualize-save-microphone-input/
尽管如此,音频出来的速度还是太快了。如果我通过添加更多的“_buffer.writeFloat(data);”将更多数据放入 _buffer,它会变得更好,当我有 12 行时,它就是所需的速度。但即使这样也只有在我碰到我的麦克风时才有帮助。如果我真的说话,那似乎也不够。
但是怎么会这样呢?为什么在我从中获取该代码的示例中,只有 2 行就足够了?有没有办法确定录制时需要将多少数据写入缓冲区?
最佳答案
FlashPlayer 中麦克风的默认采样率为 8 kHz 单声道 - 或者,如果不可用,则为第一个可用的 11.025 kHz、22.05 kHz 或 44.1 kHz。音频输出始终为 44.1 kHz 立体声。这意味着,您获得的样本太少:44.1/8 ~= 5.5。
您可以通过将录音采样率设置为 44.1 kHz 来解决此问题:
microphone.rate = 44; // Yes, the API doesn't want the decimals
您也可以将费率保持在例如22 或 11,然后在记录时将额外的重复样本写入缓冲区(简单的“上采样”) - 即如果以 22 kHz 记录,则写入 4 个浮点数,而不是 2 个,如果以 11 kHz 记录,则写入 8 个浮点数。
要注意的另一件事是输出样本不是单个浮点数,而是两个 - 每个 channel 一个。因此,麦克风将为您提供 8192 个单声道样本,您 - 就像您应该的那样 - 通过将每个样本写入两次来应用于两个 channel 。您现在有 8192 个“立体声”样本。
但是,当您编写输出时,您最多编写 8192 个浮点数 (
i
) - 对应于 4096 个立体声样本。另一半 - 我从你的代码和你的结果中假设 - 被扔掉了。最后,您得到的是 8192 个样本的前半部分,其采样率比播放采样率低大约 5.5 倍。这意味着声音的播放速度似乎太快了 2*5.5 = 11 次。
确保将所有样本写入输出,并以 44.1 kHz(或如上所述的上采样)录制,并且应该以正确的速度播放。
在旁注中,
event.data.writeBytes
复制缓冲区可能要快得多(假设 - 尚未实际检查):_lastRecord = new ByteArray();
_lastRecord.writeBytes(_buffer, 0, _buffer.bytesAvailable);
写入示例数据也是如此:
public function handlePlaybackSampleData(p_sampleEvent:SampleDataEvent) :void
{
// Maximum amount of samples we're allowed to write: 8192
// Copying bytes here, rather than floats, so:
// 8192 samples * 2 channels * 4 bytes per float = 65536:
var bytesToCopy:int = Math.min(_lastRecord.bytesAvailable, 65536);
// Using _lastRecord.position since some of it may have been written on the
// last call to handlePlaybackSampleData if it had more than 8192 samples:
p_sampleEvent.data.writeBytes(
_lastRecord,
_lastRecord.position,
bytesToCopy
);
}
关于flash - 录音正常,播放速度太快,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9380499/