{"id":2984,"date":"2021-08-13T12:26:19","date_gmt":"2021-08-13T12:26:19","guid":{"rendered":"https:\/\/blog.rastersoft.com\/?p=2984"},"modified":"2021-08-13T13:14:59","modified_gmt":"2021-08-13T13:14:59","slug":"daisy-daisy","status":"publish","type":"post","link":"https:\/\/blog.rastersoft.com\/?p=2984","title":{"rendered":"Daisy, Daisy&#8230;"},"content":{"rendered":"\n<p>Recientemente, <a rel=\"noreferrer noopener\" href=\"https:\/\/www.youtube.com\/channel\/UCmaEoq1zaakpdudbzgll-zw\" target=\"_blank\">Alva Majo, desarrollador de videojuegos indie<\/a> y youtuber, public\u00f3 un v\u00eddeo donde explicaba c\u00f3mo cre\u00f3 <a rel=\"noreferrer noopener\" href=\"https:\/\/5ro4.itch.io\/alvabot\" target=\"_blank\">Alvabot, un sintetizador de habla<\/a> que utilizaba muestras de su propia voz. Como, adem\u00e1s, hizo p\u00fablico el c\u00f3digo fuente y las muestras de voz, decid\u00ed que pod\u00eda ser divertido intentar llevarlo un poco m\u00e1s all\u00e1 y hacer que cantase. \u00a1Y lo he conseguido!<\/p>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/alvabot_canta-3.mp3\"><\/audio><\/figure>\n\n\n\n<p>S\u00ed, vale&#8230; el resultado no es exactamente <em>profesional<\/em>, pero para ser algo hecho en un par de d\u00edas, creo que no est\u00e1 mal.<\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/gitlab.com\/rastersoft\/cantabot\" target=\"_blank\">El c\u00f3digo y las muestras de <em>cantabot<\/em> est\u00e1n disponibles en mi repositorio GIT<\/a> bajo una licencia <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/MIT_License\" target=\"_blank\">MIT\/Expat<\/a> (que viene a ser equivalente al \u00abhaz lo que te de la gana\u00bb con la que distribuy\u00f3 Alva Majo su c\u00f3digo original). Tambi\u00e9n est\u00e1n disponibles las peque\u00f1as utilidades que us\u00e9 para reconstruir las muestras y adaptarlas para la tarea.<\/p>\n\n\n\n<p>El proceso fue algo alambicado, pero al final no tiene mucha ciencia. Obviamente, si hubiese querido conseguir mejores resultados tendr\u00eda que haber utilizado otras t\u00e9cnicas, pero la idea era hacer s\u00f3lo un peque\u00f1o divertimento.<\/p>\n\n\n\n<p>En primer lugar escrib\u00ed una peque\u00f1a herramienta en <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Python_(programming_language)\" target=\"_blank\">Python<\/a> (<em><a rel=\"noreferrer noopener\" href=\"https:\/\/gitlab.com\/rastersoft\/cantabot\/-\/blob\/master\/analizador.py\" target=\"_blank\">analizador.py<\/a><\/em>, disponible en el repositorio) que me permite ver la forma de onda de un fichero WAV, escoger un trozo entre dos puntos concretos, calcular la frecuencia de dicha onda, y cortar entre los m\u00e1ximos de dicho trozo (todo esto lo explicar\u00e9 mejor a continuaci\u00f3n). Gracias a que Python tiene m\u00f3dulos para todo, no necesit\u00e9 programar casi nada, sino que ha sido m\u00e1s una operaci\u00f3n \u00abde pegar cosas\u00bb.<\/p>\n\n\n\n<p>As\u00ed, tom\u00e9 los <em>samples<\/em> de las vocales y utilic\u00e9 la herramienta anterior para revisar la forma de onda de cada una (en este art\u00edculo denominar\u00e9 <em>sample<\/em> a cada fichero de audio con el sonido de una vocal o una consonante; y utilizar\u00e9 el t\u00e9rmino <em>muestra<\/em> para referirme a cada uno de los datos de sonido que hay dentro de cada fichero; esto es: cada \u00abn\u00famero\u00bb dentro del fichero .WAV ser\u00e1 una <em>muestra<\/em>).<\/p>\n\n\n\n<p>Aqu\u00ed vemos una ampliaci\u00f3n de la vocal A, tal y como se ve en la herramienta:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-10-40.png\" rel=\"lightbox-0\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"525\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-10-40-1024x525.png\" alt=\"\" class=\"wp-image-2987\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-10-40-1024x525.png 1024w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-10-40-300x154.png 300w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-10-40-768x394.png 768w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-10-40-1536x787.png 1536w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-10-40.png 1569w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Si nos fijamos, vemos que parece que hay cierta \u00abrepetici\u00f3n\u00bb. O sea: la onda no es \u00abaleatoria\u00bb, sino que parece que hay un bloque que se repite en el tiempo (como se puede apreciar por esos picos espaciados de manera regular). Es verdad que la amplitud (la altura) no es constante, pero eso es simplemente porque Alva es un ser humano, y por mucho empe\u00f1o que ponga es imposible que mantenga exactamente la misma intensidad durante toda la vocal, sino que inevitablemente subir\u00e1 y bajar\u00e1 un poco en el tiempo.<\/p>\n\n\n\n<p>Para verlo mejor, ampliemos un trozo:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-21-21-47.png\" rel=\"lightbox-1\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"527\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-21-21-47-1024x527.png\" alt=\"\" class=\"wp-image-3002\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-21-21-47-1024x527.png 1024w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-21-21-47-300x154.png 300w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-21-21-47-768x395.png 768w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-21-21-47-1536x791.png 1536w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-21-21-47.png 1577w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Aqu\u00ed ya se ve mucho mejor c\u00f3mo la vocal es, en realidad, un trocito de sonido que se repite una y otra vez. En esta imagen concreta lo vemos repetido cinco veces. Esto significa que si creamos un <em>sample<\/em> con s\u00f3lo ese trozo, podremos repetirlo en bucle y conseguir que el ordenador pronuncie una vocal durante todo el tiempo que queramos, sin que se noten cortes, ligaduras ni nada por el estilo. Esto es fundamental a la hora de cantar porque cada nota puede tener una duraci\u00f3n diferente a las dem\u00e1s, y son justo las vocales las que se \u00abestiran\u00bb en el tiempo para cubrir todo el tiempo que dura una nota.<\/p>\n\n\n\n<p>Aqu\u00ed es donde mi herramienta <em>analiza.py<\/em> me pide dos puntos en la gr\u00e1fica. El primero tiene que estar un poco ANTES de uno de los m\u00e1ximos, y el segundo un poco DESPU\u00c9S del siguiente m\u00e1ximo. Entonces, la herramienta busca hacia adelante el valor m\u00e1ximo local desde el primer punto, y hacia atr\u00e1s desde el segundo punto, para as\u00ed recortar con precisi\u00f3n el trozo peri\u00f3dico. Para la vocal A utilic\u00e9 1668 y 2023, marcados en rojo en la imagen, y que como vemos caen justo cerca de dos m\u00e1ximos consecutivos. El propio programa busca los m\u00e1ximos, los cuales est\u00e1n en 1697 y 2001.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-13-13-39-11.png\" rel=\"lightbox-2\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"277\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-13-13-39-11-1024x277.png\" alt=\"\" class=\"wp-image-3017\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-13-13-39-11-1024x277.png 1024w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-13-13-39-11-300x81.png 300w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-13-13-39-11-768x208.png 768w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-13-13-39-11-1536x415.png 1536w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-13-13-39-11.png 1561w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Lo segundo que hice fue calcular la frecuencia fundamental de cada vocal. Para los que no sepan a qu\u00e9 me refiero, la frecuencia fundamental determina la \u00abnota\u00bb en la que est\u00e1 sonando la vocal. Cuando mayor sea la frecuencia, m\u00e1s alta en la escala ser\u00e1 la nota. Al principio hice algunas pruebas con la <a rel=\"noreferrer noopener\" href=\"https:\/\/es.wikipedia.org\/wiki\/Transformada_de_Fourier\" target=\"_blank\">transformada de Fourier<\/a>, hasta que me di cuenta de que no necesitaba complicarlo tanto, pues simplemente con saber el n\u00famero de muestras que hay en el \u00abtrozo\u00bb repetitivo y la frecuencia de muestreo, ya puedo obtener la frecuencia fundamental del <em>sample<\/em>.<\/p>\n\n\n\n<p>As\u00ed, por ejemplo, si decidimos utilizar para la vocal A el bloque situado entre los picos de las muestras 1697 y 2001, vemos que hay un total de 304 muestras en \u00e9l, lo que significa que si dividimos la frecuencia de muestreo de este fichero .WAV (que es de 44100 muestras\/segundo) entre dicho valor, nos dar\u00e1 que la frecuencia a la que Alva pronunci\u00f3 la letra A es de 145 Hz.<\/p>\n\n\n\n<p>Repitiendo este proceso para las cinco vocales, sale que cada una fue pronunciada con estas frecuencias:<\/p>\n\n\n\n<p class=\"mycode\">vocal A: muestras 1697 a 2001, 145 Hz<br>vocal E: muestras 555 a 855, 147 Hz<br>vocal I: muestras 2968 a 3242, 161 Hz<br>vocal O: muestras 2246 a 2544, 148 Hz<br>vocal U: muestras 3027 a 3317, 152 Hz<\/p>\n\n\n\n<p>Esto demuestra que Alva Majo NO es un robot, pues no es capaz de afinar correctamente. Por eso cada vocal tiene una frecuencia diferente.<\/p>\n\n\n\n<figure class=\"wp-block-video meme\"><video height=\"196\" style=\"aspect-ratio: 196 \/ 196;\" width=\"196\" controls src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/02\/chiquito_jarl.mp4\"><\/video><\/figure>\n\n\n\n<p>Pero claro, para nosotros esto es un problema porque si queremos que el ordenador cante, necesitamos que las muestras est\u00e9n todas en la misma frecuencia. Si no, lo \u00fanico que conseguiremos es un ordenador que desafina.<\/p>\n\n\n\n<p>Afortunadamente, una vez que tenemos ya aislado el bloque peri\u00f3dico de cada vocal, ajustar su frecuencia es muy sencillo: s\u00f3lo necesitamos hacer que todas midan lo mismo (pues la frecuencia fundamental depende del tama\u00f1o del bloque y de la frecuencia de muestreo; como la frecuencia de muestreo tiene que ser la misma para todos los <em>samples<\/em>, tenemos que conseguir que el n\u00famero de muestras sea igual). Si calculamos la media de todas esas frecuencias, nos salen 150 Hz, as\u00ed que ajustaremos todas a ese valor para evitar tener que desplazarlas demasiado. Y si ahora dividimos la tasa de muestreo entre esa cifra, nos sale que cada bloque debe tener 44100\/150 = 294 muestras. Por supuesto, no se trata de a\u00f1adir, por ejemplo, ceros al final, porque entonces estar\u00edamos modificando la se\u00f1al. Lo que necesitamos es \u00abinventarnos\u00bb muestras en medio para estirarla si es demasiado corta, o \u00abtirar a la basura\u00bb muestras si es demasiado larga. Por supuesto, si a\u00f1adimos muestras \u00e9stas deben \u00abencajar\u00bb con las que las rodean; y si quitamos muestras, debemos hacerlo de manera \u00abrepartida\u00bb. Esto, como no, tiene un nombre: remuestreo o <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Sample-rate_conversion\" target=\"_blank\">cambio de tasa de muestreo<\/a>, y el m\u00f3dulo <em>scipy<\/em> incluye una funci\u00f3n llamada <em>resample()<\/em> que lo hace. As\u00ed que en la parte final de la herramienta hago una llamada a dicha funci\u00f3n para ajustar cada <em>sample<\/em> justo antes de grabarlo en disco.<\/p>\n\n\n\n<p>Para poder evaluar los resultados, podemos comparar el <em>antes<\/em>:<\/p>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/vocales-juntas-sin-ajustar.mp3\"><\/audio><\/figure>\n\n\n\n<p>con el <em>despu\u00e9s<\/em>:<\/p>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/vocales-juntas-ajustadas.mp3\"><\/audio><\/figure>\n\n\n\n<p>Ahora llega el momento de hacer lo mismo con las consonantes, pero esto es un poco m\u00e1s complicado, pues \u00e9stas no tienen por qu\u00e9 tener un patr\u00f3n (aunque algunas s\u00ed), por lo que ser\u00e1 dif\u00edcil calcular su frecuencia&#8230; o no, porque, afortunadamente, Alva grab\u00f3 todas las consonantes seguidas de todas las vocales. No tenemos s\u00f3lo el fonema &#8216;P&#8217;, sino que tambi\u00e9n tenemos los sonidos de &#8216;PA&#8217;, &#8216;PE&#8217;, &#8216;PI&#8217;, &#8216;PO&#8217; y &#8216;PU&#8217;, as\u00ed que podemos medir la frecuencia a la que pronunci\u00f3 la vocal y asumir que es la misma que la del fonema de la consonante. Luego s\u00f3lo tendremos que cortar justo en el punto donde termina la consonante y empieza la vocal, y tendremos el sonido puro de la consonante. Veamos un ejemplo con la s\u00edlaba \u00abDA\u00bb:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-54-12.png\" rel=\"lightbox-3\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"527\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-54-12-1024x527.png\" alt=\"\" class=\"wp-image-2998\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-54-12-1024x527.png 1024w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-54-12-300x154.png 300w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-54-12-768x395.png 768w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-54-12-1536x790.png 1536w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/Captura-de-pantalla-de-2021-08-12-16-54-12.png 1567w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Para hacer esto escrib\u00ed otra peque\u00f1a herramienta, <em><a rel=\"noreferrer noopener\" href=\"https:\/\/gitlab.com\/rastersoft\/cantabot\/-\/blob\/master\/cortar_consonantes.py\" target=\"_blank\">cortar_consonantes.py<\/a><\/em>, la cual carga un fichero .WAV, muestra su forma de onda para que podamos buscar dos muestras que delimiten un periodo de la vocal, y nos pide que tecleemos su posici\u00f3n. Con ellas calcula la frecuencia a la que est\u00e1 pronunciada y tambi\u00e9n cuanto tiene que estirar o encoger todo el fichero WAV para ajustarlo a los 150 Hz que decidimos que ser\u00eda nuestra frecuencia central.<\/p>\n\n\n\n<p>Una vez que est\u00e1 ajustada, nos pide el n\u00famero de muestra en la que realizar el corte para separar la consonante de la vocal. Como no es f\u00e1cil acertar, lo que hice es que, tras dar un punto de corte, reproduzca la consonante seguida de la vocal \u00abI\u00bb (para lo cual, utilizo los <em>samples<\/em> que gener\u00e9 antes). De esta manera, si se recorta demasiado poco y se cuela parte de la vocal original, sonar\u00e1 AIIIIIII en lugar de IIIIIII. As\u00ed podremos ir ajustando hasta encontrar el punto \u00f3ptimo de cada consonante. Cuando hayamos encontrado el punto exacto, simplemente pulsamos RETURN en lugar de meter un nuevo n\u00famero y el programa grabar\u00e1 el nuevo <em>sample<\/em> con s\u00f3lo la consonante, ya ajustada a 150 Hz.<\/p>\n\n\n\n<p>Algunas consonantes, pese a todo, son sonoras, lo que significa que SI est\u00e1n formadas por una zona repetitiva. En concreto, para la B, la M y la N utilic\u00e9 el mismo sistema que para las vocales, pues se entend\u00edan mucho mejor que extray\u00e9ndolas \u00abtal cual\u00bb de los <em>samples<\/em>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Haciendo que hable<\/h2>\n\n\n\n<p>Ahora que ya tenemos los sonidos vocales y consonantes aislados y a la misma frecuencia, podemos hacer una primera prueba que se limite a hablar. Para ello escrib\u00ed <em>hablar.py<\/em>, que generar\u00e1 un fichero <em>habla.wav<\/em> en el que pronunciar\u00e1 la frase que se le pase por la propia l\u00ednea de comandos.<\/p>\n\n\n\n<p>Lo primero que hace este programa es sustituir las letras por fonemas, de manera que no hace falta pensar en sonidos sino que podemos escribir directamente una frase. Adem\u00e1s, si alguna vocal tiene tilde la pronunciar\u00e1 a una frecuencia ligeramente superior, lo que permite simular la entonaci\u00f3n de las frases. En teor\u00eda se podr\u00eda hacer que fuese completamente autom\u00e1tico, y que si una palabra no tiene tilde, compruebe si acaba en <em>n<\/em>, <em>s<\/em> o <em>vocal<\/em> y, en base a ello, determine si es aguda o llana y ponga la tilde autom\u00e1ticamente, pero no me apeteci\u00f3 ponerme con ello, as\u00ed que hay que hacerlo <em>a mano<\/em>.<\/p>\n\n\n\n<p>Ejemplo: \u00abH\u00f3la, s\u00f3y cantab\u00f3t habl\u00e1ndo.\u00bb<\/p>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2021\/08\/habla-1.mp3\"><\/audio><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Y haciendo que cante<\/h2>\n\n\n\n<p>Y por \u00faltimo, est\u00e1 la herramienta final, <em>cantar.py<\/em>, que genera un fichero .WAV con una canci\u00f3n generada con las muestras.<\/p>\n\n\n\n<p>El programa se compone de una clase con dos m\u00e9todos fundamentales: <em>interpreta()<\/em> y <em>pausa()<\/em>. Estos dos m\u00e9todos se deben ir llamando para <em>introducir<\/em> la partitura y la letra de la canci\u00f3n. Cada llamada <em>renderiza<\/em> los sonidos correspondientes, que se van a\u00f1adiendo a un buffer interno. Cuando la canci\u00f3n est\u00e1 lista, se llama al m\u00e9todo <em>grabar()<\/em>, que lo almacenar\u00e1 en disco en formato WAV con el nombre <em>canta.wav<\/em>.<\/p>\n\n\n\n<p>El m\u00e9todo <em>pausa<\/em> es el m\u00e1s sencillo, y simplemente recibe como par\u00e1metro un n\u00famero decimal con el n\u00famero de segundos de silencio que se deben a\u00f1adir al buffer. Permite a\u00f1adir silencios entre notas.<\/p>\n\n\n\n<p>El m\u00e9todo <em>interpreta<\/em> es el m\u00e1s complejo, y recibe tres par\u00e1metros:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Un entero con la octava de la nota a interpretar. Este valor estar\u00e1 entre 0 y 12 e indica el semitono concreto. La correspondencia exacta est\u00e1 en el c\u00f3digo fuente<\/li><li>Un valor decimal con la duraci\u00f3n en segundos de la nota.<\/li><li>Un string con los fonemas a cantar en dicha nota<\/li><\/ul>\n\n\n\n<p>Para simplificar la composici\u00f3n, se definen seis variables (<em>redonda, redondadot, blanca, blancadot, negra<\/em> y <em>negradot<\/em>) con las duraciones en segundos. Se establece la duraci\u00f3n de la redonda en 1,5 segundos, y el valor de la blanca y la negra queda definido autom\u00e1ticamente como la mitad y la cuarta parte de la redonda. A mayores, las duraciones con \u00abdot\u00bb son un 50% m\u00e1s que la correspondiente sin \u00abdot\u00bb. Adem\u00e1s, se definen tambi\u00e9n las variables <em>nota_XX<\/em>, con el valor de semitono correspondiente a cada nota (por ejemplo, <em>nota_sol<\/em> vale 5).<\/p>\n\n\n\n<p>Por otro lado, a la hora de decidir cuanto tiempo dura cada fonema de la nota se siguen las siguientes reglas:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Las consonantes durar\u00e1n lo que dure su <em>sample<\/em>, salvo las consonantes \u00absonoras\u00bb, que durar\u00e1n 0,2 segundos<\/li><li>Las vocales que no sean la \u00faltima durar\u00e1n 0,15 segundos<\/li><li>La \u00faltima vocal durar\u00e1 el tiempo necesario para completar la duraci\u00f3n de la nota<\/li><\/ul>\n\n\n\n<p>As\u00ed, la \u00faltima vocal durar\u00e1 realmente la duraci\u00f3n de la nota menos la duraci\u00f3n del resto de fonemas. Este valor se calcula autom\u00e1ticamente, lo que simplifica mucho meter una partitura.<\/p>\n\n\n\n<p>Dado que ya nos preocupamos antes de ajustar todos los <em>samples<\/em> para que estuviesen a 150 Hz, ahora lo \u00fanico que tenemos que hacer es ajustar la frecuencia de todos los fonemas a la necesaria para la nota. Y lo interesante es que para saber cuanto tenemos que ajustar la frecuencia, s\u00f3lo necesitamos elevar la ra\u00edz doceava de 2 al valor del semitono que le pasamos a la funci\u00f3n (por supuesto, tras restar 5, pues por convenio he decidido que los <em>samples<\/em> estar\u00e1n en SOL).<\/p>\n\n\n\n<p>\u00bfY por qu\u00e9 la ra\u00edz doceava de 2? <a rel=\"noreferrer noopener lightbox-video-0\" href=\"https:\/\/www.youtube.com\/watch?v=1Hqm0dYKUx4\" target=\"_blank\">En este v\u00eddeo de Minute Physics  lo explican muy bien<\/a>, pero para simplificar: como la frecuencia de una nota cualquiera tiene que ser la mitad de la frecuencia de la misma nota en la siguiente octava, y cada octava son doce semitonos, la \u00fanica manera de que esto encaje es que la frecuencia de cada semitono sea la frecuencia del semitono anterior multiplicado por la ra\u00edz doceava de dos. As\u00ed que si quiero hacer sonar un LA (semitono 7 como vemos en la tabla de arriba), necesito subir la frecuencia de los fonemas en dos semitonos, o sea, multiplicar dos veces por la ra\u00edz doceava de dos. En cambio, si quiero interpretar un MI, tengo que bajar la frecuencia en tres semitonos; o sea, dividir tres veces entre la ra\u00edz doceava de dos.<\/p>\n\n\n\n<p>\u00bfY c\u00f3mo cambiamos la frecuencia de los fonemas? Pues exactamente como vimos antes: interpolando para estirarlos o encogerlos. Si los estiramos, la frecuencia baja; y si los encojemos, la frecuencia sube. Por tanto, una vez hemos calculado el factor entre la frecuencia inicial y la final, s\u00f3lo tenemos que coger el n\u00famero de muestras que tiene cada fonema y multiplicarlo por dicho factor, obteniendo as\u00ed el nuevo n\u00famero de muestras que tiene que tener. Con ese n\u00famero llamamos a <em>interpolate()<\/em> para que haga su magia, y a\u00f1adimos las muestras al buffer.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recientemente, Alva Majo, desarrollador de videojuegos indie y youtuber, public\u00f3 un v\u00eddeo donde explicaba c\u00f3mo cre\u00f3 Alvabot, un sintetizador de habla que utilizaba muestras de su propia voz. Como, adem\u00e1s, hizo p\u00fablico el c\u00f3digo fuente y las muestras de voz, decid\u00ed que pod\u00eda ser divertido intentar llevarlo un poco m\u00e1s all\u00e1 y hacer que cantase. &hellip; <a href=\"https:\/\/blog.rastersoft.com\/?p=2984\" class=\"more-link\">Seguir leyendo <span class=\"screen-reader-text\">Daisy, Daisy&#8230;<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,5,7],"tags":[],"class_list":["post-2984","post","type-post","status-publish","format-standard","hentry","category-cacharreo","category-programacion","category-tutoriales"],"_links":{"self":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/2984","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2984"}],"version-history":[{"count":28,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/2984\/revisions"}],"predecessor-version":[{"id":3031,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/2984\/revisions\/3031"}],"wp:attachment":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2984"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2984"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2984"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}