[FFmpeg-cvslog] r14719 - in trunk/libavcodec: ac3dec.c ac3dec.h

lorenm subversion
Wed Aug 13 01:45:46 CEST 2008


Author: lorenm
Date: Wed Aug 13 01:45:46 2008
New Revision: 14719

Log:
optimize ac3_downmix.
1.3x faster 5.1->stereo, 1.9x faster 5.1->mono.


Modified:
   trunk/libavcodec/ac3dec.c
   trunk/libavcodec/ac3dec.h

Modified: trunk/libavcodec/ac3dec.c
==============================================================================
--- trunk/libavcodec/ac3dec.c	(original)
+++ trunk/libavcodec/ac3dec.c	Wed Aug 13 01:45:46 2008
@@ -321,6 +321,7 @@ static void set_downmix_coeffs(AC3Decode
     int i;
     float cmix = gain_levels[center_levels[s->center_mix_level]];
     float smix = gain_levels[surround_levels[s->surround_mix_level]];
+    float norm0, norm1;
 
     for(i=0; i<s->fbw_channels; i++) {
         s->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]];
@@ -338,14 +339,23 @@ static void set_downmix_coeffs(AC3Decode
         s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix;
     }
 
-    /* calculate adjustment needed for each channel to avoid clipping */
-    s->downmix_coeff_adjust[0] = s->downmix_coeff_adjust[1] = 0.0f;
+    /* renormalize */
+    norm0 = norm1 = 0.0;
     for(i=0; i<s->fbw_channels; i++) {
-        s->downmix_coeff_adjust[0] += s->downmix_coeffs[i][0];
-        s->downmix_coeff_adjust[1] += s->downmix_coeffs[i][1];
+        norm0 += s->downmix_coeffs[i][0];
+        norm1 += s->downmix_coeffs[i][1];
+    }
+    norm0 = 1.0f / norm0;
+    norm1 = 1.0f / norm1;
+    for(i=0; i<s->fbw_channels; i++) {
+        s->downmix_coeffs[i][0] *= norm0;
+        s->downmix_coeffs[i][1] *= norm1;
+    }
+
+    if(s->output_mode == AC3_CHMODE_MONO) {
+        for(i=0; i<s->fbw_channels; i++)
+            s->downmix_coeffs[i][0] = (s->downmix_coeffs[i][0] + s->downmix_coeffs[i][1]) * LEVEL_MINUS_3DB;
     }
-    s->downmix_coeff_adjust[0] = 1.0f / s->downmix_coeff_adjust[0];
-    s->downmix_coeff_adjust[1] = 1.0f / s->downmix_coeff_adjust[1];
 }
 
 /**
@@ -619,25 +629,28 @@ static inline void do_imdct(AC3DecodeCon
 /**
  * Downmix the output to mono or stereo.
  */
-static void ac3_downmix(AC3DecodeContext *s,
-                        float samples[AC3_MAX_CHANNELS][256], int ch_offset)
+static av_noinline void ac3_downmix(AC3DecodeContext *s,
+                                    float samples[AC3_MAX_CHANNELS][256])
 {
     int i, j;
     float v0, v1;
 
-    for(i=0; i<256; i++) {
-        v0 = v1 = 0.0f;
-        for(j=0; j<s->fbw_channels; j++) {
-            v0 += samples[j+ch_offset][i] * s->downmix_coeffs[j][0];
-            v1 += samples[j+ch_offset][i] * s->downmix_coeffs[j][1];
+    if(s->output_mode == AC3_CHMODE_STEREO) {
+        for(i=0; i<256; i++) {
+            v0 = v1 = 0.0f;
+            for(j=0; j<s->fbw_channels; j++) {
+                v0 += samples[j][i] * s->downmix_coeffs[j][0];
+                v1 += samples[j][i] * s->downmix_coeffs[j][1];
+            }
+            samples[0][i] = v0;
+            samples[1][i] = v1;
         }
-        v0 *= s->downmix_coeff_adjust[0];
-        v1 *= s->downmix_coeff_adjust[1];
-        if(s->output_mode == AC3_CHMODE_MONO) {
-            samples[ch_offset][i] = (v0 + v1) * LEVEL_MINUS_3DB;
-        } else if(s->output_mode == AC3_CHMODE_STEREO) {
-            samples[  ch_offset][i] = v0;
-            samples[1+ch_offset][i] = v1;
+    } else if(s->output_mode == AC3_CHMODE_MONO) {
+        for(i=0; i<256; i++) {
+            v0 = 0.0f;
+            for(j=0; j<s->fbw_channels; j++)
+                v0 += samples[j][i] * s->downmix_coeffs[j][0];
+            samples[0][i] = v0;
         }
     }
 }
@@ -1002,17 +1015,17 @@ static int decode_audio_block(AC3DecodeC
         do_imdct(s, s->channels);
 
         if(downmix_output) {
-            ac3_downmix(s, s->output, 0);
+            ac3_downmix(s, s->output);
         }
     } else {
         if(downmix_output) {
-            ac3_downmix(s, s->transform_coeffs, 1);
+            ac3_downmix(s, s->transform_coeffs+1);
         }
 
         if(!s->downmixed) {
             s->downmixed = 1;
             // FIXME delay[] is half the size of the other downmixes
-            ac3_downmix(s, s->delay, 0);
+            ac3_downmix(s, s->delay);
         }
 
         do_imdct(s, s->out_channels);

Modified: trunk/libavcodec/ac3dec.h
==============================================================================
--- trunk/libavcodec/ac3dec.h	(original)
+++ trunk/libavcodec/ac3dec.h	Wed Aug 13 01:45:46 2008
@@ -99,7 +99,6 @@ typedef struct {
     int channels;                               ///< number of total channels
     int lfe_ch;                                 ///< index of LFE channel
     float downmix_coeffs[AC3_MAX_CHANNELS][2];  ///< stereo downmix coefficients
-    float downmix_coeff_adjust[2];              ///< adjustment needed for each output channel when downmixing
     int downmixed;                              ///< indicates if coeffs are currently downmixed
     int output_mode;                            ///< output channel configuration
     int out_channels;                           ///< number of output channels




More information about the ffmpeg-cvslog mailing list