Repository: Baidu-AIP/speech-vad-demo Branch: master Commit: 8a9906246e6d Files: 67 Total size: 347.0 KB Directory structure: gitextract_iq5s0_a2/ ├── .gitignore ├── CMakeLists.txt ├── README.md ├── build_and_run.sh ├── src/ │ ├── common.h │ ├── file_cut.c │ ├── file_cut.h │ ├── main.c │ ├── period_format.c │ ├── period_format.h │ ├── simple_vad.c │ └── simple_vad.h ├── thirdparty/ │ └── webrtc/ │ ├── BUILD.gn │ ├── common_audio/ │ │ ├── rename.sh │ │ ├── rename.sh~ │ │ ├── signal_processing/ │ │ │ ├── cross_correlation.c │ │ │ ├── cross_correlation_mips.c.mips │ │ │ ├── cross_correlation_neon.c.neon │ │ │ ├── division_operations.c │ │ │ ├── downsample_fast.c │ │ │ ├── downsample_fast_mips.c.mips │ │ │ ├── downsample_fast_neon.c.neon │ │ │ ├── energy.c │ │ │ ├── get_scaling_square.c │ │ │ ├── include/ │ │ │ │ ├── real_fft.h │ │ │ │ ├── signal_processing_library.h │ │ │ │ ├── spl_inl.h │ │ │ │ ├── spl_inl_armv7.h │ │ │ │ └── spl_inl_mips.h │ │ │ ├── min_max_operations.c │ │ │ ├── min_max_operations_mips.c.mips │ │ │ ├── min_max_operations_neon.c.neon │ │ │ ├── resample_48khz.c │ │ │ ├── resample_by_2_internal.c │ │ │ ├── resample_by_2_internal.h │ │ │ ├── resample_fractional.c │ │ │ ├── spl_init.c │ │ │ ├── vector_scaling_operations.c │ │ │ └── vector_scaling_operations_mips.c.mips │ │ └── vad/ │ │ ├── include/ │ │ │ ├── vad.h │ │ │ └── webrtc_vad.h │ │ ├── mock/ │ │ │ └── mock_vad.h │ │ ├── vad.cc │ │ ├── vad_core.c │ │ ├── vad_core.h │ │ ├── vad_core_unittest.cc │ │ ├── vad_filterbank.c │ │ ├── vad_filterbank.h │ │ ├── vad_filterbank_unittest.cc │ │ ├── vad_gmm.c │ │ ├── vad_gmm.h │ │ ├── vad_gmm_unittest.cc │ │ ├── vad_sp.c │ │ ├── vad_sp.h │ │ ├── vad_sp_unittest.cc │ │ ├── vad_unittest.cc │ │ ├── vad_unittest.h │ │ └── webrtc_vad.c │ ├── rtc_base/ │ │ ├── checks.cc │ │ ├── checks.h │ │ ├── compile_assert_c.h │ │ ├── numerics/ │ │ │ └── safe_compare.h │ │ ├── sanitizer.h │ │ └── type_traits.h │ ├── system_wrappers/ │ │ └── include/ │ │ └── cpu_features_wrapper.h │ └── typedefs.h └── valgrind.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ pcm/ build/ output_pcm/ .vscode/ vad-demo* ================================================ FILE: CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) set(CMAKE_VERBOSE_MAKEFILE on) project(vad-demo) set(CMAKE_BUILD_TYPE DEBUG) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #set(CMAKE_C_STANDARD 99) file(GLOB SRC_FILES src/*.c src/*.h thirdparty/webrtc/common_audio/*/*.c thirdparty/webrtc/rtc_base/*.c*) include_directories(thirdparty/webrtc) #thirdparty/include/webrtc add_executable(vad-demo ${SRC_FILES}) target_link_libraries(vad-demo pthread) ================================================ FILE: README.md ================================================ # speech-vad-demo ## 简介 ### 简介 项目地址: https://github.com/Baidu-AIP/speech-vad-demo 集成 [webrtc](https://webrtc.org/) 开源项目,vad模块,具体算法*GMM*(Gaussian Mixture Model)。 由于百度rest api接口有60s的音频时长限制,使用此demo可以粗略地按照静音切分音频。 ### 原理 一个FRAME时长默认10s,通过webrtc的vad计算这个FRAME是否是活动(ACTIVE: 有声音, INACTIVE,静音)。 这样可以获得音频的所有FRAME的活动值(ACTIVE或者INACTIVE)。从而在静音(INACTIVE)的音频段上的切分音频。 ### 运行环境 - g++ 4.8以上, - cmake 2.8 及 make 3.8 编译需要,可以跳过或者尝试使用低版本 - 任意操作系统 如果没有g++ 4.8的版本,centos可以参考“Linux C++ SDK”的文档,进行g++ 4.8的安装。 由于webrtc项目vad模块依赖于rtc_base模块 进行运行时的参数检查,因此需要可以编译rtc_base的。 如果您无法升级到g++ 4.8 或者是只能编译C项目,可以自行修改源代码,删除rtc_bas目录,及其它文件对rtc_base中宏的依赖,,剩余文件均为C代码。去除后请详细测试。 ## 运行及结果 ### 运行命令 Linux: ```bash # 确认g++ 和cmake 版本 sh build_and_run.sh # 或 cmake . && make ``` Windows: Windows 安装 cygwin,及cygwin 中 下载cmake make gcc g++等编译软件 ```bat sh build_and_run.sh # 或 cmake . && make ``` ### 结果 如果不修改代码的话,结果保存在 output_pcm 内。 文件名如下 ``` 16k_1.pcm_0-12989_A.pcm // 第0-12989毫秒的音频, 16k_1.pcm_33730-47389_A.pcm // 第33730-47389毫秒的音频 16k_1.pcm_0-4049_A.pcm // A 表示此段有声音,不是完全的静音 ··· 16k_1.pcm_114060-121689_I.pcm // I 表示此段都是静音 ``` ## 参数设置 ### common.h ```c // MULTI = 1 2 3 webrtc vad可以设置分别为以10ms 20ms 30ms作为包 #define MULTI 1 // VAD 模式 Aggressiveness mode (0, 1, 2, or 3). 数值越大,判断越是粗略,连着的静音或者响声增多 #define WEBRTC_VAD_MODE 3 // 有声音的音频段,xxx 毫秒后,认为该音频段结束,不能为0 #define FILE_CUT_SILENCE_AFTER_ACTIVE_MS 500 // 静音的音频段,切分xxx毫秒给之后有声音的音频段 #define FILE_CUT_SILENCE_BEFORE_ACTIVE_MS 300 // 最小的音频切分长度,即每个切分后音频文件不少于这个时长,最后一个除外 #define FILE_CUT_MIN_MS (10 * 1000) // 最大的音频切分长度,即每个切分后音频文件不多于这个时长 #define FILE_CUT_MAX_MS (60 * 1000) /** 上述示例中音频文件尽可能依次满足如下条件 1. 最短10s,最长 60s。 2. 每个音频文件的最后的静音500ms, 2. 每个音频文件的开始的静300ms。 */ ``` ### 切割逻辑修改 demo因为考虑到流式,采用了尽快切割的方法。如果您对这个切割算法不满意的话,可以对照periods_print的结果, 自行修改file_cut.c内的代码逻辑 ```c // [5150, 5220) [5230, 6380) [6520, 6970) [7000, 8040) [8080, 8670) // 表示 [5150, 5220) 等区间内是有声音的,其它区间均为静音, // 如果需要切割的话,应该在静音区间选择合适的位置切割 ``` ================================================ FILE: build_and_run.sh ================================================ #!/usr/bin/env bash set -uex check_version(){ CMD=$1 OPT=$2 VERSION=$3 #$CMD $OPT RES=$($CMD $OPT |head -1) echo $RES } check_version "gcc" "--version" "4.8.2" check_version "cmake" "--version" "2.8" sleep 2; echo "" mkdir -p build && \ mkdir -p output_pcm && \ rm -rf output_pcm/* build/* && \ cd build && \ cmake .. && \ make -j4 && \ cp vad-demo .. && cd .. && \ echo "build success wait 3s to run" && \ sleep 3 && \ ./vad-demo ================================================ FILE: src/common.h ================================================ // // Created by fu on 3/7/18. // #ifndef VAD_DEMO_COMMON_H #define VAD_DEMO_COMMON_H #include // MULTI = 1 2 3 webrtc vad可以设置分别为以10ms 20ms 30ms作为包 #define MULTI 1 // VAD 模式 Aggressiveness mode (0, 1, 2, or 3). 数值越大,判断越是粗略,连着的静音或者响声增多 #define WEBRTC_VAD_MODE 3 // 有声音的音频段,xxx 毫秒后,认为该音频段结束,不能为0 #define FILE_CUT_SILENCE_AFTER_ACTIVE_MS 500 // 静音的音频段,切分xxx毫秒给之后有声音的音频段 #define FILE_CUT_SILENCE_BEFORE_ACTIVE_MS 300 // 最小的音频切分长度,即每个切分后音频文件不少于这个时长,最后一个除外 #define FILE_CUT_MIN_MS (10 * 1000) // 最大的音频切分长度,即每个切分后音频文件不多于这个时长 #define FILE_CUT_MAX_MS (60 * 1000) //16000 采样率固定 #define SAMPLE_RATE 16000 // 用于period_format.h #define PERIODS_SIZE_INITIED 100 #define FRAME_SIZE (16 * MULTI * 10 ) #define CAL_TIME_BY_FRAME(frame) (MULTI * 10 * frame) #define CAL_FRAME_BY_TIME(time) (time / (MULTI * 10)) /*` uint64_t inline CAL_TIME_BY_FRAME(int frame){ return MULTI * frame * 10; }; int inline CAL_FRAME_BY_TIME(uint64_t time){ return time / (MULTI * 10); }; */ #endif //VAD_DEMO_COMMON_H ================================================ FILE: src/file_cut.c ================================================ // // Created by fu on 3/7/18. // #include #include "file_cut.h" // static size_t file_total = 0; static inline int cut_write_file(struct cut_info *cut, int frames) { int size = frames * FRAME_SIZE ; uint16_t buffer[size]; int readed = fread(buffer, sizeof(uint16_t), size, cut->fp); if (readed > 0) { FILE *res_file = fopen(cut->result_filename, "wb+"); if (res_file == NULL) { fprintf(stderr, "file open failed, %s\n", cut->result_filename); return 3; } int written = fwrite(buffer, sizeof(uint16_t), readed, res_file); fclose(res_file); if (written != readed) { fprintf(stderr, "written is %d, readed is %d\n", written, readed); return 2; } // file_total += written; // printf("file write success, %s, written %d\n", cut->result_filename, written); return 0; } else { return 1; } } static inline int cut_frame(struct cut_info *cut, int last_frame, int force) { int frames = last_frame - cut->cut_begin_frame; if (force || (frames >= CAL_FRAME_BY_TIME(FILE_CUT_MIN_MS))) { if (last_frame == 109) { printf("%d", 109); } //printf("cut file at frame: %d\n", last_frame); snprintf(cut->result_filename, sizeof(cut->result_filename), "%s/%s_%ld-%ld_%s.pcm", cut->output_file_dir, cut->output_filename_prefix, CAL_TIME_BY_FRAME(cut->cut_begin_frame), CAL_TIME_BY_FRAME(last_frame) - 1, cut->is_contain_active ? "A" : "I"); cut_write_file(cut, frames); cut->is_pervious_active = 0; cut->is_contain_active = 0; cut->cut_begin_frame = last_frame; return 0; } else { return 1; } } static inline int add_continued(struct cut_info *cut, int is_active) { if (!is_active && cut->is_contain_active) { // 有响声,之后连续静音 int diff = cut->previous_along_frames - CAL_FRAME_BY_TIME(FILE_CUT_SILENCE_AFTER_ACTIVE_MS); if (diff >= 0) { int res = cut_frame(cut, cut->current_frame, 0); if (res == 0) { int frame = -1 * (cut->current_frame); cut->previous_along_frames = 1; return frame; } } } cut->previous_along_frames++; return 0; } static inline int add_changed(struct cut_info *cut, int is_active) { int frame = 0; if (is_active) { // 连续静音,之后遇到响声 if (cut->previous_along_frames > CAL_FRAME_BY_TIME(FILE_CUT_SILENCE_BEFORE_ACTIVE_MS)) { int c_frames = cut->current_frame - CAL_FRAME_BY_TIME(FILE_CUT_SILENCE_BEFORE_ACTIVE_MS); int res = cut_frame(cut, c_frames, 0); if (res == 0) { frame = -1 * (c_frames); } // cut->previous_along_frames = FILE_CUT_SILENCE_AFTER_ACTIVE_MS; } } cut->previous_along_frames = 1; return frame; } struct cut_info *cut_info_create(FILE *fp) { struct cut_info *cut = calloc(1, sizeof(struct cut_info)); cut->fp = fp; return cut; } int cut_add_vad_activity(struct cut_info *cut, int is_active, int is_last) { int res; if (is_last || (cut->current_frame - cut->cut_begin_frame == CAL_FRAME_BY_TIME(FILE_CUT_MAX_MS))) { cut_frame(cut, cut->current_frame, is_last); res = -1 * cut->current_frame; } else if (cut->is_pervious_active == is_active) { res = add_continued(cut, is_active); } else { res = add_changed(cut, is_active); if (is_active) { cut->is_contain_active = 1; } } cut->is_pervious_active = is_active; cut->current_frame++; return res; } void cut_info_free(struct cut_info *cut) { free(cut); } void cut_info_print(struct cut_info *cut) { printf("%s, %s, %d, frame %d\n", cut->is_pervious_active ? "PA" : "PI", cut->is_contain_active ? "CA" : "CI", cut->previous_along_frames, cut->current_frame); } ================================================ FILE: src/file_cut.h ================================================ // // Created by fu on 3/7/18. // #ifndef VAD_DEMO_FILE_CUT_H #define VAD_DEMO_FILE_CUT_H #include #include "common.h" #include "stdint.h" struct cut_info { int is_pervious_active; int is_contain_active; int previous_along_frames; FILE *fp; int current_frame; int cut_begin_frame; char result_filename[200]; char output_file_dir[100]; char output_filename_prefix[100]; }; struct cut_info *cut_info_create(FILE *fp); int cut_add_vad_activity(struct cut_info *cut, int is_active, int is_last); void cut_info_free(struct cut_info *cut); void cut_info_print(struct cut_info *cut); #endif //VAD_DEMO_FILE_CUT_H /** struct cut_info *cut = cut_create_info(NULL); int acts[] = {0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}; int len = sizeof(acts) / sizeof(int); int is_cuts[len]; printf(" acts length: %d\n", len); int j, k; for (k = 0; k < len; k++) { printf("%d ", acts[k]); is_cuts[k] = 0; } printf("\n"); for (k = 0; k < len; k++) { printf("\n"); int res = cut_add_vad_activity(cut, acts[k], k == len - 1); cut_info_print(cut); if (res < 0) { is_cuts[-1 * res] = 1; } for (j = 0; j <= k; j++) { if (is_cuts[j]) { printf("| "); } printf("%d ", acts[j]); } } printf("\n"); for (j = 0; j <= k; j++) { if (is_cuts[j]) { printf("| "); } printf("%d ", acts[j]); } printf("\n"); printf("PROGRAM FINISH\n"); **/ ================================================ FILE: src/main.c ================================================ #include #include #include #include "simple_vad.h" #include "period_format.h" #include "file_cut.h" // 16000 采样率 10ms, 大小 = 160 * 16bits/8 = 320字节 , int run(FILE *fp, simple_vad *vad, struct cut_info *cut); int add_period_activity(struct periods *per, int is_active, int is_last); //int add_cut_file_activity(struct cut_info *cut, int is_active, int is_last); int main() { const char filename[] = "pcm/16k_1.pcm"; // 读取的文件 const char output_filename_prefix[] = "16k_1.pcm"; // 保存的文件名 const char output_dir[] = "output_pcm"; // 保存的目录 FILE *fp = fopen(filename, "rb"); if (fp == NULL) { fprintf(stderr, "%s does not exist\n", filename); return 3; } simple_vad *vad = simple_vad_create(); if (vad == NULL) { return 4; } FILE *fp2 = fopen(filename, "rb"); struct cut_info *cut = cut_info_create(fp2); snprintf(cut->output_filename_prefix, sizeof(cut->output_filename_prefix), "%s", output_filename_prefix); snprintf(cut->output_file_dir, sizeof(cut->output_file_dir), "%s", output_dir); int res = run(fp, vad, cut); fclose(fp); fclose(fp2); simple_vad_free(vad); cut_info_free(cut); printf("PROGRAM FINISH\n"); return res; } int run(FILE *fp, simple_vad *vad, struct cut_info *cut) { int16_t data[FRAME_SIZE]; int res = 0; struct periods *per = periods_create(); while (res == 0) { res = read_int16_bytes(fp, data); if (res <= 1) { int is_last = (res == 1); int is_active = process_vad(vad, data); add_period_activity(per, is_active, is_last); int vad_file_res = cut_add_vad_activity(cut, is_active, is_last); if (vad_file_res < 0) { printf("file write success %s\n", cut->result_filename); } } else if (ferror(fp)) { printf("read failed ferror result : %d\n", ferror(fp)); } } periods_free(per); if (res != 1) { fprintf(stderr, "read file error %d\n", res); return res; } return 0; } int add_period_activity(struct periods *per, int is_active, int is_last) { static int old_is_active = 0; static int count = 0; int res_add = period_add_vad_activity(per, is_active, is_last); if (res_add != 0) { return res_add; } if (is_active != old_is_active) { // printf("%s,%d \n", old_is_active ? "A" : "I", count); // I,1 表示之前的1个FRAME是 INACTIVE的; // I,1 A,10 表示之前的1个FRAME是 INACTIVE的;第2-10个FRAME是ACTIVE的 // periods_print(per); old_is_active = is_active; } count += 1; if (is_last) { periods_print(per); printf("total frames %d\n", count); } } ================================================ FILE: src/period_format.c ================================================ // // Created by fu on 3/6/18. // #ifdef __APPLE__ #include #else #include #endif #include "common.h" #include "period_format.h" static int add_period_start(struct periods *per) { per->size++; if (per->size > per->size_allocated) { size_t new_size = per->size_allocated * 2 * sizeof(uint64_t); per->period_start = realloc(per->period_start, new_size); if (per->period_start == NULL) { fprintf(stderr, "per->period_start allocated failed %ld", new_size); return 1; } per->period_end = realloc(per->period_end, new_size); if (per->period_end == NULL) { fprintf(stderr, "per->period_end allocated failed %ld", new_size); return 2; } per->size_allocated *= 2; } uint64_t start_time = CAL_TIME_BY_FRAME(per->current_frame); per->period_start[per->size - 1] = start_time; per->is_end_filled = 0; return 0; } static void add_period_end(struct periods *per) { size_t end_time = CAL_TIME_BY_FRAME(per->current_frame); per->period_end[per->size - 1] = end_time; per->is_end_filled = 1; } struct periods *periods_create() { struct periods *per = calloc(1, sizeof(struct periods)); if (per == NULL) { fprintf(stderr, "per alloc failed"); return NULL; } per->period_start = calloc(PERIODS_SIZE_INITIED, sizeof(uint64_t)); if (per->period_start == NULL) { fprintf(stderr, "per->period_start alloc failed"); } else { per->period_end = calloc(PERIODS_SIZE_INITIED, sizeof(uint64_t)); if (per->period_end == NULL) { fprintf(stderr, "per->period_start alloc failed"); } else { per->size_allocated = PERIODS_SIZE_INITIED; return per; } } return NULL; } void periods_print(struct periods *per) { int size = per->size; int is_ended_fill = per->is_end_filled; printf("PERIODS SIZE :%d, is_end_filled:%s ", size, is_ended_fill ? "true" : "false"); int i; for (i = 0; i < size; i++) { if ((i != size - 1) || is_ended_fill) { printf("[%ld, %ld] ", per->period_start[i], per->period_end[i]); } else { printf("[%ld, N]", per->period_start[size]); } } // printf("size %ld allocated %ld", per->size, per->size_allocated); printf("\n"); } int period_add_vad_activity(struct periods *per, int is_active, int is_last) { if (!per->is_pervious_active && is_active) { int res = add_period_start(per); if (res != 0) { return res; } per->is_pervious_active = is_active; } else if (per->is_pervious_active && (!is_active || is_last)) { add_period_end(per); per->is_pervious_active = is_active; } per->current_frame++; return 0; } void periods_free(struct periods *per) { free(per->period_start); free(per->period_end); free(per); } ================================================ FILE: src/period_format.h ================================================ // // 收集和打印非静音的声音段 // Created by fu on 3/6/18. // #ifndef VAD_DEMO_PERIOD_FORMAT_H #define VAD_DEMO_PERIOD_FORMAT_H #include "simple_vad.h" struct periods { int is_pervious_active; size_t current_frame; uint64_t *period_start; uint64_t *period_end; int size; size_t size_allocated; int is_end_filled; }; struct periods *periods_create(); /** * @brief * @param per * @param is_active 是否是有声音的FRAME * @param is_last 是否是最后一个FRAME * @return */ int period_add_vad_activity(struct periods *per, int is_active, int is_last); void periods_free(struct periods *per); void periods_print(struct periods *per); /* * 测试例子 * struct periods *per=periods_create(); period_add_vad_activity(per,1,0); period_add_vad_activity(per,1,0); periods_print(per); period_add_vad_activity(per,0,0); periods_print(per); period_add_vad_activity(per,1,0); periods_print(per); period_add_vad_activity(per,0,0); period_add_vad_activity(per,0,0); period_add_vad_activity(per,0,0); periods_print(per); period_add_vad_activity(per,1,0); period_add_vad_activity(per,1,1); periods_print(per); periods_free(per); */ #endif //VAD_DEMO_PERIOD_FORMAT_H ================================================ FILE: src/simple_vad.c ================================================ // // Created by fu on 3/6/18. // #include "simple_vad.h" #include static int check_end_file(FILE *fp) { if (feof(fp)) { return 0; } return ferror(fp); } int read_int16_bytes(FILE *fp, int16_t *output) { if (feof(fp)) { return 1; } size_t readed = fread(output, sizeof(int16_t), FRAME_SIZE, fp); if (readed <= 0) { int res = check_end_file(fp); return (res == 0) ? 1 : 1000 + res; } if (readed < FRAME_SIZE) { memset(output + readed, 0, (FRAME_SIZE - readed) * sizeof(int16_t)); // printf("only %ld bits, will refill to %ld\n", readed, length); } return 0; } simple_vad *simple_vad_create() { VadInst *inst = WebRtcVad_Create(); int res = WebRtcVad_Init(inst); if (res != 0) { fprintf(stderr, "WebRtcVad_Init failed %d", res); return NULL; } res = WebRtcVad_set_mode(inst, WEBRTC_VAD_MODE); if (res != 0) { fprintf(stderr, "WebRtcVad_set_mode failed %d", res); WebRtcVad_Free(inst); return NULL; } return inst; } int process_vad(VadInst *inst, int16_t *data) { int res = WebRtcVad_Process(inst, SAMPLE_RATE, data, FRAME_SIZE); return res; } void simple_vad_free(simple_vad *inst) { WebRtcVad_Free(inst); } ================================================ FILE: src/simple_vad.h ================================================ // // 包装webrtc 的gmm vad算法 // // Created by fu on 3/6/18. // #ifndef VAD_DEMO_FILE_READ_H #define VAD_DEMO_FILE_READ_H #include #include #include #include "common.h" // 一个FRAME代表的时长。MULTI=1: 10ms;MULTI=2: 20ms;MULTI=3: 30ms; // FRAME_SIZE = 160 * MULTI = SAMPLE_RATE /1000 * MULTI , typedef VadInst simple_vad; /** * @brief 读取int16_t的数组 * @param fp * @param output * @return 0 正常 1 文件结束 , 1000+ferror : 文件错误 */ int read_int16_bytes(FILE *fp, int16_t *output); /** * @brief * @return NULL 创建失败 */ simple_vad *simple_vad_create(); /** * @brief * @param inst * @param data 例如read_int16_bytes读取的数据 * @return */ int process_vad(VadInst *inst, int16_t *data); /** * @brief * @param inst */ void simple_vad_free(simple_vad *inst); #endif //VAD_DEMO_FILE_READ_H ================================================ FILE: thirdparty/webrtc/BUILD.gn ================================================ # Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. # # Use of this source code is governed by a BSD-style license # that can be found in the LICENSE file in the root of the source # tree. An additional intellectual property rights grant can be found # in the file PATENTS. All contributing project authors may # be found in the AUTHORS file in the root of the source tree. # This is the root build file for GN. GN will start processing by loading this # file, and recursively load all dependencies until all dependencies are either # resolved or known not to exist (which will cause the build to fail). So if # you add a new build file, there must be some path of dependencies from this # file to your new one or GN won't know about it. import("//build/config/linux/pkg_config.gni") import("//build/config/sanitizers/sanitizers.gni") import("webrtc.gni") if (!build_with_mozilla) { import("//third_party/protobuf/proto_library.gni") } if (is_android) { import("//build/config/android/config.gni") import("//build/config/android/rules.gni") } if (!build_with_chromium) { # This target should (transitively) cause everything to be built; if you run # 'ninja default' and then 'ninja all', the second build should do no work. group("default") { testonly = true deps = [ ":webrtc", ] if (rtc_build_examples) { deps += [ "examples" ] } if (rtc_build_tools) { deps += [ "rtc_tools" ] } if (rtc_include_tests) { deps += [ ":rtc_unittests", ":video_engine_tests", ":webrtc_nonparallel_tests", ":webrtc_perf_tests", "common_audio:common_audio_unittests", "common_video:common_video_unittests", "media:rtc_media_unittests", "modules:modules_tests", "modules:modules_unittests", "modules/audio_coding:audio_coding_tests", "modules/audio_processing:audio_processing_tests", "modules/remote_bitrate_estimator:bwe_simulations_tests", "modules/rtp_rtcp:test_packet_masks_metrics", "modules/video_capture:video_capture_internal_impl", "ortc:ortc_unittests", "pc:peerconnection_unittests", "pc:rtc_pc_unittests", "rtc_base:rtc_base_tests_utils", "stats:rtc_stats_unittests", "system_wrappers:system_wrappers_unittests", "test", "video:screenshare_loopback", "video:sv_loopback", "video:video_loopback", ] if (is_android) { deps += [ ":android_junit_tests", "sdk/android:libjingle_peerconnection_android_unittest", ] } else { deps += [ "modules/video_capture:video_capture_tests" ] } if (rtc_enable_protobuf) { deps += [ "audio:low_bandwidth_audio_test", "logging:rtc_event_log2rtp_dump", ] } } } } # Contains the defines and includes in common.gypi that are duplicated both as # target_defaults and direct_dependent_settings. config("common_inherited_config") { defines = [] cflags = [] ldflags = [] if (build_with_mozilla) { defines += [ "WEBRTC_MOZILLA_BUILD" ] } # Some tests need to declare their own trace event handlers. If this define is # not set, the first time TRACE_EVENT_* is called it will store the return # value for the current_frame handler in an static variable, so that subsequent # changes to the handler for that TRACE_EVENT_* will be ignored. # So when tests are included, we set this define, making it possible to use # different event handlers in different tests. if (rtc_include_tests) { defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=1" ] } else { defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0" ] } if (build_with_chromium) { defines += [ # TODO(kjellander): Cleanup unused ones and move defines closer to # the source when webrtc:4256 is completed. "GTEST_RELATIVE_PATH", "WEBRTC_CHROMIUM_BUILD", ] include_dirs = [ # The overrides must be included first as that is the mechanism for # selecting the override headers in Chromium. "../webrtc_overrides", # Allow includes to be prefixed with webrtc/ in case it is not an # immediate subdirectory of the top-level. ".", ] } if (is_posix) { defines += [ "WEBRTC_POSIX" ] } if (is_ios) { defines += [ "WEBRTC_MAC", "WEBRTC_IOS", ] } if (is_linux) { defines += [ "WEBRTC_LINUX" ] } if (is_mac) { defines += [ "WEBRTC_MAC" ] } if (is_fuchsia) { defines += [ "WEBRTC_FUCHSIA" ] } if (is_win) { defines += [ "WEBRTC_WIN", "_CRT_SECURE_NO_WARNINGS", # Suppress warnings about _vsnprinf ] } if (is_android) { defines += [ "WEBRTC_LINUX", "WEBRTC_ANDROID", ] if (build_with_mozilla) { defines += [ "WEBRTC_ANDROID_OPENSLES" ] } } if (is_chromeos) { defines += [ "CHROMEOS" ] } if (rtc_sanitize_coverage != "") { assert(is_clang, "sanitizer coverage requires clang") cflags += [ "-fsanitize-coverage=${rtc_sanitize_coverage}" ] ldflags += [ "-fsanitize-coverage=${rtc_sanitize_coverage}" ] } if (is_ubsan) { cflags += [ "-fsanitize=float-cast-overflow" ] } } config("common_config") { cflags = [] cflags_cc = [] defines = [] if (rtc_enable_protobuf) { defines += [ "WEBRTC_ENABLE_PROTOBUF=1" ] } else { defines += [ "WEBRTC_ENABLE_PROTOBUF=0" ] } if (rtc_include_internal_audio_device) { defines += [ "WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE" ] } if (!rtc_libvpx_build_vp9) { defines += [ "RTC_DISABLE_VP9" ] } if (rtc_enable_sctp) { defines += [ "HAVE_SCTP" ] } if (rtc_enable_external_auth) { defines += [ "ENABLE_EXTERNAL_AUTH" ] } if (rtc_use_builtin_sw_codecs) { defines += [ "USE_BUILTIN_SW_CODECS" ] } if (build_with_chromium) { defines += [ # NOTICE: Since common_inherited_config is used in public_configs for our # targets, there's no point including the defines in that config here. # TODO(kjellander): Cleanup unused ones and move defines closer to the # source when webrtc:4256 is completed. "HAVE_WEBRTC_VIDEO", "HAVE_WEBRTC_VOICE", "LOGGING_INSIDE_WEBRTC", ] } else { if (is_posix) { # Enable more warnings: -Wextra is currently disabled in Chromium. cflags = [ "-Wextra", # Repeat some flags that get overridden by -Wextra. "-Wno-unused-parameter", "-Wno-missing-field-initializers", "-Wno-strict-overflow", ] cflags_cc = [ "-Wnon-virtual-dtor", # This is enabled for clang; enable for gcc as well. "-Woverloaded-virtual", ] } if (is_clang) { cflags += [ "-Wc++11-narrowing", "-Wimplicit-fallthrough", "-Wthread-safety", "-Winconsistent-missing-override", "-Wundef", ] # use_xcode_clang only refers to the iOS toolchain, host binaries use # chromium's clang always. if (!is_nacl && (!use_xcode_clang || current_toolchain == host_toolchain)) { # Flags NaCl (Clang 3.7) and Xcode 7.3 (Clang clang-703.0.31) do not # recognize. cflags += [ "-Wunused-lambda-capture" ] } } } if (current_cpu == "arm64") { defines += [ "WEBRTC_ARCH_ARM64" ] defines += [ "WEBRTC_HAS_NEON" ] } if (current_cpu == "arm") { defines += [ "WEBRTC_ARCH_ARM" ] if (arm_version >= 7) { defines += [ "WEBRTC_ARCH_ARM_V7" ] if (arm_use_neon) { defines += [ "WEBRTC_HAS_NEON" ] } } } if (current_cpu == "mipsel") { defines += [ "MIPS32_LE" ] if (mips_float_abi == "hard") { defines += [ "MIPS_FPU_LE" ] } if (mips_arch_variant == "r2") { defines += [ "MIPS32_R2_LE" ] } if (mips_dsp_rev == 1) { defines += [ "MIPS_DSP_R1_LE" ] } else if (mips_dsp_rev == 2) { defines += [ "MIPS_DSP_R1_LE", "MIPS_DSP_R2_LE", ] } } if (is_android && !is_clang) { # The Android NDK doesn"t provide optimized versions of these # functions. Ensure they are disabled for all compilers. cflags += [ "-fno-builtin-cos", "-fno-builtin-sin", "-fno-builtin-cosf", "-fno-builtin-sinf", ] } if (use_libfuzzer || use_drfuzz || use_afl) { # Used in Chromium's overrides to disable logging defines += [ "WEBRTC_UNSAFE_FUZZER_MODE" ] } } config("common_objc") { libs = [ "Foundation.framework" ] } if (!build_with_chromium) { # Target to build all the WebRTC production code. rtc_static_library("webrtc") { # Only the root target should depend on this. visibility = [ "//:default" ] sources = [] complete_static_lib = true defines = [] deps = [ ":webrtc_common", "api:transport_api", "audio", "call", "common_audio", "common_video", "media", "modules", "modules/video_capture:video_capture_internal_impl", "ortc", "rtc_base", "sdk", "system_wrappers:system_wrappers_default", "video", ] if (build_with_mozilla) { deps += [ "api:video_frame_api", "system_wrappers:field_trial_default", "system_wrappers:metrics_default", ] } else { deps += [ "api", "logging", "p2p", "pc", "stats", ] } if (rtc_enable_protobuf) { defines += [ "ENABLE_RTC_EVENT_LOG" ] deps += [ "logging:rtc_event_log_proto" ] } } } rtc_source_set("typedefs") { sources = [ "typedefs.h", ] } rtc_static_library("webrtc_common") { sources = [ "common_types.cc", "common_types.h", ] deps = [ ":typedefs", "api:array_view", "api:optional", "rtc_base:checks", "rtc_base:deprecation", "rtc_base:stringutils", ] if (!build_with_chromium && is_clang) { # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] } } if (use_libfuzzer || use_drfuzz || use_afl) { # This target is only here for gn to discover fuzzer build targets under # webrtc/test/fuzzers/. group("webrtc_fuzzers_dummy") { testonly = true deps = [ "test/fuzzers:webrtc_fuzzer_main", ] } } if (rtc_include_tests) { config("rtc_unittests_config") { # GN orders flags on a target before flags from configs. The default config # adds -Wall, and this flag have to be after -Wall -- so they need to # come from a config and can"t be on the target directly. if (is_clang) { cflags = [ "-Wno-sign-compare", "-Wno-unused-const-variable", ] } } rtc_test("rtc_unittests") { testonly = true deps = [ ":webrtc_common", "api:rtc_api_unittests", "api/audio_codecs/test:audio_codecs_api_unittests", "p2p:libstunprober_unittests", "p2p:rtc_p2p_unittests", "rtc_base:rtc_base_approved_unittests", "rtc_base:rtc_base_tests_main", "rtc_base:rtc_base_tests_utils", "rtc_base:rtc_base_unittests", "rtc_base:rtc_numerics_unittests", "rtc_base:rtc_task_queue_unittests", "rtc_base:sequenced_task_checker_unittests", "rtc_base:weak_ptr_unittests", "system_wrappers:metrics_default", "system_wrappers:runtime_enabled_features_default", ] if (rtc_enable_protobuf) { deps += [ "logging:rtc_event_log_tests" ] } if (is_android) { # Do not use Chromium's launcher. native_unittests defines its own JNI_OnLoad. use_default_launcher = false deps += [ "sdk/android:native_unittests", "sdk/android:native_unittests_java", "//testing/android/native_test:native_test_support", ] shard_timeout = 900 } if (is_ios || is_mac) { deps += [ "sdk:sdk_unittests_objc" ] } } # TODO(pbos): Rename test suite, this is no longer "just" for video targets. video_engine_tests_resources = [ "resources/foreman_cif_short.yuv", "resources/voice_engine/audio_long16.pcm", ] if (is_ios) { bundle_data("video_engine_tests_bundle_data") { testonly = true sources = video_engine_tests_resources outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}", ] } } rtc_test("video_engine_tests") { testonly = true deps = [ "audio:audio_tests", # TODO(eladalon): call_tests aren't actually video-specific, so we # should move them to a more appropriate test suite. "call:call_tests", "modules/video_capture", "rtc_base:rtc_base_tests_utils", "test:test_common", "test:test_main", "test:video_test_common", "video:video_tests", ] data = video_engine_tests_resources if (!build_with_chromium && is_clang) { # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] } if (is_android) { deps += [ "//testing/android/native_test:native_test_native_code" ] shard_timeout = 900 } if (is_ios) { deps += [ ":video_engine_tests_bundle_data" ] } } webrtc_perf_tests_resources = [ "resources/audio_coding/speech_mono_16kHz.pcm", "resources/audio_coding/speech_mono_32_48kHz.pcm", "resources/audio_coding/testfile32kHz.pcm", "resources/ConferenceMotion_1280_720_50.yuv", "resources/difficult_photo_1850_1110.yuv", "resources/foreman_cif.yuv", "resources/google-wifi-3mbps.rx", "resources/paris_qcif.yuv", "resources/photo_1850_1110.yuv", "resources/presentation_1850_1110.yuv", "resources/verizon4g-downlink.rx", "resources/voice_engine/audio_long16.pcm", "resources/web_screenshot_1850_1110.yuv", ] if (is_ios) { bundle_data("webrtc_perf_tests_bundle_data") { testonly = true sources = webrtc_perf_tests_resources outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}", ] } } rtc_test("webrtc_perf_tests") { testonly = true configs += [ ":rtc_unittests_config" ] deps = [ "audio:audio_perf_tests", "call:call_perf_tests", "modules/audio_coding:audio_coding_perf_tests", "modules/audio_processing:audio_processing_perf_tests", "modules/remote_bitrate_estimator:remote_bitrate_estimator_perf_tests", "test:test_main", "video:video_full_stack_tests", ] data = webrtc_perf_tests_resources if (is_android) { deps += [ "//testing/android/native_test:native_test_native_code" ] shard_timeout = 2700 } if (is_ios) { deps += [ ":webrtc_perf_tests_bundle_data" ] } } rtc_test("webrtc_nonparallel_tests") { testonly = true deps = [ "rtc_base:rtc_base_nonparallel_tests", ] if (is_android) { deps += [ "//testing/android/native_test:native_test_support" ] shard_timeout = 900 } } if (is_android) { junit_binary("android_junit_tests") { java_files = [ "examples/androidjunit/src/org/appspot/apprtc/BluetoothManagerTest.java", "examples/androidjunit/src/org/appspot/apprtc/DirectRTCClientTest.java", "examples/androidjunit/src/org/appspot/apprtc/TCPChannelClientTest.java", "sdk/android/tests/src/org/webrtc/CameraEnumerationTest.java", ] deps = [ "examples:AppRTCMobile_javalib", "sdk/android:libjingle_peerconnection_java", "//base:base_java_test_support", ] } } } ================================================ FILE: thirdparty/webrtc/common_audio/rename.sh ================================================ #!/bin/sh rename 's/mips\.c$/mips\.c\.mips/' signal_processing/*.c rename 's/neon\.c$/neon\.c\.neon/' signal_processing/*.c ================================================ FILE: thirdparty/webrtc/common_audio/rename.sh~ ================================================ #!/bin/sh rename 's/mips\.c$/mips\.c\.mips/' signal_processing/*.c rename 's/neon\.c$/neon\.c\.neon/' signal_processing/*.c ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/cross_correlation.c ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/signal_processing/include/signal_processing_library.h" /* C version of WebRtcSpl_CrossCorrelation() for generic platforms. */ void WebRtcSpl_CrossCorrelationC(int32_t* cross_correlation, const int16_t* seq1, const int16_t* seq2, size_t dim_seq, size_t dim_cross_correlation, int right_shifts, int step_seq2) { size_t i = 0, j = 0; for (i = 0; i < dim_cross_correlation; i++) { int32_t corr = 0; for (j = 0; j < dim_seq; j++) corr += (seq1[j] * seq2[j]) >> right_shifts; seq2 += step_seq2; *cross_correlation++ = corr; } } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/cross_correlation_mips.c.mips ================================================ /* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/signal_processing/include/signal_processing_library.h" void WebRtcSpl_CrossCorrelation_mips(int32_t* cross_correlation, const int16_t* seq1, const int16_t* seq2, size_t dim_seq, size_t dim_cross_correlation, int right_shifts, int step_seq2) { int32_t t0 = 0, t1 = 0, t2 = 0, t3 = 0, sum = 0; int16_t *pseq2 = NULL; int16_t *pseq1 = NULL; int16_t *pseq1_0 = (int16_t*)&seq1[0]; int16_t *pseq2_0 = (int16_t*)&seq2[0]; int k = 0; __asm __volatile ( ".set push \n\t" ".set noreorder \n\t" "sll %[step_seq2], %[step_seq2], 1 \n\t" "andi %[t0], %[dim_seq], 1 \n\t" "bgtz %[t0], 3f \n\t" " nop \n\t" "1: \n\t" "move %[pseq1], %[pseq1_0] \n\t" "move %[pseq2], %[pseq2_0] \n\t" "sra %[k], %[dim_seq], 1 \n\t" "addiu %[dim_cc], %[dim_cc], -1 \n\t" "xor %[sum], %[sum], %[sum] \n\t" "2: \n\t" "lh %[t0], 0(%[pseq1]) \n\t" "lh %[t1], 0(%[pseq2]) \n\t" "lh %[t2], 2(%[pseq1]) \n\t" "lh %[t3], 2(%[pseq2]) \n\t" "mul %[t0], %[t0], %[t1] \n\t" "addiu %[k], %[k], -1 \n\t" "mul %[t2], %[t2], %[t3] \n\t" "addiu %[pseq1], %[pseq1], 4 \n\t" "addiu %[pseq2], %[pseq2], 4 \n\t" "srav %[t0], %[t0], %[right_shifts] \n\t" "addu %[sum], %[sum], %[t0] \n\t" "srav %[t2], %[t2], %[right_shifts] \n\t" "bgtz %[k], 2b \n\t" " addu %[sum], %[sum], %[t2] \n\t" "addu %[pseq2_0], %[pseq2_0], %[step_seq2] \n\t" "sw %[sum], 0(%[cc]) \n\t" "bgtz %[dim_cc], 1b \n\t" " addiu %[cc], %[cc], 4 \n\t" "b 6f \n\t" " nop \n\t" "3: \n\t" "move %[pseq1], %[pseq1_0] \n\t" "move %[pseq2], %[pseq2_0] \n\t" "sra %[k], %[dim_seq], 1 \n\t" "addiu %[dim_cc], %[dim_cc], -1 \n\t" "beqz %[k], 5f \n\t" " xor %[sum], %[sum], %[sum] \n\t" "4: \n\t" "lh %[t0], 0(%[pseq1]) \n\t" "lh %[t1], 0(%[pseq2]) \n\t" "lh %[t2], 2(%[pseq1]) \n\t" "lh %[t3], 2(%[pseq2]) \n\t" "mul %[t0], %[t0], %[t1] \n\t" "addiu %[k], %[k], -1 \n\t" "mul %[t2], %[t2], %[t3] \n\t" "addiu %[pseq1], %[pseq1], 4 \n\t" "addiu %[pseq2], %[pseq2], 4 \n\t" "srav %[t0], %[t0], %[right_shifts] \n\t" "addu %[sum], %[sum], %[t0] \n\t" "srav %[t2], %[t2], %[right_shifts] \n\t" "bgtz %[k], 4b \n\t" " addu %[sum], %[sum], %[t2] \n\t" "5: \n\t" "lh %[t0], 0(%[pseq1]) \n\t" "lh %[t1], 0(%[pseq2]) \n\t" "mul %[t0], %[t0], %[t1] \n\t" "srav %[t0], %[t0], %[right_shifts] \n\t" "addu %[sum], %[sum], %[t0] \n\t" "addu %[pseq2_0], %[pseq2_0], %[step_seq2] \n\t" "sw %[sum], 0(%[cc]) \n\t" "bgtz %[dim_cc], 3b \n\t" " addiu %[cc], %[cc], 4 \n\t" "6: \n\t" ".set pop \n\t" : [step_seq2] "+r" (step_seq2), [t0] "=&r" (t0), [t1] "=&r" (t1), [t2] "=&r" (t2), [t3] "=&r" (t3), [pseq1] "=&r" (pseq1), [pseq2] "=&r" (pseq2), [pseq1_0] "+r" (pseq1_0), [pseq2_0] "+r" (pseq2_0), [k] "=&r" (k), [dim_cc] "+r" (dim_cross_correlation), [sum] "=&r" (sum), [cc] "+r" (cross_correlation) : [dim_seq] "r" (dim_seq), [right_shifts] "r" (right_shifts) : "hi", "lo", "memory" ); } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/cross_correlation_neon.c.neon ================================================ /* * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/signal_processing/include/signal_processing_library.h" #include static inline void DotProductWithScaleNeon(int32_t* cross_correlation, const int16_t* vector1, const int16_t* vector2, size_t length, int scaling) { size_t i = 0; size_t len1 = length >> 3; size_t len2 = length & 7; int64x2_t sum0 = vdupq_n_s64(0); int64x2_t sum1 = vdupq_n_s64(0); for (i = len1; i > 0; i -= 1) { int16x8_t seq1_16x8 = vld1q_s16(vector1); int16x8_t seq2_16x8 = vld1q_s16(vector2); #if defined(WEBRTC_ARCH_ARM64) int32x4_t tmp0 = vmull_s16(vget_low_s16(seq1_16x8), vget_low_s16(seq2_16x8)); int32x4_t tmp1 = vmull_high_s16(seq1_16x8, seq2_16x8); #else int32x4_t tmp0 = vmull_s16(vget_low_s16(seq1_16x8), vget_low_s16(seq2_16x8)); int32x4_t tmp1 = vmull_s16(vget_high_s16(seq1_16x8), vget_high_s16(seq2_16x8)); #endif sum0 = vpadalq_s32(sum0, tmp0); sum1 = vpadalq_s32(sum1, tmp1); vector1 += 8; vector2 += 8; } // Calculate the rest of the samples. int64_t sum_res = 0; for (i = len2; i > 0; i -= 1) { sum_res += WEBRTC_SPL_MUL_16_16(*vector1, *vector2); vector1++; vector2++; } sum0 = vaddq_s64(sum0, sum1); #if defined(WEBRTC_ARCH_ARM64) int64_t sum2 = vaddvq_s64(sum0); *cross_correlation = (int32_t)((sum2 + sum_res) >> scaling); #else int64x1_t shift = vdup_n_s64(-scaling); int64x1_t sum2 = vadd_s64(vget_low_s64(sum0), vget_high_s64(sum0)); sum2 = vadd_s64(sum2, vdup_n_s64(sum_res)); sum2 = vshl_s64(sum2, shift); vst1_lane_s32(cross_correlation, vreinterpret_s32_s64(sum2), 0); #endif } /* NEON version of WebRtcSpl_CrossCorrelation() for ARM32/64 platforms. */ void WebRtcSpl_CrossCorrelationNeon(int32_t* cross_correlation, const int16_t* seq1, const int16_t* seq2, size_t dim_seq, size_t dim_cross_correlation, int right_shifts, int step_seq2) { size_t i = 0; for (i = 0; i < dim_cross_correlation; i++) { const int16_t* seq1_ptr = seq1; const int16_t* seq2_ptr = seq2 + (step_seq2 * i); DotProductWithScaleNeon(cross_correlation, seq1_ptr, seq2_ptr, dim_seq, right_shifts); cross_correlation++; } } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/division_operations.c ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file contains implementations of the divisions * WebRtcSpl_DivU32U16() * WebRtcSpl_DivW32W16() * WebRtcSpl_DivW32W16ResW16() * WebRtcSpl_DivResultInQ31() * WebRtcSpl_DivW32HiLow() * * The description header can be found in signal_processing_library.h * */ #include "common_audio/signal_processing/include/signal_processing_library.h" #include "rtc_base/sanitizer.h" uint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den) { // Guard against division with 0 if (den != 0) { return (uint32_t)(num / den); } else { return (uint32_t)0xFFFFFFFF; } } int32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den) { // Guard against division with 0 if (den != 0) { return (int32_t)(num / den); } else { return (int32_t)0x7FFFFFFF; } } int16_t WebRtcSpl_DivW32W16ResW16(int32_t num, int16_t den) { // Guard against division with 0 if (den != 0) { return (int16_t)(num / den); } else { return (int16_t)0x7FFF; } } int32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den) { int32_t L_num = num; int32_t L_den = den; int32_t div = 0; int k = 31; int change_sign = 0; if (num == 0) return 0; if (num < 0) { change_sign++; L_num = -num; } if (den < 0) { change_sign++; L_den = -den; } while (k--) { div <<= 1; L_num <<= 1; if (L_num >= L_den) { L_num -= L_den; div++; } } if (change_sign == 1) { div = -div; } return div; } int32_t RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486 WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low) { int16_t approx, tmp_hi, tmp_low, num_hi, num_low; int32_t tmpW32; approx = (int16_t)WebRtcSpl_DivW32W16((int32_t)0x1FFFFFFF, den_hi); // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30) // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30) tmpW32 = (den_hi * approx << 1) + ((den_low * approx >> 15) << 1); // tmpW32 = den * approx tmpW32 = (int32_t)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx)) // UBSan: 2147483647 - -2 cannot be represented in type 'int' // Store tmpW32 in hi and low format tmp_hi = (int16_t)(tmpW32 >> 16); tmp_low = (int16_t)((tmpW32 - ((int32_t)tmp_hi << 16)) >> 1); // tmpW32 = 1/den in Q29 tmpW32 = (tmp_hi * approx + (tmp_low * approx >> 15)) << 1; // 1/den in hi and low format tmp_hi = (int16_t)(tmpW32 >> 16); tmp_low = (int16_t)((tmpW32 - ((int32_t)tmp_hi << 16)) >> 1); // Store num in hi and low format num_hi = (int16_t)(num >> 16); num_low = (int16_t)((num - ((int32_t)num_hi << 16)) >> 1); // num * (1/den) by 32 bit multiplication (result in Q28) tmpW32 = num_hi * tmp_hi + (num_hi * tmp_low >> 15) + (num_low * tmp_hi >> 15); // Put result in Q31 (convert from Q28) tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3); return tmpW32; } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/downsample_fast.c ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/signal_processing/include/signal_processing_library.h" #include "rtc_base/checks.h" #include "rtc_base/sanitizer.h" // TODO(Bjornv): Change the function parameter order to WebRTC code style. // C version of WebRtcSpl_DownsampleFast() for generic platforms. int WebRtcSpl_DownsampleFastC(const int16_t* data_in, size_t data_in_length, int16_t* data_out, size_t data_out_length, const int16_t* __restrict coefficients, size_t coefficients_length, int factor, size_t delay) { int16_t* const original_data_out = data_out; size_t i = 0; size_t j = 0; int32_t out_s32 = 0; size_t endpos = delay + factor * (data_out_length - 1) + 1; // Return error if any of the running conditions doesn't meet. if (data_out_length == 0 || coefficients_length == 0 || data_in_length < endpos) { return -1; } rtc_MsanCheckInitialized(coefficients, sizeof(coefficients[0]), coefficients_length); for (i = delay; i < endpos; i += factor) { out_s32 = 2048; // Round value, 0.5 in Q12. for (j = 0; j < coefficients_length; j++) { rtc_MsanCheckInitialized(&data_in[i - j], sizeof(data_in[0]), 1); out_s32 += coefficients[j] * data_in[i - j]; // Q12. } out_s32 >>= 12; // Q0. // Saturate and store the output. *data_out++ = WebRtcSpl_SatW32ToW16(out_s32); } RTC_DCHECK_EQ(original_data_out + data_out_length, data_out); rtc_MsanCheckInitialized(original_data_out, sizeof(original_data_out[0]), data_out_length); return 0; } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/downsample_fast_mips.c.mips ================================================ /* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/signal_processing/include/signal_processing_library.h" // Version of WebRtcSpl_DownsampleFast() for MIPS platforms. int WebRtcSpl_DownsampleFast_mips(const int16_t* data_in, size_t data_in_length, int16_t* data_out, size_t data_out_length, const int16_t* __restrict coefficients, size_t coefficients_length, int factor, size_t delay) { int i; int j; int k; int32_t out_s32 = 0; size_t endpos = delay + factor * (data_out_length - 1) + 1; int32_t tmp1, tmp2, tmp3, tmp4, factor_2; int16_t* p_coefficients; int16_t* p_data_in; int16_t* p_data_in_0 = (int16_t*)&data_in[delay]; int16_t* p_coefficients_0 = (int16_t*)&coefficients[0]; #if !defined(MIPS_DSP_R1_LE) int32_t max_16 = 0x7FFF; int32_t min_16 = 0xFFFF8000; #endif // #if !defined(MIPS_DSP_R1_LE) // Return error if any of the running conditions doesn't meet. if (data_out_length == 0 || coefficients_length == 0 || data_in_length < endpos) { return -1; } #if defined(MIPS_DSP_R2_LE) __asm __volatile ( ".set push \n\t" ".set noreorder \n\t" "subu %[i], %[endpos], %[delay] \n\t" "sll %[factor_2], %[factor], 1 \n\t" "1: \n\t" "move %[p_data_in], %[p_data_in_0] \n\t" "mult $zero, $zero \n\t" "move %[p_coefs], %[p_coefs_0] \n\t" "sra %[j], %[coef_length], 2 \n\t" "beq %[j], $zero, 3f \n\t" " andi %[k], %[coef_length], 3 \n\t" "2: \n\t" "lwl %[tmp1], 1(%[p_data_in]) \n\t" "lwl %[tmp2], 3(%[p_coefs]) \n\t" "lwl %[tmp3], -3(%[p_data_in]) \n\t" "lwl %[tmp4], 7(%[p_coefs]) \n\t" "lwr %[tmp1], -2(%[p_data_in]) \n\t" "lwr %[tmp2], 0(%[p_coefs]) \n\t" "lwr %[tmp3], -6(%[p_data_in]) \n\t" "lwr %[tmp4], 4(%[p_coefs]) \n\t" "packrl.ph %[tmp1], %[tmp1], %[tmp1] \n\t" "packrl.ph %[tmp3], %[tmp3], %[tmp3] \n\t" "dpa.w.ph $ac0, %[tmp1], %[tmp2] \n\t" "dpa.w.ph $ac0, %[tmp3], %[tmp4] \n\t" "addiu %[j], %[j], -1 \n\t" "addiu %[p_data_in], %[p_data_in], -8 \n\t" "bgtz %[j], 2b \n\t" " addiu %[p_coefs], %[p_coefs], 8 \n\t" "3: \n\t" "beq %[k], $zero, 5f \n\t" " nop \n\t" "4: \n\t" "lhu %[tmp1], 0(%[p_data_in]) \n\t" "lhu %[tmp2], 0(%[p_coefs]) \n\t" "addiu %[p_data_in], %[p_data_in], -2 \n\t" "addiu %[k], %[k], -1 \n\t" "dpa.w.ph $ac0, %[tmp1], %[tmp2] \n\t" "bgtz %[k], 4b \n\t" " addiu %[p_coefs], %[p_coefs], 2 \n\t" "5: \n\t" "extr_r.w %[out_s32], $ac0, 12 \n\t" "addu %[p_data_in_0], %[p_data_in_0], %[factor_2] \n\t" "subu %[i], %[i], %[factor] \n\t" "shll_s.w %[out_s32], %[out_s32], 16 \n\t" "sra %[out_s32], %[out_s32], 16 \n\t" "sh %[out_s32], 0(%[data_out]) \n\t" "bgtz %[i], 1b \n\t" " addiu %[data_out], %[data_out], 2 \n\t" ".set pop \n\t" : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp4] "=&r" (tmp4), [p_data_in] "=&r" (p_data_in), [p_data_in_0] "+r" (p_data_in_0), [p_coefs] "=&r" (p_coefficients), [j] "=&r" (j), [out_s32] "=&r" (out_s32), [factor_2] "=&r" (factor_2), [i] "=&r" (i), [k] "=&r" (k) : [coef_length] "r" (coefficients_length), [data_out] "r" (data_out), [p_coefs_0] "r" (p_coefficients_0), [endpos] "r" (endpos), [delay] "r" (delay), [factor] "r" (factor) : "memory", "hi", "lo" ); #else // #if defined(MIPS_DSP_R2_LE) __asm __volatile ( ".set push \n\t" ".set noreorder \n\t" "sll %[factor_2], %[factor], 1 \n\t" "subu %[i], %[endpos], %[delay] \n\t" "1: \n\t" "move %[p_data_in], %[p_data_in_0] \n\t" "addiu %[out_s32], $zero, 2048 \n\t" "move %[p_coefs], %[p_coefs_0] \n\t" "sra %[j], %[coef_length], 1 \n\t" "beq %[j], $zero, 3f \n\t" " andi %[k], %[coef_length], 1 \n\t" "2: \n\t" "lh %[tmp1], 0(%[p_data_in]) \n\t" "lh %[tmp2], 0(%[p_coefs]) \n\t" "lh %[tmp3], -2(%[p_data_in]) \n\t" "lh %[tmp4], 2(%[p_coefs]) \n\t" "mul %[tmp1], %[tmp1], %[tmp2] \n\t" "addiu %[p_coefs], %[p_coefs], 4 \n\t" "mul %[tmp3], %[tmp3], %[tmp4] \n\t" "addiu %[j], %[j], -1 \n\t" "addiu %[p_data_in], %[p_data_in], -4 \n\t" "addu %[tmp1], %[tmp1], %[tmp3] \n\t" "bgtz %[j], 2b \n\t" " addu %[out_s32], %[out_s32], %[tmp1] \n\t" "3: \n\t" "beq %[k], $zero, 4f \n\t" " nop \n\t" "lh %[tmp1], 0(%[p_data_in]) \n\t" "lh %[tmp2], 0(%[p_coefs]) \n\t" "mul %[tmp1], %[tmp1], %[tmp2] \n\t" "addu %[out_s32], %[out_s32], %[tmp1] \n\t" "4: \n\t" "sra %[out_s32], %[out_s32], 12 \n\t" "addu %[p_data_in_0], %[p_data_in_0], %[factor_2] \n\t" #if defined(MIPS_DSP_R1_LE) "shll_s.w %[out_s32], %[out_s32], 16 \n\t" "sra %[out_s32], %[out_s32], 16 \n\t" #else // #if defined(MIPS_DSP_R1_LE) "slt %[tmp1], %[max_16], %[out_s32] \n\t" "movn %[out_s32], %[max_16], %[tmp1] \n\t" "slt %[tmp1], %[out_s32], %[min_16] \n\t" "movn %[out_s32], %[min_16], %[tmp1] \n\t" #endif // #if defined(MIPS_DSP_R1_LE) "subu %[i], %[i], %[factor] \n\t" "sh %[out_s32], 0(%[data_out]) \n\t" "bgtz %[i], 1b \n\t" " addiu %[data_out], %[data_out], 2 \n\t" ".set pop \n\t" : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp4] "=&r" (tmp4), [p_data_in] "=&r" (p_data_in), [k] "=&r" (k), [p_data_in_0] "+r" (p_data_in_0), [p_coefs] "=&r" (p_coefficients), [j] "=&r" (j), [out_s32] "=&r" (out_s32), [factor_2] "=&r" (factor_2), [i] "=&r" (i) : [coef_length] "r" (coefficients_length), [data_out] "r" (data_out), [p_coefs_0] "r" (p_coefficients_0), [endpos] "r" (endpos), #if !defined(MIPS_DSP_R1_LE) [max_16] "r" (max_16), [min_16] "r" (min_16), #endif // #if !defined(MIPS_DSP_R1_LE) [delay] "r" (delay), [factor] "r" (factor) : "memory", "hi", "lo" ); #endif // #if defined(MIPS_DSP_R2_LE) return 0; } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/downsample_fast_neon.c.neon ================================================ /* * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/signal_processing/include/signal_processing_library.h" #include // NEON intrinsics version of WebRtcSpl_DownsampleFast() // for ARM 32-bit/64-bit platforms. int WebRtcSpl_DownsampleFastNeon(const int16_t* data_in, size_t data_in_length, int16_t* data_out, size_t data_out_length, const int16_t* __restrict coefficients, size_t coefficients_length, int factor, size_t delay) { size_t i = 0; size_t j = 0; int32_t out_s32 = 0; size_t endpos = delay + factor * (data_out_length - 1) + 1; size_t res = data_out_length & 0x7; size_t endpos1 = endpos - factor * res; // Return error if any of the running conditions doesn't meet. if (data_out_length == 0 || coefficients_length == 0 || data_in_length < endpos) { return -1; } // First part, unroll the loop 8 times, with 3 subcases // (factor == 2, 4, others). switch (factor) { case 2: { for (i = delay; i < endpos1; i += 16) { // Round value, 0.5 in Q12. int32x4_t out32x4_0 = vdupq_n_s32(2048); int32x4_t out32x4_1 = vdupq_n_s32(2048); #if defined(WEBRTC_ARCH_ARM64) // Unroll the loop 2 times. for (j = 0; j < coefficients_length - 1; j += 2) { int32x2_t coeff32 = vld1_dup_s32((int32_t*)&coefficients[j]); int16x4_t coeff16x4 = vreinterpret_s16_s32(coeff32); int16x8x2_t in16x8x2 = vld2q_s16(&data_in[i - j - 1]); // Mul and accumulate low 64-bit data. int16x4_t in16x4_0 = vget_low_s16(in16x8x2.val[0]); int16x4_t in16x4_1 = vget_low_s16(in16x8x2.val[1]); out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_0, coeff16x4, 1); out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_1, coeff16x4, 0); // Mul and accumulate high 64-bit data. // TODO: vget_high_s16 need extra cost on ARM64. This could be // replaced by vmlal_high_lane_s16. But for the interface of // vmlal_high_lane_s16, there is a bug in gcc 4.9. // This issue need to be tracked in the future. int16x4_t in16x4_2 = vget_high_s16(in16x8x2.val[0]); int16x4_t in16x4_3 = vget_high_s16(in16x8x2.val[1]); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_2, coeff16x4, 1); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_3, coeff16x4, 0); } for (; j < coefficients_length; j++) { int16x4_t coeff16x4 = vld1_dup_s16(&coefficients[j]); int16x8x2_t in16x8x2 = vld2q_s16(&data_in[i - j]); // Mul and accumulate low 64-bit data. int16x4_t in16x4_0 = vget_low_s16(in16x8x2.val[0]); out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_0, coeff16x4, 0); // Mul and accumulate high 64-bit data. // TODO: vget_high_s16 need extra cost on ARM64. This could be // replaced by vmlal_high_lane_s16. But for the interface of // vmlal_high_lane_s16, there is a bug in gcc 4.9. // This issue need to be tracked in the future. int16x4_t in16x4_1 = vget_high_s16(in16x8x2.val[0]); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_1, coeff16x4, 0); } #else // On ARMv7, the loop unrolling 2 times results in performance // regression. for (j = 0; j < coefficients_length; j++) { int16x4_t coeff16x4 = vld1_dup_s16(&coefficients[j]); int16x8x2_t in16x8x2 = vld2q_s16(&data_in[i - j]); // Mul and accumulate. int16x4_t in16x4_0 = vget_low_s16(in16x8x2.val[0]); int16x4_t in16x4_1 = vget_high_s16(in16x8x2.val[0]); out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_0, coeff16x4, 0); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_1, coeff16x4, 0); } #endif // Saturate and store the output. int16x4_t out16x4_0 = vqshrn_n_s32(out32x4_0, 12); int16x4_t out16x4_1 = vqshrn_n_s32(out32x4_1, 12); vst1q_s16(data_out, vcombine_s16(out16x4_0, out16x4_1)); data_out += 8; } break; } case 4: { for (i = delay; i < endpos1; i += 32) { // Round value, 0.5 in Q12. int32x4_t out32x4_0 = vdupq_n_s32(2048); int32x4_t out32x4_1 = vdupq_n_s32(2048); // Unroll the loop 4 times. for (j = 0; j < coefficients_length - 3; j += 4) { int16x4_t coeff16x4 = vld1_s16(&coefficients[j]); int16x8x4_t in16x8x4 = vld4q_s16(&data_in[i - j - 3]); // Mul and accumulate low 64-bit data. int16x4_t in16x4_0 = vget_low_s16(in16x8x4.val[0]); int16x4_t in16x4_2 = vget_low_s16(in16x8x4.val[1]); int16x4_t in16x4_4 = vget_low_s16(in16x8x4.val[2]); int16x4_t in16x4_6 = vget_low_s16(in16x8x4.val[3]); out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_0, coeff16x4, 3); out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_2, coeff16x4, 2); out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_4, coeff16x4, 1); out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_6, coeff16x4, 0); // Mul and accumulate high 64-bit data. // TODO: vget_high_s16 need extra cost on ARM64. This could be // replaced by vmlal_high_lane_s16. But for the interface of // vmlal_high_lane_s16, there is a bug in gcc 4.9. // This issue need to be tracked in the future. int16x4_t in16x4_1 = vget_high_s16(in16x8x4.val[0]); int16x4_t in16x4_3 = vget_high_s16(in16x8x4.val[1]); int16x4_t in16x4_5 = vget_high_s16(in16x8x4.val[2]); int16x4_t in16x4_7 = vget_high_s16(in16x8x4.val[3]); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_1, coeff16x4, 3); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_3, coeff16x4, 2); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_5, coeff16x4, 1); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_7, coeff16x4, 0); } for (; j < coefficients_length; j++) { int16x4_t coeff16x4 = vld1_dup_s16(&coefficients[j]); int16x8x4_t in16x8x4 = vld4q_s16(&data_in[i - j]); // Mul and accumulate low 64-bit data. int16x4_t in16x4_0 = vget_low_s16(in16x8x4.val[0]); out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_0, coeff16x4, 0); // Mul and accumulate high 64-bit data. // TODO: vget_high_s16 need extra cost on ARM64. This could be // replaced by vmlal_high_lane_s16. But for the interface of // vmlal_high_lane_s16, there is a bug in gcc 4.9. // This issue need to be tracked in the future. int16x4_t in16x4_1 = vget_high_s16(in16x8x4.val[0]); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_1, coeff16x4, 0); } // Saturate and store the output. int16x4_t out16x4_0 = vqshrn_n_s32(out32x4_0, 12); int16x4_t out16x4_1 = vqshrn_n_s32(out32x4_1, 12); vst1q_s16(data_out, vcombine_s16(out16x4_0, out16x4_1)); data_out += 8; } break; } default: { for (i = delay; i < endpos1; i += factor * 8) { // Round value, 0.5 in Q12. int32x4_t out32x4_0 = vdupq_n_s32(2048); int32x4_t out32x4_1 = vdupq_n_s32(2048); for (j = 0; j < coefficients_length; j++) { int16x4_t coeff16x4 = vld1_dup_s16(&coefficients[j]); int16x4_t in16x4_0 = vld1_dup_s16(&data_in[i - j]); in16x4_0 = vld1_lane_s16(&data_in[i + factor - j], in16x4_0, 1); in16x4_0 = vld1_lane_s16(&data_in[i + factor * 2 - j], in16x4_0, 2); in16x4_0 = vld1_lane_s16(&data_in[i + factor * 3 - j], in16x4_0, 3); int16x4_t in16x4_1 = vld1_dup_s16(&data_in[i + factor * 4 - j]); in16x4_1 = vld1_lane_s16(&data_in[i + factor * 5 - j], in16x4_1, 1); in16x4_1 = vld1_lane_s16(&data_in[i + factor * 6 - j], in16x4_1, 2); in16x4_1 = vld1_lane_s16(&data_in[i + factor * 7 - j], in16x4_1, 3); // Mul and accumulate. out32x4_0 = vmlal_lane_s16(out32x4_0, in16x4_0, coeff16x4, 0); out32x4_1 = vmlal_lane_s16(out32x4_1, in16x4_1, coeff16x4, 0); } // Saturate and store the output. int16x4_t out16x4_0 = vqshrn_n_s32(out32x4_0, 12); int16x4_t out16x4_1 = vqshrn_n_s32(out32x4_1, 12); vst1q_s16(data_out, vcombine_s16(out16x4_0, out16x4_1)); data_out += 8; } break; } } // Second part, do the rest iterations (if any). for (; i < endpos; i += factor) { out_s32 = 2048; // Round value, 0.5 in Q12. for (j = 0; j < coefficients_length; j++) { out_s32 = WebRtc_MulAccumW16(coefficients[j], data_in[i - j], out_s32); } // Saturate and store the output. out_s32 >>= 12; *data_out++ = WebRtcSpl_SatW32ToW16(out_s32); } return 0; } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/energy.c ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file contains the function WebRtcSpl_Energy(). * The description header can be found in signal_processing_library.h * */ #include "common_audio/signal_processing/include/signal_processing_library.h" int32_t WebRtcSpl_Energy(int16_t* vector, size_t vector_length, int* scale_factor) { int32_t en = 0; size_t i; int scaling = WebRtcSpl_GetScalingSquare(vector, vector_length, vector_length); size_t looptimes = vector_length; int16_t *vectorptr = vector; for (i = 0; i < looptimes; i++) { en += (*vectorptr * *vectorptr) >> scaling; vectorptr++; } *scale_factor = scaling; return en; } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/get_scaling_square.c ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file contains the function WebRtcSpl_GetScalingSquare(). * The description header can be found in signal_processing_library.h * */ #include "common_audio/signal_processing/include/signal_processing_library.h" int16_t WebRtcSpl_GetScalingSquare(int16_t* in_vector, size_t in_vector_length, size_t times) { int16_t nbits = WebRtcSpl_GetSizeInBits((uint32_t)times); size_t i; int16_t smax = -1; int16_t sabs; int16_t *sptr = in_vector; int16_t t; size_t looptimes = in_vector_length; for (i = looptimes; i > 0; i--) { sabs = (*sptr > 0 ? *sptr++ : -*sptr++); smax = (sabs > smax ? sabs : smax); } t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax)); if (smax == 0) { return 0; // Since norm(0) returns 0 } else { return (t > nbits) ? 0 : nbits - t; } } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/include/real_fft.h ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_ #define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_ #include "typedefs.h" // NOLINT(build/include) // For ComplexFFT(), the maximum fft order is 10; // for OpenMax FFT in ARM, it is 12; // WebRTC APM uses orders of only 7 and 8. enum {kMaxFFTOrder = 10}; struct RealFFT; #ifdef __cplusplus extern "C" { #endif struct RealFFT* WebRtcSpl_CreateRealFFT(int order); void WebRtcSpl_FreeRealFFT(struct RealFFT* self); // Compute an FFT for a real-valued signal of length of 2^order, // where 1 < order <= MAX_FFT_ORDER. Transform length is determined by the // specification structure, which must be initialized prior to calling the FFT // function with WebRtcSpl_CreateRealFFT(). // The relationship between the input and output sequences can // be expressed in terms of the DFT, i.e.: // x[n] = (2^(-scalefactor)/N) . SUM[k=0,...,N-1] X[k].e^(jnk.2.pi/N) // n=0,1,2,...N-1 // N=2^order. // The conjugate-symmetric output sequence is represented using a CCS vector, // which is of length N+2, and is organized as follows: // Index: 0 1 2 3 4 5 . . . N-2 N-1 N N+1 // Component: R0 0 R1 I1 R2 I2 . . . R[N/2-1] I[N/2-1] R[N/2] 0 // where R[n] and I[n], respectively, denote the real and imaginary components // for FFT bin 'n'. Bins are numbered from 0 to N/2, where N is the FFT length. // Bin index 0 corresponds to the DC component, and bin index N/2 corresponds to // the foldover frequency. // // Input Arguments: // self - pointer to preallocated and initialized FFT specification structure. // real_data_in - the input signal. For an ARM Neon platform, it must be // aligned on a 32-byte boundary. // // Output Arguments: // complex_data_out - the output complex signal with (2^order + 2) 16-bit // elements. For an ARM Neon platform, it must be different // from real_data_in, and aligned on a 32-byte boundary. // // Return Value: // 0 - FFT calculation is successful. // -1 - Error with bad arguments (null pointers). int WebRtcSpl_RealForwardFFT(struct RealFFT* self, const int16_t* real_data_in, int16_t* complex_data_out); // Compute the inverse FFT for a conjugate-symmetric input sequence of length of // 2^order, where 1 < order <= MAX_FFT_ORDER. Transform length is determined by // the specification structure, which must be initialized prior to calling the // FFT function with WebRtcSpl_CreateRealFFT(). // For a transform of length M, the input sequence is represented using a packed // CCS vector of length M+2, which is explained in the comments for // WebRtcSpl_RealForwardFFTC above. // // Input Arguments: // self - pointer to preallocated and initialized FFT specification structure. // complex_data_in - the input complex signal with (2^order + 2) 16-bit // elements. For an ARM Neon platform, it must be aligned on // a 32-byte boundary. // // Output Arguments: // real_data_out - the output real signal. For an ARM Neon platform, it must // be different to complex_data_in, and aligned on a 32-byte // boundary. // // Return Value: // 0 or a positive number - a value that the elements in the |real_data_out| // should be shifted left with in order to get // correct physical values. // -1 - Error with bad arguments (null pointers). int WebRtcSpl_RealInverseFFT(struct RealFFT* self, const int16_t* complex_data_in, int16_t* real_data_out); #ifdef __cplusplus } #endif #endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_ ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/include/signal_processing_library.h ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This header file includes all of the fix point signal processing library (SPL) function * descriptions and declarations. * For specific function calls, see bottom of file. */ #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SIGNAL_PROCESSING_LIBRARY_H_ #define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SIGNAL_PROCESSING_LIBRARY_H_ #include #include "typedefs.h" // NOLINT(build/include) // Macros specific for the fixed point implementation #define WEBRTC_SPL_WORD16_MAX 32767 #define WEBRTC_SPL_WORD16_MIN -32768 #define WEBRTC_SPL_WORD32_MAX (int32_t)0x7fffffff #define WEBRTC_SPL_WORD32_MIN (int32_t)0x80000000 #define WEBRTC_SPL_MAX_LPC_ORDER 14 #define WEBRTC_SPL_MIN(A, B) (A < B ? A : B) // Get min value #define WEBRTC_SPL_MAX(A, B) (A > B ? A : B) // Get max value // TODO(kma/bjorn): For the next two macros, investigate how to correct the code // for inputs of a = WEBRTC_SPL_WORD16_MIN or WEBRTC_SPL_WORD32_MIN. #define WEBRTC_SPL_ABS_W16(a) \ (((int16_t)a >= 0) ? ((int16_t)a) : -((int16_t)a)) #define WEBRTC_SPL_ABS_W32(a) \ (((int32_t)a >= 0) ? ((int32_t)a) : -((int32_t)a)) #define WEBRTC_SPL_MUL(a, b) \ ((int32_t) ((int32_t)(a) * (int32_t)(b))) #define WEBRTC_SPL_UMUL(a, b) \ ((uint32_t) ((uint32_t)(a) * (uint32_t)(b))) #define WEBRTC_SPL_UMUL_32_16(a, b) \ ((uint32_t) ((uint32_t)(a) * (uint16_t)(b))) #define WEBRTC_SPL_MUL_16_U16(a, b) \ ((int32_t)(int16_t)(a) * (uint16_t)(b)) #ifndef WEBRTC_ARCH_ARM_V7 // For ARMv7 platforms, these are inline functions in spl_inl_armv7.h #ifndef MIPS32_LE // For MIPS platforms, these are inline functions in spl_inl_mips.h #define WEBRTC_SPL_MUL_16_16(a, b) \ ((int32_t) (((int16_t)(a)) * ((int16_t)(b)))) #define WEBRTC_SPL_MUL_16_32_RSFT16(a, b) \ (WEBRTC_SPL_MUL_16_16(a, b >> 16) \ + ((WEBRTC_SPL_MUL_16_16(a, (b & 0xffff) >> 1) + 0x4000) >> 15)) #endif #endif #define WEBRTC_SPL_MUL_16_32_RSFT11(a, b) \ (WEBRTC_SPL_MUL_16_16(a, (b) >> 16) * (1 << 5) + \ (((WEBRTC_SPL_MUL_16_U16(a, (uint16_t)(b)) >> 1) + 0x0200) >> 10)) #define WEBRTC_SPL_MUL_16_32_RSFT14(a, b) \ (WEBRTC_SPL_MUL_16_16(a, (b) >> 16) * (1 << 2) + \ (((WEBRTC_SPL_MUL_16_U16(a, (uint16_t)(b)) >> 1) + 0x1000) >> 13)) #define WEBRTC_SPL_MUL_16_32_RSFT15(a, b) \ ((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) * (1 << 1)) + \ (((WEBRTC_SPL_MUL_16_U16(a, (uint16_t)(b)) >> 1) + 0x2000) >> 14)) #define WEBRTC_SPL_MUL_16_16_RSFT(a, b, c) \ (WEBRTC_SPL_MUL_16_16(a, b) >> (c)) #define WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(a, b, c) \ ((WEBRTC_SPL_MUL_16_16(a, b) + ((int32_t) \ (((int32_t)1) << ((c) - 1)))) >> (c)) // C + the 32 most significant bits of A * B #define WEBRTC_SPL_SCALEDIFF32(A, B, C) \ (C + (B >> 16) * A + (((uint32_t)(B & 0x0000FFFF) * A) >> 16)) #define WEBRTC_SPL_SAT(a, b, c) (b > a ? a : b < c ? c : b) // Shifting with negative numbers allowed // Positive means left shift #define WEBRTC_SPL_SHIFT_W32(x, c) ((c) >= 0 ? (x) * (1 << (c)) : (x) >> -(c)) // Shifting with negative numbers not allowed // We cannot do casting here due to signed/unsigned problem #define WEBRTC_SPL_LSHIFT_W32(x, c) ((x) << (c)) #define WEBRTC_SPL_RSHIFT_U32(x, c) ((uint32_t)(x) >> (c)) #define WEBRTC_SPL_RAND(a) \ ((int16_t)((((int16_t)a * 18816) >> 7) & 0x00007fff)) #ifdef __cplusplus extern "C" { #endif #define WEBRTC_SPL_MEMCPY_W16(v1, v2, length) \ memcpy(v1, v2, (length) * sizeof(int16_t)) // inline functions: #include "common_audio/signal_processing/include/spl_inl.h" // Initialize SPL. Currently it contains only function pointer initialization. // If the underlying platform is known to be ARM-Neon (WEBRTC_HAS_NEON defined), // the pointers will be assigned to code optimized for Neon; otherwise, generic // C code will be assigned. // Note that this function MUST be called in any application that uses SPL // functions. void WebRtcSpl_Init(); int16_t WebRtcSpl_GetScalingSquare(int16_t* in_vector, size_t in_vector_length, size_t times); // Copy and set operations. Implementation in copy_set_operations.c. // Descriptions at bottom of file. void WebRtcSpl_MemSetW16(int16_t* vector, int16_t set_value, size_t vector_length); void WebRtcSpl_MemSetW32(int32_t* vector, int32_t set_value, size_t vector_length); void WebRtcSpl_MemCpyReversedOrder(int16_t* out_vector, int16_t* in_vector, size_t vector_length); void WebRtcSpl_CopyFromEndW16(const int16_t* in_vector, size_t in_vector_length, size_t samples, int16_t* out_vector); void WebRtcSpl_ZerosArrayW16(int16_t* vector, size_t vector_length); void WebRtcSpl_ZerosArrayW32(int32_t* vector, size_t vector_length); // End: Copy and set operations. // Minimum and maximum operation functions and their pointers. // Implementation in min_max_operations.c. // Returns the largest absolute value in a signed 16-bit vector. // // Input: // - vector : 16-bit input vector. // - length : Number of samples in vector. // // Return value : Maximum absolute value in vector. typedef int16_t (*MaxAbsValueW16)(const int16_t* vector, size_t length); extern MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16; int16_t WebRtcSpl_MaxAbsValueW16C(const int16_t* vector, size_t length); #if defined(WEBRTC_HAS_NEON) int16_t WebRtcSpl_MaxAbsValueW16Neon(const int16_t* vector, size_t length); #endif #if defined(MIPS32_LE) int16_t WebRtcSpl_MaxAbsValueW16_mips(const int16_t* vector, size_t length); #endif // Returns the largest absolute value in a signed 32-bit vector. // // Input: // - vector : 32-bit input vector. // - length : Number of samples in vector. // // Return value : Maximum absolute value in vector. typedef int32_t (*MaxAbsValueW32)(const int32_t* vector, size_t length); extern MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32; int32_t WebRtcSpl_MaxAbsValueW32C(const int32_t* vector, size_t length); #if defined(WEBRTC_HAS_NEON) int32_t WebRtcSpl_MaxAbsValueW32Neon(const int32_t* vector, size_t length); #endif #if defined(MIPS_DSP_R1_LE) int32_t WebRtcSpl_MaxAbsValueW32_mips(const int32_t* vector, size_t length); #endif // Returns the maximum value of a 16-bit vector. // // Input: // - vector : 16-bit input vector. // - length : Number of samples in vector. // // Return value : Maximum sample value in |vector|. typedef int16_t (*MaxValueW16)(const int16_t* vector, size_t length); extern MaxValueW16 WebRtcSpl_MaxValueW16; int16_t WebRtcSpl_MaxValueW16C(const int16_t* vector, size_t length); #if defined(WEBRTC_HAS_NEON) int16_t WebRtcSpl_MaxValueW16Neon(const int16_t* vector, size_t length); #endif #if defined(MIPS32_LE) int16_t WebRtcSpl_MaxValueW16_mips(const int16_t* vector, size_t length); #endif // Returns the maximum value of a 32-bit vector. // // Input: // - vector : 32-bit input vector. // - length : Number of samples in vector. // // Return value : Maximum sample value in |vector|. typedef int32_t (*MaxValueW32)(const int32_t* vector, size_t length); extern MaxValueW32 WebRtcSpl_MaxValueW32; int32_t WebRtcSpl_MaxValueW32C(const int32_t* vector, size_t length); #if defined(WEBRTC_HAS_NEON) int32_t WebRtcSpl_MaxValueW32Neon(const int32_t* vector, size_t length); #endif #if defined(MIPS32_LE) int32_t WebRtcSpl_MaxValueW32_mips(const int32_t* vector, size_t length); #endif // Returns the minimum value of a 16-bit vector. // // Input: // - vector : 16-bit input vector. // - length : Number of samples in vector. // // Return value : Minimum sample value in |vector|. typedef int16_t (*MinValueW16)(const int16_t* vector, size_t length); extern MinValueW16 WebRtcSpl_MinValueW16; int16_t WebRtcSpl_MinValueW16C(const int16_t* vector, size_t length); #if defined(WEBRTC_HAS_NEON) int16_t WebRtcSpl_MinValueW16Neon(const int16_t* vector, size_t length); #endif #if defined(MIPS32_LE) int16_t WebRtcSpl_MinValueW16_mips(const int16_t* vector, size_t length); #endif // Returns the minimum value of a 32-bit vector. // // Input: // - vector : 32-bit input vector. // - length : Number of samples in vector. // // Return value : Minimum sample value in |vector|. typedef int32_t (*MinValueW32)(const int32_t* vector, size_t length); extern MinValueW32 WebRtcSpl_MinValueW32; int32_t WebRtcSpl_MinValueW32C(const int32_t* vector, size_t length); #if defined(WEBRTC_HAS_NEON) int32_t WebRtcSpl_MinValueW32Neon(const int32_t* vector, size_t length); #endif #if defined(MIPS32_LE) int32_t WebRtcSpl_MinValueW32_mips(const int32_t* vector, size_t length); #endif // Returns the vector index to the largest absolute value of a 16-bit vector. // // Input: // - vector : 16-bit input vector. // - length : Number of samples in vector. // // Return value : Index to the maximum absolute value in vector. // If there are multiple equal maxima, return the index of the // first. -32768 will always have precedence over 32767 (despite // -32768 presenting an int16 absolute value of 32767). size_t WebRtcSpl_MaxAbsIndexW16(const int16_t* vector, size_t length); // Returns the vector index to the maximum sample value of a 16-bit vector. // // Input: // - vector : 16-bit input vector. // - length : Number of samples in vector. // // Return value : Index to the maximum value in vector (if multiple // indexes have the maximum, return the first). size_t WebRtcSpl_MaxIndexW16(const int16_t* vector, size_t length); // Returns the vector index to the maximum sample value of a 32-bit vector. // // Input: // - vector : 32-bit input vector. // - length : Number of samples in vector. // // Return value : Index to the maximum value in vector (if multiple // indexes have the maximum, return the first). size_t WebRtcSpl_MaxIndexW32(const int32_t* vector, size_t length); // Returns the vector index to the minimum sample value of a 16-bit vector. // // Input: // - vector : 16-bit input vector. // - length : Number of samples in vector. // // Return value : Index to the mimimum value in vector (if multiple // indexes have the minimum, return the first). size_t WebRtcSpl_MinIndexW16(const int16_t* vector, size_t length); // Returns the vector index to the minimum sample value of a 32-bit vector. // // Input: // - vector : 32-bit input vector. // - length : Number of samples in vector. // // Return value : Index to the mimimum value in vector (if multiple // indexes have the minimum, return the first). size_t WebRtcSpl_MinIndexW32(const int32_t* vector, size_t length); // End: Minimum and maximum operations. // Vector scaling operations. Implementation in vector_scaling_operations.c. // Description at bottom of file. void WebRtcSpl_VectorBitShiftW16(int16_t* out_vector, size_t vector_length, const int16_t* in_vector, int16_t right_shifts); void WebRtcSpl_VectorBitShiftW32(int32_t* out_vector, size_t vector_length, const int32_t* in_vector, int16_t right_shifts); void WebRtcSpl_VectorBitShiftW32ToW16(int16_t* out_vector, size_t vector_length, const int32_t* in_vector, int right_shifts); void WebRtcSpl_ScaleVector(const int16_t* in_vector, int16_t* out_vector, int16_t gain, size_t vector_length, int16_t right_shifts); void WebRtcSpl_ScaleVectorWithSat(const int16_t* in_vector, int16_t* out_vector, int16_t gain, size_t vector_length, int16_t right_shifts); void WebRtcSpl_ScaleAndAddVectors(const int16_t* in_vector1, int16_t gain1, int right_shifts1, const int16_t* in_vector2, int16_t gain2, int right_shifts2, int16_t* out_vector, size_t vector_length); // The functions (with related pointer) perform the vector operation: // out_vector[k] = ((scale1 * in_vector1[k]) + (scale2 * in_vector2[k]) // + round_value) >> right_shifts, // where round_value = (1 << right_shifts) >> 1. // // Input: // - in_vector1 : Input vector 1 // - in_vector1_scale : Gain to be used for vector 1 // - in_vector2 : Input vector 2 // - in_vector2_scale : Gain to be used for vector 2 // - right_shifts : Number of right bit shifts to be applied // - length : Number of elements in the input vectors // // Output: // - out_vector : Output vector // Return value : 0 if OK, -1 if (in_vector1 == null // || in_vector2 == null || out_vector == null // || length <= 0 || right_shift < 0). typedef int (*ScaleAndAddVectorsWithRound)(const int16_t* in_vector1, int16_t in_vector1_scale, const int16_t* in_vector2, int16_t in_vector2_scale, int right_shifts, int16_t* out_vector, size_t length); extern ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound; int WebRtcSpl_ScaleAndAddVectorsWithRoundC(const int16_t* in_vector1, int16_t in_vector1_scale, const int16_t* in_vector2, int16_t in_vector2_scale, int right_shifts, int16_t* out_vector, size_t length); #if defined(MIPS_DSP_R1_LE) int WebRtcSpl_ScaleAndAddVectorsWithRound_mips(const int16_t* in_vector1, int16_t in_vector1_scale, const int16_t* in_vector2, int16_t in_vector2_scale, int right_shifts, int16_t* out_vector, size_t length); #endif // End: Vector scaling operations. // iLBC specific functions. Implementations in ilbc_specific_functions.c. // Description at bottom of file. void WebRtcSpl_ReverseOrderMultArrayElements(int16_t* out_vector, const int16_t* in_vector, const int16_t* window, size_t vector_length, int16_t right_shifts); void WebRtcSpl_ElementwiseVectorMult(int16_t* out_vector, const int16_t* in_vector, const int16_t* window, size_t vector_length, int16_t right_shifts); void WebRtcSpl_AddVectorsAndShift(int16_t* out_vector, const int16_t* in_vector1, const int16_t* in_vector2, size_t vector_length, int16_t right_shifts); void WebRtcSpl_AddAffineVectorToVector(int16_t* out_vector, int16_t* in_vector, int16_t gain, int32_t add_constant, int16_t right_shifts, size_t vector_length); void WebRtcSpl_AffineTransformVector(int16_t* out_vector, int16_t* in_vector, int16_t gain, int32_t add_constant, int16_t right_shifts, size_t vector_length); // End: iLBC specific functions. // Signal processing operations. // A 32-bit fix-point implementation of auto-correlation computation // // Input: // - in_vector : Vector to calculate autocorrelation upon // - in_vector_length : Length (in samples) of |vector| // - order : The order up to which the autocorrelation should be // calculated // // Output: // - result : auto-correlation values (values should be seen // relative to each other since the absolute values // might have been down shifted to avoid overflow) // // - scale : The number of left shifts required to obtain the // auto-correlation in Q0 // // Return value : Number of samples in |result|, i.e. (order+1) size_t WebRtcSpl_AutoCorrelation(const int16_t* in_vector, size_t in_vector_length, size_t order, int32_t* result, int* scale); // A 32-bit fix-point implementation of the Levinson-Durbin algorithm that // does NOT use the 64 bit class // // Input: // - auto_corr : Vector with autocorrelation values of length >= |order|+1 // - order : The LPC filter order (support up to order 20) // // Output: // - lpc_coef : lpc_coef[0..order] LPC coefficients in Q12 // - refl_coef : refl_coef[0...order-1]| Reflection coefficients in Q15 // // Return value : 1 for stable 0 for unstable int16_t WebRtcSpl_LevinsonDurbin(const int32_t* auto_corr, int16_t* lpc_coef, int16_t* refl_coef, size_t order); // Converts reflection coefficients |refl_coef| to LPC coefficients |lpc_coef|. // This version is a 16 bit operation. // // NOTE: The 16 bit refl_coef -> lpc_coef conversion might result in a // "slightly unstable" filter (i.e., a pole just outside the unit circle) in // "rare" cases even if the reflection coefficients are stable. // // Input: // - refl_coef : Reflection coefficients in Q15 that should be converted // to LPC coefficients // - use_order : Number of coefficients in |refl_coef| // // Output: // - lpc_coef : LPC coefficients in Q12 void WebRtcSpl_ReflCoefToLpc(const int16_t* refl_coef, int use_order, int16_t* lpc_coef); // Converts LPC coefficients |lpc_coef| to reflection coefficients |refl_coef|. // This version is a 16 bit operation. // The conversion is implemented by the step-down algorithm. // // Input: // - lpc_coef : LPC coefficients in Q12, that should be converted to // reflection coefficients // - use_order : Number of coefficients in |lpc_coef| // // Output: // - refl_coef : Reflection coefficients in Q15. void WebRtcSpl_LpcToReflCoef(int16_t* lpc_coef, int use_order, int16_t* refl_coef); // Calculates reflection coefficients (16 bit) from auto-correlation values // // Input: // - auto_corr : Auto-correlation values // - use_order : Number of coefficients wanted be calculated // // Output: // - refl_coef : Reflection coefficients in Q15. void WebRtcSpl_AutoCorrToReflCoef(const int32_t* auto_corr, int use_order, int16_t* refl_coef); // The functions (with related pointer) calculate the cross-correlation between // two sequences |seq1| and |seq2|. // |seq1| is fixed and |seq2| slides as the pointer is increased with the // amount |step_seq2|. Note the arguments should obey the relationship: // |dim_seq| - 1 + |step_seq2| * (|dim_cross_correlation| - 1) < // buffer size of |seq2| // // Input: // - seq1 : First sequence (fixed throughout the correlation) // - seq2 : Second sequence (slides |step_vector2| for each // new correlation) // - dim_seq : Number of samples to use in the cross-correlation // - dim_cross_correlation : Number of cross-correlations to calculate (the // start position for |vector2| is updated for each // new one) // - right_shifts : Number of right bit shifts to use. This will // become the output Q-domain. // - step_seq2 : How many (positive or negative) steps the // |vector2| pointer should be updated for each new // cross-correlation value. // // Output: // - cross_correlation : The cross-correlation in Q(-right_shifts) typedef void (*CrossCorrelation)(int32_t* cross_correlation, const int16_t* seq1, const int16_t* seq2, size_t dim_seq, size_t dim_cross_correlation, int right_shifts, int step_seq2); extern CrossCorrelation WebRtcSpl_CrossCorrelation; void WebRtcSpl_CrossCorrelationC(int32_t* cross_correlation, const int16_t* seq1, const int16_t* seq2, size_t dim_seq, size_t dim_cross_correlation, int right_shifts, int step_seq2); #if defined(WEBRTC_HAS_NEON) void WebRtcSpl_CrossCorrelationNeon(int32_t* cross_correlation, const int16_t* seq1, const int16_t* seq2, size_t dim_seq, size_t dim_cross_correlation, int right_shifts, int step_seq2); #endif #if defined(MIPS32_LE) void WebRtcSpl_CrossCorrelation_mips(int32_t* cross_correlation, const int16_t* seq1, const int16_t* seq2, size_t dim_seq, size_t dim_cross_correlation, int right_shifts, int step_seq2); #endif // Creates (the first half of) a Hanning window. Size must be at least 1 and // at most 512. // // Input: // - size : Length of the requested Hanning window (1 to 512) // // Output: // - window : Hanning vector in Q14. void WebRtcSpl_GetHanningWindow(int16_t* window, size_t size); // Calculates y[k] = sqrt(1 - x[k]^2) for each element of the input vector // |in_vector|. Input and output values are in Q15. // // Inputs: // - in_vector : Values to calculate sqrt(1 - x^2) of // - vector_length : Length of vector |in_vector| // // Output: // - out_vector : Output values in Q15 void WebRtcSpl_SqrtOfOneMinusXSquared(int16_t* in_vector, size_t vector_length, int16_t* out_vector); // End: Signal processing operations. // Randomization functions. Implementations collected in // randomization_functions.c and descriptions at bottom of this file. int16_t WebRtcSpl_RandU(uint32_t* seed); int16_t WebRtcSpl_RandN(uint32_t* seed); int16_t WebRtcSpl_RandUArray(int16_t* vector, int16_t vector_length, uint32_t* seed); // End: Randomization functions. // Math functions int32_t WebRtcSpl_Sqrt(int32_t value); int32_t WebRtcSpl_SqrtFloor(int32_t value); // Divisions. Implementations collected in division_operations.c and // descriptions at bottom of this file. uint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den); int32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den); int16_t WebRtcSpl_DivW32W16ResW16(int32_t num, int16_t den); int32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den); int32_t WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low); // End: Divisions. int32_t WebRtcSpl_Energy(int16_t* vector, size_t vector_length, int* scale_factor); // Filter operations. size_t WebRtcSpl_FilterAR(const int16_t* ar_coef, size_t ar_coef_length, const int16_t* in_vector, size_t in_vector_length, int16_t* filter_state, size_t filter_state_length, int16_t* filter_state_low, size_t filter_state_low_length, int16_t* out_vector, int16_t* out_vector_low, size_t out_vector_low_length); // WebRtcSpl_FilterMAFastQ12(...) // // Performs a MA filtering on a vector in Q12 // // Input: // - in_vector : Input samples (state in positions // in_vector[-order] .. in_vector[-1]) // - ma_coef : Filter coefficients (in Q12) // - ma_coef_length : Number of B coefficients (order+1) // - vector_length : Number of samples to be filtered // // Output: // - out_vector : Filtered samples // void WebRtcSpl_FilterMAFastQ12(const int16_t* in_vector, int16_t* out_vector, const int16_t* ma_coef, size_t ma_coef_length, size_t vector_length); // Performs a AR filtering on a vector in Q12 // Input: // - data_in : Input samples // - data_out : State information in positions // data_out[-order] .. data_out[-1] // - coefficients : Filter coefficients (in Q12) // - coefficients_length: Number of coefficients (order+1) // - data_length : Number of samples to be filtered // Output: // - data_out : Filtered samples void WebRtcSpl_FilterARFastQ12(const int16_t* data_in, int16_t* data_out, const int16_t* __restrict coefficients, size_t coefficients_length, size_t data_length); // The functions (with related pointer) perform a MA down sampling filter // on a vector. // Input: // - data_in : Input samples (state in positions // data_in[-order] .. data_in[-1]) // - data_in_length : Number of samples in |data_in| to be filtered. // This must be at least // |delay| + |factor|*(|out_vector_length|-1) + 1) // - data_out_length : Number of down sampled samples desired // - coefficients : Filter coefficients (in Q12) // - coefficients_length: Number of coefficients (order+1) // - factor : Decimation factor // - delay : Delay of filter (compensated for in out_vector) // Output: // - data_out : Filtered samples // Return value : 0 if OK, -1 if |in_vector| is too short typedef int (*DownsampleFast)(const int16_t* data_in, size_t data_in_length, int16_t* data_out, size_t data_out_length, const int16_t* __restrict coefficients, size_t coefficients_length, int factor, size_t delay); extern DownsampleFast WebRtcSpl_DownsampleFast; int WebRtcSpl_DownsampleFastC(const int16_t* data_in, size_t data_in_length, int16_t* data_out, size_t data_out_length, const int16_t* __restrict coefficients, size_t coefficients_length, int factor, size_t delay); #if defined(WEBRTC_HAS_NEON) int WebRtcSpl_DownsampleFastNeon(const int16_t* data_in, size_t data_in_length, int16_t* data_out, size_t data_out_length, const int16_t* __restrict coefficients, size_t coefficients_length, int factor, size_t delay); #endif #if defined(MIPS32_LE) int WebRtcSpl_DownsampleFast_mips(const int16_t* data_in, size_t data_in_length, int16_t* data_out, size_t data_out_length, const int16_t* __restrict coefficients, size_t coefficients_length, int factor, size_t delay); #endif // End: Filter operations. // FFT operations int WebRtcSpl_ComplexFFT(int16_t vector[], int stages, int mode); int WebRtcSpl_ComplexIFFT(int16_t vector[], int stages, int mode); // Treat a 16-bit complex data buffer |complex_data| as an array of 32-bit // values, and swap elements whose indexes are bit-reverses of each other. // // Input: // - complex_data : Complex data buffer containing 2^|stages| real // elements interleaved with 2^|stages| imaginary // elements: [Re Im Re Im Re Im....] // - stages : Number of FFT stages. Must be at least 3 and at most // 10, since the table WebRtcSpl_kSinTable1024[] is 1024 // elements long. // // Output: // - complex_data : The complex data buffer. void WebRtcSpl_ComplexBitReverse(int16_t* __restrict complex_data, int stages); // End: FFT operations /************************************************************ * * RESAMPLING FUNCTIONS AND THEIR STRUCTS ARE DEFINED BELOW * ************************************************************/ /******************************************************************* * resample.c * * Includes the following resampling combinations * 22 kHz -> 16 kHz * 16 kHz -> 22 kHz * 22 kHz -> 8 kHz * 8 kHz -> 22 kHz * ******************************************************************/ // state structure for 22 -> 16 resampler typedef struct { int32_t S_22_44[8]; int32_t S_44_32[8]; int32_t S_32_16[8]; } WebRtcSpl_State22khzTo16khz; void WebRtcSpl_Resample22khzTo16khz(const int16_t* in, int16_t* out, WebRtcSpl_State22khzTo16khz* state, int32_t* tmpmem); void WebRtcSpl_ResetResample22khzTo16khz(WebRtcSpl_State22khzTo16khz* state); // state structure for 16 -> 22 resampler typedef struct { int32_t S_16_32[8]; int32_t S_32_22[8]; } WebRtcSpl_State16khzTo22khz; void WebRtcSpl_Resample16khzTo22khz(const int16_t* in, int16_t* out, WebRtcSpl_State16khzTo22khz* state, int32_t* tmpmem); void WebRtcSpl_ResetResample16khzTo22khz(WebRtcSpl_State16khzTo22khz* state); // state structure for 22 -> 8 resampler typedef struct { int32_t S_22_22[16]; int32_t S_22_16[8]; int32_t S_16_8[8]; } WebRtcSpl_State22khzTo8khz; void WebRtcSpl_Resample22khzTo8khz(const int16_t* in, int16_t* out, WebRtcSpl_State22khzTo8khz* state, int32_t* tmpmem); void WebRtcSpl_ResetResample22khzTo8khz(WebRtcSpl_State22khzTo8khz* state); // state structure for 8 -> 22 resampler typedef struct { int32_t S_8_16[8]; int32_t S_16_11[8]; int32_t S_11_22[8]; } WebRtcSpl_State8khzTo22khz; void WebRtcSpl_Resample8khzTo22khz(const int16_t* in, int16_t* out, WebRtcSpl_State8khzTo22khz* state, int32_t* tmpmem); void WebRtcSpl_ResetResample8khzTo22khz(WebRtcSpl_State8khzTo22khz* state); /******************************************************************* * resample_fractional.c * Functions for internal use in the other resample functions * * Includes the following resampling combinations * 48 kHz -> 32 kHz * 32 kHz -> 24 kHz * 44 kHz -> 32 kHz * ******************************************************************/ void WebRtcSpl_Resample48khzTo32khz(const int32_t* In, int32_t* Out, size_t K); void WebRtcSpl_Resample32khzTo24khz(const int32_t* In, int32_t* Out, size_t K); void WebRtcSpl_Resample44khzTo32khz(const int32_t* In, int32_t* Out, size_t K); /******************************************************************* * resample_48khz.c * * Includes the following resampling combinations * 48 kHz -> 16 kHz * 16 kHz -> 48 kHz * 48 kHz -> 8 kHz * 8 kHz -> 48 kHz * ******************************************************************/ typedef struct { int32_t S_48_48[16]; int32_t S_48_32[8]; int32_t S_32_16[8]; } WebRtcSpl_State48khzTo16khz; void WebRtcSpl_Resample48khzTo16khz(const int16_t* in, int16_t* out, WebRtcSpl_State48khzTo16khz* state, int32_t* tmpmem); void WebRtcSpl_ResetResample48khzTo16khz(WebRtcSpl_State48khzTo16khz* state); typedef struct { int32_t S_16_32[8]; int32_t S_32_24[8]; int32_t S_24_48[8]; } WebRtcSpl_State16khzTo48khz; void WebRtcSpl_Resample16khzTo48khz(const int16_t* in, int16_t* out, WebRtcSpl_State16khzTo48khz* state, int32_t* tmpmem); void WebRtcSpl_ResetResample16khzTo48khz(WebRtcSpl_State16khzTo48khz* state); typedef struct { int32_t S_48_24[8]; int32_t S_24_24[16]; int32_t S_24_16[8]; int32_t S_16_8[8]; } WebRtcSpl_State48khzTo8khz; void WebRtcSpl_Resample48khzTo8khz(const int16_t* in, int16_t* out, WebRtcSpl_State48khzTo8khz* state, int32_t* tmpmem); void WebRtcSpl_ResetResample48khzTo8khz(WebRtcSpl_State48khzTo8khz* state); typedef struct { int32_t S_8_16[8]; int32_t S_16_12[8]; int32_t S_12_24[8]; int32_t S_24_48[8]; } WebRtcSpl_State8khzTo48khz; void WebRtcSpl_Resample8khzTo48khz(const int16_t* in, int16_t* out, WebRtcSpl_State8khzTo48khz* state, int32_t* tmpmem); void WebRtcSpl_ResetResample8khzTo48khz(WebRtcSpl_State8khzTo48khz* state); /******************************************************************* * resample_by_2.c * * Includes down and up sampling by a factor of two. * ******************************************************************/ void WebRtcSpl_DownsampleBy2(const int16_t* in, size_t len, int16_t* out, int32_t* filtState); void WebRtcSpl_UpsampleBy2(const int16_t* in, size_t len, int16_t* out, int32_t* filtState); /************************************************************ * END OF RESAMPLING FUNCTIONS ************************************************************/ void WebRtcSpl_AnalysisQMF(const int16_t* in_data, size_t in_data_length, int16_t* low_band, int16_t* high_band, int32_t* filter_state1, int32_t* filter_state2); void WebRtcSpl_SynthesisQMF(const int16_t* low_band, const int16_t* high_band, size_t band_length, int16_t* out_data, int32_t* filter_state1, int32_t* filter_state2); #ifdef __cplusplus } #endif // __cplusplus #endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SIGNAL_PROCESSING_LIBRARY_H_ // // WebRtcSpl_AddSatW16(...) // WebRtcSpl_AddSatW32(...) // // Returns the result of a saturated 16-bit, respectively 32-bit, addition of // the numbers specified by the |var1| and |var2| parameters. // // Input: // - var1 : Input variable 1 // - var2 : Input variable 2 // // Return value : Added and saturated value // // // WebRtcSpl_SubSatW16(...) // WebRtcSpl_SubSatW32(...) // // Returns the result of a saturated 16-bit, respectively 32-bit, subtraction // of the numbers specified by the |var1| and |var2| parameters. // // Input: // - var1 : Input variable 1 // - var2 : Input variable 2 // // Returned value : Subtracted and saturated value // // // WebRtcSpl_GetSizeInBits(...) // // Returns the # of bits that are needed at the most to represent the number // specified by the |value| parameter. // // Input: // - value : Input value // // Return value : Number of bits needed to represent |value| // // // WebRtcSpl_NormW32(...) // // Norm returns the # of left shifts required to 32-bit normalize the 32-bit // signed number specified by the |value| parameter. // // Input: // - value : Input value // // Return value : Number of bit shifts needed to 32-bit normalize |value| // // // WebRtcSpl_NormW16(...) // // Norm returns the # of left shifts required to 16-bit normalize the 16-bit // signed number specified by the |value| parameter. // // Input: // - value : Input value // // Return value : Number of bit shifts needed to 32-bit normalize |value| // // // WebRtcSpl_NormU32(...) // // Norm returns the # of left shifts required to 32-bit normalize the unsigned // 32-bit number specified by the |value| parameter. // // Input: // - value : Input value // // Return value : Number of bit shifts needed to 32-bit normalize |value| // // // WebRtcSpl_GetScalingSquare(...) // // Returns the # of bits required to scale the samples specified in the // |in_vector| parameter so that, if the squares of the samples are added the // # of times specified by the |times| parameter, the 32-bit addition will not // overflow (result in int32_t). // // Input: // - in_vector : Input vector to check scaling on // - in_vector_length : Samples in |in_vector| // - times : Number of additions to be performed // // Return value : Number of right bit shifts needed to avoid // overflow in the addition calculation // // // WebRtcSpl_MemSetW16(...) // // Sets all the values in the int16_t vector |vector| of length // |vector_length| to the specified value |set_value| // // Input: // - vector : Pointer to the int16_t vector // - set_value : Value specified // - vector_length : Length of vector // // // WebRtcSpl_MemSetW32(...) // // Sets all the values in the int32_t vector |vector| of length // |vector_length| to the specified value |set_value| // // Input: // - vector : Pointer to the int16_t vector // - set_value : Value specified // - vector_length : Length of vector // // // WebRtcSpl_MemCpyReversedOrder(...) // // Copies all the values from the source int16_t vector |in_vector| to a // destination int16_t vector |out_vector|. It is done in reversed order, // meaning that the first sample of |in_vector| is copied to the last sample of // the |out_vector|. The procedure continues until the last sample of // |in_vector| has been copied to the first sample of |out_vector|. This // creates a reversed vector. Used in e.g. prediction in iLBC. // // Input: // - in_vector : Pointer to the first sample in a int16_t vector // of length |length| // - vector_length : Number of elements to copy // // Output: // - out_vector : Pointer to the last sample in a int16_t vector // of length |length| // // // WebRtcSpl_CopyFromEndW16(...) // // Copies the rightmost |samples| of |in_vector| (of length |in_vector_length|) // to the vector |out_vector|. // // Input: // - in_vector : Input vector // - in_vector_length : Number of samples in |in_vector| // - samples : Number of samples to extract (from right side) // from |in_vector| // // Output: // - out_vector : Vector with the requested samples // // // WebRtcSpl_ZerosArrayW16(...) // WebRtcSpl_ZerosArrayW32(...) // // Inserts the value "zero" in all positions of a w16 and a w32 vector // respectively. // // Input: // - vector_length : Number of samples in vector // // Output: // - vector : Vector containing all zeros // // // WebRtcSpl_VectorBitShiftW16(...) // WebRtcSpl_VectorBitShiftW32(...) // // Bit shifts all the values in a vector up or downwards. Different calls for // int16_t and int32_t vectors respectively. // // Input: // - vector_length : Length of vector // - in_vector : Pointer to the vector that should be bit shifted // - right_shifts : Number of right bit shifts (negative value gives left // shifts) // // Output: // - out_vector : Pointer to the result vector (can be the same as // |in_vector|) // // // WebRtcSpl_VectorBitShiftW32ToW16(...) // // Bit shifts all the values in a int32_t vector up or downwards and // stores the result as an int16_t vector. The function will saturate the // signal if needed, before storing in the output vector. // // Input: // - vector_length : Length of vector // - in_vector : Pointer to the vector that should be bit shifted // - right_shifts : Number of right bit shifts (negative value gives left // shifts) // // Output: // - out_vector : Pointer to the result vector (can be the same as // |in_vector|) // // // WebRtcSpl_ScaleVector(...) // // Performs the vector operation: // out_vector[k] = (gain*in_vector[k])>>right_shifts // // Input: // - in_vector : Input vector // - gain : Scaling gain // - vector_length : Elements in the |in_vector| // - right_shifts : Number of right bit shifts applied // // Output: // - out_vector : Output vector (can be the same as |in_vector|) // // // WebRtcSpl_ScaleVectorWithSat(...) // // Performs the vector operation: // out_vector[k] = SATURATE( (gain*in_vector[k])>>right_shifts ) // // Input: // - in_vector : Input vector // - gain : Scaling gain // - vector_length : Elements in the |in_vector| // - right_shifts : Number of right bit shifts applied // // Output: // - out_vector : Output vector (can be the same as |in_vector|) // // // WebRtcSpl_ScaleAndAddVectors(...) // // Performs the vector operation: // out_vector[k] = (gain1*in_vector1[k])>>right_shifts1 // + (gain2*in_vector2[k])>>right_shifts2 // // Input: // - in_vector1 : Input vector 1 // - gain1 : Gain to be used for vector 1 // - right_shifts1 : Right bit shift to be used for vector 1 // - in_vector2 : Input vector 2 // - gain2 : Gain to be used for vector 2 // - right_shifts2 : Right bit shift to be used for vector 2 // - vector_length : Elements in the input vectors // // Output: // - out_vector : Output vector // // // WebRtcSpl_ReverseOrderMultArrayElements(...) // // Performs the vector operation: // out_vector[n] = (in_vector[n]*window[-n])>>right_shifts // // Input: // - in_vector : Input vector // - window : Window vector (should be reversed). The pointer // should be set to the last value in the vector // - right_shifts : Number of right bit shift to be applied after the // multiplication // - vector_length : Number of elements in |in_vector| // // Output: // - out_vector : Output vector (can be same as |in_vector|) // // // WebRtcSpl_ElementwiseVectorMult(...) // // Performs the vector operation: // out_vector[n] = (in_vector[n]*window[n])>>right_shifts // // Input: // - in_vector : Input vector // - window : Window vector. // - right_shifts : Number of right bit shift to be applied after the // multiplication // - vector_length : Number of elements in |in_vector| // // Output: // - out_vector : Output vector (can be same as |in_vector|) // // // WebRtcSpl_AddVectorsAndShift(...) // // Performs the vector operation: // out_vector[k] = (in_vector1[k] + in_vector2[k])>>right_shifts // // Input: // - in_vector1 : Input vector 1 // - in_vector2 : Input vector 2 // - right_shifts : Number of right bit shift to be applied after the // multiplication // - vector_length : Number of elements in |in_vector1| and |in_vector2| // // Output: // - out_vector : Output vector (can be same as |in_vector1|) // // // WebRtcSpl_AddAffineVectorToVector(...) // // Adds an affine transformed vector to another vector |out_vector|, i.e, // performs // out_vector[k] += (in_vector[k]*gain+add_constant)>>right_shifts // // Input: // - in_vector : Input vector // - gain : Gain value, used to multiply the in vector with // - add_constant : Constant value to add (usually 1<<(right_shifts-1), // but others can be used as well // - right_shifts : Number of right bit shifts (0-16) // - vector_length : Number of samples in |in_vector| and |out_vector| // // Output: // - out_vector : Vector with the output // // // WebRtcSpl_AffineTransformVector(...) // // Affine transforms a vector, i.e, performs // out_vector[k] = (in_vector[k]*gain+add_constant)>>right_shifts // // Input: // - in_vector : Input vector // - gain : Gain value, used to multiply the in vector with // - add_constant : Constant value to add (usually 1<<(right_shifts-1), // but others can be used as well // - right_shifts : Number of right bit shifts (0-16) // - vector_length : Number of samples in |in_vector| and |out_vector| // // Output: // - out_vector : Vector with the output // // // WebRtcSpl_IncreaseSeed(...) // // Increases the seed (and returns the new value) // // Input: // - seed : Seed for random calculation // // Output: // - seed : Updated seed value // // Return value : The new seed value // // // WebRtcSpl_RandU(...) // // Produces a uniformly distributed value in the int16_t range // // Input: // - seed : Seed for random calculation // // Output: // - seed : Updated seed value // // Return value : Uniformly distributed value in the range // [Word16_MIN...Word16_MAX] // // // WebRtcSpl_RandN(...) // // Produces a normal distributed value in the int16_t range // // Input: // - seed : Seed for random calculation // // Output: // - seed : Updated seed value // // Return value : N(0,1) value in the Q13 domain // // // WebRtcSpl_RandUArray(...) // // Produces a uniformly distributed vector with elements in the int16_t // range // // Input: // - vector_length : Samples wanted in the vector // - seed : Seed for random calculation // // Output: // - vector : Vector with the uniform values // - seed : Updated seed value // // Return value : Number of samples in vector, i.e., |vector_length| // // // WebRtcSpl_Sqrt(...) // // Returns the square root of the input value |value|. The precision of this // function is integer precision, i.e., sqrt(8) gives 2 as answer. // If |value| is a negative number then 0 is returned. // // Algorithm: // // A sixth order Taylor Series expansion is used here to compute the square // root of a number y^0.5 = (1+x)^0.5 // where // x = y-1 // = 1+(x/2)-0.5*((x/2)^2+0.5*((x/2)^3-0.625*((x/2)^4+0.875*((x/2)^5) // 0.5 <= x < 1 // // Input: // - value : Value to calculate sqrt of // // Return value : Result of the sqrt calculation // // // WebRtcSpl_SqrtFloor(...) // // Returns the square root of the input value |value|. The precision of this // function is rounding down integer precision, i.e., sqrt(8) gives 2 as answer. // If |value| is a negative number then 0 is returned. // // Algorithm: // // An iterative 4 cylce/bit routine // // Input: // - value : Value to calculate sqrt of // // Return value : Result of the sqrt calculation // // // WebRtcSpl_DivU32U16(...) // // Divides a uint32_t |num| by a uint16_t |den|. // // If |den|==0, (uint32_t)0xFFFFFFFF is returned. // // Input: // - num : Numerator // - den : Denominator // // Return value : Result of the division (as a uint32_t), i.e., the // integer part of num/den. // // // WebRtcSpl_DivW32W16(...) // // Divides a int32_t |num| by a int16_t |den|. // // If |den|==0, (int32_t)0x7FFFFFFF is returned. // // Input: // - num : Numerator // - den : Denominator // // Return value : Result of the division (as a int32_t), i.e., the // integer part of num/den. // // // WebRtcSpl_DivW32W16ResW16(...) // // Divides a int32_t |num| by a int16_t |den|, assuming that the // result is less than 32768, otherwise an unpredictable result will occur. // // If |den|==0, (int16_t)0x7FFF is returned. // // Input: // - num : Numerator // - den : Denominator // // Return value : Result of the division (as a int16_t), i.e., the // integer part of num/den. // // // WebRtcSpl_DivResultInQ31(...) // // Divides a int32_t |num| by a int16_t |den|, assuming that the // absolute value of the denominator is larger than the numerator, otherwise // an unpredictable result will occur. // // Input: // - num : Numerator // - den : Denominator // // Return value : Result of the division in Q31. // // // WebRtcSpl_DivW32HiLow(...) // // Divides a int32_t |num| by a denominator in hi, low format. The // absolute value of the denominator has to be larger (or equal to) the // numerator. // // Input: // - num : Numerator // - den_hi : High part of denominator // - den_low : Low part of denominator // // Return value : Divided value in Q31 // // // WebRtcSpl_Energy(...) // // Calculates the energy of a vector // // Input: // - vector : Vector which the energy should be calculated on // - vector_length : Number of samples in vector // // Output: // - scale_factor : Number of left bit shifts needed to get the physical // energy value, i.e, to get the Q0 value // // Return value : Energy value in Q(-|scale_factor|) // // // WebRtcSpl_FilterAR(...) // // Performs a 32-bit AR filtering on a vector in Q12 // // Input: // - ar_coef : AR-coefficient vector (values in Q12), // ar_coef[0] must be 4096. // - ar_coef_length : Number of coefficients in |ar_coef|. // - in_vector : Vector to be filtered. // - in_vector_length : Number of samples in |in_vector|. // - filter_state : Current state (higher part) of the filter. // - filter_state_length : Length (in samples) of |filter_state|. // - filter_state_low : Current state (lower part) of the filter. // - filter_state_low_length : Length (in samples) of |filter_state_low|. // - out_vector_low_length : Maximum length (in samples) of // |out_vector_low|. // // Output: // - filter_state : Updated state (upper part) vector. // - filter_state_low : Updated state (lower part) vector. // - out_vector : Vector containing the upper part of the // filtered values. // - out_vector_low : Vector containing the lower part of the // filtered values. // // Return value : Number of samples in the |out_vector|. // // // WebRtcSpl_ComplexIFFT(...) // // Complex Inverse FFT // // Computes an inverse complex 2^|stages|-point FFT on the input vector, which // is in bit-reversed order. The original content of the vector is destroyed in // the process, since the input is overwritten by the output, normal-ordered, // FFT vector. With X as the input complex vector, y as the output complex // vector and with M = 2^|stages|, the following is computed: // // M-1 // y(k) = sum[X(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]] // i=0 // // The implementations are optimized for speed, not for code size. It uses the // decimation-in-time algorithm with radix-2 butterfly technique. // // Input: // - vector : In pointer to complex vector containing 2^|stages| // real elements interleaved with 2^|stages| imaginary // elements. // [ReImReImReIm....] // The elements are in Q(-scale) domain, see more on Return // Value below. // // - stages : Number of FFT stages. Must be at least 3 and at most 10, // since the table WebRtcSpl_kSinTable1024[] is 1024 // elements long. // // - mode : This parameter gives the user to choose how the FFT // should work. // mode==0: Low-complexity and Low-accuracy mode // mode==1: High-complexity and High-accuracy mode // // Output: // - vector : Out pointer to the FFT vector (the same as input). // // Return Value : The scale value that tells the number of left bit shifts // that the elements in the |vector| should be shifted with // in order to get Q0 values, i.e. the physically correct // values. The scale parameter is always 0 or positive, // except if N>1024 (|stages|>10), which returns a scale // value of -1, indicating error. // // // WebRtcSpl_ComplexFFT(...) // // Complex FFT // // Computes a complex 2^|stages|-point FFT on the input vector, which is in // bit-reversed order. The original content of the vector is destroyed in // the process, since the input is overwritten by the output, normal-ordered, // FFT vector. With x as the input complex vector, Y as the output complex // vector and with M = 2^|stages|, the following is computed: // // M-1 // Y(k) = 1/M * sum[x(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]] // i=0 // // The implementations are optimized for speed, not for code size. It uses the // decimation-in-time algorithm with radix-2 butterfly technique. // // This routine prevents overflow by scaling by 2 before each FFT stage. This is // a fixed scaling, for proper normalization - there will be log2(n) passes, so // this results in an overall factor of 1/n, distributed to maximize arithmetic // accuracy. // // Input: // - vector : In pointer to complex vector containing 2^|stages| real // elements interleaved with 2^|stages| imaginary elements. // [ReImReImReIm....] // The output is in the Q0 domain. // // - stages : Number of FFT stages. Must be at least 3 and at most 10, // since the table WebRtcSpl_kSinTable1024[] is 1024 // elements long. // // - mode : This parameter gives the user to choose how the FFT // should work. // mode==0: Low-complexity and Low-accuracy mode // mode==1: High-complexity and High-accuracy mode // // Output: // - vector : The output FFT vector is in the Q0 domain. // // Return value : The scale parameter is always 0, except if N>1024, // which returns a scale value of -1, indicating error. // // // WebRtcSpl_AnalysisQMF(...) // // Splits a 0-2*F Hz signal into two sub bands: 0-F Hz and F-2*F Hz. The // current version has F = 8000, therefore, a super-wideband audio signal is // split to lower-band 0-8 kHz and upper-band 8-16 kHz. // // Input: // - in_data : Wide band speech signal, 320 samples (10 ms) // // Input & Output: // - filter_state1 : Filter state for first All-pass filter // - filter_state2 : Filter state for second All-pass filter // // Output: // - low_band : Lower-band signal 0-8 kHz band, 160 samples (10 ms) // - high_band : Upper-band signal 8-16 kHz band (flipped in frequency // domain), 160 samples (10 ms) // // // WebRtcSpl_SynthesisQMF(...) // // Combines the two sub bands (0-F and F-2*F Hz) into a signal of 0-2*F // Hz, (current version has F = 8000 Hz). So the filter combines lower-band // (0-8 kHz) and upper-band (8-16 kHz) channels to obtain super-wideband 0-16 // kHz audio. // // Input: // - low_band : The signal with the 0-8 kHz band, 160 samples (10 ms) // - high_band : The signal with the 8-16 kHz band, 160 samples (10 ms) // // Input & Output: // - filter_state1 : Filter state for first All-pass filter // - filter_state2 : Filter state for second All-pass filter // // Output: // - out_data : Super-wideband speech signal, 0-16 kHz // // int16_t WebRtcSpl_SatW32ToW16(...) // // This function saturates a 32-bit word into a 16-bit word. // // Input: // - value32 : The value of a 32-bit word. // // Output: // - out16 : the saturated 16-bit word. // // int32_t WebRtc_MulAccumW16(...) // // This function multiply a 16-bit word by a 16-bit word, and accumulate this // value to a 32-bit integer. // // Input: // - a : The value of the first 16-bit word. // - b : The value of the second 16-bit word. // - c : The value of an 32-bit integer. // // Return Value: The value of a * b + c. // ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/include/spl_inl.h ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // This header file includes the inline functions in // the fix point signal processing library. #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_ #define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_ #include "rtc_base/compile_assert_c.h" extern const int8_t kWebRtcSpl_CountLeadingZeros32_Table[64]; // Don't call this directly except in tests! static __inline int WebRtcSpl_CountLeadingZeros32_NotBuiltin(uint32_t n) { // Normalize n by rounding up to the nearest number that is a sequence of 0 // bits followed by a sequence of 1 bits. This number has the same number of // leading zeros as the original n. There are exactly 33 such values. n |= n >> 1; n |= n >> 2; n |= n >> 4; n |= n >> 8; n |= n >> 16; // Multiply the modified n with a constant selected (by exhaustive search) // such that each of the 33 possible values of n give a product whose 6 most // significant bits are unique. Then look up the answer in the table. return kWebRtcSpl_CountLeadingZeros32_Table[(n * 0x8c0b2891) >> 26]; } // Don't call this directly except in tests! static __inline int WebRtcSpl_CountLeadingZeros64_NotBuiltin(uint64_t n) { const int leading_zeros = n >> 32 == 0 ? 32 : 0; return leading_zeros + WebRtcSpl_CountLeadingZeros32_NotBuiltin( (uint32_t)(n >> (32 - leading_zeros))); } // Returns the number of leading zero bits in the argument. static __inline int WebRtcSpl_CountLeadingZeros32(uint32_t n) { #ifdef __GNUC__ RTC_COMPILE_ASSERT(sizeof(unsigned int) == sizeof(uint32_t)); return n == 0 ? 32 : __builtin_clz(n); #else return WebRtcSpl_CountLeadingZeros32_NotBuiltin(n); #endif } // Returns the number of leading zero bits in the argument. static __inline int WebRtcSpl_CountLeadingZeros64(uint64_t n) { #ifdef __GNUC__ RTC_COMPILE_ASSERT(sizeof(unsigned long long) == sizeof(uint64_t)); // NOLINT return n == 0 ? 64 : __builtin_clzll(n); #else return WebRtcSpl_CountLeadingZeros64_NotBuiltin(n); #endif } #ifdef WEBRTC_ARCH_ARM_V7 #include "common_audio/signal_processing/include/spl_inl_armv7.h" #else #if defined(MIPS32_LE) #include "common_audio/signal_processing/include/spl_inl_mips.h" #endif #if !defined(MIPS_DSP_R1_LE) static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) { int16_t out16 = (int16_t) value32; if (value32 > 32767) out16 = 32767; else if (value32 < -32768) out16 = -32768; return out16; } static __inline int32_t WebRtcSpl_AddSatW32(int32_t a, int32_t b) { // Do the addition in unsigned numbers, since signed overflow is undefined // behavior. const int32_t sum = (int32_t)((uint32_t)a + (uint32_t)b); // a + b can't overflow if a and b have different signs. If they have the // same sign, a + b also has the same sign iff it didn't overflow. if ((a < 0) == (b < 0) && (a < 0) != (sum < 0)) { // The direction of the overflow is obvious from the sign of a + b. return sum < 0 ? INT32_MAX : INT32_MIN; } return sum; } static __inline int32_t WebRtcSpl_SubSatW32(int32_t a, int32_t b) { // Do the subtraction in unsigned numbers, since signed overflow is undefined // behavior. const int32_t diff = (int32_t)((uint32_t)a - (uint32_t)b); // a - b can't overflow if a and b have the same sign. If they have different // signs, a - b has the same sign as a iff it didn't overflow. if ((a < 0) != (b < 0) && (a < 0) != (diff < 0)) { // The direction of the overflow is obvious from the sign of a - b. return diff < 0 ? INT32_MAX : INT32_MIN; } return diff; } static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) { return WebRtcSpl_SatW32ToW16((int32_t) a + (int32_t) b); } static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) { return WebRtcSpl_SatW32ToW16((int32_t) var1 - (int32_t) var2); } #endif // #if !defined(MIPS_DSP_R1_LE) #if !defined(MIPS32_LE) static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) { return 32 - WebRtcSpl_CountLeadingZeros32(n); } // Return the number of steps a can be left-shifted without overflow, // or 0 if a == 0. static __inline int16_t WebRtcSpl_NormW32(int32_t a) { return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a < 0 ? ~a : a) - 1; } // Return the number of steps a can be left-shifted without overflow, // or 0 if a == 0. static __inline int16_t WebRtcSpl_NormU32(uint32_t a) { return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a); } // Return the number of steps a can be left-shifted without overflow, // or 0 if a == 0. static __inline int16_t WebRtcSpl_NormW16(int16_t a) { const int32_t a32 = a; return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a < 0 ? ~a32 : a32) - 17; } static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) { return (a * b + c); } #endif // #if !defined(MIPS32_LE) #endif // WEBRTC_ARCH_ARM_V7 #endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_ ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/include/spl_inl_armv7.h ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* This header file includes the inline functions for ARM processors in * the fix point signal processing library. */ #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_ARMV7_H_ #define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_ARMV7_H_ /* TODO(kma): Replace some assembly code with GCC intrinsics * (e.g. __builtin_clz). */ /* This function produces result that is not bit exact with that by the generic * C version in some cases, although the former is at least as accurate as the * later. */ static __inline int32_t WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a, int32_t b) { int32_t tmp = 0; __asm __volatile ("smulwb %0, %1, %2":"=r"(tmp):"r"(b), "r"(a)); return tmp; } static __inline int32_t WEBRTC_SPL_MUL_16_16(int16_t a, int16_t b) { int32_t tmp = 0; __asm __volatile ("smulbb %0, %1, %2":"=r"(tmp):"r"(a), "r"(b)); return tmp; } // TODO(kma): add unit test. static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) { int32_t tmp = 0; __asm __volatile ("smlabb %0, %1, %2, %3":"=r"(tmp):"r"(a), "r"(b), "r"(c)); return tmp; } static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) { int32_t s_sum = 0; __asm __volatile ("qadd16 %0, %1, %2":"=r"(s_sum):"r"(a), "r"(b)); return (int16_t) s_sum; } static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) { int32_t l_sum = 0; __asm __volatile ("qadd %0, %1, %2":"=r"(l_sum):"r"(l_var1), "r"(l_var2)); return l_sum; } static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) { int32_t l_sub = 0; __asm __volatile ("qsub %0, %1, %2":"=r"(l_sub):"r"(l_var1), "r"(l_var2)); return l_sub; } static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) { int32_t s_sub = 0; __asm __volatile ("qsub16 %0, %1, %2":"=r"(s_sub):"r"(var1), "r"(var2)); return (int16_t)s_sub; } static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) { int32_t tmp = 0; __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(n)); return (int16_t)(32 - tmp); } static __inline int16_t WebRtcSpl_NormW32(int32_t a) { int32_t tmp = 0; if (a == 0) { return 0; } else if (a < 0) { a ^= 0xFFFFFFFF; } __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a)); return (int16_t)(tmp - 1); } static __inline int16_t WebRtcSpl_NormU32(uint32_t a) { int tmp = 0; if (a == 0) return 0; __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a)); return (int16_t)tmp; } static __inline int16_t WebRtcSpl_NormW16(int16_t a) { int32_t tmp = 0; int32_t a_32 = a; if (a_32 == 0) { return 0; } else if (a_32 < 0) { a_32 ^= 0xFFFFFFFF; } __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a_32)); return (int16_t)(tmp - 17); } // TODO(kma): add unit test. static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) { int32_t out = 0; __asm __volatile ("ssat %0, #16, %1" : "=r"(out) : "r"(value32)); return (int16_t)out; } #endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_ARMV7_H_ ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/include/spl_inl_mips.h ================================================ /* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // This header file includes the inline functions in // the fix point signal processing library. #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_MIPS_H_ #define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_MIPS_H_ static __inline int32_t WEBRTC_SPL_MUL_16_16(int32_t a, int32_t b) { int32_t value32 = 0; int32_t a1 = 0, b1 = 0; __asm __volatile( #if defined(MIPS32_R2_LE) "seh %[a1], %[a] \n\t" "seh %[b1], %[b] \n\t" #else "sll %[a1], %[a], 16 \n\t" "sll %[b1], %[b], 16 \n\t" "sra %[a1], %[a1], 16 \n\t" "sra %[b1], %[b1], 16 \n\t" #endif "mul %[value32], %[a1], %[b1] \n\t" : [value32] "=r" (value32), [a1] "=&r" (a1), [b1] "=&r" (b1) : [a] "r" (a), [b] "r" (b) : "hi", "lo"); return value32; } static __inline int32_t WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a, int32_t b) { int32_t value32 = 0, b1 = 0, b2 = 0; int32_t a1 = 0; __asm __volatile( #if defined(MIPS32_R2_LE) "seh %[a1], %[a] \n\t" #else "sll %[a1], %[a], 16 \n\t" "sra %[a1], %[a1], 16 \n\t" #endif "andi %[b2], %[b], 0xFFFF \n\t" "sra %[b1], %[b], 16 \n\t" "sra %[b2], %[b2], 1 \n\t" "mul %[value32], %[a1], %[b1] \n\t" "mul %[b2], %[a1], %[b2] \n\t" "addiu %[b2], %[b2], 0x4000 \n\t" "sra %[b2], %[b2], 15 \n\t" "addu %[value32], %[value32], %[b2] \n\t" : [value32] "=&r" (value32), [b1] "=&r" (b1), [b2] "=&r" (b2), [a1] "=&r" (a1) : [a] "r" (a), [b] "r" (b) : "hi", "lo"); return value32; } #if defined(MIPS_DSP_R1_LE) static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) { __asm __volatile( "shll_s.w %[value32], %[value32], 16 \n\t" "sra %[value32], %[value32], 16 \n\t" : [value32] "+r" (value32) :); int16_t out16 = (int16_t)value32; return out16; } static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) { int32_t value32 = 0; __asm __volatile( "addq_s.ph %[value32], %[a], %[b] \n\t" : [value32] "=r" (value32) : [a] "r" (a), [b] "r" (b) ); return (int16_t)value32; } static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) { int32_t l_sum; __asm __volatile( "addq_s.w %[l_sum], %[l_var1], %[l_var2] \n\t" : [l_sum] "=r" (l_sum) : [l_var1] "r" (l_var1), [l_var2] "r" (l_var2) ); return l_sum; } static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) { int32_t value32; __asm __volatile( "subq_s.ph %[value32], %[var1], %[var2] \n\t" : [value32] "=r" (value32) : [var1] "r" (var1), [var2] "r" (var2) ); return (int16_t)value32; } static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) { int32_t l_diff; __asm __volatile( "subq_s.w %[l_diff], %[l_var1], %[l_var2] \n\t" : [l_diff] "=r" (l_diff) : [l_var1] "r" (l_var1), [l_var2] "r" (l_var2) ); return l_diff; } #endif static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) { int bits = 0; int i32 = 32; __asm __volatile( "clz %[bits], %[n] \n\t" "subu %[bits], %[i32], %[bits] \n\t" : [bits] "=&r" (bits) : [n] "r" (n), [i32] "r" (i32) ); return (int16_t)bits; } static __inline int16_t WebRtcSpl_NormW32(int32_t a) { int zeros = 0; __asm __volatile( ".set push \n\t" ".set noreorder \n\t" "bnez %[a], 1f \n\t" " sra %[zeros], %[a], 31 \n\t" "b 2f \n\t" " move %[zeros], $zero \n\t" "1: \n\t" "xor %[zeros], %[a], %[zeros] \n\t" "clz %[zeros], %[zeros] \n\t" "addiu %[zeros], %[zeros], -1 \n\t" "2: \n\t" ".set pop \n\t" : [zeros]"=&r"(zeros) : [a] "r" (a) ); return (int16_t)zeros; } static __inline int16_t WebRtcSpl_NormU32(uint32_t a) { int zeros = 0; __asm __volatile( "clz %[zeros], %[a] \n\t" : [zeros] "=r" (zeros) : [a] "r" (a) ); return (int16_t)(zeros & 0x1f); } static __inline int16_t WebRtcSpl_NormW16(int16_t a) { int zeros = 0; int a0 = a << 16; __asm __volatile( ".set push \n\t" ".set noreorder \n\t" "bnez %[a0], 1f \n\t" " sra %[zeros], %[a0], 31 \n\t" "b 2f \n\t" " move %[zeros], $zero \n\t" "1: \n\t" "xor %[zeros], %[a0], %[zeros] \n\t" "clz %[zeros], %[zeros] \n\t" "addiu %[zeros], %[zeros], -1 \n\t" "2: \n\t" ".set pop \n\t" : [zeros]"=&r"(zeros) : [a0] "r" (a0) ); return (int16_t)zeros; } static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) { int32_t res = 0, c1 = 0; __asm __volatile( #if defined(MIPS32_R2_LE) "seh %[a], %[a] \n\t" "seh %[b], %[b] \n\t" #else "sll %[a], %[a], 16 \n\t" "sll %[b], %[b], 16 \n\t" "sra %[a], %[a], 16 \n\t" "sra %[b], %[b], 16 \n\t" #endif "mul %[res], %[a], %[b] \n\t" "addu %[c1], %[c], %[res] \n\t" : [c1] "=r" (c1), [res] "=&r" (res) : [a] "r" (a), [b] "r" (b), [c] "r" (c) : "hi", "lo"); return (c1); } #endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_MIPS_H_ ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/min_max_operations.c ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file contains the implementation of functions * WebRtcSpl_MaxAbsValueW16C() * WebRtcSpl_MaxAbsValueW32C() * WebRtcSpl_MaxValueW16C() * WebRtcSpl_MaxValueW32C() * WebRtcSpl_MinValueW16C() * WebRtcSpl_MinValueW32C() * WebRtcSpl_MaxAbsIndexW16() * WebRtcSpl_MaxIndexW16() * WebRtcSpl_MaxIndexW32() * WebRtcSpl_MinIndexW16() * WebRtcSpl_MinIndexW32() * */ #include #include "rtc_base/checks.h" #include "common_audio/signal_processing/include/signal_processing_library.h" // TODO(bjorn/kma): Consolidate function pairs (e.g. combine // WebRtcSpl_MaxAbsValueW16C and WebRtcSpl_MaxAbsIndexW16 into a single one.) // TODO(kma): Move the next six functions into min_max_operations_c.c. // Maximum absolute value of word16 vector. C version for generic platforms. int16_t WebRtcSpl_MaxAbsValueW16C(const int16_t* vector, size_t length) { size_t i = 0; int absolute = 0, maximum = 0; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { absolute = abs((int)vector[i]); if (absolute > maximum) { maximum = absolute; } } // Guard the case for abs(-32768). if (maximum > WEBRTC_SPL_WORD16_MAX) { maximum = WEBRTC_SPL_WORD16_MAX; } return (int16_t)maximum; } // Maximum absolute value of word32 vector. C version for generic platforms. int32_t WebRtcSpl_MaxAbsValueW32C(const int32_t* vector, size_t length) { // Use uint32_t for the local variables, to accommodate the return value // of abs(0x80000000), which is 0x80000000. uint32_t absolute = 0, maximum = 0; size_t i = 0; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { absolute = abs((int)vector[i]); if (absolute > maximum) { maximum = absolute; } } maximum = WEBRTC_SPL_MIN(maximum, WEBRTC_SPL_WORD32_MAX); return (int32_t)maximum; } // Maximum value of word16 vector. C version for generic platforms. int16_t WebRtcSpl_MaxValueW16C(const int16_t* vector, size_t length) { int16_t maximum = WEBRTC_SPL_WORD16_MIN; size_t i = 0; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { if (vector[i] > maximum) maximum = vector[i]; } return maximum; } // Maximum value of word32 vector. C version for generic platforms. int32_t WebRtcSpl_MaxValueW32C(const int32_t* vector, size_t length) { int32_t maximum = WEBRTC_SPL_WORD32_MIN; size_t i = 0; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { if (vector[i] > maximum) maximum = vector[i]; } return maximum; } // Minimum value of word16 vector. C version for generic platforms. int16_t WebRtcSpl_MinValueW16C(const int16_t* vector, size_t length) { int16_t minimum = WEBRTC_SPL_WORD16_MAX; size_t i = 0; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { if (vector[i] < minimum) minimum = vector[i]; } return minimum; } // Minimum value of word32 vector. C version for generic platforms. int32_t WebRtcSpl_MinValueW32C(const int32_t* vector, size_t length) { int32_t minimum = WEBRTC_SPL_WORD32_MAX; size_t i = 0; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { if (vector[i] < minimum) minimum = vector[i]; } return minimum; } // Index of maximum absolute value in a word16 vector. size_t WebRtcSpl_MaxAbsIndexW16(const int16_t* vector, size_t length) { // Use type int for local variables, to accomodate the value of abs(-32768). size_t i = 0, index = 0; int absolute = 0, maximum = 0; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { absolute = abs((int)vector[i]); if (absolute > maximum) { maximum = absolute; index = i; } } return index; } // Index of maximum value in a word16 vector. size_t WebRtcSpl_MaxIndexW16(const int16_t* vector, size_t length) { size_t i = 0, index = 0; int16_t maximum = WEBRTC_SPL_WORD16_MIN; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { if (vector[i] > maximum) { maximum = vector[i]; index = i; } } return index; } // Index of maximum value in a word32 vector. size_t WebRtcSpl_MaxIndexW32(const int32_t* vector, size_t length) { size_t i = 0, index = 0; int32_t maximum = WEBRTC_SPL_WORD32_MIN; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { if (vector[i] > maximum) { maximum = vector[i]; index = i; } } return index; } // Index of minimum value in a word16 vector. size_t WebRtcSpl_MinIndexW16(const int16_t* vector, size_t length) { size_t i = 0, index = 0; int16_t minimum = WEBRTC_SPL_WORD16_MAX; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { if (vector[i] < minimum) { minimum = vector[i]; index = i; } } return index; } // Index of minimum value in a word32 vector. size_t WebRtcSpl_MinIndexW32(const int32_t* vector, size_t length) { size_t i = 0, index = 0; int32_t minimum = WEBRTC_SPL_WORD32_MAX; RTC_DCHECK_GT(length, 0); for (i = 0; i < length; i++) { if (vector[i] < minimum) { minimum = vector[i]; index = i; } } return index; } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/min_max_operations_mips.c.mips ================================================ /* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file contains the implementation of function * WebRtcSpl_MaxAbsValueW16() * * The description header can be found in signal_processing_library.h. * */ #include "rtc_base/checks.h" #include "common_audio/signal_processing/include/signal_processing_library.h" // Maximum absolute value of word16 vector. int16_t WebRtcSpl_MaxAbsValueW16_mips(const int16_t* vector, size_t length) { int32_t totMax = 0; int32_t tmp32_0, tmp32_1, tmp32_2, tmp32_3; size_t i, loop_size; RTC_DCHECK_GT(length, 0); #if defined(MIPS_DSP_R1) const int32_t* tmpvec32 = (int32_t*)vector; loop_size = length >> 4; for (i = 0; i < loop_size; i++) { __asm__ volatile ( "lw %[tmp32_0], 0(%[tmpvec32]) \n\t" "lw %[tmp32_1], 4(%[tmpvec32]) \n\t" "lw %[tmp32_2], 8(%[tmpvec32]) \n\t" "lw %[tmp32_3], 12(%[tmpvec32]) \n\t" "absq_s.ph %[tmp32_0], %[tmp32_0] \n\t" "absq_s.ph %[tmp32_1], %[tmp32_1] \n\t" "cmp.lt.ph %[totMax], %[tmp32_0] \n\t" "pick.ph %[totMax], %[tmp32_0], %[totMax] \n\t" "lw %[tmp32_0], 16(%[tmpvec32]) \n\t" "absq_s.ph %[tmp32_2], %[tmp32_2] \n\t" "cmp.lt.ph %[totMax], %[tmp32_1] \n\t" "pick.ph %[totMax], %[tmp32_1], %[totMax] \n\t" "lw %[tmp32_1], 20(%[tmpvec32]) \n\t" "absq_s.ph %[tmp32_3], %[tmp32_3] \n\t" "cmp.lt.ph %[totMax], %[tmp32_2] \n\t" "pick.ph %[totMax], %[tmp32_2], %[totMax] \n\t" "lw %[tmp32_2], 24(%[tmpvec32]) \n\t" "cmp.lt.ph %[totMax], %[tmp32_3] \n\t" "pick.ph %[totMax], %[tmp32_3], %[totMax] \n\t" "lw %[tmp32_3], 28(%[tmpvec32]) \n\t" "absq_s.ph %[tmp32_0], %[tmp32_0] \n\t" "absq_s.ph %[tmp32_1], %[tmp32_1] \n\t" "cmp.lt.ph %[totMax], %[tmp32_0] \n\t" "pick.ph %[totMax], %[tmp32_0], %[totMax] \n\t" "absq_s.ph %[tmp32_2], %[tmp32_2] \n\t" "cmp.lt.ph %[totMax], %[tmp32_1] \n\t" "pick.ph %[totMax], %[tmp32_1], %[totMax] \n\t" "absq_s.ph %[tmp32_3], %[tmp32_3] \n\t" "cmp.lt.ph %[totMax], %[tmp32_2] \n\t" "pick.ph %[totMax], %[tmp32_2], %[totMax] \n\t" "cmp.lt.ph %[totMax], %[tmp32_3] \n\t" "pick.ph %[totMax], %[tmp32_3], %[totMax] \n\t" "addiu %[tmpvec32], %[tmpvec32], 32 \n\t" : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1), [tmp32_2] "=&r" (tmp32_2), [tmp32_3] "=&r" (tmp32_3), [totMax] "+r" (totMax), [tmpvec32] "+r" (tmpvec32) : : "memory" ); } __asm__ volatile ( "rotr %[tmp32_0], %[totMax], 16 \n\t" "cmp.lt.ph %[totMax], %[tmp32_0] \n\t" "pick.ph %[totMax], %[tmp32_0], %[totMax] \n\t" "packrl.ph %[totMax], $0, %[totMax] \n\t" : [tmp32_0] "=&r" (tmp32_0), [totMax] "+r" (totMax) : ); loop_size = length & 0xf; for (i = 0; i < loop_size; i++) { __asm__ volatile ( "lh %[tmp32_0], 0(%[tmpvec32]) \n\t" "addiu %[tmpvec32], %[tmpvec32], 2 \n\t" "absq_s.w %[tmp32_0], %[tmp32_0] \n\t" "slt %[tmp32_1], %[totMax], %[tmp32_0] \n\t" "movn %[totMax], %[tmp32_0], %[tmp32_1] \n\t" : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1), [tmpvec32] "+r" (tmpvec32), [totMax] "+r" (totMax) : : "memory" ); } #else // #if defined(MIPS_DSP_R1) int32_t v16MaxMax = WEBRTC_SPL_WORD16_MAX; int32_t r, r1, r2, r3; const int16_t* tmpvector = vector; loop_size = length >> 4; for (i = 0; i < loop_size; i++) { __asm__ volatile ( "lh %[tmp32_0], 0(%[tmpvector]) \n\t" "lh %[tmp32_1], 2(%[tmpvector]) \n\t" "lh %[tmp32_2], 4(%[tmpvector]) \n\t" "lh %[tmp32_3], 6(%[tmpvector]) \n\t" "abs %[tmp32_0], %[tmp32_0] \n\t" "abs %[tmp32_1], %[tmp32_1] \n\t" "abs %[tmp32_2], %[tmp32_2] \n\t" "abs %[tmp32_3], %[tmp32_3] \n\t" "slt %[r], %[totMax], %[tmp32_0] \n\t" "movn %[totMax], %[tmp32_0], %[r] \n\t" "slt %[r1], %[totMax], %[tmp32_1] \n\t" "movn %[totMax], %[tmp32_1], %[r1] \n\t" "slt %[r2], %[totMax], %[tmp32_2] \n\t" "movn %[totMax], %[tmp32_2], %[r2] \n\t" "slt %[r3], %[totMax], %[tmp32_3] \n\t" "movn %[totMax], %[tmp32_3], %[r3] \n\t" "lh %[tmp32_0], 8(%[tmpvector]) \n\t" "lh %[tmp32_1], 10(%[tmpvector]) \n\t" "lh %[tmp32_2], 12(%[tmpvector]) \n\t" "lh %[tmp32_3], 14(%[tmpvector]) \n\t" "abs %[tmp32_0], %[tmp32_0] \n\t" "abs %[tmp32_1], %[tmp32_1] \n\t" "abs %[tmp32_2], %[tmp32_2] \n\t" "abs %[tmp32_3], %[tmp32_3] \n\t" "slt %[r], %[totMax], %[tmp32_0] \n\t" "movn %[totMax], %[tmp32_0], %[r] \n\t" "slt %[r1], %[totMax], %[tmp32_1] \n\t" "movn %[totMax], %[tmp32_1], %[r1] \n\t" "slt %[r2], %[totMax], %[tmp32_2] \n\t" "movn %[totMax], %[tmp32_2], %[r2] \n\t" "slt %[r3], %[totMax], %[tmp32_3] \n\t" "movn %[totMax], %[tmp32_3], %[r3] \n\t" "lh %[tmp32_0], 16(%[tmpvector]) \n\t" "lh %[tmp32_1], 18(%[tmpvector]) \n\t" "lh %[tmp32_2], 20(%[tmpvector]) \n\t" "lh %[tmp32_3], 22(%[tmpvector]) \n\t" "abs %[tmp32_0], %[tmp32_0] \n\t" "abs %[tmp32_1], %[tmp32_1] \n\t" "abs %[tmp32_2], %[tmp32_2] \n\t" "abs %[tmp32_3], %[tmp32_3] \n\t" "slt %[r], %[totMax], %[tmp32_0] \n\t" "movn %[totMax], %[tmp32_0], %[r] \n\t" "slt %[r1], %[totMax], %[tmp32_1] \n\t" "movn %[totMax], %[tmp32_1], %[r1] \n\t" "slt %[r2], %[totMax], %[tmp32_2] \n\t" "movn %[totMax], %[tmp32_2], %[r2] \n\t" "slt %[r3], %[totMax], %[tmp32_3] \n\t" "movn %[totMax], %[tmp32_3], %[r3] \n\t" "lh %[tmp32_0], 24(%[tmpvector]) \n\t" "lh %[tmp32_1], 26(%[tmpvector]) \n\t" "lh %[tmp32_2], 28(%[tmpvector]) \n\t" "lh %[tmp32_3], 30(%[tmpvector]) \n\t" "abs %[tmp32_0], %[tmp32_0] \n\t" "abs %[tmp32_1], %[tmp32_1] \n\t" "abs %[tmp32_2], %[tmp32_2] \n\t" "abs %[tmp32_3], %[tmp32_3] \n\t" "slt %[r], %[totMax], %[tmp32_0] \n\t" "movn %[totMax], %[tmp32_0], %[r] \n\t" "slt %[r1], %[totMax], %[tmp32_1] \n\t" "movn %[totMax], %[tmp32_1], %[r1] \n\t" "slt %[r2], %[totMax], %[tmp32_2] \n\t" "movn %[totMax], %[tmp32_2], %[r2] \n\t" "slt %[r3], %[totMax], %[tmp32_3] \n\t" "movn %[totMax], %[tmp32_3], %[r3] \n\t" "addiu %[tmpvector], %[tmpvector], 32 \n\t" : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1), [tmp32_2] "=&r" (tmp32_2), [tmp32_3] "=&r" (tmp32_3), [totMax] "+r" (totMax), [r] "=&r" (r), [tmpvector] "+r" (tmpvector), [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3) : : "memory" ); } loop_size = length & 0xf; for (i = 0; i < loop_size; i++) { __asm__ volatile ( "lh %[tmp32_0], 0(%[tmpvector]) \n\t" "addiu %[tmpvector], %[tmpvector], 2 \n\t" "abs %[tmp32_0], %[tmp32_0] \n\t" "slt %[tmp32_1], %[totMax], %[tmp32_0] \n\t" "movn %[totMax], %[tmp32_0], %[tmp32_1] \n\t" : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1), [tmpvector] "+r" (tmpvector), [totMax] "+r" (totMax) : : "memory" ); } __asm__ volatile ( "slt %[r], %[v16MaxMax], %[totMax] \n\t" "movn %[totMax], %[v16MaxMax], %[r] \n\t" : [totMax] "+r" (totMax), [r] "=&r" (r) : [v16MaxMax] "r" (v16MaxMax) ); #endif // #if defined(MIPS_DSP_R1) return (int16_t)totMax; } #if defined(MIPS_DSP_R1_LE) // Maximum absolute value of word32 vector. Version for MIPS platform. int32_t WebRtcSpl_MaxAbsValueW32_mips(const int32_t* vector, size_t length) { // Use uint32_t for the local variables, to accommodate the return value // of abs(0x80000000), which is 0x80000000. uint32_t absolute = 0, maximum = 0; int tmp1 = 0, max_value = 0x7fffffff; RTC_DCHECK_GT(length, 0); __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "1: \n\t" "lw %[absolute], 0(%[vector]) \n\t" "absq_s.w %[absolute], %[absolute] \n\t" "addiu %[length], %[length], -1 \n\t" "slt %[tmp1], %[maximum], %[absolute] \n\t" "movn %[maximum], %[absolute], %[tmp1] \n\t" "bgtz %[length], 1b \n\t" " addiu %[vector], %[vector], 4 \n\t" "slt %[tmp1], %[max_value], %[maximum] \n\t" "movn %[maximum], %[max_value], %[tmp1] \n\t" ".set pop \n\t" : [tmp1] "=&r" (tmp1), [maximum] "+r" (maximum), [absolute] "+r" (absolute) : [vector] "r" (vector), [length] "r" (length), [max_value] "r" (max_value) : "memory" ); return (int32_t)maximum; } #endif // #if defined(MIPS_DSP_R1_LE) // Maximum value of word16 vector. Version for MIPS platform. int16_t WebRtcSpl_MaxValueW16_mips(const int16_t* vector, size_t length) { int16_t maximum = WEBRTC_SPL_WORD16_MIN; int tmp1; int16_t value; RTC_DCHECK_GT(length, 0); __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "1: \n\t" "lh %[value], 0(%[vector]) \n\t" "addiu %[length], %[length], -1 \n\t" "slt %[tmp1], %[maximum], %[value] \n\t" "movn %[maximum], %[value], %[tmp1] \n\t" "bgtz %[length], 1b \n\t" " addiu %[vector], %[vector], 2 \n\t" ".set pop \n\t" : [tmp1] "=&r" (tmp1), [maximum] "+r" (maximum), [value] "=&r" (value) : [vector] "r" (vector), [length] "r" (length) : "memory" ); return maximum; } // Maximum value of word32 vector. Version for MIPS platform. int32_t WebRtcSpl_MaxValueW32_mips(const int32_t* vector, size_t length) { int32_t maximum = WEBRTC_SPL_WORD32_MIN; int tmp1, value; RTC_DCHECK_GT(length, 0); __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "1: \n\t" "lw %[value], 0(%[vector]) \n\t" "addiu %[length], %[length], -1 \n\t" "slt %[tmp1], %[maximum], %[value] \n\t" "movn %[maximum], %[value], %[tmp1] \n\t" "bgtz %[length], 1b \n\t" " addiu %[vector], %[vector], 4 \n\t" ".set pop \n\t" : [tmp1] "=&r" (tmp1), [maximum] "+r" (maximum), [value] "=&r" (value) : [vector] "r" (vector), [length] "r" (length) : "memory" ); return maximum; } // Minimum value of word16 vector. Version for MIPS platform. int16_t WebRtcSpl_MinValueW16_mips(const int16_t* vector, size_t length) { int16_t minimum = WEBRTC_SPL_WORD16_MAX; int tmp1; int16_t value; RTC_DCHECK_GT(length, 0); __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "1: \n\t" "lh %[value], 0(%[vector]) \n\t" "addiu %[length], %[length], -1 \n\t" "slt %[tmp1], %[value], %[minimum] \n\t" "movn %[minimum], %[value], %[tmp1] \n\t" "bgtz %[length], 1b \n\t" " addiu %[vector], %[vector], 2 \n\t" ".set pop \n\t" : [tmp1] "=&r" (tmp1), [minimum] "+r" (minimum), [value] "=&r" (value) : [vector] "r" (vector), [length] "r" (length) : "memory" ); return minimum; } // Minimum value of word32 vector. Version for MIPS platform. int32_t WebRtcSpl_MinValueW32_mips(const int32_t* vector, size_t length) { int32_t minimum = WEBRTC_SPL_WORD32_MAX; int tmp1, value; RTC_DCHECK_GT(length, 0); __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "1: \n\t" "lw %[value], 0(%[vector]) \n\t" "addiu %[length], %[length], -1 \n\t" "slt %[tmp1], %[value], %[minimum] \n\t" "movn %[minimum], %[value], %[tmp1] \n\t" "bgtz %[length], 1b \n\t" " addiu %[vector], %[vector], 4 \n\t" ".set pop \n\t" : [tmp1] "=&r" (tmp1), [minimum] "+r" (minimum), [value] "=&r" (value) : [vector] "r" (vector), [length] "r" (length) : "memory" ); return minimum; } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/min_max_operations_neon.c.neon ================================================ /* * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include #include "rtc_base/checks.h" #include "common_audio/signal_processing/include/signal_processing_library.h" // Maximum absolute value of word16 vector. C version for generic platforms. int16_t WebRtcSpl_MaxAbsValueW16Neon(const int16_t* vector, size_t length) { int absolute = 0, maximum = 0; RTC_DCHECK_GT(length, 0); const int16_t* p_start = vector; size_t rest = length & 7; const int16_t* p_end = vector + length - rest; int16x8_t v; uint16x8_t max_qv; max_qv = vdupq_n_u16(0); while (p_start < p_end) { v = vld1q_s16(p_start); // Note vabs doesn't change the value of -32768. v = vabsq_s16(v); // Use u16 so we don't lose the value -32768. max_qv = vmaxq_u16(max_qv, vreinterpretq_u16_s16(v)); p_start += 8; } #ifdef WEBRTC_ARCH_ARM64 maximum = (int)vmaxvq_u16(max_qv); #else uint16x4_t max_dv; max_dv = vmax_u16(vget_low_u16(max_qv), vget_high_u16(max_qv)); max_dv = vpmax_u16(max_dv, max_dv); max_dv = vpmax_u16(max_dv, max_dv); maximum = (int)vget_lane_u16(max_dv, 0); #endif p_end = vector + length; while (p_start < p_end) { absolute = abs((int)(*p_start)); if (absolute > maximum) { maximum = absolute; } p_start++; } // Guard the case for abs(-32768). if (maximum > WEBRTC_SPL_WORD16_MAX) { maximum = WEBRTC_SPL_WORD16_MAX; } return (int16_t)maximum; } // Maximum absolute value of word32 vector. NEON intrinsics version for // ARM 32-bit/64-bit platforms. int32_t WebRtcSpl_MaxAbsValueW32Neon(const int32_t* vector, size_t length) { // Use uint32_t for the local variables, to accommodate the return value // of abs(0x80000000), which is 0x80000000. uint32_t absolute = 0, maximum = 0; size_t i = 0; size_t residual = length & 0x7; RTC_DCHECK_GT(length, 0); const int32_t* p_start = vector; uint32x4_t max32x4_0 = vdupq_n_u32(0); uint32x4_t max32x4_1 = vdupq_n_u32(0); // First part, unroll the loop 8 times. for (i = 0; i < length - residual; i += 8) { int32x4_t in32x4_0 = vld1q_s32(p_start); p_start += 4; int32x4_t in32x4_1 = vld1q_s32(p_start); p_start += 4; in32x4_0 = vabsq_s32(in32x4_0); in32x4_1 = vabsq_s32(in32x4_1); // vabs doesn't change the value of 0x80000000. // Use u32 so we don't lose the value 0x80000000. max32x4_0 = vmaxq_u32(max32x4_0, vreinterpretq_u32_s32(in32x4_0)); max32x4_1 = vmaxq_u32(max32x4_1, vreinterpretq_u32_s32(in32x4_1)); } uint32x4_t max32x4 = vmaxq_u32(max32x4_0, max32x4_1); #if defined(WEBRTC_ARCH_ARM64) maximum = vmaxvq_u32(max32x4); #else uint32x2_t max32x2 = vmax_u32(vget_low_u32(max32x4), vget_high_u32(max32x4)); max32x2 = vpmax_u32(max32x2, max32x2); maximum = vget_lane_u32(max32x2, 0); #endif // Second part, do the remaining iterations (if any). for (i = residual; i > 0; i--) { absolute = abs((int)(*p_start)); if (absolute > maximum) { maximum = absolute; } p_start++; } // Guard against the case for 0x80000000. maximum = WEBRTC_SPL_MIN(maximum, WEBRTC_SPL_WORD32_MAX); return (int32_t)maximum; } // Maximum value of word16 vector. NEON intrinsics version for // ARM 32-bit/64-bit platforms. int16_t WebRtcSpl_MaxValueW16Neon(const int16_t* vector, size_t length) { int16_t maximum = WEBRTC_SPL_WORD16_MIN; size_t i = 0; size_t residual = length & 0x7; RTC_DCHECK_GT(length, 0); const int16_t* p_start = vector; int16x8_t max16x8 = vdupq_n_s16(WEBRTC_SPL_WORD16_MIN); // First part, unroll the loop 8 times. for (i = 0; i < length - residual; i += 8) { int16x8_t in16x8 = vld1q_s16(p_start); max16x8 = vmaxq_s16(max16x8, in16x8); p_start += 8; } #if defined(WEBRTC_ARCH_ARM64) maximum = vmaxvq_s16(max16x8); #else int16x4_t max16x4 = vmax_s16(vget_low_s16(max16x8), vget_high_s16(max16x8)); max16x4 = vpmax_s16(max16x4, max16x4); max16x4 = vpmax_s16(max16x4, max16x4); maximum = vget_lane_s16(max16x4, 0); #endif // Second part, do the remaining iterations (if any). for (i = residual; i > 0; i--) { if (*p_start > maximum) maximum = *p_start; p_start++; } return maximum; } // Maximum value of word32 vector. NEON intrinsics version for // ARM 32-bit/64-bit platforms. int32_t WebRtcSpl_MaxValueW32Neon(const int32_t* vector, size_t length) { int32_t maximum = WEBRTC_SPL_WORD32_MIN; size_t i = 0; size_t residual = length & 0x7; RTC_DCHECK_GT(length, 0); const int32_t* p_start = vector; int32x4_t max32x4_0 = vdupq_n_s32(WEBRTC_SPL_WORD32_MIN); int32x4_t max32x4_1 = vdupq_n_s32(WEBRTC_SPL_WORD32_MIN); // First part, unroll the loop 8 times. for (i = 0; i < length - residual; i += 8) { int32x4_t in32x4_0 = vld1q_s32(p_start); p_start += 4; int32x4_t in32x4_1 = vld1q_s32(p_start); p_start += 4; max32x4_0 = vmaxq_s32(max32x4_0, in32x4_0); max32x4_1 = vmaxq_s32(max32x4_1, in32x4_1); } int32x4_t max32x4 = vmaxq_s32(max32x4_0, max32x4_1); #if defined(WEBRTC_ARCH_ARM64) maximum = vmaxvq_s32(max32x4); #else int32x2_t max32x2 = vmax_s32(vget_low_s32(max32x4), vget_high_s32(max32x4)); max32x2 = vpmax_s32(max32x2, max32x2); maximum = vget_lane_s32(max32x2, 0); #endif // Second part, do the remaining iterations (if any). for (i = residual; i > 0; i--) { if (*p_start > maximum) maximum = *p_start; p_start++; } return maximum; } // Minimum value of word16 vector. NEON intrinsics version for // ARM 32-bit/64-bit platforms. int16_t WebRtcSpl_MinValueW16Neon(const int16_t* vector, size_t length) { int16_t minimum = WEBRTC_SPL_WORD16_MAX; size_t i = 0; size_t residual = length & 0x7; RTC_DCHECK_GT(length, 0); const int16_t* p_start = vector; int16x8_t min16x8 = vdupq_n_s16(WEBRTC_SPL_WORD16_MAX); // First part, unroll the loop 8 times. for (i = 0; i < length - residual; i += 8) { int16x8_t in16x8 = vld1q_s16(p_start); min16x8 = vminq_s16(min16x8, in16x8); p_start += 8; } #if defined(WEBRTC_ARCH_ARM64) minimum = vminvq_s16(min16x8); #else int16x4_t min16x4 = vmin_s16(vget_low_s16(min16x8), vget_high_s16(min16x8)); min16x4 = vpmin_s16(min16x4, min16x4); min16x4 = vpmin_s16(min16x4, min16x4); minimum = vget_lane_s16(min16x4, 0); #endif // Second part, do the remaining iterations (if any). for (i = residual; i > 0; i--) { if (*p_start < minimum) minimum = *p_start; p_start++; } return minimum; } // Minimum value of word32 vector. NEON intrinsics version for // ARM 32-bit/64-bit platforms. int32_t WebRtcSpl_MinValueW32Neon(const int32_t* vector, size_t length) { int32_t minimum = WEBRTC_SPL_WORD32_MAX; size_t i = 0; size_t residual = length & 0x7; RTC_DCHECK_GT(length, 0); const int32_t* p_start = vector; int32x4_t min32x4_0 = vdupq_n_s32(WEBRTC_SPL_WORD32_MAX); int32x4_t min32x4_1 = vdupq_n_s32(WEBRTC_SPL_WORD32_MAX); // First part, unroll the loop 8 times. for (i = 0; i < length - residual; i += 8) { int32x4_t in32x4_0 = vld1q_s32(p_start); p_start += 4; int32x4_t in32x4_1 = vld1q_s32(p_start); p_start += 4; min32x4_0 = vminq_s32(min32x4_0, in32x4_0); min32x4_1 = vminq_s32(min32x4_1, in32x4_1); } int32x4_t min32x4 = vminq_s32(min32x4_0, min32x4_1); #if defined(WEBRTC_ARCH_ARM64) minimum = vminvq_s32(min32x4); #else int32x2_t min32x2 = vmin_s32(vget_low_s32(min32x4), vget_high_s32(min32x4)); min32x2 = vpmin_s32(min32x2, min32x2); minimum = vget_lane_s32(min32x2, 0); #endif // Second part, do the remaining iterations (if any). for (i = residual; i > 0; i--) { if (*p_start < minimum) minimum = *p_start; p_start++; } return minimum; } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/resample_48khz.c ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file contains resampling functions between 48 kHz and nb/wb. * The description header can be found in signal_processing_library.h * */ #include #include "common_audio/signal_processing/include/signal_processing_library.h" #include "common_audio/signal_processing/resample_by_2_internal.h" //////////////////////////// ///// 48 kHz -> 16 kHz ///// //////////////////////////// // 48 -> 16 resampler void WebRtcSpl_Resample48khzTo16khz(const int16_t* in, int16_t* out, WebRtcSpl_State48khzTo16khz* state, int32_t* tmpmem) { ///// 48 --> 48(LP) ///// // int16_t in[480] // int32_t out[480] ///// WebRtcSpl_LPBy2ShortToInt(in, 480, tmpmem + 16, state->S_48_48); ///// 48 --> 32 ///// // int32_t in[480] // int32_t out[320] ///// // copy state to and from input array memcpy(tmpmem + 8, state->S_48_32, 8 * sizeof(int32_t)); memcpy(state->S_48_32, tmpmem + 488, 8 * sizeof(int32_t)); WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 160); ///// 32 --> 16 ///// // int32_t in[320] // int16_t out[160] ///// WebRtcSpl_DownBy2IntToShort(tmpmem, 320, out, state->S_32_16); } // initialize state of 48 -> 16 resampler void WebRtcSpl_ResetResample48khzTo16khz(WebRtcSpl_State48khzTo16khz* state) { memset(state->S_48_48, 0, 16 * sizeof(int32_t)); memset(state->S_48_32, 0, 8 * sizeof(int32_t)); memset(state->S_32_16, 0, 8 * sizeof(int32_t)); } //////////////////////////// ///// 16 kHz -> 48 kHz ///// //////////////////////////// // 16 -> 48 resampler void WebRtcSpl_Resample16khzTo48khz(const int16_t* in, int16_t* out, WebRtcSpl_State16khzTo48khz* state, int32_t* tmpmem) { ///// 16 --> 32 ///// // int16_t in[160] // int32_t out[320] ///// WebRtcSpl_UpBy2ShortToInt(in, 160, tmpmem + 16, state->S_16_32); ///// 32 --> 24 ///// // int32_t in[320] // int32_t out[240] // copy state to and from input array ///// memcpy(tmpmem + 8, state->S_32_24, 8 * sizeof(int32_t)); memcpy(state->S_32_24, tmpmem + 328, 8 * sizeof(int32_t)); WebRtcSpl_Resample32khzTo24khz(tmpmem + 8, tmpmem, 80); ///// 24 --> 48 ///// // int32_t in[240] // int16_t out[480] ///// WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48); } // initialize state of 16 -> 48 resampler void WebRtcSpl_ResetResample16khzTo48khz(WebRtcSpl_State16khzTo48khz* state) { memset(state->S_16_32, 0, 8 * sizeof(int32_t)); memset(state->S_32_24, 0, 8 * sizeof(int32_t)); memset(state->S_24_48, 0, 8 * sizeof(int32_t)); } //////////////////////////// ///// 48 kHz -> 8 kHz ///// //////////////////////////// // 48 -> 8 resampler void WebRtcSpl_Resample48khzTo8khz(const int16_t* in, int16_t* out, WebRtcSpl_State48khzTo8khz* state, int32_t* tmpmem) { ///// 48 --> 24 ///// // int16_t in[480] // int32_t out[240] ///// WebRtcSpl_DownBy2ShortToInt(in, 480, tmpmem + 256, state->S_48_24); ///// 24 --> 24(LP) ///// // int32_t in[240] // int32_t out[240] ///// WebRtcSpl_LPBy2IntToInt(tmpmem + 256, 240, tmpmem + 16, state->S_24_24); ///// 24 --> 16 ///// // int32_t in[240] // int32_t out[160] ///// // copy state to and from input array memcpy(tmpmem + 8, state->S_24_16, 8 * sizeof(int32_t)); memcpy(state->S_24_16, tmpmem + 248, 8 * sizeof(int32_t)); WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 80); ///// 16 --> 8 ///// // int32_t in[160] // int16_t out[80] ///// WebRtcSpl_DownBy2IntToShort(tmpmem, 160, out, state->S_16_8); } // initialize state of 48 -> 8 resampler void WebRtcSpl_ResetResample48khzTo8khz(WebRtcSpl_State48khzTo8khz* state) { memset(state->S_48_24, 0, 8 * sizeof(int32_t)); memset(state->S_24_24, 0, 16 * sizeof(int32_t)); memset(state->S_24_16, 0, 8 * sizeof(int32_t)); memset(state->S_16_8, 0, 8 * sizeof(int32_t)); } //////////////////////////// ///// 8 kHz -> 48 kHz ///// //////////////////////////// // 8 -> 48 resampler void WebRtcSpl_Resample8khzTo48khz(const int16_t* in, int16_t* out, WebRtcSpl_State8khzTo48khz* state, int32_t* tmpmem) { ///// 8 --> 16 ///// // int16_t in[80] // int32_t out[160] ///// WebRtcSpl_UpBy2ShortToInt(in, 80, tmpmem + 264, state->S_8_16); ///// 16 --> 12 ///// // int32_t in[160] // int32_t out[120] ///// // copy state to and from input array memcpy(tmpmem + 256, state->S_16_12, 8 * sizeof(int32_t)); memcpy(state->S_16_12, tmpmem + 416, 8 * sizeof(int32_t)); WebRtcSpl_Resample32khzTo24khz(tmpmem + 256, tmpmem + 240, 40); ///// 12 --> 24 ///// // int32_t in[120] // int16_t out[240] ///// WebRtcSpl_UpBy2IntToInt(tmpmem + 240, 120, tmpmem, state->S_12_24); ///// 24 --> 48 ///// // int32_t in[240] // int16_t out[480] ///// WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48); } // initialize state of 8 -> 48 resampler void WebRtcSpl_ResetResample8khzTo48khz(WebRtcSpl_State8khzTo48khz* state) { memset(state->S_8_16, 0, 8 * sizeof(int32_t)); memset(state->S_16_12, 0, 8 * sizeof(int32_t)); memset(state->S_12_24, 0, 8 * sizeof(int32_t)); memset(state->S_24_48, 0, 8 * sizeof(int32_t)); } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/resample_by_2_internal.c ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This header file contains some internal resampling functions. * */ #include "common_audio/signal_processing/resample_by_2_internal.h" #include "rtc_base/sanitizer.h" // allpass filter coefficients. static const int16_t kResampleAllpass[2][3] = { {821, 6110, 12382}, {3050, 9368, 15063} }; // // decimator // input: int32_t (shifted 15 positions to the left, + offset 16384) OVERWRITTEN! // output: int16_t (saturated) (of length len/2) // state: filter state array; length = 8 void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486 WebRtcSpl_DownBy2IntToShort(int32_t *in, int32_t len, int16_t *out, int32_t *state) { int32_t tmp0, tmp1, diff; int32_t i; len >>= 1; // lower allpass filter (operates on even input samples) for (i = 0; i < len; i++) { tmp0 = in[i << 1]; diff = tmp0 - state[1]; // UBSan: -1771017321 - 999586185 cannot be represented in type 'int' // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[0] + diff * kResampleAllpass[1][0]; state[0] = tmp0; diff = tmp1 - state[2]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[1] + diff * kResampleAllpass[1][1]; state[1] = tmp1; diff = tmp0 - state[3]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[3] = state[2] + diff * kResampleAllpass[1][2]; state[2] = tmp0; // divide by two and store temporarily in[i << 1] = (state[3] >> 1); } in++; // upper allpass filter (operates on odd input samples) for (i = 0; i < len; i++) { tmp0 = in[i << 1]; diff = tmp0 - state[5]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[4] + diff * kResampleAllpass[0][0]; state[4] = tmp0; diff = tmp1 - state[6]; // scale down and round diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[5] + diff * kResampleAllpass[0][1]; state[5] = tmp1; diff = tmp0 - state[7]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[7] = state[6] + diff * kResampleAllpass[0][2]; state[6] = tmp0; // divide by two and store temporarily in[i << 1] = (state[7] >> 1); } in--; // combine allpass outputs for (i = 0; i < len; i += 2) { // divide by two, add both allpass outputs and round tmp0 = (in[i << 1] + in[(i << 1) + 1]) >> 15; tmp1 = (in[(i << 1) + 2] + in[(i << 1) + 3]) >> 15; if (tmp0 > (int32_t)0x00007FFF) tmp0 = 0x00007FFF; if (tmp0 < (int32_t)0xFFFF8000) tmp0 = 0xFFFF8000; out[i] = (int16_t)tmp0; if (tmp1 > (int32_t)0x00007FFF) tmp1 = 0x00007FFF; if (tmp1 < (int32_t)0xFFFF8000) tmp1 = 0xFFFF8000; out[i + 1] = (int16_t)tmp1; } } // // decimator // input: int16_t // output: int32_t (shifted 15 positions to the left, + offset 16384) (of length len/2) // state: filter state array; length = 8 void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486 WebRtcSpl_DownBy2ShortToInt(const int16_t *in, int32_t len, int32_t *out, int32_t *state) { int32_t tmp0, tmp1, diff; int32_t i; len >>= 1; // lower allpass filter (operates on even input samples) for (i = 0; i < len; i++) { tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14); diff = tmp0 - state[1]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[0] + diff * kResampleAllpass[1][0]; state[0] = tmp0; diff = tmp1 - state[2]; // UBSan: -1379909682 - 834099714 cannot be represented in type 'int' // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[1] + diff * kResampleAllpass[1][1]; state[1] = tmp1; diff = tmp0 - state[3]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[3] = state[2] + diff * kResampleAllpass[1][2]; state[2] = tmp0; // divide by two and store temporarily out[i] = (state[3] >> 1); } in++; // upper allpass filter (operates on odd input samples) for (i = 0; i < len; i++) { tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14); diff = tmp0 - state[5]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[4] + diff * kResampleAllpass[0][0]; state[4] = tmp0; diff = tmp1 - state[6]; // scale down and round diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[5] + diff * kResampleAllpass[0][1]; state[5] = tmp1; diff = tmp0 - state[7]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[7] = state[6] + diff * kResampleAllpass[0][2]; state[6] = tmp0; // divide by two and store temporarily out[i] += (state[7] >> 1); } in--; } // // interpolator // input: int16_t // output: int32_t (normalized, not saturated) (of length len*2) // state: filter state array; length = 8 void WebRtcSpl_UpBy2ShortToInt(const int16_t *in, int32_t len, int32_t *out, int32_t *state) { int32_t tmp0, tmp1, diff; int32_t i; // upper allpass filter (generates odd output samples) for (i = 0; i < len; i++) { tmp0 = ((int32_t)in[i] << 15) + (1 << 14); diff = tmp0 - state[5]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[4] + diff * kResampleAllpass[0][0]; state[4] = tmp0; diff = tmp1 - state[6]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[5] + diff * kResampleAllpass[0][1]; state[5] = tmp1; diff = tmp0 - state[7]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[7] = state[6] + diff * kResampleAllpass[0][2]; state[6] = tmp0; // scale down, round and store out[i << 1] = state[7] >> 15; } out++; // lower allpass filter (generates even output samples) for (i = 0; i < len; i++) { tmp0 = ((int32_t)in[i] << 15) + (1 << 14); diff = tmp0 - state[1]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[0] + diff * kResampleAllpass[1][0]; state[0] = tmp0; diff = tmp1 - state[2]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[1] + diff * kResampleAllpass[1][1]; state[1] = tmp1; diff = tmp0 - state[3]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[3] = state[2] + diff * kResampleAllpass[1][2]; state[2] = tmp0; // scale down, round and store out[i << 1] = state[3] >> 15; } } // // interpolator // input: int32_t (shifted 15 positions to the left, + offset 16384) // output: int32_t (shifted 15 positions to the left, + offset 16384) (of length len*2) // state: filter state array; length = 8 void WebRtcSpl_UpBy2IntToInt(const int32_t *in, int32_t len, int32_t *out, int32_t *state) { int32_t tmp0, tmp1, diff; int32_t i; // upper allpass filter (generates odd output samples) for (i = 0; i < len; i++) { tmp0 = in[i]; diff = tmp0 - state[5]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[4] + diff * kResampleAllpass[0][0]; state[4] = tmp0; diff = tmp1 - state[6]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[5] + diff * kResampleAllpass[0][1]; state[5] = tmp1; diff = tmp0 - state[7]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[7] = state[6] + diff * kResampleAllpass[0][2]; state[6] = tmp0; // scale down, round and store out[i << 1] = state[7]; } out++; // lower allpass filter (generates even output samples) for (i = 0; i < len; i++) { tmp0 = in[i]; diff = tmp0 - state[1]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[0] + diff * kResampleAllpass[1][0]; state[0] = tmp0; diff = tmp1 - state[2]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[1] + diff * kResampleAllpass[1][1]; state[1] = tmp1; diff = tmp0 - state[3]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[3] = state[2] + diff * kResampleAllpass[1][2]; state[2] = tmp0; // scale down, round and store out[i << 1] = state[3]; } } // // interpolator // input: int32_t (shifted 15 positions to the left, + offset 16384) // output: int16_t (saturated) (of length len*2) // state: filter state array; length = 8 void WebRtcSpl_UpBy2IntToShort(const int32_t *in, int32_t len, int16_t *out, int32_t *state) { int32_t tmp0, tmp1, diff; int32_t i; // upper allpass filter (generates odd output samples) for (i = 0; i < len; i++) { tmp0 = in[i]; diff = tmp0 - state[5]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[4] + diff * kResampleAllpass[0][0]; state[4] = tmp0; diff = tmp1 - state[6]; // scale down and round diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[5] + diff * kResampleAllpass[0][1]; state[5] = tmp1; diff = tmp0 - state[7]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[7] = state[6] + diff * kResampleAllpass[0][2]; state[6] = tmp0; // scale down, saturate and store tmp1 = state[7] >> 15; if (tmp1 > (int32_t)0x00007FFF) tmp1 = 0x00007FFF; if (tmp1 < (int32_t)0xFFFF8000) tmp1 = 0xFFFF8000; out[i << 1] = (int16_t)tmp1; } out++; // lower allpass filter (generates even output samples) for (i = 0; i < len; i++) { tmp0 = in[i]; diff = tmp0 - state[1]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[0] + diff * kResampleAllpass[1][0]; state[0] = tmp0; diff = tmp1 - state[2]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[1] + diff * kResampleAllpass[1][1]; state[1] = tmp1; diff = tmp0 - state[3]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[3] = state[2] + diff * kResampleAllpass[1][2]; state[2] = tmp0; // scale down, saturate and store tmp1 = state[3] >> 15; if (tmp1 > (int32_t)0x00007FFF) tmp1 = 0x00007FFF; if (tmp1 < (int32_t)0xFFFF8000) tmp1 = 0xFFFF8000; out[i << 1] = (int16_t)tmp1; } } // lowpass filter // input: int16_t // output: int32_t (normalized, not saturated) // state: filter state array; length = 8 void WebRtcSpl_LPBy2ShortToInt(const int16_t* in, int32_t len, int32_t* out, int32_t* state) { int32_t tmp0, tmp1, diff; int32_t i; len >>= 1; // lower allpass filter: odd input -> even output samples in++; // initial state of polyphase delay element tmp0 = state[12]; for (i = 0; i < len; i++) { diff = tmp0 - state[1]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[0] + diff * kResampleAllpass[1][0]; state[0] = tmp0; diff = tmp1 - state[2]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[1] + diff * kResampleAllpass[1][1]; state[1] = tmp1; diff = tmp0 - state[3]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[3] = state[2] + diff * kResampleAllpass[1][2]; state[2] = tmp0; // scale down, round and store out[i << 1] = state[3] >> 1; tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14); } in--; // upper allpass filter: even input -> even output samples for (i = 0; i < len; i++) { tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14); diff = tmp0 - state[5]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[4] + diff * kResampleAllpass[0][0]; state[4] = tmp0; diff = tmp1 - state[6]; // scale down and round diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[5] + diff * kResampleAllpass[0][1]; state[5] = tmp1; diff = tmp0 - state[7]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[7] = state[6] + diff * kResampleAllpass[0][2]; state[6] = tmp0; // average the two allpass outputs, scale down and store out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15; } // switch to odd output samples out++; // lower allpass filter: even input -> odd output samples for (i = 0; i < len; i++) { tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14); diff = tmp0 - state[9]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[8] + diff * kResampleAllpass[1][0]; state[8] = tmp0; diff = tmp1 - state[10]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[9] + diff * kResampleAllpass[1][1]; state[9] = tmp1; diff = tmp0 - state[11]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[11] = state[10] + diff * kResampleAllpass[1][2]; state[10] = tmp0; // scale down, round and store out[i << 1] = state[11] >> 1; } // upper allpass filter: odd input -> odd output samples in++; for (i = 0; i < len; i++) { tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14); diff = tmp0 - state[13]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[12] + diff * kResampleAllpass[0][0]; state[12] = tmp0; diff = tmp1 - state[14]; // scale down and round diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[13] + diff * kResampleAllpass[0][1]; state[13] = tmp1; diff = tmp0 - state[15]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[15] = state[14] + diff * kResampleAllpass[0][2]; state[14] = tmp0; // average the two allpass outputs, scale down and store out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15; } } // lowpass filter // input: int32_t (shifted 15 positions to the left, + offset 16384) // output: int32_t (normalized, not saturated) // state: filter state array; length = 8 void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486 WebRtcSpl_LPBy2IntToInt(const int32_t* in, int32_t len, int32_t* out, int32_t* state) { int32_t tmp0, tmp1, diff; int32_t i; len >>= 1; // lower allpass filter: odd input -> even output samples in++; // initial state of polyphase delay element tmp0 = state[12]; for (i = 0; i < len; i++) { diff = tmp0 - state[1]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[0] + diff * kResampleAllpass[1][0]; state[0] = tmp0; diff = tmp1 - state[2]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[1] + diff * kResampleAllpass[1][1]; state[1] = tmp1; diff = tmp0 - state[3]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[3] = state[2] + diff * kResampleAllpass[1][2]; state[2] = tmp0; // scale down, round and store out[i << 1] = state[3] >> 1; tmp0 = in[i << 1]; } in--; // upper allpass filter: even input -> even output samples for (i = 0; i < len; i++) { tmp0 = in[i << 1]; diff = tmp0 - state[5]; // UBSan: -794814117 - 1566149201 cannot be represented in type 'int' // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[4] + diff * kResampleAllpass[0][0]; state[4] = tmp0; diff = tmp1 - state[6]; // scale down and round diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[5] + diff * kResampleAllpass[0][1]; state[5] = tmp1; diff = tmp0 - state[7]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[7] = state[6] + diff * kResampleAllpass[0][2]; state[6] = tmp0; // average the two allpass outputs, scale down and store out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15; } // switch to odd output samples out++; // lower allpass filter: even input -> odd output samples for (i = 0; i < len; i++) { tmp0 = in[i << 1]; diff = tmp0 - state[9]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[8] + diff * kResampleAllpass[1][0]; state[8] = tmp0; diff = tmp1 - state[10]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[9] + diff * kResampleAllpass[1][1]; state[9] = tmp1; diff = tmp0 - state[11]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[11] = state[10] + diff * kResampleAllpass[1][2]; state[10] = tmp0; // scale down, round and store out[i << 1] = state[11] >> 1; } // upper allpass filter: odd input -> odd output samples in++; for (i = 0; i < len; i++) { tmp0 = in[i << 1]; diff = tmp0 - state[13]; // scale down and round diff = (diff + (1 << 13)) >> 14; tmp1 = state[12] + diff * kResampleAllpass[0][0]; state[12] = tmp0; diff = tmp1 - state[14]; // scale down and round diff = diff >> 14; if (diff < 0) diff += 1; tmp0 = state[13] + diff * kResampleAllpass[0][1]; state[13] = tmp1; diff = tmp0 - state[15]; // scale down and truncate diff = diff >> 14; if (diff < 0) diff += 1; state[15] = state[14] + diff * kResampleAllpass[0][2]; state[14] = tmp0; // average the two allpass outputs, scale down and store out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15; } } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/resample_by_2_internal.h ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This header file contains some internal resampling functions. * */ #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_RESAMPLE_BY_2_INTERNAL_H_ #define COMMON_AUDIO_SIGNAL_PROCESSING_RESAMPLE_BY_2_INTERNAL_H_ #include "typedefs.h" // NOLINT(build/include) /******************************************************************* * resample_by_2_fast.c * Functions for internal use in the other resample functions ******************************************************************/ void WebRtcSpl_DownBy2IntToShort(int32_t *in, int32_t len, int16_t *out, int32_t *state); void WebRtcSpl_DownBy2ShortToInt(const int16_t *in, int32_t len, int32_t *out, int32_t *state); void WebRtcSpl_UpBy2ShortToInt(const int16_t *in, int32_t len, int32_t *out, int32_t *state); void WebRtcSpl_UpBy2IntToInt(const int32_t *in, int32_t len, int32_t *out, int32_t *state); void WebRtcSpl_UpBy2IntToShort(const int32_t *in, int32_t len, int16_t *out, int32_t *state); void WebRtcSpl_LPBy2ShortToInt(const int16_t* in, int32_t len, int32_t* out, int32_t* state); void WebRtcSpl_LPBy2IntToInt(const int32_t* in, int32_t len, int32_t* out, int32_t* state); #endif // COMMON_AUDIO_SIGNAL_PROCESSING_RESAMPLE_BY_2_INTERNAL_H_ ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/resample_fractional.c ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file contains the resampling functions between 48, 44, 32 and 24 kHz. * The description headers can be found in signal_processing_library.h * */ #include "common_audio/signal_processing/include/signal_processing_library.h" // interpolation coefficients static const int16_t kCoefficients48To32[2][8] = { {778, -2050, 1087, 23285, 12903, -3783, 441, 222}, {222, 441, -3783, 12903, 23285, 1087, -2050, 778} }; static const int16_t kCoefficients32To24[3][8] = { {767, -2362, 2434, 24406, 10620, -3838, 721, 90}, {386, -381, -2646, 19062, 19062, -2646, -381, 386}, {90, 721, -3838, 10620, 24406, 2434, -2362, 767} }; static const int16_t kCoefficients44To32[4][9] = { {117, -669, 2245, -6183, 26267, 13529, -3245, 845, -138}, {-101, 612, -2283, 8532, 29790, -5138, 1789, -524, 91}, {50, -292, 1016, -3064, 32010, 3933, -1147, 315, -53}, {-156, 974, -3863, 18603, 21691, -6246, 2353, -712, 126} }; // Resampling ratio: 2/3 // input: int32_t (normalized, not saturated) :: current_frame 3 * K // output: int32_t (shifted 15 positions to the left, + offset 16384) :: current_frame 2 * K // K: number of blocks void WebRtcSpl_Resample48khzTo32khz(const int32_t *In, int32_t *Out, size_t K) { ///////////////////////////////////////////////////////////// // Filter operation: // // Perform resampling (3 input samples -> 2 output samples); // process in sub blocks of current_frame 3 samples. int32_t tmp; size_t m; for (m = 0; m < K; m++) { tmp = 1 << 14; tmp += kCoefficients48To32[0][0] * In[0]; tmp += kCoefficients48To32[0][1] * In[1]; tmp += kCoefficients48To32[0][2] * In[2]; tmp += kCoefficients48To32[0][3] * In[3]; tmp += kCoefficients48To32[0][4] * In[4]; tmp += kCoefficients48To32[0][5] * In[5]; tmp += kCoefficients48To32[0][6] * In[6]; tmp += kCoefficients48To32[0][7] * In[7]; Out[0] = tmp; tmp = 1 << 14; tmp += kCoefficients48To32[1][0] * In[1]; tmp += kCoefficients48To32[1][1] * In[2]; tmp += kCoefficients48To32[1][2] * In[3]; tmp += kCoefficients48To32[1][3] * In[4]; tmp += kCoefficients48To32[1][4] * In[5]; tmp += kCoefficients48To32[1][5] * In[6]; tmp += kCoefficients48To32[1][6] * In[7]; tmp += kCoefficients48To32[1][7] * In[8]; Out[1] = tmp; // update pointers In += 3; Out += 2; } } // Resampling ratio: 3/4 // input: int32_t (normalized, not saturated) :: current_frame 4 * K // output: int32_t (shifted 15 positions to the left, + offset 16384) :: current_frame 3 * K // K: number of blocks void WebRtcSpl_Resample32khzTo24khz(const int32_t *In, int32_t *Out, size_t K) { ///////////////////////////////////////////////////////////// // Filter operation: // // Perform resampling (4 input samples -> 3 output samples); // process in sub blocks of current_frame 4 samples. size_t m; int32_t tmp; for (m = 0; m < K; m++) { tmp = 1 << 14; tmp += kCoefficients32To24[0][0] * In[0]; tmp += kCoefficients32To24[0][1] * In[1]; tmp += kCoefficients32To24[0][2] * In[2]; tmp += kCoefficients32To24[0][3] * In[3]; tmp += kCoefficients32To24[0][4] * In[4]; tmp += kCoefficients32To24[0][5] * In[5]; tmp += kCoefficients32To24[0][6] * In[6]; tmp += kCoefficients32To24[0][7] * In[7]; Out[0] = tmp; tmp = 1 << 14; tmp += kCoefficients32To24[1][0] * In[1]; tmp += kCoefficients32To24[1][1] * In[2]; tmp += kCoefficients32To24[1][2] * In[3]; tmp += kCoefficients32To24[1][3] * In[4]; tmp += kCoefficients32To24[1][4] * In[5]; tmp += kCoefficients32To24[1][5] * In[6]; tmp += kCoefficients32To24[1][6] * In[7]; tmp += kCoefficients32To24[1][7] * In[8]; Out[1] = tmp; tmp = 1 << 14; tmp += kCoefficients32To24[2][0] * In[2]; tmp += kCoefficients32To24[2][1] * In[3]; tmp += kCoefficients32To24[2][2] * In[4]; tmp += kCoefficients32To24[2][3] * In[5]; tmp += kCoefficients32To24[2][4] * In[6]; tmp += kCoefficients32To24[2][5] * In[7]; tmp += kCoefficients32To24[2][6] * In[8]; tmp += kCoefficients32To24[2][7] * In[9]; Out[2] = tmp; // update pointers In += 4; Out += 3; } } // // fractional resampling filters // Fout = 11/16 * Fin // Fout = 8/11 * Fin // // compute two inner-products and store them to output array static void WebRtcSpl_ResampDotProduct(const int32_t *in1, const int32_t *in2, const int16_t *coef_ptr, int32_t *out1, int32_t *out2) { int32_t tmp1 = 16384; int32_t tmp2 = 16384; int16_t coef; coef = coef_ptr[0]; tmp1 += coef * in1[0]; tmp2 += coef * in2[-0]; coef = coef_ptr[1]; tmp1 += coef * in1[1]; tmp2 += coef * in2[-1]; coef = coef_ptr[2]; tmp1 += coef * in1[2]; tmp2 += coef * in2[-2]; coef = coef_ptr[3]; tmp1 += coef * in1[3]; tmp2 += coef * in2[-3]; coef = coef_ptr[4]; tmp1 += coef * in1[4]; tmp2 += coef * in2[-4]; coef = coef_ptr[5]; tmp1 += coef * in1[5]; tmp2 += coef * in2[-5]; coef = coef_ptr[6]; tmp1 += coef * in1[6]; tmp2 += coef * in2[-6]; coef = coef_ptr[7]; tmp1 += coef * in1[7]; tmp2 += coef * in2[-7]; coef = coef_ptr[8]; *out1 = tmp1 + coef * in1[8]; *out2 = tmp2 + coef * in2[-8]; } // Resampling ratio: 8/11 // input: int32_t (normalized, not saturated) :: current_frame 11 * K // output: int32_t (shifted 15 positions to the left, + offset 16384) :: current_frame 8 * K // K: number of blocks void WebRtcSpl_Resample44khzTo32khz(const int32_t *In, int32_t *Out, size_t K) { ///////////////////////////////////////////////////////////// // Filter operation: // // Perform resampling (11 input samples -> 8 output samples); // process in sub blocks of current_frame 11 samples. int32_t tmp; size_t m; for (m = 0; m < K; m++) { tmp = 1 << 14; // first output sample Out[0] = ((int32_t)In[3] << 15) + tmp; // sum and accumulate filter coefficients and input samples tmp += kCoefficients44To32[3][0] * In[5]; tmp += kCoefficients44To32[3][1] * In[6]; tmp += kCoefficients44To32[3][2] * In[7]; tmp += kCoefficients44To32[3][3] * In[8]; tmp += kCoefficients44To32[3][4] * In[9]; tmp += kCoefficients44To32[3][5] * In[10]; tmp += kCoefficients44To32[3][6] * In[11]; tmp += kCoefficients44To32[3][7] * In[12]; tmp += kCoefficients44To32[3][8] * In[13]; Out[4] = tmp; // sum and accumulate filter coefficients and input samples WebRtcSpl_ResampDotProduct(&In[0], &In[17], kCoefficients44To32[0], &Out[1], &Out[7]); // sum and accumulate filter coefficients and input samples WebRtcSpl_ResampDotProduct(&In[2], &In[15], kCoefficients44To32[1], &Out[2], &Out[6]); // sum and accumulate filter coefficients and input samples WebRtcSpl_ResampDotProduct(&In[3], &In[14], kCoefficients44To32[2], &Out[3], &Out[5]); // update pointers In += 11; Out += 8; } } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/spl_init.c ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* The global function contained in this file initializes SPL function * pointers, currently only for ARM platforms. * * Some code came from common/rtcd.c in the WebM project. */ #include "common_audio/signal_processing/include/signal_processing_library.h" #include "system_wrappers/include/cpu_features_wrapper.h" /* Declare function pointers. */ MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16; MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32; MaxValueW16 WebRtcSpl_MaxValueW16; MaxValueW32 WebRtcSpl_MaxValueW32; MinValueW16 WebRtcSpl_MinValueW16; MinValueW32 WebRtcSpl_MinValueW32; CrossCorrelation WebRtcSpl_CrossCorrelation; DownsampleFast WebRtcSpl_DownsampleFast; ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound; #if (!defined(WEBRTC_HAS_NEON)) && !defined(MIPS32_LE) /* Initialize function pointers to the generic C version. */ static void InitPointersToC() { WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16C; WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C; WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16C; WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32C; WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16C; WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32C; WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationC; WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastC; WebRtcSpl_ScaleAndAddVectorsWithRound = WebRtcSpl_ScaleAndAddVectorsWithRoundC; } #endif #if defined(WEBRTC_HAS_NEON) /* Initialize function pointers to the Neon version. */ static void InitPointersToNeon() { WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16Neon; WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32Neon; WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16Neon; WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32Neon; WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16Neon; WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32Neon; WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationNeon; WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastNeon; WebRtcSpl_ScaleAndAddVectorsWithRound = WebRtcSpl_ScaleAndAddVectorsWithRoundC; } #endif #if defined(MIPS32_LE) /* Initialize function pointers to the MIPS version. */ static void InitPointersToMIPS() { WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16_mips; WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16_mips; WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32_mips; WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16_mips; WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32_mips; WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelation_mips; WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFast_mips; #if defined(MIPS_DSP_R1_LE) WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32_mips; WebRtcSpl_ScaleAndAddVectorsWithRound = WebRtcSpl_ScaleAndAddVectorsWithRound_mips; #else WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C; WebRtcSpl_ScaleAndAddVectorsWithRound = WebRtcSpl_ScaleAndAddVectorsWithRoundC; #endif } #endif static void InitFunctionPointers(void) { #if defined(WEBRTC_HAS_NEON) InitPointersToNeon(); #elif defined(MIPS32_LE) InitPointersToMIPS(); #else InitPointersToC(); #endif /* WEBRTC_HAS_NEON */ } #if defined(WEBRTC_POSIX) #include static void once(void (*func)(void)) { static pthread_once_t lock = PTHREAD_ONCE_INIT; pthread_once(&lock, func); } #elif defined(_WIN32) #include static void once(void (*func)(void)) { /* Didn't use InitializeCriticalSection() since there's no race-simple_vad_free context * in which to execute it. * * TODO(kma): Change to different implementation (e.g. * InterlockedCompareExchangePointer) to avoid issues similar to * http://code.google.com/p/webm/issues/detail?id=467. */ static CRITICAL_SECTION lock = {(void *)((size_t)-1), -1, 0, 0, 0, 0}; static int done = 0; EnterCriticalSection(&lock); if (!done) { func(); done = 1; } LeaveCriticalSection(&lock); } /* There's no fallback version as an #else block here to ensure thread safety. * In case of neither pthread for WEBRTC_POSIX nor _WIN32 is present, build * system should pick it up. */ #endif /* WEBRTC_POSIX */ void WebRtcSpl_Init() { once(InitFunctionPointers); } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/vector_scaling_operations.c ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file contains implementations of the functions * WebRtcSpl_VectorBitShiftW16() * WebRtcSpl_VectorBitShiftW32() * WebRtcSpl_VectorBitShiftW32ToW16() * WebRtcSpl_ScaleVector() * WebRtcSpl_ScaleVectorWithSat() * WebRtcSpl_ScaleAndAddVectors() * WebRtcSpl_ScaleAndAddVectorsWithRoundC() */ #include "common_audio/signal_processing/include/signal_processing_library.h" void WebRtcSpl_VectorBitShiftW16(int16_t *res, size_t length, const int16_t *in, int16_t right_shifts) { size_t i; if (right_shifts > 0) { for (i = length; i > 0; i--) { (*res++) = ((*in++) >> right_shifts); } } else { for (i = length; i > 0; i--) { (*res++) = ((*in++) * (1 << (-right_shifts))); } } } void WebRtcSpl_VectorBitShiftW32(int32_t *out_vector, size_t vector_length, const int32_t *in_vector, int16_t right_shifts) { size_t i; if (right_shifts > 0) { for (i = vector_length; i > 0; i--) { (*out_vector++) = ((*in_vector++) >> right_shifts); } } else { for (i = vector_length; i > 0; i--) { (*out_vector++) = ((*in_vector++) << (-right_shifts)); } } } void WebRtcSpl_VectorBitShiftW32ToW16(int16_t* out, size_t length, const int32_t* in, int right_shifts) { size_t i; int32_t tmp_w32; if (right_shifts >= 0) { for (i = length; i > 0; i--) { tmp_w32 = (*in++) >> right_shifts; (*out++) = WebRtcSpl_SatW32ToW16(tmp_w32); } } else { int left_shifts = -right_shifts; for (i = length; i > 0; i--) { tmp_w32 = (*in++) << left_shifts; (*out++) = WebRtcSpl_SatW32ToW16(tmp_w32); } } } void WebRtcSpl_ScaleVector(const int16_t *in_vector, int16_t *out_vector, int16_t gain, size_t in_vector_length, int16_t right_shifts) { // Performs vector operation: out_vector = (gain*in_vector)>>right_shifts size_t i; const int16_t *inptr; int16_t *outptr; inptr = in_vector; outptr = out_vector; for (i = 0; i < in_vector_length; i++) { *outptr++ = (int16_t)((*inptr++ * gain) >> right_shifts); } } void WebRtcSpl_ScaleVectorWithSat(const int16_t *in_vector, int16_t *out_vector, int16_t gain, size_t in_vector_length, int16_t right_shifts) { // Performs vector operation: out_vector = (gain*in_vector)>>right_shifts size_t i; const int16_t *inptr; int16_t *outptr; inptr = in_vector; outptr = out_vector; for (i = 0; i < in_vector_length; i++) { *outptr++ = WebRtcSpl_SatW32ToW16((*inptr++ * gain) >> right_shifts); } } void WebRtcSpl_ScaleAndAddVectors(const int16_t *in1, int16_t gain1, int shift1, const int16_t *in2, int16_t gain2, int shift2, int16_t *out, size_t vector_length) { // Performs vector operation: out = (gain1*in1)>>shift1 + (gain2*in2)>>shift2 size_t i; const int16_t *in1ptr; const int16_t *in2ptr; int16_t *outptr; in1ptr = in1; in2ptr = in2; outptr = out; for (i = 0; i < vector_length; i++) { *outptr++ = (int16_t)((gain1 * *in1ptr++) >> shift1) + (int16_t)((gain2 * *in2ptr++) >> shift2); } } // C version of WebRtcSpl_ScaleAndAddVectorsWithRound() for generic platforms. int WebRtcSpl_ScaleAndAddVectorsWithRoundC(const int16_t* in_vector1, int16_t in_vector1_scale, const int16_t* in_vector2, int16_t in_vector2_scale, int right_shifts, int16_t* out_vector, size_t length) { size_t i = 0; int round_value = (1 << right_shifts) >> 1; if (in_vector1 == NULL || in_vector2 == NULL || out_vector == NULL || length == 0 || right_shifts < 0) { return -1; } for (i = 0; i < length; i++) { out_vector[i] = (int16_t)(( in_vector1[i] * in_vector1_scale + in_vector2[i] * in_vector2_scale + round_value) >> right_shifts); } return 0; } ================================================ FILE: thirdparty/webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c.mips ================================================ /* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file contains implementations of the functions * WebRtcSpl_ScaleAndAddVectorsWithRound_mips() */ #include "common_audio/signal_processing/include/signal_processing_library.h" int WebRtcSpl_ScaleAndAddVectorsWithRound_mips(const int16_t* in_vector1, int16_t in_vector1_scale, const int16_t* in_vector2, int16_t in_vector2_scale, int right_shifts, int16_t* out_vector, size_t length) { int16_t r0 = 0, r1 = 0; int16_t *in1 = (int16_t*)in_vector1; int16_t *in2 = (int16_t*)in_vector2; int16_t *out = out_vector; size_t i = 0; int value32 = 0; if (in_vector1 == NULL || in_vector2 == NULL || out_vector == NULL || length == 0 || right_shifts < 0) { return -1; } for (i = 0; i < length; i++) { __asm __volatile ( "lh %[r0], 0(%[in1]) \n\t" "lh %[r1], 0(%[in2]) \n\t" "mult %[r0], %[in_vector1_scale] \n\t" "madd %[r1], %[in_vector2_scale] \n\t" "extrv_r.w %[value32], $ac0, %[right_shifts] \n\t" "addiu %[in1], %[in1], 2 \n\t" "addiu %[in2], %[in2], 2 \n\t" "sh %[value32], 0(%[out]) \n\t" "addiu %[out], %[out], 2 \n\t" : [value32] "=&r" (value32), [out] "+r" (out), [in1] "+r" (in1), [in2] "+r" (in2), [r0] "=&r" (r0), [r1] "=&r" (r1) : [in_vector1_scale] "r" (in_vector1_scale), [in_vector2_scale] "r" (in_vector2_scale), [right_shifts] "r" (right_shifts) : "hi", "lo", "memory" ); } return 0; } ================================================ FILE: thirdparty/webrtc/common_audio/vad/include/vad.h ================================================ /* * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef COMMON_AUDIO_VAD_INCLUDE_VAD_H_ #define COMMON_AUDIO_VAD_INCLUDE_VAD_H_ #include #include "common_audio/vad/include/webrtc_vad.h" #include "rtc_base/checks.h" #include "typedefs.h" // NOLINT(build/include) namespace webrtc { class Vad { public: enum Aggressiveness { kVadNormal = 0, kVadLowBitrate = 1, kVadAggressive = 2, kVadVeryAggressive = 3 }; enum Activity { kPassive = 0, kActive = 1, kError = -1 }; virtual ~Vad() = default; // Calculates a VAD decision for the given audio frame. Valid sample rates // are 8000, 16000, and 32000 Hz; the number of samples must be such that the // frame is 10, 20, or 30 ms long. virtual Activity VoiceActivity(const int16_t* audio, size_t num_samples, int sample_rate_hz) = 0; // Resets VAD state. virtual void Reset() = 0; }; // Returns a Vad instance that's implemented on top of WebRtcVad. std::unique_ptr CreateVad(Vad::Aggressiveness aggressiveness); } // namespace webrtc #endif // COMMON_AUDIO_VAD_INCLUDE_VAD_H_ ================================================ FILE: thirdparty/webrtc/common_audio/vad/include/webrtc_vad.h ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This header file includes the VAD API calls. Specific function calls are given below. */ #ifndef COMMON_AUDIO_VAD_INCLUDE_WEBRTC_VAD_H_ // NOLINT #define COMMON_AUDIO_VAD_INCLUDE_WEBRTC_VAD_H_ #include #include "typedefs.h" // NOLINT(build/include) typedef struct WebRtcVadInst VadInst; #ifdef __cplusplus extern "C" { #endif // Creates an instance to the VAD structure. VadInst* WebRtcVad_Create(); // Frees the dynamic memory of a specified VAD instance. // // - handle [i] : Pointer to VAD instance that should be freed. void WebRtcVad_Free(VadInst* handle); // Initializes a VAD instance. // // - handle [i/o] : Instance that should be initialized. // // returns : 0 - (OK), // -1 - (null pointer or Default mode could not be set). int WebRtcVad_Init(VadInst* handle); // Sets the VAD operating mode. A more aggressive (higher mode) VAD is more // restrictive in reporting speech. Put in other words the probability of being // speech when the VAD returns 1 is increased with increasing mode. As a // consequence also the missed detection rate goes up. // // - handle [i/o] : VAD instance. // - mode [i] : Aggressiveness mode (0, 1, 2, or 3). // // returns : 0 - (OK), // -1 - (null pointer, mode could not be set or the VAD instance // has not been initialized). int WebRtcVad_set_mode(VadInst* handle, int mode); // Calculates a VAD decision for the |audio_frame|. For valid sampling rates // frame lengths, see the description of WebRtcVad_ValidRatesAndFrameLengths(). // // - handle [i/o] : VAD Instance. Needs to be initialized by // WebRtcVad_Init() before call. // - fs [i] : Sampling frequency (Hz): 8000, 16000, or 32000 // - audio_frame [i] : Audio frame buffer. // - frame_length [i] : Length of audio frame buffer in number of samples. // // returns : 1 - (Active Voice), // 0 - (Non-active Voice), // -1 - (Error) int WebRtcVad_Process(VadInst* handle, int fs, const int16_t* audio_frame, size_t frame_length); // Checks for valid combinations of |rate| and |frame_length|. We support 10, // 20 and 30 ms frames and the rates 8000, 16000 and 32000 Hz. // // - rate [i] : Sampling frequency (Hz). // - frame_length [i] : Speech frame buffer length in number of samples. // // returns : 0 - (valid combination), -1 - (invalid combination) int WebRtcVad_ValidRateAndFrameLength(int rate, size_t frame_length); #ifdef __cplusplus } #endif #endif // COMMON_AUDIO_VAD_INCLUDE_WEBRTC_VAD_H_ // NOLINT ================================================ FILE: thirdparty/webrtc/common_audio/vad/mock/mock_vad.h ================================================ /* * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef COMMON_AUDIO_VAD_MOCK_MOCK_VAD_H_ #define COMMON_AUDIO_VAD_MOCK_MOCK_VAD_H_ #include "common_audio/vad/include/vad.h" #include "test/gmock.h" namespace webrtc { class MockVad : public Vad { public: virtual ~MockVad() { Die(); } MOCK_METHOD0(Die, void()); MOCK_METHOD3(VoiceActivity, enum Activity(const int16_t* audio, size_t num_samples, int sample_rate_hz)); MOCK_METHOD0(Reset, void()); }; } // namespace webrtc #endif // COMMON_AUDIO_VAD_MOCK_MOCK_VAD_H_ ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad.cc ================================================ /* * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/vad/include/vad.h" #include #include "rtc_base/checks.h" namespace webrtc { namespace { class VadImpl final : public Vad { public: explicit VadImpl(Aggressiveness aggressiveness) : handle_(nullptr), aggressiveness_(aggressiveness) { Reset(); } ~VadImpl() override { WebRtcVad_Free(handle_); } Activity VoiceActivity(const int16_t* audio, size_t num_samples, int sample_rate_hz) override { int ret = WebRtcVad_Process(handle_, sample_rate_hz, audio, num_samples); switch (ret) { case 0: return kPassive; case 1: return kActive; default: RTC_NOTREACHED() << "WebRtcVad_Process returned an error."; return kError; } } void Reset() override { if (handle_) WebRtcVad_Free(handle_); handle_ = WebRtcVad_Create(); RTC_CHECK(handle_); RTC_CHECK_EQ(WebRtcVad_Init(handle_), 0); RTC_CHECK_EQ(WebRtcVad_set_mode(handle_, aggressiveness_), 0); } private: VadInst* handle_; Aggressiveness aggressiveness_; }; } // namespace std::unique_ptr CreateVad(Vad::Aggressiveness aggressiveness) { return std::unique_ptr(new VadImpl(aggressiveness)); } } // namespace webrtc ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_core.c ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/vad/vad_core.h" #include "rtc_base/sanitizer.h" #include "common_audio/signal_processing/include/signal_processing_library.h" #include "common_audio/vad/vad_filterbank.h" #include "common_audio/vad/vad_gmm.h" #include "common_audio/vad/vad_sp.h" #include "typedefs.h" // NOLINT(build/include) // Spectrum Weighting static const int16_t kSpectrumWeight[kNumChannels] = { 6, 8, 10, 12, 14, 16 }; static const int16_t kNoiseUpdateConst = 655; // Q15 static const int16_t kSpeechUpdateConst = 6554; // Q15 static const int16_t kBackEta = 154; // Q8 // Minimum difference between the two models, Q5 static const int16_t kMinimumDifference[kNumChannels] = { 544, 544, 576, 576, 576, 576 }; // Upper limit of mean value for speech model, Q7 static const int16_t kMaximumSpeech[kNumChannels] = { 11392, 11392, 11520, 11520, 11520, 11520 }; // Minimum value for mean value static const int16_t kMinimumMean[kNumGaussians] = { 640, 768 }; // Upper limit of mean value for noise model, Q7 static const int16_t kMaximumNoise[kNumChannels] = { 9216, 9088, 8960, 8832, 8704, 8576 }; // Start values for the Gaussian models, Q7 // Weights for the two Gaussians for the six channels (noise) static const int16_t kNoiseDataWeights[kTableSize] = { 34, 62, 72, 66, 53, 25, 94, 66, 56, 62, 75, 103 }; // Weights for the two Gaussians for the six channels (speech) static const int16_t kSpeechDataWeights[kTableSize] = { 48, 82, 45, 87, 50, 47, 80, 46, 83, 41, 78, 81 }; // Means for the two Gaussians for the six channels (noise) static const int16_t kNoiseDataMeans[kTableSize] = { 6738, 4892, 7065, 6715, 6771, 3369, 7646, 3863, 7820, 7266, 5020, 4362 }; // Means for the two Gaussians for the six channels (speech) static const int16_t kSpeechDataMeans[kTableSize] = { 8306, 10085, 10078, 11823, 11843, 6309, 9473, 9571, 10879, 7581, 8180, 7483 }; // Stds for the two Gaussians for the six channels (noise) static const int16_t kNoiseDataStds[kTableSize] = { 378, 1064, 493, 582, 688, 593, 474, 697, 475, 688, 421, 455 }; // Stds for the two Gaussians for the six channels (speech) static const int16_t kSpeechDataStds[kTableSize] = { 555, 505, 567, 524, 585, 1231, 509, 828, 492, 1540, 1079, 850 }; // Constants used in GmmProbability(). // // Maximum number of counted speech (VAD = 1) frames in a row. static const int16_t kMaxSpeechFrames = 6; // Minimum standard deviation for both speech and noise. static const int16_t kMinStd = 384; // Constants in WebRtcVad_InitCore(). // Default aggressiveness mode. static const short kDefaultMode = 0; static const int kInitCheck = 42; // Constants used in WebRtcVad_set_mode_core(). // // Thresholds for different frame lengths (10 ms, 20 ms and 30 ms). // // Mode 0, Quality. static const int16_t kOverHangMax1Q[3] = { 8, 4, 3 }; static const int16_t kOverHangMax2Q[3] = { 14, 7, 5 }; static const int16_t kLocalThresholdQ[3] = { 24, 21, 24 }; static const int16_t kGlobalThresholdQ[3] = { 57, 48, 57 }; // Mode 1, Low bitrate. static const int16_t kOverHangMax1LBR[3] = { 8, 4, 3 }; static const int16_t kOverHangMax2LBR[3] = { 14, 7, 5 }; static const int16_t kLocalThresholdLBR[3] = { 37, 32, 37 }; static const int16_t kGlobalThresholdLBR[3] = { 100, 80, 100 }; // Mode 2, Aggressive. static const int16_t kOverHangMax1AGG[3] = { 6, 3, 2 }; static const int16_t kOverHangMax2AGG[3] = { 9, 5, 3 }; static const int16_t kLocalThresholdAGG[3] = { 82, 78, 82 }; static const int16_t kGlobalThresholdAGG[3] = { 285, 260, 285 }; // Mode 3, Very aggressive. static const int16_t kOverHangMax1VAG[3] = { 6, 3, 2 }; static const int16_t kOverHangMax2VAG[3] = { 9, 5, 3 }; static const int16_t kLocalThresholdVAG[3] = { 94, 94, 94 }; static const int16_t kGlobalThresholdVAG[3] = { 1100, 1050, 1100 }; // Calculates the weighted average w.r.t. number of Gaussians. The |data| are // updated with an |offset| before averaging. // // - data [i/o] : Data to average. // - offset [i] : An offset added to |data|. // - weights [i] : Weights used for averaging. // // returns : The weighted average. static int32_t WeightedAverage(int16_t* data, int16_t offset, const int16_t* weights) { int k; int32_t weighted_average = 0; for (k = 0; k < kNumGaussians; k++) { data[k * kNumChannels] += offset; weighted_average += data[k * kNumChannels] * weights[k * kNumChannels]; } return weighted_average; } // An s16 x s32 -> s32 multiplication that's allowed to overflow. (It's still // undefined behavior, so not a good idea; this just makes UBSan ignore the // violation, so that our old code can continue to do what it's always been // doing.) static inline int32_t RTC_NO_SANITIZE("signed-integer-overflow") OverflowingMulS16ByS32ToS32(int16_t a, int32_t b) { return a * b; } // Calculates the probabilities for both speech and background noise using // Gaussian Mixture Models (GMM). A hypothesis-test is performed to decide which // type of signal is most probable. // // - self [i/o] : Pointer to VAD instance // - features [i] : Feature vector of length |kNumChannels| // = log10(energy in frequency band) // - total_power [i] : Total power in audio frame. // - frame_length [i] : Number of input samples // // - returns : the VAD decision (0 - noise, 1 - speech). static int16_t GmmProbability(VadInstT* self, int16_t* features, int16_t total_power, size_t frame_length) { int channel, k; int16_t feature_minimum; int16_t h0, h1; int16_t log_likelihood_ratio; int16_t vadflag = 0; int16_t shifts_h0, shifts_h1; int16_t tmp_s16, tmp1_s16, tmp2_s16; int16_t diff; int gaussian; int16_t nmk, nmk2, nmk3, smk, smk2, nsk, ssk; int16_t delt, ndelt; int16_t maxspe, maxmu; int16_t deltaN[kTableSize], deltaS[kTableSize]; int16_t ngprvec[kTableSize] = { 0 }; // Conditional probability = 0. int16_t sgprvec[kTableSize] = { 0 }; // Conditional probability = 0. int32_t h0_test, h1_test; int32_t tmp1_s32, tmp2_s32; int32_t sum_log_likelihood_ratios = 0; int32_t noise_global_mean, speech_global_mean; int32_t noise_probability[kNumGaussians], speech_probability[kNumGaussians]; int16_t overhead1, overhead2, individualTest, totalTest; // Set various thresholds based on frame lengths (80, 160 or 240 samples). if (frame_length == 80) { overhead1 = self->over_hang_max_1[0]; overhead2 = self->over_hang_max_2[0]; individualTest = self->individual[0]; totalTest = self->total[0]; } else if (frame_length == 160) { overhead1 = self->over_hang_max_1[1]; overhead2 = self->over_hang_max_2[1]; individualTest = self->individual[1]; totalTest = self->total[1]; } else { overhead1 = self->over_hang_max_1[2]; overhead2 = self->over_hang_max_2[2]; individualTest = self->individual[2]; totalTest = self->total[2]; } if (total_power > kMinEnergy) { // The signal power of current_frame frame is large enough for processing. The // processing consists of two parts: // 1) Calculating the likelihood of speech and thereby a VAD decision. // 2) Updating the underlying model, w.r.t., the decision made. // The detection scheme is an LRT with hypothesis // H0: Noise // H1: Speech // // We combine a global LRT with local tests, for each frequency sub-band, // here defined as |channel|. for (channel = 0; channel < kNumChannels; channel++) { // For each channel we model the probability with a GMM consisting of // |kNumGaussians|, with different means and standard deviations depending // on H0 or H1. h0_test = 0; h1_test = 0; for (k = 0; k < kNumGaussians; k++) { gaussian = channel + k * kNumChannels; // Probability under H0, that is, probability of frame being noise. // Value given in Q27 = Q7 * Q20. tmp1_s32 = WebRtcVad_GaussianProbability(features[channel], self->noise_means[gaussian], self->noise_stds[gaussian], &deltaN[gaussian]); noise_probability[k] = kNoiseDataWeights[gaussian] * tmp1_s32; h0_test += noise_probability[k]; // Q27 // Probability under H1, that is, probability of frame being speech. // Value given in Q27 = Q7 * Q20. tmp1_s32 = WebRtcVad_GaussianProbability(features[channel], self->speech_means[gaussian], self->speech_stds[gaussian], &deltaS[gaussian]); speech_probability[k] = kSpeechDataWeights[gaussian] * tmp1_s32; h1_test += speech_probability[k]; // Q27 } // Calculate the log likelihood ratio: log2(Pr{X|H1} / Pr{X|H1}). // Approximation: // log2(Pr{X|H1} / Pr{X|H1}) = log2(Pr{X|H1}*2^Q) - log2(Pr{X|H1}*2^Q) // = log2(h1_test) - log2(h0_test) // = log2(2^(31-shifts_h1)*(1+b1)) // - log2(2^(31-shifts_h0)*(1+b0)) // = shifts_h0 - shifts_h1 // + log2(1+b1) - log2(1+b0) // ~= shifts_h0 - shifts_h1 // // Note that b0 and b1 are values less than 1, hence, 0 <= log2(1+b0) < 1. // Further, b0 and b1 are independent and on the average the two terms // cancel. shifts_h0 = WebRtcSpl_NormW32(h0_test); shifts_h1 = WebRtcSpl_NormW32(h1_test); if (h0_test == 0) { shifts_h0 = 31; } if (h1_test == 0) { shifts_h1 = 31; } log_likelihood_ratio = shifts_h0 - shifts_h1; // Update |sum_log_likelihood_ratios| with spectrum weighting. This is // used for the global VAD decision. sum_log_likelihood_ratios += (int32_t) (log_likelihood_ratio * kSpectrumWeight[channel]); // Local VAD decision. if ((log_likelihood_ratio * 4) > individualTest) { vadflag = 1; } // TODO(bjornv): The conditional probabilities below are applied on the // hard coded number of Gaussians set to two. Find a way to generalize. // Calculate local noise probabilities used later when updating the GMM. h0 = (int16_t) (h0_test >> 12); // Q15 if (h0 > 0) { // High probability of noise. Assign conditional probabilities for each // Gaussian in the GMM. tmp1_s32 = (noise_probability[0] & 0xFFFFF000) << 2; // Q29 ngprvec[channel] = (int16_t) WebRtcSpl_DivW32W16(tmp1_s32, h0); // Q14 ngprvec[channel + kNumChannels] = 16384 - ngprvec[channel]; } else { // Low noise probability. Assign conditional probability 1 to the first // Gaussian and 0 to the rest (which is already set at initialization). ngprvec[channel] = 16384; } // Calculate local speech probabilities used later when updating the GMM. h1 = (int16_t) (h1_test >> 12); // Q15 if (h1 > 0) { // High probability of speech. Assign conditional probabilities for each // Gaussian in the GMM. Otherwise use the initialized values, i.e., 0. tmp1_s32 = (speech_probability[0] & 0xFFFFF000) << 2; // Q29 sgprvec[channel] = (int16_t) WebRtcSpl_DivW32W16(tmp1_s32, h1); // Q14 sgprvec[channel + kNumChannels] = 16384 - sgprvec[channel]; } } // Make a global VAD decision. vadflag |= (sum_log_likelihood_ratios >= totalTest); // Update the model parameters. maxspe = 12800; for (channel = 0; channel < kNumChannels; channel++) { // Get minimum value in past which is used for long term correction in Q4. feature_minimum = WebRtcVad_FindMinimum(self, features[channel], channel); // Compute the "global" mean, that is the sum of the two means weighted. noise_global_mean = WeightedAverage(&self->noise_means[channel], 0, &kNoiseDataWeights[channel]); tmp1_s16 = (int16_t) (noise_global_mean >> 6); // Q8 for (k = 0; k < kNumGaussians; k++) { gaussian = channel + k * kNumChannels; nmk = self->noise_means[gaussian]; smk = self->speech_means[gaussian]; nsk = self->noise_stds[gaussian]; ssk = self->speech_stds[gaussian]; // Update noise mean vector if the frame consists of noise only. nmk2 = nmk; if (!vadflag) { // deltaN = (x-mu)/sigma^2 // ngprvec[k] = |noise_probability[k]| / // (|noise_probability[0]| + |noise_probability[1]|) // (Q14 * Q11 >> 11) = Q14. delt = (int16_t)((ngprvec[gaussian] * deltaN[gaussian]) >> 11); // Q7 + (Q14 * Q15 >> 22) = Q7. nmk2 = nmk + (int16_t)((delt * kNoiseUpdateConst) >> 22); } // Long term correction of the noise mean. // Q8 - Q8 = Q8. ndelt = (feature_minimum << 4) - tmp1_s16; // Q7 + (Q8 * Q8) >> 9 = Q7. nmk3 = nmk2 + (int16_t)((ndelt * kBackEta) >> 9); // Control that the noise mean does not drift to much. tmp_s16 = (int16_t) ((k + 5) << 7); if (nmk3 < tmp_s16) { nmk3 = tmp_s16; } tmp_s16 = (int16_t) ((72 + k - channel) << 7); if (nmk3 > tmp_s16) { nmk3 = tmp_s16; } self->noise_means[gaussian] = nmk3; if (vadflag) { // Update speech mean vector: // |deltaS| = (x-mu)/sigma^2 // sgprvec[k] = |speech_probability[k]| / // (|speech_probability[0]| + |speech_probability[1]|) // (Q14 * Q11) >> 11 = Q14. delt = (int16_t)((sgprvec[gaussian] * deltaS[gaussian]) >> 11); // Q14 * Q15 >> 21 = Q8. tmp_s16 = (int16_t)((delt * kSpeechUpdateConst) >> 21); // Q7 + (Q8 >> 1) = Q7. With rounding. smk2 = smk + ((tmp_s16 + 1) >> 1); // Control that the speech mean does not drift to much. maxmu = maxspe + 640; if (smk2 < kMinimumMean[k]) { smk2 = kMinimumMean[k]; } if (smk2 > maxmu) { smk2 = maxmu; } self->speech_means[gaussian] = smk2; // Q7. // (Q7 >> 3) = Q4. With rounding. tmp_s16 = ((smk + 4) >> 3); tmp_s16 = features[channel] - tmp_s16; // Q4 // (Q11 * Q4 >> 3) = Q12. tmp1_s32 = (deltaS[gaussian] * tmp_s16) >> 3; tmp2_s32 = tmp1_s32 - 4096; tmp_s16 = sgprvec[gaussian] >> 2; // (Q14 >> 2) * Q12 = Q24. tmp1_s32 = tmp_s16 * tmp2_s32; tmp2_s32 = tmp1_s32 >> 4; // Q20 // 0.1 * Q20 / Q7 = Q13. if (tmp2_s32 > 0) { tmp_s16 = (int16_t) WebRtcSpl_DivW32W16(tmp2_s32, ssk * 10); } else { tmp_s16 = (int16_t) WebRtcSpl_DivW32W16(-tmp2_s32, ssk * 10); tmp_s16 = -tmp_s16; } // Divide by 4 giving an update factor of 0.025 (= 0.1 / 4). // Note that division by 4 equals shift by 2, hence, // (Q13 >> 8) = (Q13 >> 6) / 4 = Q7. tmp_s16 += 128; // Rounding. ssk += (tmp_s16 >> 8); if (ssk < kMinStd) { ssk = kMinStd; } self->speech_stds[gaussian] = ssk; } else { // Update GMM variance vectors. // deltaN * (features[channel] - nmk) - 1 // Q4 - (Q7 >> 3) = Q4. tmp_s16 = features[channel] - (nmk >> 3); // (Q11 * Q4 >> 3) = Q12. tmp1_s32 = (deltaN[gaussian] * tmp_s16) >> 3; tmp1_s32 -= 4096; // (Q14 >> 2) * Q12 = Q24. tmp_s16 = (ngprvec[gaussian] + 2) >> 2; tmp2_s32 = OverflowingMulS16ByS32ToS32(tmp_s16, tmp1_s32); // Q20 * approx 0.001 (2^-10=0.0009766), hence, // (Q24 >> 14) = (Q24 >> 4) / 2^10 = Q20. tmp1_s32 = tmp2_s32 >> 14; // Q20 / Q7 = Q13. if (tmp1_s32 > 0) { tmp_s16 = (int16_t) WebRtcSpl_DivW32W16(tmp1_s32, nsk); } else { tmp_s16 = (int16_t) WebRtcSpl_DivW32W16(-tmp1_s32, nsk); tmp_s16 = -tmp_s16; } tmp_s16 += 32; // Rounding nsk += tmp_s16 >> 6; // Q13 >> 6 = Q7. if (nsk < kMinStd) { nsk = kMinStd; } self->noise_stds[gaussian] = nsk; } } // Separate models if they are too close. // |noise_global_mean| in Q14 (= Q7 * Q7). noise_global_mean = WeightedAverage(&self->noise_means[channel], 0, &kNoiseDataWeights[channel]); // |speech_global_mean| in Q14 (= Q7 * Q7). speech_global_mean = WeightedAverage(&self->speech_means[channel], 0, &kSpeechDataWeights[channel]); // |diff| = "global" speech mean - "global" noise mean. // (Q14 >> 9) - (Q14 >> 9) = Q5. diff = (int16_t) (speech_global_mean >> 9) - (int16_t) (noise_global_mean >> 9); if (diff < kMinimumDifference[channel]) { tmp_s16 = kMinimumDifference[channel] - diff; // |tmp1_s16| = ~0.8 * (kMinimumDifference - diff) in Q7. // |tmp2_s16| = ~0.2 * (kMinimumDifference - diff) in Q7. tmp1_s16 = (int16_t)((13 * tmp_s16) >> 2); tmp2_s16 = (int16_t)((3 * tmp_s16) >> 2); // Move Gaussian means for speech model by |tmp1_s16| and update // |speech_global_mean|. Note that |self->speech_means[channel]| is // changed after the call. speech_global_mean = WeightedAverage(&self->speech_means[channel], tmp1_s16, &kSpeechDataWeights[channel]); // Move Gaussian means for noise model by -|tmp2_s16| and update // |noise_global_mean|. Note that |self->noise_means[channel]| is // changed after the call. noise_global_mean = WeightedAverage(&self->noise_means[channel], -tmp2_s16, &kNoiseDataWeights[channel]); } // Control that the speech & noise means do not drift to much. maxspe = kMaximumSpeech[channel]; tmp2_s16 = (int16_t) (speech_global_mean >> 7); if (tmp2_s16 > maxspe) { // Upper limit of speech model. tmp2_s16 -= maxspe; for (k = 0; k < kNumGaussians; k++) { self->speech_means[channel + k * kNumChannels] -= tmp2_s16; } } tmp2_s16 = (int16_t) (noise_global_mean >> 7); if (tmp2_s16 > kMaximumNoise[channel]) { tmp2_s16 -= kMaximumNoise[channel]; for (k = 0; k < kNumGaussians; k++) { self->noise_means[channel + k * kNumChannels] -= tmp2_s16; } } } self->frame_counter++; } // Smooth with respect to transition hysteresis. if (!vadflag) { if (self->over_hang > 0) { vadflag = 2 + self->over_hang; self->over_hang--; } self->num_of_speech = 0; } else { self->num_of_speech++; if (self->num_of_speech > kMaxSpeechFrames) { self->num_of_speech = kMaxSpeechFrames; self->over_hang = overhead2; } else { self->over_hang = overhead1; } } return vadflag; } // Initialize the VAD. Set aggressiveness mode to default value. int WebRtcVad_InitCore(VadInstT* self) { int i; if (self == NULL) { return -1; } // Initialization of general struct variables. self->vad = 1; // Speech active (=1). self->frame_counter = 0; self->over_hang = 0; self->num_of_speech = 0; // Initialization of downsampling filter state. memset(self->downsampling_filter_states, 0, sizeof(self->downsampling_filter_states)); // Initialization of 48 to 8 kHz downsampling. WebRtcSpl_ResetResample48khzTo8khz(&self->state_48_to_8); // Read initial PDF parameters. for (i = 0; i < kTableSize; i++) { self->noise_means[i] = kNoiseDataMeans[i]; self->speech_means[i] = kSpeechDataMeans[i]; self->noise_stds[i] = kNoiseDataStds[i]; self->speech_stds[i] = kSpeechDataStds[i]; } // Initialize Index and Minimum value vectors. for (i = 0; i < 16 * kNumChannels; i++) { self->low_value_vector[i] = 10000; self->index_vector[i] = 0; } // Initialize splitting filter states. memset(self->upper_state, 0, sizeof(self->upper_state)); memset(self->lower_state, 0, sizeof(self->lower_state)); // Initialize high pass filter states. memset(self->hp_filter_state, 0, sizeof(self->hp_filter_state)); // Initialize mean value memory, for WebRtcVad_FindMinimum(). for (i = 0; i < kNumChannels; i++) { self->mean_value[i] = 1600; } // Set aggressiveness mode to default (=|kDefaultMode|). if (WebRtcVad_set_mode_core(self, kDefaultMode) != 0) { return -1; } self->init_flag = kInitCheck; return 0; } // Set aggressiveness mode int WebRtcVad_set_mode_core(VadInstT* self, int mode) { int return_value = 0; switch (mode) { case 0: // Quality mode. memcpy(self->over_hang_max_1, kOverHangMax1Q, sizeof(self->over_hang_max_1)); memcpy(self->over_hang_max_2, kOverHangMax2Q, sizeof(self->over_hang_max_2)); memcpy(self->individual, kLocalThresholdQ, sizeof(self->individual)); memcpy(self->total, kGlobalThresholdQ, sizeof(self->total)); break; case 1: // Low bitrate mode. memcpy(self->over_hang_max_1, kOverHangMax1LBR, sizeof(self->over_hang_max_1)); memcpy(self->over_hang_max_2, kOverHangMax2LBR, sizeof(self->over_hang_max_2)); memcpy(self->individual, kLocalThresholdLBR, sizeof(self->individual)); memcpy(self->total, kGlobalThresholdLBR, sizeof(self->total)); break; case 2: // Aggressive mode. memcpy(self->over_hang_max_1, kOverHangMax1AGG, sizeof(self->over_hang_max_1)); memcpy(self->over_hang_max_2, kOverHangMax2AGG, sizeof(self->over_hang_max_2)); memcpy(self->individual, kLocalThresholdAGG, sizeof(self->individual)); memcpy(self->total, kGlobalThresholdAGG, sizeof(self->total)); break; case 3: // Very aggressive mode. memcpy(self->over_hang_max_1, kOverHangMax1VAG, sizeof(self->over_hang_max_1)); memcpy(self->over_hang_max_2, kOverHangMax2VAG, sizeof(self->over_hang_max_2)); memcpy(self->individual, kLocalThresholdVAG, sizeof(self->individual)); memcpy(self->total, kGlobalThresholdVAG, sizeof(self->total)); break; default: return_value = -1; break; } return return_value; } // Calculate VAD decision by first extracting feature values and then calculate // probability for both speech and background noise. int WebRtcVad_CalcVad48khz(VadInstT* inst, const int16_t* speech_frame, size_t frame_length) { int vad; size_t i; int16_t speech_nb[240]; // 30 ms in 8 kHz. // |tmp_mem| is a temporary memory used by resample function, length is // frame length in 10 ms (480 samples) + 256 extra. int32_t tmp_mem[480 + 256] = { 0 }; const size_t kFrameLen10ms48khz = 480; const size_t kFrameLen10ms8khz = 80; size_t num_10ms_frames = frame_length / kFrameLen10ms48khz; for (i = 0; i < num_10ms_frames; i++) { WebRtcSpl_Resample48khzTo8khz(speech_frame, &speech_nb[i * kFrameLen10ms8khz], &inst->state_48_to_8, tmp_mem); } // Do VAD on an 8 kHz signal vad = WebRtcVad_CalcVad8khz(inst, speech_nb, frame_length / 6); return vad; } int WebRtcVad_CalcVad32khz(VadInstT* inst, const int16_t* speech_frame, size_t frame_length) { size_t len; int vad; int16_t speechWB[480]; // Downsampled speech frame: 960 samples (30ms in SWB) int16_t speechNB[240]; // Downsampled speech frame: 480 samples (30ms in WB) // Downsample signal 32->16->8 before doing VAD WebRtcVad_Downsampling(speech_frame, speechWB, &(inst->downsampling_filter_states[2]), frame_length); len = frame_length / 2; WebRtcVad_Downsampling(speechWB, speechNB, inst->downsampling_filter_states, len); len /= 2; // Do VAD on an 8 kHz signal vad = WebRtcVad_CalcVad8khz(inst, speechNB, len); return vad; } int WebRtcVad_CalcVad16khz(VadInstT* inst, const int16_t* speech_frame, size_t frame_length) { size_t len; int vad; int16_t speechNB[240]; // Downsampled speech frame: 480 samples (30ms in WB) // Wideband: Downsample signal before doing VAD WebRtcVad_Downsampling(speech_frame, speechNB, inst->downsampling_filter_states, frame_length); len = frame_length / 2; vad = WebRtcVad_CalcVad8khz(inst, speechNB, len); return vad; } int WebRtcVad_CalcVad8khz(VadInstT* inst, const int16_t* speech_frame, size_t frame_length) { int16_t feature_vector[kNumChannels], total_power; // Get power in the bands total_power = WebRtcVad_CalculateFeatures(inst, speech_frame, frame_length, feature_vector); // Make a VAD inst->vad = GmmProbability(inst, feature_vector, total_power, frame_length); return inst->vad; } ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_core.h ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This header file includes the descriptions of the core VAD calls. */ #ifndef COMMON_AUDIO_VAD_VAD_CORE_H_ #define COMMON_AUDIO_VAD_VAD_CORE_H_ #include "common_audio/signal_processing/include/signal_processing_library.h" #include "typedefs.h" // NOLINT(build/include) enum { kNumChannels = 6 }; // Number of frequency bands (named channels). enum { kNumGaussians = 2 }; // Number of Gaussians per channel in the GMM. enum { kTableSize = kNumChannels * kNumGaussians }; enum { kMinEnergy = 10 }; // Minimum energy required to trigger audio signal. typedef struct VadInstT_ { int vad; int32_t downsampling_filter_states[4]; WebRtcSpl_State48khzTo8khz state_48_to_8; int16_t noise_means[kTableSize]; int16_t speech_means[kTableSize]; int16_t noise_stds[kTableSize]; int16_t speech_stds[kTableSize]; // TODO(bjornv): Change to |frame_count|. int32_t frame_counter; int16_t over_hang; // Over Hang int16_t num_of_speech; // TODO(bjornv): Change to |age_vector|. int16_t index_vector[16 * kNumChannels]; int16_t low_value_vector[16 * kNumChannels]; // TODO(bjornv): Change to |median|. int16_t mean_value[kNumChannels]; int16_t upper_state[5]; int16_t lower_state[5]; int16_t hp_filter_state[4]; int16_t over_hang_max_1[3]; int16_t over_hang_max_2[3]; int16_t individual[3]; int16_t total[3]; int init_flag; } VadInstT; // Initializes the core VAD component. The default aggressiveness mode is // controlled by |kDefaultMode| in vad_core.c. // // - self [i/o] : Instance that should be initialized // // returns : 0 (OK), -1 (null pointer in or if the default mode can't be // set) int WebRtcVad_InitCore(VadInstT* self); /**************************************************************************** * WebRtcVad_set_mode_core(...) * * This function changes the VAD settings * * Input: * - inst : VAD instance * - mode : Aggressiveness degree * 0 (High quality) - 3 (Highly aggressive) * * Output: * - inst : Changed instance * * Return value : 0 - Ok * -1 - Error */ int WebRtcVad_set_mode_core(VadInstT* self, int mode); /**************************************************************************** * WebRtcVad_CalcVad48khz(...) * WebRtcVad_CalcVad32khz(...) * WebRtcVad_CalcVad16khz(...) * WebRtcVad_CalcVad8khz(...) * * Calculate probability for active speech and make VAD decision. * * Input: * - inst : Instance that should be initialized * - speech_frame : Input speech frame * - frame_length : Number of input samples * * Output: * - inst : Updated filter states etc. * * Return value : VAD decision * 0 - No active speech * 1-6 - Active speech */ int WebRtcVad_CalcVad48khz(VadInstT* inst, const int16_t* speech_frame, size_t frame_length); int WebRtcVad_CalcVad32khz(VadInstT* inst, const int16_t* speech_frame, size_t frame_length); int WebRtcVad_CalcVad16khz(VadInstT* inst, const int16_t* speech_frame, size_t frame_length); int WebRtcVad_CalcVad8khz(VadInstT* inst, const int16_t* speech_frame, size_t frame_length); #endif // COMMON_AUDIO_VAD_VAD_CORE_H_ ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_core_unittest.cc ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include "common_audio/vad/vad_unittest.h" #include "test/gtest.h" #include "typedefs.h" // NOLINT(build/include) extern "C" { #include "common_audio/vad/vad_core.h" } namespace webrtc { namespace test { TEST_F(VadTest, InitCore) { // Test WebRtcVad_InitCore(). VadInstT* self = reinterpret_cast(malloc(sizeof(VadInstT))); // null pointer test. EXPECT_EQ(-1, WebRtcVad_InitCore(nullptr)); // Verify return = 0 for non-null pointer. EXPECT_EQ(0, WebRtcVad_InitCore(self)); // Verify init_flag is set. EXPECT_EQ(42, self->init_flag); free(self); } TEST_F(VadTest, set_mode_core) { VadInstT* self = reinterpret_cast(malloc(sizeof(VadInstT))); // TODO(bjornv): Add null pointer check if we take care of it in // vad_core.c ASSERT_EQ(0, WebRtcVad_InitCore(self)); // Test WebRtcVad_set_mode_core(). // Invalid modes should return -1. EXPECT_EQ(-1, WebRtcVad_set_mode_core(self, -1)); EXPECT_EQ(-1, WebRtcVad_set_mode_core(self, 1000)); // Valid modes should return 0. for (size_t j = 0; j < kModesSize; ++j) { EXPECT_EQ(0, WebRtcVad_set_mode_core(self, kModes[j])); } free(self); } TEST_F(VadTest, CalcVad) { VadInstT* self = reinterpret_cast(malloc(sizeof(VadInstT))); int16_t speech[kMaxFrameLength]; // TODO(bjornv): Add null pointer check if we take care of it in // vad_core.c // Test WebRtcVad_CalcVadXXkhz() // Verify that all zeros in gives VAD = 0 out. memset(speech, 0, sizeof(speech)); ASSERT_EQ(0, WebRtcVad_InitCore(self)); for (size_t j = 0; j < kFrameLengthsSize; ++j) { if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) { EXPECT_EQ(0, WebRtcVad_CalcVad8khz(self, speech, kFrameLengths[j])); } if (ValidRatesAndFrameLengths(16000, kFrameLengths[j])) { EXPECT_EQ(0, WebRtcVad_CalcVad16khz(self, speech, kFrameLengths[j])); } if (ValidRatesAndFrameLengths(32000, kFrameLengths[j])) { EXPECT_EQ(0, WebRtcVad_CalcVad32khz(self, speech, kFrameLengths[j])); } if (ValidRatesAndFrameLengths(48000, kFrameLengths[j])) { EXPECT_EQ(0, WebRtcVad_CalcVad48khz(self, speech, kFrameLengths[j])); } } // Construct a speech signal that will trigger the VAD in all modes. It is // known that (i * i) will wrap around, but that doesn't matter in this case. for (size_t i = 0; i < kMaxFrameLength; ++i) { speech[i] = static_cast(i * i); } for (size_t j = 0; j < kFrameLengthsSize; ++j) { if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) { EXPECT_EQ(1, WebRtcVad_CalcVad8khz(self, speech, kFrameLengths[j])); } if (ValidRatesAndFrameLengths(16000, kFrameLengths[j])) { EXPECT_EQ(1, WebRtcVad_CalcVad16khz(self, speech, kFrameLengths[j])); } if (ValidRatesAndFrameLengths(32000, kFrameLengths[j])) { EXPECT_EQ(1, WebRtcVad_CalcVad32khz(self, speech, kFrameLengths[j])); } if (ValidRatesAndFrameLengths(48000, kFrameLengths[j])) { EXPECT_EQ(1, WebRtcVad_CalcVad48khz(self, speech, kFrameLengths[j])); } } free(self); } } // namespace test } // namespace webrtc ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_filterbank.c ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/vad/vad_filterbank.h" #include "rtc_base/checks.h" #include "common_audio/signal_processing/include/signal_processing_library.h" #include "typedefs.h" // NOLINT(build/include) // Constants used in LogOfEnergy(). static const int16_t kLogConst = 24660; // 160*log10(2) in Q9. static const int16_t kLogEnergyIntPart = 14336; // 14 in Q10 // Coefficients used by HighPassFilter, Q14. static const int16_t kHpZeroCoefs[3] = { 6631, -13262, 6631 }; static const int16_t kHpPoleCoefs[3] = { 16384, -7756, 5620 }; // Allpass filter coefficients, upper and lower, in Q15. // Upper: 0.64, Lower: 0.17 static const int16_t kAllPassCoefsQ15[2] = { 20972, 5571 }; // Adjustment for division with two in SplitFilter. static const int16_t kOffsetVector[6] = { 368, 368, 272, 176, 176, 176 }; // High pass filtering, with a cut-off frequency at 80 Hz, if the |data_in| is // sampled at 500 Hz. // // - data_in [i] : Input audio data sampled at 500 Hz. // - data_length [i] : Length of input and output data. // - filter_state [i/o] : State of the filter. // - data_out [o] : Output audio data in the frequency interval // 80 - 250 Hz. static void HighPassFilter(const int16_t* data_in, size_t data_length, int16_t* filter_state, int16_t* data_out) { size_t i; const int16_t* in_ptr = data_in; int16_t* out_ptr = data_out; int32_t tmp32 = 0; // The sum of the absolute values of the impulse response: // The zero/pole-filter has a max amplification of a single sample of: 1.4546 // Impulse response: 0.4047 -0.6179 -0.0266 0.1993 0.1035 -0.0194 // The all-zero section has a max amplification of a single sample of: 1.6189 // Impulse response: 0.4047 -0.8094 0.4047 0 0 0 // The all-pole section has a max amplification of a single sample of: 1.9931 // Impulse response: 1.0000 0.4734 -0.1189 -0.2187 -0.0627 0.04532 for (i = 0; i < data_length; i++) { // All-zero section (filter coefficients in Q14). tmp32 = kHpZeroCoefs[0] * *in_ptr; tmp32 += kHpZeroCoefs[1] * filter_state[0]; tmp32 += kHpZeroCoefs[2] * filter_state[1]; filter_state[1] = filter_state[0]; filter_state[0] = *in_ptr++; // All-pole section (filter coefficients in Q14). tmp32 -= kHpPoleCoefs[1] * filter_state[2]; tmp32 -= kHpPoleCoefs[2] * filter_state[3]; filter_state[3] = filter_state[2]; filter_state[2] = (int16_t) (tmp32 >> 14); *out_ptr++ = filter_state[2]; } } // All pass filtering of |data_in|, used before splitting the signal into two // frequency bands (low pass vs high pass). // Note that |data_in| and |data_out| can NOT correspond to the same address. // // - data_in [i] : Input audio signal given in Q0. // - data_length [i] : Length of input and output data. // - filter_coefficient [i] : Given in Q15. // - filter_state [i/o] : State of the filter given in Q(-1). // - data_out [o] : Output audio signal given in Q(-1). static void AllPassFilter(const int16_t* data_in, size_t data_length, int16_t filter_coefficient, int16_t* filter_state, int16_t* data_out) { // The filter can only cause overflow (in the w16 output variable) // if more than 4 consecutive input numbers are of maximum value and // has the the same sign as the impulse responses first taps. // First 6 taps of the impulse response: // 0.6399 0.5905 -0.3779 0.2418 -0.1547 0.0990 size_t i; int16_t tmp16 = 0; int32_t tmp32 = 0; int32_t state32 = ((int32_t) (*filter_state) * (1 << 16)); // Q15 for (i = 0; i < data_length; i++) { tmp32 = state32 + filter_coefficient * *data_in; tmp16 = (int16_t) (tmp32 >> 16); // Q(-1) *data_out++ = tmp16; state32 = (*data_in * (1 << 14)) - filter_coefficient * tmp16; // Q14 state32 *= 2; // Q15. data_in += 2; } *filter_state = (int16_t) (state32 >> 16); // Q(-1) } // Splits |data_in| into |hp_data_out| and |lp_data_out| corresponding to // an upper (high pass) part and a lower (low pass) part respectively. // // - data_in [i] : Input audio data to be split into two frequency bands. // - data_length [i] : Length of |data_in|. // - upper_state [i/o] : State of the upper filter, given in Q(-1). // - lower_state [i/o] : State of the lower filter, given in Q(-1). // - hp_data_out [o] : Output audio data of the upper half of the spectrum. // The length is |data_length| / 2. // - lp_data_out [o] : Output audio data of the lower half of the spectrum. // The length is |data_length| / 2. static void SplitFilter(const int16_t* data_in, size_t data_length, int16_t* upper_state, int16_t* lower_state, int16_t* hp_data_out, int16_t* lp_data_out) { size_t i; size_t half_length = data_length >> 1; // Downsampling by 2. int16_t tmp_out; // All-pass filtering upper branch. AllPassFilter(&data_in[0], half_length, kAllPassCoefsQ15[0], upper_state, hp_data_out); // All-pass filtering lower branch. AllPassFilter(&data_in[1], half_length, kAllPassCoefsQ15[1], lower_state, lp_data_out); // Make LP and HP signals. for (i = 0; i < half_length; i++) { tmp_out = *hp_data_out; *hp_data_out++ -= *lp_data_out; *lp_data_out++ += tmp_out; } } // Calculates the energy of |data_in| in dB, and also updates an overall // |total_energy| if necessary. // // - data_in [i] : Input audio data for energy calculation. // - data_length [i] : Length of input data. // - offset [i] : Offset value added to |log_energy|. // - total_energy [i/o] : An external energy updated with the energy of // |data_in|. // NOTE: |total_energy| is only updated if // |total_energy| <= |kMinEnergy|. // - log_energy [o] : 10 * log10("energy of |data_in|") given in Q4. static void LogOfEnergy(const int16_t* data_in, size_t data_length, int16_t offset, int16_t* total_energy, int16_t* log_energy) { // |tot_rshifts| accumulates the number of right shifts performed on |energy|. int tot_rshifts = 0; // The |energy| will be normalized to 15 bits. We use unsigned integer because // we eventually will mask out the fractional part. uint32_t energy = 0; RTC_DCHECK(data_in); RTC_DCHECK_GT(data_length, 0); energy = (uint32_t) WebRtcSpl_Energy((int16_t*) data_in, data_length, &tot_rshifts); if (energy != 0) { // By construction, normalizing to 15 bits is equivalent with 17 leading // zeros of an unsigned 32 bit value. int normalizing_rshifts = 17 - WebRtcSpl_NormU32(energy); // In a 15 bit representation the leading bit is 2^14. log2(2^14) in Q10 is // (14 << 10), which is what we initialize |log2_energy| with. For a more // detailed derivations, see below. int16_t log2_energy = kLogEnergyIntPart; tot_rshifts += normalizing_rshifts; // Normalize |energy| to 15 bits. // |tot_rshifts| is now the total number of right shifts performed on // |energy| after normalization. This means that |energy| is in // Q(-tot_rshifts). if (normalizing_rshifts < 0) { energy <<= -normalizing_rshifts; } else { energy >>= normalizing_rshifts; } // Calculate the energy of |data_in| in dB, in Q4. // // 10 * log10("true energy") in Q4 = 2^4 * 10 * log10("true energy") = // 160 * log10(|energy| * 2^|tot_rshifts|) = // 160 * log10(2) * log2(|energy| * 2^|tot_rshifts|) = // 160 * log10(2) * (log2(|energy|) + log2(2^|tot_rshifts|)) = // (160 * log10(2)) * (log2(|energy|) + |tot_rshifts|) = // |kLogConst| * (|log2_energy| + |tot_rshifts|) // // We know by construction that |energy| is normalized to 15 bits. Hence, // |energy| = 2^14 + frac_Q15, where frac_Q15 is a fractional part in Q15. // Further, we'd like |log2_energy| in Q10 // log2(|energy|) in Q10 = 2^10 * log2(2^14 + frac_Q15) = // 2^10 * log2(2^14 * (1 + frac_Q15 * 2^-14)) = // 2^10 * (14 + log2(1 + frac_Q15 * 2^-14)) ~= // (14 << 10) + 2^10 * (frac_Q15 * 2^-14) = // (14 << 10) + (frac_Q15 * 2^-4) = (14 << 10) + (frac_Q15 >> 4) // // Note that frac_Q15 = (|energy| & 0x00003FFF) // Calculate and add the fractional part to |log2_energy|. log2_energy += (int16_t) ((energy & 0x00003FFF) >> 4); // |kLogConst| is in Q9, |log2_energy| in Q10 and |tot_rshifts| in Q0. // Note that we in our derivation above have accounted for an output in Q4. *log_energy = (int16_t)(((kLogConst * log2_energy) >> 19) + ((tot_rshifts * kLogConst) >> 9)); if (*log_energy < 0) { *log_energy = 0; } } else { *log_energy = offset; return; } *log_energy += offset; // Update the approximate |total_energy| with the energy of |data_in|, if // |total_energy| has not exceeded |kMinEnergy|. |total_energy| is used as an // energy indicator in WebRtcVad_GmmProbability() in vad_core.c. if (*total_energy <= kMinEnergy) { if (tot_rshifts >= 0) { // We know by construction that the |energy| > |kMinEnergy| in Q0, so add // an arbitrary value such that |total_energy| exceeds |kMinEnergy|. *total_energy += kMinEnergy + 1; } else { // By construction |energy| is represented by 15 bits, hence any number of // right shifted |energy| will fit in an int16_t. In addition, adding the // value to |total_energy| is wrap around safe as long as // |kMinEnergy| < 8192. *total_energy += (int16_t) (energy >> -tot_rshifts); // Q0. } } } int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in, size_t data_length, int16_t* features) { int16_t total_energy = 0; // We expect |data_length| to be 80, 160 or 240 samples, which corresponds to // 10, 20 or 30 ms in 8 kHz. Therefore, the intermediate downsampled data will // have at most 120 samples after the first split and at most 60 samples after // the second split. int16_t hp_120[120], lp_120[120]; int16_t hp_60[60], lp_60[60]; const size_t half_data_length = data_length >> 1; size_t length = half_data_length; // |data_length| / 2, corresponds to // bandwidth = 2000 Hz after downsampling. // Initialize variables for the first SplitFilter(). int frequency_band = 0; const int16_t* in_ptr = data_in; // [0 - 4000] Hz. int16_t* hp_out_ptr = hp_120; // [2000 - 4000] Hz. int16_t* lp_out_ptr = lp_120; // [0 - 2000] Hz. RTC_DCHECK_LE(data_length, 240); RTC_DCHECK_LT(4, kNumChannels - 1); // Checking maximum |frequency_band|. // Split at 2000 Hz and downsample. SplitFilter(in_ptr, data_length, &self->upper_state[frequency_band], &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr); // For the upper band (2000 Hz - 4000 Hz) split at 3000 Hz and downsample. frequency_band = 1; in_ptr = hp_120; // [2000 - 4000] Hz. hp_out_ptr = hp_60; // [3000 - 4000] Hz. lp_out_ptr = lp_60; // [2000 - 3000] Hz. SplitFilter(in_ptr, length, &self->upper_state[frequency_band], &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr); // Energy in 3000 Hz - 4000 Hz. length >>= 1; // |data_length| / 4 <=> bandwidth = 1000 Hz. LogOfEnergy(hp_60, length, kOffsetVector[5], &total_energy, &features[5]); // Energy in 2000 Hz - 3000 Hz. LogOfEnergy(lp_60, length, kOffsetVector[4], &total_energy, &features[4]); // For the lower band (0 Hz - 2000 Hz) split at 1000 Hz and downsample. frequency_band = 2; in_ptr = lp_120; // [0 - 2000] Hz. hp_out_ptr = hp_60; // [1000 - 2000] Hz. lp_out_ptr = lp_60; // [0 - 1000] Hz. length = half_data_length; // |data_length| / 2 <=> bandwidth = 2000 Hz. SplitFilter(in_ptr, length, &self->upper_state[frequency_band], &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr); // Energy in 1000 Hz - 2000 Hz. length >>= 1; // |data_length| / 4 <=> bandwidth = 1000 Hz. LogOfEnergy(hp_60, length, kOffsetVector[3], &total_energy, &features[3]); // For the lower band (0 Hz - 1000 Hz) split at 500 Hz and downsample. frequency_band = 3; in_ptr = lp_60; // [0 - 1000] Hz. hp_out_ptr = hp_120; // [500 - 1000] Hz. lp_out_ptr = lp_120; // [0 - 500] Hz. SplitFilter(in_ptr, length, &self->upper_state[frequency_band], &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr); // Energy in 500 Hz - 1000 Hz. length >>= 1; // |data_length| / 8 <=> bandwidth = 500 Hz. LogOfEnergy(hp_120, length, kOffsetVector[2], &total_energy, &features[2]); // For the lower band (0 Hz - 500 Hz) split at 250 Hz and downsample. frequency_band = 4; in_ptr = lp_120; // [0 - 500] Hz. hp_out_ptr = hp_60; // [250 - 500] Hz. lp_out_ptr = lp_60; // [0 - 250] Hz. SplitFilter(in_ptr, length, &self->upper_state[frequency_band], &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr); // Energy in 250 Hz - 500 Hz. length >>= 1; // |data_length| / 16 <=> bandwidth = 250 Hz. LogOfEnergy(hp_60, length, kOffsetVector[1], &total_energy, &features[1]); // Remove 0 Hz - 80 Hz, by high pass filtering the lower band. HighPassFilter(lp_60, length, self->hp_filter_state, hp_120); // Energy in 80 Hz - 250 Hz. LogOfEnergy(hp_120, length, kOffsetVector[0], &total_energy, &features[0]); return total_energy; } ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_filterbank.h ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * This file includes feature calculating functionality used in vad_core.c. */ #ifndef COMMON_AUDIO_VAD_VAD_FILTERBANK_H_ #define COMMON_AUDIO_VAD_VAD_FILTERBANK_H_ #include "common_audio/vad/vad_core.h" #include "typedefs.h" // NOLINT(build/include) // Takes |data_length| samples of |data_in| and calculates the logarithm of the // energy of each of the |kNumChannels| = 6 frequency bands used by the VAD: // 80 Hz - 250 Hz // 250 Hz - 500 Hz // 500 Hz - 1000 Hz // 1000 Hz - 2000 Hz // 2000 Hz - 3000 Hz // 3000 Hz - 4000 Hz // // The values are given in Q4 and written to |features|. Further, an approximate // overall energy is returned. The return value is used in // WebRtcVad_GmmProbability() as a signal indicator, hence it is arbitrary above // the threshold |kMinEnergy|. // // - self [i/o] : State information of the VAD. // - data_in [i] : Input audio data, for feature extraction. // - data_length [i] : Audio data current_frame, in number of samples. // - features [o] : 10 * log10(energy in each frequency band), Q4. // - returns : Total energy of the signal (NOTE! This value is not // exact. It is only used in a comparison.) int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in, size_t data_length, int16_t* features); #endif // COMMON_AUDIO_VAD_VAD_FILTERBANK_H_ ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_filterbank_unittest.cc ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include "common_audio/vad/vad_unittest.h" #include "test/gtest.h" #include "typedefs.h" // NOLINT(build/include) extern "C" { #include "common_audio/vad/vad_core.h" #include "common_audio/vad/vad_filterbank.h" } namespace webrtc { namespace test { const int kNumValidFrameLengths = 3; TEST_F(VadTest, vad_filterbank) { VadInstT* self = reinterpret_cast(malloc(sizeof(VadInstT))); static const int16_t kReference[kNumValidFrameLengths] = { 48, 11, 11 }; static const int16_t kFeatures[kNumValidFrameLengths * kNumChannels] = { 1213, 759, 587, 462, 434, 272, 1479, 1385, 1291, 1200, 1103, 1099, 1732, 1692, 1681, 1629, 1436, 1436 }; static const int16_t kOffsetVector[kNumChannels] = { 368, 368, 272, 176, 176, 176 }; int16_t features[kNumChannels]; // Construct a speech signal that will trigger the VAD in all modes. It is // known that (i * i) will wrap around, but that doesn't matter in this case. int16_t speech[kMaxFrameLength]; for (size_t i = 0; i < kMaxFrameLength; ++i) { speech[i] = static_cast(i * i); } int frame_length_index = 0; ASSERT_EQ(0, WebRtcVad_InitCore(self)); for (size_t j = 0; j < kFrameLengthsSize; ++j) { if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) { EXPECT_EQ(kReference[frame_length_index], WebRtcVad_CalculateFeatures(self, speech, kFrameLengths[j], features)); for (int k = 0; k < kNumChannels; ++k) { EXPECT_EQ(kFeatures[k + frame_length_index * kNumChannels], features[k]); } frame_length_index++; } } EXPECT_EQ(kNumValidFrameLengths, frame_length_index); // Verify that all zeros in gives kOffsetVector out. memset(speech, 0, sizeof(speech)); ASSERT_EQ(0, WebRtcVad_InitCore(self)); for (size_t j = 0; j < kFrameLengthsSize; ++j) { if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) { EXPECT_EQ(0, WebRtcVad_CalculateFeatures(self, speech, kFrameLengths[j], features)); for (int k = 0; k < kNumChannels; ++k) { EXPECT_EQ(kOffsetVector[k], features[k]); } } } // Verify that all ones in gives kOffsetVector out. Any other constant input // will have a small impact in the sub bands. for (size_t i = 0; i < kMaxFrameLength; ++i) { speech[i] = 1; } for (size_t j = 0; j < kFrameLengthsSize; ++j) { if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) { ASSERT_EQ(0, WebRtcVad_InitCore(self)); EXPECT_EQ(0, WebRtcVad_CalculateFeatures(self, speech, kFrameLengths[j], features)); for (int k = 0; k < kNumChannels; ++k) { EXPECT_EQ(kOffsetVector[k], features[k]); } } } free(self); } } // namespace test } // namespace webrtc ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_gmm.c ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/vad/vad_gmm.h" #include "common_audio/signal_processing/include/signal_processing_library.h" #include "typedefs.h" // NOLINT(build/include) static const int32_t kCompVar = 22005; static const int16_t kLog2Exp = 5909; // log2(exp(1)) in Q12. // For a normal distribution, the probability of |input| is calculated and // returned (in Q20). The formula for normal distributed probability is // // 1 / s * exp(-(x - m)^2 / (2 * s^2)) // // where the parameters are given in the following Q domains: // m = |mean| (Q7) // s = |std| (Q7) // x = |input| (Q4) // in addition to the probability we output |delta| (in Q11) used when updating // the noise/speech model. int32_t WebRtcVad_GaussianProbability(int16_t input, int16_t mean, int16_t std, int16_t* delta) { int16_t tmp16, inv_std, inv_std2, exp_value = 0; int32_t tmp32; // Calculate |inv_std| = 1 / s, in Q10. // 131072 = 1 in Q17, and (|std| >> 1) is for rounding instead of truncation. // Q-domain: Q17 / Q7 = Q10. tmp32 = (int32_t) 131072 + (int32_t) (std >> 1); inv_std = (int16_t) WebRtcSpl_DivW32W16(tmp32, std); // Calculate |inv_std2| = 1 / s^2, in Q14. tmp16 = (inv_std >> 2); // Q10 -> Q8. // Q-domain: (Q8 * Q8) >> 2 = Q14. inv_std2 = (int16_t)((tmp16 * tmp16) >> 2); // TODO(bjornv): Investigate if changing to // inv_std2 = (int16_t)((inv_std * inv_std) >> 6); // gives better accuracy. tmp16 = (input << 3); // Q4 -> Q7 tmp16 = tmp16 - mean; // Q7 - Q7 = Q7 // To be used later, when updating noise/speech model. // |delta| = (x - m) / s^2, in Q11. // Q-domain: (Q14 * Q7) >> 10 = Q11. *delta = (int16_t)((inv_std2 * tmp16) >> 10); // Calculate the exponent |tmp32| = (x - m)^2 / (2 * s^2), in Q10. Replacing // division by two with one shift. // Q-domain: (Q11 * Q7) >> 8 = Q10. tmp32 = (*delta * tmp16) >> 9; // If the exponent is small enough to give a non-zero probability we calculate // |exp_value| ~= exp(-(x - m)^2 / (2 * s^2)) // ~= exp2(-log2(exp(1)) * |tmp32|). if (tmp32 < kCompVar) { // Calculate |tmp16| = log2(exp(1)) * |tmp32|, in Q10. // Q-domain: (Q12 * Q10) >> 12 = Q10. tmp16 = (int16_t)((kLog2Exp * tmp32) >> 12); tmp16 = -tmp16; exp_value = (0x0400 | (tmp16 & 0x03FF)); tmp16 ^= 0xFFFF; tmp16 >>= 10; tmp16 += 1; // Get |exp_value| = exp(-|tmp32|) in Q10. exp_value >>= tmp16; } // Calculate and return (1 / s) * exp(-(x - m)^2 / (2 * s^2)), in Q20. // Q-domain: Q10 * Q10 = Q20. return inv_std * exp_value; } ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_gmm.h ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // Gaussian probability calculations internally used in vad_core.c. #ifndef COMMON_AUDIO_VAD_VAD_GMM_H_ #define COMMON_AUDIO_VAD_VAD_GMM_H_ #include "typedefs.h" // NOLINT(build/include) // Calculates the probability for |input|, given that |input| comes from a // normal distribution with mean and standard deviation (|mean|, |std|). // // Inputs: // - input : input sample in Q4. // - mean : mean input in the statistical model, Q7. // - std : standard deviation, Q7. // // Output: // // - delta : input used when updating the model, Q11. // |delta| = (|input| - |mean|) / |std|^2. // // Return: // (probability for |input|) = // 1 / |std| * exp(-(|input| - |mean|)^2 / (2 * |std|^2)); int32_t WebRtcVad_GaussianProbability(int16_t input, int16_t mean, int16_t std, int16_t* delta); #endif // COMMON_AUDIO_VAD_VAD_GMM_H_ ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_gmm_unittest.cc ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/vad/vad_unittest.h" #include "test/gtest.h" #include "typedefs.h" // NOLINT(build/include) extern "C" { #include "common_audio/vad/vad_gmm.h" } namespace webrtc { namespace test { TEST_F(VadTest, vad_gmm) { int16_t delta = 0; // Input value at mean. EXPECT_EQ(1048576, WebRtcVad_GaussianProbability(0, 0, 128, &delta)); EXPECT_EQ(0, delta); EXPECT_EQ(1048576, WebRtcVad_GaussianProbability(16, 128, 128, &delta)); EXPECT_EQ(0, delta); EXPECT_EQ(1048576, WebRtcVad_GaussianProbability(-16, -128, 128, &delta)); EXPECT_EQ(0, delta); // Largest possible input to give non-zero probability. EXPECT_EQ(1024, WebRtcVad_GaussianProbability(59, 0, 128, &delta)); EXPECT_EQ(7552, delta); EXPECT_EQ(1024, WebRtcVad_GaussianProbability(75, 128, 128, &delta)); EXPECT_EQ(7552, delta); EXPECT_EQ(1024, WebRtcVad_GaussianProbability(-75, -128, 128, &delta)); EXPECT_EQ(-7552, delta); // Too large input, should give zero probability. EXPECT_EQ(0, WebRtcVad_GaussianProbability(105, 0, 128, &delta)); EXPECT_EQ(13440, delta); } } // namespace test } // namespace webrtc ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_sp.c ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/vad/vad_sp.h" #include "rtc_base/checks.h" #include "common_audio/signal_processing/include/signal_processing_library.h" #include "common_audio/vad/vad_core.h" #include "typedefs.h" // NOLINT(build/include) // Allpass filter coefficients, upper and lower, in Q13. // Upper: 0.64, Lower: 0.17. static const int16_t kAllPassCoefsQ13[2] = { 5243, 1392 }; // Q13. static const int16_t kSmoothingDown = 6553; // 0.2 in Q15. static const int16_t kSmoothingUp = 32439; // 0.99 in Q15. // TODO(bjornv): Move this function to vad_filterbank.c. // Downsampling filter based on splitting filter and allpass functions. void WebRtcVad_Downsampling(const int16_t* signal_in, int16_t* signal_out, int32_t* filter_state, size_t in_length) { int16_t tmp16_1 = 0, tmp16_2 = 0; int32_t tmp32_1 = filter_state[0]; int32_t tmp32_2 = filter_state[1]; size_t n = 0; // Downsampling by 2 gives half length. size_t half_length = (in_length >> 1); // Filter coefficients in Q13, filter state in Q0. for (n = 0; n < half_length; n++) { // All-pass filtering upper branch. tmp16_1 = (int16_t) ((tmp32_1 >> 1) + ((kAllPassCoefsQ13[0] * *signal_in) >> 14)); *signal_out = tmp16_1; tmp32_1 = (int32_t)(*signal_in++) - ((kAllPassCoefsQ13[0] * tmp16_1) >> 12); // All-pass filtering lower branch. tmp16_2 = (int16_t) ((tmp32_2 >> 1) + ((kAllPassCoefsQ13[1] * *signal_in) >> 14)); *signal_out++ += tmp16_2; tmp32_2 = (int32_t)(*signal_in++) - ((kAllPassCoefsQ13[1] * tmp16_2) >> 12); } // Store the filter states. filter_state[0] = tmp32_1; filter_state[1] = tmp32_2; } // Inserts |feature_value| into |low_value_vector|, if it is one of the 16 // smallest values the last 100 frames. Then calculates and returns the median // of the five smallest values. int16_t WebRtcVad_FindMinimum(VadInstT* self, int16_t feature_value, int channel) { int i = 0, j = 0; int position = -1; // Offset to beginning of the 16 minimum values in memory. const int offset = (channel << 4); int16_t current_median = 1600; int16_t alpha = 0; int32_t tmp32 = 0; // Pointer to memory for the 16 minimum values and the age of each value of // the |channel|. int16_t* age = &self->index_vector[offset]; int16_t* smallest_values = &self->low_value_vector[offset]; RTC_DCHECK_LT(channel, kNumChannels); // Each value in |smallest_values| is getting 1 loop older. Update |age|, and // remove old values. for (i = 0; i < 16; i++) { if (age[i] != 100) { age[i]++; } else { // Too old value. Remove from memory and shift larger values downwards. for (j = i; j < 16; j++) { smallest_values[j] = smallest_values[j + 1]; age[j] = age[j + 1]; } age[15] = 101; smallest_values[15] = 10000; } } // Check if |feature_value| is smaller than any of the values in // |smallest_values|. If so, find the |position| where to insert the new value // (|feature_value|). if (feature_value < smallest_values[7]) { if (feature_value < smallest_values[3]) { if (feature_value < smallest_values[1]) { if (feature_value < smallest_values[0]) { position = 0; } else { position = 1; } } else if (feature_value < smallest_values[2]) { position = 2; } else { position = 3; } } else if (feature_value < smallest_values[5]) { if (feature_value < smallest_values[4]) { position = 4; } else { position = 5; } } else if (feature_value < smallest_values[6]) { position = 6; } else { position = 7; } } else if (feature_value < smallest_values[15]) { if (feature_value < smallest_values[11]) { if (feature_value < smallest_values[9]) { if (feature_value < smallest_values[8]) { position = 8; } else { position = 9; } } else if (feature_value < smallest_values[10]) { position = 10; } else { position = 11; } } else if (feature_value < smallest_values[13]) { if (feature_value < smallest_values[12]) { position = 12; } else { position = 13; } } else if (feature_value < smallest_values[14]) { position = 14; } else { position = 15; } } // If we have detected a new small value, insert it at the correct position // and shift larger values up. if (position > -1) { for (i = 15; i > position; i--) { smallest_values[i] = smallest_values[i - 1]; age[i] = age[i - 1]; } smallest_values[position] = feature_value; age[position] = 1; } // Get |current_median|. if (self->frame_counter > 2) { current_median = smallest_values[2]; } else if (self->frame_counter > 0) { current_median = smallest_values[0]; } // Smooth the median value. if (self->frame_counter > 0) { if (current_median < self->mean_value[channel]) { alpha = kSmoothingDown; // 0.2 in Q15. } else { alpha = kSmoothingUp; // 0.99 in Q15. } } tmp32 = (alpha + 1) * self->mean_value[channel]; tmp32 += (WEBRTC_SPL_WORD16_MAX - alpha) * current_median; tmp32 += 16384; self->mean_value[channel] = (int16_t) (tmp32 >> 15); return self->mean_value[channel]; } ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_sp.h ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // This file includes specific signal processing tools used in vad_core.c. #ifndef COMMON_AUDIO_VAD_VAD_SP_H_ #define COMMON_AUDIO_VAD_VAD_SP_H_ #include "common_audio/vad/vad_core.h" #include "typedefs.h" // NOLINT(build/include) // Downsamples the signal by a factor 2, eg. 32->16 or 16->8. // // Inputs: // - signal_in : Input signal. // - in_length : Length of input signal in samples. // // Input & Output: // - filter_state : Current filter states of the two all-pass filters. The // |filter_state| is updated after all samples have been // processed. // // Output: // - signal_out : Downsampled signal (of length |in_length| / 2). void WebRtcVad_Downsampling(const int16_t* signal_in, int16_t* signal_out, int32_t* filter_state, size_t in_length); // Updates and returns the smoothed feature minimum. As minimum we use the // median of the five smallest feature values in a 100 frames long window. // As long as |handle->frame_counter| is zero, that is, we haven't received any // "valid" data, FindMinimum() outputs the default value of 1600. // // Inputs: // - feature_value : New feature value to update with. // - channel : Channel number. // // Input & Output: // - handle : State information of the VAD. // // Returns: // : Smoothed minimum value for a moving window. int16_t WebRtcVad_FindMinimum(VadInstT* handle, int16_t feature_value, int channel); #endif // COMMON_AUDIO_VAD_VAD_SP_H_ ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_sp_unittest.cc ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include "common_audio/vad/vad_unittest.h" #include "test/gtest.h" #include "typedefs.h" // NOLINT(build/include) extern "C" { #include "common_audio/vad/vad_core.h" #include "common_audio/vad/vad_sp.h" } namespace webrtc { namespace test { TEST_F(VadTest, vad_sp) { VadInstT* self = reinterpret_cast(malloc(sizeof(VadInstT))); const size_t kMaxFrameLenSp = 960; // Maximum frame length in this unittest. int16_t zeros[kMaxFrameLenSp] = { 0 }; int32_t state[2] = { 0 }; int16_t data_in[kMaxFrameLenSp]; int16_t data_out[kMaxFrameLenSp]; // We expect the first value to be 1600 as long as |frame_counter| is zero, // which is true for the first iteration. static const int16_t kReferenceMin[32] = { 1600, 720, 509, 512, 532, 552, 570, 588, 606, 624, 642, 659, 675, 691, 707, 723, 1600, 544, 502, 522, 542, 561, 579, 597, 615, 633, 651, 667, 683, 699, 715, 731 }; // Construct a speech signal that will trigger the VAD in all modes. It is // known that (i * i) will wrap around, but that doesn't matter in this case. for (size_t i = 0; i < kMaxFrameLenSp; ++i) { data_in[i] = static_cast(i * i); } // Input values all zeros, expect all zeros out. WebRtcVad_Downsampling(zeros, data_out, state, kMaxFrameLenSp); EXPECT_EQ(0, state[0]); EXPECT_EQ(0, state[1]); for (size_t i = 0; i < kMaxFrameLenSp / 2; ++i) { EXPECT_EQ(0, data_out[i]); } // Make a simple non-zero data test. WebRtcVad_Downsampling(data_in, data_out, state, kMaxFrameLenSp); EXPECT_EQ(207, state[0]); EXPECT_EQ(2270, state[1]); ASSERT_EQ(0, WebRtcVad_InitCore(self)); // TODO(bjornv): Replace this part of the test with taking values from an // array and calculate the reference value here. Make sure the values are not // ordered. for (int16_t i = 0; i < 16; ++i) { int16_t value = 500 * (i + 1); for (int j = 0; j < kNumChannels; ++j) { // Use values both above and below initialized value. EXPECT_EQ(kReferenceMin[i], WebRtcVad_FindMinimum(self, value, j)); EXPECT_EQ(kReferenceMin[i + 16], WebRtcVad_FindMinimum(self, 12000, j)); } self->frame_counter++; } free(self); } } // namespace test } // namespace webrtc ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_unittest.cc ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/vad/vad_unittest.h" #include #include "common_audio/signal_processing/include/signal_processing_library.h" #include "common_audio/vad/include/webrtc_vad.h" #include "rtc_base/arraysize.h" #include "rtc_base/checks.h" #include "test/gtest.h" #include "typedefs.h" // NOLINT(build/include) VadTest::VadTest() {} void VadTest::SetUp() {} void VadTest::TearDown() {} // Returns true if the rate and frame length combination is valid. bool VadTest::ValidRatesAndFrameLengths(int rate, size_t frame_length) { if (rate == 8000) { if (frame_length == 80 || frame_length == 160 || frame_length == 240) { return true; } return false; } else if (rate == 16000) { if (frame_length == 160 || frame_length == 320 || frame_length == 480) { return true; } return false; } else if (rate == 32000) { if (frame_length == 320 || frame_length == 640 || frame_length == 960) { return true; } return false; } else if (rate == 48000) { if (frame_length == 480 || frame_length == 960 || frame_length == 1440) { return true; } return false; } return false; } namespace webrtc { namespace test { TEST_F(VadTest, ApiTest) { // This API test runs through the APIs for all possible valid and invalid // combinations. VadInst* handle = WebRtcVad_Create(); int16_t zeros[kMaxFrameLength] = { 0 }; // Construct a speech signal that will trigger the VAD in all modes. It is // known that (i * i) will wrap around, but that doesn't matter in this case. int16_t speech[kMaxFrameLength]; for (size_t i = 0; i < kMaxFrameLength; i++) { speech[i] = static_cast(i * i); } // nullptr instance tests EXPECT_EQ(-1, WebRtcVad_Init(nullptr)); EXPECT_EQ(-1, WebRtcVad_set_mode(nullptr, kModes[0])); EXPECT_EQ(-1, WebRtcVad_Process(nullptr, kRates[0], speech, kFrameLengths[0])); // WebRtcVad_Create() RTC_CHECK(handle); // Not initialized tests EXPECT_EQ(-1, WebRtcVad_Process(handle, kRates[0], speech, kFrameLengths[0])); EXPECT_EQ(-1, WebRtcVad_set_mode(handle, kModes[0])); // WebRtcVad_Init() test ASSERT_EQ(0, WebRtcVad_Init(handle)); // WebRtcVad_set_mode() invalid modes tests. Tries smallest supported value // minus one and largest supported value plus one. EXPECT_EQ(-1, WebRtcVad_set_mode(handle, WebRtcSpl_MinValueW32(kModes, kModesSize) - 1)); EXPECT_EQ(-1, WebRtcVad_set_mode(handle, WebRtcSpl_MaxValueW32(kModes, kModesSize) + 1)); // WebRtcVad_Process() tests // nullptr as speech pointer EXPECT_EQ(-1, WebRtcVad_Process(handle, kRates[0], nullptr, kFrameLengths[0])); // Invalid sampling rate EXPECT_EQ(-1, WebRtcVad_Process(handle, 9999, speech, kFrameLengths[0])); // All zeros as input should work EXPECT_EQ(0, WebRtcVad_Process(handle, kRates[0], zeros, kFrameLengths[0])); for (size_t k = 0; k < kModesSize; k++) { // Test valid modes EXPECT_EQ(0, WebRtcVad_set_mode(handle, kModes[k])); // Loop through sampling rate and frame length combinations for (size_t i = 0; i < kRatesSize; i++) { for (size_t j = 0; j < kFrameLengthsSize; j++) { if (ValidRatesAndFrameLengths(kRates[i], kFrameLengths[j])) { EXPECT_EQ(1, WebRtcVad_Process(handle, kRates[i], speech, kFrameLengths[j])); } else { EXPECT_EQ(-1, WebRtcVad_Process(handle, kRates[i], speech, kFrameLengths[j])); } } } } WebRtcVad_Free(handle); } TEST_F(VadTest, ValidRatesFrameLengths) { // This test verifies valid and invalid rate/frame_length combinations. We // loop through some sampling rates and frame lengths from negative values to // values larger than possible. const int kRates[] = { -8000, -4000, 0, 4000, 8000, 8001, 15999, 16000, 32000, 48000, 48001, 96000 }; const size_t kFrameLengths[] = { 0, 80, 81, 159, 160, 240, 320, 480, 640, 960, 1440, 2000 }; for (size_t i = 0; i < arraysize(kRates); i++) { for (size_t j = 0; j < arraysize(kFrameLengths); j++) { if (ValidRatesAndFrameLengths(kRates[i], kFrameLengths[j])) { EXPECT_EQ(0, WebRtcVad_ValidRateAndFrameLength(kRates[i], kFrameLengths[j])); } else { EXPECT_EQ(-1, WebRtcVad_ValidRateAndFrameLength(kRates[i], kFrameLengths[j])); } } } } // TODO(bjornv): Add a process test, run on file. } // namespace test } // namespace webrtc ================================================ FILE: thirdparty/webrtc/common_audio/vad/vad_unittest.h ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef COMMON_AUDIO_VAD_VAD_UNITTEST_H_ #define COMMON_AUDIO_VAD_VAD_UNITTEST_H_ #include // size_t #include "test/gtest.h" #include "typedefs.h" // NOLINT(build/include) namespace webrtc { namespace test { // Modes we support const int kModes[] = { 0, 1, 2, 3 }; const size_t kModesSize = sizeof(kModes) / sizeof(*kModes); // Rates we support. const int kRates[] = { 8000, 12000, 16000, 24000, 32000, 48000 }; const size_t kRatesSize = sizeof(kRates) / sizeof(*kRates); // Frame lengths we support. const size_t kMaxFrameLength = 1440; const size_t kFrameLengths[] = { 80, 120, 160, 240, 320, 480, 640, 960, kMaxFrameLength }; const size_t kFrameLengthsSize = sizeof(kFrameLengths) / sizeof(*kFrameLengths); } // namespace test } // namespace webrtc class VadTest : public ::testing::Test { protected: VadTest(); virtual void SetUp(); virtual void TearDown(); // Returns true if the rate and frame length combination is valid. bool ValidRatesAndFrameLengths(int rate, size_t frame_length); }; #endif // COMMON_AUDIO_VAD_VAD_UNITTEST_H_ ================================================ FILE: thirdparty/webrtc/common_audio/vad/webrtc_vad.c ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/vad/include/webrtc_vad.h" #include #include #include "common_audio/signal_processing/include/signal_processing_library.h" #include "common_audio/vad/vad_core.h" #include "typedefs.h" // NOLINT(build/include) static const int kInitCheck = 42; static const int kValidRates[] = { 8000, 16000, 32000, 48000 }; static const size_t kRatesSize = sizeof(kValidRates) / sizeof(*kValidRates); static const int kMaxFrameLengthMs = 30; VadInst* WebRtcVad_Create() { VadInstT* self = (VadInstT*)malloc(sizeof(VadInstT)); WebRtcSpl_Init(); self->init_flag = 0; return (VadInst*)self; } void WebRtcVad_Free(VadInst* handle) { free(handle); } // TODO(bjornv): Move WebRtcVad_InitCore() code here. int WebRtcVad_Init(VadInst* handle) { // Initialize the core VAD component. return WebRtcVad_InitCore((VadInstT*) handle); } // TODO(bjornv): Move WebRtcVad_set_mode_core() code here. int WebRtcVad_set_mode(VadInst* handle, int mode) { VadInstT* self = (VadInstT*) handle; if (handle == NULL) { return -1; } if (self->init_flag != kInitCheck) { return -1; } return WebRtcVad_set_mode_core(self, mode); } int WebRtcVad_Process(VadInst* handle, int fs, const int16_t* audio_frame, size_t frame_length) { int vad = -1; VadInstT* self = (VadInstT*) handle; if (handle == NULL) { return -1; } if (self->init_flag != kInitCheck) { return -1; } if (audio_frame == NULL) { return -1; } if (WebRtcVad_ValidRateAndFrameLength(fs, frame_length) != 0) { return -1; } if (fs == 48000) { vad = WebRtcVad_CalcVad48khz(self, audio_frame, frame_length); } else if (fs == 32000) { vad = WebRtcVad_CalcVad32khz(self, audio_frame, frame_length); } else if (fs == 16000) { vad = WebRtcVad_CalcVad16khz(self, audio_frame, frame_length); } else if (fs == 8000) { vad = WebRtcVad_CalcVad8khz(self, audio_frame, frame_length); } if (vad > 0) { vad = 1; } return vad; } int WebRtcVad_ValidRateAndFrameLength(int rate, size_t frame_length) { int return_value = -1; size_t i; int valid_length_ms; size_t valid_length; // We only allow 10, 20 or 30 ms frames. Loop through valid frame rates and // see if we have a matching pair. for (i = 0; i < kRatesSize; i++) { if (kValidRates[i] == rate) { for (valid_length_ms = 10; valid_length_ms <= kMaxFrameLengthMs; valid_length_ms += 10) { valid_length = (size_t)(kValidRates[i] / 1000 * valid_length_ms); if (frame_length == valid_length) { return_value = 0; break; } } break; } } return return_value; } ================================================ FILE: thirdparty/webrtc/rtc_base/checks.cc ================================================ /* * Copyright 2006 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // Most of this was borrowed (with minor modifications) from V8's and Chromium's // src/base/logging.cc. #include #include #include //added by me #include "typedefs.h" #if defined(WEBRTC_ANDROID) #define RTC_LOG_TAG_ANDROID "rtc" #include // NOLINT #endif #if defined(WEBRTC_WIN) #include #endif #if defined(WEBRTC_WIN) #define LAST_SYSTEM_ERROR (::GetLastError()) #elif defined(__native_client__) && __native_client__ #define LAST_SYSTEM_ERROR (0) #elif defined(WEBRTC_POSIX) #include #define LAST_SYSTEM_ERROR (errno) #endif // WEBRTC_WIN #include "rtc_base/checks.h" #if defined(_MSC_VER) // Warning C4722: destructor never returns, potential memory leak. // FatalMessage's dtor very intentionally aborts. #pragma warning(disable:4722) #endif namespace rtc { namespace { void VPrintError(const char* format, va_list args) { #if defined(WEBRTC_ANDROID) __android_log_vprint(ANDROID_LOG_ERROR, RTC_LOG_TAG_ANDROID, format, args); #else vfprintf(stderr, format, args); #endif } #if defined(__GNUC__) void PrintError(const char* format, ...) __attribute__((__format__(__printf__, 1, 2))); #endif void PrintError(const char* format, ...) { va_list args; va_start(args, format); VPrintError(format, args); va_end(args); } } // namespace FatalMessage::FatalMessage(const char* file, int line) { Init(file, line); } FatalMessage::FatalMessage(const char* file, int line, std::string* result) { Init(file, line); stream_ << "Check failed: " << *result << std::endl << "# "; delete result; } NO_RETURN FatalMessage::~FatalMessage() { fflush(stdout); fflush(stderr); stream_ << std::endl << "#" << std::endl; PrintError("%s", stream_.str().c_str()); fflush(stderr); abort(); } void FatalMessage::Init(const char* file, int line) { stream_ << std::endl << std::endl << "#" << std::endl << "# Fatal error in " << file << ", line " << line << std::endl << "# last system error: " << LAST_SYSTEM_ERROR << std::endl << "# "; } // MSVC doesn't like complex extern templates and DLLs. #if !defined(COMPILER_MSVC) // Explicit instantiations for commonly used comparisons. template std::string* MakeCheckOpString( const int&, const int&, const char* names); template std::string* MakeCheckOpString( const unsigned long&, const unsigned long&, const char* names); template std::string* MakeCheckOpString( const unsigned long&, const unsigned int&, const char* names); template std::string* MakeCheckOpString( const unsigned int&, const unsigned long&, const char* names); template std::string* MakeCheckOpString( const std::string&, const std::string&, const char* name); #endif } // namespace rtc // Function to call from the C version of the RTC_CHECK and RTC_DCHECK macros. NO_RETURN void rtc_FatalMessage(const char* file, int line, const char* msg) { rtc::FatalMessage(file, line).stream() << msg; } ================================================ FILE: thirdparty/webrtc/rtc_base/checks.h ================================================ /* * Copyright 2006 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef RTC_BASE_CHECKS_H_ #define RTC_BASE_CHECKS_H_ #include "typedefs.h" // NOLINT(build/include) // If you for some reson need to know if DCHECKs are on, test the value of // RTC_DCHECK_IS_ON. (Test its value, not if it's defined; it'll always be // defined, to either a true or a false value.) #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) #define RTC_DCHECK_IS_ON 1 #else #define RTC_DCHECK_IS_ON 0 #endif #ifdef __cplusplus extern "C" { #endif NO_RETURN void rtc_FatalMessage(const char* file, int line, const char* msg); #ifdef __cplusplus } // extern "C" #endif #ifdef __cplusplus // C++ version. #include #include #include "rtc_base/numerics/safe_compare.h" // The macros here print a message to stderr and abort under various // conditions. All will accept additional stream messages. For example: // RTC_DCHECK_EQ(foo, bar) << "I'm printed when foo != bar."; // // - RTC_CHECK(x) is an assertion that x is always true, and that if it isn't, // it's better to terminate the process than to continue. During development, // the reason that it's better to terminate might simply be that the error // handling code isn't in place yet; in production, the reason might be that // the author of the code truly believes that x will always be true, but that // she recognizes that if she is wrong, abrupt and unpleasant process // termination is still better than carrying on with the assumption violated. // // RTC_CHECK always evaluates its argument, so it's OK for x to have side // effects. // // - RTC_DCHECK(x) is the same as RTC_CHECK(x)---an assertion that x is always // true---except that x will only be evaluated in debug builds; in production // builds, x is simply assumed to be true. This is useful if evaluating x is // expensive and the expected cost of failing to detect the violated // assumption is acceptable. You should not handle cases where a production // build fails to spot a violated condition, even those that would result in // crashes. If the code needs to cope with the error, make it cope, but don't // call RTC_DCHECK; if the condition really can't occur, but you'd sleep // better at night knowing that the process will suicide instead of carrying // on in case you were wrong, use RTC_CHECK instead of RTC_DCHECK. // // RTC_DCHECK only evaluates its argument in debug builds, so if x has visible // side effects, you need to write e.g. // bool w = x; RTC_DCHECK(w); // // - RTC_CHECK_EQ, _NE, _GT, ..., and RTC_DCHECK_EQ, _NE, _GT, ... are // specialized variants of RTC_CHECK and RTC_DCHECK that print prettier // messages if the condition doesn't hold. Prefer them to raw RTC_CHECK and // RTC_DCHECK. // // - FATAL() aborts unconditionally. // // TODO(ajm): Ideally, checks.h would be combined with logging.h, but // consolidation with system_wrappers/logging.h should happen first. namespace rtc { // Helper macro which avoids evaluating the arguments to a stream if // the condition doesn't hold. #define RTC_LAZY_STREAM(stream, condition) \ !(condition) ? static_cast(0) : rtc::FatalMessageVoidify() & (stream) // The actual stream used isn't important. We reference |ignored| in the code // but don't evaluate it; this is to avoid "unused variable" warnings (we do so // in a particularly convoluted way with an extra ?: because that appears to be // the simplest construct that keeps Visual Studio from complaining about // condition being unused). #define RTC_EAT_STREAM_PARAMETERS(ignored) \ (true ? true : ((void)(ignored), true)) \ ? static_cast(0) \ : rtc::FatalMessageVoidify() & rtc::FatalMessage("", 0).stream() // Call RTC_EAT_STREAM_PARAMETERS with an argument that fails to compile if // values of the same types as |a| and |b| can't be compared with the given // operation, and that would evaluate |a| and |b| if evaluated. #define RTC_EAT_STREAM_PARAMETERS_OP(op, a, b) \ RTC_EAT_STREAM_PARAMETERS(((void)rtc::Safe##op(a, b))) // RTC_CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG or anything else, so the check will be executed // regardless of compilation mode. // // We make sure RTC_CHECK et al. always evaluates their arguments, as // doing RTC_CHECK(FunctionWithSideEffect()) is a common idiom. #define RTC_CHECK(condition) \ RTC_LAZY_STREAM(rtc::FatalMessage(__FILE__, __LINE__).stream(), \ !(condition)) \ << "Check failed: " #condition << std::endl << "# " // Helper macro for binary operators. // Don't use this macro directly in your code, use RTC_CHECK_EQ et al below. // // TODO(akalin): Rewrite this so that constructs like if (...) // RTC_CHECK_EQ(...) else { ... } work properly. #define RTC_CHECK_OP(name, op, val1, val2) \ if (std::string* _result = \ rtc::Check##name##Impl((val1), (val2), #val1 " " #op " " #val2)) \ rtc::FatalMessage(__FILE__, __LINE__, _result).stream() // Build the error message string. This is separate from the "Impl" // function template because it is not performance critical and so can // be out of line, while the "Impl" code should be inline. Caller // takes ownership of the returned string. template std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { std::ostringstream ss; ss << names << " (" << v1 << " vs. " << v2 << ")"; std::string* msg = new std::string(ss.str()); return msg; } // MSVC doesn't like complex extern templates and DLLs. #if !defined(COMPILER_MSVC) // Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated // in logging.cc. extern template std::string* MakeCheckOpString( const int&, const int&, const char* names); extern template std::string* MakeCheckOpString( const unsigned long&, const unsigned long&, const char* names); extern template std::string* MakeCheckOpString( const unsigned long&, const unsigned int&, const char* names); extern template std::string* MakeCheckOpString( const unsigned int&, const unsigned long&, const char* names); extern template std::string* MakeCheckOpString( const std::string&, const std::string&, const char* name); #endif // Helper functions for RTC_CHECK_OP macro. // The (int, int) specialization works around the issue that the compiler // will not instantiate the template version of the function on values of // unnamed enum type - see comment below. #define DEFINE_RTC_CHECK_OP_IMPL(name) \ template \ inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ const char* names) { \ if (rtc::Safe##name(v1, v2)) \ return nullptr; \ else \ return rtc::MakeCheckOpString(v1, v2, names); \ } \ inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \ if (rtc::Safe##name(v1, v2)) \ return nullptr; \ else \ return rtc::MakeCheckOpString(v1, v2, names); \ } DEFINE_RTC_CHECK_OP_IMPL(Eq) DEFINE_RTC_CHECK_OP_IMPL(Ne) DEFINE_RTC_CHECK_OP_IMPL(Le) DEFINE_RTC_CHECK_OP_IMPL(Lt) DEFINE_RTC_CHECK_OP_IMPL(Ge) DEFINE_RTC_CHECK_OP_IMPL(Gt) #undef DEFINE_RTC_CHECK_OP_IMPL #define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(Eq, ==, val1, val2) #define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(Ne, !=, val1, val2) #define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(Le, <=, val1, val2) #define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(Lt, <, val1, val2) #define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(Ge, >=, val1, val2) #define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(Gt, >, val1, val2) // The RTC_DCHECK macro is equivalent to RTC_CHECK except that it only generates // code in debug builds. It does reference the condition parameter in all cases, // though, so callers won't risk getting warnings about unused variables. #if RTC_DCHECK_IS_ON #define RTC_DCHECK(condition) RTC_CHECK(condition) #define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2) #define RTC_DCHECK_NE(v1, v2) RTC_CHECK_NE(v1, v2) #define RTC_DCHECK_LE(v1, v2) RTC_CHECK_LE(v1, v2) #define RTC_DCHECK_LT(v1, v2) RTC_CHECK_LT(v1, v2) #define RTC_DCHECK_GE(v1, v2) RTC_CHECK_GE(v1, v2) #define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2) #else #define RTC_DCHECK(condition) RTC_EAT_STREAM_PARAMETERS(condition) #define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Eq, v1, v2) #define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ne, v1, v2) #define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Le, v1, v2) #define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Lt, v1, v2) #define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ge, v1, v2) #define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Gt, v1, v2) #endif // This is identical to LogMessageVoidify but in name. class FatalMessageVoidify { public: FatalMessageVoidify() { } // This has to be an operator with a precedence lower than << but // higher than ?: void operator&(std::ostream&) { } }; #define RTC_UNREACHABLE_CODE_HIT false #define RTC_NOTREACHED() RTC_DCHECK(RTC_UNREACHABLE_CODE_HIT) // TODO(bugs.webrtc.org/8454): Add an RTC_ prefix or rename differently. #define FATAL() rtc::FatalMessage(__FILE__, __LINE__).stream() // TODO(ajm): Consider adding RTC_NOTIMPLEMENTED macro when // base/logging.h and system_wrappers/logging.h are consolidated such that we // can match the Chromium behavior. // Like a stripped-down LogMessage from logging.h, except that it aborts. class FatalMessage { public: FatalMessage(const char* file, int line); // Used for RTC_CHECK_EQ(), etc. Takes ownership of the given string. FatalMessage(const char* file, int line, std::string* result); NO_RETURN ~FatalMessage(); std::ostream& stream() { return stream_; } private: void Init(const char* file, int line); std::ostringstream stream_; }; // Performs the integer division a/b and returns the result. CHECKs that the // remainder is zero. template inline T CheckedDivExact(T a, T b) { RTC_CHECK_EQ(a % b, 0) << a << " is not evenly divisible by " << b; return a / b; } } // namespace rtc #else // __cplusplus not defined // C version. Lacks many features compared to the C++ version, but usage // guidelines are the same. #define RTC_CHECK(condition) \ do { \ if (!(condition)) { \ rtc_FatalMessage(__FILE__, __LINE__, "CHECK failed: " #condition); \ } \ } while (0) #define RTC_CHECK_EQ(a, b) RTC_CHECK((a) == (b)) #define RTC_CHECK_NE(a, b) RTC_CHECK((a) != (b)) #define RTC_CHECK_LE(a, b) RTC_CHECK((a) <= (b)) #define RTC_CHECK_LT(a, b) RTC_CHECK((a) < (b)) #define RTC_CHECK_GE(a, b) RTC_CHECK((a) >= (b)) #define RTC_CHECK_GT(a, b) RTC_CHECK((a) > (b)) #define RTC_DCHECK(condition) \ do { \ if (RTC_DCHECK_IS_ON && !(condition)) { \ rtc_FatalMessage(__FILE__, __LINE__, "DCHECK failed: " #condition); \ } \ } while (0) #define RTC_DCHECK_EQ(a, b) RTC_DCHECK((a) == (b)) #define RTC_DCHECK_NE(a, b) RTC_DCHECK((a) != (b)) #define RTC_DCHECK_LE(a, b) RTC_DCHECK((a) <= (b)) #define RTC_DCHECK_LT(a, b) RTC_DCHECK((a) < (b)) #define RTC_DCHECK_GE(a, b) RTC_DCHECK((a) >= (b)) #define RTC_DCHECK_GT(a, b) RTC_DCHECK((a) > (b)) #endif // __cplusplus #endif // RTC_BASE_CHECKS_H_ ================================================ FILE: thirdparty/webrtc/rtc_base/compile_assert_c.h ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef RTC_BASE_COMPILE_ASSERT_C_H_ #define RTC_BASE_COMPILE_ASSERT_C_H_ // Use this macro to verify at compile time that certain restrictions are met. // The argument is the boolean expression to evaluate. // Example: // RTC_COMPILE_ASSERT(sizeof(foo) < 128); // Note: In C++, use static_assert instead! #define RTC_COMPILE_ASSERT(expression) switch (0) {case 0: case expression:;} #endif // RTC_BASE_COMPILE_ASSERT_C_H_ ================================================ FILE: thirdparty/webrtc/rtc_base/numerics/safe_compare.h ================================================ /* * Copyright 2016 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // This file defines six constexpr functions: // // rtc::SafeEq // == // rtc::SafeNe // != // rtc::SafeLt // < // rtc::SafeLe // <= // rtc::SafeGt // > // rtc::SafeGe // >= // // They each accept two arguments of arbitrary types, and in almost all cases, // they simply call the appropriate comparison operator. However, if both // arguments are integers, they don't compare them using C++'s quirky rules, // but instead adhere to the true mathematical definitions. It is as if the // arguments were first converted to infinite-range signed integers, and then // compared, although of course nothing expensive like that actually takes // place. In practice, for signed/signed and unsigned/unsigned comparisons and // some mixed-signed comparisons with a compile-time constant, the overhead is // zero; in the remaining cases, it is just a few machine instructions (no // branches). #ifndef RTC_BASE_NUMERICS_SAFE_COMPARE_H_ #define RTC_BASE_NUMERICS_SAFE_COMPARE_H_ #include #include #include #include #include "rtc_base/type_traits.h" namespace rtc { namespace safe_cmp_impl { template struct LargerIntImpl : std::false_type {}; template <> struct LargerIntImpl : std::true_type { using type = int16_t; }; template <> struct LargerIntImpl : std::true_type { using type = int32_t; }; template <> struct LargerIntImpl : std::true_type { using type = int64_t; }; // LargerInt::value is true iff there's a signed type that's larger // than T1 (and no larger than the larger of T2 and int*, for performance // reasons); and if there is such a type, LargerInt::type is an alias // for it. template struct LargerInt : LargerIntImpl {}; template constexpr typename std::make_unsigned::type MakeUnsigned(T a) { return static_cast::type>(a); } // Overload for when both T1 and T2 have the same signedness. template ::value == std::is_signed::value>::type* = nullptr> constexpr bool Cmp(T1 a, T2 b) { return Op::Op(a, b); } // Overload for signed - unsigned comparison that can be promoted to a bigger // signed type. template ::value && std::is_unsigned::value && LargerInt::value>::type* = nullptr> constexpr bool Cmp(T1 a, T2 b) { return Op::Op(a, static_cast::type>(b)); } // Overload for unsigned - signed comparison that can be promoted to a bigger // signed type. template ::value && std::is_signed::value && LargerInt::value>::type* = nullptr> constexpr bool Cmp(T1 a, T2 b) { return Op::Op(static_cast::type>(a), b); } // Overload for signed - unsigned comparison that can't be promoted to a bigger // signed type. template ::value && std::is_unsigned::value && !LargerInt::value>::type* = nullptr> constexpr bool Cmp(T1 a, T2 b) { return a < 0 ? Op::Op(-1, 0) : Op::Op(safe_cmp_impl::MakeUnsigned(a), b); } // Overload for unsigned - signed comparison that can't be promoted to a bigger // signed type. template ::value && std::is_signed::value && !LargerInt::value>::type* = nullptr> constexpr bool Cmp(T1 a, T2 b) { return b < 0 ? Op::Op(0, -1) : Op::Op(a, safe_cmp_impl::MakeUnsigned(b)); } #define RTC_SAFECMP_MAKE_OP(name, op) \ struct name { \ template \ static constexpr bool Op(T1 a, T2 b) { \ return a op b; \ } \ }; RTC_SAFECMP_MAKE_OP(EqOp, ==) RTC_SAFECMP_MAKE_OP(NeOp, !=) RTC_SAFECMP_MAKE_OP(LtOp, <) RTC_SAFECMP_MAKE_OP(LeOp, <=) RTC_SAFECMP_MAKE_OP(GtOp, >) RTC_SAFECMP_MAKE_OP(GeOp, >=) #undef RTC_SAFECMP_MAKE_OP } // namespace safe_cmp_impl #define RTC_SAFECMP_MAKE_FUN(name) \ template \ constexpr \ typename std::enable_if::value && IsIntlike::value, \ bool>::type Safe##name(T1 a, T2 b) { \ /* Unary plus here turns enums into real integral types. */ \ return safe_cmp_impl::Cmp(+a, +b); \ } \ template \ constexpr \ typename std::enable_if::value || !IsIntlike::value, \ bool>::type Safe##name(const T1& a, \ const T2& b) { \ return safe_cmp_impl::name##Op::Op(a, b); \ } RTC_SAFECMP_MAKE_FUN(Eq) RTC_SAFECMP_MAKE_FUN(Ne) RTC_SAFECMP_MAKE_FUN(Lt) RTC_SAFECMP_MAKE_FUN(Le) RTC_SAFECMP_MAKE_FUN(Gt) RTC_SAFECMP_MAKE_FUN(Ge) #undef RTC_SAFECMP_MAKE_FUN } // namespace rtc #endif // RTC_BASE_NUMERICS_SAFE_COMPARE_H_ ================================================ FILE: thirdparty/webrtc/rtc_base/sanitizer.h ================================================ /* * Copyright 2016 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef RTC_BASE_SANITIZER_H_ #define RTC_BASE_SANITIZER_H_ #include // for size_t #if defined(__has_feature) #if __has_feature(address_sanitizer) #define RTC_HAS_ASAN 1 #endif #if __has_feature(memory_sanitizer) #define RTC_HAS_MSAN 1 #endif #endif #ifndef RTC_HAS_ASAN #define RTC_HAS_ASAN 0 #endif #ifndef RTC_HAS_MSAN #define RTC_HAS_MSAN 0 #endif #if RTC_HAS_ASAN #include #endif #if RTC_HAS_MSAN #include #endif #ifdef __has_attribute #if __has_attribute(no_sanitize) #define RTC_NO_SANITIZE(what) __attribute__((no_sanitize(what))) #endif #endif #ifndef RTC_NO_SANITIZE #define RTC_NO_SANITIZE(what) #endif // Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements) // as being unaddressable, so that reads and writes are not allowed. ASan may // narrow the range to the nearest alignment boundaries. static inline void rtc_AsanPoison(const volatile void* ptr, size_t element_size, size_t num_elements) { #if RTC_HAS_ASAN ASAN_POISON_MEMORY_REGION(ptr, element_size * num_elements); #endif } // Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements) // as being addressable, so that reads and writes are allowed. ASan may widen // the range to the nearest alignment boundaries. static inline void rtc_AsanUnpoison(const volatile void* ptr, size_t element_size, size_t num_elements) { #if RTC_HAS_ASAN ASAN_UNPOISON_MEMORY_REGION(ptr, element_size * num_elements); #endif } // Ask MSan to mark the memory range [ptr, ptr + element_size * num_elements) // as being uninitialized. static inline void rtc_MsanMarkUninitialized(const volatile void* ptr, size_t element_size, size_t num_elements) { #if RTC_HAS_MSAN __msan_poison(ptr, element_size * num_elements); #endif } // Force an MSan check (if any bits in the memory range [ptr, ptr + // element_size * num_elements) are uninitialized the call will crash with an // MSan report). static inline void rtc_MsanCheckInitialized(const volatile void* ptr, size_t element_size, size_t num_elements) { #if RTC_HAS_MSAN __msan_check_mem_is_initialized(ptr, element_size * num_elements); #endif } #ifdef __cplusplus namespace rtc { template inline void AsanPoison(const T& mem) { rtc_AsanPoison(mem.data(), sizeof(mem.data()[0]), mem.size()); } template inline void AsanUnpoison(const T& mem) { rtc_AsanUnpoison(mem.data(), sizeof(mem.data()[0]), mem.size()); } template inline void MsanMarkUninitialized(const T& mem) { rtc_MsanMarkUninitialized(mem.data(), sizeof(mem.data()[0]), mem.size()); } template inline void MsanCheckInitialized(const T& mem) { rtc_MsanCheckInitialized(mem.data(), sizeof(mem.data()[0]), mem.size()); } } // namespace rtc #endif // __cplusplus #endif // RTC_BASE_SANITIZER_H_ ================================================ FILE: thirdparty/webrtc/rtc_base/type_traits.h ================================================ /* * Copyright 2016 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef RTC_BASE_TYPE_TRAITS_H_ #define RTC_BASE_TYPE_TRAITS_H_ #include #include namespace rtc { // Determines if the given class has zero-argument .data() and .size() methods // whose return values are convertible to T* and size_t, respectively. template class HasDataAndSize { private: template < typename C, typename std::enable_if< std::is_convertible().data()), T*>::value && std::is_convertible().size()), std::size_t>::value>::type* = nullptr> static int Test(int); template static char Test(...); public: static constexpr bool value = std::is_same(0)), int>::value; }; namespace test_has_data_and_size { template struct Test1 { DR data(); SR size(); }; static_assert(HasDataAndSize, int>::value, ""); static_assert(HasDataAndSize, const int>::value, ""); static_assert(HasDataAndSize, const int>::value, ""); static_assert(!HasDataAndSize, int>::value, "implicit cast of const int* to int*"); static_assert(!HasDataAndSize, int>::value, "implicit cast of char* to int*"); struct Test2 { int* data; size_t size; }; static_assert(!HasDataAndSize::value, ".data and .size aren't functions"); struct Test3 { int* data(); }; static_assert(!HasDataAndSize::value, ".size() is missing"); class Test4 { int* data(); size_t size(); }; static_assert(!HasDataAndSize::value, ".data() and .size() are private"); } // namespace test_has_data_and_size namespace type_traits_impl { // Determines if the given type is an enum that converts implicitly to // an integral type. template struct IsIntEnum { private: // This overload is used if the type is an enum, and unary plus // compiles and turns it into an integral type. template ::value && std::is_integral())>::value>::type* = nullptr> static int Test(int); // Otherwise, this overload is used. template static char Test(...); public: static constexpr bool value = std::is_same::type>(0)), int>::value; }; } // namespace type_traits_impl // Determines if the given type is integral, or an enum that // converts implicitly to an integral type. template struct IsIntlike { private: using X = typename std::remove_reference::type; public: static constexpr bool value = std::is_integral::value || type_traits_impl::IsIntEnum::value; }; namespace test_enum_intlike { enum E1 { e1 }; enum { e2 }; enum class E3 { e3 }; struct S {}; static_assert(type_traits_impl::IsIntEnum::value, ""); static_assert(type_traits_impl::IsIntEnum::value, ""); static_assert(!type_traits_impl::IsIntEnum::value, ""); static_assert(!type_traits_impl::IsIntEnum::value, ""); static_assert(!type_traits_impl::IsIntEnum::value, ""); static_assert(!type_traits_impl::IsIntEnum::value, ""); static_assert(IsIntlike::value, ""); static_assert(IsIntlike::value, ""); static_assert(!IsIntlike::value, ""); static_assert(IsIntlike::value, ""); static_assert(!IsIntlike::value, ""); static_assert(!IsIntlike::value, ""); } // test_enum_intlike } // namespace rtc #endif // RTC_BASE_TYPE_TRAITS_H_ ================================================ FILE: thirdparty/webrtc/system_wrappers/include/cpu_features_wrapper.h ================================================ /* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_ #define SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_ #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #include "typedefs.h" // NOLINT(build/include) // List of features in x86. typedef enum { kSSE2, kSSE3 } CPUFeature; // List of features in ARM. enum { kCPUFeatureARMv7 = (1 << 0), kCPUFeatureVFPv3 = (1 << 1), kCPUFeatureNEON = (1 << 2), kCPUFeatureLDREXSTREX = (1 << 3) }; typedef int (*WebRtc_CPUInfo)(CPUFeature feature); // Returns true if the CPU supports the feature. extern WebRtc_CPUInfo WebRtc_GetCPUInfo; // No CPU feature is available => straight C path. extern WebRtc_CPUInfo WebRtc_GetCPUInfoNoASM; // Return the features in an ARM device. // It detects the features in the hardware platform, and returns supported // values in the above enum definition as a bitmask. extern uint64_t WebRtc_GetCPUFeaturesARM(void); #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif #endif // SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_ ================================================ FILE: thirdparty/webrtc/typedefs.h ================================================ /* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // This file contains platform-specific typedefs and defines. // Much of it is derived from Chromium's build/build_config.h. #ifndef TYPEDEFS_H_ #define TYPEDEFS_H_ // 参考BUILD.gn 以linux为例定义如下几个变量 #define WEBRTC_POSIX #define WEBRTC_LINUX // Processor architecture detection. For more info on what's defined, see: // http://msdn.microsoft.com/en-us/library/b0084kay.aspx // http://www.agner.org/optimize/calling_conventions.pdf // or with gcc, run: "echo | gcc -E -dM -" #if defined(_M_X64) || defined(__x86_64__) #define WEBRTC_ARCH_X86_FAMILY #define WEBRTC_ARCH_X86_64 #define WEBRTC_ARCH_64_BITS #define WEBRTC_ARCH_LITTLE_ENDIAN #elif defined(__aarch64__) #define WEBRTC_ARCH_ARM_FAMILY #define WEBRTC_ARCH_64_BITS #define WEBRTC_ARCH_LITTLE_ENDIAN #elif defined(_M_IX86) || defined(__i386__) #define WEBRTC_ARCH_X86_FAMILY #define WEBRTC_ARCH_X86 #define WEBRTC_ARCH_32_BITS #define WEBRTC_ARCH_LITTLE_ENDIAN #elif defined(__ARMEL__) #define WEBRTC_ARCH_ARM_FAMILY #define WEBRTC_ARCH_32_BITS #define WEBRTC_ARCH_LITTLE_ENDIAN #elif defined(__MIPSEL__) #define WEBRTC_ARCH_MIPS_FAMILY #if defined(__LP64__) #define WEBRTC_ARCH_64_BITS #else #define WEBRTC_ARCH_32_BITS #endif #define WEBRTC_ARCH_LITTLE_ENDIAN #elif defined(__pnacl__) #define WEBRTC_ARCH_32_BITS #define WEBRTC_ARCH_LITTLE_ENDIAN #else #error Please add support for your architecture in typedefs.h #endif #if !(defined(WEBRTC_ARCH_LITTLE_ENDIAN) ^ defined(WEBRTC_ARCH_BIG_ENDIAN)) #error Define either WEBRTC_ARCH_LITTLE_ENDIAN or WEBRTC_ARCH_BIG_ENDIAN #endif // TODO(zhongwei.yao): WEBRTC_CPU_DETECTION is only used in one place; we should // probably just remove it. #if (defined(WEBRTC_ARCH_X86_FAMILY) && !defined(__SSE2__)) #define WEBRTC_CPU_DETECTION #endif #include // Annotate a function indicating the caller must examine the return value. // Use like: // int foo() RTC_WARN_UNUSED_RESULT; // To explicitly ignore a result, cast to void. // TODO(kwiberg): Remove when we can use [[nodiscard]] from C++17. #if defined(__clang__) #define RTC_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) #elif defined(__GNUC__) // gcc has a __warn_unused_result__ attribute, but you can't quiet it by // casting to void, so we don't use it. #define RTC_WARN_UNUSED_RESULT #else #define RTC_WARN_UNUSED_RESULT #endif // Put after a variable that might not be used, to prevent compiler warnings: // int result ATTRIBUTE_UNUSED = DoSomething(); // assert(result == 17); // Deprecated since it only works with GCC & clang. See RTC_UNUSED below. // TODO(terelius): Remove. #ifndef ATTRIBUTE_UNUSED #if defined(__GNUC__) || defined(__clang__) #define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) #else #define ATTRIBUTE_UNUSED #endif #endif #ifndef NO_RETURN // Annotate a function that will not return control flow to the caller. #if defined(_MSC_VER) #define NO_RETURN __declspec(noreturn) #elif defined(__GNUC__) #define NO_RETURN __attribute__ ((__noreturn__)) #else #define NO_RETURN #endif #endif // Prevent the compiler from warning about an unused variable. For example: // int result = DoSomething(); // assert(result == 17); // RTC_UNUSED(result); // Note: In most cases it is better to remove the unused variable rather than // suppressing the compiler warning. #ifndef RTC_UNUSED #define RTC_UNUSED(x) static_cast(x) #endif // RTC_UNUSED #endif // TYPEDEFS_H_ ================================================ FILE: valgrind.sh ================================================ #!/usr/bin/env bash FILE=build/vad-demo valgrind --leak-check=full --show-leak-kinds=all --show-reachable=no --track-origins=yes $FILE