<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Palmera blog &#187; Audio e Informática</title>
	<atom:link href="http://www.pablogindel.com/category/audio/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pablogindel.com</link>
	<description>robots, música, cosas raras con electricidad</description>
	<lastBuildDate>Wed, 31 Aug 2011 14:43:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2-alpha</generator>
		<item>
		<title>Composición Algorítmica</title>
		<link>http://www.pablogindel.com/2011/07/composicion-algoritmica/</link>
		<comments>http://www.pablogindel.com/2011/07/composicion-algoritmica/#comments</comments>
		<pubDate>Sun, 24 Jul 2011 00:43:40 +0000</pubDate>
		<dc:creator>pabloxid</dc:creator>
				<category><![CDATA[Audio e Informática]]></category>
		<category><![CDATA[Música]]></category>
		<category><![CDATA[algorithmic]]></category>
		<category><![CDATA[algorítmica]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[compás]]></category>
		<category><![CDATA[composer]]></category>
		<category><![CDATA[compositor]]></category>
		<category><![CDATA[estructura]]></category>
		<category><![CDATA[fractal]]></category>
		<category><![CDATA[generative]]></category>
		<category><![CDATA[grammars]]></category>
		<category><![CDATA[markov]]></category>
		<category><![CDATA[melódico]]></category>
		<category><![CDATA[métrica]]></category>
		<category><![CDATA[MIDI]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[musical]]></category>
		<category><![CDATA[pattern]]></category>
		<category><![CDATA[probabilidad]]></category>
		<category><![CDATA[probability]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[recursive]]></category>
		<category><![CDATA[rhythmic]]></category>

		<guid isPermaLink="false">http://www.pablogindel.com/?p=1506</guid>
		<description><![CDATA[Introducción. Sé muy poco sobre este tema, a pesar de lo mucho que me interesa. He estado haciendo programas &#8220;generativos&#8221; desde la época del QBASIC, a principios de los 90&#8242;s. En aquel entonces lo hacía con letras y palabras. Más tarde llegó el MIDI. En mi opinión el MIDI, como concepto, es algo trascendente, aunque [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: justify;">Introducción.</h4>
<p style="text-align: justify;">Sé muy poco sobre este tema, a pesar de lo mucho que me interesa. He estado haciendo programas &#8220;generativos&#8221; desde la época del <a href="http://es.wikipedia.org/wiki/QBASIC" target="_blank">QBASIC</a>, a principios de los 90&#8242;s. En aquel entonces lo hacía con letras y palabras. Más tarde llegó el <a href="http://es.wikipedia.org/wiki/MIDI" target="_blank">MIDI</a>. En mi opinión el MIDI, como concepto, es algo trascendente, aunque nunca logré explicar claramente la razón de mi entusiasmo -que se mantiene incluso en la actualidad, cuando el MIDI parece haber sido superado por nuevas tecnologías-, y eso que tuve a mi cargo la docencia de esa materia durante varios años en la <a href="http://web.ort.edu.uy/perfil.jsp?docenteId=1283" target="_blank">ORT</a>.</p>
<p style="text-align: justify;">Parte de esa explicación la encontraremos hoy aquí. Veremos que, en efecto, el MIDI tiene mucho que ver con lo que podríamos llamar la &#8220;modelización&#8221; de la música, y que ésta, a su vez, se vincula directamente con el tema central del presente artículo. La música, como fenómeno complejo que es, admite distintos <em><a href="http://en.wikipedia.org/wiki/High-_and_low-level" target="_blank">niveles de descripción</a>. </em>La idea de &#8220;niveles de descripción&#8221; está muy bien explicada en el capítulo X de un libro que me parece maravilloso: <em><a href="http://es.wikipedia.org/wiki/Douglas_Hofstadter" target="_blank">Gödel, Escher, Bach</a>&#8230;</em> de <em>Douglas Hofstadter</em> (no es un libro de música). El concepto que Hofstadter maneja allí, al que llama de esta manera, es de uso corriente en la teoría informática, pero se puede aplicar prácticamente a cualquier sistema. No voy a desarrollar aquí el concepto mismo, sino que me limitaré a poner algunos ejemplos de su aplicación al campo de la música, con los cuales va a quedar clara inmediatamente la idea.</p>
<p style="text-align: justify;">En la música, el nivel de descripción más <em>bajo</em> que tenemos es el del sonido mismo, nivel en el que podemos medir amplitudes, frecuencias, fases, aplicar análisis de <a href="http://es.wikipedia.org/wiki/An%C3%A1lisis_arm%C3%B3nico" target="_blank">Fourier</a>, etc. Está claro que este es el nivel más exacto de descripción posible, pero que, a su vez, no contiene ningún elemento &#8220;musical&#8221; propiamente dicho, es decir, no nos dice nada del estilo, del carácter, de la forma de una obra, ni tampoco de los ritmos, escalas o acordes que ella utiliza. Todos esos conceptos (estilo, carácter, ritmo, etc.) pertenecen a descripciones de <em>alto nivel</em>, algunas de más alto nivel que otras. El concepto de <em>nota</em> musical, por ejemplo, pertenece a un nivel de descripción más alto que el del sonido mismo, podría definirse como un sonido que empieza y que termina, es decir, cuya amplitud crece desde 0, se estabiliza en cierto nivel -la <em>intensidad</em> de la nota- y luego decrece nuevamente a 0, posee por ende una <em>duración</em>, y durante la misma mantiene una característica tonal definida, con una frecuencia que predomina sobre las otras -la <em>altura</em> del sonido, que además, no se mide en Hz, sino en Do, Re, Mi, Fa, etc., una escala logarítmica y cíclica de frecuencias-. De esta manera, creamos un concepto de alto nivel a partir de conceptos pertenecientes a una descripción de nivel inferior, y en adelante, podemos prescindir de las nociones de frecuencia, amplitud, etc., para hablar directamente de notas, duraciones, alturas, etc. Luego, a partir de estos nuevos conceptos, podemos definir otros de más alto nivel aun, como escala, acorde, ritmo, melodía, etc.</p>
<p style="text-align: justify;">Tonalidad, forma, estructura, cadencia, modulación, armonía, constituyen, a su vez, un nuevo nivel de conceptos que pueden definirse a partir de los anteriores como acorde, escala y ritmo, por ejemplo. Pero allí no termina la pirámide conceptual de la música. Es habitual, sobre todo en la crítica musical, utilizar conceptos de altísimo nivel, por ejemplo, decir que una música es triste, alegre, solemne, grave, mística, sublime, hermética, fresca, sutil, elegante, iconoclasta, emotiva, soberbia, ingenua, lúdica, etc., etc., etc. (la lista es interminable), o decir que tiene un sonido más pop, con toques de funk y reggae, pero con firmes raíces en el blues (para tener una idea cabal de lo disparatado que puede llegar a ser esto de los géneros, véase la siguente <a href="http://es.wikipedia.org/wiki/G%C3%A9neros_de_m%C3%BAsica_electr%C3%B3nica" target="_blank">página</a>). En un nivel no tan alto, pero igualmente opinable, se encuentran todas las consideraciones respecto a la interpretación musical, por ejemplo si un cantante hace un uso exagerado del <em>vibrato</em>, si un guitarrista es <em>virtuoso</em>, etc.</p>
<p style="text-align: justify;">Los niveles de descripción más altos de la música, son aquellos que podríamos llamar <em>conceptuales</em> y comprenden otra interminable lista de cosas ya muy lejanas al sonido mismo, desde la letra de una canción (desde el punto de vista semántico, no el de su sonido, que pertenece obviamente a un nivel mucho más bajo), el libro, la filosofía, doctrina o teoría en que está inspirada una obra, hasta la vestimenta o la actitud de los músicos en el escenario, su relación con el público, su extracción etárea, geográfica, social, etc. Todos estos elementos suelen estar presentes cuando se habla de música, y muchas veces se abusa de ellos y se los maneja imprudentemente, como si se tratara de conceptos de bajo nivel, evidentes, medibles e inmutables, como una frecuencia o una amplitud, lo cual me parece una aberración, pero eso ya es tema para otro artículo.</p>
<p style="text-align: justify;">Bien, volviendo al tema del MIDI, ¿en qué radica su trascendencia? El MIDI constituye una descripción de alto nivel de la música, pero sin embargo su nivel es más bajo que el de una partitura de notación musical tradicional. El MIDI no es, por supuesto, una descripción del sonido mismo, en términos de amplitud, frecuencia y fase, sino que se basa en el concepto recién visto de <em>nota</em>, al igual que la teoría musical clásica. El MIDI presenta un nivel de <a href="http://es.wikipedia.org/wiki/Abstracci%C3%B3n_(inform%C3%A1tica)" target="_blank">abstracción</a>¹ -para mi gusto- ideal, que permite describir la música en términos de <em>piano-roll</em> (rollo de pianola), es decir, como una gráfica de notas en función del tiempo, que admite alturas, comienzos, duraciones e intensidades arbitrarias para cualquier número de notas. Desde este punto de vista, el MIDI podría definirse como una &#8220;partitura de bajo nivel&#8221;.</p>
<p style="text-align: justify;">La partitura de notación musical estándar no es una descripción completa de la música, solamente establece en forma unívoca la secuencia de alturas de las notas, y brinda una descripción muy somera de su relación con el tiempo, siendo el intérprete en última instancia el que posee y aporta el resto de la información necesaria para convertir esa notación en música, a la hora de ejecutar. Una &#8220;secuencia&#8221; MIDI, por su parte, comparte con la notación tradicional el hecho de estar basada en notas, pero en cambio, ofrece una descripción muchísimo más completa del aspecto más olvidado de la <a href="http://en.wikipedia.org/wiki/Music_theory" target="_blank">teoría musical</a> tradicional (y de la propia música clásica europea): <strong>el ritmo</strong>. Por ejemplo, dos notas que en una partitura normal aparecen como iguales, pueden tener, en la ejecución real, distintas intensidades y distintas duraciones; el MIDI reflejaría sin problemas esa diferencia mientras que la partitura estándar no. (La partitura estándar realiza una abstracción que deja fuera esos detalles, manteniendo en cambio una descripción completa del aspecto tonal; esta predilección por las alturas tiñe a la propia teoría, como ya veremos, y juega -a mi juicio- un rol negativo en la comprensión del fenómeno musical mismo).</p>
<p style="text-align: justify;">El MIDI es, por otro lado, una manera de codificar la música electrónicamente. A principios de la década del 80 las computadoras pudieron manipular este tipo de información, grabar, reproducir, editar, modificar, componer (&#8220;secuenciar&#8221;), experimentar, y por qué no, generar música <a href="http://es.wikipedia.org/wiki/Algoritmo" target="_blank">algorítmicamente</a>. Actualmente las computadoras son capaces de trabajar con el sonido mismo, con las amplitudes, las frecuencias, las fases, logrando un control sin precedentes sobre la grabación musical desde el nivel más bajo, sin necesidad de recurrir a la abstracción del MIDI. Sin embargo, el MIDI como concepto sigue estando presente en los casos en que se trabaja con <a href="http://en.wikipedia.org/wiki/Sound_synthesis" target="_blank">sintetizadores</a> -virtuales o no-, y el software permite editar notas, arpegios, escalas, acordes, ritmos; aunque no se vea, el MIDI sigue estando allí. Aunque el resultado final de la cadena salga en forma de audio, el MIDI sigue formando parte de ella. En el caso de la <a href="http://en.wikipedia.org/wiki/Algorithmic_composition" target="_blank">composición algorítmica</a>, cuando el <em>modelo </em>de teoría musical que usamos está basado en notas (podría no estarlo, de hecho existe una buena cantidad de músicas imposibles de describir en términos de notas; no nos ocuparemos de ellas en el presente artículo), entonces ocurre esto mismo, lo que nuestro algoritmo está generando, en última instancia, puede representarse directamente como información MIDI.</p>
<p style="text-align: justify;">Es importante aclarar lo siguiente: resulta imposible disponer de un modelo o una teoría de la música que funcione en todos los niveles de descripción y se ajuste a todas las músicas existentes o posibles (a menudo se habla de <em>sistemas musicales</em>) e incluso que pueda explicar todos los elementos presentes en una sola obra, si vamos al caso. Asimismo, cuando hablamos de composición algorítmica, siempre vamos a estar hablando de niveles de descripción relativamente bajos de la música. Por ahora, la posibilidad de que un programa informático genere u opere con elementos conceptuales, semánticos o de un nivel de abstracción relativamente alto, se encuentra tan lejana como la de que una computadora piense o tenga sentimientos. (Esta aclaración puede resultar obvia, pero sé que a algunas personas les cuesta entender por qué nos fascinan los robots, por ejemplo, y esperan que un robot haga algo verdaderamente humano. De lo que se trata, en realidad, es de investigar, a través de la composición algorítmica, la <a href="http://en.wikipedia.org/wiki/Artificial_intelligence" target="_blank">inteligencia artificial</a>, o lo que sea, temas como <em>de qué está hecha la música</em>, y en definitiva, <em>de qué estamos hechos nosotros</em>). En este artículo nos centraremos en el nivel de descripción de la música que nos brinda el MIDI, aquel en el que podemos hablar de notas, intensidades, duraciones, alturas, ritmo, melodía, armonía, etc., pero está claro que este no es el único nivel posible, que no puede aplicarse a cualquier música, y que ni siquiera puede abarcar todos los aspectos de una sola obra, como dije antes. En particular, soy consciente de que el enfoque MIDI descuida un aspecto del sonido que es de enorme importancia a nivel sensible: el <strong>timbre</strong>, sin el cual mucha gente se encuentra perdida a la hora de escuchar.</p>
<p style="text-align: justify;">Como decía al principio, sé muy poco sobre composición algorítmica, he leído apenas por arriba algunas generalidades, escuchado sin mucha atención algunos ejemplos, probado sin mucho esmero algún que otro software y tomado nota sin mucho convencimiento de algún que otro algoritmo. Por lo tanto lo que voy a decir aquí carece de &#8220;rigor científico&#8221;, es más bien una serie de intuiciones que tengo al respecto. La primera de ellas es una observación que insinué más arriba, pero que voy plantear de lleno en este momento: la teoría musical tradicional, y por ende, también la gran mayoría de los artículos que pude encontrar sobre composición algorítmica, se basan en un modelo musical incompleto, en el que se le da mucha importancia al estudio de las <em>alturas </em>(escalas, acordes, armonía) pero que es muy pobre en su descripción del <em>ritmo</em>.</p>
<p style="text-align: justify;">No obstante, algunos <a href="http://en.wikipedia.org/wiki/Fred_Lerdahl" target="_blank">teóricos modernos</a> han profundizado en el <a href="http://www.eumus.edu.uy/docentes/jure/teoria/lerdahl/estructura_ritmica.html" target="_blank">estudio del ritmo</a>, devolviéndolo de alguna manera a su justo lugar dentro de la teoría musical, y no es casualidad que estos mismos autores también se hayan ocupado, en algunos casos, de temas como la relación entre <em>música y lenguaje</em> o entre <em>música y cognición</em>. En mi concepción, la música es esencialmente ritmo, la melodía puede verse como un concepto ampliado de ritmo (un ritmo <em>multidimensional</em>, y esto abarca, antes que las alturas, las ya mencionadas intensidades individuales de cada nota). El nivel de descripción en el que se habla de <em>frases </em>musicales, puede ser visto como una &#8220;melodía de melodías&#8221;, y los niveles armónico, formal, estructural, pueden ser vistos también como macro-melodías de <em>bloques</em> musicales, o de reglas que rigen esos bloques.</p>
<p style="text-align: justify;">Ahora bien, ¿qué importancia tiene todo esto, el modelo musical o el nombre que le pongamos a cada cosa? El problema, para mí, es que un modelo incompleto de la música, conduce a centrar la atención en aspectos irrelevantes, o que por sí solos carecen de sentido, tanto a la hora de analizar música como a la de intentar <em>emularla</em> por medios informáticos. Precisamente, intentar generar música con un software es una buena manera de advertir la limitación de nuestro modelo, y entender la necesidad de un modelo más profunfo, que parta de más abajo y llegue hasta más arriba -en materia de niveles-, y que explique ya no lo que vemos en una partitura, sino lo que realmente suena, la música misma.</p>
<p style="text-align: justify;">En esta última frase se encuentra el quid de la cuestión (qué expresión antigua, ¿eh?). Dijimos más arriba que la partitura tradicional &#8220;establece en forma unívoca la secuencia de alturas&#8221; pero en cambio, describe en forma pobre o directamente nula otros elementos que, sin embargo, están presentes en una <em>interpretación </em>-quiero decir, en la ejecución de la partitura-, y que no son triviales, dado que la alteración de estos elementos produce cambios radicales en la &#8220;musicalidad&#8221; del resultado final. Esto es muy fácil de comprobar: si ingresamos la información explícita de una partitura -mayormente las alturas de los sonidos y sus duraciones- en un programa de notación musical, y luego le pedimos al programa que nos haga un <em>preview</em> auditivo de dicha partitura, dependiendo del estilo de la música que se trate observaremos que, en el mejor de los casos, el resultado se parece a una mala ejecución de esa música, pero que también puede resultar una mala ejecución de otra música bastante distinta, o directamente algo que no es música en absoluto.</p>
<p style="text-align: justify;">Por alguna razón, existe una tendencia ingenua, simplista, a modelizar la música como lo que más claramente vemos en una partitura: la secuencia de alturas, prescindiendo de todo lo demás. Incluso el propio Hofstadter tiende a caer en este error cada vez que analiza una música, en su premiado libro (aunque talvez las obras de <a href="http://es.wikipedia.org/wiki/Johann_Sebastian_Bach" target="_blank">Bach</a> a las que se refiere allí, sean las que mejor se presten a este tipo de análisis). Lo que me interesa destacar es que me parece trivial concebir un sistema de composición como un simple método para obtener una secuencia de alturas. Una secuencia de alturas no determina prácticamente nada en música, no existen secuencias de alturas &#8220;musicales&#8221; y secuencias &#8220;no musicales&#8221;, ni tampoco secuencias más musicales que otras. Cualquier sucesión de alturas puede utilizarse para hacer música, más aun si esas alturas se desprenden de una <em><a href="http://es.wikipedia.org/wiki/Escala_diat%C3%B3nica" target="_blank">escala diatónica</a>.</em> Esa es precisamente la razón por la que, se presume, muchos compositores clásicos habrían recurrido de distintas formas al azar como herramienta compositiva, o por la que <a href="http://es.wikipedia.org/wiki/Hermeto_Pascoal" target="_blank">Hermeto Pascoal</a> practica una composición instantánea a partir de una secuencia de notas azarosa aportada por el público, o por la que, en definitiva, existen tantos sistemas de composición &#8220;algorítmicos&#8221;, que realmente funcionan, en el sentido de que es posible gracias a ellos componer una música nueva, con la intervención del hombre, pero que no son suficientes por sí solos para generar una pseudomúsica mínimamente interesante, es decir, no resuelven el principal problema de <em>emular</em> electrónicamente un comportamiento musical (no está claro, por supuesto, que sea ése el objetivo que se proponen, pero sí el mio).</p>
<p style="text-align: justify;">En síntesis, considero que concentrarse en sintetizar secuencias de alturas es perder el tiempo, así como lo es analizar la música exclusivamente desde esa perspectiva, o con un énfasis exagerado en ese aspecto. No dudo que la melodía es un elemento sobresaliente en la música, y que merece un estudio detenido y toda nuestra atención, el problema es que el modelo ingenuo de melodía al que se suele recurrir es estéril. Está claro que abstraer la secuencia de alturas <em>per se </em>no conduce a nada, es básicamente un error. Antes bien, nuestro modelo musical debe partir del ritmo. Es imposible explicar la melodía sin recurrir al ritmo, en cambio sí es posible explicar incluso una secuencia de alturas como un fenómeno rítmico. Esta es una idea intuitiva que tengo, que no voy a poder desarrollar por completo aquí, pero que voy a intentar trasmitir a través de los ejemplos de mis propias investigaciones en <a href="http://en.wikipedia.org/wiki/Generative_music" target="_blank">música generativa</a>.</p>
<p style="text-align: justify;"> </p>
<h4 style="text-align: justify;">Mi propia experiencia.</h4>
<p style="text-align: justify;">En el 2008, no recuerdo bien en qué circunstancias, me propuse hacer un programa que generara música. La idea, que aun sigue vigente, en realidad, era crear algo así como un instrumento musical de alto nivel, es decir, algo que sirviera a los fines de la expresión pero que en su interacción, en lugar de producir <em>notas</em> como un instrumento estándar, produjera <em>músicas. </em>Claro, en realidad ya existen múltiples dispositivos y softwares de este tipo, desde los viejos órganos con acompañamiento automático que, recuerdo, me atraían mucho cuando era chico, pero la idea era crear uno a mi entero gusto y satisfacción.</p>
<p style="text-align: justify;">Comencé a trabajar y pronto me dí cuenta de que el primer paso era generar patrones rítmicos, prescindiendo momentáneamente del tema de las alturas de las notas. Comprobé, sin embargo, que a su vez, para que haya ritmo deben haber distintas notas, distintos sonidos que contrasten entre sí. Al final terminé modelando un software que generaba comportamientos baterísticos, y lo llamé &#8220;Zappator&#8221;; <strong><a href="http://www.pablogindel.com/2009/08/el-zappator/" target="_blank">aquí</a></strong> está el artículo que en aquel momento le dediqué, y <strong><a href="http://www.pablogindel.com/applets/zappator.html" target="_blank">aquí</a></strong> está el programa mismo.</p>
<p style="text-align: justify;">Posteriormente, intenté seguir desarrollando el Zappator pero no llegué muy lejos. Prácticamente no volví a meterme en el tema de la música algorítmica, exceptuando, si se quiere, el caso de la <a href="http://www.youtube.com/watch?v=0O3bUluSemc" target="_blank">Pelota de los Dioses</a> y la danza del <a href="http://www.youtube.com/watch?v=RXG5YfQqeus" target="_blank">Robotito</a>. En el primero de esos casos no se trataba tanto de generar patrones musicales, sino de <em>mapear data</em> proveniente de sensores a parámetros del sonido, una de las técnicas clásicas de la composición algorítmica, cuando esa data en lugar de provenir de sensores proviene de <a href="http://es.wikipedia.org/wiki/Proceso_estoc%C3%A1stico" target="_blank">procesos estocásticos</a>, <a href="http://es.wikipedia.org/wiki/Aut%C3%B3mata_celular" target="_blank">autómatas celulares</a> y todo tipo de algoritmos matemáticos. Precisamente, en ocasión de trabajar en ese proyecto, volví a caer en la cuenta de que asignar secuencias &#8220;mágicas&#8221; de números obtenidos por el más bello algoritmo, o por el muestreo del más significativo fenómeno, a algún parámetro de relativo bajo nivel del sonido -las alturas y las duraciones de las notas, por ejemplo, o directamente la frecuencia de un oscilador o un filtro dentro de un algoritmo de síntesis- produce resultados muy interesantes, pero en ningún caso música, tal como yo la concibo. En LPDLD había una rutina generadora de música, en realidad, y eran los parámetros de esa rutina los que se veian afectados por los ejes del sensor, junto con algún parámetro directo del MIDI, típicamente el <em>pitchbend</em>. Pero la rutina generadora de música era bastante aleatoria y muy poco musical, aunque el resultado podía mejorar en cierta medida gracias a la &#8220;habilidad&#8221; (o la suerte) del ejecutante.</p>
<p style="text-align: justify;">El mes pasado, tuve la oportunidad de trabajar para la instalación Picidae Chorus, de <a href="http://www.tangibleinteraction.com/">Tangible Interaction</a>, que se estrenó el 8 de Julio en el <a href="http://en.wikipedia.org/wiki/Stanley_Park" target="_blank">Stanley Park</a>, con motivo del <a href="http://www.celebratevancouver125.ca/" target="_blank">125 aniversario</a> de la ciudad de Vancouver. Mi trabajo consistió en desarrollar el software que desde una <a href="http://arduino.cc/en/Main/ArduinoBoardMega2560" target="_blank">Arduino Mega 2560</a> controla a los 7 &#8220;woodpeckers&#8221; (pájaros carpinteros) que picotean rítmica y sincronizadamente sobre una madera sonora, cada uno en su árbol, y al hacerlo se alumbran con un <a href="http://macetech.com/blog/node/54" target="_blank">led RGB</a> y luego disminuyen lentamente su luminosidad. Estos pájaros generan en su conjunto una pseudomúsica, que va evolucionando lentamente, con patrones que ocasionalmente se repiten, voces que se contestan unas a otras, etc., como para dar la sensación de que hay una inteligencia en ellos.</p>
<p style="text-align: justify;">Este trabajo me dio la oportunidad de reflotar uno de los intentos fallidos que había ensayado en 2008, previos al Zappator: la <em>fractal_rhythm</em>. Se trataba de una rutina <a href="http://es.wikipedia.org/wiki/Recursi%C3%B3n" target="_blank">recursiva</a>, con la cual quería poner en práctica la idea de que ritmo, melodía y estructura podrían obedecer a las mismas reglas de generación. Era una idea atractiva y ambiciosa, pero en la práctica no había funcionado. Volví entonces a implementar esta rutina recursiva, pero ahora con reglas mucho más explícitas, y que pueden ser distintas para cada nivel de recursión. Esta vez sí tuve éxito, gracias además, a que las probabilidades de cada opción que el programa puede tomar en cada momento, se controlan fácilmente y de forma precisa con una rutina que vengo utilizando en otros proyectos, la <em>markov</em> (en honor a las <a href="http://es.wikipedia.org/wiki/Cadena_de_Markov" target="_blank">cadenas</a> de este señor).</p>
<p style="text-align: justify;">Veamos aquí una de las primeras pruebas que realicé antes de llegar a la versión final, utilizando la <a href="http://www.youtube.com/watch?v=6U3MrOgVE2g" target="_blank">garrafa</a> de brazos de disco duro que gentilmente me prestaron Daniel Argente y Marcos Umpiérrez, sus creadores.</p>
<p style="text-align: center;"><p><a href="http://www.pablogindel.com/2011/07/composicion-algoritmica/"><em>Pinche aquí para ver el vídeo</em></a></p></p>
<p style="text-align: justify;">Otras pruebas con la misma versión del software pueden verse aquí: <a href="http://www.youtube.com/watch?v=JINSk-5as8I" target="_blank">[1]</a> <a href="http://www.youtube.com/watch?v=B0RDFAmfjSo" target="_blank">[2]</a> <a href="http://www.youtube.com/watch?v=RXi0EoXCYP0" target="_blank">[3]</a>.</p>
<p style="text-align: justify;">Expliquemos brevemente cómo funciona esto. El software de control alojado en la Arduino, consta fundamentalmente de 2 módulos: por un lado el <em>generador</em> y por otro lado el <em>reproductor</em>. El <em>generador</em> se encarga de crear los <em>patterns</em> musicales, a demanda, colocándolos en un gran <em><a href="http://en.wikipedia.org/wiki/Data_buffer" target="_blank">buffer</a></em> con capacidad para 384 divisiones rítmicas en total. El <em>reproductor</em> se encarga de traducir esa información a los distintos periféricos (<a href="http://www.sparkfun.com/products/10391" target="_blank">solenoides</a>, luces RGB, salida MIDI) en tiempo real.</p>
<p style="text-align: justify;">Una capa de nivel superior que podríamos llamar el <em>programador</em> se encarga de decidir cuándo, con qué parámetros y en qué región del <em>buffer</em> generar, y cuándo, qué, y con qué parámetros, reproducir. Este módulo es el responsable de la lenta “evolución” de los estilos musicales, los cambios de tempo, de métrica, etc., la repetición de <em>patterns</em> y las paráfrasis (<em>patterns</em> que se repiten pero con leves cambios). Para esto último, el <em>programador</em> llama ocasionalmente a unas subrutinas denominadas <em>plugins</em>, que producen transformaciones sobre los <em>patterns</em> actualmente almacenados, por ejemplo “cambiar alturas”, “quitar notas”, “agregar notas”, etc. El <em>programador</em> es entonces responsable de la macro-estructura musical. (En la versión de los videos, esta capa no está implementada aun, y en su lugar hay un tosco programador que cambia bruscamente los parámetros cada entre 3 a 8 compases, generando la sensación de que la música se va del tiempo, y jamás repite un <em>pattern</em> sino que siempre genera uno nuevo; pero más abajo tendremos un <em>render</em> de 8 minutos de audio generados con la última versión de este software, en la que sí está implementado el <em>programador</em>).</p>
<p style="text-align: justify;">Existe tambíén una capa de bajo nivel, gobernada por una <a href="http://es.wikipedia.org/wiki/Interrupci%C3%B3n" target="_blank">interrupción</a> asociada con un <em><a href="http://extremeelectronics.co.in/avr-tutorials/avr-timers-an-introduction/" target="_blank">timer</a></em>, que gestiona la temporización necesaria para los solenoides y las luces. Los solenoides necesitan un tiempo de <em>sustain</em> de aproximadamente 50ms y las luces necesitan atención permanente para producir el efecto de fade-out. Esta capa no tiene nada que ver con la música, pero gracias a ella el hardware puede ser controlado con la misma Arduino, sin interferir con la reproducción musical <em>real-time</em>, cuyos tiempos tienen que ser exactos.</p>
<p style="text-align: justify;">De todos estos módulos, el <em>generador</em> es por supuesto el más complejo. Su funcionamiento se basa en la rutina recursiva antes mencionada, que va recorriendo la línea de tiempo, y a cada paso tiene la opción de colocar una nota, colocar un silencio, o subdividir, o sea generar un nuevo nivel de recursión. La subdivisión puede ser en 2, 3, o 4 partes iguales, o incluso en patrones métricos predefinidos, como por ejemplo el 3-3-2. Esta estructura de <a href="http://es.wikipedia.org/wiki/%C3%81rbol_(inform%C3%A1tica)" target="_blank">árbol</a> básica, está condicionada por una cantidad de reglas definidas, las cuales establecen la <a href="http://es.wikipedia.org/wiki/Probabilidad" target="_blank">probabilidad</a> de que ocurra una u otra de estas opciones, dependiendo del nivel de recursión en que se esté, de la ubicación temporal, de la duración de la nota anterior, etc., etc. A este conjunto de &#8220;reglas rítmicas&#8221;, se suman las &#8220;reglas melódicas&#8221;, es decir, una vez que se establece que en determinado punto va un sonido y se conoce su duración, hay otro conjunto de reglas para determinar la altura de ese sonido y su intensidad (<em>velocity</em> MIDI). Estas nuevas reglas también utilizan probabilidades controladas, que dependen del lugar que ocupe la nota en la métrica, de su duración, y de las propiedades de las notas anteriores, entre otras cosas.</p>
<p style="text-align: justify;">A su vez, todas estas reglas poseen parámetros globales ajustables desde el <em>programador</em>, por ejemplo: coeficiente de silencio, coeficiente para cada uno de los tipos de subdivisión, rango de alturas restringido, etc., etc. Combinando todos estos parámetros, más la propia medida del pattern y el tempo global, es posible generar una amplia gama de comportamientos, que van desde un simple tren de <a href="http://es.wikipedia.org/wiki/Negra" target="_blank">negras</a>, a sobrecargados e intrincados ritmos, desde una nota única que se repite, a escalas que suben y bajan. De esta manera, podríamos implementar varios de estos generadores trabajando simultáneamente, asignados a distintos timbres, con distintas pautas de comportamiento y distintas <a href="http://es.wikipedia.org/wiki/Tesitura" target="_blank">tesituras</a>, es decir, una verdadera &#8220;orquesta&#8221; algorítmica. Para realizar esta prueba sería necesario antes que nada portar el programa a <a href="http://processing.org/" target="_blank">Processing</a>, porque el Arduino no tiene suficientes recursos para esto.</p>
<p style="text-align: justify;">Como ya dijimos, en los 4 videos anteriores no existe la capa de alto nivel encargada de darle cierta &#8220;forma&#8221; al material. El concepto de &#8220;melodía&#8221; que maneja el programa es en realidad un concepto rítmico, es decir, considera el conjunto de notas -que en este caso es de 7 notas- como un conjunto ordenado de &#8220;sonidos contrastantes con los que generar un ritmo&#8221;,  sin preocuparse en absoluto de las relaciones armónicas entre las notas. (En este caso los intevalos entre las notas sucesivas son de 5as., para las 7 notas que salen del módulo MIDI, pero a su vez esas 7 notas están mapeadas sobre las 4 notas de la garrafa, cuyas alturas son poco definidas, y prácticamente aleatorias). En el siguiente ejemplo escucharemos un audio de 8 minutos aprox., usando la salida MIDI con un timbre de piano, obtenido con la última versión del programa. En este caso, las notas son 12 y corresponden a una <a href="http://es.wikipedia.org/wiki/Escala_crom%C3%A1tica" target="_blank">escala cromática</a>.</p>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">Como podemos oir, el programa sigue sin saber nada de intervalos ni de armonía. Su concepto de melodía consiste en gravitar en torno a una altura y aplicar <a href="http://fr.wikipedia.org/wiki/Seconde_(musique)" target="_blank">grado conjunto</a> (que en este caso resulta ser siempre un semitono) o saltos mayores dependiendo de la articulación rítmica. Sabe, por ejemplo, la dirección melódica, y tiene reglas que le indican cuándo conservarla y cuándo invertirla. Las reglas melódicas en realidad son muy básicas, porque, en efecto, la aplicación para la que fue concebido era meramente percusiva. El algoritmo no maneja duraciones de notas, por ejemplo, sí puntos de comienzo, por supuesto, y también <em>acentuaciones</em> (intensidades individuales de cada nota) lo cual es importante. El paso para dotarlo de noción armónica es simplemente restringir a escalas o arpegios predefinidos el subconjunto de notas con que puede operar en cada compás o fragmento de compás, y, con un grado aun mayor de sofisticación, establecer un subconjunto más restringido para tiempos fuertes o partes fuertes del tiempo, y otro más amplio para tiempos débiles o partes débiles del tiempo.</p>
<p style="text-align: justify;">Obsérvese la acción del <em>programador</em>. Aquí sí podemos hablar de una capa de nivel superior que se encarga de administrar los patterns y repetirlos ocasionalmente, total o parcialmente, textualmente o con pequeñas modificaciones. En la práctica, el programa trabaja sobre un buffer de 4 compases, donde ocasionalmente sustituye cierto sector por un material completamente nuevo, otras veces transforma levemente lo que está actualmente almacenado en un sector, y otras veces simplemente ejecuta al azar alguno de los sectores. Los &#8220;sectores&#8221; normalmente son compases, pero puede ocurrir que sean fragmentos de compás, cuando, por ejemplo, un material fue generado en 4/4 y a la hora de ejecutarlo o modificarlo, la métrica puede haber pasado a 2/4 o a 3/4, o a la inversa, entonces ocasionalmente se forman combinaciones parciales de <em>patterns</em>, muy interesantes.</p>
<p style="text-align: justify;">El resultado de todo esto es que se generan estructuras parecidas a las de la música normal, tipo AABA&#8217;CBC&#8217;ADD&#8217;CDB&#8217;EC etc. Esta capa de macroestructura es lo que estaba faltando para que la pseudomúsica tuviera &#8220;forma&#8221;, pero comprobé que no hace falta que las estructuras sean simétricas, geométricas, ni con ninguna forma especial, sino que basta con esa simple cadena levemente aleatoria para obtener un resultado bastante &#8220;musical&#8221;, muy distinto de lo que se oye en los anteriores videos. Con respecto a los <em>plugins</em> que transforman el material, actualmente hay uno solo, pero ya tengo en mente muchísimos más, que emularían los recursos clásicos de la composición (paráfrasis, inversión, espejo, desplazamiento rítmico, transposición, expansión-compresión temporal, etc., etc.).</p>
<p style="text-align: right;">P.G., 26/7/2011</p>
<p style="text-align: right;">Revisión e ilustraciones de Alvaro Cassinelli</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pablogindel.com/2011/07/composicion-algoritmica/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Reconocimiento de voz en SAMSA</title>
		<link>http://www.pablogindel.com/2010/03/reconocimiento-de-voz-novedades-de-samsa-2/</link>
		<comments>http://www.pablogindel.com/2010/03/reconocimiento-de-voz-novedades-de-samsa-2/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 02:38:08 +0000</pubDate>
		<dc:creator>pabloxid</dc:creator>
				<category><![CDATA[Artículos técnicos, etc.]]></category>
		<category><![CDATA[Audio e Informática]]></category>
		<category><![CDATA[ANN]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[artificial neural network]]></category>
		<category><![CDATA[atmega128]]></category>
		<category><![CDATA[atmel]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[backpropagation]]></category>
		<category><![CDATA[gradient descent]]></category>
		<category><![CDATA[hexapod]]></category>
		<category><![CDATA[hexápodo]]></category>
		<category><![CDATA[microcontroller]]></category>
		<category><![CDATA[montevideo]]></category>
		<category><![CDATA[neural network]]></category>
		<category><![CDATA[pablo gindel]]></category>
		<category><![CDATA[physical computing]]></category>
		<category><![CDATA[processing]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[reconocimiento de voz]]></category>
		<category><![CDATA[red neuronal]]></category>
		<category><![CDATA[robot]]></category>
		<category><![CDATA[robótica]]></category>
		<category><![CDATA[robotics]]></category>
		<category><![CDATA[robots]]></category>
		<category><![CDATA[SAMSA]]></category>
		<category><![CDATA[sigmoid]]></category>
		<category><![CDATA[speech recognition]]></category>
		<category><![CDATA[steepest descent]]></category>
		<category><![CDATA[TCFM]]></category>
		<category><![CDATA[training]]></category>
		<category><![CDATA[uruguay]]></category>
		<category><![CDATA[wiring]]></category>

		<guid isPermaLink="false">http://www.pablogindel.com/?p=548</guid>
		<description><![CDATA[  En setiembre del año pasado, luego de su presentación en el marco de los workshops del 6º Campeonato de Sumo Robótico, todavía no tenía muy claro qué hacer con SAMSA, hacia dónde orientar su programación. Finalmente decidí que SAMSA tenía que ser un robot capaz de un nivel más sofisticado de sensibilidad auditiva, ya [...]]]></description>
			<content:encoded><![CDATA[<h4><p><a href="http://www.pablogindel.com/2010/03/reconocimiento-de-voz-novedades-de-samsa-2/"><em>Pinche aquí para ver el vídeo</em></a></p></h4>
<p> </p>
<p style="TEXT-ALIGN: justify">En setiembre del año pasado, luego de su presentación en el marco de los workshops del <a href="http://www.pablogindel.com/2009/09/sexto-campeonato-uruguayo-de-sumo-robotico/" target="_blank">6º Campeonato de Sumo Robótico</a>, todavía no tenía muy claro qué hacer con SAMSA, hacia dónde orientar su programación.</p>
<p style="TEXT-ALIGN: justify">Finalmente decidí que SAMSA tenía que ser un robot capaz de un nivel más sofisticado de sensibilidad auditiva, ya que en mis robots anteriores había experimentado más que nada con diversos tipos de dispositivos ópticos (con mayor o menor suerte), y de emisores de sonido. Esto podría darme la excusa, por ejemplo, para desarrollar un sistema de reconocimiento del ritmo, que le permitiera al robot bailar al compás de la música (y de paso me serviría para el momentáneamente abandonado proyecto <a href="http://www.pablogindel.com/2009/08/el-zappator/" target="_blank">Zappator</a>). Por otro lado, me interesaba también experimentar con redes neuronales, ya que suponía que éstas podrían constituir una alternativa a tener que programar línea por línea todo el comportamiento de un robot.</p>
<p style="TEXT-ALIGN: justify">Tal como había publicado en la <a href="http://www.pablogindel.com/2009/09/documentacion-de-samsa-1ª-entrega/" target="_blank">1ª etrega de la documentación de SAMSA</a>, la distribución total de tareas del robot a cargo de un sólo y modesto ATmega128 (microcontrolador de 8bit/128KB/16MHz) dejaba, en lo que respecta al audio, tan sólo la posibilidad de medir la intensidad del sonido cada cierto lapso, y ni soñar siquiera con algún tipo de análisis de frecuencias.</p>
<p style="TEXT-ALIGN: justify">La única alternativa parecía ser la de incluir un segundo procesador hardware, exclusivamente dedicado al procesamiento de sonido; pero eso implicaba agregar más componentes, en definitiva, exigirle más al ya sobrecargado sistema electro-mecánico del robot. Era mucho trabajo, y no me convencía.</p>
<p style="TEXT-ALIGN: justify">Se me ocurrió entonces otra solución: al mejor estilo “<a href="http://es.wikipedia.org/wiki/Sinclair_ZX81" target="_blank">ZX-81</a>”, el robot entraría temporalmente en un modo “escucha”, durante el cual no podría moverse, mostrar gráficos ni hacer ninguna otra cosa; utilizaría todos sus recursos para “analizar” el audio y actuar en consecuencia. La idea sería aumentar la frecuencia de las interrupciones (a 8KHz, de hecho), y sustituir la actual ISR (interrupt service routine), por otra que sólo procesara audio.</p>
<p style="TEXT-ALIGN: justify">Bien, y cuando decimos “procesar audio”, lo primero que nos viene a la mente es analizar frecuencias. ¿Por qué? Por muchísimas razones, talvez la más importante es que nuestro cerebro mismo percibe el sonido de esa manera. Como no soy para nada experto en <a href="http://es.wikipedia.org/wiki/Transformada_r%C3%A1pida_de_Fourier" target="_blank">FFT</a>, ni estaba seguro de que fuera realmente posible su implementación con estos escasos recursos de cómputo, busqué algún tipo de proceso más liviano, hasta que llegué a un algoritmo que yo mismo bauticé “<strong>filtros por correlation recursivos</strong>”, que ya debe estar inventado, con otro o con el mismo nombre, y que veremos en breve.</p>
<p style="TEXT-ALIGN: justify">Una vez implementados los 4 filtros de frecuencias fijas (o bandas, no me pregunten.. por cierto, es probable que toda la implementación esté plagada de errores de <a href="http://es.wikipedia.org/wiki/Aliasing" target="_blank">aliasing</a> y distorsiones de todo tipo; no obstante, contra todo pronóstico, funciona) mirando en la pantalla las gráficas que estos filtros producían, tuve la intuición de que era posible intentar un reconocimiento de palabras, y eso me iba a dar la excusa para “entrarle” a las redes neuronales.</p>
<p style="TEXT-ALIGN: justify">Pasaron un poco más de 6 meses, durante los cuales primero desarrollé la herramienta de diseño y entrenamiento de redes neuronales (<a href="http://www.pablogindel.com/2009/12/palmer-neural-networks/" target="_blank">Palmer Neural Networks</a>), pero después, al momento de usarla, me daba cuenta de que faltaba algo y no podía avanzar, estaba bloqueado. Por un lado no disponía de mucho tiempo para pensar en esta idea, y por otro lado había empezado a dudar de que fuera posible cumplir con el objetivo. Finalmente a fines de febrero de este año, comencé a dedicarle horas al proyecto, hasta que llegué a este resultado, que dista de ser ideal, pero que nos ilustra claramente qué podemos esperar y qué no, de un sistema con estas características.</p>
<p style="TEXT-ALIGN: justify">Los invito a compartir un viaje por la arquitectura interna de un sistema de reconocimiento de palabras implementado íntegramente en un microcontrolador ATmega128.</p>
<p style="TEXT-ALIGN: justify"> </p>
<p style="TEXT-ALIGN: justify"><span style="color: #000000;"><strong>Siguiente sección &#8211;&gt; </strong><a href="http://www.pablogindel.com/informacion/Reconocimiento-de-voz/" target="_self"><strong>Reconocimiento de voz en un ATmega128</strong></a></span></p>
<p style="TEXT-ALIGN: justify"><span style="color: #000000;"> </span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.pablogindel.com/2010/03/reconocimiento-de-voz-novedades-de-samsa-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Síntesis Modular con Processing</title>
		<link>http://www.pablogindel.com/2010/01/sintesis-modular-con-processing/</link>
		<comments>http://www.pablogindel.com/2010/01/sintesis-modular-con-processing/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 00:08:28 +0000</pubDate>
		<dc:creator>pabloxid</dc:creator>
				<category><![CDATA[Audio e Informática]]></category>
		<category><![CDATA[Música]]></category>
		<category><![CDATA[AM]]></category>
		<category><![CDATA[chebyshev]]></category>
		<category><![CDATA[convolution]]></category>
		<category><![CDATA[DSP]]></category>
		<category><![CDATA[envelope]]></category>
		<category><![CDATA[envolvente]]></category>
		<category><![CDATA[FFT]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[filtro]]></category>
		<category><![CDATA[FM]]></category>
		<category><![CDATA[fourier]]></category>
		<category><![CDATA[IIR]]></category>
		<category><![CDATA[javasound]]></category>
		<category><![CDATA[MIDI]]></category>
		<category><![CDATA[minim]]></category>
		<category><![CDATA[modular]]></category>
		<category><![CDATA[oscilador]]></category>
		<category><![CDATA[oscillator]]></category>
		<category><![CDATA[processing]]></category>
		<category><![CDATA[síntesis]]></category>
		<category><![CDATA[synth]]></category>
		<category><![CDATA[synthesis]]></category>

		<guid isPermaLink="false">http://www.pablogindel.com/?p=276</guid>
		<description><![CDATA[Introducción. Buscando una herramienta para programar y experimentar con audio, efectos y síntesis, decidí probar la biblioteca Minim de Processing. Existen muchos entornos informáticos interesantes para diseñar sonido, algunos son gráficos, otros son de escribir código, algunos son libres, otros son pagos; cito algunos ejemplos: Reaktor, Max-MSP, PureData, SynthEdit, SynthMaker, JSyn, Csound, SuperCollider, ChucK. Dentro [...]]]></description>
			<content:encoded><![CDATA[<h4><span style="color: #000000;">Introducción.</span></h4>
<p style="TEXT-ALIGN: justify">Buscando una herramienta para programar y experimentar con audio, efectos y síntesis, decidí probar la biblioteca <a href="http://code.compartmental.net/tools/minim/" target="_blank">Minim</a> de Processing. Existen muchos entornos informáticos interesantes para diseñar sonido, algunos son gráficos, otros son de escribir código, algunos son libres, otros son pagos; cito algunos ejemplos: Reaktor, Max-MSP, PureData, SynthEdit, SynthMaker, JSyn, Csound, SuperCollider, ChucK.<span id="more-276"></span></p>
<p style="TEXT-ALIGN: justify">Dentro de <a href="http://processing.org/" target="_blank">Processing</a>, existen varias bibliotecas para manejar sonido, entre ellas: Ess, Sonia y Minim, siendo esta última la que viene con la distribución oficial del producto. Rápidamente, repasemos las principales ventajas e inconvenientes -a mi modesto entender- de Minim:</p>
<ul style="TEXT-ALIGN: justify">
<li>Ventajas: es simple, transparente, bastante bien documentada y Open Source.</li>
<li>Inconvenientes: utiliza <a href="http://java.sun.com/products/java-media/sound/" target="_self">Java Sound</a> para comunicarse con el hardware de audio.</li>
</ul>
<p style="TEXT-ALIGN: justify">Muchas de las bibliotecas de Processing son justamente &#8220;wrappers&#8221; de las funcionalidades de Java. Minim utiliza Java Sound para el audio I/O, partes de otras bibliotecas para otras tareas -como reproducir mp3, por ejemplo- pero también agrega cosas propias e interesantes, en materia de análisis, procesamiento y generación de sonido. A su vez, uno de los principales inconvenientes del sistema de audio de Java es que no soporta <a href="http://www.steinberg.net/en/company/steinberg_technology.html" target="_blank">ASIO</a>, que como todos sabemos, es la única manera de obtener baja<em> latencia</em>, al menos bajo Windows XP.</p>
<p style="TEXT-ALIGN: justify"><span style="color: #000000;"><strong>¿Cómo funciona la generación de sonido a nivel de software?</strong></span></p>
<p style="TEXT-ALIGN: justify">El audio digital, a nivel del software, se maneja en <em>buffers</em>. Un buffer es un conjunto de muestras -por ejemplo, 1024 muestras- que se envían o se reciben en bloque hacia o desde el hardware. Mientras la tarjeta de audio reproduce esas 1024 muestras (lo que le llevará 23ms, si el muestreo es de 44,1KHz), el programa tiene tiempo de calcular el bloque siguiente. Cuanto más grande sea el buffer, o sea cuantas más muestras contenga, mayor será la latencia de la que hablábamos en el párrafo anterior (más información sobre buffers y latencia <a href="http://www.pablogindel.com/2009/07/manual-de-audio-2008/">aqui</a>).</p>
<p style="TEXT-ALIGN: justify">En Minim, la clase <a href="http://code.compartmental.net/tools/minim/manual-oscillator/" target="_blank">Oscillator</a> es la base de los generadores de sonido. Cuando se llama al método &#8220;<em>generate&#8221;</em>, este &#8220;llena&#8221; un buffer con una forma de onda calculada de alguna manera, por ejemplo con la función trigonométrica seno.</p>
<p style="TEXT-ALIGN: justify">Una consecuencia interesante de esta naturaleza de Minim, es que si nosotros intentamos modificar un parámetro de la onda que se está generando -por ejemplo su amplitud o su frecuencia- desde el módulo principal (la Draw() de Processing) ya sea a partir de un control externo o de una función prefijada, los cambios se van a manifestar de a &#8220;saltos&#8221; equivalentes a la duración del buffer (23ms, en el ejemplo que veíamos). Esto nos impide hacer un cambio gradual y continuo de cierto parámetro, por ejemplo una <a href="http://es.wikipedia.org/wiki/Envolvente_ac%C3%BAstico" target="_blank">envolvente de amplitud</a>. Para lograr este tipo de control, necesitamos implementar otro &#8220;Oscillator&#8221; que genere la señal de control, y que el primer &#8220;Oscillator&#8221; consulte a esa señal al calcular cada muestra que pone en el buffer.</p>
<p style="TEXT-ALIGN: justify">Aplicando esta idea a diversos módulos de la biblioteca, e implementando algunos módulos nuevos, surgió la <strong>Minim 2.02 PE</strong> (palmer edition), con la cual podemos hacer una modesta síntesis modular, que paso a describir y ejemplificar en la página a continuación.</p>
<h4 style="TEXT-ALIGN: justify"><span style="color: #000000;"> </span></h4>
<p style="TEXT-ALIGN: justify"><span style="color: #000000;"><strong>Siguiente sección &#8211;&gt; </strong><a href="http://www.pablogindel.com/informacion/minim-2-02-palmer-edition/" target="_self"><strong>Minim 2.02 Palmer Edition</strong></a></span></p>
<p style="TEXT-ALIGN: justify"><span style="color: #000000;"> </span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.pablogindel.com/2010/01/sintesis-modular-con-processing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Palmer Neural Networks</title>
		<link>http://www.pablogindel.com/2009/12/palmer-neural-networks/</link>
		<comments>http://www.pablogindel.com/2009/12/palmer-neural-networks/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 02:17:44 +0000</pubDate>
		<dc:creator>pabloxid</dc:creator>
				<category><![CDATA[Artículos técnicos, etc.]]></category>
		<category><![CDATA[Audio e Informática]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[3D]]></category>
		<category><![CDATA[algoritmo de entrenamiento]]></category>
		<category><![CDATA[ANN]]></category>
		<category><![CDATA[artificial neural network]]></category>
		<category><![CDATA[backpropagation]]></category>
		<category><![CDATA[bias]]></category>
		<category><![CDATA[feedforward]]></category>
		<category><![CDATA[gradiente descendente]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[mínimo local]]></category>
		<category><![CDATA[montevideo]]></category>
		<category><![CDATA[neural network]]></category>
		<category><![CDATA[pablo gindel]]></category>
		<category><![CDATA[perceptron]]></category>
		<category><![CDATA[processing]]></category>
		<category><![CDATA[red neuronal]]></category>
		<category><![CDATA[redes neuronales]]></category>
		<category><![CDATA[sigmoide]]></category>
		<category><![CDATA[uruguay]]></category>

		<guid isPermaLink="false">http://www.pablogindel.com/?p=234</guid>
		<description><![CDATA[Como decíamos en artículos anteriores, existen -en principio- dos caminos para lograr que un programa se comporte de determinada manera en función de ciertas variables de entrada: elaborando una tabla con todas las posibles combinaciones de esas variables y sus respectivas acciones asociadas, o econtrando algún tipo de modelo matemático, una fórmula o un algoritmo [...]]]></description>
			<content:encoded><![CDATA[<p style="TEXT-ALIGN: justify">Como decíamos en artículos anteriores, existen -en principio- dos caminos para lograr que un programa se comporte de determinada manera en función de ciertas variables de entrada: elaborando una <strong>tabla</strong> con todas las posibles combinaciones de esas variables y sus respectivas acciones asociadas, o econtrando algún tipo de modelo matemático, una fórmula o un <strong>algoritmo</strong> que aplicado a dichas variables nos dé el resultado buscado en cada caso.</p>
<p style="TEXT-ALIGN: justify"><span id="more-234"></span>Cuando la cantidad de combinaciones de variables de entrada es demasiado grande como para elaborar una tabla, y la función es demasiado compleja como para encontrar un algoritmo, las <strong>Redes Neuronales Artificiales </strong>constituyen una manera distinta de abordar el problema, sumamente efectiva aunque no perfecta, como ya veremos.</p>
<p style="TEXT-ALIGN: justify">Podríamos considerar a la RNA como una especie de &#8220;algoritmo universal&#8221;, capaz de responder de muchísimas maneras distintas, y al que podemos &#8220;enseñar&#8221; el comportamiento deseado &#8220;mostrándole&#8221; ejemplos del mismo (una tabla parcial), para luego esperar que se comporte de la manera buscada frente a todos los casos posibles. Precisamente en esto radican sus principales virtud y defecto: el porcentaje de <em>aciertos</em> puede ser increíblemente grande (teniendo en cuenta lo general que es el método) pero no tenemos ninguna garantía de la <em>exactitud</em> del resultado. La analogía con un &#8220;cerebro&#8221; animal surge inmediatamente.</p>
<p style="TEXT-ALIGN: justify">Existen en internet numerosos artículos introductorios y avanzados, que explican claramente el funcionamiento de una RNA, mucho mejor que cualquier cosa que yo pudiera escribir aquí al respecto (empezando por <a href="http://es.wikipedia.org/wiki/Red_neuronal_artificial" target="_blank">este</a>). Mi aporte, en cambio, consistirá en presentar un programa mediante el cual podemos tener una aproximación práctica a la materia, experimentar con redes neuronales, introducir ejemplos reales, lidiar con el entrenamiento y visualizar el proceso de aprendizaje. <strong>PNN</strong> nos permite &#8220;sentir&#8221; las redes neuronales artificiales en nuestra propia experiencia, y también resolver algún caso práctico, que fue lo que originalmente me motivó a desarrollarlo.</p>
<p style="TEXT-ALIGN: justify"><strong>Características técnicas del programa.</strong></p>
<p style="TEXT-ALIGN: justify">Este programa  se basa en el artículo de Steven W. Smith sobre redes neuronales artificiales, en el capítulo 26 de su excelente <a href="http://www.dspguide.com/ch26.htm" target="_blank">The Scientist and Engineer&#8217;s Guide to DSP</a>. La red presentada vendría a ser un <em>perceptrón multicapa</em>, con una <em>capa de entrada</em>, una <em>capa oculta</em> y una <em>capa de salida</em>, cada una de ellas interconectada totalmente con la siguiente, con neuronas de <em>bias</em> en las dos primeras capas  y con función de transferencia <em>sigmoide</em> en cada neurona.  El algoritmo de entrenamiento es el que propone dicho autor, al que llama <em>steepest descent</em>, pero que también podemos encontrar bajo el nombre de <em>gradient descent</em> o simplemente <strong>backpropagation</strong>.</p>
<p style="TEXT-ALIGN: justify"><strong>Instrucciones</strong></p>
<p style="TEXT-ALIGN: justify">Para invocar el applet, hagan click <a title="Palmer Neural Networks" href="http://www.pablogindel.com/applets/PNN.html" target="_blank"><strong>aquí</strong></a>.</p>
<p style="TEXT-ALIGN: justify">Al hacerlo, aparecerán 2 ventanas: la ventana de <em>visualización</em>, hecha en <a href="http://processing.org/" target="_blank">Processing</a>, y el <em>panel de control</em> flotante, hecho en <a href="http://www.java.com/" target="_blank">Java</a> (que a veces queda oculto tras aquella).</p>
<p style="TEXT-ALIGN: justify">Lo primero que debemos hacer es <em>dimensionar</em> nuestra red. Escribimos el número de neuronas o <em>nodos</em> de cada capa, y apretamos el botón &#8220;Dimensionar&#8221;. Al hacerlo aparecerá en la ventana de visualización un modelo 3D en el que las neuronas de cada capa están representadas por esferas de distinto color (y las de <em>bias</em>, de un tamaño ligeramente mayor y blancas [ya nos ocuparemos de las opciones de esa visualización, antes de eso, sigamos con la parte "científica"]).</p>
<p style="TEXT-ALIGN: justify">Al apretar el botón &#8220;Aleatorizar pesos&#8221; aparecen las conexiones entre las neuronas; las verdes son positivas y las azules negativas, y su diámetro es proporcional al <em>peso</em> de la conexión correspondiente.</p>
<p style="TEXT-ALIGN: justify">A continuación deberíamos ir a &#8220;Archivo&#8221; y seleccionar &#8220;Cargar set de ejemplos&#8221;, pero lamentablemente esta opción no está habilitada en las <em>applets</em> de internet, por razones de seguridad. En su lugar podemos ir a &#8220;Ayuda&#8221; y seleccionar &#8220;Demo&#8221;. Esto tendrá el efecto de dimensionar una red con 7 entradas y 3 salidas, y cargar 3 sets de ejemplos.</p>
<p style="TEXT-ALIGN: justify">Para simplificar las cosas, todos los ejemplos están &#8220;asociados&#8221; a una salida; esto quiere decir que se asume que producen &#8220;<strong>1</strong>&#8221; en dicha salida y &#8220;<strong>0</strong>&#8221; en todas las demás. En la lista podemos ver a qué salida está asignado cada ejemplo. Los ejemplos se pueden sacar, seleccionándolos y apretando la tecla &#8220;suprimir&#8221;. Si apretamos &#8220;Enter&#8221; sobre un ejemplo, éste se carga arriba, y podemos testear el comportamiento de la red apretando &#8220;Procesar salida&#8221;. También es posible ingresar valores manualmente en ese campo y probarlos, y una vez ingresados se pueden agregar a la lista con el botón &#8220;Agregar ejemplo&#8221;. Los valores en las entradas pueden ser <em>enteros</em> de cualquier tamaño; los pesos son números de <em>coma flotante</em>, y los valores de salida son de coma flotante entre <strong>0</strong> y <strong>1</strong>.</p>
<p style="TEXT-ALIGN: justify">Si ahora probamos cualquier grupo de valores de entrada, el resultado en las tres salidas va a ser siempre aproximadamente 0,5. Eso se debe a que la red no está <em>entrenada</em> aun. Para entrenarla debemos apretar el botón &#8220;Iniciar aprendizaje&#8221;. Al hacerlo, los pesos se irán modificando, y un número grande a la derecha nos irá indicando la <em>suma del error</em> que producen todos los ejemplos al ser procesados en la red actual. El objetivo del &#8220;juego&#8221; (si usted decide aceptarlo) consiste en dejar ese valor lo más bajo posible. El proceso de optimización se repite 1000 veces cada vez que apretamos &#8220;Iniciar aprendizaje&#8221;, pero habitualmente esto no es suficiente; la cantidad de repeticiones se puede subir a 10000 con el deslizador de abajo a la izquierda. En todo momento podemos ir probando el comportamiento de la red, entre aprendizaje y aprendizaje.</p>
<p style="TEXT-ALIGN: justify">Hasta aquí la operación general del programa. Veamos ahora los detalles.</p>
<p style="TEXT-ALIGN: justify"><strong>Redimensionar la red</strong></p>
<p style="TEXT-ALIGN: justify">Al cambiar el número de neuronas en las capas de entrada o de salida, se pierden todos los ejemplos y el aprendizaje realizado. No así al redimensionar la <strong>capa oculta</strong>. De hecho, es un buen recurso, si notamos que nuestra red tiene &#8220;dificultades para aprender&#8221;, dotarla de más &#8220;capacidad&#8221; aumentando el número de neuronas de la capa oculta.</p>
<p style="TEXT-ALIGN: justify"><strong>Factor de aprendizaje</strong></p>
<p style="TEXT-ALIGN: justify">Al aumentar este número, hacemos que el aprendizaje sea más rápido, pero también inestable; en ocasiones el error puede quedar oscilando o incluso aumentar. Al disminuir el valor, el aprendizaje se vuelve lento pero seguro.</p>
<p style="TEXT-ALIGN: justify"><strong>Aprendizaje extra</strong></p>
<p style="TEXT-ALIGN: justify">La idea de este parámetro está sacada del antes citado libro de S. W. Smith, y consiste darle más importancia, en el aprendizaje, a los ejemplos &#8220;positivos&#8221; o a los &#8220;negativos&#8221; (un ejemplo destinado a la salida <strong>2</strong> es un ejemplo &#8220;negativo&#8221; para la salida <strong>1</strong>). Sinceramente yo no encontré ningún resultado con esto, lo voy a revisar para la próxima versión.</p>
<p style="TEXT-ALIGN: justify"><strong>Menú Archivo</strong></p>
<p style="TEXT-ALIGN: justify">Todas las opciones del menú Archivo están desactivadas, algunas por razones de seguridad del Java, otras porque no están implementadas aun. La más importante sería la de salvar los pesos una vez concluido el entrenamiento. También podríamos volverlos a cargar para usarlos como punto de partida de una siguiente sesión de aprendizaje.</p>
<p style="TEXT-ALIGN: justify"><strong>Menú Configuración</strong></p>
<p style="TEXT-ALIGN: justify">El &#8220;Modo Automático&#8221; va a estar implementado en la próxima versión. Consistiría en que el propio programa tome nota de cómo va decreciendo o aumentando el <strong>error</strong>, ajuste automáticamente los parámetros de entrenamiento, y siga actuando solo hasta llegar a un mínimo de error prefijado.</p>
<p style="TEXT-ALIGN: justify">Los distintos &#8220;modos de aleatorización&#8221; afectan al comportamiento del botón &#8220;Aleatorizar pesos&#8221;. El algoritmo de aprendizaje parte de un estado aleatorio de los pesos y va modificando sus valores en el sentido en que el error decrece. Puede pasar que en determinado momento el error no descienda más, pero aun continúe alto: estaríamos frente a lo que llaman un <em>mínimo local</em>. Aquí viene al caso la aleatorización <em>relativa</em>, que lo que hace es modificar levemente los pesos pero en relación a su valor actual (introduce una pequeña &#8220;mutación&#8221;). Con esto conseguimos, a veces, que el error aumente un poco pero luego siga disminuyendo, es algo así como  &#8221;un paso atrás, dos adelante&#8221;.</p>
<p style="TEXT-ALIGN: justify"><strong>Respecto al error</strong></p>
<p style="TEXT-ALIGN: justify">El dato mostrado a la derecha como &#8220;error&#8221; se calcula de la siguiente manera:</p>
<p style="TEXT-ALIGN: justify">cada uno de los ejemplos que están en la lista se pasa por la red, y se mide la diferencia entre el valor que debe producir en cada salida y el que realmente produce. Todos estos valores elevados al cuadrado, sumados entre sí y sumados con los provenientes del resto de los ejemplos, nos dan el <strong>error</strong> total para un estado en particular de la red (media cuadrática). Esto quiere decir que cuanto mayores sean el número de salidas y el número de ejemplos cargados, mucho más difícil va a ser llevar ese valor a <strong>0 </strong>(y por supuesto, esto también depende del <em>contenido </em>de los ejemplos mismos). En el caso del problema que viene como <em>demo</em> (que, dicho sea de paso, consiste en diversas versiones de las palabras &#8220;uno&#8221;, &#8220;dos&#8221; y &#8220;tres&#8221; capturadas y codificadas por un nuevo programa de procesamiento de audio que estoy desarrollando para <a href="http://www.pablogindel.com/2009/07/samsa-el-hexapodo/" target="_blank">SAMSA</a>) la red se desempeña aceptablemente bien con el error en <strong>20</strong>, más o menos.</p>
<p style="TEXT-ALIGN: justify"><strong>Opciones de visualización</strong></p>
<p style="TEXT-ALIGN: justify">Por último, la parte &#8220;coqueta&#8221; del programa.</p>
<p style="TEXT-ALIGN: justify">Al hacer foco en la ventana de visualización, quedan disponibles las siguientes opciones:</p>
<ul style="TEXT-ALIGN: justify">
<li>haciendo click con el botón derecho del mouse, detenemos o reanudamos la rotación automática del modelo. Cuando la rotación automática está detenida, podemos rotarlo libremente con el botón izquierdo del mouse.</li>
<li>con las teclas de dirección seleccionamos un parámetro, que va a aparecer detallado en el ángulo inferior izquierdo de la pantalla, y con las teclas &#8220;<strong>+</strong>&#8221; y &#8220;<strong>&#8211;</strong>&#8221; modificamos ese parámetro.</li>
<li>los parámetros que se pueden modificar son: la disposición espacial de las neuronas en cada capa, el espaciado de las mismas, la rotación de todo el plano de la capa y la cantidad de caras de la sección de los &#8220;caños&#8221; que interconectan a las neuronas, que por defecto es 20, pero puede ir de 2 a 50, generando la sensación cilíndrica.</li>
</ul>
<p style="TEXT-ALIGN: justify"><strong>Mejoras para el futuro</strong></p>
<p style="TEXT-ALIGN: justify">Esta es una lista de las mejoras que podrían implementarse en futuras versiones del <strong>PNN</strong>, algunas de las cuales fueron sugeridas por mis amigos Alvaro y Tomás  (y otras pueden ser un divague, también).</p>
<ul style="TEXT-ALIGN: justify">
<li>que las neuronas se muevan, respondiendo a leyes físicas, y que las fuerzas de atracción y repulsión dependan de los pesos.</li>
<li>ponerle sonido (con la biblioteca <em>minim</em> de Processing)</li>
<li>esferas texturadas que giren sobre sí mismas</li>
<li>que las conexiones cambien de color cuando son modificadas</li>
<li>que las neuronas vibren según su &#8220;energía&#8221;</li>
<li>que unas bolas circulen por adentro de los caños</li>
<li>rotación de las conexiones</li>
<li>hay que inventar algo para que no haya que apretar 200 veces &#8220;Iniciar aprendizaje&#8221;</li>
<li>salvar y cargar pesos</li>
<li style="TEXT-ALIGN: justify">modo automático: que combine algoritmos genéticos con el backpropagation.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.pablogindel.com/2009/12/palmer-neural-networks/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>La pelota de los dioses</title>
		<link>http://www.pablogindel.com/2009/08/la-pelota-de-los-dioses/</link>
		<comments>http://www.pablogindel.com/2009/08/la-pelota-de-los-dioses/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 01:27:31 +0000</pubDate>
		<dc:creator>pabloxid</dc:creator>
				<category><![CDATA[Audio e Informática]]></category>
		<category><![CDATA[Música]]></category>
		<category><![CDATA[Physical Computing]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[bluetooth]]></category>
		<category><![CDATA[processing]]></category>

		<guid isPermaLink="false">http://www.pablogindel.com/?p=106</guid>
		<description><![CDATA[LPDLD fue el proyecto colectivo que encaramos en el &#8220;Taller de arte y computación física&#8221; de Alvaro Cassinelli, en diciembre de 2008. En escencia se trata de una esfera con un acelerómetro de 3 ejes, un módulo bluetooth para comunicar con la PC, y un programa en Processing que recibe los datos y genera a partir de ellos [...]]]></description>
			<content:encoded><![CDATA[<p>LPDLD fue el proyecto colectivo que encaramos en el &#8220;Taller de arte y computación física&#8221; de Alvaro Cassinelli, en diciembre de 2008. En escencia se trata de una esfera con un acelerómetro de 3 ejes, un módulo bluetooth para comunicar con la PC, y un programa en Processing que recibe los datos y genera a partir de ellos sonido, en este caso mensajes MIDI que son trasmitidos a un sintetizador (Reaktor). Ese vendría a ser su estado actual, pero el proyecto tuvo algunos cambios en el transcurso de su desarrollo, y todavía se está trabajando en él.<span id="more-106"></span></p>
<p>Este post es provisorio, como siempre, aquí van a ver parte de la presentación en dorkbot.mvd el 19 de abril de este año, pero prometo ampliar la información técnica y anecdótica de este maravilloso artefacto, en el futuro.</p>
<p><a href="http://www.pablogindel.com/2009/08/la-pelota-de-los-dioses/"><em>Pinche aquí para ver el vídeo</em></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.pablogindel.com/2009/08/la-pelota-de-los-dioses/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Manual de Audio 2008</title>
		<link>http://www.pablogindel.com/2009/07/manual-de-audio-2008/</link>
		<comments>http://www.pablogindel.com/2009/07/manual-de-audio-2008/#comments</comments>
		<pubDate>Sun, 19 Jul 2009 12:59:41 +0000</pubDate>
		<dc:creator>pabloxid</dc:creator>
				<category><![CDATA[Audio e Informática]]></category>
		<category><![CDATA[DAW]]></category>

		<guid isPermaLink="false">http://localhost/palmera/?p=3</guid>
		<description><![CDATA[Pequeño manual de audio para el técnico informático. Este manual lo escribí en el 2008 para mis cursos. Actualmente lo estoy reformulando por completo, tratando de hacerlo menos denso. Esta entrada es provisoria, el slide contiene incluso algunas páginas en borrador. ]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">Pequeño manual de audio para el técnico informático.</p>
<p style="text-align: justify;">Este manual lo escribí en el 2008 para mis cursos. Actualmente lo estoy reformulando por completo, tratando de hacerlo menos denso. Esta entrada es provisoria, el slide contiene incluso algunas páginas en borrador. <span id="more-3"></span></p>
<div id="__ss_1739792" style="text-align: center; width: 425px;"><object style="margin: 0px;" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=manualdeaudio2008-090719073304-phpapp01&amp;stripped_title=manual-de-audio-2008" /><param name="allowfullscreen" value="true" /><embed style="margin: 0px;" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=manualdeaudio2008-090719073304-phpapp01&amp;stripped_title=manual-de-audio-2008" allowscriptaccess="always" allowfullscreen="true"></embed></object></div>
]]></content:encoded>
			<wfw:commentRss>http://www.pablogindel.com/2009/07/manual-de-audio-2008/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

