Mercurial > mplayer.hg
comparison libao2/pl_surround.c @ 3681:26126e5c3532
surround channels can now be decoded in stereoish
author | steve |
---|---|
date | Sun, 23 Dec 2001 19:10:00 +0000 |
parents | cc1c879533ee |
children | d358dc143a9e |
comparison
equal
deleted
inserted
replaced
3680:2cc5737ec923 | 3681:26126e5c3532 |
---|---|
19 | 19 |
20 Original author: Steve Davies <steve@daviesfam.org> | 20 Original author: Steve Davies <steve@daviesfam.org> |
21 */ | 21 */ |
22 | 22 |
23 /* The principle: Make rear channels by extracting anti-phase data | 23 /* The principle: Make rear channels by extracting anti-phase data |
24 from the front channels, delay by 15msec and feed to rear in anti-phase | 24 from the front channels, delay by 20msec and feed to rear in anti-phase |
25 www.dolby.com has the background | |
26 */ | 25 */ |
26 | |
27 | |
28 // SPLITREAR: Define to decode two distinct rear channels - | |
29 // this doesn't work so well in practice because | |
30 // separation in a passive matrix is not high. | |
31 // C (dialogue) to Ls and Rs 14dB or so - | |
32 // so dialogue leaks to the rear. | |
33 // Still - give it a try and send feedback. | |
34 // comment this define for old behaviour of a single | |
35 // surround sent to rear in anti-phase | |
36 #define SPLITREAR | |
27 | 37 |
28 | 38 |
29 #include <stdio.h> | 39 #include <stdio.h> |
30 #include <stdlib.h> | 40 #include <stdlib.h> |
31 #include <unistd.h> | 41 #include <unistd.h> |
63 int format; // input format | 73 int format; // input format |
64 int input_channels; // input channels | 74 int input_channels; // input channels |
65 | 75 |
66 } pl_surround_t; | 76 } pl_surround_t; |
67 | 77 |
68 static pl_surround_t pl_surround={0,15,NULL,NULL,NULL,0,0,NULL,0,0,0}; | 78 static pl_surround_t pl_surround={0,20,NULL,NULL,NULL,0,0,NULL,0,0,0}; |
69 | 79 |
70 // to set/get/query special features/parameters | 80 // to set/get/query special features/parameters |
71 static int control(int cmd,int arg){ | 81 static int control(int cmd,int arg){ |
72 switch(cmd){ | 82 switch(cmd){ |
73 case AOCONTROL_PLUGIN_SET_LEN: | 83 case AOCONTROL_PLUGIN_SET_LEN: |
151 pl_surround.delaybuf_pos = 0; | 161 pl_surround.delaybuf_pos = 0; |
152 memset(pl_surround.Ls_delaybuf, 0, sizeof(int16_t)*pl_surround.delaybuf_len); | 162 memset(pl_surround.Ls_delaybuf, 0, sizeof(int16_t)*pl_surround.delaybuf_len); |
153 memset(pl_surround.Rs_delaybuf, 0, sizeof(int16_t)*pl_surround.delaybuf_len); | 163 memset(pl_surround.Rs_delaybuf, 0, sizeof(int16_t)*pl_surround.delaybuf_len); |
154 } | 164 } |
155 | 165 |
166 // The beginnings of an active matrix... | |
167 static double steering_matrix[][12] = { | |
168 // LL RL LR RR LS RS LLs RLs LRs RRs LC RC | |
169 {.707, .0, .0, .707, .5, -.5, .5878, -.3928, .3928, -.5878, .5, .5}, | |
170 }; | |
171 | |
172 // Experimental moving average dominances | |
173 static int amp_L = 0, amp_R = 0, amp_C = 0, amp_S = 0; | |
156 | 174 |
157 // processes 'ao_plugin_data.len' bytes of 'data' | 175 // processes 'ao_plugin_data.len' bytes of 'data' |
158 // called for every block of data | 176 // called for every block of data |
159 static int play(){ | 177 static int play(){ |
160 int16_t *in, *out; | 178 int16_t *in, *out; |
161 int i, samples; | 179 int i, samples; |
162 int surround; | 180 double *matrix = steering_matrix[0]; // later we'll index based on detected dominance |
163 | 181 |
164 if (pl_surround.passthrough) return 1; | 182 if (pl_surround.passthrough) return 1; |
165 | 183 |
166 // fprintf(stderr, "pl_surround: play %d bytes, %d samples\n", ao_plugin_data.len, samples); | 184 // fprintf(stderr, "pl_surround: play %d bytes, %d samples\n", ao_plugin_data.len, samples); |
167 | 185 |
168 samples = ao_plugin_data.len / sizeof(int16_t) / pl_surround.input_channels; | 186 samples = ao_plugin_data.len / sizeof(int16_t) / pl_surround.input_channels; |
169 out = pl_surround.databuf; in = (int16_t *)ao_plugin_data.data; | 187 out = pl_surround.databuf; in = (int16_t *)ao_plugin_data.data; |
170 | 188 |
171 // Testing - place a 1kHz tone in the front channels in anti-phase | 189 // Testing - place a 1kHz tone on Lt and Rt in anti-phase: should decode in S |
172 //sinewave(in, samples, pl_surround.input_channels, 1000, 0.0, pl_surround.rate); | 190 //sinewave(in, samples, pl_surround.input_channels, 1000, 0.0, pl_surround.rate); |
173 //sinewave(&in[1], samples, pl_surround.input_channels, 1000, PI, pl_surround.rate); | 191 //sinewave(&in[1], samples, pl_surround.input_channels, 1000, PI, pl_surround.rate); |
174 | 192 |
175 for (i=0; i<samples; i++) { | 193 for (i=0; i<samples; i++) { |
194 | |
195 // Dominance: | |
196 //abs(in[0]) abs(in[1]); | |
197 //abs(in[0]+in[1]) abs(in[0]-in[1]); | |
198 //10 * log( abs(in[0]) / (abs(in[1])|1) ); | |
199 //10 * log( abs(in[0]+in[1]) / (abs(in[0]-in[1])|1) ); | |
176 | 200 |
177 // About volume balancing... | 201 // About volume balancing... |
178 // Surround encoding does the following: | 202 // Surround encoding does the following: |
179 // Lt=L+.707*C+.707*S, Rt=R+.707*C-.707*S | 203 // Lt=L+.707*C+.707*S, Rt=R+.707*C-.707*S |
180 // So S should be extracted as: | 204 // So S should be extracted as: |
181 // (Lt-Rt) | 205 // (Lt-Rt) |
182 // But we are splitting the S to two output channels, so we | 206 // But we are splitting the S to two output channels, so we |
183 // must take 3dB off as we split it: | 207 // must take 3dB off as we split it: |
184 // Ls=Rs=.707*(Lt-Rt) | 208 // Ls=Rs=.707*(Lt-Rt) |
185 // Trouble is, Lt could be +32767, Rt -32768, so possibility that S will | 209 // Trouble is, Lt could be +32767, Rt -32768, so possibility that S will |
186 // clip. So to avoid that, we cut L/R by 3dB (*.707), and S by 6dB (/2). | 210 // overflow. So to avoid that, we cut L/R by 3dB (*.707), and S by 6dB (/2). |
211 // this keeps the overall balance, but guarantees no overflow. | |
187 | 212 |
188 // output front left and right | 213 // output front left and right |
189 out[0] = in[0]*.707; | 214 out[0] = matrix[0]*in[0] + matrix[1]*in[1]; |
190 out[1] = in[1]*.707; | 215 out[1] = matrix[2]*in[0] + matrix[3]*in[1]; |
191 // output Ls and Rs - from 15msec ago, lowpass filtered @ 7kHz | 216 // output Ls and Rs - from 20msec ago, lowpass filtered @ 7kHz |
192 out[2] = firfilter(pl_surround.Ls_delaybuf, pl_surround.delaybuf_pos, | 217 out[2] = firfilter(pl_surround.Ls_delaybuf, pl_surround.delaybuf_pos, |
193 pl_surround.delaybuf_len, 32, pl_surround.filter_coefs_surround); | 218 pl_surround.delaybuf_len, 32, pl_surround.filter_coefs_surround); |
194 out[3] = - out[2]; | 219 #ifdef SPLITREAR |
195 // out[3] = firfilter(pl_surround.Rs_delaybuf, pl_surround.delaybuf_pos, | 220 out[3] = firfilter(pl_surround.Rs_delaybuf, pl_surround.delaybuf_pos, |
196 // pl_surround.delaybuf_len, 32, pl_surround.filter_coefs_surround); | 221 pl_surround.delaybuf_len, 32, pl_surround.filter_coefs_surround); |
197 // calculate and save surround for 15msecs time | 222 #else |
198 surround = (in[0]/2 - in[1]/2); | 223 out[3] = -out[2]; |
199 pl_surround.Ls_delaybuf[pl_surround.delaybuf_pos] = surround; | 224 #endif |
200 pl_surround.Rs_delaybuf[pl_surround.delaybuf_pos++] = - surround; | 225 // calculate and save surround for 20msecs time |
226 #ifdef SPLITREAR | |
227 pl_surround.Ls_delaybuf[pl_surround.delaybuf_pos] = | |
228 matrix[6]*in[0] + matrix[7]*in[1]; | |
229 pl_surround.Rs_delaybuf[pl_surround.delaybuf_pos++] = | |
230 matrix[8]*in[0] + matrix[9]*in[1]; | |
231 #else | |
232 pl_surround.Ls_delaybuf[pl_surround.delaybuf_pos] = | |
233 matrix[4]*in[0] + matrix[5]*in[1]; | |
234 #endif | |
201 pl_surround.delaybuf_pos %= pl_surround.delaybuf_len; | 235 pl_surround.delaybuf_pos %= pl_surround.delaybuf_len; |
236 | |
202 // next samples... | 237 // next samples... |
203 in = &in[pl_surround.input_channels]; out = &out[4]; | 238 in = &in[pl_surround.input_channels]; out = &out[4]; |
204 } | 239 } |
240 | |
241 // Show some state | |
242 //printf("\npl_surround: delaybuf_pos=%d, samples=%d\r\033[A", pl_surround.delaybuf_pos, samples); | |
205 | 243 |
206 // Set output block/len | 244 // Set output block/len |
207 ao_plugin_data.data=pl_surround.databuf; | 245 ao_plugin_data.data=pl_surround.databuf; |
208 ao_plugin_data.len=samples*sizeof(int16_t)*4; | 246 ao_plugin_data.len=samples*sizeof(int16_t)*4; |
209 return 1; | 247 return 1; |