git-svn-id: http://webrtc.googlecode.com/svn/trunk@4 4adac7df-926f-26a2-2b94-8c16560cd09d

This commit is contained in:
niklase@google.com
2011-05-30 11:22:19 +00:00
parent 01813fe945
commit 77ae29bc81
1153 changed files with 404089 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
tlegrand@google.com
turajs@google.com
jks@google.com

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,245 @@
/*
* 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 AUDIO_CODING_MODULE_TYPEDEFS_H
#define AUDIO_CODING_MODULE_TYPEDEFS_H
#include "typedefs.h"
namespace webrtc
{
///////////////////////////////////////////////////////////////////////////
// enum AudioPlayoutMode
// An enumerator for different playout modes.
//
// -voice : This is the standard mode for VoIP calls. The trade-off
// between low delay and jitter robustness is optimized
// for high-quality two-way communication.
// NetEQs packet loss concealment and signal processing
// capabilities are fully employed.
// -fax : The fax mode is optimized for decodability of fax signals
// rather than for perceived audio quality. When this mode
// is selected, NetEQ will do as few delay changes as possible,
// trying to maintain a high and constant delay. Meanwhile,
// the packet loss concealment efforts are reduced.
//
// -streaming : In the case of one-way communication such as passive
// conference participant, a webinar, or a streaming application,
// this mode can be used to improve the jitter robustness at
// the cost of increased delay.
//
enum AudioPlayoutMode
{
voice = 0,
fax = 1,
streaming = 2
};
///////////////////////////////////////////////////////////////////////////
// enum ACMSpeechType
// An enumerator for possible labels of a decoded frame.
//
// -normal : a normal speech frame. If VAD is enabled on the
// incoming stream this label indicate that the
// frame is active.
// -PLC : a PLC frame. The corresponding packet was lost
// and this frame generated by PLC techniques.
// -CNG : the frame is comfort noise. This happens if VAD
// is enabled at the sender and we have received
// SID.
// -PLCCNG : PLC will fade to comfort noise if the duration
// of PLC is long. This labels such a case.
// -VADPassive : the VAD at the receiver recognizes this frame as
// passive.
//
enum ACMSpeechType
{
normal = 0,
PLC = 1,
CNG = 2,
PLCCNG = 3,
VADPassive = 4
};
///////////////////////////////////////////////////////////////////////////
// enum ACMVADMode
// An enumerator for aggressiveness of VAD
// -VADNormal : least aggressive mode.
// -VADLowBitrate : more aggressive than "VADNormal" to save on
// bit-rate.
// -VADAggr : an aggressive mode.
// -VADVeryAggr : the most agressive mode.
//
enum ACMVADMode
{
VADNormal = 0,
VADLowBitrate = 1,
VADAggr = 2,
VADVeryAggr = 3
};
///////////////////////////////////////////////////////////////////////////
// enum ACMCountries
// An enumerator for countries, used when enabling CPT for a specific country.
//
enum ACMCountries
{
ACMDisableCountryDetection = -1, // disable CPT detection
ACMUSA = 0,
ACMJapan,
ACMCanada,
ACMFrance,
ACMGermany,
ACMAustria,
ACMBelgium,
ACMUK,
ACMCzech,
ACMDenmark,
ACMFinland,
ACMGreece,
ACMHungary,
ACMIceland ,
ACMIreland,
ACMItaly,
ACMLuxembourg,
ACMMexico,
ACMNorway,
ACMPoland,
ACMPortugal,
ACMSpain,
ACMSweden,
ACMTurkey,
ACMChina,
ACMHongkong,
ACMTaiwan,
ACMKorea,
ACMSingapore,
ACMNonStandard1 // non-standard countries
};
///////////////////////////////////////////////////////////////////////////
// enum ACMAMRPackingFormat
// An enumerator for different bit-packing format of AMR codec according to
// RFC 3267.
//
// -AMRUndefined : undefined.
// -AMRBandwidthEfficient : bandwidth-efficient mode.
// -AMROctetAlligned : Octet-alligned mode.
// -AMRFileStorage : file-storage mode.
//
enum ACMAMRPackingFormat
{
AMRUndefined = -1,
AMRBandwidthEfficient = 0,
AMROctetAlligned = 1,
AMRFileStorage = 2
};
///////////////////////////////////////////////////////////////////////////
//
// Struct containing network statistics
//
// -currentBufferSize : current jitter buffer size in ms
// -preferredBufferSize : preferred (optimal) buffer size in ms
// -currentPacketLossRate : loss rate (network + late) (in Q14)
// -currentDiscardRate : late loss rate (in Q14)
// -currentExpandRate : fraction (of original stream) of synthesized speech
// inserted through expansion (in Q14)
// -currentPreemptiveRate : fraction of synthesized speech inserted through
// pre-emptive expansion (in Q14)
// -currentAccelerateRate : fraction of data removed through acceleration (in Q14)
typedef struct
{
WebRtc_UWord16 currentBufferSize;
WebRtc_UWord16 preferredBufferSize;
WebRtc_UWord16 currentPacketLossRate;
WebRtc_UWord16 currentDiscardRate;
WebRtc_UWord16 currentExpandRate;
WebRtc_UWord16 currentPreemptiveRate;
WebRtc_UWord16 currentAccelerateRate;
} ACMNetworkStatistics;
///////////////////////////////////////////////////////////////////////////
//
// Struct containing jitter statistics
//
// -jbMinSize : smallest Jitter Buffer size during call in ms
// -jbMaxSize : largest Jitter Buffer size during call in ms
// -jbAvgSize : the average JB size, measured over time - ms
// -jbChangeCount : number of times the Jitter Buffer changed (using Accelerate or Pre-emptive Expand)
// -lateLossMs : amount (in ms) of audio data received late
// -accelerateMs : milliseconds removed to reduce jitter buffer size
// -flushedMs : milliseconds discarded through buffer flushing
// -generatedSilentMs : milliseconds of generated silence
// -interpolatedVoiceMs : milliseconds of synthetic audio data (non-background noise)
// -interpolatedSilentMs : milliseconds of synthetic audio data (background noise level)
// -numExpandTiny : count of tiny expansions in output audio less than 250 ms*/
// -numExpandSmall : count of small expansions in output audio 250 to 500 ms*/
// -numExpandMedium : count of medium expansions in output audio 500 to 2000 ms*/
// -numExpandLong : count of long expansions in output audio longer than 2000
// -longestExpandDurationMs : duration of longest audio drop-out
// -countIAT500ms : count of times we got small network outage (inter-arrival time in [500, 1000) ms)
// -countIAT1000ms : count of times we got medium network outage (inter-arrival time in [1000, 2000) ms)
// -countIAT2000ms : count of times we got large network outage (inter-arrival time >= 2000 ms)
// -longestIATms : longest packet inter-arrival time in ms
// -minPacketDelayMs : min time incoming Packet "waited" to be played
// -maxPacketDelayMs : max time incoming Packet "waited" to be played
// -avgPacketDelayMs : avg time incoming Packet "waited" to be played
//
typedef struct
{
WebRtc_UWord32 jbMinSize;
WebRtc_UWord32 jbMaxSize;
WebRtc_UWord32 jbAvgSize;
WebRtc_UWord32 jbChangeCount;
WebRtc_UWord32 lateLossMs;
WebRtc_UWord32 accelerateMs;
WebRtc_UWord32 flushedMs;
WebRtc_UWord32 generatedSilentMs;
WebRtc_UWord32 interpolatedVoiceMs;
WebRtc_UWord32 interpolatedSilentMs;
WebRtc_UWord32 numExpandTiny;
WebRtc_UWord32 numExpandSmall;
WebRtc_UWord32 numExpandMedium;
WebRtc_UWord32 numExpandLong;
WebRtc_UWord32 longestExpandDurationMs;
WebRtc_UWord32 countIAT500ms;
WebRtc_UWord32 countIAT1000ms;
WebRtc_UWord32 countIAT2000ms;
WebRtc_UWord32 longestIATms;
WebRtc_UWord32 minPacketDelayMs;
WebRtc_UWord32 maxPacketDelayMs;
WebRtc_UWord32 avgPacketDelayMs;
} ACMJitterStatistics;
///////////////////////////////////////////////////////////////////////////
//
// Enumeration of background noise mode a mapping from NetEQ interface.
//
// -On : default "normal" behavior with eternal noise
// -Fade : noise fades to zero after some time
// -Off : background noise is always zero
//
enum ACMBackgroundNoiseMode
{
On,
Fade,
Off
};
} // namespace webrtc
#endif

View File

@@ -0,0 +1,592 @@
/*
* 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 "acm_amr.h"
#include "acm_common_defs.h"
#include "acm_neteq.h"
#include "audio_coding_module_typedefs.h"
#include "rw_lock_wrapper.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_AMR
// NOTE! GSM AMR is not included in the open-source package. Modify this file or your codec
// API to match the function call and name of used AMR API file.
// #include "amr_interface.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_AMR
ACMAMR::ACMAMR(WebRtc_Word16 /* codecID */)
{
return;
}
ACMAMR::~ACMAMR()
{
return;
}
WebRtc_Word16
ACMAMR::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMAMR::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMAMR::EnableDTX()
{
return -1;
}
WebRtc_Word16
ACMAMR::DisableDTX()
{
return -1;
}
WebRtc_Word16
ACMAMR::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMAMR::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMAMR::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMAMR::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMAMR::InternalCreateEncoder()
{
return -1;
}
void
ACMAMR::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMAMR::InternalCreateDecoder()
{
return -1;
}
void
ACMAMR::DestructDecoderSafe()
{
return;
}
WebRtc_Word16
ACMAMR::SetBitRateSafe(
const WebRtc_Word32 /* rate */)
{
return -1;
}
void
ACMAMR::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMAMR::SetAMREncoderPackingFormat(
ACMAMRPackingFormat /* packingFormat */)
{
return -1;
}
ACMAMRPackingFormat
ACMAMR::AMREncoderPackingFormat() const
{
return AMRUndefined;
}
WebRtc_Word16
ACMAMR::SetAMRDecoderPackingFormat(
ACMAMRPackingFormat /* packingFormat */)
{
return -1;
}
ACMAMRPackingFormat
ACMAMR::AMRDecoderPackingFormat() const
{
return AMRUndefined;
}
WebRtc_Word16
ACMAMR::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
#define WEBRTC_AMR_MR475 0
#define WEBRTC_AMR_MR515 1
#define WEBRTC_AMR_MR59 2
#define WEBRTC_AMR_MR67 3
#define WEBRTC_AMR_MR74 4
#define WEBRTC_AMR_MR795 5
#define WEBRTC_AMR_MR102 6
#define WEBRTC_AMR_MR122 7
// Remove when integrating a real GSM AMR wrapper
extern WebRtc_Word16 WebRtcAmr_CreateEnc(AMR_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcAmr_CreateDec(AMR_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcAmr_FreeEnc(AMR_encinst_t_* encInst);
extern WebRtc_Word16 WebRtcAmr_FreeDec(AMR_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcAmr_Encode(AMR_encinst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16 len,
WebRtc_Word16*output,
WebRtc_Word16 mode);
extern WebRtc_Word16 WebRtcAmr_EncoderInit(AMR_encinst_t_* encInst,
WebRtc_Word16 dtxMode);
extern WebRtc_Word16 WebRtcAmr_EncodeBitmode(AMR_encinst_t_* encInst,
ACMAMRPackingFormat format);
extern WebRtc_Word16 WebRtcAmr_Decode(AMR_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcAmr_DecodePlc(AMR_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcAmr_DecoderInit(AMR_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcAmr_DecodeBitmode(AMR_decinst_t_* decInst,
ACMAMRPackingFormat format);
ACMAMR::ACMAMR(WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_decoderInstPtr(NULL),
_encodingMode(-1), // invalid value
_encodingRate(0) // invalid value
{
_codecID = codecID;
_hasInternalDTX = true;
_encoderPackingFormat = AMRBandwidthEfficient;
_decoderPackingFormat = AMRBandwidthEfficient;
return;
}
ACMAMR::~ACMAMR()
{
if(_encoderInstPtr != NULL)
{
WebRtcAmr_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
if(_decoderInstPtr != NULL)
{
WebRtcAmr_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
return;
}
WebRtc_Word16
ACMAMR::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
WebRtc_Word16 vadDecision = 1;
// sanity check, if the rate is set correctly. we might skip this
// sanity check. if rate is not set correctly, initialization flag
// should be false and should not be here.
if((_encodingMode < WEBRTC_AMR_MR475) || (_encodingMode > WEBRTC_AMR_MR122))
{
*bitStreamLenByte = 0;
return -1;
}
*bitStreamLenByte = WebRtcAmr_Encode(_encoderInstPtr,
&_inAudio[_inAudioIxRead], _frameLenSmpl, (WebRtc_Word16*)bitStream,
_encodingMode);
// Update VAD, if internal DTX is used
if(_hasInternalDTX && _dtxEnabled)
{
if(*bitStreamLenByte <= (7*_frameLenSmpl/160))
{
vadDecision = 0;
}
for(WebRtc_Word16 n = 0; n < MAX_FRAME_SIZE_10MSEC; n++)
{
_vadLabel[n] = vadDecision;
}
}
// increment the read index
_inAudioIxRead += _frameLenSmpl;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMAMR::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMAMR::EnableDTX()
{
if(_dtxEnabled)
{
return 0;
}
else if(_encoderExist) // check if encoder exist
{
// enable DTX
if(WebRtcAmr_EncoderInit(_encoderInstPtr, 1) < 0)
{
return -1;
}
_dtxEnabled = true;
return 0;
}
else
{
return -1;
}
}
WebRtc_Word16
ACMAMR::DisableDTX()
{
if(!_dtxEnabled)
{
return 0;
}
else if(_encoderExist) // check if encoder exist
{
// disable DTX
if(WebRtcAmr_EncoderInit(_encoderInstPtr, 0) < 0)
{
return -1;
}
_dtxEnabled = false;
return 0;
}
else
{
// encoder doesn't exists, therefore disabling is harmless
return 0;
}
}
WebRtc_Word16
ACMAMR::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
WebRtc_Word16 status = SetBitRateSafe((codecParams->codecInstant).rate);
status += (WebRtcAmr_EncoderInit(_encoderInstPtr,
((codecParams->enableDTX)? 1:0)) < 0)? -1:0;
status += (WebRtcAmr_EncodeBitmode(_encoderInstPtr,
_encoderPackingFormat ) < 0)? -1:0;
return (status < 0)? -1:0;
}
WebRtc_Word16
ACMAMR::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
WebRtc_Word16 status = (
(WebRtcAmr_DecoderInit(_decoderInstPtr) < 0)? -1:0);
status +=
WebRtcAmr_DecodeBitmode(_decoderInstPtr, _decoderPackingFormat);
return (status < 0)? -1:0;
}
WebRtc_Word32
ACMAMR::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
// Todo:
// log error
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_AMR_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderAMR, codecInst.pltype,
_decoderInstPtr, 8000);
SET_AMR_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMAMR::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMAMR::InternalCreateEncoder()
{
return WebRtcAmr_CreateEnc(&_encoderInstPtr);
}
void
ACMAMR::DestructEncoderSafe()
{
if(_encoderInstPtr != NULL)
{
WebRtcAmr_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
// there is no encoder set the following
_encoderExist = false;
_encoderInitialized = false;
_encodingMode = -1; // invalid value
_encodingRate = 0; // invalid value
}
WebRtc_Word16
ACMAMR::InternalCreateDecoder()
{
return WebRtcAmr_CreateDec(&_decoderInstPtr);
}
void
ACMAMR::DestructDecoderSafe()
{
if(_decoderInstPtr != NULL)
{
WebRtcAmr_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
// there is no encoder instance set the followings
_decoderExist = false;
_decoderInitialized = false;
}
WebRtc_Word16
ACMAMR::SetBitRateSafe(const WebRtc_Word32 rate)
{
switch(rate)
{
case 4750:
_encodingMode = WEBRTC_AMR_MR475;
_encodingRate = 4750;
break;
case 5150:
_encodingMode = WEBRTC_AMR_MR515;
_encodingRate = 5150;
break;
case 5900:
_encodingMode = WEBRTC_AMR_MR59;
_encodingRate = 5900;
break;
case 6700:
_encodingMode = WEBRTC_AMR_MR67;
_encodingRate = 6700;
break;
case 7400:
_encodingMode = WEBRTC_AMR_MR74;
_encodingRate = 7400;
break;
case 7950:
_encodingMode = WEBRTC_AMR_MR795;
_encodingRate = 7950;
break;
case 10200:
_encodingMode = WEBRTC_AMR_MR102;
_encodingRate = 10200;
break;
case 12200:
_encodingMode = WEBRTC_AMR_MR122;
_encodingRate = 12200;
break;
default:
return -1;
break;
}
return 0;
}
void
ACMAMR::InternalDestructEncoderInst(
void* ptrInst)
{
// Free the memory where ptrInst is pointing to
if(ptrInst != NULL)
{
WebRtcAmr_FreeEnc((AMR_encinst_t_*)ptrInst);
}
return;
}
WebRtc_Word16
ACMAMR::SetAMREncoderPackingFormat(
ACMAMRPackingFormat packingFormat)
{
if((packingFormat != AMRBandwidthEfficient) &&
(packingFormat != AMROctetAlligned) &&
(packingFormat != AMRFileStorage))
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Invalid AMR Encoder packing-format.");
return -1;
}
else
{
if(WebRtcAmr_EncodeBitmode(_encoderInstPtr,
packingFormat) < 0)
{
return -1;
}
else
{
_encoderPackingFormat = packingFormat;
return 0;
}
}
}
ACMAMRPackingFormat
ACMAMR::AMREncoderPackingFormat() const
{
return _encoderPackingFormat;
}
WebRtc_Word16
ACMAMR::SetAMRDecoderPackingFormat(
ACMAMRPackingFormat packingFormat)
{
if((packingFormat != AMRBandwidthEfficient) &&
(packingFormat != AMROctetAlligned) &&
(packingFormat != AMRFileStorage))
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Invalid AMR decoder packing-format.");
return -1;
}
else
{
if(WebRtcAmr_DecodeBitmode(_decoderInstPtr,
packingFormat) < 0)
{
return -1;
}
else
{
_decoderPackingFormat = packingFormat;
return 0;
}
}
}
ACMAMRPackingFormat
ACMAMR::AMRDecoderPackingFormat() const
{
return _decoderPackingFormat;
}
WebRtc_Word16
ACMAMR::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderAMR);
}
#endif
}

View File

@@ -0,0 +1,97 @@
/*
* 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_AMR_H
#define ACM_AMR_H
#include "acm_generic_codec.h"
// forward declaration
struct AMR_encinst_t_;
struct AMR_decinst_t_;
namespace webrtc
{
enum ACMAMRPackingFormat;
class ACMAMR : public ACMGenericCodec
{
public:
ACMAMR(WebRtc_Word16 codecID);
~ACMAMR();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 SetAMREncoderPackingFormat(
const ACMAMRPackingFormat packingFormat);
ACMAMRPackingFormat AMREncoderPackingFormat() const;
WebRtc_Word16 SetAMRDecoderPackingFormat(
const ACMAMRPackingFormat packingFormat);
ACMAMRPackingFormat AMRDecoderPackingFormat() const;
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 SetBitRateSafe(
const WebRtc_Word32 rate);
WebRtc_Word16 EnableDTX();
WebRtc_Word16 DisableDTX();
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
AMR_encinst_t_* _encoderInstPtr;
AMR_decinst_t_* _decoderInstPtr;
WebRtc_Word16 _encodingMode;
WebRtc_Word16 _encodingRate;
ACMAMRPackingFormat _encoderPackingFormat;
ACMAMRPackingFormat _decoderPackingFormat;
};
} // namespace webrtc
#endif // ACM_AMR_H

View File

@@ -0,0 +1,590 @@
/*
* 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 "acm_amrwb.h"
#include "acm_common_defs.h"
#include "acm_neteq.h"
#include "audio_coding_module_typedefs.h"
#include "rw_lock_wrapper.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_AMRWB
// NOTE! GSM AMR-wb is not included in the open-source package. Modify this file or your
// codec API to match the function call and name of used AMR-wb API file.
// #include "amrwb_interface.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_AMRWB
ACMAMRwb::ACMAMRwb(WebRtc_Word16 /* codecID*/)
{
return;
}
ACMAMRwb::~ACMAMRwb()
{
return;
}
WebRtc_Word16
ACMAMRwb::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMAMRwb::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMAMRwb::EnableDTX()
{
return -1;
}
WebRtc_Word16
ACMAMRwb::DisableDTX()
{
return -1;
}
WebRtc_Word16
ACMAMRwb::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMAMRwb::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMAMRwb::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMAMRwb::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMAMRwb::InternalCreateEncoder()
{
return -1;
}
void
ACMAMRwb::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMAMRwb::InternalCreateDecoder()
{
return -1;
}
void
ACMAMRwb::DestructDecoderSafe()
{
return;
}
WebRtc_Word16
ACMAMRwb::SetBitRateSafe(
const WebRtc_Word32 /* rate */)
{
return -1;
}
void
ACMAMRwb::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMAMRwb::SetAMRwbEncoderPackingFormat(
ACMAMRPackingFormat /* packingFormat */)
{
return -1;
}
ACMAMRPackingFormat
ACMAMRwb::AMRwbEncoderPackingFormat() const
{
return AMRUndefined;
}
WebRtc_Word16 ACMAMRwb::SetAMRwbDecoderPackingFormat(
ACMAMRPackingFormat /* packingFormat */)
{
return -1;
}
ACMAMRPackingFormat
ACMAMRwb::AMRwbDecoderPackingFormat() const
{
return AMRUndefined;
}
WebRtc_Word16
ACMAMRwb::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
#define AMRWB_MODE_7k 0
#define AMRWB_MODE_9k 1
#define AMRWB_MODE_12k 2
#define AMRWB_MODE_14k 3
#define AMRWB_MODE_16k 4
#define AMRWB_MODE_18k 5
#define AMRWB_MODE_20k 6
#define AMRWB_MODE_23k 7
#define AMRWB_MODE_24k 8
// Remove when integrating a real GSM AMR wrapper
extern WebRtc_Word16 WebRtcAmrWb_CreateEnc(AMRWB_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcAmrWb_CreateDec(AMRWB_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcAmrWb_FreeEnc(AMRWB_encinst_t_* encInst);
extern WebRtc_Word16 WebRtcAmrWb_FreeDec(AMRWB_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcAmrWb_Encode(AMRWB_encinst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16 len,
WebRtc_Word16*output,
WebRtc_Word16 mode);
extern WebRtc_Word16 WebRtcAmrWb_EncoderInit(AMRWB_encinst_t_* encInst,
WebRtc_Word16 dtxMode);
extern WebRtc_Word16 WebRtcAmrWb_EncodeBitmode(AMRWB_encinst_t_* encInst,
ACMAMRPackingFormat format);
extern WebRtc_Word16 WebRtcAmrWb_Decode(AMRWB_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcAmrWb_DecodePlc(AMRWB_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcAmrWb_DecoderInit(AMRWB_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcAmrWb_DecodeBitmode(AMRWB_decinst_t_* decInst,
ACMAMRPackingFormat format);
ACMAMRwb::ACMAMRwb(WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_decoderInstPtr(NULL),
_encodingMode(-1), // invalid value
_encodingRate(0) // invalid value
{
_codecID = codecID;
_hasInternalDTX = true;
_encoderPackingFormat = AMRBandwidthEfficient;
_decoderPackingFormat = AMRBandwidthEfficient;
return;
}
ACMAMRwb::~ACMAMRwb()
{
if(_encoderInstPtr != NULL)
{
WebRtcAmrWb_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
if(_decoderInstPtr != NULL)
{
WebRtcAmrWb_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
return;
}
WebRtc_Word16
ACMAMRwb::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
WebRtc_Word16 vadDecision = 1;
// sanity check, if the rate is set correctly. we might skip this
// sanity check. if rate is not set correctly, initialization flag
// should be false and should not be here.
if((_encodingMode < AMRWB_MODE_7k) || (_encodingMode > AMRWB_MODE_24k))
{
*bitStreamLenByte = 0;
return -1;
}
*bitStreamLenByte =
WebRtcAmrWb_Encode(_encoderInstPtr, &_inAudio[_inAudioIxRead],
_frameLenSmpl, (WebRtc_Word16*)bitStream, _encodingMode);
// Update VAD, if internal DTX is used
if(_hasInternalDTX && _dtxEnabled)
{
if (*bitStreamLenByte <= (7*_frameLenSmpl/160))
{
vadDecision = 0;
}
for(WebRtc_Word16 n = 0; n < MAX_FRAME_SIZE_10MSEC; n++)
{
_vadLabel[n] = vadDecision;
}
}
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _frameLenSmpl;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMAMRwb::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMAMRwb::EnableDTX()
{
if(_dtxEnabled)
{
return 0;
}
else if(_encoderExist) // check if encoder exist
{
// enable DTX
if(WebRtcAmrWb_EncoderInit(_encoderInstPtr, 1) < 0)
{
return -1;
}
_dtxEnabled = true;
return 0;
}
else
{
return -1;
}
}
WebRtc_Word16
ACMAMRwb::DisableDTX()
{
if(!_dtxEnabled)
{
return 0;
}
else if(_encoderExist) // check if encoder exist
{
// disable DTX
if(WebRtcAmrWb_EncoderInit(_encoderInstPtr, 0) < 0)
{
return -1;
}
_dtxEnabled = false;
return 0;
}
else
{
// encoder doesn't exists, therefore disabling is harmless
return 0;
}
}
WebRtc_Word16
ACMAMRwb::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
// sanity check
if (_encoderInstPtr == NULL)
{
return -1;
}
WebRtc_Word16 status = SetBitRateSafe((codecParams->codecInstant).rate);
status += (WebRtcAmrWb_EncoderInit(
_encoderInstPtr, ((codecParams->enableDTX)? 1:0)) < 0)? -1:0;
status += (WebRtcAmrWb_EncodeBitmode(
_encoderInstPtr, _encoderPackingFormat ) < 0)? -1:0;
return (status < 0)? -1:0;
}
WebRtc_Word16
ACMAMRwb::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
WebRtc_Word16 status = WebRtcAmrWb_DecodeBitmode(
_decoderInstPtr, _decoderPackingFormat);
status += ((WebRtcAmrWb_DecoderInit(_decoderInstPtr) < 0)? -1:0);
return (status < 0)? -1:0;
}
WebRtc_Word32
ACMAMRwb::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
// Todo:
// log error
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_AMRWB_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderAMRWB, codecInst.pltype,
_decoderInstPtr, 16000);
SET_AMRWB_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMAMRwb::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMAMRwb::InternalCreateEncoder()
{
return WebRtcAmrWb_CreateEnc(&_encoderInstPtr);
}
void
ACMAMRwb::DestructEncoderSafe()
{
if(_encoderInstPtr != NULL)
{
WebRtcAmrWb_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
// there is no encoder set the following
_encoderExist = false;
_encoderInitialized = false;
_encodingMode = -1; // invalid value
_encodingRate = 0;
}
WebRtc_Word16
ACMAMRwb::InternalCreateDecoder()
{
return WebRtcAmrWb_CreateDec(&_decoderInstPtr);
}
void
ACMAMRwb::DestructDecoderSafe()
{
if(_decoderInstPtr != NULL)
{
WebRtcAmrWb_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
// there is no encoder instance set the followings
_decoderExist = false;
_decoderInitialized = false;
}
WebRtc_Word16
ACMAMRwb::SetBitRateSafe(
const WebRtc_Word32 rate)
{
switch(rate)
{
case 7000:
{
_encodingMode = AMRWB_MODE_7k;
_encodingRate = 7000;
break;
}
case 9000:
{
_encodingMode = AMRWB_MODE_9k;
_encodingRate = 9000;
break;
}
case 12000:
{
_encodingMode = AMRWB_MODE_12k;
_encodingRate = 12000;
break;
}
case 14000:
{
_encodingMode = AMRWB_MODE_14k;
_encodingRate = 14000;
break;
}
case 16000:
{
_encodingMode = AMRWB_MODE_16k;
_encodingRate = 16000;
break;
}
case 18000:
{
_encodingMode = AMRWB_MODE_18k;
_encodingRate = 18000;
break;
}
case 20000:
{
_encodingMode = AMRWB_MODE_20k;
_encodingRate = 20000;
break;
}
case 23000:
{
_encodingMode = AMRWB_MODE_23k;
_encodingRate = 23000;
break;
}
case 24000:
{
_encodingMode = AMRWB_MODE_24k;
_encodingRate = 24000;
break;
}
default:
{
return -1;
break;
}
}
return 0;
}
void
ACMAMRwb::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
WebRtcAmrWb_FreeEnc((AMRWB_encinst_t_*)ptrInst);
}
return;
}
WebRtc_Word16
ACMAMRwb::SetAMRwbEncoderPackingFormat(
ACMAMRPackingFormat packingFormat)
{
if((packingFormat != AMRBandwidthEfficient) &&
(packingFormat != AMROctetAlligned) &&
(packingFormat != AMRFileStorage))
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Invalid AMRwb encoder packing-format.");
return -1;
}
else
{
if(WebRtcAmrWb_EncodeBitmode(_encoderInstPtr,
packingFormat) < 0)
{
return -1;
}
else
{
_encoderPackingFormat = packingFormat;
return 0;
}
}
}
ACMAMRPackingFormat
ACMAMRwb::AMRwbEncoderPackingFormat() const
{
return _encoderPackingFormat;
}
WebRtc_Word16 ACMAMRwb::SetAMRwbDecoderPackingFormat(
ACMAMRPackingFormat packingFormat)
{
if((packingFormat != AMRBandwidthEfficient) &&
(packingFormat != AMROctetAlligned) &&
(packingFormat != AMRFileStorage))
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Invalid AMRwb decoder packing-format.");
return -1;
}
else
{
if(WebRtcAmrWb_DecodeBitmode(_decoderInstPtr,
packingFormat) < 0)
{
return -1;
}
else
{
_decoderPackingFormat = packingFormat;
return 0;
}
}
}
ACMAMRPackingFormat
ACMAMRwb::AMRwbDecoderPackingFormat() const
{
return _decoderPackingFormat;
}
WebRtc_Word16
ACMAMRwb::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderAMRWB);
}
#endif
} // namespace webrtc

View File

@@ -0,0 +1,98 @@
/*
* 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_AMRWB_H
#define ACM_AMRWB_H
#include "acm_generic_codec.h"
// forward declaration
struct AMRWB_encinst_t_;
struct AMRWB_decinst_t_;
namespace webrtc
{
enum ACMAMRPackingFormat;
class ACMAMRwb : public ACMGenericCodec
{
public:
ACMAMRwb(WebRtc_Word16 codecID);
~ACMAMRwb();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 SetAMRwbEncoderPackingFormat(
const ACMAMRPackingFormat packingFormat);
ACMAMRPackingFormat AMRwbEncoderPackingFormat() const;
WebRtc_Word16 SetAMRwbDecoderPackingFormat(
const ACMAMRPackingFormat packingFormat);
ACMAMRPackingFormat AMRwbDecoderPackingFormat() const;
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 SetBitRateSafe(
const WebRtc_Word32 rate);
WebRtc_Word16 EnableDTX();
WebRtc_Word16 DisableDTX();
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
AMRWB_encinst_t_* _encoderInstPtr;
AMRWB_decinst_t_* _decoderInstPtr;
WebRtc_Word16 _encodingMode;
WebRtc_Word16 _encodingRate;
ACMAMRPackingFormat _encoderPackingFormat;
ACMAMRPackingFormat _decoderPackingFormat;
};
} // namespace webrtc
#endif // ACM_AMRWB_H

View File

@@ -0,0 +1,228 @@
/*
* 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 "acm_cng.h"
#include "acm_codec_database.h"
#include "acm_common_defs.h"
#include "acm_neteq.h"
#include "trace.h"
#include "webrtc_cng.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
namespace webrtc
{
ACMCNG::ACMCNG(WebRtc_Word16 codecID)
{
_encoderInstPtr = NULL;
_decoderInstPtr = NULL;
_codecID = codecID;
if(_codecID == ACMCodecDB::cnNB)
{
_sampFreqHz = 8000;
}
else if(_codecID == ACMCodecDB::cnWB)
{
_sampFreqHz = 16000;
}
else if(_codecID == ACMCodecDB::cnSWB)
{
_sampFreqHz = 32000;
}
else
{
_sampFreqHz = -1;
}
return;
}
ACMCNG::~ACMCNG()
{
if(_encoderInstPtr != NULL)
{
WebRtcCng_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
if(_decoderInstPtr != NULL)
{
WebRtcCng_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
return;
}
// CNG is not like a regular encoder, this function
// should not be called normally
// instead the following function is called from inside
// ACMGenericCodec::ProcessFrameVADDTX
WebRtc_Word16
ACMCNG::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMCNG::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
// CNG is not like a regular encoder,
// this function should not be called normally
// instead the following function is called from inside
// ACMGenericCodec::ProcessFrameVADDTX
WebRtc_Word16
ACMCNG::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMCNG::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return WebRtcCng_InitDec(_decoderInstPtr);
}
WebRtc_Word32
ACMCNG::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
// TODO (tlegrand): log error
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_CNG_FUNCTION."
// Then return the structure back to NetEQ to add the codec to it's
// database.
if (_sampFreqHz == 8000 || _sampFreqHz == 16000 || _sampFreqHz == 32000)
{
SET_CODEC_PAR((codecDef), kDecoderCNG, codecInst.pltype,
_decoderInstPtr, _sampFreqHz);
SET_CNG_FUNCTIONS((codecDef));
return 0;
}
else
{
return -1;
}
}
ACMGenericCodec* ACMCNG::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMCNG::InternalCreateEncoder()
{
if(WebRtcCng_CreateEnc(&_encoderInstPtr) < 0)
{
_encoderInstPtr = NULL;
return -1;
}
else
{
return 0;
}
}
void
ACMCNG::DestructEncoderSafe()
{
if(_encoderInstPtr != NULL)
{
WebRtcCng_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
_encoderExist = false;
_encoderInitialized = false;
}
WebRtc_Word16
ACMCNG::InternalCreateDecoder()
{
if(WebRtcCng_CreateDec(&_decoderInstPtr) < 0)
{
_decoderInstPtr = NULL;
return -1;
}
else
{
return 0;
}
}
void
ACMCNG::DestructDecoderSafe()
{
if(_decoderInstPtr != NULL)
{
WebRtcCng_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
_decoderExist = false;
_decoderInitialized = false;
}
void
ACMCNG::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
WebRtcCng_FreeEnc((CNG_enc_inst*)ptrInst);
}
return;
}
WebRtc_Word16
ACMCNG::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderCNG);
}
} // namespace webrtc

View File

@@ -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 ACM_CNG_H
#define ACM_CNG_H
#include "acm_generic_codec.h"
// forward declaration
struct WebRtcCngEncInst;
struct WebRtcCngDecInst;
namespace webrtc
{
class ACMCNG : public ACMGenericCodec
{
public:
ACMCNG(WebRtc_Word16 codecID);
~ACMCNG();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 EnableDTX()
{
return -1;
}
WebRtc_Word16 DisableDTX()
{
return -1;
}
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
WebRtcCngEncInst* _encoderInstPtr;
WebRtcCngDecInst* _decoderInstPtr;
WebRtc_Word16 _sampFreqHz;
};
} // namespace webrtc
#endif // ACM_CNG_H

View File

@@ -0,0 +1,953 @@
/*
* 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.
*/
// 'conversion' conversion from 'type1' to 'type2', possible loss of data
#pragma warning(disable: 4267)
#include <stdio.h>
#include "acm_codec_database.h"
#include "acm_common_defs.h"
#include "trace.h"
// Includes needed to get version info
// and to create the codecs
#include "acm_pcma.h"
#include "acm_pcmu.h"
#include "g711_interface.h"
#include "webrtc_neteq.h"
#include "webrtc_cng.h"
#include "acm_cng.h"
#ifdef WEBRTC_CODEC_AVT
#include "acm_dtmf_playout.h"
#endif
#ifdef WEBRTC_CODEC_RED
#include "acm_red.h"
#endif
#ifdef WEBRTC_CODEC_ILBC
#include "acm_ilbc.h"
#include "ilbc.h"
#endif
#ifdef WEBRTC_CODEC_ISAC
#include "acm_isac.h"
#include "acm_isac_macros.h"
#include "isac.h"
#endif
#ifdef WEBRTC_CODEC_ISACFX
#include "acm_isac.h"
#include "acm_isac_macros.h"
#include "isacfix.h"
#endif
#ifdef WEBRTC_CODEC_PCM16
#include "pcm16b.h"
#include "acm_pcm16b.h"
#endif
#ifdef WEBRTC_CODEC_G722
#include "acm_g722.h"
#include "g722_interface.h"
#endif
namespace webrtc
{
#define TEMPORARY_BUFFER_SIZE 500
bool ACMCodecDB::_isInitiated = false;
WebRtc_Word16 ACMCodecDB::_noOfCodecs = 0;
WebRtc_Word16 ACMCodecDB::_noNetEqDecoders = 0;
WebRtc_Word16 ACMCodecDB::_noPayloads = 0;
WebRtc_Word16 ACMCodecDB::isac = -1;
WebRtc_Word16 ACMCodecDB::isacswb = -1;
WebRtc_Word16 ACMCodecDB::pcm16b = -1;
WebRtc_Word16 ACMCodecDB::pcm16bwb = -1;
WebRtc_Word16 ACMCodecDB::pcm16bswb32 = -1;
WebRtc_Word16 ACMCodecDB::pcm16bswb48 = -1;
WebRtc_Word16 ACMCodecDB::pcmu = -1;
WebRtc_Word16 ACMCodecDB::pcma = -1;
WebRtc_Word16 ACMCodecDB::ilbc = -1;
WebRtc_Word16 ACMCodecDB::gsmAMR = -1;
WebRtc_Word16 ACMCodecDB::gsmAMRWB = -1;
WebRtc_Word16 ACMCodecDB::g722 = -1;
WebRtc_Word16 ACMCodecDB::g722_1_32 = -1;
WebRtc_Word16 ACMCodecDB::g722_1_24 = -1;
WebRtc_Word16 ACMCodecDB::g722_1_16 = -1;
WebRtc_Word16 ACMCodecDB::g722_1C_48 = -1;
WebRtc_Word16 ACMCodecDB::g722_1C_32 = -1;
WebRtc_Word16 ACMCodecDB::g722_1C_24 = -1;
WebRtc_Word16 ACMCodecDB::g729 = -1;
WebRtc_Word16 ACMCodecDB::gsmfr = -1;
WebRtc_Word16 ACMCodecDB::speex8 = -1;
WebRtc_Word16 ACMCodecDB::speex16 = -1;
WebRtc_Word16 ACMCodecDB::cnNB = -1;
WebRtc_Word16 ACMCodecDB::cnWB = -1;
WebRtc_Word16 ACMCodecDB::cnSWB = -1;
WebRtc_Word16 ACMCodecDB::avt = -1;
WebRtc_Word16 ACMCodecDB::red = -1;
WebRtc_UWord8 ACMCodecDB::_nrOfAllowedPacSizes[MAX_NR_OF_CODECS];
WebRtc_UWord16 ACMCodecDB::_allowedPacSizesSmpl[MAX_NR_OF_CODECS][MAX_NR_OF_PACSIZES];
CodecInst ACMCodecDB::_mycodecs[MAX_NR_OF_CODECS];
enum WebRtcNetEQDecoder ACMCodecDB::_netEqDecoders[MAX_NR_OF_CODECS];
WebRtc_Word8 ACMCodecDB::_versions[VERSION_SIZE];
WebRtc_UWord16 ACMCodecDB::_basicCodingBlockSmpl[MAX_NR_OF_CODECS];
WebRtc_UWord16 ACMCodecDB::_channelSupport[MAX_NR_OF_CODECS];
WebRtc_UWord32 ACMCodecDB::_versionStringSize = 0;
// We dynamically allocate some of the dynamic payload types to the defined codecs
// Note! There are a limited number of payload types. If more codecs are defined
// they will receive reserved fixed payload types (values 65-95).
static int kDynamicPayloadtypes[MAX_NR_OF_CODECS] = {
105, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 95, 94, 93, 92, 91, 90, 89,
88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75,
74, 73, 72, 71, 70, 69, 68, 67, 66, 65
};
WebRtc_Word16
ACMCodecDB::Codec(
WebRtc_Word16 listnr,
CodecInst* codec_inst)
{
// Error check to se that listnr is between 0 and (_noOfCodecs - 1)
if ((listnr < 0) || (listnr >= _noOfCodecs))
{
return -1;
}
memcpy(codec_inst,&_mycodecs[listnr],sizeof(CodecInst));
return 0;
}
WebRtc_Word16
ACMCodecDB::CodecNumber(
const CodecInst* codecInst,
WebRtc_Word16& mirrorID,
WebRtc_Word8* errMessage,
WebRtc_Word16 maxErrMsgLenByte)
{
WebRtc_Word16 codecID = ACMCodecDB::CodecNumber(codecInst, mirrorID);
if((codecID < 0) && (errMessage != NULL))
{
WebRtc_Word8 myErrMsg[1000];
if (codecID == -10)
{
// Codec not supported
sprintf(myErrMsg,
"Call to ACMCodecDB::CodecNumber failed, plname=%s is \
not a valid codec", codecInst->plname);
}
else if (codecID == -20)
{
// Sampling frequency doesn't match codec
sprintf(myErrMsg,
"Call to ACMCodecDB::CodecNumber failed, plfreq=%d is \
not a valid frequency for the codec %s", codecInst->plfreq, codecInst->plname);
}
else if (codecID == -30)
{
// Wrong payload type for Comfort Noise
sprintf(myErrMsg,
"Call to ACMCodecDB::CodecNumber failed, payload \
number %d is out of range for %s", codecInst->pltype, codecInst->plname);
}
else if (codecID == -40)
{
// Wrong payload type for RED
sprintf(myErrMsg,
"Call to ACMCodecDB::CodecNumber failed, payload \
number %d is out of range for %s", codecInst->pltype, codecInst->plname);
}
else if (codecID == -50)
{
// Packet size is out of range for the codec
sprintf(myErrMsg,
"Call to ACMCodecDB::CodecNumber failed, Packet \
size is out of range for %s", codecInst->plname);
}
else if (codecID == -60)
{
// Not a valid rate for the codec
sprintf(myErrMsg,
"Call to ACMCodecDB::CodecNumber failed, rate=%d \
is not a valid rate for %s", codecInst->rate, codecInst->plname);
}
else
{
// Other error
sprintf(myErrMsg,
"invalid codec parameters to be registered, \
ACMCodecDB::CodecNumber failed");
}
strncpy(errMessage, myErrMsg, maxErrMsgLenByte - 1);
// make sure that the massage is null-terminated.
errMessage[maxErrMsgLenByte - 1] = '\0';
}
return codecID;
}
WebRtc_Word16
ACMCodecDB::CodecNumber(
const CodecInst* codec_inst,
WebRtc_Word16& mirrorID)
{
WebRtc_Word16 codecNumber = -1;
WebRtc_Word16 nameMatch = 0;
// Find a matching payload name and frequency in the codec list
// Need to check both since some codecs have several codec entries with
// Different frequencies (like iSAC)
for(WebRtc_Word16 i = 0; i < _noOfCodecs; i++)
{
if(STR_CASE_CMP(_mycodecs[i].plname, codec_inst->plname) == 0)
{
//We have found a matching codec name in the list
nameMatch = 1;
// Check if frequncy match
if (codec_inst->plfreq == _mycodecs[i].plfreq)
{
codecNumber = i;
break;
}
}
}
if(codecNumber == -1)
{
if (!nameMatch) {
// Codec name doesn't match any codec in the list
return -10;
} else {
// Error in payload frequency, doesn't match codec
return -20;
}
}
// Check the validity of payload type
if(ValidPayloadType(codec_inst->pltype) < 0)
{
// Payload type out of range
return -40;
}
// Comfort Noise is special case, packet-size & rate is not checked
if(STR_CASE_CMP(_mycodecs[codecNumber].plname, "CN") == 0)
{
mirrorID = codecNumber;
return codecNumber;
}
// RED is special case, packet-size & rate is not checked
if(STR_CASE_CMP(_mycodecs[codecNumber].plname, "red") == 0)
{
mirrorID = codecNumber;
return codecNumber;
}
// Check the validity of packet size
if(_nrOfAllowedPacSizes[codecNumber] > 0)
{
// Check that the new packet size is in the valid range.
bool pacSizeOK = false;
for(WebRtc_Word32 i=0;i< _nrOfAllowedPacSizes[codecNumber];i++)
{
if(codec_inst->pacsize == _allowedPacSizesSmpl[codecNumber][i])
{
pacSizeOK = true;
break;
}
}
if(!pacSizeOK)
{
// Packet size is out of range
return -50;
}
}
if( codec_inst->pacsize < 1)
{
// Packet size is out of range
return -50;
}
mirrorID = codecNumber;
// Check the validity of rate
if(STR_CASE_CMP("isac", codec_inst->plname) == 0)
{
if(IsISACRateValid(codec_inst->rate))
{
// Set mirrorID to iSAC WB which is only created
// once to be used both for iSAC WB and SWB, because
// they need to share struct
mirrorID = ACMCodecDB::isac;
return codecNumber;
}
else
{
// Not a valid rate
return -60;
}
}
else if(STR_CASE_CMP("ilbc", codec_inst->plname) == 0)
{
return IsILBCRateValid(codec_inst->rate, codec_inst->pacsize) ? codecNumber : -60;
}
return IsRateValid(codecNumber, codec_inst->rate) ? codecNumber : -60;
}
WebRtc_Word16
ACMCodecDB::ReceiverCodecNumber(
const CodecInst& codecInst,
WebRtc_Word16& mirrorID)
{
WebRtc_Word16 codecNumber = -1;
WebRtc_Word16 nameMatch = 0;
// Find a matching payload name and frequency in the codec list
// Need to check both since some codecs have several codec entries with
// Different frequencies (like iSAC)
for(WebRtc_Word16 i = 0; i < _noOfCodecs; i++)
{
if(STR_CASE_CMP(_mycodecs[i].plname, codecInst.plname) == 0)
{
//We have found a matching codec name in the list
nameMatch = 1;
// Check if frequency match
if (codecInst.plfreq == _mycodecs[i].plfreq)
{
codecNumber = i;
mirrorID = codecNumber;
// Check if codec is iSAC, set mirrorID to iSAC WB
// which is only created once to be used both for
// iSAC WB and SWB, because they need to share struct
if(STR_CASE_CMP(codecInst.plname, "ISAC") == 0)
{
mirrorID = ACMCodecDB::isac;
}
break;
}
}
}
if(codecNumber == -1)
{
return codecNumber;
}
return codecNumber;
}
// Return number of codecs in the database
WebRtc_Word16
ACMCodecDB::NoOfCodecs()
{
return _noOfCodecs;
}
// Return number of NetEQ decoders in the database.
// Note that the number is huigher than _moOfCodecs because some payload names
// are treated as different decoders in NetEQ, like iSAC wb and swb.
WebRtc_Word16
ACMCodecDB::NoNetEqDecoders()
{
return _noNetEqDecoders;
}
// Return the codec sampling frequency for code number "listnr" in database
WebRtc_Word32
ACMCodecDB::CodecFreq(WebRtc_Word16 listnr)
{
// Error check to se that listnr is between 0 and (_noOfCodecs - 1)
if ( listnr < 0 || listnr >= _noOfCodecs)
return -1;
return _mycodecs[listnr].plfreq;
}
// Return the codecs basic coding block size in samples
WebRtc_Word16
ACMCodecDB::BasicCodingBlock(
WebRtc_Word16 listNr)
{
// Error check to se that listnr is between 0 and (_noOfCodecs - 1)
if ( listNr < 0 || listNr >= _noOfCodecs)
return -1;
return _basicCodingBlockSmpl[listNr];
}
// Return the NetEQ decoder database
enum WebRtcNetEQDecoder*
ACMCodecDB::NetEqDecoders()
{
return _netEqDecoders;
}
// All version numbers for the codecs in the data base are listed in text.
WebRtc_Word16
ACMCodecDB::CodecsVersion(
WebRtc_Word8* version,
WebRtc_UWord32& remainingBufferInBytes,
WebRtc_UWord32& position)
{
WebRtc_UWord32 len = position;
strncpy(&version[len], _versions, remainingBufferInBytes);
position = (WebRtc_UWord32)strlen(version);
remainingBufferInBytes -= (position - len);
if(remainingBufferInBytes < _versionStringSize)
{
return -1;
}
return 0;
}
// Get mirror id. The Id is used for codecs sharing struct for settings that
// need different payload types.
WebRtc_Word16
ACMCodecDB::MirrorID(
const WebRtc_Word16 codecID)
{
if(STR_CASE_CMP(_mycodecs[codecID].plname, "isac") == 0)
{
return ACMCodecDB::isac;
}
else
{
return codecID;
}
}
ACMGenericCodec*
ACMCodecDB::CreateCodecInstance(
const CodecInst* codecInst)
{
// All we have support for right now
if(!STR_CASE_CMP(codecInst->plname, "ISAC"))
{
#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
return new ACMISAC(isac);
#endif
}
else if(!STR_CASE_CMP(codecInst->plname, "PCMU"))
{
return new ACMPCMU(pcmu);
}
else if(!STR_CASE_CMP(codecInst->plname, "PCMA"))
{
return new ACMPCMA(pcma);
}
else if(!STR_CASE_CMP(codecInst->plname, "ILBC"))
{
#ifdef WEBRTC_CODEC_ILBC
return new ACMILBC(ilbc);
#endif
}
else if(!STR_CASE_CMP(codecInst->plname, "G722"))
{
#ifdef WEBRTC_CODEC_G722
return new ACMG722(g722);
#endif
}
else if(!STR_CASE_CMP(codecInst->plname, "CN"))
{
// We need to check sampling frequency
// know what codec to create.
WebRtc_Word16 codecID;
switch(codecInst->plfreq)
{
case 8000:
{
codecID = ACMCodecDB::cnNB;
break;
}
case 16000:
{
codecID = ACMCodecDB::cnWB;
break;
}
case 32000:
{
codecID = ACMCodecDB::cnSWB;
break;
}
default:
return NULL;
}
return new ACMCNG(codecID);
}
else if(!STR_CASE_CMP(codecInst->plname, "L16"))
{
#ifdef WEBRTC_CODEC_PCM16
// For this codec we need to check sampling frequency
// to know what codec to create.
WebRtc_Word16 codecID;
switch(codecInst->plfreq)
{
case 8000:
{
codecID = ACMCodecDB::pcm16b;
break;
}
case 16000:
{
codecID = ACMCodecDB::pcm16bwb;
break;
}
case 32000:
{
codecID = ACMCodecDB::pcm16bswb32;
break;
}
default:
return NULL;
}
return new ACMPCM16B(codecID);
#endif
}
else if(!STR_CASE_CMP(codecInst->plname, "telephone-event"))
{
#ifdef WEBRTC_CODEC_AVT
return new ACMDTMFPlayout(avt);
#endif
}
else if(!STR_CASE_CMP(codecInst->plname, "red"))
{
#ifdef WEBRTC_CODEC_RED
return new ACMRED(red);
#endif
}
return NULL;
}
//Here we build the complete database "_mycodecs" of our codecs
void
ACMCodecDB::initACMCodecDB()
{
if(_isInitiated)
{
return;
}
else
{
_isInitiated = true;
}
WebRtc_Word8 versionNrBuff[TEMPORARY_BUFFER_SIZE];
WebRtc_Word32 remainingSize = VERSION_SIZE;
_versions[0] = '\0';
// Init the stereo settings vector
for (int i=0; i<MAX_NR_OF_CODECS; i++)
{
_channelSupport[i] = 1;
}
#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
strcpy(_mycodecs[_noOfCodecs].plname,"ISAC");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = ISACWB_DEFAULT_RATE; // Default rate
_mycodecs[_noOfCodecs].plfreq = 16000;
_mycodecs[_noOfCodecs].pltype = 103;
_mycodecs[_noOfCodecs].pacsize = ISACWB_PAC_SIZE; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 2;
_allowedPacSizesSmpl[_noOfCodecs][0] = ISACWB_PAC_SIZE; // 480 sampels equals 30 ms
_allowedPacSizesSmpl[_noOfCodecs][1] = ISACWB_PAC_SIZE*2; // 960 sampels equals 60 ms
_basicCodingBlockSmpl[_noOfCodecs] = 0;
isac=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderISAC;
_noOfCodecs++;
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
ACM_ISAC_VERSION(versionNrBuff);
strncat(_versions, "ISAC\t\t", remainingSize);
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, versionNrBuff, remainingSize);
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, "\n", remainingSize);
# if (defined(WEBRTC_CODEC_ISAC))
strcpy(_mycodecs[_noOfCodecs].plname,"ISAC");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = ISACSWB_DEFAULT_RATE; // Default rate
_mycodecs[_noOfCodecs].plfreq = 32000;
_mycodecs[_noOfCodecs].pltype = 104;
_mycodecs[_noOfCodecs].pacsize = ISACSWB_PAC_SIZE; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 1;
_allowedPacSizesSmpl[_noOfCodecs][0] = ISACSWB_PAC_SIZE; // 960 sampels equals 60 ms
_basicCodingBlockSmpl[_noOfCodecs] = 0;
isacswb = _noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderISACswb;
_noOfCodecs++;
# endif
#endif
#ifdef WEBRTC_CODEC_PCM16
strcpy(_mycodecs[_noOfCodecs].plname,"L16");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 128000;
_mycodecs[_noOfCodecs].plfreq = 8000;
_mycodecs[_noOfCodecs].pltype = kDynamicPayloadtypes[_noPayloads++];
_mycodecs[_noOfCodecs].pacsize = 80; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 4;
_allowedPacSizesSmpl[_noOfCodecs][0] = 80; // 80 sampels equals 10 ms
_allowedPacSizesSmpl[_noOfCodecs][1] = 160; // 160 sampels equals 20 ms
_allowedPacSizesSmpl[_noOfCodecs][2] = 240; // 240 sampels equals 30 ms
_allowedPacSizesSmpl[_noOfCodecs][3] = 320; // 320 sampels equals 40 ms
_basicCodingBlockSmpl[_noOfCodecs] = 0;
_channelSupport[_noOfCodecs] = 2;
pcm16b=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderPCM16B;
_noOfCodecs++;
strcpy(_mycodecs[_noOfCodecs].plname,"L16");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 256000;
_mycodecs[_noOfCodecs].plfreq = 16000;
_mycodecs[_noOfCodecs].pltype = kDynamicPayloadtypes[_noPayloads++];
_mycodecs[_noOfCodecs].pacsize = 160; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 4;
_allowedPacSizesSmpl[_noOfCodecs][0] = 160; // 160 sampels equals 10 ms
_allowedPacSizesSmpl[_noOfCodecs][1] = 320; // 320 sampels equals 20 ms
_allowedPacSizesSmpl[_noOfCodecs][2] = 480; // 480 sampels equals 30 ms
_allowedPacSizesSmpl[_noOfCodecs][3] = 640; // 640 sampels equals 40 ms
_basicCodingBlockSmpl[_noOfCodecs] = 0;
_channelSupport[_noOfCodecs] = 2;
pcm16bwb=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderPCM16Bwb;
_noOfCodecs++;
strcpy(_mycodecs[_noOfCodecs].plname,"L16");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 512000;
_mycodecs[_noOfCodecs].plfreq = 32000;
_mycodecs[_noOfCodecs].pltype = kDynamicPayloadtypes[_noPayloads++];
_mycodecs[_noOfCodecs].pacsize = 320; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 2;
_allowedPacSizesSmpl[_noOfCodecs][0] = 320; // 320 sampels equals 10 ms
_allowedPacSizesSmpl[_noOfCodecs][1] = 640; // 640 sampels equals 20 ms
_basicCodingBlockSmpl[_noOfCodecs] = 0;
_channelSupport[_noOfCodecs] = 2;
pcm16bswb32=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderPCM16Bswb32kHz;
_noOfCodecs++;
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, "L16\t\t1.0.0\n", remainingSize);
#endif
strcpy(_mycodecs[_noOfCodecs].plname,"PCMU");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 64000;
_mycodecs[_noOfCodecs].plfreq = 8000;
_mycodecs[_noOfCodecs].pltype = 0;
_mycodecs[_noOfCodecs].pacsize = 160; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 6;
_allowedPacSizesSmpl[_noOfCodecs][0] = 80; // 80 sampels equals 10 ms
_allowedPacSizesSmpl[_noOfCodecs][1] = 160; // 160 sampels equals 20 ms
_allowedPacSizesSmpl[_noOfCodecs][2] = 240; // 240 sampels equals 30 ms
_allowedPacSizesSmpl[_noOfCodecs][3] = 320; // 320 sampels equals 40 ms
_allowedPacSizesSmpl[_noOfCodecs][4] = 400; // 400 sampels equals 50 ms
_allowedPacSizesSmpl[_noOfCodecs][5] = 480; // 480 sampels equals 60 ms
_basicCodingBlockSmpl[_noOfCodecs] = 0; /* 0 indicates all allowed
packetsizes can be used as
basic coding block */
_channelSupport[_noOfCodecs] = 2;
pcmu=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderPCMu;
_noOfCodecs++;
strcpy(_mycodecs[_noOfCodecs].plname,"PCMA");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 64000;
_mycodecs[_noOfCodecs].plfreq = 8000;
_mycodecs[_noOfCodecs].pltype = 8;
_mycodecs[_noOfCodecs].pacsize = 160; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 6;
_allowedPacSizesSmpl[_noOfCodecs][0] = 80; // 80 sampels equals 10 ms
_allowedPacSizesSmpl[_noOfCodecs][1] = 160; // 160 sampels equals 20 ms
_allowedPacSizesSmpl[_noOfCodecs][2] = 240; // 240 sampels equals 30 ms
_allowedPacSizesSmpl[_noOfCodecs][3] = 320; // 320 sampels equals 40 ms
_allowedPacSizesSmpl[_noOfCodecs][4] = 400; // 400 sampels equals 50 ms
_allowedPacSizesSmpl[_noOfCodecs][5] = 480; // 480 sampels equals 60 ms
_basicCodingBlockSmpl[_noOfCodecs] = 0; /* 0 indicates all allowed
packetsizes can be used as
basic coding block */
_channelSupport[_noOfCodecs] = 2;
pcma=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderPCMa;
_noOfCodecs++;
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
WebRtcG711_Version(versionNrBuff, TEMPORARY_BUFFER_SIZE);
strncat(_versions, "G.711\t\t", remainingSize);
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, versionNrBuff, remainingSize);
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, "\n", remainingSize);
#ifdef WEBRTC_CODEC_ILBC
strcpy(_mycodecs[_noOfCodecs].plname,"iLBC");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 13300;
_mycodecs[_noOfCodecs].plfreq = 8000;
_mycodecs[_noOfCodecs].pltype = 102;
_mycodecs[_noOfCodecs].pacsize = 240; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 4;
_allowedPacSizesSmpl[_noOfCodecs][0] = 160; // 160 sampels equals 20 ms
_allowedPacSizesSmpl[_noOfCodecs][1] = 240; // 240 sampels equals 30 ms
_allowedPacSizesSmpl[_noOfCodecs][2] = 320; // 320 sampels equals 40 ms
_allowedPacSizesSmpl[_noOfCodecs][3] = 480; // 480 sampels equals 60 ms
_basicCodingBlockSmpl[_noOfCodecs] = 0; /* 0 indicates all allowed
packetsizes can be used as
basic coding block */
ilbc=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderILBC;
_noOfCodecs++;
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
WebRtcIlbcfix_version(versionNrBuff);
strncat(_versions, "ILBC\t\t", remainingSize);
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, versionNrBuff, remainingSize);
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, "\n", remainingSize);
#endif
#ifdef WEBRTC_CODEC_G722
strcpy(_mycodecs[_noOfCodecs].plname,"G722");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 64000;
_mycodecs[_noOfCodecs].plfreq = 16000;
_mycodecs[_noOfCodecs].pltype = 9;
_mycodecs[_noOfCodecs].pacsize = 320; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 6;
_allowedPacSizesSmpl[_noOfCodecs][0] = 160; // 160 sampels equals 10 ms
_allowedPacSizesSmpl[_noOfCodecs][1] = 320; // 320 sampels equals 20 ms
_allowedPacSizesSmpl[_noOfCodecs][2] = 480; // 480 sampels equals 30 ms
_allowedPacSizesSmpl[_noOfCodecs][3] = 640; // 640 sampels equals 40 ms
_allowedPacSizesSmpl[_noOfCodecs][4] = 800; // 480 sampels equals 50 ms
_allowedPacSizesSmpl[_noOfCodecs][5] = 960; // 640 sampels equals 60 ms
_basicCodingBlockSmpl[_noOfCodecs] = 0;
_channelSupport[_noOfCodecs] = 2;
g722=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderG722;
_noOfCodecs++;
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
WebRtcG722_Version(versionNrBuff, TEMPORARY_BUFFER_SIZE);
strncat(_versions, "G.722\t\t", remainingSize);
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, versionNrBuff, remainingSize);
#endif
// Comfort Noise is always included in the build, no #ifdef needed
strcpy(_mycodecs[_noOfCodecs].plname,"CN");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 0;
_mycodecs[_noOfCodecs].plfreq = 8000;
_mycodecs[_noOfCodecs].pltype = 13;
_mycodecs[_noOfCodecs].pacsize = 240; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 1;
_allowedPacSizesSmpl[_noOfCodecs][0] = 240; // 240 samples equals 30 ms
_basicCodingBlockSmpl[_noOfCodecs] = 240;
cnNB=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderCNG;
_noOfCodecs++;
strcpy(_mycodecs[_noOfCodecs].plname,"CN");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 0;
_mycodecs[_noOfCodecs].plfreq = 16000;
_mycodecs[_noOfCodecs].pltype = 98;
_mycodecs[_noOfCodecs].pacsize = 480; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 1;
_allowedPacSizesSmpl[_noOfCodecs][0] = 480; // 480 samples equals 30 ms
_basicCodingBlockSmpl[_noOfCodecs] = 480;
cnWB=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderCNG;
_noOfCodecs++;
strcpy(_mycodecs[_noOfCodecs].plname,"CN");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 0;
_mycodecs[_noOfCodecs].plfreq = 32000;
_mycodecs[_noOfCodecs].pltype = 99;
_mycodecs[_noOfCodecs].pacsize = 960; // Default packet size
_nrOfAllowedPacSizes[_noOfCodecs] = 1;
_allowedPacSizesSmpl[_noOfCodecs][0] = 960; // 960 samples equals 30 ms
_basicCodingBlockSmpl[_noOfCodecs] = 960;
cnSWB=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderCNG;
_noOfCodecs++;
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
WebRtcCng_Version(versionNrBuff);
strncat(_versions, "CNG\t\t", remainingSize);
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, versionNrBuff, remainingSize);
#ifdef WEBRTC_CODEC_AVT
strcpy(_mycodecs[_noOfCodecs].plname,"telephone-event");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].plfreq = 8000;
_mycodecs[_noOfCodecs].rate = 0;
_mycodecs[_noOfCodecs].pltype = 106;
_mycodecs[_noOfCodecs].pacsize = 240; // Default packet size 240ms
_nrOfAllowedPacSizes[_noOfCodecs] = 1;
_allowedPacSizesSmpl[_noOfCodecs][0] = 240; // 240 samples equals 30 ms
_basicCodingBlockSmpl[_noOfCodecs] = 240;
avt=_noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderAVT;
_noOfCodecs++;
// Currently tone generation doesn't have a getVersion-function
remainingSize = (WebRtc_Word32)(VERSION_SIZE - strlen(_versions));
strncat(_versions, "Tone Generation\t1.0.0\n", remainingSize);
#endif
#ifdef WEBRTC_CODEC_RED
strcpy(_mycodecs[_noOfCodecs].plname,"red");
_mycodecs[_noOfCodecs].channels = 1;
_mycodecs[_noOfCodecs].rate = 0;
_mycodecs[_noOfCodecs].plfreq = 8000;
_mycodecs[_noOfCodecs].pltype = 127;
_mycodecs[_noOfCodecs].pacsize = 0;
_nrOfAllowedPacSizes[_noOfCodecs] = 1;
_allowedPacSizesSmpl[_noOfCodecs][0] = 0;
_basicCodingBlockSmpl[_noOfCodecs] = 0;
red = _noOfCodecs;
_netEqDecoders[_noNetEqDecoders++] = kDecoderRED;
_noOfCodecs++;
#endif
_versionStringSize = (WebRtc_UWord32)strlen(_versions);
}
// Check if the bitrate is valid for the codec
bool
ACMCodecDB::IsRateValid(
const WebRtc_Word16 listNr,
const WebRtc_Word32 rate)
{
if(_mycodecs[listNr].rate == rate)
{
return true;
}
else
{
return false;
}
}
// Check if the bitrate is valid for iSAC
bool
ACMCodecDB::IsISACRateValid(
#if (!defined(WEBRTC_CODEC_ISAC) && !defined(WEBRTC_CODEC_ISACFX))
const WebRtc_Word32 /* rate */)
{
return false;
#else
const WebRtc_Word32 rate)
{
if((rate == -1) ||
((rate <= 56000) && (rate >= 10000)))
{
return true;
}
else
{
return false;
}
#endif
}
// Check if the bitrate is valid for iLBC
bool
ACMCodecDB::IsILBCRateValid(
#ifndef WEBRTC_CODEC_ILBC
const WebRtc_Word32 /* rate */,
const WebRtc_Word16 /* frameSizeSamples */)
{
return false;
#else
const WebRtc_Word32 rate,
const WebRtc_Word16 frameSizeSamples)
{
if(((frameSizeSamples == 240) || (frameSizeSamples == 480)) &&
(rate == 13300))
{
return true;
}
else if(((frameSizeSamples == 160) || (frameSizeSamples == 320)) &&
(rate == 15200))
{
return true;
}
else
{
return false;
}
#endif
}
// Check if the payload type is valid
WebRtc_Word16
ACMCodecDB::ValidPayloadType(
const int payloadType)
{
if((payloadType < 0) || (payloadType > 127))
{
return -1;
}
return 0;
}
} // namespace webrtc

View File

@@ -0,0 +1,138 @@
/*
* 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_CODEC_DATABASE_H
#define ACM_CODEC_DATABASE_H
#include "acm_generic_codec.h"
#include "common_types.h"
#include "typedefs.h"
#include "webrtc_neteq.h"
namespace webrtc
{
// These might need to be increased if adding a new codec to
// the database
#define MAX_NR_OF_CODECS 52
#define MAX_NR_OF_PACSIZES 6
#define VERSION_SIZE 1000
class ACMCodecDB
{
public:
static WebRtc_Word16 Codec(
WebRtc_Word16 listnr,
CodecInst* codec_inst);
static WebRtc_Word16 CodecNumber(
const CodecInst* codec_inst,
WebRtc_Word16& mirrorID,
WebRtc_Word8* errMessage,
WebRtc_Word16 maxErrMsgLenByte);
static WebRtc_Word16 CodecNumber(
const CodecInst* codec_inst,
WebRtc_Word16& mirrorID);
static WebRtc_Word16 ReceiverCodecNumber(
const CodecInst& codecInst,
WebRtc_Word16& mirrorID);
static WebRtc_Word16 NoOfCodecs();
static WebRtc_Word16 NoNetEqDecoders();
static WebRtc_Word32 CodecFreq(
WebRtc_Word16 listnr);
static WebRtc_Word16 BasicCodingBlock(
WebRtc_Word16 listnr);
static enum WebRtcNetEQDecoder* NetEqDecoders();
static WebRtc_Word16 CodecsVersion(
WebRtc_Word8* version,
WebRtc_UWord32& remainingBufferInBytes,
WebRtc_UWord32& position);
static WebRtc_Word16 MirrorID(
const WebRtc_Word16 codecID);
static ACMGenericCodec* CreateCodecInstance(
const CodecInst* codecInst);
static void initACMCodecDB();
static bool IsRateValid(
const WebRtc_Word16 listNr,
const WebRtc_Word32 rate);
static bool IsISACRateValid(
const WebRtc_Word32 rate);
static bool IsILBCRateValid(
const WebRtc_Word32 rate,
const WebRtc_Word16 frameSizeSamples);
static WebRtc_Word16 ValidPayloadType(
const int payloadType);
static WebRtc_Word16
pcm16b,
pcm16bwb,
pcm16bswb32,
pcm16bswb48,
pcmu,
pcma,
ilbc,
gsmAMR,
gsmAMRWB,
g722,
g722_1_32,
g722_1_24,
g722_1_16,
g722_1C_48,
g722_1C_32,
g722_1C_24,
g729,
isac,
isacswb,
gsmfr,
speex8,
speex16,
cnNB,
cnWB,
cnSWB,
avt,
red;
static WebRtc_Word16 _noOfCodecs;
static WebRtc_Word16 _noNetEqDecoders;
static WebRtc_Word16 _noPayloads;
// Information about the supported codecs
static CodecInst _mycodecs[MAX_NR_OF_CODECS];
static enum WebRtcNetEQDecoder _netEqDecoders[MAX_NR_OF_CODECS];
static WebRtc_UWord16 _allowedPacSizesSmpl[MAX_NR_OF_CODECS][MAX_NR_OF_PACSIZES];
static WebRtc_UWord8 _nrOfAllowedPacSizes[MAX_NR_OF_CODECS];
static WebRtc_UWord16 _basicCodingBlockSmpl[MAX_NR_OF_CODECS];
static WebRtc_UWord16 _channelSupport[MAX_NR_OF_CODECS];
private:
static bool _isInitiated;
static WebRtc_Word8 _versions[VERSION_SIZE];
static WebRtc_UWord32 _versionStringSize;
};
} // namespace webrtc
#endif //ACM_CODEC_DATABASE_H

View File

@@ -0,0 +1,120 @@
/*
* 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 WEBRTC_ACM_COMMON_DEFS_H
#define WEBRTC_ACM_COMMON_DEFS_H
#include <string.h>
#include "audio_coding_module_typedefs.h"
#include "common_types.h"
#include "engine_configurations.h"
#include "typedefs.h"
// Checks for enabled codecs, we prevent enabling codecs which are not
// compatible.
#if ((defined WEBRTC_CODEC_ISAC) && (defined WEBRTC_CODEC_ISACFX))
# error iSAC and iSACFX codecs cannot be enabled at the same time
#endif
#ifdef WIN32
// 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
namespace webrtc
{
// 60 ms is the maximum block size we support. An extra 20 ms is considered
// for safety if process() method is not called when it should be, i.e. we
// accept 20 ms of jitter. 80 ms @ 32 kHz (super wide-band) is 2560 samples.
#define AUDIO_BUFFER_SIZE_W16 2560
// There is one timestamp per each 10 ms of audio
// the audio buffer, at max, may contain 32 blocks of 10ms
// audio if the sampling frequency is 8000 Hz (80 samples per block).
// Therefore, The size of the buffer where we keep timestamps
// is defined as follows
#define TIMESTAMP_BUFFER_SIZE_W32 AUDIO_BUFFER_SIZE_W16/80
// The maximum size of a payload, that is 60 ms of PCM-16 @ 32 kHz stereo
#define MAX_PAYLOAD_SIZE_BYTE 7680
// General codec specific defines
#define ISACWB_DEFAULT_RATE 32000
#define ISACSWB_DEFAULT_RATE 56000
#define ISACWB_PAC_SIZE 480
#define ISACSWB_PAC_SIZE 960
// An encoded bit-stream is labeled by one of the following enumerators.
//
// kNoEncoding : There has been no encoding.
// kActiveNormalEncoded : Active audio frame coded by the codec.
// kPassiveNormalEncoded : Passive audio frame coded by the codec.
// kPassiveDTXNB : Passive audio frame coded by narrow-band CN.
// kPassiveDTXWB : Passive audio frame coded by wide-band CN.
// kPassiveDTXSWB : Passive audio frame coded by super-wide-band CN.
//
enum WebRtcACMEncodingType
{
kNoEncoding,
kActiveNormalEncoded,
kPassiveNormalEncoded,
kPassiveDTXNB,
kPassiveDTXWB,
kPassiveDTXSWB
};
// A structure which contains codec parameters. For instance, used when
// initializing encoder and decoder.
//
// codecInstant : c.f. common_types.h
// enableDTX : set true to enable DTX. If codec does not have
// internal DTX, this will enable VAD.
// enableVAD : set true to enable VAD.
// vadMode : VAD mode, c.f. audio_coding_module_typedefs.h
// for possible values.
struct WebRtcACMCodecParams
{
CodecInst codecInstant;
bool enableDTX;
bool enableVAD;
ACMVADMode vadMode;
};
// A structure that encapsulates audio buffer and related parameters
// used for synchronization of audio of two ACMs.
//
// inAudio : same as ACMGenericCodec::_inAudio
// inAudioIxRead : same as ACMGenericCodec::_inAudioIxRead
// inAudioIxWrite : same as ACMGenericCodec::_inAudioIxWrite
// inTimestamp : same as ACMGenericCodec::_inTimestamp
// inTimestampIxWrite : same as ACMGenericCodec::_inTImestampIxWrite
// lastTimestamp : same as ACMGenericCodec::_lastTimestamp
// lastInTimestamp : same as AudioCodingModuleImpl::_lastInTimestamp
//
struct WebRtcACMAudioBuff
{
WebRtc_Word16 inAudio[AUDIO_BUFFER_SIZE_W16];
WebRtc_Word16 inAudioIxRead;
WebRtc_Word16 inAudioIxWrite;
WebRtc_UWord32 inTimestamp[TIMESTAMP_BUFFER_SIZE_W32];
WebRtc_Word16 inTimestampIxWrite;
WebRtc_UWord32 lastTimestamp;
WebRtc_UWord32 lastInTimestamp;
};
} // namespace webrtc
#endif

View File

@@ -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.
*/
#include "acm_dtmf_detection.h"
#include "audio_coding_module_typedefs.h"
namespace webrtc
{
ACMDTMFDetection::ACMDTMFDetection()
{
}
ACMDTMFDetection::~ACMDTMFDetection()
{
}
WebRtc_Word16
ACMDTMFDetection::Enable(
ACMCountries /* cpt */)
{
return -1;
}
WebRtc_Word16
ACMDTMFDetection::Disable()
{
return -1;
}
WebRtc_Word16
ACMDTMFDetection::Detect(
const WebRtc_Word16* /* inAudioBuff */,
const WebRtc_UWord16 /* inBuffLenWord16 */,
const WebRtc_Word32 /* inFreqHz */,
bool& /* toneDetected */,
WebRtc_Word16& /* tone */)
{
return -1;
}
WebRtc_Word16
ACMDTMFDetection::GetVersion(
WebRtc_Word8* /* version */,
WebRtc_UWord32& /* remainingBufferInBytes */,
WebRtc_UWord32& /* position */)
{
return -1;
}
} // namespace webrtc

View File

@@ -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 ACM_DTMF_DETECTION_H
#define ACM_DTMF_DETECTION_H
#include "acm_resampler.h"
#include "audio_coding_module_typedefs.h"
#include "typedefs.h"
namespace webrtc
{
class ACMDTMFDetection
{
public:
ACMDTMFDetection();
~ACMDTMFDetection();
WebRtc_Word16 Enable(ACMCountries cpt = ACMDisableCountryDetection);
WebRtc_Word16 Disable();
WebRtc_Word16 Detect(
const WebRtc_Word16* inAudioBuff,
const WebRtc_UWord16 inBuffLenWord16,
const WebRtc_Word32 inFreqHz,
bool& toneDetected,
WebRtc_Word16& tone);
static WebRtc_Word16 GetVersion(
WebRtc_Word8* version,
WebRtc_UWord32& remainingBufferInBytes,
WebRtc_UWord32& position);
private:
ACMResampler _resampler;
bool _init;
};
} // namespace webrtc
#endif // ACM_DTMF_DETECTION_H

View File

@@ -0,0 +1,268 @@
/*
* 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 "acm_common_defs.h"
#include "acm_dtmf_playout.h"
#include "acm_neteq.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
namespace webrtc
{
#ifndef WEBRTC_CODEC_AVT
ACMDTMFPlayout::ACMDTMFPlayout(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMDTMFPlayout::~ACMDTMFPlayout()
{
return;
}
WebRtc_Word16
ACMDTMFPlayout::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMDTMFPlayout::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMDTMFPlayout::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMDTMFPlayout::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMDTMFPlayout::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMDTMFPlayout::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMDTMFPlayout::InternalCreateEncoder()
{
return -1;
}
WebRtc_Word16
ACMDTMFPlayout::InternalCreateDecoder()
{
return -1;
}
void
ACMDTMFPlayout::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
void
ACMDTMFPlayout::DestructEncoderSafe()
{
return;
}
void
ACMDTMFPlayout::DestructDecoderSafe()
{
return;
}
WebRtc_Word16
ACMDTMFPlayout::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
ACMDTMFPlayout::ACMDTMFPlayout(
WebRtc_Word16 codecID)
{
_codecID = codecID;
}
ACMDTMFPlayout::~ACMDTMFPlayout()
{
return;
}
WebRtc_Word16
ACMDTMFPlayout::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return 0;
}
WebRtc_Word16
ACMDTMFPlayout::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMDTMFPlayout::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// DTMFPlayout has no instance
return 0;
}
WebRtc_Word16
ACMDTMFPlayout::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// DTMFPlayout has no instance
return 0;
}
WebRtc_Word32
ACMDTMFPlayout::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_AVT_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderAVT, codecInst.pltype, NULL, 8000);
SET_AVT_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMDTMFPlayout::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMDTMFPlayout::InternalCreateEncoder()
{
// DTMFPlayout has no instance
return 0;
}
WebRtc_Word16
ACMDTMFPlayout::InternalCreateDecoder()
{
// DTMFPlayout has no instance
return 0;
}
void
ACMDTMFPlayout::InternalDestructEncoderInst(
void* /* ptrInst */)
{
// DTMFPlayout has no instance
return;
}
void
ACMDTMFPlayout::DestructEncoderSafe()
{
// DTMFPlayout has no instance
return;
}
void
ACMDTMFPlayout::DestructDecoderSafe()
{
// DTMFPlayout has no instance
return;
}
WebRtc_Word16
ACMDTMFPlayout::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderAVT);
}
#endif
} // namespace webrtc

View File

@@ -0,0 +1,68 @@
/*
* 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_DTMF_PLAYOUT_H
#define ACM_DTMF_PLAYOUT_H
#include "acm_generic_codec.h"
namespace webrtc
{
class ACMDTMFPlayout : public ACMGenericCodec
{
public:
ACMDTMFPlayout(WebRtc_Word16 codecID);
~ACMDTMFPlayout();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
void InternalDestructEncoderInst(
void* ptrInst);
};
} // namespace webrtc
#endif // ACM_DTMF_PLAYOUT_H

View File

@@ -0,0 +1,449 @@
/*
* 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 "acm_codec_database.h"
#include "acm_common_defs.h"
#include "acm_g722.h"
#include "acm_neteq.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#include "g722_interface.h"
namespace webrtc
{
#ifndef WEBRTC_CODEC_G722
ACMG722::ACMG722(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMG722::~ACMG722()
{
return;
}
WebRtc_Word32
ACMG722::Add10MsDataSafe(
const WebRtc_UWord32 /* timestamp */,
const WebRtc_Word16* /* data */,
const WebRtc_UWord16 /* lengthSmpl */,
const WebRtc_UWord8 /* audioChannel */)
{
return -1;
}
WebRtc_Word16
ACMG722::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMG722::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMG722::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMG722::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMG722::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMG722::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG722::InternalCreateEncoder()
{
return -1;
}
void
ACMG722::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMG722::InternalCreateDecoder()
{
return -1;
}
void
ACMG722::DestructDecoderSafe()
{
return;
}
void
ACMG722::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMG722::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
// Encoder and decoder memory
struct ACMG722EncStr {
G722EncInst* inst; // instance for left channel in case of stereo
G722EncInst* instRight; // instance for right channel in case of stereo
};
struct ACMG722DecStr {
G722DecInst* inst; // instance for left channel in case of stereo
G722DecInst* instRight; // instance for right channel in case of stereo
};
ACMG722::ACMG722(
WebRtc_Word16 codecID)
{
// Encoder
_ptrEncStr = new ACMG722EncStr;
if(_ptrEncStr != NULL)
{
_ptrEncStr->inst = NULL;
_ptrEncStr->instRight = NULL;
}
// Decoder
_ptrDecStr = new ACMG722DecStr;
if(_ptrDecStr != NULL)
{
_ptrDecStr->inst = NULL;
_ptrDecStr->instRight = NULL; // Not used
}
_codecID = codecID;
return;
}
ACMG722::~ACMG722()
{
if(_ptrEncStr != NULL)
{
if(_ptrEncStr->inst != NULL)
{
WebRtcG722_FreeEncoder(_ptrEncStr->inst);
_ptrEncStr->inst = NULL;
}
if(_ptrEncStr->instRight != NULL)
{
WebRtcG722_FreeEncoder(_ptrEncStr->instRight);
_ptrEncStr->instRight = NULL;
}
delete _ptrEncStr;
_ptrEncStr = NULL;
}
if(_ptrDecStr != NULL)
{
if(_ptrDecStr->inst != NULL)
{
WebRtcG722_FreeDecoder(_ptrDecStr->inst);
_ptrDecStr->inst = NULL;
}
if(_ptrDecStr->instRight != NULL)
{
WebRtcG722_FreeDecoder(_ptrDecStr->instRight);
_ptrDecStr->instRight = NULL;
}
delete _ptrDecStr;
_ptrDecStr = NULL;
}
return;
}
WebRtc_Word32
ACMG722::Add10MsDataSafe(
const WebRtc_UWord32 timestamp,
const WebRtc_Word16* data,
const WebRtc_UWord16 lengthSmpl,
const WebRtc_UWord8 audioChannel)
{
return ACMGenericCodec::Add10MsDataSafe((timestamp>>1), data, lengthSmpl,
audioChannel);
}
WebRtc_Word16
ACMG722::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
// If stereo, split input signal in left and right channel before encoding
if(_noChannels == 2) {
WebRtc_Word16 leftChannel[960];
WebRtc_Word16 rightChannel[960];
WebRtc_UWord8 outLeft[480];
WebRtc_UWord8 outRight[480];
WebRtc_Word16 lenInBytes;
for (int i=0, j=0; i<_frameLenSmpl*2; i+=2, j++) {
leftChannel[j] = _inAudio[_inAudioIxRead+i];
rightChannel[j] = _inAudio[_inAudioIxRead+i+1];
}
lenInBytes = WebRtcG722_Encode(_encoderInstPtr,
leftChannel, _frameLenSmpl, (WebRtc_Word16*)outLeft);
lenInBytes += WebRtcG722_Encode(_encoderInstPtrRight,
rightChannel, _frameLenSmpl, (WebRtc_Word16*)outRight);
*bitStreamLenByte = lenInBytes;
// Interleave the 4 bits per sample from left and right channel
for (int i=0, j=0; i<lenInBytes; i+=2, j++)
{
bitStream[i] = (outRight[j] & 0xF0) + (outLeft[j] >> 4);
bitStream[i+1] = ((outRight[j] & 0x0F) << 4) + (outLeft[j] & 0x0F);
}
} else {
*bitStreamLenByte = WebRtcG722_Encode(_encoderInstPtr,
&_inAudio[_inAudioIxRead], _frameLenSmpl, (WebRtc_Word16*)bitStream);
}
// increment the read index this tell the caller how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _frameLenSmpl*_noChannels;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMG722::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMG722::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
if(codecParams->codecInstant.channels == 2)
{
// Create codec struct for right channel
if (_ptrEncStr->instRight == NULL)
{
WebRtcG722_CreateEncoder(&_ptrEncStr->instRight);
if(_ptrEncStr->instRight == NULL)
{
return -1;
}
}
_encoderInstPtrRight = (G722EncInst*)_ptrEncStr->instRight;
if (WebRtcG722_EncoderInit(_encoderInstPtrRight) < 0)
{
return -1;
}
}
return WebRtcG722_EncoderInit(_encoderInstPtr);
}
WebRtc_Word16
ACMG722::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return WebRtcG722_DecoderInit(_decoderInstPtr);
}
WebRtc_Word32
ACMG722::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
// TODO: log error
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_G722_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderG722, codecInst.pltype,
_decoderInstPtr, 16000);
SET_G722_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMG722::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG722::InternalCreateEncoder()
{
if(_ptrEncStr == NULL)
{
// this structure must be created at the costructor
// if it is still NULL then there is a probelm and
// we dont continue
return -1;
}
WebRtcG722_CreateEncoder(&_ptrEncStr->inst);
if(_ptrEncStr->inst == NULL)
{
return -1;
}
_encoderInstPtr = (G722EncInst*)_ptrEncStr->inst;
return 0;
}
void
ACMG722::DestructEncoderSafe()
{
if(_ptrEncStr != NULL)
{
if(_ptrEncStr->inst != NULL)
{
WebRtcG722_FreeEncoder(_ptrEncStr->inst);
_ptrEncStr->inst = NULL;
}
}
_encoderExist = false;
_encoderInitialized = false;
}
WebRtc_Word16
ACMG722::InternalCreateDecoder()
{
if(_ptrDecStr == NULL)
{
// this structure must be created at the costructor
// if it is still NULL then there is a probelm and
// we dont continue
return -1;
}
WebRtcG722_CreateDecoder(&_ptrDecStr->inst);
if(_ptrDecStr->inst == NULL)
{
return -1;
}
_decoderInstPtr = (G722DecInst*)_ptrDecStr->inst;
return 0;
}
void
ACMG722::DestructDecoderSafe()
{
_decoderExist = false;
_decoderInitialized = false;
if(_ptrDecStr != NULL)
{
if(_ptrDecStr->inst != NULL)
{
WebRtcG722_FreeDecoder(_ptrDecStr->inst);
_ptrDecStr->inst = NULL;
}
}
}
void
ACMG722::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
WebRtcG722_FreeEncoder((G722EncInst*)ptrInst);
}
return;
}
WebRtc_Word16
ACMG722::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderG722);
}
#endif
} // namespace webrtc

View File

@@ -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 ACM_G722_H
#define ACM_G722_H
#include "acm_generic_codec.h"
typedef struct WebRtcG722EncInst G722EncInst;
typedef struct WebRtcG722DecInst G722DecInst;
namespace webrtc
{
// forward declaration
struct ACMG722EncStr;
struct ACMG722DecStr;
class ACMG722 : public ACMGenericCodec
{
public:
ACMG722(WebRtc_Word16 codecID);
~ACMG722();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
WebRtc_Word32 Add10MsDataSafe(
const WebRtc_UWord32 timestamp,
const WebRtc_Word16* data,
const WebRtc_UWord16 lengthSmpl,
const WebRtc_UWord8 audioChannel);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
ACMG722EncStr* _ptrEncStr;
ACMG722DecStr* _ptrDecStr;
G722EncInst* _encoderInstPtr;
G722EncInst* _encoderInstPtrRight; // Prepared for stereo
G722DecInst* _decoderInstPtr;
};
} // namespace webrtc
#endif // ACM_G722_H

View File

@@ -0,0 +1,675 @@
/*
* 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 "acm_codec_database.h"
#include "acm_common_defs.h"
#include "acm_g7221.h"
#include "acm_neteq.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_G722_1
// NOTE! G.722.1 is not included in the open-source package. Modify this file or your codec
// API to match the function call and name of used G.722.1 API file.
// #include "g7221_interface.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_G722_1
ACMG722_1::ACMG722_1(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMG722_1::~ACMG722_1()
{
return;
}
WebRtc_Word16
ACMG722_1::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMG722_1::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMG722_1::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMG722_1::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMG722_1::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMG722_1::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG722_1::InternalCreateEncoder()
{
return -1;
}
void
ACMG722_1::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMG722_1::InternalCreateDecoder()
{
return -1;
}
void
ACMG722_1::DestructDecoderSafe()
{
return;
}
void
ACMG722_1::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMG722_1::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
// Remove when integrating a real G.722.1 wrapper
struct G722_1_Inst_t_;
extern WebRtc_Word16 WebRtcG7221_CreateEnc16(G722_1_16_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221_CreateEnc24(G722_1_24_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221_CreateEnc32(G722_1_32_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221_CreateDec16(G722_1_16_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221_CreateDec24(G722_1_24_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221_CreateDec32(G722_1_32_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221_FreeEnc16(G722_1_16_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221_FreeEnc24(G722_1_24_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221_FreeEnc32(G722_1_32_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221_FreeDec16(G722_1_16_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221_FreeDec24(G722_1_24_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221_FreeDec32(G722_1_32_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221_EncoderInit16(G722_1_16_encinst_t_* encInst);
extern WebRtc_Word16 WebRtcG7221_EncoderInit24(G722_1_24_encinst_t_* encInst);
extern WebRtc_Word16 WebRtcG7221_EncoderInit32(G722_1_32_encinst_t_* encInst);
extern WebRtc_Word16 WebRtcG7221_DecoderInit16(G722_1_16_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcG7221_DecoderInit24(G722_1_24_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcG7221_DecoderInit32(G722_1_32_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcG7221_Encode16(G722_1_16_encinst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221_Encode24(G722_1_24_encinst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221_Encode32(G722_1_32_encinst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221_Decode16(G722_1_16_decinst_t_* decInst,
WebRtc_Word16* bitstream,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221_Decode24(G722_1_24_decinst_t_* decInst,
WebRtc_Word16* bitstream,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221_Decode32(G722_1_32_decinst_t_* decInst,
WebRtc_Word16* bitstream,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221_DecodePlc16(G722_1_16_decinst_t_* decInst,
WebRtc_Word16* output,
WebRtc_Word16 nrLostFrames);
extern WebRtc_Word16 WebRtcG7221_DecodePlc24(G722_1_24_decinst_t_* decInst,
WebRtc_Word16* output,
WebRtc_Word16 nrLostFrames);
extern WebRtc_Word16 WebRtcG7221_DecodePlc32(G722_1_32_decinst_t_* decInst,
WebRtc_Word16* output,
WebRtc_Word16 nrLostFrames);
ACMG722_1::ACMG722_1(
WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_encoderInstPtrRight(NULL),
_decoderInstPtr(NULL),
_encoderInst16Ptr(NULL),
_encoderInst16PtrR(NULL),
_encoderInst24Ptr(NULL),
_encoderInst24PtrR(NULL),
_encoderInst32Ptr(NULL),
_encoderInst32PtrR(NULL),
_decoderInst16Ptr(NULL),
_decoderInst24Ptr(NULL),
_decoderInst32Ptr(NULL)
{
_codecID = codecID;
if(_codecID == ACMCodecDB::g722_1_16)
{
_operationalRate = 16000;
}
else if(_codecID == ACMCodecDB::g722_1_24)
{
_operationalRate = 24000;
}
else if(_codecID == ACMCodecDB::g722_1_32)
{
_operationalRate = 32000;
}
else
{
_operationalRate = -1;
}
return;
}
ACMG722_1::~ACMG722_1()
{
if(_encoderInstPtr != NULL)
{
delete _encoderInstPtr;
_encoderInstPtr = NULL;
}
if(_encoderInstPtrRight != NULL)
{
delete _encoderInstPtrRight;
_encoderInstPtrRight = NULL;
}
if(_decoderInstPtr != NULL)
{
delete _decoderInstPtr;
_decoderInstPtr = NULL;
}
switch(_operationalRate)
{
case 16000:
{
_encoderInst16Ptr = NULL;
_encoderInst16PtrR = NULL;
_decoderInst16Ptr = NULL;
break;
}
case 24000:
{
_encoderInst24Ptr = NULL;
_encoderInst24PtrR = NULL;
_decoderInst24Ptr = NULL;
break;
}
case 32000:
{
_encoderInst32Ptr = NULL;
_encoderInst32PtrR = NULL;
_decoderInst32Ptr = NULL;
break;
}
default:
{
break;
}
}
return;
}
WebRtc_Word16
ACMG722_1::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
WebRtc_Word16 leftChannel[320];
WebRtc_Word16 rightChannel[320];
WebRtc_Word16 lenInBytes;
WebRtc_Word16 outB[160];
// If stereo, split input signal in left and right channel before encoding
if(_noChannels == 2)
{
for (int i=0, j=0; i<_frameLenSmpl*2; i+=2, j++) {
leftChannel[j] = _inAudio[_inAudioIxRead+i];
rightChannel[j] = _inAudio[_inAudioIxRead+i+1];
}
} else {
memcpy(leftChannel, &_inAudio[_inAudioIxRead], 320);
}
switch(_operationalRate)
{
case 16000:
{
lenInBytes = WebRtcG7221_Encode16(_encoderInst16Ptr,
leftChannel, 320, &outB[0]);
if (_noChannels == 2)
{
lenInBytes += WebRtcG7221_Encode16(_encoderInst16PtrR,
rightChannel, 320, &outB[lenInBytes/2]);
}
break;
}
case 24000:
{
lenInBytes = WebRtcG7221_Encode24(_encoderInst24Ptr,
leftChannel, 320, &outB[0]);
if (_noChannels == 2)
{
lenInBytes += WebRtcG7221_Encode24(_encoderInst24PtrR,
rightChannel, 320, &outB[lenInBytes/2]);
}
break;
}
case 32000:
{
lenInBytes = WebRtcG7221_Encode32(_encoderInst32Ptr,
leftChannel, 320, &outB[0]);
if (_noChannels == 2)
{
lenInBytes += WebRtcG7221_Encode32(_encoderInst32PtrR,
rightChannel, 320, &outB[lenInBytes/2]);
}
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitEncode: Wrong rate for G722_1.");
return -1;
break;
}
}
memcpy(bitStream, outB, lenInBytes);
*bitStreamLenByte = lenInBytes;
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += 320*_noChannels;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMG722_1::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMG722_1::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
WebRtc_Word16 ret;
switch(_operationalRate)
{
case 16000:
{
ret = WebRtcG7221_EncoderInit16(_encoderInst16PtrR);
if (ret < 0) {
return ret;
}
return WebRtcG7221_EncoderInit16(_encoderInst16Ptr);
break;
}
case 24000:
{
ret = WebRtcG7221_EncoderInit24(_encoderInst24PtrR);
if (ret < 0) {
return ret;
}
return WebRtcG7221_EncoderInit24(_encoderInst24Ptr);
break;
}
case 32000:
{
ret = WebRtcG7221_EncoderInit32(_encoderInst32PtrR);
if (ret < 0) {
return ret;
}
return WebRtcG7221_EncoderInit32(_encoderInst32Ptr);
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitEncoder: Wrong rate for G722_1.");
return -1;
break;
}
}
}
WebRtc_Word16
ACMG722_1::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
switch(_operationalRate)
{
case 16000:
{
return WebRtcG7221_DecoderInit16(_decoderInst16Ptr);
break;
}
case 24000:
{
return WebRtcG7221_DecoderInit24(_decoderInst24Ptr);
break;
}
case 32000:
{
return WebRtcG7221_DecoderInit32(_decoderInst32Ptr);
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitDecoder: Wrong rate for G722_1.");
return -1;
break;
}
}
}
WebRtc_Word32
ACMG722_1::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
// Todo:
// log error
return -1;
}
// NetEq has an array of pointers to WebRtcNetEQ_CodecDef.
// get an entry of that array (neteq wrapper will allocate memory)
// by calling "netEq->CodecDef", where "NETEQ_CODEC_G722_1_XX" would
// be the index of the entry.
// Fill up the given structure by calling
// "SET_CODEC_PAR" & "SET_G722_1_XX_FUNCTION."
// Then return the structure back to NetEQ to add the codec to it's
// database.
switch(_operationalRate)
{
case 16000:
{
SET_CODEC_PAR((codecDef), kDecoderG722_1_16, codecInst.pltype,
_decoderInst16Ptr, 16000);
SET_G722_1_16_FUNCTIONS((codecDef));
break;
}
case 24000:
{
SET_CODEC_PAR((codecDef), kDecoderG722_1_24, codecInst.pltype,
_decoderInst24Ptr, 16000);
SET_G722_1_24_FUNCTIONS((codecDef));
break;
}
case 32000:
{
SET_CODEC_PAR((codecDef), kDecoderG722_1_32, codecInst.pltype,
_decoderInst32Ptr, 16000);
SET_G722_1_32_FUNCTIONS((codecDef));
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"CodecDef: Wrong rate for G722_1.");
return -1;
break;
}
}
return 0;
}
ACMGenericCodec*
ACMG722_1::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG722_1::InternalCreateEncoder()
{
if((_encoderInstPtr == NULL) || (_encoderInstPtrRight == NULL))
{
return -1;
}
switch(_operationalRate)
{
case 16000:
{
WebRtcG7221_CreateEnc16(&_encoderInst16Ptr);
WebRtcG7221_CreateEnc16(&_encoderInst16PtrR);
break;
}
case 24000:
{
WebRtcG7221_CreateEnc24(&_encoderInst24Ptr);
WebRtcG7221_CreateEnc24(&_encoderInst24PtrR);
break;
}
case 32000:
{
WebRtcG7221_CreateEnc32(&_encoderInst32Ptr);
WebRtcG7221_CreateEnc32(&_encoderInst32PtrR);
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateEncoder: Wrong rate for G722_1.");
return -1;
break;
}
}
return 0;
}
void
ACMG722_1::DestructEncoderSafe()
{
_encoderExist = false;
_encoderInitialized = false;
if(_encoderInstPtr != NULL)
{
delete _encoderInstPtr;
_encoderInstPtr = NULL;
}
if(_encoderInstPtrRight != NULL)
{
delete _encoderInstPtrRight;
_encoderInstPtrRight = NULL;
}
_encoderInst16Ptr = NULL;
_encoderInst24Ptr = NULL;
_encoderInst32Ptr = NULL;
}
WebRtc_Word16
ACMG722_1::InternalCreateDecoder()
{
if(_decoderInstPtr == NULL)
{
return -1;
}
switch(_operationalRate)
{
case 16000:
{
WebRtcG7221_CreateDec16(&_decoderInst16Ptr);
break;
}
case 24000:
{
WebRtcG7221_CreateDec24(&_decoderInst24Ptr);
break;
}
case 32000:
{
WebRtcG7221_CreateDec32(&_decoderInst32Ptr);
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateDecoder: Wrong rate for G722_1.");
return -1;
break;
}
}
return 0;
}
void
ACMG722_1::DestructDecoderSafe()
{
_decoderExist = false;
_decoderInitialized = false;
if(_decoderInstPtr != NULL)
{
delete _decoderInstPtr;
_decoderInstPtr = NULL;
}
_decoderInst16Ptr = NULL;
_decoderInst24Ptr = NULL;
_decoderInst32Ptr = NULL;
}
void
ACMG722_1::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
delete ptrInst;
}
return;
}
WebRtc_Word16
ACMG722_1::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
switch(_operationalRate)
{
case 16000:
{
return netEq->RemoveCodec(kDecoderG722_1_16);
}
case 24000:
{
return netEq->RemoveCodec(kDecoderG722_1_24);
}
case 32000:
{
return netEq->RemoveCodec(kDecoderG722_1_32);
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"UnregisterFromNetEqSafe: Wrong rate for G722_1.");
return -1;
}
}
}
#endif
} // namespace webrtc

View File

@@ -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 ACM_G722_1_H
#define ACM_G722_1_H
#include "acm_generic_codec.h"
namespace webrtc
{
// forward declaration
struct G722_1_16_encinst_t_;
struct G722_1_16_decinst_t_;
struct G722_1_24_encinst_t_;
struct G722_1_24_decinst_t_;
struct G722_1_32_encinst_t_;
struct G722_1_32_decinst_t_;
struct G722_1_Inst_t_;
class ACMG722_1 : public ACMGenericCodec
{
public:
ACMG722_1(WebRtc_Word16 codecID);
~ACMG722_1();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
WebRtc_Word32 _operationalRate;
G722_1_Inst_t_* _encoderInstPtr;
G722_1_Inst_t_* _encoderInstPtrRight; //Used in stereo mode
G722_1_Inst_t_* _decoderInstPtr;
// Only one set of these pointer is valid at any instance
G722_1_16_encinst_t_* _encoderInst16Ptr;
G722_1_16_encinst_t_* _encoderInst16PtrR;
G722_1_24_encinst_t_* _encoderInst24Ptr;
G722_1_24_encinst_t_* _encoderInst24PtrR;
G722_1_32_encinst_t_* _encoderInst32Ptr;
G722_1_32_encinst_t_* _encoderInst32PtrR;
// Only one of these pointer is valid at any instance
G722_1_16_decinst_t_* _decoderInst16Ptr;
G722_1_24_decinst_t_* _decoderInst24Ptr;
G722_1_32_decinst_t_* _decoderInst32Ptr;
};
} // namespace webrtc
#endif // ACM_G722_1_H

View File

@@ -0,0 +1,685 @@
/*
* 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 "acm_codec_database.h"
#include "acm_common_defs.h"
#include "acm_g7221c.h"
#include "acm_neteq.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#include "trace.h"
#ifdef WEBRTC_CODEC_G722_1C
// NOTE! G.722.1C is not included in the open-source package. Modify this file or your
// codec API to match the function call and name of used G.722.1C API file.
// #include "g7221C_interface.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_G722_1C
ACMG722_1C::ACMG722_1C(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMG722_1C::~ACMG722_1C()
{
return;
}
WebRtc_Word16
ACMG722_1C::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMG722_1C::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMG722_1C::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMG722_1C::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMG722_1C::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMG722_1C::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG722_1C::InternalCreateEncoder()
{
return -1;
}
void
ACMG722_1C::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMG722_1C::InternalCreateDecoder()
{
return -1;
}
void
ACMG722_1C::DestructDecoderSafe()
{
return;
}
void
ACMG722_1C::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMG722_1C::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
// Remove when integrating a real G,722.1 wrapper
struct G722_1_Inst_t_;
extern WebRtc_Word16 WebRtcG7221C_CreateEnc24(G722_1C_24_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221C_CreateEnc32(G722_1C_32_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221C_CreateEnc48(G722_1C_48_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221C_CreateDec24(G722_1C_24_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221C_CreateDec32(G722_1C_32_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221C_CreateDec48(G722_1C_48_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221C_FreeEnc24(G722_1C_24_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221C_FreeEnc32(G722_1C_32_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221C_FreeEnc48(G722_1C_48_encinst_t_** encInst);
extern WebRtc_Word16 WebRtcG7221C_FreeDec24(G722_1C_24_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221C_FreeDec32(G722_1C_32_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221C_FreeDec48(G722_1C_48_decinst_t_** decInst);
extern WebRtc_Word16 WebRtcG7221C_EncoderInit24(G722_1C_24_encinst_t_* encInst);
extern WebRtc_Word16 WebRtcG7221C_EncoderInit32(G722_1C_32_encinst_t_* encInst);
extern WebRtc_Word16 WebRtcG7221C_EncoderInit48(G722_1C_48_encinst_t_* encInst);
extern WebRtc_Word16 WebRtcG7221C_DecoderInit24(G722_1C_24_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcG7221C_DecoderInit32(G722_1C_32_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcG7221C_DecoderInit48(G722_1C_48_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcG7221C_Encode24(G722_1C_24_encinst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221C_Encode32(G722_1C_32_encinst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221C_Encode48(G722_1C_48_encinst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221C_Decode24(G722_1C_24_decinst_t_* decInst,
WebRtc_Word16* bitstream,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221C_Decode32(G722_1C_32_decinst_t_* decInst,
WebRtc_Word16* bitstream,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221C_Decode48(G722_1C_48_decinst_t_* decInst,
WebRtc_Word16* bitstream,
WebRtc_Word16 len,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG7221C_DecodePlc24(G722_1C_24_decinst_t_* decInst,
WebRtc_Word16* output,
WebRtc_Word16 nrLostFrames);
extern WebRtc_Word16 WebRtcG7221C_DecodePlc32(G722_1C_32_decinst_t_* decInst,
WebRtc_Word16* output,
WebRtc_Word16 nrLostFrames);
extern WebRtc_Word16 WebRtcG7221C_DecodePlc48(G722_1C_48_decinst_t_* decInst,
WebRtc_Word16* output,
WebRtc_Word16 nrLostFrames);
ACMG722_1C::ACMG722_1C(
WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_encoderInstPtrRight(NULL),
_decoderInstPtr(NULL),
_encoderInst24Ptr(NULL),
_encoderInst24PtrR(NULL),
_encoderInst32Ptr(NULL),
_encoderInst32PtrR(NULL),
_encoderInst48Ptr(NULL),
_encoderInst48PtrR(NULL),
_decoderInst24Ptr(NULL),
_decoderInst32Ptr(NULL),
_decoderInst48Ptr(NULL)
{
_codecID = codecID;
if(_codecID == ACMCodecDB::g722_1C_24)
{
_operationalRate = 24000;
}
else if(_codecID == ACMCodecDB::g722_1C_32)
{
_operationalRate = 32000;
}
else if(_codecID == ACMCodecDB::g722_1C_48)
{
_operationalRate = 48000;
}
else
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Wrong codec id for G722_1c.");
_operationalRate = -1;
}
return;
}
ACMG722_1C::~ACMG722_1C()
{
if(_encoderInstPtr != NULL)
{
delete _encoderInstPtr;
_encoderInstPtr = NULL;
}
if(_encoderInstPtrRight != NULL)
{
delete _encoderInstPtrRight;
_encoderInstPtrRight = NULL;
}
if(_decoderInstPtr != NULL)
{
delete _decoderInstPtr;
_decoderInstPtr = NULL;
}
switch(_operationalRate)
{
case 24000:
{
_encoderInst24Ptr = NULL;
_encoderInst24PtrR = NULL;
_decoderInst24Ptr = NULL;
break;
}
case 32000:
{
_encoderInst32Ptr = NULL;
_encoderInst32PtrR = NULL;
_decoderInst32Ptr = NULL;
break;
}
case 48000:
{
_encoderInst48Ptr = NULL;
_encoderInst48PtrR = NULL;
_decoderInst48Ptr = NULL;
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Wrong rate for G722_1c.");
break;
}
}
return;
}
WebRtc_Word16
ACMG722_1C::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
WebRtc_Word16 leftChannel[640];
WebRtc_Word16 rightChannel[640];
WebRtc_Word16 lenInBytes;
WebRtc_Word16 outB[240];
// If stereo, split input signal in left and right channel before encoding
if(_noChannels == 2)
{
for (int i=0, j=0; i<_frameLenSmpl*2; i+=2, j++) {
leftChannel[j] = _inAudio[_inAudioIxRead+i];
rightChannel[j] = _inAudio[_inAudioIxRead+i+1];
}
} else {
memcpy(leftChannel, &_inAudio[_inAudioIxRead], 640);
}
switch(_operationalRate)
{
case 24000:
{
lenInBytes = WebRtcG7221C_Encode24(_encoderInst24Ptr,
leftChannel, 640, &outB[0]);
if (_noChannels == 2)
{
lenInBytes += WebRtcG7221C_Encode24(_encoderInst24PtrR,
rightChannel, 640, &outB[lenInBytes/2]);
}
break;
}
case 32000:
{
lenInBytes = WebRtcG7221C_Encode32(_encoderInst32Ptr,
leftChannel, 640, &outB[0]);
if (_noChannels == 2)
{
lenInBytes += WebRtcG7221C_Encode32(_encoderInst32PtrR,
rightChannel, 640, &outB[lenInBytes/2]);
}
break;
}
case 48000:
{
lenInBytes = WebRtcG7221C_Encode48(_encoderInst48Ptr,
leftChannel, 640, &outB[0]);
if (_noChannels == 2)
{
lenInBytes += WebRtcG7221C_Encode48(_encoderInst48PtrR,
rightChannel, 640, &outB[lenInBytes/2]);
}
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalEncode: Wrong rate for G722_1c.");
return -1;
break;
}
}
memcpy(bitStream, outB, lenInBytes);
*bitStreamLenByte = lenInBytes;
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += 640*_noChannels;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMG722_1C::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMG722_1C::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
WebRtc_Word16 ret;
switch(_operationalRate)
{
case 24000:
{
ret = WebRtcG7221C_EncoderInit24(_encoderInst24PtrR);
if (ret < 0) {
return ret;
}
return WebRtcG7221C_EncoderInit24(_encoderInst24Ptr);
break;
}
case 32000:
{
ret = WebRtcG7221C_EncoderInit32(_encoderInst32PtrR);
if (ret < 0) {
return ret;
}
return WebRtcG7221C_EncoderInit32(_encoderInst32Ptr);
break;
}
case 48000:
{
ret = WebRtcG7221C_EncoderInit48(_encoderInst48PtrR);
if (ret < 0) {
return ret;
}
return WebRtcG7221C_EncoderInit48(_encoderInst48Ptr);
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitEncode: Wrong rate for G722_1c.");
return -1;
break;
}
}
}
WebRtc_Word16
ACMG722_1C::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
switch(_operationalRate)
{
case 24000:
{
return WebRtcG7221C_DecoderInit24(_decoderInst24Ptr);
break;
}
case 32000:
{
return WebRtcG7221C_DecoderInit32(_decoderInst32Ptr);
break;
}
case 48000:
{
return WebRtcG7221C_DecoderInit48(_decoderInst48Ptr);
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitDecoder: Wrong rate for G722_1c.");
return -1;
break;
}
}
}
WebRtc_Word32
ACMG722_1C::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"CodeDef: decoder not initialized for G722_1c");
return -1;
}
// NetEq has an array of pointers to WebRtcNetEQ_CodecDef.
// get an entry of that array (neteq wrapper will allocate memory)
// by calling "netEq->CodecDef", where "NETEQ_CODEC_G722_1_XX" would
// be the index of the entry.
// Fill up the given structure by calling
// "SET_CODEC_PAR" & "SET_G722_1_XX_FUNCTION."
// Then return the structure back to NetEQ to add the codec to it's
// database.
switch(_operationalRate)
{
case 24000:
{
SET_CODEC_PAR((codecDef), kDecoderG722_1C_24, codecInst.pltype,
_decoderInst24Ptr, 32000);
SET_G722_1C_24_FUNCTIONS((codecDef));
break;
}
case 32000:
{
SET_CODEC_PAR((codecDef), kDecoderG722_1C_32, codecInst.pltype,
_decoderInst32Ptr, 32000);
SET_G722_1C_32_FUNCTIONS((codecDef));
break;
}
case 48000:
{
SET_CODEC_PAR((codecDef), kDecoderG722_1C_32, codecInst.pltype,
_decoderInst48Ptr, 32000);
SET_G722_1C_48_FUNCTIONS((codecDef));
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"CodeDef: Wrong rate for G722_1c.");
return -1;
break;
}
}
return 0;
}
ACMGenericCodec*
ACMG722_1C::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG722_1C::InternalCreateEncoder()
{
if((_encoderInstPtr == NULL) || (_encoderInstPtrRight == NULL))
{
return -1;
}
switch(_operationalRate)
{
case 24000:
{
WebRtcG7221C_CreateEnc24(&_encoderInst24Ptr);
WebRtcG7221C_CreateEnc24(&_encoderInst24PtrR);
break;
}
case 32000:
{
WebRtcG7221C_CreateEnc32(&_encoderInst32Ptr);
WebRtcG7221C_CreateEnc32(&_encoderInst32PtrR);
break;
}
case 48000:
{
WebRtcG7221C_CreateEnc48(&_encoderInst48Ptr);
WebRtcG7221C_CreateEnc48(&_encoderInst48PtrR);
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateEncoder: Wrong rate for G722_1c.");
return -1;
break;
}
}
return 0;
}
void
ACMG722_1C::DestructEncoderSafe()
{
_encoderExist = false;
_encoderInitialized = false;
if(_encoderInstPtr != NULL)
{
delete _encoderInstPtr;
_encoderInstPtr = NULL;
}
if(_encoderInstPtrRight != NULL)
{
delete _encoderInstPtrRight;
_encoderInstPtrRight = NULL;
}
_encoderInst24Ptr = NULL;
_encoderInst32Ptr = NULL;
_encoderInst48Ptr = NULL;
}
WebRtc_Word16
ACMG722_1C::InternalCreateDecoder()
{
if(_decoderInstPtr == NULL)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateEncoder: cannot create decoder");
return -1;
}
switch(_operationalRate)
{
case 24000:
{
WebRtcG7221C_CreateDec24(&_decoderInst24Ptr);
break;
}
case 32000:
{
WebRtcG7221C_CreateDec32(&_decoderInst32Ptr);
break;
}
case 48000:
{
WebRtcG7221C_CreateDec48(&_decoderInst48Ptr);
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateEncoder: Wrong rate for G722_1c.");
return -1;
break;
}
}
return 0;
}
void
ACMG722_1C::DestructDecoderSafe()
{
_decoderExist = false;
_decoderInitialized = false;
if(_decoderInstPtr != NULL)
{
delete _decoderInstPtr;
_decoderInstPtr = NULL;
}
_decoderInst24Ptr = NULL;
_decoderInst32Ptr = NULL;
_decoderInst48Ptr = NULL;
}
void
ACMG722_1C::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
delete ptrInst;
}
return;
}
WebRtc_Word16
ACMG722_1C::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
switch(_operationalRate)
{
case 24000:
{
return netEq->RemoveCodec(kDecoderG722_1C_24);
}
case 32000:
{
return netEq->RemoveCodec(kDecoderG722_1C_32);
}
case 48000:
{
return netEq->RemoveCodec(kDecoderG722_1C_48);
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Could not remove codec from NetEQ for G722_1c. \
Sampling frequency doesn't match");
return -1;
}
}
}
#endif
} // namespace webrtc

View File

@@ -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 ACM_G722_1C_H
#define ACM_G722_1C_H
#include "acm_generic_codec.h"
namespace webrtc
{
// forward declaration
struct G722_1C_24_encinst_t_;
struct G722_1C_24_decinst_t_;
struct G722_1C_32_encinst_t_;
struct G722_1C_32_decinst_t_;
struct G722_1C_48_encinst_t_;
struct G722_1C_48_decinst_t_;
struct G722_1_Inst_t_;
class ACMG722_1C : public ACMGenericCodec
{
public:
ACMG722_1C(WebRtc_Word16 codecID);
~ACMG722_1C();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
WebRtc_Word32 _operationalRate;
G722_1_Inst_t_* _encoderInstPtr;
G722_1_Inst_t_* _encoderInstPtrRight; //Used in stereo mode
G722_1_Inst_t_* _decoderInstPtr;
// Only one set of these pointer is valid at any instance
G722_1C_24_encinst_t_* _encoderInst24Ptr;
G722_1C_24_encinst_t_* _encoderInst24PtrR;
G722_1C_32_encinst_t_* _encoderInst32Ptr;
G722_1C_32_encinst_t_* _encoderInst32PtrR;
G722_1C_48_encinst_t_* _encoderInst48Ptr;
G722_1C_48_encinst_t_* _encoderInst48PtrR;
// Only one of these pointer is valid at any instance
G722_1C_24_decinst_t_* _decoderInst24Ptr;
G722_1C_32_decinst_t_* _decoderInst32Ptr;
G722_1C_48_decinst_t_* _decoderInst48Ptr;
};
} // namespace webrtc;
#endif // ACM_G722_1C_H

View File

@@ -0,0 +1,544 @@
/*
* 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 "acm_common_defs.h"
#include "acm_g729.h"
#include "acm_neteq.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_G729
// NOTE! G.729 is not included in the open-source package. Modify this file or your codec
// API to match the function call and name of used G.729 API file.
// #include "g729_interface.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_G729
ACMG729::ACMG729(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMG729::~ACMG729()
{
return;
}
WebRtc_Word16
ACMG729::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMG729::EnableDTX()
{
return -1;
}
WebRtc_Word16
ACMG729::DisableDTX()
{
return -1;
}
WebRtc_Word32
ACMG729::ReplaceInternalDTXSafe(
const bool /*replaceInternalDTX*/)
{
return -1;
}
WebRtc_Word32
ACMG729::IsInternalDTXReplacedSafe(
bool* /* internalDTXReplaced */)
{
return -1;
}
WebRtc_Word16
ACMG729::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMG729::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMG729::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMG729::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMG729::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG729::InternalCreateEncoder()
{
return -1;
}
void
ACMG729::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMG729::InternalCreateDecoder()
{
return -1;
}
void
ACMG729::DestructDecoderSafe()
{
return;
}
void
ACMG729::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMG729::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
// Remove when integrating a real GSM FR wrapper
extern WebRtc_Word16 WebRtcG729_CreateEnc(G729_encinst_t_** inst);
extern WebRtc_Word16 WebRtcG729_CreateDec(G729_decinst_t_** inst);
extern WebRtc_Word16 WebRtcG729_FreeEnc(G729_encinst_t_* inst);
extern WebRtc_Word16 WebRtcG729_FreeDec(G729_decinst_t_* inst);
extern WebRtc_Word16 WebRtcG729_Encode(G729_encinst_t_* encInst, WebRtc_Word16* input,
WebRtc_Word16 len, WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcG729_EncoderInit(G729_encinst_t_* encInst, WebRtc_Word16 mode);
extern WebRtc_Word16 WebRtcG729_Decode(G729_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcG729_DecodeBwe(G729_decinst_t_* decInst, WebRtc_Word16* input);
extern WebRtc_Word16 WebRtcG729_DecodePlc(G729_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcG729_DecoderInit(G729_decinst_t_* decInst);
ACMG729::ACMG729(
WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_decoderInstPtr(NULL)
{
_codecID = codecID;
_hasInternalDTX = true;
return;
}
ACMG729::~ACMG729()
{
if(_encoderInstPtr != NULL)
{
// Delete encoder memory
WebRtcG729_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
if(_decoderInstPtr != NULL)
{
// Delete decoder memory
WebRtcG729_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
return;
}
WebRtc_Word16
ACMG729::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
// Initialize before entering the loop
WebRtc_Word16 noEncodedSamples = 0;
WebRtc_Word16 tmpLenByte = 0;
WebRtc_Word16 vadDecision = 0;
*bitStreamLenByte = 0;
while(noEncodedSamples < _frameLenSmpl)
{
// Call G.729 encoder with pointer to encoder memory, input
// audio, number of samples and bitsream
tmpLenByte = WebRtcG729_Encode(_encoderInstPtr,
&_inAudio[_inAudioIxRead], 80,
(WebRtc_Word16*)(&(bitStream[*bitStreamLenByte])));
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += 80;
// sanity check
if(tmpLenByte < 0)
{
// error has happened
*bitStreamLenByte = 0;
return -1;
}
// increment number of written bytes
*bitStreamLenByte += tmpLenByte;
switch(tmpLenByte)
{
case 0:
{
if(0 == noEncodedSamples)
{
// this is the first 10 ms in this packet and there is
// no data generated, perhaps DTX is enabled and the
// codec is not generating any bit-stream for this 10 ms.
// we do not continue encoding this frame.
return 0;
}
break;
}
case 2:
{
// check if G.729 internal DTX is enabled
if(_hasInternalDTX && _dtxEnabled)
{
vadDecision = 0;
for(WebRtc_Word16 n = 0; n < MAX_FRAME_SIZE_10MSEC; n++)
{
_vadLabel[n] = vadDecision;
}
}
// we got a SID and have to send out this packet no matter
// how much audio we have encoded
return *bitStreamLenByte;
}
case 10:
{
vadDecision = 1;
// this is a valid length just continue encoding
break;
}
default:
{
return -1;
}
}
// update number of encoded samples
noEncodedSamples += 80;
}
// update VAD decision vector
if(_hasInternalDTX && !vadDecision && _dtxEnabled)
{
for(WebRtc_Word16 n = 0; n < MAX_FRAME_SIZE_10MSEC; n++)
{
_vadLabel[n] = vadDecision;
}
}
// done encoding, return number of encoded bytes
return *bitStreamLenByte;
}
WebRtc_Word16
ACMG729::EnableDTX()
{
if(_dtxEnabled)
{
// DTX already enabled, do nothing
return 0;
}
else if(_encoderExist)
{
// Re-init the G.729 encoder to turn on DTX
if(WebRtcG729_EncoderInit(_encoderInstPtr, 1) < 0)
{
return -1;
}
_dtxEnabled = true;
return 0;
}
else
{
return -1;
}
}
WebRtc_Word16
ACMG729::DisableDTX()
{
if(!_dtxEnabled)
{
// DTX already dissabled, do nothing
return 0;
}
else if(_encoderExist)
{
// Re-init the G.729 decoder to turn off DTX
if(WebRtcG729_EncoderInit(_encoderInstPtr, 0) < 0)
{
return -1;
}
_dtxEnabled = false;
return 0;
}
else
{
// encoder doesn't exists, therefore disabling is harmless
return 0;
}
}
WebRtc_Word32
ACMG729::ReplaceInternalDTXSafe(
const bool replaceInternalDTX)
{
// This function is used to dissable the G.729 built in DTX and use an
// external instead.
if(replaceInternalDTX == _hasInternalDTX)
{
// Make sure we keep the DTX/VAD setting if possible
bool oldEnableDTX = _dtxEnabled;
bool oldEnableVAD = _vadEnabled;
ACMVADMode oldMode = _vadMode;
if (replaceInternalDTX)
{
// Disable internal DTX before enabling external DTX
DisableDTX();
}
else
{
// Disable external DTX before enabling internal
ACMGenericCodec::DisableDTX();
}
_hasInternalDTX = !replaceInternalDTX;
WebRtc_Word16 status = SetVADSafe(oldEnableDTX, oldEnableVAD, oldMode);
// Check if VAD status has changed from inactive to active, or if error was
// reported
if (status == 1) {
_vadEnabled = true;
return status;
} else if (status < 0) {
_hasInternalDTX = replaceInternalDTX;
return -1;
}
}
return 0;
}
WebRtc_Word32
ACMG729::IsInternalDTXReplacedSafe(
bool* internalDTXReplaced)
{
// Get status of wether DTX is replaced or not
*internalDTXReplaced = !_hasInternalDTX;
return 0;
}
WebRtc_Word16
ACMG729::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
// This function is not used. G.729 decoder is called from inside NetEQ
return 0;
}
WebRtc_Word16
ACMG729::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
// Init G.729 encoder
return WebRtcG729_EncoderInit(_encoderInstPtr,
((codecParams->enableDTX)? 1:0));
}
WebRtc_Word16
ACMG729::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
// Init G.729 decoder
return WebRtcG729_DecoderInit(_decoderInstPtr);
}
WebRtc_Word32
ACMG729::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
// Todo:
// log error
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_G729_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderG729, codecInst.pltype,
_decoderInstPtr, 8000);
SET_G729_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMG729::CreateInstance(void)
{
// Function not used
return NULL;
}
WebRtc_Word16
ACMG729::InternalCreateEncoder()
{
// Create encoder memory
return WebRtcG729_CreateEnc(&_encoderInstPtr);
}
void
ACMG729::DestructEncoderSafe()
{
// Free encoder memory
_encoderExist = false;
_encoderInitialized = false;
if(_encoderInstPtr != NULL)
{
WebRtcG729_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
}
WebRtc_Word16
ACMG729::InternalCreateDecoder()
{
// Create decoder memory
return WebRtcG729_CreateDec(&_decoderInstPtr);
}
void
ACMG729::DestructDecoderSafe()
{
// Free decoder memory
_decoderExist = false;
_decoderInitialized = false;
if(_decoderInstPtr != NULL)
{
WebRtcG729_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
}
void
ACMG729::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
WebRtcG729_FreeEnc((G729_encinst_t_*)ptrInst);
}
return;
}
WebRtc_Word16
ACMG729::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
// Remove codec from the NetEQ database
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderG729);
}
#endif
} // namespace webrtc

View File

@@ -0,0 +1,86 @@
/*
* 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_G729_H
#define ACM_G729_H
#include "acm_generic_codec.h"
// forward declaration
struct G729_encinst_t_;
struct G729_decinst_t_;
namespace webrtc
{
class ACMG729 : public ACMGenericCodec
{
public:
ACMG729(WebRtc_Word16 codecID);
~ACMG729();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 EnableDTX();
WebRtc_Word16 DisableDTX();
WebRtc_Word32 ReplaceInternalDTXSafe(
const bool replaceInternalDTX);
WebRtc_Word32 IsInternalDTXReplacedSafe(
bool* internalDTXReplaced);
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
G729_encinst_t_* _encoderInstPtr;
G729_decinst_t_* _decoderInstPtr;
};
} // namespace webrtc
#endif //ACM_G729_H

View File

@@ -0,0 +1,504 @@
/*
* 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 "acm_common_defs.h"
#include "acm_g7291.h"
#include "acm_neteq.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_G729_1
// NOTE! G.729.1 is not included in the open-source package. Modify this file or your codec
// API to match the function call and name of used G.729.1 API file.
// #include "g7291_interface.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_G729_1
ACMG729_1::ACMG729_1(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMG729_1::~ACMG729_1()
{
return;
}
WebRtc_Word16
ACMG729_1::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMG729_1::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMG729_1::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMG729_1::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMG729_1::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMG729_1::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG729_1::InternalCreateEncoder()
{
return -1;
}
void
ACMG729_1::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMG729_1::InternalCreateDecoder()
{
return -1;
}
void
ACMG729_1::DestructDecoderSafe()
{
return;
}
void
ACMG729_1::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMG729_1::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
WebRtc_Word16
ACMG729_1::SetBitRateSafe(
const WebRtc_Word32 /*rate*/ )
{
return -1;
}
#else //===================== Actual Implementation =======================
// Remove when integrating a real GSM AMR wrapper
struct G729_1_inst_t_;
extern WebRtc_Word16 WebRtcG7291_Create(G729_1_inst_t_** inst);
extern WebRtc_Word16 WebRtcG7291_Free(G729_1_inst_t_* inst);
extern WebRtc_Word16 WebRtcG7291_Encode(G729_1_inst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16* output,
WebRtc_Word16 myRate,
WebRtc_Word16 nrFrames);
extern WebRtc_Word16 WebRtcG7291_EncoderInit(G729_1_inst_t_* encInst,
WebRtc_Word16 myRate,
WebRtc_Word16 flag8kHz,
WebRtc_Word16 flagG729mode);
extern WebRtc_Word16 WebRtcG7291_Decode(G729_1_inst_t_* decInst);
extern WebRtc_Word16 WebRtcG7291_DecodeBwe(G729_1_inst_t_* decInst, WebRtc_Word16* input);
extern WebRtc_Word16 WebRtcG7291_DecodePlc(G729_1_inst_t_* decInst);
extern WebRtc_Word16 WebRtcG7291_DecoderInit(G729_1_inst_t_* decInst);
ACMG729_1::ACMG729_1(
WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_decoderInstPtr(NULL)
{
_codecID = codecID;
// Our current G729.1 does not support Annex C
// which is DTX.
_hasInternalDTX = false;
// Default rate
_myRate = 32000;
_flag8kHz = 0;
_flagG729mode = 0;
return;
}
ACMG729_1::~ACMG729_1()
{
if(_encoderInstPtr != NULL)
{
WebRtcG7291_Free(_encoderInstPtr);
_encoderInstPtr = NULL;
}
if(_decoderInstPtr != NULL)
{
WebRtcG7291_Free(_decoderInstPtr);
_decoderInstPtr = NULL;
}
return;
}
WebRtc_Word16
ACMG729_1::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
// Initialize before entering the loop
WebRtc_Word16 noEncodedSamples = 0;
WebRtc_Word16 tmpLenByte = 0;
*bitStreamLenByte = 0;
WebRtc_Word16 byteLengthFrame = 0;
// Derive number of 20ms frames per encoded packet.
// [1,2,3] <=> [20,40,60]ms <=> [320,640,960] samples
WebRtc_Word16 n20msFrames = (_frameLenSmpl / 320);
// Byte length for the frame. +1 is for rate information.
byteLengthFrame = _myRate/(8*50) * n20msFrames + (1 - _flagG729mode);
// The following might be revised if we have G729.1 Annex C (support for DTX);
do
{
*bitStreamLenByte = WebRtcG7291_Encode(_encoderInstPtr, &_inAudio[_inAudioIxRead],
(WebRtc_Word16*)bitStream, _myRate, n20msFrames);
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += 160;
// sanity check
if(*bitStreamLenByte < 0)
{
// error has happened
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalEncode: Encode error for G729_1");
*bitStreamLenByte = 0;
return -1;
}
noEncodedSamples += 160;
} while(*bitStreamLenByte == 0);
// This criteria will change if we have Annex C.
if(*bitStreamLenByte != byteLengthFrame)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalEncode: Encode error for G729_1");
*bitStreamLenByte = 0;
return -1;
}
if(noEncodedSamples != _frameLenSmpl)
{
*bitStreamLenByte = 0;
return -1;
}
return *bitStreamLenByte;
}
WebRtc_Word16
ACMG729_1::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMG729_1::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
//set the bit rate and initialize
_myRate = codecParams->codecInstant.rate;
return SetBitRateSafe( (WebRtc_UWord32)_myRate);
}
WebRtc_Word16
ACMG729_1::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
if (WebRtcG7291_DecoderInit(_decoderInstPtr) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitDecoder: init decoder failed for G729_1");
return -1;
}
return 0;
}
WebRtc_Word32
ACMG729_1::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"CodeDef: Decoder uninitialized for G729_1");
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_G729_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderG729_1, codecInst.pltype,
_decoderInstPtr, 16000);
SET_G729_1_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMG729_1::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG729_1::InternalCreateEncoder()
{
if (WebRtcG7291_Create(&_encoderInstPtr) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateEncoder: create encoder failed for G729_1");
return -1;
}
return 0;
}
void
ACMG729_1::DestructEncoderSafe()
{
_encoderExist = false;
_encoderInitialized = false;
if(_encoderInstPtr != NULL)
{
WebRtcG7291_Free(_encoderInstPtr);
_encoderInstPtr = NULL;
}
}
WebRtc_Word16
ACMG729_1::InternalCreateDecoder()
{
if (WebRtcG7291_Create(&_decoderInstPtr) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateDecoder: create decoder failed for G729_1");
return -1;
}
return 0;
}
void
ACMG729_1::DestructDecoderSafe()
{
_decoderExist = false;
_decoderInitialized = false;
if(_decoderInstPtr != NULL)
{
WebRtcG7291_Free(_decoderInstPtr);
_decoderInstPtr = NULL;
}
}
void
ACMG729_1::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
//WebRtcG7291_Free((G729_1_inst_t*)ptrInst);
}
return;
}
WebRtc_Word16
ACMG729_1::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec: given payload-type does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderG729_1);
}
WebRtc_Word16
ACMG729_1::SetBitRateSafe(
const WebRtc_Word32 rate)
{
//allowed rates: { 8000, 12000, 14000, 16000, 18000, 20000,
// 22000, 24000, 26000, 28000, 30000, 32000};
switch(rate)
{
case 8000:
{
_myRate = 8000;
break;
}
case 12000:
{
_myRate = 12000;
break;
}
case 14000:
{
_myRate = 14000;
break;
}
case 16000:
{
_myRate = 16000;
break;
}
case 18000:
{
_myRate = 18000;
break;
}
case 20000:
{
_myRate = 20000;
break;
}
case 22000:
{
_myRate = 22000;
break;
}
case 24000:
{
_myRate = 24000;
break;
}
case 26000:
{
_myRate = 26000;
break;
}
case 28000:
{
_myRate = 28000;
break;
}
case 30000:
{
_myRate = 30000;
break;
}
case 32000:
{
_myRate = 32000;
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"SetBitRateSafe: Invalid rate G729_1");
return -1;
break;
}
}
// Re-init with new rate
if (WebRtcG7291_EncoderInit(_encoderInstPtr, _myRate, _flag8kHz, _flagG729mode) >= 0)
{
_encoderParams.codecInstant.rate = _myRate;
return 0;
}
else
{
return -1;
}
}
#endif
} // namespace webrtc

View File

@@ -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 ACM_G729_1_H
#define ACM_G729_1_H
#include "acm_generic_codec.h"
namespace webrtc
{
// forward declaration
struct G729_1_inst_t_;
struct G729_1_inst_t_;
class ACMG729_1: public ACMGenericCodec
{
public:
ACMG729_1(WebRtc_Word16 codecID);
~ACMG729_1();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
//WebRtc_Word16 EnableDTX();
//
//WebRtc_Word16 DisableDTX();
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
WebRtc_Word16 SetBitRateSafe(
const WebRtc_Word32 rate);
G729_1_inst_t_* _encoderInstPtr;
G729_1_inst_t_* _decoderInstPtr;
WebRtc_UWord16 _myRate;
WebRtc_Word16 _flag8kHz;
WebRtc_Word16 _flagG729mode;
};
} // namespace webrtc
#endif // ACM_G729_1_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,413 @@
/*
* 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 "acm_common_defs.h"
#include "acm_gsmfr.h"
#include "acm_neteq.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_GSMFR
// NOTE! GSM-FR is not included in the open-source package. Modify this file or your codec
// API to match the function call and name of used GSM-FR API file.
// #include "gsmfr_interface.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_GSMFR
ACMGSMFR::ACMGSMFR(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMGSMFR::~ACMGSMFR()
{
return;
}
WebRtc_Word16
ACMGSMFR::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMGSMFR::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMGSMFR::EnableDTX()
{
return -1;
}
WebRtc_Word16
ACMGSMFR::DisableDTX()
{
return -1;
}
WebRtc_Word16
ACMGSMFR::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMGSMFR::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMGSMFR::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMGSMFR::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMGSMFR::InternalCreateEncoder()
{
return -1;
}
void
ACMGSMFR::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMGSMFR::InternalCreateDecoder()
{
return -1;
}
void
ACMGSMFR::DestructDecoderSafe()
{
return;
}
void
ACMGSMFR::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMGSMFR::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
// Remove when integrating a real GSM FR wrapper
extern WebRtc_Word16 WebRtcGSMFR_CreateEnc(GSMFR_encinst_t_** inst);
extern WebRtc_Word16 WebRtcGSMFR_CreateDec(GSMFR_decinst_t_** inst);
extern WebRtc_Word16 WebRtcGSMFR_FreeEnc(GSMFR_encinst_t_* inst);
extern WebRtc_Word16 WebRtcGSMFR_FreeDec(GSMFR_decinst_t_* inst);
extern WebRtc_Word16 WebRtcGSMFR_Encode(GSMFR_encinst_t_* encInst, WebRtc_Word16* input,
WebRtc_Word16 len, WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcGSMFR_EncoderInit(GSMFR_encinst_t_* encInst, WebRtc_Word16 mode);
extern WebRtc_Word16 WebRtcGSMFR_Decode(GSMFR_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcGSMFR_DecodeBwe(GSMFR_decinst_t_* decInst, WebRtc_Word16* input);
extern WebRtc_Word16 WebRtcGSMFR_DecodePlc(GSMFR_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcGSMFR_DecoderInit(GSMFR_decinst_t_* decInst);
ACMGSMFR::ACMGSMFR(
WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_decoderInstPtr(NULL)
{
_codecID = codecID;
_hasInternalDTX = true;
return;
}
ACMGSMFR::~ACMGSMFR()
{
if(_encoderInstPtr != NULL)
{
WebRtcGSMFR_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
if(_decoderInstPtr != NULL)
{
WebRtcGSMFR_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
return;
}
WebRtc_Word16
ACMGSMFR::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
*bitStreamLenByte = WebRtcGSMFR_Encode(_encoderInstPtr,
&_inAudio[_inAudioIxRead], _frameLenSmpl, (WebRtc_Word16*)bitStream);
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _frameLenSmpl;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMGSMFR::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMGSMFR::EnableDTX()
{
if(_dtxEnabled)
{
return 0;
}
else if(_encoderExist)
{
if(WebRtcGSMFR_EncoderInit(_encoderInstPtr, 1) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"EnableDTX: cannot init encoder for GSMFR");
return -1;
}
_dtxEnabled = true;
return 0;
}
else
{
return -1;
}
}
WebRtc_Word16
ACMGSMFR::DisableDTX()
{
if(!_dtxEnabled)
{
return 0;
}
else if(_encoderExist)
{
if(WebRtcGSMFR_EncoderInit(_encoderInstPtr, 0) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"DisableDTX: cannot init encoder for GSMFR");
return -1;
}
_dtxEnabled = false;
return 0;
}
else
{
// encoder doesn't exists, therefore disabling is harmless
return 0;
}
}
WebRtc_Word16
ACMGSMFR::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
if (WebRtcGSMFR_EncoderInit(_encoderInstPtr, ((codecParams->enableDTX)? 1:0)) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitEncoder: cannot init encoder for GSMFR");
}
return 0;
}
WebRtc_Word16
ACMGSMFR::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
if (WebRtcGSMFR_DecoderInit(_decoderInstPtr) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitDecoder: cannot init decoder for GSMFR");
return -1;
}
return 0;
}
WebRtc_Word32
ACMGSMFR::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"CodecDef: decoder is not initialized for GSMFR");
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_GSMFR_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderGSMFR, codecInst.pltype,
_decoderInstPtr, 8000);
SET_GSMFR_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMGSMFR::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMGSMFR::InternalCreateEncoder()
{
if (WebRtcGSMFR_CreateEnc(&_encoderInstPtr) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateEncoder: cannot create instance for GSMFR encoder");
return -1;
}
return 0;
}
void
ACMGSMFR::DestructEncoderSafe()
{
if(_encoderInstPtr != NULL)
{
WebRtcGSMFR_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
_encoderExist = false;
_encoderInitialized = false;
}
WebRtc_Word16
ACMGSMFR::InternalCreateDecoder()
{
if (WebRtcGSMFR_CreateDec(&_decoderInstPtr) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateDecoder: cannot create instance for GSMFR decoder");
return -1;
}
return 0;
}
void
ACMGSMFR::DestructDecoderSafe()
{
if(_decoderInstPtr != NULL)
{
WebRtcGSMFR_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
_decoderExist = false;
_decoderInitialized = false;
}
void
ACMGSMFR::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
WebRtcGSMFR_FreeEnc((GSMFR_encinst_t_*)ptrInst);
}
return;
}
WebRtc_Word16
ACMGSMFR::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec: payload-type does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderGSMFR);
}
#endif
} // namespace webrtc

View File

@@ -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 ACM_GSMFR_H
#define ACM_GSMFR_H
#include "acm_generic_codec.h"
namespace webrtc
{
// forward declaration
struct GSMFR_encinst_t_;
struct GSMFR_decinst_t_;
class ACMGSMFR : public ACMGenericCodec
{
public:
ACMGSMFR(WebRtc_Word16 codecID);
~ACMGSMFR();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 EnableDTX();
WebRtc_Word16 DisableDTX();
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
GSMFR_encinst_t_* _encoderInstPtr;
GSMFR_decinst_t_* _decoderInstPtr;
};
} // namespace webrtc
#endif // ACM_GSMFR_H

View File

@@ -0,0 +1,390 @@
/*
* 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 "acm_common_defs.h"
#include "acm_ilbc.h"
#include "acm_neteq.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_ILBC
#include "ilbc.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_ILBC
ACMILBC::ACMILBC(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMILBC::~ACMILBC()
{
return;
}
WebRtc_Word16
ACMILBC::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMILBC::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMILBC::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMILBC::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMILBC::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMILBC::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMILBC::InternalCreateEncoder()
{
return -1;
}
void
ACMILBC::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMILBC::InternalCreateDecoder()
{
return -1;
}
void
ACMILBC::DestructDecoderSafe()
{
return;
}
void
ACMILBC::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMILBC::SetBitRateSafe(const WebRtc_Word32 /* rate */)
{
return -1;
}
WebRtc_Word16
ACMILBC::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
ACMILBC::ACMILBC(
WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_decoderInstPtr(NULL)
{
_codecID = codecID;
return;
}
ACMILBC::~ACMILBC()
{
if(_encoderInstPtr != NULL)
{
WebRtcIlbcfix_EncoderFree(_encoderInstPtr);
_encoderInstPtr = NULL;
}
if(_decoderInstPtr != NULL)
{
WebRtcIlbcfix_DecoderFree(_decoderInstPtr);
_decoderInstPtr = NULL;
}
return;
}
WebRtc_Word16
ACMILBC::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
*bitStreamLenByte = WebRtcIlbcfix_Encode(_encoderInstPtr,
&_inAudio[_inAudioIxRead], _frameLenSmpl, (WebRtc_Word16*)bitStream);
if (*bitStreamLenByte < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalEncode: error in encode for ILBC");
return -1;
}
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _frameLenSmpl;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMILBC::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMILBC::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
// initialize with a correct processing block length
if((160 == (codecParams->codecInstant).pacsize) ||
(320 == (codecParams->codecInstant).pacsize))
{
// processing block of 20ms
return WebRtcIlbcfix_EncoderInit(_encoderInstPtr, 20);
}
else if((240 == (codecParams->codecInstant).pacsize) ||
(480 == (codecParams->codecInstant).pacsize))
{
// processing block of 30ms
return WebRtcIlbcfix_EncoderInit(_encoderInstPtr, 30);
}
else
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitEncoder: invalid processing block");
return -1;
}
}
WebRtc_Word16
ACMILBC::InternalInitDecoder(
WebRtcACMCodecParams* codecParams)
{
// initialize with a correct processing block length
if((160 == (codecParams->codecInstant).pacsize) ||
(320 == (codecParams->codecInstant).pacsize))
{
// processing block of 20ms
return WebRtcIlbcfix_DecoderInit(_decoderInstPtr, 20);
}
else if((240 == (codecParams->codecInstant).pacsize) ||
(480 == (codecParams->codecInstant).pacsize))
{
// processing block of 30ms
return WebRtcIlbcfix_DecoderInit(_decoderInstPtr, 30);
}
else
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitDecoder: invalid processing block");
return -1;
}
}
WebRtc_Word32
ACMILBC::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"CodeDef: decoder not initialized for ILBC");
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_ILBC_FUNCTION."
// Then return the structure back to NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderILBC, codecInst.pltype,
_decoderInstPtr, 8000);
SET_ILBC_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMILBC::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMILBC::InternalCreateEncoder()
{
if (WebRtcIlbcfix_EncoderCreate(&_encoderInstPtr) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateEncoder: cannot create instance for ILBC encoder");
return -1;
}
return 0;
}
void
ACMILBC::DestructEncoderSafe()
{
_encoderInitialized = false;
_encoderExist = false;
if(_encoderInstPtr != NULL)
{
WebRtcIlbcfix_EncoderFree(_encoderInstPtr);
_encoderInstPtr = NULL;
}
}
WebRtc_Word16
ACMILBC::InternalCreateDecoder()
{
if (WebRtcIlbcfix_DecoderCreate(&_decoderInstPtr) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateDecoder: cannot create instance for ILBC decoder");
return -1;
}
return 0;
}
void
ACMILBC::DestructDecoderSafe()
{
_decoderInitialized = false;
_decoderExist = false;
if(_decoderInstPtr != NULL)
{
WebRtcIlbcfix_DecoderFree(_decoderInstPtr);
_decoderInstPtr = NULL;
}
}
void
ACMILBC::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
WebRtcIlbcfix_EncoderFree((iLBC_encinst_t_*)ptrInst);
}
return;
}
WebRtc_Word16
ACMILBC::SetBitRateSafe(const WebRtc_Word32 rate)
{
// Check that rate is valid. No need to store the value
if (rate == 13300)
{
WebRtcIlbcfix_EncoderInit(_encoderInstPtr, 30);
}
else if (rate == 15200)
{
WebRtcIlbcfix_EncoderInit(_encoderInstPtr, 20);
}
else
{
return -1;
}
_encoderParams.codecInstant.rate = rate;
return 0;
}
WebRtc_Word16
ACMILBC::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec: given payload-type does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderILBC);
}
#endif
} // namespace webrtc

View File

@@ -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 ACM_ILBC_H
#define ACM_ILBC_H
#include "acm_generic_codec.h"
// forward declaration
struct iLBC_encinst_t_;
struct iLBC_decinst_t_;
namespace webrtc
{
class ACMILBC : public ACMGenericCodec
{
public:
ACMILBC(WebRtc_Word16 codecID);
~ACMILBC();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
WebRtc_Word16 SetBitRateSafe(
const WebRtc_Word32 rate);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
iLBC_encinst_t_* _encoderInstPtr;
iLBC_decinst_t_* _decoderInstPtr;
};
} // namespace webrtc
#endif //ACM_ILBC_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
/*
* 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_H
#define ACM_ISAC_H
#include "acm_generic_codec.h"
namespace webrtc
{
struct ACMISACInst;
enum iSACCodingMode {ADAPTIVE, CHANNEL_INDEPENDENT};
class ACMISAC : public ACMGenericCodec
{
public:
ACMISAC(WebRtc_Word16 codecID);
~ACMISAC();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 DeliverCachedIsacData(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte,
WebRtc_UWord32* timestamp,
WebRtcACMEncodingType* encodingType,
const WebRtc_UWord16 isacRate,
const WebRtc_UWord8 isacBWestimate);
WebRtc_Word16 DeliverCachedData(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */,
WebRtc_UWord32* /* timestamp */,
WebRtcACMEncodingType* /* encodingType */)
{
return -1;
}
WebRtc_Word16 UpdateDecoderSampFreq(
WebRtc_Word16 codecId);
WebRtc_Word16 UpdateEncoderSampFreq(
WebRtc_UWord16 sampFreqHz);
WebRtc_Word16 EncoderSampFreq(
WebRtc_UWord16& sampFreqHz);
WebRtc_Word32 ConfigISACBandwidthEstimator(
const WebRtc_UWord8 initFrameSizeMsec,
const WebRtc_UWord16 initRateBitPerSec,
const bool enforceFrameSize);
WebRtc_Word32 SetISACMaxPayloadSize(
const WebRtc_UWord16 maxPayloadLenBytes);
WebRtc_Word32 SetISACMaxRate(
const WebRtc_UWord32 maxRateBitPerSec);
WebRtc_Word16 REDPayloadISAC(
const WebRtc_Word32 isacRate,
const WebRtc_Word16 isacBwEstimate,
WebRtc_UWord8* payload,
WebRtc_Word16* payloadLenBytes);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 SetBitRateSafe(
const WebRtc_Word32 bitRate);
WebRtc_Word32 GetEstimatedBandwidthSafe();
WebRtc_Word32 SetEstimatedBandwidthSafe(WebRtc_Word32 estimatedBandwidth);
WebRtc_Word32 GetRedPayloadSafe(
WebRtc_UWord8* redPayload,
WebRtc_Word16* payloadBytes);
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 Transcode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte,
WebRtc_Word16 qBWE,
WebRtc_Word32 rate,
bool isRED);
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
void CurrentRate(WebRtc_Word32& rateBitPerSec);
void UpdateFrameLen();
bool DecoderParamsSafe(
WebRtcACMCodecParams *decParams,
const WebRtc_UWord8 payloadType);
void SaveDecoderParamSafe(
const WebRtcACMCodecParams* codecParams);
ACMISACInst* _codecInstPtr;
bool _isEncInitialized;
iSACCodingMode _isacCodingMode;
bool _enforceFrameSize;
WebRtc_Word32 _isacCurrentBN;
WebRtc_UWord16 _samplesIn10MsAudio;
WebRtcACMCodecParams _decoderParams32kHz;
};
} //namespace
#endif // ACM_ISAC_H

View File

@@ -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 ACM_ISAC_MACROS_H
#define ACM_ISAC_MACROS_H
#include "engine_configurations.h"
namespace webrtc
{
#ifdef WEBRTC_CODEC_ISAC
# define ACM_ISAC_CREATE WebRtcIsac_Create
# define ACM_ISAC_FREE WebRtcIsac_Free
# define ACM_ISAC_ENCODERINIT WebRtcIsac_EncoderInit
# define ACM_ISAC_ENCODE WebRtcIsac_Encode
# define ACM_ISAC_DECODERINIT WebRtcIsac_DecoderInit
# define ACM_ISAC_DECODE_BWE WebRtcIsac_UpdateBwEstimate
# define ACM_ISAC_DECODE_B WebRtcIsac_Decode
# define ACM_ISAC_DECODEPLC WebRtcIsac_DecodePlc
# define ACM_ISAC_CONTROL WebRtcIsac_Control
# define ACM_ISAC_CONTROL_BWE WebRtcIsac_ControlBwe
# define ACM_ISAC_GETFRAMELEN WebRtcIsac_ReadFrameLen
# define ACM_ISAC_VERSION WebRtcIsac_version
# define ACM_ISAC_GETERRORCODE WebRtcIsac_GetErrorCode
# define ACM_ISAC_GETSENDBITRATE WebRtcIsac_GetUplinkBw
# define ACM_ISAC_SETMAXPAYLOADSIZE WebRtcIsac_SetMaxPayloadSize
# define ACM_ISAC_SETMAXRATE WebRtcIsac_SetMaxRate
# define ACM_ISAC_GETNEWBITSTREAM WebRtcIsac_GetNewBitStream
# define ACM_ISAC_GETSENDBWE WebRtcIsac_GetDownLinkBwIndex
# define ACM_ISAC_SETBWE WebRtcIsac_UpdateUplinkBw
# define ACM_ISAC_GETBWE WebRtcIsac_ReadBwIndex
# define ACM_ISAC_GETNEWFRAMELEN WebRtcIsac_GetNewFrameLen
# define ACM_ISAC_STRUCT ISACStruct
# define ACM_ISAC_GETENCSAMPRATE WebRtcIsac_EncSampRate
# define ACM_ISAC_GETDECSAMPRATE WebRtcIsac_DecSampRate
#endif
#ifdef WEBRTC_CODEC_ISACFX
# define ACM_ISAC_CREATE WebRtcIsacfix_Create
# define ACM_ISAC_FREE WebRtcIsacfix_Free
# define ACM_ISAC_ENCODERINIT WebRtcIsacfix_EncoderInit
# define ACM_ISAC_ENCODE WebRtcIsacfix_Encode
# define ACM_ISAC_DECODERINIT WebRtcIsacfix_DecoderInit
# define ACM_ISAC_DECODE_BWE WebRtcIsacfix_UpdateBwEstimate
# define ACM_ISAC_DECODE_B WebRtcIsacfix_Decode
# define ACM_ISAC_DECODEPLC WebRtcIsacfix_DecodePlc
# define ACM_ISAC_CONTROL ACMISACFixControl // local Impl
# define ACM_ISAC_CONTROL_BWE ACMISACFixControlBWE // local Impl
# define ACM_ISAC_GETFRAMELEN WebRtcIsacfix_ReadFrameLen
# define ACM_ISAC_VERSION WebRtcIsacfix_version
# define ACM_ISAC_GETERRORCODE WebRtcIsacfix_GetErrorCode
# define ACM_ISAC_GETSENDBITRATE ACMISACFixGetSendBitrate // local Impl
# define ACM_ISAC_SETMAXPAYLOADSIZE WebRtcIsacfix_SetMaxPayloadSize
# define ACM_ISAC_SETMAXRATE WebRtcIsacfix_SetMaxRate
# define ACM_ISAC_GETNEWBITSTREAM ACMISACFixGetNewBitstream // local Impl
# define ACM_ISAC_GETSENDBWE ACMISACFixGetSendBWE // local Impl
# define ACM_ISAC_SETBWE WebRtcIsacfix_UpdateUplinkBw
# define ACM_ISAC_GETBWE WebRtcIsacfix_ReadBwIndex
# define ACM_ISAC_GETNEWFRAMELEN WebRtcIsacfix_GetNewFrameLen
# define ACM_ISAC_STRUCT ISACFIX_MainStruct
# define ACM_ISAC_GETENCSAMPRATE ACMISACFixGetEncSampRate // local Impl
# define ACM_ISAC_GETDECSAMPRATE ACMISACFixGetDecSampRate // local Impl
#endif
} //namespace
#endif // ACM_ISAC_MACROS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,446 @@
/*
* 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_NETEQ_H
#define ACM_NETEQ_H
#include "audio_coding_module.h"
#include "audio_coding_module_typedefs.h"
#include "engine_configurations.h"
#include "module_common_types.h"
#include "typedefs.h"
#include "webrtc_neteq.h"
#include "webrtc_vad.h"
namespace webrtc {
class CriticalSectionWrapper;
class RWLockWrapper;
struct CodecInst;
enum AudioPlayoutMode;
enum ACMSpeechType;
#define MAX_NUM_SLAVE_NETEQ 1
class ACMNetEQ
{
public:
// Constructor of the class
ACMNetEQ();
// Destructor of the class.
~ACMNetEQ();
//
// GetVersion()
// Fills the version array with the NetEQ version and updates the
// remainingBufferInBytes and position variables accordingly.
//
// Output:
// - version : An array to be filled with the version
// data.
//
// Input/Output:
// - remainingBuffInBytes : The number of free bytes at the end of
// the version array.
// - position : Position where the free space starts.
//
// Return value : 0 if ok.
// -1 if NetEQ returned an error.
//
static WebRtc_Word32 GetVersion(
WebRtc_Word8* version,
WebRtc_UWord32& remainingBuffInBytes,
WebRtc_UWord32& position);
//
// Init()
// Allocates memory for NetEQ and VAD and initializes them.
//
// Return value : 0 if ok.
// -1 if NetEQ or VAD returned an error or
// if out of memory.
//
WebRtc_Word32 Init();
//
// RecIn()
// Gives the payload to NetEQ.
//
// Input:
// - incomingPayload : Incoming audio payload.
// - payloadLength : Length of incoming audio payload.
// - rtpInfo : RTP header for the incoming payload containing
// information about payload type, sequence number,
// timestamp, ssrc and marker bit.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 RecIn(
const WebRtc_Word8* incomingPayload,
const WebRtc_Word32 payloadLength,
const WebRtcRTPHeader& rtpInfo);
//
// RecOut()
// Asks NetEQ for 10 ms of decoded audio.
//
// Input:
// -audioFrame : an audio frame were output data and
// associated parameters are written to.
//
// Return value : 0 if ok.
// -1 if NetEQ returned an error.
//
WebRtc_Word32 RecOut(
AudioFrame& audioFrame);
//
// AddCodec()
// Adds a new codec to the NetEQ codec database.
//
// Input:
// - codecDef : The codec to be added.
// - toMaster : true if the codec has to be added to Master
// NetEq, otherwise will be added to the Slave
// NetEQ.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 AddCodec(
WebRtcNetEQ_CodecDef *codecDef,
bool toMaster = true);
//
// AllocatePacketBuffer()
// Allocates the NetEQ packet buffer.
//
// Input:
// - usedCodecs : An array of the codecs to be used by NetEQ.
// - noOfCodecs : Number of codecs in usedCodecs.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 AllocatePacketBuffer(
WebRtcNetEQDecoder* usedCodecs,
WebRtc_Word16 noOfCodecs);
//
// SetExtraDelay()
// Sets an delayInMS milliseconds extra delay in NetEQ.
//
// Input:
// - delayInMS : Extra delay in milliseconds.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 SetExtraDelay(
const WebRtc_Word32 delayInMS);
//
// SetAVTPlayout()
// Enable/disable playout of AVT payloads.
//
// Input:
// - enable : Enable if true, disable if false.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 SetAVTPlayout(
const bool enable);
//
// AVTPlayout()
// Get the current AVT playout state.
//
// Return value : True if AVT playout is enabled.
// False if AVT playout is disabled.
//
bool AVTPlayout() const;
//
// CurrentSampFreqHz()
// Get the current sampling frequency in Hz.
//
// Return value : Sampling frequency in Hz.
//
WebRtc_Word32 CurrentSampFreqHz() const;
//
// SetPlayoutMode()
// Sets the playout mode to voice or fax.
//
// Input:
// - mode : The playout mode to be used, voice,
// fax, or streaming.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 SetPlayoutMode(
const AudioPlayoutMode mode);
//
// PlayoutMode()
// Get the current playout mode.
//
// Return value : The current playout mode.
//
AudioPlayoutMode PlayoutMode() const;
//
// NetworkStatistics()
// Get the current network statistics from NetEQ.
//
// Output:
// - statistics : The current network statistics.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 NetworkStatistics(
ACMNetworkStatistics* statistics) const;
//
// JitterStatistics()
// Get the current jitter statistics from NetEQ.
//
// Output:
// - jitterStatistics : The current jitter statistics.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 JitterStatistics(
ACMJitterStatistics* jitterStatistics) const;
//
// PreferredBufferSize()
// Get the currently preferred buffer size from NetEQ.
//
// Output:
// - prefBufSize : The optimal buffer size for the current network
// conditions.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 PreferredBufferSize(
WebRtc_UWord16* prefBufSize) const;
//
// ResetJitterStatistics()
// Resets the NetEQ jitter statistics.
//
// Return value : 0 if ok.
// <0 if NetEQ returned an error.
//
WebRtc_Word32 ResetJitterStatistics() const;
//
// VADStatus()
// Get the current VAD status.
//
// Return value : True if VAD is enabled.
// False if VAD is disabled.
//
bool VADStatus() const;
//
// SetVADStatus()
// Enable/disable VAD.
//
// Input:
// - enable : Enable if true, disable if false.
//
// Return value : 0 if ok.
// -1 if an error occurred.
//
WebRtc_Word16 SetVADStatus(
const bool status);
//
// VADMode()
// Get the current VAD Mode.
//
// Return value : The current VAD mode.
//
ACMVADMode VADMode() const;
//
// SetVADMode()
// Set the VAD mode.
//
// Input:
// - mode : The new VAD mode.
//
// Return value : 0 if ok.
// -1 if an error occurred.
//
WebRtc_Word16 SetVADMode(
const ACMVADMode mode);
//
// DecodeLock()
// Get the decode lock used to protect decoder instances while decoding.
//
// Return value : Pointer to the decode lock.
//
RWLockWrapper* DecodeLock() const
{
return _decodeLock;
}
//
// FlushBuffers()
// Flushes the NetEQ packet and speech buffers.
//
// Return value : 0 if ok.
// -1 if NetEQ returned an error.
//
WebRtc_Word32 FlushBuffers();
//
// RemoveCodec()
// Removes a codec from the NetEQ codec database.
//
// Input:
// - codecIdx : Codec to be removed.
//
// Return value : 0 if ok.
// -1 if an error occurred.
//
WebRtc_Word16 RemoveCodec(
WebRtcNetEQDecoder codecIdx,
bool isStereo = false);
//
// Delay()
// Get the length of the current audio buffer in milliseconds. That is
// approximately the playout delay, which can be used for lip-synch.
//
// Output:
// - currentDelayInMs : delay in audio buffer given in milliseconds
//
// return value : 0 if ok
// -1 if an error occurred.
//
WebRtc_Word16 Delay(
WebRtc_UWord16& currentDelayInMs) const;
//
// SetBackgroundNoiseMode()
// Set the mode of the background noise.
//
// Input:
// - mode : an enumerator specifying the mode of the
// background noise.
//
// Return value : 0 if succeeded,
// -1 if failed to set the mode.
//
WebRtc_Word16 SetBackgroundNoiseMode(
const ACMBackgroundNoiseMode mode);
//
// BackgroundNoiseMode()
// return the mode of the background noise.
//
// Return value : The mode of background noise.
//
WebRtc_Word16 BackgroundNoiseMode(
ACMBackgroundNoiseMode& mode);
void SetUniqueId(
WebRtc_Word32 id);
WebRtc_Word32 PlayoutTimestamp(
WebRtc_UWord32& timestamp);
void SetReceivedStereo(
bool receivedStereo);
WebRtc_UWord8 NumSlaves();
enum JB {masterJB = 0, slaveJB = 1};
WebRtc_Word16 AddSlave(
WebRtcNetEQDecoder* usedCodecs,
WebRtc_Word16 noOfCodecs);
private:
//
// RTPPack()
// Creates a Word16 RTP packet out of the payload data in Word16 and
// a WebRtcRTPHeader.
//
// Input:
// - payload : Payload to be packetized.
// - payloadLengthW8 : Length of the payload in bytes.
// - rtpInfo : RTP header struct.
//
// Output:
// - rtpPacket : The RTP packet.
//
static void RTPPack(
WebRtc_Word16* rtpPacket,
const WebRtc_Word8* payload,
const WebRtc_Word32 payloadLengthW8,
const WebRtcRTPHeader& rtpInfo);
void LogError(
const WebRtc_Word8* neteqFuncName,
const WebRtc_Word16 idx) const;
WebRtc_Word16 InitByIdxSafe(
const WebRtc_Word16 idx);
WebRtc_Word16 EnableVADByIdxSafe(
const WebRtc_Word16 idx);
WebRtc_Word16 AllocatePacketBufferByIdxSafe(
WebRtcNetEQDecoder* usedCodecs,
WebRtc_Word16 noOfCodecs,
const WebRtc_Word16 idx);
void* _inst[MAX_NUM_SLAVE_NETEQ + 1];
void* _instMem[MAX_NUM_SLAVE_NETEQ + 1];
WebRtc_Word16* _netEqPacketBuffer[MAX_NUM_SLAVE_NETEQ + 1];
WebRtc_Word32 _id;
float _currentSampFreqKHz;
bool _avtPlayout;
AudioPlayoutMode _playoutMode;
CriticalSectionWrapper* _netEqCritSect;
WebRtcVadInst* _ptrVADInst[MAX_NUM_SLAVE_NETEQ + 1];
bool _vadStatus;
ACMVADMode _vadMode;
RWLockWrapper* _decodeLock;
bool _isInitialized[MAX_NUM_SLAVE_NETEQ + 1];
WebRtc_UWord8 _numSlaves;
bool _receivedStereo;
void* _masterSlaveInfo;
AudioFrame::VADActivity _previousAudioActivity;
CriticalSectionWrapper* _callbackCritSect;
};
} //namespace webrtc
#endif //ACM_NETEQ_H

View File

@@ -0,0 +1,480 @@
/*
* 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 "acm_common_defs.h"
#include "acm_neteq.h"
#include "acm_opus.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_OPUS
// NOTE! Opus is not included in the open-source package. Modify this file or your codec
// API to match the function call and name of used Opus API file.
// #include "opus_interface.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_OPUS
ACMOPUS::ACMOPUS(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMOPUS::~ACMOPUS()
{
return;
}
WebRtc_Word16
ACMOPUS::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMOPUS::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMOPUS::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMOPUS::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMOPUS::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMOPUS::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMOPUS::InternalCreateEncoder()
{
return -1;
}
void
ACMOPUS::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMOPUS::InternalCreateDecoder()
{
return -1;
}
void
ACMOPUS::DestructDecoderSafe()
{
return;
}
void
ACMOPUS::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMOPUS::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
WebRtc_Word16
ACMOPUS::SetBitRateSafe(
const WebRtc_Word32 /*rate*/ )
{
return -1;
}
#else //===================== Actual Implementation =======================
// Remove when integrating a real Opus wrapper
extern WebRtc_Word16 WebRtcOpus_CreateEnc(OPUS_inst_t_** inst, WebRtc_Word16 samplFreq);
extern WebRtc_Word16 WebRtcOpus_CreateDec(OPUS_inst_t_** inst, WebRtc_Word16 samplFreq);
extern WebRtc_Word16 WebRtcOpus_FreeEnc(OPUS_inst_t_* inst);
extern WebRtc_Word16 WebRtcOpus_FreeDec(OPUS_inst_t_* inst);
extern WebRtc_Word16 WebRtcOpus_Encode(OPUS_inst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16* output,
WebRtc_Word16 len,
WebRtc_Word16 byteLen);
extern WebRtc_Word16 WebRtcOpus_EncoderInit(OPUS_inst_t_* encInst,
WebRtc_Word16 samplFreq,
WebRtc_Word16 mode,
WebRtc_Word16 vbrFlag);
extern WebRtc_Word16 WebRtcOpus_Decode(OPUS_inst_t_* decInst);
extern WebRtc_Word16 WebRtcOpus_DecodeBwe(OPUS_inst_t_* decInst, WebRtc_Word16* input);
extern WebRtc_Word16 WebRtcOpus_DecodePlc(OPUS_inst_t_* decInst);
extern WebRtc_Word16 WebRtcOpus_DecoderInit(OPUS_inst_t_* decInst);
ACMOPUS::ACMOPUS(
WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_decoderInstPtr(NULL),
_opusMode(1), // default mode is the hybrid mode
_flagVBR(0) // default VBR off
{
_codecID = codecID;
// Current implementation doesn't have DTX. That might change.
_hasInternalDTX = false;
// Default sampling frequency
_mySampFreq = 48000;
// default rate
_myRate = 50000;
return;
}
ACMOPUS::~ACMOPUS()
{
if(_encoderInstPtr != NULL)
{
WebRtcOpus_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
if(_decoderInstPtr != NULL)
{
WebRtcOpus_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
return;
}
WebRtc_Word16
ACMOPUS::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
WebRtc_Word16 noEncodedSamples = 0;
WebRtc_Word16 tmpLenByte = 0;
*bitStreamLenByte = 0;
WebRtc_Word16 byteLengthFrame = 0;
// Derive what byte-length is requested
byteLengthFrame = _myRate*_frameLenSmpl/(8*_mySampFreq);
// Call Encoder
*bitStreamLenByte = WebRtcOpus_Encode(_encoderInstPtr, &_inAudio[_inAudioIxRead],
(WebRtc_Word16*)bitStream, _frameLenSmpl, byteLengthFrame);
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _frameLenSmpl;
// sanity check
if(*bitStreamLenByte < 0)
{
// error has happened
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalEncode: Encode error for Opus");
*bitStreamLenByte = 0;
return -1;
}
return *bitStreamLenByte;
}
WebRtc_Word16
ACMOPUS::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMOPUS::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
//set the bit rate and initialize
_myRate = codecParams->codecInstant.rate;
return SetBitRateSafe( (WebRtc_UWord32)_myRate);
}
WebRtc_Word16
ACMOPUS::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
if (WebRtcOpus_DecoderInit(_decoderInstPtr) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalInitDecoder: init decoder failed for Opus");
return -1;
}
return 0;
}
WebRtc_Word32
ACMOPUS::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"CodeDef: Decoder uninitialized for Opus");
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_G729_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderOpus, codecInst.pltype,
_decoderInstPtr, 16000);
SET_OPUS_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMOPUS::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMOPUS::InternalCreateEncoder()
{
if (WebRtcOpus_CreateEnc(&_encoderInstPtr, _mySampFreq) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateEncoder: create encoder failed for Opus");
return -1;
}
return 0;
}
void
ACMOPUS::DestructEncoderSafe()
{
_encoderExist = false;
_encoderInitialized = false;
if(_encoderInstPtr != NULL)
{
WebRtcOpus_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
}
WebRtc_Word16
ACMOPUS::InternalCreateDecoder()
{
if (WebRtcOpus_CreateDec(&_decoderInstPtr, _mySampFreq) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"InternalCreateDecoder: create decoder failed for Opus");
return -1;
}
return 0;
}
void
ACMOPUS::DestructDecoderSafe()
{
_decoderExist = false;
_decoderInitialized = false;
if(_decoderInstPtr != NULL)
{
WebRtcOpus_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
}
void
ACMOPUS::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
WebRtcOpus_FreeEnc((OPUS_inst_t*)ptrInst);
}
return;
}
WebRtc_Word16
ACMOPUS::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec: given payload-type does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderOpus);
}
WebRtc_Word16
ACMOPUS::SetBitRateSafe(
const WebRtc_Word32 rate)
{
//allowed rates: {8000, 12000, 14000, 16000, 18000, 20000,
// 22000, 24000, 26000, 28000, 30000, 32000};
switch(rate)
{
case 8000:
{
_myRate = 8000;
break;
}
case 12000:
{
_myRate = 12000;
break;
}
case 14000:
{
_myRate = 14000;
break;
}
case 16000:
{
_myRate = 16000;
break;
}
case 18000:
{
_myRate = 18000;
break;
}
case 20000:
{
_myRate = 20000;
break;
}
case 22000:
{
_myRate = 22000;
break;
}
case 24000:
{
_myRate = 24000;
break;
}
case 26000:
{
_myRate = 26000;
break;
}
case 28000:
{
_myRate = 28000;
break;
}
case 30000:
{
_myRate = 30000;
break;
}
case 32000:
{
_myRate = 32000;
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"SetBitRateSafe: Invalid rate Opus");
return -1;
break;
}
}
// Re-init with new rate
if (WebRtcOpus_EncoderInit(_encoderInstPtr, _mySampFreq, _opusMode, _flagVBR) >= 0)
{
_encoderParams.codecInstant.rate = _myRate;
return 0;
}
else
{
return -1;
}
}
#endif
} // namespace webrtc

View File

@@ -0,0 +1,84 @@
/*
* 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_OPUS_H
#define ACM_OPUS_H
#include "acm_generic_codec.h"
// forward declaration
struct OPUS_inst_t_;
struct OPUS_inst_t_;
namespace webrtc
{
class ACMOPUS: public ACMGenericCodec
{
public:
ACMOPUS(WebRtc_Word16 codecID);
~ACMOPUS();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
WebRtc_Word16 SetBitRateSafe(
const WebRtc_Word32 rate);
OPUS_inst_t_* _encoderInstPtr;
OPUS_inst_t_* _decoderInstPtr;
WebRtc_UWord16 _mySampFreq;
WebRtc_UWord16 _myRate;
WebRtc_Word16 _opusMode;
WebRtc_Word16 _flagVBR;
};
} // namespace webrtc
#endif // ACM_OPUS_H

View File

@@ -0,0 +1,337 @@
/*
* 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 "acm_codec_database.h"
#include "acm_common_defs.h"
#include "acm_neteq.h"
#include "acm_pcm16b.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_PCM16
#include "pcm16b.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_PCM16
ACMPCM16B::ACMPCM16B(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMPCM16B::~ACMPCM16B()
{
return;
}
WebRtc_Word16
ACMPCM16B::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMPCM16B::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMPCM16B::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMPCM16B::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMPCM16B::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMPCM16B::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMPCM16B::InternalCreateEncoder()
{
return -1;
}
WebRtc_Word16
ACMPCM16B::InternalCreateDecoder()
{
return -1;
}
void
ACMPCM16B::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
void
ACMPCM16B::DestructEncoderSafe()
{
return;
}
void
ACMPCM16B::DestructDecoderSafe()
{
return;
}
WebRtc_Word16
ACMPCM16B::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
ACMPCM16B::ACMPCM16B(
WebRtc_Word16 codecID)
{
_codecID = codecID;
_samplingFreqHz = ACMCodecDB::CodecFreq(_codecID);
}
ACMPCM16B::~ACMPCM16B()
{
return;
}
WebRtc_Word16
ACMPCM16B::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
*bitStreamLenByte = WebRtcPcm16b_Encode(&_inAudio[_inAudioIxRead],
_frameLenSmpl*_noChannels,
bitStream);
// increment the read index to tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _frameLenSmpl*_noChannels;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMPCM16B::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMPCM16B::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// PCM has no instance
return 0;
}
WebRtc_Word16
ACMPCM16B::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// PCM has no instance
return 0;
}
WebRtc_Word32
ACMPCM16B::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_PCMU_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
switch(_samplingFreqHz)
{
case 8000:
{
SET_CODEC_PAR((codecDef), kDecoderPCM16B, codecInst.pltype,
NULL, 8000);
SET_PCM16B_FUNCTIONS((codecDef));
break;
}
case 16000:
{
SET_CODEC_PAR((codecDef), kDecoderPCM16Bwb, codecInst.pltype,
NULL, 16000);
SET_PCM16B_WB_FUNCTIONS((codecDef));
break;
}
case 32000:
{
SET_CODEC_PAR((codecDef), kDecoderPCM16Bswb32kHz,
codecInst.pltype, NULL, 32000);
SET_PCM16B_SWB32_FUNCTIONS((codecDef));
break;
}
default:
{
return -1;
}
}
return 0;
}
ACMGenericCodec*
ACMPCM16B::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMPCM16B::InternalCreateEncoder()
{
// PCM has no instance
return 0;
}
WebRtc_Word16
ACMPCM16B::InternalCreateDecoder()
{
// PCM has no instance
return 0;
}
void
ACMPCM16B::InternalDestructEncoderInst(
void* /* ptrInst */)
{
// PCM has no instance
return;
}
void
ACMPCM16B::DestructEncoderSafe()
{
// PCM has no instance
_encoderExist = false;
_encoderInitialized = false;
return;
}
void
ACMPCM16B::DestructDecoderSafe()
{
// PCM has no instance
_decoderExist = false;
_decoderInitialized = false;
return;
}
WebRtc_Word16
ACMPCM16B::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
switch(_samplingFreqHz)
{
case 8000:
{
return netEq->RemoveCodec(kDecoderPCM16B);
break;
}
case 16000:
{
return netEq->RemoveCodec(kDecoderPCM16Bwb);
break;
}
case 32000:
{
return netEq->RemoveCodec(kDecoderPCM16Bswb32kHz);
break;
}
default:
{
return -1;
}
}
}
#endif
} // namespace webrtc

View File

@@ -0,0 +1,70 @@
/*
* 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_PCM16B_H
#define ACM_PCM16B_H
#include "acm_generic_codec.h"
namespace webrtc
{
class ACMPCM16B : public ACMGenericCodec
{
public:
ACMPCM16B(WebRtc_Word16 codecID);
~ACMPCM16B();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word32 _samplingFreqHz;
};
} // namespace webrtc
#endif //ACM_PCM16B_H

View File

@@ -0,0 +1,165 @@
/*
* 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 "acm_common_defs.h"
#include "acm_neteq.h"
#include "acm_pcma.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
// Codec interface
#include "g711_interface.h"
namespace webrtc
{
ACMPCMA::ACMPCMA(WebRtc_Word16 codecID)
{
_codecID = codecID;
}
ACMPCMA::~ACMPCMA()
{
return;
}
WebRtc_Word16
ACMPCMA::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
*bitStreamLenByte = WebRtcG711_EncodeA(NULL, &_inAudio[_inAudioIxRead],
_frameLenSmpl*_noChannels, (WebRtc_Word16*)bitStream);
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _frameLenSmpl*_noChannels;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMPCMA::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMPCMA::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// PCM has no instance
return 0;
}
WebRtc_Word16
ACMPCMA::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// PCM has no instance
return 0;
}
WebRtc_Word32 ACMPCMA::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_PCMA_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderPCMa, codecInst.pltype, NULL, 8000);
SET_PCMA_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMPCMA::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMPCMA::InternalCreateEncoder()
{
// PCM has no instance
return 0;
}
WebRtc_Word16
ACMPCMA::InternalCreateDecoder()
{
// PCM has no instance
return 0;
}
void
ACMPCMA::InternalDestructEncoderInst(
void* /* ptrInst */)
{
// PCM has no instance
return;
}
void
ACMPCMA::DestructEncoderSafe()
{
// PCM has no instance
return;
}
void
ACMPCMA::DestructDecoderSafe()
{
// PCM has no instance
_decoderInitialized = false;
_decoderExist = false;
return;
}
WebRtc_Word16
ACMPCMA::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderPCMa);
}
} // namespace webrtc

View File

@@ -0,0 +1,68 @@
/*
* 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_PCMA_H
#define ACM_PCMA_H
#include "acm_generic_codec.h"
namespace webrtc
{
class ACMPCMA : public ACMGenericCodec
{
public:
ACMPCMA(WebRtc_Word16 codecID);
~ACMPCMA();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
void InternalDestructEncoderInst(
void* ptrInst);
};
} // namespace webrtc
#endif //ACM_PCMA_H

View File

@@ -0,0 +1,167 @@
/*
* 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 "acm_common_defs.h"
#include "acm_neteq.h"
#include "acm_pcmu.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
// Codec interface
#include "g711_interface.h"
namespace webrtc
{
ACMPCMU::ACMPCMU(WebRtc_Word16 codecID)
{
_codecID = codecID;
}
ACMPCMU::~ACMPCMU()
{
return;
}
WebRtc_Word16
ACMPCMU::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
*bitStreamLenByte = WebRtcG711_EncodeU(NULL, &_inAudio[_inAudioIxRead],
_frameLenSmpl*_noChannels, (WebRtc_Word16*)bitStream);
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _frameLenSmpl*_noChannels;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMPCMU::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMPCMU::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// PCM has no instance
return 0;
}
WebRtc_Word16
ACMPCMU::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// PCM has no instance
return 0;
}
WebRtc_Word32
ACMPCMU::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_PCMU_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderPCMu, codecInst.pltype, NULL, 8000);
SET_PCMU_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMPCMU::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMPCMU::InternalCreateEncoder()
{
// PCM has no instance
return 0;
}
WebRtc_Word16
ACMPCMU::InternalCreateDecoder()
{
// PCM has no instance
return 0;
}
void
ACMPCMU::InternalDestructEncoderInst(
void* /* ptrInst */)
{
// PCM has no instance
return;
}
void
ACMPCMU::DestructEncoderSafe()
{
// PCM has no instance
_encoderExist = false;
_encoderInitialized = false;
return;
}
void ACMPCMU::DestructDecoderSafe()
{
// PCM has no instance
_decoderInitialized = false;
_decoderExist = false;
return;
}
WebRtc_Word16
ACMPCMU::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderPCMu);
}
} // namespace webrtc

View File

@@ -0,0 +1,68 @@
/*
* 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_PCMU_H
#define ACM_PCMU_H
#include "acm_generic_codec.h"
namespace webrtc
{
class ACMPCMU : public ACMGenericCodec
{
public:
ACMPCMU(WebRtc_Word16 codecID);
~ACMPCMU();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
void InternalDestructEncoderInst(
void* ptrInst);
};
} // namespace webrtc
#endif //ACM_PCMU_H

View File

@@ -0,0 +1,163 @@
/*
* 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 "acm_red.h"
#include "acm_neteq.h"
#include "acm_common_defs.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
namespace webrtc
{
ACMRED::ACMRED(WebRtc_Word16 codecID)
{
_codecID = codecID;
}
ACMRED::~ACMRED()
{
return;
}
WebRtc_Word16
ACMRED::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
// RED is never used as an encoder
// RED has no instance
return 0;
}
WebRtc_Word16
ACMRED::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMRED::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// RED has no instance
return 0;
}
WebRtc_Word16
ACMRED::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
// This codec does not need initialization,
// RED has no instance
return 0;
}
WebRtc_Word32
ACMRED::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
// Todo:
// log error
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_PCMU_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderRED, codecInst.pltype, NULL, 8000);
SET_RED_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMRED::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMRED::InternalCreateEncoder()
{
// RED has no instance
return 0;
}
WebRtc_Word16
ACMRED::InternalCreateDecoder()
{
// RED has no instance
return 0;
}
void
ACMRED::InternalDestructEncoderInst(
void* /* ptrInst */)
{
// RED has no instance
return;
}
void
ACMRED::DestructEncoderSafe()
{
// RED has no instance
return;
}
void ACMRED::DestructDecoderSafe()
{
// RED has no instance
return;
}
WebRtc_Word16
ACMRED::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
return netEq->RemoveCodec(kDecoderRED);
}
} // namespace webrtc

View File

@@ -0,0 +1,68 @@
/*
* 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_RED_H
#define ACM_RED_H
#include "acm_generic_codec.h"
namespace webrtc
{
class ACMRED : public ACMGenericCodec
{
public:
ACMRED(WebRtc_Word16 codecID);
~ACMRED();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
void InternalDestructEncoderInst(
void* ptrInst);
};
} // namespace webrtc
#endif //ACM_RED_H

View File

@@ -0,0 +1,90 @@
/*
* 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 <string.h>
#include "acm_resampler.h"
#include "critical_section_wrapper.h"
#include "resampler.h"
#include "signal_processing_library.h"
#include "trace.h"
namespace webrtc
{
ACMResampler::ACMResampler():
_resamplerCritSect(*CriticalSectionWrapper::CreateCriticalSection())
{
}
ACMResampler::~ACMResampler()
{
delete &_resamplerCritSect;
}
WebRtc_Word16
ACMResampler::Resample10Msec(
const WebRtc_Word16* inAudio,
WebRtc_Word32 inFreqHz,
WebRtc_Word16* outAudio,
WebRtc_Word32 outFreqHz,
WebRtc_UWord8 numAudioChannels)
{
CriticalSectionScoped cs(_resamplerCritSect);
if(inFreqHz == outFreqHz)
{
memcpy(outAudio, inAudio, (inFreqHz*numAudioChannels / 100) * sizeof(WebRtc_Word16));
return (WebRtc_Word16)(inFreqHz / 100);
}
int maxLen = 480 * numAudioChannels; //max number of samples for 10ms at 48kHz
int lengthIn = (WebRtc_Word16)(inFreqHz / 100) * numAudioChannels;
int outLen;
WebRtc_Word32 ret;
ResamplerType type;
type = (numAudioChannels == 1)? kResamplerSynchronous:kResamplerSynchronousStereo;
ret = _resampler.ResetIfNeeded(inFreqHz,outFreqHz,type);
if (ret < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id,
"Error in reset of resampler");
return -1;
}
ret = _resampler.Push(inAudio, lengthIn, outAudio, maxLen, outLen);
if (ret < 0 )
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id,
"Error in resampler: resampler.Push");
return -1;
}
WebRtc_Word16 outAudioLenSmpl = (WebRtc_Word16) outLen / numAudioChannels;
return outAudioLenSmpl;
}
void
ACMResampler::SetUniqueId(
WebRtc_Word32 id)
{
CriticalSectionScoped lock(_resamplerCritSect);
_id = id;
}
} // namespace webrtc

View File

@@ -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 ACM_RESAMPLER_H
#define ACM_RESAMPLER_H
#include "resampler.h"
#include "typedefs.h"
namespace webrtc {
class CriticalSectionWrapper;
class ACMResampler
{
public:
ACMResampler();
~ACMResampler();
WebRtc_Word16 Resample10Msec(
const WebRtc_Word16* inAudio,
const WebRtc_Word32 inFreqHz,
WebRtc_Word16* outAudio,
const WebRtc_Word32 outFreqHz,
WebRtc_UWord8 numAudioChannels);
void SetUniqueId(
WebRtc_Word32 id);
private:
//Use the Resampler class
Resampler _resampler;
WebRtc_Word32 _id;
CriticalSectionWrapper& _resamplerCritSect;
};
} // namespace webrtc
#endif //ACM_RESAMPLER_H

View File

@@ -0,0 +1,661 @@
/*
* 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 "acm_codec_database.h"
#include "acm_common_defs.h"
#include "acm_neteq.h"
#include "acm_speex.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#ifdef WEBRTC_CODEC_SPEEX
// NOTE! Speex is not included in the open-source package. Modify this file or your codec
// API to match the function call and name of used Speex API file.
// #include "speex_interface.h"
#endif
namespace webrtc
{
#ifndef WEBRTC_CODEC_SPEEX
ACMSPEEX::ACMSPEEX(WebRtc_Word16 /* codecID*/)
{
return;
}
ACMSPEEX::~ACMSPEEX()
{
return;
}
WebRtc_Word16
ACMSPEEX::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMSPEEX::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMSPEEX::EnableDTX()
{
return -1;
}
WebRtc_Word16
ACMSPEEX::DisableDTX()
{
return -1;
}
WebRtc_Word16
ACMSPEEX::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMSPEEX::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMSPEEX::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMSPEEX::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMSPEEX::InternalCreateEncoder()
{
return -1;
}
void
ACMSPEEX::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMSPEEX::InternalCreateDecoder()
{
return -1;
}
void
ACMSPEEX::DestructDecoderSafe()
{
return;
}
WebRtc_Word16
ACMSPEEX::SetBitRateSafe(
const WebRtc_Word32 /* rate */)
{
return -1;
}
void
ACMSPEEX::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMSPEEX::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#ifdef UNUSEDSPEEX
WebRtc_Word16
ACMSPEEX::EnableVBR()
{
return -1;
}
WebRtc_Word16
ACMSPEEX::DisableVBR()
{
return -1;
}
WebRtc_Word16
ACMSPEEX::SetComplMode(
WebRtc_Word16 mode)
{
return -1;
}
#endif
#else //===================== Actual Implementation =======================
// Remove when integrating a real Speex wrapper
extern WebRtc_Word16 WebRtcSpeex_CreateEnc(SPEEX_encinst_t_** inst,
WebRtc_Word16 samplFreq);
extern WebRtc_Word16 WebRtcSpeex_CreateDec(SPEEX_decinst_t_** inst,
WebRtc_Word16 samplFreq,
WebRtc_Word16 mode);
extern WebRtc_Word16 WebRtcSpeex_FreeEnc(SPEEX_encinst_t_* inst);
extern WebRtc_Word16 WebRtcSpeex_FreeDec(SPEEX_decinst_t_* inst);
extern WebRtc_Word16 WebRtcSpeex_Encode(SPEEX_encinst_t_* encInst,
WebRtc_Word16* input,
WebRtc_Word16 rate);
extern WebRtc_Word16 WebRtcSpeex_EncoderInit(SPEEX_encinst_t_* encInst,
WebRtc_Word16 samplFreq,
WebRtc_Word16 mode,
WebRtc_Word16 vbrFlag);
extern WebRtc_Word16 WebRtcSpeex_GetBitstream(SPEEX_encinst_t_* encInst,
WebRtc_Word16* output);
extern WebRtc_Word16 WebRtcSpeex_Decode(SPEEX_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcSpeex_DecodePlc(SPEEX_decinst_t_* decInst);
extern WebRtc_Word16 WebRtcSpeex_DecoderInit(SPEEX_decinst_t_* decInst);
ACMSPEEX::ACMSPEEX(WebRtc_Word16 codecID):
_encoderInstPtr(NULL),
_decoderInstPtr(NULL)
{
_codecID = codecID;
// Set sampling frequency, frame size and rate Speex
if(_codecID == ACMCodecDB::speex8)
{
_samplingFrequency = 8000;
_samplesIn20MsAudio = 160;
_encodingRate = 11000;
}
else if(_codecID == ACMCodecDB::speex16)
{
_samplingFrequency = 16000;
_samplesIn20MsAudio = 320;
_encodingRate = 22000;
}
else
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Wrong codec id for Speex.");
_samplingFrequency = -1;
_samplesIn20MsAudio = -1;
_encodingRate = -1;
}
_hasInternalDTX = true;
_dtxEnabled = false;
_vbrEnabled = false;
_complMode = 3; // default complexity value
return;
}
ACMSPEEX::~ACMSPEEX()
{
if(_encoderInstPtr != NULL)
{
WebRtcSpeex_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
if(_decoderInstPtr != NULL)
{
WebRtcSpeex_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
return;
}
WebRtc_Word16
ACMSPEEX::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
WebRtc_Word16 status;
WebRtc_Word16 numEncodedSamples = 0;
WebRtc_Word16 n = 0;
while( numEncodedSamples < _frameLenSmpl)
{
status = WebRtcSpeex_Encode(_encoderInstPtr, &_inAudio[_inAudioIxRead],
_encodingRate);
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _samplesIn20MsAudio;
numEncodedSamples += _samplesIn20MsAudio;
if(status < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Error in Speex encoder");
return status;
}
// Update VAD, if internal DTX is used
if(_hasInternalDTX && _dtxEnabled)
{
_vadLabel[n++] = status;
_vadLabel[n++] = status;
}
if(status == 0)
{
// This frame is detected as inactive. We need send whatever
// encoded so far.
*bitStreamLenByte = WebRtcSpeex_GetBitstream(_encoderInstPtr,
(WebRtc_Word16*)bitStream);
return *bitStreamLenByte;
}
}
*bitStreamLenByte = WebRtcSpeex_GetBitstream(_encoderInstPtr,
(WebRtc_Word16*)bitStream);
return *bitStreamLenByte;
}
WebRtc_Word16
ACMSPEEX::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMSPEEX::EnableDTX()
{
if(_dtxEnabled)
{
return 0;
}
else if(_encoderExist) // check if encoder exist
{
// enable DTX
if(WebRtcSpeex_EncoderInit(_encoderInstPtr, (_vbrEnabled ? 1:0), _complMode, 1) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot enable DTX for Speex");
return -1;
}
_dtxEnabled = true;
return 0;
}
else
{
return -1;
}
return 0;
}
WebRtc_Word16
ACMSPEEX::DisableDTX()
{
if(!_dtxEnabled)
{
return 0;
}
else if(_encoderExist) // check if encoder exist
{
// disable DTX
if(WebRtcSpeex_EncoderInit(_encoderInstPtr, (_vbrEnabled ? 1:0), _complMode, 0) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot disable DTX for Speex");
return -1;
}
_dtxEnabled = false;
return 0;
}
else
{
// encoder doesn't exists, therefore disabling is harmless
return 0;
}
return 0;
}
WebRtc_Word16
ACMSPEEX::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
// sanity check
if (_encoderInstPtr == NULL)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot initialize Speex encoder, instance does not exist");
return -1;
}
WebRtc_Word16 status = SetBitRateSafe((codecParams->codecInstant).rate);
status += (WebRtcSpeex_EncoderInit(_encoderInstPtr, _vbrEnabled, _complMode, ((codecParams->enableDTX)? 1:0)) < 0)? -1:0;
if (status >= 0) {
return 0;
} else {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Error in initialization of Speex encoder");
return -1;
}
}
WebRtc_Word16
ACMSPEEX::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
WebRtc_Word16 status;
// sanity check
if (_decoderInstPtr == NULL)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot initialize Speex decoder, instance does not exist");
return -1;
}
status = ((WebRtcSpeex_DecoderInit(_decoderInstPtr) < 0)? -1:0);
if (status >= 0) {
return 0;
} else {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Error in initialization of Speex decoder");
return -1;
}
}
WebRtc_Word32
ACMSPEEX::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Error, Speex decoder is not initialized");
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_SPEEX_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
switch(_samplingFrequency)
{
case 8000:
{
SET_CODEC_PAR((codecDef), kDecoderSPEEX_8, codecInst.pltype,
_decoderInstPtr, 8000);
break;
}
case 16000:
{
SET_CODEC_PAR((codecDef), kDecoderSPEEX_16, codecInst.pltype,
_decoderInstPtr, 16000);
break;
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Unsupported sampling frequency for Speex");
return -1;
break;
}
}
SET_SPEEX_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMSPEEX::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMSPEEX::InternalCreateEncoder()
{
return WebRtcSpeex_CreateEnc(&_encoderInstPtr, _samplingFrequency);
}
void
ACMSPEEX::DestructEncoderSafe()
{
if(_encoderInstPtr != NULL)
{
WebRtcSpeex_FreeEnc(_encoderInstPtr);
_encoderInstPtr = NULL;
}
// there is no encoder set the following
_encoderExist = false;
_encoderInitialized = false;
_encodingRate = 0;
}
WebRtc_Word16
ACMSPEEX::InternalCreateDecoder()
{
return WebRtcSpeex_CreateDec(&_decoderInstPtr, _samplingFrequency, 1);
}
void
ACMSPEEX::DestructDecoderSafe()
{
if(_decoderInstPtr != NULL)
{
WebRtcSpeex_FreeDec(_decoderInstPtr);
_decoderInstPtr = NULL;
}
// there is no encoder instance set the followings
_decoderExist = false;
_decoderInitialized = false;
}
WebRtc_Word16
ACMSPEEX::SetBitRateSafe(
const WebRtc_Word32 rate)
{
// Check if changed rate
if (rate == _encodingRate) {
return 0;
} else if (rate > 2000) {
_encodingRate = rate;
_encoderParams.codecInstant.rate = rate;
} else {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Unsupported encoding rate for Speex");
return -1;
}
return 0;
}
void
ACMSPEEX::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
WebRtcSpeex_FreeEnc((SPEEX_encinst_t_*)ptrInst);
}
return;
}
WebRtc_Word16
ACMSPEEX::UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType)
{
if(payloadType != _decoderParams.codecInstant.pltype)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot unregister codec %s given payload-type %d does not match \
the stored payload type",
_decoderParams.codecInstant.plname,
payloadType,
_decoderParams.codecInstant.pltype);
return -1;
}
switch(_samplingFrequency)
{
case 8000:
{
return netEq->RemoveCodec(kDecoderSPEEX_8);
}
case 16000:
{
return netEq->RemoveCodec(kDecoderSPEEX_16);
}
default:
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Could not unregister Speex from NetEQ. Sampling frequency doesn't match");
return -1;
}
}
}
#ifdef UNUSEDSPEEX
// This API is currently not in use. If requested to be able to enable/disable VBR
// an ACM API need to be added.
WebRtc_Word16
ACMSPEEX::EnableVBR()
{
if(_vbrEnabled)
{
return 0;
}
else if(_encoderExist) // check if encoder exist
{
// enable Variable Bit Rate (VBR)
if(WebRtcSpeex_EncoderInit(_encoderInstPtr, 1, _complMode, (_dtxEnabled? 1:0)) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot enable VBR mode for Speex");
return -1;
}
_vbrEnabled = true;
return 0;
}
else
{
return -1;
}
}
// This API is currently not in use. If requested to be able to enable/disable VBR
// an ACM API need to be added.
WebRtc_Word16
ACMSPEEX::DisableVBR()
{
if(!_vbrEnabled)
{
return 0;
}
else if(_encoderExist) // check if encoder exist
{
// disable DTX
if(WebRtcSpeex_EncoderInit(_encoderInstPtr, 0, _complMode, (_dtxEnabled? 1:0)) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Cannot disable DTX for Speex");
return -1;
}
_vbrEnabled = false;
return 0;
}
else
{
// encoder doesn't exists, therefore disabling is harmless
return 0;
}
}
// This API is currently not in use. If requested to be able to set complexity
// an ACM API need to be added.
WebRtc_Word16
ACMSPEEX::SetComplMode(
WebRtc_Word16 mode)
{
// Check if new mode
if(mode == _complMode)
{
return 0;
}
else if(_encoderExist) // check if encoder exist
{
// Set new mode
if(WebRtcSpeex_EncoderInit(_encoderInstPtr, 0, mode, (_dtxEnabled? 1:0)) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Error in complexity mode for Speex");
return -1;
}
_complMode = mode;
return 0;
}
else
{
// encoder doesn't exists, therefore disabling is harmless
return 0;
}
}
#endif
#endif
} // namespace webrtc

View File

@@ -0,0 +1,95 @@
/*
* 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_SPEEX_H
#define ACM_SPEEX_H
#include "acm_generic_codec.h"
namespace webrtc
{
// forward declaration
struct SPEEX_encinst_t_;
struct SPEEX_decinst_t_;
class ACMSPEEX : public ACMGenericCodec
{
public:
ACMSPEEX(WebRtc_Word16 codecID);
~ACMSPEEX();
// for FEC
ACMGenericCodec* CreateInstance(void);
WebRtc_Word16 InternalEncode(
WebRtc_UWord8* bitstream,
WebRtc_Word16* bitStreamLenByte);
WebRtc_Word16 InternalInitEncoder(
WebRtcACMCodecParams *codecParams);
WebRtc_Word16 InternalInitDecoder(
WebRtcACMCodecParams *codecParams);
protected:
WebRtc_Word16 DecodeSafe(
WebRtc_UWord8* bitStream,
WebRtc_Word16 bitStreamLenByte,
WebRtc_Word16* audio,
WebRtc_Word16* audioSamples,
WebRtc_Word8* speechType);
WebRtc_Word32 CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst);
void DestructEncoderSafe();
void DestructDecoderSafe();
WebRtc_Word16 InternalCreateEncoder();
WebRtc_Word16 InternalCreateDecoder();
void InternalDestructEncoderInst(
void* ptrInst);
WebRtc_Word16 SetBitRateSafe(
const WebRtc_Word32 rate);
WebRtc_Word16 EnableDTX();
WebRtc_Word16 DisableDTX();
#ifdef UNUSEDSPEEX
WebRtc_Word16 EnableVBR();
WebRtc_Word16 DisableVBR();
WebRtc_Word16 SetComplMode(
WebRtc_Word16 mode);
#endif
WebRtc_Word16 UnregisterFromNetEqSafe(
ACMNetEQ* netEq,
WebRtc_Word16 payloadType);
SPEEX_encinst_t_* _encoderInstPtr;
SPEEX_decinst_t_* _decoderInstPtr;
WebRtc_Word16 _complMode;
bool _vbrEnabled;
WebRtc_Word32 _encodingRate;
WebRtc_Word16 _samplingFrequency;
WebRtc_UWord16 _samplesIn20MsAudio;
};
} // namespace webrtc
#endif // ACM_SPEEX_H

View File

@@ -0,0 +1,184 @@
/*
* 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.
*/
// 'conversion' conversion from 'type1' to 'type2', possible loss of data
#pragma warning(disable: 4267)
#include "acm_dtmf_detection.h"
#include "audio_coding_module.h"
#include "audio_coding_module_impl.h"
#include "trace.h"
namespace webrtc
{
// Create module
AudioCodingModule*
AudioCodingModule::Create(
const WebRtc_Word32 id)
{
return new AudioCodingModuleImpl(id);
}
// Destroy module
void
AudioCodingModule::Destroy(
AudioCodingModule* module)
{
delete static_cast<AudioCodingModuleImpl*> (module);
}
// Returns version of the module and its components.
WebRtc_Word32
AudioCodingModule::GetVersion(
WebRtc_Word8* version,
WebRtc_UWord32& remainingBufferInBytes,
WebRtc_UWord32& position)
{
WebRtc_Word32 len = position;
strncpy(&version[position], "AudioCodingModule 1.3.0\n", remainingBufferInBytes);
position = (WebRtc_UWord32)strlen(version);
remainingBufferInBytes -= (position - len);
if(ACMNetEQ::GetVersion(version,
remainingBufferInBytes, position) < 0)
{
return -1;
}
ACMCodecDB::initACMCodecDB();
if(ACMCodecDB::CodecsVersion(version,
remainingBufferInBytes, position) < 0)
{
return -1;
}
return 0;
}
// Get number of supported codecs
WebRtc_UWord8 AudioCodingModule::NumberOfCodecs()
{
WEBRTC_TRACE(webrtc::kTraceModuleCall, webrtc::kTraceAudioCoding, -1,
"NumberOfCodecs()");
ACMCodecDB::initACMCodecDB();
return (WebRtc_UWord8)ACMCodecDB::NoOfCodecs();
}
// Get supported codec param with id
WebRtc_Word32
AudioCodingModule::Codec(
const WebRtc_UWord8 listId,
CodecInst& codec)
{
WEBRTC_TRACE(webrtc::kTraceModuleCall, webrtc::kTraceAudioCoding, -1,
"Codec(const WebRtc_UWord8 listId, CodecInst& codec)");
ACMCodecDB::initACMCodecDB();
// Get the codec settings for the codec with the given list ID
return ACMCodecDB::Codec(listId, &codec);
}
// Get supported codec Param with name
WebRtc_Word32
AudioCodingModule::Codec(
const WebRtc_Word8* payloadName,
CodecInst& codec,
const WebRtc_Word32 samplingFreqHz)
{
WEBRTC_TRACE(webrtc::kTraceModuleCall, webrtc::kTraceAudioCoding, -1,
"Codec(const WebRtc_Word8* payloadName, CodecInst& codec)");
ACMCodecDB::initACMCodecDB();
// Search through codec list for a matching name
for(WebRtc_Word16 codecCntr = 0; codecCntr < ACMCodecDB::NoOfCodecs();
codecCntr++)
{
// Store codec settings for codec number "codeCntr" in the output struct
ACMCodecDB::Codec(codecCntr, &codec);
if(!STR_CASE_CMP(codec.plname, payloadName))
{
// If samplingFreqHz is set (!= -1), check if frequency matches
if((samplingFreqHz == codec.plfreq) || (samplingFreqHz == -1))
{
// We found a match, return OK
return 0;
}
}
}
// if we are here we couldn't find anything
// set the params to unacceptable values
codec.plname[0] = '\0';
codec.pltype = -1;
codec.pacsize = 0;
codec.rate = 0;
codec.plfreq = 0;
return -1;
}
// Get supported codec Index with name, and frequency if needed
WebRtc_Word32
AudioCodingModule::Codec(
const WebRtc_Word8* payloadName,
const WebRtc_Word32 samplingFreqHz)
{
WEBRTC_TRACE(webrtc::kTraceModuleCall, webrtc::kTraceAudioCoding, -1,
"Codec(const WebRtc_Word8* payloadName)");
ACMCodecDB::initACMCodecDB();
CodecInst codec;
// Search through codec list for a matching name
for(WebRtc_Word16 codecCntr = 0; codecCntr < ACMCodecDB::NoOfCodecs();
codecCntr++)
{
// Temporally store codec settings for codec number "codeCntr" in "codec"
ACMCodecDB::Codec(codecCntr, &codec);
if(!STR_CASE_CMP(codec.plname, payloadName))
{
// If samplingFreqHz is set (!= -1), check if frequency matches
if((samplingFreqHz == codec.plfreq) || (samplingFreqHz == -1))
{
// We found a match, return codec list number (index)
return codecCntr;
}
}
}
// We did not find a matching codec in the list
return -1;
}
// Checks the validity of the parameters of the given codec
bool
AudioCodingModule::IsCodecValid(
const CodecInst& codec)
{
WebRtc_Word16 mirrorID;
WebRtc_Word8 errMsg[500];
WEBRTC_TRACE(webrtc::kTraceModuleCall, webrtc::kTraceAudioCoding, -1,
"IsCodecValid(const CodecInst& codec)");
ACMCodecDB::initACMCodecDB();
WebRtc_Word16 codecNumber = ACMCodecDB::CodecNumber(&codec, mirrorID, errMsg, 500);
if(codecNumber < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, -1, errMsg);
return false;
}
else
{
return true;
}
}
} // namespace webrtc

View File

@@ -0,0 +1,138 @@
# 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.
{
'includes': [
'../../../../common_settings.gypi', # Common settings
],
'targets': [
{
'target_name': 'audio_coding_module',
'type': '<(library)',
'dependencies': [
'../../codecs/CNG/main/source/cng.gyp:CNG',
'../../codecs/G711/main/source/g711.gyp:G711',
'../../codecs/G722/main/source/g722.gyp:G722',
'../../codecs/iLBC/main/source/ilbc.gyp:iLBC',
'../../codecs/iSAC/main/source/isac.gyp:iSAC',
'../../codecs/iSAC/fix/source/isacfix.gyp:iSACFix',
'../../codecs/PCM16B/main/source/pcm16b.gyp:PCM16B',
'../../NetEQ/main/source/neteq.gyp:NetEq',
'../../../../common_audio/resampler/main/source/resampler.gyp:resampler',
'../../../../common_audio/signal_processing_library/main/source/spl.gyp:spl',
'../../../../common_audio/vad/main/source/vad.gyp:vad',
'../../../../system_wrappers/source/system_wrappers.gyp:system_wrappers',
],
'include_dirs': [
'../interface',
'../../../interface',
],
'direct_dependent_settings': {
'include_dirs': [
'../interface',
'../../../interface',
],
},
'sources': [
# TODO: Remove files from here and P4 when ACM is slimmed down.
'../interface/audio_coding_module.h',
'../interface/audio_coding_module_typedefs.h',
'acm_amr.cc',
'acm_amr.h',
'acm_amrwb.cc',
'acm_amrwb.h',
'acm_cng.cc',
'acm_cng.h',
'acm_codec_database.cc',
'acm_codec_database.h',
'acm_dtmf_detection.cc',
'acm_dtmf_detection.h',
'acm_dtmf_playout.cc',
'acm_dtmf_playout.h',
'acm_g722.cc',
'acm_g722.h',
'acm_g7221.cc',
'acm_g7221.h',
'acm_g7221c.cc',
'acm_g7221c.h',
'acm_g729.cc',
'acm_g729.h',
'acm_g7291.cc',
'acm_g7291.h',
'acm_generic_codec.cc',
'acm_generic_codec.h',
'acm_gsmfr.cc',
'acm_gsmfr.h',
'acm_ilbc.cc',
'acm_ilbc.h',
'acm_isac.cc',
'acm_isac.h',
'acm_isac_macros.h',
'acm_neteq.cc',
'acm_neteq.h',
'acm_opus.cc',
'acm_opus.h',
'acm_speex.cc',
'acm_speex.h',
'acm_pcm16b.cc',
'acm_pcm16b.h',
'acm_pcma.cc',
'acm_pcma.h',
'acm_pcmu.cc',
'acm_pcmu.h',
'acm_red.cc',
'acm_red.h',
'acm_resampler.cc',
'acm_resampler.h',
'audio_coding_module.cc',
'audio_coding_module_impl.cc',
'audio_coding_module_impl.h',
],
},
{
'target_name': 'audio_coding_module_test',
'type': 'executable',
'dependencies': [
'audio_coding_module',
'../../../../system_wrappers/source/system_wrappers.gyp:system_wrappers',
],
'sources': [
'../test/ACMTest.cpp',
'../test/APITest.cpp',
'../test/Channel.cpp',
'../test/EncodeDecodeTest.cpp',
'../test/EncodeToFileTest.cpp',
'../test/iSACTest.cpp',
'../test/PCMFile.cpp',
'../test/RTPFile.cpp',
'../test/SpatialAudio.cpp',
'../test/TestAllCodecs.cpp',
'../test/Tester.cpp',
'../test/TestFEC.cpp',
'../test/TestStereo.cpp',
'../test/TestVADDTX.cpp',
'../test/TimedTrace.cpp',
'../test/TwoWayCommunication.cpp',
'../test/utility.cpp',
],
'conditions': [
['OS=="linux"', {
'cflags': [
'-fexceptions', # enable exceptions
],
}],
],
},
],
}
# Local Variables:
# tab-width:2
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=2 shiftwidth=2:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,400 @@
/*
* 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 AUDIO_CODING_MODULE_IMPL_H
#define AUDIO_CODING_MODULE_IMPL_H
#include "acm_codec_database.h"
#include "acm_neteq.h"
#include "acm_resampler.h"
#include "common_types.h"
#include "engine_configurations.h"
namespace webrtc {
class ACMDTMFDetection;
class ACMGenericCodec;
class CriticalSectionWrapper;
class RWLockWrapper;
//#define TIMED_LOGGING
#ifdef TIMED_LOGGING
#include "../test/timedtrace.h"
#endif
#ifdef ACM_QA_TEST
# include <stdio.h>
#endif
class AudioCodingModuleImpl : public AudioCodingModule
{
public:
// constructor
AudioCodingModuleImpl(
const WebRtc_Word32 id);
// destructor
~AudioCodingModuleImpl();
// get version information for ACM and all components
WebRtc_Word32 Version(
WebRtc_Word8* version,
WebRtc_UWord32& remainingBufferInBytes,
WebRtc_UWord32& position) const;
// change the unique identifier of this object
virtual WebRtc_Word32 ChangeUniqueId(
const WebRtc_Word32 id);
// returns the number of milliseconds until the module want
// a worker thread to call Process
WebRtc_Word32 TimeUntilNextProcess();
// Process any pending tasks such as timeouts
WebRtc_Word32 Process();
// used in conference to go to and from active encoding, hence
// in and out of mix
WebRtc_Word32 SetMode(
const bool passive);
/////////////////////////////////////////
// Sender
//
// initialize send codec
WebRtc_Word32 InitializeSender();
// reset send codec
WebRtc_Word32 ResetEncoder();
// can be called multiple times for Codec, CNG, RED
WebRtc_Word32 RegisterSendCodec(
const CodecInst& sendCodec);
// get current send codec
WebRtc_Word32 SendCodec(
CodecInst& currentSendCodec) const;
// get current send freq
WebRtc_Word32 SendFrequency() const;
// Get encode bitrate
// Adaptive rate codecs return their current encode target rate, while other codecs
// return there longterm avarage or their fixed rate.
WebRtc_Word32 SendBitrate() const;
// set available bandwidth, inform the encoder about the
// estimated bandwidth received from the remote party
virtual WebRtc_Word32 SetReceivedEstimatedBandwidth(
const WebRtc_Word32 bw);
// register a transport callback which will be
// called to deliver the encoded buffers
WebRtc_Word32 RegisterTransportCallback(
AudioPacketizationCallback* transport);
// Used by the module to deliver messages to the codec module/application
// AVT(DTMF)
WebRtc_Word32 RegisterIncomingMessagesCallback(
AudioCodingFeedback* incomingMessagesCallback,
const ACMCountries cpt);
// Add 10MS of raw (PCM) audio data to the encoder
WebRtc_Word32 Add10MsData(
const AudioFrame& audioFrame);
// set background noise mode for NetEQ, on, off or fade
WebRtc_Word32 SetBackgroundNoiseMode(
const ACMBackgroundNoiseMode mode);
// get current background noise mode
WebRtc_Word32 BackgroundNoiseMode(
ACMBackgroundNoiseMode& mode);
/////////////////////////////////////////
// (FEC) Forward Error Correction
//
// configure FEC status i.e on/off
WebRtc_Word32 SetFECStatus(
const bool enable);
// Get FEC status
bool FECStatus() const;
/////////////////////////////////////////
// (VAD) Voice Activity Detection
// and
// (CNG) Comfort Noise Generation
//
WebRtc_Word32 SetVAD(
const bool enableDTX = true,
const bool enableVAD = false,
const ACMVADMode vadMode = VADNormal);
WebRtc_Word32 VAD(
bool& dtxEnabled,
bool& vadEnabled,
ACMVADMode& vadMode) const;
WebRtc_Word32 RegisterVADCallback(
ACMVADCallback* vadCallback);
// Get VAD status on the incoming stream
bool ReceiveVADStatus() const;
// configure VAD status i.e on/off on the incoming stream
WebRtc_Word16 SetReceiveVADStatus(
const bool enable);
// Get VAD aggressiveness on the incoming stream
ACMVADMode ReceiveVADMode() const;
// Configure VAD aggressiveness on the incoming stream
WebRtc_Word16 SetReceiveVADMode(
const ACMVADMode mode);
/////////////////////////////////////////
// Receiver
//
// initialize receiver, resets codec database etc
WebRtc_Word32 InitializeReceiver();
// reset the decoder state
WebRtc_Word32 ResetDecoder();
// get current receive freq
WebRtc_Word32 ReceiveFrequency() const;
// get current playout freq
WebRtc_Word32 PlayoutFrequency() const;
// register possible reveive codecs, can be called multiple times,
// for codecs, CNG, DTMF, RED
WebRtc_Word32 RegisterReceiveCodec(
const CodecInst& receiveCodec);
// get current received codec
WebRtc_Word32 ReceiveCodec(
CodecInst& currentReceiveCodec) const;
// incoming packet from network parsed and ready for decode
WebRtc_Word32 IncomingPacket(
const WebRtc_Word8* incomingPayload,
const WebRtc_Word32 payloadLength,
const WebRtcRTPHeader& rtpInfo);
// Incoming payloads, without rtp-info, the rtp-info will be created in ACM.
// One usage for this API is when pre-encoded files are pushed in ACM.
WebRtc_Word32 IncomingPayload(
const WebRtc_Word8* incomingPayload,
const WebRtc_Word32 payloadLength,
const WebRtc_UWord8 payloadType,
const WebRtc_UWord32 timestamp = 0);
// Minimum playout dealy (Used for lip-sync)
WebRtc_Word32 SetMinimumPlayoutDelay(
const WebRtc_Word32 timeMs);
// current play out delay
WebRtc_Word32 Delay(WebRtc_UWord16& delayMs) const;
// configure Dtmf playout status i.e on/off playout the incoming outband Dtmf tone
WebRtc_Word32 SetDtmfPlayoutStatus(
const bool enable);
// Get Dtmf playout status
bool DtmfPlayoutStatus() const;
// Estimate the Bandwidth based on the incoming stream
// This is also done in the RTP module
// need this for one way audio where the RTCP send the BW estimate
WebRtc_Word32 DecoderEstimatedBandwidth() const;
// Set playout mode voice, fax
WebRtc_Word32 SetPlayoutMode(
const AudioPlayoutMode mode);
// Get playout mode voice, fax
AudioPlayoutMode PlayoutMode() const;
// Get playout timestamp
WebRtc_Word32 PlayoutTimestamp(
WebRtc_UWord32& timestamp);
// Get 10 milliseconds of raw audio data to play out
// automatic resample to the requested frequency if > 0
WebRtc_Word32 PlayoutData10Ms(
const WebRtc_Word32 desiredFreqHz,
AudioFrame &audioFrame);
/////////////////////////////////////////
// Statistics
//
WebRtc_Word32 NetworkStatistics(
ACMNetworkStatistics& statistics) const;
WebRtc_Word32 JitterStatistics(
ACMJitterStatistics& jitterStatistics) const;
WebRtc_Word32 PreferredBufferSize(
WebRtc_UWord16& prefbufsize) const;
WebRtc_Word32 ResetJitterStatistics() const;
void DestructEncoderInst(void* ptrInst);
WebRtc_Word16 AudioBuffer(WebRtcACMAudioBuff& audioBuff);
// GET RED payload for iSAC. The method id called
// when 'this' ACM is default ACM.
WebRtc_Word32 REDPayloadISAC(
const WebRtc_Word32 isacRate,
const WebRtc_Word16 isacBwEstimate,
WebRtc_UWord8* payload,
WebRtc_Word16* payloadLenByte);
WebRtc_Word16 SetAudioBuffer(WebRtcACMAudioBuff& audioBuff);
WebRtc_UWord32 EarliestTimestamp() const;
WebRtc_Word32 LastEncodedTimestamp(WebRtc_UWord32& timestamp) const;
WebRtc_Word32 ReplaceInternalDTXWithWebRtc(
const bool useWebRtcDTX);
WebRtc_Word32 IsInternalDTXReplacedWithWebRtc(
bool& usesWebRtcDTX);
WebRtc_Word32 SetISACMaxRate(
const WebRtc_UWord32 rateBitPerSec);
WebRtc_Word32 SetISACMaxPayloadSize(
const WebRtc_UWord16 payloadLenBytes);
WebRtc_Word32 ConfigISACBandwidthEstimator(
const WebRtc_UWord8 initFrameSizeMsec,
const WebRtc_UWord16 initRateBitPerSec,
const bool enforceFrameSize = false);
WebRtc_Word32 UnregisterReceiveCodec(
const WebRtc_Word16 payloadType);
protected:
void UnregisterSendCodec();
WebRtc_Word32 UnregisterReceiveCodecSafe(
const WebRtc_Word16 codecID);
ACMGenericCodec* CreateCodec(
const CodecInst& codec);
WebRtc_Word16 DecoderParamByPlType(
const WebRtc_UWord8 payloadType,
WebRtcACMCodecParams& codecParams) const;
WebRtc_Word16 DecoderListIDByPlName(
const WebRtc_Word8* payloadName,
const WebRtc_UWord16 sampFreqHz = 0) const;
WebRtc_Word32 InitializeReceiverSafe();
bool HaveValidEncoder(const WebRtc_Word8* callerName) const;
WebRtc_Word32 RegisterRecCodecMSSafe(
const CodecInst& receiveCodec,
WebRtc_Word16 codecId,
WebRtc_Word16 mirrorId,
ACMNetEQ::JB jitterBuffer);
private:
AudioPacketizationCallback* _packetizationCallback;
WebRtc_Word32 _id;
WebRtc_UWord32 _lastTimestamp;
WebRtc_UWord32 _lastInTimestamp;
CodecInst _sendCodecInst;
CodecInst _cngNB;
CodecInst _cngWB;
CodecInst _cngSWB;
CodecInst _RED;
bool _REDRegistered;
CodecInst _DTMF;
bool _DTMFRegistered;
bool _vadEnabled;
bool _dtxEnabled;
ACMVADMode _vadMode;
ACMGenericCodec* _codecs[MAX_NR_OF_CODECS];
ACMGenericCodec* _slaveCodecs[MAX_NR_OF_CODECS];
WebRtc_Word16 _mirrorCodecIdx[MAX_NR_OF_CODECS];
bool _stereoReceive[MAX_NR_OF_CODECS];
bool _stereoSend;
WebRtc_Word32 _currentSendCodecIdx;
bool _sendCodecRegistered;
ACMResampler _inputResampler;
ACMResampler _outputResampler;
ACMNetEQ _netEq;
CriticalSectionWrapper* _acmCritSect;
ACMVADCallback* _vadCallback;
WebRtc_UWord8 _lastRecvAudioCodecPlType;
// RED/FEC
bool _isFirstRED;
bool _fecEnabled;
WebRtc_UWord8* _redBuffer;
RTPFragmentationHeader* _fragmentation;
WebRtc_UWord32 _lastFECTimestamp;
WebRtc_UWord8 _redPayloadType;
// if no RED is registered as receive codec this
// will have an invalid value.
WebRtc_UWord8 _receiveREDPayloadType;
// This is to keep track of CN instances where we can send DTMFs
WebRtc_UWord8 _previousPayloadType;
// This keeps track of payload types associated with _codecs[].
// We define it as signed variable and initialize with -1 to indicate
// unused elements.
WebRtc_Word16 _registeredPlTypes[MAX_NR_OF_CODECS];
// Used when payloads are pushed into ACM without any RTP info
// One example is when pre-encoded bit-stream is pushed from
// a file.
WebRtcRTPHeader* _dummyRTPHeader;
WebRtc_UWord16 _recvPlFrameSizeSmpls;
bool _receiverInitialized;
ACMDTMFDetection* _dtmfDetector;
AudioCodingFeedback* _dtmfCallback;
WebRtc_Word16 _lastDetectedTone;
CriticalSectionWrapper* _callbackCritSect;
#ifdef TIMED_LOGGING
TimedTrace _trace;
#endif
#ifdef ACM_QA_TEST
FILE* _outgoingPL;
FILE* _incomingPL;
#endif
};
} // namespace webrtc
#endif

View File

@@ -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()
{
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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];
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

Binary file not shown.

Binary file not shown.

View File

@@ -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;
}

View File

@@ -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