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
44 DEFINE_bool(use_log_file, false,
45 "Output logs to a file; by default they will be printed to stderr.");
46
47 using namespace webrtc;
48 using 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
56 VoiceEngine* m_voe = NULL;
57 VoEBase* base1 = NULL;
58 VoECodec* codec = NULL;
59 VoEVolumeControl* volume = NULL;
60 VoEDtmf* dtmf = NULL;
61 VoERTP_RTCP* rtp_rtcp = NULL;
62 VoEAudioProcessing* apm = NULL;
63 VoENetwork* netw = NULL;
64 VoEFile* file = NULL;
65 VoEVideoSync* vsync = NULL;
66 VoEHardware* hardware = NULL;
67 VoEExternalMedia* xmedia = NULL;
68 VoENetEqStats* neteqst = NULL;
69
70 void RunTest(std::string out_path);
71
72 class MyObserver : public VoiceEngineObserver {
73 public:
74 virtual void CallbackOnError(int channel, int err_code);
75 };
76
CallbackOnError(int channel,int err_code)77 void 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
SetStereoIfOpus(bool use_stereo,CodecInst * codec_params)102 void 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
PrintCodecs(bool opus_stereo)111 void 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
main(int argc,char ** argv)122 int 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
RunTest(std::string out_path)225 void 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