[MPlayer-dev-eng] [PATCH] Proof of concept extrasurround plugin

Kis Gergely kisg at lme.linux.hu
Thu Apr 4 00:05:16 CEST 2002


Hi,

This is an _experimental_ patch. Only a proof of concept.
Use it at your own risk!

The problem: Most video files come with stereo or dolby surround 
audio encoding.
These files doesn't sound very well on a 5.1 speaker set. The purpose of
this plugin is to address this problem.

The solution (well, workaround :-) ): Take the surround plugin, 
and make it output to the 6th (subwoofer) channel too. 
The 5th (center speaker) channel remains silent, because it would ruin 
the stereo experience.
The signal sent to the subwoofer channel is a mono mix of the two front
speakers filtered through a lowpass filter.
This plugin is only suitable for people with a 5.1 soundcard!

The current implementation:
The current implementation is not suited for CVS commit. But it works for
me. 

TODO: 
-Make the new functionality an option of the plugin
-Use the same lowpass filter as in the original surround part of the plugin. I
couldn't figure the firfilter thingie out, so I stole^H^H^H^H^H reused
the simple RC lowpass filter from sox.
-Fix the bugs

KNOWN BUGS:
-I couldn't play any files with 48000 Hz sample rate. But it worked with
44100 Hz sample rate files. I tried to use the resample plugin with
fout=44100, but it still didn't work. So I tried fout=22050, and it worked!
That's because I have no clue, how the whole thing works. Please somebody
enlighten me!

The workaround for 48kHz files is:
mplayer -aop list=resample,surround:fout=22050 filename

I hope you will like it, or hate it and make it better.  

Thanks,
kisg
-------------- next part --------------
--- pl_surround.c.orig	Tue Dec 25 10:52:21 2001
+++ pl_surround.c	Wed Apr  3 23:38:47 2002
@@ -72,6 +72,9 @@
   int rate;             // input data rate
   int format;           // input format
   int input_channels;   // input channels
+  float lowp_cutoff;    // cutoff freq for the lowpass filter
+  double lowp_A, lowp_B; // parameters for lowpass filter
+  double lowp_outm1;		// output for lowpass filter (??)
 
 } pl_surround_t;
 
@@ -89,7 +92,7 @@
       free(pl_surround.databuf);  pl_surround.databuf = NULL;
     }
     // Allocate output buffer
-    pl_surround.databuf = calloc(ao_plugin_data.len, 1);
+    pl_surround.databuf = calloc(ao_plugin_data.len*3, 1);
     // Return back smaller len so we don't get overflowed...
     ao_plugin_data.len /= 2;
     return CONTROL_OK;
@@ -121,8 +124,11 @@
   pl_surround.input_channels=ao_plugin_data.channels;
 
   // Input 2 channels, output will be 4 - tell ao_plugin
-  ao_plugin_data.channels    = 4;
-  ao_plugin_data.sz_mult    /= 2;
+//  ao_plugin_data.channels    = 4;
+//  ao_plugin_data.sz_mult    /= 2;
+
+  ao_plugin_data.channels    = 6;
+  ao_plugin_data.sz_mult    /= 3;
 
   // Figure out buffer space (in int16_ts) needed for the 15msec delay
   // Extra 31 samples allow for lowpass filter delay (taps-1)
@@ -137,6 +143,16 @@
   pl_surround.filter_coefs_surround = calc_coefficients_7kHz_lowpass(pl_surround.rate);
   //dump_filter_coefficients(pl_surround.filter_coefs_surround);
   //testfilter(pl_surround.filter_coefs_surround, 32, pl_surround.rate);
+  
+  pl_surround.lowp_cutoff = 7000;
+  if (pl_surround.lowp_cutoff > pl_surround.rate / 2) {
+    // Cutoff rate must be < sample rate / 2 (Nyquist rate)
+    pl_surround.lowp_cutoff = pl_surround.rate / 2 - 1;
+  } 
+  pl_surround.lowp_B = exp ((-2.0 * M_PI * (pl_surround.lowp_cutoff / pl_surround.rate)));
+  pl_surround.lowp_A = 1 - pl_surround.lowp_B;
+  pl_surround.lowp_outm1 = 0.0;
+  
   return 1;
 }
 
@@ -222,6 +238,24 @@
 #else
     out[3] = -out[2];
 #endif
+    // Only 4.1 output, center speaker remains silent
+    out[4] = 0;
+    {
+	int32_t avg;
+	double d;
+	avg = out[0] + out[1] / 2;
+	
+	d = pl_surround.lowp_A * avg + pl_surround.lowp_B * pl_surround.lowp_outm1;
+
+	if (d > 32767L) {
+	    d = 32767L;
+	}
+	if (d < -32768L) {
+	    d = -32768L;
+	}
+	pl_surround.lowp_outm1 = d;
+	out[5] = d;
+    }
     // calculate and save surround for 20msecs time
 #ifdef SPLITREAR
     pl_surround.Ls_delaybuf[pl_surround.delaybuf_pos] =
@@ -235,7 +269,7 @@
     pl_surround.delaybuf_pos %= pl_surround.delaybuf_len;
 
     // next samples...
-    in = &in[pl_surround.input_channels];  out = &out[4];
+    in = &in[pl_surround.input_channels];  out = &out[6];
   }
 
   // Show some state
@@ -243,6 +277,6 @@
   
   // Set output block/len
   ao_plugin_data.data=pl_surround.databuf;
-  ao_plugin_data.len=samples*sizeof(int16_t)*4;
+  ao_plugin_data.len=samples*sizeof(int16_t)*6;
   return 1;
 }


More information about the MPlayer-dev-eng mailing list