Le librerie aubio sono state incapsulate con SWIG e possono quindi essere utilizzate da Python. Tra le loro molte caratteristiche vi sono diversi metodi per il rilevamento/stima del pitch, tra cui l'algoritmo YIN e alcuni algoritmi a pettine armonico.
Tuttavia, se vuoi qualcosa di più semplice, ho scritto del codice per la stima del passo qualche tempo fa e puoi prenderlo o lasciarlo. Non sarà accurato come usare gli algoritmi di aubio, ma potrebbe essere abbastanza buono per le tue esigenze. Fondamentalmente ho appena preso la FFT dei dati volte una finestra (una finestra Blackman in questo caso), ha quadrato i valori FFT, trovato il bin che aveva il valore più alto e ho usato un'interpolazione quadratica attorno al picco usando il log del valore massimo e i suoi due valori vicini per trovare la frequenza fondamentale. L'interpolazione quadratica che ho preso da un foglio che ho trovato.
Funziona abbastanza bene sui toni di prova, ma non sarà così robusto o preciso come gli altri metodi menzionati sopra. L'accuratezza può essere aumentata aumentando la dimensione del blocco (o ridotta diminuendola). La dimensione del blocco dovrebbe essere un multiplo di 2 per sfruttare appieno la FFT. Inoltre, sto solo determinando la tonalità fondamentale per ogni blocco senza sovrapposizioni. Ho usato PyAudio per riprodurre il suono mentre scrivevo la tonalità stimata. Codice
Fonte:
# 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()
fonte
2010-04-15 22:52:01
Questo può essere utile (assicurarsi di leggere le risposte): http://www.keyongtech.com/5003865-frequency-analysis-without-numpy – ChristopheD