原理

  短时傅里叶变换(Short Time Fourier Transform, STFT) 是一个用于语音信号处理的通用工具.它定义了一个非常有用的时间和频率分布类, 其指定了任意信号随时间和频率变化的复数幅度. 实际上,计算短时傅里叶变换的过程是把一个较长的时间信号分成相同长度的更短的段, 在每个更短的段上计算傅里叶变换, 即傅里叶频谱.

短时傅里叶变换通常的数学定义如下:

其中,

DTFT (Decrete Time Fourier Transform) 为离散时间傅里叶变换.  其数学公式, 如下所示:

  其中,  x(n) 为在采样数 n 处的信号幅度. ω~ 的定义如下:

  实现时, 短时傅里叶变换被计算为一系列加窗数据帧的快速傅里叶变换 (Fast Fourier Transform, FFT),其中窗口随时间 “滑动” (slide) 或“跳跃” (hop) 。

Python 实现

  在程序中, frame_size 为将信号分为较短的帧的大小, 在语音处理中, 通常帧大小在 20ms 到 40ms 之间. 这里设置为 25ms, 即 frame_size = 0.025;

  frame_stride 为相邻帧的滑动尺寸或跳跃尺寸, 通常帧的滑动尺寸在 10ms 到 20ms 之间, 这里设置为 10ms, 即 frame_stride = 0.01. 此时, 相邻帧的交叠大小为 15ms;

  窗函数采用汉明窗函数 (Hamming Function) ;

  在每一帧, 进行 512 点快速傅里叶变换, 即 NFFT = 512. 具体程序如下:

# -*- coding: utf8 -*-
import numpy as np def calc_stft(signal, sample_rate=16000, frame_size=0.025, frame_stride=0.01, winfunc=np.hamming, NFFT=512): # Calculate the number of frames from the signal
frame_length = frame_size * sample_rate
frame_step = frame_stride * sample_rate
signal_length = len(signal)
frame_length = int(round(frame_length))
frame_step = int(round(frame_step))
num_frames = 1 + int(np.ceil(float(np.abs(signal_length - frame_length)) / frame_step))
# zero padding
pad_signal_length = num_frames * frame_step + frame_length
z = np.zeros((pad_signal_length - signal_length))
# Pad signal to make sure that all frames have equal number of samples
# without truncating any samples from the original signal
pad_signal = np.append(signal, z) # Slice the signal into frames from indices
indices = np.tile(np.arange(0, frame_length), (num_frames, 1)) + \
np.tile(np.arange(0, num_frames * frame_step, frame_step), (frame_length, 1)).T
frames = pad_signal[indices.astype(np.int32, copy=False)]
# Get windowed frames
frames *= winfunc(frame_length)
# Compute the one-dimensional n-point discrete Fourier Transform(DFT) of
# a real-valued array by means of an efficient algorithm called Fast Fourier Transform (FFT)
mag_frames = np.absolute(np.fft.rfft(frames, NFFT))
# Compute power spectrum
pow_frames = (1.0 / NFFT) * ((mag_frames) ** 2) return pow_frames if __name__ == '__main__':
import scipy.io.wavfile
import matplotlib.pyplot as plt # Read wav file
# "OSR_us_000_0010_8k.wav" is downloaded from http://www.voiptroubleshooter.com/open_speech/american.html
sample_rate, signal = scipy.io.wavfile.read("OSR_us_000_0010_8k.wav")
# Get speech data in the first 2 seconds
signal = signal[0:int(2. * sample_rate)] # Calculate the short time fourier transform
pow_spec = calc_stft(signal, sample_rate) plt.imshow(pow_spec)
plt.tight_layout()
plt.show()

参考资料

1. DISCRETE TIME FOURIER TRANSFORM (DTFT). https://www.dsprelated.com/freebooks/mdft/Discrete_Time_Fourier_Transform.html

2. THE SHORT-TIME FOURIER TRANSFORM. https://www.dsprelated.com/freebooks/sasp/Short_Time_Fourier_Transform.html

3. Short-time Fourier transform. https://en.wikipedia.org/wiki/Short-time_Fourier_transform

4. Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs) and What's In-Between. https://haythamfayek.com/2016/04/21/speech-processing-for-machine-learning.html

短时傅里叶变换(Short Time Fourier Transform)原理及 Python 实现的更多相关文章

  1. 从傅里叶级数(Fourier series)到离散傅里叶变换(Discrete Fourier transform)

    从傅里叶级数(Fourier series)到离散傅里叶变换(Discrete Fourier transform) 一. 傅里叶级数(FS) 首先从最直观的开始,我们有一个信号\(x(t)\)(满足 ...

  2. Python scipy 计算短时傅里叶变换(Short-time Fourier transforms)

    计算短时傅里叶变换(STFT) scipy.signal.stft(x,fs = 1.0,window ='hann',nperseg = 256,noverlap = None,nfft = Non ...

  3. matlab 时频分析(短时傅里叶变换、STFT)

    短时傅里叶变换,short-time fourier transformation,有时也叫加窗傅里叶变换,时间窗口使得信号只在某一小区间内有效,这就避免了传统的傅里叶变换在时频局部表达能力上的不足, ...

  4. 傅里叶变换 - Fourier Transform

    傅里叶级数 傅里叶在他的专著<热的解析理论>中提出,任何一个周期函数都可以表示为若干个正弦函数的和,即: \[f(t)=a_0+\sum_{n=1}^{\infty}(a_ncos(n\o ...

  5. 【OI向】快速傅里叶变换(Fast Fourier Transform)

    [OI向]快速傅里叶变换(Fast Fourier Transform) FFT的作用 ​ 在学习一项算法之前,我们总该关心这个算法究竟是为了干什么. ​ (以下应用只针对OI) ​ 一句话:求多项式 ...

  6. 数字图像处理实验(5):PROJECT 04-01 [Multiple Uses],Two-Dimensional Fast Fourier Transform 标签: 图像处理MATLAB数字图像处理

    实验要求: Objective: To further understand the well-known algorithm Fast Fourier Transform (FFT) and ver ...

  7. 「学习笔记」Fast Fourier Transform

    前言 快速傅里叶变换(\(\text{Fast Fourier Transform,FFT}\) )是一种能在\(O(n \log n)\)的时间内完成多项式乘法的算法,在\(OI\)中的应用很多,是 ...

  8. 【manim】3b1b的"Almost" Fourier Transform复刻

    最近在做Fourier Transform的内容,记录一下今天下午的成果. 本文代码全部自行编写,需要math and music项目完整工程可以在gayhub上获取.(现在还没弄完,就先不发了.) ...

  9. 浅谈范德蒙德(Vandermonde)方阵的逆矩阵的求法以及快速傅里叶变换(FFT)中IDFT的原理

    浅谈范德蒙德(Vandermonde)方阵的逆矩阵与拉格朗日(Lagrange)插值的关系以及快速傅里叶变换(FFT)中IDFT的原理 标签: 行列式 矩阵 线性代数 FFT 拉格朗日插值 只要稍微看 ...

随机推荐

  1. 友盟在部分手机上在进程被kill的情况下接收不到推送的问题

    app集成友盟推送后就能接收推送消息,即使在进程被kill的情况下也能接收.这个因为友盟有长连互保,用户设备中任何一个集成过友盟推送的app打开,即使他的app没打开也能启动push service, ...

  2. invalid request block size: 4542 (max 4096)...skip引起的Nginx 502 Bad Geteway

    今天有用户报告了一个issue: 当他访问我们的网站时出现了以下错误: 但是我访问同样的地址却没有这个问题,连续访问多次,查看uWSGI日志发现出现以下ERROR: 原来是请求头的大小超出了uWSGI ...

  3. 使用Koa2搭建web项目

    随着Node.js的日益火热,各种框架开始层出不穷的涌现出来,Node.js也开始逐渐的被应用到处理服务端请求的场景中.搭建Web项目的框架也随之开始出现——express.koa.koa2.egg等 ...

  4. Servlet多文件上传

    各位大侠可能会对263电子邮箱中的"上传附件"功能有印象,就是:在浏览 器中点击"浏览",弹出一个对话框,选中文件后,单击"确定",文件就被 ...

  5. 在Docker平台实现MySQL Replication(复制)

    MySQL Replication提供了数据库之间复制数据的功能,通过这个功能可以让一个数据库的数据更改自动同步到另外一个数据库.通常用这个功能来实现数据备份.数据容灾.数据冗余,进一步实现数据的读写 ...

  6. js oop中的三种继承方法

    JS OOP 中的三种继承方法: 很多读者关于js opp的继承比较模糊,本文总结了oop中的三种继承方法,以助于读者进行区分. <继承使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方 ...

  7. C# 进程优先级和线程优先级的方法

    C# 设置进程优先级的方法 this.process1= Process.GetCurrentProcess(); process1.PriorityClass = ProcessPriorityCl ...

  8. JS 重写alert,使之能输出多个参数

    windows._alert = windows.alert; windows.alert = function(){ _alert = (Array.prototype.slice(argument ...

  9. 【转】JUC下面线程池介绍

    介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new T ...

  10. 【转】类找不到总结java.lang.ClassNotFoundException

    (1)org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.microsoft.sqls ...