ADPCMのデコードはほぼできた。次はエンコード。
いろんなソース見とるが、予測時に分岐しまくるのやばくね?とおもってたらそのとおりで、ffmpeg実装は乗算を使ってる:
static inline int16_t adpcm_ima_expand_nibble(ADPCMChannelStatus *c, int8_t nibble, int shift)
{
int step_index;
int predictor;
int sign, delta, diff, step;
step = ff_adpcm_step_table[c->step_index];
step_index = c->step_index + ff_adpcm_index_table[(unsigned)nibble];
step_index = av_clip(step_index, 0, 88);
sign = nibble & 8;
delta = nibble & 7;
/* perform direct multiplication instead of series of jumps proposed by
* the reference ADPCM implementation since modern CPUs can do the mults
* quickly enough */
diff = ((2 * delta + 1) * step) >> shift;
predictor = c->predictor;
if (sign) predictor -= diff;
else predictor += diff;
c->predictor = av_clip_int16(predictor);
c->step_index = step_index;
return (int16_t)c->predictor;
}
static inline uint8_t adpcm_ima_compress_sample(ADPCMChannelStatus *c,
int16_t sample)
{
int delta = sample - c->prev_sample;
int nibble = FFMIN(7, abs(delta) * 4 /
ff_adpcm_step_table[c->step_index]) + (delta < 0) * 8;
c->prev_sample += ((ff_adpcm_step_table[c->step_index] *
ff_adpcm_yamaha_difflookup[nibble]) / 8);
c->prev_sample = av_clip_int16(c->prev_sample);
c->step_index = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88);
return nibble;
}
nibbleってなんだよ・・・って思って調べたら1/2バイト(4bit)のことだった。
デコーダ作って安定させてたら、AudacityとffmpegのADPCM(IMA)のデコード結果が違うことに気付く。 原因は、Audacityを始めとした多くのコーデックでは分岐が多い近似実装になっているからだった。 こいつ が原因か。 一方、ffmpegは近頃のCPUは十分乗算が早いからと言う理由で厳密計算している。ということで自分も厳密計算を選ぶ。
もう一点、AudacityにADPCM(IMA)を突っ込むと末尾が伸びてしまう。これは末尾のブロックも同一サンプル数でデコードしているから…。 あきらかな不具合。PR送るか、送らざるべきか…。
Audacityは内部でlibsndfileを使ってるから、 こっち にPRを送るべき。