# 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 ids = {81, 83, 16, 53, 65, 102, 53}; // 音素 id(未 intersperse) std::vector 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++ 范围内(见"范围说明")。