录制音频作品,播放方式太快

时间:2012-02-21 15:46:02

标签: flash actionscript-3 audio audio-recording playback

我正在使用以下功能录制麦克风的音频输入:

    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行就足够了?有没有办法确定录制时需要写入缓冲区的数据量?

1 个答案:

答案 0 :(得分:4)

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然后在录制时将额外的重复样本写入缓冲区(简单的“上采样”) - 即写入4个浮点数,而不是2,如果以22 kHz录制,8如果以11 kHz录制则为8。

要注意的另一件事是输出样本不是单个浮点数,而是两个 - 每个通道一个。因此,麦克风将为您提供8192个单声道样本,您应该 - 通过将每个样本写入两次来应用于两个声道。您现在有8192个“立体声”样本。

但是,当您编写输出时,您最多写入8192个浮点数(i) - 这对应于4096个立体声采样。另一半 - 我假设您的代码和结果 - 被抛弃了。

最后,您得到的是在采样率下记录的8192个样本的前半部分,比回放采样率低约5.5倍。意思是声音看起来会播放2 * 5.5 = 11倍太快。

确保将所有样本写入输出,并以44.1 kHz(或如上所述的上采样)进行录制,并且应以正确的速度播放。

在旁注中,复制缓冲区的event.data.writeBytes可能更快 lot (假设 - 实际上没有检查过):

_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
   );
}