【问题标题】:audio-unit sample rate and buffer size音频单元采样率和缓冲区大小
【发布时间】:2012-02-03 02:16:29
【问题描述】:

在使用 remoteIO 对 iphone 音频进行采样时,我遇到了一个真正的误解。

从一方面来说,我可以做这个数学运算:44khz 采样率意味着每 1ms 44 个样本。这意味着如果我将 bufferSize 设置为 0.005 :

float bufferLength = 0.00005;
     AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(bufferLength), &bufferLength);

这意味着 5ms 缓冲区大小 - 这意味着每个回调的缓冲区中有 44*5=220 个样本。 但是我从 inNumberFrames 每个回调中获得 512 个样本。即使我更改缓冲区长度,它也保持不变。

另一件事,我的回调是每 11 毫秒,并且没有改变!我需要更快的回调。

所以! 这里发生了什么 ? 谁设置了什么?

我需要在 FSK 调制中传递数字信息,并且必须准确地知道样本中的缓冲区大小,以及它所具有的信号的时间,以便知道如何正确地对其进行 FFT。

对此有何解释? 非常感谢。

【问题讨论】:

  • float bufferLength = 0.00005; 将是 50 µs,而不是 5 ms - 这太小了。
  • 那是我的错误,我已经改了。它应该是 0.005
  • 问题中仍然显示 0.00005 - 如果这不正确,那么您需要点击 edit 按钮并修复它

标签: objective-c xcode core-audio audio-recording


【解决方案1】:

目前所有 iOS 10 设备都无法以比每 5 到 6 毫秒更快的速率获取 RemoteIO 音频录制缓冲区回调。操作系统甚至可能决定在运行时切换到以更低的回调速率发送更大的缓冲区。您请求的速率只是一个请求,然后操作系统决定硬件、设备驱动程序和设备状态可能的实际速率。此速率可能保持不变,也可能不会保持不变,因此您的应用只需要处理不同的缓冲区大小和速率。

您的一个选项可能是将每个回调缓冲区连接到您自己的缓冲区,然后在音频回调之外根据您喜欢的方式分割第二个缓冲区。但这不会减少实际延迟。

添加:一些较新的 iOS 设备允许返回持续时间短于 5.x 毫秒的音频单元缓冲区,通常是 2 的幂,采样率为 48000。

【讨论】:

  • 我可以得到 3ms。见上面的帖子。
  • 一些较新的 iOS 设备现在可以做到低于 5.3 毫秒,但并非所有 iOS 10 设备都可以。
  • 我试图在 48000 Hz 的 40 毫秒内获取音频样本,结果是 1920 个样本,但是每当调用回调函数时,它都会获取 2048 个样本,并且我测量到回调函数也每 42.6 毫秒调用一次(与 48000 Hz 的 2048 个样本一致)。是否只有固定水平的样本数量,这些是否总是 2 的幂?有没有办法控制采集的样本数量?
  • ...我注意到,无论我选择什么作为收集样本的持续时间,它都会自动选择 2 的幂并相应地更改持续时间。有没有办法更精确地控制它?
  • 缓冲区大小,因此持续时间可能基于 iOS 设备 ADC 硬件 DMA 传输大小,因此不会在 OS 驱动程序之外暴露给任何应用程序 API。所以你需要自己做缓冲(循环队列/fifo)来获得你需要的大小。
【解决方案2】:

音频会话属性是一个建议值。你可以输入一个非常小的数字,但只会达到它可以的最低值。我在 iOS 设备上使用 16 位立体声时看到的最快速度是 0.002902 second ( ~3ms )。

即每个回调 128 个样本(LR 立体帧)。因此,每个回调 512 个字节。 所以128/44100 = 0.002902 seconds。

您可以通过以下方式进行检查:

AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &size, &bufferDuration)

原帖中的值 512 是否意味着字节而不是样本?

【讨论】:

    【解决方案3】:

    我需要在 FSK 调制中传递数字信息,并且必须准确地知道样本中的缓冲区大小,以及它所具有的信号的时间,以便知道如何正确地对其进行 FFT。

    它不是这样工作的 - 您不要求各种主机或硬件以最适合您的处理的精确方式运行。您可以请求减少延迟 - 在一定程度上。音频系统通常以大小为 2 的幂的样本块的形式传递流式 pcm 数据,以实现高效的实时 io。

    您将为您的处理器创建自己的缓冲区,并报告延迟(如果适用)。您可以尝试通过选择其他采样率或使用较小的 N 来减少墙延迟。

    【讨论】:

    • 谢谢。什么是 N?如果我降低采样率,我的回调会更快吗?我可以将采样率降低到 10khz。那么我的回调会更快吗?现在是 11 毫秒。它对我来说很慢。
    • 我已将采样率降低到 22100,有时每 11 毫秒和有时 6 毫秒都会收到回调。它甚至没有关闭到固定。我只需要大约 1ms 的固定时间回调,并且使用 goertzel 算法,我正在做 fft,每 1ms 再次。
    • @Rant 我指的是你的 fft 的长度。更长的 fft 会增加延迟(在实时环境中)。重新采样率:也许,也许不是。它取决于硬件以及程序和硬件之间的软件。如果缓冲区大小有最小值,更高的采样率会产生更少的延迟并且你的回调频率会增加。如果您还以较小的块传递数据,则降低采样率也会有所帮助。对于在 fft 中运行并受 fft 精度约束的程序,增加采样率通常只会增加 cpu 的工作量。 (续)
    • (续)但是是的,您可以在某些情况下提高采样率和/或减少 fft 长度以减少延迟。您必须测试硬件设置以查看哪个提供最低延迟(或谷歌) - 我不知道答案。一旦确定,为您的应用程序找到合适的 fft 长度。
    • 我认为你没有抓住重点。您创建自己的缓冲区。报告您的延迟。当样本进入时写入缓冲区,然后从排队样本的缓冲区中读取。然后产生输出——如果你遵循,你会看到这个过程也会引入延迟。您的处理器不能依赖固定的输入大小。如果您在 logic 或garageband 中打开 AU,录制启用轨道,添加使用长 fft 的插入,并实时监控效果,您也会在那里听到问题。没有处理器可以预测未来。需要运行或分析时间段的处理器会引入延迟。
    猜你喜欢
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2017-07-10
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多