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 ******************************************************************************/
a2dp_sbc_init_up_sample(uint32_t src_sps,uint32_t dst_sps,uint8_t bits,uint8_t n_channels)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 ******************************************************************************/
a2dp_sbc_up_sample(void * p_src,void * p_dst,uint32_t src_samples,uint32_t dst_samples,uint32_t * p_ret)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 ******************************************************************************/
a2dp_sbc_up_sample_16s(void * p_src,void * p_dst,uint32_t src_samples,uint32_t dst_samples,uint32_t * p_ret)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 ******************************************************************************/
a2dp_sbc_up_sample_16m(void * p_src,void * p_dst,uint32_t src_samples,uint32_t dst_samples,uint32_t * p_ret)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 ******************************************************************************/
a2dp_sbc_up_sample_8s(void * p_src,void * p_dst,uint32_t src_samples,uint32_t dst_samples,uint32_t * p_ret)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 ******************************************************************************/
a2dp_sbc_up_sample_8m(void * p_src,void * p_dst,uint32_t src_samples,uint32_t dst_samples,uint32_t * p_ret)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