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