1 /*
2 * Copyright (c) 2015 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 <algorithm>
12 #include <numeric>
13 #include <sstream>
14 #include <vector>
15
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webrtc/base/buffer.h"
18 #include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h"
19 #include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
20 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
21 #include "webrtc/test/testsupport/fileutils.h"
22
23 namespace webrtc {
24
25 namespace {
26
27 const int kIsacNumberOfSamples = 32 * 60; // 60 ms at 32 kHz
28
LoadSpeechData()29 std::vector<int16_t> LoadSpeechData() {
30 webrtc::test::InputAudioFile input_file(
31 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"));
32 std::vector<int16_t> speech_data(kIsacNumberOfSamples);
33 input_file.Read(kIsacNumberOfSamples, speech_data.data());
34 return speech_data;
35 }
36
37 template <typename T>
GetBwInfo(typename T::instance_type * inst)38 IsacBandwidthInfo GetBwInfo(typename T::instance_type* inst) {
39 IsacBandwidthInfo bi;
40 T::GetBandwidthInfo(inst, &bi);
41 EXPECT_TRUE(bi.in_use);
42 return bi;
43 }
44
45 // Encodes one packet. Returns the packet duration in milliseconds.
46 template <typename T>
EncodePacket(typename T::instance_type * inst,const IsacBandwidthInfo * bi,const int16_t * speech_data,rtc::Buffer * output)47 int EncodePacket(typename T::instance_type* inst,
48 const IsacBandwidthInfo* bi,
49 const int16_t* speech_data,
50 rtc::Buffer* output) {
51 output->SetSize(1000);
52 for (int duration_ms = 10;; duration_ms += 10) {
53 if (bi)
54 T::SetBandwidthInfo(inst, bi);
55 int encoded_bytes = T::Encode(inst, speech_data, output->data());
56 if (encoded_bytes > 0 || duration_ms >= 60) {
57 EXPECT_GT(encoded_bytes, 0);
58 EXPECT_LE(static_cast<size_t>(encoded_bytes), output->size());
59 output->SetSize(encoded_bytes);
60 return duration_ms;
61 }
62 }
63 }
64
65 template <typename T>
DecodePacket(typename T::instance_type * inst,const rtc::Buffer & encoded)66 std::vector<int16_t> DecodePacket(typename T::instance_type* inst,
67 const rtc::Buffer& encoded) {
68 std::vector<int16_t> decoded(kIsacNumberOfSamples);
69 int16_t speech_type;
70 int nsamples = T::DecodeInternal(inst, encoded.data(), encoded.size(),
71 &decoded.front(), &speech_type);
72 EXPECT_GT(nsamples, 0);
73 EXPECT_LE(static_cast<size_t>(nsamples), decoded.size());
74 decoded.resize(nsamples);
75 return decoded;
76 }
77
78 class BoundedCapacityChannel final {
79 public:
BoundedCapacityChannel(int sample_rate_hz,int rate_bits_per_second)80 BoundedCapacityChannel(int sample_rate_hz, int rate_bits_per_second)
81 : current_time_rtp_(0),
82 channel_rate_bytes_per_sample_(rate_bits_per_second /
83 (8.0 * sample_rate_hz)) {}
84
85 // Simulate sending the given number of bytes at the given RTP time. Returns
86 // the new current RTP time after the sending is done.
Send(int send_time_rtp,int nbytes)87 int Send(int send_time_rtp, int nbytes) {
88 current_time_rtp_ = std::max(current_time_rtp_, send_time_rtp) +
89 nbytes / channel_rate_bytes_per_sample_;
90 return current_time_rtp_;
91 }
92
93 private:
94 int current_time_rtp_;
95 // The somewhat strange unit for channel rate, bytes per sample, is because
96 // RTP time is measured in samples:
97 const double channel_rate_bytes_per_sample_;
98 };
99
100 // Test that the iSAC encoder produces identical output whether or not we use a
101 // conjoined encoder+decoder pair or a separate encoder and decoder that
102 // communicate BW estimation info explicitly.
103 template <typename T, bool adaptive>
TestGetSetBandwidthInfo(const int16_t * speech_data,int rate_bits_per_second,int sample_rate_hz,int frame_size_ms)104 void TestGetSetBandwidthInfo(const int16_t* speech_data,
105 int rate_bits_per_second,
106 int sample_rate_hz,
107 int frame_size_ms) {
108 const int bit_rate = 32000;
109
110 // Conjoined encoder/decoder pair:
111 typename T::instance_type* encdec;
112 ASSERT_EQ(0, T::Create(&encdec));
113 ASSERT_EQ(0, T::EncoderInit(encdec, adaptive ? 0 : 1));
114 T::DecoderInit(encdec);
115 ASSERT_EQ(0, T::SetEncSampRate(encdec, sample_rate_hz));
116 if (adaptive)
117 ASSERT_EQ(0, T::ControlBwe(encdec, bit_rate, frame_size_ms, false));
118 else
119 ASSERT_EQ(0, T::Control(encdec, bit_rate, frame_size_ms));
120
121 // Disjoint encoder/decoder pair:
122 typename T::instance_type* enc;
123 ASSERT_EQ(0, T::Create(&enc));
124 ASSERT_EQ(0, T::EncoderInit(enc, adaptive ? 0 : 1));
125 ASSERT_EQ(0, T::SetEncSampRate(enc, sample_rate_hz));
126 if (adaptive)
127 ASSERT_EQ(0, T::ControlBwe(enc, bit_rate, frame_size_ms, false));
128 else
129 ASSERT_EQ(0, T::Control(enc, bit_rate, frame_size_ms));
130 typename T::instance_type* dec;
131 ASSERT_EQ(0, T::Create(&dec));
132 T::DecoderInit(dec);
133 T::SetInitialBweBottleneck(dec, bit_rate);
134 T::SetEncSampRateInDecoder(dec, sample_rate_hz);
135
136 // 0. Get initial BW info from decoder.
137 auto bi = GetBwInfo<T>(dec);
138
139 BoundedCapacityChannel channel1(sample_rate_hz, rate_bits_per_second),
140 channel2(sample_rate_hz, rate_bits_per_second);
141
142 int elapsed_time_ms = 0;
143 for (int i = 0; elapsed_time_ms < 10000; ++i) {
144 std::ostringstream ss;
145 ss << " i = " << i;
146 SCOPED_TRACE(ss.str());
147
148 // 1. Encode 3 * 10 ms or 6 * 10 ms. The separate encoder is given the BW
149 // info before each encode call.
150 rtc::Buffer bitstream1, bitstream2;
151 int duration1_ms =
152 EncodePacket<T>(encdec, nullptr, speech_data, &bitstream1);
153 int duration2_ms = EncodePacket<T>(enc, &bi, speech_data, &bitstream2);
154 EXPECT_EQ(duration1_ms, duration2_ms);
155 if (adaptive)
156 EXPECT_TRUE(duration1_ms == 30 || duration1_ms == 60);
157 else
158 EXPECT_EQ(frame_size_ms, duration1_ms);
159 ASSERT_EQ(bitstream1.size(), bitstream2.size());
160 EXPECT_EQ(bitstream1, bitstream2);
161
162 // 2. Deliver the encoded data to the decoders.
163 const int send_time = elapsed_time_ms * (sample_rate_hz / 1000);
164 EXPECT_EQ(0, T::UpdateBwEstimate(
165 encdec, bitstream1.data(), bitstream1.size(), i, send_time,
166 channel1.Send(send_time, bitstream1.size())));
167 EXPECT_EQ(0, T::UpdateBwEstimate(
168 dec, bitstream2.data(), bitstream2.size(), i, send_time,
169 channel2.Send(send_time, bitstream2.size())));
170
171 // 3. Decode, and get new BW info from the separate decoder.
172 ASSERT_EQ(0, T::SetDecSampRate(encdec, sample_rate_hz));
173 ASSERT_EQ(0, T::SetDecSampRate(dec, sample_rate_hz));
174 auto decoded1 = DecodePacket<T>(encdec, bitstream1);
175 auto decoded2 = DecodePacket<T>(dec, bitstream2);
176 EXPECT_EQ(decoded1, decoded2);
177 bi = GetBwInfo<T>(dec);
178
179 elapsed_time_ms += duration1_ms;
180 }
181
182 EXPECT_EQ(0, T::Free(encdec));
183 EXPECT_EQ(0, T::Free(enc));
184 EXPECT_EQ(0, T::Free(dec));
185 }
186
187 enum class IsacType { Fix, Float };
188
operator <<(std::ostream & os,IsacType t)189 std::ostream& operator<<(std::ostream& os, IsacType t) {
190 os << (t == IsacType::Fix ? "fix" : "float");
191 return os;
192 }
193
194 struct IsacTestParam {
195 IsacType isac_type;
196 bool adaptive;
197 int channel_rate_bits_per_second;
198 int sample_rate_hz;
199 int frame_size_ms;
200
operator <<(std::ostream & os,const IsacTestParam & itp)201 friend std::ostream& operator<<(std::ostream& os, const IsacTestParam& itp) {
202 os << '{' << itp.isac_type << ','
203 << (itp.adaptive ? "adaptive" : "nonadaptive") << ','
204 << itp.channel_rate_bits_per_second << ',' << itp.sample_rate_hz << ','
205 << itp.frame_size_ms << '}';
206 return os;
207 }
208 };
209
210 class IsacCommonTest : public testing::TestWithParam<IsacTestParam> {};
211
212 } // namespace
213
TEST_P(IsacCommonTest,GetSetBandwidthInfo)214 TEST_P(IsacCommonTest, GetSetBandwidthInfo) {
215 auto p = GetParam();
216 auto test_fun = [p] {
217 if (p.isac_type == IsacType::Fix) {
218 if (p.adaptive)
219 return TestGetSetBandwidthInfo<IsacFix, true>;
220 else
221 return TestGetSetBandwidthInfo<IsacFix, false>;
222 } else {
223 if (p.adaptive)
224 return TestGetSetBandwidthInfo<IsacFloat, true>;
225 else
226 return TestGetSetBandwidthInfo<IsacFloat, false>;
227 }
228 }();
229 test_fun(LoadSpeechData().data(), p.channel_rate_bits_per_second,
230 p.sample_rate_hz, p.frame_size_ms);
231 }
232
TestCases()233 std::vector<IsacTestParam> TestCases() {
234 static const IsacType types[] = {IsacType::Fix, IsacType::Float};
235 static const bool adaptives[] = {true, false};
236 static const int channel_rates[] = {12000, 15000, 19000, 22000};
237 static const int sample_rates[] = {16000, 32000};
238 static const int frame_sizes[] = {30, 60};
239 std::vector<IsacTestParam> cases;
240 for (IsacType type : types)
241 for (bool adaptive : adaptives)
242 for (int channel_rate : channel_rates)
243 for (int sample_rate : sample_rates)
244 if (!(type == IsacType::Fix && sample_rate == 32000))
245 for (int frame_size : frame_sizes)
246 if (!(sample_rate == 32000 && frame_size == 60))
247 cases.push_back(
248 {type, adaptive, channel_rate, sample_rate, frame_size});
249 return cases;
250 }
251
252 INSTANTIATE_TEST_CASE_P(, IsacCommonTest, testing::ValuesIn(TestCases()));
253
254 } // namespace webrtc
255