Обнаружение частоты Python

Хорошо, что я пытаюсь сделать, это своего рода программное обеспечение для обработки звука, которое может определить преобладающую частоту, и если частота воспроизводится достаточно долго (несколько мс), я знаю, что получил положительное совпадение. я знаю, что мне нужно будет использовать БПФ или что-то подобное, но в этой области математики я отстой, я искал в Интернете, но не нашел код, который мог бы сделать только это.

цель, которую я пытаюсь достичь, состоит в том, чтобы создать собственный протокол для отправки данных через звук, нужен очень низкий битрейт в секунду (5-10 бит / с), но я также очень ограничен на передающей стороне, поэтому принимающее программное обеспечение должно быть настроено ( не могу использовать настоящий аппаратный/программный модем) также я хочу, чтобы это было только программное обеспечение (без дополнительного оборудования, кроме звуковой карты)

Большое спасибо за помощь.


person MatijaG    schedule 15.04.2010    source источник
comment
Это может быть полезно (обязательно прочитайте ответы): keyongtech.com/5003865 -частотный анализ-без-numpy   -  person ChristopheD    schedule 15.04.2010


Ответы (4)


Библиотеки aubio упакованы в SWIG и поэтому могут использоваться Python. Среди их многочисленных функций есть несколько методов обнаружения/оценки основного тона, включая YIN. алгоритм и некоторые алгоритмы гармонической гребенки.

Однако, если вы хотите чего-то более простого, я некоторое время назад написал код для оценки высоты тона, и вы можете взять его или оставить. Это будет не так точно, как использование алгоритмов в aubio, но этого может быть достаточно для ваших нужд. Я в основном просто взял БПФ данных, умноженных на окно (в данном случае окно Блэкмана), возвел в квадрат значения БПФ, нашел ячейку с наибольшим значением и использовал квадратичную интерполяцию вокруг пика, используя журнал максимального значения. и два его соседних значения, чтобы найти основную частоту. Квадратичную интерполяцию я взял из какой-то статьи, которую нашел.

Он довольно хорошо работает с тестовыми звуками, но не так надежен и точен, как другие методы, упомянутые выше. Точность можно повысить, увеличив размер блока (или уменьшить, уменьшив его). Размер фрагмента должен быть кратен 2, чтобы в полной мере использовать БПФ. Кроме того, я определяю только основную высоту звука для каждого фрагмента без перекрытия. Я использовал PyAudio для воспроизведения звука во время записи предполагаемой высоты тона.

Исходный код:

# Read in a WAV and find the freq's
import pyaudio
import wave
import numpy as np

chunk = 2048

# open up a wave
wf = wave.open('test-tones/440hz.wav', 'rb')
swidth = wf.getsampwidth()
RATE = wf.getframerate()
# use a Blackman window
window = np.blackman(chunk)
# open stream
p = pyaudio.PyAudio()
stream = p.open(format =
                p.get_format_from_width(wf.getsampwidth()),
                channels = wf.getnchannels(),
                rate = RATE,
                output = True)

# read some data
data = wf.readframes(chunk)
# play stream and find the frequency of each chunk
while len(data) == chunk*swidth:
    # write data out to the audio stream
    stream.write(data)
    # unpack the data and times by the hamming window
    indata = np.array(wave.struct.unpack("%dh"%(len(data)/swidth),\
                                         data))*window
    # Take the fft and square each value
    fftData=abs(np.fft.rfft(indata))**2
    # find the maximum
    which = fftData[1:].argmax() + 1
    # use quadratic interpolation around the max
    if which != len(fftData)-1:
        y0,y1,y2 = np.log(fftData[which-1:which+2:])
        x1 = (y2 - y0) * .5 / (2 * y1 - y2 - y0)
        # find the frequency and output it
        thefreq = (which+x1)*RATE/chunk
        print "The freq is %f Hz." % (thefreq)
    else:
        thefreq = which*RATE/chunk
        print "The freq is %f Hz." % (thefreq)
    # read some more data
    data = wf.readframes(chunk)
if data:
    stream.write(data)
stream.close()
p.terminate()
person Justin Peel    schedule 15.04.2010
comment
вау, большое спасибо, похоже, сейчас подойдет, мне только нужно понять, как читать звук в реальном времени с входа auido (микрофон) - person MatijaG; 16.04.2010
comment
Перейдите на сайт PyAudio people.csail.mit.edu/hubert/pyaudio и прокрутите вниз к примерам. Вы увидите некоторые из них, которые принимают вход с микрофона. - person Justin Peel; 16.04.2010
comment
ммм, не могли бы вы помочь мне понять, почему возникает эта ошибка: нужно больше 0 значений для распаковки в следующей строке y0, y1, y2 = np.log (fftData [what-1: which + 2:]) - person MatijaG; 16.04.2010
comment
Да, там что-то глючило. Я исправил это. Проблема заключалась в том, что если бы это было = 0 или последнее значение fftData, то он не вернул бы там 3 значения. В любом случае нам не нужно значение в нулевой ячейке fftData (это смещение постоянного тока). - person Justin Peel; 16.04.2010
comment
Можно ли было бы использовать np.fft.fftfreq для получения частот вместо того, чтобы самостоятельно выполнять преобразование и интерполяцию? - person ad rees; 30.03.2011
comment
@ad rees, не похоже, что np.fft.fftfreq делает то, что мы хотим. - person Justin Peel; 30.03.2011
comment
@JustinPeel Я хочу сравнить два аудио, не могли бы вы мне помочь? - person ehsandotnet; 07.07.2013
comment
Кто-нибудь знает, как получить основную частоту с аудиовхода микрофона? - person GiacomoLicari; 07.11.2014
comment
Почему моя длина данных всегда удваивает ширину блока * выборки? Я не могу войти в петлю. - person Liam Larsen; 27.02.2020

Если вы собираетесь использовать FSK (частотную манипуляцию) для кодирования данных, вероятно, лучше использовать алгоритм Герцеля, чтобы вы могли проверять только нужные вам частоты, а не полное ДПФ/БПФ.

person Guilherme    schedule 05.05.2011

Вы можете найти частотный спектр скользящих окон над вашим звуком из здесь и затем проверьте наличие преобладающей полосы частот, найдя область под кривой частотного спектра для этой полосы из здесь.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import auc
np.random.seed(0)

# Sine sample with a frequency of 5hz and add some noise
sr = 32  # sampling rate
y = np.linspace(0, 5 * 2*np.pi, sr)
y = np.tile(np.sin(y), 5)
y += np.random.normal(0, 1, y.shape)
t = np.arange(len(y)) / float(sr)

# Generate frquency spectrum
spectrum, freqs, _ = plt.magnitude_spectrum(y, sr)

# Calculate percentage for a frequency range 
lower_frq, upper_frq = 4, 6
ind_band = np.where((freqs > lower_frq) & (freqs < upper_frq))
plt.fill_between(freqs[ind_band], spectrum[ind_band], color='red', alpha=0.6)
frq_band_perc = auc(freqs[ind_band], spectrum[ind_band]) / auc(freqs, spectrum)
print('{:.1%}'.format(frq_band_perc))
# 19.8%

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

person Reveille    schedule 03.07.2019

Хотя я раньше не пробовал обрабатывать звук с помощью Python, возможно, вы могли бы создать что-то на основе SciPy (или его подпроект NumPy), основу для эффективных научных/инженерных численных вычислений? Вы можете начать с просмотра scipy.fftpack для своего БПФ.

person Karmastan    schedule 15.04.2010
comment
хорошо, я нашел это swharden.com/blog/ теперь мне интересно, как мне найти диапазон частот, который находится на самом высоком уровне (также SciPy немного помог, спасибо - person MatijaG; 15.04.2010
comment
так ты понял как это сделать? - person kRazzy R; 05.12.2017