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でも同じだったので、気づいてないのかな?。
メールでもそのうち送るとするかな。