傅里叶变换

参照网址短时傅里叶变换

参照上述网址,尝试编写短时傅里叶变换得程序,为了加深对短时傅里叶计算过程的理解,也为后续的其他算法先打下基础。编程能力较差,虽然仿照,但可能依然由很多考虑不到。

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)');

短时傅里叶变换图