在Scipy中复现Sox频谱图

3
例如,我有一段包含语音的wav文件。
我可以使用sox创建漂亮的频谱可视化:
wget https://google.github.io/tacotron/publications/tacotron2/demos/romance_gt.wav
sox romance_gt.wav -n spectrogram -o spectrogram.png

如何在Python中重现这个频谱图?

以下是使用scipy.signal.spectrogram的示例:

enter image description here

input_file = 'temp/romance_gt.wav'
fs, x = wavfile.read(input_file)
print('fs', fs)
print('x.shape', x.shape)

f, t, Sxx = signal.spectrogram(x, fs)
print('f.shape', f.shape)
print('t.shape', t.shape)
print('Sxx.shape', Sxx.shape)
plt.pcolormesh(t, f, Sxx)
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.savefig('spectrogram_scipy.png')

但看起来有些参数不好或某些东西出了问题: enter image description here
1个回答

5
请注意sox生成的图表中色条的刻度。单位是dBFS: 相对于满刻度的分贝数。要使用SciPy和Matplotlib重现此图,您需要缩放值,使最大值为1,然后对值取对数以转换为dB。
以下是修改版本的脚本,其中包括各种对spectrogram和pcolormesh参数的微调,以创建类似于sox输出的图表。
import numpy as np
from scipy.io import wavfile
from scipy import signal
import matplotlib.pyplot as plt

input_file = 'romance_gt.wav'
fs, x = wavfile.read(input_file)
print('fs', fs)
print('x.shape', x.shape)

nperseg = 1025
noverlap = nperseg - 1
f, t, Sxx = signal.spectrogram(x, fs,
                               nperseg=nperseg,
                               noverlap=noverlap,
                               window='hann')
print('f.shape', f.shape)
print('t.shape', t.shape)
print('Sxx.shape', Sxx.shape)
plt.pcolormesh(1000*t, f/1000, 10*np.log10(Sxx/Sxx.max()),
               vmin=-120, vmax=0, cmap='inferno')
plt.ylabel('Frequency [kHz]')
plt.xlabel('Time [ms]')
plt.colorbar()
plt.savefig('spectrogram_scipy.png')

我将Sxx除以Sxx.max(),以考虑dBFS的“全尺度”方面。我调整了spectrogramnpersegnoverlap参数,以在频率和时间轴上提供比默认值更高的分辨率。我使用window='hann'来匹配sox的默认行为。(你可以在http://sox.sourceforge.net/sox.html找到sox spectrogram的详细信息。) 我还在pcolormesh中使用vmin=-120vmax=0,以匹配sox spectrogram使用的默认范围。
这是图表:

spectogram

“地狱”色图与sox图中使用的色图相比不那么强烈。请参见"Matplotlib中选择配色方案"教程以获取备选配色方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接