在 scipy 中重现 sox 频谱图

mrg*_*oom 3 python scipy sox spectrogram

例如,我有一个带有语音的 wav 文件。

我可以使用 sox 创建漂亮的频谱图可视化:

wget https://google.github.io/tacotron/publications/tacotron2/demos/romance_gt.wav
sox romance_gt.wav -n spectrogram -o spectrogram.png
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我怎样才能在Python中重现这个频谱图?

这是使用scipy.signal.spectrogram的示例

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')
Run Code Online (Sandbox Code Playgroud)

但看起来有些参数不好或者有什么东西坏了: 在此输入图像描述

War*_*ser 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')
Run Code Online (Sandbox Code Playgroud)

我除Sxx以来Sxx.max()解释 dBFS 的“全面”方面。我调整了nperseg和 的noverlap参数,spectrogram使频率和时间轴上的分辨率都高于默认值。我曾经window='hann'匹配sox的默认行为。(您可以在http://sox.sourceforge.net/sox.html中找到 sox 频谱图的详细信息。)我还在中使用vmin=-120和来匹配 sox 频谱图使用的默认范围。vmax=0pcolormesh

情节如下:

频谱图

“地狱”色彩图并不像红袜图中使用的色彩图那么强烈。有关替代颜色图,请参阅“在 Matplotlib 中选择颜色图”教程。