1 /*
2 * Copyright (c) 2012 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 "webrtc/modules/audio_coding/test/iSACTest.h"
12
13 #include <ctype.h>
14 #include <stdio.h>
15 #include <string.h>
16
17 #if _WIN32
18 #include <windows.h>
19 #elif WEBRTC_LINUX
20 #include <time.h>
21 #else
22 #include <sys/time.h>
23 #include <time.h>
24 #endif
25
26 #include "webrtc/modules/audio_coding/acm2/acm_common_defs.h"
27 #include "webrtc/modules/audio_coding/test/utility.h"
28 #include "webrtc/system_wrappers/include/event_wrapper.h"
29 #include "webrtc/system_wrappers/include/tick_util.h"
30 #include "webrtc/system_wrappers/include/trace.h"
31 #include "webrtc/test/testsupport/fileutils.h"
32
33 namespace webrtc {
34
SetISACConfigDefault(ACMTestISACConfig & isacConfig)35 void SetISACConfigDefault(ACMTestISACConfig& isacConfig) {
36 isacConfig.currentRateBitPerSec = 0;
37 isacConfig.currentFrameSizeMsec = 0;
38 isacConfig.encodingMode = -1;
39 isacConfig.initRateBitPerSec = 0;
40 isacConfig.initFrameSizeInMsec = 0;
41 isacConfig.enforceFrameSize = false;
42 return;
43 }
44
SetISAConfig(ACMTestISACConfig & isacConfig,AudioCodingModule * acm,int testMode)45 int16_t SetISAConfig(ACMTestISACConfig& isacConfig, AudioCodingModule* acm,
46 int testMode) {
47
48 if ((isacConfig.currentRateBitPerSec != 0)
49 || (isacConfig.currentFrameSizeMsec != 0)) {
50 auto sendCodec = acm->SendCodec();
51 EXPECT_TRUE(sendCodec);
52 if (isacConfig.currentRateBitPerSec < 0) {
53 // Register iSAC in adaptive (channel-dependent) mode.
54 sendCodec->rate = -1;
55 EXPECT_EQ(0, acm->RegisterSendCodec(*sendCodec));
56 } else {
57 if (isacConfig.currentRateBitPerSec != 0) {
58 sendCodec->rate = isacConfig.currentRateBitPerSec;
59 }
60 if (isacConfig.currentFrameSizeMsec != 0) {
61 sendCodec->pacsize = isacConfig.currentFrameSizeMsec
62 * (sendCodec->plfreq / 1000);
63 }
64 EXPECT_EQ(0, acm->RegisterSendCodec(*sendCodec));
65 }
66 }
67
68 return 0;
69 }
70
ISACTest(int testMode)71 ISACTest::ISACTest(int testMode)
72 : _acmA(AudioCodingModule::Create(1)),
73 _acmB(AudioCodingModule::Create(2)),
74 _testMode(testMode) {}
75
~ISACTest()76 ISACTest::~ISACTest() {}
77
Setup()78 void ISACTest::Setup() {
79 int codecCntr;
80 CodecInst codecParam;
81
82 for (codecCntr = 0; codecCntr < AudioCodingModule::NumberOfCodecs();
83 codecCntr++) {
84 EXPECT_EQ(0, AudioCodingModule::Codec(codecCntr, &codecParam));
85 if (!STR_CASE_CMP(codecParam.plname, "ISAC")
86 && codecParam.plfreq == 16000) {
87 memcpy(&_paramISAC16kHz, &codecParam, sizeof(CodecInst));
88 _idISAC16kHz = codecCntr;
89 }
90 if (!STR_CASE_CMP(codecParam.plname, "ISAC")
91 && codecParam.plfreq == 32000) {
92 memcpy(&_paramISAC32kHz, &codecParam, sizeof(CodecInst));
93 _idISAC32kHz = codecCntr;
94 }
95 }
96
97 // Register both iSAC-wb & iSAC-swb in both sides as receiver codecs.
98 EXPECT_EQ(0, _acmA->RegisterReceiveCodec(_paramISAC16kHz));
99 EXPECT_EQ(0, _acmA->RegisterReceiveCodec(_paramISAC32kHz));
100 EXPECT_EQ(0, _acmB->RegisterReceiveCodec(_paramISAC16kHz));
101 EXPECT_EQ(0, _acmB->RegisterReceiveCodec(_paramISAC32kHz));
102
103 //--- Set A-to-B channel
104 _channel_A2B.reset(new Channel);
105 EXPECT_EQ(0, _acmA->RegisterTransportCallback(_channel_A2B.get()));
106 _channel_A2B->RegisterReceiverACM(_acmB.get());
107
108 //--- Set B-to-A channel
109 _channel_B2A.reset(new Channel);
110 EXPECT_EQ(0, _acmB->RegisterTransportCallback(_channel_B2A.get()));
111 _channel_B2A->RegisterReceiverACM(_acmA.get());
112
113 file_name_swb_ = webrtc::test::ResourcePath("audio_coding/testfile32kHz",
114 "pcm");
115
116 EXPECT_EQ(0, _acmB->RegisterSendCodec(_paramISAC16kHz));
117 EXPECT_EQ(0, _acmA->RegisterSendCodec(_paramISAC32kHz));
118
119 _inFileA.Open(file_name_swb_, 32000, "rb");
120 // Set test length to 500 ms (50 blocks of 10 ms each).
121 _inFileA.SetNum10MsBlocksToRead(50);
122 // Fast-forward 1 second (100 blocks) since the files start with silence.
123 _inFileA.FastForward(100);
124 std::string fileNameA = webrtc::test::OutputPath() + "testisac_a.pcm";
125 std::string fileNameB = webrtc::test::OutputPath() + "testisac_b.pcm";
126 _outFileA.Open(fileNameA, 32000, "wb");
127 _outFileB.Open(fileNameB, 32000, "wb");
128
129 while (!_inFileA.EndOfFile()) {
130 Run10ms();
131 }
132 CodecInst receiveCodec;
133 EXPECT_EQ(0, _acmA->ReceiveCodec(&receiveCodec));
134 EXPECT_EQ(0, _acmB->ReceiveCodec(&receiveCodec));
135
136 _inFileA.Close();
137 _outFileA.Close();
138 _outFileB.Close();
139 }
140
Perform()141 void ISACTest::Perform() {
142 Setup();
143
144 int16_t testNr = 0;
145 ACMTestISACConfig wbISACConfig;
146 ACMTestISACConfig swbISACConfig;
147
148 SetISACConfigDefault(wbISACConfig);
149 SetISACConfigDefault(swbISACConfig);
150
151 wbISACConfig.currentRateBitPerSec = -1;
152 swbISACConfig.currentRateBitPerSec = -1;
153 testNr++;
154 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
155
156 if (_testMode != 0) {
157 SetISACConfigDefault(wbISACConfig);
158 SetISACConfigDefault(swbISACConfig);
159
160 wbISACConfig.currentRateBitPerSec = -1;
161 swbISACConfig.currentRateBitPerSec = -1;
162 wbISACConfig.initRateBitPerSec = 13000;
163 wbISACConfig.initFrameSizeInMsec = 60;
164 swbISACConfig.initRateBitPerSec = 20000;
165 swbISACConfig.initFrameSizeInMsec = 30;
166 testNr++;
167 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
168
169 SetISACConfigDefault(wbISACConfig);
170 SetISACConfigDefault(swbISACConfig);
171
172 wbISACConfig.currentRateBitPerSec = 20000;
173 swbISACConfig.currentRateBitPerSec = 48000;
174 testNr++;
175 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
176
177 wbISACConfig.currentRateBitPerSec = 16000;
178 swbISACConfig.currentRateBitPerSec = 30000;
179 wbISACConfig.currentFrameSizeMsec = 60;
180 testNr++;
181 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
182 }
183
184 SetISACConfigDefault(wbISACConfig);
185 SetISACConfigDefault(swbISACConfig);
186 testNr++;
187 EncodeDecode(testNr, wbISACConfig, swbISACConfig);
188
189 testNr++;
190 if (_testMode == 0) {
191 SwitchingSamplingRate(testNr, 4);
192 } else {
193 SwitchingSamplingRate(testNr, 80);
194 }
195 }
196
Run10ms()197 void ISACTest::Run10ms() {
198 AudioFrame audioFrame;
199 EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
200 EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
201 EXPECT_GE(_acmB->Add10MsData(audioFrame), 0);
202 EXPECT_EQ(0, _acmA->PlayoutData10Ms(32000, &audioFrame));
203 _outFileA.Write10MsData(audioFrame);
204 EXPECT_EQ(0, _acmB->PlayoutData10Ms(32000, &audioFrame));
205 _outFileB.Write10MsData(audioFrame);
206 }
207
EncodeDecode(int testNr,ACMTestISACConfig & wbISACConfig,ACMTestISACConfig & swbISACConfig)208 void ISACTest::EncodeDecode(int testNr, ACMTestISACConfig& wbISACConfig,
209 ACMTestISACConfig& swbISACConfig) {
210 // Files in Side A and B
211 _inFileA.Open(file_name_swb_, 32000, "rb", true);
212 _inFileB.Open(file_name_swb_, 32000, "rb", true);
213
214 std::string file_name_out;
215 std::stringstream file_stream_a;
216 std::stringstream file_stream_b;
217 file_stream_a << webrtc::test::OutputPath();
218 file_stream_b << webrtc::test::OutputPath();
219 file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
220 file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
221 file_name_out = file_stream_a.str();
222 _outFileA.Open(file_name_out, 32000, "wb");
223 file_name_out = file_stream_b.str();
224 _outFileB.Open(file_name_out, 32000, "wb");
225
226 EXPECT_EQ(0, _acmA->RegisterSendCodec(_paramISAC16kHz));
227 EXPECT_EQ(0, _acmA->RegisterSendCodec(_paramISAC32kHz));
228 EXPECT_EQ(0, _acmB->RegisterSendCodec(_paramISAC32kHz));
229 EXPECT_EQ(0, _acmB->RegisterSendCodec(_paramISAC16kHz));
230
231 // Side A is sending super-wideband, and side B is sending wideband.
232 SetISAConfig(swbISACConfig, _acmA.get(), _testMode);
233 SetISAConfig(wbISACConfig, _acmB.get(), _testMode);
234
235 bool adaptiveMode = false;
236 if ((swbISACConfig.currentRateBitPerSec == -1)
237 || (wbISACConfig.currentRateBitPerSec == -1)) {
238 adaptiveMode = true;
239 }
240 _myTimer.Reset();
241 _channel_A2B->ResetStats();
242 _channel_B2A->ResetStats();
243
244 char currentTime[500];
245 EventTimerWrapper* myEvent = EventTimerWrapper::Create();
246 EXPECT_TRUE(myEvent->StartTimer(true, 10));
247 while (!(_inFileA.EndOfFile() || _inFileA.Rewinded())) {
248 Run10ms();
249 _myTimer.Tick10ms();
250 _myTimer.CurrentTimeHMS(currentTime);
251
252 if ((adaptiveMode) && (_testMode != 0)) {
253 myEvent->Wait(5000);
254 EXPECT_TRUE(_acmA->SendCodec());
255 EXPECT_TRUE(_acmB->SendCodec());
256 }
257 }
258
259 if (_testMode != 0) {
260 printf("\n\nSide A statistics\n\n");
261 _channel_A2B->PrintStats(_paramISAC32kHz);
262
263 printf("\n\nSide B statistics\n\n");
264 _channel_B2A->PrintStats(_paramISAC16kHz);
265 }
266
267 _channel_A2B->ResetStats();
268 _channel_B2A->ResetStats();
269
270 _outFileA.Close();
271 _outFileB.Close();
272 _inFileA.Close();
273 _inFileB.Close();
274 }
275
SwitchingSamplingRate(int testNr,int maxSampRateChange)276 void ISACTest::SwitchingSamplingRate(int testNr, int maxSampRateChange) {
277 // Files in Side A
278 _inFileA.Open(file_name_swb_, 32000, "rb");
279 _inFileB.Open(file_name_swb_, 32000, "rb");
280
281 std::string file_name_out;
282 std::stringstream file_stream_a;
283 std::stringstream file_stream_b;
284 file_stream_a << webrtc::test::OutputPath();
285 file_stream_b << webrtc::test::OutputPath();
286 file_stream_a << "out_iSACTest_A_" << testNr << ".pcm";
287 file_stream_b << "out_iSACTest_B_" << testNr << ".pcm";
288 file_name_out = file_stream_a.str();
289 _outFileA.Open(file_name_out, 32000, "wb");
290 file_name_out = file_stream_b.str();
291 _outFileB.Open(file_name_out, 32000, "wb");
292
293 // Start with side A sending super-wideband and side B seding wideband.
294 // Toggle sending wideband/super-wideband in this test.
295 EXPECT_EQ(0, _acmA->RegisterSendCodec(_paramISAC32kHz));
296 EXPECT_EQ(0, _acmB->RegisterSendCodec(_paramISAC16kHz));
297
298 int numSendCodecChanged = 0;
299 _myTimer.Reset();
300 char currentTime[50];
301 while (numSendCodecChanged < (maxSampRateChange << 1)) {
302 Run10ms();
303 _myTimer.Tick10ms();
304 _myTimer.CurrentTimeHMS(currentTime);
305 if (_testMode == 2)
306 printf("\r%s", currentTime);
307 if (_inFileA.EndOfFile()) {
308 if (_inFileA.SamplingFrequency() == 16000) {
309 // Switch side A to send super-wideband.
310 _inFileA.Close();
311 _inFileA.Open(file_name_swb_, 32000, "rb");
312 EXPECT_EQ(0, _acmA->RegisterSendCodec(_paramISAC32kHz));
313 } else {
314 // Switch side A to send wideband.
315 _inFileA.Close();
316 _inFileA.Open(file_name_swb_, 32000, "rb");
317 EXPECT_EQ(0, _acmA->RegisterSendCodec(_paramISAC16kHz));
318 }
319 numSendCodecChanged++;
320 }
321
322 if (_inFileB.EndOfFile()) {
323 if (_inFileB.SamplingFrequency() == 16000) {
324 // Switch side B to send super-wideband.
325 _inFileB.Close();
326 _inFileB.Open(file_name_swb_, 32000, "rb");
327 EXPECT_EQ(0, _acmB->RegisterSendCodec(_paramISAC32kHz));
328 } else {
329 // Switch side B to send wideband.
330 _inFileB.Close();
331 _inFileB.Open(file_name_swb_, 32000, "rb");
332 EXPECT_EQ(0, _acmB->RegisterSendCodec(_paramISAC16kHz));
333 }
334 numSendCodecChanged++;
335 }
336 }
337 _outFileA.Close();
338 _outFileB.Close();
339 _inFileA.Close();
340 _inFileB.Close();
341 }
342
343 } // namespace webrtc
344