录音正常,播放速度太快

发布于 2025-01-08 01:36:00 字数 1798 浏览 1 评论 0原文

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

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

I am recording audio input from microphone using the following function:

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

This seems to work. After I have finished recording, I copy the recorded data to another buffer like this:

            _buffer.position = 0;
            _lastRecord = new ByteArray();
            while (_buffer.bytesAvailable)
            {
                _lastRecord.writeFloat(_buffer.readFloat());
            }
            _lastRecord.position = 0;

And after that, I use play() on a newly created sound and feed the _lastRecord buffer to it using this function:

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

While it does basically work, the resulting sound that is played is waaaaay too fast.
I have taken most of the code from an example in which this works perfectly fine. I see no more vital differences between my code and this one: http://labs.makemachine.net/2011/04/record-visualize-save-microphone-input/

Still, the audio comes out way too fast. If I put even more data into the _buffer by adding more "_buffer.writeFloat(data);", it becomes better, and when I have 12 lines of that, it is the desired speed. But even that only helps when I just bump against my mic. If I actually speak, that does not seem sufficient, either.

But how comes that? And how comes that in the example I took that code from, only 2 lines of that is sufficient? Is there a way to determine how much data I need to write into the buffer while recording?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

木有鱼丸 2025-01-15 01:36:00

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 录音。

另一件需要注意的事情是,输出样本不是单个浮点数,而是两个浮点数 - 每个通道一个。因此,麦克风将为您提供 8192 个单声道样本,您应该通过将每个样本写入两次来将其应用到两个通道。您现在有 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
   );
}

The default sample rate of the microphone in FlashPlayer is 8 kHz mono - or, if that's not available, the first available of 11.025 kHz, 22.05 kHz or 44.1 kHz. Audio output is always 44.1 kHz stereo. This means, that the samples you're getting are too few: 44.1 / 8 ~= 5.5.

You can fix this by setting the recording sample rate to 44.1 kHz:

microphone.rate = 44; // Yes, the API doesn't want the decimals

You could also keep the rate at e.g. 22 or 11 and then write additional duplicate samples to your buffer (simple "upsampling") when recording - i.e. write 4 floats, rather than 2, if recording at 22 kHz, 8 if recording at 11 kHz.

One other thing to be aware of is that an output sample isn't a single float, but two - one for each channel. So, the microphone will give you 8192 mono samples, which you - like you should - apply to both channels by writing each sample twice. You now have 8192 "stereo" samples.

When you're writing the output, however, you're writing at most 8192 floats (i) - which correspond to 4096 stereo samples. The other half - I'd assume from your code and your results - is thrown out.

In the end, what you get is the first half of 8192 samples recorded at a samplerate approximately 5.5 times lower than the playback samplerate. Meaning the sound will appear to play 2*5.5 = 11 times too fast.

Make sure to write all the samples to the output, and record at 44.1 kHz (or upsample as described above), and it should play back at the right speed.

On a sidenote, event.data.writeBytes is likely to be a lot faster for copying the buffer (assumption - haven't actually checked):

_lastRecord = new ByteArray();
_lastRecord.writeBytes(_buffer, 0, _buffer.bytesAvailable);

Same for writing the sample data:

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
   );
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文