Home | History | Annotate | Download | only in a2dp
      1 /******************************************************************************
      2  *
      3  *  Copyright 2004-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  This module contains utility functions for dealing with SBC data frames
     22  *  and codec capabilities.
     23  *
     24  ******************************************************************************/
     25 
     26 #include "a2dp_sbc_up_sample.h"
     27 
     28 typedef int(tA2DP_SBC_ACT)(void* p_src, void* p_dst, uint32_t src_samples,
     29                            uint32_t dst_samples, uint32_t* p_ret);
     30 
     31 typedef struct {
     32   int32_t cur_pos;      /* current position */
     33   uint32_t src_sps;     /* samples per second (source audio data) */
     34   uint32_t dst_sps;     /* samples per second (converted audio data) */
     35   tA2DP_SBC_ACT* p_act; /* the action function to do the conversion */
     36   uint8_t bits;         /* number of bits per pcm sample */
     37   uint8_t n_channels;   /* number of channels (i.e. mono(1), stereo(2)...) */
     38   int16_t worker1;
     39   int16_t worker2;
     40   uint8_t div;
     41 } tA2DP_SBC_UPS_CB;
     42 
     43 tA2DP_SBC_UPS_CB a2dp_sbc_ups_cb;
     44 
     45 /*******************************************************************************
     46  *
     47  * Function         a2dp_sbc_init_up_sample
     48  *
     49  * Description      initialize the up sample
     50  *
     51  *                  src_sps: samples per second (source audio data)
     52  *                  dst_sps: samples per second (converted audio data)
     53  *                  bits: number of bits per pcm sample
     54  *                  n_channels: number of channels (i.e. mono(1), stereo(2)...)
     55  *
     56  * Returns          none
     57  *
     58  ******************************************************************************/
     59 void a2dp_sbc_init_up_sample(uint32_t src_sps, uint32_t dst_sps, uint8_t bits,
     60                              uint8_t n_channels) {
     61   a2dp_sbc_ups_cb.cur_pos = -1;
     62   a2dp_sbc_ups_cb.src_sps = src_sps;
     63   a2dp_sbc_ups_cb.dst_sps = dst_sps;
     64   a2dp_sbc_ups_cb.bits = bits;
     65   a2dp_sbc_ups_cb.n_channels = n_channels;
     66 
     67   if (n_channels == 1) {
     68     /* mono */
     69     if (bits == 8) {
     70       a2dp_sbc_ups_cb.p_act = a2dp_sbc_up_sample_8m;
     71       a2dp_sbc_ups_cb.div = 1;
     72     } else {
     73       a2dp_sbc_ups_cb.p_act = a2dp_sbc_up_sample_16m;
     74       a2dp_sbc_ups_cb.div = 2;
     75     }
     76   } else {
     77     /* stereo */
     78     if (bits == 8) {
     79       a2dp_sbc_ups_cb.p_act = a2dp_sbc_up_sample_8s;
     80       a2dp_sbc_ups_cb.div = 2;
     81     } else {
     82       a2dp_sbc_ups_cb.p_act = a2dp_sbc_up_sample_16s;
     83       a2dp_sbc_ups_cb.div = 4;
     84     }
     85   }
     86 }
     87 
     88 /*******************************************************************************
     89  *
     90  * Function         a2dp_sbc_up_sample
     91  *
     92  * Description      Given the source (p_src) audio data and
     93  *                  source speed (src_sps, samples per second),
     94  *                  This function converts it to audio data in the desired
     95  *                  format
     96  *
     97  *                  p_src: the data buffer that holds the source audio data
     98  *                  p_dst: the data buffer to hold the converted audio data
     99  *                  src_samples: The number of source samples (number of bytes)
    100  *                  dst_samples: The size of p_dst (number of bytes)
    101  *
    102  * Note:            An AE reported an issue with this function.
    103  *                  When called with a2dp_sbc_up_sample(src, uint8_array_dst..)
    104  *                  the byte before uint8_array_dst may get overwritten.
    105  *                  Using uint16_array_dst avoids the problem.
    106  *                  This issue is related to endian-ness and is hard to resolve
    107  *                  in a generic manner.
    108  * **************** Please use uint16 array as dst.
    109  *
    110  * Returns          The number of bytes used in p_dst
    111  *                  The number of bytes used in p_src (in *p_ret)
    112  *
    113  ******************************************************************************/
    114 int a2dp_sbc_up_sample(void* p_src, void* p_dst, uint32_t src_samples,
    115                        uint32_t dst_samples, uint32_t* p_ret) {
    116   uint32_t src;
    117   uint32_t dst;
    118 
    119   if (a2dp_sbc_ups_cb.p_act) {
    120     src = src_samples / a2dp_sbc_ups_cb.div;
    121     dst = dst_samples / a2dp_sbc_ups_cb.div;
    122     return (*a2dp_sbc_ups_cb.p_act)(p_src, p_dst, src, dst, p_ret);
    123   } else {
    124     *p_ret = 0;
    125     return 0;
    126   }
    127 }
    128 
    129 /*******************************************************************************
    130  *
    131  * Function         a2dp_sbc_up_sample_16s (16bits-stereo)
    132  *
    133  * Description      Given the source (p_src) audio data and
    134  *                  source speed (src_sps, samples per second),
    135  *                  This function converts it to audio data in the desired
    136  *                  format
    137  *
    138  *                  p_src: the data buffer that holds the source audio data
    139  *                  p_dst: the data buffer to hold the converted audio data
    140  *                  src_samples: The number of source samples (in uint of 4
    141  *                               bytes)
    142  *                  dst_samples: The size of p_dst (in uint of 4 bytes)
    143  *
    144  * Returns          The number of bytes used in p_dst
    145  *                  The number of bytes used in p_src (in *p_ret)
    146  *
    147  ******************************************************************************/
    148 int a2dp_sbc_up_sample_16s(void* p_src, void* p_dst, uint32_t src_samples,
    149                            uint32_t dst_samples, uint32_t* p_ret) {
    150   int16_t* p_src_tmp = (int16_t*)p_src;
    151   int16_t* p_dst_tmp = (int16_t*)p_dst;
    152   int16_t* p_worker1 = &a2dp_sbc_ups_cb.worker1;
    153   int16_t* p_worker2 = &a2dp_sbc_ups_cb.worker2;
    154   uint32_t src_sps = a2dp_sbc_ups_cb.src_sps;
    155   uint32_t dst_sps = a2dp_sbc_ups_cb.dst_sps;
    156 
    157   while (a2dp_sbc_ups_cb.cur_pos > 0 && dst_samples) {
    158     *p_dst_tmp++ = *p_worker1;
    159     *p_dst_tmp++ = *p_worker2;
    160 
    161     a2dp_sbc_ups_cb.cur_pos -= src_sps;
    162     dst_samples--;
    163   }
    164 
    165   a2dp_sbc_ups_cb.cur_pos = dst_sps;
    166 
    167   while (src_samples-- && dst_samples) {
    168     *p_worker1 = *p_src_tmp++;
    169     *p_worker2 = *p_src_tmp++;
    170 
    171     do {
    172       *p_dst_tmp++ = *p_worker1;
    173       *p_dst_tmp++ = *p_worker2;
    174 
    175       a2dp_sbc_ups_cb.cur_pos -= src_sps;
    176       dst_samples--;
    177     } while (a2dp_sbc_ups_cb.cur_pos > 0 && dst_samples);
    178 
    179     a2dp_sbc_ups_cb.cur_pos += dst_sps;
    180   }
    181 
    182   if (a2dp_sbc_ups_cb.cur_pos == (int32_t)dst_sps) a2dp_sbc_ups_cb.cur_pos = 0;
    183 
    184   *p_ret = ((char*)p_src_tmp - (char*)p_src);
    185   return ((char*)p_dst_tmp - (char*)p_dst);
    186 }
    187 
    188 /*******************************************************************************
    189  *
    190  * Function         a2dp_sbc_up_sample_16m (16bits-mono)
    191  *
    192  * Description      Given the source (p_src) audio data and
    193  *                  source speed (src_sps, samples per second),
    194  *                  This function converts it to audio data in the desired
    195  *                  format
    196  *
    197  *                  p_src: the data buffer that holds the source audio data
    198  *                  p_dst: the data buffer to hold the converted audio data
    199  *                  src_samples: The number of source samples (in uint of 2
    200  *                               bytes)
    201  *                  dst_samples: The size of p_dst (in uint of 2 bytes)
    202  *
    203  * Returns          The number of bytes used in p_dst
    204  *                  The number of bytes used in p_src (in *p_ret)
    205  *
    206  ******************************************************************************/
    207 int a2dp_sbc_up_sample_16m(void* p_src, void* p_dst, uint32_t src_samples,
    208                            uint32_t dst_samples, uint32_t* p_ret) {
    209   int16_t* p_src_tmp = (int16_t*)p_src;
    210   int16_t* p_dst_tmp = (int16_t*)p_dst;
    211   int16_t* p_worker = &a2dp_sbc_ups_cb.worker1;
    212   uint32_t src_sps = a2dp_sbc_ups_cb.src_sps;
    213   uint32_t dst_sps = a2dp_sbc_ups_cb.dst_sps;
    214 
    215   while (a2dp_sbc_ups_cb.cur_pos > 0 && dst_samples) {
    216     *p_dst_tmp++ = *p_worker;
    217     *p_dst_tmp++ = *p_worker;
    218 
    219     a2dp_sbc_ups_cb.cur_pos -= src_sps;
    220     dst_samples--;
    221     dst_samples--;
    222   }
    223 
    224   a2dp_sbc_ups_cb.cur_pos = dst_sps;
    225 
    226   while (src_samples-- && dst_samples) {
    227     *p_worker = *p_src_tmp++;
    228 
    229     do {
    230       *p_dst_tmp++ = *p_worker;
    231       *p_dst_tmp++ = *p_worker;
    232 
    233       a2dp_sbc_ups_cb.cur_pos -= src_sps;
    234       dst_samples--;
    235       dst_samples--;
    236 
    237     } while (a2dp_sbc_ups_cb.cur_pos > 0 && dst_samples);
    238 
    239     a2dp_sbc_ups_cb.cur_pos += dst_sps;
    240   }
    241 
    242   if (a2dp_sbc_ups_cb.cur_pos == (int32_t)dst_sps) a2dp_sbc_ups_cb.cur_pos = 0;
    243 
    244   *p_ret = ((char*)p_src_tmp - (char*)p_src);
    245   return ((char*)p_dst_tmp - (char*)p_dst);
    246 }
    247 
    248 /*******************************************************************************
    249  *
    250  * Function         a2dp_sbc_up_sample_8s (8bits-stereo)
    251  *
    252  * Description      Given the source (p_src) audio data and
    253  *                  source speed (src_sps, samples per second),
    254  *                  This function converts it to audio data in the desired
    255  *                  format
    256  *
    257  *                  p_src: the data buffer that holds the source audio data
    258  *                  p_dst: the data buffer to hold the converted audio data
    259  *                  src_samples: The number of source samples (in uint of 2
    260  *                               bytes)
    261  *                  dst_samples: The size of p_dst (in uint of 2 bytes)
    262  *
    263  * Returns          The number of bytes used in p_dst
    264  *                  The number of bytes used in p_src (in *p_ret)
    265  *
    266  ******************************************************************************/
    267 int a2dp_sbc_up_sample_8s(void* p_src, void* p_dst, uint32_t src_samples,
    268                           uint32_t dst_samples, uint32_t* p_ret) {
    269   uint8_t* p_src_tmp = (uint8_t*)p_src;
    270   int16_t* p_dst_tmp = (int16_t*)p_dst;
    271   int16_t* p_worker1 = &a2dp_sbc_ups_cb.worker1;
    272   int16_t* p_worker2 = &a2dp_sbc_ups_cb.worker2;
    273   uint32_t src_sps = a2dp_sbc_ups_cb.src_sps;
    274   uint32_t dst_sps = a2dp_sbc_ups_cb.dst_sps;
    275 
    276   while (a2dp_sbc_ups_cb.cur_pos > 0 && dst_samples) {
    277     *p_dst_tmp++ = *p_worker1;
    278     *p_dst_tmp++ = *p_worker2;
    279 
    280     a2dp_sbc_ups_cb.cur_pos -= src_sps;
    281     dst_samples--;
    282     dst_samples--;
    283   }
    284 
    285   a2dp_sbc_ups_cb.cur_pos = dst_sps;
    286 
    287   while (src_samples-- && dst_samples) {
    288     *p_worker1 = *(uint8_t*)p_src_tmp++;
    289     *p_worker1 -= 0x80;
    290     *p_worker1 <<= 8;
    291     *p_worker2 = *(uint8_t*)p_src_tmp++;
    292     *p_worker2 -= 0x80;
    293     *p_worker2 <<= 8;
    294 
    295     do {
    296       *p_dst_tmp++ = *p_worker1;
    297       *p_dst_tmp++ = *p_worker2;
    298 
    299       a2dp_sbc_ups_cb.cur_pos -= src_sps;
    300       dst_samples--;
    301       dst_samples--;
    302     } while (a2dp_sbc_ups_cb.cur_pos > 0 && dst_samples);
    303 
    304     a2dp_sbc_ups_cb.cur_pos += dst_sps;
    305   }
    306 
    307   if (a2dp_sbc_ups_cb.cur_pos == (int32_t)dst_sps) a2dp_sbc_ups_cb.cur_pos = 0;
    308 
    309   *p_ret = ((char*)p_src_tmp - (char*)p_src);
    310   return ((char*)p_dst_tmp - (char*)p_dst);
    311 }
    312 
    313 /*******************************************************************************
    314  *
    315  * Function         a2dp_sbc_up_sample_8m (8bits-mono)
    316  *
    317  * Description      Given the source (p_src) audio data and
    318  *                  source speed (src_sps, samples per second),
    319  *                  This function converts it to audio data in the desired
    320  *                  format
    321  *
    322  *                  p_src: the data buffer that holds the source audio data
    323  *                  p_dst: the data buffer to hold the converted audio data
    324  *                  src_samples: The number of source samples (number of bytes)
    325  *                  dst_samples: The size of p_dst (number of bytes)
    326  *
    327  * Returns          The number of bytes used in p_dst
    328  *                  The number of bytes used in p_src (in *p_ret)
    329  *
    330  ******************************************************************************/
    331 int a2dp_sbc_up_sample_8m(void* p_src, void* p_dst, uint32_t src_samples,
    332                           uint32_t dst_samples, uint32_t* p_ret) {
    333   uint8_t* p_src_tmp = (uint8_t*)p_src;
    334   int16_t* p_dst_tmp = (int16_t*)p_dst;
    335   int16_t* p_worker = &a2dp_sbc_ups_cb.worker1;
    336   uint32_t src_sps = a2dp_sbc_ups_cb.src_sps;
    337   uint32_t dst_sps = a2dp_sbc_ups_cb.dst_sps;
    338 
    339   while (a2dp_sbc_ups_cb.cur_pos > 0 && dst_samples) {
    340     *p_dst_tmp++ = *p_worker;
    341     *p_dst_tmp++ = *p_worker;
    342 
    343     a2dp_sbc_ups_cb.cur_pos -= src_sps;
    344     dst_samples -= 4;
    345   }
    346 
    347   a2dp_sbc_ups_cb.cur_pos = dst_sps;
    348 
    349   while (src_samples-- && dst_samples) {
    350     *p_worker = *(uint8_t*)p_src_tmp++;
    351     *p_worker -= 0x80;
    352     *p_worker <<= 8;
    353 
    354     do {
    355       *p_dst_tmp++ = *p_worker;
    356       *p_dst_tmp++ = *p_worker;
    357 
    358       a2dp_sbc_ups_cb.cur_pos -= src_sps;
    359       dst_samples -= 4;
    360 
    361     } while (a2dp_sbc_ups_cb.cur_pos > 0 && dst_samples);
    362 
    363     a2dp_sbc_ups_cb.cur_pos += dst_sps;
    364   }
    365 
    366   if (a2dp_sbc_ups_cb.cur_pos == (int32_t)dst_sps) a2dp_sbc_ups_cb.cur_pos = 0;
    367 
    368   *p_ret = ((char*)p_src_tmp - (char*)p_src);
    369   return ((char*)p_dst_tmp - (char*)p_dst);
    370 }
    371