xref: /aosp_15_r20/hardware/interfaces/audio/aidl/default/tests/AlsaUtilsTest.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "AlsaUtilsTest"
18 
19 #include <alsa/Utils.h>
20 #include <android-base/macros.h>
21 #include <audio_utils/primitives.h>
22 #include <gtest/gtest.h>
23 #include <log/log.h>
24 
25 extern "C" {
26 #include <tinyalsa/pcm.h>
27 }
28 
29 namespace alsa = ::aidl::android::hardware::audio::core::alsa;
30 
31 namespace {
32 
33 const static constexpr float kInt16tTolerance = 4;
34 const static constexpr float kIntTolerance = 1;
35 const static constexpr float kFloatTolerance = 1e-4;
36 const static constexpr float kUnityGain = 1;
37 const static constexpr int32_t kInt24Min = -(1 << 23);
38 const static constexpr int32_t kInt24Max = (1 << 23) - 1;
39 const static constexpr float kFloatMin = -1;
40 const static constexpr float kFloatMax = 1;
41 const static int32_t kQ8_23Min = 0x80000000;
42 const static int32_t kQ8_23Max = 0x7FFFFFFF;
43 const static std::vector<int16_t> kInt16Buffer = {10000,     100,   0,    INT16_MAX,
44                                                   INT16_MIN, -2500, 1000, -5800};
45 const static std::vector<float> kFloatBuffer = {0.5, -0.6, kFloatMin, 0.01, kFloatMax, 0.0};
46 const static std::vector<int32_t> kInt32Buffer = {100, 0, 8000, INT32_MAX, INT32_MIN, -300};
47 const static std::vector<int32_t> kQ8_23Buffer = {
48         kQ8_23Min, kQ8_23Max, 0x00000000, 0x00000001, 0x00400000, static_cast<int32_t>(0xFFD33333)};
49 const static std::vector<int32_t> kInt24Buffer = {200, 10, -100, 0, kInt24Min, kInt24Max};
50 
51 template <typename T>
CopyToBuffer(int & bytesToTransfer,std::vector<T> & destBuffer,const std::vector<T> & srcBuffer)52 void* CopyToBuffer(int& bytesToTransfer, std::vector<T>& destBuffer,
53                    const std::vector<T>& srcBuffer) {
54     bytesToTransfer = srcBuffer.size() * sizeof(T);
55     destBuffer = srcBuffer;
56     return destBuffer.data();
57 }
58 
59 template <typename T>
VerifyTypedBufferResults(const std::vector<T> & bufferWithGain,const std::vector<T> & srcBuffer,float gain,float tolerance)60 void VerifyTypedBufferResults(const std::vector<T>& bufferWithGain, const std::vector<T>& srcBuffer,
61                               float gain, float tolerance) {
62     for (size_t i = 0; i < srcBuffer.size(); i++) {
63         EXPECT_NEAR(srcBuffer[i] * gain, static_cast<float>(bufferWithGain[i]), tolerance);
64     }
65 }
66 
67 template <typename T>
VerifyTypedBufferResultsWithClamp(const std::vector<T> & bufferWithGain,const std::vector<T> & srcBuffer,float gain,float tolerance,T minValue,T maxValue)68 void VerifyTypedBufferResultsWithClamp(const std::vector<T>& bufferWithGain,
69                                        const std::vector<T>& srcBuffer, float gain, float tolerance,
70                                        T minValue, T maxValue) {
71     for (size_t i = 0; i < srcBuffer.size(); i++) {
72         float expectedResult = std::clamp(srcBuffer[i] * gain, static_cast<float>(minValue),
73                                           static_cast<float>(maxValue));
74         EXPECT_NEAR(expectedResult, static_cast<float>(bufferWithGain[i]), tolerance);
75     }
76 }
77 
78 }  // namespace
79 
80 using ApplyGainTestParameters = std::tuple<pcm_format, int, float>;
81 enum { INDEX_PCM_FORMAT, INDEX_CHANNEL_COUNT, INDEX_GAIN };
82 
83 class ApplyGainTest : public ::testing::TestWithParam<ApplyGainTestParameters> {
84   protected:
85     void SetUp() override;
86     void VerifyBufferResult(const pcm_format pcmFormat, const float gain);
87     void VerifyBufferResultWithClamp(const pcm_format pcmFormat, const float gain);
88 
89     pcm_format mPcmFormat;
90     int mBufferSizeBytes;
91     void* mBuffer;
92 
93   private:
94     std::vector<int16_t> mInt16BufferToConvert;
95     std::vector<float> mFloatBufferToConvert;
96     std::vector<int32_t> mInt32BufferToConvert;
97     std::vector<int32_t> mQ8_23BufferToConvert;
98     std::vector<int32_t> mInt24BufferToConvert;
99 };
100 
SetUp()101 void ApplyGainTest::SetUp() {
102     mPcmFormat = std::get<INDEX_PCM_FORMAT>(GetParam());
103     switch (mPcmFormat) {
104         case PCM_FORMAT_S16_LE:
105             mBuffer = CopyToBuffer(mBufferSizeBytes, mInt16BufferToConvert, kInt16Buffer);
106             break;
107         case PCM_FORMAT_FLOAT_LE:
108             mBuffer = CopyToBuffer(mBufferSizeBytes, mFloatBufferToConvert, kFloatBuffer);
109             break;
110         case PCM_FORMAT_S32_LE:
111             mBuffer = CopyToBuffer(mBufferSizeBytes, mInt32BufferToConvert, kInt32Buffer);
112             break;
113         case PCM_FORMAT_S24_LE:
114             mBuffer = CopyToBuffer(mBufferSizeBytes, mQ8_23BufferToConvert, kQ8_23Buffer);
115             break;
116         case PCM_FORMAT_S24_3LE: {
117             std::vector<int32_t> original32BitBuffer(kInt24Buffer.begin(), kInt24Buffer.end());
118             for (auto& val : original32BitBuffer) {
119                 val <<= 8;
120             }
121             mInt24BufferToConvert = std::vector<int32_t>(kInt24Buffer.size());
122             mBufferSizeBytes = kInt24Buffer.size() * 3 * sizeof(uint8_t);
123             memcpy_to_p24_from_i32(reinterpret_cast<uint8_t*>(mInt24BufferToConvert.data()),
124                                    original32BitBuffer.data(), kInt24Buffer.size());
125             mBuffer = mInt24BufferToConvert.data();
126         } break;
127         default:
128             FAIL() << "Unsupported pcm format: " << mPcmFormat;
129             return;
130     }
131 }
132 
VerifyBufferResult(const pcm_format pcmFormat,const float gain)133 void ApplyGainTest::VerifyBufferResult(const pcm_format pcmFormat, const float gain) {
134     switch (pcmFormat) {
135         case PCM_FORMAT_S16_LE:
136             VerifyTypedBufferResults(mInt16BufferToConvert, kInt16Buffer, gain, kInt16tTolerance);
137             break;
138         case PCM_FORMAT_FLOAT_LE:
139             VerifyTypedBufferResults(mFloatBufferToConvert, kFloatBuffer, gain, kFloatTolerance);
140             break;
141         case PCM_FORMAT_S32_LE:
142             VerifyTypedBufferResults(mInt32BufferToConvert, kInt32Buffer, gain, kIntTolerance);
143             break;
144         case PCM_FORMAT_S24_LE: {
145             for (size_t i = 0; i < kQ8_23Buffer.size(); i++) {
146                 EXPECT_NEAR(float_from_q8_23(kQ8_23Buffer[i]) * gain,
147                             static_cast<float>(float_from_q8_23(mQ8_23BufferToConvert[i])),
148                             kFloatTolerance);
149             }
150         } break;
151         case PCM_FORMAT_S24_3LE: {
152             size_t bufferSize = kInt24Buffer.size();
153             std::vector<int32_t> result32BitBuffer(bufferSize);
154             memcpy_to_i32_from_p24(result32BitBuffer.data(),
155                                    reinterpret_cast<uint8_t*>(mInt24BufferToConvert.data()),
156                                    bufferSize);
157             for (size_t i = 0; i < bufferSize; i++) {
158                 EXPECT_NEAR(kInt24Buffer[i] * gain, result32BitBuffer[i] >> 8, kIntTolerance);
159             }
160         } break;
161         default:
162             return;
163     }
164 }
165 
VerifyBufferResultWithClamp(const pcm_format pcmFormat,const float gain)166 void ApplyGainTest::VerifyBufferResultWithClamp(const pcm_format pcmFormat, const float gain) {
167     switch (pcmFormat) {
168         case PCM_FORMAT_S16_LE:
169             VerifyTypedBufferResultsWithClamp(mInt16BufferToConvert, kInt16Buffer, gain,
170                                               kInt16tTolerance, static_cast<int16_t>(INT16_MIN),
171                                               static_cast<int16_t>(INT16_MAX));
172             break;
173         case PCM_FORMAT_FLOAT_LE:
174             VerifyTypedBufferResultsWithClamp(mFloatBufferToConvert, kFloatBuffer, gain,
175                                               kFloatTolerance, kFloatMin, kFloatMax);
176             break;
177         case PCM_FORMAT_S32_LE:
178             VerifyTypedBufferResultsWithClamp(mInt32BufferToConvert, kInt32Buffer, gain,
179                                               kIntTolerance, INT32_MIN, INT32_MAX);
180             break;
181         case PCM_FORMAT_S24_LE: {
182             for (size_t i = 0; i < kQ8_23Buffer.size(); i++) {
183                 float expectedResult =
184                         std::clamp(float_from_q8_23(kQ8_23Buffer[i]) * gain,
185                                    float_from_q8_23(kQ8_23Min), float_from_q8_23(kQ8_23Max));
186                 EXPECT_NEAR(expectedResult,
187                             static_cast<float>(float_from_q8_23(mQ8_23BufferToConvert[i])),
188                             kFloatTolerance);
189             }
190         } break;
191         case PCM_FORMAT_S24_3LE: {
192             size_t bufferSize = kInt24Buffer.size();
193             std::vector<int32_t> result32BitBuffer(bufferSize);
194             memcpy_to_i32_from_p24(result32BitBuffer.data(),
195                                    reinterpret_cast<uint8_t*>(mInt24BufferToConvert.data()),
196                                    bufferSize);
197             for (size_t i = 0; i < bufferSize; i++) {
198                 result32BitBuffer[i] >>= 8;
199             }
200             VerifyTypedBufferResultsWithClamp(result32BitBuffer, kInt24Buffer, gain, kIntTolerance,
201                                               kInt24Min, kInt24Max);
202         } break;
203         default:
204             return;
205     }
206 }
207 
TEST_P(ApplyGainTest,ApplyGain)208 TEST_P(ApplyGainTest, ApplyGain) {
209     float gain = std::get<INDEX_GAIN>(GetParam());
210     int channelCount = std::get<INDEX_CHANNEL_COUNT>(GetParam());
211 
212     alsa::applyGain(mBuffer, gain, mBufferSizeBytes, mPcmFormat, channelCount);
213 
214     if (gain <= kUnityGain) {
215         VerifyBufferResult(mPcmFormat, gain);
216     } else {
217         VerifyBufferResultWithClamp(mPcmFormat, gain);
218     }
219 }
220 
GetApplyGainTestName(const testing::TestParamInfo<ApplyGainTestParameters> & info)221 std::string GetApplyGainTestName(const testing::TestParamInfo<ApplyGainTestParameters>& info) {
222     std::string testNameStr;
223     switch (std::get<INDEX_PCM_FORMAT>(info.param)) {
224         case PCM_FORMAT_S16_LE:
225             testNameStr = "S16_LE";
226             break;
227         case PCM_FORMAT_FLOAT_LE:
228             testNameStr = "Float_LE";
229             break;
230         case PCM_FORMAT_S32_LE:
231             testNameStr = "S32_LE";
232             break;
233         case PCM_FORMAT_S24_LE:
234             testNameStr = "S24_LE";
235             break;
236         case PCM_FORMAT_S24_3LE:
237             testNameStr = "S24_3LE";
238             break;
239         default:
240             testNameStr = "UnsupportedPcmFormat";
241             break;
242     }
243     testNameStr += std::get<INDEX_CHANNEL_COUNT>(info.param) == 1 ? "_Mono_" : "_Stereo_";
244     testNameStr += std::get<INDEX_GAIN>(info.param) <= kUnityGain ? "WithoutClamp" : "WithClamp";
245     return testNameStr;
246 }
247 
248 INSTANTIATE_TEST_SUITE_P(PerPcmFormat, ApplyGainTest,
249                          testing::Combine(testing::Values(PCM_FORMAT_S16_LE, PCM_FORMAT_FLOAT_LE,
250                                                           PCM_FORMAT_S32_LE, PCM_FORMAT_S24_LE,
251                                                           PCM_FORMAT_S24_3LE),
252                                           testing::Values(1, 2), testing::Values(0.6f, 1.5f)),
253                          GetApplyGainTestName);
254