[FFmpeg-devel] audio_resample 5.1->stereo

Brian Connolly bconnoll
Wed Jan 2 23:37:48 CET 2008


Hey there:

I've been hacking around with ffmpeg for about a year now... I've been
using the libavcodec/libavformat C APIs with great success, in order to
teach myself the basics of the AV world. Thanks alot for the great
software, everyone.

However, I just hit a snag that forced me to modify the ffmpeg sources:
I needed the audio resampler to be able to convert 5.1 audio streams
down to stereo. 

Is anyone else working to fix this? I've created a quick fix based on
some algorithms I found in various email discussions. Would it be
possible to add this code (or something like it) to the official ffmpeg
source so i wont need to continually patch my local code?

Below is the output of "svn diff" in my local source tree...

Thanks,
Bri

brian at jamo [~/src/ffmpeg/libavcodec]: svn diff resample.c
Index: resample.c
===================================================================
--- resample.c  (revision 11346)
+++ resample.c  (working copy)
@@ -99,16 +99,67 @@
     }
 }
 
-static void stereo_mux(short *output, short *input1, short *input2, int
n)
+/*
+
+*/
+static short clip_short(int v)
 {
+       if (v < -32768) 
+               v = -32768;
+    else if (v > 32767) 
+               v = 32767;
+       return (short) v;
+}
+
+/* XXX: make this better.  channels will always be >= 2. 
+- Left = front_left + rear_gain * rear_left + center_gain * center
+- Right = front_right + rear_gain * rear_right + center_gain * center
+
+where rear_gain is usually around 0.5-1.0 and center_gain is almost
always 0.7 (-3 dB) if I recall correctly. 
+*/
+static void multi_to_stereo_split(short *output1, short *output2, short
*input, int n, int channels)
+{
     int i;
+       short l,r;
 
     for(i=0;i<n;i++) {
-        *output++ = *input1++;
-        *output++ = *input2++;
+               if (channels == 2)
+               {
+                       /* simple stereo to stereo. Input is: l, r */
+               l = input[0];
+               r = input[1];
+               }
+               else if (channels == 6)
+               {
+                       /* 5.1 to stereo. l, c, r, ls, rs, sw */
+               int fl,fr,c,rl,rr,lfe;
+               fl = input[0];
+               c = input[1];
+               fr = input[2];
+               rl = input[3];
+               rr = input[4];
+               lfe = input[5];
+
+                       l = clip_short(fl + (0.5 * rl) + (0.7 * c));
+                       r = clip_short(fr + (0.5 * rr) + (0.7 * c));
+               }
+               else
+               {
+                       /* l, c, r, ? */
+               l = input[0];
+               r = input[2];
+               }
+
+               /* output l & r. */ 
+               *output1++ = l;
+        *output2++ = r;
+
+               /* increment input. */
+               input += channels;
     }
 }
 
+
 static void ac3_5p1_mux(short *output, short *input1, short *input2,
int n)
 {
     int i;
@@ -131,11 +182,13 @@
 {
     ReSampleContext *s;
 
+#ifdef nodef
     if ( input_channels > 2)
       {
         av_log(NULL, AV_LOG_ERROR, "Resampling with input channels
greater than 2 unsupported.\n");
         return NULL;
       }
+#endif
 
     s = av_mallocz(sizeof(ReSampleContext));
     if (!s)
@@ -195,18 +248,18 @@
     bufout[0]= av_malloc( lenout * sizeof(short) );
     bufout[1]= av_malloc( lenout * sizeof(short) );
 
-    if (s->input_channels == 2 &&
-        s->output_channels == 1) {
+    if ((s->input_channels == 2) && (s->output_channels == 1)) {
         buftmp3[0] = output;
         stereo_to_mono(buftmp2[0], input, nb_samples);
-    } else if (s->output_channels >= 2 && s->input_channels == 1) {
+    } else if ((s->output_channels >= 2) && (s->input_channels == 1)) {
         buftmp3[0] = bufout[0];
         memcpy(buftmp2[0], input, nb_samples*sizeof(short));
     } else if (s->output_channels >= 2) {
         buftmp3[0] = bufout[0];
         buftmp3[1] = bufout[1];
-        stereo_split(buftmp2[0], buftmp2[1], input, nb_samples);
+        multi_to_stereo_split(buftmp2[0], buftmp2[1], input,
nb_samples, s->input_channels);
     } else {
+               /* input channels = 1, output channels = 1 */
         buftmp3[0] = output;
         memcpy(buftmp2[0], input, nb_samples*sizeof(short));
     }




More information about the ffmpeg-devel mailing list