File size: 4,401 Bytes
5eee449 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | # Inflect AX TTS C++ SDK
`owensong/Inflect-Micro-v2` Encoder/Decoder 两段式 AXMODEL 的 C++ 推理 SDK,面向 **AX620E / AX637** 板端。直接链接 AX Engine 运行时(`ax_engine` + `ax_sys`,AX620E BSP 惯例)。两套 axmodel 接口一致,通过模型路径切换目标。
## 范围说明
- **包含**:encoder/decoder 推理封装(`AxRunner`)、完整 Host 链(时长取整、`generate_path` 对齐、prior 扩展、噪声注入、Tp=512 分块 crossfade、edge fade、clip、WAV 写出)——纯 C++17,无 Eigen/第三方依赖;`generate_path` 为纯整数逻辑,扩展 matmul 由 0/1 对齐性质等价实现为逐帧 gather(与 matmul 逐位一致,有自测)。
- **不包含**:eSpeak 文本前端(文本 → 音素 id)。C++ 侧 API 接收音素 id 序列;文本前端请用 Python SDK(`../python`)离线生成 id,或在板端自行集成 eSpeak-ng 后按模型仓库 `runtime/text/symbols.py` 映射。
- **seed**:C++ 用 `std::mt19937_64 + normal_distribution`,SDK 内可复现;与 PyTorch 参考及 Python SDK(numpy PCG64)均不逐位一致。
## 目录
```
src/ax_runner.{h,cpp} AX Engine 运行时封装(AX_RUNTIME_ROOT 未设时为 stub)
src/host_chain.{h,cpp} Host 链:expand_priors / inject_noise / 分块 crossfade / edge fade
src/inflect_tts.{h,cpp} InflectTTS 类:synthesize_tokens(token_ids, speed, variation, seed)
src/wav_writer.{h,cpp} 16-bit PCM WAV 写出
src/main.cpp inflect_tts_cli 示例 + --selftest
cmake/aarch64-linux-gnu.toolchain.cmake
```
## 构建
### 本机 configure / 构建检查(无 BSP,stub 引擎)
```bash
cd package/cpp
cmake -B build .
cmake --build build -j
./build/inflect_tts_cli --selftest # Host 链自测(无需 AX 运行时)
```
### 板端 aarch64 交叉编译(AX620E)
```bash
cd package/cpp
cmake -B build-aarch64 \
-DCMAKE_TOOLCHAIN_FILE=cmake/aarch64-linux-gnu.toolchain.cmake \
-DAX_RUNTIME_ROOT=/opt/ax620e_bsp/runtime \
.
cmake --build build-aarch64 -j
```
`AX_RUNTIME_ROOT` 指向 AX620E BSP SDK 的运行时目录(示例写 `/opt/ax620e_bsp/runtime`,按实际 BSP 安装位置替换),需含 `include/ax_engine_api.h`、`include/ax_sys_api.h` 与 `lib/libax_engine.so`、`lib/libax_sys.so`。板内原生编译去掉 toolchain 行、保留 `-DAX_RUNTIME_ROOT` 即可。AX637 同一份代码,仅 axmodel 与 BSP 库不同。
## 板端部署与运行
```bash
# 目标机(示例 IP 192.168.1.10,按实际板地址替换)
scp build-aarch64/inflect_tts_cli root@192.168.1.10:/opt/inflect/
scp ../models/ax620e/encoder.axmodel ../models/ax620e/decoder.axmodel root@192.168.1.10:/opt/inflect/
# 板上(dummy 音素 id,对应文本 "ðə kwɪk")
./inflect_tts_cli \
--encoder encoder.axmodel --decoder decoder.axmodel \
--tokens 81,83,16,53,65,102,53 \
--output out.wav --speed 1.0 --variation 0.667 --seed 0
```
## API
```cpp
#include "inflect_tts.h"
#include "wav_writer.h"
InflectTTS tts("encoder.axmodel", "decoder.axmodel");
std::vector<int64_t> ids = {81, 83, 16, 53, 65, 102, 53}; // 音素 id(未 intersperse)
std::vector<float> wav = tts.synthesize_tokens(ids, /*speed*/1.0f,
/*variation*/0.667f, /*seed*/0);
write_wav("out.wav", wav, 24000);
```
- `token_ids`:音素 id(**未** intersperse;SDK 内部插 blank,长度上限 127 音素 → 255 tokens,对应 encoder 静态 T=256)。
- 返回 24 kHz mono float32,[-1,1],已做 5 ms edge fade。
## I/O 契约(与 Python SDK 一致)
- encoder in:`tokens` int32 [1,256](0 右补齐;**注意 axmodel 运行时输入为 S32**,S64 input_processors 已在编译期折叠)、`x_lengths` int32 [1];out:`m_p`/`logs_p` fp32 [1,192,256]、`logw` fp32 [1,1,256](按输出名寻址,取前 x_lengths 帧)。
- decoder in:`z_p` fp32 [1,192,512](右补零);out:`wav` fp32 [1,1,131072],按有效帧裁剪、块间 64 帧 crossfade。
- Host 链限制:decoder 右缘 padding 会经卷积感受野倒灌污染末段帧(实测 T'=51 时约最后 12 帧;SDK 以 5 ms edge fade 缓解);多块(T'>512)crossfade 路径未做数值门禁验证。
## 已知限制
- 本仓库构建机上 **未做交叉编译与板端运行验证**(无 aarch64 工具链/无板):仅验证本机 configure + 构建 + `--selftest` 通过。`ax_runner.cpp` 的 AX Engine 调用按 AX620E BSP 惯例编写,首次板端构建如遇到 API 差异以 BSP 头文件为准。
- 文本前端不在 C++ 范围内(见"范围说明")。
|