当前位置:网站首页>音频 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
边栏推荐
猜你喜欢
随机推荐
Summary of SQL basic syntax for C #
多线程与高并发五:等待队列及Executor和线程池详解(重点)
matlab习题 —— 数据的基本处理
Circular sliding auto adsorption UI tool that monkeys can use
Resource management, high availability and automation (medium)
Etcd database source code analysis -- network layer server rafthandler between clusters
Database migration
从遇见大咖到成为大咖,昇腾AI开发者创享日给开发者带来无限可能
图片的懒加载和预加载
Summary of the use of composition API in the project
Huawei equipment WLAN basic service configuration command
Automatic backup of MySQL database
解析STEAM教育框架下未来教师研究能力
Import an excel file, solve the problem of skipping blank cells without reading and moving the subscript forward, and return_ BLANK_ AS_ Null red
多线程与高并发六:线程池源码解析
database
TypeError: 'module&#03…
"9 No" principle and "5 measurement dimensions" of extensible system
MySQL configuration of database Series F5 load balancing
Floating point and complex type of go data type (4)









