Práctica 2. Análisis y síntesis de la señal de voz con el modelo LPC de producción de voz.

 

 

ALUMNO:                             Antonio Corpas Cuenca

DNI:                                       48872959-Y

ASIGNATURA:                     Procesamiento de la Voz

PROFESOR:                          Victoria Eugenia Sanchez Calle

GRUPO:                                 Jueves 11:00-13:00

CURSO:                                 2002-03

 

 

Indice

 

v     Análisis y representación paramétrica de la voz usando el modelo LPC

v     Determinar los parámetros y reconstruir la señal de voz

v     Determinar los espectros de las señales

v     Preguntas

v     Modelo simplificado de producción de voz

v     Manipulación de la señal de voz

 

 

Análisis y representación paramétrica de la voz usando el modelo LPC

En esta práctica se pretende hacer una introducción al modelo LPC de producción de voz. El modelo LPC nos suministra una forma alternativa de representación de la señal de voz. Esta queda representada por los coeficientes de predicción lineal  del filtro que caracteriza al tracto vocal  y por la excitación . Para obtener una representación paramétrica de la señal de voz de esta forma hemos de tomar la señal de voz, dividirla en segmentos de tamaño entre 10 y 20 ms (se considera que durante ese tiempo el filtro que caracteriza al tracto vocal no cambia) y determinar para cada segmento de voz el valor de los coeficientes  y de la excitación . El tamaño del segmento a utilizar en esta práctica va a ser igual a 15 ms, por lo tanto, cada segmento estará constituido por 120 muestras. A continuación se describe como se calculan cada uno de estos parámetros:

 

v     1. Coeficientes . Estos se determinan para cada segmento a partir de las muestras de voz de dicho segmento y el procedimiento consiste básicamente en resolver un sistema lineal de ecuaciones, tal y como se ha estudiado en clase. Existen dos métodos para determinar los . En esta práctica se va a utilizar el método de autocorrelación, utilizándose para ello la función lpc de Matlab. El número p de parámetros  mínimos para caracterizar lo suficientemente bien la señal de voz viene dado por  donde  es la frecuencia de muestreo en KHz. En nuestro caso, como la frecuencia de muestreo de las señales que vamos a utilizar es igual a 8 KHz, el parámetro  sería igual, por tanto, a 10.

v     2. Excitación . Una vez conocidos los coeficientes  para un segmento, se puede determinar fácilmente la excitación  para dicho segmento, simplemente utilizando la fórmula que aparece a continuación, donde se ha de tener en cuenta que para calcular la excitación del segmento actual se han de considerar también las  muestras de voz anteriores del segmento precedente.

 

 

 

Determinar los parámetros y reconstruir la señal de voz

Determine la señal de excitación  y los parámetros  de las secuencias de filtros que modelan las señales de voz de los ficheros de voz del directorio fichvoz. Para comprobar que se ha realizado bien el cálculo de la señal de excitación, vuelva a obtener la señal de voz original pasando dicha excitación por el filtro del tracto vocal , es decir, realizando la operación

 

Los ficheros que se han utilizado para la realización de este apartado se muestran listados a continuación.

 

 

Fichero seg.m

 

function v=seg(s,x)

% SEG segmenta el vector s

% devuelve el vector numero x de 120 muestras

% x esta comprendido entre 1 y n

a=1+(x-1)*120;

b=a+119;

v=s(a:b);

 

 

Fichero funcak.m

 

function v=funcak(segmento,p)

% AK calcula los coeficientes ak de segmento 

ak=lpc(segmento,p);    

for z=1:p+1

    ak(z)=-1*ak(z);

end

v=[ak(2:11)];

 

 

Fichero excitacion.m

 

function v=excitacion(s,z,ak,p)

% EXCITACION calcula la excitacion Gu del segmento de 120 muestras s

% devuelve el vector de excitacion v

% z es el segmento anterior de s

% ak es el vector de coeficientes ak de tamaño p

seg_auxiliar=z(111:120);

seg_auxiliar=[seg_auxiliar,s(1:10)];

for i=1:10

    sumatorio=0.0;

    for k=1:p      

        sumatorio=ak(k)*seg_auxiliar(i+10-k)+sumatorio;

    end

    v(i)=s(i)-sumatorio;

end

 

for i=11:120

    sumatorio=0.0;

    for k=1:p      

        sumatorio=(ak(k)*s(i-k))+sumatorio;

    end

    v(i)=s(i)-sumatorio;

end

 

 

Fichero pract2_1.m

 

% abrir el fichero y reproducir

fich1=fopen('e:\facultad\pv\practica2\8k\vege1850.8k','r');

[ficheroentrada,num]=fread(fich1,inf,'int16');

 

% se eliminan los ceros del principio del fichero

principiofichero=1;

indice=1;

s=0;

for i=1:num

    if ((principiofichero==1) & (ficheroentrada(i)==0))    

        principiofichero=1;  

    else

        s(indice)=ficheroentrada(i);

        principiofichero=0;

        indice=indice+1;

    end

end

sound(s/max(s),8000);

 

% variables

Fs=8;

p=10;

numsegmento=floor(indice/120);

 

% calcular coeficientes ak

for i=1:numsegmento

    if (i==1)

        aktotal=funcak(seg(s,i),p);

    else

        aktotal=[aktotal,funcak(seg(s,i),p)];

    end

end

 

 

 

% calcular excitacion Gu primer segmento

vectorcero=1:120;

for i=1:120

    vectorcero(i)=0;

end

Gu=excitacion(seg(s,1),vectorcero,aktotal(1:10),p);

 

% calcular excitacion Gu resto segmentos

for i=2:numsegmento

    z=((i-1)*10)+1;

    Gu=[Gu,excitacion(seg(s,i),seg(s,i-1),aktotal(z:z+9),p)];

end

 

% reconstrucción de la señal

sreconstruida=1:length(s);

for i=1:length(s)

    sreconstruida(i)=0;

end

ak=aktotal(1:10);

for i=11:length(Gu)

    sumatorio=0.0;

    for k=1:p

        sumatorio=(ak(k)*sreconstruida(i-k))+sumatorio;

    end

    sreconstruida(i)=sumatorio+Gu(i);

    if ((mod(i,120)==0) & (i~=length(Gu)))

        z=((i/120)*10)+1;

        ak=aktotal(z:z+9);

    end

end

 

% calculo del error

for z=1:length(s)

  error(z)=s(z)-sreconstruida(z);

end

 

% representacion grafica de las señales

subplot(2,1,1);

plot(s);

title('SEÑAL ORIGINAL');

subplot(2,1,2);

plot(sreconstruida);

title('SEÑAL RECONSTRUIDA');

sound(sreconstruida/max(sreconstruida),8000);

pause

 

% representacion grafica segmento a segmento

for i=1:numsegmento

  subplot(2,1,1);

  plot(seg(s,i));

  title(i);

  subplot(2,1,2);

  plot(seg(sreconstruida,i));

  title('SEGMENTO RECONSTRUIDO');

  pause

  subplot(1,1,1);

  plot (seg(error,i));

  title('ERROR COMETIDO');

  pause

end

 

 

En el fichero seg.m se implementa la función que permite calcular un segmento cualquiera de 120 muestras a partir de la señal de voz original. Devuelve por lo tanto, un vector de 120 posiciones.

El fichero funcak.m se corresponde con la función que calcula los parámetros  de un segmento de 120 muestras a partir de la función lpc que encontramos en Matlab pero con algunas modificaciones ya que debemos despreciar el primer valor que devuelve dicha función y además cambiar el signo al resto de los valores devueltos.

La función que calcula la excitación  de un determinado segmento se encuentra implementada en el fichero excitación.m. Dicha función realiza el cálculo de la excitación según la fórmula o expresión que se comenta en el apartado anterior. Resaltar el hecho de que para calcular la excitación del primer segmento del fichero de voz se necesitan p muestras anteriores a la primera muestra por lo que nosotros hemos utilizado muestras con valores iguales a cero.

Una vez que hemos definido las funciones principales que vamos a necesitar a la hora de desarrollar la práctica se procede a comentar el fichero pract2_1.m que es donde se realizan los pasos comprendidos entre la apertura del fichero origen y la reconstrucción y posterior comparación de la señal de voz. En un primer paso debemos abrir el fichero de voz original, eliminar los posibles ceros del principio del fichero para no tener problemas posteriores a la hora de utilizar la función lpc y reproducir el fichero de sonido para comprobar cual es la señal de voz original. A continuación se calculan cada uno de los parámetros  correspondientes a cada uno de los segmentos de 120 muestras del fichero de voz y se almacenan en una variable que llamaremos aktotal. El siguiente paso es calcular la excitación correspondiente a cada uno de los segmentos del fichero, para lo cual se utilizará la función excitacion comentada anteriormente, almacenando los resultados obtenidos en la variable denominada Gu. Una vez que tenemos la señal de voz descompuesta en los parámetros  y en la señal de excitación, pasamos a construir una nueva señal de voz a partir de dichos parámetros, con el objetivo de comparar la señal obtenida con la señal original y estudiar los resultados. La representación se realiza mostrando en la parte superior la señal original y en la parte inferior la señal reconstruida. A continuación el programa muestra segmento a segmento cada una de las señales acompañada de la señal de error generada en la reconstrucción de la señal. Dicha señal de error se calcula restando a la señal original la señal reconstruida. El programa finaliza cuando se han mostrado todos y cada uno de los segmentos que componen el fichero de voz o bien cuando el usuario presiona las teclas CTRL-C.

A continuación se muestran los resultados obtenidos después de aplicar nuestro algoritmo a cuatro de las señales de voz disponibles en el directorio de la asignatura.

 

 

Figura 1. Representación correspondiente al fichero de voz “euge0013.8k”.

Escuchar señal original.

Escuchar señal reconstruida.

 

 

Figura 2. Representación correspondiente al fichero de voz “aage3201.8k”.

Escuchar señal original.

Escuchar señal reconstruida.

 

 

Figura 3. Representación correspondiente al fichero de voz “tsge3270.8k”.

Escuchar señal original.

Escuchar señal reconstruida.

 

 

Figura 4. Representación correspondiente al fichero de voz “vege1850.8k”.

Escuchar señal original.

Escuchar señal reconstruida.

 

 

Como se puede observar a simple vista, el resultado obtenido en todos y cada uno de los casos muestra que la señal reconstruida a partir de los parámetros  y la señal de excitación  es extremadamente parecida a la señal de voz original. Además, no solo viendo la representación gráfica de las señales se puede comprobar este hecho. Al reproducir en Matlab tanto la señal original como la señal reconstruida no se puede apreciar una diferencia significante. A continuación, y para entrar un poco más en detalle acerca de la reconstrucción de la señal, vamos a centrarnos en la señal de voz correspondiente al fichero euge0013.8k y vamos a estudiar varios segmentos de 120 muestras y los errores cometidos a la hora de reconstruir los mismos.

Para empezar se van a mostrar 2 segmentos que claramente corresponden a sonidos sonoros ya que presentan una estructura periódica (ver Figura 5 y Figura 7). Como puede verse la similitud entre el segmento original y el segmento reconstruido es muy grande. Este hecho se corrobora ya que si nos fijamos en el error cometido podemos ver como es prácticamente nulo o despreciable (ver Figura 6 y 8).

A continuación y como contraposición a la situación anterior vamos a estudiar como de bien o mal se comporta nuestro algoritmo al aplicarlo sobre un segmento que corresponda a un sonido sordo. Se han tomado dos ejemplos correspondientes a los segmentos número 36 y 90 de la señal de voz, tal como se muestran en las Figuras 9 y 11 que aparecen a continuación. Del mismo modo que en el caso anterior se muestran los errores cometidos al reconstruir la señal y correspondientes a dichos segmentos (ver Figura 10 y 12).

Como resumen a todos los casos estudiados, podemos decir que tanto el cálculo de los parámetros  como de la excitación  se ha realizado de forma correcta y que es posible reconstruir la señal a partir de dichos parámetros de forma muy precisa.

 

 

Figura 5. Representación del segmento 22 correspondiente a un sonido sonoro.

 

 

Figura 6. Error cometido correspondiente al segmento 22.

 

 

Figura 7. Representación del segmento 87 correspondiente a un sonido sonoro.

 

 

Figura 8. Error cometido correspondiente al segmento 87.

 

 

Figura 9. Representación del segmento 36 correspondiente a un sonido sordo.

 

 

Figura 10. Error cometido correspondiente al segmento 36.

 

 

Figura 11. Representación del segmento 90 correspondiente a un sonido sordo.

 

 

Figura 12. Error cometido correspondiente al segmento 90.

 

 

Determinar los espectros de las señales

Tome varios segmentos sonoros de voz y determine los espectros de las señales correspondientes (Matlab dispone de la función fft que realiza la transformada discreta de Fourier). Obtenga para cada segmento el espectro de la respuesta impulso  del filtro , que se determina , teniendo en cuenta que en este caso  es la señal impulso unidad y que la respuesta impulso para muestras anteriores a la primera muestra del segmento vale 0. Calcule también el espectro de la excitación  de cada segmento. Realice lo mismo para varios segmentos sordos.

            A continuación aparece listado el código fuente correspondiente tanto a las funciones auxiliares como al programa principal desde donde se realizan las llamadas.

 

 

Fichero calc_espectro.m

 

function calc_espectro(vector)

%

%

% calculo de los valores para las frecuencias

w=1:60;

for i=1:60

   w(i)=(2*pi*(i-1))/120;

end

 

F=1:60;

for i=1:60

   F(i)=(8000*w(i))/(2*pi);

end

 

% representacion grafica del espectro

% se representa la energia para cada frecuencia

x=F;

y=abs(fft(vector));

y=y(1:60);

plot(x,y);  

 

 

Fichero pract2_2.m

 

% ejecucion siempre posterior a pract2_1

 

% inicializacion

h=1:length(s);

for i=1:length(s)

    h(i)=0;

end

 

% calcular la respuesta impulso

h(1)=1;

ak=aktotal(1:10);

for i=2:length(h)

    sumatorio=0.0;

    for k=1:p

        if ((i-k>0))

            sumatorio=ak(k)*h(i-k)+sumatorio;

        end

    end

    if (mod((i-1),120)==0)

        h(i)=sumatorio+1;

    else

        h(i)=sumatorio;

    end

    if ((mod(i,120)==0) & (i~=length(Gu)))

        z=((i/120)*10)+1;

        ak=aktotal(z:z+9);

    end

end

 

% representacion grafica del espectro de la señal

% del espectro de la respuesta impulso y del

% espectro de la señal de excitacion Gu

for i=1:numsegmento

    subplot(3,1,1);

    calc_espectro(seg(s,i));

    title(i);

    subplot(3,1,2);

    calc_espectro(seg(h,i));

    subplot(3,1,3);

    calc_espectro(seg(Gu,i));

    pause

end

 

 

            Con la función calc_espectro se realiza el cálculo del espectro asociado al vector que se le pasa como parámetro en la llamada a la función. De esta forma si lo se le pasa es el vector donde está almacenado un determinado segmento se calcula el espectro de la señal, si el vector almacena la respuesta impulso  se calcula el espectro correspondiente a la respuesta impulso y por último, si el vector contiene la excitación  de un segmento se calcula el espectro correspondiente a esa excitación. Esta función muestra, por tanto, la representación gráfica del espectro mostrando la energía correspondiente a cada frecuencia calculada anteriormente.

            Dentro del programa principal de nuestra práctica lo que se realiza es el cálculo de la respuesta impulso , según la fórmula expuesta anteriormente, y a continuación, se realiza una comparación entre el espectro de la señal, el espectro de la respuesta impulso  y el espectro de la señal de excitación . Como nota, mencionar el hecho de que previamente a la ejecución de este apartado debemos haber ejecutado el apartado anterior ya que es allí donde se realiza la lectura del fichero y el cálculo de la señal de excitación.

            Los resultados obtenidos en forma de gráficas tras la ejecución de nuestro programa se muestran a continuación en las Figuras 13, 14, 15 y 16. En las Figuras 13 y 14 se analizan los segmentos 22 y 87 que, tal como vimos en el apartado anterior, corresponden a sonidos sonoros. Por el contrario, en las Figuras 15 y 16 se analizan los segmentos 36 y 90 y que, tal como se pudo ver en el apartado anterior, corresponden a sonidos sordos.

            El análisis de los resultados y las conclusiones obtenidas a partir de los mismos se realiza en el siguiente apartado, donde al contestar a las preguntas formuladas, se explican las relaciones y características de los espectros de las señales obtenidos para cada uno de los segmentos examinados.

 

 

Figura 13. Comparativa entre el espectro de la señal, de la respuesta impulso y de la excitación correspondientes al segmento 22 y por tanto, a un sonido sonoro.

 

 

Figura 14. Comparativa entre el espectro de la señal, de la respuesta impulso y de la excitación correspondientes al segmento 87 y por tanto, a un sonido sonoro.

 

 

Figura 15. Comparativa entre el espectro de la señal, de la respuesta impulso y de la excitación correspondientes al segmento 36 y por tanto, a un sonido sordo.

 

 

Figura 16. Comparativa entre el espectro de la señal, de la respuesta impulso y de la excitación correspondientes al segmento 36 y por tanto, a un sonido sordo.

 

 

Preguntas

v     1. ¿Qué relación encuentra entre el espectro de la señal y los espectros de la respuesta impulso y la excitación?

Tras analizar los resultados obtenidos podemos decir que la relación existente consiste en que el espectro de la señal no es más que el espectro de la respuesta impulso añadido con el espectro de la excitación. De este modo, se puede observar que la onda generada en la respuesta impulso determina o influye decisivamente en la forma que tendrá la onda generada por el espectro de la señal. Dicho de otra forma cuando a una determinada frecuencia la energía del espectro de la respuesta impulso es grande la energía del espectro de la señal también es grande y viceversa. Si a este hecho se le añade que las subidas y bajadas que tenemos en el espectro de la señal de excitación se manifiestan también en el espectro de la señal, podemos concluir en que efectivamente al juntar los espectros de la respuesta impulso y de la excitación obtenemos el espectro de la señal.

           

v     2. ¿Qué diferencias encuentra entre los espectros de la señal, de la respuesta impulso y de la excitación para señales sonoras y sordas?

Cuando nos encontramos ante un sonido sonoro se puede ver como las zonas de mayor energía, tanto del espectro de la señal como del espectro de la respuesta impulso, se encuentran en las frecuencias bajas en torno a la zona comprendida de los 500 Hz. En contraposición, cuando nos encontramos ante un sonido sordo observamos como esta vez las zonas de mayor energía, de nuevo tanto del espectro de la señal como del espectro de la respuesta impulso, se encuentran localizadas en las frecuencias altas, alrededor de los 3000 Hz.

En cuanto al espectro de la señal de excitación vemos como en los sonidos sonoros, sobretodo en la Figura 14, es una señal formada por impulsos que se producen siempre a una determinada distancia que parece similar. Por el contrario, analizando los resultados obtenidos con los sonidos sordos, Figuras 15 y 16, observamos como esta vez el espectro de la señal de excitación no parece formado por impulsos que se repiten cada cierto tiempo, sino que estos parece más bien que aparecen de forma aleatoria según intervalos no definidos. Además, también parece que cuando se trata de sonidos sordos la energía de la señal de excitación es menor que cuando se trata de sonidos sonoros.

 

v     3. Determine cuales son los formantes para cada uno de los segmentos elegidos.

Teniendo en cuenta que los formantes hacen referencia a los picos más energéticos con solo mirar los resultados obtenidos podemos responder a la pregunta. De esta forma en la Figura 13 vemos que el pico más alto corresponde a la frecuencia de 400 Hz donde la energía toma un valor de 22’3, en la Figura 14 se encuentra en la frecuencia de 400 Hz con un valor de 12’6, en la Figura 15 se encuentra en la frecuencia de 3340 Hz con un valor de 9´1 y por último en la Figura 16 se encuentra en la frecuencia de 2930 Hz con un valor igual a 5´4.

 

 

Modelo simplificado de producción de voz

A diferencia de los apartados anteriores, ahora vamos a presentar un modelo LPC simplificado, en el cual lo que se simplifica es la excitación, que pasa a estar representada por un tren de impulsos con una periodicidad igual periodo de pitch para segmentos sonoros y por ruido aleatorio para segmentos sordos.

            Este modelo simplificado permite representar la señal de voz con un número muy bajo de bits/s y también manipular la señal de voz de forma más fácil, aunque la calidad de la señal de voz generada es más baja.

            Para sintetizar y manipular la señal de voz con el modelo LPC simplificado vamos a realizar los siguientes pasos:

v     1. Tome un fichero de voz del directorio fichvoz y aplicando el algoritmo desarrollado en la práctica 1 determine para cada segmento de voz si es sordo o sonoro y en este último caso el valor del periodo de pitch.

v     2. Determine el valor de los parámetros  para cada segmento de voz, tal y como se hizo en la sección anterior.

v     3. Determine la excitación para cada segmento de voz, tal y como se hizo en la sección anterior, y a continuación calcule la energía  de la excitación.

v     4. Genere al excitación simplificada para el filtro de cada segmento de la siguiente forma

Ø      a) Si el segmento es sonoro la excitación  tendrá la siguiente forma:  es un tren de impulsos unidad separados un número de muestras T igual al periodo de pitch del segmento y G se calcula  donde L es el número de impulsos unidad que caen en el segmento.

Ø      b) Si el segmento es sordo la excitación  tendrá la siguiente forma:  es una señal aleatoria de media cero con varianza unidad (Matlab dispone de una función randn para generar una señal de este tipo) y G se calcula  donde  es la energía de la señal  generada por la función randn de Matlab.

v     5. Una vez generada la excitación simplificada, obtenga la señal de voz correspondiente pasando dicha excitación por el filtro .

 

Para llevar a cabo este apartado es necesario utilizar las funciones generadas para la práctica 1 por lo que como las vamos a utilizar de nuevo y en algunos casos se han realizado cambios para adaptar los resultados a nuestras nuevas exigencias se ha decidido incluir en este documento su código fuente junto con el código fuente de las nuevas funciones implementadas y del programa principal donde se realizan las llamadas propias de este apartado. El listado de dichas funciones se detalla a continuación.

 

 

Fichero seg_p1.m

 

function v=seg(s,x)

% SEG segmenta el vector s

% devuelve el vector numero x de 240 muestras

% solapado con el anterior 120 muestras

a=1+(x-1)*120;

b=a+239;

v=s(a:b);

 

 

Fichero clipping.m

 

function seg=clipping(s)

% CLIPPING calcula el minimo de los valores

% maximos absolutos en las primeras y las

% ultimas 80 muestras del segmento.

% los valores del segmento que queden por

% debajo del valor obtenido se hacen cero

 

a1=s(1:80);

a2=s(161:240);

 

seg=s;

 

abs(a1);

abs(a2);

 

b1=max(a1);

b2=max(a2);

 

v=[b1 b2];

resul=min(v);

resul=resul*68.0/100.0;

 

for i=1:240

    if seg(i)>0

        if seg(i)<resul

            seg(i)=0;

        end

    else

        if seg(i)>-resul

            seg(i)=0;

        end

    end

end

 

 

Fichero autoco.m

 

function pitch=autoco(s)

% AUTOCO mediante "center clipping"

% calcula la energia y el umbral

% sobre el rango de 20 a 120 muestras

r=s.*s;

energia=sum(r);

umbral=energia*30.0/100.0;

 

R=1:120;

for i=1:120

    R(i)=0;

end

 

for k=20:120

    r1=s(k+1:240);

    r2=s(1:240-k);

   

    r3=r1.*r2;

   

    R(k)=sum(r3);

end

 

[maximo,pitch]=max(R);

 

if maximo<umbral

    pitch=0;   

end

 

 

Fichero sordo_sonoro.m

 

function v=sordo_sonoro(s,numsegmento);

% SORDO_SONORO determina si un segmento es sordo o es sonoro.

% numsegmento indica el numero de segmentos de 120 muestras

% posibles

% devuelve un vector v que contiene el periodo de pitch

v=1:numsegmento*120;

for i=1:numsegmento*120;

    v(i)=0;

end

 

for i=1:numsegmento-1

    segmento=seg_p1(s,i);

    segc=clipping(segmento);

    pitch=autoco(segc);

    z=1+(i-1)*120;

    for j=z:z+119

        v(j)=pitch;

    end

end

 

 

Fichero calcular_energia.m

 

function a=calcular_energia(s)

% CALCULAR_ENERGIA calcula la energia del

% segmento s de 120 muestras

sumatorio=0.0;

for n=1:120

    sumatorio=sumatorio+(s(n)*s(n));

end

a=sumatorio/120;

 

 

Fichero pract2_3.m

 

% abrir el fichero y reproducir

fich1=fopen('e:\facultad\pv\practica2\8k\euge0013.8k','r');

[ficheroentrada,num]=fread(fich1,inf,'int16');

 

% se eliminan los ceros del principio del fichero

% para eliminar posibles errores que se puedan producir

principiofichero=1;

p=10;

indice=1;

s=0;

for i=1:num

    if ((principiofichero==1) & (ficheroentrada(i)==0))    

        principiofichero=1;  

    else

        s(indice)=ficheroentrada(i);

        principiofichero=0;

        indice=indice+1;

    end

end

sound(s/max(s),8000);

numsegmento=floor(indice/120);

 

% determinamos si la señal de voz es sonora o sorda

% segun el algoritmo implementado en la practica 1

vectorpitch=sordo_sonoro(s,numsegmento);

 

% si el segmento tiene un pitch igual a cero

% diremos que el segmento es sordo

% en caso contrario se almacena el valor de pitch

segmentosordosonoro=0;

for i=1:numsegmento

    z=1+(i-1)*120;

    segmentosordosonoro(i)=vectorpitch(z);

end

 

 

% calcular coeficientes ak

for i=1:numsegmento

    if (i==1)

        aktotal=funcak(seg(s,i),p);

    else

        aktotal=[aktotal,funcak(seg(s,i),p)];

    end

end

 

% calcular excitacion Gu primer segmento

% y la energia Ee del primer segmento

Ee=0;

vectorcero=1:120;

for i=1:120

    vectorcero(i)=0;

end

temp=excitacion(seg(s,1),vectorcero,aktotal(1:10),p);

Gu=temp;

Ee(1)=calcular_energia(temp);

 

% calcular excitacion Gu del resto de segmentos

% y la energia Ee del resto de segmentos

for i=2:numsegmento

    z=((i-1)*10)+1;

    temp=excitacion(seg(s,i),seg(s,i-1),aktotal(z:z+9),p);

    Gu=[Gu,temp];

    Ee(i)=calcular_energia(temp);

end

 

% generar la excitacion simplificada

clear('Gusimplificada');

clear('G');

for i=1:numsegmento

 

    % segmento sordo

    if (segmentosordosonoro(i)==0)

        for j=1:120

            u(j)=randn;

        end

        Eu=calcular_energia(u);

        G=sqrt(Ee(i)/Eu);

        if (exist('Gusimplificada')==0)

            Gusimplificada=G*u;

        else

            Gusimplificada=[Gusimplificada,G*u];           

        end

 

    % segmento sonoro   

    else

        for j=1:120

            u(j)=0;

        end

        L=0;

        z=1;

        while (z<=120)

            u(z)=1;

            L=L+1;

            z=z+segmentosordosonoro(i);

        end

        G=sqrt(Ee(i)/L);

        if (exist('Gusimplificada')==0)

            Gusimplificada=G*u;

        else

            Gusimplificada=[Gusimplificada,G*u];           

        end

    end

end

 

% se genera la señal de voz a partir de la señal de

% excitacion simplificada

sreconstruida=1:length(s);

for i=1:length(s)

    sreconstruida(i)=0;

end

ak=aktotal(1:10);

for i=11:length(Gusimplificada)

    sumatorio=0.0;

    for k=1:p

        sumatorio=(ak(k)*sreconstruida(i-k))+sumatorio;

    end

    sreconstruida(i)=sumatorio+Gusimplificada(i);

    if ((mod(i,120)==0) & (i~=length(Gusimplificada)))

        z=((i/120)*10)+1;

        ak=aktotal(z:z+9);

    end

end

 

% calculo del error

for z=1:length(s)

  error(z)=s(z)-sreconstruida(z);

end

 

% representacion grafica de las señales

subplot(2,1,1);

plot(s);

title('SEÑAL ORIGINAL');

subplot(2,1,2);

plot(sreconstruida);

title('SEÑAL RECONSTRUIDA');

sound(sreconstruida/max(sreconstruida),8000);

pause

 

% representacion grafica segmento a segmento

for i=1:numsegmento

  subplot(2,1,1);

  plot(seg(s,i));

  title(i);

  subplot(2,1,2);

  plot(seg(sreconstruida,i));

  title('SEGMENTO RECONSTRUIDO');

  pause

  subplot(1,1,1);

  plot (seg(error,i));

  title('ERROR COMETIDO');

  pause

end

 

 

Las funciones correspondientes a los ficheros seg_p1.m, clipping.m y autoco.m no se van a comentar ya que al ser funciones propias de la práctica anterior ya fueron adecuadamente explicadas.

La función sonoro_sordo se encarga de calcular un vector en donde se almacena el patrón de pitch correspondiente al fichero de voz. Dicho vector tiene longitud igual a la longitud del fichero de voz original y contiene un valor igual a cero para indicar que nos encontramos ante un sonido sordo o distinto de cero para indicar que tenemos un sonido sonoro en cuyo caso el valor almacenado indica el periodo de pitch.

La función calcular_energia se encarga de calcular el valor para la energía de un determinado segmento de 120 muestras aplicando la fórmula vista en. Devuelve el valor de la energía del segmento pasado como argumento.

En el fichero pract2_3.m se encuentra la implementación de la práctica en sí tal y como vamos a detallar a continuación. Lo primero que hacemos es abrir el fichero de voz original, eliminar los ceros que puedan aparecer al principio para evitar posibles errores en la llamada a la función lpc, y a continuación reproducimos el fichero de voz. A continuación se determina si la señal de voz es sonora o sorda utilizando los algoritmos comentados anteriormente y para ello creamos un vector denominado segmentosordosonoro que va a almacenar el valor de pitch correspondiente a cada uno de los segmentos de 120 muestras del fichero de voz en el caso de que el segmento corresponda a un sonido sonoro y con un valor de cero en el caso de que el segmento corresponda a un sonido sordo. El siguiente paso consiste en calcular los parámetros  tal y como se hizo en el apartado anterior. De forma similar calcularíamos la señal de excitación  con la diferencia de que en este caso debemos calcular la energía correspondiente a cada uno de los segmentos mediante la función calcular_energia. A continuación se genera la excitación simplificada utilizando el algoritmo comentado anteriormente teniendo en cuenta que tenemos que hacer una distinción dependiendo de si el segmento es sordo o sonoro. Una vez que tenemos todos los parámetros calculados solo nos resta reconstruir la señal de voz a partir de los mismos, calcular el error y representar gráficamente la señal de voz original, la señal de voz reconstruida y el error.

Para este apartado se ha decidido estudiar el comportamiento de nuestro algoritmo utilizando el fichero de voz denominado euge0013.8k. Los resultados obtenidos se representan gráficamente en las figuras 17, 18, 19, 20 y 21 que se muestran a continuación.

 

 

Figura 17. Representación correspondiente al fichero de voz “euge0013.8k”.

Escuchar señal original.

Escuchar señal reconstruida.

 

 

Figura 18. Representación del segmento 22 correspondiente a un sonido sonoro.

 

 

Figura 19. Error cometido correspondiente al segmento 22.

 

 

Figura 20. Representación del segmento 36 correspondiente a un sonido sordo.

 

 

Figura 21. Error cometido correspondiente al segmento 36.

 

 

Analizando los resultados obtenidos en los gráficos anteriores vemos que en este caso si se produce una más que notable diferencia entre la señal de voz original y la señal de voz reconstruida. A diferencia del primer apartado de la práctica, en donde la reconstrucción de la señal daba como resultado una señal de voz prácticamente igual a la señal original, vemos que en este caso la diferencia tanto gráficamente como al reproducir la señal a través de los altavoces es muy grande. Es más, al reproducir la señal de voz reconstruida escuchamos al locutor con una voz “robotizada” o “metalizada”, además de que el volumen de la misma es ostensiblemente menor. El hecho de la diferencia entre las señales, concuerda además con los valores tan grandes obtenidos en el vector de error de las señales.

            Como conclusión podemos decir, por lo tanto, que al utilizar el modelo LPC simplificado de producción de voz obtenemos una señal de voz que requiere muy pocos bits/s pero a costa de la calidad de la voz, lo que hace que este método aunque pueda ser muy práctico en algunos casos, pueda no ser útil en algunas aplicaciones de voz que requieran una alta calidad en la señal de voz.

 

 

Manipulación de la señal de voz

El modelo simplificado de producción de voz nos permite manipular la señal de voz fácilmente. Tome un fichero de voz correspondiente a un locutor femenino, doble el periodo de pitch de los segmentos sonoros en el modelo de excitación simplificado y genere una nueva señal de voz. Haga lo mismo con un fichero de voz correspondiente a un locutor masculino, pero esta vez dividiendo por la mitad el valor del periodo de pitch de los segmentos sonoros. Tome un fichero de voz y ponga el mismo valor del periodo de pitch para todos los segmentos sonoros. ¿Qué ocurre en cada uno de los casos?

           

Para estudiar el caso correspondiente a un locutor femenino se ha utilizado el fichero de voz que se ha utilizado en la mayor parte de la práctica, a saber, “euge0013.8k”. En el caso en el que debemos estudiar un fichero de voz correspondiente a un locutor masculino hemos optado por utilizar el fichero de voz denominado tsge3270.8k.

            En el primero de los casos se ha doblado el periodo de pitch en los segmentos correspondientes a un sonido sonoro sencillamente modificando el código de forma simple (ver Figura 22). En el segundo de los casos se ha procedido de forma similar al caso anterior pero esta vez al tratarse de dividir entre dos el valor de pitch en los segmentos sonoros se ha utilizado la función floor de Matlab para garantizarnos que estamos utilizando valores enteros (ver Figura 23).

            Las conclusiones obtenidas al realizar estas modificaciones en los ficheros de voz no se han podido sacar simplemente viendo las gráficas obtenidas sino que en esta ocasión ha realmente reproducir la señal de voz reconstruida mediante la tarjeta de sonido. Tras realizar este paso se comprueba como la señal de voz modificada correspondiente al locutor masculino toma una entonación digamos “especial” ya que su tono de voz hace que se asemeje en gran medida a la entonación correspondiente a un locutor femenino. El caso contrario también se da pero esta vez quizás en menor grado y el cambio es menos perceptible o evidente.

 

            Por último se nos pide que asignemos un valor fijo para el periodo de pitch correspondiente a los sonidos sonoros. Esto es más fácil aún que en el caso anterior ya que ahora solamente necesitamos conocer cuando un segmento se sordo o sonoro, la información referente al periodo de pitch de los segmentos sonoros no va a hacernos falta en este caso. Se han realizado dos pruebas para este apartado. En una primera modificación hemos asignado un valor de 30 como periodo de pitch para los segmentos sonoros (ver Figura 24). En el segundo caso se ha optado por utilizar un valor de 60 (ver Figura 25). De forma similar a lo que pasaba anteriormente ahora no nos basta estudiar la representación gráfica para obtener conclusiones acerca de las modificaciones efectuadas sino que en este caso vuelve a ser necesario escuchar la señal de voz reconstruida para ver cuales son los resultados.

            Las conclusiones que podemos sacar tras escuchar los ficheros de voz generados es que la señal de voz se vuelve digamos “robotizada” y pierde un poco la “vitalidad” de la señal de voz original ya que el fichero de voz reconstruido parece un poco “plano”. Todas las palabras se dicen de una forma como marcadas por pasos o por un determinado ritmo (suponemos que en este caso el ritmo con el que se van marcando las palabras coincide con el pitch que hayamos elegido). También reseñar como la señal en la que se ha utilizado un pitch igual a 30 resulta muy chillona ya que al haber utilizado un valor de pitch bajo, el periodo con el que se va generando la onda es también pequeño. En la segunda prueba donde se ha utilizado un pitch con un valor de 60, la señal aunque sigue pareciendo “robotizada” se ajusta un poco más al timbre o al tono que tendría una señal de voz más común.

            En resumen, aunque la señal de voz obtenida es de baja calidad y parece sometida a un efecto de “robotización” es posible que sea muy útil en los sistemas en los que prime más la necesidad de emplear pocos bits/s antes que una alta calidad en la señal de voz, ya que en este caso recordamos que solamente sería necesario almacenar los parámetros  y una variable que indicase cuáles son los segmentos sonoros.

 

 

Figura 22. Representación correspondiente al fichero de voz “euge0013.8k” cuando se ha doblado el pitch de los segmentos sonoros.

Escuchar señal original.

Escuchar señal reconstruida.

 

 

Figura 23. Representación correspondiente al fichero de voz “tsge3270.8k” cuando se ha dividido por la mitad el pitch de los segmentos sonoros.

Escuchar señal original.

Escuchar señal reconstruida.

 

 

Figura 24. Representación correspondiente al fichero de voz “euge0013.8k” cuando todos los segmentos sonoros toman un pitch igual a 30.

Escuchar señal original.

Escuchar señal reconstruida.

 

 

Figura 25. Representación correspondiente al fichero de voz “euge0013.8k” cuando todos los segmentos sonoros toman un pitch igual a 60.

Escuchar señal original.

Escuchar señal reconstruida.

 

 

www.000webhost.com