blob: 32c2a46ccd1f2c82486bf45b03f508e666bf43b5 [file] [log] [blame]
Glenn Kasten632e0c02011-12-16 10:42:58 -08001/*
2 * Copyright (C) 2011 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
Andy Hung3af2af22014-05-22 18:40:30 -070017#include <cutils/bitops.h> // for popcount()
Glenn Kasten632e0c02011-12-16 10:42:58 -080018#include <audio_utils/primitives.h>
19
Glenn Kasten7ef795a2013-07-17 07:25:05 -070020void ditherAndClamp(int32_t* out, const int32_t *sums, size_t c)
Glenn Kasten632e0c02011-12-16 10:42:58 -080021{
22 size_t i;
23 for (i=0 ; i<c ; i++) {
24 int32_t l = *sums++;
25 int32_t r = *sums++;
26 int32_t nl = l >> 12;
27 int32_t nr = r >> 12;
28 l = clamp16(nl);
29 r = clamp16(nr);
30 *out++ = (r<<16) | (l & 0xFFFF);
31 }
32}
Glenn Kastenddb2e932012-01-16 13:21:31 -080033
34void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count)
35{
36 dst += count;
37 src += count;
38 while (count--) {
39 *--dst = (int16_t)(*--src - 0x80) << 8;
40 }
41}
Glenn Kasten7a0baca2012-07-19 13:59:50 -070042
Glenn Kasten78da2ac2012-11-12 14:39:36 -080043void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count)
44{
45 while (count--) {
46 *dst++ = (*src++ >> 8) + 0x80;
47 }
48}
49
Glenn Kasten5d436052013-06-21 14:01:54 -070050void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count)
51{
52 while (count--) {
53 *dst++ = *src++ >> 16;
54 }
55}
56
57void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count)
58{
59 while (count--) {
Andy Hung65b5ccd2014-03-18 12:00:55 -070060 *dst++ = clamp16_from_float(*src++);
Glenn Kasten5d436052013-06-21 14:01:54 -070061 }
62}
63
Andy Hungb878e522014-04-04 13:05:43 -070064void memcpy_to_float_from_q4_27(float *dst, const int32_t *src, size_t count)
Andy Hungaecb15e2014-02-24 19:07:40 -080065{
Andy Hungb878e522014-04-04 13:05:43 -070066 while (count--) {
Andy Hungd2a25cd2014-04-02 11:23:56 -070067 *dst++ = float_from_q4_27(*src++);
Andy Hungaecb15e2014-02-24 19:07:40 -080068 }
69}
70
Andy Hunge0454e22014-03-06 13:04:56 -080071void memcpy_to_float_from_i16(float *dst, const int16_t *src, size_t count)
72{
73 while (count--) {
74 *dst++ = float_from_i16(*src++);
75 }
76}
77
78void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count)
79{
80 while (count--) {
81 *dst++ = float_from_p24(src);
82 src += 3;
83 }
84}
85
86void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count)
87{
88 while (count--) {
89#ifdef HAVE_BIG_ENDIAN
90 *dst++ = src[1] | (src[0] << 8);
91#else
92 *dst++ = src[1] | (src[2] << 8);
93#endif
94 src += 3;
95 }
96}
97
98void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count)
99{
100 while (count--) {
101#ifdef HAVE_BIG_ENDIAN
102 *dst++ = *src >> 8;
103 *dst++ = *src++;
104 *dst++ = 0;
105#else
106 *dst++ = 0;
107 *dst++ = *src;
108 *dst++ = *src++ >> 8;
109#endif
110 }
111}
112
113void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count)
114{
115 while (count--) {
116 int32_t ival = clamp24_from_float(*src++);
117
118#ifdef HAVE_BIG_ENDIAN
119 *dst++ = ival >> 16;
120 *dst++ = ival >> 8;
121 *dst++ = ival;
122#else
123 *dst++ = ival;
124 *dst++ = ival >> 8;
125 *dst++ = ival >> 16;
126#endif
127 }
128}
129
Glenn Kasteneee45152014-05-02 12:41:04 -0700130void memcpy_to_p24_from_q8_23(uint8_t *dst, const int32_t *src, size_t count)
131{
132 while (count--) {
133 int32_t ival = clamp24_from_q8_23(*src++);
134
135#ifdef HAVE_BIG_ENDIAN
136 *dst++ = ival >> 16;
137 *dst++ = ival >> 8;
138 *dst++ = ival;
139#else
140 *dst++ = ival;
141 *dst++ = ival >> 8;
142 *dst++ = ival >> 16;
143#endif
144 }
145}
146
Andy Hungd5829882014-03-12 11:46:15 -0700147void memcpy_to_q8_23_from_i16(int32_t *dst, const int16_t *src, size_t count)
148{
149 while (count--) {
150 *dst++ = (int32_t)*src++ << 8;
151 }
152}
153
154void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_t count)
155{
156 while (count--) {
157 *dst++ = clamp24_from_float(*src++);
158 }
159}
160
Andy Hungb878e522014-04-04 13:05:43 -0700161void memcpy_to_q4_27_from_float(int32_t *dst, const float *src, size_t count)
162{
163 while (count--) {
164 *dst++ = clampq4_27_from_float(*src++);
165 }
166}
167
Andy Hungd5829882014-03-12 11:46:15 -0700168void memcpy_to_i16_from_q8_23(int16_t *dst, const int32_t *src, size_t count)
169{
170 while (count--) {
171 *dst++ = clamp16(*src++ >> 8);
172 }
173}
174
175void memcpy_to_float_from_q8_23(float *dst, const int32_t *src, size_t count)
176{
177 while (count--) {
178 *dst++ = float_from_q8_23(*src++);
179 }
180}
181
Andy Hung2c63fb62014-03-12 14:44:12 -0700182void memcpy_to_i32_from_i16(int32_t *dst, const int16_t *src, size_t count)
183{
184 while (count--) {
185 *dst++ = (int32_t)*src++ << 16;
186 }
187}
188
189void memcpy_to_i32_from_float(int32_t *dst, const float *src, size_t count)
190{
191 while (count--) {
192 *dst++ = clamp32_from_float(*src++);
193 }
194}
195
196void memcpy_to_float_from_i32(float *dst, const int32_t *src, size_t count)
197{
198 while (count--) {
199 *dst++ = float_from_i32(*src++);
200 }
201}
202
Glenn Kasten7a0baca2012-07-19 13:59:50 -0700203void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count)
204{
205 while (count--) {
206 *dst++ = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
207 src += 2;
208 }
209}
210
211void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count)
212{
213 while (count--) {
214 int32_t temp = *src++;
215 dst[0] = temp;
216 dst[1] = temp;
217 dst += 2;
218 }
219}
Glenn Kasteneb247df2014-02-21 10:00:51 -0800220
221size_t nonZeroMono32(const int32_t *samples, size_t count)
222{
223 size_t nonZero = 0;
224 while (count-- > 0) {
225 if (*samples++ != 0) {
226 nonZero++;
227 }
228 }
229 return nonZero;
230}
231
232size_t nonZeroMono16(const int16_t *samples, size_t count)
233{
234 size_t nonZero = 0;
235 while (count-- > 0) {
236 if (*samples++ != 0) {
237 nonZero++;
238 }
239 }
240 return nonZero;
241}
242
243size_t nonZeroStereo32(const int32_t *frames, size_t count)
244{
245 size_t nonZero = 0;
246 while (count-- > 0) {
247 if (frames[0] != 0 || frames[1] != 0) {
248 nonZero++;
249 }
250 frames += 2;
251 }
252 return nonZero;
253}
254
255size_t nonZeroStereo16(const int16_t *frames, size_t count)
256{
257 size_t nonZero = 0;
258 while (count-- > 0) {
259 if (frames[0] != 0 || frames[1] != 0) {
260 nonZero++;
261 }
262 frames += 2;
263 }
264 return nonZero;
265}
Andy Hung3af2af22014-05-22 18:40:30 -0700266
267/* struct representation of 3 bytes for packed PCM 24 bit data */
268typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
269
270/*
271 * C macro to do channel mask copying independent of dst/src sample type.
272 * Don't pass in any expressions for the macro arguments here.
273 */
274#define copy_frame_by_mask(dst, dmask, src, smask, count, zero) \
275{ \
276 uint32_t bit, ormask; \
277 while (count--) { \
278 ormask = dmask | smask; \
279 while (ormask) { \
280 bit = ormask & -ormask; /* get lowest bit */ \
281 ormask ^= bit; /* remove lowest bit */ \
282 if (dmask & bit) { \
283 *dst++ = smask & bit ? *src++ : zero; \
284 } else { /* source channel only */ \
285 ++src; \
286 } \
287 } \
288 } \
289}
290
291void memcpy_by_channel_mask(void *dst, uint32_t dst_mask,
292 const void *src, uint32_t src_mask, size_t sample_size, size_t count)
293{
294#if 0
295 /* alternate way of handling memcpy_by_channel_mask by using the idxary */
296 int8_t idxary[32];
297 uint32_t src_channels = popcount(src_mask);
298 uint32_t dst_channels =
299 memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask);
300
301 memcpy_by_idxary(dst, dst_channels, src, src_channels, idxary, sample_size, count);
302#else
303 if (dst_mask == src_mask) {
304 memcpy(dst, src, sample_size * popcount(dst_mask) * count);
305 return;
306 }
307 switch (sample_size) {
308 case 1: {
309 uint8_t *udst = (uint8_t*)dst;
310 const uint8_t *usrc = (const uint8_t*)src;
311
312 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
313 } break;
314 case 2: {
315 uint16_t *udst = (uint16_t*)dst;
316 const uint16_t *usrc = (const uint16_t*)src;
317
318 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
319 } break;
320 case 3: { /* could be slow. use a struct to represent 3 bytes of data. */
321 uint8x3_t *udst = (uint8x3_t*)dst;
322 const uint8x3_t *usrc = (const uint8x3_t*)src;
323 static const uint8x3_t zero; /* tricky - we use this to zero out a sample */
324
325 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, zero);
326 } break;
327 case 4: {
328 uint32_t *udst = (uint32_t*)dst;
329 const uint32_t *usrc = (const uint32_t*)src;
330
331 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
332 } break;
333 default:
334 abort(); /* illegal value */
335 break;
336 }
337#endif
338}
339
340/*
341 * C macro to do copying by index array, to rearrange samples
342 * within a frame. This is independent of src/dst sample type.
343 * Don't pass in any expressions for the macro arguments here.
344 */
345#define copy_frame_by_idx(dst, dst_channels, src, src_channels, idxary, count, zero) \
346{ \
347 unsigned i; \
348 int index; \
349 while (count--) { \
350 for (i = 0; i < dst_channels; ++i) { \
351 index = idxary[i]; \
352 *dst++ = index < 0 ? zero : src[index]; \
353 } \
354 src += src_channels; \
355 } \
356}
357
358void memcpy_by_index_array(void *dst, uint32_t dst_channels,
359 const void *src, uint32_t src_channels,
360 const int8_t *idxary, size_t sample_size, size_t count)
361{
362 switch (sample_size) {
363 case 1: {
364 uint8_t *udst = (uint8_t*)dst;
365 const uint8_t *usrc = (const uint8_t*)src;
366
367 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
368 } break;
369 case 2: {
370 uint16_t *udst = (uint16_t*)dst;
371 const uint16_t *usrc = (const uint16_t*)src;
372
373 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
374 } break;
375 case 3: { /* could be slow. use a struct to represent 3 bytes of data. */
376 uint8x3_t *udst = (uint8x3_t*)dst;
377 const uint8x3_t *usrc = (const uint8x3_t*)src;
378 static const uint8x3_t zero;
379
380 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, zero);
381 } break;
382 case 4: {
383 uint32_t *udst = (uint32_t*)dst;
384 const uint32_t *usrc = (const uint32_t*)src;
385
386 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
387 } break;
388 default:
389 abort(); /* illegal value */
390 break;
391 }
392}
393
394size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
395 uint32_t dst_mask, uint32_t src_mask)
396{
397 size_t n = 0;
398 int srcidx = 0;
399 uint32_t bit, ormask = src_mask | dst_mask;
400
401 while (ormask && n < idxcount) {
402 bit = ormask & -ormask; /* get lowest bit */
403 ormask ^= bit; /* remove lowest bit */
404 if (src_mask & dst_mask & bit) { /* matching channel */
405 idxary[n++] = srcidx++;
406 } else if (src_mask & bit) { /* source channel only */
407 ++srcidx;
408 } else { /* destination channel only */
409 idxary[n++] = -1;
410 }
411 }
412 return n + popcount(ormask & dst_mask);
413}