| /* |
| * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "TwoWayCommunication.h" |
| |
| #include <cctype> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #ifdef WIN32 |
| #include <Windows.h> |
| #endif |
| |
| #include "common_types.h" |
| #include "engine_configurations.h" |
| #include "gtest/gtest.h" |
| #include "PCMFile.h" |
| #include "trace.h" |
| #include "testsupport/fileutils.h" |
| #include "utility.h" |
| |
| namespace webrtc { |
| |
| #define MAX_FILE_NAME_LENGTH_BYTE 500 |
| |
| TwoWayCommunication::TwoWayCommunication(int testMode) |
| { |
| _testMode = testMode; |
| } |
| |
| TwoWayCommunication::~TwoWayCommunication() |
| { |
| AudioCodingModule::Destroy(_acmA); |
| AudioCodingModule::Destroy(_acmB); |
| |
| AudioCodingModule::Destroy(_acmRefA); |
| AudioCodingModule::Destroy(_acmRefB); |
| |
| delete _channel_A2B; |
| delete _channel_B2A; |
| |
| delete _channelRef_A2B; |
| delete _channelRef_B2A; |
| #ifdef WEBRTC_DTMF_DETECTION |
| if(_dtmfDetectorA != NULL) |
| { |
| delete _dtmfDetectorA; |
| } |
| if(_dtmfDetectorB != NULL) |
| { |
| delete _dtmfDetectorB; |
| } |
| #endif |
| _inFileA.Close(); |
| _inFileB.Close(); |
| _outFileA.Close(); |
| _outFileB.Close(); |
| _outFileRefA.Close(); |
| _outFileRefB.Close(); |
| } |
| |
| |
| WebRtc_UWord8 |
| TwoWayCommunication::ChooseCodec(WebRtc_UWord8* codecID_A, |
| WebRtc_UWord8* codecID_B) |
| { |
| AudioCodingModule* tmpACM = AudioCodingModule::Create(0); |
| WebRtc_UWord8 noCodec = tmpACM->NumberOfCodecs(); |
| CodecInst codecInst; |
| printf("List of Supported Codecs\n"); |
| printf("========================\n"); |
| for(WebRtc_UWord8 codecCntr = 0; codecCntr < noCodec; codecCntr++) |
| { |
| tmpACM->Codec(codecCntr, codecInst); |
| printf("%d- %s\n", codecCntr, codecInst.plname); |
| } |
| printf("\nChoose a send codec for side A [0]: "); |
| char myStr[15] = ""; |
| EXPECT_TRUE(fgets(myStr, 10, stdin) != NULL); |
| *codecID_A = (WebRtc_UWord8)atoi(myStr); |
| |
| printf("\nChoose a send codec for side B [0]: "); |
| EXPECT_TRUE(fgets(myStr, 10, stdin) != NULL); |
| *codecID_B = (WebRtc_UWord8)atoi(myStr); |
| |
| AudioCodingModule::Destroy(tmpACM); |
| printf("\n"); |
| return 0; |
| } |
| |
| WebRtc_Word16 |
| TwoWayCommunication::ChooseFile(char* fileName, WebRtc_Word16 maxLen, |
| WebRtc_UWord16* frequencyHz) |
| { |
| WebRtc_Word8 tmpName[MAX_FILE_NAME_LENGTH_BYTE]; |
| //strcpy(_fileName, "in.pcm"); |
| //printf("\n\nPlease enter the input file: "); |
| EXPECT_TRUE(fgets(tmpName, MAX_FILE_NAME_LENGTH_BYTE, stdin) != NULL); |
| tmpName[MAX_FILE_NAME_LENGTH_BYTE-1] = '\0'; |
| WebRtc_Word16 n = 0; |
| |
| // removing leading spaces |
| while((isspace(tmpName[n]) || iscntrl(tmpName[n])) && |
| (tmpName[n] != 0) && |
| (n < MAX_FILE_NAME_LENGTH_BYTE)) |
| { |
| n++; |
| } |
| if(n > 0) |
| { |
| memmove(tmpName, &tmpName[n], MAX_FILE_NAME_LENGTH_BYTE - n); |
| } |
| |
| //removing trailing spaces |
| n = (WebRtc_Word16)(strlen(tmpName) - 1); |
| if(n >= 0) |
| { |
| while((isspace(tmpName[n]) || iscntrl(tmpName[n])) && |
| (n >= 0)) |
| { |
| n--; |
| } |
| } |
| if(n >= 0) |
| { |
| tmpName[n + 1] = '\0'; |
| } |
| |
| WebRtc_Word16 len = (WebRtc_Word16)strlen(tmpName); |
| if(len > maxLen) |
| { |
| return -1; |
| } |
| if(len > 0) |
| { |
| strncpy(fileName, tmpName, len+1); |
| } |
| printf("Enter the sampling frequency (in Hz) of the above file [%u]: ", |
| *frequencyHz); |
| EXPECT_TRUE(fgets(tmpName, 6, stdin) != NULL); |
| WebRtc_UWord16 tmpFreq = (WebRtc_UWord16)atoi(tmpName); |
| if(tmpFreq > 0) |
| { |
| *frequencyHz = tmpFreq; |
| } |
| return 0; |
| } |
| |
| WebRtc_Word16 TwoWayCommunication::SetUp() |
| { |
| _acmA = AudioCodingModule::Create(1); |
| _acmB = AudioCodingModule::Create(2); |
| |
| _acmRefA = AudioCodingModule::Create(3); |
| _acmRefB = AudioCodingModule::Create(4); |
| |
| WebRtc_UWord8 codecID_A; |
| WebRtc_UWord8 codecID_B; |
| |
| ChooseCodec(&codecID_A, &codecID_B); |
| CodecInst codecInst_A; |
| CodecInst codecInst_B; |
| CodecInst dummyCodec; |
| _acmA->Codec(codecID_A, codecInst_A); |
| _acmB->Codec(codecID_B, codecInst_B); |
| |
| _acmA->Codec(6, dummyCodec); |
| |
| //--- Set A codecs |
| CHECK_ERROR(_acmA->RegisterSendCodec(codecInst_A)); |
| CHECK_ERROR(_acmA->RegisterReceiveCodec(codecInst_B)); |
| #ifdef WEBRTC_DTMF_DETECTION |
| _dtmfDetectorA = new(DTMFDetector); |
| CHECK_ERROR(_acmA->RegisterIncomingMessagesCallback(_dtmfDetectorA, |
| ACMUSA)); |
| #endif |
| //--- Set ref-A codecs |
| CHECK_ERROR(_acmRefA->RegisterSendCodec(codecInst_A)); |
| CHECK_ERROR(_acmRefA->RegisterReceiveCodec(codecInst_B)); |
| |
| //--- Set B codecs |
| CHECK_ERROR(_acmB->RegisterSendCodec(codecInst_B)); |
| CHECK_ERROR(_acmB->RegisterReceiveCodec(codecInst_A)); |
| #ifdef WEBRTC_DTMF_DETECTION |
| _dtmfDetectorB = new(DTMFDetector); |
| CHECK_ERROR(_acmB->RegisterIncomingMessagesCallback(_dtmfDetectorB, |
| ACMUSA)); |
| #endif |
| |
| //--- Set ref-B codecs |
| CHECK_ERROR(_acmRefB->RegisterSendCodec(codecInst_B)); |
| CHECK_ERROR(_acmRefB->RegisterReceiveCodec(codecInst_A)); |
| |
| char fileName[500]; |
| char refFileName[500]; |
| WebRtc_UWord16 frequencyHz; |
| |
| //--- Input A |
| strcpy(fileName, "./test/data/audio_coding/testfile32kHz.pcm"); |
| frequencyHz = 32000; |
| printf("Enter input file at side A [%s]: ", fileName); |
| ChooseFile(fileName, 499, &frequencyHz); |
| |
| |
| _inFileA.Open(fileName, frequencyHz, "rb"); |
| |
| //--- Output A |
| std::string outputFileA = webrtc::test::OutputPath() + "outA.pcm"; |
| strcpy(fileName, outputFileA.c_str()); |
| frequencyHz = 16000; |
| printf("Enter output file at side A [%s]: ", fileName); |
| ChooseFile(fileName, 499, &frequencyHz); |
| _outFileA.Open(fileName, frequencyHz, "wb"); |
| strcpy(refFileName, "ref_"); |
| strcat(refFileName, fileName); |
| _outFileRefA.Open(refFileName, frequencyHz, "wb"); |
| |
| //--- Input B |
| strcpy(fileName, "./test/data/audio_coding/testfile32kHz.pcm"); |
| frequencyHz = 32000; |
| printf("\n\nEnter input file at side B [%s]: ", fileName); |
| ChooseFile(fileName, 499, &frequencyHz); |
| _inFileB.Open(fileName, frequencyHz, "rb"); |
| |
| //--- Output B |
| std::string outputFileB = webrtc::test::OutputPath() + "outB.pcm"; |
| strcpy(fileName, outputFileB.c_str()); |
| frequencyHz = 16000; |
| printf("Enter output file at side B [%s]: ", fileName); |
| ChooseFile(fileName, 499, &frequencyHz); |
| _outFileB.Open(fileName, frequencyHz, "wb"); |
| strcpy(refFileName, "ref_"); |
| strcat(refFileName, fileName); |
| _outFileRefB.Open(refFileName, frequencyHz, "wb"); |
| |
| //--- Set A-to-B channel |
| _channel_A2B = new Channel; |
| _acmA->RegisterTransportCallback(_channel_A2B); |
| _channel_A2B->RegisterReceiverACM(_acmB); |
| //--- Do the same for the reference |
| _channelRef_A2B = new Channel; |
| _acmRefA->RegisterTransportCallback(_channelRef_A2B); |
| _channelRef_A2B->RegisterReceiverACM(_acmRefB); |
| |
| //--- Set B-to-A channel |
| _channel_B2A = new Channel; |
| _acmB->RegisterTransportCallback(_channel_B2A); |
| _channel_B2A->RegisterReceiverACM(_acmA); |
| //--- Do the same for reference |
| _channelRef_B2A = new Channel; |
| _acmRefB->RegisterTransportCallback(_channelRef_B2A); |
| _channelRef_B2A->RegisterReceiverACM(_acmRefA); |
| |
| // The clicks will be more obvious when we |
| // are in FAX mode. |
| _acmB->SetPlayoutMode(fax); |
| _acmRefB->SetPlayoutMode(fax); |
| |
| return 0; |
| } |
| |
| WebRtc_Word16 TwoWayCommunication::SetUpAutotest() |
| { |
| _acmA = AudioCodingModule::Create(1); |
| _acmB = AudioCodingModule::Create(2); |
| |
| _acmRefA = AudioCodingModule::Create(3); |
| _acmRefB = AudioCodingModule::Create(4); |
| |
| CodecInst codecInst_A; |
| CodecInst codecInst_B; |
| CodecInst dummyCodec; |
| |
| _acmA->Codec("ISAC", codecInst_A, 16000); |
| _acmB->Codec("L16", codecInst_B, 8000); |
| _acmA->Codec(6, dummyCodec); |
| |
| //--- Set A codecs |
| CHECK_ERROR(_acmA->RegisterSendCodec(codecInst_A)); |
| CHECK_ERROR(_acmA->RegisterReceiveCodec(codecInst_B)); |
| #ifdef WEBRTC_DTMF_DETECTION |
| _dtmfDetectorA = new(DTMFDetector); |
| CHECK_ERROR(_acmA->RegisterIncomingMessagesCallback(_dtmfDetectorA, |
| ACMUSA)); |
| #endif |
| |
| //--- Set ref-A codecs |
| CHECK_ERROR(_acmRefA->RegisterSendCodec(codecInst_A)); |
| CHECK_ERROR(_acmRefA->RegisterReceiveCodec(codecInst_B)); |
| |
| //--- Set B codecs |
| CHECK_ERROR(_acmB->RegisterSendCodec(codecInst_B)); |
| CHECK_ERROR(_acmB->RegisterReceiveCodec(codecInst_A)); |
| #ifdef WEBRTC_DTMF_DETECTION |
| _dtmfDetectorB = new(DTMFDetector); |
| CHECK_ERROR(_acmB->RegisterIncomingMessagesCallback(_dtmfDetectorB, |
| ACMUSA)); |
| #endif |
| |
| //--- Set ref-B codecs |
| CHECK_ERROR(_acmRefB->RegisterSendCodec(codecInst_B)); |
| CHECK_ERROR(_acmRefB->RegisterReceiveCodec(codecInst_A)); |
| |
| char fileName[500]; |
| char refFileName[500]; |
| WebRtc_UWord16 frequencyHz; |
| |
| |
| //--- Input A |
| strcpy(fileName, "./test/data/audio_coding/testfile32kHz.pcm"); |
| frequencyHz = 16000; |
| _inFileA.Open(fileName, frequencyHz, "rb"); |
| |
| //--- Output A |
| std::string outputFileA = webrtc::test::OutputPath() + "outAutotestA.pcm"; |
| strcpy(fileName, outputFileA.c_str()); |
| frequencyHz = 16000; |
| _outFileA.Open(fileName, frequencyHz, "wb"); |
| std::string outputRefFileA = webrtc::test::OutputPath() + "ref_outAutotestA.pcm"; |
| strcpy(refFileName, outputRefFileA.c_str()); |
| _outFileRefA.Open(refFileName, frequencyHz, "wb"); |
| |
| //--- Input B |
| strcpy(fileName, "./test/data/audio_coding/testfile32kHz.pcm"); |
| frequencyHz = 16000; |
| _inFileB.Open(fileName, frequencyHz, "rb"); |
| |
| //--- Output B |
| std::string outputFileB = webrtc::test::OutputPath() + "outAutotestB.pcm"; |
| strcpy(fileName, outputFileB.c_str()); |
| frequencyHz = 16000; |
| _outFileB.Open(fileName, frequencyHz, "wb"); |
| std::string outputRefFileB = webrtc::test::OutputPath() + "ref_outAutotestB.pcm"; |
| strcpy(refFileName, outputRefFileB.c_str()); |
| _outFileRefB.Open(refFileName, frequencyHz, "wb"); |
| |
| //--- Set A-to-B channel |
| _channel_A2B = new Channel; |
| _acmA->RegisterTransportCallback(_channel_A2B); |
| _channel_A2B->RegisterReceiverACM(_acmB); |
| //--- Do the same for the reference |
| _channelRef_A2B = new Channel; |
| _acmRefA->RegisterTransportCallback(_channelRef_A2B); |
| _channelRef_A2B->RegisterReceiverACM(_acmRefB); |
| |
| //--- Set B-to-A channel |
| _channel_B2A = new Channel; |
| _acmB->RegisterTransportCallback(_channel_B2A); |
| _channel_B2A->RegisterReceiverACM(_acmA); |
| //--- Do the same for reference |
| _channelRef_B2A = new Channel; |
| _acmRefB->RegisterTransportCallback(_channelRef_B2A); |
| _channelRef_B2A->RegisterReceiverACM(_acmRefA); |
| |
| // The clicks will be more obvious when we |
| // are in FAX mode. |
| _acmB->SetPlayoutMode(fax); |
| _acmRefB->SetPlayoutMode(fax); |
| |
| return 0; |
| } |
| |
| void |
| TwoWayCommunication::Perform() |
| { |
| if(_testMode == 0) |
| { |
| printf("Running TwoWayCommunication Test"); |
| WEBRTC_TRACE(kTraceStateInfo, kTraceAudioCoding, -1, |
| "---------- TwoWayCommunication ----------"); |
| SetUpAutotest(); |
| } |
| else |
| { |
| SetUp(); |
| } |
| unsigned int msecPassed = 0; |
| unsigned int secPassed = 0; |
| |
| WebRtc_Word32 outFreqHzA = _outFileA.SamplingFrequency(); |
| WebRtc_Word32 outFreqHzB = _outFileB.SamplingFrequency(); |
| |
| AudioFrame audioFrame; |
| |
| CodecInst codecInst_B; |
| CodecInst dummy; |
| |
| _acmB->SendCodec(codecInst_B); |
| |
| if(_testMode != 0) |
| { |
| printf("\n"); |
| printf("sec:msec A B\n"); |
| printf("-------- ----- -----\n"); |
| } |
| |
| while(!_inFileA.EndOfFile() && !_inFileB.EndOfFile()) |
| { |
| _inFileA.Read10MsData(audioFrame); |
| _acmA->Add10MsData(audioFrame); |
| _acmRefA->Add10MsData(audioFrame); |
| |
| _inFileB.Read10MsData(audioFrame); |
| _acmB->Add10MsData(audioFrame); |
| _acmRefB->Add10MsData(audioFrame); |
| |
| |
| _acmA->Process(); |
| _acmB->Process(); |
| _acmRefA->Process(); |
| _acmRefB->Process(); |
| |
| _acmA->PlayoutData10Ms(outFreqHzA, audioFrame); |
| _outFileA.Write10MsData(audioFrame); |
| |
| _acmRefA->PlayoutData10Ms(outFreqHzA, audioFrame); |
| _outFileRefA.Write10MsData(audioFrame); |
| |
| _acmB->PlayoutData10Ms(outFreqHzB, audioFrame); |
| _outFileB.Write10MsData(audioFrame); |
| |
| _acmRefB->PlayoutData10Ms(outFreqHzB, audioFrame); |
| _outFileRefB.Write10MsData(audioFrame); |
| |
| msecPassed += 10; |
| if(msecPassed >= 1000) |
| { |
| msecPassed = 0; |
| secPassed++; |
| } |
| if(((secPassed%5) == 4) && (msecPassed == 0)) |
| { |
| if(_testMode != 0) |
| { |
| printf("%3u:%3u ", secPassed, msecPassed); |
| } |
| _acmA->ResetEncoder(); |
| if(_testMode == 0) |
| { |
| WEBRTC_TRACE(kTraceStateInfo, kTraceAudioCoding, -1, |
| "---------- Errors epected"); |
| printf("."); |
| } |
| else |
| { |
| printf("Reset Encoder (click in side B) "); |
| printf("Initialize Sender (no audio in side A)\n"); |
| } |
| CHECK_ERROR(_acmB->InitializeSender()); |
| } |
| if(((secPassed%5) == 4) && (msecPassed >= 990)) |
| { |
| if(_testMode == 0) |
| { |
| WEBRTC_TRACE(kTraceStateInfo, kTraceAudioCoding, -1, |
| "----- END: Errors epected"); |
| printf("."); |
| } |
| else |
| { |
| printf("%3u:%3u ", secPassed, msecPassed); |
| printf(" "); |
| printf("Register Send Codec (audio back in side A)\n"); |
| } |
| CHECK_ERROR(_acmB->RegisterSendCodec(codecInst_B)); |
| CHECK_ERROR(_acmB->SendCodec(dummy)); |
| } |
| if(((secPassed%7) == 6) && (msecPassed == 0)) |
| { |
| CHECK_ERROR(_acmB->ResetDecoder()); |
| if(_testMode == 0) |
| { |
| WEBRTC_TRACE(kTraceStateInfo, kTraceAudioCoding, -1, |
| "---------- Errors epected"); |
| printf("."); |
| } |
| else |
| { |
| printf("%3u:%3u ", secPassed, msecPassed); |
| printf("Initialize Receiver (no audio in side A) "); |
| printf("Reset Decoder\n"); |
| } |
| CHECK_ERROR(_acmA->InitializeReceiver()); |
| } |
| if(((secPassed%7) == 6) && (msecPassed >= 990)) |
| { |
| if(_testMode == 0) |
| { |
| WEBRTC_TRACE(kTraceStateInfo, kTraceAudioCoding, -1, |
| "----- END: Errors epected"); |
| printf("."); |
| } |
| else |
| { |
| printf("%3u:%3u ", secPassed, msecPassed); |
| printf("Register Receive Coded (audio back in side A)\n"); |
| } |
| CHECK_ERROR(_acmA->RegisterReceiveCodec(codecInst_B)); |
| } |
| //Sleep(9); |
| } |
| if(_testMode == 0) |
| { |
| printf("Done!\n"); |
| } |
| |
| #ifdef WEBRTC_DTMF_DETECTION |
| printf("\nDTMF at Side A\n"); |
| _dtmfDetectorA->PrintDetectedDigits(); |
| |
| printf("\nDTMF at Side B\n"); |
| _dtmfDetectorB->PrintDetectedDigits(); |
| #endif |
| |
| } |
| |
| } // namespace webrtc |