summaryrefslogtreecommitdiffstats
path: root/libhb/downmix.c
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2010-04-02 15:10:48 +0000
committerjstebbins <[email protected]>2010-04-02 15:10:48 +0000
commiteb4ffde8a29cf9b77a84440fa6c404e94eb9b6a6 (patch)
treeea5149118b167b07f4a33f4f0cf9f1a8ea7ee61f /libhb/downmix.c
parent13eb2d6d5e7ad894d0dfe808dc3cb26a062d48b7 (diff)
downmix support for ffmpeg audio sources
now we can eat our own dogfood. i.e. aac 6ch discrete input now works, along with any other multi-channel audio ffmpeg can toss at us. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3182 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/downmix.c')
-rw-r--r--libhb/downmix.c1348
1 files changed, 1348 insertions, 0 deletions
diff --git a/libhb/downmix.c b/libhb/downmix.c
new file mode 100644
index 000000000..0ab9b90f3
--- /dev/null
+++ b/libhb/downmix.c
@@ -0,0 +1,1348 @@
+/* $Id: downmix.c,v 1.15 2005/03/17 19:22:47 stebbins Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include "common.h"
+#include "downmix.h"
+
+#define LVL_PLUS6DB 2.0
+#define LVL_PLUS3DB 1.4142135623730951
+#define LVL_3DB 0.7071067811865476
+#define LVL_45DB 0.5946035575013605
+#define LVL_6DB 0.5
+
+#define LVL_SQRT_1_3 0.577350269
+#define LVL_SQRT_2_3 0.816496581
+
+#define HB_CH_FRONT_LEFT 0x00000001
+#define HB_CH_FRONT_RIGHT 0x00000002
+#define HB_CH_FRONT_CENTER 0x00000004
+#define HB_CH_LOW_FREQUENCY 0x00000008
+#define HB_CH_BACK_LEFT 0x00000010
+#define HB_CH_BACK_RIGHT 0x00000020
+#define HB_CH_BACK_CENTER 0x00000040
+#define HB_CH_SIDE_LEFT 0x00000080
+#define HB_CH_SIDE_RIGHT 0x00000100
+
+#define HB_CH_SURROUND_MASK 0x000001f0
+#define HB_CH_MASK 0x000007ff
+
+#define HB_CH_DOLBY 0x00000800
+#define HB_CH_DPLII 0x00001000
+
+#define DOWNMIX_MONO 0
+#define DOWNMIX_STEREO 1
+#define DOWNMIX_3F 2
+#define DOWNMIX_2F1R 3
+#define DOWNMIX_3F1R 4
+#define DOWNMIX_2F2R 5
+#define DOWNMIX_3F2R 6
+#define DOWNMIX_3F4R 7
+#define DOWNMIX_DOLBY 8
+#define DOWNMIX_DPLII 9
+#define DOWNMIX_NUM_MODES 10
+
+#define DOWNMIX_CHANNEL_MASK 0x0f
+
+#define DOWNMIX_LFE_FLAG 0x10
+#define DOWNMIX_FLAGS_MASK 0x10
+
+hb_sample_t downmix_matrix[DOWNMIX_NUM_MODES][DOWNMIX_NUM_MODES][8][8] =
+{
+// MONO in
+{
+ // MONO out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // STEREO out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F out
+ { { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F1R out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F1R out
+ { { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F2R out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F2R out
+ { { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F4R out
+ { { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 1 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DOLBY out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DPLII out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+},
+// STEREO in
+{
+ // MONO out
+ { { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // STEREO out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F1R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F1R out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F2R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F2R out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F4R out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 1 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DOLBY out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DPLII out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+},
+// 3F in
+{
+ // MONO out
+ { { LVL_PLUS3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // STEREO out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F1R out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F1R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F2R out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F2R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F4R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 1 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DOLBY out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DPLII out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+},
+// 2F1R in
+{
+ // MONO out
+ { { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // STEREO out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F1R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F1R out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F2R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F2R out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, LVL_3DB, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F4R out
+ { { 0, 1, 0, 0, 0, 0, 0 , 0 },
+ { 0, 0, 1, 0, 0, 0, 0 , 0 },
+ { 0, 0, 0, 0, 0, LVL_3DB, LVL_3DB, 0 },
+ { 0, 0, 0, 0, 0, 0, 0 , 1 },
+ { 0, 0, 0, 0, 0, 0, 0 , 0 },
+ { 0, 0, 0, 0, 0, 0, 0 , 0 },
+ { 0, 0, 0, 0, 0, 0, 0 , 0 },
+ { 0, 0, 0, 0, 0, 0, 0 , 0 } },
+ // DOLBY out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DPLII out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+},
+// 3F1R in
+{
+ // MONO out
+ { { LVL_PLUS3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // STEREO out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F1R out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F1R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F2R out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F2R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, LVL_3DB, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F4R out
+ { { 1, 0, 0, 0, 0, 0, 0 , 0 },
+ { 0, 1, 0, 0, 0, 0, 0 , 0 },
+ { 0, 0, 1, 0, 0, 0, 0 , 0 },
+ { 0, 0, 0, 0, 0, LVL_3DB, LVL_3DB, 0 },
+ { 0, 0, 0, 0, 0, 0, 0 , 1 },
+ { 0, 0, 0, 0, 0, 0, 0 , 0 },
+ { 0, 0, 0, 0, 0, 0, 0 , 0 },
+ { 0, 0, 0, 0, 0, 0, 0 , 0 } },
+ // DOLBY out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DPLII out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+},
+// 2F2R in
+{
+ // MONO out
+ { { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // STEREO out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F1R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F1R out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F2R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F2R out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F4R out
+ { { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 1, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 1 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DOLBY out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { -LVL_6DB, LVL_6DB, 0, 0, 0, 0, 0, 0 },
+ { -LVL_6DB, LVL_6DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DPLII out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { LVL_SQRT_2_3, -LVL_SQRT_1_3, 0, 0, 0, 0, 0, 0 },
+ { -LVL_SQRT_1_3, LVL_SQRT_2_3, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+},
+// 3F2R in
+{
+ // MONO out
+ { { LVL_PLUS3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // STEREO out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F1R out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F1R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 2F2R out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F2R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // 3F4R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 1, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 1 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DOLBY out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ // DPLII out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { LVL_SQRT_2_3, -LVL_SQRT_1_3, 0, 0, 0, 0, 0, 0 },
+ { -LVL_SQRT_1_3, LVL_SQRT_2_3, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+},
+// 3F4R in
+{
+ // MONO out
+ { { LVL_PLUS3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_6DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_6DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_6DB, 0, 0, 0, 0, 0, 0, 0 },
+ { LVL_6DB, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 } },
+ // STEREO out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { LVL_3DB, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 } },
+ // 3F out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 } },
+ // 2F1R out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_6DB, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_6DB, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_6DB, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_6DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 } },
+ // 3F1R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_6DB, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_6DB, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_6DB, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_6DB, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 } },
+ // 2F2R out
+ { { 1, 1, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, LVL_3DB, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 } },
+ // 3F2R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, LVL_3DB, 0, 0, 0 },
+ { 0, 0, 0, LVL_3DB, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, LVL_3DB, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 } },
+ // 3F4R out
+ { { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 1, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 1 } },
+ // DOLBY out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { -LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 } },
+ // DPLII out
+ { { LVL_3DB, LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0, 0, 0 },
+ { LVL_SQRT_2_3*LVL_3DB, -LVL_SQRT_1_3*LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { -LVL_SQRT_1_3*LVL_3DB, LVL_SQRT_2_3*LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { LVL_SQRT_2_3*LVL_3DB, -LVL_SQRT_1_3*LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { -LVL_SQRT_1_3*LVL_3DB, LVL_SQRT_2_3*LVL_3DB, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0, 0, 0, 0 } }
+},
+};
+
+static int channel_layout_map[DOWNMIX_NUM_MODES] =
+{
+ // DOWNMIX_MONO
+ (HB_CH_FRONT_CENTER),
+ // DOWNMIX_STEREO
+ (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT),
+ // DOWNMIX_3F
+ (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_FRONT_CENTER),
+ // DOWNMIX_2F1R
+ (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_BACK_CENTER),
+ // DOWNMIX_3F1R
+ (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_FRONT_CENTER|HB_CH_BACK_CENTER),
+ // DOWNMIX_2F2R
+ (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT),
+ // DOWNMIX_3F2R
+ (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_FRONT_CENTER|HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT),
+ // DOWNMIX_3F4R
+ (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT|HB_CH_FRONT_CENTER|HB_CH_SIDE_LEFT|
+ HB_CH_SIDE_RIGHT|HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT),
+ // DOWNMIX_DOLBY
+ (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT),
+ // DOWNMIX_DPLII
+ (HB_CH_FRONT_LEFT|HB_CH_FRONT_RIGHT)
+};
+
+int hb_layout_to_mode(int layout)
+{
+ int mode;
+ switch (layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK)
+ {
+ case HB_INPUT_CH_LAYOUT_MONO:
+ mode = DOWNMIX_MONO;
+ break;
+ case HB_INPUT_CH_LAYOUT_STEREO:
+ mode = DOWNMIX_STEREO;
+ break;
+ case HB_INPUT_CH_LAYOUT_3F:
+ mode = DOWNMIX_3F;
+ break;
+ case HB_INPUT_CH_LAYOUT_2F1R:
+ mode = DOWNMIX_2F1R;
+ break;
+ case HB_INPUT_CH_LAYOUT_3F1R:
+ mode = DOWNMIX_3F1R;
+ break;
+ case HB_INPUT_CH_LAYOUT_2F2R:
+ mode = DOWNMIX_2F2R;
+ break;
+ case HB_INPUT_CH_LAYOUT_3F2R:
+ mode = DOWNMIX_3F2R;
+ break;
+ case HB_INPUT_CH_LAYOUT_4F2R:
+ mode = DOWNMIX_3F2R|DOWNMIX_LFE_FLAG;
+ break;
+ case HB_INPUT_CH_LAYOUT_3F4R:
+ mode = DOWNMIX_3F4R;
+ break;
+ case HB_INPUT_CH_LAYOUT_DOLBY:
+ mode = DOWNMIX_STEREO;
+ break;
+ default:
+ mode = DOWNMIX_STEREO;
+ break;
+ }
+ if (layout & HB_INPUT_CH_LAYOUT_DISCRETE_LFE_MASK)
+ mode |= DOWNMIX_LFE_FLAG;
+ return mode;
+}
+
+int hb_mixdown_to_mode(uint32_t mixdown)
+{
+ switch (mixdown)
+ {
+ case HB_AMIXDOWN_MONO:
+ return DOWNMIX_MONO;
+ case HB_AMIXDOWN_STEREO:
+ return DOWNMIX_STEREO;
+ case HB_AMIXDOWN_DOLBY:
+ return DOWNMIX_DOLBY;
+ case HB_AMIXDOWN_DOLBYPLII:
+ return DOWNMIX_DPLII;
+ case HB_AMIXDOWN_6CH:
+ return DOWNMIX_3F2R|DOWNMIX_LFE_FLAG;
+ default:
+ return DOWNMIX_STEREO;
+ }
+}
+
+// ffmpeg gives us SMPTE channel layout
+// We could use this layout and remap channels in encfaac,
+// but VLC may have problems with remapping, so lets
+// allow remapping to the default QuickTime order which is:
+//
+// C L R LS RS Rls Rrs LFE
+//
+// This arrangement also makes it possible to use half as
+// many downmix matrices since the matrix with and without
+// LFE are the same.
+//
+// Use hb_layout_remap to accomplish this. For convenience
+// I've provided the necessary maps.
+//
+// SMPTE channel layout
+//
+// DUAL-MONO L R
+// DUAL-MONO-LFE L R LFE
+// MONO M
+// MONO-LFE M LFE
+// STEREO L R
+// STEREO-LFE L R LFE
+// 3F L R C
+// 3F-LFE L R C LFE
+// 2F1 L R S
+// 2F1-LFE L R LFE S
+// 3F1 L R C S
+// 3F1-LFE L R C LFE S
+// 2F2 L R LS RS
+// 2F2-LFE L R LFE LS RS
+// 3F2 L R C LS RS
+// 3F2-LFE L R C LFE LS RS
+// 3F4 L R C Rls Rrs LS RS
+// 3F4-LFE L R C LFE Rls Rrs LS RS
+//
+
+// Map Indicies are mode, lfe, channel respectively
+int hb_ac3_chan_map[10][2][8] =
+{
+// w/o LFE w/ LFE
+// C L R LS RS Rls Rrs L R C LS RS Rls Rls LFE
+ {{ 0, }, { 1, 0, }}, // MONO
+ {{ 0, 1, }, { 1, 2, 0, }}, // STEREO
+ {{ 1, 0, 2, }, { 2, 1, 3, 0, }}, // 3F
+ {{ 0, 1, 2, }, { 1, 2, 3, 0, }}, // 2F1R
+ {{ 1, 0, 2, 3, }, { 2, 1, 3, 4, 0, }}, // 3F1R
+ {{ 0, 1, 2, 3, }, { 1, 2, 3, 4, 0, }}, // 2F2R
+ {{ 1, 0, 2, 3, 4, }, { 2, 1, 3, 4, 5, 0, }}, // 3F2R
+ {{ 1, 0, 2, 3, 4, 5, 6, }, { 2, 1, 3, 4, 5, 6, 7, 0 }}, // 3F4R
+ {{ 0, 1, }, { 0, 1, }}, // DOLBY
+ {{ 0, 1, }, { 0, 1, }} // DPLII
+};
+
+int hb_smpte_chan_map[10][2][8] =
+{
+// w/o LFE w/ LFE
+// L R C LS RS Rls Rrs L R C LS RS Rls Rls LFE
+ {{ 0, }, { 0, 1, }}, // MONO
+ {{ 0, 1, }, { 0, 1, 2, }}, // STEREO
+ {{ 2, 0, 1, }, { 2, 0, 1, 3, }}, // 3F
+ {{ 0, 1, 2, }, { 0, 1, 3, 2, }}, // 2F1R
+ {{ 2, 0, 1, 3, }, { 2, 0, 1, 4, 3, }}, // 3F1R
+ {{ 0, 1, 2, 3, }, { 0, 1, 3, 4, 2, }}, // 2F2R
+ {{ 2, 0, 1, 3, 4, }, { 2, 0, 1, 4, 5, 3, }}, // 3F2R
+ {{ 2, 0, 1, 5, 6, 3, 4, }, { 2, 0, 1, 6, 7, 4, 5, 3 }}, // 3F4R
+ {{ 0, 1, }, { 0, 1, }}, // DOLBY
+ {{ 0, 1, }, { 0, 1, }} // DPLII
+};
+static const uint8_t nchans_tbl[] = {1, 2, 3, 3, 4, 4, 5, 7, 2, 2};
+
+// Takes a set of samples and remaps the channel layout
+void hb_layout_remap( int (*layouts)[2][8], hb_sample_t * samples, int layout, int nsamples )
+{
+ int nchans;
+ int ii, jj;
+ int lfe;
+ int * map;
+ int mode;
+ hb_sample_t tmp[6];
+
+ mode = hb_layout_to_mode(layout);
+ lfe = ((mode & DOWNMIX_LFE_FLAG) != 0);
+ mode = mode & DOWNMIX_CHANNEL_MASK;
+ nchans = nchans_tbl[mode] + lfe;
+ map = layouts[mode][lfe];
+
+ for (ii = 0; ii < nsamples; ii++)
+ {
+ for (jj = 0; jj < nchans; jj++)
+ {
+ tmp[jj] = samples[jj];
+ }
+ for (jj = 0; jj < nchans; jj++)
+ {
+ samples[jj] = tmp[map[jj]];
+ }
+ samples += nchans;
+ }
+}
+
+static void matrix_mul(
+ hb_sample_t * dst,
+ hb_sample_t * src,
+ int nchans_out,
+ int nchans_in,
+ int nsamples,
+ hb_sample_t (*matrix)[8],
+ hb_sample_t bias)
+{
+ int nn, ii, jj;
+ hb_sample_t val;
+
+ for (nn = 0; nn < nsamples; nn++)
+ {
+ for (ii = 0; ii < nchans_out; ii++)
+ {
+ val = 0;
+ for (jj = 0; jj < nchans_in; jj++)
+ {
+ val += src[jj] * matrix[jj][ii];
+ }
+ dst[ii] = val + bias;
+ }
+ src += nchans_in;
+ dst += nchans_out;
+ }
+}
+
+static void set_level(
+ hb_sample_t (*matrix)[8],
+ hb_sample_t clev,
+ hb_sample_t slev,
+ hb_sample_t level,
+ int mode_in,
+ int mode_out)
+{
+ int ii, jj;
+ int spos;
+ int layout_in, layout_out;
+
+ for (ii = 0; ii < 8; ii++)
+ {
+ for (jj = 0; jj < 8; jj++)
+ {
+ matrix[ii][jj] *= level;
+ }
+ }
+ if (mode_out >= DOWNMIX_DOLBY)
+ return;
+
+ spos = 3;
+ layout_in = channel_layout_map[mode_in];
+ layout_out = channel_layout_map[mode_out];
+
+ if (!(layout_in & HB_CH_FRONT_CENTER))
+ {
+ spos--;
+ }
+ else
+ {
+ if (!(layout_out & HB_CH_FRONT_CENTER))
+ {
+ for (jj = 0; jj < 8; jj++)
+ {
+ matrix[0][jj] *= clev;
+ }
+ }
+ }
+ if (layout_in & (HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT|HB_CH_BACK_CENTER|HB_CH_SIDE_LEFT|HB_CH_SIDE_RIGHT))
+ {
+ if (layout_out & (HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT|HB_CH_BACK_CENTER|HB_CH_SIDE_LEFT|HB_CH_SIDE_RIGHT))
+ {
+ // Note, slev only gets set if input has surround, and output has none.
+ return;
+ }
+ }
+ if (layout_in & (HB_CH_SIDE_LEFT|HB_CH_SIDE_RIGHT))
+ {
+ for (jj = 0; jj < 8; jj++)
+ {
+ matrix[spos][jj] *= slev;
+ matrix[spos+1][jj] *= slev;
+ }
+ spos += 2;
+ }
+ else if (layout_in & (HB_CH_BACK_CENTER))
+ {
+ for (jj = 0; jj < 8; jj++)
+ {
+ matrix[spos][jj] *= slev;
+ }
+ }
+ if (layout_in & (HB_CH_BACK_LEFT|HB_CH_BACK_RIGHT))
+ {
+ for (jj = 0; jj < 8; jj++)
+ {
+ matrix[spos][jj] *= slev;
+ matrix[spos+1][jj] *= slev;
+ }
+ }
+}
+
+#define MIXMODE(x,y) (((x)<<4)|(y))
+// The downmix operation can result in new sample values that are
+// outside the original range of sample values. If you wish to
+// guarantee that the levels to not exceed the original range,
+// call this function after initializing downmix and setting
+// your initial levels.
+//
+// Note that this can result in generally lower volume levels
+// in the resulting downmixed audio.
+void hb_downmix_adjust_level( hb_downmix_t * downmix )
+{
+ int ii, jj;
+ int mode_in, mode_out;
+ hb_sample_t level = 1.0;
+ hb_sample_t clev = downmix->clev;
+ hb_sample_t slev = downmix->slev;
+
+ mode_in = downmix->mode_in & DOWNMIX_CHANNEL_MASK;
+ mode_out = downmix->mode_out & DOWNMIX_CHANNEL_MASK;
+
+ switch MIXMODE(mode_in, mode_out)
+ {
+ case MIXMODE(DOWNMIX_STEREO, DOWNMIX_MONO):
+ case MIXMODE(DOWNMIX_2F2R, DOWNMIX_2F1R):
+ case MIXMODE(DOWNMIX_2F2R, DOWNMIX_3F1R):
+ case MIXMODE(DOWNMIX_3F2R, DOWNMIX_3F1R):
+ case MIXMODE(DOWNMIX_3F4R, DOWNMIX_3F1R):
+ case MIXMODE(DOWNMIX_3F4R, DOWNMIX_3F2R):
+ level_3db:
+ level /= LVL_PLUS3DB;
+ break;
+
+ case MIXMODE(DOWNMIX_3F, DOWNMIX_MONO):
+ level /= LVL_PLUS3DB + clev * LVL_PLUS3DB;
+ break;
+
+ case MIXMODE(DOWNMIX_3F2R, DOWNMIX_2F1R):
+ case MIXMODE(DOWNMIX_3F4R, DOWNMIX_2F1R):
+ case MIXMODE(DOWNMIX_3F4R, DOWNMIX_2F2R):
+ if (1 + clev < LVL_PLUS3DB)
+ goto level_3db;
+ case MIXMODE(DOWNMIX_3F, DOWNMIX_STEREO):
+ case MIXMODE(DOWNMIX_3F, DOWNMIX_2F1R):
+ case MIXMODE(DOWNMIX_3F, DOWNMIX_2F2R):
+ case MIXMODE(DOWNMIX_3F, DOWNMIX_DOLBY):
+ case MIXMODE(DOWNMIX_3F, DOWNMIX_DPLII):
+ case MIXMODE(DOWNMIX_3F1R, DOWNMIX_2F1R):
+ case MIXMODE(DOWNMIX_3F1R, DOWNMIX_2F2R):
+ case MIXMODE(DOWNMIX_3F2R, DOWNMIX_2F2R):
+ level /= 1 + clev;
+ break;
+
+
+ case MIXMODE(DOWNMIX_2F1R, DOWNMIX_MONO):
+ level /= LVL_PLUS3DB + LVL_3DB * clev;
+ break;
+
+ case MIXMODE(DOWNMIX_2F1R, DOWNMIX_DOLBY):
+ level /= 1 + LVL_3DB;
+ break;
+
+ case MIXMODE(DOWNMIX_2F1R, DOWNMIX_STEREO):
+ case MIXMODE(DOWNMIX_2F1R, DOWNMIX_3F):
+ case MIXMODE(DOWNMIX_3F1R, DOWNMIX_3F):
+ level /= 1 + LVL_3DB * slev;
+ break;
+
+ case MIXMODE(DOWNMIX_3F1R, DOWNMIX_MONO):
+ level /= LVL_PLUS3DB + LVL_PLUS3DB * clev + LVL_3DB * slev;
+ break;
+
+ case MIXMODE(DOWNMIX_3F1R, DOWNMIX_STEREO):
+ level /= 1 + clev + LVL_3DB * slev;
+ break;
+
+ case MIXMODE(DOWNMIX_3F1R, DOWNMIX_DOLBY):
+ case MIXMODE(DOWNMIX_3F1R, DOWNMIX_DPLII):
+ case MIXMODE(DOWNMIX_2F2R, DOWNMIX_DOLBY):
+ level /= 1 + LVL_PLUS3DB;
+ break;
+
+ case MIXMODE(DOWNMIX_2F2R, DOWNMIX_MONO):
+ level /= LVL_PLUS3DB + LVL_PLUS3DB * slev;
+ break;
+
+ case MIXMODE(DOWNMIX_2F2R, DOWNMIX_STEREO):
+ case MIXMODE(DOWNMIX_2F2R, DOWNMIX_3F):
+ case MIXMODE(DOWNMIX_3F2R, DOWNMIX_3F):
+ level /= 1 + slev;
+ break;
+
+ case MIXMODE(DOWNMIX_2F2R, DOWNMIX_DPLII):
+ level /= 1 + LVL_SQRT_1_3 + LVL_SQRT_2_3;
+ break;
+
+ case MIXMODE(DOWNMIX_3F2R, DOWNMIX_MONO):
+ case MIXMODE(DOWNMIX_3F4R, DOWNMIX_MONO):
+ level /= LVL_PLUS3DB + LVL_PLUS3DB * clev * LVL_PLUS3DB * slev;
+ break;
+
+ case MIXMODE(DOWNMIX_3F2R, DOWNMIX_STEREO):
+ level /= 1 + clev + slev;
+ break;
+
+ case MIXMODE(DOWNMIX_3F2R, DOWNMIX_DOLBY):
+ level /= 1 + 3 * LVL_3DB;
+ break;
+
+ case MIXMODE(DOWNMIX_3F2R, DOWNMIX_DPLII):
+ level /= 1 + LVL_3DB + LVL_SQRT_1_3 + LVL_SQRT_2_3;
+ break;
+
+ case MIXMODE(DOWNMIX_3F4R, DOWNMIX_STEREO):
+ level /= 1 + clev + LVL_PLUS3DB * slev;
+ break;
+
+ case MIXMODE(DOWNMIX_3F4R, DOWNMIX_3F):
+ level /= 1 + LVL_PLUS3DB * slev;
+ break;
+
+ case MIXMODE(DOWNMIX_3F4R, DOWNMIX_DOLBY):
+ level /= 1 + 5 * LVL_3DB;
+ break;
+
+ case MIXMODE(DOWNMIX_3F4R, DOWNMIX_DPLII):
+ level /= 1 + LVL_3DB + 2 * LVL_SQRT_1_3 + 2 * LVL_SQRT_2_3;
+ }
+
+ for (ii = 0; ii < 8; ii++)
+ {
+ for (jj = 0; jj < 8; jj++)
+ {
+ downmix->matrix[ii][jj] *= level;
+ }
+ }
+}
+
+void hb_downmix_set_bias( hb_downmix_t * downmix, hb_sample_t bias )
+{
+ downmix->bias = bias;
+}
+
+// Changes the downmix mode if it needs changing after initialization
+int hb_downmix_set_mode( hb_downmix_t * downmix, int layout, int mixdown )
+{
+ int ii, jj;
+ int lfe_in, lfe_out;
+ int mode_in, mode_out;
+ hb_sample_t (*matrix)[8];
+
+ if ( downmix == NULL )
+ return -1;
+
+ mode_in = hb_layout_to_mode(layout);
+ mode_out = hb_mixdown_to_mode(mixdown);
+ downmix->mode_in = mode_in;
+ downmix->mode_out = mode_out;
+
+ mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
+ mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
+
+ if (mode_in >= DOWNMIX_NUM_MODES || mode_out >= DOWNMIX_NUM_MODES)
+ return -1;
+
+ matrix = downmix_matrix[mode_in][mode_out];
+
+ for (ii = 0; ii < 8; ii++)
+ {
+ for (jj = 0; jj < 8; jj++)
+ {
+ downmix->matrix[ii][jj] = matrix[ii][jj];
+ }
+ }
+
+ lfe_in = ((downmix->mode_in & DOWNMIX_LFE_FLAG) != 0);
+ lfe_out = ((downmix->mode_out & DOWNMIX_LFE_FLAG) != 0);
+
+ downmix->nchans_in = nchans_tbl[mode_in] + lfe_in;
+ downmix->nchans_out = nchans_tbl[mode_out] + lfe_out;
+ return 0;
+}
+
+// Changes the downmix levels if they need changing after initialization
+void hb_downmix_set_level( hb_downmix_t * downmix, hb_sample_t clev, hb_sample_t slev, hb_sample_t level )
+{
+ int ii, jj;
+ int mode_in, mode_out;
+ hb_sample_t (*matrix)[8];
+
+ if ( downmix == NULL )
+ return;
+
+ mode_in = downmix->mode_in & ~DOWNMIX_FLAGS_MASK;
+ mode_out = downmix->mode_out & ~DOWNMIX_FLAGS_MASK;
+
+ if (mode_in >= DOWNMIX_NUM_MODES || mode_out >= DOWNMIX_NUM_MODES)
+ return;
+
+ matrix = downmix_matrix[mode_in][mode_out];
+
+ for (ii = 0; ii < 8; ii++)
+ {
+ for (jj = 0; jj < 8; jj++)
+ {
+ downmix->matrix[ii][jj] = matrix[ii][jj];
+ }
+ }
+ downmix->clev = clev;
+ downmix->slev = slev;
+ downmix->level = level;
+ set_level(downmix->matrix, clev, slev, level, mode_in, mode_out);
+}
+
+hb_downmix_t * hb_downmix_init(int layout, int mixdown)
+{
+ hb_downmix_t * downmix = calloc(1, sizeof(hb_downmix_t));
+
+ if (downmix == NULL)
+ return NULL;
+ if ( hb_downmix_set_mode( downmix, layout, mixdown ) < 0 )
+ {
+ free( downmix );
+ return NULL;
+ }
+ // Set some good default values
+ downmix->clev = LVL_3DB;
+ downmix->slev = LVL_3DB;
+ downmix->level = 1.0;
+ downmix->bias = 0.0;
+ set_level(downmix->matrix, LVL_3DB, LVL_3DB, 1.0,
+ downmix->mode_in, downmix->mode_out);
+ return downmix;
+}
+
+void hb_downmix_close( hb_downmix_t **downmix )
+{
+ if (*downmix != NULL)
+ free(*downmix);
+ *downmix = NULL;
+}
+
+void hb_downmix( hb_downmix_t * downmix, hb_sample_t * dst, hb_sample_t * src, int nsamples)
+{
+ matrix_mul(dst, src, downmix->nchans_out, downmix->nchans_in,
+ nsamples, downmix->matrix, downmix->bias);
+}
+
+int hb_need_downmix( int layout, int mixdown )
+{
+ int mode_in, mode_out;
+
+ mode_in = hb_layout_to_mode(layout);
+ mode_out = hb_mixdown_to_mode(mixdown);
+
+ return (mode_in != mode_out);
+}