1 /* 2 * Copyright (C) 2011 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 <cutils/bitops.h> /* for popcount() */ 18 #include <audio_utils/primitives.h> 19 #include "private/private.h" 20 21 void ditherAndClamp(int32_t* out, const int32_t *sums, size_t c) 22 { 23 size_t i; 24 for (i=0 ; i<c ; i++) { 25 int32_t l = *sums++; 26 int32_t r = *sums++; 27 int32_t nl = l >> 12; 28 int32_t nr = r >> 12; 29 l = clamp16(nl); 30 r = clamp16(nr); 31 *out++ = (r<<16) | (l & 0xFFFF); 32 } 33 } 34 35 void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count) 36 { 37 dst += count; 38 src += count; 39 while (count--) { 40 *--dst = (int16_t)(*--src - 0x80) << 8; 41 } 42 } 43 44 void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count) 45 { 46 while (count--) { 47 *dst++ = (*src++ >> 8) + 0x80; 48 } 49 } 50 51 void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count) 52 { 53 while (count--) { 54 *dst++ = *src++ >> 16; 55 } 56 } 57 58 void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count) 59 { 60 while (count--) { 61 *dst++ = clamp16_from_float(*src++); 62 } 63 } 64 65 void memcpy_to_float_from_q4_27(float *dst, const int32_t *src, size_t count) 66 { 67 while (count--) { 68 *dst++ = float_from_q4_27(*src++); 69 } 70 } 71 72 void memcpy_to_float_from_i16(float *dst, const int16_t *src, size_t count) 73 { 74 while (count--) { 75 *dst++ = float_from_i16(*src++); 76 } 77 } 78 79 void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count) 80 { 81 while (count--) { 82 *dst++ = float_from_p24(src); 83 src += 3; 84 } 85 } 86 87 void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count) 88 { 89 while (count--) { 90 #ifdef HAVE_BIG_ENDIAN 91 *dst++ = src[1] | (src[0] << 8); 92 #else 93 *dst++ = src[1] | (src[2] << 8); 94 #endif 95 src += 3; 96 } 97 } 98 99 void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count) 100 { 101 while (count--) { 102 #ifdef HAVE_BIG_ENDIAN 103 *dst++ = *src >> 8; 104 *dst++ = *src++; 105 *dst++ = 0; 106 #else 107 *dst++ = 0; 108 *dst++ = *src; 109 *dst++ = *src++ >> 8; 110 #endif 111 } 112 } 113 114 void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count) 115 { 116 while (count--) { 117 int32_t ival = clamp24_from_float(*src++); 118 119 #ifdef HAVE_BIG_ENDIAN 120 *dst++ = ival >> 16; 121 *dst++ = ival >> 8; 122 *dst++ = ival; 123 #else 124 *dst++ = ival; 125 *dst++ = ival >> 8; 126 *dst++ = ival >> 16; 127 #endif 128 } 129 } 130 131 void memcpy_to_p24_from_q8_23(uint8_t *dst, const int32_t *src, size_t count) 132 { 133 while (count--) { 134 int32_t ival = clamp24_from_q8_23(*src++); 135 136 #ifdef HAVE_BIG_ENDIAN 137 *dst++ = ival >> 16; 138 *dst++ = ival >> 8; 139 *dst++ = ival; 140 #else 141 *dst++ = ival; 142 *dst++ = ival >> 8; 143 *dst++ = ival >> 16; 144 #endif 145 } 146 } 147 148 void memcpy_to_q8_23_from_i16(int32_t *dst, const int16_t *src, size_t count) 149 { 150 while (count--) { 151 *dst++ = (int32_t)*src++ << 8; 152 } 153 } 154 155 void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_t count) 156 { 157 while (count--) { 158 *dst++ = clamp24_from_float(*src++); 159 } 160 } 161 162 void memcpy_to_q4_27_from_float(int32_t *dst, const float *src, size_t count) 163 { 164 while (count--) { 165 *dst++ = clampq4_27_from_float(*src++); 166 } 167 } 168 169 void memcpy_to_i16_from_q8_23(int16_t *dst, const int32_t *src, size_t count) 170 { 171 while (count--) { 172 *dst++ = clamp16(*src++ >> 8); 173 } 174 } 175 176 void memcpy_to_float_from_q8_23(float *dst, const int32_t *src, size_t count) 177 { 178 while (count--) { 179 *dst++ = float_from_q8_23(*src++); 180 } 181 } 182 183 void memcpy_to_i32_from_i16(int32_t *dst, const int16_t *src, size_t count) 184 { 185 while (count--) { 186 *dst++ = (int32_t)*src++ << 16; 187 } 188 } 189 190 void memcpy_to_i32_from_float(int32_t *dst, const float *src, size_t count) 191 { 192 while (count--) { 193 *dst++ = clamp32_from_float(*src++); 194 } 195 } 196 197 void memcpy_to_float_from_i32(float *dst, const int32_t *src, size_t count) 198 { 199 while (count--) { 200 *dst++ = float_from_i32(*src++); 201 } 202 } 203 204 void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count) 205 { 206 while (count--) { 207 *dst++ = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1); 208 src += 2; 209 } 210 } 211 212 void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count) 213 { 214 while (count--) { 215 int32_t temp = *src++; 216 dst[0] = temp; 217 dst[1] = temp; 218 dst += 2; 219 } 220 } 221 222 size_t nonZeroMono32(const int32_t *samples, size_t count) 223 { 224 size_t nonZero = 0; 225 while (count-- > 0) { 226 if (*samples++ != 0) { 227 nonZero++; 228 } 229 } 230 return nonZero; 231 } 232 233 size_t nonZeroMono16(const int16_t *samples, size_t count) 234 { 235 size_t nonZero = 0; 236 while (count-- > 0) { 237 if (*samples++ != 0) { 238 nonZero++; 239 } 240 } 241 return nonZero; 242 } 243 244 size_t nonZeroStereo32(const int32_t *frames, size_t count) 245 { 246 size_t nonZero = 0; 247 while (count-- > 0) { 248 if (frames[0] != 0 || frames[1] != 0) { 249 nonZero++; 250 } 251 frames += 2; 252 } 253 return nonZero; 254 } 255 256 size_t nonZeroStereo16(const int16_t *frames, size_t count) 257 { 258 size_t nonZero = 0; 259 while (count-- > 0) { 260 if (frames[0] != 0 || frames[1] != 0) { 261 nonZero++; 262 } 263 frames += 2; 264 } 265 return nonZero; 266 } 267 268 /* 269 * C macro to do channel mask copying independent of dst/src sample type. 270 * Don't pass in any expressions for the macro arguments here. 271 */ 272 #define copy_frame_by_mask(dst, dmask, src, smask, count, zero) \ 273 { \ 274 uint32_t bit, ormask; \ 275 while (count--) { \ 276 ormask = dmask | smask; \ 277 while (ormask) { \ 278 bit = ormask & -ormask; /* get lowest bit */ \ 279 ormask ^= bit; /* remove lowest bit */ \ 280 if (dmask & bit) { \ 281 *dst++ = smask & bit ? *src++ : zero; \ 282 } else { /* source channel only */ \ 283 ++src; \ 284 } \ 285 } \ 286 } \ 287 } 288 289 void memcpy_by_channel_mask(void *dst, uint32_t dst_mask, 290 const void *src, uint32_t src_mask, size_t sample_size, size_t count) 291 { 292 #if 0 293 /* alternate way of handling memcpy_by_channel_mask by using the idxary */ 294 int8_t idxary[32]; 295 uint32_t src_channels = popcount(src_mask); 296 uint32_t dst_channels = 297 memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask); 298 299 memcpy_by_idxary(dst, dst_channels, src, src_channels, idxary, sample_size, count); 300 #else 301 if (dst_mask == src_mask) { 302 memcpy(dst, src, sample_size * popcount(dst_mask) * count); 303 return; 304 } 305 switch (sample_size) { 306 case 1: { 307 uint8_t *udst = (uint8_t*)dst; 308 const uint8_t *usrc = (const uint8_t*)src; 309 310 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0); 311 } break; 312 case 2: { 313 uint16_t *udst = (uint16_t*)dst; 314 const uint16_t *usrc = (const uint16_t*)src; 315 316 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0); 317 } break; 318 case 3: { /* could be slow. use a struct to represent 3 bytes of data. */ 319 uint8x3_t *udst = (uint8x3_t*)dst; 320 const uint8x3_t *usrc = (const uint8x3_t*)src; 321 static const uint8x3_t zero; /* tricky - we use this to zero out a sample */ 322 323 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, zero); 324 } break; 325 case 4: { 326 uint32_t *udst = (uint32_t*)dst; 327 const uint32_t *usrc = (const uint32_t*)src; 328 329 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0); 330 } break; 331 default: 332 abort(); /* illegal value */ 333 break; 334 } 335 #endif 336 } 337 338 /* 339 * C macro to do copying by index array, to rearrange samples 340 * within a frame. This is independent of src/dst sample type. 341 * Don't pass in any expressions for the macro arguments here. 342 */ 343 #define copy_frame_by_idx(dst, dst_channels, src, src_channels, idxary, count, zero) \ 344 { \ 345 unsigned i; \ 346 int index; \ 347 while (count--) { \ 348 for (i = 0; i < dst_channels; ++i) { \ 349 index = idxary[i]; \ 350 *dst++ = index < 0 ? zero : src[index]; \ 351 } \ 352 src += src_channels; \ 353 } \ 354 } 355 356 void memcpy_by_index_array(void *dst, uint32_t dst_channels, 357 const void *src, uint32_t src_channels, 358 const int8_t *idxary, size_t sample_size, size_t count) 359 { 360 switch (sample_size) { 361 case 1: { 362 uint8_t *udst = (uint8_t*)dst; 363 const uint8_t *usrc = (const uint8_t*)src; 364 365 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0); 366 } break; 367 case 2: { 368 uint16_t *udst = (uint16_t*)dst; 369 const uint16_t *usrc = (const uint16_t*)src; 370 371 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0); 372 } break; 373 case 3: { /* could be slow. use a struct to represent 3 bytes of data. */ 374 uint8x3_t *udst = (uint8x3_t*)dst; 375 const uint8x3_t *usrc = (const uint8x3_t*)src; 376 static const uint8x3_t zero; 377 378 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, zero); 379 } break; 380 case 4: { 381 uint32_t *udst = (uint32_t*)dst; 382 const uint32_t *usrc = (const uint32_t*)src; 383 384 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0); 385 } break; 386 default: 387 abort(); /* illegal value */ 388 break; 389 } 390 } 391 392 size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount, 393 uint32_t dst_mask, uint32_t src_mask) 394 { 395 size_t n = 0; 396 int srcidx = 0; 397 uint32_t bit, ormask = src_mask | dst_mask; 398 399 while (ormask && n < idxcount) { 400 bit = ormask & -ormask; /* get lowest bit */ 401 ormask ^= bit; /* remove lowest bit */ 402 if (src_mask & dst_mask & bit) { /* matching channel */ 403 idxary[n++] = srcidx++; 404 } else if (src_mask & bit) { /* source channel only */ 405 ++srcidx; 406 } else { /* destination channel only */ 407 idxary[n++] = -1; 408 } 409 } 410 return n + popcount(ormask & dst_mask); 411 } 412