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