lunes, 17 de mayo de 2010

Control remoto


Antes de exponer las novedades del proyecto debo confesar que este blog ha batido un record muy especial: el de no tener ningún comentario acerca de lo que se expone. Como autor desconozco si se comprende el contenido expuesto, si interesa o incluso si puedo ayudar a mejorar la comprensión. Esto certifica la realidad: REQUIEM es una curiosidad de un loco que ha perdido el tiempo convirtiendo los objetos del Environment en un lenguaje de programación. Pues sí, este es el caso.

Hace días contacté con una de las eminencias del Environment a nivel internacional. El interés fue tanto como larga puede ser una frase de menos de veinte palabras. El Environment ya no interesa. Es una ventana más del poderoso engranaje de Logic, pero no una prestación estelar. Lejos quedan los días en los que uno se diseñaba el entorno virtual de su estudio. Posiblemente esto sea debido a que masivamente se usan los plug-ins de sintetizadores virtuales, y éstos ya cuentan con excelentes interfaces gráficos de usuario. El Environment tenía sentido en un mundo rodeado de hardware externo con pequeñas pantallas LCD. Todos los otros usos que podamos darle son mínimos: procesos musicales para música experimental, módulos para “humanizar” pasajes, secuenciadores… REQUIEM

Pero desde el primer día dejé claro que este proyecto se hacía realidad para demostrar la potencia REAL del Environment, así que mi única misión es que diseñarlo, acabarlo, crear su documentación y dejarlo ahí en el océano de la red: crear un producto acabado.


Remote Editor

Volvamos a las novedades de los últimos días en la programación de REQUIEM: el módulo de control remoto. Mientras se resuelven varios problemas surgidos acerca del diseño del modo Song, he decidido avanzar por otro nuevo flanco: que el usuario pueda controlar parámetros de REQUIEM con los controles físicos de su teclado de control MIDI (sliders y codificadores). De esta forma se podrán abrir y cerrar filtros, controlar panoramas y volúmenes, y en definitiva todos los parámetros de síntesis de los dispositivos de REQUIEM.

La ventana “Remote Editor” muestra 8 faders virtuales que actúan como control remoto. El usuario puede asignar cualquier controlador MIDI (del 0 a 127) para controlar remotamente estos faders que a su vez pueden estar asignados a sus respectivos destinos. Por ejemplo se podría asignar el primer fader para controlar el “Cutoff” del sintetizador 1 de REQUIEM, con un ancho de banda de 0 a 127 (o por ejemplo de 80 a 100 para un efecto más suave).


Cada uno de los 8 faders virtuales puede controlar remotamente 2 destinos: uno para los sintetizadores y otro para la caja de ritmos. Además he añadido la posibilidad de seleccionar el modo de operación. En el caso de tener un destino que ya está siendo modulado (por ejemplo por un LFO), podremos elegir sustituir esa modulación o controlar su ancho de banda. Esto se hace desde la casilla “Mode”, seleccionando “Override” o “Replace”.


Así pues cada fader cuenta con estos parámetros:

  • Source: Qué controlador MIDI (0 a 127) controlará remotamente el fader desde la entrada MIDI.
  • Range-Low: Valor mínimo al que responderá el fader.
  • Range-High: Valor máximo al que responderá el fader.
  • Synths: Qué parámetro de los sintetizadores controlará.
  • Drums: Qué parámetro de la caja de ritmos controlará.
  • Mode: Sustituye o modula la modulación existente.

He creado un banco con 128 memorias almacenables por el usuario de forma que cada fader virtual pueda cargar una de las 128 memorias. A eso le he dado del nombre de “Definitions” (Definiciones) Las definiciones pueden ser copiadas, pegadas y eliminadas.


Además hay otra función muy útil: “Learn”. Al pulsar este botón REQUIEM escuchará” la información de control recibida y automáticamente establecerá el parámetro “Source”. Así el usuario no tiene que reconfigurar nada en su teclado de control, simplemente pulsar el botón y mover el control. Al recibir esos datos REQUIEM usará el controlador recibido. Como la función “Learn” abre la puerta MIDI para poder “escuchar” la informaron entrante, he incluido un tiempo de operación de forma que si no se recibe nada el modo “Learn” se deshabilite. Esto evita que un usuario abandone esa ventana dejando la función “Learn” habilitada.

Por otro lado también es posible habilitar o deshabilitar la recepción de controles de volumen y panorama para cada dispositivo (sintetizadores y caja de ritmos) además de habilitar o deshabitar la recepción desde los faders virtuales. Estas opciones no son memorizables, no forman parte de las “Definitions”.

Ya está todo funcionando, tan sólo falta enlazar los destinos y la entrada MIDI real. Espero poder avanzar con el  Modo "Song", que es mi verdadero quebradero de cabeza.

 Esquema del flujo de la señal MIDI entrante a REQUIEM

domingo, 9 de mayo de 2010

Mapa de pantallas


He montado un pequeño diagrama de las pantallas principales de REQUIEM. Como verás hay pantallas en rojo vacías. Esto significa que o bien no existen (por ejemplo la pantalla “Preferences”) o bien que se está trabajando en las mismas (como el caso de “Song”)

En este diagrama no aparecen las pantallas que contendrán todo lo relativo a la detección de acordes (una función realmente “heavy” desarrollada en parte) y el mezclador (que ya existe en estado embrionario) Iré actualizando el mapa a medida que se completen las funciones restantes.

Creo que de esta forma se entienden mejor tanto la estructuración como las funcionalidades de REQUIEM. Debajo de la imagen hay un enlace para descargar una versión en alta resolución. 

martes, 4 de mayo de 2010

E-Code: Módulos Copy / Paste


El Environment en Logic 5.5 presenta un límite de poco más de 8000 objetos. Actualmente estoy bastante cerca de ese límite: sólo podré usar algo más de 1000 objetos adicionales. Una de las soluciones es “empaquetar” conjuntos de objetos creando Macros. Un objeto Macro puede contener casi un centenar de objetos pero sólo puede tener una entrada y una salida (y no puede contener objetos Alias, aunque aquí no representa problema alguno). Esto significa que todo lo que esa Macro debe procesar sólo puede hacerse en los objetos de la Macro. Soy consciente que la expresión “una Macro sólo puede tener una entrada y una salida” es confusa. No te preocupes, lo comprenderás al ver los gráficos inferiores. En el post E-Code Lección 1 – Área de trabajo encontrarás más detalles de las Macros.

El caso es que una de las funciones que más se repite en REQUIEM es el mecanismo de las funciones “Copy” y “Paste”. En REQUIEM podemos copiar y pegar Presets de sonidos, Presets de modulación, Phrases, Patterns, Pasos de canción, las llamadas “Scenes”, Presets de Edición, Kits de batería, parámetros de los LFOs y alguna cosa más. Todo eso son funciones que pueden empaquetarse como Macros y liberar más de 600 objetos que podré usar de nuevo, incrementando el cómputo de objetos disponibles.


El ejercicio de hoy es un buen ejemplo de la filosofía del E-Code: traducir una función esquematizada con flujos de datos a objetos Environment. En nuestro caso la función a “Environear” es un buffer de copia de datos, es decir, la parte mecánica de las funciones “Copy” y “Paste”.

Un buffer de copia es una función compuesta de una puerta de entrada, un almacén que guarda los datos capturados y una puerta de salida que permite enviar esos datos capturados al receptor. Cuando señalamos una frase en un procesador de textos y procedemos a la función “Copy”, todos los datos señalados son capturados y enviados a una memoria temporal en la que se guardan. Al proceder con la función “Paste” estos datos son disparados en la posición de pegado.

Imaginemos que queremos copiar un paquete de 8 parámetros (por ejemplo los parámetros de un LFO):
  1. Pulso “Copy”.
  2. Se abre la puerta del buffer de copia (la puerta de salida está cerrada)
  3. Se envía un disparo a los datos originales a copiar
  4. Los datos reciben el disparo y se introducen en el buffer de copia.
  5. Se cierra la puerta del buffer al recibir el último dato almacenado.
Ahora procedemos con la función “Paste”:
  1. Pulso “Paste”.
  2. Se abre la puerta de salida del buffer.
  3. Se cierra la puerta de entrada (reiterativo, por seguridad)
  4. Se disparan los datos almacenados.
  5. La puerta de salida se cierra al pasar por ella el último dato almacenado.
Expresado como flujo de datos el esquema es el siguiente:


Y convertido a código E-Code el resultado es este:

 


En verde puedes ver el cable que transfiere los datos a copiar al buffer “Copy / Paste”. Este cable sale de una Macro que almacena 128 memorias cada una con 6 parámetros distintos. Es un módulo de 128 Presets.

En azul puedes ver el recorrido de la señal al realizar la copia y en amarillo, lo mismo aplicado para la punción “Paste”. En rojo se representa la salida de datos. Soy consciente que viéndolo todo simultáneamente es imposible comprenderlo. Así que lo mejor es tratarlo por partes.


Función “Copy”

En primer lugar el usuario debería seleccionar el “Preset” del cual queremos copiar los datos.

Al pulsar el botón “Copy” se introduce un “program change” valor “1” en el Transformador “IN”. Este Transformador divide la señal en dos rutas dependiendo del evento recibido. Si el evento es un cambio de programa (como el que hemos enviado) envía dicho evento por el cable superior. El evento de “program change” sigue la ruta hasta llegar a un “Ornament”, un objeto gráfico que multiplica los eventos entrantes en tantas rutas como cables usemos en su salida. En este caso salen dos cables portando el “program change” inicial. Uno se introduce en el Transformador “copy” y el otro en el Transformador “paste”. En cada uno de estos se comprueba que la función sea la de copiar o pegar. Recuerda que el “program change” tiene un valor de "1" (es la definición de salida del objeto botón “copy”), así que la ruta de señal buena será la que continua desde el Transformador “copy”. El Transformador “paste” cortará la señal ya que únicamente dejará pasar los eventos de “program change” con valor “0” (enviados desde el botón “Paste”)

A partir de este punto las tareas se dividen en dos ya que el Transformador “copy” tiene dos cables de salida:

1- Por el cable superior sale el evento “program change” valor “1” que es retardado 2 ticks de señal, convirtiéndose en una señal de disparo en el Transformador etiquetado como “bang”. La señal de disparo pasa por el Transformador “OUT” hasta alcanzar el Transformador “bang Preset”. Este envía una señal al módulo de memorias “128 Preset Memory” para que dispare los 6 parámetros del “Preset” actual (el que el usuario vería en pantalla).

2- Un segundo evento “program change” valor “1” parte del Transformador “copy” por el segundo cable de forma simultánea al primer cable. Este segundo evento es introducido en un Transformador llamado “open” que abre la puerta de entrada “In” (conmutador de cables), permitiendo el paso de los parámetros a copiar. En este instante, cuando la puerta se abre, el proceso de este cable termina, ya no ocurre nada más en esa ruta de señal.



En el paso 1 he retardado la señal 2 ticks, ¿recuerdas? (justo después del Transformador “copy” que divide la señal inicial en dos rutas de señales). Bien, cuando el módulo de memoria “128 Preset Memory” envía sus 6 parámetros gracias a la señal de disparo recibida por “bang Preset”, éstos valores se introducen por el Transformador inicial “In”, y son enviados por su segundo cable ya que no son eventos tipo “program change”. Los 6 eventos siguen el cable encontrándose una puerta “In” abierta. Precisamente hemos retardado el disparo de estos 6 eventos con un retardo para que diera tiempo a que la puerta se abriese sin arriesgarnos a perder uno de los eventos copiados (posiblemente el primero).

Los eventos cruzan un filtro de entrada que se asegura que sólo se introduzcan 6 eventos y no más. Estos eventos se reparten según su definición en 6 faders que los almacenan. Estos 6 faders están cableados a una puerta de salida “Out” que está cerrada. El último fader, llamado “Mod 6” envía dos señales a los transformadores “close” inferiores que cierran tanto la puerta de entrada “In” (que se abrió al inicio del proceso) y la puerta “Out” que aunque ya esta cerrada, recibe el evento igualmente.

Fin del proceso, los datos han sido capturados y son almacenados en 6 faders. Pero no salen, sólo se enviarán al pulsar el botón “Paste”.

La función "Copy" en funcionamiento. Los datos capturados coinciden con los que se ven en el "Monitor" superior. El "Monitor" inferior no muestra datos pues la puerta de salida "Out" está cerrada


Función “Paste”

Ahora el usuario debería seleccionar el “Preset” en el que realizaremos la función de pegar.

Al pulsar el botón “Paste” se introduce un “program change” valor “0” en el Transformador “IN”. Este Transformador vuelve a dividir la señal en dos rutas dependiendo del evento recibido. Si el evento es un cambio de programa (como el que hemos enviado) envía dicho evento por el cable superior. El evento de “program change” sigue la ruta hasta llegar al objeto “Ornament” que multiplica la señal en dos rutas portando el “program change” valor “0” inicial. Como el Transformador “copy” espera recibir un “program change” valor “1” envía el evento por el segundo cable, yendo al Transformador “paste”. El Transformador “copy” cortará la señal ya que únicamente dejará pasar los eventos de “program change” con valor “1” (enviados desde el botón “Copy")

A partir de este punto las tareas se dividen en dos ya que el Transformador “paste” tiene dos cables de salida.

1- Por el cable superior sale el evento “program change” valor “0” que es retardado 2 ticks de señal, convirtiéndose en una señal de disparo en el Transformador etiquetado como “bang”. Este Transformador multiplica la señal por 6 y la envía a sendos objetos fader que contienen los datos almacenados. Los 6 eventos almacenados son enviados hacia la puerta de salida que debería estar abierta en al paso 2. Al enviar el último evento almacenado, llamado “Mod 6”, se envía un evento que cierra las puertas “In” y “Out”. El retardo de 2 ticks se impone para que el disparo se haga después de abrir la puerta de salida “Out”.

 
2- El segundo cable del Transformador “paste” abre la puerta “Out”. Los datos se envían de vuelta al Módulo de Memoria y se almacenan en el Preset actualmente seleccionado.

 La función "Paste" en funcionamiento. Los datos capturados son enviados (ver "Monitor" inferior). El "Monitor" superior muestra los nuevos datos introducidos en la memoria


Creando la Macro

Como el proceso funciona, quizás sea el momento de empaquetar todo el buffer de copia en forma de Macro. De esta forma, todos esos objetos contarán como uno sólo. Para ello es necesario comprobar la entrada de lo que será la Macro. El Transformador “IN” será usado como Macro mientras que el Transformador “OUT” será la salida.

Objetos usados como entrada (gráfico superior) y salida (inferior)

Al seleccionar todos los objetos que compondrán la Macro comprobamos que NO HAY NINGÚN CABLE que salga de esos objetos, todos nacen y mueren dentro de la Macro. La Macro sólo tendrá una única salida: el Transformador “OUT”.

 
Listo, ¡podemos crear la Macro!


NOTA: Este buffer de copia es ideal para copiar y pegar hasta 10 parámetros. En el caso de las “Phrases” (16 notas + 16 velocidades de pulsación + 16 duraciones de nota), es necesario otro mecanismo cuya conversión a Macro es mucho más sofisticada.