blob: b85c8a0616710642fb8a3bc50e04e7e31851c04d [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"
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"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "test/testsupport/file_utils.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;
Jonas Olssona4d87372019-07-05 19:08:33 +020037const 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,
Jonas Olssona4d87372019-07-05 19:08:33 +0200110 unsigned char& m,
111 unsigned char& s,
112 unsigned short& ms) {
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100113 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.
Jonas Olssona4d87372019-07-05 19:08:33 +0200149 std::map<int, SdpAudioFormat> receive_codecs = {
150 {kISAC16kPayloadType, kISAC16kFormat},
151 {kISAC32kPayloadType, kISAC32kFormat}};
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100152 _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
Jonas Olssona4d87372019-07-05 19:08:33 +0200168 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
169 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
170 kISAC16kPayloadType));
171 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
172 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
173 kISAC32kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000174
175 _inFileA.Open(file_name_swb_, 32000, "rb");
Henrik Lundin4d682082015-12-10 16:24:39 +0100176 // Set test length to 500 ms (50 blocks of 10 ms each).
177 _inFileA.SetNum10MsBlocksToRead(50);
178 // Fast-forward 1 second (100 blocks) since the files start with silence.
179 _inFileA.FastForward(100);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000180 std::string fileNameA = webrtc::test::OutputPath() + "testisac_a.pcm";
181 std::string fileNameB = webrtc::test::OutputPath() + "testisac_b.pcm";
182 _outFileA.Open(fileNameA, 32000, "wb");
183 _outFileB.Open(fileNameB, 32000, "wb");
184
185 while (!_inFileA.EndOfFile()) {
186 Run10ms();
187 }
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100188
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000189 _inFileA.Close();
190 _outFileA.Close();
191 _outFileB.Close();
niklase@google.com470e71d2011-07-07 08:21:25 +0000192}
193
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000194void ISACTest::Perform() {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000195 Setup();
niklase@google.com470e71d2011-07-07 08:21:25 +0000196
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000197 int16_t testNr = 0;
198 ACMTestISACConfig wbISACConfig;
199 ACMTestISACConfig swbISACConfig;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000201 SetISACConfigDefault(wbISACConfig);
202 SetISACConfigDefault(swbISACConfig);
niklase@google.com470e71d2011-07-07 08:21:25 +0000203
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000204 wbISACConfig.currentRateBitPerSec = -1;
205 swbISACConfig.currentRateBitPerSec = -1;
206 testNr++;
207 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
208
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000209 SetISACConfigDefault(wbISACConfig);
210 SetISACConfigDefault(swbISACConfig);
211 testNr++;
212 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
niklase@google.com470e71d2011-07-07 08:21:25 +0000213
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000214 testNr++;
Fredrik Solenberg657b2962018-12-05 10:30:25 +0100215 SwitchingSamplingRate(testNr, 4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000216}
217
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000218void ISACTest::Run10ms() {
219 AudioFrame audioFrame;
220 EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000221 EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
222 EXPECT_GE(_acmB->Add10MsData(audioFrame), 0);
henrik.lundind4ccb002016-05-17 12:21:55 -0700223 bool muted;
224 EXPECT_EQ(0, _acmA->PlayoutData10Ms(32000, &audioFrame, &muted));
225 ASSERT_FALSE(muted);
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000226 _outFileA.Write10MsData(audioFrame);
henrik.lundind4ccb002016-05-17 12:21:55 -0700227 EXPECT_EQ(0, _acmB->PlayoutData10Ms(32000, &audioFrame, &muted));
228 ASSERT_FALSE(muted);
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000229 _outFileB.Write10MsData(audioFrame);
230}
231
Yves Gerey665174f2018-06-19 15:03:05 +0200232void ISACTest::EncodeDecode(int testNr,
233 ACMTestISACConfig& wbISACConfig,
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000234 ACMTestISACConfig& swbISACConfig) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000235 // Files in Side A and B
236 _inFileA.Open(file_name_swb_, 32000, "rb", true);
237 _inFileB.Open(file_name_swb_, 32000, "rb", true);
238
239 std::string file_name_out;
Jonas Olsson366a50c2018-09-06 13:41:30 +0200240 rtc::StringBuilder file_stream_a;
241 rtc::StringBuilder file_stream_b;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000242 file_stream_a << webrtc::test::OutputPath();
243 file_stream_b << webrtc::test::OutputPath();
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000244 file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
245 file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000246 file_name_out = file_stream_a.str();
247 _outFileA.Open(file_name_out, 32000, "wb");
248 file_name_out = file_stream_b.str();
249 _outFileB.Open(file_name_out, 32000, "wb");
250
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000251 // Side A is sending super-wideband, and side B is sending wideband.
Jonas Olssona4d87372019-07-05 19:08:33 +0200252 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
253 TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
254 swbISACConfig),
255 kISAC32kPayloadType));
256 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
257 TweakConfig(*AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
258 wbISACConfig),
259 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000260
261 bool adaptiveMode = false;
Yves Gerey665174f2018-06-19 15:03:05 +0200262 if ((swbISACConfig.currentRateBitPerSec == -1) ||
263 (wbISACConfig.currentRateBitPerSec == -1)) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000264 adaptiveMode = true;
265 }
266 _myTimer.Reset();
267 _channel_A2B->ResetStats();
268 _channel_B2A->ResetStats();
269
270 char currentTime[500];
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000271 while (!(_inFileA.EndOfFile() || _inFileA.Rewinded())) {
272 Run10ms();
273 _myTimer.Tick10ms();
274 _myTimer.CurrentTimeHMS(currentTime);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000275 }
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000276
andresp@webrtc.orgd0b436a2014-01-13 13:15:59 +0000277 _channel_A2B->ResetStats();
278 _channel_B2A->ResetStats();
279
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000280 _outFileA.Close();
281 _outFileB.Close();
282 _inFileA.Close();
283 _inFileB.Close();
niklase@google.com470e71d2011-07-07 08:21:25 +0000284}
285
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000286void ISACTest::SwitchingSamplingRate(int testNr, int maxSampRateChange) {
287 // Files in Side A
288 _inFileA.Open(file_name_swb_, 32000, "rb");
289 _inFileB.Open(file_name_swb_, 32000, "rb");
tina.legrand@webrtc.orgba468042012-08-17 10:38:28 +0000290
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000291 std::string file_name_out;
Jonas Olsson366a50c2018-09-06 13:41:30 +0200292 rtc::StringBuilder file_stream_a;
293 rtc::StringBuilder file_stream_b;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000294 file_stream_a << webrtc::test::OutputPath();
295 file_stream_b << webrtc::test::OutputPath();
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000296 file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
297 file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000298 file_name_out = file_stream_a.str();
299 _outFileA.Open(file_name_out, 32000, "wb");
300 file_name_out = file_stream_b.str();
301 _outFileB.Open(file_name_out, 32000, "wb");
niklase@google.com470e71d2011-07-07 08:21:25 +0000302
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000303 // Start with side A sending super-wideband and side B seding wideband.
304 // Toggle sending wideband/super-wideband in this test.
Jonas Olssona4d87372019-07-05 19:08:33 +0200305 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
306 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
307 kISAC32kPayloadType));
308 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
309 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
310 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000311
312 int numSendCodecChanged = 0;
313 _myTimer.Reset();
314 char currentTime[50];
315 while (numSendCodecChanged < (maxSampRateChange << 1)) {
316 Run10ms();
317 _myTimer.Tick10ms();
318 _myTimer.CurrentTimeHMS(currentTime);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000319 if (_inFileA.EndOfFile()) {
320 if (_inFileA.SamplingFrequency() == 16000) {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000321 // Switch side A to send super-wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000322 _inFileA.Close();
323 _inFileA.Open(file_name_swb_, 32000, "rb");
Jonas Olssona4d87372019-07-05 19:08:33 +0200324 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
325 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
326 kISAC32kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000327 } else {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000328 // Switch side A to send wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000329 _inFileA.Close();
330 _inFileA.Open(file_name_swb_, 32000, "rb");
Jonas Olssona4d87372019-07-05 19:08:33 +0200331 _acmA->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
332 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
333 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000334 }
335 numSendCodecChanged++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000336 }
337
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000338 if (_inFileB.EndOfFile()) {
339 if (_inFileB.SamplingFrequency() == 16000) {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000340 // Switch side B to send super-wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000341 _inFileB.Close();
342 _inFileB.Open(file_name_swb_, 32000, "rb");
Jonas Olssona4d87372019-07-05 19:08:33 +0200343 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
344 *AudioEncoderIsacFloat::SdpToConfig(kISAC32kFormat),
345 kISAC32kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000346 } else {
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +0000347 // Switch side B to send wideband.
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000348 _inFileB.Close();
349 _inFileB.Open(file_name_swb_, 32000, "rb");
Jonas Olssona4d87372019-07-05 19:08:33 +0200350 _acmB->SetEncoder(AudioEncoderIsacFloat::MakeAudioEncoder(
351 *AudioEncoderIsacFloat::SdpToConfig(kISAC16kFormat),
352 kISAC16kPayloadType));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000353 }
354 numSendCodecChanged++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000355 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000356 }
357 _outFileA.Close();
358 _outFileB.Close();
359 _inFileA.Close();
360 _inFileB.Close();
niklase@google.com470e71d2011-07-07 08:21:25 +0000361}
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +0000362
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000363} // namespace webrtc