OSDN Git Service

0ab9b90f349839fbba42a3a5a05b06b0ee9545c4
[handbrake-jp/handbrake-jp-git.git] / libhb / downmix.c
1 /* $Id: downmix.c,v 1.15 2005/03/17 19:22:47 stebbins Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include <string.h>
8 #include <stdlib.h>
9 #include <inttypes.h>
10 #include "common.h"
11 #include "downmix.h"
12
13 #define LVL_PLUS6DB 2.0
14 #define LVL_PLUS3DB 1.4142135623730951
15 #define LVL_3DB 0.7071067811865476
16 #define LVL_45DB 0.5946035575013605
17 #define LVL_6DB 0.5
18
19 #define LVL_SQRT_1_3 0.577350269
20 #define LVL_SQRT_2_3 0.816496581
21
22 #define HB_CH_FRONT_LEFT             0x00000001
23 #define HB_CH_FRONT_RIGHT            0x00000002
24 #define HB_CH_FRONT_CENTER           0x00000004
25 #define HB_CH_LOW_FREQUENCY          0x00000008
26 #define HB_CH_BACK_LEFT              0x00000010
27 #define HB_CH_BACK_RIGHT             0x00000020
28 #define HB_CH_BACK_CENTER            0x00000040
29 #define HB_CH_SIDE_LEFT              0x00000080
30 #define HB_CH_SIDE_RIGHT             0x00000100
31
32 #define HB_CH_SURROUND_MASK          0x000001f0
33 #define HB_CH_MASK                   0x000007ff
34
35 #define HB_CH_DOLBY                  0x00000800
36 #define HB_CH_DPLII                  0x00001000
37
38 #define DOWNMIX_MONO 0
39 #define DOWNMIX_STEREO 1
40 #define DOWNMIX_3F 2
41 #define DOWNMIX_2F1R 3
42 #define DOWNMIX_3F1R 4
43 #define DOWNMIX_2F2R 5
44 #define DOWNMIX_3F2R 6
45 #define DOWNMIX_3F4R 7
46 #define DOWNMIX_DOLBY 8
47 #define DOWNMIX_DPLII 9
48 #define DOWNMIX_NUM_MODES 10
49
50 #define DOWNMIX_CHANNEL_MASK 0x0f
51
52 #define DOWNMIX_LFE_FLAG 0x10
53 #define DOWNMIX_FLAGS_MASK 0x10
54
55 hb_sample_t downmix_matrix[DOWNMIX_NUM_MODES][DOWNMIX_NUM_MODES][8][8] =
56 {
57 // MONO in
58 {
59     // MONO out
60     { { 1, 0, 0, 0, 0, 0, 0, 0 },
61       { 0, 1, 0, 0, 0, 0, 0, 0 },
62       { 0, 0, 0, 0, 0, 0, 0, 0 },
63       { 0, 0, 0, 0, 0, 0, 0, 0 },
64       { 0, 0, 0, 0, 0, 0, 0, 0 },
65       { 0, 0, 0, 0, 0, 0, 0, 0 },
66       { 0, 0, 0, 0, 0, 0, 0, 0 },
67       { 0, 0, 0, 0, 0, 0, 0, 0 } },
68     // STEREO out
69     { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
70       { 0,       0,       1, 0, 0, 0, 0, 0 },
71       { 0,       0,       0, 0, 0, 0, 0, 0 },
72       { 0,       0,       0, 0, 0, 0, 0, 0 },
73       { 0,       0,       0, 0, 0, 0, 0, 0 },
74       { 0,       0,       0, 0, 0, 0, 0, 0 },
75       { 0,       0,       0, 0, 0, 0, 0, 0 },
76       { 0,       0,       0, 0, 0, 0, 0, 0 } },
77     // 3F out
78     { { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
79       { 0, 0,       0,       1, 0, 0, 0, 0 },
80       { 0, 0,       0,       0, 0, 0, 0, 0 },
81       { 0, 0,       0,       0, 0, 0, 0, 0 },
82       { 0, 0,       0,       0, 0, 0, 0, 0 },
83       { 0, 0,       0,       0, 0, 0, 0, 0 },
84       { 0, 0,       0,       0, 0, 0, 0, 0 },
85       { 0, 0,       0,       0, 0, 0, 0, 0 } },
86     // 2F1R out
87     { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
88       { 0,       0,       0, 1, 0, 0, 0, 0 },
89       { 0,       0,       0, 0, 0, 0, 0, 0 },
90       { 0,       0,       0, 0, 0, 0, 0, 0 },
91       { 0,       0,       0, 0, 0, 0, 0, 0 },
92       { 0,       0,       0, 0, 0, 0, 0, 0 },
93       { 0,       0,       0, 0, 0, 0, 0, 0 },
94       { 0,       0,       0, 0, 0, 0, 0, 0 } },
95     // 3F1R out
96     { { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
97       { 0, 0,       0,       0, 1, 0, 0, 0 },
98       { 0, 0,       0,       0, 0, 0, 0, 0 },
99       { 0, 0,       0,       0, 0, 0, 0, 0 },
100       { 0, 0,       0,       0, 0, 0, 0, 0 },
101       { 0, 0,       0,       0, 0, 0, 0, 0 },
102       { 0, 0,       0,       0, 0, 0, 0, 0 },
103       { 0, 0,       0,       0, 0, 0, 0, 0 } },
104     // 2F2R out
105     { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
106       { 0,       0,       0, 0, 1, 0, 0, 0 },
107       { 0,       0,       0, 0, 0, 0, 0, 0 },
108       { 0,       0,       0, 0, 0, 0, 0, 0 },
109       { 0,       0,       0, 0, 0, 0, 0, 0 },
110       { 0,       0,       0, 0, 0, 0, 0, 0 },
111       { 0,       0,       0, 0, 0, 0, 0, 0 },
112       { 0,       0,       0, 0, 0, 0, 0, 0 } },
113     // 3F2R out
114     { { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
115       { 0, 0,       0,       0, 0, 1, 0, 0 },
116       { 0, 0,       0,       0, 0, 0, 0, 0 },
117       { 0, 0,       0,       0, 0, 0, 0, 0 },
118       { 0, 0,       0,       0, 0, 0, 0, 0 },
119       { 0, 0,       0,       0, 0, 0, 0, 0 },
120       { 0, 0,       0,       0, 0, 0, 0, 0 },
121       { 0, 0,       0,       0, 0, 0, 0, 0 } },
122     // 3F4R out
123     { { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
124       { 0, 0,       0,       0, 0, 0, 0, 1 },
125       { 0, 0,       0,       0, 0, 0, 0, 0 },
126       { 0, 0,       0,       0, 0, 0, 0, 0 },
127       { 0, 0,       0,       0, 0, 0, 0, 0 },
128       { 0, 0,       0,       0, 0, 0, 0, 0 },
129       { 0, 0,       0,       0, 0, 0, 0, 0 },
130       { 0, 0,       0,       0, 0, 0, 0, 0 } },
131     // DOLBY out
132     { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
133       { 0,       0,       1, 0, 0, 0, 0, 0 },
134       { 0,       0,       0, 0, 0, 0, 0, 0 },
135       { 0,       0,       0, 0, 0, 0, 0, 0 },
136       { 0,       0,       0, 0, 0, 0, 0, 0 },
137       { 0,       0,       0, 0, 0, 0, 0, 0 },
138       { 0,       0,       0, 0, 0, 0, 0, 0 },
139       { 0,       0,       0, 0, 0, 0, 0, 0 } },
140     // DPLII out
141     { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
142       { 0,       0,       1, 0, 0, 0, 0, 0 },
143       { 0,       0,       0, 0, 0, 0, 0, 0 },
144       { 0,       0,       0, 0, 0, 0, 0, 0 },
145       { 0,       0,       0, 0, 0, 0, 0, 0 },
146       { 0,       0,       0, 0, 0, 0, 0, 0 },
147       { 0,       0,       0, 0, 0, 0, 0, 0 },
148       { 0,       0,       0, 0, 0, 0, 0, 0 } },
149 },
150 // STEREO in
151 {
152     // MONO out
153     { { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
154       { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
155       {       0, 1, 0, 0, 0, 0, 0, 0 },
156       {       0, 0, 0, 0, 0, 0, 0, 0 },
157       {       0, 0, 0, 0, 0, 0, 0, 0 },
158       {       0, 0, 0, 0, 0, 0, 0, 0 },
159       {       0, 0, 0, 0, 0, 0, 0, 0 },
160       {       0, 0, 0, 0, 0, 0, 0, 0 } },
161     // STEREO out
162     { { 1, 0, 0, 0, 0, 0, 0, 0 },
163       { 0, 1, 0, 0, 0, 0, 0, 0 },
164       { 0, 0, 1, 0, 0, 0, 0, 0 },
165       { 0, 0, 0, 0, 0, 0, 0, 0 },
166       { 0, 0, 0, 0, 0, 0, 0, 0 },
167       { 0, 0, 0, 0, 0, 0, 0, 0 },
168       { 0, 0, 0, 0, 0, 0, 0, 0 },
169       { 0, 0, 0, 0, 0, 0, 0, 0 } },
170     // 3F out
171     { { 0, 1, 0, 0, 0, 0, 0, 0 },
172       { 0, 0, 1, 0, 0, 0, 0, 0 },
173       { 0, 0, 0, 1, 0, 0, 0, 0 },
174       { 0, 0, 0, 0, 0, 0, 0, 0 },
175       { 0, 0, 0, 0, 0, 0, 0, 0 },
176       { 0, 0, 0, 0, 0, 0, 0, 0 },
177       { 0, 0, 0, 0, 0, 0, 0, 0 },
178       { 0, 0, 0, 0, 0, 0, 0, 0 } },
179     // 2F1R out
180     { { 1, 0, 0, 0, 0, 0, 0, 0 },
181       { 0, 1, 0, 0, 0, 0, 0, 0 },
182       { 0, 0, 0, 1, 0, 0, 0, 0 },
183       { 0, 0, 0, 0, 0, 0, 0, 0 },
184       { 0, 0, 0, 0, 0, 0, 0, 0 },
185       { 0, 0, 0, 0, 0, 0, 0, 0 },
186       { 0, 0, 0, 0, 0, 0, 0, 0 },
187       { 0, 0, 0, 0, 0, 0, 0, 0 } },
188     // 3F1R out
189     { { 0, 1, 0, 0, 0, 0, 0, 0 },
190       { 0, 0, 1, 0, 0, 0, 0, 0 },
191       { 0, 0, 0, 0, 1, 0, 0, 0 },
192       { 0, 0, 0, 0, 0, 0, 0, 0 },
193       { 0, 0, 0, 0, 0, 0, 0, 0 },
194       { 0, 0, 0, 0, 0, 0, 0, 0 },
195       { 0, 0, 0, 0, 0, 0, 0, 0 },
196       { 0, 0, 0, 0, 0, 0, 0, 0 } },
197     // 2F2R out
198     { { 1, 0, 0, 0, 0, 0, 0, 0 },
199       { 0, 1, 0, 0, 0, 0, 0, 0 },
200       { 0, 0, 0, 0, 1, 0, 0, 0 },
201       { 0, 0, 0, 0, 0, 0, 0, 0 },
202       { 0, 0, 0, 0, 0, 0, 0, 0 },
203       { 0, 0, 0, 0, 0, 0, 0, 0 },
204       { 0, 0, 0, 0, 0, 0, 0, 0 },
205       { 0, 0, 0, 0, 0, 0, 0, 0 } },
206     // 3F2R out
207     { { 0, 1, 0, 0, 0, 0, 0, 0 },
208       { 0, 0, 1, 0, 0, 0, 0, 0 },
209       { 0, 0, 0, 0, 0, 1, 0, 0 },
210       { 0, 0, 0, 0, 0, 0, 0, 0 },
211       { 0, 0, 0, 0, 0, 0, 0, 0 },
212       { 0, 0, 0, 0, 0, 0, 0, 0 },
213       { 0, 0, 0, 0, 0, 0, 0, 0 },
214       { 0, 0, 0, 0, 0, 0, 0, 0 } },
215     // 3F4R out
216     { { 0, 1, 0, 0, 0, 0, 0, 0 },
217       { 0, 0, 1, 0, 0, 0, 0, 0 },
218       { 0, 0, 0, 0, 0, 0, 0, 1 },
219       { 0, 0, 0, 0, 0, 0, 0, 0 },
220       { 0, 0, 0, 0, 0, 0, 0, 0 },
221       { 0, 0, 0, 0, 0, 0, 0, 0 },
222       { 0, 0, 0, 0, 0, 0, 0, 0 },
223       { 0, 0, 0, 0, 0, 0, 0, 0 } },
224     // DOLBY out
225     { { 1, 0, 0, 0, 0, 0, 0, 0 },
226       { 0, 1, 0, 0, 0, 0, 0, 0 },
227       { 0, 0, 1, 0, 0, 0, 0, 0 },
228       { 0, 0, 0, 0, 0, 0, 0, 0 },
229       { 0, 0, 0, 0, 0, 0, 0, 0 },
230       { 0, 0, 0, 0, 0, 0, 0, 0 },
231       { 0, 0, 0, 0, 0, 0, 0, 0 },
232       { 0, 0, 0, 0, 0, 0, 0, 0 } },
233     // DPLII out
234     { { 1, 0, 0, 0, 0, 0, 0, 0 },
235       { 0, 1, 0, 0, 0, 0, 0, 0 },
236       { 0, 0, 1, 0, 0, 0, 0, 0 },
237       { 0, 0, 0, 0, 0, 0, 0, 0 },
238       { 0, 0, 0, 0, 0, 0, 0, 0 },
239       { 0, 0, 0, 0, 0, 0, 0, 0 },
240       { 0, 0, 0, 0, 0, 0, 0, 0 },
241       { 0, 0, 0, 0, 0, 0, 0, 0 } },
242 },
243 // 3F in
244 {
245     // MONO out
246     { { LVL_PLUS3DB, 0, 0, 0, 0, 0, 0, 0 },
247       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
248       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
249       { 0,           1, 0, 0, 0, 0, 0, 0 },
250       { 0,           0, 0, 0, 0, 0, 0, 0 },
251       { 0,           0, 0, 0, 0, 0, 0, 0 },
252       { 0,           0, 0, 0, 0, 0, 0, 0 },
253       { 0,           0, 0, 0, 0, 0, 0, 0 } },
254     // STEREO out
255     { { 1, 1, 0, 0, 0, 0, 0, 0 },
256       { 1, 0, 0, 0, 0, 0, 0, 0 },
257       { 0, 1, 0, 0, 0, 0, 0, 0 },
258       { 0, 0, 1, 0, 0, 0, 0, 0 },
259       { 0, 0, 0, 0, 0, 0, 0, 0 },
260       { 0, 0, 0, 0, 0, 0, 0, 0 },
261       { 0, 0, 0, 0, 0, 0, 0, 0 },
262       { 0, 0, 0, 0, 0, 0, 0, 0 } },
263     // 3F out
264     { { 1, 0, 0, 0, 0, 0, 0, 0 },
265       { 0, 1, 0, 0, 0, 0, 0, 0 },
266       { 0, 0, 1, 0, 0, 0, 0, 0 },
267       { 0, 0, 0, 1, 0, 0, 0, 0 },
268       { 0, 0, 0, 0, 0, 0, 0, 0 },
269       { 0, 0, 0, 0, 0, 0, 0, 0 },
270       { 0, 0, 0, 0, 0, 0, 0, 0 },
271       { 0, 0, 0, 0, 0, 0, 0, 0 } },
272     // 2F1R out
273     { { 1, 1, 0, 0, 0, 0, 0, 0 },
274       { 1, 0, 0, 0, 0, 0, 0, 0 },
275       { 0, 1, 0, 0, 0, 0, 0, 0 },
276       { 0, 0, 0, 1, 0, 0, 0, 0 },
277       { 0, 0, 0, 0, 0, 0, 0, 0 },
278       { 0, 0, 0, 0, 0, 0, 0, 0 },
279       { 0, 0, 0, 0, 0, 0, 0, 0 },
280       { 0, 0, 0, 0, 0, 0, 0, 0 } },
281     // 3F1R out
282     { { 1, 0, 0, 0, 0, 0, 0, 0 },
283       { 0, 1, 0, 0, 0, 0, 0, 0 },
284       { 0, 0, 1, 0, 0, 0, 0, 0 },
285       { 0, 0, 0, 0, 1, 0, 0, 0 },
286       { 0, 0, 0, 0, 0, 0, 0, 0 },
287       { 0, 0, 0, 0, 0, 0, 0, 0 },
288       { 0, 0, 0, 0, 0, 0, 0, 0 },
289       { 0, 0, 0, 0, 0, 0, 0, 0 } },
290     // 2F2R out
291     { { 1, 1, 0, 0, 0, 0, 0, 0 },
292       { 1, 0, 0, 0, 0, 0, 0, 0 },
293       { 0, 1, 0, 0, 0, 0, 0, 0 },
294       { 0, 0, 0, 0, 1, 0, 0, 0 },
295       { 0, 0, 0, 0, 0, 0, 0, 0 },
296       { 0, 0, 0, 0, 0, 0, 0, 0 },
297       { 0, 0, 0, 0, 0, 0, 0, 0 },
298       { 0, 0, 0, 0, 0, 0, 0, 0 } },
299     // 3F2R out
300     { { 1, 0, 0, 0, 0, 0, 0, 0 },
301       { 0, 1, 0, 0, 0, 0, 0, 0 },
302       { 0, 0, 1, 0, 0, 0, 0, 0 },
303       { 0, 0, 0, 0, 0, 1, 0, 0 },
304       { 0, 0, 0, 0, 0, 0, 0, 0 },
305       { 0, 0, 0, 0, 0, 0, 0, 0 },
306       { 0, 0, 0, 0, 0, 0, 0, 0 },
307       { 0, 0, 0, 0, 0, 0, 0, 0 } },
308     // 3F4R out
309     { { 1, 0, 0, 0, 0, 0, 0, 0 },
310       { 0, 1, 0, 0, 0, 0, 0, 0 },
311       { 0, 0, 1, 0, 0, 0, 0, 0 },
312       { 0, 0, 0, 0, 0, 0, 0, 1 },
313       { 0, 0, 0, 0, 0, 0, 0, 0 },
314       { 0, 0, 0, 0, 0, 0, 0, 0 },
315       { 0, 0, 0, 0, 0, 0, 0, 0 },
316       { 0, 0, 0, 0, 0, 0, 0, 0 } },
317     // DOLBY out
318     { { 1, 1, 0, 0, 0, 0, 0, 0 },
319       { 1, 0, 0, 0, 0, 0, 0, 0 },
320       { 0, 1, 0, 0, 0, 0, 0, 0 },
321       { 0, 0, 1, 0, 0, 0, 0, 0 },
322       { 0, 0, 0, 0, 0, 0, 0, 0 },
323       { 0, 0, 0, 0, 0, 0, 0, 0 },
324       { 0, 0, 0, 0, 0, 0, 0, 0 },
325       { 0, 0, 0, 0, 0, 0, 0, 0 } },
326     // DPLII out
327     { { 1, 1, 0, 0, 0, 0, 0, 0 },
328       { 1, 0, 0, 0, 0, 0, 0, 0 },
329       { 0, 1, 0, 0, 0, 0, 0, 0 },
330       { 0, 0, 1, 0, 0, 0, 0, 0 },
331       { 0, 0, 0, 0, 0, 0, 0, 0 },
332       { 0, 0, 0, 0, 0, 0, 0, 0 },
333       { 0, 0, 0, 0, 0, 0, 0, 0 },
334       { 0, 0, 0, 0, 0, 0, 0, 0 } },
335 },
336 // 2F1R in
337 {
338     // MONO out
339     { { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
340       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
341       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
342       { 0,           1, 0, 0, 0, 0, 0, 0 },
343       { 0,           0, 0, 0, 0, 0, 0, 0 },
344       { 0,           0, 0, 0, 0, 0, 0, 0 },
345       { 0,           0, 0, 0, 0, 0, 0, 0 },
346       { 0,           0, 0, 0, 0, 0, 0, 0 } },
347     // STEREO out
348     { { 1,       0,       0, 0, 0, 0, 0, 0 },
349       { 0,       1,       0, 0, 0, 0, 0, 0 },
350       { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
351       { 0,       0,       1, 0, 0, 0, 0, 0 },
352       { 0,       0,       0, 0, 0, 0, 0, 0 },
353       { 0,       0,       0, 0, 0, 0, 0, 0 },
354       { 0,       0,       0, 0, 0, 0, 0, 0 },
355       { 0,       0,       0, 0, 0, 0, 0, 0 } },
356     // 3F out
357     { { 0, 1,       0,       0, 0, 0, 0, 0 },
358       { 0, 0,       1,       0, 0, 0, 0, 0 },
359       { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
360       { 0, 0,       0,       1, 0, 0, 0, 0 },
361       { 0, 0,       0,       0, 0, 0, 0, 0 },
362       { 0, 0,       0,       0, 0, 0, 0, 0 },
363       { 0, 0,       0,       0, 0, 0, 0, 0 },
364       { 0, 0,       0,       0, 0, 0, 0, 0 } },
365     // 2F1R out
366     { { 1, 0, 0, 0, 0, 0, 0, 0 },
367       { 0, 1, 0, 0, 0, 0, 0, 0 },
368       { 0, 0, 1, 0, 0, 0, 0, 0 },
369       { 0, 0, 0, 1, 0, 0, 0, 0 },
370       { 0, 0, 0, 0, 0, 0, 0, 0 },
371       { 0, 0, 0, 0, 0, 0, 0, 0 },
372       { 0, 0, 0, 0, 0, 0, 0, 0 },
373       { 0, 0, 0, 0, 0, 0, 0, 0 } },
374     // 3F1R out
375     { { 0, 1, 0, 0, 0, 0, 0, 0 },
376       { 0, 0, 1, 0, 0, 0, 0, 0 },
377       { 0, 0, 0, 1, 0, 0, 0, 0 },
378       { 0, 0, 0, 0, 1, 0, 0, 0 },
379       { 0, 0, 0, 0, 0, 0, 0, 0 },
380       { 0, 0, 0, 0, 0, 0, 0, 0 },
381       { 0, 0, 0, 0, 0, 0, 0, 0 },
382       { 0, 0, 0, 0, 0, 0, 0, 0 } },
383     // 2F2R out
384     { { 1, 0, 0,       0,       0, 0, 0, 0 },
385       { 0, 1, 0,       0,       0, 0, 0, 0 },
386       { 0, 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0 },
387       { 0, 0, 0,       0,       1, 0, 0, 0 },
388       { 0, 0, 0,       0,       0, 0, 0, 0 },
389       { 0, 0, 0,       0,       0, 0, 0, 0 },
390       { 0, 0, 0,       0,       0, 0, 0, 0 },
391       { 0, 0, 0,       0,       0, 0, 0, 0 } },
392     // 3F2R out
393     { { 0, 1, 0, 0,       0,       0, 0, 0 },
394       { 0, 0, 1, 0,       0,       0, 0, 0 },
395       { 0, 0, 0, LVL_3DB, LVL_3DB, 0, 0, 0 },
396       { 0, 0, 0, 0,       0,       1, 0, 0 },
397       { 0, 0, 0, 0,       0,       0, 0, 0 },
398       { 0, 0, 0, 0,       0,       0, 0, 0 },
399       { 0, 0, 0, 0,       0,       0, 0, 0 },
400       { 0, 0, 0, 0,       0,       0, 0, 0 } },
401     // 3F4R out
402     { { 0, 1, 0, 0, 0, 0,       0      , 0 },
403       { 0, 0, 1, 0, 0, 0,       0      , 0 },
404       { 0, 0, 0, 0, 0, LVL_3DB, LVL_3DB, 0 },
405       { 0, 0, 0, 0, 0, 0,       0      , 1 },
406       { 0, 0, 0, 0, 0, 0,       0      , 0 },
407       { 0, 0, 0, 0, 0, 0,       0      , 0 },
408       { 0, 0, 0, 0, 0, 0,       0      , 0 },
409       { 0, 0, 0, 0, 0, 0,       0      , 0 } },
410     // DOLBY out
411     { { 1,        0,       0, 0, 0, 0, 0, 0 },
412       { 0,        1,       0, 0, 0, 0, 0, 0 },
413       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
414       { 0,        0,       1, 0, 0, 0, 0, 0 },
415       { 0,        0,       0, 0, 0, 0, 0, 0 },
416       { 0,        0,       0, 0, 0, 0, 0, 0 },
417       { 0,        0,       0, 0, 0, 0, 0, 0 },
418       { 0,        0,       0, 0, 0, 0, 0, 0 } },
419     // DPLII out
420     { { 1,        0,       0, 0, 0, 0, 0, 0 },
421       { 0,        1,       0, 0, 0, 0, 0, 0 },
422       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
423       { 0,        0,       1, 0, 0, 0, 0, 0 },
424       { 0,        0,       0, 0, 0, 0, 0, 0 },
425       { 0,        0,       0, 0, 0, 0, 0, 0 },
426       { 0,        0,       0, 0, 0, 0, 0, 0 },
427       { 0,        0,       0, 0, 0, 0, 0, 0 } },
428 },
429 // 3F1R in
430 {
431     // MONO out
432     { { LVL_PLUS3DB, 0, 0, 0, 0, 0, 0, 0 },
433       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
434       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
435       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
436       { 0,           1, 0, 0, 0, 0, 0, 0 },
437       { 0,           0, 0, 0, 0, 0, 0, 0 },
438       { 0,           0, 0, 0, 0, 0, 0, 0 },
439       { 0,           0, 0, 0, 0, 0, 0, 0 } },
440     // STEREO out
441     { { 1,       1,       0, 0, 0, 0, 0, 0 },
442       { 1,       0,       0, 0, 0, 0, 0, 0 },
443       { 0,       1,       0, 0, 0, 0, 0, 0 },
444       { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
445       { 0,       0,       1, 0, 0, 0, 0, 0 },
446       { 0,       0,       0, 0, 0, 0, 0, 0 },
447       { 0,       0,       0, 0, 0, 0, 0, 0 },
448       { 0,       0,       0, 0, 0, 0, 0, 0 } },
449     // 3F out
450     { { 1, 0,       0,       0, 0, 0, 0, 0 },
451       { 0, 1,       0,       0, 0, 0, 0, 0 },
452       { 0, 0,       1,       0, 0, 0, 0, 0 },
453       { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
454       { 0, 0,       0,       1, 0, 0, 0, 0 },
455       { 0, 0,       0,       0, 0, 0, 0, 0 },
456       { 0, 0,       0,       0, 0, 0, 0, 0 },
457       { 0, 0,       0,       0, 0, 0, 0, 0 } },
458     // 2F1R out
459     { { 1, 1, 0, 0, 0, 0, 0, 0 },
460       { 1, 0, 0, 0, 0, 0, 0, 0 },
461       { 0, 1, 0, 0, 0, 0, 0, 0 },
462       { 0, 0, 1, 0, 0, 0, 0, 0 },
463       { 0, 0, 0, 1, 0, 0, 0, 0 },
464       { 0, 0, 0, 0, 0, 0, 0, 0 },
465       { 0, 0, 0, 0, 0, 0, 0, 0 },
466       { 0, 0, 0, 0, 0, 0, 0, 0 } },
467     // 3F1R out
468     { { 1, 0, 0, 0, 0, 0, 0, 0 },
469       { 0, 1, 0, 0, 0, 0, 0, 0 },
470       { 0, 0, 1, 0, 0, 0, 0, 0 },
471       { 0, 0, 0, 1, 0, 0, 0, 0 },
472       { 0, 0, 0, 0, 1, 0, 0, 0 },
473       { 0, 0, 0, 0, 0, 0, 0, 0 },
474       { 0, 0, 0, 0, 0, 0, 0, 0 },
475       { 0, 0, 0, 0, 0, 0, 0, 0 } },
476     // 2F2R out
477     { { 1, 1, 0,       0,       0, 0, 0, 0 },
478       { 1, 0, 0,       0,       0, 0, 0, 0 },
479       { 0, 1, 0,       0,       0, 0, 0, 0 },
480       { 0, 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0 },
481       { 0, 0, 0,       0,       1, 0, 0, 0 },
482       { 0, 0, 0,       0,       0, 0, 0, 0 },
483       { 0, 0, 0,       0,       0, 0, 0, 0 },
484       { 0, 0, 0,       0,       0, 0, 0, 0 } },
485     // 3F2R out
486     { { 1, 0, 0, 0,       0,       0, 0, 0 },
487       { 0, 1, 0, 0,       0,       0, 0, 0 },
488       { 0, 0, 1, 0,       0,       0, 0, 0 },
489       { 0, 0, 0, LVL_3DB, LVL_3DB, 0, 0, 0 },
490       { 0, 0, 0, 0,       0,       1, 0, 0 },
491       { 0, 0, 0, 0,       0,       0, 0, 0 },
492       { 0, 0, 0, 0,       0,       0, 0, 0 },
493       { 0, 0, 0, 0,       0,       0, 0, 0 } },
494     // 3F4R out
495     { { 1, 0, 0, 0, 0, 0,       0      , 0 },
496       { 0, 1, 0, 0, 0, 0,       0      , 0 },
497       { 0, 0, 1, 0, 0, 0,       0      , 0 },
498       { 0, 0, 0, 0, 0, LVL_3DB, LVL_3DB, 0 },
499       { 0, 0, 0, 0, 0, 0,       0      , 1 },
500       { 0, 0, 0, 0, 0, 0,       0      , 0 },
501       { 0, 0, 0, 0, 0, 0,       0      , 0 },
502       { 0, 0, 0, 0, 0, 0,       0      , 0 } },
503     // DOLBY out
504     { { LVL_3DB,  LVL_3DB, 0, 0, 0, 0, 0, 0 },
505       { 1,        0,       0, 0, 0, 0, 0, 0 },
506       { 0,        1,       0, 0, 0, 0, 0, 0 },
507       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
508       { 0,        0,       1, 0, 0, 0, 0, 0 },
509       { 0,        0,       0, 0, 0, 0, 0, 0 },
510       { 0,        0,       0, 0, 0, 0, 0, 0 },
511       { 0,        0,       0, 0, 0, 0, 0, 0 } },
512     // DPLII out
513     { { LVL_3DB,  LVL_3DB, 0, 0, 0, 0, 0, 0 },
514       { 1,        0,       0, 0, 0, 0, 0, 0 },
515       { 0,        1,       0, 0, 0, 0, 0, 0 },
516       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
517       { 0,        0,       1, 0, 0, 0, 0, 0 },
518       { 0,        0,       0, 0, 0, 0, 0, 0 },
519       { 0,        0,       0, 0, 0, 0, 0, 0 },
520       { 0,        0,       0, 0, 0, 0, 0, 0 } },
521 },
522 // 2F2R in
523 {
524     // MONO out
525     { { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
526       { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
527       { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
528       { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
529       { 0,       1, 0, 0, 0, 0, 0, 0 },
530       { 0,       0, 0, 0, 0, 0, 0, 0 },
531       { 0,       0, 0, 0, 0, 0, 0, 0 },
532       { 0,       0, 0, 0, 0, 0, 0, 0 } },
533     // STEREO out
534     { { 1, 0, 0, 0, 0, 0, 0, 0 },
535       { 0, 1, 0, 0, 0, 0, 0, 0 },
536       { 1, 0, 0, 0, 0, 0, 0, 0 },
537       { 0, 1, 0, 0, 0, 0, 0, 0 },
538       { 0, 0, 1, 0, 0, 0, 0, 0 },
539       { 0, 0, 0, 0, 0, 0, 0, 0 },
540       { 0, 0, 0, 0, 0, 0, 0, 0 },
541       { 0, 0, 0, 0, 0, 0, 0, 0 } },
542     // 3F out
543     { { 0, 1, 0, 0, 0, 0, 0, 0 },
544       { 0, 0, 1, 0, 0, 0, 0, 0 },
545       { 0, 1, 0, 0, 0, 0, 0, 0 },
546       { 0, 0, 1, 0, 0, 0, 0, 0 },
547       { 0, 0, 0, 1, 0, 0, 0, 0 },
548       { 0, 0, 0, 0, 0, 0, 0, 0 },
549       { 0, 0, 0, 0, 0, 0, 0, 0 },
550       { 0, 0, 0, 0, 0, 0, 0, 0 } },
551     // 2F1R out
552     { { 1, 0, 0,       0, 0, 0, 0, 0 },
553       { 0, 1, 0,       0, 0, 0, 0, 0 },
554       { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
555       { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
556       { 0, 0, 0,       1, 0, 0, 0, 0 },
557       { 0, 0, 0,       0, 0, 0, 0, 0 },
558       { 0, 0, 0,       0, 0, 0, 0, 0 },
559       { 0, 0, 0,       0, 0, 0, 0, 0 } },
560     // 3F1R out
561     { { 0, 1, 0, 0,       0, 0, 0, 0 },
562       { 0, 0, 1, 0,       0, 0, 0, 0 },
563       { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
564       { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
565       { 0, 0, 0, 0,       1, 0, 0, 0 },
566       { 0, 0, 0, 0,       0, 0, 0, 0 },
567       { 0, 0, 0, 0,       0, 0, 0, 0 },
568       { 0, 0, 0, 0,       0, 0, 0, 0 } },
569     // 2F2R out
570     { { 1, 0, 0, 0, 0, 0, 0, 0 },
571       { 0, 1, 0, 0, 0, 0, 0, 0 },
572       { 0, 0, 1, 0, 0, 0, 0, 0 },
573       { 0, 0, 0, 1, 0, 0, 0, 0 },
574       { 0, 0, 0, 0, 1, 0, 0, 0 },
575       { 0, 0, 0, 0, 0, 0, 0, 0 },
576       { 0, 0, 0, 0, 0, 0, 0, 0 },
577       { 0, 0, 0, 0, 0, 0, 0, 0 } },
578     // 3F2R out
579     { { 0, 1, 0, 0, 0, 0, 0, 0 },
580       { 0, 0, 1, 0, 0, 0, 0, 0 },
581       { 0, 0, 0, 1, 0, 0, 0, 0 },
582       { 0, 0, 0, 0, 1, 0, 0, 0 },
583       { 0, 0, 0, 0, 0, 1, 0, 0 },
584       { 0, 0, 0, 0, 0, 0, 0, 0 },
585       { 0, 0, 0, 0, 0, 0, 0, 0 },
586       { 0, 0, 0, 0, 0, 0, 0, 0 } },
587     // 3F4R out
588     { { 0, 1, 0, 0, 0, 0, 0, 0 },
589       { 0, 0, 1, 0, 0, 0, 0, 0 },
590       { 0, 0, 0, 0, 0, 1, 0, 0 },
591       { 0, 0, 0, 0, 0, 0, 1, 0 },
592       { 0, 0, 0, 0, 0, 0, 0, 1 },
593       { 0, 0, 0, 0, 0, 0, 0, 0 },
594       { 0, 0, 0, 0, 0, 0, 0, 0 },
595       { 0, 0, 0, 0, 0, 0, 0, 0 } },
596     // DOLBY out
597     { { 1,        0,       0, 0, 0, 0, 0, 0 },
598       { 0,        1,       0, 0, 0, 0, 0, 0 },
599       { -LVL_6DB, LVL_6DB, 0, 0, 0, 0, 0, 0 },
600       { -LVL_6DB, LVL_6DB, 0, 0, 0, 0, 0, 0 },
601       { 0,        0,       1, 0, 0, 0, 0, 0 },
602       { 0,        0,       0, 0, 0, 0, 0, 0 },
603       { 0,        0,       0, 0, 0, 0, 0, 0 },
604       { 0,        0,       0, 0, 0, 0, 0, 0 } },
605     // DPLII out
606     { { 1,             0,             0, 0, 0, 0, 0, 0 },
607       { 0,             1,             0, 0, 0, 0, 0, 0 },
608       { LVL_SQRT_2_3,  -LVL_SQRT_1_3, 0, 0, 0, 0, 0, 0 },
609       { -LVL_SQRT_1_3, LVL_SQRT_2_3,  0, 0, 0, 0, 0, 0 },
610       { 0,             0,             1, 0, 0, 0, 0, 0 },
611       { 0,             0,             0, 0, 0, 0, 0, 0 },
612       { 0,             0,             0, 0, 0, 0, 0, 0 },
613       { 0,             0,             0, 0, 0, 0, 0, 0 } },
614 },
615 // 3F2R in
616 {
617     // MONO out
618     { { LVL_PLUS3DB, 0, 0, 0, 0, 0, 0, 0 },
619       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
620       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
621       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
622       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
623       { 0,           1, 0, 0, 0, 0, 0, 0 },
624       { 0,           0, 0, 0, 0, 0, 0, 0 },
625       { 0,           0, 0, 0, 0, 0, 0, 0 } },
626     // STEREO out
627     { { 1, 1, 0, 0, 0, 0, 0, 0 },
628       { 1, 0, 0, 0, 0, 0, 0, 0 },
629       { 0, 1, 0, 0, 0, 0, 0, 0 },
630       { 1, 0, 0, 0, 0, 0, 0, 0 },
631       { 0, 1, 0, 0, 0, 0, 0, 0 },
632       { 0, 0, 1, 0, 0, 0, 0, 0 },
633       { 0, 0, 0, 0, 0, 0, 0, 0 },
634       { 0, 0, 0, 0, 0, 0, 0, 0 } },
635     // 3F out
636     { { 1, 0, 0, 0, 0, 0, 0, 0 },
637       { 0, 1, 0, 0, 0, 0, 0, 0 },
638       { 0, 0, 1, 0, 0, 0, 0, 0 },
639       { 0, 1, 0, 0, 0, 0, 0, 0 },
640       { 0, 0, 1, 0, 0, 0, 0, 0 },
641       { 0, 0, 0, 1, 0, 0, 0, 0 },
642       { 0, 0, 0, 0, 0, 0, 0, 0 },
643       { 0, 0, 0, 0, 0, 0, 0, 0 } },
644     // 2F1R out
645     { { 1, 1, 0,       0, 0, 0, 0, 0 },
646       { 1, 0, 0,       0, 0, 0, 0, 0 },
647       { 0, 1, 0,       0, 0, 0, 0, 0 },
648       { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
649       { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
650       { 0, 0, 0,       1, 0, 0, 0, 0 },
651       { 0, 0, 0,       0, 0, 0, 0, 0 },
652       { 0, 0, 0,       0, 0, 0, 0, 0 } },
653     // 3F1R out
654     { { 1, 0, 0, 0,       0, 0, 0, 0 },
655       { 0, 1, 0, 0,       0, 0, 0, 0 },
656       { 0, 0, 1, 0,       0, 0, 0, 0 },
657       { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
658       { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
659       { 0, 0, 0, 0,       1, 0, 0, 0 },
660       { 0, 0, 0, 0,       0, 0, 0, 0 },
661       { 0, 0, 0, 0,       0, 0, 0, 0 } },
662     // 2F2R out
663     { { 1, 1, 0, 0, 0, 0, 0, 0 },
664       { 1, 0, 0, 0, 0, 0, 0, 0 },
665       { 0, 1, 0, 0, 0, 0, 0, 0 },
666       { 0, 0, 1, 0, 0, 0, 0, 0 },
667       { 0, 0, 0, 1, 0, 0, 0, 0 },
668       { 0, 0, 0, 0, 1, 0, 0, 0 },
669       { 0, 0, 0, 0, 0, 0, 0, 0 },
670       { 0, 0, 0, 0, 0, 0, 0, 0 } },
671     // 3F2R out
672     { { 1, 0, 0, 0, 0, 0, 0, 0 },
673       { 0, 1, 0, 0, 0, 0, 0, 0 },
674       { 0, 0, 1, 0, 0, 0, 0, 0 },
675       { 0, 0, 0, 1, 0, 0, 0, 0 },
676       { 0, 0, 0, 0, 1, 0, 0, 0 },
677       { 0, 0, 0, 0, 0, 1, 0, 0 },
678       { 0, 0, 0, 0, 0, 0, 0, 0 },
679       { 0, 0, 0, 0, 0, 0, 0, 0 } },
680     // 3F4R out
681     { { 1, 0, 0, 0, 0, 0, 0, 0 },
682       { 0, 1, 0, 0, 0, 0, 0, 0 },
683       { 0, 0, 1, 0, 0, 0, 0, 0 },
684       { 0, 0, 0, 0, 0, 1, 0, 0 },
685       { 0, 0, 0, 0, 0, 0, 1, 0 },
686       { 0, 0, 0, 0, 0, 0, 0, 1 },
687       { 0, 0, 0, 0, 0, 0, 0, 0 },
688       { 0, 0, 0, 0, 0, 0, 0, 0 } },
689     // DOLBY out
690     { { LVL_3DB,  LVL_3DB, 0, 0, 0, 0, 0, 0 },
691       { 1,        0,       0, 0, 0, 0, 0, 0 },
692       { 0,        1,       0, 0, 0, 0, 0, 0 },
693       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
694       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
695       { 0,        0,       1, 0, 0, 0, 0, 0 },
696       { 0,        0,       0, 0, 0, 0, 0, 0 },
697       { 0,        0,       0, 0, 0, 0, 0, 0 } },
698     // DPLII out
699     { { LVL_3DB,       LVL_3DB,       0, 0, 0, 0, 0, 0 },
700       { 1,             0,             0, 0, 0, 0, 0, 0 },
701       { 0,             1,             0, 0, 0, 0, 0, 0 },
702       { LVL_SQRT_2_3,  -LVL_SQRT_1_3, 0, 0, 0, 0, 0, 0 },
703       { -LVL_SQRT_1_3, LVL_SQRT_2_3,  0, 0, 0, 0, 0, 0 },
704       { 0,             0,             1, 0, 0, 0, 0, 0 },
705       { 0,             0,             0, 0, 0, 0, 0, 0 },
706       { 0,             0,             0, 0, 0, 0, 0, 0 } },
707 },
708 // 3F4R in
709 {
710     // MONO out
711     { { LVL_PLUS3DB, 0, 0, 0, 0, 0, 0, 0 },
712       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
713       { LVL_3DB,     0, 0, 0, 0, 0, 0, 0 },
714       { LVL_6DB,     0, 0, 0, 0, 0, 0, 0 },
715       { LVL_6DB,     0, 0, 0, 0, 0, 0, 0 },
716       { LVL_6DB,     0, 0, 0, 0, 0, 0, 0 },
717       { LVL_6DB,     0, 0, 0, 0, 0, 0, 0 },
718       { 0,           1, 0, 0, 0, 0, 0, 0 } },
719     // STEREO out
720     { { 1,       1,       0, 0, 0, 0, 0, 0 },
721       { 1,       0,       0, 0, 0, 0, 0, 0 },
722       { 0,       1,       0, 0, 0, 0, 0, 0 },
723       { LVL_3DB, 0,       0, 0, 0, 0, 0, 0 },
724       { 0,       LVL_3DB, 0, 0, 0, 0, 0, 0 },
725       { LVL_3DB, 0,       0, 0, 0, 0, 0, 0 },
726       { 0,       LVL_3DB, 0, 0, 0, 0, 0, 0 },
727       { 0,       0,       1, 0, 0, 0, 0, 0 } },
728     // 3F out
729     { { 1, 0,       0,       0, 0, 0, 0, 0 },
730       { 0, 1,       0,       0, 0, 0, 0, 0 },
731       { 0, 0,       1,       0, 0, 0, 0, 0 },
732       { 0, LVL_3DB, 0,       0, 0, 0, 0, 0 },
733       { 0, 0,       LVL_3DB, 0, 0, 0, 0, 0 },
734       { 0, LVL_3DB, 0,       0, 0, 0, 0, 0 },
735       { 0, 0,       LVL_3DB, 0, 0, 0, 0, 0 },
736       { 0, 0,       0,       1, 0, 0, 0, 0 } },
737     // 2F1R out
738     { { 1, 1, 0,       0, 0, 0, 0, 0 },
739       { 1, 0, 0,       0, 0, 0, 0, 0 },
740       { 0, 1, 0,       0, 0, 0, 0, 0 },
741       { 0, 0, LVL_6DB, 0, 0, 0, 0, 0 },
742       { 0, 0, LVL_6DB, 0, 0, 0, 0, 0 },
743       { 0, 0, LVL_6DB, 0, 0, 0, 0, 0 },
744       { 0, 0, LVL_6DB, 0, 0, 0, 0, 0 },
745       { 0, 0, 0,       1, 0, 0, 0, 0 } },
746     // 3F1R out
747     { { 1, 0, 0, 0,       0, 0, 0, 0 },
748       { 0, 1, 0, 0,       0, 0, 0, 0 },
749       { 0, 0, 1, 0,       0, 0, 0, 0 },
750       { 0, 0, 0, LVL_6DB, 0, 0, 0, 0 },
751       { 0, 0, 0, LVL_6DB, 0, 0, 0, 0 },
752       { 0, 0, 0, LVL_6DB, 0, 0, 0, 0 },
753       { 0, 0, 0, LVL_6DB, 0, 0, 0, 0 },
754       { 0, 0, 0, 0,       1, 0, 0, 0 } },
755     // 2F2R out
756     { { 1, 1, 0,       0,       0, 0, 0, 0 },
757       { 1, 0, 0,       0,       0, 0, 0, 0 },
758       { 0, 1, 0,       0,       0, 0, 0, 0 },
759       { 0, 0, LVL_3DB, 0,       0, 0, 0, 0 },
760       { 0, 0, 0,       LVL_3DB, 0, 0, 0, 0 },
761       { 0, 0, LVL_3DB, 0,       0, 0, 0, 0 },
762       { 0, 0, 0,       LVL_3DB, 0, 0, 0, 0 },
763       { 0, 0, 0,       0,       1, 0, 0, 0 } },
764     // 3F2R out
765     { { 1, 0, 0, 0,       0,       0, 0, 0 },
766       { 0, 1, 0, 0,       0,       0, 0, 0 },
767       { 0, 0, 1, 0,       0,       0, 0, 0 },
768       { 0, 0, 0, LVL_3DB, 0,       0, 0, 0 },
769       { 0, 0, 0, 0,       LVL_3DB, 0, 0, 0 },
770       { 0, 0, 0, LVL_3DB, 0,       0, 0, 0 },
771       { 0, 0, 0, 0,       LVL_3DB, 0, 0, 0 },
772       { 0, 0, 0, 0,       0,       1, 0, 0 } },
773     // 3F4R out
774     { { 1, 0, 0, 0, 0, 0, 0, 0 },
775       { 0, 1, 0, 0, 0, 0, 0, 0 },
776       { 0, 0, 1, 0, 0, 0, 0, 0 },
777       { 0, 0, 0, 1, 0, 0, 0, 0 },
778       { 0, 0, 0, 0, 1, 0, 0, 0 },
779       { 0, 0, 0, 0, 0, 1, 0, 0 },
780       { 0, 0, 0, 0, 0, 0, 1, 0 },
781       { 0, 0, 0, 0, 0, 0, 0, 1 } },
782     // DOLBY out
783     { { LVL_3DB,  LVL_3DB, 0, 0, 0, 0, 0, 0 },
784       { 1,        0,       0, 0, 0, 0, 0, 0 },
785       { 0,        1,       0, 0, 0, 0, 0, 0 },
786       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
787       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
788       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
789       { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
790       { 0,        0,       1, 0, 0, 0, 0, 0 } },
791     // DPLII out
792     { { LVL_3DB,               LVL_3DB,               0, 0, 0, 0, 0, 0 },
793       { 1,                     0,                     0, 0, 0, 0, 0, 0 },
794       { 0,                     1,                     0, 0, 0, 0, 0, 0 },
795       { LVL_SQRT_2_3*LVL_3DB,  -LVL_SQRT_1_3*LVL_3DB, 0, 0, 0, 0, 0, 0 },
796       { -LVL_SQRT_1_3*LVL_3DB, LVL_SQRT_2_3*LVL_3DB,  0, 0, 0, 0, 0, 0 },
797       { LVL_SQRT_2_3*LVL_3DB,  -LVL_SQRT_1_3*LVL_3DB, 0, 0, 0, 0, 0, 0 },
798       { -LVL_SQRT_1_3*LVL_3DB, LVL_SQRT_2_3*LVL_3DB,  0, 0, 0, 0, 0, 0 },
799       { 0,                     0,                     1, 0, 0, 0, 0, 0 } }
800 },
801 };
802
803 static int channel_layout_map[DOWNMIX_NUM_MODES] =
804 {
805     // DOWNMIX_MONO 
806     (HB_CH_FRONT_CENTER),
807     // DOWNMIX_STEREO 
808     (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT),
809     // DOWNMIX_3F 
810     (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_FRONT_CENTER),
811     // DOWNMIX_2F1R 
812     (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_BACK_CENTER),
813     // DOWNMIX_3F1R 
814     (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_FRONT_CENTER|HB_CH_BACK_CENTER),
815     // DOWNMIX_2F2R 
816     (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT),
817     // DOWNMIX_3F2R 
818     (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_FRONT_CENTER|HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT),
819     // DOWNMIX_3F4R 
820     (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_FRONT_CENTER|HB_CH_SIDE_LEFT|
821      HB_CH_SIDE_RIGHT|HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT),
822     // DOWNMIX_DOLBY 
823     (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT),
824     // DOWNMIX_DPLII 
825     (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT)
826 };
827
828 int hb_layout_to_mode(int layout)
829 {
830     int mode;
831     switch (layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK)
832     {
833         case HB_INPUT_CH_LAYOUT_MONO:
834             mode = DOWNMIX_MONO;
835             break;
836         case HB_INPUT_CH_LAYOUT_STEREO:
837             mode = DOWNMIX_STEREO;
838             break;
839         case HB_INPUT_CH_LAYOUT_3F:
840             mode = DOWNMIX_3F;
841             break;
842         case HB_INPUT_CH_LAYOUT_2F1R:
843             mode = DOWNMIX_2F1R;
844             break;
845         case HB_INPUT_CH_LAYOUT_3F1R:
846             mode = DOWNMIX_3F1R;
847             break;
848         case HB_INPUT_CH_LAYOUT_2F2R:
849             mode = DOWNMIX_2F2R;
850             break;
851         case HB_INPUT_CH_LAYOUT_3F2R:
852             mode = DOWNMIX_3F2R;
853             break;
854         case HB_INPUT_CH_LAYOUT_4F2R:
855             mode = DOWNMIX_3F2R|DOWNMIX_LFE_FLAG;
856             break;
857         case HB_INPUT_CH_LAYOUT_3F4R:
858             mode = DOWNMIX_3F4R;
859             break;
860         case HB_INPUT_CH_LAYOUT_DOLBY:
861             mode = DOWNMIX_STEREO;
862             break;
863         default:
864             mode = DOWNMIX_STEREO;
865             break;
866     }
867     if (layout & HB_INPUT_CH_LAYOUT_DISCRETE_LFE_MASK)
868         mode |= DOWNMIX_LFE_FLAG;
869     return mode;
870 }
871
872 int hb_mixdown_to_mode(uint32_t mixdown)
873 {
874     switch (mixdown)
875     {
876         case HB_AMIXDOWN_MONO:
877             return DOWNMIX_MONO;
878         case HB_AMIXDOWN_STEREO:
879             return DOWNMIX_STEREO;
880         case HB_AMIXDOWN_DOLBY:
881             return DOWNMIX_DOLBY;
882         case HB_AMIXDOWN_DOLBYPLII:
883             return DOWNMIX_DPLII;
884         case HB_AMIXDOWN_6CH:
885             return DOWNMIX_3F2R|DOWNMIX_LFE_FLAG;
886         default:
887             return DOWNMIX_STEREO;
888     }
889 }
890
891 // ffmpeg gives us SMPTE channel layout
892 // We could use this layout and remap channels in encfaac,
893 // but VLC may have problems with remapping, so lets
894 // allow remapping to the default QuickTime order which is:
895 //
896 // C   L   R   LS  RS  Rls Rrs LFE
897 //
898 // This arrangement also makes it possible to use half as
899 // many downmix matrices since the matrix with and without
900 // LFE are the same.
901 //
902 // Use hb_layout_remap to accomplish this.  For convenience
903 // I've provided the necessary maps.
904 //
905 // SMPTE channel layout
906 //
907 // DUAL-MONO      L   R 
908 // DUAL-MONO-LFE  L   R   LFE
909 // MONO           M
910 // MONO-LFE       M   LFE
911 // STEREO         L   R 
912 // STEREO-LFE     L   R   LFE
913 // 3F             L   R   C
914 // 3F-LFE         L   R   C    LFE
915 // 2F1            L   R   S
916 // 2F1-LFE        L   R   LFE  S
917 // 3F1            L   R   C    S
918 // 3F1-LFE        L   R   C    LFE S
919 // 2F2            L   R   LS   RS
920 // 2F2-LFE        L   R   LFE  LS   RS
921 // 3F2            L   R   C    LS   RS
922 // 3F2-LFE        L   R   C    LFE  LS   RS
923 // 3F4            L   R   C    Rls  Rrs  LS   RS
924 // 3F4-LFE        L   R   C    LFE  Rls  Rrs  LS   RS
925 //
926
927 // Map Indicies are mode, lfe, channel respectively
928 int hb_ac3_chan_map[10][2][8] =
929 {
930 //     w/o LFE                       w/ LFE
931 //     C  L  R LS RS Rls Rrs         L  R  C LS RS Rls Rls LFE
932     {{ 0,                       }, { 1, 0,                     }}, // MONO
933     {{ 0, 1,                    }, { 1, 2, 0,                  }}, // STEREO
934     {{ 1, 0, 2,                 }, { 2, 1, 3, 0,               }}, // 3F
935     {{ 0, 1, 2,                 }, { 1, 2, 3, 0,               }}, // 2F1R
936     {{ 1, 0, 2, 3,              }, { 2, 1, 3, 4, 0,            }}, // 3F1R
937     {{ 0, 1, 2, 3,              }, { 1, 2, 3, 4, 0,            }}, // 2F2R
938     {{ 1, 0, 2, 3, 4,           }, { 2, 1, 3, 4, 5,  0,        }}, // 3F2R
939     {{ 1, 0, 2, 3, 4,  5,  6,   }, { 2, 1, 3, 4, 5,  6,  7,  0 }}, // 3F4R
940     {{ 0, 1,                    }, { 0, 1,                     }}, // DOLBY
941     {{ 0, 1,                    }, { 0, 1,                     }}  // DPLII
942 };
943
944 int hb_smpte_chan_map[10][2][8] =
945 {
946 //     w/o LFE                       w/ LFE
947 //     L  R  C LS RS Rls Rrs         L  R  C LS RS Rls Rls LFE
948     {{ 0,                       }, { 0, 1,                     }}, // MONO
949     {{ 0, 1,                    }, { 0, 1, 2,                  }}, // STEREO
950     {{ 2, 0, 1,                 }, { 2, 0, 1, 3,               }}, // 3F
951     {{ 0, 1, 2,                 }, { 0, 1, 3, 2,               }}, // 2F1R
952     {{ 2, 0, 1, 3,              }, { 2, 0, 1, 4, 3,            }}, // 3F1R
953     {{ 0, 1, 2, 3,              }, { 0, 1, 3, 4, 2,            }}, // 2F2R
954     {{ 2, 0, 1, 3, 4,           }, { 2, 0, 1, 4, 5,  3,        }}, // 3F2R
955     {{ 2, 0, 1, 5, 6,  3,  4,   }, { 2, 0, 1, 6, 7,  4,  5,  3 }}, // 3F4R
956     {{ 0, 1,                    }, { 0, 1,                     }}, // DOLBY
957     {{ 0, 1,                    }, { 0, 1,                     }}  // DPLII
958 };
959 static const uint8_t nchans_tbl[] = {1, 2, 3, 3, 4, 4, 5, 7, 2, 2};
960
961 // Takes a set of samples and remaps the channel layout
962 void hb_layout_remap( int (*layouts)[2][8], hb_sample_t * samples, int layout, int nsamples )
963 {
964     int nchans;
965     int ii, jj;
966     int lfe;
967     int * map;
968     int mode;
969     hb_sample_t tmp[6];
970
971     mode = hb_layout_to_mode(layout);
972     lfe = ((mode & DOWNMIX_LFE_FLAG) != 0);
973     mode = mode & DOWNMIX_CHANNEL_MASK;
974     nchans = nchans_tbl[mode] + lfe;
975     map = layouts[mode][lfe];
976
977     for (ii = 0; ii < nsamples; ii++)
978     {
979         for (jj = 0; jj < nchans; jj++)
980         {
981             tmp[jj] = samples[jj];
982         }
983         for (jj = 0; jj < nchans; jj++)
984         {
985             samples[jj] = tmp[map[jj]];
986         }
987         samples += nchans;
988     }
989 }
990
991 static void matrix_mul(
992     hb_sample_t * dst, 
993     hb_sample_t * src, 
994     int nchans_out, 
995     int nchans_in, 
996     int nsamples, 
997     hb_sample_t (*matrix)[8],
998     hb_sample_t bias)
999 {
1000     int nn, ii, jj;
1001     hb_sample_t val;
1002
1003     for (nn = 0; nn < nsamples; nn++)
1004     {
1005         for (ii = 0; ii < nchans_out; ii++)
1006         {
1007             val = 0;
1008             for (jj = 0; jj < nchans_in; jj++)
1009             {
1010                 val += src[jj] * matrix[jj][ii];
1011             }
1012             dst[ii] = val + bias;
1013         }
1014         src += nchans_in;
1015         dst += nchans_out;
1016     }
1017 }
1018
1019 static void set_level(
1020     hb_sample_t (*matrix)[8], 
1021     hb_sample_t clev, 
1022     hb_sample_t slev, 
1023     hb_sample_t level, 
1024     int mode_in, 
1025     int mode_out)
1026 {
1027     int ii, jj;
1028     int spos;
1029     int layout_in, layout_out;
1030
1031     for (ii = 0; ii < 8; ii++)
1032     {
1033         for (jj = 0; jj < 8; jj++)
1034         {
1035             matrix[ii][jj] *= level;
1036         }
1037     }
1038     if (mode_out >= DOWNMIX_DOLBY)
1039         return;
1040
1041     spos = 3;
1042     layout_in = channel_layout_map[mode_in];
1043     layout_out = channel_layout_map[mode_out];
1044
1045     if (!(layout_in & HB_CH_FRONT_CENTER))
1046     {
1047         spos--;
1048     }
1049     else
1050     {
1051         if (!(layout_out & HB_CH_FRONT_CENTER))
1052         {
1053             for (jj = 0; jj < 8; jj++)
1054             {
1055                 matrix[0][jj] *= clev;
1056             }
1057         }
1058     }
1059     if (layout_in & (HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT|HB_CH_BACK_CENTER|HB_CH_SIDE_LEFT|HB_CH_SIDE_RIGHT))
1060     {
1061         if (layout_out & (HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT|HB_CH_BACK_CENTER|HB_CH_SIDE_LEFT|HB_CH_SIDE_RIGHT))
1062         {
1063             // Note, slev only gets set if input has surround, and output has none.
1064             return;
1065         }
1066     }
1067     if (layout_in & (HB_CH_SIDE_LEFT|HB_CH_SIDE_RIGHT))
1068     {
1069         for (jj = 0; jj < 8; jj++)
1070         {
1071             matrix[spos][jj] *= slev;
1072             matrix[spos+1][jj] *= slev;
1073         }
1074         spos += 2;
1075     }
1076     else if (layout_in & (HB_CH_BACK_CENTER))
1077     {
1078         for (jj = 0; jj < 8; jj++)
1079         {
1080             matrix[spos][jj] *= slev;
1081         }
1082     }
1083     if (layout_in & (HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT))
1084     {
1085         for (jj = 0; jj < 8; jj++)
1086         {
1087             matrix[spos][jj] *= slev;
1088             matrix[spos+1][jj] *= slev;
1089         }
1090     }
1091 }
1092
1093 #define MIXMODE(x,y) (((x)<<4)|(y))
1094 // The downmix operation can result in new sample values that are
1095 // outside the original range of sample values.  If you wish to
1096 // guarantee that the levels to not exceed the original range,
1097 // call this function after initializing downmix and setting 
1098 // your initial levels.
1099 //
1100 // Note that this can result in generally lower volume levels
1101 // in the resulting downmixed audio.
1102 void hb_downmix_adjust_level( hb_downmix_t * downmix )
1103 {
1104     int ii, jj;
1105     int mode_in, mode_out;
1106     hb_sample_t level = 1.0;
1107     hb_sample_t clev = downmix->clev;
1108     hb_sample_t slev = downmix->slev;
1109
1110     mode_in = downmix->mode_in & DOWNMIX_CHANNEL_MASK;
1111     mode_out = downmix->mode_out & DOWNMIX_CHANNEL_MASK;
1112
1113     switch MIXMODE(mode_in, mode_out)
1114     {
1115     case MIXMODE(DOWNMIX_STEREO, DOWNMIX_MONO):
1116     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_2F1R):
1117     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_3F1R):
1118     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_3F1R):
1119     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_3F1R):
1120     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_3F2R):
1121     level_3db:
1122         level /= LVL_PLUS3DB;
1123         break;
1124
1125     case MIXMODE(DOWNMIX_3F, DOWNMIX_MONO):
1126         level /= LVL_PLUS3DB + clev * LVL_PLUS3DB;
1127         break;
1128
1129     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_2F1R):
1130     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_2F1R):
1131     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_2F2R):
1132         if (1 + clev < LVL_PLUS3DB)
1133             goto level_3db;
1134     case MIXMODE(DOWNMIX_3F, DOWNMIX_STEREO):
1135     case MIXMODE(DOWNMIX_3F, DOWNMIX_2F1R):
1136     case MIXMODE(DOWNMIX_3F, DOWNMIX_2F2R):
1137     case MIXMODE(DOWNMIX_3F, DOWNMIX_DOLBY):
1138     case MIXMODE(DOWNMIX_3F, DOWNMIX_DPLII):
1139     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_2F1R):
1140     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_2F2R):
1141     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_2F2R):
1142         level /= 1 + clev;
1143         break;
1144
1145
1146     case MIXMODE(DOWNMIX_2F1R, DOWNMIX_MONO):
1147         level /= LVL_PLUS3DB + LVL_3DB * clev;
1148         break;
1149
1150     case MIXMODE(DOWNMIX_2F1R, DOWNMIX_DOLBY):
1151         level /= 1 + LVL_3DB;
1152         break;
1153
1154     case MIXMODE(DOWNMIX_2F1R, DOWNMIX_STEREO):
1155     case MIXMODE(DOWNMIX_2F1R, DOWNMIX_3F):
1156     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_3F):
1157         level /= 1 + LVL_3DB * slev;
1158         break;
1159
1160     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_MONO):
1161         level /= LVL_PLUS3DB + LVL_PLUS3DB * clev + LVL_3DB * slev;
1162         break;
1163
1164     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_STEREO):
1165         level /= 1 + clev + LVL_3DB * slev;
1166         break;
1167
1168     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_DOLBY):
1169     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_DPLII):
1170     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_DOLBY):
1171         level /= 1 + LVL_PLUS3DB;
1172         break;
1173
1174     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_MONO):
1175         level /= LVL_PLUS3DB + LVL_PLUS3DB * slev;
1176         break;
1177
1178     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_STEREO):
1179     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_3F):
1180     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_3F):
1181         level /= 1 + slev;
1182         break;
1183
1184     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_DPLII):
1185         level /= 1 + LVL_SQRT_1_3 + LVL_SQRT_2_3;
1186         break;
1187
1188     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_MONO):
1189     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_MONO):
1190         level /= LVL_PLUS3DB + LVL_PLUS3DB * clev * LVL_PLUS3DB * slev;
1191         break;
1192
1193     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_STEREO):
1194         level /= 1 + clev + slev;
1195         break;
1196
1197     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_DOLBY):
1198         level /= 1 + 3 * LVL_3DB;
1199         break;
1200
1201     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_DPLII):
1202         level /= 1 + LVL_3DB + LVL_SQRT_1_3 + LVL_SQRT_2_3;
1203         break;
1204
1205     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_STEREO):
1206         level /= 1 + clev + LVL_PLUS3DB * slev;
1207         break;
1208
1209     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_3F):
1210         level /= 1 + LVL_PLUS3DB * slev;
1211         break;
1212
1213     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_DOLBY):
1214         level /= 1 + 5 * LVL_3DB;
1215         break;
1216
1217     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_DPLII):
1218         level /= 1 + LVL_3DB + 2 * LVL_SQRT_1_3 + 2 * LVL_SQRT_2_3;
1219     }
1220
1221     for (ii = 0; ii < 8; ii++)
1222     {
1223         for (jj = 0; jj < 8; jj++)
1224         {
1225             downmix->matrix[ii][jj] *= level;
1226         }
1227     }
1228 }
1229
1230 void hb_downmix_set_bias( hb_downmix_t * downmix, hb_sample_t bias )
1231 {
1232     downmix->bias = bias;
1233 }
1234
1235 // Changes the downmix mode if it needs changing after initialization
1236 int hb_downmix_set_mode( hb_downmix_t * downmix, int layout, int mixdown )
1237 {
1238     int ii, jj;
1239     int lfe_in, lfe_out;
1240     int mode_in, mode_out;
1241     hb_sample_t (*matrix)[8];
1242
1243     if ( downmix == NULL )
1244         return -1;
1245
1246     mode_in = hb_layout_to_mode(layout);
1247     mode_out = hb_mixdown_to_mode(mixdown);
1248     downmix->mode_in = mode_in;
1249     downmix->mode_out = mode_out;
1250
1251     mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
1252     mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
1253
1254     if (mode_in >= DOWNMIX_NUM_MODES || mode_out >= DOWNMIX_NUM_MODES)
1255         return -1;
1256
1257     matrix = downmix_matrix[mode_in][mode_out];
1258
1259     for (ii = 0; ii < 8; ii++)
1260     {
1261         for (jj = 0; jj < 8; jj++)
1262         {
1263             downmix->matrix[ii][jj] = matrix[ii][jj];
1264         }
1265     }
1266
1267     lfe_in = ((downmix->mode_in & DOWNMIX_LFE_FLAG) != 0);
1268     lfe_out = ((downmix->mode_out & DOWNMIX_LFE_FLAG) != 0);
1269
1270     downmix->nchans_in = nchans_tbl[mode_in] + lfe_in;
1271     downmix->nchans_out = nchans_tbl[mode_out] + lfe_out;
1272     return 0;
1273 }
1274
1275 // Changes the downmix levels if they need changing after initialization
1276 void hb_downmix_set_level( hb_downmix_t * downmix, hb_sample_t clev, hb_sample_t slev, hb_sample_t level )
1277 {
1278     int ii, jj;
1279     int mode_in, mode_out;
1280     hb_sample_t (*matrix)[8];
1281
1282     if ( downmix == NULL )
1283         return;
1284
1285     mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
1286     mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
1287
1288     if (mode_in >= DOWNMIX_NUM_MODES || mode_out >= DOWNMIX_NUM_MODES)
1289         return;
1290
1291     matrix = downmix_matrix[mode_in][mode_out];
1292
1293     for (ii = 0; ii < 8; ii++)
1294     {
1295         for (jj = 0; jj < 8; jj++)
1296         {
1297             downmix->matrix[ii][jj] = matrix[ii][jj];
1298         }
1299     }
1300     downmix->clev = clev;
1301     downmix->slev = slev;
1302     downmix->level = level;
1303     set_level(downmix->matrix, clev, slev, level, mode_in, mode_out);
1304 }
1305
1306 hb_downmix_t * hb_downmix_init(int layout, int mixdown)
1307 {
1308     hb_downmix_t * downmix = calloc(1, sizeof(hb_downmix_t));
1309     
1310     if (downmix == NULL)
1311         return NULL;
1312     if ( hb_downmix_set_mode( downmix, layout, mixdown ) < 0 )
1313     {
1314         free( downmix );
1315         return NULL;
1316     }
1317     // Set some good default values
1318     downmix->clev = LVL_3DB;
1319     downmix->slev = LVL_3DB;
1320     downmix->level = 1.0;
1321     downmix->bias = 0.0;
1322     set_level(downmix->matrix, LVL_3DB, LVL_3DB, 1.0, 
1323               downmix->mode_in, downmix->mode_out);
1324     return downmix;
1325 }
1326
1327 void hb_downmix_close( hb_downmix_t **downmix )
1328 {
1329     if (*downmix != NULL)
1330         free(*downmix);
1331     *downmix = NULL;
1332 }
1333
1334 void hb_downmix( hb_downmix_t * downmix, hb_sample_t * dst, hb_sample_t * src, int nsamples)
1335 {
1336     matrix_mul(dst, src, downmix->nchans_out, downmix->nchans_in, 
1337                nsamples, downmix->matrix, downmix->bias);
1338 }
1339
1340 int hb_need_downmix( int layout, int mixdown )
1341 {
1342     int mode_in, mode_out;
1343
1344     mode_in = hb_layout_to_mode(layout);
1345     mode_out = hb_mixdown_to_mode(mixdown);
1346
1347     return (mode_in != mode_out);
1348 }