Home | History | Annotate | Download | only in cmd_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 <stdio.h>
     12 #include <stdlib.h>
     13 #include <string.h>
     14 #ifndef _WIN32
     15 #include <unistd.h>
     16 #endif
     17 
     18 #include <vector>
     19 
     20 #include "gflags/gflags.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 #include "webrtc/engine_configurations.h"
     23 #include "webrtc/modules/audio_processing/include/audio_processing.h"
     24 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
     25 #include "webrtc/test/channel_transport/include/channel_transport.h"
     26 #include "webrtc/test/testsupport/fileutils.h"
     27 #include "webrtc/test/testsupport/trace_to_stderr.h"
     28 #include "webrtc/voice_engine/include/voe_audio_processing.h"
     29 #include "webrtc/voice_engine/include/voe_base.h"
     30 #include "webrtc/voice_engine/include/voe_codec.h"
     31 #include "webrtc/voice_engine/include/voe_dtmf.h"
     32 #include "webrtc/voice_engine/include/voe_errors.h"
     33 #include "webrtc/voice_engine/include/voe_external_media.h"
     34 #include "webrtc/voice_engine/include/voe_file.h"
     35 #include "webrtc/voice_engine/include/voe_hardware.h"
     36 #include "webrtc/voice_engine/include/voe_neteq_stats.h"
     37 #include "webrtc/voice_engine/include/voe_network.h"
     38 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
     39 #include "webrtc/voice_engine/include/voe_video_sync.h"
     40 #include "webrtc/voice_engine/include/voe_volume_control.h"
     41 
     42 DEFINE_bool(use_log_file, false,
     43     "Output logs to a file; by default they will be printed to stderr.");
     44 
     45 using namespace webrtc;
     46 using namespace test;
     47 
     48 #define VALIDATE                                           \
     49   if (res != 0) {                                          \
     50     printf("*** Error at line %i \n", __LINE__);           \
     51     printf("*** Error code = %i \n", base1->LastError());  \
     52   }
     53 
     54 VoiceEngine* m_voe = NULL;
     55 VoEBase* base1 = NULL;
     56 VoECodec* codec = NULL;
     57 VoEVolumeControl* volume = NULL;
     58 VoEDtmf* dtmf = NULL;
     59 VoERTP_RTCP* rtp_rtcp = NULL;
     60 VoEAudioProcessing* apm = NULL;
     61 VoENetwork* netw = NULL;
     62 VoEFile* file = NULL;
     63 VoEVideoSync* vsync = NULL;
     64 VoEHardware* hardware = NULL;
     65 VoEExternalMedia* xmedia = NULL;
     66 VoENetEqStats* neteqst = NULL;
     67 
     68 void RunTest(std::string out_path);
     69 
     70 class MyObserver : public VoiceEngineObserver {
     71  public:
     72    virtual void CallbackOnError(int channel, int err_code);
     73 };
     74 
     75 void MyObserver::CallbackOnError(int channel, int err_code) {
     76   // Add printf for other error codes here
     77   if (err_code == VE_TYPING_NOISE_WARNING) {
     78     printf("  TYPING NOISE DETECTED \n");
     79   } else if (err_code == VE_TYPING_NOISE_OFF_WARNING) {
     80     printf("  TYPING NOISE OFF DETECTED \n");
     81   } else if (err_code == VE_RECEIVE_PACKET_TIMEOUT) {
     82     printf("  RECEIVE PACKET TIMEOUT \n");
     83   } else if (err_code == VE_PACKET_RECEIPT_RESTARTED) {
     84     printf("  PACKET RECEIPT RESTARTED \n");
     85   } else if (err_code == VE_RUNTIME_PLAY_WARNING) {
     86     printf("  RUNTIME PLAY WARNING \n");
     87   } else if (err_code == VE_RUNTIME_REC_WARNING) {
     88     printf("  RUNTIME RECORD WARNING \n");
     89   } else if (err_code == VE_SATURATION_WARNING) {
     90     printf("  SATURATION WARNING \n");
     91   } else if (err_code == VE_RUNTIME_PLAY_ERROR) {
     92     printf("  RUNTIME PLAY ERROR \n");
     93   } else if (err_code == VE_RUNTIME_REC_ERROR) {
     94     printf("  RUNTIME RECORD ERROR \n");
     95   } else if (err_code == VE_REC_DEVICE_REMOVED) {
     96     printf("  RECORD DEVICE REMOVED \n");
     97   }
     98 }
     99 
    100 void SetStereoIfOpus(bool use_stereo, CodecInst* codec_params) {
    101   if (strncmp(codec_params->plname, "opus", 4) == 0) {
    102     if (use_stereo)
    103       codec_params->channels = 2;
    104     else
    105       codec_params->channels = 1;
    106   }
    107 }
    108 
    109 void PrintCodecs(bool opus_stereo) {
    110   CodecInst codec_params;
    111   for (int i = 0; i < codec->NumOfCodecs(); ++i) {
    112     int res = codec->GetCodec(i, codec_params);
    113     VALIDATE;
    114     SetStereoIfOpus(opus_stereo, &codec_params);
    115     printf("%2d. %3d  %s/%d/%d \n", i, codec_params.pltype, codec_params.plname,
    116            codec_params.plfreq, codec_params.channels);
    117   }
    118 }
    119 
    120 int main(int argc, char** argv) {
    121   google::ParseCommandLineFlags(&argc, &argv, true);
    122 
    123   int res = 0;
    124 
    125   printf("Test started \n");
    126 
    127   m_voe = VoiceEngine::Create();
    128   base1 = VoEBase::GetInterface(m_voe);
    129   codec = VoECodec::GetInterface(m_voe);
    130   apm = VoEAudioProcessing::GetInterface(m_voe);
    131   volume = VoEVolumeControl::GetInterface(m_voe);
    132   dtmf = VoEDtmf::GetInterface(m_voe);
    133   rtp_rtcp = VoERTP_RTCP::GetInterface(m_voe);
    134   netw = VoENetwork::GetInterface(m_voe);
    135   file = VoEFile::GetInterface(m_voe);
    136   vsync = VoEVideoSync::GetInterface(m_voe);
    137   hardware = VoEHardware::GetInterface(m_voe);
    138   xmedia = VoEExternalMedia::GetInterface(m_voe);
    139   neteqst = VoENetEqStats::GetInterface(m_voe);
    140 
    141   MyObserver my_observer;
    142 
    143   scoped_ptr<test::TraceToStderr> trace_to_stderr;
    144   if (!FLAGS_use_log_file) {
    145     trace_to_stderr.reset(new test::TraceToStderr);
    146   } else {
    147     const std::string trace_filename = test::OutputPath() + "webrtc_trace.txt";
    148     VoiceEngine::SetTraceFilter(kTraceAll);
    149     res = VoiceEngine::SetTraceFile(trace_filename.c_str());
    150     VALIDATE;
    151     res = VoiceEngine::SetTraceCallback(NULL);
    152     VALIDATE;
    153     printf("Outputting logs to file: %s\n", trace_filename.c_str());
    154   }
    155 
    156   printf("Init\n");
    157   res = base1->Init();
    158   if (res != 0) {
    159     printf("\nError calling Init: %d\n", base1->LastError());
    160     fflush(NULL);
    161     exit(1);
    162   }
    163 
    164   res = base1->RegisterVoiceEngineObserver(my_observer);
    165   VALIDATE;
    166 
    167   printf("Version\n");
    168   char tmp[1024];
    169   res = base1->GetVersion(tmp);
    170   VALIDATE;
    171   printf("%s\n", tmp);
    172 
    173   RunTest(test::OutputPath());
    174 
    175   printf("Terminate \n");
    176 
    177   base1->DeRegisterVoiceEngineObserver();
    178 
    179   res = base1->Terminate();
    180   VALIDATE;
    181 
    182   if (base1)
    183     base1->Release();
    184 
    185   if (codec)
    186     codec->Release();
    187 
    188   if (volume)
    189     volume->Release();
    190 
    191   if (dtmf)
    192     dtmf->Release();
    193 
    194   if (rtp_rtcp)
    195     rtp_rtcp->Release();
    196 
    197   if (apm)
    198     apm->Release();
    199 
    200   if (netw)
    201     netw->Release();
    202 
    203   if (file)
    204     file->Release();
    205 
    206   if (vsync)
    207     vsync->Release();
    208 
    209   if (hardware)
    210     hardware->Release();
    211 
    212   if (xmedia)
    213     xmedia->Release();
    214 
    215   if (neteqst)
    216     neteqst->Release();
    217 
    218   VoiceEngine::Delete(m_voe);
    219 
    220   return 0;
    221 }
    222 
    223 void RunTest(std::string out_path) {
    224   int chan, res;
    225   CodecInst cinst;
    226   bool enable_aec = false;
    227   bool enable_agc = false;
    228   bool enable_rx_agc = false;
    229   bool enable_cng = false;
    230   bool enable_ns = false;
    231   bool enable_rx_ns = false;
    232   bool typing_detection = false;
    233   bool muted = false;
    234   bool opus_stereo = false;
    235   bool experimental_ns_enabled = false;
    236 
    237 #if defined(WEBRTC_ANDROID)
    238   std::string resource_path = "/sdcard/";
    239 #else
    240   std::string resource_path = webrtc::test::ProjectRootPath();
    241   if (resource_path == webrtc::test::kCannotFindProjectRootDir) {
    242     printf("*** Unable to get project root directory. "
    243            "File playing may fail. ***\n");
    244     // Fall back to the current directory.
    245     resource_path = "./";
    246   } else {
    247     resource_path += "data/voice_engine/";
    248   }
    249 #endif
    250   const std::string audio_filename = resource_path + "audio_long16.pcm";
    251 
    252   const std::string play_filename = out_path + "recorded_playout.pcm";
    253   const std::string mic_filename = out_path + "recorded_mic.pcm";
    254 
    255   chan = base1->CreateChannel();
    256   if (chan < 0) {
    257     printf("************ Error code = %i\n", base1->LastError());
    258     fflush(NULL);
    259   }
    260 
    261   scoped_ptr<VoiceChannelTransport> voice_channel_transport(
    262       new VoiceChannelTransport(netw, chan));
    263 
    264   char ip[64];
    265   printf("1. 127.0.0.1 \n");
    266   printf("2. Specify IP \n");
    267   int ip_selection;
    268   ASSERT_EQ(1, scanf("%i", &ip_selection));
    269 
    270   if (ip_selection == 1) {
    271     strcpy(ip, "127.0.0.1");
    272   } else {
    273     printf("Specify remote IP: ");
    274     ASSERT_EQ(1, scanf("%s", ip));
    275   }
    276 
    277   int rPort;
    278   printf("Specify remote port (1=1234): ");
    279   ASSERT_EQ(1, scanf("%i", &rPort));
    280   if (1 == rPort)
    281     rPort = 1234;
    282   printf("Set Send port \n");
    283 
    284   printf("Set Send IP \n");
    285   res = voice_channel_transport->SetSendDestination(ip, rPort);
    286   VALIDATE;
    287 
    288   int lPort;
    289   printf("Specify local port (1=1234): ");
    290   ASSERT_EQ(1, scanf("%i", &lPort));
    291   if (1 == lPort)
    292     lPort = 1234;
    293   printf("Set Rec Port \n");
    294 
    295   res = voice_channel_transport->SetLocalReceiver(lPort);
    296   VALIDATE;
    297 
    298   printf("\n");
    299   PrintCodecs(opus_stereo);
    300   printf("Select send codec: ");
    301   int codec_selection;
    302   ASSERT_EQ(1, scanf("%i", &codec_selection));
    303   codec->GetCodec(codec_selection, cinst);
    304 
    305   printf("Set primary codec\n");
    306   SetStereoIfOpus(opus_stereo, &cinst);
    307   res = codec->SetSendCodec(chan, cinst);
    308   VALIDATE;
    309 
    310   const int kMaxNumChannels = 8;
    311   int channel_index = 0;
    312   std::vector<int> channels(kMaxNumChannels);
    313   std::vector<VoiceChannelTransport*> voice_channel_transports(kMaxNumChannels);
    314 
    315   for (int i = 0; i < kMaxNumChannels; ++i) {
    316     channels[i] = base1->CreateChannel();
    317     int port = rPort + (i + 1) * 2;
    318 
    319     voice_channel_transports[i] = new VoiceChannelTransport(netw, channels[i]);
    320 
    321     res = voice_channel_transports[i]->SetSendDestination(ip, port);
    322     VALIDATE;
    323     res = voice_channel_transports[i]->SetLocalReceiver(port);
    324     VALIDATE;
    325     res = codec->SetSendCodec(channels[i], cinst);
    326     VALIDATE;
    327   }
    328 
    329   // Call loop
    330   bool newcall = true;
    331   while (newcall) {
    332     int rd(-1), pd(-1);
    333     res = hardware->GetNumOfRecordingDevices(rd);
    334     VALIDATE;
    335     res = hardware->GetNumOfPlayoutDevices(pd);
    336     VALIDATE;
    337 
    338     char dn[128] = { 0 };
    339     char guid[128] = { 0 };
    340     printf("\nPlayout devices (%d): \n", pd);
    341     for (int j = 0; j < pd; ++j) {
    342       res = hardware->GetPlayoutDeviceName(j, dn, guid);
    343       VALIDATE;
    344       printf("  %d: %s \n", j, dn);
    345     }
    346 
    347     printf("Recording devices (%d): \n", rd);
    348     for (int j = 0; j < rd; ++j) {
    349       res = hardware->GetRecordingDeviceName(j, dn, guid);
    350       VALIDATE;
    351       printf("  %d: %s \n", j, dn);
    352     }
    353 
    354     printf("Select playout device: ");
    355     ASSERT_EQ(1, scanf("%d", &pd));
    356     res = hardware->SetPlayoutDevice(pd);
    357     VALIDATE;
    358     printf("Select recording device: ");
    359     ASSERT_EQ(1, scanf("%d", &rd));
    360     printf("Setting sound devices \n");
    361     res = hardware->SetRecordingDevice(rd);
    362     VALIDATE;
    363 
    364     res = codec->SetVADStatus(0, enable_cng);
    365     VALIDATE;
    366 
    367     res = apm->SetAgcStatus(enable_agc);
    368     VALIDATE;
    369 
    370     res = apm->SetEcStatus(enable_aec);
    371     VALIDATE;
    372 
    373     res = apm->SetNsStatus(enable_ns);
    374     VALIDATE;
    375 
    376     printf("\n1. Send, listen and playout \n");
    377     printf("2. Send only \n");
    378     printf("3. Listen and playout only \n");
    379     printf("Select transfer mode: ");
    380     int call_selection;
    381     ASSERT_EQ(1, scanf("%i", &call_selection));
    382     const bool send = !(call_selection == 3);
    383     const bool receive = !(call_selection == 2);
    384 
    385     if (receive) {
    386 #ifndef EXTERNAL_TRANSPORT
    387       printf("Start Listen \n");
    388       res = base1->StartReceive(chan);
    389       VALIDATE;
    390 #endif
    391 
    392       printf("Start Playout \n");
    393       res = base1->StartPlayout(chan);
    394       VALIDATE;
    395     }
    396 
    397     if (send) {
    398       printf("Start Send \n");
    399       res = base1->StartSend(chan);
    400       VALIDATE;
    401     }
    402 
    403     printf("Getting mic volume \n");
    404     unsigned int vol = 999;
    405     res = volume->GetMicVolume(vol);
    406     VALIDATE;
    407     if ((vol > 255) || (vol < 1)) {
    408       printf("\n****ERROR in GetMicVolume");
    409     }
    410 
    411     int forever = 1;
    412     while (forever) {
    413       printf("\nSelect codec\n");
    414       PrintCodecs(opus_stereo);
    415       printf("\nOther actions\n");
    416       const int num_codecs = codec->NumOfCodecs();
    417       int option_index = num_codecs;
    418       printf("%i. Toggle CNG\n", option_index++);
    419       printf("%i. Toggle AGC\n", option_index++);
    420       printf("%i. Toggle NS\n", option_index++);
    421       printf("%i. Toggle experimental NS\n", option_index++);
    422       printf("%i. Toggle EC\n", option_index++);
    423       printf("%i. Select AEC\n", option_index++);
    424       printf("%i. Select AECM\n", option_index++);
    425       printf("%i. Get speaker volume\n", option_index++);
    426       printf("%i. Set speaker volume\n", option_index++);
    427       printf("%i. Get microphone volume\n", option_index++);
    428       printf("%i. Set microphone volume\n", option_index++);
    429       printf("%i. Play local file (audio_long16.pcm) \n", option_index++);
    430       printf("%i. Change playout device \n", option_index++);
    431       printf("%i. Change recording device \n", option_index++);
    432       printf("%i. Toggle receive-side AGC \n", option_index++);
    433       printf("%i. Toggle receive-side NS \n", option_index++);
    434       printf("%i. AGC status \n", option_index++);
    435       printf("%i. Toggle microphone mute \n", option_index++);
    436       printf("%i. Get last error code \n", option_index++);
    437       printf("%i. Toggle typing detection \n",
    438              option_index++);
    439       printf("%i. Record a PCM file \n", option_index++);
    440       printf("%i. Play a previously recorded PCM file locally \n",
    441              option_index++);
    442       printf("%i. Play a previously recorded PCM file as microphone \n",
    443              option_index++);
    444       printf("%i. Add an additional file-playing channel \n", option_index++);
    445       printf("%i. Remove a file-playing channel \n", option_index++);
    446       printf("%i. Toggle Opus stereo (Opus must be selected again to apply "
    447              "the setting) \n", option_index++);
    448       printf("%i. Set Opus maximum playback rate \n", option_index++);
    449       printf("%i. Set bit rate (only take effect on codecs that allow the "
    450              "change) \n", option_index++);
    451 
    452       printf("Select action or %i to stop the call: ", option_index);
    453       int option_selection;
    454       ASSERT_EQ(1, scanf("%i", &option_selection));
    455 
    456       option_index = num_codecs;
    457       if (option_selection < option_index) {
    458         res = codec->GetCodec(option_selection, cinst);
    459         VALIDATE;
    460         SetStereoIfOpus(opus_stereo, &cinst);
    461         printf("Set primary codec\n");
    462         res = codec->SetSendCodec(chan, cinst);
    463         VALIDATE;
    464       } else if (option_selection == option_index++) {
    465         enable_cng = !enable_cng;
    466         res = codec->SetVADStatus(0, enable_cng);
    467         VALIDATE;
    468         if (enable_cng)
    469           printf("\n CNG is now on! \n");
    470         else
    471           printf("\n CNG is now off! \n");
    472       } else if (option_selection == option_index++) {
    473         enable_agc = !enable_agc;
    474         res = apm->SetAgcStatus(enable_agc);
    475         VALIDATE;
    476         if (enable_agc)
    477           printf("\n AGC is now on! \n");
    478         else
    479           printf("\n AGC is now off! \n");
    480       } else if (option_selection == option_index++) {
    481         enable_ns = !enable_ns;
    482         res = apm->SetNsStatus(enable_ns);
    483         VALIDATE;
    484         if (enable_ns)
    485           printf("\n NS is now on! \n");
    486         else
    487           printf("\n NS is now off! \n");
    488       } else if (option_selection == option_index++) {
    489         experimental_ns_enabled = !experimental_ns_enabled;
    490         Config config;
    491         config.Set<ExperimentalNs>(new ExperimentalNs(experimental_ns_enabled));
    492         base1->audio_processing()->SetExtraOptions(config);
    493         if (experimental_ns_enabled) {
    494           printf("\n Experimental NS is now on!\n");
    495         } else {
    496           printf("\n Experimental NS is now off!\n");
    497         }
    498       } else if (option_selection == option_index++) {
    499         enable_aec = !enable_aec;
    500         res = apm->SetEcStatus(enable_aec, kEcUnchanged);
    501         VALIDATE;
    502         if (enable_aec)
    503           printf("\n Echo control is now on! \n");
    504         else
    505           printf("\n Echo control is now off! \n");
    506       } else if (option_selection == option_index++) {
    507         res = apm->SetEcStatus(enable_aec, kEcAec);
    508         VALIDATE;
    509         printf("\n AEC selected! \n");
    510         if (enable_aec)
    511           printf(" (Echo control is on)\n");
    512         else
    513           printf(" (Echo control is off)\n");
    514       } else if (option_selection == option_index++) {
    515         res = apm->SetEcStatus(enable_aec, kEcAecm);
    516         VALIDATE;
    517         printf("\n AECM selected! \n");
    518         if (enable_aec)
    519           printf(" (Echo control is on)\n");
    520         else
    521           printf(" (Echo control is off)\n");
    522       } else if (option_selection == option_index++) {
    523         unsigned vol(0);
    524         res = volume->GetSpeakerVolume(vol);
    525         VALIDATE;
    526         printf("\n Speaker Volume is %d \n", vol);
    527       } else if (option_selection == option_index++) {
    528         printf("Level: ");
    529         int level;
    530         ASSERT_EQ(1, scanf("%i", &level));
    531         res = volume->SetSpeakerVolume(level);
    532         VALIDATE;
    533       } else if (option_selection == option_index++) {
    534         unsigned vol(0);
    535         res = volume->GetMicVolume(vol);
    536         VALIDATE;
    537         printf("\n Microphone Volume is %d \n", vol);
    538       } else if (option_selection == option_index++) {
    539         printf("Level: ");
    540         int level;
    541         ASSERT_EQ(1, scanf("%i", &level));
    542         res = volume->SetMicVolume(level);
    543         VALIDATE;
    544       } else if (option_selection == option_index++) {
    545         res = file->StartPlayingFileLocally(0, audio_filename.c_str());
    546         VALIDATE;
    547       } else if (option_selection == option_index++) {
    548         // change the playout device with current call
    549         int num_pd(-1);
    550         res = hardware->GetNumOfPlayoutDevices(num_pd);
    551         VALIDATE;
    552 
    553         char dn[128] = { 0 };
    554         char guid[128] = { 0 };
    555 
    556         printf("\nPlayout devices (%d): \n", num_pd);
    557         for (int i = 0; i < num_pd; ++i) {
    558           res = hardware->GetPlayoutDeviceName(i, dn, guid);
    559           VALIDATE;
    560           printf("  %d: %s \n", i, dn);
    561         }
    562         printf("Select playout device: ");
    563         ASSERT_EQ(1, scanf("%d", &num_pd));
    564         // Will use plughw for hardware devices
    565         res = hardware->SetPlayoutDevice(num_pd);
    566         VALIDATE;
    567       } else if (option_selection == option_index++) {
    568         // change the recording device with current call
    569         int num_rd(-1);
    570 
    571         res = hardware->GetNumOfRecordingDevices(num_rd);
    572         VALIDATE;
    573 
    574         char dn[128] = { 0 };
    575         char guid[128] = { 0 };
    576 
    577         printf("Recording devices (%d): \n", num_rd);
    578         for (int i = 0; i < num_rd; ++i) {
    579           res = hardware->GetRecordingDeviceName(i, dn, guid);
    580           VALIDATE;
    581           printf("  %d: %s \n", i, dn);
    582         }
    583 
    584         printf("Select recording device: ");
    585         ASSERT_EQ(1, scanf("%d", &num_rd));
    586         printf("Setting sound devices \n");
    587         // Will use plughw for hardware devices
    588         res = hardware->SetRecordingDevice(num_rd);
    589         VALIDATE;
    590       } else if (option_selection == option_index++) {
    591         // Remote AGC
    592         enable_rx_agc = !enable_rx_agc;
    593         res = apm->SetRxAgcStatus(chan, enable_rx_agc);
    594         VALIDATE;
    595         if (enable_rx_agc)
    596           printf("\n Receive-side AGC is now on! \n");
    597         else
    598           printf("\n Receive-side AGC is now off! \n");
    599       } else if (option_selection == option_index++) {
    600         // Remote NS
    601         enable_rx_ns = !enable_rx_ns;
    602         res = apm->SetRxNsStatus(chan, enable_rx_ns);
    603         VALIDATE;
    604         if (enable_rx_ns)
    605           printf("\n Receive-side NS is now on! \n");
    606         else
    607           printf("\n Receive-side NS is now off! \n");
    608       } else if (option_selection == option_index++) {
    609         AgcModes agcmode;
    610         bool enable;
    611         res = apm->GetAgcStatus(enable, agcmode);
    612         VALIDATE
    613             printf("\n AGC enable is %d, mode is %d \n", enable, agcmode);
    614       } else if (option_selection == option_index++) {
    615         // Toggle Mute on Microphone
    616         res = volume->GetInputMute(chan, muted);
    617         VALIDATE;
    618         muted = !muted;
    619         res = volume->SetInputMute(chan, muted);
    620         VALIDATE;
    621         if (muted)
    622           printf("\n Microphone is now on mute! \n");
    623         else
    624           printf("\n Microphone is no longer on mute! \n");
    625       } else if (option_selection == option_index++) {
    626         // Get the last error code and print to screen
    627         int err_code = 0;
    628         err_code = base1->LastError();
    629         if (err_code != -1)
    630           printf("\n The last error code was %i.\n", err_code);
    631       } else if (option_selection == option_index++) {
    632         typing_detection= !typing_detection;
    633         res = apm->SetTypingDetectionStatus(typing_detection);
    634         VALIDATE;
    635         if (typing_detection)
    636           printf("\n Typing detection is now on!\n");
    637         else
    638           printf("\n Typing detection is now off!\n");
    639       } else if (option_selection == option_index++) {
    640         int stop_record = 1;
    641         int file_source = 1;
    642         printf("\n Select source of recorded file. ");
    643         printf("\n 1. Record from microphone to file ");
    644         printf("\n 2. Record from playout to file ");
    645         printf("\n Enter your selection: \n");
    646         ASSERT_EQ(1, scanf("%i", &file_source));
    647         if (file_source == 1) {
    648           printf("\n Start recording microphone as %s \n",
    649                  mic_filename.c_str());
    650           res = file->StartRecordingMicrophone(mic_filename.c_str());
    651           VALIDATE;
    652         } else {
    653           printf("\n Start recording playout as %s \n", play_filename.c_str());
    654           res = file->StartRecordingPlayout(chan, play_filename.c_str());
    655           VALIDATE;
    656         }
    657         while (stop_record != 0) {
    658           printf("\n Type 0 to stop recording file \n");
    659           ASSERT_EQ(1, scanf("%i", &stop_record));
    660         }
    661         if (file_source == 1) {
    662           res = file->StopRecordingMicrophone();
    663           VALIDATE;
    664         } else {
    665           res = file->StopRecordingPlayout(chan);
    666           VALIDATE;
    667         }
    668         printf("\n File finished recording \n");
    669       } else if (option_selection == option_index++) {
    670         int file_type = 1;
    671         int stop_play = 1;
    672         printf("\n Select a file to play locally in a loop.");
    673         printf("\n 1. Play %s", mic_filename.c_str());
    674         printf("\n 2. Play %s", play_filename.c_str());
    675         printf("\n Enter your selection\n");
    676         ASSERT_EQ(1, scanf("%i", &file_type));
    677         if (file_type == 1)  {
    678           printf("\n Start playing %s locally in a loop\n",
    679                  mic_filename.c_str());
    680           res = file->StartPlayingFileLocally(chan, mic_filename.c_str(), true);
    681           VALIDATE;
    682         } else {
    683           printf("\n Start playing %s locally in a loop\n",
    684                  play_filename.c_str());
    685           res = file->StartPlayingFileLocally(chan, play_filename.c_str(),
    686                                               true);
    687           VALIDATE;
    688         }
    689         while (stop_play != 0) {
    690           printf("\n Type 0 to stop playing file\n");
    691           ASSERT_EQ(1, scanf("%i", &stop_play));
    692         }
    693         res = file->StopPlayingFileLocally(chan);
    694         VALIDATE;
    695       } else if (option_selection == option_index++) {
    696         int file_type = 1;
    697         int stop_play = 1;
    698         printf("\n Select a file to play as microphone in a loop.");
    699         printf("\n 1. Play %s", mic_filename.c_str());
    700         printf("\n 2. Play %s", play_filename.c_str());
    701         printf("\n Enter your selection\n");
    702         ASSERT_EQ(1, scanf("%i", &file_type));
    703         if (file_type == 1)  {
    704           printf("\n Start playing %s as mic in a loop\n",
    705                  mic_filename.c_str());
    706           res = file->StartPlayingFileAsMicrophone(chan, mic_filename.c_str(),
    707                                                    true);
    708           VALIDATE;
    709         } else {
    710           printf("\n Start playing %s as mic in a loop\n",
    711                  play_filename.c_str());
    712           res = file->StartPlayingFileAsMicrophone(chan, play_filename.c_str(),
    713                                                    true);
    714           VALIDATE;
    715         }
    716         while (stop_play != 0) {
    717           printf("\n Type 0 to stop playing file\n");
    718           ASSERT_EQ(1, scanf("%i", &stop_play));
    719         }
    720         res = file->StopPlayingFileAsMicrophone(chan);
    721         VALIDATE;
    722       } else if (option_selection == option_index++) {
    723         if (channel_index < kMaxNumChannels) {
    724           res = base1->StartReceive(channels[channel_index]);
    725           VALIDATE;
    726           res = base1->StartPlayout(channels[channel_index]);
    727           VALIDATE;
    728           res = base1->StartSend(channels[channel_index]);
    729           VALIDATE;
    730           res = file->StartPlayingFileAsMicrophone(channels[channel_index],
    731                                                    audio_filename.c_str(),
    732                                                    true,
    733                                                    false);
    734           VALIDATE;
    735           channel_index++;
    736           printf("Using %d additional channels\n", channel_index);
    737         } else {
    738           printf("Max number of channels reached\n");
    739         }
    740       } else if (option_selection == option_index++) {
    741         if (channel_index > 0) {
    742           channel_index--;
    743           res = file->StopPlayingFileAsMicrophone(channels[channel_index]);
    744           VALIDATE;
    745           res = base1->StopSend(channels[channel_index]);
    746           VALIDATE;
    747           res = base1->StopPlayout(channels[channel_index]);
    748           VALIDATE;
    749           res = base1->StopReceive(channels[channel_index]);
    750           VALIDATE;
    751           printf("Using %d additional channels\n", channel_index);
    752         } else {
    753           printf("All additional channels stopped\n");
    754         }
    755       } else if (option_selection == option_index++) {
    756         opus_stereo = !opus_stereo;
    757         if (opus_stereo)
    758           printf("\n Opus stereo enabled (select Opus again to apply the "
    759                  "setting). \n");
    760         else
    761           printf("\n Opus mono enabled (select Opus again to apply the "
    762                  "setting). \n");
    763       } else if (option_selection == option_index++) {
    764         printf("\n Input maxium playback rate in Hz: ");
    765         int max_playback_rate;
    766         ASSERT_EQ(1, scanf("%i", &max_playback_rate));
    767         res = codec->SetOpusMaxPlaybackRate(chan, max_playback_rate);
    768         VALIDATE;
    769       } else if (option_selection == option_index++) {
    770         res = codec->GetSendCodec(chan, cinst);
    771         VALIDATE;
    772         printf("Current bit rate is %i bps, set to: ", cinst.rate);
    773         ASSERT_EQ(1, scanf("%i", &cinst.rate));
    774         res = codec->SetSendCodec(chan, cinst);
    775         VALIDATE;
    776       } else {
    777         break;
    778       }
    779     }
    780 
    781     if (send) {
    782       printf("Stop Send \n");
    783       res = base1->StopSend(chan);
    784       VALIDATE;
    785     }
    786 
    787     if (receive) {
    788       printf("Stop Playout \n");
    789       res = base1->StopPlayout(chan);
    790       VALIDATE;
    791 
    792 #ifndef EXTERNAL_TRANSPORT
    793       printf("Stop Listen \n");
    794       res = base1->StopReceive(chan);
    795       VALIDATE;
    796 #endif
    797     }
    798 
    799     while (channel_index > 0) {
    800       --channel_index;
    801       res = file->StopPlayingFileAsMicrophone(channels[channel_index]);
    802       VALIDATE;
    803       res = base1->StopSend(channels[channel_index]);
    804       VALIDATE;
    805       res = base1->StopPlayout(channels[channel_index]);
    806       VALIDATE;
    807       res = base1->StopReceive(channels[channel_index]);
    808       VALIDATE;
    809     }
    810 
    811     printf("\n1. New call \n");
    812     printf("2. Quit \n");
    813     printf("Select action: ");
    814     int end_option;
    815     ASSERT_EQ(1, scanf("%i", &end_option));
    816     newcall = (end_option == 1);
    817     // Call loop
    818   }
    819   for (int i = 0; i < kMaxNumChannels; ++i) {
    820     delete voice_channel_transports[i];
    821     voice_channel_transports[i] = NULL;
    822   }
    823 
    824   printf("Delete channels \n");
    825   res = base1->DeleteChannel(chan);
    826   VALIDATE;
    827 
    828   for (int i = 0; i < kMaxNumChannels; ++i) {
    829     channels[i] = base1->DeleteChannel(channels[i]);
    830     VALIDATE;
    831   }
    832 }
    833