1153 lines
36 KiB
C++
1153 lines
36 KiB
C++
/*
|
|
* 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 <time.h>
|
|
#include <cassert>
|
|
#if defined(_WIN32)
|
|
#include <conio.h>
|
|
#endif
|
|
|
|
#include "voe_unit_test.h"
|
|
|
|
#include "../../source/voice_engine_defines.h"
|
|
#include "thread_wrapper.h"
|
|
|
|
using namespace webrtc;
|
|
|
|
namespace voetest {
|
|
|
|
#ifdef MAC_IPHONE
|
|
extern char micFile[256];
|
|
#else
|
|
extern const char* micFile;
|
|
#endif
|
|
|
|
#define CHECK(expr) \
|
|
if (expr) \
|
|
{ \
|
|
printf("Error at line: %i, %s \n", __LINE__, #expr); \
|
|
printf("Error code: %i \n", base->LastError()); \
|
|
PAUSE \
|
|
return -1; \
|
|
}
|
|
|
|
extern char* GetFilename(char* filename);
|
|
extern const char* GetFilename(const char* filename);
|
|
extern int GetResource(char* resource, char* dest, int destLen);
|
|
extern char* GetResource(char* resource);
|
|
extern const char* GetResource(const char* resource);
|
|
|
|
const char* VoEUnitTest::_key = "====YUtFWRAAAAADBtIHgAAAAAEAAAAcAAAAAQBHU0dsb2"
|
|
"JhbCBJUCBTb3VuZAAC\nAAAAIwAAAExpY2Vuc2VkIHRvIE5vcnRlbCBOZXR3cm9rcwAAAAAxA"
|
|
"AAAZxZ7/u0M\niFYyTwSwko5Uutf7mh8S0O4rYZYTFidbzQeuGonuL17F/2oD/2pfDp3jL4Rf"
|
|
"3z/A\nnlJsEJgEtASkDNFuwLILjGY0pzjjAYQp3pCl6z6k2MtE06AirdjGLYCjENpq/opX\nO"
|
|
"rs3sIuwdYK5va/aFcsjBDmlsGCUM48RDYG9s23bIHYafXUC4ofOaubbZPWiPTmL\nEVJ8WH4F"
|
|
"9pgNjALc14oJXfON7r/3\n=EsLx";
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// >>> R E A D M E F I R S T <<<
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// 1) The user must ensure that the following codecs are included in VoE:
|
|
//
|
|
// - L16
|
|
// - G.729
|
|
// - G.722.1C
|
|
|
|
// 2) It is also possible to modify the simulation time for each indivifual test
|
|
//
|
|
const int dTBetweenEachTest = 4000;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Encrypt
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void VoEUnitTest::encrypt(int channel_no,
|
|
unsigned char * in_data,
|
|
unsigned char * out_data,
|
|
int bytes_in,
|
|
int * bytes_out)
|
|
{
|
|
int i;
|
|
|
|
if (!_extOnOff)
|
|
{
|
|
// no stereo emulation <=> pure bypass
|
|
for (i = 0; i < bytes_in; i++)
|
|
out_data[i] = in_data[i];
|
|
*bytes_out = bytes_in;
|
|
}
|
|
else if (_extOnOff && (_extBitsPerSample == 16))
|
|
{
|
|
// stereo emulation (sample based, 2 bytes per sample)
|
|
|
|
const int nBytesPayload = bytes_in-12;
|
|
|
|
// RTP header (first 12 bytes)
|
|
memcpy(out_data, in_data, 12);
|
|
|
|
// skip RTP header
|
|
short* ptrIn = (short*) &in_data[12];
|
|
short* ptrOut = (short*) &out_data[12];
|
|
|
|
// network byte order
|
|
for (i = 0; i < nBytesPayload/2; i++)
|
|
{
|
|
// produce two output samples for each input sample
|
|
*ptrOut++ = *ptrIn; // left sample
|
|
*ptrOut++ = *ptrIn; // right sample
|
|
ptrIn++;
|
|
}
|
|
|
|
*bytes_out = 12 + 2*nBytesPayload;
|
|
}
|
|
else if (_extOnOff && (_extBitsPerSample == 8))
|
|
{
|
|
// stereo emulation (sample based, 1 bytes per sample)
|
|
|
|
const int nBytesPayload = bytes_in-12;
|
|
|
|
// RTP header (first 12 bytes)
|
|
memcpy(out_data, in_data, 12);
|
|
|
|
// skip RTP header
|
|
unsigned char* ptrIn = (unsigned char*) &in_data[12];
|
|
unsigned char* ptrOut = (unsigned char*) &out_data[12];
|
|
|
|
// network byte order
|
|
for (i = 0; i < nBytesPayload; i++)
|
|
{
|
|
// produce two output samples for each input sample
|
|
*ptrOut++ = *ptrIn; // left sample
|
|
*ptrOut++ = *ptrIn; // right sample
|
|
ptrIn++;
|
|
}
|
|
|
|
*bytes_out = 12 + 2*nBytesPayload;
|
|
}
|
|
else if (_extOnOff && (_extBitsPerSample == -1))
|
|
{
|
|
// stereo emulation (frame based)
|
|
|
|
const int nBytesPayload = bytes_in-12;
|
|
|
|
// RTP header (first 12 bytes)
|
|
memcpy(out_data, in_data, 12);
|
|
|
|
// skip RTP header
|
|
unsigned char* ptrIn = (unsigned char*) &in_data[12];
|
|
unsigned char* ptrOut = (unsigned char*) &out_data[12];
|
|
|
|
// left channel
|
|
for (i = 0; i < nBytesPayload; i++)
|
|
{
|
|
*ptrOut++ = *ptrIn++;
|
|
}
|
|
|
|
ptrIn = (unsigned char*) &in_data[12];
|
|
|
|
// right channel
|
|
for (i = 0; i < nBytesPayload; i++)
|
|
{
|
|
*ptrOut++ = *ptrIn++;
|
|
}
|
|
|
|
*bytes_out = 12 + 2*nBytesPayload;
|
|
}
|
|
}
|
|
|
|
void VoEUnitTest::decrypt(int channel_no,
|
|
unsigned char * in_data,
|
|
unsigned char * out_data,
|
|
int bytes_in,
|
|
int * bytes_out)
|
|
{
|
|
int i;
|
|
for (i = 0; i < bytes_in; i++)
|
|
out_data[i] = in_data[i];
|
|
*bytes_out = bytes_in;
|
|
}
|
|
|
|
void VoEUnitTest::encrypt_rtcp(int channel_no,
|
|
unsigned char * in_data,
|
|
unsigned char * out_data,
|
|
int bytes_in,
|
|
int * bytes_out)
|
|
{
|
|
int i;
|
|
for (i = 0; i < bytes_in; i++)
|
|
out_data[i] = in_data[i];
|
|
*bytes_out = bytes_in;
|
|
}
|
|
|
|
void VoEUnitTest::decrypt_rtcp(int channel_no,
|
|
unsigned char * in_data,
|
|
unsigned char * out_data,
|
|
int bytes_in,
|
|
int * bytes_out)
|
|
{
|
|
int i;
|
|
for (i = 0; i < bytes_in; i++)
|
|
out_data[i] = in_data[i];
|
|
*bytes_out = bytes_in;
|
|
}
|
|
|
|
void VoEUnitTest::SetStereoExternalEncryption(int channel,
|
|
bool onOff,
|
|
int bitsPerSample)
|
|
{
|
|
_extOnOff = onOff;
|
|
_extChannel = channel;
|
|
_extBitsPerSample = bitsPerSample;
|
|
}
|
|
|
|
// VoEVEMediaProcess
|
|
MyMedia mpobj;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// VoEUnitTest
|
|
// ----------------------------------------------------------------------------
|
|
|
|
VoEUnitTest::VoEUnitTest(VoETestManager& mgr) :
|
|
_mgr(mgr),
|
|
_extOnOff(false),
|
|
_extBitsPerSample(-1)
|
|
{
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
_listening[i] = false;
|
|
_playing[i] = false;
|
|
_sending[i] = false;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// DoTest
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int VoEUnitTest::DoTest()
|
|
{
|
|
int test(-1);
|
|
int ret(0);
|
|
while ((test != 0) && (ret != -1))
|
|
{
|
|
test = MenuSelection();
|
|
switch (test)
|
|
{
|
|
case 0:
|
|
// Quit stress test
|
|
break;
|
|
case 1:
|
|
ret = MixerTest();
|
|
break;
|
|
case 2:
|
|
ret = MixerTest();
|
|
break;
|
|
default:
|
|
// Should not be possible
|
|
printf("Invalid selection! (Test code error)\n");
|
|
assert(false);
|
|
} // switch
|
|
} // while
|
|
|
|
return ret;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// MenuSelection
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int VoEUnitTest::MenuSelection()
|
|
{
|
|
printf("------------------------------------------------\n");
|
|
printf("Select unit test\n\n");
|
|
printf(" (0) Quit\n");
|
|
printf(" (1) All\n");
|
|
printf("- - - - - - - - - - - - - - - - - - - - - - - - \n");
|
|
printf(" (2) Mixer\n");
|
|
|
|
const int maxMenuSelection = 2;
|
|
int selection(-1);
|
|
int dummy(0);
|
|
|
|
while ((selection < 0) || (selection > maxMenuSelection))
|
|
{
|
|
printf("\n: ");
|
|
dummy = scanf("%d", &selection);
|
|
if ((selection < 0) || (selection > maxMenuSelection))
|
|
{
|
|
printf("Invalid selection!\n");
|
|
}
|
|
}
|
|
|
|
return selection;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// StartMedia
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int VoEUnitTest::StartMedia(int channel,
|
|
int rtpPort,
|
|
bool listen,
|
|
bool playout,
|
|
bool send,
|
|
bool fileAsMic,
|
|
bool localFile)
|
|
{
|
|
VoEBase* base = _mgr.BasePtr();
|
|
VoEFile* file = _mgr.FilePtr();
|
|
VoECodec* codec = _mgr.CodecPtr();
|
|
|
|
_listening[channel] = false;
|
|
_playing[channel] = false;
|
|
_sending[channel] = false;
|
|
|
|
CHECK(base->SetLocalReceiver(channel, rtpPort));
|
|
CHECK(base->SetSendDestination(channel, rtpPort, "127.0.0.1"));
|
|
if (listen)
|
|
{
|
|
_listening[channel] = true;
|
|
CHECK(base->StartReceive(channel));
|
|
}
|
|
if (playout)
|
|
{
|
|
_playing[channel] = true;
|
|
CHECK(base->StartPlayout(channel));
|
|
}
|
|
if (send)
|
|
{
|
|
_sending[channel] = true;
|
|
CHECK(base->StartSend(channel));
|
|
}
|
|
if (fileAsMic)
|
|
{
|
|
// play mic as file, mix with microphone to ensure that SWB can be
|
|
//tested as well
|
|
const bool mixWithMic(true);
|
|
CHECK(file->StartPlayingFileAsMicrophone(channel, micFile,
|
|
true, mixWithMic));
|
|
}
|
|
if (localFile)
|
|
{
|
|
CHECK(file->StartPlayingFileLocally(channel,
|
|
GetResource("audio_short16.pcm"),
|
|
false,
|
|
kFileFormatPcm16kHzFile));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// StopMedia
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int VoEUnitTest::StopMedia(int channel)
|
|
{
|
|
VoEBase* base = _mgr.BasePtr();
|
|
VoEFile* file = _mgr.FilePtr();
|
|
|
|
if (file->IsPlayingFileAsMicrophone(channel))
|
|
{
|
|
CHECK(file->StopPlayingFileAsMicrophone(channel));
|
|
}
|
|
if (file->IsPlayingFileLocally(channel))
|
|
{
|
|
CHECK(file->StopPlayingFileLocally(channel));
|
|
}
|
|
if (_listening[channel])
|
|
{
|
|
_listening[channel] = false;
|
|
CHECK(base->StopReceive(channel));
|
|
}
|
|
if (_playing[channel])
|
|
{
|
|
_playing[channel] = false;
|
|
CHECK(base->StopPlayout(channel));
|
|
}
|
|
if (_sending[channel])
|
|
{
|
|
_sending[channel] = false;
|
|
CHECK(base->StopSend(channel));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void VoEUnitTest::Sleep(unsigned int timeMillisec, bool addMarker)
|
|
{
|
|
if (addMarker)
|
|
{
|
|
float dtSec = (float) ((float) timeMillisec / 1000.0);
|
|
printf("[dT=%.1f]", dtSec);
|
|
fflush(NULL);
|
|
}
|
|
::Sleep(timeMillisec);
|
|
}
|
|
|
|
void VoEUnitTest::Wait()
|
|
{
|
|
#if defined(_WIN32)
|
|
printf("\npress any key..."); fflush(NULL);
|
|
_getch();
|
|
#endif
|
|
}
|
|
|
|
void VoEUnitTest::Test(const char* msg)
|
|
{
|
|
printf(msg); fflush(NULL);
|
|
printf("\n"); fflush(NULL);
|
|
}
|
|
|
|
int VoEUnitTest::MixerTest()
|
|
{
|
|
// Set up test parameters first
|
|
//
|
|
const int testTime(dTBetweenEachTest);
|
|
|
|
printf("\n\n================================================\n");
|
|
printf(" Mixer Unit Test\n");
|
|
printf("================================================\n\n");
|
|
|
|
// Get sub-API pointers
|
|
//
|
|
VoEBase* base = _mgr.BasePtr();
|
|
VoECodec* codec = _mgr.CodecPtr();
|
|
VoEFile* file = _mgr.FilePtr();
|
|
VoEVolumeControl* volume = _mgr.VolumeControlPtr();
|
|
VoEEncryption* encrypt = _mgr.EncryptionPtr();
|
|
VoEDtmf* dtmf = _mgr.DtmfPtr();
|
|
VoEExternalMedia* xmedia = _mgr.ExternalMediaPtr();
|
|
|
|
// Set trace
|
|
//
|
|
VoiceEngine::SetTraceFile(GetFilename("UnitTest_Mixer_trace.txt"));
|
|
VoiceEngine::SetTraceFilter(kTraceStateInfo |
|
|
kTraceWarning |
|
|
kTraceError |
|
|
kTraceCritical |
|
|
kTraceApiCall |
|
|
kTraceMemory |
|
|
kTraceInfo);
|
|
|
|
// Init
|
|
//
|
|
CHECK(base->Init());
|
|
|
|
// 8 kHz
|
|
CodecInst l16_8 = { 123, "L16", 8000, 160, 1, 128000 };
|
|
CodecInst pcmu_8 = { 0, "pcmu", 8000, 160, 1, 64000 };
|
|
CodecInst g729_8 = { 18, "g729", 8000, 160, 1, 8000 };
|
|
|
|
// 16 kHz
|
|
CodecInst ipcmwb_16 = { 97, "ipcmwb", 16000, 320, 1, 80000 };
|
|
CodecInst l16_16 = { 124, "L16", 16000, 320, 1, 256000 };
|
|
|
|
// 32 kHz
|
|
CodecInst l16_32 = { 125, "L16", 32000, 320, 1, 512000 };
|
|
CodecInst g722_1c_32 = { 126, "G7221", 32000, 640, 1, 32000 };// 20ms@32kHz
|
|
|
|
// ------------------------
|
|
// Verify mixing frequency
|
|
// ------------------------
|
|
|
|
base->CreateChannel();
|
|
|
|
Test(">> Verify correct mixing frequency:\n");
|
|
|
|
Test("(ch 0) Sending file at 8kHz <=> mixing at 8kHz...");
|
|
CHECK(StartMedia(0, 12345, true, true, true, true, false));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Sending file at 16kHz <=> mixing at 16kHz...");
|
|
CHECK(codec->SetSendCodec(0, ipcmwb_16));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Sending speech at 32kHz <=> mixing at 32Hz...");
|
|
CHECK(codec->SetSendCodec(0, l16_32));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Sending file at 8kHz <=> mixing at 8kHz...");
|
|
CHECK(codec->SetSendCodec(0, pcmu_8));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Playing 16kHz file locally <=> mixing at 16kHz...");
|
|
CHECK(file->StartPlayingFileLocally(0, GetResource("audio_long16.pcm"),
|
|
false, kFileFormatPcm16kHzFile));
|
|
Sleep(testTime);
|
|
CHECK(file->StopPlayingFileLocally(0));
|
|
|
|
base->CreateChannel();
|
|
|
|
Test("(ch 0) Sending file at 8kHz <=> mixing at 8kHz...");
|
|
CHECK(codec->SetSendCodec(0, pcmu_8));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Sending speech at 32kHz <=> mixing at 32Hz...");
|
|
CHECK(codec->SetSendCodec(0, l16_32));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 1) Playing 16kHz file locally <=> mixing at 32kHz...");
|
|
CHECK(StartMedia(1, 54321, false, true, false, false, true));
|
|
Sleep(testTime);
|
|
|
|
CHECK(StopMedia(1));
|
|
CHECK(StopMedia(0));
|
|
|
|
base->DeleteChannel(1);
|
|
base->DeleteChannel(0);
|
|
ANL();
|
|
|
|
// -------------------------
|
|
// Verify stereo mode mixing
|
|
// -------------------------
|
|
|
|
base->CreateChannel();
|
|
base->CreateChannel();
|
|
|
|
// SetOutputVolumePan
|
|
//
|
|
// Ensure that all cases sound OK and that the mixer changes state between
|
|
// mono and stereo as it should. A debugger is required to trace the state
|
|
// transitions.
|
|
|
|
Test(">> Verify correct mixing in stereo using SetOutputVolumePan():\n");
|
|
|
|
Test("(ch 0) Playing 16kHz file locally <=> mixing in mono @ 16kHz...");
|
|
CHECK(StartMedia(0, 12345, false, true, false, false, true));
|
|
Sleep(testTime);
|
|
Test("Panning volume to the left <=> mixing in stereo @ 16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(-1, 1.0, 0.0));
|
|
Sleep(testTime);
|
|
Test("Panning volume to the right <=> mixing in stereo @ 16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(-1, 0.0, 1.0));
|
|
Sleep(testTime);
|
|
Test("Back to center volume again <=> mixing in mono @ 16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(-1, 1.0, 1.0));
|
|
Sleep(testTime);
|
|
Test("(ch 1) Playing 16kHz file locally <=> mixing in mono @ 16kHz...");
|
|
CHECK(StartMedia(1, 54321, false, true, false, false, true));
|
|
Sleep(testTime);
|
|
Test("Panning volume to the left <=> mixing in stereo @ 16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(-1, 1.0, 0.0));
|
|
Sleep(testTime);
|
|
Test("Back to center volume again <=> mixing in mono @ 16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(-1, 1.0, 1.0));
|
|
Sleep(testTime);
|
|
Test("(ch 1) Stopped playing file <=> mixing in mono @ 16kHz...");
|
|
CHECK(StopMedia(1));
|
|
Sleep(testTime);
|
|
CHECK(StopMedia(0));
|
|
Test("(ch 0) Sending file at 8kHz <=> mixing at 8kHz...");
|
|
CHECK(StartMedia(0, 12345, true, true, true, true, false));
|
|
Sleep(testTime);
|
|
Test("(ch 0) Sending speech at 32kHz <=> mixing at 32kHz...");
|
|
CHECK(codec->SetSendCodec(0, l16_32));
|
|
Sleep(testTime);
|
|
Test("Panning volume to the right <=> mixing in stereo @ 32kHz...");
|
|
CHECK(volume->SetOutputVolumePan(-1, 0.0, 1.0));
|
|
Sleep(testTime);
|
|
Test("Back to center volume again <=> mixing in mono @ 32kHz...");
|
|
CHECK(volume->SetOutputVolumePan(-1, 1.0, 1.0));
|
|
Sleep(testTime);
|
|
CHECK(StopMedia(0));
|
|
ANL();
|
|
|
|
base->DeleteChannel(0);
|
|
base->DeleteChannel(1);
|
|
|
|
// SetChannelOutputVolumePan
|
|
//
|
|
// Ensure that all cases sound OK and that the mixer changes state between
|
|
// mono and stereo as it should. A debugger is required to trace the state
|
|
// transitions.
|
|
|
|
base->CreateChannel();
|
|
base->CreateChannel();
|
|
|
|
Test(">> Verify correct mixing in stereo using"
|
|
" SetChannelOutputVolumePan():\n");
|
|
|
|
Test("(ch 0) Playing 16kHz file locally <=> mixing in mono @ 16kHz...");
|
|
CHECK(StartMedia(0, 12345, false, true, false, false, true));
|
|
Sleep(testTime);
|
|
Test("(ch 0) Panning channel volume to the left <=> mixing in stereo @ "
|
|
"16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(0, 1.0, 0.0));
|
|
Sleep(testTime);
|
|
Test("(ch 0) Panning channel volume to the right <=> mixing in stereo"
|
|
" @ 16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(0, 0.0, 1.0));
|
|
Sleep(testTime);
|
|
Test("(ch 0) Back to center volume again <=> mixing in mono @"
|
|
" 16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(0, 1.0, 1.0));
|
|
Sleep(testTime);
|
|
Test("(ch 1) Playing 16kHz file locally <=> mixing in mono @ 16kHz...");
|
|
CHECK(StartMedia(1, 54321, false, true, false, false, true));
|
|
Sleep(testTime);
|
|
Test("(ch 1) Panning channel volume to the left <=> mixing in stereo "
|
|
"@ 16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(1, 1.0, 0.0));
|
|
Sleep(testTime);
|
|
Test("(ch 1) Back to center volume again <=> mixing in mono @ 16kHz...");
|
|
CHECK(volume->SetOutputVolumePan(1, 1.0, 1.0));
|
|
Sleep(testTime);
|
|
Test("(ch 1) Stopped playing file <=> mixing in mono @ 16kHz...");
|
|
CHECK(StopMedia(1));
|
|
Sleep(testTime);
|
|
CHECK(StopMedia(0));
|
|
ANL();
|
|
|
|
base->DeleteChannel(0);
|
|
base->DeleteChannel(1);
|
|
|
|
// Emulate stereo-encoding using Encryption
|
|
//
|
|
// Modify the transmitted RTP stream by using external encryption.
|
|
// Supports frame based and sample based "stereo-encoding schemes".
|
|
|
|
base->CreateChannel();
|
|
|
|
Test(">> Verify correct mixing in stereo using emulated stereo input:\n");
|
|
|
|
// enable external encryption
|
|
CHECK(encrypt->RegisterExternalEncryption(0, *this));
|
|
Test("(ch 0) External Encryption is now enabled:");
|
|
|
|
Test("(ch 0) Sending file at 8kHz <=> mixing in mono @ 8kHz...");
|
|
CHECK(StartMedia(0, 12345, true, true, true, true, false));
|
|
Sleep(testTime);
|
|
|
|
// switch to 16kHz (L16) sending codec
|
|
CHECK(codec->SetSendCodec(0, l16_16));
|
|
Test("(ch 0) Sending file at 16kHz (L16) <=> mixing in mono @ 16kHz...");
|
|
Sleep(testTime);
|
|
|
|
// register L16 as 2-channel codec on receiving side =>
|
|
// should sound bad since RTP module splits all received packets in half
|
|
// (sample based)
|
|
CHECK(base->StopPlayout(0));
|
|
CHECK(base->StopReceive(0));
|
|
l16_16.channels = 2;
|
|
CHECK(codec->SetRecPayloadType(0, l16_16));
|
|
CHECK(base->StartReceive(0));
|
|
CHECK(base->StartPlayout(0));
|
|
Test("(ch 0) 16kHz L16 is now registered as 2-channel codec on RX side => "
|
|
"should sound bad...");
|
|
Sleep(testTime);
|
|
|
|
// emulate sample-based stereo encoding
|
|
Test("(ch 0) Emulate sample-based stereo encoding on sending side => "
|
|
"should sound OK...");
|
|
SetStereoExternalEncryption(0, true, 16);
|
|
Sleep(testTime);
|
|
Test("(ch 0) Stop emulating sample-based stereo encoding on sending side =>"
|
|
" should sound bad...");
|
|
SetStereoExternalEncryption(0, false, 16);
|
|
Sleep(testTime);
|
|
Test("(ch 0) Emulate sample-based stereo encoding on sending side => "
|
|
"should sound OK...");
|
|
SetStereoExternalEncryption(0, true, 16);
|
|
Sleep(testTime);
|
|
|
|
// switch to 32kHz (L16) sending codec and disable stereo encoding
|
|
CHECK(codec->SetSendCodec(0, l16_32));
|
|
SetStereoExternalEncryption(0, false, 16);
|
|
Test("(ch 0) Sending file and spech at 32kHz (L16) <=> mixing in mono @ "
|
|
"32kHz...");
|
|
Sleep(testTime);
|
|
|
|
// register L16 32kHz as 2-channel codec on receiving side
|
|
CHECK(base->StopPlayout(0));
|
|
CHECK(base->StopReceive(0));
|
|
l16_32.channels = 2;
|
|
CHECK(codec->SetRecPayloadType(0, l16_32));
|
|
CHECK(base->StartReceive(0));
|
|
CHECK(base->StartPlayout(0));
|
|
Test("(ch 0) 32kHz L16 is now registered as 2-channel codec on RX side =>"
|
|
" should sound bad...");
|
|
Sleep(testTime);
|
|
|
|
// emulate sample-based stereo encoding
|
|
Test("(ch 0) Emulate sample-based stereo encoding on sending side =>"
|
|
" should sound OK...");
|
|
SetStereoExternalEncryption(0, true, 16);
|
|
Sleep(testTime);
|
|
|
|
StopMedia(0);
|
|
l16_32.channels = 1;
|
|
|
|
// disable external encryption
|
|
CHECK(encrypt->DeRegisterExternalEncryption(0));
|
|
ANL();
|
|
|
|
base->DeleteChannel(0);
|
|
|
|
// ------------------
|
|
// Verify put-on-hold
|
|
// ------------------
|
|
|
|
base->CreateChannel();
|
|
base->CreateChannel();
|
|
|
|
Test(">> Verify put-on-hold functionality:\n");
|
|
|
|
Test("(ch 0) Sending at 8kHz...");
|
|
CHECK(StartMedia(0, 12345, true, true, true, true, false));
|
|
Sleep(testTime);
|
|
|
|
CHECK(base->SetOnHoldStatus(0, true, kHoldPlayOnly));
|
|
Test("(ch 0) Playout is now on hold...");
|
|
Sleep(testTime);
|
|
CHECK(base->SetOnHoldStatus(0, false, kHoldPlayOnly));
|
|
Test("(ch 0) Playout is now enabled again...");
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Sending at 16kHz...");
|
|
l16_16.channels = 1;
|
|
CHECK(codec->SetSendCodec(0, l16_16));
|
|
Sleep(testTime);
|
|
|
|
CHECK(base->SetOnHoldStatus(0, true, kHoldPlayOnly));
|
|
Test("(ch 0) Playout is now on hold...");
|
|
Sleep(testTime);
|
|
CHECK(base->SetOnHoldStatus(0, false, kHoldPlayOnly));
|
|
Test("(ch 0) Playout is now enabled again...");
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Perform minor panning to the left to force mixing in"
|
|
" stereo...");
|
|
CHECK(volume->SetOutputVolumePan(0, (float)1.0, (float)0.7));
|
|
Sleep(testTime);
|
|
|
|
CHECK(base->SetOnHoldStatus(0, true, kHoldPlayOnly));
|
|
Test("(ch 0) Playout is now on hold...");
|
|
Sleep(testTime);
|
|
CHECK(base->SetOnHoldStatus(0, false, kHoldPlayOnly));
|
|
Test("(ch 0) Playout is now enabled again...");
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Back to center volume again...");
|
|
CHECK(volume->SetOutputVolumePan(0, 1.0, 1.0));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 1) Add 16kHz local file to the mixer...");
|
|
CHECK(StartMedia(1, 54321, false, true, false, false, true));
|
|
Sleep(testTime);
|
|
|
|
CHECK(base->SetOnHoldStatus(0, true, kHoldPlayOnly));
|
|
Test("(ch 0) Playout is now on hold...");
|
|
Sleep(testTime);
|
|
CHECK(base->SetOnHoldStatus(1, true, kHoldPlayOnly));
|
|
Test("(ch 1) Playout is now on hold => should be silent...");
|
|
Sleep(testTime);
|
|
CHECK(base->SetOnHoldStatus(0, false, kHoldPlayOnly));
|
|
Test("(ch 0) Playout is now enabled again...");
|
|
CHECK(base->SetOnHoldStatus(1, false, kHoldPlayOnly));
|
|
Test("(ch 1) Playout is now enabled again...");
|
|
Sleep(testTime);
|
|
StopMedia(1);
|
|
Test("(ch 1) Stopped playing file...");
|
|
Sleep(testTime);
|
|
StopMedia(0);
|
|
ANL();
|
|
|
|
base->DeleteChannel(0);
|
|
base->DeleteChannel(1);
|
|
|
|
// -----------------------------------
|
|
// Verify recording of playout to file
|
|
// -----------------------------------
|
|
|
|
// StartRecordingPlayout
|
|
//
|
|
// Verify that the correct set of signals is recorded in the mixer.
|
|
// Record each channel and all channels (-1) to ensure that post and pre
|
|
// mixing recording works.
|
|
|
|
base->CreateChannel();
|
|
base->CreateChannel();
|
|
|
|
Test(">> Verify file-recording functionality:\n");
|
|
|
|
Test("(ch 0) Sending at 8kHz...");
|
|
CHECK(StartMedia(0, 12345, true, true, true, true, false));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Recording of playout to 16kHz PCM file...");
|
|
CHECK(file->StartRecordingPlayout(
|
|
0, GetFilename("RecordedPlayout16kHz.pcm"), NULL));
|
|
Sleep(testTime);
|
|
CHECK(file->StopRecordingPlayout(0));
|
|
|
|
Test("(ch 0) Playing out the recorded file...");
|
|
CHECK(volume->SetInputMute(0, true));
|
|
CHECK(file->StartPlayingFileLocally(
|
|
0, GetFilename("RecordedPlayout16kHz.pcm")));
|
|
Sleep(testTime);
|
|
CHECK(file->StopPlayingFileLocally(0));
|
|
CHECK(volume->SetInputMute(0, false));
|
|
|
|
CHECK(codec->SetSendCodec(0, l16_16));
|
|
Test("(ch 0) Sending at 16kHz (L16)...");
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Recording of playout to 16kHz PCM file...");
|
|
CHECK(file->StartRecordingPlayout(
|
|
0, GetFilename("RecordedPlayout16kHz.pcm"), NULL));
|
|
Sleep(testTime);
|
|
CHECK(file->StopRecordingPlayout(0));
|
|
|
|
Test("(ch 0) Playing out the recorded file...");
|
|
CHECK(volume->SetInputMute(0, true));
|
|
CHECK(file->StartPlayingFileLocally(
|
|
0, GetFilename("RecordedPlayout16kHz.pcm")));
|
|
Sleep(testTime);
|
|
CHECK(file->StopPlayingFileLocally(0));
|
|
CHECK(volume->SetInputMute(0, false));
|
|
|
|
CHECK(codec->SetSendCodec(0, l16_32));
|
|
Test("(ch 0) Sending at 32kHz (L16)...");
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Recording of playout to 16kHz PCM file...");
|
|
CHECK(file->StartRecordingPlayout(
|
|
0, GetFilename("RecordedPlayout16kHz.pcm"), NULL));
|
|
Sleep(testTime);
|
|
CHECK(file->StopRecordingPlayout(0));
|
|
|
|
Test("(ch 0) Playing out the recorded file...");
|
|
CHECK(volume->SetInputMute(0, true));
|
|
CHECK(file->StartPlayingFileLocally(
|
|
0, GetFilename("RecordedPlayout16kHz.pcm")));
|
|
Sleep(testTime);
|
|
CHECK(file->StopPlayingFileLocally(0));
|
|
CHECK(volume->SetInputMute(0, false));
|
|
|
|
Test("(ch 0) Sending at 16kHz without file as mic but file added on the"
|
|
" playout side instead...");
|
|
CHECK(StopMedia(0));
|
|
CHECK(StartMedia(0, 12345, false, true, false, false, true));
|
|
CHECK(codec->SetSendCodec(0, l16_16));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Recording of playout to 16kHz PCM file...");
|
|
CHECK(file->StartRecordingPlayout(
|
|
0, GetFilename("RecordedPlayout16kHz.pcm"), NULL));
|
|
Sleep(testTime);
|
|
CHECK(file->StopRecordingPlayout(0));
|
|
CHECK(file->StopPlayingFileLocally(0));
|
|
|
|
Test("(ch 0) Playing out the recorded file...");
|
|
CHECK(file->StartPlayingFileLocally(
|
|
0, GetFilename("RecordedPlayout16kHz.pcm")));
|
|
Sleep(testTime);
|
|
CHECK(file->StopPlayingFileLocally(0));
|
|
|
|
CHECK(StopMedia(0));
|
|
CHECK(StopMedia(1));
|
|
|
|
Test("(ch 0) Sending at 16kHz...");
|
|
CHECK(StartMedia(0, 12345, true, true, true, false, false));
|
|
CHECK(codec->SetSendCodec(0, l16_16));
|
|
Test("(ch 1) Adding playout file...");
|
|
CHECK(StartMedia(1, 33333, false, true, false, false, true));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch -1) Speak while recording all channels to add mixer input on "
|
|
"channel 0...");
|
|
CHECK(file->StartRecordingPlayout(
|
|
-1, GetFilename("RecordedPlayout16kHz.pcm"), NULL));
|
|
Sleep(testTime);
|
|
CHECK(file->StopRecordingPlayout(-1));
|
|
CHECK(file->StopPlayingFileLocally(1));
|
|
|
|
Test("(ch 0) Playing out the recorded file...");
|
|
CHECK(volume->SetInputMute(0, true));
|
|
CHECK(file->StartPlayingFileLocally(
|
|
0, GetFilename("RecordedPlayout16kHz.pcm")));
|
|
Sleep(testTime);
|
|
CHECK(file->StopPlayingFileLocally(0));
|
|
CHECK(volume->SetInputMute(0, false));
|
|
|
|
CHECK(StopMedia(0));
|
|
CHECK(StopMedia(1));
|
|
ANL();
|
|
|
|
// StartRecordingPlayoutStereo
|
|
|
|
Test(">> Verify recording of playout in stereo:\n");
|
|
|
|
Test("(ch 0) Sending at 32kHz...");
|
|
CHECK(codec->SetSendCodec(0, l16_16));
|
|
CHECK(StartMedia(0, 12345, true, true, true, true, false));
|
|
Sleep(testTime);
|
|
|
|
Test("Modified master balance (L=10%%, R=100%%) to force stereo mixing...");
|
|
CHECK(volume->SetOutputVolumePan(-1, (float)0.1, (float)1.0));
|
|
Sleep(testTime);
|
|
|
|
/*
|
|
Test("Recording of left and right channel playout to two 16kHz PCM "
|
|
"files...");
|
|
file->StartRecordingPlayoutStereo(
|
|
GetFilename("RecordedPlayout_Left_16kHz.pcm"),
|
|
GetFilename("RecordedPlayout_Right_16kHz.pcm"), StereoBoth);
|
|
Sleep(testTime);
|
|
Test("Back to center volume again...");
|
|
CHECK(volume->SetOutputVolumePan(-1, (float)1.0, (float)1.0));
|
|
*/
|
|
|
|
Test("(ch 0) Playing out the recorded file for the left channel (10%%)...");
|
|
CHECK(volume->SetInputMute(0, true));
|
|
CHECK(file->StartPlayingFileLocally(
|
|
0, GetFilename("RecordedPlayout_Left_16kHz.pcm")));
|
|
Sleep(testTime);
|
|
CHECK(file->StopPlayingFileLocally(0));
|
|
|
|
Test("(ch 0) Playing out the recorded file for the right channel (100%%) =>"
|
|
" should sound louder than the left channel...");
|
|
CHECK(file->StartPlayingFileLocally(
|
|
0, GetFilename("RecordedPlayout_Right_16kHz.pcm")));
|
|
Sleep(testTime);
|
|
CHECK(file->StopPlayingFileLocally(0));
|
|
CHECK(volume->SetInputMute(0, false));
|
|
|
|
base->DeleteChannel(0);
|
|
base->DeleteChannel(1);
|
|
ANL();
|
|
|
|
// ---------------------------
|
|
// Verify inserted Dtmf tones
|
|
// ---------------------------
|
|
|
|
Test(">> Verify Dtmf feedback functionality:\n");
|
|
|
|
base->CreateChannel();
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
if (i == 0)
|
|
Test("Dtmf direct feedback is now enabled...");
|
|
else
|
|
Test("Dtmf direct feedback is now disabled...");
|
|
|
|
CHECK(dtmf->SetDtmfFeedbackStatus(true, (i==0)));
|
|
|
|
Test("(ch 0) Sending at 32kHz using G.722.1C...");
|
|
CHECK(codec->SetRecPayloadType(0, g722_1c_32));
|
|
CHECK(codec->SetSendCodec(0, g722_1c_32));
|
|
CHECK(StartMedia(0, 12345, true, true, true, false, false));
|
|
Sleep(500);
|
|
|
|
Test("(ch 0) Sending outband Dtmf events => ensure that they are added"
|
|
" to the mixer...");
|
|
// ensure that receiver will not play out outband Dtmf
|
|
CHECK(dtmf->SetSendTelephoneEventPayloadType(0, 118));
|
|
CHECK(dtmf->SendTelephoneEvent(0, 9, true, 390));
|
|
Sleep(500);
|
|
CHECK(dtmf->SendTelephoneEvent(0, 1, true, 390));
|
|
Sleep(500);
|
|
CHECK(dtmf->SendTelephoneEvent(0, 5, true, 390));
|
|
Sleep(500);
|
|
Sleep(testTime - 1500);
|
|
|
|
Test("(ch 0) Changing codec to 8kHz PCMU...");
|
|
CHECK(codec->SetSendCodec(0, pcmu_8));
|
|
Sleep(500);
|
|
|
|
Test("(ch 0) Sending outband Dtmf events => ensure that they are added"
|
|
" to the mixer...");
|
|
CHECK(dtmf->SendTelephoneEvent(0, 9, true, 390));
|
|
Sleep(500);
|
|
CHECK(dtmf->SendTelephoneEvent(0, 1, true, 390));
|
|
Sleep(500);
|
|
CHECK(dtmf->SendTelephoneEvent(0, 5, true, 390));
|
|
Sleep(500);
|
|
Sleep(testTime - 1500);
|
|
|
|
Test("(ch 0) Changing codec to 16kHz L16...");
|
|
CHECK(codec->SetSendCodec(0, l16_16));
|
|
Sleep(500);
|
|
|
|
Test("(ch 0) Sending outband Dtmf events => ensure that they are added"
|
|
" to the mixer...");
|
|
CHECK(dtmf->SendTelephoneEvent(0, 9, true, 390));
|
|
Sleep(500);
|
|
CHECK(dtmf->SendTelephoneEvent(0, 1, true, 390));
|
|
Sleep(500);
|
|
CHECK(dtmf->SendTelephoneEvent(0, 5, true, 390));
|
|
Sleep(500);
|
|
Sleep(testTime - 1500);
|
|
|
|
StopMedia(0);
|
|
ANL();
|
|
}
|
|
|
|
base->DeleteChannel(0);
|
|
|
|
// ---------------------------
|
|
// Verify external processing
|
|
// --------------------------
|
|
|
|
base->CreateChannel();
|
|
|
|
Test(">> Verify external media processing:\n");
|
|
|
|
Test("(ch 0) Playing 16kHz file locally <=> mixing in mono @ 16kHz...");
|
|
CHECK(StartMedia(0, 12345, false, true, false, false, true));
|
|
Sleep(testTime);
|
|
Test("Enabling playout external media processing => played audio should "
|
|
"now be affected");
|
|
CHECK(xmedia->RegisterExternalMediaProcessing(
|
|
0, kPlaybackAllChannelsMixed, mpobj));
|
|
Sleep(testTime);
|
|
Test("(ch 0) Sending speech at 32kHz <=> mixing at 32kHz...");
|
|
CHECK(codec->SetSendCodec(0, l16_32));
|
|
Sleep(testTime);
|
|
printf("Back to normal again\n");
|
|
CHECK(xmedia->DeRegisterExternalMediaProcessing(0,
|
|
kPlaybackAllChannelsMixed));
|
|
Sleep(testTime);
|
|
printf("Enabling playout external media processing on ch 0 => "
|
|
"played audio should now be affected\n");
|
|
CHECK(xmedia->RegisterExternalMediaProcessing(0, kPlaybackPerChannel,
|
|
mpobj));
|
|
Sleep(testTime);
|
|
Test("Panning volume to the right <=> mixing in stereo @ 32kHz...");
|
|
CHECK(volume->SetOutputVolumePan(-1, 0.0, 1.0));
|
|
Sleep(testTime);
|
|
Test("Back to center volume again <=> mixing in mono @ 32kHz...");
|
|
CHECK(volume->SetOutputVolumePan(-1, 1.0, 1.0));
|
|
Sleep(testTime);
|
|
printf("Back to normal again\n");
|
|
CHECK(xmedia->DeRegisterExternalMediaProcessing(0, kPlaybackPerChannel));
|
|
Sleep(testTime);
|
|
CHECK(StopMedia(0));
|
|
ANL();
|
|
|
|
base->DeleteChannel(0);
|
|
|
|
// --------------------------------------------------
|
|
// Extended tests of emulated stereo encoding schemes
|
|
// --------------------------------------------------
|
|
|
|
CodecInst PCMU;
|
|
CodecInst G729;
|
|
CodecInst L16_8;
|
|
CodecInst L16_16;
|
|
CodecInst L16_32;
|
|
|
|
base->CreateChannel();
|
|
|
|
Test(">> Verify emulated stereo encoding for differenct codecs:\n");
|
|
|
|
// enable external encryption
|
|
CHECK(encrypt->RegisterExternalEncryption(0, *this));
|
|
Test("(ch 0) External Encryption is now enabled:");
|
|
|
|
// register all codecs on the receiving side
|
|
strcpy(PCMU.plname, "PCMU");
|
|
PCMU.channels = 2;
|
|
PCMU.pacsize = 160;
|
|
PCMU.plfreq = 8000;
|
|
PCMU.pltype = 125;
|
|
PCMU.rate = 64000;
|
|
CHECK(codec->SetRecPayloadType(0, PCMU));
|
|
|
|
strcpy(G729.plname, "G729");
|
|
G729.channels = 2;
|
|
G729.pacsize = 160;
|
|
G729.plfreq = 8000;
|
|
G729.pltype = 18;
|
|
G729.rate = 8000;
|
|
CHECK(codec->SetRecPayloadType(0, G729));
|
|
|
|
strcpy(L16_8.plname, "L16");
|
|
L16_8.channels = 2;
|
|
L16_8.pacsize = 160;
|
|
L16_8.plfreq = 8000;
|
|
L16_8.pltype = 120;
|
|
L16_8.rate = 128000;
|
|
CHECK(codec->SetRecPayloadType(0, L16_8));
|
|
|
|
strcpy(L16_16.plname, "L16");
|
|
L16_16.channels = 2;
|
|
L16_16.pacsize = 320;
|
|
L16_16.plfreq = 16000;
|
|
L16_16.pltype = 121;
|
|
L16_16.rate = 256000;
|
|
CHECK(codec->SetRecPayloadType(0, L16_16));
|
|
|
|
// NOTE - we cannot send larger than 1500 bytes per RTP packet
|
|
strcpy(L16_32.plname, "L16");
|
|
L16_32.channels = 2;
|
|
L16_32.pacsize = 320;
|
|
L16_32.plfreq = 32000;
|
|
L16_32.pltype = 122;
|
|
L16_32.rate = 512000;
|
|
CHECK(codec->SetRecPayloadType(0, L16_32));
|
|
|
|
// sample-based, 8-bits per sample
|
|
|
|
Test("(ch 0) Sending using G.711 (sample based, 8 bits/sample)...");
|
|
PCMU.channels = 1;
|
|
CHECK(codec->SetSendCodec(0, PCMU));
|
|
SetStereoExternalEncryption(0, true, 8);
|
|
CHECK(StartMedia(0, 12345, true, true, true, true, false));
|
|
Sleep(testTime);
|
|
|
|
// sample-based, 16-bits per sample
|
|
|
|
Test("(ch 0) Sending using L16 8kHz (sample based, 16 bits/sample)...");
|
|
L16_8.channels = 1;
|
|
CHECK(codec->SetSendCodec(0, L16_8));
|
|
SetStereoExternalEncryption(0, true, 16);
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Sending using L16 16kHz (sample based, 16 bits/sample)...");
|
|
L16_16.channels = 1;
|
|
CHECK(codec->SetSendCodec(0, L16_16));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Sending using L16 32kHz (sample based, 16 bits/sample)...");
|
|
L16_32.channels = 1;
|
|
CHECK(codec->SetSendCodec(0, L16_32));
|
|
Sleep(testTime);
|
|
|
|
Test("(ch 0) Sending using G.729 (frame based)...");
|
|
G729.channels = 1;
|
|
CHECK(codec->SetSendCodec(0, G729));
|
|
Sleep(testTime);
|
|
|
|
StopMedia(0);
|
|
|
|
// disable external encryption
|
|
CHECK(encrypt->DeRegisterExternalEncryption(0));
|
|
|
|
base->DeleteChannel(0);
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
CHECK(base->Terminate());
|
|
|
|
printf("\n\n------------------------------------------------\n");
|
|
printf(" Test passed!\n");
|
|
printf("------------------------------------------------\n\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
} // namespace voetest
|