xref: /aosp_15_r20/external/webrtc/common_audio/audio_util_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "common_audio/include/audio_util.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/arraysize.h"
14*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
15*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
18*d9f75844SAndroid Build Coastguard Worker namespace {
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker using ::testing::ElementsAreArray;
21*d9f75844SAndroid Build Coastguard Worker 
ExpectArraysEq(const int16_t * ref,const int16_t * test,size_t length)22*d9f75844SAndroid Build Coastguard Worker void ExpectArraysEq(const int16_t* ref, const int16_t* test, size_t length) {
23*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < length; ++i) {
24*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(ref[i], test[i]);
25*d9f75844SAndroid Build Coastguard Worker   }
26*d9f75844SAndroid Build Coastguard Worker }
27*d9f75844SAndroid Build Coastguard Worker 
ExpectArraysEq(const float * ref,const float * test,size_t length)28*d9f75844SAndroid Build Coastguard Worker void ExpectArraysEq(const float* ref, const float* test, size_t length) {
29*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < length; ++i) {
30*d9f75844SAndroid Build Coastguard Worker     EXPECT_NEAR(ref[i], test[i], 0.01f);
31*d9f75844SAndroid Build Coastguard Worker   }
32*d9f75844SAndroid Build Coastguard Worker }
33*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,S16ToFloat)34*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, S16ToFloat) {
35*d9f75844SAndroid Build Coastguard Worker   static constexpr int16_t kInput[] = {0, 1, -1, 16384, -16384, 32767, -32768};
36*d9f75844SAndroid Build Coastguard Worker   static constexpr float kReference[] = {
37*d9f75844SAndroid Build Coastguard Worker       0.f, 1.f / 32767.f, -1.f / 32768.f, 16384.f / 32767.f, -0.5f, 1.f, -1.f};
38*d9f75844SAndroid Build Coastguard Worker   static constexpr size_t kSize = arraysize(kInput);
39*d9f75844SAndroid Build Coastguard Worker   static_assert(arraysize(kReference) == kSize, "");
40*d9f75844SAndroid Build Coastguard Worker   float output[kSize];
41*d9f75844SAndroid Build Coastguard Worker   S16ToFloat(kInput, kSize, output);
42*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kReference, output, kSize);
43*d9f75844SAndroid Build Coastguard Worker }
44*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,FloatS16ToS16)45*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, FloatS16ToS16) {
46*d9f75844SAndroid Build Coastguard Worker   static constexpr float kInput[] = {0.f,   0.4f,    0.5f,    -0.4f,
47*d9f75844SAndroid Build Coastguard Worker                                      -0.5f, 32768.f, -32769.f};
48*d9f75844SAndroid Build Coastguard Worker   static constexpr int16_t kReference[] = {0, 0, 1, 0, -1, 32767, -32768};
49*d9f75844SAndroid Build Coastguard Worker   static constexpr size_t kSize = arraysize(kInput);
50*d9f75844SAndroid Build Coastguard Worker   static_assert(arraysize(kReference) == kSize, "");
51*d9f75844SAndroid Build Coastguard Worker   int16_t output[kSize];
52*d9f75844SAndroid Build Coastguard Worker   FloatS16ToS16(kInput, kSize, output);
53*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kReference, output, kSize);
54*d9f75844SAndroid Build Coastguard Worker }
55*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,FloatToFloatS16)56*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, FloatToFloatS16) {
57*d9f75844SAndroid Build Coastguard Worker   static constexpr float kInput[] = {0.f,
58*d9f75844SAndroid Build Coastguard Worker                                      0.4f / 32768.f,
59*d9f75844SAndroid Build Coastguard Worker                                      0.6f / 32768.f,
60*d9f75844SAndroid Build Coastguard Worker                                      -0.4f / 32768.f,
61*d9f75844SAndroid Build Coastguard Worker                                      -0.6f / 32768.f,
62*d9f75844SAndroid Build Coastguard Worker                                      1.f,
63*d9f75844SAndroid Build Coastguard Worker                                      -1.f,
64*d9f75844SAndroid Build Coastguard Worker                                      1.f,
65*d9f75844SAndroid Build Coastguard Worker                                      -1.f};
66*d9f75844SAndroid Build Coastguard Worker   static constexpr float kReference[] = {
67*d9f75844SAndroid Build Coastguard Worker       0.f, 0.4f, 0.6f, -0.4f, -0.6f, 32768.f, -32768.f, 32768.f, -32768.f};
68*d9f75844SAndroid Build Coastguard Worker   static constexpr size_t kSize = arraysize(kInput);
69*d9f75844SAndroid Build Coastguard Worker   static_assert(arraysize(kReference) == kSize, "");
70*d9f75844SAndroid Build Coastguard Worker   float output[kSize];
71*d9f75844SAndroid Build Coastguard Worker   FloatToFloatS16(kInput, kSize, output);
72*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kReference, output, kSize);
73*d9f75844SAndroid Build Coastguard Worker }
74*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,FloatS16ToFloat)75*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, FloatS16ToFloat) {
76*d9f75844SAndroid Build Coastguard Worker   static constexpr float kInput[] = {0.f,     0.4f,     0.6f,    -0.4f,   -0.6f,
77*d9f75844SAndroid Build Coastguard Worker                                      32767.f, -32768.f, 32767.f, -32768.f};
78*d9f75844SAndroid Build Coastguard Worker   static constexpr float kReference[] = {0.f,
79*d9f75844SAndroid Build Coastguard Worker                                          0.4f / 32768.f,
80*d9f75844SAndroid Build Coastguard Worker                                          0.6f / 32768.f,
81*d9f75844SAndroid Build Coastguard Worker                                          -0.4f / 32768.f,
82*d9f75844SAndroid Build Coastguard Worker                                          -0.6f / 32768.f,
83*d9f75844SAndroid Build Coastguard Worker                                          1.f,
84*d9f75844SAndroid Build Coastguard Worker                                          -1.f,
85*d9f75844SAndroid Build Coastguard Worker                                          1.f,
86*d9f75844SAndroid Build Coastguard Worker                                          -1.f};
87*d9f75844SAndroid Build Coastguard Worker   static constexpr size_t kSize = arraysize(kInput);
88*d9f75844SAndroid Build Coastguard Worker   static_assert(arraysize(kReference) == kSize, "");
89*d9f75844SAndroid Build Coastguard Worker   float output[kSize];
90*d9f75844SAndroid Build Coastguard Worker   FloatS16ToFloat(kInput, kSize, output);
91*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kReference, output, kSize);
92*d9f75844SAndroid Build Coastguard Worker }
93*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,DbfsToFloatS16)94*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, DbfsToFloatS16) {
95*d9f75844SAndroid Build Coastguard Worker   static constexpr float kInput[] = {-90.f, -70.f, -30.f, -20.f, -10.f,
96*d9f75844SAndroid Build Coastguard Worker                                      -5.f,  -1.f,  0.f,   1.f};
97*d9f75844SAndroid Build Coastguard Worker   static constexpr float kReference[] = {
98*d9f75844SAndroid Build Coastguard Worker       1.036215186f, 10.36215115f, 1036.215088f, 3276.800049f, 10362.15137f,
99*d9f75844SAndroid Build Coastguard Worker       18426.80078f, 29204.51172f, 32768.f,      36766.30078f};
100*d9f75844SAndroid Build Coastguard Worker   static constexpr size_t kSize = arraysize(kInput);
101*d9f75844SAndroid Build Coastguard Worker   static_assert(arraysize(kReference) == kSize, "");
102*d9f75844SAndroid Build Coastguard Worker   float output[kSize];
103*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < kSize; ++i) {
104*d9f75844SAndroid Build Coastguard Worker     output[i] = DbfsToFloatS16(kInput[i]);
105*d9f75844SAndroid Build Coastguard Worker   }
106*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kReference, output, kSize);
107*d9f75844SAndroid Build Coastguard Worker }
108*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,FloatS16ToDbfs)109*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, FloatS16ToDbfs) {
110*d9f75844SAndroid Build Coastguard Worker   static constexpr float kInput[] = {1.036215143f, 10.36215143f,  1036.215143f,
111*d9f75844SAndroid Build Coastguard Worker                                      3276.8f,      10362.151436f, 18426.800543f,
112*d9f75844SAndroid Build Coastguard Worker                                      29204.51074f, 32768.0f,      36766.30071f};
113*d9f75844SAndroid Build Coastguard Worker 
114*d9f75844SAndroid Build Coastguard Worker   static constexpr float kReference[] = {
115*d9f75844SAndroid Build Coastguard Worker       -90.f, -70.f, -30.f, -20.f, -10.f, -5.f, -1.f, 0.f, 0.9999923706f};
116*d9f75844SAndroid Build Coastguard Worker   static constexpr size_t kSize = arraysize(kInput);
117*d9f75844SAndroid Build Coastguard Worker   static_assert(arraysize(kReference) == kSize, "");
118*d9f75844SAndroid Build Coastguard Worker 
119*d9f75844SAndroid Build Coastguard Worker   float output[kSize];
120*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < kSize; ++i) {
121*d9f75844SAndroid Build Coastguard Worker     output[i] = FloatS16ToDbfs(kInput[i]);
122*d9f75844SAndroid Build Coastguard Worker   }
123*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kReference, output, kSize);
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,InterleavingStereo)126*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, InterleavingStereo) {
127*d9f75844SAndroid Build Coastguard Worker   const int16_t kInterleaved[] = {2, 3, 4, 9, 8, 27, 16, 81};
128*d9f75844SAndroid Build Coastguard Worker   const size_t kSamplesPerChannel = 4;
129*d9f75844SAndroid Build Coastguard Worker   const int kNumChannels = 2;
130*d9f75844SAndroid Build Coastguard Worker   const size_t kLength = kSamplesPerChannel * kNumChannels;
131*d9f75844SAndroid Build Coastguard Worker   int16_t left[kSamplesPerChannel], right[kSamplesPerChannel];
132*d9f75844SAndroid Build Coastguard Worker   int16_t* deinterleaved[] = {left, right};
133*d9f75844SAndroid Build Coastguard Worker   Deinterleave(kInterleaved, kSamplesPerChannel, kNumChannels, deinterleaved);
134*d9f75844SAndroid Build Coastguard Worker   const int16_t kRefLeft[] = {2, 4, 8, 16};
135*d9f75844SAndroid Build Coastguard Worker   const int16_t kRefRight[] = {3, 9, 27, 81};
136*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kRefLeft, left, kSamplesPerChannel);
137*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kRefRight, right, kSamplesPerChannel);
138*d9f75844SAndroid Build Coastguard Worker 
139*d9f75844SAndroid Build Coastguard Worker   int16_t interleaved[kLength];
140*d9f75844SAndroid Build Coastguard Worker   Interleave(deinterleaved, kSamplesPerChannel, kNumChannels, interleaved);
141*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kInterleaved, interleaved, kLength);
142*d9f75844SAndroid Build Coastguard Worker }
143*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,InterleavingMonoIsIdentical)144*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, InterleavingMonoIsIdentical) {
145*d9f75844SAndroid Build Coastguard Worker   const int16_t kInterleaved[] = {1, 2, 3, 4, 5};
146*d9f75844SAndroid Build Coastguard Worker   const size_t kSamplesPerChannel = 5;
147*d9f75844SAndroid Build Coastguard Worker   const int kNumChannels = 1;
148*d9f75844SAndroid Build Coastguard Worker   int16_t mono[kSamplesPerChannel];
149*d9f75844SAndroid Build Coastguard Worker   int16_t* deinterleaved[] = {mono};
150*d9f75844SAndroid Build Coastguard Worker   Deinterleave(kInterleaved, kSamplesPerChannel, kNumChannels, deinterleaved);
151*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(kInterleaved, mono, kSamplesPerChannel);
152*d9f75844SAndroid Build Coastguard Worker 
153*d9f75844SAndroid Build Coastguard Worker   int16_t interleaved[kSamplesPerChannel];
154*d9f75844SAndroid Build Coastguard Worker   Interleave(deinterleaved, kSamplesPerChannel, kNumChannels, interleaved);
155*d9f75844SAndroid Build Coastguard Worker   ExpectArraysEq(mono, interleaved, kSamplesPerChannel);
156*d9f75844SAndroid Build Coastguard Worker }
157*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,DownmixInterleavedToMono)158*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, DownmixInterleavedToMono) {
159*d9f75844SAndroid Build Coastguard Worker   {
160*d9f75844SAndroid Build Coastguard Worker     const size_t kNumFrames = 4;
161*d9f75844SAndroid Build Coastguard Worker     const int kNumChannels = 1;
162*d9f75844SAndroid Build Coastguard Worker     const int16_t interleaved[kNumChannels * kNumFrames] = {1, 2, -1, -3};
163*d9f75844SAndroid Build Coastguard Worker     int16_t deinterleaved[kNumFrames];
164*d9f75844SAndroid Build Coastguard Worker 
165*d9f75844SAndroid Build Coastguard Worker     DownmixInterleavedToMono(interleaved, kNumFrames, kNumChannels,
166*d9f75844SAndroid Build Coastguard Worker                              deinterleaved);
167*d9f75844SAndroid Build Coastguard Worker 
168*d9f75844SAndroid Build Coastguard Worker     EXPECT_THAT(deinterleaved, ElementsAreArray(interleaved));
169*d9f75844SAndroid Build Coastguard Worker   }
170*d9f75844SAndroid Build Coastguard Worker   {
171*d9f75844SAndroid Build Coastguard Worker     const size_t kNumFrames = 2;
172*d9f75844SAndroid Build Coastguard Worker     const int kNumChannels = 2;
173*d9f75844SAndroid Build Coastguard Worker     const int16_t interleaved[kNumChannels * kNumFrames] = {10, 20, -10, -30};
174*d9f75844SAndroid Build Coastguard Worker     int16_t deinterleaved[kNumFrames];
175*d9f75844SAndroid Build Coastguard Worker 
176*d9f75844SAndroid Build Coastguard Worker     DownmixInterleavedToMono(interleaved, kNumFrames, kNumChannels,
177*d9f75844SAndroid Build Coastguard Worker                              deinterleaved);
178*d9f75844SAndroid Build Coastguard Worker     const int16_t expected[kNumFrames] = {15, -20};
179*d9f75844SAndroid Build Coastguard Worker 
180*d9f75844SAndroid Build Coastguard Worker     EXPECT_THAT(deinterleaved, ElementsAreArray(expected));
181*d9f75844SAndroid Build Coastguard Worker   }
182*d9f75844SAndroid Build Coastguard Worker   {
183*d9f75844SAndroid Build Coastguard Worker     const size_t kNumFrames = 3;
184*d9f75844SAndroid Build Coastguard Worker     const int kNumChannels = 3;
185*d9f75844SAndroid Build Coastguard Worker     const int16_t interleaved[kNumChannels * kNumFrames] = {
186*d9f75844SAndroid Build Coastguard Worker         30000, 30000, 24001, -5, -10, -20, -30000, -30999, -30000};
187*d9f75844SAndroid Build Coastguard Worker     int16_t deinterleaved[kNumFrames];
188*d9f75844SAndroid Build Coastguard Worker 
189*d9f75844SAndroid Build Coastguard Worker     DownmixInterleavedToMono(interleaved, kNumFrames, kNumChannels,
190*d9f75844SAndroid Build Coastguard Worker                              deinterleaved);
191*d9f75844SAndroid Build Coastguard Worker     const int16_t expected[kNumFrames] = {28000, -11, -30333};
192*d9f75844SAndroid Build Coastguard Worker 
193*d9f75844SAndroid Build Coastguard Worker     EXPECT_THAT(deinterleaved, ElementsAreArray(expected));
194*d9f75844SAndroid Build Coastguard Worker   }
195*d9f75844SAndroid Build Coastguard Worker }
196*d9f75844SAndroid Build Coastguard Worker 
TEST(AudioUtilTest,DownmixToMonoTest)197*d9f75844SAndroid Build Coastguard Worker TEST(AudioUtilTest, DownmixToMonoTest) {
198*d9f75844SAndroid Build Coastguard Worker   {
199*d9f75844SAndroid Build Coastguard Worker     const size_t kNumFrames = 4;
200*d9f75844SAndroid Build Coastguard Worker     const int kNumChannels = 1;
201*d9f75844SAndroid Build Coastguard Worker     const float input_data[kNumChannels][kNumFrames] = {{1.f, 2.f, -1.f, -3.f}};
202*d9f75844SAndroid Build Coastguard Worker     const float* input[kNumChannels];
203*d9f75844SAndroid Build Coastguard Worker     for (int i = 0; i < kNumChannels; ++i) {
204*d9f75844SAndroid Build Coastguard Worker       input[i] = input_data[i];
205*d9f75844SAndroid Build Coastguard Worker     }
206*d9f75844SAndroid Build Coastguard Worker 
207*d9f75844SAndroid Build Coastguard Worker     float downmixed[kNumFrames];
208*d9f75844SAndroid Build Coastguard Worker 
209*d9f75844SAndroid Build Coastguard Worker     DownmixToMono<float, float>(input, kNumFrames, kNumChannels, downmixed);
210*d9f75844SAndroid Build Coastguard Worker 
211*d9f75844SAndroid Build Coastguard Worker     EXPECT_THAT(downmixed, ElementsAreArray(input_data[0]));
212*d9f75844SAndroid Build Coastguard Worker   }
213*d9f75844SAndroid Build Coastguard Worker   {
214*d9f75844SAndroid Build Coastguard Worker     const size_t kNumFrames = 3;
215*d9f75844SAndroid Build Coastguard Worker     const int kNumChannels = 2;
216*d9f75844SAndroid Build Coastguard Worker     const float input_data[kNumChannels][kNumFrames] = {{1.f, 2.f, -1.f},
217*d9f75844SAndroid Build Coastguard Worker                                                         {3.f, 0.f, 1.f}};
218*d9f75844SAndroid Build Coastguard Worker     const float* input[kNumChannels];
219*d9f75844SAndroid Build Coastguard Worker     for (int i = 0; i < kNumChannels; ++i) {
220*d9f75844SAndroid Build Coastguard Worker       input[i] = input_data[i];
221*d9f75844SAndroid Build Coastguard Worker     }
222*d9f75844SAndroid Build Coastguard Worker 
223*d9f75844SAndroid Build Coastguard Worker     float downmixed[kNumFrames];
224*d9f75844SAndroid Build Coastguard Worker     const float expected[kNumFrames] = {2.f, 1.f, 0.f};
225*d9f75844SAndroid Build Coastguard Worker 
226*d9f75844SAndroid Build Coastguard Worker     DownmixToMono<float, float>(input, kNumFrames, kNumChannels, downmixed);
227*d9f75844SAndroid Build Coastguard Worker 
228*d9f75844SAndroid Build Coastguard Worker     EXPECT_THAT(downmixed, ElementsAreArray(expected));
229*d9f75844SAndroid Build Coastguard Worker   }
230*d9f75844SAndroid Build Coastguard Worker   {
231*d9f75844SAndroid Build Coastguard Worker     const size_t kNumFrames = 3;
232*d9f75844SAndroid Build Coastguard Worker     const int kNumChannels = 3;
233*d9f75844SAndroid Build Coastguard Worker     const int16_t input_data[kNumChannels][kNumFrames] = {
234*d9f75844SAndroid Build Coastguard Worker         {30000, -5, -30000}, {30000, -10, -30999}, {24001, -20, -30000}};
235*d9f75844SAndroid Build Coastguard Worker     const int16_t* input[kNumChannels];
236*d9f75844SAndroid Build Coastguard Worker     for (int i = 0; i < kNumChannels; ++i) {
237*d9f75844SAndroid Build Coastguard Worker       input[i] = input_data[i];
238*d9f75844SAndroid Build Coastguard Worker     }
239*d9f75844SAndroid Build Coastguard Worker 
240*d9f75844SAndroid Build Coastguard Worker     int16_t downmixed[kNumFrames];
241*d9f75844SAndroid Build Coastguard Worker     const int16_t expected[kNumFrames] = {28000, -11, -30333};
242*d9f75844SAndroid Build Coastguard Worker 
243*d9f75844SAndroid Build Coastguard Worker     DownmixToMono<int16_t, int32_t>(input, kNumFrames, kNumChannels, downmixed);
244*d9f75844SAndroid Build Coastguard Worker 
245*d9f75844SAndroid Build Coastguard Worker     EXPECT_THAT(downmixed, ElementsAreArray(expected));
246*d9f75844SAndroid Build Coastguard Worker   }
247*d9f75844SAndroid Build Coastguard Worker }
248*d9f75844SAndroid Build Coastguard Worker 
249*d9f75844SAndroid Build Coastguard Worker }  // namespace
250*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
251