[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