# BFSRC **Repository Path**: BlueVale/BFSRC ## Basic Information - **Project Name**: BFSRC - **Description**: 学习型帧频域修正器把普通歌曲高质量升采样到 192kHz,并叠加母带级保护输出 - **Primary Language**: Rust - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-25 - **Last Updated**: 2026-07-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # BFSRC — 无带限平稳帧采样率转换(Bandlimit-Free Stationary Frame SRC) BFSRC 是一个用 Rust 实现的、生产级母带输出 SRC(Sample Rate Conversion)引擎,默认包含稳定 CUDA Driver/NVRTC GPU 后端,并保留 NVIDIA `cuda-oxide` 实验后端 feature。 它**不属于**传统的 polyphase / Farrow / windowed-sinc 这一类“局部卷积核”方案,而是把整段音频视为一个**平稳随机过程**,在一个**过完备平稳帧**(无下采样 STFT)上,求解一个**全局最小二乘 + 带权自协方差正则**的线性算子。该算子在频域上**不再是逐点标量乘子**,而是一个**耦合相邻帧的 2×2 块矩阵估计器**,它在你定义的“感知 + 正则”目标下,对 teacher(高精度 apodizing sinc 重建)做全局最优逼近。 整条链路是: > RKHS / 变分广义采样 → 频域 Tikhonov 闭式解 → 离散化为全局 giant-FFT 帧算子 → 2×2 跨帧块矩阵。 --- ## 1. 它解决什么问题 把 44100 Hz / 48000 Hz 的音频升采样到 192000 Hz(或任意更高采样率),并且让默认输出可以作为最终母带导出的首选路径: - **可听频段(通带)完全保真**:1 kHz 到 18 kHz 实测 0.00 dB,20 kHz 采用 apodizing 温和滚降,避免砖墙 sinc 的前振铃; - **镜像 / 超声成分被强力压制**:实测最差镜像 < −117 dB,不会把廉价插值产生的镜像泄漏带进成品; - **母带级输出保护**:DC/次声清理、声道联动 lookahead 限幅、-1.0 dBFS ceiling、最终硬 ceiling; - 输出为 **24-bit + TPDF 抖动 + 二阶噪声整形**,听感噪声底进一步下压; - **大量音源训练**:可以递归读取整个音源文件夹,按输入采样率自动分组训练多个 `.bfm` 模型; - **真实 NVIDIA GPU 加速**:`run`、`process`、`learn`、`learn-folder` 的 teacher sinc 路径支持 `--gpu`,会通过 CUDA Driver + NVRTC 在 NVIDIA GPU 上执行 sinc kernel; - 输入不再局限于 WAV,现已通过 Symphonia 支持 WAV / FLAC / MP3 / OGG / M4A / MP4 / AAC / ALAC 等常见音频容器和编码。 --- ## 2. 数学框架 ### 2.1 过完备平稳帧 对(升采样基线后的)信号 $x[n]$ 做平移不变的加窗 STFT: $$ X_m[k] = \sum_{n} x[n]g[n-mL]e^{-i 2\pi k n / N} $$ 其中 $g$ 为周期 Hann 窗,$N$ 为 FFT 长度,$L$ 为 hop(默认 75% 重叠)。由于高度重叠,这是一个**过完备平稳帧**,重建非唯一,从而留出优化自由度。 ### 2.2 变分目标与闭式解 在帧系数空间上,对每个频率 bin $k$ 学习一个线性算子,使其在加权最小二乘 + Frobenius 正则 + 自协方差约束下逼近 teacher: $$ J(G)=\sum_{m,k} W[k]\big|(SGX)[m,k]-X^{\text{teacher}}[m,k]\big|^2 +\lambda\|G\|_{\mathcal F}^2+\mu\Phi(G) $$ 对 $G$ 求导得每个 bin 独立的矩阵正规方程,闭式解为: $$ G[k]=\Big(R_X[k]+\lambda I+\mu Q[k]\Big)^{-1} R_{XX^{\text{teacher}}}[k] $$ - $R_X[k]=\mathbb E\left[X[k]X[k]^{H}\right]$:输入帧系数的(跨帧)自协方差; - $R_{XX^{\text{teacher}}}[k]=\mathbb E\left[X^{\text{teacher}}[k]X[k]^{H}\right]$:teacher 与输入的互协方差; - $Q[k]$:功率谱约束(高频惩罚,抑制超声/镜像噪声); - $\lambda,\mu$:正则参数。 ### 2.3 2×2 跨帧块矩阵 本实现把 $G[k]$ 从标量乘子扩展为耦合“当前帧 + 前一帧”的 2 抽头估计器。对每个 bin $k$,定义回归向量: $$ u_m[k]=\big[\,X_m[k],\; X_{m-1}[k]\,\big]^{T} $$ 目标为 teacher 系数 $T_m[k]$。复数最小二乘的正规方程为 $R[k]g[k]=r[k]$,其中 $$ R[k]=\sum_m \overline{u_m[k]}u_m[k]^{T}\in\mathbb C^{2\times 2},\qquad r[k]=\sum_m \overline{u_m[k]}T_m[k]\in\mathbb C^{2} $$ 加入对角正则 $\rho_k=\lambda+\mu Q[k]$ 后,$R$ 为 2×2 Hermitian 矩阵 $\begin{bmatrix}a&b\\\bar b&d\end{bmatrix}$,用闭式 cofactor 求逆: $$ \det = (a+\rho_k)(d+\rho_k)-|b|^2, \quad g_0=\frac{(d+\rho_k)r_0-b\,r_1}{\det}, \quad g_1=\frac{-\bar b\,r_0+(a+\rho_k)r_1}{\det} $$ 在线应用: $$ Y_m[k]=g_0[k]X_m[k]+g_1[k]X_{m-1}[k] $$ 对实信号,统计量天然满足 $g[N-k]=\overline{g[k]}$,因此输出严格保持 Hermitian 对称,重建为实信号。 --- ## 3. 处理链路 ```text 输入 (fs_in) ├─ 默认 run: Kaiser 窗 sinc 多相 SRC (CPU Rayon 或 CUDA GPU) ──► 母带级输出链 ──► 24-bit TPDF + 噪声整形 ├─ run-fft: 逐帧 giant-FFT / Tikhonov 频域 SRC ──► OLA ──► 24-bit 输出 └─ learn/process: Catmull-Rom 基线 ─► STFT ─► 学习/应用 2×2 G ─┐ Kaiser-sinc teacher/参考路径 (CPU 或 CUDA) ───┘ ``` - **默认 `run`**:直接使用高精度 apodizing Kaiser-sinc 多相 SRC,优先保证听感和通带保真,不再把质量上限绑在 Catmull-Rom 基线上。 - **母带输出链(完全透明)**:先做 DC/8 Hz 次声清理,再做声道联动 4 ms lookahead 限幅,85 ms release,ceiling 为 -1.0 dBFS。`max_gain_db = 0`,即**绝不向上推响度**,只在峰值超过 -1 dBFS 时温和下压保护,完整保留原始动态,避免响度最大化带来的发闷、抽水和瞬态发挤。 - **并行渲染**:未使用 `--gpu` 时,高精度 sinc 内核使用 Rayon 并行处理声道和输出样本;使用 `--gpu` 时,sinc teacher/参考路径通过 CUDA Driver + NVRTC 编译并执行 GPU kernel。 - **`run-fft`**:保留逐帧 giant-FFT / Tikhonov 路线,用频域闭式算子与 OLA 近似整体 giant-FFT,适合实验和对照。 - **teacher(apodizing 设计)**:Kaiser($\beta=12$)窗 sinc 多相插值,48 个零交叉半宽,截止取 input Nyquist 的 0.955 倍,1024 子相位查找表 + 线性插值。对升采样而言镜像谱远在 input Nyquist 之上,无需极陡砖墙,因此改用更短、更柔和的内核:通带平坦到 18 kHz(0.00 dB),20 kHz 仅 −2.04 dB 温和滚降,镜像抑制 < −117 dB,并将线性相位前振铃从旧版超长砖墙的明显拖尾降到很低,瞬态更自然、无数码毛刺。 - **G 的作用**:学习“基线 → teacher”的差异。`process` 会把离线模型作为有界轻量修饰,并由 sinc 参考路径兜底;模型修饰量限制在局部幅度范围内,避免外推带来的高频发暗、毛刺、削波或听感染色。 - **真实离线学习**:`learn` 可以同时读取多首训练音频,把所有声道作为训练样本聚合,学习一个可复用的全局模型。正则项按每个频率 bin 的局部谱能量缩放,避免旧版本绝对正则在低能量频段过度收缩。 - **文件夹训练**:`learn-folder` 会递归扫描音源目录,并自动按输入采样率分组。若目录里同时有 44.1 kHz 和 192 kHz 文件,会分别输出 `模型名_44100to192000.bfm` 和 `模型名_192000to192000.bfm`。 - **NVIDIA GPU**:默认 `cuda` feature 使用 `cudarc` 调用 CUDA Driver + NVRTC,运行时编译并启动 sinc resampling kernel。项目也引入 NVIDIA 官方 `cuda-oxide` crate,作为 `cuda-oxide` feature 的实验后端;当前 `cuda-oxide` 官方上游在 Windows + MSVC 下仍存在 `cuda-core` 绑定类型问题,因此 Windows 推荐默认 CUDA Driver/NVRTC 后端。 - **STFT**:周期 Hann 窗,$N=4096$,hop $=1024$(75% 重叠),分析窗 + 合成窗 + $\sum w^2$ 归一化,保证恒等算子下完美重建(COLA)。 - **流式实现**:学习与应用都逐帧流式进行,仅保留前一帧,内存占用与文件长度无关,可处理任意时长音频。 --- ## 4. 构建 需要 Rust(stable)工具链。默认构建包含稳定 CUDA Driver/NVRTC 后端,使用动态加载,不要求链接 CUDA 静态库;运行 `--gpu` 时需要 NVIDIA 驱动、可用 GPU,以及 CUDA Toolkit 中的 NVRTC 运行库。 ```powershell cargo build --release ``` 可执行文件位于 `target/release/bfsrc.exe`(Windows)或 `target/release/bfsrc`(Linux/macOS)。 Windows 若 CUDA Toolkit 未加入环境变量,可设置: ```powershell $env:CUDA_PATH = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.8" $env:PATH = "$env:CUDA_PATH\bin;$env:PATH" ``` NVIDIA `cuda-oxide` 实验后端需要官方要求的 nightly、`rust-src`、`rustc-dev`、`llvm-tools`、CUDA Toolkit、cargo-oxide,以及当前更适合 Linux 的构建环境: ```powershell rustup toolchain install nightly-2026-04-03 --component rust-src --component rustc-dev --component llvm-tools cargo install --git https://github.com/NVlabs/cuda-oxide.git cargo-oxide cargo oxide build --release --no-default-features --features cuda-oxide ``` --- ## 5. 使用 ### 5.1 一步到位(最高保真,推荐) ```powershell bfsrc run 输入音频 输出.wav --fs-out 192000 bfsrc run 输入音频 输出.wav --fs-out 192000 --gpu ``` 这是默认推荐路径,目标是稳定、干净、保真,并可直接作为最终母带 WAV 输出。输出前会自动清理 DC/次声、做声道联动 lookahead 限幅,并把最终峰值控制在 -1.0 dBFS ceiling。`--gpu` 会把 sinc teacher 路径交给 NVIDIA GPU 执行;若 GPU 或 CUDA 运行库不可用,会明确报错,不会降级伪装。 ### 5.2 giant-FFT / Tikhonov 路线 ```powershell bfsrc run-fft 输入音频 输出.wav --fs-out 192000 ``` 这一路径对应频域闭式解和 OLA 近似 giant-FFT 的实现。它更适合做算法实验;如果目标是最终听感,请优先使用 `run`。 ### 5.3 分离的学习 / 应用 ```powershell bfsrc learn model.bfm 训练1.wav 训练2.m4a 训练3.ogg --fs-out 192000 --gpu bfsrc process 输入音频 model 输出.wav --gpu ``` 所有训练音频必须具有相同输入采样率。不同容器和编码可以混合使用,例如 WAV + M4A + OGG,但如果采样率不同,应先分开训练不同模型。`process` 可以接收一个真实单模型,也可以接收一个模型组前缀,例如 `model`。当同目录存在 `model_44100to192000.bfm`、`model_48000to192000.bfm`、`model_96000to192000.bfm` 等分组模型时,程序会先读取输入音频采样率,再自动选择匹配的模型;你不需要手动判断输入是 44.1 kHz、48 kHz 还是 96 kHz,也不需要真的存在一个 `model.bfm` 文件。`learn`/`learn-folder` 使用 `--gpu` 时,训练 teacher 生成阶段在 CUDA 上运行;STFT 统计、模型求解与 I/O 仍在 CPU 上执行。`process` 使用 `--gpu` 时,参考 sinc 路径在 CUDA 上运行,2×2 模型应用按声道 Rayon 并行执行。 ### 5.4 大量音源文件夹训练 ```powershell bfsrc learn-folder music_models.bfm 音源文件夹 --fs-out 192000 --gpu ``` `learn-folder` 会递归读取文件夹中的 WAV / FLAC / MP3 / OGG / M4A / MP4 / AAC / ALAC 等音频。若输入采样率混合,会自动按采样率拆分模型。示例: ```text music_models_44100to192000.bfm music_models_48000to192000.bfm music_models_192000to192000.bfm ``` 处理未知采样率音频时只需要传入同一个模型组入口: ```powershell bfsrc process 任意输入音频 music_models 输出.wav --gpu ``` 如果输入是 44.1 kHz,程序会自动加载 `music_models_44100to192000.bfm`;如果输入是 48 kHz,会自动加载 `music_models_48000to192000.bfm`。如果没有对应采样率的模型,程序会明确报错并提示缺少哪个分组模型。 `--gpu` 会检测并打印 NVIDIA GPU 信息,并真实调用 CUDA sinc kernel。若当前二进制未启用 CUDA feature、NVIDIA 驱动不可用、NVRTC 无法加载或 kernel 编译失败,程序会停止并报告原因。 ### 5.5 分析音频 ```powershell bfsrc analyze 音频1 音频2 ``` 输出采样率、声道、时长、Peak/RMS/Crest、削波样本数、立体声相关度、频谱重心、95% rolloff,以及 20 Hz 到 20 kHz 各频段能量占比。 ### 5.6 参数 - `--fs-out `:目标采样率,默认 `192000`。 - `--gpu`:对 `run`、`learn`、`learn-folder`、`process` 启用 NVIDIA GPU sinc teacher/参考路径。 - 输入采样率从音频容器/编码信息自动读取;目标采样率必须大于输入采样率(本工具用于升采样)。 --- ## 6. 输入 / 输出格式 - **输入**:WAV / FLAC / MP3 / OGG / M4A / MP4 / AAC / ALAC 等 Symphonia 可解码格式,单声道或多声道。 - **输出**:WAV,24-bit PCM,目标采样率,声道数与输入一致。 - 多声道:统计量在所有声道上聚合学习,得到单一算子,再逐声道应用。 --- ## 7. 模型文件 (`.bfm`) 二进制、小端序: | 字段 | 类型 | 说明 | | ------ | ------ | ------ | | magic | 4 字节 | `BFS1` | | fs_in / fs_out | f64 ×2 | 输入 / 输出采样率 | | fft_len / hop | u32 ×2 | STFT 参数 | | lambda / mu | f64 ×2 | 正则参数 | | taps | u32 | 跨帧耦合阶数(=2) | | g | (f64 re, f64 im) × fft_len × 2 | 每 bin 的 2 个复系数 | `process` 子命令会校验输入采样率与模型 `fs_in` 一致。 --- ## 8. 默认参数(见 `src/config.rs`) | 参数 | 默认值 | 含义 | | ------ | -------- | ------ | | `fft_len` | 4096 | FFT 长度 | | `hop` | 1024 | 帧步进(75% 重叠) | | `lambda` | 1e-3 | Frobenius 正则 | | `mu` | 5e-3 | 自协方差 / 高频惩罚权重 | | `teacher_half_width` | 48 | teacher sinc 零交叉半宽(较短→低振铃) | | `teacher_subphase` | 1024 | teacher 查找表子相位数 | | `teacher_beta` | 12.0 | teacher Kaiser 窗 β | | `teacher_cutoff` | 0.955 | apodizing 截止(input Nyquist 的倍数) | --- ## 9. 工程结构 ```text src/ main.rs 命令行入口 (run / run-fft / learn / learn-folder / process / analyze) audio.rs 多格式音频解码与 24-bit WAV 写入 analysis.rs 音频电平、削波、立体声相关度与频谱分析 config.rs 配置与感知高频权重 Q[k] cuda_backend.rs CUDA Driver/NVRTC 后端与 cuda-oxide 实验后端 master.rs 母带级 DC/次声清理、联动 lookahead 限幅与 ceiling spectral.rs 逐帧 giant-FFT / Tikhonov 频域 SRC resample.rs teacher (Kaiser-sinc 多相) 与基线 (Catmull-Rom) 升采样 stft.rs 平稳帧分解 / 合成 (COLA, 流式) learn.rs 2×2 跨帧块算子学习 (B1 闭式解) gpu.rs NVIDIA GPU 检测与 CUDA feature 状态 apply.rs 在线全局帧算子应用 + 重叠相加 model.rs 算子序列化 / 反序列化 quantize.rs 24-bit TPDF 抖动 + 二阶噪声整形 ``` --- ## 10. 实测(44.1 kHz → 192 kHz) | 频率 | 类型 | 输出电平 | | ------ | ------ | ---------- | | 1 kHz | 通带 | 0.00 dB | | 5 kHz | 通带 | 0.00 dB | | 10 kHz | 通带 | 0.00 dB | | 15 kHz | 通带 | 0.00 dB | | 18 kHz | 通带 | 0.00 dB | | 20 kHz | 顶端 apodizing | −2.04 dB | | 21 kHz | 输入 Nyquist 近旁 | −6.35 dB | | 最差镜像 | 23.1 kHz 以上 | < −117 dB | 通带精确保真到 18 kHz,20 kHz 温和滚降,避免旧式超长砖墙 sinc 的前振铃和数码毛刺;镜像与超声被压制到不可闻范围。脉冲响应前/后振铃约 2.4 dB 且对称,瞬态比旧版 96 半宽砖墙内核更自然。 GPU 实测:在 Windows + RTX 4070 SUPER + CUDA 12.8 环境中,`bfsrc run tools/_gpu_in.wav tools/_gpu_out.wav --fs-out 192000 --gpu` 成功检测 GPU、启动 CUDA kernel,并生成 192 kHz / 24-bit WAV。CPU 与 GPU 输出分析一致:1 kHz 测试音 peak -13.89 dBFS、RMS -16.99 dBFS、削波样本 0、centroid 1000 Hz、95% rolloff 1008 Hz。 母带输出链热信号测试:输入接近满幅的 44.1 kHz 双声道测试信号,升采样到 192 kHz 后,输出 peak 为 -1.00 dBFS,削波样本为 0,左右声道相关度保持 1.000。 --- ## 11. 复杂度说明 - 默认 `run` 使用 48 半宽、β=12、apodizing 截止 0.955 的 Kaiser-sinc SRC。CPU 路径通过 Rayon 多线程并行渲染;GPU 路径通过 CUDA Driver + NVRTC 在 NVIDIA GPU 上并行计算输出样本; - `run-fft` 使用逐帧 FFT/IFFT + OLA,复杂度约 $O(N_{\text{out}}\log N)$,适合算法对照; - `learn/process` 使用 STFT 帧算子路径,其中 `process` 会以高精度 sinc 参考路径兜底,并对模型修饰量做有界控制,避免模型外推造成母带质量下降。 --- ## 许可 见 `Cargo.toml` 中的 `license` 字段。