Home | History | Annotate | Download | only in audio_utils
      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