4-2 BMS形式

ここでは曲ファイルの仕様について説明しています。

■BMS形式とは?

この形式は元祖BM98で仕様化され採用された曲データフォーマットです。
仕様の詳細はBM98のヘルプファイルに詳しく書かれていますが、製作の関係上ここでも説明したいと思います。

BMS内に記述する内容とは、簡単に言うと楽譜をそのまま文字化したものです。
なお、楽譜とは通常1つの楽器に対して記述されるため、この楽譜上の音符は全て同じ楽器の音であり音階が違うだけですが、
BMSでは楽器という概念は無く、1つ1つの音符ごとに自由に音を割り当てられる仕様になっています。
このため、BMS上の音符とはあくまでも音を出すだけの命令であると言えます。
ちなみに楽譜では途中でテンポや拍子の変更が可能ですが、BMSではこれも記述することが出来ます。

BMSファイルはテキストファイルなのでメモ帳で編集することができます。
このため誰でも曲を作ることが出来るという利点があります。
またこの形式は古くから使われているため、インターネットを探せば直ぐに見つけることが出来ます。

さらに最近ではBMSを作成するソフトとしてBMS Creator(他にBMSEGDAC2など)というものもあり、
マウスのクリックでデータを配置できる便利なソフトも公開されています。
これを使えばグラフィカルに直感で曲データを作ることが出来ます。


BMSファイルは特に言語についての規定はありませんが、BMS自体は日本産であるため通常はShiftJIS形式で保存されます。
ただし、最近はいろいろな言語に対応するために、UNICODEやUTF8形式にも対応するよう求められることがあります。
※このサイトでは現状海外は意識せずにShiftJISの読み込みのみに対応します


■基本型

# BMSの実際のコマンド定義です。
#????? という形でコマンドが定義されます。
% オプションの定義です。
%????? という形で定義されます。
この定義は無視しても構いません。
* 行のはじめに書くと、その行はコメントとして無視されます。
なお、行の始めが#%で無ければ、基本的に全てコメント扱いとなるため、
わざわざ*をチェックする必要はありません。
コマンドにはパラメータが付きますが、例えば「#TITLE 魔法つかいプリキュア!」のように、
パラメータは1文字以上のスペースを空けることによって分割されます。



■システムコマンド(ヘッダ)

#PLAYER プレイヤー番号 ビーマニで左側プレイは1、右側プレイは2、新しい仕様ではダブルプレイは3になっているようです。
これはオブジェの配置情報から求めることができるため、この定義を無視しても問題ありません。
#GENRE ジャンル名 日本語でも問題ありませんが文字数はアプリケーションに依存します。
通常は256文字ほどの容量がロードできれば問題無いでしょう。
#TITLE タイトル名
#ARTIST アーティスト名
#BPM 初期のテンポ数 BMSの仕様では最大が255です。
これ以上を指定するにはアプリケーション側が適切に処理をしなければなりません。
なお元祖BM98では整数値でしたがこのサイトのプログラムは小数値も扱えます。
#PLAYLEVEL ゲームの難易度 1~8が一般的ですが、アプリケーションによって数値を変えられます。
これは一般的に画面に難しさを表示するために使用されます。
#RANK 判定の難易度? 通常1~3でタイミングの判定の度合いを指定しますが、
ゲーム側で勝手に決められるので無視してもかまいません。
#VOLWAV マスターボリューム ゲーム全体の音量を定義します。
この値はほとんど使われないので無視しても大丈夫です。
#TOTAL ゲージの増減率 省略時は200%で全てをGREATでクリアしたとき、元ゲージの何%の量になるかの割合。
特に意識してゲージを操作しなくても、アプリ側の難易度で決めてもいいです。
#STAGEFILE データ読み込み時に
表示されるファイル名
ゲームデータのロード中に表示させておく画像ファイルを記述します。
ソフト側の対応によりBMPの他にもPNGやJPGも読み込めるため、特に規定はありません。
※これ以外にも他のBMSプレイヤーで拡張されたコマンドが多数ありますが、ここではひとまず上記のものだけを解析します



■音声データ定義

#WAV?? ファイル名
例)
 #WAV01 ひぐらし.wav
 #WAV02 斧.wav

??はインデックス番号で01~FFまでの値を16進数で定義します。
※新仕様では00は地雷用の音に使用されます

この番号は配列番号として使えるので、ここでは256個の音配列を用意すればよいことになります。
※拡張版ではZZ(36進数)まで定義出来るので、このときは1296個の配列が必要です

ファイル名は通常wavを指定しますが、アプリケーションで他の形式(oggやmp3など)を扱える場合は、
そのファイル名でも問題ありません。



■アニメーションファイル

#BMP?? ファイル名
例)
 #BMP01 お魚咥えたドラ猫.bmp
 #BMP02 追っかけるサザエ.bmp

??には01~FFまでを16進数で定義します。
※BM98では00をミス時の画像としています

この番号も配列番号として使えるので、ここでは256個の画像配列を用意すればよいことになります。
※拡張版ではZZ(36進数)まで定義出来るので、このときは1296個の配列が必要です

ファイル名は通常bmpを指定しますが、アプリケーションで他の形式(pngやjpgなど)を扱える場合は、
そのファイル名でも問題ありません。

なお、BM98では256x256の8bitカラーのビットマップが基本でしたが、
現在のプレイヤーのほとんどは256x256の24bitのフルカラー画像が使用可能です。
※そもそもDirect3Dでは8bitカラーは扱えないため、内部で自動的に24bitなどに変換されます

画像サイズがこのサイズ以外だった場合、画像と画面それぞれ中央上部を原点として表示し、
はみ出た場合はカットするなどの処理が規定されているようですが、
基本的に256x256以外の画像を使わないのが暗黙の了解だったため、
常に256x256に引き伸ばして表示するなど、ソフト側で適当に処理して問題ありません。
 



■メインデータ

1.定義
BMSの曲データ部分は1行を1小節として定義します。
そしてその文字数が小節内の分割数になり、1小節内で連打をするようなところは文字数が多くなります。
書式は以下の通りになります。
#nnncc:dddddddd
nnn 小節番号を必ず3文字の書式で定義します。
ここでは000~999まで指定出来ます。
cc チャンネル番号を2文字の書式で定義します。
BM98では以下のような値が決められています。
01 その位置に来たら自動的に再生されるWAVを指定(BGM再生)
このチャンネルは同一の位置に複数のサウンドを配置することが出来ます。
これによりバスドラやスネア、ハイハットのWAVだけを使ってリズムを作ることも出来ます。
02 指定の小節の長さを定義倍する(小数点可)
#00102:0.5   … 1小節目を2/4拍子に
#00202:0.75  … 2小節目を3/4拍子に

この命令は1小節に1つの定義しか出来ません。
もし複数定義されていた場合は後方を優先します。
例)
 #00102:0.25
 #00102:0.5
 ※1小節目に2つの定義があった場合は後方の0.5が使用される
03 再生テンポの途中変更(1~255を16進数で定義可能)
04 バックグラウンドのアニメーション画像の定義
#BMPnnで指定した番号を使用します。
05 落下してくるオブジェを、別のキャラクターナンバーのものにすり替える機能
06 POORを出したときに表示される画像の変更
07 04で指定したBGAの上にかぶせるBMPを指定(スプライト表示)
8bitや24bit画像の場合は、抜き色(カラーキー)として黒で塗られた部分が
透過されるようになっています。なお、グラフィックボードにより24bitカラーを
16bitカラーに変換する場合など、濃い灰色も黒に変換されることがあり、
意図しない箇所が透過されてしまうという問題があります。
このため黒を表現するには、16bitに変換しても黒にならないような
濃い灰色を選択する必要があります。
10~19 1プレイヤー用の音符データ
音符データは同一の位置に存在してはなりません。
※厳密には存在可能ですが、ゲーム中は1回のキー押しで1つしか判定されないため、
 もう1つの方はミスになってしまいます
20~29 2プレイヤー用の音符データ(1プレイヤー側と仕様は同じ)

拡張版では以下の定義が追加されています。
08 インデックス型テンポ変更
合わせて#BPM??コマンドが追加(#BPMとは別物で続けてインデックスが付くかで判断する必要がある)されており、
先に256個分のテンポバッファに指定のテンポ値を入れておき、データ側にてそのインデックスを指定することで、
指定のタイミングでテンポを変更することが出来ます。
これは03チャンネルでは16進数の上限としてFF(255bpm)までしか定義出来なかったのと、
小数値のテンポチェンジが一切扱えなかったという問題を解決するために追加されました。
※このサイトではこの機能も実装しています
09 ストップシーケンス
一定時間譜面のスクロールを完全に停止させます。
※このサイトではこの機能は実装されません
:(コロン) コマンド部とデータ部の分割用です。
システムコマンドではスペースでしたが、こちらはコロンにて分割する形になっています。
dddddddd 実際のデータとなり文字数は可変となります。
2つの文字列で1つの値を定義します。
このためこの文字数は必ず偶数になります。
例)
 01000200 → 01 00 02 00
ここで気をつけなければならないのは小節番号は0から始まっていることです。
1から始めることも出来ますが、計算上0から始めた方がいいというのはプログラマが一番よく分かっていると思います。

2.サンプル
ここでサンプルを見てみましょう。
#WAV01 BOMB.WAV

#00111:01
まず始めにシステムコマンドとしてWAVコマンドを使用しています。
ここではインデックス
01番目のWAVデータとしてBOMB.WAVというファイルを使用するという意味になります。

そして曲定義部の
00111では上で説明した書式から、1小節目のチャンネル11番にデータを記入しています。
ちなみにチャンネル11番目というのはBM98でいうと左下の白鍵となります。

実データには
01と定義されていますが、この番号はWAVのインデックス番号となるので、
ここでは1小節目の最初にBOMB.WAVを鳴らすという解釈となっています。
画面上では以下のような場所となります。

3.全音符からn分音符
上で説明したサンプルデータではオブジェは1つしか定義しませんでした。
ということはこれは、全音符という1小節まるまる鳴らすという定義になります。

ではn分音符の定義をするにはどうするでしょうか?
順番に考えていきましょう。
まず1小節内に1個とするにはデータを1個(01)を指定しました。
1小節内に2個とするにはデータを2個配置すればいいと言う事ですね。
これを半音符と言いました。

よく耳にする(と思われる)四分音符というのは1小節に4個あるわけなので、
これは4個書けばいい事になります。

そしてこれを踏まえて以下の表にまとめてみました。
名称 データ 文字数
全音符(一分音符) 01 2
二分音符 0101 4
四分音符 01010101 8
八分音符 0101010101010101 16
十六分音符 01010101010101010101010101010101 32
n分音符 0101010101~~~~~~~~~~~~~~~~~~ n*2

これだけ出来ればいいような気もしますが、実は音符にはまだまだ種類があります。
3連符(さんれんぷ)というものを聞いたことがあるでしょうか?
表記的には下のような感じです。



連符は元となる音符を下の数字で割ったものとして定義されるそうですが、
実はBMSではこの表記データも記述することが出来ます。

たとえば下のように四分音符を3つに分割した3連符が1小節の最初に1つあったとします。



これをデータ化するとこうなります。
データ 文字数
010101000000000000000000 24
3連符では1拍あたり3個のデータ(01が3個)になったので、
これを残りの部分に足すことで1小節分のデータを定義出来ることになります。

ちなみに3連符以上のものも存在し、5連符や7連符など1拍内に叩く数が多くなったときは、
そのデータ文字数を4倍することで1小節分のデータにすることが出来ますが、
7連符を定義したとすると、7連x4x2文字で56文字となるので、
細かいデータを定義するほど文字数が増えるということになります。

4.まだまだある表記法
これだけかと思いきや、実はまだまだ音符の定義は存在します。

たとえば付点n分音符です。
付点が付くとその音符の長さの半分をその音符に追加した長さになります。
つまり付点が1つ付くとその音符は1.5倍の長さになります。

実は付点は複数付けることができ、付けるごとにその音符の半分の半分の半分の・・・
長さをすべて足した長さになります。

ややこしいので詳しくは説明しませんが、付点の付いたデータがあった場合、
小節の細かさをその倍にすればいいということです。
たとえば四分音符の文字数を2倍の八分音符にすることで2倍の細かさで定義が出来るので、
これで付点四分音符の長さが定義できます。

なお、BMSは再生開始位置だけを持った仕様であり、その音符の長さ情報は持っていません
このためここでの長さというのは、実際には割り当てた音自体の再生時間であり、
再生時間が次の音符にまたぐような場合でも、特に停止させる必要はありません。


■メインデータの裏技

連符と通常のn分音符が混ざったようなデータはどう定義するでしょうか?

例えば以下のような譜面です。


実はBMSの仕様では同一の小節とチャンネルのデータは複数定義することができ、これらを合成したデータをゲーム内で使用します。
つまりn分音符だけのデータを1行、連符だけのデータを1行、それぞれ2行書いて1つのデータに合成します。
ただし、合成するのはゲーム本体側でやらなければならないので、このようなデータにも対応しなければなりません。

この場合は以下のように、同じチャンネル同じ小節に2つのデータを定義します。

#00111:010101000000010101000000
#00111:0000010100000101


ちなみに頑張ればこれを1行で済ますことも出来ます。
それは3連符と八分音符との最小公倍数を求める方法です。

まず3連符は1小節あたり12個分あることになるので12分音符と表現出来ます。
そしてこの12と8の最小公倍数を求めると結果は24となります。
つまり24分音符として配置していけば1行に収めることが出来ます。

以下は24部音符(48文字)で定義した場合の例です。

#00111:010001000100010000010000010001000100010000010000

赤時は3連符部分、青字は八分音符部分となります



■応用

BMSは以上のような構成により、ほぼすべての曲データに対応できるという優れた能力を持っています。

この原理が理解できれば他の音ゲーにも流用することが出来るし、 また解析後のデータを独自のバイナリ形式などで保存すれば、
BMSが使われた形跡を残さないようにすることも出来ます。