糖糖
|
d331128e88
|
输出设备不写死: 面板设备选择 + 自动挂载守护(治开机后"双重混响")
- 问题: 30-collaplex-eq.conf 的 node.target 是安装时探测一次写死的。开机时设备若还没枚举
(USB 耳机晚到很常见: 09-24 实测开机 08:57、耳机 09:19:43 才出现; 09-23 是 21:01 → 21:03),
建链时目标不存在 → 末段连到别处或干脆不连, 设备出现后不会自己改回来 → 听感"双重混响",
只能 stop + start
- 新增 web/output_route.py: 设备清单(pw-dump) + 选择落盘(output.json) + 守护线程(每 3 秒核对
collaplex_eq_out 只连选中设备, 不对就拆错的、按声道补对的) → 设备一出现自动挂上
- web/server.py: GET /api/devices, POST /api/device(落盘 + 立刻挂载), 快照带 output 段,
main() 起守护线程
- web/index.html: 「输出设备」卡片(下拉 + 应用 + 状态 + 守护备注; 设备表变化才重建选项, 免得
60 Hz 重建打断点击)
- 脚本/安装.sh: 优先用记住的设备(不在位也照样按它建链), 不再"猜第一个 digital"
- 实测: 面板真点应用切走再切回 ✓ / 连错 2 秒自动纠回 ✓ / 全拆 3 秒自动挂回 ✓ / start 自检
打印 [在位] ✓ / 面板像素验收 ✓; pyright strict 0 errors 0 warnings
- 坑: pw-dump 的 Link 键名是 output-port-id / input-port-id(写 output-port 一条连线都读不到);
面板服务 enable --now 不会重启已在运行的实例(改 web/*.py 必须 restart)
v1.0.9
|
2026-09-24 09:36:36 +08:00 |
|
lou
|
117a0c65d6
|
stop: 清锁改用通配 —— 锁文件是每声道一份(.lock0/.lock1), 只删基名会留残留
|
2026-09-23 21:11:18 +08:00 |
|
lou
|
717842f0a9
|
场所预设: 「电影院」「歌剧院」一键切 EQ + 混响
影院和歌剧院最本质的差别是混响时间(0.4~0.8 s vs 1.4~1.8 s), 光切 EQ 不够 ——
所以把这两个入口从 EQ 预设里移出来, 单独立一排「场所」按钮, 点一下同时切:
- 电影院: EQ(X-curve 高频滚降 + sub 低频) + 湿量 0.35
- 歌剧院: EQ(木质厅堂温暖 + presence) + 湿量 0.78
实现:
- PRESETS 里的两个条目搬到新的 VENUES(带 wet 字段); 抽出 applyEqPoints() 给两者共用
- 按钮互斥高亮: 点场所清掉 EQ 预设高亮, 反之亦然; 手动拖 EQ 滑块 / 湿量 / 全部归零都清
- 坑: wet 的 change handler 里是 `await post(...)` 之后才 markVenue(null), 属于异步 ——
会在 applyVenue 点亮之后才跑, 把高亮清掉(第一轮 CDP 验收就是这么挂的)。用
venueApplying 标志在 dispatch 那一刻记录意图, handler 据此决定清不清。
- applyVenue 里 markBusy("wet", 1500) 防 SSE 轮询把刚设的湿量弹回旧值
总音量不放进场所里 —— 那是个人听音响度, 不该切个场所就被改掉。
验收(CDP 真实点击): 点两个场所, 前端湿量与 /api/state 后端值一致(0.78 / 0.35),
EQ 32 段与设计逐位一致, 高亮 = 对应按钮名; 手动拖湿量后高亮清空。截图核过像素。
v1.0.8
|
2026-09-20 17:15:59 +08:00 |
|
lou
|
2566307e6c
|
EQ 预设加「电影院」「歌剧院」+ 预设按钮选中高亮
两个新预设按现实场所的声学设计, 不是随手画的微笑曲线:
- 电影院: 高频按 X-curve(ISO 2969 国际版, 2 kHz 以上约 -1.5 dB/oct, 实测 2k->4k->8k->16k
逐段 -1.5)再叠银幕透声损失; 低频 25~60 Hz +2.5~3 dB(影院 sub / LFE 通道的体感)
—— 厚, 暗, 有力
- 歌剧院: 中低频 150~400 Hz +2 dB(木质厅堂的温暖); 2~5 kHz +0.5~1 dB(没有扩声系统,
歌手靠 presence 区投射, 这里不能削); 极低频 20~40 Hz -1 dB; 高频只随大空间空气吸收
缓降 —— 暖, 亮, 有细节
两者实测差: 25~60 Hz 影院重 3.4 dB / 3.15~5 kHz 歌剧院足 3.0 dB / 8~16 kHz 歌剧院足 3.5 dB。
顺带修: `.presets button.on` 的样式一直定义了但没有任何代码加这个类 —— 点了预设没有选中
反馈。加 markPreset(): 点预设高亮对应按钮, 手动拖滑块 / 全部归零时同步更新。
验收(CDP 真实点击): 两个预设的 32 段值与设计逐位一致; 高亮 = 对应按钮名; 手动拖滑块后
高亮清空。README 加「EQ 预设的设计依据」节(含影院/歌剧院的混响湿量建议)。
v1.0.7
|
2026-09-20 13:51:25 +08:00 |
|
lou
|
3b6ce2c57e
|
参数持久化: 面板改动落盘, 重启/开机后自动恢复
问题(09-20 实测复现): dsp/common.py 的 open_store() 是"文件不存在就零填充创建", 而
/dev/shm 是 tmpfs —— 重启后参数全变 0。听感上不是"参数没保存", 而是**"混响突然没了"**
(湿量 0), 极易被当成链路故障去查。
修法:
- common.py: 加 params.json 落盘(load_saved_params / save_params / restore_params);
open_store() 检测到文件是"新建的"就从落盘恢复(带上下限夹取)。幂等 —— 两个声道进程
同时判定为新建也没关系, 写进去的值一样。
- web/server.py: 面板每次改参数(POST /api/eq|volume|wet)后 save_params() 落盘; 值没变不写。
- 初始化.py: 改成"优先用落盘, 没有才用默认值", 并报告参数来源。
实测(rm /dev/shm/collaplex-eq* + 重启 pipewire): 参数自动恢复, 与落盘逐值一致
(总音量 +2.0 / 湿量 0.600 / EQ 非零 30 段)。
落盘位置 ~/.local/state/cinema-spatial/params.json(与 loudness.json 同目录)。
README 加「参数持久化」节 + 坑表条目。
v1.0.6
|
2026-09-20 13:40:06 +08:00 |
|
lou
|
5c6a982210
|
修低频过量的四条: HRIR 均衡 + 房间 IR 校平 + LN_MAX_BOOST + EQ 平直
诊断见 README「实测(2026-09-20)」: 链路的**线性**部分干净(无驻波、失真 −116 dB),
"低频脏 + 沙沙"来自电平被顶穿之后软限幅常年介入 —— 归一化把内容提到满刻度, 宽频信号
一削, 互调产物堆在低频(听感"脏")、高频碎屑(听感"沙沙")。实测超软限幅阈值样本 50.49%、
峰值因子被从 14 dB 压到 2.0 dB。
四条修复:
1. LN_MAX_BOOST 20 -> 12(默认值): 20 dB 的提升上限让任何轻内容都被顶穿满刻度
2. HRIR 同相合并响应均衡(lowshelf 500Hz −7.2dB Q=0.707, 12 条共用一条曲线,
方向线索 ILD/ITD 不受影响): 这套 HRIR 是原始测量数据、没做过漫反射场均衡。
★ 口径注意: 标准 DF-EQ 用各方向**功率平均**做参考, 只要求压 1.5 dB; 但真实内容
L≈R 时两耳信号是**相加**的, 同相合并响应才对应实测的 7.5 dB
3. 房间 IR 低频校平(lowshelf 300Hz −21dB Q=0.70): 低频比中频高 24.5 dB -> 压到 +5.8 dB
(留一点厚度); IR 峰值随之掉 3.7 dB, 湿路 gain 0.4 -> 0.61 补偿, 保持混响响度不变
4. EQ 微笑曲线(20~63Hz +2.5 / 高频 +3)改回平直
复测(同素材同脚本): 低频 20~200Hz **+13.6 -> +0.2 dB**; 整链峰值因子 **2.0 -> 12.2 dB**;
超阈值样本 **50.49% -> 0.00%**; 峰值/RMS −0.1/−2.1 -> −6.2/−18.4 dBFS。
响度目标回到 −14 dB 也不会再顶穿。
新增: 工具/分析均衡曲线.py(量曲线)、工具/均衡IR.py(施加校正, 可重跑);
README 加「IR 校正」节 + 修复前后对照 + 两条测量方法上的坑。
IR 备份: hrir/*.pre-eq.wav 与 reverb/*.wav.pre-eq.wav(频响校正前)、
reverb/*.orig.wav(剪直达声前)。重跑顺序: 先 重做混响IR.py, 再 均衡IR.py。
v1.0.5
|
2026-09-20 13:05:10 +08:00 |
|
lou
|
c9e9a5ac28
|
混响立体声丢失: 重做 IR 的工具把双声道压成了单声道 -> conf 改用 convolver 的 channel 按声道取
- 工具/重做混响IR.py 原来写 `x = x[:, 0]`, 只取左声道、把右声道丢掉, 写出去的 IR 成了
单声道; 而 20-conf 里 revL/revR 读的是同一个文件 -> 两路湿声完全同源, 混响糊在正中央、
没有宽度(原 IR 本身是双声道真立体声, 左右相关 0.884)
- 改为逐声道处理 + 双声道写回; 重新生成 reverb/房间混响IR-96k.wav (285888 x 2, 相关 0.9492)
- 20-conf: revL 用 channel = 0 / revR 用 channel = 1 —— PipeWire 的 convolver 支持该键,
从多声道 IR 文件里按索引取声道。实测(通道探针: 左零右真的文件 + channel = 1)右耳尾巴
不塌, 左右差仅 1.1 dB; 若读错声道会掉 40 dB 以上
- 新增取证脚本: 扫频测频响(Farina 反卷积, 确定性信号才测得准)、电平与失真诊断(只改电平的
对照实验)、验证混响声道(文件级 + 物理级检查)、诊断低频沙沙(逐级旁路)
- 扫频脚本修了一个 bug: 湿量只在第一轮写, 后面几轮沿用被改过的值, 导致 B/C 两轮测的是同一配置
- README: 坑表加两条(双声道 IR + 验证判据的坑) + 2026-09-20 低频/沙沙诊断实测段
|
2026-09-20 12:55:51 +08:00 |
|
lou
|
c362aabb5e
|
修"播着播着没声音" + 响度目标 -16 调到 -12
- 10-/30- conf 的虚拟声卡与各级输出都加 node.always-process + node.pause-on-idle=false:
空闲时若被 suspend, 客户端(Chromium 经 pipewire-pulse)会认为输出端不再消费而停止推数据,
表现为"播着播着突然没声音, 刷新页面才恢复"
- LN_TARGET_DB -16 -> -12(听着更响)
- 新增 测试/监控链路.py
|
2026-09-20 12:55:51 +08:00 |
|
lou
|
3f64190187
|
修'刷几条视频后没声音': 归一化 DSP 原来拿'连续 10 秒无数据'当'链路已断'的判据, 但音频流本来就有静默期(视频间隙/暂停/切歌), 于是正常使用时自己退出 -> pipe 断 -> 没声音, 刷新页面重连才恢复。改用'启动时的 ppid'比对(filter-chain 死后子进程被 systemd 收养, ppid 必变), 静默不再退出; IDLE_LIMIT 降级为 600s 兜底。实测: 静默 15s 后归一化进程仍在(修前降为 0)
|
2026-09-19 21:12:08 +08:00 |
|
lou
|
43919f5f97
|
开机自启: 链路靠 PipeWire 自动加载 conf(不需要服务); 面板加 systemd --user 服务 collaplex-audio-panel.service(start 时自动装并 enable, Restart=no); 修 stop 漏杀按相对路径起的面板进程(端口被占导致新服务起不来); 打包带上 systemd/; README 加自启段 + 进程匹配要按后段的坑
v1.0.4
|
2026-09-19 20:48:47 +08:00 |
|
lou
|
3aa10897ba
|
打包脚本排除 IR 备份文件(.orig.wav 只留源码树), deb 从 2.8M 回到 968K
v1.0.2
|
2026-09-19 20:32:31 +08:00 |
|
lou
|
a422792df2
|
修回声: 房间 IR 含 30ms 传播延迟(声源到麦克风 10.3m 的声程)且前两次反射与直达声同量级(30ms 处 0dB/40ms 处 -1.6dB), 与零延迟的干声相加 -> 湿声晚 30ms 还很响 = 回声; 处理 IR(裁前 22ms 静音 + 前 55ms 余弦渐入, 直达声段 0 -> -23.6dB)再把 gain 重标 0.126->0.4 补回混响量; 脉冲取证: 修前 120ms 处 -26dBFS 孤立峰(+12dB), 修后包络单调衰减无孤立峰; 新增 测试/test_echo.py 与 工具/重做混响IR.py, 原 IR 备份 .orig.wav
|
2026-09-19 20:32:07 +08:00 |
|
lou
|
ddd642b772
|
主命令改成日常三个动作: start(接管系统音频) / stop(恢复默认输出+停面板) / web(起面板并打开浏览器); 安装脚本 /proc 进程消失竞态静默; README 与 deb 描述同步; 版本 1.0.1
v1.0.1
|
2026-09-19 20:13:12 +08:00 |
|
lou
|
489a8a79c2
|
README: 第二代声明(对第一代 cinema-spatial 推倒重构) + 代际对比表(架构/EQ/响度/混响/控制/分发)
v1.0.0
|
2026-09-19 20:04:12 +08:00 |
|
lou
|
f1d6f84b2f
|
发布准备: 主命令 collaplex-audio(install/uninstall/status/panel) + 打包deb.sh(deb 1.9MB, Arch all, 依赖 python3-numpy/scipy, 装完不自动启用) + 安装脚本支持系统解释器(deb 场景无 venv) + 自检补湿量进程 + README 重写(链路图/面板/预设/数据来源/坑表/实测表/测试脚本清单)
|
2026-09-19 20:02:21 +08:00 |
|
lou
|
6a43111d5a
|
EQ 预设 10 个(平直/流行/摇滚/爵士/古典/人声/低音/高音/深夜/柔化): 用控制点在对数频率轴插值成 32 段; CDP 点击实测低音[7,7,7,7,6.5,6]+后段-1、柔化前段-2后段-4.5 均写入 DSP
|
2026-09-19 19:56:58 +08:00 |
|
lou
|
bd9238e8b0
|
面板刷新率 4Hz -> 62Hz: 服务端加 SSE 推送 /api/stream(FRAME_SEC=16ms), 前端改用 EventSource; 电平表加'上升立刻跟 + 下落每帧最多 0.9dB 平滑 + 峰值保持 1.6 秒', 归一化电平/增益同套平滑, 增益显示两位小数
|
2026-09-19 19:54:11 +08:00 |
|
lou
|
00c9ced2c0
|
前端: 归一化加输入电平与动态增益显示(读归一化 DSP 状态); 修总音量滑块回弹(activeElement 判断不准 -> 显式 busy 标志 + 松手静默期), CDP 真鼠标拖动实测 4->10.5 停住不回弹
|
2026-09-19 19:47:11 +08:00 |
|
lou
|
6f5729baf2
|
前端加 4 个电平表(入L/出L/入R/出R, 双声道由 flock 分槽) + 混响湿度滑块(实时); 湿量抽成独立 DSP 增益级(wet_gain.py), 混响仍用 PipeWire convolver 跑 3 秒长 IR; 实测湿量 0 无尾巴 / 1 有 3 秒衰减尾巴
|
2026-09-19 19:37:54 +08:00 |
|
lou
|
927309b1a9
|
README 补 SADIE II 来源(约克大学 H4, Zenodo DOI); 更新已修的残留描述(块间插值/限幅阈值); 记下'峰值失真纯音测不出'的教训
|
2026-09-19 19:28:21 +08:00 |
|
lou
|
b154ac46c1
|
修限幅介入过早: 阈值 -3.9 -> -0.63 dBFS(ceiling 0.99/knee 0.06). 纯音峰值因子仅3dB测不出, 音乐(10-14dB)峰值长期落在旧阈值内被压 -> 中低频谐波; 类音乐实测非瞬态增益精确 +6.00dB, 纯音+6dB 谐波 -65.6 -> -91.1 dB; 新增 test_limit.py(高峰值因子素材)
|
2026-09-19 19:27:04 +08:00 |
|
lou
|
f3069cdb15
|
96k 时钟 conf 收进项目(原来只在系统侧, 重装会丢 -> HRIR 被按 48k 降采样); 安装脚本一并部署 91-clock.conf
|
2026-09-19 19:23:20 +08:00 |
|
lou
|
38ae1fa22e
|
修块间台阶残留: 归一化增益改块内逐样本线性插值(zipper 噪声); 谐波(相对基频) +0/+6dB 由 -12.1/-15.9 降到 -90.1/-70.6 dB; 调试用的测试脚本收进 测试/, 清理全部调试残留
|
2026-09-19 19:22:48 +08:00 |
|
lou
|
a81adb616b
|
修中低频沙沙: 房间混响 IR 未归一化(中低频频响 +20dB), 湿路径干湿相加使 HRTF 级 +19dB, 把归一化的 -14dBFS 顶到 +5dBFS 导致软限幅持续工作生成谐波; 给混响 convolver 加线性增益 0.126(-18dB); EQ入峰值 +5.16->-15.57 dBFS, 600Hz 谐波 -9.9->-28.9dB
|
2026-09-19 19:17:31 +08:00 |
|
lou
|
2dd51e3324
|
修沙沙声: eq.py 块长不再假设固定的 1024 样本(quantum 在 32~2048 间变化, 原来用 np.resize 重复填充 -> 周期性伪影); 改为按实际块长一对一处理; 实测 4096/2048/1024/512/384 字节全部一对一
|
2026-09-19 18:58:30 +08:00 |
|
lou
|
b25770cd51
|
修第二处放大 bug: 删掉 20- 里残留的固定 +6dB 音量级和多余 param_eq(与面板总音量叠了两级, 把归一化的 -3dBFS 顶到 +3dBFS); 逐级实测排除归一化与混响; 修后 +0/+6/+12dB 输出峰值 -12.28/-6.35/-1.11 dBFS
|
2026-09-19 18:53:18 +08:00 |
|
lou
|
e8b402472c
|
修削峰: 总音量输出级 np.clip 硬削 -> soft_limit 软限幅(上限-1dBFS, tanh 渐近); +12dB 时贴顶样本 64.6%->0%, 峰值 -1.01 dBFS
|
2026-09-19 18:45:12 +08:00 |
|
lou
|
5a4b11092c
|
前端: 抽公共层(dsp/common.py 共享内存协议)+ 32段EQ/总音量 DSP(dsp/eq.py, scipy sosfilt) + 本地控制面板(web/, 滑块+滚轮捕捉); 安装脚本接 30-collaplex-eq; pyright strict 0 error
|
2026-09-19 18:34:56 +08:00 |
|
lou
|
f32c2cad24
|
核心后加 EQ(三段平直) + 总音量放大(+6dB, VOL_DB 可调); param_eq 端口须带编号(In 1/Out 1); README 补调参与坑
|
2026-09-19 18:24:18 +08:00 |
|
lou
|
0dc55ddcb5
|
归一化接在核心前面: 全局音频 -> 虚拟声卡 -> 响度归一化 -> HRTF(湿量0.3) -> 数字输出; 安装脚本单脚本可复现(含残留DSP清理)
|
2026-09-19 18:16:43 +08:00 |
|
lou
|
1b93498096
|
虚拟声卡接入 HRTF 直出: 全局音频 -> 虚拟声卡 -> HRTF(湿量0.3) -> 数字输出; 安装脚本重写为两级独立部署+自检
|
2026-09-19 18:09:29 +08:00 |
|
lou
|
0840c7d398
|
HRTF 独立实例: 接入(collaplex_hrtf_in) -> 双耳 HRTF + 房间混响(湿量0.3) -> 数字输出; 虚拟声卡退回纯转发
|
2026-09-19 18:06:23 +08:00 |
|
lou
|
f1a3c80fd4
|
固化链路: 虚拟声卡 + 响度归一化 -> 数字输出 (安装脚本可复现部署)
|
2026-09-19 17:22:03 +08:00 |
|
lou
|
4ca821011b
|
初始化: collaplex音效 项目骨架 (venv + gitignore)
|
2026-09-19 17:07:19 +08:00 |
|