Support for Channel Mapping 253
[opus.git] / src / mapping_matrix.c
1 /* Copyright (c) 2017 Google Inc.
2    Written by Andrew Allen */
3 /*
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions
6    are met:
7
8    - Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10
11    - Redistributions in binary form must reproduce the above copyright
12    notice, this list of conditions and the following disclaimer in the
13    documentation and/or other materials provided with the distribution.
14
15    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "arch.h"
33 #include "float_cast.h"
34 #include "opus_private.h"
35 #include "opus_defines.h"
36 #include "mapping_matrix.h"
37
38 #ifdef ENABLE_EXPERIMENTAL_AMBISONICS
39
40 #define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
41
42 int mapping_matrix_get_size(int rows, int cols)
43 {
44   return align(sizeof(MappingMatrix)) + rows * cols * sizeof(opus_int16);
45 }
46
47 opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
48 {
49   return (opus_int16*)(void *)(matrix + align(sizeof(MappingMatrix)));
50 }
51
52 void mapping_matrix_init(MappingMatrix * const matrix,
53   int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
54 {
55   int i;
56   opus_int16 *ptr;
57
58 #if !defined(ENABLE_ASSERTIONS)
59   (void)data_size;
60 #endif
61   celt_assert((opus_uint32)data_size == rows * cols * sizeof(opus_int16));
62
63   matrix->rows = rows;
64   matrix->cols = cols;
65   matrix->gain = gain;
66   ptr = mapping_matrix_get_data(matrix);
67   for (i = 0; i < rows * cols; i++)
68   {
69      ptr[i] = data[i];
70   }
71 }
72
73 #ifndef DISABLE_FLOAT_API
74 void mapping_matrix_multiply_float(const MappingMatrix *matrix,
75                                    const float *input, int input_rows,
76                                    float *output, int output_rows,
77                                    int frame_size)
78 {
79   /* Matrix data is ordered col-wise.
80    * Input (x) is [n x k], output (y) is [m x k], matrix (M) is [m x n]:
81    *   y = M x
82    */
83   opus_int16* matrix_data;
84   int i, row, col;
85   float matrix_cell, input_sample;
86
87   celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
88
89   matrix_data = mapping_matrix_get_data(matrix);
90
91   for (i = 0; i < frame_size; i++)
92   {
93     for (row = 0; row < output_rows; row++)
94     {
95       output[MATRIX_INDEX(output_rows, row, i)] = 0;
96       for (col = 0; col < input_rows; col++)
97       {
98         matrix_cell = (0.000030518f)*(float)matrix_data[MATRIX_INDEX(matrix->rows, row, col)];
99         input_sample = input[MATRIX_INDEX(input_rows, col, i)];
100         output[MATRIX_INDEX(output_rows, row, i)] += matrix_cell * input_sample;
101       }
102     }
103   }
104 }
105 #endif /* DISABLE_FLOAT_API */
106
107 void mapping_matrix_multiply_short(const MappingMatrix *matrix,
108                                    const opus_int16 *input, int input_rows,
109                                    opus_int16 *output, int output_rows,
110                                    int frame_size)
111 {
112   /* Matrix data is ordered col-wise.
113    * Input (x) is [n x k], output (y) is [m x k], matrix (M) is [m x n]:
114    *   y = M x
115    */
116   opus_int16* matrix_data;
117   int i, row, col;
118
119   celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
120
121   matrix_data = mapping_matrix_get_data(matrix);
122
123   for (i = 0; i < frame_size; i++)
124   {
125     for (row = 0; row < output_rows; row++)
126     {
127       opus_int32 tmp = 0;
128       for (col = 0; col < input_rows; col++)
129       {
130         tmp +=
131           (matrix_data[MATRIX_INDEX(matrix->rows, row, col)] *
132           input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
133       }
134       output[MATRIX_INDEX(output_rows, row, i)] = (tmp + 64)>>7;
135     }
136   }
137 }
138
139 const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
140 const opus_int16 mapping_matrix_foa_mixing_data[36] = {
141      16384,      0, -16384,  23170,      0,      0,  16384,  23170,
142      16384,      0,      0,      0,  16384,      0, -16384, -23170,
143          0,      0,  16384, -23170,  16384,      0,      0,      0,
144          0,      0,      0,      0,  32767,      0,      0,      0,
145          0,      0,      0,  32767
146 };
147
148 const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
149 const opus_int16 mapping_matrix_soa_mixing_data[121] = {
150      10923,   7723,  13377, -13377,  11585,   9459,   7723, -16384,
151      -6689,      0,      0,  10923,   7723,  13377,  13377, -11585,
152       9459,   7723,  16384,  -6689,      0,      0,  10923, -15447,
153      13377,      0,      0, -18919,   7723,      0,  13377,      0,
154          0,  10923,   7723, -13377, -13377,  11585,  -9459,   7723,
155      16384,  -6689,      0,      0,  10923,  -7723,      0,  13377,
156     -16384,      0, -15447,      0,   9459,      0,      0,  10923,
157      -7723,      0, -13377,  16384,      0, -15447,      0,   9459,
158          0,      0,  10923,  15447,      0,      0,      0,      0,
159     -15447,      0, -18919,      0,      0,  10923,   7723, -13377,
160      13377, -11585,  -9459,   7723, -16384,  -6689,      0,      0,
161      10923, -15447, -13377,      0,      0,  18919,   7723,      0,
162      13377,      0,      0,      0,      0,      0,      0,      0,
163          0,      0,      0,      0,  32767,      0,      0,      0,
164          0,      0,      0,      0,      0,      0,      0,      0,
165      32767
166 };
167
168 const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
169 const opus_int16 mapping_matrix_toa_mixing_data[324] = {
170       8208,      0,   -881,  14369,      0,      0,  -8192,  -4163,
171      13218,      0,      0,      0,  11095,  -8836,  -6218,  14833,
172          0,      0,   8208, -10161,    881,  10161, -13218,  -2944,
173      -8192,   2944,      0, -10488,  -6218,   6248, -11095,  -6248,
174          0, -10488,      0,      0,   8208,  10161,    881, -10161,
175     -13218,   2944,  -8192,  -2944,      0,  10488,  -6218,  -6248,
176     -11095,   6248,      0,  10488,      0,      0,   8176,   5566,
177     -11552,   5566,   9681, -11205,   8192, -11205,      0,   4920,
178     -15158,   9756,  -3334,   9756,      0,  -4920,      0,      0,
179       8176,   7871,  11552,      0,      0,  15846,   8192,      0,
180      -9681,  -6958,      0,  13797,   3334,      0, -15158,      0,
181          0,      0,   8176,      0,  11552,   7871,      0,      0,
182       8192,  15846,   9681,      0,      0,      0,   3334,  13797,
183      15158,   6958,      0,      0,   8176,   5566, -11552,  -5566,
184      -9681, -11205,   8192,  11205,      0,   4920,  15158,   9756,
185      -3334,  -9756,      0,   4920,      0,      0,   8208,  14369,
186       -881,      0,      0,  -4163,  -8192,      0, -13218, -14833,
187          0,  -8836,  11095,      0,   6218,      0,      0,      0,
188       8208,  10161,    881,  10161,  13218,   2944,  -8192,   2944,
189          0,  10488,   6218,  -6248, -11095,  -6248,      0, -10488,
190          0,      0,   8208, -14369,   -881,      0,      0,   4163,
191      -8192,      0, -13218,  14833,      0,   8836,  11095,      0,
192       6218,      0,      0,      0,   8208,      0,   -881, -14369,
193          0,      0,  -8192,   4163,  13218,      0,      0,      0,
194      11095,   8836,  -6218, -14833,      0,      0,   8176,  -5566,
195     -11552,   5566,  -9681,  11205,   8192, -11205,      0,  -4920,
196      15158,  -9756,  -3334,   9756,      0,  -4920,      0,      0,
197       8176,      0,  11552,  -7871,      0,      0,   8192, -15846,
198       9681,      0,      0,      0,   3334, -13797,  15158,  -6958,
199          0,      0,   8176,  -7871,  11552,      0,      0, -15846,
200       8192,      0,  -9681,   6958,      0, -13797,   3334,      0,
201     -15158,      0,      0,      0,   8176,  -5566, -11552,  -5566,
202       9681,  11205,   8192,  11205,      0,  -4920, -15158,  -9756,
203      -3334,  -9756,      0,   4920,      0,      0,   8208, -10161,
204        881, -10161,  13218,  -2944,  -8192,  -2944,      0, -10488,
205       6218,   6248, -11095,   6248,      0,  10488,      0,      0,
206          0,      0,      0,      0,      0,      0,      0,      0,
207          0,      0,      0,      0,      0,      0,      0,      0,
208      32767,      0,      0,      0,      0,      0,      0,      0,
209          0,      0,      0,      0,      0,      0,      0,      0,
210          0,      0,      0,  32767
211 };
212
213 const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
214 const opus_int16 mapping_matrix_foa_demixing_data[36] = {
215      16384,  16384,  16384,  16384,      0,      0,      0,  23170,
216          0, -23170,      0,      0, -16384,  16384, -16384,  16384,
217          0,      0,  23170,      0, -23170,      0,      0,      0,
218          0,      0,      0,      0,  32767,      0,      0,      0,
219          0,      0,      0,  32767
220 };
221
222 const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
223 const opus_int16 mapping_matrix_soa_demixing_data[121] = {
224       2771,   2771,   2771,   2771,   2771,   2771,   2771,   2771,
225       2771,      0,      0,  10033,  10033, -20066,  10033,  14189,
226      14189, -28378,  10033, -20066,      0,      0,   3393,   3393,
227       3393,  -3393,      0,      0,      0,  -3393,  -3393,      0,
228          0, -17378,  17378,      0, -17378, -24576,  24576,      0,
229      17378,      0,      0,      0, -14189,  14189,      0, -14189,
230     -28378,  28378,      0,  14189,      0,      0,      0,   2399,
231       2399,  -4799,  -2399,      0,      0,      0,  -2399,   4799,
232          0,      0,   1959,   1959,   1959,   1959,  -3918,  -3918,
233      -3918,   1959,   1959,      0,      0,  -4156,   4156,      0,
234       4156,      0,      0,      0,  -4156,      0,      0,      0,
235       8192,   8192, -16384,   8192,  16384,  16384, -32768,   8192,
236     -16384,      0,      0,      0,      0,      0,      0,      0,
237          0,      0,      0,      0,   8312,      0,      0,      0,
238          0,      0,      0,      0,      0,      0,      0,      0,
239       8312
240 };
241
242 const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
243 const opus_int16 mapping_matrix_toa_demixing_data[324] = {
244       8192,   8192,   8192,   8192,   8192,   8192,   8192,   8192,
245       8192,   8192,   8192,   8192,   8192,   8192,   8192,   8192,
246          0,      0,      0,  -9779,   9779,   6263,   8857,      0,
247       6263,  13829,   9779, -13829,      0,  -6263,      0,  -8857,
248      -6263,  -9779,      0,      0,  -3413,   3413,   3413, -11359,
249      11359,  11359, -11359,  -3413,   3413,  -3413,  -3413, -11359,
250      11359,  11359, -11359,   3413,      0,      0,  13829,   9779,
251      -9779,   6263,      0,   8857,  -6263,      0,   9779,      0,
252     -13829,   6263,  -8857,      0,  -6263,  -9779,      0,      0,
253          0, -15617, -15617,   6406,      0,      0,  -6406,      0,
254      15617,      0,      0,  -6406,      0,      0,   6406,  15617,
255          0,      0,      0,  -5003,   5003, -10664,  15081,      0,
256     -10664,  -7075,   5003,   7075,      0,  10664,      0, -15081,
257      10664,  -5003,      0,      0,  -8176,  -8176,  -8176,   8208,
258       8208,   8208,   8208,  -8176,  -8176,  -8176,  -8176,   8208,
259       8208,   8208,   8208,  -8176,      0,      0,  -7075,   5003,
260      -5003, -10664,      0,  15081,  10664,      0,   5003,      0,
261       7075, -10664, -15081,      0,  10664,  -5003,      0,      0,
262      15617,      0,      0,      0,  -6406,   6406,      0, -15617,
263          0, -15617,  15617,      0,   6406,  -6406,      0,      0,
264          0,      0,      0, -11393,  11393,   2993,  -4233,      0,
265       2993, -16112,  11393,  16112,      0,  -2993,      0,   4233,
266      -2993, -11393,      0,      0,      0,  -9974,  -9974, -13617,
267          0,      0,  13617,      0,   9974,      0,      0,  13617,
268          0,      0, -13617,   9974,      0,      0,      0,   5579,
269      -5579,  10185,  14403,      0,  10185,  -7890,  -5579,   7890,
270          0, -10185,      0, -14403, -10185,   5579,      0,      0,
271      11826, -11826, -11826,   -901,    901,    901,   -901,  11826,
272     -11826,  11826,  11826,   -901,    901,    901,   -901, -11826,
273          0,      0,  -7890,  -5579,   5579,  10185,      0,  14403,
274     -10185,      0,  -5579,      0,   7890,  10185, -14403,      0,
275     -10185,   5579,      0,      0,  -9974,      0,      0,      0,
276     -13617,  13617,      0,   9974,      0,   9974,  -9974,      0,
277      13617, -13617,      0,      0,      0,      0,  16112, -11393,
278      11393,  -2993,      0,   4233,   2993,      0, -11393,      0,
279     -16112,  -2993,  -4233,      0,   2993,  11393,      0,      0,
280          0,      0,      0,      0,      0,      0,      0,      0,
281          0,      0,      0,      0,      0,      0,      0,      0,
282      32767,      0,      0,      0,      0,      0,      0,      0,
283          0,      0,      0,      0,      0,      0,      0,      0,
284          0,      0,      0,  32767
285 };
286
287 #endif /* ENABLE_EXPERIMENTAL_AMBISONICS */