torch 中的 stft、torchaudio 中的 Spectrogram、Melscale、MelSpectrogram 的使用

目录

  • torch 中的 stft、torchaudio 中的 Spectrogram、Melscale、MelSpectrogram 的使用
    • torch.stft
    • torchaudio.transforms.Spectrogram
    • torchaudio.transforms.MelScale
    • torchaudio.transforms.MelSpectrogram
    • 其他

torch.stft

output = torch.stft(input, n_fft, hop_length=None, win_length=None, window=None, center=True, pad_mode='reflect', normalized=False, onesided=None, return_complex=None)

简介:短时傅里叶变换

其中:

  • input(Tensor) 代表输入信号
  • n_fft(int) 代表快速傅里叶变换的序列长度
  • hop_length(int) 代表相邻两个滑动窗口帧之间的距离,也即是帧移
  • win_length(int) 代表窗口大小,默认等于 n_fft
  • window(Tensor) 代表窗口函数,默认是矩形窗口(全1)
  • center(bool) 代表是否对输入tensor在两端进行padding,使得第 ttt 帧是以 t×hop_lengtht \times hop\_lengtht×hop_length 为中心的,默认为 True,如果为 False,则第 ttt 帧以 t×hop_lengtht \times hop\_lengtht×hop_length 开始。
  • pad_mode(str) 代表padding的模式(当center为True才有效),默认为 reflect,即对边界的值进行reflect padding
  • normalized(bool) 代表是否对返回的STFT结果进行归一化,默认为 False
  • onesided(bool) 代表是否只返回一侧的STFT结果(当输入Tensor为实数时,输出为对称的),当输入Tensor和window都为实数时默认为 True,反之为 False
  • return_complex(bool) 代表返回实部和虚部的STFT结果还是返回复数

输出:

  • output(Tensor) 代表输出的STFT结果,维度为 ⋆×N×T\star \times N \times T⋆×N×T,⋆\star⋆ 代表 batch size,NNN 代表频率域的维度,TTT 代表时间域的维度。

计算表达式为:

X[ω,m]=∑k=0win_length-1 window [k]input [m×hop_length +k]exp⁡(−j2π⋅ωkwin_length )X[\omega, m] = \sum_{k=0}^{\text {win\_length-1 }} \text { window }[k] \text { input }[m \times \text { hop\_length }+k] \exp \left(-j \frac{2 \pi \cdot \omega k}{\text { win\_length }}\right) X[ω,m]=k=0∑win_length-1 ​ window [k] input [m× hop_length +k]exp(−j win_length 2π⋅ωk​)

其中,mmm 为滑动窗口的索引,ω\omegaω 代表频率,当 onesided=False 时,ω\omegaω 的取值范围为:[0,n_fft ][0, \text { n\_fft }][0, n_fft ],当 onesided=True 时,ω\omegaω 的取值范围为:[0,⌊n_fft2⌋][0, \lfloor \frac{\text { n\_fft} }2 \rfloor ][0,⌊2 n_fft​⌋]

注意:上面的表达式是加窗的短时傅里叶变换,但是在计算过程中,往往采用快速傅里叶变换来计算每个 mmm 对应的帧,因此 n_fft 和 win_length 可以不相等,计算时对加窗后的信号进行补零到 n_fft 的长度,所以需要满足: 0 < win_length <= n_fft

当参数center默认为True时,此时会对信号进行padding,第 000 帧以 x[0]x[0]x[0] 居中,且左右两边 padding 的长度为 ⌊n_fft2⌋\lfloor \frac{\text { n\_fft} }2 \rfloor⌊2 n_fft​⌋,输出的帧数为 T=⌊seq_lenhop_length⌋+1T = \lfloor \frac{\text{seq\_len}}{\text{hop\_length}}\rfloor + 1T=⌊hop_lengthseq_len​⌋+1 其中,seq_len 代表输入tensor的序列长度。

而当设置center参数为False时,第 000 帧以 x[0]x[0]x[0] 为开头,输出维度很奇怪,这里我也不太懂,欢迎讨论。

在频域维度,当 oneside=True 输出的 N=n_fft2+1N = \frac{\text { n\_fft} }2 + 1N=2 n_fft​+1 ,当 oneside=False 输出的 N=n_fftN = \text { n\_fft}N= n_fft

最后,由于此时并不知道输入信号的采样频率, 所以输出的频率没有具体值。或者说,输出矩阵在频率轴的值对应的频率为 ω=2πNk\omega = \frac{2\pi}{N}kω=N2π​k,其中,kkk 为频率轴的索引,且这里的 ω\omegaω 为DSP中常说的数字角频率,他和模拟频率 fff 的关系为:ω=2πffs\omega = \frac{2\pi f}{f_s}ω=fs​2πf​,其中 fsf_sfs​ 为输入信号的采样频率,那么 k=n_fft2k=\frac{\text{n\_fft}}{2}k=2n_fft​ 为频率轴信号的最高频率(假定 oneside=True ),对应的具体值为采样率的 1/21/21/2,而这也符合奈奎斯特采样定理:

为了不失真地恢复原始信号,采样率必须大于测量信号最大频率的两倍 fs>2×fNf_s > 2 \times f_Nfs​>2×fN​

torchaudio.transforms.Spectrogram

output = torchaudio.transforms.Spectrogram(n_fft: int = 400, win_length: Optional[int] = None, hop_length: Optional[int] = None, pad: int = 0, window_fn: Callable[[...], torch.Tensor] = <built-in method hann_window of type object>, power: Optional[float] = 2.0, normalized: bool = False, wkwargs: Optional[dict] = None, center: bool = True, pad_mode: str = 'reflect', onesided: bool = True, return_complex: Optional[bool] = None)

简介:求输入信号的语谱图

其中:

  • n_fft 为FFT的长度,默认为400,会生成 n_fft // 2 + 1 个 bins
  • win_length 为窗口的长度,默认为 n_fft
  • hop_length 为相邻两个滑动窗口帧之间的距离,即帧移,默认为 win_length // 2
  • pad 为对输入信号两边的补零长度,默认为 0
  • window_fn 为窗函数,默认为 torch.hann_window
  • power 为语谱图的幂指数,默认为 2.0,值必须大于 0,取 1 代表能量,取 2 代表功率。
  • normalized 为是否对语谱图进行归一化,默认为 False
  • wkwargs 为窗函数的参数,默认为 None
  • center 为是否对输入tensor在两端进行padding,使得第 ttt 帧是以 t×hop_lengtht \times hop\_lengtht×hop_length 为中心的,默认为 True,如果为 False,则第 ttt 帧以 t×hop_lengtht \times hop\_lengtht×hop_length 开始。
  • pad_mode 为补零方式,默认为 reflect
  • onesided 为是否只计算一侧的语谱图,默认为 True,即返回单侧的语谱图,如果为 False,则返回全部的语谱图。
  • return_complex 不再使用了

求解Spectrogram的本质其实还是stft,因此当 power=1时,输出的就是stft的能量谱。当 power=None时,就是直接输出了stft的结果,当power=2时,输出就是power=1的值的平方,更多细节见其他中的第二条。

torchaudio.transforms.MelScale

torchaudio.transforms.MelScale(n_mels: int = 128, sample_rate: int = 16000, f_min: float = 0.0, f_max: Optional[float] = None, n_stft: Optional[int] = None, norm: Optional[str] = None, mel_scale: str = 'htk')

简介:用来将stft的结果转换为mel域中的stft的结果。

其中:

  • n_mels(int) 为mel滤波器的个数,默认为128
  • sample_rate(int) 为音频采样率,默认为16000
  • f_min(float) 为音频的最小频率,默认为0.0
  • f_max(float) 为音频的最大频率,默认为采样率二分之一: sample_rate // 2
  • n_stft(int) 为stft的bin的个数,不给的话默认为None,从第一个输入计算得到。
  • norm(str) 如果为“slaney”,则将三角形mel权重除以mel bin的宽度(即进行面积归一化),默认为None
  • mel_scale(str) 采用的mel尺度: htk 或者 slaney,默认 htk

输入:

  • input(Tensor) Spectrogram 的输出,其维度为 ⋆×n_stft×T\star \times n\_stft \times T⋆×n_stft×T
    输出:
  • output(Tensor) 返回大小为 ⋆×n_mels×T\star \times n\_mels \times T⋆×n_mels×T 的Tensor

这一过程其实就是首先计算一个 ⋆×n_stft×n_mels\star \times n\_stft \times n\_mels⋆×n_stft×n_mels 的滤波器组矩阵,这个矩阵体现了信号频率 和 mel 域频率之间的转换关系,然后和输入的 Spectrogram 做矩阵乘法:

最后求得mel域的Spectrogram,即Mel谱。

注意:计算Spectrogram的时候不需要采样率,这是因为输出的频率是数字域角频率,而在计算MelScale的时候,需要具体的模拟频率和Mel域频率之间的转换关系,因此需要采样率来求出模拟频率的具体值,最后再转换到Mel域频率。

torchaudio.transforms.MelSpectrogram

torchaudio.transforms.MelSpectrogram(sample_rate: int = 16000, n_fft: int = 400, win_length: Optional[int] = None, hop_length: Optional[int] = None, f_min: float = 0.0, f_max: Optional[float] = None, pad: int = 0, n_mels: int = 128, window_fn: Callable[[...], torch.Tensor] = <built-in method hann_window of type object>, power: float = 2.0, normalized: bool = False, wkwargs: Optional[dict] = None, center: bool = True, pad_mode: str = 'reflect', onesided: bool = True, norm: Optional[str] = None, mel_scale: str = 'htk')

简介:求输入信号的Mel谱

其中:

  • sample_rate(int) 为输入波形的采样率
  • n_fft(int) 为FFT的长度,默认为400,会生成 n_fft // 2 + 1 个 bins
  • win_length 为窗口的长度,默认为 n_fft
  • hop_length 为相邻两个滑动窗口帧之间的距离,即帧移,默认为 win_length // 2
  • f_min(float) 为音频的最小频率,默认为0.0
  • f_max(float) 为音频的最大频率,默认为None
  • pad 为对输入信号两边的补零长度,默认为 0
  • n_mels(int) 为mel滤波器的个数,默认为128
  • window_fn 为窗函数,默认为 torch.hann_window
  • power(float) 为语谱图的幂指数,默认为 2.0,值必须大于 0,取 1 代表能量,取 2 代表功率。
  • normalized(bool) 为是否对stft的输出进行归一化,默认为 False
  • wkwargs 为窗函数的参数,默认为 None
  • center(bool) 为是否对输入tensor在两端进行padding,使得第 ttt 帧是以 t×hop_lengtht \times hop\_lengtht×hop_length 为中心的,默认为 True,如果为 False,则第 ttt 帧以 t×hop_lengtht \times hop\_lengtht×hop_length 开始。
  • pad_mode(str) 为补零方式,默认为 reflect
  • onesided(bool) 为是否只计算一侧的谱图,默认为 True,即返回单侧的语谱图,如果为 False,则返回全部的谱图。
  • norm(str) 如果为“slaney”,则将三角形mel权重除以mel bin的宽度(即进行面积归一化),默认为None
  • mel_scale(str) 采用的mel尺度: htk 或者 slaney,默认 htk

输入:

  • input(Tensor) 输入波形信号

输出:

  • output(Tensor) 输出Mel谱

可以看出,MelSpectrogram的参数完全就是Spectrogram的参数+MelScale的参数。实际上,这个函数的计算过程就是在里面先计算spectrogram再计算mel_scale:
测试结果也验证了这一点:

用两种方法计算的mel谱结果完全一样。

其他

  1. 关于信号的能量谱和功率谱(参考):
  • 能量谱:通常用来描述能量信号(能量有限的信号称为能量信号),表示的是信号在各个频点中的能量分布情况,如果对能量谱在频域进行积分,则可以求出信号的总能量。
  • 功率谱:通常用来描述功率信号(功率有限的信号称为功率信号),是指用密度的概念表示信号功率在各频率点的分布情况,对功率谱在频域上积分就可以得到信号的功率。
  • 维纳-辛钦定理:信号的功率谱和其自相关函数是一对傅里叶变换。在工程实际中,即便是功率信号,由于持续的时间有限,可以直接对信号进行傅里叶变换,然后对得到的幅度谱的模求平方,再除以持续时间来估计信号的功率谱。
  • 根据上面的解释,torchaudio.transforms.Spectrogram求功率谱时并没有除以持续时间,而是直接输出了平方值。
  1. 关于Spectrogram和stft:
  • torchaudio.transforms.Spectrogram网络中的 power=1时,输出的Spectrogram是能量图,在其他参数完全相同的情况下,其输出结果和 torch.stft函数中 return_complex=True的输出再求复数的模值之后的结果相同:
    图中,x1x_1x1​ 是stft函数求模之后的结果,x2x_2x2​ 是直接求Spectrogram得到的结果。
  • torchaudio.transforms.Spectrogram网络中的 power=None时,输出的Spectrogram是sftf的直接结果,在其他参数完全相同的情况下,其输出结果和 torch.stft函数中 return_complex=True完全相同:

图中,x1x_1x1​ 是stft函数之后的结果,x2x_2x2​ 是直接求Spectrogram得到的结果。

  • 事实上,Spectrogram内部就是调用了stft的计算:

然后根据 power取值计算最终的输出。

  1. reflect padding : 以矩阵的边界为对称轴,将内部的数据复制到外部:

torch 中的 stft、torchaudio 中的 Spectrogram、Melscale、MelSpectrogram 的使用相关推荐

  1. PyTorch:torchAudio中wav2vec2

    一.概述 torchAudio在0.10.0版本中已经兼容了hubert的代码(现在已经0.11.0了).然而,我连wav2vec2.0的代码都没跑过,官方文档也给出了一个wav2vec2.0代码的运 ...

  2. from d2l import torch as d2l这个语句中torch报错的解决方法

    最近在看<动手学深度学习>时书写上面的代码时,会有 from d2l import torch as d2l这个语句中torch报错,原因是没有导入这个d2l包,如何导入这个库呢 1.打开 ...

  3. self计算机语言,python中self在函数中如何使用

    python中self在函数中如何使用 发布时间:2020-12-14 09:12:49 来源:亿速云 阅读:108 作者:小新 这篇文章将为大家详细讲解有关python中self在函数中如何使用,小 ...

  4. html img调用js,html调用js变量 如何在html中输出js文件中的变量

    html页面代码中怎么调用js变量?html页面代码中怎么调用js变量,例如 在html代码中插入js代码: a=取浏览你把index1.js 中的onReady 去掉,把index1.js改成 fu ...

  5. jsp mysql 图片路径,请教JSP中怎么向MySql中存入和取出图片

    当前位置:我的异常网» Java Web开发 » 请教JSP中怎么向MySql中存入和取出图片 请教JSP中怎么向MySql中存入和取出图片 www.myexceptions.net  网友分享于:2 ...

  6. 如何从JavaScript中的给定数字中形成最小的数字

    by Prashant Yadav 通过Prashant Yadav 如何从JavaScript中的给定数字中形成最小的数字 (How to form the smallest possible nu ...

  7. python中读取文件过程中seek()函数的使用

    python中读取文件过程中seek()函数的使用 目录 概述: 语法: 参数: 返回值: 实例: 概述: seek() 方法用于移动文件读取指针到指定位置. 语法: seek() 方法语法如下: 文 ...

  8. mysql隐藏密码_MySQL在Linux系统中隐藏命令行中的密码的方法

    在命令行中输入命令并不是一个好主意,会造成安全问题.但是如果你决定去写一个应用,而这个应用需要在命令行中使用密码或者其他敏感信息.那么,你能通过以下方法禁止系统的其他用户轻易的看到这些敏感数据 呢?, ...

  9. springboot yml怎么建常量_【Java】SpringBoot 中从application.yml中获取自定义常量

    由于这里我想通过java连接linux,connection连接需要host.port.username.password及其他路径等等.不想每次修改的时候都去改源文件,所以想写在applicatio ...

  10. html js文本框文字列出,js实现文本框中输入文字页面中div层同步获取文本框内容的方法...

    这篇文章主要介绍了js实现文本框中输入文字页面中div层同步获取文本框内容的方法,实例分析了javascript操作dom元素的技巧,需要的朋友可以参考下 本文实例讲述了js实现文本框中输入文字页面中 ...

最新文章

  1. 做好信贷业务必须了解这八大问题!
  2. SSM三大框架整合Springfox(Swagger2)详细解决方案
  3. J.U.C系列(二)CyclicBarrier的使用
  4. linux进程被中断打断,linux – 当中断处理程序被另一个中断中断时,中断上下文如何“恢复”?...
  5. 项目经理有必要学python吗_项目经理到底要不要懂技术
  6. C#里如何遍历枚举所有的项
  7. EJB3.0学习笔记---定义客户端访问接口:
  8. Android的DatePicker和TimePicker-android学习之旅(三十八)
  9. Atlas Control Toolkit更新发布V1.0.60914.0
  10. matlab imhist与histeq函数
  11. 微信api中转站(用python搭建flask服务器)
  12. 苹果在新西兰的所得税都缴纳给了澳大利亚
  13. 2010爆牙笑话第一季!【转】
  14. [POJ 3311] Hie with the Pie
  15. 【Linux】MBR磁盘分区表只能有四个分区?
  16. 表白神器-摩斯密码1121311233321113212313323332113
  17. C51单片机实现串口通信
  18. 风能matlab仿真_风能产量预测—深度学习项目
  19. axure没有团队页签_使用Axure管理团队项目以及分享原型
  20. corrcoef函数的用法

热门文章

  1. phpstudy的安装教程
  2. cc2430的ram和rom的划分
  3. 【屏幕适配】像素密度 分辨率 dp px的关系
  4. stm32单片机按键消抖、长按、多击终极解决方案
  5. JS阻止form表单提交
  6. html以鼠标为中心放大网页,鼠标滚轮网页放大缩小
  7. 怎么看台式计算机是几位的,电脑多少位在哪里看_如何看电脑系统是多少位-win7之家...
  8. Chrome解决网页文字无法复制
  9. Excepted in :flat namespace
  10. 权重确定方法四:主成分分析法确定权重(PCA)