feat(audiod): DAC 实时监控 — 数字域电平表(100ms窗口整数RMS/peak,deci-dBFS)+1s监控日志(TF audio_monitor_<bootts>.log,流停即停)+CLI monitor 电平条;STATE 补 rms/peak/lvlseq 键(ABI兼容)。宿主47/47,qemu+真机0.7.91 tone验证(1kHz 0.3幅:rms=-13.9 peak=-10.8dBFS,hwrate~44.1k健康)。audiod ab193a2b meow_audio 891ab264
This commit is contained in:
1 parent
70aec677ce
commit
9a4ea10c64
9 files changed
+377
-5
No files matched your search
@@ -479,6 +479,99 @@ int main(void)
|
||||
close(z7.fd);
|
||||
stop_audiod();
|
||||
|
||||
/* ---- T8:数字域电平表 + 全面监控日志(M2.97 DAC 实时监控)。
|
||||
* 已知幅度正弦(amp=0.3, 440Hz):理论 RMS=0.3/√2 → -13.5dBFS,peak=0.3 → -10.5dBFS。
|
||||
* audiod 电平表为整数近似(octave 线性插值,误差 ~0.5dB)→ 容差 ±2.5dB。
|
||||
* 监控日志:流活跃期主线程 1s 节拍写 /tmp/audio_monitor_<bootts>.log(宿主无卡降级)。 ---- */
|
||||
printf("[T8 level meter + monitor log]\n");
|
||||
unlink(TSOCK); unlink(TWAV);
|
||||
g_audiod_pid = start_audiod(); /* file sink */
|
||||
usleep(400000);
|
||||
struct cli m8;
|
||||
check(cli_connect(&m8) == 0, "connect M8");
|
||||
m_audio_open_ack_t ackM8;
|
||||
check(do_open(&m8, 44100, 2, AUDIO_FMT_S16, &ackM8) == 0 && ackM8.err == MEOW_OK, "open M8");
|
||||
/* 喂 ~270ms 的 440Hz/0.3 幅度正弦(>2 个 100ms 窗口) */
|
||||
for (int i = 0; i < 12; i++)
|
||||
do_write(&m8, pcm, (uint32_t)gen_sine(pcm, sizeof pcm, AUDIO_FMT_S16, 1000, 440, 44100));
|
||||
char q8[1024];
|
||||
check(do_query(&m8, q8, sizeof q8) == 0 && strstr(q8, "rms=") && strstr(q8, "peak="),
|
||||
"query exposes rms/peak keys");
|
||||
int rms8 = -990, pk8 = -990;
|
||||
for (int i = 0; i < 20; i++) { /* 最多 2s 等首个窗口结算(播放排空竞态护栏) */
|
||||
do_query(&m8, q8, sizeof q8);
|
||||
rms8 = atoi(strstr(q8, "rms=") + 4);
|
||||
pk8 = atoi(strstr(q8, "peak=") + 5);
|
||||
if (rms8 > -990) break;
|
||||
usleep(100000);
|
||||
}
|
||||
printf(" sine 0.3: rms=%d peak=%d (expect rms≈-135 peak≈-105 deci-dB)\n", rms8, pk8);
|
||||
check(rms8 >= -160 && rms8 <= -110, "sine RMS ≈ -13.5dBFS (±2.5dB)");
|
||||
check(pk8 >= -130 && pk8 <= -80, "sine peak ≈ -10.5dBFS (±2.5dB)");
|
||||
/* 静音 → 地板(轮询等窗口结算:窗口按块粒度对齐,消除播放排空时序竞态) */
|
||||
{
|
||||
uint8_t zeros[4096];
|
||||
memset(zeros, 0, sizeof zeros);
|
||||
for (int i = 0; i < 8; i++) do_write(&m8, zeros, sizeof zeros); /* ~186ms */
|
||||
int floor_ok = 0;
|
||||
for (int i = 0; i < 20; i++) { /* 最多 2s 等纯零窗口结算 */
|
||||
usleep(100000);
|
||||
do_query(&m8, q8, sizeof q8);
|
||||
rms8 = atoi(strstr(q8, "rms=") + 4);
|
||||
pk8 = atoi(strstr(q8, "peak=") + 5);
|
||||
if (rms8 <= -990 && pk8 <= -990) { floor_ok = 1; break; }
|
||||
}
|
||||
printf(" silence: rms=%d peak=%d\n", rms8, pk8);
|
||||
check(floor_ok, "silence -> -inf floor");
|
||||
}
|
||||
/* monitor CLI 冒烟(流仍活跃:输出含电平字段+电平条) */
|
||||
{
|
||||
unlink("/tmp/meow_mon_cli.out");
|
||||
pid_t mp = fork();
|
||||
if (mp == 0) {
|
||||
setenv("MEOW_AUDIO_SOCK", TSOCK, 1);
|
||||
int fd = open("/tmp/meow_mon_cli.out", O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd >= 0) { dup2(fd, 1); close(fd); }
|
||||
execl("./meow_audio_host", "meow_audio_host", "monitor", "2", (char *)0);
|
||||
_exit(127);
|
||||
}
|
||||
int mst = 0;
|
||||
waitpid(mp, &mst, 0);
|
||||
char mb[4096];
|
||||
int ml = 0;
|
||||
int fd = open("/tmp/meow_mon_cli.out", O_RDONLY);
|
||||
if (fd >= 0) { ml = (int)read(fd, mb, sizeof mb - 1); close(fd); if (ml > 0) mb[ml] = 0; }
|
||||
check(ml > 0 && strstr(mb, "rms=") && strstr(mb, "LIVE") && strchr(mb, '['),
|
||||
"monitor CLI prints live level bar");
|
||||
}
|
||||
/* 监控日志文件:活跃期应已写入(前面耗时已超 2 个 1s 节拍) */
|
||||
char bootts[64] = "";
|
||||
{
|
||||
int fd = open("/tmp/meow_bootts", O_RDONLY);
|
||||
if (fd >= 0) { ssize_t r = read(fd, bootts, 63); close(fd); if (r > 0) bootts[r] = 0; }
|
||||
}
|
||||
char monpath[160];
|
||||
snprintf(monpath, sizeof monpath, "/tmp/audio_monitor_%s.log", bootts);
|
||||
char monbuf[4096];
|
||||
int monlen = 0;
|
||||
{
|
||||
int fd = open(monpath, O_RDONLY);
|
||||
if (fd >= 0) { monlen = (int)read(fd, monbuf, sizeof monbuf - 1); close(fd); if (monlen > 0) monbuf[monlen] = 0; }
|
||||
}
|
||||
check(monlen > 0 && strstr(monbuf, "app=test") && strstr(monbuf, "rms=") &&
|
||||
strstr(monbuf, "hwrate=") && strstr(monbuf, "vol="),
|
||||
"monitor log file written while stream active");
|
||||
/* 流停止即停写 */
|
||||
do_ctrl(&m8, MSG_AUDIO_STOP, ackM8.stream_id);
|
||||
usleep(1400000);
|
||||
off_t msz1 = -1, msz2 = -1;
|
||||
{ int fd = open(monpath, O_RDONLY); if (fd >= 0) { msz1 = lseek(fd, 0, SEEK_END); close(fd); } }
|
||||
usleep(1400000);
|
||||
{ int fd = open(monpath, O_RDONLY); if (fd >= 0) { msz2 = lseek(fd, 0, SEEK_END); close(fd); } }
|
||||
check(msz1 >= 0 && msz1 == msz2, "monitor log stops when stream stops");
|
||||
close(m8.fd);
|
||||
stop_audiod();
|
||||
|
||||
printf("=== SUMMARY: pass=%d fail=%d ===\n", g_pass, g_fail);
|
||||
return g_fail ? 1 : 0;
|
||||
}
|
||||
Reference in new issue
Block a user