来源:
notes/documents/01_dg板卡X5_麦克风与耳机链路排查及录音回放程序.mddg 板卡 X5 麦克风与耳机链路排查及录音回放程序
日期:2026-09-20
设备:D-Robotics RDK X5(dg,root@10.71.48.154),Ubuntu 22.04,内核 6.1.83,8×aarch64,3 GB RAM
一句话结论
dg 上的麦克风和耳机硬件与驱动都是好的,卡点在别处:(1) 声卡 codec(ES8326)只支持 8k/16k/32k/48k,44.1k 会静默变调约 8.84%;(2) 环境音电平极低(语音峰值仅 -53.9 dBFS),容易误判成”麦克风没声音”。本次交付了一个 dg:/root/mic_loopback.py:采集 10 秒麦克风音频后用耳机回放,只用 arecord/aplay,无 pip 依赖。语音转写步骤因机器关机未完成,没有产出文本。
一、录音设备(硬件与驱动)
- 板卡:D-Robotics RDK X5(Horizon 系,内核里能看到
hobot_*驱动) - 声卡:ES8326 codec,挂在 i2c
7-0018,走 I2S0(320b0000.dw_i2s0) - 卡结构:单声卡
duplex-audio,唯一 PCM 节点hw:0,0,播放和录音共用同一个 PCM(duplex), 所以”边放边录”是可行的,但也意味着没有独立的第二路设备 - 麦克风:单只麦克风,录制数据左右声道完全相同(复制到双声道)
- 软件栈:PulseAudio 15.99.1 以
sunrise用户运行(不是 PipeWire 接管);/etc/asound.conf未定制 - DAPM 通路:
MIC1..MIC4 → ADC L/R、I2S IN ← Left/Right DAC、HPOL/HPOR ← LHPMIX/RHPMIX; 驱动里没有 Speaker widget,输出实际走耳机放大器HPOL/HPOR - 没有插孔检测:DT 无
hp-det-gpio、无 jack kcontrol、无对应 input device → 软件无法判断耳机有没有插上,只能靠耳朵
二、采样率:44.1k 会变调(重要)
| 采样率 | 结果 |
|---|---|
| 8000 / 16000 / 32000 / 48000 | 正常,无告警 |
| 22050 / 44100 | 能开流,但 dmesg 报 Clock coefficients do not match |
根因:MCLK 是固定值(时钟树 dsp_i2s0_mclk = 24545455 Hz,对应 24.576 MHz 档),而 ES8326 驱动
get_coeff(mclk, rate) 要求 MCLK 精确命中系数表。44100 的合法 MCLK 只有
2822400 / 5644800 / 11289600 / 22579200,24545455 一个都不匹配 → 返回 -EINVAL → 驱动
打印告警并跳过写 8 个时钟分频寄存器,codec 保留上一次(48000)的系数。
读回寄存器验证:48k 播放后 04=0xe0 05=0x00 06=0x00 07=0x2d 08=0x48 09=0x08 0x0a=0x1f 0x0b=0x1f,
正好是系数表里 {512, 48000, 24576000, ...} 那一行。
声学回环实测(喇叭放音 → 麦克风录回,测主峰频率):
| 播放采样率 | 录回主峰 | 说明 |
|---|---|---|
| 48000 | 440.0 Hz | 正确 |
| 44100 | 479.0 Hz | 440×48000/44100 = 478.9,升高约 8.84%(≈1.5 个半音) |
走 PulseAudio(aplay -D default)没有这个问题——PA 会把 44.1k 重采样到 48k,
44.1k 和 48k 素材回录都是准确的 440 Hz。只有绕开 PA 直接用 hw:0,0 喂 44.1k 才会中招。
开机时那几条 Clock coefficients do not match 是 PA 启动探测按 44100 开设备触发的,属噪声。
三、Mixer 关键设置与耳机音量
| 控件 | 原始值 | dB |
|---|---|---|
DAC Playback Volume |
151 | -20.0 |
HPL Playback Volume |
151 | -20.0 |
HPR Playback Volume |
191 | 0.0 |
SPKL/SPKR Playback Volume |
191 | 0.0 |
HPVol SPKVol Switch |
0 | HPVOL: HPL+HPL, SPKVOL: HPL+HPL |
ADC Capture Volume |
191/191 | 0.0 |
ADC PGA Volume |
0/0 | 0.0 |
ADC PGA Gain Volume |
8 | +24.0 |
两个坑:
DAC和HPL是同一个寄存器ES8326_DACL_VOL,改一个另一个跟着变。 排查过程中有一条命令被中断,把HPL/HPR设成了 0,结果DAC也一起变成 0, 整条输出通路静音(-95.5 dB)——后来按原值还原。HPVol SPKVol Switch= 0 时左右耳机音量都取HPL,HPR=191 实际上不生效, 所以耳机输出被压在 -20 dB。想要满幅需要把HPL提到 191(+20 dB)。
采集侧还有充足余量:ADC PGA 0→5(每级 6 dB,最多 +30 dB)、ADC PGA Gain 8→10(+6 dB)、
ADC Capture 191→255(+32 dB)。
四、麦克风体检
| 项目 | 结果 |
|---|---|
| 环境录音 10 s RMS | -44.9 dBFS |
| 底噪(60 s 的 10% 分位) | -65.7 dBFS |
| 直流偏置 | +1.1(可忽略) |
| 50 Hz / 100 Hz 工频干扰 | -98.5 / -89.5 dBFS(几乎没有,供电干净) |
| 起始瞬态 | 前约 20 个样本满刻度削波(录音起始爆音) |
| 拾音验证 | 播放 1 kHz 测试音,麦克风该频点 -67.8 → -52.5 dBFS(+15.3 dB) |
增益实验:把 ADC PGA 从 0 提到 5(+30 dB),整体电平 -47.3 → -17.1 dBFS(正好 +30 dB),
而 300–3400 Hz 的频谱平坦度只从 0.264 变到 0.226(几乎不变)——说明只是把同一份噪声放大了,
没有隐藏的语音被挖出来,当前噪声底是真实的。
五、人声判定:第一次判错了
我最初用”电平 + 频段能量”判断,得出”10 秒里没人说话”的结论,这是错的。 正确做法是看周期性。判据:短时自相关基频强度(40 ms 帧,lag 对应 70–350 Hz),> 0.3 视为浊音。
| 文件 | 浊音帧 | 基频 | 结论 |
|---|---|---|---|
mic_take.wav(第一次 10 s) |
11/40 = 28% | 零星 | 少量浊音 |
mic_take2.wav(第二次 10 s) |
33/40 = 82% | 85–160 Hz,不断起伏 | 确认有人在说话 |
窄带语谱图(FFT 1024 @ 8 kHz,7.8 Hz/bin)里 mic_take2.wav 低频段能看到清晰的谐波横条,
且横条随语调上下摆动,这是浊音(声带振动)的典型特征;mic_take.wav 只有零星几小段。
教训:低电平人声(峰值仅 -53.9 dBFS,只比底噪高 10–20 dB)不能靠电平阈值判断, 必须用周期性/谐波性判据,否则会误判成”只有底噪”。
另外一个对后续转写很关键的点:能量集中在 800 Hz 以下,1.5 kHz 以上很弱, 擦音/辅音基本丢失——这会明显拉低 ASR 准确率,是比增益更麻烦的问题。
六、录音回放程序
部署位置:dg:/root/mic_loopback.py(源码归档见文末)。默认录 10 秒,然后从声卡原样回放。
ssh dg python3 /root/mic_loopback.py # 录 10 秒再回放
ssh dg python3 /root/mic_loopback.py -d 5 # 录 5 秒
ssh dg python3 /root/mic_loopback.py -o /root/take.wav # 保留录音
ssh dg python3 /root/mic_loopback.py --no-play # 只录不放
设计要点:
- 采样率默认 48000;传
-r 44100会被拦截并自动改成 48000(避免静默变调) - 录音开头有约 20 个满刻度削波样本(起始爆音),回放前加 20 ms 淡入淡出压掉; 若瞬态之外还有削波会额外告警
- 电平低于 -55 dBFS 时提示”基本只有底噪”
- 只用
arecord/aplay,不依赖任何 pip 包
实测:3 秒冒烟 RMS -41.2 dBFS、10 秒正式 RMS -43.0 dBFS、10 秒(mic_take2.wav)RMS -45.3 dBFS,
三次都是退出码 0,回放正常。
七、语音转写:选型与未完成状态
目标是”麦克风实时语音转文字”。环境核查结果:
| 端点 | 状态 |
|---|---|
pypi.org / github.com / hf-mirror.com |
200 |
huggingface.co |
不通(000) |
alphacephei.com/vosk/models/ |
403 |
aarch64 可直接装的 wheel:faster-whisper 1.2.1、ctranslate2 4.8.2、onnxruntime 1.23.2、vosk 0.3.45。
当时选了 faster-whisper(模型走 hf-mirror.com),pip3 install faster-whisper 执行到一半机器关机,
没有产出任何转写文本。
选型上是走了弯路:本工作区已有一篇 notes/documents/01_dg板卡X5_语音转文字方案对比与转写结果.md,
里面实测过 Whisper-small 在这块板上中文更差(同一段音频精确率明显低于 paraformer)、
且 RTF 2.536(外推 2h35m 要 6.5 小时),明确排除了 Whisper 路线,
推荐的是 sherpa-onnx + paraformer-zh(large int8 + 标点,600 秒切片 decode 109.6s,RTF 0.183)。
这次选型没有先复用既有结论,下次应该先查知识库再动手。
后续要做转写,正确路径是:
- 用 sherpa-onnx paraformer-zh large int8 + CT-Transformer 标点模型做离线转写;
- 转写前先做增益归一化(这段素材语音峰值只有 -53.9 dBFS)和重采样到 16 kHz 单声道;
- 实时场景再单独评估延迟,paraformer 非流式模型要配 VAD 切片。
八、遗留与待办
dg已关机,pip3 install faster-whisper的结果没有取回- 麦克风灵敏度偏低:若要提升识别率,先把
ADC PGA Gain由 8 提到 10,或ADC PGA提到 2~3 - 44.1k 素材若要直接走
hw:0,0,必须先重采样到 48k - 耳机偏小声:建议把
HPL由 151 提到 191(+20 dB);本次测试临时提过,已还原为 151 - 素材本身缺高频(>1.5 kHz 很弱),是转写准确率的主要物理限制
九、产物清单
- 程序源码:
notes/sources/dg_audio_loopback/mic_loopback.py(部署于dg:/root/mic_loopback.py) - 分析脚本:
notes/sources/dg_audio_loopback/inspect_capture.py(波形/频谱/频段能量/调制分析)、notes/sources/dg_audio_loopback/voiced_speech_check.py(窄带语谱图 + 自相关基频检测) - 测量明细:
notes/sources/dg_audio_loopback/measurements.md - 录音样本:
notes/sources/dg_audio_loopback/mic_take.wav、mic_take2.wav(各 10 秒 / 48 kHz / 立体声) - 图表:
notes/sources/dg_audio_loopback/spectrogram_mic_take2.png(宽带语谱图+电平条)、narrowband_mic_take.png、narrowband_mic_take2.png(窄带语谱图+浊音判定条)