[FFmpeg-soc] [soc]: r3561 - mlp/mlpenc.c

ramiro subversion at mplayerhq.hu
Sat Aug 23 17:39:26 CEST 2008


Author: ramiro
Date: Sat Aug 23 17:39:25 2008
New Revision: 3561

Log:
Simple stereo decorrelation (mostly copied from alacenc.c).

Modified:
   mlp/mlpenc.c

Modified: mlp/mlpenc.c
==============================================================================
--- mlp/mlpenc.c	(original)
+++ mlp/mlpenc.c	Sat Aug 23 17:39:25 2008
@@ -49,7 +49,8 @@ typedef struct {
     uint8_t         count;                  ///< number of matrices to apply
 
     uint8_t         outch[MAX_MATRICES];    ///< output channel for each matrix
-    int32_t         coeff[MAX_MATRICES][MAX_CHANNELS+2];
+    int32_t         forco[MAX_MATRICES][MAX_CHANNELS+2];    ///< forward coefficients
+    int32_t         coeff[MAX_MATRICES][MAX_CHANNELS+2];    ///< decoding coefficients
     uint8_t         fbits[MAX_CHANNELS];    ///< fraction bits
 
     int8_t          shift[MAX_CHANNELS];    ///< Left shift to apply to decoded PCM values to get final 24-bit output.
@@ -881,6 +882,40 @@ static void generate_2_noise_channels(ML
     rh->noisegen_seed = seed & ((1 << 24)-1);
 }
 
+#define MLP_CHMODE_LEFT_RIGHT   0
+#define MLP_CHMODE_LEFT_SIDE    1
+#define MLP_CHMODE_RIGHT_SIDE   2
+#define MLP_CHMODE_MID_SIDE     3
+
+static int estimate_stereo_mode(MLPEncodeContext *ctx)
+{
+    uint64_t score[4], sum[4] = { 0, 0, 0, 0, };
+    int32_t *right_ch = ctx->sample_buffer + 1;
+    int32_t *left_ch  = ctx->sample_buffer;
+    int i, best = 0;
+
+    for(i = 2; i < ctx->major_frame_size; i++) {
+        int32_t left  = left_ch [i * ctx->num_channels] - 2 * left_ch [(i - 1) * ctx->num_channels] + left_ch [(i - 2) * ctx->num_channels];
+        int32_t right = right_ch[i * ctx->num_channels] - 2 * right_ch[(i - 1) * ctx->num_channels] + right_ch[(i - 2) * ctx->num_channels];
+
+        sum[0] += FFABS( left        );
+        sum[1] += FFABS(        right);
+        sum[2] += FFABS((left + right) >> 1);
+        sum[3] += FFABS( left - right);
+    }
+
+    score[0] = sum[0] + sum[1];
+    score[1] = sum[0] + sum[3];
+    score[2] = sum[1] + sum[3];
+    score[3] = sum[2] + sum[3];
+
+    for(i = 1; i < 4; i++)
+        if(score[i] < score[best])
+            best = i;
+
+    return best;
+}
+
 /** Determines how many fractional bits are needed to encode matrix
  *  coefficients. Also shifts the coefficients to fit within 2.14 bits.
  */
@@ -908,8 +943,10 @@ static void code_matrix_coeffs(MLPEncode
     shift = FFMAX(0, FFMAX(number_sbits(min), number_sbits(max)) - 16);
 
     if (shift) {
-        for (channel = 0; channel < ctx->num_channels; channel++)
+        for (channel = 0; channel < ctx->num_channels; channel++) {
             mp->coeff[mat][channel] >>= shift;
+            mp->forco[mat][channel] >>= shift;
+        }
 
         coeff_mask >>= shift;
     }
@@ -927,6 +964,7 @@ static void lossless_matrix_coeffs(MLPEn
 {
     DecodingParams *dp = ctx->cur_decoding_params;
     MatrixParams *mp = &dp->matrix_params;
+    int mode, mat;
 
     /* No decorrelation for mono. */
     if (ctx->num_channels - 2 == 1) {
@@ -936,17 +974,48 @@ static void lossless_matrix_coeffs(MLPEn
 
     generate_2_noise_channels(ctx);
 
-    /* TODO actual decorrelation. */
-
-    mp->count    = 1;
-    mp->outch[0] = 1;
+    mode = estimate_stereo_mode(ctx);
 
-    mp->coeff[0][0] =  1 << 14;
-    mp->coeff[0][1] = -1 << 14;
-    mp->coeff[0][2] =  0 << 14;
-    mp->coeff[0][3] =  0 << 14;
+    switch(mode) {
+        case MLP_CHMODE_MID_SIDE:
+        case MLP_CHMODE_LEFT_RIGHT:
+            mp->count    = 0;
+            break;
+        case MLP_CHMODE_LEFT_SIDE:
+            mp->count    = 1;
+            mp->outch[0] = 0;
+            mp->coeff[0][0] =  1 << 14; mp->coeff[0][1] =  1 << 14;
+            mp->coeff[0][2] =  0 << 14; mp->coeff[0][2] =  0 << 14;
+            mp->forco[0][0] =  1 << 14; mp->forco[0][1] = -1 << 14;
+            mp->forco[0][2] =  0 << 14; mp->forco[0][2] =  0 << 14;
+            break;
+        case MLP_CHMODE_RIGHT_SIDE:
+            mp->count    = 1;
+            mp->outch[0] = 1;
+            mp->coeff[0][0] =  1 << 14; mp->coeff[0][1] = -1 << 14;
+            mp->coeff[0][2] =  0 << 14; mp->coeff[0][2] =  0 << 14;
+            mp->forco[0][0] =  1 << 14; mp->forco[0][1] = -1 << 14;
+            mp->forco[0][2] =  0 << 14; mp->forco[0][2] =  0 << 14;
+            break;
+#if 0 /* TODO shift all matrix coeffs if any matrix needs it. */
+        case MLP_CHMODE_MID_SIDE:
+            mp->count    = 2;
+            mp->outch[0] = 0;
+            mp->coeff[0][0] =  1 << 13; mp->coeff[0][1] =  1 << 14;
+            mp->coeff[0][2] =  0 << 14; mp->coeff[0][2] =  0 << 14;
+            mp->forco[0][0] =  1 << 14; mp->forco[0][1] = -1 << 14;
+            mp->forco[0][2] =  0 << 14; mp->forco[0][2] =  0 << 14;
+            mp->outch[1] = 1;
+            mp->coeff[1][0] = -1 << 14; mp->coeff[1][1] =  1 << 15;
+            mp->coeff[1][2] =  0 << 14; mp->coeff[1][2] =  0 << 14;
+            mp->forco[1][0] =  1 << 13; mp->forco[1][1] =  1 << 14;
+            mp->forco[1][2] =  0 << 14; mp->forco[1][2] =  0 << 14;
+            break;
+#endif
+    }
 
-    code_matrix_coeffs(ctx, 0);
+    for (mat = 0; mat < mp->count; mat++)
+        code_matrix_coeffs(ctx, mat);
 }
 
 /** Applies output_shift to all channels when it is needed because of shifted
@@ -992,7 +1061,7 @@ static void rematrix_channels(MLPEncodeC
 
             for (src_ch = 0; src_ch < maxchan; src_ch++) {
                 int32_t sample = *(sample_buffer + src_ch);
-                accum += (int64_t) sample * mp->coeff[mat][src_ch];
+                accum += (int64_t) sample * mp->forco[mat][src_ch];
             }
             sample_buffer[outch] = (accum >> 14) & mask;
 



More information about the FFmpeg-soc mailing list