展示HN:完美的Windows蓝牙MIDI

3作者: mayerwin大约 3 小时前原帖
嗨,HN,我是Erwin。我开发了一个小型的免费开源工具,可以将蓝牙低能耗(BLE)MIDI键盘连接到新的Windows MIDI服务堆栈,这样任何数字音频工作站(DAW)或Web MIDI应用程序都可以像使用有线设备一样使用它们。 我购买了一台Roland FP-90X钢琴,部分原因是它支持蓝牙MIDI。在我的Windows 11电脑上,配对成功,但我的DAW无法识别键盘,电脑发送的音符从未让钢琴发声。在经历了令人遗憾的多个晚上后,我将这个问题分解为三个独立的bug,层层叠加。 第一个问题是著名的:Windows仅通过WinRT API原生支持BLE-MIDI,而几乎没有DAW会轮询这个API。因此,即使配对成功,MIDI应用程序仍然无法看到设备。通常的解决方法是使用MIDIberry和loopMIDI,但在我的情况下,这种组合无法可靠工作,我希望找到一个单一应用的解决方案。新的Windows MIDI服务堆栈提供了一种名为回环端点的功能:写入一个端点的任何内容都会从另一个端点输出,任何winmm/WinRT/WMS应用程序都将其视为正常的MIDI端口。因此,该应用程序实现了WinRT BLE-MIDI输入,WMS回环输出。这解决了从钢琴到电脑的方向问题。 然而,从电脑到钢琴的方向仍然无法工作。NoteOn写入遭遇了ATT攻击,但钢琴依然沉默。我尝试了两种写入模式(某些BLE-MIDI固件会默默丢弃其中一种),并探测了专有的ISSC特征。每种变体都遭遇了ATT攻击,每种变体都产生了沉默。因此,字节确实到达了钢琴,但GATT层之上的某些东西将其丢弃了。 在排除了配对、加密、写入模式和专有特征后,唯一明显的杠杆就是MIDI通道本身。FP-90X有一个面板设置叫做“传输通道”,默认是1。然而,FP-90X实际上是在通道4上接收(并且无法更改)。我在通道1上发送的音符被GATT攻击并在合成引擎处静默丢弃,因为它们不在引擎监听的通道上。任何层面都没有反馈。解决方案必须在应用层,因此我添加了一个“检测”按钮,可以在每个通道上从1到16播放N个测试音符:你计算实际听到的音符数量,这个数字就是接收通道。每个BLE MAC保存大约75秒,永久适用于每台钢琴。 技术栈:.NET 10,使用Avalonia作为UI(BLE/MIDI部分仅适用于Windows,但UI层是可移植的),使用Microsoft.Windows.Devices.Midi2包用于WMS,直接使用Windows.Devices.Midi(WinRT)用于BLE,而不是依赖Korg的旧WinMM驱动程序。MIT许可证,单个自包含的约21MB可执行文件,无需安装程序,无遥测,无需账户。 我为自己开发了这个工具,并用它与我的FP-90X通过几个应用程序和Web MIDI网站进行演奏。当我在r/synthesizers上分享时,来自微软Windows MIDI服务团队的Pete对BLE集成给予了积极的评价(链接:[Reddit](https://www.reddit.com/r/synthesizers/comments/1szvuiq/comment/oj5ew9b/))。 网站(带截图):[Perfect Bluetooth MIDI For Windows](https://mayerwin.github.io/Perfect-Bluetooth-MIDI-For-Windows) 源代码:[GitHub](https://github.com/mayerwin/Perfect-Bluetooth-MIDI-For-Windows) 详细的技术文章和完整的调试故事:[Dev.to](https://dev.to/mayerwin/why-your-bluetooth-midi-keyboard-silently-drops-notes-on-windows-2i84) 个人仅在我的FP-90X上进行了测试。BLE部分是通用的,因此其他键盘(如WIDI Master、CME、Yamaha MD-BT01、Korg microKey Air、ROLI Seaboard等)应该也能工作,但我尚未逐一确认。欢迎提供设备测试报告、问题反馈和PR。
查看原文
Hi HN, I&#x27;m Erwin. I built a small free open-source utility that bridges Bluetooth LE MIDI keyboards into the new Windows MIDI Services stack so any DAW or Web MIDI app can use them as if they were wired.<p>I bought a Roland FP-90X piano partly because it had Bluetooth MIDI. On my Windows 11 PC, pairing succeeded, but my DAW couldn&#x27;t see the keyboard, and notes I sent from the PC never made the piano sing. After a regrettable number of evenings, I&#x27;d separated this into three independent bugs stacked on top of each other.<p>The first one is the famous one: Windows only natively exposes BLE-MIDI through the WinRT API, which almost no DAW polls. So even when pairing succeeds, MIDI apps still don&#x27;t see the device. The usual workaround is MIDIberry + loopMIDI, but I couldn&#x27;t get that combination to work reliably in my case, and I wanted a single-app solution. The new Windows MIDI Services stack ships with a feature called loopback endpoints: anything written to one comes out the other, and any winmm&#x2F;WinRT&#x2F;WMS app sees them as normal MIDI ports. So the app does WinRT BLE-MIDI in, WMS loopback out. That solved direction one, piano to PC.<p>Direction two, PC to piano, still didn&#x27;t work. NoteOn writes were getting ATT-acked, but the piano stayed silent. I tried both write modes (some BLE-MIDI firmware silently drops one or the other), poked the proprietary ISSC characteristic. Every variant ATT-acked, every variant produced silence. So the bytes were reaching the piano. Something above the GATT layer was discarding them.<p>After ruling out pairing, encryption, write-mode, and proprietary characteristics, the only obvious lever left was the MIDI channel itself. The FP-90X has a panel setting called Transmit Channel, default 1. Yet it turns out the FP-90X actually receives on channel 4 (and it can&#x27;t be changed). Notes I sent on channel 1 were being GATT-acked and silently dropped at the synth engine because they weren&#x27;t on the channel the engine was listening to. Zero feedback at any layer. The fix had to live up at the application layer, so I added a Detect button that plays N test notes ascending on each channel from 1 to 16: you count the notes you actually hear, and that number is the receive channel. Saved per BLE MAC, about 75 seconds, done forever per piano.<p>Tech stack: .NET 10, Avalonia for the UI (the BLE&#x2F;MIDI side is Windows-only but the UI layer is portable), Microsoft.Windows.Devices.Midi2 packages for WMS, Windows.Devices.Midi (WinRT) directly for BLE rather than relying on Korg&#x27;s older WinMM driver. MIT, single self-contained ~21 MB exe, no installer, no telemetry, no account.<p>I built it for myself and use it with my FP-90X to play through a few apps and Web MIDI sites. Pete from the Microsoft Windows MIDI Services team commented positively on the BLE integration when I shared it on r&#x2F;synthesizers (<a href="https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;synthesizers&#x2F;comments&#x2F;1szvuiq&#x2F;comment&#x2F;oj5ew9b&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;synthesizers&#x2F;comments&#x2F;1szvuiq&#x2F;comme...</a>).<p>Site (with screenshots): <a href="https:&#x2F;&#x2F;mayerwin.github.io&#x2F;Perfect-Bluetooth-MIDI-For-Windows&#x2F;" rel="nofollow">https:&#x2F;&#x2F;mayerwin.github.io&#x2F;Perfect-Bluetooth-MIDI-For-Window...</a> Source: <a href="https:&#x2F;&#x2F;github.com&#x2F;mayerwin&#x2F;Perfect-Bluetooth-MIDI-For-Windows" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;mayerwin&#x2F;Perfect-Bluetooth-MIDI-For-Windo...</a> Long-form technical writeup with the full debugging story: <a href="https:&#x2F;&#x2F;dev.to&#x2F;mayerwin&#x2F;why-your-bluetooth-midi-keyboard-silently-drops-notes-on-windows-2i84" rel="nofollow">https:&#x2F;&#x2F;dev.to&#x2F;mayerwin&#x2F;why-your-bluetooth-midi-keyboard-sil...</a><p>Personally tested with my FP-90X only. The BLE side is generic, so other keyboards (WIDI Master, CME, Yamaha MD-BT01, Korg microKey Air, ROLI Seaboard, etc.) should work, but I haven&#x27;t confirmed individually. Device test reports, issues, and PRs very welcome.