Un poco sobre sampling parte 1

Para este post voy a tomar varios conceptos que se pueden encontraren el libro "The Theory and Technique of Electronic Music" de Miller Puckette, el cual puede ser consultado en este hipervínculo

Antes de comenzar, examinemos el comportamiento de un objeto muy importante para este tema, se trata de samphold~. Este objeto permite almacenar un valor temporalmente, el cual va a ser el valor en el que se encuentre la entrada de la izquierda cuando el valor de la entrada en la derecha comienza a ser menor.

Examinemos el siguiente gráfico, en el cual usaremos como señales dos phasor~ y la frecuencia del de la derecha tiene el doble de la frecuencia que el de la izquierda.


En este caso samphold~ almacenará dos valores, correspondientes a los que tiene el de la izquierda cuando ocurren los dos descensos en el phasor~ de la derecha (0 y 0.5 respectivamente). En este caso la coordinación al comienzo de la fase incidirá en la especificidad de los valores, pero si las fases no coinciden, igualmente la relación entre los dos valores, por ejemplo si estos fueran 0.1 y 0.6, la relación de 0.5 entre los dos valores se mantiene, lo cual es realmente importante para lo que construiremos más adelante en este post.

Un loop muy simple

Examinemos rápidamente los objetos y condiciones necesarias para tener un loop, sea este de algo que capturemos en tiempo real o algo que tengamos pregrabado y carguemos a una tabla (array). En el siguiente gráfico encontramos tales elementos básicos.


Para leer el fragmento de audio que tenemos almacenado, necesitamos establecer el valor de las dos variables que se señalan con una flecha. La frecuencia establecerá la velocidad con la cual debe recorrerse una tabla para que su reproducción sea igual a la original en términos de duración y altura.

Asumiendo que tenemos una tasa de muestreo constante de R muestras en un segundo y deseamos hallar la frecuencia para leer un fragmento de N muestras, podemos aplicar una regla de tres inversa. Es decir R----> 1, como N ---->X, por tanto tenemos  ( R * 1 ) / N, o sea, R/N. Dos ejemplos: 1. si tenemos una sonido de 32000 muestras tenemos una frecuencia de 44100/32000 = 1,378125. 2. si el sonido que hemos almacenado es mayor a nuestra tasa de muestreo, la frecuencia será inferior a 1, por ejemplo 44100/88200 = 0.5.

Siempre es posible alterar la frecuencia y como consecuencia se alterará la duración y la altura del sonido reproducido. Tal vez le resulte interesante querer hacerlo en algún temperamento que desee, en este ejemplo que usaré a continuación usaré una formula general para cualquier temperamento igual. Si consideramos la naturaleza exponencial de ese tipo de temperamento basta con multiplicar la frecuencia obtenida por un factor que se debe calcular para el temperamento y transposición deseados.

El factor puede ser calculado con la siguiente formula: 2^(transposición / temperamento). Si pensamos en el caso de los semitonos sería 2^(transposición/12), pero podemos con esto explorar cualquier temperamento posible y lo haríamos relativo al sonido que almacenamos. Si ese factor se incluye dentro de la relación que hallamos anteriormente (R/N), tenemos una nueva formula para frecuencia: (2^(transposición/temperamento)*R)/N.

 
 
Por otro lado, es posible que no siempre los sonidos que capturemos terminen y comiencen en una misma intensidad, lo cual dificulta un poco la creación del loop, pues tendremos "pops o clicks" indeseados. Por esta razón es posible que necesitemos usar una envolvente para atenuar la intensidad del principio y final de nuestro loop. Como ya tenemos una frecuencia y un phasor~ podemos coordinar la envolvente usando la función coseno con el objeto cos~.
 

Primero, debemos considerar que la función comienza en uno y nosotros necesitamos que comience en cero, también que la función abarca un ámbito de amplitud entre 1 y -1 y nosotros necesitamos que su ámbito sea entre cero y 1. Si multiplicamos la salida de la función por un número negativo, lograríamos que su comportamiento inicial sea ascendente y no descendente como es usual, adicional a eso si ese número negativo es 0.5 reduciremos su ámbito a -0.5 y 0.5 y al añadirle 0.5, tendremos entre 0 y 1 con la forma que necesitamos.

Al agregar esa envolvente, podemos escuchar que el loop ha cambiado y no podemos contemplar la totalidad, pero si superponemos dos loops con un desfase de la mitad de la fase, podemos lograr reconstituirlo. Esto y la envolvente lo podemos contemplar en el siguiente gráfico:

 
 
Es posible seguir añadiendo complejidad a nuestro loop. Primero vamos a añadir un punto para iniciar la lectura del sonido, esto puede ser detallado desde cada nuestra o puede ser en algún intervalo de tiempo que se especifique. En nuestro caso será en centésimos de segundo.
 
Consideremos que si afectamos las condiciones agregando un punto de lectura inicial, estaremos afectando el tamaño en la relación R/M y por ende la frecuencia, así que lo que era una constante en la fórmula ahora será una variable. De la misma forma, afectaremos la configuración de los objetos que controlan el punto de lectura para la tabla (objeto tabwrite4~).
 
 
 En el gráfico podemos observar que con los objetos expr hemos añadido el redimensionamiento del término M, restando el tamaño de la tabla y el punto inicial (88200-$f1). Por otro lado, también se recalcula la frecuencia enviando la nueva dimensión de M a la división(44100/ $f1). Como hemos cambiado el tamaño de lo que se va a leer, la última modificación debe hacerse en la fórmula para la transposición.
 
 
Al añadir estos parámetros, es necesario alterar las operaciones para la lectura de la tabla. Ya no es posible sólo multiplicar por el tamaño total de la tabla, es necesario hacerlo por la nueva dimensión que tiene M. Adicionalmente, para poder comenzar en el punto que deseamos es necesario sumar ese punto. Si lo pensamos esto corresponde a la alteración de y=x (phasor~), por y = Mx + Pto.
 
 
El anterior patch es funcional, sobretodo si vamos a trabajar con el propósito de guardar los sonidos para usarlos posteriormente, pero si el propósito es el trabajo de modificación en vivo resulta inapropiado, pues se introducirán ruidos (zipper noise) causados por la conexión de objetos de datos numéricos a objetos de audio.
 
Examinemos la solución y adicionalmente vamos a añadir otra variable más. Para este nuevo caso vamos a elegir también el punto final de lectura. Al cambiar estos aspectos, nuevamente tenemos que modificar sustancialmente el patch que creamos previamente. Debemos recordar que cada uno de los patches que se han programado hasta este momento sirven para crear una gama de sonidos con sus particularidades.
 
Para este ejemplo, vanos atrabajar con un archivo de sonido previamente grabado, para abrirlo usaremos los objetos openpanel y soundfiler. El primero, sirve para obtener la ruta y nombre del archivo en el computador (es una cadena de texto, symbol) la cual será enviada a soundfiler junto con el resto del mensaje ubicado después de openpanel. Tal mensaje simplemente le dice qué hacer a soundfiler, que a su vez realizará operaciones sobre la tabla que hemos usado para almacenar nuestros sonidos.
 
 La tabla será redimensionada y como salida de soundfiler obtenemos la cantidad de  muestras que tiene el archivo de audio. Tal cantidad será usada para establecer el límite superior para las muestras o puntos que determinaremos para la lectura.Como agregamos un punto final, lo que en realidad hacemos es cambiar constantemente el tamaño de la cantidad de muestras a leer.
 
 
Finalmente, para eliminar el ruido que introducíamos anteriormente cuando cambiábamos los datos, usaremos el objeto samphold~, el cual acoplaremos a la fase que generamos. Notarán que en este caso al cambiar la posición también lo hace la transposición, pues la fase sí cambia constantemente su frecuencia, mientras que los puntos de lectura sólo lo harán cuando se acaben ciclo de la fase. He decidido dejarlo de esta forma, pues es posible aprovechar esta particularidad para amar un pequeño "sampler scratch".
 
 
 
 




Comentarios

Entradas populares de este blog

Conociendo lo básico de Pure Data

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

Síntesis aditiva