ヤマハミュージックデータショップから 購入したSMF(スタンダード・ミディ・ファイル)から歌詞のデータを取り出して 表示してみたいと思います。 歌詞のデータはXFというフォーマットに従ってSMFファイルの中に書き込まれています。 SMFフォーマットほ1991年に決まった仕様です。 こちらのページ からダウンロードできるMIDI1.0規格書の中に記載があります。
一方、XFフォーマットはヤマハの決めた仕様です。
こちらから
ダウンロードできる仕様書は2000年のV2.03となっています。
どちらも古い仕様ですが未だ使われています。
この両方を見ないと、歌詞を読み出すことができません。
SMFファイルはバイナリファイルです。テキストエディタでは開いても内容がわかりません、 バイナリエディタ、例えばvimエディタで開くことで中身が読めます。
> vim -b filename.mid : を押してコマンドモードに入り %!xxd
SMFファイルのいくつかのブロック(チャンクと言う)が書き込まれています。 チャンクの先頭は4つのキャラクタで、その後にチャンクのサイズが入っています。
MThd <length of header data> <header data> MTrk <length of track data> <track data> MTrk <length of track data> <track data> ...
さて、XFデータははMTrkチャンクの後に以下のように入っています。
XFIH <length of XF information header> <information header data> XFKM <length of XF karaoke message> <karaoke message data>
例えば、あるファイルを開いて見ると以下のようになっていました。
歌詞情報はkaraoke messageの中の0xFF 0x05の後に入っています。 karaoke messageは次の順に書き込まれています。 delta-timeは一つ前の歌詞から、ここで定義される歌詞を表示するまでの時間を示しています。
<delta-time> 0xFF 0x05 <length of charactor> text text ...
テキストはShift-JISでエンコードされています。ですので2バイトの文字と、1バイドの文字の場合があります。 次に例を示します。
オレンジ色はdelta-time, 黄色がキャラクタの数、赤文字がテキストです。赤文字の下にデコードした文字を書きます。
歌詞を表示する際、改行などの表示制御用の記号が歌詞のテキストの中に1バイト文字で 書き込まれています。
記号 | 意味 | 内容 |
---|---|---|
"(" ")" | よみがな | かっこ"("および")"で囲まれた文字列は"("の直前の一文字のよみがなを表す |
"[" "]" | ルビ | "["の直前の一文字のよみがなを表す。よみがなと違って通常の読み方とはちがった読み方に使う |
"^" | 空白 | スペースの代わりに用いられる |
"/" | 改行 | 改行コードの代わりに用いられる |
"%" | 副改行 | 一行内での文章の意味的な区切りをあらわす |
"<" | 改頁 | 文字列の先頭に記載、新しいページの先頭から歌詞を表示させる |
">" | タブ | 水平タブを表す |
"\" | バックスラッシュ | その後の1文字を制御機能として扱わない |
XFに記載されている文字はShift-JIS、これをブラウザに表示する時はUTF-8に 変換する必要があります。以下のコードはChat GPTに書いてもらいました。
<script src="https://cdnjs.cloudflare.com/ajax/libs/encoding-japanese/2.0.0/encoding.min.js"></script> <script // Shift-JISのバイナリデータ(Uint8Array)をUTF-8の文字列に変換 function convertShiftJISToUTF8(sjisArrayBuffer) { // ArrayBuffer → Uint8Array に変換 const sjisBytes = new Uint8Array(sjisArrayBuffer); // Shift-JIS → Unicode(内部的にUTF-16)に変換 const unicodeString = Encoding.convert(sjisBytes, { to: 'UNICODE', from: 'SJIS', type: 'string' }); // これで JavaScript の文字列(UTF-8扱い)として使える // console.log(unicodeString); return unicodeString; } </script>
SMFファイルを再生するSMFPlayerに歌詞表示を組み込んでみました。