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 23namespace webrtc { 24 25namespace { 26 27const int kIsacNumberOfSamples = 32 * 60; // 60 ms at 32 kHz 28 29std::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 37template <typename T> 38IsacBandwidthInfo 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. 46template <typename T> 47int 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 65template <typename T> 66std::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 78class BoundedCapacityChannel final { 79 public: 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. 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. 103template <typename T, bool adaptive> 104void 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 187enum class IsacType { Fix, Float }; 188 189std::ostream& operator<<(std::ostream& os, IsacType t) { 190 os << (t == IsacType::Fix ? "fix" : "float"); 191 return os; 192} 193 194struct 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 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 210class IsacCommonTest : public testing::TestWithParam<IsacTestParam> {}; 211 212} // namespace 213 214TEST_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 233std::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 252INSTANTIATE_TEST_CASE_P(, IsacCommonTest, testing::ValuesIn(TestCases())); 253 254} // namespace webrtc 255