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