blob: bad71abf51bf64b2551246330f4318d9233f7a0e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 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
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +000011#include "TwoWayCommunication.h"
12
niklase@google.com470e71d2011-07-07 08:21:25 +000013#include <cctype>
14#include <stdio.h>
15#include <string.h>
16
17#ifdef WIN32
18#include <Windows.h>
19#endif
20
niklase@google.com470e71d2011-07-07 08:21:25 +000021#include "common_types.h"
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +000022#include "engine_configurations.h"
23#include "gtest/gtest.h"
24#include "PCMFile.h"
25#include "trace.h"
26#include "utility.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000027
28using namespace webrtc;
29
30#define MAX_FILE_NAME_LENGTH_BYTE 500
31
32TwoWayCommunication::TwoWayCommunication(int testMode)
33{
34 _testMode = testMode;
35}
36
37TwoWayCommunication::~TwoWayCommunication()
38{
39 AudioCodingModule::Destroy(_acmA);
40 AudioCodingModule::Destroy(_acmB);
41
42 AudioCodingModule::Destroy(_acmRefA);
43 AudioCodingModule::Destroy(_acmRefB);
44
45 delete _channel_A2B;
46 delete _channel_B2A;
47
48 delete _channelRef_A2B;
49 delete _channelRef_B2A;
50#ifdef WEBRTC_DTMF_DETECTION
51 if(_dtmfDetectorA != NULL)
52 {
53 delete _dtmfDetectorA;
54 }
55 if(_dtmfDetectorB != NULL)
56 {
57 delete _dtmfDetectorB;
58 }
59#endif
60 _inFileA.Close();
61 _inFileB.Close();
62 _outFileA.Close();
63 _outFileB.Close();
64 _outFileRefA.Close();
65 _outFileRefB.Close();
66}
67
68
69WebRtc_UWord8
70TwoWayCommunication::ChooseCodec(WebRtc_UWord8* codecID_A, WebRtc_UWord8* codecID_B)
71{
72 AudioCodingModule* tmpACM = AudioCodingModule::Create(0);
73 WebRtc_UWord8 noCodec = tmpACM->NumberOfCodecs();
74 CodecInst codecInst;
75 printf("List of Supported Codecs\n");
76 printf("========================\n");
77 for(WebRtc_UWord8 codecCntr = 0; codecCntr < noCodec; codecCntr++)
78 {
79 tmpACM->Codec(codecCntr, codecInst);
80 printf("%d- %s\n", codecCntr, codecInst.plname);
81 }
82 printf("\nChoose a send codec for side A [0]: ");
83 char myStr[15] = "";
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +000084 EXPECT_TRUE(fgets(myStr, 10, stdin) != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +000085 *codecID_A = (WebRtc_UWord8)atoi(myStr);
86
87 printf("\nChoose a send codec for side B [0]: ");
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +000088 EXPECT_TRUE(fgets(myStr, 10, stdin) != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +000089 *codecID_B = (WebRtc_UWord8)atoi(myStr);
90
91 AudioCodingModule::Destroy(tmpACM);
92 printf("\n");
93 return 0;
94}
95
96WebRtc_Word16
97TwoWayCommunication::ChooseFile(char* fileName, WebRtc_Word16 maxLen, WebRtc_UWord16* frequencyHz)
98{
99 WebRtc_Word8 tmpName[MAX_FILE_NAME_LENGTH_BYTE];
100 //strcpy(_fileName, "in.pcm");
101 //printf("\n\nPlease enter the input file: ");
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +0000102 EXPECT_TRUE(fgets(tmpName, MAX_FILE_NAME_LENGTH_BYTE, stdin) != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000103 tmpName[MAX_FILE_NAME_LENGTH_BYTE-1] = '\0';
104 WebRtc_Word16 n = 0;
105
106 // removing leading spaces
107 while((isspace(tmpName[n]) || iscntrl(tmpName[n])) &&
108 (tmpName[n] != 0) &&
109 (n < MAX_FILE_NAME_LENGTH_BYTE))
110 {
111 n++;
112 }
113 if(n > 0)
114 {
115 memmove(tmpName, &tmpName[n], MAX_FILE_NAME_LENGTH_BYTE - n);
116 }
117
118 //removing trailing spaces
119 n = (WebRtc_Word16)(strlen(tmpName) - 1);
120 if(n >= 0)
121 {
122 while((isspace(tmpName[n]) || iscntrl(tmpName[n])) &&
123 (n >= 0))
124 {
125 n--;
126 }
127 }
128 if(n >= 0)
129 {
130 tmpName[n + 1] = '\0';
131 }
132
133 WebRtc_Word16 len = (WebRtc_Word16)strlen(tmpName);
134 if(len > maxLen)
135 {
136 return -1;
137 }
138 if(len > 0)
139 {
140 strncpy(fileName, tmpName, len+1);
141 }
142 printf("Enter the sampling frequency (in Hz) of the above file [%u]: ", *frequencyHz);
kjellander@webrtc.org543c3ea2011-11-23 12:20:35 +0000143 EXPECT_TRUE(fgets(tmpName, 6, stdin) != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000144 WebRtc_UWord16 tmpFreq = (WebRtc_UWord16)atoi(tmpName);
145 if(tmpFreq > 0)
146 {
147 *frequencyHz = tmpFreq;
148 }
149 return 0;
150}
151
152WebRtc_Word16 TwoWayCommunication::SetUp()
153{
154 _acmA = AudioCodingModule::Create(1);
155 _acmB = AudioCodingModule::Create(2);
156
157 _acmRefA = AudioCodingModule::Create(3);
158 _acmRefB = AudioCodingModule::Create(4);
159
160 WebRtc_UWord8 codecID_A;
161 WebRtc_UWord8 codecID_B;
162
163 ChooseCodec(&codecID_A, &codecID_B);
164 CodecInst codecInst_A;
165 CodecInst codecInst_B;
166 CodecInst dummyCodec;
167 _acmA->Codec(codecID_A, codecInst_A);
168 _acmB->Codec(codecID_B, codecInst_B);
169
170 _acmA->Codec(6, dummyCodec);
171
172 //--- Set A codecs
173 CHECK_ERROR(_acmA->RegisterSendCodec(codecInst_A));
174 CHECK_ERROR(_acmA->RegisterReceiveCodec(codecInst_B));
175#ifdef WEBRTC_DTMF_DETECTION
176 _dtmfDetectorA = new(DTMFDetector);
177 CHECK_ERROR(_acmA->RegisterIncomingMessagesCallback(_dtmfDetectorA, ACMUSA));
178#endif
179 //--- Set ref-A codecs
180 CHECK_ERROR(_acmRefA->RegisterSendCodec(codecInst_A));
181 CHECK_ERROR(_acmRefA->RegisterReceiveCodec(codecInst_B));
182
183 //--- Set B codecs
184 CHECK_ERROR(_acmB->RegisterSendCodec(codecInst_B));
185 CHECK_ERROR(_acmB->RegisterReceiveCodec(codecInst_A));
186#ifdef WEBRTC_DTMF_DETECTION
187 _dtmfDetectorB = new(DTMFDetector);
188 CHECK_ERROR(_acmB->RegisterIncomingMessagesCallback(_dtmfDetectorB, ACMUSA));
189#endif
190
191 //--- Set ref-B codecs
192 CHECK_ERROR(_acmRefB->RegisterSendCodec(codecInst_B));
193 CHECK_ERROR(_acmRefB->RegisterReceiveCodec(codecInst_A));
194
195 char fileName[500];
196 char refFileName[500];
197 WebRtc_UWord16 frequencyHz;
198
199 //--- Input A
tlegrand@google.com3675f9b2011-07-08 06:43:34 +0000200 strcpy(fileName, "./test/data/audio_coding/testfile32kHz.pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000201 frequencyHz = 32000;
202 printf("Enter input file at side A [%s]: ", fileName);
203 ChooseFile(fileName, 499, &frequencyHz);
204
205
206 _inFileA.Open(fileName, frequencyHz, "rb");
207
208 //--- Output A
209 strcpy(fileName, "outA.pcm");
210 frequencyHz = 16000;
211 printf("Enter output file at side A [%s]: ", fileName);
212 ChooseFile(fileName, 499, &frequencyHz);
213 _outFileA.Open(fileName, frequencyHz, "wb");
214 strcpy(refFileName, "ref_");
215 strcat(refFileName, fileName);
216 _outFileRefA.Open(refFileName, frequencyHz, "wb");
217
218 //--- Input B
tlegrand@google.com3675f9b2011-07-08 06:43:34 +0000219 strcpy(fileName, "./test/data/audio_coding/testfile32kHz.pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000220 frequencyHz = 32000;
221 printf("\n\nEnter input file at side B [%s]: ", fileName);
222 ChooseFile(fileName, 499, &frequencyHz);
223 _inFileB.Open(fileName, frequencyHz, "rb");
224
225 //--- Output B
226 strcpy(fileName, "outB.pcm");
227 frequencyHz = 16000;
228 printf("Enter output file at side B [%s]: ", fileName);
229 ChooseFile(fileName, 499, &frequencyHz);
230 _outFileB.Open(fileName, frequencyHz, "wb");
231 strcpy(refFileName, "ref_");
232 strcat(refFileName, fileName);
233 _outFileRefB.Open(refFileName, frequencyHz, "wb");
234
235 //--- Set A-to-B channel
236 _channel_A2B = new Channel;
237 _acmA->RegisterTransportCallback(_channel_A2B);
238 _channel_A2B->RegisterReceiverACM(_acmB);
239 //--- Do the same for the reference
240 _channelRef_A2B = new Channel;
241 _acmRefA->RegisterTransportCallback(_channelRef_A2B);
242 _channelRef_A2B->RegisterReceiverACM(_acmRefB);
243
244 //--- Set B-to-A channel
245 _channel_B2A = new Channel;
246 _acmB->RegisterTransportCallback(_channel_B2A);
247 _channel_B2A->RegisterReceiverACM(_acmA);
248 //--- Do the same for reference
249 _channelRef_B2A = new Channel;
250 _acmRefB->RegisterTransportCallback(_channelRef_B2A);
251 _channelRef_B2A->RegisterReceiverACM(_acmRefA);
252
253 // The clicks will be more obvious when we
254 // are in FAX mode.
255 _acmB->SetPlayoutMode(fax);
256 _acmRefB->SetPlayoutMode(fax);
257
258 return 0;
259}
260
261WebRtc_Word16 TwoWayCommunication::SetUpAutotest()
262{
263 _acmA = AudioCodingModule::Create(1);
264 _acmB = AudioCodingModule::Create(2);
265
266 _acmRefA = AudioCodingModule::Create(3);
267 _acmRefB = AudioCodingModule::Create(4);
268
269 CodecInst codecInst_A;
270 CodecInst codecInst_B;
271 CodecInst dummyCodec;
272
273 _acmA->Codec("ISAC", codecInst_A, 16000);
274 _acmB->Codec("L16", codecInst_B, 8000);
275 _acmA->Codec(6, dummyCodec);
276
277 //--- Set A codecs
278 CHECK_ERROR(_acmA->RegisterSendCodec(codecInst_A));
279 CHECK_ERROR(_acmA->RegisterReceiveCodec(codecInst_B));
280#ifdef WEBRTC_DTMF_DETECTION
281 _dtmfDetectorA = new(DTMFDetector);
282 CHECK_ERROR(_acmA->RegisterIncomingMessagesCallback(_dtmfDetectorA, ACMUSA));
283#endif
284
285 //--- Set ref-A codecs
286 CHECK_ERROR(_acmRefA->RegisterSendCodec(codecInst_A));
287 CHECK_ERROR(_acmRefA->RegisterReceiveCodec(codecInst_B));
288
289 //--- Set B codecs
290 CHECK_ERROR(_acmB->RegisterSendCodec(codecInst_B));
291 CHECK_ERROR(_acmB->RegisterReceiveCodec(codecInst_A));
292#ifdef WEBRTC_DTMF_DETECTION
293 _dtmfDetectorB = new(DTMFDetector);
294 CHECK_ERROR(_acmB->RegisterIncomingMessagesCallback(_dtmfDetectorB, ACMUSA));
295#endif
296
297 //--- Set ref-B codecs
298 CHECK_ERROR(_acmRefB->RegisterSendCodec(codecInst_B));
299 CHECK_ERROR(_acmRefB->RegisterReceiveCodec(codecInst_A));
300
301 char fileName[500];
302 char refFileName[500];
303 WebRtc_UWord16 frequencyHz;
304
305
306 //--- Input A
tlegrand@google.com3675f9b2011-07-08 06:43:34 +0000307 strcpy(fileName, "./test/data/audio_coding/testfile32kHz.pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000308 frequencyHz = 16000;
309 _inFileA.Open(fileName, frequencyHz, "rb");
310
311 //--- Output A
tlegrand@google.com3675f9b2011-07-08 06:43:34 +0000312 strcpy(fileName, "./src/modules/audio_coding/main/test/outAutotestA.pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000313 frequencyHz = 16000;
314 _outFileA.Open(fileName, frequencyHz, "wb");
tlegrand@google.com3675f9b2011-07-08 06:43:34 +0000315 strcpy(refFileName, "./src/modules/audio_coding/main/test/ref_outAutotestA.pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000316 _outFileRefA.Open(refFileName, frequencyHz, "wb");
317
318 //--- Input B
tlegrand@google.com3675f9b2011-07-08 06:43:34 +0000319 strcpy(fileName, "./test/data/audio_coding/testfile32kHz.pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000320 frequencyHz = 16000;
321 _inFileB.Open(fileName, frequencyHz, "rb");
322
323 //--- Output B
tlegrand@google.com3675f9b2011-07-08 06:43:34 +0000324 strcpy(fileName, "./src/modules/audio_coding/main/test/outAutotestB.pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000325 frequencyHz = 16000;
326 _outFileB.Open(fileName, frequencyHz, "wb");
tlegrand@google.com3675f9b2011-07-08 06:43:34 +0000327 strcpy(refFileName, "./src/modules/audio_coding/main/test/ref_outAutotestB.pcm");
niklase@google.com470e71d2011-07-07 08:21:25 +0000328 _outFileRefB.Open(refFileName, frequencyHz, "wb");
329
330 //--- Set A-to-B channel
331 _channel_A2B = new Channel;
332 _acmA->RegisterTransportCallback(_channel_A2B);
333 _channel_A2B->RegisterReceiverACM(_acmB);
334 //--- Do the same for the reference
335 _channelRef_A2B = new Channel;
336 _acmRefA->RegisterTransportCallback(_channelRef_A2B);
337 _channelRef_A2B->RegisterReceiverACM(_acmRefB);
338
339 //--- Set B-to-A channel
340 _channel_B2A = new Channel;
341 _acmB->RegisterTransportCallback(_channel_B2A);
342 _channel_B2A->RegisterReceiverACM(_acmA);
343 //--- Do the same for reference
344 _channelRef_B2A = new Channel;
345 _acmRefB->RegisterTransportCallback(_channelRef_B2A);
346 _channelRef_B2A->RegisterReceiverACM(_acmRefA);
347
348 // The clicks will be more obvious when we
349 // are in FAX mode.
350 _acmB->SetPlayoutMode(fax);
351 _acmRefB->SetPlayoutMode(fax);
352
353 return 0;
354}
355
356void
357TwoWayCommunication::Perform()
358{
359 if(_testMode == 0)
360 {
361 printf("Running TwoWayCommunication Test");
362 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, "---------- TwoWayCommunication ----------");
363 SetUpAutotest();
364 }
365 else
366 {
367 SetUp();
368 }
369 unsigned int msecPassed = 0;
370 unsigned int secPassed = 0;
371
372 WebRtc_Word32 outFreqHzA = _outFileA.SamplingFrequency();
373 WebRtc_Word32 outFreqHzB = _outFileB.SamplingFrequency();
374
375 AudioFrame audioFrame;
376
377 CodecInst codecInst_B;
378 CodecInst dummy;
379
380 _acmB->SendCodec(codecInst_B);
381
382 if(_testMode != 0)
383 {
384 printf("\n");
385 printf("sec:msec A B\n");
386 printf("-------- ----- -----\n");
387 }
388
389 while(!_inFileA.EndOfFile() && !_inFileB.EndOfFile())
390 {
391 _inFileA.Read10MsData(audioFrame);
392 _acmA->Add10MsData(audioFrame);
393 _acmRefA->Add10MsData(audioFrame);
394
395 _inFileB.Read10MsData(audioFrame);
396 _acmB->Add10MsData(audioFrame);
397 _acmRefB->Add10MsData(audioFrame);
398
399
400 _acmA->Process();
401 _acmB->Process();
402 _acmRefA->Process();
403 _acmRefB->Process();
404
405 _acmA->PlayoutData10Ms(outFreqHzA, audioFrame);
406 _outFileA.Write10MsData(audioFrame);
407
408 _acmRefA->PlayoutData10Ms(outFreqHzA, audioFrame);
409 _outFileRefA.Write10MsData(audioFrame);
410
411 _acmB->PlayoutData10Ms(outFreqHzB, audioFrame);
412 _outFileB.Write10MsData(audioFrame);
413
414 _acmRefB->PlayoutData10Ms(outFreqHzB, audioFrame);
415 _outFileRefB.Write10MsData(audioFrame);
416
417 msecPassed += 10;
418 if(msecPassed >= 1000)
419 {
420 msecPassed = 0;
421 secPassed++;
422 }
423 if(((secPassed%5) == 4) && (msecPassed == 0))
424 {
425 if(_testMode != 0)
426 {
427 printf("%3u:%3u ", secPassed, msecPassed);
428 }
429 _acmA->ResetEncoder();
430 if(_testMode == 0)
431 {
432 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, "---------- Errors epected");
433 printf(".");
434 }
435 else
436 {
437 printf("Reset Encoder (click in side B) ");
438 printf("Initialize Sender (no audio in side A)\n");
439 }
440 CHECK_ERROR(_acmB->InitializeSender());
441 }
442 if(((secPassed%5) == 4) && (msecPassed >= 990))
443 {
444 if(_testMode == 0)
445 {
446 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, "----- END: Errors epected");
447 printf(".");
448 }
449 else
450 {
451 printf("%3u:%3u ", secPassed, msecPassed);
452 printf(" ");
453 printf("Register Send Codec (audio back in side A)\n");
454 }
455 CHECK_ERROR(_acmB->RegisterSendCodec(codecInst_B));
456 CHECK_ERROR(_acmB->SendCodec(dummy));
457 }
458 if(((secPassed%7) == 6) && (msecPassed == 0))
459 {
460 CHECK_ERROR(_acmB->ResetDecoder());
461 if(_testMode == 0)
462 {
463 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, "---------- Errors epected");
464 printf(".");
465 }
466 else
467 {
468 printf("%3u:%3u ", secPassed, msecPassed);
469 printf("Initialize Receiver (no audio in side A) ");
470 printf("Reset Decoder\n");
471 }
472 CHECK_ERROR(_acmA->InitializeReceiver());
473 }
474 if(((secPassed%7) == 6) && (msecPassed >= 990))
475 {
476 if(_testMode == 0)
477 {
478 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, "----- END: Errors epected");
479 printf(".");
480 }
481 else
482 {
483 printf("%3u:%3u ", secPassed, msecPassed);
484 printf("Register Receive Coded (audio back in side A)\n");
485 }
486 CHECK_ERROR(_acmA->RegisterReceiveCodec(codecInst_B));
487 }
488 //Sleep(9);
489 }
490 if(_testMode == 0)
491 {
492 printf("Done!\n");
493 }
494
495#ifdef WEBRTC_DTMF_DETECTION
496 printf("\nDTMF at Side A\n");
497 _dtmfDetectorA->PrintDetectedDigits();
498
499 printf("\nDTMF at Side B\n");
500 _dtmfDetectorB->PrintDetectedDigits();
501#endif
502
503
504}
505