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 #define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
39
mapping_matrix_get_size(int rows,int cols)40 opus_int32 mapping_matrix_get_size(int rows, int cols)
41 {
42 opus_int32 size;
43
44 /* Mapping Matrix must only support up to 255 channels in or out.
45 * Additionally, the total cell count must be <= 65004 octets in order
46 * for the matrix to be stored in an OGG header.
47 */
48 if (rows > 255 || cols > 255)
49 return 0;
50 size = rows * (opus_int32)cols * sizeof(opus_int16);
51 if (size > 65004)
52 return 0;
53
54 return align(sizeof(MappingMatrix)) + align(size);
55 }
56
mapping_matrix_get_data(const MappingMatrix * matrix)57 opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
58 {
59 /* void* cast avoids clang -Wcast-align warning */
60 return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix)));
61 }
62
mapping_matrix_init(MappingMatrix * const matrix,int rows,int cols,int gain,const opus_int16 * data,opus_int32 data_size)63 void mapping_matrix_init(MappingMatrix * const matrix,
64 int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
65 {
66 int i;
67 opus_int16 *ptr;
68
69 #if !defined(ENABLE_ASSERTIONS)
70 (void)data_size;
71 #endif
72 celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
73
74 matrix->rows = rows;
75 matrix->cols = cols;
76 matrix->gain = gain;
77 ptr = mapping_matrix_get_data(matrix);
78 for (i = 0; i < rows * cols; i++)
79 {
80 ptr[i] = data[i];
81 }
82 }
83
84 #ifndef DISABLE_FLOAT_API
mapping_matrix_multiply_channel_in_float(const MappingMatrix * matrix,const float * input,int input_rows,opus_val16 * output,int output_row,int output_rows,int frame_size)85 void mapping_matrix_multiply_channel_in_float(
86 const MappingMatrix *matrix,
87 const float *input,
88 int input_rows,
89 opus_val16 *output,
90 int output_row,
91 int output_rows,
92 int frame_size)
93 {
94 /* Matrix data is ordered col-wise. */
95 opus_int16* matrix_data;
96 int i, col;
97
98 celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
99
100 matrix_data = mapping_matrix_get_data(matrix);
101
102 for (i = 0; i < frame_size; i++)
103 {
104 float tmp = 0;
105 for (col = 0; col < input_rows; col++)
106 {
107 tmp +=
108 matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
109 input[MATRIX_INDEX(input_rows, col, i)];
110 }
111 #if defined(FIXED_POINT)
112 output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp);
113 #else
114 output[output_rows * i] = (1/32768.f)*tmp;
115 #endif
116 }
117 }
118
mapping_matrix_multiply_channel_out_float(const MappingMatrix * matrix,const opus_val16 * input,int input_row,int input_rows,float * output,int output_rows,int frame_size)119 void mapping_matrix_multiply_channel_out_float(
120 const MappingMatrix *matrix,
121 const opus_val16 *input,
122 int input_row,
123 int input_rows,
124 float *output,
125 int output_rows,
126 int frame_size
127 )
128 {
129 /* Matrix data is ordered col-wise. */
130 opus_int16* matrix_data;
131 int i, row;
132 float input_sample;
133
134 celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
135
136 matrix_data = mapping_matrix_get_data(matrix);
137
138 for (i = 0; i < frame_size; i++)
139 {
140 #if defined(FIXED_POINT)
141 input_sample = (1/32768.f)*input[input_rows * i];
142 #else
143 input_sample = input[input_rows * i];
144 #endif
145 for (row = 0; row < output_rows; row++)
146 {
147 float tmp =
148 (1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
149 input_sample;
150 output[MATRIX_INDEX(output_rows, row, i)] += tmp;
151 }
152 }
153 }
154 #endif /* DISABLE_FLOAT_API */
155
mapping_matrix_multiply_channel_in_short(const MappingMatrix * matrix,const opus_int16 * input,int input_rows,opus_val16 * output,int output_row,int output_rows,int frame_size)156 void mapping_matrix_multiply_channel_in_short(
157 const MappingMatrix *matrix,
158 const opus_int16 *input,
159 int input_rows,
160 opus_val16 *output,
161 int output_row,
162 int output_rows,
163 int frame_size)
164 {
165 /* Matrix data is ordered col-wise. */
166 opus_int16* matrix_data;
167 int i, col;
168
169 celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
170
171 matrix_data = mapping_matrix_get_data(matrix);
172
173 for (i = 0; i < frame_size; i++)
174 {
175 opus_val32 tmp = 0;
176 for (col = 0; col < input_rows; col++)
177 {
178 #if defined(FIXED_POINT)
179 tmp +=
180 ((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
181 (opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
182 #else
183 tmp +=
184 matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
185 input[MATRIX_INDEX(input_rows, col, i)];
186 #endif
187 }
188 #if defined(FIXED_POINT)
189 output[output_rows * i] = (opus_int16)((tmp + 64) >> 7);
190 #else
191 output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
192 #endif
193 }
194 }
195
mapping_matrix_multiply_channel_out_short(const MappingMatrix * matrix,const opus_val16 * input,int input_row,int input_rows,opus_int16 * output,int output_rows,int frame_size)196 void mapping_matrix_multiply_channel_out_short(
197 const MappingMatrix *matrix,
198 const opus_val16 *input,
199 int input_row,
200 int input_rows,
201 opus_int16 *output,
202 int output_rows,
203 int frame_size)
204 {
205 /* Matrix data is ordered col-wise. */
206 opus_int16* matrix_data;
207 int i, row;
208 opus_int32 input_sample;
209
210 celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
211
212 matrix_data = mapping_matrix_get_data(matrix);
213
214 for (i = 0; i < frame_size; i++)
215 {
216 #if defined(FIXED_POINT)
217 input_sample = (opus_int32)input[input_rows * i];
218 #else
219 input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]);
220 #endif
221 for (row = 0; row < output_rows; row++)
222 {
223 opus_int32 tmp =
224 (opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
225 input_sample;
226 output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
227 }
228 }
229 }
230
231 const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
232 const opus_int16 mapping_matrix_foa_mixing_data[36] = {
233 16384, 0, -16384, 23170, 0, 0, 16384, 23170,
234 16384, 0, 0, 0, 16384, 0, -16384, -23170,
235 0, 0, 16384, -23170, 16384, 0, 0, 0,
236 0, 0, 0, 0, 32767, 0, 0, 0,
237 0, 0, 0, 32767
238 };
239
240 const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
241 const opus_int16 mapping_matrix_soa_mixing_data[121] = {
242 10923, 7723, 13377, -13377, 11585, 9459, 7723, -16384,
243 -6689, 0, 0, 10923, 7723, 13377, 13377, -11585,
244 9459, 7723, 16384, -6689, 0, 0, 10923, -15447,
245 13377, 0, 0, -18919, 7723, 0, 13377, 0,
246 0, 10923, 7723, -13377, -13377, 11585, -9459, 7723,
247 16384, -6689, 0, 0, 10923, -7723, 0, 13377,
248 -16384, 0, -15447, 0, 9459, 0, 0, 10923,
249 -7723, 0, -13377, 16384, 0, -15447, 0, 9459,
250 0, 0, 10923, 15447, 0, 0, 0, 0,
251 -15447, 0, -18919, 0, 0, 10923, 7723, -13377,
252 13377, -11585, -9459, 7723, -16384, -6689, 0, 0,
253 10923, -15447, -13377, 0, 0, 18919, 7723, 0,
254 13377, 0, 0, 0, 0, 0, 0, 0,
255 0, 0, 0, 0, 32767, 0, 0, 0,
256 0, 0, 0, 0, 0, 0, 0, 0,
257 32767
258 };
259
260 const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
261 const opus_int16 mapping_matrix_toa_mixing_data[324] = {
262 8208, 0, -881, 14369, 0, 0, -8192, -4163,
263 13218, 0, 0, 0, 11095, -8836, -6218, 14833,
264 0, 0, 8208, -10161, 881, 10161, -13218, -2944,
265 -8192, 2944, 0, -10488, -6218, 6248, -11095, -6248,
266 0, -10488, 0, 0, 8208, 10161, 881, -10161,
267 -13218, 2944, -8192, -2944, 0, 10488, -6218, -6248,
268 -11095, 6248, 0, 10488, 0, 0, 8176, 5566,
269 -11552, 5566, 9681, -11205, 8192, -11205, 0, 4920,
270 -15158, 9756, -3334, 9756, 0, -4920, 0, 0,
271 8176, 7871, 11552, 0, 0, 15846, 8192, 0,
272 -9681, -6958, 0, 13797, 3334, 0, -15158, 0,
273 0, 0, 8176, 0, 11552, 7871, 0, 0,
274 8192, 15846, 9681, 0, 0, 0, 3334, 13797,
275 15158, 6958, 0, 0, 8176, 5566, -11552, -5566,
276 -9681, -11205, 8192, 11205, 0, 4920, 15158, 9756,
277 -3334, -9756, 0, 4920, 0, 0, 8208, 14369,
278 -881, 0, 0, -4163, -8192, 0, -13218, -14833,
279 0, -8836, 11095, 0, 6218, 0, 0, 0,
280 8208, 10161, 881, 10161, 13218, 2944, -8192, 2944,
281 0, 10488, 6218, -6248, -11095, -6248, 0, -10488,
282 0, 0, 8208, -14369, -881, 0, 0, 4163,
283 -8192, 0, -13218, 14833, 0, 8836, 11095, 0,
284 6218, 0, 0, 0, 8208, 0, -881, -14369,
285 0, 0, -8192, 4163, 13218, 0, 0, 0,
286 11095, 8836, -6218, -14833, 0, 0, 8176, -5566,
287 -11552, 5566, -9681, 11205, 8192, -11205, 0, -4920,
288 15158, -9756, -3334, 9756, 0, -4920, 0, 0,
289 8176, 0, 11552, -7871, 0, 0, 8192, -15846,
290 9681, 0, 0, 0, 3334, -13797, 15158, -6958,
291 0, 0, 8176, -7871, 11552, 0, 0, -15846,
292 8192, 0, -9681, 6958, 0, -13797, 3334, 0,
293 -15158, 0, 0, 0, 8176, -5566, -11552, -5566,
294 9681, 11205, 8192, 11205, 0, -4920, -15158, -9756,
295 -3334, -9756, 0, 4920, 0, 0, 8208, -10161,
296 881, -10161, 13218, -2944, -8192, -2944, 0, -10488,
297 6218, 6248, -11095, 6248, 0, 10488, 0, 0,
298 0, 0, 0, 0, 0, 0, 0, 0,
299 0, 0, 0, 0, 0, 0, 0, 0,
300 32767, 0, 0, 0, 0, 0, 0, 0,
301 0, 0, 0, 0, 0, 0, 0, 0,
302 0, 0, 0, 32767
303 };
304
305 const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
306 const opus_int16 mapping_matrix_foa_demixing_data[36] = {
307 16384, 16384, 16384, 16384, 0, 0, 0, 23170,
308 0, -23170, 0, 0, -16384, 16384, -16384, 16384,
309 0, 0, 23170, 0, -23170, 0, 0, 0,
310 0, 0, 0, 0, 32767, 0, 0, 0,
311 0, 0, 0, 32767
312 };
313
314 const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
315 const opus_int16 mapping_matrix_soa_demixing_data[121] = {
316 2771, 2771, 2771, 2771, 2771, 2771, 2771, 2771,
317 2771, 0, 0, 10033, 10033, -20066, 10033, 14189,
318 14189, -28378, 10033, -20066, 0, 0, 3393, 3393,
319 3393, -3393, 0, 0, 0, -3393, -3393, 0,
320 0, -17378, 17378, 0, -17378, -24576, 24576, 0,
321 17378, 0, 0, 0, -14189, 14189, 0, -14189,
322 -28378, 28378, 0, 14189, 0, 0, 0, 2399,
323 2399, -4799, -2399, 0, 0, 0, -2399, 4799,
324 0, 0, 1959, 1959, 1959, 1959, -3918, -3918,
325 -3918, 1959, 1959, 0, 0, -4156, 4156, 0,
326 4156, 0, 0, 0, -4156, 0, 0, 0,
327 8192, 8192, -16384, 8192, 16384, 16384, -32768, 8192,
328 -16384, 0, 0, 0, 0, 0, 0, 0,
329 0, 0, 0, 0, 8312, 0, 0, 0,
330 0, 0, 0, 0, 0, 0, 0, 0,
331 8312
332 };
333
334 const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
335 const opus_int16 mapping_matrix_toa_demixing_data[324] = {
336 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
337 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
338 0, 0, 0, -9779, 9779, 6263, 8857, 0,
339 6263, 13829, 9779, -13829, 0, -6263, 0, -8857,
340 -6263, -9779, 0, 0, -3413, 3413, 3413, -11359,
341 11359, 11359, -11359, -3413, 3413, -3413, -3413, -11359,
342 11359, 11359, -11359, 3413, 0, 0, 13829, 9779,
343 -9779, 6263, 0, 8857, -6263, 0, 9779, 0,
344 -13829, 6263, -8857, 0, -6263, -9779, 0, 0,
345 0, -15617, -15617, 6406, 0, 0, -6406, 0,
346 15617, 0, 0, -6406, 0, 0, 6406, 15617,
347 0, 0, 0, -5003, 5003, -10664, 15081, 0,
348 -10664, -7075, 5003, 7075, 0, 10664, 0, -15081,
349 10664, -5003, 0, 0, -8176, -8176, -8176, 8208,
350 8208, 8208, 8208, -8176, -8176, -8176, -8176, 8208,
351 8208, 8208, 8208, -8176, 0, 0, -7075, 5003,
352 -5003, -10664, 0, 15081, 10664, 0, 5003, 0,
353 7075, -10664, -15081, 0, 10664, -5003, 0, 0,
354 15617, 0, 0, 0, -6406, 6406, 0, -15617,
355 0, -15617, 15617, 0, 6406, -6406, 0, 0,
356 0, 0, 0, -11393, 11393, 2993, -4233, 0,
357 2993, -16112, 11393, 16112, 0, -2993, 0, 4233,
358 -2993, -11393, 0, 0, 0, -9974, -9974, -13617,
359 0, 0, 13617, 0, 9974, 0, 0, 13617,
360 0, 0, -13617, 9974, 0, 0, 0, 5579,
361 -5579, 10185, 14403, 0, 10185, -7890, -5579, 7890,
362 0, -10185, 0, -14403, -10185, 5579, 0, 0,
363 11826, -11826, -11826, -901, 901, 901, -901, 11826,
364 -11826, 11826, 11826, -901, 901, 901, -901, -11826,
365 0, 0, -7890, -5579, 5579, 10185, 0, 14403,
366 -10185, 0, -5579, 0, 7890, 10185, -14403, 0,
367 -10185, 5579, 0, 0, -9974, 0, 0, 0,
368 -13617, 13617, 0, 9974, 0, 9974, -9974, 0,
369 13617, -13617, 0, 0, 0, 0, 16112, -11393,
370 11393, -2993, 0, 4233, 2993, 0, -11393, 0,
371 -16112, -2993, -4233, 0, 2993, 11393, 0, 0,
372 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 0, 0, 0, 0, 0, 0, 0,
374 32767, 0, 0, 0, 0, 0, 0, 0,
375 0, 0, 0, 0, 0, 0, 0, 0,
376 0, 0, 0, 32767
377 };
378
379