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