当前位置:网站首页>音频 scipy 中 spectrogram 的运作机制
音频 scipy 中 spectrogram 的运作机制
2022-06-28 03:06:00 【mingqian_chu】
本文介绍的scipy 版本信息如下
Name: scipy
Version: 1.4.1
Summary: SciPy: Scientific Library for Python
Home-page: https://www.scipy.org
Author:
Author-email:
License: BSD
anaconda3/envs/torch1.7.1/lib/python3.7/site-packages
Requires: numpy
Required-by: scikit-learn, resampy, librosa
如图,给出了spectrogram 中核心调用函数, 除此之外,spectrogram 函数也调用了其他函数;

1. 输入输出参数
def spectrogram(x, fs=1.0, window=('tukey', .25), nperseg=None, noverlap=None,
nfft=None, detrend='constant', return_onesided=True,
scaling='density', axis=-1, mode='psd'):
...
pass
return freqs, time, Sxx
1.1 输入参数
data: 音频数据,
fs: 采样率
mode: 复数模式
**kwargs: {
nperseg: 1000, noverlap: 500, nfft: 5000 }
nperseg: number of per segment;
代表每一段(帧)的点数长度, 默认值 None, 如果给出nperseg, 则使用给出值;
如果 window 是 字符或者元组, 则设置成256,
如果 window 是 类似数组, 则设置成 window 长度的大小;
noverlap: 相邻两帧之间的重叠度;
nfft; 对每一帧进行 FFT变换的点数;
1.2 输出参数
Returns
-------
freqs : ndarray
Array of sample frequencies.
t : ndarray
Array of times corresponding to each data segment
result : ndarray
Array of output data, contents dependent on *mode* kwarg.
freq: 频域信息 ; 样本的频率
t: 时域信息; 多帧的时间信息
spec: 时频谱, 基于 mode 选择输出;
1.3 输入,输出计算
当输入参数:
data= 10001 个数值; fs = 100; mode = "complex";
**kwargs: {
nperseg: 1000, noverlap: 500, nfft: 5000 }
输出参数如下:
freq = 2501 个数值, 代表频率;
t = 19 个数值, 代表19 帧;
spect = (2501, 19) 输出的是一个复数矩阵, 由于mode = "complex"
2. spectrogram() 函数中的运作机制
2.1 选择模式
根据 modelist = [‘psd’, ‘complex’, ‘magnitude’, ‘angle’, ‘phase’]
选择对应的模式
2.2 调用 _triage_segments()
window, nperseg = _triage_segments(window, nperseg, input_length=x.shape[axis])
输入: window, nperseg, input_length()
返回参数: win, nperseg()
设置 window, nperseg参数, 用于 spectrogram 和 _spectral_helper()
参数解释:
window: string, tuple, or ndarray 可选的有三种类型;
如果window 窗口是通过 string ,or tuple 指定了, 并且 nperseg 没有指定,
则nperseg 设置成256,并且返回指定窗口的长度;如果window 是个 arrary_like()类似数组的, 并且nperseg 没有指定,
则nperseg 设置成窗口长度的大小;错误情况, 如果用户同时提供了类似数组的窗口, 又提供 nperseg的数值, 但是nperseg != 数组窗口的长度;
则会报错;
当window 是string 或者 tuple 类型时:
比如, window = (“tukey”, 0.25), nperseg = 1000;
执行以下流程
判断, nperseg 是否大于 input_length,
if nperseg > input_length , 则发出警告, 说明设定一帧的长度大于输入的总长度,
重新给nperseg 赋值, 赋值为 input_length;然后调用
get_window(window, nperseg)函数,获取 win 长度;
返回 三个参数,- 一个段(帧)中的样本点 (长度为nperseg),
- 窗口的类型;
- 是否采样fftbins,
最终 triage_segments() 返回的是,
- window() 一帧的样本点数, 这里1000个数;
- nperseg() 一帧样本的长度, 这里是指一个 整型数 ,数值为1000;
2.3 设置 noverlap
if noverlap is None:
noverlap = nperseg // 8
2.4 核心调用 _spectral_helper()
根据模式选择, mode == stft:
当模式是STFT 或者 complex 时, 两者等价;
freqs, time, Sxx = _spectral_helper(x, x, fs, window, nperseg,
noverlap, nfft, detrend,
return_onesided, scaling, axis,
mode='stft')
输出结果 freqs,time 和 Sxx,下面结合具体实现流程分析:
判断模式是 psd, stft
boundary_func : 是否对输入信号在两边进行边界延拓,
延拓的效果是在数据X的基础上, 向两侧分别延长 (nperseg//2)的长度,
延拓的方式有 (const_ext, even_ext, odd_ext, zero_ext);判断x, y 两个数据类型相等
使得输出类型为 np.complex64 复数;
调用 win, nperseg = _triage_segments(window, nperseg, input_length= x.shape[-1] )
此时win = 之前的window ,为相同的一千个数;
nperseg 仍代表 一个整形数 1000 ;判断 nfft 的点数必须 >= nperseg, 一个段(帧)中的点数;
nstep = nperseg - noverlap
根据scaling 是
density还是spectrum, 求出对应的scale,
这里采用density求出的 scale 为0.00344;freqs = sp_fft.rfftfreq(nfft, 1/fs)该函数的作用是取 nfft 中的, 单边fft 取实数部分, 所以 rfft 求出来的个数,是nfft 中的一半;
freqs = 2501 ( nfft/2); 执行结束后, freqs= ( 2501,) 是包含 2501 个数的数组;
_fft_helper()
主要实现 FFT 变换的计算, 在这一步骤中;
对每一个 nperseg 窗口序列的长度, 进行nfft 长度的fft 变换;
10.1. 求出 step = nperseg - noverlap = 500
10.2. 求出 shape = (19, 1000) tuple;
10.3. 求出 strides = (4000, 8)
10.4. result = fun1(x, shape, strides), ndarray(19, 1000)
detrend(result), 对每一帧数据进行去 趋势效应;
10.5. result = win * result;
result = (19, 1000)
10.6. result = result. real , 取出 result 中的实部, 本来就是实数;
10.7. 令 func = sp_fft. rfft;
10.8. result = func(result, n= nfft),
result = (19, 1000) , nfft = 5000;
result = (19, 2501) 是一个复数矩阵, 每一个数都是复数;
result *= scale 进行尺度缩放;
time = {ndarray: 19}
result = 维度置换, resutl: (19, 2501) --> (2501, 19)
2.5 小结
scipy中 spectrogram 函数中的核心实现,通过 _spectral_helper() 函数;
而 _spectral_helper() 中的核心功能是通过 _fft_helper() 实现;
最终 spectrogram 函数返回的参数, 都是通过_spectral_helper() 函数获得的,spectrogram 返回的是三项参数:
freqs: 2501 个数
time: 19 段帧,
result: (2501, 19) 一个复数矩阵, 代表了时频谱图;
3. scipy 中的 spectral.py 文件介绍
该文件中, 主要实现了 14 个功能函数,
其中 10 个核心函数:
stft, istft, csd, welch, coherence, periodogram,
spectrogram, check_COLA, check_NOLA, lombscargle
4 个辅助函数;
_triage_segments()
_spectral_helper()
_fft_helper()
_median_bias()
其余的为其他模块中的函数调用;
3.1 调用关系

3.2 运作机制
具体的运作机理, 请阅读这里参考spectral.py
边栏推荐
- Automatic backup of MySQL database
- database
- 如何给Eclips自动添加作者,时间等…
- 数字有为,易步到位 华为携“5极”明星产品加速布局商业市场
- STM32外设SDIO和SD卡的配置
- 文档问题
- Custom controls under WPF and adaption of controls in Grid
- Summary of SQL basic syntax for C #
- 自用工具 猴子都会用的unity视频播放器
- 17 `bs object Node name h3 Parent ` parents get parent node ancestor node
猜你喜欢

A pit filling trip based on LNMP to build a personal website

云应用、服务的“5层”架构

【毕业季】研究生の毕业总结

工业物联网将取代人工发展吗?

Summary of SQL basic syntax for C #

如何系统学习一门编程语言? | 黑马程序员

How does the open-ended Hall current sensor help the transformation of DC power distribution?

__ getitem__ And__ setitem__

Etcd database source code analysis -- network layer server rafthandler between clusters

Analysis of slow logs in MySQL and tidb of database Series
随机推荐
密码加密md5和加盐处理
database
How to automatically add author, time, etc. to eclipse
如何给Eclips自动添加作者,时间等…
Establishment of SSH Framework (Part I)
kubernetes资源对象介绍及常用命令
调试利器 go-spew
Lost connection repair: make "hide and seek" nowhere to hide
自用工具 猴子都会用的unity视频播放器
STM32 peripheral SDIO and SD card configuration
数据库系列之MySQL配置F5负载均衡
No  result  defined& nbsp…
MySQL错误
Li Kou daily question - day 29 -575 Divide candy
力扣每日一题-第29天-523.在区间范围统计奇数数目
Documentation issues
A pit filling trip based on LNMP to build a personal website
matlab习题 —— 数据的基本处理
__ getitem__ And__ setitem__
Research and arrangement of electronic map coordinate system