Simplify gain block handling.
authorIan Braithwaite <ian@braithwaite.dk>
Thu, 8 Mar 2007 20:43:51 +0000 (20:43 +0000)
committerBenjamin Larsson <banan@ludd.ltu.se>
Thu, 8 Mar 2007 20:43:51 +0000 (20:43 +0000)
Patch by Ian Braithwaite <ian at braithwaite dot dk>

Originally committed as revision 8298 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/cook.c

index 07655b0..0bc9719 100644 (file)
 //#define COOKDEBUG
 
 typedef struct {
 //#define COOKDEBUG
 
 typedef struct {
-    int     size;
-    int     loccode[8];
-    int     levcode[8];
-} COOKgain;
+    int *now;
+    int *previous;
+} cook_gains;
 
 typedef struct {
     GetBitContext       gb;
 
 typedef struct {
     GetBitContext       gb;
@@ -102,12 +101,12 @@ typedef struct {
     int                 mlt_size;       //modulated lapped transform size
 
     /* gain buffers */
     int                 mlt_size;       //modulated lapped transform size
 
     /* gain buffers */
-    COOKgain            *gain_ptr1[2];
-    COOKgain            *gain_ptr2[2];
-    COOKgain            gain_1;
-    COOKgain            gain_2;
-    COOKgain            gain_3;
-    COOKgain            gain_4;
+    cook_gains          gains1;
+    cook_gains          gains2;
+    int                 gain_1[9];
+    int                 gain_2[9];
+    int                 gain_3[9];
+    int                 gain_4[9];
 
     /* VLC data */
     int                 js_vlc_bits;
 
     /* VLC data */
     int                 js_vlc_bits;
@@ -339,29 +338,27 @@ static int cook_decode_close(AVCodecContext *avctx)
 }
 
 /**
 }
 
 /**
- * Fill the COOKgain structure for the timedomain quantization.
+ * Fill the gain array for the timedomain quantization.
  *
  * @param q                 pointer to the COOKContext
  *
  * @param q                 pointer to the COOKContext
- * @param gaininfo          pointer to the COOKgain
+ * @param gaininfo[9]       array of gain indices
  */
 
  */
 
-static void decode_gain_info(GetBitContext *gb, COOKgain* gaininfo) {
-    int i;
+static void decode_gain_info(GetBitContext *gb, int *gaininfo)
+{
+    int i, n;
 
     while (get_bits1(gb)) {}
 
     while (get_bits1(gb)) {}
+    n = get_bits_count(gb) - 1;     //amount of elements*2 to update
 
 
-    gaininfo->size = get_bits_count(gb) - 1;     //amount of elements*2 to update
+    i = 0;
+    while (n--) {
+        int index = get_bits(gb, 3);
+        int gain = get_bits1(gb) ? get_bits(gb, 4) - 7 : -1;
 
 
-    if (get_bits_count(gb) - 1 <= 0) return;
-
-    for (i=0 ; i<gaininfo->size ; i++){
-        gaininfo->loccode[i] = get_bits(gb,3);
-        if (get_bits1(gb)) {
-            gaininfo->levcode[i] = get_bits(gb,4) - 7;  //convert to signed
-        } else {
-            gaininfo->levcode[i] = -1;
-        }
+        while (i <= index) gaininfo[i++] = gain;
     }
     }
+    while (i <= 8) gaininfo[i++] = 0;
 }
 
 /**
 }
 
 /**
@@ -784,77 +781,34 @@ static void interpolate(COOKContext *q, float* buffer,
     }
 }
 
     }
 }
 
-/**
- * timedomain requantization of the timedomain samples
- *
- * @param q                 pointer to the COOKContext
- * @param buffer            pointer to the timedomain buffer
- * @param gain_now          current gain structure
- * @param gain_previous     previous gain structure
- */
-
-static void gain_window(COOKContext *q, float* buffer, COOKgain* gain_now,
-                        COOKgain* gain_previous){
-    int i, index;
-    int gain_index[9];
-    int tmp_gain_index;
-
-    gain_index[8]=0;
-    index = gain_previous->size;
-    for (i=7 ; i>=0 ; i--) {
-        if(index && gain_previous->loccode[index-1]==i) {
-            gain_index[i] = gain_previous->levcode[index-1];
-            index--;
-        } else {
-            gain_index[i]=gain_index[i+1];
-        }
-    }
-    /* This is applied to the to be previous data buffer. */
-    for(i=0;i<8;i++){
-        interpolate(q, &buffer[q->samples_per_channel+q->gain_size_factor*i],
-                    gain_index[i], gain_index[i+1]);
-    }
-
-    tmp_gain_index = gain_index[0];
-    index = gain_now->size;
-    for (i=7 ; i>=0 ; i--) {
-        if(index && gain_now->loccode[index-1]==i) {
-            gain_index[i]= gain_now->levcode[index-1];
-            index--;
-        } else {
-            gain_index[i]=gain_index[i+1];
-        }
-    }
-
-    /* This is applied to the to be current block. */
-    for(i=0;i<8;i++){
-        interpolate(q, &buffer[i*q->gain_size_factor],
-                    tmp_gain_index+gain_index[i],
-                    tmp_gain_index+gain_index[i+1]);
-    }
-}
-
 
 /**
  * mlt overlapping and buffer management
  *
  * @param q                 pointer to the COOKContext
 
 /**
  * mlt overlapping and buffer management
  *
  * @param q                 pointer to the COOKContext
- * @param buffer            pointer to the timedomain buffer
- * @param gain_now          current gain structure
- * @param gain_previous     previous gain structure
+ * @param gains_ptr         current and previous gains
  * @param previous_buffer   pointer to the previous buffer to be used for overlapping
  * @param previous_buffer   pointer to the previous buffer to be used for overlapping
- *
  */
 
  */
 
-static void gain_compensate(COOKContext *q, float* buffer, COOKgain* gain_now,
-                            COOKgain* gain_previous, float* previous_buffer) {
+static void gain_compensate(COOKContext *q, cook_gains *gains_ptr,
+                            float* previous_buffer)
+{
+    const float fc = q->pow2tab[gains_ptr->previous[0] + 63];
+    float *buffer = q->mono_mdct_output;
     int i;
     int i;
-    if((gain_now->size  || gain_previous->size)) {
-        gain_window(q, buffer, gain_now, gain_previous);
-    }
 
     /* Overlap with the previous block. */
 
     /* Overlap with the previous block. */
-    for(i=0 ; i<q->samples_per_channel ; i++) buffer[i]+=previous_buffer[i];
+    for(i=0 ; i<q->samples_per_channel ; i++) {
+        buffer[i] *= fc;
+        buffer[i] += previous_buffer[i];
+    }
+
+    /* Apply gain profile */
+    for (i = 0; i < 8; i++) {
+        if (gains_ptr->now[i] || gains_ptr->now[i + 1])
+            interpolate(q, &buffer[q->gain_size_factor * i],
+                        gains_ptr->now[i], gains_ptr->now[i + 1]);
+    }
 
     /* Save away the current to be previous block. */
     memcpy(previous_buffer, buffer+q->samples_per_channel,
 
     /* Save away the current to be previous block. */
     memcpy(previous_buffer, buffer+q->samples_per_channel,
@@ -956,7 +910,7 @@ static void joint_decode(COOKContext *q, float* mlt_buffer1,
 
 static inline void
 decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer,
 
 static inline void
 decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer,
-                      COOKgain *gain_ptr[])
+                      cook_gains *gains_ptr)
 {
     int offset;
 
 {
     int offset;
 
@@ -964,10 +918,10 @@ decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer,
                           q->bits_per_subpacket/8);
     init_get_bits(&q->gb, q->decoded_bytes_buffer + offset,
                   q->bits_per_subpacket);
                           q->bits_per_subpacket/8);
     init_get_bits(&q->gb, q->decoded_bytes_buffer + offset,
                   q->bits_per_subpacket);
-    decode_gain_info(&q->gb, gain_ptr[0]);
+    decode_gain_info(&q->gb, gains_ptr->now);
 
     /* Swap current and previous gains */
 
     /* Swap current and previous gains */
-    FFSWAP(COOKgain *, gain_ptr[0], gain_ptr[1]);
+    FFSWAP(int *, gains_ptr->now, gains_ptr->previous);
 }
 
 /**
 }
 
 /**
@@ -985,14 +939,13 @@ decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer,
 
 static inline void
 mlt_compensate_output(COOKContext *q, float *decode_buffer,
 
 static inline void
 mlt_compensate_output(COOKContext *q, float *decode_buffer,
-                      COOKgain *gain_ptr[], float *previous_buffer,
+                      cook_gains *gains, float *previous_buffer,
                       int16_t *out, int chan)
 {
     int j;
 
     cook_imlt(q, decode_buffer, q->mono_mdct_output, q->mlt_tmp);
                       int16_t *out, int chan)
 {
     int j;
 
     cook_imlt(q, decode_buffer, q->mono_mdct_output, q->mlt_tmp);
-    gain_compensate(q, q->mono_mdct_output, gain_ptr[0],
-                    gain_ptr[1], previous_buffer);
+    gain_compensate(q, gains, previous_buffer);
 
     /* Clip and convert floats to 16 bits.
      */
 
     /* Clip and convert floats to 16 bits.
      */
@@ -1022,7 +975,7 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer,
 //    }
 //    av_log(NULL, AV_LOG_ERROR, "\n");
 
 //    }
 //    av_log(NULL, AV_LOG_ERROR, "\n");
 
-    decode_bytes_and_gain(q, inbuffer, q->gain_ptr1);
+    decode_bytes_and_gain(q, inbuffer, &q->gains1);
 
     if (q->joint_stereo) {
         joint_decode(q, q->decode_buffer_1, q->decode_buffer_2);
 
     if (q->joint_stereo) {
         joint_decode(q, q->decode_buffer_1, q->decode_buffer_2);
@@ -1030,21 +983,20 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer,
         mono_decode(q, q->decode_buffer_1);
 
         if (q->nb_channels == 2) {
         mono_decode(q, q->decode_buffer_1);
 
         if (q->nb_channels == 2) {
-            decode_bytes_and_gain(q, inbuffer + sub_packet_size/2,
-                                  q->gain_ptr2);
+            decode_bytes_and_gain(q, inbuffer + sub_packet_size/2, &q->gains2);
             mono_decode(q, q->decode_buffer_2);
         }
     }
 
             mono_decode(q, q->decode_buffer_2);
         }
     }
 
-    mlt_compensate_output(q, q->decode_buffer_1, q->gain_ptr1,
+    mlt_compensate_output(q, q->decode_buffer_1, &q->gains1,
                           q->mono_previous_buffer1, outbuffer, 0);
 
     if (q->nb_channels == 2) {
         if (q->joint_stereo) {
                           q->mono_previous_buffer1, outbuffer, 0);
 
     if (q->nb_channels == 2) {
         if (q->joint_stereo) {
-            mlt_compensate_output(q, q->decode_buffer_2, q->gain_ptr1,
+            mlt_compensate_output(q, q->decode_buffer_2, &q->gains1,
                                   q->mono_previous_buffer2, outbuffer, 1);
         } else {
                                   q->mono_previous_buffer2, outbuffer, 1);
         } else {
-            mlt_compensate_output(q, q->decode_buffer_2, q->gain_ptr2,
+            mlt_compensate_output(q, q->decode_buffer_2, &q->gains2,
                                   q->mono_previous_buffer2, outbuffer, 1);
         }
     }
                                   q->mono_previous_buffer2, outbuffer, 1);
         }
     }
@@ -1225,10 +1177,10 @@ static int cook_decode_init(AVCodecContext *avctx)
     if (q->decoded_bytes_buffer == NULL)
         return -1;
 
     if (q->decoded_bytes_buffer == NULL)
         return -1;
 
-    q->gain_ptr1[0] = &q->gain_1;
-    q->gain_ptr1[1] = &q->gain_2;
-    q->gain_ptr2[0] = &q->gain_3;
-    q->gain_ptr2[1] = &q->gain_4;
+    q->gains1.now      = q->gain_1;
+    q->gains1.previous = q->gain_2;
+    q->gains2.now      = q->gain_3;
+    q->gains2.previous = q->gain_4;
 
     /* Initialize transform. */
     if ( init_cook_mlt(q) == 0 )
 
     /* Initialize transform. */
     if ( init_cook_mlt(q) == 0 )