Mercurial > mplayer.hg
changeset 3681:26126e5c3532
surround channels can now be decoded in stereoish
author | steve |
---|---|
date | Sun, 23 Dec 2001 19:10:00 +0000 |
parents | 2cc5737ec923 |
children | c48a595d5c50 |
files | libao2/pl_surround.c |
diffstat | 1 files changed, 54 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/libao2/pl_surround.c Sun Dec 23 19:09:24 2001 +0000 +++ b/libao2/pl_surround.c Sun Dec 23 19:10:00 2001 +0000 @@ -21,11 +21,21 @@ */ /* The principle: Make rear channels by extracting anti-phase data - from the front channels, delay by 15msec and feed to rear in anti-phase - www.dolby.com has the background + from the front channels, delay by 20msec and feed to rear in anti-phase */ +// SPLITREAR: Define to decode two distinct rear channels - +// this doesn't work so well in practice because +// separation in a passive matrix is not high. +// C (dialogue) to Ls and Rs 14dB or so - +// so dialogue leaks to the rear. +// Still - give it a try and send feedback. +// comment this define for old behaviour of a single +// surround sent to rear in anti-phase +#define SPLITREAR + + #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -65,7 +75,7 @@ } pl_surround_t; -static pl_surround_t pl_surround={0,15,NULL,NULL,NULL,0,0,NULL,0,0,0}; +static pl_surround_t pl_surround={0,20,NULL,NULL,NULL,0,0,NULL,0,0,0}; // to set/get/query special features/parameters static int control(int cmd,int arg){ @@ -153,13 +163,21 @@ memset(pl_surround.Rs_delaybuf, 0, sizeof(int16_t)*pl_surround.delaybuf_len); } +// The beginnings of an active matrix... +static double steering_matrix[][12] = { +// LL RL LR RR LS RS LLs RLs LRs RRs LC RC + {.707, .0, .0, .707, .5, -.5, .5878, -.3928, .3928, -.5878, .5, .5}, +}; + +// Experimental moving average dominances +static int amp_L = 0, amp_R = 0, amp_C = 0, amp_S = 0; // processes 'ao_plugin_data.len' bytes of 'data' // called for every block of data static int play(){ int16_t *in, *out; int i, samples; - int surround; + double *matrix = steering_matrix[0]; // later we'll index based on detected dominance if (pl_surround.passthrough) return 1; @@ -168,12 +186,18 @@ samples = ao_plugin_data.len / sizeof(int16_t) / pl_surround.input_channels; out = pl_surround.databuf; in = (int16_t *)ao_plugin_data.data; - // Testing - place a 1kHz tone in the front channels in anti-phase + // Testing - place a 1kHz tone on Lt and Rt in anti-phase: should decode in S //sinewave(in, samples, pl_surround.input_channels, 1000, 0.0, pl_surround.rate); //sinewave(&in[1], samples, pl_surround.input_channels, 1000, PI, pl_surround.rate); for (i=0; i<samples; i++) { + // Dominance: + //abs(in[0]) abs(in[1]); + //abs(in[0]+in[1]) abs(in[0]-in[1]); + //10 * log( abs(in[0]) / (abs(in[1])|1) ); + //10 * log( abs(in[0]+in[1]) / (abs(in[0]-in[1])|1) ); + // About volume balancing... // Surround encoding does the following: // Lt=L+.707*C+.707*S, Rt=R+.707*C-.707*S @@ -183,25 +207,39 @@ // must take 3dB off as we split it: // Ls=Rs=.707*(Lt-Rt) // Trouble is, Lt could be +32767, Rt -32768, so possibility that S will - // clip. So to avoid that, we cut L/R by 3dB (*.707), and S by 6dB (/2). + // overflow. So to avoid that, we cut L/R by 3dB (*.707), and S by 6dB (/2). + // this keeps the overall balance, but guarantees no overflow. // output front left and right - out[0] = in[0]*.707; - out[1] = in[1]*.707; - // output Ls and Rs - from 15msec ago, lowpass filtered @ 7kHz + out[0] = matrix[0]*in[0] + matrix[1]*in[1]; + out[1] = matrix[2]*in[0] + matrix[3]*in[1]; + // output Ls and Rs - from 20msec ago, lowpass filtered @ 7kHz out[2] = firfilter(pl_surround.Ls_delaybuf, pl_surround.delaybuf_pos, pl_surround.delaybuf_len, 32, pl_surround.filter_coefs_surround); - out[3] = - out[2]; - // out[3] = firfilter(pl_surround.Rs_delaybuf, pl_surround.delaybuf_pos, - // pl_surround.delaybuf_len, 32, pl_surround.filter_coefs_surround); - // calculate and save surround for 15msecs time - surround = (in[0]/2 - in[1]/2); - pl_surround.Ls_delaybuf[pl_surround.delaybuf_pos] = surround; - pl_surround.Rs_delaybuf[pl_surround.delaybuf_pos++] = - surround; +#ifdef SPLITREAR + out[3] = firfilter(pl_surround.Rs_delaybuf, pl_surround.delaybuf_pos, + pl_surround.delaybuf_len, 32, pl_surround.filter_coefs_surround); +#else + out[3] = -out[2]; +#endif + // calculate and save surround for 20msecs time +#ifdef SPLITREAR + pl_surround.Ls_delaybuf[pl_surround.delaybuf_pos] = + matrix[6]*in[0] + matrix[7]*in[1]; + pl_surround.Rs_delaybuf[pl_surround.delaybuf_pos++] = + matrix[8]*in[0] + matrix[9]*in[1]; +#else + pl_surround.Ls_delaybuf[pl_surround.delaybuf_pos] = + matrix[4]*in[0] + matrix[5]*in[1]; +#endif pl_surround.delaybuf_pos %= pl_surround.delaybuf_len; + // next samples... in = &in[pl_surround.input_channels]; out = &out[4]; } + + // Show some state + //printf("\npl_surround: delaybuf_pos=%d, samples=%d\r\033[A", pl_surround.delaybuf_pos, samples); // Set output block/len ao_plugin_data.data=pl_surround.databuf;