Matlab_spectrogram_短时傅里叶分析_实现与讨论 [未完成]

在语音与音乐处理过程中,常用到短时傅里叶变换(Short Time Fourier Transformation, STFT)。在一些学习路径中,STFT也是学习小波之前的预备知识。本文简单实现了 Matlab 中 Spectrogram 函数,在没有小波知识支撑下,讨论了参数的选择,以及分辨率相关的问题。

参考博客:

  来源:    作者:
  来源:    作者:
  来源:    作者:

短时傅里叶变换简介



  自己写一下对STFT的认识,不一定对。

  短时傅里叶变换,其实还是傅里叶变换,只不过把一段长信号按信号长度(nsc)、重叠点数(nov)重新采样。原始信号的每一个数据点,都有一个电压值对应,即只有一个直流自由度。重新采样之后,数据点个数变少,每一个数据点由(nsc)个点组成,即得到了其他频率的自由度。但是这个点的频谱是有上下限的——上限受采样频率界定,下限受数据时长界定,和 FFT 一样。

  这么处理数据是有缘由的。语音与音乐信号中,信号频率常常变化,而且频率成分丰富,导致简单的傅里叶变换不能很好的描述信号。然而我们人耳处理声音的能力很强,可以对很短的一段声音进行精确的频率分析。所以在语音识别以及语音信号预处理过程中,STFT 是 FFT 的仿生改良版(个人理解)。当然,在其他声学相关方向中,STFT也是蛮有用的。没查过相关文献不敢乱说,模态分析、瞬态特性等应该能用上(个人猜测)。

上图是我用本文的例程实现的语音“XX大学”的 STFT 结果。语音是自己拿录音笔录的,时间域上没有做截断,但由于自己声线太低,频率域截到 2000 Hz。可以看到,我在开始之后等了一段时间才开始说话,后面有几段“嘎嘣脆”的噪声。还可以看到,我的元音发音还是很清晰的,但声线真心低。理论上能从这张图还原出原始信号,不在话下。

Spectrogram 函数函数实现



  简单编了一个 STFT 函数如下:

function [ S , W , T ] = mf_spectrogram...
    ( signal , nsc , nov , fs )
%MF_SPECTROGRAM Short-time Fourier transform realization
% Input
%       signal      - Signal vector
%       nsc         - Abb. of Number SeCtion
%       nov         - Abb. of Number OverLap
%       fs          - Abb. of Frequency of Sample
% Output
%       S           - A matrix that each colum is a FFT for time of nsc
%       W           - A vector labeling frequency
%       T           - A vector labeling time

  % Signal Preprocessing
    h = hamming(nsc, ‘periodic‘);   % Hamming weight function
    L = length(signal);             % Length of Signal
    nst = nsc-nov;                  % Number of STep per colum
    ncl = fix( (L-nsc)/nst ) + 1;   % Number of CoLum
    nff = 2^nextpow2(nsc);          % Number of Fast Fourier Transformation
    Ps = zeros(nsc,ncl);
    for n = 1:ncl                   % Ps means Processed Signal
        Ps(:,n) = signal( (n-1)*nst+1 : (n-1)*nst+nsc ).*h‘;
    end                             % Ps is a matrix

  % Short-time Fourier transform
    STFT0 = fft(Ps,nff);

  % Turn into DFT in dB
    STFT1 = abs(STFT0/nff);
    STFT2 = STFT1(1:nff/2+1,:);             % Symmetric results of FFT
    STFT2(2:end-1,:) = 2*STFT2(2:end-1,:);  % Add the value of the other half
    STFT3 = 20*log10(STFT2);                % Turn sound pressure into dB level

  % Axis Generating
    fax = fs*(0:(nff/2))/nff;                           % Frequency axis setting
    tax = ( .5*nsc : nst : nst*(ncl-1)+.5*nsc ) / fs;   % Time axis generating
    [ffax,ttax] = meshgrid(tax,fax);                    % Generating grid of figure

  % Output
    W = ffax;
    T = ttax;
    S = STFT3;
end

  为了节省代码量,我搞了一个绘图函数:

function [  ] = my_pcolor( f , t , s )
%MY_PCOLOR 绘图函数
% Input
%       f               - 频率轴矩阵
%       t               - 时间轴矩阵
%       s               - 幅度轴矩阵
    gca = pcolor(f,t,s);                      % 绘制伪彩色图
        set(gca, ‘LineStyle‘,‘none‘);         % 取消网格,避免一片黑
    handl = colorbar;                         % 彩图坐标尺
        set(handl, ‘FontName‘, ‘Times New Roman‘, ‘FontSize‘, 14)
        ylabel(handl, ‘Magnitude, dB‘)        % 坐标尺名称
end

  下面是实现的例程:

clc
clear
close all

% 基本参数
fa = [ 50 800 ];    % 扫描频率上下限
fs = 6400;          % 采样频率

% 分辨率相关设定参数
te = 1;             % [s] 扫频时间长度
fre = 8;            % [s] 频率分辨率
tre = 0.002;        % [Hz] 时间分辨率

% Chirp 信号生成
t = 0:1/fs:te;                  % [s] 时间序列
sc = chirp(t,fa(1),te,fa(2));   % 信号生成

% 分辨率相关输入参数
nsc = floor(fs/fre);
% nov = floor(nsc-(fs*tre));
nov = floor(nsc*0.9);
nff = max(256,2^nextpow2(nsc));

% 计算与绘制结果
subplot(1,3,1)                            % 绘制自编函数结果
    [S,W,T] = mf_spectrogram(sc,nsc,nov,fs);
    my_pcolor(W,T,S)
    caxis([-130.86,-13.667]);
    title(‘自编函数‘);
    xlabel(‘时间 second‘);
    ylabel(‘频率 Hz‘);
subplot(1,3,2)                            % 绘制 Matlab 函数结果
    s = spectrogram(sc,hamming(nsc),nov,nff,fs,‘yaxis‘);
        % Turn into DFT in dB
        s1 = abs(s/nff);
        s2 = s1(1:nff/2+1,:);             % Symmetric results of FFT
        s2(2:end-1,:) = 2*s2(2:end-1,:);  % Add the value of the other half
        s3 = 20*log10(s2);                % Turn sound pressure into dB level
    my_pcolor(W,T,s3 )
    caxis([-130.86,-13.667]);
    title(‘Matlab 自带函数‘);
    xlabel(‘时间 second‘);
    ylabel(‘频率 Hz‘);
subplot(1,3,3)                            % 两者误差
    my_pcolor(W,T,20*log10(abs(10.^(s3/20)-10.^(S/20))))
    caxis([-180,-13.667]);
    title(‘error‘);
    ylabel(‘频率 Hz‘);
    xlabel(‘时间 second‘);
suptitle(‘Spectrogram 实现与比较‘);

  跑的结果我就不贴了,Demo确定是没问题的。网上也有很多相关话题的,例程都比较简单,但我非常善于把问题复杂化:te(扫描长度)、fre(频率下限)、tre(时域分辨率)、nsc(单段数据长度)、nov(重叠数据点数)、nff(FFT点数) 等参数都是为了看设定什么样的参数能够使得 STFT 结果最优。我只是科普性地了解过小波,公式推导还没展开,所以在此只能“实验性”地讨论“尺度”相关的话题。

  观察频率上限受到采样频率限制,频率下限受到nsc限制。nsc越大,单段数据时间跨度越长,一旦频率变化率较快,结果就很粗(te = 1 ; fre = 2 ; nov = 99%)。另一方面,为了保持 FFT 频率分辨率,设置 nff 不低于256,这使得当nsc较小时,单段信号中,低频成分可能也就几个周期就结束了,造成了频域上的失真。一句话,单段信号过短,低频效果不好;单段信号过长,捕捉不到频率快速变化的信号。

FFT 周期数、点数、补零数对结果的影响



Matlab_spectrogram_短时傅里叶分析_实现与讨论 [未完成]

原文地址:https://www.cnblogs.com/adgk07/p/9314892.html

时间: 2024-10-16 22:18:04

Matlab_spectrogram_短时傅里叶分析_实现与讨论 [未完成]的相关文章

spectrogram函数做短时傅里叶分析

整理自:http://blog.sina.com.cn/s/blog_6163bdeb0102dwfw.html 今天偶人发现原来matlab自带了短时傅里叶变换的分析函数,老版本的matlab是specgram函数,新的改成了spectrogram函数,虽然一说到时频分析,都会说到小波分析,小波分析要比短时傅里叶要好云云,但在分析信号的瞬时频谱时,短时傅里叶还是有它的用武之地的.前一阵也看了一些有关小波分析的matlab实现,发现帮助中使用小波也多是除噪.压缩,都说小波是时频显微镜,它的用武之

Matlab_xcorr_互相关函数的讨论 [未完成]

假设两个平稳信号 $\bold{x}$ 和 $\bold{y}$ ,如果 $x\left(t+\tao\right)= y\left(t\right)$ ,则可通过互相关求 $\tao$ . 首先,通过实现 xcorr 函数介绍互相关计算流程: clc clear close % 实现 xcorr 函数 % 基本设置 T = 1; % [s] 总时间长度 fs = 5000; % [Hz] 采样频率 t = 0:1/fs:T; % [s] 时间坐标 N = length(t); % 信号个数 %

讨论一下文章的阅读量 (个人观点)

讨论一下文章的阅读量 (个人观点) 昨天我写了一篇文章,不对,应该是前天才对,文章的名字叫<分享一个SQLSERVER脚本> 想不到会有这么多的阅读量和推荐量:102个推荐  5000+阅读 我觉得这篇文章跟那个脚本是普通得不能再普通的了 这篇文章一开始是先上了最多推荐,在最多推荐阶段已经累计有40+个推荐,以至于当天一直停留在最多推荐的位置 通常一般来说,如果你的文章写得好,在短时间之内能够保持10+个推荐,那么一般都能上最多推荐,当然这个短时间没有一个确定的时间 又一般来说,你的文章会在“

【DWT笔记】傅里叶变换与小波变换

[DWT笔记]傅里叶变换与小波变换 一.前言 我们经常接触到的信号,正弦信号,余弦信号,甚至是复杂的心电图.脑电图.地震波信号都是时域上的信号,我们也成为原始信号,但是通常情况下,我们在原始信号中得到的信息是有限的,所以为了获得更多的信息,我们就需要对原始信号进行数学变换,得到变换域的信号,通常接触到的变换主要有傅里叶变换.拉普拉斯变换.Z变换.小波变换等等,今天主要讨论下傅里叶变换与小波变换. 二.平稳信号与非平稳信号 在介绍主体之前,先要说下平稳信号与非平稳信号的区别. 平稳信号是指分布参数

数据库基础之左连接

左外连接就是在等值连接的基础上加上主表中的未匹配数据. 今天下午处理一个SQL,通过left outer join(so as right left outer join)的表的关联方式. 看到这种语法,直觉上反映查询结果的条数应该是Where之后主表返回的记录数(下将Where描述前置略去),直到今天下午写了一个SQL语句,返回的记录数表总表的比总表的还要多.呐尼! 觉得有点不可接受,why?参考资料也没反应整明白是为什么,查找了半天资料,也没明白所以然. 于是拉旁边的哥们讨论一下,哥们看了一

阅读记录(2016年9月)

本文记录本人曾经阅读过的一些文章,其中主要包括在编程.学习过程中搜集的一些琐碎知识点等. 由于文章过多,此处只记录文章的地址,可点击查看原网页. 由于内容很多,放在一篇文章中显得太长,故每个月一篇. 2016-09-21 Linux Python OpenCV python - OpenCV - cannot find module cv2 - Stack Overflow 设置环境变量:export PYTHONPATH=/opt/opencv-2.4.10/lib/python2.7/sit

南京都昌科技电子病历模板库清单

2015年1月30号南京都昌科技电子病历模板库有1074个模板文件,清单如下,有意购买者请致电13382028281南京都昌科技市场部刘经理. 文档模板库\SG\南京都昌科技2_24小时内入出院记录.xml文档模板库\SG\南京都昌科技2_24小时内入院死亡记录.xml文档模板库\SG\南京都昌科技2_上级查房记录.xml文档模板库\SG\南京都昌科技2_会诊记录.xml文档模板库\SG\南京都昌科技2_入院记录.xml文档模板库\SG\南京都昌科技2_出院记录.xml文档模板库\SG\南京都昌

信号处理必读的文章(-)—傅里叶分析之掐死教程(完整版)_转载至知乎

傅里叶分析之掐死教程(完整版)更新于2014.06.06 http://zhuanlan.zhihu.com/p/19763358 作 者:韩 昊 知 乎:Heinrich 微 博:@花生油工人 知乎专栏:与时间无关的故事 谨以此文献给大连海事大学的吴楠老师,柳晓鸣老师,王新年老师以及张晶泊老师. 转载的同学请保留上面这句话,谢谢.如果还能保留文章来源就更感激不尽了. ——更新于2014.6.6,想直接看更新的同学可以直接跳到第四章———— 我保证这篇文章和你以前看过的所有文章都不同,这是12年

python作业之用户管理程序_未完成

admin|admin123.|28812341026|[email protected]|1root|admin123.|134456634887|[email protected]|1bob|admin123.|1301231576356|[email protected]|0Cevin|admin123.|45566778990|[email protected]|0 #Auther Bob#--*--conding:utf-8 --*--#1.普通用户 # 登陆,注册,修改密码,查看本用