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