15个版本 (稳定)
3.3.0 | 2023年5月28日 |
---|---|
3.2.0 | 2022年12月8日 |
3.1.0 | 2022年11月9日 |
3.0.0 | 2022年2月9日 |
0.2.1 | 2020年7月22日 |
#82 in 算法
48,886 每月下载量
在 81 个crate中使用 (24直接使用)
54KB
833 行
realfft
RealFFT:基于RustFFT的实数到复数的正向FFT和复数到实数的逆向FFT
这个库是对RustFFT的一个包装,它能够快速方便地对实值数据进行FFT。API设计得尽可能接近RustFFT。
使用这个库代替直接使用RustFFT,可以避免在执行FFT之前将实值数据转换为复数。如果长度是偶数,它还可以通过使用长度为原来一半的复数FFT来加快计算速度。然后,将长度为N的实值信号打包到一个长度为N/2的复数缓冲区中,并使用标准的复数到复数FFT进行转换。FFT的结果然后经过后处理,只给出复数频谱的前半部分,即一个长度为N/2+1的复数向量。
逆向FFT通过反向执行相同的步骤,将长度为N/2+1的复数频谱转换成长度为N的实值信号。
与仅将输入转换为长度为N的复数向量并使用长度为N的复数到复数FFT相比,速度提升取决于输入数据的长度。对于较长的FFT以及长度超过约1000个元素的长度,改进大约是一个因子2。对于较短的长度,差异缩小,大约在30个元素时不再有差异。
为什么要使用实数到复数的FFT?
使用复数到复数FFT
将实值信号转换为复数后,使用复数到复数FFT是一种简单的变换方法。
假设 x
是一个长度为6的实向量
x = [x0r, x1r, x2r, x3r, x4r, x5r]
我们现在将 x
转换为复数,通过添加一个值为零的虚部。使用表示复数值 xN
的符号 (xNr, xNi)
,这变为
x_c = [(x0r, 0), (x1r, 0), (x2r, 0), (x3r, 0), (x4r, 0), (x5r, 0)]
执行常规复数FFT,FFT(x_c)
的结果是
FFT(x_c) = [(X0r, X0i), (X1r, X1i), (X2r, X2i), (X3r, X3i), (X4r, X4i), (X5r, X5i)]
但是因为我们的x_c
是实值的(所有虚部都是零),其中一些就变得多余了
FFT(x_c) = [(X0r, 0), (X1r, X1i), (X2r, X2i), (X3r, 0), (X2r, -X2i), (X1r, -X1i)]
最后两个值是X1
和X2
的共轭复数。此外,X0i
和X3i
为零。正如我们所见,输出包含了6个独立值,其余的都是多余的。但FFT计算这些多余值仍然需要时间。将输入数据转换为复数也需要一点时间。
如果x
的长度是7,结果将是
FFT(x_c) = [(X0r, 0), (X1r, X1i), (X2r, X2i), (X3r, X3i), (X3r, -X3i), (X2r, -X2i), (X1r, -X1i)]
结果是相似的,但这次X3i
处没有零。在这种情况下,我们得到的独立值数量与开始时相同。
实数到复数
使用实数到复数FFT消除了将输入数据转换为复数的需要。它还避免了计算多余的输出值。
6个元素的结果是
RealFFT(x) = [(X0r, 0), (X1r, X1i), (X2r, X2i), (X3r, 0)]
7个元素的答案是
RealFFT(x) = [(X0r, 0), (X1r, X1i), (X2r, X2i), (X3r, X3i)]
这是实数到复数FFT输出的数据布局,也是复杂到实数逆FFT所需的输入。
缩放
RealFFT与RustFFT的行为相匹配,并不对正向或反向FFT的输出进行归一化。要获得归一化结果,每个元素必须乘以1/sqrt(length)
,其中length
是实值信号的长度。如果处理涉及到FFT和iFFT步骤,建议将两个归一化步骤合并为单个,通过乘以1/length
。
文档
完整的文档可以通过rustdoc生成。要生成并查看它,请运行
cargo doc --open
基准测试
要运行一组基准测试,比较实数到复数FFT与标准复数到复数FFT,请输入
cargo bench
运行时打印结果,并编译成包含更多详细信息的HTML报告。要查看,请在浏览器中打开target/criterion/report/index.html
。
示例
转换信号,然后对结果进行逆变换。
use realfft::RealFftPlanner;
use rustfft::num_complex::Complex;
use rustfft::num_traits::Zero;
let length = 256;
// make a planner
let mut real_planner = RealFftPlanner::<f64>::new();
// create a FFT
let r2c = real_planner.plan_fft_forward(length);
// make a dummy real-valued signal (filled with zeros)
let mut indata = r2c.make_input_vec();
// make a vector for storing the spectrum
let mut spectrum = r2c.make_output_vec();
// Are they the length we expect?
assert_eq!(indata.len(), length);
assert_eq!(spectrum.len(), length/2+1);
// forward transform the signal
r2c.process(&mut indata, &mut spectrum).unwrap();
// create an inverse FFT
let c2r = real_planner.plan_fft_inverse(length);
// create a vector for storing the output
let mut outdata = c2r.make_output_vec();
assert_eq!(outdata.len(), length);
// inverse transform the spectrum back to a real-valued signal
c2r.process(&mut spectrum, &mut outdata).unwrap();
版本
- 3.3.0: 添加获取复数输入/输出长度的方法。错误修正:清除零虚部中的数值噪声。
- 3.2.0: 允许临时缓冲区大于所需大小。
- 3.1.0: 更新到RustFFT 6.1,支持Neon。
- 3.0.2: 修复有关临时长度错误的令人困惑的错误。
- 3.0.1: 更有用的错误消息,修复令人困惑的错误。
- 3.0.0: 改进错误报告。
- 2.0.1: 小型错误修复。
- 2.0.0: 将RustFFT更新到6.0.0,并将num-complex更新到0.4.0。
- 1.1.0: 添加缺失的Sync+Send。
- 1.0.0: 新api的第一个版本。
兼容性
realfft
crate与RustFFT具有相同的rustc版本要求。除AArch64平台外,所有平台的最低rustc版本为1.37。在AArch64上,最低rustc版本为1.61。
许可证:MIT
依赖项
~3MB
~57K SLoC