1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <string.h> 18 #include <audio_utils/channels.h> 19 #include "private/private.h" 20 21 /* 22 * Clamps a 24-bit value from a 32-bit sample 23 */ 24 static inline int32_t clamp24(int32_t sample) 25 { 26 if ((sample>>23) ^ (sample>>31)) { 27 sample = 0x007FFFFF ^ (sample>>31); 28 } 29 return sample; 30 } 31 32 /* 33 * Converts a uint8x3_t into an int32_t 34 */ 35 static inline int32_t uint8x3_to_int32(uint8x3_t val) { 36 #if HAVE_BIG_ENDIAN 37 int32_t temp = (val.c[0] << 24 | val.c[1] << 16 | val.c[2] << 8) >> 8; 38 #else 39 int32_t temp = (val.c[2] << 24 | val.c[1] << 16 | val.c[0] << 8) >> 8; 40 #endif 41 return clamp24(temp); 42 } 43 44 /* 45 * Converts an int32_t to a uint8x3_t 46 */ 47 static inline uint8x3_t int32_to_uint8x3(int32_t in) { 48 uint8x3_t out; 49 #if HAVE_BIG_ENDIAN 50 out.c[2] = in; 51 out.c[1] = in >> 8; 52 out.c[0] = in >> 16; 53 #else 54 out.c[0] = in; 55 out.c[1] = in >> 8; 56 out.c[2] = in >> 16; 57 #endif 58 return out; 59 } 60 61 /* Channel expands (adds zeroes to audio frame end) from an input buffer to an output buffer. 62 * See expand_channels() function below for parameter definitions. 63 * 64 * Move from back to front so that the conversion can be done in-place 65 * i.e. in_buff == out_buff 66 * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size. 67 */ 68 #define EXPAND_CHANNELS(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes, zero) \ 69 { \ 70 size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \ 71 size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \ 72 typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \ 73 size_t src_index; \ 74 typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \ 75 size_t num_zero_chans = (out_buff_chans) - (in_buff_chans); \ 76 for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \ 77 size_t dst_offset; \ 78 for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) { \ 79 *dst_ptr-- = zero; \ 80 } \ 81 for (; dst_offset < (out_buff_chans); dst_offset++) { \ 82 *dst_ptr-- = *src_ptr--; \ 83 } \ 84 } \ 85 /* return number of *bytes* generated */ \ 86 return num_out_samples * sizeof(*(out_buff)); \ 87 } 88 89 /* Channel expands from an input buffer to an output buffer. 90 * See expand_selected_channels() function below for parameter definitions. 91 * Selected channels are replaced in the output buffer, with any extra channels 92 * per frame left alone. 93 * 94 * Move from back to front so that the conversion can be done in-place 95 * i.e. in_buff == out_buff 96 * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size. 97 */ 98 /* This is written as a C macro because it operates on generic types, 99 * which in a C++ file could be alternatively achieved by a "template" 100 * or an "auto" declaration. 101 * TODO: convert this from a C file to a C++ file. 102 */ 103 #define EXPAND_SELECTED_CHANNELS( \ 104 in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes) \ 105 { \ 106 size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \ 107 size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \ 108 typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \ 109 size_t src_index; \ 110 typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \ 111 size_t num_extra_chans = (out_buff_chans) - (in_buff_chans); \ 112 for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \ 113 dst_ptr -= num_extra_chans; \ 114 for (size_t dst_offset = num_extra_chans; dst_offset < (out_buff_chans); dst_offset++) { \ 115 *dst_ptr-- = *src_ptr--; \ 116 } \ 117 } \ 118 /* return number of *bytes* generated */ \ 119 return num_out_samples * sizeof(*(out_buff)); \ 120 } 121 122 123 /* Channel expands from a MONO input buffer to a MULTICHANNEL output buffer by duplicating the 124 * single input channel to the first 2 output channels and 0-filling the remaining. 125 * See expand_channels() function below for parameter definitions. 126 * 127 * in_buff_chans MUST be 1 and out_buff_chans MUST be >= 2 128 * 129 * Move from back to front so that the conversion can be done in-place 130 * i.e. in_buff == out_buff 131 * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size. 132 */ 133 #define EXPAND_MONO_TO_MULTI(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes, zero) \ 134 { \ 135 size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \ 136 size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \ 137 typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \ 138 size_t src_index; \ 139 typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \ 140 size_t num_zero_chans = (out_buff_chans) - (in_buff_chans) - 1; \ 141 for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \ 142 size_t dst_offset; \ 143 for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) { \ 144 *dst_ptr-- = zero; \ 145 } \ 146 for (; dst_offset < (out_buff_chans); dst_offset++) { \ 147 *dst_ptr-- = *src_ptr; \ 148 } \ 149 src_ptr--; \ 150 } \ 151 /* return number of *bytes* generated */ \ 152 return num_out_samples * sizeof(*(out_buff)); \ 153 } 154 155 /* Channel contracts (removes from audio frame end) from an input buffer to an output buffer. 156 * See contract_channels() function below for parameter definitions. 157 * 158 * Move from front to back so that the conversion can be done in-place 159 * i.e. in_buff == out_buff 160 * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size. 161 */ 162 #define CONTRACT_CHANNELS(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes) \ 163 { \ 164 size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \ 165 size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \ 166 size_t num_skip_samples = (in_buff_chans) - (out_buff_chans); \ 167 typeof(out_buff) dst_ptr = out_buff; \ 168 typeof(in_buff) src_ptr = in_buff; \ 169 size_t src_index; \ 170 for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \ 171 size_t dst_offset; \ 172 for (dst_offset = 0; dst_offset < (out_buff_chans); dst_offset++) { \ 173 *dst_ptr++ = *src_ptr++; \ 174 } \ 175 src_ptr += num_skip_samples; \ 176 } \ 177 /* return number of *bytes* generated */ \ 178 return num_out_samples * sizeof(*(out_buff)); \ 179 } 180 181 /* Channel contracts from a MULTICHANNEL input buffer to a MONO output buffer by mixing the 182 * first two input channels into the single output channel (and skipping the rest). 183 * See contract_channels() function below for parameter definitions. 184 * 185 * in_buff_chans MUST be >= 2 and out_buff_chans MUST be 1 186 * 187 * Move from front to back so that the conversion can be done in-place 188 * i.e. in_buff == out_buff 189 * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size. 190 * NOTE: Overload of the summed channels is avoided by averaging the two input channels. 191 * NOTE: Can not be used for uint8x3_t samples, see CONTRACT_TO_MONO_24() below. 192 */ 193 #define CONTRACT_TO_MONO(in_buff, out_buff, num_in_bytes) \ 194 { \ 195 size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \ 196 size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \ 197 size_t num_skip_samples = in_buff_chans - 2; \ 198 typeof(out_buff) dst_ptr = out_buff; \ 199 typeof(in_buff) src_ptr = in_buff; \ 200 int32_t temp0, temp1; \ 201 size_t src_index; \ 202 for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \ 203 temp0 = *src_ptr++; \ 204 temp1 = *src_ptr++; \ 205 /* *dst_ptr++ = temp >> 1; */ \ 206 /* This bit of magic adds and normalizes without overflow (or so claims hunga@) */ \ 207 /* Bitwise half adder trick, see http://en.wikipedia.org/wiki/Adder_(electronics) */ \ 208 /* Hacker's delight, p. 19 http://www.hackersdelight.org/basics2.pdf */ \ 209 *dst_ptr++ = (temp0 & temp1) + ((temp0 ^ temp1) >> 1); \ 210 src_ptr += num_skip_samples; \ 211 } \ 212 /* return number of *bytes* generated */ \ 213 return num_out_samples * sizeof(*(out_buff)); \ 214 } 215 216 /* Channel contracts from a MULTICHANNEL uint8x3_t input buffer to a MONO uint8x3_t output buffer 217 * by mixing the first two input channels into the single output channel (and skipping the rest). 218 * See contract_channels() function below for parameter definitions. 219 * 220 * Move from front to back so that the conversion can be done in-place 221 * i.e. in_buff == out_buff 222 * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size. 223 * NOTE: Overload of the summed channels is avoided by averaging the two input channels. 224 * NOTE: Can not be used for normal, scalar samples, see CONTRACT_TO_MONO() above. 225 */ 226 #define CONTRACT_TO_MONO_24(in_buff, out_buff, num_in_bytes) \ 227 { \ 228 size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \ 229 size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \ 230 size_t num_skip_samples = in_buff_chans - 2; \ 231 typeof(out_buff) dst_ptr = out_buff; \ 232 typeof(in_buff) src_ptr = in_buff; \ 233 int32_t temp; \ 234 size_t src_index; \ 235 for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \ 236 temp = uint8x3_to_int32(*src_ptr++); \ 237 temp += uint8x3_to_int32(*src_ptr++); \ 238 *dst_ptr = int32_to_uint8x3(temp >> 1); \ 239 src_ptr += num_skip_samples; \ 240 } \ 241 /* return number of *bytes* generated */ \ 242 return num_out_samples * sizeof(*(out_buff)); \ 243 } 244 245 /* 246 * Convert a buffer of N-channel, interleaved samples to M-channel 247 * (where N > M). 248 * in_buff points to the buffer of samples 249 * in_buff_channels Specifies the number of channels in the input buffer. 250 * out_buff points to the buffer to receive converted samples. 251 * out_buff_channels Specifies the number of channels in the output buffer. 252 * sample_size_in_bytes Specifies the number of bytes per sample. 253 * num_in_bytes size of input buffer in BYTES 254 * returns 255 * the number of BYTES of output data. 256 * NOTE 257 * channels > M are thrown away. 258 * The out and sums buffers must either be completely separate (non-overlapping), or 259 * they must both start at the same address. Partially overlapping buffers are not supported. 260 */ 261 static size_t contract_channels(const void* in_buff, size_t in_buff_chans, 262 void* out_buff, size_t out_buff_chans, 263 unsigned sample_size_in_bytes, size_t num_in_bytes) 264 { 265 switch (sample_size_in_bytes) { 266 case 1: 267 if (out_buff_chans == 1) { 268 /* Special case Multi to Mono */ 269 CONTRACT_TO_MONO((const uint8_t*)in_buff, (uint8_t*)out_buff, num_in_bytes); 270 // returns in macro 271 } else { 272 CONTRACT_CHANNELS((const uint8_t*)in_buff, in_buff_chans, 273 (uint8_t*)out_buff, out_buff_chans, 274 num_in_bytes); 275 // returns in macro 276 } 277 case 2: 278 if (out_buff_chans == 1) { 279 /* Special case Multi to Mono */ 280 CONTRACT_TO_MONO((const int16_t*)in_buff, (int16_t*)out_buff, num_in_bytes); 281 // returns in macro 282 } else { 283 CONTRACT_CHANNELS((const int16_t*)in_buff, in_buff_chans, 284 (int16_t*)out_buff, out_buff_chans, 285 num_in_bytes); 286 // returns in macro 287 } 288 case 3: 289 if (out_buff_chans == 1) { 290 /* Special case Multi to Mono */ 291 CONTRACT_TO_MONO_24((const uint8x3_t*)in_buff, 292 (uint8x3_t*)out_buff, num_in_bytes); 293 // returns in macro 294 } else { 295 CONTRACT_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans, 296 (uint8x3_t*)out_buff, out_buff_chans, 297 num_in_bytes); 298 // returns in macro 299 } 300 case 4: 301 if (out_buff_chans == 1) { 302 /* Special case Multi to Mono */ 303 CONTRACT_TO_MONO((const int32_t*)in_buff, (int32_t*)out_buff, num_in_bytes); 304 // returns in macro 305 } else { 306 CONTRACT_CHANNELS((const int32_t*)in_buff, in_buff_chans, 307 (int32_t*)out_buff, out_buff_chans, 308 num_in_bytes); 309 // returns in macro 310 } 311 default: 312 return 0; 313 } 314 } 315 316 /* 317 * Convert a buffer of N-channel, interleaved samples to M-channel 318 * (where N < M). 319 * in_buff points to the buffer of samples 320 * in_buff_channels Specifies the number of channels in the input buffer. 321 * out_buff points to the buffer to receive converted samples. 322 * out_buff_channels Specifies the number of channels in the output buffer. 323 * sample_size_in_bytes Specifies the number of bytes per sample. 324 * num_in_bytes size of input buffer in BYTES 325 * returns 326 * the number of BYTES of output data. 327 * NOTE 328 * channels > N are filled with silence. 329 * The out and sums buffers must either be completely separate (non-overlapping), or 330 * they must both start at the same address. Partially overlapping buffers are not supported. 331 */ 332 static size_t expand_channels(const void* in_buff, size_t in_buff_chans, 333 void* out_buff, size_t out_buff_chans, 334 unsigned sample_size_in_bytes, size_t num_in_bytes) 335 { 336 static const uint8x3_t packed24_zero; /* zero 24 bit sample */ 337 338 switch (sample_size_in_bytes) { 339 case 1: 340 if (in_buff_chans == 1) { 341 /* special case of mono source to multi-channel */ 342 EXPAND_MONO_TO_MULTI((const uint8_t*)in_buff, in_buff_chans, 343 (uint8_t*)out_buff, out_buff_chans, 344 num_in_bytes, 0); 345 // returns in macro 346 } else { 347 EXPAND_CHANNELS((const uint8_t*)in_buff, in_buff_chans, 348 (uint8_t*)out_buff, out_buff_chans, 349 num_in_bytes, 0); 350 // returns in macro 351 } 352 case 2: 353 if (in_buff_chans == 1) { 354 /* special case of mono source to multi-channel */ 355 EXPAND_MONO_TO_MULTI((const int16_t*)in_buff, in_buff_chans, 356 (int16_t*)out_buff, out_buff_chans, 357 num_in_bytes, 0); 358 // returns in macro 359 } else { 360 EXPAND_CHANNELS((const int16_t*)in_buff, in_buff_chans, 361 (int16_t*)out_buff, out_buff_chans, 362 num_in_bytes, 0); 363 // returns in macro 364 } 365 case 3: 366 if (in_buff_chans == 1) { 367 /* special case of mono source to multi-channel */ 368 EXPAND_MONO_TO_MULTI((const uint8x3_t*)in_buff, in_buff_chans, 369 (uint8x3_t*)out_buff, out_buff_chans, 370 num_in_bytes, packed24_zero); 371 // returns in macro 372 } else { 373 EXPAND_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans, 374 (uint8x3_t*)out_buff, out_buff_chans, 375 num_in_bytes, packed24_zero); 376 // returns in macro 377 } 378 case 4: 379 if (in_buff_chans == 1) { 380 /* special case of mono source to multi-channel */ 381 EXPAND_MONO_TO_MULTI((const int32_t*)in_buff, in_buff_chans, 382 (int32_t*)out_buff, out_buff_chans, 383 num_in_bytes, 0); 384 // returns in macro 385 } else { 386 EXPAND_CHANNELS((const int32_t*)in_buff, in_buff_chans, 387 (int32_t*)out_buff, out_buff_chans, 388 num_in_bytes, 0); 389 // returns in macro 390 } 391 default: 392 return 0; 393 } 394 } 395 396 size_t adjust_channels(const void* in_buff, size_t in_buff_chans, 397 void* out_buff, size_t out_buff_chans, 398 unsigned sample_size_in_bytes, size_t num_in_bytes) 399 { 400 if (out_buff_chans > in_buff_chans) { 401 return expand_channels(in_buff, in_buff_chans, out_buff, out_buff_chans, 402 sample_size_in_bytes, num_in_bytes); 403 } else if (out_buff_chans < in_buff_chans) { 404 return contract_channels(in_buff, in_buff_chans, out_buff, out_buff_chans, 405 sample_size_in_bytes, num_in_bytes); 406 } else if (in_buff != out_buff) { 407 memcpy(out_buff, in_buff, num_in_bytes); 408 } 409 410 return num_in_bytes; 411 } 412 413 /* 414 * Convert a buffer of N-channel, interleaved samples to M-channel 415 * (where N < M). 416 * in_buff points to the buffer of samples 417 * in_buff_channels Specifies the number of channels in the input buffer. 418 * out_buff points to the buffer to receive converted samples. 419 * out_buff_channels Specifies the number of channels in the output buffer. 420 * sample_size_in_bytes Specifies the number of bytes per sample. 421 * num_in_bytes size of input buffer in BYTES 422 * returns 423 * the number of BYTES of output data. 424 * NOTE 425 * channels > N are left alone in out_buff. 426 * The out and in buffers must either be completely separate (non-overlapping), or 427 * they must both start at the same address. Partially overlapping buffers are not supported. 428 */ 429 static size_t expand_selected_channels(const void* in_buff, size_t in_buff_chans, 430 void* out_buff, size_t out_buff_chans, 431 unsigned sample_size_in_bytes, size_t num_in_bytes) 432 { 433 switch (sample_size_in_bytes) { 434 case 1: 435 436 EXPAND_SELECTED_CHANNELS((const uint8_t*)in_buff, in_buff_chans, 437 (uint8_t*)out_buff, out_buff_chans, 438 num_in_bytes); 439 // returns in macro 440 441 case 2: 442 443 EXPAND_SELECTED_CHANNELS((const int16_t*)in_buff, in_buff_chans, 444 (int16_t*)out_buff, out_buff_chans, 445 num_in_bytes); 446 // returns in macro 447 448 case 3: 449 450 EXPAND_SELECTED_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans, 451 (uint8x3_t*)out_buff, out_buff_chans, 452 num_in_bytes); 453 // returns in macro 454 455 case 4: 456 457 EXPAND_SELECTED_CHANNELS((const int32_t*)in_buff, in_buff_chans, 458 (int32_t*)out_buff, out_buff_chans, 459 num_in_bytes); 460 // returns in macro 461 462 default: 463 return 0; 464 } 465 } 466 467 size_t adjust_selected_channels(const void* in_buff, size_t in_buff_chans, 468 void* out_buff, size_t out_buff_chans, 469 unsigned sample_size_in_bytes, size_t num_in_bytes) 470 { 471 if (out_buff_chans > in_buff_chans) { 472 return expand_selected_channels(in_buff, in_buff_chans, out_buff, out_buff_chans, 473 sample_size_in_bytes, num_in_bytes); 474 } else if (out_buff_chans < in_buff_chans) { 475 return contract_channels(in_buff, in_buff_chans, out_buff, out_buff_chans, 476 sample_size_in_bytes, num_in_bytes); 477 } else if (in_buff != out_buff) { 478 memcpy(out_buff, in_buff, num_in_bytes); 479 } 480 481 return num_in_bytes; 482 } 483 484