├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── include ├── echo_control_mobile.h └── typedefs.h ├── src ├── Makefile ├── aecm_core.c ├── aecm_core.h ├── aecm_defines.h ├── compile_assert.h ├── complex_bit_reverse.c ├── complex_fft.c ├── complex_fft_tables.h ├── cpu_features_wrapper.h ├── cross_correlation.c ├── delay_estimator.c ├── delay_estimator.h ├── delay_estimator_internal.h ├── delay_estimator_wrapper.c ├── delay_estimator_wrapper.h ├── division_operations.c ├── downsample_fast.c ├── echo_control_mobile.c ├── echo_control_mobile.h ├── fk.sh ├── min_max_operations.c ├── randomization_functions.c ├── real_fft.c ├── real_fft.h ├── ring_buffer.c ├── ring_buffer.h ├── signal_processing_library.h ├── spl_init.c ├── spl_inl.h ├── spl_sqrt_floor.c ├── typedefs.h └── vector_scaling_operations.c ├── test ├── Makefile └── main.c └── tools ├── Makefile ├── Makefile.rule └── am.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | 5 | # 依赖关系头文件 6 | *.d 7 | 8 | # Libraries 9 | *.lib 10 | *.a 11 | 12 | # Shared objects (inc. Windows DLLs) 13 | *.dll 14 | *.so 15 | *.so.* 16 | *.dylib 17 | 18 | # Executables 19 | *.exe 20 | *.out 21 | *.app 22 | ctags 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | os: linux 3 | addons: 4 | packages: 5 | - make 6 | 7 | compiler: gcc 8 | script: 9 | - mkdir lib 10 | - make 11 | - make aec 12 | - ./test/aec 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY:all aec clean 2 | r=$(PWD) 3 | 4 | all clean: 5 | if [ "$@" == "clean" ];then\ 6 | rm lib/* -f;\ 7 | fi 8 | for i in `find src -name "Makefile"|sed 's/Makefile//g'`;do\ 9 | $(MAKE) -C $$i r=$r $@ || exit 1;\ 10 | done 11 | 12 | aec: 13 | $(MAKE) -C test/ r=$r $@ || exit 1;\ 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/LuoZhongYao/webrtcaecm.svg?branch=master)](https://travis-ci.org/LuoZhongYao/webrtcaecm) 2 | 3 | 4 | webrtcaecm 5 | ========== 6 | 7 | webRTC aecm模块 ,单独编译,相关头文件都已经整理 8 | 9 | ### 说明 10 | 11 | 之前上传的版本是无法编译的, 现在上传能编译版本. 12 | 自上次整理以来,webrtc进行了大量修改, 从之前的C语言换成了C++实现, 要将audio_process模块提取出来 13 | 单独使用,难度比较大, 建议直接编译webrtc直接调用webrtc接口更为方便. 14 | -------------------------------------------------------------------------------- /include/echo_control_mobile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_ 12 | #define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_ 13 | 14 | #include 15 | 16 | #include "typedefs.h" 17 | 18 | enum { 19 | AecmFalse = 0, 20 | AecmTrue 21 | }; 22 | 23 | // Errors 24 | #define AECM_UNSPECIFIED_ERROR 12000 25 | #define AECM_UNSUPPORTED_FUNCTION_ERROR 12001 26 | #define AECM_UNINITIALIZED_ERROR 12002 27 | #define AECM_NULL_POINTER_ERROR 12003 28 | #define AECM_BAD_PARAMETER_ERROR 12004 29 | 30 | // Warnings 31 | #define AECM_BAD_PARAMETER_WARNING 12100 32 | 33 | typedef struct { 34 | int16_t cngMode; // AECM_FALSE, AECM_TRUE (default) 35 | int16_t echoMode; // 0, 1, 2, 3 (default), 4 36 | } AecmConfig; 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | /* 43 | * Allocates the memory needed by the AECM. The memory needs to be 44 | * initialized separately using the WebRtcAecm_Init() function. 45 | * 46 | * Inputs Description 47 | * ------------------------------------------------------------------- 48 | * void **aecmInst Pointer to the AECM instance to be 49 | * created and initialized 50 | * 51 | * Outputs Description 52 | * ------------------------------------------------------------------- 53 | * int32_t return 0: OK 54 | * -1: error 55 | */ 56 | int32_t WebRtcAecm_Create(void **aecmInst); 57 | 58 | /* 59 | * This function releases the memory allocated by WebRtcAecm_Create() 60 | * 61 | * Inputs Description 62 | * ------------------------------------------------------------------- 63 | * void *aecmInst Pointer to the AECM instance 64 | * 65 | * Outputs Description 66 | * ------------------------------------------------------------------- 67 | * int32_t return 0: OK 68 | * -1: error 69 | */ 70 | int32_t WebRtcAecm_Free(void *aecmInst); 71 | 72 | /* 73 | * Initializes an AECM instance. 74 | * 75 | * Inputs Description 76 | * ------------------------------------------------------------------- 77 | * void *aecmInst Pointer to the AECM instance 78 | * int32_t sampFreq Sampling frequency of data 79 | * 80 | * Outputs Description 81 | * ------------------------------------------------------------------- 82 | * int32_t return 0: OK 83 | * -1: error 84 | */ 85 | int32_t WebRtcAecm_Init(void* aecmInst, int32_t sampFreq); 86 | 87 | /* 88 | * Inserts an 80 or 160 sample block of data into the farend buffer. 89 | * 90 | * Inputs Description 91 | * ------------------------------------------------------------------- 92 | * void *aecmInst Pointer to the AECM instance 93 | * int16_t *farend In buffer containing one frame of 94 | * farend signal 95 | * int16_t nrOfSamples Number of samples in farend buffer 96 | * 97 | * Outputs Description 98 | * ------------------------------------------------------------------- 99 | * int32_t return 0: OK 100 | * -1: error 101 | */ 102 | int32_t WebRtcAecm_BufferFarend(void* aecmInst, 103 | const int16_t* farend, 104 | int16_t nrOfSamples); 105 | 106 | /* 107 | * Runs the AECM on an 80 or 160 sample blocks of data. 108 | * 109 | * Inputs Description 110 | * ------------------------------------------------------------------- 111 | * void *aecmInst Pointer to the AECM instance 112 | * int16_t *nearendNoisy In buffer containing one frame of 113 | * reference nearend+echo signal. If 114 | * noise reduction is active, provide 115 | * the noisy signal here. 116 | * int16_t *nearendClean In buffer containing one frame of 117 | * nearend+echo signal. If noise 118 | * reduction is active, provide the 119 | * clean signal here. Otherwise pass a 120 | * NULL pointer. 121 | * int16_t nrOfSamples Number of samples in nearend buffer 122 | * int16_t msInSndCardBuf Delay estimate for sound card and 123 | * system buffers 124 | * 125 | * Outputs Description 126 | * ------------------------------------------------------------------- 127 | * int16_t *out Out buffer, one frame of processed nearend 128 | * int32_t return 0: OK 129 | * -1: error 130 | */ 131 | int32_t WebRtcAecm_Process(void* aecmInst, 132 | const int16_t* nearendNoisy, 133 | const int16_t* nearendClean, 134 | int16_t* out, 135 | int16_t nrOfSamples, 136 | int16_t msInSndCardBuf); 137 | 138 | /* 139 | * This function enables the user to set certain parameters on-the-fly 140 | * 141 | * Inputs Description 142 | * ------------------------------------------------------------------- 143 | * void *aecmInst Pointer to the AECM instance 144 | * AecmConfig config Config instance that contains all 145 | * properties to be set 146 | * 147 | * Outputs Description 148 | * ------------------------------------------------------------------- 149 | * int32_t return 0: OK 150 | * -1: error 151 | */ 152 | int32_t WebRtcAecm_set_config(void* aecmInst, AecmConfig config); 153 | 154 | /* 155 | * This function enables the user to set certain parameters on-the-fly 156 | * 157 | * Inputs Description 158 | * ------------------------------------------------------------------- 159 | * void *aecmInst Pointer to the AECM instance 160 | * 161 | * Outputs Description 162 | * ------------------------------------------------------------------- 163 | * AecmConfig *config Pointer to the config instance that 164 | * all properties will be written to 165 | * int32_t return 0: OK 166 | * -1: error 167 | */ 168 | int32_t WebRtcAecm_get_config(void *aecmInst, AecmConfig *config); 169 | 170 | /* 171 | * This function enables the user to set the echo path on-the-fly. 172 | * 173 | * Inputs Description 174 | * ------------------------------------------------------------------- 175 | * void* aecmInst Pointer to the AECM instance 176 | * void* echo_path Pointer to the echo path to be set 177 | * size_t size_bytes Size in bytes of the echo path 178 | * 179 | * Outputs Description 180 | * ------------------------------------------------------------------- 181 | * int32_t return 0: OK 182 | * -1: error 183 | */ 184 | int32_t WebRtcAecm_InitEchoPath(void* aecmInst, 185 | const void* echo_path, 186 | size_t size_bytes); 187 | 188 | /* 189 | * This function enables the user to get the currently used echo path 190 | * on-the-fly 191 | * 192 | * Inputs Description 193 | * ------------------------------------------------------------------- 194 | * void* aecmInst Pointer to the AECM instance 195 | * void* echo_path Pointer to echo path 196 | * size_t size_bytes Size in bytes of the echo path 197 | * 198 | * Outputs Description 199 | * ------------------------------------------------------------------- 200 | * int32_t return 0: OK 201 | * -1: error 202 | */ 203 | int32_t WebRtcAecm_GetEchoPath(void* aecmInst, 204 | void* echo_path, 205 | size_t size_bytes); 206 | 207 | /* 208 | * This function enables the user to get the echo path size in bytes 209 | * 210 | * Outputs Description 211 | * ------------------------------------------------------------------- 212 | * size_t return : size in bytes 213 | */ 214 | size_t WebRtcAecm_echo_path_size_bytes(); 215 | 216 | /* 217 | * Gets the last error code. 218 | * 219 | * Inputs Description 220 | * ------------------------------------------------------------------- 221 | * void *aecmInst Pointer to the AECM instance 222 | * 223 | * Outputs Description 224 | * ------------------------------------------------------------------- 225 | * int32_t return 11000-11100: error code 226 | */ 227 | int32_t WebRtcAecm_get_error_code(void *aecmInst); 228 | 229 | #ifdef __cplusplus 230 | } 231 | #endif 232 | #endif // WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_ 233 | -------------------------------------------------------------------------------- /include/typedefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // This file contains platform-specific typedefs and defines. 12 | // Much of it is derived from Chromium's build/build_config.h. 13 | 14 | #ifndef WEBRTC_TYPEDEFS_H_ 15 | #define WEBRTC_TYPEDEFS_H_ 16 | 17 | // For access to standard POSIXish features, use WEBRTC_POSIX instead of a 18 | // more specific macro. 19 | #if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX) || \ 20 | defined(WEBRTC_ANDROID) 21 | #define WEBRTC_POSIX 22 | #endif 23 | 24 | // Processor architecture detection. For more info on what's defined, see: 25 | // http://msdn.microsoft.com/en-us/library/b0084kay.aspx 26 | // http://www.agner.org/optimize/calling_conventions.pdf 27 | // or with gcc, run: "echo | gcc -E -dM -" 28 | // TODO(andrew): replace WEBRTC_LITTLE_ENDIAN with WEBRTC_ARCH_LITTLE_ENDIAN. 29 | #if defined(_M_X64) || defined(__x86_64__) 30 | #define WEBRTC_ARCH_X86_FAMILY 31 | #define WEBRTC_ARCH_X86_64 32 | #define WEBRTC_ARCH_64_BITS 33 | #define WEBRTC_ARCH_LITTLE_ENDIAN 34 | #define WEBRTC_LITTLE_ENDIAN 35 | #elif defined(_M_IX86) || defined(__i386__) 36 | #define WEBRTC_ARCH_X86_FAMILY 37 | #define WEBRTC_ARCH_X86 38 | #define WEBRTC_ARCH_32_BITS 39 | #define WEBRTC_ARCH_LITTLE_ENDIAN 40 | #define WEBRTC_LITTLE_ENDIAN 41 | #elif defined(__ARMEL__) 42 | // TODO(andrew): We'd prefer to control platform defines here, but this is 43 | // currently provided by the Android makefiles. Commented to avoid duplicate 44 | // definition warnings. 45 | //#define WEBRTC_ARCH_ARM 46 | // TODO(andrew): Chromium uses the following two defines. Should we switch? 47 | //#define WEBRTC_ARCH_ARM_FAMILY 48 | //#define WEBRTC_ARCH_ARMEL 49 | #define WEBRTC_ARCH_32_BITS 50 | #define WEBRTC_ARCH_LITTLE_ENDIAN 51 | #define WEBRTC_LITTLE_ENDIAN 52 | #elif defined(__MIPSEL__) 53 | #define WEBRTC_ARCH_32_BITS 54 | #define WEBRTC_ARCH_LITTLE_ENDIAN 55 | #define WEBRTC_LITTLE_ENDIAN 56 | #else 57 | #error Please add support for your architecture in typedefs.h 58 | #endif 59 | 60 | #if defined(__SSE2__) || defined(_MSC_VER) 61 | #define WEBRTC_USE_SSE2 62 | #endif 63 | 64 | #if !defined(_MSC_VER) 65 | #include 66 | #else 67 | // Define C99 equivalent types, since MSVC doesn't provide stdint.h. 68 | typedef signed char int8_t; 69 | typedef signed short int16_t; 70 | typedef signed int int32_t; 71 | typedef __int64 int64_t; 72 | typedef unsigned char uint8_t; 73 | typedef unsigned short uint16_t; 74 | typedef unsigned int uint32_t; 75 | typedef unsigned __int64 uint64_t; 76 | #endif 77 | 78 | // Borrowed from Chromium's base/compiler_specific.h. 79 | // Annotate a virtual method indicating it must be overriding a virtual 80 | // method in the parent class. 81 | // Use like: 82 | // virtual void foo() OVERRIDE; 83 | #if defined(_MSC_VER) 84 | #define OVERRIDE override 85 | #elif defined(__clang__) 86 | // Clang defaults to C++03 and warns about using override. Squelch that. 87 | // Intentionally no push/pop here so all users of OVERRIDE ignore the warning 88 | // too. This is like passing -Wno-c++11-extensions, except that GCC won't die 89 | // (because it won't see this pragma). 90 | #pragma clang diagnostic ignored "-Wc++11-extensions" 91 | #define OVERRIDE override 92 | #else 93 | #define OVERRIDE 94 | #endif 95 | 96 | #endif // WEBRTC_TYPEDEFS_H_ 97 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | LOCAL_PATH=$(notdir $(shell pwd)) 2 | CFILES=$(shell find ./ -maxdepth 1 -name "*.c") 3 | CXXFILES=$(shell find ./ -maxdepth 1 -name "*.cc") 4 | OBJS = $(CFILES:%.c=%.o) $(CXXFILES:%.cc=%.o) 5 | 6 | .PHONY:all clean 7 | 8 | 9 | ifneq ($(OBJS),) 10 | OBJ=$r/lib/libaec.a 11 | CFLAGS += -DWEBRTC_POSIX 12 | all:$(OBJ) 13 | 14 | $(OBJ):$(OBJS) 15 | ar -r $@ $^ 16 | 17 | include $r/tools/Makefile.rule 18 | -include $(OBJS:%.o=%.d) 19 | -include $(OBJS:%.o=%.d) 20 | else 21 | $(error 该目录下没有文件可以生成.o) 22 | endif 23 | -------------------------------------------------------------------------------- /src/aecm_core.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // Performs echo control (suppression) with fft routines in fixed-point. 12 | 13 | #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_AECM_CORE_H_ 14 | #define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_AECM_CORE_H_ 15 | 16 | #include "signal_processing_library.h" 17 | #include "aecm_defines.h" 18 | #include "ring_buffer.h" 19 | #include "typedefs.h" 20 | 21 | #ifdef _MSC_VER // visual c++ 22 | #define ALIGN8_BEG __declspec(align(8)) 23 | #define ALIGN8_END 24 | #else // gcc or icc 25 | #define ALIGN8_BEG 26 | #define ALIGN8_END __attribute__((aligned(8))) 27 | #endif 28 | 29 | typedef struct { 30 | int16_t real; 31 | int16_t imag; 32 | } complex16_t; 33 | 34 | typedef struct { 35 | int farBufWritePos; 36 | int farBufReadPos; 37 | int knownDelay; 38 | int lastKnownDelay; 39 | int firstVAD; // Parameter to control poorly initialized channels 40 | 41 | RingBuffer* farFrameBuf; 42 | RingBuffer* nearNoisyFrameBuf; 43 | RingBuffer* nearCleanFrameBuf; 44 | RingBuffer* outFrameBuf; 45 | 46 | int16_t farBuf[FAR_BUF_LEN]; 47 | 48 | int16_t mult; 49 | uint32_t seed; 50 | 51 | // Delay estimation variables 52 | void* delay_estimator_farend; 53 | void* delay_estimator; 54 | uint16_t currentDelay; 55 | // Far end history variables 56 | // TODO(bjornv): Replace |far_history| with ring_buffer. 57 | uint16_t far_history[PART_LEN1 * MAX_DELAY]; 58 | int far_history_pos; 59 | int far_q_domains[MAX_DELAY]; 60 | 61 | int16_t nlpFlag; 62 | int16_t fixedDelay; 63 | 64 | uint32_t totCount; 65 | 66 | int16_t dfaCleanQDomain; 67 | int16_t dfaCleanQDomainOld; 68 | int16_t dfaNoisyQDomain; 69 | int16_t dfaNoisyQDomainOld; 70 | 71 | int16_t nearLogEnergy[MAX_BUF_LEN]; 72 | int16_t farLogEnergy; 73 | int16_t echoAdaptLogEnergy[MAX_BUF_LEN]; 74 | int16_t echoStoredLogEnergy[MAX_BUF_LEN]; 75 | 76 | // The extra 16 or 32 bytes in the following buffers are for alignment based 77 | // Neon code. 78 | // It's designed this way since the current GCC compiler can't align a 79 | // buffer in 16 or 32 byte boundaries properly. 80 | int16_t channelStored_buf[PART_LEN1 + 8]; 81 | int16_t channelAdapt16_buf[PART_LEN1 + 8]; 82 | int32_t channelAdapt32_buf[PART_LEN1 + 8]; 83 | int16_t xBuf_buf[PART_LEN2 + 16]; // farend 84 | int16_t dBufClean_buf[PART_LEN2 + 16]; // nearend 85 | int16_t dBufNoisy_buf[PART_LEN2 + 16]; // nearend 86 | int16_t outBuf_buf[PART_LEN + 8]; 87 | 88 | // Pointers to the above buffers 89 | int16_t *channelStored; 90 | int16_t *channelAdapt16; 91 | int32_t *channelAdapt32; 92 | int16_t *xBuf; 93 | int16_t *dBufClean; 94 | int16_t *dBufNoisy; 95 | int16_t *outBuf; 96 | 97 | int32_t echoFilt[PART_LEN1]; 98 | int16_t nearFilt[PART_LEN1]; 99 | int32_t noiseEst[PART_LEN1]; 100 | int noiseEstTooLowCtr[PART_LEN1]; 101 | int noiseEstTooHighCtr[PART_LEN1]; 102 | int16_t noiseEstCtr; 103 | int16_t cngMode; 104 | 105 | int32_t mseAdaptOld; 106 | int32_t mseStoredOld; 107 | int32_t mseThreshold; 108 | 109 | int16_t farEnergyMin; 110 | int16_t farEnergyMax; 111 | int16_t farEnergyMaxMin; 112 | int16_t farEnergyVAD; 113 | int16_t farEnergyMSE; 114 | int currentVADValue; 115 | int16_t vadUpdateCount; 116 | 117 | int16_t startupState; 118 | int16_t mseChannelCount; 119 | int16_t supGain; 120 | int16_t supGainOld; 121 | 122 | int16_t supGainErrParamA; 123 | int16_t supGainErrParamD; 124 | int16_t supGainErrParamDiffAB; 125 | int16_t supGainErrParamDiffBD; 126 | 127 | struct RealFFT* real_fft; 128 | 129 | #ifdef AEC_DEBUG 130 | FILE *farFile; 131 | FILE *nearFile; 132 | FILE *outFile; 133 | #endif 134 | } AecmCore_t; 135 | 136 | //////////////////////////////////////////////////////////////////////////////// 137 | // WebRtcAecm_CreateCore(...) 138 | // 139 | // Allocates the memory needed by the AECM. The memory needs to be 140 | // initialized separately using the WebRtcAecm_InitCore() function. 141 | // 142 | // Input: 143 | // - aecm : Instance that should be created 144 | // 145 | // Output: 146 | // - aecm : Created instance 147 | // 148 | // Return value : 0 - Ok 149 | // -1 - Error 150 | // 151 | int WebRtcAecm_CreateCore(AecmCore_t **aecm); 152 | 153 | //////////////////////////////////////////////////////////////////////////////// 154 | // WebRtcAecm_InitCore(...) 155 | // 156 | // This function initializes the AECM instant created with 157 | // WebRtcAecm_CreateCore(...) 158 | // Input: 159 | // - aecm : Pointer to the AECM instance 160 | // - samplingFreq : Sampling Frequency 161 | // 162 | // Output: 163 | // - aecm : Initialized instance 164 | // 165 | // Return value : 0 - Ok 166 | // -1 - Error 167 | // 168 | int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq); 169 | 170 | //////////////////////////////////////////////////////////////////////////////// 171 | // WebRtcAecm_FreeCore(...) 172 | // 173 | // This function releases the memory allocated by WebRtcAecm_CreateCore() 174 | // Input: 175 | // - aecm : Pointer to the AECM instance 176 | // 177 | // Return value : 0 - Ok 178 | // -1 - Error 179 | // 11001-11016: Error 180 | // 181 | int WebRtcAecm_FreeCore(AecmCore_t *aecm); 182 | 183 | int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag); 184 | 185 | //////////////////////////////////////////////////////////////////////////////// 186 | // WebRtcAecm_InitEchoPathCore(...) 187 | // 188 | // This function resets the echo channel adaptation with the specified channel. 189 | // Input: 190 | // - aecm : Pointer to the AECM instance 191 | // - echo_path : Pointer to the data that should initialize the echo 192 | // path 193 | // 194 | // Output: 195 | // - aecm : Initialized instance 196 | // 197 | void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, 198 | const int16_t* echo_path); 199 | 200 | //////////////////////////////////////////////////////////////////////////////// 201 | // WebRtcAecm_ProcessFrame(...) 202 | // 203 | // This function processes frames and sends blocks to 204 | // WebRtcAecm_ProcessBlock(...) 205 | // 206 | // Inputs: 207 | // - aecm : Pointer to the AECM instance 208 | // - farend : In buffer containing one frame of echo signal 209 | // - nearendNoisy : In buffer containing one frame of nearend+echo signal 210 | // without NS 211 | // - nearendClean : In buffer containing one frame of nearend+echo signal 212 | // with NS 213 | // 214 | // Output: 215 | // - out : Out buffer, one frame of nearend signal : 216 | // 217 | // 218 | int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, const int16_t * farend, 219 | const int16_t * nearendNoisy, 220 | const int16_t * nearendClean, 221 | int16_t * out); 222 | 223 | //////////////////////////////////////////////////////////////////////////////// 224 | // WebRtcAecm_ProcessBlock(...) 225 | // 226 | // This function is called for every block within one frame 227 | // This function is called by WebRtcAecm_ProcessFrame(...) 228 | // 229 | // Inputs: 230 | // - aecm : Pointer to the AECM instance 231 | // - farend : In buffer containing one block of echo signal 232 | // - nearendNoisy : In buffer containing one frame of nearend+echo signal 233 | // without NS 234 | // - nearendClean : In buffer containing one frame of nearend+echo signal 235 | // with NS 236 | // 237 | // Output: 238 | // - out : Out buffer, one block of nearend signal : 239 | // 240 | // 241 | int WebRtcAecm_ProcessBlock(AecmCore_t * aecm, const int16_t * farend, 242 | const int16_t * nearendNoisy, 243 | const int16_t * noisyClean, 244 | int16_t * out); 245 | 246 | //////////////////////////////////////////////////////////////////////////////// 247 | // WebRtcAecm_BufferFarFrame() 248 | // 249 | // Inserts a frame of data into farend buffer. 250 | // 251 | // Inputs: 252 | // - aecm : Pointer to the AECM instance 253 | // - farend : In buffer containing one frame of farend signal 254 | // - farLen : Length of frame 255 | // 256 | void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm, 257 | const int16_t * const farend, 258 | const int farLen); 259 | 260 | //////////////////////////////////////////////////////////////////////////////// 261 | // WebRtcAecm_FetchFarFrame() 262 | // 263 | // Read the farend buffer to account for known delay 264 | // 265 | // Inputs: 266 | // - aecm : Pointer to the AECM instance 267 | // - farend : In buffer containing one frame of farend signal 268 | // - farLen : Length of frame 269 | // - knownDelay : known delay 270 | // 271 | void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, 272 | int16_t * const farend, 273 | const int farLen, const int knownDelay); 274 | 275 | /////////////////////////////////////////////////////////////////////////////// 276 | // Some function pointers, for internal functions shared by ARM NEON and 277 | // generic C code. 278 | // 279 | typedef void (*CalcLinearEnergies)( 280 | AecmCore_t* aecm, 281 | const uint16_t* far_spectrum, 282 | int32_t* echoEst, 283 | uint32_t* far_energy, 284 | uint32_t* echo_energy_adapt, 285 | uint32_t* echo_energy_stored); 286 | extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies; 287 | 288 | typedef void (*StoreAdaptiveChannel)( 289 | AecmCore_t* aecm, 290 | const uint16_t* far_spectrum, 291 | int32_t* echo_est); 292 | extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel; 293 | 294 | typedef void (*ResetAdaptiveChannel)(AecmCore_t* aecm); 295 | extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel; 296 | 297 | // For the above function pointers, functions for generic platforms are declared 298 | // and defined as static in file aecm_core.c, while those for ARM Neon platforms 299 | // are declared below and defined in file aecm_core_neon.s. 300 | #if (defined WEBRTC_DETECT_ARM_NEON) || defined (WEBRTC_ARCH_ARM_NEON) 301 | void WebRtcAecm_CalcLinearEnergiesNeon(AecmCore_t* aecm, 302 | const uint16_t* far_spectrum, 303 | int32_t* echo_est, 304 | uint32_t* far_energy, 305 | uint32_t* echo_energy_adapt, 306 | uint32_t* echo_energy_stored); 307 | 308 | void WebRtcAecm_StoreAdaptiveChannelNeon(AecmCore_t* aecm, 309 | const uint16_t* far_spectrum, 310 | int32_t* echo_est); 311 | 312 | void WebRtcAecm_ResetAdaptiveChannelNeon(AecmCore_t* aecm); 313 | #endif 314 | 315 | #endif 316 | -------------------------------------------------------------------------------- /src/aecm_defines.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_AECM_DEFINES_H_ 12 | #define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_AECM_DEFINES_H_ 13 | 14 | #define AECM_DYNAMIC_Q /* Turn on/off dynamic Q-domain. */ 15 | 16 | /* Algorithm parameters */ 17 | #define FRAME_LEN 80 /* Total frame length, 10 ms. */ 18 | 19 | #define PART_LEN 64 /* Length of partition. */ 20 | #define PART_LEN_SHIFT 7 /* Length of (PART_LEN * 2) in base 2. */ 21 | 22 | #define PART_LEN1 (PART_LEN + 1) /* Unique fft coefficients. */ 23 | #define PART_LEN2 (PART_LEN << 1) /* Length of partition * 2. */ 24 | #define PART_LEN4 (PART_LEN << 2) /* Length of partition * 4. */ 25 | #define FAR_BUF_LEN PART_LEN4 /* Length of buffers. */ 26 | #define MAX_DELAY 100 27 | 28 | /* Counter parameters */ 29 | #define CONV_LEN 512 /* Convergence length used at startup. */ 30 | #define CONV_LEN2 (CONV_LEN << 1) /* Used at startup. */ 31 | 32 | /* Energy parameters */ 33 | #define MAX_BUF_LEN 64 /* History length of energy signals. */ 34 | #define FAR_ENERGY_MIN 1025 /* Lowest Far energy level: At least 2 */ 35 | /* in energy. */ 36 | #define FAR_ENERGY_DIFF 929 /* Allowed difference between max */ 37 | /* and min. */ 38 | #define ENERGY_DEV_OFFSET 0 /* The energy error offset in Q8. */ 39 | #define ENERGY_DEV_TOL 400 /* The energy estimation tolerance (Q8). */ 40 | #define FAR_ENERGY_VAD_REGION 230 /* Far VAD tolerance region. */ 41 | 42 | /* Stepsize parameters */ 43 | #define MU_MIN 10 /* Min stepsize 2^-MU_MIN (far end energy */ 44 | /* dependent). */ 45 | #define MU_MAX 1 /* Max stepsize 2^-MU_MAX (far end energy */ 46 | /* dependent). */ 47 | #define MU_DIFF 9 /* MU_MIN - MU_MAX */ 48 | 49 | /* Channel parameters */ 50 | #define MIN_MSE_COUNT 20 /* Min number of consecutive blocks with enough */ 51 | /* far end energy to compare channel estimates. */ 52 | #define MIN_MSE_DIFF 29 /* The ratio between adapted and stored channel to */ 53 | /* accept a new storage (0.8 in Q-MSE_RESOLUTION). */ 54 | #define MSE_RESOLUTION 5 /* MSE parameter resolution. */ 55 | #define RESOLUTION_CHANNEL16 12 /* W16 Channel in Q-RESOLUTION_CHANNEL16. */ 56 | #define RESOLUTION_CHANNEL32 28 /* W32 Channel in Q-RESOLUTION_CHANNEL. */ 57 | #define CHANNEL_VAD 16 /* Minimum energy in frequency band */ 58 | /* to update channel. */ 59 | 60 | /* Suppression gain parameters: SUPGAIN parameters in Q-(RESOLUTION_SUPGAIN). */ 61 | #define RESOLUTION_SUPGAIN 8 /* Channel in Q-(RESOLUTION_SUPGAIN). */ 62 | #define SUPGAIN_DEFAULT (1 << RESOLUTION_SUPGAIN) /* Default. */ 63 | #define SUPGAIN_ERROR_PARAM_A 3072 /* Estimation error parameter */ 64 | /* (Maximum gain) (8 in Q8). */ 65 | #define SUPGAIN_ERROR_PARAM_B 1536 /* Estimation error parameter */ 66 | /* (Gain before going down). */ 67 | #define SUPGAIN_ERROR_PARAM_D SUPGAIN_DEFAULT /* Estimation error parameter */ 68 | /* (Should be the same as Default) (1 in Q8). */ 69 | #define SUPGAIN_EPC_DT 200 /* SUPGAIN_ERROR_PARAM_C * ENERGY_DEV_TOL */ 70 | 71 | /* Defines for "check delay estimation" */ 72 | #define CORR_WIDTH 31 /* Number of samples to correlate over. */ 73 | #define CORR_MAX 16 /* Maximum correlation offset. */ 74 | #define CORR_MAX_BUF 63 75 | #define CORR_DEV 4 76 | #define CORR_MAX_LEVEL 20 77 | #define CORR_MAX_LOW 4 78 | #define CORR_BUF_LEN (CORR_MAX << 1) + 1 79 | /* Note that CORR_WIDTH + 2*CORR_MAX <= MAX_BUF_LEN. */ 80 | 81 | #define ONE_Q14 (1 << 14) 82 | 83 | /* NLP defines */ 84 | #define NLP_COMP_LOW 3277 /* 0.2 in Q14 */ 85 | #define NLP_COMP_HIGH ONE_Q14 /* 1 in Q14 */ 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /src/compile_assert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ 12 | #define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ 13 | 14 | /* Use this macro to verify at compile time that certain restrictions are met. 15 | * The argument is the boolean expression to evaluate. 16 | * Example: 17 | * COMPILE_ASSERT(sizeof(foo) < 128); 18 | */ 19 | #define COMPILE_ASSERT(expression) switch(0){case 0: case expression:;} 20 | 21 | #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_ 22 | -------------------------------------------------------------------------------- /src/complex_bit_reverse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "signal_processing_library.h" 12 | 13 | /* Tables for data buffer indexes that are bit reversed and thus need to be 14 | * swapped. Note that, index_7[{0, 2, 4, ...}] are for the left side of the swap 15 | * operations, while index_7[{1, 3, 5, ...}] are for the right side of the 16 | * operation. Same for index_8. 17 | */ 18 | 19 | /* Indexes for the case of stages == 7. */ 20 | static const int16_t index_7[112] = { 21 | 1, 64, 2, 32, 3, 96, 4, 16, 5, 80, 6, 48, 7, 112, 9, 72, 10, 40, 11, 104, 22 | 12, 24, 13, 88, 14, 56, 15, 120, 17, 68, 18, 36, 19, 100, 21, 84, 22, 52, 23 | 23, 116, 25, 76, 26, 44, 27, 108, 29, 92, 30, 60, 31, 124, 33, 66, 35, 98, 24 | 37, 82, 38, 50, 39, 114, 41, 74, 43, 106, 45, 90, 46, 58, 47, 122, 49, 70, 25 | 51, 102, 53, 86, 55, 118, 57, 78, 59, 110, 61, 94, 63, 126, 67, 97, 69, 26 | 81, 71, 113, 75, 105, 77, 89, 79, 121, 83, 101, 87, 117, 91, 109, 95, 125, 27 | 103, 115, 111, 123 28 | }; 29 | 30 | /* Indexes for the case of stages == 8. */ 31 | static const int16_t index_8[240] = { 32 | 1, 128, 2, 64, 3, 192, 4, 32, 5, 160, 6, 96, 7, 224, 8, 16, 9, 144, 10, 80, 33 | 11, 208, 12, 48, 13, 176, 14, 112, 15, 240, 17, 136, 18, 72, 19, 200, 20, 34 | 40, 21, 168, 22, 104, 23, 232, 25, 152, 26, 88, 27, 216, 28, 56, 29, 184, 35 | 30, 120, 31, 248, 33, 132, 34, 68, 35, 196, 37, 164, 38, 100, 39, 228, 41, 36 | 148, 42, 84, 43, 212, 44, 52, 45, 180, 46, 116, 47, 244, 49, 140, 50, 76, 37 | 51, 204, 53, 172, 54, 108, 55, 236, 57, 156, 58, 92, 59, 220, 61, 188, 62, 38 | 124, 63, 252, 65, 130, 67, 194, 69, 162, 70, 98, 71, 226, 73, 146, 74, 82, 39 | 75, 210, 77, 178, 78, 114, 79, 242, 81, 138, 83, 202, 85, 170, 86, 106, 87, 40 | 234, 89, 154, 91, 218, 93, 186, 94, 122, 95, 250, 97, 134, 99, 198, 101, 41 | 166, 103, 230, 105, 150, 107, 214, 109, 182, 110, 118, 111, 246, 113, 142, 42 | 115, 206, 117, 174, 119, 238, 121, 158, 123, 222, 125, 190, 127, 254, 131, 43 | 193, 133, 161, 135, 225, 137, 145, 139, 209, 141, 177, 143, 241, 147, 201, 44 | 149, 169, 151, 233, 155, 217, 157, 185, 159, 249, 163, 197, 167, 229, 171, 45 | 213, 173, 181, 175, 245, 179, 205, 183, 237, 187, 221, 191, 253, 199, 227, 46 | 203, 211, 207, 243, 215, 235, 223, 251, 239, 247 47 | }; 48 | 49 | void WebRtcSpl_ComplexBitReverse(int16_t* __restrict complex_data, int stages) { 50 | /* For any specific value of stages, we know exactly the indexes that are 51 | * bit reversed. Currently (Feb. 2012) in WebRTC the only possible values of 52 | * stages are 7 and 8, so we use tables to save unnecessary iterations and 53 | * calculations for these two cases. 54 | */ 55 | if (stages == 7 || stages == 8) { 56 | int m = 0; 57 | int length = 112; 58 | const int16_t* index = index_7; 59 | 60 | if (stages == 8) { 61 | length = 240; 62 | index = index_8; 63 | } 64 | 65 | /* Decimation in time. Swap the elements with bit-reversed indexes. */ 66 | for (m = 0; m < length; m += 2) { 67 | /* We declare a int32_t* type pointer, to load both the 16-bit real 68 | * and imaginary elements from complex_data in one instruction, reducing 69 | * complexity. 70 | */ 71 | int32_t* complex_data_ptr = (int32_t*)complex_data; 72 | int32_t temp = 0; 73 | 74 | temp = complex_data_ptr[index[m]]; /* Real and imaginary */ 75 | complex_data_ptr[index[m]] = complex_data_ptr[index[m + 1]]; 76 | complex_data_ptr[index[m + 1]] = temp; 77 | } 78 | } 79 | else { 80 | int m = 0, mr = 0, l = 0; 81 | int n = 1 << stages; 82 | int nn = n - 1; 83 | 84 | /* Decimation in time - re-order data */ 85 | for (m = 1; m <= nn; ++m) { 86 | int32_t* complex_data_ptr = (int32_t*)complex_data; 87 | int32_t temp = 0; 88 | 89 | /* Find out indexes that are bit-reversed. */ 90 | l = n; 91 | do { 92 | l >>= 1; 93 | } while (l > nn - mr); 94 | mr = (mr & (l - 1)) + l; 95 | 96 | if (mr <= m) { 97 | continue; 98 | } 99 | 100 | /* Swap the elements with bit-reversed indexes. 101 | * This is similar to the loop in the stages == 7 or 8 cases. 102 | */ 103 | temp = complex_data_ptr[m]; /* Real and imaginary */ 104 | complex_data_ptr[m] = complex_data_ptr[mr]; 105 | complex_data_ptr[mr] = temp; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/complex_fft.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | 12 | /* 13 | * This file contains the function WebRtcSpl_ComplexFFT(). 14 | * The description header can be found in signal_processing_library.h 15 | * 16 | */ 17 | 18 | #include "complex_fft_tables.h" 19 | #include "signal_processing_library.h" 20 | 21 | #define CFFTSFT 14 22 | #define CFFTRND 1 23 | #define CFFTRND2 16384 24 | 25 | #define CIFFTSFT 14 26 | #define CIFFTRND 1 27 | 28 | 29 | int WebRtcSpl_ComplexFFT(int16_t frfi[], int stages, int mode) 30 | { 31 | int i, j, l, k, istep, n, m; 32 | int16_t wr, wi; 33 | int32_t tr32, ti32, qr32, qi32; 34 | 35 | /* The 1024-value is a constant given from the size of kSinTable1024[], 36 | * and should not be changed depending on the input parameter 'stages' 37 | */ 38 | n = 1 << stages; 39 | if (n > 1024) 40 | return -1; 41 | 42 | l = 1; 43 | k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change 44 | depending on the input parameter 'stages' */ 45 | 46 | if (mode == 0) 47 | { 48 | // mode==0: Low-complexity and Low-accuracy mode 49 | while (l < n) 50 | { 51 | istep = l << 1; 52 | 53 | for (m = 0; m < l; ++m) 54 | { 55 | j = m << k; 56 | 57 | /* The 256-value is a constant given as 1/4 of the size of 58 | * kSinTable1024[], and should not be changed depending on the input 59 | * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 60 | */ 61 | wr = kSinTable1024[j + 256]; 62 | wi = -kSinTable1024[j]; 63 | 64 | for (i = m; i < n; i += istep) 65 | { 66 | j = i + l; 67 | 68 | tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) 69 | - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1])), 15); 70 | 71 | ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) 72 | + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j])), 15); 73 | 74 | qr32 = (int32_t)frfi[2 * i]; 75 | qi32 = (int32_t)frfi[2 * i + 1]; 76 | frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, 1); 77 | frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, 1); 78 | frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, 1); 79 | frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, 1); 80 | } 81 | } 82 | 83 | --k; 84 | l = istep; 85 | 86 | } 87 | 88 | } else 89 | { 90 | // mode==1: High-complexity and High-accuracy mode 91 | while (l < n) 92 | { 93 | istep = l << 1; 94 | 95 | for (m = 0; m < l; ++m) 96 | { 97 | j = m << k; 98 | 99 | /* The 256-value is a constant given as 1/4 of the size of 100 | * kSinTable1024[], and should not be changed depending on the input 101 | * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 102 | */ 103 | wr = kSinTable1024[j + 256]; 104 | wi = -kSinTable1024[j]; 105 | 106 | #ifdef WEBRTC_ARCH_ARM_V7 107 | int32_t wri = 0; 108 | int32_t frfi_r = 0; 109 | __asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) : 110 | "r"((int32_t)wr), "r"((int32_t)wi)); 111 | #endif 112 | 113 | for (i = m; i < n; i += istep) 114 | { 115 | j = i + l; 116 | 117 | #ifdef WEBRTC_ARCH_ARM_V7 118 | __asm __volatile( 119 | "pkhbt %[frfi_r], %[frfi_even], %[frfi_odd], lsl #16\n\t" 120 | "smlsd %[tr32], %[wri], %[frfi_r], %[cfftrnd]\n\t" 121 | "smladx %[ti32], %[wri], %[frfi_r], %[cfftrnd]\n\t" 122 | :[frfi_r]"+r"(frfi_r), 123 | [tr32]"=r"(tr32), 124 | [ti32]"=r"(ti32) 125 | :[frfi_even]"r"((int32_t)frfi[2*j]), 126 | [frfi_odd]"r"((int32_t)frfi[2*j +1]), 127 | [wri]"r"(wri), 128 | [cfftrnd]"r"(CFFTRND) 129 | ); 130 | 131 | #else 132 | tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) 133 | - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CFFTRND; 134 | 135 | ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) 136 | + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CFFTRND; 137 | #endif 138 | 139 | tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CFFTSFT); 140 | ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CFFTSFT); 141 | 142 | qr32 = ((int32_t)frfi[2 * i]) << CFFTSFT; 143 | qi32 = ((int32_t)frfi[2 * i + 1]) << CFFTSFT; 144 | 145 | frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 146 | (qr32 - tr32 + CFFTRND2), 1 + CFFTSFT); 147 | frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 148 | (qi32 - ti32 + CFFTRND2), 1 + CFFTSFT); 149 | frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 150 | (qr32 + tr32 + CFFTRND2), 1 + CFFTSFT); 151 | frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 152 | (qi32 + ti32 + CFFTRND2), 1 + CFFTSFT); 153 | } 154 | } 155 | 156 | --k; 157 | l = istep; 158 | } 159 | } 160 | return 0; 161 | } 162 | 163 | int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode) 164 | { 165 | int i, j, l, k, istep, n, m, scale, shift; 166 | int16_t wr, wi; 167 | int32_t tr32, ti32, qr32, qi32; 168 | int32_t tmp32, round2; 169 | 170 | /* The 1024-value is a constant given from the size of kSinTable1024[], 171 | * and should not be changed depending on the input parameter 'stages' 172 | */ 173 | n = 1 << stages; 174 | if (n > 1024) 175 | return -1; 176 | 177 | scale = 0; 178 | 179 | l = 1; 180 | k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change 181 | depending on the input parameter 'stages' */ 182 | 183 | while (l < n) 184 | { 185 | // variable scaling, depending upon data 186 | shift = 0; 187 | round2 = 8192; 188 | 189 | tmp32 = (int32_t)WebRtcSpl_MaxAbsValueW16(frfi, 2 * n); 190 | if (tmp32 > 13573) 191 | { 192 | shift++; 193 | scale++; 194 | round2 <<= 1; 195 | } 196 | if (tmp32 > 27146) 197 | { 198 | shift++; 199 | scale++; 200 | round2 <<= 1; 201 | } 202 | 203 | istep = l << 1; 204 | 205 | if (mode == 0) 206 | { 207 | // mode==0: Low-complexity and Low-accuracy mode 208 | for (m = 0; m < l; ++m) 209 | { 210 | j = m << k; 211 | 212 | /* The 256-value is a constant given as 1/4 of the size of 213 | * kSinTable1024[], and should not be changed depending on the input 214 | * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 215 | */ 216 | wr = kSinTable1024[j + 256]; 217 | wi = kSinTable1024[j]; 218 | 219 | for (i = m; i < n; i += istep) 220 | { 221 | j = i + l; 222 | 223 | tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j], 0) 224 | - WEBRTC_SPL_MUL_16_16_RSFT(wi, frfi[2 * j + 1], 0)), 15); 225 | 226 | ti32 = WEBRTC_SPL_RSHIFT_W32( 227 | (WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j + 1], 0) 228 | + WEBRTC_SPL_MUL_16_16_RSFT(wi,frfi[2*j],0)), 15); 229 | 230 | qr32 = (int32_t)frfi[2 * i]; 231 | qi32 = (int32_t)frfi[2 * i + 1]; 232 | frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, shift); 233 | frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, shift); 234 | frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, shift); 235 | frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, shift); 236 | } 237 | } 238 | } else 239 | { 240 | // mode==1: High-complexity and High-accuracy mode 241 | 242 | for (m = 0; m < l; ++m) 243 | { 244 | j = m << k; 245 | 246 | /* The 256-value is a constant given as 1/4 of the size of 247 | * kSinTable1024[], and should not be changed depending on the input 248 | * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 249 | */ 250 | wr = kSinTable1024[j + 256]; 251 | wi = kSinTable1024[j]; 252 | 253 | #ifdef WEBRTC_ARCH_ARM_V7 254 | int32_t wri = 0; 255 | int32_t frfi_r = 0; 256 | __asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) : 257 | "r"((int32_t)wr), "r"((int32_t)wi)); 258 | #endif 259 | 260 | for (i = m; i < n; i += istep) 261 | { 262 | j = i + l; 263 | 264 | #ifdef WEBRTC_ARCH_ARM_V7 265 | __asm __volatile( 266 | "pkhbt %[frfi_r], %[frfi_even], %[frfi_odd], lsl #16\n\t" 267 | "smlsd %[tr32], %[wri], %[frfi_r], %[cifftrnd]\n\t" 268 | "smladx %[ti32], %[wri], %[frfi_r], %[cifftrnd]\n\t" 269 | :[frfi_r]"+r"(frfi_r), 270 | [tr32]"=r"(tr32), 271 | [ti32]"=r"(ti32) 272 | :[frfi_even]"r"((int32_t)frfi[2*j]), 273 | [frfi_odd]"r"((int32_t)frfi[2*j +1]), 274 | [wri]"r"(wri), 275 | [cifftrnd]"r"(CIFFTRND) 276 | ); 277 | #else 278 | 279 | tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) 280 | - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CIFFTRND; 281 | 282 | ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) 283 | + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CIFFTRND; 284 | #endif 285 | tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CIFFTSFT); 286 | ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CIFFTSFT); 287 | 288 | qr32 = ((int32_t)frfi[2 * i]) << CIFFTSFT; 289 | qi32 = ((int32_t)frfi[2 * i + 1]) << CIFFTSFT; 290 | 291 | frfi[2 * j] = (int16_t)WEBRTC_SPL_RSHIFT_W32((qr32 - tr32+round2), 292 | shift+CIFFTSFT); 293 | frfi[2 * j + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 294 | (qi32 - ti32 + round2), shift + CIFFTSFT); 295 | frfi[2 * i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((qr32 + tr32 + round2), 296 | shift + CIFFTSFT); 297 | frfi[2 * i + 1] = (int16_t)WEBRTC_SPL_RSHIFT_W32( 298 | (qi32 + ti32 + round2), shift + CIFFTSFT); 299 | } 300 | } 301 | 302 | } 303 | --k; 304 | l = istep; 305 | } 306 | return scale; 307 | } 308 | -------------------------------------------------------------------------------- /src/complex_fft_tables.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | 12 | #ifndef WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_ 13 | #define WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_ 14 | 15 | #include "typedefs.h" 16 | 17 | static const int16_t kSinTable1024[] = { 18 | 0, 201, 402, 603, 804, 1005, 1206, 1406, 19 | 1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011, 20 | 3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608, 21 | 4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195, 22 | 6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766, 23 | 7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319, 24 | 9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849, 25 | 11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353, 26 | 12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827, 27 | 14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268, 28 | 15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672, 29 | 16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036, 30 | 18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357, 31 | 19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631, 32 | 20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855, 33 | 22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027, 34 | 23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143, 35 | 24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201, 36 | 25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198, 37 | 26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132, 38 | 27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001, 39 | 28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802, 40 | 28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534, 41 | 29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195, 42 | 30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783, 43 | 30851, 30918, 30984, 31049, 31113, 31175, 31236, 31297, 44 | 31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735, 45 | 31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097, 46 | 32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382, 47 | 32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588, 48 | 32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717, 49 | 32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766, 50 | 32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736, 51 | 32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628, 52 | 32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441, 53 | 32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176, 54 | 32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833, 55 | 31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413, 56 | 31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918, 57 | 30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349, 58 | 30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706, 59 | 29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992, 60 | 28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208, 61 | 28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355, 62 | 27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437, 63 | 26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456, 64 | 25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413, 65 | 24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311, 66 | 23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153, 67 | 22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942, 68 | 20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680, 69 | 19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371, 70 | 18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017, 71 | 16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623, 72 | 15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191, 73 | 14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724, 74 | 12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227, 75 | 11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703, 76 | 9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156, 77 | 7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589, 78 | 6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006, 79 | 4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411, 80 | 3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808, 81 | 1607, 1406, 1206, 1005, 804, 603, 402, 201, 82 | 0, -201, -402, -603, -804, -1005, -1206, -1406, 83 | -1607, -1808, -2009, -2209, -2410, -2610, -2811, -3011, 84 | -3211, -3411, -3611, -3811, -4011, -4210, -4409, -4608, 85 | -4807, -5006, -5205, -5403, -5601, -5799, -5997, -6195, 86 | -6392, -6589, -6786, -6982, -7179, -7375, -7571, -7766, 87 | -7961, -8156, -8351, -8545, -8739, -8932, -9126, -9319, 88 | -9511, -9703, -9895, -10087, -10278, -10469, -10659, -10849, 89 | -11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353, 90 | -12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827, 91 | -14009, -14191, -14372, -14552, -14732, -14911, -15090, -15268, 92 | -15446, -15623, -15799, -15975, -16150, -16325, -16499, -16672, 93 | -16845, -17017, -17189, -17360, -17530, -17699, -17868, -18036, 94 | -18204, -18371, -18537, -18702, -18867, -19031, -19194, -19357, 95 | -19519, -19680, -19840, -20000, -20159, -20317, -20474, -20631, 96 | -20787, -20942, -21096, -21249, -21402, -21554, -21705, -21855, 97 | -22004, -22153, -22301, -22448, -22594, -22739, -22883, -23027, 98 | -23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143, 99 | -24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201, 100 | -25329, -25456, -25582, -25707, -25831, -25954, -26077, -26198, 101 | -26318, -26437, -26556, -26673, -26789, -26905, -27019, -27132, 102 | -27244, -27355, -27466, -27575, -27683, -27790, -27896, -28001, 103 | -28105, -28208, -28309, -28410, -28510, -28608, -28706, -28802, 104 | -28897, -28992, -29085, -29177, -29268, -29358, -29446, -29534, 105 | -29621, -29706, -29790, -29873, -29955, -30036, -30116, -30195, 106 | -30272, -30349, -30424, -30498, -30571, -30643, -30713, -30783, 107 | -30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297, 108 | -31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735, 109 | -31785, -31833, -31880, -31926, -31970, -32014, -32056, -32097, 110 | -32137, -32176, -32213, -32249, -32284, -32318, -32350, -32382, 111 | -32412, -32441, -32468, -32495, -32520, -32544, -32567, -32588, 112 | -32609, -32628, -32646, -32662, -32678, -32692, -32705, -32717, 113 | -32727, -32736, -32744, -32751, -32757, -32761, -32764, -32766, 114 | -32767, -32766, -32764, -32761, -32757, -32751, -32744, -32736, 115 | -32727, -32717, -32705, -32692, -32678, -32662, -32646, -32628, 116 | -32609, -32588, -32567, -32544, -32520, -32495, -32468, -32441, 117 | -32412, -32382, -32350, -32318, -32284, -32249, -32213, -32176, 118 | -32137, -32097, -32056, -32014, -31970, -31926, -31880, -31833, 119 | -31785, -31735, -31684, -31633, -31580, -31525, -31470, -31413, 120 | -31356, -31297, -31236, -31175, -31113, -31049, -30984, -30918, 121 | -30851, -30783, -30713, -30643, -30571, -30498, -30424, -30349, 122 | -30272, -30195, -30116, -30036, -29955, -29873, -29790, -29706, 123 | -29621, -29534, -29446, -29358, -29268, -29177, -29085, -28992, 124 | -28897, -28802, -28706, -28608, -28510, -28410, -28309, -28208, 125 | -28105, -28001, -27896, -27790, -27683, -27575, -27466, -27355, 126 | -27244, -27132, -27019, -26905, -26789, -26673, -26556, -26437, 127 | -26318, -26198, -26077, -25954, -25831, -25707, -25582, -25456, 128 | -25329, -25201, -25072, -24942, -24811, -24679, -24546, -24413, 129 | -24278, -24143, -24006, -23869, -23731, -23592, -23452, -23311, 130 | -23169, -23027, -22883, -22739, -22594, -22448, -22301, -22153, 131 | -22004, -21855, -21705, -21554, -21402, -21249, -21096, -20942, 132 | -20787, -20631, -20474, -20317, -20159, -20000, -19840, -19680, 133 | -19519, -19357, -19194, -19031, -18867, -18702, -18537, -18371, 134 | -18204, -18036, -17868, -17699, -17530, -17360, -17189, -17017, 135 | -16845, -16672, -16499, -16325, -16150, -15975, -15799, -15623, 136 | -15446, -15268, -15090, -14911, -14732, -14552, -14372, -14191, 137 | -14009, -13827, -13645, -13462, -13278, -13094, -12909, -12724, 138 | -12539, -12353, -12166, -11980, -11792, -11604, -11416, -11227, 139 | -11038, -10849, -10659, -10469, -10278, -10087, -9895, -9703, 140 | -9511, -9319, -9126, -8932, -8739, -8545, -8351, -8156, 141 | -7961, -7766, -7571, -7375, -7179, -6982, -6786, -6589, 142 | -6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006, 143 | -4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411, 144 | -3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808, 145 | -1607, -1406, -1206, -1005, -804, -603, -402, -201 146 | }; 147 | 148 | #endif // WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_ 149 | -------------------------------------------------------------------------------- /src/cpu_features_wrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_FEATURES_WRAPPER_H_ 12 | #define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_FEATURES_WRAPPER_H_ 13 | 14 | #if defined(__cplusplus) || defined(c_plusplus) 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | // List of features in x86. 21 | typedef enum { 22 | kSSE2, 23 | kSSE3 24 | } CPUFeature; 25 | 26 | // List of features in ARM. 27 | enum { 28 | kCPUFeatureARMv7 = (1 << 0), 29 | kCPUFeatureVFPv3 = (1 << 1), 30 | kCPUFeatureNEON = (1 << 2), 31 | kCPUFeatureLDREXSTREX = (1 << 3) 32 | }; 33 | 34 | typedef int (*WebRtc_CPUInfo)(CPUFeature feature); 35 | 36 | // Returns true if the CPU supports the feature. 37 | extern WebRtc_CPUInfo WebRtc_GetCPUInfo; 38 | 39 | // No CPU feature is available => straight C path. 40 | extern WebRtc_CPUInfo WebRtc_GetCPUInfoNoASM; 41 | 42 | // Return the features in an ARM device. 43 | // It detects the features in the hardware platform, and returns supported 44 | // values in the above enum definition as a bitmask. 45 | extern uint64_t WebRtc_GetCPUFeaturesARM(void); 46 | 47 | #if defined(__cplusplus) || defined(c_plusplus) 48 | } // extern "C" 49 | #endif 50 | 51 | #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_FEATURES_WRAPPER_H_ 52 | -------------------------------------------------------------------------------- /src/cross_correlation.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "signal_processing_library.h" 12 | 13 | /* C version of WebRtcSpl_CrossCorrelation() for generic platforms. */ 14 | void WebRtcSpl_CrossCorrelationC(int32_t* cross_correlation, 15 | const int16_t* seq1, 16 | const int16_t* seq2, 17 | int16_t dim_seq, 18 | int16_t dim_cross_correlation, 19 | int16_t right_shifts, 20 | int16_t step_seq2) { 21 | int i = 0, j = 0; 22 | 23 | for (i = 0; i < dim_cross_correlation; i++) { 24 | *cross_correlation = 0; 25 | /* Unrolling doesn't seem to improve performance. */ 26 | for (j = 0; j < dim_seq; j++) { 27 | *cross_correlation += (seq1[j] * seq2[step_seq2 * i + j]) >> right_shifts; 28 | } 29 | cross_correlation++; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/delay_estimator.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "delay_estimator.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | // Number of right shifts for scaling is linearly depending on number of bits in 18 | // the far-end binary spectrum. 19 | static const int kShiftsAtZero = 13; // Right shifts at zero binary spectrum. 20 | static const int kShiftsLinearSlope = 3; 21 | 22 | static const int32_t kProbabilityOffset = 1024; // 2 in Q9. 23 | static const int32_t kProbabilityLowerLimit = 8704; // 17 in Q9. 24 | static const int32_t kProbabilityMinSpread = 2816; // 5.5 in Q9. 25 | 26 | // Counts and returns number of bits of a 32-bit word. 27 | static int BitCount(uint32_t u32) { 28 | uint32_t tmp = u32 - ((u32 >> 1) & 033333333333) - 29 | ((u32 >> 2) & 011111111111); 30 | tmp = ((tmp + (tmp >> 3)) & 030707070707); 31 | tmp = (tmp + (tmp >> 6)); 32 | tmp = (tmp + (tmp >> 12) + (tmp >> 24)) & 077; 33 | 34 | return ((int) tmp); 35 | } 36 | 37 | // Compares the |binary_vector| with all rows of the |binary_matrix| and counts 38 | // per row the number of times they have the same value. 39 | // 40 | // Inputs: 41 | // - binary_vector : binary "vector" stored in a long 42 | // - binary_matrix : binary "matrix" stored as a vector of long 43 | // - matrix_size : size of binary "matrix" 44 | // 45 | // Output: 46 | // - bit_counts : "Vector" stored as a long, containing for each 47 | // row the number of times the matrix row and the 48 | // input vector have the same value 49 | // 50 | static void BitCountComparison(uint32_t binary_vector, 51 | const uint32_t* binary_matrix, 52 | int matrix_size, 53 | int32_t* bit_counts) { 54 | int n = 0; 55 | 56 | // Compare |binary_vector| with all rows of the |binary_matrix| 57 | for (; n < matrix_size; n++) { 58 | bit_counts[n] = (int32_t) BitCount(binary_vector ^ binary_matrix[n]); 59 | } 60 | } 61 | 62 | void WebRtc_FreeBinaryDelayEstimatorFarend(BinaryDelayEstimatorFarend* self) { 63 | 64 | if (self == NULL) { 65 | return; 66 | } 67 | 68 | free(self->binary_far_history); 69 | self->binary_far_history = NULL; 70 | 71 | free(self->far_bit_counts); 72 | self->far_bit_counts = NULL; 73 | 74 | free(self); 75 | } 76 | 77 | BinaryDelayEstimatorFarend* WebRtc_CreateBinaryDelayEstimatorFarend( 78 | int history_size) { 79 | BinaryDelayEstimatorFarend* self = NULL; 80 | 81 | if (history_size > 1) { 82 | // Sanity conditions fulfilled. 83 | self = malloc(sizeof(BinaryDelayEstimatorFarend)); 84 | } 85 | if (self != NULL) { 86 | int malloc_fail = 0; 87 | 88 | self->history_size = history_size; 89 | 90 | // Allocate memory for history buffers. 91 | self->binary_far_history = malloc(history_size * sizeof(uint32_t)); 92 | malloc_fail |= (self->binary_far_history == NULL); 93 | 94 | self->far_bit_counts = malloc(history_size * sizeof(int)); 95 | malloc_fail |= (self->far_bit_counts == NULL); 96 | 97 | if (malloc_fail) { 98 | WebRtc_FreeBinaryDelayEstimatorFarend(self); 99 | self = NULL; 100 | } 101 | } 102 | 103 | return self; 104 | } 105 | 106 | void WebRtc_InitBinaryDelayEstimatorFarend(BinaryDelayEstimatorFarend* self) { 107 | assert(self != NULL); 108 | memset(self->binary_far_history, 0, sizeof(uint32_t) * self->history_size); 109 | memset(self->far_bit_counts, 0, sizeof(int) * self->history_size); 110 | } 111 | 112 | void WebRtc_AddBinaryFarSpectrum(BinaryDelayEstimatorFarend* handle, 113 | uint32_t binary_far_spectrum) { 114 | assert(handle != NULL); 115 | // Shift binary spectrum history and insert current |binary_far_spectrum|. 116 | memmove(&(handle->binary_far_history[1]), &(handle->binary_far_history[0]), 117 | (handle->history_size - 1) * sizeof(uint32_t)); 118 | handle->binary_far_history[0] = binary_far_spectrum; 119 | 120 | // Shift history of far-end binary spectrum bit counts and insert bit count 121 | // of current |binary_far_spectrum|. 122 | memmove(&(handle->far_bit_counts[1]), &(handle->far_bit_counts[0]), 123 | (handle->history_size - 1) * sizeof(int)); 124 | handle->far_bit_counts[0] = BitCount(binary_far_spectrum); 125 | } 126 | 127 | void WebRtc_FreeBinaryDelayEstimator(BinaryDelayEstimator* self) { 128 | 129 | if (self == NULL) { 130 | return; 131 | } 132 | 133 | free(self->mean_bit_counts); 134 | self->mean_bit_counts = NULL; 135 | 136 | free(self->bit_counts); 137 | self->bit_counts = NULL; 138 | 139 | free(self->binary_near_history); 140 | self->binary_near_history = NULL; 141 | 142 | // BinaryDelayEstimator does not have ownership of |farend|, hence we do not 143 | // free the memory here. That should be handled separately by the user. 144 | self->farend = NULL; 145 | 146 | free(self); 147 | } 148 | 149 | BinaryDelayEstimator* WebRtc_CreateBinaryDelayEstimator( 150 | BinaryDelayEstimatorFarend* farend, int lookahead) { 151 | BinaryDelayEstimator* self = NULL; 152 | 153 | if ((farend != NULL) && (lookahead >= 0)) { 154 | // Sanity conditions fulfilled. 155 | self = malloc(sizeof(BinaryDelayEstimator)); 156 | } 157 | 158 | if (self != NULL) { 159 | int malloc_fail = 0; 160 | 161 | self->farend = farend; 162 | self->near_history_size = lookahead + 1; 163 | 164 | // Allocate memory for spectrum buffers. 165 | self->mean_bit_counts = malloc(farend->history_size * sizeof(int32_t)); 166 | malloc_fail |= (self->mean_bit_counts == NULL); 167 | 168 | self->bit_counts = malloc(farend->history_size * sizeof(int32_t)); 169 | malloc_fail |= (self->bit_counts == NULL); 170 | 171 | // Allocate memory for history buffers. 172 | self->binary_near_history = malloc((lookahead + 1) * sizeof(uint32_t)); 173 | malloc_fail |= (self->binary_near_history == NULL); 174 | 175 | if (malloc_fail) { 176 | WebRtc_FreeBinaryDelayEstimator(self); 177 | self = NULL; 178 | } 179 | } 180 | 181 | return self; 182 | } 183 | 184 | void WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* self) { 185 | int i = 0; 186 | assert(self != NULL); 187 | 188 | memset(self->bit_counts, 0, sizeof(int32_t) * self->farend->history_size); 189 | memset(self->binary_near_history, 0, 190 | sizeof(uint32_t) * self->near_history_size); 191 | for (i = 0; i < self->farend->history_size; ++i) { 192 | self->mean_bit_counts[i] = (20 << 9); // 20 in Q9. 193 | } 194 | self->minimum_probability = (32 << 9); // 32 in Q9. 195 | self->last_delay_probability = (32 << 9); // 32 in Q9. 196 | 197 | // Default return value if we're unable to estimate. -1 is used for errors. 198 | self->last_delay = -2; 199 | } 200 | 201 | int WebRtc_ProcessBinarySpectrum(BinaryDelayEstimator* self, 202 | uint32_t binary_near_spectrum) { 203 | int i = 0; 204 | int candidate_delay = -1; 205 | 206 | int32_t value_best_candidate = 32 << 9; // 32 in Q9, (max |mean_bit_counts|). 207 | int32_t value_worst_candidate = 0; 208 | 209 | assert(self != NULL); 210 | if (self->near_history_size > 1) { 211 | // If we apply lookahead, shift near-end binary spectrum history. Insert 212 | // current |binary_near_spectrum| and pull out the delayed one. 213 | memmove(&(self->binary_near_history[1]), &(self->binary_near_history[0]), 214 | (self->near_history_size - 1) * sizeof(uint32_t)); 215 | self->binary_near_history[0] = binary_near_spectrum; 216 | binary_near_spectrum = 217 | self->binary_near_history[self->near_history_size - 1]; 218 | } 219 | 220 | // Compare with delayed spectra and store the |bit_counts| for each delay. 221 | BitCountComparison(binary_near_spectrum, self->farend->binary_far_history, 222 | self->farend->history_size, self->bit_counts); 223 | 224 | // Update |mean_bit_counts|, which is the smoothed version of |bit_counts|. 225 | for (i = 0; i < self->farend->history_size; i++) { 226 | // |bit_counts| is constrained to [0, 32], meaning we can smooth with a 227 | // factor up to 2^26. We use Q9. 228 | int32_t bit_count = (self->bit_counts[i] << 9); // Q9. 229 | 230 | // Update |mean_bit_counts| only when far-end signal has something to 231 | // contribute. If |far_bit_counts| is zero the far-end signal is weak and 232 | // we likely have a poor echo condition, hence don't update. 233 | if (self->farend->far_bit_counts[i] > 0) { 234 | // Make number of right shifts piecewise linear w.r.t. |far_bit_counts|. 235 | int shifts = kShiftsAtZero; 236 | shifts -= (kShiftsLinearSlope * self->farend->far_bit_counts[i]) >> 4; 237 | WebRtc_MeanEstimatorFix(bit_count, shifts, &(self->mean_bit_counts[i])); 238 | } 239 | } 240 | 241 | // Find |candidate_delay|, |value_best_candidate| and |value_worst_candidate| 242 | // of |mean_bit_counts|. 243 | for (i = 0; i < self->farend->history_size; i++) { 244 | if (self->mean_bit_counts[i] < value_best_candidate) { 245 | value_best_candidate = self->mean_bit_counts[i]; 246 | candidate_delay = i; 247 | } 248 | if (self->mean_bit_counts[i] > value_worst_candidate) { 249 | value_worst_candidate = self->mean_bit_counts[i]; 250 | } 251 | } 252 | 253 | // The |value_best_candidate| is a good indicator on the probability of 254 | // |candidate_delay| being an accurate delay (a small |value_best_candidate| 255 | // means a good binary match). In the following sections we make a decision 256 | // whether to update |last_delay| or not. 257 | // 1) If the difference bit counts between the best and the worst delay 258 | // candidates is too small we consider the situation to be unreliable and 259 | // don't update |last_delay|. 260 | // 2) If the situation is reliable we update |last_delay| if the value of the 261 | // best candidate delay has a value less than 262 | // i) an adaptive threshold |minimum_probability|, or 263 | // ii) this corresponding value |last_delay_probability|, but updated at 264 | // this time instant. 265 | 266 | // Update |minimum_probability|. 267 | if ((self->minimum_probability > kProbabilityLowerLimit) && 268 | (value_worst_candidate - value_best_candidate > kProbabilityMinSpread)) { 269 | // The "hard" threshold can't be lower than 17 (in Q9). 270 | // The valley in the curve also has to be distinct, i.e., the 271 | // difference between |value_worst_candidate| and |value_best_candidate| has 272 | // to be large enough. 273 | int32_t threshold = value_best_candidate + kProbabilityOffset; 274 | if (threshold < kProbabilityLowerLimit) { 275 | threshold = kProbabilityLowerLimit; 276 | } 277 | if (self->minimum_probability > threshold) { 278 | self->minimum_probability = threshold; 279 | } 280 | } 281 | // Update |last_delay_probability|. 282 | // We use a Markov type model, i.e., a slowly increasing level over time. 283 | self->last_delay_probability++; 284 | if (value_worst_candidate > value_best_candidate + kProbabilityOffset) { 285 | // Reliable delay value for usage. 286 | if (value_best_candidate < self->minimum_probability) { 287 | self->last_delay = candidate_delay; 288 | } 289 | if (value_best_candidate < self->last_delay_probability) { 290 | self->last_delay = candidate_delay; 291 | // Reset |last_delay_probability|. 292 | self->last_delay_probability = value_best_candidate; 293 | } 294 | } 295 | 296 | return self->last_delay; 297 | } 298 | 299 | int WebRtc_binary_last_delay(BinaryDelayEstimator* self) { 300 | assert(self != NULL); 301 | return self->last_delay; 302 | } 303 | 304 | int WebRtc_binary_last_delay_quality(BinaryDelayEstimator* self) { 305 | int delay_quality = 0; 306 | assert(self != NULL); 307 | // |last_delay_probability| is the opposite of quality and states how deep the 308 | // minimum of the cost function is. The value states how many non-matching 309 | // bits we have between the binary spectra for the corresponding delay 310 | // estimate. The range is thus from 0 to 32, since we use 32 bits in the 311 | // binary spectra. 312 | 313 | // Return the |delay_quality| = 1 - |last_delay_probability| / 32 (in Q14). 314 | delay_quality = (32 << 9) - self->last_delay_probability; 315 | if (delay_quality < 0) { 316 | delay_quality = 0; 317 | } 318 | return delay_quality; 319 | } 320 | 321 | void WebRtc_MeanEstimatorFix(int32_t new_value, 322 | int factor, 323 | int32_t* mean_value) { 324 | int32_t diff = new_value - *mean_value; 325 | 326 | // mean_new = mean_value + ((new_value - mean_value) >> factor); 327 | if (diff < 0) { 328 | diff = -((-diff) >> factor); 329 | } else { 330 | diff = (diff >> factor); 331 | } 332 | *mean_value += diff; 333 | } 334 | -------------------------------------------------------------------------------- /src/delay_estimator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // Performs delay estimation on binary converted spectra. 12 | // The return value is 0 - OK and -1 - Error, unless otherwise stated. 13 | 14 | #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_ 15 | #define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_ 16 | 17 | #include "typedefs.h" 18 | 19 | typedef struct { 20 | // Pointer to bit counts. 21 | int* far_bit_counts; 22 | // Binary history variables. 23 | uint32_t* binary_far_history; 24 | int history_size; 25 | } BinaryDelayEstimatorFarend; 26 | 27 | typedef struct { 28 | // Pointer to bit counts. 29 | int32_t* mean_bit_counts; 30 | // Array only used locally in ProcessBinarySpectrum() but whose size is 31 | // determined at run-time. 32 | int32_t* bit_counts; 33 | 34 | // Binary history variables. 35 | uint32_t* binary_near_history; 36 | int near_history_size; 37 | 38 | // Delay estimation variables. 39 | int32_t minimum_probability; 40 | int last_delay_probability; 41 | 42 | // Delay memory. 43 | int last_delay; 44 | 45 | // Far-end binary spectrum history buffer etc. 46 | BinaryDelayEstimatorFarend* farend; 47 | } BinaryDelayEstimator; 48 | 49 | // Releases the memory allocated by 50 | // WebRtc_CreateBinaryDelayEstimatorFarend(...). 51 | // Input: 52 | // - self : Pointer to the binary delay estimation far-end 53 | // instance which is the return value of 54 | // WebRtc_CreateBinaryDelayEstimatorFarend(). 55 | // 56 | void WebRtc_FreeBinaryDelayEstimatorFarend(BinaryDelayEstimatorFarend* self); 57 | 58 | // Allocates the memory needed by the far-end part of the binary delay 59 | // estimation. The memory needs to be initialized separately through 60 | // WebRtc_InitBinaryDelayEstimatorFarend(...). 61 | // 62 | // Inputs: 63 | // - history_size : Size of the far-end binary spectrum history. 64 | // 65 | // Return value: 66 | // - BinaryDelayEstimatorFarend* 67 | // : Created |handle|. If the memory can't be allocated 68 | // or if any of the input parameters are invalid NULL 69 | // is returned. 70 | // 71 | BinaryDelayEstimatorFarend* WebRtc_CreateBinaryDelayEstimatorFarend( 72 | int history_size); 73 | 74 | // Initializes the delay estimation far-end instance created with 75 | // WebRtc_CreateBinaryDelayEstimatorFarend(...). 76 | // 77 | // Input: 78 | // - self : Pointer to the delay estimation far-end instance. 79 | // 80 | // Output: 81 | // - self : Initialized far-end instance. 82 | // 83 | void WebRtc_InitBinaryDelayEstimatorFarend(BinaryDelayEstimatorFarend* self); 84 | 85 | // Adds the binary far-end spectrum to the internal far-end history buffer. This 86 | // spectrum is used as reference when calculating the delay using 87 | // WebRtc_ProcessBinarySpectrum(). 88 | // 89 | // Inputs: 90 | // - self : Pointer to the delay estimation far-end 91 | // instance. 92 | // - binary_far_spectrum : Far-end binary spectrum. 93 | // 94 | // Output: 95 | // - self : Updated far-end instance. 96 | // 97 | void WebRtc_AddBinaryFarSpectrum(BinaryDelayEstimatorFarend* self, 98 | uint32_t binary_far_spectrum); 99 | 100 | // Releases the memory allocated by WebRtc_CreateBinaryDelayEstimator(...). 101 | // 102 | // Note that BinaryDelayEstimator utilizes BinaryDelayEstimatorFarend, but does 103 | // not take ownership of it, hence the BinaryDelayEstimator has to be torn down 104 | // before the far-end. 105 | // 106 | // Input: 107 | // - self : Pointer to the binary delay estimation instance 108 | // which is the return value of 109 | // WebRtc_CreateBinaryDelayEstimator(). 110 | // 111 | void WebRtc_FreeBinaryDelayEstimator(BinaryDelayEstimator* self); 112 | 113 | // Allocates the memory needed by the binary delay estimation. The memory needs 114 | // to be initialized separately through WebRtc_InitBinaryDelayEstimator(...). 115 | // 116 | // Inputs: 117 | // - farend : Pointer to the far-end part of the Binary Delay 118 | // Estimator. This memory has to be created separately 119 | // prior to this call using 120 | // WebRtc_CreateBinaryDelayEstimatorFarend(). 121 | // 122 | // Note that BinaryDelayEstimator does not take 123 | // ownership of |farend|. 124 | // 125 | // - lookahead : Amount of non-causal lookahead to use. This can 126 | // detect cases in which a near-end signal occurs before 127 | // the corresponding far-end signal. It will delay the 128 | // estimate for the current block by an equal amount, 129 | // and the returned values will be offset by it. 130 | // 131 | // A value of zero is the typical no-lookahead case. 132 | // This also represents the minimum delay which can be 133 | // estimated. 134 | // 135 | // Note that the effective range of delay estimates is 136 | // [-|lookahead|,... ,|history_size|-|lookahead|) 137 | // where |history_size| was set upon creating the far-end 138 | // history buffer size. 139 | // 140 | // Return value: 141 | // - BinaryDelayEstimator* 142 | // : Created |handle|. If the memory can't be allocated 143 | // or if any of the input parameters are invalid NULL 144 | // is returned. 145 | // 146 | BinaryDelayEstimator* WebRtc_CreateBinaryDelayEstimator( 147 | BinaryDelayEstimatorFarend* farend, int lookahead); 148 | 149 | // Initializes the delay estimation instance created with 150 | // WebRtc_CreateBinaryDelayEstimator(...). 151 | // 152 | // Input: 153 | // - self : Pointer to the delay estimation instance. 154 | // 155 | // Output: 156 | // - self : Initialized instance. 157 | // 158 | void WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* self); 159 | 160 | // Estimates and returns the delay between the binary far-end and binary near- 161 | // end spectra. It is assumed the binary far-end spectrum has been added using 162 | // WebRtc_AddBinaryFarSpectrum() prior to this call. The value will be offset by 163 | // the lookahead (i.e. the lookahead should be subtracted from the returned 164 | // value). 165 | // 166 | // Inputs: 167 | // - self : Pointer to the delay estimation instance. 168 | // - binary_near_spectrum : Near-end binary spectrum of the current block. 169 | // 170 | // Output: 171 | // - self : Updated instance. 172 | // 173 | // Return value: 174 | // - delay : >= 0 - Calculated delay value. 175 | // -2 - Insufficient data for estimation. 176 | // 177 | int WebRtc_ProcessBinarySpectrum(BinaryDelayEstimator* self, 178 | uint32_t binary_near_spectrum); 179 | 180 | // Returns the last calculated delay updated by the function 181 | // WebRtc_ProcessBinarySpectrum(...). 182 | // 183 | // Input: 184 | // - self : Pointer to the delay estimation instance. 185 | // 186 | // Return value: 187 | // - delay : >= 0 - Last calculated delay value 188 | // -2 - Insufficient data for estimation. 189 | // 190 | int WebRtc_binary_last_delay(BinaryDelayEstimator* self); 191 | 192 | // Returns the estimation quality of the last calculated delay updated by the 193 | // function WebRtc_ProcessBinarySpectrum(...). The estimation quality is a value 194 | // in the interval [0, 1] in Q14. The higher the value, the better quality. 195 | // 196 | // Input: 197 | // - self : Pointer to the delay estimation instance. 198 | // 199 | // Return value: 200 | // - delay_quality : >= 0 - Estimation quality (in Q14) of last 201 | // calculated delay value. 202 | // -2 - Insufficient data for estimation. 203 | // 204 | int WebRtc_binary_last_delay_quality(BinaryDelayEstimator* self); 205 | 206 | // Updates the |mean_value| recursively with a step size of 2^-|factor|. This 207 | // function is used internally in the Binary Delay Estimator as well as the 208 | // Fixed point wrapper. 209 | // 210 | // Inputs: 211 | // - new_value : The new value the mean should be updated with. 212 | // - factor : The step size, in number of right shifts. 213 | // 214 | // Input/Output: 215 | // - mean_value : Pointer to the mean value. 216 | // 217 | void WebRtc_MeanEstimatorFix(int32_t new_value, 218 | int factor, 219 | int32_t* mean_value); 220 | 221 | 222 | #endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_ 223 | -------------------------------------------------------------------------------- /src/delay_estimator_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // Header file including the delay estimator handle used for testing. 12 | 13 | #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_ 14 | #define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_ 15 | 16 | #include "delay_estimator.h" 17 | #include "typedefs.h" 18 | 19 | typedef union { 20 | float float_; 21 | int32_t int32_; 22 | } SpectrumType; 23 | 24 | typedef struct { 25 | // Pointers to mean values of spectrum. 26 | SpectrumType* mean_far_spectrum; 27 | // |mean_far_spectrum| initialization indicator. 28 | int far_spectrum_initialized; 29 | 30 | int spectrum_size; 31 | 32 | // Far-end part of binary spectrum based delay estimation. 33 | BinaryDelayEstimatorFarend* binary_farend; 34 | } DelayEstimatorFarend; 35 | 36 | typedef struct { 37 | // Pointers to mean values of spectrum. 38 | SpectrumType* mean_near_spectrum; 39 | // |mean_near_spectrum| initialization indicator. 40 | int near_spectrum_initialized; 41 | 42 | int spectrum_size; 43 | 44 | // Binary spectrum based delay estimator 45 | BinaryDelayEstimator* binary_handle; 46 | } DelayEstimator; 47 | 48 | #endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_ 49 | -------------------------------------------------------------------------------- /src/delay_estimator_wrapper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "delay_estimator_wrapper.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "delay_estimator.h" 18 | #include "delay_estimator_internal.h" 19 | #include "compile_assert.h" 20 | 21 | // Only bit |kBandFirst| through bit |kBandLast| are processed and 22 | // |kBandFirst| - |kBandLast| must be < 32. 23 | enum { kBandFirst = 12 }; 24 | enum { kBandLast = 43 }; 25 | 26 | static __inline uint32_t SetBit(uint32_t in, int pos) { 27 | uint32_t mask = (1 << pos); 28 | uint32_t out = (in | mask); 29 | 30 | return out; 31 | } 32 | 33 | // Calculates the mean recursively. Same version as WebRtc_MeanEstimatorFix(), 34 | // but for float. 35 | // 36 | // Inputs: 37 | // - new_value : New additional value. 38 | // - scale : Scale for smoothing (should be less than 1.0). 39 | // 40 | // Input/Output: 41 | // - mean_value : Pointer to the mean value for updating. 42 | // 43 | static void MeanEstimatorFloat(float new_value, 44 | float scale, 45 | float* mean_value) { 46 | assert(scale < 1.0f); 47 | *mean_value += (new_value - *mean_value) * scale; 48 | } 49 | 50 | // Computes the binary spectrum by comparing the input |spectrum| with a 51 | // |threshold_spectrum|. Float and fixed point versions. 52 | // 53 | // Inputs: 54 | // - spectrum : Spectrum of which the binary spectrum should be 55 | // calculated. 56 | // - threshold_spectrum : Threshold spectrum with which the input 57 | // spectrum is compared. 58 | // Return: 59 | // - out : Binary spectrum. 60 | // 61 | static uint32_t BinarySpectrumFix(uint16_t* spectrum, 62 | SpectrumType* threshold_spectrum, 63 | int q_domain, 64 | int* threshold_initialized) { 65 | int i = kBandFirst; 66 | uint32_t out = 0; 67 | 68 | assert(q_domain < 16); 69 | 70 | if (!(*threshold_initialized)) { 71 | // Set the |threshold_spectrum| to half the input |spectrum| as starting 72 | // value. This speeds up the convergence. 73 | for (i = kBandFirst; i <= kBandLast; i++) { 74 | if (spectrum[i] > 0) { 75 | // Convert input spectrum from Q(|q_domain|) to Q15. 76 | int32_t spectrum_q15 = ((int32_t) spectrum[i]) << (15 - q_domain); 77 | threshold_spectrum[i].int32_ = (spectrum_q15 >> 1); 78 | *threshold_initialized = 1; 79 | } 80 | } 81 | } 82 | for (i = kBandFirst; i <= kBandLast; i++) { 83 | // Convert input spectrum from Q(|q_domain|) to Q15. 84 | int32_t spectrum_q15 = ((int32_t) spectrum[i]) << (15 - q_domain); 85 | // Update the |threshold_spectrum|. 86 | WebRtc_MeanEstimatorFix(spectrum_q15, 6, &(threshold_spectrum[i].int32_)); 87 | // Convert |spectrum| at current frequency bin to a binary value. 88 | if (spectrum_q15 > threshold_spectrum[i].int32_) { 89 | out = SetBit(out, i - kBandFirst); 90 | } 91 | } 92 | 93 | return out; 94 | } 95 | 96 | static uint32_t BinarySpectrumFloat(float* spectrum, 97 | SpectrumType* threshold_spectrum, 98 | int* threshold_initialized) { 99 | int i = kBandFirst; 100 | uint32_t out = 0; 101 | const float kScale = 1 / 64.0; 102 | 103 | if (!(*threshold_initialized)) { 104 | // Set the |threshold_spectrum| to half the input |spectrum| as starting 105 | // value. This speeds up the convergence. 106 | for (i = kBandFirst; i <= kBandLast; i++) { 107 | if (spectrum[i] > 0.0f) { 108 | threshold_spectrum[i].float_ = (spectrum[i] / 2); 109 | *threshold_initialized = 1; 110 | } 111 | } 112 | } 113 | 114 | for (i = kBandFirst; i <= kBandLast; i++) { 115 | // Update the |threshold_spectrum|. 116 | MeanEstimatorFloat(spectrum[i], kScale, &(threshold_spectrum[i].float_)); 117 | // Convert |spectrum| at current frequency bin to a binary value. 118 | if (spectrum[i] > threshold_spectrum[i].float_) { 119 | out = SetBit(out, i - kBandFirst); 120 | } 121 | } 122 | 123 | return out; 124 | } 125 | 126 | void WebRtc_FreeDelayEstimatorFarend(void* handle) { 127 | DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; 128 | 129 | if (handle == NULL) { 130 | return; 131 | } 132 | 133 | free(self->mean_far_spectrum); 134 | self->mean_far_spectrum = NULL; 135 | 136 | WebRtc_FreeBinaryDelayEstimatorFarend(self->binary_farend); 137 | self->binary_farend = NULL; 138 | 139 | free(self); 140 | } 141 | 142 | void* WebRtc_CreateDelayEstimatorFarend(int spectrum_size, int history_size) { 143 | DelayEstimatorFarend* self = NULL; 144 | 145 | // Check if the sub band used in the delay estimation is small enough to fit 146 | // the binary spectra in a uint32_t. 147 | COMPILE_ASSERT(kBandLast - kBandFirst < 32); 148 | 149 | if (spectrum_size >= kBandLast) { 150 | self = malloc(sizeof(DelayEstimator)); 151 | } 152 | 153 | if (self != NULL) { 154 | int memory_fail = 0; 155 | 156 | // Allocate memory for the binary far-end spectrum handling. 157 | self->binary_farend = WebRtc_CreateBinaryDelayEstimatorFarend(history_size); 158 | memory_fail |= (self->binary_farend == NULL); 159 | 160 | // Allocate memory for spectrum buffers. 161 | self->mean_far_spectrum = malloc(spectrum_size * sizeof(SpectrumType)); 162 | memory_fail |= (self->mean_far_spectrum == NULL); 163 | 164 | self->spectrum_size = spectrum_size; 165 | 166 | if (memory_fail) { 167 | WebRtc_FreeDelayEstimatorFarend(self); 168 | self = NULL; 169 | } 170 | } 171 | 172 | return self; 173 | } 174 | 175 | int WebRtc_InitDelayEstimatorFarend(void* handle) { 176 | DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; 177 | 178 | if (self == NULL) { 179 | return -1; 180 | } 181 | 182 | // Initialize far-end part of binary delay estimator. 183 | WebRtc_InitBinaryDelayEstimatorFarend(self->binary_farend); 184 | 185 | // Set averaged far and near end spectra to zero. 186 | memset(self->mean_far_spectrum, 0, 187 | sizeof(SpectrumType) * self->spectrum_size); 188 | // Reset initialization indicators. 189 | self->far_spectrum_initialized = 0; 190 | 191 | return 0; 192 | } 193 | 194 | int WebRtc_AddFarSpectrumFix(void* handle, uint16_t* far_spectrum, 195 | int spectrum_size, int far_q) { 196 | DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; 197 | uint32_t binary_spectrum = 0; 198 | 199 | if (self == NULL) { 200 | return -1; 201 | } 202 | if (far_spectrum == NULL) { 203 | // Empty far end spectrum. 204 | return -1; 205 | } 206 | if (spectrum_size != self->spectrum_size) { 207 | // Data sizes don't match. 208 | return -1; 209 | } 210 | if (far_q > 15) { 211 | // If |far_q| is larger than 15 we cannot guarantee no wrap around. 212 | return -1; 213 | } 214 | 215 | // Get binary spectrum. 216 | binary_spectrum = BinarySpectrumFix(far_spectrum, self->mean_far_spectrum, 217 | far_q, &(self->far_spectrum_initialized)); 218 | WebRtc_AddBinaryFarSpectrum(self->binary_farend, binary_spectrum); 219 | 220 | return 0; 221 | } 222 | 223 | int WebRtc_AddFarSpectrumFloat(void* handle, float* far_spectrum, 224 | int spectrum_size) { 225 | DelayEstimatorFarend* self = (DelayEstimatorFarend*) handle; 226 | uint32_t binary_spectrum = 0; 227 | 228 | if (self == NULL) { 229 | return -1; 230 | } 231 | if (far_spectrum == NULL) { 232 | // Empty far end spectrum. 233 | return -1; 234 | } 235 | if (spectrum_size != self->spectrum_size) { 236 | // Data sizes don't match. 237 | return -1; 238 | } 239 | 240 | // Get binary spectrum. 241 | binary_spectrum = BinarySpectrumFloat(far_spectrum, self->mean_far_spectrum, 242 | &(self->far_spectrum_initialized)); 243 | WebRtc_AddBinaryFarSpectrum(self->binary_farend, binary_spectrum); 244 | 245 | return 0; 246 | } 247 | 248 | void WebRtc_FreeDelayEstimator(void* handle) { 249 | DelayEstimator* self = (DelayEstimator*) handle; 250 | 251 | if (handle == NULL) { 252 | return; 253 | } 254 | 255 | free(self->mean_near_spectrum); 256 | self->mean_near_spectrum = NULL; 257 | 258 | WebRtc_FreeBinaryDelayEstimator(self->binary_handle); 259 | self->binary_handle = NULL; 260 | 261 | free(self); 262 | } 263 | 264 | void* WebRtc_CreateDelayEstimator(void* farend_handle, int lookahead) { 265 | DelayEstimator* self = NULL; 266 | DelayEstimatorFarend* farend = (DelayEstimatorFarend*) farend_handle; 267 | 268 | if (farend_handle != NULL) { 269 | self = malloc(sizeof(DelayEstimator)); 270 | } 271 | 272 | if (self != NULL) { 273 | int memory_fail = 0; 274 | 275 | // Allocate memory for the farend spectrum handling. 276 | self->binary_handle = 277 | WebRtc_CreateBinaryDelayEstimator(farend->binary_farend, lookahead); 278 | memory_fail |= (self->binary_handle == NULL); 279 | 280 | // Allocate memory for spectrum buffers. 281 | self->mean_near_spectrum = malloc(farend->spectrum_size * 282 | sizeof(SpectrumType)); 283 | memory_fail |= (self->mean_near_spectrum == NULL); 284 | 285 | self->spectrum_size = farend->spectrum_size; 286 | 287 | if (memory_fail) { 288 | WebRtc_FreeDelayEstimator(self); 289 | self = NULL; 290 | } 291 | } 292 | 293 | return self; 294 | } 295 | 296 | int WebRtc_InitDelayEstimator(void* handle) { 297 | DelayEstimator* self = (DelayEstimator*) handle; 298 | 299 | if (self == NULL) { 300 | return -1; 301 | } 302 | 303 | // Initialize binary delay estimator. 304 | WebRtc_InitBinaryDelayEstimator(self->binary_handle); 305 | 306 | // Set averaged far and near end spectra to zero. 307 | memset(self->mean_near_spectrum, 0, 308 | sizeof(SpectrumType) * self->spectrum_size); 309 | // Reset initialization indicators. 310 | self->near_spectrum_initialized = 0; 311 | 312 | return 0; 313 | } 314 | 315 | int WebRtc_DelayEstimatorProcessFix(void* handle, 316 | uint16_t* near_spectrum, 317 | int spectrum_size, 318 | int near_q) { 319 | DelayEstimator* self = (DelayEstimator*) handle; 320 | uint32_t binary_spectrum = 0; 321 | 322 | if (self == NULL) { 323 | return -1; 324 | } 325 | if (near_spectrum == NULL) { 326 | // Empty near end spectrum. 327 | return -1; 328 | } 329 | if (spectrum_size != self->spectrum_size) { 330 | // Data sizes don't match. 331 | return -1; 332 | } 333 | if (near_q > 15) { 334 | // If |near_q| is larger than 15 we cannot guarantee no wrap around. 335 | return -1; 336 | } 337 | 338 | // Get binary spectra. 339 | binary_spectrum = BinarySpectrumFix(near_spectrum, 340 | self->mean_near_spectrum, 341 | near_q, 342 | &(self->near_spectrum_initialized)); 343 | 344 | return WebRtc_ProcessBinarySpectrum(self->binary_handle, binary_spectrum); 345 | } 346 | 347 | int WebRtc_DelayEstimatorProcessFloat(void* handle, 348 | float* near_spectrum, 349 | int spectrum_size) { 350 | DelayEstimator* self = (DelayEstimator*) handle; 351 | uint32_t binary_spectrum = 0; 352 | 353 | if (self == NULL) { 354 | return -1; 355 | } 356 | if (near_spectrum == NULL) { 357 | // Empty near end spectrum. 358 | return -1; 359 | } 360 | if (spectrum_size != self->spectrum_size) { 361 | // Data sizes don't match. 362 | return -1; 363 | } 364 | 365 | // Get binary spectrum. 366 | binary_spectrum = BinarySpectrumFloat(near_spectrum, self->mean_near_spectrum, 367 | &(self->near_spectrum_initialized)); 368 | 369 | return WebRtc_ProcessBinarySpectrum(self->binary_handle, binary_spectrum); 370 | } 371 | 372 | int WebRtc_last_delay(void* handle) { 373 | DelayEstimator* self = (DelayEstimator*) handle; 374 | 375 | if (self == NULL) { 376 | return -1; 377 | } 378 | 379 | return WebRtc_binary_last_delay(self->binary_handle); 380 | } 381 | 382 | int WebRtc_last_delay_quality(void* handle) { 383 | DelayEstimator* self = (DelayEstimator*) handle; 384 | 385 | if (self == NULL) { 386 | return -1; 387 | } 388 | 389 | return WebRtc_binary_last_delay_quality(self->binary_handle); 390 | } 391 | -------------------------------------------------------------------------------- /src/delay_estimator_wrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // Performs delay estimation on block by block basis. 12 | // The return value is 0 - OK and -1 - Error, unless otherwise stated. 13 | 14 | #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_WRAPPER_H_ 15 | #define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_WRAPPER_H_ 16 | 17 | #include "typedefs.h" 18 | 19 | // Releases the memory allocated by WebRtc_CreateDelayEstimatorFarend(...) 20 | // Input: 21 | // - handle : Pointer to the delay estimation far-end instance. 22 | // 23 | void WebRtc_FreeDelayEstimatorFarend(void* handle); 24 | 25 | // Allocates the memory needed by the far-end part of the delay estimation. The 26 | // memory needs to be initialized separately through 27 | // WebRtc_InitDelayEstimatorFarend(...). 28 | // 29 | // Inputs: 30 | // - spectrum_size : Size of the spectrum used both in far-end and 31 | // near-end. Used to allocate memory for spectrum 32 | // specific buffers. 33 | // - history_size : The far-end history buffer size. Note that the maximum 34 | // delay which can be estimated is controlled together 35 | // with |lookahead| through 36 | // WebRtc_CreateDelayEstimator(). 37 | // 38 | // Return value: 39 | // - void* : Created |handle|. If the memory can't be allocated or 40 | // if any of the input parameters are invalid NULL is 41 | // returned. 42 | // 43 | void* WebRtc_CreateDelayEstimatorFarend(int spectrum_size, int history_size); 44 | 45 | // Initializes the far-end part of the delay estimation instance returned by 46 | // WebRtc_CreateDelayEstimatorFarend(...) 47 | // Input: 48 | // - handle : Pointer to the delay estimation far-end instance. 49 | // 50 | // Output: 51 | // - handle : Initialized instance. 52 | // 53 | int WebRtc_InitDelayEstimatorFarend(void* handle); 54 | 55 | // Adds the far-end spectrum to the far-end history buffer. This spectrum is 56 | // used as reference when calculating the delay using 57 | // WebRtc_ProcessSpectrum(). 58 | // 59 | // Inputs: 60 | // - handle : Pointer to the delay estimation far-end instance. 61 | // - far_spectrum : Far-end spectrum. 62 | // - spectrum_size : The size of the data arrays (same for both far- and 63 | // near-end). 64 | // - far_q : The Q-domain of the far-end data. 65 | // 66 | // Output: 67 | // - handle : Updated far-end instance. 68 | // 69 | int WebRtc_AddFarSpectrumFix(void* handle, uint16_t* far_spectrum, 70 | int spectrum_size, int far_q); 71 | 72 | // See WebRtc_AddFarSpectrumFix() for description. 73 | int WebRtc_AddFarSpectrumFloat(void* handle, float* far_spectrum, 74 | int spectrum_size); 75 | 76 | // Releases the memory allocated by WebRtc_CreateDelayEstimator(...) 77 | // Input: 78 | // - handle : Pointer to the delay estimation instance. 79 | // 80 | void WebRtc_FreeDelayEstimator(void* handle); 81 | 82 | // Allocates the memory needed by the delay estimation. The memory needs to be 83 | // initialized separately through WebRtc_InitDelayEstimator(...). 84 | // 85 | // Inputs: 86 | // - farend_handle : Pointer to the far-end part of the delay estimation 87 | // instance created prior to this call using 88 | // WebRtc_CreateDelayEstimatorFarend(). 89 | // 90 | // Note that WebRtc_CreateDelayEstimator does not take 91 | // ownership of |farend_handle|, which has to be torn 92 | // down properly after this instance. 93 | // 94 | // - lookahead : Amount of non-causal lookahead to use. This can 95 | // detect cases in which a near-end signal occurs before 96 | // the corresponding far-end signal. It will delay the 97 | // estimate for the current block by an equal amount, 98 | // and the returned values will be offset by it. 99 | // 100 | // A value of zero is the typical no-lookahead case. 101 | // This also represents the minimum delay which can be 102 | // estimated. 103 | // 104 | // Note that the effective range of delay estimates is 105 | // [-|lookahead|,... ,|history_size|-|lookahead|) 106 | // where |history_size| was set upon creating the far-end 107 | // history buffer size. 108 | // 109 | // Return value: 110 | // - void* : Created |handle|. If the memory can't be allocated or 111 | // if any of the input parameters are invalid NULL is 112 | // returned. 113 | // 114 | void* WebRtc_CreateDelayEstimator(void* farend_handle, int lookahead); 115 | 116 | // Initializes the delay estimation instance returned by 117 | // WebRtc_CreateDelayEstimator(...) 118 | // Input: 119 | // - handle : Pointer to the delay estimation instance. 120 | // 121 | // Output: 122 | // - handle : Initialized instance. 123 | // 124 | int WebRtc_InitDelayEstimator(void* handle); 125 | 126 | // Estimates and returns the delay between the far-end and near-end blocks. The 127 | // value will be offset by the lookahead (i.e. the lookahead should be 128 | // subtracted from the returned value). 129 | // Inputs: 130 | // - handle : Pointer to the delay estimation instance. 131 | // - near_spectrum : Pointer to the near-end spectrum data of the current 132 | // block. 133 | // - spectrum_size : The size of the data arrays (same for both far- and 134 | // near-end). 135 | // - near_q : The Q-domain of the near-end data. 136 | // 137 | // Output: 138 | // - handle : Updated instance. 139 | // 140 | // Return value: 141 | // - delay : >= 0 - Calculated delay value. 142 | // -1 - Error. 143 | // -2 - Insufficient data for estimation. 144 | // 145 | int WebRtc_DelayEstimatorProcessFix(void* handle, 146 | uint16_t* near_spectrum, 147 | int spectrum_size, 148 | int near_q); 149 | 150 | // See WebRtc_DelayEstimatorProcessFix() for description. 151 | int WebRtc_DelayEstimatorProcessFloat(void* handle, 152 | float* near_spectrum, 153 | int spectrum_size); 154 | 155 | // Returns the last calculated delay updated by the function 156 | // WebRtc_DelayEstimatorProcess(...). 157 | // 158 | // Input: 159 | // - handle : Pointer to the delay estimation instance. 160 | // 161 | // Return value: 162 | // - delay : >= 0 - Last calculated delay value. 163 | // -1 - Error. 164 | // -2 - Insufficient data for estimation. 165 | // 166 | int WebRtc_last_delay(void* handle); 167 | 168 | // Returns the estimation quality/probability of the last calculated delay 169 | // updated by the function WebRtc_DelayEstimatorProcess(...). The estimation 170 | // quality is a value in the interval [0, 1] in Q9. The higher the value, the 171 | // better quality. 172 | // 173 | // Input: 174 | // - handle : Pointer to the delay estimation instance. 175 | // 176 | // Return value: 177 | // - delay_quality : >= 0 - Estimation quality (in Q9) of last calculated 178 | // delay value. 179 | // -1 - Error. 180 | // -2 - Insufficient data for estimation. 181 | // 182 | int WebRtc_last_delay_quality(void* handle); 183 | 184 | #endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_WRAPPER_H_ 185 | -------------------------------------------------------------------------------- /src/division_operations.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | 12 | /* 13 | * This file contains implementations of the divisions 14 | * WebRtcSpl_DivU32U16() 15 | * WebRtcSpl_DivW32W16() 16 | * WebRtcSpl_DivW32W16ResW16() 17 | * WebRtcSpl_DivResultInQ31() 18 | * WebRtcSpl_DivW32HiLow() 19 | * 20 | * The description header can be found in signal_processing_library.h 21 | * 22 | */ 23 | 24 | #include "signal_processing_library.h" 25 | 26 | uint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den) 27 | { 28 | // Guard against division with 0 29 | if (den != 0) 30 | { 31 | return (uint32_t)(num / den); 32 | } else 33 | { 34 | return (uint32_t)0xFFFFFFFF; 35 | } 36 | } 37 | 38 | int32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den) 39 | { 40 | // Guard against division with 0 41 | if (den != 0) 42 | { 43 | return (int32_t)(num / den); 44 | } else 45 | { 46 | return (int32_t)0x7FFFFFFF; 47 | } 48 | } 49 | 50 | int16_t WebRtcSpl_DivW32W16ResW16(int32_t num, int16_t den) 51 | { 52 | // Guard against division with 0 53 | if (den != 0) 54 | { 55 | return (int16_t)(num / den); 56 | } else 57 | { 58 | return (int16_t)0x7FFF; 59 | } 60 | } 61 | 62 | int32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den) 63 | { 64 | int32_t L_num = num; 65 | int32_t L_den = den; 66 | int32_t div = 0; 67 | int k = 31; 68 | int change_sign = 0; 69 | 70 | if (num == 0) 71 | return 0; 72 | 73 | if (num < 0) 74 | { 75 | change_sign++; 76 | L_num = -num; 77 | } 78 | if (den < 0) 79 | { 80 | change_sign++; 81 | L_den = -den; 82 | } 83 | while (k--) 84 | { 85 | div <<= 1; 86 | L_num <<= 1; 87 | if (L_num >= L_den) 88 | { 89 | L_num -= L_den; 90 | div++; 91 | } 92 | } 93 | if (change_sign == 1) 94 | { 95 | div = -div; 96 | } 97 | return div; 98 | } 99 | 100 | int32_t WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low) 101 | { 102 | int16_t approx, tmp_hi, tmp_low, num_hi, num_low; 103 | int32_t tmpW32; 104 | 105 | approx = (int16_t)WebRtcSpl_DivW32W16((int32_t)0x1FFFFFFF, den_hi); 106 | // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30) 107 | 108 | // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30) 109 | tmpW32 = (WEBRTC_SPL_MUL_16_16(den_hi, approx) << 1) 110 | + ((WEBRTC_SPL_MUL_16_16(den_low, approx) >> 15) << 1); 111 | // tmpW32 = den * approx 112 | 113 | tmpW32 = (int32_t)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx)) 114 | 115 | // Store tmpW32 in hi and low format 116 | tmp_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16); 117 | tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((tmpW32 118 | - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1); 119 | 120 | // tmpW32 = 1/den in Q29 121 | tmpW32 = ((WEBRTC_SPL_MUL_16_16(tmp_hi, approx) + (WEBRTC_SPL_MUL_16_16(tmp_low, approx) 122 | >> 15)) << 1); 123 | 124 | // 1/den in hi and low format 125 | tmp_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16); 126 | tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((tmpW32 127 | - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1); 128 | 129 | // Store num in hi and low format 130 | num_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(num, 16); 131 | num_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((num 132 | - WEBRTC_SPL_LSHIFT_W32((int32_t)num_hi, 16)), 1); 133 | 134 | // num * (1/den) by 32 bit multiplication (result in Q28) 135 | 136 | tmpW32 = (WEBRTC_SPL_MUL_16_16(num_hi, tmp_hi) + (WEBRTC_SPL_MUL_16_16(num_hi, tmp_low) 137 | >> 15) + (WEBRTC_SPL_MUL_16_16(num_low, tmp_hi) >> 15)); 138 | 139 | // Put result in Q31 (convert from Q28) 140 | tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3); 141 | 142 | return tmpW32; 143 | } 144 | -------------------------------------------------------------------------------- /src/downsample_fast.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "signal_processing_library.h" 12 | 13 | // TODO(Bjornv): Change the function parameter order to WebRTC code style. 14 | // C version of WebRtcSpl_DownsampleFast() for generic platforms. 15 | int WebRtcSpl_DownsampleFastC(const int16_t* data_in, 16 | int data_in_length, 17 | int16_t* data_out, 18 | int data_out_length, 19 | const int16_t* __restrict coefficients, 20 | int coefficients_length, 21 | int factor, 22 | int delay) { 23 | int i = 0; 24 | int j = 0; 25 | int32_t out_s32 = 0; 26 | int endpos = delay + factor * (data_out_length - 1) + 1; 27 | 28 | // Return error if any of the running conditions doesn't meet. 29 | if (data_out_length <= 0 || coefficients_length <= 0 30 | || data_in_length < endpos) { 31 | return -1; 32 | } 33 | 34 | for (i = delay; i < endpos; i += factor) { 35 | out_s32 = 2048; // Round value, 0.5 in Q12. 36 | 37 | for (j = 0; j < coefficients_length; j++) { 38 | out_s32 += coefficients[j] * data_in[i - j]; // Q12. 39 | } 40 | 41 | out_s32 >>= 12; // Q0. 42 | 43 | // Saturate and store the output. 44 | *data_out++ = WebRtcSpl_SatW32ToW16(out_s32); 45 | } 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /src/echo_control_mobile.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "echo_control_mobile.h" 12 | 13 | #ifdef AEC_DEBUG 14 | #include 15 | #endif 16 | #include 17 | 18 | #include "signal_processing_library.h" 19 | #include "aecm_core.h" 20 | #include "ring_buffer.h" 21 | 22 | #define BUF_SIZE_FRAMES 50 // buffer size (frames) 23 | // Maximum length of resampled signal. Must be an integer multiple of frames 24 | // (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN 25 | // The factor of 2 handles wb, and the + 1 is as a safety margin 26 | #define MAX_RESAMP_LEN (5 * FRAME_LEN) 27 | 28 | static const size_t kBufSizeSamp = BUF_SIZE_FRAMES * FRAME_LEN; // buffer size (samples) 29 | static const int kSampMsNb = 8; // samples per ms in nb 30 | // Target suppression levels for nlp modes 31 | // log{0.001, 0.00001, 0.00000001} 32 | static const int kInitCheck = 42; 33 | 34 | typedef struct 35 | { 36 | int sampFreq; 37 | int scSampFreq; 38 | short bufSizeStart; 39 | int knownDelay; 40 | 41 | // Stores the last frame added to the farend buffer 42 | short farendOld[2][FRAME_LEN]; 43 | short initFlag; // indicates if AEC has been initialized 44 | 45 | // Variables used for averaging far end buffer size 46 | short counter; 47 | short sum; 48 | short firstVal; 49 | short checkBufSizeCtr; 50 | 51 | // Variables used for delay shifts 52 | short msInSndCardBuf; 53 | short filtDelay; 54 | int timeForDelayChange; 55 | int ECstartup; 56 | int checkBuffSize; 57 | int delayChange; 58 | short lastDelayDiff; 59 | 60 | int16_t echoMode; 61 | 62 | #ifdef AEC_DEBUG 63 | FILE *bufFile; 64 | FILE *delayFile; 65 | FILE *preCompFile; 66 | FILE *postCompFile; 67 | #endif // AEC_DEBUG 68 | // Structures 69 | RingBuffer *farendBuf; 70 | 71 | int lastError; 72 | 73 | AecmCore_t *aecmCore; 74 | } aecmob_t; 75 | 76 | // Estimates delay to set the position of the farend buffer read pointer 77 | // (controlled by knownDelay) 78 | static int WebRtcAecm_EstBufDelay(aecmob_t *aecmInst, short msInSndCardBuf); 79 | 80 | // Stuffs the farend buffer if the estimated delay is too large 81 | static int WebRtcAecm_DelayComp(aecmob_t *aecmInst); 82 | 83 | int32_t WebRtcAecm_Create(void **aecmInst) 84 | { 85 | aecmob_t *aecm; 86 | if (aecmInst == NULL) 87 | { 88 | return -1; 89 | } 90 | 91 | aecm = malloc(sizeof(aecmob_t)); 92 | *aecmInst = aecm; 93 | if (aecm == NULL) 94 | { 95 | return -1; 96 | } 97 | 98 | WebRtcSpl_Init(); 99 | 100 | if (WebRtcAecm_CreateCore(&aecm->aecmCore) == -1) 101 | { 102 | WebRtcAecm_Free(aecm); 103 | aecm = NULL; 104 | return -1; 105 | } 106 | 107 | aecm->farendBuf = WebRtc_CreateBuffer(kBufSizeSamp, 108 | sizeof(int16_t)); 109 | if (!aecm->farendBuf) 110 | { 111 | WebRtcAecm_Free(aecm); 112 | aecm = NULL; 113 | return -1; 114 | } 115 | 116 | aecm->initFlag = 0; 117 | aecm->lastError = 0; 118 | 119 | #ifdef AEC_DEBUG 120 | aecm->aecmCore->farFile = fopen("aecFar.pcm","wb"); 121 | aecm->aecmCore->nearFile = fopen("aecNear.pcm","wb"); 122 | aecm->aecmCore->outFile = fopen("aecOut.pcm","wb"); 123 | //aecm->aecmCore->outLpFile = fopen("aecOutLp.pcm","wb"); 124 | 125 | aecm->bufFile = fopen("aecBuf.dat", "wb"); 126 | aecm->delayFile = fopen("aecDelay.dat", "wb"); 127 | aecm->preCompFile = fopen("preComp.pcm", "wb"); 128 | aecm->postCompFile = fopen("postComp.pcm", "wb"); 129 | #endif // AEC_DEBUG 130 | return 0; 131 | } 132 | 133 | int32_t WebRtcAecm_Free(void *aecmInst) 134 | { 135 | aecmob_t *aecm = aecmInst; 136 | 137 | if (aecm == NULL) 138 | { 139 | return -1; 140 | } 141 | 142 | #ifdef AEC_DEBUG 143 | fclose(aecm->aecmCore->farFile); 144 | fclose(aecm->aecmCore->nearFile); 145 | fclose(aecm->aecmCore->outFile); 146 | //fclose(aecm->aecmCore->outLpFile); 147 | 148 | fclose(aecm->bufFile); 149 | fclose(aecm->delayFile); 150 | fclose(aecm->preCompFile); 151 | fclose(aecm->postCompFile); 152 | #endif // AEC_DEBUG 153 | WebRtcAecm_FreeCore(aecm->aecmCore); 154 | WebRtc_FreeBuffer(aecm->farendBuf); 155 | free(aecm); 156 | 157 | return 0; 158 | } 159 | 160 | int32_t WebRtcAecm_Init(void *aecmInst, int32_t sampFreq) 161 | { 162 | aecmob_t *aecm = aecmInst; 163 | AecmConfig aecConfig; 164 | 165 | if (aecm == NULL) 166 | { 167 | return -1; 168 | } 169 | 170 | if (sampFreq != 8000 && sampFreq != 16000) 171 | { 172 | aecm->lastError = AECM_BAD_PARAMETER_ERROR; 173 | return -1; 174 | } 175 | aecm->sampFreq = sampFreq; 176 | 177 | // Initialize AECM core 178 | if (WebRtcAecm_InitCore(aecm->aecmCore, aecm->sampFreq) == -1) 179 | { 180 | aecm->lastError = AECM_UNSPECIFIED_ERROR; 181 | return -1; 182 | } 183 | 184 | // Initialize farend buffer 185 | if (WebRtc_InitBuffer(aecm->farendBuf) == -1) 186 | { 187 | aecm->lastError = AECM_UNSPECIFIED_ERROR; 188 | return -1; 189 | } 190 | 191 | aecm->initFlag = kInitCheck; // indicates that initialization has been done 192 | 193 | aecm->delayChange = 1; 194 | 195 | aecm->sum = 0; 196 | aecm->counter = 0; 197 | aecm->checkBuffSize = 1; 198 | aecm->firstVal = 0; 199 | 200 | aecm->ECstartup = 1; 201 | aecm->bufSizeStart = 0; 202 | aecm->checkBufSizeCtr = 0; 203 | aecm->filtDelay = 0; 204 | aecm->timeForDelayChange = 0; 205 | aecm->knownDelay = 0; 206 | aecm->lastDelayDiff = 0; 207 | 208 | memset(&aecm->farendOld[0][0], 0, 160); 209 | 210 | // Default settings. 211 | aecConfig.cngMode = AecmTrue; 212 | aecConfig.echoMode = 3; 213 | 214 | if (WebRtcAecm_set_config(aecm, aecConfig) == -1) 215 | { 216 | aecm->lastError = AECM_UNSPECIFIED_ERROR; 217 | return -1; 218 | } 219 | 220 | return 0; 221 | } 222 | 223 | int32_t WebRtcAecm_BufferFarend(void *aecmInst, const int16_t *farend, 224 | int16_t nrOfSamples) 225 | { 226 | aecmob_t *aecm = aecmInst; 227 | int32_t retVal = 0; 228 | 229 | if (aecm == NULL) 230 | { 231 | return -1; 232 | } 233 | 234 | if (farend == NULL) 235 | { 236 | aecm->lastError = AECM_NULL_POINTER_ERROR; 237 | return -1; 238 | } 239 | 240 | if (aecm->initFlag != kInitCheck) 241 | { 242 | aecm->lastError = AECM_UNINITIALIZED_ERROR; 243 | return -1; 244 | } 245 | 246 | if (nrOfSamples != 80 && nrOfSamples != 160) 247 | { 248 | aecm->lastError = AECM_BAD_PARAMETER_ERROR; 249 | return -1; 250 | } 251 | 252 | // TODO: Is this really a good idea? 253 | if (!aecm->ECstartup) 254 | { 255 | WebRtcAecm_DelayComp(aecm); 256 | } 257 | 258 | WebRtc_WriteBuffer(aecm->farendBuf, farend, (size_t) nrOfSamples); 259 | 260 | return retVal; 261 | } 262 | 263 | int32_t WebRtcAecm_Process(void *aecmInst, const int16_t *nearendNoisy, 264 | const int16_t *nearendClean, int16_t *out, 265 | int16_t nrOfSamples, int16_t msInSndCardBuf) 266 | { 267 | aecmob_t *aecm = aecmInst; 268 | int32_t retVal = 0; 269 | short i; 270 | short nmbrOfFilledBuffers; 271 | short nBlocks10ms; 272 | short nFrames; 273 | #ifdef AEC_DEBUG 274 | short msInAECBuf; 275 | #endif 276 | 277 | if (aecm == NULL) 278 | { 279 | return -1; 280 | } 281 | 282 | if (nearendNoisy == NULL) 283 | { 284 | aecm->lastError = AECM_NULL_POINTER_ERROR; 285 | return -1; 286 | } 287 | 288 | if (out == NULL) 289 | { 290 | aecm->lastError = AECM_NULL_POINTER_ERROR; 291 | return -1; 292 | } 293 | 294 | if (aecm->initFlag != kInitCheck) 295 | { 296 | aecm->lastError = AECM_UNINITIALIZED_ERROR; 297 | return -1; 298 | } 299 | 300 | if (nrOfSamples != 80 && nrOfSamples != 160) 301 | { 302 | aecm->lastError = AECM_BAD_PARAMETER_ERROR; 303 | return -1; 304 | } 305 | 306 | if (msInSndCardBuf < 0) 307 | { 308 | msInSndCardBuf = 0; 309 | aecm->lastError = AECM_BAD_PARAMETER_WARNING; 310 | retVal = -1; 311 | } else if (msInSndCardBuf > 500) 312 | { 313 | msInSndCardBuf = 500; 314 | aecm->lastError = AECM_BAD_PARAMETER_WARNING; 315 | retVal = -1; 316 | } 317 | msInSndCardBuf += 10; 318 | aecm->msInSndCardBuf = msInSndCardBuf; 319 | 320 | nFrames = nrOfSamples / FRAME_LEN; 321 | nBlocks10ms = nFrames / aecm->aecmCore->mult; 322 | 323 | if (aecm->ECstartup) 324 | { 325 | if (nearendClean == NULL) 326 | { 327 | if (out != nearendNoisy) 328 | { 329 | memcpy(out, nearendNoisy, sizeof(short) * nrOfSamples); 330 | } 331 | } else if (out != nearendClean) 332 | { 333 | memcpy(out, nearendClean, sizeof(short) * nrOfSamples); 334 | } 335 | 336 | nmbrOfFilledBuffers = 337 | (short) WebRtc_available_read(aecm->farendBuf) / FRAME_LEN; 338 | // The AECM is in the start up mode 339 | // AECM is disabled until the soundcard buffer and farend buffers are OK 340 | 341 | // Mechanism to ensure that the soundcard buffer is reasonably stable. 342 | if (aecm->checkBuffSize) 343 | { 344 | aecm->checkBufSizeCtr++; 345 | // Before we fill up the far end buffer we require the amount of data on the 346 | // sound card to be stable (+/-8 ms) compared to the first value. This 347 | // comparison is made during the following 4 consecutive frames. If it seems 348 | // to be stable then we start to fill up the far end buffer. 349 | 350 | if (aecm->counter == 0) 351 | { 352 | aecm->firstVal = aecm->msInSndCardBuf; 353 | aecm->sum = 0; 354 | } 355 | 356 | if (abs(aecm->firstVal - aecm->msInSndCardBuf) 357 | < WEBRTC_SPL_MAX(0.2 * aecm->msInSndCardBuf, kSampMsNb)) 358 | { 359 | aecm->sum += aecm->msInSndCardBuf; 360 | aecm->counter++; 361 | } else 362 | { 363 | aecm->counter = 0; 364 | } 365 | 366 | if (aecm->counter * nBlocks10ms >= 6) 367 | { 368 | // The farend buffer size is determined in blocks of 80 samples 369 | // Use 75% of the average value of the soundcard buffer 370 | aecm->bufSizeStart 371 | = WEBRTC_SPL_MIN((3 * aecm->sum 372 | * aecm->aecmCore->mult) / (aecm->counter * 40), BUF_SIZE_FRAMES); 373 | // buffersize has now been determined 374 | aecm->checkBuffSize = 0; 375 | } 376 | 377 | if (aecm->checkBufSizeCtr * nBlocks10ms > 50) 378 | { 379 | // for really bad sound cards, don't disable echocanceller for more than 0.5 sec 380 | aecm->bufSizeStart = WEBRTC_SPL_MIN((3 * aecm->msInSndCardBuf 381 | * aecm->aecmCore->mult) / 40, BUF_SIZE_FRAMES); 382 | aecm->checkBuffSize = 0; 383 | } 384 | } 385 | 386 | // if checkBuffSize changed in the if-statement above 387 | if (!aecm->checkBuffSize) 388 | { 389 | // soundcard buffer is now reasonably stable 390 | // When the far end buffer is filled with approximately the same amount of 391 | // data as the amount on the sound card we end the start up phase and start 392 | // to cancel echoes. 393 | 394 | if (nmbrOfFilledBuffers == aecm->bufSizeStart) 395 | { 396 | aecm->ECstartup = 0; // Enable the AECM 397 | } else if (nmbrOfFilledBuffers > aecm->bufSizeStart) 398 | { 399 | WebRtc_MoveReadPtr(aecm->farendBuf, 400 | (int) WebRtc_available_read(aecm->farendBuf) 401 | - (int) aecm->bufSizeStart * FRAME_LEN); 402 | aecm->ECstartup = 0; 403 | } 404 | } 405 | 406 | } else 407 | { 408 | // AECM is enabled 409 | 410 | // Note only 1 block supported for nb and 2 blocks for wb 411 | for (i = 0; i < nFrames; i++) 412 | { 413 | int16_t farend[FRAME_LEN]; 414 | const int16_t* farend_ptr = NULL; 415 | 416 | nmbrOfFilledBuffers = 417 | (short) WebRtc_available_read(aecm->farendBuf) / FRAME_LEN; 418 | 419 | // Check that there is data in the far end buffer 420 | if (nmbrOfFilledBuffers > 0) 421 | { 422 | // Get the next 80 samples from the farend buffer 423 | WebRtc_ReadBuffer(aecm->farendBuf, (void**) &farend_ptr, farend, 424 | FRAME_LEN); 425 | 426 | // Always store the last frame for use when we run out of data 427 | memcpy(&(aecm->farendOld[i][0]), farend_ptr, 428 | FRAME_LEN * sizeof(short)); 429 | } else 430 | { 431 | // We have no data so we use the last played frame 432 | memcpy(farend, &(aecm->farendOld[i][0]), FRAME_LEN * sizeof(short)); 433 | farend_ptr = farend; 434 | } 435 | 436 | // Call buffer delay estimator when all data is extracted, 437 | // i,e. i = 0 for NB and i = 1 for WB 438 | if ((i == 0 && aecm->sampFreq == 8000) || (i == 1 && aecm->sampFreq == 16000)) 439 | { 440 | WebRtcAecm_EstBufDelay(aecm, aecm->msInSndCardBuf); 441 | } 442 | 443 | // Call the AECM 444 | /*WebRtcAecm_ProcessFrame(aecm->aecmCore, farend, &nearend[FRAME_LEN * i], 445 | &out[FRAME_LEN * i], aecm->knownDelay);*/ 446 | if (nearendClean == NULL) 447 | { 448 | if (WebRtcAecm_ProcessFrame(aecm->aecmCore, 449 | farend_ptr, 450 | &nearendNoisy[FRAME_LEN * i], 451 | NULL, 452 | &out[FRAME_LEN * i]) == -1) 453 | { 454 | return -1; 455 | } 456 | } else 457 | { 458 | if (WebRtcAecm_ProcessFrame(aecm->aecmCore, 459 | farend_ptr, 460 | &nearendNoisy[FRAME_LEN * i], 461 | &nearendClean[FRAME_LEN * i], 462 | &out[FRAME_LEN * i]) == -1) 463 | { 464 | return -1; 465 | } 466 | } 467 | } 468 | } 469 | 470 | #ifdef AEC_DEBUG 471 | msInAECBuf = (short) WebRtc_available_read(aecm->farendBuf) / 472 | (kSampMsNb * aecm->aecmCore->mult); 473 | fwrite(&msInAECBuf, 2, 1, aecm->bufFile); 474 | fwrite(&(aecm->knownDelay), sizeof(aecm->knownDelay), 1, aecm->delayFile); 475 | #endif 476 | 477 | return retVal; 478 | } 479 | 480 | int32_t WebRtcAecm_set_config(void *aecmInst, AecmConfig config) 481 | { 482 | aecmob_t *aecm = aecmInst; 483 | 484 | if (aecm == NULL) 485 | { 486 | return -1; 487 | } 488 | 489 | if (aecm->initFlag != kInitCheck) 490 | { 491 | aecm->lastError = AECM_UNINITIALIZED_ERROR; 492 | return -1; 493 | } 494 | 495 | if (config.cngMode != AecmFalse && config.cngMode != AecmTrue) 496 | { 497 | aecm->lastError = AECM_BAD_PARAMETER_ERROR; 498 | return -1; 499 | } 500 | aecm->aecmCore->cngMode = config.cngMode; 501 | 502 | if (config.echoMode < 0 || config.echoMode > 4) 503 | { 504 | aecm->lastError = AECM_BAD_PARAMETER_ERROR; 505 | return -1; 506 | } 507 | aecm->echoMode = config.echoMode; 508 | 509 | if (aecm->echoMode == 0) 510 | { 511 | aecm->aecmCore->supGain = SUPGAIN_DEFAULT >> 3; 512 | aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT >> 3; 513 | aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A >> 3; 514 | aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D >> 3; 515 | aecm->aecmCore->supGainErrParamDiffAB = (SUPGAIN_ERROR_PARAM_A >> 3) 516 | - (SUPGAIN_ERROR_PARAM_B >> 3); 517 | aecm->aecmCore->supGainErrParamDiffBD = (SUPGAIN_ERROR_PARAM_B >> 3) 518 | - (SUPGAIN_ERROR_PARAM_D >> 3); 519 | } else if (aecm->echoMode == 1) 520 | { 521 | aecm->aecmCore->supGain = SUPGAIN_DEFAULT >> 2; 522 | aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT >> 2; 523 | aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A >> 2; 524 | aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D >> 2; 525 | aecm->aecmCore->supGainErrParamDiffAB = (SUPGAIN_ERROR_PARAM_A >> 2) 526 | - (SUPGAIN_ERROR_PARAM_B >> 2); 527 | aecm->aecmCore->supGainErrParamDiffBD = (SUPGAIN_ERROR_PARAM_B >> 2) 528 | - (SUPGAIN_ERROR_PARAM_D >> 2); 529 | } else if (aecm->echoMode == 2) 530 | { 531 | aecm->aecmCore->supGain = SUPGAIN_DEFAULT >> 1; 532 | aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT >> 1; 533 | aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A >> 1; 534 | aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D >> 1; 535 | aecm->aecmCore->supGainErrParamDiffAB = (SUPGAIN_ERROR_PARAM_A >> 1) 536 | - (SUPGAIN_ERROR_PARAM_B >> 1); 537 | aecm->aecmCore->supGainErrParamDiffBD = (SUPGAIN_ERROR_PARAM_B >> 1) 538 | - (SUPGAIN_ERROR_PARAM_D >> 1); 539 | } else if (aecm->echoMode == 3) 540 | { 541 | aecm->aecmCore->supGain = SUPGAIN_DEFAULT; 542 | aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT; 543 | aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A; 544 | aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D; 545 | aecm->aecmCore->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B; 546 | aecm->aecmCore->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D; 547 | } else if (aecm->echoMode == 4) 548 | { 549 | aecm->aecmCore->supGain = SUPGAIN_DEFAULT << 1; 550 | aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT << 1; 551 | aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A << 1; 552 | aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D << 1; 553 | aecm->aecmCore->supGainErrParamDiffAB = (SUPGAIN_ERROR_PARAM_A << 1) 554 | - (SUPGAIN_ERROR_PARAM_B << 1); 555 | aecm->aecmCore->supGainErrParamDiffBD = (SUPGAIN_ERROR_PARAM_B << 1) 556 | - (SUPGAIN_ERROR_PARAM_D << 1); 557 | } 558 | 559 | return 0; 560 | } 561 | 562 | int32_t WebRtcAecm_get_config(void *aecmInst, AecmConfig *config) 563 | { 564 | aecmob_t *aecm = aecmInst; 565 | 566 | if (aecm == NULL) 567 | { 568 | return -1; 569 | } 570 | 571 | if (config == NULL) 572 | { 573 | aecm->lastError = AECM_NULL_POINTER_ERROR; 574 | return -1; 575 | } 576 | 577 | if (aecm->initFlag != kInitCheck) 578 | { 579 | aecm->lastError = AECM_UNINITIALIZED_ERROR; 580 | return -1; 581 | } 582 | 583 | config->cngMode = aecm->aecmCore->cngMode; 584 | config->echoMode = aecm->echoMode; 585 | 586 | return 0; 587 | } 588 | 589 | int32_t WebRtcAecm_InitEchoPath(void* aecmInst, 590 | const void* echo_path, 591 | size_t size_bytes) 592 | { 593 | aecmob_t *aecm = aecmInst; 594 | const int16_t* echo_path_ptr = echo_path; 595 | 596 | if (aecmInst == NULL) { 597 | return -1; 598 | } 599 | if (echo_path == NULL) { 600 | aecm->lastError = AECM_NULL_POINTER_ERROR; 601 | return -1; 602 | } 603 | if (size_bytes != WebRtcAecm_echo_path_size_bytes()) 604 | { 605 | // Input channel size does not match the size of AECM 606 | aecm->lastError = AECM_BAD_PARAMETER_ERROR; 607 | return -1; 608 | } 609 | if (aecm->initFlag != kInitCheck) 610 | { 611 | aecm->lastError = AECM_UNINITIALIZED_ERROR; 612 | return -1; 613 | } 614 | 615 | WebRtcAecm_InitEchoPathCore(aecm->aecmCore, echo_path_ptr); 616 | 617 | return 0; 618 | } 619 | 620 | int32_t WebRtcAecm_GetEchoPath(void* aecmInst, 621 | void* echo_path, 622 | size_t size_bytes) 623 | { 624 | aecmob_t *aecm = aecmInst; 625 | int16_t* echo_path_ptr = echo_path; 626 | 627 | if (aecmInst == NULL) { 628 | return -1; 629 | } 630 | if (echo_path == NULL) { 631 | aecm->lastError = AECM_NULL_POINTER_ERROR; 632 | return -1; 633 | } 634 | if (size_bytes != WebRtcAecm_echo_path_size_bytes()) 635 | { 636 | // Input channel size does not match the size of AECM 637 | aecm->lastError = AECM_BAD_PARAMETER_ERROR; 638 | return -1; 639 | } 640 | if (aecm->initFlag != kInitCheck) 641 | { 642 | aecm->lastError = AECM_UNINITIALIZED_ERROR; 643 | return -1; 644 | } 645 | 646 | memcpy(echo_path_ptr, aecm->aecmCore->channelStored, size_bytes); 647 | return 0; 648 | } 649 | 650 | size_t WebRtcAecm_echo_path_size_bytes() 651 | { 652 | return (PART_LEN1 * sizeof(int16_t)); 653 | } 654 | 655 | int32_t WebRtcAecm_get_error_code(void *aecmInst) 656 | { 657 | aecmob_t *aecm = aecmInst; 658 | 659 | if (aecm == NULL) 660 | { 661 | return -1; 662 | } 663 | 664 | return aecm->lastError; 665 | } 666 | 667 | static int WebRtcAecm_EstBufDelay(aecmob_t *aecm, short msInSndCardBuf) 668 | { 669 | short delayNew, nSampSndCard; 670 | short nSampFar = (short) WebRtc_available_read(aecm->farendBuf); 671 | short diff; 672 | 673 | nSampSndCard = msInSndCardBuf * kSampMsNb * aecm->aecmCore->mult; 674 | 675 | delayNew = nSampSndCard - nSampFar; 676 | 677 | if (delayNew < FRAME_LEN) 678 | { 679 | WebRtc_MoveReadPtr(aecm->farendBuf, FRAME_LEN); 680 | delayNew += FRAME_LEN; 681 | } 682 | 683 | aecm->filtDelay = WEBRTC_SPL_MAX(0, (8 * aecm->filtDelay + 2 * delayNew) / 10); 684 | 685 | diff = aecm->filtDelay - aecm->knownDelay; 686 | if (diff > 224) 687 | { 688 | if (aecm->lastDelayDiff < 96) 689 | { 690 | aecm->timeForDelayChange = 0; 691 | } else 692 | { 693 | aecm->timeForDelayChange++; 694 | } 695 | } else if (diff < 96 && aecm->knownDelay > 0) 696 | { 697 | if (aecm->lastDelayDiff > 224) 698 | { 699 | aecm->timeForDelayChange = 0; 700 | } else 701 | { 702 | aecm->timeForDelayChange++; 703 | } 704 | } else 705 | { 706 | aecm->timeForDelayChange = 0; 707 | } 708 | aecm->lastDelayDiff = diff; 709 | 710 | if (aecm->timeForDelayChange > 25) 711 | { 712 | aecm->knownDelay = WEBRTC_SPL_MAX((int)aecm->filtDelay - 160, 0); 713 | } 714 | return 0; 715 | } 716 | 717 | static int WebRtcAecm_DelayComp(aecmob_t *aecm) 718 | { 719 | int nSampFar = (int) WebRtc_available_read(aecm->farendBuf); 720 | int nSampSndCard, delayNew, nSampAdd; 721 | const int maxStuffSamp = 10 * FRAME_LEN; 722 | 723 | nSampSndCard = aecm->msInSndCardBuf * kSampMsNb * aecm->aecmCore->mult; 724 | delayNew = nSampSndCard - nSampFar; 725 | 726 | if (delayNew > FAR_BUF_LEN - FRAME_LEN * aecm->aecmCore->mult) 727 | { 728 | // The difference of the buffer sizes is larger than the maximum 729 | // allowed known delay. Compensate by stuffing the buffer. 730 | nSampAdd = (int)(WEBRTC_SPL_MAX(((nSampSndCard >> 1) - nSampFar), 731 | FRAME_LEN)); 732 | nSampAdd = WEBRTC_SPL_MIN(nSampAdd, maxStuffSamp); 733 | 734 | WebRtc_MoveReadPtr(aecm->farendBuf, -nSampAdd); 735 | aecm->delayChange = 1; // the delay needs to be updated 736 | } 737 | 738 | return 0; 739 | } 740 | -------------------------------------------------------------------------------- /src/echo_control_mobile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_ 12 | #define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_ 13 | 14 | #include 15 | 16 | #include "typedefs.h" 17 | 18 | enum { 19 | AecmFalse = 0, 20 | AecmTrue 21 | }; 22 | 23 | // Errors 24 | #define AECM_UNSPECIFIED_ERROR 12000 25 | #define AECM_UNSUPPORTED_FUNCTION_ERROR 12001 26 | #define AECM_UNINITIALIZED_ERROR 12002 27 | #define AECM_NULL_POINTER_ERROR 12003 28 | #define AECM_BAD_PARAMETER_ERROR 12004 29 | 30 | // Warnings 31 | #define AECM_BAD_PARAMETER_WARNING 12100 32 | 33 | typedef struct { 34 | int16_t cngMode; // AECM_FALSE, AECM_TRUE (default) 35 | int16_t echoMode; // 0, 1, 2, 3 (default), 4 36 | } AecmConfig; 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | /* 43 | * Allocates the memory needed by the AECM. The memory needs to be 44 | * initialized separately using the WebRtcAecm_Init() function. 45 | * 46 | * Inputs Description 47 | * ------------------------------------------------------------------- 48 | * void **aecmInst Pointer to the AECM instance to be 49 | * created and initialized 50 | * 51 | * Outputs Description 52 | * ------------------------------------------------------------------- 53 | * int32_t return 0: OK 54 | * -1: error 55 | */ 56 | int32_t WebRtcAecm_Create(void **aecmInst); 57 | 58 | /* 59 | * This function releases the memory allocated by WebRtcAecm_Create() 60 | * 61 | * Inputs Description 62 | * ------------------------------------------------------------------- 63 | * void *aecmInst Pointer to the AECM instance 64 | * 65 | * Outputs Description 66 | * ------------------------------------------------------------------- 67 | * int32_t return 0: OK 68 | * -1: error 69 | */ 70 | int32_t WebRtcAecm_Free(void *aecmInst); 71 | 72 | /* 73 | * Initializes an AECM instance. 74 | * 75 | * Inputs Description 76 | * ------------------------------------------------------------------- 77 | * void *aecmInst Pointer to the AECM instance 78 | * int32_t sampFreq Sampling frequency of data 79 | * 80 | * Outputs Description 81 | * ------------------------------------------------------------------- 82 | * int32_t return 0: OK 83 | * -1: error 84 | */ 85 | int32_t WebRtcAecm_Init(void* aecmInst, int32_t sampFreq); 86 | 87 | /* 88 | * Inserts an 80 or 160 sample block of data into the farend buffer. 89 | * 90 | * Inputs Description 91 | * ------------------------------------------------------------------- 92 | * void *aecmInst Pointer to the AECM instance 93 | * int16_t *farend In buffer containing one frame of 94 | * farend signal 95 | * int16_t nrOfSamples Number of samples in farend buffer 96 | * 97 | * Outputs Description 98 | * ------------------------------------------------------------------- 99 | * int32_t return 0: OK 100 | * -1: error 101 | */ 102 | int32_t WebRtcAecm_BufferFarend(void* aecmInst, 103 | const int16_t* farend, 104 | int16_t nrOfSamples); 105 | 106 | /* 107 | * Runs the AECM on an 80 or 160 sample blocks of data. 108 | * 109 | * Inputs Description 110 | * ------------------------------------------------------------------- 111 | * void *aecmInst Pointer to the AECM instance 112 | * int16_t *nearendNoisy In buffer containing one frame of 113 | * reference nearend+echo signal. If 114 | * noise reduction is active, provide 115 | * the noisy signal here. 116 | * int16_t *nearendClean In buffer containing one frame of 117 | * nearend+echo signal. If noise 118 | * reduction is active, provide the 119 | * clean signal here. Otherwise pass a 120 | * NULL pointer. 121 | * int16_t nrOfSamples Number of samples in nearend buffer 122 | * int16_t msInSndCardBuf Delay estimate for sound card and 123 | * system buffers 124 | * 125 | * Outputs Description 126 | * ------------------------------------------------------------------- 127 | * int16_t *out Out buffer, one frame of processed nearend 128 | * int32_t return 0: OK 129 | * -1: error 130 | */ 131 | int32_t WebRtcAecm_Process(void* aecmInst, 132 | const int16_t* nearendNoisy, 133 | const int16_t* nearendClean, 134 | int16_t* out, 135 | int16_t nrOfSamples, 136 | int16_t msInSndCardBuf); 137 | 138 | /* 139 | * This function enables the user to set certain parameters on-the-fly 140 | * 141 | * Inputs Description 142 | * ------------------------------------------------------------------- 143 | * void *aecmInst Pointer to the AECM instance 144 | * AecmConfig config Config instance that contains all 145 | * properties to be set 146 | * 147 | * Outputs Description 148 | * ------------------------------------------------------------------- 149 | * int32_t return 0: OK 150 | * -1: error 151 | */ 152 | int32_t WebRtcAecm_set_config(void* aecmInst, AecmConfig config); 153 | 154 | /* 155 | * This function enables the user to set certain parameters on-the-fly 156 | * 157 | * Inputs Description 158 | * ------------------------------------------------------------------- 159 | * void *aecmInst Pointer to the AECM instance 160 | * 161 | * Outputs Description 162 | * ------------------------------------------------------------------- 163 | * AecmConfig *config Pointer to the config instance that 164 | * all properties will be written to 165 | * int32_t return 0: OK 166 | * -1: error 167 | */ 168 | int32_t WebRtcAecm_get_config(void *aecmInst, AecmConfig *config); 169 | 170 | /* 171 | * This function enables the user to set the echo path on-the-fly. 172 | * 173 | * Inputs Description 174 | * ------------------------------------------------------------------- 175 | * void* aecmInst Pointer to the AECM instance 176 | * void* echo_path Pointer to the echo path to be set 177 | * size_t size_bytes Size in bytes of the echo path 178 | * 179 | * Outputs Description 180 | * ------------------------------------------------------------------- 181 | * int32_t return 0: OK 182 | * -1: error 183 | */ 184 | int32_t WebRtcAecm_InitEchoPath(void* aecmInst, 185 | const void* echo_path, 186 | size_t size_bytes); 187 | 188 | /* 189 | * This function enables the user to get the currently used echo path 190 | * on-the-fly 191 | * 192 | * Inputs Description 193 | * ------------------------------------------------------------------- 194 | * void* aecmInst Pointer to the AECM instance 195 | * void* echo_path Pointer to echo path 196 | * size_t size_bytes Size in bytes of the echo path 197 | * 198 | * Outputs Description 199 | * ------------------------------------------------------------------- 200 | * int32_t return 0: OK 201 | * -1: error 202 | */ 203 | int32_t WebRtcAecm_GetEchoPath(void* aecmInst, 204 | void* echo_path, 205 | size_t size_bytes); 206 | 207 | /* 208 | * This function enables the user to get the echo path size in bytes 209 | * 210 | * Outputs Description 211 | * ------------------------------------------------------------------- 212 | * size_t return : size in bytes 213 | */ 214 | size_t WebRtcAecm_echo_path_size_bytes(); 215 | 216 | /* 217 | * Gets the last error code. 218 | * 219 | * Inputs Description 220 | * ------------------------------------------------------------------- 221 | * void *aecmInst Pointer to the AECM instance 222 | * 223 | * Outputs Description 224 | * ------------------------------------------------------------------- 225 | * int32_t return 11000-11100: error code 226 | */ 227 | int32_t WebRtcAecm_get_error_code(void *aecmInst); 228 | 229 | #ifdef __cplusplus 230 | } 231 | #endif 232 | #endif // WEBRTC_MODULES_AUDIO_PROCESSING_AECM_INCLUDE_ECHO_CONTROL_MOBILE_H_ 233 | -------------------------------------------------------------------------------- /src/fk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sed -i 's/\(#include\s*"\).*\/\(.*"\)/\1\2/g' *.[ch] 3 | files=`grep "#include\s*\".*\"" -h *.[ch] | sed 's/#include\s*\"\(.*\)\"/\1/g'` 4 | for i in $files;do 5 | if [ ! -f "$i" ];then 6 | find ../../webrtc -name "$i" -exec cp {} ./ \; 7 | fi 8 | done 9 | 10 | -------------------------------------------------------------------------------- /src/min_max_operations.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | /* 12 | * This file contains the implementation of functions 13 | * WebRtcSpl_MaxAbsValueW16C() 14 | * WebRtcSpl_MaxAbsValueW32C() 15 | * WebRtcSpl_MaxValueW16C() 16 | * WebRtcSpl_MaxValueW32C() 17 | * WebRtcSpl_MinValueW16C() 18 | * WebRtcSpl_MinValueW32C() 19 | * WebRtcSpl_MaxAbsIndexW16() 20 | * WebRtcSpl_MaxIndexW16() 21 | * WebRtcSpl_MaxIndexW32() 22 | * WebRtcSpl_MinIndexW16() 23 | * WebRtcSpl_MinIndexW32() 24 | * 25 | */ 26 | 27 | #include "signal_processing_library.h" 28 | 29 | #include 30 | 31 | // TODO(bjorn/kma): Consolidate function pairs (e.g. combine 32 | // WebRtcSpl_MaxAbsValueW16C and WebRtcSpl_MaxAbsIndexW16 into a single one.) 33 | // TODO(kma): Move the next six functions into min_max_operations_c.c. 34 | 35 | // Maximum absolute value of word16 vector. C version for generic platforms. 36 | int16_t WebRtcSpl_MaxAbsValueW16C(const int16_t* vector, int length) { 37 | int i = 0, absolute = 0, maximum = 0; 38 | 39 | if (vector == NULL || length <= 0) { 40 | return -1; 41 | } 42 | 43 | for (i = 0; i < length; i++) { 44 | absolute = abs((int)vector[i]); 45 | 46 | if (absolute > maximum) { 47 | maximum = absolute; 48 | } 49 | } 50 | 51 | // Guard the case for abs(-32768). 52 | if (maximum > WEBRTC_SPL_WORD16_MAX) { 53 | maximum = WEBRTC_SPL_WORD16_MAX; 54 | } 55 | 56 | return (int16_t)maximum; 57 | } 58 | 59 | // Maximum absolute value of word32 vector. C version for generic platforms. 60 | int32_t WebRtcSpl_MaxAbsValueW32C(const int32_t* vector, int length) { 61 | // Use uint32_t for the local variables, to accommodate the return value 62 | // of abs(0x80000000), which is 0x80000000. 63 | 64 | uint32_t absolute = 0, maximum = 0; 65 | int i = 0; 66 | 67 | if (vector == NULL || length <= 0) { 68 | return -1; 69 | } 70 | 71 | for (i = 0; i < length; i++) { 72 | absolute = abs((int)vector[i]); 73 | if (absolute > maximum) { 74 | maximum = absolute; 75 | } 76 | } 77 | 78 | maximum = WEBRTC_SPL_MIN(maximum, WEBRTC_SPL_WORD32_MAX); 79 | 80 | return (int32_t)maximum; 81 | } 82 | 83 | // Maximum value of word16 vector. C version for generic platforms. 84 | int16_t WebRtcSpl_MaxValueW16C(const int16_t* vector, int length) { 85 | int16_t maximum = WEBRTC_SPL_WORD16_MIN; 86 | int i = 0; 87 | 88 | if (vector == NULL || length <= 0) { 89 | return maximum; 90 | } 91 | 92 | for (i = 0; i < length; i++) { 93 | if (vector[i] > maximum) 94 | maximum = vector[i]; 95 | } 96 | return maximum; 97 | } 98 | 99 | // Maximum value of word32 vector. C version for generic platforms. 100 | int32_t WebRtcSpl_MaxValueW32C(const int32_t* vector, int length) { 101 | int32_t maximum = WEBRTC_SPL_WORD32_MIN; 102 | int i = 0; 103 | 104 | if (vector == NULL || length <= 0) { 105 | return maximum; 106 | } 107 | 108 | for (i = 0; i < length; i++) { 109 | if (vector[i] > maximum) 110 | maximum = vector[i]; 111 | } 112 | return maximum; 113 | } 114 | 115 | // Minimum value of word16 vector. C version for generic platforms. 116 | int16_t WebRtcSpl_MinValueW16C(const int16_t* vector, int length) { 117 | int16_t minimum = WEBRTC_SPL_WORD16_MAX; 118 | int i = 0; 119 | 120 | if (vector == NULL || length <= 0) { 121 | return minimum; 122 | } 123 | 124 | for (i = 0; i < length; i++) { 125 | if (vector[i] < minimum) 126 | minimum = vector[i]; 127 | } 128 | return minimum; 129 | } 130 | 131 | // Minimum value of word32 vector. C version for generic platforms. 132 | int32_t WebRtcSpl_MinValueW32C(const int32_t* vector, int length) { 133 | int32_t minimum = WEBRTC_SPL_WORD32_MAX; 134 | int i = 0; 135 | 136 | if (vector == NULL || length <= 0) { 137 | return minimum; 138 | } 139 | 140 | for (i = 0; i < length; i++) { 141 | if (vector[i] < minimum) 142 | minimum = vector[i]; 143 | } 144 | return minimum; 145 | } 146 | 147 | // Index of maximum absolute value in a word16 vector. 148 | int WebRtcSpl_MaxAbsIndexW16(const int16_t* vector, int length) { 149 | // Use type int for local variables, to accomodate the value of abs(-32768). 150 | 151 | int i = 0, absolute = 0, maximum = 0, index = 0; 152 | 153 | if (vector == NULL || length <= 0) { 154 | return -1; 155 | } 156 | 157 | for (i = 0; i < length; i++) { 158 | absolute = abs((int)vector[i]); 159 | 160 | if (absolute > maximum) { 161 | maximum = absolute; 162 | index = i; 163 | } 164 | } 165 | 166 | return index; 167 | } 168 | 169 | // Index of maximum value in a word16 vector. 170 | int WebRtcSpl_MaxIndexW16(const int16_t* vector, int length) { 171 | int i = 0, index = 0; 172 | int16_t maximum = WEBRTC_SPL_WORD16_MIN; 173 | 174 | if (vector == NULL || length <= 0) { 175 | return -1; 176 | } 177 | 178 | for (i = 0; i < length; i++) { 179 | if (vector[i] > maximum) { 180 | maximum = vector[i]; 181 | index = i; 182 | } 183 | } 184 | 185 | return index; 186 | } 187 | 188 | // Index of maximum value in a word32 vector. 189 | int WebRtcSpl_MaxIndexW32(const int32_t* vector, int length) { 190 | int i = 0, index = 0; 191 | int32_t maximum = WEBRTC_SPL_WORD32_MIN; 192 | 193 | if (vector == NULL || length <= 0) { 194 | return -1; 195 | } 196 | 197 | for (i = 0; i < length; i++) { 198 | if (vector[i] > maximum) { 199 | maximum = vector[i]; 200 | index = i; 201 | } 202 | } 203 | 204 | return index; 205 | } 206 | 207 | // Index of minimum value in a word16 vector. 208 | int WebRtcSpl_MinIndexW16(const int16_t* vector, int length) { 209 | int i = 0, index = 0; 210 | int16_t minimum = WEBRTC_SPL_WORD16_MAX; 211 | 212 | if (vector == NULL || length <= 0) { 213 | return -1; 214 | } 215 | 216 | for (i = 0; i < length; i++) { 217 | if (vector[i] < minimum) { 218 | minimum = vector[i]; 219 | index = i; 220 | } 221 | } 222 | 223 | return index; 224 | } 225 | 226 | // Index of minimum value in a word32 vector. 227 | int WebRtcSpl_MinIndexW32(const int32_t* vector, int length) { 228 | int i = 0, index = 0; 229 | int32_t minimum = WEBRTC_SPL_WORD32_MAX; 230 | 231 | if (vector == NULL || length <= 0) { 232 | return -1; 233 | } 234 | 235 | for (i = 0; i < length; i++) { 236 | if (vector[i] < minimum) { 237 | minimum = vector[i]; 238 | index = i; 239 | } 240 | } 241 | 242 | return index; 243 | } 244 | -------------------------------------------------------------------------------- /src/randomization_functions.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | 12 | /* 13 | * This file contains implementations of the randomization functions 14 | * WebRtcSpl_IncreaseSeed() 15 | * WebRtcSpl_RandU() 16 | * WebRtcSpl_RandN() 17 | * WebRtcSpl_RandUArray() 18 | * 19 | * The description header can be found in signal_processing_library.h 20 | * 21 | */ 22 | 23 | #include "signal_processing_library.h" 24 | 25 | static const int16_t kRandNTable[] = { 26 | 9178, -7260, 40, 10189, 4894, -3531, -13779, 14764, 27 | -4008, -8884, -8990, 1008, 7368, 5184, 3251, -5817, 28 | -9786, 5963, 1770, 8066, -7135, 10772, -2298, 1361, 29 | 6484, 2241, -8633, 792, 199, -3344, 6553, -10079, 30 | -15040, 95, 11608, -12469, 14161, -4176, 2476, 6403, 31 | 13685, -16005, 6646, 2239, 10916, -3004, -602, -3141, 32 | 2142, 14144, -5829, 5305, 8209, 4713, 2697, -5112, 33 | 16092, -1210, -2891, -6631, -5360, -11878, -6781, -2739, 34 | -6392, 536, 10923, 10872, 5059, -4748, -7770, 5477, 35 | 38, -1025, -2892, 1638, 6304, 14375, -11028, 1553, 36 | -1565, 10762, -393, 4040, 5257, 12310, 6554, -4799, 37 | 4899, -6354, 1603, -1048, -2220, 8247, -186, -8944, 38 | -12004, 2332, 4801, -4933, 6371, 131, 8614, -5927, 39 | -8287, -22760, 4033, -15162, 3385, 3246, 3153, -5250, 40 | 3766, 784, 6494, -62, 3531, -1582, 15572, 662, 41 | -3952, -330, -3196, 669, 7236, -2678, -6569, 23319, 42 | -8645, -741, 14830, -15976, 4903, 315, -11342, 10311, 43 | 1858, -7777, 2145, 5436, 5677, -113, -10033, 826, 44 | -1353, 17210, 7768, 986, -1471, 8291, -4982, 8207, 45 | -14911, -6255, -2449, -11881, -7059, -11703, -4338, 8025, 46 | 7538, -2823, -12490, 9470, -1613, -2529, -10092, -7807, 47 | 9480, 6970, -12844, 5123, 3532, 4816, 4803, -8455, 48 | -5045, 14032, -4378, -1643, 5756, -11041, -2732, -16618, 49 | -6430, -18375, -3320, 6098, 5131, -4269, -8840, 2482, 50 | -7048, 1547, -21890, -6505, -7414, -424, -11722, 7955, 51 | 1653, -17299, 1823, 473, -9232, 3337, 1111, 873, 52 | 4018, -8982, 9889, 3531, -11763, -3799, 7373, -4539, 53 | 3231, 7054, -8537, 7616, 6244, 16635, 447, -2915, 54 | 13967, 705, -2669, -1520, -1771, -16188, 5956, 5117, 55 | 6371, -9936, -1448, 2480, 5128, 7550, -8130, 5236, 56 | 8213, -6443, 7707, -1950, -13811, 7218, 7031, -3883, 57 | 67, 5731, -2874, 13480, -3743, 9298, -3280, 3552, 58 | -4425, -18, -3785, -9988, -5357, 5477, -11794, 2117, 59 | 1416, -9935, 3376, 802, -5079, -8243, 12652, 66, 60 | 3653, -2368, 6781, -21895, -7227, 2487, 7839, -385, 61 | 6646, -7016, -4658, 5531, -1705, 834, 129, 3694, 62 | -1343, 2238, -22640, -6417, -11139, 11301, -2945, -3494, 63 | -5626, 185, -3615, -2041, -7972, -3106, -60, -23497, 64 | -1566, 17064, 3519, 2518, 304, -6805, -10269, 2105, 65 | 1936, -426, -736, -8122, -1467, 4238, -6939, -13309, 66 | 360, 7402, -7970, 12576, 3287, 12194, -6289, -16006, 67 | 9171, 4042, -9193, 9123, -2512, 6388, -4734, -8739, 68 | 1028, -5406, -1696, 5889, -666, -4736, 4971, 3565, 69 | 9362, -6292, 3876, -3652, -19666, 7523, -4061, 391, 70 | -11773, 7502, -3763, 4929, -9478, 13278, 2805, 4496, 71 | 7814, 16419, 12455, -14773, 2127, -2746, 3763, 4847, 72 | 3698, 6978, 4751, -6957, -3581, -45, 6252, 1513, 73 | -4797, -7925, 11270, 16188, -2359, -5269, 9376, -10777, 74 | 7262, 20031, -6515, -2208, -5353, 8085, -1341, -1303, 75 | 7333, 5576, 3625, 5763, -7931, 9833, -3371, -10305, 76 | 6534, -13539, -9971, 997, 8464, -4064, -1495, 1857, 77 | 13624, 5458, 9490, -11086, -4524, 12022, -550, -198, 78 | 408, -8455, -7068, 10289, 9712, -3366, 9028, -7621, 79 | -5243, 2362, 6909, 4672, -4933, -1799, 4709, -4563, 80 | -62, -566, 1624, -7010, 14730, -17791, -3697, -2344, 81 | -1741, 7099, -9509, -6855, -1989, 3495, -2289, 2031, 82 | 12784, 891, 14189, -3963, -5683, 421, -12575, 1724, 83 | -12682, -5970, -8169, 3143, -1824, -5488, -5130, 8536, 84 | 12799, 794, 5738, 3459, -11689, -258, -3738, -3775, 85 | -8742, 2333, 8312, -9383, 10331, 13119, 8398, 10644, 86 | -19433, -6446, -16277, -11793, 16284, 9345, 15222, 15834, 87 | 2009, -7349, 130, -14547, 338, -5998, 3337, 21492, 88 | 2406, 7703, -951, 11196, -564, 3406, 2217, 4806, 89 | 2374, -5797, 11839, 8940, -11874, 18213, 2855, 10492 90 | }; 91 | 92 | uint32_t WebRtcSpl_IncreaseSeed(uint32_t *seed) 93 | { 94 | seed[0] = (seed[0] * ((int32_t)69069) + 1) & (WEBRTC_SPL_MAX_SEED_USED - 1); 95 | return seed[0]; 96 | } 97 | 98 | int16_t WebRtcSpl_RandU(uint32_t *seed) 99 | { 100 | return (int16_t)(WebRtcSpl_IncreaseSeed(seed) >> 16); 101 | } 102 | 103 | int16_t WebRtcSpl_RandN(uint32_t *seed) 104 | { 105 | return kRandNTable[WebRtcSpl_IncreaseSeed(seed) >> 23]; 106 | } 107 | 108 | // Creates an array of uniformly distributed variables 109 | int16_t WebRtcSpl_RandUArray(int16_t* vector, 110 | int16_t vector_length, 111 | uint32_t* seed) 112 | { 113 | int i; 114 | for (i = 0; i < vector_length; i++) 115 | { 116 | vector[i] = WebRtcSpl_RandU(seed); 117 | } 118 | return vector_length; 119 | } 120 | -------------------------------------------------------------------------------- /src/real_fft.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #include "real_fft.h" 12 | 13 | #include 14 | 15 | #include "signal_processing_library.h" 16 | 17 | struct RealFFT { 18 | int order; 19 | }; 20 | 21 | struct RealFFT* WebRtcSpl_CreateRealFFTC(int order) { 22 | struct RealFFT* self = NULL; 23 | 24 | if (order > kMaxFFTOrder || order < 0) { 25 | return NULL; 26 | } 27 | 28 | self = malloc(sizeof(struct RealFFT)); 29 | if (self == NULL) { 30 | return NULL; 31 | } 32 | self->order = order; 33 | 34 | return self; 35 | } 36 | 37 | void WebRtcSpl_FreeRealFFTC(struct RealFFT* self) { 38 | if (self != NULL) { 39 | free(self); 40 | } 41 | } 42 | 43 | // The C version FFT functions (i.e. WebRtcSpl_RealForwardFFTC and 44 | // WebRtcSpl_RealInverseFFTC) are real-valued FFT wrappers for complex-valued 45 | // FFT implementation in SPL. 46 | 47 | int WebRtcSpl_RealForwardFFTC(struct RealFFT* self, 48 | const int16_t* real_data_in, 49 | int16_t* complex_data_out) { 50 | int i = 0; 51 | int j = 0; 52 | int result = 0; 53 | int n = 1 << self->order; 54 | // The complex-value FFT implementation needs a buffer to hold 2^order 55 | // 16-bit COMPLEX numbers, for both time and frequency data. 56 | int16_t complex_buffer[2 << kMaxFFTOrder]; 57 | 58 | // Insert zeros to the imaginary parts for complex forward FFT input. 59 | for (i = 0, j = 0; i < n; i += 1, j += 2) { 60 | complex_buffer[j] = real_data_in[i]; 61 | complex_buffer[j + 1] = 0; 62 | }; 63 | 64 | WebRtcSpl_ComplexBitReverse(complex_buffer, self->order); 65 | result = WebRtcSpl_ComplexFFT(complex_buffer, self->order, 1); 66 | 67 | // For real FFT output, use only the first N + 2 elements from 68 | // complex forward FFT. 69 | memcpy(complex_data_out, complex_buffer, sizeof(int16_t) * (n + 2)); 70 | 71 | return result; 72 | } 73 | 74 | int WebRtcSpl_RealInverseFFTC(struct RealFFT* self, 75 | const int16_t* complex_data_in, 76 | int16_t* real_data_out) { 77 | int i = 0; 78 | int j = 0; 79 | int result = 0; 80 | int n = 1 << self->order; 81 | // Create the buffer specific to complex-valued FFT implementation. 82 | int16_t complex_buffer[2 << kMaxFFTOrder]; 83 | 84 | // For n-point FFT, first copy the first n + 2 elements into complex 85 | // FFT, then construct the remaining n - 2 elements by real FFT's 86 | // conjugate-symmetric properties. 87 | memcpy(complex_buffer, complex_data_in, sizeof(int16_t) * (n + 2)); 88 | for (i = n + 2; i < 2 * n; i += 2) { 89 | complex_buffer[i] = complex_data_in[2 * n - i]; 90 | complex_buffer[i + 1] = -complex_data_in[2 * n - i + 1]; 91 | } 92 | 93 | WebRtcSpl_ComplexBitReverse(complex_buffer, self->order); 94 | result = WebRtcSpl_ComplexIFFT(complex_buffer, self->order, 1); 95 | 96 | // Strip out the imaginary parts of the complex inverse FFT output. 97 | for (i = 0, j = 0; i < n; i += 1, j += 2) { 98 | real_data_out[i] = complex_buffer[j]; 99 | } 100 | 101 | return result; 102 | } 103 | 104 | #if defined(WEBRTC_DETECT_ARM_NEON) || defined(WEBRTC_ARCH_ARM_NEON) 105 | // TODO(kma): Replace the following function bodies into optimized functions 106 | // for ARM Neon. 107 | struct RealFFT* WebRtcSpl_CreateRealFFTNeon(int order) { 108 | return WebRtcSpl_CreateRealFFTC(order); 109 | } 110 | 111 | void WebRtcSpl_FreeRealFFTNeon(struct RealFFT* self) { 112 | WebRtcSpl_FreeRealFFTC(self); 113 | } 114 | 115 | int WebRtcSpl_RealForwardFFTNeon(struct RealFFT* self, 116 | const int16_t* real_data_in, 117 | int16_t* complex_data_out) { 118 | return WebRtcSpl_RealForwardFFTC(self, real_data_in, complex_data_out); 119 | } 120 | 121 | int WebRtcSpl_RealInverseFFTNeon(struct RealFFT* self, 122 | const int16_t* complex_data_in, 123 | int16_t* real_data_out) { 124 | return WebRtcSpl_RealInverseFFTC(self, complex_data_in, real_data_out); 125 | } 126 | #endif // WEBRTC_DETECT_ARM_NEON || WEBRTC_ARCH_ARM_NEON 127 | -------------------------------------------------------------------------------- /src/real_fft.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_ 12 | #define WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_ 13 | 14 | #include "typedefs.h" 15 | 16 | // For ComplexFFT(), the maximum fft order is 10; 17 | // for OpenMax FFT in ARM, it is 12; 18 | // WebRTC APM uses orders of only 7 and 8. 19 | enum {kMaxFFTOrder = 10}; 20 | 21 | struct RealFFT; 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | typedef struct RealFFT* (*CreateRealFFT)(int order); 28 | typedef void (*FreeRealFFT)(struct RealFFT* self); 29 | typedef int (*RealForwardFFT)(struct RealFFT* self, 30 | const int16_t* real_data_in, 31 | int16_t* complex_data_out); 32 | typedef int (*RealInverseFFT)(struct RealFFT* self, 33 | const int16_t* complex_data_in, 34 | int16_t* real_data_out); 35 | 36 | extern CreateRealFFT WebRtcSpl_CreateRealFFT; 37 | extern FreeRealFFT WebRtcSpl_FreeRealFFT; 38 | extern RealForwardFFT WebRtcSpl_RealForwardFFT; 39 | extern RealInverseFFT WebRtcSpl_RealInverseFFT; 40 | 41 | struct RealFFT* WebRtcSpl_CreateRealFFTC(int order); 42 | void WebRtcSpl_FreeRealFFTC(struct RealFFT* self); 43 | 44 | #if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON) 45 | struct RealFFT* WebRtcSpl_CreateRealFFTNeon(int order); 46 | void WebRtcSpl_FreeRealFFTNeon(struct RealFFT* self); 47 | #endif 48 | 49 | // Compute an FFT for a real-valued signal of length of 2^order, 50 | // where 1 < order <= MAX_FFT_ORDER. Transform length is determined by the 51 | // specification structure, which must be initialized prior to calling the FFT 52 | // function with WebRtcSpl_CreateRealFFT(). 53 | // The relationship between the input and output sequences can 54 | // be expressed in terms of the DFT, i.e.: 55 | // x[n] = (2^(-scalefactor)/N) . SUM[k=0,...,N-1] X[k].e^(jnk.2.pi/N) 56 | // n=0,1,2,...N-1 57 | // N=2^order. 58 | // The conjugate-symmetric output sequence is represented using a CCS vector, 59 | // which is of length N+2, and is organized as follows: 60 | // Index: 0 1 2 3 4 5 . . . N-2 N-1 N N+1 61 | // Component: R0 0 R1 I1 R2 I2 . . . R[N/2-1] I[N/2-1] R[N/2] 0 62 | // where R[n] and I[n], respectively, denote the real and imaginary components 63 | // for FFT bin 'n'. Bins are numbered from 0 to N/2, where N is the FFT length. 64 | // Bin index 0 corresponds to the DC component, and bin index N/2 corresponds to 65 | // the foldover frequency. 66 | // 67 | // Input Arguments: 68 | // self - pointer to preallocated and initialized FFT specification structure. 69 | // real_data_in - the input signal. For an ARM Neon platform, it must be 70 | // aligned on a 32-byte boundary. 71 | // 72 | // Output Arguments: 73 | // complex_data_out - the output complex signal with (2^order + 2) 16-bit 74 | // elements. For an ARM Neon platform, it must be different 75 | // from real_data_in, and aligned on a 32-byte boundary. 76 | // 77 | // Return Value: 78 | // 0 - FFT calculation is successful. 79 | // -1 - Error with bad arguments (NULL pointers). 80 | int WebRtcSpl_RealForwardFFTC(struct RealFFT* self, 81 | const int16_t* real_data_in, 82 | int16_t* complex_data_out); 83 | 84 | #if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON) 85 | int WebRtcSpl_RealForwardFFTNeon(struct RealFFT* self, 86 | const int16_t* real_data_in, 87 | int16_t* complex_data_out); 88 | #endif 89 | 90 | // Compute the inverse FFT for a conjugate-symmetric input sequence of length of 91 | // 2^order, where 1 < order <= MAX_FFT_ORDER. Transform length is determined by 92 | // the specification structure, which must be initialized prior to calling the 93 | // FFT function with WebRtcSpl_CreateRealFFT(). 94 | // For a transform of length M, the input sequence is represented using a packed 95 | // CCS vector of length M+2, which is explained in the comments for 96 | // WebRtcSpl_RealForwardFFTC above. 97 | // 98 | // Input Arguments: 99 | // self - pointer to preallocated and initialized FFT specification structure. 100 | // complex_data_in - the input complex signal with (2^order + 2) 16-bit 101 | // elements. For an ARM Neon platform, it must be aligned on 102 | // a 32-byte boundary. 103 | // 104 | // Output Arguments: 105 | // real_data_out - the output real signal. For an ARM Neon platform, it must 106 | // be different to complex_data_in, and aligned on a 32-byte 107 | // boundary. 108 | // 109 | // Return Value: 110 | // 0 or a positive number - a value that the elements in the |real_data_out| 111 | // should be shifted left with in order to get 112 | // correct physical values. 113 | // -1 - Error with bad arguments (NULL pointers). 114 | int WebRtcSpl_RealInverseFFTC(struct RealFFT* self, 115 | const int16_t* complex_data_in, 116 | int16_t* real_data_out); 117 | 118 | #if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON) 119 | int WebRtcSpl_RealInverseFFTNeon(struct RealFFT* self, 120 | const int16_t* complex_data_in, 121 | int16_t* real_data_out); 122 | #endif 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | 128 | #endif // WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_ 129 | -------------------------------------------------------------------------------- /src/ring_buffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // A ring buffer to hold arbitrary data. Provides no thread safety. Unless 12 | // otherwise specified, functions return 0 on success and -1 on error. 13 | 14 | #include "ring_buffer.h" 15 | 16 | #include // size_t 17 | #include 18 | #include 19 | 20 | enum Wrap { 21 | SAME_WRAP, 22 | DIFF_WRAP 23 | }; 24 | 25 | struct RingBuffer { 26 | size_t read_pos; 27 | size_t write_pos; 28 | size_t element_count; 29 | size_t element_size; 30 | enum Wrap rw_wrap; 31 | char* data; 32 | }; 33 | 34 | // Get address of region(s) from which we can read data. 35 | // If the region is contiguous, |data_ptr_bytes_2| will be zero. 36 | // If non-contiguous, |data_ptr_bytes_2| will be the size in bytes of the second 37 | // region. Returns room available to be read or |element_count|, whichever is 38 | // smaller. 39 | static size_t GetBufferReadRegions(RingBuffer* buf, 40 | size_t element_count, 41 | void** data_ptr_1, 42 | size_t* data_ptr_bytes_1, 43 | void** data_ptr_2, 44 | size_t* data_ptr_bytes_2) { 45 | 46 | const size_t readable_elements = WebRtc_available_read(buf); 47 | const size_t read_elements = (readable_elements < element_count ? 48 | readable_elements : element_count); 49 | const size_t margin = buf->element_count - buf->read_pos; 50 | 51 | // Check to see if read is not contiguous. 52 | if (read_elements > margin) { 53 | // Write data in two blocks that wrap the buffer. 54 | *data_ptr_1 = buf->data + buf->read_pos * buf->element_size; 55 | *data_ptr_bytes_1 = margin * buf->element_size; 56 | *data_ptr_2 = buf->data; 57 | *data_ptr_bytes_2 = (read_elements - margin) * buf->element_size; 58 | } else { 59 | *data_ptr_1 = buf->data + buf->read_pos * buf->element_size; 60 | *data_ptr_bytes_1 = read_elements * buf->element_size; 61 | *data_ptr_2 = NULL; 62 | *data_ptr_bytes_2 = 0; 63 | } 64 | 65 | return read_elements; 66 | } 67 | 68 | RingBuffer* WebRtc_CreateBuffer(size_t element_count, size_t element_size) { 69 | RingBuffer* self = NULL; 70 | if (element_count == 0 || element_size == 0) { 71 | return NULL; 72 | } 73 | 74 | self = malloc(sizeof(RingBuffer)); 75 | if (!self) { 76 | return NULL; 77 | } 78 | 79 | self->data = malloc(element_count * element_size); 80 | if (!self->data) { 81 | free(self); 82 | self = NULL; 83 | return NULL; 84 | } 85 | 86 | self->element_count = element_count; 87 | self->element_size = element_size; 88 | 89 | return self; 90 | } 91 | 92 | int WebRtc_InitBuffer(RingBuffer* self) { 93 | if (!self) { 94 | return -1; 95 | } 96 | 97 | self->read_pos = 0; 98 | self->write_pos = 0; 99 | self->rw_wrap = SAME_WRAP; 100 | 101 | // Initialize buffer to zeros 102 | memset(self->data, 0, self->element_count * self->element_size); 103 | 104 | return 0; 105 | } 106 | 107 | void WebRtc_FreeBuffer(void* handle) { 108 | RingBuffer* self = (RingBuffer*)handle; 109 | if (!self) { 110 | return; 111 | } 112 | 113 | free(self->data); 114 | free(self); 115 | } 116 | 117 | size_t WebRtc_ReadBuffer(RingBuffer* self, 118 | void** data_ptr, 119 | void* data, 120 | size_t element_count) { 121 | 122 | if (self == NULL) { 123 | return 0; 124 | } 125 | if (data == NULL) { 126 | return 0; 127 | } 128 | 129 | { 130 | void* buf_ptr_1 = NULL; 131 | void* buf_ptr_2 = NULL; 132 | size_t buf_ptr_bytes_1 = 0; 133 | size_t buf_ptr_bytes_2 = 0; 134 | const size_t read_count = GetBufferReadRegions(self, 135 | element_count, 136 | &buf_ptr_1, 137 | &buf_ptr_bytes_1, 138 | &buf_ptr_2, 139 | &buf_ptr_bytes_2); 140 | 141 | if (buf_ptr_bytes_2 > 0) { 142 | // We have a wrap around when reading the buffer. Copy the buffer data to 143 | // |data| and point to it. 144 | memcpy(data, buf_ptr_1, buf_ptr_bytes_1); 145 | memcpy(((char*) data) + buf_ptr_bytes_1, buf_ptr_2, buf_ptr_bytes_2); 146 | buf_ptr_1 = data; 147 | } else if (!data_ptr) { 148 | // No wrap, but a memcpy was requested. 149 | memcpy(data, buf_ptr_1, buf_ptr_bytes_1); 150 | } 151 | if (data_ptr) { 152 | // |buf_ptr_1| == |data| in the case of a wrap. 153 | *data_ptr = buf_ptr_1; 154 | } 155 | 156 | // Update read position 157 | WebRtc_MoveReadPtr(self, (int) read_count); 158 | 159 | return read_count; 160 | } 161 | } 162 | 163 | size_t WebRtc_WriteBuffer(RingBuffer* self, 164 | const void* data, 165 | size_t element_count) { 166 | if (!self) { 167 | return 0; 168 | } 169 | if (!data) { 170 | return 0; 171 | } 172 | 173 | { 174 | const size_t free_elements = WebRtc_available_write(self); 175 | const size_t write_elements = (free_elements < element_count ? free_elements 176 | : element_count); 177 | size_t n = write_elements; 178 | const size_t margin = self->element_count - self->write_pos; 179 | 180 | if (write_elements > margin) { 181 | // Buffer wrap around when writing. 182 | memcpy(self->data + self->write_pos * self->element_size, 183 | data, margin * self->element_size); 184 | self->write_pos = 0; 185 | n -= margin; 186 | self->rw_wrap = DIFF_WRAP; 187 | } 188 | memcpy(self->data + self->write_pos * self->element_size, 189 | ((const char*) data) + ((write_elements - n) * self->element_size), 190 | n * self->element_size); 191 | self->write_pos += n; 192 | 193 | return write_elements; 194 | } 195 | } 196 | 197 | int WebRtc_MoveReadPtr(RingBuffer* self, int element_count) { 198 | if (!self) { 199 | return 0; 200 | } 201 | 202 | { 203 | // We need to be able to take care of negative changes, hence use "int" 204 | // instead of "size_t". 205 | const int free_elements = (int) WebRtc_available_write(self); 206 | const int readable_elements = (int) WebRtc_available_read(self); 207 | int read_pos = (int) self->read_pos; 208 | 209 | if (element_count > readable_elements) { 210 | element_count = readable_elements; 211 | } 212 | if (element_count < -free_elements) { 213 | element_count = -free_elements; 214 | } 215 | 216 | read_pos += element_count; 217 | if (read_pos > (int) self->element_count) { 218 | // Buffer wrap around. Restart read position and wrap indicator. 219 | read_pos -= (int) self->element_count; 220 | self->rw_wrap = SAME_WRAP; 221 | } 222 | if (read_pos < 0) { 223 | // Buffer wrap around. Restart read position and wrap indicator. 224 | read_pos += (int) self->element_count; 225 | self->rw_wrap = DIFF_WRAP; 226 | } 227 | 228 | self->read_pos = (size_t) read_pos; 229 | 230 | return element_count; 231 | } 232 | } 233 | 234 | size_t WebRtc_available_read(const RingBuffer* self) { 235 | if (!self) { 236 | return 0; 237 | } 238 | 239 | if (self->rw_wrap == SAME_WRAP) { 240 | return self->write_pos - self->read_pos; 241 | } else { 242 | return self->element_count - self->read_pos + self->write_pos; 243 | } 244 | } 245 | 246 | size_t WebRtc_available_write(const RingBuffer* self) { 247 | if (!self) { 248 | return 0; 249 | } 250 | 251 | return self->element_count - WebRtc_available_read(self); 252 | } 253 | -------------------------------------------------------------------------------- /src/ring_buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // A ring buffer to hold arbitrary data. Provides no thread safety. Unless 12 | // otherwise specified, functions return 0 on success and -1 on error. 13 | 14 | #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_RING_BUFFER_H_ 15 | #define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_RING_BUFFER_H_ 16 | 17 | #include // size_t 18 | 19 | typedef struct RingBuffer RingBuffer; 20 | 21 | // Returns NULL on failure. 22 | RingBuffer* WebRtc_CreateBuffer(size_t element_count, size_t element_size); 23 | int WebRtc_InitBuffer(RingBuffer* handle); 24 | void WebRtc_FreeBuffer(void* handle); 25 | 26 | // Reads data from the buffer. The |data_ptr| will point to the address where 27 | // it is located. If all |element_count| data are feasible to read without 28 | // buffer wrap around |data_ptr| will point to the location in the buffer. 29 | // Otherwise, the data will be copied to |data| (memory allocation done by the 30 | // user) and |data_ptr| points to the address of |data|. |data_ptr| is only 31 | // guaranteed to be valid until the next call to WebRtc_WriteBuffer(). 32 | // 33 | // To force a copying to |data|, pass a NULL |data_ptr|. 34 | // 35 | // Returns number of elements read. 36 | size_t WebRtc_ReadBuffer(RingBuffer* handle, 37 | void** data_ptr, 38 | void* data, 39 | size_t element_count); 40 | 41 | // Writes |data| to buffer and returns the number of elements written. 42 | size_t WebRtc_WriteBuffer(RingBuffer* handle, const void* data, 43 | size_t element_count); 44 | 45 | // Moves the buffer read position and returns the number of elements moved. 46 | // Positive |element_count| moves the read position towards the write position, 47 | // that is, flushing the buffer. Negative |element_count| moves the read 48 | // position away from the the write position, that is, stuffing the buffer. 49 | // Returns number of elements moved. 50 | int WebRtc_MoveReadPtr(RingBuffer* handle, int element_count); 51 | 52 | // Returns number of available elements to read. 53 | size_t WebRtc_available_read(const RingBuffer* handle); 54 | 55 | // Returns number of available elements for write. 56 | size_t WebRtc_available_write(const RingBuffer* handle); 57 | 58 | #endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_RING_BUFFER_H_ 59 | -------------------------------------------------------------------------------- /src/spl_init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | /* The global function contained in this file initializes SPL function 12 | * pointers, currently only for ARM platforms. 13 | * 14 | * Some code came from common/rtcd.c in the WebM project. 15 | */ 16 | 17 | #include "real_fft.h" 18 | #include "signal_processing_library.h" 19 | #include "cpu_features_wrapper.h" 20 | 21 | /* Declare function pointers. */ 22 | MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16; 23 | MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32; 24 | MaxValueW16 WebRtcSpl_MaxValueW16; 25 | MaxValueW32 WebRtcSpl_MaxValueW32; 26 | MinValueW16 WebRtcSpl_MinValueW16; 27 | MinValueW32 WebRtcSpl_MinValueW32; 28 | CrossCorrelation WebRtcSpl_CrossCorrelation; 29 | DownsampleFast WebRtcSpl_DownsampleFast; 30 | ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound; 31 | CreateRealFFT WebRtcSpl_CreateRealFFT; 32 | FreeRealFFT WebRtcSpl_FreeRealFFT; 33 | RealForwardFFT WebRtcSpl_RealForwardFFT; 34 | RealInverseFFT WebRtcSpl_RealInverseFFT; 35 | 36 | #if (defined(WEBRTC_DETECT_ARM_NEON) || !defined(WEBRTC_ARCH_ARM_NEON)) && \ 37 | !defined(MIPS32_LE) 38 | /* Initialize function pointers to the generic C version. */ 39 | static void InitPointersToC() { 40 | WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16C; 41 | WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C; 42 | WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16C; 43 | WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32C; 44 | WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16C; 45 | WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32C; 46 | WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationC; 47 | WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastC; 48 | WebRtcSpl_ScaleAndAddVectorsWithRound = 49 | WebRtcSpl_ScaleAndAddVectorsWithRoundC; 50 | WebRtcSpl_CreateRealFFT = WebRtcSpl_CreateRealFFTC; 51 | WebRtcSpl_FreeRealFFT = WebRtcSpl_FreeRealFFTC; 52 | WebRtcSpl_RealForwardFFT = WebRtcSpl_RealForwardFFTC; 53 | WebRtcSpl_RealInverseFFT = WebRtcSpl_RealInverseFFTC; 54 | } 55 | #endif 56 | 57 | #if defined(WEBRTC_DETECT_ARM_NEON) || defined(WEBRTC_ARCH_ARM_NEON) 58 | /* Initialize function pointers to the Neon version. */ 59 | static void InitPointersToNeon() { 60 | WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16Neon; 61 | WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32Neon; 62 | WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16Neon; 63 | WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32Neon; 64 | WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16Neon; 65 | WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32Neon; 66 | WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationNeon; 67 | WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastNeon; 68 | WebRtcSpl_ScaleAndAddVectorsWithRound = 69 | WebRtcSpl_ScaleAndAddVectorsWithRoundNeon; 70 | WebRtcSpl_CreateRealFFT = WebRtcSpl_CreateRealFFTNeon; 71 | WebRtcSpl_FreeRealFFT = WebRtcSpl_FreeRealFFTNeon; 72 | WebRtcSpl_RealForwardFFT = WebRtcSpl_RealForwardFFTNeon; 73 | WebRtcSpl_RealInverseFFT = WebRtcSpl_RealInverseFFTNeon; 74 | } 75 | #endif 76 | 77 | #if defined(MIPS32_LE) 78 | /* Initialize function pointers to the MIPS version. */ 79 | static void InitPointersToMIPS() { 80 | WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16_mips; 81 | WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16_mips; 82 | WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32_mips; 83 | WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16_mips; 84 | WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32_mips; 85 | WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelation_mips; 86 | WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFast_mips; 87 | WebRtcSpl_CreateRealFFT = WebRtcSpl_CreateRealFFTC; 88 | WebRtcSpl_FreeRealFFT = WebRtcSpl_FreeRealFFTC; 89 | WebRtcSpl_RealForwardFFT = WebRtcSpl_RealForwardFFTC; 90 | WebRtcSpl_RealInverseFFT = WebRtcSpl_RealInverseFFTC; 91 | #if defined(MIPS_DSP_R1_LE) 92 | WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32_mips; 93 | WebRtcSpl_ScaleAndAddVectorsWithRound = 94 | WebRtcSpl_ScaleAndAddVectorsWithRound_mips; 95 | #else 96 | WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C; 97 | WebRtcSpl_ScaleAndAddVectorsWithRound = 98 | WebRtcSpl_ScaleAndAddVectorsWithRoundC; 99 | #endif 100 | } 101 | #endif 102 | 103 | static void InitFunctionPointers(void) { 104 | #if defined(WEBRTC_DETECT_ARM_NEON) 105 | if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) { 106 | InitPointersToNeon(); 107 | } else { 108 | InitPointersToC(); 109 | } 110 | #elif defined(WEBRTC_ARCH_ARM_NEON) 111 | InitPointersToNeon(); 112 | #elif defined(MIPS32_LE) 113 | InitPointersToMIPS(); 114 | #else 115 | InitPointersToC(); 116 | #endif /* WEBRTC_DETECT_ARM_NEON */ 117 | } 118 | 119 | #if defined(WEBRTC_POSIX) 120 | #include 121 | 122 | static void once(void (*func)(void)) { 123 | static pthread_once_t lock = PTHREAD_ONCE_INIT; 124 | pthread_once(&lock, func); 125 | } 126 | 127 | #elif defined(_WIN32) 128 | #include 129 | 130 | static void once(void (*func)(void)) { 131 | /* Didn't use InitializeCriticalSection() since there's no race-free context 132 | * in which to execute it. 133 | * 134 | * TODO(kma): Change to different implementation (e.g. 135 | * InterlockedCompareExchangePointer) to avoid issues similar to 136 | * http://code.google.com/p/webm/issues/detail?id=467. 137 | */ 138 | static CRITICAL_SECTION lock = {(void *)((size_t)-1), -1, 0, 0, 0, 0}; 139 | static int done = 0; 140 | 141 | EnterCriticalSection(&lock); 142 | if (!done) { 143 | func(); 144 | done = 1; 145 | } 146 | LeaveCriticalSection(&lock); 147 | } 148 | 149 | /* There's no fallback version as an #else block here to ensure thread safety. 150 | * In case of neither pthread for WEBRTC_POSIX nor _WIN32 is present, build 151 | * system should pick it up. 152 | */ 153 | #endif /* WEBRTC_POSIX */ 154 | 155 | void WebRtcSpl_Init() { 156 | once(InitFunctionPointers); 157 | } 158 | -------------------------------------------------------------------------------- /src/spl_inl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | 12 | // This header file includes the inline functions in 13 | // the fix point signal processing library. 14 | 15 | #ifndef WEBRTC_SPL_SPL_INL_H_ 16 | #define WEBRTC_SPL_SPL_INL_H_ 17 | 18 | #ifdef WEBRTC_ARCH_ARM_V7 19 | #include "webrtc/common_audio/signal_processing/include/spl_inl_armv7.h" 20 | #else 21 | 22 | #if defined(MIPS32_LE) 23 | #include "webrtc/common_audio/signal_processing/include/spl_inl_mips.h" 24 | #endif 25 | 26 | #if !defined(MIPS_DSP_R1_LE) 27 | static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) { 28 | int16_t out16 = (int16_t) value32; 29 | 30 | if (value32 > 32767) 31 | out16 = 32767; 32 | else if (value32 < -32768) 33 | out16 = -32768; 34 | 35 | return out16; 36 | } 37 | 38 | static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) { 39 | return WebRtcSpl_SatW32ToW16((int32_t) a + (int32_t) b); 40 | } 41 | 42 | static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) { 43 | return WebRtcSpl_SatW32ToW16((int32_t) var1 - (int32_t) var2); 44 | } 45 | #endif // #if !defined(MIPS_DSP_R1_LE) 46 | 47 | #if !defined(MIPS32_LE) 48 | static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) { 49 | int bits; 50 | 51 | if (0xFFFF0000 & n) { 52 | bits = 16; 53 | } else { 54 | bits = 0; 55 | } 56 | if (0x0000FF00 & (n >> bits)) bits += 8; 57 | if (0x000000F0 & (n >> bits)) bits += 4; 58 | if (0x0000000C & (n >> bits)) bits += 2; 59 | if (0x00000002 & (n >> bits)) bits += 1; 60 | if (0x00000001 & (n >> bits)) bits += 1; 61 | 62 | return bits; 63 | } 64 | 65 | static __inline int WebRtcSpl_NormW32(int32_t a) { 66 | int zeros; 67 | 68 | if (a == 0) { 69 | return 0; 70 | } 71 | else if (a < 0) { 72 | a = ~a; 73 | } 74 | 75 | if (!(0xFFFF8000 & a)) { 76 | zeros = 16; 77 | } else { 78 | zeros = 0; 79 | } 80 | if (!(0xFF800000 & (a << zeros))) zeros += 8; 81 | if (!(0xF8000000 & (a << zeros))) zeros += 4; 82 | if (!(0xE0000000 & (a << zeros))) zeros += 2; 83 | if (!(0xC0000000 & (a << zeros))) zeros += 1; 84 | 85 | return zeros; 86 | } 87 | 88 | static __inline int WebRtcSpl_NormU32(uint32_t a) { 89 | int zeros; 90 | 91 | if (a == 0) return 0; 92 | 93 | if (!(0xFFFF0000 & a)) { 94 | zeros = 16; 95 | } else { 96 | zeros = 0; 97 | } 98 | if (!(0xFF000000 & (a << zeros))) zeros += 8; 99 | if (!(0xF0000000 & (a << zeros))) zeros += 4; 100 | if (!(0xC0000000 & (a << zeros))) zeros += 2; 101 | if (!(0x80000000 & (a << zeros))) zeros += 1; 102 | 103 | return zeros; 104 | } 105 | 106 | static __inline int WebRtcSpl_NormW16(int16_t a) { 107 | int zeros; 108 | 109 | if (a == 0) { 110 | return 0; 111 | } 112 | else if (a < 0) { 113 | a = ~a; 114 | } 115 | 116 | if (!(0xFF80 & a)) { 117 | zeros = 8; 118 | } else { 119 | zeros = 0; 120 | } 121 | if (!(0xF800 & (a << zeros))) zeros += 4; 122 | if (!(0xE000 & (a << zeros))) zeros += 2; 123 | if (!(0xC000 & (a << zeros))) zeros += 1; 124 | 125 | return zeros; 126 | } 127 | 128 | static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) { 129 | return (a * b + c); 130 | } 131 | #endif // #if !defined(MIPS32_LE) 132 | 133 | #endif // WEBRTC_ARCH_ARM_V7 134 | 135 | // The following functions have no optimized versions. 136 | // TODO(kma): Consider saturating add/sub instructions in X86 platform. 137 | #if !defined(MIPS_DSP_R1_LE) 138 | static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) { 139 | int32_t l_sum; 140 | 141 | // Perform long addition 142 | l_sum = l_var1 + l_var2; 143 | 144 | if (l_var1 < 0) { // Check for underflow. 145 | if ((l_var2 < 0) && (l_sum >= 0)) { 146 | l_sum = (int32_t)0x80000000; 147 | } 148 | } else { // Check for overflow. 149 | if ((l_var2 > 0) && (l_sum < 0)) { 150 | l_sum = (int32_t)0x7FFFFFFF; 151 | } 152 | } 153 | 154 | return l_sum; 155 | } 156 | 157 | static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) { 158 | int32_t l_diff; 159 | 160 | // Perform subtraction. 161 | l_diff = l_var1 - l_var2; 162 | 163 | if (l_var1 < 0) { // Check for underflow. 164 | if ((l_var2 > 0) && (l_diff > 0)) { 165 | l_diff = (int32_t)0x80000000; 166 | } 167 | } else { // Check for overflow. 168 | if ((l_var2 < 0) && (l_diff < 0)) { 169 | l_diff = (int32_t)0x7FFFFFFF; 170 | } 171 | } 172 | 173 | return l_diff; 174 | } 175 | #endif // #if !defined(MIPS_DSP_R1_LE) 176 | 177 | #endif // WEBRTC_SPL_SPL_INL_H_ 178 | -------------------------------------------------------------------------------- /src/spl_sqrt_floor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Wilco Dijkstra, 1996. The following email exchange establishes the 3 | * license. 4 | * 5 | * From: Wilco Dijkstra 6 | * Date: Fri, Jun 24, 2011 at 3:20 AM 7 | * Subject: Re: sqrt routine 8 | * To: Kevin Ma 9 | * Hi Kevin, 10 | * Thanks for asking. Those routines are public domain (originally posted to 11 | * comp.sys.arm a long time ago), so you can use them freely for any purpose. 12 | * Cheers, 13 | * Wilco 14 | * 15 | * ----- Original Message ----- 16 | * From: "Kevin Ma" 17 | * To: 18 | * Sent: Thursday, June 23, 2011 11:44 PM 19 | * Subject: Fwd: sqrt routine 20 | * Hi Wilco, 21 | * I saw your sqrt routine from several web sites, including 22 | * http://www.finesse.demon.co.uk/steven/sqrt.html. 23 | * Just wonder if there's any copyright information with your Successive 24 | * approximation routines, or if I can freely use it for any purpose. 25 | * Thanks. 26 | * Kevin 27 | */ 28 | 29 | // Minor modifications in code style for WebRTC, 2012. 30 | 31 | #include "signal_processing_library.h" 32 | 33 | /* 34 | * Algorithm: 35 | * Successive approximation of the equation (root + delta) ^ 2 = N 36 | * until delta < 1. If delta < 1 we have the integer part of SQRT (N). 37 | * Use delta = 2^i for i = 15 .. 0. 38 | * 39 | * Output precision is 16 bits. Note for large input values (close to 40 | * 0x7FFFFFFF), bit 15 (the highest bit of the low 16-bit half word) 41 | * contains the MSB information (a non-sign value). Do with caution 42 | * if you need to cast the output to int16_t type. 43 | * 44 | * If the input value is negative, it returns 0. 45 | */ 46 | 47 | #define WEBRTC_SPL_SQRT_ITER(N) \ 48 | try1 = root + (1 << (N)); \ 49 | if (value >= try1 << (N)) \ 50 | { \ 51 | value -= try1 << (N); \ 52 | root |= 2 << (N); \ 53 | } 54 | 55 | int32_t WebRtcSpl_SqrtFloor(int32_t value) 56 | { 57 | int32_t root = 0, try1; 58 | 59 | WEBRTC_SPL_SQRT_ITER (15); 60 | WEBRTC_SPL_SQRT_ITER (14); 61 | WEBRTC_SPL_SQRT_ITER (13); 62 | WEBRTC_SPL_SQRT_ITER (12); 63 | WEBRTC_SPL_SQRT_ITER (11); 64 | WEBRTC_SPL_SQRT_ITER (10); 65 | WEBRTC_SPL_SQRT_ITER ( 9); 66 | WEBRTC_SPL_SQRT_ITER ( 8); 67 | WEBRTC_SPL_SQRT_ITER ( 7); 68 | WEBRTC_SPL_SQRT_ITER ( 6); 69 | WEBRTC_SPL_SQRT_ITER ( 5); 70 | WEBRTC_SPL_SQRT_ITER ( 4); 71 | WEBRTC_SPL_SQRT_ITER ( 3); 72 | WEBRTC_SPL_SQRT_ITER ( 2); 73 | WEBRTC_SPL_SQRT_ITER ( 1); 74 | WEBRTC_SPL_SQRT_ITER ( 0); 75 | 76 | return root >> 1; 77 | } 78 | -------------------------------------------------------------------------------- /src/typedefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // This file contains platform-specific typedefs and defines. 12 | // Much of it is derived from Chromium's build/build_config.h. 13 | 14 | #ifndef WEBRTC_TYPEDEFS_H_ 15 | #define WEBRTC_TYPEDEFS_H_ 16 | 17 | // For access to standard POSIXish features, use WEBRTC_POSIX instead of a 18 | // more specific macro. 19 | #if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX) || \ 20 | defined(WEBRTC_ANDROID) 21 | #define WEBRTC_POSIX 22 | #endif 23 | 24 | // Processor architecture detection. For more info on what's defined, see: 25 | // http://msdn.microsoft.com/en-us/library/b0084kay.aspx 26 | // http://www.agner.org/optimize/calling_conventions.pdf 27 | // or with gcc, run: "echo | gcc -E -dM -" 28 | // TODO(andrew): replace WEBRTC_LITTLE_ENDIAN with WEBRTC_ARCH_LITTLE_ENDIAN. 29 | #if defined(_M_X64) || defined(__x86_64__) 30 | #define WEBRTC_ARCH_X86_FAMILY 31 | #define WEBRTC_ARCH_X86_64 32 | #define WEBRTC_ARCH_64_BITS 33 | #define WEBRTC_ARCH_LITTLE_ENDIAN 34 | #define WEBRTC_LITTLE_ENDIAN 35 | #elif defined(_M_IX86) || defined(__i386__) 36 | #define WEBRTC_ARCH_X86_FAMILY 37 | #define WEBRTC_ARCH_X86 38 | #define WEBRTC_ARCH_32_BITS 39 | #define WEBRTC_ARCH_LITTLE_ENDIAN 40 | #define WEBRTC_LITTLE_ENDIAN 41 | #elif defined(__ARMEL__) 42 | // TODO(andrew): We'd prefer to control platform defines here, but this is 43 | // currently provided by the Android makefiles. Commented to avoid duplicate 44 | // definition warnings. 45 | //#define WEBRTC_ARCH_ARM 46 | // TODO(andrew): Chromium uses the following two defines. Should we switch? 47 | //#define WEBRTC_ARCH_ARM_FAMILY 48 | //#define WEBRTC_ARCH_ARMEL 49 | #define WEBRTC_ARCH_32_BITS 50 | #define WEBRTC_ARCH_LITTLE_ENDIAN 51 | #define WEBRTC_LITTLE_ENDIAN 52 | #elif defined(__MIPSEL__) 53 | #define WEBRTC_ARCH_32_BITS 54 | #define WEBRTC_ARCH_LITTLE_ENDIAN 55 | #define WEBRTC_LITTLE_ENDIAN 56 | #else 57 | #error Please add support for your architecture in typedefs.h 58 | #endif 59 | 60 | #if defined(__SSE2__) || defined(_MSC_VER) 61 | #define WEBRTC_USE_SSE2 62 | #endif 63 | 64 | #if !defined(_MSC_VER) 65 | #include 66 | #else 67 | // Define C99 equivalent types, since MSVC doesn't provide stdint.h. 68 | typedef signed char int8_t; 69 | typedef signed short int16_t; 70 | typedef signed int int32_t; 71 | typedef __int64 int64_t; 72 | typedef unsigned char uint8_t; 73 | typedef unsigned short uint16_t; 74 | typedef unsigned int uint32_t; 75 | typedef unsigned __int64 uint64_t; 76 | #endif 77 | 78 | // Borrowed from Chromium's base/compiler_specific.h. 79 | // Annotate a virtual method indicating it must be overriding a virtual 80 | // method in the parent class. 81 | // Use like: 82 | // virtual void foo() OVERRIDE; 83 | #if defined(_MSC_VER) 84 | #define OVERRIDE override 85 | #elif defined(__clang__) 86 | // Clang defaults to C++03 and warns about using override. Squelch that. 87 | // Intentionally no push/pop here so all users of OVERRIDE ignore the warning 88 | // too. This is like passing -Wno-c++11-extensions, except that GCC won't die 89 | // (because it won't see this pragma). 90 | #pragma clang diagnostic ignored "-Wc++11-extensions" 91 | #define OVERRIDE override 92 | #else 93 | #define OVERRIDE 94 | #endif 95 | 96 | #endif // WEBRTC_TYPEDEFS_H_ 97 | -------------------------------------------------------------------------------- /src/vector_scaling_operations.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | 12 | /* 13 | * This file contains implementations of the functions 14 | * WebRtcSpl_VectorBitShiftW16() 15 | * WebRtcSpl_VectorBitShiftW32() 16 | * WebRtcSpl_VectorBitShiftW32ToW16() 17 | * WebRtcSpl_ScaleVector() 18 | * WebRtcSpl_ScaleVectorWithSat() 19 | * WebRtcSpl_ScaleAndAddVectors() 20 | * WebRtcSpl_ScaleAndAddVectorsWithRoundC() 21 | */ 22 | 23 | #include "signal_processing_library.h" 24 | 25 | void WebRtcSpl_VectorBitShiftW16(int16_t *res, int16_t length, 26 | const int16_t *in, int16_t right_shifts) 27 | { 28 | int i; 29 | 30 | if (right_shifts > 0) 31 | { 32 | for (i = length; i > 0; i--) 33 | { 34 | (*res++) = ((*in++) >> right_shifts); 35 | } 36 | } else 37 | { 38 | for (i = length; i > 0; i--) 39 | { 40 | (*res++) = ((*in++) << (-right_shifts)); 41 | } 42 | } 43 | } 44 | 45 | void WebRtcSpl_VectorBitShiftW32(int32_t *out_vector, 46 | int16_t vector_length, 47 | const int32_t *in_vector, 48 | int16_t right_shifts) 49 | { 50 | int i; 51 | 52 | if (right_shifts > 0) 53 | { 54 | for (i = vector_length; i > 0; i--) 55 | { 56 | (*out_vector++) = ((*in_vector++) >> right_shifts); 57 | } 58 | } else 59 | { 60 | for (i = vector_length; i > 0; i--) 61 | { 62 | (*out_vector++) = ((*in_vector++) << (-right_shifts)); 63 | } 64 | } 65 | } 66 | 67 | void WebRtcSpl_VectorBitShiftW32ToW16(int16_t* out, int length, 68 | const int32_t* in, int right_shifts) { 69 | int i; 70 | int32_t tmp_w32; 71 | 72 | if (right_shifts >= 0) { 73 | for (i = length; i > 0; i--) { 74 | tmp_w32 = (*in++) >> right_shifts; 75 | (*out++) = WebRtcSpl_SatW32ToW16(tmp_w32); 76 | } 77 | } else { 78 | int16_t left_shifts = -right_shifts; 79 | for (i = length; i > 0; i--) { 80 | tmp_w32 = (*in++) << left_shifts; 81 | (*out++) = WebRtcSpl_SatW32ToW16(tmp_w32); 82 | } 83 | } 84 | } 85 | 86 | void WebRtcSpl_ScaleVector(const int16_t *in_vector, int16_t *out_vector, 87 | int16_t gain, int16_t in_vector_length, 88 | int16_t right_shifts) 89 | { 90 | // Performs vector operation: out_vector = (gain*in_vector)>>right_shifts 91 | int i; 92 | const int16_t *inptr; 93 | int16_t *outptr; 94 | 95 | inptr = in_vector; 96 | outptr = out_vector; 97 | 98 | for (i = 0; i < in_vector_length; i++) 99 | { 100 | (*outptr++) = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(*inptr++, gain, right_shifts); 101 | } 102 | } 103 | 104 | void WebRtcSpl_ScaleVectorWithSat(const int16_t *in_vector, int16_t *out_vector, 105 | int16_t gain, int16_t in_vector_length, 106 | int16_t right_shifts) 107 | { 108 | // Performs vector operation: out_vector = (gain*in_vector)>>right_shifts 109 | int i; 110 | int32_t tmpW32; 111 | const int16_t *inptr; 112 | int16_t *outptr; 113 | 114 | inptr = in_vector; 115 | outptr = out_vector; 116 | 117 | for (i = 0; i < in_vector_length; i++) 118 | { 119 | tmpW32 = WEBRTC_SPL_MUL_16_16_RSFT(*inptr++, gain, right_shifts); 120 | (*outptr++) = WebRtcSpl_SatW32ToW16(tmpW32); 121 | } 122 | } 123 | 124 | void WebRtcSpl_ScaleAndAddVectors(const int16_t *in1, int16_t gain1, int shift1, 125 | const int16_t *in2, int16_t gain2, int shift2, 126 | int16_t *out, int vector_length) 127 | { 128 | // Performs vector operation: out = (gain1*in1)>>shift1 + (gain2*in2)>>shift2 129 | int i; 130 | const int16_t *in1ptr; 131 | const int16_t *in2ptr; 132 | int16_t *outptr; 133 | 134 | in1ptr = in1; 135 | in2ptr = in2; 136 | outptr = out; 137 | 138 | for (i = 0; i < vector_length; i++) 139 | { 140 | (*outptr++) = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(gain1, *in1ptr++, shift1) 141 | + (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(gain2, *in2ptr++, shift2); 142 | } 143 | } 144 | 145 | // C version of WebRtcSpl_ScaleAndAddVectorsWithRound() for generic platforms. 146 | int WebRtcSpl_ScaleAndAddVectorsWithRoundC(const int16_t* in_vector1, 147 | int16_t in_vector1_scale, 148 | const int16_t* in_vector2, 149 | int16_t in_vector2_scale, 150 | int right_shifts, 151 | int16_t* out_vector, 152 | int length) { 153 | int i = 0; 154 | int round_value = (1 << right_shifts) >> 1; 155 | 156 | if (in_vector1 == NULL || in_vector2 == NULL || out_vector == NULL || 157 | length <= 0 || right_shifts < 0) { 158 | return -1; 159 | } 160 | 161 | for (i = 0; i < length; i++) { 162 | out_vector[i] = (int16_t)(( 163 | WEBRTC_SPL_MUL_16_16(in_vector1[i], in_vector1_scale) 164 | + WEBRTC_SPL_MUL_16_16(in_vector2[i], in_vector2_scale) 165 | + round_value) >> right_shifts); 166 | } 167 | 168 | return 0; 169 | } 170 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | LOCAL_PATH=$(notdir $(shell pwd)) 2 | CFILES=$(shell find ./ -maxdepth 1 -name "*.c") 3 | CXXFILES=$(shell find ./ -maxdepth 1 -name "*.cc") 4 | OBJS=$(CFILES:%.c=%.o) $(CXXFILE:%.cc=%.o) 5 | 6 | .PHONY:all clean 7 | 8 | 9 | ifneq ($(OBJS),) 10 | LIBS= aec m pthread 11 | LDLIBS += $(addprefix -l,$(LIBS)) 12 | 13 | 14 | aec:$(OBJS) 15 | $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) 16 | 17 | include $r/tools/Makefile.rule 18 | -include $(OBJS:%.o=%.d) 19 | -include $(OBJS:%.o=%.d) 20 | else 21 | $(error 该目录下没有文件可以生成.o) 22 | endif 23 | -------------------------------------------------------------------------------- /test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(void){ 6 | void *aecInst; 7 | if(-1 == WebRtcAecm_Create(&aecInst)){ 8 | perror("WebRtcAec_Create:"); 9 | exit(1); 10 | } 11 | if(-1 == WebRtcAecm_Init(aecInst,8000)){ 12 | perror("WebRtcAec_Init:"); 13 | exit(1); 14 | } 15 | WebRtcAecm_Free(aecInst); 16 | 17 | printf("hello webRTC\n"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /tools/Makefile: -------------------------------------------------------------------------------- 1 | LOCAL_PATH=$(notdir $(shell pwd)) 2 | CFILES=$(shell find ./ -maxdepth 1 -name "*.c") 3 | CXXFILES=$(shell find ./ -maxdepth 1 -name "*.cc") 4 | OBJS = $(CFILES:%.c=%.o) $(CXXFILES:%.cc=%.o) 5 | 6 | .PHONY:all clean 7 | 8 | 9 | ifneq ($(OBJS),) 10 | OBJ=$r/lib/lib$(LOCAL_PATH).a 11 | all:$(OBJ) 12 | 13 | $(OBJ):$(OBJS) 14 | ar -r $@ $^ 15 | 16 | include $r/tools/Makefile.rule 17 | -include $(OBJS:%.o=%.d) 18 | -include $(OBJS:%.o=%.d) 19 | else 20 | $(error 该目录下没有文件可以生成.o) 21 | endif 22 | -------------------------------------------------------------------------------- /tools/Makefile.rule: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 项目编译规则文件,其他目录引用该文件的规则来编译。这种用法来自BlueLab。 4 | # 一个把消息机制用得非常烂的蓝牙开发平台。 5 | .PHONY: clean 6 | i = $r/include $r/lib 7 | l = $r/lib 8 | 9 | vpath %.h $i 10 | vpath %.a $l 11 | 12 | AR = ar 13 | CC = gcc 14 | CXX = g++ 15 | LD = ld 16 | RM =rm -f 17 | MAKE = make 18 | 19 | CFLAGS += $(addprefix -I,$i) -std=gnu99 -g 20 | CXXFLAGS += $(addprefix -I,$i) -g 21 | 22 | #-Wall -Werror 23 | LDFLAGS += $(addprefix -L,$l) -g 24 | 25 | ifndef r 26 | $(error 未定义根目录,如果你不想定义,看看/目录下,相信你会改变这个主意的.你能看到目录的原因是rm 没有-rf!) 27 | endif 28 | 29 | 30 | %.o:%.c 31 | @$(CC) -c $< $(CFLAGS) -MD -MP -MT"$(@:%.o=%.d)" -MT"$@" -o $@ 32 | 33 | %.o:%.cc 34 | @$(CXX) -c $< $(CXXFLAGS) -MD -MP -MT"$(@:%.o=%.d)" -MT"$@" -o $@ 35 | 36 | %.a:%.o 37 | @$(AR) -r $@ $^ 38 | 39 | clean: 40 | -$(RM) *.out *.o *.d 41 | -------------------------------------------------------------------------------- /tools/am.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 递归扫描目录,在包含*.c的目录下生成Makefile文件,该makefile包含/tools/Makefile # 4 | # 生成的Makefile将最后的目录做为库名,将目录下的所有.c编译成.o添加到库里 5 | # 6 | 7 | 8 | ########### 生成库 ############### 9 | #常常将Makefile写成Makfile,弄个变量保存,防止出现这样低级的错误 10 | mf=Makefile 11 | function spitMakefile() 12 | { 13 | #目录切换 14 | cd 15 | local src=`ls *.c 2>/dev/null` 16 | if [ ! -z "$src" ];then 17 | echo "在生成Makfile文件" 18 | echo "# 静态库的编译,该Makefile由脚本自动生成" > $mf 19 | echo "">>$mf 20 | echo "">>$mf 21 | echo "# 下面是将要被添加进库的文件" >> $mf 22 | echo ".PHONY:all" >> $mf 23 | echo "sources=\\" >> $mf 24 | for file in $src;do 25 | if [ -f "$file" ];then 26 | echo " $file\\" >> $mf 27 | fi 28 | done 29 | echo "" >> $mf 30 | echo "# 最终生成文件,使用隐含规则" >> $mf 31 | echo "all:\$r/lib/lib.a" >> $mf 32 | echo "" >> $mf 33 | echo "\$r/lib/lib.a:\$(sources:%.c=%.o)" >> $mf 34 | echo "" >> $mf 35 | echo "include \$r/tools/Makefile" >> $mf 36 | echo "-include \$(sources:%.c=%.d)" >> $mf 37 | fi 38 | cd .. # 回到上层目录 39 | } 40 | 41 | ## 递归扫描目录 42 | # 听说不推荐使用递归,我讨厌那些允许你做,却极力不推荐你做的语言,听说lisp就是鼓励你怎么想就怎么做,不要做语言的奴隶 43 | # 不推荐递归的语言不是好语言 44 | function rEachDir() 45 | { 46 | if [ ! -z "" ];then 47 | cd 48 | fi 49 | local dirs=`ls -d */ 2>/dev/null` 50 | if [ ! -z "$dirs" ];then 51 | for i in $dirs;do 52 | rEachDir $i 53 | done 54 | fi 55 | if [ ! -z "" ];then 56 | cd .. 57 | fi 58 | spitMakefile `echo |tr -d '/'` 59 | } 60 | 61 | if [ ! -z "" ];then 62 | rEachDir 63 | else 64 | echo "Uase $0 path" 65 | fi 66 | --------------------------------------------------------------------------------