inoryQwQ commited on
Commit
6dc3c2b
·
verified ·
1 Parent(s): 817ca71

Upload folder using huggingface_hub

Browse files
Files changed (50) hide show
  1. .gitignore +6 -0
  2. LICENSE +32 -0
  3. NPU_ONLY_SDK.md +1 -0
  4. README.md +65 -0
  5. config.json +1 -0
  6. cpp/CMakeLists.txt +37 -0
  7. cpp/README.md +29 -0
  8. cpp/examples/main.cpp +58 -0
  9. cpp/include/model_runner.hpp +24 -0
  10. cpp/include/rnnoise_ax.hpp +26 -0
  11. cpp/src/model_runner.cpp +202 -0
  12. cpp/src/rnnoise/_kiss_fft_guts.h +182 -0
  13. cpp/src/rnnoise/arch.h +261 -0
  14. cpp/src/rnnoise/celt_lpc.c +174 -0
  15. cpp/src/rnnoise/celt_lpc.h +45 -0
  16. cpp/src/rnnoise/common.h +56 -0
  17. cpp/src/rnnoise/compile.sh +3 -0
  18. cpp/src/rnnoise/cpu_support.h +53 -0
  19. cpp/src/rnnoise/denoise.c +505 -0
  20. cpp/src/rnnoise/denoise.h +56 -0
  21. cpp/src/rnnoise/dump_features.c +499 -0
  22. cpp/src/rnnoise/dump_rnnoise_tables.c +105 -0
  23. cpp/src/rnnoise/kiss_fft.c +601 -0
  24. cpp/src/rnnoise/kiss_fft.h +203 -0
  25. cpp/src/rnnoise/nnet.c +123 -0
  26. cpp/src/rnnoise/nnet.h +169 -0
  27. cpp/src/rnnoise/nnet_arch.h +257 -0
  28. cpp/src/rnnoise/nnet_default.c +35 -0
  29. cpp/src/rnnoise/opus_types.h +159 -0
  30. cpp/src/rnnoise/parse_lpcnet_weights.c +237 -0
  31. cpp/src/rnnoise/pitch.c +528 -0
  32. cpp/src/rnnoise/pitch.h +147 -0
  33. cpp/src/rnnoise/rnn.c +60 -0
  34. cpp/src/rnnoise/rnn.h +49 -0
  35. cpp/src/rnnoise/rnn_train.py +66 -0
  36. cpp/src/rnnoise/rnnoise.h +131 -0
  37. cpp/src/rnnoise/rnnoise_data.c +18 -0
  38. cpp/src/rnnoise/rnnoise_data.h +55 -0
  39. cpp/src/rnnoise/rnnoise_tables.c +874 -0
  40. cpp/src/rnnoise/vec.h +388 -0
  41. cpp/src/rnnoise/vec_avx.h +884 -0
  42. cpp/src/rnnoise/vec_neon.h +474 -0
  43. cpp/src/rnnoise/write_weights.c +77 -0
  44. cpp/src/rnnoise/x86/dnn_x86.h +85 -0
  45. cpp/src/rnnoise/x86/nnet_avx2.c +40 -0
  46. cpp/src/rnnoise/x86/nnet_sse4_1.c +40 -0
  47. cpp/src/rnnoise/x86/x86_arch_macros.h +47 -0
  48. cpp/src/rnnoise/x86/x86_dnn_map.c +74 -0
  49. cpp/src/rnnoise/x86/x86cpu.c +166 -0
  50. cpp/src/rnnoise/x86/x86cpu.h +88 -0
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ build/
4
+ CMakeFiles/
5
+ CMakeCache.txt
6
+ *.egg-info/
LICENSE ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2007-2017, 2024 Jean-Marc Valin
2
+ Copyright (c) 2023 Amazon
3
+ Copyright (c) 2017, Mozilla
4
+ Copyright (c) 2005-2017, Xiph.Org Foundation
5
+ Copyright (c) 2003-2004, Mark Borgerding
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions
9
+ are met:
10
+
11
+ - Redistributions of source code must retain the above copyright
12
+ notice, this list of conditions and the following disclaimer.
13
+
14
+ - Redistributions in binary form must reproduce the above copyright
15
+ notice, this list of conditions and the following disclaimer in the
16
+ documentation and/or other materials provided with the distribution.
17
+
18
+ - Neither the name of the Xiph.Org Foundation nor the names of its
19
+ contributors may be used to endorse or promote products derived from
20
+ this software without specific prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
26
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
NPU_ONLY_SDK.md ADDED
@@ -0,0 +1 @@
 
 
1
+ 本交付包已通过端到端 NPU 验证,Python SDK 仅依赖 pyaxengine,不含 onnxruntime/torch/transformers 等运行时回退。
README.md ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: isc
3
+ pipeline_tag: audio-to-audio
4
+ tags:
5
+ - axmodel
6
+ - axera
7
+ - rnnoise-ax650
8
+ ---
9
+ # RNNoise AX650 实时降噪(AXMODEL 交付包)
10
+
11
+ 48kHz 单声道实时降噪:原版 RNNoise 网络编译到 AX650 NPU3,前后处理 1:1 对齐
12
+ 官方 C 管线。板端 C++ 每帧 2.85ms(10ms 帧预算内),输出与官方实现 cosine ≈ 0.98+;
13
+ 模型 3.3MB,支持 U16 混合精度推理。
14
+
15
+ ## 快速开始(只需两步)
16
+
17
+ ### 1. 安装环境
18
+
19
+ ```bash
20
+ bash setup.sh
21
+ ```
22
+
23
+ ### 2. 跑推理(板端)
24
+
25
+ ```bash
26
+ bash run.sh
27
+ ```
28
+
29
+ `run.sh` 会处理自带的 1 秒演示音频(`python/sample_speech.pcm`),
30
+ 输出去噪 PCM 到 `output/out.pcm`,并打印语音存在比例。
31
+
32
+ ## 目录说明
33
+
34
+ | 目录 | 用途 |
35
+ |------|------|
36
+ | `models/` | `model.axmodel`(AX650 NPU3)+ `model_meta.json` |
37
+ | `python/` | Python SDK(pyaxengine,NPU 专用,仅依赖 numpy + pyaxengine)|
38
+ | `cpp/` | C++ SDK(原版 C 信号处理 + AX Engine,实时路径)|
39
+ | `model_convert/` | 模型导出 & 编译脚本(可复现)|
40
+ | `reports/` | 导出/编译/仿真/上板报告 |
41
+
42
+ ## 自己调用 SDK(核心 3 行)
43
+
44
+ ```python
45
+ from rnnoise_ax650_sdk import RNNoiseDenoiser
46
+ denoiser = RNNoiseDenoiser("models/model.axmodel") # 板端 pyaxengine
47
+ out_frame, vad = denoiser.process_frame(pcm_frame_480) # 48k float32 帧
48
+ ```
49
+
50
+ 输入帧为 16-bit PCM 等价 float(±32768 量级,不做归一化,与官方 demo 一致);
51
+ 模型逐帧 6 输入(features + 5 个状态)/ 7 输出(gains/vad + 5 个新状态),
52
+ 状态由 SDK 内部维护。
53
+
54
+ ## 常见问题
55
+
56
+ **Q: import 报错找不到 pyaxengine?**
57
+ A: 在 AX 板端运行 `bash setup.sh` 自动安装(交付版不做 CPU 回退)。
58
+
59
+ **Q: Python 每帧要 60ms,能实时吗?**
60
+ A: Python 版面向原型/离线批处理;实时降噪请用 `cpp/`(2.85ms/帧),
61
+ 编译方法见 `cpp/README.md`。
62
+
63
+ **Q: 想自己重新编译模型?**
64
+ A: 进入 `model_convert/`,按 README 准备 Pulsar2 7.0 Docker 后运行
65
+ `bash compile_pulsar2.sh`。
config.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {}
cpp/CMakeLists.txt ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required(VERSION 3.15)
2
+ project(rnnoise_ax650_sdk LANGUAGES CXX C)
3
+
4
+ set(CMAKE_CXX_STANDARD 14)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+
7
+ include_directories(include src/rnnoise)
8
+
9
+ # 原版 rnnoise 信号处理(denoise/pitch/FFT/LPC/表格)。
10
+ # 注意:不编译 rnn.c(其 compute_rnn 由 src/rnnoise_ax.cpp 用 AX Engine 替换)。
11
+ add_library(rnnoise_c STATIC
12
+ src/rnnoise/denoise.c
13
+ src/rnnoise/pitch.c
14
+ src/rnnoise/kiss_fft.c
15
+ src/rnnoise/celt_lpc.c
16
+ src/rnnoise/nnet.c
17
+ src/rnnoise/nnet_default.c
18
+ src/rnnoise/parse_lpcnet_weights.c
19
+ src/rnnoise/rnnoise_data.c
20
+ src/rnnoise/rnnoise_tables.c
21
+ )
22
+
23
+ add_library(rnnoise_ax650_sdk STATIC
24
+ src/model_runner.cpp
25
+ src/rnnoise_ax.cpp
26
+ )
27
+ target_include_directories(rnnoise_ax650_sdk PUBLIC include)
28
+ target_link_libraries(rnnoise_ax650_sdk PRIVATE rnnoise_c)
29
+
30
+ add_executable(model_example examples/main.cpp)
31
+ target_link_libraries(model_example PRIVATE rnnoise_ax650_sdk)
32
+
33
+ if(AX_RUNTIME_ROOT)
34
+ target_include_directories(rnnoise_ax650_sdk PUBLIC ${AX_RUNTIME_ROOT}/include)
35
+ target_link_directories(rnnoise_ax650_sdk PUBLIC ${AX_RUNTIME_ROOT}/lib)
36
+ target_link_libraries(rnnoise_ax650_sdk PUBLIC ax_engine ax_sys pthread dl atomic)
37
+ endif()
cpp/README.md ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # rnnoise-ax650 C++ SDK
2
+
3
+ 48kHz 单声道实时降噪,RNNoise 原版 C 信号处理 + AX Engine(NPU3)网络推理。
4
+
5
+ ## 编译(AX650 板端/交叉环境)
6
+
7
+ ```bash
8
+ export AX_RUNTIME_ROOT=/path/to/axruntime # 含 include/ax_engine_api.h 与 lib/libax_engine.so
9
+ mkdir -p build && cd build
10
+ cmake .. -DAX_RUNTIME_ROOT=$AX_RUNTIME_ROOT
11
+ make -j$(nproc)
12
+ ```
13
+
14
+ ## 运行
15
+
16
+ ```bash
17
+ ./build/model_example model.axmodel in.pcm out.pcm
18
+ ```
19
+
20
+ 输入为 48kHz f32le PCM(16-bit 等价域 ±32768,不做归一化);
21
+ 输出为同格式去噪 PCM。每帧 480 采样(10ms),vad 打印均值。
22
+
23
+ ## 结构
24
+
25
+ - `include/rnnoise_ax.hpp`:`RNNoiseAX` 类(进程内单实例)
26
+ - `src/rnnoise_ax.cpp`:以 AX Engine 替换原版 `compute_rnn`(6 输入/7 输出逐帧状态化)
27
+ - `src/model_runner.cpp`:AX Engine 会话封装(按张量名映射,含缓存同步)
28
+ - `src/rnnoise/`:原版 rnnoise C 信号处理源码(denoise/pitch/FFT/LPC/表格,ISC 许可);
29
+ 网络权重已内嵌 AXMODEL,`rnnoise_data.c` 为最小 stub(空权重表 + 零初始化)
cpp/examples/main.cpp ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // RNNoise AX650 示例:处理 48k f32 PCM(16-bit 等价域),输出去噪 PCM。
2
+ // 用法: ./model_example model.axmodel in.pcm out.pcm
3
+ #include "rnnoise_ax.hpp"
4
+
5
+ #include <cstdio>
6
+ #include <cstdlib>
7
+ #include <chrono>
8
+ #include <vector>
9
+
10
+ int main(int argc, char** argv) {
11
+ if (argc != 4) {
12
+ std::fprintf(stderr, "用法: %s model.axmodel in.pcm out.pcm\n", argv[0]);
13
+ return 1;
14
+ }
15
+ FILE* in = std::fopen(argv[2], "rb");
16
+ if (!in) {
17
+ std::fprintf(stderr, "无法打开输入 %s\n", argv[2]);
18
+ return 1;
19
+ }
20
+ std::fseek(in, 0, SEEK_END);
21
+ long bytes = std::ftell(in);
22
+ std::fseek(in, 0, SEEK_SET);
23
+ std::vector<float> pcm(bytes / sizeof(float));
24
+ if (!pcm.empty()) {
25
+ std::fread(pcm.data(), sizeof(float), pcm.size(), in);
26
+ }
27
+ std::fclose(in);
28
+
29
+ const int frame = RNNoiseAX::FrameSize();
30
+ const int frames = static_cast<int>(pcm.size() / frame);
31
+ if (frames == 0) {
32
+ std::fprintf(stderr, "输入过短\n");
33
+ return 1;
34
+ }
35
+
36
+ RNNoiseAX denoiser(argv[1]);
37
+ std::vector<float> out(pcm.size());
38
+ double vad_sum = 0.0;
39
+ auto t0 = std::chrono::steady_clock::now();
40
+ for (int i = 0; i < frames; ++i) {
41
+ vad_sum += denoiser.ProcessFrame(
42
+ &out[i * frame], &pcm[i * frame]);
43
+ }
44
+ auto t1 = std::chrono::steady_clock::now();
45
+ double secs = std::chrono::duration<double>(t1 - t0).count();
46
+
47
+ FILE* of = std::fopen(argv[3], "wb");
48
+ if (!of) {
49
+ std::fprintf(stderr, "无法写入输出 %s\n", argv[3]);
50
+ return 1;
51
+ }
52
+ std::fwrite(out.data(), sizeof(float), out.size(), of);
53
+ std::fclose(of);
54
+
55
+ std::printf("frames=%d vad_mean=%.4f per_frame_ms=%.3f out=%s\n",
56
+ frames, vad_sum / frames, secs / frames * 1000.0, argv[3]);
57
+ return 0;
58
+ }
cpp/include/model_runner.hpp ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <vector>
5
+
6
+ // AX Engine 会话封装:加载 AXMODEL,按张量名映射输入输出。
7
+ class ModelRunner {
8
+ public:
9
+ explicit ModelRunner(const std::string& model_path,
10
+ const std::string& model_name = "rnnoise");
11
+ ~ModelRunner();
12
+
13
+ ModelRunner(const ModelRunner&) = delete;
14
+ ModelRunner& operator=(const ModelRunner&) = delete;
15
+
16
+ // 6 输入(features/conv1_mem/conv2_mem/gru1_s/gru2_s/gru3_s)
17
+ // -> 7 输出(gains/vad/conv1_mem_new/conv2_mem_new/gru1_s_new/gru2_s_new/gru3_s_new)
18
+ std::vector<std::vector<float>> Run(
19
+ const std::vector<std::vector<float>>& inputs);
20
+
21
+ private:
22
+ struct Impl;
23
+ Impl* impl_;
24
+ };
cpp/include/rnnoise_ax.hpp ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <string>
5
+
6
+ // RNNoise AX650 实时降噪器:原版 rnnoise C 信号处理 + AX Engine 网络推理。
7
+ class RNNoiseAX {
8
+ public:
9
+ explicit RNNoiseAX(const std::string& model_path);
10
+ ~RNNoiseAX();
11
+
12
+ RNNoiseAX(const RNNoiseAX&) = delete;
13
+ RNNoiseAX& operator=(const RNNoiseAX&) = delete;
14
+
15
+ static int FrameSize() { return 480; }
16
+
17
+ void Reset();
18
+
19
+ // 处理一帧 48k PCM(16-bit 等价 float,±32768 域)。
20
+ // in/out 各至少 FrameSize() 个 float;返回 vad(0~1)。
21
+ float ProcessFrame(float* out, const float* in);
22
+
23
+ private:
24
+ struct Impl;
25
+ std::unique_ptr<Impl> impl_;
26
+ };
cpp/src/model_runner.cpp ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "model_runner.hpp"
2
+
3
+ #include <ax_engine_api.h>
4
+ #include <ax_sys_api.h>
5
+
6
+ #include <algorithm>
7
+ #include <cstring>
8
+ #include <fstream>
9
+ #include <iterator>
10
+ #include <stdexcept>
11
+ #include <unordered_map>
12
+
13
+ namespace {
14
+
15
+ // 老版本 ax_sys_api.h 未声明这两个缓存同步接口,这里补充声明(板端 libax_sys 已导出)。
16
+ extern "C" AX_S32 AX_SYS_MflushCache(AX_U64 phy_addr, AX_VOID* vir_addr, AX_U32 size);
17
+ extern "C" AX_S32 AX_SYS_MinvalidateCache(AX_U64 phy_addr, AX_VOID* vir_addr, AX_U32 size);
18
+
19
+ std::vector<char> read_binary(const std::string& path) {
20
+ std::ifstream file(path, std::ios::binary);
21
+ if (!file) {
22
+ throw std::runtime_error("failed to open " + path);
23
+ }
24
+ return std::vector<char>(
25
+ std::istreambuf_iterator<char>(file),
26
+ std::istreambuf_iterator<char>());
27
+ }
28
+
29
+ void check_ax(int ret, const char* message) {
30
+ if (ret != 0) {
31
+ throw std::runtime_error(message);
32
+ }
33
+ }
34
+
35
+ const char* kInputNames[6] = {
36
+ "features", "conv1_mem", "conv2_mem",
37
+ "gru1_s", "gru2_s", "gru3_s",
38
+ };
39
+ const char* kOutputNames[7] = {
40
+ "gains", "vad",
41
+ "conv1_mem_new", "conv2_mem_new",
42
+ "gru1_s_new", "gru2_s_new", "gru3_s_new",
43
+ };
44
+
45
+ // 兼容不同 AX SDK 版本:新版 AX_ENGINE_RunSyncV2(handle, context, io),
46
+ // 旧版 AX_ENGINE_Run(context, io)。
47
+ namespace axrun {
48
+ template <typename H, typename C, typename IO>
49
+ auto run(H h, C c, IO* io, int)
50
+ -> decltype(AX_ENGINE_RunSyncV2(h, c, io)) {
51
+ return AX_ENGINE_RunSyncV2(h, c, io);
52
+ }
53
+ template <typename H, typename C, typename IO>
54
+ auto run(H /*h*/, C c, IO* io, long)
55
+ -> decltype(AX_ENGINE_Run(c, io)) {
56
+ return AX_ENGINE_Run(c, io);
57
+ }
58
+ } // namespace axrun
59
+
60
+ } // namespace
61
+
62
+ struct ModelRunner::Impl {
63
+ AX_ENGINE_HANDLE handle = nullptr;
64
+ AX_ENGINE_CONTEXT_T context = nullptr;
65
+ AX_ENGINE_IO_INFO_T* info = nullptr;
66
+ AX_ENGINE_IO_T io {};
67
+ std::vector<AX_ENGINE_IO_BUFFER_T> buffers;
68
+ std::vector<int> input_idx;
69
+ std::vector<int> output_idx;
70
+ std::vector<char> model;
71
+
72
+ explicit Impl(const std::string& model_path, const std::string& model_name)
73
+ : model(read_binary(model_path)) {
74
+ check_ax(AX_SYS_Init(), "AX_SYS_Init failed");
75
+
76
+ AX_ENGINE_NPU_ATTR_T npu_attr;
77
+ std::memset(&npu_attr, 0, sizeof(npu_attr));
78
+ npu_attr.eHardMode = static_cast<AX_ENGINE_NPU_MODE_T>(0);
79
+ check_ax(AX_ENGINE_Init(&npu_attr), "AX_ENGINE_Init failed");
80
+
81
+ AX_ENGINE_HANDLE_EXTRA_T extra;
82
+ std::memset(&extra, 0, sizeof(extra));
83
+ extra.pName = const_cast<AX_S8*>(
84
+ reinterpret_cast<const AX_S8*>(model_name.c_str()));
85
+ check_ax(
86
+ AX_ENGINE_CreateHandleV2(
87
+ &handle, model.data(),
88
+ static_cast<AX_U32>(model.size()), &extra),
89
+ "AX_ENGINE_CreateHandleV2 failed");
90
+ check_ax(
91
+ AX_ENGINE_CreateContextV2(handle, &context),
92
+ "AX_ENGINE_CreateContextV2 failed");
93
+ check_ax(AX_ENGINE_GetIOInfo(handle, &info), "AX_ENGINE_GetIOInfo failed");
94
+ if (!info || info->nInputSize < 6 || info->nOutputSize < 7) {
95
+ throw std::runtime_error("model IO mismatch (expect 6 in / 7 out)");
96
+ }
97
+
98
+ // 按张量名建立索引映射
99
+ input_idx.resize(6, -1);
100
+ output_idx.resize(7, -1);
101
+ std::unordered_map<std::string, int> in_map, out_map;
102
+ for (AX_U32 i = 0; i < info->nInputSize; ++i) {
103
+ const char* nm = info->pInputs[i].pName;
104
+ in_map[nm ? nm : ""] = static_cast<int>(i);
105
+ }
106
+ for (AX_U32 i = 0; i < info->nOutputSize; ++i) {
107
+ const char* nm = info->pOutputs[i].pName;
108
+ out_map[nm ? nm : ""] = static_cast<int>(i);
109
+ }
110
+ for (int i = 0; i < 6; ++i) {
111
+ auto it = in_map.find(kInputNames[i]);
112
+ if (it == in_map.end()) {
113
+ throw std::runtime_error(std::string("missing input ") + kInputNames[i]);
114
+ }
115
+ input_idx[i] = it->second;
116
+ }
117
+ for (int i = 0; i < 7; ++i) {
118
+ auto it = out_map.find(kOutputNames[i]);
119
+ if (it == out_map.end()) {
120
+ throw std::runtime_error(std::string("missing output ") + kOutputNames[i]);
121
+ }
122
+ output_idx[i] = it->second;
123
+ }
124
+
125
+ buffers.resize(info->nInputSize + info->nOutputSize);
126
+ io.pInputs = buffers.data();
127
+ io.nInputSize = info->nInputSize;
128
+ io.pOutputs = buffers.data() + info->nInputSize;
129
+ io.nOutputSize = info->nOutputSize;
130
+ for (AX_U32 i = 0; i < info->nInputSize; ++i) {
131
+ std::memset(&buffers[i], 0, sizeof(buffers[i]));
132
+ buffers[i].nSize = info->pInputs[i].nSize;
133
+ check_ax(
134
+ AX_SYS_MemAllocCached(
135
+ &buffers[i].phyAddr, &buffers[i].pVirAddr,
136
+ buffers[i].nSize, 128,
137
+ reinterpret_cast<const AX_S8*>("model_input")),
138
+ "AX_SYS_MemAllocCached(input) failed");
139
+ }
140
+ for (AX_U32 i = 0; i < info->nOutputSize; ++i) {
141
+ AX_ENGINE_IO_BUFFER_T& buf = buffers[info->nInputSize + i];
142
+ std::memset(&buf, 0, sizeof(buf));
143
+ buf.nSize = info->pOutputs[i].nSize;
144
+ check_ax(
145
+ AX_SYS_MemAllocCached(
146
+ &buf.phyAddr, &buf.pVirAddr, buf.nSize, 128,
147
+ reinterpret_cast<const AX_S8*>("model_output")),
148
+ "AX_SYS_MemAllocCached(output) failed");
149
+ }
150
+ }
151
+
152
+ ~Impl() {
153
+ for (auto& item : buffers) {
154
+ if (item.phyAddr) {
155
+ AX_SYS_MemFree(item.phyAddr, item.pVirAddr);
156
+ }
157
+ }
158
+ if (handle) {
159
+ AX_ENGINE_DestroyHandle(handle);
160
+ }
161
+ AX_ENGINE_Deinit();
162
+ AX_SYS_Deinit();
163
+ }
164
+ };
165
+
166
+ ModelRunner::ModelRunner(const std::string& model_path,
167
+ const std::string& model_name)
168
+ : impl_(new Impl(model_path, model_name)) {}
169
+
170
+ ModelRunner::~ModelRunner() {
171
+ delete impl_;
172
+ }
173
+
174
+ std::vector<std::vector<float>> ModelRunner::Run(
175
+ const std::vector<std::vector<float>>& inputs) {
176
+ if (inputs.size() != 6) {
177
+ throw std::runtime_error("rnnoise expects 6 inputs");
178
+ }
179
+ for (int i = 0; i < 6; ++i) {
180
+ const size_t bytes = inputs[i].size() * sizeof(float);
181
+ AX_ENGINE_IO_BUFFER_T& buf = impl_->buffers[impl_->input_idx[i]];
182
+ if (bytes > buf.nSize) {
183
+ throw std::runtime_error("input larger than model tensor");
184
+ }
185
+ std::memcpy(buf.pVirAddr, inputs[i].data(), bytes);
186
+ AX_SYS_MflushCache(buf.phyAddr, buf.pVirAddr,
187
+ static_cast<AX_U32>(bytes));
188
+ }
189
+ check_ax(axrun::run(impl_->handle, impl_->context, &impl_->io, 0),
190
+ "AX_ENGINE_Run failed");
191
+
192
+ std::vector<std::vector<float>> outputs(7);
193
+ for (int i = 0; i < 7; ++i) {
194
+ const AX_ENGINE_IO_BUFFER_T& buf =
195
+ impl_->buffers[impl_->info->nInputSize + impl_->output_idx[i]];
196
+ AX_SYS_MinvalidateCache(buf.phyAddr, buf.pVirAddr, buf.nSize);
197
+ const size_t count = buf.nSize / sizeof(float);
198
+ const auto* src = static_cast<const float*>(buf.pVirAddr);
199
+ outputs[i].assign(src, src + count);
200
+ }
201
+ return outputs;
202
+ }
cpp/src/rnnoise/_kiss_fft_guts.h ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 */
cpp/src/rnnoise/arch.h ADDED
@@ -0,0 +1,261 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 <stdio.h>
54
+ #include <stdlib.h>
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 */
cpp/src/rnnoise/celt_lpc.c ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ #include "denoise.h"
37
+
38
+ void rnn_lpc(
39
+ opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */
40
+ const opus_val32 *ac, /* in: [0...p] autocorrelation values */
41
+ int p
42
+ )
43
+ {
44
+ int i, j;
45
+ opus_val32 r;
46
+ opus_val32 error = ac[0];
47
+ #ifdef FIXED_POINT
48
+ opus_val32 lpc[LPC_ORDER];
49
+ #else
50
+ float *lpc = _lpc;
51
+ #endif
52
+
53
+ RNN_CLEAR(lpc, p);
54
+ if (ac[0] != 0)
55
+ {
56
+ for (i = 0; i < p; i++) {
57
+ /* Sum up this iteration's reflection coefficient */
58
+ opus_val32 rr = 0;
59
+ for (j = 0; j < i; j++)
60
+ rr += MULT32_32_Q31(lpc[j],ac[i - j]);
61
+ rr += SHR32(ac[i + 1],3);
62
+ r = -SHL32(rr,3)/error;
63
+ /* Update LPC coefficients and total error */
64
+ lpc[i] = SHR32(r,3);
65
+ for (j = 0; j < (i+1)>>1; j++)
66
+ {
67
+ opus_val32 tmp1, tmp2;
68
+ tmp1 = lpc[j];
69
+ tmp2 = lpc[i-1-j];
70
+ lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2);
71
+ lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
72
+ }
73
+
74
+ error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
75
+ /* Bail out once we get 30 dB gain */
76
+ #ifdef FIXED_POINT
77
+ if (error<SHR32(ac[0],10))
78
+ break;
79
+ #else
80
+ if (error<.001f*ac[0])
81
+ break;
82
+ #endif
83
+ }
84
+ }
85
+ #ifdef FIXED_POINT
86
+ for (i=0;i<p;i++)
87
+ _lpc[i] = ROUND16(lpc[i],16);
88
+ #endif
89
+ }
90
+
91
+
92
+ int rnn_autocorr(
93
+ const opus_val16 *x, /* in: [0...n-1] samples x */
94
+ opus_val32 *ac, /* out: [0...lag-1] ac values */
95
+ const opus_val16 *window,
96
+ int overlap,
97
+ int lag,
98
+ int n)
99
+ {
100
+ opus_val32 d;
101
+ int i, k;
102
+ int fastN=n-lag;
103
+ int shift;
104
+ const opus_val16 *xptr;
105
+ opus_val16 xx[PITCH_BUF_SIZE/2];
106
+ celt_assert(n>0);
107
+ celt_assert(n<=PITCH_BUF_SIZE/2)
108
+ celt_assert(overlap>=0);
109
+ if (overlap == 0)
110
+ {
111
+ xptr = x;
112
+ } else {
113
+ for (i=0;i<n;i++)
114
+ xx[i] = x[i];
115
+ for (i=0;i<overlap;i++)
116
+ {
117
+ xx[i] = MULT16_16_Q15(x[i],window[i]);
118
+ xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]);
119
+ }
120
+ xptr = xx;
121
+ }
122
+ shift=0;
123
+ #ifdef FIXED_POINT
124
+ {
125
+ opus_val32 ac0;
126
+ ac0 = 1+(n<<7);
127
+ if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9);
128
+ for(i=(n&1);i<n;i+=2)
129
+ {
130
+ ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9);
131
+ ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9);
132
+ }
133
+
134
+ shift = celt_ilog2(ac0)-30+10;
135
+ shift = (shift)/2;
136
+ if (shift>0)
137
+ {
138
+ for(i=0;i<n;i++)
139
+ xx[i] = PSHR32(xptr[i], shift);
140
+ xptr = xx;
141
+ } else
142
+ shift = 0;
143
+ }
144
+ #endif
145
+ rnn_pitch_xcorr(xptr, xptr, ac, fastN, lag+1);
146
+ for (k=0;k<=lag;k++)
147
+ {
148
+ for (i = k+fastN, d = 0; i < n; i++)
149
+ d = MAC16_16(d, xptr[i], xptr[i-k]);
150
+ ac[k] += d;
151
+ }
152
+ #ifdef FIXED_POINT
153
+ shift = 2*shift;
154
+ if (shift<=0)
155
+ ac[0] += SHL32((opus_int32)1, -shift);
156
+ if (ac[0] < 268435456)
157
+ {
158
+ int shift2 = 29 - EC_ILOG(ac[0]);
159
+ for (i=0;i<=lag;i++)
160
+ ac[i] = SHL32(ac[i], shift2);
161
+ shift -= shift2;
162
+ } else if (ac[0] >= 536870912)
163
+ {
164
+ int shift2=1;
165
+ if (ac[0] >= 1073741824)
166
+ shift2++;
167
+ for (i=0;i<=lag;i++)
168
+ ac[i] = SHR32(ac[i], shift2);
169
+ shift += shift2;
170
+ }
171
+ #endif
172
+
173
+ return shift;
174
+ }
cpp/src/rnnoise/celt_lpc.h ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 */
cpp/src/rnnoise/common.h ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ # if !defined(OPUS_GNUC_PREREQ)
47
+ # if defined(__GNUC__)&&defined(__GNUC_MINOR__)
48
+ # define OPUS_GNUC_PREREQ(_maj,_min) \
49
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
50
+ # else
51
+ # define OPUS_GNUC_PREREQ(_maj,_min) 0
52
+ # endif
53
+ # endif
54
+
55
+
56
+ #endif
cpp/src/rnnoise/compile.sh ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ #!/bin/sh
2
+
3
+ gcc -DTRAINING=1 -Wall -W -O3 -g -I../include denoise.c kiss_fft.c pitch.c celt_lpc.c rnn.c rnn_data.c -o denoise_training -lm
cpp/src/rnnoise/cpu_support.h ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2010 Xiph.Org Foundation
2
+ * Copyright (c) 2013 Parrot */
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 CPU_SUPPORT_H
29
+ #define CPU_SUPPORT_H
30
+
31
+ #include "opus_types.h"
32
+ #include "common.h"
33
+
34
+ #ifdef RNN_ENABLE_X86_RTCD
35
+
36
+ #include "x86/x86cpu.h"
37
+ /* We currently support 5 x86 variants:
38
+ * arch[0] -> sse2
39
+ * arch[1] -> sse4.1
40
+ * arch[2] -> avx2
41
+ */
42
+ #define OPUS_ARCHMASK 3
43
+ int rnn_select_arch(void);
44
+
45
+ #else
46
+ #define OPUS_ARCHMASK 0
47
+
48
+ static OPUS_INLINE int rnn_select_arch(void)
49
+ {
50
+ return 0;
51
+ }
52
+ #endif
53
+ #endif
cpp/src/rnnoise/denoise.c ADDED
@@ -0,0 +1,505 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2024 Jean-Marc Valin
2
+ * Copyright (c) 2018 Gregor Richards
3
+ * Copyright (c) 2017 Mozilla */
4
+ /*
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ - Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+
12
+ - Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #ifdef HAVE_CONFIG_H
30
+ #include "config.h"
31
+ #endif
32
+
33
+ #include <stdlib.h>
34
+ #include <string.h>
35
+ #include <stdio.h>
36
+ #include "kiss_fft.h"
37
+ #include "common.h"
38
+ #include "denoise.h"
39
+ #include <math.h>
40
+ #include "rnnoise.h"
41
+ #include "pitch.h"
42
+ #include "arch.h"
43
+ #include "rnn.h"
44
+ #include "cpu_support.h"
45
+
46
+ #define SQUARE(x) ((x)*(x))
47
+
48
+
49
+ #ifndef TRAINING
50
+ #define TRAINING 0
51
+ #endif
52
+
53
+
54
+ /* ERB bandwidths going in reverse from 20 kHz and then replacing the 700 and 800
55
+ with just 750 because having 32 bands is convenient for the DNN.
56
+ B(1)=400;
57
+ for k=2:35
58
+ B(k) = B(k-1) - max(2, round(24.7*(4.37*B(k-1)/20+1)/50));
59
+ end
60
+ printf("%d, ", B(end:-1:1));
61
+ printf("\n")
62
+ */
63
+ const int eband20ms[NB_BANDS+2] = {
64
+ /*0 100 200 300 400 500 600 750 900 1.1 1.2 1.4 1.6 1.8 2.1 2.4 2.7 3.0 3.4 3.9 4.4 4.9 5.5 6.2 7.0 7.9 8.8 9.9 11.2 12.6 14.1 15.9 17.8 20.0*/
65
+ 0, 2, 4, 6, 8, 10, 12, 15, 18, 21, 24, 28, 32, 36, 41, 47, 53, 60, 68, 77, 87, 98, 110, 124, 140, 157, 176, 198, 223, 251, 282, 317, 356, 400};
66
+
67
+
68
+ struct DenoiseState {
69
+ RNNoise model;
70
+ #if !TRAINING
71
+ int arch;
72
+ #endif
73
+ float analysis_mem[FRAME_SIZE];
74
+ int memid;
75
+ float synthesis_mem[FRAME_SIZE];
76
+ float pitch_buf[PITCH_BUF_SIZE];
77
+ float pitch_enh_buf[PITCH_BUF_SIZE];
78
+ float last_gain;
79
+ int last_period;
80
+ float mem_hp_x[2];
81
+ float lastg[NB_BANDS];
82
+ RNNState rnn;
83
+ kiss_fft_cpx delayed_X[FREQ_SIZE];
84
+ kiss_fft_cpx delayed_P[FREQ_SIZE];
85
+ float delayed_Ex[NB_BANDS], delayed_Ep[NB_BANDS];
86
+ float delayed_Exp[NB_BANDS];
87
+
88
+ };
89
+
90
+ static void compute_band_energy(float *bandE, const kiss_fft_cpx *X) {
91
+ int i;
92
+ float sum[NB_BANDS+2] = {0};
93
+ for (i=0;i<NB_BANDS+1;i++)
94
+ {
95
+ int j;
96
+ int band_size;
97
+ band_size = eband20ms[i+1]-eband20ms[i];
98
+ for (j=0;j<band_size;j++) {
99
+ float tmp;
100
+ float frac = (float)j/band_size;
101
+ tmp = SQUARE(X[eband20ms[i] + j].r);
102
+ tmp += SQUARE(X[eband20ms[i] + j].i);
103
+ sum[i] += (1-frac)*tmp;
104
+ sum[i+1] += frac*tmp;
105
+ }
106
+ }
107
+ sum[1] = (sum[0]+sum[1])*2/3;
108
+ sum[NB_BANDS] = (sum[NB_BANDS]+sum[NB_BANDS+1])*2/3;
109
+ for (i=0;i<NB_BANDS;i++)
110
+ {
111
+ bandE[i] = sum[i+1];
112
+ }
113
+ }
114
+
115
+ static void compute_band_corr(float *bandE, const kiss_fft_cpx *X, const kiss_fft_cpx *P) {
116
+ int i;
117
+ float sum[NB_BANDS+2] = {0};
118
+ for (i=0;i<NB_BANDS+1;i++)
119
+ {
120
+ int j;
121
+ int band_size;
122
+ band_size = eband20ms[i+1]-eband20ms[i];
123
+ for (j=0;j<band_size;j++) {
124
+ float tmp;
125
+ float frac = (float)j/band_size;
126
+ tmp = X[eband20ms[i] + j].r * P[eband20ms[i] + j].r;
127
+ tmp += X[eband20ms[i] + j].i * P[eband20ms[i] + j].i;
128
+ sum[i] += (1-frac)*tmp;
129
+ sum[i+1] += frac*tmp;
130
+ }
131
+ }
132
+ sum[1] = (sum[0]+sum[1])*2/3;
133
+ sum[NB_BANDS] = (sum[NB_BANDS]+sum[NB_BANDS+1])*2/3;
134
+ for (i=0;i<NB_BANDS;i++)
135
+ {
136
+ bandE[i] = sum[i+1];
137
+ }
138
+ }
139
+
140
+ static void interp_band_gain(float *g, const float *bandE) {
141
+ int i,j;
142
+ memset(g, 0, FREQ_SIZE);
143
+ for (i=1;i<NB_BANDS;i++)
144
+ {
145
+ int band_size;
146
+ band_size = eband20ms[i+1]-eband20ms[i];
147
+ for (j=0;j<band_size;j++) {
148
+ float frac = (float)j/band_size;
149
+ g[eband20ms[i] + j] = (1-frac)*bandE[i-1] + frac*bandE[i];
150
+ }
151
+ }
152
+ for (j=0;j<eband20ms[1];j++) g[j] = bandE[0];
153
+ for (j=eband20ms[NB_BANDS];j<eband20ms[NB_BANDS+1];j++) g[j] = bandE[NB_BANDS-1];
154
+ }
155
+
156
+ extern const float rnn_dct_table[];
157
+ extern const kiss_fft_state rnn_kfft;
158
+ extern const float rnn_half_window[];
159
+
160
+ static void dct(float *out, const float *in) {
161
+ int i;
162
+ for (i=0;i<NB_BANDS;i++) {
163
+ int j;
164
+ float sum = 0;
165
+ for (j=0;j<NB_BANDS;j++) {
166
+ sum += in[j] * rnn_dct_table[j*NB_BANDS + i];
167
+ }
168
+ out[i] = sum*sqrt(2./22);
169
+ }
170
+ }
171
+
172
+ #if 0
173
+ static void idct(float *out, const float *in) {
174
+ int i;
175
+ for (i=0;i<NB_BANDS;i++) {
176
+ int j;
177
+ float sum = 0;
178
+ for (j=0;j<NB_BANDS;j++) {
179
+ sum += in[j] * rnn_dct_table[i*NB_BANDS + j];
180
+ }
181
+ out[i] = sum*sqrt(2./22);
182
+ }
183
+ }
184
+ #endif
185
+
186
+ static void forward_transform(kiss_fft_cpx *out, const float *in) {
187
+ int i;
188
+ kiss_fft_cpx x[WINDOW_SIZE];
189
+ kiss_fft_cpx y[WINDOW_SIZE];
190
+ for (i=0;i<WINDOW_SIZE;i++) {
191
+ x[i].r = in[i];
192
+ x[i].i = 0;
193
+ }
194
+ rnn_fft(&rnn_kfft, x, y, 0);
195
+ for (i=0;i<FREQ_SIZE;i++) {
196
+ out[i] = y[i];
197
+ }
198
+ }
199
+
200
+ static void inverse_transform(float *out, const kiss_fft_cpx *in) {
201
+ int i;
202
+ kiss_fft_cpx x[WINDOW_SIZE];
203
+ kiss_fft_cpx y[WINDOW_SIZE];
204
+ for (i=0;i<FREQ_SIZE;i++) {
205
+ x[i] = in[i];
206
+ }
207
+ for (;i<WINDOW_SIZE;i++) {
208
+ x[i].r = x[WINDOW_SIZE - i].r;
209
+ x[i].i = -x[WINDOW_SIZE - i].i;
210
+ }
211
+ rnn_fft(&rnn_kfft, x, y, 0);
212
+ /* output in reverse order for IFFT. */
213
+ out[0] = WINDOW_SIZE*y[0].r;
214
+ for (i=1;i<WINDOW_SIZE;i++) {
215
+ out[i] = WINDOW_SIZE*y[WINDOW_SIZE - i].r;
216
+ }
217
+ }
218
+
219
+ static void apply_window(float *x) {
220
+ int i;
221
+ for (i=0;i<FRAME_SIZE;i++) {
222
+ x[i] *= rnn_half_window[i];
223
+ x[WINDOW_SIZE - 1 - i] *= rnn_half_window[i];
224
+ }
225
+ }
226
+
227
+ struct RNNModel {
228
+ /* Set either blob or const_blob. */
229
+ const void *const_blob;
230
+ void *blob;
231
+ int blob_len;
232
+ FILE *file;
233
+ };
234
+
235
+ RNNModel *rnnoise_model_from_buffer(const void *ptr, int len) {
236
+ RNNModel *model;
237
+ model = malloc(sizeof(*model));
238
+ model->blob = NULL;
239
+ model->const_blob = ptr;
240
+ model->blob_len = len;
241
+ return model;
242
+ }
243
+
244
+ RNNModel *rnnoise_model_from_filename(const char *filename) {
245
+ RNNModel *model;
246
+ FILE *f = fopen(filename, "rb");
247
+ model = rnnoise_model_from_file(f);
248
+ model->file = f;
249
+ return model;
250
+ }
251
+
252
+ RNNModel *rnnoise_model_from_file(FILE *f) {
253
+ RNNModel *model;
254
+ model = malloc(sizeof(*model));
255
+ model->file = NULL;
256
+
257
+ fseek(f, 0, SEEK_END);
258
+ model->blob_len = ftell(f);
259
+ fseek(f, 0, SEEK_SET);
260
+
261
+ model->const_blob = NULL;
262
+ model->blob = malloc(model->blob_len);
263
+ if (fread(model->blob, model->blob_len, 1, f) != 1)
264
+ {
265
+ rnnoise_model_free(model);
266
+ return NULL;
267
+ }
268
+ return model;
269
+ }
270
+
271
+ void rnnoise_model_free(RNNModel *model) {
272
+ if (model->file != NULL) fclose(model->file);
273
+ if (model->blob != NULL) free(model->blob);
274
+ free(model);
275
+ }
276
+
277
+ int rnnoise_get_size(void) {
278
+ return sizeof(DenoiseState);
279
+ }
280
+
281
+ int rnnoise_get_frame_size(void) {
282
+ return FRAME_SIZE;
283
+ }
284
+
285
+ int rnnoise_init(DenoiseState *st, RNNModel *model) {
286
+ memset(st, 0, sizeof(*st));
287
+ #if !TRAINING
288
+ if (model != NULL) {
289
+ WeightArray *list;
290
+ int ret = 1;
291
+ parse_weights(&list, model->blob ? model->blob : model->const_blob, model->blob_len);
292
+ if (list != NULL) {
293
+ ret = init_rnnoise(&st->model, list);
294
+ opus_free(list);
295
+ }
296
+ if (ret != 0) return -1;
297
+ }
298
+ #ifndef USE_WEIGHTS_FILE
299
+ else {
300
+ int ret = init_rnnoise(&st->model, rnnoise_arrays);
301
+ if (ret != 0) return -1;
302
+ }
303
+ #endif
304
+ st->arch = rnn_select_arch();
305
+ #else
306
+ (void)model;
307
+ #endif
308
+ return 0;
309
+ }
310
+
311
+ DenoiseState *rnnoise_create(RNNModel *model) {
312
+ int ret;
313
+ DenoiseState *st;
314
+ st = malloc(rnnoise_get_size());
315
+ ret = rnnoise_init(st, model);
316
+ if (ret != 0) {
317
+ free(st);
318
+ return NULL;
319
+ }
320
+ return st;
321
+ }
322
+
323
+ void rnnoise_destroy(DenoiseState *st) {
324
+ free(st);
325
+ }
326
+
327
+ #if TRAINING
328
+ extern int lowpass;
329
+ extern int band_lp;
330
+ #endif
331
+
332
+ void rnn_frame_analysis(DenoiseState *st, kiss_fft_cpx *X, float *Ex, const float *in) {
333
+ int i;
334
+ float x[WINDOW_SIZE];
335
+ RNN_COPY(x, st->analysis_mem, FRAME_SIZE);
336
+ for (i=0;i<FRAME_SIZE;i++) x[FRAME_SIZE + i] = in[i];
337
+ RNN_COPY(st->analysis_mem, in, FRAME_SIZE);
338
+ apply_window(x);
339
+ forward_transform(X, x);
340
+ #if TRAINING
341
+ for (i=lowpass;i<FREQ_SIZE;i++)
342
+ X[i].r = X[i].i = 0;
343
+ #endif
344
+ compute_band_energy(Ex, X);
345
+ }
346
+
347
+ int rnn_compute_frame_features(DenoiseState *st, kiss_fft_cpx *X, kiss_fft_cpx *P,
348
+ float *Ex, float *Ep, float *Exp, float *features, const float *in) {
349
+ int i;
350
+ float E = 0;
351
+ float Ly[NB_BANDS];
352
+ float p[WINDOW_SIZE];
353
+ float pitch_buf[PITCH_BUF_SIZE>>1];
354
+ int pitch_index;
355
+ float gain;
356
+ float *(pre[1]);
357
+ float follow, logMax;
358
+ rnn_frame_analysis(st, X, Ex, in);
359
+ RNN_MOVE(st->pitch_buf, &st->pitch_buf[FRAME_SIZE], PITCH_BUF_SIZE-FRAME_SIZE);
360
+ RNN_COPY(&st->pitch_buf[PITCH_BUF_SIZE-FRAME_SIZE], in, FRAME_SIZE);
361
+ pre[0] = &st->pitch_buf[0];
362
+ rnn_pitch_downsample(pre, pitch_buf, PITCH_BUF_SIZE, 1);
363
+ rnn_pitch_search(pitch_buf+(PITCH_MAX_PERIOD>>1), pitch_buf, PITCH_FRAME_SIZE,
364
+ PITCH_MAX_PERIOD-3*PITCH_MIN_PERIOD, &pitch_index);
365
+ pitch_index = PITCH_MAX_PERIOD-pitch_index;
366
+
367
+ gain = rnn_remove_doubling(pitch_buf, PITCH_MAX_PERIOD, PITCH_MIN_PERIOD,
368
+ PITCH_FRAME_SIZE, &pitch_index, st->last_period, st->last_gain);
369
+ st->last_period = pitch_index;
370
+ st->last_gain = gain;
371
+ for (i=0;i<WINDOW_SIZE;i++)
372
+ p[i] = st->pitch_buf[PITCH_BUF_SIZE-WINDOW_SIZE-pitch_index+i];
373
+ apply_window(p);
374
+ forward_transform(P, p);
375
+ compute_band_energy(Ep, P);
376
+ compute_band_corr(Exp, X, P);
377
+ for (i=0;i<NB_BANDS;i++) Exp[i] = Exp[i]/sqrt(.001+Ex[i]*Ep[i]);
378
+ dct(&features[NB_BANDS], Exp);
379
+ features[2*NB_BANDS] = .01*(pitch_index-300);
380
+ logMax = -2;
381
+ follow = -2;
382
+ for (i=0;i<NB_BANDS;i++) {
383
+ Ly[i] = log10(1e-2+Ex[i]);
384
+ Ly[i] = MAX16(logMax-7, MAX16(follow-1.5, Ly[i]));
385
+ logMax = MAX16(logMax, Ly[i]);
386
+ follow = MAX16(follow-1.5, Ly[i]);
387
+ E += Ex[i];
388
+ }
389
+ if (!TRAINING && E < 0.04) {
390
+ /* If there's no audio, avoid messing up the state. */
391
+ RNN_CLEAR(features, NB_FEATURES);
392
+ return 1;
393
+ }
394
+ dct(features, Ly);
395
+ features[0] -= 12;
396
+ features[1] -= 4;
397
+ return TRAINING && E < 0.1;
398
+ }
399
+
400
+ static void frame_synthesis(DenoiseState *st, float *out, const kiss_fft_cpx *y) {
401
+ float x[WINDOW_SIZE];
402
+ int i;
403
+ inverse_transform(x, y);
404
+ apply_window(x);
405
+ for (i=0;i<FRAME_SIZE;i++) out[i] = x[i] + st->synthesis_mem[i];
406
+ RNN_COPY(st->synthesis_mem, &x[FRAME_SIZE], FRAME_SIZE);
407
+ }
408
+
409
+ void rnn_biquad(float *y, float mem[2], const float *x, const float *b, const float *a, int N) {
410
+ int i;
411
+ for (i=0;i<N;i++) {
412
+ float xi, yi;
413
+ xi = x[i];
414
+ yi = x[i] + mem[0];
415
+ mem[0] = mem[1] + (b[0]*(double)xi - a[0]*(double)yi);
416
+ mem[1] = (b[1]*(double)xi - a[1]*(double)yi);
417
+ y[i] = yi;
418
+ }
419
+ }
420
+
421
+ void rnn_pitch_filter(kiss_fft_cpx *X, const kiss_fft_cpx *P, const float *Ex, const float *Ep,
422
+ const float *Exp, const float *g) {
423
+ int i;
424
+ float r[NB_BANDS];
425
+ float rf[FREQ_SIZE] = {0};
426
+ float newE[NB_BANDS];
427
+ float norm[NB_BANDS];
428
+ float normf[FREQ_SIZE]={0};
429
+ for (i=0;i<NB_BANDS;i++) {
430
+ #if 0
431
+ if (Exp[i]>g[i]) r[i] = 1;
432
+ else r[i] = Exp[i]*(1-g[i])/(.001 + g[i]*(1-Exp[i]));
433
+ r[i] = MIN16(1, MAX16(0, r[i]));
434
+ #else
435
+ if (Exp[i]>g[i]) r[i] = 1;
436
+ else r[i] = SQUARE(Exp[i])*(1-SQUARE(g[i]))/(.001 + SQUARE(g[i])*(1-SQUARE(Exp[i])));
437
+ r[i] = sqrt(MIN16(1, MAX16(0, r[i])));
438
+ #endif
439
+ r[i] *= sqrt(Ex[i]/(1e-8+Ep[i]));
440
+ }
441
+ interp_band_gain(rf, r);
442
+ for (i=0;i<FREQ_SIZE;i++) {
443
+ X[i].r += rf[i]*P[i].r;
444
+ X[i].i += rf[i]*P[i].i;
445
+ }
446
+ compute_band_energy(newE, X);
447
+ for (i=0;i<NB_BANDS;i++) {
448
+ norm[i] = sqrt(Ex[i]/(1e-8+newE[i]));
449
+ }
450
+ interp_band_gain(normf, norm);
451
+ for (i=0;i<FREQ_SIZE;i++) {
452
+ X[i].r *= normf[i];
453
+ X[i].i *= normf[i];
454
+ }
455
+ }
456
+
457
+ float rnnoise_process_frame(DenoiseState *st, float *out, const float *in) {
458
+ int i;
459
+ kiss_fft_cpx X[FREQ_SIZE];
460
+ kiss_fft_cpx P[FREQ_SIZE];
461
+ float x[FRAME_SIZE];
462
+ float Ex[NB_BANDS], Ep[NB_BANDS];
463
+ float Exp[NB_BANDS];
464
+ float features[NB_FEATURES];
465
+ float g[NB_BANDS];
466
+ float gf[FREQ_SIZE]={1};
467
+ float vad_prob = 0;
468
+ int silence;
469
+ static const float a_hp[2] = {-1.99599, 0.99600};
470
+ static const float b_hp[2] = {-2, 1};
471
+ rnn_biquad(x, st->mem_hp_x, in, b_hp, a_hp, FRAME_SIZE);
472
+ silence = rnn_compute_frame_features(st, X, P, Ex, Ep, Exp, features, x);
473
+
474
+ if (!silence) {
475
+ #if !TRAINING
476
+ compute_rnn(&st->model, &st->rnn, g, &vad_prob, features, st->arch);
477
+ #endif
478
+ rnn_pitch_filter(st->delayed_X, st->delayed_P, st->delayed_Ex, st->delayed_Ep, st->delayed_Exp, g);
479
+ for (i=0;i<NB_BANDS;i++) {
480
+ float alpha = .6f;
481
+ /* Cap the decay at 0.6 per frame, corresponding to an RT60 of 135 ms.
482
+ That avoids unnaturally quick attenuation. */
483
+ g[i] = MAX16(g[i], alpha*st->lastg[i]);
484
+ /* Compensate for energy change across frame when computing the threshold gain.
485
+ Avoids leaking noise when energy increases (e.g. transient noise). */
486
+ st->lastg[i] = MIN16(1.f, g[i]*(st->delayed_Ex[i]+1e-3)/(Ex[i]+1e-3));
487
+ }
488
+ interp_band_gain(gf, g);
489
+ #if 1
490
+ for (i=0;i<FREQ_SIZE;i++) {
491
+ st->delayed_X[i].r *= gf[i];
492
+ st->delayed_X[i].i *= gf[i];
493
+ }
494
+ #endif
495
+ }
496
+ frame_synthesis(st, out, st->delayed_X);
497
+
498
+ RNN_COPY(st->delayed_X, X, FREQ_SIZE);
499
+ RNN_COPY(st->delayed_P, P, FREQ_SIZE);
500
+ RNN_COPY(st->delayed_Ex, Ex, NB_BANDS);
501
+ RNN_COPY(st->delayed_Ep, Ep, NB_BANDS);
502
+ RNN_COPY(st->delayed_Exp, Exp, NB_BANDS);
503
+ return vad_prob;
504
+ }
505
+
cpp/src/rnnoise/denoise.h ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2017 Mozilla */
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
+ #include "rnnoise.h"
28
+ #include "kiss_fft.h"
29
+ #include "nnet.h"
30
+
31
+ #define FRAME_SIZE 480
32
+ #define WINDOW_SIZE (2*FRAME_SIZE)
33
+ #define FREQ_SIZE (FRAME_SIZE + 1)
34
+ #define NB_BANDS 32
35
+ #define NB_FEATURES (2*NB_BANDS+1)
36
+
37
+
38
+ #define PITCH_MIN_PERIOD 60
39
+ #define PITCH_MAX_PERIOD 768
40
+ #define PITCH_FRAME_SIZE 960
41
+ #define PITCH_BUF_SIZE (PITCH_MAX_PERIOD+PITCH_FRAME_SIZE)
42
+
43
+ extern const WeightArray rnnoise_arrays[];
44
+
45
+ extern const int eband20ms[];
46
+
47
+
48
+ void rnn_biquad(float *y, float mem[2], const float *x, const float *b, const float *a, int N);
49
+
50
+ void rnn_pitch_filter(kiss_fft_cpx *X, const kiss_fft_cpx *P, const float *Ex, const float *Ep,
51
+ const float *Exp, const float *g);
52
+
53
+ void rnn_frame_analysis(DenoiseState *st, kiss_fft_cpx *X, float *Ex, const float *in);
54
+
55
+ int rnn_compute_frame_features(DenoiseState *st, kiss_fft_cpx *X, kiss_fft_cpx *P,
56
+ float *Ex, float *Ep, float *Exp, float *features, const float *in);
cpp/src/rnnoise/dump_features.c ADDED
@@ -0,0 +1,499 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2024 Jean-Marc Valin
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
+
33
+ #include <stdio.h>
34
+ #include <math.h>
35
+ #include <stdlib.h>
36
+ #include <unistd.h>
37
+ #include <errno.h>
38
+ #include "rnnoise.h"
39
+ #include "common.h"
40
+ #include "denoise.h"
41
+ #include "arch.h"
42
+ #include "kiss_fft.h"
43
+ #include "src/_kiss_fft_guts.h"
44
+
45
+ int lowpass = FREQ_SIZE;
46
+ int band_lp = NB_BANDS;
47
+
48
+ #define SEQUENCE_LENGTH 2000
49
+ #define SEQUENCE_SAMPLES (SEQUENCE_LENGTH*FRAME_SIZE)
50
+
51
+ #define RIR_FFT_SIZE 65536
52
+ #define RIR_MAX_DURATION (RIR_FFT_SIZE/2)
53
+ #define FILENAME_MAX_SIZE 1000
54
+
55
+ struct rir_list {
56
+ int nb_rirs;
57
+ int block_size;
58
+ kiss_fft_state *fft;
59
+ kiss_fft_cpx **rir;
60
+ kiss_fft_cpx **early;
61
+ };
62
+
63
+ kiss_fft_cpx *load_rir(const char *rir_file, kiss_fft_state *fft, int early) {
64
+ kiss_fft_cpx *x, *X;
65
+ float rir[RIR_MAX_DURATION];
66
+ int len;
67
+ int i;
68
+ FILE *f;
69
+ f = fopen(rir_file, "rb");
70
+ if (f==NULL) {
71
+ fprintf(stderr, "cannot open %s: %s\n", rir_file, strerror(errno));
72
+ exit(1);
73
+ }
74
+ x = (kiss_fft_cpx*)calloc(fft->nfft, sizeof(*x));
75
+ X = (kiss_fft_cpx*)calloc(fft->nfft, sizeof(*X));
76
+ len = fread(rir, sizeof(*rir), RIR_MAX_DURATION, f);
77
+ if (early) {
78
+ for (i=0;i<240;i++) {
79
+ rir[480+i] *= (1 - i/240.f);
80
+ }
81
+ RNN_CLEAR(&rir[240+480], RIR_MAX_DURATION-240-480);
82
+ }
83
+ for (i=0;i<len;i++) x[i].r = rir[i];
84
+ rnn_fft_c(fft, x, X);
85
+ free(x);
86
+ fclose(f);
87
+ return X;
88
+ }
89
+
90
+ void load_rir_list(const char *list_file, struct rir_list *rirs) {
91
+ int allocated;
92
+ char rir_filename[FILENAME_MAX_SIZE];
93
+ FILE *f;
94
+ f = fopen(list_file, "rb");
95
+ if (f==NULL) {
96
+ fprintf(stderr, "cannot open %s: %s\n", list_file, strerror(errno));
97
+ exit(1);
98
+ }
99
+ rirs->nb_rirs = 0;
100
+ allocated = 2;
101
+ rirs->fft = rnn_fft_alloc_twiddles(RIR_FFT_SIZE, NULL, NULL, NULL, 0);
102
+ rirs->rir = malloc(allocated*sizeof(rirs->rir[0]));
103
+ rirs->early = malloc(allocated*sizeof(rirs->early[0]));
104
+ while (fgets(rir_filename, FILENAME_MAX_SIZE, f) != NULL) {
105
+ /* Chop trailing newline. */
106
+ rir_filename[strcspn(rir_filename, "\n")] = 0;
107
+ if (rirs->nb_rirs+1 > allocated) {
108
+ allocated *= 2;
109
+ rirs->rir = realloc(rirs->rir, allocated*sizeof(rirs->rir[0]));
110
+ rirs->early = realloc(rirs->early, allocated*sizeof(rirs->early[0]));
111
+ }
112
+ rirs->rir[rirs->nb_rirs] = load_rir(rir_filename, rirs->fft, 0);
113
+ rirs->early[rirs->nb_rirs] = load_rir(rir_filename, rirs->fft, 1);
114
+ rirs->nb_rirs++;
115
+ }
116
+ fclose(f);
117
+ }
118
+
119
+ void rir_filter_sequence(const struct rir_list *rirs, float *audio, int rir_id, int early) {
120
+ int i;
121
+ kiss_fft_cpx x[RIR_FFT_SIZE] = {{0,0}};
122
+ kiss_fft_cpx y[RIR_FFT_SIZE] = {{0,0}};
123
+ kiss_fft_cpx X[RIR_FFT_SIZE] = {{0,0}};
124
+ const kiss_fft_cpx *Y;
125
+ if (early) Y = rirs->early[rir_id];
126
+ else Y = rirs->rir[rir_id];
127
+ i=0;
128
+ while (i<SEQUENCE_SAMPLES) {
129
+ int j;
130
+ RNN_COPY(&x[0], &x[RIR_FFT_SIZE/2], RIR_FFT_SIZE/2);
131
+ for (j=0;j<IMIN(SEQUENCE_SAMPLES-i, RIR_FFT_SIZE/2);j++) x[RIR_FFT_SIZE/2+j].r = audio[i+j];
132
+ for (;j<RIR_FFT_SIZE/2;j++) x[RIR_FFT_SIZE/2+j].r = 0;
133
+ rnn_fft_c(rirs->fft, x, X);
134
+ for (j=0;j<RIR_FFT_SIZE;j++) {
135
+ kiss_fft_cpx tmp;
136
+ C_MUL(tmp, X[j], Y[j]);
137
+ X[j].r = tmp.r*RIR_FFT_SIZE/2;
138
+ X[j].i = tmp.i*RIR_FFT_SIZE/2;
139
+ }
140
+ rnn_ifft_c(rirs->fft, X, y);
141
+ for (j=0;j<IMIN(SEQUENCE_SAMPLES-i, RIR_FFT_SIZE/2);j++) audio[i+j] = y[RIR_FFT_SIZE/2+j].r;
142
+ i += RIR_FFT_SIZE/2;
143
+ }
144
+ }
145
+
146
+ static unsigned rand_lcg(unsigned *seed) {
147
+ *seed = 1664525**seed + 1013904223;
148
+ return *seed;
149
+ }
150
+
151
+ static float uni_rand() {
152
+ return rand()/(double)RAND_MAX-.5;
153
+ }
154
+
155
+ static float randf(float f) {
156
+ return f*rand()/(double)RAND_MAX;
157
+ }
158
+
159
+ static void rand_filt(float *a) {
160
+ if (rand()%3!=0) {
161
+ a[0] = a[1] = 0;
162
+ }
163
+ else if (uni_rand()>0) {
164
+ float r, theta;
165
+ r = rand()/(double)RAND_MAX;
166
+ r = .7*r*r;
167
+ theta = rand()/(double)RAND_MAX;
168
+ theta = M_PI*theta*theta;
169
+ a[0] = -2*r*cos(theta);
170
+ a[1] = r*r;
171
+ } else {
172
+ float r0,r1;
173
+ r0 = 1.4*uni_rand();
174
+ r1 = 1.4*uni_rand();
175
+ a[0] = -r0-r1;
176
+ a[1] = r0*r1;
177
+ }
178
+ }
179
+
180
+ static void rand_resp(float *a, float *b) {
181
+ rand_filt(a);
182
+ rand_filt(b);
183
+ }
184
+
185
+ short speech16[SEQUENCE_LENGTH*FRAME_SIZE];
186
+ short noise16[SEQUENCE_LENGTH*FRAME_SIZE];
187
+ short fgnoise16[SEQUENCE_LENGTH*FRAME_SIZE];
188
+ float x[SEQUENCE_LENGTH*FRAME_SIZE];
189
+ float n[SEQUENCE_LENGTH*FRAME_SIZE];
190
+ float fn[SEQUENCE_LENGTH*FRAME_SIZE];
191
+ float xn[SEQUENCE_LENGTH*FRAME_SIZE];
192
+
193
+ #define P00 0.99f
194
+ #define P01 0.01f
195
+ #define P10 0.01f
196
+ #define P11 0.99f
197
+ #define LOGIT_SCALE 0.5f
198
+
199
+ static void viterbi_vad(const float *E, int *vad) {
200
+ int i;
201
+ float Enoise, Esig;
202
+ int back[SEQUENCE_LENGTH][2];
203
+ float curr;
204
+ Enoise = Esig = 1e-30;
205
+ for (i=0;i<SEQUENCE_LENGTH;i++) {
206
+ Esig += E[i]*E[i];
207
+ }
208
+ Esig = sqrt(Esig/SEQUENCE_LENGTH);
209
+ for (i=0;i<SEQUENCE_LENGTH;i++) {
210
+ Enoise += 1.f/(1e-8*Esig*Esig + E[i]*E[i]);
211
+ }
212
+ Enoise = 1.f/sqrt(Enoise/SEQUENCE_LENGTH);
213
+ curr = 0.5;
214
+ for (i=0;i<SEQUENCE_LENGTH;i++) {
215
+ float p0, pspeech, pnoise;
216
+ float prior;
217
+ p0 = (log(1e-15+E[i]) - log(Enoise))/(.01 + log(Esig) - log(Enoise));
218
+ p0 = MIN16(.9f, MAX16(.1f, p0));
219
+ p0 = 1.f/(1.f + pow((1.f-p0)/p0, LOGIT_SCALE));
220
+ if (curr*P11 > (1-curr)*P01) {
221
+ back[i][1] = 1;
222
+ prior = curr*P11;
223
+ } else {
224
+ back[i][1] = 0;
225
+ prior = (1-curr)*P01;
226
+ }
227
+ pspeech = prior*p0;
228
+
229
+ if ((1-curr)*P00 > curr*P10) {
230
+ back[i][0] = 0;
231
+ prior = (1-curr)*P00;
232
+ } else {
233
+ back[i][0] = 1;
234
+ prior = curr*P10;
235
+ }
236
+ pnoise = prior*(1-p0);
237
+ curr = pspeech / (pspeech + pnoise);
238
+ /*printf("%f ", curr);*/
239
+ }
240
+ vad[SEQUENCE_LENGTH-1] = curr > .5;
241
+ for (i=SEQUENCE_LENGTH-2;i>=0;i--) {
242
+ if (vad[i+1]) {
243
+ vad[i] = back[i+1][1];
244
+ } else {
245
+ vad[i] = back[i+1][0];
246
+ }
247
+ }
248
+ for (i=0;i<SEQUENCE_LENGTH-1;i++) {
249
+ if (vad[i+1]) vad[i] = 1;
250
+ }
251
+ for (i=SEQUENCE_LENGTH-1;i>=1;i--) {
252
+ if (vad[i-1]) vad[i] = 1;
253
+ }
254
+ }
255
+
256
+ static void clear_vad(float *x, int *vad) {
257
+ int i;
258
+ int active = vad[0];
259
+ for (i=0;i<SEQUENCE_LENGTH;i++) {
260
+ if (!active) {
261
+ if (i<SEQUENCE_LENGTH-1 && vad[i+1]) {
262
+ int j;
263
+ for (j=0;j<FRAME_SIZE;j++) x[i*FRAME_SIZE+j] *= j/(float)FRAME_SIZE;
264
+ active = 1;
265
+ } else {
266
+ RNN_CLEAR(&x[i*FRAME_SIZE], FRAME_SIZE);
267
+ }
268
+ } else {
269
+ if (i>=1 && vad[i]==0 && vad[i-1]==0) {
270
+ int j;
271
+ for (j=0;j<FRAME_SIZE;j++) x[i*FRAME_SIZE+j] *= 1.f - j/(float)FRAME_SIZE;
272
+ active = 0;
273
+ }
274
+ }
275
+ }
276
+ /*printf("\n");
277
+ for (i=0;i<SEQUENCE_LENGTH;i++) {
278
+ printf("%d ", vad[i]);
279
+ }
280
+ printf("\n");*/
281
+ }
282
+
283
+ static float weighted_rms(float *x) {
284
+ int i;
285
+ float tmp[SEQUENCE_SAMPLES];
286
+ float weighting_b[2] = {-2.f, 1.f};
287
+ float weighting_a[2] = {-1.89f, .895f};
288
+ float mem[2] = {0};
289
+ float mse = 1e-15f;
290
+ rnn_biquad(tmp, mem, x, weighting_b, weighting_a, SEQUENCE_SAMPLES);
291
+ for (i=0;i<SEQUENCE_SAMPLES;i++) mse += tmp[i]*tmp[i];
292
+ return 0.9506*sqrt(mse/SEQUENCE_SAMPLES);
293
+ }
294
+
295
+ int main(int argc, char **argv) {
296
+ int i, j;
297
+ int count=0;
298
+ static const float a_hp[2] = {-1.99599, 0.99600};
299
+ static const float b_hp[2] = {-2, 1};
300
+ float a_noise[2] = {0};
301
+ float b_noise[2] = {0};
302
+ float a_fgnoise[2] = {0};
303
+ float b_fgnoise[2] = {0};
304
+ float a_sig[2] = {0};
305
+ float b_sig[2] = {0};
306
+ float speech_gain = 1, noise_gain = 1, fgnoise_gain = 1;
307
+ FILE *f1, *f2, *f3, *fout;
308
+ long speech_length, noise_length, fgnoise_length;
309
+ int maxCount;
310
+ unsigned seed;
311
+ DenoiseState *st;
312
+ DenoiseState *noisy;
313
+ char *argv0;
314
+ char *rir_filename = NULL;
315
+ struct rir_list rirs;
316
+ seed = getpid();
317
+ srand(seed);
318
+ st = rnnoise_create(NULL);
319
+ noisy = rnnoise_create(NULL);
320
+ argv0 = argv[0];
321
+ while (argc>6) {
322
+ if (strcmp(argv[1], "-rir_list")==0) {
323
+ rir_filename = argv[2];
324
+ argv+=2;
325
+ argc-=2;
326
+ }
327
+ }
328
+ if (argc!=6) {
329
+ fprintf(stderr, "usage: %s [-rir_list list] <speech> <noise> <fg_noise> <output> <count>\n", argv0);
330
+ return 1;
331
+ }
332
+ f1 = fopen(argv[1], "rb");
333
+ f2 = fopen(argv[2], "rb");
334
+ f3 = fopen(argv[3], "rb");
335
+ fout = fopen(argv[4], "wb");
336
+
337
+ fseek(f1, 0, SEEK_END);
338
+ speech_length = ftell(f1);
339
+ fseek(f1, 0, SEEK_SET);
340
+
341
+ fseek(f2, 0, SEEK_END);
342
+ noise_length = ftell(f2);
343
+ fseek(f2, 0, SEEK_SET);
344
+
345
+ fseek(f3, 0, SEEK_END);
346
+ fgnoise_length = ftell(f3);
347
+ fseek(f3, 0, SEEK_SET);
348
+
349
+ maxCount = atoi(argv[5]);
350
+ if (rir_filename) load_rir_list(rir_filename, &rirs);
351
+ for (count=0;count<maxCount;count++) {
352
+ int rir_id;
353
+ int vad[SEQUENCE_LENGTH];
354
+ long speech_pos, noise_pos, fgnoise_pos;
355
+ int start_pos=0;
356
+ float E[SEQUENCE_LENGTH] = {0};
357
+ float mem[2]={0};
358
+ int frame;
359
+ int silence;
360
+ kiss_fft_cpx X[FREQ_SIZE], Y[FREQ_SIZE], P[WINDOW_SIZE];
361
+ float Ex[NB_BANDS], Ey[NB_BANDS], Ep[NB_BANDS];
362
+ float Exp[NB_BANDS];
363
+ float features[NB_FEATURES];
364
+ float g[NB_BANDS];
365
+ float speech_rms, noise_rms, fgnoise_rms;
366
+ if ((count%1000)==0) fprintf(stderr, "%d\r", count);
367
+ speech_pos = (rand_lcg(&seed)*2.3283e-10)*speech_length;
368
+ noise_pos = (rand_lcg(&seed)*2.3283e-10)*noise_length;
369
+ fgnoise_pos = (rand_lcg(&seed)*2.3283e-10)*fgnoise_length;
370
+ if (speech_pos > speech_length-(long)sizeof(speech16)) speech_pos = speech_length-sizeof(speech16);
371
+ if (noise_pos > noise_length-(long)sizeof(noise16)) noise_pos = noise_length-sizeof(noise16);
372
+ if (fgnoise_pos > fgnoise_length-(long)sizeof(fgnoise16)) fgnoise_pos = fgnoise_length-sizeof(fgnoise16);
373
+ speech_pos -= speech_pos&1;
374
+ noise_pos -= noise_pos&1;
375
+ fgnoise_pos -= fgnoise_pos&1;
376
+ fseek(f1, speech_pos, SEEK_SET);
377
+ fseek(f2, noise_pos, SEEK_SET);
378
+ fseek(f3, fgnoise_pos, SEEK_SET);
379
+ fread(speech16, sizeof(speech16), 1, f1);
380
+ fread(noise16, sizeof(noise16), 1, f2);
381
+ fread(fgnoise16, sizeof(fgnoise16), 1, f3);
382
+ if (rand()%4) start_pos = 0;
383
+ else start_pos = -(int)(1000*log(rand()/(float)RAND_MAX));
384
+ start_pos = IMIN(start_pos, SEQUENCE_LENGTH*FRAME_SIZE);
385
+
386
+ speech_gain = pow(10., (-45+randf(45.f)+randf(10.f))/20.);
387
+ noise_gain = pow(10., (-30+randf(40.f)+randf(15.f))/20.);
388
+ fgnoise_gain = pow(10., (-30+randf(40.f)+randf(15.f))/20.);
389
+ if (rand()%8==0) noise_gain = 0;
390
+ if (rand()%8!=0) fgnoise_gain = 0;
391
+ if (rand()%12==0) {
392
+ noise_gain *= 0.03;
393
+ fgnoise_gain *= 0.03;
394
+ }
395
+ noise_gain *= speech_gain;
396
+ fgnoise_gain *= speech_gain;
397
+ rand_resp(a_noise, b_noise);
398
+ rand_resp(a_fgnoise, b_fgnoise);
399
+ rand_resp(a_sig, b_sig);
400
+ lowpass = FREQ_SIZE * 3000./24000. * pow(50., rand()/(double)RAND_MAX);
401
+ for (i=0;i<NB_BANDS;i++) {
402
+ if (eband20ms[i] > lowpass) {
403
+ band_lp = i;
404
+ break;
405
+ }
406
+ }
407
+
408
+ for (frame=0;frame<SEQUENCE_LENGTH;frame++) {
409
+ E[frame] = 0;
410
+ for(j=0;j<FRAME_SIZE;j++) {
411
+ float s = speech16[frame*FRAME_SIZE+j];
412
+ E[frame] += s*s;
413
+ x[frame*FRAME_SIZE+j] = speech16[frame*FRAME_SIZE+j];
414
+ n[frame*FRAME_SIZE+j] = noise16[frame*FRAME_SIZE+j];
415
+ fn[frame*FRAME_SIZE+j] = fgnoise16[frame*FRAME_SIZE+j];
416
+ }
417
+ }
418
+ viterbi_vad(E, vad);
419
+
420
+ RNN_CLEAR(mem, 2);
421
+ rnn_biquad(x, mem, x, b_hp, a_hp, SEQUENCE_LENGTH*FRAME_SIZE);
422
+ RNN_CLEAR(mem, 2);
423
+ rnn_biquad(x, mem, x, b_sig, a_sig, SEQUENCE_LENGTH*FRAME_SIZE);
424
+ RNN_CLEAR(mem, 2);
425
+ rnn_biquad(n, mem, n, b_hp, a_hp, SEQUENCE_LENGTH*FRAME_SIZE);
426
+ RNN_CLEAR(mem, 2);
427
+ rnn_biquad(n, mem, n, b_noise, a_noise, SEQUENCE_LENGTH*FRAME_SIZE);
428
+ RNN_CLEAR(mem, 2);
429
+ rnn_biquad(fn, mem, fn, b_hp, a_hp, SEQUENCE_LENGTH*FRAME_SIZE);
430
+ RNN_CLEAR(mem, 2);
431
+ rnn_biquad(fn, mem, fn, b_fgnoise, a_fgnoise, SEQUENCE_LENGTH*FRAME_SIZE);
432
+
433
+ speech_rms = weighted_rms(x);
434
+ noise_rms = weighted_rms(n);
435
+ fgnoise_rms = weighted_rms(fn);
436
+
437
+ RNN_CLEAR(vad, start_pos/FRAME_SIZE);
438
+ clear_vad(x, vad);
439
+
440
+ speech_gain *= 3000.f/(1+speech_rms);
441
+ noise_gain *= 3000.f/(1+noise_rms);
442
+ fgnoise_gain *= 3000.f/(1+fgnoise_rms);
443
+ for (j=0;j<SEQUENCE_SAMPLES;j++) {
444
+ x[j] *= speech_gain;
445
+ n[j] *= noise_gain;
446
+ fn[j] *= fgnoise_gain;
447
+ xn[j] = x[j] + n[j] + fn[j];
448
+ }
449
+ if (rir_filename && rand()%2==0) {
450
+ rir_id = rand()%rirs.nb_rirs;
451
+ rir_filter_sequence(&rirs, x, rir_id, 1);
452
+ rir_filter_sequence(&rirs, xn, rir_id, 0);
453
+ }
454
+ if (rand()%4==0) {
455
+ /* Apply input clipping to 0 dBFS (don't clip target). */
456
+ for (j=0;j<SEQUENCE_SAMPLES;j++) {
457
+ xn[j] = MIN16(32767.f, MAX16(-32767.f, xn[j]));
458
+ }
459
+ }
460
+ if (rand()%2==0) {
461
+ /* Apply 16-bit quantization. */
462
+ for (j=0;j<SEQUENCE_SAMPLES;j++) {
463
+ xn[j] = floor(.5f + xn[j]);
464
+ }
465
+ }
466
+ for (frame=0;frame<SEQUENCE_LENGTH;frame++) {
467
+ float vad_target;
468
+ rnn_frame_analysis(st, Y, Ey, &x[frame*FRAME_SIZE]);
469
+ silence = rnn_compute_frame_features(noisy, X, P, Ex, Ep, Exp, features, &xn[frame*FRAME_SIZE]);
470
+ /*rnn_pitch_filter(X, P, Ex, Ep, Exp, g);*/
471
+ vad_target = vad[frame];
472
+ for (i=0;i<NB_BANDS;i++) {
473
+ g[i] = sqrt((Ey[i]+1e-3)/(Ex[i]+1e-3));
474
+ if (g[i] > 1) g[i] = 1;
475
+ if (silence || i > band_lp) g[i] = -1;
476
+ if (Ey[i] < 5e-2 && Ex[i] < 5e-2) g[i] = -1;
477
+ if (vad_target==0 && noise_gain==0 && fgnoise_gain==0) g[i] = -1;
478
+ }
479
+ #if 0
480
+ {
481
+ short tmp[FRAME_SIZE];
482
+ for (j=0;j<FRAME_SIZE;j++) tmp[j] = MIN16(32767, MAX16(-32767, xn[frame*FRAME_SIZE+j]));
483
+ fwrite(tmp, FRAME_SIZE, 2, fout);
484
+ }
485
+ #endif
486
+ #if 1
487
+ fwrite(features, sizeof(float), NB_FEATURES, fout);
488
+ fwrite(g, sizeof(float), NB_BANDS, fout);
489
+ fwrite(&vad_target, sizeof(float), 1, fout);
490
+ #endif
491
+ }
492
+ }
493
+
494
+ fclose(f1);
495
+ fclose(f2);
496
+ fclose(f3);
497
+ fclose(fout);
498
+ return 0;
499
+ }
cpp/src/rnnoise/dump_rnnoise_tables.c ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2017-2018 Mozilla
2
+ Copyright (c) 2023 Amazon */
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 <math.h>
33
+ #include <stdio.h>
34
+ #include "denoise.h"
35
+ #include "kiss_fft.h"
36
+
37
+ #define OVERLAP_SIZE FRAME_SIZE
38
+
39
+ int main(void) {
40
+ int i;
41
+ FILE *file;
42
+ kiss_fft_state *kfft;
43
+ float half_window[OVERLAP_SIZE];
44
+ float dct_table[NB_BANDS*NB_BANDS];
45
+
46
+ file=fopen("rnnoise_tables.c", "wb");
47
+ fprintf(file, "/* The contents of this file was automatically generated by dump_rnnoise_tables.c*/\n\n");
48
+ fprintf(file, "#ifdef HAVE_CONFIG_H\n");
49
+ fprintf(file, "#include \"config.h\"\n");
50
+ fprintf(file, "#endif\n");
51
+
52
+ fprintf(file, "#include \"kiss_fft.h\"\n\n");
53
+
54
+ kfft = rnn_fft_alloc_twiddles(WINDOW_SIZE, NULL, NULL, NULL, 0);
55
+
56
+ fprintf(file, "static const arch_fft_state arch_fft = {0, NULL};\n\n");
57
+
58
+ fprintf (file, "static const opus_int32 fft_bitrev[%d] = {\n", kfft->nfft);
59
+ for (i=0;i<kfft->nfft;i++)
60
+ fprintf (file, "%d,%c", kfft->bitrev[i],(i+16)%15==0?'\n':' ');
61
+ fprintf (file, "};\n\n");
62
+
63
+ fprintf (file, "static const kiss_twiddle_cpx fft_twiddles[%d] = {\n", kfft->nfft);
64
+ for (i=0;i<kfft->nfft;i++)
65
+ fprintf (file, "{%#0.9gf, %#0.9gf},%c", kfft->twiddles[i].r, kfft->twiddles[i].i,(i+3)%2==0?'\n':' ');
66
+ fprintf (file, "};\n\n");
67
+
68
+
69
+ fprintf(file, "const kiss_fft_state rnn_kfft = {\n");
70
+ fprintf(file, "%d, /* nfft */\n", kfft->nfft);
71
+ fprintf(file, "%#0.8gf, /* scale */\n", kfft->scale);
72
+ fprintf(file, "%d, /* shift */\n", kfft->shift);
73
+ fprintf(file, "{");
74
+ for (i=0;i<2*MAXFACTORS;i++) {
75
+ fprintf(file, "%d, ", kfft->factors[i]);
76
+ }
77
+ fprintf(file, "}, /* factors */\n");
78
+ fprintf(file, "fft_bitrev, /* bitrev*/\n");
79
+ fprintf(file, "fft_twiddles, /* twiddles*/\n");
80
+ fprintf(file, "(arch_fft_state *)&arch_fft, /* arch_fft*/\n");
81
+
82
+ fprintf(file, "};\n\n");
83
+
84
+ for (i=0;i<OVERLAP_SIZE;i++)
85
+ half_window[i] = sin(.5*M_PI*sin(.5*M_PI*(i+.5)/OVERLAP_SIZE) * sin(.5*M_PI*(i+.5)/OVERLAP_SIZE));
86
+ fprintf(file, "const float rnn_half_window[] = {\n");
87
+ for (i=0;i<OVERLAP_SIZE;i++)
88
+ fprintf (file, "%#0.9gf,%c", half_window[i],(i+6)%5==0?'\n':' ');
89
+ fprintf(file, "};\n\n");
90
+
91
+ for (i=0;i<NB_BANDS;i++) {
92
+ int j;
93
+ for (j=0;j<NB_BANDS;j++) {
94
+ dct_table[i*NB_BANDS + j] = cos((i+.5)*j*M_PI/NB_BANDS);
95
+ if (j==0) dct_table[i*NB_BANDS + j] *= sqrt(.5);
96
+ }
97
+ }
98
+ fprintf(file, "const float rnn_dct_table[] = {\n");
99
+ for (i=0;i<NB_BANDS*NB_BANDS;i++)
100
+ fprintf (file, "%#0.9gf,%c", dct_table[i],(i+6)%5==0?'\n':' ');
101
+ fprintf(file, "};\n");
102
+
103
+ fclose(file);
104
+ return 0;
105
+ }
cpp/src/rnnoise/kiss_fft.c ADDED
@@ -0,0 +1,601 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;i<N;i++)
59
+ {
60
+ kiss_fft_cpx t;
61
+ Fout2 = Fout + 1;
62
+ t = *Fout2;
63
+ C_SUB( *Fout2 , *Fout , t );
64
+ C_ADDTO( *Fout , t );
65
+ Fout += 2;
66
+ }
67
+ } else
68
+ #endif
69
+ {
70
+ opus_val16 tw;
71
+ tw = QCONST16(0.7071067812f, 15);
72
+ /* We know that m==4 here because the radix-2 is just after a radix-4 */
73
+ celt_assert(m==4);
74
+ for (i=0;i<N;i++)
75
+ {
76
+ kiss_fft_cpx t;
77
+ Fout2 = Fout + 4;
78
+ t = Fout2[0];
79
+ C_SUB( Fout2[0] , Fout[0] , t );
80
+ C_ADDTO( Fout[0] , t );
81
+
82
+ t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw);
83
+ t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw);
84
+ C_SUB( Fout2[1] , Fout[1] , t );
85
+ C_ADDTO( Fout[1] , t );
86
+
87
+ t.r = Fout2[2].i;
88
+ t.i = -Fout2[2].r;
89
+ C_SUB( Fout2[2] , Fout[2] , t );
90
+ C_ADDTO( Fout[2] , t );
91
+
92
+ t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw);
93
+ t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw);
94
+ C_SUB( Fout2[3] , Fout[3] , t );
95
+ C_ADDTO( Fout[3] , t );
96
+ Fout += 8;
97
+ }
98
+ }
99
+ }
100
+
101
+ static void kf_bfly4(
102
+ kiss_fft_cpx * Fout,
103
+ const size_t fstride,
104
+ const kiss_fft_state *st,
105
+ int m,
106
+ int N,
107
+ int mm
108
+ )
109
+ {
110
+ int i;
111
+
112
+ if (m==1)
113
+ {
114
+ /* Degenerate case where all the twiddles are 1. */
115
+ for (i=0;i<N;i++)
116
+ {
117
+ kiss_fft_cpx scratch0, scratch1;
118
+
119
+ C_SUB( scratch0 , *Fout, Fout[2] );
120
+ C_ADDTO(*Fout, Fout[2]);
121
+ C_ADD( scratch1 , Fout[1] , Fout[3] );
122
+ C_SUB( Fout[2], *Fout, scratch1 );
123
+ C_ADDTO( *Fout , scratch1 );
124
+ C_SUB( scratch1 , Fout[1] , Fout[3] );
125
+
126
+ Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i);
127
+ Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r);
128
+ Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i);
129
+ Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r);
130
+ Fout+=4;
131
+ }
132
+ } else {
133
+ int j;
134
+ kiss_fft_cpx scratch[6];
135
+ const kiss_twiddle_cpx *tw1,*tw2,*tw3;
136
+ const int m2=2*m;
137
+ const int m3=3*m;
138
+ kiss_fft_cpx * Fout_beg = Fout;
139
+ for (i=0;i<N;i++)
140
+ {
141
+ Fout = Fout_beg + i*mm;
142
+ tw3 = tw2 = tw1 = st->twiddles;
143
+ /* m is guaranteed to be a multiple of 4. */
144
+ for (j=0;j<m;j++)
145
+ {
146
+ C_MUL(scratch[0],Fout[m] , *tw1 );
147
+ C_MUL(scratch[1],Fout[m2] , *tw2 );
148
+ C_MUL(scratch[2],Fout[m3] , *tw3 );
149
+
150
+ C_SUB( scratch[5] , *Fout, scratch[1] );
151
+ C_ADDTO(*Fout, scratch[1]);
152
+ C_ADD( scratch[3] , scratch[0] , scratch[2] );
153
+ C_SUB( scratch[4] , scratch[0] , scratch[2] );
154
+ C_SUB( Fout[m2], *Fout, scratch[3] );
155
+ tw1 += fstride;
156
+ tw2 += fstride*2;
157
+ tw3 += fstride*3;
158
+ C_ADDTO( *Fout , scratch[3] );
159
+
160
+ Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i);
161
+ Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r);
162
+ Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i);
163
+ Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r);
164
+ ++Fout;
165
+ }
166
+ }
167
+ }
168
+ }
169
+
170
+
171
+ #ifndef RADIX_TWO_ONLY
172
+
173
+ static void kf_bfly3(
174
+ kiss_fft_cpx * Fout,
175
+ const size_t fstride,
176
+ const kiss_fft_state *st,
177
+ int m,
178
+ int N,
179
+ int mm
180
+ )
181
+ {
182
+ int i;
183
+ size_t k;
184
+ const size_t m2 = 2*m;
185
+ const kiss_twiddle_cpx *tw1,*tw2;
186
+ kiss_fft_cpx scratch[5];
187
+ kiss_twiddle_cpx epi3;
188
+
189
+ kiss_fft_cpx * Fout_beg = Fout;
190
+ #ifdef FIXED_POINT
191
+ /*epi3.r = -16384;*/ /* Unused */
192
+ epi3.i = -28378;
193
+ #else
194
+ epi3 = st->twiddles[fstride*m];
195
+ #endif
196
+ for (i=0;i<N;i++)
197
+ {
198
+ Fout = Fout_beg + i*mm;
199
+ tw1=tw2=st->twiddles;
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;i<N;i++)
260
+ {
261
+ Fout = Fout_beg + i*mm;
262
+ Fout0=Fout;
263
+ Fout1=Fout0+m;
264
+ Fout2=Fout0+2*m;
265
+ Fout3=Fout0+3*m;
266
+ Fout4=Fout0+4*m;
267
+
268
+ /* For non-custom modes, m is guaranteed to be a multiple of 4. */
269
+ for ( u=0; u<m; ++u ) {
270
+ scratch[0] = *Fout0;
271
+
272
+ C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
273
+ C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
274
+ C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
275
+ C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
276
+
277
+ C_ADD( scratch[7],scratch[1],scratch[4]);
278
+ C_SUB( scratch[10],scratch[1],scratch[4]);
279
+ C_ADD( scratch[8],scratch[2],scratch[3]);
280
+ C_SUB( scratch[9],scratch[2],scratch[3]);
281
+
282
+ Fout0->r = 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_int32 *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;j<p;j++)
332
+ {
333
+ *f = Fout+j;
334
+ f += fstride*in_stride;
335
+ }
336
+ } else {
337
+ int j;
338
+ for (j=0;j<p;j++)
339
+ {
340
+ compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
341
+ f += fstride*in_stride;
342
+ Fout += m;
343
+ }
344
+ }
345
+ }
346
+
347
+ /* facbuf is populated by p1,m1,p2,m2, ...
348
+ where
349
+ p[i] * m[i] = m[i-1]
350
+ m0 = n */
351
+ static
352
+ int kf_factor(int n,opus_int16 * facbuf)
353
+ {
354
+ int p=4;
355
+ int i;
356
+ int stages=0;
357
+ int nbak = n;
358
+
359
+ /*factor out powers of 4, powers of 2, then any remaining primes */
360
+ do {
361
+ while (n % p) {
362
+ switch (p) {
363
+ case 4: p = 2; break;
364
+ case 2: p = 3; break;
365
+ default: p += 2; break;
366
+ }
367
+ if (p>32000 || (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<stages/2;i++)
392
+ {
393
+ int tmp;
394
+ tmp = facbuf[2*i];
395
+ facbuf[2*i] = facbuf[2*(stages-i-1)];
396
+ facbuf[2*(stages-i-1)] = tmp;
397
+ }
398
+ for (i=0;i<stages;i++)
399
+ {
400
+ n /= facbuf[2*i];
401
+ facbuf[2*i+1] = n;
402
+ }
403
+ return 1;
404
+ }
405
+
406
+ static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
407
+ {
408
+ int i;
409
+ #ifdef FIXED_POINT
410
+ for (i=0;i<nfft;++i) {
411
+ opus_val32 phase = -i;
412
+ kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
413
+ }
414
+ #else
415
+ for (i=0;i<nfft;++i) {
416
+ const double pi=3.14159265358979323846264338327;
417
+ double phase = ( -2*pi /nfft ) * i;
418
+ kf_cexp(twiddles+i, phase );
419
+ }
420
+ #endif
421
+ }
422
+
423
+ int rnn_fft_alloc_arch_c(kiss_fft_state *st) {
424
+ (void)st;
425
+ return 0;
426
+ }
427
+
428
+ /*
429
+ *
430
+ * Allocates all necessary storage space for the fft and ifft.
431
+ * The return value is a contiguous block of memory. As such,
432
+ * It can be freed with free().
433
+ * */
434
+ kiss_fft_state *rnn_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,
435
+ const kiss_fft_state *base, int arch)
436
+ {
437
+ kiss_fft_state *st=NULL;
438
+ size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
439
+
440
+ if ( lenmem==NULL ) {
441
+ st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded );
442
+ }else{
443
+ if (mem != NULL && *lenmem >= memneeded)
444
+ st = (kiss_fft_state*)mem;
445
+ *lenmem = memneeded;
446
+ }
447
+ if (st) {
448
+ opus_int32 *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<<st->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<<st->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_int32*)KISS_FFT_MALLOC(sizeof(opus_int32)*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_int32*)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]<<shift,st,m, fstride[i], m2);
552
+ break;
553
+ #ifndef RADIX_TWO_ONLY
554
+ case 3:
555
+ kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2);
556
+ break;
557
+ case 5:
558
+ kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2);
559
+ break;
560
+ #endif
561
+ }
562
+ m = m2;
563
+ }
564
+ }
565
+
566
+ void rnn_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
567
+ {
568
+ int i;
569
+ opus_val16 scale;
570
+ #ifdef FIXED_POINT
571
+ /* Allows us to scale with MULT16_32_Q16(), which is faster than
572
+ MULT16_32_Q15() on ARM. */
573
+ int scale_shift = st->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;i<st->nfft;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;i<st->nfft;i++)
595
+ fout[st->bitrev[i]] = fin[i];
596
+ for (i=0;i<st->nfft;i++)
597
+ fout[i].i = -fout[i].i;
598
+ rnn_fft_impl(st, fout);
599
+ for (i=0;i<st->nfft;i++)
600
+ fout[i].i = -fout[i].i;
601
+ }
cpp/src/rnnoise/kiss_fft.h ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 <stdlib.h>
33
+ #include <math.h>
34
+ #include "arch.h"
35
+
36
+ #include <stdlib.h>
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 <xmmintrin.h>
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_int32 *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
cpp/src/rnnoise/nnet.c ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018 Mozilla
2
+ 2008-2011 Octasic Inc.
3
+ 2012-2017 Jean-Marc Valin */
4
+ /*
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ - Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+
12
+ - Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #ifdef HAVE_CONFIG_H
30
+ #include "config.h"
31
+ #endif
32
+
33
+ #include <stdlib.h>
34
+ #include <math.h>
35
+ #include "opus_types.h"
36
+ #include "arch.h"
37
+ #include "nnet.h"
38
+ #include "common.h"
39
+ #include "vec.h"
40
+
41
+ #ifdef ENABLE_OSCE
42
+ #include "osce.h"
43
+ #endif
44
+
45
+ #ifdef NO_OPTIMIZATIONS
46
+ #if defined(_MSC_VER)
47
+ #pragma message ("Compiling without any vectorization. This code will be very slow")
48
+ #else
49
+ #warning Compiling without any vectorization. This code will be very slow
50
+ #endif
51
+ #endif
52
+
53
+
54
+ #define SOFTMAX_HACK
55
+
56
+
57
+ void compute_generic_dense(const LinearLayer *layer, float *output, const float *input, int activation, int arch)
58
+ {
59
+ compute_linear(layer, output, input, arch);
60
+ compute_activation(output, output, layer->nb_outputs, activation, arch);
61
+ }
62
+
63
+ #define MAX_RNN_NEURONS_ALL 1024
64
+
65
+ void compute_generic_gru(const LinearLayer *input_weights, const LinearLayer *recurrent_weights, float *state, const float *in, int arch)
66
+ {
67
+ int i;
68
+ int N;
69
+ float zrh[3*MAX_RNN_NEURONS_ALL];
70
+ float recur[3*MAX_RNN_NEURONS_ALL];
71
+ float *z;
72
+ float *r;
73
+ float *h;
74
+ celt_assert(3*recurrent_weights->nb_inputs == recurrent_weights->nb_outputs);
75
+ celt_assert(input_weights->nb_outputs == recurrent_weights->nb_outputs);
76
+ N = recurrent_weights->nb_inputs;
77
+ z = zrh;
78
+ r = &zrh[N];
79
+ h = &zrh[2*N];
80
+ celt_assert(recurrent_weights->nb_outputs <= 3*MAX_RNN_NEURONS_ALL);
81
+ celt_assert(in != state);
82
+ compute_linear(input_weights, zrh, in, arch);
83
+ compute_linear(recurrent_weights, recur, state, arch);
84
+ for (i=0;i<2*N;i++)
85
+ zrh[i] += recur[i];
86
+ compute_activation(zrh, zrh, 2*N, ACTIVATION_SIGMOID, arch);
87
+ for (i=0;i<N;i++)
88
+ h[i] += recur[2*N+i]*r[i];
89
+ compute_activation(h, h, N, ACTIVATION_TANH, arch);
90
+ for (i=0;i<N;i++)
91
+ h[i] = z[i]*state[i] + (1-z[i])*h[i];
92
+ for (i=0;i<N;i++)
93
+ state[i] = h[i];
94
+ }
95
+
96
+ void compute_glu(const LinearLayer *layer, float *output, const float *input, int arch)
97
+ {
98
+ int i;
99
+ float act2[MAX_INPUTS];
100
+ celt_assert(layer->nb_inputs == layer->nb_outputs);
101
+ compute_linear(layer, act2, input, arch);
102
+ compute_activation(act2, act2, layer->nb_outputs, ACTIVATION_SIGMOID, arch);
103
+ if (input == output) {
104
+ /* Give a vectorization hint to the compiler for the in-place case. */
105
+ for (i=0;i<layer->nb_outputs;i++) output[i] = output[i]*act2[i];
106
+ } else {
107
+ for (i=0;i<layer->nb_outputs;i++) output[i] = input[i]*act2[i];
108
+ }
109
+ }
110
+
111
+ #define MAX_CONV_INPUTS_ALL 1024
112
+
113
+ void compute_generic_conv1d(const LinearLayer *layer, float *output, float *mem, const float *input, int input_size, int activation, int arch)
114
+ {
115
+ float tmp[MAX_CONV_INPUTS_ALL];
116
+ celt_assert(input != output);
117
+ celt_assert(layer->nb_inputs <= MAX_CONV_INPUTS_ALL);
118
+ if (layer->nb_inputs!=input_size) RNN_COPY(tmp, mem, layer->nb_inputs-input_size);
119
+ RNN_COPY(&tmp[layer->nb_inputs-input_size], input, input_size);
120
+ compute_linear(layer, output, tmp, arch);
121
+ compute_activation(output, output, layer->nb_outputs, activation, arch);
122
+ if (layer->nb_inputs!=input_size) RNN_COPY(mem, &tmp[input_size], layer->nb_inputs-input_size);
123
+ }
cpp/src/rnnoise/nnet.h ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018 Mozilla
2
+ Copyright (c) 2017 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 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 NNET_H_
29
+ #define NNET_H_
30
+
31
+ #include <stddef.h>
32
+ #include "opus_types.h"
33
+
34
+ #define ACTIVATION_LINEAR 0
35
+ #define ACTIVATION_SIGMOID 1
36
+ #define ACTIVATION_TANH 2
37
+ #define ACTIVATION_RELU 3
38
+ #define ACTIVATION_SOFTMAX 4
39
+ #define ACTIVATION_SWISH 5
40
+
41
+ #define WEIGHT_BLOB_VERSION 0
42
+ #define WEIGHT_BLOCK_SIZE 64
43
+ typedef struct {
44
+ const char *name;
45
+ int type;
46
+ int size;
47
+ const void *data;
48
+ } WeightArray;
49
+
50
+ #define WEIGHT_TYPE_float 0
51
+ #define WEIGHT_TYPE_int 1
52
+ #define WEIGHT_TYPE_qweight 2
53
+ #define WEIGHT_TYPE_int8 3
54
+
55
+ typedef struct {
56
+ char head[4];
57
+ int version;
58
+ int type;
59
+ int size;
60
+ int block_size;
61
+ char name[44];
62
+ } WeightHead;
63
+
64
+ /* Generic sparse affine transformation. */
65
+ typedef struct {
66
+ const float *bias;
67
+ const float *subias;
68
+ const opus_int8 *weights;
69
+ const float *float_weights;
70
+ const int *weights_idx;
71
+ const float *diag;
72
+ const float *scale;
73
+ int nb_inputs;
74
+ int nb_outputs;
75
+ } LinearLayer;
76
+
77
+ /* Generic sparse affine transformation. */
78
+ typedef struct {
79
+ const float *bias;
80
+ const float *float_weights;
81
+ int in_channels;
82
+ int out_channels;
83
+ int ktime;
84
+ int kheight;
85
+ } Conv2dLayer;
86
+
87
+
88
+ /* Changes some symbol names to add the rnn_ prefix so we don't get conflicts with Opus. */
89
+ #define linear_init rnn_linear_init
90
+ #define conv2d_init rnn_conv2d_init
91
+ #define compute_generic_dense rnn_compute_generic_dense
92
+ #define compute_generic_gru rnn_compute_generic_gru
93
+ #define compute_generic_conv1d rnn_compute_generic_conv1d
94
+ #define compute_glu rnn_compute_glu
95
+
96
+ #define parse_weights rnn_parse_weights
97
+
98
+ #define compute_linear_c rnn_compute_linear_c
99
+ #define compute_activation_c rnn_compute_activation_c
100
+ #define compute_conv2d_c rnn_compute_conv2d_c
101
+ #define compute_linear_sse4_1 rnn_compute_linear_sse4_1
102
+ #define compute_activation_sse4_1 rnn_compute_activation_sse4_1
103
+ #define compute_conv2d_sse4_1 rnn_compute_conv2d_sse4_1
104
+ #define compute_linear_avx2 rnn_compute_linear_avx2
105
+ #define compute_activation_avx2 rnn_compute_activation_avx2
106
+ #define compute_conv2d_avx2 rnn_compute_conv2d_avx2
107
+
108
+
109
+ void compute_generic_dense(const LinearLayer *layer, float *output, const float *input, int activation, int arch);
110
+ void compute_generic_gru(const LinearLayer *input_weights, const LinearLayer *recurrent_weights, float *state, const float *in, int arch);
111
+ void compute_generic_conv1d(const LinearLayer *layer, float *output, float *mem, const float *input, int input_size, int activation, int arch);
112
+ void compute_glu(const LinearLayer *layer, float *output, const float *input, int arch);
113
+
114
+
115
+ int parse_weights(WeightArray **list, const void *data, int len);
116
+
117
+
118
+
119
+ int linear_init(LinearLayer *layer, const WeightArray *arrays,
120
+ const char *bias,
121
+ const char *subias,
122
+ const char *weights,
123
+ const char *float_weights,
124
+ const char *weights_idx,
125
+ const char *diag,
126
+ const char *scale,
127
+ int nb_inputs,
128
+ int nb_outputs);
129
+
130
+ int conv2d_init(Conv2dLayer *layer, const WeightArray *arrays,
131
+ const char *bias,
132
+ const char *float_weights,
133
+ int in_channels,
134
+ int out_channels,
135
+ int ktime,
136
+ int kheight);
137
+
138
+
139
+ void compute_linear_c(const LinearLayer *linear, float *out, const float *in);
140
+ void compute_activation_c(float *output, const float *input, int N, int activation);
141
+ void compute_conv2d_c(const Conv2dLayer *conv, float *out, float *mem, const float *in, int height, int hstride, int activation);
142
+
143
+ #ifdef RNN_ENABLE_X86_RTCD
144
+ #include "x86/dnn_x86.h"
145
+ #endif
146
+
147
+ #ifndef OVERRIDE_COMPUTE_LINEAR
148
+ #define compute_linear(linear, out, in, arch) ((void)(arch),compute_linear_c(linear, out, in))
149
+ #endif
150
+
151
+ #ifndef OVERRIDE_COMPUTE_ACTIVATION
152
+ #define compute_activation(output, input, N, activation, arch) ((void)(arch),compute_activation_c(output, input, N, activation))
153
+ #endif
154
+
155
+ #ifndef OVERRIDE_COMPUTE_CONV2D
156
+ #define compute_conv2d(conv, out, mem, in, height, hstride, activation, arch) ((void)(arch),compute_conv2d_c(conv, out, mem, in, height, hstride, activation))
157
+ #endif
158
+
159
+ #if defined(__x86_64__) && !defined(RNN_ENABLE_X86_RTCD) && !defined(__AVX2__)
160
+ #if defined(_MSC_VER)
161
+ #pragma message ("Only SSE and SSE2 are available. On newer machines, enable SSSE3/AVX/AVX2 to get better performance")
162
+ #else
163
+ #warning "Only SSE and SSE2 are available. On newer machines, enable SSSE3/AVX/AVX2 using -march= to get better performance"
164
+ #endif
165
+ #endif
166
+
167
+
168
+
169
+ #endif /* NNET_H_ */
cpp/src/rnnoise/nnet_arch.h ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018-2019 Mozilla
2
+ 2023 Amazon */
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 NNET_ARCH_H
29
+ #define NNET_ARCH_H
30
+
31
+ #include "nnet.h"
32
+ #include "arch.h"
33
+ #include "common.h"
34
+ #include "vec.h"
35
+
36
+ #define CAT_SUFFIX2(a,b) a ## b
37
+ #define CAT_SUFFIX(a,b) CAT_SUFFIX2(a, b)
38
+
39
+ #define RTCD_SUF(name) CAT_SUFFIX(name, RTCD_ARCH)
40
+
41
+ # if !defined(OPUS_GNUC_PREREQ)
42
+ # if defined(__GNUC__)&&defined(__GNUC_MINOR__)
43
+ # define OPUS_GNUC_PREREQ(_maj,_min) \
44
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
45
+ # else
46
+ # define OPUS_GNUC_PREREQ(_maj,_min) 0
47
+ # endif
48
+ # endif
49
+
50
+
51
+ /* Force vectorization on for DNN code because some of the loops rely on
52
+ compiler vectorization rather than explicitly using intrinsics. */
53
+ #if OPUS_GNUC_PREREQ(5,1)
54
+ #define GCC_POP_OPTIONS
55
+ #pragma GCC push_options
56
+ #pragma GCC optimize("tree-vectorize")
57
+ #endif
58
+
59
+
60
+ #define MAX_ACTIVATIONS (4096)
61
+
62
+ static OPUS_INLINE void vec_swish(float *y, const float *x, int N)
63
+ {
64
+ int i;
65
+ float tmp[MAX_ACTIVATIONS];
66
+ celt_assert(N <= MAX_ACTIVATIONS);
67
+ vec_sigmoid(tmp, x, N);
68
+ for (i=0;i<N;i++)
69
+ y[i] = x[i]*tmp[i];
70
+ }
71
+
72
+ static OPUS_INLINE float relu(float x)
73
+ {
74
+ return x < 0 ? 0 : x;
75
+ }
76
+
77
+ /*#define HIGH_ACCURACY */
78
+
79
+ void RTCD_SUF(compute_activation_)(float *output, const float *input, int N, int activation)
80
+ {
81
+ int i;
82
+ if (activation == ACTIVATION_SIGMOID) {
83
+ #ifdef HIGH_ACCURACY
84
+ for (int n=0; n<N; n++)
85
+ {
86
+ output[n] = 1.f / (1 + exp(-input[n]));
87
+ }
88
+ #else
89
+ vec_sigmoid(output, input, N);
90
+ #endif
91
+ } else if (activation == ACTIVATION_TANH) {
92
+ #ifdef HIGH_ACCURACY
93
+ for (int n=0; n<N; n++)
94
+ {
95
+ output[n] = tanh(input[n]);
96
+ }
97
+ #else
98
+ vec_tanh(output, input, N);
99
+ #endif
100
+ } else if (activation == ACTIVATION_SWISH) {
101
+ vec_swish(output, input, N);
102
+ } else if (activation == ACTIVATION_RELU) {
103
+ for (i=0;i<N;i++)
104
+ output[i] = relu(input[i]);
105
+ } else if (activation == ACTIVATION_SOFTMAX) {
106
+ #ifdef SOFTMAX_HACK
107
+ RNN_COPY(output, input, N);
108
+ /*for (i=0;i<N;i++)
109
+ output[i] = input[i];*/
110
+ #else
111
+ float sum = 0;
112
+ softmax(output, input, N);
113
+ for (i=0;i<N;i++) {
114
+ sum += output[i];
115
+ }
116
+ sum = 1.f/(sum+1e-30);
117
+ for (i=0;i<N;i++)
118
+ output[i] = sum*output[i];
119
+ #endif
120
+ } else {
121
+ celt_assert(activation == ACTIVATION_LINEAR);
122
+ if (input != output) {
123
+ for (i=0;i<N;i++)
124
+ output[i] = input[i];
125
+ }
126
+ }
127
+ }
128
+
129
+
130
+ void RTCD_SUF(compute_linear_) (const LinearLayer *linear, float *out, const float *in)
131
+ {
132
+ int i, M, N;
133
+ const float *bias;
134
+ celt_assert(in != out);
135
+ bias = linear->bias;
136
+ M = linear->nb_inputs;
137
+ N = linear->nb_outputs;
138
+ if (linear->float_weights != NULL) {
139
+ if (linear->weights_idx != NULL) sparse_sgemv8x4(out, linear->float_weights, linear->weights_idx, N, in);
140
+ else sgemv(out, linear->float_weights, N, M, N, in);
141
+ } else if (linear->weights != NULL) {
142
+ if (linear->weights_idx != NULL) sparse_cgemv8x4(out, linear->weights, linear->weights_idx, linear->scale, N, M, in);
143
+ else cgemv8x4(out, linear->weights, linear->scale, N, M, in);
144
+ /* Only use SU biases on for integer matrices on SU archs. */
145
+ #ifdef USE_SU_BIAS
146
+ bias = linear->subias;
147
+ #endif
148
+ }
149
+ else RNN_CLEAR(out, N);
150
+ if (bias != NULL) {
151
+ for (i=0;i<N;i++) out[i] += bias[i];
152
+ }
153
+ if (linear->diag) {
154
+ /* Diag is only used for GRU recurrent weights. */
155
+ celt_assert(3*M == N);
156
+ for (i=0;i<M;i++) {
157
+ out[i] += linear->diag[i]*in[i];
158
+ out[i+M] += linear->diag[i+M]*in[i];
159
+ out[i+2*M] += linear->diag[i+2*M]*in[i];
160
+ }
161
+ }
162
+ }
163
+
164
+ /* Computes non-padded convolution for input [ ksize1 x in_channels x (len2+ksize2) ],
165
+ kernel [ out_channels x in_channels x ksize1 x ksize2 ],
166
+ storing the output as [ out_channels x len2 ].
167
+ We assume that the output dimension along the ksize1 axis is 1,
168
+ i.e. processing one frame at a time. */
169
+ static void conv2d_float(float *out, const float *weights, int in_channels, int out_channels, int ktime, int kheight, const float *in, int height, int hstride)
170
+ {
171
+ int i;
172
+ int in_stride;
173
+ in_stride = height+kheight-1;
174
+ for (i=0;i<out_channels;i++) {
175
+ int m;
176
+ RNN_CLEAR(&out[i*hstride], height);
177
+ for (m=0;m<in_channels;m++) {
178
+ int t;
179
+ for (t=0;t<ktime;t++) {
180
+ int h;
181
+ for (h=0;h<kheight;h++) {
182
+ int j;
183
+ for (j=0;j<height;j++) {
184
+ out[i*hstride + j] += weights[i*in_channels*ktime*kheight + m*ktime*kheight + t*kheight + h] *
185
+ in[t*in_channels*in_stride + m*in_stride + j + h];
186
+ }
187
+ }
188
+ }
189
+ }
190
+ }
191
+ }
192
+
193
+ /* There's no intrinsics in this function (or the one above) because the gcc (and hopefully other compiler) auto-vectorizer is smart enough to
194
+ produce the right code by itself based on the compile flags. */
195
+ static void conv2d_3x3_float(float *out, const float *weights, int in_channels, int out_channels, const float *in, int height, int hstride)
196
+ {
197
+ int i;
198
+ int in_stride;
199
+ int kheight, ktime;
200
+ kheight = ktime = 3;
201
+ in_stride = height+kheight-1;
202
+ for (i=0;i<out_channels;i++) {
203
+ int m;
204
+ RNN_CLEAR(&out[i*hstride], height);
205
+ for (m=0;m<in_channels;m++) {
206
+ int j;
207
+ for (j=0;j<height;j++) {
208
+ /* Unrolled version of previous function -- compiler will figure out the indexing simplifications. */
209
+ out[i*hstride + j] += weights[i*in_channels*ktime*kheight + m*ktime*kheight + 0*kheight + 0]*in[0*in_channels*in_stride + m*in_stride + j + 0]
210
+ + weights[i*in_channels*ktime*kheight + m*ktime*kheight + 0*kheight + 1]*in[0*in_channels*in_stride + m*in_stride + j + 1]
211
+ + weights[i*in_channels*ktime*kheight + m*ktime*kheight + 0*kheight + 2]*in[0*in_channels*in_stride + m*in_stride + j + 2]
212
+ + weights[i*in_channels*ktime*kheight + m*ktime*kheight + 1*kheight + 0]*in[1*in_channels*in_stride + m*in_stride + j + 0]
213
+ + weights[i*in_channels*ktime*kheight + m*ktime*kheight + 1*kheight + 1]*in[1*in_channels*in_stride + m*in_stride + j + 1]
214
+ + weights[i*in_channels*ktime*kheight + m*ktime*kheight + 1*kheight + 2]*in[1*in_channels*in_stride + m*in_stride + j + 2]
215
+ + weights[i*in_channels*ktime*kheight + m*ktime*kheight + 2*kheight + 0]*in[2*in_channels*in_stride + m*in_stride + j + 0]
216
+ + weights[i*in_channels*ktime*kheight + m*ktime*kheight + 2*kheight + 1]*in[2*in_channels*in_stride + m*in_stride + j + 1]
217
+ + weights[i*in_channels*ktime*kheight + m*ktime*kheight + 2*kheight + 2]*in[2*in_channels*in_stride + m*in_stride + j + 2];
218
+ }
219
+ }
220
+ }
221
+ }
222
+
223
+ #define MAX_CONV2D_INPUTS 8192
224
+
225
+ void RTCD_SUF(compute_conv2d_)(const Conv2dLayer *conv, float *out, float *mem, const float *in, int height, int hstride, int activation)
226
+ {
227
+ int i;
228
+ const float *bias;
229
+ float in_buf[MAX_CONV2D_INPUTS];
230
+ int time_stride;
231
+ celt_assert(in != out);
232
+ time_stride = conv->in_channels*(height+conv->kheight-1);
233
+ celt_assert(conv->ktime*time_stride <= MAX_CONV2D_INPUTS);
234
+ RNN_COPY(in_buf, mem, (conv->ktime-1)*time_stride);
235
+ RNN_COPY(&in_buf[(conv->ktime-1)*time_stride], in, time_stride);
236
+ RNN_COPY(mem, &in_buf[time_stride], (conv->ktime-1)*time_stride);
237
+ bias = conv->bias;
238
+ if (conv->kheight == 3 && conv->ktime == 3)
239
+ conv2d_3x3_float(out, conv->float_weights, conv->in_channels, conv->out_channels, in_buf, height, hstride);
240
+ else
241
+ conv2d_float(out, conv->float_weights, conv->in_channels, conv->out_channels, conv->ktime, conv->kheight, in_buf, height, hstride);
242
+ if (bias != NULL) {
243
+ for (i=0;i<conv->out_channels;i++) {
244
+ int j;
245
+ for (j=0;j<height;j++) out[i*hstride+j] += bias[i];
246
+ }
247
+ }
248
+ for (i=0;i<conv->out_channels;i++) {
249
+ RTCD_SUF(compute_activation_)(&out[i*hstride], &out[i*hstride], height, activation);
250
+ }
251
+ }
252
+
253
+ #ifdef GCC_POP_OPTIONS
254
+ #pragma GCC pop_options
255
+ #endif
256
+
257
+ #endif
cpp/src/rnnoise/nnet_default.c ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018-2019 Mozilla
2
+ 2023 Amazon */
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
+
33
+ #define RTCD_ARCH c
34
+
35
+ #include "nnet_arch.h"
cpp/src/rnnoise/opus_types.h ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 <stdint.h>
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 <sys/types.h>
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 <sys/types.h>
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 <inttypes.h>
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 */
cpp/src/rnnoise/parse_lpcnet_weights.c ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2023 Amazon */
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
+ #ifdef HAVE_CONFIG_H
28
+ #include "config.h"
29
+ #endif
30
+
31
+ #include <string.h>
32
+ #include <stdlib.h>
33
+ #include "nnet.h"
34
+
35
+ #define SPARSE_BLOCK_SIZE 32
36
+
37
+ static int parse_record(const void **data, int *len, WeightArray *array) {
38
+ WeightHead *h = (WeightHead *)*data;
39
+ if (*len < WEIGHT_BLOCK_SIZE) return -1;
40
+ if (h->block_size < h->size) return -1;
41
+ if (h->block_size > *len-WEIGHT_BLOCK_SIZE) return -1;
42
+ if (h->name[sizeof(h->name)-1] != 0) return -1;
43
+ if (h->size < 0) return -1;
44
+ array->name = h->name;
45
+ array->type = h->type;
46
+ array->size = h->size;
47
+ array->data = (void*)((unsigned char*)(*data)+WEIGHT_BLOCK_SIZE);
48
+
49
+ *data = (void*)((unsigned char*)*data + h->block_size+WEIGHT_BLOCK_SIZE);
50
+ *len -= h->block_size+WEIGHT_BLOCK_SIZE;
51
+ return array->size;
52
+ }
53
+
54
+ int parse_weights(WeightArray **list, const void *data, int len)
55
+ {
56
+ int nb_arrays=0;
57
+ int capacity=20;
58
+ *list = calloc(capacity*sizeof(WeightArray), 1);
59
+ while (len > 0) {
60
+ int ret;
61
+ WeightArray array = {NULL, 0, 0, 0};
62
+ ret = parse_record(&data, &len, &array);
63
+ if (ret > 0) {
64
+ if (nb_arrays+1 >= capacity) {
65
+ /* Make sure there's room for the ending NULL element too. */
66
+ capacity = capacity*3/2;
67
+ *list = realloc(*list, capacity*sizeof(WeightArray));
68
+ }
69
+ (*list)[nb_arrays++] = array;
70
+ } else {
71
+ free(*list);
72
+ *list = NULL;
73
+ return -1;
74
+ }
75
+ }
76
+ (*list)[nb_arrays].name=NULL;
77
+ return nb_arrays;
78
+ }
79
+
80
+ static const void *find_array_entry(const WeightArray *arrays, const char *name) {
81
+ while (arrays->name && strcmp(arrays->name, name) != 0) arrays++;
82
+ return arrays;
83
+ }
84
+
85
+ static const void *find_array_check(const WeightArray *arrays, const char *name, int size) {
86
+ const WeightArray *a = find_array_entry(arrays, name);
87
+ if (a->name && a->size == size) return a->data;
88
+ else return NULL;
89
+ }
90
+
91
+ static const void *opt_array_check(const WeightArray *arrays, const char *name, int size, int *error) {
92
+ const WeightArray *a = find_array_entry(arrays, name);
93
+ *error = (a->name != NULL && a->size != size);
94
+ if (a->name && a->size == size) return a->data;
95
+ else return NULL;
96
+ }
97
+
98
+ static const void *find_idx_check(const WeightArray *arrays, const char *name, int nb_in, int nb_out, int *total_blocks) {
99
+ int remain;
100
+ const int *idx;
101
+ const WeightArray *a = find_array_entry(arrays, name);
102
+ *total_blocks = 0;
103
+ if (a == NULL) return NULL;
104
+ idx = a->data;
105
+ remain = a->size/sizeof(int);
106
+ while (remain > 0) {
107
+ int nb_blocks;
108
+ int i;
109
+ nb_blocks = *idx++;
110
+ if (remain < nb_blocks+1) return NULL;
111
+ for (i=0;i<nb_blocks;i++) {
112
+ int pos = *idx++;
113
+ if (pos+3 >= nb_in || (pos&0x3)) return NULL;
114
+ }
115
+ nb_out -= 8;
116
+ remain -= nb_blocks+1;
117
+ *total_blocks += nb_blocks;
118
+ }
119
+ if (nb_out != 0) return NULL;
120
+ return a->data;
121
+ }
122
+
123
+ int linear_init(LinearLayer *layer, const WeightArray *arrays,
124
+ const char *bias,
125
+ const char *subias,
126
+ const char *weights,
127
+ const char *float_weights,
128
+ const char *weights_idx,
129
+ const char *diag,
130
+ const char *scale,
131
+ int nb_inputs,
132
+ int nb_outputs)
133
+ {
134
+ int err;
135
+ layer->bias = NULL;
136
+ layer->subias = NULL;
137
+ layer->weights = NULL;
138
+ layer->float_weights = NULL;
139
+ layer->weights_idx = NULL;
140
+ layer->diag = NULL;
141
+ layer->scale = NULL;
142
+ if (bias != NULL) {
143
+ if ((layer->bias = find_array_check(arrays, bias, nb_outputs*sizeof(layer->bias[0]))) == NULL) return 1;
144
+ }
145
+ if (subias != NULL) {
146
+ if ((layer->subias = find_array_check(arrays, subias, nb_outputs*sizeof(layer->subias[0]))) == NULL) return 1;
147
+ }
148
+ if (weights_idx != NULL) {
149
+ int total_blocks;
150
+ if ((layer->weights_idx = find_idx_check(arrays, weights_idx, nb_inputs, nb_outputs, &total_blocks)) == NULL) return 1;
151
+ if (weights != NULL) {
152
+ if ((layer->weights = find_array_check(arrays, weights, SPARSE_BLOCK_SIZE*total_blocks*sizeof(layer->weights[0]))) == NULL) return 1;
153
+ }
154
+ if (float_weights != NULL) {
155
+ layer->float_weights = opt_array_check(arrays, float_weights, SPARSE_BLOCK_SIZE*total_blocks*sizeof(layer->float_weights[0]), &err);
156
+ if (err) return 1;
157
+ }
158
+ } else {
159
+ if (weights != NULL) {
160
+ if ((layer->weights = find_array_check(arrays, weights, nb_inputs*nb_outputs*sizeof(layer->weights[0]))) == NULL) return 1;
161
+ }
162
+ if (float_weights != NULL) {
163
+ layer->float_weights = opt_array_check(arrays, float_weights, nb_inputs*nb_outputs*sizeof(layer->float_weights[0]), &err);
164
+ if (err) return 1;
165
+ }
166
+ }
167
+ if (diag != NULL) {
168
+ if ((layer->diag = find_array_check(arrays, diag, nb_outputs*sizeof(layer->diag[0]))) == NULL) return 1;
169
+ }
170
+ if (weights != NULL) {
171
+ if ((layer->scale = find_array_check(arrays, scale, nb_outputs*sizeof(layer->scale[0]))) == NULL) return 1;
172
+ }
173
+ layer->nb_inputs = nb_inputs;
174
+ layer->nb_outputs = nb_outputs;
175
+ return 0;
176
+ }
177
+
178
+ int conv2d_init(Conv2dLayer *layer, const WeightArray *arrays,
179
+ const char *bias,
180
+ const char *float_weights,
181
+ int in_channels,
182
+ int out_channels,
183
+ int ktime,
184
+ int kheight)
185
+ {
186
+ int err;
187
+ layer->bias = NULL;
188
+ layer->float_weights = NULL;
189
+ if (bias != NULL) {
190
+ if ((layer->bias = find_array_check(arrays, bias, out_channels*sizeof(layer->bias[0]))) == NULL) return 1;
191
+ }
192
+ if (float_weights != NULL) {
193
+ layer->float_weights = opt_array_check(arrays, float_weights, in_channels*out_channels*ktime*kheight*sizeof(layer->float_weights[0]), &err);
194
+ if (err) return 1;
195
+ }
196
+ layer->in_channels = in_channels;
197
+ layer->out_channels = out_channels;
198
+ layer->ktime = ktime;
199
+ layer->kheight = kheight;
200
+ return 0;
201
+ }
202
+
203
+
204
+
205
+ #if 0
206
+ #include <fcntl.h>
207
+ #include <sys/mman.h>
208
+ #include <unistd.h>
209
+ #include <sys/stat.h>
210
+ #include <stdio.h>
211
+
212
+ int main()
213
+ {
214
+ int fd;
215
+ void *data;
216
+ int len;
217
+ int nb_arrays;
218
+ int i;
219
+ WeightArray *list;
220
+ struct stat st;
221
+ const char *filename = "weights_blob.bin";
222
+ stat(filename, &st);
223
+ len = st.st_size;
224
+ fd = open(filename, O_RDONLY);
225
+ data = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
226
+ printf("size is %d\n", len);
227
+ nb_arrays = parse_weights(&list, data, len);
228
+ for (i=0;i<nb_arrays;i++) {
229
+ printf("found %s: size %d\n", list[i].name, list[i].size);
230
+ }
231
+ printf("%p\n", list[i].name);
232
+ free(list);
233
+ munmap(data, len);
234
+ close(fd);
235
+ return 0;
236
+ }
237
+ #endif
cpp/src/rnnoise/pitch.c ADDED
@@ -0,0 +1,528 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 "denoise.h"
41
+ #include "celt_lpc.h"
42
+ #include "math.h"
43
+
44
+ static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
45
+ int max_pitch, int *best_pitch
46
+ #ifdef FIXED_POINT
47
+ , int yshift, opus_val32 maxcorr
48
+ #endif
49
+ )
50
+ {
51
+ int i, j;
52
+ opus_val32 Syy=1;
53
+ opus_val16 best_num[2];
54
+ opus_val32 best_den[2];
55
+ #ifdef FIXED_POINT
56
+ int xshift;
57
+
58
+ xshift = celt_ilog2(maxcorr)-14;
59
+ #endif
60
+
61
+ best_num[0] = -1;
62
+ best_num[1] = -1;
63
+ best_den[0] = 0;
64
+ best_den[1] = 0;
65
+ best_pitch[0] = 0;
66
+ best_pitch[1] = 1;
67
+ for (j=0;j<len;j++)
68
+ Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
69
+ for (i=0;i<max_pitch;i++)
70
+ {
71
+ if (xcorr[i]>0)
72
+ {
73
+ opus_val16 num;
74
+ opus_val32 xcorr16;
75
+ xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
76
+ #ifndef FIXED_POINT
77
+ /* Considering the range of xcorr16, this should avoid both underflows
78
+ and overflows (inf) when squaring xcorr16 */
79
+ xcorr16 *= 1e-12f;
80
+ #endif
81
+ num = MULT16_16_Q15(xcorr16,xcorr16);
82
+ if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
83
+ {
84
+ if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
85
+ {
86
+ best_num[1] = best_num[0];
87
+ best_den[1] = best_den[0];
88
+ best_pitch[1] = best_pitch[0];
89
+ best_num[0] = num;
90
+ best_den[0] = Syy;
91
+ best_pitch[0] = i;
92
+ } else {
93
+ best_num[1] = num;
94
+ best_den[1] = Syy;
95
+ best_pitch[1] = i;
96
+ }
97
+ }
98
+ }
99
+ Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift);
100
+ Syy = MAX32(1, Syy);
101
+ }
102
+ }
103
+
104
+ static void celt_fir5(const opus_val16 *x,
105
+ const opus_val16 *num,
106
+ opus_val16 *y,
107
+ int N,
108
+ opus_val16 *mem)
109
+ {
110
+ int i;
111
+ opus_val16 num0, num1, num2, num3, num4;
112
+ opus_val32 mem0, mem1, mem2, mem3, mem4;
113
+ num0=num[0];
114
+ num1=num[1];
115
+ num2=num[2];
116
+ num3=num[3];
117
+ num4=num[4];
118
+ mem0=mem[0];
119
+ mem1=mem[1];
120
+ mem2=mem[2];
121
+ mem3=mem[3];
122
+ mem4=mem[4];
123
+ for (i=0;i<N;i++)
124
+ {
125
+ opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
126
+ sum = MAC16_16(sum,num0,mem0);
127
+ sum = MAC16_16(sum,num1,mem1);
128
+ sum = MAC16_16(sum,num2,mem2);
129
+ sum = MAC16_16(sum,num3,mem3);
130
+ sum = MAC16_16(sum,num4,mem4);
131
+ mem4 = mem3;
132
+ mem3 = mem2;
133
+ mem2 = mem1;
134
+ mem1 = mem0;
135
+ mem0 = x[i];
136
+ y[i] = ROUND16(sum, SIG_SHIFT);
137
+ }
138
+ mem[0]=mem0;
139
+ mem[1]=mem1;
140
+ mem[2]=mem2;
141
+ mem[3]=mem3;
142
+ mem[4]=mem4;
143
+ }
144
+
145
+
146
+ void rnn_pitch_downsample(celt_sig *x[], opus_val16 *x_lp,
147
+ int len, int C)
148
+ {
149
+ int i;
150
+ opus_val32 ac[5];
151
+ opus_val16 tmp=Q15ONE;
152
+ opus_val16 lpc[4], mem[5]={0,0,0,0,0};
153
+ opus_val16 lpc2[5];
154
+ opus_val16 c1 = QCONST16(.8f,15);
155
+ #ifdef FIXED_POINT
156
+ int shift;
157
+ opus_val32 maxabs = celt_maxabs32(x[0], len);
158
+ if (C==2)
159
+ {
160
+ opus_val32 maxabs_1 = celt_maxabs32(x[1], len);
161
+ maxabs = MAX32(maxabs, maxabs_1);
162
+ }
163
+ if (maxabs<1)
164
+ maxabs=1;
165
+ shift = celt_ilog2(maxabs)-10;
166
+ if (shift<0)
167
+ shift=0;
168
+ if (C==2)
169
+ shift++;
170
+ #endif
171
+ for (i=1;i<len>>1;i++)
172
+ x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift);
173
+ x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift);
174
+ if (C==2)
175
+ {
176
+ for (i=1;i<len>>1;i++)
177
+ x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift);
178
+ x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift);
179
+ }
180
+
181
+ rnn_autocorr(x_lp, ac, NULL, 0,
182
+ 4, len>>1);
183
+
184
+ /* Noise floor -40 dB */
185
+ #ifdef FIXED_POINT
186
+ ac[0] += SHR32(ac[0],13);
187
+ #else
188
+ ac[0] *= 1.0001f;
189
+ #endif
190
+ /* Lag windowing */
191
+ for (i=1;i<=4;i++)
192
+ {
193
+ /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
194
+ #ifdef FIXED_POINT
195
+ ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
196
+ #else
197
+ ac[i] -= ac[i]*(.008f*i)*(.008f*i);
198
+ #endif
199
+ }
200
+
201
+ rnn_lpc(lpc, ac, 4);
202
+ for (i=0;i<4;i++)
203
+ {
204
+ tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
205
+ lpc[i] = MULT16_16_Q15(lpc[i], tmp);
206
+ }
207
+ /* Add a zero */
208
+ lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT);
209
+ lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]);
210
+ lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
211
+ lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
212
+ lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
213
+ celt_fir5(x_lp, lpc2, x_lp, len>>1, mem);
214
+ }
215
+
216
+ void rnn_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
217
+ opus_val32 *xcorr, int len, int max_pitch)
218
+ {
219
+
220
+ #if 0 /* This is a simple version of the pitch correlation that should work
221
+ well on DSPs like Blackfin and TI C5x/C6x */
222
+ int i, j;
223
+ #ifdef FIXED_POINT
224
+ opus_val32 maxcorr=1;
225
+ #endif
226
+ for (i=0;i<max_pitch;i++)
227
+ {
228
+ opus_val32 sum = 0;
229
+ for (j=0;j<len;j++)
230
+ sum = MAC16_16(sum, _x[j], _y[i+j]);
231
+ xcorr[i] = sum;
232
+ #ifdef FIXED_POINT
233
+ maxcorr = MAX32(maxcorr, sum);
234
+ #endif
235
+ }
236
+ #ifdef FIXED_POINT
237
+ return maxcorr;
238
+ #endif
239
+
240
+ #else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
241
+ int i;
242
+ /*The EDSP version requires that max_pitch is at least 1, and that _x is
243
+ 32-bit aligned.
244
+ Since it's hard to put asserts in assembly, put them here.*/
245
+ #ifdef FIXED_POINT
246
+ opus_val32 maxcorr=1;
247
+ #endif
248
+ celt_assert(max_pitch>0);
249
+ celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
250
+ for (i=0;i<max_pitch-3;i+=4)
251
+ {
252
+ opus_val32 sum[4]={0,0,0,0};
253
+ xcorr_kernel(_x, _y+i, sum, len);
254
+ xcorr[i]=sum[0];
255
+ xcorr[i+1]=sum[1];
256
+ xcorr[i+2]=sum[2];
257
+ xcorr[i+3]=sum[3];
258
+ #ifdef FIXED_POINT
259
+ sum[0] = MAX32(sum[0], sum[1]);
260
+ sum[2] = MAX32(sum[2], sum[3]);
261
+ sum[0] = MAX32(sum[0], sum[2]);
262
+ maxcorr = MAX32(maxcorr, sum[0]);
263
+ #endif
264
+ }
265
+ /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
266
+ for (;i<max_pitch;i++)
267
+ {
268
+ opus_val32 sum;
269
+ sum = celt_inner_prod(_x, _y+i, len);
270
+ xcorr[i] = sum;
271
+ #ifdef FIXED_POINT
272
+ maxcorr = MAX32(maxcorr, sum);
273
+ #endif
274
+ }
275
+ #ifdef FIXED_POINT
276
+ return maxcorr;
277
+ #endif
278
+ #endif
279
+ }
280
+
281
+ void rnn_pitch_search(const opus_val16 *x_lp, opus_val16 *y,
282
+ int len, int max_pitch, int *pitch)
283
+ {
284
+ int i, j;
285
+ int lag;
286
+ int best_pitch[2]={0,0};
287
+ #ifdef FIXED_POINT
288
+ opus_val32 maxcorr;
289
+ opus_val32 xmax, ymax;
290
+ int shift=0;
291
+ #endif
292
+ int offset;
293
+ opus_val16 x_lp4[PITCH_FRAME_SIZE>>2];
294
+ opus_val16 y_lp4[(PITCH_FRAME_SIZE+PITCH_MAX_PERIOD)>>2];
295
+ opus_val32 xcorr[PITCH_MAX_PERIOD>>1];
296
+
297
+ celt_assert(len <= PITCH_FRAME_SIZE);
298
+ celt_assert(max_pitch <= PITCH_MAX_PERIOD);
299
+ celt_assert(len>0);
300
+ celt_assert(max_pitch>0);
301
+ lag = len+max_pitch;
302
+
303
+
304
+ /* Downsample by 2 again */
305
+ for (j=0;j<len>>2;j++)
306
+ x_lp4[j] = x_lp[2*j];
307
+ for (j=0;j<lag>>2;j++)
308
+ y_lp4[j] = y[2*j];
309
+
310
+ #ifdef FIXED_POINT
311
+ xmax = celt_maxabs16(x_lp4, len>>2);
312
+ ymax = celt_maxabs16(y_lp4, lag>>2);
313
+ shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax)))-11;
314
+ if (shift>0)
315
+ {
316
+ for (j=0;j<len>>2;j++)
317
+ x_lp4[j] = SHR16(x_lp4[j], shift);
318
+ for (j=0;j<lag>>2;j++)
319
+ y_lp4[j] = SHR16(y_lp4[j], shift);
320
+ /* Use double the shift for a MAC */
321
+ shift *= 2;
322
+ } else {
323
+ shift = 0;
324
+ }
325
+ #endif
326
+
327
+ /* Coarse search with 4x decimation */
328
+
329
+ #ifdef FIXED_POINT
330
+ maxcorr =
331
+ #endif
332
+ rnn_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2);
333
+
334
+ find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
335
+ #ifdef FIXED_POINT
336
+ , 0, maxcorr
337
+ #endif
338
+ );
339
+
340
+ /* Finer search with 2x decimation */
341
+ #ifdef FIXED_POINT
342
+ maxcorr=1;
343
+ #endif
344
+ for (i=0;i<max_pitch>>1;i++)
345
+ {
346
+ opus_val32 sum;
347
+ xcorr[i] = 0;
348
+ if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
349
+ continue;
350
+ #ifdef FIXED_POINT
351
+ sum = 0;
352
+ for (j=0;j<len>>1;j++)
353
+ sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
354
+ #else
355
+ sum = celt_inner_prod(x_lp, y+i, len>>1);
356
+ #endif
357
+ xcorr[i] = MAX32(-1, sum);
358
+ #ifdef FIXED_POINT
359
+ maxcorr = MAX32(maxcorr, sum);
360
+ #endif
361
+ }
362
+ find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
363
+ #ifdef FIXED_POINT
364
+ , shift+1, maxcorr
365
+ #endif
366
+ );
367
+
368
+ /* Refine by pseudo-interpolation */
369
+ if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
370
+ {
371
+ opus_val32 a, b, c;
372
+ a = xcorr[best_pitch[0]-1];
373
+ b = xcorr[best_pitch[0]];
374
+ c = xcorr[best_pitch[0]+1];
375
+ if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
376
+ offset = 1;
377
+ else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
378
+ offset = -1;
379
+ else
380
+ offset = 0;
381
+ } else {
382
+ offset = 0;
383
+ }
384
+ *pitch = 2*best_pitch[0]-offset;
385
+ }
386
+
387
+ #ifdef FIXED_POINT
388
+ static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
389
+ {
390
+ opus_val32 x2y2;
391
+ int sx, sy, shift;
392
+ opus_val32 g;
393
+ opus_val16 den;
394
+ if (xy == 0 || xx == 0 || yy == 0)
395
+ return 0;
396
+ sx = celt_ilog2(xx)-14;
397
+ sy = celt_ilog2(yy)-14;
398
+ shift = sx + sy;
399
+ x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
400
+ if (shift & 1) {
401
+ if (x2y2 < 32768)
402
+ {
403
+ x2y2 <<= 1;
404
+ shift--;
405
+ } else {
406
+ x2y2 >>= 1;
407
+ shift++;
408
+ }
409
+ }
410
+ den = celt_rsqrt_norm(x2y2);
411
+ g = MULT16_32_Q15(den, xy);
412
+ g = VSHR32(g, (shift>>1)-1);
413
+ return EXTRACT16(MIN32(g, Q15ONE));
414
+ }
415
+ #else
416
+ static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
417
+ {
418
+ return xy/sqrt(1+xx*yy);
419
+ }
420
+ #endif
421
+
422
+ static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
423
+ opus_val16 rnn_remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
424
+ int N, int *T0_, int prev_period, opus_val16 prev_gain)
425
+ {
426
+ int k, i, T, T0;
427
+ opus_val16 g, g0;
428
+ opus_val16 pg;
429
+ opus_val32 xy,xx,yy,xy2;
430
+ opus_val32 xcorr[3];
431
+ opus_val32 best_xy, best_yy;
432
+ int offset;
433
+ int minperiod0;
434
+ opus_val32 yy_lookup[PITCH_MAX_PERIOD+1];
435
+
436
+ celt_assert(maxperiod <= PITCH_MAX_PERIOD);
437
+
438
+ minperiod0 = minperiod;
439
+ maxperiod /= 2;
440
+ minperiod /= 2;
441
+ *T0_ /= 2;
442
+ prev_period /= 2;
443
+ N /= 2;
444
+ x += maxperiod;
445
+ if (*T0_>=maxperiod)
446
+ *T0_=maxperiod-1;
447
+
448
+ T = T0 = *T0_;
449
+ dual_inner_prod(x, x, x-T0, N, &xx, &xy);
450
+ yy_lookup[0] = xx;
451
+ yy=xx;
452
+ for (i=1;i<=maxperiod;i++)
453
+ {
454
+ yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]);
455
+ yy_lookup[i] = MAX32(0, yy);
456
+ }
457
+ yy = yy_lookup[T0];
458
+ best_xy = xy;
459
+ best_yy = yy;
460
+ g = g0 = compute_pitch_gain(xy, xx, yy);
461
+ /* Look for any pitch at T/k */
462
+ for (k=2;k<=15;k++)
463
+ {
464
+ int T1, T1b;
465
+ opus_val16 g1;
466
+ opus_val16 cont=0;
467
+ opus_val16 thresh;
468
+ T1 = (2*T0+k)/(2*k);
469
+ if (T1 < minperiod)
470
+ break;
471
+ /* Look for another strong correlation at T1b */
472
+ if (k==2)
473
+ {
474
+ if (T1+T0>maxperiod)
475
+ T1b = T0;
476
+ else
477
+ T1b = T0+T1;
478
+ } else
479
+ {
480
+ T1b = (2*second_check[k]*T0+k)/(2*k);
481
+ }
482
+ dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2);
483
+ xy = HALF32(xy + xy2);
484
+ yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]);
485
+ g1 = compute_pitch_gain(xy, xx, yy);
486
+ if (abs(T1-prev_period)<=1)
487
+ cont = prev_gain;
488
+ else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
489
+ cont = HALF16(prev_gain);
490
+ else
491
+ cont = 0;
492
+ thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
493
+ /* Bias against very high pitch (very short period) to avoid false-positives
494
+ due to short-term correlation */
495
+ if (T1<3*minperiod)
496
+ thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
497
+ else if (T1<2*minperiod)
498
+ thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
499
+ if (g1 > thresh)
500
+ {
501
+ best_xy = xy;
502
+ best_yy = yy;
503
+ T = T1;
504
+ g = g1;
505
+ }
506
+ }
507
+ best_xy = MAX32(0, best_xy);
508
+ if (best_yy <= best_xy)
509
+ pg = Q15ONE;
510
+ else
511
+ pg = best_xy/(best_yy+1);
512
+
513
+ for (k=0;k<3;k++)
514
+ xcorr[k] = celt_inner_prod(x, x-(T+k-1), N);
515
+ if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
516
+ offset = 1;
517
+ else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
518
+ offset = -1;
519
+ else
520
+ offset = 0;
521
+ if (pg > g)
522
+ pg = g;
523
+ *T0_ = 2*T+offset;
524
+
525
+ if (*T0_<minperiod0)
526
+ *T0_=minperiod0;
527
+ return pg;
528
+ }
cpp/src/rnnoise/pitch.h ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2007-2008 CSIRO
2
+ Copyright (c) 2007-2009 Xiph.Org Foundation
3
+ Written by Jean-Marc Valin */
4
+ /**
5
+ @file pitch.h
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
+ #ifndef PITCH_H
35
+ #define PITCH_H
36
+
37
+ #include "arch.h"
38
+
39
+ void rnn_pitch_downsample(celt_sig *x[], opus_val16 *x_lp,
40
+ int len, int C);
41
+
42
+ void rnn_pitch_search(const opus_val16 *x_lp, opus_val16 *y,
43
+ int len, int max_pitch, int *pitch);
44
+
45
+ opus_val16 rnn_remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
46
+ int N, int *T0, int prev_period, opus_val16 prev_gain);
47
+
48
+
49
+ /* OPT: This is the kernel you really want to optimize. It gets used a lot
50
+ by the prefilter and by the PLC. */
51
+ static OPUS_INLINE void xcorr_kernel(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[4], int len)
52
+ {
53
+ int j;
54
+ opus_val16 y_0, y_1, y_2, y_3;
55
+ celt_assert(len>=3);
56
+ y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */
57
+ y_0=*y++;
58
+ y_1=*y++;
59
+ y_2=*y++;
60
+ for (j=0;j<len-3;j+=4)
61
+ {
62
+ opus_val16 tmp;
63
+ tmp = *x++;
64
+ y_3=*y++;
65
+ sum[0] = MAC16_16(sum[0],tmp,y_0);
66
+ sum[1] = MAC16_16(sum[1],tmp,y_1);
67
+ sum[2] = MAC16_16(sum[2],tmp,y_2);
68
+ sum[3] = MAC16_16(sum[3],tmp,y_3);
69
+ tmp=*x++;
70
+ y_0=*y++;
71
+ sum[0] = MAC16_16(sum[0],tmp,y_1);
72
+ sum[1] = MAC16_16(sum[1],tmp,y_2);
73
+ sum[2] = MAC16_16(sum[2],tmp,y_3);
74
+ sum[3] = MAC16_16(sum[3],tmp,y_0);
75
+ tmp=*x++;
76
+ y_1=*y++;
77
+ sum[0] = MAC16_16(sum[0],tmp,y_2);
78
+ sum[1] = MAC16_16(sum[1],tmp,y_3);
79
+ sum[2] = MAC16_16(sum[2],tmp,y_0);
80
+ sum[3] = MAC16_16(sum[3],tmp,y_1);
81
+ tmp=*x++;
82
+ y_2=*y++;
83
+ sum[0] = MAC16_16(sum[0],tmp,y_3);
84
+ sum[1] = MAC16_16(sum[1],tmp,y_0);
85
+ sum[2] = MAC16_16(sum[2],tmp,y_1);
86
+ sum[3] = MAC16_16(sum[3],tmp,y_2);
87
+ }
88
+ if (j++<len)
89
+ {
90
+ opus_val16 tmp = *x++;
91
+ y_3=*y++;
92
+ sum[0] = MAC16_16(sum[0],tmp,y_0);
93
+ sum[1] = MAC16_16(sum[1],tmp,y_1);
94
+ sum[2] = MAC16_16(sum[2],tmp,y_2);
95
+ sum[3] = MAC16_16(sum[3],tmp,y_3);
96
+ }
97
+ if (j++<len)
98
+ {
99
+ opus_val16 tmp=*x++;
100
+ y_0=*y++;
101
+ sum[0] = MAC16_16(sum[0],tmp,y_1);
102
+ sum[1] = MAC16_16(sum[1],tmp,y_2);
103
+ sum[2] = MAC16_16(sum[2],tmp,y_3);
104
+ sum[3] = MAC16_16(sum[3],tmp,y_0);
105
+ }
106
+ if (j<len)
107
+ {
108
+ opus_val16 tmp=*x++;
109
+ y_1=*y++;
110
+ sum[0] = MAC16_16(sum[0],tmp,y_2);
111
+ sum[1] = MAC16_16(sum[1],tmp,y_3);
112
+ sum[2] = MAC16_16(sum[2],tmp,y_0);
113
+ sum[3] = MAC16_16(sum[3],tmp,y_1);
114
+ }
115
+ }
116
+
117
+ static OPUS_INLINE void dual_inner_prod(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
118
+ int N, opus_val32 *xy1, opus_val32 *xy2)
119
+ {
120
+ int i;
121
+ opus_val32 xy01=0;
122
+ opus_val32 xy02=0;
123
+ for (i=0;i<N;i++)
124
+ {
125
+ xy01 = MAC16_16(xy01, x[i], y01[i]);
126
+ xy02 = MAC16_16(xy02, x[i], y02[i]);
127
+ }
128
+ *xy1 = xy01;
129
+ *xy2 = xy02;
130
+ }
131
+
132
+ /*We make sure a C version is always available for cases where the overhead of
133
+ vectorization and passing around an arch flag aren't worth it.*/
134
+ static OPUS_INLINE opus_val32 celt_inner_prod(const opus_val16 *x,
135
+ const opus_val16 *y, int N)
136
+ {
137
+ int i;
138
+ opus_val32 xy=0;
139
+ for (i=0;i<N;i++)
140
+ xy = MAC16_16(xy, x[i], y[i]);
141
+ return xy;
142
+ }
143
+
144
+ void rnn_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
145
+ opus_val32 *xcorr, int len, int max_pitch);
146
+
147
+ #endif
cpp/src/rnnoise/rnn.c ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2008-2011 Octasic Inc.
2
+ 2012-2017 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 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 <math.h>
33
+ #include "opus_types.h"
34
+ #include "common.h"
35
+ #include "arch.h"
36
+ #include "rnn.h"
37
+ #include "rnnoise_data.h"
38
+ #include <stdio.h>
39
+
40
+
41
+ #define INPUT_SIZE 42
42
+
43
+
44
+ void compute_rnn(const RNNoise *model, RNNState *rnn, float *gains, float *vad, const float *input, int arch) {
45
+ float tmp[MAX_NEURONS];
46
+ float cat[CONV2_OUT_SIZE + GRU1_OUT_SIZE + GRU2_OUT_SIZE + GRU3_OUT_SIZE];
47
+ /*for (int i=0;i<INPUT_SIZE;i++) printf("%f ", input[i]);printf("\n");*/
48
+ compute_generic_conv1d(&model->conv1, tmp, rnn->conv1_state, input, CONV1_IN_SIZE, ACTIVATION_TANH, arch);
49
+ compute_generic_conv1d(&model->conv2, cat, rnn->conv2_state, tmp, CONV2_IN_SIZE, ACTIVATION_TANH, arch);
50
+ compute_generic_gru(&model->gru1_input, &model->gru1_recurrent, rnn->gru1_state, cat, arch);
51
+ compute_generic_gru(&model->gru2_input, &model->gru2_recurrent, rnn->gru2_state, rnn->gru1_state, arch);
52
+ compute_generic_gru(&model->gru3_input, &model->gru3_recurrent, rnn->gru3_state, rnn->gru2_state, arch);
53
+ RNN_COPY(&cat[CONV2_OUT_SIZE], rnn->gru1_state, GRU1_OUT_SIZE);
54
+ RNN_COPY(&cat[CONV2_OUT_SIZE+GRU1_OUT_SIZE], rnn->gru2_state, GRU2_OUT_SIZE);
55
+ RNN_COPY(&cat[CONV2_OUT_SIZE+GRU1_OUT_SIZE+GRU2_OUT_SIZE], rnn->gru3_state, GRU3_OUT_SIZE);
56
+ compute_generic_dense(&model->dense_out, gains, cat, ACTIVATION_SIGMOID, arch);
57
+ compute_generic_dense(&model->vad_dense, vad, cat, ACTIVATION_SIGMOID, arch);
58
+ /*for (int i=0;i<22;i++) printf("%f ", gains[i]);printf("\n");*/
59
+ /*printf("%f\n", *vad);*/
60
+ }
cpp/src/rnnoise/rnn.h ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ #include "rnnoise_data.h"
32
+
33
+ #include "opus_types.h"
34
+
35
+ #define WEIGHTS_SCALE (1.f/256)
36
+
37
+ #define MAX_NEURONS 1024
38
+
39
+
40
+ typedef struct {
41
+ float conv1_state[CONV1_STATE_SIZE];
42
+ float conv2_state[CONV2_STATE_SIZE];
43
+ float gru1_state[GRU1_STATE_SIZE];
44
+ float gru2_state[GRU2_STATE_SIZE];
45
+ float gru3_state[GRU3_STATE_SIZE];
46
+ } RNNState;
47
+ void compute_rnn(const RNNoise *model, RNNState *rnn, float *gains, float *vad, const float *input, int arch);
48
+
49
+ #endif /* RNN_H_ */
cpp/src/rnnoise/rnn_train.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/python
2
+
3
+ from __future__ import print_function
4
+
5
+ from keras.models import Sequential
6
+ from keras.models import Model
7
+ from keras.layers import Input
8
+ from keras.layers import Dense
9
+ from keras.layers import LSTM
10
+ from keras.layers import GRU
11
+ from keras.layers import SimpleRNN
12
+ from keras.layers import Dropout
13
+ from keras import losses
14
+ import h5py
15
+
16
+ from keras import backend as K
17
+ import numpy as np
18
+
19
+ print('Build model...')
20
+ main_input = Input(shape=(None, 22), name='main_input')
21
+ #x = Dense(44, activation='relu')(main_input)
22
+ #x = GRU(44, dropout=0.0, recurrent_dropout=0.0, activation='tanh', recurrent_activation='sigmoid', return_sequences=True)(x)
23
+ x=main_input
24
+ x = GRU(128, activation='tanh', recurrent_activation='sigmoid', return_sequences=True)(x)
25
+ #x = GRU(128, return_sequences=True)(x)
26
+ #x = GRU(22, activation='relu', return_sequences=True)(x)
27
+ x = Dense(22, activation='sigmoid')(x)
28
+ #x = Dense(22, activation='softplus')(x)
29
+ model = Model(inputs=main_input, outputs=x)
30
+
31
+ batch_size = 32
32
+
33
+ print('Loading data...')
34
+ with h5py.File('denoise_data.h5', 'r') as hf:
35
+ all_data = hf['denoise_data'][:]
36
+ print('done.')
37
+
38
+ window_size = 500
39
+
40
+ nb_sequences = len(all_data)//window_size
41
+ print(nb_sequences, ' sequences')
42
+ x_train = all_data[:nb_sequences*window_size, :-22]
43
+ x_train = np.reshape(x_train, (nb_sequences, window_size, 22))
44
+
45
+ y_train = np.copy(all_data[:nb_sequences*window_size, -22:])
46
+ y_train = np.reshape(y_train, (nb_sequences, window_size, 22))
47
+
48
+ #y_train = -20*np.log10(np.add(y_train, .03));
49
+
50
+ all_data = 0;
51
+ x_train = x_train.astype('float32')
52
+ y_train = y_train.astype('float32')
53
+
54
+ print(len(x_train), 'train sequences. x shape =', x_train.shape, 'y shape = ', y_train.shape)
55
+
56
+ # try using different optimizers and different optimizer configs
57
+ model.compile(loss='mean_squared_error',
58
+ optimizer='adam',
59
+ metrics=['binary_accuracy'])
60
+
61
+ print('Train...')
62
+ model.fit(x_train, y_train,
63
+ batch_size=batch_size,
64
+ epochs=200,
65
+ validation_data=(x_train, y_train))
66
+ model.save("newweights.hdf5")
cpp/src/rnnoise/rnnoise.h ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 <stdio.h>
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(void);
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(void);
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 memory buffer
98
+ *
99
+ * It must be deallocated with rnnoise_model_free() and the buffer must remain
100
+ * valid until after the returned object is destroyed.
101
+ */
102
+ RNNOISE_EXPORT RNNModel *rnnoise_model_from_buffer(const void *ptr, int len);
103
+
104
+
105
+ /**
106
+ * Load a model from a file
107
+ *
108
+ * It must be deallocated with rnnoise_model_free() and the file must not be
109
+ * closed until the returned object is destroyed.
110
+ */
111
+ RNNOISE_EXPORT RNNModel *rnnoise_model_from_file(FILE *f);
112
+
113
+ /**
114
+ * Load a model from a file name
115
+ *
116
+ * It must be deallocated with rnnoise_model_free()
117
+ */
118
+ RNNOISE_EXPORT RNNModel *rnnoise_model_from_filename(const char *filename);
119
+
120
+ /**
121
+ * Free a custom model
122
+ *
123
+ * It must be called after all the DenoiseStates referring to it are freed.
124
+ */
125
+ RNNOISE_EXPORT void rnnoise_model_free(RNNModel *model);
126
+
127
+ #ifdef __cplusplus
128
+ }
129
+ #endif
130
+
131
+ #endif
cpp/src/rnnoise/rnnoise_data.c ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* RNNoise 网络权重占位(SDK 版)。
2
+ *
3
+ * 本交付包的网络权重已内嵌到 AXMODEL 中,compute_rnn 由 AX Engine 推理替换,
4
+ * 不再需要原版 rnnoise_data.c 的 75MB 权重数组。此处仅保留空权重表与
5
+ * init_rnnoise 空实现(memset 清零),以保持原版 denoise.c 的初始化链路。
6
+ */
7
+ #include <string.h>
8
+
9
+ #include "rnnoise_data.h"
10
+
11
+ const WeightArray rnnoise_arrays[] = {{NULL, 0, 0, NULL}};
12
+ const WeightArray n[] = {{NULL, 0, 0, NULL}};
13
+
14
+ int init_rnnoise(RNNoise *model, const WeightArray *arrays) {
15
+ (void)arrays;
16
+ memset(model, 0, sizeof(*model));
17
+ return 0;
18
+ }
cpp/src/rnnoise/rnnoise_data.h ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #ifndef RNNOISE_DATA_H
3
+ #define RNNOISE_DATA_H
4
+
5
+ #include "nnet.h"
6
+
7
+
8
+ #define CONV1_OUT_SIZE 128
9
+
10
+ #define CONV1_IN_SIZE 65
11
+
12
+ #define CONV1_STATE_SIZE (65 * (2))
13
+
14
+ #define CONV1_DELAY 1
15
+
16
+ #define CONV2_OUT_SIZE 384
17
+
18
+ #define CONV2_IN_SIZE 128
19
+
20
+ #define CONV2_STATE_SIZE (128 * (2))
21
+
22
+ #define CONV2_DELAY 1
23
+
24
+ #define GRU1_OUT_SIZE 384
25
+
26
+ #define GRU1_STATE_SIZE 384
27
+
28
+ #define GRU2_OUT_SIZE 384
29
+
30
+ #define GRU2_STATE_SIZE 384
31
+
32
+ #define GRU3_OUT_SIZE 384
33
+
34
+ #define GRU3_STATE_SIZE 384
35
+
36
+ #define DENSE_OUT_OUT_SIZE 32
37
+
38
+ #define VAD_DENSE_OUT_SIZE 1
39
+
40
+ typedef struct {
41
+ LinearLayer conv1;
42
+ LinearLayer conv2;
43
+ LinearLayer gru1_input;
44
+ LinearLayer gru1_recurrent;
45
+ LinearLayer gru2_input;
46
+ LinearLayer gru2_recurrent;
47
+ LinearLayer gru3_input;
48
+ LinearLayer gru3_recurrent;
49
+ LinearLayer dense_out;
50
+ LinearLayer vad_dense;
51
+ } RNNoise;
52
+
53
+ int init_rnnoise(RNNoise *model, const WeightArray *arrays);
54
+
55
+ #endif /* RNNOISE_DATA_H */
cpp/src/rnnoise/rnnoise_tables.c ADDED
@@ -0,0 +1,874 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* The contents of this file was automatically generated by dump_rnnoise_tables.c*/
2
+
3
+ #ifdef HAVE_CONFIG_H
4
+ #include "config.h"
5
+ #endif
6
+ #include "kiss_fft.h"
7
+
8
+ static const arch_fft_state arch_fft = {0, NULL};
9
+
10
+ static const opus_int32 fft_bitrev[960] = {
11
+ 0, 192, 384, 576, 768, 64, 256, 448, 640, 832, 128, 320, 512, 704, 896,
12
+ 16, 208, 400, 592, 784, 80, 272, 464, 656, 848, 144, 336, 528, 720, 912,
13
+ 32, 224, 416, 608, 800, 96, 288, 480, 672, 864, 160, 352, 544, 736, 928,
14
+ 48, 240, 432, 624, 816, 112, 304, 496, 688, 880, 176, 368, 560, 752, 944,
15
+ 4, 196, 388, 580, 772, 68, 260, 452, 644, 836, 132, 324, 516, 708, 900,
16
+ 20, 212, 404, 596, 788, 84, 276, 468, 660, 852, 148, 340, 532, 724, 916,
17
+ 36, 228, 420, 612, 804, 100, 292, 484, 676, 868, 164, 356, 548, 740, 932,
18
+ 52, 244, 436, 628, 820, 116, 308, 500, 692, 884, 180, 372, 564, 756, 948,
19
+ 8, 200, 392, 584, 776, 72, 264, 456, 648, 840, 136, 328, 520, 712, 904,
20
+ 24, 216, 408, 600, 792, 88, 280, 472, 664, 856, 152, 344, 536, 728, 920,
21
+ 40, 232, 424, 616, 808, 104, 296, 488, 680, 872, 168, 360, 552, 744, 936,
22
+ 56, 248, 440, 632, 824, 120, 312, 504, 696, 888, 184, 376, 568, 760, 952,
23
+ 12, 204, 396, 588, 780, 76, 268, 460, 652, 844, 140, 332, 524, 716, 908,
24
+ 28, 220, 412, 604, 796, 92, 284, 476, 668, 860, 156, 348, 540, 732, 924,
25
+ 44, 236, 428, 620, 812, 108, 300, 492, 684, 876, 172, 364, 556, 748, 940,
26
+ 60, 252, 444, 636, 828, 124, 316, 508, 700, 892, 188, 380, 572, 764, 956,
27
+ 1, 193, 385, 577, 769, 65, 257, 449, 641, 833, 129, 321, 513, 705, 897,
28
+ 17, 209, 401, 593, 785, 81, 273, 465, 657, 849, 145, 337, 529, 721, 913,
29
+ 33, 225, 417, 609, 801, 97, 289, 481, 673, 865, 161, 353, 545, 737, 929,
30
+ 49, 241, 433, 625, 817, 113, 305, 497, 689, 881, 177, 369, 561, 753, 945,
31
+ 5, 197, 389, 581, 773, 69, 261, 453, 645, 837, 133, 325, 517, 709, 901,
32
+ 21, 213, 405, 597, 789, 85, 277, 469, 661, 853, 149, 341, 533, 725, 917,
33
+ 37, 229, 421, 613, 805, 101, 293, 485, 677, 869, 165, 357, 549, 741, 933,
34
+ 53, 245, 437, 629, 821, 117, 309, 501, 693, 885, 181, 373, 565, 757, 949,
35
+ 9, 201, 393, 585, 777, 73, 265, 457, 649, 841, 137, 329, 521, 713, 905,
36
+ 25, 217, 409, 601, 793, 89, 281, 473, 665, 857, 153, 345, 537, 729, 921,
37
+ 41, 233, 425, 617, 809, 105, 297, 489, 681, 873, 169, 361, 553, 745, 937,
38
+ 57, 249, 441, 633, 825, 121, 313, 505, 697, 889, 185, 377, 569, 761, 953,
39
+ 13, 205, 397, 589, 781, 77, 269, 461, 653, 845, 141, 333, 525, 717, 909,
40
+ 29, 221, 413, 605, 797, 93, 285, 477, 669, 861, 157, 349, 541, 733, 925,
41
+ 45, 237, 429, 621, 813, 109, 301, 493, 685, 877, 173, 365, 557, 749, 941,
42
+ 61, 253, 445, 637, 829, 125, 317, 509, 701, 893, 189, 381, 573, 765, 957,
43
+ 2, 194, 386, 578, 770, 66, 258, 450, 642, 834, 130, 322, 514, 706, 898,
44
+ 18, 210, 402, 594, 786, 82, 274, 466, 658, 850, 146, 338, 530, 722, 914,
45
+ 34, 226, 418, 610, 802, 98, 290, 482, 674, 866, 162, 354, 546, 738, 930,
46
+ 50, 242, 434, 626, 818, 114, 306, 498, 690, 882, 178, 370, 562, 754, 946,
47
+ 6, 198, 390, 582, 774, 70, 262, 454, 646, 838, 134, 326, 518, 710, 902,
48
+ 22, 214, 406, 598, 790, 86, 278, 470, 662, 854, 150, 342, 534, 726, 918,
49
+ 38, 230, 422, 614, 806, 102, 294, 486, 678, 870, 166, 358, 550, 742, 934,
50
+ 54, 246, 438, 630, 822, 118, 310, 502, 694, 886, 182, 374, 566, 758, 950,
51
+ 10, 202, 394, 586, 778, 74, 266, 458, 650, 842, 138, 330, 522, 714, 906,
52
+ 26, 218, 410, 602, 794, 90, 282, 474, 666, 858, 154, 346, 538, 730, 922,
53
+ 42, 234, 426, 618, 810, 106, 298, 490, 682, 874, 170, 362, 554, 746, 938,
54
+ 58, 250, 442, 634, 826, 122, 314, 506, 698, 890, 186, 378, 570, 762, 954,
55
+ 14, 206, 398, 590, 782, 78, 270, 462, 654, 846, 142, 334, 526, 718, 910,
56
+ 30, 222, 414, 606, 798, 94, 286, 478, 670, 862, 158, 350, 542, 734, 926,
57
+ 46, 238, 430, 622, 814, 110, 302, 494, 686, 878, 174, 366, 558, 750, 942,
58
+ 62, 254, 446, 638, 830, 126, 318, 510, 702, 894, 190, 382, 574, 766, 958,
59
+ 3, 195, 387, 579, 771, 67, 259, 451, 643, 835, 131, 323, 515, 707, 899,
60
+ 19, 211, 403, 595, 787, 83, 275, 467, 659, 851, 147, 339, 531, 723, 915,
61
+ 35, 227, 419, 611, 803, 99, 291, 483, 675, 867, 163, 355, 547, 739, 931,
62
+ 51, 243, 435, 627, 819, 115, 307, 499, 691, 883, 179, 371, 563, 755, 947,
63
+ 7, 199, 391, 583, 775, 71, 263, 455, 647, 839, 135, 327, 519, 711, 903,
64
+ 23, 215, 407, 599, 791, 87, 279, 471, 663, 855, 151, 343, 535, 727, 919,
65
+ 39, 231, 423, 615, 807, 103, 295, 487, 679, 871, 167, 359, 551, 743, 935,
66
+ 55, 247, 439, 631, 823, 119, 311, 503, 695, 887, 183, 375, 567, 759, 951,
67
+ 11, 203, 395, 587, 779, 75, 267, 459, 651, 843, 139, 331, 523, 715, 907,
68
+ 27, 219, 411, 603, 795, 91, 283, 475, 667, 859, 155, 347, 539, 731, 923,
69
+ 43, 235, 427, 619, 811, 107, 299, 491, 683, 875, 171, 363, 555, 747, 939,
70
+ 59, 251, 443, 635, 827, 123, 315, 507, 699, 891, 187, 379, 571, 763, 955,
71
+ 15, 207, 399, 591, 783, 79, 271, 463, 655, 847, 143, 335, 527, 719, 911,
72
+ 31, 223, 415, 607, 799, 95, 287, 479, 671, 863, 159, 351, 543, 735, 927,
73
+ 47, 239, 431, 623, 815, 111, 303, 495, 687, 879, 175, 367, 559, 751, 943,
74
+ 63, 255, 447, 639, 831, 127, 319, 511, 703, 895, 191, 383, 575, 767, 959,
75
+ };
76
+
77
+ static const kiss_twiddle_cpx fft_twiddles[960] = {
78
+ {1.00000000f, -0.00000000f}, {0.999978602f, -0.00654493785f},
79
+ {0.999914348f, -0.0130895954f}, {0.999807239f, -0.0196336918f},
80
+ {0.999657333f, -0.0261769481f}, {0.999464571f, -0.0327190831f},
81
+ {0.999229014f, -0.0392598175f}, {0.998950660f, -0.0457988679f},
82
+ {0.998629510f, -0.0523359552f}, {0.998265624f, -0.0588708036f},
83
+ {0.997858942f, -0.0654031262f}, {0.997409463f, -0.0719326511f},
84
+ {0.996917307f, -0.0784590989f}, {0.996382475f, -0.0849821791f},
85
+ {0.995804906f, -0.0915016159f}, {0.995184720f, -0.0980171412f},
86
+ {0.994521916f, -0.104528464f}, {0.993816435f, -0.111035310f},
87
+ {0.993068457f, -0.117537394f}, {0.992277920f, -0.124034449f},
88
+ {0.991444886f, -0.130526185f}, {0.990569353f, -0.137012348f},
89
+ {0.989651382f, -0.143492624f}, {0.988691032f, -0.149966761f},
90
+ {0.987688363f, -0.156434461f}, {0.986643314f, -0.162895471f},
91
+ {0.985556066f, -0.169349506f}, {0.984426558f, -0.175796285f},
92
+ {0.983254910f, -0.182235524f}, {0.982041121f, -0.188666970f},
93
+ {0.980785251f, -0.195090324f}, {0.979487419f, -0.201505318f},
94
+ {0.978147626f, -0.207911685f}, {0.976765871f, -0.214309156f},
95
+ {0.975342333f, -0.220697433f}, {0.973876953f, -0.227076262f},
96
+ {0.972369909f, -0.233445361f}, {0.970821202f, -0.239804462f},
97
+ {0.969230890f, -0.246153295f}, {0.967599094f, -0.252491564f},
98
+ {0.965925813f, -0.258819044f}, {0.964211166f, -0.265135437f},
99
+ {0.962455213f, -0.271440446f}, {0.960658073f, -0.277733833f},
100
+ {0.958819747f, -0.284015357f}, {0.956940353f, -0.290284663f},
101
+ {0.955019951f, -0.296541572f}, {0.953058660f, -0.302785784f},
102
+ {0.951056540f, -0.309017003f}, {0.949013650f, -0.315234989f},
103
+ {0.946930110f, -0.321439475f}, {0.944806039f, -0.327630192f},
104
+ {0.942641497f, -0.333806872f}, {0.940436542f, -0.339969248f},
105
+ {0.938191354f, -0.346117049f}, {0.935905933f, -0.352250040f},
106
+ {0.933580399f, -0.358367950f}, {0.931214929f, -0.364470512f},
107
+ {0.928809524f, -0.370557427f}, {0.926364362f, -0.376628488f},
108
+ {0.923879504f, -0.382683426f}, {0.921355128f, -0.388721973f},
109
+ {0.918791234f, -0.394743860f}, {0.916187942f, -0.400748819f},
110
+ {0.913545430f, -0.406736642f}, {0.910863817f, -0.412707031f},
111
+ {0.908143163f, -0.418659747f}, {0.905383646f, -0.424594522f},
112
+ {0.902585268f, -0.430511087f}, {0.899748266f, -0.436409235f},
113
+ {0.896872759f, -0.442288697f}, {0.893958807f, -0.448149204f},
114
+ {0.891006529f, -0.453990489f}, {0.888016105f, -0.459812373f},
115
+ {0.884987652f, -0.465614527f}, {0.881921291f, -0.471396744f},
116
+ {0.878817141f, -0.477158755f}, {0.875675321f, -0.482900351f},
117
+ {0.872496009f, -0.488621235f}, {0.869279325f, -0.494321197f},
118
+ {0.866025388f, -0.500000000f}, {0.862734377f, -0.505657375f},
119
+ {0.859406412f, -0.511293113f}, {0.856041610f, -0.516906917f},
120
+ {0.852640152f, -0.522498548f}, {0.849202156f, -0.528067827f},
121
+ {0.845727801f, -0.533614516f}, {0.842217207f, -0.539138317f},
122
+ {0.838670552f, -0.544639051f}, {0.835087955f, -0.550116420f},
123
+ {0.831469595f, -0.555570245f}, {0.827815652f, -0.561000228f},
124
+ {0.824126184f, -0.566406250f}, {0.820401430f, -0.571787953f},
125
+ {0.816641569f, -0.577145219f}, {0.812846661f, -0.582477689f},
126
+ {0.809017003f, -0.587785244f}, {0.805152655f, -0.593067646f},
127
+ {0.801253796f, -0.598324597f}, {0.797320664f, -0.603555918f},
128
+ {0.793353319f, -0.608761430f}, {0.789352059f, -0.613940835f},
129
+ {0.785316944f, -0.619093955f}, {0.781248152f, -0.624220550f},
130
+ {0.777145982f, -0.629320383f}, {0.773010433f, -0.634393275f},
131
+ {0.768841803f, -0.639438987f}, {0.764640272f, -0.644457340f},
132
+ {0.760405958f, -0.649448037f}, {0.756139100f, -0.654410958f},
133
+ {0.751839817f, -0.659345806f}, {0.747508347f, -0.664252460f},
134
+ {0.743144810f, -0.669130623f}, {0.738749504f, -0.673980117f},
135
+ {0.734322488f, -0.678800762f}, {0.729864061f, -0.683592319f},
136
+ {0.725374401f, -0.688354552f}, {0.720853567f, -0.693087339f},
137
+ {0.716301918f, -0.697790444f}, {0.711719632f, -0.702463686f},
138
+ {0.707106769f, -0.707106769f}, {0.702463686f, -0.711719632f},
139
+ {0.697790444f, -0.716301918f}, {0.693087339f, -0.720853567f},
140
+ {0.688354552f, -0.725374401f}, {0.683592319f, -0.729864061f},
141
+ {0.678800762f, -0.734322488f}, {0.673980117f, -0.738749504f},
142
+ {0.669130623f, -0.743144810f}, {0.664252460f, -0.747508347f},
143
+ {0.659345806f, -0.751839817f}, {0.654410958f, -0.756139100f},
144
+ {0.649448037f, -0.760405958f}, {0.644457340f, -0.764640272f},
145
+ {0.639438987f, -0.768841803f}, {0.634393275f, -0.773010433f},
146
+ {0.629320383f, -0.777145982f}, {0.624220550f, -0.781248152f},
147
+ {0.619093955f, -0.785316944f}, {0.613940835f, -0.789352059f},
148
+ {0.608761430f, -0.793353319f}, {0.603555918f, -0.797320664f},
149
+ {0.598324597f, -0.801253796f}, {0.593067646f, -0.805152655f},
150
+ {0.587785244f, -0.809017003f}, {0.582477689f, -0.812846661f},
151
+ {0.577145219f, -0.816641569f}, {0.571787953f, -0.820401430f},
152
+ {0.566406250f, -0.824126184f}, {0.561000228f, -0.827815652f},
153
+ {0.555570245f, -0.831469595f}, {0.550116420f, -0.835087955f},
154
+ {0.544639051f, -0.838670552f}, {0.539138317f, -0.842217207f},
155
+ {0.533614516f, -0.845727801f}, {0.528067827f, -0.849202156f},
156
+ {0.522498548f, -0.852640152f}, {0.516906917f, -0.856041610f},
157
+ {0.511293113f, -0.859406412f}, {0.505657375f, -0.862734377f},
158
+ {0.500000000f, -0.866025388f}, {0.494321197f, -0.869279325f},
159
+ {0.488621235f, -0.872496009f}, {0.482900351f, -0.875675321f},
160
+ {0.477158755f, -0.878817141f}, {0.471396744f, -0.881921291f},
161
+ {0.465614527f, -0.884987652f}, {0.459812373f, -0.888016105f},
162
+ {0.453990489f, -0.891006529f}, {0.448149204f, -0.893958807f},
163
+ {0.442288697f, -0.896872759f}, {0.436409235f, -0.899748266f},
164
+ {0.430511087f, -0.902585268f}, {0.424594522f, -0.905383646f},
165
+ {0.418659747f, -0.908143163f}, {0.412707031f, -0.910863817f},
166
+ {0.406736642f, -0.913545430f}, {0.400748819f, -0.916187942f},
167
+ {0.394743860f, -0.918791234f}, {0.388721973f, -0.921355128f},
168
+ {0.382683426f, -0.923879504f}, {0.376628488f, -0.926364362f},
169
+ {0.370557427f, -0.928809524f}, {0.364470512f, -0.931214929f},
170
+ {0.358367950f, -0.933580399f}, {0.352250040f, -0.935905933f},
171
+ {0.346117049f, -0.938191354f}, {0.339969248f, -0.940436542f},
172
+ {0.333806872f, -0.942641497f}, {0.327630192f, -0.944806039f},
173
+ {0.321439475f, -0.946930110f}, {0.315234989f, -0.949013650f},
174
+ {0.309017003f, -0.951056540f}, {0.302785784f, -0.953058660f},
175
+ {0.296541572f, -0.955019951f}, {0.290284663f, -0.956940353f},
176
+ {0.284015357f, -0.958819747f}, {0.277733833f, -0.960658073f},
177
+ {0.271440446f, -0.962455213f}, {0.265135437f, -0.964211166f},
178
+ {0.258819044f, -0.965925813f}, {0.252491564f, -0.967599094f},
179
+ {0.246153295f, -0.969230890f}, {0.239804462f, -0.970821202f},
180
+ {0.233445361f, -0.972369909f}, {0.227076262f, -0.973876953f},
181
+ {0.220697433f, -0.975342333f}, {0.214309156f, -0.976765871f},
182
+ {0.207911685f, -0.978147626f}, {0.201505318f, -0.979487419f},
183
+ {0.195090324f, -0.980785251f}, {0.188666970f, -0.982041121f},
184
+ {0.182235524f, -0.983254910f}, {0.175796285f, -0.984426558f},
185
+ {0.169349506f, -0.985556066f}, {0.162895471f, -0.986643314f},
186
+ {0.156434461f, -0.987688363f}, {0.149966761f, -0.988691032f},
187
+ {0.143492624f, -0.989651382f}, {0.137012348f, -0.990569353f},
188
+ {0.130526185f, -0.991444886f}, {0.124034449f, -0.992277920f},
189
+ {0.117537394f, -0.993068457f}, {0.111035310f, -0.993816435f},
190
+ {0.104528464f, -0.994521916f}, {0.0980171412f, -0.995184720f},
191
+ {0.0915016159f, -0.995804906f}, {0.0849821791f, -0.996382475f},
192
+ {0.0784590989f, -0.996917307f}, {0.0719326511f, -0.997409463f},
193
+ {0.0654031262f, -0.997858942f}, {0.0588708036f, -0.998265624f},
194
+ {0.0523359552f, -0.998629510f}, {0.0457988679f, -0.998950660f},
195
+ {0.0392598175f, -0.999229014f}, {0.0327190831f, -0.999464571f},
196
+ {0.0261769481f, -0.999657333f}, {0.0196336918f, -0.999807239f},
197
+ {0.0130895954f, -0.999914348f}, {0.00654493785f, -0.999978602f},
198
+ {6.12323426e-17f, -1.00000000f}, {-0.00654493785f, -0.999978602f},
199
+ {-0.0130895954f, -0.999914348f}, {-0.0196336918f, -0.999807239f},
200
+ {-0.0261769481f, -0.999657333f}, {-0.0327190831f, -0.999464571f},
201
+ {-0.0392598175f, -0.999229014f}, {-0.0457988679f, -0.998950660f},
202
+ {-0.0523359552f, -0.998629510f}, {-0.0588708036f, -0.998265624f},
203
+ {-0.0654031262f, -0.997858942f}, {-0.0719326511f, -0.997409463f},
204
+ {-0.0784590989f, -0.996917307f}, {-0.0849821791f, -0.996382475f},
205
+ {-0.0915016159f, -0.995804906f}, {-0.0980171412f, -0.995184720f},
206
+ {-0.104528464f, -0.994521916f}, {-0.111035310f, -0.993816435f},
207
+ {-0.117537394f, -0.993068457f}, {-0.124034449f, -0.992277920f},
208
+ {-0.130526185f, -0.991444886f}, {-0.137012348f, -0.990569353f},
209
+ {-0.143492624f, -0.989651382f}, {-0.149966761f, -0.988691032f},
210
+ {-0.156434461f, -0.987688363f}, {-0.162895471f, -0.986643314f},
211
+ {-0.169349506f, -0.985556066f}, {-0.175796285f, -0.984426558f},
212
+ {-0.182235524f, -0.983254910f}, {-0.188666970f, -0.982041121f},
213
+ {-0.195090324f, -0.980785251f}, {-0.201505318f, -0.979487419f},
214
+ {-0.207911685f, -0.978147626f}, {-0.214309156f, -0.976765871f},
215
+ {-0.220697433f, -0.975342333f}, {-0.227076262f, -0.973876953f},
216
+ {-0.233445361f, -0.972369909f}, {-0.239804462f, -0.970821202f},
217
+ {-0.246153295f, -0.969230890f}, {-0.252491564f, -0.967599094f},
218
+ {-0.258819044f, -0.965925813f}, {-0.265135437f, -0.964211166f},
219
+ {-0.271440446f, -0.962455213f}, {-0.277733833f, -0.960658073f},
220
+ {-0.284015357f, -0.958819747f}, {-0.290284663f, -0.956940353f},
221
+ {-0.296541572f, -0.955019951f}, {-0.302785784f, -0.953058660f},
222
+ {-0.309017003f, -0.951056540f}, {-0.315234989f, -0.949013650f},
223
+ {-0.321439475f, -0.946930110f}, {-0.327630192f, -0.944806039f},
224
+ {-0.333806872f, -0.942641497f}, {-0.339969248f, -0.940436542f},
225
+ {-0.346117049f, -0.938191354f}, {-0.352250040f, -0.935905933f},
226
+ {-0.358367950f, -0.933580399f}, {-0.364470512f, -0.931214929f},
227
+ {-0.370557427f, -0.928809524f}, {-0.376628488f, -0.926364362f},
228
+ {-0.382683426f, -0.923879504f}, {-0.388721973f, -0.921355128f},
229
+ {-0.394743860f, -0.918791234f}, {-0.400748819f, -0.916187942f},
230
+ {-0.406736642f, -0.913545430f}, {-0.412707031f, -0.910863817f},
231
+ {-0.418659747f, -0.908143163f}, {-0.424594522f, -0.905383646f},
232
+ {-0.430511087f, -0.902585268f}, {-0.436409235f, -0.899748266f},
233
+ {-0.442288697f, -0.896872759f}, {-0.448149204f, -0.893958807f},
234
+ {-0.453990489f, -0.891006529f}, {-0.459812373f, -0.888016105f},
235
+ {-0.465614527f, -0.884987652f}, {-0.471396744f, -0.881921291f},
236
+ {-0.477158755f, -0.878817141f}, {-0.482900351f, -0.875675321f},
237
+ {-0.488621235f, -0.872496009f}, {-0.494321197f, -0.869279325f},
238
+ {-0.500000000f, -0.866025388f}, {-0.505657375f, -0.862734377f},
239
+ {-0.511293113f, -0.859406412f}, {-0.516906917f, -0.856041610f},
240
+ {-0.522498548f, -0.852640152f}, {-0.528067827f, -0.849202156f},
241
+ {-0.533614516f, -0.845727801f}, {-0.539138317f, -0.842217207f},
242
+ {-0.544639051f, -0.838670552f}, {-0.550116420f, -0.835087955f},
243
+ {-0.555570245f, -0.831469595f}, {-0.561000228f, -0.827815652f},
244
+ {-0.566406250f, -0.824126184f}, {-0.571787953f, -0.820401430f},
245
+ {-0.577145219f, -0.816641569f}, {-0.582477689f, -0.812846661f},
246
+ {-0.587785244f, -0.809017003f}, {-0.593067646f, -0.805152655f},
247
+ {-0.598324597f, -0.801253796f}, {-0.603555918f, -0.797320664f},
248
+ {-0.608761430f, -0.793353319f}, {-0.613940835f, -0.789352059f},
249
+ {-0.619093955f, -0.785316944f}, {-0.624220550f, -0.781248152f},
250
+ {-0.629320383f, -0.777145982f}, {-0.634393275f, -0.773010433f},
251
+ {-0.639438987f, -0.768841803f}, {-0.644457340f, -0.764640272f},
252
+ {-0.649448037f, -0.760405958f}, {-0.654410958f, -0.756139100f},
253
+ {-0.659345806f, -0.751839817f}, {-0.664252460f, -0.747508347f},
254
+ {-0.669130623f, -0.743144810f}, {-0.673980117f, -0.738749504f},
255
+ {-0.678800762f, -0.734322488f}, {-0.683592319f, -0.729864061f},
256
+ {-0.688354552f, -0.725374401f}, {-0.693087339f, -0.720853567f},
257
+ {-0.697790444f, -0.716301918f}, {-0.702463686f, -0.711719632f},
258
+ {-0.707106769f, -0.707106769f}, {-0.711719632f, -0.702463686f},
259
+ {-0.716301918f, -0.697790444f}, {-0.720853567f, -0.693087339f},
260
+ {-0.725374401f, -0.688354552f}, {-0.729864061f, -0.683592319f},
261
+ {-0.734322488f, -0.678800762f}, {-0.738749504f, -0.673980117f},
262
+ {-0.743144810f, -0.669130623f}, {-0.747508347f, -0.664252460f},
263
+ {-0.751839817f, -0.659345806f}, {-0.756139100f, -0.654410958f},
264
+ {-0.760405958f, -0.649448037f}, {-0.764640272f, -0.644457340f},
265
+ {-0.768841803f, -0.639438987f}, {-0.773010433f, -0.634393275f},
266
+ {-0.777145982f, -0.629320383f}, {-0.781248152f, -0.624220550f},
267
+ {-0.785316944f, -0.619093955f}, {-0.789352059f, -0.613940835f},
268
+ {-0.793353319f, -0.608761430f}, {-0.797320664f, -0.603555918f},
269
+ {-0.801253796f, -0.598324597f}, {-0.805152655f, -0.593067646f},
270
+ {-0.809017003f, -0.587785244f}, {-0.812846661f, -0.582477689f},
271
+ {-0.816641569f, -0.577145219f}, {-0.820401430f, -0.571787953f},
272
+ {-0.824126184f, -0.566406250f}, {-0.827815652f, -0.561000228f},
273
+ {-0.831469595f, -0.555570245f}, {-0.835087955f, -0.550116420f},
274
+ {-0.838670552f, -0.544639051f}, {-0.842217207f, -0.539138317f},
275
+ {-0.845727801f, -0.533614516f}, {-0.849202156f, -0.528067827f},
276
+ {-0.852640152f, -0.522498548f}, {-0.856041610f, -0.516906917f},
277
+ {-0.859406412f, -0.511293113f}, {-0.862734377f, -0.505657375f},
278
+ {-0.866025388f, -0.500000000f}, {-0.869279325f, -0.494321197f},
279
+ {-0.872496009f, -0.488621235f}, {-0.875675321f, -0.482900351f},
280
+ {-0.878817141f, -0.477158755f}, {-0.881921291f, -0.471396744f},
281
+ {-0.884987652f, -0.465614527f}, {-0.888016105f, -0.459812373f},
282
+ {-0.891006529f, -0.453990489f}, {-0.893958807f, -0.448149204f},
283
+ {-0.896872759f, -0.442288697f}, {-0.899748266f, -0.436409235f},
284
+ {-0.902585268f, -0.430511087f}, {-0.905383646f, -0.424594522f},
285
+ {-0.908143163f, -0.418659747f}, {-0.910863817f, -0.412707031f},
286
+ {-0.913545430f, -0.406736642f}, {-0.916187942f, -0.400748819f},
287
+ {-0.918791234f, -0.394743860f}, {-0.921355128f, -0.388721973f},
288
+ {-0.923879504f, -0.382683426f}, {-0.926364362f, -0.376628488f},
289
+ {-0.928809524f, -0.370557427f}, {-0.931214929f, -0.364470512f},
290
+ {-0.933580399f, -0.358367950f}, {-0.935905933f, -0.352250040f},
291
+ {-0.938191354f, -0.346117049f}, {-0.940436542f, -0.339969248f},
292
+ {-0.942641497f, -0.333806872f}, {-0.944806039f, -0.327630192f},
293
+ {-0.946930110f, -0.321439475f}, {-0.949013650f, -0.315234989f},
294
+ {-0.951056540f, -0.309017003f}, {-0.953058660f, -0.302785784f},
295
+ {-0.955019951f, -0.296541572f}, {-0.956940353f, -0.290284663f},
296
+ {-0.958819747f, -0.284015357f}, {-0.960658073f, -0.277733833f},
297
+ {-0.962455213f, -0.271440446f}, {-0.964211166f, -0.265135437f},
298
+ {-0.965925813f, -0.258819044f}, {-0.967599094f, -0.252491564f},
299
+ {-0.969230890f, -0.246153295f}, {-0.970821202f, -0.239804462f},
300
+ {-0.972369909f, -0.233445361f}, {-0.973876953f, -0.227076262f},
301
+ {-0.975342333f, -0.220697433f}, {-0.976765871f, -0.214309156f},
302
+ {-0.978147626f, -0.207911685f}, {-0.979487419f, -0.201505318f},
303
+ {-0.980785251f, -0.195090324f}, {-0.982041121f, -0.188666970f},
304
+ {-0.983254910f, -0.182235524f}, {-0.984426558f, -0.175796285f},
305
+ {-0.985556066f, -0.169349506f}, {-0.986643314f, -0.162895471f},
306
+ {-0.987688363f, -0.156434461f}, {-0.988691032f, -0.149966761f},
307
+ {-0.989651382f, -0.143492624f}, {-0.990569353f, -0.137012348f},
308
+ {-0.991444886f, -0.130526185f}, {-0.992277920f, -0.124034449f},
309
+ {-0.993068457f, -0.117537394f}, {-0.993816435f, -0.111035310f},
310
+ {-0.994521916f, -0.104528464f}, {-0.995184720f, -0.0980171412f},
311
+ {-0.995804906f, -0.0915016159f}, {-0.996382475f, -0.0849821791f},
312
+ {-0.996917307f, -0.0784590989f}, {-0.997409463f, -0.0719326511f},
313
+ {-0.997858942f, -0.0654031262f}, {-0.998265624f, -0.0588708036f},
314
+ {-0.998629510f, -0.0523359552f}, {-0.998950660f, -0.0457988679f},
315
+ {-0.999229014f, -0.0392598175f}, {-0.999464571f, -0.0327190831f},
316
+ {-0.999657333f, -0.0261769481f}, {-0.999807239f, -0.0196336918f},
317
+ {-0.999914348f, -0.0130895954f}, {-0.999978602f, -0.00654493785f},
318
+ {-1.00000000f, -1.22464685e-16f}, {-0.999978602f, 0.00654493785f},
319
+ {-0.999914348f, 0.0130895954f}, {-0.999807239f, 0.0196336918f},
320
+ {-0.999657333f, 0.0261769481f}, {-0.999464571f, 0.0327190831f},
321
+ {-0.999229014f, 0.0392598175f}, {-0.998950660f, 0.0457988679f},
322
+ {-0.998629510f, 0.0523359552f}, {-0.998265624f, 0.0588708036f},
323
+ {-0.997858942f, 0.0654031262f}, {-0.997409463f, 0.0719326511f},
324
+ {-0.996917307f, 0.0784590989f}, {-0.996382475f, 0.0849821791f},
325
+ {-0.995804906f, 0.0915016159f}, {-0.995184720f, 0.0980171412f},
326
+ {-0.994521916f, 0.104528464f}, {-0.993816435f, 0.111035310f},
327
+ {-0.993068457f, 0.117537394f}, {-0.992277920f, 0.124034449f},
328
+ {-0.991444886f, 0.130526185f}, {-0.990569353f, 0.137012348f},
329
+ {-0.989651382f, 0.143492624f}, {-0.988691032f, 0.149966761f},
330
+ {-0.987688363f, 0.156434461f}, {-0.986643314f, 0.162895471f},
331
+ {-0.985556066f, 0.169349506f}, {-0.984426558f, 0.175796285f},
332
+ {-0.983254910f, 0.182235524f}, {-0.982041121f, 0.188666970f},
333
+ {-0.980785251f, 0.195090324f}, {-0.979487419f, 0.201505318f},
334
+ {-0.978147626f, 0.207911685f}, {-0.976765871f, 0.214309156f},
335
+ {-0.975342333f, 0.220697433f}, {-0.973876953f, 0.227076262f},
336
+ {-0.972369909f, 0.233445361f}, {-0.970821202f, 0.239804462f},
337
+ {-0.969230890f, 0.246153295f}, {-0.967599094f, 0.252491564f},
338
+ {-0.965925813f, 0.258819044f}, {-0.964211166f, 0.265135437f},
339
+ {-0.962455213f, 0.271440446f}, {-0.960658073f, 0.277733833f},
340
+ {-0.958819747f, 0.284015357f}, {-0.956940353f, 0.290284663f},
341
+ {-0.955019951f, 0.296541572f}, {-0.953058660f, 0.302785784f},
342
+ {-0.951056540f, 0.309017003f}, {-0.949013650f, 0.315234989f},
343
+ {-0.946930110f, 0.321439475f}, {-0.944806039f, 0.327630192f},
344
+ {-0.942641497f, 0.333806872f}, {-0.940436542f, 0.339969248f},
345
+ {-0.938191354f, 0.346117049f}, {-0.935905933f, 0.352250040f},
346
+ {-0.933580399f, 0.358367950f}, {-0.931214929f, 0.364470512f},
347
+ {-0.928809524f, 0.370557427f}, {-0.926364362f, 0.376628488f},
348
+ {-0.923879504f, 0.382683426f}, {-0.921355128f, 0.388721973f},
349
+ {-0.918791234f, 0.394743860f}, {-0.916187942f, 0.400748819f},
350
+ {-0.913545430f, 0.406736642f}, {-0.910863817f, 0.412707031f},
351
+ {-0.908143163f, 0.418659747f}, {-0.905383646f, 0.424594522f},
352
+ {-0.902585268f, 0.430511087f}, {-0.899748266f, 0.436409235f},
353
+ {-0.896872759f, 0.442288697f}, {-0.893958807f, 0.448149204f},
354
+ {-0.891006529f, 0.453990489f}, {-0.888016105f, 0.459812373f},
355
+ {-0.884987652f, 0.465614527f}, {-0.881921291f, 0.471396744f},
356
+ {-0.878817141f, 0.477158755f}, {-0.875675321f, 0.482900351f},
357
+ {-0.872496009f, 0.488621235f}, {-0.869279325f, 0.494321197f},
358
+ {-0.866025388f, 0.500000000f}, {-0.862734377f, 0.505657375f},
359
+ {-0.859406412f, 0.511293113f}, {-0.856041610f, 0.516906917f},
360
+ {-0.852640152f, 0.522498548f}, {-0.849202156f, 0.528067827f},
361
+ {-0.845727801f, 0.533614516f}, {-0.842217207f, 0.539138317f},
362
+ {-0.838670552f, 0.544639051f}, {-0.835087955f, 0.550116420f},
363
+ {-0.831469595f, 0.555570245f}, {-0.827815652f, 0.561000228f},
364
+ {-0.824126184f, 0.566406250f}, {-0.820401430f, 0.571787953f},
365
+ {-0.816641569f, 0.577145219f}, {-0.812846661f, 0.582477689f},
366
+ {-0.809017003f, 0.587785244f}, {-0.805152655f, 0.593067646f},
367
+ {-0.801253796f, 0.598324597f}, {-0.797320664f, 0.603555918f},
368
+ {-0.793353319f, 0.608761430f}, {-0.789352059f, 0.613940835f},
369
+ {-0.785316944f, 0.619093955f}, {-0.781248152f, 0.624220550f},
370
+ {-0.777145982f, 0.629320383f}, {-0.773010433f, 0.634393275f},
371
+ {-0.768841803f, 0.639438987f}, {-0.764640272f, 0.644457340f},
372
+ {-0.760405958f, 0.649448037f}, {-0.756139100f, 0.654410958f},
373
+ {-0.751839817f, 0.659345806f}, {-0.747508347f, 0.664252460f},
374
+ {-0.743144810f, 0.669130623f}, {-0.738749504f, 0.673980117f},
375
+ {-0.734322488f, 0.678800762f}, {-0.729864061f, 0.683592319f},
376
+ {-0.725374401f, 0.688354552f}, {-0.720853567f, 0.693087339f},
377
+ {-0.716301918f, 0.697790444f}, {-0.711719632f, 0.702463686f},
378
+ {-0.707106769f, 0.707106769f}, {-0.702463686f, 0.711719632f},
379
+ {-0.697790444f, 0.716301918f}, {-0.693087339f, 0.720853567f},
380
+ {-0.688354552f, 0.725374401f}, {-0.683592319f, 0.729864061f},
381
+ {-0.678800762f, 0.734322488f}, {-0.673980117f, 0.738749504f},
382
+ {-0.669130623f, 0.743144810f}, {-0.664252460f, 0.747508347f},
383
+ {-0.659345806f, 0.751839817f}, {-0.654410958f, 0.756139100f},
384
+ {-0.649448037f, 0.760405958f}, {-0.644457340f, 0.764640272f},
385
+ {-0.639438987f, 0.768841803f}, {-0.634393275f, 0.773010433f},
386
+ {-0.629320383f, 0.777145982f}, {-0.624220550f, 0.781248152f},
387
+ {-0.619093955f, 0.785316944f}, {-0.613940835f, 0.789352059f},
388
+ {-0.608761430f, 0.793353319f}, {-0.603555918f, 0.797320664f},
389
+ {-0.598324597f, 0.801253796f}, {-0.593067646f, 0.805152655f},
390
+ {-0.587785244f, 0.809017003f}, {-0.582477689f, 0.812846661f},
391
+ {-0.577145219f, 0.816641569f}, {-0.571787953f, 0.820401430f},
392
+ {-0.566406250f, 0.824126184f}, {-0.561000228f, 0.827815652f},
393
+ {-0.555570245f, 0.831469595f}, {-0.550116420f, 0.835087955f},
394
+ {-0.544639051f, 0.838670552f}, {-0.539138317f, 0.842217207f},
395
+ {-0.533614516f, 0.845727801f}, {-0.528067827f, 0.849202156f},
396
+ {-0.522498548f, 0.852640152f}, {-0.516906917f, 0.856041610f},
397
+ {-0.511293113f, 0.859406412f}, {-0.505657375f, 0.862734377f},
398
+ {-0.500000000f, 0.866025388f}, {-0.494321197f, 0.869279325f},
399
+ {-0.488621235f, 0.872496009f}, {-0.482900351f, 0.875675321f},
400
+ {-0.477158755f, 0.878817141f}, {-0.471396744f, 0.881921291f},
401
+ {-0.465614527f, 0.884987652f}, {-0.459812373f, 0.888016105f},
402
+ {-0.453990489f, 0.891006529f}, {-0.448149204f, 0.893958807f},
403
+ {-0.442288697f, 0.896872759f}, {-0.436409235f, 0.899748266f},
404
+ {-0.430511087f, 0.902585268f}, {-0.424594522f, 0.905383646f},
405
+ {-0.418659747f, 0.908143163f}, {-0.412707031f, 0.910863817f},
406
+ {-0.406736642f, 0.913545430f}, {-0.400748819f, 0.916187942f},
407
+ {-0.394743860f, 0.918791234f}, {-0.388721973f, 0.921355128f},
408
+ {-0.382683426f, 0.923879504f}, {-0.376628488f, 0.926364362f},
409
+ {-0.370557427f, 0.928809524f}, {-0.364470512f, 0.931214929f},
410
+ {-0.358367950f, 0.933580399f}, {-0.352250040f, 0.935905933f},
411
+ {-0.346117049f, 0.938191354f}, {-0.339969248f, 0.940436542f},
412
+ {-0.333806872f, 0.942641497f}, {-0.327630192f, 0.944806039f},
413
+ {-0.321439475f, 0.946930110f}, {-0.315234989f, 0.949013650f},
414
+ {-0.309017003f, 0.951056540f}, {-0.302785784f, 0.953058660f},
415
+ {-0.296541572f, 0.955019951f}, {-0.290284663f, 0.956940353f},
416
+ {-0.284015357f, 0.958819747f}, {-0.277733833f, 0.960658073f},
417
+ {-0.271440446f, 0.962455213f}, {-0.265135437f, 0.964211166f},
418
+ {-0.258819044f, 0.965925813f}, {-0.252491564f, 0.967599094f},
419
+ {-0.246153295f, 0.969230890f}, {-0.239804462f, 0.970821202f},
420
+ {-0.233445361f, 0.972369909f}, {-0.227076262f, 0.973876953f},
421
+ {-0.220697433f, 0.975342333f}, {-0.214309156f, 0.976765871f},
422
+ {-0.207911685f, 0.978147626f}, {-0.201505318f, 0.979487419f},
423
+ {-0.195090324f, 0.980785251f}, {-0.188666970f, 0.982041121f},
424
+ {-0.182235524f, 0.983254910f}, {-0.175796285f, 0.984426558f},
425
+ {-0.169349506f, 0.985556066f}, {-0.162895471f, 0.986643314f},
426
+ {-0.156434461f, 0.987688363f}, {-0.149966761f, 0.988691032f},
427
+ {-0.143492624f, 0.989651382f}, {-0.137012348f, 0.990569353f},
428
+ {-0.130526185f, 0.991444886f}, {-0.124034449f, 0.992277920f},
429
+ {-0.117537394f, 0.993068457f}, {-0.111035310f, 0.993816435f},
430
+ {-0.104528464f, 0.994521916f}, {-0.0980171412f, 0.995184720f},
431
+ {-0.0915016159f, 0.995804906f}, {-0.0849821791f, 0.996382475f},
432
+ {-0.0784590989f, 0.996917307f}, {-0.0719326511f, 0.997409463f},
433
+ {-0.0654031262f, 0.997858942f}, {-0.0588708036f, 0.998265624f},
434
+ {-0.0523359552f, 0.998629510f}, {-0.0457988679f, 0.998950660f},
435
+ {-0.0392598175f, 0.999229014f}, {-0.0327190831f, 0.999464571f},
436
+ {-0.0261769481f, 0.999657333f}, {-0.0196336918f, 0.999807239f},
437
+ {-0.0130895954f, 0.999914348f}, {-0.00654493785f, 0.999978602f},
438
+ {-1.83697015e-16f, 1.00000000f}, {0.00654493785f, 0.999978602f},
439
+ {0.0130895954f, 0.999914348f}, {0.0196336918f, 0.999807239f},
440
+ {0.0261769481f, 0.999657333f}, {0.0327190831f, 0.999464571f},
441
+ {0.0392598175f, 0.999229014f}, {0.0457988679f, 0.998950660f},
442
+ {0.0523359552f, 0.998629510f}, {0.0588708036f, 0.998265624f},
443
+ {0.0654031262f, 0.997858942f}, {0.0719326511f, 0.997409463f},
444
+ {0.0784590989f, 0.996917307f}, {0.0849821791f, 0.996382475f},
445
+ {0.0915016159f, 0.995804906f}, {0.0980171412f, 0.995184720f},
446
+ {0.104528464f, 0.994521916f}, {0.111035310f, 0.993816435f},
447
+ {0.117537394f, 0.993068457f}, {0.124034449f, 0.992277920f},
448
+ {0.130526185f, 0.991444886f}, {0.137012348f, 0.990569353f},
449
+ {0.143492624f, 0.989651382f}, {0.149966761f, 0.988691032f},
450
+ {0.156434461f, 0.987688363f}, {0.162895471f, 0.986643314f},
451
+ {0.169349506f, 0.985556066f}, {0.175796285f, 0.984426558f},
452
+ {0.182235524f, 0.983254910f}, {0.188666970f, 0.982041121f},
453
+ {0.195090324f, 0.980785251f}, {0.201505318f, 0.979487419f},
454
+ {0.207911685f, 0.978147626f}, {0.214309156f, 0.976765871f},
455
+ {0.220697433f, 0.975342333f}, {0.227076262f, 0.973876953f},
456
+ {0.233445361f, 0.972369909f}, {0.239804462f, 0.970821202f},
457
+ {0.246153295f, 0.969230890f}, {0.252491564f, 0.967599094f},
458
+ {0.258819044f, 0.965925813f}, {0.265135437f, 0.964211166f},
459
+ {0.271440446f, 0.962455213f}, {0.277733833f, 0.960658073f},
460
+ {0.284015357f, 0.958819747f}, {0.290284663f, 0.956940353f},
461
+ {0.296541572f, 0.955019951f}, {0.302785784f, 0.953058660f},
462
+ {0.309017003f, 0.951056540f}, {0.315234989f, 0.949013650f},
463
+ {0.321439475f, 0.946930110f}, {0.327630192f, 0.944806039f},
464
+ {0.333806872f, 0.942641497f}, {0.339969248f, 0.940436542f},
465
+ {0.346117049f, 0.938191354f}, {0.352250040f, 0.935905933f},
466
+ {0.358367950f, 0.933580399f}, {0.364470512f, 0.931214929f},
467
+ {0.370557427f, 0.928809524f}, {0.376628488f, 0.926364362f},
468
+ {0.382683426f, 0.923879504f}, {0.388721973f, 0.921355128f},
469
+ {0.394743860f, 0.918791234f}, {0.400748819f, 0.916187942f},
470
+ {0.406736642f, 0.913545430f}, {0.412707031f, 0.910863817f},
471
+ {0.418659747f, 0.908143163f}, {0.424594522f, 0.905383646f},
472
+ {0.430511087f, 0.902585268f}, {0.436409235f, 0.899748266f},
473
+ {0.442288697f, 0.896872759f}, {0.448149204f, 0.893958807f},
474
+ {0.453990489f, 0.891006529f}, {0.459812373f, 0.888016105f},
475
+ {0.465614527f, 0.884987652f}, {0.471396744f, 0.881921291f},
476
+ {0.477158755f, 0.878817141f}, {0.482900351f, 0.875675321f},
477
+ {0.488621235f, 0.872496009f}, {0.494321197f, 0.869279325f},
478
+ {0.500000000f, 0.866025388f}, {0.505657375f, 0.862734377f},
479
+ {0.511293113f, 0.859406412f}, {0.516906917f, 0.856041610f},
480
+ {0.522498548f, 0.852640152f}, {0.528067827f, 0.849202156f},
481
+ {0.533614516f, 0.845727801f}, {0.539138317f, 0.842217207f},
482
+ {0.544639051f, 0.838670552f}, {0.550116420f, 0.835087955f},
483
+ {0.555570245f, 0.831469595f}, {0.561000228f, 0.827815652f},
484
+ {0.566406250f, 0.824126184f}, {0.571787953f, 0.820401430f},
485
+ {0.577145219f, 0.816641569f}, {0.582477689f, 0.812846661f},
486
+ {0.587785244f, 0.809017003f}, {0.593067646f, 0.805152655f},
487
+ {0.598324597f, 0.801253796f}, {0.603555918f, 0.797320664f},
488
+ {0.608761430f, 0.793353319f}, {0.613940835f, 0.789352059f},
489
+ {0.619093955f, 0.785316944f}, {0.624220550f, 0.781248152f},
490
+ {0.629320383f, 0.777145982f}, {0.634393275f, 0.773010433f},
491
+ {0.639438987f, 0.768841803f}, {0.644457340f, 0.764640272f},
492
+ {0.649448037f, 0.760405958f}, {0.654410958f, 0.756139100f},
493
+ {0.659345806f, 0.751839817f}, {0.664252460f, 0.747508347f},
494
+ {0.669130623f, 0.743144810f}, {0.673980117f, 0.738749504f},
495
+ {0.678800762f, 0.734322488f}, {0.683592319f, 0.729864061f},
496
+ {0.688354552f, 0.725374401f}, {0.693087339f, 0.720853567f},
497
+ {0.697790444f, 0.716301918f}, {0.702463686f, 0.711719632f},
498
+ {0.707106769f, 0.707106769f}, {0.711719632f, 0.702463686f},
499
+ {0.716301918f, 0.697790444f}, {0.720853567f, 0.693087339f},
500
+ {0.725374401f, 0.688354552f}, {0.729864061f, 0.683592319f},
501
+ {0.734322488f, 0.678800762f}, {0.738749504f, 0.673980117f},
502
+ {0.743144810f, 0.669130623f}, {0.747508347f, 0.664252460f},
503
+ {0.751839817f, 0.659345806f}, {0.756139100f, 0.654410958f},
504
+ {0.760405958f, 0.649448037f}, {0.764640272f, 0.644457340f},
505
+ {0.768841803f, 0.639438987f}, {0.773010433f, 0.634393275f},
506
+ {0.777145982f, 0.629320383f}, {0.781248152f, 0.624220550f},
507
+ {0.785316944f, 0.619093955f}, {0.789352059f, 0.613940835f},
508
+ {0.793353319f, 0.608761430f}, {0.797320664f, 0.603555918f},
509
+ {0.801253796f, 0.598324597f}, {0.805152655f, 0.593067646f},
510
+ {0.809017003f, 0.587785244f}, {0.812846661f, 0.582477689f},
511
+ {0.816641569f, 0.577145219f}, {0.820401430f, 0.571787953f},
512
+ {0.824126184f, 0.566406250f}, {0.827815652f, 0.561000228f},
513
+ {0.831469595f, 0.555570245f}, {0.835087955f, 0.550116420f},
514
+ {0.838670552f, 0.544639051f}, {0.842217207f, 0.539138317f},
515
+ {0.845727801f, 0.533614516f}, {0.849202156f, 0.528067827f},
516
+ {0.852640152f, 0.522498548f}, {0.856041610f, 0.516906917f},
517
+ {0.859406412f, 0.511293113f}, {0.862734377f, 0.505657375f},
518
+ {0.866025388f, 0.500000000f}, {0.869279325f, 0.494321197f},
519
+ {0.872496009f, 0.488621235f}, {0.875675321f, 0.482900351f},
520
+ {0.878817141f, 0.477158755f}, {0.881921291f, 0.471396744f},
521
+ {0.884987652f, 0.465614527f}, {0.888016105f, 0.459812373f},
522
+ {0.891006529f, 0.453990489f}, {0.893958807f, 0.448149204f},
523
+ {0.896872759f, 0.442288697f}, {0.899748266f, 0.436409235f},
524
+ {0.902585268f, 0.430511087f}, {0.905383646f, 0.424594522f},
525
+ {0.908143163f, 0.418659747f}, {0.910863817f, 0.412707031f},
526
+ {0.913545430f, 0.406736642f}, {0.916187942f, 0.400748819f},
527
+ {0.918791234f, 0.394743860f}, {0.921355128f, 0.388721973f},
528
+ {0.923879504f, 0.382683426f}, {0.926364362f, 0.376628488f},
529
+ {0.928809524f, 0.370557427f}, {0.931214929f, 0.364470512f},
530
+ {0.933580399f, 0.358367950f}, {0.935905933f, 0.352250040f},
531
+ {0.938191354f, 0.346117049f}, {0.940436542f, 0.339969248f},
532
+ {0.942641497f, 0.333806872f}, {0.944806039f, 0.327630192f},
533
+ {0.946930110f, 0.321439475f}, {0.949013650f, 0.315234989f},
534
+ {0.951056540f, 0.309017003f}, {0.953058660f, 0.302785784f},
535
+ {0.955019951f, 0.296541572f}, {0.956940353f, 0.290284663f},
536
+ {0.958819747f, 0.284015357f}, {0.960658073f, 0.277733833f},
537
+ {0.962455213f, 0.271440446f}, {0.964211166f, 0.265135437f},
538
+ {0.965925813f, 0.258819044f}, {0.967599094f, 0.252491564f},
539
+ {0.969230890f, 0.246153295f}, {0.970821202f, 0.239804462f},
540
+ {0.972369909f, 0.233445361f}, {0.973876953f, 0.227076262f},
541
+ {0.975342333f, 0.220697433f}, {0.976765871f, 0.214309156f},
542
+ {0.978147626f, 0.207911685f}, {0.979487419f, 0.201505318f},
543
+ {0.980785251f, 0.195090324f}, {0.982041121f, 0.188666970f},
544
+ {0.983254910f, 0.182235524f}, {0.984426558f, 0.175796285f},
545
+ {0.985556066f, 0.169349506f}, {0.986643314f, 0.162895471f},
546
+ {0.987688363f, 0.156434461f}, {0.988691032f, 0.149966761f},
547
+ {0.989651382f, 0.143492624f}, {0.990569353f, 0.137012348f},
548
+ {0.991444886f, 0.130526185f}, {0.992277920f, 0.124034449f},
549
+ {0.993068457f, 0.117537394f}, {0.993816435f, 0.111035310f},
550
+ {0.994521916f, 0.104528464f}, {0.995184720f, 0.0980171412f},
551
+ {0.995804906f, 0.0915016159f}, {0.996382475f, 0.0849821791f},
552
+ {0.996917307f, 0.0784590989f}, {0.997409463f, 0.0719326511f},
553
+ {0.997858942f, 0.0654031262f}, {0.998265624f, 0.0588708036f},
554
+ {0.998629510f, 0.0523359552f}, {0.998950660f, 0.0457988679f},
555
+ {0.999229014f, 0.0392598175f}, {0.999464571f, 0.0327190831f},
556
+ {0.999657333f, 0.0261769481f}, {0.999807239f, 0.0196336918f},
557
+ {0.999914348f, 0.0130895954f}, {0.999978602f, 0.00654493785f},
558
+ };
559
+
560
+ const kiss_fft_state rnn_kfft = {
561
+ 960, /* nfft */
562
+ 0.0010416667f, /* scale */
563
+ -1, /* shift */
564
+ {5, 192, 3, 64, 4, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
565
+ fft_bitrev, /* bitrev*/
566
+ fft_twiddles, /* twiddles*/
567
+ (arch_fft_state *)&arch_fft, /* arch_fft*/
568
+ };
569
+
570
+ const float rnn_half_window[] = {
571
+ 4.20549168e-06f, 3.78491532e-05f, 0.000105135041f, 0.000206060256f, 0.000340620492f,
572
+ 0.000508809986f, 0.000710621476f, 0.000946046319f, 0.00121507444f, 0.00151769421f,
573
+ 0.00185389258f, 0.00222365512f, 0.00262696599f, 0.00306380726f, 0.00353416055f,
574
+ 0.00403800514f, 0.00457531959f, 0.00514607970f, 0.00575026125f, 0.00638783723f,
575
+ 0.00705878017f, 0.00776306028f, 0.00850064680f, 0.00927150715f, 0.0100756064f,
576
+ 0.0109129101f, 0.0117833801f, 0.0126869772f, 0.0136236614f, 0.0145933898f,
577
+ 0.0155961197f, 0.0166318044f, 0.0177003983f, 0.0188018531f, 0.0199361145f,
578
+ 0.0211031344f, 0.0223028567f, 0.0235352255f, 0.0248001851f, 0.0260976739f,
579
+ 0.0274276342f, 0.0287899990f, 0.0301847085f, 0.0316116922f, 0.0330708846f,
580
+ 0.0345622115f, 0.0360856056f, 0.0376409888f, 0.0392282903f, 0.0408474281f,
581
+ 0.0424983241f, 0.0441808924f, 0.0458950549f, 0.0476407260f, 0.0494178124f,
582
+ 0.0512262285f, 0.0530658774f, 0.0549366735f, 0.0568385124f, 0.0587713011f,
583
+ 0.0607349351f, 0.0627293140f, 0.0647543296f, 0.0668098852f, 0.0688958541f,
584
+ 0.0710121393f, 0.0731586292f, 0.0753351897f, 0.0775417164f, 0.0797780901f,
585
+ 0.0820441842f, 0.0843398646f, 0.0866650119f, 0.0890194997f, 0.0914031938f,
586
+ 0.0938159525f, 0.0962576419f, 0.0987281203f, 0.101227246f, 0.103754878f,
587
+ 0.106310867f, 0.108895063f, 0.111507311f, 0.114147455f, 0.116815343f,
588
+ 0.119510807f, 0.122233689f, 0.124983832f, 0.127761051f, 0.130565181f,
589
+ 0.133396059f, 0.136253506f, 0.139137328f, 0.142047361f, 0.144983411f,
590
+ 0.147945285f, 0.150932819f, 0.153945804f, 0.156984031f, 0.160047337f,
591
+ 0.163135484f, 0.166248307f, 0.169385567f, 0.172547072f, 0.175732598f,
592
+ 0.178941950f, 0.182174906f, 0.185431242f, 0.188710734f, 0.192013159f,
593
+ 0.195338294f, 0.198685899f, 0.202055752f, 0.205447599f, 0.208861232f,
594
+ 0.212296382f, 0.215752810f, 0.219230279f, 0.222728521f, 0.226247311f,
595
+ 0.229786381f, 0.233345464f, 0.236924306f, 0.240522653f, 0.244140238f,
596
+ 0.247776777f, 0.251432031f, 0.255105674f, 0.258797467f, 0.262507141f,
597
+ 0.266234398f, 0.269978970f, 0.273740560f, 0.277518868f, 0.281313598f,
598
+ 0.285124481f, 0.288951218f, 0.292793512f, 0.296651065f, 0.300523549f,
599
+ 0.304410696f, 0.308312178f, 0.312227666f, 0.316156894f, 0.320099503f,
600
+ 0.324055225f, 0.328023702f, 0.332004637f, 0.335997701f, 0.340002567f,
601
+ 0.344018906f, 0.348046392f, 0.352084726f, 0.356133521f, 0.360192508f,
602
+ 0.364261299f, 0.368339598f, 0.372427016f, 0.376523286f, 0.380627990f,
603
+ 0.384740859f, 0.388861477f, 0.392989576f, 0.397124738f, 0.401266664f,
604
+ 0.405414969f, 0.409569323f, 0.413729399f, 0.417894781f, 0.422065198f,
605
+ 0.426240236f, 0.430419534f, 0.434602767f, 0.438789606f, 0.442979604f,
606
+ 0.447172493f, 0.451367885f, 0.455565393f, 0.459764689f, 0.463965416f,
607
+ 0.468167186f, 0.472369671f, 0.476572484f, 0.480775267f, 0.484977663f,
608
+ 0.489179343f, 0.493379891f, 0.497579008f, 0.501776278f, 0.505971372f,
609
+ 0.510163903f, 0.514353573f, 0.518539906f, 0.522722721f, 0.526901484f,
610
+ 0.531075954f, 0.535245717f, 0.539410412f, 0.543569744f, 0.547723293f,
611
+ 0.551870763f, 0.556011736f, 0.560145974f, 0.564273000f, 0.568392515f,
612
+ 0.572504222f, 0.576607704f, 0.580702662f, 0.584788740f, 0.588865638f,
613
+ 0.592932940f, 0.596990347f, 0.601037502f, 0.605074167f, 0.609099925f,
614
+ 0.613114417f, 0.617117405f, 0.621108532f, 0.625087440f, 0.629053831f,
615
+ 0.633007407f, 0.636947870f, 0.640874863f, 0.644788086f, 0.648687243f,
616
+ 0.652572036f, 0.656442165f, 0.660297334f, 0.664137185f, 0.667961538f,
617
+ 0.671769977f, 0.675562322f, 0.679338276f, 0.683097482f, 0.686839759f,
618
+ 0.690564752f, 0.694272280f, 0.697961986f, 0.701633692f, 0.705287039f,
619
+ 0.708921850f, 0.712537885f, 0.716134787f, 0.719712436f, 0.723270535f,
620
+ 0.726808906f, 0.730327189f, 0.733825266f, 0.737302899f, 0.740759790f,
621
+ 0.744195819f, 0.747610688f, 0.751004279f, 0.754376352f, 0.757726669f,
622
+ 0.761055112f, 0.764361382f, 0.767645359f, 0.770906866f, 0.774145722f,
623
+ 0.777361751f, 0.780554771f, 0.783724606f, 0.786871076f, 0.789994121f,
624
+ 0.793093503f, 0.796169102f, 0.799220800f, 0.802248418f, 0.805251837f,
625
+ 0.808230937f, 0.811185598f, 0.814115703f, 0.817021132f, 0.819901764f,
626
+ 0.822757542f, 0.825588286f, 0.828393936f, 0.831174433f, 0.833929658f,
627
+ 0.836659551f, 0.839363992f, 0.842042983f, 0.844696403f, 0.847324252f,
628
+ 0.849926353f, 0.852502763f, 0.855053425f, 0.857578218f, 0.860077202f,
629
+ 0.862550259f, 0.864997447f, 0.867418647f, 0.869813919f, 0.872183204f,
630
+ 0.874526560f, 0.876843870f, 0.879135191f, 0.881400526f, 0.883639932f,
631
+ 0.885853291f, 0.888040781f, 0.890202343f, 0.892337978f, 0.894447744f,
632
+ 0.896531701f, 0.898589849f, 0.900622249f, 0.902628958f, 0.904610038f,
633
+ 0.906565487f, 0.908495426f, 0.910399914f, 0.912279010f, 0.914132774f,
634
+ 0.915961266f, 0.917764664f, 0.919542909f, 0.921296239f, 0.923024654f,
635
+ 0.924728215f, 0.926407158f, 0.928061485f, 0.929691315f, 0.931296766f,
636
+ 0.932878017f, 0.934435070f, 0.935968161f, 0.937477291f, 0.938962698f,
637
+ 0.940424502f, 0.941862822f, 0.943277776f, 0.944669485f, 0.946038187f,
638
+ 0.947383940f, 0.948706925f, 0.950007319f, 0.951285243f, 0.952540874f,
639
+ 0.953774393f, 0.954985917f, 0.956175685f, 0.957343817f, 0.958490491f,
640
+ 0.959615886f, 0.960720181f, 0.961803555f, 0.962866247f, 0.963908315f,
641
+ 0.964930058f, 0.965931594f, 0.966913164f, 0.967874944f, 0.968817174f,
642
+ 0.969739914f, 0.970643520f, 0.971528113f, 0.972393870f, 0.973241091f,
643
+ 0.974069893f, 0.974880517f, 0.975673139f, 0.976447999f, 0.977205336f,
644
+ 0.977945268f, 0.978668094f, 0.979374051f, 0.980063200f, 0.980735898f,
645
+ 0.981392324f, 0.982032716f, 0.982657254f, 0.983266115f, 0.983859658f,
646
+ 0.984437943f, 0.985001266f, 0.985549867f, 0.986083925f, 0.986603677f,
647
+ 0.987109363f, 0.987601161f, 0.988079309f, 0.988544047f, 0.988995552f,
648
+ 0.989434063f, 0.989859879f, 0.990273118f, 0.990674019f, 0.991062820f,
649
+ 0.991439700f, 0.991804957f, 0.992158771f, 0.992501318f, 0.992832899f,
650
+ 0.993153632f, 0.993463814f, 0.993763626f, 0.994053245f, 0.994332969f,
651
+ 0.994602919f, 0.994863331f, 0.995114446f, 0.995356441f, 0.995589554f,
652
+ 0.995813966f, 0.996029854f, 0.996237516f, 0.996437073f, 0.996628702f,
653
+ 0.996812642f, 0.996989131f, 0.997158289f, 0.997320294f, 0.997475445f,
654
+ 0.997623861f, 0.997765720f, 0.997901261f, 0.998030603f, 0.998153925f,
655
+ 0.998271465f, 0.998383403f, 0.998489857f, 0.998591006f, 0.998687088f,
656
+ 0.998778164f, 0.998864532f, 0.998946249f, 0.999023557f, 0.999096513f,
657
+ 0.999165416f, 0.999230266f, 0.999291301f, 0.999348700f, 0.999402523f,
658
+ 0.999453008f, 0.999500215f, 0.999544322f, 0.999585509f, 0.999623775f,
659
+ 0.999659419f, 0.999692440f, 0.999723017f, 0.999751270f, 0.999777317f,
660
+ 0.999801278f, 0.999823213f, 0.999843359f, 0.999861658f, 0.999878347f,
661
+ 0.999893486f, 0.999907196f, 0.999919534f, 0.999930561f, 0.999940455f,
662
+ 0.999949217f, 0.999957025f, 0.999963880f, 0.999969840f, 0.999975085f,
663
+ 0.999979615f, 0.999983490f, 0.999986768f, 0.999989510f, 0.999991834f,
664
+ 0.999993742f, 0.999995291f, 0.999996543f, 0.999997556f, 0.999998271f,
665
+ 0.999998868f, 0.999999285f, 0.999999523f, 0.999999762f, 0.999999881f,
666
+ 0.999999940f, 1.00000000f, 1.00000000f, 1.00000000f, 1.00000000f,
667
+ };
668
+
669
+ const float rnn_dct_table[] = {
670
+ 0.707106769f, 0.998795450f, 0.995184720f, 0.989176512f, 0.980785251f,
671
+ 0.970031261f, 0.956940353f, 0.941544056f, 0.923879504f, 0.903989315f,
672
+ 0.881921291f, 0.857728601f, 0.831469595f, 0.803207517f, 0.773010433f,
673
+ 0.740951121f, 0.707106769f, 0.671558976f, 0.634393275f, 0.595699310f,
674
+ 0.555570245f, 0.514102757f, 0.471396744f, 0.427555084f, 0.382683426f,
675
+ 0.336889863f, 0.290284663f, 0.242980182f, 0.195090324f, 0.146730468f,
676
+ 0.0980171412f, 0.0490676761f, 0.707106769f, 0.989176512f, 0.956940353f,
677
+ 0.903989315f, 0.831469595f, 0.740951121f, 0.634393275f, 0.514102757f,
678
+ 0.382683426f, 0.242980182f, 0.0980171412f, -0.0490676761f, -0.195090324f,
679
+ -0.336889863f, -0.471396744f, -0.595699310f, -0.707106769f, -0.803207517f,
680
+ -0.881921291f, -0.941544056f, -0.980785251f, -0.998795450f, -0.995184720f,
681
+ -0.970031261f, -0.923879504f, -0.857728601f, -0.773010433f, -0.671558976f,
682
+ -0.555570245f, -0.427555084f, -0.290284663f, -0.146730468f, 0.707106769f,
683
+ 0.970031261f, 0.881921291f, 0.740951121f, 0.555570245f, 0.336889863f,
684
+ 0.0980171412f, -0.146730468f, -0.382683426f, -0.595699310f, -0.773010433f,
685
+ -0.903989315f, -0.980785251f, -0.998795450f, -0.956940353f, -0.857728601f,
686
+ -0.707106769f, -0.514102757f, -0.290284663f, -0.0490676761f, 0.195090324f,
687
+ 0.427555084f, 0.634393275f, 0.803207517f, 0.923879504f, 0.989176512f,
688
+ 0.995184720f, 0.941544056f, 0.831469595f, 0.671558976f, 0.471396744f,
689
+ 0.242980182f, 0.707106769f, 0.941544056f, 0.773010433f, 0.514102757f,
690
+ 0.195090324f, -0.146730468f, -0.471396744f, -0.740951121f, -0.923879504f,
691
+ -0.998795450f, -0.956940353f, -0.803207517f, -0.555570245f, -0.242980182f,
692
+ 0.0980171412f, 0.427555084f, 0.707106769f, 0.903989315f, 0.995184720f,
693
+ 0.970031261f, 0.831469595f, 0.595699310f, 0.290284663f, -0.0490676761f,
694
+ -0.382683426f, -0.671558976f, -0.881921291f, -0.989176512f, -0.980785251f,
695
+ -0.857728601f, -0.634393275f, -0.336889863f, 0.707106769f, 0.903989315f,
696
+ 0.634393275f, 0.242980182f, -0.195090324f, -0.595699310f, -0.881921291f,
697
+ -0.998795450f, -0.923879504f, -0.671558976f, -0.290284663f, 0.146730468f,
698
+ 0.555570245f, 0.857728601f, 0.995184720f, 0.941544056f, 0.707106769f,
699
+ 0.336889863f, -0.0980171412f, -0.514102757f, -0.831469595f, -0.989176512f,
700
+ -0.956940353f, -0.740951121f, -0.382683426f, 0.0490676761f, 0.471396744f,
701
+ 0.803207517f, 0.980785251f, 0.970031261f, 0.773010433f, 0.427555084f,
702
+ 0.707106769f, 0.857728601f, 0.471396744f, -0.0490676761f, -0.555570245f,
703
+ -0.903989315f, -0.995184720f, -0.803207517f, -0.382683426f, 0.146730468f,
704
+ 0.634393275f, 0.941544056f, 0.980785251f, 0.740951121f, 0.290284663f,
705
+ -0.242980182f, -0.707106769f, -0.970031261f, -0.956940353f, -0.671558976f,
706
+ -0.195090324f, 0.336889863f, 0.773010433f, 0.989176512f, 0.923879504f,
707
+ 0.595699310f, 0.0980171412f, -0.427555084f, -0.831469595f, -0.998795450f,
708
+ -0.881921291f, -0.514102757f, 0.707106769f, 0.803207517f, 0.290284663f,
709
+ -0.336889863f, -0.831469595f, -0.998795450f, -0.773010433f, -0.242980182f,
710
+ 0.382683426f, 0.857728601f, 0.995184720f, 0.740951121f, 0.195090324f,
711
+ -0.427555084f, -0.881921291f, -0.989176512f, -0.707106769f, -0.146730468f,
712
+ 0.471396744f, 0.903989315f, 0.980785251f, 0.671558976f, 0.0980171412f,
713
+ -0.514102757f, -0.923879504f, -0.970031261f, -0.634393275f, -0.0490676761f,
714
+ 0.555570245f, 0.941544056f, 0.956940353f, 0.595699310f, 0.707106769f,
715
+ 0.740951121f, 0.0980171412f, -0.595699310f, -0.980785251f, -0.857728601f,
716
+ -0.290284663f, 0.427555084f, 0.923879504f, 0.941544056f, 0.471396744f,
717
+ -0.242980182f, -0.831469595f, -0.989176512f, -0.634393275f, 0.0490676761f,
718
+ 0.707106769f, 0.998795450f, 0.773010433f, 0.146730468f, -0.555570245f,
719
+ -0.970031261f, -0.881921291f, -0.336889863f, 0.382683426f, 0.903989315f,
720
+ 0.956940353f, 0.514102757f, -0.195090324f, -0.803207517f, -0.995184720f,
721
+ -0.671558976f, 0.707106769f, 0.671558976f, -0.0980171412f, -0.803207517f,
722
+ -0.980785251f, -0.514102757f, 0.290284663f, 0.903989315f, 0.923879504f,
723
+ 0.336889863f, -0.471396744f, -0.970031261f, -0.831469595f, -0.146730468f,
724
+ 0.634393275f, 0.998795450f, 0.707106769f, -0.0490676761f, -0.773010433f,
725
+ -0.989176512f, -0.555570245f, 0.242980182f, 0.881921291f, 0.941544056f,
726
+ 0.382683426f, -0.427555084f, -0.956940353f, -0.857728601f, -0.195090324f,
727
+ 0.595699310f, 0.995184720f, 0.740951121f, 0.707106769f, 0.595699310f,
728
+ -0.290284663f, -0.941544056f, -0.831469595f, -0.0490676761f, 0.773010433f,
729
+ 0.970031261f, 0.382683426f, -0.514102757f, -0.995184720f, -0.671558976f,
730
+ 0.195090324f, 0.903989315f, 0.881921291f, 0.146730468f, -0.707106769f,
731
+ -0.989176512f, -0.471396744f, 0.427555084f, 0.980785251f, 0.740951121f,
732
+ -0.0980171412f, -0.857728601f, -0.923879504f, -0.242980182f, 0.634393275f,
733
+ 0.998795450f, 0.555570245f, -0.336889863f, -0.956940353f, -0.803207517f,
734
+ 0.707106769f, 0.514102757f, -0.471396744f, -0.998795450f, -0.555570245f,
735
+ 0.427555084f, 0.995184720f, 0.595699310f, -0.382683426f, -0.989176512f,
736
+ -0.634393275f, 0.336889863f, 0.980785251f, 0.671558976f, -0.290284663f,
737
+ -0.970031261f, -0.707106769f, 0.242980182f, 0.956940353f, 0.740951121f,
738
+ -0.195090324f, -0.941544056f, -0.773010433f, 0.146730468f, 0.923879504f,
739
+ 0.803207517f, -0.0980171412f, -0.903989315f, -0.831469595f, 0.0490676761f,
740
+ 0.881921291f, 0.857728601f, 0.707106769f, 0.427555084f, -0.634393275f,
741
+ -0.970031261f, -0.195090324f, 0.803207517f, 0.881921291f, -0.0490676761f,
742
+ -0.923879504f, -0.740951121f, 0.290284663f, 0.989176512f, 0.555570245f,
743
+ -0.514102757f, -0.995184720f, -0.336889863f, 0.707106769f, 0.941544056f,
744
+ 0.0980171412f, -0.857728601f, -0.831469595f, 0.146730468f, 0.956940353f,
745
+ 0.671558976f, -0.382683426f, -0.998795450f, -0.471396744f, 0.595699310f,
746
+ 0.980785251f, 0.242980182f, -0.773010433f, -0.903989315f, 0.707106769f,
747
+ 0.336889863f, -0.773010433f, -0.857728601f, 0.195090324f, 0.989176512f,
748
+ 0.471396744f, -0.671558976f, -0.923879504f, 0.0490676761f, 0.956940353f,
749
+ 0.595699310f, -0.555570245f, -0.970031261f, -0.0980171412f, 0.903989315f,
750
+ 0.707106769f, -0.427555084f, -0.995184720f, -0.242980182f, 0.831469595f,
751
+ 0.803207517f, -0.290284663f, -0.998795450f, -0.382683426f, 0.740951121f,
752
+ 0.881921291f, -0.146730468f, -0.980785251f, -0.514102757f, 0.634393275f,
753
+ 0.941544056f, 0.707106769f, 0.242980182f, -0.881921291f, -0.671558976f,
754
+ 0.555570245f, 0.941544056f, -0.0980171412f, -0.989176512f, -0.382683426f,
755
+ 0.803207517f, 0.773010433f, -0.427555084f, -0.980785251f, -0.0490676761f,
756
+ 0.956940353f, 0.514102757f, -0.707106769f, -0.857728601f, 0.290284663f,
757
+ 0.998795450f, 0.195090324f, -0.903989315f, -0.634393275f, 0.595699310f,
758
+ 0.923879504f, -0.146730468f, -0.995184720f, -0.336889863f, 0.831469595f,
759
+ 0.740951121f, -0.471396744f, -0.970031261f, 0.707106769f, 0.146730468f,
760
+ -0.956940353f, -0.427555084f, 0.831469595f, 0.671558976f, -0.634393275f,
761
+ -0.857728601f, 0.382683426f, 0.970031261f, -0.0980171412f, -0.998795450f,
762
+ -0.195090324f, 0.941544056f, 0.471396744f, -0.803207517f, -0.707106769f,
763
+ 0.595699310f, 0.881921291f, -0.336889863f, -0.980785251f, 0.0490676761f,
764
+ 0.995184720f, 0.242980182f, -0.923879504f, -0.514102757f, 0.773010433f,
765
+ 0.740951121f, -0.555570245f, -0.903989315f, 0.290284663f, 0.989176512f,
766
+ 0.707106769f, 0.0490676761f, -0.995184720f, -0.146730468f, 0.980785251f,
767
+ 0.242980182f, -0.956940353f, -0.336889863f, 0.923879504f, 0.427555084f,
768
+ -0.881921291f, -0.514102757f, 0.831469595f, 0.595699310f, -0.773010433f,
769
+ -0.671558976f, 0.707106769f, 0.740951121f, -0.634393275f, -0.803207517f,
770
+ 0.555570245f, 0.857728601f, -0.471396744f, -0.903989315f, 0.382683426f,
771
+ 0.941544056f, -0.290284663f, -0.970031261f, 0.195090324f, 0.989176512f,
772
+ -0.0980171412f, -0.998795450f, 0.707106769f, -0.0490676761f, -0.995184720f,
773
+ 0.146730468f, 0.980785251f, -0.242980182f, -0.956940353f, 0.336889863f,
774
+ 0.923879504f, -0.427555084f, -0.881921291f, 0.514102757f, 0.831469595f,
775
+ -0.595699310f, -0.773010433f, 0.671558976f, 0.707106769f, -0.740951121f,
776
+ -0.634393275f, 0.803207517f, 0.555570245f, -0.857728601f, -0.471396744f,
777
+ 0.903989315f, 0.382683426f, -0.941544056f, -0.290284663f, 0.970031261f,
778
+ 0.195090324f, -0.989176512f, -0.0980171412f, 0.998795450f, 0.707106769f,
779
+ -0.146730468f, -0.956940353f, 0.427555084f, 0.831469595f, -0.671558976f,
780
+ -0.634393275f, 0.857728601f, 0.382683426f, -0.970031261f, -0.0980171412f,
781
+ 0.998795450f, -0.195090324f, -0.941544056f, 0.471396744f, 0.803207517f,
782
+ -0.707106769f, -0.595699310f, 0.881921291f, 0.336889863f, -0.980785251f,
783
+ -0.0490676761f, 0.995184720f, -0.242980182f, -0.923879504f, 0.514102757f,
784
+ 0.773010433f, -0.740951121f, -0.555570245f, 0.903989315f, 0.290284663f,
785
+ -0.989176512f, 0.707106769f, -0.242980182f, -0.881921291f, 0.671558976f,
786
+ 0.555570245f, -0.941544056f, -0.0980171412f, 0.989176512f, -0.382683426f,
787
+ -0.803207517f, 0.773010433f, 0.427555084f, -0.980785251f, 0.0490676761f,
788
+ 0.956940353f, -0.514102757f, -0.707106769f, 0.857728601f, 0.290284663f,
789
+ -0.998795450f, 0.195090324f, 0.903989315f, -0.634393275f, -0.595699310f,
790
+ 0.923879504f, 0.146730468f, -0.995184720f, 0.336889863f, 0.831469595f,
791
+ -0.740951121f, -0.471396744f, 0.970031261f, 0.707106769f, -0.336889863f,
792
+ -0.773010433f, 0.857728601f, 0.195090324f, -0.989176512f, 0.471396744f,
793
+ 0.671558976f, -0.923879504f, -0.0490676761f, 0.956940353f, -0.595699310f,
794
+ -0.555570245f, 0.970031261f, -0.0980171412f, -0.903989315f, 0.707106769f,
795
+ 0.427555084f, -0.995184720f, 0.242980182f, 0.831469595f, -0.803207517f,
796
+ -0.290284663f, 0.998795450f, -0.382683426f, -0.740951121f, 0.881921291f,
797
+ 0.146730468f, -0.980785251f, 0.514102757f, 0.634393275f, -0.941544056f,
798
+ 0.707106769f, -0.427555084f, -0.634393275f, 0.970031261f, -0.195090324f,
799
+ -0.803207517f, 0.881921291f, 0.0490676761f, -0.923879504f, 0.740951121f,
800
+ 0.290284663f, -0.989176512f, 0.555570245f, 0.514102757f, -0.995184720f,
801
+ 0.336889863f, 0.707106769f, -0.941544056f, 0.0980171412f, 0.857728601f,
802
+ -0.831469595f, -0.146730468f, 0.956940353f, -0.671558976f, -0.382683426f,
803
+ 0.998795450f, -0.471396744f, -0.595699310f, 0.980785251f, -0.242980182f,
804
+ -0.773010433f, 0.903989315f, 0.707106769f, -0.514102757f, -0.471396744f,
805
+ 0.998795450f, -0.555570245f, -0.427555084f, 0.995184720f, -0.595699310f,
806
+ -0.382683426f, 0.989176512f, -0.634393275f, -0.336889863f, 0.980785251f,
807
+ -0.671558976f, -0.290284663f, 0.970031261f, -0.707106769f, -0.242980182f,
808
+ 0.956940353f, -0.740951121f, -0.195090324f, 0.941544056f, -0.773010433f,
809
+ -0.146730468f, 0.923879504f, -0.803207517f, -0.0980171412f, 0.903989315f,
810
+ -0.831469595f, -0.0490676761f, 0.881921291f, -0.857728601f, 0.707106769f,
811
+ -0.595699310f, -0.290284663f, 0.941544056f, -0.831469595f, 0.0490676761f,
812
+ 0.773010433f, -0.970031261f, 0.382683426f, 0.514102757f, -0.995184720f,
813
+ 0.671558976f, 0.195090324f, -0.903989315f, 0.881921291f, -0.146730468f,
814
+ -0.707106769f, 0.989176512f, -0.471396744f, -0.427555084f, 0.980785251f,
815
+ -0.740951121f, -0.0980171412f, 0.857728601f, -0.923879504f, 0.242980182f,
816
+ 0.634393275f, -0.998795450f, 0.555570245f, 0.336889863f, -0.956940353f,
817
+ 0.803207517f, 0.707106769f, -0.671558976f, -0.0980171412f, 0.803207517f,
818
+ -0.980785251f, 0.514102757f, 0.290284663f, -0.903989315f, 0.923879504f,
819
+ -0.336889863f, -0.471396744f, 0.970031261f, -0.831469595f, 0.146730468f,
820
+ 0.634393275f, -0.998795450f, 0.707106769f, 0.0490676761f, -0.773010433f,
821
+ 0.989176512f, -0.555570245f, -0.242980182f, 0.881921291f, -0.941544056f,
822
+ 0.382683426f, 0.427555084f, -0.956940353f, 0.857728601f, -0.195090324f,
823
+ -0.595699310f, 0.995184720f, -0.740951121f, 0.707106769f, -0.740951121f,
824
+ 0.0980171412f, 0.595699310f, -0.980785251f, 0.857728601f, -0.290284663f,
825
+ -0.427555084f, 0.923879504f, -0.941544056f, 0.471396744f, 0.242980182f,
826
+ -0.831469595f, 0.989176512f, -0.634393275f, -0.0490676761f, 0.707106769f,
827
+ -0.998795450f, 0.773010433f, -0.146730468f, -0.555570245f, 0.970031261f,
828
+ -0.881921291f, 0.336889863f, 0.382683426f, -0.903989315f, 0.956940353f,
829
+ -0.514102757f, -0.195090324f, 0.803207517f, -0.995184720f, 0.671558976f,
830
+ 0.707106769f, -0.803207517f, 0.290284663f, 0.336889863f, -0.831469595f,
831
+ 0.998795450f, -0.773010433f, 0.242980182f, 0.382683426f, -0.857728601f,
832
+ 0.995184720f, -0.740951121f, 0.195090324f, 0.427555084f, -0.881921291f,
833
+ 0.989176512f, -0.707106769f, 0.146730468f, 0.471396744f, -0.903989315f,
834
+ 0.980785251f, -0.671558976f, 0.0980171412f, 0.514102757f, -0.923879504f,
835
+ 0.970031261f, -0.634393275f, 0.0490676761f, 0.555570245f, -0.941544056f,
836
+ 0.956940353f, -0.595699310f, 0.707106769f, -0.857728601f, 0.471396744f,
837
+ 0.0490676761f, -0.555570245f, 0.903989315f, -0.995184720f, 0.803207517f,
838
+ -0.382683426f, -0.146730468f, 0.634393275f, -0.941544056f, 0.980785251f,
839
+ -0.740951121f, 0.290284663f, 0.242980182f, -0.707106769f, 0.970031261f,
840
+ -0.956940353f, 0.671558976f, -0.195090324f, -0.336889863f, 0.773010433f,
841
+ -0.989176512f, 0.923879504f, -0.595699310f, 0.0980171412f, 0.427555084f,
842
+ -0.831469595f, 0.998795450f, -0.881921291f, 0.514102757f, 0.707106769f,
843
+ -0.903989315f, 0.634393275f, -0.242980182f, -0.195090324f, 0.595699310f,
844
+ -0.881921291f, 0.998795450f, -0.923879504f, 0.671558976f, -0.290284663f,
845
+ -0.146730468f, 0.555570245f, -0.857728601f, 0.995184720f, -0.941544056f,
846
+ 0.707106769f, -0.336889863f, -0.0980171412f, 0.514102757f, -0.831469595f,
847
+ 0.989176512f, -0.956940353f, 0.740951121f, -0.382683426f, -0.0490676761f,
848
+ 0.471396744f, -0.803207517f, 0.980785251f, -0.970031261f, 0.773010433f,
849
+ -0.427555084f, 0.707106769f, -0.941544056f, 0.773010433f, -0.514102757f,
850
+ 0.195090324f, 0.146730468f, -0.471396744f, 0.740951121f, -0.923879504f,
851
+ 0.998795450f, -0.956940353f, 0.803207517f, -0.555570245f, 0.242980182f,
852
+ 0.0980171412f, -0.427555084f, 0.707106769f, -0.903989315f, 0.995184720f,
853
+ -0.970031261f, 0.831469595f, -0.595699310f, 0.290284663f, 0.0490676761f,
854
+ -0.382683426f, 0.671558976f, -0.881921291f, 0.989176512f, -0.980785251f,
855
+ 0.857728601f, -0.634393275f, 0.336889863f, 0.707106769f, -0.970031261f,
856
+ 0.881921291f, -0.740951121f, 0.555570245f, -0.336889863f, 0.0980171412f,
857
+ 0.146730468f, -0.382683426f, 0.595699310f, -0.773010433f, 0.903989315f,
858
+ -0.980785251f, 0.998795450f, -0.956940353f, 0.857728601f, -0.707106769f,
859
+ 0.514102757f, -0.290284663f, 0.0490676761f, 0.195090324f, -0.427555084f,
860
+ 0.634393275f, -0.803207517f, 0.923879504f, -0.989176512f, 0.995184720f,
861
+ -0.941544056f, 0.831469595f, -0.671558976f, 0.471396744f, -0.242980182f,
862
+ 0.707106769f, -0.989176512f, 0.956940353f, -0.903989315f, 0.831469595f,
863
+ -0.740951121f, 0.634393275f, -0.514102757f, 0.382683426f, -0.242980182f,
864
+ 0.0980171412f, 0.0490676761f, -0.195090324f, 0.336889863f, -0.471396744f,
865
+ 0.595699310f, -0.707106769f, 0.803207517f, -0.881921291f, 0.941544056f,
866
+ -0.980785251f, 0.998795450f, -0.995184720f, 0.970031261f, -0.923879504f,
867
+ 0.857728601f, -0.773010433f, 0.671558976f, -0.555570245f, 0.427555084f,
868
+ -0.290284663f, 0.146730468f, 0.707106769f, -0.998795450f, 0.995184720f,
869
+ -0.989176512f, 0.980785251f, -0.970031261f, 0.956940353f, -0.941544056f,
870
+ 0.923879504f, -0.903989315f, 0.881921291f, -0.857728601f, 0.831469595f,
871
+ -0.803207517f, 0.773010433f, -0.740951121f, 0.707106769f, -0.671558976f,
872
+ 0.634393275f, -0.595699310f, 0.555570245f, -0.514102757f, 0.471396744f,
873
+ -0.427555084f, 0.382683426f, -0.336889863f, 0.290284663f, -0.242980182f,
874
+ 0.195090324f, -0.146730468f, 0.0980171412f, -0.0490676761f, };
cpp/src/rnnoise/vec.h ADDED
@@ -0,0 +1,388 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018 Mozilla
2
+ 2008-2011 Octasic Inc.
3
+ 2012-2017 Jean-Marc Valin */
4
+ /*
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ - Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+
12
+ - Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #ifndef VEC_H
30
+ #define VEC_H
31
+
32
+ #include "opus_types.h"
33
+ #include "common.h"
34
+ #include <math.h>
35
+ #include "arch.h"
36
+ #include "x86/x86_arch_macros.h"
37
+
38
+
39
+ #if defined(__AVX__) || defined(__SSE2__)
40
+ #include "vec_avx.h"
41
+ #elif (defined(__ARM_NEON__) || defined(__ARM_NEON)) && !defined(DISABLE_NEON)
42
+ #include "vec_neon.h"
43
+ #else
44
+
45
+ #define MAX_INPUTS (2048)
46
+
47
+ #define NO_OPTIMIZATIONS
48
+
49
+ static inline void sgemv16x1(float *out, const float *weights, int rows, int cols, int col_stride, const float *x)
50
+ {
51
+ int i, j;
52
+ RNN_CLEAR(out, rows);
53
+ for (i=0;i<rows;i+=16)
54
+ {
55
+ for (j=0;j<cols;j++)
56
+ {
57
+ const float * restrict w;
58
+ float * restrict y;
59
+ float xj;
60
+ w = &weights[j*col_stride + i];
61
+ xj = x[j];
62
+ y = &out[i];
63
+ y[0] += w[0]*xj;
64
+ y[1] += w[1]*xj;
65
+ y[2] += w[2]*xj;
66
+ y[3] += w[3]*xj;
67
+ y[4] += w[4]*xj;
68
+ y[5] += w[5]*xj;
69
+ y[6] += w[6]*xj;
70
+ y[7] += w[7]*xj;
71
+ y[8] += w[8]*xj;
72
+ y[9] += w[9]*xj;
73
+ y[10] += w[10]*xj;
74
+ y[11] += w[11]*xj;
75
+ y[12] += w[12]*xj;
76
+ y[13] += w[13]*xj;
77
+ y[14] += w[14]*xj;
78
+ y[15] += w[15]*xj;
79
+ }
80
+ }
81
+ }
82
+
83
+ static inline void sgemv8x1(float *out, const float *weights, int rows, int cols, int col_stride, const float *x)
84
+ {
85
+ int i, j;
86
+ RNN_CLEAR(out, rows);
87
+ for (i=0;i<rows;i+=8)
88
+ {
89
+ for (j=0;j<cols;j++)
90
+ {
91
+ const float * restrict w;
92
+ float * restrict y;
93
+ float xj;
94
+ w = &weights[j*col_stride + i];
95
+ xj = x[j];
96
+ y = &out[i];
97
+ y[0] += w[0]*xj;
98
+ y[1] += w[1]*xj;
99
+ y[2] += w[2]*xj;
100
+ y[3] += w[3]*xj;
101
+ y[4] += w[4]*xj;
102
+ y[5] += w[5]*xj;
103
+ y[6] += w[6]*xj;
104
+ y[7] += w[7]*xj;
105
+ }
106
+ }
107
+ }
108
+
109
+ static inline void sgemv(float *out, const float *weights, int rows, int cols, int col_stride, const float *x)
110
+ {
111
+ if ((rows&0xf) == 0) sgemv16x1(out, weights, rows, cols, col_stride, x);
112
+ else if ((rows&0x7) == 0) sgemv8x1(out, weights, rows, cols, col_stride, x);
113
+ else {
114
+ int i, j;
115
+ for (i=0;i<rows;i++)
116
+ {
117
+ out[i] = 0;
118
+ for (j=0;j<cols;j++) out[i] += weights[j*col_stride + i]*x[j];
119
+ }
120
+ }
121
+ }
122
+
123
+ static inline void sparse_sgemv8x4(float *out, const float *w, const int *idx, int rows, const float *x)
124
+ {
125
+ int i, j;
126
+ RNN_CLEAR(out, rows);
127
+ for (i=0;i<rows;i+=8)
128
+ {
129
+ int cols;
130
+ cols = *idx++;
131
+ for (j=0;j<cols;j++)
132
+ {
133
+ int pos;
134
+ float * restrict y;
135
+ float xj0, xj1, xj2, xj3;
136
+ pos = (*idx++);
137
+ xj0 = x[pos+0];
138
+ xj1 = x[pos+1];
139
+ xj2 = x[pos+2];
140
+ xj3 = x[pos+3];
141
+ y = &out[i];
142
+ y[0] += w[0]*xj0;
143
+ y[1] += w[1]*xj0;
144
+ y[2] += w[2]*xj0;
145
+ y[3] += w[3]*xj0;
146
+ y[4] += w[4]*xj0;
147
+ y[5] += w[5]*xj0;
148
+ y[6] += w[6]*xj0;
149
+ y[7] += w[7]*xj0;
150
+
151
+ y[0] += w[8]*xj1;
152
+ y[1] += w[9]*xj1;
153
+ y[2] += w[10]*xj1;
154
+ y[3] += w[11]*xj1;
155
+ y[4] += w[12]*xj1;
156
+ y[5] += w[13]*xj1;
157
+ y[6] += w[14]*xj1;
158
+ y[7] += w[15]*xj1;
159
+
160
+ y[0] += w[16]*xj2;
161
+ y[1] += w[17]*xj2;
162
+ y[2] += w[18]*xj2;
163
+ y[3] += w[19]*xj2;
164
+ y[4] += w[20]*xj2;
165
+ y[5] += w[21]*xj2;
166
+ y[6] += w[22]*xj2;
167
+ y[7] += w[23]*xj2;
168
+
169
+ y[0] += w[24]*xj3;
170
+ y[1] += w[25]*xj3;
171
+ y[2] += w[26]*xj3;
172
+ y[3] += w[27]*xj3;
173
+ y[4] += w[28]*xj3;
174
+ y[5] += w[29]*xj3;
175
+ y[6] += w[30]*xj3;
176
+ y[7] += w[31]*xj3;
177
+ w += 32;
178
+ }
179
+ }
180
+ }
181
+
182
+ #ifdef USE_SU_BIAS
183
+ static inline void sparse_cgemv8x4(float *out, const opus_int8 *w, const int *idx, const float *scale, int rows, int cols, const float *_x)
184
+ {
185
+ int i, j;
186
+ unsigned char x[MAX_INPUTS];
187
+ for (i=0;i<rows;i++) out[i] = 0;
188
+ for (i=0;i<cols;i++) x[i] = 127+floor(.5+127*_x[i]);
189
+ for (i=0;i<rows;i+=8)
190
+ {
191
+ int colblocks;
192
+ colblocks = *idx++;
193
+ for (j=0;j<colblocks;j++)
194
+ {
195
+ int pos;
196
+ float * restrict y;
197
+ int xj0, xj1, xj2, xj3;
198
+ pos = (*idx++);
199
+ xj0 = x[pos+0];
200
+ xj1 = x[pos+1];
201
+ xj2 = x[pos+2];
202
+ xj3 = x[pos+3];
203
+ y = &out[i];
204
+ y[0] += (w[0]*xj0+w[1]*xj1+w[2]*xj2+w[3]*xj3);
205
+ y[1] += (w[4]*xj0+w[5]*xj1+w[6]*xj2+w[7]*xj3);
206
+ y[2] += (w[8]*xj0+w[9]*xj1+w[10]*xj2+w[11]*xj3);
207
+ y[3] += (w[12]*xj0+w[13]*xj1+w[14]*xj2+w[15]*xj3);
208
+ y[4] += (w[16]*xj0+w[17]*xj1+w[18]*xj2+w[19]*xj3);
209
+ y[5] += (w[20]*xj0+w[21]*xj1+w[22]*xj2+w[23]*xj3);
210
+ y[6] += (w[24]*xj0+w[25]*xj1+w[26]*xj2+w[27]*xj3);
211
+ y[7] += (w[28]*xj0+w[29]*xj1+w[30]*xj2+w[31]*xj3);
212
+ w += 32;
213
+ }
214
+ }
215
+ for (i=0;i<rows;i++) out[i] *= scale[i];
216
+ }
217
+ static inline void cgemv8x4(float *out, const opus_int8 *w, const float *scale, int rows, int cols, const float *_x)
218
+ {
219
+ int i, j;
220
+ unsigned char x[MAX_INPUTS];
221
+ for (i=0;i<rows;i++) out[i] = 0;
222
+ for (i=0;i<cols;i++) x[i] = 127+(int)floor(.5+127*_x[i]);
223
+ for (i=0;i<rows;i+=8)
224
+ {
225
+ for (j=0;j<cols;j+=4)
226
+ {
227
+ float *y;
228
+ float xj0, xj1, xj2, xj3;
229
+ xj0 = x[j+0];
230
+ xj1 = x[j+1];
231
+ xj2 = x[j+2];
232
+ xj3 = x[j+3];
233
+ y = &out[i];
234
+ y[0] += (w[0]*xj0+w[1]*xj1+w[2]*xj2+w[3]*xj3);
235
+ y[1] += (w[4]*xj0+w[5]*xj1+w[6]*xj2+w[7]*xj3);
236
+ y[2] += (w[8]*xj0+w[9]*xj1+w[10]*xj2+w[11]*xj3);
237
+ y[3] += (w[12]*xj0+w[13]*xj1+w[14]*xj2+w[15]*xj3);
238
+ y[4] += (w[16]*xj0+w[17]*xj1+w[18]*xj2+w[19]*xj3);
239
+ y[5] += (w[20]*xj0+w[21]*xj1+w[22]*xj2+w[23]*xj3);
240
+ y[6] += (w[24]*xj0+w[25]*xj1+w[26]*xj2+w[27]*xj3);
241
+ y[7] += (w[28]*xj0+w[29]*xj1+w[30]*xj2+w[31]*xj3);
242
+ w += 32;
243
+ }
244
+ }
245
+ for (i=0;i<rows;i++) out[i] *= scale[i];
246
+ }
247
+ #else
248
+ static inline void sparse_cgemv8x4(float *out, const opus_int8 *w, const int *idx, const float *scale, int rows, int cols, const float *_x)
249
+ {
250
+ int i, j;
251
+ opus_int8 x[MAX_INPUTS];
252
+ for (i=0;i<rows;i++) out[i] = 0;
253
+ for (i=0;i<cols;i++) x[i] = (int)floor(.5+127*_x[i]);
254
+ for (i=0;i<rows;i+=8)
255
+ {
256
+ int colblocks;
257
+ colblocks = *idx++;
258
+ for (j=0;j<colblocks;j++)
259
+ {
260
+ int pos;
261
+ float * restrict y;
262
+ int xj0, xj1, xj2, xj3;
263
+ pos = (*idx++);
264
+ xj0 = x[pos+0];
265
+ xj1 = x[pos+1];
266
+ xj2 = x[pos+2];
267
+ xj3 = x[pos+3];
268
+ y = &out[i];
269
+ y[0] += (w[0]*xj0+w[1]*xj1+w[2]*xj2+w[3]*xj3);
270
+ y[1] += (w[4]*xj0+w[5]*xj1+w[6]*xj2+w[7]*xj3);
271
+ y[2] += (w[8]*xj0+w[9]*xj1+w[10]*xj2+w[11]*xj3);
272
+ y[3] += (w[12]*xj0+w[13]*xj1+w[14]*xj2+w[15]*xj3);
273
+ y[4] += (w[16]*xj0+w[17]*xj1+w[18]*xj2+w[19]*xj3);
274
+ y[5] += (w[20]*xj0+w[21]*xj1+w[22]*xj2+w[23]*xj3);
275
+ y[6] += (w[24]*xj0+w[25]*xj1+w[26]*xj2+w[27]*xj3);
276
+ y[7] += (w[28]*xj0+w[29]*xj1+w[30]*xj2+w[31]*xj3);
277
+ w += 32;
278
+ }
279
+ }
280
+ for (i=0;i<rows;i++) out[i] *= scale[i];
281
+ }
282
+ static inline void cgemv8x4(float *out, const opus_int8 *w, const float *scale, int rows, int cols, const float *_x)
283
+ {
284
+ int i, j;
285
+ opus_int8 x[MAX_INPUTS];
286
+ for (i=0;i<rows;i++) out[i] = 0;
287
+ for (i=0;i<cols;i++) x[i] = (int)floor(.5+127*_x[i]);
288
+ for (i=0;i<rows;i+=8)
289
+ {
290
+ for (j=0;j<cols;j+=4)
291
+ {
292
+ float *y;
293
+ float xj0, xj1, xj2, xj3;
294
+ xj0 = x[j+0];
295
+ xj1 = x[j+1];
296
+ xj2 = x[j+2];
297
+ xj3 = x[j+3];
298
+ y = &out[i];
299
+ y[0] += (w[0]*xj0+w[1]*xj1+w[2]*xj2+w[3]*xj3);
300
+ y[1] += (w[4]*xj0+w[5]*xj1+w[6]*xj2+w[7]*xj3);
301
+ y[2] += (w[8]*xj0+w[9]*xj1+w[10]*xj2+w[11]*xj3);
302
+ y[3] += (w[12]*xj0+w[13]*xj1+w[14]*xj2+w[15]*xj3);
303
+ y[4] += (w[16]*xj0+w[17]*xj1+w[18]*xj2+w[19]*xj3);
304
+ y[5] += (w[20]*xj0+w[21]*xj1+w[22]*xj2+w[23]*xj3);
305
+ y[6] += (w[24]*xj0+w[25]*xj1+w[26]*xj2+w[27]*xj3);
306
+ y[7] += (w[28]*xj0+w[29]*xj1+w[30]*xj2+w[31]*xj3);
307
+ w += 32;
308
+ }
309
+ }
310
+ for (i=0;i<rows;i++) out[i] *= scale[i];
311
+ }
312
+ #endif
313
+
314
+ /* No AVX2/FMA support */
315
+ #ifndef LPCNET_TEST
316
+ static inline float lpcnet_exp2(float x)
317
+ {
318
+ int integer;
319
+ float frac;
320
+ union {
321
+ float f;
322
+ opus_uint32 i;
323
+ } res;
324
+ integer = floor(x);
325
+ if (integer < -50)
326
+ return 0;
327
+ frac = x-integer;
328
+ /* K0 = 1, K1 = log(2), K2 = 3-4*log(2), K3 = 3*log(2) - 2 */
329
+ res.f = 0.99992522f + frac * (0.69583354f
330
+ + frac * (0.22606716f + 0.078024523f*frac));
331
+ res.i = (res.i + (integer<<23)) & 0x7fffffff;
332
+ return res.f;
333
+ }
334
+ #define lpcnet_exp(x) lpcnet_exp2((x)*1.44269504f)
335
+
336
+ #define fmadd(a, b, c) ((a)*(b)+(c))
337
+ static OPUS_INLINE float tanh_approx(float x)
338
+ {
339
+ const float N0 = 952.52801514f;
340
+ const float N1 = 96.39235687f;
341
+ const float N2 = 0.60863042f;
342
+ const float D0 = 952.72399902f;
343
+ const float D1 = 413.36801147f;
344
+ const float D2 = 11.88600922f;
345
+ float X2, num, den;
346
+ X2 = x*x;
347
+ num = fmadd(fmadd(N2, X2, N1), X2, N0);
348
+ den = fmadd(fmadd(D2, X2, D1), X2, D0);
349
+ num = num*x/den;
350
+ return MAX32(-1.f, MIN32(1.f, num));
351
+ }
352
+
353
+ static inline float sigmoid_approx(float x)
354
+ {
355
+ return .5f + .5f*tanh_approx(.5f*x);
356
+ }
357
+
358
+ static inline void softmax(float *y, const float *x, int N)
359
+ {
360
+ int i;
361
+ for (i=0;i<N;i++)
362
+ y[i] = lpcnet_exp(x[i]);
363
+ }
364
+
365
+ static inline void vec_tanh(float *y, const float *x, int N)
366
+ {
367
+ int i;
368
+ for (i=0;i<N;i++)
369
+ {
370
+ y[i] = tanh_approx(x[i]);
371
+ }
372
+ }
373
+
374
+ static inline void vec_sigmoid(float *y, const float *x, int N)
375
+ {
376
+ int i;
377
+ for (i=0;i<N;i++)
378
+ {
379
+ y[i] = sigmoid_approx(x[i]);
380
+ }
381
+ }
382
+ #endif
383
+
384
+ #define SCALE (128.f*127.f)
385
+ #define SCALE_1 (1.f/128.f/127.f)
386
+
387
+ #endif /*no optimizations*/
388
+ #endif /*VEC_H*/
cpp/src/rnnoise/vec_avx.h ADDED
@@ -0,0 +1,884 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018 Mozilla
2
+ 2012-2017 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 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
+ AVX implementation of vector operations, compile with -mavx
29
+ AVX2/FMA implementation of vector operations, compile with -mavx2 -mfma
30
+ */
31
+
32
+ #ifndef VEC_AVX_H
33
+ #define VEC_AVX_H
34
+
35
+ #include <immintrin.h>
36
+ #include <math.h>
37
+ #include "x86/x86cpu.h"
38
+
39
+ #define MAX_INPUTS (2048)
40
+
41
+ #define USE_SU_BIAS
42
+
43
+ #ifndef __SSE_4_1__
44
+ static inline __m128 mm_floor_ps(__m128 x) {
45
+ __m128 half = _mm_set1_ps(0.5);
46
+ return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_sub_ps(x, half)));
47
+ }
48
+ #undef _mm_floor_ps
49
+ #define _mm_floor_ps(x) mm_floor_ps(x)
50
+ #endif
51
+
52
+
53
+ /* If we don't have AVX available, emulate what we need with SSE up to 4.1. */
54
+ #ifndef __AVX__
55
+
56
+ typedef struct {
57
+ __m128 lo;
58
+ __m128 hi;
59
+ } mm256_emu;
60
+ #define __m256 mm256_emu
61
+
62
+ static inline mm256_emu mm256_loadu_ps(const float *src) {
63
+ mm256_emu ret;
64
+ ret.lo = _mm_loadu_ps(&src[0]);
65
+ ret.hi = _mm_loadu_ps(&src[4]);
66
+ return ret;
67
+ }
68
+ #define _mm256_loadu_ps(src) mm256_loadu_ps(src)
69
+
70
+
71
+ static inline void mm256_storeu_ps(float *dst, mm256_emu src) {
72
+ _mm_storeu_ps(dst, src.lo);
73
+ _mm_storeu_ps(&dst[4], src.hi);
74
+ }
75
+ #define _mm256_storeu_ps(dst, src) mm256_storeu_ps(dst, src)
76
+
77
+
78
+ static inline mm256_emu mm256_setzero_ps(void) {
79
+ mm256_emu ret;
80
+ ret.lo = _mm_setzero_ps();
81
+ ret.hi = ret.lo;
82
+ return ret;
83
+ }
84
+ #define _mm256_setzero_ps mm256_setzero_ps
85
+
86
+ static inline mm256_emu mm256_broadcast_ss(const float *x) {
87
+ mm256_emu ret;
88
+ ret.lo = _mm_set1_ps(*x);
89
+ ret.hi = ret.lo;
90
+ return ret;
91
+ }
92
+ #define _mm256_broadcast_ss(x) mm256_broadcast_ss(x)
93
+
94
+ static inline mm256_emu mm256_set1_ps(float x) {
95
+ mm256_emu ret;
96
+ ret.lo = _mm_set1_ps(x);
97
+ ret.hi = ret.lo;
98
+ return ret;
99
+ }
100
+ #define _mm256_set1_ps(x) mm256_set1_ps(x)
101
+
102
+
103
+
104
+ static inline mm256_emu mm256_mul_ps(mm256_emu a, mm256_emu b) {
105
+ mm256_emu ret;
106
+ ret.lo = _mm_mul_ps(a.lo, b.lo);
107
+ ret.hi = _mm_mul_ps(a.hi, b.hi);
108
+ return ret;
109
+ }
110
+ #define _mm256_mul_ps(a,b) mm256_mul_ps(a,b)
111
+
112
+ static inline mm256_emu mm256_add_ps(mm256_emu a, mm256_emu b) {
113
+ mm256_emu ret;
114
+ ret.lo = _mm_add_ps(a.lo, b.lo);
115
+ ret.hi = _mm_add_ps(a.hi, b.hi);
116
+ return ret;
117
+ }
118
+ #define _mm256_add_ps(a,b) mm256_add_ps(a,b)
119
+
120
+
121
+ static inline mm256_emu mm256_max_ps(mm256_emu a, mm256_emu b) {
122
+ mm256_emu ret;
123
+ ret.lo = _mm_max_ps(a.lo, b.lo);
124
+ ret.hi = _mm_max_ps(a.hi, b.hi);
125
+ return ret;
126
+ }
127
+ #define _mm256_max_ps(a,b) mm256_max_ps(a,b)
128
+
129
+ static inline mm256_emu mm256_min_ps(mm256_emu a, mm256_emu b) {
130
+ mm256_emu ret;
131
+ ret.lo = _mm_min_ps(a.lo, b.lo);
132
+ ret.hi = _mm_min_ps(a.hi, b.hi);
133
+ return ret;
134
+ }
135
+ #define _mm256_min_ps(a,b) mm256_min_ps(a,b)
136
+
137
+ static inline mm256_emu mm256_rcp_ps(mm256_emu a) {
138
+ mm256_emu ret;
139
+ ret.lo = _mm_rcp_ps(a.lo);
140
+ ret.hi = _mm_rcp_ps(a.hi);
141
+ return ret;
142
+ }
143
+ #define _mm256_rcp_ps(a) mm256_rcp_ps(a)
144
+
145
+
146
+ static inline __m128 mm256_extractf128_ps(mm256_emu x, int i) {
147
+ return (i==0) ? x.lo : x.hi;
148
+ }
149
+ #undef _mm256_extractf128_ps
150
+ #define _mm256_extractf128_ps(x,i) mm256_extractf128_ps(x,i)
151
+
152
+ static inline mm256_emu mm256_insertf128_ps(mm256_emu dst, __m128 src, int i) {
153
+ if (i==0) dst.lo = src;
154
+ else dst.hi = src;
155
+ return dst;
156
+ }
157
+ #undef _mm256_insertf128_ps
158
+ #define _mm256_insertf128_ps(dst,src,i) mm256_insertf128_ps(dst,src,i)
159
+
160
+ #endif /* __AVX__ */
161
+
162
+
163
+
164
+ /* If we don't have AVX2 available, emulate what we need with SSE up to 4.1. */
165
+ #ifndef __AVX2__
166
+
167
+ typedef struct {
168
+ __m128i lo;
169
+ __m128i hi;
170
+ } mm256i_emu;
171
+ typedef __m256i real_m256i;
172
+ #define __m256i mm256i_emu
173
+
174
+ static inline mm256i_emu mm256_setzero_si256(void) {
175
+ mm256i_emu ret;
176
+ ret.lo = _mm_setzero_si128();
177
+ ret.hi = ret.lo;
178
+ return ret;
179
+ }
180
+ #define _mm256_setzero_si256 mm256_setzero_si256
181
+
182
+
183
+ static inline mm256i_emu mm256_loadu_si256(const mm256i_emu *src) {
184
+ mm256i_emu ret;
185
+ ret.lo = _mm_loadu_si128((const __m128i*)src);
186
+ ret.hi = _mm_loadu_si128(&((const __m128i*)src)[1]);
187
+ return ret;
188
+ }
189
+ #define _mm256_loadu_si256(src) mm256_loadu_si256(src)
190
+
191
+
192
+ static inline void mm256_storeu_si256(mm256i_emu *dst, mm256i_emu src) {
193
+ _mm_storeu_si128((__m128i*)dst, src.lo);
194
+ _mm_storeu_si128(&((__m128i*)dst)[1], src.hi);
195
+ }
196
+ #define _mm256_storeu_si256(dst, src) mm256_storeu_si256(dst, src)
197
+
198
+
199
+ static inline mm256i_emu mm256_broadcastd_epi32(__m128i x) {
200
+ mm256i_emu ret;
201
+ ret.hi = ret.lo = _mm_shuffle_epi32(x, 0);
202
+ return ret;
203
+ }
204
+ #define _mm256_broadcastd_epi32(x) mm256_broadcastd_epi32(x)
205
+
206
+
207
+ static inline mm256i_emu mm256_set1_epi32(int x) {
208
+ mm256i_emu ret;
209
+ ret.lo = _mm_set1_epi32(x);
210
+ ret.hi = ret.lo;
211
+ return ret;
212
+ }
213
+ #define _mm256_set1_epi32(x) mm256_set1_epi32(x)
214
+
215
+ static inline mm256i_emu mm256_set1_epi16(int x) {
216
+ mm256i_emu ret;
217
+ ret.lo = _mm_set1_epi16(x);
218
+ ret.hi = ret.lo;
219
+ return ret;
220
+ }
221
+ #define _mm256_set1_epi16(x) mm256_set1_epi16(x)
222
+
223
+
224
+ static inline mm256i_emu mm256_add_epi32(mm256i_emu a, mm256i_emu b) {
225
+ mm256i_emu ret;
226
+ ret.lo = _mm_add_epi32(a.lo, b.lo);
227
+ ret.hi = _mm_add_epi32(a.hi, b.hi);
228
+ return ret;
229
+ }
230
+ #define _mm256_add_epi32(a,b) mm256_add_epi32(a,b)
231
+
232
+ static inline mm256i_emu mm256_madd_epi16(mm256i_emu a, mm256i_emu b) {
233
+ mm256i_emu ret;
234
+ ret.lo = _mm_madd_epi16(a.lo, b.lo);
235
+ ret.hi = _mm_madd_epi16(a.hi, b.hi);
236
+ return ret;
237
+ }
238
+ #define _mm256_madd_epi16(a,b) mm256_madd_epi16(a,b)
239
+
240
+ static inline mm256i_emu mm256_maddubs_epi16(mm256i_emu a, mm256i_emu b) {
241
+ mm256i_emu ret;
242
+ ret.lo = _mm_maddubs_epi16(a.lo, b.lo);
243
+ ret.hi = _mm_maddubs_epi16(a.hi, b.hi);
244
+ return ret;
245
+ }
246
+ #define _mm256_maddubs_epi16(a,b) mm256_maddubs_epi16(a,b)
247
+
248
+
249
+
250
+ /* Emulating the conversion functions is tricky because they use __m256i but are defined in AVX.
251
+ So we need to make a special when only AVX is available. */
252
+ #ifdef __AVX__
253
+
254
+ typedef union {
255
+ mm256i_emu fake;
256
+ real_m256i real;
257
+ } mm256_union;
258
+
259
+ static inline __m256 mm256_cvtepi32_ps(mm256i_emu a) {
260
+ mm256_union src;
261
+ src.fake = a;
262
+ return _mm256_cvtepi32_ps(src.real);
263
+ }
264
+ #define _mm256_cvtepi32_ps(a) mm256_cvtepi32_ps(a)
265
+
266
+ static inline mm256i_emu mm256_cvtps_epi32(__m256 a) {
267
+ mm256_union ret;
268
+ ret.real = _mm256_cvtps_epi32(a);
269
+ return ret.fake;
270
+ }
271
+ #define _mm256_cvtps_epi32(a) mm256_cvtps_epi32(a)
272
+
273
+
274
+ #else
275
+
276
+ static inline mm256_emu mm256_cvtepi32_ps(mm256i_emu a) {
277
+ mm256_emu ret;
278
+ ret.lo = _mm_cvtepi32_ps(a.lo);
279
+ ret.hi = _mm_cvtepi32_ps(a.hi);
280
+ return ret;
281
+ }
282
+ #define _mm256_cvtepi32_ps(a) mm256_cvtepi32_ps(a)
283
+
284
+ static inline mm256i_emu mm256_cvtps_epi32(mm256_emu a) {
285
+ mm256i_emu ret;
286
+ ret.lo = _mm_cvtps_epi32(a.lo);
287
+ ret.hi = _mm_cvtps_epi32(a.hi);
288
+ return ret;
289
+ }
290
+ #define _mm256_cvtps_epi32(a) mm256_cvtps_epi32(a)
291
+
292
+ #endif /* __AVX__ */
293
+
294
+
295
+ #endif /* __AVX2__ */
296
+
297
+ /* In case we don't have FMA, make it a mul and an add. */
298
+ #if !(defined(__FMA__) && defined(__AVX__))
299
+ #define _mm256_fmadd_ps(a,b,c) _mm256_add_ps(_mm256_mul_ps(a, b), c)
300
+ #define _mm_fmadd_ps(a,b,c) _mm_add_ps(_mm_mul_ps(a, b), c)
301
+ #endif
302
+
303
+ #ifdef __AVX2__
304
+ static inline __m256 exp8_approx(__m256 X)
305
+ {
306
+ const __m256 K0 = _mm256_set1_ps(0.99992522f);
307
+ const __m256 K1 = _mm256_set1_ps(0.69583354f);
308
+ const __m256 K2 = _mm256_set1_ps(0.22606716f);
309
+ const __m256 K3 = _mm256_set1_ps(0.078024523f);
310
+ const __m256 log2_E = _mm256_set1_ps(1.44269504f);
311
+ const __m256 max_in = _mm256_set1_ps(50.f);
312
+ const __m256 min_in = _mm256_set1_ps(-50.f);
313
+ __m256 XF, Y;
314
+ __m256i I;
315
+ X = _mm256_mul_ps(X, log2_E);
316
+ X = _mm256_max_ps(min_in, _mm256_min_ps(max_in, X));
317
+ XF = _mm256_floor_ps(X);
318
+ I = _mm256_cvtps_epi32(XF);
319
+ X = _mm256_sub_ps(X, XF);
320
+ Y = _mm256_fmadd_ps(_mm256_fmadd_ps(_mm256_fmadd_ps(K3, X, K2), X, K1), X, K0);
321
+ I = _mm256_slli_epi32(I, 23);
322
+ Y = _mm256_castsi256_ps(_mm256_add_epi32(I, _mm256_castps_si256(Y)));
323
+ return Y;
324
+ }
325
+
326
+ static inline void vector_ps_to_epi8(unsigned char *x, const float *_x, int len) {
327
+ int i;
328
+ __m256 const127 = _mm256_set1_ps(127.f);
329
+ for (i=0;i<len;i+=8) {
330
+ __m256 xf;
331
+ __m256i xi;
332
+ xf = _mm256_loadu_ps(&_x[i]);
333
+ xf = _mm256_fmadd_ps(xf, const127, const127);
334
+ xi = _mm256_cvtps_epi32(xf);
335
+ xi = _mm256_packus_epi32(xi, _mm256_setzero_si256());
336
+ xi = _mm256_permute4x64_epi64(xi, 0xD8);
337
+ xi = _mm256_packus_epi16(xi, _mm256_setzero_si256());
338
+ xi = _mm256_permutevar8x32_epi32(xi, _mm256_setr_epi32(0,1, 0,0, 0,0, 0,0));
339
+ _mm256_storeu_si256 ((__m256i *)(void*)&x[i], xi);
340
+ }
341
+ }
342
+
343
+ #else
344
+ static inline __m128 exp4_approx(__m128 X)
345
+ {
346
+ const __m128 K0 = _mm_set1_ps(0.99992522f);
347
+ const __m128 K1 = _mm_set1_ps(0.69583354f);
348
+ const __m128 K2 = _mm_set1_ps(0.22606716f);
349
+ const __m128 K3 = _mm_set1_ps(0.078024523f);
350
+ const __m128 log2_E = _mm_set1_ps(1.44269504);
351
+ const __m128 max_in = _mm_set1_ps(50.f);
352
+ const __m128 min_in = _mm_set1_ps(-50.f);
353
+ const __m128i mask = _mm_set1_epi32(0x7fffffff);
354
+ __m128 XF, Y;
355
+ __m128i I;
356
+ X = _mm_mul_ps(X, log2_E);
357
+ X = _mm_max_ps(min_in, _mm_min_ps(max_in, X));
358
+ XF = _mm_floor_ps(X);
359
+ I = _mm_cvtps_epi32(XF);
360
+ X = _mm_sub_ps(X, XF);
361
+ Y = _mm_fmadd_ps(_mm_fmadd_ps(_mm_fmadd_ps(K3, X, K2), X, K1), X, K0);
362
+ I = _mm_slli_epi32(I, 23);
363
+ Y = _mm_castsi128_ps(_mm_and_si128(mask, _mm_add_epi32(I, _mm_castps_si128(Y))));
364
+ return Y;
365
+ }
366
+ static inline __m256 exp8_approx(__m256 X)
367
+ {
368
+ __m256 Y;
369
+ __m128 Xhi, Xlo, Yhi, Ylo;
370
+ Xhi = _mm256_extractf128_ps(X, 1);
371
+ Xlo = _mm256_extractf128_ps(X, 0);
372
+ Yhi = exp4_approx(Xhi);
373
+ Ylo = exp4_approx(Xlo);
374
+ Y = _mm256_insertf128_ps(_mm256_setzero_ps(), Yhi, 1);
375
+ Y = _mm256_insertf128_ps(Y, Ylo, 0);
376
+ return Y;
377
+ }
378
+
379
+ static inline void vector_ps_to_epi8(unsigned char *x, const float *_x, int len) {
380
+ int i;
381
+ for (i=0;i<len;i++) x[i] = 127+(int)floor(.5+127*_x[i]);
382
+ }
383
+
384
+ #endif
385
+
386
+
387
+ #ifdef __AVX__
388
+
389
+ /* Approximating tanh() using a Padé-like rational function:
390
+ tanh(x) ~= x * (N0 + N1*x^2 + N2*x^4)/(D0 + D1*x^2 + D2*x^4)
391
+ subject to the +/- 1 bounds.
392
+ The coefficients were determined by gradient descent trying to minimize
393
+ the maximum deviation over the whole range (this is only possible because
394
+ of the bounds). The max error is around 3e-4 and is dominated by the
395
+ reciprocal approximation (the max error of the rational function is
396
+ around 6e-5).
397
+ */
398
+ static inline __m256 tanh8_approx(__m256 X)
399
+ {
400
+ const __m256 N0 = _mm256_set1_ps(952.52801514f);
401
+ const __m256 N1 = _mm256_set1_ps(96.39235687f);
402
+ const __m256 N2 = _mm256_set1_ps(0.60863042f);
403
+ const __m256 D0 = _mm256_set1_ps(952.72399902f);
404
+ const __m256 D1 = _mm256_set1_ps(413.36801147f);
405
+ const __m256 D2 = _mm256_set1_ps(11.88600922f);
406
+ const __m256 max_out = _mm256_set1_ps(1.f);
407
+ const __m256 min_out = _mm256_set1_ps(-1.f);
408
+ __m256 X2, num, den;
409
+ X2 = _mm256_mul_ps(X, X);
410
+ num = _mm256_fmadd_ps(_mm256_fmadd_ps(N2, X2, N1), X2, N0);
411
+ den = _mm256_fmadd_ps(_mm256_fmadd_ps(D2, X2, D1), X2, D0);
412
+ num = _mm256_mul_ps(num, X);
413
+ den = _mm256_rcp_ps(den);
414
+ num = _mm256_mul_ps(num, den);
415
+ return _mm256_max_ps(min_out, _mm256_min_ps(max_out, num));
416
+ }
417
+
418
+ /* Sigmoid approximation using a Padé-like rational function:
419
+ 1/(1+exp(-x)) ~= 0.5 + x * (N0 + N1*x^2 + N2*x^4)/(D0 + D1*x^2 + D2*x^4)
420
+ subject to the [0, 1] bounds.
421
+ The coefficients are directly derived by dividing the tanh() coefficients
422
+ by powers of two to get the correct scaling. The max error is around 1.5e-4
423
+ and is dominated by the reciprocal approximation (the max error of the
424
+ rational function is around 3e-5).
425
+ */
426
+ static inline __m256 sigmoid8_approx(__m256 X)
427
+ {
428
+ const __m256 N0 = _mm256_set1_ps(238.13200378f);
429
+ const __m256 N1 = _mm256_set1_ps(6.02452230f);
430
+ const __m256 N2 = _mm256_set1_ps(0.00950985f);
431
+ const __m256 D0 = _mm256_set1_ps(952.72399902f);
432
+ const __m256 D1 = _mm256_set1_ps(103.34200287f);
433
+ const __m256 D2 = _mm256_set1_ps(0.74287558f);
434
+ const __m256 half = _mm256_set1_ps(0.5);
435
+ const __m256 max_out = _mm256_set1_ps(1.f);
436
+ const __m256 min_out = _mm256_set1_ps(0.f);
437
+ __m256 X2, num, den;
438
+ X2 = _mm256_mul_ps(X, X);
439
+ num = _mm256_fmadd_ps(_mm256_fmadd_ps(N2, X2, N1), X2, N0);
440
+ den = _mm256_fmadd_ps(_mm256_fmadd_ps(D2, X2, D1), X2, D0);
441
+ num = _mm256_mul_ps(num, X);
442
+ den = _mm256_rcp_ps(den);
443
+ num = _mm256_fmadd_ps(num, den, half);
444
+ return _mm256_max_ps(min_out, _mm256_min_ps(max_out, num));
445
+ }
446
+
447
+ static inline float tanh_approx(float x)
448
+ {
449
+ float out[8];
450
+ __m256 X, Y;
451
+ X = _mm256_set1_ps(x);
452
+ Y = tanh8_approx(X);
453
+ _mm256_storeu_ps(out, Y);
454
+ return out[0];
455
+ }
456
+
457
+ static inline float sigmoid_approx(float x)
458
+ {
459
+ float out[8];
460
+ __m256 X, Y;
461
+ X = _mm256_set1_ps(x);
462
+ Y = sigmoid8_approx(X);
463
+ _mm256_storeu_ps(out, Y);
464
+ return out[0];
465
+ }
466
+
467
+ #else
468
+
469
+ static inline __m128 tanh4_approx(__m128 X)
470
+ {
471
+ const __m128 N0 = _mm_set1_ps(952.52801514f);
472
+ const __m128 N1 = _mm_set1_ps(96.39235687f);
473
+ const __m128 N2 = _mm_set1_ps(0.60863042f);
474
+ const __m128 D0 = _mm_set1_ps(952.72399902f);
475
+ const __m128 D1 = _mm_set1_ps(413.36801147f);
476
+ const __m128 D2 = _mm_set1_ps(11.88600922f);
477
+ const __m128 max_out = _mm_set1_ps(1.f);
478
+ const __m128 min_out = _mm_set1_ps(-1.f);
479
+ __m128 X2, num, den;
480
+ X2 = _mm_mul_ps(X, X);
481
+ num = _mm_fmadd_ps(_mm_fmadd_ps(N2, X2, N1), X2, N0);
482
+ den = _mm_fmadd_ps(_mm_fmadd_ps(D2, X2, D1), X2, D0);
483
+ num = _mm_mul_ps(num, X);
484
+ den = _mm_rcp_ps(den);
485
+ num = _mm_mul_ps(num, den);
486
+ return _mm_max_ps(min_out, _mm_min_ps(max_out, num));
487
+ }
488
+
489
+ static inline __m128 sigmoid4_approx(__m128 X)
490
+ {
491
+ const __m128 N0 = _mm_set1_ps(238.13200378f);
492
+ const __m128 N1 = _mm_set1_ps(6.02452230f);
493
+ const __m128 N2 = _mm_set1_ps(0.00950985f);
494
+ const __m128 D0 = _mm_set1_ps(952.72399902f);
495
+ const __m128 D1 = _mm_set1_ps(103.34200287f);
496
+ const __m128 D2 = _mm_set1_ps(0.74287558f);
497
+ const __m128 half = _mm_set1_ps(0.5);
498
+ const __m128 max_out = _mm_set1_ps(1.f);
499
+ const __m128 min_out = _mm_set1_ps(0.f);
500
+ __m128 X2, num, den;
501
+ X2 = _mm_mul_ps(X, X);
502
+ num = _mm_fmadd_ps(_mm_fmadd_ps(N2, X2, N1), X2, N0);
503
+ den = _mm_fmadd_ps(_mm_fmadd_ps(D2, X2, D1), X2, D0);
504
+ num = _mm_mul_ps(num, X);
505
+ den = _mm_rcp_ps(den);
506
+ num = _mm_fmadd_ps(num, den, half);
507
+ return _mm_max_ps(min_out, _mm_min_ps(max_out, num));
508
+ }
509
+
510
+ static inline float tanh_approx(float x)
511
+ {
512
+ float out[4];
513
+ __m128 X, Y;
514
+ X = _mm_set1_ps(x);
515
+ Y = tanh4_approx(X);
516
+ _mm_storeu_ps(out, Y);
517
+ return out[0];
518
+ }
519
+
520
+ static inline float sigmoid_approx(float x)
521
+ {
522
+ float out[4];
523
+ __m128 X, Y;
524
+ X = _mm_set1_ps(x);
525
+ Y = sigmoid4_approx(X);
526
+ _mm_storeu_ps(out, Y);
527
+ return out[0];
528
+ }
529
+
530
+ #endif
531
+
532
+ static inline float lpcnet_exp(float x)
533
+ {
534
+ float out[8];
535
+ __m256 X, Y;
536
+ X = _mm256_set1_ps(x);
537
+ Y = exp8_approx(X);
538
+ _mm256_storeu_ps(out, Y);
539
+ return out[0];
540
+ }
541
+
542
+ static inline void softmax(float *y, const float *x, int N)
543
+ {
544
+ int i;
545
+ for (i=0;i<N-7;i+=8)
546
+ {
547
+ __m256 X, Y;
548
+ X = _mm256_loadu_ps(&x[i]);
549
+ Y = exp8_approx(X);
550
+ _mm256_storeu_ps(&y[i], Y);
551
+ }
552
+ for (;i<N;i++)
553
+ y[i] = lpcnet_exp(x[i]);
554
+ }
555
+
556
+ #ifdef __AVX__
557
+ static inline void vec_tanh(float *y, const float *x, int N)
558
+ {
559
+ int i;
560
+ for (i=0;i<N-7;i+=8)
561
+ {
562
+ __m256 X, Y;
563
+ X = _mm256_loadu_ps(&x[i]);
564
+ Y = tanh8_approx(X);
565
+ _mm256_storeu_ps(&y[i], Y);
566
+ }
567
+ for (;i<N;i++)
568
+ {
569
+ y[i] = tanh_approx(x[i]);
570
+ }
571
+ }
572
+
573
+ static inline void vec_sigmoid(float *y, const float *x, int N)
574
+ {
575
+ int i;
576
+ for (i=0;i<N-7;i+=8)
577
+ {
578
+ __m256 X, Y;
579
+ X = _mm256_loadu_ps(&x[i]);
580
+ Y = sigmoid8_approx(X);
581
+ _mm256_storeu_ps(&y[i], Y);
582
+ }
583
+ for (;i<N;i++)
584
+ {
585
+ y[i] = sigmoid_approx(x[i]);
586
+ }
587
+ }
588
+ #else
589
+ static inline void vec_tanh(float *y, const float *x, int N)
590
+ {
591
+ int i;
592
+ for (i=0;i<N-3;i+=4)
593
+ {
594
+ __m128 X, Y;
595
+ X = _mm_loadu_ps(&x[i]);
596
+ Y = tanh4_approx(X);
597
+ _mm_storeu_ps(&y[i], Y);
598
+ }
599
+ for (;i<N;i++)
600
+ {
601
+ y[i] = tanh_approx(x[i]);
602
+ }
603
+ }
604
+
605
+ static inline void vec_sigmoid(float *y, const float *x, int N)
606
+ {
607
+ int i;
608
+ for (i=0;i<N-3;i+=4)
609
+ {
610
+ __m128 X, Y;
611
+ X = _mm_loadu_ps(&x[i]);
612
+ Y = sigmoid4_approx(X);
613
+ _mm_storeu_ps(&y[i], Y);
614
+ }
615
+ for (;i<N;i++)
616
+ {
617
+ y[i] = sigmoid_approx(x[i]);
618
+ }
619
+ }
620
+
621
+ #endif
622
+
623
+ #if defined(__AVXVNNI__) || defined(__AVX512VNNI__)
624
+
625
+ #define opus_mm256_dpbusds_epi32(src, a, b) _mm256_dpbusds_epi32(src, a, b)
626
+
627
+ #elif defined(__AVX2__)
628
+
629
+ static inline __m256i opus_mm256_dpbusds_epi32(__m256i src, __m256i a, __m256i b) {
630
+ __m256i ones, tmp;
631
+ ones = _mm256_set1_epi16(1);
632
+ tmp = _mm256_maddubs_epi16(a, b);
633
+ tmp = _mm256_madd_epi16(tmp, ones);
634
+ return _mm256_add_epi32(src, tmp);
635
+ }
636
+
637
+ #elif defined(__SSSE3__)
638
+
639
+ static inline mm256i_emu opus_mm256_dpbusds_epi32(mm256i_emu src, mm256i_emu a, mm256i_emu b) {
640
+ mm256i_emu ones, tmp;
641
+ ones = _mm256_set1_epi16(1);
642
+ tmp = _mm256_maddubs_epi16(a, b);
643
+ tmp = _mm256_madd_epi16(tmp, ones);
644
+ return _mm256_add_epi32(src, tmp);
645
+ }
646
+
647
+ #elif defined(__SSE2__)
648
+
649
+ static inline __m128i mm_dpbusds_epi32(__m128i src, __m128i a, __m128i b) {
650
+ __m128i ah, al, bh, bl, tmp;
651
+ ah = _mm_srli_epi16(a, 8);
652
+ bh = _mm_srai_epi16(b, 8);
653
+ al = _mm_srli_epi16(_mm_slli_epi16(a, 8), 8);
654
+ bl = _mm_srai_epi16(_mm_slli_epi16(b, 8), 8);
655
+ tmp = _mm_add_epi32(_mm_madd_epi16(ah, bh), _mm_madd_epi16(al, bl));
656
+ return _mm_add_epi32(src, tmp);
657
+ }
658
+
659
+ static inline mm256i_emu opus_mm256_dpbusds_epi32(mm256i_emu src, mm256i_emu a, mm256i_emu b) {
660
+ mm256i_emu res;
661
+ res.hi = mm_dpbusds_epi32(src.hi, a.hi, b.hi);
662
+ res.lo = mm_dpbusds_epi32(src.lo, a.lo, b.lo);
663
+ return res;
664
+ }
665
+
666
+
667
+ #else
668
+
669
+ #error "No optimizations in vec_avx.h. This should never happen. "
670
+ #endif
671
+
672
+ static inline void sgemv(float *out, const float *weights, int rows, int cols, int col_stride, const float *x)
673
+ {
674
+ int i, j;
675
+ i=0;
676
+ for (;i<rows-15;i+=16)
677
+ {
678
+ float *y;
679
+ __m256 vy0, vy8;
680
+ y = &out[i];
681
+ vy0 = _mm256_setzero_ps();
682
+ vy8 = _mm256_setzero_ps();
683
+ for (j=0;j<cols;j++)
684
+ {
685
+ __m256 vxj;
686
+ __m256 vw;
687
+ vxj = _mm256_broadcast_ss(&x[j]);
688
+
689
+ vw = _mm256_loadu_ps(&weights[j*col_stride + i]);
690
+ vy0 = _mm256_fmadd_ps(vw, vxj, vy0);
691
+
692
+ vw = _mm256_loadu_ps(&weights[j*col_stride + i + 8]);
693
+ vy8 = _mm256_fmadd_ps(vw, vxj, vy8);
694
+ }
695
+ _mm256_storeu_ps (&y[0], vy0);
696
+ _mm256_storeu_ps (&y[8], vy8);
697
+ }
698
+ for (;i<rows-7;i+=8)
699
+ {
700
+ float *y;
701
+ __m256 vy0;
702
+ y = &out[i];
703
+ vy0 = _mm256_setzero_ps();
704
+ for (j=0;j<cols;j++)
705
+ {
706
+ __m256 vxj;
707
+ __m256 vw;
708
+ vxj = _mm256_broadcast_ss(&x[j]);
709
+
710
+ vw = _mm256_loadu_ps(&weights[j*col_stride + i]);
711
+ vy0 = _mm256_fmadd_ps(vw, vxj, vy0);
712
+ }
713
+ _mm256_storeu_ps (&y[0], vy0);
714
+ }
715
+ for (;i<rows-3;i+=4)
716
+ {
717
+ float *y;
718
+ __m128 vy0;
719
+ y = &out[i];
720
+ vy0 = _mm_setzero_ps();
721
+ for (j=0;j<cols;j++)
722
+ {
723
+ __m128 vxj;
724
+ __m128 vw;
725
+ vxj = _mm_set1_ps(x[j]);
726
+
727
+ vw = _mm_loadu_ps(&weights[j*col_stride + i]);
728
+ vy0 = _mm_fmadd_ps(vw, vxj, vy0);
729
+ }
730
+ _mm_storeu_ps (&y[0], vy0);
731
+ }
732
+ for (;i<rows;i++)
733
+ {
734
+ out[i] = 0;
735
+ for (j=0;j<cols;j++) out[i] += weights[j*col_stride + i]*x[j];
736
+ }
737
+ }
738
+
739
+ static inline void sparse_sgemv8x4(float *out, const float *weights, const int *idx, int rows, const float *x)
740
+ {
741
+ int i, j;
742
+ for (i=0;i<rows;i+=8)
743
+ {
744
+ float *y;
745
+ int cols;
746
+ __m256 vy0;
747
+ y = &out[i];
748
+ vy0 = _mm256_setzero_ps();
749
+ cols = *idx++;
750
+ for (j=0;j<cols;j++)
751
+ {
752
+ int id;
753
+ __m256 vxj;
754
+ __m256 vw;
755
+ id = *idx++;
756
+ vxj = _mm256_broadcast_ss(&x[id]);
757
+ vw = _mm256_loadu_ps(&weights[0]);
758
+ vy0 = _mm256_fmadd_ps(vw, vxj, vy0);
759
+
760
+ vxj = _mm256_broadcast_ss(&x[id+1]);
761
+ vw = _mm256_loadu_ps(&weights[8]);
762
+ vy0 = _mm256_fmadd_ps(vw, vxj, vy0);
763
+
764
+ vxj = _mm256_broadcast_ss(&x[id+2]);
765
+ vw = _mm256_loadu_ps(&weights[16]);
766
+ vy0 = _mm256_fmadd_ps(vw, vxj, vy0);
767
+
768
+ vxj = _mm256_broadcast_ss(&x[id+3]);
769
+ vw = _mm256_loadu_ps(&weights[24]);
770
+ vy0 = _mm256_fmadd_ps(vw, vxj, vy0);
771
+
772
+ weights += 32;
773
+ }
774
+ _mm256_storeu_ps (&y[0], vy0);
775
+ }
776
+ }
777
+
778
+ static inline void sparse_cgemv8x4(float *_out, const opus_int8 *w, const int *idx, const float *scale, int rows, int cols, const float *_x)
779
+ {
780
+ int i, j;
781
+ unsigned char x[MAX_INPUTS];
782
+ /*for (i=0;i<cols;i++) x[i] = 127+floor(.5+127*_x[i]);*/
783
+ vector_ps_to_epi8(x, _x, cols);
784
+ for (i=0;i<rows;i+=8)
785
+ {
786
+ int colblocks;
787
+ __m256i vy0;
788
+ __m256 vout;
789
+ colblocks = *idx++;
790
+ vy0 = _mm256_setzero_si256();
791
+ j=0;
792
+ #if 1 /* Unrolling by 4 gives some gain, comment out if it does not. */
793
+ for (;j<colblocks-3;j+=4)
794
+ {
795
+ __m256i vxj;
796
+ __m256i vw;
797
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[*idx++]));
798
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
799
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
800
+ w += 32;
801
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[*idx++]));
802
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
803
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
804
+ w += 32;
805
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[*idx++]));
806
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
807
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
808
+ w += 32;
809
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[*idx++]));
810
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
811
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
812
+ w += 32;
813
+ }
814
+ #endif
815
+ for (;j<colblocks;j++)
816
+ {
817
+ __m256i vxj;
818
+ __m256i vw;
819
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[*idx++]));
820
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
821
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
822
+ w += 32;
823
+ }
824
+ vout = _mm256_cvtepi32_ps(vy0);
825
+ vout = _mm256_mul_ps(vout, _mm256_loadu_ps(&scale[i]));
826
+ _mm256_storeu_ps(&_out[i], vout);
827
+ }
828
+ }
829
+ static inline void cgemv8x4(float *_out, const opus_int8 *w, const float *scale, int rows, int cols, const float *_x)
830
+ {
831
+ int i, j;
832
+ unsigned char x[MAX_INPUTS];
833
+ /*for (i=0;i<cols;i++) x[i] = 127+floor(.5+127*_x[i]);*/
834
+ vector_ps_to_epi8(x, _x, cols);
835
+ for (i=0;i<rows;i+=8)
836
+ {
837
+ __m256i vy0;
838
+ __m256 vout;
839
+ vy0 = _mm256_setzero_si256();
840
+ j=0;
841
+ #if 1 /* Unrolling by 4 gives some gain, comment out if it does not. */
842
+ for (;j<cols-12;j+=16)
843
+ {
844
+ __m256i vxj;
845
+ __m256i vw;
846
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[j]));
847
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
848
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
849
+ w += 32;
850
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[j+4]));
851
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
852
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
853
+ w += 32;
854
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[j+8]));
855
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
856
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
857
+ w += 32;
858
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[j+12]));
859
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
860
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
861
+ w += 32;
862
+ }
863
+ #endif
864
+ for (;j<cols;j+=4)
865
+ {
866
+ __m256i vxj;
867
+ __m256i vw;
868
+ vxj = _mm256_broadcastd_epi32(_mm_loadu_si32(&x[j]));
869
+ vw = _mm256_loadu_si256((const __m256i *)(void*)w);
870
+ vy0 = opus_mm256_dpbusds_epi32(vy0, vxj, vw);
871
+ w += 32;
872
+ }
873
+ vout = _mm256_cvtepi32_ps(vy0);
874
+ vout = _mm256_mul_ps(vout, _mm256_loadu_ps(&scale[i]));
875
+ _mm256_storeu_ps(&_out[i], vout);
876
+ }
877
+ }
878
+
879
+ #define SCALE (128.f*127.f)
880
+ #define SCALE_1 (1.f/128.f/127.f)
881
+ #define USE_SU_BIAS
882
+
883
+
884
+ #endif /*VEC_AVX_H*/
cpp/src/rnnoise/vec_neon.h ADDED
@@ -0,0 +1,474 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018 David Rowe
2
+ 2018 Mozilla
3
+ 2008-2011 Octasic Inc.
4
+ 2012-2017 Jean-Marc Valin */
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
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
21
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+ /* NEON support for ARM machines */
30
+
31
+ #ifndef VEC_NEON_H
32
+ #define VEC_NEON_H
33
+
34
+ #include <arm_neon.h>
35
+ #include "opus_types.h"
36
+ #include "common.h"
37
+
38
+ #if defined(__arm__) && !defined(__aarch64__) && (__ARM_ARCH < 8 || !defined(__clang__))
39
+ /* Emulate vcvtnq_s32_f32() for ARMv7 Neon. */
40
+ static OPUS_INLINE int32x4_t vcvtnq_s32_f32(float32x4_t x) {
41
+ return vrshrq_n_s32(vcvtq_n_s32_f32(x, 8), 8);
42
+ }
43
+
44
+ static OPUS_INLINE int16x8_t vpaddq_s16(int16x8_t a, int16x8_t b) {
45
+ return vcombine_s16(vpadd_s16(vget_low_s16(a), vget_high_s16(a)), vpadd_s16(vget_low_s16(b), vget_high_s16(b)));
46
+ }
47
+
48
+ static OPUS_INLINE int16x8_t vmull_high_s8(int8x16_t a, int8x16_t b) {
49
+ return vmull_s8(vget_high_s8(a), vget_high_s8(b));
50
+ }
51
+ #endif
52
+
53
+ #ifdef __ARM_FEATURE_FMA
54
+ /* If we can, force the compiler to use an FMA instruction rather than break
55
+ vmlaq_f32() into fmul/fadd. */
56
+ #define vmlaq_f32(a,b,c) vfmaq_f32(a,b,c)
57
+ #endif
58
+
59
+ #ifndef LPCNET_TEST
60
+ static inline float32x4_t exp4_approx(float32x4_t x) {
61
+ int32x4_t i;
62
+ float32x4_t xf;
63
+
64
+ x = vmaxq_f32(vminq_f32(x, vdupq_n_f32(88.f)), vdupq_n_f32(-88.f));
65
+
66
+ /* express exp(x) as exp2(x/log(2)), add 127 for the exponent later */
67
+ x = vmlaq_f32(vdupq_n_f32(127.f), x, vdupq_n_f32(1.44269504f));
68
+
69
+ /* split into integer and fractional parts */
70
+ i = vcvtq_s32_f32(x);
71
+ xf = vcvtq_f32_s32(i);
72
+ x = vsubq_f32(x, xf);
73
+
74
+ float32x4_t K0 = vdupq_n_f32(0.99992522f);
75
+ float32x4_t K1 = vdupq_n_f32(0.69583354f);
76
+ float32x4_t K2 = vdupq_n_f32(0.22606716f);
77
+ float32x4_t K3 = vdupq_n_f32(0.078024523f);
78
+ float32x4_t Y = vmlaq_f32(K0, x, vmlaq_f32(K1, x, vmlaq_f32(K2, K3, x)));
79
+
80
+ /* compute 2^i */
81
+ float32x4_t exponent = vreinterpretq_f32_s32(vshlq_n_s32(i, 23));
82
+
83
+ Y = vmulq_f32(Y, exponent);
84
+ return Y;
85
+ }
86
+
87
+ static inline float32x4_t tanh4_approx(float32x4_t X)
88
+ {
89
+ const float32x4_t N0 = vdupq_n_f32(952.52801514f);
90
+ const float32x4_t N1 = vdupq_n_f32(96.39235687f);
91
+ const float32x4_t N2 = vdupq_n_f32(0.60863042f);
92
+ const float32x4_t D0 = vdupq_n_f32(952.72399902f);
93
+ const float32x4_t D1 = vdupq_n_f32(413.36801147f);
94
+ const float32x4_t D2 = vdupq_n_f32(11.88600922f);
95
+ const float32x4_t max_out = vdupq_n_f32(1.f);
96
+ const float32x4_t min_out = vdupq_n_f32(-1.f);
97
+ float32x4_t X2, num, den;
98
+ X2 = vmulq_f32(X, X);
99
+ num = vmlaq_f32(N0, X2, vmlaq_f32(N1, N2, X2));
100
+ den = vmlaq_f32(D0, X2, vmlaq_f32(D1, D2, X2));
101
+ num = vmulq_f32(num, X);
102
+ den = vrecpeq_f32(den);
103
+ num = vmulq_f32(num, den);
104
+ return vmaxq_f32(min_out, vminq_f32(max_out, num));
105
+ }
106
+
107
+ static inline float32x4_t sigmoid4_approx(float32x4_t X)
108
+ {
109
+ const float32x4_t N0 = vdupq_n_f32(238.13200378f);
110
+ const float32x4_t N1 = vdupq_n_f32(6.02452230f);
111
+ const float32x4_t N2 = vdupq_n_f32(0.00950985f);
112
+ const float32x4_t D0 = vdupq_n_f32(952.72399902f);
113
+ const float32x4_t D1 = vdupq_n_f32(103.34200287f);
114
+ const float32x4_t D2 = vdupq_n_f32(0.74287558f);
115
+ const float32x4_t half = vdupq_n_f32(0.5f);
116
+ const float32x4_t max_out = vdupq_n_f32(1.f);
117
+ const float32x4_t min_out = vdupq_n_f32(0.f);
118
+ float32x4_t X2, num, den;
119
+ X2 = vmulq_f32(X, X);
120
+ num = vmlaq_f32(N0, X2, vmlaq_f32(N1, N2, X2));
121
+ den = vmlaq_f32(D0, X2, vmlaq_f32(D1, D2, X2));
122
+ num = vmulq_f32(num, X);
123
+ den = vrecpeq_f32(den);
124
+ num = vmlaq_f32(half, num, den);
125
+ return vmaxq_f32(min_out, vminq_f32(max_out, num));
126
+ }
127
+
128
+ static inline float lpcnet_exp(float x)
129
+ {
130
+ float out[4];
131
+ float32x4_t X, Y;
132
+ X = vdupq_n_f32(x);
133
+ Y = exp4_approx(X);
134
+ vst1q_f32(out, Y);
135
+ return out[0];
136
+ }
137
+
138
+ static inline float tanh_approx(float x)
139
+ {
140
+ float out[4];
141
+ float32x4_t X, Y;
142
+ X = vdupq_n_f32(x);
143
+ Y = tanh4_approx(X);
144
+ vst1q_f32(out, Y);
145
+ return out[0];
146
+ }
147
+
148
+ static inline float sigmoid_approx(float x)
149
+ {
150
+ float out[4];
151
+ float32x4_t X, Y;
152
+ X = vdupq_n_f32(x);
153
+ Y = sigmoid4_approx(X);
154
+ vst1q_f32(out, Y);
155
+ return out[0];
156
+ }
157
+
158
+ static inline void softmax(float *y, const float *x, int N)
159
+ {
160
+ int i;
161
+ for (i=0;i<N-3;i+=4)
162
+ {
163
+ float32x4_t X, Y;
164
+ X = vld1q_f32(&x[i]);
165
+ Y = exp4_approx(X);
166
+ vst1q_f32(&y[i], Y);
167
+ }
168
+ for (;i<N;i++)
169
+ y[i] = lpcnet_exp(x[i]);
170
+ }
171
+
172
+ static inline void vec_tanh(float *y, const float *x, int N)
173
+ {
174
+ int i;
175
+ for (i=0;i<N-3;i+=4)
176
+ {
177
+ float32x4_t X, Y;
178
+ X = vld1q_f32(&x[i]);
179
+ Y = tanh4_approx(X);
180
+ vst1q_f32(&y[i], Y);
181
+ }
182
+ for (;i<N;i++)
183
+ {
184
+ float ex2;
185
+ ex2 = lpcnet_exp(2*x[i]);
186
+ y[i] = (ex2-1)/(ex2+1);
187
+ }
188
+ }
189
+
190
+ static inline void vec_sigmoid(float *y, const float *x, int N)
191
+ {
192
+ int i;
193
+ for (i=0;i<N-3;i+=4)
194
+ {
195
+ float32x4_t X, Y;
196
+ X = vld1q_f32(&x[i]);
197
+ Y = sigmoid4_approx(X);
198
+ vst1q_f32(&y[i], Y);
199
+ }
200
+ for (;i<N;i++)
201
+ {
202
+ float ex;
203
+ ex = lpcnet_exp(x[i]);
204
+ y[i] = (ex)/(ex+1);
205
+ }
206
+ }
207
+ #endif
208
+
209
+ static inline void sgemv16x1(float *out, const float *weights, int rows, int cols, int col_stride, const float *x)
210
+ {
211
+ int i, j;
212
+ for (i=0;i<rows;i+=16)
213
+ {
214
+ float * restrict y = &out[i];
215
+
216
+ /* keep y[0..15] in registers for duration of inner loop */
217
+
218
+ float32x4_t y0_3 = vdupq_n_f32(0);
219
+ float32x4_t y4_7 = vdupq_n_f32(0);
220
+ float32x4_t y8_11 = vdupq_n_f32(0);
221
+ float32x4_t y12_15 = vdupq_n_f32(0);
222
+
223
+ for (j=0;j<cols;j++)
224
+ {
225
+ const float * restrict w;
226
+ float32x4_t wvec0_3, wvec4_7, wvec8_11, wvec12_15;
227
+ float32x4_t xj;
228
+
229
+ w = &weights[j*col_stride + i];
230
+ wvec0_3 = vld1q_f32(&w[0]);
231
+ wvec4_7 = vld1q_f32(&w[4]);
232
+ wvec8_11 = vld1q_f32(&w[8]);
233
+ wvec12_15 = vld1q_f32(&w[12]);
234
+
235
+ xj = vld1q_dup_f32(&x[j]);
236
+
237
+ y0_3 = vmlaq_f32(y0_3, wvec0_3, xj);
238
+ y4_7 = vmlaq_f32(y4_7, wvec4_7, xj);
239
+ y8_11 = vmlaq_f32(y8_11, wvec8_11, xj);
240
+ y12_15 = vmlaq_f32(y12_15, wvec12_15, xj);
241
+ }
242
+
243
+ /* save y[0..15] back to memory */
244
+
245
+ vst1q_f32(&y[0], y0_3);
246
+ vst1q_f32(&y[4], y4_7);
247
+ vst1q_f32(&y[8], y8_11);
248
+ vst1q_f32(&y[12], y12_15);
249
+
250
+ }
251
+ }
252
+
253
+ static inline void sgemv8x1(float *out, const float *weights, int rows, int cols, int col_stride, const float *x)
254
+ {
255
+ int i, j;
256
+ for (i=0;i<rows;i+=8)
257
+ {
258
+ float * restrict y = &out[i];
259
+
260
+ /* keep y[0..15] in registers for duration of inner loop */
261
+
262
+ float32x4_t y0_3 = vdupq_n_f32(0);
263
+ float32x4_t y4_7 = vdupq_n_f32(0);
264
+
265
+ for (j=0;j<cols;j++)
266
+ {
267
+ const float * restrict w;
268
+ float32x4_t wvec0_3, wvec4_7;
269
+ float32x4_t xj;
270
+
271
+ w = &weights[j*col_stride + i];
272
+ wvec0_3 = vld1q_f32(&w[0]);
273
+ wvec4_7 = vld1q_f32(&w[4]);
274
+
275
+ xj = vld1q_dup_f32(&x[j]);
276
+
277
+ y0_3 = vmlaq_f32(y0_3, wvec0_3, xj);
278
+ y4_7 = vmlaq_f32(y4_7, wvec4_7, xj);
279
+ }
280
+
281
+ /* save y[0..15] back to memory */
282
+
283
+ vst1q_f32(&y[0], y0_3);
284
+ vst1q_f32(&y[4], y4_7);
285
+ }
286
+ }
287
+
288
+ static inline void sgemv(float *out, const float *weights, int rows, int cols, int col_stride, const float *x)
289
+ {
290
+ if ((rows&0xf) == 0) sgemv16x1(out, weights, rows, cols, col_stride, x);
291
+ else if ((rows&0x7) == 0) sgemv8x1(out, weights, rows, cols, col_stride, x);
292
+ else {
293
+ int i, j;
294
+ for (i=0;i<rows;i++)
295
+ {
296
+ out[i] = 0;
297
+ for (j=0;j<cols;j++) out[i] += weights[j*col_stride + i]*x[j];
298
+ }
299
+ }
300
+ }
301
+
302
+ /* Temporarily use unoptimized version */
303
+ static inline void sparse_sgemv8x4(float *out, const float *w, const int *idx, int rows, const float *x)
304
+ {
305
+ int i, j;
306
+ RNN_CLEAR(out, rows);
307
+ for (i=0;i<rows;i+=8)
308
+ {
309
+ int cols;
310
+ cols = *idx++;
311
+ for (j=0;j<cols;j++)
312
+ {
313
+ int pos;
314
+ float * restrict y;
315
+ float xj0, xj1, xj2, xj3;
316
+ pos = (*idx++);
317
+ xj0 = x[pos+0];
318
+ xj1 = x[pos+1];
319
+ xj2 = x[pos+2];
320
+ xj3 = x[pos+3];
321
+ y = &out[i];
322
+ y[0] += w[0]*xj0;
323
+ y[1] += w[1]*xj0;
324
+ y[2] += w[2]*xj0;
325
+ y[3] += w[3]*xj0;
326
+ y[4] += w[4]*xj0;
327
+ y[5] += w[5]*xj0;
328
+ y[6] += w[6]*xj0;
329
+ y[7] += w[7]*xj0;
330
+
331
+ y[0] += w[8]*xj1;
332
+ y[1] += w[9]*xj1;
333
+ y[2] += w[10]*xj1;
334
+ y[3] += w[11]*xj1;
335
+ y[4] += w[12]*xj1;
336
+ y[5] += w[13]*xj1;
337
+ y[6] += w[14]*xj1;
338
+ y[7] += w[15]*xj1;
339
+
340
+ y[0] += w[16]*xj2;
341
+ y[1] += w[17]*xj2;
342
+ y[2] += w[18]*xj2;
343
+ y[3] += w[19]*xj2;
344
+ y[4] += w[20]*xj2;
345
+ y[5] += w[21]*xj2;
346
+ y[6] += w[22]*xj2;
347
+ y[7] += w[23]*xj2;
348
+
349
+ y[0] += w[24]*xj3;
350
+ y[1] += w[25]*xj3;
351
+ y[2] += w[26]*xj3;
352
+ y[3] += w[27]*xj3;
353
+ y[4] += w[28]*xj3;
354
+ y[5] += w[29]*xj3;
355
+ y[6] += w[30]*xj3;
356
+ y[7] += w[31]*xj3;
357
+ w += 32;
358
+ }
359
+ }
360
+ }
361
+
362
+
363
+ #define SCALE (128.f*127.f)
364
+ #define SCALE_1 (1.f/128.f/127.f)
365
+
366
+ #define MAX_INPUTS 2048
367
+ #define MAX_OUTPUTS 8192
368
+
369
+ #if __ARM_FEATURE_DOTPROD
370
+ static inline int32x4_t vdotprod(int32x4_t acc, int8x16_t a, int8x16_t b) {
371
+ return vdotq_s32(acc, a, b);
372
+ }
373
+ #else
374
+ static inline int32x4_t vdotprod(int32x4_t acc, int8x16_t a, int8x16_t b)
375
+ {
376
+ return vpadalq_s16(acc, vpaddq_s16(vmull_s8(vget_low_s8(a), vget_low_s8(b)), vmull_high_s8(a, b)));
377
+ }
378
+ #endif
379
+
380
+ static inline void cgemv8x4(float *_out, const opus_int8 *w, const float *scale, int rows, int cols, const float *_x)
381
+ {
382
+ int i, j;
383
+ opus_int32 x_int[MAX_INPUTS/4];
384
+ opus_int8 *x = (opus_int8*) x_int;
385
+ const float32x4_t const127 = vdupq_n_f32(127.);
386
+ for (i=0;i<cols;i+=8) {
387
+ int32x4_t xi0, xi4;
388
+ int16x8_t x_short;
389
+ xi0 = vcvtnq_s32_f32(vmulq_f32(const127, vld1q_f32(&_x[i])));
390
+ xi4 = vcvtnq_s32_f32(vmulq_f32(const127, vld1q_f32(&_x[i+4])));
391
+ x_short = vcombine_s16(vmovn_s32(xi0), vmovn_s32(xi4));
392
+ vst1_s8(&x[i], vmovn_s16(x_short));
393
+ }
394
+ for (i=0;i<rows;i+=8)
395
+ {
396
+ int32x4_t acc0, acc1;
397
+ int32x4_t acc2, acc3;
398
+ acc0 = vdupq_n_s32(0);
399
+ acc1 = vdupq_n_s32(0);
400
+ acc2 = vdupq_n_s32(0);
401
+ acc3 = vdupq_n_s32(0);
402
+ j=0;
403
+ for (;j<cols-4;j+=8)
404
+ {
405
+ int8x16_t vw0, vw1, vw2, vw3, vx0, vx1;
406
+ vx0 = (int8x16_t)vld1q_dup_s32((int*)(void*)&x[j]);
407
+ vw0 = vld1q_s8(w);
408
+ vw1 = vld1q_s8(&w[16]);
409
+ acc0 = vdotprod(acc0, vw0, vx0);
410
+ acc1 = vdotprod(acc1, vw1, vx0);
411
+ vx1 = (int8x16_t)vld1q_dup_s32((int*)(void*)&x[j+4]);
412
+ vw2 = vld1q_s8(&w[32]);
413
+ vw3 = vld1q_s8(&w[48]);
414
+ acc2 = vdotprod(acc2, vw2, vx1);
415
+ acc3 = vdotprod(acc3, vw3, vx1);
416
+ w += 64;
417
+ }
418
+ acc0 = vaddq_s32(acc0, acc2);
419
+ acc1 = vaddq_s32(acc1, acc3);
420
+ for (;j<cols;j+=4)
421
+ {
422
+ int8x16_t vw0, vw1, vx;
423
+ vx = (int8x16_t)vld1q_dup_s32((int*)(void*)&x[j]);
424
+ vw0 = vld1q_s8(w);
425
+ vw1 = vld1q_s8(&w[16]);
426
+ acc0 = vdotprod(acc0, vw0, vx);
427
+ acc1 = vdotprod(acc1, vw1, vx);
428
+ w += 32;
429
+ }
430
+ vst1q_f32(&_out[i], vmulq_f32(vld1q_f32(&scale[i]), vcvtq_f32_s32(acc0)));
431
+ vst1q_f32(&_out[i+4], vmulq_f32(vld1q_f32(&scale[i+4]), vcvtq_f32_s32(acc1)));
432
+ }
433
+ }
434
+
435
+ static inline void sparse_cgemv8x4(float *_out, const opus_int8 *w, const int *idx, const float *scale, int rows, int cols, const float *_x)
436
+ {
437
+ int i, j;
438
+ opus_int32 x_int[MAX_INPUTS/4];
439
+ opus_int8 *x = (opus_int8*) x_int;
440
+ const float32x4_t const127 = vdupq_n_f32(127.);
441
+ for (i=0;i<cols;i+=8) {
442
+ int32x4_t xi0, xi4;
443
+ int16x8_t x_short;
444
+ xi0 = vcvtnq_s32_f32(vmulq_f32(const127, vld1q_f32(&_x[i])));
445
+ xi4 = vcvtnq_s32_f32(vmulq_f32(const127, vld1q_f32(&_x[i+4])));
446
+ x_short = vcombine_s16(vmovn_s32(xi0), vmovn_s32(xi4));
447
+ vst1_s8(&x[i], vmovn_s16(x_short));
448
+ }
449
+ for (i=0;i<rows;i+=8)
450
+ {
451
+ int colblocks;
452
+ int32x4_t acc0, acc1;
453
+ acc0 = vdupq_n_s32(0);
454
+ acc1 = vdupq_n_s32(0);
455
+ colblocks = *idx++;
456
+ for (j=0;j<colblocks;j++)
457
+ {
458
+ int pos;
459
+ pos = (*idx++);
460
+ int8x16_t vw0, vw1, vx;
461
+ vx = (int8x16_t)vld1q_dup_s32((int*)(void*)&x[pos]);
462
+ vw0 = vld1q_s8(w);
463
+ vw1 = vld1q_s8(&w[16]);
464
+ acc0 = vdotprod(acc0, vw0, vx);
465
+ acc1 = vdotprod(acc1, vw1, vx);
466
+ w += 32;
467
+ }
468
+ vst1q_f32(&_out[i], vmulq_f32(vld1q_f32(&scale[i]), vcvtq_f32_s32(acc0)));
469
+ vst1q_f32(&_out[i+4], vmulq_f32(vld1q_f32(&scale[i+4]), vcvtq_f32_s32(acc1)));
470
+ }
471
+ }
472
+
473
+
474
+ #endif
cpp/src/rnnoise/write_weights.c ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2023 Amazon */
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
+ #ifdef HAVE_CONFIG_H
28
+ #include "config.h"
29
+ #endif
30
+
31
+ #include <stdio.h>
32
+ #include <string.h>
33
+ #include <stddef.h>
34
+ #include "nnet.h"
35
+ #include "arch.h"
36
+ #include "nnet.h"
37
+
38
+ /* This is a bit of a hack because we need to build nnet_data.c and plc_data.c without USE_WEIGHTS_FILE,
39
+ but USE_WEIGHTS_FILE is defined in config.h. */
40
+ #undef HAVE_CONFIG_H
41
+ #ifdef USE_WEIGHTS_FILE
42
+ #undef USE_WEIGHTS_FILE
43
+ #endif
44
+ #include "rnnoise_data.c"
45
+
46
+ void write_weights(const WeightArray *list, FILE *fout)
47
+ {
48
+ int i=0;
49
+ unsigned char zeros[WEIGHT_BLOCK_SIZE] = {0};
50
+ while (list[i].name != NULL) {
51
+ WeightHead h;
52
+ if (strlen(list[i].name) >= sizeof(h.name) - 1) {
53
+ printf("[write_weights] warning: name %s too long\n", list[i].name);
54
+ }
55
+ memcpy(h.head, "DNNw", 4);
56
+ h.version = WEIGHT_BLOB_VERSION;
57
+ h.type = list[i].type;
58
+ h.size = list[i].size;
59
+ h.block_size = (h.size+WEIGHT_BLOCK_SIZE-1)/WEIGHT_BLOCK_SIZE*WEIGHT_BLOCK_SIZE;
60
+ RNN_CLEAR(h.name, sizeof(h.name));
61
+ strncpy(h.name, list[i].name, sizeof(h.name));
62
+ h.name[sizeof(h.name)-1] = 0;
63
+ celt_assert(sizeof(h) == WEIGHT_BLOCK_SIZE);
64
+ fwrite(&h, 1, WEIGHT_BLOCK_SIZE, fout);
65
+ fwrite(list[i].data, 1, h.size, fout);
66
+ fwrite(zeros, 1, h.block_size-h.size, fout);
67
+ i++;
68
+ }
69
+ }
70
+
71
+ int main(void)
72
+ {
73
+ FILE *fout = fopen("weights_blob.bin", "w");
74
+ write_weights(rnnoise_arrays, fout);
75
+ fclose(fout);
76
+ return 0;
77
+ }
cpp/src/rnnoise/x86/dnn_x86.h ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2011-2019 Mozilla
2
+ 2023 Amazon */
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 DNN_X86_H
29
+ #define DNN_X86_H
30
+
31
+ #include "cpu_support.h"
32
+ #include "opus_types.h"
33
+
34
+ void compute_linear_sse4_1(const LinearLayer *linear, float *out, const float *in);
35
+ void compute_activation_sse4_1(float *output, const float *input, int N, int activation);
36
+ void compute_conv2d_sse4_1(const Conv2dLayer *conv, float *out, float *mem, const float *in, int height, int hstride, int activation);
37
+
38
+ void compute_linear_avx2(const LinearLayer *linear, float *out, const float *in);
39
+ void compute_activation_avx2(float *output, const float *input, int N, int activation);
40
+ void compute_conv2d_avx2(const Conv2dLayer *conv, float *out, float *mem, const float *in, int height, int hstride, int activation);
41
+
42
+
43
+
44
+ #ifdef RNN_ENABLE_X86_RTCD
45
+
46
+ extern void (*const RNN_COMPUTE_LINEAR_IMPL[OPUS_ARCHMASK + 1])(
47
+ const LinearLayer *linear,
48
+ float *out,
49
+ const float *in
50
+ );
51
+ #define OVERRIDE_COMPUTE_LINEAR
52
+ #define compute_linear(linear, out, in, arch) \
53
+ ((*RNN_COMPUTE_LINEAR_IMPL[(arch) & OPUS_ARCHMASK])(linear, out, in))
54
+
55
+
56
+ extern void (*const RNN_COMPUTE_ACTIVATION_IMPL[OPUS_ARCHMASK + 1])(
57
+ float *output,
58
+ const float *input,
59
+ int N,
60
+ int activation
61
+ );
62
+ #define OVERRIDE_COMPUTE_ACTIVATION
63
+ #define compute_activation(output, input, N, activation, arch) \
64
+ ((*RNN_COMPUTE_ACTIVATION_IMPL[(arch) & OPUS_ARCHMASK])(output, input, N, activation))
65
+
66
+
67
+ extern void (*const RNN_COMPUTE_CONV2D_IMPL[OPUS_ARCHMASK + 1])(
68
+ const Conv2dLayer *conv,
69
+ float *out,
70
+ float *mem,
71
+ const float *in,
72
+ int height,
73
+ int hstride,
74
+ int activation
75
+ );
76
+ #define OVERRIDE_COMPUTE_CONV2D
77
+ #define compute_conv2d(conv, out, mem, in, height, hstride, activation, arch) \
78
+ ((*RNN_COMPUTE_CONV2D_IMPL[(arch) & OPUS_ARCHMASK])(conv, out, mem, in, height, hstride, activation))
79
+
80
+
81
+ #endif
82
+
83
+
84
+
85
+ #endif /* DNN_X86_H */
cpp/src/rnnoise/x86/nnet_avx2.c ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018-2019 Mozilla
2
+ 2023 Amazon */
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 "x86/x86_arch_macros.h"
33
+
34
+ #ifndef __AVX2__
35
+ #error nnet_avx2.c is being compiled without AVX2 enabled
36
+ #endif
37
+
38
+ #define RTCD_ARCH avx2
39
+
40
+ #include "nnet_arch.h"
cpp/src/rnnoise/x86/nnet_sse4_1.c ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018-2019 Mozilla
2
+ 2023 Amazon */
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 "x86/x86_arch_macros.h"
33
+
34
+ #ifndef __SSE4_1__
35
+ #error nnet_sse4_1.c is being compiled without SSE4.1 enabled
36
+ #endif
37
+
38
+ #define RTCD_ARCH sse4_1
39
+
40
+ #include "nnet_arch.h"
cpp/src/rnnoise/x86/x86_arch_macros.h ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2023 Amazon */
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
+ #ifdef _MSC_VER
28
+
29
+ # ifdef OPUS_X86_MAY_HAVE_SSE
30
+ # ifndef __SSE__
31
+ # define __SSE__
32
+ # endif
33
+ # endif
34
+
35
+ # ifdef OPUS_X86_MAY_HAVE_SSE2
36
+ # ifndef __SSE2__
37
+ # define __SSE2__
38
+ # endif
39
+ # endif
40
+
41
+ # ifdef OPUS_X86_MAY_HAVE_SSE4_1
42
+ # ifndef __SSE4_1__
43
+ # define __SSE4_1__
44
+ # endif
45
+ # endif
46
+
47
+ #endif
cpp/src/rnnoise/x86/x86_dnn_map.c ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2018-2019 Mozilla
2
+ 2023 Amazon */
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 "x86/x86cpu.h"
33
+ #include "nnet.h"
34
+
35
+ #ifdef RNN_ENABLE_X86_RTCD
36
+
37
+
38
+ void (*const RNN_COMPUTE_LINEAR_IMPL[OPUS_ARCHMASK + 1])(
39
+ const LinearLayer *linear,
40
+ float *out,
41
+ const float *in
42
+ ) = {
43
+ compute_linear_c, /* non-sse */
44
+ MAY_HAVE_SSE4_1(compute_linear), /* sse4.1 */
45
+ MAY_HAVE_AVX2(compute_linear) /* avx */
46
+ };
47
+
48
+ void (*const RNN_COMPUTE_ACTIVATION_IMPL[OPUS_ARCHMASK + 1])(
49
+ float *output,
50
+ const float *input,
51
+ int N,
52
+ int activation
53
+ ) = {
54
+ compute_activation_c, /* non-sse */
55
+ MAY_HAVE_SSE4_1(compute_activation), /* sse4.1 */
56
+ MAY_HAVE_AVX2(compute_activation) /* avx */
57
+ };
58
+
59
+ void (*const RNN_COMPUTE_CONV2D_IMPL[OPUS_ARCHMASK + 1])(
60
+ const Conv2dLayer *conv,
61
+ float *out,
62
+ float *mem,
63
+ const float *in,
64
+ int height,
65
+ int hstride,
66
+ int activation
67
+ ) = {
68
+ compute_conv2d_c, /* non-sse */
69
+ MAY_HAVE_SSE4_1(compute_conv2d), /* sse4.1 */
70
+ MAY_HAVE_AVX2(compute_conv2d) /* avx */
71
+ };
72
+
73
+
74
+ #endif
cpp/src/rnnoise/x86/x86cpu.c ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2014, Cisco Systems, INC
2
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
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 "cpu_support.h"
33
+ #include "pitch.h"
34
+ #include "x86cpu.h"
35
+
36
+ #ifdef RNN_ENABLE_X86_RTCD
37
+
38
+ #if defined(_MSC_VER)
39
+
40
+ #include <intrin.h>
41
+ static _inline void cpuid(unsigned int CPUInfo[4], unsigned int InfoType)
42
+ {
43
+ __cpuid((int*)CPUInfo, InfoType);
44
+ }
45
+
46
+ #else
47
+
48
+ #if defined(CPU_INFO_BY_C)
49
+ #include <cpuid.h>
50
+ #endif
51
+
52
+ static void cpuid(unsigned int CPUInfo[4], unsigned int InfoType)
53
+ {
54
+ #if defined(CPU_INFO_BY_ASM)
55
+ #if defined(__i386__) && defined(__PIC__)
56
+ /* %ebx is PIC register in 32-bit, so mustn't clobber it. */
57
+ __asm__ __volatile__ (
58
+ "xchg %%ebx, %1\n"
59
+ "cpuid\n"
60
+ "xchg %%ebx, %1\n":
61
+ "=a" (CPUInfo[0]),
62
+ "=r" (CPUInfo[1]),
63
+ "=c" (CPUInfo[2]),
64
+ "=d" (CPUInfo[3]) :
65
+ /* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */
66
+ "0" (InfoType), "2" (0)
67
+ );
68
+ #else
69
+ __asm__ __volatile__ (
70
+ "cpuid":
71
+ "=a" (CPUInfo[0]),
72
+ "=b" (CPUInfo[1]),
73
+ "=c" (CPUInfo[2]),
74
+ "=d" (CPUInfo[3]) :
75
+ /* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */
76
+ "0" (InfoType), "2" (0)
77
+ );
78
+ #endif
79
+ #elif defined(CPU_INFO_BY_C)
80
+ /* We use __get_cpuid_count to clear ECX to avoid a valgrind false-positive
81
+ prior to v3.17.0.*/
82
+ if (!__get_cpuid_count(InfoType, 0, &(CPUInfo[0]), &(CPUInfo[1]), &(CPUInfo[2]), &(CPUInfo[3]))) {
83
+ /* Our function cannot fail, but __get_cpuid{_count} can.
84
+ Returning all zeroes will effectively disable all SIMD, which is
85
+ what we want on CPUs that don't support CPUID. */
86
+ CPUInfo[3] = CPUInfo[2] = CPUInfo[1] = CPUInfo[0] = 0;
87
+ }
88
+ #else
89
+ # error "Configured to use x86 RTCD, but no CPU detection method available. " \
90
+ "Reconfigure with --disable-rtcd (or send patches)."
91
+ #endif
92
+ }
93
+
94
+ #endif
95
+
96
+ typedef struct CPU_Feature{
97
+ /* SIMD: 128-bit */
98
+ int HW_SSE;
99
+ int HW_SSE2;
100
+ int HW_SSE41;
101
+ /* SIMD: 256-bit */
102
+ int HW_AVX2;
103
+ } CPU_Feature;
104
+
105
+ static void rnn_cpu_feature_check(CPU_Feature *cpu_feature)
106
+ {
107
+ unsigned int info[4];
108
+ unsigned int nIds = 0;
109
+
110
+ cpuid(info, 0);
111
+ nIds = info[0];
112
+
113
+ if (nIds >= 1){
114
+ cpuid(info, 1);
115
+ cpu_feature->HW_SSE = (info[3] & (1 << 25)) != 0;
116
+ cpu_feature->HW_SSE2 = (info[3] & (1 << 26)) != 0;
117
+ cpu_feature->HW_SSE41 = (info[2] & (1 << 19)) != 0;
118
+ cpu_feature->HW_AVX2 = (info[2] & (1 << 28)) != 0 && (info[2] & (1 << 12)) != 0;
119
+ if (cpu_feature->HW_AVX2 && nIds >= 7) {
120
+ cpuid(info, 7);
121
+ cpu_feature->HW_AVX2 = cpu_feature->HW_AVX2 && (info[1] & (1 << 5)) != 0;
122
+ } else {
123
+ cpu_feature->HW_AVX2 = 0;
124
+ }
125
+ }
126
+ else {
127
+ cpu_feature->HW_SSE = 0;
128
+ cpu_feature->HW_SSE2 = 0;
129
+ cpu_feature->HW_SSE41 = 0;
130
+ cpu_feature->HW_AVX2 = 0;
131
+ }
132
+ }
133
+
134
+ static int rnn_select_arch_impl(void)
135
+ {
136
+ CPU_Feature cpu_feature;
137
+ int arch;
138
+
139
+ rnn_cpu_feature_check(&cpu_feature);
140
+
141
+ arch = 0;
142
+ if (!cpu_feature.HW_SSE41)
143
+ {
144
+ return arch;
145
+ }
146
+ arch++;
147
+
148
+ if (!cpu_feature.HW_AVX2)
149
+ {
150
+ return arch;
151
+ }
152
+ arch++;
153
+
154
+ return arch;
155
+ }
156
+
157
+ int rnn_select_arch(void) {
158
+ int arch = rnn_select_arch_impl();
159
+ #ifdef FUZZING
160
+ /* Randomly downgrade the architecture. */
161
+ arch = rand()%(arch+1);
162
+ #endif
163
+ return arch;
164
+ }
165
+
166
+ #endif
cpp/src/rnnoise/x86/x86cpu.h ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright (c) 2014, Cisco Systems, INC
2
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
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
+ #if !defined(X86CPU_H)
29
+ # define X86CPU_H
30
+
31
+ # define MAY_HAVE_SSE4_1(name) name ## _sse4_1
32
+
33
+ # define MAY_HAVE_AVX2(name) name ## _avx2
34
+
35
+ # ifdef RNN_ENABLE_X86_RTCD
36
+ int opus_select_arch(void);
37
+ # endif
38
+
39
+ # if defined(__SSE2__)
40
+ # include "common.h"
41
+
42
+ /*MOVD should not impose any alignment restrictions, but the C standard does,
43
+ and UBSan will report errors if we actually make unaligned accesses.
44
+ Use this to work around those restrictions (which should hopefully all get
45
+ optimized to a single MOVD instruction).
46
+ GCC implemented _mm_loadu_si32() since GCC 11; HOWEVER, there is a bug!
47
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99754
48
+ LLVM implemented _mm_loadu_si32() since Clang 8.0, however the
49
+ __clang_major__ version number macro is unreliable, as vendors
50
+ (specifically, Apple) will use different numbering schemes than upstream.
51
+ Clang's advice is "use feature detection", but they do not provide feature
52
+ detection support for specific SIMD functions.
53
+ We follow the approach from the SIMDe project and instead detect unrelated
54
+ features that should be available in the version we want (see
55
+ <https://github.com/simd-everywhere/simde/blob/master/simde/simde-detect-clang.h>).*/
56
+ # if defined(__clang__)
57
+ # if __has_warning("-Wextra-semi-stmt") || \
58
+ __has_builtin(__builtin_rotateleft32)
59
+ # define OPUS_CLANG_8 (1)
60
+ # endif
61
+ # endif
62
+ # if !defined(_MSC_VER) && !OPUS_GNUC_PREREQ(11,3) && !defined(OPUS_CLANG_8)
63
+ # include <string.h>
64
+ # include <emmintrin.h>
65
+
66
+ # ifdef _mm_loadu_si32
67
+ # undef _mm_loadu_si32
68
+ # endif
69
+ # define _mm_loadu_si32 WORKAROUND_mm_loadu_si32
70
+ static inline __m128i WORKAROUND_mm_loadu_si32(void const* mem_addr) {
71
+ int val;
72
+ memcpy(&val, mem_addr, sizeof(val));
73
+ return _mm_cvtsi32_si128(val);
74
+ }
75
+ # elif defined(_MSC_VER)
76
+ /* MSVC needs this for _mm_loadu_si32 */
77
+ # include <immintrin.h>
78
+ # endif
79
+
80
+ # define OP_CVTEPI8_EPI32_M32(x) \
81
+ (_mm_cvtepi8_epi32(_mm_loadu_si32(x)))
82
+
83
+ # define OP_CVTEPI16_EPI32_M64(x) \
84
+ (_mm_cvtepi16_epi32(_mm_loadl_epi64((__m128i *)(void*)(x))))
85
+
86
+ # endif
87
+
88
+ #endif