После некоторого реверс-инжиниринга исходного кода Audacity вот несколько ответов. Во-первых, они используют алгоритм Уэлча для оценки PSD. Короче говоря, он разделяет сигнал на перекрывающиеся сегменты, применяет некоторую оконную функцию, применяет БПФ и усредняет результат. Главным образом, поскольку это помогает получить лучшие результаты при наличии шума. В любом случае, после извлечения необходимых параметров вот решение, которое приближает спектрограмму Audacity:
import numpy as np
from scipy.io import wavfile
from scipy import signal
from matplotlib import pyplot as plt
segment_size = 512
fs, x = wavfile.read('sine3k6k.wav')
x = x / 32768.0 # scale signal to [-1.0 .. 1.0]
noverlap = segment_size / 2
f, Pxx = signal.welch(x, # signal
fs=fs, # sample rate
nperseg=segment_size, # segment size
window='hanning', # window type to use
nfft=segment_size, # num. of samples in FFT
detrend=False, # remove DC part
scaling='spectrum', # return power spectrum [V^2]
noverlap=noverlap) # overlap between segments
# set 0 dB to energy of sine wave with maximum amplitude
ref = (1/np.sqrt(2)**2) # simply 0.5 ;)
p = 10 * np.log10(Pxx/ref)
fill_to = -150 * (np.ones_like(p)) # anything below -150dB is irrelevant
plt.fill_between(f, p, fill_to )
plt.xlim([f[2], f[-1]])
plt.ylim([-90, 6])
# plt.xscale('log') # uncomment if you want log scale on x-axis
plt.xlabel('f, Hz')
plt.ylabel('Power spectrum, dB')
plt.grid(True)
plt.show()
Некоторые необходимые пояснения по параметрам:
- волновой файл читается как 16-битный PCM, чтобы быть совместимым с Audacity, он должен быть масштабирован до | A | <1.0 </li>
segment_size
соответствует Size
в графическом интерфейсе Audacity.
- тип окна по умолчанию - Hanning, вы можете изменить его, если хотите.
- перекрытие
segment_size/2
как в коде Audacity.
- окно вывода оформлено в соответствии со стилем Audacity. Они выбрасывают первые низкочастотные контейнеры и режут все ниже -90 дБ
![enter image description here](https://i.stack.imgur.com/YPVLz.png)
Какое физическое значение амплитуды на втором рисунке?
Это в основном количество энергии в частотном бине.
Как нормализовать амплитуду до 0 дБ, как в Audacity?
Вам нужно выбрать опорную точку. Графики в децибелах всегда имеют отношение к чему-либо. Когда вы выбираете максимальный уровень энергии в качестве эталона, ваша точка 0 дБ является максимальной энергией (очевидно). Это приемлемо, чтобы установить в качестве опорной энергии синусоидальной волны с максимальной амплитудой. См. ref
переменная. Мощность синусоидального сигнала - это просто среднеквадратическое среднеквадратичное значение, и для получения среднеквадратичного значения нужно просто разделить амплитуду на sqrt (2). Таким образом, коэффициент масштабирования просто 0,5. Обратите внимание, что коэффициент перед log10
равен 10, а не 20, это потому, что мы имеем дело с мощностью сигнала, а не с амплитудой.
Можно ли считать амплитуду ниже -90 дБ настолько низкой, чтобы ее можно было игнорировать?
Да, все, что ниже -40 дБ, обычно считается незначительным