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