#数字信号 #FFT #频谱 #数字信号处理 #音频 #频率

无 std spectrum-analyzer

一个易于使用且快速的 no_std 库(包含 alloc),用于通过 FFT 获取数字信号(例如音频)的频谱。

30 个版本 (14 个稳定版)

1.5.0 2023 年 9 月 21 日
1.4.0 2023 年 3 月 5 日
1.2.6 2022 年 7 月 20 日
1.2.3 2021 年 11 月 26 日
0.4.1 2021 年 3 月 30 日

#7多媒体

Download history 250/week @ 2024-04-24 265/week @ 2024-05-01 183/week @ 2024-05-08 317/week @ 2024-05-15 207/week @ 2024-05-22 249/week @ 2024-05-29 175/week @ 2024-06-05 163/week @ 2024-06-12 175/week @ 2024-06-19 195/week @ 2024-06-26 95/week @ 2024-07-03 192/week @ 2024-07-10 196/week @ 2024-07-17 237/week @ 2024-07-24 194/week @ 2024-07-31 198/week @ 2024-08-07

每月 852 次下载
11 个包 中使用 (8 个直接使用)

MIT 许可证

110KB
1.5K SLoC

Rust:使用 FFT 进行频谱分析的库

一个易于使用且快速的 no_std 库(包含 alloc),用于通过 FFT 获取数字信号(例如音频)的频谱。

最小支持的 Rust 版本(MSRV)是 1.63.0

我想了解 FFT 如何用于获取频谱

请参阅文件 /EDUCATIONAL.md

如何使用(包括 no_std 环境)

大多数提示和评论位于代码中,所以请查看 GitHub 上的仓库!无论如何,最基本的用法如下

Cargo.toml

# by default feature "microfft-real" is used
[dependencies]
spectrum-analyzer = "<latest version, see crates.io>"

your_binary.rs

use spectrum_analyzer::{samples_fft_to_spectrum, FrequencyLimit};
use spectrum_analyzer::windows::hann_window;
use spectrum_analyzer::scaling::divide_by_N_sqrt;

/// Minimal example.
fn main() {
    // YOU need to implement the samples source; get microphone input for example
    let samples: &[f32] = &[0.0, 3.14, 2.718, -1.0, -2.0, -4.0, 7.0, 6.0];
    // apply hann window for smoothing; length must be a power of 2 for the FFT
    // 2048 is a good starting point with 44100 kHz
    let hann_window = hann_window(&samples[0..8]);
    // calc spectrum
    let spectrum_hann_window = samples_fft_to_spectrum(
        // (windowed) samples
        &hann_window,
        // sampling rate
        44100,
        // optional frequency limit: e.g. only interested in frequencies 50 <= f <= 150?
        FrequencyLimit::All,
        // optional scale
        Some(&divide_by_N_sqrt),
    ).unwrap();

    for (fr, fr_val) in spectrum_hann_window.data().iter() {
        println!("{}Hz => {}", fr, fr_val)
    }
}

性能

在 i7-1165G7 @ 2.80GHz(单线程)上优化构建的测量结果

我测试了多个 FFT 实现。以下是你为什么决定使用 microfft::real 的原因。它不仅是最快的,而且可以在 no_std 环境中工作。

操作 时间
4096 个样本的汉宁窗口 ≈68µs
4096 个样本的汉明窗口 ≈118µs
4096 个样本的 FFT(rustfft)到频谱 ≈170µs
4096 个样本的 FFT(microfft::real)到频谱 ≈90µs
4096 个样本的 FFT(microfft::complex)到频谱 ≈250µs

示例可视化

在以下示例中,您可以看到从 0 到 4000Hz 的频谱的基本可视化,用于 44100Hz 采样率下 50Hz、1000Hz 和 3777Hz 正弦波的分层信号。给定频率的峰值清晰可见。每个计算都是使用 2048 个样本完成的,即 ≈46ms 的音频信号。

噪声(错误峰值)也来自添加的正弦波的削顶!

样本上的无窗口函数频谱

峰值(50Hz、1000Hz、3777Hz)清晰可见,但也存在一些噪声。0-4000Hz分层正弦信号(50Hz、1000Hz、3777Hz)频谱的图像(无窗口函数)

在FFT之前的样本上使用Hann窗口函数的频谱

峰值(50Hz、1000Hz、3777Hz)清晰可见,Hann窗口函数略微减少了噪声。由于本例中噪声较少,您看不到太大的差异。0-4000Hz分层正弦信号(50Hz、1000Hz、3777Hz)频谱的图像(Hann窗口函数)

在FFT之前的样本上使用Hamming窗口函数的频谱

峰值(50Hz、1000Hz、3777Hz)清晰可见,Hamming窗口函数略微减少了噪声。由于本例中噪声较少,您看不到太大的差异。0-4000Hz分层正弦信号(50Hz、1000Hz、3777Hz)频谱的图像(Hamming窗口函数)

实时音频加频谱可视化

执行示例 $ cargo run --release --example live-visualization。它将向您展示如何实时可视化音频数据以及当前频谱。

Example visualization of real-time audio + spectrum analysis

构建和执行测试

要执行测试,您需要包libfreetype6-dev(在Ubuntu/Debian上)。这是必需的,因为并非所有测试都是“自动单元测试”,还有需要通过查看生成的频谱图来视觉检查的测试。

趣味/常见问题解答

为什么使用f64而不是f32?

我测试了f64,但额外的精度并不足以抵消大约40%的计算开销(在x86_64上)。

我该如何对抗噪声?

应用窗口函数,例如Hann窗口或Hamming窗口。

更多信息的良好资源

还可以查看我的博客文章

依赖关系

~2MB
~97K SLoC