2010-04-15 14 views
29

Ok co próbuję zrobić, to rodzaj oprogramowania przetwarzającego audio, które może wykryć powszechną częstotliwość i jeśli częstotliwość jest odtwarzana przez wystarczająco długi czas (kilka ms), wiem, że mam pozytywny wynik. Wiem, że musiałbym używać FFT lub czegoś podobnego, ale w tej dziedzinie matematyki ssałem, przeszukałem internet, ale nie znalazłem kodu, który mógłby zrobić tylko to.Wykrywanie częstotliwości w Pythonie

celem, w którym staram się je zdobyć, jest stworzenie niestandardowego protokołu przesyłania dźwięku w systemie danych, potrzeba bardzo niskiej przepływności na sekundę (5-10b/s), ale również bardzo ograniczonej na końcu transmisji, aby oprogramowanie do odbierania danych było potrzebne być w stanie niestandardowym (nie mogę używać rzeczywistego modemu sprzętowego/programowego), ale chcę, żeby to było tylko oprogramowanie (bez dodatkowego sprzętu z wyjątkiem karty dźwiękowej).

+1

Może to być pomocne (koniecznie przeczytaj odpowiedzi): http://www.keyongtech.com/5003865-przypadku-analizy-z-nadruku-numpy – ChristopheD

Odpowiedz

37

Biblioteki aubio zostały opakowane za pomocą SWIG i dlatego mogą być używane przez Python. Wśród wielu ich funkcji znajduje się kilka metod wykrywania/szacowania wysokości tonu, w tym algorytmu YIN i niektórych harmonicznych algorytmów grzebieniowych.

Jednakże, jeśli chcesz czegoś prostszego, napisałem jakiś kod do oszacowania wysokości tonu jakiś czas temu i możesz go przyjąć lub odrzucić. To nie będzie tak dokładne, jak użycie algorytmów w aubio, ale może być wystarczająco dobre dla twoich potrzeb. Zasadniczo po prostu wziąłem FFT z danych razy okno (okno Blackman w tym przypadku), podniesiono do kwadratu wartości FFT, odnalazłem pojemnik, który miał najwyższą wartość, i wykorzystałem kwadratową interpolację wokół piku używając dziennika maksymalnej wartości i jego dwie sąsiednie wartości, aby znaleźć częstotliwość podstawową. Kwadratowa interpolacja, którą wziąłem z jakiegoś papieru, który znalazłem.

Działa dość dobrze na tony testowe, ale nie będzie tak solidny i dokładny jak inne metody wymienione powyżej. Dokładność można zwiększyć, zwiększając rozmiar porcji (lub zmniejszając ją, zmniejszając). Rozmiar porcji powinien być wielokrotnością 2, aby w pełni wykorzystać FFT. Ponadto określam tylko podstawową wysokość dla każdego fragmentu bez nakładania się. Użyłem PyAudio do odtworzenia dźwięku podczas pisania szacowanej wysokości dźwięku. Kod

Źródło:

# 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() 
+0

Wow wielkie dzięki, to wygląda na to, że zrobię teraz tylko gota rysunek jak czytać audio w czasie rzeczywistym z wejścia auido (mikrofon) – MatijaG

+2

Wejdź na stronę PyAudio http://people.csail.mit.edu/hubert/pyaudio/ i przewiń stronę do przykładów. Zobaczysz kilka, które pobierają dane z mikrofonu –

+0

uhm możesz mi pomóc dlaczego tak się dzieje: " potrzebujesz więcej niż 0 wartości, aby rozpakować " w następującej linii " y0, y1, y2 = np.log (fftData [which-1: which + 2:]) " – MatijaG

0

Podczas gdy wcześniej nie próbowałem przetwarzania dźwięku w Pythonie, być może mógłbyś zbudować coś na podstawie SciPy (lub jego podprojektu NumPy), ramy dla wydajnych naukowych obliczeń numerycznych? Możesz zacząć od spojrzenia na scipy.fftpack dla swojej FFT.

+1

ok znalazłem ten http://www.swharden.com/ blog/2010-03-05-realtime-fft-graph-of-audio-wav-file-or-mikrofon-input-with-python-scipy-and-wckgraph/tho teraz zastanawiam się, jak znajdę zakres częstotliwości, który jest na najwyższym poziomie (również SciPy pomógł mi nieco dzięki – MatijaG

+0

, więc wymyśliłeś, jak to zrobić? –

Powiązane problemy