├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── examples ├── benchmark │ ├── CMakeLists.txt │ └── main.c ├── serial │ ├── CMakeLists.txt │ ├── main.c │ ├── requirements.txt │ └── serial_denoise.py └── usb_pdm_microphone │ ├── CMakeLists.txt │ └── main.c ├── lib └── rnnoise │ ├── AUTHORS │ ├── COPYING │ ├── include │ └── rnnoise.h │ └── src │ ├── _kiss_fft_guts.h │ ├── arch.h │ ├── celt_lpc.c │ ├── celt_lpc.h │ ├── common.h │ ├── denoise.c │ ├── kiss_fft.c │ ├── kiss_fft.h │ ├── opus_types.h │ ├── pitch.c │ ├── pitch.h │ ├── rnn.c │ ├── rnn.h │ ├── rnn_data.c │ ├── rnn_data.h │ └── tansig_table.h └── pico_sdk_import.cmake /.gitignore: -------------------------------------------------------------------------------- 1 | build* 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/microphone-library-for-pico"] 2 | path = lib/microphone-library-for-pico 3 | url = https://github.com/ArmDeveloperEcosystem/microphone-library-for-pico.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13...3.27) 2 | 3 | include(pico_sdk_import.cmake) 4 | 5 | project(rnn-noise-examples-for-pico-2) 6 | 7 | pico_sdk_init() 8 | 9 | add_library(rnnoise INTERFACE) 10 | 11 | target_sources(rnnoise INTERFACE 12 | ${CMAKE_CURRENT_LIST_DIR}/lib/rnnoise/src/celt_lpc.c 13 | ${CMAKE_CURRENT_LIST_DIR}/lib/rnnoise/src/denoise.c 14 | ${CMAKE_CURRENT_LIST_DIR}/lib/rnnoise/src/kiss_fft.c 15 | ${CMAKE_CURRENT_LIST_DIR}/lib/rnnoise/src/pitch.c 16 | ${CMAKE_CURRENT_LIST_DIR}/lib/rnnoise/src/rnn.c 17 | ${CMAKE_CURRENT_LIST_DIR}/lib/rnnoise/src/rnn_data.c 18 | ) 19 | 20 | target_include_directories(rnnoise INTERFACE 21 | ${CMAKE_CURRENT_LIST_DIR}/lib/rnnoise/src 22 | ${CMAKE_CURRENT_LIST_DIR}/lib/rnnoise/include 23 | ) 24 | 25 | add_subdirectory("examples/benchmark") 26 | add_subdirectory("examples/serial") 27 | add_subdirectory("examples/usb_pdm_microphone") 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024, Arm Limited 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RNNoise Examples for Pico 2 2 | 3 | Example project to demonstrate the [RNNoise](https://github.com/xiph/rnnoise) audio noise suppression algorithm running on a Raspberry Pi Pico 2 board, using the RP2350's Cortex-M33 processor. 4 | 5 | 6 | ## Hardware 7 | 8 | * RP2350 board 9 | * Raspberry Pi Pico 2 10 | * Microphones 11 | * PDM 12 | * [Adafruit PDM MEMS Microphone Breakout](https://www.adafruit.com/product/3492) 13 | 14 | ### Default Pinout 15 | 16 | 17 | #### PDM Microphone 18 | 19 | | Raspberry Pi Pico 2 / RP2350 | PDM Microphone | 20 | | ---------------------------- | ----------------- | 21 | | 3.3V | VCC | 22 | | GND | GND | 23 | | GND | SEL | 24 | | GPIO 21 | DAT | 25 | | GPIO 20 | CLK | 26 | 27 | GPIO pins are configurable in example. 28 | 29 | ## Examples 30 | 31 | See [examples](examples/) folder. 32 | 33 | 34 | ## Cloning 35 | 36 | ```sh 37 | git clone https://github.com/ArmDeveloperEcosystem/rnnoise-examples-for-pico-2.git 38 | ``` 39 | 40 | ## Building 41 | 42 | 1. [Set up the Pico C/C++ SDK](https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf) 43 | 2. Set `PICO_SDK_PATH` 44 | ```sh 45 | export PICO_SDK_PATH=/path/to/pico-sdk 46 | ``` 47 | 3. Create `build` dir, run `cmake` and `make`: 48 | ``` 49 | mkdir build 50 | cd build 51 | cmake .. -DPICO_BOARD=pico2 52 | make 53 | ``` 54 | 4. Copy example `.uf2` to Pico when in BOOT mode. 55 | 56 | ## License 57 | 58 | [BSD-3-Clause license](LICENSE) 59 | 60 | 61 | --- 62 | 63 | Disclaimer: This is not an official Arm product. -------------------------------------------------------------------------------- /examples/benchmark/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13...3.27) 2 | 3 | add_executable(rnnoise-benchmark 4 | main.c 5 | ) 6 | 7 | target_compile_definitions(rnnoise-benchmark PRIVATE 8 | -DPICO_STACK_SIZE=0xc000 9 | ) 10 | 11 | target_link_libraries(rnnoise-benchmark 12 | pico_stdlib 13 | rnnoise 14 | ) 15 | 16 | pico_enable_stdio_usb(rnnoise-benchmark 1) 17 | pico_enable_stdio_uart(rnnoise-benchmark 0) 18 | 19 | pico_add_extra_outputs(rnnoise-benchmark) 20 | -------------------------------------------------------------------------------- /examples/benchmark/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | // 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "rnnoise.h" 13 | 14 | int main() 15 | { 16 | stdio_init_all(); 17 | 18 | while (!stdio_usb_connected()) { 19 | tight_loop_contents(); 20 | } 21 | 22 | DenoiseState* st = rnnoise_create(NULL); 23 | 24 | #define FRAME_SIZE 480 25 | float x[FRAME_SIZE]; 26 | 27 | // run once without timing to init 28 | memset(x, 0x00, sizeof(x)); 29 | rnnoise_process_frame(st, x, x); 30 | 31 | const int benchmark_iterations = 100; 32 | absolute_time_t rnnoise_process_frame_time = 0; 33 | 34 | for (int j = 0; j < benchmark_iterations; j++) { 35 | for (int i = 0; i < FRAME_SIZE; i++) { 36 | x[i] = ((float)rand()) / ((float)RAND_MAX) * 0x7fff; 37 | } 38 | 39 | absolute_time_t usec_rnnoise_process_frame_start = get_absolute_time(); 40 | 41 | rnnoise_process_frame(st, x, x); 42 | 43 | absolute_time_t usec_rnnoise_process_frame_end = get_absolute_time(); 44 | 45 | rnnoise_process_frame_time += (usec_rnnoise_process_frame_end - usec_rnnoise_process_frame_start); 46 | } 47 | 48 | printf("rnnoise_process_frame %llu usec\n", (rnnoise_process_frame_time / benchmark_iterations)); 49 | 50 | while (1) { 51 | tight_loop_contents(); 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /examples/serial/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13...3.27) 2 | 3 | add_executable(rnnoise-serial 4 | main.c 5 | ) 6 | 7 | target_compile_definitions(rnnoise-serial PRIVATE 8 | -DPICO_STACK_SIZE=0xc000 9 | ) 10 | 11 | target_link_libraries(rnnoise-serial 12 | pico_stdlib 13 | rnnoise 14 | ) 15 | 16 | pico_enable_stdio_usb(rnnoise-serial 1) 17 | pico_enable_stdio_uart(rnnoise-serial 0) 18 | 19 | pico_add_extra_outputs(rnnoise-serial) 20 | -------------------------------------------------------------------------------- /examples/serial/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | // 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "rnnoise.h" 13 | 14 | int main() 15 | { 16 | stdio_init_all(); 17 | 18 | while (!stdio_usb_connected()) { 19 | tight_loop_contents(); 20 | } 21 | 22 | #define FRAME_SIZE 480 23 | int16_t x_i16[FRAME_SIZE]; 24 | float x_f32[FRAME_SIZE]; 25 | uint8_t* x_i8 = (uint8_t*)x_i16; 26 | 27 | DenoiseState* st = rnnoise_create(NULL); 28 | 29 | // run once to init 30 | memset(x_f32, 0x00, sizeof(x_f32)); 31 | rnnoise_process_frame(st, x_f32, x_f32); 32 | 33 | while (1) { 34 | for (size_t i = 0; i < sizeof(x_i16); i++) { 35 | x_i8[i] = getchar(); 36 | } 37 | 38 | for (int i = 0; i < FRAME_SIZE; i++) { 39 | x_f32[i] = x_i16[i]; 40 | } 41 | 42 | float vad = rnnoise_process_frame(st, x_f32, x_f32); 43 | 44 | for (int i = 0; i < FRAME_SIZE; i++) { 45 | x_i16[i] = x_f32[i]; 46 | } 47 | 48 | for (int i = 0; i < sizeof(x_i16); i++) { 49 | putchar_raw(x_i8[i]); 50 | } 51 | } 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /examples/serial/requirements.txt: -------------------------------------------------------------------------------- 1 | pyserial 2 | -------------------------------------------------------------------------------- /examples/serial/serial_denoise.py: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | # 5 | 6 | import sys 7 | 8 | import serial 9 | 10 | port = sys.argv[1] 11 | input_file = sys.argv[2] 12 | output_file = sys.argv[3] 13 | 14 | with serial.Serial(port, 115200, timeout=1) as ser: 15 | with open(input_file, 'rb') as input: 16 | with open(output_file, 'wb') as output: 17 | while True: 18 | in_ = input.read(480 * 2) 19 | if len(in_) == 0: 20 | break 21 | 22 | ser.write(in_) 23 | out = ser.read(480 * 2) 24 | output.write(out) 25 | 26 | print('.', end='') 27 | 28 | print(' done!') 29 | -------------------------------------------------------------------------------- /examples/usb_pdm_microphone/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13...3.27) 2 | 3 | add_executable(rnnoise_usb_pdm_microphone 4 | main.c 5 | ${CMAKE_CURRENT_LIST_DIR}/../../lib/microphone-library-for-pico/examples/usb_microphone/usb_descriptors.c 6 | ${CMAKE_CURRENT_LIST_DIR}/../../lib/microphone-library-for-pico/examples/usb_microphone/usb_microphone.c 7 | ) 8 | 9 | target_include_directories(rnnoise_usb_pdm_microphone PRIVATE 10 | ${CMAKE_CURRENT_LIST_DIR} 11 | ${CMAKE_CURRENT_LIST_DIR}/../../lib/microphone-library-for-pico/examples/usb_microphone 12 | ) 13 | 14 | target_link_libraries(rnnoise_usb_pdm_microphone PRIVATE 15 | hardware_pwm 16 | pico_stdlib 17 | pico_multicore 18 | tinyusb_device 19 | tinyusb_board 20 | pico_pdm_microphone 21 | rnnoise 22 | ) 23 | 24 | add_subdirectory( 25 | ${CMAKE_CURRENT_LIST_DIR}/../../lib/microphone-library-for-pico 26 | microphone-library-for-pico 27 | EXCLUDE_FROM_ALL 28 | ) 29 | 30 | pico_enable_stdio_usb(rnnoise_usb_pdm_microphone 0) 31 | pico_enable_stdio_uart(rnnoise_usb_pdm_microphone 1) 32 | 33 | pico_add_extra_outputs(rnnoise_usb_pdm_microphone) 34 | -------------------------------------------------------------------------------- /examples/usb_pdm_microphone/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | // 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "pico/pdm_microphone.h" 12 | 13 | #include "usb_microphone.h" 14 | 15 | #include "rnnoise.h" 16 | 17 | const int noise_suppression_enabled_pin = 18; 18 | 19 | // configuration 20 | const struct pdm_microphone_config pdm_config = { 21 | .gpio_data = 21, 22 | .gpio_clk = 20, 23 | .pio = pio0, 24 | .pio_sm = 0, 25 | .sample_rate = SAMPLE_RATE, 26 | .sample_buffer_size = 480, 27 | }; 28 | 29 | // variables 30 | int16_t denoise_buffer[480]; 31 | volatile bool new_samples = false; 32 | 33 | uint16_t sample_buffer[480 * 2]; 34 | 35 | 36 | volatile bool reset_indexes = false; 37 | int in_index = 0; 38 | int out_index = 0; 39 | absolute_time_t last_tx = 0; 40 | 41 | // callback functions 42 | void on_pdm_samples_ready(); 43 | void on_usb_microphone_tx_ready(); 44 | 45 | uint32_t core1_stack[0xc000 / sizeof(uint32_t)]; 46 | void core1_entry(); 47 | 48 | 49 | int main(void) 50 | { 51 | stdio_init_all(); 52 | 53 | // initialized GPIO pin for switch 54 | gpio_init(noise_suppression_enabled_pin); 55 | gpio_pull_up(noise_suppression_enabled_pin); 56 | gpio_set_dir(noise_suppression_enabled_pin, GPIO_IN); 57 | 58 | // initialize the USB microphone interface 59 | usb_microphone_init(); 60 | usb_microphone_set_tx_ready_handler(on_usb_microphone_tx_ready); 61 | 62 | multicore_launch_core1_with_stack(core1_entry, core1_stack, sizeof(core1_stack)); 63 | 64 | while (1) { 65 | // run the USB microphone task continuously 66 | usb_microphone_task(); 67 | } 68 | 69 | return 0; 70 | } 71 | 72 | void core1_entry() 73 | { 74 | gpio_set_function(PICO_DEFAULT_LED_PIN, GPIO_FUNC_PWM); 75 | uint slice_num = pwm_gpio_to_slice_num(PICO_DEFAULT_LED_PIN); 76 | pwm_config pwn_cfg = pwm_get_default_config(); 77 | pwm_config_set_clkdiv(&pwn_cfg, 4.0f); 78 | pwm_init(slice_num, &pwn_cfg, true); 79 | 80 | float x_f32[480]; 81 | DenoiseState* st = rnnoise_create(NULL); 82 | 83 | // run once to init 84 | memset(x_f32, 0x00, sizeof(x_f32)); 85 | rnnoise_process_frame(st, x_f32, x_f32); 86 | 87 | // initialize and start the PDM microphone 88 | pdm_microphone_init(&pdm_config); 89 | pdm_microphone_set_samples_ready_handler(on_pdm_samples_ready); 90 | pdm_microphone_set_filter_gain(16); 91 | pdm_microphone_start(); 92 | 93 | while (1) { 94 | while(!new_samples) { 95 | tight_loop_contents(); 96 | } 97 | 98 | new_samples = false; 99 | 100 | if (reset_indexes) { 101 | out_index = 0; 102 | in_index = 480; 103 | reset_indexes = false; 104 | } 105 | 106 | float vad = 0.0; 107 | float* f32 = x_f32; 108 | int16_t* i16 = denoise_buffer; 109 | 110 | // copy new 16-bit samples to 32-bit floating point buffer 111 | for (int i = 0; i < 480; i++) { 112 | *f32++ = *i16++; 113 | } 114 | 115 | if (gpio_get(noise_suppression_enabled_pin)) { 116 | vad = rnnoise_process_frame(st, x_f32, x_f32); 117 | } else { 118 | // noise supression disabled 119 | } 120 | 121 | i16 = &sample_buffer[in_index]; 122 | f32 = x_f32; 123 | 124 | // copy processed 32-bit floating point buffer to 16-bit with gain 125 | for (int i = 0; i < 480; i++) { 126 | *i16++ = *f32++; 127 | } 128 | 129 | in_index = (in_index + 480) % (480 * 2); 130 | 131 | pwm_set_gpio_level(PICO_DEFAULT_LED_PIN, (vad * 0xffff)); 132 | } 133 | } 134 | 135 | void on_pdm_samples_ready() 136 | { 137 | pdm_microphone_read(denoise_buffer, 480); 138 | 139 | new_samples = true; 140 | } 141 | 142 | void on_usb_microphone_tx_ready() 143 | { 144 | absolute_time_t now = get_absolute_time(); 145 | if ((now - last_tx) > 2000) { 146 | reset_indexes = true; 147 | } 148 | last_tx = now; 149 | 150 | usb_microphone_write(&sample_buffer[out_index], 16 * 2); 151 | out_index = (out_index + 16) % (480 * 2); 152 | } 153 | -------------------------------------------------------------------------------- /lib/rnnoise/AUTHORS: -------------------------------------------------------------------------------- 1 | Jean-Marc Valin 2 | -------------------------------------------------------------------------------- /lib/rnnoise/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, Mozilla 2 | Copyright (c) 2007-2017, Jean-Marc Valin 3 | Copyright (c) 2005-2017, Xiph.Org Foundation 4 | Copyright (c) 2003-2004, Mark Borgerding 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | - Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | - Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | - Neither the name of the Xiph.Org Foundation nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION 25 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /lib/rnnoise/include/rnnoise.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2018 Gregor Richards 2 | * Copyright (c) 2017 Mozilla */ 3 | /* 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | - Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | - Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 19 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef RNNOISE_H 29 | #define RNNOISE_H 1 30 | 31 | #include 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | #ifndef RNNOISE_EXPORT 38 | # if defined(WIN32) 39 | # if defined(RNNOISE_BUILD) && defined(DLL_EXPORT) 40 | # define RNNOISE_EXPORT __declspec(dllexport) 41 | # else 42 | # define RNNOISE_EXPORT 43 | # endif 44 | # elif defined(__GNUC__) && defined(RNNOISE_BUILD) 45 | # define RNNOISE_EXPORT __attribute__ ((visibility ("default"))) 46 | # else 47 | # define RNNOISE_EXPORT 48 | # endif 49 | #endif 50 | 51 | typedef struct DenoiseState DenoiseState; 52 | typedef struct RNNModel RNNModel; 53 | 54 | /** 55 | * Return the size of DenoiseState 56 | */ 57 | RNNOISE_EXPORT int rnnoise_get_size(); 58 | 59 | /** 60 | * Return the number of samples processed by rnnoise_process_frame at a time 61 | */ 62 | RNNOISE_EXPORT int rnnoise_get_frame_size(); 63 | 64 | /** 65 | * Initializes a pre-allocated DenoiseState 66 | * 67 | * If model is NULL the default model is used. 68 | * 69 | * See: rnnoise_create() and rnnoise_model_from_file() 70 | */ 71 | RNNOISE_EXPORT int rnnoise_init(DenoiseState *st, RNNModel *model); 72 | 73 | /** 74 | * Allocate and initialize a DenoiseState 75 | * 76 | * If model is NULL the default model is used. 77 | * 78 | * The returned pointer MUST be freed with rnnoise_destroy(). 79 | */ 80 | RNNOISE_EXPORT DenoiseState *rnnoise_create(RNNModel *model); 81 | 82 | /** 83 | * Free a DenoiseState produced by rnnoise_create. 84 | * 85 | * The optional custom model must be freed by rnnoise_model_free() after. 86 | */ 87 | RNNOISE_EXPORT void rnnoise_destroy(DenoiseState *st); 88 | 89 | /** 90 | * Denoise a frame of samples 91 | * 92 | * in and out must be at least rnnoise_get_frame_size() large. 93 | */ 94 | RNNOISE_EXPORT float rnnoise_process_frame(DenoiseState *st, float *out, const float *in); 95 | 96 | /** 97 | * Load a model from a file 98 | * 99 | * It must be deallocated with rnnoise_model_free() 100 | */ 101 | RNNOISE_EXPORT RNNModel *rnnoise_model_from_file(FILE *f); 102 | 103 | /** 104 | * Free a custom model 105 | * 106 | * It must be called after all the DenoiseStates referring to it are freed. 107 | */ 108 | RNNOISE_EXPORT void rnnoise_model_free(RNNModel *model); 109 | 110 | #ifdef __cplusplus 111 | } 112 | #endif 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /lib/rnnoise/src/_kiss_fft_guts.h: -------------------------------------------------------------------------------- 1 | /*Copyright (c) 2003-2004, Mark Borgerding 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE.*/ 25 | 26 | #ifndef KISS_FFT_GUTS_H 27 | #define KISS_FFT_GUTS_H 28 | 29 | #define MIN(a,b) ((a)<(b) ? (a):(b)) 30 | #define MAX(a,b) ((a)>(b) ? (a):(b)) 31 | 32 | /* kiss_fft.h 33 | defines kiss_fft_scalar as either short or a float type 34 | and defines 35 | typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ 36 | #include "kiss_fft.h" 37 | 38 | /* 39 | Explanation of macros dealing with complex math: 40 | 41 | C_MUL(m,a,b) : m = a*b 42 | C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise 43 | C_SUB( res, a,b) : res = a - b 44 | C_SUBFROM( res , a) : res -= a 45 | C_ADDTO( res , a) : res += a 46 | * */ 47 | #ifdef FIXED_POINT 48 | #include "arch.h" 49 | 50 | 51 | #define SAMP_MAX 2147483647 52 | #define TWID_MAX 32767 53 | #define TRIG_UPSCALE 1 54 | 55 | #define SAMP_MIN -SAMP_MAX 56 | 57 | 58 | # define S_MUL(a,b) MULT16_32_Q15(b, a) 59 | 60 | # define C_MUL(m,a,b) \ 61 | do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ 62 | (m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0) 63 | 64 | # define C_MULC(m,a,b) \ 65 | do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ 66 | (m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0) 67 | 68 | # define C_MULBYSCALAR( c, s ) \ 69 | do{ (c).r = S_MUL( (c).r , s ) ;\ 70 | (c).i = S_MUL( (c).i , s ) ; }while(0) 71 | 72 | # define DIVSCALAR(x,k) \ 73 | (x) = S_MUL( x, (TWID_MAX-((k)>>1))/(k)+1 ) 74 | 75 | # define C_FIXDIV(c,div) \ 76 | do { DIVSCALAR( (c).r , div); \ 77 | DIVSCALAR( (c).i , div); }while (0) 78 | 79 | #define C_ADD( res, a,b)\ 80 | do {(res).r=ADD32_ovflw((a).r,(b).r); (res).i=ADD32_ovflw((a).i,(b).i); \ 81 | }while(0) 82 | #define C_SUB( res, a,b)\ 83 | do {(res).r=SUB32_ovflw((a).r,(b).r); (res).i=SUB32_ovflw((a).i,(b).i); \ 84 | }while(0) 85 | #define C_ADDTO( res , a)\ 86 | do {(res).r = ADD32_ovflw((res).r, (a).r); (res).i = ADD32_ovflw((res).i,(a).i);\ 87 | }while(0) 88 | 89 | #define C_SUBFROM( res , a)\ 90 | do {(res).r = ADD32_ovflw((res).r,(a).r); (res).i = SUB32_ovflw((res).i,(a).i); \ 91 | }while(0) 92 | 93 | #if defined(OPUS_ARM_INLINE_ASM) 94 | #include "arm/kiss_fft_armv4.h" 95 | #endif 96 | 97 | #if defined(OPUS_ARM_INLINE_EDSP) 98 | #include "arm/kiss_fft_armv5e.h" 99 | #endif 100 | #if defined(MIPSr1_ASM) 101 | #include "mips/kiss_fft_mipsr1.h" 102 | #endif 103 | 104 | #else /* not FIXED_POINT*/ 105 | 106 | # define S_MUL(a,b) ( (a)*(b) ) 107 | #define C_MUL(m,a,b) \ 108 | do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ 109 | (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) 110 | #define C_MULC(m,a,b) \ 111 | do{ (m).r = (a).r*(b).r + (a).i*(b).i;\ 112 | (m).i = (a).i*(b).r - (a).r*(b).i; }while(0) 113 | 114 | #define C_MUL4(m,a,b) C_MUL(m,a,b) 115 | 116 | # define C_FIXDIV(c,div) /* NOOP */ 117 | # define C_MULBYSCALAR( c, s ) \ 118 | do{ (c).r *= (s);\ 119 | (c).i *= (s); }while(0) 120 | #endif 121 | 122 | #ifndef CHECK_OVERFLOW_OP 123 | # define CHECK_OVERFLOW_OP(a,op,b) /* noop */ 124 | #endif 125 | 126 | #ifndef C_ADD 127 | #define C_ADD( res, a,b)\ 128 | do { \ 129 | CHECK_OVERFLOW_OP((a).r,+,(b).r)\ 130 | CHECK_OVERFLOW_OP((a).i,+,(b).i)\ 131 | (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ 132 | }while(0) 133 | #define C_SUB( res, a,b)\ 134 | do { \ 135 | CHECK_OVERFLOW_OP((a).r,-,(b).r)\ 136 | CHECK_OVERFLOW_OP((a).i,-,(b).i)\ 137 | (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ 138 | }while(0) 139 | #define C_ADDTO( res , a)\ 140 | do { \ 141 | CHECK_OVERFLOW_OP((res).r,+,(a).r)\ 142 | CHECK_OVERFLOW_OP((res).i,+,(a).i)\ 143 | (res).r += (a).r; (res).i += (a).i;\ 144 | }while(0) 145 | 146 | #define C_SUBFROM( res , a)\ 147 | do {\ 148 | CHECK_OVERFLOW_OP((res).r,-,(a).r)\ 149 | CHECK_OVERFLOW_OP((res).i,-,(a).i)\ 150 | (res).r -= (a).r; (res).i -= (a).i; \ 151 | }while(0) 152 | #endif /* C_ADD defined */ 153 | 154 | #ifdef FIXED_POINT 155 | /*# define KISS_FFT_COS(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase)))) 156 | # define KISS_FFT_SIN(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/ 157 | # define KISS_FFT_COS(phase) floor(.5+TWID_MAX*cos (phase)) 158 | # define KISS_FFT_SIN(phase) floor(.5+TWID_MAX*sin (phase)) 159 | # define HALF_OF(x) ((x)>>1) 160 | #elif defined(USE_SIMD) 161 | # define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) 162 | # define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) 163 | # define HALF_OF(x) ((x)*_mm_set1_ps(.5f)) 164 | #else 165 | # define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) 166 | # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) 167 | # define HALF_OF(x) ((x)*.5f) 168 | #endif 169 | 170 | #define kf_cexp(x,phase) \ 171 | do{ \ 172 | (x)->r = KISS_FFT_COS(phase);\ 173 | (x)->i = KISS_FFT_SIN(phase);\ 174 | }while(0) 175 | 176 | #define kf_cexp2(x,phase) \ 177 | do{ \ 178 | (x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\ 179 | (x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\ 180 | }while(0) 181 | 182 | #endif /* KISS_FFT_GUTS_H */ 183 | -------------------------------------------------------------------------------- /lib/rnnoise/src/arch.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2003-2008 Jean-Marc Valin 2 | Copyright (c) 2007-2008 CSIRO 3 | Copyright (c) 2007-2009 Xiph.Org Foundation 4 | Written by Jean-Marc Valin */ 5 | /** 6 | @file arch.h 7 | @brief Various architecture definitions for CELT 8 | */ 9 | /* 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions 12 | are met: 13 | 14 | - Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | 17 | - Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 25 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef ARCH_H 35 | #define ARCH_H 36 | 37 | #include "opus_types.h" 38 | #include "common.h" 39 | 40 | # if !defined(__GNUC_PREREQ) 41 | # if defined(__GNUC__)&&defined(__GNUC_MINOR__) 42 | # define __GNUC_PREREQ(_maj,_min) \ 43 | ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) 44 | # else 45 | # define __GNUC_PREREQ(_maj,_min) 0 46 | # endif 47 | # endif 48 | 49 | #define CELT_SIG_SCALE 32768.f 50 | 51 | #define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__); 52 | #ifdef ENABLE_ASSERTIONS 53 | #include 54 | #include 55 | #ifdef __GNUC__ 56 | __attribute__((noreturn)) 57 | #endif 58 | static OPUS_INLINE void _celt_fatal(const char *str, const char *file, int line) 59 | { 60 | fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str); 61 | abort(); 62 | } 63 | #define celt_assert(cond) {if (!(cond)) {celt_fatal("assertion failed: " #cond);}} 64 | #define celt_assert2(cond, message) {if (!(cond)) {celt_fatal("assertion failed: " #cond "\n" message);}} 65 | #else 66 | #define celt_assert(cond) 67 | #define celt_assert2(cond, message) 68 | #endif 69 | 70 | #define IMUL32(a,b) ((a)*(b)) 71 | 72 | #define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 16-bit value. */ 73 | #define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ 74 | #define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 32-bit value. */ 75 | #define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */ 76 | #define IMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum int value. */ 77 | #define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */ 78 | #define UADD32(a,b) ((a)+(b)) 79 | #define USUB32(a,b) ((a)-(b)) 80 | 81 | /* Set this if opus_int64 is a native type of the CPU. */ 82 | /* Assume that all LP64 architectures have fast 64-bit types; also x86_64 83 | (which can be ILP32 for x32) and Win64 (which is LLP64). */ 84 | #if defined(__x86_64__) || defined(__LP64__) || defined(_WIN64) 85 | #define OPUS_FAST_INT64 1 86 | #else 87 | #define OPUS_FAST_INT64 0 88 | #endif 89 | 90 | #define PRINT_MIPS(file) 91 | 92 | #ifdef FIXED_POINT 93 | 94 | typedef opus_int16 opus_val16; 95 | typedef opus_int32 opus_val32; 96 | typedef opus_int64 opus_val64; 97 | 98 | typedef opus_val32 celt_sig; 99 | typedef opus_val16 celt_norm; 100 | typedef opus_val32 celt_ener; 101 | 102 | #define Q15ONE 32767 103 | 104 | #define SIG_SHIFT 12 105 | /* Safe saturation value for 32-bit signals. Should be less than 106 | 2^31*(1-0.85) to avoid blowing up on DC at deemphasis.*/ 107 | #define SIG_SAT (300000000) 108 | 109 | #define NORM_SCALING 16384 110 | 111 | #define DB_SHIFT 10 112 | 113 | #define EPSILON 1 114 | #define VERY_SMALL 0 115 | #define VERY_LARGE16 ((opus_val16)32767) 116 | #define Q15_ONE ((opus_val16)32767) 117 | 118 | #define SCALEIN(a) (a) 119 | #define SCALEOUT(a) (a) 120 | 121 | #define ABS16(x) ((x) < 0 ? (-(x)) : (x)) 122 | #define ABS32(x) ((x) < 0 ? (-(x)) : (x)) 123 | 124 | static OPUS_INLINE opus_int16 SAT16(opus_int32 x) { 125 | return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x; 126 | } 127 | 128 | #ifdef FIXED_DEBUG 129 | #include "fixed_debug.h" 130 | #else 131 | 132 | #include "fixed_generic.h" 133 | 134 | #ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR 135 | #include "arm/fixed_arm64.h" 136 | #elif OPUS_ARM_INLINE_EDSP 137 | #include "arm/fixed_armv5e.h" 138 | #elif defined (OPUS_ARM_INLINE_ASM) 139 | #include "arm/fixed_armv4.h" 140 | #elif defined (BFIN_ASM) 141 | #include "fixed_bfin.h" 142 | #elif defined (TI_C5X_ASM) 143 | #include "fixed_c5x.h" 144 | #elif defined (TI_C6X_ASM) 145 | #include "fixed_c6x.h" 146 | #endif 147 | 148 | #endif 149 | 150 | #else /* FIXED_POINT */ 151 | 152 | typedef float opus_val16; 153 | typedef float opus_val32; 154 | typedef float opus_val64; 155 | 156 | typedef float celt_sig; 157 | typedef float celt_norm; 158 | typedef float celt_ener; 159 | 160 | #ifdef FLOAT_APPROX 161 | /* This code should reliably detect NaN/inf even when -ffast-math is used. 162 | Assumes IEEE 754 format. */ 163 | static OPUS_INLINE int celt_isnan(float x) 164 | { 165 | union {float f; opus_uint32 i;} in; 166 | in.f = x; 167 | return ((in.i>>23)&0xFF)==0xFF && (in.i&0x007FFFFF)!=0; 168 | } 169 | #else 170 | #ifdef __FAST_MATH__ 171 | #error Cannot build libopus with -ffast-math unless FLOAT_APPROX is defined. This could result in crashes on extreme (e.g. NaN) input 172 | #endif 173 | #define celt_isnan(x) ((x)!=(x)) 174 | #endif 175 | 176 | #define Q15ONE 1.0f 177 | 178 | #define NORM_SCALING 1.f 179 | 180 | #define EPSILON 1e-15f 181 | #define VERY_SMALL 1e-30f 182 | #define VERY_LARGE16 1e15f 183 | #define Q15_ONE ((opus_val16)1.f) 184 | 185 | /* This appears to be the same speed as C99's fabsf() but it's more portable. */ 186 | #define ABS16(x) ((float)fabs(x)) 187 | #define ABS32(x) ((float)fabs(x)) 188 | 189 | #define QCONST16(x,bits) (x) 190 | #define QCONST32(x,bits) (x) 191 | 192 | #define NEG16(x) (-(x)) 193 | #define NEG32(x) (-(x)) 194 | #define NEG32_ovflw(x) (-(x)) 195 | #define EXTRACT16(x) (x) 196 | #define EXTEND32(x) (x) 197 | #define SHR16(a,shift) (a) 198 | #define SHL16(a,shift) (a) 199 | #define SHR32(a,shift) (a) 200 | #define SHL32(a,shift) (a) 201 | #define PSHR32(a,shift) (a) 202 | #define VSHR32(a,shift) (a) 203 | 204 | #define PSHR(a,shift) (a) 205 | #define SHR(a,shift) (a) 206 | #define SHL(a,shift) (a) 207 | #define SATURATE(x,a) (x) 208 | #define SATURATE16(x) (x) 209 | 210 | #define ROUND16(a,shift) (a) 211 | #define SROUND16(a,shift) (a) 212 | #define HALF16(x) (.5f*(x)) 213 | #define HALF32(x) (.5f*(x)) 214 | 215 | #define ADD16(a,b) ((a)+(b)) 216 | #define SUB16(a,b) ((a)-(b)) 217 | #define ADD32(a,b) ((a)+(b)) 218 | #define SUB32(a,b) ((a)-(b)) 219 | #define ADD32_ovflw(a,b) ((a)+(b)) 220 | #define SUB32_ovflw(a,b) ((a)-(b)) 221 | #define MULT16_16_16(a,b) ((a)*(b)) 222 | #define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(b)) 223 | #define MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b)) 224 | 225 | #define MULT16_32_Q15(a,b) ((a)*(b)) 226 | #define MULT16_32_Q16(a,b) ((a)*(b)) 227 | 228 | #define MULT32_32_Q31(a,b) ((a)*(b)) 229 | 230 | #define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) 231 | #define MAC16_32_Q16(c,a,b) ((c)+(a)*(b)) 232 | 233 | #define MULT16_16_Q11_32(a,b) ((a)*(b)) 234 | #define MULT16_16_Q11(a,b) ((a)*(b)) 235 | #define MULT16_16_Q13(a,b) ((a)*(b)) 236 | #define MULT16_16_Q14(a,b) ((a)*(b)) 237 | #define MULT16_16_Q15(a,b) ((a)*(b)) 238 | #define MULT16_16_P15(a,b) ((a)*(b)) 239 | #define MULT16_16_P13(a,b) ((a)*(b)) 240 | #define MULT16_16_P14(a,b) ((a)*(b)) 241 | #define MULT16_32_P16(a,b) ((a)*(b)) 242 | 243 | #define DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b)) 244 | #define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b)) 245 | 246 | #define SCALEIN(a) ((a)*CELT_SIG_SCALE) 247 | #define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE)) 248 | 249 | #define SIG2WORD16(x) (x) 250 | 251 | #endif /* !FIXED_POINT */ 252 | 253 | #ifndef GLOBAL_STACK_SIZE 254 | #ifdef FIXED_POINT 255 | #define GLOBAL_STACK_SIZE 120000 256 | #else 257 | #define GLOBAL_STACK_SIZE 120000 258 | #endif 259 | #endif 260 | 261 | #endif /* ARCH_H */ 262 | -------------------------------------------------------------------------------- /lib/rnnoise/src/celt_lpc.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009-2010 Xiph.Org Foundation 2 | Written by Jean-Marc Valin */ 3 | /* 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | - Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | - Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 19 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifdef HAVE_CONFIG_H 29 | #include "config.h" 30 | #endif 31 | 32 | #include "celt_lpc.h" 33 | #include "arch.h" 34 | #include "common.h" 35 | #include "pitch.h" 36 | 37 | void rnn_lpc( 38 | opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */ 39 | const opus_val32 *ac, /* in: [0...p] autocorrelation values */ 40 | int p 41 | ) 42 | { 43 | int i, j; 44 | opus_val32 r; 45 | opus_val32 error = ac[0]; 46 | #ifdef FIXED_POINT 47 | opus_val32 lpc[LPC_ORDER]; 48 | #else 49 | float *lpc = _lpc; 50 | #endif 51 | 52 | RNN_CLEAR(lpc, p); 53 | if (ac[0] != 0) 54 | { 55 | for (i = 0; i < p; i++) { 56 | /* Sum up this iteration's reflection coefficient */ 57 | opus_val32 rr = 0; 58 | for (j = 0; j < i; j++) 59 | rr += MULT32_32_Q31(lpc[j],ac[i - j]); 60 | rr += SHR32(ac[i + 1],3); 61 | r = -SHL32(rr,3)/error; 62 | /* Update LPC coefficients and total error */ 63 | lpc[i] = SHR32(r,3); 64 | for (j = 0; j < (i+1)>>1; j++) 65 | { 66 | opus_val32 tmp1, tmp2; 67 | tmp1 = lpc[j]; 68 | tmp2 = lpc[i-1-j]; 69 | lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2); 70 | lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1); 71 | } 72 | 73 | error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error); 74 | /* Bail out once we get 30 dB gain */ 75 | #ifdef FIXED_POINT 76 | if (error0); 106 | celt_assert(overlap>=0); 107 | if (overlap == 0) 108 | { 109 | xptr = x; 110 | } else { 111 | for (i=0;i0) 135 | { 136 | for(i=0;i= 536870912) 161 | { 162 | int shift2=1; 163 | if (ac[0] >= 1073741824) 164 | shift2++; 165 | for (i=0;i<=lag;i++) 166 | ac[i] = SHR32(ac[i], shift2); 167 | shift += shift2; 168 | } 169 | #endif 170 | 171 | return shift; 172 | } 173 | -------------------------------------------------------------------------------- /lib/rnnoise/src/celt_lpc.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009-2010 Xiph.Org Foundation 2 | Written by Jean-Marc Valin */ 3 | /* 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | - Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | - Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 19 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef PLC_H 29 | #define PLC_H 30 | 31 | #include "arch.h" 32 | #include "common.h" 33 | 34 | #if defined(OPUS_X86_MAY_HAVE_SSE4_1) 35 | #include "x86/celt_lpc_sse.h" 36 | #endif 37 | 38 | #define LPC_ORDER 24 39 | 40 | void rnn_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p); 41 | 42 | int rnn_autocorr(const opus_val16 *x, opus_val32 *ac, 43 | const opus_val16 *window, int overlap, int lag, int n); 44 | 45 | #endif /* PLC_H */ 46 | -------------------------------------------------------------------------------- /lib/rnnoise/src/common.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef COMMON_H 4 | #define COMMON_H 5 | 6 | #include "stdlib.h" 7 | #include "string.h" 8 | 9 | #define RNN_INLINE inline 10 | #define OPUS_INLINE inline 11 | 12 | 13 | /** RNNoise wrapper for malloc(). To do your own dynamic allocation, all you need t 14 | o do is replace this function and rnnoise_free */ 15 | #ifndef OVERRIDE_RNNOISE_ALLOC 16 | static RNN_INLINE void *rnnoise_alloc (size_t size) 17 | { 18 | return malloc(size); 19 | } 20 | #endif 21 | 22 | /** RNNoise wrapper for free(). To do your own dynamic allocation, all you need to do is replace this function and rnnoise_alloc */ 23 | #ifndef OVERRIDE_RNNOISE_FREE 24 | static RNN_INLINE void rnnoise_free (void *ptr) 25 | { 26 | free(ptr); 27 | } 28 | #endif 29 | 30 | /** Copy n elements from src to dst. The 0* term provides compile-time type checking */ 31 | #ifndef OVERRIDE_RNN_COPY 32 | #define RNN_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) 33 | #endif 34 | 35 | /** Copy n elements from src to dst, allowing overlapping regions. The 0* term 36 | provides compile-time type checking */ 37 | #ifndef OVERRIDE_RNN_MOVE 38 | #define RNN_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) 39 | #endif 40 | 41 | /** Set n elements of dst to zero */ 42 | #ifndef OVERRIDE_RNN_CLEAR 43 | #define RNN_CLEAR(dst, n) (memset((dst), 0, (n)*sizeof(*(dst)))) 44 | #endif 45 | 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /lib/rnnoise/src/denoise.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2018 Gregor Richards 2 | * Copyright (c) 2017 Mozilla */ 3 | /* 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | - Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | - Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 19 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifdef HAVE_CONFIG_H 29 | #include "config.h" 30 | #endif 31 | 32 | #include 33 | #include 34 | #include 35 | #include "kiss_fft.h" 36 | #include "common.h" 37 | #include 38 | #include "rnnoise.h" 39 | #include "pitch.h" 40 | #include "arch.h" 41 | #include "rnn.h" 42 | #include "rnn_data.h" 43 | 44 | #ifdef __arm__ 45 | // force using floating point in biquad, and for log10 and sqrt 46 | #define double float 47 | #define log10 log10f 48 | #define sqrt sqrtf 49 | #endif 50 | 51 | #define FRAME_SIZE_SHIFT 2 52 | #define FRAME_SIZE (120<rnn.model = model; 280 | else 281 | st->rnn.model = &rnnoise_model_orig; 282 | st->rnn.vad_gru_state = calloc(sizeof(float), st->rnn.model->vad_gru_size); 283 | st->rnn.noise_gru_state = calloc(sizeof(float), st->rnn.model->noise_gru_size); 284 | st->rnn.denoise_gru_state = calloc(sizeof(float), st->rnn.model->denoise_gru_size); 285 | return 0; 286 | } 287 | 288 | DenoiseState *rnnoise_create(RNNModel *model) { 289 | DenoiseState *st; 290 | st = malloc(rnnoise_get_size()); 291 | rnnoise_init(st, model); 292 | return st; 293 | } 294 | 295 | void rnnoise_destroy(DenoiseState *st) { 296 | free(st->rnn.vad_gru_state); 297 | free(st->rnn.noise_gru_state); 298 | free(st->rnn.denoise_gru_state); 299 | free(st); 300 | } 301 | 302 | #if TRAINING 303 | int lowpass = FREQ_SIZE; 304 | int band_lp = NB_BANDS; 305 | #endif 306 | 307 | static void frame_analysis(DenoiseState *st, kiss_fft_cpx *X, float *Ex, const float *in) { 308 | int i; 309 | float x[WINDOW_SIZE]; 310 | RNN_COPY(x, st->analysis_mem, FRAME_SIZE); 311 | for (i=0;ianalysis_mem, in, FRAME_SIZE); 313 | apply_window(x); 314 | forward_transform(X, x); 315 | #if TRAINING 316 | for (i=lowpass;i>1]; 331 | int pitch_index; 332 | float gain; 333 | float *(pre[1]); 334 | float tmp[NB_BANDS]; 335 | float follow, logMax; 336 | frame_analysis(st, X, Ex, in); 337 | RNN_MOVE(st->pitch_buf, &st->pitch_buf[FRAME_SIZE], PITCH_BUF_SIZE-FRAME_SIZE); 338 | RNN_COPY(&st->pitch_buf[PITCH_BUF_SIZE-FRAME_SIZE], in, FRAME_SIZE); 339 | pre[0] = &st->pitch_buf[0]; 340 | rnn_pitch_downsample(pre, pitch_buf, PITCH_BUF_SIZE, 1); 341 | rnn_pitch_search(pitch_buf+(PITCH_MAX_PERIOD>>1), pitch_buf, PITCH_FRAME_SIZE, 342 | PITCH_MAX_PERIOD-3*PITCH_MIN_PERIOD, &pitch_index); 343 | pitch_index = PITCH_MAX_PERIOD-pitch_index; 344 | 345 | gain = rnn_remove_doubling(pitch_buf, PITCH_MAX_PERIOD, PITCH_MIN_PERIOD, 346 | PITCH_FRAME_SIZE, &pitch_index, st->last_period, st->last_gain); 347 | st->last_period = pitch_index; 348 | st->last_gain = gain; 349 | for (i=0;ipitch_buf[PITCH_BUF_SIZE-WINDOW_SIZE-pitch_index+i]; 351 | apply_window(p); 352 | forward_transform(P, p); 353 | compute_band_energy(Ep, P); 354 | compute_band_corr(Exp, X, P); 355 | for (i=0;icepstral_mem[st->memid]; 379 | ceps_1 = (st->memid < 1) ? st->cepstral_mem[CEPS_MEM+st->memid-1] : st->cepstral_mem[st->memid-1]; 380 | ceps_2 = (st->memid < 2) ? st->cepstral_mem[CEPS_MEM+st->memid-2] : st->cepstral_mem[st->memid-2]; 381 | for (i=0;imemid++; 383 | for (i=0;imemid == CEPS_MEM) st->memid = 0; 390 | for (i=0;icepstral_mem[i][k] - st->cepstral_mem[j][k]; 402 | dist += tmp*tmp; 403 | } 404 | if (j!=i) 405 | mindist = MIN32(mindist, dist); 406 | } 407 | spec_variability += mindist; 408 | } 409 | features[NB_BANDS+3*NB_DELTA_CEPS+1] = spec_variability/CEPS_MEM-2.1; 410 | return TRAINING && E < 0.1; 411 | } 412 | 413 | static void frame_synthesis(DenoiseState *st, float *out, const kiss_fft_cpx *y) { 414 | float x[WINDOW_SIZE]; 415 | int i; 416 | inverse_transform(x, y); 417 | apply_window(x); 418 | for (i=0;isynthesis_mem[i]; 419 | RNN_COPY(st->synthesis_mem, &x[FRAME_SIZE], FRAME_SIZE); 420 | } 421 | 422 | static void biquad(float *y, float mem[2], const float *x, const float *b, const float *a, int N) { 423 | int i; 424 | for (i=0;ig[i]) r[i] = 1; 442 | else r[i] = Exp[i]*(1-g[i])/(.001 + g[i]*(1-Exp[i])); 443 | r[i] = MIN16(1, MAX16(0, r[i])); 444 | #else 445 | if (Exp[i]>g[i]) r[i] = 1; 446 | else r[i] = SQUARE(Exp[i])*(1-SQUARE(g[i]))/(.001 + SQUARE(g[i])*(1-SQUARE(Exp[i]))); 447 | r[i] = sqrt(MIN16(1, MAX16(0, r[i]))); 448 | #endif 449 | r[i] *= sqrt(Ex[i]/(1e-8+Ep[i])); 450 | } 451 | interp_band_gain(rf, r); 452 | for (i=0;imem_hp_x, in, b_hp, a_hp, FRAME_SIZE); 485 | silence = compute_frame_features(st, X, P, Ex, Ep, Exp, features, x); 486 | 487 | if (!silence) { 488 | compute_rnn(&st->rnn, g, &vad_prob, features); 489 | pitch_filter(X, P, Ex, Ep, Exp, g); 490 | for (i=0;ilastg[i]); 493 | st->lastg[i] = g[i]; 494 | } 495 | interp_band_gain(gf, g); 496 | #if 1 497 | for (i=0;i \n", argv[0]); 550 | return 1; 551 | } 552 | f1 = fopen(argv[1], "r"); 553 | f2 = fopen(argv[2], "r"); 554 | maxCount = atoi(argv[3]); 555 | for(i=0;i<150;i++) { 556 | short tmp[FRAME_SIZE]; 557 | fread(tmp, sizeof(short), FRAME_SIZE, f2); 558 | } 559 | while (1) { 560 | kiss_fft_cpx X[FREQ_SIZE], Y[FREQ_SIZE], N[FREQ_SIZE], P[WINDOW_SIZE]; 561 | float Ex[NB_BANDS], Ey[NB_BANDS], En[NB_BANDS], Ep[NB_BANDS]; 562 | float Exp[NB_BANDS]; 563 | float Ln[NB_BANDS]; 564 | float features[NB_FEATURES]; 565 | float g[NB_BANDS]; 566 | short tmp[FRAME_SIZE]; 567 | float vad=0; 568 | float E=0; 569 | if (count==maxCount) break; 570 | if ((count%1000)==0) fprintf(stderr, "%d\r", count); 571 | if (++gain_change_count > 2821) { 572 | speech_gain = pow(10., (-40+(rand()%60))/20.); 573 | noise_gain = pow(10., (-30+(rand()%50))/20.); 574 | if (rand()%10==0) noise_gain = 0; 575 | noise_gain *= speech_gain; 576 | if (rand()%10==0) speech_gain = 0; 577 | gain_change_count = 0; 578 | rand_resp(a_noise, b_noise); 579 | rand_resp(a_sig, b_sig); 580 | lowpass = FREQ_SIZE * 3000./24000. * pow(50., rand()/(double)RAND_MAX); 581 | for (i=0;i lowpass) { 583 | band_lp = i; 584 | break; 585 | } 586 | } 587 | } 588 | if (speech_gain != 0) { 589 | fread(tmp, sizeof(short), FRAME_SIZE, f1); 590 | if (feof(f1)) { 591 | rewind(f1); 592 | fread(tmp, sizeof(short), FRAME_SIZE, f1); 593 | } 594 | for (i=0;i 1e9f) { 616 | vad_cnt=0; 617 | } else if (E > 1e8f) { 618 | vad_cnt -= 5; 619 | } else if (E > 1e7f) { 620 | vad_cnt++; 621 | } else { 622 | vad_cnt+=2; 623 | } 624 | if (vad_cnt < 0) vad_cnt = 0; 625 | if (vad_cnt > 15) vad_cnt = 15; 626 | 627 | if (vad_cnt >= 10) vad = 0; 628 | else if (vad_cnt > 0) vad = 0.5f; 629 | else vad = 1.f; 630 | 631 | frame_analysis(st, Y, Ey, x); 632 | frame_analysis(noise_state, N, En, n); 633 | for (i=0;ilast_gain, noisy->last_period); 637 | for (i=0;i 1) g[i] = 1; 640 | if (silence || i > band_lp) g[i] = -1; 641 | if (Ey[i] < 5e-2 && Ex[i] < 5e-2) g[i] = -1; 642 | if (vad==0 && noise_gain==0) g[i] = -1; 643 | } 644 | count++; 645 | #if 1 646 | fwrite(features, sizeof(float), NB_FEATURES, stdout); 647 | fwrite(g, sizeof(float), NB_BANDS, stdout); 648 | fwrite(Ln, sizeof(float), NB_BANDS, stdout); 649 | fwrite(&vad, sizeof(float), 1, stdout); 650 | #endif 651 | } 652 | fprintf(stderr, "matrix size: %d x %d\n", count, NB_FEATURES + 2*NB_BANDS + 1); 653 | fclose(f1); 654 | fclose(f2); 655 | return 0; 656 | } 657 | 658 | #endif 659 | -------------------------------------------------------------------------------- /lib/rnnoise/src/kiss_fft.c: -------------------------------------------------------------------------------- 1 | /*Copyright (c) 2003-2004, Mark Borgerding 2 | Lots of modifications by Jean-Marc Valin 3 | Copyright (c) 2005-2007, Xiph.Org Foundation 4 | Copyright (c) 2008, Xiph.Org Foundation, CSIRO 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE.*/ 28 | 29 | /* This code is originally from Mark Borgerding's KISS-FFT but has been 30 | heavily modified to better suit Opus */ 31 | 32 | #ifndef SKIP_CONFIG_H 33 | # ifdef HAVE_CONFIG_H 34 | # include "config.h" 35 | # endif 36 | #endif 37 | 38 | #include "_kiss_fft_guts.h" 39 | #define CUSTOM_MODES 40 | 41 | /* The guts header contains all the multiplication and addition macros that are defined for 42 | complex numbers. It also declares the kf_ internal functions. 43 | */ 44 | 45 | static void kf_bfly2( 46 | kiss_fft_cpx * Fout, 47 | int m, 48 | int N 49 | ) 50 | { 51 | kiss_fft_cpx * Fout2; 52 | int i; 53 | (void)m; 54 | #ifdef CUSTOM_MODES 55 | if (m==1) 56 | { 57 | celt_assert(m==1); 58 | for (i=0;itwiddles; 143 | /* m is guaranteed to be a multiple of 4. */ 144 | for (j=0;jtwiddles[fstride*m]; 195 | #endif 196 | for (i=0;itwiddles; 200 | /* For non-custom modes, m is guaranteed to be a multiple of 4. */ 201 | k=m; 202 | do { 203 | 204 | C_MUL(scratch[1],Fout[m] , *tw1); 205 | C_MUL(scratch[2],Fout[m2] , *tw2); 206 | 207 | C_ADD(scratch[3],scratch[1],scratch[2]); 208 | C_SUB(scratch[0],scratch[1],scratch[2]); 209 | tw1 += fstride; 210 | tw2 += fstride*2; 211 | 212 | Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r)); 213 | Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i)); 214 | 215 | C_MULBYSCALAR( scratch[0] , epi3.i ); 216 | 217 | C_ADDTO(*Fout,scratch[3]); 218 | 219 | Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i); 220 | Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r); 221 | 222 | Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i); 223 | Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r); 224 | 225 | ++Fout; 226 | } while(--k); 227 | } 228 | } 229 | 230 | 231 | #ifndef OVERRIDE_kf_bfly5 232 | static void kf_bfly5( 233 | kiss_fft_cpx * Fout, 234 | const size_t fstride, 235 | const kiss_fft_state *st, 236 | int m, 237 | int N, 238 | int mm 239 | ) 240 | { 241 | kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; 242 | int i, u; 243 | kiss_fft_cpx scratch[13]; 244 | const kiss_twiddle_cpx *tw; 245 | kiss_twiddle_cpx ya,yb; 246 | kiss_fft_cpx * Fout_beg = Fout; 247 | 248 | #ifdef FIXED_POINT 249 | ya.r = 10126; 250 | ya.i = -31164; 251 | yb.r = -26510; 252 | yb.i = -19261; 253 | #else 254 | ya = st->twiddles[fstride*m]; 255 | yb = st->twiddles[fstride*2*m]; 256 | #endif 257 | tw=st->twiddles; 258 | 259 | for (i=0;ir = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r)); 283 | Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i)); 284 | 285 | scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r))); 286 | scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r))); 287 | 288 | scratch[6].r = ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i)); 289 | scratch[6].i = NEG32_ovflw(ADD32_ovflw(S_MUL(scratch[10].r,ya.i), S_MUL(scratch[9].r,yb.i))); 290 | 291 | C_SUB(*Fout1,scratch[5],scratch[6]); 292 | C_ADD(*Fout4,scratch[5],scratch[6]); 293 | 294 | scratch[11].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r))); 295 | scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r))); 296 | scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i)); 297 | scratch[12].i = SUB32_ovflw(S_MUL(scratch[10].r,yb.i), S_MUL(scratch[9].r,ya.i)); 298 | 299 | C_ADD(*Fout2,scratch[11],scratch[12]); 300 | C_SUB(*Fout3,scratch[11],scratch[12]); 301 | 302 | ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; 303 | } 304 | } 305 | } 306 | #endif /* OVERRIDE_kf_bfly5 */ 307 | 308 | 309 | #endif 310 | 311 | 312 | #ifdef CUSTOM_MODES 313 | 314 | static 315 | void compute_bitrev_table( 316 | int Fout, 317 | opus_int16 *f, 318 | const size_t fstride, 319 | int in_stride, 320 | opus_int16 * factors, 321 | const kiss_fft_state *st 322 | ) 323 | { 324 | const int p=*factors++; /* the radix */ 325 | const int m=*factors++; /* stage's fft length/p */ 326 | 327 | /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/ 328 | if (m==1) 329 | { 330 | int j; 331 | for (j=0;j32000 || (opus_int32)p*(opus_int32)p > n) 368 | p = n; /* no more factors, skip to end */ 369 | } 370 | n /= p; 371 | #ifdef RADIX_TWO_ONLY 372 | if (p!=2 && p != 4) 373 | #else 374 | if (p>5) 375 | #endif 376 | { 377 | return 0; 378 | } 379 | facbuf[2*stages] = p; 380 | if (p==2 && stages > 1) 381 | { 382 | facbuf[2*stages] = 4; 383 | facbuf[2] = 2; 384 | } 385 | stages++; 386 | } while (n > 1); 387 | n = nbak; 388 | /* Reverse the order to get the radix 4 at the end, so we can use the 389 | fast degenerate case. It turns out that reversing the order also 390 | improves the noise behaviour. */ 391 | for (i=0;i= memneeded) 444 | st = (kiss_fft_state*)mem; 445 | *lenmem = memneeded; 446 | } 447 | if (st) { 448 | opus_int16 *bitrev; 449 | kiss_twiddle_cpx *twiddles; 450 | 451 | st->nfft=nfft; 452 | #ifdef FIXED_POINT 453 | st->scale_shift = celt_ilog2(st->nfft); 454 | if (st->nfft == 1<scale_shift) 455 | st->scale = Q15ONE; 456 | else 457 | st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift); 458 | #else 459 | st->scale = 1.f/nfft; 460 | #endif 461 | if (base != NULL) 462 | { 463 | st->twiddles = base->twiddles; 464 | st->shift = 0; 465 | while (st->shift < 32 && nfft<shift != base->nfft) 466 | st->shift++; 467 | if (st->shift>=32) 468 | goto fail; 469 | } else { 470 | st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft); 471 | compute_twiddles(twiddles, nfft); 472 | st->shift = -1; 473 | } 474 | if (!kf_factor(nfft,st->factors)) 475 | { 476 | goto fail; 477 | } 478 | 479 | /* bitrev */ 480 | st->bitrev = bitrev = (opus_int16*)KISS_FFT_MALLOC(sizeof(opus_int16)*nfft); 481 | if (st->bitrev==NULL) 482 | goto fail; 483 | compute_bitrev_table(0, bitrev, 1,1, st->factors,st); 484 | 485 | /* Initialize architecture specific fft parameters */ 486 | if (rnn_fft_alloc_arch(st, arch)) 487 | goto fail; 488 | } 489 | return st; 490 | fail: 491 | rnn_fft_free(st, arch); 492 | return NULL; 493 | } 494 | 495 | kiss_fft_state *rnn_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch) 496 | { 497 | return rnn_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch); 498 | } 499 | 500 | void rnn_fft_free_arch_c(kiss_fft_state *st) { 501 | (void)st; 502 | } 503 | 504 | void rnn_fft_free(const kiss_fft_state *cfg, int arch) 505 | { 506 | if (cfg) 507 | { 508 | rnn_fft_free_arch((kiss_fft_state *)cfg, arch); 509 | opus_free((opus_int16*)cfg->bitrev); 510 | if (cfg->shift < 0) 511 | opus_free((kiss_twiddle_cpx*)cfg->twiddles); 512 | opus_free((kiss_fft_state*)cfg); 513 | } 514 | } 515 | 516 | #endif /* CUSTOM_MODES */ 517 | 518 | void rnn_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout) 519 | { 520 | int m2, m; 521 | int p; 522 | int L; 523 | int fstride[MAXFACTORS]; 524 | int i; 525 | int shift; 526 | 527 | /* st->shift can be -1 */ 528 | shift = st->shift>0 ? st->shift : 0; 529 | 530 | fstride[0] = 1; 531 | L=0; 532 | do { 533 | p = st->factors[2*L]; 534 | m = st->factors[2*L+1]; 535 | fstride[L+1] = fstride[L]*p; 536 | L++; 537 | } while(m!=1); 538 | m = st->factors[2*L-1]; 539 | for (i=L-1;i>=0;i--) 540 | { 541 | if (i!=0) 542 | m2 = st->factors[2*i-1]; 543 | else 544 | m2 = 1; 545 | switch (st->factors[2*i]) 546 | { 547 | case 2: 548 | kf_bfly2(fout, m, fstride[i]); 549 | break; 550 | case 4: 551 | kf_bfly4(fout,fstride[i]<scale_shift-1; 574 | #endif 575 | scale = st->scale; 576 | 577 | celt_assert2 (fin != fout, "In-place FFT not supported"); 578 | /* Bit-reverse the input */ 579 | for (i=0;infft;i++) 580 | { 581 | kiss_fft_cpx x = fin[i]; 582 | fout[st->bitrev[i]].r = SHR32(MULT16_32_Q16(scale, x.r), scale_shift); 583 | fout[st->bitrev[i]].i = SHR32(MULT16_32_Q16(scale, x.i), scale_shift); 584 | } 585 | rnn_fft_impl(st, fout); 586 | } 587 | 588 | 589 | void rnn_ifft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) 590 | { 591 | int i; 592 | celt_assert2 (fin != fout, "In-place FFT not supported"); 593 | /* Bit-reverse the input */ 594 | for (i=0;infft;i++) 595 | fout[st->bitrev[i]] = fin[i]; 596 | for (i=0;infft;i++) 597 | fout[i].i = -fout[i].i; 598 | rnn_fft_impl(st, fout); 599 | for (i=0;infft;i++) 600 | fout[i].i = -fout[i].i; 601 | } 602 | -------------------------------------------------------------------------------- /lib/rnnoise/src/kiss_fft.h: -------------------------------------------------------------------------------- 1 | /*Copyright (c) 2003-2004, Mark Borgerding 2 | Lots of modifications by Jean-Marc Valin 3 | Copyright (c) 2005-2007, Xiph.Org Foundation 4 | Copyright (c) 2008, Xiph.Org Foundation, CSIRO 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE.*/ 28 | 29 | #ifndef KISS_FFT_H 30 | #define KISS_FFT_H 31 | 32 | #include 33 | #include 34 | #include "arch.h" 35 | 36 | #include 37 | #define opus_alloc(x) malloc(x) 38 | #define opus_free(x) free(x) 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | #ifdef USE_SIMD 45 | # include 46 | # define kiss_fft_scalar __m128 47 | #define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes) 48 | #else 49 | #define KISS_FFT_MALLOC opus_alloc 50 | #endif 51 | 52 | #ifdef FIXED_POINT 53 | #include "arch.h" 54 | 55 | # define kiss_fft_scalar opus_int32 56 | # define kiss_twiddle_scalar opus_int16 57 | 58 | 59 | #else 60 | # ifndef kiss_fft_scalar 61 | /* default is float */ 62 | # define kiss_fft_scalar float 63 | # define kiss_twiddle_scalar float 64 | # define KF_SUFFIX _celt_single 65 | # endif 66 | #endif 67 | 68 | typedef struct { 69 | kiss_fft_scalar r; 70 | kiss_fft_scalar i; 71 | }kiss_fft_cpx; 72 | 73 | typedef struct { 74 | kiss_twiddle_scalar r; 75 | kiss_twiddle_scalar i; 76 | }kiss_twiddle_cpx; 77 | 78 | #define MAXFACTORS 8 79 | /* e.g. an fft of length 128 has 4 factors 80 | as far as kissfft is concerned 81 | 4*4*4*2 82 | */ 83 | 84 | typedef struct arch_fft_state{ 85 | int is_supported; 86 | void *priv; 87 | } arch_fft_state; 88 | 89 | typedef struct kiss_fft_state{ 90 | int nfft; 91 | opus_val16 scale; 92 | #ifdef FIXED_POINT 93 | int scale_shift; 94 | #endif 95 | int shift; 96 | opus_int16 factors[2*MAXFACTORS]; 97 | const opus_int16 *bitrev; 98 | const kiss_twiddle_cpx *twiddles; 99 | arch_fft_state *arch_fft; 100 | } kiss_fft_state; 101 | 102 | #if defined(HAVE_ARM_NE10) 103 | #include "arm/fft_arm.h" 104 | #endif 105 | 106 | /*typedef struct kiss_fft_state* kiss_fft_cfg;*/ 107 | 108 | /** 109 | * opus_fft_alloc 110 | * 111 | * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. 112 | * 113 | * typical usage: kiss_fft_cfg mycfg=opus_fft_alloc(1024,0,NULL,NULL); 114 | * 115 | * The return value from fft_alloc is a cfg buffer used internally 116 | * by the fft routine or NULL. 117 | * 118 | * If lenmem is NULL, then opus_fft_alloc will allocate a cfg buffer using malloc. 119 | * The returned value should be free()d when done to avoid memory leaks. 120 | * 121 | * The state can be placed in a user supplied buffer 'mem': 122 | * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, 123 | * then the function places the cfg in mem and the size used in *lenmem 124 | * and returns mem. 125 | * 126 | * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), 127 | * then the function returns NULL and places the minimum cfg 128 | * buffer size in *lenmem. 129 | * */ 130 | 131 | kiss_fft_state *rnn_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base, int arch); 132 | 133 | kiss_fft_state *rnn_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch); 134 | 135 | /** 136 | * opus_fft(cfg,in_out_buf) 137 | * 138 | * Perform an FFT on a complex input buffer. 139 | * for a forward FFT, 140 | * fin should be f[0] , f[1] , ... ,f[nfft-1] 141 | * fout will be F[0] , F[1] , ... ,F[nfft-1] 142 | * Note that each element is complex and can be accessed like 143 | f[k].r and f[k].i 144 | * */ 145 | void rnn_fft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); 146 | void rnn_ifft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); 147 | 148 | void rnn_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout); 149 | void rnn_ifft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout); 150 | 151 | void rnn_fft_free(const kiss_fft_state *cfg, int arch); 152 | 153 | 154 | void rnn_fft_free_arch_c(kiss_fft_state *st); 155 | int rnn_fft_alloc_arch_c(kiss_fft_state *st); 156 | 157 | #if !defined(OVERRIDE_OPUS_FFT) 158 | /* Is run-time CPU detection enabled on this platform? */ 159 | #if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) 160 | 161 | extern int (*const OPUS_FFT_ALLOC_ARCH_IMPL[OPUS_ARCHMASK+1])( 162 | kiss_fft_state *st); 163 | 164 | #define opus_fft_alloc_arch(_st, arch) \ 165 | ((*OPUS_FFT_ALLOC_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st)) 166 | 167 | extern void (*const OPUS_FFT_FREE_ARCH_IMPL[OPUS_ARCHMASK+1])( 168 | kiss_fft_state *st); 169 | #define opus_fft_free_arch(_st, arch) \ 170 | ((*OPUS_FFT_FREE_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st)) 171 | 172 | extern void (*const OPUS_FFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg, 173 | const kiss_fft_cpx *fin, kiss_fft_cpx *fout); 174 | #define opus_fft(_cfg, _fin, _fout, arch) \ 175 | ((*OPUS_FFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout)) 176 | 177 | extern void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg, 178 | const kiss_fft_cpx *fin, kiss_fft_cpx *fout); 179 | #define opus_ifft(_cfg, _fin, _fout, arch) \ 180 | ((*OPUS_IFFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout)) 181 | 182 | #else /* else for if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */ 183 | 184 | #define rnn_fft_alloc_arch(_st, arch) \ 185 | ((void)(arch), rnn_fft_alloc_arch_c(_st)) 186 | 187 | #define rnn_fft_free_arch(_st, arch) \ 188 | ((void)(arch), rnn_fft_free_arch_c(_st)) 189 | 190 | #define rnn_fft(_cfg, _fin, _fout, arch) \ 191 | ((void)(arch), rnn_fft_c(_cfg, _fin, _fout)) 192 | 193 | #define rnn_ifft(_cfg, _fin, _fout, arch) \ 194 | ((void)(arch), rnn_ifft_c(_cfg, _fin, _fout)) 195 | 196 | #endif /* end if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */ 197 | #endif /* end if !defined(OVERRIDE_OPUS_FFT) */ 198 | 199 | #ifdef __cplusplus 200 | } 201 | #endif 202 | 203 | #endif 204 | -------------------------------------------------------------------------------- /lib/rnnoise/src/opus_types.h: -------------------------------------------------------------------------------- 1 | /* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */ 2 | /* Modified by Jean-Marc Valin */ 3 | /* 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | - Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | - Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 19 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | /* opus_types.h based on ogg_types.h from libogg */ 28 | 29 | /** 30 | @file opus_types.h 31 | @brief Opus reference implementation types 32 | */ 33 | #ifndef OPUS_TYPES_H 34 | #define OPUS_TYPES_H 35 | 36 | /* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */ 37 | #if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H)) 38 | #include 39 | 40 | typedef int16_t opus_int16; 41 | typedef uint16_t opus_uint16; 42 | typedef int32_t opus_int32; 43 | typedef uint32_t opus_uint32; 44 | #elif defined(_WIN32) 45 | 46 | # if defined(__CYGWIN__) 47 | # include <_G_config.h> 48 | typedef _G_int32_t opus_int32; 49 | typedef _G_uint32_t opus_uint32; 50 | typedef _G_int16 opus_int16; 51 | typedef _G_uint16 opus_uint16; 52 | # elif defined(__MINGW32__) 53 | typedef short opus_int16; 54 | typedef unsigned short opus_uint16; 55 | typedef int opus_int32; 56 | typedef unsigned int opus_uint32; 57 | # elif defined(__MWERKS__) 58 | typedef int opus_int32; 59 | typedef unsigned int opus_uint32; 60 | typedef short opus_int16; 61 | typedef unsigned short opus_uint16; 62 | # else 63 | /* MSVC/Borland */ 64 | typedef __int32 opus_int32; 65 | typedef unsigned __int32 opus_uint32; 66 | typedef __int16 opus_int16; 67 | typedef unsigned __int16 opus_uint16; 68 | # endif 69 | 70 | #elif defined(__MACOS__) 71 | 72 | # include 73 | typedef SInt16 opus_int16; 74 | typedef UInt16 opus_uint16; 75 | typedef SInt32 opus_int32; 76 | typedef UInt32 opus_uint32; 77 | 78 | #elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ 79 | 80 | # include 81 | typedef int16_t opus_int16; 82 | typedef u_int16_t opus_uint16; 83 | typedef int32_t opus_int32; 84 | typedef u_int32_t opus_uint32; 85 | 86 | #elif defined(__BEOS__) 87 | 88 | /* Be */ 89 | # include 90 | typedef int16 opus_int16; 91 | typedef u_int16 opus_uint16; 92 | typedef int32_t opus_int32; 93 | typedef u_int32_t opus_uint32; 94 | 95 | #elif defined (__EMX__) 96 | 97 | /* OS/2 GCC */ 98 | typedef short opus_int16; 99 | typedef unsigned short opus_uint16; 100 | typedef int opus_int32; 101 | typedef unsigned int opus_uint32; 102 | 103 | #elif defined (DJGPP) 104 | 105 | /* DJGPP */ 106 | typedef short opus_int16; 107 | typedef unsigned short opus_uint16; 108 | typedef int opus_int32; 109 | typedef unsigned int opus_uint32; 110 | 111 | #elif defined(R5900) 112 | 113 | /* PS2 EE */ 114 | typedef int opus_int32; 115 | typedef unsigned opus_uint32; 116 | typedef short opus_int16; 117 | typedef unsigned short opus_uint16; 118 | 119 | #elif defined(__SYMBIAN32__) 120 | 121 | /* Symbian GCC */ 122 | typedef signed short opus_int16; 123 | typedef unsigned short opus_uint16; 124 | typedef signed int opus_int32; 125 | typedef unsigned int opus_uint32; 126 | 127 | #elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) 128 | 129 | typedef short opus_int16; 130 | typedef unsigned short opus_uint16; 131 | typedef long opus_int32; 132 | typedef unsigned long opus_uint32; 133 | 134 | #elif defined(CONFIG_TI_C6X) 135 | 136 | typedef short opus_int16; 137 | typedef unsigned short opus_uint16; 138 | typedef int opus_int32; 139 | typedef unsigned int opus_uint32; 140 | 141 | #else 142 | 143 | /* Give up, take a reasonable guess */ 144 | typedef short opus_int16; 145 | typedef unsigned short opus_uint16; 146 | typedef int opus_int32; 147 | typedef unsigned int opus_uint32; 148 | 149 | #endif 150 | 151 | #define opus_int int /* used for counters etc; at least 16 bits */ 152 | #define opus_int64 long long 153 | #define opus_int8 signed char 154 | 155 | #define opus_uint unsigned int /* used for counters etc; at least 16 bits */ 156 | #define opus_uint64 unsigned long long 157 | #define opus_uint8 unsigned char 158 | 159 | #endif /* OPUS_TYPES_H */ 160 | -------------------------------------------------------------------------------- /lib/rnnoise/src/pitch.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2008 CSIRO 2 | Copyright (c) 2007-2009 Xiph.Org Foundation 3 | Written by Jean-Marc Valin */ 4 | /** 5 | @file pitch.c 6 | @brief Pitch analysis 7 | */ 8 | 9 | /* 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions 12 | are met: 13 | 14 | - Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | 17 | - Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 25 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifdef HAVE_CONFIG_H 35 | #include "config.h" 36 | #endif 37 | 38 | #include "pitch.h" 39 | #include "common.h" 40 | #include "celt_lpc.h" 41 | #include "math.h" 42 | 43 | static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len, 44 | int max_pitch, int *best_pitch 45 | #ifdef FIXED_POINT 46 | , int yshift, opus_val32 maxcorr 47 | #endif 48 | ) 49 | { 50 | int i, j; 51 | opus_val32 Syy=1; 52 | opus_val16 best_num[2]; 53 | opus_val32 best_den[2]; 54 | #ifdef FIXED_POINT 55 | int xshift; 56 | 57 | xshift = celt_ilog2(maxcorr)-14; 58 | #endif 59 | 60 | best_num[0] = -1; 61 | best_num[1] = -1; 62 | best_den[0] = 0; 63 | best_den[1] = 0; 64 | best_pitch[0] = 0; 65 | best_pitch[1] = 1; 66 | for (j=0;j0) 71 | { 72 | opus_val16 num; 73 | opus_val32 xcorr16; 74 | xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift)); 75 | #ifndef FIXED_POINT 76 | /* Considering the range of xcorr16, this should avoid both underflows 77 | and overflows (inf) when squaring xcorr16 */ 78 | xcorr16 *= 1e-12f; 79 | #endif 80 | num = MULT16_16_Q15(xcorr16,xcorr16); 81 | if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy)) 82 | { 83 | if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy)) 84 | { 85 | best_num[1] = best_num[0]; 86 | best_den[1] = best_den[0]; 87 | best_pitch[1] = best_pitch[0]; 88 | best_num[0] = num; 89 | best_den[0] = Syy; 90 | best_pitch[0] = i; 91 | } else { 92 | best_num[1] = num; 93 | best_den[1] = Syy; 94 | best_pitch[1] = i; 95 | } 96 | } 97 | } 98 | Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift); 99 | Syy = MAX32(1, Syy); 100 | } 101 | } 102 | 103 | static void celt_fir5(const opus_val16 *x, 104 | const opus_val16 *num, 105 | opus_val16 *y, 106 | int N, 107 | opus_val16 *mem) 108 | { 109 | int i; 110 | opus_val16 num0, num1, num2, num3, num4; 111 | opus_val32 mem0, mem1, mem2, mem3, mem4; 112 | num0=num[0]; 113 | num1=num[1]; 114 | num2=num[2]; 115 | num3=num[3]; 116 | num4=num[4]; 117 | mem0=mem[0]; 118 | mem1=mem[1]; 119 | mem2=mem[2]; 120 | mem3=mem[3]; 121 | mem4=mem[4]; 122 | for (i=0;i>1;i++) 171 | x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift); 172 | x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift); 173 | if (C==2) 174 | { 175 | for (i=1;i>1;i++) 176 | x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift); 177 | x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift); 178 | } 179 | 180 | rnn_autocorr(x_lp, ac, NULL, 0, 181 | 4, len>>1); 182 | 183 | /* Noise floor -40 dB */ 184 | #ifdef FIXED_POINT 185 | ac[0] += SHR32(ac[0],13); 186 | #else 187 | ac[0] *= 1.0001f; 188 | #endif 189 | /* Lag windowing */ 190 | for (i=1;i<=4;i++) 191 | { 192 | /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/ 193 | #ifdef FIXED_POINT 194 | ac[i] -= MULT16_32_Q15(2*i*i, ac[i]); 195 | #else 196 | ac[i] -= ac[i]*(.008f*i)*(.008f*i); 197 | #endif 198 | } 199 | 200 | rnn_lpc(lpc, ac, 4); 201 | for (i=0;i<4;i++) 202 | { 203 | tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp); 204 | lpc[i] = MULT16_16_Q15(lpc[i], tmp); 205 | } 206 | /* Add a zero */ 207 | lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT); 208 | lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]); 209 | lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]); 210 | lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]); 211 | lpc2[4] = MULT16_16_Q15(c1,lpc[3]); 212 | celt_fir5(x_lp, lpc2, x_lp, len>>1, mem); 213 | } 214 | 215 | void rnn_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y, 216 | opus_val32 *xcorr, int len, int max_pitch) 217 | { 218 | 219 | #if 0 /* This is a simple version of the pitch correlation that should work 220 | well on DSPs like Blackfin and TI C5x/C6x */ 221 | int i, j; 222 | #ifdef FIXED_POINT 223 | opus_val32 maxcorr=1; 224 | #endif 225 | for (i=0;i0); 248 | celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); 249 | for (i=0;i0); 294 | celt_assert(max_pitch>0); 295 | lag = len+max_pitch; 296 | 297 | opus_val16 x_lp4[len>>2]; 298 | opus_val16 y_lp4[lag>>2]; 299 | opus_val32 xcorr[max_pitch>>1]; 300 | 301 | /* Downsample by 2 again */ 302 | for (j=0;j>2;j++) 303 | x_lp4[j] = x_lp[2*j]; 304 | for (j=0;j>2;j++) 305 | y_lp4[j] = y[2*j]; 306 | 307 | #ifdef FIXED_POINT 308 | xmax = celt_maxabs16(x_lp4, len>>2); 309 | ymax = celt_maxabs16(y_lp4, lag>>2); 310 | shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax)))-11; 311 | if (shift>0) 312 | { 313 | for (j=0;j>2;j++) 314 | x_lp4[j] = SHR16(x_lp4[j], shift); 315 | for (j=0;j>2;j++) 316 | y_lp4[j] = SHR16(y_lp4[j], shift); 317 | /* Use double the shift for a MAC */ 318 | shift *= 2; 319 | } else { 320 | shift = 0; 321 | } 322 | #endif 323 | 324 | /* Coarse search with 4x decimation */ 325 | 326 | #ifdef FIXED_POINT 327 | maxcorr = 328 | #endif 329 | rnn_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2); 330 | 331 | find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch 332 | #ifdef FIXED_POINT 333 | , 0, maxcorr 334 | #endif 335 | ); 336 | 337 | /* Finer search with 2x decimation */ 338 | #ifdef FIXED_POINT 339 | maxcorr=1; 340 | #endif 341 | for (i=0;i>1;i++) 342 | { 343 | opus_val32 sum; 344 | xcorr[i] = 0; 345 | if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2) 346 | continue; 347 | #ifdef FIXED_POINT 348 | sum = 0; 349 | for (j=0;j>1;j++) 350 | sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift); 351 | #else 352 | sum = celt_inner_prod(x_lp, y+i, len>>1); 353 | #endif 354 | xcorr[i] = MAX32(-1, sum); 355 | #ifdef FIXED_POINT 356 | maxcorr = MAX32(maxcorr, sum); 357 | #endif 358 | } 359 | find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch 360 | #ifdef FIXED_POINT 361 | , shift+1, maxcorr 362 | #endif 363 | ); 364 | 365 | /* Refine by pseudo-interpolation */ 366 | if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1) 367 | { 368 | opus_val32 a, b, c; 369 | a = xcorr[best_pitch[0]-1]; 370 | b = xcorr[best_pitch[0]]; 371 | c = xcorr[best_pitch[0]+1]; 372 | if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a)) 373 | offset = 1; 374 | else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c)) 375 | offset = -1; 376 | else 377 | offset = 0; 378 | } else { 379 | offset = 0; 380 | } 381 | *pitch = 2*best_pitch[0]-offset; 382 | } 383 | 384 | #ifdef FIXED_POINT 385 | static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy) 386 | { 387 | opus_val32 x2y2; 388 | int sx, sy, shift; 389 | opus_val32 g; 390 | opus_val16 den; 391 | if (xy == 0 || xx == 0 || yy == 0) 392 | return 0; 393 | sx = celt_ilog2(xx)-14; 394 | sy = celt_ilog2(yy)-14; 395 | shift = sx + sy; 396 | x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14); 397 | if (shift & 1) { 398 | if (x2y2 < 32768) 399 | { 400 | x2y2 <<= 1; 401 | shift--; 402 | } else { 403 | x2y2 >>= 1; 404 | shift++; 405 | } 406 | } 407 | den = celt_rsqrt_norm(x2y2); 408 | g = MULT16_32_Q15(den, xy); 409 | g = VSHR32(g, (shift>>1)-1); 410 | return EXTRACT16(MIN32(g, Q15ONE)); 411 | } 412 | #else 413 | static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy) 414 | { 415 | return xy/sqrt(1+xx*yy); 416 | } 417 | #endif 418 | 419 | static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2}; 420 | opus_val16 rnn_remove_doubling(opus_val16 *x, int maxperiod, int minperiod, 421 | int N, int *T0_, int prev_period, opus_val16 prev_gain) 422 | { 423 | int k, i, T, T0; 424 | opus_val16 g, g0; 425 | opus_val16 pg; 426 | opus_val32 xy,xx,yy,xy2; 427 | opus_val32 xcorr[3]; 428 | opus_val32 best_xy, best_yy; 429 | int offset; 430 | int minperiod0; 431 | 432 | minperiod0 = minperiod; 433 | maxperiod /= 2; 434 | minperiod /= 2; 435 | *T0_ /= 2; 436 | prev_period /= 2; 437 | N /= 2; 438 | x += maxperiod; 439 | if (*T0_>=maxperiod) 440 | *T0_=maxperiod-1; 441 | 442 | T = T0 = *T0_; 443 | opus_val32 yy_lookup[maxperiod+1]; 444 | dual_inner_prod(x, x, x-T0, N, &xx, &xy); 445 | yy_lookup[0] = xx; 446 | yy=xx; 447 | for (i=1;i<=maxperiod;i++) 448 | { 449 | yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]); 450 | yy_lookup[i] = MAX32(0, yy); 451 | } 452 | yy = yy_lookup[T0]; 453 | best_xy = xy; 454 | best_yy = yy; 455 | g = g0 = compute_pitch_gain(xy, xx, yy); 456 | /* Look for any pitch at T/k */ 457 | for (k=2;k<=15;k++) 458 | { 459 | int T1, T1b; 460 | opus_val16 g1; 461 | opus_val16 cont=0; 462 | opus_val16 thresh; 463 | T1 = (2*T0+k)/(2*k); 464 | if (T1 < minperiod) 465 | break; 466 | /* Look for another strong correlation at T1b */ 467 | if (k==2) 468 | { 469 | if (T1+T0>maxperiod) 470 | T1b = T0; 471 | else 472 | T1b = T0+T1; 473 | } else 474 | { 475 | T1b = (2*second_check[k]*T0+k)/(2*k); 476 | } 477 | dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2); 478 | xy = HALF32(xy + xy2); 479 | yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]); 480 | g1 = compute_pitch_gain(xy, xx, yy); 481 | if (abs(T1-prev_period)<=1) 482 | cont = prev_gain; 483 | else if (abs(T1-prev_period)<=2 && 5*k*k < T0) 484 | cont = HALF16(prev_gain); 485 | else 486 | cont = 0; 487 | thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont); 488 | /* Bias against very high pitch (very short period) to avoid false-positives 489 | due to short-term correlation */ 490 | if (T1<3*minperiod) 491 | thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont); 492 | else if (T1<2*minperiod) 493 | thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont); 494 | if (g1 > thresh) 495 | { 496 | best_xy = xy; 497 | best_yy = yy; 498 | T = T1; 499 | g = g1; 500 | } 501 | } 502 | best_xy = MAX32(0, best_xy); 503 | if (best_yy <= best_xy) 504 | pg = Q15ONE; 505 | else 506 | pg = best_xy/(best_yy+1); 507 | 508 | for (k=0;k<3;k++) 509 | xcorr[k] = celt_inner_prod(x, x-(T+k-1), N); 510 | if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0])) 511 | offset = 1; 512 | else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2])) 513 | offset = -1; 514 | else 515 | offset = 0; 516 | if (pg > g) 517 | pg = g; 518 | *T0_ = 2*T+offset; 519 | 520 | if (*T0_=3); 58 | y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */ 59 | y_0=*y++; 60 | y_1=*y++; 61 | y_2=*y++; 62 | for (j=0;j 33 | #include "opus_types.h" 34 | #include "common.h" 35 | #include "arch.h" 36 | #include "tansig_table.h" 37 | #include "rnn.h" 38 | #include "rnn_data.h" 39 | #include 40 | 41 | static OPUS_INLINE float tansig_approx(float x) 42 | { 43 | int i; 44 | float y, dy; 45 | float sign=1; 46 | /* Tests are reversed to catch NaNs */ 47 | if (!(x<8)) 48 | return 1; 49 | if (!(x>-8)) 50 | return -1; 51 | #ifndef FIXED_POINT 52 | /* Another check in case of -ffast-math */ 53 | if (celt_isnan(x)) 54 | return 0; 55 | #endif 56 | if (x<0) 57 | { 58 | x=-x; 59 | sign=-1; 60 | } 61 | i = (int)floor(.5f+25*x); 62 | x -= .04f*i; 63 | y = tansig_table[i]; 64 | dy = 1-y*y; 65 | y = y + x*dy*(1 - y*x); 66 | return sign*y; 67 | } 68 | 69 | static OPUS_INLINE float sigmoid_approx(float x) 70 | { 71 | return .5 + .5*tansig_approx(.5*x); 72 | } 73 | 74 | static OPUS_INLINE float relu(float x) 75 | { 76 | return x < 0 ? 0 : x; 77 | } 78 | 79 | static void compute_dense(const DenseLayer *layer, float *output, const float *input) 80 | { 81 | int i, j; 82 | int N, M; 83 | int stride; 84 | M = layer->nb_inputs; 85 | N = layer->nb_neurons; 86 | stride = N; 87 | for (i=0;ibias[i]; 91 | for (j=0;jinput_weights[j*stride + i]*input[j]; 93 | output[i] = WEIGHTS_SCALE*sum; 94 | } 95 | if (layer->activation == ACTIVATION_SIGMOID) { 96 | for (i=0;iactivation == ACTIVATION_TANH) { 99 | for (i=0;iactivation == ACTIVATION_RELU) { 102 | for (i=0;inb_inputs; 118 | N = gru->nb_neurons; 119 | stride = 3*N; 120 | for (i=0;ibias[i]; 124 | for (j=0;jinput_weights[j*stride + i]*input[j]; 126 | for (j=0;jrecurrent_weights[j*stride + i]*state[j]; 128 | z[i] = sigmoid_approx(WEIGHTS_SCALE*sum); 129 | } 130 | for (i=0;ibias[N + i]; 134 | for (j=0;jinput_weights[N + j*stride + i]*input[j]; 136 | for (j=0;jrecurrent_weights[N + j*stride + i]*state[j]; 138 | r[i] = sigmoid_approx(WEIGHTS_SCALE*sum); 139 | } 140 | for (i=0;ibias[2*N + i]; 144 | for (j=0;jinput_weights[2*N + j*stride + i]*input[j]; 146 | for (j=0;jrecurrent_weights[2*N + j*stride + i]*state[j]*r[j]; 148 | if (gru->activation == ACTIVATION_SIGMOID) sum = sigmoid_approx(WEIGHTS_SCALE*sum); 149 | else if (gru->activation == ACTIVATION_TANH) sum = tansig_approx(WEIGHTS_SCALE*sum); 150 | else if (gru->activation == ACTIVATION_RELU) sum = relu(WEIGHTS_SCALE*sum); 151 | else *(int*)0=0; 152 | h[i] = z[i]*state[i] + (1-z[i])*sum; 153 | } 154 | for (i=0;imodel->input_dense, dense_out, input); 166 | compute_gru(rnn->model->vad_gru, rnn->vad_gru_state, dense_out); 167 | compute_dense(rnn->model->vad_output, vad, rnn->vad_gru_state); 168 | for (i=0;imodel->input_dense_size;i++) noise_input[i] = dense_out[i]; 169 | for (i=0;imodel->vad_gru_size;i++) noise_input[i+rnn->model->input_dense_size] = rnn->vad_gru_state[i]; 170 | for (i=0;imodel->input_dense_size+rnn->model->vad_gru_size] = input[i]; 171 | compute_gru(rnn->model->noise_gru, rnn->noise_gru_state, noise_input); 172 | 173 | for (i=0;imodel->vad_gru_size;i++) denoise_input[i] = rnn->vad_gru_state[i]; 174 | for (i=0;imodel->noise_gru_size;i++) denoise_input[i+rnn->model->vad_gru_size] = rnn->noise_gru_state[i]; 175 | for (i=0;imodel->vad_gru_size+rnn->model->noise_gru_size] = input[i]; 176 | compute_gru(rnn->model->denoise_gru, rnn->denoise_gru_state, denoise_input); 177 | compute_dense(rnn->model->denoise_output, gains, rnn->denoise_gru_state); 178 | } 179 | -------------------------------------------------------------------------------- /lib/rnnoise/src/rnn.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017 Jean-Marc Valin */ 2 | /* 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 7 | - Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | - Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 18 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef RNN_H_ 28 | #define RNN_H_ 29 | 30 | #include "rnnoise.h" 31 | 32 | #include "opus_types.h" 33 | 34 | #define WEIGHTS_SCALE (1.f/256) 35 | 36 | #define MAX_NEURONS 128 37 | 38 | #define ACTIVATION_TANH 0 39 | #define ACTIVATION_SIGMOID 1 40 | #define ACTIVATION_RELU 2 41 | 42 | typedef signed char rnn_weight; 43 | 44 | typedef struct { 45 | const rnn_weight *bias; 46 | const rnn_weight *input_weights; 47 | int nb_inputs; 48 | int nb_neurons; 49 | int activation; 50 | } DenseLayer; 51 | 52 | typedef struct { 53 | const rnn_weight *bias; 54 | const rnn_weight *input_weights; 55 | const rnn_weight *recurrent_weights; 56 | int nb_inputs; 57 | int nb_neurons; 58 | int activation; 59 | } GRULayer; 60 | 61 | typedef struct RNNState RNNState; 62 | 63 | void compute_rnn(RNNState *rnn, float *gains, float *vad, const float *input); 64 | 65 | #endif /* RNN_H_ */ 66 | -------------------------------------------------------------------------------- /lib/rnnoise/src/rnn_data.h: -------------------------------------------------------------------------------- 1 | #ifndef RNN_DATA_H 2 | #define RNN_DATA_H 3 | 4 | #include "rnn.h" 5 | 6 | struct RNNModel { 7 | int input_dense_size; 8 | const DenseLayer *input_dense; 9 | 10 | int vad_gru_size; 11 | const GRULayer *vad_gru; 12 | 13 | int noise_gru_size; 14 | const GRULayer *noise_gru; 15 | 16 | int denoise_gru_size; 17 | const GRULayer *denoise_gru; 18 | 19 | int denoise_output_size; 20 | const DenseLayer *denoise_output; 21 | 22 | int vad_output_size; 23 | const DenseLayer *vad_output; 24 | }; 25 | 26 | struct RNNState { 27 | const RNNModel *model; 28 | float *vad_gru_state; 29 | float *noise_gru_state; 30 | float *denoise_gru_state; 31 | }; 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lib/rnnoise/src/tansig_table.h: -------------------------------------------------------------------------------- 1 | /* This file is auto-generated by gen_tables */ 2 | 3 | static const float tansig_table[201] = { 4 | 0.000000f, 0.039979f, 0.079830f, 0.119427f, 0.158649f, 5 | 0.197375f, 0.235496f, 0.272905f, 0.309507f, 0.345214f, 6 | 0.379949f, 0.413644f, 0.446244f, 0.477700f, 0.507977f, 7 | 0.537050f, 0.564900f, 0.591519f, 0.616909f, 0.641077f, 8 | 0.664037f, 0.685809f, 0.706419f, 0.725897f, 0.744277f, 9 | 0.761594f, 0.777888f, 0.793199f, 0.807569f, 0.821040f, 10 | 0.833655f, 0.845456f, 0.856485f, 0.866784f, 0.876393f, 11 | 0.885352f, 0.893698f, 0.901468f, 0.908698f, 0.915420f, 12 | 0.921669f, 0.927473f, 0.932862f, 0.937863f, 0.942503f, 13 | 0.946806f, 0.950795f, 0.954492f, 0.957917f, 0.961090f, 14 | 0.964028f, 0.966747f, 0.969265f, 0.971594f, 0.973749f, 15 | 0.975743f, 0.977587f, 0.979293f, 0.980869f, 0.982327f, 16 | 0.983675f, 0.984921f, 0.986072f, 0.987136f, 0.988119f, 17 | 0.989027f, 0.989867f, 0.990642f, 0.991359f, 0.992020f, 18 | 0.992631f, 0.993196f, 0.993718f, 0.994199f, 0.994644f, 19 | 0.995055f, 0.995434f, 0.995784f, 0.996108f, 0.996407f, 20 | 0.996682f, 0.996937f, 0.997172f, 0.997389f, 0.997590f, 21 | 0.997775f, 0.997946f, 0.998104f, 0.998249f, 0.998384f, 22 | 0.998508f, 0.998623f, 0.998728f, 0.998826f, 0.998916f, 23 | 0.999000f, 0.999076f, 0.999147f, 0.999213f, 0.999273f, 24 | 0.999329f, 0.999381f, 0.999428f, 0.999472f, 0.999513f, 25 | 0.999550f, 0.999585f, 0.999617f, 0.999646f, 0.999673f, 26 | 0.999699f, 0.999722f, 0.999743f, 0.999763f, 0.999781f, 27 | 0.999798f, 0.999813f, 0.999828f, 0.999841f, 0.999853f, 28 | 0.999865f, 0.999875f, 0.999885f, 0.999893f, 0.999902f, 29 | 0.999909f, 0.999916f, 0.999923f, 0.999929f, 0.999934f, 30 | 0.999939f, 0.999944f, 0.999948f, 0.999952f, 0.999956f, 31 | 0.999959f, 0.999962f, 0.999965f, 0.999968f, 0.999970f, 32 | 0.999973f, 0.999975f, 0.999977f, 0.999978f, 0.999980f, 33 | 0.999982f, 0.999983f, 0.999984f, 0.999986f, 0.999987f, 34 | 0.999988f, 0.999989f, 0.999990f, 0.999990f, 0.999991f, 35 | 0.999992f, 0.999992f, 0.999993f, 0.999994f, 0.999994f, 36 | 0.999994f, 0.999995f, 0.999995f, 0.999996f, 0.999996f, 37 | 0.999996f, 0.999997f, 0.999997f, 0.999997f, 0.999997f, 38 | 0.999997f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 39 | 0.999998f, 0.999998f, 0.999999f, 0.999999f, 0.999999f, 40 | 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 41 | 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 42 | 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 43 | 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 44 | 1.000000f, 45 | }; 46 | -------------------------------------------------------------------------------- /pico_sdk_import.cmake: -------------------------------------------------------------------------------- 1 | # This is a copy of /external/pico_sdk_import.cmake 2 | 3 | # This can be dropped into an external project to help locate this SDK 4 | # It should be include()ed prior to project() 5 | 6 | if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) 7 | set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) 8 | message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") 9 | endif () 10 | 11 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) 12 | set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) 13 | message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") 14 | endif () 15 | 16 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) 17 | set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) 18 | message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") 19 | endif () 20 | 21 | set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") 22 | set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") 23 | set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") 24 | 25 | if (NOT PICO_SDK_PATH) 26 | if (PICO_SDK_FETCH_FROM_GIT) 27 | include(FetchContent) 28 | set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) 29 | if (PICO_SDK_FETCH_FROM_GIT_PATH) 30 | get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") 31 | endif () 32 | # GIT_SUBMODULES_RECURSE was added in 3.17 33 | if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") 34 | FetchContent_Declare( 35 | pico_sdk 36 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 37 | GIT_TAG master 38 | GIT_SUBMODULES_RECURSE FALSE 39 | ) 40 | else () 41 | FetchContent_Declare( 42 | pico_sdk 43 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 44 | GIT_TAG master 45 | ) 46 | endif () 47 | 48 | if (NOT pico_sdk) 49 | message("Downloading Raspberry Pi Pico SDK") 50 | FetchContent_Populate(pico_sdk) 51 | set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) 52 | endif () 53 | set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) 54 | else () 55 | message(FATAL_ERROR 56 | "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." 57 | ) 58 | endif () 59 | endif () 60 | 61 | get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") 62 | if (NOT EXISTS ${PICO_SDK_PATH}) 63 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") 64 | endif () 65 | 66 | set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) 67 | if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) 68 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") 69 | endif () 70 | 71 | set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) 72 | 73 | include(${PICO_SDK_INIT_CMAKE_FILE}) 74 | --------------------------------------------------------------------------------