ブラウザから旧世代シンセを鳴らすと壊れる——犯人は「遅いCPU」ではなかった

テクノロジー
スポンサーリンク

ブラウザのタブを開いて、1983年発売のシンセサイザーをUSBでつなぐ。ドライバーもインストーラーもいらず、そのまま音色データを読み書きできる——Web MIDIを使えば、これが本当にできてしまう。ところが、ここには落とし穴がある。データを送る速度がほんの少し速いだけで、40年前のシンセは簡単に音を上げる。液晶画面が意味不明なブロックで埋まり、内部のメモリー保護が働いて書き込みを拒む。

このトラブルの正体を1か月かけて突き止めた、という技術ブログがHackaday経由で話題になっていた。書いたのは、Web MIDIでビンテージシンセの音色を扱うツール「knob.monster」の開発者だ。要点は、不具合の原因が意外なところにある、という点にある。

不具合の原因は「遅い8ビットCPU」ではない

まず語られがちなのは、「昔の8ビットマイコンが、現代の速いMIDIデータを処理しきれないから」という説明だ。直感的で、いかにもありそうに聞こえる。だが、開発者がたどり着いた結論はこれを否定する。悪いのはシンセ側のCPUではなく、データを送り出す現代のソフトウェアの書き方のほうだった。

Hackadayのコメント欄でも、同じ指摘をする人が何人もいた。ビンテージシンセが遅いのではなく、送信側がMIDIをきちんとバッファリングしていないだけだ、という声だ。40年以上使われ続けてきた規格のほうに問題があるわけではない、というのが現場の実感らしい。

MIDIの31,250ボーという速度の壁

昔ながらのMIDIは、そもそも遅い。転送速度は31,250ボー(毎秒およそ3,125バイト)に固定されている。一方でYamaha DX7の音色バンク一式は、たった4KBほどしかない。つまりシンセの側は、4KBを受け取るだけの時間を十分に持っている。

問題は送り手にある。現代のPCはUSB経由で毎秒メガバイト級のデータを吐き出せる。しかも標準的なMIDIケーブルには、受け手が「まだ前のブロックを書き込み中だから待ってくれ」と伝えるための信号線がない。パソコンの通信でいうフロー制御にあたるものが、そもそも用意されていないのだ。だから送り手が加減せずにファイル全体を一気に投げつけると、シンセの受信バッファは一瞬であふれる。

安価なUSB-MIDIアダプターという落とし穴

多くの人は、数千円するプロ用のMIDIインターフェースではなく、通販で数百円で買えるUSB-MIDI変換アダプターを使う。ここに二つ目の罠がある。安価なアダプターに載っている小さなマイコンには、まともなバッファがない。大きなSysExデータ(システムエクスクルーシブ。メーカー独自の一括データのこと)を送りつけると、アダプターはUSBの速度で受け取ったそれを、そのままの勢いでMIDI出力へ吐き出してしまう。

本来あるべきパケットとパケットの隙間が潰れ、SysExの先頭情報が壊れ、シンセにはゴミしか届かない。つまり、送り手のPCと受け手のシンセのあいだに挟まったこの小さな部品が、速度差をならすどころか、かえって事態を悪化させていることになる。

解決の鍵はWeb MIDI内蔵のスケジューラ

高価なインターフェースには十分なバッファが積まれていて、この問題を吸収してくれる。だが、もっと素直な解決策がWeb MIDIそのものに用意されている。API内蔵のスケジューラを使い、送信のタイミングをこちら側で指定してやればいい。

コツは二つある。まず、データを適当なバイト数でぶつ切りにしないこと。そして、JavaScriptのsetTimeoutで60ミリ秒待つ、といったやり方も避けること。この手の待ち方はCPUの負荷しだいで間隔がずれてしまい、かえってメモリーを壊す。代わりに、F0で始まりF7で終わる完結したメッセージを単位として、performance.now()を基準にした正確な時刻を添えて送り出す。

function sendSysExWithPacing(midiOutput, messages) {
  const INTER_MESSAGE_DELAY_MS = 60; // 旧世代CPU向けの安全な間隔
  let offset = 0;
  for (const message of messages) {
    midiOutput.send(message, performance.now() + offset);
    offset += INTER_MESSAGE_DELAY_MS;
  }
}

やっていることは、メッセージごとに60ミリ秒ずつ間隔を空けて送るだけだ。この「送り手の側を落ち着かせる」という発想自体は、新しいものではない。1990年代のシーケンサーソフトにも、SysExを1バイトごとにわずかに遅らせて流す設定があった。Hackadayのコメントでも、当時のCakewalkでバイト遅延を入れていた、LinuxのALSAで同じことをした、といった経験談が並んでいた。速いのは送り手のほうで、遅らせるべきも送り手のほう、というわけだ。

メーカーごとに異なるSysExの中身

送れるようになったら、次は届いたバイト列を読み解く番になる。1980年代のMIDI規格は、SysExの中身の作り方をメーカーの裁量に丸投げしていた。おかげで機種ごとにデータ構造がばらばらで、それぞれに癖がある。

  • Yamaha DX7:ぴったり4,104バイトを吐き出す。32個ある音色スロットの、それぞれ末尾10バイトに音色名がASCIIで入っている。
  • Roland Juno-106:外部からの「データを送れ」という要求には応じない。本体の「WRITE」キーを人が実際に押して、はじめて現在のメモリーが流れ出す。
  • Korg M1:7ビット単位に詰め込んだ独特の構造を使う。MIDIのデータバイトは最上位ビットを0にしておく決まりがあるため、7バイトごとにまとめ、あぶれた8ビット目だけを別に付け足す。テキストを読むだけのために、ビットをずらして元に戻す処理を自前で書く必要があった。

手元の古いシンセで試すなら

なお、この記事のもとになったknob.monster自体は、ブラウザからビンテージシンセの音色をバックアップ・整理する有料ツールで、記事はその開発者が書いたものだ(月額ではなく買い切りのライセンスとのこと)。宣伝を兼ねた技術ブログではあるが、Web MIDIのスケジューラで送信を整える手法そのものは、特定のツールに縛られない一般的なテクニックとして使える。

手元に古いシンセと数百円のアダプターがあって、ブラウザから音色を流し込もうとして画面がバグった経験がある人なら、原因の切り分けとして覚えておいて損はない。疑うべきはシンセの古いCPUではなく、送り手の速度と、あいだに挟んだ安物のアダプターのほうだ。

出典

knob.monster: How do you pace Web MIDI SysEx for vintage synths?(2026年6月23日)
Hackaday: Old Midi Instruments Don’t Like Modern Midi. What’s To Be Done?(2026年7月5日)

コメント

タイトルとURLをコピーしました