12 de mayo de 2011

Realización de un sintetizador de voz



Programando un sintetizador de voz (vocoder) en Matlab.






Aquí puede verse una presentación del trabajo realizado:







                                             CÓDIGO                                                   



function [salida]=vocoderlpc(wav)
% % Se ejecuta con la instrucción:
% vocoderlp('elarchivo.wav');
% Por ejemplo; vocoderlpc('osa.wav').
[signal,fs,nbits]=wavread(wav);
[STotal,PTotal,Er,CoefLpcTotal,vent]=codificador(signal,fs);
[salida,residuo]=decodificador(STotal,PTotal,Er,CoefLpcTotal,vent);
KI=calcerror(signal,salida);
wavwrite(salida,fs,'vozsint')
plot(salida);
sound(salida,fs);
sound(residuo,fs);
figure(1);
subplot(3,1,1);plot(signal);title('Señal de voz original');
subplot(3,1,2);plot(salida);title('Señal de voz sintetizada');
subplot(3,1,3);plot(KI);title('Error');
figure(2);
subplot(2,1,1);plot(PTotal);title('PITCH');
subplot(2,1,2);plot(STotal);title('SONORIDAD');
end


function [sonoridadTotal,pitchTotal,Er,coeflpcTotal,vent]=codificador(signal,fs)
durtrama=0.03; % duración de cada trama
x=(signal/max(abs(signal))); % Normalizar la señal
vent=round(fs*durtrama); % Longitud de la ventana
mtotal=length(x); % Longitud de la señal
n=floor(mtotal/vent); % num. ventanas ***FLOOR!  
sonoridadTotal=[];
pitchTotal=[];
coeflpcTotal=[];
Er=[];
for i=1:n
    trama=x(((i-1)*vent+1):(i*vent)); % Trama i
    trama=trama-mean(trama); % Diferencia trama y valormedio
    [sonoridad,pitch_]=pitch(trama,fs); %Calculamos el pitch
    sonoridadTotal=[sonoridadTotal sonoridad];
    pitchTotal=[pitchTotal pitch_];
    coeflpc=analisis_lpc(trama); %Cálculo coeficientes LPC 
    coeflpcTotal=[coeflpcTotal;coeflpc]; % Genera matriz coeficientes LPC (TODOS)
    E=filtrado_lpc(trama,coeflpc);
    Er=[Er E];
end

end




function [salida,residuo]=decodificador(STotal,PTotal,Er,CoefLpcTotal,vent)
% Sabiendo si una trama es sorda o sonora, se generan los impulsos
% correspondientes al pitch, y en caso de que sea sorda se genera ruido
% aleatorio.
n_tramas=length(PTotal); % Número de tramas
m_trama=vent; % Número de muestras por trama
salida=[];
residuo=[];
vux3=[];
a=[];
for i=1:n_tramas
    if(STotal(i)==1)
        Precup=PTotal(i);
        vux=zeros(1,m_trama);
        for j=1:(floor(m_trama/Precup))
           vux(j*Precup)=1;
        end
    else
        vux=rand(1,m_trama);
    end
E=sum(vux.^2);
G=sqrt(Er(i)/E);        
vux2=G.*vux;
residuo=[residuo vux2];
trama=filter(1,CoefLpcTotal(i,:),vux2);
salida=[salida trama];
end
end


function [diferencia]=calcerror(signal,salida)
signalAux=signal';
signalAux=signalAux(1:length(salida));
diferencia=abs(salida-signalAux);
end




function [sonoridad,pitch] = pitch(trama,fs)
N=25; % Orden del filtro paso bajo
fo=900; % Frecuencia de corte del filtro
M=4; % Orden del filtro para calculo residuo
B=fir1(N,(2*pi/fo));
    


tramafilt=filter(B,1,trama); % filtrado paso bajo trama
    coefresiduo=lpc(trama,M); % Generación cálculo residuo
    residuo=filter(coefresiduo,1,tramafilt); % Filtrado residuo
    corresiduo=xcorr(residuo); % Autocorrelación del residuo
    [A1,P1]=max(corresiduo);  % Maximo de la Autocorr residuo
    [A2,P2]=max(corresiduo(P1+(0.0025*fs):P1+(0.02*fs))); 
    % SEGUNDO maximo de la Autocorr residuo 2.5-20ms después
    P2=(P2+P1+0.0025*fs); % Posición real del segundo máximo
    sonoridad=0;
    pitch=0;
    if A2>(0.3*A1) 
        sonoridad=1;
        pitch=P2-P1;
        pitch=round(pitch);
    end
end


function [coeflpc] = analisis_lpc(trama)
%Genera los coeficientes de predicción lineal de una trama dada.
coeflpc=lpc(trama,10); %Crea un vector con los coeficientes LPC de cada trama.
end


function [E] = filtrado_lpc(trama,coeflpc)
%FILTRADO_LPC Realiza el filtrado LPC de la trama y 
% calcula la energía del residuo.
residuo=filter(coeflpc,1,trama); % Filtrado residuo
E=sum(residuo.^2);
end