]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/nellymoserdec.c
fix adpcm ima qt decoding, channel at init is 0, correct stereo out since samples...
[ffmpeg] / libavcodec / nellymoserdec.c
index 7679f25c2cd0b34b01ce2e34ae6ddbac26fd364d..470465d9d285a22ca195d5aba129c608ee3e296b 100644 (file)
@@ -92,18 +92,18 @@ static const int16_t nelly_delta_table[32] = {
 typedef struct NellyMoserDecodeContext {
     AVCodecContext* avctx;
     DECLARE_ALIGNED_16(float,float_buf[NELLY_SAMPLES]);
-    float           state[64];
+    float           state[128];
     AVRandomState   random_state;
     GetBitContext   gb;
     int             add_bias;
-    int             scale_bias;
+    float           scale_bias;
     DSPContext      dsp;
     MDCTContext     imdct_ctx;
     DECLARE_ALIGNED_16(float,imdct_tmp[NELLY_BUF_LEN]);
     DECLARE_ALIGNED_16(float,imdct_out[NELLY_BUF_LEN * 2]);
 } NellyMoserDecodeContext;
 
-DECLARE_ALIGNED_16(float,sine_window[128]);
+static DECLARE_ALIGNED_16(float,sine_window[128]);
 
 static inline int signed_shift(int i, int shift) {
     if (shift > 0)
@@ -111,32 +111,22 @@ static inline int signed_shift(int i, int shift) {
     return i >> -shift;
 }
 
-static void overlap_and_window(NellyMoserDecodeContext *s, float *state, float *audio)
+
+static void overlap_and_window(NellyMoserDecodeContext *s, float *state, float *audio, float *a_in)
 {
-    int bot, mid_up, mid_down, top;
-    float s_bot, s_top;
+    int bot, top;
 
     bot = 0;
     top = NELLY_BUF_LEN-1;
-    mid_up = NELLY_BUF_LEN/2;
-    mid_down = (NELLY_BUF_LEN/2)-1;
-
-    while (bot < NELLY_BUF_LEN/4) {
-        s_bot = audio[bot];
-        s_top = audio[top];
-        audio[bot] =  (audio[mid_up]*sine_window[bot]-state[bot   ]*sine_window[top])/s->scale_bias + s->add_bias;
-        audio[top] = (-state[bot   ]*sine_window[bot]-audio[mid_up]*sine_window[top])/s->scale_bias + s->add_bias;
-        state[bot] =  audio[mid_down];
 
-        audio[mid_down] =  (s_top          *sine_window[mid_down]-state[mid_down]*sine_window[mid_up])/s->scale_bias + s->add_bias;
-        audio[mid_up  ] = (-state[mid_down]*sine_window[mid_down]-s_top          *sine_window[mid_up])/s->scale_bias + s->add_bias;
-        state[mid_down] =  s_bot;
+    while (bot < NELLY_BUF_LEN) {
+        audio[bot] = a_in [bot]*sine_window[bot]
+                    +state[bot]*sine_window[top] + s->add_bias;
 
         bot++;
-        mid_up++;
-        mid_down--;
         top--;
     }
+    memcpy(state, a_in + NELLY_BUF_LEN, sizeof(float)*NELLY_BUF_LEN);
 }
 
 static int sum_bits(short *buf, short shift, short off)
@@ -274,14 +264,13 @@ static void get_sample_bits(const float *buf, int *bits)
     }
 }
 
-void nelly_decode_block(NellyMoserDecodeContext *s, unsigned char block[NELLY_BLOCK_LEN], float audio[NELLY_SAMPLES])
+void nelly_decode_block(NellyMoserDecodeContext *s, const unsigned char block[NELLY_BLOCK_LEN], float audio[NELLY_SAMPLES])
 {
     int i,j;
     float buf[NELLY_FILL_LEN], pows[NELLY_FILL_LEN];
     float *aptr, *bptr, *pptr, val, pval;
     int bits[NELLY_BUF_LEN];
     unsigned char v;
-    float a;
 
     init_get_bits(&s->gb, block, NELLY_BLOCK_LEN * 8);
 
@@ -291,7 +280,7 @@ void nelly_decode_block(NellyMoserDecodeContext *s, unsigned char block[NELLY_BL
     for (i=0 ; i<NELLY_BANDS ; i++) {
         if (i > 0)
             val += nelly_delta_table[get_bits(&s->gb, 5)];
-        pval = pow(2, val/2048);
+        pval = -pow(2, val/2048) * s->scale_bias;
         for (j = 0; j < nelly_band_sizes_table[i]; j++) {
             *bptr++ = val;
             *pptr++ = pval;
@@ -324,16 +313,11 @@ void nelly_decode_block(NellyMoserDecodeContext *s, unsigned char block[NELLY_BL
                                     aptr, s->imdct_tmp);
         /* XXX: overlapping and windowing should be part of a more
            generic imdct function */
-        a = 1.0 / 8.0;
-        for(j = 0; j < NELLY_BUF_LEN / 2; j++) {
-            aptr[j] = s->imdct_out[j + NELLY_BUF_LEN + NELLY_BUF_LEN / 2] * a;
-            aptr[j + NELLY_BUF_LEN / 2] = -s->imdct_out[j] * a;
-        }
-        overlap_and_window(s, s->state, aptr);
+        overlap_and_window(s, s->state, aptr, s->imdct_out);
     }
 }
 
-static int decode_init(AVCodecContext * avctx) {
+static av_cold int decode_init(AVCodecContext * avctx) {
     NellyMoserDecodeContext *s = avctx->priv_data;
     int i;
 
@@ -345,10 +329,10 @@ static int decode_init(AVCodecContext * avctx) {
 
     if(s->dsp.float_to_int16 == ff_float_to_int16_c) {
         s->add_bias = 385;
-        s->scale_bias = 32768;
+        s->scale_bias = 1.0/(8*32768);
     } else {
         s->add_bias = 0;
-        s->scale_bias = 1;
+        s->scale_bias = 1.0/(1*8);
     }
 
     /* Generate overlap window */
@@ -362,7 +346,7 @@ static int decode_init(AVCodecContext * avctx) {
 
 static int decode_tag(AVCodecContext * avctx,
                       void *data, int *data_size,
-                      uint8_t * buf, int buf_size) {
+                      const uint8_t * buf, int buf_size) {
     NellyMoserDecodeContext *s = avctx->priv_data;
     int blocks, i;
     int16_t* samples;
@@ -379,8 +363,10 @@ static int decode_tag(AVCodecContext * avctx,
             blocks = 2; break;
         case 256:   // 22050Hz
             blocks = 4; break;
+        case 512:   // 44100Hz
+            blocks = 8; break;
         default:
-            av_log(avctx, AV_LOG_DEBUG, "Tag size %d unknown, report sample!\n", buf_size);
+            av_log(avctx, AV_LOG_ERROR, "Tag size %d unknown, report sample!\n", buf_size);
             return buf_size;
     }
 
@@ -393,7 +379,7 @@ static int decode_tag(AVCodecContext * avctx,
     return buf_size;
 }
 
-static int decode_end(AVCodecContext * avctx) {
+static av_cold int decode_end(AVCodecContext * avctx) {
     NellyMoserDecodeContext *s = avctx->priv_data;
 
     ff_mdct_end(&s->imdct_ctx);