Улучшение разрешения спектрограммы в Python?

21

Я использую specgram()функцию matplotlibдля генерации спектрограмм файлов речевых волн в Python, но результат всегда значительно хуже, чем то, что может генерировать мое обычное программное обеспечение для транскрипции, Praat. Например, следующий вызов:

specgram(
    fromstring(spf.readframes(-1), 'Int16'),
    Fs=framerate,
    cmap=cm.gray_r,
)

Создает это:

введите описание изображения здесь

Пока Praat работает над тем же аудиосэмплом со следующими настройками:

  • Диапазон просмотра: 0-8000 Гц
  • Длина окна: 0,005 с
  • Динамический диапазон: 70 дБ
  • Шаг по времени: 1000
  • Частота шагов: 250
  • Форма окна: гауссов

Создает это:

введите описание изображения здесь

Что я делаю не так? Я попытался поиграться со всеми specgram()параметрами, но, кажется, ничто не улучшило разрешение. У меня практически нет опыта работы с БПФ.

Алек Шторм
источник
Не могли бы вы привести пример конфигураций параметров matplotlib.specgram, которые вы пробовали? Вы приводите очень конкретный пример параметров для Praat, но не показывает ту же конфигурацию для matplotlib.specgram?
Кристофер Фелтон

Ответы:

11

Вот параметры matplotlib.specgram

matplotlib.mlab.specgram(x, 
                         NFFT=256, 
                         Fs=2, 
                         detrend=<function detrend_none at 0x1dd6410>, 
                         window=<function window_hanning at 0x1e0b1b8>, 
                         noverlap=128, 
                         pad_to=None, 
                         sides='default', 
                         scale_by_freq=None)

Параметры, приведенные в описании вопроса, необходимо преобразовать в сопоставимые параметры mpl.specgram. Ниже приведен пример сопоставления:

View range: 0-8000Hz            Fs=16000
Window length: 0.005s           NFFT = int(Fs*0.005) = 80
                                noverlap = int(Fs*0.0025) = 40
Dynamic range: 70dB             n/a
Time steps: 1000                n/a
Frequency steps: 250            
Window shape: Gaussian          default window is hanning change to gaussian

Если вы используете 8 мс, вы получите мощность 2 БПФ (128). Ниже приведено описание настроек Praat с их веб-сайта.

Диапазон просмотра (Гц) : диапазон отображаемых частот. Стандарт составляет 0 Гц внизу и 5000 Гц вверху. Если эта максимальная частота выше частоты Найквиста Звука (которая составляет половину его частоты дискретизации), некоторые значения в спектрограмме будут равны нулю, а более высокие частоты будут отображаться белым цветом. Это можно увидеть, если записать звук с частотой 44100 Гц и установить диапазон просмотра от 0 до 25000 Гц.

Длина окна : продолжительность окна анализа. Если это 0,005 секунды (стандарт), Praat использует для каждого кадра ту часть звука, которая находится между 0,0025 секундами до и 0,0025 секундами после центра этого кадра (для гауссовых окон Praat фактически использует немного больше). Длина окна определяет ширину полосы спектрального анализа, то есть ширину горизонтальной линии на спектрограмме чистой синусоидальной волны (см. Ниже). Для окна Гаусса полоса пропускания -3 дБ составляет 2 * sqrt (6 * ln (2)) / (π * Длина окна) или 1.2982804 / Длина окна. Чтобы получить broad-band' spectrogram (bandwidth 260 Hz), keep the standard window length of 5 ms; to get aузкополосную спектрограмму (ширина полосы 43 Гц), установите ее на 30 мс (0,03 секунды). Другие формы окна дают немного другие значения.

Динамический диапазон (дБ) : Все значения, превышающие динамический диапазон дБ ниже максимума (возможно, после динамического сжатия, см. Дополнительные параметры спектрограммы ...), будут отображаться белым цветом. Значения между ними имеют соответствующие оттенки серого. Таким образом, если самый высокий пик в спектрограмме имеет высоту 30 дБ / Гц, а динамический диапазон составляет 50 дБ (что является стандартным значением), то значения ниже -20 дБ / Гц будут отображаться белым цветом, а значения между -20 дБ / Гц и 30 дБ / Гц будут отображаться в различных оттенках серого.

Ссылка на настройки Praat

Вопрос ОП может касаться разницы в контрасте между программой Praat и программой mpl (matplotlib). Praat имеет настройку динамического диапазона, которая влияет на контраст. Функция mpl не имеет аналогичных настроек / параметров. Mpl.specgram возвращает двумерный массив уровней мощности (спектрограмму), динамический диапазон может быть применен к возвращаемому массиву и перенастроен.

Ниже приведен фрагмент кода для создания графиков ниже. Пример - речь ~ 1m15s с частотой от 20 Гц до 8000 Гц.

import numpy
import pylab
import wave
import array
pylab.close('all')
w1 = wave.open('example_no_noise.wav')
w2 = wave.open('example_noise.wav')
# hmmm, probably a better way to do this, scipy.io function?
x1 = numpy.array(array.array('h', w1.readframes(w1.getnframes())))
x2 = numpy.array(array.array('h', w2.readframes(w2.getnframes())))
x1 = x1 / (2.**(16-1))  # normalize
x2 = x2 / (2.**(16-1))  # normalize
Fs = 16000.
NFFT = int(Fs*0.005)  # 5ms window
noverlap = int(Fs*0.0025)
pylab.figure(1)
pylab.specgram(x1, NFFT=NFFT, Fs=Fs, noverlap=noverlap, 
               cmap=pylab.get_cmap('Greys'))
pylab.title('Full 1m15s example min noise')
pylab.figure(2)
pylab.specgram(x2, NFFT=NFFT, Fs=Fs, noverlap=noverlap, 
               cmap=pylab.get_cmap('Greys'))
pylab.title('Full 1m15s example more noise')
pylab.figure(3); n=2100*176;
pylab.specgram(x2[n:n+256*256], NFFT=NFFT, Fs=Fs, noverlap=noverlap, 
               cmap=pylab.get_cmap('Greys'))
pylab.title('Full ~4s example min noise')
pylab.figure(4); pylab.plot(x1[n:n+256*256])

Кристофер Фелтон
источник
1
Подумав немного об этом, параметр Praat «Dynamic Range» может быть основным фактором, влияющим на разницу в том, как выглядят графики. Praat «Динамический диапазон» может ограничивать диапазон (сжатие), чтобы вы получили больший контраст на графике. BOMK MPL не имеет подобной функции, но ее можно добавить.
Кристофер Фелтон
6

Кажется, это проблема разрешения времени / частоты. Ваш график Праата имеет худшее разрешение по частоте (вы даже не можете четко видеть гармоники) и лучшее разрешение по времени. Попробуйте уменьшить размер окна (NFFT) до 16000 x 0,05 = 80 выборок. Я бы предложил использовать большую степень 2 в pad_to (128 или 256).

pichenettes
источник