数字信号处理——时频分析(短时傅里叶变换)

短时傅里叶变换的概念

背景:
傅里叶变换的局限性:在做傅里叶变换的时候,使用的是(-∞,∞)的时间信息来计算单个频率的频谱,所以傅里叶变换是一种全局性的描述,不能反映信号局部区域的信息,故如果信号在某一段时间内发生错误,则进行傅里叶分析时就会出错。

短时傅里叶变换的思想:
把非平稳过程看成是一系列短时平稳信号的叠加,短时性可通过在时间上加窗实现。(即利用一个窗函数,从时间轴的最左端开始向右滑动,每一次取窗内的信号并利用窗进行加权后作fft,组成该时段的频谱,最后可以得到一系列时段的频谱)

短时傅里叶变换的局限:
在短时傅里叶变换过程中,窗的长度决定频谱图的时间分辨率和频率分辨率,窗长越长,截取的信号越长,信号越长,傅里叶变换后频率分辨率越高,时间分辨率越差;相反,窗长越短,截取的信号就越短,频率分辨率越差,时间分辨率越好,也就是说短时傅里叶变换中,时间分辨率和频率分辨率之间不能兼得,应该根据具体需求进行取舍。

小波变化的引出:
短时傅里叶变换的窗函数是固定的,但是对于高频信号应该取短窗,低频信号应该取长窗,故引入具有自适应性窗口的小波变换。

matlab实现时频分析

1.利用库实现
这里主要就是函数spectrogram()的用法

[S,F,T,P]=spectrogram(y,WINDOW,NOVERLAP,NFFT,Fs);
@param1 y:输入的信号 向量
@param2 WINDOW:窗口长度 该函数默认使用海明窗
@param3 NOVERLAP:各段之间重叠的采样点数 即两窗口相重叠的部分
@param4 NFFT:对窗口下的信号做FFT的点数
@param5:信号的采样率

@ret1 S:输入信号x的短时傅里叶变换。
		它的每一列包含一个短期局部时间的频率成分估计,时间沿列增加,频率沿行增加。
@ret2 F:为四舍五入的频率,其长度等于S的行数。
@ret3 T:频谱图计算的时刻点,值为窗的时刻中值。
@ret4 P:功率谱密度PSD(Power Spectral Density) 公式见下:

功率谱密度PSD计算公式,其中w(n)为窗函数,Fs为采样率
在这里插入图片描述

%%
clc;clear;
[y_vowel,Fs_vowel]=audioread('元音3.m4a');
[y_consonant,Fs_consonant]=audioread('辅音4.m4a');
WINDOW = 128;%设置窗长
NOVERLAP = 64;%设置覆盖长度
NFFT = 128;%设置fft的点数
subplot(221);
[S_vowel,FF_vowel,T_vowel,P_vowel]=spectrogram(y_vowel(:,1),WINDOW,NOVERLAP,NFFT,Fs_vowel);

spectrogram(y_vowel(:,1),WINDOW,NOVERLAP,NFFT,Fs_vowel,'yaxis');title('元音的时频分析');
%surf(T_vowel,FF_vowel,10*log10(abs(P_vowel)),'EdgeColor','none');
subplot(222);
[S_consonant,FF_consonant,T_consonant,P_consonant]=spectrogram(y_consonant(:,1),WINDOW,NOVERLAP,NFFT,Fs_consonant);

spectrogram(y_consonant(:,1),WINDOW,NOVERLAP,NFFT,Fs_consonant,'yaxis');title('辅音的时频分析');
% sound(y_vowel,Fs_vowel);
% sound(y_consonant,Fs_consonant);

subplot(223);
F_vowel=fft(y_vowel);
stem(0:Fs_vowel/length(F_vowel):Fs_vowel/2-Fs_vowel/length(F_vowel),abs(F_vowel(1:length(F_vowel)/2)));title('元音的频谱');

subplot(224);
F_consonant=fft(y_consonant);
stem(0:Fs_consonant/length(F_consonant):Fs_consonant/2-Fs_consonant/length(F_consonant),abs(F_consonant(1:length(F_consonant)/2)));title('辅音的频谱');

结果分析:
在这里插入图片描述
1.对于元音,由于声带振动可等效膜振动(弦振动?滚去研究研究生理声学。。。),所以频谱会存在高次谐波,即频谱不连续。
2.对于辅音,暂时只知道存在频谱没什么规律,很容易出高频。。。

2.手动实现时频分析
算法描述:
1.建立一个窗函数,带权重系数
2.每一次对窗内信号乘窗函数进行加权,然后作fft,得到该时段的频谱
3.窗函数右移(窗函数长度-重复部分长度)
4.直到时域信号剩下的时间不足以一个窗函数的长度时,补零作fft
注意:
1.这里使用imagesc()做出时频图,利用axis xy上下翻转图像
2.只取0:Fs/2的频段
3.作图像时使用功率谱密度,注意幅值的换算

%%
%短时傅里叶变换变换 
%clc;clear;
[y_vo,Fs]=audioread('元音.m4a');
window=128;
nover=64;
i=1;
j=1;
a=0.46;
n=0:window-1;
w= (1 -a) - a*cos(2*pi*n/(window-1));%使用海明窗
%w = n;  %直接使用矩形窗
while (i+window)<length(y_vo)      %短时傅里叶变换
    temp=y_vo(i:i+window-1);
    s(:,j)=fft(w.*temp');
    j=j+1;
    i=i+window-nover;
end
s(:,j)=fft(y_vo(i:end),window);         %对最后一部分数据进行补零的fft
s_standard=s(1:window/2+1,:);
[f_length,t_length]=size(s_standard);
t_axis=1:t_length;                         
t_axis=t_axis/length(t_axis)*(length(y_vo)/Fs); %时间坐标变换
f_axis=1:f_length;
f_axis=(f_axis/64)*Fs/2;                                  %频率轴坐标变换
%surf(t_axis,f_axis,abs(s_standard),'EdgeColor','none');xlabel('Time');ylabel('Frequency (Hz)');    
figure;
k=2/(Fs*sum([1:window].^2));    %算出系数,用于求功率谱密度PSD
imagesc(t_axis,f_axis,10*log10(abs(k*(s_standard).^2)+eps));colorbar;axis xy; %使图像上下翻转

结果分析:
在这里插入图片描述
左图为做出来的结果图,右图为利用spectrogram()得到的短时傅里叶变换序列S与自己实现的短时傅里叶变换s_standard的差,可以发现,误差基本仅存在于最后,可能是直接补零带来的误差。

发布了99 篇原创文章 · 获赞 29 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44586750/article/details/103219952