Main Content
本页翻译不是最新的。点击此处可查看最新英文版本。
快速傅里叶变换
全页折叠
语法
Y = fft(X)
Y = fft(X,n)
Y = fft(X,n,dim)
说明
Y = fft(X)
使用快速傅里叶变换 (FFT) 算法计算 X
的离散傅里叶变换 (DFT)。Y
与 X
的大小相同。
如果
X
是向量,则fft(X)
返回该向量的傅里叶变换。如果
X
是矩阵,则fft(X)
将X
的各列视为向量,并返回每列的傅里叶变换。如果
X
是一个多维数组,则fft(X)
将沿大小不等于 1 的第一个数组维度的值视为向量,并返回每个向量的傅里叶变换。
示例
Y = fft(X,n)
返回 n
点 DFT。
如果
X
是向量且X
的长度小于n
,则为X
补上尾零以达到长度n
。如果
X
是向量且X
的长度大于n
,则对X
进行截断以达到长度n
。如果
X
是矩阵,则每列的处理与在向量情况下相同。如果
X
为多维数组,则大小不等于 1 的第一个数组维度的处理与在向量情况下相同。
示例
Y = fft(X,n,dim)
返回沿维度 dim
的傅里叶变换。例如,如果 X
是矩阵,则 fft(X,n,2)
返回每行的 n
点傅里叶变换。
示例
示例
全部折叠
含噪信号
打开实时脚本
通过使用傅里叶变换,求出隐藏在噪声中的信号的频率分量,并求出峰值频率的振幅。
指定信号的参数,采样频率为 1 kHz,信号持续时间为 1.5 秒。
Fs = 1000; % Sampling frequency T = 1/Fs; % Sampling period L = 1500; % Length of signalt = (0:L-1)*T; % Time vector
构造一个信号,其中包含振幅为 0.8 的 DC 偏移量、振幅为 0.7 的 50 Hz 正弦量和振幅为 1 的 120 Hz 正弦量。
S = 0.8 + 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
用均值为零、方差为 4 的随机噪声扰乱该信号。
X = S + 2*randn(size(t));
在时域中绘制含噪信号。频率分量在图中显示不明显。
plot(1000*t,X)title("Signal Corrupted with Zero-Mean Random Noise")xlabel("t (milliseconds)")ylabel("X(t)")
计算信号的傅里叶变换。
Y = fft(X);
由于傅里叶变换涉及复数,因此绘制 fft
频谱的复数模。
plot(Fs/L*(0:L-1),abs(Y),"LineWidth",3)title("Complex Magnitude of fft Spectrum")xlabel("f (Hz)")ylabel("|fft(X)|")
该图显示五个频率峰值,包括 DC 偏移量在 0 Hz 处的峰值。在此示例中,信号预计在 0 Hz、50 Hz 和 120 Hz 处有三个频率峰值。此处,绘图的后半部分是前半部分的镜像,不包括 0 Hz 处的峰值。原因是时域信号的离散傅里叶变换具有周期性,其频谱的前半部分为正频率,后半部分为负频率,第一个元素保留用于零频率。
对于实信号,fft
频谱是双边频谱,其中正频率的频谱是负频率的频谱的复共轭。要显示正负频率的 fft
频谱,可以使用 fftshift
。对于偶数长度 L
,频域从奈奎斯特频率的负值 -Fs/2
开始,直到 Fs/2-Fs/L
,间距或频率分辨率为 Fs/L
。
plot(Fs/L*(-L/2:L/2-1),abs(fftshift(Y)),"LineWidth",3)title("fft Spectrum in the Positive and Negative Frequencies")xlabel("f (Hz)")ylabel("|fft(X)|")
为了找到三个频率峰值的幅值,将 Y
中的 fft
频谱转换为单边振幅频谱。由于 fft
函数包括原始信号和变换信号之间的缩放因子 L
,因此通过除以 L
来重新缩放 Y
。取 fft
频谱的复数模。双边振幅频谱 P2
(其中正频率的频谱是负频率的频谱的复共轭),其峰值振幅是时域信号中对应峰值振幅的一半。要转换为单边频谱,取双边频谱 P2
的前半部分。将正频率的频谱乘以 2。您不需要将 P1(1)
和 P1(end)
乘以 2,因为这些振幅分别对应于零频率和奈奎斯特频率,并且在负频率下没有复共轭对组。
P2 = abs(Y/L);P1 = P2(1:L/2+1);P1(2:end-1) = 2*P1(2:end-1);
定义单边频谱的频域 f
。绘制单边振幅频谱 P1
。与预期相符,振幅接近 0.8、0.7 和 1,但由于增加了噪声,它们并不精确等于这些值。大多数情况下,较长的信号会产生更好的频率逼近值。
f = Fs/L*(0:(L/2));plot(f,P1,"LineWidth",3) title("Single-Sided Amplitude Spectrum of X(t)")xlabel("f (Hz)")ylabel("|P1(f)|")
现在,采用原始的、未破坏信号的傅里叶变换并检索精确振幅在 0.8、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,"LineWidth",3) title("Single-Sided Amplitude Spectrum of S(t)")xlabel("f (Hz)")ylabel("|P1(f)|")
高斯脉冲
打开实时脚本
将高斯脉冲从时域转换为频域。
指定信号的参数,采样频率为 44.1 kHz,信号持续时间为 1 秒。创建一倍标准差为 0.1 ms 的高斯脉冲。
Fs = 44100; % Sampling frequencyT = 1/Fs; % Sampling periodt = -0.5:T:0.5; % Time vectorL = length(t); % Signal lengthX = 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/sqrt(n)).^2;plot(f,P(1:n/2+1)) title("Gaussian Pulse in Frequency Domain")xlabel("f (Hz)")ylabel("|P(f)|")
余弦波
打开实时脚本
比较时域和频域中的余弦波。
指定信号的参数,采样频率为 1 kHz,信号持续时间为 1 秒。
Fs = 1000; % Sampling frequencyT = 1/Fs; % Sampling periodL = 1000; % Length of signalt = (0:L-1)*T; % Time vector
创建一个矩阵,其中每一行代表一个频率经过缩放的余弦波。结果 X
为 3×1000 矩阵。第一行的波频为 50,第二行的波频为 150,第三行的波频为 300。
x1 = cos(2*pi*50*t); % First row wavex2 = cos(2*pi*150*t); % Second row wavex3 = cos(2*pi*300*t); % Third row waveX = [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 算法优化。
算法
FFT 函数(fft
、fft2
、fftn
、ifft
、ifft2
、ifftn
)基于一个称为 FFTW [1] [2] 的库。
参考
[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
也始终为复数。
有关详细信息,请参阅在 GPU 上运行 MATLAB 函数 (Parallel Computing Toolbox)。
分布式数组
使用 Parallel Computing Toolbox™ 在集群的组合内存中对大型数组进行分区。
用法说明和限制:
对于分布式数组,
fft
不使用并行 FFT 算法,而是在单个工作进程上收集向量以执行质数长度 FFT。对于质数长度较大的向量 FFT,可能导致内存不足错误。
有关详细信息,请参阅使用分布式数组运行 MATLAB 函数 (Parallel Computing Toolbox)。
版本历史记录
在 R2006a 之前推出
另请参阅
函数
- fft2 | fftn | fftw | fftshift | ifft | interpft
主题
- 傅里叶变换
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:
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)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 简体中文
- English
- 日本 (日本語)
- 한국 (한국어)
Contact your local office