OSDN Git Service

WinGui:
[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_4 0.5
20 #define LVL_SQRT_3_4 0.866025404
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_3_4, LVL_SQRT_1_4,  0, 0, 0, 0, 0, 0 },
609       { -LVL_SQRT_1_4, LVL_SQRT_3_4,  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_3_4, LVL_SQRT_1_4,  0, 0, 0, 0, 0, 0 },
703       { -LVL_SQRT_1_4, LVL_SQRT_3_4,  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_3_4*LVL_3DB, LVL_SQRT_1_4*LVL_3DB,  0, 0, 0, 0, 0, 0 },
796       { -LVL_SQRT_1_4*LVL_3DB, LVL_SQRT_3_4*LVL_3DB,  0, 0, 0, 0, 0, 0 },
797       { -LVL_SQRT_3_4*LVL_3DB, LVL_SQRT_1_4*LVL_3DB,  0, 0, 0, 0, 0, 0 },
798       { -LVL_SQRT_1_4*LVL_3DB, LVL_SQRT_3_4*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
892 // ffmpeg gives us SMPTE channel layout
893 // We could use this layout and remap channels in encfaac,
894 // but VLC may have problems with remapping, so lets
895 // allow remapping to the default QuickTime order which is:
896 //
897 // C   L   R   LS  RS  Rls Rrs LFE
898 //
899 // This arrangement also makes it possible to use half as
900 // many downmix matrices since the matrix with and without
901 // LFE are the same.
902 //
903 // Use hb_layout_remap to accomplish this.  For convenience
904 // I've provided the necessary maps.
905 //
906 // SMPTE channel layout
907 //
908 // DUAL-MONO      L   R 
909 // DUAL-MONO-LFE  L   R   LFE
910 // MONO           M
911 // MONO-LFE       M   LFE
912 // STEREO         L   R 
913 // STEREO-LFE     L   R   LFE
914 // 3F             L   R   C
915 // 3F-LFE         L   R   C    LFE
916 // 2F1            L   R   S
917 // 2F1-LFE        L   R   LFE  S
918 // 3F1            L   R   C    S
919 // 3F1-LFE        L   R   C    LFE S
920 // 2F2            L   R   LS   RS
921 // 2F2-LFE        L   R   LFE  LS   RS
922 // 3F2            L   R   C    LS   RS
923 // 3F2-LFE        L   R   C    LFE  LS   RS
924 // 3F4            L   R   C    Rls  Rrs  LS   RS
925 // 3F4-LFE        L   R   C    LFE  Rls  Rrs  LS   RS
926 //
927
928 #define CH_C      0
929 #define CH_L      1
930 #define CH_R      2
931 #define CH_CS     3
932 #define CH_LS     3
933 #define CH_RS     4
934 #define CH_Rls    5
935 #define CH_Rrs    6
936 #define CH_LFE    7
937
938 hb_chan_map_t hb_qt_chan_map =
939 {
940 {
941     {{ CH_C,                                                     },
942      { CH_C, CH_LFE,                                             }}, // MONO
943
944     {{ CH_L, CH_R,                                               },
945      { CH_L, CH_R, CH_LFE,                                       }}, // STEREO
946
947     {{ CH_C, CH_L, CH_R,                                         },
948      { CH_C, CH_L, CH_R, CH_LFE,                                 }}, // 3F
949
950     {{ CH_L, CH_R, CH_CS,                                        },
951      { CH_L, CH_R, CH_CS, CH_LFE,                                }}, // 2F1R
952
953     {{ CH_C, CH_L, CH_R, CH_CS,                                  },
954      { CH_C, CH_L, CH_R, CH_CS, CH_LFE,                          }}, // 3F1R
955
956     {{ CH_L, CH_R, CH_LS, CH_RS,                                 },
957      { CH_L, CH_R, CH_LS, CH_RS, CH_LFE,                         }}, // 2F2R
958
959     {{ CH_C, CH_L, CH_R, CH_LS, CH_RS,                           },
960      { CH_C, CH_L, CH_R, CH_LS, CH_RS, CH_LFE,                   }}, // 3F2R
961
962     {{ CH_C, CH_L, CH_R, CH_LS, CH_RS,  CH_Rls,  CH_Rrs,         },
963      { CH_C, CH_L, CH_R, CH_LS, CH_RS,  CH_Rls,  CH_Rrs,  CH_LFE }}, // 3F4R
964
965     {{ CH_L, CH_R,                                               },
966      { CH_L, CH_R,                                               }}, // DOLBY
967
968     {{ CH_L, CH_R,                                               },
969      { CH_L, CH_R,                                               }}  // DPLII
970 },
971 {
972     // CH_C  CH_L  CH_R  CH_LS/CS  CH_RS   CH_Rls   CH_Rrs   CH_LFE 
973     {{ 0,    0,    0,    0,        0,      0,       0,       0   },
974      { 0,    0,    0,    0,        0,      0,       0,       1   }}, // MONO
975
976     {{ 0,    0,    1,    0,        0,      0,       0,       0   },
977      { 0,    0,    1,    0,        0,      0,       0,       2   }}, // STEREO
978
979     {{ 0,    1,    2,    0,        0,      0,       0,       0   },
980      { 0,    1,    2,    0,        0,      0,       0,       3   }}, // 3F
981
982     {{ 0,    0,    1,    2,        0,      0,       0,       0   },
983      { 0,    0,    1,    2,        0,      0,       0,       3   }}, // 2F1R
984
985     {{ 0,    1,    2,    3,        0,      0,       0,       0   },
986      { 0,    1,    2,    3,        0,      0,       0,       4   }}, // 3F1R
987
988     {{ 0,    0,    1,    2,        3,      0,       0,       0   },
989      { 0,    0,    1,    2,        3,      0,       0,       4   }}, // 2F2R
990
991     {{ 0,    1,    2,    3,        4,      0,       0,       0   },
992      { 0,    1,    2,    3,        4,      0,       0,       5   }}, // 3F2R
993
994     {{ 0,    1,    2,    3,        4,      5,       6,       0   },
995      { 0,    1,    2,    3,        4,      5,       6,       7   }}, // 3F4R
996
997     {{ 0,    0,    1,    0,        0,      0,       0,       0   },
998      { 0,    0,    1,    0,        0,      0,       0,       0   }}, // DOLBY
999
1000     {{ 0,    0,    1,    0,        0,      0,       0,       0   },
1001      { 0,    0,    1,    0,        0,      0,       0,       0   }}  // DPLII
1002 }
1003 };
1004
1005 hb_chan_map_t hb_smpte_chan_map =
1006 {
1007 {
1008     {{ CH_C,                                                     },
1009      { CH_C, CH_LFE,                                             }}, // MONO
1010
1011     {{ CH_L, CH_R,                                               },
1012      { CH_L, CH_R, CH_LFE,                                       }}, // STEREO
1013
1014     {{ CH_L, CH_R, CH_C,                                         },
1015      { CH_L, CH_R, CH_C, CH_LFE,                                 }}, // 3F
1016
1017     {{ CH_L, CH_R, CH_CS,                                        },
1018      { CH_L, CH_R, CH_LFE, CH_CS,                                }}, // 2F1R
1019
1020     {{ CH_L, CH_R, CH_C,   CH_CS,                                },
1021      { CH_L, CH_R, CH_LFE, CH_CS,                                }}, // 3F1R
1022
1023     {{ CH_L, CH_R, CH_LS,  CH_RS,                                },
1024      { CH_L, CH_R, CH_LFE, CH_LS, CH_RS,                         }}, // 2F2R
1025
1026     {{ CH_L, CH_R, CH_C, CH_LS,  CH_RS,                          },
1027      { CH_L, CH_R, CH_C, CH_LFE, CH_LS, CH_RS,                   }}, // 3F2R
1028
1029     {{ CH_L, CH_R, CH_C, CH_Rls, CH_Rrs, CH_LS, CH_RS },
1030      { CH_L, CH_R, CH_C, CH_LFE, CH_Rls, CH_Rrs, CH_LS, CH_RS    }}, // 3F4R
1031
1032     {{ CH_L, CH_R,                                               },
1033      { CH_L, CH_R,                                               }}, // DOLBY
1034
1035     {{ CH_L, CH_R,                                               },
1036      { CH_L, CH_R,                                               }}  // DPLII
1037 },
1038 {
1039     // CH_C  CH_L  CH_R  CH_LS/CS  CH_RS   CH_Rls   CH_Rrs   CH_LFE 
1040     {{ 0,    0,    0,    0,        0,      0,       0,       0   },
1041      { 0,    0,    0,    0,        0,      0,       0,       1   }}, // MONO
1042
1043     {{ 0,    0,    1,    0,        0,      0,       0,       0   },
1044      { 0,    0,    1,    0,        0,      0,       0,       2   }}, // STEREO
1045
1046     {{ 2,    0,    1,    0,        0,      0,       0,       0   },
1047      { 2,    0,    1,    0,        0,      0,       0,       3   }}, // 3F
1048
1049     {{ 0,    0,    1,    2,        0,      0,       0,       0   },
1050      { 0,    0,    1,    3,        0,      0,       0,       2   }}, // 2F1R
1051
1052     {{ 2,    0,    1,    3,        0,      0,       0,       0   },
1053      { 2,    0,    1,    4,        0,      0,       0,       3   }}, // 3F1R
1054
1055     {{ 0,    0,    1,    2,        3,      0,       0,       0   },
1056      { 0,    0,    1,    3,        4,      0,       0,       2   }}, // 2F2R
1057
1058     {{ 2,    0,    1,    3,        4,      0,       0,       0   },
1059      { 2,    0,    1,    4,        5,      0,       0,       3   }}, // 3F2R
1060
1061     {{ 2,    0,    1,    5,        6,      3,       4,       0   },
1062      { 2,    0,    1,    6,        7,      4,       5,       3   }}, // 3F4R
1063
1064     {{ 0,    0,    1,    0,        0,      0,       0,       0   },
1065      { 0,    0,    1,    0,        0,      0,       0,       0   }}, // DOLBY
1066
1067     {{ 0,    0,    1,    0,        0,      0,       0,       0   },
1068      { 0,    0,    1,    0,        0,      0,       0,       0   }}  // DPLII
1069 }
1070 };
1071
1072 hb_chan_map_t hb_ac3_chan_map =
1073 {
1074 {
1075     {{ CH_C,                                                     },
1076      { CH_LFE, CH_C,                                             }}, // MONO
1077
1078     {{ CH_L, CH_R,                                               },
1079      { CH_LFE, CH_L, CH_R,                                       }}, // STEREO
1080
1081     {{ CH_L, CH_C, CH_R,                                         },
1082      { CH_LFE, CH_L, CH_C, CH_R,                                 }}, // 3F
1083
1084     {{ CH_L, CH_R, CH_CS,                                        },
1085      { CH_LFE, CH_L, CH_R, CH_CS,                                }}, // 2F1R
1086
1087     {{ CH_L, CH_C, CH_R, CH_CS,                                  },
1088      { CH_LFE, CH_L, CH_C, CH_R, CH_CS,                          }}, // 3F1R
1089
1090     {{ CH_L, CH_R, CH_LS, CH_RS,                                 },
1091      { CH_LFE, CH_L, CH_R, CH_LS, CH_RS,                         }}, // 2F2R
1092
1093     {{ CH_L, CH_C, CH_R, CH_LS, CH_RS,                           },
1094      { CH_LFE, CH_L, CH_C, CH_R, CH_LS, CH_RS,                   }}, // 3F2R
1095
1096     {{ CH_L, CH_C, CH_R, CH_LS, CH_RS,  CH_Rls,  CH_Rrs,         },
1097      { CH_LFE, CH_L, CH_C, CH_R, CH_LS, CH_RS,  CH_Rls,  CH_Rrs  }}, // 3F4R
1098
1099     {{ CH_L, CH_R,                                               },
1100      { CH_L, CH_R,                                               }}, // DOLBY
1101
1102     {{ CH_L, CH_R,                                               },
1103      { CH_L, CH_R,                                               }}  // DPLII
1104 },
1105 {
1106     // CH_C  CH_L  CH_R  CH_LS/CS  CH_RS   CH_Rls   CH_Rrs   CH_LFE 
1107     {{ 0,    0,    0,    0,        0,      0,       0,       0   },
1108      { 1,    0,    0,    0,        0,      0,       0,       0   }}, // MONO
1109
1110     {{ 0,    0,    1,    0,        0,      0,       0,       0   },
1111      { 0,    1,    2,    0,        0,      0,       0,       0   }}, // STEREO
1112
1113     {{ 1,    0,    2,    0,        0,      0,       0,       0   },
1114      { 2,    1,    3,    0,        0,      0,       0,       0   }}, // 3F
1115
1116     {{ 0,    0,    1,    2,        0,      0,       0,       0   },
1117      { 0,    1,    2,    3,        0,      0,       0,       0   }}, // 2F1R
1118
1119     {{ 1,    0,    2,    3,        0,      0,       0,       0   },
1120      { 2,    1,    3,    4,        0,      0,       0,       0   }}, // 3F1R
1121
1122     {{ 0,    0,    1,    2,        3,      0,       0,       0   },
1123      { 0,    1,    2,    3,        4,      0,       0,       0   }}, // 2F2R
1124
1125     {{ 1,    0,    2,    3,        4,      0,       0,       0   },
1126      { 2,    1,    3,    4,        5,      0,       0,       0   }}, // 3F2R
1127
1128     {{ 1,    0,    2,    3,        4,      5,       6,       0   },
1129      { 2,    1,    3,    4,        5,      6,       7,       0   }}, // 3F4R
1130
1131     {{ 0,    0,    1,    0,        0,      0,       0,       0   },
1132      { 0,    0,    1,    0,        0,      0,       0,       0   }}, // DOLBY
1133
1134     {{ 0,    0,    1,    0,        0,      0,       0,       0   },
1135      { 0,    0,    1,    0,        0,      0,       0,       0   }}  // DPLII
1136 }
1137 };
1138
1139 static const uint8_t nchans_tbl[] = {1, 2, 3, 3, 4, 4, 5, 7, 2, 2};
1140
1141 // Takes a set of samples and remaps the channel layout
1142 void hb_layout_remap( 
1143     hb_chan_map_t * map_in, 
1144     hb_chan_map_t * map_out, 
1145     int layout, 
1146     hb_sample_t * samples, 
1147     int nsamples )
1148 {
1149     int nchans;
1150     int ii, jj;
1151     int lfe;
1152     int * map;
1153     int * inv_map;
1154     int mode;
1155     hb_sample_t tmp[8];
1156
1157     mode = hb_layout_to_mode(layout);
1158     lfe = ((mode & DOWNMIX_LFE_FLAG) != 0);
1159     mode = mode & DOWNMIX_CHANNEL_MASK;
1160     nchans = nchans_tbl[mode] + lfe;
1161     inv_map = map_in->inv_chan_map[mode][lfe];
1162     map = map_out->chan_map[mode][lfe];
1163
1164     for (ii = 0; ii < nsamples; ii++)
1165     {
1166         for (jj = 0; jj < nchans; jj++)
1167         {
1168             tmp[jj] = samples[jj];
1169         }
1170         for (jj = 0; jj < nchans; jj++)
1171         {
1172             int ord = map[jj];
1173             samples[jj] = tmp[inv_map[ord]];
1174         }
1175         samples += nchans;
1176     }
1177 }
1178
1179 static void matrix_mul(
1180     hb_sample_t * dst, 
1181     hb_sample_t * src, 
1182     int nchans_out, 
1183     int nchans_in, 
1184     int nsamples, 
1185     hb_sample_t (*matrix)[8],
1186     hb_sample_t bias)
1187 {
1188     int nn, ii, jj;
1189     hb_sample_t val;
1190
1191     for (nn = 0; nn < nsamples; nn++)
1192     {
1193         for (ii = 0; ii < nchans_out; ii++)
1194         {
1195             val = 0;
1196             for (jj = 0; jj < nchans_in; jj++)
1197             {
1198                 val += src[jj] * matrix[jj][ii];
1199             }
1200             dst[ii] = val + bias;
1201         }
1202         src += nchans_in;
1203         dst += nchans_out;
1204     }
1205 }
1206
1207 static void set_level( hb_downmix_t * downmix )
1208 {
1209     int ii, jj;
1210     int layout_in, layout_out;
1211     int mode_in;
1212     int mode_out;
1213
1214     mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
1215     mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
1216
1217     for (ii = 0; ii < 8; ii++)
1218     {
1219         for (jj = 0; jj < 8; jj++)
1220         {
1221             downmix->matrix[ii][jj] *= downmix->level;
1222         }
1223     }
1224     if (mode_out >= DOWNMIX_DOLBY)
1225         return;
1226
1227     layout_in = channel_layout_map[mode_in];
1228     layout_out = channel_layout_map[mode_out];
1229
1230     if (layout_in & HB_CH_FRONT_CENTER)
1231     {
1232         if (!(layout_out & HB_CH_FRONT_CENTER))
1233         {
1234             for (jj = 0; jj < 8; jj++)
1235             {
1236                 downmix->matrix[downmix->center][jj] *= downmix->clev;
1237             }
1238         }
1239     }
1240     if (layout_in & (HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT|HB_CH_BACK_CENTER|HB_CH_SIDE_LEFT|HB_CH_SIDE_RIGHT))
1241     {
1242         if (layout_out & (HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT|HB_CH_BACK_CENTER|HB_CH_SIDE_LEFT|HB_CH_SIDE_RIGHT))
1243         {
1244             // Note, slev only gets set if input has surround, and output has none.
1245             return;
1246         }
1247     }
1248     for (jj = 0; jj < 8; jj++)
1249     {
1250         if ( downmix->left_surround >= 0 )
1251             downmix->matrix[downmix->left_surround][jj] *= downmix->slev;
1252         if ( downmix->right_surround >= 0 )
1253             downmix->matrix[downmix->right_surround][jj] *= downmix->slev;
1254         if ( downmix->rear_left_surround >= 0 )
1255             downmix->matrix[downmix->rear_left_surround][jj] *= downmix->slev;
1256         if ( downmix->rear_right_surround >= 0 )
1257             downmix->matrix[downmix->rear_right_surround][jj] *= downmix->slev;
1258     }
1259 }
1260
1261 #define MIXMODE(x,y) (((x)<<4)|(y))
1262 // The downmix operation can result in new sample values that are
1263 // outside the original range of sample values.  If you wish to
1264 // guarantee that the levels to not exceed the original range,
1265 // call this function after initializing downmix and setting 
1266 // your initial levels.
1267 //
1268 // Note that this can result in generally lower volume levels
1269 // in the resulting downmixed audio.
1270 void hb_downmix_adjust_level( hb_downmix_t * downmix )
1271 {
1272     int mode_in, mode_out;
1273     hb_sample_t level = downmix->level;
1274     hb_sample_t clev = downmix->clev;
1275     hb_sample_t slev = downmix->slev;
1276
1277     mode_in = downmix->mode_in & DOWNMIX_CHANNEL_MASK;
1278     mode_out = downmix->mode_out & DOWNMIX_CHANNEL_MASK;
1279
1280     switch MIXMODE(mode_in, mode_out)
1281     {
1282     case MIXMODE(DOWNMIX_STEREO, DOWNMIX_MONO):
1283     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_2F1R):
1284     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_3F1R):
1285     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_3F1R):
1286     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_3F1R):
1287     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_3F2R):
1288     level_3db:
1289         level /= LVL_PLUS3DB;
1290         break;
1291
1292     case MIXMODE(DOWNMIX_3F, DOWNMIX_MONO):
1293         level /= LVL_PLUS3DB + clev * LVL_PLUS3DB;
1294         break;
1295
1296     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_2F1R):
1297     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_2F1R):
1298     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_2F2R):
1299         if (1 + clev < LVL_PLUS3DB)
1300             goto level_3db;
1301     case MIXMODE(DOWNMIX_3F, DOWNMIX_STEREO):
1302     case MIXMODE(DOWNMIX_3F, DOWNMIX_2F1R):
1303     case MIXMODE(DOWNMIX_3F, DOWNMIX_2F2R):
1304     case MIXMODE(DOWNMIX_3F, DOWNMIX_DOLBY):
1305     case MIXMODE(DOWNMIX_3F, DOWNMIX_DPLII):
1306     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_2F1R):
1307     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_2F2R):
1308     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_2F2R):
1309         level /= 1 + clev;
1310         break;
1311
1312
1313     case MIXMODE(DOWNMIX_2F1R, DOWNMIX_MONO):
1314         level /= LVL_PLUS3DB + LVL_3DB * clev;
1315         break;
1316
1317     case MIXMODE(DOWNMIX_2F1R, DOWNMIX_DOLBY):
1318         level /= 1 + LVL_3DB;
1319         break;
1320
1321     case MIXMODE(DOWNMIX_2F1R, DOWNMIX_STEREO):
1322     case MIXMODE(DOWNMIX_2F1R, DOWNMIX_3F):
1323     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_3F):
1324         level /= 1 + LVL_3DB * slev;
1325         break;
1326
1327     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_MONO):
1328         level /= LVL_PLUS3DB + LVL_PLUS3DB * clev + LVL_3DB * slev;
1329         break;
1330
1331     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_STEREO):
1332         level /= 1 + clev + LVL_3DB * slev;
1333         break;
1334
1335     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_DOLBY):
1336     case MIXMODE(DOWNMIX_3F1R, DOWNMIX_DPLII):
1337     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_DOLBY):
1338         level /= 1 + LVL_PLUS3DB;
1339         break;
1340
1341     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_MONO):
1342         level /= LVL_PLUS3DB + LVL_PLUS3DB * slev;
1343         break;
1344
1345     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_STEREO):
1346     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_3F):
1347     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_3F):
1348         level /= 1 + slev;
1349         break;
1350
1351     case MIXMODE(DOWNMIX_2F2R, DOWNMIX_DPLII):
1352         level /= 1 + LVL_SQRT_1_4 + LVL_SQRT_3_4;
1353         break;
1354
1355     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_MONO):
1356     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_MONO):
1357         level /= LVL_PLUS3DB + LVL_PLUS3DB * clev * LVL_PLUS3DB * slev;
1358         break;
1359
1360     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_STEREO):
1361         level /= 1 + clev + slev;
1362         break;
1363
1364     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_DOLBY):
1365         level /= 1 + 3 * LVL_3DB;
1366         break;
1367
1368     case MIXMODE(DOWNMIX_3F2R, DOWNMIX_DPLII):
1369         level /= 1 + LVL_3DB + LVL_SQRT_1_4 + LVL_SQRT_3_4;
1370         break;
1371
1372     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_STEREO):
1373         level /= 1 + clev + LVL_PLUS3DB * slev;
1374         break;
1375
1376     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_3F):
1377         level /= 1 + LVL_PLUS3DB * slev;
1378         break;
1379
1380     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_DOLBY):
1381         level /= 1 + 5 * LVL_3DB;
1382         break;
1383
1384     case MIXMODE(DOWNMIX_3F4R, DOWNMIX_DPLII):
1385         level /= 1 + LVL_3DB + 2 * LVL_SQRT_1_4 + 2 * LVL_SQRT_3_4;
1386     }
1387
1388     downmix->level = level;
1389     downmix->matrix_initialized = 0;
1390 }
1391
1392 void hb_downmix_set_bias( hb_downmix_t * downmix, hb_sample_t bias )
1393 {
1394     downmix->bias = bias;
1395 }
1396
1397 // Changes the downmix mode if it needs changing after initialization
1398 static void set_mode( hb_downmix_t * downmix )
1399 {
1400     int ii, jj;
1401     int mode_in, mode_out;
1402     hb_sample_t (*matrix)[8];
1403
1404     mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
1405     mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
1406
1407     matrix = downmix_matrix[mode_in][mode_out];
1408
1409     for (ii = 0; ii < 8; ii++)
1410     {
1411         for (jj = 0; jj < 8; jj++)
1412         {
1413             downmix->matrix[ii][jj] = matrix[ii][jj];
1414         }
1415     }
1416 }
1417
1418 // Changes the downmix mode if it needs changing after initialization
1419 int hb_downmix_set_mode( hb_downmix_t * downmix, int layout, int mixdown )
1420 {
1421     int lfe_in, lfe_out;
1422     int mode_in, mode_out;
1423
1424     if ( downmix == NULL )
1425         return -1;
1426
1427     mode_in = hb_layout_to_mode(layout);
1428     mode_out = hb_mixdown_to_mode(mixdown);
1429     downmix->mode_in = mode_in;
1430     downmix->mode_out = mode_out;
1431
1432     mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
1433     mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
1434
1435     if (mode_in >= DOWNMIX_NUM_MODES || mode_out >= DOWNMIX_NUM_MODES)
1436         return -1;
1437
1438     lfe_in = ((downmix->mode_in & DOWNMIX_LFE_FLAG) != 0);
1439     lfe_out = ((downmix->mode_out & DOWNMIX_LFE_FLAG) != 0);
1440
1441     downmix->nchans_in = nchans_tbl[mode_in] + lfe_in;
1442     downmix->nchans_out = nchans_tbl[mode_out] + lfe_out;
1443
1444     downmix->matrix_initialized = 0;
1445     return 0;
1446 }
1447
1448 // Changes the downmix levels if they need changing after initialization
1449 void hb_downmix_set_level( hb_downmix_t * downmix, hb_sample_t clev, hb_sample_t slev, hb_sample_t level )
1450 {
1451     if ( downmix == NULL )
1452         return;
1453
1454     downmix->clev = clev;
1455     downmix->slev = slev;
1456     downmix->level = level;
1457     downmix->matrix_initialized = 0;
1458 }
1459
1460 static void set_chan_map( hb_downmix_t * downmix )
1461 {
1462     int nchans;
1463     int ii, jj;
1464     int lfe;
1465     int * map;
1466     int * inv_map;
1467     int mode;
1468     hb_sample_t matrix[8][8];
1469
1470     // Copy the matrix
1471     for ( ii = 0; ii < 8; ii++ )
1472     {
1473         for ( jj = 0; jj < 8; jj++ )
1474         {
1475             matrix[ii][jj] = downmix->matrix[ii][jj];
1476         }
1477     }
1478
1479     // Rearrange the rows to correspond to the input channel order
1480     lfe = ((downmix->mode_in & DOWNMIX_LFE_FLAG) != 0);
1481     mode = downmix->mode_in & DOWNMIX_CHANNEL_MASK;
1482     nchans = nchans_tbl[mode] + lfe;
1483     map = downmix->map_in.chan_map[mode][lfe];
1484     inv_map = hb_qt_chan_map.inv_chan_map[mode][lfe];
1485
1486     downmix->center = -1;
1487     downmix->left_surround = -1;
1488     downmix->right_surround = -1;
1489     downmix->rear_left_surround = -1;
1490     downmix->rear_right_surround = -1;
1491     for ( ii = 0; ii < nchans; ii++ )
1492     {
1493         int ord = map[ii];
1494         int row = inv_map[ord];
1495         switch (ord)
1496         {
1497             case CH_C:
1498                 downmix->center = ii;
1499                 break;
1500             case CH_LS:
1501                 downmix->left_surround = ii;
1502                 break;
1503             case CH_RS:
1504                 downmix->right_surround = ii;
1505                 break;
1506             case CH_Rls:
1507                 downmix->rear_right_surround = ii;
1508                 break;
1509             case CH_Rrs:
1510                 downmix->rear_left_surround = ii;
1511                 break;
1512         }
1513         for ( jj = 0; jj < 8; jj++ )
1514         {
1515             downmix->matrix[ii][jj] = matrix[row][jj];
1516         }
1517     }
1518
1519     // Copy the matrix
1520     for ( ii = 0; ii < 8; ii++ )
1521     {
1522         for ( jj = 0; jj < 8; jj++ )
1523         {
1524             matrix[ii][jj] = downmix->matrix[ii][jj];
1525         }
1526     }
1527
1528     // Rearrange the columns to correspond to the output channel order
1529     lfe = ((downmix->mode_out & DOWNMIX_LFE_FLAG) != 0);
1530     mode = downmix->mode_out & DOWNMIX_CHANNEL_MASK;
1531     nchans = nchans_tbl[mode] + lfe;
1532     map = downmix->map_out.chan_map[mode][lfe];
1533     inv_map = hb_qt_chan_map.inv_chan_map[mode][lfe];
1534     for ( ii = 0; ii < nchans; ii++ )
1535     {
1536         int ord = map[ii];
1537         int col = inv_map[ord];
1538         for ( jj = 0; jj < 8; jj++ )
1539         {
1540             downmix->matrix[jj][ii] = matrix[jj][col];
1541         }
1542     }
1543 }
1544
1545 void hb_downmix_set_chan_map( 
1546     hb_downmix_t * downmix, 
1547     hb_chan_map_t * map_in, 
1548     hb_chan_map_t * map_out )
1549 {
1550     downmix->map_in = *map_in;
1551     downmix->map_out = *map_out;
1552     downmix->matrix_initialized = 0;
1553 }
1554
1555 hb_downmix_t * hb_downmix_init(int layout, int mixdown)
1556 {
1557     hb_downmix_t * downmix = calloc(1, sizeof(hb_downmix_t));
1558     
1559     if (downmix == NULL)
1560         return NULL;
1561     if ( hb_downmix_set_mode( downmix, layout, mixdown ) < 0 )
1562     {
1563         free( downmix );
1564         return NULL;
1565     }
1566     // Set some good default values
1567     hb_downmix_set_level( downmix, LVL_3DB, LVL_3DB, 1.0 );
1568     downmix->bias = 0.0;
1569     downmix->matrix_initialized = 0;
1570     // The default input and output channel order is QT
1571     hb_downmix_set_chan_map( downmix, &hb_qt_chan_map, &hb_qt_chan_map );
1572     return downmix;
1573 }
1574
1575 void hb_downmix_close( hb_downmix_t **downmix )
1576 {
1577     if (*downmix != NULL)
1578         free(*downmix);
1579     *downmix = NULL;
1580 }
1581
1582 static void init_matrix( hb_downmix_t * downmix )
1583 {
1584     if ( !downmix->matrix_initialized )
1585     {
1586         set_mode( downmix );
1587         set_chan_map( downmix );
1588         set_level(downmix);
1589         downmix->matrix_initialized = 1;
1590     }
1591 }
1592
1593 void hb_downmix( hb_downmix_t * downmix, hb_sample_t * dst, hb_sample_t * src, int nsamples)
1594 {
1595     init_matrix( downmix );
1596     matrix_mul( dst, src, downmix->nchans_out, downmix->nchans_in, 
1597                nsamples, downmix->matrix, downmix->bias );
1598 }
1599
1600 int hb_need_downmix( int layout, int mixdown )
1601 {
1602     int mode_in, mode_out;
1603
1604     mode_in = hb_layout_to_mode(layout);
1605     mode_out = hb_mixdown_to_mode(mixdown);
1606
1607     return (mode_in != mode_out);
1608 }