Fix echo issue on WP8

This commit is contained in:
bossiel 2014-11-16 19:40:20 +00:00
parent 67d37f7e24
commit e3fe08a09f
116 changed files with 2888 additions and 3138 deletions

View File

@ -38,14 +38,14 @@ m_nFrameDuration(nFrameDuration),
m_nChannels(nChannels),
m_nQuality(nQuality)
{
if((m_pWrappedResampler = tmedia_resampler_create())){
if ((m_pWrappedResampler = tmedia_resampler_create())) {
int ret;
if((ret = tmedia_resampler_open(m_pWrappedResampler, nInFreq, nOutFreq, nFrameDuration, nChannels, nChannels, m_nQuality))){
if ((ret = tmedia_resampler_open(m_pWrappedResampler, nInFreq, nOutFreq, nFrameDuration, nChannels, nChannels, m_nQuality, 16))){
TSK_DEBUG_ERROR("Failed to open audio resampler (%d)", ret);
TSK_OBJECT_SAFE_FREE(m_pWrappedResampler);
}
}
else{
else {
TSK_DEBUG_ERROR("No audio resampler could be found. Did you forget to call tdav_init()?");
}
}

View File

@ -255,20 +255,20 @@ uint64_t MediaSessionMgr::getSessionId(twrap_media_type_t media)const
ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
uint64_t id = 0;
if(media != twrap_media_audio && media != twrap_media_video){
if (media != twrap_media_audio && media != twrap_media_video) {
TSK_DEBUG_ERROR("Invalid media type");
return tsk_null;
return 0;
}
if(manager && m_pWrappedMgr){
if (manager && m_pWrappedMgr) {
tmedia_type_t _media = twrap_get_native_media_type(media);
tmedia_session_t* session = tmedia_session_mgr_find(m_pWrappedMgr, _media);
if(session){
if (session) {
id = session->id;
}
tsk_object_unref(session);
}
else{
else {
TSK_DEBUG_ERROR("Invalid state");
}
@ -346,7 +346,7 @@ bool MediaSessionMgr::defaultsSetEchoSkew(uint32_t echo_skew)
bool MediaSessionMgr::defaultsSetEchoSuppEnabled(bool echo_supp_enabled)
{
return tmedia_defaults_set_echo_supp_enabled(echo_supp_enabled) == 0;
return tmedia_defaults_set_echo_supp_enabled(echo_supp_enabled ? tsk_true : tsk_false) == 0;
}
bool MediaSessionMgr::defaultsGetEchoSuppEnabled()

View File

@ -81,7 +81,7 @@ int twrap_consumer_proxy_audio_prepare(tmedia_consumer_t* self, const tmedia_cod
}
}
else {
TSK_DEBUG_ERROR("Invalid parameter/state: codec=%d, manager=%d", codec, manager);
TSK_DEBUG_ERROR("Invalid parameter/state: codec=%d, manager=%d", codec, (int)manager);
}
return ret;

0
branches/2.0/doubango/bindings/autogen.sh Normal file → Executable file
View File

View File

@ -73,6 +73,7 @@ namespace doubango_rt
uint64 getSessionId(rt_twrap_media_type_t media);
internal: // Must be from SIP service to share same global memory space
static bool defaultsSetProfile(rt_tmedia_profile_t profile);
static rt_tmedia_profile_t defaultsGetProfile();
static bool defaultsSetPrefVideoSize(enum class rt_tmedia_pref_video_size_t pref_video_size);

View File

@ -6,7 +6,7 @@
#
AC_PREREQ([2.0])
AC_INIT(libdoubango, 2.0.1158, doubango(at)googlegroups(dot)com)
AC_INIT(libdoubango, 2.0.1181, doubango(at)googlegroups(dot)com)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE([subdir-objects])
AC_CONFIG_MACRO_DIR([m4])

View File

@ -46,8 +46,6 @@
#ifndef _AES_H
#define _AES_H
#include "config.h"
#include "datatypes.h"
#include "gf2_8.h"
#include "err.h"

View File

@ -17,6 +17,8 @@
typedef struct {
v128_t state; /* cipher chaining state */
v128_t previous; /* previous ciphertext block */
uint8_t key[32];
int key_len;
aes_expanded_key_t expanded_key; /* the cipher key */
} aes_cbc_ctx_t;
@ -31,10 +33,10 @@ aes_cbc_encrypt(aes_cbc_ctx_t *c,
err_status_t
aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key,
int key_len, cipher_direction_t dir);
int key_len);
err_status_t
aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv);
aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv, int direction);
err_status_t
aes_cbc_nist_encrypt(aes_cbc_ctx_t *c,

View File

@ -0,0 +1,63 @@
/*
* aes_gcm_ossl.h
*
* Header for AES Galois Counter Mode.
*
* John A. Foley
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2013, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef AES_GCM_OSSL_H
#define AES_GCM_OSSL_H
#include "cipher.h"
#include "srtp.h"
#include <openssl/evp.h>
#include <openssl/aes.h>
typedef struct {
v256_t key;
int key_size;
int tag_len;
EVP_CIPHER_CTX ctx;
cipher_direction_t dir;
} aes_gcm_ctx_t;
#endif /* AES_GCM_OSSL_H */

View File

@ -29,7 +29,7 @@ aes_icm_context_init(aes_icm_ctx_t *c,
int key_len);
err_status_t
aes_icm_set_iv(aes_icm_ctx_t *c, void *iv);
aes_icm_set_iv(aes_icm_ctx_t *c, void *iv, int direction);
err_status_t
aes_icm_encrypt(aes_icm_ctx_t *c,
@ -37,7 +37,7 @@ aes_icm_encrypt(aes_icm_ctx_t *c,
err_status_t
aes_icm_output(aes_icm_ctx_t *c,
unsigned char *buf, int bytes_to_output);
unsigned char *buf, unsigned int bytes_to_output);
err_status_t
aes_icm_dealloc(cipher_t *c);
@ -53,5 +53,8 @@ aes_icm_alloc_ismacryp(cipher_t **c,
int key_len,
int forIsmacryp);
uint16_t
aes_icm_bytes_encrypted(aes_icm_ctx_t *c);
#endif /* AES_ICM_H */

View File

@ -0,0 +1,76 @@
/*
* aes_icm.h
*
* Header for AES Integer Counter Mode.
*
* David A. McGrew
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2001-2005,2012, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef AES_ICM_H
#define AES_ICM_H
#include "cipher.h"
#include <openssl/evp.h>
#include <openssl/aes.h>
#define SALT_SIZE 14
#define AES_128_KEYSIZE AES_BLOCK_SIZE
#define AES_192_KEYSIZE AES_BLOCK_SIZE + AES_BLOCK_SIZE / 2
#define AES_256_KEYSIZE AES_BLOCK_SIZE * 2
#define AES_128_KEYSIZE_WSALT AES_128_KEYSIZE + SALT_SIZE
#define AES_192_KEYSIZE_WSALT AES_192_KEYSIZE + SALT_SIZE
#define AES_256_KEYSIZE_WSALT AES_256_KEYSIZE + SALT_SIZE
typedef struct {
v128_t counter; /* holds the counter value */
v128_t offset; /* initial offset value */
v256_t key;
int key_size;
EVP_CIPHER_CTX ctx;
} aes_icm_ctx_t;
err_status_t aes_icm_openssl_set_iv(aes_icm_ctx_t *c, void *iv, int dir);
err_status_t aes_icm_openssl_context_init(aes_icm_ctx_t *c, const uint8_t *key, int len);
err_status_t aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output);
uint16_t aes_icm_bytes_encrypted(aes_icm_ctx_t *c);
#endif /* AES_ICM_H */

View File

@ -8,7 +8,7 @@
*/
/*
*
* Copyright (c) 2001-2006, Cisco Systems, Inc.
* Copyright (c) 2001-2006,2013 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -80,15 +80,14 @@ typedef struct cipher_t *cipher_pointer_t;
*/
typedef err_status_t (*cipher_alloc_func_t)
(cipher_pointer_t *cp, int key_len);
(cipher_pointer_t *cp, int key_len, int tag_len);
/*
* a cipher_init_func_t [re-]initializes a cipher_t with a given key
* and direction (i.e., encrypt or decrypt)
*/
typedef err_status_t (*cipher_init_func_t)
(void *state, const uint8_t *key, int key_len, cipher_direction_t dir);
(void *state, const uint8_t *key, int key_len);
/* a cipher_dealloc_func_t de-allocates a cipher_t */
@ -99,6 +98,13 @@ typedef err_status_t (*cipher_dealloc_func_t)(cipher_pointer_t cp);
typedef err_status_t (*cipher_set_segment_func_t)
(void *state, xtd_seq_num_t idx);
/*
* a cipher_set_aad_func_t processes the AAD data for AEAD ciphers
*/
typedef err_status_t (*cipher_set_aad_func_t)
(void *state, uint8_t *aad, unsigned int aad_len);
/* a cipher_encrypt_func_t encrypts data in-place */
typedef err_status_t (*cipher_encrypt_func_t)
@ -114,7 +120,15 @@ typedef err_status_t (*cipher_decrypt_func_t)
*/
typedef err_status_t (*cipher_set_iv_func_t)
(cipher_pointer_t cp, void *iv);
(cipher_pointer_t cp, void *iv, cipher_direction_t direction);
/*
* a cipher_get_tag_funct_t function is used to get the authentication
* tag that was calculated by an AEAD cipher.
*/
typedef err_status_t (*cipher_get_tag_func_t)
(void *state, void *tag, int *len);
/*
* cipher_test_case_t is a (list of) key, salt, xtd_seq_num_t,
@ -132,6 +146,9 @@ typedef struct cipher_test_case_t {
uint8_t *plaintext; /* plaintext */
int ciphertext_length_octets; /* octets in plaintext */
uint8_t *ciphertext; /* ciphertext */
int aad_length_octets; /* octets in AAD */
uint8_t *aad; /* AAD */
int tag_length_octets; /* Length of AEAD tag */
struct cipher_test_case_t *next_test_case; /* pointer to next testcase */
} cipher_test_case_t;
@ -141,9 +158,11 @@ typedef struct cipher_type_t {
cipher_alloc_func_t alloc;
cipher_dealloc_func_t dealloc;
cipher_init_func_t init;
cipher_set_aad_func_t set_aad;
cipher_encrypt_func_t encrypt;
cipher_encrypt_func_t decrypt;
cipher_set_iv_func_t set_iv;
cipher_get_tag_func_t get_tag;
char *description;
int ref_count;
cipher_test_case_t *test_data;
@ -160,27 +179,32 @@ typedef struct cipher_t {
cipher_type_t *type;
void *state;
int key_len;
#ifdef FORCE_64BIT_ALIGN
int pad;
#endif
int algorithm;
} cipher_t;
/* some syntactic sugar on these function types */
#define cipher_type_alloc(ct, c, klen) ((ct)->alloc((c), (klen)))
#define cipher_type_alloc(ct, c, klen, tlen) ((ct)->alloc((c), (klen), (tlen)))
#define cipher_dealloc(c) (((c)->type)->dealloc(c))
#define cipher_init(c, k, dir) (((c)->type)->init(((c)->state), (k), ((c)->key_len), (dir)))
#define cipher_init(c, k) (((c)->type)->init(((c)->state), (k), ((c)->key_len)))
#define cipher_encrypt(c, buf, len) \
(((c)->type)->encrypt(((c)->state), (buf), (len)))
#define cipher_get_tag(c, buf, len) \
(((c)->type)->get_tag(((c)->state), (buf), (len)))
#define cipher_decrypt(c, buf, len) \
(((c)->type)->decrypt(((c)->state), (buf), (len)))
#define cipher_set_iv(c, n) \
((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)->state), (n))) : \
#define cipher_set_iv(c, n, dir) \
((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)->state), (n), (dir))) : \
err_status_no_such_op)
#define cipher_set_aad(c, a, l) \
(((c) && (((c)->type)->set_aad)) ? \
(((c)->type)->set_aad(((c)->state), (a), (l))) : \
err_status_no_such_op)
err_status_t

View File

@ -221,7 +221,8 @@ crypto_kernel_load_debug_module(debug_module_t *new_dm);
err_status_t
crypto_kernel_alloc_cipher(cipher_type_id_t id,
cipher_pointer_t *cp,
int key_len);
int key_len,
int tag_len);
/*
* crypto_kernel_alloc_auth(id, ap, key_len, tag_len);

View File

@ -8,7 +8,7 @@
*/
/*
*
* Copyright(c) 2001-2006 Cisco Systems, Inc.
* Copyright(c) 2001-2006,2013 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -141,6 +141,34 @@
*/
#define STRONGHOLD_CIPHER AES_ICM
/**
* @brief AES-192 Integer Counter Mode (AES ICM)
* AES-192 ICM is a deprecated alternate name for AES ICM.
*/
#define AES_192_ICM 4
/**
* @brief AES-256 Integer Counter Mode (AES ICM)
* AES-256 ICM is a deprecated alternate name for AES ICM.
*/
#define AES_256_ICM 5
/**
* @brief AES-128_GCM Galois Counter Mode (AES GCM)
*
* AES-128 GCM is the variant of galois counter mode that is used by
* Secure RTP. This cipher uses a 16-octet key.
*/
#define AES_128_GCM 6
/**
* @brief AES-256_GCM Galois Counter Mode (AES GCM)
*
* AES-256 GCM is the variant of galois counter mode that is used by
* Secure RTP. This cipher uses a 32-octet key.
*/
#define AES_256_GCM 7
/**
* @}
*/

View File

@ -92,6 +92,12 @@ typedef union {
uint64_t v64[2];
} v128_t;
typedef union {
uint8_t v8[32];
uint16_t v16[16];
uint32_t v32[8];
uint64_t v64[4];
} v256_t;
/* some useful and simple math functions */
@ -377,7 +383,7 @@ void
octet_string_set_to_zero(uint8_t *s, int len);
#ifndef SRTP_KERNEL_LINUX
#if !defined(SRTP_KERNEL_LINUX) && defined(HAVE_CONFIG_H)
/*
* Convert big endian integers to CPU byte order.
@ -409,7 +415,7 @@ static inline uint32_t be32_to_cpu(uint32_t v) {
# define be32_to_cpu(x) ntohl((x))
# endif /* HAVE_X86 */
static __inline uint64_t be64_to_cpu(uint64_t v) {
static inline uint64_t be64_to_cpu(uint64_t v) {
# ifdef NO_64BIT_MATH
/* use the make64 functions to do 64-bit math */
v = make64(htonl(low32(v)),htonl(high32(v)));
@ -503,4 +509,8 @@ bitvector_left_shift(bitvector_t *x, int index);
char *
bitvector_bit_string(bitvector_t *x, char* buf, int len);
#ifdef TESTAPP_SOURCE
int base64_string_to_octet_string(char *raw, int *pad, char *base64, int len);
#endif
#endif /* _DATATYPES_H */

View File

@ -46,7 +46,8 @@
#ifndef ERR_H
#define ERR_H
#include "datatypes.h"
#include <stdio.h>
#include <stdarg.h>
/**
* @defgroup Error Error Codes
@ -87,7 +88,7 @@ typedef enum {
err_status_nonce_bad = 18, /**< nonce check failed */
err_status_read_fail = 19, /**< couldn't read data */
err_status_write_fail = 20, /**< couldn't write data */
err_status_parse_err = 21, /**< error pasring data */
err_status_parse_err = 21, /**< error parsing data */
err_status_encode_err = 22, /**< error encoding data */
err_status_semaphore_err = 23,/**< error while using semaphores */
err_status_pfkey_err = 24 /**< error while using pfkey */
@ -118,7 +119,7 @@ typedef enum {
*/
err_status_t
err_reporting_init(char *ident);
err_reporting_init(const char *ident);
#ifdef SRTP_KERNEL_LINUX
extern err_reporting_level_t err_level;
@ -135,7 +136,7 @@ extern err_reporting_level_t err_level;
*/
void
err_report(int priority, char *format, ...);
err_report(int priority, const char *format, ...);
#endif /* ! SRTP_KERNEL_LINUX */
@ -145,7 +146,7 @@ err_report(int priority, char *format, ...);
typedef struct {
int on; /* 1 if debugging is on, 0 if it is off */
char *name; /* printable name for debug module */
const char *name; /* printable name for debug module */
} debug_module_t;
#ifdef ENABLE_DEBUGGING

View File

@ -9,7 +9,7 @@
*/
/*
*
* Copyright (c) 2001-2006, Cisco Systems, Inc.
* Copyright (c) 2001-2006,2013, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -53,6 +53,10 @@ typedef struct {
uint8_t opad[64];
sha1_ctx_t ctx;
sha1_ctx_t init_ctx;
#ifdef OPENSSL
int ctx_initialized;
int init_ctx_initialized;
#endif
} hmac_ctx_t;
err_status_t

View File

@ -47,7 +47,6 @@
#ifndef INTEGERS_H
#define INTEGERS_H
#include "config.h" /* configuration file, using autoconf */
#ifdef SRTP_KERNEL
@ -76,7 +75,7 @@
#endif
/* Can we do 64 bit integers? */
#ifndef HAVE_UINT64_T
#if !defined(HAVE_UINT64_T)
# if SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long uint64_t;
# elif SIZEOF_UNSIGNED_LONG_LONG == 8
@ -99,7 +98,7 @@ typedef unsigned int uint32_t;
#endif
#ifdef NO_64BIT_MATH
#if defined(NO_64BIT_MATH) && defined(HAVE_CONFIG_H)
typedef double uint64_t;
/* assert that sizeof(double) == 8 */
extern uint64_t make64(uint32_t high, uint32_t low);

View File

@ -12,7 +12,12 @@
#include "rand_source.h" /* for rand_source_func_t definition */
#include "aes.h" /* for aes */
//FIXME: this is temporary until we pull in the code to use OpenSSL for RNG
#ifdef OPENSSL
#include "aes_icm_ossl.h" /* for aes ctr */
#else
#include "aes_icm.h" /* for aes ctr */
#endif
#define MAX_PRNG_OUT_LEN 0xffffffffU

View File

@ -48,6 +48,44 @@
#define SHA1_H
#include "err.h"
#ifdef OPENSSL
#include <openssl/evp.h>
#include <stdint.h>
typedef EVP_MD_CTX sha1_ctx_t;
/*
* sha1_init(&ctx) initializes the SHA1 context ctx
*
* sha1_update(&ctx, msg, len) hashes the len octets starting at msg
* into the SHA1 context
*
* sha1_final(&ctx, output) performs the final processing of the SHA1
* context and writes the result to the 20 octets at output
*
* Return values are ignored on the EVP functions since all three
* of these functions return void.
*
*/
inline void sha1_init (sha1_ctx_t *ctx)
{
EVP_MD_CTX_init(ctx);
EVP_DigestInit(ctx, EVP_sha1());
}
inline void sha1_update (sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg)
{
EVP_DigestUpdate(ctx, M, octets_in_msg);
}
inline void sha1_final (sha1_ctx_t *ctx, uint32_t *output)
{
unsigned int len = 0;
EVP_DigestFinal(ctx, (unsigned char*)output, &len);
}
#else
#include "datatypes.h"
typedef struct {
@ -104,5 +142,7 @@ sha1_final(sha1_ctx_t *ctx, uint32_t output[5]);
void
sha1_core(const uint32_t M[16], uint32_t hash_value[5]);
#endif /* else OPENSSL */
#endif /* SHA1_H */

View File

@ -50,7 +50,10 @@
extern "C" {
#endif
#include "crypto_kernel.h"
#include <stdint.h>
#include "crypto.h"
#include "crypto_types.h"
#include "err.h"
/**
* @defgroup SRTP Secure RTP
@ -88,6 +91,18 @@ extern "C" {
*/
#define SRTP_MAX_TRAILER_LEN SRTP_MAX_TAG_LEN
/*
* SRTP_AEAD_SALT_LEN is the length of the SALT values used with
* GCM mode. GCM mode requires an IV. The SALT value is used
* as part of the IV formation logic applied to each RTP packet.
*/
#define SRTP_AEAD_SALT_LEN 12
#define AES_128_GCM_KEYSIZE_WSALT SRTP_AEAD_SALT_LEN + 16
#define AES_192_GCM_KEYSIZE_WSALT SRTP_AEAD_SALT_LEN + 24
#define AES_256_GCM_KEYSIZE_WSALT SRTP_AEAD_SALT_LEN + 32
/*
* nota bene: since libSRTP doesn't support the use of the MKI, the
* SRTP_MAX_TRAILER_LEN value is just the maximum tag length
@ -304,6 +319,11 @@ srtp_shutdown(void);
* packet, and assumes that the RTP packet is aligned on a 32-bit
* boundary.
*
* @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN
* into the location in memory immediately following the RTP packet.
* Callers MUST ensure that this much writable memory is available in
* the buffer that holds the RTP packet.
*
* @param ctx is the SRTP context to use in processing the packet.
*
* @param rtp_hdr is a pointer to the RTP packet (before the call); after
@ -342,8 +362,7 @@ srtp_protect(srtp_t ctx, void *rtp_hdr, int *len_ptr);
* @warning This function assumes that the SRTP packet is aligned on a
* 32-bit boundary.
*
* @param ctx is a pointer to the srtp_t which applies to the
* particular packet.
* @param ctx is the SRTP session which applies to the particular packet.
*
* @param srtp_hdr is a pointer to the header of the SRTP packet
* (before the call). after the function returns, it points to the
@ -376,7 +395,8 @@ srtp_unprotect(srtp_t ctx, void *srtp_hdr, int *len_ptr);
* initializes an SRTP session context, applying the given policy and
* key.
*
* @param session is the SRTP session to which the policy is to be added.
* @param session is a pointer to the SRTP session to which the policy is
* to be added.
*
* @param policy is the srtp_policy_t struct that describes the policy
* for the session. The struct may be a single element, or it may be
@ -658,6 +678,178 @@ void crypto_policy_set_aes_cm_256_hmac_sha1_80(crypto_policy_t *p);
void
crypto_policy_set_aes_cm_256_hmac_sha1_32(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_cm_256_null_auth() sets a crypto
* policy structure to an encryption-only policy
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_cm_256_null_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-256 Counter Mode), but to use no authentication method. This
* policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5
* of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt).
*
* This function is a convenience that helps to avoid dealing directly
* with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that
* include more elements in the crypto_policy_t datatype.
*
* @warning This policy is NOT RECOMMENDED for SRTP unless it is
* unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see
* Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt).
*
* @return void.
*
*/
void
crypto_policy_set_aes_cm_256_null_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_128_8_auth() sets a crypto
* policy structure to an AEAD encryption policy.
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_128_8_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-128 Galois Counter Mode) with 8 octet auth tag. This
* policy applies confidentiality and authentication to both the
* RTP and RTCP packets.
*
* This function is a convenience that helps to avoid dealing directly
* with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that
* include more elements in the crypto_policy_t datatype.
*
* @return void.
*
*/
void
crypto_policy_set_aes_gcm_128_8_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_256_8_auth() sets a crypto
* policy structure to an AEAD encryption policy
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_256_8_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-256 Galois Counter Mode) with 8 octet auth tag. This
* policy applies confidentiality and authentication to both the
* RTP and RTCP packets.
*
* This function is a convenience that helps to avoid dealing directly
* with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that
* include more elements in the crypto_policy_t datatype.
*
* @return void.
*
*/
void
crypto_policy_set_aes_gcm_256_8_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_128_8_only_auth() sets a crypto
* policy structure to an AEAD authentication-only policy
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_128_8_only_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-128 Galois Counter Mode) with 8 octet auth tag. This policy
* applies confidentiality and authentication to the RTP packets,
* but only authentication to the RTCP packets.
*
* This function is a convenience that helps to avoid dealing directly
* with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that
* include more elements in the crypto_policy_t datatype.
*
* @return void.
*
*/
void
crypto_policy_set_aes_gcm_128_8_only_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_256_8_only_auth() sets a crypto
* policy structure to an AEAD authentication-only policy
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_256_8_only_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-256 Galois Counter Mode) with 8 octet auth tag. This policy
* applies confidentiality and authentication to the RTP packets,
* but only authentication to the RTCP packets.
*
* This function is a convenience that helps to avoid dealing directly
* with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that
* include more elements in the crypto_policy_t datatype.
*
* @return void.
*
*/
void
crypto_policy_set_aes_gcm_256_8_only_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_128_16_auth() sets a crypto
* policy structure to an AEAD encryption policy.
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_128_16_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-128 Galois Counter Mode) with 16 octet auth tag. This
* policy applies confidentiality and authentication to both the
* RTP and RTCP packets.
*
* This function is a convenience that helps to avoid dealing directly
* with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that
* include more elements in the crypto_policy_t datatype.
*
* @return void.
*
*/
void
crypto_policy_set_aes_gcm_128_16_auth(crypto_policy_t *p);
/**
* @brief crypto_policy_set_aes_gcm_256_16_auth() sets a crypto
* policy structure to an AEAD encryption policy
*
* @param p is a pointer to the policy structure to be set
*
* The function call crypto_policy_set_aes_gcm_256_16_auth(&p) sets
* the crypto_policy_t at location p to use the SRTP default cipher
* (AES-256 Galois Counter Mode) with 16 octet auth tag. This
* policy applies confidentiality and authentication to both the
* RTP and RTCP packets.
*
* This function is a convenience that helps to avoid dealing directly
* with the policy data structure. You are encouraged to initialize
* policy elements with this function call. Doing so may allow your
* code to be forward compatible with later versions of libSRTP that
* include more elements in the crypto_policy_t datatype.
*
* @return void.
*
*/
void
crypto_policy_set_aes_gcm_256_16_auth(crypto_policy_t *p);
/**
* @brief srtp_dealloc() deallocates storage for an SRTP session
@ -823,6 +1015,11 @@ append_salt_to_key(unsigned char *key, unsigned int bytes_in_key,
* packet, and assumes that the RTCP packet is aligned on a 32-bit
* boundary.
*
* @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4
* into the location in memory immediately following the RTCP packet.
* Callers MUST ensure that this much writable memory is available in
* the buffer that holds the RTCP packet.
*
* @param ctx is the SRTP context to use in processing the packet.
*
* @param rtcp_hdr is a pointer to the RTCP packet (before the call); after
@ -890,6 +1087,57 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len);
* @}
*/
/**
* @defgroup User data associated to a SRTP session.
* @ingroup SRTP
*
* @brief Store custom user data within a SRTP session.
*
* @{
*/
/**
* @brief srtp_set_user_data() stores the given pointer into the SRTP
* session for later retrieval.
*
* @param ctx is the srtp_t context in which the given data pointer is
* stored.
*
* @param data is a pointer to the custom information (struct, function,
* etc) associated with the SRTP session.
*
* @return void.
*
*/
void
srtp_set_user_data(srtp_t ctx, void *data);
/**
* @brief srtp_get_user_data() retrieves the pointer to the custom data
* previously stored with srtp_set_user_data().
*
* This function is mostly useful for retrieving data associated to a
* SRTP session when an event fires. The user can then get such a custom
* data by calling this function with the session field of the
* srtp_event_data_t struct as argument.
*
* @param ctx is the srtp_t context in which the given data pointer was
* stored.
*
* @return void* pointer to the user data.
*
*/
void*
srtp_get_user_data(srtp_t ctx);
/**
* @}
*/
/**
* @defgroup SRTPevents SRTP events and callbacks
* @ingroup SRTP
@ -990,6 +1238,18 @@ typedef void (srtp_event_handler_func_t)(srtp_event_data_t *data);
err_status_t
srtp_install_event_handler(srtp_event_handler_func_t func);
/**
* @brief Returns the version string of the library.
*
*/
const char *srtp_get_version_string(void);
/**
* @brief Returns the numeric representation of the library version.
*
*/
unsigned int srtp_get_version(void);
/**
* @}
*/

View File

@ -45,10 +45,20 @@
#ifndef SRTP_PRIV_H
#define SRTP_PRIV_H
#include "config.h"
#include "srtp.h"
#include "rdbx.h"
#include "rdb.h"
#include "integers.h"
#include "crypto.h"
#include "cipher.h"
#include "auth.h"
#include "aes.h"
#include "key.h"
#include "crypto_kernel.h"
#define SRTP_VER_STRING PACKAGE_STRING
#define SRTP_VERSION PACKAGE_VERSION
/*
* an srtp_hdr_t represents the srtp header
@ -88,7 +98,7 @@ typedef struct {
unsigned char x:1; /* header extension flag */
unsigned char cc:4; /* CSRC count */
unsigned char m:1; /* marker bit */
unsigned pt:7; /* payload type */
unsigned char pt:7; /* payload type */
uint16_t seq; /* sequence number */
uint32_t ts; /* timestamp */
uint32_t ssrc; /* synchronization source */
@ -220,6 +230,8 @@ typedef struct srtp_stream_ctx_t {
direction_t direction;
int allow_repeat_tx;
ekt_stream_t ekt;
uint8_t salt[SRTP_AEAD_SALT_LEN]; /* used with GCM mode for SRTP */
uint8_t c_salt[SRTP_AEAD_SALT_LEN]; /* used with GCM mode for SRTCP */
struct srtp_stream_ctx_t *next; /* linked list of streams */
} srtp_stream_ctx_t;
@ -231,6 +243,7 @@ typedef struct srtp_stream_ctx_t {
typedef struct srtp_ctx_t {
srtp_stream_ctx_t *stream_list; /* linked list of streams */
srtp_stream_ctx_t *stream_template; /* act as template for other streams */
void *user_data; /* user custom data */
} srtp_ctx_t;

View File

@ -1,207 +0,0 @@
/*
* Copyright (c) 2012 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 MODULES_AUDIO_DEVICE_MAIN_INTERFACE_AUDIO_DEVICE_H_
#define MODULES_AUDIO_DEVICE_MAIN_INTERFACE_AUDIO_DEVICE_H_
#include "module.h"
#include "audio_device_defines.h"
namespace webrtc {
class AudioDeviceModule : public RefCountedModule {
public:
enum ErrorCode {
kAdmErrNone = 0,
kAdmErrArgument = 1
};
enum AudioLayer {
kPlatformDefaultAudio = 0,
kWindowsWaveAudio = 1,
kWindowsCoreAudio = 2,
kLinuxAlsaAudio = 3,
kLinuxPulseAudio = 4,
kDummyAudio = 5
};
enum WindowsDeviceType {
kDefaultCommunicationDevice = -1,
kDefaultDevice = -2
};
enum BufferType {
kFixedBufferSize = 0,
kAdaptiveBufferSize = 1
};
enum ChannelType {
kChannelLeft = 0,
kChannelRight = 1,
kChannelBoth = 2
};
public:
// Retrieve the currently utilized audio layer
virtual int32_t ActiveAudioLayer(AudioLayer* audioLayer) const = 0;
// Error handling
virtual ErrorCode LastError() const = 0;
virtual int32_t RegisterEventObserver(AudioDeviceObserver* eventCallback) = 0;
// Full-duplex transportation of PCM audio
virtual int32_t RegisterAudioCallback(AudioTransport* audioCallback) = 0;
// Main initialization and termination
virtual int32_t Init() = 0;
virtual int32_t Terminate() = 0;
virtual bool Initialized() const = 0;
// Device enumeration
virtual int16_t PlayoutDevices() = 0;
virtual int16_t RecordingDevices() = 0;
virtual int32_t PlayoutDeviceName(uint16_t index,
char name[kAdmMaxDeviceNameSize],
char guid[kAdmMaxGuidSize]) = 0;
virtual int32_t RecordingDeviceName(uint16_t index,
char name[kAdmMaxDeviceNameSize],
char guid[kAdmMaxGuidSize]) = 0;
// Device selection
virtual int32_t SetPlayoutDevice(uint16_t index) = 0;
virtual int32_t SetPlayoutDevice(WindowsDeviceType device) = 0;
virtual int32_t SetRecordingDevice(uint16_t index) = 0;
virtual int32_t SetRecordingDevice(WindowsDeviceType device) = 0;
// Audio transport initialization
virtual int32_t PlayoutIsAvailable(bool* available) = 0;
virtual int32_t InitPlayout() = 0;
virtual bool PlayoutIsInitialized() const = 0;
virtual int32_t RecordingIsAvailable(bool* available) = 0;
virtual int32_t InitRecording() = 0;
virtual bool RecordingIsInitialized() const = 0;
// Audio transport control
virtual int32_t StartPlayout() = 0;
virtual int32_t StopPlayout() = 0;
virtual bool Playing() const = 0;
virtual int32_t StartRecording() = 0;
virtual int32_t StopRecording() = 0;
virtual bool Recording() const = 0;
// Microphone Automatic Gain Control (AGC)
virtual int32_t SetAGC(bool enable) = 0;
virtual bool AGC() const = 0;
// Volume control based on the Windows Wave API (Windows only)
virtual int32_t SetWaveOutVolume(uint16_t volumeLeft,
uint16_t volumeRight) = 0;
virtual int32_t WaveOutVolume(uint16_t* volumeLeft,
uint16_t* volumeRight) const = 0;
// Audio mixer initialization
virtual int32_t SpeakerIsAvailable(bool* available) = 0;
virtual int32_t InitSpeaker() = 0;
virtual bool SpeakerIsInitialized() const = 0;
virtual int32_t MicrophoneIsAvailable(bool* available) = 0;
virtual int32_t InitMicrophone() = 0;
virtual bool MicrophoneIsInitialized() const = 0;
// Speaker volume controls
virtual int32_t SpeakerVolumeIsAvailable(bool* available) = 0;
virtual int32_t SetSpeakerVolume(uint32_t volume) = 0;
virtual int32_t SpeakerVolume(uint32_t* volume) const = 0;
virtual int32_t MaxSpeakerVolume(uint32_t* maxVolume) const = 0;
virtual int32_t MinSpeakerVolume(uint32_t* minVolume) const = 0;
virtual int32_t SpeakerVolumeStepSize(uint16_t* stepSize) const = 0;
// Microphone volume controls
virtual int32_t MicrophoneVolumeIsAvailable(bool* available) = 0;
virtual int32_t SetMicrophoneVolume(uint32_t volume) = 0;
virtual int32_t MicrophoneVolume(uint32_t* volume) const = 0;
virtual int32_t MaxMicrophoneVolume(uint32_t* maxVolume) const = 0;
virtual int32_t MinMicrophoneVolume(uint32_t* minVolume) const = 0;
virtual int32_t MicrophoneVolumeStepSize(uint16_t* stepSize) const = 0;
// Speaker mute control
virtual int32_t SpeakerMuteIsAvailable(bool* available) = 0;
virtual int32_t SetSpeakerMute(bool enable) = 0;
virtual int32_t SpeakerMute(bool* enabled) const = 0;
// Microphone mute control
virtual int32_t MicrophoneMuteIsAvailable(bool* available) = 0;
virtual int32_t SetMicrophoneMute(bool enable) = 0;
virtual int32_t MicrophoneMute(bool* enabled) const = 0;
// Microphone boost control
virtual int32_t MicrophoneBoostIsAvailable(bool* available) = 0;
virtual int32_t SetMicrophoneBoost(bool enable) = 0;
virtual int32_t MicrophoneBoost(bool* enabled) const = 0;
// Stereo support
virtual int32_t StereoPlayoutIsAvailable(bool* available) const = 0;
virtual int32_t SetStereoPlayout(bool enable) = 0;
virtual int32_t StereoPlayout(bool* enabled) const = 0;
virtual int32_t StereoRecordingIsAvailable(bool* available) const = 0;
virtual int32_t SetStereoRecording(bool enable) = 0;
virtual int32_t StereoRecording(bool* enabled) const = 0;
virtual int32_t SetRecordingChannel(const ChannelType channel) = 0;
virtual int32_t RecordingChannel(ChannelType* channel) const = 0;
// Delay information and control
virtual int32_t SetPlayoutBuffer(const BufferType type,
uint16_t sizeMS = 0) = 0;
virtual int32_t PlayoutBuffer(BufferType* type, uint16_t* sizeMS) const = 0;
virtual int32_t PlayoutDelay(uint16_t* delayMS) const = 0;
virtual int32_t RecordingDelay(uint16_t* delayMS) const = 0;
// CPU load
virtual int32_t CPULoad(uint16_t* load) const = 0;
// Recording of raw PCM data
virtual int32_t StartRawOutputFileRecording(
const char pcmFileNameUTF8[kAdmMaxFileNameSize]) = 0;
virtual int32_t StopRawOutputFileRecording() = 0;
virtual int32_t StartRawInputFileRecording(
const char pcmFileNameUTF8[kAdmMaxFileNameSize]) = 0;
virtual int32_t StopRawInputFileRecording() = 0;
// Native sample rate controls (samples/sec)
virtual int32_t SetRecordingSampleRate(const uint32_t samplesPerSec) = 0;
virtual int32_t RecordingSampleRate(uint32_t* samplesPerSec) const = 0;
virtual int32_t SetPlayoutSampleRate(const uint32_t samplesPerSec) = 0;
virtual int32_t PlayoutSampleRate(uint32_t* samplesPerSec) const = 0;
// Mobile device specific functions
virtual int32_t ResetAudioDevice() = 0;
virtual int32_t SetLoudspeakerStatus(bool enable) = 0;
virtual int32_t GetLoudspeakerStatus(bool* enabled) const = 0;
// *Experimental - not recommended for use.*
// Enables the Windows Core Audio built-in AEC. Fails on other platforms.
//
// Must be called before InitRecording(). When enabled:
// 1. StartPlayout() must be called before StartRecording().
// 2. StopRecording() should be called before StopPlayout().
// The reverse order may cause garbage audio to be rendered or the
// capture side to halt until StopRecording() is called.
virtual int32_t EnableBuiltInAEC(bool enable) { return -1; }
virtual bool BuiltInAECIsEnabled() const { return false; }
protected:
virtual ~AudioDeviceModule() {};
};
AudioDeviceModule* CreateAudioDeviceModule(
WebRtc_Word32 id, AudioDeviceModule::AudioLayer audioLayer);
} // namespace webrtc
#endif // MODULES_AUDIO_DEVICE_MAIN_INTERFACE_AUDIO_DEVICE_H_

View File

@ -1,129 +0,0 @@
/*
* Copyright (c) 2012 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_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H
#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H
#include "typedefs.h"
//#include "../../../../common_audio/resampler/include/resampler.h"
#include "file_wrapper.h"
#include "audio_device.h"
#include "list_wrapper.h"
namespace webrtc {
class CriticalSectionWrapper;
const WebRtc_UWord32 kPulsePeriodMs = 1000;
const WebRtc_UWord32 kMaxBufferSizeBytes = 3840; // 10ms in stereo @ 96kHz
class AudioDeviceObserver;
class MediaFile;
class AudioDeviceBuffer
{
public:
void SetId(WebRtc_UWord32 id);
WebRtc_Word32 RegisterAudioCallback(AudioTransport* audioCallback);
WebRtc_Word32 InitPlayout();
WebRtc_Word32 InitRecording();
WebRtc_Word32 SetRecordingSampleRate(WebRtc_UWord32 fsHz);
WebRtc_Word32 SetPlayoutSampleRate(WebRtc_UWord32 fsHz);
WebRtc_Word32 RecordingSampleRate() const;
WebRtc_Word32 PlayoutSampleRate() const;
WebRtc_Word32 SetRecordingChannels(WebRtc_UWord8 channels);
WebRtc_Word32 SetPlayoutChannels(WebRtc_UWord8 channels);
WebRtc_UWord8 RecordingChannels() const;
WebRtc_UWord8 PlayoutChannels() const;
WebRtc_Word32 SetRecordingChannel(
const AudioDeviceModule::ChannelType channel);
WebRtc_Word32 RecordingChannel(
AudioDeviceModule::ChannelType& channel) const;
WebRtc_Word32 SetRecordedBuffer(const void* audioBuffer,
WebRtc_UWord32 nSamples);
WebRtc_Word32 SetCurrentMicLevel(WebRtc_UWord32 level);
WebRtc_Word32 SetVQEData(WebRtc_UWord32 playDelayMS,
WebRtc_UWord32 recDelayMS,
WebRtc_Word32 clockDrift);
WebRtc_Word32 DeliverRecordedData();
WebRtc_UWord32 NewMicLevel() const;
WebRtc_Word32 RequestPlayoutData(WebRtc_UWord32 nSamples);
WebRtc_Word32 GetPlayoutData(void* audioBuffer);
WebRtc_Word32 StartInputFileRecording(
const char fileName[kAdmMaxFileNameSize]);
WebRtc_Word32 StopInputFileRecording();
WebRtc_Word32 StartOutputFileRecording(
const char fileName[kAdmMaxFileNameSize]);
WebRtc_Word32 StopOutputFileRecording();
AudioDeviceBuffer();
~AudioDeviceBuffer();
private:
void _EmptyList();
private:
WebRtc_Word32 _id;
CriticalSectionWrapper& _critSect;
CriticalSectionWrapper& _critSectCb;
AudioTransport* _ptrCbAudioTransport;
WebRtc_UWord32 _recSampleRate;
WebRtc_UWord32 _playSampleRate;
WebRtc_UWord8 _recChannels;
WebRtc_UWord8 _playChannels;
// selected recording channel (left/right/both)
AudioDeviceModule::ChannelType _recChannel;
// 2 or 4 depending on mono or stereo
WebRtc_UWord8 _recBytesPerSample;
WebRtc_UWord8 _playBytesPerSample;
// 10ms in stereo @ 96kHz
int8_t _recBuffer[kMaxBufferSizeBytes];
// one sample <=> 2 or 4 bytes
WebRtc_UWord32 _recSamples;
WebRtc_UWord32 _recSize; // in bytes
// 10ms in stereo @ 96kHz
int8_t _playBuffer[kMaxBufferSizeBytes];
// one sample <=> 2 or 4 bytes
WebRtc_UWord32 _playSamples;
WebRtc_UWord32 _playSize; // in bytes
FileWrapper& _recFile;
FileWrapper& _playFile;
WebRtc_UWord32 _currentMicLevel;
WebRtc_UWord32 _newMicLevel;
WebRtc_UWord32 _playDelayMS;
WebRtc_UWord32 _recDelayMS;
WebRtc_Word32 _clockDrift;
bool _measureDelay;
ListWrapper _pulseList;
WebRtc_UWord32 _lastPulseTime;
};
} // namespace webrtc
#endif // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H

View File

@ -1,44 +0,0 @@
/*
* 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_AUDIO_DEVICE_AUDIO_DEVICE_CONFIG_H
#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_CONFIG_H
// Enumerators
//
enum { kAdmMaxIdleTimeProcess = 1000 };
enum { GET_MIC_VOLUME_INTERVAL_MS = 1000 };
// Platform specifics
//
#if defined(_WIN32)
#if (_MSC_VER >= 1400)
// Windows Core Audio is the default audio layer in Windows.
// Only supported for VS 2005 and higher.
#define WEBRTC_WINDOWS_CORE_AUDIO_BUILD
#endif
#endif
#if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400))
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#define DEBUG_PRINT(...) \
{ \
TCHAR msg[256]; \
StringCchPrintf(msg, 256, __VA_ARGS__); \
OutputDebugString(msg); \
}
#else
#define DEBUG_PRINT(exp) ((void)0)
#endif
#endif // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_CONFIG_H

View File

@ -1,80 +0,0 @@
/*
* 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_AUDIO_DEVICE_AUDIO_DEVICE_DEFINES_H
#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_DEFINES_H
#include "typedefs.h"
namespace webrtc {
static const int kAdmMaxDeviceNameSize = 128;
static const int kAdmMaxFileNameSize = 512;
static const int kAdmMaxGuidSize = 128;
static const int kAdmMinPlayoutBufferSizeMs = 10;
static const int kAdmMaxPlayoutBufferSizeMs = 250;
// ----------------------------------------------------------------------------
// AudioDeviceObserver
// ----------------------------------------------------------------------------
class AudioDeviceObserver
{
public:
enum ErrorCode
{
kRecordingError = 0,
kPlayoutError = 1
};
enum WarningCode
{
kRecordingWarning = 0,
kPlayoutWarning = 1
};
virtual void OnErrorIsReported(const ErrorCode error) = 0;
virtual void OnWarningIsReported(const WarningCode warning) = 0;
protected:
virtual ~AudioDeviceObserver() {}
};
// ----------------------------------------------------------------------------
// AudioTransport
// ----------------------------------------------------------------------------
class AudioTransport
{
public:
virtual int32_t RecordedDataIsAvailable(const void* audioSamples,
const uint32_t nSamples,
const uint8_t nBytesPerSample,
const uint8_t nChannels,
const uint32_t samplesPerSec,
const uint32_t totalDelayMS,
const int32_t clockDrift,
const uint32_t currentMicLevel,
uint32_t& newMicLevel) = 0;
virtual int32_t NeedMorePlayData(const uint32_t nSamples,
const uint8_t nBytesPerSample,
const uint8_t nChannels,
const uint32_t samplesPerSec,
void* audioSamples,
uint32_t& nSamplesOut) = 0;
protected:
virtual ~AudioTransport() {}
};
} // namespace webrtc
#endif // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_DEFINES_H

View File

@ -1,235 +0,0 @@
/*
* Copyright (c) 2012 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_AUDIO_DEVICE_AUDIO_DEVICE_IMPL_H
#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_IMPL_H
#include "audio_device.h"
#include "audio_device_buffer.h"
namespace webrtc
{
class AudioDeviceGeneric;
class AudioDeviceUtility;
class CriticalSectionWrapper;
class AudioDeviceModuleImpl : public AudioDeviceModule
{
public:
enum PlatformType
{
kPlatformNotSupported = 0,
kPlatformWin32 = 1,
kPlatformWinCe = 2,
kPlatformLinux = 3,
kPlatformMac = 4,
kPlatformAndroid = 5
};
WebRtc_Word32 CheckPlatform();
WebRtc_Word32 CreatePlatformSpecificObjects();
WebRtc_Word32 AttachAudioBuffer();
AudioDeviceModuleImpl(const WebRtc_Word32 id, const AudioLayer audioLayer);
virtual ~AudioDeviceModuleImpl();
public: // RefCountedModule
virtual WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id);
virtual WebRtc_Word32 TimeUntilNextProcess();
virtual WebRtc_Word32 Process();
public:
// Factory methods (resource allocation/deallocation)
static AudioDeviceModule* Create(
const WebRtc_Word32 id,
const AudioLayer audioLayer = kPlatformDefaultAudio);
// Retrieve the currently utilized audio layer
virtual WebRtc_Word32 ActiveAudioLayer(AudioLayer* audioLayer) const;
// Error handling
virtual ErrorCode LastError() const;
virtual WebRtc_Word32 RegisterEventObserver(
AudioDeviceObserver* eventCallback);
// Full-duplex transportation of PCM audio
virtual WebRtc_Word32 RegisterAudioCallback(
AudioTransport* audioCallback);
// Main initializaton and termination
virtual WebRtc_Word32 Init();
virtual WebRtc_Word32 Terminate();
virtual bool Initialized() const;
// Device enumeration
virtual WebRtc_Word16 PlayoutDevices();
virtual WebRtc_Word16 RecordingDevices();
virtual WebRtc_Word32 PlayoutDeviceName(
WebRtc_UWord16 index,
char name[kAdmMaxDeviceNameSize],
char guid[kAdmMaxGuidSize]);
virtual WebRtc_Word32 RecordingDeviceName(
WebRtc_UWord16 index,
char name[kAdmMaxDeviceNameSize],
char guid[kAdmMaxGuidSize]);
// Device selection
virtual WebRtc_Word32 SetPlayoutDevice(WebRtc_UWord16 index);
virtual WebRtc_Word32 SetPlayoutDevice(WindowsDeviceType device);
virtual WebRtc_Word32 SetRecordingDevice(WebRtc_UWord16 index);
virtual WebRtc_Word32 SetRecordingDevice(WindowsDeviceType device);
// Audio transport initialization
virtual WebRtc_Word32 PlayoutIsAvailable(bool* available);
virtual WebRtc_Word32 InitPlayout();
virtual bool PlayoutIsInitialized() const;
virtual WebRtc_Word32 RecordingIsAvailable(bool* available);
virtual WebRtc_Word32 InitRecording();
virtual bool RecordingIsInitialized() const;
// Audio transport control
virtual WebRtc_Word32 StartPlayout();
virtual WebRtc_Word32 StopPlayout();
virtual bool Playing() const;
virtual WebRtc_Word32 StartRecording();
virtual WebRtc_Word32 StopRecording();
virtual bool Recording() const;
// Microphone Automatic Gain Control (AGC)
virtual WebRtc_Word32 SetAGC(bool enable);
virtual bool AGC() const;
// Volume control based on the Windows Wave API (Windows only)
virtual WebRtc_Word32 SetWaveOutVolume(WebRtc_UWord16 volumeLeft,
WebRtc_UWord16 volumeRight);
virtual WebRtc_Word32 WaveOutVolume(WebRtc_UWord16* volumeLeft,
WebRtc_UWord16* volumeRight) const;
// Audio mixer initialization
virtual WebRtc_Word32 SpeakerIsAvailable(bool* available);
virtual WebRtc_Word32 InitSpeaker();
virtual bool SpeakerIsInitialized() const;
virtual WebRtc_Word32 MicrophoneIsAvailable(bool* available);
virtual WebRtc_Word32 InitMicrophone();
virtual bool MicrophoneIsInitialized() const;
// Speaker volume controls
virtual WebRtc_Word32 SpeakerVolumeIsAvailable(bool* available);
virtual WebRtc_Word32 SetSpeakerVolume(WebRtc_UWord32 volume);
virtual WebRtc_Word32 SpeakerVolume(WebRtc_UWord32* volume) const;
virtual WebRtc_Word32 MaxSpeakerVolume(WebRtc_UWord32* maxVolume) const;
virtual WebRtc_Word32 MinSpeakerVolume(WebRtc_UWord32* minVolume) const;
virtual WebRtc_Word32 SpeakerVolumeStepSize(
WebRtc_UWord16* stepSize) const;
// Microphone volume controls
virtual WebRtc_Word32 MicrophoneVolumeIsAvailable(bool* available);
virtual WebRtc_Word32 SetMicrophoneVolume(WebRtc_UWord32 volume);
virtual WebRtc_Word32 MicrophoneVolume(WebRtc_UWord32* volume) const;
virtual WebRtc_Word32 MaxMicrophoneVolume(
WebRtc_UWord32* maxVolume) const;
virtual WebRtc_Word32 MinMicrophoneVolume(
WebRtc_UWord32* minVolume) const;
virtual WebRtc_Word32 MicrophoneVolumeStepSize(
WebRtc_UWord16* stepSize) const;
// Speaker mute control
virtual WebRtc_Word32 SpeakerMuteIsAvailable(bool* available);
virtual WebRtc_Word32 SetSpeakerMute(bool enable);
virtual WebRtc_Word32 SpeakerMute(bool* enabled) const;
// Microphone mute control
virtual WebRtc_Word32 MicrophoneMuteIsAvailable(bool* available);
virtual WebRtc_Word32 SetMicrophoneMute(bool enable);
virtual WebRtc_Word32 MicrophoneMute(bool* enabled) const;
// Microphone boost control
virtual WebRtc_Word32 MicrophoneBoostIsAvailable(bool* available);
virtual WebRtc_Word32 SetMicrophoneBoost(bool enable);
virtual WebRtc_Word32 MicrophoneBoost(bool* enabled) const;
// Stereo support
virtual WebRtc_Word32 StereoPlayoutIsAvailable(bool* available) const;
virtual WebRtc_Word32 SetStereoPlayout(bool enable);
virtual WebRtc_Word32 StereoPlayout(bool* enabled) const;
virtual WebRtc_Word32 StereoRecordingIsAvailable(bool* available) const;
virtual WebRtc_Word32 SetStereoRecording(bool enable);
virtual WebRtc_Word32 StereoRecording(bool* enabled) const;
virtual WebRtc_Word32 SetRecordingChannel(const ChannelType channel);
virtual WebRtc_Word32 RecordingChannel(ChannelType* channel) const;
// Delay information and control
virtual WebRtc_Word32 SetPlayoutBuffer(const BufferType type,
WebRtc_UWord16 sizeMS = 0);
virtual WebRtc_Word32 PlayoutBuffer(BufferType* type,
WebRtc_UWord16* sizeMS) const;
virtual WebRtc_Word32 PlayoutDelay(WebRtc_UWord16* delayMS) const;
virtual WebRtc_Word32 RecordingDelay(WebRtc_UWord16* delayMS) const;
// CPU load
virtual WebRtc_Word32 CPULoad(WebRtc_UWord16* load) const;
// Recording of raw PCM data
virtual WebRtc_Word32 StartRawOutputFileRecording(
const char pcmFileNameUTF8[kAdmMaxFileNameSize]);
virtual WebRtc_Word32 StopRawOutputFileRecording();
virtual WebRtc_Word32 StartRawInputFileRecording(
const char pcmFileNameUTF8[kAdmMaxFileNameSize]);
virtual WebRtc_Word32 StopRawInputFileRecording();
// Native sample rate controls (samples/sec)
virtual WebRtc_Word32 SetRecordingSampleRate(
const WebRtc_UWord32 samplesPerSec);
virtual WebRtc_Word32 RecordingSampleRate(
WebRtc_UWord32* samplesPerSec) const;
virtual WebRtc_Word32 SetPlayoutSampleRate(
const WebRtc_UWord32 samplesPerSec);
virtual WebRtc_Word32 PlayoutSampleRate(
WebRtc_UWord32* samplesPerSec) const;
// Mobile device specific functions
virtual WebRtc_Word32 ResetAudioDevice();
virtual WebRtc_Word32 SetLoudspeakerStatus(bool enable);
virtual WebRtc_Word32 GetLoudspeakerStatus(bool* enabled) const;
virtual int32_t EnableBuiltInAEC(bool enable);
virtual bool BuiltInAECIsEnabled() const;
public:
WebRtc_Word32 Id() {return _id;}
private:
PlatformType Platform() const;
AudioLayer PlatformAudioLayer() const;
private:
CriticalSectionWrapper& _critSect;
CriticalSectionWrapper& _critSectEventCb;
CriticalSectionWrapper& _critSectAudioCb;
AudioDeviceObserver* _ptrCbAudioDeviceObserver;
AudioDeviceUtility* _ptrAudioDeviceUtility;
AudioDeviceGeneric* _ptrAudioDevice;
AudioDeviceBuffer _audioDeviceBuffer;
WebRtc_Word32 _id;
AudioLayer _platformAudioLayer;
WebRtc_UWord32 _lastProcessTime;
PlatformType _platformType;
bool _initialized;
mutable ErrorCode _lastError;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_INTERFACE_AUDIO_DEVICE_IMPL_H_

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2012 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_AUDIO_DEVICE_AUDIO_DEVICE_UTILITY_H
#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_UTILITY_H
#include "typedefs.h"
namespace webrtc
{
class AudioDeviceUtility
{
public:
static WebRtc_UWord32 GetTimeInMS();
static void Sleep(WebRtc_UWord32 milliseconds);
static void WaitForKey();
static bool StringCompare(const char* str1,
const char* str2,
const WebRtc_UWord32 length);
virtual WebRtc_Word32 Init() = 0;
virtual ~AudioDeviceUtility() {}
};
} // namespace webrtc
#endif // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_UTILITY_H

View File

@ -1,602 +0,0 @@
/*
* Copyright (c) 2012 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_COMMON_TYPES_H
#define WEBRTC_COMMON_TYPES_H
#include "typedefs.h"
#ifdef WEBRTC_EXPORT
#define WEBRTC_DLLEXPORT _declspec(dllexport)
#elif WEBRTC_DLL
#define WEBRTC_DLLEXPORT _declspec(dllimport)
#else
#define WEBRTC_DLLEXPORT
#endif
#ifndef NULL
#define NULL 0
#endif
#define RTP_PAYLOAD_NAME_SIZE 32
namespace webrtc {
class InStream
{
public:
virtual int Read(void *buf,int len) = 0;
virtual int Rewind() {return -1;}
virtual ~InStream() {}
protected:
InStream() {}
};
class OutStream
{
public:
virtual bool Write(const void *buf,int len) = 0;
virtual int Rewind() {return -1;}
virtual ~OutStream() {}
protected:
OutStream() {}
};
enum TraceModule
{
// not a module, triggered from the engine code
kTraceVoice = 0x0001,
// not a module, triggered from the engine code
kTraceVideo = 0x0002,
// not a module, triggered from the utility code
kTraceUtility = 0x0003,
kTraceRtpRtcp = 0x0004,
kTraceTransport = 0x0005,
kTraceSrtp = 0x0006,
kTraceAudioCoding = 0x0007,
kTraceAudioMixerServer = 0x0008,
kTraceAudioMixerClient = 0x0009,
kTraceFile = 0x000a,
kTraceAudioProcessing = 0x000b,
kTraceVideoCoding = 0x0010,
kTraceVideoMixer = 0x0011,
kTraceAudioDevice = 0x0012,
kTraceVideoRenderer = 0x0014,
kTraceVideoCapture = 0x0015,
kTraceVideoPreocessing = 0x0016
};
enum TraceLevel
{
kTraceNone = 0x0000, // no trace
kTraceStateInfo = 0x0001,
kTraceWarning = 0x0002,
kTraceError = 0x0004,
kTraceCritical = 0x0008,
kTraceApiCall = 0x0010,
kTraceDefault = 0x00ff,
kTraceModuleCall = 0x0020,
kTraceMemory = 0x0100, // memory info
kTraceTimer = 0x0200, // timing info
kTraceStream = 0x0400, // "continuous" stream of data
// used for debug purposes
kTraceDebug = 0x0800, // debug
kTraceInfo = 0x1000, // debug info
kTraceAll = 0xffff
};
// External Trace API
class TraceCallback
{
public:
virtual void Print(const TraceLevel level,
const char *traceString,
const int length) = 0;
protected:
virtual ~TraceCallback() {}
TraceCallback() {}
};
enum FileFormats
{
kFileFormatWavFile = 1,
kFileFormatCompressedFile = 2,
kFileFormatAviFile = 3,
kFileFormatPreencodedFile = 4,
kFileFormatPcm16kHzFile = 7,
kFileFormatPcm8kHzFile = 8,
kFileFormatPcm32kHzFile = 9
};
enum ProcessingTypes
{
kPlaybackPerChannel = 0,
kPlaybackAllChannelsMixed,
kRecordingPerChannel,
kRecordingAllChannelsMixed
};
// Encryption enums
enum CipherTypes
{
kCipherNull = 0,
kCipherAes128CounterMode = 1
};
enum AuthenticationTypes
{
kAuthNull = 0,
kAuthHmacSha1 = 3
};
enum SecurityLevels
{
kNoProtection = 0,
kEncryption = 1,
kAuthentication = 2,
kEncryptionAndAuthentication = 3
};
// Interface for encrypting and decrypting regular data and rtp/rtcp packets.
// Implement this interface if you wish to provide an encryption scheme to
// the voice or video engines.
class Encryption
{
public:
// Encrypt the given data.
//
// Args:
// channel: The channel to encrypt data for.
// in_data: The data to encrypt. This data is bytes_in bytes long.
// out_data: The buffer to write the encrypted data to. You may write more
// bytes of encrypted data than what you got as input, up to a maximum
// of webrtc::kViEMaxMtu if you are encrypting in the video engine, or
// webrtc::kVoiceEngineMaxIpPacketSizeBytes for the voice engine.
// bytes_in: The number of bytes in the input buffer.
// bytes_out: The number of bytes written in out_data.
virtual void encrypt(
int channel,
unsigned char* in_data,
unsigned char* out_data,
int bytes_in,
int* bytes_out) = 0;
// Decrypts the given data. This should reverse the effects of encrypt().
//
// Args:
// channel_no: The channel to decrypt data for.
// in_data: The data to decrypt. This data is bytes_in bytes long.
// out_data: The buffer to write the decrypted data to. You may write more
// bytes of decrypted data than what you got as input, up to a maximum
// of webrtc::kViEMaxMtu if you are encrypting in the video engine, or
// webrtc::kVoiceEngineMaxIpPacketSizeBytes for the voice engine.
// bytes_in: The number of bytes in the input buffer.
// bytes_out: The number of bytes written in out_data.
virtual void decrypt(
int channel,
unsigned char* in_data,
unsigned char* out_data,
int bytes_in,
int* bytes_out) = 0;
// Encrypts a RTCP packet. Otherwise, this method has the same contract as
// encrypt().
virtual void encrypt_rtcp(
int channel,
unsigned char* in_data,
unsigned char* out_data,
int bytes_in,
int* bytes_out) = 0;
// Decrypts a RTCP packet. Otherwise, this method has the same contract as
// decrypt().
virtual void decrypt_rtcp(
int channel,
unsigned char* in_data,
unsigned char* out_data,
int bytes_in,
int* bytes_out) = 0;
protected:
virtual ~Encryption() {}
Encryption() {}
};
// External transport callback interface
class Transport
{
public:
virtual int SendPacket(int channel, const void *data, int len) = 0;
virtual int SendRTCPPacket(int channel, const void *data, int len) = 0;
protected:
virtual ~Transport() {}
Transport() {}
};
// ==================================================================
// Voice specific types
// ==================================================================
// Each codec supported can be described by this structure.
struct CodecInst
{
int pltype;
char plname[RTP_PAYLOAD_NAME_SIZE];
int plfreq;
int pacsize;
int channels;
int rate;
};
enum FrameType
{
kFrameEmpty = 0,
kAudioFrameSpeech = 1,
kAudioFrameCN = 2,
kVideoFrameKey = 3, // independent frame
kVideoFrameDelta = 4, // depends on the previus frame
kVideoFrameGolden = 5, // depends on a old known previus frame
kVideoFrameAltRef = 6
};
// RTP
enum {kRtpCsrcSize = 15}; // RFC 3550 page 13
enum RTPDirections
{
kRtpIncoming = 0,
kRtpOutgoing
};
enum PayloadFrequencies
{
kFreq8000Hz = 8000,
kFreq16000Hz = 16000,
kFreq32000Hz = 32000
};
enum VadModes // degree of bandwidth reduction
{
kVadConventional = 0, // lowest reduction
kVadAggressiveLow,
kVadAggressiveMid,
kVadAggressiveHigh // highest reduction
};
struct NetworkStatistics // NETEQ statistics
{
// current jitter buffer size in ms
WebRtc_UWord16 currentBufferSize;
// preferred (optimal) buffer size in ms
WebRtc_UWord16 preferredBufferSize;
// adding extra delay due to "peaky jitter"
bool jitterPeaksFound;
// loss rate (network + late) in percent (in Q14)
WebRtc_UWord16 currentPacketLossRate;
// late loss rate in percent (in Q14)
WebRtc_UWord16 currentDiscardRate;
// fraction (of original stream) of synthesized speech inserted through
// expansion (in Q14)
WebRtc_UWord16 currentExpandRate;
// fraction of synthesized speech inserted through pre-emptive expansion
// (in Q14)
WebRtc_UWord16 currentPreemptiveRate;
// fraction of data removed through acceleration (in Q14)
WebRtc_UWord16 currentAccelerateRate;
// clock-drift in parts-per-million (negative or positive)
int32_t clockDriftPPM;
// average packet waiting time in the jitter buffer (ms)
int meanWaitingTimeMs;
// median packet waiting time in the jitter buffer (ms)
int medianWaitingTimeMs;
// min packet waiting time in the jitter buffer (ms)
int minWaitingTimeMs;
// max packet waiting time in the jitter buffer (ms)
int maxWaitingTimeMs;
};
typedef struct
{
int min; // minumum
int max; // maximum
int average; // average
} StatVal;
typedef struct // All levels are reported in dBm0
{
StatVal speech_rx; // long-term speech levels on receiving side
StatVal speech_tx; // long-term speech levels on transmitting side
StatVal noise_rx; // long-term noise/silence levels on receiving side
StatVal noise_tx; // long-term noise/silence levels on transmitting side
} LevelStatistics;
typedef struct // All levels are reported in dB
{
StatVal erl; // Echo Return Loss
StatVal erle; // Echo Return Loss Enhancement
StatVal rerl; // RERL = ERL + ERLE
// Echo suppression inside EC at the point just before its NLP
StatVal a_nlp;
} EchoStatistics;
enum TelephoneEventDetectionMethods
{
kInBand = 0,
kOutOfBand = 1,
kInAndOutOfBand = 2
};
enum NsModes // type of Noise Suppression
{
kNsUnchanged = 0, // previously set mode
kNsDefault, // platform default
kNsConference, // conferencing default
kNsLowSuppression, // lowest suppression
kNsModerateSuppression,
kNsHighSuppression,
kNsVeryHighSuppression, // highest suppression
};
enum AgcModes // type of Automatic Gain Control
{
kAgcUnchanged = 0, // previously set mode
kAgcDefault, // platform default
// adaptive mode for use when analog volume control exists (e.g. for
// PC softphone)
kAgcAdaptiveAnalog,
// scaling takes place in the digital domain (e.g. for conference servers
// and embedded devices)
kAgcAdaptiveDigital,
// can be used on embedded devices where the capture signal level
// is predictable
kAgcFixedDigital
};
// EC modes
enum EcModes // type of Echo Control
{
kEcUnchanged = 0, // previously set mode
kEcDefault, // platform default
kEcConference, // conferencing default (aggressive AEC)
kEcAec, // Acoustic Echo Cancellation
kEcAecm, // AEC mobile
};
// AECM modes
enum AecmModes // mode of AECM
{
kAecmQuietEarpieceOrHeadset = 0,
// Quiet earpiece or headset use
kAecmEarpiece, // most earpiece use
kAecmLoudEarpiece, // Loud earpiece or quiet speakerphone use
kAecmSpeakerphone, // most speakerphone use (default)
kAecmLoudSpeakerphone // Loud speakerphone
};
// AGC configuration
typedef struct
{
unsigned short targetLeveldBOv;
unsigned short digitalCompressionGaindB;
bool limiterEnable;
} AgcConfig; // AGC configuration parameters
enum StereoChannel
{
kStereoLeft = 0,
kStereoRight,
kStereoBoth
};
// Audio device layers
enum AudioLayers
{
kAudioPlatformDefault = 0,
kAudioWindowsWave = 1,
kAudioWindowsCore = 2,
kAudioLinuxAlsa = 3,
kAudioLinuxPulse = 4
};
enum NetEqModes // NetEQ playout configurations
{
// Optimized trade-off between low delay and jitter robustness for two-way
// communication.
kNetEqDefault = 0,
// Improved jitter robustness at the cost of increased delay. Can be
// used in one-way communication.
kNetEqStreaming = 1,
// Optimzed for decodability of fax signals rather than for perceived audio
// quality.
kNetEqFax = 2,
};
enum NetEqBgnModes // NetEQ Background Noise (BGN) configurations
{
// BGN is always on and will be generated when the incoming RTP stream
// stops (default).
kBgnOn = 0,
// The BGN is faded to zero (complete silence) after a few seconds.
kBgnFade = 1,
// BGN is not used at all. Silence is produced after speech extrapolation
// has faded.
kBgnOff = 2,
};
enum OnHoldModes // On Hold direction
{
kHoldSendAndPlay = 0, // Put both sending and playing in on-hold state.
kHoldSendOnly, // Put only sending in on-hold state.
kHoldPlayOnly // Put only playing in on-hold state.
};
enum AmrMode
{
kRfc3267BwEfficient = 0,
kRfc3267OctetAligned = 1,
kRfc3267FileStorage = 2,
};
// ==================================================================
// Video specific types
// ==================================================================
// Raw video types
enum RawVideoType
{
kVideoI420 = 0,
kVideoYV12 = 1,
kVideoYUY2 = 2,
kVideoUYVY = 3,
kVideoIYUV = 4,
kVideoARGB = 5,
kVideoRGB24 = 6,
kVideoRGB565 = 7,
kVideoARGB4444 = 8,
kVideoARGB1555 = 9,
kVideoMJPEG = 10,
kVideoNV12 = 11,
kVideoNV21 = 12,
kVideoBGRA = 13,
kVideoUnknown = 99
};
// Video codec
enum { kConfigParameterSize = 128};
enum { kPayloadNameSize = 32};
enum { kMaxSimulcastStreams = 4};
enum { kMaxTemporalStreams = 4};
enum VideoCodecComplexity
{
kComplexityNormal = 0,
kComplexityHigh = 1,
kComplexityHigher = 2,
kComplexityMax = 3
};
enum VideoCodecProfile
{
kProfileBase = 0x00,
kProfileMain = 0x01
};
enum VP8ResilienceMode {
kResilienceOff, // The stream produced by the encoder requires a
// recovery frame (typically a key frame) to be
// decodable after a packet loss.
kResilientStream, // A stream produced by the encoder is resilient to
// packet losses, but packets within a frame subsequent
// to a loss can't be decoded.
kResilientFrames // Same as kResilientStream but with added resilience
// within a frame.
};
// VP8 specific
struct VideoCodecVP8
{
bool pictureLossIndicationOn;
bool feedbackModeOn;
VideoCodecComplexity complexity;
VP8ResilienceMode resilience;
unsigned char numberOfTemporalLayers;
bool denoisingOn;
bool errorConcealmentOn;
};
// Unknown specific
struct VideoCodecGeneric
{
};
// Video codec types
enum VideoCodecType
{
kVideoCodecVP8,
kVideoCodecI420,
kVideoCodecRED,
kVideoCodecULPFEC,
kVideoCodecUnknown
};
union VideoCodecUnion
{
VideoCodecVP8 VP8;
VideoCodecGeneric Generic;
};
// Simulcast is when the same stream is encoded multiple times with different
// settings such as resolution.
struct SimulcastStream
{
unsigned short width;
unsigned short height;
unsigned char numberOfTemporalLayers;
unsigned int maxBitrate;
unsigned int qpMax; // minimum quality
};
// Common video codec properties
struct VideoCodec
{
VideoCodecType codecType;
char plName[kPayloadNameSize];
unsigned char plType;
unsigned short width;
unsigned short height;
unsigned int startBitrate;
unsigned int maxBitrate;
unsigned int minBitrate;
unsigned char maxFramerate;
VideoCodecUnion codecSpecific;
unsigned int qpMax;
unsigned char numberOfSimulcastStreams;
SimulcastStream simulcastStream[kMaxSimulcastStreams];
};
// Bandwidth over-use detector options. These are used to drive
// experimentation with bandwidth estimation parameters.
// See modules/remote_bitrate_estimator/overuse_detector.h
struct OverUseDetectorOptions {
OverUseDetectorOptions()
: initial_slope(8.0/512.0),
initial_offset(0),
initial_e(),
initial_process_noise(),
initial_avg_noise(0.0),
initial_var_noise(500),
initial_threshold(25.0) {
initial_e[0][0] = 100;
initial_e[1][1] = 1e-1;
initial_e[0][1] = initial_e[1][0] = 0;
initial_process_noise[0] = 1e-10;
initial_process_noise[1] = 1e-2;
}
double initial_slope;
double initial_offset;
double initial_e[2][2];
double initial_process_noise[2];
double initial_avg_noise;
double initial_var_noise;
double initial_threshold;
};
} // namespace webrtc
#endif // WEBRTC_COMMON_TYPES_H

View File

@ -1,50 +0,0 @@
/*
* 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.
*/
/*
* WebRtc
* Copy from third_party/libjingle/source/talk/base/constructormagic.h
*/
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONSTRUCTOR_MAGIC_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONSTRUCTOR_MAGIC_H_
#ifndef DISALLOW_ASSIGN
#define DISALLOW_ASSIGN(TypeName) \
void operator=(const TypeName&)
#endif
#ifndef DISALLOW_COPY_AND_ASSIGN
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
DISALLOW_ASSIGN(TypeName)
#endif
#ifndef DISALLOW_EVIL_CONSTRUCTORS
// Alternative, less-accurate legacy name.
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
DISALLOW_COPY_AND_ASSIGN(TypeName)
#endif
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
DISALLOW_EVIL_CONSTRUCTORS(TypeName)
#endif
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONSTRUCTOR_MAGIC_H_

View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 2012 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_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_
#include "typedefs.h"
enum {
AecmFalse = 0,
AecmTrue
};
// Errors
#define AECM_UNSPECIFIED_ERROR 12000
#define AECM_UNSUPPORTED_FUNCTION_ERROR 12001
#define AECM_UNINITIALIZED_ERROR 12002
#define AECM_NULL_POINTER_ERROR 12003
#define AECM_BAD_PARAMETER_ERROR 12004
// Warnings
#define AECM_BAD_PARAMETER_WARNING 12100
typedef struct {
WebRtc_Word16 cngMode; // AECM_FALSE, AECM_TRUE (default)
WebRtc_Word16 echoMode; // 0, 1, 2, 3 (default), 4
} AecmConfig;
#ifdef __cplusplus
extern "C" {
#endif
/*
* Allocates the memory needed by the AECM. The memory needs to be
* initialized separately using the WebRtcAecm_Init() function.
*
* Inputs Description
* -------------------------------------------------------------------
* void **aecmInst Pointer to the AECM instance to be
* created and initialized
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Create(void **aecmInst);
/*
* This function releases the memory allocated by WebRtcAecm_Create()
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Free(void *aecmInst);
/*
* Initializes an AECM instance.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* WebRtc_Word32 sampFreq Sampling frequency of data
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Init(void* aecmInst,
WebRtc_Word32 sampFreq);
/*
* Inserts an 80 or 160 sample block of data into the farend buffer.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* WebRtc_Word16 *farend In buffer containing one frame of
* farend signal
* WebRtc_Word16 nrOfSamples Number of samples in farend buffer
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_BufferFarend(void* aecmInst,
const WebRtc_Word16* farend,
WebRtc_Word16 nrOfSamples);
/*
* Runs the AECM on an 80 or 160 sample blocks of data.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* WebRtc_Word16 *nearendNoisy In buffer containing one frame of
* reference nearend+echo signal. If
* noise reduction is active, provide
* the noisy signal here.
* WebRtc_Word16 *nearendClean In buffer containing one frame of
* nearend+echo signal. If noise
* reduction is active, provide the
* clean signal here. Otherwise pass a
* NULL pointer.
* WebRtc_Word16 nrOfSamples Number of samples in nearend buffer
* WebRtc_Word16 msInSndCardBuf Delay estimate for sound card and
* system buffers
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word16 *out Out buffer, one frame of processed nearend
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Process(void* aecmInst,
const WebRtc_Word16* nearendNoisy,
const WebRtc_Word16* nearendClean,
WebRtc_Word16* out,
WebRtc_Word16 nrOfSamples,
WebRtc_Word16 msInSndCardBuf);
/*
* This function enables the user to set certain parameters on-the-fly
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* AecmConfig config Config instance that contains all
* properties to be set
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_set_config(void* aecmInst,
AecmConfig config);
/*
* This function enables the user to set certain parameters on-the-fly
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecmConfig *config Pointer to the config instance that
* all properties will be written to
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_get_config(void *aecmInst,
AecmConfig *config);
/*
* This function enables the user to set the echo path on-the-fly.
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecmInst Pointer to the AECM instance
* void* echo_path Pointer to the echo path to be set
* size_t size_bytes Size in bytes of the echo path
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_InitEchoPath(void* aecmInst,
const void* echo_path,
size_t size_bytes);
/*
* This function enables the user to get the currently used echo path
* on-the-fly
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecmInst Pointer to the AECM instance
* void* echo_path Pointer to echo path
* size_t size_bytes Size in bytes of the echo path
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_GetEchoPath(void* aecmInst,
void* echo_path,
size_t size_bytes);
/*
* This function enables the user to get the echo path size in bytes
*
* Outputs Description
* -------------------------------------------------------------------
* size_t return : size in bytes
*/
size_t WebRtcAecm_echo_path_size_bytes();
/*
* Gets the last error code.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 11000-11100: error code
*/
WebRtc_Word32 WebRtcAecm_get_error_code(void *aecmInst);
#ifdef __cplusplus
}
#endif
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_

View File

@ -1,79 +0,0 @@
/*
* 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_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_
#include <stddef.h>
#include "common_types.h"
#include "typedefs.h"
// Implementation of an InStream and OutStream that can read (exclusive) or
// write from/to a file.
namespace webrtc {
class FileWrapper : public InStream, public OutStream
{
public:
static const size_t kMaxFileNameSize = 1024;
// Factory method. Constructor disabled.
static FileWrapper* Create();
// Returns true if a file has been opened.
virtual bool Open() const = 0;
// Opens a file in read or write mode, decided by the readOnly parameter.
virtual int OpenFile(const char* fileNameUTF8,
bool readOnly,
bool loop = false,
bool text = false) = 0;
virtual int CloseFile() = 0;
// Limits the file size to |bytes|. Writing will fail after the cap
// is hit. Pass zero to use an unlimited size.
virtual int SetMaxFileSize(size_t bytes) = 0;
// Flush any pending writes.
virtual int Flush() = 0;
// Returns the opened file's name in |fileNameUTF8|. Provide the size of
// the buffer in bytes in |size|. The name will be truncated if |size| is
// too small.
virtual int FileName(char* fileNameUTF8,
size_t size) const = 0;
// Write |format| to the opened file. Arguments are taken in the same manner
// as printf. That is, supply a format string containing text and
// specifiers. Returns the number of characters written or -1 on error.
virtual int WriteText(const char* format, ...) = 0;
// Inherited from Instream.
// Reads |length| bytes from file to |buf|. Returns the number of bytes read
// or -1 on error.
virtual int Read(void* buf, int length) = 0;
// Inherited from OutStream.
// Writes |length| bytes from |buf| to file. The actual writing may happen
// some time later. Call Flush() to force a write.
virtual bool Write(const void *buf, int length) = 0;
// Inherited from both Instream and OutStream.
// Rewinds the file to the start. Only available when OpenFile() has been
// called with |loop| == true or |readOnly| == true.
virtual int Rewind() = 0;
};
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_FILE_WRAPPER_H_

View File

@ -0,0 +1,259 @@
/*
* Copyright (c) 2012 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_MODULES_AUDIO_PROCESSING_AGC_INCLUDE_GAIN_CONTROL_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AGC_INCLUDE_GAIN_CONTROL_H_
#include "typedefs.h"
// Errors
#define AGC_UNSPECIFIED_ERROR 18000
#define AGC_UNSUPPORTED_FUNCTION_ERROR 18001
#define AGC_UNINITIALIZED_ERROR 18002
#define AGC_NULL_POINTER_ERROR 18003
#define AGC_BAD_PARAMETER_ERROR 18004
// Warnings
#define AGC_BAD_PARAMETER_WARNING 18050
enum
{
kAgcModeUnchanged,
kAgcModeAdaptiveAnalog,
kAgcModeAdaptiveDigital,
kAgcModeFixedDigital
};
enum
{
kAgcFalse = 0,
kAgcTrue
};
typedef struct
{
WebRtc_Word16 targetLevelDbfs; // default 3 (-3 dBOv)
WebRtc_Word16 compressionGaindB; // default 9 dB
WebRtc_UWord8 limiterEnable; // default kAgcTrue (on)
} WebRtcAgc_config_t;
#if defined(__cplusplus)
extern "C"
{
#endif
/*
* This function processes a 10/20ms frame of far-end speech to determine
* if there is active speech. Far-end speech length can be either 10ms or
* 20ms. The length of the input speech vector must be given in samples
* (80/160 when FS=8000, and 160/320 when FS=16000 or FS=32000).
*
* Input:
* - agcInst : AGC instance.
* - inFar : Far-end input speech vector (10 or 20ms)
* - samples : Number of samples in input vector
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_AddFarend(void* agcInst,
const WebRtc_Word16* inFar,
WebRtc_Word16 samples);
/*
* This function processes a 10/20ms frame of microphone speech to determine
* if there is active speech. Microphone speech length can be either 10ms or
* 20ms. The length of the input speech vector must be given in samples
* (80/160 when FS=8000, and 160/320 when FS=16000 or FS=32000). For very low
* input levels, the input signal is increased in level by multiplying and
* overwriting the samples in inMic[].
*
* This function should be called before any further processing of the
* near-end microphone signal.
*
* Input:
* - agcInst : AGC instance.
* - inMic : Microphone input speech vector (10 or 20 ms) for
* L band
* - inMic_H : Microphone input speech vector (10 or 20 ms) for
* H band
* - samples : Number of samples in input vector
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_AddMic(void* agcInst,
WebRtc_Word16* inMic,
WebRtc_Word16* inMic_H,
WebRtc_Word16 samples);
/*
* This function replaces the analog microphone with a virtual one.
* It is a digital gain applied to the input signal and is used in the
* agcAdaptiveDigital mode where no microphone level is adjustable.
* Microphone speech length can be either 10ms or 20ms. The length of the
* input speech vector must be given in samples (80/160 when FS=8000, and
* 160/320 when FS=16000 or FS=32000).
*
* Input:
* - agcInst : AGC instance.
* - inMic : Microphone input speech vector for (10 or 20 ms)
* L band
* - inMic_H : Microphone input speech vector for (10 or 20 ms)
* H band
* - samples : Number of samples in input vector
* - micLevelIn : Input level of microphone (static)
*
* Output:
* - inMic : Microphone output after processing (L band)
* - inMic_H : Microphone output after processing (H band)
* - micLevelOut : Adjusted microphone level after processing
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_VirtualMic(void* agcInst,
WebRtc_Word16* inMic,
WebRtc_Word16* inMic_H,
WebRtc_Word16 samples,
WebRtc_Word32 micLevelIn,
WebRtc_Word32* micLevelOut);
/*
* This function processes a 10/20ms frame and adjusts (normalizes) the gain
* both analog and digitally. The gain adjustments are done only during
* active periods of speech. The input speech length can be either 10ms or
* 20ms and the output is of the same length. The length of the speech
* vectors must be given in samples (80/160 when FS=8000, and 160/320 when
* FS=16000 or FS=32000). The echo parameter can be used to ensure the AGC will
* not adjust upward in the presence of echo.
*
* This function should be called after processing the near-end microphone
* signal, in any case after any echo cancellation.
*
* Input:
* - agcInst : AGC instance
* - inNear : Near-end input speech vector (10 or 20 ms) for
* L band
* - inNear_H : Near-end input speech vector (10 or 20 ms) for
* H band
* - samples : Number of samples in input/output vector
* - inMicLevel : Current microphone volume level
* - echo : Set to 0 if the signal passed to add_mic is
* almost certainly free of echo; otherwise set
* to 1. If you have no information regarding echo
* set to 0.
*
* Output:
* - outMicLevel : Adjusted microphone volume level
* - out : Gain-adjusted near-end speech vector (L band)
* : May be the same vector as the input.
* - out_H : Gain-adjusted near-end speech vector (H band)
* - saturationWarning : A returned value of 1 indicates a saturation event
* has occurred and the volume cannot be further
* reduced. Otherwise will be set to 0.
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_Process(void* agcInst,
const WebRtc_Word16* inNear,
const WebRtc_Word16* inNear_H,
WebRtc_Word16 samples,
WebRtc_Word16* out,
WebRtc_Word16* out_H,
WebRtc_Word32 inMicLevel,
WebRtc_Word32* outMicLevel,
WebRtc_Word16 echo,
WebRtc_UWord8* saturationWarning);
/*
* This function sets the config parameters (targetLevelDbfs,
* compressionGaindB and limiterEnable).
*
* Input:
* - agcInst : AGC instance
* - config : config struct
*
* Output:
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_set_config(void* agcInst, WebRtcAgc_config_t config);
/*
* This function returns the config parameters (targetLevelDbfs,
* compressionGaindB and limiterEnable).
*
* Input:
* - agcInst : AGC instance
*
* Output:
* - config : config struct
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_get_config(void* agcInst, WebRtcAgc_config_t* config);
/*
* This function creates an AGC instance, which will contain the state
* information for one (duplex) channel.
*
* Return value : AGC instance if successful
* : 0 (i.e., a NULL pointer) if unsuccessful
*/
int WebRtcAgc_Create(void **agcInst);
/*
* This function frees the AGC instance created at the beginning.
*
* Input:
* - agcInst : AGC instance.
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcAgc_Free(void *agcInst);
/*
* This function initializes an AGC instance.
*
* Input:
* - agcInst : AGC instance.
* - minLevel : Minimum possible mic level
* - maxLevel : Maximum possible mic level
* - agcMode : 0 - Unchanged
* : 1 - Adaptive Analog Automatic Gain Control -3dBOv
* : 2 - Adaptive Digital Automatic Gain Control -3dBOv
* : 3 - Fixed Digital Gain 0dB
* - fs : Sampling frequency
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcAgc_Init(void *agcInst,
WebRtc_Word32 minLevel,
WebRtc_Word32 maxLevel,
WebRtc_Word16 agcMode,
WebRtc_UWord32 fs);
#if defined(__cplusplus)
}
#endif
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_INCLUDE_GAIN_CONTROL_H_

View File

@ -1,107 +0,0 @@
/*
* 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_SYSTEM_WRAPPERS_INTERFACE_LIST_WRAPPER_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LIST_WRAPPER_H_
#include "constructor_magic.h"
namespace webrtc {
class CriticalSectionWrapper;
class ListItem
{
friend class ListWrapper;
public:
ListItem(const void* ptr);
ListItem(const unsigned int item);
virtual ~ListItem();
void* GetItem() const;
unsigned int GetUnsignedItem() const;
protected:
ListItem* next_;
ListItem* prev_;
private:
const void* item_ptr_;
const unsigned int item_;
};
class ListWrapper
{
public:
ListWrapper();
virtual ~ListWrapper();
// Returns the number of elements stored in the list.
unsigned int GetSize() const;
// Puts a pointer to anything last in the list.
int PushBack(const void* ptr);
// Puts a pointer to anything first in the list.
int PushFront(const void* ptr);
// Puts a copy of the specified integer last in the list.
int PushBack(const unsigned int item_id);
// Puts a copy of the specified integer first in the list.
int PushFront(const unsigned int item_id);
// Pops the first ListItem from the list
int PopFront();
// Pops the last ListItem from the list
int PopBack();
// Returns true if the list is empty
bool Empty() const;
// Returns a pointer to the first ListItem in the list.
ListItem* First() const;
// Returns a pointer to the last ListItem in the list.
ListItem* Last() const;
// Returns a pointer to the ListItem stored after item in the list.
ListItem* Next(ListItem* item) const;
// Returns a pointer to the ListItem stored before item in the list.
ListItem* Previous(ListItem* item) const;
// Removes item from the list.
int Erase(ListItem* item);
// Insert list item after existing_previous_item. Please note that new_item
// must be created using new ListItem(). The map will take ownership of
// new_item following a successfull insert. If insert fails new_item will
// not be released by the List
int Insert(ListItem* existing_previous_item,
ListItem* new_item);
// Insert list item before existing_next_item. Please note that new_item
// must be created using new ListItem(). The map will take ownership of
// new_item following a successfull insert. If insert fails new_item will
// not be released by the List
int InsertBefore(ListItem* existing_next_item,
ListItem* new_item);
private:
void PushBackImpl(ListItem* item);
void PushFrontImpl(ListItem* item);
CriticalSectionWrapper* critical_section_;
ListItem* first_;
ListItem* last_;
unsigned int size_;
};
} //namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_LIST_WRAPPER_H_

View File

@ -1,66 +0,0 @@
/*
* Copyright (c) 2012 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 MODULES_INTERFACE_MODULE_H_
#define MODULES_INTERFACE_MODULE_H_
#include <assert.h>
#include "typedefs.h"
namespace webrtc {
class Module {
public:
// TODO(henrika): Remove this when chrome is updated.
// DEPRICATED Change the unique identifier of this object.
virtual int32_t ChangeUniqueId(const int32_t id) { return 0; }
// Returns the number of milliseconds until the module want a worker
// thread to call Process.
virtual int32_t TimeUntilNextProcess() = 0;
// Process any pending tasks such as timeouts.
virtual int32_t Process() = 0;
protected:
virtual ~Module() {}
};
// Reference counted version of the module interface.
class RefCountedModule : public Module {
public:
// Increase the reference count by one.
// Returns the incremented reference count.
// TODO(perkj): Make this pure virtual when Chromium have implemented
// reference counting ADM and Video capture module.
virtual int32_t AddRef() {
assert(false && "Not implemented.");
return 1;
}
// Decrease the reference count by one.
// Returns the decreased reference count.
// Returns 0 if the last reference was just released.
// When the reference count reach 0 the object will self-destruct.
// TODO(perkj): Make this pure virtual when Chromium have implemented
// reference counting ADM and Video capture module.
virtual int32_t Release() {
assert(false && "Not implemented.");
return 1;
}
protected:
virtual ~RefCountedModule() {}
};
} // namespace webrtc
#endif // MODULES_INTERFACE_MODULE_H_

View File

@ -20,14 +20,14 @@ extern "C" {
#endif
/*
* This function creates an instance to the noise reduction structure
* This function creates an instance to the noise suppression structure
*
* Input:
* - NS_inst : Pointer to noise reduction instance that should be
* - NS_inst : Pointer to noise suppression instance that should be
* created
*
* Output:
* - NS_inst : Pointer to created noise reduction instance
* - NS_inst : Pointer to created noise suppression instance
*
* Return value : 0 - Ok
* -1 - Error
@ -36,7 +36,7 @@ int WebRtcNs_Create(NsHandle** NS_inst);
/*
* This function frees the dynamic memory of a specified Noise Reduction
* This function frees the dynamic memory of a specified noise suppression
* instance.
*
* Input:
@ -49,7 +49,8 @@ int WebRtcNs_Free(NsHandle* NS_inst);
/*
* This function initializes a NS instance
* This function initializes a NS instance and has to be called before any other
* processing is made.
*
* Input:
* - NS_inst : Instance that should be initialized
@ -67,11 +68,11 @@ int WebRtcNs_Init(NsHandle* NS_inst, WebRtc_UWord32 fs);
* This changes the aggressiveness of the noise suppression method.
*
* Input:
* - NS_inst : Instance that should be initialized
* - NS_inst : Noise suppression instance.
* - mode : 0: Mild, 1: Medium , 2: Aggressive
*
* Output:
* - NS_inst : Initialized instance
* - NS_inst : Updated instance.
*
* Return value : 0 - Ok
* -1 - Error
@ -84,7 +85,7 @@ int WebRtcNs_set_policy(NsHandle* NS_inst, int mode);
* input and output signals should always be 10ms (80 or 160 samples).
*
* Input
* - NS_inst : NS Instance. Needs to be initiated before call.
* - NS_inst : Noise suppression instance.
* - spframe : Pointer to speech frame buffer for L band
* - spframe_H : Pointer to speech frame buffer for H band
* - fs : sampling frequency
@ -103,6 +104,18 @@ int WebRtcNs_Process(NsHandle* NS_inst,
short* outframe,
short* outframe_H);
/* Returns the internally used prior speech probability of the current frame.
* There is a frequency bin based one as well, with which this should not be
* confused.
*
* Input
* - handle : Noise suppression instance.
*
* Return value : Prior speech probability in interval [0.0, 1.0].
* -1 - NULL pointer or uninitialized instance.
*/
float WebRtcNs_prior_speech_probability(NsHandle* handle);
#ifdef __cplusplus
}
#endif

View File

@ -9,17 +9,22 @@
*/
// This file contains platform-specific typedefs and defines.
// Much of it is derived from Chromium's build/build_config.h.
#ifndef WEBRTC_TYPEDEFS_H_
#define WEBRTC_TYPEDEFS_H_
// Reserved words definitions
// TODO(andrew): Look at removing these.
#define WEBRTC_EXTERN extern
// TODO(andrew): Remove this.
#define G_CONST const
#define WEBRTC_INLINE extern __inline
// Derived from Chromium's build/build_config.h
// For access to standard POSIXish features, use WEBRTC_POSIX instead of a
// more specific macro.
#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX) || \
defined(WEBRTC_ANDROID)
#define WEBRTC_POSIX
#endif
// Processor architecture detection. For more info on what's defined, see:
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
// http://www.agner.org/optimize/calling_conventions.pdf
@ -48,6 +53,10 @@
#define WEBRTC_ARCH_32_BITS
#define WEBRTC_ARCH_LITTLE_ENDIAN
#define WEBRTC_LITTLE_ENDIAN
#elif defined(__MIPSEL__)
#define WEBRTC_ARCH_32_BITS
#define WEBRTC_ARCH_LITTLE_ENDIAN
#define WEBRTC_LITTLE_ENDIAN
#else
#error Please add support for your architecture in typedefs.h
#endif

View File

@ -0,0 +1,262 @@
/*
* Copyright (c) 2012 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_MODULES_AUDIO_PROCESSING_AEC_INCLUDE_ECHO_CANCELLATION_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_INCLUDE_ECHO_CANCELLATION_H_
#include "typedefs.h"
// Errors
#define AEC_UNSPECIFIED_ERROR 12000
#define AEC_UNSUPPORTED_FUNCTION_ERROR 12001
#define AEC_UNINITIALIZED_ERROR 12002
#define AEC_NULL_POINTER_ERROR 12003
#define AEC_BAD_PARAMETER_ERROR 12004
// Warnings
#define AEC_BAD_PARAMETER_WARNING 12050
enum {
kAecNlpConservative = 0,
kAecNlpModerate,
kAecNlpAggressive
};
enum {
kAecFalse = 0,
kAecTrue
};
typedef struct {
WebRtc_Word16 nlpMode; // default kAecNlpModerate
WebRtc_Word16 skewMode; // default kAecFalse
WebRtc_Word16 metricsMode; // default kAecFalse
int delay_logging; // default kAecFalse
//float realSkew;
} AecConfig;
typedef struct {
WebRtc_Word16 instant;
WebRtc_Word16 average;
WebRtc_Word16 max;
WebRtc_Word16 min;
} AecLevel;
typedef struct {
AecLevel rerl;
AecLevel erl;
AecLevel erle;
AecLevel aNlp;
} AecMetrics;
#ifdef __cplusplus
extern "C" {
#endif
/*
* Allocates the memory needed by the AEC. The memory needs to be initialized
* separately using the WebRtcAec_Init() function.
*
* Inputs Description
* -------------------------------------------------------------------
* void **aecInst Pointer to the AEC instance to be created
* and initialized
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_Create(void **aecInst);
/*
* This function releases the memory allocated by WebRtcAec_Create().
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_Free(void *aecInst);
/*
* Initializes an AEC instance.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
* WebRtc_Word32 sampFreq Sampling frequency of data
* WebRtc_Word32 scSampFreq Soundcard sampling frequency
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_Init(void *aecInst,
WebRtc_Word32 sampFreq,
WebRtc_Word32 scSampFreq);
/*
* Inserts an 80 or 160 sample block of data into the farend buffer.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
* WebRtc_Word16 *farend In buffer containing one frame of
* farend signal for L band
* WebRtc_Word16 nrOfSamples Number of samples in farend buffer
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_BufferFarend(void *aecInst,
const WebRtc_Word16 *farend,
WebRtc_Word16 nrOfSamples);
/*
* Runs the echo canceller on an 80 or 160 sample blocks of data.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
* WebRtc_Word16 *nearend In buffer containing one frame of
* nearend+echo signal for L band
* WebRtc_Word16 *nearendH In buffer containing one frame of
* nearend+echo signal for H band
* WebRtc_Word16 nrOfSamples Number of samples in nearend buffer
* WebRtc_Word16 msInSndCardBuf Delay estimate for sound card and
* system buffers
* WebRtc_Word16 skew Difference between number of samples played
* and recorded at the soundcard (for clock skew
* compensation)
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word16 *out Out buffer, one frame of processed nearend
* for L band
* WebRtc_Word16 *outH Out buffer, one frame of processed nearend
* for H band
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_Process(void *aecInst,
const WebRtc_Word16 *nearend,
const WebRtc_Word16 *nearendH,
WebRtc_Word16 *out,
WebRtc_Word16 *outH,
WebRtc_Word16 nrOfSamples,
WebRtc_Word16 msInSndCardBuf,
WebRtc_Word32 skew);
/*
* This function enables the user to set certain parameters on-the-fly.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
* AecConfig config Config instance that contains all
* properties to be set
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_set_config(void *aecInst, AecConfig config);
/*
* Gets the on-the-fly paramters.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecConfig *config Pointer to the config instance that
* all properties will be written to
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_get_config(void *aecInst, AecConfig *config);
/*
* Gets the current echo status of the nearend signal.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word16 *status 0: Almost certainly nearend single-talk
* 1: Might not be neared single-talk
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_get_echo_status(void *aecInst, WebRtc_Word16 *status);
/*
* Gets the current echo metrics for the session.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecMetrics *metrics Struct which will be filled out with the
* current echo metrics.
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics);
/*
* Gets the current delay metrics for the session.
*
* Inputs Description
* -------------------------------------------------------------------
* void* handle Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* int* median Delay median value.
* int* std Delay standard deviation.
*
* int return 0: OK
* -1: error
*/
int WebRtcAec_GetDelayMetrics(void* handle, int* median, int* std);
/*
* Gets the last error code.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 11000-11100: error code
*/
WebRtc_Word32 WebRtcAec_get_error_code(void *aecInst);
#ifdef __cplusplus
}
#endif
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_INCLUDE_ECHO_CANCELLATION_H_

View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 2012 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_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_
#include "typedefs.h"
enum {
AecmFalse = 0,
AecmTrue
};
// Errors
#define AECM_UNSPECIFIED_ERROR 12000
#define AECM_UNSUPPORTED_FUNCTION_ERROR 12001
#define AECM_UNINITIALIZED_ERROR 12002
#define AECM_NULL_POINTER_ERROR 12003
#define AECM_BAD_PARAMETER_ERROR 12004
// Warnings
#define AECM_BAD_PARAMETER_WARNING 12100
typedef struct {
WebRtc_Word16 cngMode; // AECM_FALSE, AECM_TRUE (default)
WebRtc_Word16 echoMode; // 0, 1, 2, 3 (default), 4
} AecmConfig;
#ifdef __cplusplus
extern "C" {
#endif
/*
* Allocates the memory needed by the AECM. The memory needs to be
* initialized separately using the WebRtcAecm_Init() function.
*
* Inputs Description
* -------------------------------------------------------------------
* void **aecmInst Pointer to the AECM instance to be
* created and initialized
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Create(void **aecmInst);
/*
* This function releases the memory allocated by WebRtcAecm_Create()
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Free(void *aecmInst);
/*
* Initializes an AECM instance.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* WebRtc_Word32 sampFreq Sampling frequency of data
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Init(void* aecmInst,
WebRtc_Word32 sampFreq);
/*
* Inserts an 80 or 160 sample block of data into the farend buffer.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* WebRtc_Word16 *farend In buffer containing one frame of
* farend signal
* WebRtc_Word16 nrOfSamples Number of samples in farend buffer
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_BufferFarend(void* aecmInst,
const WebRtc_Word16* farend,
WebRtc_Word16 nrOfSamples);
/*
* Runs the AECM on an 80 or 160 sample blocks of data.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* WebRtc_Word16 *nearendNoisy In buffer containing one frame of
* reference nearend+echo signal. If
* noise reduction is active, provide
* the noisy signal here.
* WebRtc_Word16 *nearendClean In buffer containing one frame of
* nearend+echo signal. If noise
* reduction is active, provide the
* clean signal here. Otherwise pass a
* NULL pointer.
* WebRtc_Word16 nrOfSamples Number of samples in nearend buffer
* WebRtc_Word16 msInSndCardBuf Delay estimate for sound card and
* system buffers
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word16 *out Out buffer, one frame of processed nearend
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Process(void* aecmInst,
const WebRtc_Word16* nearendNoisy,
const WebRtc_Word16* nearendClean,
WebRtc_Word16* out,
WebRtc_Word16 nrOfSamples,
WebRtc_Word16 msInSndCardBuf);
/*
* This function enables the user to set certain parameters on-the-fly
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* AecmConfig config Config instance that contains all
* properties to be set
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_set_config(void* aecmInst,
AecmConfig config);
/*
* This function enables the user to set certain parameters on-the-fly
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecmConfig *config Pointer to the config instance that
* all properties will be written to
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_get_config(void *aecmInst,
AecmConfig *config);
/*
* This function enables the user to set the echo path on-the-fly.
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecmInst Pointer to the AECM instance
* void* echo_path Pointer to the echo path to be set
* size_t size_bytes Size in bytes of the echo path
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_InitEchoPath(void* aecmInst,
const void* echo_path,
size_t size_bytes);
/*
* This function enables the user to get the currently used echo path
* on-the-fly
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecmInst Pointer to the AECM instance
* void* echo_path Pointer to echo path
* size_t size_bytes Size in bytes of the echo path
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_GetEchoPath(void* aecmInst,
void* echo_path,
size_t size_bytes);
/*
* This function enables the user to get the echo path size in bytes
*
* Outputs Description
* -------------------------------------------------------------------
* size_t return : size in bytes
*/
size_t WebRtcAecm_echo_path_size_bytes();
/*
* Gets the last error code.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 11000-11100: error code
*/
WebRtc_Word32 WebRtcAecm_get_error_code(void *aecmInst);
#ifdef __cplusplus
}
#endif
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_

View File

@ -0,0 +1,259 @@
/*
* Copyright (c) 2012 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_MODULES_AUDIO_PROCESSING_AGC_INCLUDE_GAIN_CONTROL_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AGC_INCLUDE_GAIN_CONTROL_H_
#include "typedefs.h"
// Errors
#define AGC_UNSPECIFIED_ERROR 18000
#define AGC_UNSUPPORTED_FUNCTION_ERROR 18001
#define AGC_UNINITIALIZED_ERROR 18002
#define AGC_NULL_POINTER_ERROR 18003
#define AGC_BAD_PARAMETER_ERROR 18004
// Warnings
#define AGC_BAD_PARAMETER_WARNING 18050
enum
{
kAgcModeUnchanged,
kAgcModeAdaptiveAnalog,
kAgcModeAdaptiveDigital,
kAgcModeFixedDigital
};
enum
{
kAgcFalse = 0,
kAgcTrue
};
typedef struct
{
WebRtc_Word16 targetLevelDbfs; // default 3 (-3 dBOv)
WebRtc_Word16 compressionGaindB; // default 9 dB
WebRtc_UWord8 limiterEnable; // default kAgcTrue (on)
} WebRtcAgc_config_t;
#if defined(__cplusplus)
extern "C"
{
#endif
/*
* This function processes a 10/20ms frame of far-end speech to determine
* if there is active speech. Far-end speech length can be either 10ms or
* 20ms. The length of the input speech vector must be given in samples
* (80/160 when FS=8000, and 160/320 when FS=16000 or FS=32000).
*
* Input:
* - agcInst : AGC instance.
* - inFar : Far-end input speech vector (10 or 20ms)
* - samples : Number of samples in input vector
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_AddFarend(void* agcInst,
const WebRtc_Word16* inFar,
WebRtc_Word16 samples);
/*
* This function processes a 10/20ms frame of microphone speech to determine
* if there is active speech. Microphone speech length can be either 10ms or
* 20ms. The length of the input speech vector must be given in samples
* (80/160 when FS=8000, and 160/320 when FS=16000 or FS=32000). For very low
* input levels, the input signal is increased in level by multiplying and
* overwriting the samples in inMic[].
*
* This function should be called before any further processing of the
* near-end microphone signal.
*
* Input:
* - agcInst : AGC instance.
* - inMic : Microphone input speech vector (10 or 20 ms) for
* L band
* - inMic_H : Microphone input speech vector (10 or 20 ms) for
* H band
* - samples : Number of samples in input vector
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_AddMic(void* agcInst,
WebRtc_Word16* inMic,
WebRtc_Word16* inMic_H,
WebRtc_Word16 samples);
/*
* This function replaces the analog microphone with a virtual one.
* It is a digital gain applied to the input signal and is used in the
* agcAdaptiveDigital mode where no microphone level is adjustable.
* Microphone speech length can be either 10ms or 20ms. The length of the
* input speech vector must be given in samples (80/160 when FS=8000, and
* 160/320 when FS=16000 or FS=32000).
*
* Input:
* - agcInst : AGC instance.
* - inMic : Microphone input speech vector for (10 or 20 ms)
* L band
* - inMic_H : Microphone input speech vector for (10 or 20 ms)
* H band
* - samples : Number of samples in input vector
* - micLevelIn : Input level of microphone (static)
*
* Output:
* - inMic : Microphone output after processing (L band)
* - inMic_H : Microphone output after processing (H band)
* - micLevelOut : Adjusted microphone level after processing
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_VirtualMic(void* agcInst,
WebRtc_Word16* inMic,
WebRtc_Word16* inMic_H,
WebRtc_Word16 samples,
WebRtc_Word32 micLevelIn,
WebRtc_Word32* micLevelOut);
/*
* This function processes a 10/20ms frame and adjusts (normalizes) the gain
* both analog and digitally. The gain adjustments are done only during
* active periods of speech. The input speech length can be either 10ms or
* 20ms and the output is of the same length. The length of the speech
* vectors must be given in samples (80/160 when FS=8000, and 160/320 when
* FS=16000 or FS=32000). The echo parameter can be used to ensure the AGC will
* not adjust upward in the presence of echo.
*
* This function should be called after processing the near-end microphone
* signal, in any case after any echo cancellation.
*
* Input:
* - agcInst : AGC instance
* - inNear : Near-end input speech vector (10 or 20 ms) for
* L band
* - inNear_H : Near-end input speech vector (10 or 20 ms) for
* H band
* - samples : Number of samples in input/output vector
* - inMicLevel : Current microphone volume level
* - echo : Set to 0 if the signal passed to add_mic is
* almost certainly free of echo; otherwise set
* to 1. If you have no information regarding echo
* set to 0.
*
* Output:
* - outMicLevel : Adjusted microphone volume level
* - out : Gain-adjusted near-end speech vector (L band)
* : May be the same vector as the input.
* - out_H : Gain-adjusted near-end speech vector (H band)
* - saturationWarning : A returned value of 1 indicates a saturation event
* has occurred and the volume cannot be further
* reduced. Otherwise will be set to 0.
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_Process(void* agcInst,
const WebRtc_Word16* inNear,
const WebRtc_Word16* inNear_H,
WebRtc_Word16 samples,
WebRtc_Word16* out,
WebRtc_Word16* out_H,
WebRtc_Word32 inMicLevel,
WebRtc_Word32* outMicLevel,
WebRtc_Word16 echo,
WebRtc_UWord8* saturationWarning);
/*
* This function sets the config parameters (targetLevelDbfs,
* compressionGaindB and limiterEnable).
*
* Input:
* - agcInst : AGC instance
* - config : config struct
*
* Output:
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_set_config(void* agcInst, WebRtcAgc_config_t config);
/*
* This function returns the config parameters (targetLevelDbfs,
* compressionGaindB and limiterEnable).
*
* Input:
* - agcInst : AGC instance
*
* Output:
* - config : config struct
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_get_config(void* agcInst, WebRtcAgc_config_t* config);
/*
* This function creates an AGC instance, which will contain the state
* information for one (duplex) channel.
*
* Return value : AGC instance if successful
* : 0 (i.e., a NULL pointer) if unsuccessful
*/
int WebRtcAgc_Create(void **agcInst);
/*
* This function frees the AGC instance created at the beginning.
*
* Input:
* - agcInst : AGC instance.
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcAgc_Free(void *agcInst);
/*
* This function initializes an AGC instance.
*
* Input:
* - agcInst : AGC instance.
* - minLevel : Minimum possible mic level
* - maxLevel : Maximum possible mic level
* - agcMode : 0 - Unchanged
* : 1 - Adaptive Analog Automatic Gain Control -3dBOv
* : 2 - Adaptive Digital Automatic Gain Control -3dBOv
* : 3 - Fixed Digital Gain 0dB
* - fs : Sampling frequency
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcAgc_Init(void *agcInst,
WebRtc_Word32 minLevel,
WebRtc_Word32 maxLevel,
WebRtc_Word16 agcMode,
WebRtc_UWord32 fs);
#if defined(__cplusplus)
}
#endif
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_INCLUDE_GAIN_CONTROL_H_

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2012 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_MODULES_AUDIO_PROCESSING_NS_INCLUDE_NOISE_SUPPRESSION_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_NS_INCLUDE_NOISE_SUPPRESSION_H_
#include "typedefs.h"
typedef struct NsHandleT NsHandle;
#ifdef __cplusplus
extern "C" {
#endif
/*
* This function creates an instance to the noise suppression structure
*
* Input:
* - NS_inst : Pointer to noise suppression instance that should be
* created
*
* Output:
* - NS_inst : Pointer to created noise suppression instance
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcNs_Create(NsHandle** NS_inst);
/*
* This function frees the dynamic memory of a specified noise suppression
* instance.
*
* Input:
* - NS_inst : Pointer to NS instance that should be freed
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcNs_Free(NsHandle* NS_inst);
/*
* This function initializes a NS instance and has to be called before any other
* processing is made.
*
* Input:
* - NS_inst : Instance that should be initialized
* - fs : sampling frequency
*
* Output:
* - NS_inst : Initialized instance
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcNs_Init(NsHandle* NS_inst, WebRtc_UWord32 fs);
/*
* This changes the aggressiveness of the noise suppression method.
*
* Input:
* - NS_inst : Noise suppression instance.
* - mode : 0: Mild, 1: Medium , 2: Aggressive
*
* Output:
* - NS_inst : Updated instance.
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcNs_set_policy(NsHandle* NS_inst, int mode);
/*
* This functions does Noise Suppression for the inserted speech frame. The
* input and output signals should always be 10ms (80 or 160 samples).
*
* Input
* - NS_inst : Noise suppression instance.
* - spframe : Pointer to speech frame buffer for L band
* - spframe_H : Pointer to speech frame buffer for H band
* - fs : sampling frequency
*
* Output:
* - NS_inst : Updated NS instance
* - outframe : Pointer to output frame for L band
* - outframe_H : Pointer to output frame for H band
*
* Return value : 0 - OK
* -1 - Error
*/
int WebRtcNs_Process(NsHandle* NS_inst,
short* spframe,
short* spframe_H,
short* outframe,
short* outframe_H);
/* Returns the internally used prior speech probability of the current frame.
* There is a frequency bin based one as well, with which this should not be
* confused.
*
* Input
* - handle : Noise suppression instance.
*
* Return value : Prior speech probability in interval [0.0, 1.0].
* -1 - NULL pointer or uninitialized instance.
*/
float WebRtcNs_prior_speech_probability(NsHandle* handle);
#ifdef __cplusplus
}
#endif
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_NS_INCLUDE_NOISE_SUPPRESSION_H_

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2012 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_MODULES_AUDIO_PROCESSING_NS_INCLUDE_NOISE_SUPPRESSION_X_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_NS_INCLUDE_NOISE_SUPPRESSION_X_H_
#include "typedefs.h"
typedef struct NsxHandleT NsxHandle;
#ifdef __cplusplus
extern "C" {
#endif
/*
* This function creates an instance to the noise reduction structure
*
* Input:
* - nsxInst : Pointer to noise reduction instance that should be
* created
*
* Output:
* - nsxInst : Pointer to created noise reduction instance
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcNsx_Create(NsxHandle** nsxInst);
/*
* This function frees the dynamic memory of a specified Noise Suppression
* instance.
*
* Input:
* - nsxInst : Pointer to NS instance that should be freed
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcNsx_Free(NsxHandle* nsxInst);
/*
* This function initializes a NS instance
*
* Input:
* - nsxInst : Instance that should be initialized
* - fs : sampling frequency
*
* Output:
* - nsxInst : Initialized instance
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcNsx_Init(NsxHandle* nsxInst, WebRtc_UWord32 fs);
/*
* This changes the aggressiveness of the noise suppression method.
*
* Input:
* - nsxInst : Instance that should be initialized
* - mode : 0: Mild, 1: Medium , 2: Aggressive
*
* Output:
* - nsxInst : Initialized instance
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcNsx_set_policy(NsxHandle* nsxInst, int mode);
/*
* This functions does noise suppression for the inserted speech frame. The
* input and output signals should always be 10ms (80 or 160 samples).
*
* Input
* - nsxInst : NSx instance. Needs to be initiated before call.
* - speechFrame : Pointer to speech frame buffer for L band
* - speechFrameHB : Pointer to speech frame buffer for H band
* - fs : sampling frequency
*
* Output:
* - nsxInst : Updated NSx instance
* - outFrame : Pointer to output frame for L band
* - outFrameHB : Pointer to output frame for H band
*
* Return value : 0 - OK
* -1 - Error
*/
int WebRtcNsx_Process(NsxHandle* nsxInst,
short* speechFrame,
short* speechFrameHB,
short* outFrame,
short* outFrameHB);
#ifdef __cplusplus
}
#endif
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_NS_INCLUDE_NOISE_SUPPRESSION_X_H_

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2012 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.
*/
// This file contains platform-specific typedefs and defines.
// Much of it is derived from Chromium's build/build_config.h.
#ifndef WEBRTC_TYPEDEFS_H_
#define WEBRTC_TYPEDEFS_H_
// Reserved words definitions
// TODO(andrew): Remove this.
#define G_CONST const
// For access to standard POSIXish features, use WEBRTC_POSIX instead of a
// more specific macro.
#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX) || \
defined(WEBRTC_ANDROID)
#define WEBRTC_POSIX
#endif
// Processor architecture detection. For more info on what's defined, see:
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
// http://www.agner.org/optimize/calling_conventions.pdf
// or with gcc, run: "echo | gcc -E -dM -"
// TODO(andrew): replace WEBRTC_LITTLE_ENDIAN with WEBRTC_ARCH_LITTLE_ENDIAN.
#if defined(_M_X64) || defined(__x86_64__)
#define WEBRTC_ARCH_X86_FAMILY
#define WEBRTC_ARCH_X86_64
#define WEBRTC_ARCH_64_BITS
#define WEBRTC_ARCH_LITTLE_ENDIAN
#define WEBRTC_LITTLE_ENDIAN
#elif defined(_M_IX86) || defined(__i386__)
#define WEBRTC_ARCH_X86_FAMILY
#define WEBRTC_ARCH_X86
#define WEBRTC_ARCH_32_BITS
#define WEBRTC_ARCH_LITTLE_ENDIAN
#define WEBRTC_LITTLE_ENDIAN
#elif defined(__ARMEL__)
// TODO(andrew): We'd prefer to control platform defines here, but this is
// currently provided by the Android makefiles. Commented to avoid duplicate
// definition warnings.
//#define WEBRTC_ARCH_ARM
// TODO(andrew): Chromium uses the following two defines. Should we switch?
//#define WEBRTC_ARCH_ARM_FAMILY
//#define WEBRTC_ARCH_ARMEL
#define WEBRTC_ARCH_32_BITS
#define WEBRTC_ARCH_LITTLE_ENDIAN
#define WEBRTC_LITTLE_ENDIAN
#elif defined(__MIPSEL__)
#define WEBRTC_ARCH_32_BITS
#define WEBRTC_ARCH_LITTLE_ENDIAN
#define WEBRTC_LITTLE_ENDIAN
#else
#error Please add support for your architecture in typedefs.h
#endif
#if defined(__SSE2__) || defined(_MSC_VER)
#define WEBRTC_USE_SSE2
#endif
#if !defined(_MSC_VER)
#include <stdint.h>
#else
// Define C99 equivalent types, since MSVC doesn't provide stdint.h.
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef __int64 int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned __int64 uint64_t;
#endif
// TODO(andrew): remove WebRtc_ types:
// http://code.google.com/p/webrtc/issues/detail?id=314
typedef int8_t WebRtc_Word8;
typedef int16_t WebRtc_Word16;
typedef int32_t WebRtc_Word32;
typedef int64_t WebRtc_Word64;
typedef uint8_t WebRtc_UWord8;
typedef uint16_t WebRtc_UWord16;
typedef uint32_t WebRtc_UWord32;
typedef uint64_t WebRtc_UWord64;
#endif // WEBRTC_TYPEDEFS_H_

View File

@ -81,30 +81,7 @@
TDAV_BEGIN_DECLS
/** Speex denoiser*/
typedef struct tdav_webrtc_denoise_s
{
TMEDIA_DECLARE_DENOISE;
void *AEC_inst;
#if HAVE_SPEEX_DSP && PREFER_SPEEX_DENOISER
SpeexPreprocessState *SpeexDenoiser_proc;
#else
TDAV_NsHandle *NS_inst;
#endif
uint32_t echo_tail;
uint32_t echo_skew;
uint32_t record_frame_size_samples, record_sampling_rate;
uint32_t playback_frame_size_samples, playback_sampling_rate;
int16_t *temp_rec_out;
TSK_DECLARE_SAFEOBJ;
}
tdav_webrtc_denoise_t;
const tmedia_denoise_plugin_def_t *tdav_webrtc_denoise_plugin_def_t;
extern const tmedia_denoise_plugin_def_t *tdav_webrtc_denoise_plugin_def_t;
TDAV_END_DECLS

View File

@ -62,7 +62,7 @@
#endif
// Mobile
#if defined(_WIN32_WCE) || defined(ANDROID) || TDAV_UNDER_IPHONE || TDAV_UNDER_IPHONE_SIMULATOR
#if defined(_WIN32_WCE) || defined(ANDROID) || TDAV_UNDER_IPHONE || TDAV_UNDER_IPHONE_SIMULATOR || TDAV_UNDER_WINDOWS_PHONE
# define TDAV_UNDER_MOBILE 1
#endif

View File

@ -84,9 +84,9 @@ static void* TSK_STDCALL _tdav_consumer_dsound_playback_thread(void *param)
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
while(dsound->started){
while (dsound->started) {
dwEvent = WaitForMultipleObjects(TDAV_DSOUND_CONSUMER_NOTIF_POS_COUNT, dsound->notifEvents, FALSE, INFINITE);
if(!dsound->started){
if (!dsound->started) {
break;
}
@ -98,28 +98,30 @@ static void* TSK_STDCALL _tdav_consumer_dsound_playback_thread(void *param)
&lpvAudio1, &dwBytesAudio1,
&lpvAudio2, &dwBytesAudio2,
DSBLOCK_FROMWRITECURSOR);
if(hr != DS_OK){
if (hr != DS_OK) {
tdav_win32_print_error("IDirectSoundBuffer_Lock", hr);
goto next;
}
out_size = tdav_consumer_audio_get(TDAV_CONSUMER_AUDIO(dsound), dsound->bytes_per_notif_ptr, dsound->bytes_per_notif_size);
if(out_size < dsound->bytes_per_notif_size) {
if (out_size < dsound->bytes_per_notif_size) {
// fill with silence
memset(&dsound->bytes_per_notif_ptr[out_size], 0, (dsound->bytes_per_notif_size - out_size));
}
if((dwBytesAudio1 + dwBytesAudio2) == dsound->bytes_per_notif_size) {
if ((dwBytesAudio1 + dwBytesAudio2) == dsound->bytes_per_notif_size) {
memcpy(lpvAudio1, dsound->bytes_per_notif_ptr, dwBytesAudio1);
if(lpvAudio2 && dwBytesAudio2) {
if (lpvAudio2 && dwBytesAudio2) {
memcpy(lpvAudio2, &dsound->bytes_per_notif_ptr[dwBytesAudio1], dwBytesAudio2);
}
}
else {
TSK_DEBUG_ERROR("Not expected: %d+%d#%d", dwBytesAudio1, dwBytesAudio2, dsound->bytes_per_notif_size);
}
#if 0
memset(lpvAudio1, rand(), dwBytesAudio1);
#endif
// unlock
if((hr = IDirectSoundBuffer_Unlock(dsound->secondaryBuffer, lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2)) != DS_OK){
if ((hr = IDirectSoundBuffer_Unlock(dsound->secondaryBuffer, lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2)) != DS_OK) {
tdav_win32_print_error("IDirectSoundBuffer_UnLock", hr);
goto next;
}
@ -203,6 +205,11 @@ static int tdav_consumer_dsound_prepare(tmedia_consumer_t* self, const tmedia_co
TMEDIA_CONSUMER(dsound)->audio.in.channels = TMEDIA_CODEC_CHANNELS_AUDIO_DECODING(codec);
TMEDIA_CONSUMER(dsound)->audio.in.rate = TMEDIA_CODEC_RATE_DECODING(codec);
#if 0
TMEDIA_CONSUMER(dsound)->audio.out.rate = 48000;
TMEDIA_CONSUMER(dsound)->audio.out.channels = 2;
#endif
/* Create sound device */
if((hr = DirectSoundCreate(NULL, &dsound->device, NULL) != DS_OK)){
tdav_win32_print_error("DirectSoundCreate", hr);
@ -219,7 +226,7 @@ static int tdav_consumer_dsound_prepare(tmedia_consumer_t* self, const tmedia_co
/* Creates the primary buffer and apply format */
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = TMEDIA_CONSUMER(dsound)->audio.in.channels;
wfx.nChannels = TMEDIA_CONSUMER(dsound)->audio.out.channels ? TMEDIA_CONSUMER(dsound)->audio.out.channels : TMEDIA_CONSUMER(dsound)->audio.in.channels;
wfx.nSamplesPerSec = TMEDIA_CONSUMER(dsound)->audio.out.rate ? TMEDIA_CONSUMER(dsound)->audio.out.rate : TMEDIA_CONSUMER(dsound)->audio.in.rate;
wfx.wBitsPerSample = TMEDIA_CONSUMER(dsound)->audio.bits_per_sample;
wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample/8);

View File

@ -79,27 +79,32 @@ static void* TSK_STDCALL _tdav_producer_dsound_record_thread(void *param)
HRESULT hr;
LPVOID lpvAudio1, lpvAudio2;
DWORD dwBytesAudio1, dwBytesAudio2, dwEvent;
DWORD dwBytesAudio1, dwBytesAudio2, dwEvent, dwIndex;
TSK_DEBUG_INFO("__record_thread -- START");
TSK_DEBUG_INFO("_tdav_producer_dsound_record_thread -- START");
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
while(dsound->started){
while (dsound->started) {
dwEvent = WaitForMultipleObjects(TDAV_DSOUND_PRODUCER_NOTIF_POS_COUNT, dsound->notifEvents, FALSE, INFINITE);
if(!dsound->started){
if (!dsound->started) {
break;
}
if (dwEvent < WAIT_OBJECT_0 || dwEvent > (WAIT_OBJECT_0 + TDAV_DSOUND_PRODUCER_NOTIF_POS_COUNT)) {
TSK_DEBUG_ERROR("Invalid dwEvent(%d)", dwEvent);
break;
}
dwIndex = (dwEvent - WAIT_OBJECT_0);
// lock
if((hr = IDirectSoundCaptureBuffer_Lock(dsound->captureBuffer, (dwEvent * dsound->bytes_per_notif_size), dsound->bytes_per_notif_size, &lpvAudio1, &dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0)) != DS_OK){
if ((hr = IDirectSoundCaptureBuffer_Lock(dsound->captureBuffer, (dwIndex * dsound->bytes_per_notif_size), dsound->bytes_per_notif_size, &lpvAudio1, &dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0)) != DS_OK) {
tdav_win32_print_error("IDirectSoundCaptureBuffer_Lock", hr);
continue;
}
if(TMEDIA_PRODUCER(dsound)->enc_cb.callback){
if (TMEDIA_PRODUCER(dsound)->enc_cb.callback) {
#if SEND_SILENCE_ON_MUTE
if(dsound->mute){
if (dsound->mute) {
memset(lpvAudio1, 0, dwBytesAudio1);
if(lpvAudio2){
memset(lpvAudio2, 0, dwBytesAudio2);
@ -107,19 +112,19 @@ static void* TSK_STDCALL _tdav_producer_dsound_record_thread(void *param)
}
#endif
TMEDIA_PRODUCER(dsound)->enc_cb.callback(TMEDIA_PRODUCER(dsound)->enc_cb.callback_data, lpvAudio1, dwBytesAudio1);
if(lpvAudio2){
if (lpvAudio2) {
TMEDIA_PRODUCER(dsound)->enc_cb.callback(TMEDIA_PRODUCER(dsound)->enc_cb.callback_data, lpvAudio2, dwBytesAudio2);
}
}
// unlock
if((hr = IDirectSoundCaptureBuffer_Unlock(dsound->captureBuffer, lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2)) != DS_OK){
if ((hr = IDirectSoundCaptureBuffer_Unlock(dsound->captureBuffer, lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2)) != DS_OK) {
tdav_win32_print_error("IDirectSoundCaptureBuffer_Unlock", hr);
continue;
}
}
TSK_DEBUG_INFO("__record_thread -- STOP");
TSK_DEBUG_INFO("_tdav_producer_dsound_record_thread -- STOP");
return tsk_null;
@ -127,18 +132,18 @@ static void* TSK_STDCALL _tdav_producer_dsound_record_thread(void *param)
static int _tdav_producer_dsound_unprepare(tdav_producer_dsound_t* dsound)
{
if(dsound){
if (dsound) {
tsk_size_t i;
if(dsound->captureBuffer){
if (dsound->captureBuffer) {
IDirectSoundCaptureBuffer_Release(dsound->captureBuffer);
dsound->captureBuffer = NULL;
}
if(dsound->device){
if (dsound->device) {
IDirectSoundCapture_Release(dsound->device);
dsound->device = NULL;
}
for(i = 0; i<sizeof(dsound->notifEvents)/sizeof(dsound->notifEvents[0]); i++){
if(dsound->notifEvents[i]){
for (i = 0; i<(sizeof(dsound->notifEvents)/sizeof(dsound->notifEvents[0])); i++){
if(dsound->notifEvents[i]) {
CloseHandle(dsound->notifEvents[i]);
dsound->notifEvents[i] = NULL;
}
@ -154,19 +159,19 @@ static int _tdav_producer_dsound_unprepare(tdav_producer_dsound_t* dsound)
static int tdav_producer_dsound_set(tmedia_producer_t* self, const tmedia_param_t* param)
{
tdav_producer_dsound_t* dsound = (tdav_producer_dsound_t*)self;
if(param->plugin_type == tmedia_ppt_producer){
if(param->value_type == tmedia_pvt_int32){
if(tsk_striequals(param->key, "volume")){
if (param->plugin_type == tmedia_ppt_producer) {
if (param->value_type == tmedia_pvt_int32) {
if (tsk_striequals(param->key, "volume")) {
return 0;
}
else if(tsk_striequals(param->key, "mute")){
else if (tsk_striequals(param->key, "mute")) {
dsound->mute = (TSK_TO_INT32((uint8_t*)param->value) != 0);
#if !SEND_SILENCE_ON_MUTE
if(dsound->started){
if(dsound->mute){
if (dsound->started) {
if (dsound->mute) {
IDirectSoundCaptureBuffer_Stop(dsound->captureBuffer);
}
else{
else {
IDirectSoundCaptureBuffer_Start(dsound->captureBuffer, DSBPLAY_LOOPING);
}
}
@ -186,12 +191,12 @@ static int tdav_producer_dsound_prepare(tmedia_producer_t* self, const tmedia_co
tdav_producer_dsound_t* dsound = (tdav_producer_dsound_t*)self;
if(!dsound || !codec){
if (!dsound || !codec) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(dsound->device || dsound->captureBuffer){
if (dsound->device || dsound->captureBuffer) {
TSK_DEBUG_ERROR("Producer already prepared");
return -2;
}
@ -200,8 +205,13 @@ static int tdav_producer_dsound_prepare(tmedia_producer_t* self, const tmedia_co
TMEDIA_PRODUCER(dsound)->audio.rate = TMEDIA_CODEC_RATE_ENCODING(codec);
TMEDIA_PRODUCER(dsound)->audio.ptime = TMEDIA_CODEC_PTIME_AUDIO_ENCODING(codec);
#if 0
TMEDIA_PRODUCER(dsound)->audio.rate = 48000;
TMEDIA_PRODUCER(dsound)->audio.channels = 1;
#endif
/* Create capture device */
if((hr = DirectSoundCaptureCreate(NULL, &dsound->device, NULL) != DS_OK)){
if ((hr = DirectSoundCaptureCreate(NULL, &dsound->device, NULL) != DS_OK)) {
tdav_win32_print_error("DirectSoundCaptureCreate", hr);
return -3;
}
@ -221,7 +231,7 @@ static int tdav_producer_dsound_prepare(tmedia_producer_t* self, const tmedia_co
dsbd.dwBufferBytes = (TDAV_DSOUND_PRODUCER_NOTIF_POS_COUNT * dsound->bytes_per_notif_size);
dsbd.lpwfxFormat = &wfx;
if((hr = IDirectSoundCapture_CreateCaptureBuffer(dsound->device, &dsbd, &dsound->captureBuffer, NULL)) != DS_OK){
if ((hr = IDirectSoundCapture_CreateCaptureBuffer(dsound->device, &dsbd, &dsound->captureBuffer, NULL)) != DS_OK) {
tdav_win32_print_error("IDirectSoundCapture_CreateCaptureBuffer", hr);
return -4;
}
@ -234,51 +244,54 @@ static int tdav_producer_dsound_start(tmedia_producer_t* self)
tdav_producer_dsound_t* dsound = (tdav_producer_dsound_t*)self;
tsk_size_t i;
DWORD dwOffset;
HRESULT hr;
LPDIRECTSOUNDNOTIFY lpDSBNotify;
DSBPOSITIONNOTIFY pPosNotify[TDAV_DSOUND_PRODUCER_NOTIF_POS_COUNT] = {0};
if(!dsound){
if (!dsound) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(!dsound->device || !dsound->captureBuffer){
if (!dsound->device || !dsound->captureBuffer) {
TSK_DEBUG_ERROR("Producer not prepared");
return -2;
}
if(dsound->started){
if (dsound->started) {
return 0;
}
if((hr = IDirectSoundCaptureBuffer_QueryInterface(dsound->captureBuffer, &IID_IDirectSoundNotify, (LPVOID*)&lpDSBNotify)) != DS_OK){
if ((hr = IDirectSoundCaptureBuffer_QueryInterface(dsound->captureBuffer, &IID_IDirectSoundNotify, (LPVOID*)&lpDSBNotify)) != DS_OK) {
tdav_win32_print_error("IDirectSoundCaptureBuffer_QueryInterface", hr);
return -3;
}
/* Events associated to notification points */
for(i = 0; i<TDAV_DSOUND_PRODUCER_NOTIF_POS_COUNT; i++){
dwOffset = dsound->bytes_per_notif_size - 1;
for (i = 0; i<(sizeof(dsound->notifEvents)/sizeof(dsound->notifEvents[0])); i++){
dsound->notifEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
pPosNotify[i].dwOffset = (dsound->bytes_per_notif_size * i) + (dsound->bytes_per_notif_size >> 1);
pPosNotify[i].dwOffset = dwOffset;
pPosNotify[i].hEventNotify = dsound->notifEvents[i];
dwOffset += dsound->bytes_per_notif_size;
}
if((hr = IDirectSoundNotify_SetNotificationPositions(lpDSBNotify, TDAV_DSOUND_PRODUCER_NOTIF_POS_COUNT, pPosNotify)) != DS_OK){
if ((hr = IDirectSoundNotify_SetNotificationPositions(lpDSBNotify, TDAV_DSOUND_PRODUCER_NOTIF_POS_COUNT, pPosNotify)) != DS_OK) {
IDirectSoundNotify_Release(lpDSBNotify);
tdav_win32_print_error("IDirectSoundBuffer_QueryInterface", hr);
return -4;
}
if((hr = IDirectSoundNotify_Release(lpDSBNotify))){
if ((hr = IDirectSoundNotify_Release(lpDSBNotify))) {
tdav_win32_print_error("IDirectSoundNotify_Release", hr);
}
/* Start the buffer */
if((hr = IDirectSoundCaptureBuffer_Start(dsound->captureBuffer, DSBPLAY_LOOPING)) != DS_OK){
if ((hr = IDirectSoundCaptureBuffer_Start(dsound->captureBuffer, DSBPLAY_LOOPING)) != DS_OK) {
tdav_win32_print_error("IDirectSoundCaptureBuffer_Start", hr);
return -5;
}
/* start the reader thread */
dsound->started = tsk_true;
tsk_thread_create(&dsound->tid[0], _tdav_producer_dsound_record_thread, dsound);
@ -297,12 +310,12 @@ static int tdav_producer_dsound_stop(tmedia_producer_t* self)
HRESULT hr;
if(!self){
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(!dsound->started){
if (!dsound->started) {
return 0;
}
@ -310,18 +323,18 @@ static int tdav_producer_dsound_stop(tmedia_producer_t* self)
dsound->started = tsk_false;
#if !SEND_SILENCE_ON_MUTE
if(dsound->mute && dsound->notifEvents[0]){
if (dsound->mute && dsound->notifEvents[0]) {
// thread is paused -> raise event now that "started" is equal to false
SetEvent(dsound->notifEvents[0]);
}
#endif
// stop thread
if(dsound->tid[0]){
if (dsound->tid[0]) {
tsk_thread_join(&(dsound->tid[0]));
}
if((hr = IDirectSoundCaptureBuffer_Stop(dsound->captureBuffer)) != DS_OK){
if ((hr = IDirectSoundCaptureBuffer_Stop(dsound->captureBuffer)) != DS_OK) {
tdav_win32_print_error("IDirectSoundCaptureBuffer_Stop", hr);
}
@ -340,7 +353,7 @@ static int tdav_producer_dsound_stop(tmedia_producer_t* self)
static tsk_object_t* tdav_producer_dsound_ctor(tsk_object_t * self, va_list * app)
{
tdav_producer_dsound_t *producer = self;
if(producer){
if (producer) {
/* init base */
tdav_producer_audio_init(TDAV_PRODUCER_AUDIO(producer));
/* init self */
@ -352,9 +365,9 @@ static tsk_object_t* tdav_producer_dsound_ctor(tsk_object_t * self, va_list * ap
static tsk_object_t* tdav_producer_dsound_dtor(tsk_object_t * self)
{
tdav_producer_dsound_t *dsound = self;
if(dsound){
if (dsound) {
/* stop */
if(dsound->started){
if (dsound->started) {
tdav_producer_dsound_stop(self);
}

View File

@ -119,7 +119,7 @@ static void* TSK_STDCALL _tdav_consumer_oss_playback_thread(void *param)
tsk_safeobj_unlock(p_oss);
}
bail:
OSS_DEBUG_INFO("__record_thread -- STOP");
OSS_DEBUG_INFO("__playback_thread -- STOP");
return tsk_null;
}
@ -155,8 +155,8 @@ static int tdav_consumer_oss_prepare(tmedia_consumer_t* self, const tmedia_codec
}
TMEDIA_CONSUMER(p_oss)->audio.ptime = TMEDIA_CODEC_PTIME_AUDIO_DECODING(codec);
TMEDIA_CONSUMER(p_oss)->audio.in.channels = TMEDIA_CODEC_CHANNELS_AUDIO_DECODING(codec);
TMEDIA_CONSUMER(p_oss)->audio.in.rate = TMEDIA_CODEC_RATE_DECODING(codec);
TMEDIA_CONSUMER(p_oss)->audio.in.channels = TMEDIA_CODEC_CHANNELS_AUDIO_DECODING(codec);
TMEDIA_CONSUMER(p_oss)->audio.in.rate = TMEDIA_CODEC_RATE_DECODING(codec);
// Set using requested
channels = TMEDIA_CONSUMER(p_oss)->audio.in.channels;
@ -276,7 +276,7 @@ static int tdav_consumer_oss_consume(tmedia_consumer_t* self, const void* buffer
goto bail;
}
if ((err = tdav_consumer_audio_put(TDAV_CONSUMER_AUDIO(p_oss), buffer, size, proto_hdr))/*thread-safe*/) {
OSS_DEBUG_WARN("Failed to put audio data");
OSS_DEBUG_WARN("Failed to put audio data to the jitter buffer");
goto bail;
}

View File

@ -181,22 +181,22 @@ tsk_size_t tdav_consumer_audio_get(tdav_consumer_audio_t* self, void* out_data,
tsk_safeobj_unlock(self);
// denoiser
if(self->denoise && self->denoise->opened && (self->denoise->echo_supp_enabled || self->denoise->noise_supp_enabled)){
if(self->denoise->echo_supp_enabled){
if (self->denoise && self->denoise->opened && (self->denoise->echo_supp_enabled || self->denoise->noise_supp_enabled)) {
if (self->denoise->echo_supp_enabled) {
// Echo process last frame
if(self->denoise->last_frame && self->denoise->last_frame->size){
tmedia_denoise_echo_playback(self->denoise, self->denoise->last_frame->data, self->denoise->last_frame->size);
if (self->denoise->playback_frame && self->denoise->playback_frame->size) {
tmedia_denoise_echo_playback(self->denoise, self->denoise->playback_frame->data, self->denoise->playback_frame->size);
}
if(ret_size){
if (ret_size){
// save
tsk_buffer_copy(self->denoise->last_frame, 0, out_data, ret_size);
tsk_buffer_copy(self->denoise->playback_frame, 0, out_data, ret_size);
}
}
#if 1 // suppress noise if not supported by remote party's encoder
// suppress noise
if(self->denoise->noise_supp_enabled){
tmedia_denoise_process_playback(self->denoise, out_data, out_size);
if (self->denoise->noise_supp_enabled && ret_size) {
tmedia_denoise_process_playback(self->denoise, out_data, ret_size);
}
#endif
}

View File

@ -406,6 +406,7 @@ static int tdav_session_audio_start(tmedia_session_t* self)
if(audio->denoise){
uint32_t record_frame_size_samples = TMEDIA_CODEC_PCM_FRAME_SIZE_AUDIO_ENCODING(audio->encoder.codec);
uint32_t record_sampling_rate = TMEDIA_CODEC_RATE_ENCODING(audio->encoder.codec);
uint32_t record_channels = TMEDIA_CODEC_CHANNELS_AUDIO_ENCODING(audio->encoder.codec);
uint32_t playback_frame_size_samples = (base->consumer && base->consumer->audio.ptime && base->consumer->audio.out.rate && base->consumer->audio.out.channels)
? ((base->consumer->audio.ptime * base->consumer->audio.out.rate) / 1000) * base->consumer->audio.out.channels
@ -413,15 +414,19 @@ static int tdav_session_audio_start(tmedia_session_t* self)
uint32_t playback_sampling_rate = (base->consumer && base->consumer->audio.out.rate)
? base->consumer->audio.out.rate
: TMEDIA_CODEC_RATE_DECODING(audio->encoder.codec);
uint32_t playback_channels = (base->consumer && base->consumer->audio.out.channels)
? base->consumer->audio.out.channels
: TMEDIA_CODEC_CHANNELS_AUDIO_DECODING(audio->encoder.codec);
TSK_DEBUG_INFO("Audio denoiser to be opened(record_frame_size_samples=%u, record_sampling_rate=%u, playback_frame_size_samples=%u, playback_sampling_rate=%u)", record_frame_size_samples, record_sampling_rate, playback_frame_size_samples, playback_sampling_rate);
TSK_DEBUG_INFO("Audio denoiser to be opened(record_frame_size_samples=%u, record_sampling_rate=%u, record_channels=%u, playback_frame_size_samples=%u, playback_sampling_rate=%u, playback_channels=%u)",
record_frame_size_samples, record_sampling_rate, record_channels, playback_frame_size_samples, playback_sampling_rate, playback_channels);
// close()
tmedia_denoise_close(audio->denoise);
// open() with new values
tmedia_denoise_open(audio->denoise,
record_frame_size_samples, record_sampling_rate,
playback_frame_size_samples, playback_sampling_rate);
record_frame_size_samples, record_sampling_rate, TSK_CLAMP(1, record_channels, 2),
playback_frame_size_samples, playback_sampling_rate, TSK_CLAMP(1, playback_channels, 2));
}
}
@ -742,19 +747,19 @@ static tmedia_resampler_t* _tdav_session_audio_resampler_create(int32_t bytes_pe
resampler_buff_size = (((out_freq * frame_duration)/1000) * bytes_per_sample) << (out_channels == 2 ? 1 : 0);
if(!(resampler = tmedia_resampler_create())){
if (!(resampler = tmedia_resampler_create())) {
TSK_DEBUG_ERROR("Failed to create audio resampler");
return tsk_null;
}
else {
if((ret = tmedia_resampler_open(resampler, in_freq, out_freq, frame_duration, in_channels, out_channels, quality))){
if ((ret = tmedia_resampler_open(resampler, in_freq, out_freq, frame_duration, in_channels, out_channels, quality, 16))) {
TSK_DEBUG_ERROR("Failed to open audio resampler (%d, %d, %d, %d, %d,%d) with retcode=%d", in_freq, out_freq, frame_duration, in_channels, out_channels, quality, ret);
TSK_OBJECT_SAFE_FREE(resampler);
goto done;
}
}
// create temp resampler buffer
if((*resampler_buffer = tsk_realloc(*resampler_buffer, resampler_buff_size))){
if ((*resampler_buffer = tsk_realloc(*resampler_buffer, resampler_buff_size))) {
*resampler_buffer_size = resampler_buff_size;
}
else {

View File

@ -69,13 +69,13 @@ static int tdav_speex_denoise_set(tmedia_denoise_t* _self, const tmedia_param_t*
return -1;
}
static int tdav_speex_denoise_open(tmedia_denoise_t* self, uint32_t record_frame_size_samples, uint32_t record_sampling_rate, uint32_t playback_frame_size_samples, uint32_t playback_sampling_rate)
static int tdav_speex_denoise_open(tmedia_denoise_t* self, uint32_t record_frame_size_samples, uint32_t record_sampling_rate, uint32_t record_channels, uint32_t playback_frame_size_samples, uint32_t playback_sampling_rate, uint32_t playback_channels)
{
tdav_speex_denoise_t *denoiser = (tdav_speex_denoise_t *)self;
float f;
int i;
if(!denoiser->echo_state && TMEDIA_DENOISE(denoiser)->echo_supp_enabled){
if (!denoiser->echo_state && TMEDIA_DENOISE(denoiser)->echo_supp_enabled) {
TSK_DEBUG_INFO("Init Aec frame_size[%u] filter_length[%u] SampleRate[%u]",
(uint32_t)(record_frame_size_samples),TMEDIA_DENOISE(denoiser)->echo_tail*record_frame_size_samples, record_sampling_rate);
if((denoiser->echo_state = speex_echo_state_init(record_frame_size_samples, TMEDIA_DENOISE(denoiser)->echo_tail))){
@ -83,7 +83,7 @@ static int tdav_speex_denoise_open(tmedia_denoise_t* self, uint32_t record_frame
}
}
if(!denoiser->preprocess_state_record && !denoiser->preprocess_state_playback){
if (!denoiser->preprocess_state_record && !denoiser->preprocess_state_playback) {
denoiser->record_frame_size_samples = record_frame_size_samples;
denoiser->record_frame_size_bytes = (record_frame_size_samples << 1);
denoiser->playback_frame_size_samples = playback_frame_size_samples;

View File

@ -37,9 +37,10 @@ typedef struct tdav_speex_resampler_s
tsk_size_t out_size;
uint32_t in_channels;
uint32_t out_channels;
uint32_t bytes_per_sample;
struct{
spx_int16_t* ptr;
void* ptr;
tsk_size_t size_in_samples;
} tmp_buffer;
@ -47,33 +48,39 @@ typedef struct tdav_speex_resampler_s
}
tdav_speex_resampler_t;
static int tdav_speex_resampler_open(tmedia_resampler_t* self, uint32_t in_freq, uint32_t out_freq, uint32_t frame_duration, uint32_t in_channels, uint32_t out_channels, uint32_t quality)
static int tdav_speex_resampler_open(tmedia_resampler_t* self, uint32_t in_freq, uint32_t out_freq, uint32_t frame_duration, uint32_t in_channels, uint32_t out_channels, uint32_t quality, uint32_t bits_per_sample)
{
tdav_speex_resampler_t *resampler = (tdav_speex_resampler_t *)self;
int ret = 0;
uint32_t bytes_per_sample = (bits_per_sample >> 3);
if(in_channels != 1 && in_channels != 2){
if (in_channels != 1 && in_channels != 2) {
TSK_DEBUG_ERROR("%d not valid as input channel", in_channels);
return -1;
}
if(out_channels != 1 && out_channels != 2){
if (out_channels != 1 && out_channels != 2) {
TSK_DEBUG_ERROR("%d not valid as output channel", out_channels);
return -1;
}
if (bytes_per_sample != sizeof(spx_int16_t) && bytes_per_sample != sizeof(float)) {
TSK_DEBUG_ERROR("%d not valid as bits_per_sample", bits_per_sample);
return -1;
}
if(!(resampler->state = speex_resampler_init(in_channels, in_freq, out_freq, quality>10 ? TDAV_SPEEX_RESAMPLER_MAX_QUALITY : quality, &ret))){
if (!(resampler->state = speex_resampler_init(in_channels, in_freq, out_freq, TSK_CLAMP(0, quality, TDAV_SPEEX_RESAMPLER_MAX_QUALITY), &ret))) {
TSK_DEBUG_ERROR("speex_resampler_init() returned %d", ret);
return -2;
}
resampler->bytes_per_sample = bytes_per_sample;
resampler->in_size = ((in_freq * frame_duration) / 1000) << (in_channels == 2 ? 1 : 0);
resampler->out_size = ((out_freq * frame_duration) / 1000) << (out_channels == 2 ? 1 : 0);
resampler->in_channels = in_channels;
resampler->out_channels = out_channels;
if(in_channels != out_channels){
if (in_channels != out_channels) {
resampler->tmp_buffer.size_in_samples = ((TSK_MAX(in_freq, out_freq) * frame_duration) / 1000) << (TSK_MAX(in_channels, out_channels) == 2 ? 1 : 0);
if(!(resampler->tmp_buffer.ptr = (spx_int16_t*)tsk_realloc(resampler->tmp_buffer.ptr, resampler->tmp_buffer.size_in_samples * sizeof(spx_int16_t)))){
if (!(resampler->tmp_buffer.ptr = tsk_realloc(resampler->tmp_buffer.ptr, resampler->tmp_buffer.size_in_samples * resampler->bytes_per_sample))) {
resampler->tmp_buffer.size_in_samples = 0;
return -2;
}
@ -82,88 +89,104 @@ static int tdav_speex_resampler_open(tmedia_resampler_t* self, uint32_t in_freq,
return 0;
}
static tsk_size_t tdav_speex_resampler_process(tmedia_resampler_t* self, const uint16_t* in_data, tsk_size_t in_size, uint16_t* out_data, tsk_size_t out_size)
static tsk_size_t tdav_speex_resampler_process(tmedia_resampler_t* self, const void* in_data, tsk_size_t in_size_in_sample, void* out_data, tsk_size_t out_size_in_sample)
{
tdav_speex_resampler_t *resampler = (tdav_speex_resampler_t *)self;
spx_uint32_t out_len = (spx_uint32_t)out_size;
int err = RESAMPLER_ERR_SUCCESS;
if(!resampler->state || !out_data){
spx_uint32_t _out_size_in_sample = (spx_uint32_t)out_size_in_sample;
if (!resampler->state || !out_data) {
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
if(in_size != resampler->in_size){
if (in_size_in_sample != resampler->in_size) {
TSK_DEBUG_ERROR("Input data has wrong size");
return 0;
}
if(out_size < resampler->out_size){
if (out_size_in_sample < resampler->out_size) {
TSK_DEBUG_ERROR("Output data is too short");
return 0;
}
if(resampler->in_channels == resampler->out_channels) {
err = speex_resampler_process_int(resampler->state, 0,
(const spx_int16_t *)in_data, (spx_uint32_t *)&in_size,
(spx_int16_t *)out_data, &out_len);
if (resampler->in_channels == resampler->out_channels) {
if (resampler->bytes_per_sample == sizeof(spx_int16_t)) {
err = speex_resampler_process_int(resampler->state, 0,
(const spx_int16_t *)in_data, (spx_uint32_t *)&in_size_in_sample,
(spx_int16_t *)out_data, &_out_size_in_sample);
}
else {
err = speex_resampler_process_float(resampler->state, 0,
(const float *)in_data, (spx_uint32_t *)&in_size_in_sample,
(float *)out_data, &_out_size_in_sample);
}
}
else {
spx_uint32_t i, j;
// in_channels = 1, out_channels = 2
if (resampler->in_channels == 1) {
#if 0 // WP8 -> noise
// in_channels = 1, out_channels = 2
spx_int16_t* pout_data = (spx_int16_t*)(out_data);
speex_resampler_set_output_stride(resampler->state, 2);
err = speex_resampler_process_int(resampler->state, 0,
(const spx_int16_t *)in_data, (spx_uint32_t *)&in_size,
pout_data, &out_len);
if (err == RESAMPLER_ERR_SUCCESS) {
spx_uint32_t i;
// duplicate
for (i = 0; i < out_len; i += 2) {
pout_data[i + 1] = pout_data[i];
if (resampler->bytes_per_sample == sizeof(spx_int16_t)) {
err = speex_resampler_process_int(resampler->state, 0, (const spx_int16_t *)in_data, (spx_uint32_t *)&in_size_in_sample, resampler->tmp_buffer.ptr, &_out_size_in_sample);
if (err == RESAMPLER_ERR_SUCCESS) {
spx_int16_t* pout_data = (spx_int16_t*)(out_data);
for (i = 0, j = 0; i < _out_size_in_sample; ++i, j += 2) {
pout_data[j] = pout_data[j + 1] = *(((const spx_int16_t*)resampler->tmp_buffer.ptr) + i);
}
}
}
#else
out_len = out_size;
err = speex_resampler_process_int(resampler->state, 0, (const spx_int16_t *)in_data, (spx_uint32_t *)&in_size, resampler->tmp_buffer.ptr, &out_len);
if (err == RESAMPLER_ERR_SUCCESS) {
spx_uint32_t i, j;
spx_int16_t* pout_data = (spx_int16_t*)(out_data);
out_len = TSK_MIN(out_len, out_size);
for (i = 0, j = 0; i < out_len; ++i, j += 2) {
pout_data[j] = pout_data[j + 1] = resampler->tmp_buffer.ptr[i];
else {
err = speex_resampler_process_float(resampler->state, 0, (const float *)in_data, (spx_uint32_t *)&in_size_in_sample, resampler->tmp_buffer.ptr, &_out_size_in_sample);
if (err == RESAMPLER_ERR_SUCCESS) {
float* pout_data = (float*)(out_data);
for (i = 0, j = 0; i < _out_size_in_sample; ++i, j += 2) {
pout_data[j] = pout_data[j + 1] = *(((const float*)resampler->tmp_buffer.ptr) + i);
}
}
}
#endif
}
else {
// in_channels = 2, out_channels = 1
spx_uint32_t out_len_chan2 = (out_len << 1);
err = speex_resampler_process_int(resampler->state, 0,
(const spx_int16_t *)in_data, (spx_uint32_t *)&in_size,
(spx_int16_t *)resampler->tmp_buffer.ptr, &out_len_chan2);
if(err == RESAMPLER_ERR_SUCCESS) {
spx_uint32_t i, j;
spx_int16_t* pout_data = (spx_int16_t*)(out_data);
for(i = 0, j = 0; j < out_len_chan2; ++i, j+=2){
pout_data[i] = resampler->tmp_buffer.ptr[j];
spx_uint32_t _out_size2_in_sample = (_out_size_in_sample << 1);
if (resampler->bytes_per_sample == sizeof(spx_int16_t)) {
err = speex_resampler_process_int(resampler->state, 0,
(const spx_int16_t *)in_data, (spx_uint32_t *)&in_size_in_sample,
(spx_int16_t *)resampler->tmp_buffer.ptr, &_out_size2_in_sample);
if (err == RESAMPLER_ERR_SUCCESS) {
spx_int16_t* pout_data = (spx_int16_t*)(out_data);
_out_size_in_sample = resampler->out_size;
for (i = 0, j = 0; j < _out_size2_in_sample; ++i, j+=2) {
pout_data[i] = *(((const spx_int16_t*)resampler->tmp_buffer.ptr) + j);
}
}
}
else {
err = speex_resampler_process_float(resampler->state, 0,
(const float *)in_data, (spx_uint32_t *)&in_size_in_sample,
(float *)resampler->tmp_buffer.ptr, &_out_size2_in_sample);
if (err == RESAMPLER_ERR_SUCCESS) {
float* pout_data = (float*)(out_data);
for (i = 0, j = 0; j < _out_size2_in_sample; ++i, j+=2) {
pout_data[i] = *(((const float*)resampler->tmp_buffer.ptr) + j);
}
}
}
}
}
if(err != RESAMPLER_ERR_SUCCESS){
if (err != RESAMPLER_ERR_SUCCESS) {
TSK_DEBUG_ERROR("speex_resampler_process_int() failed with error code %d", err);
return 0;
}
return (tsk_size_t)out_len;
return (tsk_size_t)_out_size_in_sample;
}
static int tdav_speex_resampler_close(tmedia_resampler_t* self)
{
tdav_speex_resampler_t *resampler = (tdav_speex_resampler_t *)self;
if(resampler->state){
if (resampler->state) {
speex_resampler_destroy(resampler->state);
resampler->state = tsk_null;
}
@ -195,7 +218,7 @@ static tsk_object_t* tdav_speex_resampler_dtor(tsk_object_t * self)
/* deinit base */
tmedia_resampler_deinit(TMEDIA_RESAMPLER(resampler));
/* deinit self */
if(resampler->state){
if (resampler->state) {
speex_resampler_destroy(resampler->state);
resampler->state = tsk_null;
}

View File

@ -1,7 +1,6 @@
/*
* Copyright (C) 2011 Doubango Telecom <http://www.doubango.org>
*
* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
* Copyright (C) 2011-204 Mamadou DIOP
* Copyright (C) 2011-204 Doubango Telecom <http://www.doubango.org>
*
* This file is part of Open Source Doubango Framework.
*
@ -22,10 +21,6 @@
/**@file tdav_webrtc_denoise.c
* @brief Google WebRTC Denoiser (Noise suppression, AGC, AEC) Plugin
*
* @author Mamadou Diop <diopmamadou(at)doubango.org>
*
*/
#include "tinydav/audio/tdav_webrtc_denoise.h"
@ -36,6 +31,7 @@
#include "tsk_debug.h"
#include "tinymedia/tmedia_defaults.h"
#include "tinymedia/tmedia_resampler.h"
#include <string.h>
@ -47,19 +43,92 @@
#endif
#if !defined(WEBRTC_MIN_ECHO_TAIL)
# define WEBRTC_MIN_ECHO_TAIL 20 // 0 will cause random crashes
static const int32_t kSizeOfWord16 = sizeof(int16_t);
#endif
#if TDAV_UNDER_MOBILE || 1 // FIXME
typedef int16_t sample_t;
#else
typedef float sample_t;
#endif
typedef struct tdav_webrtc_pin_xs
{
uint32_t n_duration;
uint32_t n_rate;
uint32_t n_channels;
uint32_t n_sample_size;
}
tdav_webrtc_pin_xt;
typedef struct tdav_webrtc_resampler_s
{
TSK_DECLARE_OBJECT;
tmedia_resampler_t* p_resampler;
void* p_bufftmp_ptr; // used to convert float <->int16
tsk_size_t n_bufftmp_size_in_bytes;
struct {
tdav_webrtc_pin_xt x_pin;
tsk_size_t n_buff_size_in_bytes;
tsk_size_t n_buff_size_in_samples;
} in;
struct {
tdav_webrtc_pin_xt x_pin;
void* p_buff_ptr;
tsk_size_t n_buff_size_in_bytes;
tsk_size_t n_buff_size_in_samples;
} out;
}
tdav_webrtc_resampler_t;
static int _tdav_webrtc_resampler_create(const tdav_webrtc_pin_xt* p_pin_in, const tdav_webrtc_pin_xt* p_pin_out, tdav_webrtc_resampler_t **pp_resampler);
static int _tdav_webrtc_resampler_process(tdav_webrtc_resampler_t* p_self, const void* p_buff_ptr, tsk_size_t n_buff_size_in_bytes);
/** WebRTC denoiser (AEC, NS, AGC...) */
typedef struct tdav_webrtc_denoise_s
{
TMEDIA_DECLARE_DENOISE;
void *AEC_inst;
#if HAVE_SPEEX_DSP && PREFER_SPEEX_DENOISER
SpeexPreprocessState *SpeexDenoiser_proc;
#else
TDAV_NsHandle *NS_inst;
#endif
uint32_t echo_tail;
uint32_t echo_skew;
struct {
tdav_webrtc_resampler_t* p_rpl_in2den; // input -> denoiser
tdav_webrtc_resampler_t* p_rpl_den2in; // denoiser -> input
} record;
struct {
tdav_webrtc_resampler_t* p_rpl_in2den; // input -> denoiser
tdav_webrtc_resampler_t* p_rpl_den2in; // denoiser -> input
} playback;
struct {
uint32_t nb_samples_per_process;
uint32_t sampling_rate;
uint32_t channels; // always "1"
} neg;
TSK_DECLARE_SAFEOBJ;
}
tdav_webrtc_denoise_t;
static int tdav_webrtc_denoise_set(tmedia_denoise_t* _self, const tmedia_param_t* param)
{
tdav_webrtc_denoise_t *self = (tdav_webrtc_denoise_t *)_self;
if(!self || !param){
if (!self || !param) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(param->value_type == tmedia_pvt_int32){
if(tsk_striequals(param->key, "echo-tail")){
if (param->value_type == tmedia_pvt_int32) {
if (tsk_striequals(param->key, "echo-tail")) {
int32_t echo_tail = *((int32_t*)param->value);
self->echo_tail = TSK_CLAMP(WEBRTC_MIN_ECHO_TAIL, echo_tail, WEBRTC_MAX_ECHO_TAIL);
TSK_DEBUG_INFO("set_echo_tail (%d->%d)", echo_tail, self->echo_tail);
@ -69,17 +138,18 @@ static int tdav_webrtc_denoise_set(tmedia_denoise_t* _self, const tmedia_param_t
return -1;
}
static int tdav_webrtc_denoise_open(tmedia_denoise_t* self, uint32_t record_frame_size_samples, uint32_t record_sampling_rate, uint32_t playback_frame_size_samples, uint32_t playback_sampling_rate)
static int tdav_webrtc_denoise_open(tmedia_denoise_t* self, uint32_t record_frame_size_samples, uint32_t record_sampling_rate, uint32_t record_channels, uint32_t playback_frame_size_samples, uint32_t playback_sampling_rate, uint32_t playback_channels)
{
tdav_webrtc_denoise_t *denoiser = (tdav_webrtc_denoise_t *)self;
int ret;
tdav_webrtc_pin_xt pin_record_in = { 0 }, pin_record_den = { 0 }, pin_playback_in = { 0 }, pin_playback_den = { 0 };
if(!denoiser){
if (!denoiser) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if(denoiser->AEC_inst ||
if (denoiser->AEC_inst ||
#if HAVE_SPEEX_DSP && PREFER_SPEEX_DENOISER
denoiser->SpeexDenoiser_proc
#else
@ -91,184 +161,232 @@ static int tdav_webrtc_denoise_open(tmedia_denoise_t* self, uint32_t record_fram
}
denoiser->echo_tail = TSK_CLAMP(WEBRTC_MIN_ECHO_TAIL, TMEDIA_DENOISE(denoiser)->echo_tail, WEBRTC_MAX_ECHO_TAIL);
TSK_DEBUG_INFO("echo_tail=%d", denoiser->echo_tail);
denoiser->echo_skew = TMEDIA_DENOISE(denoiser)->echo_skew;
denoiser->record_frame_size_samples = record_frame_size_samples;
denoiser->record_sampling_rate = record_sampling_rate;
denoiser->playback_frame_size_samples = playback_frame_size_samples;
denoiser->playback_sampling_rate = playback_sampling_rate;
TSK_DEBUG_INFO("echo_tail=%d, echo_skew=%d, echo_supp_enabled=%d, noise_supp_enabled=%d", denoiser->echo_tail, denoiser->echo_skew, self->echo_supp_enabled, self->noise_supp_enabled);
//
// DENOISER
//
#if TDAV_UNDER_MOBILE // AECM= [8-16]k, AEC=[8-32]k
denoiser->neg.sampling_rate = TSK_MIN(TSK_MAX(record_sampling_rate, playback_sampling_rate), 16000);
#else
denoiser->neg.sampling_rate = TSK_MIN(TSK_MAX(record_sampling_rate, playback_sampling_rate), 16000); // FIXME: 32000 accepted by echo_process fails
#endif
denoiser->neg.nb_samples_per_process = /*TSK_CLAMP(80,*/ ((denoiser->neg.sampling_rate * 10) / 1000)/*, 160)*/; // Supported by the module: "80"(10ms) and "160"(20ms)
denoiser->neg.channels = 1;
//
// RECORD
//
TSK_OBJECT_SAFE_FREE(denoiser->record.p_rpl_den2in);
TSK_OBJECT_SAFE_FREE(denoiser->record.p_rpl_in2den);
pin_record_in.n_sample_size = sizeof(int16_t);
pin_record_in.n_rate = record_sampling_rate;
pin_record_in.n_channels = record_channels;
pin_record_in.n_duration = (((record_frame_size_samples * 1000) / record_sampling_rate)) / record_channels;
pin_record_den.n_sample_size = sizeof(sample_t);
pin_record_den.n_rate = denoiser->neg.sampling_rate;
pin_record_den.n_channels = 1;
pin_record_den.n_duration = pin_record_in.n_duration;
if (pin_record_in.n_sample_size != pin_record_den.n_sample_size || pin_record_in.n_rate != pin_record_den.n_rate || pin_record_in.n_channels != pin_record_den.n_channels) {
if ((ret = _tdav_webrtc_resampler_create(&pin_record_in, &pin_record_den, &denoiser->record.p_rpl_in2den))) {
return ret;
}
if ((ret = _tdav_webrtc_resampler_create(&pin_record_den, &pin_record_in, &denoiser->record.p_rpl_den2in))) {
return ret;
}
}
//
// PLAYBACK
//
TSK_OBJECT_SAFE_FREE(denoiser->playback.p_rpl_den2in);
TSK_OBJECT_SAFE_FREE(denoiser->playback.p_rpl_in2den);
pin_playback_in.n_sample_size = sizeof(int16_t);
pin_playback_in.n_rate = playback_sampling_rate;
pin_playback_in.n_channels = playback_channels;
pin_playback_in.n_duration = (((playback_frame_size_samples * 1000) / playback_sampling_rate)) / playback_channels;
pin_playback_den.n_sample_size = sizeof(sample_t);
pin_playback_den.n_rate = denoiser->neg.sampling_rate;
pin_playback_den.n_channels = 1;
pin_playback_den.n_duration = pin_playback_in.n_duration;
if (pin_playback_in.n_sample_size != pin_playback_den.n_sample_size || pin_playback_in.n_rate != pin_playback_den.n_rate || pin_playback_in.n_channels != pin_playback_den.n_channels) {
if ((ret = _tdav_webrtc_resampler_create(&pin_playback_in, &pin_playback_den, &denoiser->playback.p_rpl_in2den))) {
return ret;
}
if ((ret = _tdav_webrtc_resampler_create(&pin_playback_den, &pin_playback_in, &denoiser->playback.p_rpl_den2in))) {
return ret;
}
}
//
// AEC instance
//
if((ret = TDAV_WebRtcAec_Create(&denoiser->AEC_inst))){
if ((ret = TDAV_WebRtcAec_Create(&denoiser->AEC_inst))) {
TSK_DEBUG_ERROR("WebRtcAec_Create failed with error code = %d", ret);
return ret;
}
if((ret = TDAV_WebRtcAec_Init(denoiser->AEC_inst, denoiser->record_sampling_rate, denoiser->record_sampling_rate))){
if ((ret = TDAV_WebRtcAec_Init(denoiser->AEC_inst, denoiser->neg.sampling_rate, denoiser->neg.sampling_rate))) {
TSK_DEBUG_ERROR("WebRtcAec_Init failed with error code = %d", ret);
return ret;
}
#if WEBRTC_AEC_AGGRESSIVE
#if TDAV_UNDER_MOBILE
#else
{
AecConfig aecConfig;
#if WEBRTC_AEC_AGGRESSIVE
aecConfig.nlpMode = kAecNlpAggressive;
aecConfig.skewMode = kAecTrue;
aecConfig.metricsMode = kAecFalse;
#else
aecConfig.nlpMode = kAecNlpModerate;
#endif
aecConfig.skewMode = kAecFalse;
aecConfig.metricsMode = kAecTrue;
aecConfig.delay_logging = kAecFalse;
if((ret = WebRtcAec_set_config(denoiser->AEC_inst, aecConfig))){
if ((ret = WebRtcAec_set_config(denoiser->AEC_inst, aecConfig))) {
TSK_DEBUG_ERROR("WebRtcAec_set_config failed with error code = %d", ret);
}
}
#endif
//
// Noise Suppression instance
//
if(TMEDIA_DENOISE(denoiser)->noise_supp_enabled){
if (TMEDIA_DENOISE(denoiser)->noise_supp_enabled) {
#if HAVE_SPEEX_DSP && PREFER_SPEEX_DENOISER
if((denoiser->SpeexDenoiser_proc = speex_preprocess_state_init(denoiser->record_frame_size_samples, denoiser->record_sampling_rate))){
if ((denoiser->SpeexDenoiser_proc = speex_preprocess_state_init((pin_record_den.n_rate / 1000) * pin_record_den.n_duration, pin_record_den.n_rate))) {
int i = 1;
speex_preprocess_ctl(denoiser->SpeexDenoiser_proc, SPEEX_PREPROCESS_SET_DENOISE, &i);
i = TMEDIA_DENOISE(denoiser)->noise_supp_level;
speex_preprocess_ctl(denoiser->SpeexDenoiser_proc, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &i);
}
#else
if((ret = TDAV_WebRtcNs_Create(&denoiser->NS_inst))){
if ((ret = TDAV_WebRtcNs_Create(&denoiser->NS_inst))) {
TSK_DEBUG_ERROR("WebRtcNs_Create failed with error code = %d", ret);
return ret;
}
if((ret = TDAV_WebRtcNs_Init(denoiser->NS_inst, denoiser->sampling_rate))){
if ((ret = TDAV_WebRtcNs_Init(denoiser->NS_inst, 80))) {
TSK_DEBUG_ERROR("WebRtcNs_Init failed with error code = %d", ret);
return ret;
}
#endif
}
// allocate temp buffer for record processing
if(!(denoiser->temp_rec_out = tsk_realloc(denoiser->temp_rec_out, denoiser->record_frame_size_samples * kSizeOfWord16))){
TSK_DEBUG_ERROR("Failed to allocate new buffer");
return -3;
}
TSK_DEBUG_INFO("WebRTC denoiser opened");
TSK_DEBUG_INFO("WebRTC denoiser opened: record:%uHz,%uchannels // playback:%uHz,%uchannels // neg:%uHz,%uchannels",
record_sampling_rate, record_channels,
playback_sampling_rate, playback_channels,
denoiser->neg.sampling_rate, denoiser->neg.channels);
return ret;
}
static int tdav_webrtc_denoise_echo_playback(tmedia_denoise_t* self, const void* echo_frame, uint32_t echo_frame_size_bytes)
{
tdav_webrtc_denoise_t *denoiser = (tdav_webrtc_denoise_t *)self;
if(denoiser->AEC_inst){
int ret;
const int16_t *pEchoFrame = (const int16_t *)echo_frame;
switch(denoiser->record_sampling_rate){
case 8000:
{
if((ret = TDAV_WebRtcAec_BufferFarend(denoiser->AEC_inst, pEchoFrame, denoiser->record_frame_size_samples))){
TSK_DEBUG_ERROR("WebRtcAec_BufferFarend failed with error code = %d", ret);
return ret;
}
break;
}
case 16000:
case 32000:
{
// Split in several 160 samples
uint32_t i, k = (denoiser->record_sampling_rate == 16000 ? 1 : 2);
for(i = 0; i<denoiser->record_frame_size_samples; i+=(denoiser->record_frame_size_samples>>k)){
if((ret = TDAV_WebRtcAec_BufferFarend(denoiser->AEC_inst, &pEchoFrame[i], (denoiser->record_frame_size_samples>>k)))){
TSK_DEBUG_ERROR("WebRtcAec_BufferFarend failed with error code = %d", ret);
return ret;
}
}
break;
}
default:
{
TSK_DEBUG_ERROR("%d Hz not supported by WebRTC AEC", denoiser->record_sampling_rate);
return -2;
tdav_webrtc_denoise_t *p_self = (tdav_webrtc_denoise_t *)self;
int ret = 0;
tsk_safeobj_lock(p_self);
if (p_self->AEC_inst && echo_frame && echo_frame_size_bytes) {
const sample_t* _echo_frame = (const sample_t*)echo_frame;
uint32_t _echo_frame_size_bytes = echo_frame_size_bytes;
uint32_t _echo_frame_size_samples = (_echo_frame_size_bytes / sizeof(int16_t));
// IN -> DEN
if (p_self->playback.p_rpl_in2den) {
if ((ret = _tdav_webrtc_resampler_process(p_self->playback.p_rpl_in2den, _echo_frame, _echo_frame_size_bytes))) {
goto bail;
}
_echo_frame = p_self->playback.p_rpl_in2den->out.p_buff_ptr;
_echo_frame_size_bytes = p_self->playback.p_rpl_in2den->out.n_buff_size_in_bytes;
_echo_frame_size_samples = p_self->playback.p_rpl_in2den->out.n_buff_size_in_samples;
}
// PROCESS
if (_echo_frame_size_samples && _echo_frame) {
uint32_t _samples;
for (_samples = 0; _samples < _echo_frame_size_samples; _samples+= p_self->neg.nb_samples_per_process) {
if ((ret = TDAV_WebRtcAec_BufferFarend(p_self->AEC_inst, &_echo_frame[_samples], p_self->neg.nb_samples_per_process))){
TSK_DEBUG_ERROR("WebRtcAec_BufferFarend failed with error code = %d, nb_samples_per_process=%u", ret, p_self->neg.nb_samples_per_process);
goto bail;
}
}
}
}
return 0;
bail:
tsk_safeobj_unlock(p_self);
return ret;
}
static int tdav_webrtc_denoise_process_record(tmedia_denoise_t* self, void* audio_frame, uint32_t audio_frame_size_bytes, tsk_bool_t* silence_or_noise)
{
tdav_webrtc_denoise_t *denoiser = (tdav_webrtc_denoise_t *)self;
tdav_webrtc_denoise_t *p_self = (tdav_webrtc_denoise_t *)self;
int ret = 0;
*silence_or_noise = tsk_false;
tsk_safeobj_lock(denoiser);
tsk_safeobj_lock(p_self);
if(denoiser->AEC_inst){
int16_t *pAudioFrame = audio_frame;
// Noise suppression
#if HAVE_SPEEX_DSP && PREFER_SPEEX_DENOISER
if(denoiser->SpeexDenoiser_proc){
speex_preprocess_run(denoiser->SpeexDenoiser_proc, pAudioFrame);
}
memcpy(denoiser->temp_rec_out, pAudioFrame, denoiser->record_frame_size_samples * sizeof(spx_int16_t));
#else
// WebRTC NoiseSupp only accept 10ms frames
// Our encoder will always output 20ms frames ==> execute 2x noise_supp
if(denoiser->NS_inst){
if(
(ret = TDAV_WebRtcNs_Process(denoiser->NS_inst, pAudioFrame, tsk_null, denoiser->temp_rec_out, tsk_null)) ||
(ret = TDAV_WebRtcNs_Process(denoiser->NS_inst, &pAudioFrame[(denoiser->frame_size>>1)], tsk_null, &denoiser->temp_rec_out[(denoiser->frame_size>>1)], tsk_null))
)
{
TSK_DEBUG_ERROR("WebRtcNs_Process with error code = %d", ret);
if (p_self->AEC_inst && audio_frame && audio_frame_size_bytes) {
uint32_t _samples;
const sample_t* _audio_frame = (const sample_t*)audio_frame;
uint32_t _audio_frame_size_bytes = audio_frame_size_bytes;
uint32_t _audio_frame_size_samples = (_audio_frame_size_bytes / sizeof(int16_t));
// IN -> DEN
if (p_self->record.p_rpl_in2den) {
if ((ret = _tdav_webrtc_resampler_process(p_self->record.p_rpl_in2den, _audio_frame, _audio_frame_size_bytes))) {
goto bail;
}
_audio_frame = p_self->record.p_rpl_in2den->out.p_buff_ptr;
_audio_frame_size_bytes = p_self->record.p_rpl_in2den->out.n_buff_size_in_bytes;
_audio_frame_size_samples = p_self->record.p_rpl_in2den->out.n_buff_size_in_samples;
}
else{
memcpy(denoiser->temp_rec_out, pAudioFrame, (denoiser->frame_size * kSizeOfWord16));
// NOISE SUPPRESSION
#if HAVE_SPEEX_DSP && PREFER_SPEEX_DENOISER
if (p_self->SpeexDenoiser_proc) {
speex_preprocess_run(p_self->SpeexDenoiser_proc, (spx_int16_t*)_audio_frame);
}
#endif
// AEC
switch(denoiser->record_sampling_rate){
case 8000:
{
if((ret = TDAV_WebRtcAec_Process(denoiser->AEC_inst, denoiser->temp_rec_out, tsk_null, pAudioFrame, tsk_null, denoiser->record_frame_size_samples, denoiser->echo_tail, denoiser->echo_skew))){
TSK_DEBUG_ERROR("WebRtcAec_Process with error code = %d", ret);
goto bail;
}
break;
}
case 16000:
case 32000:
{
// Split in several 160 samples
uint32_t i, k = (denoiser->record_sampling_rate == 16000 ? 1 : 2);
for(i = 0; i<denoiser->record_frame_size_samples; i+=(denoiser->record_frame_size_samples>>k)){
if((ret = TDAV_WebRtcAec_Process(denoiser->AEC_inst, &denoiser->temp_rec_out[i], tsk_null, &pAudioFrame[i], tsk_null, (denoiser->record_frame_size_samples>>k), denoiser->echo_tail, denoiser->echo_skew))){
TSK_DEBUG_ERROR("WebRtcAec_Process with error code = %d", ret);
goto bail;
}
}
break;
}
default:
{
TSK_DEBUG_ERROR("%d Hz not supported by WebRTC AEC", denoiser->record_sampling_rate);
ret = -2;
#else
// WebRTC NoiseSupp only accept 10ms frames
// Our encoder will always output 20ms frames ==> execute 2x noise_supp
if (p_self->NS_inst) {
for (_samples = 0; _samples < _audio_frame_size_samples; _samples+= denoiser->neg.nb_samples_per_process) {
if ((ret = TDAV_WebRtcNs_Process(p_self->NS_inst, &_audio_frame[_samples], tsk_null, _audio_frame, tsk_null))) {
TSK_DEBUG_ERROR("WebRtcNs_Process with error code = %d", ret);
goto bail;
}
}
}
#endif
// PROCESS
if (_audio_frame_size_samples && _audio_frame) {
for (_samples = 0; _samples < _audio_frame_size_samples; _samples+= p_self->neg.nb_samples_per_process) {
if ((ret = TDAV_WebRtcAec_Process(p_self->AEC_inst, &_audio_frame[_samples], tsk_null, (sample_t*)&_audio_frame[_samples], tsk_null, p_self->neg.nb_samples_per_process, p_self->echo_tail, p_self->echo_skew))){
TSK_DEBUG_ERROR("WebRtcAec_Process with error code = %d, nb_samples_per_process=%u", ret, p_self->neg.nb_samples_per_process);
goto bail;
}
}
}
// DEN -> IN
if (p_self->record.p_rpl_den2in) {
if ((ret = _tdav_webrtc_resampler_process(p_self->record.p_rpl_den2in, _audio_frame, _audio_frame_size_bytes))) {
goto bail;
}
_audio_frame = p_self->record.p_rpl_den2in->out.p_buff_ptr;
_audio_frame_size_bytes = p_self->record.p_rpl_den2in->out.n_buff_size_in_bytes;
_audio_frame_size_samples = p_self->record.p_rpl_den2in->out.n_buff_size_in_samples;
}
// Sanity check
if (_audio_frame_size_bytes != audio_frame_size_bytes) {
TSK_DEBUG_ERROR("Size mismatch: %u <> %u", _audio_frame_size_bytes, audio_frame_size_bytes);
ret = -3;
goto bail;
}
if (audio_frame != (const void*)_audio_frame) {
memcpy(audio_frame, _audio_frame, _audio_frame_size_bytes);
}
}
bail:
tsk_safeobj_unlock(denoiser);
tsk_safeobj_unlock(p_self);
return ret;
}
@ -288,30 +406,162 @@ static int tdav_webrtc_denoise_close(tmedia_denoise_t* self)
tdav_webrtc_denoise_t *denoiser = (tdav_webrtc_denoise_t *)self;
tsk_safeobj_lock(denoiser);
if(denoiser->AEC_inst){
if (denoiser->AEC_inst) {
TDAV_WebRtcAec_Free(denoiser->AEC_inst);
denoiser->AEC_inst = tsk_null;
}
#if HAVE_SPEEX_DSP && PREFER_SPEEX_DENOISER
if(denoiser->SpeexDenoiser_proc){
if (denoiser->SpeexDenoiser_proc) {
speex_preprocess_state_destroy(denoiser->SpeexDenoiser_proc);
denoiser->SpeexDenoiser_proc = tsk_null;
}
#else
if(denoiser->NS_inst){
if (denoiser->NS_inst) {
TDAV_WebRtcNs_Free(denoiser->NS_inst);
denoiser->NS_inst = tsk_null;
}
#endif
TSK_FREE(denoiser->temp_rec_out);
tsk_safeobj_unlock(denoiser);
return 0;
}
static int _tdav_webrtc_resampler_create(const tdav_webrtc_pin_xt* p_pin_in, const tdav_webrtc_pin_xt* p_pin_out, tdav_webrtc_resampler_t **pp_resampler)
{
extern const tsk_object_def_t *tdav_webrtc_resampler_def_t;
int ret = 0;
if (!p_pin_in || !p_pin_out || !pp_resampler || *pp_resampler) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (!(*pp_resampler = tsk_object_new(tdav_webrtc_resampler_def_t))) {
TSK_DEBUG_ERROR("Failed to create resampler object");
ret = -3;
goto bail;
}
if (!((*pp_resampler)->p_resampler = tmedia_resampler_create())) {
ret = -3;
goto bail;
}
ret = tmedia_resampler_open((*pp_resampler)->p_resampler,
p_pin_in->n_rate, p_pin_out->n_rate,
p_pin_in->n_duration,
p_pin_in->n_channels, p_pin_out->n_channels,
TMEDIA_RESAMPLER_QUALITY,
(p_pin_out->n_sample_size << 3));
if (ret) {
TSK_DEBUG_ERROR("Failed to open resampler: in_rate=%u,in_duration=%u,in_channels=%u /// out_rate=%u,out_duration=%u,out_channels=%u",
p_pin_in->n_rate, p_pin_in->n_duration, p_pin_in->n_channels,
p_pin_out->n_rate, p_pin_out->n_duration, p_pin_out->n_channels);
goto bail;
}
(*pp_resampler)->out.n_buff_size_in_bytes = ((((p_pin_out->n_rate * p_pin_out->n_duration) / 1000)) * p_pin_out->n_channels) * p_pin_out->n_sample_size;
(*pp_resampler)->out.p_buff_ptr = tsk_malloc((*pp_resampler)->out.n_buff_size_in_bytes);
if (!(*pp_resampler)->out.p_buff_ptr) {
TSK_DEBUG_ERROR("Failed to allocate buffer with size=%u", (*pp_resampler)->out.n_buff_size_in_bytes);
ret = -3;
goto bail;
}
(*pp_resampler)->out.n_buff_size_in_samples = (*pp_resampler)->out.n_buff_size_in_bytes / p_pin_out->n_sample_size;
(*pp_resampler)->in.n_buff_size_in_bytes = ((((p_pin_in->n_rate * p_pin_in->n_duration) / 1000)) * p_pin_in->n_channels) * p_pin_in->n_sample_size;
(*pp_resampler)->in.n_buff_size_in_samples = (*pp_resampler)->in.n_buff_size_in_bytes / p_pin_in->n_sample_size;
(*pp_resampler)->n_bufftmp_size_in_bytes = (((48000 * TSK_MAX(p_pin_in->n_duration, p_pin_out->n_duration)) / 1000) * 2/*channels*/) * sizeof(float); // Max
(*pp_resampler)->p_bufftmp_ptr = tsk_malloc((*pp_resampler)->n_bufftmp_size_in_bytes);
if (!(*pp_resampler)->p_bufftmp_ptr) {
TSK_DEBUG_ERROR("Failed to allocate buffer with size:%u", (*pp_resampler)->n_bufftmp_size_in_bytes);
ret = -3;
goto bail;
}
memcpy(&(*pp_resampler)->in.x_pin, p_pin_in, sizeof(tdav_webrtc_pin_xt));
memcpy(&(*pp_resampler)->out.x_pin, p_pin_out, sizeof(tdav_webrtc_pin_xt));
bail:
if (ret) {
TSK_OBJECT_SAFE_FREE((*pp_resampler));
}
return ret;
}
static int _tdav_webrtc_resampler_process(tdav_webrtc_resampler_t *p_self, const void* p_buff_ptr, tsk_size_t n_buff_size_in_bytes)
{
tsk_size_t n_out_size;
const void* _p_buff_ptr = p_buff_ptr;
tsk_size_t _n_buff_size_in_bytes = n_buff_size_in_bytes;
tsk_size_t _n_buff_size_in_samples;
if (!p_self || !p_buff_ptr || !n_buff_size_in_bytes) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
if (p_self->in.n_buff_size_in_bytes != n_buff_size_in_bytes) {
TSK_DEBUG_ERROR("Invalid input size: %u <> %u", p_self->in.n_buff_size_in_bytes, n_buff_size_in_bytes);
return -2;
}
_n_buff_size_in_samples = p_self->in.n_buff_size_in_samples;
if (p_self->in.x_pin.n_sample_size != p_self->out.x_pin.n_sample_size) {
tsk_size_t index;
if (p_self->in.x_pin.n_sample_size == sizeof(int16_t)) {
// int16_t -> float
const int16_t* p_src = (const int16_t*)p_buff_ptr;
float* p_dst = (float*) p_self->p_bufftmp_ptr;
for (index = 0; index < _n_buff_size_in_samples; ++index) {
p_dst[index] = (float)p_src[index];
}
}
else {
// float -> int16_t
const float* p_src = (const float*)p_buff_ptr;
int16_t* p_dst = (int16_t*) p_self->p_bufftmp_ptr;
for (index = 0; index < _n_buff_size_in_samples; ++index) {
p_dst[index] = (int16_t)p_src[index];
}
}
_p_buff_ptr = p_self->p_bufftmp_ptr;
_n_buff_size_in_bytes = p_self->in.n_buff_size_in_bytes;
}
n_out_size = tmedia_resampler_process(p_self->p_resampler, _p_buff_ptr, _n_buff_size_in_samples, (int16_t*)p_self->out.p_buff_ptr, p_self->out.n_buff_size_in_samples);
if (n_out_size != p_self->out.n_buff_size_in_samples) {
TSK_DEBUG_ERROR("Invalid output size: %u <> %u", n_out_size, p_self->out.n_buff_size_in_bytes);
return -4;
}
return 0;
}
//
// Speex denoiser Plugin definition
// WEBRTC resampler object definition
//
static tsk_object_t* tdav_webrtc_resampler_ctor(tsk_object_t * self, va_list * app)
{
tdav_webrtc_resampler_t *p_resampler = (tdav_webrtc_resampler_t*)self;
if (p_resampler) {
}
return self;
}
static tsk_object_t* tdav_webrtc_resampler_dtor(tsk_object_t * self)
{
tdav_webrtc_resampler_t *p_resampler = (tdav_webrtc_resampler_t*)self;
if (p_resampler) {
TSK_OBJECT_SAFE_FREE(p_resampler->p_resampler);
TSK_FREE(p_resampler->out.p_buff_ptr);
TSK_FREE(p_resampler->p_bufftmp_ptr);
}
return self;
}
static const tsk_object_def_t tdav_webrtc_resampler_def_s =
{
sizeof(tdav_webrtc_resampler_t),
tdav_webrtc_resampler_ctor,
tdav_webrtc_resampler_dtor,
tsk_object_cmp,
};
const tsk_object_def_t *tdav_webrtc_resampler_def_t = &tdav_webrtc_resampler_def_s;
//
// WEBRTC denoiser Plugin definition
//
/* constructor */
@ -323,6 +573,7 @@ static tsk_object_t* tdav_webrtc_denoise_ctor(tsk_object_t * _self, va_list * ap
tmedia_denoise_init(TMEDIA_DENOISE(self));
/* init self */
tsk_safeobj_init(self);
self->neg.channels = 1;
TSK_DEBUG_INFO("Create WebRTC denoiser");
}
@ -336,6 +587,11 @@ static tsk_object_t* tdav_webrtc_denoise_dtor(tsk_object_t * _self)
/* deinit base (will close the denoise if not done yet) */
tmedia_denoise_deinit(TMEDIA_DENOISE(self));
/* deinit self */
tdav_webrtc_denoise_close(TMEDIA_DENOISE(self));
TSK_OBJECT_SAFE_FREE(self->record.p_rpl_in2den);
TSK_OBJECT_SAFE_FREE(self->record.p_rpl_den2in);
TSK_OBJECT_SAFE_FREE(self->playback.p_rpl_in2den);
TSK_OBJECT_SAFE_FREE(self->playback.p_rpl_den2in);
tsk_safeobj_deinit(self);
TSK_DEBUG_INFO("*** Destroy WebRTC denoiser ***");

Some files were not shown because too many files have changed in this diff Show More