[2/2] adpcm: Use the right rounding in the trellis IMA QT encoder

Message ID 1402045390-22418-2-git-send-email-martin@martin.st
State New
Headers show

Commit Message

Martin Storsjö June 6, 2014, 9:03 a.m.
This improves the PSNR of the trellis encodes (previously it was
worse than non-trellis for this codec) of IMA QT. This logic
has to be special cased for the IMA QT encoder though - for IMA WAV
it makes the PSNR slightly worse (but still better than non-trellis),
for ADPCM_YAMAHA it makes it much much worse.
---
Not sure if this is worthwhile, but right now the trellis option
for the IMA QT encoder basically only makes things (slightly)
worse (according to our own decoder).
---
 libavcodec/adpcmenc.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

Patch

diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index 341dda4..ea457ad 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -390,7 +390,6 @@  static void adpcm_compress_trellis(AVCodecContext *avctx,
                                (ff_adpcm_AdaptationTable[nibble] * step) >> 8));
                 }
             } else if (version == AV_CODEC_ID_ADPCM_IMA_WAV ||
-                       version == AV_CODEC_ID_ADPCM_IMA_QT  ||
                        version == AV_CODEC_ID_ADPCM_SWF) {
 #define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\
                 const int predictor = nodes[j]->sample1;\
@@ -410,11 +409,39 @@  static void adpcm_compress_trellis(AVCodecContext *avctx,
                 }
                 LOOP_NODES(ima, ff_adpcm_step_table[step],
                            av_clip(step + ff_adpcm_index_table[nibble], 0, 88));
-            } else { //AV_CODEC_ID_ADPCM_YAMAHA
+            } else if (version == AV_CODEC_ID_ADPCM_YAMAHA) {
                 LOOP_NODES(yamaha, step,
                            av_clip((step * ff_adpcm_yamaha_indexscale[nibble]) >> 8,
                                    127, 24567));
 #undef LOOP_NODES
+            } else if (version == AV_CODEC_ID_ADPCM_IMA_QT) {
+#define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)                        \
+                const int predictor = nodes[j]->sample1;                \
+                const int div = (sample - predictor) * 4 / STEP_TABLE;  \
+                int nmin = av_clip(div - range, -7, 6);                 \
+                int nmax = av_clip(div + range, -6, 7);                 \
+                if (nmin <= 0)                                          \
+                    nmin--; /* distinguish -0 from +0 */                \
+                if (nmax < 0)                                           \
+                    nmax--;                                             \
+                for (nidx = nmin; nidx <= nmax; nidx++) {               \
+                    const int nibble = nidx < 0 ? 7 - nidx : nidx;      \
+                    int stepval = STEP_TABLE, mask, diff = stepval >> 3;\
+                    int dec_sample;                                     \
+                    for (mask = 4; mask;) {                             \
+                        if (nibble & mask)                              \
+                            diff += stepval;                            \
+                        stepval >>= 1;                                  \
+                        mask >>= 1;                                     \
+                    }                                                   \
+                    if (nibble & 8)                                     \
+                        dec_sample = predictor - diff;                  \
+                    else                                                \
+                        dec_sample = predictor + diff;                  \
+                    STORE_NODE(NAME, STEP_INDEX);                       \
+                }
+                LOOP_NODES(ima_qt, ff_adpcm_step_table[step],
+                           av_clip(step + ff_adpcm_index_table[nibble], 0, 88));
 #undef STORE_NODE
             }
         }