git-svn-id: http://webrtc.googlecode.com/svn/trunk@156 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/src/modules/audio_coding/main/test/ACMTest.cpp b/src/modules/audio_coding/main/test/ACMTest.cpp
new file mode 100644
index 0000000..1bbac0e
--- /dev/null
+++ b/src/modules/audio_coding/main/test/ACMTest.cpp
@@ -0,0 +1,16 @@
+/*
+ * 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 "ACMTest.h"
+
+ACMTest::~ACMTest()
+{
+}
+
diff --git a/src/modules/audio_coding/main/test/ACMTest.h b/src/modules/audio_coding/main/test/ACMTest.h
new file mode 100644
index 0000000..e965671
--- /dev/null
+++ b/src/modules/audio_coding/main/test/ACMTest.h
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#ifndef ACMTEST_H
+#define ACMTEST_H
+
+class ACMTest
+{
+public:
+ virtual ~ACMTest() =0;
+ virtual void Perform() =0;
+};
+
+#endif
diff --git a/src/modules/audio_coding/main/test/APITest.cpp b/src/modules/audio_coding/main/test/APITest.cpp
new file mode 100644
index 0000000..98c3905
--- /dev/null
+++ b/src/modules/audio_coding/main/test/APITest.cpp
@@ -0,0 +1,1602 @@
+/*
+ * 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 <cctype>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <iostream>
+#include <ostream>
+
+#include "APITest.h"
+#include "thread_wrapper.h"
+#include "event_wrapper.h"
+#include "tick_util.h"
+#include "trace.h"
+#include "utility.h"
+#include "common_types.h"
+#include "engine_configurations.h"
+
+#define TEST_DURATION_SEC 600
+
+#define NUMBER_OF_SENDER_TESTS 6
+
+#define MAX_FILE_NAME_LENGTH_BYTE 500
+#define CHECK_THREAD_NULLITY(myThread, S) if(myThread != NULL){unsigned int i; (myThread)->Start(i);}else{throw S; exit(1);}
+
+using namespace webrtc;
+
+void
+APITest::Wait(WebRtc_UWord32 waitLengthMs)
+{
+ if(_randomTest)
+ {
+ return;
+ }
+ else
+ {
+ EventWrapper* myEvent = EventWrapper::Create();
+ myEvent->Wait(waitLengthMs);
+ delete myEvent;
+ return;
+ }
+}
+
+
+
+APITest::APITest():
+_acmA(NULL),
+_acmB(NULL),
+_channel_A2B(NULL),
+_channel_B2A(NULL),
+_writeToFile(true),
+_pullEventA(NULL),
+_pushEventA(NULL),
+_processEventA(NULL),
+_apiEventA(NULL),
+_pullEventB(NULL),
+_pushEventB(NULL),
+_processEventB(NULL),
+_apiEventB(NULL),
+_codecCntrA(0),
+_codecCntrB(0),
+_testCntrA(1),
+_testCntrB(1),
+_thereIsEncoderA(false),
+_thereIsEncoderB(false),
+_thereIsDecoderA(false),
+_thereIsDecoderB(false),
+_sendVADA(false),
+_sendDTXA(false),
+_sendVADModeA(VADNormal),
+_sendVADB(false),
+_sendDTXB(false),
+_sendVADModeB(VADNormal),
+_minDelayA(0),
+_minDelayB(0),
+_dotPositionA(0),
+_dotMoveDirectionA(1),
+_dotPositionB(39),
+_dotMoveDirectionB(-1),
+_dtmfCallback(NULL),
+_vadCallbackA(NULL),
+_vadCallbackB(NULL),
+_apiTestRWLock(*RWLockWrapper::CreateRWLock()),
+_randomTest(false),
+_testNumA(0),
+_testNumB(1)
+{
+ int n;
+ for( n = 0; n < 32; n++)
+ {
+ _payloadUsed[n] = false;
+ }
+
+ for(n = 0; n < 3; n++)
+ {
+ _receiveVADActivityA[n] = 0;
+ _receiveVADActivityB[n] = 0;
+ }
+
+ _movingDot[40] = '\0';
+
+ for(int n = 0; n <40; n++)
+ {
+ _movingDot[n] = ' ';
+ }
+}
+
+APITest::~APITest()
+{
+ DESTROY_ACM(_acmA);
+ DESTROY_ACM(_acmB);
+
+ DELETE_POINTER(_channel_A2B);
+ DELETE_POINTER(_channel_B2A);
+
+ DELETE_POINTER(_pushEventA);
+ DELETE_POINTER(_pullEventA);
+ DELETE_POINTER(_processEventA);
+ DELETE_POINTER(_apiEventA);
+
+ DELETE_POINTER(_pushEventB);
+ DELETE_POINTER(_pullEventB);
+ DELETE_POINTER(_processEventB);
+ DELETE_POINTER(_apiEventB);
+
+ _inFileA.Close();
+ _outFileA.Close();
+
+ _inFileB.Close();
+ _outFileB.Close();
+
+ DELETE_POINTER(_dtmfCallback);
+ DELETE_POINTER(_vadCallbackA);
+ DELETE_POINTER(_vadCallbackB);
+
+ delete &_apiTestRWLock;
+}
+
+
+
+//WebRtc_Word16
+//APITest::SetInFile(char* fileName, WebRtc_UWord16 frequencyHz)
+//{
+// return _inFile.Open(fileName, frequencyHz, "rb");
+//}
+//
+//WebRtc_Word16
+//APITest::SetOutFile(char* fileName, WebRtc_UWord16 frequencyHz)
+//{
+// return _outFile.Open(fileName, frequencyHz, "wb");
+//}
+
+WebRtc_Word16
+APITest::SetUp()
+{
+ _acmA = AudioCodingModule::Create(1);
+ _acmB = AudioCodingModule::Create(2);
+
+ CodecInst dummyCodec;
+ int lastPayloadType = 0;
+
+ WebRtc_Word16 numCodecs = _acmA->NumberOfCodecs();
+ for(WebRtc_UWord8 n = 0; n < numCodecs; n++)
+ {
+ AudioCodingModule::Codec(n, dummyCodec);
+ if((STR_CASE_CMP(dummyCodec.plname, "CN") == 0) &&
+ (dummyCodec.plfreq == 32000))
+ {
+ continue;
+ }
+
+ printf("Register Receive Codec %s ", dummyCodec.plname);
+
+ if((n != 0) && !FixedPayloadTypeCodec(dummyCodec.plname))
+ {
+ // Check registration with an already occupied payload type
+ int currentPayloadType = dummyCodec.pltype;
+ dummyCodec.pltype = 97; //lastPayloadType;
+ CHECK_ERROR(_acmB->RegisterReceiveCodec(dummyCodec));
+ dummyCodec.pltype = currentPayloadType;
+ }
+
+ if((n < numCodecs - 1) && !FixedPayloadTypeCodec(dummyCodec.plname))
+ {
+ // test if re-registration works;
+ CodecInst nextCodec;
+ int currentPayloadType = dummyCodec.pltype;
+ AudioCodingModule::Codec(n + 1, nextCodec);
+ dummyCodec.pltype = nextCodec.pltype;
+ if(!FixedPayloadTypeCodec(nextCodec.plname))
+ {
+ _acmB->RegisterReceiveCodec(dummyCodec);
+ }
+ dummyCodec.pltype = currentPayloadType;
+ }
+
+ if((n < numCodecs - 1) && !FixedPayloadTypeCodec(dummyCodec.plname))
+ {
+ // test if un-registration works;
+ CodecInst nextCodec;
+ int currentPayloadType = dummyCodec.pltype;
+ AudioCodingModule::Codec(n + 1, nextCodec);
+ nextCodec.pltype = dummyCodec.pltype;
+ if(!FixedPayloadTypeCodec(nextCodec.plname))
+ {
+ CHECK_ERROR_MT(_acmA->RegisterReceiveCodec(nextCodec));
+ CHECK_ERROR_MT(_acmA->UnregisterReceiveCodec(nextCodec.pltype));
+ }
+ }
+
+
+ CHECK_ERROR_MT(_acmA->RegisterReceiveCodec(dummyCodec));
+ printf(" side A done!");
+ CHECK_ERROR_MT(_acmB->RegisterReceiveCodec(dummyCodec));
+ printf(" side B done!\n");
+
+ if(!strcmp(dummyCodec.plname, "CN"))
+ {
+ CHECK_ERROR_MT(_acmA->RegisterSendCodec(dummyCodec));
+ CHECK_ERROR_MT(_acmB->RegisterSendCodec(dummyCodec));
+ }
+ lastPayloadType = dummyCodec.pltype;
+ if((lastPayloadType >= 96) && (lastPayloadType <= 127))
+ {
+ _payloadUsed[lastPayloadType - 96] = true;
+ }
+ }
+ _thereIsDecoderA = true;
+ _thereIsDecoderB = true;
+
+ // Register Send Codec
+ AudioCodingModule::Codec((WebRtc_UWord8)_codecCntrA, dummyCodec);
+ CHECK_ERROR_MT(_acmA->RegisterSendCodec(dummyCodec));
+ _thereIsEncoderA = true;
+ //
+ AudioCodingModule::Codec((WebRtc_UWord8)_codecCntrB, dummyCodec);
+ CHECK_ERROR_MT(_acmB->RegisterSendCodec(dummyCodec));
+ _thereIsEncoderB = true;
+
+ char fileName[500];
+ WebRtc_UWord16 frequencyHz;
+
+ printf("\n\nAPI Test\n");
+ printf("========\n");
+ printf("Hit enter to accept the default values indicated in []\n\n");
+
+ //--- Input A
+ strcpy(fileName, "./modules/audio_coding/main/test/testfile32kHz.pcm");
+ frequencyHz = 32000;
+ printf("Enter input file at side A [%s]: ", fileName);
+ PCMFile::ChooseFile(fileName, 499, &frequencyHz);
+ _inFileA.Open(fileName, frequencyHz, "rb", true);
+
+ //--- Output A
+ strcpy(fileName, "./modules/audio_coding/main/test/outA.pcm");
+ printf("Enter output file at side A [%s]: ", fileName);
+ PCMFile::ChooseFile(fileName, 499, &frequencyHz);
+ _outFileA.Open(fileName, frequencyHz, "wb");
+
+ //--- Input B
+ strcpy(fileName, "./modules/audio_coding/main/test/testfile32kHz.pcm");
+ printf("\n\nEnter input file at side B [%s]: ", fileName);
+ PCMFile::ChooseFile(fileName, 499, &frequencyHz);
+ _inFileB.Open(fileName, frequencyHz, "rb", true);
+
+ //--- Output B
+ strcpy(fileName, "./modules/audio_coding/main/test/outB.pcm");
+ printf("Enter output file at side B [%s]: ", fileName);
+ PCMFile::ChooseFile(fileName, 499, &frequencyHz);
+ _outFileB.Open(fileName, frequencyHz, "wb");
+
+ //--- Set A-to-B channel
+ _channel_A2B = new Channel(2);
+ CHECK_ERROR_MT(_acmA->RegisterTransportCallback(_channel_A2B));
+ _channel_A2B->RegisterReceiverACM(_acmB);
+
+ //--- Set B-to-A channel
+ _channel_B2A = new Channel(1);
+ CHECK_ERROR_MT(_acmB->RegisterTransportCallback(_channel_B2A));
+ _channel_B2A->RegisterReceiverACM(_acmA);
+
+ //--- EVENT TIMERS
+ // A
+ _pullEventA = EventWrapper::Create();
+ _pushEventA = EventWrapper::Create();
+ _processEventA = EventWrapper::Create();
+ _apiEventA = EventWrapper::Create();
+ // B
+ _pullEventB = EventWrapper::Create();
+ _pushEventB = EventWrapper::Create();
+ _processEventB = EventWrapper::Create();
+ _apiEventB = EventWrapper::Create();
+
+ //--- I/O params
+ // A
+ _outFreqHzA = _outFileA.SamplingFrequency();
+ // B
+ _outFreqHzB = _outFileB.SamplingFrequency();
+
+
+ //Trace::SetEncryptedTraceFile("ACMAPITestEncrypted.txt");
+
+ char print[11];
+
+ printf("\nRandom Test (y/n)?");
+ fgets(print, 10, stdin);
+ print[10] = '\0';
+ if(strstr(print, "y") != NULL)
+ {
+ _randomTest = true;
+ _verbose = false;
+ _writeToFile = false;
+ Trace::CreateTrace();
+ Trace::SetTraceFile("ACMAPITest.txt");
+ //freopen("APITest_log.txt", "w", stdout);
+ }
+ else
+ {
+ Trace::CreateTrace();
+ Trace::SetTraceFile("ACMAPITest.txt", true);
+ _randomTest = false;
+ printf("\nPrint Tests (y/n)? ");
+ fgets(print, 10, stdin);
+ print[10] = '\0';
+ if(strstr(print, "y") == NULL)
+ {
+ freopen("APITest_log.txt", "w", stdout);
+ _verbose = false;
+ }
+ }
+
+#ifdef WEBRTC_DTMF_DETECTION
+ _dtmfCallback = new DTMFDetector;
+#endif
+ _vadCallbackA = new VADCallback;
+ _vadCallbackB = new VADCallback;
+
+ return 0;
+}
+
+bool
+APITest::PushAudioThreadA(void* obj)
+{
+ return static_cast<APITest*>(obj)->PushAudioRunA();
+}
+
+bool
+APITest::PushAudioThreadB(void* obj)
+{
+ return static_cast<APITest*>(obj)->PushAudioRunB();
+}
+
+bool
+APITest::PullAudioThreadA(void* obj)
+{
+ return static_cast<APITest*>(obj)->PullAudioRunA();
+}
+
+bool
+APITest::PullAudioThreadB(void* obj)
+{
+ return static_cast<APITest*>(obj)->PullAudioRunB();
+}
+
+bool
+APITest::ProcessThreadA(void* obj)
+{
+ return static_cast<APITest*>(obj)->ProcessRunA();
+}
+
+bool
+APITest::ProcessThreadB(void* obj)
+{
+ return static_cast<APITest*>(obj)->ProcessRunB();
+}
+
+bool
+APITest::APIThreadA(void* obj)
+{
+ return static_cast<APITest*>(obj)->APIRunA();
+}
+
+bool
+APITest::APIThreadB(void* obj)
+{
+ return static_cast<APITest*>(obj)->APIRunB();
+}
+
+bool
+APITest::PullAudioRunA()
+{
+ _pullEventA->Wait(100);
+ AudioFrame audioFrame;
+ if(_acmA->PlayoutData10Ms(_outFreqHzA, audioFrame) < 0)
+ {
+ bool thereIsDecoder;
+ {
+ ReadLockScoped rl(_apiTestRWLock);
+ thereIsDecoder = _thereIsDecoderA;
+ }
+ if(thereIsDecoder)
+ {
+ fprintf(stderr, "\n>>>>>> cannot pull audio A <<<<<<<< \n");
+ }
+ }
+ else
+ {
+ if(_writeToFile)
+ {
+ _outFileA.Write10MsData(audioFrame);
+ }
+ _receiveVADActivityA[(int)audioFrame._vadActivity]++;
+ }
+ return true;
+}
+
+bool
+APITest::PullAudioRunB()
+{
+ _pullEventB->Wait(100);
+ AudioFrame audioFrame;
+ if(_acmB->PlayoutData10Ms(_outFreqHzB, audioFrame) < 0)
+ {
+ bool thereIsDecoder;
+ {
+ ReadLockScoped rl(_apiTestRWLock);
+ thereIsDecoder = _thereIsDecoderB;
+ }
+ if(thereIsDecoder)
+ {
+ fprintf(stderr, "\n>>>>>> cannot pull audio B <<<<<<<< \n");
+ fprintf(stderr, "%d %d\n", _testNumA, _testNumB);
+ }
+ }
+ else
+ {
+ if(_writeToFile)
+ {
+ _outFileB.Write10MsData(audioFrame);
+ }
+ _receiveVADActivityB[(int)audioFrame._vadActivity]++;
+ }
+ return true;
+}
+
+bool
+APITest::PushAudioRunA()
+{
+ _pushEventA->Wait(100);
+ AudioFrame audioFrame;
+ _inFileA.Read10MsData(audioFrame);
+ if(_acmA->Add10MsData(audioFrame) < 0)
+ {
+ bool thereIsEncoder;
+ {
+ ReadLockScoped rl(_apiTestRWLock);
+ thereIsEncoder = _thereIsEncoderA;
+ }
+ if(thereIsEncoder)
+ {
+ fprintf(stderr, "\n>>>> add10MsData at A failed <<<<\n");
+ }
+ }
+ return true;
+}
+
+bool
+APITest::PushAudioRunB()
+{
+ _pushEventB->Wait(100);
+ AudioFrame audioFrame;
+ _inFileB.Read10MsData(audioFrame);
+ if(_acmB->Add10MsData(audioFrame) < 0)
+ {
+ bool thereIsEncoder;
+ {
+ ReadLockScoped rl(_apiTestRWLock);
+ thereIsEncoder = _thereIsEncoderB;
+ }
+
+ if(thereIsEncoder)
+ {
+ fprintf(stderr, "\n>>>> cannot add audio to B <<<<");
+ }
+ }
+
+ return true;
+}
+
+bool
+APITest::ProcessRunA()
+{
+ _processEventA->Wait(100);
+ if(_acmA->Process() < 0)
+ {
+ // do not print error message if there is no encoder
+ bool thereIsEncoder;
+ {
+ ReadLockScoped rl(_apiTestRWLock);
+ thereIsEncoder = _thereIsEncoderA;
+ }
+
+ if(thereIsEncoder)
+ {
+ fprintf(stderr, "\n>>>>> Process Failed at A <<<<<\n");
+ }
+ }
+ return true;
+}
+
+bool
+APITest::ProcessRunB()
+{
+ _processEventB->Wait(100);
+ if(_acmB->Process() < 0)
+ {
+ bool thereIsEncoder;
+ {
+ ReadLockScoped rl(_apiTestRWLock);
+ thereIsEncoder = _thereIsEncoderB;
+ }
+ if(thereIsEncoder)
+ {
+ fprintf(stderr, "\n>>>>> Process Failed at B <<<<<\n");
+ }
+ }
+ return true;
+}
+
+/*/
+ *
+ * In side A we test the APIs which are related to sender Side.
+ *
+/*/
+
+
+void
+APITest::RunTest(char thread)
+{
+ int testNum;
+ {
+ WriteLockScoped cs(_apiTestRWLock);
+ if(thread == 'A')
+ {
+ _testNumA = (_testNumB + 1 + (rand() % 6)) % 7;
+ testNum = _testNumA;
+
+ _movingDot[_dotPositionA] = ' ';
+ if(_dotPositionA == 0)
+ {
+ _dotMoveDirectionA = 1;
+ }
+ if(_dotPositionA == 19)
+ {
+ _dotMoveDirectionA = -1;
+ }
+ _dotPositionA += _dotMoveDirectionA;
+ _movingDot[_dotPositionA] = (_dotMoveDirectionA > 0)? '>':'<';
+ }
+ else
+ {
+ _testNumB = (_testNumA + 1 + (rand() % 6)) % 7;
+ testNum = _testNumB;
+
+ _movingDot[_dotPositionB] = ' ';
+ if(_dotPositionB == 20)
+ {
+ _dotMoveDirectionB = 1;
+ }
+ if(_dotPositionB == 39)
+ {
+ _dotMoveDirectionB = -1;
+ }
+ _dotPositionB += _dotMoveDirectionB;
+ _movingDot[_dotPositionB] = (_dotMoveDirectionB > 0)? '>':'<';
+ }
+ //fprintf(stderr, "%c: %d \n", thread, testNum);
+ //fflush(stderr);
+ }
+ switch(testNum)
+ {
+ case 0:
+ CurrentCodec('A');
+ ChangeCodec('A');
+ break;
+ case 1:
+ TestPlayout('B');
+ break;
+ case 2:
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\nTesting Delay ...\n");
+ }
+ TestDelay('A');
+ break;
+ case 3:
+ TestSendVAD('A');
+ break;
+ case 4:
+ TestRegisteration('A');
+ break;
+ case 5:
+ TestReceiverVAD('A');
+ break;
+ case 6:
+#ifdef WEBRTC_DTMF_DETECTION
+ LookForDTMF('A');
+#endif
+ break;
+ default:
+ fprintf(stderr, "Wrong Test Number\n");
+ getchar();
+ exit(1);
+ }
+}
+
+
+
+bool
+APITest::APIRunA()
+{
+ _apiEventA->Wait(50);
+
+ bool randomTest;
+ {
+ ReadLockScoped rl(_apiTestRWLock);
+ randomTest = _randomTest;
+ }
+ if(randomTest)
+ {
+ RunTest('A');
+ }
+ else
+ {
+ CurrentCodec('A');
+ ChangeCodec('A');
+ TestPlayout('B');
+ if(_codecCntrA == 0)
+ {
+ fprintf(stdout, "\nTesting Delay ...\n");
+ TestDelay('A');
+ }
+ // VAD TEST
+ TestSendVAD('A');
+ TestRegisteration('A');
+ TestReceiverVAD('A');
+#ifdef WEBRTC_DTMF_DETECTION
+ LookForDTMF('A');
+#endif
+ }
+ return true;
+}
+
+bool
+APITest::APIRunB()
+{
+ _apiEventB->Wait(50);
+ bool randomTest;
+ {
+ ReadLockScoped rl(_apiTestRWLock);
+ randomTest = _randomTest;
+ }
+ //_apiEventB->Wait(2000);
+ if(randomTest)
+ {
+ RunTest('B');
+ }
+
+ return true;
+}
+
+void
+APITest::Perform()
+{
+ SetUp();
+
+ //--- THREADS
+ // A
+ // PUSH
+ ThreadWrapper* myPushAudioThreadA = ThreadWrapper::CreateThread(PushAudioThreadA,
+ this, kNormalPriority, "PushAudioThreadA");
+ CHECK_THREAD_NULLITY(myPushAudioThreadA, "Unable to start A::PUSH thread");
+ // PULL
+ ThreadWrapper* myPullAudioThreadA = ThreadWrapper::CreateThread(PullAudioThreadA,
+ this, kNormalPriority, "PullAudioThreadA");
+ CHECK_THREAD_NULLITY(myPullAudioThreadA, "Unable to start A::PULL thread");
+ // Process
+ ThreadWrapper* myProcessThreadA = ThreadWrapper::CreateThread(ProcessThreadA,
+ this, kNormalPriority, "ProcessThreadA");
+ CHECK_THREAD_NULLITY(myProcessThreadA, "Unable to start A::Process thread");
+ // API
+ ThreadWrapper* myAPIThreadA = ThreadWrapper::CreateThread(APIThreadA,
+ this, kNormalPriority, "APIThreadA");
+ CHECK_THREAD_NULLITY(myAPIThreadA, "Unable to start A::API thread");
+ // B
+ // PUSH
+ ThreadWrapper* myPushAudioThreadB = ThreadWrapper::CreateThread(PushAudioThreadB,
+ this, kNormalPriority, "PushAudioThreadB");
+ CHECK_THREAD_NULLITY(myPushAudioThreadB, "Unable to start B::PUSH thread");
+ // PULL
+ ThreadWrapper* myPullAudioThreadB = ThreadWrapper::CreateThread(PullAudioThreadB,
+ this, kNormalPriority, "PullAudioThreadB");
+ CHECK_THREAD_NULLITY(myPullAudioThreadB, "Unable to start B::PULL thread");
+ // Process
+ ThreadWrapper* myProcessThreadB = ThreadWrapper::CreateThread(ProcessThreadB,
+ this, kNormalPriority, "ProcessThreadB");
+ CHECK_THREAD_NULLITY(myProcessThreadB, "Unable to start B::Process thread");
+ // API
+ ThreadWrapper* myAPIThreadB = ThreadWrapper::CreateThread(APIThreadB,
+ this, kNormalPriority, "APIThreadB");
+ CHECK_THREAD_NULLITY(myAPIThreadB, "Unable to start B::API thread");
+
+
+ //_apiEventA->StartTimer(true, 5000);
+ //_apiEventB->StartTimer(true, 5000);
+
+ _processEventA->StartTimer(true, 10);
+ _processEventB->StartTimer(true, 10);
+
+ _pullEventA->StartTimer(true, 10);
+ _pullEventB->StartTimer(true, 10);
+
+ _pushEventA->StartTimer(true, 10);
+ _pushEventB->StartTimer(true, 10);
+
+ // Keep main thread waiting for sender/receiver
+ // threads to complete
+ EventWrapper* completeEvent = EventWrapper::Create();
+ WebRtc_UWord64 startTime = TickTime::MillisecondTimestamp();
+ WebRtc_UWord64 currentTime;
+ do
+ {
+ {
+ //ReadLockScoped rl(_apiTestRWLock);
+ //fprintf(stderr, "\r%s", _movingDot);
+ }
+ //fflush(stderr);
+ completeEvent->Wait(50);
+ currentTime = TickTime::MillisecondTimestamp();
+ } while((currentTime - startTime) < 120000); // Run test in 2 minutes (120000 ms)
+
+ //completeEvent->Wait(0xFFFFFFFF);//(unsigned long)((unsigned long)TEST_DURATION_SEC * (unsigned long)1000));
+ delete completeEvent;
+
+ myPushAudioThreadA->Stop();
+ myPullAudioThreadA->Stop();
+ myProcessThreadA->Stop();
+ myAPIThreadA->Stop();
+
+ delete myPushAudioThreadA;
+ delete myPullAudioThreadA;
+ delete myProcessThreadA;
+ delete myAPIThreadA;
+
+
+ myPushAudioThreadB->Stop();
+ myPullAudioThreadB->Stop();
+ myProcessThreadB->Stop();
+ myAPIThreadB->Stop();
+
+ delete myPushAudioThreadB;
+ delete myPullAudioThreadB;
+ delete myProcessThreadB;
+ delete myAPIThreadB;
+}
+
+
+void
+APITest::CheckVADStatus(char side)
+{
+
+ bool dtxEnabled;
+ bool vadEnabled;
+ ACMVADMode vadMode;
+ EventWrapper* myEvent = EventWrapper::Create();
+ if(side == 'A')
+ {
+ _acmA->VAD(dtxEnabled, vadEnabled, vadMode);
+ _acmA->RegisterVADCallback(NULL);
+ _vadCallbackA->Reset();
+ _acmA->RegisterVADCallback(_vadCallbackA);
+
+ if(!_randomTest)
+ {
+ if(_verbose)
+ {
+ fprintf(stdout, "DTX %3s, VAD %3s, Mode %d",
+ dtxEnabled? "ON":"OFF",
+ vadEnabled? "ON":"OFF",
+ (int)vadMode);
+ Wait(5000);
+ fprintf(stdout, " => bit-rate %3.0f kbps\n",
+ _channel_A2B->BitRate());
+ }
+ else
+ {
+ Wait(5000);
+ fprintf(stdout, "DTX %3s, VAD %3s, Mode %d => bit-rate %3.0f kbps\n",
+ dtxEnabled? "ON":"OFF",
+ vadEnabled? "ON":"OFF",
+ (int)vadMode,
+ _channel_A2B->BitRate());
+ }
+ _vadCallbackA->PrintFrameTypes();
+ }
+
+ if(dtxEnabled != _sendDTXA)
+ {
+ fprintf(stderr, ">>> Error Enabling DTX <<<\n");
+ }
+ if((vadEnabled != _sendVADA) && (!dtxEnabled))
+ {
+ fprintf(stderr, ">>> Error Enabling VAD <<<\n");
+ }
+ if((vadMode != _sendVADModeA) && vadEnabled)
+ {
+ fprintf(stderr, ">>> Error setting VAD-mode <<<\n");
+ }
+ }
+ else
+ {
+ _acmB->VAD(dtxEnabled, vadEnabled, vadMode);
+
+ _acmB->RegisterVADCallback(NULL);
+ _vadCallbackB->Reset();
+ _acmB->RegisterVADCallback(_vadCallbackB);
+
+ if(!_randomTest)
+ {
+ if(_verbose)
+ {
+ fprintf(stdout, "DTX %3s, VAD %3s, Mode %d",
+ dtxEnabled? "ON":"OFF",
+ vadEnabled? "ON":"OFF",
+ (int)vadMode);
+ Wait(5000);
+ fprintf(stdout, " => bit-rate %3.0f kbps\n",
+ _channel_B2A->BitRate());
+ }
+ else
+ {
+ Wait(5000);
+ fprintf(stdout, "DTX %3s, VAD %3s, Mode %d => bit-rate %3.0f kbps\n",
+ dtxEnabled? "ON":"OFF",
+ vadEnabled? "ON":"OFF",
+ (int)vadMode,
+ _channel_B2A->BitRate());
+ }
+ _vadCallbackB->PrintFrameTypes();
+ }
+
+ if(dtxEnabled != _sendDTXB)
+ {
+ fprintf(stderr, ">>> Error Enabling DTX <<<\n");
+ }
+ if((vadEnabled != _sendVADB) && (!dtxEnabled))
+ {
+ fprintf(stderr, ">>> Error Enabling VAD <<<\n");
+ }
+ if((vadMode != _sendVADModeB) && vadEnabled)
+ {
+ fprintf(stderr, ">>> Error setting VAD-mode <<<\n");
+ }
+ }
+}
+
+// Set Min delay, get delay, playout timestamp
+void
+APITest::TestDelay(char side)
+{
+ AudioCodingModule* myACM;
+ Channel* myChannel;
+ WebRtc_Word32* myMinDelay;
+ EventWrapper* myEvent = EventWrapper::Create();
+
+ WebRtc_UWord32 inTimestamp = 0;
+ WebRtc_UWord32 outTimestamp = 0;
+ double estimDelay = 0;
+ WebRtc_UWord16 delay = 0;
+
+ double averageEstimDelay = 0;
+ double averageDelay = 0;
+
+ CircularBuffer estimDelayCB(100);
+ CircularBuffer delayCB(100);
+ estimDelayCB.SetArithMean(true);
+ delayCB.SetArithMean(true);
+
+
+ if(side == 'A')
+ {
+ myACM = _acmA;
+ myChannel = _channel_B2A;
+ myMinDelay = &_minDelayA;
+ }
+ else
+ {
+ myACM = _acmB;
+ myChannel = _channel_A2B;
+ myMinDelay = &_minDelayB;
+ }
+
+
+ CHECK_ERROR_MT(myACM->SetMinimumPlayoutDelay(*myMinDelay));
+
+
+ inTimestamp = myChannel->LastInTimestamp();
+ CHECK_ERROR_MT(myACM->PlayoutTimestamp(outTimestamp));
+ CHECK_ERROR_MT(myACM->Delay(delay));
+
+ if(!_randomTest)
+ {
+ myEvent->StartTimer(true, 30);
+ int n = 0;
+ int settlePoint = 5000;
+ while(n < settlePoint + 400)
+ {
+ myEvent->Wait(1000);
+
+ inTimestamp = myChannel->LastInTimestamp();
+ CHECK_ERROR_MT(myACM->PlayoutTimestamp(outTimestamp));
+
+ //std::cout << outTimestamp << std::endl << std::flush;
+ estimDelay = (double)((WebRtc_UWord32)(inTimestamp - outTimestamp)) /
+ ((double)myACM->ReceiveFrequency() / 1000.0);
+
+ estimDelayCB.Update(estimDelay);
+
+ estimDelayCB.ArithMean(averageEstimDelay);
+ //printf("\n %6.1f \n", estimDelay);
+ //std::cout << " " << std::flush;
+
+ CHECK_ERROR_MT(myACM->Delay(delay));
+ delayCB.Update(delay);
+ delayCB.ArithMean(averageDelay);
+
+ if(_verbose)
+ {
+ fprintf(stdout, "\rExpected: %4d, retreived: %6.1f, measured: %6.1f",
+ *myMinDelay, averageDelay, averageEstimDelay);
+ std::cout << " " << std::flush;
+ }
+ if((averageDelay > *myMinDelay) && (n < settlePoint))
+ {
+ settlePoint = n;
+ }
+ n++;
+ }
+ myEvent->StopTimer();
+ }
+
+ if((!_verbose) && (!_randomTest))
+ {
+ fprintf(stdout, "\nExpected: %4d, retreived: %6.1f, measured: %6.1f",
+ *myMinDelay, averageDelay, averageEstimDelay);
+ }
+
+ *myMinDelay = (rand() % 1000) + 1;
+
+ ACMJitterStatistics jitterStat;
+ ACMNetworkStatistics networkStat;
+ CHECK_ERROR_MT(myACM->JitterStatistics(jitterStat));
+ CHECK_ERROR_MT(myACM->NetworkStatistics(networkStat));
+
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n\nJitter Statistics at Side %c\n", side);
+ fprintf(stdout, "--------------------------------------\n");
+ fprintf(stdout, "buffer-size............. %d\n", networkStat.currentBufferSize);
+ fprintf(stdout, "Preferred buffer-size... %d\n", networkStat.preferredBufferSize);
+ fprintf(stdout, "packet-size rate........ %d\n", networkStat.currentPacketLossRate);
+ fprintf(stdout, "discard rate............ %d\n", networkStat.currentDiscardRate);
+ fprintf(stdout, "expand rate............. %d\n", networkStat.currentExpandRate);
+ fprintf(stdout, "Preemptive rate......... %d\n", networkStat.currentPreemptiveRate);
+ fprintf(stdout, "Accelerate rate......... %d\n", networkStat.currentAccelerateRate);
+
+ fprintf(stdout, "\n\nJitter Statistics at side %c\n", side);
+ fprintf(stdout, "--------------------------------------\n");
+ fprintf(stdout, "Jitter buffer min size....... %d\n", jitterStat.jbMinSize);
+ fprintf(stdout, "Jitter buffer Max size....... %d\n", jitterStat.jbMaxSize);
+ fprintf(stdout, "Jitter buffer Average size... %d\n", jitterStat.jbAvgSize);
+ fprintf(stdout, "Change Count................. %d ms\n", jitterStat.jbChangeCount);
+ fprintf(stdout, "Late Loss.................... %d ms\n", jitterStat.lateLossMs);
+ fprintf(stdout, "Accelerate................... %d ms\n", jitterStat.accelerateMs);
+ fprintf(stdout, "Flushed...................... %d ms\n", jitterStat.flushedMs);
+ fprintf(stdout, "Generated Silence............ %d ms\n", jitterStat.generatedSilentMs);
+ fprintf(stdout, "Interpolated Voice........... %d ms\n", jitterStat.interpolatedVoiceMs);
+ fprintf(stdout, "Interpolated Silence......... %d ms\n", jitterStat.interpolatedSilentMs);
+ fprintf(stdout, "No tiny expand............... %d\n", jitterStat.numExpandTiny);
+ fprintf(stdout, "No small expand.............. %d\n", jitterStat.numExpandSmall);
+ fprintf(stdout, "No Medium expand............. %d\n", jitterStat.numExpandMedium);
+ fprintf(stdout, "No long expand............... %d\n", jitterStat.numExpandLong);
+ fprintf(stdout, "longest expand............... %d ms\n", jitterStat.longestExpandDurationMs);
+ fprintf(stdout, "No IAT 500................... %d ms\n", jitterStat.countIAT500ms);
+ fprintf(stdout, "No IAT 1000.................. %d ms\n", jitterStat.countIAT1000ms);
+ fprintf(stdout, "No IAT 2000.................. %d ms\n", jitterStat.countIAT2000ms);
+ fprintf(stdout, "longest IAT.................. %d ms\n", jitterStat.longestIATms);
+ fprintf(stdout, "Min packet delay............. %d ms\n", jitterStat.minPacketDelayMs);
+ fprintf(stdout, "Max packet delay............. %d ms\n", jitterStat.maxPacketDelayMs);
+ fprintf(stdout, "Average packet delay......... %d ms\n", jitterStat.avgPacketDelayMs);
+ }
+
+ CHECK_ERROR_MT(myACM->SetMinimumPlayoutDelay(*myMinDelay));
+
+ if(!_randomTest)
+ {
+ myEvent->Wait(500);
+ fprintf(stdout, "\n");
+ fprintf(stdout, "\n");
+ }
+ delete myEvent;
+}
+
+// Unregister a codec & register again.
+void
+APITest::TestRegisteration(char sendSide)
+{
+ AudioCodingModule* sendACM;
+ AudioCodingModule* receiveACM;
+ bool* thereIsDecoder;
+ EventWrapper* myEvent = EventWrapper::Create();
+
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n\n");
+ fprintf(stdout, "---------------------------------------------------------\n");
+ fprintf(stdout, " Unregister/register Receive Codec\n");
+ fprintf(stdout, "---------------------------------------------------------\n");
+ }
+
+ switch(sendSide)
+ {
+ case 'A':
+ {
+ sendACM = _acmA;
+ receiveACM = _acmB;
+ thereIsDecoder = &_thereIsDecoderB;
+ break;
+ }
+ case 'B':
+ {
+ sendACM = _acmB;
+ receiveACM = _acmA;
+ thereIsDecoder = &_thereIsDecoderA;
+ break;
+ }
+ default:
+ fprintf(stderr, "Invalid sender-side in TestRegistration(%c)\n", sendSide);
+ exit(-1);
+ }
+
+ CodecInst myCodec;
+ if(sendACM->SendCodec(myCodec) < 0)
+ {
+ AudioCodingModule::Codec(_codecCntrA, myCodec);
+ }
+
+ if(!_randomTest)
+ {
+ fprintf(stdout, "Unregistering reveive codec, NO AUDIO.\n");
+ fflush(stdout);
+ }
+ {
+ WriteLockScoped wl(_apiTestRWLock);
+ *thereIsDecoder = false;
+ }
+ //myEvent->Wait(20);
+ CHECK_ERROR_MT(receiveACM->UnregisterReceiveCodec(myCodec.pltype));
+ Wait(1000);
+
+ int currentPayload = myCodec.pltype;
+
+ if(!FixedPayloadTypeCodec(myCodec.plname))
+ {
+ WebRtc_Word32 i;
+ for(i = 0; i < 32; i++)
+ {
+ if(!_payloadUsed[i])
+ {
+ if(!_randomTest)
+ {
+ fprintf(stdout, "Register receive codec with new Payload, AUDIO BACK.\n");
+ }
+ //myCodec.pltype = i + 96;
+ //CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
+ //CHECK_ERROR_MT(sendACM->RegisterSendCodec(myCodec));
+ //myEvent->Wait(20);
+ //{
+ // WriteLockScoped wl(_apiTestRWLock);
+ // *thereIsDecoder = true;
+ //}
+ Wait(1000);
+
+ if(!_randomTest)
+ {
+ fprintf(stdout, "Unregistering reveive codec, NO AUDIO.\n");
+ }
+ //{
+ // WriteLockScoped wl(_apiTestRWLock);
+ // *thereIsDecoder = false;
+ //}
+ //myEvent->Wait(20);
+ //CHECK_ERROR_MT(receiveACM->UnregisterReceiveCodec(myCodec.pltype));
+ Wait(1000);
+
+ myCodec.pltype = currentPayload;
+ if(!_randomTest)
+ {
+ fprintf(stdout, "Register receive codec with default Payload, AUDIO BACK.\n");
+ fflush(stdout);
+ }
+ CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
+ //CHECK_ERROR_MT(sendACM->RegisterSendCodec(myCodec));
+ myEvent->Wait(20);
+ {
+ WriteLockScoped wl(_apiTestRWLock);
+ *thereIsDecoder = true;
+ }
+ Wait(1000);
+
+ break;
+ }
+ }
+ if(i == 32)
+ {
+ CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
+ {
+ WriteLockScoped wl(_apiTestRWLock);
+ *thereIsDecoder = true;
+ }
+ }
+ }
+ else
+ {
+ if(!_randomTest)
+ {
+ fprintf(stdout, "Register receive codec with fixed Payload, AUDIO BACK.\n");
+ fflush(stdout);
+ }
+ CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
+ //CHECK_ERROR_MT(receiveACM->UnregisterReceiveCodec(myCodec.pltype));
+ //CHECK_ERROR_MT(receiveACM->RegisterReceiveCodec(myCodec));
+ myEvent->Wait(20);
+ {
+ WriteLockScoped wl(_apiTestRWLock);
+ *thereIsDecoder = true;
+ }
+ }
+ delete myEvent;
+ if(!_randomTest)
+ {
+ fprintf(stdout, "---------------------------------------------------------\n");
+ }
+}
+
+// Playout Mode, background noise mode.
+// Receiver Frequency, playout frequency.
+void
+APITest::TestPlayout(char receiveSide)
+{
+ AudioCodingModule* receiveACM;
+ AudioPlayoutMode* playoutMode;
+ ACMBackgroundNoiseMode* bgnMode;
+ switch(receiveSide)
+ {
+ case 'A':
+ {
+ receiveACM = _acmA;
+ playoutMode = &_playoutModeA;
+ bgnMode = &_bgnModeA;
+ break;
+ }
+ case 'B':
+ {
+ receiveACM = _acmB;
+ playoutMode = &_playoutModeB;
+ bgnMode = &_bgnModeB;
+ break;
+ }
+ default:
+ receiveACM = _acmA;
+ }
+
+ WebRtc_Word32 receiveFreqHz = receiveACM->ReceiveFrequency();
+ WebRtc_Word32 playoutFreqHz = receiveACM->PlayoutFrequency();
+
+ CHECK_ERROR_MT(receiveFreqHz);
+ CHECK_ERROR_MT(playoutFreqHz);
+
+ char bgnString[25];
+ switch(*bgnMode)
+ {
+ case On:
+ {
+ *bgnMode = Fade;
+ strncpy(bgnString, "Fade", 25);
+ break;
+ }
+ case Fade:
+ {
+ *bgnMode = Off;
+ strncpy(bgnString, "OFF", 25);
+ break;
+ }
+ case Off:
+ {
+ *bgnMode = On;
+ strncpy(bgnString, "ON", 25);
+ break;
+ }
+ default:
+ *bgnMode = On;
+ strncpy(bgnString, "ON", 25);
+ }
+ CHECK_ERROR_MT(receiveACM->SetBackgroundNoiseMode(*bgnMode));
+ bgnString[24] = '\0';
+
+ char playoutString[25];
+ switch(*playoutMode)
+ {
+ case voice:
+ {
+ *playoutMode = fax;
+ strncpy(playoutString, "FAX", 25);
+ break;
+ }
+ case fax:
+ {
+ *playoutMode = streaming;
+ strncpy(playoutString, "Streaming", 25);
+ break;
+ }
+ case streaming:
+ {
+ *playoutMode = voice;
+ strncpy(playoutString, "Voice", 25);
+ break;
+ }
+ default:
+ *playoutMode = voice;
+ strncpy(playoutString, "Voice", 25);
+ }
+ CHECK_ERROR_MT(receiveACM->SetPlayoutMode(*playoutMode));
+ playoutString[24] = '\0';
+
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n");
+ fprintf(stdout, "In Side %c\n", receiveSide);
+ fprintf(stdout, "---------------------------------\n");
+ fprintf(stdout, "Receive Frequency....... %d Hz\n", receiveFreqHz);
+ fprintf(stdout, "Playout Frequency....... %d Hz\n", playoutFreqHz);
+ fprintf(stdout, "Audio Playout Mode...... %s\n", playoutString);
+ fprintf(stdout, "Background Noise Mode... %s\n", bgnString);
+ }
+}
+
+// set/get receiver VAD status & mode.
+void
+APITest::TestReceiverVAD(char side)
+{
+ AudioCodingModule* myACM;
+ EventWrapper* myEvent = EventWrapper::Create();
+ WebRtc_UWord64* myReceiveVADActivity;
+
+ if(side == 'A')
+ {
+ myACM = _acmA;
+ myReceiveVADActivity = _receiveVADActivityA;
+ }
+ else
+ {
+ myACM = _acmB;
+ myReceiveVADActivity = _receiveVADActivityB;
+ }
+
+ bool vadStatus = myACM->ReceiveVADStatus();
+ ACMVADMode mode = myACM->ReceiveVADMode();
+
+ CHECK_ERROR_MT(mode);
+
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n\nCurrent Receive VAD at side %c\n", side);
+ fprintf(stdout, "----------------------------------\n");
+ fprintf(stdout, "Status........ %s\n", vadStatus? "ON":"OFF");
+ fprintf(stdout, "mode.......... %d\n", (int)mode);
+ fprintf(stdout, "VAD Active.... %llu\n", myReceiveVADActivity[0]);
+ fprintf(stdout, "VAD Passive... %llu\n", myReceiveVADActivity[1]);
+ fprintf(stdout, "VAD Unknown... %llu\n", myReceiveVADActivity[2]);
+ }
+
+ if(vadStatus)
+ {
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\nChange Receive VAD at side %c\n\n", side);
+ }
+
+ switch(mode)
+ {
+ case VADNormal:
+ mode = VADAggr;
+ break;
+ case VADLowBitrate:
+ mode = VADVeryAggr;
+ break;
+ case VADAggr:
+ mode = VADLowBitrate;
+ break;
+ case VADVeryAggr:
+ vadStatus = false;
+ mode = VADNormal;
+ break;
+ default:
+ mode = VADNormal;
+ }
+
+ CHECK_ERROR_MT(myACM->SetReceiveVADMode(mode));
+ CHECK_ERROR_MT(myACM->SetReceiveVADStatus(vadStatus));
+ }
+ else
+ {
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\nTurn on Receive VAD at side %c\n\n", side);
+ }
+ CHECK_ERROR_MT(myACM->SetReceiveVADStatus(true));
+ CHECK_ERROR_MT(myACM->SetReceiveVADMode(VADNormal));
+ }
+ for(int n = 0; n < 3; n++)
+ {
+ myReceiveVADActivity[n] = 0;
+ }
+}
+
+
+void
+APITest::TestSendVAD(char side)
+{
+ if(_randomTest)
+ {
+ return;
+ }
+
+ bool* vad;
+ bool* dtx;
+ ACMVADMode* mode;
+ Channel* myChannel;
+ AudioCodingModule* myACM;
+
+ CodecInst myCodec;
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n\n");
+ fprintf(stdout, "-----------------------------------------------\n");
+ fprintf(stdout, " Test VAD API\n");
+ fprintf(stdout, "-----------------------------------------------\n");
+ }
+
+ if(side == 'A')
+ {
+ AudioCodingModule::Codec(_codecCntrA, myCodec);
+ vad = &_sendVADA;
+ dtx = &_sendDTXA;
+ mode = &_sendVADModeA;
+ myChannel = _channel_A2B;
+ myACM = _acmA;
+ }
+ else
+ {
+ AudioCodingModule::Codec(_codecCntrB, myCodec);
+ vad = &_sendVADB;
+ dtx = &_sendDTXB;
+ mode = &_sendVADModeB;
+ myChannel = _channel_B2A;
+ myACM = _acmB;
+ }
+
+ CheckVADStatus(side);
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n\n");
+ }
+
+ switch(*mode)
+ {
+ case VADNormal:
+ *vad = true;
+ *dtx = true;
+ *mode = VADAggr;
+ break;
+ case VADLowBitrate:
+ *vad = true;
+ *dtx = true;
+ *mode = VADVeryAggr;
+ break;
+ case VADAggr:
+ *vad = true;
+ *dtx = true;
+ *mode = VADLowBitrate;
+ break;
+ case VADVeryAggr:
+ *vad = false;
+ *dtx = false;
+ *mode = VADNormal;
+ break;
+ default:
+ *mode = VADNormal;
+ }
+
+ *dtx = (myCodec.plfreq == 32000)? false:*dtx;
+
+ CHECK_ERROR_MT(myACM->SetVAD(*dtx, *vad, *mode));
+ myChannel->ResetStats();
+
+ CheckVADStatus(side);
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n");
+ fprintf(stdout, "-----------------------------------------------\n");
+ }
+
+ // Fault Test
+ CHECK_PROTECTED_MT(myACM->SetVAD(false, true, (ACMVADMode)-1));
+ CHECK_PROTECTED_MT(myACM->SetVAD(false, true, (ACMVADMode)4));
+
+
+
+}
+
+
+void
+APITest::CurrentCodec(char side)
+{
+ CodecInst myCodec;
+ EventWrapper* myEvent = EventWrapper::Create();
+ if(side == 'A')
+ {
+ _acmA->SendCodec(myCodec);
+ }
+ else
+ {
+ _acmB->SendCodec(myCodec);
+ }
+
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n\n");
+ fprintf(stdout, "Send codec in Side A\n");
+ fprintf(stdout, "----------------------------\n");
+ fprintf(stdout, "Name................. %s\n", myCodec.plname);
+ fprintf(stdout, "Sampling Frequency... %d\n", myCodec.plfreq);
+ fprintf(stdout, "Rate................. %d\n", myCodec.rate);
+ fprintf(stdout, "Payload-type......... %d\n", myCodec.pltype);
+ fprintf(stdout, "Packet-size.......... %d\n", myCodec.pacsize);
+ }
+
+ Wait(100);
+}
+
+void
+APITest::ChangeCodec(char side)
+{
+ CodecInst myCodec;
+ AudioCodingModule* myACM;
+ WebRtc_UWord8* codecCntr;
+ bool* thereIsEncoder;
+ bool* vad;
+ bool* dtx;
+ ACMVADMode* mode;
+ Channel* myChannel;
+ EventWrapper* myEvent = EventWrapper::Create();
+ // Reset and Wait
+ if(!_randomTest)
+ {
+ fprintf(stdout, "Reset Encoder Side A \n");
+ }
+ if(side == 'A')
+ {
+ myACM = _acmA;
+ codecCntr = &_codecCntrA;
+ {
+ WriteLockScoped wl(_apiTestRWLock);
+ thereIsEncoder = &_thereIsEncoderA;
+ }
+ vad = &_sendVADA;
+ dtx = &_sendDTXA;
+ mode = &_sendVADModeA;
+ myChannel = _channel_A2B;
+ }
+ else
+ {
+ myACM = _acmB;
+ codecCntr = &_codecCntrB;
+ {
+ WriteLockScoped wl(_apiTestRWLock);
+ thereIsEncoder = &_thereIsEncoderB;
+ }
+ vad = &_sendVADB;
+ dtx = &_sendDTXB;
+ mode = &_sendVADModeB;
+ myChannel = _channel_B2A;
+ }
+
+ myACM->ResetEncoder();
+ Wait(100);
+
+ // Register the next codec
+ do
+ {
+ *codecCntr = (*codecCntr < AudioCodingModule::NumberOfCodecs() - 1)?
+ (*codecCntr + 1):0;
+
+ if(*codecCntr == 0)
+ {
+ //printf("Initialize Sender Side A \n");
+ {
+ WriteLockScoped wl(_apiTestRWLock);
+ *thereIsEncoder = false;
+ }
+ CHECK_ERROR_MT(myACM->InitializeSender());
+ Wait(1000);
+
+ // After Initialization CN is lost, re-register them
+ if(AudioCodingModule::Codec("CN", myCodec, 8000) >= 0)
+ {
+ CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
+ }
+ if(AudioCodingModule::Codec("CN", myCodec, 16000) >= 0)
+ {
+ CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
+ }
+ // VAD & DTX are disabled after initialization
+ *vad = false;
+ *dtx = false;
+ _writeToFile = false;
+ }
+
+ AudioCodingModule::Codec(*codecCntr, myCodec);
+ } while(!STR_CASE_CMP(myCodec.plname, "CN") ||
+ !STR_CASE_CMP(myCodec.plname, "telephone-event") ||
+ !STR_CASE_CMP(myCodec.plname, "RED"));
+
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n====================================================================\n");
+ fprintf(stdout, " Registering New Codec %s, %d kHz, %d kbps\n",
+ myCodec.plname, myCodec.plfreq / 1000, myCodec.rate / 1000);
+ }
+ //std::cout<< std::flush;
+
+ // NO DTX for supe-wideband codec at this point
+ if(myCodec.plfreq == 32000)
+ {
+ *dtx = false;
+ CHECK_ERROR_MT(myACM->SetVAD(*dtx, *vad, *mode));
+
+ }
+
+ CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
+ myChannel->ResetStats();
+ {
+ WriteLockScoped wl(_apiTestRWLock);
+ *thereIsEncoder = true;
+ }
+ Wait(500);
+}
+
+
+void
+APITest::LookForDTMF(char side)
+{
+ if(!_randomTest)
+ {
+ fprintf(stdout, "\n\nLooking for DTMF Signal in Side %c\n", side);
+ fprintf(stdout, "----------------------------------------\n");
+ }
+
+ if(side == 'A')
+ {
+ _acmB->RegisterIncomingMessagesCallback(NULL);
+ _acmA->RegisterIncomingMessagesCallback(_dtmfCallback);
+ Wait(1000);
+ _acmA->RegisterIncomingMessagesCallback(NULL);
+ }
+ else
+ {
+ _acmA->RegisterIncomingMessagesCallback(NULL);
+ _acmB->RegisterIncomingMessagesCallback(_dtmfCallback);
+ Wait(1000);
+ _acmB->RegisterIncomingMessagesCallback(NULL);
+ }
+}
diff --git a/src/modules/audio_coding/main/test/APITest.h b/src/modules/audio_coding/main/test/APITest.h
new file mode 100644
index 0000000..52ecb27
--- /dev/null
+++ b/src/modules/audio_coding/main/test/APITest.h
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+#ifndef API_TEST_H
+#define API_TEST_H
+
+#include "ACMTest.h"
+#include "Channel.h"
+#include "PCMFile.h"
+#include "event_wrapper.h"
+#include "utility.h"
+
+enum APITESTAction {TEST_CHANGE_CODEC_ONLY = 0, DTX_TEST = 1};
+
+class APITest : public ACMTest
+{
+public:
+ APITest();
+ ~APITest();
+
+ void Perform();
+private:
+ WebRtc_Word16 SetUp();
+
+ static bool PushAudioThreadA(void* obj);
+ static bool PullAudioThreadA(void* obj);
+ static bool ProcessThreadA(void* obj);
+ static bool APIThreadA(void* obj);
+
+ static bool PushAudioThreadB(void* obj);
+ static bool PullAudioThreadB(void* obj);
+ static bool ProcessThreadB(void* obj);
+ static bool APIThreadB(void* obj);
+
+ void CheckVADStatus(char side);
+
+ // Set Min delay, get delay, playout timestamp
+ void TestDelay(char side);
+
+ // Unregister a codec & register again.
+ void TestRegisteration(char side);
+
+ // Playout Mode, background noise mode.
+ // Receiver Frequency, playout frequency.
+ void TestPlayout(char receiveSide);
+
+ // set/get receiver VAD status & mode.
+ void TestReceiverVAD(char side);
+
+ //
+ void TestSendVAD(char side);
+
+ void CurrentCodec(char side);
+
+ void ChangeCodec(char side);
+
+ void Wait(WebRtc_UWord32 waitLengthMs);
+
+ void LookForDTMF(char side);
+
+ void RunTest(char thread);
+
+ bool PushAudioRunA();
+ bool PullAudioRunA();
+ bool ProcessRunA();
+ bool APIRunA();
+
+ bool PullAudioRunB();
+ bool PushAudioRunB();
+ bool ProcessRunB();
+ bool APIRunB();
+
+
+
+ //--- ACMs
+ AudioCodingModule* _acmA;
+ AudioCodingModule* _acmB;
+
+ //--- Channels
+ Channel* _channel_A2B;
+ Channel* _channel_B2A;
+
+ //--- I/O files
+ // A
+ PCMFile _inFileA;
+ PCMFile _outFileA;
+ // B
+ PCMFile _outFileB;
+ PCMFile _inFileB;
+
+ //--- I/O params
+ // A
+ WebRtc_Word32 _outFreqHzA;
+ // B
+ WebRtc_Word32 _outFreqHzB;
+
+ // Should we write to file.
+ // we might skip writing to file if we
+ // run the test for a long time.
+ bool _writeToFile;
+ //--- Events
+ // A
+ EventWrapper* _pullEventA; // pulling data from ACM
+ EventWrapper* _pushEventA; // pushing data to ACM
+ EventWrapper* _processEventA; // process
+ EventWrapper* _apiEventA; // API calls
+ // B
+ EventWrapper* _pullEventB; // pulling data from ACM
+ EventWrapper* _pushEventB; // pushing data to ACM
+ EventWrapper* _processEventB; // process
+ EventWrapper* _apiEventB; // API calls
+
+ // keep track of the codec in either side.
+ WebRtc_UWord8 _codecCntrA;
+ WebRtc_UWord8 _codecCntrB;
+
+ // keep track of tests
+ WebRtc_UWord8 _testCntrA;
+ WebRtc_UWord8 _testCntrB;
+
+ // Is set to true if there is no encoder in either side
+ bool _thereIsEncoderA;
+ bool _thereIsEncoderB;
+ bool _thereIsDecoderA;
+ bool _thereIsDecoderB;
+
+ bool _sendVADA;
+ bool _sendDTXA;
+ ACMVADMode _sendVADModeA;
+
+ bool _sendVADB;
+ bool _sendDTXB;
+ ACMVADMode _sendVADModeB;
+
+ WebRtc_Word32 _minDelayA;
+ WebRtc_Word32 _minDelayB;
+ bool _payloadUsed[32];
+
+ AudioPlayoutMode _playoutModeA;
+ AudioPlayoutMode _playoutModeB;
+
+ ACMBackgroundNoiseMode _bgnModeA;
+ ACMBackgroundNoiseMode _bgnModeB;
+
+
+ WebRtc_UWord64 _receiveVADActivityA[3];
+ WebRtc_UWord64 _receiveVADActivityB[3];
+ bool _verbose;
+
+ int _dotPositionA;
+ int _dotMoveDirectionA;
+ int _dotPositionB;
+ int _dotMoveDirectionB;
+
+ char _movingDot[41];
+
+ DTMFDetector* _dtmfCallback;
+ VADCallback* _vadCallbackA;
+ VADCallback* _vadCallbackB;
+ RWLockWrapper& _apiTestRWLock;
+ bool _randomTest;
+ int _testNumA;
+ int _testNumB;
+};
+
+
+#endif
diff --git a/src/modules/audio_coding/main/test/Channel.cpp b/src/modules/audio_coding/main/test/Channel.cpp
new file mode 100644
index 0000000..bf440ea
--- /dev/null
+++ b/src/modules/audio_coding/main/test/Channel.cpp
@@ -0,0 +1,481 @@
+/*
+ * 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 <assert.h>
+#include <iostream>
+
+#include "audio_coding_module.h"
+#include "Channel.h"
+#include "tick_util.h"
+#include "typedefs.h"
+#include "common_types.h"
+
+using namespace webrtc;
+
+WebRtc_Word32
+Channel::SendData(
+ const FrameType frameType,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* fragmentation)
+{
+ WebRtcRTPHeader rtpInfo;
+ WebRtc_Word32 status;
+ WebRtc_UWord16 payloadDataSize = payloadSize;
+
+ rtpInfo.header.markerBit = false;
+ rtpInfo.header.ssrc = 0;
+ rtpInfo.header.sequenceNumber = _seqNo++;
+ rtpInfo.header.payloadType = payloadType;
+ rtpInfo.header.timestamp = timeStamp;
+ if(frameType == kAudioFrameCN)
+ {
+ rtpInfo.type.Audio.isCNG = true;
+ }
+ else
+ {
+ rtpInfo.type.Audio.isCNG = false;
+ }
+ if(frameType == kFrameEmpty)
+ {
+ // Skip this frame
+ return 0;
+ }
+
+ rtpInfo.type.Audio.channel = 1;
+ // Treat fragmentation separately
+ if(fragmentation != NULL)
+ {
+ if((fragmentation->fragmentationTimeDiff[1] <= 0x3fff) && // silence for too long send only new data
+ (fragmentation->fragmentationVectorSize == 2))
+ {
+ // only 0x80 if we have multiple blocks
+ _payloadData[0] = 0x80 + fragmentation->fragmentationPlType[1];
+ WebRtc_UWord32 REDheader = (((WebRtc_UWord32)fragmentation->fragmentationTimeDiff[1]) << 10) + fragmentation->fragmentationLength[1];
+ _payloadData[1] = WebRtc_UWord8((REDheader >> 16) & 0x000000FF);
+ _payloadData[2] = WebRtc_UWord8((REDheader >> 8) & 0x000000FF);
+ _payloadData[3] = WebRtc_UWord8(REDheader & 0x000000FF);
+
+ _payloadData[4] = fragmentation->fragmentationPlType[0];
+ // copy the RED data
+ memcpy(_payloadData + 5,
+ payloadData + fragmentation->fragmentationOffset[1],
+ fragmentation->fragmentationLength[1]);
+ // copy the normal data
+ memcpy(_payloadData + 5 + fragmentation->fragmentationLength[1],
+ payloadData + fragmentation->fragmentationOffset[0],
+ fragmentation->fragmentationLength[0]);
+ payloadDataSize += 5;
+ } else
+ {
+ // single block (newest one)
+ memcpy(_payloadData,
+ payloadData + fragmentation->fragmentationOffset[0],
+ fragmentation->fragmentationLength[0]);
+ payloadDataSize = WebRtc_UWord16(fragmentation->fragmentationLength[0]);
+ rtpInfo.header.payloadType = fragmentation->fragmentationPlType[0];
+ }
+ }
+ else
+ {
+ memcpy(_payloadData, payloadData, payloadDataSize);
+ if(_isStereo)
+ {
+ if(_leftChannel)
+ {
+ memcpy(&_rtpInfo, &rtpInfo, sizeof(WebRtcRTPHeader));
+ _leftChannel = false;
+ rtpInfo.type.Audio.channel = 1;
+ }
+ else
+ {
+ memcpy(&rtpInfo, &_rtpInfo, sizeof(WebRtcRTPHeader));
+ _leftChannel = true;
+ rtpInfo.type.Audio.channel = 2;
+ }
+ }
+ }
+
+ _channelCritSect->Enter();
+ if(_saveBitStream)
+ {
+ //fwrite(payloadData, sizeof(WebRtc_UWord8), payloadSize, _bitStreamFile);
+ }
+
+ if(!_isStereo)
+ {
+ CalcStatistics(rtpInfo, payloadSize);
+ }
+ _lastInTimestamp = timeStamp;
+ _totalBytes += payloadDataSize;
+ _channelCritSect->Leave();
+
+ if(_useFECTestWithPacketLoss)
+ {
+ _packetLoss += 1;
+ if(_packetLoss == 3)
+ {
+ _packetLoss = 0;
+ return 0;
+ }
+ }
+
+
+ //status = _receiverACM->IncomingPayload((WebRtc_Word8*)_payloadData, payloadSize, payloadType, timeStamp);
+ status = _receiverACM->IncomingPacket((WebRtc_Word8*)_payloadData, payloadDataSize, rtpInfo);
+
+ //delete [] payloadData;
+
+
+
+ return status;
+}
+
+void
+Channel::CalcStatistics(
+ WebRtcRTPHeader& rtpInfo,
+ WebRtc_UWord16 payloadSize)
+{
+ int n;
+ if((rtpInfo.header.payloadType != _lastPayloadType) &&
+ (_lastPayloadType != -1))
+ {
+ // payload-type is changed.
+ // we have to terminate the calculations on the previous payload type
+ // we ignore the last packet in that payload type just to make things
+ // easier.
+ for(n = 0; n < MAX_NUM_PAYLOADS; n++)
+ {
+ if(_lastPayloadType == _payloadStats[n].payloadType)
+ {
+ _payloadStats[n].newPacket = true;
+ break;
+ }
+ }
+ }
+ _lastPayloadType = rtpInfo.header.payloadType;
+
+ bool newPayload = true;
+ ACMTestPayloadStats* currentPayloadStr;
+ for(n = 0; n < MAX_NUM_PAYLOADS; n++)
+ {
+ if(rtpInfo.header.payloadType == _payloadStats[n].payloadType)
+ {
+ newPayload = false;
+ currentPayloadStr = &_payloadStats[n];
+ break;
+ }
+ }
+
+ if(!newPayload)
+ {
+ if(!currentPayloadStr->newPacket)
+ {
+ WebRtc_UWord32 lastFrameSizeSample = (WebRtc_UWord32)((WebRtc_UWord32)rtpInfo.header.timestamp -
+ (WebRtc_UWord32)currentPayloadStr->lastTimestamp);
+ assert(lastFrameSizeSample > 0);
+ int k = 0;
+ while((currentPayloadStr->frameSizeStats[k].frameSizeSample !=
+ lastFrameSizeSample) &&
+ (currentPayloadStr->frameSizeStats[k].frameSizeSample != 0))
+ {
+ k++;
+ }
+ ACMTestFrameSizeStats* currentFrameSizeStats =
+ &(currentPayloadStr->frameSizeStats[k]);
+ currentFrameSizeStats->frameSizeSample = (WebRtc_Word16)lastFrameSizeSample;
+
+ // increment the number of encoded samples.
+ currentFrameSizeStats->totalEncodedSamples +=
+ lastFrameSizeSample;
+ // increment the number of recveived packets
+ currentFrameSizeStats->numPackets++;
+ // increment the total number of bytes (this is based on
+ // the previous payload we don't know the frame-size of
+ // the current payload.
+ currentFrameSizeStats->totalPayloadLenByte +=
+ currentPayloadStr->lastPayloadLenByte;
+ // store the maximum payload-size (this is based on
+ // the previous payload we don't know the frame-size of
+ // the current payload.
+ if(currentFrameSizeStats->maxPayloadLen <
+ currentPayloadStr->lastPayloadLenByte)
+ {
+ currentFrameSizeStats->maxPayloadLen =
+ currentPayloadStr->lastPayloadLenByte;
+ }
+ // store the current values for the next time
+ currentPayloadStr->lastTimestamp = rtpInfo.header.timestamp;
+ currentPayloadStr->lastPayloadLenByte = payloadSize;
+ }
+ else
+ {
+ currentPayloadStr->newPacket = false;
+ currentPayloadStr->lastPayloadLenByte = payloadSize;
+ currentPayloadStr->lastTimestamp = rtpInfo.header.timestamp;
+ currentPayloadStr->payloadType = rtpInfo.header.payloadType;
+ }
+ }
+ else
+ {
+ n = 0;
+ while(_payloadStats[n].payloadType != -1)
+ {
+ n++;
+ }
+ // first packet
+ _payloadStats[n].newPacket = false;
+ _payloadStats[n].lastPayloadLenByte = payloadSize;
+ _payloadStats[n].lastTimestamp = rtpInfo.header.timestamp;
+ _payloadStats[n].payloadType = rtpInfo.header.payloadType;
+ }
+}
+
+Channel::Channel(WebRtc_Word16 chID) :
+_receiverACM(NULL),
+_seqNo(0),
+_channelCritSect(CriticalSectionWrapper::CreateCriticalSection()),
+_bitStreamFile(NULL),
+_saveBitStream(false),
+_lastPayloadType(-1),
+_isStereo(false),
+_leftChannel(true),
+_useFECTestWithPacketLoss(false),
+_packetLoss(0),
+_lastInTimestamp(0),
+_chID(chID),
+_beginTime(TickTime::MillisecondTimestamp()),
+_totalBytes(0)
+{
+ int n;
+ int k;
+ for(n = 0; n < MAX_NUM_PAYLOADS; n++)
+ {
+ _payloadStats[n].payloadType = -1;
+ _payloadStats[n].newPacket = true;
+ for(k = 0; k < MAX_NUM_FRAMESIZES; k++)
+ {
+ _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
+ _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
+ _payloadStats[n].frameSizeStats[k].numPackets = 0;
+ _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
+ _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
+ }
+ }
+ if(chID >= 0)
+ {
+ _saveBitStream = true;
+ char bitStreamFileName[500];
+ sprintf(bitStreamFileName, "bitStream_%d.dat", chID);
+ _bitStreamFile = fopen(bitStreamFileName, "wb");
+ }
+ else
+ {
+ _saveBitStream = false;
+ }
+}
+
+Channel::~Channel()
+{
+ delete _channelCritSect;
+}
+
+void
+Channel::RegisterReceiverACM(AudioCodingModule* acm)
+{
+ _receiverACM = acm;
+ return;
+}
+
+void
+Channel::ResetStats()
+{
+ int n;
+ int k;
+ _channelCritSect->Enter();
+ _lastPayloadType = -1;
+ for(n = 0; n < MAX_NUM_PAYLOADS; n++)
+ {
+ _payloadStats[n].payloadType = -1;
+ _payloadStats[n].newPacket = true;
+ for(k = 0; k < MAX_NUM_FRAMESIZES; k++)
+ {
+ _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
+ _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
+ _payloadStats[n].frameSizeStats[k].numPackets = 0;
+ _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
+ _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
+ }
+ }
+ _beginTime = TickTime::MillisecondTimestamp();
+ _totalBytes = 0;
+ _channelCritSect->Leave();
+}
+
+WebRtc_Word16
+Channel::Stats(CodecInst& codecInst, ACMTestPayloadStats& payloadStats)
+{
+ _channelCritSect->Enter();
+ int n;
+ payloadStats.payloadType = -1;
+ for(n = 0; n < MAX_NUM_PAYLOADS; n++)
+ {
+ if(_payloadStats[n].payloadType == codecInst.pltype)
+ {
+ memcpy(&payloadStats, &_payloadStats[n], sizeof(ACMTestPayloadStats));
+ break;
+ }
+ }
+ if(payloadStats.payloadType == -1)
+ {
+ _channelCritSect->Leave();
+ return -1;
+ }
+ for(n = 0; n < MAX_NUM_FRAMESIZES; n++)
+ {
+ if(payloadStats.frameSizeStats[n].frameSizeSample == 0)
+ {
+ _channelCritSect->Leave();
+ return 0;
+ }
+ payloadStats.frameSizeStats[n].usageLenSec =
+ (double)payloadStats.frameSizeStats[n].totalEncodedSamples
+ / (double)codecInst.plfreq;
+
+ payloadStats.frameSizeStats[n].rateBitPerSec =
+ payloadStats.frameSizeStats[n].totalPayloadLenByte * 8 /
+ payloadStats.frameSizeStats[n].usageLenSec;
+
+ }
+ _channelCritSect->Leave();
+ return 0;
+}
+
+void
+Channel::Stats(WebRtc_UWord32* numPackets)
+{
+ _channelCritSect->Enter();
+ int k;
+ int n;
+ memset(numPackets, 0, MAX_NUM_PAYLOADS * sizeof(WebRtc_UWord32));
+ for(k = 0; k < MAX_NUM_PAYLOADS; k++)
+ {
+ if(_payloadStats[k].payloadType == -1)
+ {
+ break;
+ }
+ numPackets[k] = 0;
+ for(n = 0; n < MAX_NUM_FRAMESIZES; n++)
+ {
+ if(_payloadStats[k].frameSizeStats[n].frameSizeSample == 0)
+ {
+ break;
+ }
+ numPackets[k] +=
+ _payloadStats[k].frameSizeStats[n].numPackets;
+ }
+ }
+ _channelCritSect->Leave();
+}
+
+void
+Channel::Stats(WebRtc_UWord8* payloadType, WebRtc_UWord32* payloadLenByte)
+{
+ _channelCritSect->Enter();
+
+ int k;
+ int n;
+ memset(payloadLenByte, 0, MAX_NUM_PAYLOADS * sizeof(WebRtc_UWord32));
+ for(k = 0; k < MAX_NUM_PAYLOADS; k++)
+ {
+ if(_payloadStats[k].payloadType == -1)
+ {
+ break;
+ }
+ payloadType[k] = (WebRtc_UWord8)_payloadStats[k].payloadType;
+ payloadLenByte[k] = 0;
+ for(n = 0; n < MAX_NUM_FRAMESIZES; n++)
+ {
+ if(_payloadStats[k].frameSizeStats[n].frameSizeSample == 0)
+ {
+ break;
+ }
+ payloadLenByte[k] += (WebRtc_UWord16)
+ _payloadStats[k].frameSizeStats[n].totalPayloadLenByte;
+ }
+ }
+
+ _channelCritSect->Leave();
+}
+
+
+void
+Channel::PrintStats(CodecInst& codecInst)
+{
+ ACMTestPayloadStats payloadStats;
+ Stats(codecInst, payloadStats);
+ printf("%s %d kHz\n",
+ codecInst.plname,
+ codecInst.plfreq / 1000);
+ printf("=====================================================\n");
+ if(payloadStats.payloadType == -1)
+ {
+ printf("No Packets are sent with payload-type %d (%s)\n\n",
+ codecInst.pltype,
+ codecInst.plname);
+ return;
+ }
+ for(int k = 0; k < MAX_NUM_FRAMESIZES; k++)
+ {
+ if(payloadStats.frameSizeStats[k].frameSizeSample == 0)
+ {
+ break;
+ }
+ printf("Frame-size.................... %d samples\n",
+ payloadStats.frameSizeStats[k].frameSizeSample);
+ printf("Average Rate.................. %.0f bits/sec\n",
+ payloadStats.frameSizeStats[k].rateBitPerSec);
+ printf("Maximum Payload-Size.......... %d Bytes\n",
+ payloadStats.frameSizeStats[k].maxPayloadLen);
+ printf("Maximum Instantaneous Rate.... %.0f bits/sec\n",
+ ((double)payloadStats.frameSizeStats[k].maxPayloadLen * 8.0 *
+ (double)codecInst.plfreq) /
+ (double)payloadStats.frameSizeStats[k].frameSizeSample);
+ printf("Number of Packets............. %u\n",
+ (unsigned int)payloadStats.frameSizeStats[k].numPackets);
+ printf("Duration...................... %0.3f sec\n\n",
+ payloadStats.frameSizeStats[k].usageLenSec);
+
+ }
+
+}
+
+WebRtc_UWord32
+Channel::LastInTimestamp()
+{
+ WebRtc_UWord32 timestamp;
+ _channelCritSect->Enter();
+ timestamp = _lastInTimestamp;
+ _channelCritSect->Leave();
+ return timestamp;
+}
+
+double
+Channel::BitRate()
+{
+ double rate;
+ WebRtc_UWord64 currTime = TickTime::MillisecondTimestamp();
+ _channelCritSect->Enter();
+ rate = ((double)_totalBytes * 8.0)/ (double)(currTime - _beginTime);
+ _channelCritSect->Leave();
+ return rate;
+}
diff --git a/src/modules/audio_coding/main/test/Channel.h b/src/modules/audio_coding/main/test/Channel.h
new file mode 100644
index 0000000..396fadc
--- /dev/null
+++ b/src/modules/audio_coding/main/test/Channel.h
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#ifndef CHANNEL_H
+#define CHANNEL_H
+
+#include <stdio.h>
+
+#include "audio_coding_module.h"
+#include "critical_section_wrapper.h"
+#include "rw_lock_wrapper.h"
+
+
+#define MAX_NUM_PAYLOADS 50
+#define MAX_NUM_FRAMESIZES 6
+
+
+struct ACMTestFrameSizeStats
+{
+ WebRtc_UWord16 frameSizeSample;
+ WebRtc_Word16 maxPayloadLen;
+ WebRtc_UWord32 numPackets;
+ WebRtc_UWord64 totalPayloadLenByte;
+ WebRtc_UWord64 totalEncodedSamples;
+ double rateBitPerSec;
+ double usageLenSec;
+
+};
+
+struct ACMTestPayloadStats
+{
+ bool newPacket;
+ WebRtc_Word16 payloadType;
+ WebRtc_Word16 lastPayloadLenByte;
+ WebRtc_UWord32 lastTimestamp;
+ ACMTestFrameSizeStats frameSizeStats[MAX_NUM_FRAMESIZES];
+};
+
+using namespace webrtc;
+
+class Channel: public AudioPacketizationCallback
+{
+public:
+
+ Channel(
+ WebRtc_Word16 chID = -1);
+ ~Channel();
+
+ WebRtc_Word32 SendData(
+ const FrameType frameType,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* fragmentation);
+
+ void RegisterReceiverACM(
+ AudioCodingModule *acm);
+
+ void ResetStats();
+
+ WebRtc_Word16 Stats(
+ CodecInst& codecInst,
+ ACMTestPayloadStats& payloadStats);
+
+ void Stats(
+ WebRtc_UWord32* numPackets);
+
+ void Stats(
+ WebRtc_UWord8* payloadLenByte,
+ WebRtc_UWord32* payloadType);
+
+ void PrintStats(
+ CodecInst& codecInst);
+
+ void SetIsStereo(bool isStereo)
+ {
+ _isStereo = isStereo;
+ }
+
+ WebRtc_UWord32 LastInTimestamp();
+
+ void SetFECTestWithPacketLoss(bool usePacketLoss)
+ {
+ _useFECTestWithPacketLoss = usePacketLoss;
+ }
+
+ double BitRate();
+
+private:
+ void CalcStatistics(
+ WebRtcRTPHeader& rtpInfo,
+ WebRtc_UWord16 payloadSize);
+
+ AudioCodingModule* _receiverACM;
+ WebRtc_UWord16 _seqNo;
+ // 60 msec * 32 sample (max) / msec * 2 description (maybe) * 2 bytes / sample
+ WebRtc_UWord8 _payloadData[60 * 32 * 2 * 2];
+
+ CriticalSectionWrapper* _channelCritSect;
+ FILE* _bitStreamFile;
+ bool _saveBitStream;
+ WebRtc_Word16 _lastPayloadType;
+ ACMTestPayloadStats _payloadStats[MAX_NUM_PAYLOADS];
+ bool _isStereo;
+ WebRtcRTPHeader _rtpInfo;
+ bool _leftChannel;
+ WebRtc_UWord32 _lastInTimestamp;
+ // FEC Test variables
+ WebRtc_Word16 _packetLoss;
+ bool _useFECTestWithPacketLoss;
+ WebRtc_Word16 _chID;
+ WebRtc_UWord64 _beginTime;
+ WebRtc_UWord64 _totalBytes;
+};
+
+
+#endif
diff --git a/src/modules/audio_coding/main/test/EncodeDecodeTest.cpp b/src/modules/audio_coding/main/test/EncodeDecodeTest.cpp
new file mode 100644
index 0000000..08555da
--- /dev/null
+++ b/src/modules/audio_coding/main/test/EncodeDecodeTest.cpp
@@ -0,0 +1,303 @@
+/*
+ * 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 "EncodeDecodeTest.h"
+#include "common_types.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "trace.h"
+#include "utility.h"
+
+Receiver::Receiver()
+:
+_playoutLengthSmpls(WEBRTC_10MS_PCM_AUDIO),
+_payloadSizeBytes(MAX_INCOMING_PAYLOAD)
+{
+}
+
+void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream)
+{
+ struct CodecInst recvCodec;
+ int noOfCodecs;
+ acm->InitializeReceiver();
+
+ noOfCodecs = acm->NumberOfCodecs();
+ for (int i=0; i < noOfCodecs; i++)
+ {
+ acm->Codec((WebRtc_UWord8)i, recvCodec);
+ if (acm->RegisterReceiveCodec(recvCodec) != 0)
+ {
+ printf("Unable to register codec: for run: codecId: %d\n", codeId);
+ exit(1);
+ }
+ }
+
+ char filename[128];
+ _rtpStream = rtpStream;
+ int playSampFreq;
+
+ if (testMode == 1)
+ {
+ playSampFreq=recvCodec.plfreq;
+ //output file for current run
+ sprintf(filename,"./modules/audio_coding/main/test/res_tests/out%dFile.pcm",codeId);
+ _pcmFile.Open(filename, recvCodec.plfreq, "wb+");
+ }
+ else if (testMode == 0)
+ {
+ playSampFreq=32000;
+ //output file for current run
+ sprintf(filename,"./modules/audio_coding/main/test/res_autotests/encodeDecode_out%d.pcm",codeId);
+ _pcmFile.Open(filename, 32000/*recvCodec.plfreq*/, "wb+");
+ }
+ else
+ {
+ printf("\nValid output frequencies:\n");
+ printf("8000\n16000\n32000\n-1, which means output freq equal to received signal freq");
+ printf("\n\nChoose output sampling frequency: ");
+ scanf("%d", &playSampFreq);
+ char fileName[] = "./modules/audio_coding/main/test/outFile.pcm";
+ _pcmFile.Open(fileName, 32000, "wb+");
+ }
+
+ _realPayloadSizeBytes = 0;
+ _playoutBuffer = new WebRtc_Word16[WEBRTC_10MS_PCM_AUDIO];
+ _frequency = playSampFreq;
+ _acm = acm;
+ _firstTime = true;
+}
+
+void Receiver::Teardown()
+{
+ delete [] _playoutBuffer;
+ _pcmFile.Close();
+ if (testMode > 1) Trace::ReturnTrace();
+}
+
+bool Receiver::IncomingPacket()
+{
+ if (!_rtpStream->EndOfFile())
+ {
+ if (_firstTime)
+ {
+ _firstTime = false;
+ _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload, _payloadSizeBytes, &_nextTime);
+ if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile())
+ {
+ _firstTime = true;
+ return true;
+ }
+ }
+
+ WebRtc_Word32 ok = _acm->IncomingPacket(_incomingPayload, _realPayloadSizeBytes, _rtpInfo);
+ if (ok != 0)
+ {
+ printf("Error when inserting packet to ACM, for run: codecId: %d\n", codeId);
+ exit(1);
+ }
+ _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload, _payloadSizeBytes, &_nextTime);
+ if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile())
+ {
+ _firstTime = true;
+ }
+ }
+ return true;
+}
+
+bool Receiver::PlayoutData()
+{
+ AudioFrame audioFrame;
+
+ if (_acm->PlayoutData10Ms(_frequency, audioFrame) != 0)
+ {
+ printf("Error when calling PlayoutData10Ms, for run: codecId: %d\n", codeId);
+ exit(1);
+ }
+ if (_playoutLengthSmpls == 0)
+ {
+ return false;
+ }
+ _pcmFile.Write10MsData(audioFrame._payloadData, audioFrame._payloadDataLengthInSamples);
+ return true;
+}
+
+void Receiver::Run()
+{
+ WebRtc_UWord8 counter500Ms = 50;
+
+ WebRtc_UWord32 clock = 0;
+
+ while (counter500Ms > 0)
+ {
+ if (clock == 0 || clock >= _nextTime)
+ {
+ IncomingPacket();
+ if (clock == 0)
+ {
+ clock = _nextTime;
+ }
+ }
+ if ((clock % 10) == 0)
+ {
+ if (!PlayoutData())
+ {
+ clock++;
+ continue;
+ }
+ }
+ if (_rtpStream->EndOfFile())
+ {
+ counter500Ms--;
+ }
+ clock++;
+ }
+}
+
+EncodeDecodeTest::EncodeDecodeTest()
+{
+ _testMode = 2;
+ Trace::CreateTrace();
+ Trace::SetTraceFile("acm_encdec_test.txt");
+}
+
+EncodeDecodeTest::EncodeDecodeTest(int testMode)
+{
+ //testMode == 0 for autotest
+ //testMode == 1 for testing all codecs/parameters
+ //testMode > 1 for specific user-input test (as it was used before)
+ _testMode = testMode;
+ if(_testMode != 0)
+ {
+ Trace::CreateTrace();
+ Trace::SetTraceFile("acm_encdec_test.txt");
+ }
+}
+void EncodeDecodeTest::Perform()
+{
+
+ if(_testMode == 0)
+ {
+ printf("Running Encode/Decode Test");
+ WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, "---------- EncodeDecodeTest ----------");
+ }
+
+ int numCodecs = 1;
+ int codePars[3]; //freq, pacsize, rate
+ int playoutFreq[3]; //8, 16, 32k
+
+ int numPars[52]; //number of codec parameters sets (rate,freq,pacsize)to test, for a given codec
+
+ codePars[0]=0;
+ codePars[1]=0;
+ codePars[2]=0;
+
+ if (_testMode == 1)
+ {
+ AudioCodingModule *acmTmp = AudioCodingModule::Create(0);
+ struct CodecInst sendCodecTmp;
+ numCodecs = acmTmp->NumberOfCodecs();
+ printf("List of supported codec.\n");
+ for(int n = 0; n < numCodecs; n++)
+ {
+ acmTmp->Codec(n, sendCodecTmp);
+ if (STR_CASE_CMP(sendCodecTmp.plname, "telephone-event") == 0) {
+ numPars[n] = 0;
+ } else if (STR_CASE_CMP(sendCodecTmp.plname, "cn") == 0) {
+ numPars[n] = 0;
+ } else if (STR_CASE_CMP(sendCodecTmp.plname, "red") == 0) {
+ numPars[n] = 0;
+ } else {
+ numPars[n] = 1;
+ printf("%d %s\n", n, sendCodecTmp.plname);
+ }
+ }
+ AudioCodingModule::Destroy(acmTmp);
+ playoutFreq[1]=16000;
+ }
+ else if (_testMode == 0)
+ {
+ AudioCodingModule *acmTmp = AudioCodingModule::Create(0);
+ numCodecs = acmTmp->NumberOfCodecs();
+ AudioCodingModule::Destroy(acmTmp);
+ struct CodecInst dummyCodec;
+
+ //chose range of testing for codecs/parameters
+ for(int i = 0 ; i < numCodecs ; i++)
+ {
+ numPars[i] = 1;
+ acmTmp->Codec(i, dummyCodec);
+ if (STR_CASE_CMP(dummyCodec.plname, "telephone-event") == 0)
+ {
+ numPars[i] = 0;
+ } else if (STR_CASE_CMP(dummyCodec.plname, "cn") == 0) {
+ numPars[i] = 0;
+ } else if (STR_CASE_CMP(dummyCodec.plname, "red") == 0) {
+ numPars[i] = 0;
+ }
+ }
+ playoutFreq[1] = 16000;
+ }
+ else
+ {
+ numCodecs = 1;
+ numPars[0] = 1;
+ playoutFreq[1]=16000;
+ }
+
+ _receiver.testMode = _testMode;
+
+ //loop over all codecs:
+ for(int codeId=0;codeId<numCodecs;codeId++)
+ {
+ //only encode using real encoders, not telephone-event anc cn
+ for(int loopPars=1;loopPars<=numPars[codeId];loopPars++)
+ {
+ if (_testMode == 1)
+ {
+ printf("\n");
+ printf("***FOR RUN: codeId: %d\n",codeId);
+ printf("\n");
+ }
+ else if (_testMode == 0)
+ {
+ printf(".");
+ }
+
+ EncodeToFileTest::Perform(1, codeId, codePars, _testMode);
+
+ AudioCodingModule *acm = AudioCodingModule::Create(10);
+ RTPFile rtpFile;
+ char fileName[] = "outFile.rtp";
+ rtpFile.Open(fileName, "rb");
+
+ _receiver.codeId = codeId;
+
+ rtpFile.ReadHeader();
+ _receiver.Setup(acm, &rtpFile);
+ _receiver.Run();
+ _receiver.Teardown();
+ rtpFile.Close();
+ AudioCodingModule::Destroy(acm);
+
+ if (_testMode == 1)
+ {
+ printf("***COMPLETED RUN FOR: codecID: %d ***\n",
+ codeId);
+ }
+ }
+ }
+ if (_testMode == 0)
+ {
+ printf("Done!\n");
+ }
+ if (_testMode == 1) Trace::ReturnTrace();
+}
+
diff --git a/src/modules/audio_coding/main/test/EncodeDecodeTest.h b/src/modules/audio_coding/main/test/EncodeDecodeTest.h
new file mode 100644
index 0000000..01172f3
--- /dev/null
+++ b/src/modules/audio_coding/main/test/EncodeDecodeTest.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef ENCODEDECODETEST_H
+#define ENCODEDECODETEST_H
+
+#include "EncodeToFileTest.h"
+
+#define MAX_INCOMING_PAYLOAD 8096
+#include "audio_coding_module.h"
+
+class Receiver
+{
+public:
+ Receiver();
+ void Setup(AudioCodingModule *acm, RTPStream *rtpStream);
+ void Teardown();
+ void Run();
+ bool IncomingPacket();
+ bool PlayoutData();
+
+ //for auto_test and logging
+ WebRtc_UWord8 codeId;
+ WebRtc_UWord8 testMode;
+
+private:
+ AudioCodingModule* _acm;
+ bool _rtpEOF;
+ RTPStream* _rtpStream;
+ PCMFile _pcmFile;
+ WebRtc_Word16* _playoutBuffer;
+ WebRtc_UWord16 _playoutLengthSmpls;
+ WebRtc_Word8 _incomingPayload[MAX_INCOMING_PAYLOAD];
+ WebRtc_UWord16 _payloadSizeBytes;
+ WebRtc_UWord16 _realPayloadSizeBytes;
+ WebRtc_Word32 _frequency;
+ bool _firstTime;
+ WebRtcRTPHeader _rtpInfo;
+ WebRtc_UWord32 _nextTime;
+};
+
+class EncodeDecodeTest : public EncodeToFileTest
+{
+public:
+ EncodeDecodeTest();
+ EncodeDecodeTest(int testMode);
+ virtual void Perform();
+ WebRtc_UWord16 _playoutFreq;
+ WebRtc_UWord8 _testMode;
+protected:
+ Receiver _receiver;
+};
+
+
+
+#endif
+
diff --git a/src/modules/audio_coding/main/test/EncodeToFileTest.cpp b/src/modules/audio_coding/main/test/EncodeToFileTest.cpp
new file mode 100644
index 0000000..6eed2ea
--- /dev/null
+++ b/src/modules/audio_coding/main/test/EncodeToFileTest.cpp
@@ -0,0 +1,188 @@
+/*
+ * 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 "EncodeToFileTest.h"
+#include "audio_coding_module.h"
+#include "common_types.h"
+
+#ifdef WIN32
+# include <Winsock2.h>
+#else
+# include <arpa/inet.h>
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+TestPacketization::TestPacketization(RTPStream *rtpStream, WebRtc_UWord16 frequency)
+:
+_frequency(frequency),
+_seqNo(0)
+{
+ _rtpStream = rtpStream;
+}
+
+TestPacketization::~TestPacketization()
+{
+}
+
+WebRtc_Word32 TestPacketization::SendData(
+ const FrameType /* frameType */,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* /* fragmentation */)
+{
+ _rtpStream->Write(payloadType, timeStamp, _seqNo++, payloadData, payloadSize, _frequency);
+ //delete [] payloadData;
+ return 1;
+}
+
+Sender::Sender()
+:
+_acm(NULL),
+//_payloadData(NULL),
+_payloadSize(0),
+_timeStamp(0)
+{
+}
+
+void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream)
+{
+ acm->InitializeSender();
+ struct CodecInst sendCodec;
+ int noOfCodecs = acm->NumberOfCodecs();
+ int codecNo;
+
+ if (testMode == 1)
+ {
+ //set the codec, input file, and parameters for the current test
+ codecNo = codeId;
+ //use same input file for now
+ char fileName[] = "./modules/audio_coding/main/test/testfile32kHz.pcm";
+ _pcmFile.Open(fileName, 32000, "rb");
+ }
+ else if (testMode == 0)
+ {
+ //set the codec, input file, and parameters for the current test
+ codecNo = codeId;
+ acm->Codec(codecNo, sendCodec);
+ //use same input file for now
+ char fileName[] = "./modules/audio_coding/main/test/testfile32kHz.pcm";
+ _pcmFile.Open(fileName, 32000, "rb");
+ }
+ else
+ {
+ printf("List of supported codec.\n");
+ for(int n = 0; n < noOfCodecs; n++)
+ {
+ acm->Codec(n, sendCodec);
+ printf("%d %s\n", n, sendCodec.plname);
+ }
+ printf("Choose your codec:");
+
+ scanf("%d", &codecNo);
+ char fileName[] = "./modules/audio_coding/main/test/testfile32kHz.pcm";
+ _pcmFile.Open(fileName, 32000, "rb");
+ }
+
+ acm->Codec(codecNo, sendCodec);
+ acm->RegisterSendCodec(sendCodec);
+ _packetization = new TestPacketization(rtpStream, sendCodec.plfreq);
+ if(acm->RegisterTransportCallback(_packetization) < 0)
+ {
+ printf("Registering Transport Callback failed, for run: codecId: %d: --\n",
+ codeId);
+ }
+
+ _acm = acm;
+}
+
+void Sender::Teardown()
+{
+ _pcmFile.Close();
+ delete _packetization;
+}
+
+bool Sender::Add10MsData()
+{
+ if (!_pcmFile.EndOfFile())
+ {
+ _pcmFile.Read10MsData(_audioFrame);
+ WebRtc_Word32 ok = _acm->Add10MsData(_audioFrame);
+ if (ok != 0)
+ {
+ printf("Error calling Add10MsData: for run: codecId: %d\n",
+ codeId);
+ exit(1);
+ }
+ //_audioFrame._timeStamp += _pcmFile.PayloadLength10Ms();
+ return true;
+ }
+ return false;
+}
+
+bool Sender::Process()
+{
+ WebRtc_Word32 ok = _acm->Process();
+ if (ok < 0)
+ {
+ printf("Error calling Add10MsData: for run: codecId: %d\n",
+ codeId);
+ exit(1);
+ }
+ return true;
+}
+
+void Sender::Run()
+{
+ while (true)
+ {
+ if (!Add10MsData())
+ {
+ break;
+ }
+ if (!Process()) // This could be done in a processing thread
+ {
+ break;
+ }
+ }
+}
+
+EncodeToFileTest::EncodeToFileTest()
+{
+}
+
+
+void EncodeToFileTest::Perform(int fileType, int codeId, int* codePars, int testMode)
+{
+ AudioCodingModule *acm = AudioCodingModule::Create(0);
+ RTPFile rtpFile;
+ char fileName[] = "outFile.rtp";
+ rtpFile.Open(fileName, "wb+");
+ rtpFile.WriteHeader();
+
+ //for auto_test and logging
+ _sender.testMode = testMode;
+ _sender.codeId = codeId;
+
+ _sender.Setup(acm, &rtpFile);
+ struct CodecInst sendCodecInst;
+ if(acm->SendCodec(sendCodecInst) >= 0)
+ {
+ _sender.Run();
+ }
+ _sender.Teardown();
+ rtpFile.Close();
+ AudioCodingModule::Destroy(acm);
+}
diff --git a/src/modules/audio_coding/main/test/EncodeToFileTest.h b/src/modules/audio_coding/main/test/EncodeToFileTest.h
new file mode 100644
index 0000000..fdd3804
--- /dev/null
+++ b/src/modules/audio_coding/main/test/EncodeToFileTest.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#ifndef ENCODETOFILETEST_H
+#define ENCODETOFILETEST_H
+
+#include "ACMTest.h"
+#include "audio_coding_module.h"
+#include "typedefs.h"
+#include "RTPFile.h"
+#include "PCMFile.h"
+#include <stdio.h>
+
+using namespace webrtc;
+
+// TestPacketization callback which writes the encoded payloads to file
+class TestPacketization : public AudioPacketizationCallback
+{
+public:
+ TestPacketization(RTPStream *rtpStream, WebRtc_UWord16 frequency);
+ ~TestPacketization();
+ virtual WebRtc_Word32 SendData(const FrameType frameType,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* fragmentation);
+
+private:
+ static void MakeRTPheader(WebRtc_UWord8* rtpHeader,
+ WebRtc_UWord8 payloadType, WebRtc_Word16 seqNo,
+ WebRtc_UWord32 timeStamp, WebRtc_UWord32 ssrc);
+ RTPStream* _rtpStream;
+ WebRtc_Word32 _frequency;
+ WebRtc_Word16 _seqNo;
+};
+
+class Sender
+{
+public:
+ Sender();
+ void Setup(AudioCodingModule *acm, RTPStream *rtpStream);
+ void Teardown();
+ void Run();
+ bool Add10MsData();
+ bool Process();
+
+ //for auto_test and logging
+ WebRtc_UWord8 testMode;
+ WebRtc_UWord8 codeId;
+
+private:
+ AudioCodingModule* _acm;
+ PCMFile _pcmFile;
+ //WebRtc_Word16* _payloadData;
+ AudioFrame _audioFrame;
+ WebRtc_UWord16 _payloadSize;
+ WebRtc_UWord32 _timeStamp;
+ TestPacketization* _packetization;
+};
+
+// Test class
+class EncodeToFileTest : public ACMTest
+{
+public:
+ EncodeToFileTest();
+ virtual void Perform(int fileType, int codeId, int* codePars, int testMode);
+protected:
+ Sender _sender;
+};
+
+#endif
diff --git a/src/modules/audio_coding/main/test/PCMFile.cpp b/src/modules/audio_coding/main/test/PCMFile.cpp
new file mode 100644
index 0000000..7418a3e
--- /dev/null
+++ b/src/modules/audio_coding/main/test/PCMFile.cpp
@@ -0,0 +1,300 @@
+/*
+ * 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 <cctype>
+#include <stdio.h>
+#include <string.h>
+
+
+#include "PCMFile.h"
+#include "module_common_types.h"
+
+#define MAX_FILE_NAME_LENGTH_BYTE 500
+
+
+
+PCMFile::PCMFile():
+_pcmFile(NULL),
+_nSamples10Ms(160),
+_frequency(16000),
+_endOfFile(false),
+_autoRewind(false),
+_rewinded(false),
+_timestamp(0),
+_readStereo(false),
+_saveStereo(false)
+{
+ _timestamp = (((WebRtc_UWord32)rand() & 0x0000FFFF) << 16) |
+ ((WebRtc_UWord32)rand() & 0x0000FFFF);
+}
+
+/*
+PCMFile::~PCMFile()
+{
+ if(_pcmFile != NULL)
+ {
+ fclose(_pcmFile);
+ _pcmFile = NULL;
+ }
+}
+*/
+
+WebRtc_Word16
+PCMFile::ChooseFile(
+ char* fileName,
+ WebRtc_Word16 maxLen)
+{
+ WebRtc_Word8 tmpName[MAX_FILE_NAME_LENGTH_BYTE];
+ //strcpy(_fileName, "in.pcm");
+ //printf("\n\nPlease enter the input file: ");
+ fgets(tmpName, MAX_FILE_NAME_LENGTH_BYTE, stdin);
+ 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);
+ }
+ return 0;
+}
+
+WebRtc_Word16
+PCMFile::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: ");
+ fgets(tmpName, MAX_FILE_NAME_LENGTH_BYTE, stdin);
+ 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);
+ fgets(tmpName, 10, stdin);
+ WebRtc_UWord16 tmpFreq = (WebRtc_UWord16)atoi(tmpName);
+ if(tmpFreq > 0)
+ {
+ *frequencyHz = tmpFreq;
+ }
+ return 0;
+}
+
+void
+PCMFile::Open(
+ char* filename,
+ WebRtc_UWord16 frequency,
+ const char* mode,
+ bool autoRewind)
+{
+ if ((_pcmFile = fopen(filename, mode)) == NULL)
+ {
+ printf("Cannot open file %s.\n", filename);
+ throw "Unable to read file";
+ exit(1);
+ }
+ _frequency = frequency;
+ _nSamples10Ms = (WebRtc_UWord16)(_frequency / 100);
+ _autoRewind = autoRewind;
+ _endOfFile = false;
+ _rewinded = false;
+}
+
+WebRtc_Word32
+PCMFile::SamplingFrequency() const
+{
+ return _frequency;
+}
+
+WebRtc_UWord16
+PCMFile::PayloadLength10Ms() const
+{
+ return _nSamples10Ms;
+}
+
+WebRtc_Word32
+PCMFile::Read10MsData(
+ AudioFrame& audioFrame)
+{
+ WebRtc_UWord16 noChannels = 1;
+ if (_readStereo)
+ {
+ noChannels = 2;
+ }
+
+ WebRtc_Word32 payloadSize = (WebRtc_Word32)fread(audioFrame._payloadData, sizeof(WebRtc_UWord16), _nSamples10Ms*noChannels, _pcmFile);
+ if (payloadSize < _nSamples10Ms*noChannels) {
+ for (int k = payloadSize; k < _nSamples10Ms*noChannels; k++)
+ {
+ audioFrame._payloadData[k] = 0;
+ }
+ if(_autoRewind)
+ {
+ rewind(_pcmFile);
+ _rewinded = true;
+ }
+ else
+ {
+ _endOfFile = true;
+ }
+ }
+ audioFrame._payloadDataLengthInSamples = _nSamples10Ms;
+ audioFrame._frequencyInHz = _frequency;
+ audioFrame._audioChannel = noChannels;
+ audioFrame._timeStamp = _timestamp;
+ _timestamp += _nSamples10Ms;
+ return _nSamples10Ms;
+}
+
+void
+PCMFile::Write10MsData(
+ AudioFrame& audioFrame)
+{
+ if(audioFrame._audioChannel == 1)
+ {
+ if(!_saveStereo)
+ {
+ fwrite(audioFrame._payloadData, sizeof(WebRtc_UWord16),
+ audioFrame._payloadDataLengthInSamples, _pcmFile);
+ }
+ else
+ {
+ WebRtc_Word16* stereoAudio = new WebRtc_Word16[2 *
+ audioFrame._payloadDataLengthInSamples];
+ int k;
+ for(k = 0; k < audioFrame._payloadDataLengthInSamples; k++)
+ {
+ stereoAudio[k<<1] = audioFrame._payloadData[k];
+ stereoAudio[(k<<1) + 1] = audioFrame._payloadData[k];
+ }
+ fwrite(stereoAudio, sizeof(WebRtc_Word16), 2*audioFrame._payloadDataLengthInSamples,
+ _pcmFile);
+ delete [] stereoAudio;
+ }
+ }
+ else
+ {
+ fwrite(audioFrame._payloadData, sizeof(WebRtc_Word16),
+ audioFrame._audioChannel * audioFrame._payloadDataLengthInSamples, _pcmFile);
+ }
+}
+
+
+void
+PCMFile::Write10MsData(
+ WebRtc_Word16* playoutBuffer,
+ WebRtc_UWord16 playoutLengthSmpls)
+{
+ fwrite(playoutBuffer, sizeof(WebRtc_UWord16), playoutLengthSmpls, _pcmFile);
+}
+
+
+void
+PCMFile::Close()
+{
+ fclose(_pcmFile);
+ _pcmFile = NULL;
+}
+
+void
+PCMFile::Rewind()
+{
+ rewind(_pcmFile);
+ _endOfFile = false;
+}
+
+bool
+PCMFile::Rewinded()
+{
+ return _rewinded;
+}
+
+void
+PCMFile::SaveStereo(
+ bool saveStereo)
+{
+ _saveStereo = saveStereo;
+}
+
+void
+PCMFile::ReadStereo(
+ bool readStereo)
+{
+ _readStereo = readStereo;
+}
diff --git a/src/modules/audio_coding/main/test/PCMFile.h b/src/modules/audio_coding/main/test/PCMFile.h
new file mode 100644
index 0000000..dd8d06f
--- /dev/null
+++ b/src/modules/audio_coding/main/test/PCMFile.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#ifndef PCMFILE_H
+#define PCMFILE_H
+
+#include "typedefs.h"
+#include "module_common_types.h"
+#include <cstdio>
+#include <cstdlib>
+
+// class PCMStream
+// {
+// protected:
+// PCMStream(){}
+// ~PCMStream(){}
+// public:
+// virtual WebRtc_Word32 Read10MsData(AudioFrame& audioFrame) = 0;
+// virtual void Write10MsData(WebRtc_Word16 *playoutBuffer, WebRtc_UWord16 playoutLengthSmpls) = 0;
+// virtual WebRtc_UWord16 PayloadLength10Ms() const = 0;
+// virtual WebRtc_Word32 SamplingFrequency() const = 0;
+// };
+
+
+using namespace webrtc;
+
+class PCMFile /*: public PCMStream*/
+{
+public:
+ PCMFile();
+ ~PCMFile()
+ {
+ if(_pcmFile != NULL)
+ {
+ fclose(_pcmFile);
+ }
+ }
+ void Open(char *filename, WebRtc_UWord16 frequency, const char *mode, bool autoRewind = false);
+
+ WebRtc_Word32 Read10MsData(AudioFrame& audioFrame);
+
+ void Write10MsData(WebRtc_Word16 *playoutBuffer, WebRtc_UWord16 playoutLengthSmpls);
+ void Write10MsData(AudioFrame& audioFrame);
+
+ WebRtc_UWord16 PayloadLength10Ms() const;
+ WebRtc_Word32 SamplingFrequency() const;
+ void Close();
+ bool EndOfFile() const { return _endOfFile; }
+ void Rewind();
+ static WebRtc_Word16 ChooseFile(char* fileName, WebRtc_Word16 maxLen, WebRtc_UWord16* frequencyHz);
+ static WebRtc_Word16 ChooseFile(char* fileName, WebRtc_Word16 maxLen);
+ bool Rewinded();
+ void SaveStereo(
+ bool saveStereo = true);
+ void ReadStereo(
+ bool readStereo = true);
+private:
+ FILE* _pcmFile;
+ WebRtc_UWord16 _nSamples10Ms;
+ WebRtc_Word32 _frequency;
+ bool _endOfFile;
+ bool _autoRewind;
+ bool _rewinded;
+ WebRtc_UWord32 _timestamp;
+ bool _saveStereo;
+ bool _readStereo;
+};
+
+#endif
diff --git a/src/modules/audio_coding/main/test/RTPFile.cpp b/src/modules/audio_coding/main/test/RTPFile.cpp
new file mode 100644
index 0000000..23d78d7
--- /dev/null
+++ b/src/modules/audio_coding/main/test/RTPFile.cpp
@@ -0,0 +1,297 @@
+/*
+ * 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 "RTPFile.h"
+#include "rw_lock_wrapper.h"
+#include "engine_configurations.h"
+#include <stdlib.h>
+
+#ifdef WIN32
+# include <Winsock2.h>
+#else
+# include <arpa/inet.h>
+#endif
+
+#include "audio_coding_module.h"
+
+void RTPStream::ParseRTPHeader(WebRtcRTPHeader* rtpInfo, const WebRtc_UWord8* rtpHeader)
+{
+ rtpInfo->header.payloadType = rtpHeader[1];
+ rtpInfo->header.sequenceNumber = (static_cast<WebRtc_UWord16>(rtpHeader[2])<<8) | rtpHeader[3];
+ rtpInfo->header.timestamp = (static_cast<WebRtc_UWord32>(rtpHeader[4])<<24) |
+ (static_cast<WebRtc_UWord32>(rtpHeader[5])<<16) |
+ (static_cast<WebRtc_UWord32>(rtpHeader[6])<<8) |
+ rtpHeader[7];
+ rtpInfo->header.ssrc = (static_cast<WebRtc_UWord32>(rtpHeader[8])<<24) |
+ (static_cast<WebRtc_UWord32>(rtpHeader[9])<<16) |
+ (static_cast<WebRtc_UWord32>(rtpHeader[10])<<8) |
+ rtpHeader[11];
+}
+
+void RTPStream::MakeRTPheader(WebRtc_UWord8* rtpHeader,
+ WebRtc_UWord8 payloadType, WebRtc_Word16 seqNo,
+ WebRtc_UWord32 timeStamp, WebRtc_UWord32 ssrc)
+{
+ rtpHeader[0]=(unsigned char)0x80;
+ rtpHeader[1]=(unsigned char)(payloadType & 0xFF);
+ rtpHeader[2]=(unsigned char)((seqNo>>8)&0xFF);
+ rtpHeader[3]=(unsigned char)((seqNo)&0xFF);
+ rtpHeader[4]=(unsigned char)((timeStamp>>24)&0xFF);
+ rtpHeader[5]=(unsigned char)((timeStamp>>16)&0xFF);
+
+ rtpHeader[6]=(unsigned char)((timeStamp>>8)&0xFF);
+ rtpHeader[7]=(unsigned char)(timeStamp & 0xFF);
+
+ rtpHeader[8]=(unsigned char)((ssrc>>24)&0xFF);
+ rtpHeader[9]=(unsigned char)((ssrc>>16)&0xFF);
+
+ rtpHeader[10]=(unsigned char)((ssrc>>8)&0xFF);
+ rtpHeader[11]=(unsigned char)(ssrc & 0xFF);
+}
+
+
+RTPPacket::RTPPacket(WebRtc_UWord8 payloadType, WebRtc_UWord32 timeStamp,
+ WebRtc_Word16 seqNo, const WebRtc_UWord8* payloadData,
+ WebRtc_UWord16 payloadSize, WebRtc_UWord32 frequency)
+ :
+payloadType(payloadType),
+timeStamp(timeStamp),
+seqNo(seqNo),
+payloadSize(payloadSize),
+frequency(frequency)
+{
+ if (payloadSize > 0)
+ {
+ this->payloadData = new WebRtc_UWord8[payloadSize];
+ memcpy(this->payloadData, payloadData, payloadSize);
+ }
+}
+
+RTPPacket::~RTPPacket()
+{
+ delete [] payloadData;
+}
+
+RTPBuffer::RTPBuffer()
+{
+ _queueRWLock = RWLockWrapper::CreateRWLock();
+}
+
+RTPBuffer::~RTPBuffer()
+{
+ delete _queueRWLock;
+}
+
+void
+RTPBuffer::Write(const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp,
+ const WebRtc_Word16 seqNo, const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize, WebRtc_UWord32 frequency)
+{
+ RTPPacket *packet = new RTPPacket(payloadType, timeStamp, seqNo, payloadData, payloadSize, frequency);
+ _queueRWLock->AcquireLockExclusive();
+ _rtpQueue.push(packet);
+ _queueRWLock->ReleaseLockExclusive();
+}
+
+WebRtc_UWord16
+RTPBuffer::Read(WebRtcRTPHeader* rtpInfo,
+ WebRtc_Word8* payloadData,
+ WebRtc_UWord16 payloadSize,
+ WebRtc_UWord32* offset)
+{
+ _queueRWLock->AcquireLockShared();
+ RTPPacket *packet = _rtpQueue.front();
+ _rtpQueue.pop();
+ _queueRWLock->ReleaseLockShared();
+ rtpInfo->header.markerBit = 1;
+ rtpInfo->header.payloadType = packet->payloadType;
+ rtpInfo->header.sequenceNumber = packet->seqNo;
+ rtpInfo->header.ssrc = 0;
+ rtpInfo->header.timestamp = packet->timeStamp;
+ if (packet->payloadSize > 0 && payloadSize >= packet->payloadSize)
+ {
+ memcpy(payloadData, packet->payloadData, packet->payloadSize);
+ }
+ else
+ {
+ throw "Payload buffer too small";
+ exit(1);
+ }
+/*#ifdef WEBRTC_CODEC_G722
+ if(ACMCodecDB::_mycodecs[ACMCodecDB::g722].pltype == packet->payloadType)
+ {
+ *offset = (packet->timeStamp/(packet->frequency/1000))<<1;
+ }
+ else
+ {
+#endif*/
+ *offset = (packet->timeStamp/(packet->frequency/1000));
+/*#ifdef WEBRTC_CODEC_G722
+ }
+#endif*/
+ return packet->payloadSize;
+}
+
+bool
+RTPBuffer::EndOfFile() const
+{
+ _queueRWLock->AcquireLockShared();
+ bool eof = _rtpQueue.empty();
+ _queueRWLock->ReleaseLockShared();
+ return eof;
+}
+
+void RTPFile::Open(char *filename, const char *mode)
+{
+ if ((_rtpFile = fopen(filename, mode)) == NULL)
+ {
+ printf("Cannot write file %s.\n", filename);
+ throw "Unable to write file";
+ exit(1);
+ }
+}
+
+void RTPFile::Close()
+{
+ if (_rtpFile != NULL)
+ {
+ fclose(_rtpFile);
+ _rtpFile = NULL;
+ }
+}
+
+
+void RTPFile::WriteHeader()
+{
+ // Write data in a format that NetEQ and RTP Play can parse
+ fprintf(_rtpFile, "#!RTPencode%s\n", "1.0");
+ WebRtc_UWord32 dummy_variable = 0; // should be converted to network endian format, but does not matter when 0
+ fwrite(&dummy_variable, 4, 1, _rtpFile);
+ fwrite(&dummy_variable, 4, 1, _rtpFile);
+ fwrite(&dummy_variable, 4, 1, _rtpFile);
+ fwrite(&dummy_variable, 2, 1, _rtpFile);
+ fwrite(&dummy_variable, 2, 1, _rtpFile);
+ fflush(_rtpFile);
+}
+
+void RTPFile::ReadHeader()
+{
+ WebRtc_UWord32 start_sec, start_usec, source;
+ WebRtc_UWord16 port, padding;
+ char fileHeader[40];
+ fgets(fileHeader, 40, _rtpFile);
+ fread(&start_sec, 4, 1, _rtpFile);
+ start_sec=ntohl(start_sec);
+ fread(&start_usec, 4, 1, _rtpFile);
+ start_usec=ntohl(start_usec);
+ fread(&source, 4, 1, _rtpFile);
+ source=ntohl(source);
+ fread(&port, 2, 1, _rtpFile);
+ port=ntohs(port);
+ fread(&padding, 2, 1, _rtpFile);
+ padding=ntohs(padding);
+}
+
+void RTPFile::Write(const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp,
+ const WebRtc_Word16 seqNo, const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize, WebRtc_UWord32 frequency)
+{
+ /* write RTP packet to file */
+ WebRtc_UWord8 rtpHeader[12];
+ MakeRTPheader(rtpHeader, payloadType, seqNo, timeStamp, 0);
+ WebRtc_UWord16 lengthBytes = htons(12 + payloadSize + 8);
+ WebRtc_UWord16 plen = htons(12 + payloadSize);
+ WebRtc_UWord32 offsetMs;
+/*#ifdef WEBRTC_CODEC_G722
+ if(ACMCodecDB::_mycodecs[ACMCodecDB::g722].pltype == payloadType)
+ {
+ offsetMs = (timeStamp/(frequency/1000))<<1;
+ }
+ else
+ {
+#endif*/
+ offsetMs = (timeStamp/(frequency/1000));
+/*#ifdef WEBRTC_CODEC_G722
+ }
+#endif*/
+ offsetMs = htonl(offsetMs);
+ fwrite(&lengthBytes, 2, 1, _rtpFile);
+ fwrite(&plen, 2, 1, _rtpFile);
+ fwrite(&offsetMs, 4, 1, _rtpFile);
+ fwrite(rtpHeader, 12, 1, _rtpFile);
+ fwrite(payloadData, 1, payloadSize, _rtpFile);
+}
+
+WebRtc_UWord16 RTPFile::Read(WebRtcRTPHeader* rtpInfo,
+ WebRtc_Word8* payloadData,
+ WebRtc_UWord16 payloadSize,
+ WebRtc_UWord32* offset)
+{
+ WebRtc_UWord16 lengthBytes;
+ WebRtc_UWord16 plen;
+ WebRtc_UWord8 rtpHeader[12];
+ fread(&lengthBytes, 2, 1, _rtpFile);
+ if (feof(_rtpFile))
+ {
+ _rtpEOF = true;
+ return 0;
+ }
+ fread(&plen, 2, 1, _rtpFile);
+ if (feof(_rtpFile))
+ {
+ _rtpEOF = true;
+ return 0;
+ }
+ fread(offset, 4, 1, _rtpFile);
+ if (feof(_rtpFile))
+ {
+ _rtpEOF = true;
+ return 0;
+ }
+ lengthBytes = ntohs(lengthBytes);
+ plen = ntohs(plen);
+ *offset = ntohl(*offset);
+ if (plen < 12)
+ {
+ throw "Unable to read RTP file";
+ exit(1);
+ }
+ fread(rtpHeader, 12, 1, _rtpFile);
+ if (feof(_rtpFile))
+ {
+ _rtpEOF = true;
+ return 0;
+ }
+ ParseRTPHeader(rtpInfo, rtpHeader);
+ rtpInfo->type.Audio.isCNG = false;
+ rtpInfo->type.Audio.channel = 1;
+ if (lengthBytes != plen + 8)
+ {
+ throw "Length parameters in RTP file doesn't match";
+ exit(1);
+ }
+ if (plen == 0)
+ {
+ return 0;
+ }
+ else if (lengthBytes - 20 > payloadSize)
+ {
+ throw "Payload buffer too small";
+ exit(1);
+ }
+ lengthBytes -= 20;
+ fread(payloadData, 1, lengthBytes, _rtpFile);
+ if (feof(_rtpFile))
+ {
+ _rtpEOF = true;
+ }
+ return lengthBytes;
+}
+
diff --git a/src/modules/audio_coding/main/test/RTPFile.h b/src/modules/audio_coding/main/test/RTPFile.h
new file mode 100644
index 0000000..23a43d0
--- /dev/null
+++ b/src/modules/audio_coding/main/test/RTPFile.h
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#ifndef RTPFILE_H
+#define RTPFILE_H
+
+#include "audio_coding_module.h"
+#include "module_common_types.h"
+#include "typedefs.h"
+#include "rw_lock_wrapper.h"
+#include <stdio.h>
+#include <queue>
+
+using namespace webrtc;
+
+class RTPStream
+{
+public:
+ virtual ~RTPStream(){}
+
+ virtual void Write(const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp,
+ const WebRtc_Word16 seqNo, const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize, WebRtc_UWord32 frequency) = 0;
+ virtual WebRtc_UWord16 Read(WebRtcRTPHeader* rtpInfo,
+ WebRtc_Word8* payloadData,
+ WebRtc_UWord16 payloadSize,
+ WebRtc_UWord32* offset) = 0;
+ virtual bool EndOfFile() const = 0;
+
+protected:
+ void MakeRTPheader(WebRtc_UWord8* rtpHeader,
+ WebRtc_UWord8 payloadType, WebRtc_Word16 seqNo,
+ WebRtc_UWord32 timeStamp, WebRtc_UWord32 ssrc);
+ void ParseRTPHeader(WebRtcRTPHeader* rtpInfo, const WebRtc_UWord8* rtpHeader);
+};
+
+class RTPPacket
+{
+public:
+ RTPPacket(WebRtc_UWord8 payloadType, WebRtc_UWord32 timeStamp,
+ WebRtc_Word16 seqNo, const WebRtc_UWord8* payloadData,
+ WebRtc_UWord16 payloadSize, WebRtc_UWord32 frequency);
+ ~RTPPacket();
+ WebRtc_UWord8 payloadType;
+ WebRtc_UWord32 timeStamp;
+ WebRtc_Word16 seqNo;
+ WebRtc_UWord8* payloadData;
+ WebRtc_UWord16 payloadSize;
+ WebRtc_UWord32 frequency;
+};
+
+class RTPBuffer : public RTPStream
+{
+public:
+ RTPBuffer();
+ ~RTPBuffer();
+ void Write(const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp,
+ const WebRtc_Word16 seqNo, const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize, WebRtc_UWord32 frequency);
+ WebRtc_UWord16 Read(WebRtcRTPHeader* rtpInfo,
+ WebRtc_Word8* payloadData,
+ WebRtc_UWord16 payloadSize,
+ WebRtc_UWord32* offset);
+ virtual bool EndOfFile() const;
+private:
+ RWLockWrapper* _queueRWLock;
+ std::queue<RTPPacket *> _rtpQueue;
+};
+
+class RTPFile : public RTPStream
+{
+public:
+ ~RTPFile(){}
+ RTPFile() : _rtpFile(NULL),_rtpEOF(false) {}
+ void Open(char *outFilename, const char *mode);
+ void Close();
+ void WriteHeader();
+ void ReadHeader();
+ void Write(const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp,
+ const WebRtc_Word16 seqNo, const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize, WebRtc_UWord32 frequency);
+ WebRtc_UWord16 Read(WebRtcRTPHeader* rtpInfo,
+ WebRtc_Word8* payloadData,
+ WebRtc_UWord16 payloadSize,
+ WebRtc_UWord32* offset);
+ bool EndOfFile() const { return _rtpEOF; }
+private:
+ FILE* _rtpFile;
+ bool _rtpEOF;
+};
+
+#endif
diff --git a/src/modules/audio_coding/main/test/SpatialAudio.cpp b/src/modules/audio_coding/main/test/SpatialAudio.cpp
new file mode 100644
index 0000000..016ec0a
--- /dev/null
+++ b/src/modules/audio_coding/main/test/SpatialAudio.cpp
@@ -0,0 +1,239 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+
+#include <math.h>
+
+#include "SpatialAudio.h"
+#include "utility.h"
+#include "trace.h"
+#include "common_types.h"
+
+using namespace webrtc;
+
+#define NUM_PANN_COEFFS 10
+
+SpatialAudio::SpatialAudio(int testMode)
+{
+ _testMode = testMode;
+}
+
+SpatialAudio::~SpatialAudio()
+{
+ AudioCodingModule::Destroy(_acmLeft);
+ AudioCodingModule::Destroy(_acmRight);
+ AudioCodingModule::Destroy(_acmReceiver);
+ delete _channel;
+ _inFile.Close();
+ _outFile.Close();
+}
+
+WebRtc_Word16
+SpatialAudio::Setup()
+{
+ // Create ACMs and the Channel;
+ _acmLeft = AudioCodingModule::Create(1);
+ _acmRight = AudioCodingModule::Create(2);
+ _acmReceiver = AudioCodingModule::Create(3);
+ _channel = new Channel;
+
+ // Register callback for the sender side.
+ CHECK_ERROR(_acmLeft->RegisterTransportCallback(_channel));
+ CHECK_ERROR(_acmRight->RegisterTransportCallback(_channel));
+ // Register the receiver ACM in channel
+ _channel->RegisterReceiverACM(_acmReceiver);
+
+ WebRtc_Word8 audioFileName[MAX_FILE_NAME_LENGTH_BYTE];
+ WebRtc_UWord16 sampFreqHz = 32000;
+
+ strncpy(audioFileName, "./modules/audio_coding/main/test/testfile32kHz.pcm",
+ MAX_FILE_NAME_LENGTH_BYTE - 1);
+ if(_testMode == 1)
+ {
+ printf("Enter the input file [%s]: ", audioFileName);
+ PCMFile::ChooseFile(audioFileName, MAX_FILE_NAME_LENGTH_BYTE, &sampFreqHz);
+ }
+ _inFile.Open(audioFileName, sampFreqHz, "rb", false);
+
+ if(_testMode == 0)
+ {
+ strncpy(audioFileName, "./modules/audio_coding/main/test/res_autotests/out_spatial_autotest.pcm",
+ MAX_FILE_NAME_LENGTH_BYTE - 1);
+ }
+ else if(_testMode == 1)
+ {
+ printf("\n");
+ strncpy(audioFileName, "./modules/audio_coding/main/test/res_tests/testspatial_out.pcm",
+ MAX_FILE_NAME_LENGTH_BYTE - 1);
+ printf("Enter the output file [%s]: ", audioFileName);
+ PCMFile::ChooseFile(audioFileName, MAX_FILE_NAME_LENGTH_BYTE, &sampFreqHz);
+ }
+ else
+ {
+ strncpy(audioFileName, "./modules/audio_coding/main/test/res_tests/testspatial_out.pcm",
+ MAX_FILE_NAME_LENGTH_BYTE - 1);
+ }
+ _outFile.Open(audioFileName, sampFreqHz, "wb", false);
+ _outFile.SaveStereo(true);
+
+
+ // Register couple of codecs as receive codec
+ CodecInst codecInst;
+
+ _acmLeft->Codec((WebRtc_UWord8)0, codecInst);
+ codecInst.channels = 2;
+ CHECK_ERROR(_acmReceiver->RegisterReceiveCodec(codecInst));
+
+ _acmLeft->Codec((WebRtc_UWord8)3, codecInst);
+ codecInst.channels = 2;
+ CHECK_ERROR(_acmReceiver->RegisterReceiveCodec(codecInst));
+
+ _acmLeft->Codec((WebRtc_UWord8)1, codecInst);
+ CHECK_ERROR(_acmReceiver->RegisterReceiveCodec(codecInst));
+
+ _acmLeft->Codec((WebRtc_UWord8)4, codecInst);
+ CHECK_ERROR(_acmReceiver->RegisterReceiveCodec(codecInst));
+
+ return 0;
+}
+
+void
+SpatialAudio::Perform()
+{
+ if(_testMode == 0)
+ {
+ printf("Running SpatialAudio Test");
+ WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, "---------- SpatialAudio ----------");
+ }
+
+ Setup();
+
+ CodecInst codecInst;
+ _acmLeft->Codec((WebRtc_UWord8)1, codecInst);
+ CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
+ EncodeDecode();
+
+ WebRtc_Word16 pannCntr = 0;
+
+ double leftPanning[NUM_PANN_COEFFS] =
+ {1.00, 0.95, 0.90, 0.85, 0.80, 0.75, 0.70, 0.60, 0.55, 0.50};
+ double rightPanning[NUM_PANN_COEFFS] =
+ {0.50, 0.55, 0.60, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00};
+
+ while((pannCntr + 1) < NUM_PANN_COEFFS)
+ {
+ _acmLeft->Codec((WebRtc_UWord8)0, codecInst);
+ codecInst.pacsize = 480;
+ CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
+ CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst));
+
+ EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]);
+ pannCntr++;
+
+ // Change codec
+ _acmLeft->Codec((WebRtc_UWord8)3, codecInst);
+ codecInst.pacsize = 320;
+ CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
+ CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst));
+
+ EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]);
+ pannCntr++;
+ if(_testMode == 0)
+ {
+ printf(".");
+ }
+ }
+
+ _acmLeft->Codec((WebRtc_UWord8)4, codecInst);
+ CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
+ EncodeDecode();
+
+ _acmLeft->Codec((WebRtc_UWord8)0, codecInst);
+ codecInst.pacsize = 480;
+ CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
+ CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst));
+ pannCntr = NUM_PANN_COEFFS -1;
+ while(pannCntr >= 0)
+ {
+ EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]);
+ pannCntr--;
+ if(_testMode == 0)
+ {
+ printf(".");
+ }
+ }
+ if(_testMode == 0)
+ {
+ printf("Done!\n");
+ }
+}
+
+void
+SpatialAudio::EncodeDecode(
+ const double leftPanning,
+ const double rightPanning)
+{
+ AudioFrame audioFrame;
+ WebRtc_Word32 outFileSampFreq = _outFile.SamplingFrequency();
+
+ const double rightToLeftRatio = rightPanning / leftPanning;
+
+ _channel->SetIsStereo(true);
+
+ while(!_inFile.EndOfFile())
+ {
+ _inFile.Read10MsData(audioFrame);
+ for(int n = 0; n < audioFrame._payloadDataLengthInSamples; n++)
+ {
+ audioFrame._payloadData[n] = (WebRtc_Word16)floor(
+ audioFrame._payloadData[n] * leftPanning + 0.5);
+ }
+ CHECK_ERROR(_acmLeft->Add10MsData(audioFrame));
+
+ for(int n = 0; n < audioFrame._payloadDataLengthInSamples; n++)
+ {
+ audioFrame._payloadData[n] = (WebRtc_Word16)floor(
+ audioFrame._payloadData[n] * rightToLeftRatio + 0.5);
+ }
+ CHECK_ERROR(_acmRight->Add10MsData(audioFrame));
+
+ CHECK_ERROR(_acmLeft->Process());
+ CHECK_ERROR(_acmRight->Process());
+
+ CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, audioFrame));
+ _outFile.Write10MsData(audioFrame);
+ }
+ _inFile.Rewind();
+}
+
+void
+SpatialAudio::EncodeDecode()
+{
+ AudioFrame audioFrame;
+ WebRtc_Word32 outFileSampFreq = _outFile.SamplingFrequency();
+
+ _channel->SetIsStereo(false);
+
+ while(!_inFile.EndOfFile())
+ {
+ _inFile.Read10MsData(audioFrame);
+ CHECK_ERROR(_acmLeft->Add10MsData(audioFrame));
+
+ CHECK_ERROR(_acmLeft->Process());
+
+ CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, audioFrame));
+ _outFile.Write10MsData(audioFrame);
+ }
+ _inFile.Rewind();
+}
+
+
diff --git a/src/modules/audio_coding/main/test/SpatialAudio.h b/src/modules/audio_coding/main/test/SpatialAudio.h
new file mode 100644
index 0000000..6a137d4
--- /dev/null
+++ b/src/modules/audio_coding/main/test/SpatialAudio.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#ifndef ACM_TEST_SPATIAL_AUDIO_H
+#define ACM_TEST_SPATIAL_AUDIO_H
+
+#include "ACMTest.h"
+#include "Channel.h"
+#include "PCMFile.h"
+#include "audio_coding_module.h"
+#include "utility.h"
+
+#define MAX_FILE_NAME_LENGTH_BYTE 500
+
+
+class SpatialAudio : public ACMTest
+{
+public:
+ SpatialAudio(int testMode);
+ ~SpatialAudio();
+
+ void Perform();
+private:
+ WebRtc_Word16 Setup();
+ void EncodeDecode(double leftPanning, double rightPanning);
+ void EncodeDecode();
+
+ AudioCodingModule* _acmLeft;
+ AudioCodingModule* _acmRight;
+ AudioCodingModule* _acmReceiver;
+ Channel* _channel;
+ PCMFile _inFile;
+ PCMFile _outFile;
+ int _testMode;
+};
+#endif
diff --git a/src/modules/audio_coding/main/test/TestAllCodecs.cpp b/src/modules/audio_coding/main/test/TestAllCodecs.cpp
new file mode 100644
index 0000000..35e5b0a
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TestAllCodecs.cpp
@@ -0,0 +1,858 @@
+/*
+ * 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 "TestAllCodecs.h"
+
+#include "audio_coding_module_typedefs.h"
+#include "common_types.h"
+#include "engine_configurations.h"
+#include <cassert>
+#include <iostream>
+#include "trace.h"
+#include "utility.h"
+
+// Class for simulating packet handling
+TestPack::TestPack():
+_receiverACM(NULL),
+_seqNo(0),
+_timeStampDiff(0),
+_lastInTimestamp(0),
+_totalBytes(0),
+_payloadSize(0)
+{
+}
+TestPack::~TestPack()
+{
+}
+
+void
+TestPack::RegisterReceiverACM(AudioCodingModule* acm)
+{
+ _receiverACM = acm;
+ return;
+}
+WebRtc_Word32
+TestPack::SendData(
+ const FrameType frameType,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* fragmentation)
+{
+ WebRtcRTPHeader rtpInfo;
+ WebRtc_Word32 status;
+ WebRtc_UWord16 payloadDataSize = payloadSize;
+
+ rtpInfo.header.markerBit = false;
+ rtpInfo.header.ssrc = 0;
+ rtpInfo.header.sequenceNumber = _seqNo++;
+ rtpInfo.header.payloadType = payloadType;
+ rtpInfo.header.timestamp = timeStamp;
+ if(frameType == kAudioFrameCN)
+ {
+ rtpInfo.type.Audio.isCNG = true;
+ }
+ else
+ {
+ rtpInfo.type.Audio.isCNG = false;
+ }
+ if(frameType == kFrameEmpty)
+ {
+ // Skip this frame
+ return 0;
+ }
+
+ rtpInfo.type.Audio.channel = 1;
+ memcpy(_payloadData, payloadData, payloadDataSize);
+
+ status = _receiverACM->IncomingPacket((WebRtc_Word8*)_payloadData, payloadDataSize, rtpInfo);
+
+ _payloadSize = payloadDataSize;
+ _timeStampDiff = timeStamp - _lastInTimestamp;
+ _lastInTimestamp = timeStamp;
+ _totalBytes += payloadDataSize;
+ return status;
+}
+
+WebRtc_UWord16
+TestPack::GetPayloadSize()
+{
+ return _payloadSize;
+}
+
+
+WebRtc_UWord32
+TestPack::GetTimeStampDiff()
+{
+ return _timeStampDiff;
+}
+
+void
+TestPack::ResetPayloadSize()
+{
+ _payloadSize = 0;
+}
+
+TestAllCodecs::TestAllCodecs(int testMode):
+_acmA(NULL),
+_acmB(NULL),
+_channelA2B(NULL),
+_testCntr(0),
+_packSizeSamp(0),
+_packSizeBytes(0),
+_counter(0)
+{
+ // testMode = 0 for silent test (auto test)
+ _testMode = testMode;
+}
+
+using namespace std;
+TestAllCodecs::~TestAllCodecs()
+{
+ if(_acmA != NULL)
+ {
+ AudioCodingModule::Destroy(_acmA);
+ _acmA = NULL;
+ }
+ if(_acmB != NULL)
+ {
+ AudioCodingModule::Destroy(_acmB);
+ _acmB = NULL;
+ }
+ if(_channelA2B != NULL)
+ {
+ delete _channelA2B;
+ _channelA2B = NULL;
+ }
+}
+
+void TestAllCodecs::Perform()
+{
+
+ char file[] = "./modules/audio_coding/main/test/testfile32kHz.pcm";
+ _inFileA.Open(file, 32000, "rb");
+
+ if(_testMode == 0)
+ {
+ printf("Running All Codecs Test");
+ WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
+ "---------- TestAllCodecs ----------");
+ }
+
+ _acmA = AudioCodingModule::Create(0);
+ _acmB = AudioCodingModule::Create(1);
+
+ _acmA->InitializeReceiver();
+ _acmB->InitializeReceiver();
+
+ WebRtc_UWord8 numEncoders = _acmA->NumberOfCodecs();
+ CodecInst myCodecParam;
+
+ for(WebRtc_UWord8 n = 0; n < numEncoders; n++)
+ {
+ _acmB->Codec(n, myCodecParam);
+ _acmB->RegisterReceiveCodec(myCodecParam);
+ }
+
+ // Create and connect the channel
+ _channelA2B = new TestPack;
+ _acmA->RegisterTransportCallback(_channelA2B);
+ _channelA2B->RegisterReceiverACM(_acmB);
+
+ // All codecs are tested for all allowed sampling frequencies, rates and packet sizes
+#ifdef WEBRTC_CODEC_GSMAMR
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecAMR[] = "AMR";
+ RegisterSendCodec('A', codecAMR, 8000, 4750, 160, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 4750, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 4750, 480, 3);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 5150, 160, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 5150, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 5150, 480, 3);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 5900, 160, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 5900, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 5900, 480, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 6700, 160, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 6700, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 6700, 480, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 7400, 160, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 7400, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 7400, 480, 3);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 7950, 160, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 7950, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 7950, 480, 3);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 10200, 160, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 10200, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 10200, 480, 3);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 12200, 160, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 12200, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMR, 8000, 12200, 480, 3);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_GSMAMRWB
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ char codecAMRWB[] = "AMR-WB";
+ OpenOutFile(_testCntr);
+ RegisterSendCodec('A', codecAMRWB, 16000, 7000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 7000, 640, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 7000, 960, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 9000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 9000, 640, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 9000, 960, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 12000, 320, 3);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 12000, 640, 6);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 12000, 960, 8);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 14000, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 14000, 640, 4);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 14000, 960, 5);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 16000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 16000, 640, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 16000, 960, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 18000, 320, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 18000, 640, 4);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 18000, 960, 5);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 20000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 20000, 640, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 20000, 960, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 23000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 23000, 640, 3);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 23000, 960, 3);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 24000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 24000, 640, 2);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecAMRWB, 16000, 24000, 960, 2);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_G722
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecG722[] = "G722";
+ RegisterSendCodec('A', codecG722, 16000, 64000, 160, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 480, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 640, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 800, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 960, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_G722_1
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecG7221_1[] = "G7221";
+ RegisterSendCodec('A', codecG7221_1, 16000, 32000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7221_1, 16000, 24000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7221_1, 16000, 16000, 320, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_G722_1C
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecG7221_2[] = "G7221";
+ RegisterSendCodec('A', codecG7221_2, 32000, 48000, 640, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7221_2, 32000, 32000, 640, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7221_2, 32000, 24000, 640, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_G729
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecG729[] = "G729";
+ RegisterSendCodec('A', codecG729, 8000, 8000, 80, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG729, 8000, 8000, 160, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG729, 8000, 8000, 240, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG729, 8000, 8000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG729, 8000, 8000, 400, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG729, 8000, 8000, 480, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_G729_1
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecG7291[] = "G7291";
+ RegisterSendCodec('A', codecG7291, 16000, 8000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 8000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 8000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 12000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 12000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 12000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 14000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 14000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 14000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 16000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 16000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 16000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 18000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 18000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 18000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 20000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 20000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 20000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 22000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 22000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 22000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 24000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 24000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 24000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 26000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 26000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 26000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 28000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 28000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 28000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 30000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 30000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 30000, 960, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 32000, 320, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 32000, 640, 1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG7291, 16000, 32000, 960, 1);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_GSMFR
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecGSM[] = "GSM";
+ RegisterSendCodec('A', codecGSM, 8000, 13200, 160, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecGSM, 8000, 13200, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecGSM, 8000, 13200, 480, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_ILBC
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecILBC[] = "ILBC";
+ RegisterSendCodec('A', codecILBC, 8000, 13300, 240, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecILBC, 8000, 13300, 480, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecILBC, 8000, 15200, 160, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecILBC, 8000, 15200, 320, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecISAC[] = "ISAC";
+ RegisterSendCodec('A', codecISAC, 16000, -1, 480, -1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecISAC, 16000, -1, 960, -1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecISAC, 16000, 15000, 480, -1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecISAC, 16000, 32000, 960, -1);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_ISAC
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ RegisterSendCodec('A', codecISAC, 32000, -1, 960, -1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecISAC, 32000, 56000, 960, -1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecISAC, 32000, 37000, 960, -1);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecISAC, 32000, 32000, 960, -1);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_PCM16
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecL16[] = "L16";
+ RegisterSendCodec('A', codecL16, 8000, 128000, 80, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 8000, 128000, 160, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 8000, 128000, 240, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 8000, 128000, 320, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ RegisterSendCodec('A', codecL16, 16000, 256000, 160, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 16000, 256000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 16000, 256000, 480, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 16000, 256000, 640, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ RegisterSendCodec('A', codecL16, 32000, 512000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 32000, 512000, 640, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecPCMA[] = "PCMA";
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 160, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 240, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 400, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 480, 0);
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ Run(_channelA2B);
+ char codecPCMU[] = "PCMU";
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 160, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 240, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 400, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 480, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+#ifdef WEBRTC_CODEC_SPEEX
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecSPEEX[] = "SPEEX";
+ RegisterSendCodec('A', codecSPEEX, 8000, 2400, 160, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecSPEEX, 8000, 8000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecSPEEX, 8000, 18200, 480, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ RegisterSendCodec('A', codecSPEEX, 16000, 4000, 320, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecSPEEX, 16000, 12800, 640, 0);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecSPEEX, 16000, 34200, 960, 0);
+ Run(_channelA2B);
+ _outFileB.Close();
+#endif
+
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf("Done!\n");
+ }
+
+ /* Print out all codecs that were not tested in the run */
+
+
+ if(_testMode != 0) {
+ printf("The following codecs was not included in the test:\n");
+#ifndef WEBRTC_CODEC_GSMAMR
+ printf(" GSMAMR\n");
+#endif
+#ifndef WEBRTC_CODEC_GSMAMRWB
+ printf(" GSMAMR-wb\n");
+#endif
+#ifndef WEBRTC_CODEC_G722
+ printf(" G.722\n");
+#endif
+#ifndef WEBRTC_CODEC_G722_1
+ printf(" G.722.1\n");
+#endif
+#ifndef WEBRTC_CODEC_G722_1C
+ printf(" G.722.1C\n");
+#endif
+#ifndef WEBRTC_CODEC_G729
+ printf(" G.729\n");
+#endif
+#ifndef WEBRTC_CODEC_G729_1
+ printf(" G.729.1\n");
+#endif
+#ifndef WEBRTC_CODEC_GSMFR
+ printf(" GSMFR\n");
+#endif
+#ifndef WEBRTC_CODEC_ILBC
+ printf(" iLBC\n");
+#endif
+#ifndef WEBRTC_CODEC_ISAC
+ printf(" ISAC float\n");
+#endif
+#ifndef WEBRTC_CODEC_ISACFX
+ printf(" ISAC fix\n");
+#endif
+#ifndef WEBRTC_CODEC_PCM16
+ printf(" PCM16\n");
+#endif
+#ifndef WEBRTC_CODEC_SPEEX
+ printf(" Speex\n");
+#endif
+
+ printf("\nTo complete the test, listen to the %d number of output files.\n", _testCntr);
+ }
+}
+
+// Register Codec to use in the test
+//
+// Input: side - which ACM to use, 'A' or 'B'
+// codecName - name to use when register the codec
+// samplingFreqHz - sampling frequency in Herz
+// rate - bitrate in bytes
+// packSize - packet size in samples
+// extraByte - if extra bytes needed compared to the bitrate
+// used when registering, can be an internal header
+// set to -1 if the codec is a variable rate codec
+WebRtc_Word16 TestAllCodecs::RegisterSendCodec(char side,
+ char* codecName,
+ WebRtc_Word32 samplingFreqHz,
+ int rate,
+ int packSize,
+ int extraByte)
+{
+ if(_testMode != 0) {
+ // Print out codec and settings
+ printf("codec: %s Freq: %d Rate: %d PackSize: %d", codecName, samplingFreqHz, rate, packSize);
+ }
+
+ // Store packetsize in samples, used to validate the recieved packet
+ _packSizeSamp = packSize;
+
+ // Store the expected packet size in bytes, used to validate the recieved packet
+ // If variable rate codec (extraByte == -1), set to -1 (65535)
+ if (extraByte != -1)
+ {
+ // Add 0.875 to always round up to a whole byte
+ _packSizeBytes = (WebRtc_UWord16)((float)(packSize*rate)/(float)(samplingFreqHz*8)+0.875)+extraByte;
+ }
+ else
+ {
+ // Packets will have a variable size
+ _packSizeBytes = -1;
+ }
+
+ // Set pointer to the ACM where to register the codec
+ AudioCodingModule* myACM;
+ switch(side)
+ {
+ case 'A':
+ {
+ myACM = _acmA;
+ break;
+ }
+ case 'B':
+ {
+ myACM = _acmB;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if(myACM == NULL)
+ {
+ assert(false);
+ return -1;
+ }
+ CodecInst myCodecParam;
+
+ // Get all codec paramters before registering
+ CHECK_ERROR(AudioCodingModule::Codec(codecName, myCodecParam, samplingFreqHz));
+ myCodecParam.rate = rate;
+ myCodecParam.pacsize = packSize;
+ CHECK_ERROR(myACM->RegisterSendCodec(myCodecParam));
+
+ // initialization was succesful
+ return 0;
+}
+
+void TestAllCodecs::Run(TestPack* channel)
+{
+ AudioFrame audioFrame;
+
+ WebRtc_UWord16 SamplesIn10MsecA = _inFileA.PayloadLength10Ms();
+ WebRtc_UWord32 timestampA = 1;
+ WebRtc_Word32 outFreqHzB = _outFileB.SamplingFrequency();
+ WebRtc_UWord16 recSize;
+ WebRtc_UWord32 timeStampDiff;
+ channel->ResetPayloadSize();
+ int errorCount = 0;
+
+ // Only run 1 second for each test case
+ while((_counter<1000)&& (!_inFileA.EndOfFile()))
+ {
+ // Add 10 msec to ACM
+ _inFileA.Read10MsData(audioFrame);
+ CHECK_ERROR(_acmA->Add10MsData(audioFrame));
+
+ // Run sender side of ACM
+ CHECK_ERROR(_acmA->Process());
+
+ // Verify that the received packet size matches the settings
+ recSize = channel->GetPayloadSize();
+ if (recSize) {
+ if ((recSize != _packSizeBytes) && (_packSizeBytes < 65535)) {
+ errorCount++;
+ }
+
+ // Verify that the timestamp is updated with expected length
+ timeStampDiff = channel->GetTimeStampDiff();
+ if ((_counter > 10) && (timeStampDiff != _packSizeSamp))
+ errorCount++;
+ }
+
+
+ // Run received side of ACM
+ CHECK_ERROR(_acmB->PlayoutData10Ms(outFreqHzB, audioFrame));
+
+ // Write output speech to file
+ _outFileB.Write10MsData(audioFrame._payloadData, audioFrame._payloadDataLengthInSamples);
+ }
+
+ if (errorCount)
+ {
+ printf(" - test FAILED\n");
+ }
+ else if(_testMode != 0)
+ {
+ printf(" - test PASSED\n");
+ }
+
+ // Reset _counter
+ if (_counter == 1000) {
+ _counter = 0;
+ }
+ if (_inFileA.EndOfFile()) {
+ _inFileA.Rewind();
+ }
+}
+
+void TestAllCodecs::OpenOutFile(WebRtc_Word16 testNumber)
+{
+ char fileName[500] = "testallcodecs_out_";
+ char cntrStr[10];
+
+ sprintf(cntrStr, "%02d.pcm", testNumber);
+ strcat(fileName, cntrStr);
+ _outFileB.Open(fileName, 32000, "wb");
+}
+
+void TestAllCodecs::DisplaySendReceiveCodec()
+{
+ CodecInst myCodecParam;
+ _acmA->SendCodec(myCodecParam);
+ printf("%s -> ", myCodecParam.plname);
+ _acmB->ReceiveCodec(myCodecParam);
+ printf("%s\n", myCodecParam.plname);
+}
+
diff --git a/src/modules/audio_coding/main/test/TestAllCodecs.h b/src/modules/audio_coding/main/test/TestAllCodecs.h
new file mode 100644
index 0000000..958cefd
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TestAllCodecs.h
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_ALL_CODECS_H
+#define TEST_ALL_CODECS_H
+
+#include "ACMTest.h"
+#include "Channel.h"
+#include "PCMFile.h"
+
+class TestPack : public AudioPacketizationCallback
+{
+public:
+ TestPack();
+ ~TestPack();
+
+ void RegisterReceiverACM(AudioCodingModule* acm);
+
+ virtual WebRtc_Word32 SendData(const FrameType frameType,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* fragmentation);
+
+ WebRtc_UWord16 GetPayloadSize();
+ WebRtc_UWord32 GetTimeStampDiff();
+ void ResetPayloadSize();
+
+private:
+ AudioCodingModule* _receiverACM;
+ WebRtc_Word16 _seqNo;
+ WebRtc_UWord8 _payloadData[60 * 32 * 2 * 2];
+ WebRtc_UWord32 _timeStampDiff;
+ WebRtc_UWord32 _lastInTimestamp;
+ WebRtc_UWord64 _totalBytes;
+ WebRtc_UWord16 _payloadSize;
+};
+
+class TestAllCodecs : public ACMTest
+{
+public:
+ TestAllCodecs(int testMode);
+ ~TestAllCodecs();
+
+ void Perform();
+private:
+ // The default value of '-1' indicates that the registration is based only on codec name
+ // and a sampling frequncy matching is not required. This is useful for codecs which support
+ // several sampling frequency.
+ WebRtc_Word16 RegisterSendCodec(char side,
+ char* codecName,
+ WebRtc_Word32 sampFreqHz,
+ int rate,
+ int packSize,
+ int extraByte);
+
+ void Run(TestPack* channel);
+ void OpenOutFile(WebRtc_Word16 testNumber);
+ void DisplaySendReceiveCodec();
+
+ WebRtc_Word32 SendData(
+ const FrameType frameType,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* fragmentation);
+
+ int _testMode;
+
+ AudioCodingModule* _acmA;
+ AudioCodingModule* _acmB;
+
+ TestPack* _channelA2B;
+
+ PCMFile _inFileA;
+ PCMFile _outFileB;
+ WebRtc_Word16 _testCntr;
+ WebRtc_UWord16 _packSizeSamp;
+ WebRtc_UWord16 _packSizeBytes;
+ int _counter;
+};
+
+
+#endif // TEST_ALL_CODECS_H
+
diff --git a/src/modules/audio_coding/main/test/TestFEC.cpp b/src/modules/audio_coding/main/test/TestFEC.cpp
new file mode 100644
index 0000000..829e1de
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TestFEC.cpp
@@ -0,0 +1,627 @@
+/*
+ * 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 "TestFEC.h"
+
+#include "audio_coding_module_typedefs.h"
+#include "common_types.h"
+#include "engine_configurations.h"
+
+#include <cassert>
+#include <iostream>
+#include "trace.h"
+#include "utility.h"
+
+TestFEC::TestFEC(int testMode):
+_acmA(NULL),
+_acmB(NULL),
+_channelA2B(NULL),
+_testCntr(0)
+{
+ _testMode = testMode;
+}
+
+using namespace std;
+
+TestFEC::~TestFEC()
+{
+ if(_acmA != NULL)
+ {
+ AudioCodingModule::Destroy(_acmA);
+ _acmA = NULL;
+ }
+ if(_acmB != NULL)
+ {
+ AudioCodingModule::Destroy(_acmB);
+ _acmB = NULL;
+ }
+ if(_channelA2B != NULL)
+ {
+ delete _channelA2B;
+ _channelA2B = NULL;
+ }
+}
+
+void TestFEC::Perform()
+{
+
+ if(_testMode == 0)
+ {
+ printf("Running FEC Test");
+ WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
+ "---------- TestFEC ----------");
+ }
+ char fileName[] = "./modules/audio_coding/main/test/testfile32kHz.pcm";
+ _inFileA.Open(fileName, 32000, "rb");
+
+
+ bool fecEnabled;
+
+ _acmA = AudioCodingModule::Create(0);
+ _acmB = AudioCodingModule::Create(1);
+
+ _acmA->InitializeReceiver();
+ _acmB->InitializeReceiver();
+
+ WebRtc_UWord8 numEncoders = _acmA->NumberOfCodecs();
+ CodecInst myCodecParam;
+ if(_testMode != 0)
+ {
+ printf("Registering codecs at receiver... \n");
+ }
+ for(WebRtc_UWord8 n = 0; n < numEncoders; n++)
+ {
+ _acmB->Codec(n, myCodecParam);
+ if(_testMode != 0)
+ {
+ printf("%s\n", myCodecParam.plname);
+ }
+ _acmB->RegisterReceiveCodec(myCodecParam);
+ }
+
+ // Create and connect the channel
+ _channelA2B = new Channel;
+ _acmA->RegisterTransportCallback(_channelA2B);
+ _channelA2B->RegisterReceiverACM(_acmB);
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+#ifndef WEBRTC_CODEC_G722
+ printf("G722 needs to be activated to run this test\n");
+ exit(-1);
+#endif
+ char nameG722[] = "G722";
+ RegisterSendCodec('A', nameG722, 16000);
+ char nameCN[] = "CN";
+ RegisterSendCodec('A', nameCN, 16000);
+ char nameRED[] = "RED";
+ RegisterSendCodec('A', nameRED);
+ OpenOutFile(_testCntr);
+ SetVAD(true, true, VADAggr);
+ _acmA->SetFECStatus(false);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+ _outFileB.Close();
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ _acmA->SetFECStatus(true);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ OpenOutFile(_testCntr);
+ Run();
+ _outFileB.Close();
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ char nameISAC[] = "iSAC";
+ RegisterSendCodec('A',nameISAC, 16000);
+ OpenOutFile(_testCntr);
+ SetVAD(true, true, VADVeryAggr);
+ _acmA->SetFECStatus(false);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+ _outFileB.Close();
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ _acmA->SetFECStatus(true);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ OpenOutFile(_testCntr);
+ Run();
+ _outFileB.Close();
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+
+ RegisterSendCodec('A', nameISAC, 32000);
+ OpenOutFile(_testCntr);
+ SetVAD(true, true, VADVeryAggr);
+ _acmA->SetFECStatus(false);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+ _outFileB.Close();
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ _acmA->SetFECStatus(true);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ OpenOutFile(_testCntr);
+ Run();
+ _outFileB.Close();
+
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+
+ RegisterSendCodec('A', nameISAC, 32000);
+ OpenOutFile(_testCntr);
+ SetVAD(false, false, VADNormal);
+ _acmA->SetFECStatus(true);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+
+
+ RegisterSendCodec('A', nameISAC, 16000);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+
+ RegisterSendCodec('A', nameISAC, 32000);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+
+ RegisterSendCodec('A', nameISAC, 16000);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+ _outFileB.Close();
+
+
+
+
+
+
+
+ _channelA2B->SetFECTestWithPacketLoss(true);
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+
+ RegisterSendCodec('A',nameG722);
+ RegisterSendCodec('A', nameCN, 16000);
+ OpenOutFile(_testCntr);
+ SetVAD(true, true, VADAggr);
+ _acmA->SetFECStatus(false);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+ _outFileB.Close();
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ _acmA->SetFECStatus(true);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ OpenOutFile(_testCntr);
+ Run();
+ _outFileB.Close();
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ RegisterSendCodec('A', nameISAC, 16000);
+ OpenOutFile(_testCntr);
+ SetVAD(true, true, VADVeryAggr);
+ _acmA->SetFECStatus(false);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+ _outFileB.Close();
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ _acmA->SetFECStatus(true);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ OpenOutFile(_testCntr);
+ Run();
+ _outFileB.Close();
+
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ RegisterSendCodec('A', nameISAC, 32000);
+ OpenOutFile(_testCntr);
+ SetVAD(true, true, VADVeryAggr);
+ _acmA->SetFECStatus(false);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+ _outFileB.Close();
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ _acmA->SetFECStatus(true);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ OpenOutFile(_testCntr);
+ Run();
+ _outFileB.Close();
+
+
+
+
+
+
+ if(_testMode != 0)
+ {
+ printf("=======================================================================\n");
+ printf("%d ",_testCntr++);
+ }
+ else
+ {
+ printf(".");
+ }
+ RegisterSendCodec('A', nameISAC, 32000);
+ OpenOutFile(_testCntr);
+ SetVAD(false, false, VADNormal);
+ _acmA->SetFECStatus(true);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+
+
+ RegisterSendCodec('A', nameISAC, 16000);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+
+ RegisterSendCodec('A', nameISAC, 32000);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+
+ RegisterSendCodec('A', nameISAC, 16000);
+ fecEnabled = _acmA->FECStatus();
+ if(_testMode != 0)
+ {
+ printf("FEC currently %s\n",(fecEnabled?"ON":"OFF"));
+ DisplaySendReceiveCodec();
+ }
+ Run();
+ _outFileB.Close();
+
+
+
+ if(_testMode == 0)
+ {
+ printf("Done!\n");
+ }
+}
+
+WebRtc_Word32 TestFEC::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode)
+{
+ if(_testMode != 0)
+ {
+ printf("DTX %s; VAD %s; VAD-Mode %d\n",
+ enableDTX? "ON":"OFF",
+ enableVAD? "ON":"OFF",
+ (WebRtc_Word16)vadMode);
+ }
+ return _acmA->SetVAD(enableDTX, enableVAD, vadMode);
+}
+
+WebRtc_Word16 TestFEC::RegisterSendCodec(char side, char* codecName, WebRtc_Word32 samplingFreqHz)
+{
+ if(_testMode != 0)
+ {
+ if(samplingFreqHz > 0)
+ {
+ printf("Registering %s-%d for side %c\n", codecName, samplingFreqHz, side);
+ }
+ else
+ {
+ printf("Registering %s for side %c\n", codecName, side);
+ }
+ }
+ cout << flush;
+ AudioCodingModule* myACM;
+ switch(side)
+ {
+ case 'A':
+ {
+ myACM = _acmA;
+ break;
+ }
+ case 'B':
+ {
+ myACM = _acmB;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if(myACM == NULL)
+ {
+ assert(false);
+ return -1;
+ }
+ CodecInst myCodecParam;
+
+ CHECK_ERROR(AudioCodingModule::Codec(codecName, myCodecParam, samplingFreqHz));
+
+ CHECK_ERROR(myACM->RegisterSendCodec(myCodecParam));
+
+ // initialization was succesful
+ return 0;
+}
+
+void TestFEC::Run()
+{
+ AudioFrame audioFrame;
+
+ WebRtc_UWord16 msecPassed = 0;
+ WebRtc_UWord32 secPassed = 0;
+ WebRtc_UWord16 SamplesIn10MsecA = _inFileA.PayloadLength10Ms();
+ WebRtc_UWord32 timestampA = 1;
+ WebRtc_Word32 outFreqHzB = _outFileB.SamplingFrequency();
+
+ while(!_inFileA.EndOfFile())
+ {
+ _inFileA.Read10MsData(audioFrame);
+ //audioFrame._timeStamp = timestampA;
+ //timestampA += SamplesIn10MsecA;
+ CHECK_ERROR(_acmA->Add10MsData(audioFrame));
+
+ CHECK_ERROR(_acmA->Process());
+
+ CHECK_ERROR(_acmB->PlayoutData10Ms(outFreqHzB, audioFrame));
+ _outFileB.Write10MsData(audioFrame._payloadData, audioFrame._payloadDataLengthInSamples);
+ msecPassed += 10;
+ if(msecPassed >= 1000)
+ {
+ msecPassed = 0;
+ secPassed++;
+ }
+ if(((secPassed%5) == 4) && (msecPassed == 0) && (_testCntr > 14))
+ {
+ printf("%3u:%3u ", secPassed, msecPassed);
+ _acmA->SetFECStatus(false);
+ printf("FEC currently %s\n",(_acmA->FECStatus()?"ON":"OFF"));
+ }
+ if(((secPassed%5) == 4) && (msecPassed >= 990) && (_testCntr > 14))
+ {
+ printf("%3u:%3u ", secPassed, msecPassed);
+ _acmA->SetFECStatus(true);
+ printf("FEC currently %s\n",(_acmA->FECStatus()?"ON":"OFF"));
+ }
+ }
+ _inFileA.Rewind();
+}
+
+void TestFEC::OpenOutFile(WebRtc_Word16 testNumber)
+{
+ char fileName[500] = "./modules/audio_coding/main/test/res_tests/TestFEC_outFile_";
+ char cntrStr[10];
+
+ if(_testMode == 0)
+ {
+ sprintf(fileName, "./modules/audio_coding/main/test/res_autotests/TestFEC_outFile_");
+ }
+ sprintf(cntrStr, "%02d.pcm", testNumber);
+ strcat(fileName, cntrStr);
+ _outFileB.Open(fileName, 32000, "wb");
+}
+
+void TestFEC::DisplaySendReceiveCodec()
+{
+ CodecInst myCodecParam;
+ _acmA->SendCodec(myCodecParam);
+ printf("%s -> ", myCodecParam.plname);
+ _acmB->ReceiveCodec(myCodecParam);
+ printf("%s\n", myCodecParam.plname);
+}
diff --git a/src/modules/audio_coding/main/test/TestFEC.h b/src/modules/audio_coding/main/test/TestFEC.h
new file mode 100644
index 0000000..09d1009
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TestFEC.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_FEC_H
+#define TEST_FEC_H
+
+#include "ACMTest.h"
+#include "Channel.h"
+#include "PCMFile.h"
+
+class TestFEC : public ACMTest
+{
+public:
+ TestFEC(int testMode);
+ ~TestFEC();
+
+ void Perform();
+private:
+ // The default value of '-1' indicates that the registration is based only on codec name
+ // and a sampling frequncy matching is not required. This is useful for codecs which support
+ // several sampling frequency.
+ WebRtc_Word16 RegisterSendCodec(char side, char* codecName, WebRtc_Word32 sampFreqHz = -1);
+ void Run();
+ void OpenOutFile(WebRtc_Word16 testNumber);
+ void DisplaySendReceiveCodec();
+ WebRtc_Word32 SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode);
+ AudioCodingModule* _acmA;
+ AudioCodingModule* _acmB;
+
+ Channel* _channelA2B;
+
+ PCMFile _inFileA;
+ PCMFile _outFileB;
+ WebRtc_Word16 _testCntr;
+ int _testMode;
+};
+
+
+#endif
+
diff --git a/src/modules/audio_coding/main/test/TestStereo.cpp b/src/modules/audio_coding/main/test/TestStereo.cpp
new file mode 100644
index 0000000..bb4c40b
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TestStereo.cpp
@@ -0,0 +1,553 @@
+/*
+ * 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 "TestStereo.h"
+
+#include "common_types.h"
+#include "audio_coding_module_typedefs.h"
+#include "engine_configurations.h"
+#include <iostream>
+#include "utility.h"
+#include <cassert>
+#include "trace.h"
+
+
+// Class for simulating packet handling
+TestPackStereo::TestPackStereo():
+_receiverACM(NULL),
+_seqNo(0),
+_timeStampDiff(0),
+_lastInTimestamp(0),
+_totalBytes(0),
+_payloadSize(0),
+_noChannels(1),
+_codecType(0)
+{
+}
+TestPackStereo::~TestPackStereo()
+{
+}
+
+void
+TestPackStereo::RegisterReceiverACM(AudioCodingModule* acm)
+{
+ _receiverACM = acm;
+ return;
+}
+
+
+WebRtc_Word32
+TestPackStereo::SendData(
+ const FrameType frameType,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* fragmentation)
+{
+ WebRtcRTPHeader rtpInfo;
+ WebRtc_Word32 status;
+ WebRtc_UWord16 payloadDataSize = payloadSize;
+ WebRtc_UWord8 payloadDataMaster[60 * 32 * 2 * 2];
+ WebRtc_UWord8 payloadDataSlave[60 * 32 * 2 * 2];
+ bool twoBytePerSample = false;
+ bool oneBytePerSample = true;
+ bool frameBased = false;
+
+ rtpInfo.header.markerBit = false;
+ rtpInfo.header.ssrc = 0;
+ rtpInfo.header.sequenceNumber = _seqNo++;
+ rtpInfo.header.payloadType = payloadType;
+ rtpInfo.header.timestamp = timeStamp;
+ if(frameType == kFrameEmpty)
+ {
+ // Skip this frame
+ return 0;
+ }
+ if(frameType != kAudioFrameCN)
+ {
+ rtpInfo.type.Audio.isCNG = false;
+
+ // For stereo we need to call ACM with two incoming packets, one for each channel.
+ // Different packet-splitting depending on codec.
+ if (_codecType == 0) {
+ // one byte per sample
+ for (int i=0, j=0; i<payloadDataSize; i+=2, j++)
+ {
+ payloadDataMaster[j] = payloadData[i];
+ payloadDataSlave[j] = payloadData[i+1];
+ }
+ } else if (_codecType == 1) {
+ // two bytes per sample
+ for (int i=0, j=0; i<payloadDataSize; i+=4, j+=2)
+ {
+ payloadDataMaster[j] = payloadData[i];
+ payloadDataMaster[j+1] = payloadData[i+1];
+ payloadDataSlave[j] = payloadData[i+2];
+ payloadDataSlave[j+1] = payloadData[i+3];
+ }
+ } else if (_codecType == 2) {
+ // frameBased
+ memcpy(payloadDataMaster, &payloadData[0], payloadDataSize/2);
+ memcpy(payloadDataSlave, &payloadData[payloadDataSize/2], payloadDataSize/2);
+ } else if (_codecType == 3) {
+ // four bits per sample
+ for (int i=0, j=0; i<payloadDataSize; i+=2, j++)
+ {
+ payloadDataMaster[j] = (payloadData[i] & 0xF0) + (payloadData[i+1] >> 4);
+ payloadDataSlave[j] = ((payloadData[i] & 0x0F) << 4) + (payloadData[i+1] & 0x0F);
+ }
+ }
+ }
+ else
+ {
+ // If CNG packet, send the same packet to both master and slave.
+ rtpInfo.type.Audio.isCNG = true;
+ memcpy(payloadDataMaster, payloadData, payloadSize);
+ memcpy(payloadDataSlave, payloadData, payloadSize);
+ payloadDataSize = payloadSize*2;
+ }
+
+ // Call ACM with two packets, one for each channel
+ rtpInfo.type.Audio.channel = 1;
+ status = _receiverACM->IncomingPacket((WebRtc_Word8*)payloadDataMaster, payloadDataSize/2, rtpInfo);
+ rtpInfo.type.Audio.channel = 2;
+ status = _receiverACM->IncomingPacket((WebRtc_Word8*)payloadDataSlave, payloadDataSize/2, rtpInfo);
+
+ if (frameType != kAudioFrameCN) {
+ _payloadSize = payloadDataSize;
+ } else {
+ _payloadSize = -1;
+ }
+ _timeStampDiff = timeStamp - _lastInTimestamp;
+ _lastInTimestamp = timeStamp;
+ _totalBytes += payloadDataSize;
+ return status;
+}
+
+WebRtc_UWord16
+TestPackStereo::GetPayloadSize()
+{
+ return _payloadSize;
+}
+
+
+WebRtc_UWord32
+TestPackStereo::GetTimeStampDiff()
+{
+ return _timeStampDiff;
+}
+
+void
+TestPackStereo::ResetPayloadSize()
+{
+ _payloadSize = 0;
+}
+
+void
+TestPackStereo::SetCodecType(int codecType)
+{
+ _codecType = codecType;
+}
+
+TestStereo::TestStereo(int testMode):
+_acmA(NULL),
+_acmB(NULL),
+_channelA2B(NULL),
+_testCntr(0),
+_packSizeSamp(0),
+_packSizeBytes(0),
+_counter(0)
+{
+ // testMode = 0 for silent test (auto test)
+ _testMode = testMode;
+}
+
+using namespace std;
+TestStereo::~TestStereo()
+{
+ if(_acmA != NULL)
+ {
+ AudioCodingModule::Destroy(_acmA);
+ _acmA = NULL;
+ }
+ if(_acmB != NULL)
+ {
+ AudioCodingModule::Destroy(_acmB);
+ _acmB = NULL;
+ }
+ if(_channelA2B != NULL)
+ {
+ delete _channelA2B;
+ _channelA2B = NULL;
+ }
+}
+
+void TestStereo::Perform()
+{
+ char fileName[500];
+ WebRtc_UWord16 frequencyHz;
+
+ if(_testMode == 0)
+ {
+ printf("Running Stereo Test");
+ WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
+ "---------- TestStereo ----------");
+ }
+
+ strcpy(fileName, "./modules/audio_coding/main/test/teststereo32kHz.pcm");
+ frequencyHz = 32000;
+
+ _inFileA.Open(fileName, frequencyHz, "rb");
+ _inFileA.ReadStereo(true);
+
+ _acmA = AudioCodingModule::Create(0);
+ _acmB = AudioCodingModule::Create(1);
+
+ _acmA->InitializeReceiver();
+ _acmB->InitializeReceiver();
+
+ WebRtc_UWord8 numEncoders = _acmA->NumberOfCodecs();
+ CodecInst myCodecParam;
+
+ for(WebRtc_UWord8 n = 0; n < numEncoders; n++)
+ {
+ _acmB->Codec(n, myCodecParam);
+ if(!strcmp(myCodecParam.plname, "L16") ||
+ !strcmp(myCodecParam.plname, "PCMA")||
+ !strcmp(myCodecParam.plname, "PCMU")||
+ !strcmp(myCodecParam.plname, "G722"))
+ {
+ myCodecParam.channels=2;
+ _acmB->RegisterReceiveCodec(myCodecParam);
+ }
+ }
+
+ // Create and connect the channel
+ _channelA2B = new TestPackStereo;
+ _acmA->RegisterTransportCallback(_channelA2B);
+ _channelA2B->RegisterReceiverACM(_acmB);
+
+ // All codecs are tested for all allowed sampling frequencies, rates and packet sizes
+#ifdef WEBRTC_CODEC_G722
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _channelA2B->SetCodecType(3);
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecG722[] = "G722";
+ RegisterSendCodec('A', codecG722, 16000, 64000, 160);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 320);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 480);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 640);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 800);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 960);
+ Run(_channelA2B);
+ _acmA->SetVAD(true, true, VADNormal);
+ RegisterSendCodec('A', codecG722, 16000, 64000, 320);
+ Run(_channelA2B);
+ _acmA->SetVAD(false, false, VADNormal);
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_PCM16
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _channelA2B->SetCodecType(1);
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecL16[] = "L16";
+ RegisterSendCodec('A', codecL16, 8000, 128000, 80);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 8000, 128000, 160);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 8000, 128000, 240);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 8000, 128000, 320);
+ Run(_channelA2B);
+ _acmA->SetVAD(true, true, VADNormal);
+ RegisterSendCodec('A', codecL16, 8000, 128000, 80);
+ Run(_channelA2B);
+ _acmA->SetVAD(false, false, VADNormal);
+ _outFileB.Close();
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ RegisterSendCodec('A', codecL16, 16000, 256000, 160);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 16000, 256000, 320);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 16000, 256000, 480);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 16000, 256000, 640);
+ Run(_channelA2B);
+ _acmA->SetVAD(true, true, VADNormal);
+ RegisterSendCodec('A', codecL16, 16000, 256000, 160);
+ Run(_channelA2B);
+ _acmA->SetVAD(false, false, VADNormal);
+ _outFileB.Close();
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ RegisterSendCodec('A', codecL16, 32000, 512000, 320);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecL16, 32000, 512000, 640);
+ Run(_channelA2B);
+ _acmA->SetVAD(true, true, VADNormal);
+ RegisterSendCodec('A', codecL16, 32000, 512000, 320);
+ Run(_channelA2B);
+ _acmA->SetVAD(false, false, VADNormal);
+ _outFileB.Close();
+#endif
+#define PCMA_AND_PCMU
+#ifdef PCMA_AND_PCMU
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _channelA2B->SetCodecType(0);
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ char codecPCMA[] = "PCMA";
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 80);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 160);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 240);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 320);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 400);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 480);
+ _acmA->SetVAD(true, true, VADNormal);
+ RegisterSendCodec('A', codecPCMA, 8000, 64000, 80);
+ Run(_channelA2B);
+ _acmA->SetVAD(false, false, VADNormal);
+ _outFileB.Close();
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+ _testCntr++;
+ OpenOutFile(_testCntr);
+ Run(_channelA2B);
+ char codecPCMU[] = "PCMU";
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 80);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 160);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 240);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 320);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 400);
+ Run(_channelA2B);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 480);
+ _acmA->SetVAD(true, true, VADNormal);
+ RegisterSendCodec('A', codecPCMU, 8000, 64000, 80);
+ Run(_channelA2B);
+ _acmA->SetVAD(false, false, VADNormal);
+ Run(_channelA2B);
+ _outFileB.Close();
+ if(_testMode != 0) {
+ printf("=======================================================================\n");
+ } else {
+ printf(".");
+ }
+#endif
+
+ /* Print out which codecs were tested, and which were not, in the run */
+
+ if(_testMode != 0) {
+ printf("The following codecs was INCLUDED in the test:\n");
+#ifdef WEBRTC_CODEC_G722
+ printf(" G.722\n");
+#endif
+#ifdef WEBRTC_CODEC_PCM16
+ printf(" PCM16\n");
+#endif
+ printf(" G.711\n");
+
+ printf("\nTo complete the test, listen to the %d number of output files.\n", _testCntr);
+ } else {
+ printf("Done!\n");
+ }
+}
+
+// Register Codec to use in the test
+//
+// Input: side - which ACM to use, 'A' or 'B'
+// codecName - name to use when register the codec
+// samplingFreqHz - sampling frequency in Herz
+// rate - bitrate in bytes
+// packSize - packet size in samples
+// extraByte - if extra bytes needed compared to the bitrate
+// used when registering, can be an internal header
+// set to -1 if the codec is a variable rate codec
+WebRtc_Word16 TestStereo::RegisterSendCodec(char side,
+ char* codecName,
+ WebRtc_Word32 samplingFreqHz,
+ int rate,
+ int packSize)
+{
+ if(_testMode != 0) {
+ // Print out codec and settings
+ printf("codec: %s Freq: %d Rate: %d PackSize: %d", codecName, samplingFreqHz, rate, packSize);
+ }
+
+ // Store packetsize in samples, used to validate the recieved packet
+ _packSizeSamp = packSize;
+
+ // Store the expected packet size in bytes, used to validate the recieved packet
+ // Add 0.875 to always round up to a whole byte
+ _packSizeBytes = (WebRtc_UWord16)((float)(packSize*rate)/(float)(samplingFreqHz*8)+0.875);
+
+ // Set pointer to the ACM where to register the codec
+ AudioCodingModule* myACM;
+ switch(side)
+ {
+ case 'A':
+ {
+ myACM = _acmA;
+ break;
+ }
+ case 'B':
+ {
+ myACM = _acmB;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if(myACM == NULL)
+ {
+ assert(false);
+ return -1;
+ }
+ CodecInst myCodecParam;
+
+ // Get all codec paramters before registering
+ CHECK_ERROR(AudioCodingModule::Codec(codecName, myCodecParam, samplingFreqHz));
+ myCodecParam.rate = rate;
+ myCodecParam.pacsize = packSize;
+ myCodecParam.channels = 2;
+ CHECK_ERROR(myACM->RegisterSendCodec(myCodecParam));
+
+ // initialization was succesful
+ return 0;
+}
+
+void TestStereo::Run(TestPackStereo* channel)
+{
+ AudioFrame audioFrame;
+
+ WebRtc_UWord16 SamplesIn10MsecA = _inFileA.PayloadLength10Ms();
+ WebRtc_UWord32 timestampA = 1;
+ WebRtc_Word32 outFreqHzB = _outFileB.SamplingFrequency();
+ WebRtc_UWord16 recSize;
+ WebRtc_UWord32 timeStampDiff;
+ channel->ResetPayloadSize();
+ int errorCount = 0;
+
+ // Only run 1 second for each test case
+ while((_counter<1000)&& (!_inFileA.EndOfFile()))
+ {
+ // Add 10 msec to ACM
+ _inFileA.Read10MsData(audioFrame);
+ CHECK_ERROR(_acmA->Add10MsData(audioFrame));
+
+ // Run sender side of ACM
+ CHECK_ERROR(_acmA->Process());
+
+ // Verify that the received packet size matches the settings
+ recSize = channel->GetPayloadSize();
+ if ((0<recSize) & (recSize<65535)) {
+ if ((recSize != _packSizeBytes*2) && (_packSizeBytes < 65535)) {
+ errorCount++;
+ }
+
+ // Verify that the timestamp is updated with expected length
+ timeStampDiff = channel->GetTimeStampDiff();
+ if ((_counter > 10) && (timeStampDiff != _packSizeSamp)) {
+ errorCount++;
+ }
+ }
+
+ // Run received side of ACM
+ CHECK_ERROR(_acmB->PlayoutData10Ms(outFreqHzB, audioFrame));
+
+ // Write output speech to file
+ _outFileB.Write10MsData(audioFrame._payloadData, audioFrame._payloadDataLengthInSamples*audioFrame._audioChannel);
+ }
+
+ if (errorCount)
+ {
+ printf(" - test FAILED\n");
+ }
+ else if(_testMode != 0)
+ {
+ printf(" - test PASSED\n");
+ }
+
+ // Reset _counter
+ if (_counter == 1000) {
+ _counter = 0;
+ }
+ if (_inFileA.EndOfFile()) {
+ _inFileA.Rewind();
+ }
+}
+
+void TestStereo::OpenOutFile(WebRtc_Word16 testNumber)
+{
+ char fileName[500] = "./modules/audio_coding/main/test/res_tests/teststereo_out_";
+ char cntrStr[10];
+
+ sprintf(cntrStr, "%02d.pcm", testNumber);
+ strcat(fileName, cntrStr);
+
+ _outFileB.Open(fileName, 32000, "wb");
+}
+
+void TestStereo::DisplaySendReceiveCodec()
+{
+ CodecInst myCodecParam;
+ _acmA->SendCodec(myCodecParam);
+ if(_testMode != 0) {
+ printf("%s -> ", myCodecParam.plname);
+ }
+ _acmB->ReceiveCodec(myCodecParam);
+ if(_testMode != 0) {
+ printf("%s\n", myCodecParam.plname);
+ }
+}
+
diff --git a/src/modules/audio_coding/main/test/TestStereo.h b/src/modules/audio_coding/main/test/TestStereo.h
new file mode 100644
index 0000000..07c32de
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TestStereo.h
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_STEREO_H
+#define TEST_STEREO_H
+
+#include "ACMTest.h"
+#include "Channel.h"
+#include "PCMFile.h"
+
+class TestPackStereo : public AudioPacketizationCallback
+{
+public:
+ TestPackStereo();
+ ~TestPackStereo();
+
+ void RegisterReceiverACM(AudioCodingModule* acm);
+
+ virtual WebRtc_Word32 SendData(const FrameType frameType,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* fragmentation);
+
+ WebRtc_UWord16 GetPayloadSize();
+ WebRtc_UWord32 GetTimeStampDiff();
+ void ResetPayloadSize();
+ void SetCodecType(int codecType);
+
+
+private:
+ AudioCodingModule* _receiverACM;
+ WebRtc_Word16 _seqNo;
+ WebRtc_UWord8 _payloadData[60 * 32 * 2 * 2];
+ WebRtc_UWord32 _timeStampDiff;
+ WebRtc_UWord32 _lastInTimestamp;
+ WebRtc_UWord64 _totalBytes;
+ WebRtc_UWord16 _payloadSize;
+ WebRtc_UWord16 _noChannels;
+ int _codecType;
+};
+
+class TestStereo : public ACMTest
+{
+public:
+ TestStereo(int testMode);
+ ~TestStereo();
+
+ void Perform();
+private:
+ // The default value of '-1' indicates that the registration is based only on codec name
+ // and a sampling frequncy matching is not required. This is useful for codecs which support
+ // several sampling frequency.
+ WebRtc_Word16 RegisterSendCodec(char side,
+ char* codecName,
+ WebRtc_Word32 sampFreqHz,
+ int rate,
+ int packSize);
+
+ void Run(TestPackStereo* channel);
+ void OpenOutFile(WebRtc_Word16 testNumber);
+ void DisplaySendReceiveCodec();
+
+ WebRtc_Word32 SendData(
+ const FrameType frameType,
+ const WebRtc_UWord8 payloadType,
+ const WebRtc_UWord32 timeStamp,
+ const WebRtc_UWord8* payloadData,
+ const WebRtc_UWord16 payloadSize,
+ const RTPFragmentationHeader* fragmentation);
+
+ int _testMode;
+
+ AudioCodingModule* _acmA;
+ AudioCodingModule* _acmB;
+
+ TestPackStereo* _channelA2B;
+
+ PCMFile _inFileA;
+ PCMFile _outFileB;
+ PCMFile _inFileStereo;
+ WebRtc_Word16 _testCntr;
+ WebRtc_UWord16 _packSizeSamp;
+ WebRtc_UWord16 _packSizeBytes;
+ int _counter;
+ int _codecType;
+};
+
+
+#endif
+
diff --git a/src/modules/audio_coding/main/test/TestVADDTX.cpp b/src/modules/audio_coding/main/test/TestVADDTX.cpp
new file mode 100644
index 0000000..8186f62
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TestVADDTX.cpp
@@ -0,0 +1,503 @@
+/*
+ * 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 "TestVADDTX.h"
+
+#include "common_types.h"
+#include "audio_coding_module_typedefs.h"
+#include "utility.h"
+#include "engine_configurations.h"
+#include <iostream>
+#include "trace.h"
+
+
+TestVADDTX::TestVADDTX(int testMode):
+_acmA(NULL),
+_acmB(NULL),
+_channelA2B(NULL),
+_testResults(0)
+{
+ //testMode == 1 for more extensive testing
+ //testMode == 0 for quick test (autotest)
+ _testMode = testMode;
+}
+
+using namespace std;
+TestVADDTX::~TestVADDTX()
+{
+ if(_acmA != NULL)
+ {
+ AudioCodingModule::Destroy(_acmA);
+ _acmA = NULL;
+ }
+ if(_acmB != NULL)
+ {
+ AudioCodingModule::Destroy(_acmB);
+ _acmB = NULL;
+ }
+ if(_channelA2B != NULL)
+ {
+ delete _channelA2B;
+ _channelA2B = NULL;
+ }
+}
+
+void TestVADDTX::Perform()
+{
+
+ if(_testMode == 0)
+ {
+ printf("Running VAD/DTX Test");
+ WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
+ "---------- TestVADDTX ----------");
+ }
+ char fileName[] = "./modules/audio_coding/main/test/testfile32kHz.pcm";
+ _inFileA.Open(fileName, 32000, "rb");
+
+ _acmA = AudioCodingModule::Create(0);
+ _acmB = AudioCodingModule::Create(1);
+
+ _acmA->InitializeReceiver();
+ _acmB->InitializeReceiver();
+
+ WebRtc_UWord8 numEncoders = _acmA->NumberOfCodecs();
+ CodecInst myCodecParam;
+ if(_testMode != 0)
+ {
+ printf("Registering codecs at receiver... \n");
+ }
+ for(WebRtc_UWord8 n = 0; n < numEncoders; n++)
+ {
+ _acmB->Codec(n, myCodecParam);
+ if(_testMode != 0)
+ {
+ printf("%s\n", myCodecParam.plname);
+ }
+ _acmB->RegisterReceiveCodec(myCodecParam);
+ }
+
+ // Create and connect the channel
+ _channelA2B = new Channel;
+ _acmA->RegisterTransportCallback(_channelA2B);
+ _channelA2B->RegisterReceiverACM(_acmB);
+
+ _acmA->RegisterVADCallback(&_monitor);
+
+
+ WebRtc_Word16 testCntr = 1;
+ VADDTXstruct setDTX, getDTX, expectedDTX;
+ bool dtxReplaced;
+ WebRtc_Word16 testResults = 0;
+
+#ifdef WEBRTC_CODEC_ISAC
+ // Open outputfile
+ OpenOutFile(testCntr++);
+
+ // Register iSAC WB as send codec
+ char nameISAC[] = "ISAC";
+ RegisterSendCodec('A', nameISAC, 16000);
+
+ // Run the five test cased
+ runTestCases();
+
+ // Close file
+ _outFileB.Close();
+
+ // Open outputfile
+ OpenOutFile(testCntr++);
+
+ // Register iSAC SWB as send codec
+ RegisterSendCodec('A', nameISAC, 32000);
+
+ // Run the five test cased
+ runTestCases();
+
+ // Close file
+ _outFileB.Close();
+#endif
+#ifdef WEBRTC_CODEC_ILBC
+ // Open outputfile
+ OpenOutFile(testCntr++);
+
+ // Register iLBC as send codec
+ char nameILBC[] = "ilbc";
+ RegisterSendCodec('A', nameILBC);
+
+ // Run the five test cased
+ runTestCases();
+
+ // Close file
+ _outFileB.Close();
+
+#endif
+ if(_testMode) {
+ printf("Done!\n");
+ }
+
+ printf("VAD/DTX test completed with %d subtests failed\n", testResults);
+ if (testResults > 0)
+ {
+ printf("Press return\n\n", testResults);
+ getchar();
+ }
+}
+
+void TestVADDTX::runTestCases()
+{
+ if(_testMode != 0)
+ {
+ CodecInst myCodecParam;
+ _acmA->SendCodec(myCodecParam);
+ printf("%s\n", myCodecParam.plname);
+ }
+ else
+ {
+ printf(".");
+ }
+ // #1 DTX = OFF, VAD = ON, VADNormal
+ if(_testMode != 0)
+ printf("Test #1 ");
+ SetVAD(false, true, VADNormal);
+ Run();
+ _testResults += VerifyTest();
+
+ // #2 DTX = OFF, VAD = ON, VADAggr
+ if(_testMode != 0)
+ printf("Test #2 ");
+ SetVAD(false, true, VADAggr);
+ Run();
+ _testResults += VerifyTest();
+
+ // #3 DTX = ON, VAD = ON, VADLowBitrate
+ if(_testMode != 0)
+ printf("Test #3 ");
+ SetVAD(true, true, VADLowBitrate);
+ Run();
+ _testResults += VerifyTest();
+
+ // #4 DTX = ON, VAD = ON, VADVeryAggr
+ if(_testMode != 0)
+ printf("Test #4 ");
+ SetVAD(true, true, VADVeryAggr);
+ Run();
+ _testResults += VerifyTest();
+
+ // #5 DTX = ON, VAD = OFF, VADNormal
+ if(_testMode != 0)
+ printf("Test #5 ");
+ SetVAD(true, false, VADNormal);
+ Run();
+ _testResults += VerifyTest();
+
+}
+void TestVADDTX::runTestInternalDTX()
+{
+ // #6 DTX = ON, VAD = ON, VADNormal
+ if(_testMode != 0)
+ printf("Test #6 ");
+
+ SetVAD(true, true, VADNormal);
+ if(_acmA->ReplaceInternalDTXWithWebRtc(true) < 0) {
+ printf("Was not able to replace DTX since CN was not registered\n");
+ }
+ Run();
+ _testResults += VerifyTest();
+}
+
+void TestVADDTX::SetVAD(bool statusDTX, bool statusVAD, WebRtc_Word16 vadMode)
+{
+ WebRtc_Word32 status;
+ bool dtxEnabled, vadEnabled;
+ ACMVADMode vadModeSet;
+
+ status = _acmA->SetVAD(statusDTX, statusVAD, (ACMVADMode) vadMode);
+ status = _acmA->VAD(dtxEnabled, vadEnabled, vadModeSet);
+
+ if(_testMode != 0)
+ {
+ if(statusDTX != dtxEnabled)
+ {
+ printf("DTX: %s not the same as requested: %s\n",
+ dtxEnabled? "ON":"OFF", dtxEnabled? "OFF":"ON");
+ }
+ if((statusVAD == true) && (vadEnabled == false) ||
+ (statusVAD == false) && (vadEnabled == false) && (statusDTX == true))
+ {
+ printf("VAD: %s not the same as requested: %s\n",
+ vadEnabled? "ON":"OFF", vadEnabled? "OFF":"ON");
+ }
+ if(vadModeSet != vadMode)
+ {
+ printf("VAD mode: %d not the same as requested: %d\n",
+ (WebRtc_Word16)vadModeSet, (WebRtc_Word16)vadMode);
+ }
+ }
+
+ // Requested VAD/DTX settings
+ _setStruct.statusDTX = statusDTX;
+ _setStruct.statusVAD = statusVAD;
+ _setStruct.vadMode = (ACMVADMode) vadMode;
+
+ // VAD settings after setting VAD in ACM
+ _getStruct.statusDTX = dtxEnabled;
+ _getStruct.statusVAD = vadEnabled;
+ _getStruct.vadMode = vadModeSet;
+
+}
+
+VADDTXstruct TestVADDTX::GetVAD()
+{
+ VADDTXstruct retStruct;
+ WebRtc_Word32 status;
+ bool dtxEnabled, vadEnabled;
+ ACMVADMode vadModeSet;
+
+ status = _acmA->VAD(dtxEnabled, vadEnabled, vadModeSet);
+
+ retStruct.statusDTX = dtxEnabled;
+ retStruct.statusVAD = vadEnabled;
+ retStruct.vadMode = vadModeSet;
+ return retStruct;
+}
+
+WebRtc_Word16 TestVADDTX::RegisterSendCodec(char side,
+ char* codecName,
+ WebRtc_Word32 samplingFreqHz,
+ WebRtc_Word32 rateKbps)
+{
+ if(_testMode != 0)
+ {
+ printf("Registering %s for side %c\n", codecName, side);
+ }
+ cout << flush;
+ AudioCodingModule* myACM;
+ switch(side)
+ {
+ case 'A':
+ {
+ myACM = _acmA;
+ break;
+ }
+ case 'B':
+ {
+ myACM = _acmB;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if(myACM == NULL)
+ {
+ return -1;
+ }
+
+ CodecInst myCodecParam;
+ for(WebRtc_Word16 codecCntr = 0; codecCntr < myACM->NumberOfCodecs();
+ codecCntr++)
+ {
+ CHECK_ERROR(myACM->Codec((WebRtc_UWord8)codecCntr, myCodecParam));
+ if(!STR_CASE_CMP(myCodecParam.plname, codecName))
+ {
+ if((samplingFreqHz == -1) || (myCodecParam.plfreq == samplingFreqHz))
+ {
+ if((rateKbps == -1) || (myCodecParam.rate == rateKbps))
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ CHECK_ERROR(myACM->RegisterSendCodec(myCodecParam));
+
+ // initialization was succesful
+ return 0;
+}
+
+void TestVADDTX::Run()
+{
+ AudioFrame audioFrame;
+
+ WebRtc_UWord16 SamplesIn10MsecA = _inFileA.PayloadLength10Ms();
+ WebRtc_UWord32 timestampA = 1;
+ WebRtc_Word32 outFreqHzB = _outFileB.SamplingFrequency();
+
+ while(!_inFileA.EndOfFile())
+ {
+ _inFileA.Read10MsData(audioFrame);
+ audioFrame._timeStamp = timestampA;
+ timestampA += SamplesIn10MsecA;
+ CHECK_ERROR(_acmA->Add10MsData(audioFrame));
+
+ CHECK_ERROR(_acmA->Process());
+
+ CHECK_ERROR(_acmB->PlayoutData10Ms(outFreqHzB, audioFrame));
+ _outFileB.Write10MsData(audioFrame._payloadData, audioFrame._payloadDataLengthInSamples);
+ }
+#ifdef PRINT_STAT
+ _monitor.PrintStatistics(_testMode);
+#endif
+ _inFileA.Rewind();
+ _monitor.GetStatistics(_statCounter);
+ _monitor.ResetStatistics();
+}
+
+void TestVADDTX::OpenOutFile(WebRtc_Word16 testNumber)
+{
+ char fileName[500] = "./modules/audio_coding/main/test/res_tests/testVADDTX_outFile_";
+ char cntrStr[10];
+
+ if(_testMode == 0)
+ {
+ sprintf(fileName, "./modules/audio_coding/main/test/res_autotests/testVADDTX_outFile_");
+ }
+ sprintf(cntrStr, "%02d.pcm", testNumber);
+ strcat(fileName, cntrStr);
+ _outFileB.Open(fileName, 16000, "wb");
+}
+
+
+WebRtc_Word16 TestVADDTX::VerifyTest()
+{
+ // Verify empty frame result
+ WebRtc_UWord8 statusEF = 0;
+ WebRtc_UWord8 vadPattern = 0;
+ WebRtc_UWord8 emptyFramePattern[6];
+ CodecInst myCodecParam;
+ _acmA->SendCodec(myCodecParam);
+ bool dtxInUse = true;
+ bool isReplaced = false;
+ if ((STR_CASE_CMP(myCodecParam.plname,"G729") == 0) ||
+ (STR_CASE_CMP(myCodecParam.plname,"G723") == 0) ||
+ (STR_CASE_CMP(myCodecParam.plname,"AMR") == 0) ||
+ (STR_CASE_CMP(myCodecParam.plname,"AMR-wb") == 0) ||
+ (STR_CASE_CMP(myCodecParam.plname,"speex") == 0))
+ {
+ _acmA->IsInternalDTXReplacedWithWebRtc(isReplaced);
+ if (!isReplaced)
+ {
+ dtxInUse = false;
+ }
+ }
+
+ // Check for error in VAD/DTX settings
+ if (_getStruct.statusDTX != _setStruct.statusDTX){
+ // DTX status doesn't match expected
+ vadPattern |= 4;
+ }
+ if (_getStruct.statusDTX){
+ if ((!_getStruct.statusVAD && dtxInUse) || (!dtxInUse && (_getStruct.statusVAD !=_setStruct.statusVAD)))
+ {
+ // Missmatch in VAD setting
+ vadPattern |= 2;
+ }
+ } else {
+ if (_getStruct.statusVAD != _setStruct.statusVAD){
+ // VAD status doesn't match expected
+ vadPattern |= 2;
+ }
+ }
+ if (_getStruct.vadMode != _setStruct.vadMode){
+ // VAD Mode doesn't match expected
+ vadPattern |= 1;
+ }
+
+ // Set expected empty frame pattern
+ int ii;
+ for (ii = 0; ii < 6; ii++) {
+ emptyFramePattern[ii] = 0;
+ }
+ emptyFramePattern[0] = 1; // "kNoEncoding", not important to check. Codecs with packetsize != 80 samples will get this output.
+ emptyFramePattern[1] = 1; // Expect to always receive some frames labeled "kActiveNormalEncoded"
+ emptyFramePattern[2] = (((!_getStruct.statusDTX && _getStruct.statusVAD) || (!dtxInUse && _getStruct.statusDTX))); // "kPassiveNormalEncoded"
+ emptyFramePattern[3] = ((_getStruct.statusDTX && dtxInUse && (_acmA->SendFrequency() == 8000))); // "kPassiveDTXNB"
+ emptyFramePattern[4] = ((_getStruct.statusDTX && dtxInUse && (_acmA->SendFrequency() == 16000))); // "kPassiveDTXWB"
+ emptyFramePattern[5] = ((_getStruct.statusDTX && dtxInUse && (_acmA->SendFrequency() == 32000))); // "kPassiveDTXSWB"
+
+ // Check pattern 1-5 (skip 0)
+ for (int ii = 1; ii < 6; ii++)
+ {
+ if (emptyFramePattern[ii])
+ {
+ statusEF |= (_statCounter[ii] == 0);
+ }
+ else
+ {
+ statusEF |= (_statCounter[ii] > 0);
+ }
+ }
+ if ((statusEF == 0) && (vadPattern == 0))
+ {
+ if(_testMode != 0)
+ {
+ printf(" Test OK!\n");
+ }
+ return 0;
+ }
+ else
+ {
+ if (statusEF)
+ {
+ printf("\t\t\tUnexpected empty frame result!\n");
+ }
+ if (vadPattern)
+ {
+ printf("\t\t\tUnexpected SetVAD() result!\tDTX: %d\tVAD: %d\tMode: %d\n", (vadPattern >> 2) & 1, (vadPattern >> 1) & 1, vadPattern & 1);
+ }
+ return 1;
+ }
+}
+
+ActivityMonitor::ActivityMonitor()
+{
+ _counter[0] = _counter[1] = _counter[2] = _counter[3] = _counter[4] = _counter[5] = 0;
+}
+
+ActivityMonitor::~ActivityMonitor()
+{
+}
+
+WebRtc_Word32 ActivityMonitor::InFrameType(WebRtc_Word16 frameType)
+{
+ _counter[frameType]++;
+ return 0;
+}
+
+void ActivityMonitor::PrintStatistics(int testMode)
+{
+ if(testMode != 0)
+ {
+ printf("\n");
+ printf("kActiveNormalEncoded kPassiveNormalEncoded kPassiveDTXWB kPassiveDTXNB kPassiveDTXSWB kFrameEmpty\n");
+
+ printf("%19u", _counter[1]);
+ printf("%22u", _counter[2]);
+ printf("%14u", _counter[3]);
+ printf("%14u", _counter[4]);
+ printf("%14u", _counter[5]);
+ printf("%11u", _counter[0]);
+
+ printf("\n\n");
+ }
+}
+
+void ActivityMonitor::ResetStatistics()
+{
+ _counter[0] = _counter[1] = _counter[2] = _counter[3] = _counter[4] = _counter[5] = 0;
+}
+
+void ActivityMonitor::GetStatistics(WebRtc_UWord32* getCounter)
+{
+ for (int ii = 0; ii < 6; ii++)
+ {
+ getCounter[ii] = _counter[ii];
+ }
+}
diff --git a/src/modules/audio_coding/main/test/TestVADDTX.h b/src/modules/audio_coding/main/test/TestVADDTX.h
new file mode 100644
index 0000000..cf9088b
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TestVADDTX.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_VAD_DTX_H
+#define TEST_VAD_DTX_H
+
+#include "ACMTest.h"
+#include "Channel.h"
+#include "PCMFile.h"
+
+typedef struct
+{
+ bool statusDTX;
+ bool statusVAD;
+ ACMVADMode vadMode;
+} VADDTXstruct;
+
+class ActivityMonitor : public ACMVADCallback
+{
+public:
+ ActivityMonitor();
+ ~ActivityMonitor();
+ WebRtc_Word32 InFrameType(WebRtc_Word16 frameType);
+ void PrintStatistics(int testMode);
+ void ResetStatistics();
+ void GetStatistics(WebRtc_UWord32* getCounter);
+private:
+ // counting according to
+ /*enum WebRtcACMEncodingType
+ {
+ kNoEncoding,
+ kActiveNormalEncoded,
+ kPassiveNormalEncoded,
+ kPassiveDTXNB,
+ kPassiveDTXWB,
+ kPassiveDTXSWB
+ };*/
+ WebRtc_UWord32 _counter[6];
+};
+
+class TestVADDTX : public ACMTest
+{
+public:
+ TestVADDTX(int testMode);
+ ~TestVADDTX();
+
+ void Perform();
+private:
+ // Registration can be based on codec name only, codec name and sampling frequency, or
+ // codec name, sampling frequency and rate.
+ WebRtc_Word16 RegisterSendCodec(char side,
+ char* codecName,
+ WebRtc_Word32 samplingFreqHz = -1,
+ WebRtc_Word32 rateKhz = -1);
+ void Run();
+ void OpenOutFile(WebRtc_Word16 testNumber);
+ void runTestCases();
+ void runTestInternalDTX();
+ void SetVAD(bool statusDTX, bool statusVAD, WebRtc_Word16 vadMode);
+ VADDTXstruct GetVAD();
+ WebRtc_Word16 VerifyTest();//VADDTXstruct setDTX, VADDTXstruct getDTX);
+ AudioCodingModule* _acmA;
+ AudioCodingModule* _acmB;
+
+ Channel* _channelA2B;
+
+ PCMFile _inFileA;
+ PCMFile _outFileB;
+
+ ActivityMonitor _monitor;
+ WebRtc_UWord32 _statCounter[6];
+
+ int _testMode;
+ int _testResults;
+ VADDTXstruct _setStruct;
+ VADDTXstruct _getStruct;
+};
+
+
+#endif
diff --git a/src/modules/audio_coding/main/test/Tester.cpp b/src/modules/audio_coding/main/test/Tester.cpp
new file mode 100644
index 0000000..1049cad
--- /dev/null
+++ b/src/modules/audio_coding/main/test/Tester.cpp
@@ -0,0 +1,131 @@
+/*
+ * 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 <stdio.h>
+#include <vector>
+
+#include "audio_coding_module.h"
+#include "trace.h"
+
+#include "APITest.h"
+#include "EncodeDecodeTest.h"
+#include "EncodeToFileTest.h"
+#include "iSACTest.h"
+#include "SpatialAudio.h"
+#include "TestAllCodecs.h"
+#include "TestFEC.h"
+#include "TestStereo.h"
+#include "TestVADDTX.h"
+#include "TwoWayCommunication.h"
+
+// Be sure to create the following directories before running the tests:
+// ./modules/audio_coding/main/test/res_tests
+// ./modules/audio_coding/main/test/res_autotests
+
+// Choose what tests to run by defining one or more of the following:
+#define ACM_AUTO_TEST // Most common codecs and settings will be tested
+//#define ACM_TEST_ENC_DEC // You decide what to test in run time.
+ // Used for debugging and for testing while implementing.
+//#define ACM_TEST_TWO_WAY // Debugging
+//#define ACM_TEST_ALL_ENC_DEC // Loop through all defined codecs and settings
+//#define ACM_TEST_STEREO // Run stereo and spatial audio tests
+//#define ACM_TEST_VAD_DTX // Run all VAD/DTX tests
+//#define ACM_TEST_FEC // Test FEC (also called RED)
+//#define ACM_TEST_CODEC_SPEC_API // Only iSAC has codec specfic APIs in this version
+//#define ACM_TEST_FULL_API // Test all APIs with threads (long test)
+
+
+void PopulateTests(std::vector<ACMTest*>* tests)
+{
+
+ Trace::CreateTrace();
+ Trace::SetTraceFile("./modules/audio_coding/main/test/res_tests/test_trace.txt");
+
+ printf("The following tests will be executed:\n");
+#ifdef ACM_AUTO_TEST
+ printf(" ACM auto test\n");
+ tests->push_back(new EncodeDecodeTest(0));
+ tests->push_back(new TwoWayCommunication(0));
+ tests->push_back(new TestAllCodecs(0));
+ tests->push_back(new TestStereo(0));
+ tests->push_back(new SpatialAudio(0));
+ tests->push_back(new TestVADDTX(0));
+ tests->push_back(new TestFEC(0));
+ tests->push_back(new ISACTest(0));
+#endif
+#ifdef ACM_TEST_ENC_DEC
+ printf(" ACM encode-decode test\n");
+ tests->push_back(new EncodeDecodeTest(2));
+#endif
+#ifdef ACM_TEST_TWO_WAY
+ printf(" ACM two-way communication test\n");
+ tests->push_back(new TwoWayCommunication(1));
+#endif
+#ifdef ACM_TEST_ALL_ENC_DEC
+ printf(" ACM all codecs test\n");
+ tests->push_back(new TestAllCodecs(1));
+#endif
+#ifdef ACM_TEST_STEREO
+ printf(" ACM stereo test\n");
+ tests->push_back(new TestStereo(1));
+ tests->push_back(new SpatialAudio(2));
+#endif
+#ifdef ACM_TEST_VAD_DTX
+ printf(" ACM VAD-DTX test\n");
+ tests->push_back(new TestVADDTX(1));
+#endif
+#ifdef ACM_TEST_FEC
+ printf(" ACM FEC test\n");
+ tests->push_back(new TestFEC(1));
+#endif
+#ifdef ACM_TEST_CODEC_SPEC_API
+ printf(" ACM codec API test\n");
+ tests->push_back(new ISACTest(1));
+#endif
+#ifdef ACM_TEST_FULL_API
+ printf(" ACM full API test\n");
+ tests->push_back(new APITest());
+#endif
+ printf("\n");
+}
+
+int main()
+{
+ std::vector<ACMTest*> tests;
+ PopulateTests(&tests);
+ std::vector<ACMTest*>::iterator it;
+ WebRtc_Word8 version[5000];
+ version[0] = '\0';
+
+ WebRtc_UWord32 remainingBufferInByte = 4999;
+ WebRtc_UWord32 position = 0;
+ AudioCodingModule::GetVersion(version, remainingBufferInByte, position);
+
+ printf("%s\n", version);
+ for (it=tests.begin() ; it < tests.end(); it++)
+ {
+ try {
+
+ (*it)->Perform();
+ }
+ catch (char *except)
+ {
+ printf("Test failed with message: %s", except);
+ getchar();
+ return -1;
+ }
+ delete (*it);
+ }
+
+ Trace::ReturnTrace();
+ printf("ACM test completed\n");
+
+ return 0;
+}
diff --git a/src/modules/audio_coding/main/test/TimedTrace.cpp b/src/modules/audio_coding/main/test/TimedTrace.cpp
new file mode 100644
index 0000000..6bf301f
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TimedTrace.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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 "TimedTrace.h"
+#include <math.h>
+
+double TimedTrace::_timeEllapsedSec = 0;
+FILE* TimedTrace::_timedTraceFile = NULL;
+
+TimedTrace::TimedTrace()
+{
+
+}
+
+TimedTrace::~TimedTrace()
+{
+ if(_timedTraceFile != NULL)
+ {
+ fclose(_timedTraceFile);
+ }
+ _timedTraceFile = NULL;
+}
+
+WebRtc_Word16
+TimedTrace::SetUp(char* fileName)
+{
+ if(_timedTraceFile == NULL)
+ {
+ _timedTraceFile = fopen(fileName, "w");
+ }
+ if(_timedTraceFile == NULL)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+void
+TimedTrace::SetTimeEllapsed(double timeEllapsedSec)
+{
+ _timeEllapsedSec = timeEllapsedSec;
+}
+
+double
+TimedTrace::TimeEllapsed()
+{
+ return _timeEllapsedSec;
+}
+
+void
+TimedTrace::Tick10Msec()
+{
+ _timeEllapsedSec += 0.010;
+}
+
+void
+TimedTrace::TimedLogg(char* message)
+{
+ unsigned int minutes = (WebRtc_UWord32)floor(_timeEllapsedSec / 60.0);
+ double seconds = _timeEllapsedSec - minutes * 60;
+ //char myFormat[100] = "%8.2f, %3u:%05.2f: %s\n";
+ if(_timedTraceFile != NULL)
+ {
+ fprintf(_timedTraceFile, "%8.2f, %3u:%05.2f: %s\n",
+ _timeEllapsedSec,
+ minutes,
+ seconds,
+ message);
+ }
+}
diff --git a/src/modules/audio_coding/main/test/TimedTrace.h b/src/modules/audio_coding/main/test/TimedTrace.h
new file mode 100644
index 0000000..d37d287
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TimedTrace.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef TIMED_TRACE_H
+#define TIMED_TRACE_H
+
+#include "typedefs.h"
+
+#include <cstdio>
+#include <cstdlib>
+
+
+class TimedTrace
+{
+public:
+ TimedTrace();
+ ~TimedTrace();
+
+ void SetTimeEllapsed(double myTime);
+ double TimeEllapsed();
+ void Tick10Msec();
+ WebRtc_Word16 SetUp(char* fileName);
+ void TimedLogg(char* message);
+
+private:
+ static double _timeEllapsedSec;
+ static FILE* _timedTraceFile;
+
+};
+
+#endif
diff --git a/src/modules/audio_coding/main/test/TwoWayCommunication.cpp b/src/modules/audio_coding/main/test/TwoWayCommunication.cpp
new file mode 100644
index 0000000..21d4012
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TwoWayCommunication.cpp
@@ -0,0 +1,503 @@
+/*
+ * 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 <cctype>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef WIN32
+#include <Windows.h>
+#endif
+
+#include "TwoWayCommunication.h"
+#include "engine_configurations.h"
+#include "PCMFile.h"
+#include "utility.h"
+#include "trace.h"
+#include "common_types.h"
+
+using 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] = "";
+ fgets(myStr, 10, stdin);
+ *codecID_A = (WebRtc_UWord8)atoi(myStr);
+
+ printf("\nChoose a send codec for side B [0]: ");
+ fgets(myStr, 10, stdin);
+ *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: ");
+ fgets(tmpName, MAX_FILE_NAME_LENGTH_BYTE, stdin);
+ 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);
+ fgets(tmpName, 6, stdin);
+ 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, "./modules/audio_coding/main/test/testfile32kHz.pcm");
+ frequencyHz = 32000;
+ printf("Enter input file at side A [%s]: ", fileName);
+ ChooseFile(fileName, 499, &frequencyHz);
+
+
+ _inFileA.Open(fileName, frequencyHz, "rb");
+
+ //--- Output A
+ strcpy(fileName, "outA.pcm");
+ 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, "./modules/audio_coding/main/test/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
+ strcpy(fileName, "outB.pcm");
+ 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, "./modules/audio_coding/main/test/testfile32kHz.pcm");
+ frequencyHz = 16000;
+ _inFileA.Open(fileName, frequencyHz, "rb");
+
+ //--- Output A
+ strcpy(fileName, "./modules/audio_coding/main/test/res_autotests/outAutotestA.pcm");
+ frequencyHz = 16000;
+ _outFileA.Open(fileName, frequencyHz, "wb");
+ strcpy(refFileName, "./modules/audio_coding/main/test/res_autotests/ref_outAutotestA.pcm");
+ _outFileRefA.Open(refFileName, frequencyHz, "wb");
+
+ //--- Input B
+ strcpy(fileName, "./modules/audio_coding/main/test/testfile32kHz.pcm");
+ frequencyHz = 16000;
+ _inFileB.Open(fileName, frequencyHz, "rb");
+
+ //--- Output B
+ strcpy(fileName, "./modules/audio_coding/main/test/res_autotests/outAutotestB.pcm");
+ frequencyHz = 16000;
+ _outFileB.Open(fileName, frequencyHz, "wb");
+ strcpy(refFileName, "./modules/audio_coding/main/test/res_autotests/ref_outAutotestB.pcm");
+ _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(webrtc::kTraceStateInfo, webrtc::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(webrtc::kTraceStateInfo, webrtc::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(webrtc::kTraceStateInfo, webrtc::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(webrtc::kTraceStateInfo, webrtc::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(webrtc::kTraceStateInfo, webrtc::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
+
+
+}
+
diff --git a/src/modules/audio_coding/main/test/TwoWayCommunication.h b/src/modules/audio_coding/main/test/TwoWayCommunication.h
new file mode 100644
index 0000000..66ede04
--- /dev/null
+++ b/src/modules/audio_coding/main/test/TwoWayCommunication.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef TWO_WAY_COMMUNICATION_H
+#define TWO_WAY_COMMUNICATION_H
+
+#include "ACMTest.h"
+#include "Channel.h"
+#include "PCMFile.h"
+#include "audio_coding_module.h"
+#include "utility.h"
+
+
+class TwoWayCommunication : public ACMTest
+{
+public:
+ TwoWayCommunication(int testMode = 1);
+ ~TwoWayCommunication();
+
+ void Perform();
+private:
+ WebRtc_UWord8 ChooseCodec(WebRtc_UWord8* codecID_A, WebRtc_UWord8* codecID_B);
+ WebRtc_Word16 ChooseFile(char* fileName, WebRtc_Word16 maxLen, WebRtc_UWord16* frequencyHz);
+ WebRtc_Word16 SetUp();
+ WebRtc_Word16 SetUpAutotest();
+
+ AudioCodingModule* _acmA;
+ AudioCodingModule* _acmB;
+
+ AudioCodingModule* _acmRefA;
+ AudioCodingModule* _acmRefB;
+
+ Channel* _channel_A2B;
+ Channel* _channel_B2A;
+
+ Channel* _channelRef_A2B;
+ Channel* _channelRef_B2A;
+
+ PCMFile _inFileA;
+ PCMFile _inFileB;
+
+ PCMFile _outFileA;
+ PCMFile _outFileB;
+
+ PCMFile _outFileRefA;
+ PCMFile _outFileRefB;
+
+ DTMFDetector* _dtmfDetectorA;
+ DTMFDetector* _dtmfDetectorB;
+
+ int _testMode;
+};
+
+
+#endif
diff --git a/src/modules/audio_coding/main/test/iSACTest.cpp b/src/modules/audio_coding/main/test/iSACTest.cpp
new file mode 100644
index 0000000..b1c0119
--- /dev/null
+++ b/src/modules/audio_coding/main/test/iSACTest.cpp
@@ -0,0 +1,597 @@
+/*
+ * 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 <cctype>
+#include <stdio.h>
+#include <string.h>
+
+#if _WIN32
+#include <windows.h>
+#elif WEBRTC_LINUX
+#include <ctime>
+#else
+#include <sys/time.h>
+#include <time.h>
+#endif
+
+#include "event_wrapper.h"
+#include "iSACTest.h"
+#include "utility.h"
+#include "trace.h"
+
+#include "tick_util.h"
+
+
+void SetISACConfigDefault(
+ ACMTestISACConfig& isacConfig)
+{
+ isacConfig.currentRateBitPerSec = 0;
+ isacConfig.currentFrameSizeMsec = 0;
+ isacConfig.maxRateBitPerSec = 0;
+ isacConfig.maxPayloadSizeByte = 0;
+ isacConfig.encodingMode = -1;
+ isacConfig.initRateBitPerSec = 0;
+ isacConfig.initFrameSizeInMsec = 0;
+ isacConfig.enforceFrameSize = false;
+ return;
+}
+
+
+WebRtc_Word16 SetISAConfig(
+ ACMTestISACConfig& isacConfig,
+ AudioCodingModule* acm,
+ int testMode)
+{
+
+ if((isacConfig.currentRateBitPerSec != 0) ||
+ (isacConfig.currentFrameSizeMsec != 0))
+ {
+ CodecInst sendCodec;
+ acm->SendCodec(sendCodec);
+ if(isacConfig.currentRateBitPerSec < 0)
+ {
+ sendCodec.rate = -1;
+ CHECK_ERROR(acm->RegisterSendCodec(sendCodec));
+ if(testMode != 0)
+ {
+ printf("ISAC-%s Registered in adaptive (channel-dependent) mode.\n",
+ (sendCodec.plfreq == 32000)? "swb":"wb");
+ }
+ }
+ else
+ {
+
+ if(isacConfig.currentRateBitPerSec != 0)
+ {
+ sendCodec.rate = isacConfig.currentRateBitPerSec;
+ }
+ if(isacConfig.currentFrameSizeMsec != 0)
+ {
+ sendCodec.pacsize = isacConfig.currentFrameSizeMsec *
+ (sendCodec.plfreq / 1000);
+ }
+ CHECK_ERROR(acm->RegisterSendCodec(sendCodec));
+ if(testMode != 0)
+ {
+ printf("Target rate is set to %d bit/sec with frame-size %d ms \n",
+ (int)isacConfig.currentRateBitPerSec,
+ (int)sendCodec.pacsize / (sendCodec.plfreq / 1000));
+ }
+ }
+ }
+
+ if(isacConfig.maxRateBitPerSec > 0)
+ {
+ CHECK_ERROR(acm->SetISACMaxRate(isacConfig.maxRateBitPerSec));
+ if(testMode != 0)
+ {
+ printf("Max rate is set to %u bit/sec\n",
+ isacConfig.maxRateBitPerSec);
+ }
+ }
+ if(isacConfig.maxPayloadSizeByte > 0)
+ {
+ CHECK_ERROR(acm->SetISACMaxPayloadSize(isacConfig.maxPayloadSizeByte));
+ if(testMode != 0)
+ {
+ printf("Max payload-size is set to %u bit/sec\n",
+ isacConfig.maxPayloadSizeByte);
+ }
+ }
+ if((isacConfig.initFrameSizeInMsec != 0) ||
+ (isacConfig.initRateBitPerSec != 0))
+ {
+ CHECK_ERROR(acm->ConfigISACBandwidthEstimator(
+ (WebRtc_UWord8)isacConfig.initFrameSizeInMsec,
+ (WebRtc_UWord16)isacConfig.initRateBitPerSec,
+ isacConfig.enforceFrameSize));
+ if((isacConfig.initFrameSizeInMsec != 0) && (testMode != 0))
+ {
+ printf("Initialize BWE to %d msec frame-size\n",
+ isacConfig.initFrameSizeInMsec);
+ }
+ if((isacConfig.initRateBitPerSec != 0) && (testMode != 0))
+ {
+ printf("Initialize BWE to %u bit/sec send-bandwidth\n",
+ isacConfig.initRateBitPerSec);
+ }
+ }
+
+ return 0;
+}
+
+
+ISACTest::ISACTest(int testMode)
+{
+ _testMode = testMode;
+}
+
+ISACTest::~ISACTest()
+{
+ AudioCodingModule::Destroy(_acmA);
+ AudioCodingModule::Destroy(_acmB);
+
+ delete _channel_A2B;
+ delete _channel_B2A;
+}
+
+
+WebRtc_Word16
+ISACTest::Setup()
+{
+ int codecCntr;
+ CodecInst codecParam;
+
+ _acmA = AudioCodingModule::Create(1);
+ _acmB = AudioCodingModule::Create(2);
+
+ for(codecCntr = 0; codecCntr < AudioCodingModule::NumberOfCodecs(); codecCntr++)
+ {
+ AudioCodingModule::Codec(codecCntr, codecParam);
+ if(!STR_CASE_CMP(codecParam.plname, "ISAC") && codecParam.plfreq == 16000)
+ {
+ memcpy(&_paramISAC16kHz, &codecParam, sizeof(CodecInst));
+ _idISAC16kHz = codecCntr;
+ }
+ if(!STR_CASE_CMP(codecParam.plname, "ISAC") && codecParam.plfreq == 32000)
+ {
+ memcpy(&_paramISAC32kHz, &codecParam, sizeof(CodecInst));
+ _idISAC32kHz = codecCntr;
+ }
+ }
+
+ // register both iSAC-wb & iSAC-swb in both sides as receiver codecs
+ CHECK_ERROR(_acmA->RegisterReceiveCodec(_paramISAC16kHz));
+ CHECK_ERROR(_acmA->RegisterReceiveCodec(_paramISAC32kHz));
+ CHECK_ERROR(_acmB->RegisterReceiveCodec(_paramISAC16kHz));
+ CHECK_ERROR(_acmB->RegisterReceiveCodec(_paramISAC32kHz));
+
+ //--- Set A-to-B channel
+ _channel_A2B = new Channel;
+ CHECK_ERROR(_acmA->RegisterTransportCallback(_channel_A2B));
+ _channel_A2B->RegisterReceiverACM(_acmB);
+
+ //--- Set B-to-A channel
+ _channel_B2A = new Channel;
+ CHECK_ERROR(_acmB->RegisterTransportCallback(_channel_B2A));
+ _channel_B2A->RegisterReceiverACM(_acmA);
+
+ strncpy(_fileNameSWB, "./modules/audio_coding/main/test/testfile32kHz.pcm",
+ MAX_FILE_NAME_LENGTH_BYTE);
+
+ _acmB->RegisterSendCodec(_paramISAC16kHz);
+ _acmA->RegisterSendCodec(_paramISAC32kHz);
+
+ if(_testMode != 0)
+ {
+ printf("Side A Send Codec\n");
+ printf("%s %d\n", _paramISAC32kHz.plname, _paramISAC32kHz.plfreq);
+
+ printf("Side B Send Codec\n");
+ printf("%s %d\n", _paramISAC16kHz.plname, _paramISAC16kHz.plfreq);
+ }
+
+ _inFileA.Open(_fileNameSWB, 32000, "rb");
+ if(_testMode == 0)
+ {
+ char fileNameA[] = "./modules/audio_coding/main/test/res_autotests/testisac_a.pcm";
+ char fileNameB[] = "./modules/audio_coding/main/test/res_autotests/testisac_b.pcm";
+ _outFileA.Open(fileNameA, 32000, "wb");
+ _outFileB.Open(fileNameB, 32000, "wb");
+ }
+ else
+ {
+ char fileNameA[] = "./modules/audio_coding/main/test/res_tests/testisac_a.pcm";
+ char fileNameB[] = "./modules/audio_coding/main/test/res_tests/testisac_b.pcm";
+ _outFileA.Open(fileNameA, 32000, "wb");
+ _outFileB.Open(fileNameB, 32000, "wb");
+ }
+
+ while(!_inFileA.EndOfFile())
+ {
+ Run10ms();
+ }
+ CodecInst receiveCodec;
+ CHECK_ERROR(_acmA->ReceiveCodec(receiveCodec));
+ if(_testMode != 0)
+ {
+ printf("Side A Receive Codec\n");
+ printf("%s %d\n", receiveCodec.plname, receiveCodec.plfreq);
+ }
+
+ CHECK_ERROR(_acmB->ReceiveCodec(receiveCodec));
+ if(_testMode != 0)
+ {
+ printf("Side B Receive Codec\n");
+ printf("%s %d\n", receiveCodec.plname, receiveCodec.plfreq);
+ }
+
+ _inFileA.Close();
+ _outFileA.Close();
+ _outFileB.Close();
+
+ return 0;
+}
+
+
+void
+ISACTest::Perform()
+{
+ if(_testMode == 0)
+ {
+ printf("Running iSAC Test");
+ WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1, "---------- iSACTest ----------");
+ }
+
+ Setup();
+
+ WebRtc_Word16 testNr = 0;
+ ACMTestISACConfig wbISACConfig;
+ ACMTestISACConfig swbISACConfig;
+
+ SetISACConfigDefault(wbISACConfig);
+ SetISACConfigDefault(swbISACConfig);
+
+ wbISACConfig.currentRateBitPerSec = -1;
+ swbISACConfig.currentRateBitPerSec = -1;
+ testNr++;
+ EncodeDecode(testNr, wbISACConfig, swbISACConfig);
+
+ if (_testMode != 0)
+ {
+ SetISACConfigDefault(wbISACConfig);
+ SetISACConfigDefault(swbISACConfig);
+
+ wbISACConfig.currentRateBitPerSec = -1;
+ swbISACConfig.currentRateBitPerSec = -1;
+ wbISACConfig.initRateBitPerSec = 13000;
+ wbISACConfig.initFrameSizeInMsec = 60;
+ swbISACConfig.initRateBitPerSec = 20000;
+ swbISACConfig.initFrameSizeInMsec = 30;
+ testNr++;
+ EncodeDecode(testNr, wbISACConfig, swbISACConfig);
+
+ SetISACConfigDefault(wbISACConfig);
+ SetISACConfigDefault(swbISACConfig);
+
+ wbISACConfig.currentRateBitPerSec = 20000;
+ swbISACConfig.currentRateBitPerSec = 48000;
+ testNr++;
+ EncodeDecode(testNr, wbISACConfig, swbISACConfig);
+
+ wbISACConfig.currentRateBitPerSec = 16000;
+ swbISACConfig.currentRateBitPerSec = 30000;
+ wbISACConfig.currentFrameSizeMsec = 60;
+ testNr++;
+ EncodeDecode(testNr, wbISACConfig, swbISACConfig);
+ }
+
+ SetISACConfigDefault(wbISACConfig);
+ SetISACConfigDefault(swbISACConfig);
+ testNr++;
+ EncodeDecode(testNr, wbISACConfig, swbISACConfig);
+
+ int dummy;
+ if((_testMode == 0) || (_testMode == 1))
+ {
+ swbISACConfig.maxPayloadSizeByte = (WebRtc_UWord16)200;
+ wbISACConfig.maxPayloadSizeByte = (WebRtc_UWord16)200;
+ }
+ else
+ {
+ printf("Enter the max payload-size for side A: ");
+ scanf("%d", &dummy);
+ swbISACConfig.maxPayloadSizeByte = (WebRtc_UWord16)dummy;
+ printf("Enter the max payload-size for side B: ");
+ scanf("%d", &dummy);
+ wbISACConfig.maxPayloadSizeByte = (WebRtc_UWord16)dummy;
+ }
+ testNr++;
+ EncodeDecode(testNr, wbISACConfig, swbISACConfig);
+
+ _acmA->ResetEncoder();
+ _acmB->ResetEncoder();
+ SetISACConfigDefault(wbISACConfig);
+ SetISACConfigDefault(swbISACConfig);
+
+ if((_testMode == 0) || (_testMode == 1))
+ {
+ swbISACConfig.maxRateBitPerSec = (WebRtc_UWord32)48000;
+ wbISACConfig.maxRateBitPerSec = (WebRtc_UWord32)48000;
+ }
+ else
+ {
+ printf("Enter the max rate for side A: ");
+ scanf("%d", &dummy);
+ swbISACConfig.maxRateBitPerSec = (WebRtc_UWord32)dummy;
+ printf("Enter the max rate for side B: ");
+ scanf("%d", &dummy);
+ wbISACConfig.maxRateBitPerSec = (WebRtc_UWord32)dummy;
+ }
+
+ testNr++;
+ EncodeDecode(testNr, wbISACConfig, swbISACConfig);
+
+
+ testNr++;
+ if(_testMode == 0)
+ {
+ SwitchingSamplingRate(testNr, 4);
+ printf("Done!\n");
+ }
+ else
+ {
+ SwitchingSamplingRate(testNr, 80);
+ }
+}
+
+
+void
+ISACTest::Run10ms()
+{
+ AudioFrame audioFrame;
+
+ _inFileA.Read10MsData(audioFrame);
+ CHECK_ERROR(_acmA->Add10MsData(audioFrame));
+
+ CHECK_ERROR(_acmB->Add10MsData(audioFrame));
+
+ CHECK_ERROR(_acmA->Process());
+ CHECK_ERROR(_acmB->Process());
+
+ CHECK_ERROR(_acmA->PlayoutData10Ms(32000, audioFrame));
+ _outFileA.Write10MsData(audioFrame);
+
+ CHECK_ERROR(_acmB->PlayoutData10Ms(32000, audioFrame));
+ _outFileB.Write10MsData(audioFrame);
+}
+
+void
+ISACTest::EncodeDecode(
+ int testNr,
+ ACMTestISACConfig& wbISACConfig,
+ ACMTestISACConfig& swbISACConfig)
+{
+ if(_testMode == 0)
+ {
+ printf(".");
+ }
+ else
+ {
+ printf("\nTest %d:\n\n", testNr);
+ }
+ char fileNameOut[MAX_FILE_NAME_LENGTH_BYTE];
+
+ // Files in Side A
+ _inFileA.Open(_fileNameSWB, 32000, "rb", true);
+ if(_testMode == 0)
+ {
+ sprintf(fileNameOut,
+ "./modules/audio_coding/main/test/res_autotests/out_iSACTest_%s_%02d.pcm",
+ "A",
+ testNr);
+ }
+ else
+ {
+ sprintf(fileNameOut,
+ "./modules/audio_coding/main/test/res_tests/out%s_%02d.pcm",
+ "A",
+ testNr);
+ }
+ _outFileA.Open(fileNameOut, 32000, "wb");
+
+ // Files in Side B
+ _inFileB.Open(_fileNameSWB, 32000, "rb", true);
+ if(_testMode == 0)
+ {
+ sprintf(fileNameOut,
+ "./modules/audio_coding/main/test/res_autotests/out_iSACTest_%s_%02d.pcm",
+ "B",
+ testNr);
+ }
+ else
+ {
+ sprintf(fileNameOut,
+ "./modules/audio_coding/main/test/res_tests/out%s_%02d.pcm",
+ "B",
+ testNr);
+ }
+ _outFileB.Open(fileNameOut, 32000, "wb");
+
+ CHECK_ERROR(_acmA->RegisterSendCodec(_paramISAC16kHz));
+ CHECK_ERROR(_acmA->RegisterSendCodec(_paramISAC32kHz));
+
+ CHECK_ERROR(_acmB->RegisterSendCodec(_paramISAC32kHz));
+ CHECK_ERROR(_acmB->RegisterSendCodec(_paramISAC16kHz));
+ if(_testMode != 0)
+ {
+ printf("Side A Sending Super-Wideband \n");
+ printf("Side B Sending Wideband\n\n");
+ }
+
+ SetISAConfig(swbISACConfig, _acmA, _testMode);
+ SetISAConfig(wbISACConfig, _acmB, _testMode);
+
+ bool adaptiveMode = false;
+ if((swbISACConfig.currentRateBitPerSec == -1) ||
+ (wbISACConfig.currentRateBitPerSec == -1))
+ {
+ adaptiveMode = true;
+ }
+ _myTimer.Reset();
+ _channel_A2B->ResetStats();
+ _channel_B2A->ResetStats();
+
+ char currentTime[500];
+ if(_testMode == 2) printf("\n");
+ CodecInst sendCodec;
+ EventWrapper* myEvent = EventWrapper::Create();
+ myEvent->StartTimer(true, 10);
+ while(!(_inFileA.EndOfFile() || _inFileA.Rewinded()))
+ {
+ Run10ms();
+ _myTimer.Tick10ms();
+ _myTimer.CurrentTimeHMS(currentTime);
+ if(_testMode == 2) printf("\r%s ", currentTime);
+
+ if((adaptiveMode) && (_testMode != 0))
+ {
+ myEvent->Wait(5000);
+
+ _acmA->SendCodec(sendCodec);
+ if(_testMode == 2) printf("[%d] ", sendCodec.rate);
+ _acmB->SendCodec(sendCodec);
+ if(_testMode == 2) printf("[%d] ", sendCodec.rate);
+ }
+ }
+
+ if(_testMode != 0)
+ {
+ printf("\n\nSide A statistics\n\n");
+ _channel_A2B->PrintStats(_paramISAC32kHz);
+
+ printf("\n\nSide B statistics\n\n");
+ _channel_B2A->PrintStats(_paramISAC16kHz);
+ }
+
+ _channel_A2B->ResetStats();
+ _channel_B2A->ResetStats();
+
+ if(_testMode != 0) printf("\n");
+ _outFileA.Close();
+ _outFileB.Close();
+ _inFileA.Close();
+ _inFileB.Close();
+}
+
+void
+ISACTest::SwitchingSamplingRate(
+ int testNr,
+ int maxSampRateChange)
+{
+ char fileNameOut[MAX_FILE_NAME_LENGTH_BYTE];
+
+ // Files in Side A
+ _inFileA.Open(_fileNameSWB, 32000, "rb");
+ if(_testMode == 0)
+ {
+ sprintf(fileNameOut,
+ "./modules/audio_coding/main/test/res_autotests/out_iSACTest_%s_%02d.pcm",
+ "A",
+ testNr);
+ }
+ else
+ {
+ printf("\nTest %d", testNr);
+ printf(" Alternate between WB and SWB at the sender Side\n\n");
+ sprintf(fileNameOut,
+ "./modules/audio_coding/main/test/res_tests/out%s_%02d.pcm",
+ "A",
+ testNr);
+ }
+ _outFileA.Open(fileNameOut, 32000, "wb", true);
+
+ // Files in Side B
+ _inFileB.Open(_fileNameSWB, 32000, "rb");
+ if(_testMode == 0)
+ {
+ sprintf(fileNameOut,
+ "./modules/audio_coding/main/test/res_autotests/out_iSACTest_%s_%02d.pcm",
+ "B",
+ testNr);
+ }
+ else
+ {
+ sprintf(fileNameOut, "./modules/audio_coding/main/test/res_tests/out%s_%02d.pcm",
+ "B",
+ testNr);
+ }
+ _outFileB.Open(fileNameOut, 32000, "wb", true);
+
+ CHECK_ERROR(_acmA->RegisterSendCodec(_paramISAC32kHz));
+ CHECK_ERROR(_acmB->RegisterSendCodec(_paramISAC16kHz));
+ if(_testMode != 0)
+ {
+ printf("Side A Sending Super-Wideband \n");
+ printf("Side B Sending Wideband\n");
+ }
+
+ int numSendCodecChanged = 0;
+ _myTimer.Reset();
+ char currentTime[50];
+ while(numSendCodecChanged < (maxSampRateChange<<1))
+ {
+ Run10ms();
+ _myTimer.Tick10ms();
+ _myTimer.CurrentTimeHMS(currentTime);
+ if(_testMode == 2) printf("\r%s", currentTime);
+ if(_inFileA.EndOfFile())
+ {
+ if(_inFileA.SamplingFrequency() == 16000)
+ {
+ if(_testMode != 0) printf("\nSide A switched to Send Super-Wideband\n");
+ _inFileA.Close();
+ _inFileA.Open(_fileNameSWB, 32000, "rb");
+ CHECK_ERROR(_acmA->RegisterSendCodec(_paramISAC32kHz));
+ }
+ else
+ {
+ if(_testMode != 0) printf("\nSide A switched to Send Wideband\n");
+ _inFileA.Close();
+ _inFileA.Open(_fileNameSWB, 32000, "rb");
+ CHECK_ERROR(_acmA->RegisterSendCodec(_paramISAC16kHz));
+ }
+ numSendCodecChanged++;
+ }
+
+ if(_inFileB.EndOfFile())
+ {
+ if(_inFileB.SamplingFrequency() == 16000)
+ {
+ if(_testMode != 0) printf("\nSide B switched to Send Super-Wideband\n");
+ _inFileB.Close();
+ _inFileB.Open(_fileNameSWB, 32000, "rb");
+ CHECK_ERROR(_acmB->RegisterSendCodec(_paramISAC32kHz));
+ }
+ else
+ {
+ if(_testMode != 0) printf("\nSide B switched to Send Wideband\n");
+ _inFileB.Close();
+ _inFileB.Open(_fileNameSWB, 32000, "rb");
+ CHECK_ERROR(_acmB->RegisterSendCodec(_paramISAC16kHz));
+ }
+ numSendCodecChanged++;
+ }
+ }
+ _outFileA.Close();
+ _outFileB.Close();
+ _inFileA.Close();
+ _inFileB.Close();
+}
diff --git a/src/modules/audio_coding/main/test/iSACTest.h b/src/modules/audio_coding/main/test/iSACTest.h
new file mode 100644
index 0000000..c6d4b9c
--- /dev/null
+++ b/src/modules/audio_coding/main/test/iSACTest.h
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#ifndef ACM_ISAC_TEST_H
+#define ACM_ISAC_TEST_H
+
+#include "ACMTest.h"
+#include "Channel.h"
+#include "PCMFile.h"
+#include "audio_coding_module.h"
+#include "utility.h"
+#include "common_types.h"
+
+#define MAX_FILE_NAME_LENGTH_BYTE 500
+#define NO_OF_CLIENTS 15
+
+struct ACMTestISACConfig
+{
+ WebRtc_Word32 currentRateBitPerSec;
+ WebRtc_Word16 currentFrameSizeMsec;
+ WebRtc_UWord32 maxRateBitPerSec;
+ WebRtc_Word16 maxPayloadSizeByte;
+ WebRtc_Word16 encodingMode;
+ WebRtc_UWord32 initRateBitPerSec;
+ WebRtc_Word16 initFrameSizeInMsec;
+ bool enforceFrameSize;
+};
+
+
+
+class ISACTest : public ACMTest
+{
+public:
+ ISACTest(int testMode);
+ ~ISACTest();
+
+ void Perform();
+private:
+ WebRtc_Word16 Setup();
+ WebRtc_Word16 SetupConference();
+ WebRtc_Word16 RunConference();
+
+
+ void Run10ms();
+
+ void EncodeDecode(
+ int testNr,
+ ACMTestISACConfig& wbISACConfig,
+ ACMTestISACConfig& swbISACConfig);
+
+ void TestBWE(
+ int testNr);
+
+ void SwitchingSamplingRate(
+ int testNr,
+ int maxSampRateChange);
+
+ AudioCodingModule* _acmA;
+ AudioCodingModule* _acmB;
+
+ Channel* _channel_A2B;
+ Channel* _channel_B2A;
+
+ PCMFile _inFileA;
+ PCMFile _inFileB;
+
+ PCMFile _outFileA;
+ PCMFile _outFileB;
+
+ WebRtc_UWord8 _idISAC16kHz;
+ WebRtc_UWord8 _idISAC32kHz;
+ CodecInst _paramISAC16kHz;
+ CodecInst _paramISAC32kHz;
+
+ char _fileNameWB[MAX_FILE_NAME_LENGTH_BYTE];
+ char _fileNameSWB[MAX_FILE_NAME_LENGTH_BYTE];
+
+ ACMTestTimer _myTimer;
+ int _testMode;
+
+ AudioCodingModule* _defaultACM32;
+ AudioCodingModule* _defaultACM16;
+
+ AudioCodingModule* _confACM[NO_OF_CLIENTS];
+ AudioCodingModule* _clientACM[NO_OF_CLIENTS];
+ Channel* _conf2Client[NO_OF_CLIENTS];
+ Channel* _client2Conf[NO_OF_CLIENTS];
+
+ PCMFile _clientOutFile[NO_OF_CLIENTS];
+};
+
+
+#endif
diff --git a/src/modules/audio_coding/main/test/utility.cpp b/src/modules/audio_coding/main/test/utility.cpp
new file mode 100644
index 0000000..c654019
--- /dev/null
+++ b/src/modules/audio_coding/main/test/utility.cpp
@@ -0,0 +1,431 @@
+/*
+ * 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 "utility.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include "audio_coding_module.h"
+#include "common_types.h"
+
+
+#define NUM_CODECS_WITH_FIXED_PAYLOAD_TYPE 13
+
+
+ACMTestTimer::ACMTestTimer() :
+_msec(0),
+_sec(0),
+_min(0),
+_hour(0)
+{
+ return;
+}
+
+ACMTestTimer::~ACMTestTimer()
+{
+ return;
+}
+
+void ACMTestTimer::Reset()
+{
+ _msec = 0;
+ _sec = 0;
+ _min = 0;
+ _hour = 0;
+ return;
+}
+void ACMTestTimer::Tick10ms()
+{
+ _msec += 10;
+ Adjust();
+ return;
+}
+
+void ACMTestTimer::Tick1ms()
+{
+ _msec++;
+ Adjust();
+ return;
+}
+
+void ACMTestTimer::Tick100ms()
+{
+ _msec += 100;
+ Adjust();
+ return;
+}
+
+void ACMTestTimer::Tick1sec()
+{
+ _sec++;
+ Adjust();
+ return;
+}
+
+void ACMTestTimer::CurrentTimeHMS(char* currTime)
+{
+ sprintf(currTime, "%4lu:%02u:%06.3f", _hour, _min, (double)_sec + (double)_msec / 1000.);
+ return;
+}
+
+void ACMTestTimer::CurrentTime(
+ unsigned long& h,
+ unsigned char& m,
+ unsigned char& s,
+ unsigned short& ms)
+{
+ h = _hour;
+ m = _min;
+ s = _sec;
+ ms = _msec;
+ return;
+}
+
+void ACMTestTimer::Adjust()
+{
+ unsigned int n;
+ if(_msec >= 1000)
+ {
+ n = _msec / 1000;
+ _msec -= (1000 * n);
+ _sec += n;
+ }
+ if(_sec >= 60)
+ {
+ n = _sec / 60;
+ _sec -= (n * 60);
+ _min += n;
+ }
+ if(_min >= 60)
+ {
+ n = _min / 60;
+ _min -= (n * 60);
+ _hour += n;
+ }
+}
+
+
+WebRtc_Word16
+ChooseCodec(
+ CodecInst& codecInst)
+{
+
+ PrintCodecs();
+ //AudioCodingModule* tmpACM = AudioCodingModule::Create(0);
+ WebRtc_UWord8 noCodec = AudioCodingModule::NumberOfCodecs();
+ WebRtc_Word8 codecID;
+ bool outOfRange = false;
+ char myStr[15] = "";
+ do
+ {
+ printf("\nChoose a codec [0]: ");
+ fgets(myStr, 10, stdin);
+ codecID = atoi(myStr);
+ if((codecID < 0) || (codecID >= noCodec))
+ {
+ printf("\nOut of range.\n");
+ outOfRange = true;
+ }
+ } while(outOfRange);
+
+ CHECK_ERROR(AudioCodingModule::Codec((WebRtc_UWord8)codecID, codecInst));
+ return 0;
+}
+
+void
+PrintCodecs()
+{
+ WebRtc_UWord8 noCodec = AudioCodingModule::NumberOfCodecs();
+
+ CodecInst codecInst;
+ printf("No Name [Hz] [bps]\n");
+ for(WebRtc_UWord8 codecCntr = 0; codecCntr < noCodec; codecCntr++)
+ {
+ AudioCodingModule::Codec(codecCntr, codecInst);
+ printf("%2d- %-18s %5d %6d\n",
+ codecCntr, codecInst.plname, codecInst.plfreq, codecInst.rate);
+ }
+
+}
+
+CircularBuffer::CircularBuffer(WebRtc_UWord32 len):
+_buffIsFull(false),
+_calcAvg(false),
+_calcVar(false),
+_sum(0),
+_sumSqr(0),
+_idx(0),
+_buff(NULL)
+{
+ _buff = new(double[len]);
+ if(_buff == NULL)
+ {
+ _buffLen = 0;
+ }
+ else
+ {
+ for(WebRtc_UWord32 n = 0; n < len; n++)
+ {
+ _buff[n] = 0;
+ }
+ _buffLen = len;
+ }
+}
+
+CircularBuffer::~CircularBuffer()
+{
+ if(_buff != NULL)
+ {
+ delete [] _buff;
+ _buff = NULL;
+ }
+}
+
+void
+CircularBuffer::Update(
+ const double newVal)
+{
+ assert(_buffLen > 0);
+
+ // store the value that is going to be overwritten
+ double oldVal = _buff[_idx];
+ // record the new value
+ _buff[_idx] = newVal;
+ // increment the index, to point to where we would
+ // write next
+ _idx++;
+ // it is a circular buffer, if we are at the end
+ // we have to cycle to the beginning
+ if(_idx >= _buffLen)
+ {
+ // flag that the buffer is filled up.
+ _buffIsFull = true;
+ _idx = 0;
+ }
+
+ // Update
+
+ if(_calcAvg)
+ {
+ // for the average we have to update
+ // the sum
+ _sum += (newVal - oldVal);
+ }
+
+ if(_calcVar)
+ {
+ // to calculate variance we have to update
+ // the sum of squares
+ _sumSqr += (double)(newVal - oldVal) * (double)(newVal + oldVal);
+ }
+}
+
+void
+CircularBuffer::SetArithMean(
+ bool enable)
+{
+ assert(_buffLen > 0);
+
+ if(enable && !_calcAvg)
+ {
+ WebRtc_UWord32 lim;
+ if(_buffIsFull)
+ {
+ lim = _buffLen;
+ }
+ else
+ {
+ lim = _idx;
+ }
+ _sum = 0;
+ for(WebRtc_UWord32 n = 0; n < lim; n++)
+ {
+ _sum += _buff[n];
+ }
+ }
+ _calcAvg = enable;
+}
+
+void
+CircularBuffer::SetVariance(
+ bool enable)
+{
+ assert(_buffLen > 0);
+
+ if(enable && !_calcVar)
+ {
+ WebRtc_UWord32 lim;
+ if(_buffIsFull)
+ {
+ lim = _buffLen;
+ }
+ else
+ {
+ lim = _idx;
+ }
+ _sumSqr = 0;
+ for(WebRtc_UWord32 n = 0; n < lim; n++)
+ {
+ _sumSqr += _buff[n] * _buff[n];
+ }
+ }
+ _calcAvg = enable;
+}
+
+WebRtc_Word16
+CircularBuffer::ArithMean(double& mean)
+{
+ assert(_buffLen > 0);
+
+ if(_buffIsFull)
+ {
+
+ mean = _sum / (double)_buffLen;
+ return 0;
+ }
+ else
+ {
+ if(_idx > 0)
+ {
+ mean = _sum / (double)_idx;
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+
+ }
+}
+
+WebRtc_Word16
+CircularBuffer::Variance(double& var)
+{
+ assert(_buffLen > 0);
+
+ if(_buffIsFull)
+ {
+ var = _sumSqr / (double)_buffLen;
+ return 0;
+ }
+ else
+ {
+ if(_idx > 0)
+ {
+ var = _sumSqr / (double)_idx;
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+}
+
+
+
+bool
+FixedPayloadTypeCodec(const char* payloadName)
+{
+ char fixPayloadTypeCodecs[NUM_CODECS_WITH_FIXED_PAYLOAD_TYPE][32] = {
+ "PCMU",
+ "PCMA",
+ "GSM",
+ "G723",
+ "DVI4",
+ "LPC",
+ "PCMA",
+ "G722",
+ "QCELP",
+ "CN",
+ "MPA",
+ "G728",
+ "G729"
+ };
+
+ for(int n = 0; n < NUM_CODECS_WITH_FIXED_PAYLOAD_TYPE; n++)
+ {
+ if(!STR_CASE_CMP(payloadName, fixPayloadTypeCodecs[n]))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+DTMFDetector::DTMFDetector()
+{
+ for(WebRtc_Word16 n = 0; n < 1000; n++)
+ {
+ _toneCntr[n] = 0;
+ }
+}
+
+DTMFDetector::~DTMFDetector()
+{
+}
+
+WebRtc_Word32 DTMFDetector::IncomingDtmf(const WebRtc_UWord8 digitDtmf, const bool /* toneEnded */)
+{
+ fprintf(stdout, "%d-",digitDtmf);
+ _toneCntr[digitDtmf]++;
+ return 0;
+}
+
+void DTMFDetector::PrintDetectedDigits()
+{
+ for(WebRtc_Word16 n = 0; n < 1000; n++)
+ {
+ if(_toneCntr[n] > 0)
+ {
+ fprintf(stdout, "%d %u msec, \n", n, _toneCntr[n]*10);
+ }
+ }
+ fprintf(stdout, "\n");
+ return;
+}
+
+void
+VADCallback::Reset()
+{
+ for(int n = 0; n < 6; n++)
+ {
+ _numFrameTypes[n] = 0;
+ }
+}
+
+VADCallback::VADCallback()
+{
+ for(int n = 0; n < 6; n++)
+ {
+ _numFrameTypes[n] = 0;
+ }
+}
+
+void
+VADCallback::PrintFrameTypes()
+{
+ fprintf(stdout, "No encoding.................. %d\n", _numFrameTypes[0]);
+ fprintf(stdout, "Active normal encoded........ %d\n", _numFrameTypes[1]);
+ fprintf(stdout, "Passive normal encoded....... %d\n", _numFrameTypes[2]);
+ fprintf(stdout, "Passive DTX wideband......... %d\n", _numFrameTypes[3]);
+ fprintf(stdout, "Passive DTX narrowband....... %d\n", _numFrameTypes[4]);
+ fprintf(stdout, "Passive DTX super-wideband... %d\n", _numFrameTypes[5]);
+}
+
+WebRtc_Word32
+VADCallback::InFrameType(
+ WebRtc_Word16 frameType)
+{
+ _numFrameTypes[frameType]++;
+ return 0;
+}
diff --git a/src/modules/audio_coding/main/test/utility.h b/src/modules/audio_coding/main/test/utility.h
new file mode 100644
index 0000000..b25de44
--- /dev/null
+++ b/src/modules/audio_coding/main/test/utility.h
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+#ifndef ACM_TEST_UTILITY_H
+#define ACM_TEST_UTILITY_H
+
+#include "audio_coding_module.h"
+
+//-----------------------------
+#define CHECK_ERROR(f) \
+ do { \
+ if(f < 0) { \
+ char errString[500]; \
+ sprintf(errString, "Error Calling API in file %s at line %d \n", \
+ __FILE__, __LINE__); \
+ throw errString; \
+ } \
+ }while(0)
+
+//-----------------------------
+#define CHECK_PROTECTED(f) \
+ do { \
+ if(f >= 0) { \
+ char errString[500]; \
+ sprintf(errString, "Error Calling API in file %s at line %d \n", \
+ __FILE__, __LINE__); \
+ throw errString; \
+ } \
+ else { \
+ printf("An expected error is caught.\n"); \
+ } \
+ }while(0)
+
+//----------------------------
+#define CHECK_ERROR_MT(f) \
+ do { \
+ if(f < 0) { \
+ fprintf(stderr, "Error Calling API in file %s at line %d \n", \
+ __FILE__, __LINE__); \
+ } \
+ }while(0)
+
+//----------------------------
+#define CHECK_PROTECTED_MT(f) \
+ do { \
+ if(f >= 0) { \
+ fprintf(stderr, "Error Calling API in file %s at line %d \n", \
+ __FILE__, __LINE__); \
+ } \
+ else { \
+ printf("An expected error is caught.\n"); \
+ } \
+ }while(0)
+
+
+
+#ifdef WIN32
+ /* Exclude rarely-used stuff from Windows headers */
+ //#define WIN32_LEAN_AND_MEAN
+ /* OS-dependent case-insensitive string comparison */
+ #define STR_CASE_CMP(x,y) ::_stricmp(x,y)
+#else
+ /* OS-dependent case-insensitive string comparison */
+ #define STR_CASE_CMP(x,y) ::strcasecmp(x,y)
+#endif
+
+#define DESTROY_ACM(acm) \
+ do { \
+ if(acm != NULL) { \
+ AudioCodingModule::Destroy(acm); \
+ acm = NULL; \
+ } \
+ } while(0)
+
+
+#define DELETE_POINTER(p) \
+ do { \
+ if(p != NULL) { \
+ delete p; \
+ p = NULL; \
+ } \
+ } while(0)
+
+using namespace webrtc;
+
+class ACMTestTimer
+{
+public:
+ ACMTestTimer();
+ ~ACMTestTimer();
+
+ void Reset();
+ void Tick10ms();
+ void Tick1ms();
+ void Tick100ms();
+ void Tick1sec();
+ void CurrentTimeHMS(
+ char* currTime);
+ void CurrentTime(
+ unsigned long& h,
+ unsigned char& m,
+ unsigned char& s,
+ unsigned short& ms);
+
+private:
+ void Adjust();
+
+ unsigned short _msec;
+ unsigned char _sec;
+ unsigned char _min;
+ unsigned long _hour;
+};
+
+
+
+class CircularBuffer
+{
+public:
+ CircularBuffer(WebRtc_UWord32 len);
+ ~CircularBuffer();
+
+ void SetArithMean(
+ bool enable);
+ void SetVariance(
+ bool enable);
+
+ void Update(
+ const double newVal);
+ void IsBufferFull();
+
+ WebRtc_Word16 Variance(double& var);
+ WebRtc_Word16 ArithMean(double& mean);
+
+protected:
+ double* _buff;
+ WebRtc_UWord32 _idx;
+ WebRtc_UWord32 _buffLen;
+
+ bool _buffIsFull;
+ bool _calcAvg;
+ bool _calcVar;
+ double _sum;
+ double _sumSqr;
+};
+
+
+
+
+
+WebRtc_Word16 ChooseCodec(
+ CodecInst& codecInst);
+
+void PrintCodecs();
+
+bool FixedPayloadTypeCodec(const char* payloadName);
+
+
+
+
+class DTMFDetector: public AudioCodingFeedback
+{
+public:
+ DTMFDetector();
+ ~DTMFDetector();
+ // used for inband DTMF detection
+ WebRtc_Word32 IncomingDtmf(const WebRtc_UWord8 digitDtmf, const bool toneEnded);
+ void PrintDetectedDigits();
+
+private:
+ WebRtc_UWord32 _toneCntr[1000];
+
+};
+
+
+
+
+class VADCallback : public ACMVADCallback
+{
+public:
+ VADCallback();
+ ~VADCallback(){}
+
+ WebRtc_Word32 InFrameType(
+ WebRtc_Word16 frameType);
+
+ void PrintFrameTypes();
+ void Reset();
+
+private:
+ WebRtc_UWord32 _numFrameTypes[6];
+};
+
+
+
+#endif // ACM_TEST_UTILITY_H