mpg123

mpg123-0.65では

configure --with-cpu=generic_nofpu

とするとMakefiles中のCFLAGSに-DREAL_IS_FIXEDと書かれて、整数化マクロが有効になり基本的に整数演算となります。


整数化マクロはmpg123.hに書かれており、

# define real long
# define REAL_RADIX            15
# define REAL_FACTOR           (32.0 * 1024.0)
# define REAL_PLUS_32767       ( 32767 << REAL_RADIX )
# define REAL_MINUS_32768      ( -32768 << REAL_RADIX )
# define DOUBLE_TO_REAL(x)     ((int)((x) * REAL_FACTOR))
# define REAL_TO_SHORT(x)      ((x) >> REAL_RADIX)
# define REAL_MUL(x, y)        (((long long)(x) * (long long)(y)) >> REAL_RADIX)

と、こんな感じで固定少数で符号1bit、実数部16bit、小数部15bitです。


ソースコード中、まずおかしいのがdecode_ntom.cです。
上記マクロのREAL_MULを使わないで掛算してます。
そこを直すだけでも、結構再生出来ます。


しかし、一部の楽曲ではやはりおかしい。
これは探すまでかなり時間が掛かりました。
最近ようやく解ったのですが、layer3.cに問題がありました。

for(i=-256;i<118+4;i++)
    gainpow2[i+256] = DOUBLE_TO_REAL(pow((double)2.0,-0.25 * (double) (i+210)));

ここで、gainpow2はreal型(つまりlong)です。
一見、なんの問題の無いように見えますが・・・値の範囲がおかしい。
固定少数で小数部15bitしかないのに値が小さくなり過ぎです。
ここで作ったgainpow2はgr_info->pow2gainに参照され、

v = gr_info->pow2gain[(*scf++) << shift];

という形になり

*xrpnt = REAL_MUL(-ispow[x], v);

として使用されます。
計算結果は丁度いい大きさになりますが、途中ではかなり小さくなります。


対策として、とりあえずgainpow2に関係する部分は全部floatに戻しました。
音量関係の部分なのでfloatにしてもそんなに重くなりません。


本来であれば全て整数で計算すべく、アルゴリズムを見直すべきなのかもしれません。
しかしアルゴリズムを直すとなると、相当大変です・・・。
本家の方でなんとか直してくれないものか・・・。
最新の0.66でも同じだったので、気づいてないのかな?。
メールでもそのうち送るとするかな。