見出し画像

【脳筋】東方旧作アレンジのMMLを再生したくてWSLでCライブラリをビルドした話

注意:筆者はPMD、MML、PC-98のFM音源について本当に何の知識もない状態からスタートしています。PC-98すら実機を触ったことがありません。詳しい方から見たら突っ込みどころしかないと思いますが、そういう記事です。「知識ゼロの人間がAIに丸投げしたらどうなったか」の記録として読んでください。

音楽だと思ったら暗号だった

音楽ファイルだと思ってわくわくしながらダウンロードしたら、暗号だった。

きっかけはSaria Lemesという作者の東方旧作アレンジだった。

YouTubeで見つけた。

【PC-98アレンジ】永遠の巫女 - 東方靈異伝

PC-98のFM音源で鳴る東方の曲。「Eternal Shrine Maiden」——東方靈異伝のテーマ曲のPMDアレンジ。

配布リンクがあった。Pastebinという馴染みのないサイトだった。

ダウンロードボタンを押した。落ちてきたのはテキストファイルだった。

開いてみる。

#Title		Eternal Shrine Maiden (Website Ver.)
#Composer	ZUN
#Arranger	pedipanol
#DT2Flag	on
#Timer		190

ヘッダの後に意味不明な文字列がズラズラ並んでいる。@004 0 6 18 12 1 4 3 35...みたいな変な数値の羅列。A l8 v11 [d2dc<a f b2>dc<a...]みたいな記号の嵐。

なんやねんこれ。

MIDIは知ってる。でもこれは未知すぎた。音楽のための楽譜に見えない。ただの暗号にしか見えなかった。

あとで知ったが、これはMML(Music Macro Language)というテキストで音楽を記述する言語で、CDEFGABが音階、L4が四分音符、O4がオクターブ、という体系らしい。らしい、というのは当時の自分にはそんな知識は一切なかったからだ。

でもこのテキストをどうやって音にするのか分からない。

サイトは英語だし、PMDの再生環境なんて触ったこともない。このテキストを「コンパイル」して.Mファイルにして、それをFM音源エミュレータで鳴らす? 手順が多すぎる。

FMPMD2000というWindows用のPMD再生ソフトがあることは見つけた。2025年4月更新。Win11でも動きそうだ。使おうと思った。

「PMDWin.dllが見つかりません」

即あきらめた。たぶん探せばどこかにあるんだろうけど、めんどくさかった。


いつもの

Claude Codeに丸投げした

あーもういいや。AIにやらせよう。

Claude Codeを開いて、このテキストファイルを渡した。

「これを再生したい」

ここから遠回りが始まった。

MMLソースから音を出すまで

Claude Codeが提案したのは、WSL(Windows Subsystem for Linux)上でpmdminiというCライブラリをビルドするアプローチだった。

pmdmini。PC-98のFM音源ドライバ「PMD」(Professional Music Driver、KAJA氏作)の再生エンジンをCライブラリ化したOSSプロジェクト。内部でYM2608(OPNA)のFM音源をソフトウェアエミュレーションしている。GitHubにある。

Ubuntu上でcloneして、依存関係を解決して、ビルドする。言葉にすると簡単だが、PC-98音源ドライバのエミュレーションライブラリだ。すんなりいくわけがない。

ビルドエラー。依存関係の不足。ヘッダファイルの不整合。Claude Codeと二人三脚でひとつずつ潰していく。人間の部下だったら発狂してる作業量を、AIは淡々とこなす。

ただ、ここでひとつ問題があった。

手元にあるのはMMLのソーステキストであって、コンパイル済みの.Mファイルではない。pmdminiが食えるのは.Mファイルだ。MMLソースをコンパイルして.Mにする工程が別途必要になる。

結論から言うと、Saria LemesのMMLソースの再生は後述する筆者のガバによって苦難の道になった。

MMLをコンパイルして.Mにする環境構築、音色定義の解釈、PMDコンパイラの入手……どれもハードルが高すぎた。しかもClaude Codeは、YM2608のFM合成エンジンをPythonで丸ごと再実装しようとし始めた。pmd_renderer.py、1400行超。FM音源チップのソフトウェアエミュレータを自前で書くという、とんでもない方向に突っ走った。その解析に49分かかっても終わらない。「Imagining...」の表示を延々と眺める。修正を一発入れるだけでも33分。「Cooking...」の表示を延々と眺める。


別プロジェクトでは長くても10分以内なのにこの作業は33分
49分 最長記録


悟った。これは無理だ。

もっと簡単な曲から試すべきだった。いきなりSaria Lemesの複雑なアレンジで挑んだのが間違いだった。

ZUNの.Mファイルで道が開けた

行き詰まっていたとき、方針を変えた。

MMLソースのコンパイルは諦めて、最初からコンパイル済みの.Mファイルを探した。

見つけたのはZUN本人のサイトだった。

https://www16.big.or.jp/~zun/html/pmd.html

ZUNの個人サイトといえば「幻想的音楽」のページが有名だが、実はPMDファイルの配布ページが別にある。ここに東方旧作のBGMが.Mファイルで置いてあった。知る人は少ないかもしれない。

ダウンロードした。タイムスタンプを見た。

1998年10月26日。

28年前のバイナリファイルが、2026年のWindows 11のダウンロードフォルダに入っている。ファイルの中身は、28年前のZUNがPC-98の前に座って打ち込んだFM音源の楽曲データだ。

これをpmd2wavに通した。

鳴った。

YM2608っぽい音がした。「幻樂団の歴史」——ZUNが過去の東方楽曲をアレンジしたCDに収録されているPC-98音源の音と似た音が出ていた。28年前にZUNが打ち込んだ曲が、2026年のWSL上で、pmdminiのソフトウェアエミュレーションを通じて、WAVファイルとして再生された。

デジタル考古学だと思った。

pmdminiの中身はYM2608のFM音源をソフトウェアで再現している。でもあくまで「近似」だ。ヤマハのエンジニアが設計したFM音源チップを、ソフトウェアで模倣している。完全再現ではない。でもその近似で十分だった。

ここから道が開けた。.Mファイルの再生パイプラインが確立したことで、pmd2mml(逆コンパイラ)も使えるようになった。.Mファイルの中身をMMLテキストとして読み出せる。

ただし「逆コンパイル」という言葉には注意が必要だ。

MMLテキストをmc.exe(PMDコンパイラ)でコンパイルすると、人間のための情報は全部捨てられる。コメント、マクロ名、ループ構造、セクション区切り、空白やインデント——全部消える。残るのは「チャンネルごとの命令バイト列」だけ。音符のピッチ、長さ、音色変更、テンポ変更がバイナリで並んでいるだけのデータ。

逆コンパイルで復元できるのは、音程や長さ、音色・音量・テンポの変更命令くらいだ。元のループ構造、マクロ定義、コメント、作者の意図した書き方は戻ってこない。

C言語をコンパイルして.exeにしたあと、逆アセンブルしても元のCソースには戻らないのと同じ理屈だ。機械が実行するのに必要な情報だけが残って、人間が読むための情報は全部捨てられる。

つまりpmd2mmlが出力するMMLは「機械的に復元した楽譜」であって、Saria Lemesが書いた「人間の意図を持ったMML」とは全く違うものになる。

環境は ~/Desktop/pmd-mml-player/ に出来上がった。3つのツールが使える状態になった。

  • pmd2wav — .MファイルをWAVに変換。コマンド一発。

  • pmd2mml — .Mファイル(コンパイル済みバイナリ)をMMLテキストに逆コンパイル。楽譜が読める。

  • pmdmini本体 — PMD再生エンジンのCライブラリ。

この時点では、最初の目的だったSaria LemesのMMLソースの再生にはたどり着けていなかった。pmdminiとは別に、FM合成エンジンを自前でPythonに書かせて再現しようとするアプローチが間違っていた。正規ルート(PMDDotNETでコンパイル)に気づくのはもう少し後の話だ。

でも方針を変えてZUNの.Mファイルを食わせたら道が開けた。遠回りしたおかげで「.Mファイルの再生・変換・逆コンパイル環境」という資産が生まれた。

遠回りで得た資産

整理する。

FMPMD2000のDLLエラーで撤退してClaude Codeに丸投げした結果、今できるようになったのはこの程度だ。

  1. pmd2wavでZUNの.MファイルをWAV化できるようになった — 幻樂団の歴史のCDみたいな音でWAVファイルが出力される。コマンド一発。

  2. pmd2mmlで逆コンパイルできるようになった — ただし前述の通り、復元されるのは機械的な楽譜であって、元のMMLソースとは別物。

  3. WSL上のビルド環境ができた — 今後PC-98関連のツールをビルドする基盤。

この時点ではSaria LemesのMMLソースの再生にはたどり着けていなかった。MMLからの自前WAV生成もガビガビで全然似てなかった。

でも「.Mファイルを渡せばWAVが出てくる環境」がWSL上にある、という事実は残った。そしてこの環境が、のちに正規ルート(mc.exeでのコンパイル)に切り替えたとき、そのまま活きることになる。

読者向け:2つの方法

「自分も.Mファイルを再生したい」という人向けに、2つの方法をまとめておく。

方法1:簡単な方法(FMPMD2000)

所要時間:3分

  1. FMPMD2000をダウンロード・インストール

  2. .Mファイルを開く

  3. 再生ボタンを押す

以上。「とりあえず聴きたいだけ」ならこれが最速。ただし「PMDWin.dllが見つかりません」と出る場合は、ドライバ(DLL)を適切な場所から探してきてください。筆者はここを横着した結果地獄を見ました。また、MMLソーステキスト(.txt)しか手元にない場合は、別途PMDコンパイラでのコンパイルが必要。

方法2:遠回りだけど資産が残る方法(WSL + pmdmini)

所要時間:30分〜1時間

WSL (Ubuntu) が入っている前提。

bash

# 1. 依存パッケージ
sudo apt update
sudo apt install -y build-essential git libsdl2-dev

# 2. pmdminiクローン & ビルド
cd ~/Desktop
git clone https://github.com/mistydemeo/pmdmini.git
cd pmdmini
make

# 3. pmd2wav で .M → WAV変換
./pmd2wav input.M output.wav

# 4. pmd2mml で逆コンパイル(MMLソース復元)
./pmd2mml input.M > output.mml

(※実際のビルド手順は環境により異なる場合があります。上記は概要です)

WAV変換ができれば、ffmpegでMP3にするなり好きにできる。pmd2mmlで逆コンパイルすれば、28年前に打ち込まれたMMLがテキストとして手に入る。

そもそもの正解ルート

ここまで読んで「いや、最初からこうすればよかったのでは」と思った方、その通りです。

筆者の当初の目的は「PastebinにあったMMLソーステキストを音にしたい」だった。正解ルートはこうだったはずだ。

  1. PMDコンパイラを入手する — オリジナルはKAJA氏のmc.exe(DOS用)だが、現代環境ではPMDDotNET(kuma4649氏作、.NET製の互換実装)が使える

  2. MMLテキストを.Mファイルにコンパイルする — MMLソース → .Mバイナリ

  3. FMPMD2000で.Mを再生する(DLLをちゃんと揃えて)、またはpmd2wavでWAV化する

「MMLソース → コンパイラで.Mに変換 → 再生」の3ステップ。

筆者がやったのは、この「コンパイル」の工程を飛ばして、pmdminiで直接どうにかしようとしたことだ。pmdminiは.Mファイルを食う再生エンジンであって、MMLコンパイラではない。そもそも道具の選択が間違っていた。

知識がないとはこういうことだ。

追記:正規ルートでやり直したら一発だった

この記事を書いている途中で、正規ルートを実際に試してみた。

PMDDotNET(PMDコンパイラの.NET互換実装)を入手し、Saria LemesのMMLソーステキストをコンパイルして.Mファイルを生成。それをpmd2wavに通した。

一発できれいな音が出た。

正規ルート導入前は悲惨だった。パートはバラバラ、音は全く似てない、ガビガビ。あれだけ時間をかけて出来上がったのがゴミみたいな音だった。それが正規ルートに切り替えた瞬間、一発でリファレンスに近い音が出た。大革命だった。

音程が低い問題があったが、+2、+3、+4半音のバージョンを作って聴き比べた結果、+4半音(短3度)で完全一致。たぶん鳴らしたかったMMLは原曲から4半音低く書かれていて?、マスタートランスポーズ _M+4 で補正するのが正解だったらしい。知らんけど。

最初にYouTubeで聴いて「この音を自分の環境で鳴らしたい」と思った、あの音がWSLから出てきた。音量が多少違うくらいで、ほぼ同じ音。

あの49分間は何だったのか。

用語集

PMD — Professional Music Driver。KAJA氏作のPC-98用FM音源ドライバ。MMLで書かれた楽曲を.Mファイルにコンパイルして再生する

mc.exe — PMDのオリジナルMMLコンパイラ。DOS用

PMDDotNET — mc.exeの.NET互換実装(kuma4649氏作)。現代のWindows/Linux環境で動く

YM2608 (OPNA) — PC-9801-86サウンドボードに搭載されたFM音源チップ。FM 6ch + SSG 3ch + リズム + ADPCM ヤマハ製

MML — Music Macro Language。テキストで音楽を記述する言語

pmdmini — PMDの再生エンジンをCライブラリ化したOSS。FM音源のソフトウェアエミュレーションを行う

pmd2wav — pmdminiを使って.MファイルをWAVに変換するCLIツール

pmd2mml — .Mファイルをmmlソースに逆コンパイルするツール

FMPMD2000 — Windows用のPMD/FMP再生ソフト。GUIで.Mファイルを開けば即再生

Pastebin — テキスト共有サイト。MMLソースの配布に使われていた

おわりに

Pastebinからテキストファイルが落ちてきて、英語だし意味わかんないからClaude Codeに丸投げして、WSLでCライブラリをビルドして、28年前の.Mファイルで道が開けて、YM2608っぽい音が鳴った。

FMPMD2000で3秒で終わる話を、盛大に遠回りした。

でも、その遠回りのおかげで、.Mファイルを「聴く」だけでなく「変換する」「読む」「理解する」がたぶん?できるようになった。

そして記事を書いている途中で正規ルートを試したら、当初の目的だった東方のMMLアレンジが一発で鳴った。盛大に遠回りした末に、最初の目的地にたどり着いた。

教訓:AIに丸投げする前にフローを作れ

AIコーディング系記事では耳タコ案件かもしれないが反省点がある。
正規ルートに切り替えたら一発で鳴った。ということは、泥沼にハマった本質はAIに丸投げしたことじゃない。何も分からない状態でいきなりAIに投げたことだ。

正解ルートは「MMLソース → mc.exeでコンパイル → .M → 再生」の3ステップだった。これを最初に把握していれば、Claude Codeへの指示も「mc.exeをWSLで動かしてこのMMLをコンパイルして」と具体的にできた。

でも筆者にはPMDの知識がゼロだったので、「このテキストファイルを再生したい」としか言えなかった。Claude Codeは言われた通りにpmdminiをビルドし、さらにFM合成エンジンを自前でPythonで書き始め、49分かけて迷子になった。道具の選択が最初から間違っていた。

AIと協力してプロジェクトを進めるなら、丸投げの前にまず全体のフローを作った方がいい。「入力は何で、出力は何で、間に何が必要か」を人間側で整理してからAIに渡す。でないと、AIは全力で間違った方向に突っ走る。人間が方向を示して、AIが実行する。この順番を守らないと、今回みたいに時間を盛大に無駄にする。

AIは万能じゃない。ただし、正しいルートを与えれば、最短でゴールまで連れていく。正規ルートに切り替えたら一発で鳴ったのがその証拠だ。

実は筆者、全く同じ失敗を前にもやっている。

PS3のホームブリュー開発を始めたとき、PSL1GHT(PS3ホームブリュー用のOSSツールチェイン)の存在を知らなかった。本来は「Cでコードを書いてmakeでビルドする」のが正規の手順だが、ビルド環境の存在自体を知らなかったので、AIにPythonでバイナリパッチを当てさせてSELFファイルを直接生成させようとした。しかもClaude Codeではなくチャットで。

構造が全く同じだ。「ツールチェインの存在を知らない人間がAIに丸投げして、力技で突破しようとする」。PMDでmc.exeを知らなかったのと、PS3でPSL1GHTを知らなかったのは同じ失敗。2回目なのに学んでいない。

デジタル考古学は、遠回りした方が面白い。……でも次こそはもう少し賢く遠回りしたい。3回目はさすがにない。たぶん。

普段はAIがミスるたびに反省の川柳を詠ませている側なのだが、今回ばかりは自分が詠む番だ。

懲りもせず また丸投げの 力技 知らぬまま AIも共に 道迷う 正解は 三歩手前に あったのに 四十九分 画面の向こう まだ考え DLL 見つかりません で全て終わる

田中


いいなと思ったら応援しよう!