Home | History | Annotate | Download | only in test
      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