音频配置与提示音
本文档详细介绍 AC792N SDK(fw-AC792_SDK,分支 release/AC792N_SDK_V3)中音频配置与提示音相关的实现:数字音量通道体系(audio_dvol.h)、提示音播放接口(tone_player / bt_tone_player)、正弦波提示音合成(sine_make)、提示音数据在 Bank 中的存储管理,以及 TWS 提示音同步、空间音效模式切换提示音等配置项。
Purpose and Scope
本页覆盖"音频配置与提示音"这一完整能力的端到端实现,包括:
- 数字音量(Digital Volume)的多通道配置与淡入淡出机制(
sdk/audio/common/audio_dvol.h) - 提示音播放 API(
tone_play/tone_play_index/tone_stop)及其与蓝牙状态机的联动(BT_STATUS_TONE_BY_FILE_NAME) - 正弦波提示音合成器(
sdk/include_lib/media/sine_make.h) - 提示音数据在 Flash Bank 中的存放(
CONFIG_BANK_NUM_TONE) - 与提示音相关的应用层配置项(TWS 开机提示音同步、空间音效切换提示音开关)
以下主题属于相邻页面,不在本页展开:音频编解码器(AAC/SBC 等)细节、蓝牙协议栈 HFP 的 DTMF 信令(仅在 avctp_user.h 中引用)、麦克风/录音链路、音效 DSP 算法本身(变调变速 audio_pitch_speed_api.h 仅作为提示音处理的扩展点提及)。
Overview
在蓝牙音频设备(如本 SDK 中的 wifi_bbm、wifi_camera 等应用)中,"提示音"是用户与设备交互的重要反馈渠道:开机提示音、按键音、来电铃声、连接/断开提示音、TWS 同步提示音等。这些提示音通常是一段短小的 PCM 数据(可预先烧录在 Flash 的 Tone Bank 中,也可由正弦波合成器实时生成),通过数字音量(DVOL)通道混入主音频通路输出。
SDK 的设计将"音量控制"与"声音内容"解耦:
- 音量控制由
dvol_handle(数字音量句柄)统一管理,支持多路声音叠加时按通道独立设置音量、淡入淡出(fade)、静音与音量上限; - 声音内容由提示音播放器(
tone_player)或正弦波合成器(sine_make)产生,前者播放预置的音频文件,后者按参数(频率、点数、窗函数、衰减、增益)实时合成提示音。
两者通过公共音频通路(audio_dvol_run 处理 PCM 数据)衔接,形成一条从"事件触发 → 提示音数据源 → 数字音量 → 输出"的完整链路。
Architecture
flowchart TD
subgraph sg_Event["事件触发层"]
BT["蓝牙状态机<br/>BT_STATUS_TONE_BY_FILE_NAME"]
KEY["按键事件"]
TWS["TWS 同步事件"]
SPATIAL["空间音效模式切换<br/>audio_spatial_effects_mode_switch_tone_play"]
end
subgraph sg_TonePlayer["提示音播放层"]
TP["tone_player / bt_tone_player<br/>tone_play / tone_play_index / tone_stop"]
RING["ring_player<br/>来电铃声"]
end
subgraph sg_Source["提示音数据源"]
SINE["sine_make 正弦波合成器<br/>sin_tone_open / sin_tone_make"]
BANK["Tone Bank 存储<br/>CONFIG_BANK_NUM_TONE / __BANK_TONE_ENTRY"]
end
subgraph sg_DVOL["数字音量层"]
DVOL["dvol_handle 多通道音量<br/>MUSIC / CALL / TONE / RING / KEY_TONE / TTS / TWS / FLOW"]
FADE["淡入淡出控制<br/>fade_step / vol_target / vol_fade"]
MUTE["静音与音量上限<br/>mute_en / vol_limit / vol_max"]
end
subgraph sg_Out["输出层"]
DAC["DAC / 音频通路输出"]
end
BT -->|"按文件名播放"| TP
KEY --> TP
TWS --> TP
SPATIAL --> TP
TP --> SINE
TP --> BANK
SINE -->|"PCM 数据"| DVOL
BANK -->|"PCM 数据"| DVOL
DVOL --> FADE
DVOL --> MUTE
DVOL -->|"audio_dvol_run"| DAC
架构说明:
- 事件触发层是提示音的入口:蓝牙协议栈上报
BT_STATUS_TONE_BY_FILE_NAME(直接使用文件名播放提示音,见 avctp_user.h),应用层按键、TWS 同步、空间音效模式切换等事件也会触发播放。 - 提示音播放层封装了播放逻辑:
tone_play(const char *name)按文件名播放、tone_play_index(u8 index)按下标播放、tone_stop()停止播放;铃声播放由ring_player单独管理(两者在app_tone.h中一并引入)。 - 数据源层决定声音内容来自何处:实时合成(
sine_make)或预置存储(Tone Bank)。Tone Bank 通过bank_switch.h中的__BANK_TONE_ENTRY宏挂接到 Flash 分区,只有定义了CONFIG_BANK_NUM_TONE才启用独立 Tone Bank。 - 数字音量层是多路音频叠加时的关键仲裁点:8 个通道(MUSIC/CALL/TONE/RING/KEY_TONE/TTS/TWS/FLOW)各自拥有音量、淡入淡出步进和最大等级,
audio_dvol_run逐样本处理 PCM 数据。 - 输出层将混音结果送 DAC。整条链路中提示音只是"声音内容"的一种,与音乐、通话、TTS 共用同一数字音量框架,这正是本设计的核心意图:音量策略统一、声音内容可插拔。
数字音量通道体系(audio_dvol.h)
audio_dvol.h 是整个音频配置体系的基石,它定义了数字音量(Digital Volume)的分辨率、通道掩码、淡入淡出步进与最大音量等级,以及两个核心数据结构 audio_vol_params 与 dvol_handle。
全局音量参数
#define DVOL_RESOLUTION 14
#define DVOL_MAX 16384
#define DVOL_MAX_FLOAT 16384.0f
#define BG_DVOL_FADE_ENABLE 0 /*多路声音叠加,背景声音自动淡出小声*/
#define DIGITAL_VOLUME_LEVEL_MAX 200 //默认的音量等级限制设成200
来源:audio_dvol.h
DVOL_RESOLUTION为 14 位,DVOL_MAX为 16384,即数字音量的满刻度对应 2^14 个量化等级;DVOL_MAX_FLOAT是供浮点计算使用的同值常量。BG_DVOL_FADE_ENABLE默认为 0:多路声音叠加时,背景声音不会自动淡出。若置 1,dvol_handle中会额外维护vol_bk(后台自动淡出前音量值)与entry(链表节点),用于实现"提示音/通话声打断时背景音自动让位"的效果。DIGITAL_VOLUME_LEVEL_MAX为 200,是默认的音量等级上限,应用层可据此映射 0~200 的 UI 音量刻度。
通道掩码:声音类型的仲裁基础
/*Digital Volume Channel*/
#define MUSIC_DVOL 0b00001
#define CALL_DVOL 0b00010
#define TONE_DVOL 0b00100
#define RING_DVOL 0b01000
#define KEY_TONE_DVOL 0b10000
#define TTS_DVOL 0b100000
#define TWS_TONE_DVOL 0b1000000
#define FLOW_DVOL 0b10000000
/*Digital Volume Fade Step*/
#define MUSIC_DVOL_FS 2
#define CALL_DVOL_FS 4
#define TONE_DVOL_FS 30
/*Digital Volume Max Level*/
#define MUSIC_DVOL_MAX 16
#define CALL_DVOL_MAX 15
#define TONE_DVOL_MAX 16
来源:audio_dvol.h
设计意图解读:
- 每个通道使用独立的 bit 位(
0b00001~0b10000000),意味着这些掩码可以按位组合,用于表示"这路声音属于哪些类型"或在多路混音时按类型仲裁优先级。 - 通道划分体现了声音的业务语义:音乐(MUSIC)、通话(CALL)、系统提示音(TONE)、来电铃声(RING)、按键音(KEY_TONE)、语音合成(TTS)、TWS 对耳提示音(TWS_TONE)、流水/渐变提示音(FLOW)。不同业务的声音可以同时存在(如音乐 + 提示音),各自独立控制音量。
- 淡入淡出步进(Fade Step)是各通道音量的"变化速度":MUSIC 为 2(缓慢渐入渐出,避免音乐突兀)、CALL 为 4、TONE 为 30(提示音短促,需要快速完成淡入淡出,否则听感拖沓)。这是典型的"按业务特性调参"的设计。
- 最大等级(Max Level)限制每类声音能达到的最大音量:TONE 为 16,比 MUSIC(16)相同、比 CALL(15)高,保证提示音在混音中可被清晰听见。
数据结构:audio_vol_params 与 dvol_handle
struct audio_vol_params {
u16 vol;
u16 vol_max;
u16 fade_step;
s16 vol_limit;
u8 bit_wide;
};
typedef struct {
u8 toggle; /*数字音量开关*/
u8 fade; /*淡入淡出标志*/
u16 vol; /*淡入淡出当前音量(level)*/
u16 vol_max; /*淡入淡出最大音量(level)*/
s16 vol_limit; /*最大数字音量限制*/
s16 vol_fade; /*淡入淡出对应的起始音量*/
#if BG_DVOL_FADE_ENABLE
s16 vol_bk; /*后台自动淡出前音量值*/
struct list_head entry;
#endif/*BG_DVOL_FADE_ENABLE*/
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
volatile u16 fade_step; /*淡入淡出的步进*/
float cfg_vol_min; /*最小音量的分贝数*/
float cfg_vol_max; /*最小音量的分贝数*/
u16 cfg_level_max; /*最大音量等级*/
u8 vol_table_custom; /*是否使用外部工具读取的音量表*/
u8 vol_table_default; /*是否使用默认的音量表*/
u8 mute_en; /*是否将数据设成0*/
u8 bit_wide; /*数据位宽*/
float *vol_table; /*自定义音量表*/
} dvol_handle;
来源:audio_dvol.h
audio_vol_params是打开数字音量通道时的入参:初始音量、最大音量、淡入淡出步进、音量上限与数据位宽。dvol_handle是运行期句柄:vol/vol_target/vol_fade构成淡入淡出状态机(起始音量 → 逐 tick 步进 → 目标音量),fade_step与vol_target用volatile修饰,说明它们会在中断/多任务上下文中被并发读写。- 音量表机制:
vol_table_custom与vol_table_default两个标志配合vol_table指针,支持"使用外部工具读取的音量表"或"默认音量表"两种曲线,用于把线性音量等级映射为符合人耳感知的对数分贝曲线。 mute_en为 1 时audio_dvol_run直接输出 0,实现瞬时静音;bit_wide决定数据处理时的位宽(16/24/32 bit)。
数字音量 API 一览
int audio_digital_vol_init(u16 *vol_table, u16 vol_max);
void audio_digital_vol_bg_fade(u8 fade_out);
dvol_handle *audio_digital_vol_open(struct audio_vol_params *params);
void audio_digital_vol_close(dvol_handle *dvol);
void audio_digital_vol_set(dvol_handle *dvol, u16 vol);
void audio_digital_vol_mute_set(dvol_handle *dvol, u8 mute_en);
int audio_digital_vol_run(dvol_handle *dvol, void *data, u32 len);
void audio_digital_vol_reset_fade(dvol_handle *dvol);
来源:audio_dvol.h
典型生命周期:audio_digital_vol_init(全局初始化音量表)→ audio_digital_vol_open(为某路声音打开通道,返回句柄)→ 循环调用 audio_digital_vol_run(对 PCM 数据逐样本应用音量)→ 需要变音时 audio_digital_vol_set / audio_digital_vol_reset_fade → 结束后 audio_digital_vol_close。audio_digital_vol_bg_fade 在 BG_DVOL_FADE_ENABLE=1 时用于让背景声音整体淡出。
提示音播放接口与触发流程
提示音的播放入口位于应用层:app_tone.h 统一引入 tone_player.h 与 ring_player.h(见 wifi_bbm/include/app_tone.h 与 wifi_camera/include/app_tone.h),而 bt_tone_player.h 给出了播放器的核心接口:
void tone_stop();
int tone_play(const char *name);
int tone_play_index(u8 index);
tone_play(const char *name):按文件名播放提示音,例如tone_play("power_on.mp3")。这一接口与蓝牙状态机上报的BT_STATUS_TONE_BY_FILE_NAME事件一一对应——协议栈侧直接给出文件名,播放器按名查找并播放,省去"事件→编号→文件"的映射表。tone_play_index(u8 index):按下标播放,适用于预置提示音表(tone table)的场景,播放器内部按下标查表得到文件。tone_stop():停止当前提示音。由于提示音通常有严格时序(如开机音播完才初始化 TWS),停止接口必须可被抢占式调用。
蓝牙状态事件与提示音的联动
在蓝牙协议栈的用户事件定义中:
BT_STATUS_TONE_BY_FILE_NAME, /*直接使用文件名播放提示音*/
来源:avctp_user.h
该事件与 BT_STATUS_INBAND_RINGTONE(来电铃声内录)、BT_STATUS_VOICE_RECOGNITION 等事件并列,说明提示音播放已经内建到蓝牙状态机的事件分发机制中:协议栈在连接成功、断开、来电等状态跳转时主动上报文件名,应用层只需在事件回调中调用 tone_play 即可,无需自行判断状态。
TWS 提示音同步
#define TCFG_TWS_INIT_AFTER_POWERON_TONE_PLAY_END 1 //tws播完开机提示音再初始化,处理提示音不同步问题
当 TCFG_TWS_INIT_AFTER_POWERON_TONE_PLAY_END 置 1 时,TWS(真无线对耳)的初始化被推迟到开机提示音播放完毕之后。设计意图:左右耳若在开机音播放中途各自初始化 TWS 链路,会造成两耳提示音不同步;先播完提示音再初始化,可保证双耳提示音节奏一致。这是提示音时序与系统初始化顺序耦合的典型配置。
正弦波提示音合成(sine_make)
对于不需要预置音频文件的场景(如按键音、低电提示音),SDK 提供实时正弦波合成器,接口定义在 sine_make.h:
#define DEFAULT_SINE_SAMPLE_RATE 16000
#define SINE_TOTAL_VOLUME 26843546//16106128//20132660 //26843546
struct sin_param {
//int idx_increment;
int freq;
int points;
int win;
int decay;
float gain; // 0到-90dB
};
int sin_tone_make(void *_maker, void *data, int len);
void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat);
int sin_tone_points(void *_maker);
void sin_tone_close(void *_maker);
void sin_pcm_fill(void *buf, u32 len, u32 fs);
void sweepsin_pcm_fill(void *buf, u32 len);
来源:sine_make.h
sin_param定义单音参数:freq频率(Hz)、points采样点数、win窗函数类型(用于平滑首尾、抑制频谱泄漏)、decay衰减(使音色自然收尾)、gain增益(0 ~ -90 dB)。sin_tone_open(param, num, channel, repeat):创建合成器实例。num为音调个数(可连续合成多个频率构成旋律/和弦),channel为声道数,repeat是否循环播放。sin_tone_make:每次调用填充len字节的 PCM 数据到data缓冲区,供数字音量层处理。sin_tone_points:返回当前合成的总点数,用于上层判断播放进度;sin_tone_close释放句柄。- 默认采样率为 16000 Hz;
SINE_TOTAL_VOLUME为 28 位满幅量化值(注释中保留了多次调参痕迹:16106128 → 20132660 → 26843546),说明该常量经历过响度校准。
与数字音量的衔接:sin_tone_make 产出的 PCM 数据与 Tone Bank 播出的 PCM 数据走同一条通路——先进入对应通道的 dvol_handle,经 audio_dvol_run 应用音量与淡入淡出后再输出。因此合成提示音同样受 TONE_DVOL 通道的步进(30)与最大等级(16)约束,保证与预置提示音听感一致。
提示音数据存储(Tone Bank)
预置提示音(开机音、配对音等音频文件)通过 Bank 机制存放在 Flash 中,由 bank_switch.h 统一管理:
#ifdef CONFIG_BANK_NUM_TONE
#define __BANK_TONE_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_TONE)
#define __BANK_TONE __BANK_NUM(CONFIG_BANK_NUM_TONE)
#else
#define __BANK_TONE_ENTRY
#define __BANK_TONE
#endif
- 当定义了
CONFIG_BANK_NUM_TONE时,编译器为提示音分配独立的 Flash Bank 编号,__BANK_TONE_ENTRY声明该 Bank 的入口(entry),__BANK_TONE提供 Bank 号访问宏;未定义时两者为空,提示音资源回退到普通代码段/资源段。 - 设计意图:把提示音数据独立成 Bank 可以在运行时按需切换/加载(Bank Switch 机制),减少常驻内存占用;同时便于通过工具单独烧录/升级提示音资源,无需重刷整个固件。
空间音效模式切换提示音
在空间音效(Spatial Effect)处理模块中,模式切换是否播放打断提示音由宏控制:
#define SPATIAL_AUDIO_EFFECT_SW_TONE_PLAY 0
配套接口为 audio_spatial_effects_mode_switch_tone_play(enum SPATIAL_EFX_MODE mode)。当宏置 1 时,切换空间音效模式(如标准 → 音乐厅 → 影院)会先播放一段打断提示音,同时重开数据流;置 0(默认)则静默切换。该配置体现了提示音策略的"可裁剪"特性——不同产品对提示音数量的要求差异很大,宏开关让开发者按需取舍。
核心流程:一次提示音播放的完整链路
sequenceDiagram
participant App as 应用/协议栈事件
participant TP as tone_player<br/>(tone_play / tone_play_index)
participant SRC as 数据源<br/>(Tone Bank / sine_make)
participant DVOL as dvol_handle<br/>(TONE_DVOL 通道)
participant DAC as 音频输出
App->>TP: 事件触发(BT_STATUS_TONE_BY_FILE_NAME / 按键 / TWS)
TP->>TP: 解析文件名或下标,查找提示音资源
TP->>SRC: 打开数据源(读 Bank 文件或 sin_tone_open)
SRC-->>TP: 返回数据句柄 / 合成器句柄
loop 每帧数据
TP->>SRC: 请求 PCM 数据(sin_tone_make / 文件读取)
SRC-->>DVOL: PCM buffer
DVOL->>DVOL: audio_dvol_run 应用音量/淡入淡出/mute
DVOL->>DAC: 混音后输出
end
App->>TP: 播放结束或被抢占(tone_stop)
TP->>SRC: 关闭数据源(sin_tone_close)
TP-->>App: 返回(tone_play 返回值 0/负错误码)
流程要点:
- 触发源多样化但入口统一:蓝牙状态事件(按文件名)、应用按键、TWS 同步、空间音效模式切换都收敛到
tone_play/tone_play_index。 - 数据源二选一:预置文件从 Tone Bank 读取,合成音由
sine_make实时生成;两者最终都产出标准 PCM。 - 数字音量层逐帧处理:
audio_dvol_run是每帧必经路径,TONE_DVOL通道的fade_step=30使提示音快速到位,vol_limit限制其峰值。 - 生命周期管理:
tone_stop可随时抢占;TWS 场景下播放结束事件还参与系统初始化时序(TCFG_TWS_INIT_AFTER_POWERON_TONE_PLAY_END)。
Usage Examples
示例一:配置并打开一路提示音数字音量通道
以下代码展示了如何用 audio_vol_params 配置 TONE 通道并打开 dvol_handle(流程:设置初始音量/最大音量/步进/上限 → open → 逐帧 run → close):
struct audio_vol_params params = {
.vol = 0, /*初始音量,从 0 开始便于淡入*/
.vol_max = TONE_DVOL_MAX,/*最大等级 16*/
.fade_step = TONE_DVOL_FS, /*淡入淡出步进 30,提示音快速到位*/
.vol_limit = TONE_DVOL_MAX,/*音量上限*/
.bit_wide = 16, /*16bit PCM*/
};
dvol_handle *tone_dvol = audio_digital_vol_open(¶ms);
/* ... 每帧对提示音 PCM 调用 audio_dvol_run(tone_dvol, pcm, len) ... */
audio_digital_vol_close(tone_dvol);
来源:audio_dvol.h(
audio_vol_params定义)与 audio_dvol.h(API 声明)
说明:
TONE_DVOL_FS/TONE_DVOL_MAX分别对应淡入淡出步进 30 与最大等级 16,见 audio_dvol.h。
示例二:按文件名播放提示音(蓝牙事件场景)
蓝牙状态机上报 BT_STATUS_TONE_BY_FILE_NAME 后,应用直接以文件名播放:
int tone_play(const char *name); /*按文件名播放,如 "power_on.mp3"*/
int tone_play_index(u8 index); /*按下标播放预置提示音表*/
void tone_stop(); /*停止当前提示音*/
调用示例(示意,按协议栈回调事件驱动):
case BT_STATUS_TONE_BY_FILE_NAME: {
/*参数携带文件名,直接播放*/
tone_play(file_name);
break;
}
来源:avctp_user.h(事件定义)
示例三:实时合成正弦提示音
无需预置文件时,用 sine_make 按参数合成(如 880 Hz、带衰减、单声道、不循环的按键提示音):
struct sin_param param = {
.freq = 880, /*频率 Hz*/
.points = 3200, /*200ms @ 16kHz*/
.win = 1, /*加窗平滑*/
.decay = 8, /*衰减,自然收尾*/
.gain = -6.0f, /*增益 -6dB,0 到 -90dB*/
};
void *maker = sin_tone_open(¶m, 1, 1, 0); /*1 个音调、单声道、不循环*/
int pts = sin_tone_points(maker);
/* 循环填充 PCM:sin_tone_make(maker, buf, len) 后送入 TONE 通道 dvol */
sin_tone_close(maker);
来源:sine_make.h
Configuration Options
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
DVOL_RESOLUTION | 宏 (int) | 14 | 数字音量分辨率(位),满刻度 DVOL_MAX=16384 |
BG_DVOL_FADE_ENABLE | 宏 (int) | 0 | 多路声音叠加时背景音是否自动淡出(1 启用,启用后 dvol_handle 增加 vol_bk/链表字段) |
DIGITAL_VOLUME_LEVEL_MAX | 宏 (int) | 200 | 默认音量等级上限,UI 音量刻度基准 |
MUSIC_DVOL_FS / CALL_DVOL_FS / TONE_DVOL_FS | 宏 (int) | 2 / 4 / 30 | 音乐/通话/提示音通道淡入淡出步进 |
MUSIC_DVOL_MAX / CALL_DVOL_MAX / TONE_DVOL_MAX | 宏 (int) | 16 / 15 / 16 | 音乐/通话/提示音通道最大音量等级 |
DEFAULT_SINE_SAMPLE_RATE | 宏 (int) | 16000 | 正弦波合成默认采样率 |
SINE_TOTAL_VOLUME | 宏 (int) | 26843546 | 正弦波合成满幅音量(响度校准值) |
CONFIG_BANK_NUM_TONE | 宏 (int) | 未定义 | 定义后启用独立 Tone Bank(__BANK_TONE_ENTRY / __BANK_TONE) |
TCFG_TWS_INIT_AFTER_POWERON_TONE_PLAY_END | 宏 (int) | 1 | TWS 播完开机提示音后再初始化,避免双耳提示音不同步 |
SPATIAL_AUDIO_EFFECT_SW_TONE_PLAY | 宏 (int) | 0 | 空间音效模式切换时是否播放打断提示音 |
API Reference
int audio_digital_vol_init(u16 *vol_table, u16 vol_max)
初始化数字音量模块(设置全局音量表与最大等级)。
参数:
vol_table(u16*):音量查找表(可为自定义曲线),NULL 时使用默认表vol_max(u16):全局最大音量
返回: 0 成功;负值失败。
来源:audio_dvol.h
dvol_handle *audio_digital_vol_open(struct audio_vol_params *params)
打开一路数字音量通道,返回句柄。
参数:
params(audio_vol_params*):初始音量、最大音量、淡入淡出步进、音量上限、位宽
返回: dvol_handle*;失败返回 NULL。
来源:audio_dvol.h
void audio_digital_vol_set(dvol_handle *dvol, u16 vol)
设置目标音量,触发淡入淡出(从当前音量向 vol 以 fade_step 步进)。
参数:
dvol(dvol_handle*):通道句柄vol(u16):目标音量等级
int audio_digital_vol_run(dvol_handle *dvol, void *data, u32 len)
对 PCM 数据逐样本应用音量/淡入淡出/静音。
参数:
dvol(dvol_handle*):通道句柄data(void*):PCM 缓冲区(就地处理)len(u32):数据字节数
返回: 0 成功;负值失败(如句柄非法)。
来源:audio_dvol.h
void audio_digital_vol_mute_set(dvol_handle *dvol, u8 mute_en)
设置静音标志,mute_en=1 时输出全 0。
void audio_digital_vol_reset_fade(dvol_handle *dvol)
重置淡入淡出状态(重新从当前音量开始)。
void audio_digital_vol_bg_fade(u8 fade_out)
背景音整体淡出/淡入(需 BG_DVOL_FADE_ENABLE=1)。
来源:audio_dvol.h
int tone_play(const char *name) / int tone_play_index(u8 index) / void tone_stop()
提示音播放器接口:按文件名播放、按下标播放、停止播放。
返回: tone_play/tone_play_index 返回 0 成功、负值失败(资源未找到、播放器忙等)。
void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat) / int sin_tone_make(void *_maker, void *data, int len) / int sin_tone_points(void *_maker) / void sin_tone_close(void *_maker)
正弦波提示音合成器:创建(参数:音调参数数组、音调个数、声道数、是否循环)、填充 PCM、查询总点数、释放。
来源:sine_make.h
void audio_spatial_effects_mode_switch_tone_play(enum SPATIAL_EFX_MODE mode)
空间音效模式切换时播放提示音(由 SPATIAL_AUDIO_EFFECT_SW_TONE_PLAY 宏控制是否生效)。
失败模式、边界情况与并发
提示音资源缺失
tone_play/tone_play_index在文件名或下标对应的资源不存在时返回负值。由于提示音属于"尽力而为"的反馈机制,调用方通常忽略返回值,但不应当阻塞主流程——例如蓝牙状态事件回调中播放失败不应影响连接状态机推进。- 若
CONFIG_BANK_NUM_TONE未定义,__BANK_TONE_ENTRY与__BANK_TONE展开为空,依赖 Tone Bank 的提示音将回退到默认资源路径。症状:某些提示音无声但系统正常,需检查 Bank 配置与资源烧录是否匹配。
播放抢占与打断
- 提示音可被新的提示音抢占(
tone_stop+ 新tone_play)。设计上提示音是短促的反馈信号,不允许排队阻塞——新事件直接打断旧音。对时序敏感的场景(如 TWS 双耳开机音),通过TCFG_TWS_INIT_AFTER_POWERON_TONE_PLAY_END=1把初始化推迟到播放结束后,从根源上避免"播放中途被初始化流程打断"造成的不同步。 - 来电铃声走独立的
ring_player(app_tone.h中与tone_player并列引入),避免铃声与系统提示音互相抢占导致的听感冲突。
并发读写
dvol_handle中的vol_target与fade_step使用volatile修饰,说明音量设置(可能来自按键任务/UI 线程)与audio_dvol_run(音频中断/音频任务)存在跨上下文并发访问。音频通路中不应直接加锁(会引入延迟),volatile+ 单次写入/读取是此处采用的轻量同步策略。BG_DVOL_FADE_ENABLE=1时dvol_handle挂入链表(entry),多路背景音淡出由统一流程遍历处理;此时需保证链表操作与音频回调互斥。
音量边界
- 各通道有独立的
vol_limit与vol_max(如 TONE 上限 16、CALL 上限 15),audio_digital_vol_set传入超限值时会被钳制。淡入淡出状态机以vol_fade(起始)→vol_target(目标)为界,fade_step决定每 tick 变化量,vol越界会造成音量跳变,因此上层应始终通过 API 设置而非直接改结构体字段。
合成器参数边界
sin_param.gain取值范围 0 ~ -90 dB,超出范围的增益可能导致削波或听不见;freq过高(接近采样率 16 kHz 的奈奎斯特上限)会产生混叠失真。SINE_TOTAL_VOLUME是满幅量化常量,响度已校准,业务层不宜再放大。
性能与运维考量
- 逐样本处理的开销:
audio_dvol_run对每帧 PCM 逐样本应用音量/淡入淡出,是音频热路径。TONE_DVOL_FS=30意味着提示音在极短时间(约几十个 tick)内完成淡入淡出,减少处理时长;音乐通道步进 2 则保证平滑。修改这些宏会直接影响 CPU 占用与听感,需在性能与体验间权衡。 - 正弦波合成的开销:
sine_make实时合成比播放预置文件更省 Flash 但占 CPU。对低功耗场景,优先使用 Tone Bank 预置文件;对必须动态生成的声音(频率可变),使用合成器并注意sin_tone_close释放句柄,避免泄漏。 - Bank 切换:独立 Tone Bank(
CONFIG_BANK_NUM_TONE)允许按需加载提示音资源,减小常驻内存,但 Bank 切换本身有 Flash 访问延迟,不要在音频中断里触发 Bank 加载。 - TWS 时序:
TCFG_TWS_INIT_AFTER_POWERON_TONE_PLAY_END增加开机流程时延(等待提示音播完),但换取双耳同步;若产品对开机速度敏感,可评估关闭该配置并改用短提示音。
扩展点
- 新增提示音类型:在
audio_dvol.h的通道掩码中按 bit 递增扩展(当前已用 8 位),并在dvol_handle打开时使用新通道掩码;同时补充对应的*_DVOL_FS与*_DVOL_MAX宏以独立控制其淡入淡出速度与上限。 - 自定义音量表:通过
audio_digital_vol_init(vol_table, vol_max)传入对数曲线表,或设置dvol_handle.vol_table_custom/vol_table_default切换"外部工具读取的音量表"与"默认表",可适配不同喇叭/耳机的响度特性。 - 变调变速提示音:
audio_pitch_speed_api.h提供的audio_pitch_speed_set(char *node_name, float semi_tones, float speed)(半音符 -12~12、变速 >0.5)可作为提示音的后处理扩展,在同一节点链路上实现变调变速效果。 - 提示音开关裁剪:
SPATIAL_AUDIO_EFFECT_SW_TONE_PLAY等宏开关使不同产品线可以按需裁剪提示音数量;新增提示音时建议同样以宏开关控制,保持资源可裁剪。
测试与验证建议
仓库中的音效/音频模块头文件(如 audio_pitch_speed_api.h、spatial_effects_process.h)提供了可注入的接口,验证提示音链路时可关注:
- 播放回调完整性:
tone_play后数据源正确打开、audio_dvol_run每帧被调用、tone_stop后句柄释放; - 音量边界:对
TONE_DVOL通道反复 set 0 / 16 / 超限值,确认无越界与跳变; - 抢占行为:连续快速触发多个提示音,确认无崩溃、无内存泄漏;
- TWS 时序:验证
TCFG_TWS_INIT_AFTER_POWERON_TONE_PLAY_END=1时双耳提示音播放结束才进入 TWS 初始化; - 合成器参数:用
sin_tone_open全参数遍历(freq/points/win/decay/gain)跑稳定性测试,确认sin_tone_points与sin_tone_make输出一致。
Related Links
- 音频数字音量配置(audio_dvol.h)
- 正弦波提示音合成(sine_make.h)
- 提示音播放器接口(bt_tone_player.h)
- 蓝牙状态事件定义(avctp_user.h)
- Tone Bank 存储管理(bank_switch.h)
- 空间音效切换提示音开关(spatial_effects_process.h)
- 相关能力页:蓝牙音频链路、音频编解码器、变调变速音效(
audio_pitch_speed_api.h)等主题请参见对应目录页面。