De algunos condicionales en Pure Data

La toma de decisiones resulta fundamental para el diseño de cualquier tipo de interacción entre la máquina y un ser vivo, saber qué hacer con la información que fluye entre los diferentes objetos de Pure Data o los posibles datos en el entorno y que podemos capturar de alguna forma, requiere de un estudio inicial que posiblemente estimule un desarrollo posterior de forma individual.

En este post daré algunos ejemplos que ilustren el uso de condicionales que permitirán la comunicación con la máquina o que nos permitirán diferenciar la información que estamos procesando para producir algún tipo de reacción sonora (y posteriormente es aplicable a lo visual o al control de dispositivos).

El primer caso que podemos estudiar se trata de cuando se toman decisiones simples, cuando la respuesta es si o no, o el tratamiento que hacemos tiene sólo dos respuestas. Por ejemplo, si queremos determinar cual número es mayor al comparar dos de ellos, o si queremos separar los números en diferentes rangos. Examinemos en Pd-extended el uso de estas.

Supongamos que necesitamos determinar con el objeto |>| cual número es mayor.
En este caso la respuesta que esperamos como salida del objeto es un número binario, es decir, un cero o un uno, lo cual sería ideal para controlar el encendido o apagado de alguna actividad, por ejemplo. En el gráfico que encontramos a la derecha observamos que se cumple, la operación expresada 14>5 produce una respuesta afirmativa, pero si cambiamos el número de la caja numérica de la derecha observaremos que no cambia el resultado si nosotros escribimos un número mayor que 14. Esto se debe a que en Pure Data vamos a encontrar en una gran cantidad de objetos (excepto los de audio) que van a tener entradas calientes y frías.

Esto puede ser una desventaja si nostros queremos evaluar con la llegada de un número al objeto de operación, pero puede ser ventajoso si nuestra condición es compuesta, osea que necesitamos que se cumpla algo adicional, por ejemplo que cambie la entrada de la izquierda o que se evalúe cada n-tiempo. En todo caso, solucionar esto no es complicado, existe un objeto llamado trigger (en español gatillo) el cual enviará los datos al tiempo para que se evalúe la expresión que necesitamos.

En el gráfico a la derecha lo encontramos como |t b f|: la t es la abreviatura de trigger, b la de bang y f la de float; acá lo que estamos indicando es que se coordine el envío de un bang a la izquierda y de un número a la derecha. Si el objeto |>| ya ha recibido previamente un valor por su entrada izquierda y se le envía un número a la entrada derecha al mismo tiempo que un bang a la izquierda, evaluará la expresión pues la función de bang es hacer que el objeto haga lo que tiene que a hacer.

El uso de trigger bang  float o de trigger bang bang  será recurrente en combinación con otros objetos como las operaciones aritméticas o en conjunto con el objeto expr del cual hablaré posteriormente.

Exploremos otra posibilidad. Como mencioné antes, no siempre uno quiere tener una respuesta binaria, a veces se desea enrutar los datos hacia una dirección u otra. En este caso usaremos el objeto |moses| (tiene un nombre chistoso, Moisés, sólo se debe recordar qué hizo este personaje en el Mar Rojo).  Este objeto evalúa la expresión x >= y (equis mayor o igual a ye). Tiene dos entradas, la de la izquierda será x, osea el número que comparará con otro que puede ser el de la entrada de la derecha o el número que usemos para inicializar este objeto. Sus salidas mostrarán la información según se cumpla la condición, a la izquierda saldrán los números inferiores a y, por la derecha los números mayores o iguales a y. Veámos tres ejemplos.

En estos ejemplos podemos verificar lo que ya afirmé previamente.

Condicionales anidados

Examinemos otra posibilidad para el uso de |moses|. En algunas ocasiones es posible que anidemos varios condicionales, es decir, que usemos una serie de preguntas sucesivas si hay casos afirmativos o casos negativos. Suponga que se quiere establecer una división de cualquier intervalo numérico y obtener diversas respuestas dependiendo de en cuál de estas divisiones se encuentre el número, en este caso se necesitaría preguntar. Ejemplifiquemos esto para ilustrar mejor.

Si se tiene un rango de números de 1 a 100 y uno desea dividir en cinco rangos (para este ejemplo entre 1 y 20, entre 21 y 30, entre 31 y 65, entre 66 y 90, y entre 91 y 100) y para cada uno de los intervalos que se han definido se desea obtener una reacción diferente o se desea procesar la información de una forma distinta o se desea definir una función para cada uno de esos rangos, entonces se debe preguntar de la siguiente forma:

 Vamos a suponer que es el número que entra a la pregunta. 1. ¿Es x menor que 21? Si la respuesta es afirmativa entonces se hace algo a, si no, se pregunta 2. ¿Es x menor que 31? Si la respuesta es positiva entonces se hace algo b, si no, se pregunta 3. ¿Es x menor que 66? Si la respuesta es afirmativa se hace algo c, si no, entonces se pregunta 4. ¿Es x menor que 91? Si la respuesta es afirmativa entonces se hace algo d, si no, se hace algo f.

La implementación de lo anterior en Pure Data resulta simple y muy útil (sobre todo para trabajar con probabilidad) y la presento a continuación en los gráficos:

En este gráfico observamos un número que está dentro del primer rango que se ha definido.
La salida numerada con 1 es útil para determinar este caso.

Examinemos otra posible entrada, 24, que estaría en el segundo rango definido. En este caso debemos observar que el número va a salir por las salidas 2 y 3 ¿Cuál de esas usamos entonces? La respuesta es la salida 3 porque si usamos la 2 siempre vamos a obtener todos los números mayores o iguales a 21, mientras que en la tercera sólo obtenemos todo lo que sea mayor o igual a 21 y todo lo menor a 31.

Ejercicio 

 Siguiendo el ejemplo del gráfico anterior examine y determine cuales serían las salidas apropiadas para los demás rangos.

Selección de casos

A partir del caso anterior surge la posibilidad de crear rangos muy detallados y de preguntar incluso por datos específicos, pero hacerlo con condicionales anidados puede resultar engorroso, así que presento otra posibilidad.

En muchos lenguajes de programación la selección de casos ya se encuentra implentada, en Pure Data vamos a encontrar dos casos, el primero nos permitirá identificar un dato y enviar un bang, lo que nos permitirá realizar una tarea que inicie con dicho bang; el segundo caso es cuando identificamos un dato y queremos enrutar la información.

Para el primero de los dos casos mencionados usaremos el objeto |select| o su abreviatura |sel|. Si invocamos el objeto y no escribimos valores iniciales podemos seleccionar un único caso y será el que ingresemos por la entrada derecha del objeto. Lo mejor, es definir desde un inicio los casos, por ejemplo, si uno va a seleccionar ciertos valores de un teclado MIDI o si va a usar el teclado el computador.

Voy a usar el teclado del computador para ejemplificar el uso de sel. El objeto |key| nos permite obtener el valor numérico de cualquier tecla en el computador, por ejemplo, el número 1 es 49 (ver valores en Wikipedia). Si usamos este objeto junto a sel obtenemos un primer método de comunicación entre un usuario o un intérprete y el computador.

En el objeto sel podemos observar que el número de salidas corresponde a la cantidad de casos que se escribieron y uno adicional que se encuentra a la derecha, esta última salida será usada como el caso "otros" y no producirá un bang, sino que enviará el valor que ha entrado. Es posible convertir ese valor en un bang si lo conectamos a la entrada de un bang.

También podemos observar que al ser presionada la tecla 1 en el teclado del computador se produce una respuesta en la selección del número 49 que corresponde al valor decimal de la tecla pulsada.

En el siguiente ejemplo vemos que se ha pulsado el número 6. No sería necesario usar un bang conectado como lo muestro en estos gráficos, pero para poder mostrar qué sale he conectado todos estos bangs.

El segundo caso de este tipo de condicional es el objeto |route|. Este tipo de selección de casos permite la entrada de información adicional y nos permitirá implementar una reacción variable para cada caso. Explicaré su implementación con dos ejemplos.

En algunas ocasiones queremos recibir información detallada, por ejemplo para controlar la envolvente de un oscilador, si extendemos la misma operación a varios osciladores podemos enriquecer el resultado sonoro. En el primer ejemplo que presento, he decidido enrutar mensajes que comiencen con los números del 1 al 8, sólo demostraré el funcionamiento con los dos primeros números.

Contemplemos los mensajes que hemos conectado a la entrada de |route|, dos de ellos comienzan con el número uno y el otro con el número dos. Los que comienzan por uno serán enrutados a la primera salida, el que comienza con el número dos será enrutado a la segunda salida (de izquierda a derecha) y se continuaría igual hasta completar la octava salida. Adicionalmente tenemos una salida para que salga toda la información que no tiene como primer elemento uno de los números listados en el objeto.

Si pulsamos alguno de los mensajes aparecerá en consola el mensaje sin el número inicial, esto resulta beneficioso pues no hace falta filtrar la información para asignarla a un proceso específico.

En la consola veremos la siguiente información para cada uno de los mensajes:

x1: 50 600 100 20
x1: 20 200 400
x2: 7000 20 388

Otro ejemplo es el posible uso para enrutar mensajes de OSC (open sound control) para conectar por ejemplo la aplicación TouchOSC (ir a sitio de la aplicación).

En estos caso los mensajes inician con un número de página (por ejemplo /2), como segundo elemento el tipo de control y posteriormente la información asociada a ese control (ejemplo de mensaje: /1 /fader1 0.69). Al pasarlo por los objetos route sucesivos vamos a obtener al final sólamente el valor que nos interesa y podemos asignarlo a el proceso que deseemos.

Comentarios

Publicar un comentario

Entradas populares de este blog

Conociendo lo básico de Pure Data

Pure data - Vanilla, lo básico, añadir externos

Síntesis aditiva