音频编解码与音效
本页面介绍 AC792N SDK(分支 release/AC792N_SDK_V3)中音频子系统的编解码与音效能力:支持的解码/编码格式、编解码静态库、音频解码器公共 API(audio_decoder.h)、SBC 编解码接口,以及音效/音频算法(ANC、MIC 音效等)在系统中所处的位置与接入方式。
Purpose and Scope
本页面覆盖以下主题:
- 通用解码格式与自定义解码格式(F2A / WTG / MTY / WTS)的支持清单;
- 通用编码格式支持清单;
- 编解码库(
sdk/cpu/wl83/liba/media/*.a)与编解码头文件(sdk/include_lib/media/codec/); - 音频解码器公共 API:ioctl 命令、AB 点复读、指定位置播放、循环播放、断点保存/恢复等机制;
- 音效与音频算法层的整体结构(ANC、MIC 音效、audio_algo 配置)及其与编解码链路的关系。
以下内容属于兄弟页面、不在本页展开:DAC/ADC 硬件 API(见 SDK/audio_api 相关文档)、ANC 各功能项的具体调参(见 SDK/audio_config/ANC 文档)、蓝牙音频(A2DP/LE Audio)的具体协议流程。本页只从编解码与音效子系统整体架构的角度引用它们。
概述
音频子系统是 AC792N SDK 的核心能力之一,负责将存储介质或传输链路中的压缩音频数据还原为 PCM 输出到 DAC(解码方向),以及将 ADC 采集的 PCM 数据压缩为指定格式(编码方向),并在链路上叠加 ANC、MIC 音效等音频算法。
整个子系统由四层构成:
- 应用层:播放器、录音器、蓝牙音频(A2DP/LE Audio)等业务模块;
- 媒体 API 层:
audio_decoder(解码入口)与encoder_node(编码节点)向上层提供统一的打开/喂数据/控制/关闭接口; - 编解码库层:以静态库形式提供具体格式的编解码实现,例如
lib_jla_codec.a、lib_mp2_codec.a、lib_lc3_codec.a、lib_adpcm_codec.a、lib_msbc_codec.a、lib_speex_codec.a,以及以头文件形式暴露的 SBC 接口(sbc_codec.h); - 音效/算法层与硬件层:音频算法(ANC 降噪、MIC 音效)在 ADC/DAC 链路上处理 PCM,最终由 DAC/ADC 完成数模/模数转换。
设计的核心意图是:格式无关的解码器框架 + 可裁剪的库化编解码实现。上层业务只依赖 audio_decoder 的抽象接口,具体格式通过链接不同的编解码静态库来裁剪,这样同一套播放器代码可以同时支持 MP3、WAV、JLA、LC3 等格式,而无需感知底层差异;同时静态库裁剪方式有利于按产品 ROM 容量取舍编解码能力。
架构
flowchart TD
subgraph sg_App["应用层"]
Player["播放器 / 蓝牙音频"]
Recorder["录音器"]
end
subgraph sg_API["媒体 API 层"]
DecoderAPI["audio_decoder 解码 API"]
EncoderAPI["encoder_node 编码节点"]
end
subgraph sg_CodecLib["编解码库 (lib*.a)"]
JLA["JLA / MP2 / LC3 等"]
ADPCM["ADPCM / MSBC / SPEEX 等"]
SBC["SBC (sbc_codec.h)"]
end
subgraph sg_Effect["音效/算法层"]
ANC["ANC 降噪算法"]
MicEffect["MIC 音效"]
end
subgraph sg_HW["硬件层"]
DAC["DAC"]
ADC["ADC"]
end
Player -->|"打开/喂数据/ioctl"| DecoderAPI
Recorder -->|"编码请求"| EncoderAPI
DecoderAPI --> JLA
DecoderAPI --> ADPCM
DecoderAPI --> SBC
EncoderAPI --> ADPCM
DecoderAPI -->|"PCM 输出"| DAC
Recorder -->|"PCM 采集"| MicEffect
MicEffect --> ADC
Player --> ANC
架构说明:
- 解码方向:应用层(播放器或蓝牙音频)通过
audio_decoderAPI 打开指定格式的解码器,向解码器喂入压缩数据,解码器调用对应编解码库输出 PCM 帧,PCM 最终送 DAC。音效算法(如 ANC)在播放链路上对 PCM 做处理。 - 编码方向:录音器通过
encoder_node编码节点把 ADC 采集的 PCM(可先经 MIC 音效处理)编码为 MSBC/CVSD/ADPCM/OGG/AAC/SBC/JLA/LC3/SPEEX/PCM/AMR/OPUS 等格式。 - 库化裁剪:每种格式对应一个独立的静态库(如
lib_mp2_codec.a对应 MP2),产品固件通过链接哪些库来决定支持哪些格式,这是一种"链接期裁剪"的扩展点设计。 - 公共头文件:
sdk/include_lib/media/includes.h统一包含media/audio_decoder.h、media/mixer.h等媒体层头文件,是应用代码引用解码 API 的标准入口。
编解码格式总览
SDK 官方文档《编解码格式》集中列出了解码与编码两方向的格式支持清单,下文直接引用其内容并补充编解码库层面对应关系。
通用解码格式
| 序号 | 格式 | 备注 |
|---|---|---|
| 1 | WAV | |
| 2 | MP3 | |
| 3 | WMA | |
| 4 | FLAC | |
| 5 | APE | 仅支持 Fast/Normal 压缩等级 |
| 6 | AAC | |
| 7 | SBC | |
| 8 | M4A | |
| 9 | AMR | 8k 采样率 |
| 10 | AMR_16k | 16k 采样率 |
| 11 | DTS | |
| 12 | AIFF | |
| 13 | ALAC | |
| 14 | OGG_OPUS | |
| 15 | OGG_VORBIS | |
| 16 | CVSD | |
| 17 | MSBC | |
| 18 | JLA | |
| 19 | SPEEX | |
| 20 | LC3 | |
| 21 | MIDI_FILE | |
| 22 | MIDI_CTRL |
资料来源:codec.md.txt
自定义解码格式
自定义解码格式通常是为实现特定功能需求(如提示音)同时兼顾资源效率而定制开发的编解码算法:
| 序号 | 格式 | 备注 |
|---|---|---|
| 1 | F2A | |
| 2 | WTG | |
| 3 | MTY | |
| 4 | WTS |
资料来源:codec.md.txt
设计意图:通用格式面向内容分发(音乐、语音文件),自定义格式面向提示音/UI 音效等短音频场景——提示音文件由工具离线压缩为私有格式,解码器在线解压,占用极少 RAM/ROM,且无需支付第三方格式授权成本。
通用编码格式
| 序号 | 格式 | 备注 |
|---|---|---|
| 1 | MSBC | |
| 2 | CVSD | |
| 3 | MP3 | |
| 4 | ADPCM | |
| 5 | OGG | |
| 6 | AAC | |
| 7 | SBC | |
| 8 | JLA | |
| 9 | LC3 | |
| 10 | SPEEX | |
| 11 | PCM | |
| 12 | AMR | |
| 13 | AMR_16K | |
| 14 | OPUS |
资料来源:codec.md.txt
编码方向覆盖面与解码方向基本对称,并额外包含 PCM(无压缩直通)与 OPUS。MSBC/CVSD 主要用于蓝牙通话(免提协议),SBC/LC3 用于 A2DP/LE Audio 蓝牙音乐,ADPCM/OGG/AMR 用于录音与语音存储——格式选择与产品应用场景强相关,SDK 通过编解码库裁剪来满足不同产品需求。
编解码静态库
在 sdk/cpu/wl83/liba/media/ 目录下,每种格式对应一个或一组静态库:
| 库文件 | 对应能力 |
|---|---|
| lib_adpcm_codec.a | ADPCM 编解码 |
| lib_adpcm_ima_codec.a | ADPCM-IMA 编解码 |
| lib_jl_codec_common.a | 杰理编解码公共库 |
| lib_jla_codec.a / lib_jla_ll_codec.a / lib_jla_lw_codec.a / lib_jla_v2_codec.a | JLA 系列编解码(不同版本/复杂度) |
| lib_lc3_codec.a | LC3 编解码(LE Audio) |
| lib_mp2_codec.a | MP2 编解码 |
| lib_msbc_codec.a | mSBC 编解码(蓝牙通话) |
| lib_speex_codec.a | Speex 编解码(语音) |
资料来源:media 目录文件列表
JLA 提供多个变体库(lib_jla_codec.a、lib_jla_ll_codec.a、lib_jla_lw_codec.a、lib_jla_v2_codec.a),说明同一种格式按码率/复杂度拆分为多个实现,产品可按音质与资源预算选择链接版本——这是"库化裁剪"在格式内部的进一步细分。
音频解码器 API(audio_decoder.h)
audio_decoder.h 是解码链路对应用层暴露的公共接口头文件,位于 sdk/include_lib/media/audio_decoder.h,被 sdk/include_lib/media/includes.h 统一引用,因此应用代码通常只需包含 media/includes.h 即可获得解码 API 声明。
ioctl 控制命令
解码器提供统一的 ioctl 命令字,上层通过 audio_ioctrl 系列接口下发控制指令:
enum {
AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A = 0x08, // 设置复读A点
AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B, // 设置复读B点
AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE, // 设置AB点复读模式
AUDIO_IOCTRL_CMD_REPEAT_PLAY = 0x90, // 设置循环播放
AUDIO_IOCTRL_CMD_SET_DEST_PLAYPOS = 0x93, // 设置指定位置播放
AUDIO_IOCTRL_CMD_GET_PLAYPOS = 0x94, // 获取毫秒级时间
AUDIO_IOCTRL_CMD_GET_BREAKPOINT_AB = 0xA1, //获取断点信息用于保存
AUDIO_IOCTRL_CMD_RSET_BREAKPOINT_AB = 0xA2, //设置之前保存到的断点信息
AUDIO_IOCTRL_CMD_GET_BREAKPOINT_AB_SZIE = 0xA3, //获取保存断点信息需要buf大小
//固件自定义命令(非解码器命令)
AUDIO_IOCTRL_CMD_START_SILENCT_DROP = 0x1000,//开头静音数据丢弃处理
};
Source: audio_decoder.h
命令按功能域分组,具有明确的取值设计:
- 0x08~0x0A(复读域):AB 点复读相关——设置 A 点、设置 B 点、设置复读模式,用于复读机/语言学习等场景;
- 0x90~0x94(播放控制域):循环播放(0x90)、指定位置播放(0x93)、获取毫秒级播放位置(0x94);
- 0xA1~0xA3(断点域):获取/恢复断点信息及查询所需缓冲区大小,用于断电续播(记忆播放位置);
- 0x1000(固件自定义域):非解码器标准命令,用于丢弃开头静音数据,避免播放起始出现"噗"声。
域划分的意图:将第三方解码器(如 MP3/AAC 的授权解码库)需要处理的标准命令(0x08~0xA3 区间)与固件自定义命令(≥0x1000)隔离开,避免命令号冲突,也便于新增固件私有控制项而不改动解码器实现。
指定位置播放
指定位置播放参数结构体,支持"跳转到 start_time 播放,播放到 dest_time 后回调":
struct audio_dest_time_play_param {
u32 start_time; // 要跳转过去播放的起始时间。单位:ms
u32 dest_time; // 要跳转过去播放的目标时间。单位:ms
u32(*callback_func)(void *priv); // 到达目标时间后回调
void *callback_priv; // 回调参数
};
Source: audio_decoder.h
该机制常用于"试听片段""预览歌词段落"等功能:设置 start_time 与 dest_time 后,解码器按毫秒级时间戳跳转播放,到达目标时间时在解码线程上下文中调用 callback_func,上层可在回调中执行暂停、切歌等动作。回调携带 priv 参数,避免使用全局变量,便于多实例复用。
循环播放与帧裁剪
struct audio_repeat_mode_param {
int flag;
int headcut_frame;
int tailcut_frame;
int (*repeat_callback)(void *);
void *callback_priv;
struct fixphase_repair_obj *repair_buf;
};
Source: audio_decoder.h
循环播放支持"掐头去尾"帧裁剪(headcut_frame / tailcut_frame)和循环回调(repeat_callback)。fixphase_repair_obj 是相位修复缓冲区(short fifo_buf[18 + 12][32][2],见同文件第 44-46 行),用于在循环衔接处修复 PCM 相位跳变,避免循环点出现爆音/咔哒声——这是嵌入式音频循环播放的经典难点,SDK 以显式缓冲区结构暴露给调用方,由调用方负责分配内存、解码器负责填充使用。
断点结构
struct audio_dec_breakpoint {
int len;
u32 fptr;
int data_len;
u8 header[16];
u8 data[0];
};
Source: audio_decoder.h
断点信息包含文件指针偏移(fptr)、解码器内部状态数据(data[0] 柔性数组)与头部快照(header[16])。GET_BREAKPOINT_AB_SZIE 命令先查询所需缓冲大小,上层分配缓冲后由 GET_BREAKPOINT_AB 保存、RSET_BREAKPOINT_AB 恢复。设计意图是让"断点保存"对格式透明——MP3、JLA、WAV 的断点状态各不相同,但统一封装为"长度 + 文件偏移 + 私有数据"三元组,上层只需保存/恢复即可实现任意格式的续播。
核心流程
解码播放流程
sequenceDiagram
participant App as 应用(播放器)
participant Dec as audio_decoder 解码 API
participant Lib as 编解码库(lib_jla_codec.a 等)
participant DAC as DAC 输出
App->>Dec: 打开解码器(指定格式)
Dec->>Lib: 初始化解码器实例
Lib-->>Dec: 解码器句柄/上下文
loop 播放循环
App->>Dec: 喂入压缩数据
Dec->>Lib: 解码一帧
Lib-->>Dec: PCM 帧
Dec->>DAC: 输出 PCM(可经音效处理)
App->>Dec: ioctl 控制(播放位置/复读/循环)
end
App->>Dec: 关闭解码器
Dec->>Lib: 释放解码器资源
解码链路的时序要点:
- 应用按文件头/扩展名识别格式,调用
audio_decoder打开对应解码器; - 解码器内部绑定格式对应的静态库实现(链接期已确定),初始化上下文;
- 播放循环中应用持续喂入压缩数据,解码器逐帧输出 PCM;
- PCM 可先经音效/算法层(如 ANC)处理再送 DAC;
- 播放控制(位置、复读、循环、断点)统一走 ioctl 命令,格式差异被封装在解码器内部;
- 播放结束关闭解码器,释放资源。
编码流程
编码方向由 encoder_node 编码节点承载(详见文档 encoder_node.md.txt):录音器/蓝牙通话把 ADC 采集的 PCM 按目标格式(MSBC/CVSD/ADPCM/SBC/LC3/SPEEX 等)逐帧编码,输出码流写入存储或经蓝牙链路发送。编码与解码共享同一批编解码库,因此"库化裁剪"同时作用于两个方向。
使用示例
SBC 编解码接口
SBC 编解码器对外暴露的接口极简——单个函数即可获取音频帧数量,用于蓝牙 A2DP 接收侧按帧边界切分数据:
#ifndef __SBC_CODEC_H__
#define __SBC_CODEC_H__
#include "generic/typedef.h"
#include "string.h"
int sbc_audio_frame_num_get(u8 *data, u32 len);
#endif
Source: sbc_codec.h
data 为 SBC 码流缓冲,len 为缓冲长度,返回缓冲中包含的完整 SBC 帧数。A2DP 蓝牙音乐场景下,传输层按包交付数据,解码器需要先定位帧边界才能逐帧解码,此接口正是为此设计;其"以函数而非结构体暴露"的极简风格也说明 SBC 在 SDK 中属于底层传输型编解码,上层通常不直接调用,而是由蓝牙协议栈(a2dp_media_codec.h 等)间接使用。
解码控制命令的典型组合
以下代码摘自 audio_decoder.h 的命令枚举与结构体定义,展示了"指定位置播放 + AB 复读"两个典型控制模式的参数形状(audio_dest_time_play_param 与 audio_ab_repeat_mode_param):
struct audio_dest_time_play_param {
u32 start_time; // 要跳转过去播放的起始时间。单位:ms
u32 dest_time; // 要跳转过去播放的目标时间。单位:ms
u32(*callback_func)(void *priv); // 到达目标时间后回调
void *callback_priv; // 回调参数
};
struct audio_ab_repeat_mode_param {
u32 value;
};
Sources:
实际调用时,应用把上述结构体指针作为 ioctl 参数下发(命令分别为 AUDIO_IOCTRL_CMD_SET_DEST_PLAYPOS 与 AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE),解码器据此完成时间跳转与复读状态机切换。
媒体信息(ID3)解析支持
audio_decoder.h 还定义了 ID3 标签解析的输入/输出结构(media_info_set / media_info_data / id3_info),支持按字段位图选择性解析 TIT2/TPE1/TALB/TYER/TCON/COMM 等 ID3v2 帧,并提供"返回文件偏移地址"模式供外部解析标准 ID3v2。这使播放器无需自行扫描文件头即可获得标题、作者、专辑等元数据,且通过 item_limit_len 限制单字段长度,防止畸形标签撑爆内存。
配置选项
| 配置项 | 类型 | 默认值/范围 | 说明 |
|---|---|---|---|
| 解码格式集合 | 链接期裁剪 | 由链接的 lib_*.a 决定 | 支持 WAV/MP3/WMA/FLAC/APE/AAC/SBC/M4A/AMR/DTS/AIFF/ALAC/OGG/CVSD/MSBC/JLA/SPEEX/LC3/MIDI 等 |
| 编码格式集合 | 链接期裁剪 | 由链接的 lib_*.a 决定 | 支持 MSBC/CVSD/MP3/ADPCM/OGG/AAC/SBC/JLA/LC3/SPEEX/PCM/AMR/OPUS 等 |
| 自定义解码格式 | 工具链离线生成 | F2A/WTG/MTY/WTS | 提示音等短音频的私有格式,兼顾资源效率 |
| APE 压缩等级 | 解码器约束 | 仅 Fast/Normal | 不支持 High 压缩等级 |
| AMR 采样率 | 解码器约束 | 8k / 16k | AMR 为 8k,AMR_16k 为 16k |
| 播放位置控制 | ioctl 命令 | ms 精度 | GET_PLAYPOS 获取毫秒级播放时间 |
| 断点续播 | ioctl 命令 | 需先查缓冲区大小 | GET_BREAKPOINT_AB_SZIE → GET_BREAKPOINT_AB / RSET_BREAKPOINT_AB |
| 开头静音丢弃 | ioctl 命令 | 可开关 | AUDIO_IOCTRL_CMD_START_SILENCT_DROP,避免起播爆音 |
格式清单资料来源:codec.md.txt
配置哲学:编解码侧的"配置"主要通过链接期裁剪而非运行时开关实现——不链接 lib_mp2_codec.a 就不支持 MP2,链接即使能。这避免了运行时格式表占用 ROM 与切换开销,代价是固件需要在编译期确定产品支持的格式全集;若需运行时动态加载格式,则属于扩展点范畴(见下文)。
API 参考
int sbc_audio_frame_num_get(u8 *data, u32 len)
SBC 码流帧计数接口。
参数:
data(u8*):SBC 码流缓冲指针;len(u32):缓冲长度。
返回: 缓冲中完整 SBC 帧的数量(int)。
说明: 用于 A2DP 接收链路按帧边界切分 SBC 数据。定义于 sbc_codec.h。
audio_decoder ioctl 命令
通过解码器 ioctl 通道下发的控制命令枚举(audio_decoder.h):
| 命令 | 值 | 说明 |
|---|---|---|
| AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A | 0x08 | 设置复读 A 点 |
| AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B | 0x09 | 设置复读 B 点 |
| AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE | 0x0A | 设置 AB 点复读模式 |
| AUDIO_IOCTRL_CMD_REPEAT_PLAY | 0x90 | 设置循环播放(参数为 audio_repeat_mode_param) |
| AUDIO_IOCTRL_CMD_SET_DEST_PLAYPOS | 0x93 | 指定位置播放(参数为 audio_dest_time_play_param) |
| AUDIO_IOCTRL_CMD_GET_PLAYPOS | 0x94 | 获取毫秒级播放位置 |
| AUDIO_IOCTRL_CMD_GET_BREAKPOINT_AB | 0xA1 | 获取断点信息用于保存(参数为 audio_dec_breakpoint) |
| AUDIO_IOCTRL_CMD_RSET_BREAKPOINT_AB | 0xA2 | 恢复之前保存的断点信息 |
| AUDIO_IOCTRL_CMD_GET_BREAKPOINT_AB_SZIE | 0xA3 | 获取保存断点信息所需缓冲大小 |
| AUDIO_IOCTRL_CMD_START_SILENCT_DROP | 0x1000 | 固件自定义:开头静音数据丢弃 |
关键结构体
struct audio_dest_time_play_param:指定位置播放参数(start_time/dest_time单位 ms,callback_func到达目标时间回调);struct audio_ab_repeat_mode_param:AB 复读模式参数(u32 value);struct audio_repeat_mode_param:循环播放参数(flag、headcut_frame/tailcut_frame帧裁剪、repeat_callback、repair_buf相位修复缓冲);struct audio_dec_breakpoint:断点信息(len/fptr/data_len/header[16]/data[0]);struct media_info_set/struct media_info_data/struct id3_info:ID3 标签解析输入输出结构。
音效与音频算法层
音效能力在 SDK 中与编解码同属音频子系统,但以独立的配置/API 文档组织,说明它们被设计为可独立裁剪的功能模块。
结构概览
flowchart TD
subgraph sg_Input["采集方向"]
ADC["ADC 采集 PCM"]
MicE["MIC 音效处理"]
end
subgraph sg_Output["播放方向"]
Anc["ANC 降噪"]
Dac["DAC 输出"]
end
subgraph sg_Cfg["算法配置"]
AlgoCfg["audio_algo_cfg 算法配置"]
AncCfg["ANC 配置(含 AntiSat/Ext/功能配置)"]
end
ADC --> MicE
MicE -->|"处理后的 PCM"| Encoder["编码节点/通话链路"]
Dac --> Anc
Anc -->|"降噪后 PCM"| Codec["解码器输出/播放"]
AlgoCfg --> MicE
AlgoCfg --> Anc
AncCfg --> Anc
要点说明:
- MIC 音效:位于采集方向,对 ADC 输入的 PCM 施加音效后再进入编码节点或通话链路,其 API 文档见 mic_effect.md.txt;
- 音频算法配置:
audio_algo_cfg是算法使能与参数配置的统称,文档见 audio_algo_cfg.md.txt; - ANC(主动降噪):配置面拆分为多项文档——主配置 ANC_cfg.md.txt、防饱和 ANC_AntiSat_cfg.md.txt、扩展 ANC_Ext_cfg.md.txt、功能 ANC_function_cfg.md.txt,具体调参属于 ANC 相关页面,本页不做展开。
设计意图:把"格式转换(编解码)"与"信号处理(音效/降噪)"分层解耦——解码器输出的 PCM 可以不经任何处理直接送 DAC,也可以插入 ANC;ADC 采集的 PCM 可以先经 MIC 音效再编码。这样的管道式设计使每个环节可独立裁剪、独立调试,符合嵌入式音频系统的资源约束与模块化要求。
失败模式、边界与并发
基于已核对的源码(audio_decoder.h)与格式文档(codec.md.txt),可归纳出以下失败模式与边界行为:
- 格式不支持:若固件未链接对应编解码库(如未链接
lib_lc3_codec.a却播放 LC3 文件),解码器打开会失败。这是链接期裁剪的直接后果,产品必须在编译期确认格式全集; - APE 高压缩等级:仅支持 Fast/Normal 压缩等级,High 等级文件无法解码——属于解码器约束,应在产品规格中提前限制;
- 断点续播的数据完整性:断点信息包含文件偏移与解码器私有状态,若文件内容在断点保存后被修改(如边录边播场景),恢复时可能定位错误;SDK 通过
GET_BREAKPOINT_AB_SZIE强制调用方先查询缓冲大小,减少内存越界风险; - 循环播放相位跳变:无相位修复时循环衔接点可能出现爆音,
audio_repeat_mode_param中的repair_buf(fixphase_repair_obj,short fifo_buf[18+12][32][2])即用于修复,调用方必须正确分配该缓冲; - 开头静音:部分码流头部含填充静音,直接播放会先出无声段,
AUDIO_IOCTRL_CMD_START_SILENCT_DROP用于丢弃; - ID3 标签健壮性:
media_info_set.item_limit_len限制单字段长度,防止畸形标签导致缓冲区溢出; - 并发注意:解码器通常在独立解码线程中运行,
callback_func(到达目标时间、循环回调)在解码线程上下文中被调用,上层在回调内执行耗时操作或直接操作播放状态时需注意线程安全;断点保存/恢复命令与播放主循环并发时,建议在暂停态执行。
性能与运营考虑
- 库化裁剪:编解码以静态库提供(
lib_jla_codec.a、lib_mp2_codec.a、lib_lc3_codec.a、lib_msbc_codec.a等),未链接的格式不占 ROM,是嵌入式资源控制的主要手段; - JLA 多版本库:
lib_jla_codec.a/lib_jla_ll_codec.a/lib_jla_lw_codec.a/lib_jla_v2_codec.a提供不同复杂度/码率的 JLA 实现,产品可权衡音质与 CPU/RAM 开销选择链接版本; - 自定义格式省资源:提示音使用 F2A/WTG/MTY/WTS 等私有格式,离线压缩 + 在线解压,运行时开销远低于通用格式;
- 毫秒级时间接口:
GET_PLAYPOS提供 ms 级位置,UI 进度条可直接使用,无需自行按码率估算; - 调试辅助:SDK 还提供音频调试与代码量统计文档(audio_debug.md.txt、audio_code_size.md.txt),用于排查解码异常与评估各格式库的 ROM 占用。
扩展点
- 新增格式:在
sdk/cpu/wl83/liba/media/下补充对应编解码静态库,并在sdk/include_lib/media/codec/下提供头文件(参考 sbc_codec.h 的极简风格),使解码器框架按新格式接入; - 固件自定义 ioctl 命令:命令值 ≥ 0x1000 为固件私有域(如
AUDIO_IOCTRL_CMD_START_SILENCT_DROP),可仿照此模式扩展私有控制而不与解码器标准命令冲突; - 音效/算法插入:在解码→DAC、ADC→编码的管道中插入 ANC、MIC 音效等处理节点,具体使能与参数通过
audio_algo_cfg及 ANC 系列配置文档控制; - 播放控制策略:AB 复读、指定位置播放(含回调)、循环播放(含帧裁剪与相位修复)均为可组合的 ioctl 能力,可自由组合成复读机、试听、单曲循环等产品功能。
相关链接
- 编解码格式清单:codec.md.txt
- 编码节点文档:encoder_node.md.txt
- 解码器公共头文件:audio_decoder.h
- 媒体层统一入口:includes.h
- SBC 编解码接口:sbc_codec.h
- 编解码静态库目录:sdk/cpu/wl83/liba/media
- MIC 音效 API:mic_effect.md.txt
- 音频算法配置:audio_algo_cfg.md.txt
- ANC 配置(兄弟页面):ANC_cfg.md.txt 等
- DAC/ADC API(兄弟页面):DAC_API.md.txt
说明:音效(ANC 调参、MIC 音效 API 细节)与蓝牙音频编解码链路属于兄弟页面主题,本页仅从子系统架构角度概述其位置与关系;编解码格式清单、
audio_decoder.h与sbc_codec.h的内容均已直接核对源码。