Files
2026-10-30 17:40:13 +08:00

6.3 KiB

FIR 设备集成

效果页 /effects 提供 FIR 开关;关闭时仅显示标题与开关,开启后显示数据来源、房间选择或手动双耳 .bin 上传及提交按钮。下拉选项仅显示房间名称,内部仍使用 room_id,隐藏编号、房间详情、格式说明和刷新按钮。文案与错误提示遵循设备语言,支持英文、简体中文、繁体中文;房间原始名称保持原文。上传前校验两耳,顺序上传左耳及右耳;上传全程不发送 fir_enable 请求,不改变开关状态。只有用户手动切换开关时才调用开关接口。请求成功只表示 HTTP 成功,最终是否生效仍需固件联调确认。

开发启动

先启动 Luxsin FIR 文件库(默认 http://127.0.0.1:8000),再运行本项目 npm run dev,访问:

http://localhost:3000/?ip=192.168.9.127#/effects

modern 和 legacy Vite 开发入口均将 /fir-library/* 代理到 http://127.0.0.1:8000/api/*。修改 Vite 配置后需重启开发服务。房间读取失败不会阻止手动文件上传。

生产部署时需在页面服务器配置同样的反向代理,或通过构建环境变量 VITE_FIR_API_BASE 指定可访问的 API 基地址(包含 /api,例如 https://library.example.com/api)。跨源配置需要文件库服务器允许 CORS;HTTPS 页面不能请求 HTTP 文件库。设备请求仍沿用控制器原有设备 IP 和协议选择,设备端须允许对应浏览器访问。

文件库读取接口

  • GET /api/rooms/defaults:默认房间列表,使用 room_id 和 label 构造下拉选项,保留 sample_rate、taps、metadata、measurement 供校验,但不在精简界面展示。
  • GET /api/rooms/{room_id}/device/left、/device/right:选择确认后读取设备专用二进制,严格每侧 8192 抽头、32768 字节,校验后原字节上传。后端将原 8191 抽头转换为 float32 小端并在末尾补零。未设置采样率的房间拒绝上传。

设备协议

开关(用户已确认):

GET http://设备IP/dev/info.cgi?action=setting&fir_enable=0
GET http://设备IP/dev/info.cgi?action=setting&fir_enable=1

同步状态 syncData 可返回 fir_enable: 0 | 1。未提供时默认显示关闭状态,不显示状态说明;开关请求成功后更新本地状态,请求失败不显示成功。

双耳上传:

POST http://设备IP/dev/info.cgi?action=fir&channel=left
POST http://设备IP/dev/info.cgi?action=fir&channel=right
Content-Type: application/octet-stream

请求体为无文件头的 IEEE754 float32 小端数据,左右耳分开,不使用 multipart,不附带 JSON、采样率或长度字段。手动文件保持原字节;房间输出由后端适配为 8192 抽头,不归一化、不重采样:

抽头数 每侧字节数
8191(兼容手动文件) 32764
8192(房间设备输出及手动样例) 32768

手动 .bin 原字节上传;要求以上两种长度之一、每个值为有限 float32、双耳抽头数一致。无法从无头二进制可靠判断采样率、原始格式或大小端,用户需确认文件符合协议并适配设备采样率。数组超过 float32 有限范围时拒绝转换。

失败时不自动重试、不跨重连补发,不改变 FIR 开关。两次单声道写入不具备设备端事务:左耳成功、右耳失败时必须重新上传两侧。页面提示未完成;上传失败会显示具体声道及错误原因,用户可重新上传两侧。所有设备请求沿用现有 4 秒超时。

无硬件测试

node --test scripts/fir-regression.test.mjs scripts/fir-ui.test.mjs
npx tsc --noEmit --incremental false
npm run build:modern
npm run build:legacy

测试通过 mock fetch 执行实际的 LuxsinAPI 方法及 applyFir 流程,校验 URL、POST 类型、原始字节、双耳顺序、开关、格式拒绝、404、网络及单侧失败。不向真实设备发送请求。设备固件尚未实现接口,因此测试不能替代固件兼容性验证。

开发代理与生产直连

开发模式(npm run dev / npm run dev:legacy)的 FIR 二进制上传使用同源代理 /fir-device/{私网IPv4}/{left|right}。Vite 将原始二进制转发至设备 /dev/info.cgi?action=fir&channel=left|right,避免浏览器跨域预检。代理只允许私网 IPv4、端口 80、POST、指定声道及 32764/32768 字节长度;不转发浏览器凭据。修改配置后 Vite 会重启,刷新页面再测试。

生产构建仍由浏览器直连设备,需要设备支持 CORS 或由部署服务器提供同源代理。房间数据读取仍使用 /fir-library。代理不修改数据、不重试,也不调用 FIR 开关。

房间数据使用设备专用接口输出 8192 抽头、32768 字节;内部存储及旧数组接口保持 8191 抽头。HTTP 400 表示服务端拒绝请求,需结合设备校验原因排查。

代理测试:node --test scripts/fir-proxy.test.mjs。

WAV 上传协议更新

设备 POST /dev/info.cgi?action=fir&channel=left|right 使用 Content-Type: audio/wav,请求体为完整单声道 IEEE float32 WAV(不是 multipart)。房间库 /api/rooms/{room_id}/device/{side} 返回 WAV;前端解析并保留采样率,上传时生成含 fmt、fact、data 的 WAV。手动导入使用 .wav。内部计算、AI FIR 和设备 GET 备份仍保留原始 float32 数据;没有采样率信息时上传默认 48000 Hz。此说明取代前文关于 POST 裸二进制的说明。

已核实的设备上传限制

设备 HTTP 400 正文明确要求:单声道、48000 Hz、8192 点,PCM16/24/32 或 float32。现在 encodeDeviceFirWav 将所有上传统一为 float32、48 kHz、8192 点。旧房间库的 44.1 kHz 裸系数先按元数据解析,再用窗函数 sinc 重采样;不是只改 WAV 文件头。重采样按源/目标采样率缩放以保持卷积增益,两耳使用同一时间轴;过长响应固定截取 8192 点,末尾 64 点渐隐,不足补零。48 kHz / 8192 点原系数字节不变。开发代理关闭设备连接复用,避免固件 Keep-Alive 导致回读截断。以上更新取代前文关于保留源采样率上传的说明。

2026-10-23 实机验证:Listening Room 左右耳上传均 HTTP 200;设备 GET 返回 WAV 与生成 WAV 逐字节一致。未改变 fir_enable 或音量。