[Mplayer-cvslog] CVS: main/libac3 imdct.c,1.8,1.9 imdct.h,1.1.1.1,1.2 parse.c,1.2,1.3

Stephen Davies steve at mplayer.dev.hu
Wed Nov 28 13:46:25 CET 2001


Update of /cvsroot/mplayer/main/libac3
In directory mplayer:/var/tmp.root/cvs-serv25857/libac3

Modified Files:
	imdct.c imdct.h parse.c 
Log Message:
Extended oss output driver and libac3 to support 4 and 6 channel output mixes.  added -channels command line option

Index: imdct.c
===================================================================
RCS file: /cvsroot/mplayer/main/libac3/imdct.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- imdct.c	10 Jul 2001 08:27:49 -0000	1.8
+++ imdct.c	28 Nov 2001 12:46:22 -0000	1.9
@@ -20,6 +20,9 @@
  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  *
+ *  Updated 2001-11-25 - Steve Davies <steve at daviesfam.org>:
+ *    - Added full 5.1 output
+ *    - Added decoding of lfe channel
  */
 
 #include <stdlib.h>
@@ -57,6 +60,9 @@
 static float delay[6][256] __attribute__((aligned(16)));
 static float delay1[6][256] __attribute__((aligned(16)));
 
+/* Buffer full of "silence" for output channels to be muted */
+static float silence[256] = {0.0};
+
 /* Windowing function for Modified DCT - Thank you acroread */
 static float window[] __attribute__((aligned(16))) = {
 	0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130,
@@ -493,7 +499,42 @@
 ///#include <sys/time.h>
 //FIXME remove
 
-void imdct (bsi_t *bsi,audblk_t *audblk, stream_samples_t samples, int16_t *s16_samples, dm_par_t* dm_par)
+//FIXME:SLD:Optimize - specially for <5.1 cases - and all those pointers will mean too few
+//registers to go round (check generated code...)...
+void stream_sample_6ch_to_s16(int16_t *s16_samples, int num_output_channels, dm_par_t *dm_par,
+			      float *left, float *right,
+			      float *left_s, float *right_s,
+			      float *centre, float *lfe,
+			      float *delay_left, float *delay_right,
+			      float *delay_left_s, float *delay_right_s,
+			      float *delay_centre, float *delay_lfe)
+{
+  int i;
+
+  if (num_output_channels == 4) {
+    for (i=0; i<256; i++) {
+      *s16_samples++ = (int16_t)( (*left++ + *delay_left++)     * dm_par->unit +
+			          (*centre + *delay_centre)     * dm_par->clev );
+      *s16_samples++ = (int16_t)( (*right++ + *delay_right++)   * dm_par->unit +
+				  (*centre++ + *delay_centre++) * dm_par->clev );
+      *s16_samples++ = (int16_t)(*left_s++ + *delay_left_s++);
+      *s16_samples++ = (int16_t)(*right_s++ + *delay_right_s++);
+    }
+  }
+  else {
+    for (i=0; i<256; i++) {
+      *s16_samples++ = (int16_t)(*left++ + *delay_left++);
+      *s16_samples++ = (int16_t)(*right++ + *delay_right++);
+      *s16_samples++ = (int16_t)(*left_s++ + *delay_left_s++);
+      *s16_samples++ = (int16_t)(*right_s++ + *delay_right_s++);
+      *s16_samples++ = (int16_t)(*centre++ + *delay_centre++);
+      *s16_samples++ = (int16_t)(*lfe++ + *delay_lfe++);
+    }
+  }
+}
+
+void imdct (bsi_t *bsi,audblk_t *audblk, stream_samples_t samples,
+	    int num_output_channels, int16_t *s16_samples, dm_par_t* dm_par)
 {
 	int i;
 	int doable = 0;
@@ -501,21 +542,26 @@
 	float *delay_left, *delay_right;
 	float *delay1_left, *delay1_right, *delay1_center, *delay1_sr, *delay1_sl;
 	float right_tmp, left_tmp;
-	void (*do_imdct)(float data[], float deley[]);
+	float *lfe_samples, *lfe_delay;
+	void (*do_imdct)(float data[], float delay[]);
 
-	// test if dm in frequency is doable
-	if (!(doable = audblk->blksw[0]))
-		do_imdct = imdct_do_512;
-	else
-		do_imdct = imdct_do_256;
-
-	// downmix in the frequency domain if all the channels
-	// use the same imdct
-	for (i=0; i < bsi->nfchans; i++) {
-		if (doable != audblk->blksw[i]) {
-			do_imdct = NULL;
-			break;
-		}
+	if (num_output_channels > 2)
+		do_imdct = NULL;
+	else {
+		// test if dm in frequency is doable
+	  	if (!(doable = audblk->blksw[0]))
+			do_imdct = imdct_do_512;
+	  	else
+	        	do_imdct = imdct_do_256;
+
+		// downmix in the frequency domain if all the channels
+	  	// use the same imdct
+	  	for (i=0; i < bsi->nfchans; i++) {
+	    		if (doable != audblk->blksw[i]) {
+	      			do_imdct = NULL;
+	      			break;
+	    		}
+	  	}
 	}
 
 	if (do_imdct) {
@@ -565,7 +611,105 @@
 			else
 				imdct_do_512_nol (samples[i],delay1[i]);
 		}
-
+		//FIXME:SLD:Seems to get something.  Hard to tell if its right with few
+		//FIXME:SLD:5.1 disks and without a proper subwoofer.
+		if (bsi->lfeon && num_output_channels > 5) {
+		  //lfe channel:
+		  //Here's what liba52 does:
+		  //	if (state->output & A52_LFE) {
+		  //	    coeff_get (samples - 256, state->lf_exp, state->lfe_bap,
+		  //		       &quantizer, state->dynrng, 0, 7);
+		  //	    for (i = 7; i < 256; i++)
+		  //		(samples-256)[i] = 0;
+		  //	    imdct_512 (samples - 256, samples + 1536 - 256, state->bias);
+		  //We should already have top of the samples buffer as 0s 'cos its cleared above
+		  //presumably samples+1536 is equivalent of the delay buffer
+		  //So I think we want...:
+		  imdct_do_512_nol(samples[5], delay1[5]);
+		  lfe_samples = samples[5];  lfe_delay = delay[5];
+		}
+		else
+		  lfe_samples = lfe_delay = silence;
+		  
+
+		if (num_output_channels > 2) {
+		  if (num_output_channels != 4 && num_output_channels != 6) {
+		    fprintf(stderr, "*** ERROR: %d channel mix not yet supported ***\n", num_output_channels);
+		    return;
+		  }
+		  //  multichannel mix:
+		  switch(bsi->acmod) {
+		  case 7:	// 3/2
+		    stream_sample_6ch_to_s16(s16_samples, num_output_channels, dm_par,
+					     samples[0], samples[2],
+					     samples[3], samples[4],
+					     samples[1], lfe_samples,
+					     delay[0],   delay[2],
+					     delay[3],   delay[4],
+					     delay[1],   lfe_delay);
+		    break;
+		  case 6:	// 2/2
+		    stream_sample_6ch_to_s16(s16_samples, num_output_channels, dm_par,
+					     samples[0], samples[1],
+					     samples[2], samples[3],
+					     silence,    lfe_samples,
+					     delay[0],   delay[1],
+					     delay[2],   delay[3],
+					     silence,    lfe_delay);
+		    break;
+		  case 5:	// 3/1
+		    stream_sample_6ch_to_s16(s16_samples, num_output_channels, dm_par,
+					     samples[0], samples[2],
+					     samples[3], samples[3], //FIXME: Should one be inverted?
+					     samples[1], lfe_samples,
+					     delay[0],   delay[2],
+					     delay[3],   delay[3], //FIXME: Should one be inverted?
+					     delay[1],   lfe_delay);
+		    break;
+		  case 4:	// 2/1
+		    stream_sample_6ch_to_s16(s16_samples, num_output_channels, dm_par,
+					     samples[0], samples[1],
+					     samples[2], samples[2], //FIXME: Invert one?
+					     silence,    lfe_samples,
+					     delay[0],   delay[1],
+					     delay[2],   delay[2], //FIXME: Invert one?
+					     silence,    lfe_delay);
+		    break;
+		  case 3:	// 3/0
+		    stream_sample_6ch_to_s16(s16_samples, num_output_channels, dm_par,
+					     samples[0], samples[2],
+					     silence,    silence,
+					     samples[1], lfe_samples,
+					     delay[0],   delay[2],
+					     silence,    silence,
+					     delay[1],   lfe_delay);
+		    break;
+		  case 2:	// 2/0
+		    stream_sample_6ch_to_s16(s16_samples, num_output_channels, dm_par,
+					     samples[0], samples[1],
+					     silence,    silence,
+					     silence,    lfe_samples,
+					     delay[0],   delay[1],
+					     silence,    silence,
+					     silence,    lfe_delay);
+		    break;
+		  default:	// 1/0 or dual language
+		    {
+		      int i = (bsi->acmod) ? 0 : ac3_config.dual_mono_ch_sel;
+		      stream_sample_6ch_to_s16(s16_samples, num_output_channels, dm_par,
+					       samples[i], samples[i],
+					       silence,    silence,
+					       silence,    lfe_samples,
+					       delay[i],   delay[i],
+					       silence,    silence,
+					       silence,    lfe_delay);
+		    }
+		  }
+		  // And copy the delays  (optimize?)
+		  memcpy(&delay[0], &delay1[0], sizeof(float)*6*256);
+		}
+		else {
+	  	// Downmix to stereo:
 		// mix the sample, overlap
 		switch(bsi->acmod) {
 		case 7:		// 3/2
@@ -588,7 +732,7 @@
 				*s16_samples++ = (int16_t)(left_tmp + *delay_left);
 				*s16_samples++ = (int16_t)(right_tmp + *delay_right);
 				*delay_left++ = dm_par->unit * *delay1_left++  + dm_par->clev * *delay1_center  + dm_par->slev * *delay1_sl++;
-				*delay_right++ = dm_par->unit * *delay1_right++ + dm_par->clev * *center++ + dm_par->slev * *delay1_sr++;
+				*delay_right++ = dm_par->unit * *delay1_right++ + dm_par->clev * *delay1_center++ + dm_par->slev * *delay1_sr++;
 			}
 			break;
 		case 6:		// 2/2
@@ -630,7 +774,7 @@
 				*s16_samples++ = (int16_t)(left_tmp + *delay_left);
 				*s16_samples++ = (int16_t)(right_tmp + *delay_right);
 				*delay_left++ = dm_par->unit * *delay1_left++  + dm_par->clev * *delay1_center  + dm_par->slev * *delay1_sl;
-				*delay_right++ = dm_par->unit * *delay1_right++ + dm_par->clev * *center++ + dm_par->slev * *delay1_sl++;
+				*delay_right++ = dm_par->unit * *delay1_right++ + dm_par->clev * *delay1_center++ + dm_par->slev * *delay1_sl++;
 			}
 			break;
 		case 4:		// 2/1
@@ -668,12 +812,14 @@
 				*s16_samples++ = (int16_t)(left_tmp + *delay_left);
 				*s16_samples++ = (int16_t)(right_tmp + *delay_right);
 				*delay_left++ = dm_par->unit * *delay1_left++  + dm_par->clev * *delay1_center;
-				*delay_right++ = dm_par->unit * *delay1_right++ + dm_par->clev * *center++;
+				*delay_right++ = dm_par->unit * *delay1_right++ + dm_par->clev * *delay1_center++;
 			}
 			break;
 		case 2:		// copy to output
+			//FIXME:SLD:Don't think this is right - doesn't add in the delay1[] values...
 			stream_sample_2ch_to_s16(s16_samples,samples[0],samples[1]);
 			break;
-		}
-	}
+		} /* switch */
+		} /* else of if num_output_channels > 2 */
+	} /* else of if (do_imdct) */
 }

Index: imdct.h
===================================================================
RCS file: /cvsroot/mplayer/main/libac3/imdct.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- imdct.h	24 Feb 2001 20:29:39 -0000	1.1.1.1
+++ imdct.h	28 Nov 2001 12:46:22 -0000	1.2
@@ -22,5 +22,5 @@
  *
  */
 
-void imdct (bsi_t *bsi,audblk_t *audblk, stream_samples_t samples, int16_t *s16_samples, dm_par_t *dm_par);
+void imdct (bsi_t *bsi,audblk_t *audblk, stream_samples_t samples, int num_output_channels, int16_t *s16_samples, dm_par_t *dm_par);
 void imdct_init(void);

Index: parse.c
===================================================================
RCS file: /cvsroot/mplayer/main/libac3/parse.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- parse.c	14 Jul 2001 16:33:11 -0000	1.2
+++ parse.c	28 Nov 2001 12:46:22 -0000	1.3
@@ -382,7 +382,7 @@
 			audblk->cplexps[i] = bitstream_get(7);
 	}
 
-	/* Get the fwb channel exponents */
+	/* Get the fbw channel exponents */
 	for(i=0;i < bsi->nfchans; i++) {
 		if(audblk->chexpstr[i] != EXP_REUSE) {
 			audblk->exps[i][0] = bitstream_get(4);			
@@ -442,7 +442,7 @@
 		}
 	}
 	
-	/* Get the delta bit alloaction info */
+	/* Get the delta bit allocation info */
 	audblk->deltbaie = bitstream_get(1);	
 	
 	if(audblk->deltbaie) {




More information about the MPlayer-cvslog mailing list