Fix echo issue on WP8
This commit is contained in:
parent
67d37f7e24
commit
e3fe08a09f
|
@ -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()?");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -46,8 +46,6 @@
|
|||
#ifndef _AES_H
|
||||
#define _AES_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "gf2_8.h"
|
||||
#include "err.h"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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_
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue