个人实现的版本(torch-stft)
在github上有一个大佬实现了基于pytorch, numpy和librosa的stft库(torch-stft)。我通过他的源码观察发现其实他在处理处理音频还是用的numpy格式的数据,这样的话就不是很方便的去全程使用GPU加速了。而且这个库是没有逆短时傅里叶变换的。同时,这个库在最后也提到了这样的一个问题,因为该方法实现的时候使用了卷积核反卷积的操作,就可能会导致输出的结果长度有所变化。
针对于这个github开源的库,我的个人意见是如果是初学者希望学习短时傅里叶变换的,可以仔细去查看改源码,写的非常的清晰。如果是偏工程想要快速实现的,不在乎过程是怎么样的就不是很推荐了。我个人推荐工程使用pytorch自带的stft和istft。 是torch-stft库的链接
torch-stftgithub.comPytorch官方实现的stft和istft
我为什么要写一篇这样的文章呢?首先,肯定是我自己怕我自己忘记怎么去做了。其次是,我在Google上搜了半天也没有人去做这个教程的工作。因此,我作为接盘侠就写一写了。如果有错误欢迎指正我,掐死我。
吐槽一点stft和istft竟然不是一个类的。stft属于torch类,调用的命令为torch.stft();而istft则是torchaudio实现的方法,调用的命令为torchaudio.functional.istft()。这个不要搞混淆就好了。
首先,介绍一下stft。下面是官方对于stft函数定义的参数。
torch.stft(input, n_fft, hop_length=None, win_length=None,
window=None, center=True, pad_mode='reflect', normalized=False, onesided=True)
- input:是你通过librosa或者torchaudio或者其他的音频读取库读取的一维序列或者多维的batch序列。
- n_fft:计算FFT的点数
- hop_length:窗的移动距离
- win_length:窗的大小
- window:这里比较重要,就是pytorch实现的和librosa的区别是librosa该参数是窗的名字,例如hann等,而这里需要的是窗的函数类型是Tensor的。
- center:是否在两侧都填充
- pad_mode:这个参数与
torch.nn.functional.pad()
的mode参数一致。 - normalized:是否返回归一化的STFT结果,这个不是很重要,因为一般在读取的时候已经归一化了。
- onesided:是否返回一半结果以避免冗余
接下来是torchaudio实现的istft方法。
torchaudio.functional.istft(stft_matrix, n_fft, hop_length=None, win_length=None,
window=None, center=True, pad_mode='reflect',
normalized=False, onesided=True, length=None)
- stft_matrix:是stft的输出
- n_fft,hop_length,win_length,window,center,pad_mode,normalized,onesided这些参数与stft操作保持一致,具体参数的含义与stft的也一致,我这里就不再过多解释。
- length:信号修整量(即原始信号长度),这个就是防止输出长度不一致的问题,暖暖的很贴心。
例子:
>>> source, sr = torchaudio.load('./result/mix.wav')
>>> source.shape
>>> torch.Size([1, 32768])
>>> stft = torch.stft(source, 512, 128, 512, torch.hann_window(512))
>>> stft.shape
>>> torch.Size([1, 257, 257, 2]) # 这里为什么有一个1,这个1其实是batch size,
所以这个stft实现支持batch。其次这个二是代表实数和虚数
>>> stft[0][0][0]
>>> tensor([0.0684, 0.0000])
>>> #逆傅里叶变换
>>> istft = torchaudio.functional.istft(stft, 512, 128, 512, torch.hann_window(512))
>>> istft.shape
>>> torch.Size([1, 32768])