Skip to main content

Practica 2: nuestro primer patch sonoro

¿Qué elementos nuevos introduciremos en esta práctica?

metro 

Este objeto nos va a permitir enviar un bang cada tantos milisegundos. Por ejemplo, un metro con un argumento de 10.000 enviara un bang cada 10.000 milisegundos, que es lo mismo que cada 10 segundos. Este objeto nos va a permitir por ejemplo crear un metrónomo o secuenciar acciones.

image-1666188404924.PNG

Para que el metro funcione y comience a enviar bangs, tendremos que configurar sus parámetros y activarlo con un numero distinto de 0, para ellos podemos utilizar un bang, un toggle encendido, o un mensaje con un valor numérico. Para que deje de enviar bangs, tendremos que pararlo con un mensaje de stop o un valor igual a 0. En este caso, el toggle estará apagado y el mensaje contendrá el numero 0.
El primer argumento del metro (float) indica el tiempo entre bangs que por defecto está en milisegundos. El segundo argumento (float) nos permite modificar el tempo de la velocidad que ha configurado el primer argumento. El tercer argumento (symbol) nos permite configurar las unidades por ejemplo en segundos con la palabra "second". También podremos modificar el tempo a través de un mensaje con los siguientes datos: la palabra "tempo", el valor del tempo y la unidad del tiempo.

image-1666190135976.PNG Figura x. Cuatro formas diferentes de configurar el objeto metro para que emita un bang por segundo


A través del inlet de la derecha también podremos configurar el tiempo entre bangs una vez el metro esté corriendo. Para ello, utilizaremos una cajita de numero variable o un mensaje. Si en la figura x enviamos el mensaje "stop" al metro, la emisión de bangs se detendrá.

image-1666190771414.PNGFigura X. objeto metro que emite bangs cada 294 milisegundos.


line~

El objeto line~ genera rampas lineales entre dos valores en un tiempo determinado. Su outlet está en formato de señal. Estos parámetros se determinan por los mensajes recibidos en los inlets de line. Por ejemplo, generar una secuencia de valores entre 2 y 5 en 100 milisegundos. Enviando un mensaje al inlet izquierdo podremos configurar los valores de partida, destino y el tiempo de nuestra rampa. El tiempo también podremos configurarlo con el inlet derecho.

image-1663753713136.PNG

Veamos como tenemos que construir los mensajes del inlet izquierdo para controlar nuestra rampa:

Un mensaje con único valor indicará el valor del destino. El line de la imagen ira al valor 5 en 64 milisegundos.

image-1666021298249.PNG

Cuando enviemos un mensaje con dos valores separados por un espacio, el primer valor del mensaje indicara el valor del destino y el segundo valor el tiempo que se tomara en llegar a ese valor de destino. El line de la imagen siguiente ira al valor 5 en 100 milisegundos. ¿Y aquí el 64 para qué sirve?

image-1666021553733.PNG

Enviamos un mensaje con tres valores, los dos primeros separados por "coma" "espacio" y el segundo y el tercero por un "espacio"; el primer valor indicara el valor de partida, el segundo el valor de destino y el tercero el tiempo requerido para ir desde el valor de partida al valor de destino. El line de la imagen siguiente ira desde el valor 2 al valor 5 en 100 milisegundos.

image-1666021667146.PNG

Si no especificamos el tiempo, saltará directamente al valor de destino. Si queremos detener la progresión de la rampa enviaremos un mensaje con la palabra "stop". El ultimo valor generado antes de parar la progresión, o el valor de destino de la rampa en caso de que la progresión no se detenga y llegue al final, quedará almacenado.
Cuando no especifiquemos un valor de partida, tomará como valor de partida ese valor almacenado en la interacción anterior. Cuando no haya habido una interacción anterior el valor de partida por defecto sera 0.

Lo he puesto como llamada de información porque es como importante, quítalo si no te mola

El line de la imagen siguiente ira desde el valor 2 al valor 5 en 100 milisegundos, si recibe el mensaje stop, detendrá la progresión.

image-1666021910428.PNG


snapshot~

El snapshot~ permite convertir una señal en valores numéricos. Esto nos será muy útil cuando queramos enviar valores procedentes de una señal de audio a un objeto que no sea de audio.

image-1666023347650.png

Recordad que los objetos que no son de audio no tienen la "~" y no aceptan señales de audio como input.

Lo he puesto como llamada de información porque es como importante, quítalo si no te mola
Este objeto nos será útil para visualizar qué sucede con nuestras señales de audio. Cada vez que recibe un bang registra el valor que tiene la señal en ese momento, sería el equivalente a la posición de una partícula afectada por una onda en un momento determinado. 

image-1666023066176.PNG


Ejercicio: Crea un patch con los objetos line~ snapshot~ y metro y prueba su funcionamiento. 

 

env~

El envelope "env~" recibe una señal y saca por su salida la amplitud de esta señal en dB, con una equivalencia de 1 igual a 100 dB. 

image-1666191588505.PNGEsté objeto recibe una señal y devuelve valores numéricos. Nos será muy útil para conocer el volumen de nuestra señal en dB y también para visualizar ese volumen en el VU meter que vamos a presentar a continuación. 

 

VU meter

Podremos crear este objeto desde el menu>poner>VU Meter o escribiendo "vu" en un objeto.

image-1666191690235.PNG

Este objeto es una interfaz gráfica que representa el nivel de señal como el que podemos encontrar en el master de una mesa de mezclas, o de un canal en programas como Ableton Live. Nos va a indicar el volumen de la señal

image-1666168172652.jpg

image source: https://www.freeimages.com/nl/photo/vu-meter-1242056    

El rango un VU meter va de valores negativos a valores positivos. Los valores mínimo y máximo varían en cada aparato o programa, sin embargo, el 0 sera el valor de referencia en todos ellos. Y un código de colores nos ayudara a leer esa escala. El verde nos indica un nivel de señal adecuado, el amarillo nos indica un nivel de señal próximo al límite entre un nivel adecuado y un nivel excesivo, y el rojo nos indica un nivel de señal excesivo que debemos evitar y a partir del cual consideraremos que nuestra señal esta "picando".

En Pure data el VU-meter tiene un rango visible de -100 a 12, y el 0 va a ser nuestro límite de pico entre señal adecuada y señal excesiva.

Ya que el envelope nos proporcionará valores de con una igualdad de 100 dB a 1 unidad de amplitud, tendremos que restar 100 a la salida del envelope para enviar un valor adecuado al VU meter.

image-1666192239811.PNG

 

Slider

El slider es una interfaz gráfica que nos permite enviar valores repartidos en un rango determinado, colocando y moviendo un indicador en cualquier posición de la representación de ese rango.

image-1666192683265.PNG

Para mover el indicador, clicaremos sobre el elemento y manteniendo el click pulsado moveremos el ratón. En caso de necesitar mas precisión a la hora de ajustar la posición del indicador, realizaremos la acción anteriormente mencionada mientras pulsamos la tecla SHIFT o MAYUS.

Esta representación podrá ser vertical u horizontal y configuraremos los valores mínimo y máximo de su rango, haciendo click derecho sobre el slider>Propiedades>Rango de Salida.

En propiedades también podremos configurar los colores, etiqueta o tamaño del slider.

image-1666193481513.PNG Figura X. Slider vertical a la izquierda y Slider horizontal a la derecha con sus ventanas de propiedades abiertas

El slider por defecto tiene un rango de 0 a 127, rango que tendremos que ajustar a nuestras necesidades. Este objeto nos va a ser extremadamente útil para regular el volumen. Ajustaremos su rango de 0 a 0.5 o, como máximo, de 0 a 1 en caso de necesidad.


oscilador y *~

El objeto osc~ es un generador de ondas sinusoidales, también conocidas como ondas puras. Debe recibir en su inlet izquierdo la frecuencia de la onda que queramos generar en valores en Hz.

image-1666171882601.png

Este objeto va a generar una onda con una amplitud de 1, lo que quiere decir que generara valores correspondientes a esa onda sinusoidal de -1 a 1. 

image-1666172301620.jpg

source: https://www.hsa.org.uk/electricidad/onda-y-frecuencia 


En Pure Data se parte de la equivalencia de 1 unidad de amplitud igual a 100 dB.

Recordad que los dB median la intensidad sonora percibida y que esta tiene una relación logarítmica a la amplitud, no lineal. Por lo tanto, aunque 1 unidad de amplitud equivalga a 100dB, 0,5 unidades de amplitud NO equivalen a 50 dB, 0,5 unidades de amplitud equivalen a unos 90 dB.

El objeto "*~" nos va a permitir controlar/modular la amplitud de una señal multiplicándola por un valor numérico o por otra señal.  En el ejemplo la multiplicamos por un valor numérico del tipo float. Cuando multipliquemos por valores situados entre 0 y 1 estaremos disminuyendo la amplitud de la señal. Valores mayores de 1 estarán aumentando la amplitud de la señal.

Para el control de volumen siempre multiplicaremos por valores ente 0 y 1. Más adelante también utilizaremos este objeto para mezclar señales. Sus inlets esperan una señal o un valor numérico. 

Vamos a ver esto con un ejemplo en el que utilizaremos algunos de los objetos que hemos visto anteriormente.

  • el snapshot~: para ver el valor de la señal en un momento determinado
  • el env~: para transformar la amplitud de la señal en dB
  • el metro para hacer la foto de la señal con el "snapshot~"
  • la slider para controlar el volumen.


image-1666344518110.PNGFigura x. patch con un oscilador

Patch con este ejemplo

 

MIDI to frequency: mtof


Como bien sabemos, el oscilador habla el idioma de los Hz y en estas unidades (en Herzios o en números?) interpretará los valores que reciba. El objeto mtof convierte valores numéricos de MIDI a valores numéricos de Hz. Nos sera muy útil para trabajar con los valores de la escala musical. Este objeto recibe valores numéricos y devuelve valores numéricos. Inlet (float), outlet (float)

image-1666340660781.PNG


Frequency to MIDI: ftom

Este objeto realiza el proceso inverso a mtof, convierte valores numéricos de Hz a valores numéricos de MIDI. Inlet (float), outlet (float)

image-1666340883231.PNG

Tabwrite~ y Array (GUI)

El objeto tabwrite~ nos permite almacenar los valores de una señal de manera secuencial en un vector.

image-1666342810029.PNG

podremos visualizar este vector con la interfaz gráfica "Array", que es una especie de lienzo.

image-1666342823121.PNG

¿Pero que es un vector en programación? Es una lista de valores almacenados de manera secuencial. 

image-1666342947648.pngFuente: https://montealegreluis.com/logica-programacion/docs/arreglos.html 

El argumento del tabwrite indicará el nombre del vector y para que empiece a registrar los valores que le llegan tendremos que enviar un bang.

Cuando el vector se llene dejará de registrar valores y si queremos que vuelva a registrar tendremos que enviar otro bang.
El vector almacenará 100 valores por defecto. Si queremos modificar su tamaño, haremos click derecho sobre Lienzo>Propiedades>Propiedades del array>Tamaño. En propiedades del array también podremos ver la lista de valores almacenados clicando en "Ver Lista ...".

Para modificar parámetros del lienzo utilizaremos la ventana "Propiedades de Canvas" que se ha abierto justo con la ventana de "Propiedades del array" La interfaz gráfica array nos va a permitir visualizar el valor almacenado en cada posición de un vector. Tendremos que indicar en la configuración del array el nombre del vector que queramos visualizar. La posición en el vector, el índice, se representa en el eje x y el valor almacenado, el contenido, en el eje y.image-1666342753472.PNG

He subido la imagen aquí arriba, pero vuelve a ponerla abajo si crees que es mejor. Es que me parecía que aquí arriba ilustraba lo que acabas de contar y así luego ya pasas a explicarles la metáfora de la fotografía.

Todo esto puede parecer un poco complicado, así que, para entender mejor cómo funciona, utilizaremos la representación de este vector a lo largo del tiempo. Vamos a utilizar la metáfora de una fotografía:

Cada vez que el tabwrite recibe un bang, toma una foto de los valores de la señal en un corto periodo de tiempo que medimos con un cronómetro. Cuando el cronómetro comienza a contar, el primer valor registrado ocupará la primera posición del vector y cuando el cronometro termina el último valor registrado, tomara la última posición del vector.
Para ver cómo una señal evoluciona en el tiempo, tendremos que tomar muchas fotos. Es lo mismo que sucede con un video o una película de dibujos animados, en la que por lo general vemos 24 imagen por segundo. Para que tome todas estas fotos utilizaremos el objeto metro que hemos visto anteriormente.


send~ y receive~

Estos dos objetos nos van a permitir enviar y recibir señales sin necesidad de unir cajitas con cables. Son como un emisor y un receptor inalámbricos y nos van a ser muy útiles para mantener la claridad y comprensión de nuestros programas cuando tengamos muchos elementos y conexiones. 

Imagen de patch con send and receive señal

Cuando queramos enviar datos que no tienen el formato de señal, utilizaremos los mismos objetos, pero sin la virgulilla "~". Esto nos va a permitir enviar mensajes (int, float y symbols) sin necesidad de conectar las cajitas con líneas.

image-1666344679890.PNG


dac~

dac~ = "digital to analog converter" Este objeto representa la puerta de conversion entre los números que componen señales de audio y el movimiento de la membrana del altavoz que va a generar el sonido. Nuestra tarjeta de sonido va a convertir estos datos en variaciones de corriente eléctrica que van a hacer que nuestro altavoz se mueva. 

image-1666170022900.pngVemos que el objeto tiene dos inlets, cada uno corresponde a un canal del estereo (ponía estero, pero es estereo, no?): derecha e izquierda.

image-1666345318553.PNGFigura X.

Como veis en el ejemplo anterior, puedo tener varios receptores del mismo envío y ambos reciben la misma señal.

 

¡Comencemos con la practica!

Ahora vamos a crear un patch con los elementos que acabamos de ver. Para ello os voy a dar el algoritmo escrito de cómo ha de ser nuestro programa y vosotros lo construiréis en Pure Data. Recordad que hay diferentes formas de llegar al mismo resultado así que sentíos con libertad de combinar los objetos que acabamos de introducir de diferentes maneras para probar y conseguir resolver el problema de la manera que más cómoda os resulte:

Nuestro objetivo es reproducir las notas de la escala de una octava con nuestros altavoces. En mi caso he elegido la octava tercera. A parte de rerpoducir las notas, nos gustaría elegir la nota de la octava que se reproduce a traves del ratón.

Solo enviaremos sonido a los altavoces una vez estemos seguros de que el nivel de volumen es adecuado

  1. Voy a crear un nuevo patch.
  2. Necesito tener el DSP encendido para que el programa trabaje con señales.
  3. Necesito hacer llegar a un oscilador los valores en Hz de las frecuencias correspondientes a la octava.
  4. Necesito controlar el volumen. Voy a regular la amplitud de la señal que sale del oscilador y voy a utilizar un rango de 0 a 0.5 para modularla.
  5. Me aseguro de que el volumen es adecuado. Voy a visualizar el nivel de volumen con el VU-meter antes de enviar la señal al dac~.
  6. Una vez el volumen está bajo control y con el volumen de mis altavoces bajado enviare la señal al dac~. El volumen de mis altavoces esta fuera de Pure Data, por ejemplo, en mi caso es un knob, una rueda que giro en mi tarjeta de sonido. (esto no sé si lo van a entender, no sé si saben lo que es una tarjeta de sonido, igual podrías poner una foto)
  7. Una vez escucho una de las notas de la octava probare a reproducir el resto de las notas.
  8. Subo y bajo el volumen desde Pure data. ¿Escuchas algo raro? clics y pums? Utiliza el objeto line~ para suavizar los cambios de volumen.
  9. Si quiero visualizar la señal utilizare un vector y la interfaz gráfica que me permite visualizarlo.