STM32F4を使ったデジタルオーディオプレーヤー / ソフトウエア / MP3


  • 2012.08.07 MP3再生機能追加に対応。
  • 2012.08.25現在 次の MP3 形式に対応している。
    • サンプル周波数
      • HSFタイプの場合 32kHz 44.1kHz 48kHzに対応
      • LSFタイプの場合 16kHz 22.05kHz 24kHz
    • ビットレート
      • ほぼ、全てのビットレートに対応(したつもり)
      • VBR(可変ビットレート)にも対応。
    • 注意:一部のMP3に再生はできるものの、『ジッ』と言う雑音が入るものがある。

MP3再生追加の技術的解説

  • こっから先は、ある意味、単なる苦労話なんだけど、もし、他のCPUとかにMP3再生機能を移植する事があったら、参考になるかもしれないので、記録しておく。

まず、参考になりそうな情報を探した。

  • 参考になりそうなのは、次の雑誌。これらは、ネットでググって見つけた。
    • インターフェース 2005年6月号
    • インターフェース 2010年8月号
    • インターフェース 2010年11月号
    • インターフェース 2010年12月号
    • インターフェース 2011年6月号
  • 既に古い雑誌なので、図書館とかを探した。見つからなかった雑誌もあったが、役に立ったのは、インターフェース 2010年8月号と2010年12月号。

インターフェース 2010年8月号 P102〜を参考に

  • メモリ上に展開されたMP3ファイルをSH-2Aで再生する事を説明した記事。
  • MAD:MPEG Audio Decoder が役に立ちそうな事が判る。
    • FTPからたどって、「libmad-0.15.1b.tar.gz」をダウンロード。
  • ライブラリを展開。
$ cd STM32F4/
$ tar zxvf libmad-0.15.1b.tar.gz

インターフェース 2010年12月号 P183〜を参考に

  • SDカード上のMP3ファイルをSH-2Aで再生する事を説明した記事
    • 最も関連性が高い・・と期待。
      • ところが、そうでも無かったんだよねえ。結果論だけど。
  • この記事に関連するプログラムは、CQ出版からダウンロードできる。
  • 上記のプログラムを展開して調べてみる。
    • mp3p/libmad-0.15.1b/ の中のソースはオリジナルのlibmad-0.15.1b.tar.gzと同じようだ。
    • ただし、frame.c が異なる。下記のように関数「mad_header_decode」の中に「copy_next_header()」や「get_next_frame()」、「read_frame(N)」と言ったトリッキーな関数が入り込んでいる。
      • 関数「mad_header_decode」は、「mad_frame_decode()」や「decoder.c」の「run_sync()」から呼ばれている。「mad_frame_decode()」も「run_sync()」から呼ばれている。「run_sync()」は「mad_decoder_run()」から呼ばれている。
  • mp3p/src/ の中のソースは、新規のものの同じようだ。

libmadだけで、デコードできないか、挑戦。

  • オリジナルのlibmad-0.15.1b.tar.gzのminimad.cの関数「decode()」を見ると
    • mad_decoder_init() で input、output、error の関数を設定し。
    • mad_decoder_run() が本体
    • mad_decoder_finish() で終了・・なだけ。
  • じゃあ、input、output、error を何とかすれば良いだけじゃないの?
  • 方針をlibmad 自体に手を入れること無く、ユーザー定義関数の input、output、error だけで対応する方向にしよう。

2012.07.21〜23。STM32F4 上ではなく、PC上で確認。

  • インターフェース 2010年12月号では、libmad 自体に手を入れていた。しかし、libmad 自体に手を入れること無く、ユーザー定義関数 input だけで、何とかなる事を確認。
    • 最初は、input関数のところで、MP3ファイル全体をメモリ上に全て読み込んで、デコードするテストを行った。
    • 次に、input関数で、ファイルを分割して読みだすテストを行った。
      • この時、インターフェース 2010年12月号の記事だと、1152バイト毎じゃないとデコードしてくれない様に書いてあるが、1フレーム毎でもデコードする事が判った。
  • MP3のファイルのフレーム長は1152バイトじゃなくて、MP3の速度に依存する。テストの結果が次の通り。
速度ヘッダフレーム長備考
123
128kbps0xff0xfb0x90417バイトデコードには+8バイト必要
128kbps0xff0xfb0x92418バイトデコードには+8バイト必要
256kbps0xff0xfb0xd0835バイトデコードには+8バイト必要
256kbps0xff0xfb0xd2836バイトデコードには+8バイト必要
  • http://how.x0.to/MP3on3/main4.html によると、『フレーム長= 144 × ビットレート ÷ サンプリング周波数 (パディングビットが ON なら更に+1)』となるらしい。
  • 従って、次のように計算できる。ちなみに「パディングビット」っていうのは、ヘッダの3バイト目の第2ビットのことね。
速度サンプリング周波数フレーム長パディングビットが ONの時
128kbps44.1kHz417418
192kbps44.1kHz626627
256kbps44.1kHz835836
320kbps44.1kHz10441045
128kbps48kHz384385
192kbps48kHz576577
256kbps48kHz768769
320kbps48kHz960961
  • つまり、関数 input は、読み出される度に、フレームヘッダを読み取り、フレームヘッダからフレーム長+8バイトをメモリ上に取り込めば良いってわけ。フレームの後の8バイトは重なっているから注意ね。
    • フレームヘッダの中に、速度とかサンプリング周波数とかの情報が入っている。この情報の詳細はMP3ファイルの内部構成を見てね。
  • デコードされたデータは、関数 output に渡される。この時こそ、1152個ごとに渡される。ただし、1152個と言っても1152バイトじゃない。16bitのデータがステレオ2ch分ずつ1152個なので、4608バイトずつね。
    • 1152個なのは、HSFの場合のみ。LSFの場合は、半分の576個ずつ渡される。
  • 関数 error は、曲の最後に呼び出されるだけなので、無視しよう。

2012.07.24〜08.03 STM32F4 に移植

  • ここまで行けば、STM32F4 に移植するのも難しくない。
    • 関数 input の方は、FatFs?で読みだすだけだから、大したことない。
    • 関数 output は、I2S 用のリングバッファにデータを渡すだけだ。
  • 簡単な移植の割に時間がかかったのは、途中でロケット飛ばしに行っていたから。
    • 今回は音速超えなかった。ちぇっ。

CPUクロック

  • 当たり前だが、WAVEファイルを演奏するよりもCPU速度を要求する。
    • CPUクロックを 24MHz から 48MHz に上げる必要がある。
    • SDIOのクロックは12.8MHzのままでOK。まあ、読み出し量は、むしろ少ないのだから、当たり前か。

ファイルロード用のバッファ長がラスボスだった。

  • なんでか知らないけど、256kbpsのように SDカードからファイルを読み出すバッファ長が512よりも長いと音楽が乱れる。たぶん、ロードが遅れるんだろうなあ。
  • とにかく訳も分からず、512バイトで分割すると問題は消えた。

で、現状。

  • 一応、手持ちの128kbpsと256kbpsのMP3は、ちゃんと再生できる。
    • それ以外の速度のMP3の再生もできるはず・・・なんだけど、まだ確認していない。ただし、サンプル周波数は、44.1kHzだけで、48kHzは対応していない。いずれ対応するつもりだけど。
      • 2012.08.12 48kHzのMP3ファイルにも対応した。
      • 2012.08.25 16kHz 22.05kHz 24kHz 32kHzのMP3ファイルにも対応した。
    • もし、再生できないMP3ファイルがあったら、教えてください。
  • 音質なんだけど
    • 128kbpsのMP3は、はっきり言って余り良くない。
      • 今まで、アキバで980円くらいで買ったMP3プレーヤーで聞いていた時には余り気にならなかったが、今回作ったデジタルオーディオプレーヤーは、元々音が良いから、とても粗が目立つ。
      • そもそも、libmad の音質が悪いという可能性もゼロではない・・・
    • 256kbpsのMP3だと一応鑑賞に耐える。
      • でも、44.1kHzのWAVEファイルの方が音が良いよ。当たり前だけど・・
  • まあ、一応、役に立つって言うレベルかな?

MP3ファイルの内部構成

内容
ヘッダー部分ID3やRIFF等の種類がある。ヘッダーの無い場合もある。スキップする。
MP3部分libmadへ送る。
テール部分無い場合が多い。無視する。

MP3部分:

位置内容意味
00xffヘッダー
17-4bit1111ヘッダー
3bitMPEG-2 LSF 使用の有無0:LSF extention
1:HSF
2-1bitLayer00:予約済み
01:Layer III
10:Layer II
11:Layer I
0bitProtection_bit0:冗長性・保護付き
1:冗長性・保護無し
27-4bitビットレートHSFの時LSFの時
0000:FreeFormat?0000:FreeFormat?
0001:32kbps0001:8kbps
0010:40kbps0010:16kbps
0011:48kbps0011:24kbps
0100:56kbps0100:32kbps
0101:64kbps0101:40kbps
0110:80kbps0110:48kbps
0111:96kbps0111:56kbps
1000:112kbps1000:64kbps
1001:128kbps1001:80kbps
1010:160kbps1010:96kbps
1011:192kbps1011:112kbps ??
1100:224kbps1100:128kbps
1101:256kbps1101:144kbps
1110:320kbps1110:160kbps
1111:禁止1111:禁止
3-2bitサンプル周波数HSFの時LSFの時
00:44.1kHz22.05kHz
01:48kHz24kHz
10:32kHz16kHz
01:予約済み01:予約済み
1bitPadding_bit0:フレームには追加 slot が含まれない
1:追加の 1 slot を含む
0bit私用未使用
37-6bitMode00:stereo
01:joint stereo
10:dual channel
11:single channel
5-4bitMode_extension
3bitCopyright0:著作権保護なし
1:著作権保護あり
2bitOriginal / copy0:コピー
1:オリジナル
1-0bitEmphasis00:エンファシスなし
01:50/15μs
10:予約
11:ITU-T J.17

フレーム長の計算方法

  • Layer1の場合
    • HSFの時
      • フレーム長= 12 × ビットレート ÷ サンプリング周波数 (パディングビットが ON なら更に+1)
    • LSFの時
      • フレーム長= 12 × ビットレート ÷ (サンプリング周波数 × 2) (パディングビットが ON なら更に+1)
  • Layer2 または Layer3の場合
    • HSFの時
      • フレーム長= 144 × ビットレート ÷ サンプリング周波数 (パディングビットが ON なら更に+1)
    • LSFの時
      • フレーム長= 144 × ビットレート ÷ (サンプリング周波数 × 2) (パディングビットが ON なら更に+1)

プロジェクト


共通



最新の20件

2020-11-14 2014-11-10 2014-08-17 2013-12-23 2013-09-29 2013-08-09 2013-08-07 2013-08-03 2012-11-28 2012-08-25 2012-07-05 2012-07-03 2012-07-01

今日の20件

  • counter: 3614
  • today: 1
  • yesterday: 0
  • online: 1