跳转至

音频服务(Audio Server)与缓冲管理

在音频概览中确定音频接口和产品使用场景后,可参考本页。本文重点说明应用代码、Audio Server 会话、DMA 缓冲区和硬件音频链路在运行时如何分工。

**SDK 行为的适用范围:**下文的 API 细节见于当前 SiFli SDK 中针对 SF32LB52x 的文档。针对实际目标型号和 SDK 版本,请以对应的 audio_server.h、实现代码及配置为准。缓冲区容量、任务调度和缓存维护建议属于工程建议;Audio Server 并不保证所有目标平台上的行为或缓冲区所有权完全相同。

会话职责划分

将应用层的控制策略与数据流传输分开:应用决定何时开始或停止播放、录音,以及如何处理状态变化;Audio Server 协调会话;DMA 传输采样块;驱动配置硬件。音频流运行期间,不要让 UI、蓝牙(Bluetooth)回调或文件系统读取逻辑直接操作编解码器寄存器。

表:缓冲区所有权
职责边界 所有者 评审问题
源数据 应用、解码器或存储任务 能否及时补充播放队列,避免队列耗尽?
Audio Server 写缓存(如已配置) Audio Server;容量由应用配置 当前 SDK 是否支持所设的 write_cache_size?应用是否处理了每一种 audio_write() 返回值?
正在传输的缓冲区 DMA/音频驱动 缓冲区在整个传输期间是否保持稳定,并满足缓存一致性要求?
已完成传输的缓冲区 应用或处理任务 DMA 再次使用该区域前,是否已填入播放数据,或处理完采集数据?
会话状态 Audio Server 与应用策略 重复的启动、停止、错误处理和收尾请求,是否能够避免重复关闭或释放资源?

缓冲策略

在驱动支持的情况下,可从双缓冲开始:DMA 传输一块区域时,软件在另一块区域准备播放数据,或处理已采集的数据。应区分应用的 PCM 队列和驱动的 DMA 缓冲区;向 Audio Server 写入数据,并不意味着 DMA 一定采用零拷贝传输。

只有当存储延迟(latency)、解码时间、蓝牙传输抖动或调度波动确实需要时,才扩大队列容量。容量决定内存占用,实际排队的音频数据量决定等待时间;仅分配更多缓冲区,并不一定增加延迟。可参考音频概览中的音频帧计算方法,计入声道数和每个采样值实际占用的字节数。

测量数据块持续时间、准备或处理一块数据所需的最坏时间,以及可接受的端到端延迟。每项操作的截止时间应依据目标驱动提供的缓冲区补充通知、传输完成通知以及缓冲区复用顺序确定。如果驱动提供半传输和全传输回调,应围绕这些状态切换安排处理;不要把当前传输结束视为唯一截止时间。播放数据必须在 DMA 需要时就绪;录音数据必须在 DMA 覆盖前处理完或复制出去。留出调度余量,即使只出现偶发的播放欠载(underrun)或录音溢出(overrun),也要查明原因。

对于应用或驱动直接交给 DMA 使用的内存,应遵守目标平台的缓存维护和缓冲区所有权规则:DMA 读取 CPU 写入的播放数据前,按要求将相应缓存行写回内存;接收缓冲区也要按要求提前准备;如果目标平台要求,CPU 读取已完成采集的数据前还要使相应缓存失效。这些操作取决于 SoC、内存区域和驱动 API;除非对应 API 明确要求,否则不要手动对由 Audio Server 或驱动拥有的缓冲区执行缓存维护。DMA 持有某个区域期间,不得修改、释放或复用该区域。

SF32LB52x Audio Server 文档说明,回调在 Audio Server 线程中执行;audio_open() 回调中不得调用 audio_close(),否则可能导致死锁。回调的耗时应有上限;可能阻塞的存储访问或数据处理应交给工作线程。采集回调会收到一帧数据的指针和长度,但该文档没有说明回调返回后指针还能保持多久有效。除非目标 SDK 明确保证更长的有效期,否则应在回调返回前复制数据。

该 SF32LB52x 文档说明了 audio_write() 的以下返回值:

表:文档定义的 audio_write() 返回值(SF32LB52x)
返回值 文档定义的含义
> 0 返回值等于 data_len;数据已写入写缓存。
0 写缓存已满。请求数据长度超过所配置的缓存容量时,同样会被拒绝并返回 0。
-1 客户端已暂停或挂起;本次提交的音频数据会被丢弃。
-2 参数无效。

该 API 将 write_cache_size 限制为最多 0x7FFF 字节,并建议至少设为单次 audio_write() 数据量的两倍,以支持其 ping-pong 写入方式。这是 Audio Server 的软件写缓存,不代表驱动 DMA 物理缓冲区的布局。应用这些限制前,请核对目标型号对应的 SDK 版本。客户端优先级、混音策略和可用音频链路也取决于 SDK 配置;成功打开会话,不代表芯片的所有音频接口都已接入 Audio Server。

在产品负载下验证

在产品中的典型并发负载下测试音频会话,包括显示刷新、蓝牙通知或音频、存储读写、日志记录和低功耗状态切换。记录播放欠载、录音溢出、队列占用量、回调到工作线程执行的延迟、音频卡顿、重连以及睡眠/唤醒切换。还要测试优先级抢占、挂起与恢复、启动失败和重复停止请求,确认恢复策略符合预期,而不是在没有提示的情况下丢失数据。

停止会话时,确认驱动已停止传输,尚未处理完的回调不会再访问已释放的缓冲区。检查音频相关的电源请求和外部器件是否已按硬件时序释放。系统功耗验证请参阅低功耗概览;无线共存请参阅蓝牙概览。

最后更新: