1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "gtest/gtest.h"
17 #include "hpae_pcm_dumper.h"
18 #include "hpae_format_convert.h"
19 #include "hpae_format_convert.cpp"
20
21 #define FLOAT_EPS_24BIT (1.0f / 8388608.0f)
22
23 using namespace OHOS;
24 using namespace AudioStandard;
25 using namespace HPAE;
26 using namespace testing::ext;
27 using namespace testing;
28
29 namespace OHOS {
30 namespace AudioStandard {
31 namespace HPAE {
32
33 static std::string g_rootCapturerPath = "/data/source_file_io_48000_2_s16le.pcm";
34 constexpr uint32_t TEST_FRAMES = 4;
35 constexpr uint32_t NUM_TWO = 2;
36 constexpr uint32_t NUM_THREE = 3;
37 constexpr uint32_t NUM_SIX = 6;
38 constexpr uint32_t NUM_NINE = 9;
39 constexpr uint32_t FLOAT_SAMPLE_FORMAT = 99;
40 constexpr uint32_t SHIFT_BIT_WIDTH_22 = 22;
41 constexpr uint32_t SHIFT_BIT_WIDTH_16 = 16;
42 constexpr uint32_t SHIFT_BIT_WIDTH_8 = 8;
43
44 class HpaePcmUtilsTest : public ::testing::Test {
45 protected:
46 void SetUp();
47 void TearDown();
48 };
49
SetUp()50 void HpaePcmUtilsTest::SetUp()
51 {}
52
TearDown()53 void HpaePcmUtilsTest::TearDown()
54 {}
55
56 HWTEST_F(HpaePcmUtilsTest, pcmDumperFile, TestSize.Level0)
57 {
58 HpaePcmDumper dumper1(g_rootCapturerPath);
59 EXPECT_EQ(dumper1.filename_, g_rootCapturerPath);
60
61 std::string invalidFilename = "";
62 HpaePcmDumper dumper2(invalidFilename);
63 EXPECT_EQ(dumper2.filename_, invalidFilename);
64 }
65
66 HWTEST_F(HpaePcmUtilsTest, readWrite24Bit, TestSize.Level0)
67 {
68 uint8_t data[NUM_THREE] = {0xAA, 0xBB, 0xCC};
69 uint32_t value = Read24Bit(data);
70 EXPECT_EQ(value, 0xCCBBAA);
71
72 uint8_t newData[NUM_THREE];
73 Write24Bit(newData, 0xDDEEFF);
74 EXPECT_EQ(newData[0], 0xFF);
75 EXPECT_EQ(newData[1], 0xEE);
76 EXPECT_EQ(newData[NUM_TWO], 0xDD);
77 }
78
79 HWTEST_F(HpaePcmUtilsTest, convertU8ToFloat, TestSize.Level0)
80 {
81 uint8_t u8Data[] = {0x80, 0xFF, 0x00, 0xC0};
82 float floatData[TEST_FRAMES];
83 ConvertFromU8ToFloat(TEST_FRAMES, u8Data, floatData);
84 EXPECT_FLOAT_EQ(floatData[0], 0.0f);
85 EXPECT_FLOAT_EQ(floatData[1], 0.9921875f);
86 EXPECT_FLOAT_EQ(floatData[NUM_TWO], -1.0f);
87 EXPECT_FLOAT_EQ(floatData[NUM_THREE], 0.5f);
88 }
89
90 HWTEST_F(HpaePcmUtilsTest, boundaryValueHandling, TestSize.Level0)
91 {
92 float boundaryFloat[NUM_TWO] = {
93 1.0f + FLOAT_EPS,
94 -1.0f - NUM_TWO * FLOAT_EPS
95 };
96 int16_t s16Data[NUM_TWO];
97 ConvertFromFloatTo16Bit(NUM_TWO, boundaryFloat, s16Data);
98 EXPECT_EQ(s16Data[0], INT16_MAX);
99 EXPECT_EQ(s16Data[1], -32767); // -32767: INT_MIN
100 }
101
102 HWTEST_F(HpaePcmUtilsTest, convertToFloatAllFormats, TestSize.Level0)
103 {
104 float output[TEST_FRAMES] = {0};
105 const float eps = std::numeric_limits<float>::epsilon();
106
107 // SAMPLE_U8
108 uint8_t u8Data[] = {128, 255, 0, 192};
109 ConvertToFloat(SAMPLE_U8, TEST_FRAMES, u8Data, output);
110 EXPECT_FLOAT_EQ(output[0], 0.0f);
111 EXPECT_FLOAT_EQ(output[1], 127.0f / 128.0f);
112 EXPECT_FLOAT_EQ(output[NUM_TWO], -1.0f);
113 EXPECT_FLOAT_EQ(output[NUM_THREE], 0.5f);
114
115 // SAMPLE_S16LE
116 int16_t s16Data[] = {0, INT16_MAX, INT16_MIN, 12345};
117 ConvertToFloat(SAMPLE_S16LE, TEST_FRAMES, s16Data, output);
118 EXPECT_FLOAT_EQ(output[0], 0.0f);
119 EXPECT_FLOAT_EQ(output[1], static_cast<float>(INT16_MAX) / 32768.0f);
120 EXPECT_FLOAT_EQ(output[NUM_TWO], -1.0f);
121 EXPECT_NEAR(output[NUM_THREE], 12345.0f / 32768.0f, eps);
122
123 // SAMPLE_S24LE
124 uint8_t s24Data[6] = {0}; // 6: data size
125 Write24Bit(s24Data, 0x7FFFFF); // 8388607
126 Write24Bit(s24Data + NUM_THREE, 0x800000); // -8388608
127 ConvertToFloat(SAMPLE_S24LE, NUM_TWO, s24Data, output);
128 EXPECT_FLOAT_EQ(output[0], 8388607.0f / 8388608.0f);
129 EXPECT_FLOAT_EQ(output[1], -1.0f);
130
131 // SAMPLE_S32LE
132 int32_t s32Data[] = {0, INT32_MAX, INT32_MIN, 123456789};
133 ConvertToFloat(SAMPLE_S32LE, TEST_FRAMES, s32Data, output);
134 EXPECT_FLOAT_EQ(output[0], 0.0f);
135 EXPECT_FLOAT_EQ(output[1], static_cast<float>(INT32_MAX) / 2147483648.0f);
136 EXPECT_FLOAT_EQ(output[NUM_TWO], -1.0f);
137 EXPECT_NEAR(output[NUM_THREE], 123456789.0f / 2147483648.0f, eps);
138
139 // FLOAT
140 float floatData[] = {0.0f, 0.5f, -0.5f, 1.0f - eps};
141 ConvertToFloat(static_cast<AudioSampleFormat>(FLOAT_SAMPLE_FORMAT), TEST_FRAMES, floatData, output);
142 for (size_t i = 0; i < TEST_FRAMES; ++i) {
143 EXPECT_FLOAT_EQ(output[i], floatData[i]);
144 }
145 }
146
147 HWTEST_F(HpaePcmUtilsTest, memcpyFallback, TestSize.Level0)
148 {
149 float src[TEST_FRAMES] = {0.1f, 0.2f, 0.3f, 0.4f};
150 float dest[1];
151 ConvertToFloat(static_cast<AudioSampleFormat>(FLOAT_SAMPLE_FORMAT), TEST_FRAMES, src, dest);
152 EXPECT_FLOAT_EQ(dest[0], 0.1f);
153 float newSrc[TEST_FRAMES] = {0.5f, 0.6f, 0.7f, 0.8f};
154 float newDest[TEST_FRAMES];
155 ConvertFromFloat(static_cast<AudioSampleFormat>(FLOAT_SAMPLE_FORMAT), TEST_FRAMES, newSrc, newDest);
156 EXPECT_FLOAT_EQ(newDest[0], 0.5f);
157 EXPECT_FLOAT_EQ(newDest[1], 0.6f);
158 EXPECT_FLOAT_EQ(newDest[NUM_TWO], 0.7f);
159 EXPECT_FLOAT_EQ(newDest[NUM_THREE], 0.8f);
160 }
161
162 HWTEST_F(HpaePcmUtilsTest, bit24SpecialHandling, TestSize.Level0)
163 {
164 uint8_t s24Input[12] = {0}; // 12: inputsize
165 float floatOutput[4]; // // 4: outputsize
166 Write24Bit(s24Input, 0x7FFFFF);
167 Write24Bit(s24Input + NUM_THREE, 0x800000);
168 Write24Bit(s24Input + NUM_SIX, 0x123456);
169 Write24Bit(s24Input + NUM_NINE, 0xABCDEF);
170 ConvertFrom24BitToFloat(4, s24Input, floatOutput); // 4: size
171 EXPECT_FLOAT_EQ(floatOutput[0], 1.0f - FLOAT_EPS_24BIT);
172 EXPECT_FLOAT_EQ(floatOutput[1], -1.0f);
173 }
174
175 HWTEST_F(HpaePcmUtilsTest, convertFromFloatAllFormats, TestSize.Level0)
176 {
177 float testFloat[TEST_FRAMES] = {
178 0.0f,
179 0.5f,
180 -0.5f,
181 1.0f - FLOAT_EPS
182 };
183 // U8: [0, 255], 128 is zero
184 uint8_t u8Output[TEST_FRAMES];
185 ConvertFromFloat(SAMPLE_U8, TEST_FRAMES, testFloat, u8Output);
186 EXPECT_EQ(u8Output[0], 128); // 128: 0.0f
187 EXPECT_EQ(u8Output[1], 191); // 191: 0.5f
188 EXPECT_EQ(u8Output[NUM_TWO], 64); // 64: -0.5f
189 EXPECT_EQ(u8Output[NUM_THREE], 254); // 254: near 1.0f
190 // S16LE: [-32768, 32767]
191 int16_t s16Output[TEST_FRAMES];
192 ConvertFromFloat(SAMPLE_S16LE, TEST_FRAMES, testFloat, s16Output);
193 EXPECT_EQ(s16Output[0], 0); // 0.0f
194 EXPECT_EQ(s16Output[1], 16384); // 16384: 0.5f * 32768
195 EXPECT_EQ(s16Output[NUM_TWO], -16384); // -16384: -0.5f * 32768
196 EXPECT_EQ(s16Output[NUM_THREE], 32767); // 32767: near 1.0f
197 uint8_t s24Output[NUM_THREE * TEST_FRAMES];
198 ConvertFromFloat(SAMPLE_S24LE, TEST_FRAMES, testFloat, s24Output);
199 for (int i = 0; i < TEST_FRAMES; ++i) {
200 int32_t val = (s24Output[i * NUM_THREE + NUM_TWO] << SHIFT_BIT_WIDTH_16) |
201 (s24Output[i * NUM_THREE + 1] << SHIFT_BIT_WIDTH_8) |
202 (s24Output[i * NUM_THREE + 0]);
203 if (val & 0x800000) {
204 val |= ~0xFFFFFF;
205 }
206 if (i == 0) EXPECT_EQ(val, 0);
207 if (i == 1) EXPECT_NEAR(val, (1 << SHIFT_BIT_WIDTH_22), 16); // 16: expected num
208 if (i == NUM_TWO) EXPECT_NEAR(val, -(1 << SHIFT_BIT_WIDTH_22), 16); // 16: expected num
209 if (i == NUM_THREE) EXPECT_EQ(val, 8388599); // 8388599: expected num
210 }
211 // S32LE: [-2^31, 2^31-1]
212 int32_t s32Output[TEST_FRAMES];
213 ConvertFromFloat(SAMPLE_S32LE, TEST_FRAMES, testFloat, s32Output);
214 EXPECT_EQ(s32Output[0], 0); // 0.0f
215 EXPECT_EQ(s32Output[1], 1073741824); // 1073741824: 0.5f * 2^31
216 EXPECT_EQ(s32Output[NUM_TWO], -1073741824); // -1073741824: -0.5f * 2^31
217 EXPECT_EQ(s32Output[NUM_THREE], 2147481472); // 2147481472: near 1.0f
218 }
219 } // namespace HPAE
220 } // namespace AudioStandard
221 } // namespace OHOS