]> git.sesse.net Git - vlc/blob - src/ac3_decoder/ac3_downmix.c
49203132cb6c9658c3e358100fd5211758252a00
[vlc] / src / ac3_decoder / ac3_downmix.c
1 /*****************************************************************************
2  * ac3_downmix.c: ac3 downmix functions
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22 #include "defs.h"
23
24 #include "int_types.h"
25 #include "ac3_decoder.h"
26 #include "ac3_internal.h"
27
28 #define NORM 16384
29
30 typedef struct prefs_s {
31     u16 use_dolby_surround;
32     u16 dual_mono_channel_select;
33 } prefs_t;
34
35 prefs_t global_prefs = {0,0};
36
37 /* Pre-scaled downmix coefficients */
38 static float cmixlev_lut[4] = { 0.2928, 0.2468, 0.2071, 0.2468 };
39 static float smixlev_lut[4] = { 0.2928, 0.2071, 0.0   , 0.2071 };
40
41 /* Downmix into _two_ channels...other downmix modes aren't implemented
42  * to reduce complexity. Realistically, there aren't many machines around
43  * with > 2 channel output anyways */
44
45 void downmix (ac3dec_t * p_ac3dec, s16 * out_buf)
46 {
47     int j;
48     float right_tmp;
49     float left_tmp;
50     float clev,slev;
51     float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0;
52
53     /*
54     if (p_ac3dec->bsi.acmod > 7)
55         intf_ErrMsg( "ac3dec: (downmix) invalid acmod number\n" );
56     */
57
58     /* There are two main cases, with or without Dolby Surround */
59     if (global_prefs.use_dolby_surround) {
60         switch(p_ac3dec->bsi.acmod) {
61         case 7: /* 3/2 */
62             left      = p_ac3dec->samples.channel[0];
63             centre    = p_ac3dec->samples.channel[1];
64             right     = p_ac3dec->samples.channel[2];
65             left_sur  = p_ac3dec->samples.channel[3];
66             right_sur = p_ac3dec->samples.channel[4];
67
68             for (j = 0; j < 256; j++) {
69                 right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++;
70                 left_tmp  = -1 * right_tmp;
71                 right_tmp += 0.3204f * *right++ + 0.2265f * *centre;
72                 left_tmp  += 0.3204f * *left++  + 0.2265f * *centre++;
73
74                 *(out_buf++) = left_tmp * NORM;
75                 *(out_buf++) = right_tmp * NORM;
76             }
77             break;
78
79         case 6: /* 2/2 */
80             left      = p_ac3dec->samples.channel[0];
81             right     = p_ac3dec->samples.channel[1];
82             left_sur  = p_ac3dec->samples.channel[2];
83             right_sur = p_ac3dec->samples.channel[3];
84
85             for (j = 0; j < 256; j++) {
86                 right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++;
87                 left_tmp  = -1 * right_tmp;
88                 right_tmp += 0.3204f * *right++;
89                 left_tmp  += 0.3204f * *left++ ;
90
91                 *(out_buf++) = left_tmp * NORM;
92                 *(out_buf++) = right_tmp * NORM;
93             }
94             break;
95
96         case 5: /* 3/1 */
97             left      = p_ac3dec->samples.channel[0];
98             centre    = p_ac3dec->samples.channel[1];
99             right     = p_ac3dec->samples.channel[2];
100             /* Mono surround */
101             right_sur = p_ac3dec->samples.channel[3];
102
103             for (j = 0; j < 256; j++) {
104                 right_tmp =  0.2265f * *right_sur++;
105                 left_tmp  = - right_tmp;
106                 right_tmp += 0.3204f * *right++ + 0.2265f * *centre;
107                 left_tmp  += 0.3204f * *left++  + 0.2265f * *centre++;
108
109                 *(out_buf++) = left_tmp * NORM;
110                 *(out_buf++) = right_tmp * NORM;
111             }
112             break;
113
114         case 4: /* 2/1 */
115             left      = p_ac3dec->samples.channel[0];
116             right     = p_ac3dec->samples.channel[1];
117             /* Mono surround */
118             right_sur = p_ac3dec->samples.channel[2];
119
120             for (j = 0; j < 256; j++) {
121                 right_tmp =  0.2265f * *right_sur++;
122                 left_tmp  = - right_tmp;
123                 right_tmp += 0.3204f * *right++;
124                 left_tmp  += 0.3204f * *left++;
125
126                 *(out_buf++) = left_tmp * NORM;
127                 *(out_buf++) = right_tmp * NORM;
128             }
129             break;
130
131         case 3: /* 3/0 */
132             left      = p_ac3dec->samples.channel[0];
133             centre    = p_ac3dec->samples.channel[1];
134             right     = p_ac3dec->samples.channel[2];
135
136             for (j = 0; j < 256; j++) {
137                 right_tmp = 0.3204f * *right++ + 0.2265f * *centre;
138                 left_tmp  = 0.3204f * *left++  + 0.2265f * *centre++;
139
140                 *(out_buf++) = left_tmp * NORM;
141                 *(out_buf++) = right_tmp * NORM;
142             }
143             break;
144
145         case 2: /* 2/0 */
146             left = p_ac3dec->samples.channel[0];
147             right = p_ac3dec->samples.channel[1];
148
149             for (j = 0; j < 256; j++) {
150                 *(out_buf++) = *(left++) * NORM;
151                 *(out_buf++) = *(right++) * NORM;
152             }
153             break;
154
155         case 1: /* 1/0 */
156             /* Mono program! */
157             right = p_ac3dec->samples.channel[0];
158
159             for (j = 0; j < 256; j++) {
160                 right_tmp = 0.7071f * *right++;
161
162                 *(out_buf++) = right_tmp * NORM;
163                 *(out_buf++) = right_tmp * NORM;
164             }
165             break;
166
167         case 0: /* 1+1 */
168             /* Dual mono, output selected by user */
169             right = p_ac3dec->samples.channel[global_prefs.dual_mono_channel_select];
170
171             for (j = 0; j < 256; j++) {
172                 right_tmp = 0.7071f * *right++;
173
174                 *(out_buf++) = right_tmp * NORM;
175                 *(out_buf++) = right_tmp * NORM;
176             }
177             break;
178         }
179     } else {
180         /* Non-Dolby surround downmixes */
181         switch(p_ac3dec->bsi.acmod) {
182         case 7: /* 3/2 */
183             left      = p_ac3dec->samples.channel[0];
184             centre    = p_ac3dec->samples.channel[1];
185             right     = p_ac3dec->samples.channel[2];
186             left_sur  = p_ac3dec->samples.channel[3];
187             right_sur = p_ac3dec->samples.channel[4];
188
189             clev = cmixlev_lut[p_ac3dec->bsi.cmixlev];
190             slev = smixlev_lut[p_ac3dec->bsi.surmixlev];
191
192             for (j = 0; j < 256; j++) {
193                 right_tmp= 0.4142f * *right++ + clev * *centre   + slev * *right_sur++;
194                 left_tmp = 0.4142f * *left++  + clev * *centre++ + slev * *left_sur++;
195
196                 *(out_buf++) = left_tmp * NORM;
197                 *(out_buf++) = right_tmp * NORM;
198             }
199             break;
200
201         case 6: /* 2/2 */
202             left      = p_ac3dec->samples.channel[0];
203             right     = p_ac3dec->samples.channel[1];
204             left_sur  = p_ac3dec->samples.channel[2];
205             right_sur = p_ac3dec->samples.channel[3];
206
207             slev = smixlev_lut[p_ac3dec->bsi.surmixlev];
208
209             for (j = 0; j < 256; j++) {
210                 right_tmp= 0.4142f * *right++ + slev * *right_sur++;
211                 left_tmp = 0.4142f * *left++  + slev * *left_sur++;
212
213                 *(out_buf++) = left_tmp * NORM;
214                 *(out_buf++) = right_tmp * NORM;
215             }
216             break;
217
218         case 5: /* 3/1 */
219             left      = p_ac3dec->samples.channel[0];
220             centre    = p_ac3dec->samples.channel[1];
221             right     = p_ac3dec->samples.channel[2];
222             /* Mono surround */
223             right_sur = p_ac3dec->samples.channel[3];
224
225             clev = cmixlev_lut[p_ac3dec->bsi.cmixlev];
226             slev = smixlev_lut[p_ac3dec->bsi.surmixlev];
227             
228             for (j = 0; j < 256; j++) {
229                 right_tmp= 0.4142f * *right++ + clev * *centre   + slev * *right_sur;
230                 left_tmp = 0.4142f * *left++  + clev * *centre++ + slev * *right_sur++;
231
232                 *(out_buf++) = left_tmp * NORM;
233                 *(out_buf++) = right_tmp * NORM;
234             }
235             break;
236
237         case 4: /* 2/1 */
238             left      = p_ac3dec->samples.channel[0];
239             right     = p_ac3dec->samples.channel[1];
240             /* Mono surround */
241             right_sur = p_ac3dec->samples.channel[2];
242
243             slev = smixlev_lut[p_ac3dec->bsi.surmixlev];
244
245             for (j = 0; j < 256; j++) {
246                 right_tmp= 0.4142f * *right++ + slev * *right_sur;
247                 left_tmp = 0.4142f * *left++  + slev * *right_sur++;
248
249                 *(out_buf++) = left_tmp * NORM;
250                 *(out_buf++) = right_tmp * NORM;
251             }
252             break;
253
254         case 3: /* 3/0 */
255             left      = p_ac3dec->samples.channel[0];
256             centre    = p_ac3dec->samples.channel[1];
257             right     = p_ac3dec->samples.channel[2];
258
259             clev = cmixlev_lut[p_ac3dec->bsi.cmixlev];
260
261             for (j = 0; j < 256; j++) {
262                 right_tmp= 0.4142f * *right++ + clev * *centre;
263                 left_tmp = 0.4142f * *left++  + clev * *centre++;
264
265                 *(out_buf++) = left_tmp * NORM;
266                 *(out_buf++) = right_tmp * NORM;
267             }
268             break;
269
270         case 2: /* 2/0 */
271             left = p_ac3dec->samples.channel[0];
272             right = p_ac3dec->samples.channel[1];
273
274             for (j = 0; j < 256; j++) {
275                 *(out_buf++) = *(left++) * NORM;
276                 *(out_buf++) = *(right++) * NORM;
277             }
278             break;
279
280         case 1: /* 1/0 */
281             /* Mono program! */
282             right = p_ac3dec->samples.channel[0];
283
284             for (j = 0; j < 256; j++) {
285                 right_tmp = 0.7071f * *right++;
286
287                 *(out_buf++) = right_tmp * NORM;
288                 *(out_buf++) = right_tmp * NORM;
289             }
290             break;
291
292         case 0: /* 1+1 */
293             /* Dual mono, output selected by user */
294             right = p_ac3dec->samples.channel[global_prefs.dual_mono_channel_select];
295
296             for (j = 0; j < 256; j++) {
297                 right_tmp = 0.7071f * *right++;
298
299                 *(out_buf++) = right_tmp * NORM;
300                 *(out_buf++) = right_tmp * NORM;
301             }
302             break;
303         }
304     }
305 }