1b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung/*
2b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung * Copyright (C) 2014 The Android Open Source Project
3b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung *
4b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung * Licensed under the Apache License, Version 2.0 (the "License");
5b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung * you may not use this file except in compliance with the License.
6b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung * You may obtain a copy of the License at
7b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung *
8b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung *      http://www.apache.org/licenses/LICENSE-2.0
9b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung *
10b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung * Unless required by applicable law or agreed to in writing, software
11b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung * distributed under the License is distributed on an "AS IS" BASIS,
12b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung * See the License for the specific language governing permissions and
14b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung * limitations under the License.
15b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung */
16b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
17b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung//#define LOG_NDEBUG 0
18b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung#define LOG_TAG "audio_utils_primitives_tests"
19b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
20f476054361310110757909bd63b022bca32ec649Dan Albert#include <math.h>
21b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung#include <vector>
228198c3b752e2fb00acb15345496e2a03eefb5ffbMark Salyzyn
23b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung#include <gtest/gtest.h>
244df5a2bb302fb5cb61ab48dff7fa2b1984b6ced8Mark Salyzyn#include <log/log.h>
258198c3b752e2fb00acb15345496e2a03eefb5ffbMark Salyzyn
26b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung#include <audio_utils/primitives.h>
27b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung#include <audio_utils/format.h>
28e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung#include <audio_utils/channels.h>
29b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
30b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
31b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
3210a7d323d942d143f5298010e228f3f8ff7c8328Andy Hungstatic const int32_t lim8pos = 255;
3310a7d323d942d143f5298010e228f3f8ff7c8328Andy Hungstatic const int32_t lim8neg = 0;
34b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hungstatic const int32_t lim16pos = (1 << 15) - 1;
35b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hungstatic const int32_t lim16neg = -(1 << 15);
36b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hungstatic const int32_t lim24pos = (1 << 23) - 1;
37b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hungstatic const int32_t lim24neg = -(1 << 23);
38b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
3910a7d323d942d143f5298010e228f3f8ff7c8328Andy Hunginline void testClamp8(float f)
4010a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung{
4110a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    // f is in native u8 scaling to test rounding
4210a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    uint8_t uval = clamp8_from_float((f - 128) / (1 << 7));
4310a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung
4410a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    // test clamping
4510a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    ALOGV("clamp8_from_float(%f) = %u\n", f, uval);
4610a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    if (f > lim8pos) {
4710a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung        EXPECT_EQ(lim8pos, uval);
4810a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    } else if (f < lim8neg) {
4910a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung        EXPECT_EQ(lim8neg, uval);
5010a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    }
5110a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung
5210a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    // if in range, make sure round trip clamp and conversion is correct.
5310a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    if (f < lim8pos - 1. && f > lim8neg + 1.) {
5410a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung        uint8_t uval2 = clamp8_from_float(float_from_u8(uval));
5510a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung        int diff = abs(uval - uval2);
5610a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung        EXPECT_LE(diff, 1);
5710a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    }
5810a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung}
5910a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung
60b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hunginline void testClamp16(float f)
61b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung{
6265b5ccd2a7a7c756db2cfa627ac75d17eb0484c2Andy Hung    int16_t ival = clamp16_from_float(f / (1 << 15));
63b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
64b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // test clamping
65b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    ALOGV("clamp16_from_float(%f) = %d\n", f, ival);
66b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    if (f > lim16pos) {
67bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung        EXPECT_EQ(lim16pos, ival);
68b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    } else if (f < lim16neg) {
69bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung        EXPECT_EQ(lim16neg, ival);
70b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    }
71b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
72b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // if in range, make sure round trip clamp and conversion is correct.
73b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    if (f < lim16pos - 1. && f > lim16neg + 1.) {
7465b5ccd2a7a7c756db2cfa627ac75d17eb0484c2Andy Hung        int ival2 = clamp16_from_float(float_from_i16(ival));
75b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung        int diff = abs(ival - ival2);
76b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung        EXPECT_LE(diff, 1);
77b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    }
78b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung}
79b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
80b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hunginline void testClamp24(float f)
81b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung{
82b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    int32_t ival = clamp24_from_float(f / (1 << 23));
83b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
84b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // test clamping
85b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    ALOGV("clamp24_from_float(%f) = %d\n", f, ival);
86b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    if (f > lim24pos) {
87bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung        EXPECT_EQ(lim24pos, ival);
88b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    } else if (f < lim24neg) {
89bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung        EXPECT_EQ(lim24neg, ival);
90b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    }
91b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
92b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // if in range, make sure round trip clamp and conversion is correct.
93b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    if (f < lim24pos - 1. && f > lim24neg + 1.) {
94b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung        int ival2 = clamp24_from_float(float_from_q8_23(ival));
95b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung        int diff = abs(ival - ival2);
96b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung        EXPECT_LE(diff, 1);
97b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    }
98b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung}
99b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
100b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hungtemplate<typename T>
101b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hungvoid checkMonotone(const T *ary, size_t size)
102b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung{
103b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    for (size_t i = 1; i < size; ++i) {
104b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung        EXPECT_LT(ary[i-1], ary[i]);
105b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    }
106b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung}
107b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung
108bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew Georgevoid checkMonotonep24(uint8_t * pary, size_t size)
109bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George{
110bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    size_t frames = size/3;
111bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    for (size_t i = 1; i < frames; ++i) {
112bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George        EXPECT_LT(i32_from_p24(pary + 3*(i-1)), i32_from_p24(pary + 3*i));
113bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    }
114bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George}
115bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George
116b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy HungTEST(audio_utils_primitives, clamp_to_int) {
117b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    static const float testArray[] = {
118b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            -NAN, -INFINITY,
119b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            -1.e20, -32768., 63.9,
120b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            -3.5, -3.4, -2.5, 2.4, -1.5, -1.4, -0.5, -0.2, 0., 0.2, 0.5, 0.8,
121b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            1.4, 1.5, 1.8, 2.4, 2.5, 2.6, 3.4, 3.5,
122b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            32767., 32768., 1.e20,
123b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            INFINITY, NAN };
124b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
125b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
12610a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung        testClamp8(testArray[i]);
12710a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    }
12810a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
129b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung        testClamp16(testArray[i]);
130b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    }
131b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
132b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung        testClamp24(testArray[i]);
133b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    }
134b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung
135b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    // used for ULP testing (tweaking the lsb of the float)
136b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    union {
137b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung        int32_t i;
138b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung        float f;
139b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    } val;
140b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    int32_t res;
141b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung
142b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    // check clampq4_27_from_float()
143b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    val.f = 16.;
144b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    res = clampq4_27_from_float(val.f);
145bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ(0x7fffffff, res);
146b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    val.i--;
147b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    res = clampq4_27_from_float(val.f);
148b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    EXPECT_LE(res, 0x7fffffff);
149b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    EXPECT_GE(res, 0x7fff0000);
150b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    val.f = -16.;
151b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    res = clampq4_27_from_float(val.f);
152bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((int32_t)0x80000000, res); // negative
153b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    val.i++;
154b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    res = clampq4_27_from_float(val.f);
155b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    EXPECT_GE(res, (int32_t)0x80000000); // negative
156b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    EXPECT_LE(res, (int32_t)0x80008000); // negative
157de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung
158de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    // check u4_28_from_float and u4_12_from_float
159de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    uint32_t ures;
160de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    uint16_t ures16;
161de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    val.f = 16.;
162de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    ures = u4_28_from_float(val.f);
163bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ(0xffffffff, ures);
164de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    ures16 = u4_12_from_float(val.f);
165bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ(0xffff, ures16);
166de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung
167de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    val.f = -1.;
168de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    ures = u4_28_from_float(val.f);
169bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((uint32_t)0, ures);
170de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    ures16 = u4_12_from_float(val.f);
171bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ(0, ures16);
172de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung
173de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    // check float_from_u4_28 and float_from_u4_12 (roundtrip)
174de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    for (uint32_t v = 0x100000; v <= 0xff000000; v += 0x100000) {
175de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung        ures = u4_28_from_float(float_from_u4_28(v));
176de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung        EXPECT_EQ(ures, v);
177de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    }
178de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    for (uint32_t v = 0; v <= 0xffff; ++v) { // uint32_t prevents overflow
179de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung        ures16 = u4_12_from_float(float_from_u4_12(v));
180de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung        EXPECT_EQ(ures16, v);
181de9a62b5a163e343a1ed8e1068741e227122d510Andy Hung    }
18210a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung
18310a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    // check infinity
18410a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    EXPECT_EQ(0, clamp8_from_float(-INFINITY));
18510a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    EXPECT_EQ(255, clamp8_from_float(INFINITY));
186b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung}
187b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
188b533bd205c5a0dd35736cf4d46bda804175899c5Andy HungTEST(audio_utils_primitives, memcpy) {
189b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // test round-trip.
190b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    int16_t *i16ref = new int16_t[65536];
191b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    int16_t *i16ary = new int16_t[65536];
192b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    int32_t *i32ary = new int32_t[65536];
193b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    float *fary = new float[65536];
194b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    uint8_t *pary = new uint8_t[65536*3];
195b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
196b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    for (size_t i = 0; i < 65536; ++i) {
197b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung        i16ref[i] = i16ary[i] = i - 32768;
198b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    }
199b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
200b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // do round-trip testing i16 and float
201b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_float_from_i16(fary, i16ary, 65536);
202b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
203b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(fary, 65536);
204b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
205b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_i16_from_float(i16ary, fary, 65536);
206b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(fary, 0, 65536 * sizeof(fary[0]));
207b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(i16ary, 65536);
208b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
209b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // TODO make a template case for the following?
210b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
211b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // do round-trip testing p24 to i16 and float
212b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_p24_from_i16(pary, i16ary, 65536);
213b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
214b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
215b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // check an intermediate format at a position(???)
216b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung#if 0
217b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    printf("pary[%d].0 = %u  pary[%d].1 = %u  pary[%d].2 = %u\n",
218b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            1025, (unsigned) pary[1025*3],
219b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            1025, (unsigned) pary[1025*3+1],
220b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            1025, (unsigned) pary[1025*3+2]
221b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung            );
222b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung#endif
223b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
224b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_float_from_p24(fary, pary, 65536);
225b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
226b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(fary, 65536);
227b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
228b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_p24_from_float(pary, fary, 65536);
229b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(fary, 0, 65536 * sizeof(fary[0]));
230b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
231b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_i16_from_p24(i16ary, pary, 65536);
232b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
233b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(i16ary, 65536);
234b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
235b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // do round-trip testing q8_23 to i16 and float
236b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_q8_23_from_i16(i32ary, i16ary, 65536);
237b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
238b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(i32ary, 65536);
239b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
240b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_float_from_q8_23(fary, i32ary, 65536);
241b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
242b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(fary, 65536);
243b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
244b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_q8_23_from_float_with_clamp(i32ary, fary, 65536);
245b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(fary, 0, 65536 * sizeof(fary[0]));
246b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(i32ary, 65536);
247b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
248b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_i16_from_q8_23(i16ary, i32ary, 65536);
249b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
250b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(i16ary, 65536);
251b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
252b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    // do round-trip testing i32 to i16 and float
253b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_i32_from_i16(i32ary, i16ary, 65536);
254b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
255b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(i32ary, 65536);
256b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
257b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_float_from_i32(fary, i32ary, 65536);
258b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
259b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(fary, 65536);
260b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
261b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_i32_from_float(i32ary, fary, 65536);
262b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(fary, 0, 65536 * sizeof(fary[0]));
263b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(i32ary, 65536);
264b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
265b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memcpy_to_i16_from_i32(i16ary, i32ary, 65536);
266b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
267b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(i16ary, 65536);
268b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
269bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    // do round-trip test i16 -> p24 -> i32 -> p24 -> q8_23 -> p24 -> i16
270bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memcpy_to_p24_from_i16(pary, i16ary, 65536);
271bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
272bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    checkMonotonep24(pary, 65536 * 3);
273bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George
274bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memcpy_to_i32_from_p24(i32ary, pary, 65536);
275bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
276bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    checkMonotone(i32ary, 65536);
277bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George
278bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memcpy_to_p24_from_i32(pary, i32ary, 65536);
279bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
280bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    checkMonotonep24(pary, 65536 * 3);
281bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George
282bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memcpy_to_q8_23_from_p24(i32ary, pary, 65536);
283bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
284bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    checkMonotone(i32ary, 65536);
285bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George
286bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memcpy_to_p24_from_q8_23(pary, i32ary, 65536);
287bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
288bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    checkMonotonep24(pary, 65536 * 3);
289bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George
290bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memcpy_to_i16_from_p24(i16ary, pary, 65536);
291bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
292bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George    checkMonotone(i16ary, 65536);
293bad0898a944d6a7886b4ab8ca8e0157885d9aadfHaynes Mathew George
294b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    // do partial round-trip testing q4_27 to i16 and float
295b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    memcpy_to_float_from_i16(fary, i16ary, 65536);
296b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    //memset(i16ary, 0, 65536 * sizeof(i16ary[0])); // not cleared: we don't do full roundtrip
297b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung
298b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    memcpy_to_q4_27_from_float(i32ary, fary, 65536);
299b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    memset(fary, 0, 65536 * sizeof(fary[0]));
300b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(i32ary, 65536);
301b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung
302b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    memcpy_to_float_from_q4_27(fary, i32ary, 65536);
303b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
304b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    checkMonotone(fary, 65536);
305b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung
306b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    // at the end, our i16ary must be the same. (Monotone should be equivalent to this)
307bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ(0, memcmp(i16ary, i16ref, 65536*sizeof(i16ary[0])));
308b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung
30910a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    // test round-trip for u8 and float.
31010a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    uint8_t *u8ref = new uint8_t[256];
31110a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    uint8_t *u8ary = new uint8_t[256];
31210a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung
31310a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    for (unsigned i = 0; i < 256; ++i) {
31410a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung        u8ref[i] = i;
31510a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    }
31610a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung
31710a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    memcpy_to_float_from_u8(fary, u8ref, 256);
31810a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    memcpy_to_u8_from_float(u8ary, fary, 256);
31910a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung
32010a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    EXPECT_EQ(0, memcmp(u8ary, u8ref, 256 * sizeof(u8ary[0])));
32110a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung
32210a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    delete[] u8ref;
32310a7d323d942d143f5298010e228f3f8ff7c8328Andy Hung    delete[] u8ary;
324b878e52fd43ea10f8d45eb29e5901ec1c8fb7278Andy Hung    delete[] i16ref;
325b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    delete[] i16ary;
326b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    delete[] i32ary;
327b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    delete[] fary;
328b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung    delete[] pary;
329b533bd205c5a0dd35736cf4d46bda804175899c5Andy Hung}
3303af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3313af2af2518dc5534c94285e77d39d0fc729ed917Andy Hungtemplate<typename T>
3323af2af2518dc5534c94285e77d39d0fc729ed917Andy Hungvoid checkMonotoneOrZero(const T *ary, size_t size)
3333af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung{
3343af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    T least = 0;
3353af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3363af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    for (size_t i = 1; i < size; ++i) {
3373af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung        if (ary[i]) {
3383af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            EXPECT_LT(least, ary[i]);
3393af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            least = ary[i];
3403af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung        }
3413af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    }
3423af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung}
3433af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3443af2af2518dc5534c94285e77d39d0fc729ed917Andy HungTEST(audio_utils_primitives, memcpy_by_channel_mask) {
3453af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint32_t dst_mask;
3463af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint32_t src_mask;
3473af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint16_t *u16ref = new uint16_t[65536];
3483af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint16_t *u16ary = new uint16_t[65536];
3493af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3503af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    for (size_t i = 0; i < 65536; ++i) {
3513af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung        u16ref[i] = i;
3523af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    }
3533af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3543af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test when src mask is 0.  Everything copied is zero.
3553af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = 0;
3563af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    dst_mask = 0x8d;
3573af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
3583af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
3593af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            65536 / popcount(dst_mask));
360bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
3613af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3623af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test when dst_mask is 0.  Nothing should be copied.
3633af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = 0;
3643af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    dst_mask = 0;
3653af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u16ary, 0, 65536 * sizeof(u16ref[0]));
3663af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
3673af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            65536);
368bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
3693af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3703af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test when masks are the same.  One to one copy.
3713af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = dst_mask = 0x8d;
3723af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
3733af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]), 555);
374bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ(0, memcmp(u16ary, u16ref, 555 * sizeof(u16ref[0]) * popcount(dst_mask)));
3753af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3763af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test with a gap in source:
3773af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Input 3 samples, output 4 samples, one zero inserted.
3783af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = 0x8c;
3793af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    dst_mask = 0x8d;
3803af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
3813af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
3823af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            65536 / popcount(dst_mask));
3833af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    checkMonotoneOrZero(u16ary, 65536);
384bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
3853af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3863af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test with a gap in destination:
3873af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Input 4 samples, output 3 samples, one deleted
3883af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = 0x8d;
3893af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    dst_mask = 0x8c;
3903af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
3913af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
3923af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            65536 / popcount(src_mask));
3933af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    checkMonotone(u16ary, 65536 * 3 / 4);
3943af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3953af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    delete[] u16ref;
3963af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    delete[] u16ary;
3973af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung}
3983af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
3993af2af2518dc5534c94285e77d39d0fc729ed917Andy Hungvoid memcpy_by_channel_mask2(void *dst, uint32_t dst_mask,
4003af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung        const void *src, uint32_t src_mask, size_t sample_size, size_t count)
4013af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung{
4023af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    int8_t idxary[32];
4033af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint32_t src_channels = popcount(src_mask);
4043af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint32_t dst_channels =
4053af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask);
4063af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
4073af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
4083af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung}
4093af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
4103af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung// a modified version of the memcpy_by_channel_mask test
4113af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung// but using 24 bit type and memcpy_by_index_array()
4123af2af2518dc5534c94285e77d39d0fc729ed917Andy HungTEST(audio_utils_primitives, memcpy_by_index_array) {
4133af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint32_t dst_mask;
4143af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint32_t src_mask;
4153af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
4163af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint8x3_t *u24ref = new uint8x3_t[65536];
4173af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint8x3_t *u24ary = new uint8x3_t[65536];
4183af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint16_t *u16ref = new uint16_t[65536];
4193af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    uint16_t *u16ary = new uint16_t[65536];
4203af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
421bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
4223af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
4233af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // tests prepare_index_array_from_masks()
424bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization(NULL, 0, 0x8d, 0x8c));
425bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization(NULL, 0, 0x8c, 0x8d));
4263af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
4273af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    for (size_t i = 0; i < 65536; ++i) {
4283af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung        u16ref[i] = i;
4293af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    }
4303af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
4313af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
4323af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test when src mask is 0.  Everything copied is zero.
4333af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = 0;
4343af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    dst_mask = 0x8d;
4353af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
4363af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
4373af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            65536 / popcount(dst_mask));
4383af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
439bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
4403af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
4413af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test when dst_mask is 0.  Nothing should be copied.
4423af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = 0;
4433af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    dst_mask = 0;
4443af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
4453af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
4463af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            65536);
4473af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
448bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
4493af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
4503af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test when masks are the same.  One to one copy.
4513af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = dst_mask = 0x8d;
4523af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
4533af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
454bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
4553af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
4563af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test with a gap in source:
4573af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Input 3 samples, output 4 samples, one zero inserted.
4583af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = 0x8c;
4593af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    dst_mask = 0x8d;
4603af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
4613af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
4623af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            65536 / popcount(dst_mask));
4633af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
4643af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    checkMonotoneOrZero(u16ary, 65536);
465bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
4663af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
4673af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Test with a gap in destination:
4683af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    // Input 4 samples, output 3 samples, one deleted
4693af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    src_mask = 0x8d;
4703af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    dst_mask = 0x8c;
4713af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
4723af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
4733af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung            65536 / popcount(src_mask));
4743af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
4753af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    checkMonotone(u16ary, 65536 * 3 / 4);
476291a1948093850aa87f60264680404b2b96ee327Andy Hung
477291a1948093850aa87f60264680404b2b96ee327Andy Hung    delete[] u16ref;
478291a1948093850aa87f60264680404b2b96ee327Andy Hung    delete[] u16ary;
479291a1948093850aa87f60264680404b2b96ee327Andy Hung    delete[] u24ref;
480291a1948093850aa87f60264680404b2b96ee327Andy Hung    delete[] u24ary;
481291a1948093850aa87f60264680404b2b96ee327Andy Hung}
482291a1948093850aa87f60264680404b2b96ee327Andy Hung
483291a1948093850aa87f60264680404b2b96ee327Andy Hungvoid memcpy_by_channel_mask_dst_index(void *dst, uint32_t dst_mask,
484291a1948093850aa87f60264680404b2b96ee327Andy Hung        const void *src, uint32_t src_mask, size_t sample_size, size_t count)
485291a1948093850aa87f60264680404b2b96ee327Andy Hung{
486291a1948093850aa87f60264680404b2b96ee327Andy Hung    int8_t idxary[32];
487291a1948093850aa87f60264680404b2b96ee327Andy Hung    uint32_t src_channels = popcount(src_mask);
488291a1948093850aa87f60264680404b2b96ee327Andy Hung    uint32_t dst_channels =
489291a1948093850aa87f60264680404b2b96ee327Andy Hung            memcpy_by_index_array_initialization_dst_index(idxary, 32, dst_mask, src_mask);
490291a1948093850aa87f60264680404b2b96ee327Andy Hung
491291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
492291a1948093850aa87f60264680404b2b96ee327Andy Hung}
493291a1948093850aa87f60264680404b2b96ee327Andy Hung
494291a1948093850aa87f60264680404b2b96ee327Andy Hung// a modified version of the memcpy_by_channel_mask test
495291a1948093850aa87f60264680404b2b96ee327Andy Hung// but using 24 bit type and memcpy_by_index_array()
496291a1948093850aa87f60264680404b2b96ee327Andy HungTEST(audio_utils_primitives, memcpy_by_index_array_dst_index) {
497291a1948093850aa87f60264680404b2b96ee327Andy Hung    uint32_t dst_mask;
498291a1948093850aa87f60264680404b2b96ee327Andy Hung    uint32_t src_mask;
499291a1948093850aa87f60264680404b2b96ee327Andy Hung    typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
500291a1948093850aa87f60264680404b2b96ee327Andy Hung    uint8x3_t *u24ref = new uint8x3_t[65536];
501291a1948093850aa87f60264680404b2b96ee327Andy Hung    uint8x3_t *u24ary = new uint8x3_t[65536];
502291a1948093850aa87f60264680404b2b96ee327Andy Hung    uint16_t *u16ref = new uint16_t[65536];
503291a1948093850aa87f60264680404b2b96ee327Andy Hung    uint16_t *u16ary = new uint16_t[65536];
504291a1948093850aa87f60264680404b2b96ee327Andy Hung
505291a1948093850aa87f60264680404b2b96ee327Andy Hung    EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
506291a1948093850aa87f60264680404b2b96ee327Andy Hung
507291a1948093850aa87f60264680404b2b96ee327Andy Hung    // tests prepare_index_array_from_masks()
508291a1948093850aa87f60264680404b2b96ee327Andy Hung    EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization_dst_index(NULL, 0, 0x8d, 0x8c));
509291a1948093850aa87f60264680404b2b96ee327Andy Hung    EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_dst_index(NULL, 0, 0x8c, 0x8d));
510291a1948093850aa87f60264680404b2b96ee327Andy Hung
511291a1948093850aa87f60264680404b2b96ee327Andy Hung    for (size_t i = 0; i < 65536; ++i) {
512291a1948093850aa87f60264680404b2b96ee327Andy Hung        u16ref[i] = i;
513291a1948093850aa87f60264680404b2b96ee327Andy Hung    }
514291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
515291a1948093850aa87f60264680404b2b96ee327Andy Hung
516291a1948093850aa87f60264680404b2b96ee327Andy Hung    // Test when src mask is 0.  Everything copied is zero.
517291a1948093850aa87f60264680404b2b96ee327Andy Hung    src_mask = 0;
518291a1948093850aa87f60264680404b2b96ee327Andy Hung    dst_mask = 0x8d;
519291a1948093850aa87f60264680404b2b96ee327Andy Hung    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
520291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
521291a1948093850aa87f60264680404b2b96ee327Andy Hung            65536 / popcount(dst_mask));
522291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
523291a1948093850aa87f60264680404b2b96ee327Andy Hung    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
524291a1948093850aa87f60264680404b2b96ee327Andy Hung
525291a1948093850aa87f60264680404b2b96ee327Andy Hung    // Test when dst_mask is 0.  Nothing should be copied.
526291a1948093850aa87f60264680404b2b96ee327Andy Hung    src_mask = 0;
527291a1948093850aa87f60264680404b2b96ee327Andy Hung    dst_mask = 0;
528291a1948093850aa87f60264680404b2b96ee327Andy Hung    memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
529291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
530291a1948093850aa87f60264680404b2b96ee327Andy Hung            65536);
531291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
532291a1948093850aa87f60264680404b2b96ee327Andy Hung    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
533291a1948093850aa87f60264680404b2b96ee327Andy Hung
534291a1948093850aa87f60264680404b2b96ee327Andy Hung    // Test when dst mask equals source count size.  One to one copy.
535291a1948093850aa87f60264680404b2b96ee327Andy Hung    src_mask = 0x8d;
536291a1948093850aa87f60264680404b2b96ee327Andy Hung    dst_mask = 0x0f;
537291a1948093850aa87f60264680404b2b96ee327Andy Hung    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
538291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
539291a1948093850aa87f60264680404b2b96ee327Andy Hung    EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
540291a1948093850aa87f60264680404b2b96ee327Andy Hung
541291a1948093850aa87f60264680404b2b96ee327Andy Hung    // Test with a gap in source:
542291a1948093850aa87f60264680404b2b96ee327Andy Hung    // Input 3 samples, output 4 samples, one zero inserted.
543291a1948093850aa87f60264680404b2b96ee327Andy Hung    src_mask = 0x8c;
544291a1948093850aa87f60264680404b2b96ee327Andy Hung    dst_mask = 0x0f;
545291a1948093850aa87f60264680404b2b96ee327Andy Hung    memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
546291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
547291a1948093850aa87f60264680404b2b96ee327Andy Hung            65536 / popcount(dst_mask));
548291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
549291a1948093850aa87f60264680404b2b96ee327Andy Hung    checkMonotoneOrZero(u16ary, 65536);
550291a1948093850aa87f60264680404b2b96ee327Andy Hung    EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
551291a1948093850aa87f60264680404b2b96ee327Andy Hung
552291a1948093850aa87f60264680404b2b96ee327Andy Hung    // Test with a gap in destination:
553291a1948093850aa87f60264680404b2b96ee327Andy Hung    // Input 4 samples, output 3 samples, one deleted
554291a1948093850aa87f60264680404b2b96ee327Andy Hung    src_mask = 0x8d;
555291a1948093850aa87f60264680404b2b96ee327Andy Hung    dst_mask = 0x07;
556291a1948093850aa87f60264680404b2b96ee327Andy Hung    memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
557291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
558291a1948093850aa87f60264680404b2b96ee327Andy Hung            65536 / popcount(src_mask));
559291a1948093850aa87f60264680404b2b96ee327Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
560291a1948093850aa87f60264680404b2b96ee327Andy Hung    checkMonotone(u16ary, 65536 * 3 / 4);
5613af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung
5623af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    delete[] u16ref;
5633af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    delete[] u16ary;
5643af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    delete[] u24ref;
5653af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung    delete[] u24ary;
5663af2af2518dc5534c94285e77d39d0fc729ed917Andy Hung}
567e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung
5685a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hungvoid memcpy_by_channel_mask_src_index(void *dst, uint32_t dst_mask,
5695a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung        const void *src, uint32_t src_mask, size_t sample_size, size_t count)
5705a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung{
5715a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    int8_t idxary[32];
5725a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    uint32_t src_channels = popcount(src_mask);
5735a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    uint32_t dst_channels =
5745a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung            memcpy_by_index_array_initialization_src_index(idxary, 32, dst_mask, src_mask);
5755a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
5765a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
5775a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung}
5785a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
5795a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung// a modified version of the memcpy_by_channel_mask test
5805a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung// but using 24 bit type and memcpy_by_index_array()
5815a0d0285cdd75cd5c94e020311830d634d6587b0Andy HungTEST(audio_utils_primitives, memcpy_by_index_array_src_index) {
5825a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    uint32_t dst_mask;
5835a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    uint32_t src_mask;
5845a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
5855a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    uint8x3_t *u24ref = new uint8x3_t[65536];
5865a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    uint8x3_t *u24ary = new uint8x3_t[65536];
5875a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    uint16_t *u16ref = new uint16_t[65536];
5885a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    uint16_t *u16ary = new uint16_t[65536];
5895a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
5905a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
5915a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
5925a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    // tests prepare_index_array_from_masks()
5935a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8d, 0x8c));
5945a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8c, 0x8d));
5955a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
5965a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    for (size_t i = 0; i < 65536; ++i) {
5975a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung        u16ref[i] = i;
5985a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    }
5995a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
6005a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
6015a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    // Test when src mask is 0.  Everything copied is zero.
6025a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    src_mask = 0;
6035a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    dst_mask = 0x8d;
6045a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
6055a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
6065a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung            65536 / popcount(dst_mask));
6075a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
6085a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
6095a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
6105a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    // Test when dst_mask is 0.  Nothing should be copied.
6115a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    src_mask = 0;
6125a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    dst_mask = 0;
6135a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
6145a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
6155a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung            65536);
6165a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
6175a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
6185a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
6195a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    // Test when source mask must copy to dst mask.  One to one copy.
6205a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    src_mask = 0xf;
6215a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    dst_mask = 0xf;
6225a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
6235a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
6245a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
6255a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
6265a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    // Test when source mask must copy to dst mask.  One to one copy.
6275a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    src_mask = 0xf;
6285a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    dst_mask = 0x8d;
6295a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
6305a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
6315a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
6325a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
6335a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    // Test with a gap in source:
6345a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    // Input 3 samples, output 4 samples, one zero inserted.
6355a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    src_mask = 0x07;
6365a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    dst_mask = 0x8d;
6375a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
6385a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
6395a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung            65536 / popcount(dst_mask));
6405a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
6415a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    checkMonotoneOrZero(u16ary, 65536);
6425a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
6435a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
6445a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    // Test with a gap in destination:
6455a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    // Input 4 samples, output 3 samples, one deleted
6465a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    src_mask = 0x0f;
6475a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    dst_mask = 0x8c;
6485a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
6495a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
6505a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung            65536 / popcount(src_mask));
6515a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
6525a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    checkMonotone(u16ary, 65536 * 3 / 4);
6535a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
6545a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    delete[] u16ref;
6555a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    delete[] u16ary;
6565a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    delete[] u24ref;
6575a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung    delete[] u24ary;
6585a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung}
6595a0d0285cdd75cd5c94e020311830d634d6587b0Andy Hung
660e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy HungTEST(audio_utils_channels, adjust_channels) {
661e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    uint16_t *u16ref = new uint16_t[65536];
662e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    uint16_t *u16expand = new uint16_t[65536*2];
663e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    uint16_t *u16ary = new uint16_t[65536];
664e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung
665e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    // reference buffer always increases
666e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    for (size_t i = 0; i < 65536; ++i) {
667e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung        u16ref[i] = i;
668e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    }
669e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung
670e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    // expand channels from stereo to quad.
671e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    adjust_channels(u16ref /*in_buff*/, 2 /*in_channels*/,
672e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung            u16expand /*out_buff*/, 4 /*out_channels*/,
673e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung            sizeof(u16ref[0]) /*sample_size_in_bytes*/,
674e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung            sizeof(u16ref[0])*65536 /*num_in_bytes*/);
675e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung
676e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    // expanded buffer must increase (or be zero)
677e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    checkMonotoneOrZero(u16expand, 65536*2);
678e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung
679e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    // contract channels back to stereo.
680e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    adjust_channels(u16expand /*in_buff*/, 4 /*in_channels*/,
681e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung            u16ary /*out_buff*/, 2 /*out_channels*/,
682e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung            sizeof(u16expand[0]) /*sample_size_in_bytes*/,
683e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung            sizeof(u16expand[0])*65536*2 /*num_in_bytes*/);
684e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung
685e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    // must be identical to original.
686bbc7281af9719774ea310fbeff3830f3aadd5edeAndy Hung    EXPECT_EQ(0, memcmp(u16ary, u16ref, sizeof(u16ref[0])*65536));
687e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung
688e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    delete[] u16ref;
689e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    delete[] u16expand;
690e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung    delete[] u16ary;
691e0ccb20d0b3ab5c686508a7b1413928320ec2d1fAndy Hung}
692