一、period_size 的物理意义

period_size = 每次 DMA 从 ring buffer 中消耗(或填充)多少 frames,完成后触发一次硬件中断 IRQ。

换句话说:

DMA 写/读到 period_size 的数据量,就触发一次 IRQ,让 AP 处理一次。

在 PCM 播放场景中:

  • AP(AudioFlinger → HAL)将数据写到 ALSA ring buffer

  • DMA 从 ring buffer 读数据送到 DAC

  • 每当 DMA 消耗完一个 period,DMA 产生 IRQ

  • IRQ 通知 AP:
    “我又消费完了一个 period,你可以再写数据了”

period_size 越小 → IRQ 越频繁 → latency 越低,但 AP 负载越高。


二、period_count 的物理意义

period_count = ring buffer 里包含几个 period。

所以:

总 buffer size = period_size × period_count

举例:


period_size = 240 frames period_count = 2

则:


缓冲区总容量 = 240 × 2 = 480 frames

这样 ring buffer 内部结构是:


[ period0: 240 frames ][ period1: 240 frames ]

DMA 从缓冲区循环播放
AP 往空出来的 period 写数据。


三、为什么需要 period_count?

主要原因:保证 DMA 不会饿死(underrun)

如果只有 1 个 period

  • AP 写完 240 frames

  • DMA 播放完 240 frames(这过程 AP 不能再写,因为 DMA 正在读同一块)

  • DMA 播完 → AP 才能再写

  • 非常容易 underrun
    (因为 AP 写数据/调度有 jitter)

有了 2 个 period:


DMA 播放 period0 → AP 可以同时写 period1 DMA 播放 period1 → AP 可以同时写 period0

实际音频系统常用 period_count = 2 或 3。


四、“Low-latency 240 / 2 / 480 / 10ms” 的含义

这 4 个数字典型表示:


period_size = 240 frames period_count = 2 buffer_size = 480 frames (= 240 * 2) latency = 10 ms


🔍 五、10 ms 是怎么计算的?

先判断采样率:

low-latency 输出路径通常是:


48000 Hz

计算 latency:

计算方式 1:以 ring buffer size 为准

这是 系统音频 latency 的主要来源之一


latency_ms = buffer_size / sample_rate * 1000

代入:


480 frames / 48000 Hz × 1000 = 0.01 秒 = 10 ms

这就是你看到 10ms 的来源

也就是说,这个配置的总音频硬件队列导致:

硬件播放延迟约 10ms

对 Android low_latency track 来说这符合预期
(普通 track 的 latency 要高得多,比如 20~40 ms)。


六、另外两个重要延迟(补充)

注意:10ms 只代表 driver 的 ring buffer。
Android 还包含:

  1. AudioFlinger Mixer → 1~2ms

  2. Resampler → 几 ms(取决于 CPU)

  3. HAL path → 0.5~1ms

  4. 音频 codec → 1~3ms

  5. Speaker 机械 → 1~3ms(耳机更低)

所以系统 total latency 可能是:


15~25 ms 之间

Low-latency track 主要优化:减小 ring buffer


总结(最清晰版本)

参数 物理意义
period_size DMA 每消耗 period_size frames,就触发一次 IRQ
period_count ring buffer 中 period 的个数,用于双缓冲或多缓冲
buffer_size = period_size × period_count ring buffer 总容量
latency(10ms) buffer_size / sample_rate

示例:


period_size = 240 frames period_count = 2 buffer_size = 480 frames sample_rate = 48000 Hz latency = 480 / 48000 = 0.01 秒 = 10ms

==========================另一个版本======================================

下面我把 period_size、period_count 的物理意义 以及 为什么 Low-latency 的 10 ms 是这么算出来的 全部讲清楚。
这些概念在 Android / ALSA / Qualcomm ASoC 中完全一致。


✅ 1. period_size 的物理意义:触发中断(IRQ)的单位

period_size = 每写完这么多帧后,DMA 触发一次中断 (IRQ)。

例如:

  • period_size = 240 frames

  • 采样率 = 48 kHz

那么写满这一段数据需要:

240/48000=5ms240 / 48000 = 5ms240/48000=5ms

→ 每 5ms 硬件对 AP(Audio DSP → CPU 或 DSP → AHAL)发起 一次中断

这是 Audio 中断的最小粒度,也称 interrupt interval

因此:

period_size 决定中断频率
✔ period_size 越小 → 中断越频繁 → 延迟更低但 CPU 负载更高


✅ 2. period_count 的物理意义:环形 buffer 的长度

period_count = 环形 DMA buffer 中 period 的个数。

整个 buffer 的总大小是:

buffer_size=period_size×period_countbuffer\_size = period\_size \times period\_countbuffer_size=period_size×period_count

这个 buffer 位于:

  • Playback:AHAL → DSP(PCM 环形 buffer)

  • Capture:DSP → AHAL(PCM 环形 buffer)

buffer 的作用:

🟦 period_count 是“提前准备的数据量”= 用于防止 underrun

如果只用 1 个 period,那么系统必须每 5ms 喂一次数据,稍有抖动就会 underrun。

因此:

  • period_count 通常 ≥ 2

  • 值越大 → 系统越稳 → 延迟越高

Qualcomm Low-latency:

参数 解释
period_size 240 frames 5ms
period_count 2 总 buffer 10ms
total buffer 480 frames 10ms

✅ 3. 10 ms 是怎么来的?

Low-latency 的表中有一行:


Low-latency period_size = 240 period_count = 2 buffer = 480 frames approx latency ≈ 10ms

它的计算方式非常直接:

latency=period_size×period_countsample_ratelatency = \frac{period\_size \times period\_count}{sample\_rate}latency=sample_rateperiod_size×period_count​

代入:

=240×248000=0.01=10ms= \frac{240 \times 2}{48000} = 0.01 = 10ms=48000240×2​=0.01=10ms

这就是 Qualcomm 文档中写的 10ms 低延迟模式


⚠️ 但是请注意:真实最终的“用户听到的延迟”不是 10ms

10ms 只是 DSP DMA buffer 的基础延迟
完整路径还有:

  • AudioTrack 侧 buffer(AAudio/Java/Native)

  • MixerThread / FastMixer processing 时间

  • DSP processing(effects / resampler)

  • AFE → Codec → I2S 的 pipeline 延迟

  • Codec 架构的 FIR latency

最终到耳机一般是:

25–60ms(wired)

100–200ms(Bluetooth SBC)


🟩 4. 总结(非常关键)

period_size = IRQ 粒度

  • 意味中断周期(interrupt interval)

  • 决定 CPU 负载和实时性

  • 小 period → 低延迟 → 高 CPU

period_count = DMA 环形 buffer 大小

  • 用于防 underrun

  • 期间 DSP 在消费数据

  • 越大越稳定但延迟越高

total_latency = period_size × period_count / sample_rate

Low-latency = 240 × 2 / 48000 = 10ms

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐