[FFmpeg-cvslog] adpcmenc: fix QT IMA ADPCM encoder

Baptiste Coudurier git at videolan.org
Sat Sep 24 22:46:39 CEST 2011


ffmpeg | branch: master | Baptiste Coudurier <baptiste.coudurier at gmail.com> | Wed Sep  7 22:27:03 2011 -0400| [b304244b54611e9a84e22ab40e94be4a7a474c21] | committer: Justin Ruggles

adpcmenc: fix QT IMA ADPCM encoder

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=b304244b54611e9a84e22ab40e94be4a7a474c21
---

 libavcodec/adpcmenc.c         |   39 +++++++++++++++++++++++++++++++++++----
 tests/ref/acodec/adpcm_ima_qt |    6 +++---
 2 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index ec06284..6295eed 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -164,6 +164,39 @@ static inline unsigned char adpcm_ima_compress_sample(ADPCMChannelStatus *c, sho
     return nibble;
 }
 
+static inline unsigned char adpcm_ima_qt_compress_sample(ADPCMChannelStatus *c, short sample)
+{
+    int delta = sample - c->prev_sample;
+    int mask, step = ff_adpcm_step_table[c->step_index];
+    int diff = step >> 3;
+    int nibble = 0;
+
+    if (delta < 0) {
+        nibble = 8;
+        delta = -delta;
+    }
+
+    for (mask = 4; mask;) {
+        if (delta >= step) {
+            nibble |= mask;
+            delta -= step;
+            diff += step;
+        }
+        step >>= 1;
+        mask >>= 1;
+    }
+
+    if (nibble & 8)
+        c->prev_sample -= diff;
+    else
+        c->prev_sample += diff;
+
+    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;
+}
+
 static inline unsigned char adpcm_ms_compress_sample(ADPCMChannelStatus *c, short sample)
 {
     int predictor, nibble, bias;
@@ -497,16 +530,14 @@ static int adpcm_encode_frame(AVCodecContext *avctx,
                 adpcm_compress_trellis(avctx, samples+ch, buf, &c->status[ch], 64);
                 for(i=0; i<64; i++)
                     put_bits(&pb, 4, buf[i^1]);
-                c->status[ch].prev_sample = c->status[ch].predictor & ~0x7F;
             } else {
                 for (i=0; i<64; i+=2){
                     int t1, t2;
-                    t1 = adpcm_ima_compress_sample(&c->status[ch], samples[avctx->channels*(i+0)+ch]);
-                    t2 = adpcm_ima_compress_sample(&c->status[ch], samples[avctx->channels*(i+1)+ch]);
+                    t1 = adpcm_ima_qt_compress_sample(&c->status[ch], samples[avctx->channels*(i+0)+ch]);
+                    t2 = adpcm_ima_qt_compress_sample(&c->status[ch], samples[avctx->channels*(i+1)+ch]);
                     put_bits(&pb, 4, t2);
                     put_bits(&pb, 4, t1);
                 }
-                c->status[ch].prev_sample &= ~0x7F;
             }
         }
 
diff --git a/tests/ref/acodec/adpcm_ima_qt b/tests/ref/acodec/adpcm_ima_qt
index a91cd2d..cdd60e0 100644
--- a/tests/ref/acodec/adpcm_ima_qt
+++ b/tests/ref/acodec/adpcm_ima_qt
@@ -1,4 +1,4 @@
-019564da45949d0b5278bd75ee9a4ac2 *./tests/data/acodec/adpcm_qt.aiff
+057d27978b35888776512e4e9669a63b *./tests/data/acodec/adpcm_qt.aiff
 281252 ./tests/data/acodec/adpcm_qt.aiff
-a7fb054f7bd82270c8fd476eb9f5677c *./tests/data/adpcm_ima_qt.acodec.out.wav
-stddev:  920.19 PSNR: 37.05 MAXDIFF:34029 bytes:  1058560/  1058400
+3890343c0c20934e014d7ac93f5d65bd *./tests/data/adpcm_ima_qt.acodec.out.wav
+stddev:  918.61 PSNR: 37.07 MAXDIFF:34029 bytes:  1058560/  1058400



More information about the ffmpeg-cvslog mailing list