当前位置:网站首页>音频 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
边栏推荐
- 【PaddleDetection】ModuleNotFoundError: No module named ‘paddle‘
- Introduction to kubernetes resource object and common commands
- 继承
- 数字有为,易步到位 华为携“5极”明星产品加速布局商业市场
- database
- Research and arrangement of electronic map coordinate system
- Simple implementation of cool GUI window based on WPF
- JVM一:JVM入门以及Class文件认识
- Establishment of SSH Framework (Part I)
- 多线程与高并发五:等待队列及Executor和线程池详解(重点)
猜你喜欢
如何系统学习一门编程语言? | 黑马程序员
工业物联网将取代人工发展吗?
第二轮红队免费公开课来袭~明晚八点!
WebSocket(简单体验版)
導入Excel文件,解决跳過空白單元格不讀取,並且下標前移的問題,以及RETURN_BLANK_AS_NULL報紅
自用工具 猴子都会用的unity视频播放器
Lost connection repair: make "hide and seek" nowhere to hide
Why is the service implementation class always red
开口式霍尔电流传感器如何助力直流配电改造?
Tardigrade: Trino's solution to ETL scenarios
随机推荐
小程序输入框闪动?
Learning - useful resources
Object floating tool
Resource management, high availability and automation (medium)
多线程与高并发二:volatile和CAS详细介绍
Li Kou daily question - day 29 -575 Divide candy
【PaddleDetection】ModuleNotFoundError: No module named ‘paddle‘
解决跨域
数据库
可扩展数据库(上)
第九章 APP项目测试(3) 测试工具
Establishment of SSH Framework (Part I)
SSH框架的搭建(下)
如何修改SE38编辑器主题
Li Kou daily question - day 29 -1491 Average wage after removing minimum wage and maximum wage
解析STEAM教育框架下未来教师研究能力
可扩展存储系统(上)
用于 C# 的 SQL 基本语法总结
nn. Parameter and torch nn. Init series of functions to initialize model parameters
Self use tool unity video player that monkeys can use