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