]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/cook.c
cosmetics: Move one code block to save an #ifdef in the next commit.
[ffmpeg] / libavcodec / cook.c
index 0a219451becd2e193dc80b3558cad82283a60453..32b1081cc27862b2d964eeb683d7ea28f76822c6 100644 (file)
@@ -52,6 +52,7 @@
 #include "dsputil.h"
 #include "common.h"
 #include "bytestream.h"
+#include "random.h"
 
 #include "cookdata.h"
 
@@ -87,7 +88,7 @@ typedef struct {
     int                 bits_per_subpacket;
     int                 cookversion;
     /* states */
-    int                 random_state;
+    AVRandomState       random_state;
 
     /* transform data */
     MDCTContext         mdct_ctx;
@@ -373,22 +374,6 @@ static void decode_envelope(COOKContext *q, int* quant_index_table) {
     }
 }
 
-/**
- * Create the quant value table.
- *
- * @param q                 pointer to the COOKContext
- * @param quant_value_table pointer to the array
- */
-
-static void inline dequant_envelope(COOKContext *q, int* quant_index_table,
-                                    float* quant_value_table){
-
-    int i;
-    for(i=0 ; i < q->total_subbands ; i++){
-        quant_value_table[i] = q->rootpow2tab[quant_index_table[i]+63];
-    }
-}
-
 /**
  * Calculate the category and category_index vector.
  *
@@ -536,46 +521,41 @@ static void inline expand_category(COOKContext *q, int* category,
  *
  * @param q                     pointer to the COOKContext
  * @param index                 index
- * @param band                  current subband
- * @param quant_value_table     pointer to the array
+ * @param quant_index           quantisation index
  * @param subband_coef_index    array of indexes to quant_centroid_tab
- * @param subband_coef_noise    use random noise instead of predetermined value
- * @param mlt_buffer            pointer to the mlt buffer
+ * @param subband_coef_sign     signs of coefficients
+ * @param mlt_p                 pointer into the mlt buffer
  */
 
-
-static void scalar_dequant(COOKContext *q, int index, int band,
-                           float* quant_value_table, int* subband_coef_index,
-                           int* subband_coef_noise, float* mlt_buffer){
+static void scalar_dequant(COOKContext *q, int index, int quant_index,
+                           int* subband_coef_index, int* subband_coef_sign,
+                           float* mlt_p){
     int i;
     float f1;
 
     for(i=0 ; i<SUBBAND_SIZE ; i++) {
         if (subband_coef_index[i]) {
-            if (subband_coef_noise[i]) {
-                f1 = -quant_centroid_tab[index][subband_coef_index[i]];
-            } else {
-                f1 = quant_centroid_tab[index][subband_coef_index[i]];
-            }
+            f1 = quant_centroid_tab[index][subband_coef_index[i]];
+            if (subband_coef_sign[i]) f1 = -f1;
         } else {
-            /* noise coding if subband_coef_noise[i] == 0 */
-            q->random_state = q->random_state * 214013 + 2531011;    //typical RNG numbers
-            f1 = randsign[(q->random_state/0x1000000)&1] * dither_tab[index]; //>>31
+            /* noise coding if subband_coef_index[i] == 0 */
+            f1 = dither_tab[index];
+            if (av_random(&q->random_state) < 0x80000000) f1 = -f1;
         }
-        mlt_buffer[band*20+ i] = f1 * quant_value_table[band];
+        mlt_p[i] = f1 * q->rootpow2tab[quant_index+63];
     }
 }
 /**
- * Unpack the subband_coef_index and subband_coef_noise vectors.
+ * Unpack the subband_coef_index and subband_coef_sign vectors.
  *
  * @param q                     pointer to the COOKContext
  * @param category              pointer to the category array
  * @param subband_coef_index    array of indexes to quant_centroid_tab
- * @param subband_coef_noise    use random noise instead of predetermined value
+ * @param subband_coef_sign     signs of coefficients
  */
 
 static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index,
-                       int* subband_coef_noise) {
+                       int* subband_coef_sign) {
     int i,j;
     int vlc, vd ,tmp, result;
     int ub;
@@ -599,13 +579,13 @@ static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index,
         for(j=0 ; j<vd ; j++){
             if (subband_coef_index[i*vd + j]) {
                 if(get_bits_count(&q->gb) < q->bits_per_subpacket){
-                    subband_coef_noise[i*vd+j] = get_bits1(&q->gb);
+                    subband_coef_sign[i*vd+j] = get_bits1(&q->gb);
                 } else {
                     result=1;
-                    subband_coef_noise[i*vd+j]=0;
+                    subband_coef_sign[i*vd+j]=0;
                 }
             } else {
-                subband_coef_noise[i*vd+j]=0;
+                subband_coef_sign[i*vd+j]=0;
             }
         }
     }
@@ -618,41 +598,42 @@ static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index,
  *
  * @param q                 pointer to the COOKContext
  * @param category          pointer to the category array
- * @param quant_value_table pointer to the array
+ * @param quant_index_table pointer to the array
  * @param mlt_buffer        pointer to mlt coefficients
  */
 
 
 static void decode_vectors(COOKContext* q, int* category,
-                           float* quant_value_table, float* mlt_buffer){
+                           int *quant_index_table, float* mlt_buffer){
     /* A zero in this table means that the subband coefficient is
        random noise coded. */
-    int subband_coef_noise[SUBBAND_SIZE];
+    int subband_coef_index[SUBBAND_SIZE];
     /* A zero in this table means that the subband coefficient is a
        positive multiplicator. */
-    int subband_coef_index[SUBBAND_SIZE];
+    int subband_coef_sign[SUBBAND_SIZE];
     int band, j;
     int index=0;
 
     for(band=0 ; band<q->total_subbands ; band++){
         index = category[band];
         if(category[band] < 7){
-            if(unpack_SQVH(q, category[band], subband_coef_index, subband_coef_noise)){
+            if(unpack_SQVH(q, category[band], subband_coef_index, subband_coef_sign)){
                 index=7;
                 for(j=0 ; j<q->total_subbands ; j++) category[band+j]=7;
             }
         }
         if(index==7) {
             memset(subband_coef_index, 0, sizeof(subband_coef_index));
-            memset(subband_coef_noise, 0, sizeof(subband_coef_noise));
+            memset(subband_coef_sign, 0, sizeof(subband_coef_sign));
         }
-        scalar_dequant(q, index, band, quant_value_table, subband_coef_index,
-                       subband_coef_noise, mlt_buffer);
+        scalar_dequant(q, index, quant_index_table[band],
+                       subband_coef_index, subband_coef_sign,
+                       &mlt_buffer[band * 20]);
     }
 
     if(q->total_subbands*SUBBAND_SIZE >= q->samples_per_channel){
         return;
-    }
+    } /* FIXME: should this be removed, or moved into loop above? */
 }
 
 
@@ -667,47 +648,17 @@ static void decode_vectors(COOKContext* q, int* category,
 static void mono_decode(COOKContext *q, float* mlt_buffer) {
 
     int category_index[128];
-    float quant_value_table[102];
     int quant_index_table[102];
     int category[128];
 
     memset(&category, 0, 128*sizeof(int));
-    memset(&quant_value_table, 0, 102*sizeof(int));
     memset(&category_index, 0, 128*sizeof(int));
 
     decode_envelope(q, quant_index_table);
     q->num_vectors = get_bits(&q->gb,q->log2_numvector_size);
-    dequant_envelope(q, quant_index_table, quant_value_table);
     categorize(q, quant_index_table, category, category_index);
     expand_category(q, category, category_index);
-    decode_vectors(q, category, quant_value_table, mlt_buffer);
-}
-
-
-/**
- * The modulated lapped transform, this takes transform coefficients
- * and transforms them into timedomain samples. This is done through
- * an FFT-based algorithm with pre- and postrotation steps.
- * A window and reorder step is also included.
- *
- * @param q                 pointer to the COOKContext
- * @param inbuffer          pointer to the mltcoefficients
- * @param outbuffer         pointer to the timedomain buffer
- * @param mlt_tmp           pointer to temporary storage space
- */
-
-static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer)
-{
-    int i;
-
-    q->mdct_ctx.fft.imdct_calc(&q->mdct_ctx, outbuffer, inbuffer, q->mdct_tmp);
-
-    for(i = 0; i < q->samples_per_channel; i++){
-        float tmp = outbuffer[i];
-
-        outbuffer[i] = q->mlt_window[i] * outbuffer[q->samples_per_channel + i];
-        outbuffer[q->samples_per_channel + i] = q->mlt_window[q->samples_per_channel - 1 - i] * -tmp;
-    }
+    decode_vectors(q, category, quant_index_table, mlt_buffer);
 }
 
 
@@ -743,36 +694,50 @@ static void interpolate(COOKContext *q, float* buffer,
 
 
 /**
- * mlt overlapping and buffer management
+ * The modulated lapped transform, this takes transform coefficients
+ * and transforms them into timedomain samples.
+ * Apply transform window, overlap buffers, apply gain profile
+ * and buffer management.
  *
  * @param q                 pointer to the COOKContext
+ * @param inbuffer          pointer to the mltcoefficients
  * @param gains_ptr         current and previous gains
  * @param previous_buffer   pointer to the previous buffer to be used for overlapping
  */
 
-static void gain_compensate(COOKContext *q, cook_gains *gains_ptr,
-                            float* previous_buffer)
+static void imlt_gain(COOKContext *q, float *inbuffer,
+                      cook_gains *gains_ptr, float* previous_buffer)
 {
     const float fc = q->pow2tab[gains_ptr->previous[0] + 63];
-    float *buffer = q->mono_mdct_output;
+    float *buffer0 = q->mono_mdct_output;
+    float *buffer1 = q->mono_mdct_output + q->samples_per_channel;
     int i;
 
-    /* Overlap with the previous block. */
-    for(i=0 ; i<q->samples_per_channel ; i++) {
-        buffer[i] *= fc;
-        buffer[i] += previous_buffer[i];
+    /* Inverse modified discrete cosine transform */
+    q->mdct_ctx.fft.imdct_calc(&q->mdct_ctx, q->mono_mdct_output,
+                               inbuffer, q->mdct_tmp);
+
+    /* The weird thing here, is that the two halves of the time domain
+     * buffer are swapped. Also, the newest data, that we save away for
+     * next frame, has the wrong sign. Hence the subtraction below.
+     * Almost sounds like a complex conjugate/reverse data/FFT effect.
+     */
+
+    /* Apply window and overlap */
+    for(i = 0; i < q->samples_per_channel; i++){
+        buffer1[i] = buffer1[i] * fc * q->mlt_window[i] -
+          previous_buffer[i] * q->mlt_window[q->samples_per_channel - 1 - 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],
+            interpolate(q, &buffer1[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,
-           sizeof(float)*q->samples_per_channel);
+    memcpy(previous_buffer, buffer0, sizeof(float)*q->samples_per_channel);
 }
 
 
@@ -902,16 +867,16 @@ mlt_compensate_output(COOKContext *q, float *decode_buffer,
                       cook_gains *gains, float *previous_buffer,
                       int16_t *out, int chan)
 {
+    float *output = q->mono_mdct_output + q->samples_per_channel;
     int j;
 
-    cook_imlt(q, decode_buffer, q->mono_mdct_output);
-    gain_compensate(q, gains, previous_buffer);
+    imlt_gain(q, decode_buffer, gains, previous_buffer);
 
     /* Clip and convert floats to 16 bits.
      */
     for (j = 0; j < q->samples_per_channel; j++) {
         out[chan + q->nb_channels * j] =
-          av_clip(lrintf(q->mono_mdct_output[j]), -32768, 32767);
+          av_clip(lrintf(output[j]), -32768, 32767);
     }
 }
 
@@ -1048,8 +1013,8 @@ static int cook_decode_init(AVCodecContext *avctx)
     q->nb_channels = avctx->channels;
     q->bit_rate = avctx->bit_rate;
 
-    /* Initialize state. */
-    q->random_state = 1;
+    /* Initialize RNG. */
+    av_init_random(1, &q->random_state);
 
     /* Initialize extradata related variables. */
     q->samples_per_channel = q->samples_per_frame / q->nb_channels;