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 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 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 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 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 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 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 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