Commit b3d5a4b0 authored by Baptiste Coudurier's avatar Baptiste Coudurier Committed by Michael Niedermayer

adpcmdec: Fix QT IMA ADPCM decoder

Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 6d6b0c96
...@@ -808,6 +808,32 @@ static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble, ...@@ -808,6 +808,32 @@ static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble,
return (short)c->predictor; return (short)c->predictor;
} }
static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble, int shift)
{
int step_index;
int predictor;
int diff, step;
step = step_table[c->step_index];
step_index = c->step_index + index_table[nibble];
step_index = av_clip(step_index, 0, 88);
diff = step >> 3;
if (nibble & 4) diff += step;
if (nibble & 2) diff += step >> 1;
if (nibble & 1) diff += step >> 2;
if (nibble & 8)
predictor = c->predictor - diff;
else
predictor = c->predictor + diff;
c->predictor = av_clip_int16(predictor);
c->step_index = step_index;
return c->predictor;
}
static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, char nibble) static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, char nibble)
{ {
int predictor; int predictor;
...@@ -1010,35 +1036,41 @@ static int adpcm_decode_frame(AVCodecContext *avctx, ...@@ -1010,35 +1036,41 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
case CODEC_ID_ADPCM_IMA_QT: case CODEC_ID_ADPCM_IMA_QT:
n = buf_size - 2*avctx->channels; n = buf_size - 2*avctx->channels;
for (channel = 0; channel < avctx->channels; channel++) { for (channel = 0; channel < avctx->channels; channel++) {
int16_t predictor;
int step_index;
cs = &(c->status[channel]); cs = &(c->status[channel]);
/* (pppppp) (piiiiiii) */ /* (pppppp) (piiiiiii) */
/* Bits 15-7 are the _top_ 9 bits of the 16-bit initial predictor value */ /* Bits 15-7 are the _top_ 9 bits of the 16-bit initial predictor value */
cs->predictor = (*src++) << 8; predictor = AV_RB16(src);
cs->predictor |= (*src & 0x80); step_index = predictor & 0x7F;
cs->predictor &= 0xFF80; predictor &= 0xFF80;
/* sign extension */ src += 2;
if(cs->predictor & 0x8000)
cs->predictor -= 0x10000; if (cs->step_index == step_index) {
int diff = (int)predictor - cs->predictor;
cs->predictor = av_clip_int16(cs->predictor); if (diff < 0)
diff = - diff;
cs->step_index = (*src++) & 0x7F; if (diff > 0x7f)
goto update;
} else {
update:
cs->step_index = step_index;
cs->predictor = predictor;
}
if (cs->step_index > 88){ if (cs->step_index > 88){
av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n", cs->step_index); av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n", cs->step_index);
cs->step_index = 88; cs->step_index = 88;
} }
cs->step = step_table[cs->step_index];
samples = (short*)data + channel; samples = (short*)data + channel;
for(m=32; n>0 && m>0; n--, m--) { /* in QuickTime, IMA is encoded by chuncks of 34 bytes (=64 samples) */ for(m=32; n>0 && m>0; n--, m--) { /* in QuickTime, IMA is encoded by chuncks of 34 bytes (=64 samples) */
*samples = adpcm_ima_expand_nibble(cs, src[0] & 0x0F, 3); *samples = adpcm_ima_qt_expand_nibble(cs, src[0] & 0x0F, 3);
samples += avctx->channels; samples += avctx->channels;
*samples = adpcm_ima_expand_nibble(cs, src[0] >> 4 , 3); *samples = adpcm_ima_qt_expand_nibble(cs, src[0] >> 4 , 3);
samples += avctx->channels; samples += avctx->channels;
src ++; src ++;
} }
......
3c06fd2f7831e3e8735b936e23ca220c *./tests/data/acodec/adpcm_qt.aiff 019564da45949d0b5278bd75ee9a4ac2 *./tests/data/acodec/adpcm_qt.aiff
281252 ./tests/data/acodec/adpcm_qt.aiff 281252 ./tests/data/acodec/adpcm_qt.aiff
9580492803ba1c1a3746367b24b751c8 *./tests/data/adpcm_ima_qt.acodec.out.wav a7fb054f7bd82270c8fd476eb9f5677c *./tests/data/adpcm_ima_qt.acodec.out.wav
stddev: 914.65 PSNR: 37.10 MAXDIFF:34026 bytes: 1058560/ 1058400 stddev: 920.19 PSNR: 37.05 MAXDIFF:34029 bytes: 1058560/ 1058400
721b51fd66c3bb3dc49dd88d404188eb e178ed520edf2f46492ae740d88f5815
c9e4c21fb62eca34a533f3a9ad2e394a d22be0e193dcbba1068a1ca6ab04cf77
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment