
@@ -39,14 +108,14 @@ Note that the default threshold of 0.5 is used to generate binary speech indicat
cd ./examples
python plot_pr_curves.py
```
-
+
### **2. Agent-Friendly:**
As illustrated in the figure below, TEN VAD rapidly detects speech-to-non-speech transitions, whereas Silero VAD suffers from a delay of several hundred milliseconds, resulting in increased end-to-end latency in human-agent interaction systems. In addition, as demonstrated in the 6.5s-7.0s audio segment, Silero VAD fails to identify short silent durations between adjacent speech segments.
-
+
### **3. Lightweight:**
We evaluated the RTF (Real-Time Factor) across five distinct platforms, each equipped with varying CPUs. TEN VAD demonstrates much lower computational complexity and smaller library size than Silero VAD.
@@ -57,6 +126,7 @@ We evaluated the RTF (Real-Time Factor) across five distinct platforms, each equ
CPU |
RTF |
Lib Size |
+
| TEN VAD |
@@ -68,16 +138,16 @@ We evaluated the RTF (Real-Time Factor) across five distinct platforms, each equ
Linux |
AMD Ryzen 9 5900X 12-Core |
0.0150 |
- / |
- 306KB |
- 2.16MB(JIT) / 2.22MB(ONNX) |
+ / |
+ 306KB |
+ 2.16MB(JIT) / 2.22MB(ONNX) |
- | Intel(R) Xeon(R) Platinum 8253 |
+ Intel(R) Xeon(R) Platinum 8253 |
0.0136 |
- | Intel(R) Xeon(R) Gold 6348 CPU @ 2.60GHz |
+ Intel(R) Xeon(R) Gold 6348 CPU @ 2.60GHz |
0.0086 |
0.0127 |
@@ -85,7 +155,7 @@ We evaluated the RTF (Real-Time Factor) across five distinct platforms, each equ
Windows |
Intel i7-10710U |
0.0150 |
-
/ |
+
/ |
464KB(x86) / 508KB(x64) |
@@ -94,11 +164,17 @@ We evaluated the RTF (Real-Time Factor) across five distinct platforms, each equ
| 0.0160 |
731KB |
+
+ | Web |
+ macOS(M1) |
+ 0.010 |
+ 277KB |
+
| Android |
Galaxy J6+ (32bit, 425) |
0.0570 |
- 373KB(v7a) / 532KB(v8a) |
+ 373KB(v7a) / 532KB(v8a) |
| Oppo A3s (450) |
@@ -108,33 +184,31 @@ We evaluated the RTF (Real-Time Factor) across five distinct platforms, each equ
iOS |
iPhone6 (A8) |
0.0210 |
- 320KB |
+ 320KB |
| iPhone8 (A11) |
0.0050 |
-
-
+
### **4. Multiple programming languages and platforms:**
-TEN VAD provides cross-platform C compatibility across five operating systems (Linux x64, Windows, macOS, Android, iOS), with Python bindings optimized for Linux x64.
+TEN VAD provides cross-platform C compatibility across five operating systems (Linux x64, Windows, macOS, Android, iOS), with Python bindings optimized for Linux x64, with wasm for Web.
+
+
### **5. Supproted sampling rate and hop size:**
TEN VAD operates on 16kHz audio input with configurable hop sizes (optimized frame configurations: 160/256 samples=10/16ms). Other sampling rates must be resampled to 16kHz.
-
+
+
## **Installation**
```
-git clone https://huggingface.co/TEN-framework/ten-vad
+git clone https://github.com/TEN-framework/ten-vad.git
```
+
## **Quick Start**
The project supports five major platforms with dynamic library linking.
@@ -152,7 +226,7 @@ The project supports five major platforms with dynamic library linking.
libten_vad.so |
x64 |
Python, C |
-
ten_vad.h ten_vad.py |
+
ten_vad.h ten_vad.py ten_vad.js |
|
@@ -169,6 +243,13 @@ The project supports five major platforms with dynamic library linking.
| C |
|
+
+ | Web |
+ ten_vad.wasm |
+ / |
+ JS |
+ |
+
| Android |
libten_vad.so |
@@ -178,13 +259,14 @@ The project supports five major platforms with dynamic library linking.
| iOS |
- ten_vad.framework |
- arm64 |
+ ten_vad.framework |
+ arm64 |
C |
1. not simulator 2. not iPad |
-
+
+
### **Python Usage**
#### **1. Linux**
@@ -201,7 +283,7 @@ Note: You could use other versions of above packages, but we didn't test other v
-The **lib** only depends on numpy, you have to install the dependency via requirements.txt:
+The **lib** only depend on numpy, you have to install the dependency via requirements.txt:
```pip install -r requirements.txt```
@@ -219,6 +301,7 @@ sudo apt install libc++1
+
#### **Usage**
Note: For usage in python, you can either use it by **git clone** or **pip**.
@@ -226,7 +309,7 @@ Note: For usage in python, you can either use it by **git clone** or **pip**.
1. Clone the repository
```
-git clone https://huggingface.co/TEN-framework/ten-vad
+git clone https://github.com/TEN-framework/ten-vad.git
```
2. Enter examples directory
@@ -238,6 +321,7 @@ cd ./examples
```
python test.py s0724-s0730.wav out.txt
```
+
##### **By using pip:**
@@ -252,10 +336,25 @@ pip install -U --force-reinstall -v git+https://github.com/TEN-framework/ten-vad
```
from ten_vad import TenVad
```
+
+
+### **JS Usage**
+
+#### **1. Web**
+##### **Requirements**
+- Node.js (macOS v14.18.2, Linux v16.20.2 verified)
+- Terminal
+
+##### **Usage**
+```
+1) cd ./examples
+2) node test_node.js s0724-s0730.wav out.txt
+```
+
### **C Usage**
#### **Build Scripts**
-Located in examples/ directory:
+Located in examples/ directory and examples_onnx (for **ONNX** usage on Linux):
- Linux: build-and-deploy-linux.sh
- Windows: build-and-deploy-windows.bat
@@ -275,12 +374,13 @@ Runtime library path configuration:
- Configure toolchain and architecture settings
#### **Overview of Usage**
-- Navigate to examples/
+- Navigate to examples/ or examples_onx/ (for **ONNX** usage on Linux)
- Execute platform-specific build script
- Configure dynamic library path
- Run demo with sample audio s0724-s0730.wav
- Processed results saved to out.txt
+
The detailed usage methods of each platform are as follows
@@ -296,12 +396,22 @@ sudo apt update
sudo apt install libc++1
```
-##### **Usage**
+##### **Usage (prebuilt-lib)**
```
1) cd ./examples
2) ./build-and-deploy-linux.sh
```
+##### **Usage (ONNX)**
+You have to download the **onnxruntime** packages from the [official website](https://github.com/microsoft/onnxruntime). Note that the version of onnxruntime must be higher than or equal to 1.17.1 (e.g. onnxruntime-linux-x64-1.17.1.tgz).
+```
+1) cd examples_onnx/
+2) ./build-and-deploy-linux.sh --ort-root /absolute/path/to/your/onnxruntime/root/dir
+```
+Note: If executing the onnx demo from a different directory than the one used when running build-and-deploy-linux.sh, ensure to create a symbolic link to src/onnx_model/ to prevent ONNX model file loading failures.
+
+
+
#### **2. Windows**
##### **Requirements**
- Visual Studio (2017, 2019, 2022 verified)
@@ -316,6 +426,7 @@ sudo apt install libc++1
- Visual Studio version (default: 2019)
3) ./build-and-deploy-windows.bat
```
+
#### **3. macOS**
##### **Requirements**
@@ -330,6 +441,7 @@ sudo apt install libc++1
- Alternative: x86_64 (Intel)
3) ./build-and-deploy-mac.sh
```
+
#### **4. Android**
##### **Requirements**
@@ -346,6 +458,7 @@ sudo apt install libc++1
- Toolchain: aarch64-linux-android-clang (default) or custom NDK toolchain
4) ./build-and-deploy-android.sh
```
+
#### **5. iOS**
##### **Requirements**
@@ -397,6 +510,29 @@ cd ./examples
3.5. Build in Xcode and run demo on your device.
+
+
+## TEN Ecosystem
+
+| Project | Preview |
+| ------- | ------- |
+| [**🏚️ TEN Framework**][ten-framework-link]
TEN is an open-source framework for real-time, multimodal conversational AI.
![][ten-framework-shield] | ![][ten-framework-banner] |
+| [**️🔂 TEN Turn Detection**][ten-turn-detection-link]
TEN is for full-duplex dialogue communication.
![][ten-turn-detection-shield] | ![][ten-turn-detection-banner] |
+| [**🔉 TEN VAD**][ten-vad-link]
TEN VAD is a low-latency, lightweight and high-performance streaming voice activity detector (VAD).
![][ten-vad-shield] | ![][ten-vad-banner] |
+| [**🎙️ TEN Agent**][ten-agent-link]
TEN Agent is a showcase of TEN Framewrok.
| ![][ten-agent-banner] |
+| **🎨 TMAN Designer**
TMAN Designer is low/no code option to make a voice agent with easy to use workflow UI.
| ![][tman-designer-banner] |
+| [**📒 TEN Portal**][ten-portal-link]
The official site of TEN framework, it has documentation and blog.
![][ten-portal-shield] | ![][ten-portal-banner] |
+
+
+
+## Ask Questions
+
+[](https://deepwiki.com/TEN-framework/TEN-vad)
+
+Most questions can be answered by using DeepWiki, it is fast, intutive to use and supports multiple languages.
+
+
+
## **Citations**
```
@misc{TEN VAD,
@@ -409,29 +545,34 @@ cd ./examples
email = {developer@ten.ai}
}
```
+
+
+## License
+
+This project is Apache 2.0 with additional conditions licensed. Refer to the "LICENSE" file in the root directory for detailed information. Note that `pitch_est.cc` contains modified code derived from [LPCNet](https://github.com/xiph/LPCNet), which is [BSD-2-Clause](https://spdx.org/licenses/BSD-2-Clause.html) and [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html) licensed, refer to the NOTICES file in the root directory for detailed information.
+
+
+
-## Usage Guidance
-1. You may not (i) host the TEN VAD or the Derivative Works on any End
- User devices, including but not limited to any mobile terminal devices
- or (ii) Deploy the TEN VAD in a way that competes with Agora's
- offerings and/or that allows others to compete with Agora's offerings,
- including without limitation enabling any third party to develop or
- deploy Applications.
+[back-to-top]: https://img.shields.io/badge/-Back_to_top-gray?style=flat-square
-2. You may Deploy the TEN VAD solely to create and enable deployment
- of your Application(s) solely for your benefit and the benefit of your
- direct End Users. If you prefer, you may include the following notice in
- the documentation of your Application(s): "Powered by TEN VAD".
+[ten-framework-shield]: https://img.shields.io/github/stars/ten-framework/ten_framework?color=ffcb47&labelColor=gray&style=flat-square&logo=github
+[ten-framework-banner]: https://github.com/user-attachments/assets/7c8f72d7-3993-4d01-8504-b71578a22944
+[ten-framework-link]: https://github.com/ten-framework/ten_framework
-3. "End Users" shall mean the end-users of your Application(s) who access
- the TEN VAD solely to the extent necessary to access and use the
- Application(s) you create or deploy using TEN VAD.
+[ten-vad-link]: https://github.com/ten-framework/ten-vad
+[ten-vad-shield]: https://img.shields.io/github/stars/ten-framework/ten-vad?color=ffcb47&labelColor=gray&style=flat-square&logo=github
+[ten-vad-banner]: https://github.com/user-attachments/assets/d45870e4-9453-4047-8163-08737f82863f
-4. "Application(s)" shall mean your software programs designed or developed
- by using the TEN VAD or where deployment is enabled by the TEN
- VAD.
+[ten-turn-detection-link]: https://github.com/ten-framework/ten-turn-detection
+[ten-turn-detection-shield]: https://img.shields.io/github/stars/ten-framework/ten-turn-detection?color=ffcb47&labelColor=gray&style=flat-square&logo=github
+[ten-turn-detection-banner]: https://github.com/user-attachments/assets/8d0ec716-5d0e-43e4-ad9a-d97b17305658
-## Future Open Source Plan
+[ten-agent-link]: https://github.com/TEN-framework/ten-framework/tree/main/ai_agents
+[ten-agent-banner]: https://github.com/user-attachments/assets/38de2207-939b-4702-a0aa-04491f5b5275
+[tman-designer-banner]: https://github.com/user-attachments/assets/804c3543-0a47-42b7-b40b-ef32b742fb8f
-TEN-VAD is currently released as a binary. Based on community feedback and interest, we plan to progressively open source the internal components of the binary.
\ No newline at end of file
+[ten-portal-link]: https://github.com/ten-framework/portal
+[ten-portal-shield]: https://img.shields.io/github/stars/ten-framework/portal?color=ffcb47&labelColor=gray&style=flat-square&logo=github
+[ten-portal-banner]: https://github.com/user-attachments/assets/e17d8aaa-5928-45dd-ac71-814928e26a89
diff --git a/examples/.gitattributes b/examples/.gitattributes
deleted file mode 100644
index d899f6551a51cf19763c5955c7a06a2726f018e9..0000000000000000000000000000000000000000
--- a/examples/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-*.wav filter=lfs diff=lfs merge=lfs -text
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 4c5b62c7dc8e23b43baa1f38a24fe13d89a90d11..709373c8da0df98b44d96faecf204cee9e14c422 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,3 +1,9 @@
+#
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
+#
cmake_minimum_required(VERSION 3.10)
get_filename_component(ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../ ABSOLUTE)
diff --git a/examples/build-and-deploy-android.sh b/examples/build-and-deploy-android.sh
index 80c00e9fe354d40607ecd68d241d97b7e92f78f4..d367f8d28bfaed54c1bd436790c2ff468f3b7864 100755
--- a/examples/build-and-deploy-android.sh
+++ b/examples/build-and-deploy-android.sh
@@ -1,4 +1,10 @@
#!/bin/bash
+#
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
+#
set -eo pipefail
# Customize the arch and toolchain
diff --git a/examples/build-and-deploy-ios.sh b/examples/build-and-deploy-ios.sh
index 190fe02ffc9484acfda82b9899ea7a08943dc401..ee95036810e50d5bf600547b7e02a11feed0221c 100755
--- a/examples/build-and-deploy-ios.sh
+++ b/examples/build-and-deploy-ios.sh
@@ -1,4 +1,10 @@
#!/usr/bin/env bash
+#
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
+#
set -euo pipefail
work_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
diff --git a/examples/build-and-deploy-linux.sh b/examples/build-and-deploy-linux.sh
index 359ba9c214f414b77d4a66226ca4cf3ea0fe30d8..3a66db45e62dca830646f53338ec34dfd3b87dba 100755
--- a/examples/build-and-deploy-linux.sh
+++ b/examples/build-and-deploy-linux.sh
@@ -1,4 +1,10 @@
#!/bin/bash
+#
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
+#
set -euo pipefail
arch=x64
diff --git a/examples/build-and-deploy-mac.sh b/examples/build-and-deploy-mac.sh
index 95baf6cc419fda759c7c4434151aa879a835e07e..2888712ebf8aab7f45733e24f51ba85f106e676c 100755
--- a/examples/build-and-deploy-mac.sh
+++ b/examples/build-and-deploy-mac.sh
@@ -1,4 +1,10 @@
#!/bin/bash
+#
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
+#
set -euo pipefail
# Customize the arch
diff --git a/examples/build-and-deploy-windows.bat b/examples/build-and-deploy-windows.bat
index 33b3bfd23e31eabf7347c442634122b6d225f478..d954ea02247a76597022fb7dc6354ff3e1aae931 100755
--- a/examples/build-and-deploy-windows.bat
+++ b/examples/build-and-deploy-windows.bat
@@ -1,6 +1,13 @@
@echo off
setlocal
+@REM
+@REM Copyright © 2025 Agora
+@REM This file is part of TEN Framework, an open source project.
+@REM Licensed under the Apache License, Version 2.0, with certain conditions.
+@REM Refer to the "LICENSE" file in the root directory for more information.
+@REM
+
@REM Customize the arch
set arch=x64
@REM set arch=x86
diff --git a/examples/images/.gitattributes b/examples/images/.gitattributes
deleted file mode 100644
index 3a241177f2f2488fcbabec586b5585ca46da9a25..0000000000000000000000000000000000000000
--- a/examples/images/.gitattributes
+++ /dev/null
@@ -1,2 +0,0 @@
-*.jpg filter=lfs diff=lfs merge=lfs -text
-*.png filter=lfs diff=lfs merge=lfs -text
diff --git a/examples/main.c b/examples/main.c
index 0fd879d20d3bc18239368633da48bc2e37e7a7db..e9b7239bdceb0f51b606837db840ffd24ba74e6c 100644
--- a/examples/main.c
+++ b/examples/main.c
@@ -1,7 +1,8 @@
//
+// Copyright © 2025 Agora
// This file is part of TEN Framework, an open source project.
-// Licensed under the Apache License, Version 2.0.
-// See the LICENSE file for more information.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
//
#include
#include
@@ -86,9 +87,16 @@ int vad_process(int16_t *input_buf, uint32_t frame_num,
for (int i = 0; i < frame_num; ++i)
{
int16_t *audio_data = input_buf + i * hop_size;
- ten_vad_process(ten_vad_handle, audio_data, hop_size,
- &out_probs[i], &out_flags[i]);
- printf("[%d] %0.6f, %d\n", i, out_probs[i], out_flags[i]);
+ int res = ten_vad_process(ten_vad_handle, audio_data, hop_size,
+ &out_probs[i], &out_flags[i]);
+ if (res == 0)
+ {
+ printf("[%d] %0.6f, %d\n", i, out_probs[i], out_flags[i]);
+ }
+ else
+ {
+ printf("ten_vad_process failed res %d\n", res);
+ }
}
uint64_t end = get_timestamp_ms();
*use_time = (float)(end - start);
@@ -295,4 +303,4 @@ int read_wav_file(FILE *fp, wav_info_t *info)
// restore original file position
fseek(fp, orig_pos, SEEK_SET);
return 0;
-}
\ No newline at end of file
+}
diff --git a/examples/plot_pr_curves.py b/examples/plot_pr_curves.py
index 7222305746d332f7b5aa8359051fea29d5cbc1a4..f333de22114e86bb8c0768014d80fb06f201488e 100644
--- a/examples/plot_pr_curves.py
+++ b/examples/plot_pr_curves.py
@@ -1,7 +1,8 @@
#
-# This file is part of TEN Framework, an open source project.
-# Licensed under the Apache License, Version 2.0.
-# See the LICENSE file for more information.
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
#
import os, glob, sys, torchaudio
import numpy as np
@@ -114,7 +115,7 @@ if __name__ == "__main__":
# Get the directory of the script
script_dir = os.path.dirname(os.path.abspath(__file__))
- # testset dir
+ # TEN-VAD-TestSet dir
test_dir = f"{script_dir}/../testset"
# Initialization
diff --git a/examples/sample_array.h b/examples/sample_array.h
index 7fcb2ee2e0e88fd2d37602971f98b84ee8c5eb6e..b1bab14ac3e111c040c6bf3a421f704f1cbec553 100644
--- a/examples/sample_array.h
+++ b/examples/sample_array.h
@@ -1,3 +1,9 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
// Used for iOS APP demo
unsigned char sample_array[] = {
0xe3, 0xff, 0xd4, 0xff, 0xdc, 0xff, 0xe0, 0xff, 0xf6, 0xff, 0xf5, 0xff, 0xf6, 0xff, 0xfc, 0xff,
diff --git a/examples/test.py b/examples/test.py
index 83f51646805eba599355807a4c14e6970f061bc6..7fceb5575276ba0a424db3270355501027d8c55f 100644
--- a/examples/test.py
+++ b/examples/test.py
@@ -1,7 +1,8 @@
#
-# This file is part of TEN Framework, an open source project.
-# Licensed under the Apache License, Version 2.0.
-# See the LICENSE file for more information.
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
#
import sys, os
diff --git a/examples/test_node.js b/examples/test_node.js
new file mode 100644
index 0000000000000000000000000000000000000000..fb1e1e6c024ea0bd6cbb7fc0db8fd04031890b7d
--- /dev/null
+++ b/examples/test_node.js
@@ -0,0 +1,529 @@
+#!/usr/bin/env node
+
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+
+/**
+ * TEN VAD WebAssembly Node.js Test
+ * Simplified and clean version based on main.c
+ */
+
+const fs = require('fs');
+const path = require('path');
+
+// Configuration
+const HOP_SIZE = 256; // 16ms per frame
+const VOICE_THRESHOLD = 0.5; // Voice detection threshold
+
+// WASM module paths
+const WASM_DIR = './../lib/Web';
+const WASM_JS_FILE = path.join(WASM_DIR, 'ten_vad.js');
+const WASM_BINARY_FILE = path.join(WASM_DIR, 'ten_vad.wasm');
+
+// Global state
+let vadModule = null;
+let vadHandle = null;
+let vadHandlePtr = null;
+
+// ============================================================================
+// UTILITY FUNCTIONS
+// ============================================================================
+
+function getTimestamp() {
+ return Date.now();
+}
+
+function addHelperFunctions() {
+ if (!vadModule.getValue) {
+ vadModule.getValue = function(ptr, type) {
+ switch (type) {
+ case 'i32': return vadModule.HEAP32[ptr >> 2];
+ case 'float': return vadModule.HEAPF32[ptr >> 2];
+ default: throw new Error(`Unsupported type: ${type}`);
+ }
+ };
+ }
+
+ if (!vadModule.UTF8ToString) {
+ vadModule.UTF8ToString = function(ptr) {
+ if (!ptr) return '';
+ let result = '';
+ let i = ptr;
+ while (vadModule.HEAPU8[i]) {
+ result += String.fromCharCode(vadModule.HEAPU8[i++]);
+ }
+ return result;
+ };
+ }
+}
+
+// ============================================================================
+// AUDIO GENERATION
+// ============================================================================
+
+function generateTestAudio(durationMs = 5000) {
+ const sampleRate = 16000;
+ const totalSamples = Math.floor(durationMs * sampleRate / 1000);
+ const audioData = new Int16Array(totalSamples);
+
+ console.log(`Generating ${totalSamples} samples for ${durationMs}ms audio...`);
+
+ for (let i = 0; i < totalSamples; i++) {
+ const t = i / sampleRate;
+ let sample = 0;
+
+ if (t < 2.0) {
+ // Voice frequencies (440Hz + 880Hz)
+ sample = Math.sin(2 * Math.PI * 440 * t) * 8000 +
+ Math.sin(2 * Math.PI * 880 * t) * 4000;
+ } else if (t < 3.0) {
+ // Noise
+ sample = (Math.random() - 0.5) * 3000;
+ } else if (t < 4.0) {
+ // Mixed voice (220Hz + 660Hz)
+ sample = Math.sin(2 * Math.PI * 220 * t) * 6000 +
+ Math.sin(2 * Math.PI * 660 * t) * 3000;
+ } else {
+ // Silence with minimal noise
+ sample = Math.random() * 50;
+ }
+
+ audioData[i] = Math.max(-32768, Math.min(32767, Math.floor(sample)));
+ }
+
+ return audioData;
+}
+
+// ============================================================================
+// VAD OPERATIONS
+// ============================================================================
+
+function getVADVersion() {
+ if (!vadModule) return "unknown";
+ try {
+ const versionPtr = vadModule._ten_vad_get_version();
+ return vadModule.UTF8ToString(versionPtr);
+ } catch (error) {
+ return "unknown";
+ }
+}
+
+function createVADInstance() {
+ try {
+ vadHandlePtr = vadModule._malloc(4);
+ const result = vadModule._ten_vad_create(vadHandlePtr, HOP_SIZE, VOICE_THRESHOLD);
+
+ if (result === 0) {
+ vadHandle = vadModule.getValue(vadHandlePtr, 'i32');
+ return true;
+ } else {
+ console.error(`VAD creation failed with code: ${result}`);
+ vadModule._free(vadHandlePtr);
+ return false;
+ }
+ } catch (error) {
+ console.error(`Error creating VAD instance: ${error.message}`);
+ return false;
+ }
+}
+
+function destroyVADInstance() {
+ if (vadHandlePtr && vadModule) {
+ vadModule._ten_vad_destroy(vadHandlePtr);
+ vadModule._free(vadHandlePtr);
+ vadHandlePtr = null;
+ vadHandle = null;
+ }
+}
+
+async function processAudio(inputBuf, frameNum, outProbs, outFlags) {
+ console.log(`VAD version: ${getVADVersion()}`);
+
+ if (!createVADInstance()) {
+ return -1;
+ }
+
+ const startTime = getTimestamp();
+
+ for (let i = 0; i < frameNum; i++) {
+ const frameStart = i * HOP_SIZE;
+ const frameData = inputBuf.slice(frameStart, frameStart + HOP_SIZE);
+
+ const audioPtr = vadModule._malloc(HOP_SIZE * 2);
+ const probPtr = vadModule._malloc(4);
+ const flagPtr = vadModule._malloc(4);
+
+ try {
+ vadModule.HEAP16.set(frameData, audioPtr / 2);
+
+ const result = vadModule._ten_vad_process(
+ vadHandle, audioPtr, HOP_SIZE, probPtr, flagPtr
+ );
+
+ if (result === 0) {
+ const probability = vadModule.getValue(probPtr, 'float');
+ const flag = vadModule.getValue(flagPtr, 'i32');
+
+ outProbs[i] = probability;
+ outFlags[i] = flag;
+
+ console.log(`[${i}] ${probability.toFixed(6)}, ${flag}`);
+ } else {
+ console.error(`Frame ${i} processing failed with code: ${result}`);
+ outProbs[i] = 0.0;
+ outFlags[i] = 0;
+ }
+ } finally {
+ vadModule._free(audioPtr);
+ vadModule._free(probPtr);
+ vadModule._free(flagPtr);
+ }
+ }
+
+ const endTime = getTimestamp();
+ const processingTime = endTime - startTime;
+
+ destroyVADInstance();
+ return processingTime;
+}
+
+// ============================================================================
+// RESULT HANDLING
+// ============================================================================
+
+function printResults(processingTime, totalAudioTime, outFlags, frameNum) {
+ const rtf = processingTime / totalAudioTime;
+ const voiceFrames = outFlags.filter(flag => flag === 1).length;
+ const voicePercentage = (voiceFrames / frameNum * 100).toFixed(1);
+
+ console.log(`\n=== Processing Results ===`);
+ console.log(`Time: ${processingTime}ms, Audio: ${totalAudioTime.toFixed(2)}ms, RTF: ${rtf.toFixed(6)}`);
+ console.log(`Voice frames: ${voiceFrames}/${frameNum} (${voicePercentage}%)`);
+}
+
+function saveResults(outProbs, outFlags, frameNum, filename = 'out.txt') {
+ let output = '';
+ for (let i = 0; i < frameNum; i++) {
+ output += `[${i}] ${outProbs[i].toFixed(6)}, ${outFlags[i]}\n`;
+ }
+
+ try {
+ fs.writeFileSync(filename, output);
+ console.log(`Results saved to ${filename}`);
+ } catch (error) {
+ console.error(`Failed to save results: ${error.message}`);
+ }
+}
+
+// ============================================================================
+// TEST FUNCTIONS
+// ============================================================================
+
+async function testWithArray() {
+ console.log("=== Array Test ===\n");
+
+ const inputBuf = generateTestAudio(5000);
+ const byteNum = inputBuf.byteLength;
+ const sampleNum = byteNum / 2;
+ const totalAudioTime = sampleNum / 16.0;
+ const frameNum = Math.floor(sampleNum / HOP_SIZE);
+
+ console.log(`Audio info: ${byteNum} bytes, ${frameNum} frames, ${totalAudioTime.toFixed(2)}ms`);
+
+ const outProbs = new Float32Array(frameNum);
+ const outFlags = new Int32Array(frameNum);
+
+ const processingTime = await processAudio(inputBuf, frameNum, outProbs, outFlags);
+
+ if (processingTime > 0) {
+ printResults(processingTime, totalAudioTime, outFlags, frameNum);
+ }
+
+ return 0;
+}
+
+// WAV File parsing utilities
+function parseWAVHeader(buffer) {
+ if (buffer.length < 44) {
+ throw new Error('Invalid WAV file: too small');
+ }
+
+ // Check RIFF header
+ const riffHeader = buffer.toString('ascii', 0, 4);
+ if (riffHeader !== 'RIFF') {
+ throw new Error('Invalid WAV file: missing RIFF header');
+ }
+
+ // Check WAVE format
+ const waveHeader = buffer.toString('ascii', 8, 12);
+ if (waveHeader !== 'WAVE') {
+ throw new Error('Invalid WAV file: not WAVE format');
+ }
+
+ let offset = 12;
+ let dataOffset = -1;
+ let dataSize = 0;
+ let sampleRate = 0;
+ let channels = 0;
+ let bitsPerSample = 0;
+
+ // Parse chunks
+ while (offset < buffer.length - 8) {
+ const chunkId = buffer.toString('ascii', offset, offset + 4);
+ const chunkSize = buffer.readUInt32LE(offset + 4);
+
+ if (chunkId === 'fmt ') {
+ // Format chunk
+ const audioFormat = buffer.readUInt16LE(offset + 8);
+ channels = buffer.readUInt16LE(offset + 10);
+ sampleRate = buffer.readUInt32LE(offset + 12);
+ bitsPerSample = buffer.readUInt16LE(offset + 22);
+
+ if (audioFormat !== 1) {
+ throw new Error('Unsupported WAV format: only PCM is supported');
+ }
+
+ if (bitsPerSample !== 16) {
+ throw new Error('Unsupported bit depth: only 16-bit is supported');
+ }
+ } else if (chunkId === 'data') {
+ // Data chunk
+ dataOffset = offset + 8;
+ dataSize = chunkSize;
+ break;
+ }
+
+ offset += 8 + chunkSize;
+ // Align to even byte boundary
+ if (chunkSize % 2 === 1) {
+ offset++;
+ }
+ }
+
+ if (dataOffset === -1) {
+ throw new Error('Invalid WAV file: no data chunk found');
+ }
+
+ return {
+ sampleRate,
+ channels,
+ bitsPerSample,
+ dataOffset,
+ dataSize,
+ totalSamples: dataSize / (bitsPerSample / 8),
+ samplesPerChannel: dataSize / (bitsPerSample / 8) / channels
+ };
+}
+
+async function testWithWAV(inputFile, outputFile) {
+ console.log("=== WAV File Test ===\n");
+
+ if (!fs.existsSync(inputFile)) {
+ console.error(`Input file not found: ${inputFile}`);
+ return 1;
+ }
+
+ try {
+ const buffer = fs.readFileSync(inputFile);
+
+ // Parse WAV header properly
+ const wavInfo = parseWAVHeader(buffer);
+ console.log(`WAV Format: ${wavInfo.channels} channel(s), ${wavInfo.sampleRate}Hz, ${wavInfo.bitsPerSample}-bit`);
+ console.log(`Total samples: ${wavInfo.totalSamples}, samples per channel: ${wavInfo.samplesPerChannel}`);
+
+ // Validate format requirements
+ if (wavInfo.sampleRate !== 16000) {
+ console.warn(`Warning: Sample rate is ${wavInfo.sampleRate}Hz, expected 16000Hz`);
+ }
+
+ if (wavInfo.channels !== 1) {
+ console.warn(`Warning: ${wavInfo.channels} channels detected, only first channel will be used`);
+ }
+
+ // Extract audio data
+ const audioBuffer = buffer.slice(wavInfo.dataOffset, wavInfo.dataOffset + wavInfo.dataSize);
+ const inputBuf = new Int16Array(audioBuffer.buffer.slice(audioBuffer.byteOffset));
+
+ // Calculate correct sample number (for mono audio)
+ const sampleNum = wavInfo.channels === 1 ?
+ wavInfo.samplesPerChannel :
+ Math.floor(wavInfo.samplesPerChannel); // Use only first channel if stereo
+
+ const totalAudioTime = sampleNum / wavInfo.sampleRate * 1000; // in milliseconds
+ const frameNum = Math.floor(sampleNum / HOP_SIZE);
+
+ console.log(`Audio info: ${audioBuffer.length} bytes, ${sampleNum} samples, ${frameNum} frames, ${totalAudioTime.toFixed(2)}ms`);
+
+ // If stereo, extract only the first channel
+ let processedInput = inputBuf;
+ if (wavInfo.channels > 1) {
+ console.log(`Extracting mono from ${wavInfo.channels} channels...`);
+ processedInput = new Int16Array(Math.floor(inputBuf.length / wavInfo.channels));
+ for (let i = 0; i < processedInput.length; i++) {
+ processedInput[i] = inputBuf[i * wavInfo.channels]; // Take first channel
+ }
+ }
+
+ const outProbs = new Float32Array(frameNum);
+ const outFlags = new Int32Array(frameNum);
+
+ const processingTime = await processAudio(processedInput, frameNum, outProbs, outFlags);
+
+ if (processingTime > 0) {
+ printResults(processingTime, totalAudioTime, outFlags, frameNum);
+ saveResults(outProbs, outFlags, frameNum, outputFile);
+ }
+
+ return 0;
+ } catch (error) {
+ console.error(`Error processing WAV file: ${error.message}`);
+ return 1;
+ }
+}
+
+async function runBenchmark() {
+ console.log("=== Performance Benchmark ===\n");
+
+ if (!createVADInstance()) return;
+
+ const testData = new Int16Array(HOP_SIZE);
+ for (let i = 0; i < HOP_SIZE; i++) {
+ testData[i] = Math.sin(2 * Math.PI * 440 * i / 16000) * 8000;
+ }
+
+ const testCases = [100, 1000, 10000];
+
+ for (const numFrames of testCases) {
+ const audioPtr = vadModule._malloc(HOP_SIZE * 2);
+ const probPtr = vadModule._malloc(4);
+ const flagPtr = vadModule._malloc(4);
+
+ vadModule.HEAP16.set(testData, audioPtr / 2);
+
+ const startTime = getTimestamp();
+
+ for (let i = 0; i < numFrames; i++) {
+ vadModule._ten_vad_process(vadHandle, audioPtr, HOP_SIZE, probPtr, flagPtr);
+ }
+
+ const endTime = getTimestamp();
+ const totalTime = endTime - startTime;
+ const avgTime = totalTime / numFrames;
+
+ // Calculate RTF (Real-time Factor)
+ // Each frame represents 16ms of audio (HOP_SIZE=256 samples at 16kHz)
+ const frameAudioTime = (HOP_SIZE / 16000) * 1000; // 16ms
+ const totalAudioTime = numFrames * frameAudioTime;
+ const rtf = totalTime / totalAudioTime;
+
+ console.log(`${numFrames} frames: ${totalTime}ms total, ${avgTime.toFixed(3)}ms/frame, RTF: ${rtf.toFixed(3)}`);
+
+ vadModule._free(audioPtr);
+ vadModule._free(probPtr);
+ vadModule._free(flagPtr);
+ }
+
+ destroyVADInstance();
+}
+
+// ============================================================================
+// MODULE INITIALIZATION
+// ============================================================================
+
+async function loadModule() {
+ try {
+ console.log("Loading WebAssembly module...");
+
+ if (!fs.existsSync(WASM_JS_FILE)) {
+ throw new Error(`ten_vad.js not found at ${WASM_JS_FILE}`);
+ }
+
+ if (!fs.existsSync(WASM_BINARY_FILE)) {
+ throw new Error(`ten_vad.wasm not found at ${WASM_BINARY_FILE}`);
+ }
+
+ // Read and modify the module file for Node.js compatibility
+ const wasmJsContent = fs.readFileSync(WASM_JS_FILE, 'utf8');
+ const modifiedContent = wasmJsContent
+ .replace(/import\.meta\.url/g, `"${path.resolve(WASM_JS_FILE)}"`)
+ .replace(/export default createVADModule;/, 'module.exports = createVADModule;');
+
+ // Write temporary file
+ const tempPath = './ten_vad_temp.js';
+ fs.writeFileSync(tempPath, modifiedContent);
+
+ // Load WASM binary
+ const wasmBinary = fs.readFileSync(WASM_BINARY_FILE);
+
+ // Load module
+ const createVADModule = require(path.resolve(tempPath));
+ vadModule = await createVADModule({
+ wasmBinary: wasmBinary,
+ locateFile: (filePath) => filePath.endsWith('.wasm') ? WASM_BINARY_FILE : filePath,
+ noInitialRun: false,
+ noExitRuntime: true
+ });
+
+ // Cleanup
+ fs.unlinkSync(tempPath);
+
+ // Add missing helper functions
+ addHelperFunctions();
+
+ console.log(`Module loaded successfully. Version: ${getVADVersion()}\n`);
+ return true;
+
+ } catch (error) {
+ console.error(`Failed to load module: ${error.message}`);
+ return false;
+ }
+}
+
+// ============================================================================
+// MAIN FUNCTION
+// ============================================================================
+
+async function main() {
+ const args = process.argv.slice(2);
+
+ // Initialize module
+ if (!await loadModule()) {
+ process.exit(1);
+ }
+
+ try {
+ if (args.length >= 2) {
+ // Test with WAV file
+ const [inputFile, outputFile] = args;
+ console.log(`Input: ${inputFile}, Output: ${outputFile}\n`);
+ await testWithWAV(inputFile, outputFile);
+ } else {
+ // Test with generated array
+ await testWithArray();
+ }
+ await runBenchmark();
+ return 0;
+ } catch (error) {
+ console.error(`Test failed: ${error.message}`);
+ return 1;
+ }
+}
+
+// ============================================================================
+// EXECUTION
+// ============================================================================
+
+if (require.main === module) {
+ main().then(exitCode => {
+ process.exit(exitCode);
+ }).catch(error => {
+ console.error(`Fatal error: ${error.message}`);
+ process.exit(1);
+ });
+}
+
+module.exports = { main, testWithArray, testWithWAV, runBenchmark };
\ No newline at end of file
diff --git a/examples_onnx/CMakeLists.txt b/examples_onnx/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..62f01950c93535019690be91c147f39eebe90b2d
--- /dev/null
+++ b/examples_onnx/CMakeLists.txt
@@ -0,0 +1,24 @@
+#
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
+#
+cmake_minimum_required(VERSION 3.10)
+get_filename_component(ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../ ABSOLUTE)
+
+project(ten_vad)
+
+set(CMAKE_BUILD_TYPE Release)
+add_compile_options(-Wno-write-strings -Wno-unused-result)
+include_directories(${ROOT}/src)
+include_directories(${ROOT}/include)
+include_directories(${ORT_ROOT}/include)
+file(GLOB LIBRARY_SOURCES "${ROOT}/src/*.cc" "${ROOT}/src/*.c")
+add_library(ten_vad SHARED ${LIBRARY_SOURCES})
+link_directories(${ORT_ROOT}/lib)
+target_link_libraries(ten_vad "${ORT_ROOT}/lib/libonnxruntime.so")
+
+set(EXECUTABLE_SOURCES ${ROOT}/examples/main.c)
+add_executable(ten_vad_demo ${EXECUTABLE_SOURCES})
+target_link_libraries(ten_vad_demo ten_vad)
diff --git a/examples_onnx/build-and-deploy-linux.sh b/examples_onnx/build-and-deploy-linux.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0d2c466062b9fb39a1b0922590dc28ef15e72d50
--- /dev/null
+++ b/examples_onnx/build-and-deploy-linux.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
+#
+set -euo pipefail
+
+if [[ "$#" -lt 2 || "$1" != "--ort-path" ]]; then
+ echo "usage: $0 --ort-path " >&2
+ exit 1
+fi
+
+ORT_ROOT="$2"
+shift 2
+
+if [[ ! -d "$ORT_ROOT" || ! -d "$ORT_ROOT/lib" || ! -d "$ORT_ROOT/include" ]]; then
+ echo "invalid onnxruntime library path: $ORT_ROOT" >&2
+ exit 1
+fi
+
+arch=x64
+build_dir=build-linux/$arch
+rm -rf $build_dir
+mkdir -p $build_dir
+cd $build_dir
+
+# Step 1: Build the demo
+cmake ../../ -DORT_ROOT="$ORT_ROOT"
+cmake --build . --config Release
+
+# Step 2: Run the demo
+ln -s ../../../src/onnx_model/
+./ten_vad_demo ../../../examples/s0724-s0730.wav out.txt
+
+cd ../../
diff --git a/include/ten_vad.h b/include/ten_vad.h
index 3bc01bf13c6e0f1074db417131a38998b66a6274..285244c866c579efa93a32388ccccdfa05ceb001 100644
--- a/include/ten_vad.h
+++ b/include/ten_vad.h
@@ -1,7 +1,8 @@
//
+// Copyright © 2025 Agora
// This file is part of TEN Framework, an open source project.
-// Licensed under the Apache License, Version 2.0.
-// See the LICENSE file for more information.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
//
#ifndef TEN_VAD_H
#define TEN_VAD_H
@@ -83,4 +84,4 @@ extern "C"
}
#endif
-#endif /* TEN_VAD_H */
\ No newline at end of file
+#endif /* TEN_VAD_H */
diff --git a/include/ten_vad.py b/include/ten_vad.py
index a8476f80bbd8e7345249452a3accb33813f33257..4d33a777a5f715868f253d316b55caa53ce259f7 100644
--- a/include/ten_vad.py
+++ b/include/ten_vad.py
@@ -1,7 +1,8 @@
#
-# This file is part of TEN Framework, an open source project.
-# Licensed under the Apache License, Version 2.0.
-# See the LICENSE file for more information.
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
#
from ctypes import c_int, c_int32, c_float, c_size_t, CDLL, c_void_p, POINTER
import numpy as np
diff --git a/lib/Web/ten_vad.d.ts b/lib/Web/ten_vad.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a61945076c62fbbecf38fc3ee2ea684eff8eb3e6
--- /dev/null
+++ b/lib/Web/ten_vad.d.ts
@@ -0,0 +1,111 @@
+/**
+ * This file is part of TEN Framework, an open source project.
+ * Licensed under the Apache License, Version 2.0.
+ * See the LICENSE file for more information.
+ *
+ * TEN VAD (Voice Activity Detection) WebAssembly Module
+ * TypeScript type definitions
+ */
+
+export interface TenVADModule {
+ /**
+ * Create and initialize a VAD instance
+ * @param handlePtr Pointer to store the VAD handle
+ * @param hopSize Number of samples between consecutive analysis frames (e.g., 256)
+ * @param threshold VAD detection threshold [0.0, 1.0]
+ * @returns 0 on success, -1 on error
+ */
+ _ten_vad_create(handlePtr: number, hopSize: number, threshold: number): number;
+
+ /**
+ * Process audio frame for voice activity detection
+ * @param handle Valid VAD handle from ten_vad_create
+ * @param audioDataPtr Pointer to int16 audio samples array
+ * @param audioDataLength Length of audio data (should equal hopSize)
+ * @param outProbabilityPtr Pointer to output probability [0.0, 1.0]
+ * @param outFlagPtr Pointer to output flag (0: no voice, 1: voice detected)
+ * @returns 0 on success, -1 on error
+ */
+ _ten_vad_process(
+ handle: number,
+ audioDataPtr: number,
+ audioDataLength: number,
+ outProbabilityPtr: number,
+ outFlagPtr: number
+ ): number;
+
+ /**
+ * Destroy VAD instance and release resources
+ * @param handlePtr Pointer to the VAD handle
+ * @returns 0 on success, -1 on error
+ */
+ _ten_vad_destroy(handlePtr: number): number;
+
+ /**
+ * Get library version string
+ * @returns Version string pointer
+ */
+ _ten_vad_get_version(): number;
+
+ // WebAssembly Memory Management
+ _malloc(size: number): number;
+ _free(ptr: number): void;
+
+ // Memory access helpers
+ HEAP16: Int16Array;
+ HEAPF32: Float32Array;
+ HEAP32: Int32Array;
+ HEAPU8: Uint8Array;
+
+ // Value access methods
+ getValue(ptr: number, type: 'i8' | 'i16' | 'i32' | 'float' | 'double'): number;
+ setValue(ptr: number, value: number, type: 'i8' | 'i16' | 'i32' | 'float' | 'double'): void;
+
+ // String utilities
+ UTF8ToString(ptr: number): string;
+ lengthBytesUTF8(str: string): number;
+ stringToUTF8(str: string, outPtr: number, maxBytesToWrite: number): void;
+}
+
+/**
+ * High-level TypeScript wrapper for TEN VAD
+ */
+export class TenVAD {
+ private module: TenVADModule;
+ private handle: number | null;
+ private hopSize: number;
+
+ constructor(module: TenVADModule, hopSize: number, threshold: number);
+
+ /**
+ * Process audio samples for voice activity detection
+ * @param audioData Int16Array of audio samples (length must equal hopSize)
+ * @returns Object with probability and voice detection flag
+ */
+ process(audioData: Int16Array): {
+ probability: number;
+ isVoice: boolean;
+ } | null;
+
+ /**
+ * Get library version
+ */
+ getVersion(): string;
+
+ /**
+ * Destroy VAD instance
+ */
+ destroy(): void;
+
+ /**
+ * Check if VAD instance is valid
+ */
+ isValid(): boolean;
+}
+
+/**
+ * Create TEN VAD WebAssembly module
+ */
+declare function createVADModule(): Promise;
+
+export default createVADModule;
\ No newline at end of file
diff --git a/lib/Web/ten_vad.js b/lib/Web/ten_vad.js
new file mode 100644
index 0000000000000000000000000000000000000000..c5615acd83f9ab1b7705b40e63a37dc3f635b4de
--- /dev/null
+++ b/lib/Web/ten_vad.js
@@ -0,0 +1,30 @@
+
+var createVADModule = (() => {
+ var _scriptDir = import.meta.url;
+
+ return (
+function(createVADModule) {
+ createVADModule = createVADModule || {};
+
+
+var a;a||(a=typeof createVADModule !== 'undefined' ? createVADModule : {});var k,l;a.ready=new Promise(function(b,c){k=b;l=c});var p=Object.assign({},a),r="object"==typeof window,u="function"==typeof importScripts,v="",w;
+if(r||u)u?v=self.location.href:"undefined"!=typeof document&&document.currentScript&&(v=document.currentScript.src),_scriptDir&&(v=_scriptDir),0!==v.indexOf("blob:")?v=v.substr(0,v.replace(/[?#].*/,"").lastIndexOf("/")+1):v="",u&&(w=b=>{var c=new XMLHttpRequest;c.open("GET",b,!1);c.responseType="arraybuffer";c.send(null);return new Uint8Array(c.response)});var aa=a.print||console.log.bind(console),x=a.printErr||console.warn.bind(console);Object.assign(a,p);p=null;var y;a.wasmBinary&&(y=a.wasmBinary);
+var noExitRuntime=a.noExitRuntime||!0;"object"!=typeof WebAssembly&&z("no native wasm support detected");var A,B=!1,C="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0,D,E,F;function J(){var b=A.buffer;D=b;a.HEAP8=new Int8Array(b);a.HEAP16=new Int16Array(b);a.HEAP32=new Int32Array(b);a.HEAPU8=E=new Uint8Array(b);a.HEAPU16=new Uint16Array(b);a.HEAPU32=F=new Uint32Array(b);a.HEAPF32=new Float32Array(b);a.HEAPF64=new Float64Array(b)}var K=[],L=[],M=[];
+function ba(){var b=a.preRun.shift();K.unshift(b)}var N=0,O=null,P=null;function z(b){if(a.onAbort)a.onAbort(b);b="Aborted("+b+")";x(b);B=!0;b=new WebAssembly.RuntimeError(b+". Build with -sASSERTIONS for more info.");l(b);throw b;}function Q(){return R.startsWith("data:application/octet-stream;base64,")}var R;if(a.locateFile){if(R="ten_vad.wasm",!Q()){var S=R;R=a.locateFile?a.locateFile(S,v):v+S}}else R=(new URL("ten_vad.wasm",import.meta.url)).href;
+function T(){var b=R;try{if(b==R&&y)return new Uint8Array(y);if(w)return w(b);throw"both async and sync fetching of the wasm failed";}catch(c){z(c)}}function ca(){return y||!r&&!u||"function"!=typeof fetch?Promise.resolve().then(function(){return T()}):fetch(R,{credentials:"same-origin"}).then(function(b){if(!b.ok)throw"failed to load wasm binary file at '"+R+"'";return b.arrayBuffer()}).catch(function(){return T()})}function U(b){for(;0>>=0;if(2147483648=m;m*=2){var h=c*(1+.2/m);h=Math.min(h,b+100663296);var d=Math;h=Math.max(b,h);d=d.min.call(d,2147483648,h+(65536-h%65536)%65536);a:{try{A.grow(d-D.byteLength+65535>>>16);J();var e=1;break a}catch(W){}e=void 0}if(e)return!0}return!1},e:function(){return 52},b:function(){return 70},d:function(b,c,m,h){for(var d=0,e=0;e>2],
+X=F[c+4>>2];c+=8;for(var G=0;G=q);)++t;if(16g?q+=String.fromCharCode(g):(g-=65536,q+=String.fromCharCode(55296|g>>10,56320|g&1023))}}else q+=String.fromCharCode(g)}f=q}(1===
+b?aa:x)(f);H.length=0}else H.push(f)}d+=X}F[h>>2]=d;return 0}};
+(function(){function b(d){a.asm=d.exports;A=a.asm.g;J();L.unshift(a.asm.h);N--;a.monitorRunDependencies&&a.monitorRunDependencies(N);0==N&&(null!==O&&(clearInterval(O),O=null),P&&(d=P,P=null,d()))}function c(d){b(d.instance)}function m(d){return ca().then(function(e){return WebAssembly.instantiate(e,h)}).then(function(e){return e}).then(d,function(e){x("failed to asynchronously prepare wasm: "+e);z(e)})}var h={a:ea};N++;a.monitorRunDependencies&&a.monitorRunDependencies(N);if(a.instantiateWasm)try{return a.instantiateWasm(h,
+b)}catch(d){x("Module.instantiateWasm callback failed with error: "+d),l(d)}(function(){return y||"function"!=typeof WebAssembly.instantiateStreaming||Q()||"function"!=typeof fetch?m(c):fetch(R,{credentials:"same-origin"}).then(function(d){return WebAssembly.instantiateStreaming(d,h).then(c,function(e){x("wasm streaming compile failed: "+e);x("falling back to ArrayBuffer instantiation");return m(c)})})})().catch(l);return{}})();
+a.___wasm_call_ctors=function(){return(a.___wasm_call_ctors=a.asm.h).apply(null,arguments)};a._malloc=function(){return(a._malloc=a.asm.i).apply(null,arguments)};a._free=function(){return(a._free=a.asm.j).apply(null,arguments)};a._ten_vad_create=function(){return(a._ten_vad_create=a.asm.k).apply(null,arguments)};a._ten_vad_process=function(){return(a._ten_vad_process=a.asm.l).apply(null,arguments)};a._ten_vad_destroy=function(){return(a._ten_vad_destroy=a.asm.m).apply(null,arguments)};
+a._ten_vad_get_version=function(){return(a._ten_vad_get_version=a.asm.n).apply(null,arguments)};var V;P=function fa(){V||Z();V||(P=fa)};
+function Z(){function b(){if(!V&&(V=!0,a.calledRun=!0,!B)){U(L);k(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;){var c=a.postRun.shift();M.unshift(c)}U(M)}}if(!(0 /* size_t */
+#include /* int16_t */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**
+ * @typedef ten_vad_handle
+ * @brief Opaque handle for ten_vad instance.
+ */
+ typedef void *ten_vad_handle_t;
+
+ /**
+ * @brief Create and initialize a ten_vad instance.
+ *
+ * @param[out] handle Pointer to receive the vad handle.
+ * @param[in] hop_size The number of samples between the start points of
+ * two consecutive analysis frames. (e.g., 256).
+ * @param[in] threshold VAD detection threshold ranging from [0.0, 1.0]
+ * (default: 0.5).
+ * @return 0 on success, or -1 error occurs.
+ */
+ TENVAD_API int ten_vad_create(ten_vad_handle_t *handle, size_t hop_size,
+ float threshold);
+
+ /**
+ * @brief Process one audio frame for voice activity detection.
+ * Must call ten_vad_init() before calling this, and ten_vad_destroy() when done.
+ *
+ * @param[in] handle Valid VAD handle returned by ten_vad_create().
+ * @param[in] audio_data Pointer to an array of int16_t samples,
+ * buffer length must equal the hop size specified at ten_vad_create.
+ * @param[in] audio_data_length size of audio_data buffer, here should be equal to hop_size.
+ * @param[out] out_probability Pointer to a float (size 1) that receives the
+ * voice activity probability in the range [0.0, 1.0].
+ * @param[out] out_flag Pointer to an int (size 1) that receives the
+ * detection result: 0 = no voice, 1 = voice detected.
+ * @return 0 on success, or -1 error occurs.
+ */
+ TENVAD_API int ten_vad_process(ten_vad_handle_t handle, const int16_t *audio_data, size_t audio_data_length,
+ float *out_probability, int *out_flag);
+
+ /**
+ * @brief Destroy a ten_vad instance and release its resources.
+ *
+ * @param[in,out] handle Pointer to the ten_vad handle; set to NULL on return.
+ * @return 0 on success, or -1 error occurs.
+ */
+ TENVAD_API int ten_vad_destroy(ten_vad_handle_t *handle);
+
+ /**
+ * @brief Get the ten_vad library version string.
+ *
+ * @return The version string (e.g., "1.0.0").
+ */
+ TENVAD_API const char *ten_vad_get_version(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TEN_VAD_H */
\ No newline at end of file
diff --git a/lib/iOS/ten_vad.framework/Info.plist b/lib/iOS/ten_vad.framework/Info.plist
index 5a45618645b25a2d6f89e2ab0a027075f4cf4baf..251cac0808392ecd9ea7cee595e222dfa0a64ea8 100644
Binary files a/lib/iOS/ten_vad.framework/Info.plist and b/lib/iOS/ten_vad.framework/Info.plist differ
diff --git a/lib/iOS/ten_vad.framework/Modules/module.modulemap b/lib/iOS/ten_vad.framework/Modules/module.modulemap
index 8c4ff221636e5c72db7f77eb5e722252e1cf62ef..5943409f935394a52dbb89e525864327a1ce8166 100644
--- a/lib/iOS/ten_vad.framework/Modules/module.modulemap
+++ b/lib/iOS/ten_vad.framework/Modules/module.modulemap
@@ -1,3 +1,5 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:ac22f2ff0291876b7d5069f957825d01abc06a3da84c9f4385154a8e99964096
-size 115
+framework module ten_vad {
+ umbrella header "ten_vad.h"
+ export *
+ module * { export * }
+ }
\ No newline at end of file
diff --git a/lib/macOS/ten_vad.framework/Headers b/lib/macOS/ten_vad.framework/Headers
new file mode 120000
index 0000000000000000000000000000000000000000..a177d2a6b92600696030834c319f5e1434f9ee6a
--- /dev/null
+++ b/lib/macOS/ten_vad.framework/Headers
@@ -0,0 +1 @@
+Versions/Current/Headers
\ No newline at end of file
diff --git a/lib/macOS/ten_vad.framework/Headers/ten_vad.h b/lib/macOS/ten_vad.framework/Headers/ten_vad.h
deleted file mode 100644
index dd212e632da3aab83e6b3f9b755e34a3cc4e59b7..0000000000000000000000000000000000000000
--- a/lib/macOS/ten_vad.framework/Headers/ten_vad.h
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:9bbf0ab2d2ee30d9c170556efb9a7200a53725053cfa7c66a0dff79e7c9351e8
-size 2885
diff --git a/lib/macOS/ten_vad.framework/Resources b/lib/macOS/ten_vad.framework/Resources
new file mode 120000
index 0000000000000000000000000000000000000000..953ee36f3bb709faf58a351e0b33c353e337c0a2
--- /dev/null
+++ b/lib/macOS/ten_vad.framework/Resources
@@ -0,0 +1 @@
+Versions/Current/Resources
\ No newline at end of file
diff --git a/lib/macOS/ten_vad.framework/Resources/Info.plist b/lib/macOS/ten_vad.framework/Resources/Info.plist
deleted file mode 100644
index de5bdf7e879939cd3d531ed9620e7cada57c51c9..0000000000000000000000000000000000000000
--- a/lib/macOS/ten_vad.framework/Resources/Info.plist
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:5aa8df4f544b3143b819d6ffd5c21574c02884bf41cb2b7a8df45c7f10f75c3a
-size 1216
diff --git a/lib/macOS/ten_vad.framework/Versions/A/Headers/ten_vad.h b/lib/macOS/ten_vad.framework/Versions/A/Headers/ten_vad.h
index dd212e632da3aab83e6b3f9b755e34a3cc4e59b7..ff714ee53708bd2cafe31a8dc1d2b10fbc449e50 100644
--- a/lib/macOS/ten_vad.framework/Versions/A/Headers/ten_vad.h
+++ b/lib/macOS/ten_vad.framework/Versions/A/Headers/ten_vad.h
@@ -1,3 +1,90 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:9bbf0ab2d2ee30d9c170556efb9a7200a53725053cfa7c66a0dff79e7c9351e8
-size 2885
+/*
+ * @file ten_vad.h
+ * @brief Ten Voice Activity Detection (ten_vad) C API
+ * Version: 1.0.0
+ *
+ * Provides functions to create, process, and destroy a VAD instance.
+ */
+#ifndef TEN_VAD_H
+#define TEN_VAD_H
+
+#if defined(__APPLE__) || defined(__ANDROID__) || defined(__linux__)
+#define TENVAD_API __attribute__((visibility("default")))
+#elif defined(_WIN32) || defined(__CYGWIN__)
+/**
+ * @def TENVAD_API
+ * @brief Export/import macro for ten_vad shared library symbols.
+ */
+#ifdef TENVAD_EXPORTS
+#define TENVAD_API __declspec(dllexport)
+#else
+#define TENVAD_API __declspec(dllimport)
+#endif
+#else
+#define TENVAD_API
+#endif
+
+#include /* size_t */
+#include /* int16_t */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**
+ * @typedef ten_vad_handle
+ * @brief Opaque handle for ten_vad instance.
+ */
+ typedef void *ten_vad_handle_t;
+
+ /**
+ * @brief Create and initialize a ten_vad instance.
+ *
+ * @param[out] handle Pointer to receive the vad handle.
+ * @param[in] hop_size The number of samples between the start points of
+ * two consecutive analysis frames. (e.g., 256).
+ * @param[in] threshold VAD detection threshold ranging from [0.0, 1.0]
+ * (default: 0.5).
+ * @return 0 on success, or -1 error occurs.
+ */
+ TENVAD_API int ten_vad_create(ten_vad_handle_t *handle, size_t hop_size,
+ float threshold);
+
+ /**
+ * @brief Process one audio frame for voice activity detection.
+ * Must call ten_vad_init() before calling this, and ten_vad_destroy() when done.
+ *
+ * @param[in] handle Valid VAD handle returned by ten_vad_create().
+ * @param[in] audio_data Pointer to an array of int16_t samples,
+ * buffer length must equal the hop size specified at ten_vad_create.
+ * @param[in] audio_data_length size of audio_data buffer, here should be equal to hop_size.
+ * @param[out] out_probability Pointer to a float (size 1) that receives the
+ * voice activity probability in the range [0.0, 1.0].
+ * @param[out] out_flag Pointer to an int (size 1) that receives the
+ * detection result: 0 = no voice, 1 = voice detected.
+ * @return 0 on success, or -1 error occurs.
+ */
+ TENVAD_API int ten_vad_process(ten_vad_handle_t handle, const int16_t *audio_data, size_t audio_data_length,
+ float *out_probability, int *out_flag);
+
+ /**
+ * @brief Destroy a ten_vad instance and release its resources.
+ *
+ * @param[in,out] handle Pointer to the ten_vad handle; set to NULL on return.
+ * @return 0 on success, or -1 error occurs.
+ */
+ TENVAD_API int ten_vad_destroy(ten_vad_handle_t *handle);
+
+ /**
+ * @brief Get the ten_vad library version string.
+ *
+ * @return The version string (e.g., "1.0.0").
+ */
+ TENVAD_API const char *ten_vad_get_version(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TEN_VAD_H */
\ No newline at end of file
diff --git a/lib/macOS/ten_vad.framework/Versions/A/Resources/Info.plist b/lib/macOS/ten_vad.framework/Versions/A/Resources/Info.plist
index de5bdf7e879939cd3d531ed9620e7cada57c51c9..973bb3ed11902966d66c210c039cc04c4d58308c 100644
--- a/lib/macOS/ten_vad.framework/Versions/A/Resources/Info.plist
+++ b/lib/macOS/ten_vad.framework/Versions/A/Resources/Info.plist
@@ -1,3 +1,44 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:5aa8df4f544b3143b819d6ffd5c21574c02884bf41cb2b7a8df45c7f10f75c3a
-size 1216
+
+
+
+
+ BuildMachineOSBuild
+ 23D60
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ ten_vad
+ CFBundleIdentifier
+ com.yourcompany.ten_vad
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ FMWK
+ CFBundleSignature
+ ????
+ CFBundleSupportedPlatforms
+
+ MacOSX
+
+ CSResourcesFileMapped
+
+ DTCompiler
+ com.apple.compilers.llvm.clang.1_0
+ DTPlatformBuild
+
+ DTPlatformName
+ macosx
+ DTPlatformVersion
+ 14.2
+ DTSDKBuild
+ 23C53
+ DTSDKName
+ macosx14.2
+ DTXcode
+ 1520
+ DTXcodeBuild
+ 15C500b
+ LSMinimumSystemVersion
+ 10.10
+
+
diff --git a/lib/macOS/ten_vad.framework/Versions/Current b/lib/macOS/ten_vad.framework/Versions/Current
new file mode 120000
index 0000000000000000000000000000000000000000..8c7e5a667f1b771847fe88c01c3de34413a1b220
--- /dev/null
+++ b/lib/macOS/ten_vad.framework/Versions/Current
@@ -0,0 +1 @@
+A
\ No newline at end of file
diff --git a/lib/macOS/ten_vad.framework/Versions/Current/Headers/ten_vad.h b/lib/macOS/ten_vad.framework/Versions/Current/Headers/ten_vad.h
deleted file mode 100644
index dd212e632da3aab83e6b3f9b755e34a3cc4e59b7..0000000000000000000000000000000000000000
--- a/lib/macOS/ten_vad.framework/Versions/Current/Headers/ten_vad.h
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:9bbf0ab2d2ee30d9c170556efb9a7200a53725053cfa7c66a0dff79e7c9351e8
-size 2885
diff --git a/lib/macOS/ten_vad.framework/Versions/Current/Resources/Info.plist b/lib/macOS/ten_vad.framework/Versions/Current/Resources/Info.plist
deleted file mode 100644
index de5bdf7e879939cd3d531ed9620e7cada57c51c9..0000000000000000000000000000000000000000
--- a/lib/macOS/ten_vad.framework/Versions/Current/Resources/Info.plist
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:5aa8df4f544b3143b819d6ffd5c21574c02884bf41cb2b7a8df45c7f10f75c3a
-size 1216
diff --git a/lib/macOS/ten_vad.framework/Versions/Current/ten_vad b/lib/macOS/ten_vad.framework/Versions/Current/ten_vad
deleted file mode 100755
index 2d3f0081f1933d2a51b8371f71d7ded89637138f..0000000000000000000000000000000000000000
--- a/lib/macOS/ten_vad.framework/Versions/Current/ten_vad
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:81b2de13710670bb94fef315ab50fedc903a21c04c4290c6c2ac28d8b42e715a
-size 744600
diff --git a/lib/macOS/ten_vad.framework/ten_vad b/lib/macOS/ten_vad.framework/ten_vad
deleted file mode 100755
index 2d3f0081f1933d2a51b8371f71d7ded89637138f..0000000000000000000000000000000000000000
--- a/lib/macOS/ten_vad.framework/ten_vad
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:81b2de13710670bb94fef315ab50fedc903a21c04c4290c6c2ac28d8b42e715a
-size 744600
diff --git a/lib/macOS/ten_vad.framework/ten_vad b/lib/macOS/ten_vad.framework/ten_vad
new file mode 120000
index 0000000000000000000000000000000000000000..aa3d68d1960939c037b146fb75ba2c96d1af8380
--- /dev/null
+++ b/lib/macOS/ten_vad.framework/ten_vad
@@ -0,0 +1 @@
+Versions/Current/ten_vad
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 447630397cb94ef2a8db12b1f0decc550b825860..f9237467c0bec41a0a12720f09fff18d4662379f 100644
--- a/setup.py
+++ b/setup.py
@@ -1,3 +1,9 @@
+#
+# Copyright © 2025 Agora
+# This file is part of TEN Framework, an open source project.
+# Licensed under the Apache License, Version 2.0, with certain conditions.
+# Refer to the "LICENSE" file in the root directory for more information.
+#
from setuptools import setup
import os, shutil
from setuptools.command.install import install
diff --git a/src/aed.cc b/src/aed.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b2d2d6bb487ff22191bad45d37a85bc44bead054
--- /dev/null
+++ b/src/aed.cc
@@ -0,0 +1,993 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#include
+#include
+#include
+#include
+#include "aed.h"
+#include "aed_st.h"
+#include "coeff.h"
+#include "pitch_est.h"
+#include "stft.h"
+#include
+
+#define AUP_AED_ALIGN8(o) (((o) + 7) & (~7))
+#define AUP_AED_MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define AUP_AED_MIN(x, y) (((x) > (y)) ? (y) : (x))
+#define AUP_AED_EPS (1e-20f)
+
+/// ///////////////////////////////////////////////////////////////////////
+/// Internal Utils
+/// ///////////////////////////////////////////////////////////////////////
+
+AUP_MODULE_AIVAD::AUP_MODULE_AIVAD(char* onnx_path) {
+ ort_api = OrtGetApiBase()->GetApi(ORT_API_VERSION);
+ OrtStatus* status =
+ ort_api->CreateEnv(ORT_LOGGING_LEVEL_WARNING, "TEN-VAD", &ort_env);
+ if (status) {
+ printf("Failed to create env: %s\n", ort_api->GetErrorMessage(status));
+ ort_api->ReleaseStatus(status);
+ ort_api->ReleaseEnv(ort_env);
+ ort_env = NULL;
+ return;
+ }
+
+ OrtSessionOptions* session_options;
+ ort_api->CreateSessionOptions(&session_options);
+ ort_api->SetIntraOpNumThreads(session_options, 1);
+ status =
+ ort_api->CreateSession(ort_env, onnx_path, session_options, &ort_session);
+ ort_api->ReleaseSessionOptions(session_options);
+ if (status) {
+ printf("Failed to create ort_session: %s\n",
+ ort_api->GetErrorMessage(status));
+ ort_api->ReleaseStatus(status);
+ ort_api->ReleaseEnv(ort_env);
+ ort_env = NULL;
+ return;
+ }
+
+ ort_api->GetAllocatorWithDefaultOptions(&ort_allocator);
+ size_t num_inputs;
+ ort_api->SessionGetInputCount(ort_session, &num_inputs);
+ assert(num_inputs == AUP_AED_MODEL_IO_NUM);
+ for (size_t i = 0; i < num_inputs; i++) {
+ char* input_name;
+ ort_api->SessionGetInputName(ort_session, i, ort_allocator, &input_name);
+ strncpy(input_names_buf[i], input_name, sizeof(input_names_buf[i]));
+ input_names[i] = input_names_buf[i];
+ ort_api->AllocatorFree(ort_allocator, input_name);
+ }
+
+ size_t num_outputs;
+ ort_api->SessionGetOutputCount(ort_session, &num_outputs);
+ assert(num_outputs == AUP_AED_MODEL_IO_NUM);
+ for (size_t i = 0; i < num_outputs; i++) {
+ char* output_name;
+ ort_api->SessionGetOutputName(ort_session, i, ort_allocator, &output_name);
+ strncpy(output_names_buf[i], output_name, sizeof(output_names_buf[i]));
+ output_names[i] = output_names_buf[i];
+ ort_api->AllocatorFree(ort_allocator, output_name);
+ }
+
+ OrtMemoryInfo* memory_info;
+ status = ort_api->CreateCpuMemoryInfo(OrtDeviceAllocator, OrtMemTypeDefault,
+ &memory_info);
+ if (status != NULL) {
+ printf("Failed to create memory info: %s\n",
+ ort_api->GetErrorMessage(status));
+ ort_api->ReleaseStatus(status);
+ ort_api->ReleaseSession(ort_session);
+ ort_api->ReleaseEnv(ort_env);
+ ort_session = NULL;
+ ort_env = NULL;
+ return;
+ }
+ int64_t input_shapes0[] = {1, AUP_AED_CONTEXT_WINDOW_LEN, AUP_AED_FEA_LEN};
+ int64_t input_shapes1234[] = {1, AUP_AED_MODEL_HIDDEN_DIM};
+ for (int i = 0; i < num_inputs; i++) {
+ status = ort_api->CreateTensorWithDataAsOrtValue(
+ memory_info, i == 0 ? input_data_buf_0 : input_data_buf_1234[i - 1],
+ i == 0 ? sizeof(input_data_buf_0) : sizeof(input_data_buf_1234[i - 1]),
+ i == 0 ? input_shapes0 : input_shapes1234,
+ i == 0 ? sizeof(input_shapes0) / sizeof(input_shapes0[0])
+ : sizeof(input_shapes1234) / sizeof(input_shapes1234[0]),
+ ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, &ort_input_tensors[i]);
+ if (status != NULL) {
+ printf("Failed to create input tensor %d: %s\n", i,
+ ort_api->GetErrorMessage(status));
+ ort_api->ReleaseStatus(status);
+ ort_api->ReleaseSession(ort_session);
+ ort_api->ReleaseEnv(ort_env);
+ ort_session = NULL;
+ ort_env = NULL;
+ return;
+ }
+ }
+
+ int64_t output_shapes0[] = {1, 1, 1};
+ int64_t output_shapes1234[] = {1, AUP_AED_MODEL_HIDDEN_DIM};
+ for (int i = 0; i < num_outputs; i++) {
+ status = ort_api->CreateTensorAsOrtValue(
+ ort_allocator, i == 0 ? output_shapes0 : output_shapes1234,
+ i == 0 ? sizeof(output_shapes0) / sizeof(output_shapes0[0])
+ : sizeof(output_shapes1234) / sizeof(output_shapes1234[0]),
+ ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, &ort_output_tensors[i]);
+ if (status != NULL) {
+ printf("Failed to create output tensor %d: %s\n", i,
+ ort_api->GetErrorMessage(status));
+ ort_api->ReleaseStatus(status);
+ ort_api->ReleaseSession(ort_session);
+ ort_api->ReleaseEnv(ort_env);
+ ort_session = NULL;
+ ort_env = NULL;
+ return;
+ }
+ }
+ inited = 1;
+}
+
+AUP_MODULE_AIVAD::~AUP_MODULE_AIVAD() {
+ for (int i = 0; i < AUP_AED_MODEL_IO_NUM; i++) {
+ if (ort_output_tensors[i]) {
+ ort_api->ReleaseValue(ort_output_tensors[i]);
+ }
+ }
+ if (ort_session) {
+ ort_api->ReleaseSession(ort_session);
+ }
+ if (ort_env) {
+ ort_api->ReleaseEnv(ort_env);
+ }
+}
+
+int AUP_MODULE_AIVAD::Process(float* input, float* output) {
+ if (!inited) {
+ printf("not inited!\n");
+ return -1;
+ }
+
+ memcpy(input_data_buf_0, input, sizeof(input_data_buf_0));
+ if (clear_hidden) {
+ memset(input_data_buf_1234, 0, sizeof(input_data_buf_1234));
+ clear_hidden = 0;
+ }
+ OrtStatus* status = ort_api->Run(
+ ort_session, NULL, input_names, ort_input_tensors, AUP_AED_MODEL_IO_NUM,
+ output_names, AUP_AED_MODEL_IO_NUM, ort_output_tensors);
+ float* output_data;
+ ort_api->GetTensorMutableData(ort_output_tensors[0], (void**)&output_data);
+ *output = output_data[0];
+ for (int i = 1; i < AUP_AED_MODEL_IO_NUM; i++) {
+ ort_api->GetTensorMutableData(ort_output_tensors[i], (void**)&output_data);
+ memcpy(input_data_buf_1234[i - 1], output_data,
+ sizeof(input_data_buf_1234[i - 1]));
+ }
+
+ return 0;
+}
+
+int AUP_MODULE_AIVAD::Reset() {
+ if (!inited) {
+ return -1;
+ }
+
+ clear_hidden = 1;
+ return 0;
+}
+
+static int AUP_Aed_checkStatCfg(Aed_StaticCfg* pCfg) {
+ if (pCfg == NULL) {
+ return -1;
+ }
+
+#if AUP_AED_FEA_LEN < AUP_AED_MEL_FILTER_BANK_NUM
+ return -1;
+#endif
+
+ if (pCfg->hopSz < 32) {
+ return -1;
+ }
+
+ if (pCfg->frqInputAvailableFlag == 1) {
+ if (pCfg->fftSz < 128 || pCfg->fftSz < pCfg->hopSz) {
+ return -1;
+ }
+ if (pCfg->anaWindowSz > pCfg->fftSz || pCfg->anaWindowSz < pCfg->hopSz) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int AUP_Aed_publishStaticCfg(Aed_St* stHdl) {
+ const Aed_StaticCfg* pStatCfg;
+
+ if (stHdl == NULL) {
+ return -1;
+ }
+ pStatCfg = (const Aed_StaticCfg*)(&(stHdl->stCfg));
+
+ stHdl->extFftSz = 0;
+ stHdl->extNBins = 0;
+ stHdl->extWinSz = 0;
+ if (pStatCfg->frqInputAvailableFlag == 1) {
+ stHdl->extFftSz = pStatCfg->fftSz;
+ stHdl->extNBins = (stHdl->extFftSz >> 1) + 1;
+ stHdl->extWinSz = pStatCfg->anaWindowSz;
+ }
+ stHdl->extHopSz = pStatCfg->hopSz;
+
+ stHdl->intFftSz = AUP_AED_ASSUMED_FFTSZ;
+ stHdl->intHopSz = AUP_AED_ASSUMED_HOPSZ;
+ stHdl->intWinSz = AUP_AED_ASSUMED_WINDOWSZ;
+ stHdl->intNBins = (stHdl->intFftSz >> 1) + 1;
+ stHdl->intAnalyWindowPtr = AUP_AED_STFTWindow_Hann768;
+
+ if (pStatCfg->frqInputAvailableFlag == 0 ||
+ stHdl->extHopSz != stHdl->intHopSz) {
+ // external STFT analysis framework is not supported at all
+ stHdl->intAnalyFlag =
+ 2; // internally redo analysis based on input time signal
+ } else if (stHdl->extFftSz == stHdl->intFftSz) {
+ // external STFT analysis framework completely match with internal
+ // requirement
+ stHdl->intAnalyFlag = 0; // directly use external spectrum
+ } else { // external spectrum need to be interpolated or extrapolated before
+ // AIVAD
+ stHdl->intAnalyFlag =
+ 1; // use external spectrum with interpolation / exterpolation
+ }
+ stHdl->inputTimeFIFOLen = stHdl->extHopSz + stHdl->intHopSz;
+
+ // for aiaed release2.0.0, pre-emphasis for input time-signal is needed,
+ // therefore, we need redo analysis based on input time signal preprocessed by
+ // pre-emphasis.
+ stHdl->intAnalyFlag =
+ 2; // internally redo analysis based on input time signal
+
+ stHdl->feaSz = (size_t)AUP_AED_FEA_LEN;
+ stHdl->melFbSz = (size_t)AUP_AED_MEL_FILTER_BANK_NUM;
+ stHdl->algDelay = (size_t)AUP_AED_LOOKAHEAD_NFRM;
+ stHdl->algCtxtSz = (size_t)AUP_AED_CONTEXT_WINDOW_LEN;
+ stHdl->frmRmsBufLen = AUP_AED_MAX(1, stHdl->algDelay);
+
+ return 0;
+}
+
+static int AUP_Aed_publishDynamCfg(Aed_St* stHdl) {
+ const Aed_DynamCfg* pDynmCfg;
+ PE_DynamCfg peDynmCfg;
+ if (stHdl == NULL) {
+ return -1;
+ }
+
+ pDynmCfg = (const Aed_DynamCfg*)(&(stHdl->dynamCfg));
+ stHdl->aivadResetFrmNum = pDynmCfg->resetFrameNum;
+ stHdl->voiceDecideThresh = pDynmCfg->extVoiceThr;
+
+ if (stHdl->pitchEstStPtr != NULL) {
+ peDynmCfg.voicedThr = pDynmCfg->pitchEstVoicedThr;
+ AUP_PE_setDynamCfg(stHdl->pitchEstStPtr, &peDynmCfg);
+ }
+
+ return 0;
+}
+
+static int AUP_Aed_resetVariables(Aed_St* stHdl) {
+ if (stHdl == NULL) {
+ return -1;
+ }
+
+ // first clear all the dynamic memory, all the dynamic variables which are
+ // not listed bellow are cleared to 0 by this step
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+
+ float* melFbCoef = stHdl->melFilterBankCoef;
+ size_t* melBinBuff = stHdl->melFilterBinBuff;
+ size_t i, j;
+ size_t nBins = stHdl->intNBins;
+ size_t melFbSz = stHdl->melFbSz;
+
+ stHdl->aedProcFrmCnt = 0;
+ stHdl->inputTimeFIFOIdx = 0;
+ stHdl->aivadResetCnt = 0;
+ stHdl->timeSignalPre = 0.0f;
+ stHdl->aivadScore =
+ -1.0f; // as default value, labeling as aed is not working yet
+ stHdl->aivadScorePre = -1.0f;
+
+ stHdl->pitchFreq = 0.0f;
+
+ // generate mel filter-bank coefficients
+ float low_mel = 2595.0f * log10f(1.0f + 0.0f / 700.0f);
+ float high_mel = 2595.0f * log10f(1.0f + 8000.0f / 700.0f);
+ float mel_points = 0.0f;
+ float hz_points = 0.0f;
+ size_t idx = 0;
+
+ for (i = 0; i < melFbSz + 2; i++) {
+ mel_points = i * (high_mel - low_mel) / ((float)melFbSz + 1.0f) + low_mel;
+ hz_points = 700.0f * (powf(10.0f, mel_points / 2595.0f) - 1.0f);
+ melBinBuff[i] =
+ (size_t)((stHdl->intFftSz + 1.0f) * hz_points / (float)AUP_AED_FS);
+ if (i > 0 && melBinBuff[i] == melBinBuff[i - 1]) {
+ return -1;
+ }
+ }
+
+ for (j = 0; j < melFbSz; j++) {
+ for (i = melBinBuff[j]; i < melBinBuff[j + 1]; i++) {
+ idx = j * nBins + i;
+ melFbCoef[idx] = (float)(i - melBinBuff[j]) /
+ (float)(melBinBuff[j + 1] - melBinBuff[j]);
+ }
+ for (i = melBinBuff[j + 1]; i < melBinBuff[j + 2]; i++) {
+ idx = j * nBins + i;
+ melFbCoef[idx] = (float)(melBinBuff[j + 2] - i) /
+ (float)(melBinBuff[j + 2] - melBinBuff[j + 1]);
+ }
+ }
+
+ if (stHdl->pitchEstStPtr != NULL) {
+ if (AUP_PE_init(stHdl->pitchEstStPtr) < 0) {
+ return -1;
+ }
+ }
+
+ if (stHdl->aivadInf != NULL) {
+ stHdl->aivadInf->Reset();
+ }
+
+ if (stHdl->timeInAnalysis != NULL) {
+ if (AUP_Analyzer_init(stHdl->timeInAnalysis) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int AUP_Aed_addOneCnter(int cnter) {
+ cnter++;
+ if (cnter >= 1000000000) {
+ cnter = 0; // reset every half year
+ }
+ return (cnter);
+}
+
+static void AUP_Aed_binPowerConvert(const float* src, float* tgt, int srcNBins,
+ int tgtNBins) {
+ float rate;
+ int srcIdx, tgtIdx;
+ if (srcNBins == tgtNBins) {
+ memcpy(tgt, src, sizeof(float) * tgtNBins);
+ return;
+ }
+
+ memset(tgt, 0, sizeof(float) * tgtNBins);
+
+ rate = (float)(srcNBins - 1) / (float)(tgtNBins - 1);
+ for (tgtIdx = 0; tgtIdx < tgtNBins; tgtIdx++) {
+ srcIdx = (int)(tgtIdx * rate);
+ srcIdx = AUP_AED_MIN(srcNBins - 1, AUP_AED_MAX(srcIdx, 0));
+ tgt[tgtIdx] = src[srcIdx];
+ }
+
+ return;
+}
+
+static void AUP_Aed_CalcBinPow(int nBins, const float* cmplxSpctr,
+ float* binPow) {
+ int idx, realIdx, imagIdx;
+
+ // bin-0
+ binPow[0] = cmplxSpctr[0] * cmplxSpctr[0];
+
+ // bin-(NBins-1)
+ binPow[nBins - 1] = cmplxSpctr[1] * cmplxSpctr[1];
+
+ for (idx = 1; idx < (nBins - 1); idx++) {
+ realIdx = idx << 1;
+ imagIdx = realIdx + 1;
+
+ binPow[idx] = cmplxSpctr[realIdx] * cmplxSpctr[realIdx] +
+ cmplxSpctr[imagIdx] * cmplxSpctr[imagIdx];
+ }
+ return;
+}
+
+static int AUP_Aed_pitch_proc(void* pitchModule, const float* timeSignal,
+ size_t timeLen, const float* binPow, size_t nBins,
+ PE_OutputData* pOut) {
+ PE_InputData peInData;
+
+ peInData.timeSignal = timeSignal;
+ peInData.hopSz = (int)timeLen;
+ peInData.inBinPow = binPow;
+ peInData.nBins = (int)nBins;
+ pOut->pitchFreq = 0;
+ pOut->voiced = -1;
+ return AUP_PE_proc(pitchModule, &peInData, pOut);
+}
+
+static int AUP_Aed_aivad_proc(Aed_St* stHdl, const float* inBinPow,
+ float* aivadScore) {
+ if (stHdl == NULL || inBinPow == NULL || aivadScore == NULL) {
+ return -1;
+ }
+
+ size_t i, j;
+ size_t nBins = stHdl->intNBins;
+ size_t melFbSz = stHdl->melFbSz;
+ size_t srcOffset;
+ size_t srcLen;
+
+ float* aivadInputFeatStack = stHdl->aivadInputFeatStack;
+ float* melFbCoef = stHdl->melFilterBankCoef;
+ const float* aivadFeatMean = AUP_AED_FEATURE_MEANS;
+ const float* aivadFeatStd = AUP_AED_FEATURE_STDS;
+ float* curMelFbCoefPtr = NULL;
+ float* curInputFeatPtr = NULL;
+ float perBandValue = 0.0f;
+ float powerNormal = 32768.0f * 32768.0f;
+
+ // update aivad feature buff.
+ srcOffset = stHdl->feaSz;
+ srcLen = (stHdl->algCtxtSz - 1) * stHdl->feaSz;
+ memmove(aivadInputFeatStack, aivadInputFeatStack + srcOffset,
+ sizeof(float) * srcLen);
+ curInputFeatPtr = aivadInputFeatStack + srcLen;
+
+ // cal. mel-filter-bank feature
+ for (i = 0; i < melFbSz; i++) {
+ perBandValue = 0.0f;
+ curMelFbCoefPtr = melFbCoef + i * nBins;
+ for (j = 0; j < nBins; j++) {
+ perBandValue += (inBinPow[j] * curMelFbCoefPtr[j]);
+ }
+ perBandValue = perBandValue / powerNormal;
+ perBandValue = logf(perBandValue + AUP_AED_EPS);
+ curInputFeatPtr[i] =
+ (perBandValue - aivadFeatMean[i]) / (aivadFeatStd[i] + AUP_AED_EPS);
+ }
+
+ // extra feat.
+ for (i = melFbSz; i < stHdl->feaSz; i++) {
+ curInputFeatPtr[i] =
+ (stHdl->pitchFreq - aivadFeatMean[i]) / (aivadFeatStd[i] + AUP_AED_EPS);
+ }
+
+ // exe. aivad
+ // exe. aivad
+ float aivadOutput;
+ if (stHdl->aivadInf != NULL &&
+ stHdl->aivadInf->Process(stHdl->aivadInputFeatStack, &aivadOutput) != 0) {
+ return -1;
+ }
+
+ (*aivadScore) = aivadOutput;
+
+ stHdl->aivadResetCnt += 1;
+ if (stHdl->aivadResetCnt >= stHdl->aivadResetFrmNum) {
+ if (stHdl->aivadInf != NULL && stHdl->aivadInf->Reset() != 0) {
+ }
+ stHdl->aivadResetCnt = 0;
+ }
+
+ return 0;
+}
+
+static int AUP_Aed_dynamMemPrepare(Aed_St* stHdl, void* memPtrExt,
+ size_t memSize) {
+ if (stHdl == NULL) {
+ return -1;
+ }
+ size_t pitchInNBins = stHdl->intNBins;
+ size_t totalMemSize = 0;
+ size_t inputTimeFIFOMemSize = 0;
+ size_t inputEmphTimeFIFOMemSize = 0;
+ size_t aivadInputCmplxSptrmMemSize = 0;
+ size_t aivadInputBinPowMemSize = 0;
+ size_t frameRmsBuffMemSize = 0;
+ size_t aivadInputFeatStackMemSize = 0;
+ size_t aimdInputFeatStackMemSize = 0;
+ size_t melFilterBankCoefMemSize = 0;
+ size_t melFilterBinBuffMemSize = 0;
+ size_t inputFloatBuffMemSize = 0;
+
+ // size_t vadScoreOutputBuffDelaySample = 384; // buff. delay for output
+ char* memPtr = NULL;
+
+ // size_t nBinsBufferMemSize = AUP_AED_ALIGN8(sizeof(float) * nBins);
+ // size_t spctrmMemSize = AUP_AED_ALIGN8(sizeof(float) * (nBins - 1) * 2);
+
+ inputTimeFIFOMemSize =
+ AUP_AED_ALIGN8(sizeof(float) * stHdl->inputTimeFIFOLen);
+ totalMemSize += inputTimeFIFOMemSize;
+
+ inputEmphTimeFIFOMemSize =
+ AUP_AED_ALIGN8(sizeof(float) * stHdl->inputTimeFIFOLen);
+ totalMemSize += inputEmphTimeFIFOMemSize;
+
+ aivadInputCmplxSptrmMemSize = AUP_AED_ALIGN8(sizeof(float) * stHdl->intFftSz);
+ totalMemSize += aivadInputCmplxSptrmMemSize;
+
+ aivadInputBinPowMemSize = AUP_AED_ALIGN8(sizeof(float) * stHdl->intNBins);
+ totalMemSize += aivadInputBinPowMemSize;
+
+ aivadInputFeatStackMemSize =
+ AUP_AED_ALIGN8(sizeof(float) * stHdl->algCtxtSz * stHdl->feaSz);
+ totalMemSize += aivadInputFeatStackMemSize;
+
+ aimdInputFeatStackMemSize =
+ AUP_AED_ALIGN8(sizeof(float) * stHdl->algCtxtSz * stHdl->feaSz);
+ totalMemSize += aimdInputFeatStackMemSize;
+
+ melFilterBankCoefMemSize =
+ AUP_AED_ALIGN8(sizeof(float) * pitchInNBins * stHdl->feaSz);
+ totalMemSize += melFilterBankCoefMemSize;
+
+ melFilterBinBuffMemSize = AUP_AED_ALIGN8(sizeof(size_t) * (stHdl->feaSz + 2));
+ totalMemSize += melFilterBinBuffMemSize;
+
+ frameRmsBuffMemSize = AUP_AED_ALIGN8(stHdl->frmRmsBufLen * sizeof(float));
+ totalMemSize += frameRmsBuffMemSize;
+
+ inputFloatBuffMemSize = AUP_AED_ALIGN8(stHdl->extHopSz * sizeof(float));
+ totalMemSize += inputFloatBuffMemSize;
+
+ if (memPtrExt == NULL) {
+ return ((int)totalMemSize);
+ }
+
+ if (totalMemSize > memSize) {
+ return -1;
+ }
+
+ memPtr = (char*)memPtrExt;
+
+ stHdl->inputTimeFIFO = (float*)memPtr;
+ memPtr += inputTimeFIFOMemSize;
+
+ stHdl->inputEmphTimeFIFO = (float*)memPtr;
+ memPtr += inputEmphTimeFIFOMemSize;
+
+ stHdl->aivadInputCmplxSptrm = (float*)memPtr;
+ memPtr += aivadInputCmplxSptrmMemSize;
+
+ stHdl->aivadInputBinPow = (float*)memPtr;
+ memPtr += aivadInputBinPowMemSize;
+
+ stHdl->aivadInputFeatStack = (float*)memPtr;
+ memPtr += aivadInputFeatStackMemSize;
+
+ stHdl->melFilterBankCoef = (float*)memPtr;
+ memPtr += melFilterBankCoefMemSize;
+
+ stHdl->melFilterBinBuff = (size_t*)memPtr;
+ memPtr += melFilterBinBuffMemSize;
+
+ stHdl->frameRmsBuff = (float*)memPtr;
+ memPtr += frameRmsBuffMemSize;
+
+ stHdl->inputFloatBuff = (float*)memPtr;
+ memPtr += inputFloatBuffMemSize;
+
+ if (((size_t)(memPtr - (char*)memPtrExt)) > totalMemSize) {
+ return -1;
+ }
+
+ return ((int)totalMemSize);
+}
+
+static int AUP_Aed_runOneFrm(Aed_St* stHdl, const float* tSignal, int hopSz,
+ const float* binPowPtr, int nBins) {
+ PE_OutputData peOutData = {0, 0};
+ float aivadScore = -1.0f;
+ float mediaFilterout = 0;
+ int mediaIdx = (int)(AUP_AED_OUTPUT_SMOOTH_FILTER_LEN) / 2;
+ int i;
+
+ if (AUP_Aed_pitch_proc(stHdl->pitchEstStPtr, tSignal, hopSz, binPowPtr, nBins,
+ &peOutData) < 0) {
+ return -1;
+ }
+ stHdl->pitchFreq = peOutData.pitchFreq;
+ if (AUP_Aed_aivad_proc(stHdl, binPowPtr, &aivadScore) < 0) {
+ return -1;
+ }
+ stHdl->aivadScore = aivadScore;
+
+ return 0;
+}
+
+/// ///////////////////////////////////////////////////////////////////////
+/// Public API
+/// ///////////////////////////////////////////////////////////////////////
+
+int AUP_Aed_create(void** stPtr) {
+ if (stPtr == NULL) {
+ return -1;
+ }
+ Aed_St* tmpPtr = (Aed_St*)malloc(sizeof(Aed_St));
+ if (tmpPtr == NULL) {
+ return -1;
+ }
+ memset(tmpPtr, 0, sizeof(Aed_St));
+
+ if (AUP_PE_create(&(tmpPtr->pitchEstStPtr)) < 0) {
+ return -1;
+ }
+ if (AUP_Analyzer_create(&(tmpPtr->timeInAnalysis)) < 0) {
+ return -1;
+ }
+
+ tmpPtr->stCfg.enableFlag = 1; // as default, module enabled
+ tmpPtr->stCfg.fftSz = 1024;
+ tmpPtr->stCfg.hopSz = 256;
+ tmpPtr->stCfg.anaWindowSz = 768;
+ tmpPtr->stCfg.frqInputAvailableFlag = 0;
+
+ tmpPtr->dynamCfg.extVoiceThr = 0.5f;
+ tmpPtr->dynamCfg.extMusicThr = 0.5f;
+ tmpPtr->dynamCfg.extEnergyThr = 10.0f;
+ tmpPtr->dynamCfg.resetFrameNum = 1875; // TODO
+ tmpPtr->dynamCfg.pitchEstVoicedThr = AUP_AED_PITCH_EST_DEFAULT_VOICEDTHR;
+
+ (*stPtr) = (void*)tmpPtr;
+
+ return 0;
+}
+
+int AUP_Aed_destroy(void** stPtr) {
+ if (stPtr == NULL || (*stPtr) == NULL) {
+ return -1;
+ }
+ Aed_St* stHdl = (Aed_St*)(*stPtr);
+
+ if (stHdl->aivadInf != NULL) {
+ delete stHdl->aivadInf;
+ }
+ stHdl->aivadInf = NULL;
+
+ if (AUP_PE_destroy(&(stHdl->pitchEstStPtr)) < 0) {
+ return -1;
+ }
+ if (AUP_Analyzer_destroy(&(stHdl->timeInAnalysis)) < 0) {
+ return -1;
+ }
+
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ }
+ stHdl->dynamMemPtr = NULL;
+
+ if (stHdl != NULL) {
+ free(stHdl);
+ }
+ (*stPtr) = NULL;
+
+ return 0;
+}
+
+int AUP_Aed_memAllocate(void* stPtr, const Aed_StaticCfg* pCfg) {
+ Aed_St* stHdl = (Aed_St*)(stPtr);
+ Aed_StaticCfg aedStatCfg;
+ PE_StaticCfg pitchStatCfg;
+ Analyzer_StaticCfg analyzerStatCfg;
+ int totalMemSize = 0;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+
+ // 1th: check static cfg.
+ memcpy(&aedStatCfg, pCfg, sizeof(Aed_StaticCfg));
+ if (AUP_Aed_checkStatCfg(&aedStatCfg) < 0) {
+ return -1;
+ }
+
+ memcpy(&(stHdl->stCfg), &aedStatCfg, sizeof(Aed_StaticCfg));
+
+ // 2th: publish static configuration to internal statical configuration
+ // registers
+ if (AUP_Aed_publishStaticCfg(stHdl) < 0) {
+ return -1;
+ }
+
+ // 3th: create aivad instance
+ if (stHdl->aivadInf == NULL) {
+ stHdl->aivadInf = new AUP_MODULE_AIVAD("onnx_model/ten-vad.onnx");
+ if (stHdl->aivadInf == NULL) {
+ return -1;
+ }
+ }
+ stHdl->aivadInf->Reset();
+
+ // 4th: memAllocate operation for Pitch-Estimator ............
+ if (AUP_PE_getStaticCfg(stHdl->pitchEstStPtr, &pitchStatCfg) < 0) {
+ return -1;
+ }
+ pitchStatCfg.fftSz = stHdl->intFftSz;
+ pitchStatCfg.anaWindowSz = stHdl->intWinSz;
+ pitchStatCfg.hopSz = stHdl->intHopSz;
+ pitchStatCfg.useLPCPreFiltering = AUP_AED_PITCH_EST_USE_LPC;
+ pitchStatCfg.procFs = AUP_AED_PITCH_EST_PROCFS;
+ if (AUP_PE_memAllocate(stHdl->pitchEstStPtr, &pitchStatCfg) < 0) {
+ return -1;
+ }
+
+ // creation and initialization with time-analysis module ......
+ AUP_Analyzer_getStaticCfg(stHdl->timeInAnalysis, &analyzerStatCfg);
+ analyzerStatCfg.win_len = (int)stHdl->intWinSz;
+ analyzerStatCfg.hop_size = (int)stHdl->intHopSz;
+ analyzerStatCfg.fft_size = (int)stHdl->intFftSz;
+ analyzerStatCfg.ana_win_coeff = stHdl->intAnalyWindowPtr;
+ if (AUP_Analyzer_memAllocate(stHdl->timeInAnalysis, &analyzerStatCfg) < 0) {
+ return -1;
+ }
+
+ // 5th: check memory requirement ..............................
+ totalMemSize = AUP_Aed_dynamMemPrepare(stHdl, NULL, 0);
+ if (totalMemSize < 0) {
+ return -1;
+ }
+
+ // 6th: allocate dynamic memory
+ if (totalMemSize > (int)stHdl->dynamMemSize) {
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ stHdl->dynamMemPtr = NULL;
+ stHdl->dynamMemSize = 0;
+ }
+ stHdl->dynamMemPtr = malloc(totalMemSize);
+ if (stHdl->dynamMemPtr == NULL) {
+ return -1;
+ }
+ stHdl->dynamMemSize = totalMemSize;
+ }
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+
+ // 7th: setup the pointers/variable
+ if (AUP_Aed_dynamMemPrepare(stHdl, stHdl->dynamMemPtr, stHdl->dynamMemSize) <
+ 0) {
+ return -1;
+ }
+
+ // 8th: publish internal dynamic config registers
+ if (AUP_Aed_publishDynamCfg(stHdl) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_Aed_init(void* stPtr) {
+ Aed_St* stHdl = (Aed_St*)(stPtr);
+ if (stPtr == NULL) {
+ return -1;
+ }
+
+ // publish internal dynamic config registers
+ if (AUP_Aed_publishDynamCfg(stHdl) < 0) {
+ return -1;
+ }
+
+ // clear/reset run-time variables
+ if (AUP_Aed_resetVariables(stHdl) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_Aed_setDynamCfg(void* stPtr, const Aed_DynamCfg* pCfg) {
+ Aed_St* stHdl = (Aed_St*)(stPtr);
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+
+ memcpy(&(stHdl->dynamCfg), pCfg, sizeof(Aed_DynamCfg));
+
+ // publish internal dynamic configuration registers
+ if (AUP_Aed_publishDynamCfg(stHdl) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_Aed_getStaticCfg(const void* stPtr, Aed_StaticCfg* pCfg) {
+ const Aed_St* stHdl = (const Aed_St*)(stPtr);
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+
+ memcpy(pCfg, &(stHdl->stCfg), sizeof(Aed_StaticCfg));
+
+ return 0;
+}
+
+int AUP_Aed_getDynamCfg(const void* stPtr, Aed_DynamCfg* pCfg) {
+ const Aed_St* stHdl = (const Aed_St*)(stPtr);
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+
+ memcpy(pCfg, &(stHdl->dynamCfg), sizeof(Aed_DynamCfg));
+
+ return 0;
+}
+
+int AUP_Aed_getAlgDelay(const void* stPtr, int* delayInFrms) {
+ const Aed_St* stHdl = (const Aed_St*)(stPtr);
+
+ if (stPtr == NULL || delayInFrms == NULL) {
+ return -1;
+ }
+
+ (*delayInFrms) = (int)stHdl->algDelay;
+
+ return 0;
+}
+
+int AUP_Aed_proc(void* stPtr, const Aed_InputData* pIn, Aed_OutputData* pOut) {
+ Analyzer_InputData analyzerInput;
+ Analyzer_OutputData analyzerOutput;
+ Aed_St* stHdl = (Aed_St*)(stPtr);
+
+ const float* binPowPtr = NULL;
+ float frameRms = 0.0f;
+ float frameEnergy = 0.0f;
+ float powerNormal = 32768.0f * 32768.0f;
+ int idx;
+
+ if (stPtr == NULL) {
+ return -1;
+ }
+ if (stHdl->stCfg.enableFlag == 0) { // this module is disabled
+ return 0;
+ }
+ if (pIn == NULL || pIn->timeSignal == NULL || pOut == NULL) {
+ return -1;
+ }
+
+ if (stHdl->intAnalyFlag != 2) { // the external spectra is going to be used
+ if (pIn->binPower == NULL) {
+ return -1;
+ }
+ if (pIn->nBins != (int)((stHdl->stCfg.fftSz >> 1) + 1) ||
+ pIn->hopSz != (int)(stHdl->stCfg.hopSz)) {
+ return -1;
+ }
+ }
+
+ // cal. input frame energy ....
+ for (idx = 0; idx < pIn->hopSz; idx++) {
+ frameRms += (pIn->timeSignal[idx] * pIn->timeSignal[idx]);
+ }
+ frameEnergy = frameRms;
+ frameRms = sqrtf(frameRms / (float)pIn->hopSz);
+ memmove(stHdl->frameRmsBuff, stHdl->frameRmsBuff + 1,
+ sizeof(float) * (stHdl->frmRmsBufLen - 1));
+ stHdl->frameRmsBuff[stHdl->frmRmsBufLen - 1] = frameRms;
+
+ // input signal conversion .........
+ if ((stHdl->inputTimeFIFOIdx + pIn->hopSz) > (int)stHdl->inputTimeFIFOLen) {
+ return -1;
+ }
+
+ // update pre-emphasis time signal FIFO
+ float* timeSigEphaPtr = stHdl->inputEmphTimeFIFO + stHdl->inputTimeFIFOIdx;
+ for (idx = 0; idx < pIn->hopSz; idx++) {
+ timeSigEphaPtr[idx] = pIn->timeSignal[idx] - 0.97f * stHdl->timeSignalPre;
+ stHdl->timeSignalPre = pIn->timeSignal[idx];
+ }
+
+ memcpy(stHdl->inputTimeFIFO + stHdl->inputTimeFIFOIdx, pIn->timeSignal,
+ sizeof(float) * (pIn->hopSz));
+ stHdl->inputTimeFIFOIdx += pIn->hopSz;
+
+ if (stHdl->intAnalyFlag == 0) { // directly use external spectra
+ if (stHdl->inputTimeFIFOIdx != (int)(stHdl->intHopSz) ||
+ (int)(stHdl->intNBins) != pIn->nBins) {
+ return -1;
+ }
+
+ // one-time processing ...
+ stHdl->aedProcFrmCnt = AUP_Aed_addOneCnter(stHdl->aedProcFrmCnt);
+ binPowPtr = pIn->binPower;
+
+ // update: stHdl->pitchFreq, stHdl->aivadScore
+ if (AUP_Aed_runOneFrm(stHdl, stHdl->inputTimeFIFO, (int)stHdl->intHopSz,
+ binPowPtr, (int)stHdl->intNBins) < 0) {
+ return -1;
+ }
+
+ // update the inputTimeFIFO
+ stHdl->inputTimeFIFOIdx = 0;
+ } else if (stHdl->intAnalyFlag ==
+ 1) { // do interpolation or extrapolation with external spectra
+ if (stHdl->inputTimeFIFOIdx != (int)(stHdl->intHopSz) ||
+ (int)(stHdl->extNBins) != pIn->nBins) {
+ return -1;
+ }
+
+ // one-time processing ....
+ stHdl->aedProcFrmCnt = AUP_Aed_addOneCnter(stHdl->aedProcFrmCnt);
+ AUP_Aed_binPowerConvert(pIn->binPower, stHdl->aivadInputBinPow,
+ (int)stHdl->extNBins, (int)stHdl->intNBins);
+ binPowPtr = stHdl->aivadInputBinPow;
+
+ // update: stHdl->pitchFreq, stHdl->aivadScore
+ if (AUP_Aed_runOneFrm(stHdl, stHdl->inputTimeFIFO, (int)stHdl->intHopSz,
+ binPowPtr, (int)stHdl->intNBins) < 0) {
+ return -1;
+ }
+
+ // update the inputTimeFIFO
+ stHdl->inputTimeFIFOIdx = 0;
+ } else { // we need to do STFT on the input time-signal
+ if (stHdl->timeInAnalysis == NULL) {
+ return -1;
+ }
+
+ // loop processing .....
+ while (stHdl->inputTimeFIFOIdx >= (int)stHdl->intHopSz) {
+ stHdl->aedProcFrmCnt = AUP_Aed_addOneCnter(stHdl->aedProcFrmCnt);
+
+ analyzerInput.input = stHdl->inputEmphTimeFIFO;
+ analyzerInput.iLength = (int)stHdl->intHopSz;
+ analyzerOutput.output = stHdl->aivadInputCmplxSptrm;
+ analyzerOutput.oLength = (int)stHdl->intFftSz;
+ if (AUP_Analyzer_proc(stHdl->timeInAnalysis, &analyzerInput,
+ &analyzerOutput) < 0) {
+ return -1;
+ }
+
+ AUP_Aed_CalcBinPow((int)stHdl->intNBins, stHdl->aivadInputCmplxSptrm,
+ stHdl->aivadInputBinPow);
+ binPowPtr = stHdl->aivadInputBinPow;
+
+ // update: stHdl->pitchFreq, stHdl->aivadScore
+ if (AUP_Aed_runOneFrm(stHdl, stHdl->inputTimeFIFO, (int)stHdl->intHopSz,
+ binPowPtr, (int)stHdl->intNBins) < 0) {
+ return -1;
+ }
+
+ // update the inputTimeFIFO & inputEmphTimeFIFO.....
+ if (stHdl->inputTimeFIFOIdx > (int)stHdl->intHopSz) {
+ memcpy(stHdl->inputTimeFIFO, stHdl->inputTimeFIFO + stHdl->intHopSz,
+ sizeof(float) * (stHdl->inputTimeFIFOIdx - stHdl->intHopSz));
+ memcpy(stHdl->inputEmphTimeFIFO,
+ stHdl->inputEmphTimeFIFO + stHdl->intHopSz,
+ sizeof(float) * (stHdl->inputTimeFIFOIdx - stHdl->intHopSz));
+ }
+ stHdl->inputTimeFIFOIdx -= (int)stHdl->intHopSz;
+ }
+ }
+
+ // write to output res.
+ pOut->frameEnergy = frameEnergy / powerNormal;
+ pOut->frameRms = stHdl->frameRmsBuff[0];
+ pOut->pitchFreq = stHdl->pitchFreq;
+ pOut->voiceProb = stHdl->aivadScore;
+ if (pOut->voiceProb < 0.0f) {
+ pOut->vadRes = -1;
+ } else if (pOut->voiceProb <= stHdl->voiceDecideThresh) {
+ pOut->vadRes = 0;
+ } else {
+ pOut->vadRes = 1;
+ }
+
+ return 0;
+}
diff --git a/src/aed.h b/src/aed.h
new file mode 100644
index 0000000000000000000000000000000000000000..9eeef27f095194b91f7bb1abe0245249fd337868
--- /dev/null
+++ b/src/aed.h
@@ -0,0 +1,226 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __AED_H__
+#define __AED_H__
+
+#include
+#include
+
+#define AUP_AED_MAX_FFT_SZ (1024) // the max. fft-size supported by VAD module
+#define AUP_AED_MAX_NBINS ((AUP_AED_MAX_FFT_SZ >> 1) + 1)
+
+#define AUP_AED_FS (16000) // assumed input freq.
+
+// Configuration Parameters, which impacts dynamic memory occupation, can only
+// be set during allocation
+typedef struct Aed_StaticCfg_ {
+ int enableFlag; // flag to enable or disable this module
+ // 0: disable, o.w.: enable
+ size_t fftSz; // fft-size, only support: 128, 256, 512, 1024
+ size_t hopSz; // fft-Hop Size, will be used to check
+ size_t anaWindowSz; // fft-window Size, will be used to calc rms
+ int frqInputAvailableFlag; // whether Aed_InputData will contain external
+ // freq. power-sepctra
+} Aed_StaticCfg;
+
+// Configuraiton parameters which can be modified/set every frames
+typedef struct Aed_DynamCfg_ {
+ float extVoiceThr; // threshold for ai based voice decision [0,1]
+ float extMusicThr; // threshold for ai based music decision [0,1]
+ float extEnergyThr; // threshold for energy based vad decision [0, ---]
+ size_t resetFrameNum; // frame number for aivad reset [1875, 75000]
+ float pitchEstVoicedThr; // threshold for pitch-estimator to output estimated
+ // pitch
+} Aed_DynamCfg;
+
+// Spectrum are assumed to be generated with time-domain samples in [-32768,
+// 32767] with or without pre-emphasis operation
+typedef struct Aed_InputData_ {
+ const float* binPower; // [NBins], power spectrum of 16KHz samples
+ int nBins;
+ const float*
+ timeSignal; // [hopSz] // this frame's input signal, in [-32768, 32767]
+ int hopSz; // should be equal to StaticCfg->hopSz
+} Aed_InputData;
+
+// return data from statistical ns module
+typedef struct Aed_OutputData_ {
+ float frameEnergy; // frame energy for input normalized data
+ float frameRms; // rms for input int16 data
+ int energyVadRes; // vad res 0/1 with extEnergyThreshold based on input frame
+ // energy
+ float voiceProb; // vad score [0,1]
+ int vadRes; // vad res 0/1 with extVoiceThr based on ai method, t + 16ms res
+ // correspond to the t input
+ float pitchFreq; // estimated pitch freq.
+} Aed_OutputData;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * AUP_Aed_Create(...)
+ *
+ * This function creats a state handler from nothing, which is NOT ready for
+ * processing
+ *
+ * Input:
+ *
+ * Output:
+ * - stPtr : buffer to store the returned state handler
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Aed_create(void** stPtr);
+
+/****************************************************************************
+ * AUP_Aed_Destroy(...)
+ *
+ * destroy VAD instance, and releasing all the dynamically allocated memory
+ * this interface will also release ainsFactory, which was
+ * created externally and passed to VAD module through memAllocate interface
+ *
+ * Input:
+ * - stPtr : buffer of State Handler, after this method, this
+ * handler won't be usable anymore
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Aed_destroy(void** stPtr);
+
+/****************************************************************************
+ * AUP_Aed_MemAllocate(...)
+ *
+ * This function sets Static Config params and does memory allocation
+ * operation, will lose the dynamCfg values
+ *
+ * Input:
+ * - stPtr : State Handler which was returned by _create
+ * - pCfg : static configuration parameters
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Aed_memAllocate(void* stPtr, const Aed_StaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Aed_init(...)
+ *
+ * This function resets (initialize) the VAD module and gets it prepared for
+ * processing
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Aed_init(void* stPtr);
+
+/****************************************************************************
+ * AUP_Aed_setDynamCfg(...)
+ *
+ * This function set dynamic (per-frame variable) configuration
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ * - pCfg : configuration content
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Aed_setDynamCfg(void* stPtr, const Aed_DynamCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Aed_getStaticCfg(...)
+ *
+ * This function get static configuration status from VAD module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - pCfg : configuration content
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Aed_getStaticCfg(const void* stPtr, Aed_StaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Aed_getDynamCfg(...)
+ *
+ * This function get dynamic (per-frame variable) configuration status from
+ * VAD module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - pCfg : configuration content
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Aed_getDynamCfg(const void* stPtr, Aed_DynamCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Aed_getAlgDelay(...)
+ *
+ * This function get algorithm delay from VAD module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - delayInFrms : algorithm delay in terms of frames
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Aed_getAlgDelay(const void* stPtr, int* delayInFrms);
+
+/****************************************************************************
+ * AUP_Aed_proc(...)
+ *
+ * process a single frame
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate and reset
+ * - pCtrl : per-frame variable control parameters
+ * - pIn : input data stream
+ *
+ * Output:
+ * - pOut : output data (mask, highband time-domain gain etc.)
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Aed_proc(void* stPtr, const Aed_InputData* pIn, Aed_OutputData* pOut);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/aed_st.h b/src/aed_st.h
new file mode 100644
index 0000000000000000000000000000000000000000..65764b9f51d00c219d4957ca2e5ed3617d80213a
--- /dev/null
+++ b/src/aed_st.h
@@ -0,0 +1,132 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __AED_ST_H__
+#define __AED_ST_H__
+
+#include
+#include
+
+#include "aed.h"
+
+#define AUP_AED_FS (16000)
+#define AUP_AED_MAX_IN_BUFF_SIZE (256)
+#define AUP_AED_POWER_SPCTR_NORMALIZER (9.3132e-10f) // = 1/(32768^2)
+#define AUP_AED_OUTPUT_SMOOTH_FILTER_LEN (10) // 160ms
+
+#define AUP_AED_MEL_FILTER_BANK_NUM (40)
+#define AUP_AED_LOOKAHEAD_NFRM (1)
+#define AUP_AED_CONTEXT_WINDOW_LEN (3) // context window length of AIVAD
+#define AUP_AED_FEA_LEN \
+ (AUP_AED_MEL_FILTER_BANK_NUM + 1) // feature length of AIVAD
+
+#define AUP_AED_PITCH_EST_USE_LPC (1)
+#define AUP_AED_PITCH_EST_PROCFS (4000)
+#if AUP_AED_PITCH_EST_PROCFS == 2000
+#define AUP_AED_PITCH_EST_DEFAULT_VOICEDTHR (0.45f)
+#else
+#define AUP_AED_PITCH_EST_DEFAULT_VOICEDTHR (0.4f)
+#endif
+
+#define AUP_AED_MODEL_IO_NUM (5)
+#define AUP_AED_MODEL_NAME_LENGTH (32)
+#define AUP_AED_MODEL_HIDDEN_DIM (64)
+
+class AUP_MODULE_AIVAD {
+ public:
+ AUP_MODULE_AIVAD(char* onnx_path);
+ ~AUP_MODULE_AIVAD();
+ int Process(float* input, float* output);
+ int Reset();
+
+ private:
+ const OrtApi* ort_api = NULL;
+ OrtAllocator* ort_allocator = NULL;
+ OrtEnv* ort_env = NULL;
+ OrtSession* ort_session = NULL;
+ int inited = 0;
+ int clear_hidden = 0;
+
+ char input_names_buf[AUP_AED_MODEL_IO_NUM][AUP_AED_MODEL_NAME_LENGTH] = {0};
+ const char* input_names[AUP_AED_MODEL_IO_NUM] = {NULL};
+ float input_data_buf_0[AUP_AED_CONTEXT_WINDOW_LEN * AUP_AED_FEA_LEN] = {0};
+ float input_data_buf_1234[AUP_AED_MODEL_IO_NUM - 1]
+ [AUP_AED_MODEL_HIDDEN_DIM] = {0};
+ OrtValue* ort_input_tensors[AUP_AED_MODEL_IO_NUM] = {NULL};
+
+ char output_names_buf[AUP_AED_MODEL_IO_NUM][AUP_AED_MODEL_NAME_LENGTH] = {0};
+ const char* output_names[AUP_AED_MODEL_IO_NUM] = {NULL};
+ OrtValue* ort_output_tensors[AUP_AED_MODEL_IO_NUM] = {NULL};
+};
+
+typedef struct Aed_St_ {
+ void* dynamMemPtr; // memory pointer holding the dynamic memory
+ size_t dynamMemSize; // size of the buffer *dynamMemPtr
+
+ Aed_StaticCfg stCfg;
+
+ Aed_DynamCfg dynamCfg;
+
+ // Internal Static Config Registers, which are generated from stCfg
+ size_t extFftSz; // externally decided FFT-Sz
+ size_t extHopSz; // externally decided FFT-Hop-Sz
+ size_t extNBins; // (FFTSz/2) + 1
+ size_t extWinSz; // externally decided FFT-Window-Sz
+
+ size_t intFftSz; // internal FFT Sz
+ size_t intHopSz; // internal Hop Sz
+ size_t intWinSz; // internal Window Sz
+ size_t intNBins; // internal NBins
+ const float* intAnalyWindowPtr; // internal analysis pointer
+ int intAnalyFlag; // whether to do internal analysis
+ // 0: directly use external spectrum
+ // 1: use external spectrum with interpolation / exterpolation
+ // 2: need to redo analysis based on input time-domain signal
+ size_t inputTimeFIFOLen; // length of input FIFO buffer
+ // if = 0: no need for input time-domain FIFO Queue
+
+ // Internal static config registers for pitch-est module
+ size_t feaSz;
+ size_t melFbSz;
+ size_t algDelay; // in terms of processing frames
+ size_t algCtxtSz;
+ size_t frmRmsBufLen; // frameRmsBuff: buffer-length of frameRmsBuff (FIFO)
+
+ // Internal dynamic Config Registers, which are generated from dynamCfg
+ size_t aivadResetFrmNum;
+ float voiceDecideThresh;
+
+ // SubModules
+ AUP_MODULE_AIVAD* aivadInf;
+
+ void* pitchEstStPtr; // pitch-estimation module handler
+ void* timeInAnalysis;
+ // state handler of STFT analysis module
+
+ // Variables
+ int aedProcFrmCnt; // counter of consecutive AI-VAD processed frames
+ int inputTimeFIFOIdx;
+ float* inputTimeFIFO; // [inputTimeFIFOLen]
+ // input fifo buffer of time-signal to adjust between extHopSz and intHopSz
+ float* inputEmphTimeFIFO; // [inputTimeFIFOLen]
+ float* aivadInputCmplxSptrm; // [intFftSz]
+ float* aivadInputBinPow; // [intNBins] // AIVAD input power spectrum
+ size_t aivadResetCnt;
+ float timeSignalPre;
+ float aivadScore;
+ float aivadScorePre;
+
+ float pitchFreq; // input audio pitch in Hz
+ float* frameRmsBuff; // [frmRmsBufLen], FIFO, to delay frmRms result so that
+ // it aligns with AIVAD result
+ float* aivadInputFeatStack; // [...] = [AUP_AED_CONTEXT_WINDOW_LEN *
+ // AUP_AED_FEA_LEN]
+ float* melFilterBankCoef; // [melFbSz][nBins]
+ size_t* melFilterBinBuff; // [melFbSz + 2]
+ float* inputFloatBuff; // [hopSz]
+} Aed_St;
+
+#endif
diff --git a/src/biquad.cc b/src/biquad.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cdd42e49b99cde1beec4437f86aca0d964bb1a53
--- /dev/null
+++ b/src/biquad.cc
@@ -0,0 +1,354 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#include "biquad.h"
+
+#include
+#include
+#include
+#include
+
+#include "biquad_st.h"
+
+#define AUP_BIQUAD_NUM_DUMP_FILES (20)
+#define AUP_BIQUAD_DUMP_FILENAMES (200)
+
+// ==========================================================================================
+// internal tools
+// ==========================================================================================
+
+static int AUP_Biquad_checkStatCfg(const Biquad_StaticCfg* pCfg) {
+ int secIdx;
+ if (pCfg == NULL) {
+ return -1;
+ }
+
+ if (pCfg->maxNSample == 0 ||
+ pCfg->maxNSample > AGORA_UAP_BIQUAD_MAX_INPUT_LEN) {
+ return -1;
+ }
+ if (pCfg->nsect > AGORA_UAP_BIQUAD_MAX_SECTION) {
+ return -1;
+ }
+
+ // if external filter coefficients are required, we need to check the
+ // external filter coeff pointers' validness
+ if (pCfg->nsect > 0) {
+ for (secIdx = 0; secIdx < pCfg->nsect; secIdx++) {
+ if (pCfg->B[secIdx] == NULL || pCfg->A[secIdx] == NULL) {
+ return -1;
+ }
+ }
+ if (pCfg->G == NULL) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int AUP_Biquad_publishStaticCfg(Biquad_St* stHdl) {
+ const Biquad_StaticCfg* pStatCfg;
+ int idx;
+
+ if (stHdl == NULL) {
+ return -1;
+ }
+ pStatCfg = (const Biquad_StaticCfg*)(&(stHdl->stCfg));
+
+ stHdl->maxNSample = (int)pStatCfg->maxNSample;
+
+ // first, give default (all-pass-filter) values to filter coeffs
+ for (idx = 0; idx < AGORA_UAP_BIQUAD_MAX_SECTION; idx++) {
+ stHdl->BCoeff[idx][0] = 1.0f;
+ stHdl->BCoeff[idx][1] = 0;
+ stHdl->BCoeff[idx][2] = 0;
+ stHdl->ACoeff[idx][0] = 1.0f;
+ stHdl->ACoeff[idx][1] = 0;
+ stHdl->ACoeff[idx][2] = 0;
+ stHdl->GCoeff[idx] = 1.0f;
+ }
+
+ if (pStatCfg->nsect <= 0) {
+ stHdl->nsect = _BIQUAD_DC_REMOVAL_NSECT;
+ for (idx = 0; idx < stHdl->nsect; idx++) {
+ stHdl->BCoeff[idx][0] = _BIQUAD_DC_REMOVAL_B[idx][0];
+ stHdl->BCoeff[idx][1] = _BIQUAD_DC_REMOVAL_B[idx][1];
+ stHdl->BCoeff[idx][2] = _BIQUAD_DC_REMOVAL_B[idx][2];
+ stHdl->ACoeff[idx][0] = _BIQUAD_DC_REMOVAL_A[idx][0];
+ stHdl->ACoeff[idx][1] = _BIQUAD_DC_REMOVAL_A[idx][1];
+ stHdl->ACoeff[idx][2] = _BIQUAD_DC_REMOVAL_A[idx][2];
+ stHdl->GCoeff[idx] = _BIQUAD_DC_REMOVAL_G[idx];
+ }
+ } else {
+ stHdl->nsect = pStatCfg->nsect;
+ for (idx = 0; idx < stHdl->nsect; idx++) {
+ stHdl->BCoeff[idx][0] = pStatCfg->B[idx][0];
+ stHdl->BCoeff[idx][1] = pStatCfg->B[idx][1];
+ stHdl->BCoeff[idx][2] = pStatCfg->B[idx][2];
+
+ stHdl->ACoeff[idx][0] = pStatCfg->A[idx][0];
+ stHdl->ACoeff[idx][1] = pStatCfg->A[idx][1];
+ stHdl->ACoeff[idx][2] = pStatCfg->A[idx][2];
+
+ stHdl->GCoeff[idx] = pStatCfg->G[idx];
+ }
+ }
+
+ return 0;
+}
+
+static int AUP_Biquad_resetVariables(Biquad_St* stHdl) {
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+ memset(stHdl->sectW, 0, sizeof(stHdl->sectW));
+
+ return 0;
+}
+
+// ==========================================================================================
+// public APIS
+// ==========================================================================================
+
+int AUP_Biquad_create(void** stPtr) {
+ Biquad_St* tmpPtr;
+
+ if (stPtr == NULL) {
+ return -1;
+ }
+ *stPtr = (void*)malloc(sizeof(Biquad_St));
+ if (*stPtr == NULL) {
+ return -1;
+ }
+ memset(*stPtr, 0, sizeof(Biquad_St));
+
+ tmpPtr = (Biquad_St*)(*stPtr);
+
+ tmpPtr->dynamMemPtr = NULL;
+ tmpPtr->dynamMemSize = 0;
+
+ tmpPtr->stCfg.maxNSample = 768;
+ tmpPtr->stCfg.nsect = 0;
+ for (int idx = 0; idx < AGORA_UAP_BIQUAD_MAX_SECTION; idx++) {
+ tmpPtr->stCfg.A[idx] = NULL;
+ tmpPtr->stCfg.B[idx] = NULL;
+ }
+ tmpPtr->stCfg.G = NULL;
+
+ return 0;
+}
+
+int AUP_Biquad_destroy(void** stPtr) {
+ Biquad_St* stHdl;
+
+ if (stPtr == NULL) {
+ return 0;
+ }
+
+ stHdl = (Biquad_St*)(*stPtr);
+ if (stHdl == NULL) {
+ return 0;
+ }
+
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ }
+ stHdl->dynamMemPtr = NULL;
+
+ free(stHdl);
+
+ (*stPtr) = NULL;
+
+ return 0;
+}
+
+int AUP_Biquad_memAllocate(void* stPtr, const Biquad_StaticCfg* pCfg) {
+ Biquad_St* stHdl = NULL;
+ char* memPtr = NULL;
+ int maxNSample, nsect, idx;
+
+ int inputTempBufMemSize = 0;
+ int sectOutputBufMemSize_EACH = 0;
+ int totalMemSize = 0;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+ stHdl = (Biquad_St*)(stPtr);
+
+ if (AUP_Biquad_checkStatCfg(pCfg) < 0) {
+ return -1;
+ }
+ memcpy(&(stHdl->stCfg), pCfg, sizeof(Biquad_StaticCfg));
+
+ if (AUP_Biquad_publishStaticCfg(stHdl) < 0) {
+ return -1;
+ }
+ maxNSample = stHdl->maxNSample;
+ nsect = stHdl->nsect;
+
+ // check memory requirement
+ inputTempBufMemSize = AGORA_UAP_BIQUAD_ALIGN8(sizeof(float) * maxNSample);
+ totalMemSize += inputTempBufMemSize;
+
+ sectOutputBufMemSize_EACH =
+ AGORA_UAP_BIQUAD_ALIGN8(sizeof(float) * maxNSample);
+ totalMemSize += sectOutputBufMemSize_EACH * nsect;
+
+ // allocate dynamic memory
+ if ((size_t)totalMemSize > stHdl->dynamMemSize) {
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ stHdl->dynamMemSize = 0;
+ }
+ stHdl->dynamMemPtr = malloc(totalMemSize);
+ if (stHdl->dynamMemPtr == NULL) {
+ return -1;
+ }
+ stHdl->dynamMemSize = totalMemSize;
+ }
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+
+ // setup the pointers/variable
+ memPtr = (char*)(stHdl->dynamMemPtr);
+
+ stHdl->inputTempBuf = (float*)memPtr;
+ memPtr += inputTempBufMemSize;
+
+ for (idx = 0; idx < nsect; idx++) {
+ stHdl->sectOutputBuf[idx] = (float*)memPtr;
+ memPtr += sectOutputBufMemSize_EACH;
+ }
+ for (; idx < AGORA_UAP_BIQUAD_MAX_SECTION; idx++) {
+ stHdl->sectOutputBuf[idx] = NULL;
+ }
+
+ if (((int)(memPtr - (char*)(stHdl->dynamMemPtr))) > totalMemSize) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_Biquad_init(void* stPtr) {
+ Biquad_St* stHdl;
+
+ if (stPtr == NULL) {
+ return -1;
+ }
+ stHdl = (Biquad_St*)(stPtr);
+
+ if (AUP_Biquad_resetVariables(stHdl) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_Biquad_getStaticCfg(const void* stPtr, Biquad_StaticCfg* pCfg) {
+ const Biquad_St* stHdl;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+ stHdl = (const Biquad_St*)(stPtr);
+
+ memcpy(pCfg, &(stHdl->stCfg), sizeof(Biquad_StaticCfg));
+
+ return 0;
+}
+
+int AUP_Biquad_getAlgDelay(const void* stPtr, int* delayInSamples) {
+ const Biquad_St* stHdl;
+
+ if (stPtr == NULL || delayInSamples == NULL) {
+ return -1;
+ }
+ stHdl = (const Biquad_St*)(stPtr);
+
+ *delayInSamples = stHdl->nsect;
+
+ return 0;
+}
+
+int AUP_Biquad_proc(void* stPtr, const Biquad_InputData* pIn,
+ Biquad_OutputData* pOut) {
+ Biquad_St* stHdl = NULL;
+ int isFloatIO = 0;
+ int inputNSamples, nSect;
+ int sectIdx, smplIdx;
+ float tmp1;
+ const short* pShortTemp;
+ float* src;
+ float* tgt;
+
+ if (stPtr == NULL || pIn == NULL || pOut == NULL) { // pCtrl == NULL
+ return -1;
+ }
+ if (pIn->samplesPtr == NULL || pOut->outputBuff == NULL) {
+ return -1;
+ }
+
+ stHdl = (Biquad_St*)(stPtr);
+
+ if (((int)pIn->nsamples) > stHdl->maxNSample) {
+ return -1;
+ }
+
+ isFloatIO = 0;
+ if (pIn->sampleType != 0) {
+ isFloatIO = 1;
+ }
+
+ inputNSamples = (int)pIn->nsamples;
+ nSect = stHdl->nsect;
+
+ // special handle for input
+ if (isFloatIO == 0) {
+ pShortTemp = (const short*)pIn->samplesPtr;
+ for (smplIdx = 0; smplIdx < inputNSamples; smplIdx++) {
+ stHdl->inputTempBuf[smplIdx] = (float)pShortTemp[smplIdx];
+ }
+ } else {
+ memcpy(stHdl->inputTempBuf, (const float*)pIn->samplesPtr,
+ sizeof(float) * inputNSamples);
+ }
+
+ for (sectIdx = 0; sectIdx < nSect; sectIdx++) {
+ if (sectIdx == 0) {
+ src = stHdl->inputTempBuf;
+ } else {
+ src = stHdl->sectOutputBuf[sectIdx - 1];
+ }
+ tgt = stHdl->sectOutputBuf[sectIdx];
+
+ for (smplIdx = 0; smplIdx < inputNSamples; smplIdx++) {
+ tmp1 = src[smplIdx] -
+ stHdl->ACoeff[sectIdx][1] * stHdl->sectW[sectIdx][0] -
+ stHdl->ACoeff[sectIdx][2] * stHdl->sectW[sectIdx][1];
+
+ tgt[smplIdx] = stHdl->GCoeff[sectIdx] *
+ (stHdl->BCoeff[sectIdx][0] * tmp1 +
+ stHdl->BCoeff[sectIdx][1] * stHdl->sectW[sectIdx][0] +
+ stHdl->BCoeff[sectIdx][2] * stHdl->sectW[sectIdx][1]);
+
+ stHdl->sectW[sectIdx][1] = stHdl->sectW[sectIdx][0];
+ stHdl->sectW[sectIdx][0] = tmp1;
+ }
+ }
+
+ // prepare output buffer
+ if (isFloatIO == 0) {
+ for (smplIdx = 0; smplIdx < inputNSamples; smplIdx++) {
+ ((short*)pOut->outputBuff)[smplIdx] =
+ (short)_BIQUAD_FLOAT2SHORT(stHdl->sectOutputBuf[nSect - 1][smplIdx]);
+ }
+ } else {
+ memcpy(pOut->outputBuff, stHdl->sectOutputBuf[nSect - 1],
+ sizeof(float) * inputNSamples);
+ }
+
+ return 0;
+}
diff --git a/src/biquad.h b/src/biquad.h
new file mode 100644
index 0000000000000000000000000000000000000000..98c888f35f35d11017c48ff48ca6bf4cce55c5cf
--- /dev/null
+++ b/src/biquad.h
@@ -0,0 +1,190 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __BIQUAD_H__
+#define __BIQUAD_H__
+
+#include
+
+#define AGORA_UAP_BIQUAD_MAX_SECTION (20)
+// the max. number of sections supported by this Biquad module
+
+#define AGORA_UAP_BIQUAD_MAX_INPUT_LEN (3840)
+// max. number of samples each time can be fed in
+
+#define AGORA_UAP_BIQUAD_ALIGN8(o) (((o) + 7) & (~7))
+#define _BIQUAD_FLOAT2SHORT(x) \
+ ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : (short)floor(.5 + (x))))
+
+#define _BIQUAD_DC_REMOVAL_NSECT (2)
+const float _BIQUAD_DC_REMOVAL_B[_BIQUAD_DC_REMOVAL_NSECT][3] = {
+ {1.0f, -2.0f, 1.0f}, {1.0f, -1.0f, 0.0f}};
+const float _BIQUAD_DC_REMOVAL_A[_BIQUAD_DC_REMOVAL_NSECT][3] = {
+ {1.0f, -1.93944294f, 0.94281253f}, {1.0f, -0.94276431f, 0.0f}};
+// const float _BIQUAD_DC_REMOVAL_G[_BIQUAD_DC_REMOVAL_NSECT] = {0.97056387f,
+// 0.97138215f};
+const float _BIQUAD_DC_REMOVAL_G[_BIQUAD_DC_REMOVAL_NSECT] = {0.97056387f,
+ 0.8655014957f};
+
+// Configuration Parameters, which impacts dynamic memory occupation, can only
+// be set during allocation
+typedef struct Biquad_StaticCfg_ {
+ size_t maxNSample; // max. number of samples each time can be fed in
+ // (0, AGORA_UAP_BIQUAD_MAX_INPUT_LEN]
+
+ int nsect; // the number of sections to be processed by this Biquad module
+ // (-inf, AGORA_UAP_BIQUAD_MAX_SECTION]
+ // if <= 0, use internal default filter coefficients
+
+ const float* B[AGORA_UAP_BIQUAD_MAX_SECTION];
+ const float* A[AGORA_UAP_BIQUAD_MAX_SECTION];
+ // always assume A[...][0] = 1.0f
+ const float* G;
+} Biquad_StaticCfg;
+
+typedef struct Biquad_InputData_ {
+ const void*
+ samplesPtr; // externally provided buffer containing input time samples
+ // either in short or float type
+ short sampleType; // = 0: samplesPtr = short*; o.w. samplesPtr = float*
+ size_t nsamples; // number of samples fed in this time
+} Biquad_InputData;
+
+typedef struct Biquad_OutputData_ {
+ void* outputBuff; // externally provided output buffer,
+ // assumed to be of enough size nsamples *
+ // sizeof(short)/sizeof(short) output data type is the same
+ // as input
+} Biquad_OutputData;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * AUP_Biquad_create(...)
+ *
+ * This function creats a state handler from nothing, which is NOT ready for
+ * processing
+ *
+ * Input:
+ *
+ * Output:
+ * - stPtr : buffer to store the returned state handler
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Biquad_create(void** stPtr);
+
+/****************************************************************************
+ * AUP_Biquad_destroy(...)
+ *
+ * destroy biquad instance, and releasing all the dynamically allocated memory
+ *
+ * Input:
+ * - stPtr : buffer of State Handler, after this method, this
+ * handler won't be usable anymore
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Biquad_destroy(void** stPtr);
+
+/****************************************************************************
+ * AUP_Biquad_memAllocate(...)
+ *
+ * This function sets Static Config params and does memory allocation
+ * operation
+ *
+ * Input:
+ * - stPtr : State Handler which was returned by _create
+ * - pCfg : static configuration parameters
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Biquad_memAllocate(void* stPtr, const Biquad_StaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Biquad_init(...)
+ *
+ * This function resets (initialize) the biquad module and gets it prepared for
+ * processing
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Biquad_init(void* stPtr);
+
+/****************************************************************************
+ * AUP_Biquad_getStaticCfg(...)
+ *
+ * This function get static configuration status from Biquad module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - pCfg : configuration content
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Biquad_getStaticCfg(const void* stPtr, Biquad_StaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Biquad_getAlgDelay(...)
+ *
+ * This function get algorithm delay from biquad module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - delayInSamples : algorithm delay in terms of samples
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Biquad_getAlgDelay(const void* stPtr, int* delayInSamples);
+
+/****************************************************************************
+ * AUP_Biquad_proc(...)
+ *
+ * process a single frame
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ * - pCtrl : per-frame variable control parameters
+ * - pIn : input data stream
+ *
+ * Output:
+ * - pOut : output data (mask, highband time-domain gain etc.)
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Biquad_proc(void* stPtr, const Biquad_InputData* pIn,
+ Biquad_OutputData* pOut);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // __BIQUAD_H__
diff --git a/src/biquad_st.h b/src/biquad_st.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9ee02fd837c1301e0b3ab6bfd09565effc1d3ce
--- /dev/null
+++ b/src/biquad_st.h
@@ -0,0 +1,37 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __BIQUAD_ST_H__
+#define __BIQUAD_ST_H__
+
+#include
+#include "biquad.h"
+
+typedef struct Biquad_St_ {
+ void* dynamMemPtr; // memory pointer holding the dynamic memory
+ size_t dynamMemSize; // size of the buffer *dynamMemPtr
+
+ // Static Configuration
+ Biquad_StaticCfg stCfg;
+
+ // ---------------------------------------------------------------
+ // Internal Static Config Registers, which are generated from stCfg
+ int maxNSample;
+ int nsect;
+ float BCoeff[AGORA_UAP_BIQUAD_MAX_SECTION][3];
+ float ACoeff[AGORA_UAP_BIQUAD_MAX_SECTION][3];
+ float GCoeff[AGORA_UAP_BIQUAD_MAX_SECTION]; // gain for each section
+
+ // Variables
+ float* inputTempBuf; // [maxNSample]
+ float sectW[AGORA_UAP_BIQUAD_MAX_SECTION][2];
+ // each section's register
+ float* sectOutputBuf
+ [AGORA_UAP_BIQUAD_MAX_SECTION]; //[AGORA_UAP_BIQUAD_MAX_SECTION][maxNSample]
+ // each section's output buffer
+} Biquad_St;
+
+#endif // __BIQUAD_ST_H__
diff --git a/src/coeff.h b/src/coeff.h
new file mode 100755
index 0000000000000000000000000000000000000000..ed102b13b5e93b5a4de2d52330f8bb2d9fbf2a05
--- /dev/null
+++ b/src/coeff.h
@@ -0,0 +1,246 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __COEFF_H__
+#define __COEFF_H__
+
+#include "aed_st.h"
+
+#define AUP_AED_MEAN_STD_NBINS AUP_AED_FEA_LEN
+
+#define AUP_AED_ASSUMED_HOPSZ (256)
+#define AUP_AED_ASSUMED_WINDOWSZ (768)
+#define AUP_AED_ASSUMED_FFTSZ (1024)
+
+// means of inpu-mel-filterbank
+const float AUP_AED_FEATURE_MEANS[AUP_AED_MEAN_STD_NBINS] = {
+ -8.198236465454e+00f, -6.265716552734e+00f, -5.483818531036e+00f,
+ -4.758691310883e+00f, -4.417088985443e+00f, -4.142892837524e+00f,
+ -3.912850379944e+00f, -3.845927953720e+00f, -3.657090425491e+00f,
+ -3.723418712616e+00f, -3.876134157181e+00f, -3.843890905380e+00f,
+ -3.690405130386e+00f, -3.756065845490e+00f, -3.698696136475e+00f,
+ -3.650463104248e+00f, -3.700468778610e+00f, -3.567321300507e+00f,
+ -3.498900175095e+00f, -3.477807044983e+00f, -3.458816051483e+00f,
+ -3.444923877716e+00f, -3.401328563690e+00f, -3.306261301041e+00f,
+ -3.278556823730e+00f, -3.233250856400e+00f, -3.198616027832e+00f,
+ -3.204526424408e+00f, -3.208798646927e+00f, -3.257838010788e+00f,
+ -3.381376743317e+00f, -3.534021377563e+00f, -3.640867948532e+00f,
+ -3.726858854294e+00f, -3.773730993271e+00f, -3.804667234421e+00f,
+ -3.832901000977e+00f, -3.871120452881e+00f, -3.990592956543e+00f,
+ -4.480289459229e+00f, 9.235690307617e+01f};
+
+// stds of input-mel-filterbank
+const float AUP_AED_FEATURE_STDS[AUP_AED_MEAN_STD_NBINS] = {
+ 5.166063785553e+00f, 4.977209568024e+00f, 4.698895931244e+00f,
+ 4.630621433258e+00f, 4.634347915649e+00f, 4.641156196594e+00f,
+ 4.640676498413e+00f, 4.666367053986e+00f, 4.650534629822e+00f,
+ 4.640020847321e+00f, 4.637400150299e+00f, 4.620099067688e+00f,
+ 4.596316337585e+00f, 4.562654972076e+00f, 4.554360389709e+00f,
+ 4.566910743713e+00f, 4.562489986420e+00f, 4.562412738800e+00f,
+ 4.585299491882e+00f, 4.600179672241e+00f, 4.592845916748e+00f,
+ 4.585922718048e+00f, 4.583496570587e+00f, 4.626092910767e+00f,
+ 4.626957893372e+00f, 4.626289367676e+00f, 4.637005805969e+00f,
+ 4.683015823364e+00f, 4.726813793182e+00f, 4.734289646149e+00f,
+ 4.753227233887e+00f, 4.849722862244e+00f, 4.869434833527e+00f,
+ 4.884482860565e+00f, 4.921327114105e+00f, 4.959212303162e+00f,
+ 4.996619224548e+00f, 5.044823646545e+00f, 5.072216987610e+00f,
+ 5.096439361572e+00f, 1.152136917114e+02f};
+
+const float AUP_AED_STFTWindow_Hann768[768] = {
+ 0.0000000e+00f, 1.6733041e-05f, 6.6931045e-05f, 1.5059065e-04f,
+ 2.6770626e-04f, 4.1827004e-04f, 6.0227190e-04f, 8.1969953e-04f,
+ 1.0705384e-03f, 1.3547717e-03f, 1.6723803e-03f, 2.0233432e-03f,
+ 2.4076367e-03f, 2.8252351e-03f, 3.2761105e-03f, 3.7602327e-03f,
+ 4.2775693e-03f, 4.8280857e-03f, 5.4117450e-03f, 6.0285082e-03f,
+ 6.6783340e-03f, 7.3611788e-03f, 8.0769970e-03f, 8.8257407e-03f,
+ 9.6073598e-03f, 1.0421802e-02f, 1.1269013e-02f, 1.2148935e-02f,
+ 1.3061510e-02f, 1.4006678e-02f, 1.4984373e-02f, 1.5994532e-02f,
+ 1.7037087e-02f, 1.8111967e-02f, 1.9219101e-02f, 2.0358415e-02f,
+ 2.1529832e-02f, 2.2733274e-02f, 2.3968661e-02f, 2.5235910e-02f,
+ 2.6534935e-02f, 2.7865651e-02f, 2.9227967e-02f, 3.0621794e-02f,
+ 3.2047037e-02f, 3.3503601e-02f, 3.4991388e-02f, 3.6510300e-02f,
+ 3.8060234e-02f, 3.9641086e-02f, 4.1252752e-02f, 4.2895122e-02f,
+ 4.4568088e-02f, 4.6271536e-02f, 4.8005353e-02f, 4.9769424e-02f,
+ 5.1563629e-02f, 5.3387849e-02f, 5.5241962e-02f, 5.7125844e-02f,
+ 5.9039368e-02f, 6.0982406e-02f, 6.2954829e-02f, 6.4956504e-02f,
+ 6.6987298e-02f, 6.9047074e-02f, 7.1135695e-02f, 7.3253021e-02f,
+ 7.5398909e-02f, 7.7573217e-02f, 7.9775799e-02f, 8.2006508e-02f,
+ 8.4265194e-02f, 8.6551706e-02f, 8.8865891e-02f, 9.1207593e-02f,
+ 9.3576658e-02f, 9.5972925e-02f, 9.8396234e-02f, 1.0084642e-01f,
+ 1.0332333e-01f, 1.0582679e-01f, 1.0835663e-01f, 1.1091268e-01f,
+ 1.1349477e-01f, 1.1610274e-01f, 1.1873640e-01f, 1.2139558e-01f,
+ 1.2408010e-01f, 1.2678978e-01f, 1.2952444e-01f, 1.3228389e-01f,
+ 1.3506796e-01f, 1.3787646e-01f, 1.4070919e-01f, 1.4356597e-01f,
+ 1.4644661e-01f, 1.4935091e-01f, 1.5227868e-01f, 1.5522973e-01f,
+ 1.5820385e-01f, 1.6120085e-01f, 1.6422052e-01f, 1.6726267e-01f,
+ 1.7032709e-01f, 1.7341358e-01f, 1.7652192e-01f, 1.7965192e-01f,
+ 1.8280336e-01f, 1.8597603e-01f, 1.8916971e-01f, 1.9238420e-01f,
+ 1.9561929e-01f, 1.9887474e-01f, 2.0215035e-01f, 2.0544589e-01f,
+ 2.0876115e-01f, 2.1209590e-01f, 2.1544993e-01f, 2.1882300e-01f,
+ 2.2221488e-01f, 2.2562536e-01f, 2.2905421e-01f, 2.3250119e-01f,
+ 2.3596607e-01f, 2.3944863e-01f, 2.4294863e-01f, 2.4646583e-01f,
+ 2.5000000e-01f, 2.5355090e-01f, 2.5711830e-01f, 2.6070196e-01f,
+ 2.6430163e-01f, 2.6791708e-01f, 2.7154806e-01f, 2.7519434e-01f,
+ 2.7885565e-01f, 2.8253178e-01f, 2.8622245e-01f, 2.8992744e-01f,
+ 2.9364649e-01f, 2.9737934e-01f, 3.0112576e-01f, 3.0488549e-01f,
+ 3.0865828e-01f, 3.1244388e-01f, 3.1624203e-01f, 3.2005248e-01f,
+ 3.2387498e-01f, 3.2770926e-01f, 3.3155507e-01f, 3.3541216e-01f,
+ 3.3928027e-01f, 3.4315913e-01f, 3.4704849e-01f, 3.5094809e-01f,
+ 3.5485766e-01f, 3.5877695e-01f, 3.6270569e-01f, 3.6664362e-01f,
+ 3.7059048e-01f, 3.7454600e-01f, 3.7850991e-01f, 3.8248196e-01f,
+ 3.8646187e-01f, 3.9044938e-01f, 3.9444422e-01f, 3.9844613e-01f,
+ 4.0245484e-01f, 4.0647007e-01f, 4.1049157e-01f, 4.1451906e-01f,
+ 4.1855226e-01f, 4.2259092e-01f, 4.2663476e-01f, 4.3068351e-01f,
+ 4.3473690e-01f, 4.3879466e-01f, 4.4285652e-01f, 4.4692220e-01f,
+ 4.5099143e-01f, 4.5506394e-01f, 4.5913946e-01f, 4.6321772e-01f,
+ 4.6729844e-01f, 4.7138134e-01f, 4.7546616e-01f, 4.7955263e-01f,
+ 4.8364046e-01f, 4.8772939e-01f, 4.9181913e-01f, 4.9590943e-01f,
+ 5.0000000e-01f, 5.0409057e-01f, 5.0818087e-01f, 5.1227061e-01f,
+ 5.1635954e-01f, 5.2044737e-01f, 5.2453384e-01f, 5.2861866e-01f,
+ 5.3270156e-01f, 5.3678228e-01f, 5.4086054e-01f, 5.4493606e-01f,
+ 5.4900857e-01f, 5.5307780e-01f, 5.5714348e-01f, 5.6120534e-01f,
+ 5.6526310e-01f, 5.6931649e-01f, 5.7336524e-01f, 5.7740908e-01f,
+ 5.8144774e-01f, 5.8548094e-01f, 5.8950843e-01f, 5.9352993e-01f,
+ 5.9754516e-01f, 6.0155387e-01f, 6.0555578e-01f, 6.0955062e-01f,
+ 6.1353813e-01f, 6.1751804e-01f, 6.2149009e-01f, 6.2545400e-01f,
+ 6.2940952e-01f, 6.3335638e-01f, 6.3729431e-01f, 6.4122305e-01f,
+ 6.4514234e-01f, 6.4905191e-01f, 6.5295151e-01f, 6.5684087e-01f,
+ 6.6071973e-01f, 6.6458784e-01f, 6.6844493e-01f, 6.7229074e-01f,
+ 6.7612502e-01f, 6.7994752e-01f, 6.8375797e-01f, 6.8755612e-01f,
+ 6.9134172e-01f, 6.9511451e-01f, 6.9887424e-01f, 7.0262066e-01f,
+ 7.0635351e-01f, 7.1007256e-01f, 7.1377755e-01f, 7.1746822e-01f,
+ 7.2114435e-01f, 7.2480566e-01f, 7.2845194e-01f, 7.3208292e-01f,
+ 7.3569837e-01f, 7.3929804e-01f, 7.4288170e-01f, 7.4644910e-01f,
+ 7.5000000e-01f, 7.5353417e-01f, 7.5705137e-01f, 7.6055137e-01f,
+ 7.6403393e-01f, 7.6749881e-01f, 7.7094579e-01f, 7.7437464e-01f,
+ 7.7778512e-01f, 7.8117700e-01f, 7.8455007e-01f, 7.8790410e-01f,
+ 7.9123885e-01f, 7.9455411e-01f, 7.9784965e-01f, 8.0112526e-01f,
+ 8.0438071e-01f, 8.0761580e-01f, 8.1083029e-01f, 8.1402397e-01f,
+ 8.1719664e-01f, 8.2034808e-01f, 8.2347808e-01f, 8.2658642e-01f,
+ 8.2967291e-01f, 8.3273733e-01f, 8.3577948e-01f, 8.3879915e-01f,
+ 8.4179615e-01f, 8.4477027e-01f, 8.4772132e-01f, 8.5064909e-01f,
+ 8.5355339e-01f, 8.5643403e-01f, 8.5929081e-01f, 8.6212354e-01f,
+ 8.6493204e-01f, 8.6771611e-01f, 8.7047556e-01f, 8.7321022e-01f,
+ 8.7591990e-01f, 8.7860442e-01f, 8.8126360e-01f, 8.8389726e-01f,
+ 8.8650523e-01f, 8.8908732e-01f, 8.9164337e-01f, 8.9417321e-01f,
+ 8.9667667e-01f, 8.9915358e-01f, 9.0160377e-01f, 9.0402708e-01f,
+ 9.0642334e-01f, 9.0879241e-01f, 9.1113411e-01f, 9.1344829e-01f,
+ 9.1573481e-01f, 9.1799349e-01f, 9.2022420e-01f, 9.2242678e-01f,
+ 9.2460109e-01f, 9.2674698e-01f, 9.2886431e-01f, 9.3095293e-01f,
+ 9.3301270e-01f, 9.3504350e-01f, 9.3704517e-01f, 9.3901759e-01f,
+ 9.4096063e-01f, 9.4287416e-01f, 9.4475804e-01f, 9.4661215e-01f,
+ 9.4843637e-01f, 9.5023058e-01f, 9.5199465e-01f, 9.5372846e-01f,
+ 9.5543191e-01f, 9.5710488e-01f, 9.5874725e-01f, 9.6035891e-01f,
+ 9.6193977e-01f, 9.6348970e-01f, 9.6500861e-01f, 9.6649640e-01f,
+ 9.6795296e-01f, 9.6937821e-01f, 9.7077203e-01f, 9.7213435e-01f,
+ 9.7346506e-01f, 9.7476409e-01f, 9.7603134e-01f, 9.7726673e-01f,
+ 9.7847017e-01f, 9.7964159e-01f, 9.8078090e-01f, 9.8188803e-01f,
+ 9.8296291e-01f, 9.8400547e-01f, 9.8501563e-01f, 9.8599332e-01f,
+ 9.8693849e-01f, 9.8785107e-01f, 9.8873099e-01f, 9.8957820e-01f,
+ 9.9039264e-01f, 9.9117426e-01f, 9.9192300e-01f, 9.9263882e-01f,
+ 9.9332167e-01f, 9.9397149e-01f, 9.9458825e-01f, 9.9517191e-01f,
+ 9.9572243e-01f, 9.9623977e-01f, 9.9672389e-01f, 9.9717476e-01f,
+ 9.9759236e-01f, 9.9797666e-01f, 9.9832762e-01f, 9.9864523e-01f,
+ 9.9892946e-01f, 9.9918030e-01f, 9.9939773e-01f, 9.9958173e-01f,
+ 9.9973229e-01f, 9.9984941e-01f, 9.9993307e-01f, 9.9998327e-01f,
+ 1.0000000e+00f, 9.9998327e-01f, 9.9993307e-01f, 9.9984941e-01f,
+ 9.9973229e-01f, 9.9958173e-01f, 9.9939773e-01f, 9.9918030e-01f,
+ 9.9892946e-01f, 9.9864523e-01f, 9.9832762e-01f, 9.9797666e-01f,
+ 9.9759236e-01f, 9.9717476e-01f, 9.9672389e-01f, 9.9623977e-01f,
+ 9.9572243e-01f, 9.9517191e-01f, 9.9458825e-01f, 9.9397149e-01f,
+ 9.9332167e-01f, 9.9263882e-01f, 9.9192300e-01f, 9.9117426e-01f,
+ 9.9039264e-01f, 9.8957820e-01f, 9.8873099e-01f, 9.8785107e-01f,
+ 9.8693849e-01f, 9.8599332e-01f, 9.8501563e-01f, 9.8400547e-01f,
+ 9.8296291e-01f, 9.8188803e-01f, 9.8078090e-01f, 9.7964159e-01f,
+ 9.7847017e-01f, 9.7726673e-01f, 9.7603134e-01f, 9.7476409e-01f,
+ 9.7346506e-01f, 9.7213435e-01f, 9.7077203e-01f, 9.6937821e-01f,
+ 9.6795296e-01f, 9.6649640e-01f, 9.6500861e-01f, 9.6348970e-01f,
+ 9.6193977e-01f, 9.6035891e-01f, 9.5874725e-01f, 9.5710488e-01f,
+ 9.5543191e-01f, 9.5372846e-01f, 9.5199465e-01f, 9.5023058e-01f,
+ 9.4843637e-01f, 9.4661215e-01f, 9.4475804e-01f, 9.4287416e-01f,
+ 9.4096063e-01f, 9.3901759e-01f, 9.3704517e-01f, 9.3504350e-01f,
+ 9.3301270e-01f, 9.3095293e-01f, 9.2886431e-01f, 9.2674698e-01f,
+ 9.2460109e-01f, 9.2242678e-01f, 9.2022420e-01f, 9.1799349e-01f,
+ 9.1573481e-01f, 9.1344829e-01f, 9.1113411e-01f, 9.0879241e-01f,
+ 9.0642334e-01f, 9.0402708e-01f, 9.0160377e-01f, 8.9915358e-01f,
+ 8.9667667e-01f, 8.9417321e-01f, 8.9164337e-01f, 8.8908732e-01f,
+ 8.8650523e-01f, 8.8389726e-01f, 8.8126360e-01f, 8.7860442e-01f,
+ 8.7591990e-01f, 8.7321022e-01f, 8.7047556e-01f, 8.6771611e-01f,
+ 8.6493204e-01f, 8.6212354e-01f, 8.5929081e-01f, 8.5643403e-01f,
+ 8.5355339e-01f, 8.5064909e-01f, 8.4772132e-01f, 8.4477027e-01f,
+ 8.4179615e-01f, 8.3879915e-01f, 8.3577948e-01f, 8.3273733e-01f,
+ 8.2967291e-01f, 8.2658642e-01f, 8.2347808e-01f, 8.2034808e-01f,
+ 8.1719664e-01f, 8.1402397e-01f, 8.1083029e-01f, 8.0761580e-01f,
+ 8.0438071e-01f, 8.0112526e-01f, 7.9784965e-01f, 7.9455411e-01f,
+ 7.9123885e-01f, 7.8790410e-01f, 7.8455007e-01f, 7.8117700e-01f,
+ 7.7778512e-01f, 7.7437464e-01f, 7.7094579e-01f, 7.6749881e-01f,
+ 7.6403393e-01f, 7.6055137e-01f, 7.5705137e-01f, 7.5353417e-01f,
+ 7.5000000e-01f, 7.4644910e-01f, 7.4288170e-01f, 7.3929804e-01f,
+ 7.3569837e-01f, 7.3208292e-01f, 7.2845194e-01f, 7.2480566e-01f,
+ 7.2114435e-01f, 7.1746822e-01f, 7.1377755e-01f, 7.1007256e-01f,
+ 7.0635351e-01f, 7.0262066e-01f, 6.9887424e-01f, 6.9511451e-01f,
+ 6.9134172e-01f, 6.8755612e-01f, 6.8375797e-01f, 6.7994752e-01f,
+ 6.7612502e-01f, 6.7229074e-01f, 6.6844493e-01f, 6.6458784e-01f,
+ 6.6071973e-01f, 6.5684087e-01f, 6.5295151e-01f, 6.4905191e-01f,
+ 6.4514234e-01f, 6.4122305e-01f, 6.3729431e-01f, 6.3335638e-01f,
+ 6.2940952e-01f, 6.2545400e-01f, 6.2149009e-01f, 6.1751804e-01f,
+ 6.1353813e-01f, 6.0955062e-01f, 6.0555578e-01f, 6.0155387e-01f,
+ 5.9754516e-01f, 5.9352993e-01f, 5.8950843e-01f, 5.8548094e-01f,
+ 5.8144774e-01f, 5.7740908e-01f, 5.7336524e-01f, 5.6931649e-01f,
+ 5.6526310e-01f, 5.6120534e-01f, 5.5714348e-01f, 5.5307780e-01f,
+ 5.4900857e-01f, 5.4493606e-01f, 5.4086054e-01f, 5.3678228e-01f,
+ 5.3270156e-01f, 5.2861866e-01f, 5.2453384e-01f, 5.2044737e-01f,
+ 5.1635954e-01f, 5.1227061e-01f, 5.0818087e-01f, 5.0409057e-01f,
+ 5.0000000e-01f, 4.9590943e-01f, 4.9181913e-01f, 4.8772939e-01f,
+ 4.8364046e-01f, 4.7955263e-01f, 4.7546616e-01f, 4.7138134e-01f,
+ 4.6729844e-01f, 4.6321772e-01f, 4.5913946e-01f, 4.5506394e-01f,
+ 4.5099143e-01f, 4.4692220e-01f, 4.4285652e-01f, 4.3879466e-01f,
+ 4.3473690e-01f, 4.3068351e-01f, 4.2663476e-01f, 4.2259092e-01f,
+ 4.1855226e-01f, 4.1451906e-01f, 4.1049157e-01f, 4.0647007e-01f,
+ 4.0245484e-01f, 3.9844613e-01f, 3.9444422e-01f, 3.9044938e-01f,
+ 3.8646187e-01f, 3.8248196e-01f, 3.7850991e-01f, 3.7454600e-01f,
+ 3.7059048e-01f, 3.6664362e-01f, 3.6270569e-01f, 3.5877695e-01f,
+ 3.5485766e-01f, 3.5094809e-01f, 3.4704849e-01f, 3.4315913e-01f,
+ 3.3928027e-01f, 3.3541216e-01f, 3.3155507e-01f, 3.2770926e-01f,
+ 3.2387498e-01f, 3.2005248e-01f, 3.1624203e-01f, 3.1244388e-01f,
+ 3.0865828e-01f, 3.0488549e-01f, 3.0112576e-01f, 2.9737934e-01f,
+ 2.9364649e-01f, 2.8992744e-01f, 2.8622245e-01f, 2.8253178e-01f,
+ 2.7885565e-01f, 2.7519434e-01f, 2.7154806e-01f, 2.6791708e-01f,
+ 2.6430163e-01f, 2.6070196e-01f, 2.5711830e-01f, 2.5355090e-01f,
+ 2.5000000e-01f, 2.4646583e-01f, 2.4294863e-01f, 2.3944863e-01f,
+ 2.3596607e-01f, 2.3250119e-01f, 2.2905421e-01f, 2.2562536e-01f,
+ 2.2221488e-01f, 2.1882300e-01f, 2.1544993e-01f, 2.1209590e-01f,
+ 2.0876115e-01f, 2.0544589e-01f, 2.0215035e-01f, 1.9887474e-01f,
+ 1.9561929e-01f, 1.9238420e-01f, 1.8916971e-01f, 1.8597603e-01f,
+ 1.8280336e-01f, 1.7965192e-01f, 1.7652192e-01f, 1.7341358e-01f,
+ 1.7032709e-01f, 1.6726267e-01f, 1.6422052e-01f, 1.6120085e-01f,
+ 1.5820385e-01f, 1.5522973e-01f, 1.5227868e-01f, 1.4935091e-01f,
+ 1.4644661e-01f, 1.4356597e-01f, 1.4070919e-01f, 1.3787646e-01f,
+ 1.3506796e-01f, 1.3228389e-01f, 1.2952444e-01f, 1.2678978e-01f,
+ 1.2408010e-01f, 1.2139558e-01f, 1.1873640e-01f, 1.1610274e-01f,
+ 1.1349477e-01f, 1.1091268e-01f, 1.0835663e-01f, 1.0582679e-01f,
+ 1.0332333e-01f, 1.0084642e-01f, 9.8396234e-02f, 9.5972925e-02f,
+ 9.3576658e-02f, 9.1207593e-02f, 8.8865891e-02f, 8.6551706e-02f,
+ 8.4265194e-02f, 8.2006508e-02f, 7.9775799e-02f, 7.7573217e-02f,
+ 7.5398909e-02f, 7.3253021e-02f, 7.1135695e-02f, 6.9047074e-02f,
+ 6.6987298e-02f, 6.4956504e-02f, 6.2954829e-02f, 6.0982406e-02f,
+ 5.9039368e-02f, 5.7125844e-02f, 5.5241962e-02f, 5.3387849e-02f,
+ 5.1563629e-02f, 4.9769424e-02f, 4.8005353e-02f, 4.6271536e-02f,
+ 4.4568088e-02f, 4.2895122e-02f, 4.1252752e-02f, 3.9641086e-02f,
+ 3.8060234e-02f, 3.6510300e-02f, 3.4991388e-02f, 3.3503601e-02f,
+ 3.2047037e-02f, 3.0621794e-02f, 2.9227967e-02f, 2.7865651e-02f,
+ 2.6534935e-02f, 2.5235910e-02f, 2.3968661e-02f, 2.2733274e-02f,
+ 2.1529832e-02f, 2.0358415e-02f, 1.9219101e-02f, 1.8111967e-02f,
+ 1.7037087e-02f, 1.5994532e-02f, 1.4984373e-02f, 1.4006678e-02f,
+ 1.3061510e-02f, 1.2148935e-02f, 1.1269013e-02f, 1.0421802e-02f,
+ 9.6073598e-03f, 8.8257407e-03f, 8.0769970e-03f, 7.3611788e-03f,
+ 6.6783340e-03f, 6.0285082e-03f, 5.4117450e-03f, 4.8280857e-03f,
+ 4.2775693e-03f, 3.7602327e-03f, 3.2761105e-03f, 2.8252351e-03f,
+ 2.4076367e-03f, 2.0233432e-03f, 1.6723803e-03f, 1.3547717e-03f,
+ 1.0705384e-03f, 8.1969953e-04f, 6.0227190e-04f, 4.1827004e-04f,
+ 2.6770626e-04f, 1.5059065e-04f, 6.6931045e-05f, 1.6733041e-05f};
+
+#endif
diff --git a/src/fftw.c b/src/fftw.c
new file mode 100644
index 0000000000000000000000000000000000000000..39e56db9316fda4be953fddf9421ed97863f74db
--- /dev/null
+++ b/src/fftw.c
@@ -0,0 +1,3601 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#include
+#include
+#include
+#include
+
+#include "fftw.h"
+
+static const int AUP_FFTW_g_ip256[] = {64, 64, 0, 16, 0, 64, 32, 96};
+static const float AUP_FFTW_g_w256[] = {
+ 1.000000e+00f, 7.071068e-01f, 5.006030e-01f, 5.054710e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.024193e-01f, 5.224986e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.097956e-01f, 6.013449e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 1.000000e+00f, 7.071068e-01f, 9.238795e-01f, 3.826834e-01f,
+ 1.000000e+00f, 7.071068e-01f, 0.000000e+00f, 0.000000e+00f,
+ 7.071068e-01f, 4.998494e-01f, 4.993977e-01f, 4.986452e-01f,
+ 4.975924e-01f, 4.962398e-01f, 4.945883e-01f, 4.926388e-01f,
+ 4.903926e-01f, 4.878511e-01f, 4.850156e-01f, 4.818880e-01f,
+ 4.784702e-01f, 4.747641e-01f, 4.707720e-01f, 4.664964e-01f,
+ 4.619398e-01f, 4.571049e-01f, 4.519946e-01f, 4.466122e-01f,
+ 4.409606e-01f, 4.350435e-01f, 4.288643e-01f, 4.224268e-01f,
+ 4.157348e-01f, 4.087924e-01f, 4.016038e-01f, 3.941732e-01f,
+ 3.865052e-01f, 3.786044e-01f, 3.704756e-01f, 3.621235e-01f,
+ 3.535534e-01f, 3.447703e-01f, 3.357795e-01f, 3.265864e-01f,
+ 3.171966e-01f, 3.076158e-01f, 2.978497e-01f, 2.879041e-01f,
+ 2.777851e-01f, 2.674988e-01f, 2.570514e-01f, 2.464491e-01f,
+ 2.356984e-01f, 2.248057e-01f, 2.137775e-01f, 2.026207e-01f,
+ 1.913417e-01f, 1.799475e-01f, 1.684449e-01f, 1.568409e-01f,
+ 1.451423e-01f, 1.333564e-01f, 1.214901e-01f, 1.095506e-01f,
+ 9.754516e-02f, 8.548094e-02f, 7.336524e-02f, 6.120534e-02f,
+ 4.900857e-02f, 3.678228e-02f, 2.453384e-02f, 1.227061e-02f};
+static const int AUP_FFTW_g_ip512[] = {128, 128, 0, 16, 0, 64, 32, 96};
+static const float AUP_FFTW_g_w512[] = {
+ 1.000000e+00f, 7.071068e-01f, 5.001506e-01f, 5.013585e-01f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.006030e-01f, 5.054710e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.024193e-01f, 5.224986e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.097956e-01f, 6.013449e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 1.000000e+00f, 7.071068e-01f, 9.238795e-01f, 3.826834e-01f,
+ 1.000000e+00f, 7.071068e-01f, 0.000000e+00f, 0.000000e+00f,
+ 7.071068e-01f, 4.999624e-01f, 4.998494e-01f, 4.996612e-01f,
+ 4.993977e-01f, 4.990591e-01f, 4.986452e-01f, 4.981563e-01f,
+ 4.975924e-01f, 4.969535e-01f, 4.962398e-01f, 4.954513e-01f,
+ 4.945883e-01f, 4.936507e-01f, 4.926388e-01f, 4.915527e-01f,
+ 4.903926e-01f, 4.891587e-01f, 4.878511e-01f, 4.864700e-01f,
+ 4.850156e-01f, 4.834882e-01f, 4.818880e-01f, 4.802153e-01f,
+ 4.784702e-01f, 4.766530e-01f, 4.747641e-01f, 4.728037e-01f,
+ 4.707720e-01f, 4.686695e-01f, 4.664964e-01f, 4.642530e-01f,
+ 4.619398e-01f, 4.595569e-01f, 4.571049e-01f, 4.545840e-01f,
+ 4.519946e-01f, 4.493372e-01f, 4.466122e-01f, 4.438198e-01f,
+ 4.409606e-01f, 4.380350e-01f, 4.350435e-01f, 4.319864e-01f,
+ 4.288643e-01f, 4.256776e-01f, 4.224268e-01f, 4.191124e-01f,
+ 4.157348e-01f, 4.122947e-01f, 4.087924e-01f, 4.052286e-01f,
+ 4.016038e-01f, 3.979185e-01f, 3.941732e-01f, 3.903686e-01f,
+ 3.865052e-01f, 3.825836e-01f, 3.786044e-01f, 3.745682e-01f,
+ 3.704756e-01f, 3.663271e-01f, 3.621235e-01f, 3.578654e-01f,
+ 3.535534e-01f, 3.491881e-01f, 3.447703e-01f, 3.403005e-01f,
+ 3.357795e-01f, 3.312079e-01f, 3.265864e-01f, 3.219158e-01f,
+ 3.171966e-01f, 3.124297e-01f, 3.076158e-01f, 3.027555e-01f,
+ 2.978497e-01f, 2.928989e-01f, 2.879041e-01f, 2.828659e-01f,
+ 2.777851e-01f, 2.726625e-01f, 2.674988e-01f, 2.622948e-01f,
+ 2.570514e-01f, 2.517692e-01f, 2.464491e-01f, 2.410919e-01f,
+ 2.356984e-01f, 2.302694e-01f, 2.248057e-01f, 2.193081e-01f,
+ 2.137775e-01f, 2.082148e-01f, 2.026207e-01f, 1.969960e-01f,
+ 1.913417e-01f, 1.856586e-01f, 1.799475e-01f, 1.742093e-01f,
+ 1.684449e-01f, 1.626551e-01f, 1.568409e-01f, 1.510030e-01f,
+ 1.451423e-01f, 1.392598e-01f, 1.333564e-01f, 1.274328e-01f,
+ 1.214901e-01f, 1.155291e-01f, 1.095506e-01f, 1.035557e-01f,
+ 9.754516e-02f, 9.151994e-02f, 8.548094e-02f, 7.942907e-02f,
+ 7.336524e-02f, 6.729035e-02f, 6.120534e-02f, 5.511110e-02f,
+ 4.900857e-02f, 4.289866e-02f, 3.678228e-02f, 3.066037e-02f,
+ 2.453384e-02f, 1.840361e-02f, 1.227061e-02f, 6.135769e-03f};
+static const int AUP_FFTW_g_ip1024[] = {256, 256, 0, 16, 0, 64, 32, 96,
+ 0, 256, 128, 384, 64, 320, 192, 448};
+static const float AUP_FFTW_g_w1024[] = {
+ 1.000000e+00f, 7.071068e-01f, 5.000377e-01f, 5.003390e-01f,
+ 9.996988e-01f, 2.454123e-02f, 9.972905e-01f, -7.356456e-02f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.972905e-01f, 7.356456e-02f, 9.757021e-01f, -2.191012e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.924795e-01f, 1.224107e-01f, 9.329928e-01f, -3.598950e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.852776e-01f, 1.709619e-01f, 8.700870e-01f, -4.928982e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.757021e-01f, 2.191012e-01f, 7.883464e-01f, -6.152316e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.637761e-01f, 2.667128e-01f, 6.895405e-01f, -7.242471e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.495282e-01f, 3.136817e-01f, 5.758082e-01f, -8.175848e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.329928e-01f, 3.598950e-01f, 4.496113e-01f, -8.932243e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.142098e-01f, 4.052413e-01f, 3.136817e-01f, -9.495282e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 8.932243e-01f, 4.496113e-01f, 1.709619e-01f, -9.852776e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.700870e-01f, 4.928982e-01f, 2.454123e-02f, -9.996988e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.448536e-01f, 5.349976e-01f, -1.224107e-01f, -9.924795e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.175848e-01f, 5.758082e-01f, -2.667128e-01f, -9.637761e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.883464e-01f, 6.152316e-01f, -4.052413e-01f, -9.142098e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.572088e-01f, 6.531728e-01f, -5.349976e-01f, -8.448536e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 7.242471e-01f, 6.895405e-01f, -6.531728e-01f, -7.572088e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.001506e-01f, 5.013585e-01f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.006030e-01f, 5.054710e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.024193e-01f, 5.224986e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.097956e-01f, 6.013449e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 1.000000e+00f, 7.071068e-01f, 9.238795e-01f, 3.826834e-01f,
+ 1.000000e+00f, 7.071068e-01f, 0.000000e+00f, 0.000000e+00f,
+ 7.071068e-01f, 4.999906e-01f, 4.999624e-01f, 4.999153e-01f,
+ 4.998494e-01f, 4.997647e-01f, 4.996612e-01f, 4.995389e-01f,
+ 4.993977e-01f, 4.992378e-01f, 4.990591e-01f, 4.988615e-01f,
+ 4.986452e-01f, 4.984101e-01f, 4.981563e-01f, 4.978837e-01f,
+ 4.975924e-01f, 4.972823e-01f, 4.969535e-01f, 4.966060e-01f,
+ 4.962398e-01f, 4.958549e-01f, 4.954513e-01f, 4.950291e-01f,
+ 4.945883e-01f, 4.941288e-01f, 4.936507e-01f, 4.931540e-01f,
+ 4.926388e-01f, 4.921050e-01f, 4.915527e-01f, 4.909819e-01f,
+ 4.903926e-01f, 4.897849e-01f, 4.891587e-01f, 4.885141e-01f,
+ 4.878511e-01f, 4.871697e-01f, 4.864700e-01f, 4.857519e-01f,
+ 4.850156e-01f, 4.842610e-01f, 4.834882e-01f, 4.826972e-01f,
+ 4.818880e-01f, 4.810607e-01f, 4.802153e-01f, 4.793517e-01f,
+ 4.784702e-01f, 4.775706e-01f, 4.766530e-01f, 4.757175e-01f,
+ 4.747641e-01f, 4.737928e-01f, 4.728037e-01f, 4.717967e-01f,
+ 4.707720e-01f, 4.697296e-01f, 4.686695e-01f, 4.675918e-01f,
+ 4.664964e-01f, 4.653835e-01f, 4.642530e-01f, 4.631051e-01f,
+ 4.619398e-01f, 4.607570e-01f, 4.595569e-01f, 4.583395e-01f,
+ 4.571049e-01f, 4.558530e-01f, 4.545840e-01f, 4.532979e-01f,
+ 4.519946e-01f, 4.506744e-01f, 4.493372e-01f, 4.479831e-01f,
+ 4.466122e-01f, 4.452244e-01f, 4.438198e-01f, 4.423985e-01f,
+ 4.409606e-01f, 4.395061e-01f, 4.380350e-01f, 4.365475e-01f,
+ 4.350435e-01f, 4.335231e-01f, 4.319864e-01f, 4.304335e-01f,
+ 4.288643e-01f, 4.272790e-01f, 4.256776e-01f, 4.240602e-01f,
+ 4.224268e-01f, 4.207775e-01f, 4.191124e-01f, 4.174314e-01f,
+ 4.157348e-01f, 4.140225e-01f, 4.122947e-01f, 4.105513e-01f,
+ 4.087924e-01f, 4.070182e-01f, 4.052286e-01f, 4.034238e-01f,
+ 4.016038e-01f, 3.997686e-01f, 3.979185e-01f, 3.960533e-01f,
+ 3.941732e-01f, 3.922783e-01f, 3.903686e-01f, 3.884442e-01f,
+ 3.865052e-01f, 3.845517e-01f, 3.825836e-01f, 3.806012e-01f,
+ 3.786044e-01f, 3.765934e-01f, 3.745682e-01f, 3.725289e-01f,
+ 3.704756e-01f, 3.684083e-01f, 3.663271e-01f, 3.642322e-01f,
+ 3.621235e-01f, 3.600013e-01f, 3.578654e-01f, 3.557161e-01f,
+ 3.535534e-01f, 3.513774e-01f, 3.491881e-01f, 3.469857e-01f,
+ 3.447703e-01f, 3.425418e-01f, 3.403005e-01f, 3.380464e-01f,
+ 3.357795e-01f, 3.335000e-01f, 3.312079e-01f, 3.289033e-01f,
+ 3.265864e-01f, 3.242572e-01f, 3.219158e-01f, 3.195622e-01f,
+ 3.171966e-01f, 3.148191e-01f, 3.124297e-01f, 3.100286e-01f,
+ 3.076158e-01f, 3.051914e-01f, 3.027555e-01f, 3.003082e-01f,
+ 2.978497e-01f, 2.953799e-01f, 2.928989e-01f, 2.904070e-01f,
+ 2.879041e-01f, 2.853904e-01f, 2.828659e-01f, 2.803308e-01f,
+ 2.777851e-01f, 2.752290e-01f, 2.726625e-01f, 2.700857e-01f,
+ 2.674988e-01f, 2.649018e-01f, 2.622948e-01f, 2.596780e-01f,
+ 2.570514e-01f, 2.544151e-01f, 2.517692e-01f, 2.491138e-01f,
+ 2.464491e-01f, 2.437751e-01f, 2.410919e-01f, 2.383996e-01f,
+ 2.356984e-01f, 2.329882e-01f, 2.302694e-01f, 2.275418e-01f,
+ 2.248057e-01f, 2.220611e-01f, 2.193081e-01f, 2.165469e-01f,
+ 2.137775e-01f, 2.110001e-01f, 2.082148e-01f, 2.054216e-01f,
+ 2.026207e-01f, 1.998121e-01f, 1.969960e-01f, 1.941725e-01f,
+ 1.913417e-01f, 1.885037e-01f, 1.856586e-01f, 1.828065e-01f,
+ 1.799475e-01f, 1.770818e-01f, 1.742093e-01f, 1.713304e-01f,
+ 1.684449e-01f, 1.655532e-01f, 1.626551e-01f, 1.597510e-01f,
+ 1.568409e-01f, 1.539248e-01f, 1.510030e-01f, 1.480754e-01f,
+ 1.451423e-01f, 1.422038e-01f, 1.392598e-01f, 1.363107e-01f,
+ 1.333564e-01f, 1.303971e-01f, 1.274328e-01f, 1.244638e-01f,
+ 1.214901e-01f, 1.185118e-01f, 1.155291e-01f, 1.125420e-01f,
+ 1.095506e-01f, 1.065552e-01f, 1.035557e-01f, 1.005523e-01f,
+ 9.754516e-02f, 9.453433e-02f, 9.151994e-02f, 8.850211e-02f,
+ 8.548094e-02f, 8.245656e-02f, 7.942907e-02f, 7.639859e-02f,
+ 7.336524e-02f, 7.032912e-02f, 6.729035e-02f, 6.424906e-02f,
+ 6.120534e-02f, 5.815932e-02f, 5.511110e-02f, 5.206082e-02f,
+ 4.900857e-02f, 4.595448e-02f, 4.289866e-02f, 3.984122e-02f,
+ 3.678228e-02f, 3.372196e-02f, 3.066037e-02f, 2.759762e-02f,
+ 2.453384e-02f, 2.146913e-02f, 1.840361e-02f, 1.533740e-02f,
+ 1.227061e-02f, 9.203365e-03f, 6.135769e-03f, 3.067942e-03f};
+static const int AUP_FFTW_g_ip2048[] = {512, 512, 0, 16, 0, 64, 32, 96,
+ 0, 256, 128, 384, 64, 320, 192, 448};
+static const float AUP_FFTW_g_w2048[] = {
+ 1.000000e+00f, 7.071068e-01f, 5.000094e-01f, 5.000847e-01f,
+ 9.999247e-01f, 1.227154e-02f, 9.993224e-01f, -3.680722e-02f,
+ 9.996988e-01f, 2.454123e-02f, 9.972905e-01f, -7.356456e-02f,
+ 9.993224e-01f, 3.680722e-02f, 9.939070e-01f, -1.102222e-01f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.981181e-01f, 6.132074e-02f, 9.831055e-01f, -1.830399e-01f,
+ 9.972905e-01f, 7.356456e-02f, 9.757021e-01f, -2.191012e-01f,
+ 9.963126e-01f, 8.579731e-02f, 9.669765e-01f, -2.548657e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.939070e-01f, 1.102222e-01f, 9.456073e-01f, -3.253103e-01f,
+ 9.924795e-01f, 1.224107e-01f, 9.329928e-01f, -3.598950e-01f,
+ 9.909026e-01f, 1.345807e-01f, 9.191139e-01f, -3.939920e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.873014e-01f, 1.588581e-01f, 8.876396e-01f, -4.605387e-01f,
+ 9.852776e-01f, 1.709619e-01f, 8.700870e-01f, -4.928982e-01f,
+ 9.831055e-01f, 1.830399e-01f, 8.513552e-01f, -5.245897e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.783174e-01f, 2.071114e-01f, 8.104572e-01f, -5.857979e-01f,
+ 9.757021e-01f, 2.191012e-01f, 7.883464e-01f, -6.152316e-01f,
+ 9.729400e-01f, 2.310581e-01f, 7.651673e-01f, -6.438315e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.669765e-01f, 2.548657e-01f, 7.157308e-01f, -6.983762e-01f,
+ 9.637761e-01f, 2.667128e-01f, 6.895405e-01f, -7.242471e-01f,
+ 9.604305e-01f, 2.785197e-01f, 6.624158e-01f, -7.491364e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.533060e-01f, 3.020059e-01f, 6.055110e-01f, -7.958369e-01f,
+ 9.495282e-01f, 3.136817e-01f, 5.758082e-01f, -8.175848e-01f,
+ 9.456073e-01f, 3.253103e-01f, 5.453250e-01f, -8.382247e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.373390e-01f, 3.484187e-01f, 4.821838e-01f, -8.760701e-01f,
+ 9.329928e-01f, 3.598950e-01f, 4.496113e-01f, -8.932243e-01f,
+ 9.285061e-01f, 3.713172e-01f, 4.164296e-01f, -9.091680e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.191139e-01f, 3.939920e-01f, 3.484187e-01f, -9.373390e-01f,
+ 9.142098e-01f, 4.052413e-01f, 3.136817e-01f, -9.495282e-01f,
+ 9.091680e-01f, 4.164296e-01f, 2.785197e-01f, -9.604305e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 8.986745e-01f, 4.386162e-01f, 2.071114e-01f, -9.783174e-01f,
+ 8.932243e-01f, 4.496113e-01f, 1.709619e-01f, -9.852776e-01f,
+ 8.876396e-01f, 4.605387e-01f, 1.345807e-01f, -9.909026e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.760701e-01f, 4.821838e-01f, 6.132074e-02f, -9.981181e-01f,
+ 8.700870e-01f, 4.928982e-01f, 2.454123e-02f, -9.996988e-01f,
+ 8.639729e-01f, 5.035384e-01f, -1.227154e-02f, -9.999247e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.513552e-01f, 5.245897e-01f, -8.579731e-02f, -9.963126e-01f,
+ 8.448536e-01f, 5.349976e-01f, -1.224107e-01f, -9.924795e-01f,
+ 8.382247e-01f, 5.453250e-01f, -1.588581e-01f, -9.873014e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.245893e-01f, 5.657318e-01f, -2.310581e-01f, -9.729400e-01f,
+ 8.175848e-01f, 5.758082e-01f, -2.667128e-01f, -9.637761e-01f,
+ 8.104572e-01f, 5.857979e-01f, -3.020059e-01f, -9.533060e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.958369e-01f, 6.055110e-01f, -3.713172e-01f, -9.285061e-01f,
+ 7.883464e-01f, 6.152316e-01f, -4.052413e-01f, -9.142098e-01f,
+ 7.807372e-01f, 6.248595e-01f, -4.386162e-01f, -8.986745e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.651673e-01f, 6.438315e-01f, -5.035384e-01f, -8.639729e-01f,
+ 7.572088e-01f, 6.531728e-01f, -5.349976e-01f, -8.448536e-01f,
+ 7.491364e-01f, 6.624158e-01f, -5.657318e-01f, -8.245893e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 7.326543e-01f, 6.806010e-01f, -6.248595e-01f, -7.807372e-01f,
+ 7.242471e-01f, 6.895405e-01f, -6.531728e-01f, -7.572088e-01f,
+ 7.157308e-01f, 6.983762e-01f, -6.806010e-01f, -7.326543e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.000377e-01f, 5.003390e-01f,
+ 9.996988e-01f, 2.454123e-02f, 9.972905e-01f, -7.356456e-02f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.972905e-01f, 7.356456e-02f, 9.757021e-01f, -2.191012e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.924795e-01f, 1.224107e-01f, 9.329928e-01f, -3.598950e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.852776e-01f, 1.709619e-01f, 8.700870e-01f, -4.928982e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.757021e-01f, 2.191012e-01f, 7.883464e-01f, -6.152316e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.637761e-01f, 2.667128e-01f, 6.895405e-01f, -7.242471e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.495282e-01f, 3.136817e-01f, 5.758082e-01f, -8.175848e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.329928e-01f, 3.598950e-01f, 4.496113e-01f, -8.932243e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.142098e-01f, 4.052413e-01f, 3.136817e-01f, -9.495282e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 8.932243e-01f, 4.496113e-01f, 1.709619e-01f, -9.852776e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.700870e-01f, 4.928982e-01f, 2.454123e-02f, -9.996988e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.448536e-01f, 5.349976e-01f, -1.224107e-01f, -9.924795e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.175848e-01f, 5.758082e-01f, -2.667128e-01f, -9.637761e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.883464e-01f, 6.152316e-01f, -4.052413e-01f, -9.142098e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.572088e-01f, 6.531728e-01f, -5.349976e-01f, -8.448536e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 7.242471e-01f, 6.895405e-01f, -6.531728e-01f, -7.572088e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.001506e-01f, 5.013585e-01f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.006030e-01f, 5.054710e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.024193e-01f, 5.224986e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.097956e-01f, 6.013449e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 1.000000e+00f, 7.071068e-01f, 9.238795e-01f, 3.826834e-01f,
+ 1.000000e+00f, 7.071068e-01f, 0.000000e+00f, 0.000000e+00f,
+ 7.071068e-01f, 4.999976e-01f, 4.999906e-01f, 4.999788e-01f,
+ 4.999624e-01f, 4.999412e-01f, 4.999153e-01f, 4.998847e-01f,
+ 4.998494e-01f, 4.998094e-01f, 4.997647e-01f, 4.997153e-01f,
+ 4.996612e-01f, 4.996024e-01f, 4.995389e-01f, 4.994706e-01f,
+ 4.993977e-01f, 4.993201e-01f, 4.992378e-01f, 4.991508e-01f,
+ 4.990591e-01f, 4.989626e-01f, 4.988615e-01f, 4.987557e-01f,
+ 4.986452e-01f, 4.985300e-01f, 4.984101e-01f, 4.982856e-01f,
+ 4.981563e-01f, 4.980224e-01f, 4.978837e-01f, 4.977404e-01f,
+ 4.975924e-01f, 4.974397e-01f, 4.972823e-01f, 4.971202e-01f,
+ 4.969535e-01f, 4.967821e-01f, 4.966060e-01f, 4.964252e-01f,
+ 4.962398e-01f, 4.960497e-01f, 4.958549e-01f, 4.956554e-01f,
+ 4.954513e-01f, 4.952425e-01f, 4.950291e-01f, 4.948110e-01f,
+ 4.945883e-01f, 4.943608e-01f, 4.941288e-01f, 4.938921e-01f,
+ 4.936507e-01f, 4.934047e-01f, 4.931540e-01f, 4.928988e-01f,
+ 4.926388e-01f, 4.923743e-01f, 4.921050e-01f, 4.918312e-01f,
+ 4.915527e-01f, 4.912697e-01f, 4.909819e-01f, 4.906896e-01f,
+ 4.903926e-01f, 4.900911e-01f, 4.897849e-01f, 4.894741e-01f,
+ 4.891587e-01f, 4.888387e-01f, 4.885141e-01f, 4.881849e-01f,
+ 4.878511e-01f, 4.875127e-01f, 4.871697e-01f, 4.868221e-01f,
+ 4.864700e-01f, 4.861132e-01f, 4.857519e-01f, 4.853861e-01f,
+ 4.850156e-01f, 4.846406e-01f, 4.842610e-01f, 4.838769e-01f,
+ 4.834882e-01f, 4.830950e-01f, 4.826972e-01f, 4.822949e-01f,
+ 4.818880e-01f, 4.814766e-01f, 4.810607e-01f, 4.806402e-01f,
+ 4.802153e-01f, 4.797858e-01f, 4.793517e-01f, 4.789132e-01f,
+ 4.784702e-01f, 4.780226e-01f, 4.775706e-01f, 4.771140e-01f,
+ 4.766530e-01f, 4.761875e-01f, 4.757175e-01f, 4.752430e-01f,
+ 4.747641e-01f, 4.742807e-01f, 4.737928e-01f, 4.733005e-01f,
+ 4.728037e-01f, 4.723024e-01f, 4.717967e-01f, 4.712866e-01f,
+ 4.707720e-01f, 4.702530e-01f, 4.697296e-01f, 4.692018e-01f,
+ 4.686695e-01f, 4.681328e-01f, 4.675918e-01f, 4.670463e-01f,
+ 4.664964e-01f, 4.659421e-01f, 4.653835e-01f, 4.648204e-01f,
+ 4.642530e-01f, 4.636813e-01f, 4.631051e-01f, 4.625246e-01f,
+ 4.619398e-01f, 4.613506e-01f, 4.607570e-01f, 4.601591e-01f,
+ 4.595569e-01f, 4.589504e-01f, 4.583395e-01f, 4.577244e-01f,
+ 4.571049e-01f, 4.564811e-01f, 4.558530e-01f, 4.552206e-01f,
+ 4.545840e-01f, 4.539431e-01f, 4.532979e-01f, 4.526484e-01f,
+ 4.519946e-01f, 4.513367e-01f, 4.506744e-01f, 4.500079e-01f,
+ 4.493372e-01f, 4.486623e-01f, 4.479831e-01f, 4.472997e-01f,
+ 4.466122e-01f, 4.459204e-01f, 4.452244e-01f, 4.445242e-01f,
+ 4.438198e-01f, 4.431113e-01f, 4.423985e-01f, 4.416817e-01f,
+ 4.409606e-01f, 4.402354e-01f, 4.395061e-01f, 4.387726e-01f,
+ 4.380350e-01f, 4.372933e-01f, 4.365475e-01f, 4.357975e-01f,
+ 4.350435e-01f, 4.342854e-01f, 4.335231e-01f, 4.327568e-01f,
+ 4.319864e-01f, 4.312120e-01f, 4.304335e-01f, 4.296509e-01f,
+ 4.288643e-01f, 4.280737e-01f, 4.272790e-01f, 4.264803e-01f,
+ 4.256776e-01f, 4.248709e-01f, 4.240602e-01f, 4.232455e-01f,
+ 4.224268e-01f, 4.216041e-01f, 4.207775e-01f, 4.199469e-01f,
+ 4.191124e-01f, 4.182739e-01f, 4.174314e-01f, 4.165851e-01f,
+ 4.157348e-01f, 4.148806e-01f, 4.140225e-01f, 4.131605e-01f,
+ 4.122947e-01f, 4.114249e-01f, 4.105513e-01f, 4.096738e-01f,
+ 4.087924e-01f, 4.079072e-01f, 4.070182e-01f, 4.061253e-01f,
+ 4.052286e-01f, 4.043281e-01f, 4.034238e-01f, 4.025157e-01f,
+ 4.016038e-01f, 4.006881e-01f, 3.997686e-01f, 3.988454e-01f,
+ 3.979185e-01f, 3.969877e-01f, 3.960533e-01f, 3.951151e-01f,
+ 3.941732e-01f, 3.932276e-01f, 3.922783e-01f, 3.913253e-01f,
+ 3.903686e-01f, 3.894083e-01f, 3.884442e-01f, 3.874766e-01f,
+ 3.865052e-01f, 3.855303e-01f, 3.845517e-01f, 3.835695e-01f,
+ 3.825836e-01f, 3.815942e-01f, 3.806012e-01f, 3.796046e-01f,
+ 3.786044e-01f, 3.776007e-01f, 3.765934e-01f, 3.755826e-01f,
+ 3.745682e-01f, 3.735503e-01f, 3.725289e-01f, 3.715040e-01f,
+ 3.704756e-01f, 3.694437e-01f, 3.684083e-01f, 3.673694e-01f,
+ 3.663271e-01f, 3.652814e-01f, 3.642322e-01f, 3.631796e-01f,
+ 3.621235e-01f, 3.610641e-01f, 3.600013e-01f, 3.589350e-01f,
+ 3.578654e-01f, 3.567924e-01f, 3.557161e-01f, 3.546364e-01f,
+ 3.535534e-01f, 3.524670e-01f, 3.513774e-01f, 3.502844e-01f,
+ 3.491881e-01f, 3.480886e-01f, 3.469857e-01f, 3.458796e-01f,
+ 3.447703e-01f, 3.436577e-01f, 3.425418e-01f, 3.414228e-01f,
+ 3.403005e-01f, 3.391750e-01f, 3.380464e-01f, 3.369145e-01f,
+ 3.357795e-01f, 3.346413e-01f, 3.335000e-01f, 3.323555e-01f,
+ 3.312079e-01f, 3.300572e-01f, 3.289033e-01f, 3.277464e-01f,
+ 3.265864e-01f, 3.254233e-01f, 3.242572e-01f, 3.230880e-01f,
+ 3.219158e-01f, 3.207405e-01f, 3.195622e-01f, 3.183809e-01f,
+ 3.171966e-01f, 3.160094e-01f, 3.148191e-01f, 3.136259e-01f,
+ 3.124297e-01f, 3.112306e-01f, 3.100286e-01f, 3.088237e-01f,
+ 3.076158e-01f, 3.064050e-01f, 3.051914e-01f, 3.039749e-01f,
+ 3.027555e-01f, 3.015333e-01f, 3.003082e-01f, 2.990804e-01f,
+ 2.978497e-01f, 2.966161e-01f, 2.953799e-01f, 2.941408e-01f,
+ 2.928989e-01f, 2.916543e-01f, 2.904070e-01f, 2.891569e-01f,
+ 2.879041e-01f, 2.866486e-01f, 2.853904e-01f, 2.841295e-01f,
+ 2.828659e-01f, 2.815997e-01f, 2.803308e-01f, 2.790593e-01f,
+ 2.777851e-01f, 2.765084e-01f, 2.752290e-01f, 2.739470e-01f,
+ 2.726625e-01f, 2.713754e-01f, 2.700857e-01f, 2.687935e-01f,
+ 2.674988e-01f, 2.662016e-01f, 2.649018e-01f, 2.635996e-01f,
+ 2.622948e-01f, 2.609876e-01f, 2.596780e-01f, 2.583659e-01f,
+ 2.570514e-01f, 2.557344e-01f, 2.544151e-01f, 2.530933e-01f,
+ 2.517692e-01f, 2.504427e-01f, 2.491138e-01f, 2.477826e-01f,
+ 2.464491e-01f, 2.451132e-01f, 2.437751e-01f, 2.424346e-01f,
+ 2.410919e-01f, 2.397469e-01f, 2.383996e-01f, 2.370501e-01f,
+ 2.356984e-01f, 2.343444e-01f, 2.329882e-01f, 2.316299e-01f,
+ 2.302694e-01f, 2.289067e-01f, 2.275418e-01f, 2.261748e-01f,
+ 2.248057e-01f, 2.234344e-01f, 2.220611e-01f, 2.206856e-01f,
+ 2.193081e-01f, 2.179285e-01f, 2.165469e-01f, 2.151632e-01f,
+ 2.137775e-01f, 2.123898e-01f, 2.110001e-01f, 2.096084e-01f,
+ 2.082148e-01f, 2.068192e-01f, 2.054216e-01f, 2.040221e-01f,
+ 2.026207e-01f, 2.012173e-01f, 1.998121e-01f, 1.984050e-01f,
+ 1.969960e-01f, 1.955852e-01f, 1.941725e-01f, 1.927580e-01f,
+ 1.913417e-01f, 1.899236e-01f, 1.885037e-01f, 1.870820e-01f,
+ 1.856586e-01f, 1.842334e-01f, 1.828065e-01f, 1.813779e-01f,
+ 1.799475e-01f, 1.785155e-01f, 1.770818e-01f, 1.756464e-01f,
+ 1.742093e-01f, 1.727707e-01f, 1.713304e-01f, 1.698884e-01f,
+ 1.684449e-01f, 1.669998e-01f, 1.655532e-01f, 1.641049e-01f,
+ 1.626551e-01f, 1.612038e-01f, 1.597510e-01f, 1.582967e-01f,
+ 1.568409e-01f, 1.553836e-01f, 1.539248e-01f, 1.524646e-01f,
+ 1.510030e-01f, 1.495399e-01f, 1.480754e-01f, 1.466096e-01f,
+ 1.451423e-01f, 1.436737e-01f, 1.422038e-01f, 1.407325e-01f,
+ 1.392598e-01f, 1.377859e-01f, 1.363107e-01f, 1.348342e-01f,
+ 1.333564e-01f, 1.318773e-01f, 1.303971e-01f, 1.289156e-01f,
+ 1.274328e-01f, 1.259489e-01f, 1.244638e-01f, 1.229775e-01f,
+ 1.214901e-01f, 1.200015e-01f, 1.185118e-01f, 1.170210e-01f,
+ 1.155291e-01f, 1.140360e-01f, 1.125420e-01f, 1.110468e-01f,
+ 1.095506e-01f, 1.080534e-01f, 1.065552e-01f, 1.050559e-01f,
+ 1.035557e-01f, 1.020545e-01f, 1.005523e-01f, 9.904921e-02f,
+ 9.754516e-02f, 9.604020e-02f, 9.453433e-02f, 9.302758e-02f,
+ 9.151994e-02f, 9.001145e-02f, 8.850211e-02f, 8.699194e-02f,
+ 8.548094e-02f, 8.396915e-02f, 8.245656e-02f, 8.094320e-02f,
+ 7.942907e-02f, 7.791420e-02f, 7.639859e-02f, 7.488227e-02f,
+ 7.336524e-02f, 7.184752e-02f, 7.032912e-02f, 6.881006e-02f,
+ 6.729035e-02f, 6.577001e-02f, 6.424906e-02f, 6.272749e-02f,
+ 6.120534e-02f, 5.968261e-02f, 5.815932e-02f, 5.663548e-02f,
+ 5.511110e-02f, 5.358621e-02f, 5.206082e-02f, 5.053493e-02f,
+ 4.900857e-02f, 4.748175e-02f, 4.595448e-02f, 4.442678e-02f,
+ 4.289866e-02f, 4.137013e-02f, 3.984122e-02f, 3.831193e-02f,
+ 3.678228e-02f, 3.525229e-02f, 3.372196e-02f, 3.219132e-02f,
+ 3.066037e-02f, 2.912913e-02f, 2.759762e-02f, 2.606585e-02f,
+ 2.453384e-02f, 2.300159e-02f, 2.146913e-02f, 1.993646e-02f,
+ 1.840361e-02f, 1.687059e-02f, 1.533740e-02f, 1.380407e-02f,
+ 1.227061e-02f, 1.073704e-02f, 9.203365e-03f, 7.669603e-03f,
+ 6.135769e-03f, 4.601877e-03f, 3.067942e-03f, 1.533978e-03f};
+static const int AUP_FFTW_g_ip4096[] = {
+ 1024, 1024, 0, 16, 0, 64, 32, 96, 0, 256, 128,
+ 384, 64, 320, 192, 448, 0, 1024, 512, 1536, 256, 1280,
+ 768, 1792, 128, 1152, 640, 1664, 384, 1408, 896, 1920};
+static const float AUP_FFTW_g_w4096[] = {
+ 1.000000e+00f, 7.071068e-01f, 5.000024e-01f, 5.000212e-01f,
+ 9.999812e-01f, 6.135885e-03f, 9.998306e-01f, -1.840673e-02f,
+ 9.999247e-01f, 1.227154e-02f, 9.993224e-01f, -3.680722e-02f,
+ 9.998306e-01f, 1.840673e-02f, 9.984756e-01f, -5.519524e-02f,
+ 9.996988e-01f, 2.454123e-02f, 9.972905e-01f, -7.356456e-02f,
+ 9.995294e-01f, 3.067480e-02f, 9.957674e-01f, -9.190896e-02f,
+ 9.993224e-01f, 3.680722e-02f, 9.939070e-01f, -1.102222e-01f,
+ 9.990777e-01f, 4.293826e-02f, 9.917098e-01f, -1.284981e-01f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.984756e-01f, 5.519524e-02f, 9.863081e-01f, -1.649131e-01f,
+ 9.981181e-01f, 6.132074e-02f, 9.831055e-01f, -1.830399e-01f,
+ 9.977231e-01f, 6.744392e-02f, 9.795698e-01f, -2.011046e-01f,
+ 9.972905e-01f, 7.356456e-02f, 9.757021e-01f, -2.191012e-01f,
+ 9.968203e-01f, 7.968244e-02f, 9.715039e-01f, -2.370236e-01f,
+ 9.963126e-01f, 8.579731e-02f, 9.669765e-01f, -2.548657e-01f,
+ 9.957674e-01f, 9.190896e-02f, 9.621214e-01f, -2.726214e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.945646e-01f, 1.041216e-01f, 9.514350e-01f, -3.078496e-01f,
+ 9.939070e-01f, 1.102222e-01f, 9.456073e-01f, -3.253103e-01f,
+ 9.932119e-01f, 1.163186e-01f, 9.394592e-01f, -3.426607e-01f,
+ 9.924795e-01f, 1.224107e-01f, 9.329928e-01f, -3.598950e-01f,
+ 9.917098e-01f, 1.284981e-01f, 9.262102e-01f, -3.770074e-01f,
+ 9.909026e-01f, 1.345807e-01f, 9.191139e-01f, -3.939920e-01f,
+ 9.900582e-01f, 1.406582e-01f, 9.117060e-01f, -4.108432e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.882576e-01f, 1.527972e-01f, 8.959662e-01f, -4.441221e-01f,
+ 9.873014e-01f, 1.588581e-01f, 8.876396e-01f, -4.605387e-01f,
+ 9.863081e-01f, 1.649131e-01f, 8.790122e-01f, -4.767992e-01f,
+ 9.852776e-01f, 1.709619e-01f, 8.700870e-01f, -4.928982e-01f,
+ 9.842101e-01f, 1.770042e-01f, 8.608669e-01f, -5.088301e-01f,
+ 9.831055e-01f, 1.830399e-01f, 8.513552e-01f, -5.245897e-01f,
+ 9.819639e-01f, 1.890687e-01f, 8.415550e-01f, -5.401715e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.795698e-01f, 2.011046e-01f, 8.211025e-01f, -5.707807e-01f,
+ 9.783174e-01f, 2.071114e-01f, 8.104572e-01f, -5.857979e-01f,
+ 9.770281e-01f, 2.131103e-01f, 7.995373e-01f, -6.006165e-01f,
+ 9.757021e-01f, 2.191012e-01f, 7.883464e-01f, -6.152316e-01f,
+ 9.743394e-01f, 2.250839e-01f, 7.768885e-01f, -6.296382e-01f,
+ 9.729400e-01f, 2.310581e-01f, 7.651673e-01f, -6.438315e-01f,
+ 9.715039e-01f, 2.370236e-01f, 7.531868e-01f, -6.578067e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.685221e-01f, 2.489276e-01f, 7.284644e-01f, -6.850837e-01f,
+ 9.669765e-01f, 2.548657e-01f, 7.157308e-01f, -6.983762e-01f,
+ 9.653944e-01f, 2.607941e-01f, 7.027547e-01f, -7.114322e-01f,
+ 9.637761e-01f, 2.667128e-01f, 6.895405e-01f, -7.242471e-01f,
+ 9.621214e-01f, 2.726214e-01f, 6.760927e-01f, -7.368166e-01f,
+ 9.604305e-01f, 2.785197e-01f, 6.624158e-01f, -7.491364e-01f,
+ 9.587035e-01f, 2.844075e-01f, 6.485144e-01f, -7.612024e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.551412e-01f, 2.961509e-01f, 6.200572e-01f, -7.845566e-01f,
+ 9.533060e-01f, 3.020059e-01f, 6.055110e-01f, -7.958369e-01f,
+ 9.514350e-01f, 3.078496e-01f, 5.907597e-01f, -8.068476e-01f,
+ 9.495282e-01f, 3.136817e-01f, 5.758082e-01f, -8.175848e-01f,
+ 9.475856e-01f, 3.195020e-01f, 5.606616e-01f, -8.280450e-01f,
+ 9.456073e-01f, 3.253103e-01f, 5.453250e-01f, -8.382247e-01f,
+ 9.435935e-01f, 3.311063e-01f, 5.298036e-01f, -8.481203e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.394592e-01f, 3.426607e-01f, 4.982277e-01f, -8.670462e-01f,
+ 9.373390e-01f, 3.484187e-01f, 4.821838e-01f, -8.760701e-01f,
+ 9.351835e-01f, 3.541635e-01f, 4.659765e-01f, -8.847971e-01f,
+ 9.329928e-01f, 3.598950e-01f, 4.496113e-01f, -8.932243e-01f,
+ 9.307670e-01f, 3.656130e-01f, 4.330938e-01f, -9.013488e-01f,
+ 9.285061e-01f, 3.713172e-01f, 4.164296e-01f, -9.091680e-01f,
+ 9.262102e-01f, 3.770074e-01f, 3.996242e-01f, -9.166791e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.215140e-01f, 3.883450e-01f, 3.656130e-01f, -9.307670e-01f,
+ 9.191139e-01f, 3.939920e-01f, 3.484187e-01f, -9.373390e-01f,
+ 9.166791e-01f, 3.996242e-01f, 3.311063e-01f, -9.435935e-01f,
+ 9.142098e-01f, 4.052413e-01f, 3.136817e-01f, -9.495282e-01f,
+ 9.117060e-01f, 4.108432e-01f, 2.961509e-01f, -9.551412e-01f,
+ 9.091680e-01f, 4.164296e-01f, 2.785197e-01f, -9.604305e-01f,
+ 9.065957e-01f, 4.220003e-01f, 2.607941e-01f, -9.653944e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 9.013488e-01f, 4.330938e-01f, 2.250839e-01f, -9.743394e-01f,
+ 8.986745e-01f, 4.386162e-01f, 2.071114e-01f, -9.783174e-01f,
+ 8.959662e-01f, 4.441221e-01f, 1.890687e-01f, -9.819639e-01f,
+ 8.932243e-01f, 4.496113e-01f, 1.709619e-01f, -9.852776e-01f,
+ 8.904487e-01f, 4.550836e-01f, 1.527972e-01f, -9.882576e-01f,
+ 8.876396e-01f, 4.605387e-01f, 1.345807e-01f, -9.909026e-01f,
+ 8.847971e-01f, 4.659765e-01f, 1.163186e-01f, -9.932119e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.790122e-01f, 4.767992e-01f, 7.968244e-02f, -9.968203e-01f,
+ 8.760701e-01f, 4.821838e-01f, 6.132074e-02f, -9.981181e-01f,
+ 8.730950e-01f, 4.875502e-01f, 4.293826e-02f, -9.990777e-01f,
+ 8.700870e-01f, 4.928982e-01f, 2.454123e-02f, -9.996988e-01f,
+ 8.670462e-01f, 4.982277e-01f, 6.135885e-03f, -9.999812e-01f,
+ 8.639729e-01f, 5.035384e-01f, -1.227154e-02f, -9.999247e-01f,
+ 8.608669e-01f, 5.088301e-01f, -3.067480e-02f, -9.995294e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.545580e-01f, 5.193560e-01f, -6.744392e-02f, -9.977231e-01f,
+ 8.513552e-01f, 5.245897e-01f, -8.579731e-02f, -9.963126e-01f,
+ 8.481203e-01f, 5.298036e-01f, -1.041216e-01f, -9.945646e-01f,
+ 8.448536e-01f, 5.349976e-01f, -1.224107e-01f, -9.924795e-01f,
+ 8.415550e-01f, 5.401715e-01f, -1.406582e-01f, -9.900582e-01f,
+ 8.382247e-01f, 5.453250e-01f, -1.588581e-01f, -9.873014e-01f,
+ 8.348629e-01f, 5.504580e-01f, -1.770042e-01f, -9.842101e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.280450e-01f, 5.606616e-01f, -2.131103e-01f, -9.770281e-01f,
+ 8.245893e-01f, 5.657318e-01f, -2.310581e-01f, -9.729400e-01f,
+ 8.211025e-01f, 5.707807e-01f, -2.489276e-01f, -9.685221e-01f,
+ 8.175848e-01f, 5.758082e-01f, -2.667128e-01f, -9.637761e-01f,
+ 8.140363e-01f, 5.808140e-01f, -2.844075e-01f, -9.587035e-01f,
+ 8.104572e-01f, 5.857979e-01f, -3.020059e-01f, -9.533060e-01f,
+ 8.068476e-01f, 5.907597e-01f, -3.195020e-01f, -9.475856e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.995373e-01f, 6.006165e-01f, -3.541635e-01f, -9.351835e-01f,
+ 7.958369e-01f, 6.055110e-01f, -3.713172e-01f, -9.285061e-01f,
+ 7.921066e-01f, 6.103828e-01f, -3.883450e-01f, -9.215140e-01f,
+ 7.883464e-01f, 6.152316e-01f, -4.052413e-01f, -9.142098e-01f,
+ 7.845566e-01f, 6.200572e-01f, -4.220003e-01f, -9.065957e-01f,
+ 7.807372e-01f, 6.248595e-01f, -4.386162e-01f, -8.986745e-01f,
+ 7.768885e-01f, 6.296382e-01f, -4.550836e-01f, -8.904487e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.691033e-01f, 6.391244e-01f, -4.875502e-01f, -8.730950e-01f,
+ 7.651673e-01f, 6.438315e-01f, -5.035384e-01f, -8.639729e-01f,
+ 7.612024e-01f, 6.485144e-01f, -5.193560e-01f, -8.545580e-01f,
+ 7.572088e-01f, 6.531728e-01f, -5.349976e-01f, -8.448536e-01f,
+ 7.531868e-01f, 6.578067e-01f, -5.504580e-01f, -8.348629e-01f,
+ 7.491364e-01f, 6.624158e-01f, -5.657318e-01f, -8.245893e-01f,
+ 7.450578e-01f, 6.669999e-01f, -5.808140e-01f, -8.140363e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 7.368166e-01f, 6.760927e-01f, -6.103828e-01f, -7.921066e-01f,
+ 7.326543e-01f, 6.806010e-01f, -6.248595e-01f, -7.807372e-01f,
+ 7.284644e-01f, 6.850837e-01f, -6.391244e-01f, -7.691033e-01f,
+ 7.242471e-01f, 6.895405e-01f, -6.531728e-01f, -7.572088e-01f,
+ 7.200025e-01f, 6.939715e-01f, -6.669999e-01f, -7.450578e-01f,
+ 7.157308e-01f, 6.983762e-01f, -6.806010e-01f, -7.326543e-01f,
+ 7.114322e-01f, 7.027547e-01f, -6.939715e-01f, -7.200025e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.000094e-01f, 5.000847e-01f,
+ 9.999247e-01f, 1.227154e-02f, 9.993224e-01f, -3.680722e-02f,
+ 9.996988e-01f, 2.454123e-02f, 9.972905e-01f, -7.356456e-02f,
+ 9.993224e-01f, 3.680722e-02f, 9.939070e-01f, -1.102222e-01f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.981181e-01f, 6.132074e-02f, 9.831055e-01f, -1.830399e-01f,
+ 9.972905e-01f, 7.356456e-02f, 9.757021e-01f, -2.191012e-01f,
+ 9.963126e-01f, 8.579731e-02f, 9.669765e-01f, -2.548657e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.939070e-01f, 1.102222e-01f, 9.456073e-01f, -3.253103e-01f,
+ 9.924795e-01f, 1.224107e-01f, 9.329928e-01f, -3.598950e-01f,
+ 9.909026e-01f, 1.345807e-01f, 9.191139e-01f, -3.939920e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.873014e-01f, 1.588581e-01f, 8.876396e-01f, -4.605387e-01f,
+ 9.852776e-01f, 1.709619e-01f, 8.700870e-01f, -4.928982e-01f,
+ 9.831055e-01f, 1.830399e-01f, 8.513552e-01f, -5.245897e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.783174e-01f, 2.071114e-01f, 8.104572e-01f, -5.857979e-01f,
+ 9.757021e-01f, 2.191012e-01f, 7.883464e-01f, -6.152316e-01f,
+ 9.729400e-01f, 2.310581e-01f, 7.651673e-01f, -6.438315e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.669765e-01f, 2.548657e-01f, 7.157308e-01f, -6.983762e-01f,
+ 9.637761e-01f, 2.667128e-01f, 6.895405e-01f, -7.242471e-01f,
+ 9.604305e-01f, 2.785197e-01f, 6.624158e-01f, -7.491364e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.533060e-01f, 3.020059e-01f, 6.055110e-01f, -7.958369e-01f,
+ 9.495282e-01f, 3.136817e-01f, 5.758082e-01f, -8.175848e-01f,
+ 9.456073e-01f, 3.253103e-01f, 5.453250e-01f, -8.382247e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.373390e-01f, 3.484187e-01f, 4.821838e-01f, -8.760701e-01f,
+ 9.329928e-01f, 3.598950e-01f, 4.496113e-01f, -8.932243e-01f,
+ 9.285061e-01f, 3.713172e-01f, 4.164296e-01f, -9.091680e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.191139e-01f, 3.939920e-01f, 3.484187e-01f, -9.373390e-01f,
+ 9.142098e-01f, 4.052413e-01f, 3.136817e-01f, -9.495282e-01f,
+ 9.091680e-01f, 4.164296e-01f, 2.785197e-01f, -9.604305e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 8.986745e-01f, 4.386162e-01f, 2.071114e-01f, -9.783174e-01f,
+ 8.932243e-01f, 4.496113e-01f, 1.709619e-01f, -9.852776e-01f,
+ 8.876396e-01f, 4.605387e-01f, 1.345807e-01f, -9.909026e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.760701e-01f, 4.821838e-01f, 6.132074e-02f, -9.981181e-01f,
+ 8.700870e-01f, 4.928982e-01f, 2.454123e-02f, -9.996988e-01f,
+ 8.639729e-01f, 5.035384e-01f, -1.227154e-02f, -9.999247e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.513552e-01f, 5.245897e-01f, -8.579731e-02f, -9.963126e-01f,
+ 8.448536e-01f, 5.349976e-01f, -1.224107e-01f, -9.924795e-01f,
+ 8.382247e-01f, 5.453250e-01f, -1.588581e-01f, -9.873014e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.245893e-01f, 5.657318e-01f, -2.310581e-01f, -9.729400e-01f,
+ 8.175848e-01f, 5.758082e-01f, -2.667128e-01f, -9.637761e-01f,
+ 8.104572e-01f, 5.857979e-01f, -3.020059e-01f, -9.533060e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.958369e-01f, 6.055110e-01f, -3.713172e-01f, -9.285061e-01f,
+ 7.883464e-01f, 6.152316e-01f, -4.052413e-01f, -9.142098e-01f,
+ 7.807372e-01f, 6.248595e-01f, -4.386162e-01f, -8.986745e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.651673e-01f, 6.438315e-01f, -5.035384e-01f, -8.639729e-01f,
+ 7.572088e-01f, 6.531728e-01f, -5.349976e-01f, -8.448536e-01f,
+ 7.491364e-01f, 6.624158e-01f, -5.657318e-01f, -8.245893e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 7.326543e-01f, 6.806010e-01f, -6.248595e-01f, -7.807372e-01f,
+ 7.242471e-01f, 6.895405e-01f, -6.531728e-01f, -7.572088e-01f,
+ 7.157308e-01f, 6.983762e-01f, -6.806010e-01f, -7.326543e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.000377e-01f, 5.003390e-01f,
+ 9.996988e-01f, 2.454123e-02f, 9.972905e-01f, -7.356456e-02f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.972905e-01f, 7.356456e-02f, 9.757021e-01f, -2.191012e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.924795e-01f, 1.224107e-01f, 9.329928e-01f, -3.598950e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.852776e-01f, 1.709619e-01f, 8.700870e-01f, -4.928982e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.757021e-01f, 2.191012e-01f, 7.883464e-01f, -6.152316e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.637761e-01f, 2.667128e-01f, 6.895405e-01f, -7.242471e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.495282e-01f, 3.136817e-01f, 5.758082e-01f, -8.175848e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.329928e-01f, 3.598950e-01f, 4.496113e-01f, -8.932243e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.142098e-01f, 4.052413e-01f, 3.136817e-01f, -9.495282e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 8.932243e-01f, 4.496113e-01f, 1.709619e-01f, -9.852776e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.700870e-01f, 4.928982e-01f, 2.454123e-02f, -9.996988e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.448536e-01f, 5.349976e-01f, -1.224107e-01f, -9.924795e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.175848e-01f, 5.758082e-01f, -2.667128e-01f, -9.637761e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.883464e-01f, 6.152316e-01f, -4.052413e-01f, -9.142098e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.572088e-01f, 6.531728e-01f, -5.349976e-01f, -8.448536e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 7.242471e-01f, 6.895405e-01f, -6.531728e-01f, -7.572088e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.001506e-01f, 5.013585e-01f,
+ 9.987955e-01f, 4.906767e-02f, 9.891765e-01f, -1.467305e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.891765e-01f, 1.467305e-01f, 9.039893e-01f, -4.275551e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.700313e-01f, 2.429802e-01f, 7.409511e-01f, -6.715590e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.415441e-01f, 3.368899e-01f, 5.141027e-01f, -8.577286e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 9.039893e-01f, 4.275551e-01f, 2.429802e-01f, -9.700313e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.577286e-01f, 5.141027e-01f, -4.906767e-02f, -9.987955e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 8.032075e-01f, 5.956993e-01f, -3.368899e-01f, -9.415441e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 7.409511e-01f, 6.715590e-01f, -5.956993e-01f, -8.032075e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.006030e-01f, 5.054710e-01f,
+ 9.951847e-01f, 9.801714e-02f, 9.569403e-01f, -2.902847e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.569403e-01f, 2.902847e-01f, 6.343933e-01f, -7.730105e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.819213e-01f, 4.713967e-01f, 9.801714e-02f, -9.951847e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 7.730105e-01f, 6.343933e-01f, -4.713967e-01f, -8.819213e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.024193e-01f, 5.224986e-01f,
+ 9.807853e-01f, 1.950903e-01f, 8.314696e-01f, -5.555702e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 8.314696e-01f, 5.555702e-01f, -1.950903e-01f, -9.807853e-01f,
+ 1.000000e+00f, 7.071068e-01f, 5.097956e-01f, 6.013449e-01f,
+ 9.238795e-01f, 3.826834e-01f, 3.826834e-01f, -9.238795e-01f,
+ 1.000000e+00f, 7.071068e-01f, 9.238795e-01f, 3.826834e-01f,
+ 1.000000e+00f, 7.071068e-01f, 0.000000e+00f, 0.000000e+00f,
+ 7.071068e-01f, 4.999994e-01f, 4.999976e-01f, 4.999947e-01f,
+ 4.999906e-01f, 4.999853e-01f, 4.999788e-01f, 4.999712e-01f,
+ 4.999624e-01f, 4.999524e-01f, 4.999412e-01f, 4.999288e-01f,
+ 4.999153e-01f, 4.999006e-01f, 4.998847e-01f, 4.998676e-01f,
+ 4.998494e-01f, 4.998300e-01f, 4.998094e-01f, 4.997876e-01f,
+ 4.997647e-01f, 4.997406e-01f, 4.997153e-01f, 4.996888e-01f,
+ 4.996612e-01f, 4.996324e-01f, 4.996024e-01f, 4.995712e-01f,
+ 4.995389e-01f, 4.995053e-01f, 4.994706e-01f, 4.994348e-01f,
+ 4.993977e-01f, 4.993595e-01f, 4.993201e-01f, 4.992795e-01f,
+ 4.992378e-01f, 4.991949e-01f, 4.991508e-01f, 4.991055e-01f,
+ 4.990591e-01f, 4.990114e-01f, 4.989626e-01f, 4.989127e-01f,
+ 4.988615e-01f, 4.988092e-01f, 4.987557e-01f, 4.987011e-01f,
+ 4.986452e-01f, 4.985882e-01f, 4.985300e-01f, 4.984707e-01f,
+ 4.984101e-01f, 4.983484e-01f, 4.982856e-01f, 4.982215e-01f,
+ 4.981563e-01f, 4.980899e-01f, 4.980224e-01f, 4.979536e-01f,
+ 4.978837e-01f, 4.978126e-01f, 4.977404e-01f, 4.976670e-01f,
+ 4.975924e-01f, 4.975166e-01f, 4.974397e-01f, 4.973616e-01f,
+ 4.972823e-01f, 4.972018e-01f, 4.971202e-01f, 4.970374e-01f,
+ 4.969535e-01f, 4.968684e-01f, 4.967821e-01f, 4.966946e-01f,
+ 4.966060e-01f, 4.965162e-01f, 4.964252e-01f, 4.963331e-01f,
+ 4.962398e-01f, 4.961453e-01f, 4.960497e-01f, 4.959529e-01f,
+ 4.958549e-01f, 4.957557e-01f, 4.956554e-01f, 4.955540e-01f,
+ 4.954513e-01f, 4.953475e-01f, 4.952425e-01f, 4.951364e-01f,
+ 4.950291e-01f, 4.949206e-01f, 4.948110e-01f, 4.947002e-01f,
+ 4.945883e-01f, 4.944751e-01f, 4.943608e-01f, 4.942454e-01f,
+ 4.941288e-01f, 4.940110e-01f, 4.938921e-01f, 4.937720e-01f,
+ 4.936507e-01f, 4.935283e-01f, 4.934047e-01f, 4.932800e-01f,
+ 4.931540e-01f, 4.930270e-01f, 4.928988e-01f, 4.927694e-01f,
+ 4.926388e-01f, 4.925071e-01f, 4.923743e-01f, 4.922402e-01f,
+ 4.921050e-01f, 4.919687e-01f, 4.918312e-01f, 4.916926e-01f,
+ 4.915527e-01f, 4.914118e-01f, 4.912697e-01f, 4.911264e-01f,
+ 4.909819e-01f, 4.908363e-01f, 4.906896e-01f, 4.905417e-01f,
+ 4.903926e-01f, 4.902424e-01f, 4.900911e-01f, 4.899386e-01f,
+ 4.897849e-01f, 4.896301e-01f, 4.894741e-01f, 4.893170e-01f,
+ 4.891587e-01f, 4.889993e-01f, 4.888387e-01f, 4.886770e-01f,
+ 4.885141e-01f, 4.883500e-01f, 4.881849e-01f, 4.880185e-01f,
+ 4.878511e-01f, 4.876824e-01f, 4.875127e-01f, 4.873418e-01f,
+ 4.871697e-01f, 4.869965e-01f, 4.868221e-01f, 4.866466e-01f,
+ 4.864700e-01f, 4.862922e-01f, 4.861132e-01f, 4.859332e-01f,
+ 4.857519e-01f, 4.855696e-01f, 4.853861e-01f, 4.852014e-01f,
+ 4.850156e-01f, 4.848287e-01f, 4.846406e-01f, 4.844514e-01f,
+ 4.842610e-01f, 4.840696e-01f, 4.838769e-01f, 4.836831e-01f,
+ 4.834882e-01f, 4.832922e-01f, 4.830950e-01f, 4.828967e-01f,
+ 4.826972e-01f, 4.824966e-01f, 4.822949e-01f, 4.820920e-01f,
+ 4.818880e-01f, 4.816829e-01f, 4.814766e-01f, 4.812692e-01f,
+ 4.810607e-01f, 4.808510e-01f, 4.806402e-01f, 4.804283e-01f,
+ 4.802153e-01f, 4.800011e-01f, 4.797858e-01f, 4.795693e-01f,
+ 4.793517e-01f, 4.791330e-01f, 4.789132e-01f, 4.786923e-01f,
+ 4.784702e-01f, 4.782470e-01f, 4.780226e-01f, 4.777972e-01f,
+ 4.775706e-01f, 4.773429e-01f, 4.771140e-01f, 4.768841e-01f,
+ 4.766530e-01f, 4.764208e-01f, 4.761875e-01f, 4.759531e-01f,
+ 4.757175e-01f, 4.754808e-01f, 4.752430e-01f, 4.750041e-01f,
+ 4.747641e-01f, 4.745229e-01f, 4.742807e-01f, 4.740373e-01f,
+ 4.737928e-01f, 4.735472e-01f, 4.733005e-01f, 4.730526e-01f,
+ 4.728037e-01f, 4.725536e-01f, 4.723024e-01f, 4.720501e-01f,
+ 4.717967e-01f, 4.715422e-01f, 4.712866e-01f, 4.710299e-01f,
+ 4.707720e-01f, 4.705131e-01f, 4.702530e-01f, 4.699919e-01f,
+ 4.697296e-01f, 4.694662e-01f, 4.692018e-01f, 4.689362e-01f,
+ 4.686695e-01f, 4.684017e-01f, 4.681328e-01f, 4.678628e-01f,
+ 4.675918e-01f, 4.673196e-01f, 4.670463e-01f, 4.667719e-01f,
+ 4.664964e-01f, 4.662198e-01f, 4.659421e-01f, 4.656634e-01f,
+ 4.653835e-01f, 4.651025e-01f, 4.648204e-01f, 4.645373e-01f,
+ 4.642530e-01f, 4.639677e-01f, 4.636813e-01f, 4.633937e-01f,
+ 4.631051e-01f, 4.628154e-01f, 4.625246e-01f, 4.622327e-01f,
+ 4.619398e-01f, 4.616457e-01f, 4.613506e-01f, 4.610543e-01f,
+ 4.607570e-01f, 4.604586e-01f, 4.601591e-01f, 4.598586e-01f,
+ 4.595569e-01f, 4.592542e-01f, 4.589504e-01f, 4.586455e-01f,
+ 4.583395e-01f, 4.580325e-01f, 4.577244e-01f, 4.574152e-01f,
+ 4.571049e-01f, 4.567935e-01f, 4.564811e-01f, 4.561676e-01f,
+ 4.558530e-01f, 4.555374e-01f, 4.552206e-01f, 4.549029e-01f,
+ 4.545840e-01f, 4.542641e-01f, 4.539431e-01f, 4.536210e-01f,
+ 4.532979e-01f, 4.529736e-01f, 4.526484e-01f, 4.523220e-01f,
+ 4.519946e-01f, 4.516662e-01f, 4.513367e-01f, 4.510061e-01f,
+ 4.506744e-01f, 4.503417e-01f, 4.500079e-01f, 4.496731e-01f,
+ 4.493372e-01f, 4.490003e-01f, 4.486623e-01f, 4.483232e-01f,
+ 4.479831e-01f, 4.476420e-01f, 4.472997e-01f, 4.469565e-01f,
+ 4.466122e-01f, 4.462668e-01f, 4.459204e-01f, 4.455729e-01f,
+ 4.452244e-01f, 4.448748e-01f, 4.445242e-01f, 4.441725e-01f,
+ 4.438198e-01f, 4.434661e-01f, 4.431113e-01f, 4.427554e-01f,
+ 4.423985e-01f, 4.420406e-01f, 4.416817e-01f, 4.413217e-01f,
+ 4.409606e-01f, 4.405986e-01f, 4.402354e-01f, 4.398713e-01f,
+ 4.395061e-01f, 4.391399e-01f, 4.387726e-01f, 4.384044e-01f,
+ 4.380350e-01f, 4.376647e-01f, 4.372933e-01f, 4.369209e-01f,
+ 4.365475e-01f, 4.361730e-01f, 4.357975e-01f, 4.354210e-01f,
+ 4.350435e-01f, 4.346649e-01f, 4.342854e-01f, 4.339047e-01f,
+ 4.335231e-01f, 4.331405e-01f, 4.327568e-01f, 4.323721e-01f,
+ 4.319864e-01f, 4.315997e-01f, 4.312120e-01f, 4.308232e-01f,
+ 4.304335e-01f, 4.300427e-01f, 4.296509e-01f, 4.292581e-01f,
+ 4.288643e-01f, 4.284695e-01f, 4.280737e-01f, 4.276768e-01f,
+ 4.272790e-01f, 4.268802e-01f, 4.264803e-01f, 4.260795e-01f,
+ 4.256776e-01f, 4.252747e-01f, 4.248709e-01f, 4.244660e-01f,
+ 4.240602e-01f, 4.236533e-01f, 4.232455e-01f, 4.228366e-01f,
+ 4.224268e-01f, 4.220159e-01f, 4.216041e-01f, 4.211913e-01f,
+ 4.207775e-01f, 4.203627e-01f, 4.199469e-01f, 4.195301e-01f,
+ 4.191124e-01f, 4.186936e-01f, 4.182739e-01f, 4.178531e-01f,
+ 4.174314e-01f, 4.170088e-01f, 4.165851e-01f, 4.161604e-01f,
+ 4.157348e-01f, 4.153082e-01f, 4.148806e-01f, 4.144521e-01f,
+ 4.140225e-01f, 4.135920e-01f, 4.131605e-01f, 4.127281e-01f,
+ 4.122947e-01f, 4.118603e-01f, 4.114249e-01f, 4.109886e-01f,
+ 4.105513e-01f, 4.101130e-01f, 4.096738e-01f, 4.092336e-01f,
+ 4.087924e-01f, 4.083503e-01f, 4.079072e-01f, 4.074632e-01f,
+ 4.070182e-01f, 4.065722e-01f, 4.061253e-01f, 4.056774e-01f,
+ 4.052286e-01f, 4.047788e-01f, 4.043281e-01f, 4.038764e-01f,
+ 4.034238e-01f, 4.029702e-01f, 4.025157e-01f, 4.020602e-01f,
+ 4.016038e-01f, 4.011464e-01f, 4.006881e-01f, 4.002288e-01f,
+ 3.997686e-01f, 3.993075e-01f, 3.988454e-01f, 3.983824e-01f,
+ 3.979185e-01f, 3.974536e-01f, 3.969877e-01f, 3.965210e-01f,
+ 3.960533e-01f, 3.955847e-01f, 3.951151e-01f, 3.946446e-01f,
+ 3.941732e-01f, 3.937009e-01f, 3.932276e-01f, 3.927534e-01f,
+ 3.922783e-01f, 3.918023e-01f, 3.913253e-01f, 3.908474e-01f,
+ 3.903686e-01f, 3.898889e-01f, 3.894083e-01f, 3.889267e-01f,
+ 3.884442e-01f, 3.879608e-01f, 3.874766e-01f, 3.869913e-01f,
+ 3.865052e-01f, 3.860182e-01f, 3.855303e-01f, 3.850414e-01f,
+ 3.845517e-01f, 3.840610e-01f, 3.835695e-01f, 3.830770e-01f,
+ 3.825836e-01f, 3.820894e-01f, 3.815942e-01f, 3.810981e-01f,
+ 3.806012e-01f, 3.801033e-01f, 3.796046e-01f, 3.791050e-01f,
+ 3.786044e-01f, 3.781030e-01f, 3.776007e-01f, 3.770975e-01f,
+ 3.765934e-01f, 3.760884e-01f, 3.755826e-01f, 3.750758e-01f,
+ 3.745682e-01f, 3.740597e-01f, 3.735503e-01f, 3.730400e-01f,
+ 3.725289e-01f, 3.720169e-01f, 3.715040e-01f, 3.709902e-01f,
+ 3.704756e-01f, 3.699600e-01f, 3.694437e-01f, 3.689264e-01f,
+ 3.684083e-01f, 3.678893e-01f, 3.673694e-01f, 3.668487e-01f,
+ 3.663271e-01f, 3.658047e-01f, 3.652814e-01f, 3.647572e-01f,
+ 3.642322e-01f, 3.637063e-01f, 3.631796e-01f, 3.626520e-01f,
+ 3.621235e-01f, 3.615942e-01f, 3.610641e-01f, 3.605331e-01f,
+ 3.600013e-01f, 3.594686e-01f, 3.589350e-01f, 3.584006e-01f,
+ 3.578654e-01f, 3.573293e-01f, 3.567924e-01f, 3.562547e-01f,
+ 3.557161e-01f, 3.551767e-01f, 3.546364e-01f, 3.540953e-01f,
+ 3.535534e-01f, 3.530106e-01f, 3.524670e-01f, 3.519226e-01f,
+ 3.513774e-01f, 3.508313e-01f, 3.502844e-01f, 3.497367e-01f,
+ 3.491881e-01f, 3.486388e-01f, 3.480886e-01f, 3.475376e-01f,
+ 3.469857e-01f, 3.464331e-01f, 3.458796e-01f, 3.453254e-01f,
+ 3.447703e-01f, 3.442144e-01f, 3.436577e-01f, 3.431002e-01f,
+ 3.425418e-01f, 3.419827e-01f, 3.414228e-01f, 3.408620e-01f,
+ 3.403005e-01f, 3.397382e-01f, 3.391750e-01f, 3.386111e-01f,
+ 3.380464e-01f, 3.374808e-01f, 3.369145e-01f, 3.363474e-01f,
+ 3.357795e-01f, 3.352108e-01f, 3.346413e-01f, 3.340710e-01f,
+ 3.335000e-01f, 3.329281e-01f, 3.323555e-01f, 3.317821e-01f,
+ 3.312079e-01f, 3.306329e-01f, 3.300572e-01f, 3.294806e-01f,
+ 3.289033e-01f, 3.283253e-01f, 3.277464e-01f, 3.271668e-01f,
+ 3.265864e-01f, 3.260053e-01f, 3.254233e-01f, 3.248407e-01f,
+ 3.242572e-01f, 3.236730e-01f, 3.230880e-01f, 3.225023e-01f,
+ 3.219158e-01f, 3.213285e-01f, 3.207405e-01f, 3.201517e-01f,
+ 3.195622e-01f, 3.189720e-01f, 3.183809e-01f, 3.177892e-01f,
+ 3.171966e-01f, 3.166034e-01f, 3.160094e-01f, 3.154146e-01f,
+ 3.148191e-01f, 3.142229e-01f, 3.136259e-01f, 3.130282e-01f,
+ 3.124297e-01f, 3.118306e-01f, 3.112306e-01f, 3.106300e-01f,
+ 3.100286e-01f, 3.094265e-01f, 3.088237e-01f, 3.082201e-01f,
+ 3.076158e-01f, 3.070108e-01f, 3.064050e-01f, 3.057986e-01f,
+ 3.051914e-01f, 3.045835e-01f, 3.039749e-01f, 3.033656e-01f,
+ 3.027555e-01f, 3.021448e-01f, 3.015333e-01f, 3.009211e-01f,
+ 3.003082e-01f, 2.996946e-01f, 2.990804e-01f, 2.984654e-01f,
+ 2.978497e-01f, 2.972332e-01f, 2.966161e-01f, 2.959983e-01f,
+ 2.953799e-01f, 2.947607e-01f, 2.941408e-01f, 2.935202e-01f,
+ 2.928989e-01f, 2.922770e-01f, 2.916543e-01f, 2.910310e-01f,
+ 2.904070e-01f, 2.897823e-01f, 2.891569e-01f, 2.885308e-01f,
+ 2.879041e-01f, 2.872767e-01f, 2.866486e-01f, 2.860198e-01f,
+ 2.853904e-01f, 2.847603e-01f, 2.841295e-01f, 2.834980e-01f,
+ 2.828659e-01f, 2.822331e-01f, 2.815997e-01f, 2.809656e-01f,
+ 2.803308e-01f, 2.796954e-01f, 2.790593e-01f, 2.784225e-01f,
+ 2.777851e-01f, 2.771471e-01f, 2.765084e-01f, 2.758690e-01f,
+ 2.752290e-01f, 2.745883e-01f, 2.739470e-01f, 2.733051e-01f,
+ 2.726625e-01f, 2.720193e-01f, 2.713754e-01f, 2.707309e-01f,
+ 2.700857e-01f, 2.694400e-01f, 2.687935e-01f, 2.681465e-01f,
+ 2.674988e-01f, 2.668505e-01f, 2.662016e-01f, 2.655520e-01f,
+ 2.649018e-01f, 2.642510e-01f, 2.635996e-01f, 2.629475e-01f,
+ 2.622948e-01f, 2.616416e-01f, 2.609876e-01f, 2.603331e-01f,
+ 2.596780e-01f, 2.590223e-01f, 2.583659e-01f, 2.577089e-01f,
+ 2.570514e-01f, 2.563932e-01f, 2.557344e-01f, 2.550750e-01f,
+ 2.544151e-01f, 2.537545e-01f, 2.530933e-01f, 2.524316e-01f,
+ 2.517692e-01f, 2.511062e-01f, 2.504427e-01f, 2.497786e-01f,
+ 2.491138e-01f, 2.484485e-01f, 2.477826e-01f, 2.471162e-01f,
+ 2.464491e-01f, 2.457815e-01f, 2.451132e-01f, 2.444444e-01f,
+ 2.437751e-01f, 2.431051e-01f, 2.424346e-01f, 2.417635e-01f,
+ 2.410919e-01f, 2.404197e-01f, 2.397469e-01f, 2.390735e-01f,
+ 2.383996e-01f, 2.377251e-01f, 2.370501e-01f, 2.363745e-01f,
+ 2.356984e-01f, 2.350217e-01f, 2.343444e-01f, 2.336666e-01f,
+ 2.329882e-01f, 2.323093e-01f, 2.316299e-01f, 2.309499e-01f,
+ 2.302694e-01f, 2.295883e-01f, 2.289067e-01f, 2.282245e-01f,
+ 2.275418e-01f, 2.268586e-01f, 2.261748e-01f, 2.254905e-01f,
+ 2.248057e-01f, 2.241203e-01f, 2.234344e-01f, 2.227480e-01f,
+ 2.220611e-01f, 2.213736e-01f, 2.206856e-01f, 2.199971e-01f,
+ 2.193081e-01f, 2.186186e-01f, 2.179285e-01f, 2.172380e-01f,
+ 2.165469e-01f, 2.158553e-01f, 2.151632e-01f, 2.144706e-01f,
+ 2.137775e-01f, 2.130839e-01f, 2.123898e-01f, 2.116952e-01f,
+ 2.110001e-01f, 2.103045e-01f, 2.096084e-01f, 2.089119e-01f,
+ 2.082148e-01f, 2.075172e-01f, 2.068192e-01f, 2.061206e-01f,
+ 2.054216e-01f, 2.047221e-01f, 2.040221e-01f, 2.033216e-01f,
+ 2.026207e-01f, 2.019192e-01f, 2.012173e-01f, 2.005149e-01f,
+ 1.998121e-01f, 1.991088e-01f, 1.984050e-01f, 1.977007e-01f,
+ 1.969960e-01f, 1.962908e-01f, 1.955852e-01f, 1.948791e-01f,
+ 1.941725e-01f, 1.934655e-01f, 1.927580e-01f, 1.920501e-01f,
+ 1.913417e-01f, 1.906329e-01f, 1.899236e-01f, 1.892139e-01f,
+ 1.885037e-01f, 1.877931e-01f, 1.870820e-01f, 1.863705e-01f,
+ 1.856586e-01f, 1.849462e-01f, 1.842334e-01f, 1.835202e-01f,
+ 1.828065e-01f, 1.820924e-01f, 1.813779e-01f, 1.806629e-01f,
+ 1.799475e-01f, 1.792317e-01f, 1.785155e-01f, 1.777988e-01f,
+ 1.770818e-01f, 1.763643e-01f, 1.756464e-01f, 1.749281e-01f,
+ 1.742093e-01f, 1.734902e-01f, 1.727707e-01f, 1.720507e-01f,
+ 1.713304e-01f, 1.706096e-01f, 1.698884e-01f, 1.691669e-01f,
+ 1.684449e-01f, 1.677226e-01f, 1.669998e-01f, 1.662767e-01f,
+ 1.655532e-01f, 1.648292e-01f, 1.641049e-01f, 1.633802e-01f,
+ 1.626551e-01f, 1.619297e-01f, 1.612038e-01f, 1.604776e-01f,
+ 1.597510e-01f, 1.590240e-01f, 1.582967e-01f, 1.575690e-01f,
+ 1.568409e-01f, 1.561124e-01f, 1.553836e-01f, 1.546544e-01f,
+ 1.539248e-01f, 1.531949e-01f, 1.524646e-01f, 1.517340e-01f,
+ 1.510030e-01f, 1.502716e-01f, 1.495399e-01f, 1.488079e-01f,
+ 1.480754e-01f, 1.473427e-01f, 1.466096e-01f, 1.458761e-01f,
+ 1.451423e-01f, 1.444082e-01f, 1.436737e-01f, 1.429389e-01f,
+ 1.422038e-01f, 1.414683e-01f, 1.407325e-01f, 1.399963e-01f,
+ 1.392598e-01f, 1.385230e-01f, 1.377859e-01f, 1.370485e-01f,
+ 1.363107e-01f, 1.355726e-01f, 1.348342e-01f, 1.340954e-01f,
+ 1.333564e-01f, 1.326170e-01f, 1.318773e-01f, 1.311374e-01f,
+ 1.303971e-01f, 1.296565e-01f, 1.289156e-01f, 1.281743e-01f,
+ 1.274328e-01f, 1.266910e-01f, 1.259489e-01f, 1.252065e-01f,
+ 1.244638e-01f, 1.237208e-01f, 1.229775e-01f, 1.222340e-01f,
+ 1.214901e-01f, 1.207459e-01f, 1.200015e-01f, 1.192568e-01f,
+ 1.185118e-01f, 1.177665e-01f, 1.170210e-01f, 1.162752e-01f,
+ 1.155291e-01f, 1.147827e-01f, 1.140360e-01f, 1.132891e-01f,
+ 1.125420e-01f, 1.117945e-01f, 1.110468e-01f, 1.102988e-01f,
+ 1.095506e-01f, 1.088021e-01f, 1.080534e-01f, 1.073044e-01f,
+ 1.065552e-01f, 1.058057e-01f, 1.050559e-01f, 1.043059e-01f,
+ 1.035557e-01f, 1.028052e-01f, 1.020545e-01f, 1.013035e-01f,
+ 1.005523e-01f, 9.980088e-02f, 9.904921e-02f, 9.829730e-02f,
+ 9.754516e-02f, 9.679279e-02f, 9.604020e-02f, 9.528738e-02f,
+ 9.453433e-02f, 9.378106e-02f, 9.302758e-02f, 9.227387e-02f,
+ 9.151994e-02f, 9.076580e-02f, 9.001145e-02f, 8.925689e-02f,
+ 8.850211e-02f, 8.774713e-02f, 8.699194e-02f, 8.623654e-02f,
+ 8.548094e-02f, 8.472515e-02f, 8.396915e-02f, 8.321295e-02f,
+ 8.245656e-02f, 8.169997e-02f, 8.094320e-02f, 8.018623e-02f,
+ 7.942907e-02f, 7.867173e-02f, 7.791420e-02f, 7.715649e-02f,
+ 7.639859e-02f, 7.564052e-02f, 7.488227e-02f, 7.412384e-02f,
+ 7.336524e-02f, 7.260646e-02f, 7.184752e-02f, 7.108840e-02f,
+ 7.032912e-02f, 6.956967e-02f, 6.881006e-02f, 6.805029e-02f,
+ 6.729035e-02f, 6.653026e-02f, 6.577001e-02f, 6.500961e-02f,
+ 6.424906e-02f, 6.348835e-02f, 6.272749e-02f, 6.196649e-02f,
+ 6.120534e-02f, 6.044404e-02f, 5.968261e-02f, 5.892103e-02f,
+ 5.815932e-02f, 5.739746e-02f, 5.663548e-02f, 5.587336e-02f,
+ 5.511110e-02f, 5.434872e-02f, 5.358621e-02f, 5.282358e-02f,
+ 5.206082e-02f, 5.129793e-02f, 5.053493e-02f, 4.977181e-02f,
+ 4.900857e-02f, 4.824522e-02f, 4.748175e-02f, 4.671817e-02f,
+ 4.595448e-02f, 4.519068e-02f, 4.442678e-02f, 4.366277e-02f,
+ 4.289866e-02f, 4.213444e-02f, 4.137013e-02f, 4.060572e-02f,
+ 3.984122e-02f, 3.907662e-02f, 3.831193e-02f, 3.754715e-02f,
+ 3.678228e-02f, 3.601733e-02f, 3.525229e-02f, 3.448716e-02f,
+ 3.372196e-02f, 3.295668e-02f, 3.219132e-02f, 3.142588e-02f,
+ 3.066037e-02f, 2.989479e-02f, 2.912913e-02f, 2.836341e-02f,
+ 2.759762e-02f, 2.683177e-02f, 2.606585e-02f, 2.529987e-02f,
+ 2.453384e-02f, 2.376774e-02f, 2.300159e-02f, 2.223539e-02f,
+ 2.146913e-02f, 2.070282e-02f, 1.993646e-02f, 1.917006e-02f,
+ 1.840361e-02f, 1.763712e-02f, 1.687059e-02f, 1.610401e-02f,
+ 1.533740e-02f, 1.457075e-02f, 1.380407e-02f, 1.303736e-02f,
+ 1.227061e-02f, 1.150384e-02f, 1.073704e-02f, 9.970214e-03f,
+ 9.203365e-03f, 8.436494e-03f, 7.669603e-03f, 6.902694e-03f,
+ 6.135769e-03f, 5.368830e-03f, 4.601877e-03f, 3.834914e-03f,
+ 3.067942e-03f, 2.300963e-03f, 1.533978e-03f, 7.669901e-04f};
+
+// ==========================================================================================
+// internal tools
+// ==========================================================================================
+static void AUP_FFTW_cftleaf(int n, int isplt, float* a, int nw, float* w);
+static void AUP_FFTW_cftf1st(int n, float* a, float* w);
+static void AUP_FFTW_cftrec4(int n, float* a, int nw, float* w);
+static void AUP_FFTW_cftfsub(int n, float* a, int* ip, int nw, float* w);
+static void AUP_FFTW_cftbsub(int n, float* a, int* ip, int nw, float* w);
+static void AUP_FFTW_bitrv2(int n, int* ip, float* a);
+static void AUP_FFTW_bitrv2conj(int n, int* ip, float* a);
+static void AUP_FFTW_bitrv216(float* a);
+static void AUP_FFTW_bitrv216neg(float* a);
+static void AUP_FFTW_bitrv208(float* a);
+static void AUP_FFTW_bitrv208neg(float* a);
+static void AUP_FFTW_cftb1st(int n, float* a, float* w);
+static int AUP_FFTW_cfttree(int n, int j, int k, float* a, int nw, float* w);
+static void AUP_FFTW_cftmdl1(int n, float* a, float* w);
+static void AUP_FFTW_cftmdl2(int n, float* a, float* w);
+static void AUP_FFTW_cftfx41(int n, float* a, int nw, float* w);
+static void AUP_FFTW_cftf161(float* a, float* w);
+static void AUP_FFTW_cftf162(float* a, float* w);
+static void AUP_FFTW_cftf081(float* a, float* w);
+static void AUP_FFTW_cftf082(float* a, float* w);
+static void AUP_FFTW_cftf040(float* a);
+static void AUP_FFTW_cftb040(float* a);
+static void AUP_FFTW_cftx020(float* a);
+static void AUP_FFTW_rftfsub(int n, float* a, int nc, float* c);
+static void AUP_FFTW_rftbsub(int n, float* a, int nc, float* c);
+static void AUP_FFTW_dctsub(int n, float* a, int nc, float* c);
+static void AUP_FFTW_dstsub(int n, float* a, int nc, float* c);
+static void AUP_FFTW_rdft(int n, int isgn, float* a, int* ip, float* w);
+
+static void AUP_FFTW_cftleaf(int n, int isplt, float* a, int nw, float* w) {
+ if (n == 512) {
+ AUP_FFTW_cftmdl1(128, a, &w[nw - 64]);
+ AUP_FFTW_cftf161(a, &w[nw - 8]);
+ AUP_FFTW_cftf162(&a[32], &w[nw - 32]);
+ AUP_FFTW_cftf161(&a[64], &w[nw - 8]);
+ AUP_FFTW_cftf161(&a[96], &w[nw - 8]);
+ AUP_FFTW_cftmdl2(128, &a[128], &w[nw - 128]);
+ AUP_FFTW_cftf161(&a[128], &w[nw - 8]);
+ AUP_FFTW_cftf162(&a[160], &w[nw - 32]);
+ AUP_FFTW_cftf161(&a[192], &w[nw - 8]);
+ AUP_FFTW_cftf162(&a[224], &w[nw - 32]);
+ AUP_FFTW_cftmdl1(128, &a[256], &w[nw - 64]);
+ AUP_FFTW_cftf161(&a[256], &w[nw - 8]);
+ AUP_FFTW_cftf162(&a[288], &w[nw - 32]);
+ AUP_FFTW_cftf161(&a[320], &w[nw - 8]);
+ AUP_FFTW_cftf161(&a[352], &w[nw - 8]);
+ if (isplt != 0) {
+ AUP_FFTW_cftmdl1(128, &a[384], &w[nw - 64]);
+ AUP_FFTW_cftf161(&a[480], &w[nw - 8]);
+ } else {
+ AUP_FFTW_cftmdl2(128, &a[384], &w[nw - 128]);
+ AUP_FFTW_cftf162(&a[480], &w[nw - 32]);
+ }
+ AUP_FFTW_cftf161(&a[384], &w[nw - 8]);
+ AUP_FFTW_cftf162(&a[416], &w[nw - 32]);
+ AUP_FFTW_cftf161(&a[448], &w[nw - 8]);
+ } else {
+ AUP_FFTW_cftmdl1(64, a, &w[nw - 32]);
+ AUP_FFTW_cftf081(a, &w[nw - 8]);
+ AUP_FFTW_cftf082(&a[16], &w[nw - 8]);
+ AUP_FFTW_cftf081(&a[32], &w[nw - 8]);
+ AUP_FFTW_cftf081(&a[48], &w[nw - 8]);
+ AUP_FFTW_cftmdl2(64, &a[64], &w[nw - 64]);
+ AUP_FFTW_cftf081(&a[64], &w[nw - 8]);
+ AUP_FFTW_cftf082(&a[80], &w[nw - 8]);
+ AUP_FFTW_cftf081(&a[96], &w[nw - 8]);
+ AUP_FFTW_cftf082(&a[112], &w[nw - 8]);
+ AUP_FFTW_cftmdl1(64, &a[128], &w[nw - 32]);
+ AUP_FFTW_cftf081(&a[128], &w[nw - 8]);
+ AUP_FFTW_cftf082(&a[144], &w[nw - 8]);
+ AUP_FFTW_cftf081(&a[160], &w[nw - 8]);
+ AUP_FFTW_cftf081(&a[176], &w[nw - 8]);
+ if (isplt != 0) {
+ AUP_FFTW_cftmdl1(64, &a[192], &w[nw - 32]);
+ AUP_FFTW_cftf081(&a[240], &w[nw - 8]);
+ } else {
+ AUP_FFTW_cftmdl2(64, &a[192], &w[nw - 64]);
+ AUP_FFTW_cftf082(&a[240], &w[nw - 8]);
+ }
+ AUP_FFTW_cftf081(&a[192], &w[nw - 8]);
+ AUP_FFTW_cftf082(&a[208], &w[nw - 8]);
+ AUP_FFTW_cftf081(&a[224], &w[nw - 8]);
+ }
+}
+
+static void AUP_FFTW_cftf1st(int n, float* a, float* w) {
+ int j, j0, j1, j2, j3, k, m, mh;
+ float wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i,
+ y3r, y3i;
+
+ mh = n >> 3;
+ m = 2 * mh;
+ j1 = m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[0] + a[j2];
+ x0i = a[1] + a[j2 + 1];
+ x1r = a[0] - a[j2];
+ x1i = a[1] - a[j2 + 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ a[0] = x0r + x2r;
+ a[1] = x0i + x2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i - x2i;
+ a[j2] = x1r - x3i;
+ a[j2 + 1] = x1i + x3r;
+ a[j3] = x1r + x3i;
+ a[j3 + 1] = x1i - x3r;
+ wn4r = w[1];
+ csc1 = w[2];
+ csc3 = w[3];
+ wd1r = 1;
+ wd1i = 0;
+ wd3r = 1;
+ wd3i = 0;
+ k = 0;
+ for (j = 2; j < mh - 2; j += 4) {
+ k += 4;
+ wk1r = csc1 * (wd1r + w[k]);
+ wk1i = csc1 * (wd1i + w[k + 1]);
+ wk3r = csc3 * (wd3r + w[k + 2]);
+ wk3i = csc3 * (wd3i + w[k + 3]);
+ wd1r = w[k];
+ wd1i = w[k + 1];
+ wd3r = w[k + 2];
+ wd3i = w[k + 3];
+ j1 = j + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j] + a[j2];
+ x0i = a[j + 1] + a[j2 + 1];
+ x1r = a[j] - a[j2];
+ x1i = a[j + 1] - a[j2 + 1];
+ y0r = a[j + 2] + a[j2 + 2];
+ y0i = a[j + 3] + a[j2 + 3];
+ y1r = a[j + 2] - a[j2 + 2];
+ y1i = a[j + 3] - a[j2 + 3];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ y2r = a[j1 + 2] + a[j3 + 2];
+ y2i = a[j1 + 3] + a[j3 + 3];
+ y3r = a[j1 + 2] - a[j3 + 2];
+ y3i = a[j1 + 3] - a[j3 + 3];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ a[j + 2] = y0r + y2r;
+ a[j + 3] = y0i + y2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i - x2i;
+ a[j1 + 2] = y0r - y2r;
+ a[j1 + 3] = y0i - y2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j2] = wk1r * x0r - wk1i * x0i;
+ a[j2 + 1] = wk1r * x0i + wk1i * x0r;
+ x0r = y1r - y3i;
+ x0i = y1i + y3r;
+ a[j2 + 2] = wd1r * x0r - wd1i * x0i;
+ a[j2 + 3] = wd1r * x0i + wd1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3r * x0r + wk3i * x0i;
+ a[j3 + 1] = wk3r * x0i - wk3i * x0r;
+ x0r = y1r + y3i;
+ x0i = y1i - y3r;
+ a[j3 + 2] = wd3r * x0r + wd3i * x0i;
+ a[j3 + 3] = wd3r * x0i - wd3i * x0r;
+ j0 = m - j;
+ j1 = j0 + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j0] + a[j2];
+ x0i = a[j0 + 1] + a[j2 + 1];
+ x1r = a[j0] - a[j2];
+ x1i = a[j0 + 1] - a[j2 + 1];
+ y0r = a[j0 - 2] + a[j2 - 2];
+ y0i = a[j0 - 1] + a[j2 - 1];
+ y1r = a[j0 - 2] - a[j2 - 2];
+ y1i = a[j0 - 1] - a[j2 - 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ y2r = a[j1 - 2] + a[j3 - 2];
+ y2i = a[j1 - 1] + a[j3 - 1];
+ y3r = a[j1 - 2] - a[j3 - 2];
+ y3i = a[j1 - 1] - a[j3 - 1];
+ a[j0] = x0r + x2r;
+ a[j0 + 1] = x0i + x2i;
+ a[j0 - 2] = y0r + y2r;
+ a[j0 - 1] = y0i + y2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i - x2i;
+ a[j1 - 2] = y0r - y2r;
+ a[j1 - 1] = y0i - y2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j2] = wk1i * x0r - wk1r * x0i;
+ a[j2 + 1] = wk1i * x0i + wk1r * x0r;
+ x0r = y1r - y3i;
+ x0i = y1i + y3r;
+ a[j2 - 2] = wd1i * x0r - wd1r * x0i;
+ a[j2 - 1] = wd1i * x0i + wd1r * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3i * x0r + wk3r * x0i;
+ a[j3 + 1] = wk3i * x0i - wk3r * x0r;
+ x0r = y1r + y3i;
+ x0i = y1i - y3r;
+ a[j3 - 2] = wd3i * x0r + wd3r * x0i;
+ a[j3 - 1] = wd3i * x0i - wd3r * x0r;
+ }
+ wk1r = csc1 * (wd1r + wn4r);
+ wk1i = csc1 * (wd1i + wn4r);
+ wk3r = csc3 * (wd3r - wn4r);
+ wk3i = csc3 * (wd3i - wn4r);
+ j0 = mh;
+ j1 = j0 + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j0 - 2] + a[j2 - 2];
+ x0i = a[j0 - 1] + a[j2 - 1];
+ x1r = a[j0 - 2] - a[j2 - 2];
+ x1i = a[j0 - 1] - a[j2 - 1];
+ x2r = a[j1 - 2] + a[j3 - 2];
+ x2i = a[j1 - 1] + a[j3 - 1];
+ x3r = a[j1 - 2] - a[j3 - 2];
+ x3i = a[j1 - 1] - a[j3 - 1];
+ a[j0 - 2] = x0r + x2r;
+ a[j0 - 1] = x0i + x2i;
+ a[j1 - 2] = x0r - x2r;
+ a[j1 - 1] = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j2 - 2] = wk1r * x0r - wk1i * x0i;
+ a[j2 - 1] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3 - 2] = wk3r * x0r + wk3i * x0i;
+ a[j3 - 1] = wk3r * x0i - wk3i * x0r;
+ x0r = a[j0] + a[j2];
+ x0i = a[j0 + 1] + a[j2 + 1];
+ x1r = a[j0] - a[j2];
+ x1i = a[j0 + 1] - a[j2 + 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ a[j0] = x0r + x2r;
+ a[j0 + 1] = x0i + x2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j2] = wn4r * (x0r - x0i);
+ a[j2 + 1] = wn4r * (x0i + x0r);
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = -wn4r * (x0r + x0i);
+ a[j3 + 1] = -wn4r * (x0i - x0r);
+ x0r = a[j0 + 2] + a[j2 + 2];
+ x0i = a[j0 + 3] + a[j2 + 3];
+ x1r = a[j0 + 2] - a[j2 + 2];
+ x1i = a[j0 + 3] - a[j2 + 3];
+ x2r = a[j1 + 2] + a[j3 + 2];
+ x2i = a[j1 + 3] + a[j3 + 3];
+ x3r = a[j1 + 2] - a[j3 + 2];
+ x3i = a[j1 + 3] - a[j3 + 3];
+ a[j0 + 2] = x0r + x2r;
+ a[j0 + 3] = x0i + x2i;
+ a[j1 + 2] = x0r - x2r;
+ a[j1 + 3] = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j2 + 2] = wk1i * x0r - wk1r * x0i;
+ a[j2 + 3] = wk1i * x0i + wk1r * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3 + 2] = wk3i * x0r + wk3r * x0i;
+ a[j3 + 3] = wk3i * x0i - wk3r * x0r;
+}
+
+static void AUP_FFTW_cftrec4(int n, float* a, int nw, float* w) {
+ int isplt, j, k, m;
+
+ m = n;
+ while (m > 512) {
+ m >>= 2;
+ AUP_FFTW_cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]);
+ }
+ AUP_FFTW_cftleaf(m, 1, &a[n - m], nw, w);
+ k = 0;
+ for (j = n - m; j > 0; j -= m) {
+ k++;
+ isplt = AUP_FFTW_cfttree(m, j, k, a, nw, w);
+ AUP_FFTW_cftleaf(m, isplt, &a[j - m], nw, w);
+ }
+}
+
+static void AUP_FFTW_cftfsub(int n, float* a, int* ip, int nw, float* w) {
+ if (n > 8) {
+ if (n > 32) {
+ AUP_FFTW_cftf1st(n, a, &w[nw - (n >> 2)]);
+ if (n > 512) {
+ AUP_FFTW_cftrec4(n, a, nw, w);
+ } else if (n > 128) {
+ AUP_FFTW_cftleaf(n, 1, a, nw, w);
+ } else {
+ AUP_FFTW_cftfx41(n, a, nw, w);
+ }
+ AUP_FFTW_bitrv2(n, ip, a);
+ } else if (n == 32) {
+ AUP_FFTW_cftf161(a, &w[nw - 8]);
+ AUP_FFTW_bitrv216(a);
+ } else {
+ AUP_FFTW_cftf081(a, w);
+ AUP_FFTW_bitrv208(a);
+ }
+ } else if (n == 8) {
+ AUP_FFTW_cftf040(a);
+ } else if (n == 4) {
+ AUP_FFTW_cftx020(a);
+ }
+}
+
+static void AUP_FFTW_cftbsub(int n, float* a, int* ip, int nw, float* w) {
+ if (n > 8) {
+ if (n > 32) {
+ AUP_FFTW_cftb1st(n, a, &w[nw - (n >> 2)]);
+ if (n > 512) {
+ AUP_FFTW_cftrec4(n, a, nw, w);
+ } else if (n > 128) {
+ AUP_FFTW_cftleaf(n, 1, a, nw, w);
+ } else {
+ AUP_FFTW_cftfx41(n, a, nw, w);
+ }
+ AUP_FFTW_bitrv2conj(n, ip, a);
+ } else if (n == 32) {
+ AUP_FFTW_cftf161(a, &w[nw - 8]);
+ AUP_FFTW_bitrv216neg(a);
+ } else {
+ AUP_FFTW_cftf081(a, w);
+ AUP_FFTW_bitrv208neg(a);
+ }
+ } else if (n == 8) {
+ AUP_FFTW_cftb040(a);
+ } else if (n == 4) {
+ AUP_FFTW_cftx020(a);
+ }
+}
+
+static void AUP_FFTW_bitrv2(int n, int* ip, float* a) {
+ int j, j1, k, k1, l, m, nh, nm;
+ float xr, xi, yr, yi;
+
+ m = 1;
+ for (l = n >> 2; l > 8; l >>= 2) {
+ m <<= 1;
+ }
+ nh = n >> 1;
+ nm = 4 * m;
+ if (l == 8) {
+ for (k = 0; k < m; k++) {
+ for (j = 0; j < k; j++) {
+ j1 = 4 * j + 2 * ip[m + k];
+ k1 = 4 * k + 2 * ip[m + j];
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nh;
+ k1 += 2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= 2 * nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 += nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= 2 * nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += 2;
+ k1 += nh;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nh;
+ k1 -= 2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= 2 * nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 += nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= 2 * nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ k1 = 4 * k + 2 * ip[m + k];
+ j1 = k1 + 2;
+ k1 += nh;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= 2;
+ k1 -= nh;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nh + 2;
+ k1 += nh + 2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nh - nm;
+ k1 += 2 * nm - 2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ } else {
+ for (k = 0; k < m; k++) {
+ for (j = 0; j < k; j++) {
+ j1 = 4 * j + ip[m + k];
+ k1 = 4 * k + ip[m + j];
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nh;
+ k1 += 2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += 2;
+ k1 += nh;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nh;
+ k1 -= 2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ k1 = 4 * k + ip[m + k];
+ j1 = k1 + 2;
+ k1 += nh;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += nm;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ }
+}
+
+static void AUP_FFTW_bitrv2conj(int n, int* ip, float* a) {
+ int j, j1, k, k1, l, m, nh, nm;
+ float xr, xi, yr, yi;
+
+ m = 1;
+ for (l = n >> 2; l > 8; l >>= 2) {
+ m <<= 1;
+ }
+ nh = n >> 1;
+ nm = 4 * m;
+ if (l == 8) {
+ for (k = 0; k < m; k++) {
+ for (j = 0; j < k; j++) {
+ j1 = 4 * j + 2 * ip[m + k];
+ k1 = 4 * k + 2 * ip[m + j];
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nh;
+ k1 += 2;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= 2 * nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 += nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= 2 * nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += 2;
+ k1 += nh;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nh;
+ k1 -= 2;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= 2 * nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 += nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= 2 * nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ k1 = 4 * k + 2 * ip[m + k];
+ j1 = k1 + 2;
+ k1 += nh;
+ a[j1 - 1] = -a[j1 - 1];
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ a[k1 + 3] = -a[k1 + 3];
+ j1 += nm;
+ k1 += 2 * nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= 2;
+ k1 -= nh;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nh + 2;
+ k1 += nh + 2;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nh - nm;
+ k1 += 2 * nm - 2;
+ a[j1 - 1] = -a[j1 - 1];
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ a[k1 + 3] = -a[k1 + 3];
+ }
+ } else {
+ for (k = 0; k < m; k++) {
+ for (j = 0; j < k; j++) {
+ j1 = 4 * j + ip[m + k];
+ k1 = 4 * k + ip[m + j];
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nh;
+ k1 += 2;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += 2;
+ k1 += nh;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += nm;
+ k1 += nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nh;
+ k1 -= 2;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 -= nm;
+ k1 -= nm;
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ k1 = 4 * k + ip[m + k];
+ j1 = k1 + 2;
+ k1 += nh;
+ a[j1 - 1] = -a[j1 - 1];
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ a[k1 + 3] = -a[k1 + 3];
+ j1 += nm;
+ k1 += nm;
+ a[j1 - 1] = -a[j1 - 1];
+ xr = a[j1];
+ xi = -a[j1 + 1];
+ yr = a[k1];
+ yi = -a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ a[k1 + 3] = -a[k1 + 3];
+ }
+ }
+}
+
+static void AUP_FFTW_bitrv216(float* a) {
+ float x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i,
+ x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i;
+
+ x1r = a[2];
+ x1i = a[3];
+ x2r = a[4];
+ x2i = a[5];
+ x3r = a[6];
+ x3i = a[7];
+ x4r = a[8];
+ x4i = a[9];
+ x5r = a[10];
+ x5i = a[11];
+ x7r = a[14];
+ x7i = a[15];
+ x8r = a[16];
+ x8i = a[17];
+ x10r = a[20];
+ x10i = a[21];
+ x11r = a[22];
+ x11i = a[23];
+ x12r = a[24];
+ x12i = a[25];
+ x13r = a[26];
+ x13i = a[27];
+ x14r = a[28];
+ x14i = a[29];
+ a[2] = x8r;
+ a[3] = x8i;
+ a[4] = x4r;
+ a[5] = x4i;
+ a[6] = x12r;
+ a[7] = x12i;
+ a[8] = x2r;
+ a[9] = x2i;
+ a[10] = x10r;
+ a[11] = x10i;
+ a[14] = x14r;
+ a[15] = x14i;
+ a[16] = x1r;
+ a[17] = x1i;
+ a[20] = x5r;
+ a[21] = x5i;
+ a[22] = x13r;
+ a[23] = x13i;
+ a[24] = x3r;
+ a[25] = x3i;
+ a[26] = x11r;
+ a[27] = x11i;
+ a[28] = x7r;
+ a[29] = x7i;
+}
+
+static void AUP_FFTW_bitrv216neg(float* a) {
+ float x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i,
+ x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r,
+ x14i, x15r, x15i;
+
+ x1r = a[2];
+ x1i = a[3];
+ x2r = a[4];
+ x2i = a[5];
+ x3r = a[6];
+ x3i = a[7];
+ x4r = a[8];
+ x4i = a[9];
+ x5r = a[10];
+ x5i = a[11];
+ x6r = a[12];
+ x6i = a[13];
+ x7r = a[14];
+ x7i = a[15];
+ x8r = a[16];
+ x8i = a[17];
+ x9r = a[18];
+ x9i = a[19];
+ x10r = a[20];
+ x10i = a[21];
+ x11r = a[22];
+ x11i = a[23];
+ x12r = a[24];
+ x12i = a[25];
+ x13r = a[26];
+ x13i = a[27];
+ x14r = a[28];
+ x14i = a[29];
+ x15r = a[30];
+ x15i = a[31];
+ a[2] = x15r;
+ a[3] = x15i;
+ a[4] = x7r;
+ a[5] = x7i;
+ a[6] = x11r;
+ a[7] = x11i;
+ a[8] = x3r;
+ a[9] = x3i;
+ a[10] = x13r;
+ a[11] = x13i;
+ a[12] = x5r;
+ a[13] = x5i;
+ a[14] = x9r;
+ a[15] = x9i;
+ a[16] = x1r;
+ a[17] = x1i;
+ a[18] = x14r;
+ a[19] = x14i;
+ a[20] = x6r;
+ a[21] = x6i;
+ a[22] = x10r;
+ a[23] = x10i;
+ a[24] = x2r;
+ a[25] = x2i;
+ a[26] = x12r;
+ a[27] = x12i;
+ a[28] = x4r;
+ a[29] = x4i;
+ a[30] = x8r;
+ a[31] = x8i;
+}
+
+static void AUP_FFTW_bitrv208(float* a) {
+ float x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i;
+
+ x1r = a[2];
+ x1i = a[3];
+ x3r = a[6];
+ x3i = a[7];
+ x4r = a[8];
+ x4i = a[9];
+ x6r = a[12];
+ x6i = a[13];
+ a[2] = x4r;
+ a[3] = x4i;
+ a[6] = x6r;
+ a[7] = x6i;
+ a[8] = x1r;
+ a[9] = x1i;
+ a[12] = x3r;
+ a[13] = x3i;
+}
+
+static void AUP_FFTW_bitrv208neg(float* a) {
+ float x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
+
+ x1r = a[2];
+ x1i = a[3];
+ x2r = a[4];
+ x2i = a[5];
+ x3r = a[6];
+ x3i = a[7];
+ x4r = a[8];
+ x4i = a[9];
+ x5r = a[10];
+ x5i = a[11];
+ x6r = a[12];
+ x6i = a[13];
+ x7r = a[14];
+ x7i = a[15];
+ a[2] = x7r;
+ a[3] = x7i;
+ a[4] = x3r;
+ a[5] = x3i;
+ a[6] = x5r;
+ a[7] = x5i;
+ a[8] = x1r;
+ a[9] = x1i;
+ a[10] = x6r;
+ a[11] = x6i;
+ a[12] = x2r;
+ a[13] = x2i;
+ a[14] = x4r;
+ a[15] = x4i;
+}
+
+static void AUP_FFTW_cftb1st(int n, float* a, float* w) {
+ int j, j0, j1, j2, j3, k, m, mh;
+ float wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i,
+ y3r, y3i;
+
+ mh = n >> 3;
+ m = 2 * mh;
+ j1 = m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[0] + a[j2];
+ x0i = -a[1] - a[j2 + 1];
+ x1r = a[0] - a[j2];
+ x1i = -a[1] + a[j2 + 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ a[0] = x0r + x2r;
+ a[1] = x0i - x2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i + x2i;
+ a[j2] = x1r + x3i;
+ a[j2 + 1] = x1i + x3r;
+ a[j3] = x1r - x3i;
+ a[j3 + 1] = x1i - x3r;
+ wn4r = w[1];
+ csc1 = w[2];
+ csc3 = w[3];
+ wd1r = 1;
+ wd1i = 0;
+ wd3r = 1;
+ wd3i = 0;
+ k = 0;
+ for (j = 2; j < mh - 2; j += 4) {
+ k += 4;
+ wk1r = csc1 * (wd1r + w[k]);
+ wk1i = csc1 * (wd1i + w[k + 1]);
+ wk3r = csc3 * (wd3r + w[k + 2]);
+ wk3i = csc3 * (wd3i + w[k + 3]);
+ wd1r = w[k];
+ wd1i = w[k + 1];
+ wd3r = w[k + 2];
+ wd3i = w[k + 3];
+ j1 = j + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j] + a[j2];
+ x0i = -a[j + 1] - a[j2 + 1];
+ x1r = a[j] - a[j2];
+ x1i = -a[j + 1] + a[j2 + 1];
+ y0r = a[j + 2] + a[j2 + 2];
+ y0i = -a[j + 3] - a[j2 + 3];
+ y1r = a[j + 2] - a[j2 + 2];
+ y1i = -a[j + 3] + a[j2 + 3];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ y2r = a[j1 + 2] + a[j3 + 2];
+ y2i = a[j1 + 3] + a[j3 + 3];
+ y3r = a[j1 + 2] - a[j3 + 2];
+ y3i = a[j1 + 3] - a[j3 + 3];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i - x2i;
+ a[j + 2] = y0r + y2r;
+ a[j + 3] = y0i - y2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i + x2i;
+ a[j1 + 2] = y0r - y2r;
+ a[j1 + 3] = y0i + y2i;
+ x0r = x1r + x3i;
+ x0i = x1i + x3r;
+ a[j2] = wk1r * x0r - wk1i * x0i;
+ a[j2 + 1] = wk1r * x0i + wk1i * x0r;
+ x0r = y1r + y3i;
+ x0i = y1i + y3r;
+ a[j2 + 2] = wd1r * x0r - wd1i * x0i;
+ a[j2 + 3] = wd1r * x0i + wd1i * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3r * x0r + wk3i * x0i;
+ a[j3 + 1] = wk3r * x0i - wk3i * x0r;
+ x0r = y1r - y3i;
+ x0i = y1i - y3r;
+ a[j3 + 2] = wd3r * x0r + wd3i * x0i;
+ a[j3 + 3] = wd3r * x0i - wd3i * x0r;
+ j0 = m - j;
+ j1 = j0 + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j0] + a[j2];
+ x0i = -a[j0 + 1] - a[j2 + 1];
+ x1r = a[j0] - a[j2];
+ x1i = -a[j0 + 1] + a[j2 + 1];
+ y0r = a[j0 - 2] + a[j2 - 2];
+ y0i = -a[j0 - 1] - a[j2 - 1];
+ y1r = a[j0 - 2] - a[j2 - 2];
+ y1i = -a[j0 - 1] + a[j2 - 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ y2r = a[j1 - 2] + a[j3 - 2];
+ y2i = a[j1 - 1] + a[j3 - 1];
+ y3r = a[j1 - 2] - a[j3 - 2];
+ y3i = a[j1 - 1] - a[j3 - 1];
+ a[j0] = x0r + x2r;
+ a[j0 + 1] = x0i - x2i;
+ a[j0 - 2] = y0r + y2r;
+ a[j0 - 1] = y0i - y2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i + x2i;
+ a[j1 - 2] = y0r - y2r;
+ a[j1 - 1] = y0i + y2i;
+ x0r = x1r + x3i;
+ x0i = x1i + x3r;
+ a[j2] = wk1i * x0r - wk1r * x0i;
+ a[j2 + 1] = wk1i * x0i + wk1r * x0r;
+ x0r = y1r + y3i;
+ x0i = y1i + y3r;
+ a[j2 - 2] = wd1i * x0r - wd1r * x0i;
+ a[j2 - 1] = wd1i * x0i + wd1r * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3i * x0r + wk3r * x0i;
+ a[j3 + 1] = wk3i * x0i - wk3r * x0r;
+ x0r = y1r - y3i;
+ x0i = y1i - y3r;
+ a[j3 - 2] = wd3i * x0r + wd3r * x0i;
+ a[j3 - 1] = wd3i * x0i - wd3r * x0r;
+ }
+ wk1r = csc1 * (wd1r + wn4r);
+ wk1i = csc1 * (wd1i + wn4r);
+ wk3r = csc3 * (wd3r - wn4r);
+ wk3i = csc3 * (wd3i - wn4r);
+ j0 = mh;
+ j1 = j0 + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j0 - 2] + a[j2 - 2];
+ x0i = -a[j0 - 1] - a[j2 - 1];
+ x1r = a[j0 - 2] - a[j2 - 2];
+ x1i = -a[j0 - 1] + a[j2 - 1];
+ x2r = a[j1 - 2] + a[j3 - 2];
+ x2i = a[j1 - 1] + a[j3 - 1];
+ x3r = a[j1 - 2] - a[j3 - 2];
+ x3i = a[j1 - 1] - a[j3 - 1];
+ a[j0 - 2] = x0r + x2r;
+ a[j0 - 1] = x0i - x2i;
+ a[j1 - 2] = x0r - x2r;
+ a[j1 - 1] = x0i + x2i;
+ x0r = x1r + x3i;
+ x0i = x1i + x3r;
+ a[j2 - 2] = wk1r * x0r - wk1i * x0i;
+ a[j2 - 1] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i - x3r;
+ a[j3 - 2] = wk3r * x0r + wk3i * x0i;
+ a[j3 - 1] = wk3r * x0i - wk3i * x0r;
+ x0r = a[j0] + a[j2];
+ x0i = -a[j0 + 1] - a[j2 + 1];
+ x1r = a[j0] - a[j2];
+ x1i = -a[j0 + 1] + a[j2 + 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ a[j0] = x0r + x2r;
+ a[j0 + 1] = x0i - x2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i + x2i;
+ x0r = x1r + x3i;
+ x0i = x1i + x3r;
+ a[j2] = wn4r * (x0r - x0i);
+ a[j2 + 1] = wn4r * (x0i + x0r);
+ x0r = x1r - x3i;
+ x0i = x1i - x3r;
+ a[j3] = -wn4r * (x0r + x0i);
+ a[j3 + 1] = -wn4r * (x0i - x0r);
+ x0r = a[j0 + 2] + a[j2 + 2];
+ x0i = -a[j0 + 3] - a[j2 + 3];
+ x1r = a[j0 + 2] - a[j2 + 2];
+ x1i = -a[j0 + 3] + a[j2 + 3];
+ x2r = a[j1 + 2] + a[j3 + 2];
+ x2i = a[j1 + 3] + a[j3 + 3];
+ x3r = a[j1 + 2] - a[j3 + 2];
+ x3i = a[j1 + 3] - a[j3 + 3];
+ a[j0 + 2] = x0r + x2r;
+ a[j0 + 3] = x0i - x2i;
+ a[j1 + 2] = x0r - x2r;
+ a[j1 + 3] = x0i + x2i;
+ x0r = x1r + x3i;
+ x0i = x1i + x3r;
+ a[j2 + 2] = wk1i * x0r - wk1r * x0i;
+ a[j2 + 3] = wk1i * x0i + wk1r * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i - x3r;
+ a[j3 + 2] = wk3i * x0r + wk3r * x0i;
+ a[j3 + 3] = wk3i * x0i - wk3r * x0r;
+}
+
+static int AUP_FFTW_cfttree(int n, int j, int k, float* a, int nw, float* w) {
+ int i, isplt, m;
+
+ if ((k & 3) != 0) {
+ isplt = k & 1;
+ if (isplt != 0) {
+ AUP_FFTW_cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]);
+ } else {
+ AUP_FFTW_cftmdl2(n, &a[j - n], &w[nw - n]);
+ }
+ } else {
+ m = n;
+ for (i = k; (i & 3) == 0; i >>= 2) {
+ m <<= 2;
+ }
+ isplt = i & 1;
+ if (isplt != 0) {
+ while (m > 128) {
+ AUP_FFTW_cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]);
+ m >>= 2;
+ }
+ } else {
+ while (m > 128) {
+ AUP_FFTW_cftmdl2(m, &a[j - m], &w[nw - m]);
+ m >>= 2;
+ }
+ }
+ }
+ return isplt;
+}
+
+static void AUP_FFTW_cftmdl1(int n, float* a, float* w) {
+ int j, j0, j1, j2, j3, k, m, mh;
+ float wn4r, wk1r, wk1i, wk3r, wk3i;
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ mh = n >> 3;
+ m = 2 * mh;
+ j1 = m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[0] + a[j2];
+ x0i = a[1] + a[j2 + 1];
+ x1r = a[0] - a[j2];
+ x1i = a[1] - a[j2 + 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ a[0] = x0r + x2r;
+ a[1] = x0i + x2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i - x2i;
+ a[j2] = x1r - x3i;
+ a[j2 + 1] = x1i + x3r;
+ a[j3] = x1r + x3i;
+ a[j3 + 1] = x1i - x3r;
+ wn4r = w[1];
+ k = 0;
+ for (j = 2; j < mh; j += 2) {
+ k += 4;
+ wk1r = w[k];
+ wk1i = w[k + 1];
+ wk3r = w[k + 2];
+ wk3i = w[k + 3];
+ j1 = j + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j] + a[j2];
+ x0i = a[j + 1] + a[j2 + 1];
+ x1r = a[j] - a[j2];
+ x1i = a[j + 1] - a[j2 + 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j2] = wk1r * x0r - wk1i * x0i;
+ a[j2 + 1] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3r * x0r + wk3i * x0i;
+ a[j3 + 1] = wk3r * x0i - wk3i * x0r;
+ j0 = m - j;
+ j1 = j0 + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j0] + a[j2];
+ x0i = a[j0 + 1] + a[j2 + 1];
+ x1r = a[j0] - a[j2];
+ x1i = a[j0 + 1] - a[j2 + 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ a[j0] = x0r + x2r;
+ a[j0 + 1] = x0i + x2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j2] = wk1i * x0r - wk1r * x0i;
+ a[j2 + 1] = wk1i * x0i + wk1r * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3i * x0r + wk3r * x0i;
+ a[j3 + 1] = wk3i * x0i - wk3r * x0r;
+ }
+ j0 = mh;
+ j1 = j0 + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j0] + a[j2];
+ x0i = a[j0 + 1] + a[j2 + 1];
+ x1r = a[j0] - a[j2];
+ x1i = a[j0 + 1] - a[j2 + 1];
+ x2r = a[j1] + a[j3];
+ x2i = a[j1 + 1] + a[j3 + 1];
+ x3r = a[j1] - a[j3];
+ x3i = a[j1 + 1] - a[j3 + 1];
+ a[j0] = x0r + x2r;
+ a[j0 + 1] = x0i + x2i;
+ a[j1] = x0r - x2r;
+ a[j1 + 1] = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j2] = wn4r * (x0r - x0i);
+ a[j2 + 1] = wn4r * (x0i + x0r);
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = -wn4r * (x0r + x0i);
+ a[j3 + 1] = -wn4r * (x0i - x0r);
+}
+
+static void AUP_FFTW_cftmdl2(int n, float* a, float* w) {
+ int j, j0, j1, j2, j3, k, kr, m, mh;
+ float wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i;
+
+ mh = n >> 3;
+ m = 2 * mh;
+ wn4r = w[1];
+ j1 = m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[0] - a[j2 + 1];
+ x0i = a[1] + a[j2];
+ x1r = a[0] + a[j2 + 1];
+ x1i = a[1] - a[j2];
+ x2r = a[j1] - a[j3 + 1];
+ x2i = a[j1 + 1] + a[j3];
+ x3r = a[j1] + a[j3 + 1];
+ x3i = a[j1 + 1] - a[j3];
+ y0r = wn4r * (x2r - x2i);
+ y0i = wn4r * (x2i + x2r);
+ a[0] = x0r + y0r;
+ a[1] = x0i + y0i;
+ a[j1] = x0r - y0r;
+ a[j1 + 1] = x0i - y0i;
+ y0r = wn4r * (x3r - x3i);
+ y0i = wn4r * (x3i + x3r);
+ a[j2] = x1r - y0i;
+ a[j2 + 1] = x1i + y0r;
+ a[j3] = x1r + y0i;
+ a[j3 + 1] = x1i - y0r;
+ k = 0;
+ kr = 2 * m;
+ for (j = 2; j < mh; j += 2) {
+ k += 4;
+ wk1r = w[k];
+ wk1i = w[k + 1];
+ wk3r = w[k + 2];
+ wk3i = w[k + 3];
+ kr -= 4;
+ wd1i = w[kr];
+ wd1r = w[kr + 1];
+ wd3i = w[kr + 2];
+ wd3r = w[kr + 3];
+ j1 = j + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j] - a[j2 + 1];
+ x0i = a[j + 1] + a[j2];
+ x1r = a[j] + a[j2 + 1];
+ x1i = a[j + 1] - a[j2];
+ x2r = a[j1] - a[j3 + 1];
+ x2i = a[j1 + 1] + a[j3];
+ x3r = a[j1] + a[j3 + 1];
+ x3i = a[j1 + 1] - a[j3];
+ y0r = wk1r * x0r - wk1i * x0i;
+ y0i = wk1r * x0i + wk1i * x0r;
+ y2r = wd1r * x2r - wd1i * x2i;
+ y2i = wd1r * x2i + wd1i * x2r;
+ a[j] = y0r + y2r;
+ a[j + 1] = y0i + y2i;
+ a[j1] = y0r - y2r;
+ a[j1 + 1] = y0i - y2i;
+ y0r = wk3r * x1r + wk3i * x1i;
+ y0i = wk3r * x1i - wk3i * x1r;
+ y2r = wd3r * x3r + wd3i * x3i;
+ y2i = wd3r * x3i - wd3i * x3r;
+ a[j2] = y0r + y2r;
+ a[j2 + 1] = y0i + y2i;
+ a[j3] = y0r - y2r;
+ a[j3 + 1] = y0i - y2i;
+ j0 = m - j;
+ j1 = j0 + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j0] - a[j2 + 1];
+ x0i = a[j0 + 1] + a[j2];
+ x1r = a[j0] + a[j2 + 1];
+ x1i = a[j0 + 1] - a[j2];
+ x2r = a[j1] - a[j3 + 1];
+ x2i = a[j1 + 1] + a[j3];
+ x3r = a[j1] + a[j3 + 1];
+ x3i = a[j1 + 1] - a[j3];
+ y0r = wd1i * x0r - wd1r * x0i;
+ y0i = wd1i * x0i + wd1r * x0r;
+ y2r = wk1i * x2r - wk1r * x2i;
+ y2i = wk1i * x2i + wk1r * x2r;
+ a[j0] = y0r + y2r;
+ a[j0 + 1] = y0i + y2i;
+ a[j1] = y0r - y2r;
+ a[j1 + 1] = y0i - y2i;
+ y0r = wd3i * x1r + wd3r * x1i;
+ y0i = wd3i * x1i - wd3r * x1r;
+ y2r = wk3i * x3r + wk3r * x3i;
+ y2i = wk3i * x3i - wk3r * x3r;
+ a[j2] = y0r + y2r;
+ a[j2 + 1] = y0i + y2i;
+ a[j3] = y0r - y2r;
+ a[j3 + 1] = y0i - y2i;
+ }
+ wk1r = w[m];
+ wk1i = w[m + 1];
+ j0 = mh;
+ j1 = j0 + m;
+ j2 = j1 + m;
+ j3 = j2 + m;
+ x0r = a[j0] - a[j2 + 1];
+ x0i = a[j0 + 1] + a[j2];
+ x1r = a[j0] + a[j2 + 1];
+ x1i = a[j0 + 1] - a[j2];
+ x2r = a[j1] - a[j3 + 1];
+ x2i = a[j1 + 1] + a[j3];
+ x3r = a[j1] + a[j3 + 1];
+ x3i = a[j1 + 1] - a[j3];
+ y0r = wk1r * x0r - wk1i * x0i;
+ y0i = wk1r * x0i + wk1i * x0r;
+ y2r = wk1i * x2r - wk1r * x2i;
+ y2i = wk1i * x2i + wk1r * x2r;
+ a[j0] = y0r + y2r;
+ a[j0 + 1] = y0i + y2i;
+ a[j1] = y0r - y2r;
+ a[j1 + 1] = y0i - y2i;
+ y0r = wk1i * x1r - wk1r * x1i;
+ y0i = wk1i * x1i + wk1r * x1r;
+ y2r = wk1r * x3r - wk1i * x3i;
+ y2i = wk1r * x3i + wk1i * x3r;
+ a[j2] = y0r - y2r;
+ a[j2 + 1] = y0i - y2i;
+ a[j3] = y0r + y2r;
+ a[j3 + 1] = y0i + y2i;
+}
+
+static void AUP_FFTW_cftfx41(int n, float* a, int nw, float* w) {
+ if (n == 128) {
+ AUP_FFTW_cftf161(a, &w[nw - 8]);
+ AUP_FFTW_cftf162(&a[32], &w[nw - 32]);
+ AUP_FFTW_cftf161(&a[64], &w[nw - 8]);
+ AUP_FFTW_cftf161(&a[96], &w[nw - 8]);
+ } else {
+ AUP_FFTW_cftf081(a, &w[nw - 8]);
+ AUP_FFTW_cftf082(&a[16], &w[nw - 8]);
+ AUP_FFTW_cftf081(&a[32], &w[nw - 8]);
+ AUP_FFTW_cftf081(&a[48], &w[nw - 8]);
+ }
+}
+
+static void AUP_FFTW_cftf161(float* a, float* w) {
+ float wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r,
+ y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i,
+ y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i,
+ y15r, y15i;
+
+ wn4r = w[1];
+ wk1r = w[2];
+ wk1i = w[3];
+ x0r = a[0] + a[16];
+ x0i = a[1] + a[17];
+ x1r = a[0] - a[16];
+ x1i = a[1] - a[17];
+ x2r = a[8] + a[24];
+ x2i = a[9] + a[25];
+ x3r = a[8] - a[24];
+ x3i = a[9] - a[25];
+ y0r = x0r + x2r;
+ y0i = x0i + x2i;
+ y4r = x0r - x2r;
+ y4i = x0i - x2i;
+ y8r = x1r - x3i;
+ y8i = x1i + x3r;
+ y12r = x1r + x3i;
+ y12i = x1i - x3r;
+ x0r = a[2] + a[18];
+ x0i = a[3] + a[19];
+ x1r = a[2] - a[18];
+ x1i = a[3] - a[19];
+ x2r = a[10] + a[26];
+ x2i = a[11] + a[27];
+ x3r = a[10] - a[26];
+ x3i = a[11] - a[27];
+ y1r = x0r + x2r;
+ y1i = x0i + x2i;
+ y5r = x0r - x2r;
+ y5i = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ y9r = wk1r * x0r - wk1i * x0i;
+ y9i = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ y13r = wk1i * x0r - wk1r * x0i;
+ y13i = wk1i * x0i + wk1r * x0r;
+ x0r = a[4] + a[20];
+ x0i = a[5] + a[21];
+ x1r = a[4] - a[20];
+ x1i = a[5] - a[21];
+ x2r = a[12] + a[28];
+ x2i = a[13] + a[29];
+ x3r = a[12] - a[28];
+ x3i = a[13] - a[29];
+ y2r = x0r + x2r;
+ y2i = x0i + x2i;
+ y6r = x0r - x2r;
+ y6i = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ y10r = wn4r * (x0r - x0i);
+ y10i = wn4r * (x0i + x0r);
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ y14r = wn4r * (x0r + x0i);
+ y14i = wn4r * (x0i - x0r);
+ x0r = a[6] + a[22];
+ x0i = a[7] + a[23];
+ x1r = a[6] - a[22];
+ x1i = a[7] - a[23];
+ x2r = a[14] + a[30];
+ x2i = a[15] + a[31];
+ x3r = a[14] - a[30];
+ x3i = a[15] - a[31];
+ y3r = x0r + x2r;
+ y3i = x0i + x2i;
+ y7r = x0r - x2r;
+ y7i = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ y11r = wk1i * x0r - wk1r * x0i;
+ y11i = wk1i * x0i + wk1r * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ y15r = wk1r * x0r - wk1i * x0i;
+ y15i = wk1r * x0i + wk1i * x0r;
+ x0r = y12r - y14r;
+ x0i = y12i - y14i;
+ x1r = y12r + y14r;
+ x1i = y12i + y14i;
+ x2r = y13r - y15r;
+ x2i = y13i - y15i;
+ x3r = y13r + y15r;
+ x3i = y13i + y15i;
+ a[24] = x0r + x2r;
+ a[25] = x0i + x2i;
+ a[26] = x0r - x2r;
+ a[27] = x0i - x2i;
+ a[28] = x1r - x3i;
+ a[29] = x1i + x3r;
+ a[30] = x1r + x3i;
+ a[31] = x1i - x3r;
+ x0r = y8r + y10r;
+ x0i = y8i + y10i;
+ x1r = y8r - y10r;
+ x1i = y8i - y10i;
+ x2r = y9r + y11r;
+ x2i = y9i + y11i;
+ x3r = y9r - y11r;
+ x3i = y9i - y11i;
+ a[16] = x0r + x2r;
+ a[17] = x0i + x2i;
+ a[18] = x0r - x2r;
+ a[19] = x0i - x2i;
+ a[20] = x1r - x3i;
+ a[21] = x1i + x3r;
+ a[22] = x1r + x3i;
+ a[23] = x1i - x3r;
+ x0r = y5r - y7i;
+ x0i = y5i + y7r;
+ x2r = wn4r * (x0r - x0i);
+ x2i = wn4r * (x0i + x0r);
+ x0r = y5r + y7i;
+ x0i = y5i - y7r;
+ x3r = wn4r * (x0r - x0i);
+ x3i = wn4r * (x0i + x0r);
+ x0r = y4r - y6i;
+ x0i = y4i + y6r;
+ x1r = y4r + y6i;
+ x1i = y4i - y6r;
+ a[8] = x0r + x2r;
+ a[9] = x0i + x2i;
+ a[10] = x0r - x2r;
+ a[11] = x0i - x2i;
+ a[12] = x1r - x3i;
+ a[13] = x1i + x3r;
+ a[14] = x1r + x3i;
+ a[15] = x1i - x3r;
+ x0r = y0r + y2r;
+ x0i = y0i + y2i;
+ x1r = y0r - y2r;
+ x1i = y0i - y2i;
+ x2r = y1r + y3r;
+ x2i = y1i + y3i;
+ x3r = y1r - y3r;
+ x3i = y1i - y3i;
+ a[0] = x0r + x2r;
+ a[1] = x0i + x2i;
+ a[2] = x0r - x2r;
+ a[3] = x0i - x2i;
+ a[4] = x1r - x3i;
+ a[5] = x1i + x3r;
+ a[6] = x1r + x3i;
+ a[7] = x1i - x3r;
+}
+
+static void AUP_FFTW_cftf162(float* a, float* w) {
+ float wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r, x2i,
+ y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r,
+ y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i,
+ y14r, y14i, y15r, y15i;
+
+ wn4r = w[1];
+ wk1r = w[4];
+ wk1i = w[5];
+ wk3r = w[6];
+ wk3i = -w[7];
+ wk2r = w[8];
+ wk2i = w[9];
+ x1r = a[0] - a[17];
+ x1i = a[1] + a[16];
+ x0r = a[8] - a[25];
+ x0i = a[9] + a[24];
+ x2r = wn4r * (x0r - x0i);
+ x2i = wn4r * (x0i + x0r);
+ y0r = x1r + x2r;
+ y0i = x1i + x2i;
+ y4r = x1r - x2r;
+ y4i = x1i - x2i;
+ x1r = a[0] + a[17];
+ x1i = a[1] - a[16];
+ x0r = a[8] + a[25];
+ x0i = a[9] - a[24];
+ x2r = wn4r * (x0r - x0i);
+ x2i = wn4r * (x0i + x0r);
+ y8r = x1r - x2i;
+ y8i = x1i + x2r;
+ y12r = x1r + x2i;
+ y12i = x1i - x2r;
+ x0r = a[2] - a[19];
+ x0i = a[3] + a[18];
+ x1r = wk1r * x0r - wk1i * x0i;
+ x1i = wk1r * x0i + wk1i * x0r;
+ x0r = a[10] - a[27];
+ x0i = a[11] + a[26];
+ x2r = wk3i * x0r - wk3r * x0i;
+ x2i = wk3i * x0i + wk3r * x0r;
+ y1r = x1r + x2r;
+ y1i = x1i + x2i;
+ y5r = x1r - x2r;
+ y5i = x1i - x2i;
+ x0r = a[2] + a[19];
+ x0i = a[3] - a[18];
+ x1r = wk3r * x0r - wk3i * x0i;
+ x1i = wk3r * x0i + wk3i * x0r;
+ x0r = a[10] + a[27];
+ x0i = a[11] - a[26];
+ x2r = wk1r * x0r + wk1i * x0i;
+ x2i = wk1r * x0i - wk1i * x0r;
+ y9r = x1r - x2r;
+ y9i = x1i - x2i;
+ y13r = x1r + x2r;
+ y13i = x1i + x2i;
+ x0r = a[4] - a[21];
+ x0i = a[5] + a[20];
+ x1r = wk2r * x0r - wk2i * x0i;
+ x1i = wk2r * x0i + wk2i * x0r;
+ x0r = a[12] - a[29];
+ x0i = a[13] + a[28];
+ x2r = wk2i * x0r - wk2r * x0i;
+ x2i = wk2i * x0i + wk2r * x0r;
+ y2r = x1r + x2r;
+ y2i = x1i + x2i;
+ y6r = x1r - x2r;
+ y6i = x1i - x2i;
+ x0r = a[4] + a[21];
+ x0i = a[5] - a[20];
+ x1r = wk2i * x0r - wk2r * x0i;
+ x1i = wk2i * x0i + wk2r * x0r;
+ x0r = a[12] + a[29];
+ x0i = a[13] - a[28];
+ x2r = wk2r * x0r - wk2i * x0i;
+ x2i = wk2r * x0i + wk2i * x0r;
+ y10r = x1r - x2r;
+ y10i = x1i - x2i;
+ y14r = x1r + x2r;
+ y14i = x1i + x2i;
+ x0r = a[6] - a[23];
+ x0i = a[7] + a[22];
+ x1r = wk3r * x0r - wk3i * x0i;
+ x1i = wk3r * x0i + wk3i * x0r;
+ x0r = a[14] - a[31];
+ x0i = a[15] + a[30];
+ x2r = wk1i * x0r - wk1r * x0i;
+ x2i = wk1i * x0i + wk1r * x0r;
+ y3r = x1r + x2r;
+ y3i = x1i + x2i;
+ y7r = x1r - x2r;
+ y7i = x1i - x2i;
+ x0r = a[6] + a[23];
+ x0i = a[7] - a[22];
+ x1r = wk1i * x0r + wk1r * x0i;
+ x1i = wk1i * x0i - wk1r * x0r;
+ x0r = a[14] + a[31];
+ x0i = a[15] - a[30];
+ x2r = wk3i * x0r - wk3r * x0i;
+ x2i = wk3i * x0i + wk3r * x0r;
+ y11r = x1r + x2r;
+ y11i = x1i + x2i;
+ y15r = x1r - x2r;
+ y15i = x1i - x2i;
+ x1r = y0r + y2r;
+ x1i = y0i + y2i;
+ x2r = y1r + y3r;
+ x2i = y1i + y3i;
+ a[0] = x1r + x2r;
+ a[1] = x1i + x2i;
+ a[2] = x1r - x2r;
+ a[3] = x1i - x2i;
+ x1r = y0r - y2r;
+ x1i = y0i - y2i;
+ x2r = y1r - y3r;
+ x2i = y1i - y3i;
+ a[4] = x1r - x2i;
+ a[5] = x1i + x2r;
+ a[6] = x1r + x2i;
+ a[7] = x1i - x2r;
+ x1r = y4r - y6i;
+ x1i = y4i + y6r;
+ x0r = y5r - y7i;
+ x0i = y5i + y7r;
+ x2r = wn4r * (x0r - x0i);
+ x2i = wn4r * (x0i + x0r);
+ a[8] = x1r + x2r;
+ a[9] = x1i + x2i;
+ a[10] = x1r - x2r;
+ a[11] = x1i - x2i;
+ x1r = y4r + y6i;
+ x1i = y4i - y6r;
+ x0r = y5r + y7i;
+ x0i = y5i - y7r;
+ x2r = wn4r * (x0r - x0i);
+ x2i = wn4r * (x0i + x0r);
+ a[12] = x1r - x2i;
+ a[13] = x1i + x2r;
+ a[14] = x1r + x2i;
+ a[15] = x1i - x2r;
+ x1r = y8r + y10r;
+ x1i = y8i + y10i;
+ x2r = y9r - y11r;
+ x2i = y9i - y11i;
+ a[16] = x1r + x2r;
+ a[17] = x1i + x2i;
+ a[18] = x1r - x2r;
+ a[19] = x1i - x2i;
+ x1r = y8r - y10r;
+ x1i = y8i - y10i;
+ x2r = y9r + y11r;
+ x2i = y9i + y11i;
+ a[20] = x1r - x2i;
+ a[21] = x1i + x2r;
+ a[22] = x1r + x2i;
+ a[23] = x1i - x2r;
+ x1r = y12r - y14i;
+ x1i = y12i + y14r;
+ x0r = y13r + y15i;
+ x0i = y13i - y15r;
+ x2r = wn4r * (x0r - x0i);
+ x2i = wn4r * (x0i + x0r);
+ a[24] = x1r + x2r;
+ a[25] = x1i + x2i;
+ a[26] = x1r - x2r;
+ a[27] = x1i - x2i;
+ x1r = y12r + y14i;
+ x1i = y12i - y14r;
+ x0r = y13r - y15i;
+ x0i = y13i + y15r;
+ x2r = wn4r * (x0r - x0i);
+ x2i = wn4r * (x0i + x0r);
+ a[28] = x1r - x2i;
+ a[29] = x1i + x2r;
+ a[30] = x1r + x2i;
+ a[31] = x1i - x2r;
+}
+
+static void AUP_FFTW_cftf081(float* a, float* w) {
+ float wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r,
+ y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;
+
+ wn4r = w[1];
+ x0r = a[0] + a[8];
+ x0i = a[1] + a[9];
+ x1r = a[0] - a[8];
+ x1i = a[1] - a[9];
+ x2r = a[4] + a[12];
+ x2i = a[5] + a[13];
+ x3r = a[4] - a[12];
+ x3i = a[5] - a[13];
+ y0r = x0r + x2r;
+ y0i = x0i + x2i;
+ y2r = x0r - x2r;
+ y2i = x0i - x2i;
+ y1r = x1r - x3i;
+ y1i = x1i + x3r;
+ y3r = x1r + x3i;
+ y3i = x1i - x3r;
+ x0r = a[2] + a[10];
+ x0i = a[3] + a[11];
+ x1r = a[2] - a[10];
+ x1i = a[3] - a[11];
+ x2r = a[6] + a[14];
+ x2i = a[7] + a[15];
+ x3r = a[6] - a[14];
+ x3i = a[7] - a[15];
+ y4r = x0r + x2r;
+ y4i = x0i + x2i;
+ y6r = x0r - x2r;
+ y6i = x0i - x2i;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ x2r = x1r + x3i;
+ x2i = x1i - x3r;
+ y5r = wn4r * (x0r - x0i);
+ y5i = wn4r * (x0r + x0i);
+ y7r = wn4r * (x2r - x2i);
+ y7i = wn4r * (x2r + x2i);
+ a[8] = y1r + y5r;
+ a[9] = y1i + y5i;
+ a[10] = y1r - y5r;
+ a[11] = y1i - y5i;
+ a[12] = y3r - y7i;
+ a[13] = y3i + y7r;
+ a[14] = y3r + y7i;
+ a[15] = y3i - y7r;
+ a[0] = y0r + y4r;
+ a[1] = y0i + y4i;
+ a[2] = y0r - y4r;
+ a[3] = y0i - y4i;
+ a[4] = y2r - y6i;
+ a[5] = y2i + y6r;
+ a[6] = y2r + y6i;
+ a[7] = y2i - y6r;
+}
+
+static void AUP_FFTW_cftf082(float* a, float* w) {
+ float wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i, y3r,
+ y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;
+
+ wn4r = w[1];
+ wk1r = w[2];
+ wk1i = w[3];
+ y0r = a[0] - a[9];
+ y0i = a[1] + a[8];
+ y1r = a[0] + a[9];
+ y1i = a[1] - a[8];
+ x0r = a[4] - a[13];
+ x0i = a[5] + a[12];
+ y2r = wn4r * (x0r - x0i);
+ y2i = wn4r * (x0i + x0r);
+ x0r = a[4] + a[13];
+ x0i = a[5] - a[12];
+ y3r = wn4r * (x0r - x0i);
+ y3i = wn4r * (x0i + x0r);
+ x0r = a[2] - a[11];
+ x0i = a[3] + a[10];
+ y4r = wk1r * x0r - wk1i * x0i;
+ y4i = wk1r * x0i + wk1i * x0r;
+ x0r = a[2] + a[11];
+ x0i = a[3] - a[10];
+ y5r = wk1i * x0r - wk1r * x0i;
+ y5i = wk1i * x0i + wk1r * x0r;
+ x0r = a[6] - a[15];
+ x0i = a[7] + a[14];
+ y6r = wk1i * x0r - wk1r * x0i;
+ y6i = wk1i * x0i + wk1r * x0r;
+ x0r = a[6] + a[15];
+ x0i = a[7] - a[14];
+ y7r = wk1r * x0r - wk1i * x0i;
+ y7i = wk1r * x0i + wk1i * x0r;
+ x0r = y0r + y2r;
+ x0i = y0i + y2i;
+ x1r = y4r + y6r;
+ x1i = y4i + y6i;
+ a[0] = x0r + x1r;
+ a[1] = x0i + x1i;
+ a[2] = x0r - x1r;
+ a[3] = x0i - x1i;
+ x0r = y0r - y2r;
+ x0i = y0i - y2i;
+ x1r = y4r - y6r;
+ x1i = y4i - y6i;
+ a[4] = x0r - x1i;
+ a[5] = x0i + x1r;
+ a[6] = x0r + x1i;
+ a[7] = x0i - x1r;
+ x0r = y1r - y3i;
+ x0i = y1i + y3r;
+ x1r = y5r - y7r;
+ x1i = y5i - y7i;
+ a[8] = x0r + x1r;
+ a[9] = x0i + x1i;
+ a[10] = x0r - x1r;
+ a[11] = x0i - x1i;
+ x0r = y1r + y3i;
+ x0i = y1i - y3r;
+ x1r = y5r + y7r;
+ x1i = y5i + y7i;
+ a[12] = x0r - x1i;
+ a[13] = x0i + x1r;
+ a[14] = x0r + x1i;
+ a[15] = x0i - x1r;
+}
+
+static void AUP_FFTW_cftf040(float* a) {
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ x0r = a[0] + a[4];
+ x0i = a[1] + a[5];
+ x1r = a[0] - a[4];
+ x1i = a[1] - a[5];
+ x2r = a[2] + a[6];
+ x2i = a[3] + a[7];
+ x3r = a[2] - a[6];
+ x3i = a[3] - a[7];
+ a[0] = x0r + x2r;
+ a[1] = x0i + x2i;
+ a[2] = x1r - x3i;
+ a[3] = x1i + x3r;
+ a[4] = x0r - x2r;
+ a[5] = x0i - x2i;
+ a[6] = x1r + x3i;
+ a[7] = x1i - x3r;
+}
+
+static void AUP_FFTW_cftb040(float* a) {
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ x0r = a[0] + a[4];
+ x0i = a[1] + a[5];
+ x1r = a[0] - a[4];
+ x1i = a[1] - a[5];
+ x2r = a[2] + a[6];
+ x2i = a[3] + a[7];
+ x3r = a[2] - a[6];
+ x3i = a[3] - a[7];
+ a[0] = x0r + x2r;
+ a[1] = x0i + x2i;
+ a[2] = x1r + x3i;
+ a[3] = x1i - x3r;
+ a[4] = x0r - x2r;
+ a[5] = x0i - x2i;
+ a[6] = x1r - x3i;
+ a[7] = x1i + x3r;
+}
+
+static void AUP_FFTW_cftx020(float* a) {
+ float x0r, x0i;
+
+ x0r = a[0] - a[2];
+ x0i = a[1] - a[3];
+ a[0] += a[2];
+ a[1] += a[3];
+ a[2] = x0r;
+ a[3] = x0i;
+}
+
+static void AUP_FFTW_rftfsub(int n, float* a, int nc, float* c) {
+ int j, k, kk, ks, m;
+ float wkr, wki, xr, xi, yr, yi;
+
+ m = n >> 1;
+ ks = 2 * nc / m;
+ kk = 0;
+ for (j = 2; j < m; j += 2) {
+ k = n - j;
+ kk += ks;
+ wkr = 0.5f - c[nc - kk];
+ wki = c[kk];
+ xr = a[j] - a[k];
+ xi = a[j + 1] + a[k + 1];
+ yr = wkr * xr - wki * xi;
+ yi = wkr * xi + wki * xr;
+ a[j] -= yr;
+ a[j + 1] -= yi;
+ a[k] += yr;
+ a[k + 1] -= yi;
+ }
+}
+
+static void AUP_FFTW_rftbsub(int n, float* a, int nc, float* c) {
+ int j, k, kk, ks, m;
+ float wkr, wki, xr, xi, yr, yi;
+
+ m = n >> 1;
+ ks = 2 * nc / m;
+ kk = 0;
+ for (j = 2; j < m; j += 2) {
+ k = n - j;
+ kk += ks;
+ wkr = 0.5f - c[nc - kk];
+ wki = c[kk];
+ xr = a[j] - a[k];
+ xi = a[j + 1] + a[k + 1];
+ yr = wkr * xr + wki * xi;
+ yi = wkr * xi - wki * xr;
+ a[j] -= yr;
+ a[j + 1] -= yi;
+ a[k] += yr;
+ a[k + 1] -= yi;
+ }
+}
+
+static void AUP_FFTW_dctsub(int n, float* a, int nc, float* c) {
+ int j, k, kk, ks, m;
+ float wkr, wki, xr;
+
+ m = n >> 1;
+ ks = nc / n;
+ kk = 0;
+ for (j = 1; j < m; j++) {
+ k = n - j;
+ kk += ks;
+ wkr = c[kk] - c[nc - kk];
+ wki = c[kk] + c[nc - kk];
+ xr = wki * a[j] - wkr * a[k];
+ a[j] = wkr * a[j] + wki * a[k];
+ a[k] = xr;
+ }
+ a[m] *= c[0];
+}
+
+static void AUP_FFTW_dstsub(int n, float* a, int nc, float* c) {
+ int j, k, kk, ks, m;
+ float wkr, wki, xr;
+
+ m = n >> 1;
+ ks = nc / n;
+ kk = 0;
+ for (j = 1; j < m; j++) {
+ k = n - j;
+ kk += ks;
+ wkr = c[kk] - c[nc - kk];
+ wki = c[kk] + c[nc - kk];
+ xr = wki * a[k] - wkr * a[j];
+ a[k] = wkr * a[k] + wki * a[j];
+ a[j] = xr;
+ }
+ a[m] *= c[0];
+}
+
+static void AUP_FFTW_rdft(int n, int isgn, float* a, int* ip, float* w) {
+ float xi;
+
+ int nw = ip[0];
+ int nc = ip[1];
+
+ if (isgn >= 0) {
+ if (n > 4) {
+ AUP_FFTW_cftfsub(n, a, ip, nw, w);
+ AUP_FFTW_rftfsub(n, a, nc, w + nw);
+ } else if (n == 4) {
+ AUP_FFTW_cftfsub(n, a, ip, nw, w);
+ }
+ xi = a[0] - a[1];
+ a[0] += a[1];
+ a[1] = xi;
+ } else {
+ a[1] = 0.5f * (a[0] - a[1]);
+ a[0] -= a[1];
+ if (n > 4) {
+ AUP_FFTW_rftbsub(n, a, nc, w + nw);
+ AUP_FFTW_cftbsub(n, a, ip, nw, w);
+ } else if (n == 4) {
+ AUP_FFTW_cftbsub(n, a, ip, nw, w);
+ }
+ }
+}
+
+// ==========================================================================================
+// public APIs
+// ==========================================================================================
+
+void AUP_FFTW_r2c_256(float* in, float* out) {
+ int i;
+
+ float tmp[258] = {0};
+
+ // scale
+ for (i = 0; i < 256; ++i) {
+ tmp[i] = in[i] * 0.00390625f;
+ }
+
+ AUP_FFTW_rdft(256, 1, tmp, (int*)AUP_FFTW_g_ip256, (float*)AUP_FFTW_g_w256);
+
+ out[0] = tmp[0];
+ out[255] = tmp[1];
+ for (i = 1; i < 255; i += 2) {
+ out[i] = tmp[i + 1];
+ out[i + 1] = -tmp[i + 2];
+ }
+}
+
+void AUP_FFTW_c2r_256(float* in, float* out) {
+ int i;
+
+ out[0] = in[0];
+ out[1] = in[255];
+ for (i = 2; i < 256; i += 2) {
+ out[i] = in[i - 1];
+ out[i + 1] = -in[i];
+ }
+
+ AUP_FFTW_rdft(256, -1, out, (int*)AUP_FFTW_g_ip256, (float*)AUP_FFTW_g_w256);
+ /* 1/N */
+ for (i = 0; i < 256; i++) {
+ out[i] *= 2;
+ }
+}
+
+void AUP_FFTW_c2r_512(float* in, float* out) {
+ int i;
+
+ out[0] = in[0];
+ out[1] = in[511];
+ for (i = 2; i < 512; i += 2) {
+ out[i] = in[i - 1];
+ out[i + 1] = -in[i];
+ }
+ AUP_FFTW_rdft(512, -1, out, (int*)AUP_FFTW_g_ip512, (float*)AUP_FFTW_g_w512);
+ /* 1/N */
+ for (i = 0; i < 512; i++) {
+ out[i] *= 2;
+ }
+}
+
+void AUP_FFTW_r2c_512(float* in, float* out) {
+ int i;
+
+ float tmp[514] = {0};
+
+ // scale
+ for (i = 0; i < 512; ++i) {
+ tmp[i] = in[i] * 0.001953125f;
+ }
+
+ AUP_FFTW_rdft(512, 1, tmp, (int*)AUP_FFTW_g_ip512, (float*)AUP_FFTW_g_w512);
+
+ out[0] = tmp[0];
+ out[511] = tmp[1];
+ for (i = 1; i < 511; i += 2) {
+ out[i] = tmp[i + 1];
+ out[i + 1] = -tmp[i + 2];
+ }
+}
+
+void AUP_FFTW_r2c_1024(float* in, float* out) {
+ int i;
+
+ float tmp[1026] = {0};
+ // scale
+ for (i = 0; i < 1024; ++i) {
+ tmp[i] = in[i] * 0.0009765625f;
+ }
+
+ AUP_FFTW_rdft(1024, 1, tmp, (int*)AUP_FFTW_g_ip1024,
+ (float*)AUP_FFTW_g_w1024);
+
+ out[0] = tmp[0];
+ out[1023] = tmp[1];
+ for (i = 1; i < 1023; i += 2) {
+ out[i] = tmp[i + 1];
+ out[i + 1] = -tmp[i + 2];
+ }
+}
+
+void AUP_FFTW_c2r_1024(float* in, float* out) {
+ int i;
+ // memcpy(out,in,sizeof(float)*1024);
+ out[0] = in[0];
+ out[1] = in[1023];
+ for (i = 2; i < 1024; i += 2) {
+ out[i] = in[i - 1];
+ out[i + 1] = -in[i];
+ }
+ AUP_FFTW_rdft(1024, -1, out, (int*)AUP_FFTW_g_ip1024,
+ (float*)AUP_FFTW_g_w1024);
+ /* 1/N */
+ for (i = 0; i < 1024; i++) {
+ out[i] *= 2;
+ }
+}
+
+void AUP_FFTW_r2c_2048(float* in, float* out) {
+ int i;
+
+ float tmp[2050] = {0};
+
+ // scale
+ for (i = 0; i < 2048; ++i) {
+ tmp[i] = in[i] * 0.00048828125f;
+ }
+
+ AUP_FFTW_rdft(2048, 1, tmp, (int*)AUP_FFTW_g_ip2048,
+ (float*)AUP_FFTW_g_w2048);
+
+ out[0] = tmp[0];
+ out[2047] = tmp[1];
+ for (i = 1; i < 2047; i += 2) {
+ out[i] = tmp[i + 1];
+ out[i + 1] = -tmp[i + 2];
+ }
+}
+
+void AUP_FFTW_c2r_2048(float* in, float* out) {
+ int i;
+
+ out[0] = in[0];
+ out[1] = in[2047];
+ for (i = 2; i < 2048; i += 2) {
+ out[i] = in[i - 1];
+ out[i + 1] = -in[i];
+ }
+ AUP_FFTW_rdft(2048, -1, out, (int*)AUP_FFTW_g_ip2048,
+ (float*)AUP_FFTW_g_w2048);
+ /* 1/N */
+ for (i = 0; i < 2048; i++) {
+ out[i] *= 2;
+ }
+}
+
+void AUP_FFTW_r2c_4096(float* in, float* out) {
+ int i;
+
+ float tmp[4098] = {0};
+
+ // scale
+ for (i = 0; i < 4096; ++i) {
+ tmp[i] = in[i] * 0.000244140625f;
+ }
+
+ AUP_FFTW_rdft(4096, 1, tmp, (int*)AUP_FFTW_g_ip4096,
+ (float*)AUP_FFTW_g_w4096);
+
+ out[0] = tmp[0];
+ out[4095] = tmp[1];
+ for (i = 1; i < 4095; i += 2) {
+ out[i] = tmp[i + 1];
+ out[i + 1] = -tmp[i + 2];
+ }
+}
+
+void AUP_FFTW_c2r_4096(float* in, float* out) {
+ int i;
+
+ out[0] = in[0];
+ out[1] = in[4095];
+ for (i = 2; i < 4096; i += 2) {
+ out[i] = in[i - 1];
+ out[i + 1] = -in[i];
+ }
+ AUP_FFTW_rdft(4096, -1, out, (int*)AUP_FFTW_g_ip4096,
+ (float*)AUP_FFTW_g_w4096);
+ for (i = 0; i < 4096; i++) {
+ out[i] *= 2;
+ }
+}
+
+// if direction == 0: format1->format2
+// if direction == 1: format2->format1
+void AUP_FFTW_InplaceTransf(int direction, int fftSz, float* inplaceTranfBuf) {
+ float nyqReal;
+ int idx;
+
+ if (direction == 0) {
+ // [Real-0, Real-Nyq, Real-1, Imag-1, Real-2, Imag-2, ...] ->
+ // [Real-0, Real-1, (-1)*Imag-1, Real-2, (-1)*Imag-2, ..., Real-Nyq]
+ nyqReal = inplaceTranfBuf[1];
+ for (idx = 1; idx < (fftSz - 1); idx += 2) {
+ inplaceTranfBuf[idx] = inplaceTranfBuf[idx + 1];
+ inplaceTranfBuf[idx + 1] = -(inplaceTranfBuf[idx + 2]);
+ }
+ inplaceTranfBuf[fftSz - 1] = nyqReal;
+ } else {
+ // [Real-0, Real-1, (-1)*Imag-1, Real-2, (-1)*Imag-2, ..., Real-Nyq] ->
+ // [Real-0, Real-Nyq, Real-1, Imag-1, Real-2, Imag-2, ...]
+ nyqReal = inplaceTranfBuf[fftSz - 1];
+ for (idx = fftSz - 1; idx > 2; idx -= 2) {
+ inplaceTranfBuf[idx] = -(inplaceTranfBuf[idx - 1]);
+ inplaceTranfBuf[idx - 1] = inplaceTranfBuf[idx - 2];
+ }
+ inplaceTranfBuf[1] = nyqReal;
+ }
+ return;
+}
+
+void AUP_FFTW_RescaleFFTOut(int fftSz, float* inplaceBuf) {
+ int idx;
+ for (idx = 0; idx < fftSz; idx++) {
+ inplaceBuf[idx] *= (float)fftSz;
+ }
+ return;
+}
+
+void AUP_FFTW_RescaleIFFTOut(int fftSz, float* inplaceBuf) {
+ int idx;
+ for (idx = 0; idx < fftSz; idx++) {
+ inplaceBuf[idx] *= 0.5f;
+ }
+ return;
+}
diff --git a/src/fftw.h b/src/fftw.h
new file mode 100644
index 0000000000000000000000000000000000000000..a505dafb675cbc14a0b83015bde1ee8e9c2cb395
--- /dev/null
+++ b/src/fftw.h
@@ -0,0 +1,47 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __FFTW_H__
+#define __FFTW_H__
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+// Spectrum Storage Format definition:
+// format1: [Real-0, Real-Nyq, Real-1, Imag-1, Real-2, Imag-2, ...]
+// format2: [Real-0, Real-1, (-1)*Imag-1, Real-2, (-1)*Imag-2, ..., Real-Nyq]
+
+// the following functions assume input and output spectrum to be stored in
+// format2
+void AUP_FFTW_r2c_256(float* in, float* out);
+void AUP_FFTW_c2r_256(float* in, float* out);
+
+void AUP_FFTW_c2r_512(float* in, float* out);
+void AUP_FFTW_r2c_512(float* in, float* out);
+
+void AUP_FFTW_r2c_1024(float* in, float* out);
+void AUP_FFTW_c2r_1024(float* in, float* out);
+
+void AUP_FFTW_r2c_2048(float* in, float* out);
+void AUP_FFTW_c2r_2048(float* in, float* out);
+
+void AUP_FFTW_r2c_4096(float* in, float* out);
+void AUP_FFTW_c2r_4096(float* in, float* out);
+
+// if direction == 0: format1->format2
+// if direction == 1: format2->format1
+void AUP_FFTW_InplaceTransf(int direction, int fftSz, float* inplaceTranfBuf);
+
+void AUP_FFTW_RescaleFFTOut(int fftSz, float* inplaceBuf);
+void AUP_FFTW_RescaleIFFTOut(int fftSz, float* inplaceBuf);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // __FFTW_H__
diff --git a/src/fscvrt.cc b/src/fscvrt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..77e49c133870abe675d9fef222220a01208b72a3
--- /dev/null
+++ b/src/fscvrt.cc
@@ -0,0 +1,541 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#include
+#include
+#include
+#include
+
+#include "fscvrt.h"
+#include "fscvrt_st.h"
+#include "biquad.h"
+
+// ==========================================================================================
+// internal tools
+// ==========================================================================================
+
+static int AUP_Fscvrt_FilterSet(int resampleRate, int* nsect,
+ const float* B[_FSCVRT_MAXNSEC],
+ const float* A[_FSCVRT_MAXNSEC],
+ const float** G) {
+ int idx;
+ if (resampleRate == 2) {
+ *nsect = _FSCVRT_1over2_LOWPASS_NSEC;
+ for (idx = 0; idx < (*nsect); idx++) {
+ B[idx] = &(_FSCVRT_1over2_LOWPASS_B[idx][0]);
+ A[idx] = &(_FSCVRT_1over2_LOWPASS_A[idx][0]);
+ }
+ *G = _FSCVRT_1over2_LOWPASS_G;
+ } else if (resampleRate == 3) {
+ *nsect = _FSCVRT_1over3_LOWPASS_NSEC;
+ for (idx = 0; idx < (*nsect); idx++) {
+ B[idx] = &(_FSCVRT_1over3_LOWPASS_B[idx][0]);
+ A[idx] = &(_FSCVRT_1over3_LOWPASS_A[idx][0]);
+ }
+ *G = _FSCVRT_1over3_LOWPASS_G;
+ } else if (resampleRate == 4) {
+ *nsect = _FSCVRT_1over4_LOWPASS_NSEC;
+ for (idx = 0; idx < (*nsect); idx++) {
+ B[idx] = &(_FSCVRT_1over4_LOWPASS_B[idx][0]);
+ A[idx] = &(_FSCVRT_1over4_LOWPASS_A[idx][0]);
+ }
+ *G = _FSCVRT_1over4_LOWPASS_G;
+ } else if (resampleRate == 6) {
+ *nsect = _FSCVRT_1over6_LOWPASS_NSEC;
+ for (idx = 0; idx < (*nsect); idx++) {
+ B[idx] = &(_FSCVRT_1over6_LOWPASS_B[idx][0]);
+ A[idx] = &(_FSCVRT_1over6_LOWPASS_A[idx][0]);
+ }
+ *G = _FSCVRT_1over6_LOWPASS_G;
+ } else { // unknown resample rate
+ return -1;
+ }
+
+ return 0;
+}
+
+static int AUP_Fscvrt_dynamMemPrepare(FscvrtSt* stHdl, void* memPtrExt,
+ size_t memSize) {
+ char* memPtr = NULL;
+ int biquadInBufMemSize = 0;
+ int biquadOutBufMemSize = 0;
+ int totalMemSize = 0;
+
+ if (stHdl == NULL) {
+ return -1;
+ }
+
+ biquadInBufMemSize = _FSCVRT_ALIGN8(sizeof(float) * stHdl->biquadInBufLen);
+ totalMemSize += biquadInBufMemSize;
+
+ biquadOutBufMemSize = _FSCVRT_ALIGN8(sizeof(float) * stHdl->biquadOutBufLen);
+ totalMemSize += biquadOutBufMemSize;
+
+ totalMemSize = _FSCVRT_MAX(totalMemSize, 80);
+
+ // if no external memory provided, we are only profiling the memory
+ // requirement
+ if (memPtrExt == NULL) {
+ return (totalMemSize);
+ }
+
+ // if required memory is more than provided, error
+ if ((size_t)totalMemSize > memSize) {
+ return -1;
+ }
+ memPtr = (char*)memPtrExt;
+
+ stHdl->biquadInBuf = NULL;
+ if (biquadInBufMemSize != 0) {
+ stHdl->biquadInBuf = (float*)memPtr;
+ memPtr += biquadInBufMemSize;
+ }
+
+ stHdl->biquadOutBuf = NULL;
+ if (biquadOutBufMemSize != 0) {
+ stHdl->biquadOutBuf = (float*)memPtr;
+ memPtr += biquadOutBufMemSize;
+ }
+
+ if (((int)(memPtr - (char*)memPtrExt)) > totalMemSize) {
+ return -1;
+ }
+
+ return (totalMemSize);
+}
+
+static int AUP_Fscvrt_checkStatCfg(FscvrtStaticCfg* pCfg) {
+ if (pCfg == NULL) {
+ return -1;
+ }
+
+ if (pCfg->inputFs != 16000 && pCfg->inputFs != 24000 &&
+ pCfg->inputFs != 32000 && pCfg->inputFs != 48000) {
+ return -1;
+ }
+
+ if (pCfg->outputFs != 16000 && pCfg->outputFs != 24000 &&
+ pCfg->outputFs != 32000 && pCfg->outputFs != 48000) {
+ return -1;
+ }
+
+ if (pCfg->stepSz > AUP_FSCVRT_MAX_INPUT_LEN || pCfg->stepSz < 1) {
+ return -1;
+ }
+
+ if (pCfg->inputType != 0) {
+ pCfg->inputType = 1;
+ }
+
+ if (pCfg->outputType != 0) {
+ pCfg->outputType = 1;
+ }
+
+ return 0;
+}
+
+static int AUP_Fscvrt_publishStaticCfg(FscvrtSt* stHdl) {
+ int tmpRatio;
+ int ret;
+ int maxResmplRate = 0;
+
+ stHdl->mode = 0;
+ stHdl->upSmplRate = 1;
+ stHdl->downSmplRate = 1;
+ if (stHdl->stCfg.inputFs != stHdl->stCfg.outputFs) {
+ if (stHdl->stCfg.outputFs > stHdl->stCfg.inputFs) {
+ tmpRatio = (stHdl->stCfg.outputFs / stHdl->stCfg.inputFs);
+ if (stHdl->stCfg.outputFs == tmpRatio * stHdl->stCfg.inputFs) {
+ stHdl->mode = 1;
+ stHdl->upSmplRate = tmpRatio;
+ stHdl->downSmplRate = 1;
+ } else {
+ stHdl->mode = 3;
+ stHdl->upSmplRate = _FSCVRT_COMMON_FS / stHdl->stCfg.inputFs;
+ stHdl->downSmplRate = _FSCVRT_COMMON_FS / stHdl->stCfg.outputFs;
+ }
+ } else { // stHdl->stCfg.outputFs < stHdl->stCfg.inputFs
+ tmpRatio = (stHdl->stCfg.inputFs / stHdl->stCfg.outputFs);
+ if (stHdl->stCfg.inputFs == tmpRatio * stHdl->stCfg.outputFs) {
+ stHdl->mode = 2;
+ stHdl->upSmplRate = 1;
+ stHdl->downSmplRate = tmpRatio;
+ } else {
+ stHdl->mode = 3;
+ stHdl->upSmplRate = _FSCVRT_COMMON_FS / stHdl->stCfg.inputFs;
+ stHdl->downSmplRate = _FSCVRT_COMMON_FS / stHdl->stCfg.outputFs;
+ }
+ }
+ }
+
+ if (stHdl->mode == 0) {
+ stHdl->biquadInBufLen = 0;
+ stHdl->biquadOutBufLen = 0;
+ } else {
+ stHdl->biquadInBufLen = stHdl->stCfg.stepSz * stHdl->upSmplRate;
+ stHdl->biquadOutBufLen = 2 * (stHdl->stCfg.stepSz * stHdl->upSmplRate);
+ }
+
+ maxResmplRate = _FSCVRT_MAX(stHdl->upSmplRate, stHdl->downSmplRate);
+
+ stHdl->nSec = 0;
+ memset(stHdl->biquadB, 0, sizeof(stHdl->biquadB));
+ memset(stHdl->biquadA, 0, sizeof(stHdl->biquadA));
+ stHdl->biquadG = NULL; // gain for each section
+
+ if (stHdl->mode != 0) {
+ ret = AUP_Fscvrt_FilterSet(maxResmplRate, &(stHdl->nSec), stHdl->biquadB,
+ stHdl->biquadA, &(stHdl->biquadG));
+ if (ret < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int AUP_Fscvrt_resetVariables(FscvrtSt* stHdl) {
+ stHdl->biquadInBufCnt = 0;
+ stHdl->biquadOutBufCnt = 0;
+
+ if (stHdl->dynamMemPtr != NULL && stHdl->dynamMemSize > 0) {
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+ }
+ return 0;
+}
+
+// ==========================================================================================
+// public APIs
+// ==========================================================================================
+
+int AUP_Fscvrt_create(void** stPtr) {
+ FscvrtSt* tmpPtr;
+
+ if (stPtr == NULL) {
+ return -1;
+ }
+ *stPtr = (void*)malloc(sizeof(FscvrtSt));
+ if (*stPtr == NULL) {
+ return -1;
+ }
+ memset(*stPtr, 0, sizeof(FscvrtSt));
+
+ tmpPtr = (FscvrtSt*)(*stPtr);
+
+ tmpPtr->dynamMemPtr = NULL;
+ tmpPtr->dynamMemSize = 0;
+
+ tmpPtr->stCfg.inputFs = 24000;
+ tmpPtr->stCfg.outputFs = 32000;
+ tmpPtr->stCfg.stepSz = 240; // 10ms processing step
+ tmpPtr->stCfg.inputType = 0; // short in
+ tmpPtr->stCfg.outputType = 0; // short out
+
+ if (AUP_Biquad_create(&(tmpPtr->biquadSt)) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_Fscvrt_destroy(void** stPtr) {
+ FscvrtSt* stHdl;
+
+ if (stPtr == NULL) {
+ return 0;
+ }
+
+ stHdl = (FscvrtSt*)(*stPtr);
+ if (stHdl == NULL) {
+ return 0;
+ }
+
+ AUP_Biquad_destroy(&(stHdl->biquadSt));
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ }
+ stHdl->dynamMemPtr = NULL;
+
+ free(stHdl);
+ (*stPtr) = NULL;
+
+ return 0;
+}
+
+int AUP_Fscvrt_memAllocate(void* stPtr, const FscvrtStaticCfg* pCfg) {
+ FscvrtSt* stHdl = NULL;
+ FscvrtStaticCfg tmpStatCfg = {0};
+ Biquad_StaticCfg bqStatCfg;
+ int idx, ret;
+ int totalMemSize = 0;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+ stHdl = (FscvrtSt*)(stPtr);
+
+ memcpy(&tmpStatCfg, pCfg, sizeof(FscvrtStaticCfg));
+ if (AUP_Fscvrt_checkStatCfg(&tmpStatCfg) < 0) {
+ return -1;
+ }
+ memcpy(&(stHdl->stCfg), &tmpStatCfg, sizeof(FscvrtStaticCfg));
+
+ if (AUP_Fscvrt_publishStaticCfg(stHdl) < 0) {
+ return -1;
+ }
+
+ // check memory requirement
+ totalMemSize = AUP_Fscvrt_dynamMemPrepare(stHdl, NULL, 0);
+ if (totalMemSize < 0) {
+ return -1;
+ }
+
+ // allocate dynamic memory
+ if ((size_t)totalMemSize > stHdl->dynamMemSize) {
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ stHdl->dynamMemSize = 0;
+ }
+ stHdl->dynamMemPtr = (void*)malloc(totalMemSize);
+ if (stHdl->dynamMemPtr == NULL) {
+ return -1;
+ }
+ stHdl->dynamMemSize = totalMemSize;
+ }
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+
+ // setup the pointers/variable
+ if (AUP_Fscvrt_dynamMemPrepare(stHdl, stHdl->dynamMemPtr,
+ stHdl->dynamMemSize) < 0) {
+ return -1;
+ }
+
+ // memAllocation for upSmplBiquadSt and downSmplBiquadSt
+ if (stHdl->nSec != 0) {
+ if (stHdl->nSec > AGORA_UAP_BIQUAD_MAX_SECTION) {
+ return -1;
+ }
+ memset(&bqStatCfg, 0, sizeof(Biquad_StaticCfg));
+ bqStatCfg.maxNSample = (size_t)(stHdl->biquadInBufLen);
+ bqStatCfg.nsect = stHdl->nSec;
+ for (idx = 0; idx < stHdl->nSec; idx++) {
+ bqStatCfg.B[idx] = stHdl->biquadB[idx];
+ bqStatCfg.A[idx] = stHdl->biquadA[idx];
+ }
+ bqStatCfg.G = stHdl->biquadG;
+
+ ret = AUP_Biquad_memAllocate(stHdl->biquadSt, &bqStatCfg);
+ if (ret < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int AUP_Fscvrt_init(void* stPtr) {
+ FscvrtSt* stHdl;
+
+ if (stPtr == NULL) {
+ return -1;
+ }
+ stHdl = (FscvrtSt*)(stPtr);
+
+ // clear/reset run-time variables
+ if (AUP_Fscvrt_resetVariables(stHdl) < 0) {
+ return -1;
+ }
+
+ // init submodules ...
+ if (stHdl->biquadSt != NULL && stHdl->nSec != 0) {
+ if (AUP_Biquad_init(stHdl->biquadSt) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int AUP_Fscvrt_getStaticCfg(const void* stPtr, FscvrtStaticCfg* pCfg) {
+ const FscvrtSt* stHdl;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+ stHdl = (const FscvrtSt*)(stPtr);
+
+ memcpy(pCfg, &(stHdl->stCfg), sizeof(FscvrtStaticCfg));
+
+ return 0;
+}
+
+int AUP_Fscvrt_getInfor(const void* stPtr, FscvrtGetData* buff) {
+ const FscvrtSt* stHdl;
+ int delayBiquad = 0;
+ int tmp;
+
+ if (stPtr == NULL || buff == NULL) {
+ return -1;
+ }
+ stHdl = (const FscvrtSt*)(stPtr);
+
+ if (stHdl->nSec != 0) {
+ if (AUP_Biquad_getAlgDelay(stHdl->biquadSt, &delayBiquad) < 0) {
+ return -1;
+ }
+ }
+
+ if (stHdl->mode == 0) {
+ buff->delayInInputFs = 0;
+ } else if (stHdl->mode == 1) {
+ buff->delayInInputFs =
+ (int)roundf(delayBiquad / (float)(stHdl->upSmplRate));
+ } else if (stHdl->mode == 2) { // direct downsampling
+ buff->delayInInputFs = delayBiquad;
+ } else { // stHdl->mode == 3
+ buff->delayInInputFs =
+ (int)roundf(delayBiquad / (float)(stHdl->upSmplRate));
+ }
+ tmp = stHdl->stCfg.stepSz * stHdl->upSmplRate / stHdl->downSmplRate;
+ if (tmp * stHdl->downSmplRate == stHdl->stCfg.stepSz * stHdl->upSmplRate) {
+ buff->maxOutputStepSz = tmp;
+ } else {
+ buff->maxOutputStepSz = tmp + 1;
+ }
+
+ return 0;
+}
+
+int AUP_Fscvrt_proc(void* stPtr, const FscvrtInData* pIn, FscvrtOutData* pOut) {
+ FscvrtSt* stHdl = NULL;
+ const FscvrtStaticCfg* pCfg;
+ Biquad_InputData bqdInData;
+ Biquad_OutputData bqdOutData;
+ const short* shortSrcPtr = NULL;
+ const float* floatSrcPtr = NULL;
+ short* shortTgtPtr = NULL;
+ float* floatTgtPtr = NULL;
+ int idx, tgtIdx;
+ int nOutSamples = 0, samplesTaken = 0, samplesLeft = 0;
+ int jumpRate;
+
+ if (stPtr == NULL || pIn == NULL || pOut == NULL || pIn->inDataSeq == NULL ||
+ pOut->outDataSeq == NULL) { // pCtrl == NULL
+ return -1;
+ }
+
+ stHdl = (FscvrtSt*)(stPtr);
+ pCfg = (const FscvrtStaticCfg*)&(stHdl->stCfg);
+ shortSrcPtr = (const short*)(pIn->inDataSeq);
+ floatSrcPtr = (const float*)(pIn->inDataSeq);
+ // ==============================================================================
+ // mode-0: bypass
+ if (stHdl->mode == 0) { // direct bypass
+ if (pIn->outDataSeqLen < pCfg->stepSz) {
+ return -1;
+ }
+ pOut->nOutData = pCfg->stepSz;
+ pOut->outDataType = pCfg->outputType;
+ if (pIn->inDataSeq == pOut->outDataSeq) {
+ if (pCfg->outputType == pCfg->inputType)
+ return 0; // we don't need to do anything
+ return -1;
+ // if input buffer and the output buffer are the same, but required
+ // different data type: error, we currently do not support such usecase
+ }
+
+ if (pCfg->inputType == 0 && pCfg->outputType == 0) {
+ memcpy(pOut->outDataSeq, pIn->inDataSeq, sizeof(short) * pCfg->stepSz);
+ } else if (pCfg->inputType == 1 && pCfg->outputType == 1) {
+ memcpy(pOut->outDataSeq, pIn->inDataSeq, sizeof(float) * pCfg->stepSz);
+ } else if (pCfg->inputType == 0 && pCfg->outputType == 1) {
+ for (idx = 0; idx < pCfg->stepSz; idx++) {
+ ((float*)pOut->outDataSeq)[idx] = ((short*)pIn->inDataSeq)[idx];
+ }
+ } else { // if (pCfg->inputType == 1 && pCfg->outputType == 0)
+ for (idx = 0; idx < pCfg->stepSz; idx++) {
+ ((short*)pOut->outDataSeq)[idx] =
+ (short)_FSCVRT_FLOAT2SHORT(((float*)pIn->inDataSeq)[idx]);
+ }
+ }
+
+ return 0;
+ }
+
+ // prepare input buffer for Biquad .....
+ memset(stHdl->biquadInBuf, 0, sizeof(float) * stHdl->biquadInBufLen);
+ if (pCfg->inputType == 0) {
+ for (idx = 0; idx < pCfg->stepSz; idx++) {
+ stHdl->biquadInBuf[idx * (stHdl->upSmplRate)] =
+ ((float)shortSrcPtr[idx]) * stHdl->upSmplRate;
+ }
+ } else {
+ for (idx = 0; idx < pCfg->stepSz; idx++) {
+ stHdl->biquadInBuf[idx * (stHdl->upSmplRate)] =
+ floatSrcPtr[idx] * stHdl->upSmplRate;
+ }
+ }
+
+ // biquad filtering ......
+ memset(&bqdInData, 0, sizeof(Biquad_InputData));
+ memset(&bqdOutData, 0, sizeof(Biquad_OutputData));
+ bqdInData.samplesPtr = (const void*)(stHdl->biquadInBuf);
+ bqdInData.sampleType = 1;
+ bqdInData.nsamples = (size_t)(pCfg->stepSz * stHdl->upSmplRate);
+ bqdOutData.outputBuff = (void*)&(stHdl->biquadOutBuf[stHdl->biquadOutBufCnt]);
+ if (stHdl->biquadOutBufCnt + (pCfg->stepSz * stHdl->upSmplRate) >
+ stHdl->biquadOutBufLen) {
+ return -1;
+ }
+ if (AUP_Biquad_proc(stHdl->biquadSt, &bqdInData, &bqdOutData) < 0) {
+ return -1;
+ }
+ stHdl->biquadOutBufCnt += (pCfg->stepSz * stHdl->upSmplRate);
+
+ // checking the output buffer .........
+ nOutSamples = stHdl->biquadOutBufCnt / stHdl->downSmplRate;
+ if (pIn->outDataSeqLen < nOutSamples) {
+ return -1;
+ }
+
+ // prepare output data, downsampling and throwing out ......
+ pOut->nOutData = nOutSamples;
+ pOut->outDataType = pCfg->outputType;
+
+ shortTgtPtr = (short*)pOut->outDataSeq;
+ floatTgtPtr = (float*)pOut->outDataSeq;
+ jumpRate = stHdl->downSmplRate;
+ if (pCfg->outputType == 0) { // -> shortTgtPtr
+ for (idx = (jumpRate - 1), tgtIdx = 0; idx < stHdl->biquadOutBufCnt;
+ idx += jumpRate, tgtIdx++) {
+ shortTgtPtr[tgtIdx] = _FSCVRT_FLOAT2SHORT(stHdl->biquadOutBuf[idx]);
+ }
+ } else { // -> floatTgtPtr
+ for (idx = (jumpRate - 1), tgtIdx = 0; idx < stHdl->biquadOutBufCnt;
+ idx += jumpRate, tgtIdx++) {
+ floatTgtPtr[tgtIdx] = stHdl->biquadOutBuf[idx];
+ }
+ }
+ if (nOutSamples != tgtIdx) {
+ return -1;
+ }
+
+ // update the stHdl->biquadOutBuf and stHdl->biquadOutBufCnt
+ samplesTaken = nOutSamples * jumpRate;
+ samplesLeft = stHdl->biquadOutBufCnt - samplesTaken;
+ if (samplesLeft == 0) {
+ stHdl->biquadOutBufCnt = 0;
+ } else if (samplesLeft > 0) {
+ stHdl->biquadOutBufCnt = samplesLeft;
+ memmove(stHdl->biquadOutBuf, &(stHdl->biquadOutBuf[samplesTaken]),
+ sizeof(float) * samplesLeft);
+ } else { // samplesLeft < 0
+ stHdl->biquadOutBufCnt = 0;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/fscvrt.h b/src/fscvrt.h
new file mode 100644
index 0000000000000000000000000000000000000000..8dbda887aed8276b90773e6727d5b96bbbd8cba8
--- /dev/null
+++ b/src/fscvrt.h
@@ -0,0 +1,186 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __FSCVRT_H__
+#define __FSCVRT_H__
+
+#define AUP_FSCVRT_MAX_INPUT_LEN (2400)
+// max. number of samples each time can be fed in
+
+#include
+
+typedef struct FscvrtStaticCfg_ {
+ int inputFs; // input stream sampling freq.
+ int outputFs; // output stream sampling freq.
+ int stepSz; // number of input samples per each proc.
+ int inputType; // input data type, 0: short, 1: float
+ int outputType; // output data type, 0: short, 1: float
+} FscvrtStaticCfg;
+
+typedef struct FscvrtInData_ {
+ const void* inDataSeq; // [stepSz], externally provided buffer
+ int outDataSeqLen;
+ // the length of externally provided buffer outDataSeq in OutData
+} FscvrtInData;
+
+typedef struct FscvrtOutData_ {
+ int nOutData; // number of samples in outDataSeq
+ // this value may vary by +-1 from frame-to-frame
+ // and the user needs to check if nOutData <= outDataSeqLen
+ // o.w. the buffer outDataSeq is not long enough
+ int outDataType; // output data type, 0: short, 1: float
+ void* outDataSeq; // [outDataSeqLen], externally provided buffer
+} FscvrtOutData;
+
+typedef struct FscvrtGetData_ {
+ int maxOutputStepSz; // max. number of output samples per each proc.
+ int delayInInputFs; // algorithm delay in terms of samples @ input fs
+} FscvrtGetData;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * AUP_Fscvrt_create(...)
+ *
+ * This function creats a state handler from nothing, which is NOT ready for
+ * processing
+ *
+ * Input:
+ *
+ * Output:
+ * - stPtr : buffer to store the returned state handler
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Fscvrt_create(void** stPtr);
+
+/****************************************************************************
+ * AUP_Fscvrt_destroy(...)
+ *
+ * destroy biquad instance, and releasing all the dynamically allocated memory
+ *
+ * Input:
+ * - stPtr : buffer of State Handler, after this method, this
+ * handler won't be usable anymore
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Fscvrt_destroy(void** stPtr);
+
+/****************************************************************************
+ * AUP_Fscvrt_memAllocate(...)
+ *
+ * This function sets Static Config params and does memory allocation
+ * operation
+ *
+ * Input:
+ * - stPtr : State Handler which was returned by _create
+ * - pCfg : static configuration parameters
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Fscvrt_memAllocate(void* stPtr, const FscvrtStaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Fscvrt_init(...)
+ *
+ * This function resets (initialize) the XXXX module and gets it prepared for
+ * processing
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Fscvrt_init(void* stPtr);
+
+/****************************************************************************
+ * AUP_Fscvrt_setDynamCfg(...)
+ *
+ * This function set dynamic (per-frame variable) configuration
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ * - pCfg : configuration content
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Fscvrt_setDynamCfg(void* stPtr);
+
+/****************************************************************************
+ * AUP_Fscvrt_getStaticCfg(...)
+ *
+ * This function get static configuration status from XXXXX module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - pCfg : configuration content
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Fscvrt_getStaticCfg(const void* stPtr, FscvrtStaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Fscvrt_getInfor(...)
+ *
+ * This function get subsidiary information from Fs-Converter module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - FscvrtGetData : returned information
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Fscvrt_getInfor(const void* stPtr, FscvrtGetData* buff);
+
+/****************************************************************************
+ * AUP_Fscvrt_proc(...)
+ *
+ * process a single frame
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ * - pCtrl : per-frame variable control parameters
+ * - pIn : input data stream
+ *
+ * Output:
+ * - pOut : output data (mask, highband time-domain gain etc.)
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Fscvrt_proc(void* stPtr, const FscvrtInData* pIn, FscvrtOutData* pOut);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // __FSCVRT_H__
diff --git a/src/fscvrt_st.h b/src/fscvrt_st.h
new file mode 100644
index 0000000000000000000000000000000000000000..883fa02751557cdf219a5b61adff46ded7a338a6
--- /dev/null
+++ b/src/fscvrt_st.h
@@ -0,0 +1,123 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __FSCVRT_ST_H__
+#define __FSCVRT_ST_H__
+
+#include
+
+#include "fscvrt.h"
+
+#define _FSCVRT_MAXNSEC (40)
+#define _FSCVRT_COMMON_FS (96000)
+#define _FSCVRT_ALIGN8(o) (((o) + 7) & (~7))
+#define _FSCVRT_FLOAT2SHORT(x) \
+ ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : (short)floor(.5 + (x))))
+#define _FSCVRT_MIN(x, y) ((x > y) ? (y) : (x))
+#define _FSCVRT_MAX(x, y) ((x > y) ? (x) : (y))
+
+#define _FSCVRT_1over2_LOWPASS_NSEC (5)
+static const float _FSCVRT_1over2_LOWPASS_B[_FSCVRT_1over2_LOWPASS_NSEC][3] = {
+ {1.000000e+00f, 1.830863e+00f, 1.000000e+00f},
+ {1.000000e+00f, 1.039654e+00f, 1.000000e+00f},
+ {1.000000e+00f, 4.900788e-01f, 1.000000e+00f},
+ {1.000000e+00f, 2.419292e-01f, 1.000000e+00f},
+ {1.000000e+00f, 1.517919e-01f, 1.000000e+00f}};
+static const float _FSCVRT_1over2_LOWPASS_A[_FSCVRT_1over2_LOWPASS_NSEC][3] = {
+ {1.000000e+00f, -8.445478e-01f, 2.453003e-01f},
+ {1.000000e+00f, -5.469711e-01f, 5.010509e-01f},
+ {1.000000e+00f, -2.646897e-01f, 7.464574e-01f},
+ {1.000000e+00f, -1.074159e-01f, 8.912371e-01f},
+ {1.000000e+00f, -4.448528e-02f, 9.702184e-01f}};
+static const float _FSCVRT_1over2_LOWPASS_G[_FSCVRT_1over2_LOWPASS_NSEC] = {
+ // 4.184914e-01f,4.184914e-01f,4.184914e-01f,4.184914e-01f,4.184914e-01f
+ 4.233410e-01f, 4.233410e-01f, 4.233410e-01f, 4.233410e-01f, 4.233410e-01f};
+
+#define _FSCVRT_1over3_LOWPASS_NSEC (5)
+static const float _FSCVRT_1over3_LOWPASS_B[_FSCVRT_1over3_LOWPASS_NSEC][3] = {
+ {1.000000e+00f, 1.535971e+00f, 1.000000e+00f},
+ {1.000000e+00f, 6.284728e-02f, 1.000000e+00f},
+ {1.000000e+00f, -5.726159e-01f, 1.000000e+00f},
+ {1.000000e+00f, -7.990919e-01f, 1.000000e+00f},
+ {1.000000e+00f, -8.741772e-01f, 1.000000e+00f}};
+static const float _FSCVRT_1over3_LOWPASS_A[_FSCVRT_1over3_LOWPASS_NSEC][3] = {
+ {1.000000e+00f, -1.261229e+00f, 4.351921e-01f},
+ {1.000000e+00f, -1.171732e+00f, 6.072938e-01f},
+ {1.000000e+00f, -1.078980e+00f, 7.901941e-01f},
+ {1.000000e+00f, -1.026436e+00f, 9.073955e-01f},
+ {1.000000e+00f, -1.013524e+00f, 9.743813e-01f}};
+static const float _FSCVRT_1over3_LOWPASS_G[_FSCVRT_1over3_LOWPASS_NSEC] = {
+ // 3.126979e-01f,3.126979e-01f,3.126979e-01f,3.126979e-01f,3.126979e-01f
+ 3.1704682e-01f, 3.1704682e-01f, 3.1704682e-01f, 3.1704682e-01f,
+ 3.1704682e-01f};
+
+#define _FSCVRT_1over4_LOWPASS_NSEC (5)
+static const float _FSCVRT_1over4_LOWPASS_B[_FSCVRT_1over4_LOWPASS_NSEC][3] = {
+ {1.000000e+00f, 1.193034e+00f, 1.000000e+00f},
+ {1.000000e+00f, -5.757392e-01f, 1.000000e+00f},
+ {1.000000e+00f, -1.105338e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.271233e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.323929e+00f, 1.000000e+00f}};
+static const float _FSCVRT_1over4_LOWPASS_A[_FSCVRT_1over4_LOWPASS_NSEC][3] = {
+ {1.000000e+00f, -1.447526e+00f, 5.478735e-01f},
+ {1.000000e+00f, -1.429707e+00f, 6.830356e-01f},
+ {1.000000e+00f, -1.412017e+00f, 8.292100e-01f},
+ {1.000000e+00f, -1.405145e+00f, 9.242718e-01f},
+ {1.000000e+00f, -1.412679e+00f, 9.790443e-01f}};
+static const float _FSCVRT_1over4_LOWPASS_G[_FSCVRT_1over4_LOWPASS_NSEC] = {
+ // 2.700060e-01f,2.700060e-01f,2.700060e-01f,2.700060e-01f,2.700060e-01f
+ 2.7502688e-01f, 2.7502688e-01f, 2.7502688e-01f, 2.7502688e-01f,
+ 2.7502688e-01f};
+
+#define _FSCVRT_1over6_LOWPASS_NSEC (5)
+static const float _FSCVRT_1over6_LOWPASS_B[_FSCVRT_1over6_LOWPASS_NSEC][3] = {
+ {1.000000e+00f, 4.149228e-01f, 1.000000e+00f},
+ {1.000000e+00f, -1.285358e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.583012e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.663823e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.688104e+00f, 1.000000e+00f}};
+static const float _FSCVRT_1over6_LOWPASS_A[_FSCVRT_1over6_LOWPASS_NSEC][3] = {
+ {1.000000e+00f, -1.688731e+00f, 7.264798e-01f},
+ {1.000000e+00f, -1.696982e+00f, 8.146896e-01f},
+ {1.000000e+00f, -1.706117e+00f, 9.049889e-01f},
+ {1.000000e+00f, -1.713737e+00f, 9.598250e-01f},
+ {1.000000e+00f, -1.723161e+00f, 9.892408e-01f}};
+static const float _FSCVRT_1over6_LOWPASS_G[_FSCVRT_1over6_LOWPASS_NSEC] = {
+ // 2.333130e-01f,2.333130e-01f,2.333130e-01f,2.333130e-01f,2.333130e-01f
+ 2.3765156e-01f, 2.3765156e-01f, 2.3765156e-01f, 2.3765156e-01f,
+ 2.3765156e-01f};
+
+typedef struct FscvrtSt_ {
+ void* dynamMemPtr; // memory pointer holding the dynamic memory
+ size_t dynamMemSize; // size of the buffer *dynamMemPtr
+
+ // Static Configuration
+ FscvrtStaticCfg stCfg;
+
+ // Internal Static Config Registers, which are generated from stCfg
+ int mode;
+ // 0: direct bypass, 1: direct upsampling, 2: direct downsampling
+ // 3: upsampling->downsampling
+ int upSmplRate;
+ int downSmplRate;
+ int biquadInBufLen; // biquad input buffer length
+ int biquadOutBufLen; // biquad output buffer length
+
+ int nSec;
+ const float* biquadB[_FSCVRT_MAXNSEC];
+ const float* biquadA[_FSCVRT_MAXNSEC];
+ const float* biquadG; // gain for each section
+
+ // ---------------------------------------------------------------
+ // Variables
+ void* biquadSt; // biqua filter state handler
+ int biquadInBufCnt;
+ float* biquadInBuf; // [biquadInBufLen]
+ int biquadOutBufCnt;
+ float* biquadOutBuf; // [biquadOutBufLen]
+} FscvrtSt;
+
+#endif // __FSCVRT_ST_H__
diff --git a/src/onnx_model/ten-vad.onnx b/src/onnx_model/ten-vad.onnx
new file mode 100644
index 0000000000000000000000000000000000000000..f7fef336ce5390d7c7a0b75f552f1d6315377331
--- /dev/null
+++ b/src/onnx_model/ten-vad.onnx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e10b98a0cab1c98e847fbdda14cb3d45a38336d47535a3f63a0fb6c4e0f4cdf4
+size 315449
diff --git a/src/pitch_est.cc b/src/pitch_est.cc
new file mode 100644
index 0000000000000000000000000000000000000000..19e7ddc271c42a08b2d4e78b91944c0fcd0fe5c2
--- /dev/null
+++ b/src/pitch_est.cc
@@ -0,0 +1,1199 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+// This file contains modified code derived from LPCNet (https://github.com/mozilla/LPCNet),
+// specifically from the following functions:
+// - compute_frame_features() in lpcnet_enc.c
+// - process_superframe() in lpcnet_enc.c
+//
+// Original lpcnet_enc.c code LICENSE Text, licensed under the BSD-2-Clause License:
+// Copyright (c) 2017-2019 Mozilla
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//
+// Original LPCNet LICENSE Text, licensed under the BSD-3-Clause License:
+// Copyright (c) 2017-2018, Mozilla
+// Copyright (c) 2007-2017, Jean-Marc Valin
+// Copyright (c) 2005-2017, Xiph.Org Foundation
+// Copyright (c) 2003-2004, Mark Borgerding
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the Xiph.Org Foundation nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
+// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include
+#include
+#include
+#include
+#include
+
+#include "biquad.h"
+#include "pitch_est.h"
+#include "pitch_est_st.h"
+#include "fftw.h"
+
+// ==========================================================================================
+// internal tools
+// ==========================================================================================
+
+static int AUP_PE_checkStatCfg(PE_StaticCfg* pCfg) {
+ if (pCfg == NULL) {
+ return -1;
+ }
+
+ if (pCfg->fftSz != 256 && pCfg->fftSz != 512 && pCfg->fftSz != 1024) {
+ return -1;
+ }
+ if (pCfg->fftSz > AUP_PE_MAX_FFTSIZE) {
+ return -1;
+ }
+ if (pCfg->anaWindowSz > pCfg->fftSz || pCfg->anaWindowSz < pCfg->hopSz) {
+ return -1;
+ }
+ if (pCfg->hopSz != 64 && pCfg->hopSz != 80 && pCfg->hopSz != 128 &&
+ pCfg->hopSz != 160 && pCfg->hopSz != 256 && pCfg->hopSz != 512) {
+ return -1;
+ }
+
+ if (pCfg->useLPCPreFiltering != 0) {
+ pCfg->useLPCPreFiltering = 1;
+ }
+
+ if (pCfg->procFs != 2000 && pCfg->procFs != 4000 && pCfg->procFs != 8000 &&
+ pCfg->procFs != 16000) {
+ pCfg->procFs = 4000;
+ }
+
+ return 0;
+}
+
+static int AUP_PE_checkDynamCfg(PE_DynamCfg* pCfg) {
+ if (pCfg == NULL) {
+ return -1;
+ }
+
+ pCfg->voicedThr = AUP_PE_MIN(2.0f, AUP_PE_MAX(pCfg->voicedThr, -1.0f));
+
+ return 0;
+}
+
+static int AUP_PE_publishStaticCfg(PE_St* stHdl) {
+ const PE_StaticCfg* pStatCfg;
+ int idx, jdx;
+ int hopSz;
+ int excBufShiftLen;
+
+ if (stHdl == NULL) {
+ return -1;
+ }
+ pStatCfg = (const PE_StaticCfg*)(&(stHdl->stCfg));
+ hopSz = (int)pStatCfg->hopSz;
+
+ stHdl->nBins = ((int)(pStatCfg->fftSz >> 1)) + 1;
+ stHdl->procResampleRate = AUP_PE_FS / (int)pStatCfg->procFs;
+ stHdl->minPeriod = AUP_PE_MIN_PERIOD_16KHZ / stHdl->procResampleRate;
+ stHdl->maxPeriod = AUP_PE_MAX_PERIOD_16KHZ / stHdl->procResampleRate;
+ stHdl->difPeriod = stHdl->maxPeriod - stHdl->minPeriod;
+ stHdl->inputResampleBufLen = hopSz * 2; // give it a max. value
+ stHdl->inputQLen = AUP_PE_MAX(AUP_PE_XCORR_TRAINING_OFFSET, hopSz) + hopSz;
+
+ excBufShiftLen = (int)ceilf(hopSz / (float)stHdl->procResampleRate);
+ stHdl->excBufLen = stHdl->maxPeriod + excBufShiftLen + 1;
+
+ stHdl->nFeat = (int)ceilf(AUP_PE_FEAT_TIME_WINDOW * AUP_PE_FS /
+ ((float)hopSz * 1000.0f));
+ stHdl->nFeat = AUP_PE_MIN(stHdl->nFeat, AUP_PE_FEAT_MAX_NFRM);
+ stHdl->estDelay = 0;
+
+ // publish DCT-table coeff.
+ for (idx = 0; idx < AUP_PE_NB_BANDS; idx++) {
+ for (jdx = 0; jdx < AUP_PE_NB_BANDS; jdx++) {
+ stHdl->dct_table[idx * AUP_PE_NB_BANDS + jdx] =
+ cosf((idx + .5f) * jdx * AUP_PE_PI / AUP_PE_NB_BANDS);
+ if (jdx == 0) stHdl->dct_table[idx * AUP_PE_NB_BANDS + jdx] *= sqrtf(.5f);
+ }
+ }
+
+ return 0;
+}
+
+static int AUP_PE_resetVariables(PE_St* stHdl) {
+ // int nBins;
+ int idx;
+
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+
+ stHdl->inputResampleBufIdx = 0;
+
+ for (idx = 0; idx < AUP_PE_LPC_ORDER; idx++) {
+ stHdl->lpc[idx] = 0;
+ stHdl->pitch_mem[idx] = 0;
+ }
+ stHdl->pitch_filt = 0;
+
+ memset(stHdl->tmpFeat, 0, sizeof(stHdl->tmpFeat));
+
+ stHdl->xCorrOffsetIdx = 0;
+ for (idx = 0; idx < (AUP_PE_FEAT_MAX_NFRM * 2); idx++) {
+ stHdl->frmWeight[idx] = 0;
+ stHdl->frmWeightNorm[idx] = 0;
+ }
+
+ stHdl->pitchMaxPathAll = 0;
+ stHdl->bestPeriodEst = 0;
+
+ stHdl->voiced = 0;
+ stHdl->pitchEstResult = 0; // label as no speech
+
+ if (stHdl->procResampleRate != 1) {
+ if (AUP_Biquad_init(stHdl->biquadIIRPtr) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int AUP_PE_dynamMemPrepare(PE_St* stHdl, void* memPtrExt,
+ size_t memSize) {
+ int idx;
+
+ int inputResampleBufMemSize = 0;
+ int inputQMemSize = 0;
+ int alignedInMemSize = 0;
+ int lpcFilterOutBufMemSize = 0;
+ int excBufMemSize = 0;
+ int excBufSqMemSize = 0;
+ int xCorrInstMemSize = 0;
+ int xCorrPerFeatMemSize = 0;
+ int xCorrPerFeatTmpMemSize = 0;
+ int pitchMaxPathRegPerRegMemSize = 0;
+ int pitchPrevPerFeatMemSize = 0;
+ int totalMemSize = 0;
+ char* memPtr = NULL;
+
+ inputResampleBufMemSize =
+ AUP_PE_ALIGN8(sizeof(float) * stHdl->inputResampleBufLen);
+ totalMemSize += inputResampleBufMemSize;
+
+ inputQMemSize = AUP_PE_ALIGN8(sizeof(float) * stHdl->inputQLen);
+ totalMemSize += inputQMemSize;
+
+ alignedInMemSize = AUP_PE_ALIGN8(sizeof(float) * stHdl->stCfg.hopSz);
+ totalMemSize += alignedInMemSize;
+
+ lpcFilterOutBufMemSize = AUP_PE_ALIGN8(sizeof(float) * stHdl->stCfg.hopSz);
+ totalMemSize += lpcFilterOutBufMemSize;
+
+ excBufMemSize = AUP_PE_ALIGN8(sizeof(float) * stHdl->excBufLen);
+ totalMemSize += excBufMemSize;
+ excBufSqMemSize = excBufMemSize;
+ totalMemSize += excBufSqMemSize;
+
+ xCorrInstMemSize = AUP_PE_ALIGN8(sizeof(float) * (stHdl->maxPeriod));
+ totalMemSize += xCorrInstMemSize;
+
+ xCorrPerFeatMemSize = AUP_PE_ALIGN8(sizeof(float) * (stHdl->maxPeriod + 1));
+ xCorrPerFeatTmpMemSize = xCorrPerFeatMemSize;
+ totalMemSize +=
+ (xCorrPerFeatMemSize + xCorrPerFeatTmpMemSize) * (stHdl->nFeat * 2);
+
+ pitchMaxPathRegPerRegMemSize =
+ AUP_PE_ALIGN8(sizeof(float) * (stHdl->maxPeriod));
+ totalMemSize += pitchMaxPathRegPerRegMemSize * 2;
+
+ pitchPrevPerFeatMemSize = AUP_PE_ALIGN8(sizeof(int) * (stHdl->maxPeriod));
+ totalMemSize += pitchPrevPerFeatMemSize * (stHdl->nFeat * 2);
+
+ // if no external memory provided, we are only profiling the memory
+ // requirement
+ if (memPtrExt == NULL) {
+ return (totalMemSize);
+ }
+
+ // if required memory is more than provided, error
+ if ((size_t)totalMemSize > memSize) {
+ return -1;
+ }
+
+ memPtr = (char*)memPtrExt;
+
+ stHdl->inputResampleBuf = (float*)memPtr;
+ memPtr += inputResampleBufMemSize;
+
+ stHdl->inputQ = (float*)memPtr;
+ memPtr += inputQMemSize;
+
+ stHdl->alignedIn = (float*)memPtr;
+ memPtr += alignedInMemSize;
+
+ stHdl->lpcFilterOutBuf = (float*)memPtr;
+ memPtr += lpcFilterOutBufMemSize;
+
+ stHdl->excBuf = (float*)memPtr;
+ memPtr += excBufMemSize;
+
+ stHdl->excBufSq = (float*)memPtr;
+ memPtr += excBufSqMemSize;
+
+ stHdl->xCorrInst = (float*)memPtr;
+ memPtr += xCorrInstMemSize;
+
+ for (idx = 0; idx < AUP_PE_FEAT_MAX_NFRM * 2; idx++) {
+ stHdl->xCorr[idx] = NULL;
+ stHdl->xCorrTmp[idx] = NULL;
+ stHdl->pitchPrev[idx] = NULL;
+ }
+ for (idx = 0; idx < (stHdl->nFeat * 2); idx++) {
+ stHdl->xCorr[idx] = (float*)memPtr;
+ memPtr += xCorrPerFeatMemSize;
+
+ stHdl->xCorrTmp[idx] = (float*)memPtr;
+ memPtr += xCorrPerFeatTmpMemSize;
+
+ stHdl->pitchPrev[idx] = (int*)memPtr;
+ memPtr += pitchPrevPerFeatMemSize;
+ }
+
+ stHdl->pitchMaxPathReg[0] = (float*)memPtr;
+ memPtr += pitchMaxPathRegPerRegMemSize;
+ stHdl->pitchMaxPathReg[1] = (float*)memPtr;
+ memPtr += pitchMaxPathRegPerRegMemSize;
+
+ if (((int)(memPtr - (char*)memPtrExt)) > totalMemSize) {
+ return -1;
+ }
+
+ return (totalMemSize);
+}
+
+static void AUP_PE_computeBandEnergy(const float* inBinPower,
+ const int binPowNFFT,
+ float bandE[AUP_PE_NB_BANDS]) {
+ int i, j, bandSz;
+ // float sum[NB_BANDS] = { 0 };
+ float frac;
+ float indexConvRate = 1.0;
+ int indexOffset = 0, accIdx;
+ int nBins = (binPowNFFT >> 1) + 1;
+
+ indexConvRate = (float)binPowNFFT / AUP_PE_ASSUMED_FFT_4_BAND_ENG;
+ for (i = 0; i < AUP_PE_NB_BANDS; i++) {
+ bandE[i] = 0;
+ }
+
+ for (i = 0; i < AUP_PE_NB_BANDS - 1; i++) {
+ bandSz = (int)roundf(
+ (AUP_PE_BAND_START_INDEX[i + 1] - AUP_PE_BAND_START_INDEX[i]) *
+ indexConvRate); // WINDOW_SIZE_5MS;
+ indexOffset = (int)roundf(AUP_PE_BAND_START_INDEX[i] *
+ indexConvRate); // WINDOW_SIZE_5MS;
+
+ for (j = 0; j < bandSz; j++) {
+ frac = (float)j / bandSz;
+ accIdx = AUP_PE_MIN(nBins - 1, (indexOffset + j));
+
+ bandE[i] += (1 - frac) * inBinPower[accIdx];
+ bandE[i + 1] += frac * inBinPower[accIdx];
+ }
+ }
+ bandE[0] *= 2;
+ bandE[AUP_PE_NB_BANDS - 1] *= 2;
+
+ return;
+}
+
+static void AUP_PE_dct(const float DctTable[AUP_PE_NB_BANDS * AUP_PE_NB_BANDS],
+ const float* in, float* out) {
+ int idx, j;
+ float sum;
+ float ratio = sqrtf(2.0f / AUP_PE_NB_BANDS);
+ for (idx = 0; idx < AUP_PE_NB_BANDS; idx++) {
+ sum = 0;
+ for (j = 0; j < AUP_PE_NB_BANDS; j++) {
+ sum += in[j] * DctTable[j * AUP_PE_NB_BANDS + idx];
+ }
+ out[idx] = sum * ratio;
+ }
+ return;
+}
+
+static void AUP_PE_idct(const float DctTable[AUP_PE_NB_BANDS * AUP_PE_NB_BANDS],
+ const float* in, float* out) {
+ int idx, j;
+ float sum;
+ float ratio = sqrtf(2.0f / AUP_PE_NB_BANDS);
+ for (idx = 0; idx < AUP_PE_NB_BANDS; idx++) {
+ sum = 0;
+ for (j = 0; j < AUP_PE_NB_BANDS; j++) {
+ sum += in[j] * DctTable[idx * AUP_PE_NB_BANDS + j];
+ }
+ out[idx] = sum * ratio;
+ }
+ return;
+}
+
+static void AUP_PE_interp_band_gain(const int nBins,
+ const float bandE[AUP_PE_NB_BANDS],
+ float* g) {
+ int idx, j, bandSz;
+ float indexConvRate = 1.0f;
+ int fftSz = (nBins - 1) * 2;
+ int indexOffset = 0, accIdx;
+ float frac;
+
+ indexConvRate = ((float)fftSz) / AUP_PE_ASSUMED_FFT_4_BAND_ENG;
+ memset(g, 0, sizeof(float) * nBins);
+
+ for (idx = 0; idx < AUP_PE_NB_BANDS - 1; idx++) {
+ bandSz = (int)roundf(
+ (AUP_PE_BAND_START_INDEX[idx + 1] - AUP_PE_BAND_START_INDEX[idx]) *
+ indexConvRate); // WINDOW_SIZE_5MS;
+ indexOffset = (int)roundf(AUP_PE_BAND_START_INDEX[idx] *
+ indexConvRate); // WINDOW_SIZE_5MS;
+
+ for (j = 0; j < bandSz; j++) {
+ frac = (float)j / bandSz;
+ accIdx = AUP_PE_MIN(nBins - 1, (indexOffset + j));
+
+ g[accIdx] = (1 - frac) * bandE[idx] + frac * bandE[idx + 1];
+ }
+ }
+
+ return;
+}
+
+// ac: in: [0...p] autocorrelation values
+// p: in: buffer length of _lpc and rc
+// _lpc: out: [0...p-1] LPC coefficients
+static float AUP_PE_celt_lpc(const float* ac, const int p, float* _lpc,
+ float* rc) {
+ int i, j;
+ float r;
+ float error = ac[0];
+ float* lpc = _lpc;
+ float rr;
+ float tmp1, tmp2;
+
+ // RNN_CLEAR(lpc, p);
+ memset(lpc, 0, sizeof(float) * p);
+ // RNN_CLEAR(rc, p);
+ memset(rc, 0, sizeof(float) * p);
+
+ if (ac[0] != 0) {
+ for (i = 0; i < p; i++) {
+ /* Sum up this iteration's reflection coefficient */
+ rr = 0;
+ for (j = 0; j < i; j++) rr += lpc[j] * ac[i - j];
+ rr += ac[i + 1];
+ r = (-rr) / error;
+ rc[i] = r;
+ /* Update LPC coefficients and total error */
+ lpc[i] = r;
+ for (j = 0; j<(i + 1)>> 1; j++) {
+ tmp1 = lpc[j];
+ tmp2 = lpc[i - 1 - j];
+ lpc[j] = tmp1 + (r * tmp2);
+ lpc[i - 1 - j] = tmp2 + (r * tmp1);
+ }
+
+ error = error - (r * r * error);
+ /* Bail out once we get 30 dB gain */
+
+ if (error < .001f * ac[0]) break;
+ }
+ }
+
+ return error;
+}
+
+static float AUP_PE_lpc_from_bands(const int windowSz, const int nBins,
+ const float Ex[AUP_PE_NB_BANDS],
+ float lpc[AUP_PE_LPC_ORDER]) {
+ int i;
+ float e;
+ float ac[AUP_PE_LPC_ORDER + 1] = {0};
+ float rc[AUP_PE_LPC_ORDER] = {0};
+ float Xr[AUP_PE_MAX_NBINS] = {0};
+ float X_auto[AUP_PE_MAX_FFTSIZE + 4] = {0};
+ float x_auto[AUP_PE_MAX_FFTSIZE + 4] = {0};
+ float DC0_BIAS;
+ int fftSz = (nBins - 1) * 2;
+
+ AUP_PE_interp_band_gain(nBins, Ex, Xr);
+ Xr[nBins - 1] = 0; // remove nyquist freq.
+
+ // RNN_CLEAR(X_auto, FREQ_SIZE);
+ X_auto[0] = Xr[0]; // reformat as complex spectrum data
+ X_auto[1] = Xr[nBins - 1];
+ for (i = 1; i < (nBins - 1); i++) {
+ X_auto[i << 1] = Xr[i]; // give value to its real part
+ } // leave all the imaginary part as 0
+
+ // inverse_transform(x_auto, X_auto); // IFFT, transform back to time domain
+ // (X_auto -> x_auto)
+ AUP_FFTW_InplaceTransf(0, fftSz, X_auto);
+ if (fftSz == 256) {
+ AUP_FFTW_c2r_256(X_auto, x_auto);
+ } else if (fftSz == 512) {
+ AUP_FFTW_c2r_512(X_auto, x_auto);
+ } else if (fftSz == 1024) {
+ AUP_FFTW_c2r_1024(X_auto, x_auto);
+ }
+ AUP_FFTW_RescaleIFFTOut(fftSz, x_auto);
+
+ for (i = 0; i < (AUP_PE_LPC_ORDER + 1);
+ i++) { // take only the first LPC_ORDER + 1 coeff.
+ ac[i] = x_auto[i];
+ }
+
+ // -40 dB noise floor
+ DC0_BIAS = (windowSz / 12 / 38.0f);
+
+ ac[0] += ac[0] * 1e-4f + DC0_BIAS;
+ // Lag windowing
+ for (i = 1; i < (AUP_PE_LPC_ORDER + 1); i++) {
+ ac[i] *= (1 - 6e-5f * i * i);
+ }
+
+ e = AUP_PE_celt_lpc(ac, AUP_PE_LPC_ORDER, lpc, rc);
+
+ return (e);
+}
+
+// lpc_from_cepstrum
+static float AUP_PE_lpcCompute(
+ const int windowSz, const int nBins,
+ const float DctTable[AUP_PE_NB_BANDS * AUP_PE_NB_BANDS],
+ const float* cepstrum, float* lpc) {
+ int i;
+ float Ex[AUP_PE_NB_BANDS] = {0};
+ float tmp[AUP_PE_NB_BANDS] = {0};
+ float errValue = 0;
+
+ // RNN_COPY(tmp, cepstrum, NB_BANDS);
+ memcpy(tmp, cepstrum, sizeof(float) * AUP_PE_NB_BANDS);
+
+ AUP_PE_idct(DctTable, tmp, Ex); // idct(Ex, tmp);
+ for (i = 0; i < AUP_PE_NB_BANDS; i++) {
+ Ex[i] = powf(10.f, Ex[i]) * AUP_PE_BAND_LPC_COMP[i];
+ }
+
+ errValue = AUP_PE_lpc_from_bands(windowSz, nBins, Ex, lpc);
+
+ return (errValue);
+}
+
+static void AUP_PE_xcorr_kernel(const float* x, const float* y, float sum[4],
+ int len) {
+ int j;
+ float y_0, y_1, y_2, y_3;
+ y_3 = 0; /* gcc doesn't realize that y_3 can't be used uninitialized */
+ y_0 = *y++;
+ y_1 = *y++;
+ y_2 = *y++;
+ for (j = 0; j < len - 3; j += 4) {
+ float tmp;
+ tmp = *x++;
+ y_3 = *y++;
+ sum[0] += tmp * y_0;
+ sum[1] += tmp * y_1;
+ sum[2] += tmp * y_2;
+ sum[3] += tmp * y_3;
+ tmp = *x++;
+ y_0 = *y++;
+ sum[0] += tmp * y_1;
+ sum[1] += tmp * y_2;
+ sum[2] += tmp * y_3;
+ sum[3] += tmp * y_0;
+ tmp = *x++;
+ y_1 = *y++;
+ sum[0] += tmp * y_2;
+ sum[1] += tmp * y_3;
+ sum[2] += tmp * y_0;
+ sum[3] += tmp * y_1;
+ tmp = *x++;
+ y_2 = *y++;
+ sum[0] += tmp * y_3;
+ sum[1] += tmp * y_0;
+ sum[2] += tmp * y_1;
+ sum[3] += tmp * y_2;
+ }
+ if (j++ < len) {
+ float tmp = *x++;
+ y_3 = *y++;
+ sum[0] += tmp * y_0;
+ sum[1] += tmp * y_1;
+ sum[2] += tmp * y_2;
+ sum[3] += tmp * y_3;
+ }
+ if (j++ < len) {
+ float tmp = *x++;
+ y_0 = *y++;
+ sum[0] += tmp * y_1;
+ sum[1] += tmp * y_2;
+ sum[2] += tmp * y_3;
+ sum[3] += tmp * y_0;
+ }
+ if (j < len) {
+ float tmp = *x++;
+ y_1 = *y++;
+ sum[0] += tmp * y_2;
+ sum[1] += tmp * y_3;
+ sum[2] += tmp * y_0;
+ sum[3] += tmp * y_1;
+ }
+ return;
+}
+
+static float AUP_PE_celt_inner_prod(const float* x, const float* y, int N) {
+ int i;
+ float xy = 0;
+ for (i = 0; i < N; i++) {
+ xy += (x[i] * y[i]);
+ }
+
+ return (xy);
+}
+
+static void AUP_PE_MvingXCorr(int corrWindowLen, int corrShiftTimes,
+ const float* refIn, const float* yInToShift,
+ float* xcorr) {
+ /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
+ int i;
+ float tmp;
+
+ for (i = 0; i < corrShiftTimes - 3; i += 4) {
+ float sum[4] = {0, 0, 0, 0};
+ AUP_PE_xcorr_kernel(refIn, yInToShift + i, sum, corrWindowLen);
+ xcorr[i] = sum[0];
+ xcorr[i + 1] = sum[1];
+ xcorr[i + 2] = sum[2];
+ xcorr[i + 3] = sum[3];
+ }
+ /* In case corrShiftTimes isn't a multiple of 4, do non-unrolled version. */
+ for (; i < corrShiftTimes; i++) {
+ tmp = AUP_PE_celt_inner_prod(refIn, yInToShift + i, corrWindowLen);
+ xcorr[i] = tmp;
+ }
+ return;
+}
+
+// ==========================================================================================
+// public APIs
+// ==========================================================================================
+
+int AUP_PE_create(void** stPtr) {
+ PE_St* tmpPtr;
+
+ if (stPtr == NULL) {
+ return -1;
+ }
+
+ *stPtr = (void*)malloc(sizeof(PE_St));
+ if (*stPtr == NULL) {
+ return -1;
+ }
+ memset(*stPtr, 0, sizeof(PE_St));
+
+ tmpPtr = (PE_St*)(*stPtr);
+
+ tmpPtr->dynamMemPtr = NULL;
+ tmpPtr->dynamMemSize = 0;
+
+ if (AUP_Biquad_create(&(tmpPtr->biquadIIRPtr)) < 0 ||
+ tmpPtr->biquadIIRPtr == NULL) {
+ return -1;
+ }
+
+ tmpPtr->stCfg.fftSz = 1024;
+ tmpPtr->stCfg.anaWindowSz = 768;
+ tmpPtr->stCfg.hopSz = 256;
+ tmpPtr->stCfg.useLPCPreFiltering = 1;
+ tmpPtr->stCfg.procFs = 4000; // 4KHz resampling rate
+
+ tmpPtr->dynamCfg.voicedThr = 0.4f;
+
+ return 0;
+}
+
+int AUP_PE_destroy(void** stPtr) {
+ PE_St* stHdl;
+
+ if (stPtr == NULL) {
+ return 0;
+ }
+
+ stHdl = (PE_St*)(*stPtr);
+ if (stHdl == NULL) {
+ return 0;
+ }
+
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ }
+ stHdl->dynamMemPtr = NULL;
+
+ if (stHdl->biquadIIRPtr != NULL) {
+ AUP_Biquad_destroy(&(stHdl->biquadIIRPtr));
+ }
+
+ free(stHdl);
+ (*stPtr) = NULL;
+
+ return 0;
+}
+
+int AUP_PE_memAllocate(void* stPtr, const PE_StaticCfg* pCfg) {
+ PE_St* stHdl = NULL;
+ PE_StaticCfg localStCfg;
+ Biquad_StaticCfg biquadStCfg = {0, 0, 0, {0}, {0}, 0};
+ int idx;
+ int totalMemSize = 0;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+ stHdl = (PE_St*)(stPtr);
+
+ memcpy(&localStCfg, pCfg, sizeof(PE_StaticCfg));
+ if (AUP_PE_checkStatCfg(&localStCfg) < 0) {
+ return -1;
+ }
+
+ memcpy(&(stHdl->stCfg), &localStCfg, sizeof(PE_StaticCfg));
+
+ // publish internal static configuration registers
+ if (AUP_PE_publishStaticCfg(stHdl) < 0) {
+ return -1;
+ }
+
+ // check memory requirement
+ totalMemSize = AUP_PE_dynamMemPrepare(stHdl, NULL, 0);
+ if (totalMemSize < 0) {
+ return -1;
+ }
+
+ // allocate dynamic memory
+ if ((size_t)totalMemSize > stHdl->dynamMemSize) {
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ stHdl->dynamMemSize = 0;
+ }
+ stHdl->dynamMemPtr = malloc(totalMemSize);
+ if (stHdl->dynamMemPtr == NULL) {
+ return -1;
+ }
+ stHdl->dynamMemSize = totalMemSize;
+ }
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+
+ // setup the pointers/variable
+ if (AUP_PE_dynamMemPrepare(stHdl, stHdl->dynamMemPtr, stHdl->dynamMemSize) <
+ 0) {
+ return -1;
+ }
+
+ if (AUP_Biquad_getStaticCfg(stHdl->biquadIIRPtr, &biquadStCfg) < 0) {
+ return -1;
+ }
+ biquadStCfg.maxNSample = stHdl->stCfg.hopSz;
+ if (stHdl->procResampleRate != 1) {
+ biquadStCfg.nsect = AUP_PE_LOWPSS_NSEC;
+ if (stHdl->stCfg.procFs == 2000) {
+ biquadStCfg.G = AUP_PE_G_2KHZ;
+ for (idx = 0; idx < biquadStCfg.nsect; idx++) {
+ biquadStCfg.B[idx] = AUP_PE_B_2KHZ[idx];
+ biquadStCfg.A[idx] = AUP_PE_A_2KHZ[idx];
+ }
+ } else if (stHdl->stCfg.procFs == 4000) {
+ biquadStCfg.G = AUP_PE_G_4KHZ;
+ for (idx = 0; idx < biquadStCfg.nsect; idx++) {
+ biquadStCfg.B[idx] = AUP_PE_B_4KHZ[idx];
+ biquadStCfg.A[idx] = AUP_PE_A_4KHZ[idx];
+ }
+ } else if (stHdl->stCfg.procFs == 8000) {
+ biquadStCfg.G = AUP_PE_G_8KHZ;
+ for (idx = 0; idx < biquadStCfg.nsect; idx++) {
+ biquadStCfg.B[idx] = AUP_PE_B_8KHZ[idx];
+ biquadStCfg.A[idx] = AUP_PE_A_8KHZ[idx];
+ }
+ }
+ } else {
+ biquadStCfg.nsect = -1;
+ }
+ if (AUP_Biquad_memAllocate(stHdl->biquadIIRPtr, &biquadStCfg) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_PE_init(void* stPtr) {
+ PE_St* stHdl;
+
+ if (stPtr == NULL) {
+ return -1;
+ }
+ stHdl = (PE_St*)(stPtr);
+
+ if (AUP_PE_resetVariables(stHdl) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_PE_setDynamCfg(void* stPtr, const PE_DynamCfg* pCfg) {
+ PE_St* stHdl;
+ PE_DynamCfg localCfg;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+
+ memcpy(&localCfg, pCfg, sizeof(PE_DynamCfg));
+ if (AUP_PE_checkDynamCfg(&localCfg) < 0) {
+ return -1;
+ }
+
+ stHdl = (PE_St*)(stPtr);
+
+ memcpy(&(stHdl->dynamCfg), &localCfg, sizeof(PE_DynamCfg));
+
+ return 0;
+}
+
+int AUP_PE_getStaticCfg(const void* stPtr, PE_StaticCfg* pCfg) {
+ const PE_St* stHdl;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+ stHdl = (const PE_St*)(stPtr);
+
+ memcpy(pCfg, &(stHdl->stCfg), sizeof(PE_StaticCfg));
+
+ return 0;
+}
+
+int AUP_PE_getDynamCfg(const void* stPtr, PE_DynamCfg* pCfg) {
+ const PE_St* stHdl;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+ stHdl = (const PE_St*)(stPtr);
+
+ memcpy(pCfg, &(stHdl->dynamCfg), sizeof(PE_DynamCfg));
+
+ return 0;
+}
+
+int AUP_PE_getAlgDelay(const void* stPtr, int* delayInFrms) {
+ const PE_St* stHdl;
+
+ if (stPtr == NULL || delayInFrms == NULL) {
+ return -1;
+ }
+ stHdl = (const PE_St*)(stPtr);
+
+ *delayInFrms = stHdl->estDelay;
+
+ return 0;
+}
+
+int AUP_PE_proc(void* stPtr, const PE_InputData* pIn, PE_OutputData* pOut) {
+ PE_St* stHdl = NULL;
+ Biquad_InputData bqInData = {0, 0, 0};
+ Biquad_OutputData bqOutData = {0};
+ int nBins, fftSz, hopSz, idx, jdx, sub, offset, tmpInt, xcorrAccIdx;
+ float bandPow[AUP_PE_NB_BANDS] = {0}; // Ex
+ float Ly[AUP_PE_NB_BANDS] = {0};
+ float follow, lpcErr, logMax;
+ float energy0, slidWinSum, tmpDenom = 0, maxTrackReg = 0, maxPathReg = 0;
+ float frmCorr = 0; // frmCorrCorrection = 0;
+ const float* startPtr = NULL;
+ const float* refSeqPtr = NULL;
+ const float* mvSeqPtr = NULL;
+ int CORR_HALF_HOPSZ, SIDXT, XCIdx;
+ int bestPeriodEstLocal[AUP_PE_TOTAL_NFEAT * 2] = {0};
+ float w, sx = 0, sxx = 0, sxy = 0, sy = 0, sw = 0;
+ float bestA = 0, bestB = 0;
+ float estimatedPeriod;
+
+ if (stPtr == NULL || pIn == NULL || pIn->timeSignal == NULL) {
+ return -1;
+ }
+ stHdl = (PE_St*)(stPtr);
+
+ nBins = (int)(stHdl->nBins);
+ fftSz = (int)(stHdl->stCfg.fftSz);
+ hopSz = (int)(stHdl->stCfg.hopSz);
+ CORR_HALF_HOPSZ = hopSz / (stHdl->procResampleRate * 2);
+
+ if (pIn->hopSz != (int)stHdl->stCfg.hopSz) {
+ return -1;
+ }
+
+ if (stHdl->stCfg.useLPCPreFiltering == 1 && pIn->inBinPow == NULL) {
+ return -1;
+ }
+ if (stHdl->stCfg.useLPCPreFiltering == 1 && pIn->nBins != stHdl->nBins) {
+ return -1;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Feature Pre-Calculation .... from compute_frame_features of lpcnet_enc.cc
+ //////////////////////////////////////////////////////////////////////////////////////
+ if (stHdl->stCfg.useLPCPreFiltering == 1) {
+ // first. generate features and pre-raw information ...
+ AUP_PE_computeBandEnergy(pIn->inBinPow, fftSz, bandPow);
+ logMax = -2.0f;
+ follow = -2.0f;
+ for (idx = 0; idx < AUP_PE_NB_BANDS; idx++) {
+ Ly[idx] = log10f(1e-2f + bandPow[idx]); // Ex
+ Ly[idx] = AUP_PE_MAX(logMax - 8.0f, AUP_PE_MAX(follow - 2.5f, Ly[idx]));
+ logMax = AUP_PE_MAX(logMax, Ly[idx]);
+
+ follow = AUP_PE_MAX(follow - 2.5f, Ly[idx]);
+ }
+
+ AUP_PE_dct(stHdl->dct_table, Ly, stHdl->tmpFeat);
+
+ lpcErr = AUP_PE_lpcCompute((int)(stHdl->stCfg.anaWindowSz), nBins,
+ stHdl->dct_table, stHdl->tmpFeat, stHdl->lpc);
+
+ memmove(stHdl->inputQ, stHdl->inputQ + hopSz,
+ sizeof(float) * (stHdl->inputQLen - hopSz));
+ memcpy(&(stHdl->inputQ[stHdl->inputQLen - hopSz]), pIn->timeSignal,
+ sizeof(float) * hopSz);
+ // then, take part out into alignedIn for later correlation calculation
+ offset =
+ AUP_PE_MAX(0, stHdl->inputQLen - hopSz - AUP_PE_XCORR_TRAINING_OFFSET);
+ memcpy(stHdl->alignedIn, stHdl->inputQ + offset, sizeof(float) * hopSz);
+
+ for (idx = 0; idx < hopSz; idx++) {
+ // FIR LPC filtering .....
+ slidWinSum = stHdl->alignedIn[idx];
+ for (jdx = 0; jdx < AUP_PE_LPC_ORDER; jdx++) {
+ slidWinSum += stHdl->lpc[jdx] * stHdl->pitch_mem[jdx];
+ }
+
+ memmove(stHdl->pitch_mem + 1, stHdl->pitch_mem,
+ sizeof(float) * (AUP_PE_LPC_ORDER - 1));
+ stHdl->pitch_mem[0] =
+ stHdl->alignedIn[idx]; // push the latest base-sample into the tail
+ // of FIFO
+
+ stHdl->lpcFilterOutBuf[idx] = slidWinSum + 0.7f * stHdl->pitch_filt;
+ stHdl->pitch_filt = slidWinSum;
+ }
+
+ if (stHdl->procResampleRate != 1) {
+ // resample of lpcFilterOutBuf
+ bqInData.nsamples = (size_t)hopSz;
+ bqInData.samplesPtr = (const void*)(stHdl->lpcFilterOutBuf);
+ bqInData.sampleType = 1;
+ bqOutData.outputBuff =
+ (void*)(stHdl->inputResampleBuf + stHdl->inputResampleBufIdx);
+ if (AUP_Biquad_proc(stHdl->biquadIIRPtr, &bqInData, &bqOutData) < 0) {
+ return -1;
+ }
+ tmpInt = stHdl->inputResampleBufIdx;
+ for (idx = tmpInt; idx < (tmpInt + hopSz);
+ idx += stHdl->procResampleRate) {
+ stHdl->inputResampleBuf[stHdl->inputResampleBufIdx] =
+ stHdl->inputResampleBuf[idx];
+ stHdl->inputResampleBufIdx++;
+ }
+ // update the excBuf ....
+ tmpInt = stHdl->inputResampleBufIdx;
+ memmove(stHdl->excBuf, stHdl->excBuf + tmpInt,
+ sizeof(float) * (stHdl->excBufLen - tmpInt));
+ memcpy(stHdl->excBuf + (stHdl->excBufLen - tmpInt),
+ stHdl->inputResampleBuf, sizeof(float) * tmpInt);
+ stHdl->inputResampleBufIdx = 0;
+ } else {
+ tmpInt = hopSz;
+ memmove(stHdl->excBuf, stHdl->excBuf + tmpInt,
+ sizeof(float) * (stHdl->excBufLen - tmpInt));
+ memcpy(stHdl->excBuf + (stHdl->excBufLen - tmpInt),
+ stHdl->lpcFilterOutBuf, sizeof(float) * tmpInt);
+ }
+
+ } else {
+ if (stHdl->procResampleRate != 1) {
+ // resample of lpcFilterOutBuf
+ bqInData.nsamples = (size_t)hopSz;
+ bqInData.samplesPtr = (const void*)(pIn->timeSignal);
+ bqInData.sampleType = 1;
+ bqOutData.outputBuff =
+ (void*)(stHdl->inputResampleBuf + stHdl->inputResampleBufIdx);
+ if (AUP_Biquad_proc(stHdl->biquadIIRPtr, &bqInData, &bqOutData) < 0) {
+ return -1;
+ }
+ tmpInt = stHdl->inputResampleBufIdx;
+ for (idx = tmpInt; idx < (tmpInt + hopSz);
+ idx += stHdl->procResampleRate) {
+ stHdl->inputResampleBuf[stHdl->inputResampleBufIdx] =
+ stHdl->inputResampleBuf[idx];
+ stHdl->inputResampleBufIdx++;
+ }
+
+ // update the excBuf ....
+ tmpInt = stHdl->inputResampleBufIdx;
+ memmove(stHdl->excBuf, stHdl->excBuf + tmpInt,
+ sizeof(float) * (stHdl->excBufLen - tmpInt));
+ memcpy(stHdl->excBuf + (stHdl->excBufLen - tmpInt),
+ stHdl->inputResampleBuf, sizeof(float) * tmpInt);
+ stHdl->inputResampleBufIdx = 0;
+ } else {
+ tmpInt = hopSz;
+ memmove(stHdl->excBuf, stHdl->excBuf + tmpInt,
+ sizeof(float) * (stHdl->excBufLen - tmpInt));
+ memcpy(stHdl->excBuf + (stHdl->excBufLen - tmpInt), pIn->timeSignal,
+ sizeof(float) * tmpInt);
+ }
+ }
+
+ // prepare for cross-correlation computation ....
+ for (idx = 0; idx < stHdl->excBufLen; idx++) {
+ stHdl->excBufSq[idx] = (stHdl->excBuf[idx] * stHdl->excBuf[idx]);
+ }
+
+ // shift the frmWeight queue to left space for this new frame
+ for (idx = 0; idx < (stHdl->nFeat - 1); idx++) {
+ stHdl->frmWeight[2 * (idx)] = stHdl->frmWeight[2 * (idx + 1)];
+ stHdl->frmWeight[2 * (idx) + 1] = stHdl->frmWeight[2 * (idx + 1) + 1];
+ }
+
+ // do the cross-correlation .....
+ for (sub = 0; sub < 2; sub++) {
+ xcorrAccIdx = 2 * (stHdl->xCorrOffsetIdx) + sub;
+ offset = sub * CORR_HALF_HOPSZ;
+
+ refSeqPtr = stHdl->excBuf + (stHdl->maxPeriod + offset);
+ mvSeqPtr = stHdl->excBuf + offset;
+ AUP_PE_MvingXCorr(CORR_HALF_HOPSZ, stHdl->maxPeriod, refSeqPtr, mvSeqPtr,
+ stHdl->xCorrInst);
+
+ energy0 = 0;
+ startPtr = stHdl->excBufSq + (stHdl->maxPeriod + offset);
+ for (idx = 0; idx < CORR_HALF_HOPSZ; idx++) {
+ energy0 += startPtr[idx];
+ }
+ stHdl->frmWeight[2 * (stHdl->nFeat - 1) + sub] = energy0;
+
+ slidWinSum = 0;
+ startPtr = stHdl->excBufSq + offset;
+ for (idx = 0; idx < CORR_HALF_HOPSZ; idx++) {
+ slidWinSum += startPtr[idx];
+ }
+
+ // special hanlding for the 0th element
+ tmpDenom = AUP_PE_MAX(1e-12f, slidWinSum + (1 + energy0));
+ stHdl->xCorr[xcorrAccIdx][0] = 2 * stHdl->xCorrInst[0] / tmpDenom;
+
+ for (idx = 1; idx < stHdl->maxPeriod; idx++) {
+ // update the slidWinSum
+ slidWinSum =
+ AUP_PE_MAX(0, slidWinSum - stHdl->excBufSq[offset + idx - 1]);
+ slidWinSum += stHdl->excBufSq[offset + idx + CORR_HALF_HOPSZ - 1];
+
+ tmpDenom = AUP_PE_MAX(1e-12f, slidWinSum + (1 + energy0));
+ stHdl->xCorr[xcorrAccIdx][idx] = 2 * stHdl->xCorrInst[idx] / tmpDenom;
+ }
+
+ // shrink/sharpen the values in xCorr array ...
+ for (idx = 0; idx < (stHdl->maxPeriod - 2 * stHdl->minPeriod); idx++) {
+ tmpDenom = stHdl->xCorr[xcorrAccIdx][(stHdl->maxPeriod + idx) / 2];
+ tmpDenom = AUP_PE_MAX(
+ tmpDenom,
+ stHdl->xCorr[xcorrAccIdx][(stHdl->maxPeriod + idx + 2) / 2]);
+ tmpDenom = AUP_PE_MAX(
+ tmpDenom,
+ stHdl->xCorr[xcorrAccIdx][(stHdl->maxPeriod + idx - 1) / 2]);
+
+ if (stHdl->xCorr[xcorrAccIdx][idx] < (tmpDenom * 1.1f))
+ stHdl->xCorr[xcorrAccIdx][idx] *= 0.8f;
+ }
+ }
+ stHdl->xCorrOffsetIdx++;
+ if (stHdl->xCorrOffsetIdx >= stHdl->nFeat) {
+ stHdl->xCorrOffsetIdx = 0;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Pitch Estimation .... from process_superframe of lpcnet_enc.cc
+ //////////////////////////////////////////////////////////////////////////////////////
+ slidWinSum = 1e-15f;
+ for (sub = 0; sub < (stHdl->nFeat * 2); sub++) {
+ slidWinSum += stHdl->frmWeight[sub];
+ }
+ for (sub = 0; sub < (stHdl->nFeat * 2); sub++) {
+ stHdl->frmWeightNorm[sub] =
+ stHdl->frmWeight[sub] * ((stHdl->nFeat * 2) / slidWinSum);
+ }
+
+ // copy xCorr to xCorrTmp, so that later-on we can modify the content in
+ // xCorrTmp without impacting next hop's processing
+ for (idx = 0; idx < (stHdl->nFeat * 2); idx++) {
+ memcpy(stHdl->xCorrTmp[idx], stHdl->xCorr[idx],
+ sizeof(float) * (stHdl->maxPeriod + 1));
+ }
+
+ // shift pitchPrev buffer to left space for this new frame's result
+ for (sub = 0; sub < (stHdl->nFeat * 2 - 2); sub += 2) {
+ memcpy(stHdl->pitchPrev[sub], stHdl->pitchPrev[sub + 2],
+ sizeof(int) * stHdl->maxPeriod);
+ memcpy(stHdl->pitchPrev[sub + 1], stHdl->pitchPrev[sub + 3],
+ sizeof(int) * stHdl->maxPeriod);
+ }
+ for (sub = (stHdl->nFeat * 2 - 2); sub < (stHdl->nFeat * 2); sub++) {
+ XCIdx = sub + (stHdl->xCorrOffsetIdx * 2);
+ if (XCIdx >= (2 * stHdl->nFeat)) {
+ XCIdx -= (2 * stHdl->nFeat);
+ }
+
+ for (idx = 0; idx < stHdl->difPeriod; idx++) {
+ maxTrackReg = stHdl->pitchMaxPathAll - 1e10f;
+ stHdl->pitchPrev[sub][idx] = stHdl->bestPeriodEst;
+
+ SIDXT = AUP_PE_MIN(0, 4 - idx);
+ for (jdx = SIDXT; jdx <= 4 && (idx + jdx) < stHdl->difPeriod; jdx++) {
+ tmpDenom = stHdl->pitchMaxPathReg[0][idx + jdx] -
+ (AUP_PE_PITCHMAXPATH_W * abs(jdx) * abs(jdx));
+ if (tmpDenom > maxTrackReg) {
+ maxTrackReg = tmpDenom;
+ stHdl->pitchPrev[sub][idx] = idx + jdx;
+ }
+ }
+
+ // store the max search result into pitch_max_path[1][...]
+ stHdl->pitchMaxPathReg[1][idx] =
+ maxTrackReg + stHdl->frmWeightNorm[sub] * stHdl->xCorrTmp[XCIdx][idx];
+ }
+
+ maxPathReg = -1e15f;
+ tmpInt = 0;
+ for (idx = 0; idx < stHdl->difPeriod; idx++) {
+ if (stHdl->pitchMaxPathReg[1][idx] > maxPathReg) {
+ maxPathReg = stHdl->pitchMaxPathReg[1][idx];
+ tmpInt = idx;
+ }
+ }
+ stHdl->pitchMaxPathAll = maxPathReg;
+ stHdl->bestPeriodEst = tmpInt;
+
+ memcpy(&(stHdl->pitchMaxPathReg[0][0]), &(stHdl->pitchMaxPathReg[1][0]),
+ sizeof(float) * stHdl->maxPeriod);
+ for (idx = 0; idx < stHdl->difPeriod; idx++) {
+ stHdl->pitchMaxPathReg[0][idx] -= maxPathReg;
+ }
+ }
+
+ tmpInt = stHdl->bestPeriodEst;
+ frmCorr = 0;
+ // Backward pass
+ for (sub = (stHdl->nFeat * 2) - 1; sub >= 0; sub--) {
+ bestPeriodEstLocal[sub] = stHdl->maxPeriod - tmpInt;
+
+ XCIdx = sub + (stHdl->xCorrOffsetIdx * 2);
+ if (XCIdx >= (2 * stHdl->nFeat)) {
+ XCIdx -= (2 * stHdl->nFeat);
+ }
+ frmCorr += stHdl->frmWeightNorm[sub] * stHdl->xCorrTmp[XCIdx][tmpInt];
+ tmpInt = stHdl->pitchPrev[sub][tmpInt];
+ }
+ frmCorr = AUP_PE_MAX(0, frmCorr / (float)(stHdl->nFeat * 2));
+ stHdl->voiced = (frmCorr >= stHdl->dynamCfg.voicedThr) ? 1 : 0;
+
+ for (sub = 0; sub < (stHdl->nFeat * 2); sub++) {
+ w = stHdl->frmWeightNorm[sub];
+ sw += w;
+ sx += w * sub;
+ sxx += w * sub * sub;
+ sxy += w * sub * bestPeriodEstLocal[sub];
+ sy += w * bestPeriodEstLocal[sub];
+ }
+
+ // Linear regression to figure out the pitch contour
+ // frmCorrCorrection = frmCorr;
+ tmpDenom = (sw * sxx - sx * sx);
+ if (tmpDenom == 0)
+ bestA = (sw * sxy - sx * sy) / 1e-15f;
+ else
+ bestA = (sw * sxy - sx * sy) / tmpDenom;
+
+ if (stHdl->voiced == 1) {
+ tmpDenom = (sy / sw) / (4 * 2 * stHdl->nFeat);
+ bestA = AUP_PE_MIN(tmpDenom, AUP_PE_MAX(-tmpDenom, bestA));
+ } else { // if there is no voice inside this frame
+ bestA = 0;
+ }
+ bestB = (sy - bestA * sx) / sw;
+ estimatedPeriod = bestB + 5.5f * bestA;
+
+ if (stHdl->voiced == 1) {
+ stHdl->pitchEstResult =
+ ((float)(stHdl->stCfg.procFs)) / AUP_PE_MAX(1.0f, estimatedPeriod);
+ } else {
+ stHdl->pitchEstResult = 0;
+ }
+
+ if (pOut != NULL) {
+ pOut->pitchFreq = stHdl->pitchEstResult;
+ pOut->voiced = stHdl->voiced;
+ }
+
+ return 0;
+}
diff --git a/src/pitch_est.h b/src/pitch_est.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f7acb8d699c77bd9068bfb5b33bf2ab3b130f2e
--- /dev/null
+++ b/src/pitch_est.h
@@ -0,0 +1,229 @@
+ //
+ // Copyright © 2025 Agora
+ // This file is part of TEN Framework, an open source project.
+ // Licensed under the Apache License, Version 2.0, with certain conditions.
+ //
+ // Refer to the "LICENSE" file in the root directory for more information.
+ //
+
+#ifndef __PITCH_EST_H__
+#define __PITCH_EST_H__
+
+#include
+#include
+#include
+
+#define AUP_PE_MAX_FFTSIZE (1024)
+#define AUP_PE_MAX_NBINS ((AUP_PE_MAX_FFTSIZE >> 1) + 1)
+
+#define AUP_PE_FS (16000)
+// assumed sampling freq. of this module
+
+// Configuration Parameters, which impacts dynamic memory occupation, can only
+// be set during allocation
+typedef struct PE_StaticCfg_ {
+ size_t fftSz; // fft-size, only support: 128, 256, 512, 1024
+ size_t anaWindowSz; // analysis fft-Window Size, will be used in LPC estimate
+ size_t hopSz; // fft-Hop Size, will be used to check
+ int useLPCPreFiltering;
+ // 0: use raw pcm to estimate pitch
+ // 1: use LPC prefiltering before pitch estimation
+ size_t procFs; // internal processing sampling rate
+ // 2000/4000/8000/16000
+} PE_StaticCfg;
+
+// Configuraiton parameters which can be modified/set every frames
+typedef struct PE_DynamCfg_ {
+ float voicedThr; // threshold on frame correlation coeff to label if voice
+ // present
+ // suggested value: procFs == 2KHz, Yes: 0.45, No: 0.4
+} PE_DynamCfg;
+
+// Spectrum are assumed to be generated with time-domain samples in [-32768,
+// 32767] WITH LEC blowup protection Note: the input timeSignal has to be in
+// 16KHz sampling-rate
+typedef struct PE_InputData_ {
+ const float*
+ timeSignal; // [hopSz] // this frame's input signal, in [-32768, 32767]
+ int hopSz; // should be equal to StaticCfg->hopSz
+
+ // if useLPCPreFiltering == 0, the following two input argument
+ // are not necessary
+ const float* inBinPow; // [nBins], bin-wise power
+ int nBins;
+} PE_InputData;
+
+typedef struct PE_OutputData_ {
+ float pitchFreq; // the current estimated pitch freq.
+ // <= 0: no voice
+ int voiced; // 0: no-voice, 1: voice-present
+} PE_OutputData;
+
+typedef struct PE_GetData_ {
+ float pitchFreq; // the current estimated pitch freq.
+ // <= 0: no voice
+ int voiced; // 0: no-voice, 1: voice-present
+} PE_GetData;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * AUP_PE_create(...)
+ *
+ * This function creats a state handler from nothing, which is NOT ready for
+ * processing
+ *
+ * Input:
+ *
+ * Output:
+ * - stPtr : buffer to store the returned state handler
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_PE_create(void** stPtr);
+
+/****************************************************************************
+ * AUP_PE_destroy(...)
+ *
+ * destroy PE instance, and releasing all the dynamically allocated memory
+ *
+ * Input:
+ * - stPtr : buffer of State Handler, after this method, this
+ * handler won't be usable anymore
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_PE_destroy(void** stPtr);
+
+/****************************************************************************
+ * AUP_PE_memAllocate(...)
+ *
+ * This function sets Static Config params and does memory allocation
+ * operation, will lose the dynamCfg values
+ *
+ * Input:
+ * - stPtr : State Handler which was returned by _create
+ * - pCfg : static configuration parameters
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_PE_memAllocate(void* stPtr, const PE_StaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_PE_init(...)
+ *
+ * This function resets (initialize) the PE module and gets it prepared for
+ * processing
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_PE_init(void* stPtr);
+
+/****************************************************************************
+ * AUP_PE_setDynamCfg(...)
+ *
+ * This function set dynamic (per-frame variable) configuration
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ * - pCfg : configuration content
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_PE_setDynamCfg(void* stPtr, const PE_DynamCfg* pCfg);
+
+/****************************************************************************
+ * AUP_PE_getStaticCfg(...)
+ *
+ * This function get static configuration status from PE module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - pCfg : configuration content
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_PE_getStaticCfg(const void* stPtr, PE_StaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_PE_getDynamCfg(...)
+ *
+ * This function get dynamic (per-frame variable) configuration status from
+ * PE module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - pCfg : configuration content
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_PE_getDynamCfg(const void* stPtr, PE_DynamCfg* pCfg);
+
+/****************************************************************************
+ * AUP_PE_getAlgDelay(...)
+ *
+ * This function get algorithm delay from PE module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - delayInFrms : algorithm delay in terms of frames
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_PE_getAlgDelay(const void* stPtr, int* delayInFrms);
+
+/****************************************************************************
+ * AUP_PE_proc(...)
+ *
+ * process a single frame
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate and reset
+ * - pCtrl : per-frame variable control parameters
+ * - pIn : input data stream
+ *
+ * Output:
+ * - pOut : output data (mask, highband time-domain gain etc.)
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_PE_proc(void* stPtr, const PE_InputData* pIn, PE_OutputData* pOut);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // __PITCH_EST_H__
diff --git a/src/pitch_est_st.h b/src/pitch_est_st.h
new file mode 100644
index 0000000000000000000000000000000000000000..306db013a9dd60b929903bb7c94b1056250868b8
--- /dev/null
+++ b/src/pitch_est_st.h
@@ -0,0 +1,166 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __PITCH_EST_ST_H__
+#define __PITCH_EST_ST_H__
+
+#include
+
+#include "pitch_est.h"
+
+#define AUP_PE_ALIGN8(o) (((o) + 7) & (~7))
+#define AUP_PE_MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define AUP_PE_MIN(x, y) (((x) > (y)) ? (y) : (x))
+
+#define AUP_PE_NB_BANDS (18) // number of mel bands
+#define AUP_PE_LPC_ORDER (16)
+
+#define AUP_PE_XCORR_TRAINING_OFFSET (80) // = 80
+#define AUP_PE_MIN_PERIOD_16KHZ (32) // stands for 1.333kHz, PITCH_MIN_PERIOD
+#define AUP_PE_MAX_PERIOD_16KHZ (256) // stands for ~62Hz, PITCH_MAX_PERIOD
+
+#define AUP_PE_LOWPSS_NSEC (5)
+const float AUP_PE_B_2KHZ[AUP_PE_LOWPSS_NSEC][3] = {
+ {1.000000e+00f, -1.303155e-01f, 1.000000e+00f},
+ {1.000000e+00f, -1.563002e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.759739e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.811650e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.827332e+00f, 1.000000e+00f}};
+const float AUP_PE_A_2KHZ[AUP_PE_LOWPSS_NSEC][3] = {
+ {1.000000e+00f, -1.726800e+00f, 7.526543e-01f},
+ {1.000000e+00f, -1.762977e+00f, 8.277960e-01f},
+ {1.000000e+00f, -1.802014e+00f, 9.079320e-01f},
+ {1.000000e+00f, -1.828423e+00f, 9.594240e-01f},
+ {1.000000e+00f, -1.846774e+00f, 9.888390e-01f}};
+const float AUP_PE_G_2KHZ[AUP_PE_LOWPSS_NSEC] = {
+ 2.156619e-01f, 2.156619e-01f, 2.156619e-01f, 2.156619e-01f, 2.156619e-01f};
+
+const float AUP_PE_B_4KHZ[AUP_PE_LOWPSS_NSEC][3] = {
+ {1.000000e+00f, 1.198825e+00f, 1.000000e+00f},
+ {1.000000e+00f, -5.674614e-01f, 1.000000e+00f},
+ {1.000000e+00f, -1.099061e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.265846e+00f, 1.000000e+00f},
+ {1.000000e+00f, -1.318849e+00f, 1.000000e+00f}};
+const float AUP_PE_A_4KHZ[AUP_PE_LOWPSS_NSEC][3] = {
+ {1.000000e+00f, -1.445267e+00f, 5.463974e-01f},
+ {1.000000e+00f, -1.426720e+00f, 6.820138e-01f},
+ {1.000000e+00f, -1.408255e+00f, 8.286664e-01f},
+ {1.000000e+00f, -1.400909e+00f, 9.240320e-01f},
+ {1.000000e+00f, -1.408242e+00f, 9.789776e-01f}};
+const float AUP_PE_G_4KHZ[AUP_PE_LOWPSS_NSEC] = {
+ 2.692541e-01f, 2.692541e-01f, 2.692541e-01f, 2.692541e-01f, 2.692541e-01f};
+
+const float AUP_PE_B_8KHZ[AUP_PE_LOWPSS_NSEC][3] = {
+ {1.000000e+00f, 1.830863e+00f, 1.000000e+00f},
+ {1.000000e+00f, 1.039654e+00f, 1.000000e+00f},
+ {1.000000e+00f, 4.900788e-01f, 1.000000e+00f},
+ {1.000000e+00f, 2.419292e-01f, 1.000000e+00f},
+ {1.000000e+00f, 1.517919e-01f, 1.000000e+00f}};
+const float AUP_PE_A_8KHZ[AUP_PE_LOWPSS_NSEC][3] = {
+ {1.000000e+00f, -8.445478e-01f, 2.453003e-01f},
+ {1.000000e+00f, -5.469711e-01f, 5.010509e-01f},
+ {1.000000e+00f, -2.646897e-01f, 7.464574e-01f},
+ {1.000000e+00f, -1.074159e-01f, 8.912371e-01f},
+ {1.000000e+00f, -4.448528e-02f, 9.702184e-01f}};
+const float AUP_PE_G_8KHZ[AUP_PE_LOWPSS_NSEC] = {
+ 4.165686e-01f, 4.165686e-01f, 4.165686e-01f, 4.165686e-01f, 4.165686e-01f};
+
+#define AUP_PE_PI (3.1415926f)
+
+#define AUP_PE_FEAT_TIME_WINDOW (40) // in ms
+// how much time data to use for cross-correlation calculation
+#define AUP_PE_FEAT_MAX_NFRM (12)
+#define AUP_PE_TOTAL_NFEAT (55)
+
+#define AUP_PE_ASSUMED_FFT_4_BAND_ENG (80)
+const int AUP_PE_BAND_START_INDEX[AUP_PE_NB_BANDS] = {
+ // 0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40};
+// compensation
+const float AUP_PE_BAND_LPC_COMP[AUP_PE_NB_BANDS] = {
+ 0.8f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.666667f,
+ 0.5f, 0.5f, 0.5f, 0.333333f, 0.25f, 0.25f, 0.2f, 0.166667f, 0.173913f};
+
+#define AUP_PE_PITCHMAXPATH_W (0.02f)
+
+typedef struct PE_St_ {
+ void* dynamMemPtr; // memory pointer holding the dynamic memory
+ size_t dynamMemSize; // size of the buffer *dynamMemPtr
+ // void* ifftStHdl; // AgoraFft*
+ void* biquadIIRPtr;
+
+ // ---------------------------------------------------------------
+ // Static Configuration
+ PE_StaticCfg stCfg;
+
+ // ---------------------------------------------------------------
+ // Internal Static Config Registers, which are generated from stCfg
+ int nBins;
+ int procResampleRate; // AUP_PE_FS / stCfg.procFs
+ int minPeriod; // min. pitch period in procFs
+ int maxPeriod; // max. pitch period in procFs
+ int difPeriod; // maxPeriod - minPeriod
+ int inputResampleBufLen; // length of the resampling output buffer
+ int inputQLen; // MAX(TRAINING_OFFSET_XXXX, hopSz) + hopSz
+ int excBufLen; // PITCH_MAX_PERIOD + hopSz + 1
+ int nFeat; // number of feature frames to use/store
+ int estDelay; // pitch estimate delay in terms of frames
+ float dct_table[AUP_PE_NB_BANDS *
+ AUP_PE_NB_BANDS]; // coeff. table of DCT transformation
+
+ // ---------------------------------------------------------------
+ // Dynamic Configuration
+ PE_DynamCfg dynamCfg;
+
+ // ---------------------------------------------------------------
+ // Internal Dynamic Config Registers, which are generated from dynamCfg
+
+ // ---------------------------------------------------------------
+ // Variables
+ /////////////////////////////////////////////////////////////////////////
+ float* inputResampleBuf; // [inputResampleBufLen]
+ int inputResampleBufIdx;
+
+ float* inputQ; // [inputQLen]
+ float* alignedIn; // [hopSz]
+ float* lpcFilterOutBuf; // [hopSz]
+
+ float* excBuf; // [excBufLen]
+ // excBuf stores the smoothed LPC prediction result
+ float* excBufSq; // [excBufLen]
+ // = excBuf.^2
+
+ float lpc[AUP_PE_LPC_ORDER];
+ float pitch_mem[AUP_PE_LPC_ORDER];
+ float pitch_filt;
+
+ float tmpFeat[AUP_PE_TOTAL_NFEAT];
+
+ int xCorrOffsetIdx; // the oldest frame's index in xCorr Buffer
+ float* xCorrInst; // [maxPeriod]
+ float* xCorr[AUP_PE_FEAT_MAX_NFRM * 2]; // [stHdl->nFeat * 2][maxPeriod + 1]
+ // circ-buffer [<--->][...]
+ float*
+ xCorrTmp[AUP_PE_FEAT_MAX_NFRM * 2]; // [stHdl->nFeat * 2][maxPeriod + 1]
+ // temporarily modified version of xCorr
+
+ float frmWeight[AUP_PE_FEAT_MAX_NFRM * 2];
+ float frmWeightNorm[AUP_PE_FEAT_MAX_NFRM * 2];
+ // normalized version of frmWeight
+
+ // variables for best pitch estimation ....
+ /////////////////////////////////////////////////////////////////////////
+ float* pitchMaxPathReg[2]; // [2][maxPeriod]
+
+ int* pitchPrev[AUP_PE_FEAT_MAX_NFRM * 2]; // [stHdl->nFeat * 2][maxPeriod]
+ float pitchMaxPathAll;
+ int bestPeriodEst;
+
+ int voiced; // whether this frame has voice
+ float pitchEstResult; // the final result storing the estimated pitch freq.
+} PE_St;
+
+#endif // __PITCH_EST_ST_H__
diff --git a/src/stft.cc b/src/stft.cc
new file mode 100644
index 0000000000000000000000000000000000000000..720fac60b1f80c96cdfad64f32667405a43723b5
--- /dev/null
+++ b/src/stft.cc
@@ -0,0 +1,295 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#include
+#include
+#include
+#include
+
+#include "stft.h"
+#include "stft_st.h"
+#include "fftw.h"
+
+// ==========================================================================================
+// internal tools
+// ==========================================================================================
+
+static int AUP_Analyzer_checkStatCfg(Analyzer_StaticCfg* pCfg) {
+ if (pCfg == NULL) {
+ return -1;
+ }
+
+ if (pCfg->fft_size != 256 && pCfg->fft_size != 512 &&
+ pCfg->fft_size != 1024 && pCfg->fft_size != 2048 &&
+ pCfg->fft_size != 4096) {
+ return -1;
+ }
+
+ if (pCfg->win_len <= 0 || pCfg->win_len < pCfg->hop_size ||
+ pCfg->win_len > pCfg->fft_size) {
+ return -1;
+ }
+
+ if (pCfg->hop_size <= 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int AUP_Analyzer_publishStaticCfg(Analyzer_St* stHdl) {
+ const Analyzer_StaticCfg* pStatCfg;
+ int idx;
+
+ if (stHdl == NULL) {
+ return -1;
+ }
+ pStatCfg = (const Analyzer_StaticCfg*)(&(stHdl->stCfg));
+
+ stHdl->nBins = (pStatCfg->fft_size >> 1) + 1;
+ if (pStatCfg->ana_win_coeff != NULL) {
+ memcpy(stHdl->windowCoffCopy, pStatCfg->ana_win_coeff,
+ sizeof(float) * pStatCfg->win_len);
+ } else {
+ for (idx = 0; idx < AUP_STFT_MAX_FFTSZ; idx++) {
+ stHdl->windowCoffCopy[idx] = 1.0f;
+ }
+ }
+ return 0;
+}
+
+static int AUP_Analyzer_resetVariables(Analyzer_St* stHdl) {
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+ return 0;
+}
+
+static int AUP_Analyzer_dynamMemPrepare(Analyzer_St* stHdl, void* memPtrExt,
+ size_t memSize) {
+ int inputQMemSz = 0;
+ int fftInputBufMemSz = 0;
+ int totalMemSize = 0;
+ char* memPtr = NULL;
+
+ inputQMemSz = AUP_STFT_ALIGN8(sizeof(float) * (stHdl->stCfg.win_len + 4));
+ totalMemSize += inputQMemSz;
+
+ fftInputBufMemSz =
+ AUP_STFT_ALIGN8(sizeof(float) * (stHdl->stCfg.fft_size + 4));
+ totalMemSize += fftInputBufMemSz;
+
+ // if no external memory provided, we are only profiling the memory
+ // requirement
+ if (memPtrExt == NULL) {
+ return (totalMemSize);
+ }
+
+ // if required memory is more than provided, error
+ if ((size_t)totalMemSize > memSize) {
+ return -1;
+ }
+
+ memPtr = (char*)memPtrExt;
+
+ stHdl->inputQ = (float*)memPtr;
+ memPtr += inputQMemSz;
+
+ stHdl->fftInputBuf = (float*)memPtr;
+ memPtr += fftInputBufMemSz;
+
+ if (((int)(memPtr - (char*)memPtrExt)) > totalMemSize) {
+ return -1;
+ }
+
+ return (totalMemSize);
+}
+
+// ==========================================================================================
+// public APIs
+// ==========================================================================================
+
+int AUP_Analyzer_create(void** stPtr) {
+ Analyzer_St* tmpPtr;
+
+ if (stPtr == NULL) {
+ return -1;
+ }
+
+ *stPtr = (void*)malloc(sizeof(Analyzer_St));
+ if (*stPtr == NULL) {
+ return -1;
+ }
+ memset(*stPtr, 0, sizeof(Analyzer_St));
+
+ tmpPtr = (Analyzer_St*)(*stPtr);
+
+ tmpPtr->dynamMemPtr = NULL;
+ tmpPtr->dynamMemSize = 0;
+
+ tmpPtr->stCfg.win_len = 768;
+ tmpPtr->stCfg.hop_size = 256;
+ tmpPtr->stCfg.fft_size = 1024;
+ tmpPtr->stCfg.ana_win_coeff = NULL;
+
+ return 0;
+}
+
+int AUP_Analyzer_destroy(void** stPtr) {
+ Analyzer_St* stHdl;
+
+ if (stPtr == NULL) {
+ return 0;
+ }
+
+ stHdl = (Analyzer_St*)(*stPtr);
+ if (stHdl == NULL) {
+ return 0;
+ }
+
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ }
+ stHdl->dynamMemPtr = NULL;
+
+ free(stHdl);
+ (*stPtr) = NULL;
+
+ return 0;
+}
+
+int AUP_Analyzer_memAllocate(void* stPtr, const Analyzer_StaticCfg* pCfg) {
+ Analyzer_St* stHdl = NULL;
+ Analyzer_StaticCfg localStCfg;
+ int totalMemSize = 0;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+ stHdl = (Analyzer_St*)(stPtr);
+
+ memcpy(&localStCfg, pCfg, sizeof(Analyzer_StaticCfg));
+ if (AUP_Analyzer_checkStatCfg(&localStCfg) < 0) {
+ return -1;
+ }
+
+ memcpy(&(stHdl->stCfg), &localStCfg, sizeof(Analyzer_StaticCfg));
+
+ // 1st. publish internal static configuration registers
+ if (AUP_Analyzer_publishStaticCfg(stHdl) < 0) {
+ return -1;
+ }
+
+ // 4th: check memory requirement
+ totalMemSize = AUP_Analyzer_dynamMemPrepare(stHdl, NULL, 0);
+ if (totalMemSize < 0) {
+ return -1;
+ }
+
+ // 5th: allocate dynamic memory
+ if ((size_t)totalMemSize > stHdl->dynamMemSize) {
+ if (stHdl->dynamMemPtr != NULL) {
+ free(stHdl->dynamMemPtr);
+ stHdl->dynamMemSize = 0;
+ }
+ stHdl->dynamMemPtr = malloc(totalMemSize);
+ if (stHdl->dynamMemPtr == NULL) {
+ return -1;
+ }
+ stHdl->dynamMemSize = totalMemSize;
+ }
+ memset(stHdl->dynamMemPtr, 0, stHdl->dynamMemSize);
+
+ // 6th: setup the pointers/variable
+ if (AUP_Analyzer_dynamMemPrepare(stHdl, stHdl->dynamMemPtr,
+ stHdl->dynamMemSize) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_Analyzer_init(void* stPtr) {
+ Analyzer_St* stHdl;
+
+ if (stPtr == NULL) {
+ return -1;
+ }
+ stHdl = (Analyzer_St*)(stPtr);
+
+ if (AUP_Analyzer_resetVariables(stHdl) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int AUP_Analyzer_getStaticCfg(const void* stPtr, Analyzer_StaticCfg* pCfg) {
+ const Analyzer_St* stHdl;
+
+ if (stPtr == NULL || pCfg == NULL) {
+ return -1;
+ }
+ stHdl = (const Analyzer_St*)(stPtr);
+
+ memcpy(pCfg, &(stHdl->stCfg), sizeof(Analyzer_StaticCfg));
+
+ return 0;
+}
+
+int AUP_Analyzer_proc(void* stPtr, const Analyzer_InputData* pIn,
+ Analyzer_OutputData* pOut) {
+ Analyzer_St* stHdl = NULL;
+ int hopSz, fftSz, winLen, nBins;
+ int idx = 0;
+
+ if (stPtr == NULL || pIn == NULL || pIn->input == NULL || pOut == NULL ||
+ pOut->output == NULL) {
+ return -1;
+ }
+ stHdl = (Analyzer_St*)(stPtr);
+
+ if (pIn->iLength != stHdl->stCfg.hop_size ||
+ pOut->oLength < stHdl->stCfg.fft_size) {
+ return -1;
+ }
+ hopSz = stHdl->stCfg.hop_size;
+ fftSz = stHdl->stCfg.fft_size;
+ nBins = (fftSz >> 1) + 1;
+ winLen = stHdl->stCfg.win_len;
+
+ memset(pOut->output, 0, sizeof(float) * pOut->oLength);
+ memmove(stHdl->inputQ, stHdl->inputQ + hopSz,
+ sizeof(float) * (winLen - hopSz));
+ memcpy(stHdl->inputQ + (winLen - hopSz), pIn->input, sizeof(float) * hopSz);
+
+ if (stHdl->stCfg.ana_win_coeff != NULL) {
+ for (idx = 0; idx < winLen; idx++) {
+ stHdl->fftInputBuf[idx] = stHdl->inputQ[idx] * stHdl->windowCoffCopy[idx];
+ }
+ } else {
+ for (idx = 0; idx < winLen; idx++) {
+ stHdl->fftInputBuf[idx] = stHdl->inputQ[idx];
+ }
+ }
+ for (; idx < fftSz; idx++) {
+ stHdl->fftInputBuf[idx] = 0;
+ }
+
+ if (fftSz == 256) {
+ AUP_FFTW_r2c_256(stHdl->fftInputBuf, pOut->output);
+ } else if (fftSz == 512) {
+ AUP_FFTW_r2c_512(stHdl->fftInputBuf, pOut->output);
+ } else if (fftSz == 1024) {
+ AUP_FFTW_r2c_1024(stHdl->fftInputBuf, pOut->output);
+ } else if (fftSz == 2048) {
+ AUP_FFTW_r2c_2048(stHdl->fftInputBuf, pOut->output);
+ } else if (fftSz == 4096) {
+ AUP_FFTW_r2c_4096(stHdl->fftInputBuf, pOut->output);
+ }
+ AUP_FFTW_InplaceTransf(1, fftSz, pOut->output);
+ AUP_FFTW_RescaleFFTOut(fftSz, pOut->output);
+
+ return 0;
+}
diff --git a/src/stft.h b/src/stft.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f5c57b83c0c90077ab3910a6d693b9392c08681
--- /dev/null
+++ b/src/stft.h
@@ -0,0 +1,148 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __STFT_H__
+#define __STFT_H__
+
+#include
+#include
+#include
+
+#define AUP_STFT_MAX_FFTSZ (4096)
+
+// Configuration Parameters, which impacts dynamic memory occupation, can only
+// be set during allocation
+typedef struct Analyzer_StaticCfg_ {
+ int win_len;
+ int hop_size;
+ int fft_size;
+ const float* ana_win_coeff;
+} Analyzer_StaticCfg;
+
+// Spectrum are assumed to be generated with time-domain samples in [-32768,
+// 32767] WITH LEC blowup protection Note: the input timeSignal has to be in
+// 16KHz sampling-rate
+typedef struct Analyzer_InputData_ {
+ float* input;
+ int iLength;
+} Analyzer_InputData;
+
+typedef struct Analyzer_OutputData_ {
+ float* output; // externally provided buffe
+ int oLength; // externally provided buffer length
+} Analyzer_OutputData;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * AUP_Analyzer_create(...)
+ *
+ * This function creats a state handler from nothing, which is NOT ready for
+ * processing
+ *
+ * Input:
+ *
+ * Output:
+ * - stPtr : buffer to store the returned state handler
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Analyzer_create(void** stPtr);
+
+/****************************************************************************
+ * AUP_Analyzer_destroy(...)
+ *
+ * destroy PE instance, and releasing all the dynamically allocated memory
+ *
+ * Input:
+ * - stPtr : buffer of State Handler, after this method, this
+ * handler won't be usable anymore
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Analyzer_destroy(void** stPtr);
+
+/****************************************************************************
+ * AUP_Analyzer_memAllocate(...)
+ *
+ * This function sets Static Config params and does memory allocation
+ * operation, will lose the dynamCfg values
+ *
+ * Input:
+ * - stPtr : State Handler which was returned by _create
+ * - pCfg : static configuration parameters
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Analyzer_memAllocate(void* stPtr, const Analyzer_StaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Analyzer_init(...)
+ *
+ * This function resets (initialize) the PE module and gets it prepared for
+ * processing
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Analyzer_init(void* stPtr);
+
+/****************************************************************************
+ * AUP_Analyzer_getStaticCfg(...)
+ *
+ * This function get static configuration status from PE module
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate
+ *
+ * Output:
+ * - pCfg : configuration content
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Analyzer_getStaticCfg(const void* stPtr, Analyzer_StaticCfg* pCfg);
+
+/****************************************************************************
+ * AUP_Analyzer_proc(...)
+ *
+ * process a single frame
+ *
+ * Input:
+ * - stPtr : State Handler which has gone through create and
+ * memAllocate and reset
+ * - pCtrl : per-frame variable control parameters
+ * - pIn : input data stream
+ *
+ * Output:
+ * - pOut : output data (mask, highband time-domain gain etc.)
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+int AUP_Analyzer_proc(void* stPtr, const Analyzer_InputData* pIn,
+ Analyzer_OutputData* pOut);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // __STFT_H__
diff --git a/src/stft_st.h b/src/stft_st.h
new file mode 100644
index 0000000000000000000000000000000000000000..8bfd8c4e8fb4b13b9179526946c9a0b2f5d7808d
--- /dev/null
+++ b/src/stft_st.h
@@ -0,0 +1,42 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#ifndef __STFT_ST_H__
+#define __STFT_ST_H__
+
+#include
+#include "stft.h"
+
+#define AUP_STFT_ALIGN8(o) (((o) + 7) & (~7))
+#define AUP_STFT_MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define AUP_STFT_MIN(x, y) (((x) > (y)) ? (y) : (x))
+
+typedef struct Analyzer_St_ {
+ void* dynamMemPtr; // memory pointer holding the dynamic memory
+ size_t dynamMemSize; // size of the buffer *dynamMemPtr
+
+ // ---------------------------------------------------------------
+ // Static Configuration
+ Analyzer_StaticCfg stCfg;
+
+ // ---------------------------------------------------------------
+ // Internal Static Config Registers, which are generated from stCfg
+ int nBins;
+ float windowCoffCopy[AUP_STFT_MAX_FFTSZ];
+
+ // ---------------------------------------------------------------
+ // Dynamic Configuration
+
+ // ---------------------------------------------------------------
+ // Internal Dynamic Config Registers, which are generated from dynamCfg
+
+ // ---------------------------------------------------------------
+ // Variables
+ float* inputQ; // [stCfg->win_len + 4]
+ float* fftInputBuf; // [stCfg->fft_size + 4]
+} Analyzer_St;
+
+#endif // __STFT_ST_H__
diff --git a/src/ten_vad.cc b/src/ten_vad.cc
new file mode 100644
index 0000000000000000000000000000000000000000..976d9aa1ce89698a3e458503ce76e7dd3d1ac64c
--- /dev/null
+++ b/src/ten_vad.cc
@@ -0,0 +1,69 @@
+//
+// Copyright © 2025 Agora
+// This file is part of TEN Framework, an open source project.
+// Licensed under the Apache License, Version 2.0, with certain conditions.
+// Refer to the "LICENSE" file in the root directory for more information.
+//
+#include
+#include "ten_vad.h"
+#include "aed_st.h"
+#include "aed.h"
+
+static void int16_to_float(const int16_t* inputs, int inputLen, float* output) {
+ for (int i = 0; i < inputLen; ++i) {
+ output[i] = float(inputs[i]);
+ }
+}
+
+int ten_vad_create(ten_vad_handle_t* handle, size_t hop_size, float threshold) {
+ if (AUP_Aed_create(handle) < 0) {
+ return -1;
+ }
+ Aed_St* stHdl = nullptr;
+ Aed_StaticCfg aedStCfg;
+ aedStCfg.enableFlag = 1;
+ aedStCfg.fftSz = 0;
+ aedStCfg.hopSz = hop_size;
+ aedStCfg.anaWindowSz = 0;
+ aedStCfg.frqInputAvailableFlag = 0;
+ stHdl = (Aed_St*)(*handle);
+ stHdl->dynamCfg.extVoiceThr = threshold;
+
+ if (AUP_Aed_memAllocate(*handle, &aedStCfg) < 0) {
+ return -1;
+ }
+ if (AUP_Aed_init(*handle) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+int ten_vad_process(ten_vad_handle_t handle, const int16_t* audio_data,
+ size_t audio_data_length, float* out_probability,
+ int* out_flag) {
+ if (handle == nullptr || audio_data == nullptr ||
+ out_probability == nullptr || out_flag == nullptr) {
+ return -1;
+ }
+ Aed_St* ptr = (Aed_St*)handle;
+ assert(audio_data_length == ptr->stCfg.hopSz);
+ int16_to_float(audio_data, audio_data_length, ptr->inputFloatBuff);
+ Aed_InputData aedInputData;
+ Aed_OutputData aedOutputData;
+ aedInputData.binPower = NULL;
+ aedInputData.hopSz = ptr->stCfg.hopSz;
+ aedInputData.nBins = -1;
+ aedInputData.timeSignal = ptr->inputFloatBuff;
+ int ret = AUP_Aed_proc(handle, &aedInputData, &aedOutputData);
+ if (ret == 0) {
+ *out_probability = aedOutputData.voiceProb;
+ *out_flag = aedOutputData.vadRes;
+ }
+ return ret;
+}
+
+int ten_vad_destroy(ten_vad_handle_t* handle) {
+ return AUP_Aed_destroy(handle);
+}
+
+const char* ten_vad_get_version(void) { return "1.0"; }
\ No newline at end of file