blob: 94a6889ee7b50ff62f6dc2c591b7ad0c00021ea1 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
andrew@webrtc.org9dc45da2012-05-23 15:39:01 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/test/iSACTest.h"
tina.legrand@webrtc.org73222cf2013-03-15 13:29:17 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <ctype.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000014#include <stdio.h>
15#include <string.h>
16
Niels Möller2edab4c2018-10-22 09:48:08 +020017#include "absl/strings/match.h"
Karl Wiberg5817d3d2018-04-06 10:06:42 +020018#include "api/audio_codecs/builtin_audio_decoder_factory.h"
Karl Wibergbf7a0462018-09-25 14:48:33 +020019#include "api/audio_codecs/isac/audio_encoder_isac_float.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020020#include "rtc_base/strings/string_builder.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "rtc_base/time_utils.h"
Karl Wibergbf7a0462018-09-25 14:48:33 +020022#include "test/gmock.h"
23#include "test/gtest.h"
Steve Anton10542f22019-01-11 09:11:00 -080024#include "test/testsupport/file_utils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000025
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000026namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000027
Karl Wibergbf7a0462018-09-25 14:48:33 +020028using ::testing::AnyOf;
29using ::testing::Eq;
30using ::testing::StrCaseEq;
31
32namespace {
33
Fredrik Solenberg657b2962018-12-05 10:30:25 +010034constexpr int kISAC16kPayloadType = 103;
35constexpr int kISAC32kPayloadType = 104;
Jonas Olssona4d87372019-07-05 19:08:33 +020036const SdpAudioFormat kISAC16kFormat = {"ISAC", 16000, 1};
37const SdpAudioFormat kISAC32kFormat = {"ISAC", 32000, 1};
Karl Wibergbf7a0462018-09-25 14:48:33 +020038
39AudioEncoderIsacFloat::Config TweakConfig(
40 AudioEncoderIsacFloat::Config config,
41 const ACMTestISACConfig& test_config) {
42 if (test_config.currentRateBitPerSec > 0) {
43 config.bit_rate = test_config.currentRateBitPerSec;
44 }
45 if (test_config.currentFrameSizeMsec != 0) {
46 config.frame_size_ms = test_config.currentFrameSizeMsec;
47 }
48 EXPECT_THAT(config.IsOk(), Eq(true));
49 return config;
50}
51
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000052void SetISACConfigDefault(ACMTestISACConfig& isacConfig) {
53 isacConfig.currentRateBitPerSec = 0;
54 isacConfig.currentFrameSizeMsec = 0;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000055 isacConfig.encodingMode = -1;
56 isacConfig.initRateBitPerSec = 0;
57 isacConfig.initFrameSizeInMsec = 0;
58 isacConfig.enforceFrameSize = false;
niklase@google.com470e71d2011-07-07 08:21:25 +000059}
60
Karl Wibergbf7a0462018-09-25 14:48:33 +020061} // namespace
niklase@google.com470e71d2011-07-07 08:21:25 +000062
Fredrik Solenberg657b2962018-12-05 10:30:25 +010063ISACTest::ACMTestTimer::ACMTestTimer() : _msec(0), _sec(0), _min(0), _hour(0) {
64 return;
65}
66
67ISACTest::ACMTestTimer::~ACMTestTimer() {
68 return;
69}
70
71void ISACTest::ACMTestTimer::Reset() {
72 _msec = 0;
73 _sec = 0;
74 _min = 0;
75 _hour = 0;
76 return;
77}
78void ISACTest::ACMTestTimer::Tick10ms() {
79 _msec += 10;
80 Adjust();
81 return;
82}
83
84void ISACTest::ACMTestTimer::Tick1ms() {
85 _msec++;
86 Adjust();
87 return;
88}
89
90void ISACTest::ACMTestTimer::Tick100ms() {
91 _msec += 100;
92 Adjust();
93 return;
94}
95
96void ISACTest::ACMTestTimer::Tick1sec() {
97 _sec++;
98 Adjust();
99 return;
100}
101
102void ISACTest::ACMTestTimer::CurrentTimeHMS(char* currTime) {
103 sprintf(currTime, "%4lu:%02u:%06.3f", _hour, _min,
104 (double)_sec + (double)_msec / 1000.);
105 return;
106}
107
108void ISACTest::ACMTestTimer::CurrentTime(unsigned long& h,
Jonas Olssona4d87372019-07-05 19:08:33 +0200109 unsigned char& m,
110 unsigned char& s,
111 unsigned short& ms) {
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100112 h = _hour;
113 m = _min;
114 s = _sec;
115 ms = _msec;
116 return;
117}
118
119void ISACTest::ACMTestTimer::Adjust() {
120 unsigned int n;
121 if (_msec >= 1000) {
122 n = _msec / 1000;
123 _msec -= (1000 * n);
124 _sec += n;
125 }
126 if (_sec >= 60) {
127 n = _sec / 60;
128 _sec -= (n * 60);
129 _min += n;
130 }
131 if (_min >= 60) {
132 n = _min / 60;
133 _min -= (n * 60);
134 _hour += n;
135 }
136}
137
138ISACTest::ISACTest()
Karl Wiberg5817d3d2018-04-06 10:06:42 +0200139 : _acmA(AudioCodingModule::Create(
140 AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))),
141 _acmB(AudioCodingModule::Create(
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100142 AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000143
turaj@webrtc.org55e17232013-10-29 04:40:09 +0000144ISACTest::~ISACTest() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000145
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000146void ISACTest::Setup() {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000147 // Register both iSAC-wb & iSAC-swb in both sides as receiver codecs.
Jonas Olssona4d87372019-07-05 19:08:33 +0200148 std::map<int, SdpAudioFormat> receive_codecs = {
149 {kISAC16kPayloadType, kISAC16kFormat},
150 {kISAC32kPayloadType, kISAC32kFormat}};
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100151 _acmA->SetReceiveCodecs(receive_codecs);
152 _acmB->SetReceiveCodecs(receive_codecs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000153
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000154 //--- Set A-to-B channel
turaj@webrtc.org55e17232013-10-29 04:40:09 +0000155 _channel_A2B.reset(new Channel);
156 EXPECT_EQ(0, _acmA->RegisterTransportCallback(_channel_A2B.get()));
157 _channel_A2B->RegisterReceiverACM(_acmB.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000159 //--- Set B-to-A channel
turaj@webrtc.org55e17232013-10-29 04:40:09 +0000160 _channel_B2A.reset(new Channel);
161 EXPECT_EQ(0, _acmB->RegisterTransportCallback(_channel_B2A.get()));
162 _channel_B2A->RegisterReceiverACM(_acmA.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
Yves Gerey665174f2018-06-19 15:03:05 +0200164 file_name_swb_ =
165 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
Jonas Olssona4d87372019-07-05 19:08:33 +0200167 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
168 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
169 kISAC16kPayloadType));
170 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
171 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
172 kISAC32kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000173
174 _inFileA.Open(file_name_swb_, 32000, "rb");
Henrik Lundin4d682082015-12-10 16:24:39 +0100175 // Set test length to 500 ms (50 blocks of 10 ms each).
176 _inFileA.SetNum10MsBlocksToRead(50);
177 // Fast-forward 1 second (100 blocks) since the files start with silence.
178 _inFileA.FastForward(100);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000179 std::string fileNameA = webrtc::test::OutputPath() + "testisac_a.pcm";
180 std::string fileNameB = webrtc::test::OutputPath() + "testisac_b.pcm";
181 _outFileA.Open(fileNameA, 32000, "wb");
182 _outFileB.Open(fileNameB, 32000, "wb");
183
184 while (!_inFileA.EndOfFile()) {
185 Run10ms();
186 }
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100187
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000188 _inFileA.Close();
189 _outFileA.Close();
190 _outFileB.Close();
niklase@google.com470e71d2011-07-07 08:21:25 +0000191}
192
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000193void ISACTest::Perform() {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000194 Setup();
niklase@google.com470e71d2011-07-07 08:21:25 +0000195
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000196 int16_t testNr = 0;
197 ACMTestISACConfig wbISACConfig;
198 ACMTestISACConfig swbISACConfig;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000200 SetISACConfigDefault(wbISACConfig);
201 SetISACConfigDefault(swbISACConfig);
niklase@google.com470e71d2011-07-07 08:21:25 +0000202
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000203 wbISACConfig.currentRateBitPerSec = -1;
204 swbISACConfig.currentRateBitPerSec = -1;
205 testNr++;
206 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
207
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000208 SetISACConfigDefault(wbISACConfig);
209 SetISACConfigDefault(swbISACConfig);
210 testNr++;
211 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
niklase@google.com470e71d2011-07-07 08:21:25 +0000212
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000213 testNr++;
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100214 SwitchingSamplingRate(testNr, 4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000215}
216
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000217void ISACTest::Run10ms() {
218 AudioFrame audioFrame;
219 EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000220 EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
221 EXPECT_GE(_acmB->Add10MsData(audioFrame), 0);
henrik.lundind4ccb002016-05-17 12:21:55 -0700222 bool muted;
223 EXPECT_EQ(0, _acmA->PlayoutData10Ms(32000, &audioFrame, &muted));
224 ASSERT_FALSE(muted);
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000225 _outFileA.Write10MsData(audioFrame);
henrik.lundind4ccb002016-05-17 12:21:55 -0700226 EXPECT_EQ(0, _acmB->PlayoutData10Ms(32000, &audioFrame, &muted));
227 ASSERT_FALSE(muted);
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000228 _outFileB.Write10MsData(audioFrame);
229}
230
Yves Gerey665174f2018-06-19 15:03:05 +0200231void ISACTest::EncodeDecode(int testNr,
232 ACMTestISACConfig& wbISACConfig,
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000233 ACMTestISACConfig& swbISACConfig) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000234 // Files in Side A and B
235 _inFileA.Open(file_name_swb_, 32000, "rb", true);
236 _inFileB.Open(file_name_swb_, 32000, "rb", true);
237
238 std::string file_name_out;
Jonas Olsson366a50c2018-09-06 13:41:30 +0200239 rtc::StringBuilder file_stream_a;
240 rtc::StringBuilder file_stream_b;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000241 file_stream_a << webrtc::test::OutputPath();
242 file_stream_b << webrtc::test::OutputPath();
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000243 file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
244 file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000245 file_name_out = file_stream_a.str();
246 _outFileA.Open(file_name_out, 32000, "wb");
247 file_name_out = file_stream_b.str();
248 _outFileB.Open(file_name_out, 32000, "wb");
249
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000250 // Side A is sending super-wideband, and side B is sending wideband.
Jonas Olssona4d87372019-07-05 19:08:33 +0200251 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
252 TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
253 swbISACConfig),
254 kISAC32kPayloadType));
255 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
256 TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
257 wbISACConfig),
258 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000259
260 bool adaptiveMode = false;
Yves Gerey665174f2018-06-19 15:03:05 +0200261 if ((swbISACConfig.currentRateBitPerSec == -1) ||
262 (wbISACConfig.currentRateBitPerSec == -1)) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000263 adaptiveMode = true;
264 }
265 _myTimer.Reset();
266 _channel_A2B->ResetStats();
267 _channel_B2A->ResetStats();
268
269 char currentTime[500];
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000270 while (!(_inFileA.EndOfFile() || _inFileA.Rewinded())) {
271 Run10ms();
272 _myTimer.Tick10ms();
273 _myTimer.CurrentTimeHMS(currentTime);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000274 }
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000275
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000276 _channel_A2B->ResetStats();
277 _channel_B2A->ResetStats();
278
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000279 _outFileA.Close();
280 _outFileB.Close();
281 _inFileA.Close();
282 _inFileB.Close();
niklase@google.com470e71d2011-07-07 08:21:25 +0000283}
284
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000285void ISACTest::SwitchingSamplingRate(int testNr, int maxSampRateChange) {
286 // Files in Side A
287 _inFileA.Open(file_name_swb_, 32000, "rb");
288 _inFileB.Open(file_name_swb_, 32000, "rb");
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000289
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000290 std::string file_name_out;
Jonas Olsson366a50c2018-09-06 13:41:30 +0200291 rtc::StringBuilder file_stream_a;
292 rtc::StringBuilder file_stream_b;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000293 file_stream_a << webrtc::test::OutputPath();
294 file_stream_b << webrtc::test::OutputPath();
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000295 file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
296 file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000297 file_name_out = file_stream_a.str();
298 _outFileA.Open(file_name_out, 32000, "wb");
299 file_name_out = file_stream_b.str();
300 _outFileB.Open(file_name_out, 32000, "wb");
niklase@google.com470e71d2011-07-07 08:21:25 +0000301
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000302 // Start with side A sending super-wideband and side B seding wideband.
303 // Toggle sending wideband/super-wideband in this test.
Jonas Olssona4d87372019-07-05 19:08:33 +0200304 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
305 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
306 kISAC32kPayloadType));
307 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
308 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
309 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000310
311 int numSendCodecChanged = 0;
312 _myTimer.Reset();
313 char currentTime[50];
314 while (numSendCodecChanged < (maxSampRateChange << 1)) {
315 Run10ms();
316 _myTimer.Tick10ms();
317 _myTimer.CurrentTimeHMS(currentTime);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000318 if (_inFileA.EndOfFile()) {
319 if (_inFileA.SamplingFrequency() == 16000) {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000320 // Switch side A to send super-wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000321 _inFileA.Close();
322 _inFileA.Open(file_name_swb_, 32000, "rb");
Jonas Olssona4d87372019-07-05 19:08:33 +0200323 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
324 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
325 kISAC32kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000326 } else {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000327 // Switch side A to send wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000328 _inFileA.Close();
329 _inFileA.Open(file_name_swb_, 32000, "rb");
Jonas Olssona4d87372019-07-05 19:08:33 +0200330 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
331 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
332 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000333 }
334 numSendCodecChanged++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000335 }
336
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000337 if (_inFileB.EndOfFile()) {
338 if (_inFileB.SamplingFrequency() == 16000) {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000339 // Switch side B to send super-wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000340 _inFileB.Close();
341 _inFileB.Open(file_name_swb_, 32000, "rb");
Jonas Olssona4d87372019-07-05 19:08:33 +0200342 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
343 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
344 kISAC32kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000345 } else {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000346 // Switch side B to send wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000347 _inFileB.Close();
348 _inFileB.Open(file_name_swb_, 32000, "rb");
Jonas Olssona4d87372019-07-05 19:08:33 +0200349 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
350 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
351 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000352 }
353 numSendCodecChanged++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000354 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000355 }
356 _outFileA.Close();
357 _outFileB.Close();
358 _inFileA.Close();
359 _inFileB.Close();
niklase@google.com470e71d2011-07-07 08:21:25 +0000360}
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000361
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000362} // namespace webrtc