エピ32 mp3のデコードプログラムはどれでも同じかな
***
エピ32 mp3のデコードプログラムはどれでも同じかな
***
mp3はエンコーダによって音質の違い(こだわり)があるのです。
なので、CDからコピーしたWAVファイルをmp3に変換するとき、エンコーダによってファイルサイズが(多少?)違います。プレーヤーで再生すると音質が違うと分かるそうです(分かる人にはね)。
でもデコーダは、...。仕様・形式が定まっているのですから。
デジタルなデータをデジタルなデータにデコードするのですから同じになるはず。それがデジタルですよね。
これは圧縮ソフトによって圧縮率が違うのと似ていますね。ZIPファイルのサイズは圧縮ソフトにより違う(...コンマ数%の違いかもですが)。でも解凍すると同じファイルになる。1ビットの違いもなくね。当り前のことです。
デコーダのことを確認しましょう。
***
音楽プレーヤは、再生時の音響的な処理(エコライザやボリューム調整)、再生モード(連続、リピート、シャッフル、...)、再生時の画面表示が楽しいとか色々ありますね。
でもデコード用プログラムは、...。mp3をPCMに変換するだけだから。
あ、...でも処理速度は気になるかな。音楽プレーヤから利用するなら実時間で動かないとダメよね。再生中の負荷は軽い方が良いし。
違いがあるとしたらその辺ではないかと予想。
*
まずは ffmpeg です。
ググれば沢山の「使い方」の解説があってね、...。Wiki にもページがありますね。動画も音声も多数のファイル形式をサポート。ffpmeg を利用しているアプリは沢山。VLC も ffpmeg を利用しているんだ。
初版か不明だけど v0.3 が 2000/12/20 リリースで、最新版は 2026/8/4 リリースの v9.0。つい最近ですね。
mp3の実装は、エンコードは lame(libmp3lame)を利用。デコードは独自な実装。v9.0 では libavcodec/mpegaudiodec_template.c の mp_decode_layer3() で実装している。
*
次は lame。
mp3のエンコードが本体だけど(LAME Ain't an MP3 Encoder, LAME)、デコードもできる。
開発は 1998/9 頃から。「the 8hz source code」というコードがあって、これへのパッチとして始まり、1998/10/1 に v1.0 をリリースするも「ISO reference code (dist10)」を改造したものを 1998/10/4 に v2.0 としてリリース。2000/5/8 の 3.81beta にて「all ISO code removed!」。Wiki に書いてある通りですね。
ときどきでてくる Takehiro Tominaga さんって日本人?
最新版は 2026/7/11 リリースの v4.0。その前は 2017/10/13 の v3.100 だったので9年ぶりでした(2026/7/9 に v3.101 と v3.102 があるけど)。...、その9年間にもソースコードの更新は続いていて凄いよ。
mp3のデコードは、3.x までは mpglib/layer3.c の decode_layer3_frame() で実装。元は mpg123 のコードだけど、mpglib として改良を続けていた。アセンブラを使っていないので mpg123 ほど速くはない。
v4.0 では RIP mpglib(...、R.I.P は安らかに眠れ、ね)で、デコードは mpg123(libmpg123)を採用。mp3x って気になるな。
*
mpg123。
mp3プレーヤー。デコード専用。再生中にコンソール操作できる。軽量で高速。CPU 毎にアセンブラで最適化。
開発開始は 1997 年頃みたい。最新版は 2026/8/2 リリースの v1.33.7。古参ね。
デコードの実装は、src/libmpg123/layer3.c の INT123_do_layer3() です。
*
dist10 です。
ISO MPEG Audio サブグループが作成配布した参照実装。WEB で公開されている。初期の lame は lame とは別に dist10 を入手してパッチを当てる形でビルドしていたって。2000 年頃までの話。
Readme ファイルには 1997/01/28 の日付がある。
デコードの実装は lsf/decoder/musicout.c の main() の case 3: にあって、ここから decode.c 内の関数をコールしている。
ここで使している変数や構造体、関数の名前は、他のプログラムに影響を与えてますね。どのプログラムもほぼ同じ名前を使っている。
*
libmad (MAD)
デコーダ。ライブラリだけど、シンプルな使用例(minimad.c)がついている。
浮動小数点演算を使わず、固定小数点(整数)演算のみ。なので組込み系のCPUでも実装し易い(らしい)。多数の音楽プレーヤが利用。...、
README では「MAD is NOT a derivation of the ISO reference source or any other code」と書いている。
開発開始は 2000 年。2004/02/17 リリースの v0.15.1b が最新(と言うか、これが最後)。
20年もメンテナンスがないとね。./configure して make したらエラーメッセージが出る(gcc: error: unrecognized command line option '-fforce-mem'; did you mean '-fforce-addr'?)。Makefile から '-fforce-mem' を削除したらビルドできたけど。...、コンパイラ側の変更があったのが原因。
デコードの実装は layer3.c の III_decode()。
***
ffmpeg は使うとして。エンコードは lame で、デコードは mpg123。この3つが中心かな。
libmad は幾つかの脆弱性(セキュリティ上の問題)が指摘されているけどメンテナンスがないのが不安なんだな。ローカルのみで使うなら関係ないけど。
lame は脆弱性の指摘があったけど v3.100 で修正したし、mpg123 は脆弱性の報告と同時にパッチ提供があるようです。...、だから本当に安全かどうかは分らないけど大丈夫そう。
***
**
*
mp3ファイルを WAV または PCM に変換します。変換方法は各々、次のコマンドで行います。
■ffmpeg-3.4.2-2
ffmpeg -i test.mp3 a.wav
オプション -i で入力ファイル名(mp3ファイル)と、出力ファイル名を与える。出力は WAV 形式なので PCM データを取り出すには 'data' を検索。0x90 番地にある。
■lame3.100.1
./lame --decode test.mp3 a.wav
...まあ、mpg123 と同じかな。'data' は 0x24 番地。先頭をカットしている?
■mpg123-1.34.0
./mpg123 -s test.mp3 >a.bin
オプションの -s で標準出力を選択してリダイレクトしてファイルに保存する。単純な PCM データ。オプションの -w f で WAV ファイルに出力できるみたい。
mpg123 はmp3プレーヤなので通常はスピーカー(デバイス)に出力するのです。
■dist10
./decode test.mp3
これで test.mp3.dec ファイルができる。出力ファイル名を指定することもできるけど。オプションで AIFF ファイルにもできるようです。
出力は PCM だけど、ビックエンディアンなので注意。最初に 384 サンプルの0(384*4 = 1536 バイトの 00h)が入っている。
■libmad-0.15.1b
./minimad <test.mp3 >a.bin
minimad は make でターゲット指定するとビルドする。標準入力と標準出力を使うし、オプション無し。とてもシンプル。普通に PCM。
*
では、PCM(あるいは WAV ファイル)を比較します。
完全一致するよね、...おや? ...、一致しないよ。エラーの最大・最少は、
|libmad|ffmpeg|lame3x|mpg123|dist10|
libmad|--,---|37,-38|37,-38|37,-38|37,-38|
ffmpeg|38,-37|--,---|_2,_-2|_1,_-1|_1,_-1|
lame3x|38,-37|_2,_-2|--,---|_1,_-1|_1,_-1|
mpg123|38,-37|_1,_-1|_1,_-1|--,---|_1,_-1|
dist10|38,-37|_1,_-1|_1,_-1|_1,_-1|--,---|
※ 2026.8.17:libmadの値が間違ってました。訂正します。
※2026.8.18:dist10の値が間違ってました。訂正します。度々申し訳ない。
libmad vs 他は (37,-38) のエラー。
ffmpeg vs lame3x は ±2のエラー。
他の組合せは ±1のエラー。
*
dist10 のエラー (3825, -3823) は何なんだろう? ...、と調べていたら消えてしましまいました。バグなのか? 夏の夜の夢?
*
ISO/IEC 11172 の Part 4 で「compliance tests」を定義しているので、これの真似をします。
評価式は差分の二乗の平均のルート rms (root-mean-square) で、評価結果は三段階あって、
・Fully Compliant : 0.000e-00 〜 8.810e-06
・Limited Accuracy : 8.810e-06 〜 1.410e-04
・Not Compliant : 1.410e-04 〜 ∞
16ビットの整数化する前の実数での差分を求めるようだけど、...PCM 出力を 32768.0 で割って、他との差分を求める。
エラーレートは次の値になりました。
PCM16b |libmad___ |ffmpeg___ |lame3x___ |mpg123___ |dist10___ |
-------+----------+----------+----------+----------+----------+
libmad |--------- |1.910e-04 |1.884e-04 |1.908e-04 |1.908e-04 |
ffmpeg |1.910e-04 |--------- |1.721e-05 |1.530e-05 |1.530e-05 |
lame3x |1.884e-04 |1.721e-05 |--------- |1.411e-05 |1.411e-05 |
mpg123 |1.908e-04 |1.530e-05 |1.411e-05 |--------- |1.251e-06 |
dist10 |1.908e-04 |1.530e-05 |1.411e-05 |1.251e-06 |--------- |
※2026.8.18 バグ?修正
※2026.8.24 32768.0 に変更(libmad vs lame3x が 0.001e-04 減)
dist10 vs mpg123 は Fully Compliant な値です。
libmad は、開発元の評価で ISO/IEC 11172-4 を満たしている(RMS Level: 5.555e-08)ことから、この値は正しい評価になっていないのでしょう。差分の求め方が違うし。
でも波形を比較すると20〜30の差分は多々でている。ビルド環境やコンパイルオプションの指定が悪いかな?
*
*
*
dist10 は特定区間で大きなエラーが出ていました。最初はね。
0.1秒単位で調べると
という感じでした。エラー発生時間の波形を見ると、
のように振幅に差異が。差分を表示すると、
ノイズ的な信号が混入? どこから入った?
デバック文を入れて変数を出力して見たら、エラーはない。それで不思議に思って PCM ファイルを生成し直したら、エラーが消えた。最初の PCM ファイルにはエラーがあるけど、2つ目の PCM ファイルではエラーはない。
デバック文の影響か? うーん、無いとは言えないが。...。
今、分っているのはここまでです。※2026.8.18修正
***
最下位ビットがズレる原因は、...恐らくは実数を16ビットのPCMデータに変換する際の誤差でしょう。プログラムの中を見ないと分かりませんけど。
あ、だとしたらそれをエラーにカウントしてはいけない? ...、汗;
***
**
*
mp3ファイルの中身が気になってきましたね。
実数と整数か。...、あ、実数はアナログではないよ。数学での実数とパソコンの実数も違うし。
***
間違いの指摘とか疑問とか、ご意見・ご感想とかありましたら、どうぞ感想欄に!
***
2026.8.17 バグと誤記の訂正と推敲
2026.8.18 バグ?の修正と推敲
2026.8.21 微推敲
2026.8.24 表の更新と微推敲




