音频驱动开发指南
本文档介绍 HiDiTing V100 音频子系统的基本特性、组件关系和典型场景开发流程。文档直接以 SDK src/application/audio 中已有的音频场景代码为参考,开发者可通过内置 AT^AUDIO 命令验证场景,并据此阅读和修改业务代码。
音频驱动背景知识
音频子系统概述
HiDiTing V100 音频子系统包含输入采集、数据适配、播放、编解码和语音算法等能力。应用可使用服务层接口,也可参考 src/application/audio 的已有场景代码理解底层 UAPI 的初始化、建链、运行和释放顺序。

组件基本特性
| 组件 | 基本特性 | 典型使用场景 | 代码和接口参考 |
|---|---|---|---|
| SYS | 音频全局初始化、产品形态、场景、音量和静音管理 | 所有音频业务的生命周期管理 | AudioManagerInit、AudioManagerSetVolume |
| ADP | 在输入、算法、编解码和播放组件间适配流、帧和缓冲 | AI→AENC、AI→SOUND、SEA 链路 | /src/drivers/drivers/driver/audio/include/soc_uapi_adp.h |
| SOUND / AO | 输出设备、端口、Track、音量和音效管理 | PCM 播放、解码播放、回环 | AudioStreamOutInit、AudioStreamOutPlay |
| AI | 从 ADC、PDM、I2S 等端口采集 PCM | 录音、回环、实时编码 | AudioStreamInInit、AudioStreamInStart |
| AENC | 将 PCM 编码为 SBC、mSBC、OPUS、MP3 等码流 | 录音压缩、语音上行、存储 | AudioCodecFormat、/src/drivers/drivers/driver/audio/include/soc_uapi_aenc.h |
| ADEC | 将压缩音频码流解码为 PCM | 本地文件、网络或蓝牙码流播放 | AudioCodecFormat、/src/drivers/drivers/driver/audio/include/soc_uapi_adec.h |
| SEA | 语音增强和算法引擎管理,可插入 AEC、降噪等能力 | 语音通话、ASR 前处理 | AudioManagerSetSeaEnable、AudioManagerSetSeaParam |
| VAD | 识别静音、说话开始和结束 | 按需录音、低功耗语音业务 | /src/drivers/drivers/driver/audio/include/soc_uapi_sea.h |
| VENDOR | Codec、电源、时钟、端口路由与板级设备适配 | 新板卡、外部 Codec、PA/MIC 路由 | audio/vendor |
| ANC / HAID | 主动降噪、助听等产品化算法能力 | 耳机、助听类产品 | 受产品功能开关、算法参数和校准数据控制 |
SYS、ADP 与 SOUND 的职责
SYS 不直接处理 PCM,却决定音频实例能否按正确的场景、音量和生命周期运行。ADP 是组件间的数据适配层,负责向下游提供流或帧;SOUND 则管理播放端口和 Track。一个典型实时场景的资源顺序是:SYS/ADP 初始化 → 创建输入或解码实例 → 创建 SOUND Track → 建立连接 → 启动数据流 → 反向停止和释放。
SOUND、输出端口、Track 与 Cast
| 概念 | 含义 | 关键接口 | 使用边界 |
|---|---|---|---|
| SOUND | 一个播放设备实例,持有输出格式、端口和音效配置 | uapi_snd_open、uapi_snd_close |
先打开 SOUND,才可创建 Track 或配置端口 |
| 输出端口 | SOUND 的实际或逻辑输出目的地,如 DAC、I2S、BT、CAST | uapi_snd_out_port_attr、uapi_snd_set_track_mode |
PCM 格式必须与端口能力匹配 |
| Track | SOUND 内承载一条 PCM 输入流的播放通道,可单独设音量、启动和停止 | uapi_snd_create_track、uapi_snd_track_start、uapi_snd_track_stop |
多 Track 可由 SOUND 混音,Track 是 ADP 的常见下游 |
| Cast | SOUND 的逻辑输出端口,不连接物理扬声器;用于把播放侧 PCM 转送给 AENC 等下游 | UAPI_SND_OUT_PORT_CAST0、uapi_snd_attach_output |
适合“播放侧 PCM 再编码/转发”,不能替代 DAC/I2S 输出 |

图示说明: SOUND 实例处于播放侧中心位置。上游组件可经 ADP 将 PCM 送到 Track;Track 再按 SOUND 配置输出到 DAC、I2S、蓝牙等物理端口,或输出到 CAST 逻辑端口。开发时应先确定最终输出端口,再创建对应 SOUND 和 Track,避免出现“Track 已启动但输出端口未配置”的无声问题。

图示说明: 一个 SOUND 可以管理多个输出端口和 Track。端口属性决定设备侧 PCM 格式和路由,Track 属性决定单路业务的输入、音量和播放状态;音效参数属于 SOUND/端口侧,不能只通过修改输入 PCM 属性替代。
原始架构中定义 UAPI_SND_0、UAPI_SND_1、UAPI_SND_2 三个 SOUND 设备供组合使用;同一时刻最多允许打开 2 个 SOUND 设备、4 路 Track 和 4 个 OUTPORT。Track 输入可在 SOUND 内完成重采样和混音后输出。Track 音量和 OUTPORT 音量分两级设置,均为绝对音量,范围为 -81 dB~+18 dB,步长为 0.125 dB。
说明: CAST 使能后会形成虚拟 CAST OUTPORT,可投射系统解码输出的音频数据。它适合连接编码或分析下游,不等同于物理扬声器输出。
ADP 到 SOUND 的数据连接关系
下图不是前两张 SOUND 设备图的重复:前两图解释 SOUND、Track、OUTPORT 的设备模型;本图仅说明一条播放数据从 ADP 接入 Track 后,如何分别流向物理端口或 CAST 下游。它用于理解 PCM 播放、回环和“播放侧 PCM 再编码”场景的 attach_output 调用位置。

SOUND 默认属性说明
SOUND 的默认属性不是固定常量,而是由目标板、Codec 和产品配置决定。创建前应先调用 uapi_snd_get_default_attr() 获取默认属性,再只覆盖业务必须修改的字段。
| 默认属性项 | 获取方式 | 覆盖时机 | 说明 |
|---|---|---|---|
| 输出端口 | uapi_snd_get_default_attr() |
切换 DAC/I2S/CAST 等路由时 | 必须与 Vendor Codec 和板级连线一致 |
| 采样率、位宽、声道 | 默认 uapi_snd_attr |
输入 PCM 或下游设备格式变化时 | 必须与 Track、ADP 和端口能力兼容 |
| Track 属性 | uapi_snd_get_track_default_attr() |
创建 Track 前 | 用默认值创建后,再按业务设置音量和模式 |
| 音效 Profile / Bypass | SOUND 默认配置 | 启用特定音效或场景时 | 应在 SOUND 打开后、Track 运行前设置 |
AI 属性与数据流
| AI 属性 | 含义 | 配置要点 |
|---|---|---|
ai_port |
音频输入端口,如 ADC、PDM、I2S | 必须与板级 Codec、MIC 和引脚路由一致 |
pcm_attr.sample_rate |
采样率 | 与下游 ADP、SEA、AENC 或 SOUND 的格式兼容 |
pcm_attr.bit_depth |
PCM 位宽 | 常用 16 bit;高位宽链路需确认端口和算法能力 |
pcm_attr.channels |
声道数 | 单 MIC 常为单声道;双麦算法需匹配实际 MIC 数 |
sample_per_frame |
每帧采样点数 | 决定帧时长、缓冲大小和算法处理粒度 |
volume / mute |
输入增益和静音 | 仅在端口支持时生效;过高增益会造成削波 |
ref_attr |
参考信号属性 | AEC 等场景需指定参考输出端口 |

图示说明: 图中 AI 只负责从输入端口采集 PCM;ADP 才是供应用读取、缓存或继续挂接下游组件的数据出口。SEA、AENC、SOUND 等组件可作为 AI 或 ADP 的下游,使同一份 PCM 进入算法、编码或播放链路。
AI 默认参数说明
下表是语音采集场景的默认基线,用于快速验证 ADC/PDM/I2S 输入。实际项目应先通过 uapi_ai_get_default_attr() 取得目标板默认属性,再根据 Codec、MIC 数量和算法要求覆盖参数。
| 参数 | 语音采集默认基线 | 配置原因 |
|---|---|---|
| 采样率 | 16 kHz | 满足常见语音、mSBC、ASR/VAD 输入需求 |
| 位宽 | 16 bit | 兼顾语音精度、带宽和多数算法输入要求 |
| 声道数 | 1 | 单 MIC 采集;双麦算法按实际 MIC 数设置 |
| 每帧采样点 | sample_rate / 100 |
对应 10 ms 帧长,便于实时处理和算法调度 |
| 输入增益 | 0 dB | 先以无附加增益验证硬件,确认后再调节 |
| 静音 | 关闭 | 仅在业务需要时打开 |
| 参考信号 | 默认关闭 | AEC 等场景才开启,并指定参考输出端口 |
说明: AI 没有可供应用直接读取的音频数据出口。需要创建一路 ADP,并通过 uapi_ai_attach_output(h_ai, h_adp) 将 ADP 绑定到 AI 输出;应用或下游组件再从 ADP 获取 PCM。若下游是 SEA 或 AENC,则将 AI 输出直接绑定到对应句柄,由该组件继续处理。
AI→ADP 的关键顺序为:获取默认 AI 属性 → 设置端口和 PCM 属性 → 创建 ADP → 打开 AI → 设置音量/静音 → uapi_ai_attach_output() 绑定下游 → uapi_ai_start() 启动采集。停止时先停止 AI,再解除绑定、关闭 AI、销毁 ADP。
音频参数与接口说明
常用服务层接口可参考 AudioManager API;底层接口以表格中的头文件声明为准。
音频特性场景开发
内置 AT 命令的命令名为 AUDIO,定义在 /src/middleware/utils/at/at_audio_cmd/at/at_audio_cmd_table.h。发送 AT^AUDIO=<命令行> 后,调用链如下:audio_at_cmd_process() → audio_at_cmd_handle() → audio_para_to_args() → audio_execute_function()。
audio_execute_function() 的声明在 /src/application/audio/sample_audio.h,实现位于 /src/application/audio/sample_audio.c;该函数在 g_audio_func[] 表中查找首个参数对应的场景函数并执行。例如 AT^AUDIO=sample_ai_ao ... 最终调用 sample_ai_ao()。
/* at_audio.c:AT 参数进入现有音频场景代码的入口 */
audio_para_to_args(para_str, &argc, msg_argv);
audio_execute_function(argc, msg_argv);
| 函数 | 作用 | 与场景流程的关系 |
|---|---|---|
audio_para_to_args() |
按空格分割 AT^AUDIO 参数并分配 argv |
把串口文本转换为场景函数参数 |
audio_at_cmd_handle() |
复制 AT 原始参数、调用参数拆分,并在结束时释放内存 | AT 层只负责入口和参数生命周期,不处理 PCM |
audio_execute_function() |
在 g_audio_func 表中查找首个参数对应的场景函数并调用 |
连接 AT 与 sample_ai、sample_ao、sample_adec 等既有场景代码 |
audio_auto_exit_function() |
新实时场景启动前停止已运行的场景;收到 q 时标记结束 |
防止音频资源被多个实时场景同时占用 |
本文示例命令以一站式 CLI 为主。实际开发可从以下三种环境中选择,推荐使用一站式 CLI。
| 开发环境 | 适用场景 | 使用指南 |
|---|---|---|
| 一站式 CLI(推荐) | 快速完成目标选择、构建、烧录和串口监视 | 一站式 CLI 开发环境使用指南 |
| HiSpark Studio for VS Code | 图形化编辑、编译、烧录和调试 | HiSpark Studio for VS Code 开发环境使用指南 |
| WSL 与 Docker | 在 Windows 上使用一致的 Linux 容器构建环境 | WSL 与 Docker 环境使用指南 |
准备工作:按 一站式 CLI 开发环境使用指南 准备环境、构建和烧录;构建前必须确保 fbb doctor 成功。
PCM 播放场景(SOUND / AO)
功能说明:读取 PCM 文件,创建播放通路和 Track 后输出至 DAC 或 I2S,适用于提示音、音乐片段和扬声器验证。

实现流程:确认 PCM 格式 → 初始化 SOUND/AO → 创建并启动 Track → 循环写入 PCM → 停止 Track → 释放资源。
代码走读:参考 /src/application/audio/sample_ao/sample_ao.c。它按“文件、音量、采样率、位宽、声道”解析参数;SOUND 负责 Track 和输出设备,AO 负责将 Track 数据输出到实际端口。
| 流程步骤 | 关键函数 | 逐函数说明 |
|---|---|---|
| 初始化 | sample_ao_sys_init() |
初始化 ADP 与 SOUND;失败时不进入设备和 Track 创建。 |
| 打开设备 | sample_ao_open_snd() |
获取默认 uapi_snd_attr,设置端口、采样率、位宽、声道和 AEF Profile,调用 uapi_snd_open()。 |
| 创建通道 | sample_ao_open_track() |
获取 Track 默认属性,调用 uapi_snd_create_track(),再设置该 Track 音量。 |
| 建立数据连接 | sample_ao_open_adp() |
创建 ADP 并调用 uapi_adp_attach_output() 把 ADP 输出接到 Track。 |
| 送数播放 | sample_ao_track_thread() |
构造 uapi_audio_frame,读取 PCM,检查 ADP 空闲空间并送入播放链路。 |
| 启停释放 | sample_ao_track_start_inst() / sample_ao_track_stop_inst() |
依次启动/停止 Track 与送数线程;释放时按 ADP、Track、SOUND、SYS 的反向顺序关闭。 |
下面保留完整的最小初始化、送帧和释放顺序。实际应用应为每个接口补充返回值检查,并在失败分支中按相反顺序释放已创建资源。
uapi_adp_init();
uapi_snd_init();
uapi_snd snd_id;
uapi_snd_attr snd_attr;
uapi_snd_get_default_attr(snd_id, &snd_attr);
snd_attr.port_num = 1;
snd_attr.port_attr[0].out_port = UAPI_SND_OUT_PORT_I2S0;
snd_attr.channels = UAPI_AUDIO_CHANNEL_2;
snd_attr.bit_depth = UAPI_AUDIO_BIT_DEPTH_16;
snd_attr.sample_rate = UAPI_AUDIO_SAMPLE_RATE_48K;
td_handle h_snd = 0;
uapi_snd_open(&h_snd, snd_id, &snd_attr);
uapi_snd_track_attr track_attr;
uapi_snd_get_track_default_attr(&track_attr);
td_handle h_track = 0;
uapi_snd_create_track(&h_track, h_snd, &track_attr);
uapi_adp_attr adp_attr;
uapi_adp_get_def_attr(&adp_attr);
td_handle h_adp = 0;
uapi_adp_create(&h_adp, &adp_attr);
uapi_adp_attach_output(h_adp, h_track);
uapi_snd_track_start(h_track, TD_NULL);
while (task_active) {
uapi_audio_frame frame;
read_frame(&frame); /* 由应用实现,从文件或内存取得一帧 PCM。 */
if (uapi_adp_send_frame(h_adp, &frame) != EXT_SUCCESS) {
continue;
}
}
uapi_snd_track_stop(h_track);
uapi_adp_detach_output(h_adp, h_track);
uapi_adp_destroy(h_adp);
uapi_snd_destroy_track(h_track);
uapi_snd_close(h_snd);
uapi_snd_deinit();
uapi_adp_deinit();
预期能听到 PCM 内容;无声音时先执行 AT^AUDIO=sample_proc ao,再检查 PCM 格式、输出端口、Codec、PA 电源和音量。
PCM 采集与录制场景(AI)
功能说明:AI 从 ADC、PDM 或 I2S 输入端口采集 PCM 并保存为文件,用于验证 MIC、输入路由和采样参数。

实现流程:确认输入端口 → 初始化 AI/ADP → 配置 PCM 属性和增益 → 启动采集 → 写文件 → 停止 AI → 释放资源。
代码走读:参考 /src/application/audio/sample_ai/sample_ai.c。文件录制入口使用固定容量模型,参数为录制大小(MB)和输出文件;AI/AO 回环等实时入口也在该文件中实现。
| 流程步骤 | 关键函数 | 逐函数说明 |
|---|---|---|
| 解析和创建 | sample_ai_entry() |
解析录制容量和文件,分配实例并准备 PCM 属性。 |
| 准备下游 | sample_ai_open_file() |
创建 PCM 输出文件;文件失败时不启动 AI。 |
| 打开采集 | sample_ai_open_ai() |
填充 AI 端口和 PCM 属性,创建并启动 AI 输入。 |
| 建立处理实例 | sample_ai_open_inst() |
完成 ADP、AI 及可选 SEA 的资源打开。 |
| 启动与停止 | sample_ai_start_inst() / sample_ai_stop_inst() |
启动采集线程;停止 AI 后再关闭实例和文件。 |
录制结束后用相同的采样率、位宽和声道播放该文件。文件为空时检查 MIC 偏置、AI 端口、文件系统写权限和 Codec 输入路由。
实时回环场景(AI → ADP → SOUND)
功能说明:将 AI 采集到的 PCM 经 ADP 直接送入播放通路,是验证输入、缓冲适配和输出设备的最短链路。

实现流程:初始化 ADP、AI 和播放端 → 配置输入格式 → 创建并连接数据通路 → 同时启动采集与播放 → 发送 q 停止并按反向顺序释放。
代码走读:参考 /src/application/audio/sample_ai/sample_ai.c 的 sample_ai_ao()。该函数解析 -p/-c/-b/-s/-v 参数,并在内部完成 AI、ADP、SOUND 的实例建立和连接。
| 流程步骤 | 关键函数 | 逐函数说明 |
|---|---|---|
| 参数检查 | sample_ai_ao_parse_cmd_line() |
将端口、采样率、位宽、声道、音量及 Track 模式写入实例。 |
| 输出端准备 | sample_ai_player_open() |
创建播放侧对象和 SOUND Track,确定采集 PCM 的输出位置。 |
| 输入端准备 | sample_ai_open_adp() / sample_ai_open_ai() |
建立 ADP 与 AI,配置 AI 输入端口和 PCM 格式。 |
| 建链启动 | sample_ai_ao_start_inst() |
启动 AI 和播放链路,让 ADP 中的 PCM 持续流向 Track。 |
| 停止 | sample_ai_ao_exit() |
收到 q 后停止实例并反向释放 AI、ADP、播放器资源。 |
预期对 MIC 说话后扬声器实时输出声音。出现啸叫时先降低音量、拉开 MIC 与扬声器距离或改用耳机;这是声学反馈,不应通过改变 ADP 参数掩盖。
用户送帧编码场景(AENC)
编码协议与输入默认约束
AENC 接收前级模块或用户送入的 PCM,按所选编码器产生码流供文件、网络或远端解码使用。编码前必须先根据协议确定输入 PCM 属性;PCM 文件本身不携带格式信息,不能仅依据文件扩展名判断。
| 协议 | 通道数 | 支持的典型采样率(kHz) | 位宽(bit) | 使用说明 |
|---|---|---|---|---|
| SBC | 1 / 2 | 16 / 32 / 44.1 / 48 | 16 | 常用于音乐和蓝牙音频 |
| mSBC | 1 | 16 | 16 | 常用于窄带语音和通话 |
| OPUS | 1 / 2 | 8 / 12 / 16 / 24 / 48 | 16 | 常用于低时延语音/网络传输 |
| PCM | 1 / 2 | 8 / 16 / 32 / 44.1 / 48 | 16 / 32 | 用于透传或无压缩处理 |
| MP3 / AAC / FLAC | 以解码器能力为准 | 以解码器能力为准 | 以解码器能力为准 | 主要用于 ADEC 解码播放;是否可用受目标配置约束 |
说明: 语音编码通常采用 16 kHz / 16 bit / 单声道;若编码器属性、AI 输出和下游传输属性不一致,可能造成编码失败、变速或杂音。
功能说明:将应用已有的 PCM 文件、内存数据或其他算法输出编码为压缩码流,适用于本地存储、网络上行和蓝牙语音。

实现流程:选择编码格式 → 创建 AENC 并设置 PCM 属性 → 启动编码器 → 循环送入 PCM 帧、获取码流 → 停止并销毁编码器。
代码走读:参考 /src/application/audio/sample_encode/sample_encode.c。其核心参数顺序为 pcm_file codec sample_rate bit_depth channels;产品改为实时送帧时,仍需保持编码器属性与输入 PCM 属性一致。
| 流程步骤 | 关键函数 | 逐函数说明 |
|---|---|---|
| 配置参数 | sample_encode_parse_arg() / sample_encode_set_param() |
解析 PCM 和 codec 属性,设置码率、帧长等编码参数。 |
| 初始化 | sample_encode_sys_init() |
初始化 AENC 与 ADP 公共环境。 |
| 输入输出 ADP | sample_encode_open_adp_input() / sample_encode_open_adp_output() |
建立 PCM 输入和编码码流输出的 ADP 通道。 |
| 创建编码器 | sample_encode_open_aenc() |
填充 uapi_aenc_attr 并创建 AENC 实例。 |
| 送帧 | sample_encode_open_in_stream() / sample_encode_start_inst() |
打开 PCM 来源并启动实例,按帧向编码器输入 PCM。 |
| 清理 | sample_encode_stop_inst() / sample_encode_close_inst() |
停止数据流后依次关闭 AENC、ADP 和文件。 |
编码失败时优先检查 codec 名称及 PCM 的采样率、位宽、声道。部分语音编码格式只支持 16 kHz / 16 bit / 单声道。
实时采集编码场景(AI → AENC)
功能说明:实时采集 AI PCM,通过 ADP 送入 AENC,编码结果可写文件或发往下游,适用于压缩录音和语音上行。

实现流程:初始化 ADP、AI、AENC → 打开输出文件或下游播放器 → 创建输入实例 → 启动采集线程 → 获取码流 → 停止线程并反向释放。
代码走读:参考 /src/application/audio/sample_ai/sample_ai_aenc.c。该代码先打开文件、播放器和实例,再启动线程;这保证编码输出的去向在采集开始前已经就绪。
| 流程步骤 | 关键函数 | 逐函数说明 |
|---|---|---|
| 公共初始化 | sample_ai_aenc_sys_init() |
依次初始化 ADP、AI、可选 SEA 与 AENC。 |
| 建立对象 | sample_ai_aenc_open_adp()、sample_ai_aenc_open_ai()、sample_ai_aenc_open_aenc() |
创建 AI→ADP→AENC 的三个核心对象。 |
| 输出处理 | sample_ai_aenc_open_file() / sample_ai_aenc_proc_stream() |
有文件名时把编码码流写文件;无文件名时将码流送往下游播放器。 |
| 线程运行 | sample_ai_aenc_thread() |
循环从 ADP 获取流、处理码流并释放流。 |
| 启停 | sample_ai_aenc_start_inst() / sample_ai_aenc_exit() |
创建采集处理线程;q 触发停止、关闭对象和反初始化。 |
ret = sample_ai_aenc_open_file(inst);
ret = sample_ai_aenc_open_player(inst);
ret = sample_ai_aenc_open_inst(inst);
ret = sample_ai_aenc_start_inst(inst);
AT^AUDIO=sample_ai_aenc -p adc0 -c 1 -s 16000 -t opus -o /mnt/data/capture.opus
AT^AUDIO=sample_ai_aenc q
运行期间确认输出文件持续增长;若文件为空,依次查询 AT^AUDIO=sample_proc ai、adp、aenc,再检查端口和编码格式。
码流解码播放场景(ADEC)
功能说明:将 AAC、MP3、OPUS、SBC、mSBC 等压缩码流解码为 PCM,并交给 SOUND/AO 播放。

实现流程:确认码流格式 → 创建 ADEC 并设置属性 → 连接播放端 → 启动解码 → 输入码流、获取 PCM → 停止并销毁。
代码走读:参考 /src/application/audio/sample_decode/sample_adec.c。-i 指定文件或内存输入,-t 指定编码格式,-o play 表示解码后直接送入播放通路。
| 流程步骤 | 关键函数 | 逐函数说明 |
|---|---|---|
| 参数与数据源 | sample_adec_parse_cmd_line() / sample_adec_open_data_io() |
解析输入文件、codec 和输出方式,并初始化文件、内存或 ADP 数据 I/O。 |
| 公共初始化 | sample_adec_sys_init() |
初始化 ADEC 与 ADP 所需公共资源。 |
| 输入输出通道 | sample_adec_open_adp_in() / sample_adec_open_adp_out() |
输入端接收码流,输出端承接解码后的 PCM。 |
| 创建解码器 | sample_adec_attr_cfg() / sample_adec_open_adec() |
根据 codec 和 PCM 属性配置并创建 ADEC。 |
| 数据线程 | sample_adec_data_in_thread() / sample_adec_data_out_thread() |
分别持续送入码流、取出解码 PCM 并交给文件或播放 ADP。 |
| 启停 | sample_adec_start_inst() / sample_adec_exit() |
启动解码和数据线程;结束时先停线程再关闭 ADEC、ADP 与数据源。 |
无声音或解码失败时,先确认文件实际格式与 -t 一致;不要把容器文件、裸码流和 PCM 混用。
语音识别与通话场景(SEA / ASR)
功能说明:SEA 用于语音增强和算法引擎管理;ASR 处理 PCM 识别任务;通话场景按是否启用 SEA 和编码格式构建双向音频链路。

实现流程:初始化 ADP/AI → 按需初始化 SEA 并加载算法 → 初始化 AENC 或 ASR → 启动处理 → 获取结果或码流 → 卸载算法并反向释放。
代码走读:ASR 参考 /src/application/audio/sample_asr/sample_asr.c,SEA 场景参考 /src/application/audio/sample_sea/sample_sea.c,通话参考 /src/application/audio/sample_phone/sample_phone_apps.c。通话参数解析直接决定 SEA 和编码器属性:
| 流程步骤 | ASR 关键函数 | 通话关键函数 |
|---|---|---|
| 初始化 | sample_asr_sys_init():初始化 ADP、AI、可选 SEA 和识别环境 |
sample_phone_sys_init():初始化 ADP、AI、可选 SEA、AENC |
| 打开链路 | sample_asr_open_adp()、sample_asr_open_ai()、sample_asr_open_sea() |
sample_phone_open_adp()、sample_phone_open_ai()、sample_phone_open_sea()、sample_phone_open_aenc() |
| 处理 | sample_asr_thread():从 ADP 取帧并执行识别任务 |
sample_phone_start_inst():启动通话数据链路 |
| 释放 | sample_asr_exit():关闭实例、SEA、AI、ADP |
sample_phone_exit():停止实例并按反向顺序关闭所有对象 |
case 'm':
return sample_phone_sea_status(opt_arg, inst); /* sea / nosea */
case 't':
return sample_audio_get_acodec_id(opt_arg, &inst->acodec_id); /* pcm / msbc */
AT^AUDIO=sample_asr 1 /mnt/data/asr.pcm
AT^AUDIO=sample_phone -m sea -t msbc
AT^AUDIO=sample_phone q
ASR 依赖 NPU、模型和 CFG_SAP_ASR_SUPPORT;通话依赖板级双向音频能力。应查看识别/建链日志和 sample_proc sea、sample_proc aenc,不能仅根据 AT 返回值判断成功。
语音活动检测场景(VAD)
功能说明:VAD 判断静音、说话开始和结束,可用于按需录音、低功耗语音业务和减少上行数据。

实现流程:初始化 AI/ADP/SEA/AENC → 设置 VAD 处理参数 → 启动采集与处理线程 → 输出活动状态 → 发送 q 停止线程和释放实例。
代码走读:参考 /src/application/audio/sample_asr/sample_vad_feed.c。该代码使用单例保护同一时刻只有一个 VAD 实例;退出时显式停止线程、关闭实例和文件。
| 流程步骤 | 关键函数 | 逐函数说明 |
|---|---|---|
| 参数与状态 | sample_vad_feed_parse_cmd_line() / sample_vad_feed_set_proc() |
解析 AI 端口、PCM 属性和编码选项,设置 VAD 处理状态。 |
| 打开资源 | sample_vad_feed_open_adp()、sample_vad_feed_open_ai()、sample_vad_feed_open_sea()、sample_vad_feed_open_aenc() |
根据场景依次建立 AI、ADP、SEA、AENC。 |
| 活动检测 | sample_vad_feed_thread() / sample_vad_feed_nomal_proc() |
处理 ADP 流,按 VAD 状态缓存、编码或转存数据。 |
| 启停 | sample_vad_feed_start_inst() / sample_vad_feed_exit() |
启动线程;收到 q 后停止线程、关闭实例和文件。 |
if (strcmp(argv[1], "q") == 0) {
return sample_vad_feed_exit();
}
return sample_vad_feed_entry(argc, argv);
VAD 代码受 CFG_SAP_SMART_WATCH_PRODUCT 控制;若功能不可用,先确认产品配置和输入端口,再检查运行日志。
板级适配与高级能力(VENDOR / ANC / HAID)
VENDOR:参考 /src/application/audio/vendor。新增板卡应先完成 Codec 电源、时钟、引脚、MIC/PA 和 I2S 路由适配,再按“录制 → 回环 → 播放 → 编解码”验证。不要在业务代码中硬编码端口来规避板级配置问题。
ANC / HAID:分别由 sample_aha 和 sample_haid 代码提供场景参考,仅在 CFG_SAP_ANC_SUPPORT=y、CFG_SAP_HAID_SUPPORT=y 时纳入构建。它们还依赖耳机/助听硬件、算法参数和校准数据;未启用相应配置时不应将命令入口视为可用功能。
基于音频场景开发自己的应用
前面的 AT^AUDIO 用于运行和验证 SDK 已有场景。产品应用可使用 app_run 在系统启动时自动创建自己的任务,再在任务中按所选场景的流程调用音频接口。
app_run(func) 定义在 /src/middleware/utils/app_init/app_init.h,它将无参、无返回值的入口函数登记到启动段;系统启动时会统一调用已登记的应用入口。因此,app_run 负责何时启动应用,而 AI、ADP、SOUND、AENC 等接口负责如何建立音频业务。
开发步骤
- 选择与业务最接近的现有场景,例如播放使用
sample_ao.c,录制使用sample_ai.c,回环使用sample_ai_ao(),实时编码使用sample_ai_aenc.c。 - 在应用目录新增
audio_app.c、audio_app.h和CMakeLists.txt,将应用纳入目标组件列表。 - 在
audio_app_task()中按本指南对应场景的“初始化 → 打开设备 → 创建 ADP/Track/编解码器 → attach → start → 运行 → stop → destroy/deinit”顺序实现业务。 - 在
audio_app_entry()中创建任务,并用app_run(audio_app_entry)登记启动入口。 - 启动后通过串口日志和
AT^AUDIO=sample_proc <module>验证资源状态;不要让 app_run 入口直接执行长时间阻塞的音频循环。
文件结构
以下目录仅说明应用组织方式,名称可按产品工程调整:
/application/audio_app/
├── audio_app.c # app_run 入口和音频任务
├── audio_app.h # 应用配置和函数声明
└── CMakeLists.txt # 应用构建规则
app_run 入口代码
#include "app_init.h"
#include "osal.h"
#include "audio_app.h"
#define AUDIO_APP_TASK_STACK_SIZE 0x1000
#define AUDIO_APP_TASK_PRIO 26
static void audio_app_task(void *arg)
{
(void)arg;
/*
* 按所选场景实现:
* 1. 获取默认属性并设置板级端口/PCM 参数;
* 2. 初始化 SYS、ADP、AI/SOUND/AENC/ADEC;
* 3. 创建实例并 attach 下游;
* 4. start 后进入业务循环;
* 5. 退出时按反向顺序 stop、destroy、deinit。
*/
audio_app_start();
}
static void audio_app_entry(void)
{
osal_task *task = NULL;
osal_kthread_lock();
task = osal_kthread_create((osal_kthread_handler)audio_app_task, NULL,
"AudioAppTask", AUDIO_APP_TASK_STACK_SIZE);
if (task != NULL) {
osal_kthread_set_priority(task, AUDIO_APP_TASK_PRIO);
}
osal_kthread_unlock();
}
app_run(audio_app_entry);
代码说明: audio_app_entry() 只创建任务,避免启动框架被音频业务阻塞;audio_app_task() 承载完整音频生命周期;audio_app_start() 应由开发者按目标场景实现,不能直接照搬 AT 命令字符串。
CMakeLists.txt 示例
set(COMPONENT_NAME "audio_app")
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/audio_app.c
)
set(PRIVATE_HEADER
${ROOT_DIR}/middleware/utils/app_init
${ROOT_DIR}/application/audio
)
set(WHOLE_LINK true)
set(MAIN_COMPONENT false)
build_component()
将该组件加入目标构建配置后,检查链接脚本是否保留 app_run 段:acore.prelds 中需要包含 KEEP (*(SORT(.zinitcall.app_run*.init)))。3322 EVB 的文件路径为 acore.prelds。
验证要点
- app_run 应用在开机阶段执行,日志会与启动日志混合输出。
- 先用
AT^AUDIO验证端口、PCM 格式和场景流程,再启用 app_run 应用,便于区分应用问题和板级音频问题。 - 回环、录制、编码等实时业务必须提供退出条件;退出时按场景代码的反向顺序释放 AI、ADP、SOUND、AENC/ADEC 等资源。
注意事项
- 同一时间不要启动多个占用同一 AI、ADP、SOUND 或 AENC 资源的实时场景;先发送对应的
q停止命令。 - 使用
AT^AUDIO=sample_proc ai|adp|ao|sea|adec|aenc查询模块状态;必要时使用sample_dump抓取链路数据。 - PCM 的采样率、位宽和声道必须在 AI、ADP、AENC/ADEC、SOUND/AO 各端保持兼容。
- 路径必须位于目标系统已经挂载、且具备读写权限的文件系统;AT 参数以空格分隔,文件路径中不要包含空格。
sample_audio.c会在启动新场景前自动尝试停止已运行场景,但产品代码仍应显式管理资源生命周期。
常见编译与运行错误
| 现象 | 优先检查 |
|---|---|
AT^AUDIO 命令不可用 |
AT_COMMAND_AUDIO 是否纳入目标配置,串口是否连接到正确固件 |
| 没有声音 | PCM 格式、sample_proc ao、Codec/PA 电源、输出端口和音量 |
| 录音文件为空 | AI 端口、MIC 偏置、输入路由、文件系统写权限 |
already running |
上一个实时场景未发送 q,先停止对应场景 |
| ASR、VAD、ANC、HAID 不可用 | NPU/算法资源、CFG_SAP_ASR_SUPPORT、CFG_SAP_SMART_WATCH_PRODUCT、ANC/HAID 功能开关 |
| 编码或解码失败 | codec 名称、输入数据真实格式、采样率/位宽/声道及算法库 |