xref: /aosp_15_r20/external/webrtc/common_audio/resampler/resampler_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "common_audio/resampler/include/resampler.h"
12 
13 #include <array>
14 
15 #include "rtc_base/strings/string_builder.h"
16 #include "test/gtest.h"
17 
18 // TODO(andrew): this is a work-in-progress. Many more tests are needed.
19 
20 namespace webrtc {
21 namespace {
22 
23 const int kNumChannels[] = {1, 2};
24 const size_t kNumChannelsSize = sizeof(kNumChannels) / sizeof(*kNumChannels);
25 
26 // Rates we must support.
27 const int kMaxRate = 96000;
28 const int kRates[] = {8000, 16000, 32000, 44000, 48000, kMaxRate};
29 const size_t kRatesSize = sizeof(kRates) / sizeof(*kRates);
30 const int kMaxChannels = 2;
31 const size_t kDataSize = static_cast<size_t>(kMaxChannels * kMaxRate / 100);
32 
33 // TODO(andrew): should we be supporting these combinations?
ValidRates(int in_rate,int out_rate)34 bool ValidRates(int in_rate, int out_rate) {
35   // Not the most compact notation, for clarity.
36   if ((in_rate == 44000 && (out_rate == 48000 || out_rate == 96000)) ||
37       (out_rate == 44000 && (in_rate == 48000 || in_rate == 96000))) {
38     return false;
39   }
40 
41   return true;
42 }
43 
44 class ResamplerTest : public ::testing::Test {
45  protected:
46   ResamplerTest();
47   void SetUp() override;
48   void TearDown() override;
49 
50   void ResetIfNeededAndPush(int in_rate, int out_rate, int num_channels);
51 
52   Resampler rs_;
53   int16_t data_in_[kDataSize];
54   int16_t data_out_[kDataSize];
55 };
56 
ResamplerTest()57 ResamplerTest::ResamplerTest() {}
58 
SetUp()59 void ResamplerTest::SetUp() {
60   // Initialize input data with anything. The tests are content independent.
61   memset(data_in_, 1, sizeof(data_in_));
62 }
63 
TearDown()64 void ResamplerTest::TearDown() {}
65 
ResetIfNeededAndPush(int in_rate,int out_rate,int num_channels)66 void ResamplerTest::ResetIfNeededAndPush(int in_rate,
67                                          int out_rate,
68                                          int num_channels) {
69   rtc::StringBuilder ss;
70   ss << "Input rate: " << in_rate << ", output rate: " << out_rate
71      << ", channel count: " << num_channels;
72   SCOPED_TRACE(ss.str());
73 
74   if (ValidRates(in_rate, out_rate)) {
75     size_t in_length = static_cast<size_t>(in_rate / 100);
76     size_t out_length = 0;
77     EXPECT_EQ(0, rs_.ResetIfNeeded(in_rate, out_rate, num_channels));
78     EXPECT_EQ(0,
79               rs_.Push(data_in_, in_length, data_out_, kDataSize, out_length));
80     EXPECT_EQ(static_cast<size_t>(out_rate / 100), out_length);
81   } else {
82     EXPECT_EQ(-1, rs_.ResetIfNeeded(in_rate, out_rate, num_channels));
83   }
84 }
85 
TEST_F(ResamplerTest,Reset)86 TEST_F(ResamplerTest, Reset) {
87   // The only failure mode for the constructor is if Reset() fails. For the
88   // time being then (until an Init function is added), we rely on Reset()
89   // to test the constructor.
90 
91   // Check that all required combinations are supported.
92   for (size_t i = 0; i < kRatesSize; ++i) {
93     for (size_t j = 0; j < kRatesSize; ++j) {
94       for (size_t k = 0; k < kNumChannelsSize; ++k) {
95         rtc::StringBuilder ss;
96         ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j]
97            << ", channels: " << kNumChannels[k];
98         SCOPED_TRACE(ss.str());
99         if (ValidRates(kRates[i], kRates[j]))
100           EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kNumChannels[k]));
101         else
102           EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kNumChannels[k]));
103       }
104     }
105   }
106 }
107 
108 // TODO(tlegrand): Replace code inside the two tests below with a function
109 // with number of channels and ResamplerType as input.
TEST_F(ResamplerTest,Mono)110 TEST_F(ResamplerTest, Mono) {
111   const int kChannels = 1;
112   for (size_t i = 0; i < kRatesSize; ++i) {
113     for (size_t j = 0; j < kRatesSize; ++j) {
114       rtc::StringBuilder ss;
115       ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j];
116       SCOPED_TRACE(ss.str());
117 
118       if (ValidRates(kRates[i], kRates[j])) {
119         size_t in_length = static_cast<size_t>(kRates[i] / 100);
120         size_t out_length = 0;
121         EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kChannels));
122         EXPECT_EQ(
123             0, rs_.Push(data_in_, in_length, data_out_, kDataSize, out_length));
124         EXPECT_EQ(static_cast<size_t>(kRates[j] / 100), out_length);
125       } else {
126         EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kChannels));
127       }
128     }
129   }
130 }
131 
TEST_F(ResamplerTest,Stereo)132 TEST_F(ResamplerTest, Stereo) {
133   const int kChannels = 2;
134   for (size_t i = 0; i < kRatesSize; ++i) {
135     for (size_t j = 0; j < kRatesSize; ++j) {
136       rtc::StringBuilder ss;
137       ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j];
138       SCOPED_TRACE(ss.str());
139 
140       if (ValidRates(kRates[i], kRates[j])) {
141         size_t in_length = static_cast<size_t>(kChannels * kRates[i] / 100);
142         size_t out_length = 0;
143         EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kChannels));
144         EXPECT_EQ(
145             0, rs_.Push(data_in_, in_length, data_out_, kDataSize, out_length));
146         EXPECT_EQ(static_cast<size_t>(kChannels * kRates[j] / 100), out_length);
147       } else {
148         EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kChannels));
149       }
150     }
151   }
152 }
153 
154 // Try multiple resets between a few supported and unsupported rates.
TEST_F(ResamplerTest,MultipleResets)155 TEST_F(ResamplerTest, MultipleResets) {
156   constexpr size_t kNumChanges = 5;
157   constexpr std::array<int, kNumChanges> kInRates = {
158       {8000, 44000, 44000, 32000, 32000}};
159   constexpr std::array<int, kNumChanges> kOutRates = {
160       {16000, 48000, 48000, 16000, 16000}};
161   constexpr std::array<int, kNumChanges> kNumChannels = {{2, 2, 2, 2, 1}};
162   for (size_t i = 0; i < kNumChanges; ++i) {
163     ResetIfNeededAndPush(kInRates[i], kOutRates[i], kNumChannels[i]);
164   }
165 }
166 
167 }  // namespace
168 }  // namespace webrtc
169