Rockbox のダーティーハック(複数の値を持つ音楽メタデータへの対応)

本日誕生日のおるみんです。

みなさんは Rockbox というファームウェア/カーネルをご存知でしょうか。 単一メモリ空間,シングルプロセスで動作するファームウェアで,簡単なスレッドスケジューラを備えることによってマルチスレッドで動作可能な, 主にディジタルオーディオプレイヤー(DAP)上で動作するオープンソースファームウェアです。

初期には仏 Archos 製の MP3 プレイヤーに不満を持ったユーザーが homebrew プログラムの動作方法を見つけ,独自実装したのが始まりで韓国 iriver 製 DAP や米 SanDisk の Sansa,東芝の Gigabeat シリーズなど様々な DAP へ porting されています。

わけても初期のSony ネットワークウォークマンや大半の米 Apple iPod シリーズにも対応していることで,2000~2010 年ごろの DAP ユーザー(のごく一部)に広く知られています(広く?)。

Rockbox の場合,iPod の純正 Apple OS と違い Album Artist タグに対応してますし FLAC は再生できますし crossfeed やパラメトリックイコライザ(low-shelf,high-shelf,peaking * 8 の合わせて 10 バンドで Q 値も設定できる)など再生時のパラメータも細かく設定できるため,ギーク向きの良いファームウェアなのですが,不満もあります

何をしたいか

ここまで前置き,本題は Rockbox は意図的に複数の値を持つタグを読み捨ててしまうというところです。

音楽のメタデータは MP3 や AAC に対応する ID3 タグが知られていますが他にも Ogg Vorbis や FLAC に対応する Vorbis Comment,Monkey's Audio に対応する APE tag などが存在します。

ID3 タグの場合は ID3v2.3 だとスラッシュ,ID3v2.4 だとヌル文字を区切り文字にし複数の値を書いていけば良いという仕様がありますが,今回の記事では考えないことにします。今回は FLAC で使われる Vorbis Comment について複数の値に対応する方法を考えてみたいと思います。

Vorbis Comment

Vorbis Comment の細かい仕様は仕様書を見てもらうとして,簡単には次のようになっています。

TITLE=Canned Heat
ALBUM=Synkronized
ARTIST=Jamiroquai
...
<key, value> という構成になっているだけの至極単純なもので,key のほうは大文字小文字を区別しません。 さて,これがどのように複数アーティストに対応するかというと,次のようになります。
TITLE=Yes! Party Time!! (M@STER VERSION)
ALBUM=THE IDOLM@STER CINDERELLA GIRLS VIEWING REVOLUTION Yes! Party Time!!
ARITST=島村卯月(大橋彩香)
ARITST=渋谷凛(福原綾香)
ARITST=本田未央(原紗友里)
ARITST=赤城みりあ(黒沢ともよ)
ARITST=安部菜々(三宅麻理恵)
...
このように同じ key 名の値を複数並べていくだけです。ね,簡単でしょ?

処理をかんがえる

簡単なわけがない。ある key 名が 1 つだけ来るかもしれないし,100000000 コくるかもしれない,それをパーサーは予期できない。 しかも key の名前は推奨されるものはいくつかあるけれども,規格で決まってるわけではない。ID3 タグと違ってかなり自由度の高いメタデータが記述できるのはメリットではありますが,いくら事細かにメタデータを記入したところで読み出し側がちゃんと処理してくれなければ絵に描いた餅です。

さて,Rockbox が動作するプラットフォームは大抵メモリや CPU が貧弱極まりないため(iPod classic はかなり良いほうですね),メモリを潤沢に扱えません。そのため,Vorbis Comment については,同じ key 名が来たら読み捨てる,という手段を取ります。また,読み込んだメタデータについても,ID3 タグを念頭に置いている struct mp3entry という構造体のメンバのひとつである単一の文字配列をバッファとして全てここに読み込んでしまい,この構造体の artist や title といった名前のメンバはそのバッファへのポインタになっています。各タグの間はヌル文字で仕切る,というわけです。(rockbox/lib/rbcodec/metadata/metadata.h#L233 を参照のこと)

しかしならば話はある意味簡単です。いままで読み飛ばしてた処理のところで,読み飛ばさずに追記してしまえば良いのです。

実装

行なった実装は次のとおり。コードはわりと読み易く,改変も簡単なものなので,ものの数分でやりたいことは完了した気がします。この記事を書くほうが時間がかかったぐらいです。 ごらんの通り,以前読んだ key がやってきたら,スラッシュを区切り文字代わりにして新しい値をもうひとつ追記しています。こうすると,例えば複数のアーティストについて,

島村卯月(大橋彩香) / 渋谷凛(福原綾香) / 本田未央(原紗友里) / 赤城みりあ(黒沢ともよ) / 安部菜々(三宅麻理恵)
のように複数の値が 1 つの連結された文字列として格納されるため,結果として複数アーティストがきちんと iPod に表示されるわけです。やったね!

ところで勘の良いかたはお気付きかもしれませんが,この方法だと Vorbis Comment として

ARTIST=CHAGE
TILTE=YAH YAH YAH
ARTIST=ASKA
みたいなメタデータがやってきた場合,おそらく文字列を格納する順番から考えて TITLE の文字列の一部が上書きされてしまい,かなり微妙な読み出し結果になってしまうでしょう。つまりこのパッチはかなり雑なやりかたです。ダーティーハックですね。(ところで CHAGE and ASKA はたぶん ARTIST を分割して複数値にしたりはしないと思うのでこの例はかなり微妙ですね)

ですが良いのです。まともな頭がついてればメタデータを書き込むほうだって同じ key は連続して書くでしょう。少なくとも自分がデータ管理している foobar2000 では ; セミコロンを区切り文字にすれば ID3 タグではスラッシュやヌル文字,Vorbis Comment なら複数 key と欲しいデータをいい感じに書いてくれるみたいなので,たぶん気にしなくても良いはずです。少なくとも自分の環境ではうまくいきました。

何がうれしいの

ぶっちゃけ iPod の表示が欠けてたって何も困らないのですが,Rockbox が last.fm 向けに生成する scrobbler ログに複数アーティストが歌う曲が単独アーティストかのように間抜けに書かれて last.fm にヘンなログが残るのが無くなりました。

そのうち気分転換のコード書きたくなったらやりたいこと

とりあえず複数の値は / 区切りということで読み出してしまったので,Rockbox のデータベース生成のルーチンを書き換えて / 区切りでデータベースの値を生成したら,複数のアーティストが 1 つの文字列に連結されていてもデータベース上は複数の値として扱われるので曲の検索に便利そうです。そしてそれほど難しくないかもしれない。

app/tagcache.cを書き換えればいいのかなあ。まあいつかやりたいですね,いつか……。