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