1*b9df5ad1SAndroid Build Coastguard Worker /*
2*b9df5ad1SAndroid Build Coastguard Worker * Copyright (C) 2014 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 <math.h>
18*b9df5ad1SAndroid Build Coastguard Worker #include <vector>
19*b9df5ad1SAndroid Build Coastguard Worker
20*b9df5ad1SAndroid Build Coastguard Worker #include <gtest/gtest.h>
21*b9df5ad1SAndroid Build Coastguard Worker
22*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/primitives.h>
23*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/format.h>
24*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/channels.h>
25*b9df5ad1SAndroid Build Coastguard Worker
26*b9df5ad1SAndroid Build Coastguard Worker #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
27*b9df5ad1SAndroid Build Coastguard Worker
28*b9df5ad1SAndroid Build Coastguard Worker static const int32_t lim8pos = 255;
29*b9df5ad1SAndroid Build Coastguard Worker static const int32_t lim8neg = 0;
30*b9df5ad1SAndroid Build Coastguard Worker static const int32_t lim16pos = (1 << 15) - 1;
31*b9df5ad1SAndroid Build Coastguard Worker static const int32_t lim16neg = -(1 << 15);
32*b9df5ad1SAndroid Build Coastguard Worker static const int32_t lim24pos = (1 << 23) - 1;
33*b9df5ad1SAndroid Build Coastguard Worker static const int32_t lim24neg = -(1 << 23);
34*b9df5ad1SAndroid Build Coastguard Worker static const int64_t lim32pos = 0x000000007fffffff;
35*b9df5ad1SAndroid Build Coastguard Worker static const int64_t lim32neg = 0xffffffff80000000;
36*b9df5ad1SAndroid Build Coastguard Worker
37*b9df5ad1SAndroid Build Coastguard Worker // Use memset here since it is generally the fastest method of clearing data,
38*b9df5ad1SAndroid Build Coastguard Worker // but could be changed to std::fill or assignment should those prove faster.
39*b9df5ad1SAndroid Build Coastguard Worker template <typename T>
zeroFill(T & container)40*b9df5ad1SAndroid Build Coastguard Worker static void zeroFill(T &container) {
41*b9df5ad1SAndroid Build Coastguard Worker memset(container.data(), 0, container.size() * sizeof(container[0]));
42*b9df5ad1SAndroid Build Coastguard Worker }
43*b9df5ad1SAndroid Build Coastguard Worker
testClamp8(float f)44*b9df5ad1SAndroid Build Coastguard Worker inline void testClamp8(float f)
45*b9df5ad1SAndroid Build Coastguard Worker {
46*b9df5ad1SAndroid Build Coastguard Worker // f is in native u8 scaling to test rounding
47*b9df5ad1SAndroid Build Coastguard Worker uint8_t uval = clamp8_from_float((f - 128) / (1 << 7));
48*b9df5ad1SAndroid Build Coastguard Worker
49*b9df5ad1SAndroid Build Coastguard Worker // test clamping
50*b9df5ad1SAndroid Build Coastguard Worker if (f > lim8pos) {
51*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(lim8pos, uval);
52*b9df5ad1SAndroid Build Coastguard Worker } else if (f < lim8neg) {
53*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(lim8neg, uval);
54*b9df5ad1SAndroid Build Coastguard Worker }
55*b9df5ad1SAndroid Build Coastguard Worker
56*b9df5ad1SAndroid Build Coastguard Worker // if in range, make sure round trip clamp and conversion is correct.
57*b9df5ad1SAndroid Build Coastguard Worker if (f < lim8pos - 1. && f > lim8neg + 1.) {
58*b9df5ad1SAndroid Build Coastguard Worker uint8_t uval2 = clamp8_from_float(float_from_u8(uval));
59*b9df5ad1SAndroid Build Coastguard Worker int diff = abs(uval - uval2);
60*b9df5ad1SAndroid Build Coastguard Worker EXPECT_LE(diff, 1);
61*b9df5ad1SAndroid Build Coastguard Worker }
62*b9df5ad1SAndroid Build Coastguard Worker }
63*b9df5ad1SAndroid Build Coastguard Worker
testClamp16(float f)64*b9df5ad1SAndroid Build Coastguard Worker inline void testClamp16(float f)
65*b9df5ad1SAndroid Build Coastguard Worker {
66*b9df5ad1SAndroid Build Coastguard Worker int16_t ival = clamp16_from_float(f / (1 << 15));
67*b9df5ad1SAndroid Build Coastguard Worker
68*b9df5ad1SAndroid Build Coastguard Worker // test clamping
69*b9df5ad1SAndroid Build Coastguard Worker if (f > lim16pos) {
70*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(lim16pos, ival);
71*b9df5ad1SAndroid Build Coastguard Worker } else if (f < lim16neg) {
72*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(lim16neg, ival);
73*b9df5ad1SAndroid Build Coastguard Worker }
74*b9df5ad1SAndroid Build Coastguard Worker
75*b9df5ad1SAndroid Build Coastguard Worker // if in range, make sure round trip clamp and conversion is correct.
76*b9df5ad1SAndroid Build Coastguard Worker if (f < lim16pos - 1. && f > lim16neg + 1.) {
77*b9df5ad1SAndroid Build Coastguard Worker int ival2 = clamp16_from_float(float_from_i16(ival));
78*b9df5ad1SAndroid Build Coastguard Worker int diff = abs(ival - ival2);
79*b9df5ad1SAndroid Build Coastguard Worker EXPECT_LE(diff, 1);
80*b9df5ad1SAndroid Build Coastguard Worker }
81*b9df5ad1SAndroid Build Coastguard Worker }
82*b9df5ad1SAndroid Build Coastguard Worker
testClamp24(float f)83*b9df5ad1SAndroid Build Coastguard Worker inline void testClamp24(float f)
84*b9df5ad1SAndroid Build Coastguard Worker {
85*b9df5ad1SAndroid Build Coastguard Worker int32_t ival = clamp24_from_float(f / (1 << 23));
86*b9df5ad1SAndroid Build Coastguard Worker
87*b9df5ad1SAndroid Build Coastguard Worker // test clamping
88*b9df5ad1SAndroid Build Coastguard Worker if (f > lim24pos) {
89*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(lim24pos, ival);
90*b9df5ad1SAndroid Build Coastguard Worker } else if (f < lim24neg) {
91*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(lim24neg, ival);
92*b9df5ad1SAndroid Build Coastguard Worker }
93*b9df5ad1SAndroid Build Coastguard Worker
94*b9df5ad1SAndroid Build Coastguard Worker // if in range, make sure round trip clamp and conversion is correct.
95*b9df5ad1SAndroid Build Coastguard Worker if (f < lim24pos - 1. && f > lim24neg + 1.) {
96*b9df5ad1SAndroid Build Coastguard Worker int ival2 = clamp24_from_float(float_from_q8_23(ival));
97*b9df5ad1SAndroid Build Coastguard Worker int diff = abs(ival - ival2);
98*b9df5ad1SAndroid Build Coastguard Worker EXPECT_LE(diff, 1);
99*b9df5ad1SAndroid Build Coastguard Worker }
100*b9df5ad1SAndroid Build Coastguard Worker }
101*b9df5ad1SAndroid Build Coastguard Worker
102*b9df5ad1SAndroid Build Coastguard Worker template<typename T>
checkMonotone(const T * ary,size_t size)103*b9df5ad1SAndroid Build Coastguard Worker void checkMonotone(const T *ary, size_t size)
104*b9df5ad1SAndroid Build Coastguard Worker {
105*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 1; i < size; ++i) {
106*b9df5ad1SAndroid Build Coastguard Worker EXPECT_LT(ary[i-1], ary[i]);
107*b9df5ad1SAndroid Build Coastguard Worker }
108*b9df5ad1SAndroid Build Coastguard Worker }
109*b9df5ad1SAndroid Build Coastguard Worker
checkMonotonep24(uint8_t * pary,size_t size)110*b9df5ad1SAndroid Build Coastguard Worker void checkMonotonep24(uint8_t * pary, size_t size)
111*b9df5ad1SAndroid Build Coastguard Worker {
112*b9df5ad1SAndroid Build Coastguard Worker size_t frames = size/3;
113*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 1; i < frames; ++i) {
114*b9df5ad1SAndroid Build Coastguard Worker EXPECT_LT(i32_from_p24(pary + 3*(i-1)), i32_from_p24(pary + 3*i));
115*b9df5ad1SAndroid Build Coastguard Worker }
116*b9df5ad1SAndroid Build Coastguard Worker }
117*b9df5ad1SAndroid Build Coastguard Worker
TEST(audio_utils_primitives,clamp_to_int)118*b9df5ad1SAndroid Build Coastguard Worker TEST(audio_utils_primitives, clamp_to_int) {
119*b9df5ad1SAndroid Build Coastguard Worker static const float testArray[] = {
120*b9df5ad1SAndroid Build Coastguard Worker -NAN, -INFINITY,
121*b9df5ad1SAndroid Build Coastguard Worker -1.e20, -32768., 63.9,
122*b9df5ad1SAndroid Build Coastguard Worker -3.5, -3.4, -2.5, 2.4, -1.5, -1.4, -0.5, -0.2, 0., 0.2, 0.5, 0.8,
123*b9df5ad1SAndroid Build Coastguard Worker 1.4, 1.5, 1.8, 2.4, 2.5, 2.6, 3.4, 3.5,
124*b9df5ad1SAndroid Build Coastguard Worker 32767., 32768., 1.e20,
125*b9df5ad1SAndroid Build Coastguard Worker INFINITY, NAN };
126*b9df5ad1SAndroid Build Coastguard Worker
127*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
128*b9df5ad1SAndroid Build Coastguard Worker testClamp8(testArray[i]);
129*b9df5ad1SAndroid Build Coastguard Worker }
130*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
131*b9df5ad1SAndroid Build Coastguard Worker testClamp16(testArray[i]);
132*b9df5ad1SAndroid Build Coastguard Worker }
133*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
134*b9df5ad1SAndroid Build Coastguard Worker testClamp24(testArray[i]);
135*b9df5ad1SAndroid Build Coastguard Worker }
136*b9df5ad1SAndroid Build Coastguard Worker
137*b9df5ad1SAndroid Build Coastguard Worker // used for ULP testing (tweaking the lsb of the float)
138*b9df5ad1SAndroid Build Coastguard Worker union {
139*b9df5ad1SAndroid Build Coastguard Worker int32_t i;
140*b9df5ad1SAndroid Build Coastguard Worker float f;
141*b9df5ad1SAndroid Build Coastguard Worker } val;
142*b9df5ad1SAndroid Build Coastguard Worker int32_t res;
143*b9df5ad1SAndroid Build Coastguard Worker
144*b9df5ad1SAndroid Build Coastguard Worker // check clampq4_27_from_float()
145*b9df5ad1SAndroid Build Coastguard Worker val.f = 16.;
146*b9df5ad1SAndroid Build Coastguard Worker res = clampq4_27_from_float(val.f);
147*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0x7fffffff, res);
148*b9df5ad1SAndroid Build Coastguard Worker val.i--;
149*b9df5ad1SAndroid Build Coastguard Worker res = clampq4_27_from_float(val.f);
150*b9df5ad1SAndroid Build Coastguard Worker EXPECT_LE(res, 0x7fffffff);
151*b9df5ad1SAndroid Build Coastguard Worker EXPECT_GE(res, 0x7fff0000);
152*b9df5ad1SAndroid Build Coastguard Worker val.f = -16.;
153*b9df5ad1SAndroid Build Coastguard Worker res = clampq4_27_from_float(val.f);
154*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((int32_t)0x80000000, res); // negative
155*b9df5ad1SAndroid Build Coastguard Worker val.i++;
156*b9df5ad1SAndroid Build Coastguard Worker res = clampq4_27_from_float(val.f);
157*b9df5ad1SAndroid Build Coastguard Worker EXPECT_GE(res, (int32_t)0x80000000); // negative
158*b9df5ad1SAndroid Build Coastguard Worker EXPECT_LE(res, (int32_t)0x80008000); // negative
159*b9df5ad1SAndroid Build Coastguard Worker
160*b9df5ad1SAndroid Build Coastguard Worker // check u4_28_from_float and u4_12_from_float
161*b9df5ad1SAndroid Build Coastguard Worker uint32_t ures;
162*b9df5ad1SAndroid Build Coastguard Worker uint16_t ures16;
163*b9df5ad1SAndroid Build Coastguard Worker val.f = 16.;
164*b9df5ad1SAndroid Build Coastguard Worker ures = u4_28_from_float(val.f);
165*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0xffffffff, ures);
166*b9df5ad1SAndroid Build Coastguard Worker ures16 = u4_12_from_float(val.f);
167*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0xffff, ures16);
168*b9df5ad1SAndroid Build Coastguard Worker
169*b9df5ad1SAndroid Build Coastguard Worker val.f = -1.;
170*b9df5ad1SAndroid Build Coastguard Worker ures = u4_28_from_float(val.f);
171*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((uint32_t)0, ures);
172*b9df5ad1SAndroid Build Coastguard Worker ures16 = u4_12_from_float(val.f);
173*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, ures16);
174*b9df5ad1SAndroid Build Coastguard Worker
175*b9df5ad1SAndroid Build Coastguard Worker // check float_from_u4_28 and float_from_u4_12 (roundtrip)
176*b9df5ad1SAndroid Build Coastguard Worker for (uint32_t v = 0x100000; v <= 0xff000000; v += 0x100000) {
177*b9df5ad1SAndroid Build Coastguard Worker ures = u4_28_from_float(float_from_u4_28(v));
178*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(ures, v);
179*b9df5ad1SAndroid Build Coastguard Worker }
180*b9df5ad1SAndroid Build Coastguard Worker for (uint32_t v = 0; v <= 0xffff; ++v) { // uint32_t prevents overflow
181*b9df5ad1SAndroid Build Coastguard Worker ures16 = u4_12_from_float(float_from_u4_12(v));
182*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(ures16, v);
183*b9df5ad1SAndroid Build Coastguard Worker }
184*b9df5ad1SAndroid Build Coastguard Worker
185*b9df5ad1SAndroid Build Coastguard Worker // check infinity
186*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, clamp8_from_float(-INFINITY));
187*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(255, clamp8_from_float(INFINITY));
188*b9df5ad1SAndroid Build Coastguard Worker }
189*b9df5ad1SAndroid Build Coastguard Worker
TEST(audio_utils_primitives,memcpy)190*b9df5ad1SAndroid Build Coastguard Worker TEST(audio_utils_primitives, memcpy) {
191*b9df5ad1SAndroid Build Coastguard Worker // test round-trip.
192*b9df5ad1SAndroid Build Coastguard Worker constexpr size_t size = 65536;
193*b9df5ad1SAndroid Build Coastguard Worker std::vector<int16_t> i16ref(size);
194*b9df5ad1SAndroid Build Coastguard Worker std::vector<int16_t> i16ary(size);
195*b9df5ad1SAndroid Build Coastguard Worker std::vector<int32_t> i32ary(size);
196*b9df5ad1SAndroid Build Coastguard Worker std::vector<float> fary(size);
197*b9df5ad1SAndroid Build Coastguard Worker std::vector<uint8_t> pary(size * 3);
198*b9df5ad1SAndroid Build Coastguard Worker
199*b9df5ad1SAndroid Build Coastguard Worker
200*b9df5ad1SAndroid Build Coastguard Worker // set signed reference monotonic array from -32768 to 32767
201*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < i16ref.size(); ++i) {
202*b9df5ad1SAndroid Build Coastguard Worker i16ref[i] = i16ary[i] = i - 32768;
203*b9df5ad1SAndroid Build Coastguard Worker }
204*b9df5ad1SAndroid Build Coastguard Worker
205*b9df5ad1SAndroid Build Coastguard Worker // do round-trip testing i16 and float
206*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_i16(fary.data(), i16ary.data(), fary.size());
207*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i16ary);
208*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(fary.data(), fary.size());
209*b9df5ad1SAndroid Build Coastguard Worker
210*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_float(i16ary.data(), fary.data(), i16ary.size());
211*b9df5ad1SAndroid Build Coastguard Worker zeroFill(fary);
212*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i16ary.data(), i16ary.size());
213*b9df5ad1SAndroid Build Coastguard Worker
214*b9df5ad1SAndroid Build Coastguard Worker // TODO make a template case for the following?
215*b9df5ad1SAndroid Build Coastguard Worker
216*b9df5ad1SAndroid Build Coastguard Worker // do round-trip testing p24 to i16 and float
217*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_i16(pary.data(), i16ary.data(), size /* note pary elem is 3 bytes */);
218*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i16ary);
219*b9df5ad1SAndroid Build Coastguard Worker
220*b9df5ad1SAndroid Build Coastguard Worker // check an intermediate format at a position(???)
221*b9df5ad1SAndroid Build Coastguard Worker #if 0
222*b9df5ad1SAndroid Build Coastguard Worker printf("pary[%d].0 = %u pary[%d].1 = %u pary[%d].2 = %u\n",
223*b9df5ad1SAndroid Build Coastguard Worker 1025, (unsigned) pary[1025*3],
224*b9df5ad1SAndroid Build Coastguard Worker 1025, (unsigned) pary[1025*3+1],
225*b9df5ad1SAndroid Build Coastguard Worker 1025, (unsigned) pary[1025*3+2]
226*b9df5ad1SAndroid Build Coastguard Worker );
227*b9df5ad1SAndroid Build Coastguard Worker #endif
228*b9df5ad1SAndroid Build Coastguard Worker
229*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_p24(fary.data(), pary.data(), fary.size());
230*b9df5ad1SAndroid Build Coastguard Worker zeroFill(pary);
231*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(fary.data(), fary.size());
232*b9df5ad1SAndroid Build Coastguard Worker
233*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_float(pary.data(), fary.data(), size /* note pary elem is 3 bytes */);
234*b9df5ad1SAndroid Build Coastguard Worker zeroFill(fary);
235*b9df5ad1SAndroid Build Coastguard Worker checkMonotonep24(pary.data(), pary.size() /* this is * 3*/);
236*b9df5ad1SAndroid Build Coastguard Worker
237*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24(i16ary.data(), pary.data(), i16ary.size());
238*b9df5ad1SAndroid Build Coastguard Worker zeroFill(pary);
239*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i16ary.data(), i16ary.size());
240*b9df5ad1SAndroid Build Coastguard Worker
241*b9df5ad1SAndroid Build Coastguard Worker // do round-trip testing q8_23 to i16 and float
242*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_i16(i32ary.data(), i16ary.data(), i32ary.size());
243*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i16ary);
244*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i32ary.data(), i32ary.size());
245*b9df5ad1SAndroid Build Coastguard Worker
246*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_q8_23(fary.data(), i32ary.data(), fary.size());
247*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i32ary);
248*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(fary.data(), fary.size());
249*b9df5ad1SAndroid Build Coastguard Worker
250*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_float_with_clamp(i32ary.data(), fary.data(), i32ary.size());
251*b9df5ad1SAndroid Build Coastguard Worker zeroFill(fary);
252*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i32ary.data(), i32ary.size());
253*b9df5ad1SAndroid Build Coastguard Worker
254*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_q8_23(i16ary.data(), i32ary.data(), i16ary.size());
255*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i32ary);
256*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i16ary.data(), i16ary.size());
257*b9df5ad1SAndroid Build Coastguard Worker
258*b9df5ad1SAndroid Build Coastguard Worker // do round-trip testing i32 to i16 and float
259*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i32_from_i16(i32ary.data(), i16ary.data(), i32ary.size());
260*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i16ary);
261*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i32ary.data(), i32ary.size());
262*b9df5ad1SAndroid Build Coastguard Worker
263*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_i32(fary.data(), i32ary.data(), fary.size());
264*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i32ary);
265*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(fary.data(), fary.size());
266*b9df5ad1SAndroid Build Coastguard Worker
267*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i32_from_float(i32ary.data(), fary.data(), i32ary.size());
268*b9df5ad1SAndroid Build Coastguard Worker zeroFill(fary);
269*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i32ary.data(), i32ary.size());
270*b9df5ad1SAndroid Build Coastguard Worker
271*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_i32(i16ary.data(), i32ary.data(), i16ary.size());
272*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i32ary);
273*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i16ary.data(), i16ary.size());
274*b9df5ad1SAndroid Build Coastguard Worker
275*b9df5ad1SAndroid Build Coastguard Worker // do round-trip test i16 -> p24 -> i32 -> p24 -> q8_23 -> p24 -> i16
276*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_i16(pary.data(), i16ary.data(), size /* note pary elem is 3 bytes */);
277*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i16ary);
278*b9df5ad1SAndroid Build Coastguard Worker checkMonotonep24(pary.data(), pary.size() /* this is * 3*/);
279*b9df5ad1SAndroid Build Coastguard Worker
280*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i32_from_p24(i32ary.data(), pary.data(), i32ary.size());
281*b9df5ad1SAndroid Build Coastguard Worker zeroFill(pary);
282*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i32ary.data(), i32ary.size());
283*b9df5ad1SAndroid Build Coastguard Worker
284*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_i32(pary.data(), i32ary.data(), size /* note pary elem is 3 bytes */);
285*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i32ary);
286*b9df5ad1SAndroid Build Coastguard Worker checkMonotonep24(pary.data(), pary.size() /* this is * 3*/);
287*b9df5ad1SAndroid Build Coastguard Worker
288*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_p24(i32ary.data(), pary.data(), i32ary.size());
289*b9df5ad1SAndroid Build Coastguard Worker zeroFill(pary);
290*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i32ary.data(), i32ary.size());
291*b9df5ad1SAndroid Build Coastguard Worker
292*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_q8_23(pary.data(), i32ary.data(), size /* note pary elem is 3 bytes */);
293*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i32ary);
294*b9df5ad1SAndroid Build Coastguard Worker checkMonotonep24(pary.data(), pary.size() /* this is * 3*/);
295*b9df5ad1SAndroid Build Coastguard Worker
296*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24(i16ary.data(), pary.data(), i16ary.size());
297*b9df5ad1SAndroid Build Coastguard Worker zeroFill(pary);
298*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i16ary.data(), i16ary.size());
299*b9df5ad1SAndroid Build Coastguard Worker
300*b9df5ad1SAndroid Build Coastguard Worker // do partial round-trip testing q4_27 to i16 and float
301*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_i16(fary.data(), i16ary.data(), fary.size());
302*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i16ary);
303*b9df5ad1SAndroid Build Coastguard Worker
304*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q4_27_from_float(i32ary.data(), fary.data(), i32ary.size());
305*b9df5ad1SAndroid Build Coastguard Worker zeroFill(fary);
306*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i32ary.data(), i32ary.size());
307*b9df5ad1SAndroid Build Coastguard Worker
308*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_q4_27(i16ary.data(), i32ary.data(), i16ary.size());
309*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i16ary.data(), i16ary.size());
310*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(i16ary.data(), i16ref.data(), i16ary.size() * sizeof(i16ary[0])));
311*b9df5ad1SAndroid Build Coastguard Worker
312*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i16ary);
313*b9df5ad1SAndroid Build Coastguard Worker
314*b9df5ad1SAndroid Build Coastguard Worker // ditherAndClamp() has non-standard parameters - memcpy_to_float_from_q4_27() is preferred
315*b9df5ad1SAndroid Build Coastguard Worker ditherAndClamp(reinterpret_cast<int32_t *>(i16ary.data()),
316*b9df5ad1SAndroid Build Coastguard Worker i32ary.data(), i16ary.size() / 2);
317*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i16ary.data(), i16ary.size());
318*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(i16ary.data(), i16ref.data(), i16ary.size() * sizeof(i16ary[0])));
319*b9df5ad1SAndroid Build Coastguard Worker
320*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_q4_27(fary.data(), i32ary.data(), fary.size());
321*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i32ary);
322*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(fary.data(), fary.size());
323*b9df5ad1SAndroid Build Coastguard Worker
324*b9df5ad1SAndroid Build Coastguard Worker // at the end, our i16ary must be the same. (Monotone should be equivalent to this)
325*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(i16ary.data(), i16ref.data(), i16ary.size() * sizeof(i16ary[0])));
326*b9df5ad1SAndroid Build Coastguard Worker
327*b9df5ad1SAndroid Build Coastguard Worker // test round-trip for u8 and float.
328*b9df5ad1SAndroid Build Coastguard Worker constexpr size_t u8size = 256;
329*b9df5ad1SAndroid Build Coastguard Worker std::vector<uint8_t> u8ref(u8size);
330*b9df5ad1SAndroid Build Coastguard Worker std::vector<uint8_t> u8ary(u8size);
331*b9df5ad1SAndroid Build Coastguard Worker
332*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < u8ref.size(); ++i) {
333*b9df5ad1SAndroid Build Coastguard Worker u8ref[i] = i;
334*b9df5ad1SAndroid Build Coastguard Worker }
335*b9df5ad1SAndroid Build Coastguard Worker
336*b9df5ad1SAndroid Build Coastguard Worker constexpr size_t testsize = std::min(u8size, size);
337*b9df5ad1SAndroid Build Coastguard Worker zeroFill(fary);
338*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_u8(fary.data(), u8ref.data(), testsize);
339*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_u8_from_float(u8ary.data(), fary.data(), testsize);
340*b9df5ad1SAndroid Build Coastguard Worker
341*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(u8ary.data(), u8ref.data(), u8ary.size() * sizeof(u8ary[0])));
342*b9df5ad1SAndroid Build Coastguard Worker
343*b9df5ad1SAndroid Build Coastguard Worker // test conversion from u8 to i32
344*b9df5ad1SAndroid Build Coastguard Worker zeroFill(i32ary);
345*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i32_from_u8(i32ary.data(), u8ref.data(), testsize);
346*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(i32ary.data(), testsize);
347*b9df5ad1SAndroid Build Coastguard Worker }
348*b9df5ad1SAndroid Build Coastguard Worker
349*b9df5ad1SAndroid Build Coastguard Worker template<typename T>
checkMonotoneOrZero(const T * ary,size_t size)350*b9df5ad1SAndroid Build Coastguard Worker void checkMonotoneOrZero(const T *ary, size_t size)
351*b9df5ad1SAndroid Build Coastguard Worker {
352*b9df5ad1SAndroid Build Coastguard Worker T least = 0;
353*b9df5ad1SAndroid Build Coastguard Worker
354*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 1; i < size; ++i) {
355*b9df5ad1SAndroid Build Coastguard Worker if (ary[i]) {
356*b9df5ad1SAndroid Build Coastguard Worker EXPECT_LT(least, ary[i]);
357*b9df5ad1SAndroid Build Coastguard Worker least = ary[i];
358*b9df5ad1SAndroid Build Coastguard Worker }
359*b9df5ad1SAndroid Build Coastguard Worker }
360*b9df5ad1SAndroid Build Coastguard Worker }
361*b9df5ad1SAndroid Build Coastguard Worker
TEST(audio_utils_primitives,memcpy_by_channel_mask)362*b9df5ad1SAndroid Build Coastguard Worker TEST(audio_utils_primitives, memcpy_by_channel_mask) {
363*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_mask;
364*b9df5ad1SAndroid Build Coastguard Worker uint32_t src_mask;
365*b9df5ad1SAndroid Build Coastguard Worker uint16_t *u16ref = new uint16_t[65536];
366*b9df5ad1SAndroid Build Coastguard Worker uint16_t *u16ary = new uint16_t[65536];
367*b9df5ad1SAndroid Build Coastguard Worker
368*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < 65536; ++i) {
369*b9df5ad1SAndroid Build Coastguard Worker u16ref[i] = i;
370*b9df5ad1SAndroid Build Coastguard Worker }
371*b9df5ad1SAndroid Build Coastguard Worker
372*b9df5ad1SAndroid Build Coastguard Worker // Test when src mask is 0. Everything copied is zero.
373*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0;
374*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8d;
375*b9df5ad1SAndroid Build Coastguard Worker memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
376*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
377*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(dst_mask));
378*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
379*b9df5ad1SAndroid Build Coastguard Worker
380*b9df5ad1SAndroid Build Coastguard Worker // Test when dst_mask is 0. Nothing should be copied.
381*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0;
382*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0;
383*b9df5ad1SAndroid Build Coastguard Worker memset(u16ary, 0, 65536 * sizeof(u16ref[0]));
384*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
385*b9df5ad1SAndroid Build Coastguard Worker 65536);
386*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
387*b9df5ad1SAndroid Build Coastguard Worker
388*b9df5ad1SAndroid Build Coastguard Worker // Test when masks are the same. One to one copy.
389*b9df5ad1SAndroid Build Coastguard Worker src_mask = dst_mask = 0x8d;
390*b9df5ad1SAndroid Build Coastguard Worker memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
391*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]), 555);
392*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(u16ary, u16ref, 555 * sizeof(u16ref[0]) * __builtin_popcount(dst_mask)));
393*b9df5ad1SAndroid Build Coastguard Worker
394*b9df5ad1SAndroid Build Coastguard Worker // Test with a gap in source:
395*b9df5ad1SAndroid Build Coastguard Worker // Input 3 samples, output 4 samples, one zero inserted.
396*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0x8c;
397*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8d;
398*b9df5ad1SAndroid Build Coastguard Worker memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
399*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
400*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(dst_mask));
401*b9df5ad1SAndroid Build Coastguard Worker checkMonotoneOrZero(u16ary, 65536);
402*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
403*b9df5ad1SAndroid Build Coastguard Worker
404*b9df5ad1SAndroid Build Coastguard Worker // Test with a gap in destination:
405*b9df5ad1SAndroid Build Coastguard Worker // Input 4 samples, output 3 samples, one deleted
406*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0x8d;
407*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8c;
408*b9df5ad1SAndroid Build Coastguard Worker memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
409*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
410*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(src_mask));
411*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(u16ary, 65536 * 3 / 4);
412*b9df5ad1SAndroid Build Coastguard Worker
413*b9df5ad1SAndroid Build Coastguard Worker delete[] u16ref;
414*b9df5ad1SAndroid Build Coastguard Worker delete[] u16ary;
415*b9df5ad1SAndroid Build Coastguard Worker }
416*b9df5ad1SAndroid Build Coastguard Worker
memcpy_by_channel_mask2(void * dst,uint32_t dst_mask,const void * src,uint32_t src_mask,size_t sample_size,size_t count)417*b9df5ad1SAndroid Build Coastguard Worker void memcpy_by_channel_mask2(void *dst, uint32_t dst_mask,
418*b9df5ad1SAndroid Build Coastguard Worker const void *src, uint32_t src_mask, size_t sample_size, size_t count)
419*b9df5ad1SAndroid Build Coastguard Worker {
420*b9df5ad1SAndroid Build Coastguard Worker int8_t idxary[32];
421*b9df5ad1SAndroid Build Coastguard Worker uint32_t src_channels = __builtin_popcount(src_mask);
422*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_channels =
423*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask);
424*b9df5ad1SAndroid Build Coastguard Worker
425*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
426*b9df5ad1SAndroid Build Coastguard Worker }
427*b9df5ad1SAndroid Build Coastguard Worker
428*b9df5ad1SAndroid Build Coastguard Worker // a modified version of the memcpy_by_channel_mask test
429*b9df5ad1SAndroid Build Coastguard Worker // but using 24 bit type and memcpy_by_index_array()
TEST(audio_utils_primitives,memcpy_by_index_array)430*b9df5ad1SAndroid Build Coastguard Worker TEST(audio_utils_primitives, memcpy_by_index_array) {
431*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_mask;
432*b9df5ad1SAndroid Build Coastguard Worker uint32_t src_mask;
433*b9df5ad1SAndroid Build Coastguard Worker typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
434*b9df5ad1SAndroid Build Coastguard Worker uint8x3_t *u24ref = new uint8x3_t[65536];
435*b9df5ad1SAndroid Build Coastguard Worker uint8x3_t *u24ary = new uint8x3_t[65536];
436*b9df5ad1SAndroid Build Coastguard Worker uint16_t *u16ref = new uint16_t[65536];
437*b9df5ad1SAndroid Build Coastguard Worker uint16_t *u16ary = new uint16_t[65536];
438*b9df5ad1SAndroid Build Coastguard Worker
439*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
440*b9df5ad1SAndroid Build Coastguard Worker
441*b9df5ad1SAndroid Build Coastguard Worker // tests prepare_index_array_from_masks()
442*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization(NULL, 0, 0x8d, 0x8c));
443*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization(NULL, 0, 0x8c, 0x8d));
444*b9df5ad1SAndroid Build Coastguard Worker
445*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < 65536; ++i) {
446*b9df5ad1SAndroid Build Coastguard Worker u16ref[i] = i;
447*b9df5ad1SAndroid Build Coastguard Worker }
448*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
449*b9df5ad1SAndroid Build Coastguard Worker
450*b9df5ad1SAndroid Build Coastguard Worker // Test when src mask is 0. Everything copied is zero.
451*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0;
452*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8d;
453*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
454*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
455*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(dst_mask));
456*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
457*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
458*b9df5ad1SAndroid Build Coastguard Worker
459*b9df5ad1SAndroid Build Coastguard Worker // Test when dst_mask is 0. Nothing should be copied.
460*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0;
461*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0;
462*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
463*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
464*b9df5ad1SAndroid Build Coastguard Worker 65536);
465*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
466*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
467*b9df5ad1SAndroid Build Coastguard Worker
468*b9df5ad1SAndroid Build Coastguard Worker // Test when masks are the same. One to one copy.
469*b9df5ad1SAndroid Build Coastguard Worker src_mask = dst_mask = 0x8d;
470*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
471*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
472*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * __builtin_popcount(dst_mask)));
473*b9df5ad1SAndroid Build Coastguard Worker
474*b9df5ad1SAndroid Build Coastguard Worker // Test with a gap in source:
475*b9df5ad1SAndroid Build Coastguard Worker // Input 3 samples, output 4 samples, one zero inserted.
476*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0x8c;
477*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8d;
478*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
479*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
480*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(dst_mask));
481*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
482*b9df5ad1SAndroid Build Coastguard Worker checkMonotoneOrZero(u16ary, 65536);
483*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
484*b9df5ad1SAndroid Build Coastguard Worker
485*b9df5ad1SAndroid Build Coastguard Worker // Test with a gap in destination:
486*b9df5ad1SAndroid Build Coastguard Worker // Input 4 samples, output 3 samples, one deleted
487*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0x8d;
488*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8c;
489*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
490*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
491*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(src_mask));
492*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
493*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(u16ary, 65536 * 3 / 4);
494*b9df5ad1SAndroid Build Coastguard Worker
495*b9df5ad1SAndroid Build Coastguard Worker delete[] u16ref;
496*b9df5ad1SAndroid Build Coastguard Worker delete[] u16ary;
497*b9df5ad1SAndroid Build Coastguard Worker delete[] u24ref;
498*b9df5ad1SAndroid Build Coastguard Worker delete[] u24ary;
499*b9df5ad1SAndroid Build Coastguard Worker }
500*b9df5ad1SAndroid Build Coastguard Worker
memcpy_by_channel_mask_dst_index(void * dst,uint32_t dst_mask,const void * src,uint32_t src_mask,size_t sample_size,size_t count)501*b9df5ad1SAndroid Build Coastguard Worker void memcpy_by_channel_mask_dst_index(void *dst, uint32_t dst_mask,
502*b9df5ad1SAndroid Build Coastguard Worker const void *src, uint32_t src_mask, size_t sample_size, size_t count)
503*b9df5ad1SAndroid Build Coastguard Worker {
504*b9df5ad1SAndroid Build Coastguard Worker int8_t idxary[32];
505*b9df5ad1SAndroid Build Coastguard Worker uint32_t src_channels = __builtin_popcount(src_mask);
506*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_channels =
507*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_index_array_initialization_dst_index(idxary, 32, dst_mask, src_mask);
508*b9df5ad1SAndroid Build Coastguard Worker
509*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
510*b9df5ad1SAndroid Build Coastguard Worker }
511*b9df5ad1SAndroid Build Coastguard Worker
512*b9df5ad1SAndroid Build Coastguard Worker // a modified version of the memcpy_by_channel_mask test
513*b9df5ad1SAndroid Build Coastguard Worker // but using 24 bit type and memcpy_by_index_array()
TEST(audio_utils_primitives,memcpy_by_index_array_dst_index)514*b9df5ad1SAndroid Build Coastguard Worker TEST(audio_utils_primitives, memcpy_by_index_array_dst_index) {
515*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_mask;
516*b9df5ad1SAndroid Build Coastguard Worker uint32_t src_mask;
517*b9df5ad1SAndroid Build Coastguard Worker typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
518*b9df5ad1SAndroid Build Coastguard Worker uint8x3_t *u24ref = new uint8x3_t[65536];
519*b9df5ad1SAndroid Build Coastguard Worker uint8x3_t *u24ary = new uint8x3_t[65536];
520*b9df5ad1SAndroid Build Coastguard Worker uint16_t *u16ref = new uint16_t[65536];
521*b9df5ad1SAndroid Build Coastguard Worker uint16_t *u16ary = new uint16_t[65536];
522*b9df5ad1SAndroid Build Coastguard Worker
523*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
524*b9df5ad1SAndroid Build Coastguard Worker
525*b9df5ad1SAndroid Build Coastguard Worker // tests prepare_index_array_from_masks()
526*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization_dst_index(NULL, 0, 0x8d, 0x8c));
527*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_dst_index(NULL, 0, 0x8c, 0x8d));
528*b9df5ad1SAndroid Build Coastguard Worker
529*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < 65536; ++i) {
530*b9df5ad1SAndroid Build Coastguard Worker u16ref[i] = i;
531*b9df5ad1SAndroid Build Coastguard Worker }
532*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
533*b9df5ad1SAndroid Build Coastguard Worker
534*b9df5ad1SAndroid Build Coastguard Worker // Test when src mask is 0. Everything copied is zero.
535*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0;
536*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8d;
537*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
538*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
539*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(dst_mask));
540*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
541*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
542*b9df5ad1SAndroid Build Coastguard Worker
543*b9df5ad1SAndroid Build Coastguard Worker // Test when dst_mask is 0. Nothing should be copied.
544*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0;
545*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0;
546*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
547*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
548*b9df5ad1SAndroid Build Coastguard Worker 65536);
549*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
550*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
551*b9df5ad1SAndroid Build Coastguard Worker
552*b9df5ad1SAndroid Build Coastguard Worker // Test when dst mask equals source count size. One to one copy.
553*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0x8d;
554*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x0f;
555*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
556*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
557*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * __builtin_popcount(dst_mask)));
558*b9df5ad1SAndroid Build Coastguard Worker
559*b9df5ad1SAndroid Build Coastguard Worker // Test with a gap in source:
560*b9df5ad1SAndroid Build Coastguard Worker // Input 3 samples, output 4 samples, one zero inserted.
561*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0x8c;
562*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x0f;
563*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
564*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
565*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(dst_mask));
566*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
567*b9df5ad1SAndroid Build Coastguard Worker checkMonotoneOrZero(u16ary, 65536);
568*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
569*b9df5ad1SAndroid Build Coastguard Worker
570*b9df5ad1SAndroid Build Coastguard Worker // Test with a gap in destination:
571*b9df5ad1SAndroid Build Coastguard Worker // Input 4 samples, output 3 samples, one deleted
572*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0x8d;
573*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x07;
574*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
575*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
576*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(src_mask));
577*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
578*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(u16ary, 65536 * 3 / 4);
579*b9df5ad1SAndroid Build Coastguard Worker
580*b9df5ad1SAndroid Build Coastguard Worker delete[] u16ref;
581*b9df5ad1SAndroid Build Coastguard Worker delete[] u16ary;
582*b9df5ad1SAndroid Build Coastguard Worker delete[] u24ref;
583*b9df5ad1SAndroid Build Coastguard Worker delete[] u24ary;
584*b9df5ad1SAndroid Build Coastguard Worker }
585*b9df5ad1SAndroid Build Coastguard Worker
memcpy_by_channel_mask_src_index(void * dst,uint32_t dst_mask,const void * src,uint32_t src_mask,size_t sample_size,size_t count)586*b9df5ad1SAndroid Build Coastguard Worker void memcpy_by_channel_mask_src_index(void *dst, uint32_t dst_mask,
587*b9df5ad1SAndroid Build Coastguard Worker const void *src, uint32_t src_mask, size_t sample_size, size_t count)
588*b9df5ad1SAndroid Build Coastguard Worker {
589*b9df5ad1SAndroid Build Coastguard Worker int8_t idxary[32];
590*b9df5ad1SAndroid Build Coastguard Worker uint32_t src_channels = __builtin_popcount(src_mask);
591*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_channels =
592*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_index_array_initialization_src_index(idxary, 32, dst_mask, src_mask);
593*b9df5ad1SAndroid Build Coastguard Worker
594*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
595*b9df5ad1SAndroid Build Coastguard Worker }
596*b9df5ad1SAndroid Build Coastguard Worker
597*b9df5ad1SAndroid Build Coastguard Worker // a modified version of the memcpy_by_channel_mask test
598*b9df5ad1SAndroid Build Coastguard Worker // but using 24 bit type and memcpy_by_index_array()
TEST(audio_utils_primitives,memcpy_by_index_array_src_index)599*b9df5ad1SAndroid Build Coastguard Worker TEST(audio_utils_primitives, memcpy_by_index_array_src_index) {
600*b9df5ad1SAndroid Build Coastguard Worker uint32_t dst_mask;
601*b9df5ad1SAndroid Build Coastguard Worker uint32_t src_mask;
602*b9df5ad1SAndroid Build Coastguard Worker typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
603*b9df5ad1SAndroid Build Coastguard Worker uint8x3_t *u24ref = new uint8x3_t[65536];
604*b9df5ad1SAndroid Build Coastguard Worker uint8x3_t *u24ary = new uint8x3_t[65536];
605*b9df5ad1SAndroid Build Coastguard Worker uint16_t *u16ref = new uint16_t[65536];
606*b9df5ad1SAndroid Build Coastguard Worker uint16_t *u16ary = new uint16_t[65536];
607*b9df5ad1SAndroid Build Coastguard Worker
608*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
609*b9df5ad1SAndroid Build Coastguard Worker
610*b9df5ad1SAndroid Build Coastguard Worker // tests prepare_index_array_from_masks()
611*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8d, 0x8c));
612*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8c, 0x8d));
613*b9df5ad1SAndroid Build Coastguard Worker
614*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < 65536; ++i) {
615*b9df5ad1SAndroid Build Coastguard Worker u16ref[i] = i;
616*b9df5ad1SAndroid Build Coastguard Worker }
617*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
618*b9df5ad1SAndroid Build Coastguard Worker
619*b9df5ad1SAndroid Build Coastguard Worker // Test when src mask is 0. Everything copied is zero.
620*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0;
621*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8d;
622*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
623*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
624*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(dst_mask));
625*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
626*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
627*b9df5ad1SAndroid Build Coastguard Worker
628*b9df5ad1SAndroid Build Coastguard Worker // Test when dst_mask is 0. Nothing should be copied.
629*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0;
630*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0;
631*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
632*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
633*b9df5ad1SAndroid Build Coastguard Worker 65536);
634*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
635*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
636*b9df5ad1SAndroid Build Coastguard Worker
637*b9df5ad1SAndroid Build Coastguard Worker // Test when source mask must copy to dst mask. One to one copy.
638*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0xf;
639*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0xf;
640*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
641*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
642*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * __builtin_popcount(dst_mask)));
643*b9df5ad1SAndroid Build Coastguard Worker
644*b9df5ad1SAndroid Build Coastguard Worker // Test when source mask must copy to dst mask. One to one copy.
645*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0xf;
646*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8d;
647*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
648*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
649*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * __builtin_popcount(dst_mask)));
650*b9df5ad1SAndroid Build Coastguard Worker
651*b9df5ad1SAndroid Build Coastguard Worker // Test with a gap in source:
652*b9df5ad1SAndroid Build Coastguard Worker // Input 3 samples, output 4 samples, one zero inserted.
653*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0x07;
654*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8d;
655*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
656*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
657*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(dst_mask));
658*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
659*b9df5ad1SAndroid Build Coastguard Worker checkMonotoneOrZero(u16ary, 65536);
660*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
661*b9df5ad1SAndroid Build Coastguard Worker
662*b9df5ad1SAndroid Build Coastguard Worker // Test with a gap in destination:
663*b9df5ad1SAndroid Build Coastguard Worker // Input 4 samples, output 3 samples, one deleted
664*b9df5ad1SAndroid Build Coastguard Worker src_mask = 0x0f;
665*b9df5ad1SAndroid Build Coastguard Worker dst_mask = 0x8c;
666*b9df5ad1SAndroid Build Coastguard Worker memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
667*b9df5ad1SAndroid Build Coastguard Worker memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
668*b9df5ad1SAndroid Build Coastguard Worker 65536 / __builtin_popcount(src_mask));
669*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
670*b9df5ad1SAndroid Build Coastguard Worker checkMonotone(u16ary, 65536 * 3 / 4);
671*b9df5ad1SAndroid Build Coastguard Worker
672*b9df5ad1SAndroid Build Coastguard Worker delete[] u16ref;
673*b9df5ad1SAndroid Build Coastguard Worker delete[] u16ary;
674*b9df5ad1SAndroid Build Coastguard Worker delete[] u24ref;
675*b9df5ad1SAndroid Build Coastguard Worker delete[] u24ary;
676*b9df5ad1SAndroid Build Coastguard Worker }
677*b9df5ad1SAndroid Build Coastguard Worker
TEST(audio_utils_primitives,updown_mix)678*b9df5ad1SAndroid Build Coastguard Worker TEST(audio_utils_primitives, updown_mix) {
679*b9df5ad1SAndroid Build Coastguard Worker const size_t size = 32767;
680*b9df5ad1SAndroid Build Coastguard Worker std::vector<int16_t> i16ref(size * 2);
681*b9df5ad1SAndroid Build Coastguard Worker std::vector<int16_t> i16ary(size * 2);
682*b9df5ad1SAndroid Build Coastguard Worker
683*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i) {
684*b9df5ad1SAndroid Build Coastguard Worker i16ref[i] = i;
685*b9df5ad1SAndroid Build Coastguard Worker }
686*b9df5ad1SAndroid Build Coastguard Worker upmix_to_stereo_i16_from_mono_i16(i16ary.data(), i16ref.data(), size);
687*b9df5ad1SAndroid Build Coastguard Worker downmix_to_mono_i16_from_stereo_i16(i16ary.data(), i16ary.data(), size);
688*b9df5ad1SAndroid Build Coastguard Worker
689*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(i16ary.data(), i16ref.data(), sizeof(i16ref[0]) * size));
690*b9df5ad1SAndroid Build Coastguard Worker }
691*b9df5ad1SAndroid Build Coastguard Worker
692*b9df5ad1SAndroid Build Coastguard Worker template<typename T, typename TComparison>
checkAddedClamped(T * out,const T * in1,const T * in2,size_t size,TComparison limNeg,TComparison limPos)693*b9df5ad1SAndroid Build Coastguard Worker void checkAddedClamped(T *out, const T *in1, const T *in2, size_t size,
694*b9df5ad1SAndroid Build Coastguard Worker TComparison limNeg, TComparison limPos)
695*b9df5ad1SAndroid Build Coastguard Worker {
696*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i) {
697*b9df5ad1SAndroid Build Coastguard Worker TComparison added = (TComparison)in1[i] + in2[i];
698*b9df5ad1SAndroid Build Coastguard Worker if (added <= limNeg) {
699*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(limNeg, out[i]);
700*b9df5ad1SAndroid Build Coastguard Worker } else if (added >= limPos) {
701*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(limPos, out[i]);
702*b9df5ad1SAndroid Build Coastguard Worker } else {
703*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(added, out[i]);
704*b9df5ad1SAndroid Build Coastguard Worker }
705*b9df5ad1SAndroid Build Coastguard Worker }
706*b9df5ad1SAndroid Build Coastguard Worker }
707*b9df5ad1SAndroid Build Coastguard Worker
checkAddedClampedp24(uint8_t * pary,const uint8_t * in1,const uint8_t * in2,size_t size)708*b9df5ad1SAndroid Build Coastguard Worker void checkAddedClampedp24(uint8_t *pary, const uint8_t *in1,
709*b9df5ad1SAndroid Build Coastguard Worker const uint8_t *in2, size_t size) {
710*b9df5ad1SAndroid Build Coastguard Worker // Convert to q8_23 for comparison.
711*b9df5ad1SAndroid Build Coastguard Worker int32_t *outi32ary = new int32_t[size];
712*b9df5ad1SAndroid Build Coastguard Worker int32_t *in1i32ary = new int32_t[size];
713*b9df5ad1SAndroid Build Coastguard Worker int32_t *in2i32ary = new int32_t[size];
714*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_p24(outi32ary, pary, size);
715*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_p24(in1i32ary, in1, size);
716*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_p24(in2i32ary, in2, size);
717*b9df5ad1SAndroid Build Coastguard Worker checkAddedClamped(
718*b9df5ad1SAndroid Build Coastguard Worker outi32ary, in1i32ary, in2i32ary, size, lim24neg, lim24pos);
719*b9df5ad1SAndroid Build Coastguard Worker delete[] in2i32ary;
720*b9df5ad1SAndroid Build Coastguard Worker delete[] in1i32ary;
721*b9df5ad1SAndroid Build Coastguard Worker delete[] outi32ary;
722*b9df5ad1SAndroid Build Coastguard Worker }
723*b9df5ad1SAndroid Build Coastguard Worker
checkAddedClampedu8(uint8_t * out,const uint8_t * in1,const uint8_t * in2,size_t size)724*b9df5ad1SAndroid Build Coastguard Worker void checkAddedClampedu8(uint8_t *out, const uint8_t *in1,
725*b9df5ad1SAndroid Build Coastguard Worker const uint8_t *in2, size_t size) {
726*b9df5ad1SAndroid Build Coastguard Worker // uint8_t data is centered around 0x80, not 0, so checkAddedClamped
727*b9df5ad1SAndroid Build Coastguard Worker // won't work. Convert to i16 first.
728*b9df5ad1SAndroid Build Coastguard Worker int16_t *outi16ary = new int16_t[size];
729*b9df5ad1SAndroid Build Coastguard Worker int16_t *in1i16ary = new int16_t[size];
730*b9df5ad1SAndroid Build Coastguard Worker int16_t *in2i16ary = new int16_t[size];
731*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_u8(outi16ary, out, size);
732*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_u8(in1i16ary, in1, size);
733*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i16_from_u8(in2i16ary, in2, size);
734*b9df5ad1SAndroid Build Coastguard Worker // Only the higher order bits are used.
735*b9df5ad1SAndroid Build Coastguard Worker checkAddedClamped(outi16ary, in1i16ary, in2i16ary, size,
736*b9df5ad1SAndroid Build Coastguard Worker -0x8000, 0x7f00);
737*b9df5ad1SAndroid Build Coastguard Worker delete[] in2i16ary;
738*b9df5ad1SAndroid Build Coastguard Worker delete[] in1i16ary;
739*b9df5ad1SAndroid Build Coastguard Worker delete[] outi16ary;
740*b9df5ad1SAndroid Build Coastguard Worker }
741*b9df5ad1SAndroid Build Coastguard Worker
TEST(audio_utils_primitives,accumulate)742*b9df5ad1SAndroid Build Coastguard Worker TEST(audio_utils_primitives, accumulate) {
743*b9df5ad1SAndroid Build Coastguard Worker int16_t *i16ref = new int16_t[65536];
744*b9df5ad1SAndroid Build Coastguard Worker int16_t *i16add = new int16_t[65536];
745*b9df5ad1SAndroid Build Coastguard Worker int16_t *i16ary = new int16_t[65536];
746*b9df5ad1SAndroid Build Coastguard Worker
747*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < 65536; ++i) {
748*b9df5ad1SAndroid Build Coastguard Worker i16ref[i] = i16ary[i] = i16add[(i+1) % 65536] = i - 32768;
749*b9df5ad1SAndroid Build Coastguard Worker }
750*b9df5ad1SAndroid Build Coastguard Worker
751*b9df5ad1SAndroid Build Coastguard Worker // Test i16.
752*b9df5ad1SAndroid Build Coastguard Worker accumulate_i16(i16ary, i16add, 65536);
753*b9df5ad1SAndroid Build Coastguard Worker checkAddedClamped(i16ary, i16ref, i16add, 65536, lim16neg,
754*b9df5ad1SAndroid Build Coastguard Worker lim16pos);
755*b9df5ad1SAndroid Build Coastguard Worker
756*b9df5ad1SAndroid Build Coastguard Worker // Test i32.
757*b9df5ad1SAndroid Build Coastguard Worker int32_t *i32ary = new int32_t[65536];
758*b9df5ad1SAndroid Build Coastguard Worker int32_t *i32add = new int32_t[65536];
759*b9df5ad1SAndroid Build Coastguard Worker int32_t *i32ref = new int32_t[65536];
760*b9df5ad1SAndroid Build Coastguard Worker // Convert sample data to i32 to perform accumulate function.
761*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i32_from_i16(i32ary, i16ref, 65536);
762*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_i32_from_i16(i32add, i16add, 65536);
763*b9df5ad1SAndroid Build Coastguard Worker // Ensure the reference matches the inital output after conversion.
764*b9df5ad1SAndroid Build Coastguard Worker memcpy(i32ref, i32ary, 65536 * sizeof(i32ary[0]));
765*b9df5ad1SAndroid Build Coastguard Worker // Accumulate and check.
766*b9df5ad1SAndroid Build Coastguard Worker accumulate_i32(i32ary, i32add, 65536);
767*b9df5ad1SAndroid Build Coastguard Worker checkAddedClamped(
768*b9df5ad1SAndroid Build Coastguard Worker i32ary, i32ref, i32add, 65536, lim32neg, lim32pos);
769*b9df5ad1SAndroid Build Coastguard Worker // Cleanup
770*b9df5ad1SAndroid Build Coastguard Worker delete[] i32ref;
771*b9df5ad1SAndroid Build Coastguard Worker delete[] i32add;
772*b9df5ad1SAndroid Build Coastguard Worker delete[] i32ary;
773*b9df5ad1SAndroid Build Coastguard Worker
774*b9df5ad1SAndroid Build Coastguard Worker // Test u8.
775*b9df5ad1SAndroid Build Coastguard Worker uint8_t *u8ary = new uint8_t[65536];
776*b9df5ad1SAndroid Build Coastguard Worker uint8_t *u8add = new uint8_t[65536];
777*b9df5ad1SAndroid Build Coastguard Worker uint8_t *u8ref = new uint8_t[65536];
778*b9df5ad1SAndroid Build Coastguard Worker // Convert sample data to u8 to perform accumulate function.
779*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_u8_from_i16(u8ary, i16ref, 65536);
780*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_u8_from_i16(u8add, i16add, 65536);
781*b9df5ad1SAndroid Build Coastguard Worker // Ensure the reference matches the inital output after conversion.
782*b9df5ad1SAndroid Build Coastguard Worker memcpy(u8ref, u8ary, 65536 * sizeof(u8ary[0]));
783*b9df5ad1SAndroid Build Coastguard Worker // Accumulate and check.
784*b9df5ad1SAndroid Build Coastguard Worker accumulate_u8(u8ary, u8add, 65536);
785*b9df5ad1SAndroid Build Coastguard Worker checkAddedClampedu8(u8ary, u8ref, u8add, 65536);
786*b9df5ad1SAndroid Build Coastguard Worker // Cleanup.
787*b9df5ad1SAndroid Build Coastguard Worker delete[] u8ref;
788*b9df5ad1SAndroid Build Coastguard Worker delete[] u8add;
789*b9df5ad1SAndroid Build Coastguard Worker delete[] u8ary;
790*b9df5ad1SAndroid Build Coastguard Worker
791*b9df5ad1SAndroid Build Coastguard Worker // Test 24 bit packed.
792*b9df5ad1SAndroid Build Coastguard Worker uint8_t *pary = new uint8_t[65536 * 3];
793*b9df5ad1SAndroid Build Coastguard Worker uint8_t *padd = new uint8_t[65536 * 3];
794*b9df5ad1SAndroid Build Coastguard Worker uint8_t *pref = new uint8_t[65536 * 3];
795*b9df5ad1SAndroid Build Coastguard Worker // Convert sample data to p24 to perform accumulate function.
796*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_i16(pary, i16ref, 65536);
797*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_p24_from_i16(padd, i16add, 65536);
798*b9df5ad1SAndroid Build Coastguard Worker // Ensure the reference matches the inital output after conversion.
799*b9df5ad1SAndroid Build Coastguard Worker memcpy(pref, pary, 65536 * sizeof(pary[0]) * 3);
800*b9df5ad1SAndroid Build Coastguard Worker // Accumulate and check.
801*b9df5ad1SAndroid Build Coastguard Worker accumulate_p24(pary, padd, 65536);
802*b9df5ad1SAndroid Build Coastguard Worker checkAddedClampedp24(pary, pref, padd, 65536);
803*b9df5ad1SAndroid Build Coastguard Worker // Cleanup.
804*b9df5ad1SAndroid Build Coastguard Worker delete[] pref;
805*b9df5ad1SAndroid Build Coastguard Worker delete[] padd;
806*b9df5ad1SAndroid Build Coastguard Worker delete[] pary;
807*b9df5ad1SAndroid Build Coastguard Worker
808*b9df5ad1SAndroid Build Coastguard Worker // Test 24 bit unpacked.
809*b9df5ad1SAndroid Build Coastguard Worker int32_t *q8_23ary = new int32_t[65536];
810*b9df5ad1SAndroid Build Coastguard Worker int32_t *q8_23add = new int32_t[65536];
811*b9df5ad1SAndroid Build Coastguard Worker int32_t *q8_23ref = new int32_t[65536];
812*b9df5ad1SAndroid Build Coastguard Worker // Convert sample data to q8_23 to perform accumulate function.
813*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_i16(q8_23ary, i16ref, 65536);
814*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_q8_23_from_i16(q8_23add, i16add, 65536);
815*b9df5ad1SAndroid Build Coastguard Worker // Ensure the reference matches the inital output after conversion.
816*b9df5ad1SAndroid Build Coastguard Worker memcpy(q8_23ref, q8_23ary, 65536 * sizeof(q8_23ary[0]));
817*b9df5ad1SAndroid Build Coastguard Worker // Accumulate and check.
818*b9df5ad1SAndroid Build Coastguard Worker accumulate_q8_23(q8_23ary, q8_23add, 65536);
819*b9df5ad1SAndroid Build Coastguard Worker checkAddedClamped(
820*b9df5ad1SAndroid Build Coastguard Worker q8_23ary, q8_23ref, q8_23add, 65536, lim24neg, lim24pos);
821*b9df5ad1SAndroid Build Coastguard Worker // Cleanup.
822*b9df5ad1SAndroid Build Coastguard Worker delete[] q8_23ref;
823*b9df5ad1SAndroid Build Coastguard Worker delete[] q8_23add;
824*b9df5ad1SAndroid Build Coastguard Worker delete[] q8_23ary;
825*b9df5ad1SAndroid Build Coastguard Worker
826*b9df5ad1SAndroid Build Coastguard Worker // Test float.
827*b9df5ad1SAndroid Build Coastguard Worker float *fary = new float[65536];
828*b9df5ad1SAndroid Build Coastguard Worker float *fadd = new float[65536];
829*b9df5ad1SAndroid Build Coastguard Worker float *fref = new float[65536];
830*b9df5ad1SAndroid Build Coastguard Worker // Convert sample data to float to perform accumulate function.
831*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_i16(fary, i16ref, 65536);
832*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_i16(fadd, i16add, 65536);
833*b9df5ad1SAndroid Build Coastguard Worker // Ensure the reference matches the inital output after conversion.
834*b9df5ad1SAndroid Build Coastguard Worker memcpy(fref, fary, 65536 * sizeof(fary[0]));
835*b9df5ad1SAndroid Build Coastguard Worker // Accumulate and check. Floats aren't clamped by accumulate,
836*b9df5ad1SAndroid Build Coastguard Worker // but given the input is in the [-1.0, 1.0) range output should be in
837*b9df5ad1SAndroid Build Coastguard Worker // [-2.0, 2.0) range.
838*b9df5ad1SAndroid Build Coastguard Worker accumulate_float(fary, fadd, 65536);
839*b9df5ad1SAndroid Build Coastguard Worker checkAddedClamped(fary, fref, fadd, 65536, -2.0f, 2.0f);
840*b9df5ad1SAndroid Build Coastguard Worker // Cleanup.
841*b9df5ad1SAndroid Build Coastguard Worker delete[] fref;
842*b9df5ad1SAndroid Build Coastguard Worker delete[] fadd;
843*b9df5ad1SAndroid Build Coastguard Worker delete[] fary;
844*b9df5ad1SAndroid Build Coastguard Worker
845*b9df5ad1SAndroid Build Coastguard Worker delete[] i16ary;
846*b9df5ad1SAndroid Build Coastguard Worker delete[] i16add;
847*b9df5ad1SAndroid Build Coastguard Worker delete[] i16ref;
848*b9df5ad1SAndroid Build Coastguard Worker }
849*b9df5ad1SAndroid Build Coastguard Worker
850*b9df5ad1SAndroid Build Coastguard Worker
TEST(audio_utils_primitives,MemcpyToFloatFromFloatWithClamping)851*b9df5ad1SAndroid Build Coastguard Worker TEST(audio_utils_primitives, MemcpyToFloatFromFloatWithClamping) {
852*b9df5ad1SAndroid Build Coastguard Worker std::vector<float> src = {-INFINITY, -2, -1, -0, 0, 0.009, 1.000001, 9999999, INFINITY, NAN};
853*b9df5ad1SAndroid Build Coastguard Worker std::vector<float> dst(src.size());
854*b9df5ad1SAndroid Build Coastguard Worker float absMax = 1;
855*b9df5ad1SAndroid Build Coastguard Worker std::vector<float> expected = {-1, -1, -1, -0, 0, 0.009, 1, 1, 1, 1};
856*b9df5ad1SAndroid Build Coastguard Worker ASSERT_EQ(expected.size(), src.size());
857*b9df5ad1SAndroid Build Coastguard Worker
858*b9df5ad1SAndroid Build Coastguard Worker memcpy_to_float_from_float_with_clamping(dst.data(), src.data(), src.size(), absMax);
859*b9df5ad1SAndroid Build Coastguard Worker
860*b9df5ad1SAndroid Build Coastguard Worker ASSERT_EQ(dst, expected) << "src=" << testing::PrintToString(src);
861*b9df5ad1SAndroid Build Coastguard Worker }
862