viernes, 15 de enero de 2010

4898 objetos y subiendo


Este es el estado actual de REQUIEM Environment:

Motor de dispositivos melódicos:

- Los 8 dispositivos ya suenan enviando las notas generadas por los patrones o cadenas de patrones a los correspondientes sintetizadores ES-M y ES-P (seleccionados en el GUI) La funcionalidad de duración de las notas aún no ha sido implementada. Las notas envían el tono y velocidad, pero no la duración.
- La monitorización en el picómetro opera conmutando el dispositivo melódico visualizado actualmente en el GUI.
- Las secciones de síntesis (ES-M / ES-P) y modulación de cada dispositivo están plenamente operativas: 128 memorias de sonidos para cada sintetizador y 128 memorias de modulaciones (4 fuentes x 4 destinos, 4 x profundidades de modulación, 4 x offsets de modulación) Cada sección cuenta con funciones copiar / pegar.
- Editor de eventos de dispositivos melódicos operando. Funciones de pre-visualización, Undo y proceso destructivo. Las notas pueden ser editadas en tono, velocidad, duración, posición (es posible desplazar las notas) y además permite edición por rango de notas (1/16, 1/8, etc) El editor de eventos cuenta con 20 memorias de usuario para almacenar los ajustes y ediciones deseadas.

Motor del dispositivo rítmico:

- Por diseñar. Como Logic 5.5.1 PC no tiene dispositivos de sonidos rítmicos (sólo el sampler EXS-24), he buscado sintetizadores de percusión VST freeware. HE encontrado dos candidatos sensacionales que ofrecen 8 sonidos simultáneamente y con no más de 6 parámetros por sonido. El usuario debería descargarlos (con enlaces proporcionados desde la documentación de REQUIEM) e instalarlos en la carpeta “VSTplugins” de Logic. NOTA: ¿y en Mac?


Contenido del menú "Edit" en la ventana "Synth Editor".

Motor modo Song (Multi-Scenes):

- Por diseñar

Motor de reconocimiento de acordes a tiempo real desde entrada MIDI:

- Diseño previo operando con resultados mejorables.

Motor de harmonización según acordes (X-Pose):

- Por diseñar, aunque los patrones ya incluyen ese parámetro.

Motor de exportación a pista de Logic:

- Por diseñar


Fallos y mejoras:

- Copia de memorias de edición “Edit Sets” en el editor de eventos.
- Copia de parámetros de síntesis: el dispositivo ES-P tiene 1 parámetro más que ES-M y la función copiar / pegar debe tenerlo en cuenta.
- Los parámetros transposición y velocidad de los dispositivos melódicos solo opera en modo “Pattern” y no en modo “Phrase”. Aunque esto es correcto, ocurrirá también que el “Pattern” seleccionado y no operativo recibirá esas modificaciones.
- Modos de grabación aún no implementados (a tiempo real vía MIDI y paso a paso vía MIDI)
- La selección del tipo de sintetizador debería actualizar el interface gráfico automáticamente. Sin embargo al hacerlo se produce un bucle de datos no resuelto.
- Pre-visualización en audio en el editor de eventos según el dispositivo seleccionado actualmente.
- Funciones “mute” y “solo” en los dispositivos melódicos, y “solo” en el editor de eventos.
- Función “Get Note from Scale” dependiente de la armonización generada.
- Proceso de “Scenes” no implementado (el contenedor que aúna los “Patterns”, “Synths”, “Mods” y “Efectos”, ligándolos a una nota MIDI o paso en Modo "Song")
- Efectos: aunque lo deseable sería parametrizarlos en memorias al igual que los ES-P y ES-M, temo el disparo masivo de los parámetros de edición de 4 efectos por dispositivo melódico (4 x 8). ¿Hace falta crear memorias Preset de efectos?


Ventana "Modulators".

GUI (interface gráfico de usuario)
  • Menús superiores operativos según ventanas finalizadas.

Ventanas finalizadas y operativas:

  • Ventana principal de edición de dispositivos melódicos finalizada y operando. (Synth Editor)
  • Ventana de edición de eventos operando. (Phrase Editor)
  • Ventana de moduladores (LFOs) operando. (Modulators) Falta implementar los "Circular LFO" y el "Arkanoid LFO" con sus funciones de copiar y pegar.

Ventanas en diseño:

  • Ventana del dispositivo rítmico en diseño inicial. (Rhythm Editor)
  • Mezclador. (Mixer)

Ventanas no diseñadas:

  • Editor de patrones rítmicos.(Rhythm Phrase Editor)
  • Editor de efectos.(Effects Editor)
  • Matriz de modulación. (Matrix Editor)
  • Ventana “Song” (Multi-Scenes)
  • Editor de arpegios.(Arp Editor)
  • Preferencias. (Preferences)


4898 objetos empleados hasta la fecha:



martes, 5 de enero de 2010

E-Code Lección 2 – Uso de variables – Faders I


El uso de variables es imprescindible en el Environment al igual que con cualquier lenguaje de programación. Pero a diferencia de los otros, nosotros no contamos con una entidad real, es decir, no existen objetos “variables” sino que debemos tomar uno o varios objetos del Environment y usarlos a modo de variables. Por supuesto tampoco tenemos distintos tipos de variables: nuestras variables sólo admiten valores enteros de 0 a 127, con lo que la precisión de los cálculos es paupérrima. Lo cierto es que no vamos a usar el Environment para crear programas de matemática avanzada, sino aplicaciones musicales, con lo que las capacidades de cálculo (operadores) son más que suficientes.

Los objetos que nos servirán como variables son:

  • Objetos tipo Faders (que a continuación expongo en esta primera parte)
  • Objetos tipo Transformadores

Contenedores de variables

Considerar estos objetos como variables implica abordar otro concepto adicional: el contenedor de la variable. No puede existir un valor o variable de forma autónoma, sino que hay objetos tipo fader que pueden enviar y recibir valores, y objetos tipo transformadores también con las mismas capacidades además de poder procesar esos valores con operadores.

Aunque no existen distintos tipos de variable, si hay distintos tipos de representaciones de esos datos, por ejemplo como números (fader numérico), como controles gráficos (faders en general), o como cadenas de texto (fader de texto). Y también hay distintos tipos de contenedores, y esta es quizás la cuestión más importante. Me refiero a “contenedor” a la definición de los eventos de salida del objeto gráfico que nos permite alterar el valor de la variable, por ejemplo un fader vertical. En un fader definido para que envíe control MIDI número 7, la variable será el valor de control MIDI número 7 enviado / recibido. El contenedor sería el tipo de valor, en este caso, eventos de control MIDI número 7, y el artefacto que nos permite cambiar el valor de la variable es el propio fader gráfico (de tipo que sea, vertical, numérico, etc…)

Definición de un objeto tipo fader. Las definiciones "Fader" y "Meta" no son eventos MIDI sino eventos internos de Logic. "Fader" es el evento interno de Logic que maneja las automatizaciones de plug-ins y canales en el mezclador virtual y "Meta" son eventos internos genéricos de Logic.

Si deseo enviar más de 20 valores simultáneos a través de un objeto para que los procese (por ejemplo un transformador que añada una constante a la variable), deberé usar 20 contenedores distintos, ya que de lo contrario esas 20 señales se mezclarán en la salida y no podré recuperarlas de forma individual. Aquí la solución será definir cada uno de los 20 faders con un evento MIDI distinto, por ejemplo, 20 cambios de programa distintos (del 0 al 19), o 20 valores distintos de un mismo controlador MIDI (por ejemplo el número 7, volumen)

También hay que tener en cuenta que disponemos de 16 canales MIDI, y que podemos usarlos para individualizar las variables, por ejemplo envíar 16 cambios de programa simultáneamente (cada uno en un canal MIDI distinto) en vez de usar 16 controles MIDI en un mismo canal MIDI.

Objeto fader definido para el envío de eventos de control número 7 (tanto de entrada como de salida, observa los campos "In" y "Out" en el canal MIDI número 1.

La decisión de qué tipo de contenedor debemos usar depende de varios factores:

¿Cuántas variables distintas se procesarán en ese instante?

Si vas a procesar un bando de variables grande lo mejor es usar a los controladores MIDI como contenedor, pues tienes 128 tipos y cada uno de ellos puede enviar / recibir 128 valores. Otro evento MIDI que nos da esa facilidad es la post-pulsación polifónica (P-Press en Logic, aftertouch polifónico), que nos ofrece 128 números de nota con 128 valores cada uno. Así pues estos tipos de eventos nos ofrecen 128 variables con 128 valores en cada una (control 0 de 0 a 128, control 1 de 0 a 128, control 2 de 0 a 128… control 127 de 0 a 127) Los eventos de notas también permiten ser usados como 128 variables distintas (números de nota) con 128 valores cada una (velocidades de pulsación). Existe otro tipo de eventos que nos podrían servir: los Meta-Eventos, que requieren de un post especial pero que tienen una limitación que desvelaré en la respuesta a la siguiente pregunta.

El caso contrario serían los cambios de programa: con ellos solo tenemos una misma variable con 128 valores, ya que no hay 128 tipos de cambios de programa sino sólo 1. Lo mismo es válido para la post-pulsación de canal (C-Press en Logic, aftertouch de canal): es decir, una única variable con 128 valores.

¿Esos valores deben poder ser disparados?

La gran mayoría de variables necesitan ser disparadas en algún momento. Los disparadores en E-Code son los llamados Meta-Eventos (hay 128 distintos cuya funcionalidad ha sido prefijada por Emagic). El Meta-Evento 99 con valor 0 actúa como disparador. Este objeto tiene apariencia de botón, pero puede ser enviado también desde un transformador. El problema es que un Meta-Evento no puede disparar el valor de una variable cuyo contenedor sea otro Meta-Evento. Al crear un botón tipo “Disparar al segundo fader” (es el nombre horrible con el que aparece en Logic en español), no se envía ningún valor si el fader al que disparamos envía Meta-Eventos, en cambio si enviará cualquier otro tipo de evento si el fader no es definido para que envíe Meta-Eventos.

Disparo de una variable con un contenedor definido como control número 7

Visualización de la definición del botón: Meta-Evento 99 con valor 0. El resultado es el evento de disparo ("M 99 0") y el valor del fader en ese instante ("1 7 101", dónde "1" es el canal, "7" el contenedor y "101" el valor de la variable)

Ahora la variable tiene un contenedor definido como Meta-Evento número 7. El disparador falla, ya que un Meta-Evento no puede disparar a otro. El resultado es el evento de disparo ("M 99 0") y no el valor del fader en ese instante ("M 7 101")

¿Cómo se representarán esos valores en pantalla?

También podrías decidir el contenedor a usar para tus variables teniendo en cuenta cómo se representarán los datos en pantalla. Por ejemplo, si vas a usar un teclado virtual para “visualizar” las notas almacenadas lo mejor sería operar con eventos de nota como contenedores de variables, ya que el teclado virtual únicamente representa gráficamente ese tipo de eventos.


Variables Locales y Globales

En programación existen variables que se definen y “mueren” al final de un proceso o variables que permanecen operando todo el tiempo en el que usamos la aplicación. Las locales pues dejan de operar, aunque a diferencia de otros lenguajes de programación en E-Code siguen definidas, siguen existiendo. Esto es porque el objeto sigue insertado en el Environment, y aunque ya no disparemos más esa variable, su fader y contenedor sigue ahí.

En REQUIEM hay muchas variables locales, por ejemplo las notas grabadas. Estos datos son leídos y enviados al motor de reproducción, y esos valores ya no vuelven a circular por los objetos hasta que sean reclamados de nuevo.

En cambio, el selector de qué dispositivo virtual de REQUIEM estamos viendo y editando es una variable global, siempre está activa y operando, definiendo qué memorias se visualizarán y qué eventos podrían verse y editarse.

Como ves es todo conceptual, tú decides qué variables son globales o locales, y tener claro qué es cada objeto insertado a modo de variable facilitará mucho el desarrollo de la programación.

Tenemos a dos variables con contenedores control número 7 y control número 10, que son procesadas por un objeto transformador añadiendo 10 a los valores entrantes. Observa que sólo procesará contenedores definidos como controles MIDI 7, 8, 9 y 10 (condición "Dentro de") y que además eliminará cualquier otro evento que no sean esos (condición definida en el menú superior. El resultado es el valor de cada contenedor sumado al operador. Si cada fader tuviera el mismo contenedor, el resultado sería "1 7 110" y "1 7 60", se perdería la individualidad de cada variable.

Nos vemos…

lunes, 4 de enero de 2010

E-Code Lección 1 – Área de trabajo


Antes de comenzar, hay que resaltar que es imprescindible conocer de forma muy profunda la naturaleza de los eventos MIDI. No me refiero a la conversión a binario o hexadecimal de los bytes que componen un evento MIDI, sino a saber exactamente qué es un evento de control, las diferencias entre aftertouch polifónico o de canal, que es un MSB y LSB, cómo se compone un evento de nota, y un largo etc. Afortunadamente en la red encontrarás mucha información al respecto.

Pero además también es indispensable la necesidad de dominar el Environment y sus objetos, pues será con ellos con los que armaremos nuestro querido dreamsynth (equipo de ensueño). En este caso también encontrarás bastante información en la red, aunque la más fiable siempre proviene del manual de Logic / Logic Pro. Yo comencé con esa documentación, lo cual indica que es perfectamente válida para cualquier usuario.


Límites del código:

Logic 5 permite el uso de poco más de 8000 objetos en el Environment. Ignoro si este límite se ha incrementado en las presentes versiones de Logic / Logic Pro. Como uso la versión 5 para Windows, ese será mi límite final: toda la funcionalidad de REQUIEM debe operar con 8000 objetos Environment. ¡No caben más!

La segunda limitación del Environment se refriere a su “ancho de banda”. Aunque es muy potente, el Environment no soporta muy bien el envío masivo de datos. Puedo procesar 20 eventos por una matriz de objetos simultáneamente, pero no centenares de ellos. Si creo 100 faders conectados a un mismo objeto disparador (trigger, el meta evento 99 con valor 0… ya hablaremos de ello, no te preocupes) el resultado al efectuar el disparo de valores de esos 100 faders no serán 100 disparos. Algunos “se perderán”, simplemente dejarán de operar no devolviendo ningún valor. ¿Cuántos funcionarán? Depende básicamente de todo: el equipo usado, la propia programación del Environment, el driver de audio empleado… ¡todo!

¿Cómo superar esos dos límites?

Para el primero hay una única solución posible: Macros. Se trata de empaquetar procesos secuenciales en un único objeto llamado Macro. Así, dónde antes habían 30 objetos ahora sólo habrá uno. Pero las Macros del Environment también tienen una limitación: soportan poco más de 100 objetos, y si estos son del tipo fader de texto todavía menos. Esto indica que los Macros están limitados por memoria, pueden caber 100 faders numéricos, pero no 100 faders de texto ya que éstos almacenan además de su propio valor 128 cadenas de texto asociados a cada valor, lo cual supera sustancialmente la memoria empleada por un simple fader que no sea de texto, que solo debe almacenar el valor actual. Por último, las Macros requieren de una entrada y una salida (una puerta de entrada y una salida). Pero por ellas pueden “pasar” múltiples tipos de datos simultáneamente o secuencialmente. Ya dedicaré un post extenso a las Macros, pues son la base de la programación en E-Code.

Ejemplo de Macro creado en el Environment. Consta de 32 objetos tipo fader numérico, con un transformador de entrada y salida.

El mismo Macro pero con 32 faders tipo texo (en vez de números podrían aparecer letras o cadenas de textos) Aquí Logic se queja, no es posible crear el Macro ya que este tipo de faders requiere más memoria. Lamentablemente, el Macro no podrá ser creado.

Para el segundo límite, el ancho de banda, también hay una única solución posible: secuenciar los procesos, es decir, que éstos no ocurran simultáneamente. En el ejemplo indicaba que no es posible disparar simultáneamente 100 faders y que el resultado de ese disparo será que algunos valores “se perderán”. Puede solucionarse insertando un objeto de retardo (Delay), ajustándolo a un retardo pequeño, insignificante. Cada grupo de 10 faders podría estar disparado con un retardo insertado, así lograríamos obtener losa 100 disparos y no se perdería información. Lamentablemente esto tiene un coste: el secuenciador de Logic necesita estar reproduciendo, es decir, el control “Play” pulsado y el reloj corriendo. Esto determina algo vital: REQUIEM sólo funcionará cuando Logic esté en reproducción. De otra forma, ¿cómo podría el Environment procesar datos en el tiempo sin tener un reloj corriendo?

Motor de patrones de REQUIEM. Como puedes ver hay varios objetos retardo (icono de reloj) que se encargan de establecer el orden de ejecución. Uno de ellos está seleccionado, puedes ver sus parámetros en la caja de parámetros de la izquierda. Observa que hay muchos objetos Macro, que son reconocibles gracias al borde de color oscuro de su alrededor.

Hay tres objetos básicos que requieren que Logic esté en reproducción / grabación (es decir, con el reloj corriendo):
  • El objeto retardo (Delay).
  • El objeto TouchTracks.
  • El objeto arpegiador.
En el caso del retardo, si le hemos indicado que deje pasar la señal original recibida por su entrada, ésta saldrá por la salida aunque el reloj de Logic esté detenido, pues es una señal que no va retardada. Pero los eventos duplicados por los retardos del objeto retardo sí requerían del reloj de Logic.

Y por último, aun nos queda un límite… ¡nosotros! Es imposible programar en E-Code si no se sabe programar conceptualmente, es decir, saber dividir cada tarea en unidades de proceso individuales. Dicho de otra forma: saber traducir lo que queremos lograr al lenguaje de objetos del Environment.

¡Anda… Ya estamos en 2010 y yo sigo rodeado de cables y transformadores…!

Buenos tiempos para todos…

Proceso de creación de un Macro. Lo que estás viendo es un LFO que permite dibujar la forma de onda y que la repite infinitas veces generando una modulación.
Como puedes ver todo el proceso envía el resultado a través del transformador "OUT" que actúa como puerta de salida.

Macro empaquetada: todos esos objetos han sido reducidos a un único objeto.

sábado, 2 de enero de 2010

La idea original


Hace varios meses pude juguetear con un sintetizador Korg Triton. Me encantaron las “Combis”, que son conjuntos de hasta 8 sonidos que pueden ser controlados a tiempo real con los diales y botones del panel de control y que usan además el potente sistema de arpegiadores integrado en el aparato. “Qué pena que deba comprar uno de estos para divertirme un rato…” Ese fue el pensamiento.


Una “Performance” (o "Combi") típica en cualquier sintetizador / workstation suele contar de varios generadores de sonidos que son disparados por arpegiadores, controlados por la interpretación del músico. Logic dispone de varios generadores de sonidos, no tan sofisticados como los de un sintetizador dedicado, pero que funcionan muy bien en cualquier tipo de música electrónica. También contamos con arpegiadores, muy simples pero que pueden mejorarse hasta donde la imaginación dicte. Y contamos con un potente entorno de programación, en el que residen los propios arpegiadores y generadores de sonidos: el Environment.

Ahora imaginemos un nuevo plug-in. Con este plug-in puedo grabar una frase de varios compases que es reproducida usando el sintetizador integrado en el propio plug-in. Además, puedo encadenar frases musicales formando estructuras más densas, y por si fuera poco puedo toar un acorde a tiempo real y el plug-in corregirá las notas para adaptarse a la nueva escala. Este plug-in incluye extensas modulaciones, así puedo crear barridos de filtros automáticos, usar datos de velocidad de pulsación para controlar el panorama y otras sofisticaciones varias.

Ahora supongamos que este plug-in en realidad no tiene un único secuenciador de frases, sino 8 secuenciadores. Y cada uno de ellos dispara su propio sintetizador. Además cuenta con una sección de patrones rítmicos, creando la “groovebox” definitiva. Al más alto nivel, es posible grabar secuencialmente los cambios de patrones y sonidos, o incluso asignarlos a teclas para ser disparados al pulsar el número de nota MIDI correspondiente. Esto sería muy apetecible en actuaciones en directo.

Y otro detalle más… el plug-in cuenta con algo de inteligencia propia: puede auto-componer líneas partiendo de acordes y un asistente de composición musical.

Todo esto puede lograrse con el Environment, aunque no es una programación sencilla. Sería un Environment con varios miles de objetos, pero dichos objetos ya no serían meros objetos del Environment, sino proyecciones de un lenguaje de programación nuevo, divertido y muy potente (a nivel musical). Lo llamo E-Code y es otra forma de “ver” a los objetos del Environment y sobretodo de comprender cómo interactúan entre ellos.

Interface de usuario del Environment SOPHY

Aunque me resulta imposible relatar la función de cada nuevo objeto añadido al proyecto REQUIEM Environment, trataré de ilustrar los bloques básicos de su programación, el porqué de cada decisión tomada y las consecuencias a nivel de programación. Para ello primero deberé abordar varias cuestiones genéricas del concepto de programación E-Code. Aunque quizás suene aburrido será imprescindible para poder avanzar en la compresión del sistema de programación empleado.

Parte del motor de secuenciación del Environment SOPHY