1*b9df5ad1SAndroid Build Coastguard Worker /*
2*b9df5ad1SAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*b9df5ad1SAndroid Build Coastguard Worker *
4*b9df5ad1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*b9df5ad1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*b9df5ad1SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*b9df5ad1SAndroid Build Coastguard Worker *
8*b9df5ad1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*b9df5ad1SAndroid Build Coastguard Worker *
10*b9df5ad1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*b9df5ad1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*b9df5ad1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b9df5ad1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*b9df5ad1SAndroid Build Coastguard Worker * limitations under the License.
15*b9df5ad1SAndroid Build Coastguard Worker */
16*b9df5ad1SAndroid Build Coastguard Worker
17*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/primitives.h>
18*b9df5ad1SAndroid Build Coastguard Worker #include <string.h>
19*b9df5ad1SAndroid Build Coastguard Worker #include "private/private.h"
20*b9df5ad1SAndroid Build Coastguard Worker
ditherAndClamp(int32_t * out,const int32_t * sums,size_t pairs)21*b9df5ad1SAndroid Build Coastguard Worker void ditherAndClamp(int32_t *out, const int32_t *sums, size_t pairs)
22*b9df5ad1SAndroid Build Coastguard Worker {
23*b9df5ad1SAndroid Build Coastguard Worker for (; pairs > 0; --pairs) {
24*b9df5ad1SAndroid Build Coastguard Worker const int32_t l = clamp16(*sums++ >> 12);
25*b9df5ad1SAndroid Build Coastguard Worker const int32_t r = clamp16(*sums++ >> 12);
26*b9df5ad1SAndroid Build Coastguard Worker *out++ = (r << 16) | (l & 0xFFFF);
27*b9df5ad1SAndroid Build Coastguard Worker }
28*b9df5ad1SAndroid Build Coastguard Worker }
29*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i16_from_q4_27(int16_t * dst,const int32_t * src,size_t count)30*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i16_from_q4_27(int16_t *dst, const int32_t *src, size_t count)
31*b9df5ad1SAndroid Build Coastguard Worker {
32*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
33*b9df5ad1SAndroid Build Coastguard Worker *dst++ = clamp16(*src++ >> 12);
34*b9df5ad1SAndroid Build Coastguard Worker }
35*b9df5ad1SAndroid Build Coastguard Worker }
36*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i16_from_u8(int16_t * dst,const uint8_t * src,size_t count)37*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count)
38*b9df5ad1SAndroid Build Coastguard Worker {
39*b9df5ad1SAndroid Build Coastguard Worker dst += count;
40*b9df5ad1SAndroid Build Coastguard Worker src += count;
41*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
42*b9df5ad1SAndroid Build Coastguard Worker *--dst = (int16_t)(*--src - 0x80) << 8;
43*b9df5ad1SAndroid Build Coastguard Worker }
44*b9df5ad1SAndroid Build Coastguard Worker }
45*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_u8_from_i16(uint8_t * dst,const int16_t * src,size_t count)46*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count)
47*b9df5ad1SAndroid Build Coastguard Worker {
48*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
49*b9df5ad1SAndroid Build Coastguard Worker *dst++ = (*src++ >> 8) + 0x80;
50*b9df5ad1SAndroid Build Coastguard Worker }
51*b9df5ad1SAndroid Build Coastguard Worker }
52*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_u8_from_p24(uint8_t * dst,const uint8_t * src,size_t count)53*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_u8_from_p24(uint8_t *dst, const uint8_t *src, size_t count)
54*b9df5ad1SAndroid Build Coastguard Worker {
55*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
56*b9df5ad1SAndroid Build Coastguard Worker #if HAVE_BIG_ENDIAN
57*b9df5ad1SAndroid Build Coastguard Worker *dst++ = src[0] + 0x80;
58*b9df5ad1SAndroid Build Coastguard Worker #else
59*b9df5ad1SAndroid Build Coastguard Worker *dst++ = src[2] + 0x80;
60*b9df5ad1SAndroid Build Coastguard Worker #endif
61*b9df5ad1SAndroid Build Coastguard Worker src += 3;
62*b9df5ad1SAndroid Build Coastguard Worker }
63*b9df5ad1SAndroid Build Coastguard Worker }
64*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_u8_from_i32(uint8_t * dst,const int32_t * src,size_t count)65*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_u8_from_i32(uint8_t *dst, const int32_t *src, size_t count)
66*b9df5ad1SAndroid Build Coastguard Worker {
67*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
68*b9df5ad1SAndroid Build Coastguard Worker *dst++ = (*src++ >> 24) + 0x80;
69*b9df5ad1SAndroid Build Coastguard Worker }
70*b9df5ad1SAndroid Build Coastguard Worker }
71*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_u8_from_q8_23(uint8_t * dst,const int32_t * src,size_t count)72*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_u8_from_q8_23(uint8_t *dst, const int32_t *src, size_t count)
73*b9df5ad1SAndroid Build Coastguard Worker {
74*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
75*b9df5ad1SAndroid Build Coastguard Worker *dst++ = clamp8_from_q8_23(*src++);
76*b9df5ad1SAndroid Build Coastguard Worker }
77*b9df5ad1SAndroid Build Coastguard Worker }
78*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_u8_from_float(uint8_t * dst,const float * src,size_t count)79*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_u8_from_float(uint8_t *dst, const float *src, size_t count)
80*b9df5ad1SAndroid Build Coastguard Worker {
81*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
82*b9df5ad1SAndroid Build Coastguard Worker *dst++ = clamp8_from_float(*src++);
83*b9df5ad1SAndroid Build Coastguard Worker }
84*b9df5ad1SAndroid Build Coastguard Worker }
85*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i16_from_i32(int16_t * dst,const int32_t * src,size_t count)86*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count)
87*b9df5ad1SAndroid Build Coastguard Worker {
88*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
89*b9df5ad1SAndroid Build Coastguard Worker *dst++ = *src++ >> 16;
90*b9df5ad1SAndroid Build Coastguard Worker }
91*b9df5ad1SAndroid Build Coastguard Worker }
92*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i16_from_float(int16_t * dst,const float * src,size_t count)93*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count)
94*b9df5ad1SAndroid Build Coastguard Worker {
95*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
96*b9df5ad1SAndroid Build Coastguard Worker *dst++ = clamp16_from_float(*src++);
97*b9df5ad1SAndroid Build Coastguard Worker }
98*b9df5ad1SAndroid Build Coastguard Worker }
99*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_float_from_q4_27(float * dst,const int32_t * src,size_t count)100*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_float_from_q4_27(float *dst, const int32_t *src, size_t count)
101*b9df5ad1SAndroid Build Coastguard Worker {
102*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
103*b9df5ad1SAndroid Build Coastguard Worker *dst++ = float_from_q4_27(*src++);
104*b9df5ad1SAndroid Build Coastguard Worker }
105*b9df5ad1SAndroid Build Coastguard Worker }
106*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_float_from_i16(float * dst,const int16_t * src,size_t count)107*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_float_from_i16(float *dst, const int16_t *src, size_t count)
108*b9df5ad1SAndroid Build Coastguard Worker {
109*b9df5ad1SAndroid Build Coastguard Worker dst += count;
110*b9df5ad1SAndroid Build Coastguard Worker src += count;
111*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
112*b9df5ad1SAndroid Build Coastguard Worker *--dst = float_from_i16(*--src);
113*b9df5ad1SAndroid Build Coastguard Worker }
114*b9df5ad1SAndroid Build Coastguard Worker }
115*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_float_from_u8(float * dst,const uint8_t * src,size_t count)116*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_float_from_u8(float *dst, const uint8_t *src, size_t count)
117*b9df5ad1SAndroid Build Coastguard Worker {
118*b9df5ad1SAndroid Build Coastguard Worker dst += count;
119*b9df5ad1SAndroid Build Coastguard Worker src += count;
120*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
121*b9df5ad1SAndroid Build Coastguard Worker *--dst = float_from_u8(*--src);
122*b9df5ad1SAndroid Build Coastguard Worker }
123*b9df5ad1SAndroid Build Coastguard Worker }
124*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_float_from_p24(float * dst,const uint8_t * src,size_t count)125*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count)
126*b9df5ad1SAndroid Build Coastguard Worker {
127*b9df5ad1SAndroid Build Coastguard Worker dst += count;
128*b9df5ad1SAndroid Build Coastguard Worker src += count * 3;
129*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
130*b9df5ad1SAndroid Build Coastguard Worker src -= 3;
131*b9df5ad1SAndroid Build Coastguard Worker *--dst = float_from_p24(src);
132*b9df5ad1SAndroid Build Coastguard Worker }
133*b9df5ad1SAndroid Build Coastguard Worker }
134*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i16_from_p24(int16_t * dst,const uint8_t * src,size_t count)135*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count)
136*b9df5ad1SAndroid Build Coastguard Worker {
137*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
138*b9df5ad1SAndroid Build Coastguard Worker #if HAVE_BIG_ENDIAN
139*b9df5ad1SAndroid Build Coastguard Worker *dst++ = src[1] | (src[0] << 8);
140*b9df5ad1SAndroid Build Coastguard Worker #else
141*b9df5ad1SAndroid Build Coastguard Worker *dst++ = src[1] | (src[2] << 8);
142*b9df5ad1SAndroid Build Coastguard Worker #endif
143*b9df5ad1SAndroid Build Coastguard Worker src += 3;
144*b9df5ad1SAndroid Build Coastguard Worker }
145*b9df5ad1SAndroid Build Coastguard Worker }
146*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i32_from_p24(int32_t * dst,const uint8_t * src,size_t count)147*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i32_from_p24(int32_t *dst, const uint8_t *src, size_t count)
148*b9df5ad1SAndroid Build Coastguard Worker {
149*b9df5ad1SAndroid Build Coastguard Worker dst += count;
150*b9df5ad1SAndroid Build Coastguard Worker src += count * 3;
151*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
152*b9df5ad1SAndroid Build Coastguard Worker src -= 3;
153*b9df5ad1SAndroid Build Coastguard Worker #if HAVE_BIG_ENDIAN
154*b9df5ad1SAndroid Build Coastguard Worker *--dst = (src[2] << 8) | (src[1] << 16) | (src[0] << 24);
155*b9df5ad1SAndroid Build Coastguard Worker #else
156*b9df5ad1SAndroid Build Coastguard Worker *--dst = (src[0] << 8) | (src[1] << 16) | (src[2] << 24);
157*b9df5ad1SAndroid Build Coastguard Worker #endif
158*b9df5ad1SAndroid Build Coastguard Worker }
159*b9df5ad1SAndroid Build Coastguard Worker }
160*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_p24_from_i16(uint8_t * dst,const int16_t * src,size_t count)161*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count)
162*b9df5ad1SAndroid Build Coastguard Worker {
163*b9df5ad1SAndroid Build Coastguard Worker dst += count * 3;
164*b9df5ad1SAndroid Build Coastguard Worker src += count;
165*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
166*b9df5ad1SAndroid Build Coastguard Worker dst -= 3;
167*b9df5ad1SAndroid Build Coastguard Worker const int16_t sample = *--src;
168*b9df5ad1SAndroid Build Coastguard Worker #if HAVE_BIG_ENDIAN
169*b9df5ad1SAndroid Build Coastguard Worker dst[0] = sample >> 8;
170*b9df5ad1SAndroid Build Coastguard Worker dst[1] = sample;
171*b9df5ad1SAndroid Build Coastguard Worker dst[2] = 0;
172*b9df5ad1SAndroid Build Coastguard Worker #else
173*b9df5ad1SAndroid Build Coastguard Worker dst[0] = 0;
174*b9df5ad1SAndroid Build Coastguard Worker dst[1] = sample;
175*b9df5ad1SAndroid Build Coastguard Worker dst[2] = sample >> 8;
176*b9df5ad1SAndroid Build Coastguard Worker #endif
177*b9df5ad1SAndroid Build Coastguard Worker }
178*b9df5ad1SAndroid Build Coastguard Worker }
179*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_p24_from_float(uint8_t * dst,const float * src,size_t count)180*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count)
181*b9df5ad1SAndroid Build Coastguard Worker {
182*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
183*b9df5ad1SAndroid Build Coastguard Worker int32_t ival = clamp24_from_float(*src++);
184*b9df5ad1SAndroid Build Coastguard Worker
185*b9df5ad1SAndroid Build Coastguard Worker #if HAVE_BIG_ENDIAN
186*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 16;
187*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 8;
188*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival;
189*b9df5ad1SAndroid Build Coastguard Worker #else
190*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival;
191*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 8;
192*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 16;
193*b9df5ad1SAndroid Build Coastguard Worker #endif
194*b9df5ad1SAndroid Build Coastguard Worker }
195*b9df5ad1SAndroid Build Coastguard Worker }
196*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_p24_from_q8_23(uint8_t * dst,const int32_t * src,size_t count)197*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_p24_from_q8_23(uint8_t *dst, const int32_t *src, size_t count)
198*b9df5ad1SAndroid Build Coastguard Worker {
199*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
200*b9df5ad1SAndroid Build Coastguard Worker int32_t ival = clamp24_from_q8_23(*src++);
201*b9df5ad1SAndroid Build Coastguard Worker
202*b9df5ad1SAndroid Build Coastguard Worker #if HAVE_BIG_ENDIAN
203*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 16;
204*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 8;
205*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival;
206*b9df5ad1SAndroid Build Coastguard Worker #else
207*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival;
208*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 8;
209*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 16;
210*b9df5ad1SAndroid Build Coastguard Worker #endif
211*b9df5ad1SAndroid Build Coastguard Worker }
212*b9df5ad1SAndroid Build Coastguard Worker }
213*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_p24_from_i32(uint8_t * dst,const int32_t * src,size_t count)214*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_p24_from_i32(uint8_t *dst, const int32_t *src, size_t count)
215*b9df5ad1SAndroid Build Coastguard Worker {
216*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
217*b9df5ad1SAndroid Build Coastguard Worker int32_t ival = *src++ >> 8;
218*b9df5ad1SAndroid Build Coastguard Worker
219*b9df5ad1SAndroid Build Coastguard Worker #if HAVE_BIG_ENDIAN
220*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 16;
221*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 8;
222*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival;
223*b9df5ad1SAndroid Build Coastguard Worker #else
224*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival;
225*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 8;
226*b9df5ad1SAndroid Build Coastguard Worker *dst++ = ival >> 16;
227*b9df5ad1SAndroid Build Coastguard Worker #endif
228*b9df5ad1SAndroid Build Coastguard Worker }
229*b9df5ad1SAndroid Build Coastguard Worker }
230*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_q8_23_from_i16(int32_t * dst,const int16_t * src,size_t count)231*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_q8_23_from_i16(int32_t *dst, const int16_t *src, size_t count)
232*b9df5ad1SAndroid Build Coastguard Worker {
233*b9df5ad1SAndroid Build Coastguard Worker dst += count;
234*b9df5ad1SAndroid Build Coastguard Worker src += count;
235*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
236*b9df5ad1SAndroid Build Coastguard Worker *--dst = (int32_t)*--src << 8;
237*b9df5ad1SAndroid Build Coastguard Worker }
238*b9df5ad1SAndroid Build Coastguard Worker }
239*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_q8_23_from_float_with_clamp(int32_t * dst,const float * src,size_t count)240*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_t count)
241*b9df5ad1SAndroid Build Coastguard Worker {
242*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
243*b9df5ad1SAndroid Build Coastguard Worker *dst++ = clamp24_from_float(*src++);
244*b9df5ad1SAndroid Build Coastguard Worker }
245*b9df5ad1SAndroid Build Coastguard Worker }
246*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_q8_23_from_p24(int32_t * dst,const uint8_t * src,size_t count)247*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_q8_23_from_p24(int32_t *dst, const uint8_t *src, size_t count)
248*b9df5ad1SAndroid Build Coastguard Worker {
249*b9df5ad1SAndroid Build Coastguard Worker dst += count;
250*b9df5ad1SAndroid Build Coastguard Worker src += count * 3;
251*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
252*b9df5ad1SAndroid Build Coastguard Worker src -= 3;
253*b9df5ad1SAndroid Build Coastguard Worker #if HAVE_BIG_ENDIAN
254*b9df5ad1SAndroid Build Coastguard Worker *--dst = (int8_t)src[0] << 16 | src[1] << 8 | src[2];
255*b9df5ad1SAndroid Build Coastguard Worker #else
256*b9df5ad1SAndroid Build Coastguard Worker *--dst = (int8_t)src[2] << 16 | src[1] << 8 | src[0];
257*b9df5ad1SAndroid Build Coastguard Worker #endif
258*b9df5ad1SAndroid Build Coastguard Worker }
259*b9df5ad1SAndroid Build Coastguard Worker }
260*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_q4_27_from_float(int32_t * dst,const float * src,size_t count)261*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_q4_27_from_float(int32_t *dst, const float *src, size_t count)
262*b9df5ad1SAndroid Build Coastguard Worker {
263*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
264*b9df5ad1SAndroid Build Coastguard Worker *dst++ = clampq4_27_from_float(*src++);
265*b9df5ad1SAndroid Build Coastguard Worker }
266*b9df5ad1SAndroid Build Coastguard Worker }
267*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i16_from_q8_23(int16_t * dst,const int32_t * src,size_t count)268*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i16_from_q8_23(int16_t *dst, const int32_t *src, size_t count)
269*b9df5ad1SAndroid Build Coastguard Worker {
270*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
271*b9df5ad1SAndroid Build Coastguard Worker *dst++ = clamp16(*src++ >> 8);
272*b9df5ad1SAndroid Build Coastguard Worker }
273*b9df5ad1SAndroid Build Coastguard Worker }
274*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_float_from_q8_23(float * dst,const int32_t * src,size_t count)275*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_float_from_q8_23(float *dst, const int32_t *src, size_t count)
276*b9df5ad1SAndroid Build Coastguard Worker {
277*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
278*b9df5ad1SAndroid Build Coastguard Worker *dst++ = float_from_q8_23(*src++);
279*b9df5ad1SAndroid Build Coastguard Worker }
280*b9df5ad1SAndroid Build Coastguard Worker }
281*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i32_from_u8(int32_t * dst,const uint8_t * src,size_t count)282*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i32_from_u8(int32_t *dst, const uint8_t *src, size_t count)
283*b9df5ad1SAndroid Build Coastguard Worker {
284*b9df5ad1SAndroid Build Coastguard Worker dst += count;
285*b9df5ad1SAndroid Build Coastguard Worker src += count;
286*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
287*b9df5ad1SAndroid Build Coastguard Worker *--dst = ((int32_t)(*--src) - 0x80) << 24;
288*b9df5ad1SAndroid Build Coastguard Worker }
289*b9df5ad1SAndroid Build Coastguard Worker }
290*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i32_from_i16(int32_t * dst,const int16_t * src,size_t count)291*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i32_from_i16(int32_t *dst, const int16_t *src, size_t count)
292*b9df5ad1SAndroid Build Coastguard Worker {
293*b9df5ad1SAndroid Build Coastguard Worker dst += count;
294*b9df5ad1SAndroid Build Coastguard Worker src += count;
295*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
296*b9df5ad1SAndroid Build Coastguard Worker *--dst = (int32_t)*--src << 16;
297*b9df5ad1SAndroid Build Coastguard Worker }
298*b9df5ad1SAndroid Build Coastguard Worker }
299*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_i32_from_float(int32_t * dst,const float * src,size_t count)300*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_i32_from_float(int32_t *dst, const float *src, size_t count)
301*b9df5ad1SAndroid Build Coastguard Worker {
302*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
303*b9df5ad1SAndroid Build Coastguard Worker *dst++ = clamp32_from_float(*src++);
304*b9df5ad1SAndroid Build Coastguard Worker }
305*b9df5ad1SAndroid Build Coastguard Worker }
306*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_float_from_i32(float * dst,const int32_t * src,size_t count)307*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_float_from_i32(float *dst, const int32_t *src, size_t count)
308*b9df5ad1SAndroid Build Coastguard Worker {
309*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
310*b9df5ad1SAndroid Build Coastguard Worker *dst++ = float_from_i32(*src++);
311*b9df5ad1SAndroid Build Coastguard Worker }
312*b9df5ad1SAndroid Build Coastguard Worker }
313*b9df5ad1SAndroid Build Coastguard Worker
memcpy_to_float_from_float_with_clamping(float * dst,const float * src,size_t count,float absMax)314*b9df5ad1SAndroid Build Coastguard Worker void memcpy_to_float_from_float_with_clamping(float *dst, const float *src, size_t count,
315*b9df5ad1SAndroid Build Coastguard Worker float absMax) {
316*b9df5ad1SAndroid Build Coastguard Worker // Note: using NEON intrinsics (vminq_f32, vld1q_f32...) did NOT accelerate
317*b9df5ad1SAndroid Build Coastguard Worker // the function when benchmarked. The compiler already vectorize using FMINNM f32x4 & similar.
318*b9df5ad1SAndroid Build Coastguard Worker // Note: clamping induce a ~20% overhead compared to memcpy for count in [64, 512]
319*b9df5ad1SAndroid Build Coastguard Worker // See primitives_benchmark
320*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
321*b9df5ad1SAndroid Build Coastguard Worker const float sample = *src++;
322*b9df5ad1SAndroid Build Coastguard Worker *dst++ = fmax(-absMax, fmin(absMax, sample));
323*b9df5ad1SAndroid Build Coastguard Worker }
324*b9df5ad1SAndroid Build Coastguard Worker }
325*b9df5ad1SAndroid Build Coastguard Worker
downmix_to_mono_i16_from_stereo_i16(int16_t * dst,const int16_t * src,size_t count)326*b9df5ad1SAndroid Build Coastguard Worker void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count)
327*b9df5ad1SAndroid Build Coastguard Worker {
328*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
329*b9df5ad1SAndroid Build Coastguard Worker *dst++ = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
330*b9df5ad1SAndroid Build Coastguard Worker src += 2;
331*b9df5ad1SAndroid Build Coastguard Worker }
332*b9df5ad1SAndroid Build Coastguard Worker }
333*b9df5ad1SAndroid Build Coastguard Worker
upmix_to_stereo_i16_from_mono_i16(int16_t * dst,const int16_t * src,size_t count)334*b9df5ad1SAndroid Build Coastguard Worker void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count)
335*b9df5ad1SAndroid Build Coastguard Worker {
336*b9df5ad1SAndroid Build Coastguard Worker dst += count * 2;
337*b9df5ad1SAndroid Build Coastguard Worker src += count;
338*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
339*b9df5ad1SAndroid Build Coastguard Worker const int32_t temp = *--src;
340*b9df5ad1SAndroid Build Coastguard Worker dst -= 2;
341*b9df5ad1SAndroid Build Coastguard Worker dst[0] = temp;
342*b9df5ad1SAndroid Build Coastguard Worker dst[1] = temp;
343*b9df5ad1SAndroid Build Coastguard Worker }
344*b9df5ad1SAndroid Build Coastguard Worker }
345*b9df5ad1SAndroid Build Coastguard Worker
downmix_to_mono_float_from_stereo_float(float * dst,const float * src,size_t frames)346*b9df5ad1SAndroid Build Coastguard Worker void downmix_to_mono_float_from_stereo_float(float *dst, const float *src, size_t frames)
347*b9df5ad1SAndroid Build Coastguard Worker {
348*b9df5ad1SAndroid Build Coastguard Worker for (; frames > 0; --frames) {
349*b9df5ad1SAndroid Build Coastguard Worker *dst++ = (src[0] + src[1]) * 0.5;
350*b9df5ad1SAndroid Build Coastguard Worker src += 2;
351*b9df5ad1SAndroid Build Coastguard Worker }
352*b9df5ad1SAndroid Build Coastguard Worker }
353*b9df5ad1SAndroid Build Coastguard Worker
upmix_to_stereo_float_from_mono_float(float * dst,const float * src,size_t frames)354*b9df5ad1SAndroid Build Coastguard Worker void upmix_to_stereo_float_from_mono_float(float *dst, const float *src, size_t frames)
355*b9df5ad1SAndroid Build Coastguard Worker {
356*b9df5ad1SAndroid Build Coastguard Worker dst += frames * 2;
357*b9df5ad1SAndroid Build Coastguard Worker src += frames;
358*b9df5ad1SAndroid Build Coastguard Worker for (; frames > 0; --frames) {
359*b9df5ad1SAndroid Build Coastguard Worker const float temp = *--src;
360*b9df5ad1SAndroid Build Coastguard Worker dst -= 2;
361*b9df5ad1SAndroid Build Coastguard Worker dst[0] = temp;
362*b9df5ad1SAndroid Build Coastguard Worker dst[1] = temp;
363*b9df5ad1SAndroid Build Coastguard Worker }
364*b9df5ad1SAndroid Build Coastguard Worker }
365*b9df5ad1SAndroid Build Coastguard Worker
nonZeroMono32(const int32_t * samples,size_t count)366*b9df5ad1SAndroid Build Coastguard Worker size_t nonZeroMono32(const int32_t *samples, size_t count)
367*b9df5ad1SAndroid Build Coastguard Worker {
368*b9df5ad1SAndroid Build Coastguard Worker size_t nonZero = 0;
369*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
370*b9df5ad1SAndroid Build Coastguard Worker nonZero += *samples++ != 0;
371*b9df5ad1SAndroid Build Coastguard Worker }
372*b9df5ad1SAndroid Build Coastguard Worker return nonZero;
373*b9df5ad1SAndroid Build Coastguard Worker }
374*b9df5ad1SAndroid Build Coastguard Worker
nonZeroMono16(const int16_t * samples,size_t count)375*b9df5ad1SAndroid Build Coastguard Worker size_t nonZeroMono16(const int16_t *samples, size_t count)
376*b9df5ad1SAndroid Build Coastguard Worker {
377*b9df5ad1SAndroid Build Coastguard Worker size_t nonZero = 0;
378*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
379*b9df5ad1SAndroid Build Coastguard Worker nonZero += *samples++ != 0;
380*b9df5ad1SAndroid Build Coastguard Worker }
381*b9df5ad1SAndroid Build Coastguard Worker return nonZero;
382*b9df5ad1SAndroid Build Coastguard Worker }
383*b9df5ad1SAndroid Build Coastguard Worker
nonZeroStereo32(const int32_t * frames,size_t count)384*b9df5ad1SAndroid Build Coastguard Worker size_t nonZeroStereo32(const int32_t *frames, size_t count)
385*b9df5ad1SAndroid Build Coastguard Worker {
386*b9df5ad1SAndroid Build Coastguard Worker size_t nonZero = 0;
387*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
388*b9df5ad1SAndroid Build Coastguard Worker nonZero += frames[0] != 0 || frames[1] != 0;
389*b9df5ad1SAndroid Build Coastguard Worker frames += 2;
390*b9df5ad1SAndroid Build Coastguard Worker }
391*b9df5ad1SAndroid Build Coastguard Worker return nonZero;
392*b9df5ad1SAndroid Build Coastguard Worker }
393*b9df5ad1SAndroid Build Coastguard Worker
nonZeroStereo16(const int16_t * frames,size_t count)394*b9df5ad1SAndroid Build Coastguard Worker size_t nonZeroStereo16(const int16_t *frames, size_t count)
395*b9df5ad1SAndroid Build Coastguard Worker {
396*b9df5ad1SAndroid Build Coastguard Worker size_t nonZero = 0;
397*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
398*b9df5ad1SAndroid Build Coastguard Worker nonZero += frames[0] != 0 || frames[1] != 0;
399*b9df5ad1SAndroid Build Coastguard Worker frames += 2;
400*b9df5ad1SAndroid Build Coastguard Worker }
401*b9df5ad1SAndroid Build Coastguard Worker return nonZero;
402*b9df5ad1SAndroid Build Coastguard Worker }
403*b9df5ad1SAndroid Build Coastguard Worker
404*b9df5ad1SAndroid Build Coastguard Worker /*
405*b9df5ad1SAndroid Build Coastguard Worker * C macro to do channel mask copying independent of dst/src sample type.
406*b9df5ad1SAndroid Build Coastguard Worker * Don't pass in any expressions for the macro arguments here.
407*b9df5ad1SAndroid Build Coastguard Worker */
408*b9df5ad1SAndroid Build Coastguard Worker #define copy_frame_by_mask(dst, dmask, src, smask, count, zero) \
409*b9df5ad1SAndroid Build Coastguard Worker { \
410*b9df5ad1SAndroid Build Coastguard Worker uint32_t bit, ormask; \
411*b9df5ad1SAndroid Build Coastguard Worker for (; (count) > 0; --(count)) { \
412*b9df5ad1SAndroid Build Coastguard Worker ormask = (dmask) | (smask); \
413*b9df5ad1SAndroid Build Coastguard Worker while (ormask) { \
414*b9df5ad1SAndroid Build Coastguard Worker bit = ormask & -ormask; /* get lowest bit */ \
415*b9df5ad1SAndroid Build Coastguard Worker ormask ^= bit; /* remove lowest bit */ \
416*b9df5ad1SAndroid Build Coastguard Worker if ((dmask) & bit) { \
417*b9df5ad1SAndroid Build Coastguard Worker *(dst)++ = (smask) & bit ? *(src)++ : (zero); \
418*b9df5ad1SAndroid Build Coastguard Worker } else { /* source channel only */ \
419*b9df5ad1SAndroid Build Coastguard Worker ++(src); \
420*b9df5ad1SAndroid Build Coastguard Worker } \
421*b9df5ad1SAndroid Build Coastguard Worker } \
422*b9df5ad1SAndroid Build Coastguard Worker } \
423*b9df5ad1SAndroid Build Coastguard Worker }
424*b9df5ad1SAndroid Build Coastguard Worker
memcpy_by_channel_mask(void * dst,uint32_t dst_mask,const void * src,uint32_t src_mask,size_t sample_size,size_t count)425*b9df5ad1SAndroid Build Coastguard Worker void memcpy_by_channel_mask(void *dst, uint32_t dst_mask,
426*b9df5ad1SAndroid Build Coastguard Worker const void *src, uint32_t src_mask, size_t sample_size, size_t count)
427*b9df5ad1SAndroid Build Coastguard Worker {
428*b9df5ad1SAndroid Build Coastguard Worker #if 0
429*b9df5ad1SAndroid Build Coastguard Worker /* alternate way of handling memcpy_by_channel_mask by using the idxary */
430*b9df5ad1SAndroid Build Coastguard Worker int8_t idxary[32];
431*b9df5ad1SAndroid Build Coastguard Worker uint32_t src_channels = __builtin_popcount(src_mask);
432*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_channels =
433*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask);
434*b9df5ad1SAndroid Build Coastguard Worker
435*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_idxary(dst, dst_channels, src, src_channels, idxary, sample_size, count);
436*b9df5ad1SAndroid Build Coastguard Worker #else
437*b9df5ad1SAndroid Build Coastguard Worker if (dst_mask == src_mask) {
438*b9df5ad1SAndroid Build Coastguard Worker memcpy(dst, src, sample_size * __builtin_popcount(dst_mask) * count);
439*b9df5ad1SAndroid Build Coastguard Worker return;
440*b9df5ad1SAndroid Build Coastguard Worker }
441*b9df5ad1SAndroid Build Coastguard Worker switch (sample_size) {
442*b9df5ad1SAndroid Build Coastguard Worker case 1: {
443*b9df5ad1SAndroid Build Coastguard Worker uint8_t *udst = (uint8_t*)dst;
444*b9df5ad1SAndroid Build Coastguard Worker const uint8_t *usrc = (const uint8_t*)src;
445*b9df5ad1SAndroid Build Coastguard Worker
446*b9df5ad1SAndroid Build Coastguard Worker copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
447*b9df5ad1SAndroid Build Coastguard Worker } break;
448*b9df5ad1SAndroid Build Coastguard Worker case 2: {
449*b9df5ad1SAndroid Build Coastguard Worker uint16_t *udst = (uint16_t*)dst;
450*b9df5ad1SAndroid Build Coastguard Worker const uint16_t *usrc = (const uint16_t*)src;
451*b9df5ad1SAndroid Build Coastguard Worker
452*b9df5ad1SAndroid Build Coastguard Worker copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
453*b9df5ad1SAndroid Build Coastguard Worker } break;
454*b9df5ad1SAndroid Build Coastguard Worker case 3: { /* could be slow. use a struct to represent 3 bytes of data. */
455*b9df5ad1SAndroid Build Coastguard Worker uint8x3_t *udst = (uint8x3_t*)dst;
456*b9df5ad1SAndroid Build Coastguard Worker const uint8x3_t *usrc = (const uint8x3_t*)src;
457*b9df5ad1SAndroid Build Coastguard Worker static const uint8x3_t zero; /* tricky - we use this to zero out a sample */
458*b9df5ad1SAndroid Build Coastguard Worker
459*b9df5ad1SAndroid Build Coastguard Worker copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, zero);
460*b9df5ad1SAndroid Build Coastguard Worker } break;
461*b9df5ad1SAndroid Build Coastguard Worker case 4: {
462*b9df5ad1SAndroid Build Coastguard Worker uint32_t *udst = (uint32_t*)dst;
463*b9df5ad1SAndroid Build Coastguard Worker const uint32_t *usrc = (const uint32_t*)src;
464*b9df5ad1SAndroid Build Coastguard Worker
465*b9df5ad1SAndroid Build Coastguard Worker copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0);
466*b9df5ad1SAndroid Build Coastguard Worker } break;
467*b9df5ad1SAndroid Build Coastguard Worker default:
468*b9df5ad1SAndroid Build Coastguard Worker abort(); /* illegal value */
469*b9df5ad1SAndroid Build Coastguard Worker break;
470*b9df5ad1SAndroid Build Coastguard Worker }
471*b9df5ad1SAndroid Build Coastguard Worker #endif
472*b9df5ad1SAndroid Build Coastguard Worker }
473*b9df5ad1SAndroid Build Coastguard Worker
474*b9df5ad1SAndroid Build Coastguard Worker /*
475*b9df5ad1SAndroid Build Coastguard Worker * C macro to do copying by index array, to rearrange samples
476*b9df5ad1SAndroid Build Coastguard Worker * within a frame. This is independent of src/dst sample type.
477*b9df5ad1SAndroid Build Coastguard Worker * Don't pass in any expressions for the macro arguments here.
478*b9df5ad1SAndroid Build Coastguard Worker */
479*b9df5ad1SAndroid Build Coastguard Worker #define copy_frame_by_idx(dst, dst_channels, src, src_channels, idxary, count, zero) \
480*b9df5ad1SAndroid Build Coastguard Worker { \
481*b9df5ad1SAndroid Build Coastguard Worker unsigned i; \
482*b9df5ad1SAndroid Build Coastguard Worker int index; \
483*b9df5ad1SAndroid Build Coastguard Worker for (; (count) > 0; --(count)) { \
484*b9df5ad1SAndroid Build Coastguard Worker for (i = 0; i < (dst_channels); ++i) { \
485*b9df5ad1SAndroid Build Coastguard Worker index = (idxary)[i]; \
486*b9df5ad1SAndroid Build Coastguard Worker *(dst)++ = index < 0 ? (zero) : (src)[index]; \
487*b9df5ad1SAndroid Build Coastguard Worker } \
488*b9df5ad1SAndroid Build Coastguard Worker (src) += (src_channels); \
489*b9df5ad1SAndroid Build Coastguard Worker } \
490*b9df5ad1SAndroid Build Coastguard Worker }
491*b9df5ad1SAndroid Build Coastguard Worker
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)492*b9df5ad1SAndroid Build Coastguard Worker void memcpy_by_index_array(void *dst, uint32_t dst_channels,
493*b9df5ad1SAndroid Build Coastguard Worker const void *src, uint32_t src_channels,
494*b9df5ad1SAndroid Build Coastguard Worker const int8_t *idxary, size_t sample_size, size_t count)
495*b9df5ad1SAndroid Build Coastguard Worker {
496*b9df5ad1SAndroid Build Coastguard Worker switch (sample_size) {
497*b9df5ad1SAndroid Build Coastguard Worker case 1: {
498*b9df5ad1SAndroid Build Coastguard Worker uint8_t *udst = (uint8_t*)dst;
499*b9df5ad1SAndroid Build Coastguard Worker const uint8_t *usrc = (const uint8_t*)src;
500*b9df5ad1SAndroid Build Coastguard Worker
501*b9df5ad1SAndroid Build Coastguard Worker copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
502*b9df5ad1SAndroid Build Coastguard Worker } break;
503*b9df5ad1SAndroid Build Coastguard Worker case 2: {
504*b9df5ad1SAndroid Build Coastguard Worker uint16_t *udst = (uint16_t*)dst;
505*b9df5ad1SAndroid Build Coastguard Worker const uint16_t *usrc = (const uint16_t*)src;
506*b9df5ad1SAndroid Build Coastguard Worker
507*b9df5ad1SAndroid Build Coastguard Worker copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
508*b9df5ad1SAndroid Build Coastguard Worker } break;
509*b9df5ad1SAndroid Build Coastguard Worker case 3: { /* could be slow. use a struct to represent 3 bytes of data. */
510*b9df5ad1SAndroid Build Coastguard Worker uint8x3_t *udst = (uint8x3_t*)dst;
511*b9df5ad1SAndroid Build Coastguard Worker const uint8x3_t *usrc = (const uint8x3_t*)src;
512*b9df5ad1SAndroid Build Coastguard Worker static const uint8x3_t zero;
513*b9df5ad1SAndroid Build Coastguard Worker
514*b9df5ad1SAndroid Build Coastguard Worker copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, zero);
515*b9df5ad1SAndroid Build Coastguard Worker } break;
516*b9df5ad1SAndroid Build Coastguard Worker case 4: {
517*b9df5ad1SAndroid Build Coastguard Worker uint32_t *udst = (uint32_t*)dst;
518*b9df5ad1SAndroid Build Coastguard Worker const uint32_t *usrc = (const uint32_t*)src;
519*b9df5ad1SAndroid Build Coastguard Worker
520*b9df5ad1SAndroid Build Coastguard Worker copy_frame_by_idx(udst, dst_channels, usrc, src_channels, idxary, count, 0);
521*b9df5ad1SAndroid Build Coastguard Worker } break;
522*b9df5ad1SAndroid Build Coastguard Worker default:
523*b9df5ad1SAndroid Build Coastguard Worker abort(); /* illegal value */
524*b9df5ad1SAndroid Build Coastguard Worker break;
525*b9df5ad1SAndroid Build Coastguard Worker }
526*b9df5ad1SAndroid Build Coastguard Worker }
527*b9df5ad1SAndroid Build Coastguard Worker
memcpy_by_index_array_initialization(int8_t * idxary,size_t idxcount,uint32_t dst_mask,uint32_t src_mask)528*b9df5ad1SAndroid Build Coastguard Worker size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
529*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_mask, uint32_t src_mask)
530*b9df5ad1SAndroid Build Coastguard Worker {
531*b9df5ad1SAndroid Build Coastguard Worker size_t n = 0;
532*b9df5ad1SAndroid Build Coastguard Worker int srcidx = 0;
533*b9df5ad1SAndroid Build Coastguard Worker uint32_t bit, ormask = src_mask | dst_mask;
534*b9df5ad1SAndroid Build Coastguard Worker
535*b9df5ad1SAndroid Build Coastguard Worker while (ormask && n < idxcount) {
536*b9df5ad1SAndroid Build Coastguard Worker bit = ormask & -ormask; /* get lowest bit */
537*b9df5ad1SAndroid Build Coastguard Worker ormask ^= bit; /* remove lowest bit */
538*b9df5ad1SAndroid Build Coastguard Worker if (src_mask & dst_mask & bit) { /* matching channel */
539*b9df5ad1SAndroid Build Coastguard Worker idxary[n++] = srcidx++;
540*b9df5ad1SAndroid Build Coastguard Worker } else if (src_mask & bit) { /* source channel only */
541*b9df5ad1SAndroid Build Coastguard Worker ++srcidx;
542*b9df5ad1SAndroid Build Coastguard Worker } else { /* destination channel only */
543*b9df5ad1SAndroid Build Coastguard Worker idxary[n++] = -1;
544*b9df5ad1SAndroid Build Coastguard Worker }
545*b9df5ad1SAndroid Build Coastguard Worker }
546*b9df5ad1SAndroid Build Coastguard Worker return n + __builtin_popcount(ormask & dst_mask);
547*b9df5ad1SAndroid Build Coastguard Worker }
548*b9df5ad1SAndroid Build Coastguard Worker
memcpy_by_index_array_initialization_src_index(int8_t * idxary,size_t idxcount,uint32_t dst_mask,uint32_t src_mask)549*b9df5ad1SAndroid Build Coastguard Worker size_t memcpy_by_index_array_initialization_src_index(int8_t *idxary, size_t idxcount,
550*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_mask, uint32_t src_mask) {
551*b9df5ad1SAndroid Build Coastguard Worker size_t dst_count = __builtin_popcount(dst_mask);
552*b9df5ad1SAndroid Build Coastguard Worker if (idxcount == 0) {
553*b9df5ad1SAndroid Build Coastguard Worker return dst_count;
554*b9df5ad1SAndroid Build Coastguard Worker }
555*b9df5ad1SAndroid Build Coastguard Worker if (dst_count > idxcount) {
556*b9df5ad1SAndroid Build Coastguard Worker dst_count = idxcount;
557*b9df5ad1SAndroid Build Coastguard Worker }
558*b9df5ad1SAndroid Build Coastguard Worker
559*b9df5ad1SAndroid Build Coastguard Worker size_t src_idx, dst_idx;
560*b9df5ad1SAndroid Build Coastguard Worker for (src_idx = 0, dst_idx = 0; dst_idx < dst_count; ++dst_idx) {
561*b9df5ad1SAndroid Build Coastguard Worker if (src_mask & 1) {
562*b9df5ad1SAndroid Build Coastguard Worker idxary[dst_idx] = src_idx++;
563*b9df5ad1SAndroid Build Coastguard Worker } else {
564*b9df5ad1SAndroid Build Coastguard Worker idxary[dst_idx] = -1;
565*b9df5ad1SAndroid Build Coastguard Worker }
566*b9df5ad1SAndroid Build Coastguard Worker src_mask >>= 1;
567*b9df5ad1SAndroid Build Coastguard Worker }
568*b9df5ad1SAndroid Build Coastguard Worker return dst_idx;
569*b9df5ad1SAndroid Build Coastguard Worker }
570*b9df5ad1SAndroid Build Coastguard Worker
memcpy_by_index_array_initialization_dst_index(int8_t * idxary,size_t idxcount,uint32_t dst_mask,uint32_t src_mask)571*b9df5ad1SAndroid Build Coastguard Worker size_t memcpy_by_index_array_initialization_dst_index(int8_t *idxary, size_t idxcount,
572*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_mask, uint32_t src_mask) {
573*b9df5ad1SAndroid Build Coastguard Worker size_t src_idx, dst_idx;
574*b9df5ad1SAndroid Build Coastguard Worker size_t dst_count = __builtin_popcount(dst_mask);
575*b9df5ad1SAndroid Build Coastguard Worker size_t src_count = __builtin_popcount(src_mask);
576*b9df5ad1SAndroid Build Coastguard Worker if (idxcount == 0) {
577*b9df5ad1SAndroid Build Coastguard Worker return dst_count;
578*b9df5ad1SAndroid Build Coastguard Worker }
579*b9df5ad1SAndroid Build Coastguard Worker if (dst_count > idxcount) {
580*b9df5ad1SAndroid Build Coastguard Worker dst_count = idxcount;
581*b9df5ad1SAndroid Build Coastguard Worker }
582*b9df5ad1SAndroid Build Coastguard Worker for (src_idx = 0, dst_idx = 0; dst_idx < dst_count; ++src_idx) {
583*b9df5ad1SAndroid Build Coastguard Worker if (dst_mask & 1) {
584*b9df5ad1SAndroid Build Coastguard Worker idxary[dst_idx++] = src_idx < src_count ? (signed)src_idx : -1;
585*b9df5ad1SAndroid Build Coastguard Worker }
586*b9df5ad1SAndroid Build Coastguard Worker dst_mask >>= 1;
587*b9df5ad1SAndroid Build Coastguard Worker }
588*b9df5ad1SAndroid Build Coastguard Worker return dst_idx;
589*b9df5ad1SAndroid Build Coastguard Worker }
590*b9df5ad1SAndroid Build Coastguard Worker
accumulate_i16(int16_t * dst,const int16_t * src,size_t count)591*b9df5ad1SAndroid Build Coastguard Worker void accumulate_i16(int16_t *dst, const int16_t *src, size_t count) {
592*b9df5ad1SAndroid Build Coastguard Worker while (count--) {
593*b9df5ad1SAndroid Build Coastguard Worker *dst = clamp16((int32_t)*dst + *src++);
594*b9df5ad1SAndroid Build Coastguard Worker ++dst;
595*b9df5ad1SAndroid Build Coastguard Worker }
596*b9df5ad1SAndroid Build Coastguard Worker }
597*b9df5ad1SAndroid Build Coastguard Worker
accumulate_u8(uint8_t * dst,const uint8_t * src,size_t count)598*b9df5ad1SAndroid Build Coastguard Worker void accumulate_u8(uint8_t *dst, const uint8_t *src, size_t count) {
599*b9df5ad1SAndroid Build Coastguard Worker int32_t sum;
600*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
601*b9df5ad1SAndroid Build Coastguard Worker // 8-bit samples are centered around 0x80.
602*b9df5ad1SAndroid Build Coastguard Worker sum = *dst + *src++ - 0x80;
603*b9df5ad1SAndroid Build Coastguard Worker // Clamp to [0, 0xff].
604*b9df5ad1SAndroid Build Coastguard Worker *dst++ = (sum & 0x100) ? (~sum >> 9) : sum;
605*b9df5ad1SAndroid Build Coastguard Worker }
606*b9df5ad1SAndroid Build Coastguard Worker }
607*b9df5ad1SAndroid Build Coastguard Worker
accumulate_p24(uint8_t * dst,const uint8_t * src,size_t count)608*b9df5ad1SAndroid Build Coastguard Worker void accumulate_p24(uint8_t *dst, const uint8_t *src, size_t count) {
609*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
610*b9df5ad1SAndroid Build Coastguard Worker // Unpack.
611*b9df5ad1SAndroid Build Coastguard Worker int32_t dst_q8_23 = 0;
612*b9df5ad1SAndroid Build Coastguard Worker int32_t src_q8_23 = 0;
613*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_p24(&dst_q8_23, dst, 1);
614*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_p24(&src_q8_23, src, 1);
615*b9df5ad1SAndroid Build Coastguard Worker
616*b9df5ad1SAndroid Build Coastguard Worker // Accumulate and overwrite.
617*b9df5ad1SAndroid Build Coastguard Worker dst_q8_23 += src_q8_23;
618*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_q8_23(dst, &dst_q8_23, 1);
619*b9df5ad1SAndroid Build Coastguard Worker
620*b9df5ad1SAndroid Build Coastguard Worker // Move on to next sample.
621*b9df5ad1SAndroid Build Coastguard Worker dst += 3;
622*b9df5ad1SAndroid Build Coastguard Worker src += 3;
623*b9df5ad1SAndroid Build Coastguard Worker }
624*b9df5ad1SAndroid Build Coastguard Worker }
625*b9df5ad1SAndroid Build Coastguard Worker
accumulate_q8_23(int32_t * dst,const int32_t * src,size_t count)626*b9df5ad1SAndroid Build Coastguard Worker void accumulate_q8_23(int32_t *dst, const int32_t *src, size_t count) {
627*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
628*b9df5ad1SAndroid Build Coastguard Worker *dst = clamp24_from_q8_23(*dst + *src++);
629*b9df5ad1SAndroid Build Coastguard Worker ++dst;
630*b9df5ad1SAndroid Build Coastguard Worker }
631*b9df5ad1SAndroid Build Coastguard Worker }
632*b9df5ad1SAndroid Build Coastguard Worker
accumulate_i32(int32_t * dst,const int32_t * src,size_t count)633*b9df5ad1SAndroid Build Coastguard Worker void accumulate_i32(int32_t *dst, const int32_t *src, size_t count) {
634*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
635*b9df5ad1SAndroid Build Coastguard Worker *dst = clamp32((int64_t)*dst + *src++);
636*b9df5ad1SAndroid Build Coastguard Worker ++dst;
637*b9df5ad1SAndroid Build Coastguard Worker }
638*b9df5ad1SAndroid Build Coastguard Worker }
639*b9df5ad1SAndroid Build Coastguard Worker
accumulate_float(float * dst,const float * src,size_t count)640*b9df5ad1SAndroid Build Coastguard Worker void accumulate_float(float *dst, const float *src, size_t count) {
641*b9df5ad1SAndroid Build Coastguard Worker for (; count > 0; --count) {
642*b9df5ad1SAndroid Build Coastguard Worker *dst++ += *src++;
643*b9df5ad1SAndroid Build Coastguard Worker }
644*b9df5ad1SAndroid Build Coastguard Worker }
645