fft
快速傅里叶变换
说明
示例
含噪信号
使用傅里叶变换求噪声中隐藏的信号的频率分量。
指定信号的参数,采样频率为 1 kHz,信号持续时间为 1.5 秒。
Fs = 1000; % Sampling frequency T = 1/Fs; % Sampling period L = 1500; % Length of signal t = (0:L-1)*T; % Time vector
构造一个信号,其中包含幅值为 0.7 的 50 Hz 正弦量和幅值为 1 的 120 Hz 正弦量。
S = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
用均值为零、方差为 4 的白噪声扰乱该信号。
X = S + 2*randn(size(t));
在时域中绘制含噪信号。通过查看信号 X(t)
很难确定频率分量。
plot(1000*t(1:50),X(1:50)) title("Signal Corrupted with Zero-Mean Random Noise") xlabel("t (milliseconds)") ylabel("X(t)")
计算信号的傅里叶变换。
Y = fft(X);
计算双侧频谱 P2
。然后基于 P2
和偶数信号长度 L
计算单侧频谱 P1
。
P2 = abs(Y/L); P1 = P2(1:L/2+1); P1(2:end-1) = 2*P1(2:end-1);
定义频域 f
并绘制单侧幅值频谱 P1
。与预期相符,由于增加了噪声,幅值并不精确等于 0.7 和 1。一般情况下,较长的信号会产生更好的频率逼近值。
f = Fs*(0:(L/2))/L; plot(f,P1) title("Single-Sided Amplitude Spectrum of X(t)") xlabel("f (Hz)") ylabel("|P1(f)|")
现在,采用原始的、未破坏信号的傅里叶变换并检索精确幅值 0.7 和 1.0。
Y = fft(S); P2 = abs(Y/L); P1 = P2(1:L/2+1); P1(2:end-1) = 2*P1(2:end-1); plot(f,P1) title("Single-Sided Amplitude Spectrum of S(t)") xlabel("f (Hz)") ylabel("|P1(f)|")
高斯脉冲
将高斯脉冲从时域转换为频域。
指定信号的参数,采样频率为 44.1 kHz,信号持续时间为 1 秒。创建一倍标准差为 0.1 ms 的高斯脉冲。
Fs = 44100; % Sampling frequency T = 1/Fs; % Sampling period t = -0.5:T:0.5; % Time vector L = length(t); % Signal length X = 1/(0.4*sqrt(2*pi))*(exp(-t.^2/(2*(0.1*1e-3)^2)));
在时域中绘制脉冲。
plot(t,X) title("Gaussian Pulse in Time Domain") xlabel("Time (t)") ylabel("X(t)") axis([-1e-3 1e-3 0 1.1])
fft
的执行时间取决于变换的长度。仅具有小质因数的变换长度比那些具有大质因数的变换长度的执行时间要快得多。
在此示例中,信号长度 L
是 44101,这是非常大的质数。为了改进 fft
的性能,从原始信号长度确定一个是下一个 2 次幂的输入长度。使用此输入长度调用 fft
会将具有尾随零的脉冲 X
填充到指定的变换长度。
n = 2^nextpow2(L);
将高斯脉冲转换为频域。
Y = fft(X,n);
定义频域并绘制唯一频率。
f = Fs*(0:(n/2))/n; P = abs(Y/n).^2; plot(f,P(1:n/2+1)) title("Gaussian Pulse in Frequency Domain") xlabel("f (Hz)") ylabel("|P(f)|^2")
余弦波
比较时域和频域中的余弦波。
指定信号的参数,采样频率为 1 kHz,信号持续时间为 1 秒。
Fs = 1000; % Sampling frequency T = 1/Fs; % Sampling period L = 1000; % Length of signal t = (0:L-1)*T; % Time vector
创建一个矩阵,其中每一行代表一个频率经过缩放的余弦波。结果 X
为 3×1000 矩阵。第一行的波频为 50,第二行的波频为 150,第三行的波频为 300。
x1 = cos(2*pi*50*t); % First row wave x2 = cos(2*pi*150*t); % Second row wave x3 = cos(2*pi*300*t); % Third row wave X = [x1; x2; x3];
在单个图窗中按顺序绘制 X
的每行的前 100 个项,并比较其频率。
for i = 1:3 subplot(3,1,i) plot(t(1:100),X(i,1:100)) title("Row " + num2str(i) + " in the Time Domain") end
指定 dim
参数沿 X
的行(即对每个信号)使用 fft
。
dim = 2;
计算信号的傅里叶变换。
Y = fft(X,L,dim);
计算每个信号的双侧频谱和单侧频谱。
P2 = abs(Y/L); P1 = P2(:,1:L/2+1); P1(:,2:end-1) = 2*P1(:,2:end-1);
在频域内,为单个图窗中的每一行绘制单侧幅值频谱。
for i=1:3 subplot(3,1,i) plot(0:(Fs/L):(Fs/2-Fs/L),P1(i,1:L/2)) title("Row " + num2str(i) + " in the Frequency Domain") end
正弦波的相位
创建一个由频率为 15 Hz 和 40 Hz 的两个正弦波组成的信号。第一个正弦波是相位为 的余弦波,第二个正弦波是相位为 的余弦波。以 100 Hz 的频率对信号进行 1 秒钟的采样。
Fs = 100; t = 0:1/Fs:1-1/Fs; x = cos(2*pi*15*t - pi/4) + cos(2*pi*40*t + pi/2);
计算信号的傅里叶变换。将变换幅值绘制为频率函数。
y = fft(x); z = fftshift(y); ly = length(y); f = (-ly/2:ly/2-1)/ly*Fs; stem(f,abs(z)) title("Double-Sided Amplitude Spectrum of x(t)") xlabel("Frequency (Hz)") ylabel("|y|") grid
计算变换的相位,删除小幅值变换值。将相位绘制为频率函数。
tol = 1e-6; z(abs(z) < tol) = 0; theta = angle(z); stem(f,theta/pi) title("Phase Spectrum of x(t)") xlabel("Frequency (Hz)") ylabel("Phase/\pi") grid
FFT 的插值
通过填充零来对信号的傅里叶变换进行插值。
指定信号的参数,采样频率为 80 Hz,信号持续时间为 0.8 秒。
Fs = 80; T = 1/Fs; L = 65; t = (0:L-1)*T;
创建一个 2 Hz 正弦信号及其高次谐波的叠加。该信号包含一个 2 Hz 余弦波、一个 4 Hz 余弦波和一个 6 Hz 正弦波。
X = 3*cos(2*pi*2*t) + 2*cos(2*pi*4*t) + sin(2*pi*6*t);
在时域中绘制该信号。
plot(t,X) title("Signal superposition in time domain") xlabel("t (ms)") ylabel("X(t)")
计算信号的傅里叶变换。
Y = fft(X);
计算信号的单侧幅值频谱。
f = Fs*(0:(L-1)/2)/L; P2 = abs(Y/L); P1 = P2(1:(L+1)/2); P1(2:end) = 2*P1(2:end);
在频域中绘制单侧频谱。由于信号的时间采样相当短,傅里叶变换的频率分辨率不够精确,不足以显示 4 Hz 附近的峰值频率。
plot(f,P1,"-o") title("Single-Sided Spectrum of Original Signal") xlabel("f (Hz)") ylabel("|P1(f)|")
为了更好地评估峰值频率,您可以通过用零填充原始信号来增加分析窗的长度。这种方法以更精确的频率分辨率自动对信号的傅里叶变换进行插值。
从原始信号长度确定是下一个 2 次幂的新输入长度。用尾随零填充信号 X
以扩展其长度。计算填零后的信号的傅里叶变换。
n = 2^nextpow2(L); Y = fft(X,n);
计算填零后的信号的单侧幅值频谱。由于信号长度 n
从 65 增加到 128,频率分辨率变为 Fs/n
,即 0.625 Hz。
f = Fs*(0:(n/2))/n; P2 = abs(Y/L); P1 = P2(1:n/2+1); P1(2:end-1) = 2*P1(2:end-1);
绘制填零后的信号的单侧频谱。此新频谱在 0.625 Hz 的频率分辨率内显示 2 Hz、4 Hz 和 6 Hz 附近的峰值频率。
plot(f,P1,"-o") title("Single-Sided Spectrum of Padded Signal") xlabel("f (Hz)") ylabel("|P1(f)|")
输入参数
X
— 输入数组
向量 | 矩阵 | 多维数组
输入数组,指定为向量、矩阵或多维数组。
如果 X
为 0×0 空矩阵,则 fft(X)
返回一个 0×0 空矩阵。
数据类型: double
| single
| int8
| int16
| int32
| uint8
| uint16
| uint32
| logical
复数支持: 是
n
— 变换长度
[]
(默认) | 非负整数标量
变换长度,指定为 []
或非负整数标量。为变换长度指定正整数标量可以改进 fft
的性能。通常,长度指定为 2 的幂或可分解为小质数的乘积的值。(质因数不大于 7)。如果 n
小于信号的长度,则 fft
忽略第 n
个条目之后的其余信号值,并返回截断后的结果。如果 n
为 0
,则 fft
返回空矩阵。
示例: n = 2^nextpow2(size(X,1))
数据类型: double
| single
| int8
| int16
| int32
| uint8
| uint16
| uint32
| logical
dim
— 沿其运算的维度
正整数标量
沿其运算的维度,指定为正整数标量。如果不指定维度,则默认为第一个大于 1 的数组维度。
fft(X,[],1)
沿X
的各列进行运算,并返回每列的傅里叶变换。fft(X,[],2)
沿X
的各行进行运算,并返回每行的傅里叶变换。
如果 dim
大于 ndims(X)
,则 fft(X,[],dim)
返回 X
。当指定 n
时,fft(X,n,dim)
将对 X
进行填充或截断,以使维度 dim
的长度为 n
。
数据类型: double
| single
| int8
| int16
| int32
| uint8
| uint16
| uint32
| logical
输出参数
Y
— 频域表示
向量 | 矩阵 | 多维数组
频域表示,以向量、矩阵或多维数组形式返回。
如果 X
的类型为 single
,则 fft
本身以单精度进行计算,Y
的类型也是 single
。否则,Y
以 double
类型返回。
Y
的大小如下:
对于
Y = fft(X)
或Y = fft(X,[],dim)
,Y
的大小等于X
的大小。对于
Y = fft(X,n,dim)
,size(Y,dim)
的值等于n
,而所有其他维度的大小保持与在X
中相同。
如果 X
为实数,则 Y
是共轭对称的,且 Y
中特征点的数量为 ceil((n+1)/2)
。
数据类型: double
| single
详细信息
向量的离散傅里叶变换
Y = fft(X)
和 X = ifft(Y)
分别实现傅里叶变换和傅里叶逆变换。对于长度为 n
的 X
和 Y
,这些变换定义如下:
其中
为 n 次单位根之一。
提示
fft
的执行时间取决于变换的长度。仅具有小质因数(不大于 7)的变换长度的执行时间明显快于本身是质数或具有较大质因数的变换长度的执行时间。对于大多数
n
值,实数输入的 DFT 需要的计算时间大致是复数输入的 DFT 计算时间的一半。但是,当n
有较大的质因数时,速度很少有差别或没有差别。使用工具函数
fftw
可能会提高fft
的速度。此函数控制用于计算特殊大小和维度的 FFT 算法优化。
参考
[1] FFTW (https://www.fftw.org)
[2] Frigo, M., and S. G. Johnson. “FFTW: An Adaptive Software Architecture for the FFT.” Proceedings of the International Conference on Acoustics, Speech, and Signal Processing. Vol. 3, 1998, pp. 1381-1384.
扩展功能
C/C++ 代码生成
使用 MATLAB® Coder™ 生成 C 代码和 C++ 代码。
用法说明和限制:
有关可变大小数据的限制,请参阅Variable-Sizing Restrictions for Code Generation of Toolbox Functions (MATLAB Coder)。
对于 MEX 输出,MATLAB® Coder™ 使用 MATLAB 用于 FFT 算法的库。对于独立的 C/C++ 代码,默认情况下,代码生成器生成用于 FFT 算法的代码,而不是生成 FFT 库调用。要生成对安装的特定 FFTW 库的调用,请提供 FFT 库回调类。有关 FFT 库回调类的详细信息,请参阅
coder.fftw.StandaloneFFTW3Interface
(MATLAB Coder)。对于 MATLAB Function 模块的仿真,仿真软件使用 MATLAB 用于 FFT 算法的库。对于 C/C++ 代码生成,默认情况下,代码生成器生成用于 FFT 算法的代码,而不是生成 FFT 库调用。要生成对安装的特定 FFTW 库的调用,请提供 FFT 库回调类。有关 FFT 库回调类的详细信息,请参阅
coder.fftw.StandaloneFFTW3Interface
(MATLAB Coder)。使用代码替换库 (CRL),您可以生成在 ARM® Cortex®-A 处理器(带 Neon 扩展)上运行的优化代码。要生成此优化代码,您必须安装 Embedded Coder® Support Package for ARM Cortex-A Processors (Embedded Coder)。为 ARM Cortex-A 生成的代码使用 Ne10 库。有关详细信息,请参阅 Ne10 Conditions for MATLAB Functions to Support ARM Cortex-A Processors (Embedded Coder)。
使用代码替换库 (CRL),您可以生成在 ARM Cortex-M 处理器上运行的优化代码。要生成此优化代码,您必须安装 Embedded Coder Support Package for ARM Cortex-M Processors (Embedded Coder)。为 ARM Cortex-M 生成的代码使用 CMSIS 库。有关详细信息,请参阅 CMSIS Conditions for MATLAB Functions to Support ARM Cortex-M Processors (Embedded Coder)。
GPU 代码生成
使用 GPU Coder™ 为 NVIDIA® GPU 生成 CUDA® 代码。
基于线程的环境
使用 MATLAB® backgroundPool
在后台运行代码或使用 Parallel Computing Toolbox™ ThreadPool
加快代码运行速度。
此函数完全支持基于线程的环境。有关详细信息,请参阅在基于线程的环境中运行 MATLAB 函数。
GPU 数组
通过使用 Parallel Computing Toolbox™ 在图形处理单元 (GPU) 上运行来加快代码执行。
fft
函数部分支持 GPU 数组。当您将输入数据指定为 gpuArray
(Parallel Computing Toolbox) 时,函数的某些语法可在 GPU 上运行。用法说明和限制:
即使所有虚部都为零,输出
Y
也始终为复数。
有关详细信息,请参阅Run MATLAB Functions on a GPU (Parallel Computing Toolbox)。
分布式数组
使用 Parallel Computing Toolbox™ 在集群的组合内存中对大型数组进行分区。
用法说明和限制:
对于分布式数组,
fft
不使用并行 FFT 算法,而是在单个工作进程上收集向量以执行质数长度 FFT。对于质数长度较大的向量 FFT,可能导致内存不足错误。
有关详细信息,请参阅Run MATLAB Functions with Distributed Arrays (Parallel Computing Toolbox)。
版本历史记录
在 R2006a 之前推出
MATLAB 命令
您点击的链接对应于以下 MATLAB 命令:
请在 MATLAB 命令行窗口中直接输入以执行命令。Web 浏览器不支持 MATLAB 命令。
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list:
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)