blob: dac23947512dce17e03da1e59c303e2b8d5bf0dd [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
17#include <audio_utils/primitives.h>
Glenn Kasten3e1395a2020-06-16 15:50:08 -070018#include <string.h>
Andy Hunge0ccb202014-07-27 20:11:31 -070019#include "private/private.h"
Glenn Kasten632e0c02011-12-16 10:42:58 -080020
Andy Hung1307aa72017-11-17 15:46:55 -080021void ditherAndClamp(int32_t *out, const int32_t *sums, size_t pairs)
Glenn Kasten632e0c02011-12-16 10:42:58 -080022{
Andy Hung1307aa72017-11-17 15:46:55 -080023 for (; pairs > 0; --pairs) {
24 const int32_t l = clamp16(*sums++ >> 12);
25 const int32_t r = clamp16(*sums++ >> 12);
26 *out++ = (r << 16) | (l & 0xFFFF);
Glenn Kasten632e0c02011-12-16 10:42:58 -080027 }
28}
Glenn Kastenddb2e932012-01-16 13:21:31 -080029
Andy Hung62c3d9f2017-11-21 16:36:41 -080030void memcpy_to_i16_from_q4_27(int16_t *dst, const int32_t *src, size_t count)
31{
32 for (; count > 0; --count) {
33 *dst++ = clamp16(*src++ >> 12);
34 }
35}
36
Glenn Kastenddb2e932012-01-16 13:21:31 -080037void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count)
38{
39 dst += count;
40 src += count;
Andy Hung1307aa72017-11-17 15:46:55 -080041 for (; count > 0; --count) {
Glenn Kastenddb2e932012-01-16 13:21:31 -080042 *--dst = (int16_t)(*--src - 0x80) << 8;
43 }
44}
Glenn Kasten7a0baca2012-07-19 13:59:50 -070045
Glenn Kasten78da2ac2012-11-12 14:39:36 -080046void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count)
47{
Andy Hung1307aa72017-11-17 15:46:55 -080048 for (; count > 0; --count) {
Glenn Kasten78da2ac2012-11-12 14:39:36 -080049 *dst++ = (*src++ >> 8) + 0x80;
50 }
51}
52
Andy Hungafab01e2019-09-12 18:38:13 -070053void memcpy_to_u8_from_p24(uint8_t *dst, const uint8_t *src, size_t count)
54{
55 for (; count > 0; --count) {
56#if HAVE_BIG_ENDIAN
57 *dst++ = src[0] + 0x80;
58#else
59 *dst++ = src[2] + 0x80;
60#endif
61 src += 3;
62 }
63}
64
65void memcpy_to_u8_from_i32(uint8_t *dst, const int32_t *src, size_t count)
66{
67 for (; count > 0; --count) {
68 *dst++ = (*src++ >> 24) + 0x80;
69 }
70}
71
72void memcpy_to_u8_from_q8_23(uint8_t *dst, const int32_t *src, size_t count)
73{
74 for (; count > 0; --count) {
75 *dst++ = clamp8_from_q8_23(*src++);
76 }
77}
78
Andy Hung23ef1b32015-01-13 13:56:37 -080079void memcpy_to_u8_from_float(uint8_t *dst, const float *src, size_t count)
80{
Andy Hung1307aa72017-11-17 15:46:55 -080081 for (; count > 0; --count) {
Andy Hung23ef1b32015-01-13 13:56:37 -080082 *dst++ = clamp8_from_float(*src++);
83 }
84}
85
Glenn Kasten5d436052013-06-21 14:01:54 -070086void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count)
87{
Andy Hung1307aa72017-11-17 15:46:55 -080088 for (; count > 0; --count) {
Glenn Kasten5d436052013-06-21 14:01:54 -070089 *dst++ = *src++ >> 16;
90 }
91}
92
93void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count)
94{
Andy Hung1307aa72017-11-17 15:46:55 -080095 for (; count > 0; --count) {
Andy Hung65b5ccd2014-03-18 12:00:55 -070096 *dst++ = clamp16_from_float(*src++);
Glenn Kasten5d436052013-06-21 14:01:54 -070097 }
98}
99
Andy Hungb878e522014-04-04 13:05:43 -0700100void memcpy_to_float_from_q4_27(float *dst, const int32_t *src, size_t count)
Andy Hungaecb15e2014-02-24 19:07:40 -0800101{
Andy Hung1307aa72017-11-17 15:46:55 -0800102 for (; count > 0; --count) {
Andy Hungd2a25cd2014-04-02 11:23:56 -0700103 *dst++ = float_from_q4_27(*src++);
Andy Hungaecb15e2014-02-24 19:07:40 -0800104 }
105}
106
Andy Hunge0454e22014-03-06 13:04:56 -0800107void memcpy_to_float_from_i16(float *dst, const int16_t *src, size_t count)
108{
Andy Hung22667a62017-11-17 15:54:27 -0800109 dst += count;
110 src += count;
Andy Hung1307aa72017-11-17 15:46:55 -0800111 for (; count > 0; --count) {
Andy Hung22667a62017-11-17 15:54:27 -0800112 *--dst = float_from_i16(*--src);
Andy Hunge0454e22014-03-06 13:04:56 -0800113 }
114}
115
Andy Hung23ef1b32015-01-13 13:56:37 -0800116void memcpy_to_float_from_u8(float *dst, const uint8_t *src, size_t count)
117{
Andy Hung22667a62017-11-17 15:54:27 -0800118 dst += count;
119 src += count;
Andy Hung1307aa72017-11-17 15:46:55 -0800120 for (; count > 0; --count) {
Andy Hung22667a62017-11-17 15:54:27 -0800121 *--dst = float_from_u8(*--src);
Andy Hung23ef1b32015-01-13 13:56:37 -0800122 }
123}
124
Andy Hunge0454e22014-03-06 13:04:56 -0800125void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count)
126{
Andy Hung22667a62017-11-17 15:54:27 -0800127 dst += count;
128 src += count * 3;
Andy Hung1307aa72017-11-17 15:46:55 -0800129 for (; count > 0; --count) {
Andy Hung22667a62017-11-17 15:54:27 -0800130 src -= 3;
131 *--dst = float_from_p24(src);
Andy Hunge0454e22014-03-06 13:04:56 -0800132 }
133}
134
135void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count)
136{
Andy Hung1307aa72017-11-17 15:46:55 -0800137 for (; count > 0; --count) {
Andy Hung2af0e172017-03-31 14:08:14 -0700138#if HAVE_BIG_ENDIAN
Andy Hunge0454e22014-03-06 13:04:56 -0800139 *dst++ = src[1] | (src[0] << 8);
140#else
141 *dst++ = src[1] | (src[2] << 8);
142#endif
143 src += 3;
144 }
145}
146
Glenn Kasten95880cb2015-05-28 15:19:16 -0700147void memcpy_to_i32_from_p24(int32_t *dst, const uint8_t *src, size_t count)
148{
Andy Hung22667a62017-11-17 15:54:27 -0800149 dst += count;
150 src += count * 3;
Andy Hung1307aa72017-11-17 15:46:55 -0800151 for (; count > 0; --count) {
Andy Hung22667a62017-11-17 15:54:27 -0800152 src -= 3;
Andy Hung2af0e172017-03-31 14:08:14 -0700153#if HAVE_BIG_ENDIAN
Andy Hung22667a62017-11-17 15:54:27 -0800154 *--dst = (src[2] << 8) | (src[1] << 16) | (src[0] << 24);
Glenn Kasten95880cb2015-05-28 15:19:16 -0700155#else
Andy Hung22667a62017-11-17 15:54:27 -0800156 *--dst = (src[0] << 8) | (src[1] << 16) | (src[2] << 24);
Glenn Kasten95880cb2015-05-28 15:19:16 -0700157#endif
Glenn Kasten95880cb2015-05-28 15:19:16 -0700158 }
159}
160
Andy Hunge0454e22014-03-06 13:04:56 -0800161void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count)
162{
Andy Hung22667a62017-11-17 15:54:27 -0800163 dst += count * 3;
164 src += count;
Andy Hung1307aa72017-11-17 15:46:55 -0800165 for (; count > 0; --count) {
Andy Hung22667a62017-11-17 15:54:27 -0800166 dst -= 3;
Andy Hungc6ddd032018-04-25 17:59:24 -0700167 const int16_t sample = *--src;
Andy Hung2af0e172017-03-31 14:08:14 -0700168#if HAVE_BIG_ENDIAN
Andy Hungc6ddd032018-04-25 17:59:24 -0700169 dst[0] = sample >> 8;
170 dst[1] = sample;
Andy Hung22667a62017-11-17 15:54:27 -0800171 dst[2] = 0;
Andy Hunge0454e22014-03-06 13:04:56 -0800172#else
Andy Hung22667a62017-11-17 15:54:27 -0800173 dst[0] = 0;
Andy Hungc6ddd032018-04-25 17:59:24 -0700174 dst[1] = sample;
175 dst[2] = sample >> 8;
Andy Hunge0454e22014-03-06 13:04:56 -0800176#endif
177 }
178}
179
180void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count)
181{
Andy Hung1307aa72017-11-17 15:46:55 -0800182 for (; count > 0; --count) {
Andy Hunge0454e22014-03-06 13:04:56 -0800183 int32_t ival = clamp24_from_float(*src++);
184
Andy Hung2af0e172017-03-31 14:08:14 -0700185#if HAVE_BIG_ENDIAN
Andy Hunge0454e22014-03-06 13:04:56 -0800186 *dst++ = ival >> 16;
187 *dst++ = ival >> 8;
188 *dst++ = ival;
189#else
190 *dst++ = ival;
191 *dst++ = ival >> 8;
192 *dst++ = ival >> 16;
193#endif
194 }
195}
196
Glenn Kasteneee45152014-05-02 12:41:04 -0700197void memcpy_to_p24_from_q8_23(uint8_t *dst, const int32_t *src, size_t count)
198{
Andy Hung1307aa72017-11-17 15:46:55 -0800199 for (; count > 0; --count) {
Glenn Kasteneee45152014-05-02 12:41:04 -0700200 int32_t ival = clamp24_from_q8_23(*src++);
201
Andy Hung2af0e172017-03-31 14:08:14 -0700202#if HAVE_BIG_ENDIAN
Glenn Kasteneee45152014-05-02 12:41:04 -0700203 *dst++ = ival >> 16;
204 *dst++ = ival >> 8;
205 *dst++ = ival;
206#else
207 *dst++ = ival;
208 *dst++ = ival >> 8;
209 *dst++ = ival >> 16;
210#endif
211 }
212}
213
Glenn Kastendaa1a002015-05-29 16:50:24 -0700214void memcpy_to_p24_from_i32(uint8_t *dst, const int32_t *src, size_t count)
215{
Andy Hung1307aa72017-11-17 15:46:55 -0800216 for (; count > 0; --count) {
Glenn Kastendaa1a002015-05-29 16:50:24 -0700217 int32_t ival = *src++ >> 8;
218
Andy Hung2af0e172017-03-31 14:08:14 -0700219#if HAVE_BIG_ENDIAN
Glenn Kastendaa1a002015-05-29 16:50:24 -0700220 *dst++ = ival >> 16;
221 *dst++ = ival >> 8;
222 *dst++ = ival;
223#else
224 *dst++ = ival;
225 *dst++ = ival >> 8;
226 *dst++ = ival >> 16;
227#endif
228 }
229}
230
Andy Hungd5829882014-03-12 11:46:15 -0700231void memcpy_to_q8_23_from_i16(int32_t *dst, const int16_t *src, size_t count)
232{
Andy Hung22667a62017-11-17 15:54:27 -0800233 dst += count;
234 src += count;
Andy Hung1307aa72017-11-17 15:46:55 -0800235 for (; count > 0; --count) {
Andy Hung22667a62017-11-17 15:54:27 -0800236 *--dst = (int32_t)*--src << 8;
Andy Hungd5829882014-03-12 11:46:15 -0700237 }
238}
239
240void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_t count)
241{
Andy Hung1307aa72017-11-17 15:46:55 -0800242 for (; count > 0; --count) {
Andy Hungd5829882014-03-12 11:46:15 -0700243 *dst++ = clamp24_from_float(*src++);
244 }
245}
246
Haynes Mathew George78ac9f82015-04-09 13:50:13 -0700247void memcpy_to_q8_23_from_p24(int32_t *dst, const uint8_t *src, size_t count)
248{
Andy Hung22667a62017-11-17 15:54:27 -0800249 dst += count;
250 src += count * 3;
Andy Hung1307aa72017-11-17 15:46:55 -0800251 for (; count > 0; --count) {
Andy Hung22667a62017-11-17 15:54:27 -0800252 src -= 3;
Andy Hung2af0e172017-03-31 14:08:14 -0700253#if HAVE_BIG_ENDIAN
Andy Hung22667a62017-11-17 15:54:27 -0800254 *--dst = (int8_t)src[0] << 16 | src[1] << 8 | src[2];
Haynes Mathew George78ac9f82015-04-09 13:50:13 -0700255#else
Andy Hung22667a62017-11-17 15:54:27 -0800256 *--dst = (int8_t)src[2] << 16 | src[1] << 8 | src[0];
Haynes Mathew George78ac9f82015-04-09 13:50:13 -0700257#endif
Haynes Mathew George78ac9f82015-04-09 13:50:13 -0700258 }
259}
260
Andy Hungb878e522014-04-04 13:05:43 -0700261void memcpy_to_q4_27_from_float(int32_t *dst, const float *src, size_t count)
262{
Andy Hung1307aa72017-11-17 15:46:55 -0800263 for (; count > 0; --count) {
Andy Hungb878e522014-04-04 13:05:43 -0700264 *dst++ = clampq4_27_from_float(*src++);
265 }
266}
267
Andy Hungd5829882014-03-12 11:46:15 -0700268void memcpy_to_i16_from_q8_23(int16_t *dst, const int32_t *src, size_t count)
269{
Andy Hung1307aa72017-11-17 15:46:55 -0800270 for (; count > 0; --count) {
Andy Hungd5829882014-03-12 11:46:15 -0700271 *dst++ = clamp16(*src++ >> 8);
272 }
273}
274
275void memcpy_to_float_from_q8_23(float *dst, const int32_t *src, size_t count)
276{
Andy Hung1307aa72017-11-17 15:46:55 -0800277 for (; count > 0; --count) {
Andy Hungd5829882014-03-12 11:46:15 -0700278 *dst++ = float_from_q8_23(*src++);
279 }
280}
281
Glenn Kasten5cb49ce2018-10-30 09:02:38 -0700282void memcpy_to_i32_from_u8(int32_t *dst, const uint8_t *src, size_t count)
283{
284 dst += count;
285 src += count;
286 for (; count > 0; --count) {
287 *--dst = ((int32_t)(*--src) - 0x80) << 24;
288 }
289}
290
Andy Hung2c63fb62014-03-12 14:44:12 -0700291void memcpy_to_i32_from_i16(int32_t *dst, const int16_t *src, size_t count)
292{
Andy Hung22667a62017-11-17 15:54:27 -0800293 dst += count;
294 src += count;
Andy Hung1307aa72017-11-17 15:46:55 -0800295 for (; count > 0; --count) {
Andy Hung22667a62017-11-17 15:54:27 -0800296 *--dst = (int32_t)*--src << 16;
Andy Hung2c63fb62014-03-12 14:44:12 -0700297 }
298}
299
300void memcpy_to_i32_from_float(int32_t *dst, const float *src, size_t count)
301{
Andy Hung1307aa72017-11-17 15:46:55 -0800302 for (; count > 0; --count) {
Andy Hung2c63fb62014-03-12 14:44:12 -0700303 *dst++ = clamp32_from_float(*src++);
304 }
305}
306
307void memcpy_to_float_from_i32(float *dst, const int32_t *src, size_t count)
308{
Andy Hung1307aa72017-11-17 15:46:55 -0800309 for (; count > 0; --count) {
Andy Hung2c63fb62014-03-12 14:44:12 -0700310 *dst++ = float_from_i32(*src++);
311 }
312}
313
Kevin Rocard2d98fd32017-11-09 22:12:51 -0800314void memcpy_to_float_from_float_with_clamping(float *dst, const float *src, size_t count,
315 float absMax) {
316 // Note: using NEON intrinsics (vminq_f32, vld1q_f32...) did NOT accelerate
317 // the function when benchmarked. The compiler already vectorize using FMINNM f32x4 & similar.
318 // Note: clamping induce a ~20% overhead compared to memcpy for count in [64, 512]
319 // See primitives_benchmark
Andy Hung1307aa72017-11-17 15:46:55 -0800320 for (; count > 0; --count) {
Kevin Rocard2d98fd32017-11-09 22:12:51 -0800321 const float sample = *src++;
322 *dst++ = fmax(-absMax, fmin(absMax, sample));
323 }
324}
325
Glenn Kasten7a0baca2012-07-19 13:59:50 -0700326void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count)
327{
Andy Hung1307aa72017-11-17 15:46:55 -0800328 for (; count > 0; --count) {
Glenn Kasten7a0baca2012-07-19 13:59:50 -0700329 *dst++ = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
330 src += 2;
331 }
332}
333
334void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count)
335{
Andy Hung22667a62017-11-17 15:54:27 -0800336 dst += count * 2;
337 src += count;
Andy Hung1307aa72017-11-17 15:46:55 -0800338 for (; count > 0; --count) {
Andy Hung22667a62017-11-17 15:54:27 -0800339 const int32_t temp = *--src;
340 dst -= 2;
Glenn Kasten7a0baca2012-07-19 13:59:50 -0700341 dst[0] = temp;
342 dst[1] = temp;
Glenn Kasten7a0baca2012-07-19 13:59:50 -0700343 }
344}
Glenn Kasteneb247df2014-02-21 10:00:51 -0800345
Andy Hung9c8dd452015-04-21 13:21:36 -0700346void downmix_to_mono_float_from_stereo_float(float *dst, const float *src, size_t frames)
347{
Andy Hung1307aa72017-11-17 15:46:55 -0800348 for (; frames > 0; --frames) {
Andy Hung9c8dd452015-04-21 13:21:36 -0700349 *dst++ = (src[0] + src[1]) * 0.5;
350 src += 2;
351 }
352}
353
354void upmix_to_stereo_float_from_mono_float(float *dst, const float *src, size_t frames)
355{
Andy Hung22667a62017-11-17 15:54:27 -0800356 dst += frames * 2;
357 src += frames;
Andy Hung1307aa72017-11-17 15:46:55 -0800358 for (; frames > 0; --frames) {
Andy Hung22667a62017-11-17 15:54:27 -0800359 const float temp = *--src;
360 dst -= 2;
Andy Hung9c8dd452015-04-21 13:21:36 -0700361 dst[0] = temp;
362 dst[1] = temp;
Andy Hung9c8dd452015-04-21 13:21:36 -0700363 }
364}
365
Glenn Kasteneb247df2014-02-21 10:00:51 -0800366size_t nonZeroMono32(const int32_t *samples, size_t count)
367{
368 size_t nonZero = 0;
Andy Hung1307aa72017-11-17 15:46:55 -0800369 for (; count > 0; --count) {
Andy Hung0ebba4b2017-11-17 16:02:19 -0800370 nonZero += *samples++ != 0;
Glenn Kasteneb247df2014-02-21 10:00:51 -0800371 }
372 return nonZero;
373}
374
375size_t nonZeroMono16(const int16_t *samples, size_t count)
376{
377 size_t nonZero = 0;
Andy Hung1307aa72017-11-17 15:46:55 -0800378 for (; count > 0; --count) {
Andy Hung0ebba4b2017-11-17 16:02:19 -0800379 nonZero += *samples++ != 0;
Glenn Kasteneb247df2014-02-21 10:00:51 -0800380 }
381 return nonZero;
382}
383
384size_t nonZeroStereo32(const int32_t *frames, size_t count)
385{
386 size_t nonZero = 0;
Andy Hung1307aa72017-11-17 15:46:55 -0800387 for (; count > 0; --count) {
Andy Hung0ebba4b2017-11-17 16:02:19 -0800388 nonZero += frames[0] != 0 || frames[1] != 0;
Glenn Kasteneb247df2014-02-21 10:00:51 -0800389 frames += 2;
390 }
391 return nonZero;
392}
393
394size_t nonZeroStereo16(const int16_t *frames, size_t count)
395{
396 size_t nonZero = 0;
Andy Hung1307aa72017-11-17 15:46:55 -0800397 for (; count > 0; --count) {
Andy Hung0ebba4b2017-11-17 16:02:19 -0800398 nonZero += frames[0] != 0 || frames[1] != 0;
Glenn Kasteneb247df2014-02-21 10:00:51 -0800399 frames += 2;
400 }
401 return nonZero;
402}
Andy Hung3af2af22014-05-22 18:40:30 -0700403
Andy Hung3af2af22014-05-22 18:40:30 -0700404/*
405 * C macro to do channel mask copying independent of dst/src sample type.
406 * Don't pass in any expressions for the macro arguments here.
407 */
408#define copy_frame_by_mask(dst, dmask, src, smask, count, zero) \
409{ \
410 uint32_t bit, ormask; \
Andy Hung1307aa72017-11-17 15:46:55 -0800411 for (; (count) > 0; --(count)) { \
Chih-Hung Hsieh2c853ac2016-05-11 15:13:31 -0700412 ormask = (dmask) | (smask); \
Andy Hung3af2af22014-05-22 18:40:30 -0700413 while (ormask) { \
414 bit = ormask & -ormask; /* get lowest bit */ \
415 ormask ^= bit; /* remove lowest bit */ \
Chih-Hung Hsieh2c853ac2016-05-11 15:13:31 -0700416 if ((dmask) & bit) { \
417 *(dst)++ = (smask) & bit ? *(src)++ : (zero); \
Andy Hung3af2af22014-05-22 18:40:30 -0700418 } else { /* source channel only */ \
Chih-Hung Hsieh2c853ac2016-05-11 15:13:31 -0700419 ++(src); \
Andy Hung3af2af22014-05-22 18:40:30 -0700420 } \
421 } \
422 } \
423}
424
425void memcpy_by_channel_mask(void *dst, uint32_t dst_mask,
426 const void *src, uint32_t src_mask, size_t sample_size, size_t count)
427{
428#if 0
429 /* alternate way of handling memcpy_by_channel_mask by using the idxary */
430 int8_t idxary[32];
Glenn Kasten2220b552020-06-16 15:47:41 -0700431 uint32_t src_channels = __builtin_popcount(src_mask);
Andy Hung3af2af22014-05-22 18:40:30 -0700432 uint32_t dst_channels =
433 memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask);
434
435 memcpy_by_idxary(dst, dst_channels, src, src_channels, idxary, sample_size, count);
436#else
437 if (dst_mask == src_mask) {
Glenn Kasten2220b552020-06-16 15:47:41 -0700438 memcpy(dst, src, sample_size * __builtin_popcount(dst_mask) * count);
Andy Hung3af2af22014-05-22 18:40:30 -0700439 return;
440 }
441 switch (sample_size) {
442 case 1: {
443 uint8_t *udst = (uint8_t*)dst;
444 const uint8_t *usrc = (const uint8_t*)src;
445
446 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
447 } break;
448 case 2: {
449 uint16_t *udst = (uint16_t*)dst;
450 const uint16_t *usrc = (const uint16_t*)src;
451
452 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
453 } break;
454 case 3: { /* could be slow. use a struct to represent 3 bytes of data. */
455 uint8x3_t *udst = (uint8x3_t*)dst;
456 const uint8x3_t *usrc = (const uint8x3_t*)src;
457 static const uint8x3_t zero; /* tricky - we use this to zero out a sample */
458
459 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, zero);
460 } break;
461 case 4: {
462 uint32_t *udst = (uint32_t*)dst;
463 const uint32_t *usrc = (const uint32_t*)src;
464
465 copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
466 } break;
467 default:
468 abort(); /* illegal value */
469 break;
470 }
471#endif
472}
473
474/*
475 * C macro to do copying by index array, to rearrange samples
476 * within a frame. This is independent of src/dst sample type.
477 * Don't pass in any expressions for the macro arguments here.
478 */
479#define copy_frame_by_idx(dst, dst_channels, src, src_channels, idxary, count, zero) \
480{ \
481 unsigned i; \
482 int index; \
Andy Hung1307aa72017-11-17 15:46:55 -0800483 for (; (count) > 0; --(count)) { \
Chih-Hung Hsieh2c853ac2016-05-11 15:13:31 -0700484 for (i = 0; i < (dst_channels); ++i) { \
485 index = (idxary)[i]; \
486 *(dst)++ = index < 0 ? (zero) : (src)[index]; \
Andy Hung3af2af22014-05-22 18:40:30 -0700487 } \
Chih-Hung Hsieh2c853ac2016-05-11 15:13:31 -0700488 (src) += (src_channels); \
Andy Hung3af2af22014-05-22 18:40:30 -0700489 } \
490}
491
492void memcpy_by_index_array(void *dst, uint32_t dst_channels,
493 const void *src, uint32_t src_channels,
494 const int8_t *idxary, size_t sample_size, size_t count)
495{
496 switch (sample_size) {
497 case 1: {
498 uint8_t *udst = (uint8_t*)dst;
499 const uint8_t *usrc = (const uint8_t*)src;
500
501 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
502 } break;
503 case 2: {
504 uint16_t *udst = (uint16_t*)dst;
505 const uint16_t *usrc = (const uint16_t*)src;
506
507 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
508 } break;
509 case 3: { /* could be slow. use a struct to represent 3 bytes of data. */
510 uint8x3_t *udst = (uint8x3_t*)dst;
511 const uint8x3_t *usrc = (const uint8x3_t*)src;
512 static const uint8x3_t zero;
513
514 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, zero);
515 } break;
516 case 4: {
517 uint32_t *udst = (uint32_t*)dst;
518 const uint32_t *usrc = (const uint32_t*)src;
519
520 copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
521 } break;
522 default:
523 abort(); /* illegal value */
524 break;
525 }
526}
527
528size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
529 uint32_t dst_mask, uint32_t src_mask)
530{
531 size_t n = 0;
532 int srcidx = 0;
533 uint32_t bit, ormask = src_mask | dst_mask;
534
535 while (ormask && n < idxcount) {
536 bit = ormask & -ormask; /* get lowest bit */
537 ormask ^= bit; /* remove lowest bit */
538 if (src_mask & dst_mask & bit) { /* matching channel */
539 idxary[n++] = srcidx++;
540 } else if (src_mask & bit) { /* source channel only */
541 ++srcidx;
542 } else { /* destination channel only */
543 idxary[n++] = -1;
544 }
545 }
Glenn Kasten2220b552020-06-16 15:47:41 -0700546 return n + __builtin_popcount(ormask & dst_mask);
Andy Hung3af2af22014-05-22 18:40:30 -0700547}
Andy Hung5a0d0282015-02-02 15:34:13 -0800548
549size_t memcpy_by_index_array_initialization_src_index(int8_t *idxary, size_t idxcount,
550 uint32_t dst_mask, uint32_t src_mask) {
Glenn Kasten2220b552020-06-16 15:47:41 -0700551 size_t dst_count = __builtin_popcount(dst_mask);
Andy Hung5a0d0282015-02-02 15:34:13 -0800552 if (idxcount == 0) {
553 return dst_count;
554 }
555 if (dst_count > idxcount) {
556 dst_count = idxcount;
557 }
558
559 size_t src_idx, dst_idx;
560 for (src_idx = 0, dst_idx = 0; dst_idx < dst_count; ++dst_idx) {
561 if (src_mask & 1) {
562 idxary[dst_idx] = src_idx++;
563 } else {
564 idxary[dst_idx] = -1;
565 }
566 src_mask >>= 1;
567 }
568 return dst_idx;
569}
Andy Hung291a1942015-02-27 14:20:33 -0800570
571size_t memcpy_by_index_array_initialization_dst_index(int8_t *idxary, size_t idxcount,
572 uint32_t dst_mask, uint32_t src_mask) {
573 size_t src_idx, dst_idx;
574 size_t dst_count = __builtin_popcount(dst_mask);
575 size_t src_count = __builtin_popcount(src_mask);
576 if (idxcount == 0) {
577 return dst_count;
578 }
579 if (dst_count > idxcount) {
580 dst_count = idxcount;
581 }
582 for (src_idx = 0, dst_idx = 0; dst_idx < dst_count; ++src_idx) {
583 if (dst_mask & 1) {
584 idxary[dst_idx++] = src_idx < src_count ? (signed)src_idx : -1;
585 }
586 dst_mask >>= 1;
587 }
588 return dst_idx;
589}
Ari Hausman-Cohen90ac5f62017-08-16 18:32:22 -0700590
591void accumulate_i16(int16_t *dst, const int16_t *src, size_t count) {
592 while (count--) {
593 *dst = clamp16((int32_t)*dst + *src++);
594 ++dst;
595 }
596}
597
598void accumulate_u8(uint8_t *dst, const uint8_t *src, size_t count) {
599 int32_t sum;
Andy Hung1307aa72017-11-17 15:46:55 -0800600 for (; count > 0; --count) {
Ari Hausman-Cohen90ac5f62017-08-16 18:32:22 -0700601 // 8-bit samples are centered around 0x80.
602 sum = *dst + *src++ - 0x80;
603 // Clamp to [0, 0xff].
604 *dst++ = (sum & 0x100) ? (~sum >> 9) : sum;
605 }
606}
607
608void accumulate_p24(uint8_t *dst, const uint8_t *src, size_t count) {
Andy Hung1307aa72017-11-17 15:46:55 -0800609 for (; count > 0; --count) {
Ari Hausman-Cohen90ac5f62017-08-16 18:32:22 -0700610 // Unpack.
611 int32_t dst_q8_23 = 0;
612 int32_t src_q8_23 = 0;
613 memcpy_to_q8_23_from_p24(&dst_q8_23, dst, 1);
614 memcpy_to_q8_23_from_p24(&src_q8_23, src, 1);
615
616 // Accumulate and overwrite.
617 dst_q8_23 += src_q8_23;
618 memcpy_to_p24_from_q8_23(dst, &dst_q8_23, 1);
619
620 // Move on to next sample.
621 dst += 3;
622 src += 3;
623 }
624}
625
626void accumulate_q8_23(int32_t *dst, const int32_t *src, size_t count) {
Andy Hung1307aa72017-11-17 15:46:55 -0800627 for (; count > 0; --count) {
Ari Hausman-Cohen90ac5f62017-08-16 18:32:22 -0700628 *dst = clamp24_from_q8_23(*dst + *src++);
629 ++dst;
630 }
631}
632
633void accumulate_i32(int32_t *dst, const int32_t *src, size_t count) {
Andy Hung1307aa72017-11-17 15:46:55 -0800634 for (; count > 0; --count) {
Ari Hausman-Cohen90ac5f62017-08-16 18:32:22 -0700635 *dst = clamp32((int64_t)*dst + *src++);
636 ++dst;
637 }
638}
639
640void accumulate_float(float *dst, const float *src, size_t count) {
Andy Hung1307aa72017-11-17 15:46:55 -0800641 for (; count > 0; --count) {
Ari Hausman-Cohen90ac5f62017-08-16 18:32:22 -0700642 *dst++ += *src++;
643 }
644}