Воспроизвести спектрограмму Сокс в Scipy - PullRequest
1 голос
/ 05 июня 2019

Например, у меня есть WAV-файл с речью.

Я могу создать красивую визуализацию спектрограммы с помощью sox:

wget https://google.github.io/tacotron/publications/tacotron2/demos/romance_gt.wav
sox romance_gt.wav -n spectrogram -o spectrogram.png

enter image description here

Как я могу воспроизвести эту спектрограмму на питоне?

Вот пример использования 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')

Но похоже, что некоторые параметры плохие или что-то не работает: enter image description here

1 Ответ

1 голос
/ 05 июня 2019

Обратите внимание на масштаб цветной полосы на графике, сгенерированном sox.Единицы измерения: дБФС : децибелы относительно полной шкалы.Чтобы воспроизвести график с помощью SciPy и Matplotlib, вам нужно масштабировать значения таким образом, чтобы максимальное значение составляло 1, а затем взять логарифм значений для преобразования в дБ.

Вот измененная версия вашего сценарияэто включает в себя ряд настроек для аргументов 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.Я настроил аргументы nperseg и noverlap для spectrogram, чтобы получить разрешение, превышающее значения по умолчанию по оси частот и времени.Я использовал window='hann', чтобы соответствовать поведению sox по умолчанию.(Вы можете найти детали для спектрограммы sox в http://sox.sourceforge.net/sox.html.) Я также использовал vmin=-120 и vmax=0 в pcolormesh, чтобы соответствовать диапазону по умолчанию, используемому спектрограммой sox.

Вотplot:

spectogram

Цветовая карта "Inferno" не такая интенсивная, как у используемой на графике sox. См. учебное пособие по "Выбор цветовых карт в Matplotlib " для альтернативных цветовых карт.

...