Частично правильное определение частоты в Python

Я нашел алгоритм, который использует автокорреляцию и параболическую интерполяцию для оценки частоты звукового сигнала.

# correct the signal.
auto = scipy.signal.fftconvolve(signal, signal[::-1], mode='full')
auto = auto[len(auto)/2:]

# find the first minimum point in the signal.
difference = numpy.diff(auto)
start = matplotlib.mlab.find(difference > 0)[0]

# find the peak from that position.
peak = numpy.argmax(auto[start:]) + start
# calculate the period using parabolic interpolation.
period = 1/2.0 * (auto[peak-1] - auto[peak+1]) / (auto[peak-1] - 2 * auto[peak] + auto[peak+1]) + peak
frequency = sample_rate / period

Я знаю, что диапазон человеческого слуха составляет от 20 Гц до 20 кГц. При частоте дискретизации 44100 Гц я могу точно писать и читать 22049 Гц. Однако алгоритм ошибается на некоторых частотах.

Для сигнала 840 Гц он читает 420 Гц. При 20000 Гц алгоритм вычисляет 512 Гц. Алгоритм колеблется между точными оценками и возвращением неверной частоты.

Я не очень разбираюсь в обработке сигналов.


person lux    schedule 21.10.2015    source источник
comment
Ваш сигнал чистый (смоделированный) или это реальное (шумное) измерение?   -  person Julien    schedule 22.10.2015
comment
Сигналы чистые. Я использую модуль волны Python для записи сигналов. @JulienBernu   -  person lux    schedule 22.10.2015
comment
Я никогда не слышал об этой технике (но я не эксперт), и быстрый поиск, похоже, показывает, что она в основном используется для обнаружения `` скрытой '' основной частоты составных волн, что может как-то объяснить, как вы могли перейти от 840 до 420? Если бы у меня была та же цель, работая с чистыми синусоидальными волнами, я бы просто взял fft самого сигнала и посмотрел на пик ...   -  person Julien    schedule 22.10.2015
comment
Я тоже не эксперт. Я читал о БПФ в вольфрам-альфа и вики, но до сих пор не имею четкого представления о том, что происходит. Не могли бы вы объяснить упомянутый вами подход? @JulienBernu   -  person lux    schedule 22.10.2015
comment
БПФ означает быстрое преобразование Фурье. Быстрая часть просто относится к умному вычислительному трюку, чтобы сделать вещи ... быстрыми. Если вы ищете БПФ, вы в основном получите результаты для этого вычислительного трюка, который для вас не имеет отношения (для начала). Просто найдите преобразование Фурье, чтобы увидеть, как оно связано со спектральным анализом. Это разумно продвинутая математика, и здесь не будет краткого ответа ... Для ответа из двух слов: FT синусоиды показывает четкий пик на частоте вашего синуса (в пределах масштабирования частоты дискретизации).   -  person Julien    schedule 22.10.2015
comment
Интересная математика. Я нашел реализацию, в которой используется описанный вами алгоритм. Насколько я понимаю, пик преобразования Фурье - это частота? @JulienBernu   -  person lux    schedule 22.10.2015


Ответы (1)


Если вы хотите оценить частоту чистого смоделированного сигнала, преобразование Фурье идеально подходит для ваших нужд.

import numpy as np

SAMPLE_RATE = 48000
FREQUENCY = 840.0

# simulated pure signal
t = np.linspace(0, 1, SAMPLE_RATE)
signal = np.sin(2 * np.pi * FREQUENCY * t)

# compute the magnitude of the Fourier Transform and its corresponding frequency values
freq_magnitudes = np.abs(np.fft.fft(signal))
freq_values = np.fft.fftfreq(SAMPLE_RATE, 1/SAMPLE_RATE)

# find the max. magnitude
max_positive_freq_idx = np.argmax(freq_magnitudes[:SAMPLE_RATE//2 + 1])

print(freq_values[max_positive_freq_idx]) # 840.0

Если вы не знакомы с преобразованием Фурье, например прочтите главу 8 книги Стивена Смита Руководства для ученых и инженеров по цифровой обработке сигналов .

person Frank Zalkow    schedule 11.11.2015