mp3 header 抽出

以下のページを参考に mp3 header の抽出を試みました。

試験対象の MP3 が DefineSound に入っていた時の情報は以下の通り。

[4] tag=DefineSound(14)  length=2505
        sound_id=1
        format=2(MP3) rate=1 is_16bits=1 is_stereo=0 samples_count=11019
        sound_data(length=2498)

実験結果

mp3_filename=../game-1.mp3
mp3_data_len=2498
sync_word=0x7ff
version=0
layer=1
no_protection=1
bit_rate=2
sample_rate=0
padding=0
reserved=0
channel_mode=3
mode_extension=0
copyright=0
original=0
emphasis=0
      • -
sync_word=0x7ff version=2 layer=2 <略>

試しに sync word を scan してみたところ、
一個目の header は正しく抽出されてそう(= Winamp のファイル情報の表示内容と一致した)
ですが、2つ目以降はボロボロ。
header の後ろはある程度 skip する必要があるらしいので、
一応想定通りではあります。さて…

skip 処理を入れてみた

試しに header の後ろを何 byte か skip した所、
いい感じに header が取れました。

while (mp3_dump_frame(bs)) {
//    bitstream_incrpos(bs, 97, 0);  // NG
    bitstream_incrpos(bs, 98, 0); // OK
//    bitstream_incrpos(bs, 100, 0); // OK
}

実行結果

% ./a.out  ../game-1.mp3 | grep version=0 | wc
bitstream_getbit: bs->data_len(2498) <= bs->byte_offset(2498)
     24      24     240

bitstream_getbit の警告は bitstream.c 側の問題なのでご容赦を。(⊃д⊂)

この 98 というのは仮の数字で、
実際は header の内容から frame size を算出して
(frame size - header size 分だけ) skip する必要があるのですが、
mpglib のコード(lame/mpglib/common.c)を見ると、

witch(fr->lay)

 case 1:
           fr->framesize  = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000;
           fr->framesize /= freqs[fr->sampling_frequency];
           fr->framesize  = ((fr->framesize+fr->padding)<<2)-4;
           fr->down_sample=0;
           fr->down_sample_sblimit = SBLIMIT>>(fr->down_sample);
   break;

 case 2:
           fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000;
           fr->framesize /= freqs[fr->sampling_frequency];
           fr->framesize += fr->padding - 4;
           fr->down_sample=0;
           fr->down_sample_sblimit = SBLIMIT>>(fr->down_sample);
   break;
      case 3:
	<略>

なんだか、面倒そうなのでやっぱり自前はやめて mpglib を利用する事にします。(´Д`;)