短时傅里叶变换(Short Time Fourier Transform)原理及 Python 实现
原理
短时傅里叶变换(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 实现的更多相关文章
- 从傅里叶级数(Fourier series)到离散傅里叶变换(Discrete Fourier transform)
从傅里叶级数(Fourier series)到离散傅里叶变换(Discrete Fourier transform) 一. 傅里叶级数(FS) 首先从最直观的开始,我们有一个信号\(x(t)\)(满足 ...
- Python scipy 计算短时傅里叶变换(Short-time Fourier transforms)
计算短时傅里叶变换(STFT) scipy.signal.stft(x,fs = 1.0,window ='hann',nperseg = 256,noverlap = None,nfft = Non ...
- matlab 时频分析(短时傅里叶变换、STFT)
短时傅里叶变换,short-time fourier transformation,有时也叫加窗傅里叶变换,时间窗口使得信号只在某一小区间内有效,这就避免了传统的傅里叶变换在时频局部表达能力上的不足, ...
- 傅里叶变换 - Fourier Transform
傅里叶级数 傅里叶在他的专著<热的解析理论>中提出,任何一个周期函数都可以表示为若干个正弦函数的和,即: \[f(t)=a_0+\sum_{n=1}^{\infty}(a_ncos(n\o ...
- 【OI向】快速傅里叶变换(Fast Fourier Transform)
[OI向]快速傅里叶变换(Fast Fourier Transform) FFT的作用 在学习一项算法之前,我们总该关心这个算法究竟是为了干什么. (以下应用只针对OI) 一句话:求多项式 ...
- 数字图像处理实验(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 ...
- 「学习笔记」Fast Fourier Transform
前言 快速傅里叶变换(\(\text{Fast Fourier Transform,FFT}\) )是一种能在\(O(n \log n)\)的时间内完成多项式乘法的算法,在\(OI\)中的应用很多,是 ...
- 【manim】3b1b的"Almost" Fourier Transform复刻
最近在做Fourier Transform的内容,记录一下今天下午的成果. 本文代码全部自行编写,需要math and music项目完整工程可以在gayhub上获取.(现在还没弄完,就先不发了.) ...
- 浅谈范德蒙德(Vandermonde)方阵的逆矩阵的求法以及快速傅里叶变换(FFT)中IDFT的原理
浅谈范德蒙德(Vandermonde)方阵的逆矩阵与拉格朗日(Lagrange)插值的关系以及快速傅里叶变换(FFT)中IDFT的原理 标签: 行列式 矩阵 线性代数 FFT 拉格朗日插值 只要稍微看 ...
随机推荐
- Flow类注释解读
参考: (1)https://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html (2)https://docs.oracle.com/java ...
- C/C++ -- Gui编程 -- Qt库的使用 -- HelloWorld
1.纯代码写对话框HelloWorld 创建空Qt工程,添加C++源文件main.cpp 需要设置编码以支持中文 -----源代码main.cpp----- #include <QApplica ...
- 使用DAO模式开发宠物管理系统---hellokitty
宠物有狗和企鹅. 狗的属性有:编号.名称.亲密值.健康值.品种.所属主人编号. 企鹅的属性有:编号.名称.亲密值.健康值.性别.所属主人编号. 该系统中主人可以领养宠物,主人的属性有:编号.用户名.密 ...
- 搭建jenkins
使用Jenkins配置Git+Maven的自动化构建 实现背景:Jenkins通过给定的代码地址URL,将代码拉取到其“宿主服务器”(就是Jenkins的安装位置),进行编译.打包和发布到容器中.在J ...
- 用java做操作系统内核:软盘读写
在前两节,我们将一段代码通过软盘加载到了系统内存中,并指示cpu执行加入到内存的代码,事实上,操作系统内核加载也是这么做的.只不过我们加载的代码,最大只能512 byte, 一个操作系统内核,少说也要 ...
- JS的可枚举性
在学习ES6的过程中,涉及到遍历方法时,提到过可枚举性,且多种遍历方法都与可枚举性相关.本章节,将总结这些遍历方法的可枚举性,并在必要的部分,给出对比实例. 一.设置属性的可枚举性 在上一文章 ...
- Qt5 编程基础
Qt 是一个C++ GUI应用框架,Qt 具有良好的可移植性支持大多数桌面和移动操作系统并常用于嵌入式开发. Qt的发行版分为商业版和开源版,提供了Qt Creator作为轻量级IDE. Hello ...
- 【转】类找不到总结java.lang.ClassNotFoundException
(1)org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.microsoft.sqls ...
- spring事务注解失效问题
问题描述: 由于工作需要,需要在spring中配置两个数据源,有一天突然发现@Transactional注解失效 环境框架: springmvc+spring+spring jdbcTemplate ...
- CentOS 7 隐藏任务栏和顶栏
我使用的是Gnome,对于使用惯了windows的我来说,这个界面确实有点丑,但是,也将就着用了,最近发现有一款软件(Cairo-Dock)可以美化桌面,于是就安装了,但是安装之后发现了一个问题:原来 ...