参照网址短时傅里叶变换
参照上述网址,尝试编写短时傅里叶变换得程序,为了加深对短时傅里叶计算过程的理解,也为后续的其他算法先打下基础。编程能力较差,虽然仿照,但可能依然由很多考虑不到。
function [s,f,t] = sftf(x,window,overlap,nfft,fs) % x: 输入的一维数组 % window: 窗的类型,当输入为一整数时,默认使用hanning窗 % overlap:重叠的长度 % nfft:做一次傅里叶变换得长度 % fs:采样频率 % 默认参数设置 if nargin < 2 || isempty(window); window = hanning(256); end if length(window) == 1; window = hanning(window); end if nargin < 3 || isempty(overlap); overlap = floor(length(window)/2); end if nargin < 4 || isempty(nfft); nfft = length(window); end if nargin < 5 || isempty(fs); fs = 2; end if length(window) > nfft; nfft = length(window); end n = length(window); step = n - overlap; %每次移动的步长 step_nums = ceil(abs(length(x)-overlap)/abs(step)); %需要移动多少步 % 需要将x补全,最后不足以领补全 [x_row, x_col] = size(x); if x_row ==1; x = x'; end % x变换为一列 if x_col ~= 1 && x_row ~= 1; error('输入的x不是一维数组'); end x_len = step * (step_nums-1) + n; mm = x_len-length(x); x_bu = zeros(mm, 1); x = [x; x_bu]; % 将x进行拆分 S = zeros(n, step_nums); t = 1:step:x_len-n+1; for i = 1:length(t) S(:,i) = x(t(i):t(i)+n-1).*window; end % 进行快速傅里叶变换 SFTF = fft(S,nfft); if rem(n,2)==1; x_fre = (n+1)/2; end if rem(n,2)==0; x_fre = n/2+1; end SFTF = abs(SFTF/n); s = SFTF(1:x_fre,:); s(2:end-1,:) = 2*s(2:end-1,:); f = (0:x_fre-1)*fs/n; t = t/fs; % 画图部分 % figure % surf(t,f,10*log10(abs(s)),'EdgeColor','none'); % axis xy; % axis tight; % colormap(jet); % view(0,90); % xlabel('Time'); end
使用数据进行测试结果如下
clc Fs = 1000; N = 2000; t = 0:1/Fs:(N-1)/Fs; y = 1.5*sin(2*pi*80*t)+1.5*sin(2*pi*160*t)+1.5*sin(2*pi*240*t)+2*sin(2*pi*320*t)+2*sin(2*pi*120*t); [s,f,t] = sftf(y, 300,100,300,Fs); figure surf(t,f,10*log10(abs(s)),'EdgeColor','none'); axis xy; axis tight; colormap(jet); view(0,90); xlabel('Time'); ylabel('Frequency (Hz)');