Files
edgevoid 68db84a10c 初始化: 耳机电影院空间音频(PipeWire filter-chain + SADIE-II HRTF)
- 两个虚拟声卡: 5.1 直通版 / 立体声矩阵上混版
- 全链路 96kHz/24bit, SADIE-II 真人 HRTF 96K/512tap
- 命令: 空间音频(开关) / mpv-影院(单程序)
- deb 打包 + 验收测试脚本
- README 记录 9 个实测踩坑(增益校准/采样率/相位等)
2026-09-12 23:52:43 +08:00

62 lines
2.7 KiB
Bash

#!/bin/bash
# 电影院空间音频 demo v2 (2026-09-12)
# v1 教训: join+adelay 链没生效却因为 -loglevel error 看不出来, 交付了个假货。
# v2 换 aevalsrc 直接合成 6 声道, 且每一步都用能量分析验证。
set -eu
cd "/home/lou/桌面/工作区/实验/空间音频"
SOFA=/usr/share/libmysofa/MIT_KEMAR_normal_pinna.sofa
echo "===== 1. 造 5.1 素材: 6 个方向依次响(每声道一个频率) ====="
echo " FL 440Hz | FR 554Hz | FC 659Hz | LFE 80Hz | BL 880Hz | BR 1046Hz"
ffmpeg -y -hide_banner -loglevel warning \
-f lavfi -i "aevalsrc='0.6*sin(2*PI*440*t)*between(t,0,0.25)|0.6*sin(2*PI*554*t)*between(t,0.45,0.70)|0.6*sin(2*PI*659*t)*between(t,0.90,1.15)|0.6*sin(2*PI*80*t)*between(t,1.35,1.60)|0.6*sin(2*PI*880*t)*between(t,1.80,2.05)|0.6*sin(2*PI*1046*t)*between(t,2.25,2.50)':d=2.6:s=48000:c=5.1" \
-c:a pcm_s16le 51-test.wav
echo
echo "===== 2. 验证素材: 每 1/4 秒应该只有一个声道有能量 ====="
python3 - <<'PY'
import struct, wave
with wave.open("51-test.wav") as w:
ch, n = w.getnchannels(), w.getnframes()
raw = w.readframes(n)
s = struct.unpack("<%dh" % (len(raw) // 2), raw)
print(" 声道数 %d, 时长 %.2fs" % (ch, len(s) / ch / 48000))
seg = 48000 // 4
names = ["FL", "FR", "FC", "LFE", "BL", "BR"]
for k in range(ch):
c = [float(s[i * ch + k]) for i in range(len(s) // ch)]
blocks = ["%8.0f" % (sum(x * x for x in c[b:b + seg]) ** 0.5) for b in range(0, len(c), seg)]
print(" %-4s %s" % (names[k], " ".join(blocks)))
PY
echo
echo "===== 3. A 版: 普通下混(平时耳机听 5.1) ====="
ffmpeg -y -hide_banner -loglevel warning -i 51-test.wav -ac 2 -c:a pcm_s16le "A-普通下混.wav"
echo "===== 4. B 版: HRTF 双耳渲染(电影院包围感, gain=10 补回卷积摊掉的响度) ====="
ffmpeg -y -hide_banner -loglevel warning -i 51-test.wav \
-af "sofalizer=sofa=$SOFA:type=freq:radius=1.2:gain=10" -c:a pcm_s16le "B-HRTF环绕.wav"
echo
echo "===== 5. 双耳指标: 各段 L/R 能量比 ====="
python3 - <<'PY'
import struct, wave
for f in ("A-普通下混.wav", "B-HRTF环绕.wav"):
with wave.open(f) as w:
ch, n = w.getnchannels(), w.getnframes()
raw = w.readframes(n)
s = struct.unpack("<%dh" % (len(raw) // 2), raw)
left = [float(s[i * 2]) for i in range(len(s) // 2)]
right = [float(s[i * 2 + 1]) for i in range(len(s) // 2)]
seg = 48000 // 4
out = []
for b in range(0, len(left), seg):
el = sum(x * x for x in left[b:b + seg]) ** 0.5
er = sum(x * x for x in right[b:b + seg]) ** 0.5
out.append("%5.2f" % (el / er if er else 99.9))
print(" %-18s %s" % (f, " ".join(out)))
print(" (段序: FL FR FC LFE BL BR; 比值 >1 偏左耳, <1 偏右耳)")
PY
echo
ls -la *.wav | awk '{printf " %-22s %6.0f KB\n", $9, $5/1024}'