[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