Síntesis aditiva en Max/MSP (Tutorial 1)
1. La serie armónica. El sonido es la alteración producida en nuestro sistema perceptivo por las pequeñas y rápidas oscilaciones de la presión del aire (Blasco 2017). Un instrumento acústico (p. ej. un cello) genera ondas sonoras emitiendo vibraciones que cambian la presión del aire a su alrededor. El movimiento del aire que acompaña al paso de la onda sonora será hacia adelante y hacia atrás, en la dirección de la propagación del sonido. Para que el tímpano humano pueda percibir dichas oscilaciones como sonido, estas deben ocurrir dentro del rango de frecuencias de 20 a 20.000 Hz, en donde Hz expresa el número de ciclos de la onda en un segundo. La altura del sonido ("pitch") es proporcional a la frecuencia de la onda sonora, es decir, entre más ciclos por segundo, más agudo el sonido, y viceversa. Cuando se frota la cuerda con el arco, la cuerda vibra, y la frecuencia fundamental de dicha vibración determina la altura percibida:
Si se frota la cuerda "La" al aire de un cello, esta tendrá una oscilación fundamental de 220 ciclos por segundo (220Hz), equivalente a la altura A3 (el "La" por debajo del Do central en el piano). Porqué se habla de una oscilación fundamental, y no simplemente una oscilación? Porque existen múltiples oscilaciones que en conjunto conforman el evento sonoro, que oscilan por arriba y por abajo de la denominada frecuencia fundamental. A partir de un experimento ideado por Pitágoras (aprox. 570-510 A.C.) se demuestra que, cuando una cuerda tensionada es frotada con un arco, no sólo vibra la cuerda como un todo, sino que vibra también en distintas proporciones, dadas por números enteros. Dichas vibraciones pueden ser representadas cada una como una oscilación individual:
En teoría musical, asociamos el sonido percibido con una altura única, p. ej. la altura A3 (el "La" por debajo del Do central que resulta cuando se frota la cuerda "La" al aire de un cello). Sin embargo, además de la oscilación fundamental (producida a 220 ciclos por segundo), existen oscilaciones parciales con distintas amplitudes, correspondientes a las alturas A4 (a 440 ciclos), E4 (a 660 ciclos), A5 (a 880 ciclos), C#5 (a 1100 ciclos), etc. que en conjunto, conforman un mismo evento sonoro:
En el caso de la cuerda frotada, las alturas de las oscilaciones parciales están dadas en proporción de números enteros sobre la fundamental (es decir, 1:1, 1:2, 1:3, 1:4, etc), por lo que se les denomina "armónicos" (se dice también que el sonido tiene un espectro armónico). Esta proporción es, de hecho, la serie armónica, en la cual se basa el temperamento justo o afinación pitagórica. Veamos en el siguiente video cómo podemos recrear en Max los ocho primeros armónicos sobre la altura "La" (por debajo del Do central), utilizando un oscilador sinusoidal para representar cada uno de ellos:
Descargue este patch aquí.
En el ejemplo anterior el objeto [cycle~] representa un oscilador sinusoidal, y por ende utilizamos ocho instancias de dicho objeto para representar los ocho primeros componentes de la serie armónica. Observe que la serie se obtiene a partir de sumar el mismo valor en Hz repetidamente (220, 220 + 220, 220 + 220 + 220, etc.) Adicionalmente, utilizamos el objeto *~ para multiplicar la salida de los osciladores por una amplitud deseada. Considerando que enrutamos conjuntamente ocho señales de audio a la interfaz, multiplicamos la salida de cada oscilador por 0.125 para no sobrepasar el rango dinámico de Max, que está establecido entre 0. y 1. (1 / 8 = 0.125).
Adicionalmente, utilizando objetos de interfáz gráfica como [live.slider] es posible controlar la amplitud de cada oscilador individualmente. Así mismo, el objeto [nslider] nos permite visualizar la altura a la que corresponde cada uno de los armónicos en la serie:
Descargue este patch aquí.
Acerca del objeto [expr]: por medio del objeto [expr] es igualmente posible obtener la serie armónica, tal y como se presenta en el siguiente video:
Descargue este patch aquí.
[expr] permite realizar declaraciones matemáticas que evalúan una expresión de acuerdo a los valores de entrada (variables). La expresión matemática, como tal, es inicializada por medio del argumento de dicho objeto; en este caso, utilizamos la expresión $f1 * $f2 para calcular la altura de cada uno de los armónicos en la serie, en donde $f1 representa una altura fundamental y $f2 un número en la serie (primer armónico, segundo armónico, etc). Observe que en la sintaxis de la declaración matemática, el símbolo "$" se utiliza para variables y los símbolos que lo siguen determinan el tipo de mensaje (p. ej. "f", un número decimal) y número de entrada (en este caso, 1 para la entrada izquierda, 2 para la entrada derecha). Más información acerca de [expr] aquí.
2. Osciladores sinusoidales. Un oscilador genera una señal repetitiva consistente, en cierta medida, análoga a una de las oscilaciones producidas por la acción del arco sobre la cuerda frotada. Los osciladores sinusoidales (como cycle~ en Max) son la base de la síntesis aditiva, una técnica que construye sonidos desde abajo hacia arriba, mediante la adición incremental de osciladores simples para lograr espectros armónicos deseados (Clark 2003). En palabras de Julius O. Smith (2010), la síntesis aditiva intenta aplicar el teorema del matemático y físico francés Jean Baptiste Fourier (1768-1830) a la síntesis del sonido, empleando grandes números de osciladores sinusoidales, cada uno de los cuales tiene controles independientes de frecuencia, amplitud y fase (Smith III 2010).
Para introducir las capacidades de la síntesis aditiva, durante los siguientes cinco videos se ilustra la recreación del sonido de una campana a partir de 11 sinusoidales, de acuerdo al instrumento originalmente desarrollado por Jean-Claude Risset [tomado del libro de Miller Puckette (2007), aquí]. En primer lugar, creamos un oscilador en conjunto con su control de amplitud y los objetos de interfáz para indicar la amplitud y frecuencia de la sinusoidal, como se ha hecho en ejemplos anteriores:
Descargue este patch aquí.
Seguidamente, aplicamos una envolvente a la salida del oscilador sinusoidal para generar un ataque y decaimiento en la textura del sonido. Si pensamos en el martillo que perturba la campana para que esta emita sonido, podemos imaginar que las vibraciones sonoras tienen un inicio y un final, determinado por la cantidad de energía depositada en el golpe inicial del martillo contra la campana. Las vibraciones sonoras tendrán, por sentido común, más energía al inicio de su vida que hacia el final, y por ende, después de una etapa de ataque, vendrá un decrecimiento natural de la amplitud hasta que esta sea igual a 0. (y no sea posible percibir auditivamente dichas vibraciones). En Max podemos generar una envolvente utilizando el objeto nativo adsr~, quien entrega a su salida una señal que utilizamos para controlar la amplitud a la salida de la sinusoidal:
Descargue este patch aquí.
Las siglas ADSR se refieren a las cuatro etapas que controlan la amplitud de un sonido: una vez el objeto adsr~ recibe un trigger, en este caso, el mensaje "1.", la amplitud aumenta durante el ataque ("attack") entre "0." y "1.", se desvanece luego durante el decaimiento ("decay"), y se mantiene en el nivel seleccionado en "sustain", hasta que el objeto reciba un nuevo trigger, en este caso, el mesaje "0." (NOTE OFF), el cual activa el decrecimiento de la amplitud entre "1." y "0.". La gráfica a continuación representa simbólicamente la envolvente aplicada en el ejemplo anterior:
NOTA: El atributo “legato” en modo activo (@legato 1) configura al objeto para interrumpir el decrecimiento de la amplitud de 1. a 0. durante la etapa de "release", siempre que este reciba un nuevo trigger NOTE ON.
En el siguiente video se ilustran las modificaciones necesarias al patch para adicionar los siguientes elementos:
(1) un control relativo para variar la duración de la etapa "release" de la envolvente, utilizando el objeto [pak] y la entrada cuatro del objeto adsr~, la cual permite actualizar el valor para la duración de dicha etapa en tiempo real;
(2) los objetos [key] y [select] para accionar el trigger de la envolvente utilizando el teclado alfanumérico del computador; el objeto [key] entrega un número entero asignado a cada una de las teclas del teclado alfanumérico, mientras que [select] selecciona el número 32 (correspondiente a la barra espaciadora) y entrega un bang a su salida;
(3) utilizamos los objetos [send~] y [receive~] para enviar y recibir audio de manera remota, es decir, creamos un bus de audio por el que podemos enrutar señales sin la necesidad de utilizar cables;
(4) implementamos un control para variar la frecuencia de la sinusoidal en tiempo real, en relación con la altura fundamental inicialmente seleccionada (de manera similar a un efecto "detune"):
Descargue este patch aquí.
Una vez realizadas dichas modificaciones, es momento para salvar parte de nuestro programa como un nuevo objeto, el cual representará cada una de las 11 instancias de una sinusoidal necesarias para recrear el sonido de la campana. En primer lugar, salvamos el patch inicial en el disco duro, en una carpeta nueva y con un nombre determinado (en este caso, "main.maxpat" en el folder "Bell Class Example"). Seguidamente, seleccionamos la totalidad de objetos que har[an parte del nuevo patch, y utilizamos los comandos "apple + x" y "apple + y" para cortar y pegar dichos objetos dentro de un nuevo patch, el cual salvamos en el mismo folder ("Bell Class Example"), en este caso, bajo el nombre "partial_bell.maxpat". Debido a que ambos archivos comparten el mismo directorio (es decir, se encuentran dentro de la misma carpeta en el disco duro del computador) es posible invocar el patch "partial_bell" como un objeto dentro de nuestro patch principal ("main.maxpat"). El siguiente video ilustra dicho procedimiento:
Descargue este patch aquí.
Observe que, por medio de los símbolos #1, #2, #3, etc., es posible configurar argumentos para nuestro objeto "partial_bell", de forma tal que podemos inicializar los parámetros del oscilador sinusoidal de una forma más eficiente, sin dejar el patch principal.
Así mismo, observe cómo se ha modificado la programación del oscilador con el fin de producir una envolvente más realista, es decir, con un comportamiento más análogo al sonido producido de manera acústica. En primera instancia, hemos modificado el valor de entrada del objeto adsr~ (es decir, la amplitud del oscilador), calculando la raíz cuadrada dos veces de manera consecutiva sobre dicho valor (es decir, disminuyendo el valor de la señal considerablemente):
Posteriormente, a la salida del objeto adsr~, modificamos el patch para aumentar dicha salida a la cuarta potencia (multiplicando la señal por sí misma dos veces seguidas), de forma tal que retomamos el rango dinámico inicial para la amplitud del oscilador, al tiempo que producimos un decrecimiento de la envolvente más natural:
En el siguiente y último video, finalmente inicializamos las 11 instancias necesarias para recrear los 11 parciales en el sonido de la campana. Para ello, utilizamos la información disponible en el ejemplo original de Puckette (2007), que enlista los valores de amplitud, duración relativa, frecuencia relativa y "detune" para cada uno de los parciales, como se muestra a continuación:
Parcial 1 (1. 1. 0.56 0.)
Parcial 2 (0.67 0.9 0.56 1.)
Parcial 3 (1. 0.65 0.92 0.)
Parcial 4 (1.8 0.55 0.92 1.7)
Parcial 5 (2.67 0.325 1.19 0.)
Parcial 6 (1.67 0.35 1.7 0.)
Parcial 7 (1.46 0.25 2. 0.)
Parcial 8 (1.33 0.2 2.74 0.)
Parcial 9 (1.33 0.15 3. 0.)
Parcial 10 (1 0.1 3.76 0.)
Parcial 11 (1.33 0.075 4.07 0.)
Debido a que hemos programado el objeto "partial_bell" para que reciba los parámetros en el orden de la lista ya mencionada (y a manera de argumentos para dicho objeto), es posible copiar y pegar dichos parámetros desde la lista hacia cada una de las instancias del objeto en Max. Al ser todas instancias de un mismo objeto, responderán al unísono al trigger programado anteriormente al interior de "partial_bell". Así mismo, compartirán los valores definidos desde el patch principal para la altura fundamental y la duración global del evento sonoro global. Considerando que enrutamos conjuntamente 11 señales de audio a la interfaz, multiplicamos la salida del bus por 0.09 para no sobrepasar el rango dinámico de Max, establecido entre 0. y 1. (1 / 11 = 0.09…).
Descargue este patch aquí.
Consideraciones finales:
Miller Puckette describe los espectros armónicos e inarmónicos como espectros discretos ("discrete spectra"), debido a que la energía del sonido en dichos espectros se concentra en puntos específicos sobre el eje de la frecuencia (parciales), como en las gráficas a continuación:
En un espectro armónico, los parciales se encuentran en relación de números enteros, como se discutió en la primera sección de este tutorial. En un espectro inarmónico también existe una serie de parciales que componen el espectro (por lo que resulta igualmente discreto), más sin embargo, en este caso, no existe una frecuencia fundamental que relacione a los parciales, es decir, ningún submúltiplo común audible a sus valores en frecuencia. Un espectro contínuo es, en contraste, un espectro en el que la energía no está concentrada en un conjunto discreto de frecuencias, sino que se extiende aleatoriamente a todas las frecuencias posibles (Puckette 2007, p. 121), como por ejemplo, en el caso del ruido blanco, y ciertos instrumentos de percusión. Las campanas y los gongs en particular, tienen en gran medida componentes inarmónicos en el espectro (es decir, parciales que no están dados en números enteros sobre una altura fundamental), lo que genera la percepción de alturas indefinidas o alturas múltiples en ciertos casos (Schwarz 1998).
En el ejemplo anterior, el empleo del efecto "detune", junto con la posibilidad de establecer una frecuencia relativa para cada uno de los parciales dentro del patch, permite acercarse a esta característica inarmónica del espectro de la campana, a pesar de utilizar una altura fundamental para calcular las frecuencias de los componentes (observe los diferentes valores para la frecuencia relativa en la lista de parciales ilustrada anteriormente).
Referencias en Zotero