blob: 339d419955ce0c5434bd1ca0a5ae8c34637a622f [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"
Danil Chapovalovdb128562018-09-17 13:11:50 +020021#include "rtc_base/timeutils.h"
Niels Möllerfe3240a2018-09-06 16:47:42 +020022#include "system_wrappers/include/sleep.h"
Karl Wibergbf7a0462018-09-25 14:48:33 +020023#include "test/gmock.h"
24#include "test/gtest.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "test/testsupport/fileutils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000026
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000027namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000028
Karl Wibergbf7a0462018-09-25 14:48:33 +020029using ::testing::AnyOf;
30using ::testing::Eq;
31using ::testing::StrCaseEq;
32
33namespace {
34
Fredrik Solenberg657b2962018-12-05 10:30:25 +010035constexpr int kISAC16kPayloadType = 103;
36constexpr int kISAC32kPayloadType = 104;
37const SdpAudioFormat kISAC16kFormat = { "ISAC", 16000, 1 };
38const SdpAudioFormat kISAC32kFormat = { "ISAC", 32000, 1 };
Karl Wibergbf7a0462018-09-25 14:48:33 +020039
40AudioEncoderIsacFloat::Config TweakConfig(
41 AudioEncoderIsacFloat::Config config,
42 const ACMTestISACConfig& test_config) {
43 if (test_config.currentRateBitPerSec > 0) {
44 config.bit_rate = test_config.currentRateBitPerSec;
45 }
46 if (test_config.currentFrameSizeMsec != 0) {
47 config.frame_size_ms = test_config.currentFrameSizeMsec;
48 }
49 EXPECT_THAT(config.IsOk(), Eq(true));
50 return config;
51}
52
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000053void SetISACConfigDefault(ACMTestISACConfig& isacConfig) {
54 isacConfig.currentRateBitPerSec = 0;
55 isacConfig.currentFrameSizeMsec = 0;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000056 isacConfig.encodingMode = -1;
57 isacConfig.initRateBitPerSec = 0;
58 isacConfig.initFrameSizeInMsec = 0;
59 isacConfig.enforceFrameSize = false;
niklase@google.com470e71d2011-07-07 08:21:25 +000060}
61
Karl Wibergbf7a0462018-09-25 14:48:33 +020062} // namespace
niklase@google.com470e71d2011-07-07 08:21:25 +000063
Fredrik Solenberg657b2962018-12-05 10:30:25 +010064ISACTest::ACMTestTimer::ACMTestTimer() : _msec(0), _sec(0), _min(0), _hour(0) {
65 return;
66}
67
68ISACTest::ACMTestTimer::~ACMTestTimer() {
69 return;
70}
71
72void ISACTest::ACMTestTimer::Reset() {
73 _msec = 0;
74 _sec = 0;
75 _min = 0;
76 _hour = 0;
77 return;
78}
79void ISACTest::ACMTestTimer::Tick10ms() {
80 _msec += 10;
81 Adjust();
82 return;
83}
84
85void ISACTest::ACMTestTimer::Tick1ms() {
86 _msec++;
87 Adjust();
88 return;
89}
90
91void ISACTest::ACMTestTimer::Tick100ms() {
92 _msec += 100;
93 Adjust();
94 return;
95}
96
97void ISACTest::ACMTestTimer::Tick1sec() {
98 _sec++;
99 Adjust();
100 return;
101}
102
103void ISACTest::ACMTestTimer::CurrentTimeHMS(char* currTime) {
104 sprintf(currTime, "%4lu:%02u:%06.3f", _hour, _min,
105 (double)_sec + (double)_msec / 1000.);
106 return;
107}
108
109void ISACTest::ACMTestTimer::CurrentTime(unsigned long& h,
110 unsigned char& m,
111 unsigned char& s,
112 unsigned short& ms) {
113 h = _hour;
114 m = _min;
115 s = _sec;
116 ms = _msec;
117 return;
118}
119
120void ISACTest::ACMTestTimer::Adjust() {
121 unsigned int n;
122 if (_msec >= 1000) {
123 n = _msec / 1000;
124 _msec -= (1000 * n);
125 _sec += n;
126 }
127 if (_sec >= 60) {
128 n = _sec / 60;
129 _sec -= (n * 60);
130 _min += n;
131 }
132 if (_min >= 60) {
133 n = _min / 60;
134 _min -= (n * 60);
135 _hour += n;
136 }
137}
138
139ISACTest::ISACTest()
Karl Wiberg5817d3d2018-04-06 10:06:42 +0200140 : _acmA(AudioCodingModule::Create(
141 AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))),
142 _acmB(AudioCodingModule::Create(
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100143 AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000144
turaj@webrtc.org55e17232013-10-29 04:40:09 +0000145ISACTest::~ISACTest() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000146
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000147void ISACTest::Setup() {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000148 // Register both iSAC-wb & iSAC-swb in both sides as receiver codecs.
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100149 std::map<int, SdpAudioFormat> receive_codecs =
150 {{kISAC16kPayloadType, kISAC16kFormat},
151 {kISAC32kPayloadType, kISAC32kFormat}};
152 _acmA->SetReceiveCodecs(receive_codecs);
153 _acmB->SetReceiveCodecs(receive_codecs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000154
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000155 //--- Set A-to-B channel
turaj@webrtc.org55e17232013-10-29 04:40:09 +0000156 _channel_A2B.reset(new Channel);
157 EXPECT_EQ(0, _acmA->RegisterTransportCallback(_channel_A2B.get()));
158 _channel_A2B->RegisterReceiverACM(_acmB.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000159
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000160 //--- Set B-to-A channel
turaj@webrtc.org55e17232013-10-29 04:40:09 +0000161 _channel_B2A.reset(new Channel);
162 EXPECT_EQ(0, _acmB->RegisterTransportCallback(_channel_B2A.get()));
163 _channel_B2A->RegisterReceiverACM(_acmA.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
Yves Gerey665174f2018-06-19 15:03:05 +0200165 file_name_swb_ =
166 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100168 _acmB->SetEncoder(
169 AudioEncoderIsacFloat::MakeAudioEncoder(
170 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
171 kISAC16kPayloadType));
172 _acmA->SetEncoder(
173 AudioEncoderIsacFloat::MakeAudioEncoder(
174 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
175 kISAC32kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000176
177 _inFileA.Open(file_name_swb_, 32000, "rb");
Henrik Lundin4d682082015-12-10 16:24:39 +0100178 // Set test length to 500 ms (50 blocks of 10 ms each).
179 _inFileA.SetNum10MsBlocksToRead(50);
180 // Fast-forward 1 second (100 blocks) since the files start with silence.
181 _inFileA.FastForward(100);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000182 std::string fileNameA = webrtc::test::OutputPath() + "testisac_a.pcm";
183 std::string fileNameB = webrtc::test::OutputPath() + "testisac_b.pcm";
184 _outFileA.Open(fileNameA, 32000, "wb");
185 _outFileB.Open(fileNameB, 32000, "wb");
186
187 while (!_inFileA.EndOfFile()) {
188 Run10ms();
189 }
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100190
191 EXPECT_TRUE(_acmA->ReceiveFormat());
192 EXPECT_TRUE(_acmB->ReceiveFormat());
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000193
194 _inFileA.Close();
195 _outFileA.Close();
196 _outFileB.Close();
niklase@google.com470e71d2011-07-07 08:21:25 +0000197}
198
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000199void ISACTest::Perform() {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000200 Setup();
niklase@google.com470e71d2011-07-07 08:21:25 +0000201
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000202 int16_t testNr = 0;
203 ACMTestISACConfig wbISACConfig;
204 ACMTestISACConfig swbISACConfig;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000206 SetISACConfigDefault(wbISACConfig);
207 SetISACConfigDefault(swbISACConfig);
niklase@google.com470e71d2011-07-07 08:21:25 +0000208
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000209 wbISACConfig.currentRateBitPerSec = -1;
210 swbISACConfig.currentRateBitPerSec = -1;
211 testNr++;
212 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
213
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000214 SetISACConfigDefault(wbISACConfig);
215 SetISACConfigDefault(swbISACConfig);
216 testNr++;
217 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
niklase@google.com470e71d2011-07-07 08:21:25 +0000218
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000219 testNr++;
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100220 SwitchingSamplingRate(testNr, 4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000223void ISACTest::Run10ms() {
224 AudioFrame audioFrame;
225 EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000226 EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
227 EXPECT_GE(_acmB->Add10MsData(audioFrame), 0);
henrik.lundind4ccb002016-05-17 12:21:55 -0700228 bool muted;
229 EXPECT_EQ(0, _acmA->PlayoutData10Ms(32000, &audioFrame, &muted));
230 ASSERT_FALSE(muted);
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000231 _outFileA.Write10MsData(audioFrame);
henrik.lundind4ccb002016-05-17 12:21:55 -0700232 EXPECT_EQ(0, _acmB->PlayoutData10Ms(32000, &audioFrame, &muted));
233 ASSERT_FALSE(muted);
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000234 _outFileB.Write10MsData(audioFrame);
235}
236
Yves Gerey665174f2018-06-19 15:03:05 +0200237void ISACTest::EncodeDecode(int testNr,
238 ACMTestISACConfig& wbISACConfig,
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000239 ACMTestISACConfig& swbISACConfig) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000240 // Files in Side A and B
241 _inFileA.Open(file_name_swb_, 32000, "rb", true);
242 _inFileB.Open(file_name_swb_, 32000, "rb", true);
243
244 std::string file_name_out;
Jonas Olsson366a50c2018-09-06 13:41:30 +0200245 rtc::StringBuilder file_stream_a;
246 rtc::StringBuilder file_stream_b;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000247 file_stream_a << webrtc::test::OutputPath();
248 file_stream_b << webrtc::test::OutputPath();
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000249 file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
250 file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000251 file_name_out = file_stream_a.str();
252 _outFileA.Open(file_name_out, 32000, "wb");
253 file_name_out = file_stream_b.str();
254 _outFileB.Open(file_name_out, 32000, "wb");
255
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000256 // Side A is sending super-wideband, and side B is sending wideband.
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100257 _acmA->SetEncoder(
258 AudioEncoderIsacFloat::MakeAudioEncoder(
259 TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
260 swbISACConfig),
261 kISAC32kPayloadType));
262 _acmB->SetEncoder(
263 AudioEncoderIsacFloat::MakeAudioEncoder(
264 TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
265 wbISACConfig),
266 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000267
268 bool adaptiveMode = false;
Yves Gerey665174f2018-06-19 15:03:05 +0200269 if ((swbISACConfig.currentRateBitPerSec == -1) ||
270 (wbISACConfig.currentRateBitPerSec == -1)) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000271 adaptiveMode = true;
272 }
273 _myTimer.Reset();
274 _channel_A2B->ResetStats();
275 _channel_B2A->ResetStats();
276
277 char currentTime[500];
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000278 while (!(_inFileA.EndOfFile() || _inFileA.Rewinded())) {
279 Run10ms();
280 _myTimer.Tick10ms();
281 _myTimer.CurrentTimeHMS(currentTime);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000282 }
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000283
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000284 _channel_A2B->ResetStats();
285 _channel_B2A->ResetStats();
286
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000287 _outFileA.Close();
288 _outFileB.Close();
289 _inFileA.Close();
290 _inFileB.Close();
niklase@google.com470e71d2011-07-07 08:21:25 +0000291}
292
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000293void ISACTest::SwitchingSamplingRate(int testNr, int maxSampRateChange) {
294 // Files in Side A
295 _inFileA.Open(file_name_swb_, 32000, "rb");
296 _inFileB.Open(file_name_swb_, 32000, "rb");
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000297
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000298 std::string file_name_out;
Jonas Olsson366a50c2018-09-06 13:41:30 +0200299 rtc::StringBuilder file_stream_a;
300 rtc::StringBuilder file_stream_b;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000301 file_stream_a << webrtc::test::OutputPath();
302 file_stream_b << webrtc::test::OutputPath();
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000303 file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
304 file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000305 file_name_out = file_stream_a.str();
306 _outFileA.Open(file_name_out, 32000, "wb");
307 file_name_out = file_stream_b.str();
308 _outFileB.Open(file_name_out, 32000, "wb");
niklase@google.com470e71d2011-07-07 08:21:25 +0000309
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000310 // Start with side A sending super-wideband and side B seding wideband.
311 // Toggle sending wideband/super-wideband in this test.
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100312 _acmA->SetEncoder(
313 AudioEncoderIsacFloat::MakeAudioEncoder(
314 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
315 kISAC32kPayloadType));
316 _acmB->SetEncoder(
317 AudioEncoderIsacFloat::MakeAudioEncoder(
318 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
319 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000320
321 int numSendCodecChanged = 0;
322 _myTimer.Reset();
323 char currentTime[50];
324 while (numSendCodecChanged < (maxSampRateChange << 1)) {
325 Run10ms();
326 _myTimer.Tick10ms();
327 _myTimer.CurrentTimeHMS(currentTime);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000328 if (_inFileA.EndOfFile()) {
329 if (_inFileA.SamplingFrequency() == 16000) {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000330 // Switch side A to send super-wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000331 _inFileA.Close();
332 _inFileA.Open(file_name_swb_, 32000, "rb");
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100333 _acmA->SetEncoder(
334 AudioEncoderIsacFloat::MakeAudioEncoder(
335 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
336 kISAC32kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000337 } else {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000338 // Switch side A to send wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000339 _inFileA.Close();
340 _inFileA.Open(file_name_swb_, 32000, "rb");
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100341 _acmA->SetEncoder(
342 AudioEncoderIsacFloat::MakeAudioEncoder(
343 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
344 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000345 }
346 numSendCodecChanged++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000347 }
348
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000349 if (_inFileB.EndOfFile()) {
350 if (_inFileB.SamplingFrequency() == 16000) {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000351 // Switch side B to send super-wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000352 _inFileB.Close();
353 _inFileB.Open(file_name_swb_, 32000, "rb");
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100354 _acmB->SetEncoder(
355 AudioEncoderIsacFloat::MakeAudioEncoder(
356 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
357 kISAC32kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000358 } else {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000359 // Switch side B to send wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000360 _inFileB.Close();
361 _inFileB.Open(file_name_swb_, 32000, "rb");
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100362 _acmB->SetEncoder(
363 AudioEncoderIsacFloat::MakeAudioEncoder(
364 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
365 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000366 }
367 numSendCodecChanged++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000368 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000369 }
370 _outFileA.Close();
371 _outFileB.Close();
372 _inFileA.Close();
373 _inFileB.Close();
niklase@google.com470e71d2011-07-07 08:21:25 +0000374}
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000375
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000376} // namespace webrtc