• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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