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