OSDN Git Service

resolve merge conflicts of 28ce9cd to lmp-dev
[android-x86/system-media.git] / audio_utils / primitives.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }