Fundamental Frequency Estimation Methods
Oi Pessoal…
Eu escrevi algo bem superficial neste blog sobre Frequencia fundamental (F0), recebi alguns emails perguntando sobres os métodos utilizados para se estimar as frequencias dentro de arquivos de áudios, como aplicar estes métodos e quais deles possuem melhor desempenho!
Testei os seguintes métodos:
- Transformada de Fourrier
- Zero Crossing
- Auto-correlação
Auto-Correlação como esperado possue o pior desempenho, aplicar correlação em um sinal de áudio para depois encontrar o maior valor dentro dos dados correlacionados toma muito tempo de processamento!
Transformada de Fourrier possue um desempenho melhor comparado ao método anterior, submeter o sinal a transformada de fourrier é uma boa alternativa para encontrar frequencias diversas dentro de arquivos de áudios.
Zero Crossing o grande campeão chega a ser quinze (15) vezes mais rápido do que a auto-correlação e pensando friamente é muito mais fácil e rápido encontrar quais são os pontos de variações dentro do sinal, sem submeter o sinal a fourrier.
Tela dos testes:
Source:
from __future__ import division
from numpy.fft import rfft
from numpy import argmax, mean, diff, log, fromstring
from matplotlib.mlab import find
from scipy.signal import fftconvolve, kaiser
from time import time
import sys
import wave
def parabola(data,x):
v1=1/2*(data[x-1]-data[x+1])/(data[x-1]-2*data[x]+data[x+1])+x
v2=data[x]-1/4*(data[x-1]-data[x+1])*(v1 – x)
return (v1, v2)
def Fundamental_Frequency_zero_crossing(signal, fs):
values = find((signal[1:] >= 0) & (signal[:-1] < 0))
crossingValues = [i - signal[i] / (signal[i+1] – signal[i]) for i in values]
return fs / mean(diff(crossingValues))
def Fundamental_Frequency_fft(signal, fs):
janela = signal * kaiser(len(signal),100)
f = rfft(janela)
i = argmax(abs(f))
real = parabola(log(abs(f)), i)[0]
return fs * real / len(janela)
def Fundamental_Frequency_autocorrelation(signal, fs):
correlacao = fftconvolve(signal, signal[::-1], mode=’full’)
correlacao = correlacao[len(correlacao)/2:]
d = diff(correlacao)
inicio = find(d > 0)[0]
pico = argmax(correlacao[inicio:]) + inicio
picox, picoy = parabola(correlacao, pico)
return fs / picox
filename = sys.argv[1]
spf = wave.open(filename,’r')
signal = spf.readframes(-1)
signal = fromstring(signal, ‘Int16′)
fs = spf.getframerate()
print ‘\n ** Arquivo Aberto ** “%s”\n’ % filename
print ‘Calculando a Frequencia por FFT:’,
start_time = time()
print ‘%f Hz’ % Fundamental_Frequency_fft(signal, fs)
print ‘Tempo: %.3f s\n’ % (time() – start_time)
print ‘Calculando a Frequencia por zero crossing:’,
start_time = time()
print ‘%f Hz’ % Fundamental_Frequency_zero_crossing(signal, fs)
print ‘Tempo: %.3f s\n’ % (time() – start_time)
print ‘Calculando a Frequencia por autocorrelação:’,
start_time = time()
print ‘%f Hz’ % Fundamental_Frequency_autocorrelation(signal, fs)
print ‘Tempo: %.3f s\n’ % (time() – start_time)
Até
Eng Eder de Souza

Muito interessante esse tópico!! gostei! eu queria tirar uma dúvida… eu fiz um software de reconhecimento de fala usando uma API da Microsoft para o PT-BR que não foi liberada publicamente, dava uns errinhos mas funcionava legal
Agora será que usando esse método em ligações de reconhecimento de fala na URA iria bem? hehehe
Olá Caio a resposta é Não, a frequencia fundamental varia muito e não é recomendada para reconhecimentos de fala, uma boa pedida para reconhecimento de palavras isoladas é o Dinamic Time Warping, desenvolvi alguns algoritmos para este fim e funciona bem…
Eng Eder de Souza
Obrigado!!!!
Oi Eder. Eu estou pensando em fazer um software onde eu preciso reconhecer a frequência, atribuí-la a uma nota/figura musical e calcular seu tempo de execução. Nesse caso, você saberia me dizer qual desses métodos melhor se aplica? Obrigada. Juliana.
Oi Juliana,
A auto-correlação ou FFT possue bons resultados para identificar frequencias, tome cuidado se estiver trabalhando com detecção de frequencias em instrumentos, estes métodos podem não trabalhar bem com ondas complexas, procure por cepstrum para estes casos.
Outro ponto importante é como você ira trabalhar os dados de origem se será em realtime ou arquivos gravados… Alguns métodos se tornam inviáveis por tomar muito processamento.
De uma olhada neste meu post “http://ederwander.wordpress.com/2011/09/09/experimental-guitar-tuner/” nele utilizo o método AMDF em meus testes consegui bons resultados, no final do post tem o link onde você pode ver o source inclusive nele está implementado como converter uma frequencia em Nota
;
Eng Eder de Souza