浏览器+MIDI:让四十年老琴重新唱歌
浏览器里的时间旅行问题
想象一下这个场景:你的 JavaScript 应用跑在一个每秒能处理几十亿次运算的处理器上。而你工作室桌上的 Yamaha DX7,里面那颗处理器还是 1983 年的货色,每秒最多处理两百万次运算。当你用 Web MIDI API 把这两个世界连在一起的时候,就相当于让一辆跑车去拖一辆马车——问题是马车根本不知道怎么告诉跑车"你开慢点"。
这不是假设。越来越多的开发者在做基于浏览器的 DAW、虚拟乐器,或者硬件控制面板的时候,都撞上了这堵墙:老式 MIDI 设备压根儿就不是为现代数据传输速度设计的。
缓冲区溢出的真相
MIDI 这个协议是八十年代初设计的,传输速率固定在 31,250 比特每秒。这个速度比拨号上网还慢,所以硬件厂商只给设备装了小得可怜的缓冲区——通常就几百字节。比如 Yamaha DX7,RAM 缓冲区只有 256 字节。
但浏览器通过 USB-to-MIDI 接口发送 SysEx 数据的时候,它可不会自动降速到 MIDI 的历史水平。它直接按 USB 的带宽速度往外喷,把那些老设备冲得七零八落。而这些老设备呢,根本没有能力喊停。
结果就是:静默失败、音色数据损坏,最严重的情况下合成器直接卡死,必须断电重启。你那台花了上千块的 DX7,就这么变成了一块贵重的镇纸——就因为你的网页太热情了。
MIDI 为什么没有硬件流控制
串口通信协议一般都有握手信号线,比如 RTS/CTS 引脚,设备之间可以互相说"停一下"或者"我准备好了"。但 MIDI 线只有 5 针,没有一根是干这个用的。协议本身就没设计接收端反馈压力的机制。
这就是一条单行道。浏览器发数据的速度,可以比合成器处理的速度快得多,而合成器根本没嘴巴喊"等等"。所以这个节流阀必须由软件自己来实现。
// 最基本的限速方案
async function throttleSysEx(output, data) {
const PACED_BYTES = 128;
const DELAY_MS = 80;
for (let offset = 0; offset < data.length; offset += PACED_BYTES) {
output.send(data.slice(offset, offset + PACED_BYTES));
await sleep(DELAY_MS);
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
这些数字不是万能的。有些合成器需要在数据包之间留更多喘息空间,特别是往 EEPROM 写入或者操作音色内存的时候。必须自己试,没有统一标准——因为当年硬件厂商压根儿没想过会有人在 2024 年用网页发 SysEx。
各家厂商的数据格式乱象
传输速度的问题解决了?恭喜你,又撞上了第二堵墙:数据格式的混乱。
MIDI 协议定义了音符事件、控制变化、程序切换这些东西,但 System Exclusive 消息——也就是包含音色参数的大块数据传输——完全是各厂商自由发挥的领域。Yamaha、Roland、Korg,每家合成器公司都自己发明了一套字节结构、校验算法和音色转储格式。你的网页应用不仅要知道自己连接的是什么设备,还得知道这个设备具体想要什么格式的字节流。
Yamaha DX7 完整音色转储恰好需要 4104 字节。发 4103 字节?它直接拒绝。发 4105 字节?它可能只接受前 4104 字节,后面的数据就把现有的东西搞乱了。Roland Juno-106 又是另一种玩法——它根本不认软件发起的转储,必须有人跑到前面板上手动按按钮。
Korg 的 7 位压缩架构更是让人头疼。因为 MIDI 的数据字节用最高位做状态标识,所以 Korg 把参数数据压缩成 7 位字。要提取出真正的值,得做位运算和字节解包——做完这些你就知道 8 位架构有多幸福了。
浏览器安全与 MIDI API 的现实
Web MIDI API 之所以强大,恰恰因为它能往外部硬件发原始数据。但这份强大也让浏览器厂商很紧张。恶意网站理论上可以往连接的设备刷固件,或者发损坏的 SysEx 把合成器变砖。
所以浏览器把 MIDI 访问当成特权操作。Chrome 和 Edge 要求用户明确授权才能进行任何 MIDI 通信。Firefox 压根儿没实现这个 API,理由是担心指纹识别和硬件层面的攻击风险。Safari 的态度这些年变了好几次,但现实就是:如果想 Web MIDI 稳定可用,你得假设用户跑的是 Chromium 内核的浏览器。
这对产品规划影响很大。做面向音乐人和硬件玩家的网页工具,得面对这个现实——他们的用户里有相当一部分默认用 Safari 或 Firefox。渐进增强在这里是刚需,不是可选项:MIDI 功能对 Chrome 用户正常可用,对其他浏览器就优雅降级。
为什么这事对开发者很重要
复古合成器这个圈子可不小。经典硬件在二手市场上能卖出溢价,就是因为音乐人偏爱八十年代设备的声音、手感和工作流程。做能和这些设备互动的网页工具,确实是真实的开发机会——但前提是你得懂这些约束。
你的应用发送的每一个字节,都跨越了两个计算时代。你在限速、分块和格式处理上做的选择,决定了这是一个音乐人喜爱的工具,还是一个能把两千美元合成器干掉的杀手。搞清楚这个责任,值得花时间。
如果你在做支持 MIDI 的网页应用,从最慢的可工作传输速度开始,尽早且频繁地用真机测试,永远别把"模拟器上能用"当成什么证明。模拟器没有 256 字节的缓冲区可以溢出。你的用户的合成器有。