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