Vuelvo a presentar un nuevo detector de pitch, esta vez, basado en autocorrelación. Dicho detector está programado en MatLab y está basado en el algoritmo SIFT. Su diagrama de bloques se observa a continuación.
Primero, el audio de entrada se preprocesa remuestreando desde 44100Hz (asumimos dicha frecuencia de muestreo para el audio de entrada) a 8000Hz, habiendo ponderado previamente ambos canales estéreo para, finalmente, normalizar la señal.
Seguidamente filtramos la señal mediante un filtro tipo Butterworth paso-bajo con frecuencia de corte 800Hz (correspondiente, aproximadamente, a un Sol-5 en la escala musical) para, a continuación, aplicar un downsampling correspondiente a la nueva frecuencia máxima presente en la señal, lo que se traduce, según el criterio de Nyquist, en un remuestreo a 1600Hz. Fragmentamos en tramas el audio filtrado y, para cada trama, aplicamos el proceso descrito a partir de ahora. Se toma el frame y con él se realiza un estudio LPC (Linear Predictive Coding), con el fin de modelar la respuesta espectral referente al tracto vocal (formantes) mediante un filtro todo-polos. Una vez obtenidos los coeficientes de dicho filtro, se filtra la trama mediante otro filtro FIR cuyos coeficientes son los anteriores del modelo LPC. Con ello, intentamos eliminar la información propia del tracto vocal de la señal con el fin de mantener sólo la información de interés: el pitch. Por último se calcula la función autocorrelación de la señal filtrada y se interpola para ganar resolución temporal. El pico máximo detectado a la salida, se corresponderá con el período de pitch deseado.
La función que implementa el anterior proceso toma como datos de entrada el tamaño del frame (en segundos, con un valor típico de 40ms) y el solapamiento (también en segundos, con un valor típico de 10ms) aparte de, claro está, el propio audio cuyo pitch deseamos estimar.
También se incluye un detector de actividad de voz basado en hangover con los parámetros por defecto fijados en la función (cambiar si fuera necesario). La salida es la secuencia de pitch, a la que se le ha aplicado el logaritmo neperiano (si se desea obtener la frecuencia en Hz's, cambiar desde el código o aplicar la exponencial al vector de salida), de tal forma que no se incluyen las estimaciones para las tramas cuyo flag proporcionado por el detector de voz se corresponda con silencio.
La gráfica adjunta muestra un ejemplo del pitch estimado para la canción Hush de Deep Purple tarareada.
IMPORTANTE: La función detPico.m se encuentra en la entrada justamente anterior.
IMPORTANTE: La función detPico.m se encuentra en la entrada justamente anterior.
% Detector de pitch
% Autor: Iván López Espejo
function pitch = detPitch(x,wsize,sol)
% Preprocesado.
fm1 = 44100;
fm = 8000;
x = (x(:,1) + x(:,2))/2;
x = resample(x,fm,fm1)
x = x/max(abs(x));
% Parámetros del detector de actividad de voz.
THRESHOLD = 0.01;
MIN_SPEECH_FRAME_HANGOVER = 4;
HANGOVER = 1;
meanEn = 0;
nbSpeechFrame = 0;
ind = 1;
% Diseño de filtro paso-bajo Butterworth con frecuencia de corte a 800Hz.
fc = 800;
Nf = 2; % Orden del filtro.
Wn = 2*fc/fm;
[b,a] = butter(Nf,Wn,'low');
x = filter(b,a,x); % Filtramos paso-bajo.
x = resample(x,2*fc,fm); % Downsampling.
% Análisis por frame.
wsize = round(wsize * 2 * fc);
sol = round(sol * 2 * fc);
% Definimos las constantes de la ventana.
a0 = 0.53836;
a1 = 0.46164;
Npred = 12; % Número de coeficientes del predictor lineal.
b0 = 1;
fint = 5; % Factor de interpolación.
pitch = [];
for m = 1:(wsize-sol-1):length(x)
if wsize > length(x) - m
N = length(x) - m + 1;
else
N = wsize;
end
% Detección de la actividad de voz.
frameEn = dot(x(m:m+N-1),x(m:m+N-1))/N;
if frameEn - meanEn > THRESHOLD
VAD(ind) = 1;
nbSpeechFrame = nbSpeechFrame + 1;
if nbSpeechFrame > MIN_SPEECH_FRAME_HANGOVER
hangOver = HANGOVER;
end
else
if hangOver == 0
VAD(ind) = 0;
else
VAD(ind) = 1;
hangOver = hangOver - 1;
end
end
ind = ind + 1; % Incremento del contador.
% Enventanado del frame mediante Hamming.
n = 1:N;
win = a0 - a1*cos(2*pi*n/(N-1));
frame = x(m:m+N-1).*win';
% Método de la autocorrelación para modelado de los coeficientes del
% predictor lineal asociado a la trama.
acoef = lpc(frame,Npred);
% Usamos los anteriores coeficientes como coeficientes de un filtro
% FIR.
eps = filter(acoef,b0,frame);
reps = xcorr(eps,'biased'); % Cómputo de la autocorrelación.
% Interpolación para la obtención de mayor resolución temporal.
Pm = interp(reps,fint);
Pm = Pm(floor(length(Pm)/2):length(Pm));
% Detectamos el pico máximo en la función de autocorrelación.
picomax = detPico(Pm);
pause();
if VAD(ind-1) == 1
pitch = [pitch (log(2*fc*fint/(picomax-1)))];
end
end
% Representamos el resultado.
plot(pitch,'-*r')
grid on
xlabel('Evolución temporal')
ylabel('Frecuencia de pitch logarítmica')
title('PITCH estimado')


0 comentarios:
Publicar un comentario en la entrada