test(audiod): r1 P2-1/P2-2 — 补 rapid-toggle 回归用例 + BT 音量语义文档(实现零改动)

评审 r1 的 `p2-2items`,两项都是「缺用例 / 缺一句文档」,不改任何已交付行为。

P2-1(连续拖滑块/ramp 中途反向缺回归):
- test_vol_gain 新增 G4b:块长 100(< 512 斜坡)× 60 次 100↔10 反向,实测 59 次落在
  斜坡中段;断言增益全程 ∈ [q15(10)=4, 32768] 且从不放大、块内逐样本只朝目标单调走、
  相邻样本跳变 ≤64 LSB(硬跳变 ~16380)、停手后 cur=4/left=0/bump_left=0。
- test_audiod_host 新增 T20(daemon 侧等价集成用例):经 IPC 连发 60 次 vol,
  每次只喂 100 帧(400B),断言 60 次全 ACK、underrun/dropped=0、
  落盘 PCM 无硬跳变(max_delta 1020 = 正弦自身斜率)、尾部 RMS 1.49 比头部
  6376.58 低 72dB(10% 真的生效)。

P2-2(文档):vol_gain.h 顶部新增「App/SDK 侧契约」段:BT 下 set_volume 同样生效
(走软件增益 + 持久化),AVRCP 钉 127 只为耳机功放满量程而非「音量交给耳机」,
pct 只在 [0,100] 有意义(<=0 真静音、>100 按满量程截断),16bit 写路径的
量化下限说明;vol_gain_dac_att_reg 注释补 pct>100 行为。build_audiod.sh
头部补 M55 说明(必须一起编 vol_gain.c、旧 SDK 说法已过期)。

验证:test_audiod_host 134/134 PASS、test_vol_gain 36/36 PASS、test_bt_dev PASS;
mipsel 交叉编译 0 warning,产物 md5 6cef4c54a1cb8e0c55f4ad5b6c4a323e(与 r1 完全一致,
证明二进制未变)。
This commit is contained in:
AskaEth committed 2026-11-12 08:07:37 +08:00
1 parent e37c622597
commit 2c0ec2ba15
4 files changed
+151 -3

No files matched your search

+44
View File
@@ -177,6 +177,50 @@ int main(void)
vol_gain_ramp_apply(&c, (uint8_t *)sm, sizeof sm); /* 第二块:走完(跨块精确到点) */
check(c.cur_q15 == tgt && c.left == 0, "short ramp ends exactly at target (no overshoot)");
check(c.bump_left == 0, "no residual bump after ramp completes");
/* ---- G4b:连续拖滑块(rapid toggle)——块长 100 < 斜坡 512,目标中途反复反向 ----
* 真实场景是用户按住音量键/拖滑块,每块都改目标、大多数改动落在斜坡中段。
* 回归点(评审 P2-1):①每次从**当前** cur 重起斜坡,不许跳到位 ②增益全程在
* [q15(10)=4, 32768] 内(不出现 0 或放大)③逐样本增益只朝目标单调走、相邻样本
* 跳变 ≤64 LSB(硬跳变会是 ~16380)④停手后精确收敛到目标且无残留余额。 */
{
const int blk_n = 100; /* < VOL_GAIN_RAMP_SAMPLES:保证落在斜坡中段 */
const int toggles = 60;
int16_t blk[100];
for (int i = 0; i < blk_n; i++) blk[i] = 16384; /* 恒定幅度:输出差 = 增益差/2 */
int32_t lo = vol_gain_q15(10), hi = vol_gain_q15(100);
int midramp = 0, out_of_band = 0, maxdelta = 0, nonmono = 0;
vol_gain_ramp_snap(&c, 100);
for (int k = 0; k < toggles; k++) {
if (c.left > 0) midramp++; /* 上一次斜坡还没走完就被改目标 */
vol_gain_ramp_set(&c, (k & 1) ? 100 : 10, VOL_GAIN_RAMP_SAMPLES);
int32_t g_before = c.cur_q15;
for (int i = 0; i < blk_n; i++) blk[i] = 16384; /* 每块重铺原始信号 */
vol_gain_ramp_apply(&c, (uint8_t *)blk, sizeof blk);
if (c.cur_q15 < lo || c.cur_q15 > hi) out_of_band++;
/* 块内逐样本:只朝目标走(单调),且相邻样本差 ≤64 */
int up = c.tgt_q15 > g_before;
for (int i = 1; i < blk_n; i++) {
int d = blk[i] - blk[i - 1];
if (d < 0) d = -d;
if (d > maxdelta) maxdelta = d;
if (up ? (blk[i] < blk[i - 1]) : (blk[i] > blk[i - 1])) nonmono++;
if (blk[i] > 16384 || blk[i] < 0) out_of_band++; /* 不许放大/越界 */
}
}
check(midramp >= toggles - 2, "toggle storm actually lands mid-ramp (>=58/60)");
check(out_of_band == 0, "gain stays within [q15(10)=4, 32768] and never amplifies");
check(nonmono == 0, "each block moves monotonically toward its target (no zigzag)");
check(maxdelta <= 64, "rapid toggles: per-sample delta <= 64 LSB (hard jump ~16380)");
/* 停手:回到 10% 并推几块大缓冲,确认精确收敛、状态无残留 */
vol_gain_ramp_set(&c, 10, VOL_GAIN_RAMP_SAMPLES);
for (int i = 0; i < blk_n; i++) blk[i] = 16384;
for (int k = 0; k < 8; k++) vol_gain_ramp_apply(&c, (uint8_t *)blk, sizeof blk);
check(c.cur_q15 == vol_gain_q15(10) && c.cur_q15 == 4 && c.left == 0 && c.bump_left == 0,
"after toggle storm: cur=4 (q15 of 10%), left=0, bump_left=0");
printf(" (toggle storm: %d/60 mid-ramp reversals, max per-sample delta %d LSB)\n",
midramp, maxdelta);
}
}
/* ==== G5 稳态快路:vol=100 缓冲原样、vol=0 全 0 ==== */