1 - Bienvenido amigo :-)

Bienvenido a Sonic Pi. Espero que estés tan emocionado por comenzar a hacer sonidos sorprendentes como yo lo estoy por enseñarte a hacerlos. Será realmente divertido. Aprenderás sobre música, síntesis, programación, composición, interpretación y mucho más.

Pero espera, ¡qué maleducado soy! Deja que me presente - soy Sam Aaron - el creador de Sonic Pi. Puedes encontrarme en Twitter @samaaron y estaré encantado de saludarte. Quizás te interese saber más de mis Live Coding Performances donde programo en vivo y en directo con Sonic Pi.

Si tienes algunas observaciones o ideas para mejorar Sonic Pi - por favor pásamelas -, los comentarios son bienvenidos. Nunca se sabe, ¡tu idea podría ser incluida como una importante funcionalidad!

Este tutorial está dividido en secciones agrupadas por categoría. Lo he escrito para tener una fácil progresión de principio a fin, siéntete libre de saltar de una sección a otra cuanto te apetezca. Si piensas que hay algo que falta, házmelo saber y lo tendré en cuenta para versiones futuras.

Por último, observar a otros haciendo live-coding es una excelente manera de aprender. Yo lo hago regularmente en directo por livecoding.tv/samaaron así que pásate por allí, salúdame y haz muchas preguntas :-)

OK, comencemos…


1.1 - Live Coding (Programación en vivo)

Uno de los aspectos más excitantes de Sonic Pi es la posibilidad de escribir y modificar código para hacer música en directo, como lo harías al tocar una guitarra. Esto significa que con algo de práctica podrás usar Sonic Pi en directo.

Abre tu mente

Antes de entrar en detalle de cómo funciona Sonic Pi, me gustaría enseñarte que es programar en directo. No te preocupes si no entiendes mucho (o nada) de esto. Simplemente siéntate y disfruta …

Un Bucle en Vivo

Comencemos, copia el siguiente código en un buffer vacío:

live_loop :flibble do
  sample :bd_haus, rate: 1
  sleep 0.5
end

Ahora, presiona el botón “Ejecutar” y escucharás una batería con un ritmo rápido. Si en cualquier momento deseas parar el sonido, sólo debes presionar el botón “Parar”. Pero no lo pares, aún… antes sigue los siguientes pasos:

Asegúrate que el sonido de batería sigue sonando Cambia el valor “sleep” de “0.5” a algo más alto, por ejemplo “1”. Presiona de nuevo el botón “Ejecutar” Fíjate como ha cambiado la velocidad del bombo. Por último, recuerda este momento, esta es la primera vez que has programado en tiempo real con Sonic Pi y seguro que no será la última…

Ok, eso fue fácil. Añadamos algo a la mezcla. Encima de sample :bd_haus añade la línea sample :ambi_choir, rate: 0.3. Tu código debería ser así:

live_loop :flibble do
  sample :ambi_choir, rate: 0.3
  sample :bd_haus, rate: 1
  sleep 1
end

Ahora vamos a jugar. Cambia valores, ¿qué pasa cuando usas valores altos, bajos o negativos? Mira lo que pasa cuando cambias el valor rate: por :ambi_choir ajústalo mínimamente (digamos a 0.29). ¿Qué pasa si pones un valor muy bajo para sleep? prueba a hacerlo sonar tan rápido que tu computadora se cuelgue con un error (si eso sucede, simplemente elige un valor más alto para sleep y presiona Ejecutar de nuevo).

Intenta comentar una de las líneas del sample, añadiendo un # al comienzo:

live_loop :flibble do
  sample :ambi_choir, rate: 0.3
#  sample :bd_haus, rate: 1
  sleep 1
end

¿Te das cuenta como le dice al ordenador que lo ignore, y así no lo oímos? Esto se llama “comentar”. En Sonic Pi podemos usar comentarios para quitar y añadir cosas a la mezcla.

Por último, te dejo con algo divertido con lo que jugar. Toma el siguiente código y cópialo en un buffer vacío. Por el momento no intentes comprender demasiado más que darte cuenta que hay dos bucles - lo que significa que hay dos eventos al mismo tiempo - experimenta y juega. Te dejo algunas sugerencias:

Prueba cambiando el valor en azul de rate: para escuchar cambios en el sample. Prueba cambiando los tiempos de sleep y presta atención a cómo ambos bucles dan vueltas a diferentes valores. Oberva que pasa quitando el comentario de la línea de ejemplo (quita #) y disfruta del sonido de la guitarra tocada al revés. Prueba cambiar cualquiera de los valores azules mix: a números entre 0 (no en la mezcla) y 1 (totalmente en la mezcla).

Recuerda que debes presionar ‘Ejecutar’ para escuchar el cambio en el próximo bucle. Si termina siendo un lío, no te preocupes - dale a ‘Parar’, borra el código del buffer y pega una nueva copia del ejemplo para volver a empezar. Cometiendo errores es como aprenderás más rápidamente.

live_loop :guit do
  with_fx :echo, mix: 0.3, phase: 0.25 do
    sample :guit_em9, rate: 0.5
  end
#  sample :guit_em9, rate: -0.5
  sleep 8
end
live_loop :boom do
  with_fx :reverb, room: 1 do
    sample :bd_boom, amp: 10, rate: 1
  end
  sleep 8
end

Ahora, sigue tocando y experimentando hasta despertar tu curiosidad y te preguntes qué más puedes hacer. Ya estás listo para leer el resto del tutorial.

¿A qué estás esperando?


1.2 - La interfaz de Sonic Pi

Sonic Pi tiene una interfaz sencilla para programar música. Echemos un vistazo a esto.

La Interfaz de Sonic Pi

A - Controles de Ejecución B - Controles de edición C - Información y Ayuda D - Editor de código E - Panel de Preferencias F - Visor de Registros G - Sistema de Ayuda H - Visor de Registros

A. Controles de Ejecución

Estos botones rosados son los principales controles para comenzar y parar sonidos. El botón de Ejecutar sirve para iniciar la ejecución del código y Parar para parar todo código en Ejecución, Guardar para guardar el código a un archivo externo y Grabar para crear una grabación (archivo WAV) de los sonidos ejecutándose.

B. Controles de edición

Estos botones anaranjados te permiten manipular el editor del código. Los botones Tamaño+ y Tamaño- permiten cambiar el tamaño del texto. El botón Alinear hará que tu código este más claro y profesional.

C. Información y Ayuda

Estos botones azules te dan acceso a información, ayuda y preferencias. El botón Info abre la ventana informativa, la cual contiene información del propio programa Sonic Pi - el equipo base, historia, contribuyentes y la comunidad. El botón de Ayuda muestra u oculta el sistema de ayuda y el botón Preferencias activa la ventana de preferencias, que te permite controlar algunos parámetros básicos del sistema.

D. Editor de código

Esta es el área donde escribirás tu código y compondrás/ejecutarás música. Es un sencillo editor de texto donde puedes escribir, borrar, cortar, pegar, etc. Piensa que es una versión simplificada de Word o Google Docs. El editor colorea las palabras automáticamente, basado en su significado para el código. Al principio, esto puede parecer extraño, pero pronto lo encontrarás muy útil. Por ejemplo, sabrás que algo es un número, porque es de color azul.

E. Panel de Preferencias

Sonic Pi permite cambiar ciertos parámetros accesibles a través del botón preferencias . Este botón cambia la visibilidad del panel de preferencias, el cual incluye un número de opciones a ser cambiadas. Por ejemplo forzar el modo mono, invertir el estéreo, cambiar a vista/no vista de la bitácora, mando de volumen y un selector de audio para la Raspberry Pi.

F. Visor de Log

Cuando ejecutas un código, el visualizador del log muestra información de lo que está haciendo el programa. Predeterminado está el que veas un mensaje por cada sonido que crees con el tiempo exacto al que fue disparado el sonido. Esto es muy útil para depurar código y entender qué es lo que está haciendo.

G. Sistema de ayuda

Finalmente, una de las partes más importantes de la interfaz de Sonic Pi es el sistema de ayuda que aparece en la parte baja de la ventana. Esta puede ser activada o desactivada al apretar el botón azul «Ayuda». El sistema de ayuda contiene información de todos los aspectos de Sonic Pi incluído este tutorial, listado de sintetizadores disponibles, muestras (samples), ejemplos, efectos y una lista de todas las funciones que Sonic Pi provee para codificar música.

H. Visor de contexto

El visor de alcance le permite ver el sonido que esta escuchando. Usted puede ver fácilmente que la onda de la sierra parece una sierra y que el pitido básico es una curva de onda senoidal. También puede ver la diferencia entre sonidos fuertes y silenciosos por el tamaño de las líneas. Hay 3 alcances para jugar - el defecto es un alcance combinado para los canales izquierdos y derechos, hay un alcance estéreo que dibuja un alcance separado para cada canal. Finalmente hay un alcance de curva Lissajous que mostrará la relación de fase entre los canales izquierdo y derecho y le permitirá dibujar imágenes bonitas con sonido (https://en.wikipedia.org/wiki/Lissajous_curve).


1.3 - Aprender jugando

Sonic Pi te incita a aprender computación y música a través del juego y la experimentación. Lo más importante es que te diviertas y sin darte cuenta, estarás aprendiendo a programar, componer y reproducir.

No hay errores

Hablando de eso, déjame darte un consejo, aprendido a través de mis años programando música en vivo: «no hay errores, sólo oportunidades». Esto es algo que he escuchado a menudo en relación al jazz, pero funciona igualmente bien en el live-coding. No importa lo experimentado que seas -de completo principiante a un experimentado Algoraver, alguna vez ejecutarás código que salga de manera inesperada. Puede que suene increíblemente bien, en cuyo caso continúa con él. O puede que suene mal o fuera de lugar. Pero no importa. Toma el sonido, manipúlalo y conviértelo en algo alucinante. El público se volverá ”loco”.

Inicio simple

Cuando estás aprendiendo es tentador querer hacer cosas ya. Sin embargo, mantén ese deseo como un objetivo para después. Por ahora, piensa en lo más simple que puedas escribir sea divertido y satisfactorio, que sea un simple paso para ese increíble objetivo que tienes en mente. Una vez tengas una idea de ese simple paso, intenta y constrúyelo, juega y mira qué nuevas ideas te trae. En poco tiempo estarás demasiado ocupado divirtiéndote y teniendo un progreso real.

Sólo asegúrate de compartir tu trabajo con los demás!


2 - Sintetizadores

De acuerdo, ya esta bien de introducciones - hagamos algo de sonido.

En esta sección cubriremos las bases de desencadenar y manipular un sintetizador, que no es más que una palabra rebuscada para algo que produce sonidos. Típicamente los sintetizadores son bastante complicados de usarse - especialmente los análogos con tantos cables para unir los módulos. Sin embargo, Sonic-Pi te da mucho de ese poder en una manera mucho más sencilla.

No te confundas con la sencillez del interfaz de Sonic-Pi. Puedes llegar a manipular con mucha profundidad el sonido, si eso te interesa. Mantente atento…


2.1 - tus primeros Sonidos

Dale una mirada al siguiente código:

play 70

Así comienza todo. Adelante, copia y pega en la ventana superior de la aplicación (ese espacio grande en blanco debajo del botón Ejecutar) Ahora, presiona ‘Ejecutar’…

Sonido!

Intenso. Presiónalo otra vez, otra vez, otra vez y otra vez…

Woah, loco, estoy seguro que podrías seguir así por el resto del día. Pero espera, antes de perderte en un infinito bucle de sonidos, intenta cambiando el número:

play 75

¿Escuchas la diferencia? Intenta con un número menor:

play 60

Así que números menores hacen sonidos de tonos más graves y números mayores hacen sonidos de tonos más agudos. justo como en un piano, las teclas más a la izquierda son más graves que las del lado derecho. De hecho, los números se relacionan con las teclas del piano. play 47 significa que toque la 47va tecla del piano; play 48 es un tono arriba (la siguiente tecla a la derecha). Pasa que la tecla número 60 del piano es la 4ta octava de DO. Intenta con: play 60.

No te preocupes si nada de esto significa algo para tí, que así fue también cuando yo comenzaba. Lo que importa es que sepas que los números menores significan sonidos más graves que los números mayores.

Acordes

Si tocar una nota es divertido, tocar varias al mismo tiempo lo es aún más. Pruébalo:

play 72
play 75
play 79

Jazzy! cuando escribes múltiples plays, todos se tocan al mismo tiempo. compruébalo tú mismo - ¿cuáles suenan bien juntos, cuales suenan mal?, experimenta y encuentra por tí mismo.

Melodía

Si tocar notas y acordes es divertido, pero ¿que tal una melodía? ¿qué tal si queremos tocar notas en diferentes momentos? ¡Fácil! sólo debes poner un sleep entre las notas:

play 72
sleep 1
play 75
sleep 1
play 79

¡qué adorable pequeño arpegio! Entonces, ¿qué significa el 1 en sleep 1? Bien, significa la duración de la interrupción. Realmente significa esperar por un pulso, aunque por ahora podemos pensar que significa detenerse por espacio de 1 segundo. Así, ¿cómo haríamos para que el arpegio suene más rápido? Bueno, necesitaríamos usar valores de ‘sleep’ menores. ¿qué tal, por ejemplo 0.5:

play 72
sleep 0.5
play 75
sleep 0.5
play 79

¿Notaste que se ejecutaron más rápido? ahora prueba tú mismo cambiando los valores, usando diferentes tiempos y notas.

Una cosa a probar es tocar notas como play 52.3 y play 52.63. No hay necesidad alguna de usar notas enteras. Toca, prueba y diviértete.

Nombres tradicionales de las notas

Para aquellos de vosotros que poseáis conocimientos de notación musical (no importa si no, no es absolutamente necesario para divertirte) quizás quieras escribir una melodía usando nombres de notas como C y F# en vez de números. Sonic Pi tiene todo eso cubierto. Puedes hacer lo siguiente:

play :C
sleep 0.5
play :D
sleep 0.5
play :E

Recuerda poner los dos puntos ‘:’ delante del nombre de la nota, para que se ponga color rosa. también puedes especificar la octava, añadiendo un número delante de la nota:

play :C3
sleep 0.5
play :D3
sleep 0.5
play :E4

Si quieres hacer una nota aguda, añádele una ‘s’ al nombre de la nota así:play :Fs3 y si quieres hacer una nota plana, añádele una b así play :Eb3.

Ahora, “enloquece” y diviértete con tus propias tonadas.


2.2 - Opciones de Sintetizador: Amp y Pan

Asimismo como Sonic Pi te permite controlar cuál nota tocar o cuál muestra desencadenar, también provee un completo rango de opciones para pulir y controlar los sonidos. En este tutorial cubriremos muchos de estos y existe una gran documentación para cada uno en el sistema de ayuda. Sin embargo, por ahora introduciremos dos de los más útiles: amplitude y pan. Miremos primero cuales son las opciones.

Opciones

Sonic Pi apoya la noción de opciones (opts, abreviando) para sus sintetizadores. Opts son controles que pasas a play los cuales modifican y controlan aspectos del sonido que oyes. Cada sintetizador tiene su propio set de opts para sintonizar su sonido. Sin embargo, hay sets comunes de opts que comparten muchos, como amp: y sobre opts (cubiertas en otra sección).

Las Opts tienen dos partes principales, su nombre (el nombre del control) y su valor (el valor al que pondrás el control). Por ejemplo, puedes tener un control llamado ‘cheese:’ y querer ponerlo con un valor de 1.

Los opts se pasan a las llamadas a play por medio del uso de una coma , y después el nombre del opt, tal como amp: (no olvides los dos puntos :) y después un espacio y el valor del opt. Ejemplo:

play 50, cheese: 1

(Nota que cheese: no es un opt válido, lo usamos sólo como ejemplo).

Puedes pasar múltiples opts separados por comas:

play 50, cheese: 1, beans: 0.5

El orden de los opts no importa, el siguiente será igual al anterior:

play 50, beans: 0.5, cheese: 1

Si un Opt no es reconocido por el sintetizador, simplemente es ignorado (como en el caso de cheese y beans ¡los cuales son nombres ridículos, obviamente!)

Si accidentalmente utilizas el mismo opt dos veces con diferentes valores, el último gana. Por ejemplo, beans: aquí tendrá el valor de 2 y no el de 0.5:

play 50, beans: 0.5, cheese: 3, eggs: 0.1, beans: 2

Muchas cosas en Sonic Pi aceptan opts, sólo debes pasar tiempo aprendiendo cómo usarlas e irás bien. Ejecutemos nuestro primer opt: amp:.

Amplitud

Amplitud es una representación computarizada del volumen de un sonido. Una alta amplitud produce un sonido de alto volumen y baja amplitud produce sonido de bajo volumen. Así como Sonic Pi utiliza números para representar tonos y tiempos, usa números para representar la amplitud. Una amplitud de 0 es silencio (escucharás nada) y amplitud de 1 es volumen normal. Puedes utilizar volumen a amplitudes mayores a 2, 10, 100. Sin embargo, debes tener en cuenta que cuando la amplitud de todos los sonidos se vuelve muy alta, Sonic Pi utiliza un compresor para asegurar que no lleguen a tan alto que dañen tus oídos. Esto puede hacer que los sonidos sean extraños. Intenta con amplitudes bajas, por ejemplo en el rango de 0 to 0.5 para evitar compresión.

Amplifícalo

Para cambiar la amplitud de un sonido, utiliza el opt amp:. Por ejemplo, para tocar a la mitad de la amplitud cámbialo a 0.5:

play 60, amp: 0.5

Para hacerlo al doble de amplitud 2:

play 60, amp: 2

El opt amp: sólo modifica la llamada para el play al que está asociado. Así, en este ejemplo, la primera llamada para tocar es a mitad de volumen y la segunda es a la predeterminada (1):

play 60, amp: 0.5
sleep 0.5
play 65

Por supuesto que puedes usar diferentes valores de amp: para cada llamada a play:

play 50, amp: 0.1
sleep 0.25
play 55, amp: 0.2
sleep 0.25
play 57, amp: 0.4
sleep 0.25
play 62, amp: 1

Paneo

Otro concepto divertido de usar es el paneo pan: el cual controla el paneo de un sonido en estéreo. Panear un sonido a la izquierda, significa que lo escucharás en la bocina izquierda, panearlo a la derecha, significa que lo escucharás de la bocina derecha. Para nuestros valores, tenemos -1 para representar completamente a la izquierda, 0 para representar el centro y 1 para representar completamente a la derecha. Claro, eres libre de usar cualquier valor en medio de -1 y 1 para controlar la posición exacta de tu sonido.

Toquemos un sonido desde la bocina izquierda:

play 60, pan: -1

ahora que salga de la bocina derecha:

play 60, pan: 1

Finalmente, pongámoslo de nuevo al centro (predeterminado):

play 60, pan: 0

¡Ahora diviértete cambiando las amplitudes y paneos de tus sonidos!


2.3 - Cambiando Sintetizadores

Hasta ahora nos hemos divertido mucho sólo con sonidos. Sin embargo, de seguro ya comienzas a cansarte del sonido básico de pitidos. ¿es eso todo lo que Sonic-Pi tiene para ofrecer? Tiene que haber más que tocar pitidos. Sí, hay mucho más y lo exploraremos en esta sección con el excitante rango de sonidos que Sonic Pi tiene para ofrecer.

Sintetizadores

Sonic Pi posee un rango de instrumentos que se llaman synths, que es como abreviamos sintetizadores. Mientras que los muestreos representan sonidos pre-grabados, los sintetizadores son capaces de generar nuevos sonidos dependiendo de cómo los controles (lo cual exploraremos más adelante en el tutorial). Los sintetizadores de Sonic Pi son poderosos y expresivos, tendrás mucha diversión tocando y explorándolos. Primero, aprendamos a seleccionar el synth a usar.

Sierras y Profetas

Un sonido divertido es el de la onda sierra - probémoslo:

use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
play 62
sleep 0.25

Probemos otro sonido - prophet:

use_synth :prophet
play 38
sleep 0.25
play 50
sleep 0.25
play 62
sleep 0.25

¿Qué tal si combinamos ambos sonidos? Pongamos uno después del otro:

use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
use_synth :prophet
play 57
sleep 0.25

Ahora al mismo tiempo:

use_synth :tb303
play 38
sleep 0.25
use_synth :dsaw
play 50
sleep 0.25
use_synth :prophet
play 57
sleep 0.25

Debes notar que el comando use_synth sólo afecta a las siguientes llamadas a play. Piensa en él como un gran conmutador - nuevas llamadas a play tocarán el sintetizador que esté en uso. Puedes cambiar el conmutador a un nuevo sintetizador con use_synth.

Descubriendo Sintetizadores

Para saber qué sintetizadores tiene Sonic Pi, échale un vistazo a la opción Sintetizadores en el menú a la izquierda (a la izquierda de Efectos). Hay más de 20 entre los que elegir. Aquí están algunos de mis favoritos:

:prophet :dsaw :fm :tb303 :pulse

Ahora prueba a cambiar los sintetizadores durante la ejecución de tu música. Diviértete combinando sintetizadores para hacer nuevos sonidos así como utilizando diferentes sintetizadores para diferentes secciones de tu música.


2.4 - Duración con Envolventes

En una sección anterior, vimos cómo utilizar el comando sleep para controlar cuándo disparar sonidos. Sin embargo, aún no hemos podido controlar la duración de nuestros sonidos.

Con el fin de darnos una simple pero poderosa manera de controlar la duración de nuestros sonidos, Sonic Pi proporciona el concepto de una envolvente de amplitud ADSR (más adelante en esta sección trataremos qué significa ADSR). Una envolvente de amplitud ofrece el control de dos aspectos muy útiles:

control sobre la duración del sonido control sobre la amplitud del sonido

Duración

La duración es la longitud del sonido. Una mayor duración significa que escucharás el sonido por más tiempo. Todos los sonidos de Sonic Pi tienen una envolvente de control de la amplitud, y la duración total de la envolvente es la duración del sonido. Por lo tanto, al controlar la envolvente controlas la duración.

Amplitud

La envolvente ADSR no sólo controla la duración, también te permite control fino de la amplitud del sonido. Todos los sonidos audibles comienzan y terminan en silencio, conteniendo partes no-silentes en medio. Las envolventes permiten deslizar y mantener la amplitud de las partes no-silentes. Es como darle instrucciones a alguien sobre cómo subir y bajar el volumen del amplificador de una guitarra. Por ejemplo, puedes pedirle a alguien “comienza en silencio, lentamente llega a máximo volumen, manténlo por un momento y rápidamente vuelve a silencio”. Sonic Pi te permite controlar exactamente esta conducta con los envolventes.

Recapitulando lo visto anteriormente, una amplitud de 0 es silencio y una amplitud de 1 es volumen normal.

Ahora, veamos cada una de las partes de las envolventes.

Fase de Release (apagado del sonido)

La única parte de la envolvente que es utilizada predeterminadamente es el release, que es el tiempo que le toma al sintetizador para apagar el sonido completamente. Todos los sintetizadores tienen un tiempo de release de 1, lo que significa que tienen una duración de un pulso (el cual por defecto es 1 segundo, si el BPM es 60):

play 70

La nota será audible por 1 segundo. ¡Vamos, cronométralo! Esta es la manera abreviada de decir lo mismo que:

play 70, release: 1

¡Observa que suenan exactamente igual los últimos dos comandos! Sin embargo, es ahora muy fácil cambiar la duración con tan sólo modificar el valor del release::

play 60, release: 2

Podemos hacer que el sintetizador suene por un periodo de tiempo muy corto al poner un valor de release muy pequeño:

play 60, release: 0.2

La duración del apagado del sonido es lo que llamamos fase de release y por defecto es una transición lineal. El siguiente diagrama ilustra esta transición:

Fase de liberación de la curva de sonido (release envelope)

La línea vertical en la izquierda del diagrama muestra que el sonido comienza con amplitud 0, pero llega a amplitud completa (esto es el ataque, que cubriremos próximamente). Una vez que la amplitud es máxima, se mueve en línea recta hacia abajo hasta llegar a 0, tomando el tiempo que para ello se especificó en release:. * Cuanto más largos son los tiempos de release, más tiempo le toma al sintetizador desvanecerse.*

Puedes, por tanto, cambiar la duración de tu sonido, cambiando el tiempo de release. Prueba a añadir tiempos de release a tu música.

Fase de Ataque

Por defecto, la fase de ataque es 0 para todos los sintetizadores, lo que significa que pasan inmediatamente de amplitud 0 a 1. Ésto le da al sintetizador un sonido inicial percutivo. Sin embargo, podrías desear que el sonido se inicie gradualmente. Esto se logra con el operador attack:. Prueba hacerlo con varios sonidos:

play 60, attack: 2
sleep 3
play 65, attack: 0.5

Puedes utilizar varios operadores al mismo tiempo. Por ejemplo para un ataque corto y un release largo, prueba:

play 60, attack: 0.7, release: 4

Este ataque corto y largo release queda ilustrado en el siguiente diagrama:

Faces de ataque y release de la curva de sonido (attack release envelope)

También puedes invertirlo, prueba ahora con un ataque largo y un release corto:

play 60, attack: 4, release: 0.7

long attack short release envelope

Finalmente, puedes poner el ataque y release cortos, para obtener sonidos cortos.

play 60, attack: 0.5, release: 0.5

short attack short release envelope

Fase de Sostenimiento

Adicionalmente a especificar los tiempos de ataque y release, también puedes especificar el tiempo de sostenimiento para controlar la fase de sostenimiento. Este es el tiempo en el cual el sonido es mantenido a máxima amplitud entre las fases de ataque y release.

play 60, attack: 0.3, sustain: 1, release: 1

ASR envelope

El sostenimiento es útil para sonidos a los que desees darles máxima presencia a la mezcla antes de entrar a la fase de release. Claro, es totalmente válido usar ambos operadores, attack: y release: opts a 0 y dejar el sostenimiento sin aparecimiento gradual ni desvanecimiento. Sin embargo, ten en cuenta que un release de 0 puede producir clicks en el audio y es aconsejable usar un valor muy pequeño como 0.2.

Fase de Decaimiento

Para un nivel extra de control, también puedes especificar el tiempo de decaimiento. Esta es la fase del sobre que está entre el ataque el ataque y el sostenimiento, especifica el tiempo donde la amplitud bajará desde el nivel de ataque al de desvanecimiento attack_level: decay_level: (a menos que especiques que será sujetado al nivel de sostenimiento sustain_level:). De hecho, el decay: operando es 0 y tanto el ataque como el sostenimiento tienen valor 1, así que deberás especificarlos para que el tiempo de decaimiento tenga efecto.

play 60, attack: 0.1, attack_level: 1, decay: 0.2, sustain_level: 0.4, sustain: 1, release: 0.5

ADSR envelope

Nivel de Decaimiento

Un último truco es que aunque el decay_level: opt está predeterminado a ser el mismo valor que el sustain_level: puedes ser explícito y asignarles diferentes valores para un completo control del sobre. Esto permite crear sobres como el siguiente:

play 60, attack: 0.1, attack_level: 1, decay: 0.2, decay_level: 0.3, sustain: 1, sustain_level: 0.4, release: 0.5

ASR envelope

También es posible poner el decay_level: más elevado que el sustain_level::

play 60, attack: 0.1, attack_level: 0.1, decay: 0.2, decay_level: 1, sustain: 0.5, sustain_level: 0.8, release: 1.5

ASR envelope

Envolventes ADSR

Para resumir, las envolventes ADSR de Sonic Pi tienen las siguientes fases:

ataque - tiempo desde amplitude 0 hasta el attack_level, decaimiento - tiempo para mover la amplitud desde attack_level a decay_level, sostenimiento - tiempo para mover la amplitud desde decay_level a sustain_level, release - tiempo para mover la amplitud desde sustain_level a 0

Es importante recalcar que la duración de un sonido es la sumatoria de los tiempos de todas las fases. Por tanto, el siguiente sonido tendrá una duración de 0.5 + 1 + 2 + 0.5 = 4 pulsos:

play 60, attack: 0.5, attack_level: 1, decay: 1, sustain_level: 0.4, sustain: 2, release: 0.5

Ahora ve a jugar con envolventes en tus sonidos…


3 - Muestras

Otra gran manera de desarrollar tu música es usando sonidos pre-grabados. En la gran tradición de la “música concreta”, llamamos a estos sonidos pre-grabados “sampleos”. Another great way to develop your music is to use pre-recorded sounds. Así que si tomas un micrófono afuera y grabas el sonido de la lluvia golpeando la tela, ya creaste un sampleo.

Sonic Pi te deja hacer muchas y divertidas cosas con las muestras. No sólo viene con cerca de 90 muestras de dominio libre para que ser utilizados, sino que te deja manipular los tuyos. Veamos…


3.1 - Disparando muestras

Ejecutar pitidos es sólo el principio. Algo que sí es divertido es disparar sampleos pre-grabados. Inténtalo:

sample :ambi_lunar_land

Sonic Pi incluye muchos sampleos para que uses. Utiliza el comando play para dispararlos. Para tocar múltiples sampleos y notas, simplemente escríbelos uno detrás del otro:

play 36
play 48
sample :ambi_lunar_land
sample :ambi_drone

Si quieres distribuirlos en el tiempo, usa el comando sleep:

sample :ambi_lunar_land
sleep 1
play 48
sleep 0.5
play 36
sample :ambi_drone
sleep 1
play 36

¿Notas que Sonic Pi no espera a finalizar un sonido para comenzar el siguiente? El comando sleep sólo describe la separación de los sonidos disparados. Esto te permite hacer capas de sonidos fácilmente, creando interesantes efectos de capas superpuestas. Más tarde en el tutorial miraremos cómo controlar la *duración *de los sonidos con las envolventes.

Descubriendo las muestras

Hay dos maneras de descubrir el rango de sampleos provistos por sonic Pi. Primero, puedes utilizar este sistema de ayuda. Click en Samples en el menú vertical a la izquierda, elige tu categoria y verás un listado de sonidos disponibles.

Alternativamente puedes usar el “sistema de auto-compleción”. Simplemente teclea el comienzo de un grupo de sampleo tal como: sample :ambi_ y verás el menú de nombres de sampleos disponibles para que selecciones. Intenta las siguientes categorias de prefijos:

:ambi_ :bass_ :elec_ :perc_ :guit_ :drum_ :misc_ :bd_

¡Ahora puedes comenzar a mezclar muestras en tus composiciones!


3.2 - Parámetros de Sampleo: Amp y Pan

Como ya vimos con los sintetizadores, podemos controlar con facilidad nuestros sonidos con parámetros. Las muestras permiten exactamente el mismo mecanismo de parametrización. Veamos a nuestros viejos conocidos amp: y pan:.

Amplificando los sampleos

Puedes cambiar la amplitud de los sampleos exactamente de la misma forma que utilizamos para los sintetizadores:

sample :ambi_lunar_land, amp: 0.5

Paneando sampleos

También podemos utilizar el parámetro pan: en sampleos. Por ejemplo, aquí te muestro como tocaríamos la pausa amén en el oído izquierdo y después a la mitad, la tocaríamos en el oído derecho:

sample :loop_amen, pan: -1
sleep 0.877
sample :loop_amen, pan: 1

Nota que al 0.877 (en segundos) está la mitad de la duración del sampleo :loop_amen .

Finalmente, nota que si seteas algunos sintetizadores por defecto con use_synth_defaults (que discutiremos luego), estos serán ignorados por sample.


3.3 - Estirando Samples

Ahora que ya podemos tocar una variedad de synths y samples para crear música, es tiempo de aprender a modificar tanto los synths como los samples para hacer la música más interesante y única. Primero, exploremos la habilidad de “estirar” y “aplastar” los samples.

Representación de Sampleos

Los Samples son sonidos pregrabados guardados como números que representan cómo mover los conos de los parlantes para reproducir sonidos, estos conos se pueden mover hacia dentro y hacia afuera, así que los números sólo deben representar ese movimiento en cada momento dado. Para poder reproducir fielmente un sonido, el sample debe guardar miles de números por segundo, Sonic Pi toma esta lista de números y los alimenta a la velocidad correcta para mover los parlantes de tu computadora a la velocidad correcta para reproducir sonido. Sin embargo, también es divertido cambiar la velocidad a la que los números son alimentados al parlante para cambiar el sonido

Cambiando la Velocidad

Ejecutemos uno de los sonidos ambiente: :ambi_choir. Para tocarlo con la velocidad predeterminada, puedes añadir rate: a sample:

sample :ambi_choir, rate: 1

Así lo ejecuta a tiempo normal (1), nada especial. Sin embargo, podemos cambiar ese número a otros. ¿qué tal a 0.5 ?:

sample :ambi_choir, rate: 0.5

Woah! ¿qué sucedió? Bueno, dos cosas: Primero, el sample se ejecutó en el doble del tiempo; Segundo, sonó una octava más grave. Exploremos todo ello en más detalle.

Estiremos

Un sample que es divertido estirar y comprimir es el Amen Break. A velocidad normal, podemos imaginar poner una pista de drum ‘n’ bass:

sample :loop_amen

Sin embargo, cambiando la velocidad podemos cambiar “géneros”. Intenta con la mitad de la velocidad para un “hip hop de vieja escuela”:

sample :loop_amen, rate: 0.5

Si lo aceleramos, entramos al territorio estilístico de jungle:

sample :loop_amen, rate: 1.5

Vamos a nuestro último truco - veamos qué sucede si utilizamos una velocidad negativa:

sample :loop_amen, rate: -1

Ahaa! ¡Se toca al revés! Ahora intenta toca distintos samples y velocidades, tales como rápidas y lentísimas, observa qué sucede.

Velocidad de sampleo: una explicación sencilla

Una manera sencilla con los sampleos es pensando en ellos como resortes. La velocidad de ejecución es como “estirar” o “comprimir” resortes. Si tocas a velocidad 2 estás comprimiendo el resorte a la mitad de su tamaño, por tanto le toma la mitad del tiempo en ejecutarse, ya que es más corto. Si ejecutas el sampleo a la mitad de velocidad, estás en efecto alargándo el resorte, por tanto estás doblando su tamaño y toma el doble de tiempo el ejecutarse. Entre más comprimas (mayor velocidad), más corto se vuelve el tiempo y viceversa.

Comprimiendo un resorte incremeta su densidad (el número de embobinados por cm.), lo cual es similar a que el sampleo suene a tonos más altos. Estirándo el resorte, decrece su densidad y simlarmente el sonido es más grave.

La matemática de la velocidad de sampleo

(Esta sección es para aquellos interesados en los detalles. Eres libre de saltártela)

Como hemos visto, un sample está representado por una larga lista de números representando adónde debe estar el parlante a través del tiempo. Podemos tomar este listado de números y usarlo para dibujar un gráfico que sería similar a:

sample graph

Quizás hayas visto imágenes parecidas a esa. Se llaman “forma de onda” de un sampleo. Simplemente es la graficación de números. Típicamente una forma de onda como ésta tendrá 44100 puntos por segundo de dato (esto debido al teorema de sampleo de Nyquist-Shannon) Así que si un sample dura 2 segundos, la forma de onda será representada por 88200 números, alimentándo a los parlantes a una velocidad de 44100 puntos por segundo. Claro, podemos también alimentarlos a una velocidad doble, que sería de 88200 puntos por segundo, lo cual tomaría sólo 1 segundo para ser tocado. También podríamos tocarlo a la mitad de velocidad, lo que daría 22050 puntos por segundo tomando 4 segundos de tiempo de ejecución.

La duración del sample es afectada por la velocidad de ejecución:

doblándola, logramos reducir a la mitad el tiempo de ejecución, achicándola a la mitad, doblamos el tiempo de ejecución, usando una velocidad de ejecución de 1/4, cuadruplicamos el tiempo de ejecución, Usando una velocidad de ejecución de 1/10, tomará 10 veces el tiempo de ejecución.

Esto lo representaremos con esta fórmula:

nuevo_sample_ = (1 / velocidad) * duración_sample 

Cambiando la velocidad de ejecución se afecta el tono del sampleo. La frecuencia o tono de una forma de onda está determinada por cuán rápido se mueve hacia arriba y hacia abajo. De alguna manera, nuestro cerebro toma los movimientos rápidos de los parlantes a notas agudas, igualmente, torna movimientos lentos de los parlantes en notas graves. Por eso es que puedes ver los parlantes de bajos moverse cuando están dando notas muy bajas, porque en realidad sí se están moviendo adentro/afuera del parlante mucho más lentamente que al producir notas altas.

Si tomas una forma de onda y la comprimes, se moverá más veces por segundo hacia arriba y hacia abajo, lo que producirá un sonido más agudo. Significa que doblando la cantidad de movimientos verticales (oscilaciones) dobla la frecuencia. Así: ejecutar tu sampleo al doble de velocidad, doblará la frecuencia escuchada. Asimismo, reduciendo la velocidad a la mitad, también reduce la frecuencia a la mitad. Otras velocidades afectarán la frecuencia en acordancia.


3.4 - Sobres para sampleos

Es posible modificar la duración y amplitud de un sampleo usando un sobre ADSR. sin embargo, esto funciona algo diferentemente que con los sintetizadores (synths), ya que los sobres para sampleos sólo te permiten reducir la amplitud y duración de un sampleo, pero nunca incrementarlo. El sampleo terminará su ejecución ya sea cuando se acabe o cuando el sobre lo haga, lo que suceda antes. Así que si utilizas un largo ‘release’, ello no extenderá la duración del sampleo.

Sobres para Amen

Volvamos a nuestro amigo, el Amen Break:

sample :loop_amen

Sin operandos, escuchamos el sampleo completo y amplitud completa. Si quisiéramos aparecerlo dentro de 1 segundo, podemos utilizar el parámetro attack::

sample :loop_amen, attack: 1

Para un desaparecimiento más corto, elegiríamos un valor de ataque menor:

sample :loop_amen, attack: 0.3

Sustain Automático

Donde el sobre ADSR difiera en su conducta con el de un sintetizador es en el valor del sustain. En el sobre de un sintetizador, el sustain está predeterminado a 0 si no lo cambias manualmente. Con sampleos, el valor predeterminado de sustain está en automágico - el tiempo que resta para terminar el resto del sampleo. A ello se debe que podamos escuchar el sampleo completo cuando no pasamos parámetros. Si los valores de ataque, decaimiento,sustain y release fueran 0, nunca escucharíamos el sampleo. Por eso Sonic Pi calcula qué tan largo es el sampleo, deduce su ataque, decaimiento y tiempo de release, para utilizar esa sumatoria como tiempo de sustain. Si los valores de ataque, decaimiento y release son mayores al sampleo, el sustain se vuelve 0, simplemente.

Apagando (fade out)

Para explorar esto, consideremos nuestra pista Amen break en detalle. Si le preguntamos a Sonic Pi cuán largo es el sampleo:

print sample_duration :loop_amen

Imprimirá 1.753310657596372 que es el tamaño del sampleo en segundos. Consideremos redondearlo a 1.75 por conveniencia. Ahora, si seteamos el release a 0.75, algo sorpresivo pasará:

sample :loop_amen, release: 0.75

Ejecutará el primer segundo del sampleo a amplitud completa antes de desvanecerse por un periodo de 0.75 segundos. Esto es el auto sustain en acción. Predeterminado, el release siempre trabaja al final del sampleo. si tu sampleo fuera 10.75 segundos de largo, ejecutaría los primeros 10 segundos a completa amplitud antes de comenzar a desvanecerse por los 0.75 segundos finales.

Recuerda: por defecto, release: se desvanece al final de un sample.

Aparecimiento y desvanecimiento (Fade In and Out)

Podemos utilizar tanto el attack: como el release: juntos con el auto sustain para aparecer y desvanecer en la duración del sampleo:

sample :loop_amen, attack: 0.75, release: 0.75

Como la duración total del sampleo + attack + release suman 1.5s, el sustain queda automáticamente en 0.25s. Esto nos permite aparecer y desvanecer el sampleo con facilidad.

Sostenido explícito

Podemos fácilmente volver a los parámetros normales de nuestro ADSR de sintetizador al setear manualmente el sustain: a un valor como 0:

sample :loop_amen, sustain: 0, release: 0.75

Ahora bien, nuestro sampleo suena por 0.75 en total. Los parámetros pre- determinados para ‘attack: y decay:` son 0, el sampleo salta directamente a full amplitud por 0s y después baja a 0 de amplitud por un periodo de release de 0.75s

Címbalos

Podemos utilizar esta conducta a buen efecto para sampleos más largos que requieran los acortemos y percusivos. Considera el siguiente sampleo: :drum_cymbal_open:

sample :drum_cymbal_open

Puedes escuchar el sonido del platillo por un periodo de tiempo. Sin embargo, podemos usar el sobre para hacerlo más percusivo:

sample :drum_cymbal_open, attack: 0.01, sustain: 0, release: 0.1

Puedes emular el golpeo del platillo y después apagarlo, al incrementar el periodo de sustain:

sample :drum_cymbal_open, attack: 0.01, sustain: 0.3, release: 0.1

Ahora ve y diviértete poniendo sobres en los sampleos. Intenta cambiar la velocidad, también para unos resultados realmente interesantes.


3.5 - Sampleos parciales

Esta sección concluirá nuestra exploración del ejecuta sampleos de Sonic Pi. Hagamos un pequeño resumen; Hasta ahora hemos mirado cómo podemos disparar sampleos:

sample :loop_amen

Después miramos cómo cambiar la velocidad de los sampleos tales como ejecutarlos a media velocidad:

sample :loop_amen, rate: 0.5

Después miramos como podíamos aparecer un pequeño sampleo (haámoslo a media velocidad):

sample :loop_amen, rate: 0.5, attack: 1

También miramos como podíamos usar el comienzo de un sampleo percusivamente al darle a sustain: un valor explícito y setear ambos el ataque y el release con valores cortos:

sample :loop_amen, rate: 2, attack: 0.01, sustain: 0, release: 0.35

Sin embargo, ¿No sería mejor si no tuviésemos que comenzar por el principio ó terminar por el fin..siempre?

Escogiendo un punto de inicio

Es posible elegir un punto de inicio arbitrario en el sampleo con un valor entre 0 y 1, donde 0 es el punto de comienzo, 1 es el punto de final y 0.5 es la mitad del sampleo. Intentemos ejecutar únicamente la última mitad del sampleo de amen break:

sample :loop_amen, start: 0.5

¿Qué tal escuchar el último cuarto del sample?:

sample :loop_amen, start: 0.75

Escogiendo punto de termino

Igualmente, es posible escoger un punto de termino arbitrario en el sample, con un valor entre 0 y 1. Vamos a terminar el amen break a la mitad:

sample :loop_amen, finish: 0.5

Especificando el comienzo y el fin

Por supuesto que podemos combinar dos para tocar segmentos del archivo de audio arbitrariamente. ¿Qué tal una pequeña sección en el medio?

sample :loop_amen, start: 0.4, finish: 0.6

¿Qué pasa si elegimos comenzar en una posición después del final?

sample :loop_amen, start: 0.6, finish: 0.4

¡Cool! ¡Se toca al revés!

Combinando con velocidad

Podemos combinar esta nueva herramienta para tocar segmentos arbitrarios de audio con nuestro amigo rate:. Por ejemplo, podemos tocar una pequeña sección al medio de amen break muy lentamente:

sample :loop_amen, start: 0.5, finish: 0.7, rate: 0.2

Combinando con sobres

Finalmente podemos combinar todo esto con el sobre ADSR para producir resultados interesantes:

sample :loop_amen, start: 0.5, finish: 0.8, rate: -0.2, attack: 0.3, release: 1

Ahora vete y juega con sampleos y todas estas divertidas herramientas…


- Samples externos

Mientras los samples incluidos te ayudan a iniciar rápido, quizá quieras experimentar con otros sonidos grabados en tu música. Sonic Pi lo soporta completamente. Primero, revisemos brevemente la portabilidad de tu pieza musical.

Portabilidad

Cuando compones una pieza solamente con sintetizadores y samples incluidos, el código es todo lo que necesitas para reproducir tu música. Piensa en esto por un momento - es maravilloso! Un texto sencillo que puedes enviar por email o pegar en un Gist representa todo lo que necesitas para reproducir tus sonidos. Eso hace que sea realmente fácil de compartir con tus amigos que sólo necesitan tu código.

Por otra parte, si usas tus samples pregrabados, pierdes esta portabilidad. Esto es debido a que reproducir tu música, otras personas no solo necesitan tu código, necesitan tus samples también. Esto limita la habilidad para otros de manipular, combinar y experimentar con tu trabajo. Por supuesto, esto no debe detenerte para usar tus propios samples, es solamente algo a considerar.

Samples locales

¿Cómo reproduces cualquier archivo WAV, AIFF o FLAC en tu computadora? Todo lo que necesitas es indicar la ubicación del archivo en sample:

# Raspberry Pi, Mac, Linux
sample "/Users/sam/Desktop/my-sound.wav"
# Windows
sample "C:/Users/sam/Desktop/my-sound.wav"

Sonic Pi cargará y reproducirá el sample. También puedes indicar todos los parámetros estándar que acostumbras, indicando a sample:

# Raspberry Pi, Mac, Linux
sample "/Users/sam/Desktop/my-sound.wav", rate: 0.5, amp: 0.3
# Windows
sample "C:/Users/sam/Desktop/my-sound.wav", rate: 0.5, amp: 0.3

3.7 - Paquete de samples

Nota: esta sección del tutorial cubre un tema avanzado con directorios grandes de tus propios samples. Este puede ser el caso si has descargado o comprado tus paquetes de samples y deseas usarlos en Sonic Pi.

Siéntete libre de leer esto si estás feliz usando los samples incluídos.

Cuando trabajas con carpetas grandes de samples externos puede ser difícil tener que escribir toda la ruta cada vez que quieras usar un sample.

Por ejemplo, si tienes la siguiente carpeta en tu máquina:

/path/to/my/samples/

Cuando vemos dentro de la carpeta, encontramos los siguientes samples:

100_A#_melody1.wav 100_A#_melody2.wav 100_A#_melody3.wav 120_A#_melody4.wav 120_Bb_guit1.wav 120_Bb_piano1.wav

Típicamente, para reproducir un sample de piano, podemos usar la ruta completa:

sample "/path/to/my/samples/120_Bb_piano1.wav"

Si queremos reproducir un sample de guitarra podemos usar su ruta completa también:

sample "/path/to/my/samples/120_Bb_guit.wav"

Sin embargo, cada uno de estos llamados a sample requieren que sepamos los nombres de los samples en nuestro directorio. ¿Que tal si solo quisiéramos escuchar cada sample, uno tras otro, rápidamente?

Indexando los paquetes de samples

Si queremos reproducir el primer sample en un directorio, necesitamos indicar el nombre del directorio en sample y el índice 0 de la siguiente manera:

sample "/path/to/my/samples/", 0

Podemos incluso hacer un acceso directo a la ruta de nuestro directorio usando una variable:

samps = "/path/to/my/samples/"
sample samps, 0

Ahora, si queremos reproducir un segundo sample en nuestro directorio, sólo necesitamos añadir 1 a nuestro índice:

samps = "/path/to/my/samples/"
sample samps, 1

Date cuenta de que ya no necesitamos saber los nombres de los samples en el directorio - solamente debemos conocer el directorio (o tener una abreviatura para él). Si requerimos un indice que es mas grande que el numero de samples, simplemente retornamos al principio del directorio como si fuera un anillo. De cualquier manera, sin importar el número de índice que usemos, esta garantizado que tendremos un sample del directorio.

Filtrar paquetes de samples

Usualmente con indexarlos es suficiente, pero algunas veces necesitamos algo mas poderoso para organizar nuestros samples. Afortunadamente muchos paquetes de samples añaden información valiosa en los nombres de los archivos. Ahora miremos de nuevo los nombres de los samples en nuestro directorio:

100_A#_melody1.wav 100_A#_melody2.wav 100_A#_melody3.wav 120_A#_melody4.wav 120_Bb_guit1.wav 120_Bb_piano1.wav

Date cuenta de que en estos nombres de archivo tenemos bastante información. En primer lugar tenemos el BPM del sample (número de pulsaciones por minuto) al comienzo. Por lo tanto, el sample del piano está a 120 BPM y nuestras primeras tres melodías están a 100 BPM. Además, nuestros nombres de los samples contienen la clave musical. Por tanto, el sample de la guitarra está en Bb (si bemol) y las melodías están en A# (la sostenido). Esta información es muy útil para mezclar estos samples con el resto del código. Por ejemplo, sabemos que solamente podemos usar el sample del piano con código que está a 120 BPM y en la clave de Bb.

Podemos usar como convención esta nomenclatura de nuestros conjuntos de samples en el código para ayudarnos a filtrar los que queremos. Por ejemplo, si trabajamos a 120 BPM, podemos filtrar a todos los ejemplos que contienen la cadena " 120 " con lo siguiente:

samps = "/path/to/my/samples/"
sample samps, "120"

Ésto ejecutará el primer sample. Si queremos el segundo sample sólo necesitamos usar el índice:

samps = "/path/to/my/samples/"
sample samps, "120", 1

Incluso podemos usar varios filtros al mismo tiempo. Por ejemplo, si queremos un sample cuyo nombre de archivo contenga las subcadenas “120” y “A #”, lo encontraremos fácilmente con el siguiente código:

samps = "/path/to/my/samples/"
sample samps, "120", "A#"

Por último, podemos añadir las opciones habituales al sample:

samps = "/path/to/my/samples/"
sample samps, "120", "Bb", 1, lpf: 70, amp: 2

Fuentes

El sistema de pre-arg de filtro del sample entiende dos tipos de información: fuentes y filtros. Las fuentes son información utilizada para crear la lista de candidatos potenciales. Una fuente puede tomar dos formas:

“/path/to/samples” - una cadena que representa una ruta de acceso válida a un directorio “/path/to/samples/foo.wav” - Una cadena que representa una ruta válida a un sample

El ‘sample’ fn primero coge todas las fuentes y crear una lista con todos los candidatos. Esta lista se construye agregando primero todas las rutas válidas y añadiendo, luego, todos los ficheros .flac, .aif, .aiff, .wav, .wave contenidos en los directorios.

Por ejemplo, echemos un vistazo al siguiente código:

samps = "/path/to/my/samples/"
samps2 = "/path/to/my/samples2/"
path = "/path/to/my/samples3/foo.wav"
sample samps, samps2, path, 0

Aquí, combinamos el contenido de los samples dentro de dos directorios y añadiendo un sample específico. Si "/path/to/my/samples/" contiene 3 samples y "/path/to/my/samples2/" contiene 12, tenemos 16 samples potenciales para indexar y filtrar (3 + 12 + 1).

Por defecto, sólo los samples de un directorio se agrupan en una lista de candidatos. Es posible que tenga una serie de subcarpetas de samples en la que quieras buscar y filtrar. Por lo tanto, puedes realizar una búsqueda recursiva de todas los samples dentro de todas las subcarpetas de una carpeta determinada añadiendo ** al final de la ruta:

samps = "/path/to/nested/samples/**"
sample samps, 0

Ten cuidado ya que la búsqueda en un conjunto muy grande de carpetas puede tomar mucho tiempo. Sin embargo, el contenido de todas las fuentes de las carpetas se almacenan en el caché, por lo que el retraso sólo se producirá la primera vez.

Por último, ten en cuenta que las fuentes deben ir primero. Si no se da ninguna fuente, entonces el conjunto de samples incorporados se seleccionará de la lista predeterminada de candidatos con los que trabajar.

Filtros

Una vez que tienes una lista de candidatos deberías usar los siguientes tipos de filtros para reducir aún más la selección:

`` Foo ‘Las cadenas filtrarán la ocurrencia de la subcadena dentro del nombre de archivo (menos la ruta del directorio y la extensión). /fo[oO]/ Regular Expressions will filter on pattern matching of file name (minus directory path and extension). :foo - Keywords will filter candidates on whether the keyword is a direct match of the filename (minus directory path and extension). lambda{|a| … } - Procs with one argument will be treated as a candidate filter or generator function. It will be passed the list of current candidates and must return a new list of candidates (a list of valid paths to sample files). 1` - Numbers will select the candidate with that index (wrapping round like a ring if necessary).

Por ejemplo, podemos filtrar sobre todos las muestras en un directorio que contengan el string "foo" y ejecutar la primera muestra correspondiente a la mitad de su velocidad:

sample "/path/to/samples", "foo", rate: 0.5

See the help for sample for many detailed usage examples. Note that the ordering of the filters is honoured.

Composites

Finally, you may use lists wherever you may place a source or filter. The list will be automatically flattened and the contents will be treated as regular sources and filters. Therefore the following calls to sample are semantically equivalent:

sample "/path/to/dir", "100", "C#"
sample ["/path/to/dir", "100", "C#"]
sample "/path/to/dir", ["100", "C#"]
sample ["/path/to/dir", ["100", ["C#"]]]

Wrapping Up

This was an advanced section for people that need real power to manipulate and use sample packs. If most of this section didn’t make too much sense, don’t worry. It’s likely you don’t need any of this functionality just yet. However, you’ll know when you do need it and you can come back and re-read this when you start working with large directories of samples.


4 - Aleatoriedad

Una manera de añadir interés a tu música es usando números aleatorios. Sonic Pi tiene gran funcionalidad añadiendo aleatoriedad a la música, pero antes de comenzar, debemos aprender una verdad chocante: en Sonic Pi no existe aleatoriedad real. ¿Qué significa eso?

Repetibilidad

Una función realmente útil es rrand la cual te da un valor aleatorio entre dos números - un min y un max. (rrand es la abreviatura para ranged random). Intentemos tocar una nota al azar:

play rrand(50, 95)

¡Ooh, tocó una nota al azar! Tocó la nota 83.7527. Una nota entre 50 y 95 Woah, espera, predije el número correcto que obtuviste? ¡Algo raro sucede! Intenta con el código de nuevo. ¿qué? Otra vez 83.7527 ? ¡Eso no es aleatorio!

La respuesta es que no es realmente aleatorio, es pseudo-aleatorio. Sonic Pi te dará números como al azar en una manera repetitiva, lo cual es muy útil para asegurar que la música que creas en tú máquina suene idéntica en cualquier otra máquina - aunque utilices números al azar en tú composición.

Claro que en una pieza musical donde quieras colocar notas al “azar” y siempre eliga 83.7527 no sería ni aleatorio ni interesante. Sin embargo, no es así. Intenta lo siguiente:

loop do
  play rrand(50, 95)
  sleep 0.5
end 

¡Sí! Finalmente suena aleatorio. Dentro de una misma corrida las subsecuentes llamadas a funciones aleatorias dan valores..aleatorios. Sin embargo, la próxima corrida volverá a dar la misma secuencia de valores “aleatorios” y sonar exactamente igual. Es como si Sonic Pi volvió en el tiempo al mismo punto cuando se corrió run la primera vez. ¡Es el Groundhog Day de la síntesis musical!

Haunted Bells

Una buena ilustración de aleatoriedad en acción es el ejemplo haunted bells que buclee el sampleo de :perc_bell con velocidad de Aleatoriedad y tiempo de pausa entre los sonidos:

loop do
  sample :perc_bell, rate: (rrand 0.125, 1.5)
  sleep rrand(0.2, 2)
end

Corte aleatorio

Otro buen ejemplo de aleatoriedad es modificar el momento de corte de un sintetizador, en forma aleatoria. Un gran synth en el que hacerlo es el emulador :tb303

use_synth :tb303
loop do
  play 50, release: 0.1, cutoff: rrand(60, 120)
  sleep 0.125
end

Semillas aleatorias

¿Entonces qué, no te gusta la particular secuencia de números al azar que provee Sonic Pi? Bueno, es totalmente posible elegir un punto de comienzo via use_random_seed. Predeterminado está a 0, así que: ¡elige una semilla diferente para una aleatoriedad diferente!

Considera lo siguiente:

5.times do
  play rrand(50, 100)
  sleep 0.5
end

Cada vez que corras ese código escucharás la misma secuencia de 5 notas. Para cambiar la secuencia, simplemente cambia el valor de seed_:

use_random_seed 40
5.times do
  play rrand(50, 100)
  sleep 0.5
end

Esto producirá una diferente secuencia de 5 notas. Al cambiar el valor de seed y escuchar los resultados, puedes encontrar algo que te guste y cuando lo compartas con otros, escucharán exactamente lo mismo.

Veamos otras útiles funciones de aleatoriedad.

Elegir (choose)

Una cuestión común es elegir un ítem desde una lista de ítems conocidos Por ejemplo, quiero tocar una nota de entre las siguientes: 60, 65 or 72. Puedo lograr eso con choose pues me deja elegir un ítem de esa lista. Primero necesito confeccionar mi listado entre paréntesis cuadrados y separándolos por comas: [60, 65, 72]. Después sólo necesito pasarlos por choose:

choose([60, 65, 72])

Escuchemos como suena:

loop do
  play choose([60, 65, 72])
  sleep 1
end

Rango aleatorio (rrand)

Ya hemos visto la función rrand, pero adentrémonos más en ella. Nos proporciona un número aleatorio entre dos valores. Eso significa que nunca nos dará los números extremos del rango, sólo entre ellos. Ese número será un ‘flotante’, lo que significa que no es un número entero, sino una fracción de número. He aquí ejemplos de flotantes: rrand(20, 110):

87.5054931640625 86.05255126953125 61.77825927734375

Rango aleatorio ínclusivo ( rrand_i)

Ocasionalmente querrás un número entero aleatorio, no un flotante. Es entonces que rrand_i viene al rescate. Funcional similarmente a rrand excepto que incluye los valores mínimo y máximo como potenciales aleatorios (lo que significa que es inclusiva y no excluyente de los valores extremos del rango). Ejemplos de números con rrand_i(20, 110) son:

88 86 62

rand

Esta función te regresará un número aleatorio flotante incluyendo los valores 0 y el máximo especificado. Predeterminado está el rango entre 0 y 1. Por ello es útil para elegir valores de amp: aleatorios:

loop do
  play 60, amp: rand
  sleep 0.25
end

rand_i

De maneara similar a rrand_i y rrand, rand_i nos dará un número leatorio ENTERO entre 0 y el máximo especificado.

Dado (dice)

Alguna vez querrás emular el tiro de un dado. Para ello tenemos un caso especial de rrand_i donde el valor inferior será siempre 1. El uso de dice requiere que especifiques el número de lados del dado. Un dado estándard tiene 6 lados, así dice(6) actuará similarmente, dando valores de1, 2, 3, 4, 5, or 6. Sin embargo, como en los juegos de role-play encontrarás necesidad de un dado de 4, 12, 20 o inclusive de 120 caras..

one_in

Finalmente cuando quieras emular tirar el máximo puntaje con un dado, como 6 en un dado estándard one_in te dará eso con una posibilidad de uno en número de lados del dado. Por lo tanto, one_in(6) nos dará verdad con una probabilidad de 1 en 6 o falso. Verdadero y falso son valores muy útiles para if el cual cubriremos en la siguiente sección de este tutorial.

¡Ahora ve a jugar con códigos y algo de aleatoriedad!


5 - Estructuras de Programación

Ahora que has aprendido lo básico de crear sonidos con play y sample y crear ritmos y melodías simples con sleep en medio de los sonidos, podrías preguntarte ¿Qué es lo que codificar puede ofrecerte?

Bueno, estás a punto de ser sorprendido, porque resulta que herramientas básicas de estructuras de programación como bules, condicionales, funciones e hilos, te dan grandes posibilidades de expresión musical.

Concentrémonos en la base…


5.1 - Bloques

Una estructura que verás a menudo en Sonic Pi es el bloque. Los Bloques nos permiten hacer cosas útiles con largas sábanas de código. Por ejemplo, con parámetros de synth y sample podíamos cambiar cosas en una sóla línea. sin embargo, algunas veces queremos hacer algo significativo para un número de líneas de código. Por ejemplo buclear, añadir reverberación, pero sólo correrlo 1 de cada 5 veces. Considera el siguiente código:

play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62

Para hacer algo con un manojo de códifo, necesitamos decirle a Sonic Pi dónde comienza el bloque de código y dónde termina. Usamos para el comienzo do y para el final end . Por ejemplo:

do
  play 50
  sleep 0.5
  sample :elec_plip
  sleep 0.5
  play 62
end

Sin embargo, ese código está incompleto, porque no le hemos dicho a Sonic Pi lo que queremos hacer con ese bloque do/end (intenta y te dará error). Eso se lo decimos a Sonic Pi al escribir algunos códigos especiales antes del do. Veremos un estos códigos especiales más adelante en este tutorial Por ahora es importante conocer que envolver tu código entre do y end le dice a Sonic Pi que deseas hacer algo especial con ese pedazo de código.


5.2 - Iteración y Bucles

Hasta ahora hemos invertido tiempo en los diferentes sonidos que puedes crear con bloques de play y sample. También hemos aprendido a disparar estos sonidos a través de sleep.

Como probablemente ya notaste, hay mucha diversión a ser obtenida con estos bloques básicos de construcción. Sin embargo, una dimensión totalmente diferente de diversión se abre cuando comienzas a usar el poder de codificar para estructurar tu música y composiciones. En los próximos segmentos exploraremos algunas de estas poderosas herramientas. Primero están las iteraciones y bucles.

Repetición

¿Has escrito código que te gustaría se repita unas cuantas veces? Por ejemplo, algo así:

play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25

¿qué tal si quieeres repetirlo 3 veces? Bueno, podrías hacer algo simple y copiarlo 3 veces:

play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25

¡Eso fué bastante código! ¿qué pasa si quieres cambiar el sample a :elec_plip? Tendrías que buscar todos los lugares con el original :elec_blup y cambiarlo. Más importantemente, ¿qué si quisieras repetir l apieza original 1000 veces? Eso tomaría muchas líneas de código y lugares a los que ir a alterar si quisieses cambiar algo.

Iteración

De hecho, repetir código debería ser tan fácil como decirle haz esto tres veces. Bueno, así es, casi..Recuerda nuestro viejo amigo el bloque de código, lo podemos usar para marcar el comienzo y final de código que querramos repetir tres veces. Después usamos el código especial 3.times. Así, en vez de escribir do this three times, escribimos 3.times do - ¿sencillo, no? Sólo recuerda escribir end al final del código que quieras repetir:

3.times do
  play 50
  sleep 0.5
  sample :elec_blup
  sleep 0.5
  play 62
  sleep 0.25
end

¿Eso fué mucho más elegante que cortar y pegar! Así crearemos muchas estructuras repetitivas_:

4.times do
  play 50
  sleep 0.5
end
8.times do
  play 55, release: 0.2
  sleep 0.25
end
4.times do
  play 50
  sleep 0.5
end

Iteraciones anidadas

Podemos insertar iteraciones dentro de iteraciones para crear patrones interesantes. Por ejemplo:

4.times do
  sample :drum_heavy_kick
  2.times do
    sample :elec_blip2, rate: 2
    sleep 0.25
  end
  sample :elec_snare
  4.times do
    sample :drum_tom_mid_soft
    sleep 0.125
  end
end

Bucleando

Si deseas que algo se repita muchas veces, te puedes encontrar usando números realmente grandes como 1000.times do. En este caso es mejor pedirle a Sonic Pi que repita al infinito (hasta que aprietes el botón de parar). Bucleemos el amen break infinitamente:

loop do
  sample :loop_amen
  sleep sample_duration :loop_amen
end

Lo importante de saber acerca de los blucles (loops) es que actúan como hoyos negros para el código. Una vez que se entra ahí, sólo se sale con el botón de parar (stop). Esto significa que si tienes código después del loop, nunca lo escucharás. Por ejemplo, el platillo después de este bucle nunca se ejecutará:

loop do
  play 50
  sleep 1
end
sample :drum_cymbal_open

¡Ahora ve a estructurar tus códigos con iteración y bucles!


5.3 - condicionales

Algo común que seguramente querrás hacer es tocar más que notas al azar sino también tomar decisiones al azar y, dependiendo de cómo salga, correr más código u otro código. Por ejemplo, el querer tocar al azar una batería o platillo. Esto lo podemos hacer con if .

Tirar una moneda

Tiremos una moneda: si sale cara, que suene una batería, si sale cruz, que sea un platillo. Fácil. Podemos imitar el tiro de una moneda con la función one_in (introducida en la sección de aleatoriedad) especificando una probabilidad de 1 en 2 one_in(2). Entonces podemos utilizar el resultado para decidir entre dos piezas de código, el de batería o el de platillos:

loop do
  if one_in(2)
    sample :drum_heavy_kick
  else
    sample :drum_cymbal_closed
  end
  
  sleep 0.5
  
end

Debes notar que los if están compuestos de tres partes:

La pregunta a hacer La primera elección de código a correr (si la respuesta es ‘si’) La segunda elección de código a correr (si la respuesta es ‘no’)

Típico de lenguajes de programación, la noción de ‘sí’ está representada por el término true y la noción de ‘no’, por false. Así que debemos encontrar una pregunta que nos dé una respuesta true ofalse que es exactamente lo que hace one_in .

¿notas que la primera opción está envuelta entre el if y el else y que la segunda opción está envuelta entre el else y el end?. Igual que con los bloques do/end puedes poner múltiples líneas de código en cualquiera de esos lugares. Por ejemplo:

loop do
  if one_in(2)
    sample :drum_heavy_kick
    sleep 0.5
  else
    sample :drum_cymbal_closed
    sleep 0.25
  end
  
end

Esta vez estaremos pausando por un tiempo distinto dependiendo de cuál elección hagamos.

Condicional simple “if”

Algunas veces querrás ejecutar sólo una línea de código. Esto es posible al colocar if y después la pregunta al final. Por ejemplo:

use_synth :dsaw
loop do
  play 50, amp: 0.3, release: 2
  play 53, amp: 0.3, release: 2 if one_in(2)
  play 57, amp: 0.3, release: 2 if one_in(3)
  play 60, amp: 0.3, release: 2 if one_in(4)
  sleep 1.5
end

Eso tocará acordes de diferentes números con una probabilidad diferente para cada nota .


5.4 - Hilos

Así que hiciste una gran línea de bajo y un gran pulso. ¿cómo los tocas al mismo tiempo? Una manera de hacerlo es coserlos juntos manualmente - toca bajo, después un poco de batería y así… Sin embargo, cada vez se vuelve más complicado mantener el timing, especialmente Si’coses’ más y más elementos.

¿qué tal si Sonic Pi pudiese coser todo automáticamente para tí? Bueno, puede y lo hace con algo especial llamado thread.

Bucles infinitos

Para mantener este ejemplo sencillo, vas a tener que imaginar que es un gran pulso y bajo:

loop do
  sample :drum_heavy_kick
  sleep 1
end
loop do
  use_synth :fm
  play 40, release: 0.2
  sleep 0.5
end

Como vimos anteriormente, bucles son como ‘hoyos negros’ para el programa, una vez entras a uno, sólo puedes salir de él con el botón ‘stop’. Así que para tocar ambos bucles al mismo tiempo, debemos indicarle a Sonic Pi que queremos comenzar algo al mismo tiempo que el resto del código, aquí es cuando los hilos vienen al rescate.

Hilos al rescate

in_thread do
  loop do
    sample :drum_heavy_kick
    sleep 1
  end
end
loop do
  use_synth :fm
  play 40, release: 0.2
  sleep 0.5
end

Al envolver el primer bucle de bloque do/end con in_thread le decimos a Sonic Pi que corra los contenidos del bloque do/end exactamente al mismo tiempo que el siguiente bloque do/end (que es nuestro segundo bucle) ¿Inténtalo y escucharás ambos, el bajo y la batería conectados!

Ahora, si quisiésemos añadir un sintetizador, haríamos algo así:

in_thread do
  loop do
    sample :drum_heavy_kick
    sleep 1
  end
end
loop do
  use_synth :fm
  play 40, release: 0.2
  sleep 0.5
end
loop do
  use_synth :zawa
  play 52, release: 2.5, phase: 2, amp: 0.5
  sleep 2
end

Ahora volvemos a tener el mismo problema que antes, ya que los primeros dos bucles se tocan al mismo tiempo, gracias a in_thread. Sin embargo, el tercer bucle nunca se alcanza. Por lo tanto, necesitamos otro hilo:

in_thread do
  loop do
    sample :drum_heavy_kick
    sleep 1
  end
end
in_thread do
  loop do
    use_synth :fm
    play 40, release: 0.2
    sleep 0.5
  end
end
loop do
  use_synth :zawa
  play 52, release: 2.5, phase: 2, amp: 0.5
  sleep 2
end

Ejecutar como hilos

Puede sorprenderte que cuando aprietas el botón de Correr (Run), de hecho estás creando un nuevo hilo para que corra el código. Esta es la razón por la que al apretar el botón múltiples veces, suenan las capas de sonido una encima de la otra, ya que las corridas son de hecho hilos cosidos automáticamente para sonar.

Ámbito

En cuanto más aprendas Sonic Pi, apreciarás que los hilos son los bloques de construcción más importantes para tú música. Uno de los trabajos más importantes que realiza es aislar la noción de seteos actuales respecto a otros hilos. ¿qué significa eso? Bien, cuando cambias sintetizadores por medio de use_synth realmente estás cambiando el sintetizdor en el hilo actual, ya que ningún otro hilo cambiarás su sintetizador. Veamos esto en acción:

play 50
sleep 1
in_thread do
  use_synth :tb303
  play 50
end
sleep 1
play 50

¿Notaste que el sonido de en medio era diferente a los otros? el use_synth solamente afectó el hilo en el que se encontraba, no así el hilo externo principal.

Herencia

Cuando creas un nuevo hilo con in_thread, este automáticamente hereda la configuración del hilo actual. Veamos:

use_synth :tb303
play 50
sleep 1
in_thread do
  play 55
end

¿Notaste que la segunda nota es tocada por el sintetizador :tb303 aunque era de un hilo separado? Cualquier seteo modificado con las funciones use_* se comportará de igual manera.

Cuando se crean hilos, ellos heredan todos los seteos de su padre, pero no los comparten a su vez.

Nombres para los Hilos

Por último, podemos darles nombre a los hilos:

in_thread(name: :bass) do
  loop do
    use_synth :prophet
    play chord(:e2, :m7).choose, release: 0.6
    sleep 0.5
  end
end
in_thread(name: :drums) do
  loop do
    sample :elec_snare
    sleep 1
  end
end

Mira el panel de bitácora cuando corras este código. ¿ves que reporta el nombre del hilo?

[Run 36, Time 4.0, Thread :bass]
 |- synth :prophet, {release: 0.6, note: 47}

Sólo es permitido un nombre por hilo

Una cosa más al respecto de nombrar hilos es que sólo un hilo con su nombre puede estar corriendo a la vez. Exploremos esto, considerando el código:

in_thread do
  loop do
    sample :loop_amen
    sleep sample_duration :loop_amen
  end
end

Pega eso en un buffer y córrelo. Presiona Correr un par de veces. Escucha la cacofonía de los múltiples amen breaks bucleando desincronizadamente. Ok, ya puedes pararlo.

Esta es la conducta que hemos visto innumerables veces - si presionas el botón Correr, capas de sonidos suenan encima de otras. Así que si tienes un loop y presionas el botón Correr tres veces, obtendrás tres capas de bucles sonando simultáneamente.

sin embargo, con hilos nombrados, es diferente:

in_thread(name: :amen) do
  loop do
    sample :loop_amen
    sleep sample_duration :loop_amen
  end
end

Intenta presionando el botón Correr múltiples veces con este código. Sólo escucharás un bucle del amen break. También verás lo siguiente en la bitácora:

==> Omitiendo creación de hilo: ya existe un hilo con el nombre :amen.

Sonic Pi te está diciendo que un hilo con el nombre :amen ya existe, así que no creará otro.

Esta conducta puede no aparentar utilidad para tí - pero verás que la tiene cuando comencemos a hacer Código-vivo…


5.5 - Funciones

Cuando comiences a escribir mucho código, desearás encontrar una manera de organizar y estructurar todo para hacerlo más entendible. Las funciones permiten hacer exactamente eso, permitiéndonos darle nombre a muchas partes de nuestro código. Veamos:

Definiendo Funciones

define :foo do
  play 50
  sleep 1
  play 55
  sleep 2
end

Aquí definimos una nueva función llamada foo. Lo hacemos con nuestro viejo amigo el bloque de do/end y la palabra mágica define seguidos del nombre que queremos darle a nuestra función. No necesitábamos llamarla foo, podríamos haberla llamado cualquier cosa que quisiésemos, tales como bar, baz o idealmente algo significativo para tí como main_section o lead_riff.

Recuerda anteponer dos puntos : al nombre de la función que defines.

Llamando las Funciones

Una vez hemos definido nuestra función, podemos llamarla simplemente escribiendo su nombre:

define :foo do
  play 50
  sleep 1
  play 55
  sleep 0.5
end
foo
sleep 1
2.times do
  foo
end

Incluso podemos usar foo dentro de bloques de iteración o cualquier lugar donde hayamos escrito play o sample. Esto nos da una fantástica manera de expresar y crear nuevas palabras significativas a usar en nuestras composiciones.

Las funciones permanecen en memoria

Hasta ahora, cada vez que presionamos el botón de Ejecutar, Sonic Pi ha comenzado de cero. Sólo conoce lo que está en el buffer actual. No puedes referenciar código en otro buffer o hilo. sin embargo, las funciones cambian eso. Cuando defines una función, Sonic Pi recuerda. Probemos borrando todo el código en tu buffer y reemplazandolo por:

foo

Presiona el botón de Ejecutar y escucha. ¿Dónde se fue el código?¿cómo supo Sonic Pi qué tocar? Sonic Pi recordó tu función, inclusive cuando la borraste del buffer. Esta conducta sólo funciona con las funciones creadas con define (y defonce).

Funciones parametrizadas

Quizás te interese saber que al igual que podías pasar valores mínimos y máximos con rrand, también puedes enseñar a tus funciones a aceptar argumentos. Miremos:

define :my_player do |n|
  play n
end
my_player 80
sleep 0.5
my_player 90

Esto no es tan excitante, pero ilustra el punto. Creamos nuestra propia versión de play llamada my_player y la cual está parametrizada.

Los parámetros deben ir después del do y define en el bloque do/end, rodeado de postes verticales | y separados por comas ,. Puedes usar cualquier palabra para los nombres de los parámetros.

Lo mágico sucede dentro del bloque do/end del define . Puedes usar nombres de parámetros como si fueran valores reales. En este ejemplo estoy tocando la nota n. Puedes considerar los parámetros como una especie de promesa de que cuando el código se ejecute, ellos serán reemplazados por los valores. Esto lo haces al pasar un parámetro a la función, cuando la llamas. Yo lo hago con my_player 80 para tocar la nota 80. Dentro de la definición de la función n se reemplaza con 80, así play n se convierte en play 80. Cuando la llamo otra vez con my_player 90, n es reemplazada por 90, así que play n se convierte en play 90.

Veamos un ejemplo más interesante:

define :chord_player do |root, repeats| 
  repeats.times do
    play chord(root, :minor), release: 0.3
    sleep 0.5
  end
end
chord_player :e3, 2
sleep 0.5
chord_player :a3, 3
chord_player :g3, 4
sleep 0.5
chord_player :e3, 3

Aquí usé repeats como si fuera un número para la línea de repeats.times do. También usé root como si fuera un nombre de nota en mi llamada a play.

¡Nota cómo podemos utilizar algo muy expresivo y fácil de leer sólo con mover mucho de nuestra lógica en el código!


5.6 - Variables

A useful thing to do in your code is to create names for things. Sonic Pi makes this very easy: you write the name you wish to use, an equal sign (=), then the thing you want to remember:

sample_name = :loop_amen

Aquí hemos ‘recordado’ el símbolo :loop_amen en la variable sample_name. Ahora podemos usar sample_name en cualquier lugar donde pudiésemos usar :loop_amen. Por ejemplo:

sample_name = :loop_amen
sample sample_name

Hay tres razones principales para utilizar variables en Sonic Pi: comunicar significado, administrar repeticón y capturar los resultados de las cosas.

Comunicando significado

Cuando escribes código, es fácil pensar que sólo le dices a la computadora cómo hacer algo - mientras ella entienda, todo está bien. Sin embargo, es importante recordar que no sólo la computadora leerá el código. Otra gente podría leerlo e intentar comprender qué es lo que sucede. También sucede que quieras entender tu propio código en el futuro. Aunque pueda ser obvio para tí, ahora, ¡podría no serlo para otros o para tí en el futuro! When you write code it’s easy to just think you’re telling the computer how to do stuff - as long as the computer understands it’s OK. However, it’s important to remember that it’s not just the computer that reads the code. Other people may read it too and try to understand what’s going on. Also, you’re likely to read your own code in the future and try to understand what’s going on. Although it might seem obvious to you now - it might not be so obvious to others or even your future self!

One way to help others understand what your code is doing is to write comments (as we saw in a previous section). Another is to use meaningful variable names. Look at this code:

sleep 1.7533

¿Por qué utiliza el número 1.7533? ¿de dónde proviene? ¿qué significa? Miremos el código siguiente:

loop_amen_duration = 1.7533
sleep loop_amen_duration

Ahora está mucho más claro lo que significa 1.7533: es la duración del sample :loop_amen! claro que puedes pensar que es mucho más simple escribir:

sleep sample_duration(:loop_amen)

Lo cual es una muy buena manera de comunicar la intención del código.

Administrando las repeticiones

a menudo ves muchas repeticiones en tu código y cuando quieres cambiar algo, tienes que cambiarlo enmuchos lugares. Mira este código:

sample :loop_amen
sleep sample_duration(:loop_amen)
sample :loop_amen, rate: 0.5
sleep sample_duration(:loop_amen, rate: 0.5)
sample :loop_amen
sleep sample_duration(:loop_amen)

Estamos haciendo muchas cosas con :loop_amen! ¿qué pasa si quisiésemos escuchar otro sampleo como :loop_garzul? tendríamos que buscar y reemplazar todos los :loop_amen con :loop_garzul. Eso estaría bien si tienes mucho tiempo - pero ¿qué si está en vivo? algunas veces no tendrás el lujo del tiempo - especialmente si quieres que la gente se mantenga bailando.

¿qué tal si hubieses escrito tú código, así?:

sample_name = :loop_amen
sample sample_name
sleep sample_duration(sample_name)
sample sample_name, rate: 0.5
sleep sample_duration(sample_name, rate: 0.5)
sample sample_name
sleep sample_duration(sample_name)

Eso hace exactamente lo mismo que lo anterior (pruébalo). también nos da la habilidad de cambiar una línea sample_name = :loop_amen a sample_name = :loop_garzul y podemos hacerlo en muchos lugares gracias a las variables.

Capturando los resultados

Un buen motivo para utilizar variables es capturar los resultados de las cosas. Por ejemplo, quizás desees hacer algo con la duración de un sampleo:

sd = sample_duration(:loop_amen)

Ahora podemos usar sd en cualquier lugar donde necesitemos la duración del sampleo :loop_amen.

Más importantemente, una variable nos permite capturar el resultado de una llamada a play o sample:

s = play 50, release: 8

Ahora hemos atrapado y recordado s como una variable, lo que nos permite controlar el sintetizador mientras corre:

s = play 50, release: 8
sleep 2
control s, note: 62

Veremos en más detalle cómo controlar los sintetizadores más tarde.

Warning: Variables and Threads

Whilst variables are great for giving things names and capturing the results of things, it is important to know that they should typically only be used locally within a thread. For example, don’t do this:

a = (ring 6, 5, 4, 3, 2, 1)
live_loop :shuffled do
  a = a.shuffle
  sleep 0.5
end
live_loop :sorted do
  a = a.sort
  sleep 0.5
  puts "sorted: ", a
end

In the above example we assign a ring of numbers to a variable a and then used it within two separate live_loops. In the first live loop every 0.5s we sort the ring (to (ring 1, 2, 3, 4, 5, 6)) and then print it out to the log. If you run the code, you’ll find that the printed list is not always sorted!. This may surprise you - especially that sometimes the list is printed as sorted, and sometimes it is not. This is called non-deterministic behaviour and is the result of a rather nasty problem called a race-condition. The problem is due to the fact that the second live loop is also manipulating the list (in this case shuffling it) and by the time the list is printed, sometimes it has just been sorted and sometimes it has just been shuffled. Both live loops are racing to do something different to the same variable and every time round a different loop ‘wins’.

There are two solutions to this. Firstly, don’t use the same variable in multiple live loops or threads. For example, the following code will always print a sorted list as each live loop has its own separate variable:

live_loop :shuffled do
  a = (ring 6, 5, 4, 3, 2, 1)
  a = a.shuffle
  sleep 0.5
end
live_loop :sorted do
  a = (ring 6, 5, 4, 3, 2, 1)
  a = a.sort
  sleep 0.5
  puts "sorted: ", a
end

However, sometimes we do want to share things across threads. For example, the current key, BPM, synth etc. In these cases, the solution is to use Sonic Pi’s special thread-safe state system via the fns get and set. This is discussed later on in section 10.


5.7 - Sincronización de hilos

Cuando estés lo suficientemente avanzado en live-coding con un número de funciones e hilos simultáneamente, notarás que es muy fácil cometer un error en uno de los hilos y eso lo mata. Eso no es gran cosa, porque puedes fácilmente recomenzar el hilo con apretar Run. Sin embargo, cuando recomiences el hilo estará out of time con los hilos actuales.

Tiempo heredado

Como discutíamos anteriormente, nuevos hilos creados con in_thread heredan todos los seteos del hilo padre. Esto incluye el tiempo actual, lo que significa que los hilos estarán siempre en el tiempo con los demás cuando comenzados simultáneamente.

Sin embargo, cuando comienzas un hilo aparte, comienza con su propio tiempo que difícilmente estará sincronizado con alguno de los otros que estén siendo corridos.

Cue y Sync (funciones)

Sonic Pi provee una solución a este problema con las funciones cue y sync.

cue permite enviar mensajes de pulso a todos los otros hilos, los cuales, en principio no están interesados e ignoran estos mensajes. Sin embargo. puedes registrar fácilmente su interés con la función sync.

Lo importante de notar es que sync es similar a sleep en que para el hilo actual por un tiempo. Sin embargo, con sleep tu especificas cuánto tiempo va a esperar, en cambio con sync no sabes cuánto tiempo esperará - ya que sync espera por el siguiente cue de otro hilo.

Exploremos esto en más detalle:

in_thread do
  loop do
    cue :tick
    sleep 1
  end
end
in_thread do
  loop do
    sync :tick
    sample :drum_heavy_kick
  end
end

Aquí tenemos dos hilos - uno actuando como un metrónomo, no haciendo sonidos sino que enviando :tick mensajes de pulso. El segundo hilo está sincronizandose con los mensajes de tick y cuando recibe uno, hereda el tiempo del hilo de cue y continúa tocando.

El resultado es que escuchamos el sample de :drum_heavy_kick exactamente cuando el otro hilo envía el mensaje :tick, aunque ambos hilos no comenzaron su ejecución al mismo tiempo:

in_thread do
  loop do
    cue :tick
    sleep 1
  end
end
sleep(0.3)
in_thread do
  loop do
    sync :tick
    sample :drum_heavy_kick
  end
end

Esa llamada sleep típicamente haría que el segundo hilo vaya fuera de fase con el primero. Sin embargo, por estar usando cue y sync, sincronizamos ambos hilos automáticamente.

Nombres de Cue

Eres libre de utilizar cualquier nombre que quieras a los mensajes de cue - no sólo :tick. Sólo debes asegurarte que los otros hilos estén sync sincronizándose en el nombre correctoe - de otro modo se quedarán esperando por siempre (o hasta presionar el botón de Parar)

Juguemos con unos cuantos nombres para cue:

in_thread do
  loop do 
    cue [:foo, :bar, :baz].choose
    sleep 0.5
  end
end
in_thread do
  loop do 
    sync :foo 
    sample :elec_beep
  end
end
in_thread do
  loop do
    sync :bar
    sample :elec_flip
  end
end
in_thread do
  loop do
    sync :baz
    sample :elec_blup
  end
end

Aquí tenemos un cue principal bucleado, el cual envía aleatoriamente uno de los nombres de pulso :foo, :bar o :baz. Después tenemos también tres bucles de hilos sincronizándose entre ellos independientemente y tocando un sampleo diferente. El efecto es que escuchamos un sonido cada 0.5 pulsos que cada uno de los hilos está aleatoriamente sincronizándose sync con el hilo de cue y toca su sampleo.

Por supuesto que esto también funciona si ordenas los hilos en reversa, ya que los hilos sync siempre esperarán al siguiente cue.


6 - Estudio FX

Uno de los aspectos más satisfactorios y divertidos de Sonic Pi es su habilidad de añadir efectos de estudio a tus sonidos. Por ejemplo, si quieres añadir reverberación, eco o distorsión.

Sonic Pi provee una manera simple y poderosa de añadir efectos FX. Inclusive te permite encadenarlos (así pasas tus sonidos por la distorsión, después el eco y la reverberación). También controlar cada unidad individual de FX con operandos (similar a darle parámetros a los sintetizadores y sampleos). Inclusive puedes modificar los operandos del FX mientras se ejecutan. Por ejemplo, puedes incrementar la reverberación del bajo a través de la pista…

Pedales de Guitarra

Si todo suena un poco complicado, no te preocupes. Una vez juegues con con esto, se aclarará. Antes de eso, una simple analogía es la de los pedales de efectos de una e-guitarra. Hay muchos pedales que puedes comprar. Algunos añaden reverberación, otros distorsión etc. Una guitarrista conecta su guitarra en un pedal, después a otro y así (cadena) La salida del pedal de reverberación termina siendo conectada al amplificador:

Guitarra -> Distorsión -> Reverberación -> Amplificador

Esto se llama efectos FX en cadena. Sonic Pi soporta eso. Adicionalmente cada pedal a menudo tiene diales y deslizadores para controlar cuánta distorsión, reverberación, eco etc. aplicar. Sonic Pi soporta También esta clase de control. Finalmente, imagina un guitarrista tocar mientras otra persona controla los efectos DX. Sonic Pic también permite esto, pero en vez de otra persona, te permite a tí controlarlo todo.

¡¡ Exploremos los efectos (FX) !!


6.1 - Añadiendo efectos FX

En esta sección veremos los efectos: reverberación y eco. Veremos cómo usarlos, controlar sus operandos y encadenarlos. Llamaremos “FX” a los efectos.

El sistema de efectos de Sonic Pi, utiliza bloques. Así que si no has leído la sección 5.1, deberías.

Reverberación

Si queremos usar reverberación, escribimos with_fx :reverb como el código especial para nuestro bloque, así:

with_fx :reverb do
  play 50
  sleep 0.5
  sample :elec_plip
  sleep 0.5
  play 62
end

Cuando tocas este código tendrá reverberación. ¿suena bien, no? todo suena mejor con reverberación.

Ahora veamos qué sucede si dejamos código fuera del bloque do/end:

with_fx :reverb do
  play 50
  sleep 0.5
  sample :elec_plip
  sleep 0.5
  play 62
end
sleep 1
play 55

Nota que el lay play 55 no se ejecutó con reberveración. Esto es porque está fuera del bloque do/end, así que no es capturado por el FX reverberación.

Similarmente, si haces sonidos antes del bloque do/end, tampoco los capturará:

play 55
sleep 1
with_fx :reverb do
  play 50
  sleep 0.5
  sample :elec_plip
  sleep 0.5
  play 62
end
sleep 1
play 55

Eco

Hay muchos FX (efectos) para escoger. ¿probamos con eco?

with_fx :echo do
  play 50
  sleep 0.5
  sample :elec_plip
  sleep 0.5
  play 62
end

Uno de los aspectos más sobresalientes de Sonic Pi es que los bloques de efectos operan con parámetros similares a los utilizados con play y sample. Por ejemplo, un parámetro interesante es phase: que representa la duración de un eco dado en pulsos. Hagamos el eco más lento:

with_fx :echo, phase: 0.5 do
  play 50
  sleep 0.5
  sample :elec_plip
  sleep 0.5
  play 62
end

Ahora hagamos el eco más rápido:

with_fx :echo, phase: 0.125 do
  play 50
  sleep 0.5
  sample :elec_plip
  sleep 0.5
  play 62
end

Hagamos que al eco le tome 8 pulsos en desvanecerse, gracias a decay:

with_fx :echo, phase: 0.5, decay: 8 do
  play 50
  sleep 0.5
  sample :elec_plip
  sleep 0.5
  play 62
end

Anidando FX

Uno de los más poderosos aspectos de los bloques de FX es que puedes anidarlos, con lo que logramos encadenarlos con facilidad. Por ejemplo, si quisieras tocar código con eco y después reverberación, fácilmente pones un Fx dentro de otro:

with_fx :reverb do
  with_fx :echo, phase: 0.5, decay: 8 do
    play 50
    sleep 0.5
    sample :elec_blup
    sleep 0.5
    play 62
  end
end

Piensa en el audio fluir desde adentro. El sonido de todo el códido dentro del bloque interno do/end como play 50 es primero enviado al FX de eco y a su vez, éste es enviado al FX reverberación.

Podemos hacer uso de anidados muy profundos para resultados extremos. Sin embargo, ten presente que los Fx consumen muchos recursos y que al anidarlos estás de hecho corriendo muchos FX simultáneamente. Así que sé consciente de su uso, especialmente en plataformas de bajo rendimiento como la Raspberry Pi.

Descubriendo FX

Sonic Pi tiene muchos efectos con los cuales jugar. Para verlos, cliquea en FX a la izquierda de este sistema de Ayuda y verás el listado. Aquí te deja algunos de mis favoritos:

wobble, reverb, echo, distortion, slicer

¡Ahora haz locuras con los FX, añadiéndolos en todas partes para crear nuevos sonidos!


6.2 - FX en la práctica

Aunque a simple vista sean simples, los FX son - internamente - unas bestias complejas. Su simplicidad a veces promueve a que la gente los sobre use en su música. Esto no es un problema si tienes una máquina poderosa, pero si - como yo - usas una Raspberry Pi para tus jams, debes ser cuidadoso acerca de cuanto trabajo le asignas para asegurarte que todo fluya sin pausas.

Considera este código:

loop do
  with_fx :reverb do
    play 60, release: 0.1
    sleep 0.125
  end
end

En este código estamos tocando la nota 60 con un tiempo de release muy, corto, por lo que es una nota muy corta. También queríamos reverb, así que lo envolvimos en un bloque de reverberación. Todo bien, excepto…

Veamos lo que hace el código. Primero bucleamos para que se repita por siempre todo lo que está dentro de él. Después tenemos un bloque with_fx Esto significa que crearemos un FX reverberación cada vez que buclee. Esto es como tener un pedal de reverberación por cada vez que toques una cuerda de la guitarra. Es bueno poder hacerlo, pero no siempre lo querrás. Por ejemplo, este código tendrá dificultades en una Raspberry Pi. Todo el trabajo de crear la reverberación y después esperar hasta que ncesite ser parado y removido, es hecho por with_fx pero esto consume mucho del CPU.

¿cómo lo haríamos más similar a cuando un guitarrista tiene sólo un pedal de reverberación a través del cual pasan todos los sonidos? Simple:

with_fx :reverb do
  loop do
    play 60, release: 0.1
    sleep 0.125
  end
end

Poniendo nuestro bucle dentro del bloque with_fx. Así sólo creamos un paso a reverb para todas las notas del bucle. Este código es mucho más eficiente y funcionará bien en una Raspberry Pi.

Al utilizar with_fx sobre una iteración en un bucle:

loop do
  with_fx :reverb do
    16.times do
      play 60, release: 0.1
      sleep 0.125
    end
  end
end

This way we’ve lifted the with_fx out of the inner part of the loop and we’re now creating a new reverb every 16 notes.

This is such a common pattern that with_fx supports an opt to do exactly this but without having to write the 16.times block:

loop do
  with_fx :reverb, reps: 16 do
    play 60, release: 0.1
    sleep 0.125
  end
end

Both the reps: 16 and 16.times do examples will behave identically. The reps: 16 essentially repeats the code in the do/end block 16 times so you can use them both interchangeably and choose the one that feels best for you.

Recuerda que no hay errores, sólo posibilidades. Sin embargo, según qué manera, se producen diferentes sonidos y características de ejecución. Así que experimenta y utiliza lo que te suene mejor y funcione en la plataforma que tengas.


7 - Controlando los sonidos en ejecución

Hasta ahora hemos visto cómo disparar sintetizadores y sampleos, cambiar sus operandores tales como amplitude, paneo, seteos de sobres y más. Cada sonido disparado es, esencialmente, su propio sonido con su lista de opciones por la duración del sonido.

¿Te gustaría cambiar los operadores de los sonidos cuando aún están sonando, así como cuando vibras la cuerda de una guitarra?

¡Tienes suerte, pues ésta sección te mostrará cómo hacerlo!


7.1 - Controlando Sintetizadores en ejecución

Hasta el momento nos hemos concentrado en disparar nuevos sonidos y FXs. Sin embargo, Sonic Pi te da la posibilidad de manipular y controlar sonidos en ejecución. Esto lo hacemos al utilizar una variable para capturar una referencia de un sintetizador:

s = play 60, release: 5

Aquí utilizamos una variable de ejecución local, s que representa el sintetizador tocando la nota 60. Al ser local no puede ser accesada desde otras ejecuciones, como sucede con las funciones.

Con s, utilizaremos la función control:

s = play 60, release: 5
sleep 0.5
control s, note: 65
sleep 0.5
control s, note: 67
sleep 3
control s, note: 72

Es de notar que no se disparan 4 diferentes sintetizadores, sino que usando uno al que le cambiamos los tonos 3 veces durante su ejecución.

Podemos pasar operandos para control como amp, cutoff: o pan:.

Opciones no-controlables

Algunos de los operandos no pueden ser controlados una vez comenzado el sintetizador. Este es el caso de los parámetros de sobres ADSR. Puedes encontrar cuáles operandos sí pueden ser controlados en el sistema de ayuda. Si la documentación dice no puede ser cambiado una vez seteado, es que no puedes controlar los operandos cuando el sintetizador ha comenzado.


7.2 - Controlando efectos (FX)

También es posible controlar los efectos, aunque de una manera diferente:

with_fx :reverb do |r|
  play 50
  sleep 0.5
  control r, mix: 0.7
  play 55
  sleep 1
  control r, mix: 0.9
  sleep 1
  play 62
end

En vez de usar una variable, usamos parámetros de poste “|” de los bloques do/end. Dentro de los postes |, debemos especificar un nombre específico para nuestro efecto en ejecución, el cual después referenciaremos desde el bloque do/end que lo contiene. Esta conducta es idéntica a usar funciones parametricazadas.

¡Ahora ve a controlar sintetizadores y efectos! Now go and control some synths and FX!


7.3 - Opciones con Deslizadores

Mientras explorábamos las opciones con sintetizadores y efectos, habrás notado que hay un número de opciones que terminan en _slide. Quizás intentaste utilizarlos y no hubo efecto. Esto es porque ellos son parámetros especiales que sólo funcionan cuando controlas los sintetizadores como dijimos en la sección anterior.

Considera el siguiente ejemplo:

s = play 60, release: 5
sleep 0.5
control s, note: 65
sleep 0.5
control s, note: 67
sleep 3
control s, note: 72

Aquí puedes escuchar el sintetizador cambiando tono inmediatamente en cada llamada de control. Sin embargo, quizás querramos que el tono se deslice entre cambios. Ya que estamos controlando el parámetro note, para añadir deslizamiento (slide), debemos setear el note_slide del sintetizador:

s = play 60, release: 5, note_slide: 1
sleep 0.5
control s, note: 65
sleep 0.5
control s, note: 67
sleep 3
control s, note: 72

Ahora escuchamos las notas “deslizadas” entre cada llamada de control. ¿suena bien, no? Puedes acelerar/desacelerar el arraster usando tiempos más cortos en note_slide: 0.2.

Cada parámetro que puede ser controlado, tiene su correspondiente _slide con el que jugar.

Deslizar es pegajoso

Una vez que determines un parámetro de _slide en un sintetizador, será recordado y usado cada vez que deslices el correspondiente parámetro. Para detener el deslizamiento, debes setear el valor de _slide a 0 antes de la siguiente llamada a control.

Deslizando opciones de Efectos (FX)

También es posible deslizar opciones de efectos (FX):

with_fx :wobble, phase: 1, phase_slide: 5 do |e|
  use_synth :dsaw
  play 50, release: 5
  control e, phase: 0.025
end

Ve y diviértete deslizando todo para unas transiciones suaves y control fluído… Now have fun sliding things around for smooth transitions and flowing control…


8 - Estructuras de Datos

Una herramiento útil para los programadores es la Estrutura de Datos.

Algunas veces puedes desear usar más de una cosa. Por ejemplo, el tocar una serie de notas que se toquen una después de la otra. Los lenguajes de programación tienen estructuras de datos para permitirte eso.

Hay muchas estructuras de datos exóticas y excitantes a disposición de los programadores - y se siguen inventando nuevas. Sin embargo, por ahora sólo necesitamos considerar una estructura de datos muy sencilla - la lista.

Mirémosla en mayor detalle. Cubriremos su forma básica y también el modo de utilizarlas para representar escalas y acordes.


8.1 - Listas

En esta sección miraremos una Estructura de Datos muy útil: la Lista. Ya la vimos -brevemente- en la sección de aleatoriedad, cuando de una lista de notas elegía al azar las notas a tocar:

play choose([50, 55, 62])

Ahora también exploraremos listas que que representan acordes y escalas. Primero repasemos cómo tocar un acorde. Recuerda que si no usamos sleep, todos los sonidos suceden al mismo tiempo:

play 52
play 55
play 59

Veamos otras maneras de representar este código.

Ejecutando una Lista

Una opción es colocar todas las notas en una lista: [52, 55, 59]. Nuestro amigable play es lo suficientemente listo para entender cómo tocar una lista de notas. Probemos:

play [52, 55, 59]

Ohh, eso ya está mejor para leer. El tocar un listado de notas no significa que no puedas usar los otros parámetros, normalmente:

play [52, 55, 59], amp: 0.3

Por supuesto, puedes usar los nombres tradicionales de notas en vez de números MIDI

play [:E3, :G3, :B3]

Ahora, esos suertudos de ustedes con estudios en teoría musical, podrán reconocer que el acorde es Mi menor tocado en la 3ra octava.

Accediendo a una Lista

Otro aspecto útil de una lista es la habilidad de obtener información de la misma. Puede sonar extraño, pero es igual a alguien pidiéndote que pases a la página 23 de un libro. Con una lista, dirías, ¿qué elemento hay en el índice 23? Lo único diferente es que en índices de programación se comienza con 0 y no con 1.

Con índices de listas no contamos 1, 2, 3… sino que 0, 1, 2…

Veamos eso en mayor detalle en esta lista:

[52, 55, 59]

No hay algo espcialmente de susto en ello. Ahora, ¿qué es el segundo elemento en esa lista? Si, claro, es 55. Fácil. Veamos si la computadora puede respondernoslo, también:

puts [52, 55, 59][1]

Si se mira algo raro, confía en mí, no lo es. Hay tres partes en la línea de arriba: la palabra puts, nuestra lista 52, 55, 59 y nuestro índice [1]. Primero pedimos puts para que Sonic Pi imprima la respuesta en la bitácora. Después, le damos nuestra lista y finalmente nuestro índice le pide el segundo elemento. Necesitamos rodear nuestro índice con paréntesis cuadrados y ya que el conteo comienza en 0, el índice para el segundo elemento es 1. Mira:

# indexes:  0   1   2
           [52, 55, 59]

Prueba con puts [52, 55, 59][1] y verás 55 en la bitácora. Cambia el índice 1 a otros índices, intenta con listas más largas en tu próximo código. Por ejemplo, estructuras musicales que podrían representarse como series de números


8.2 - Acordes

Sonic Pi soporta nombres de acordes que regresarán listas. Pruébalo:

play chord(:E3, :minor)

¡Ahora estamos en algo!. Eso se mira mucho mejor que listas crudas y es más fácil de leer para otros. ¿qué otros acordes soporta Sonic Pi? Bueno, muchos. Prueba con estos:

chord(:E3, :m7) chord(:E3, :minor) chord(:E3, :dim7) chord(:E3, :dom7)

Arpegios

Podemos convertir acordes en arpegios con facilidad, gracias a la función play_pattern:

play_pattern chord(:E3, :m7)

Ok, eso no fue tan divertido, se ejecutó muy despacio. play_pattern va a tocar cada nota en la lista separada por una llamada a sleep 1 entre cada llamada a play. Podemos usar otra función play_pattern_timed para especificar nuestros propios tiempos y acelerar las cosas:

play_pattern_timed chord(:E3, :m7), 0.25

Inclusive podemos pasar una lista de tiempos, los cuales serán tratados como un círculo de tiempos:

play_pattern_timed chord(:E3, :m13), [0.25, 0.5]

Eso equivale a:

play 52
sleep 0.25
play 55
sleep 0.5
play 59
sleep 0.25
play 62
sleep 0.5
play 66
sleep 0.25
play 69
sleep 0.5
play 73

¿qué preferirías escribir?


8.3 - Escalas

Sonic Pi incluye un gran rango de escalas. ¿qué tal tocar una escala de Do3 mayor?

play_pattern_timed scale(:c3, :major), 0.125, release: 0.1

Podemos pedir para más octavas:

play_pattern_timed scale(:c3, :major, num_octaves: 3), 0.125, release: 0.1

¿qué tal todas las notas de la escala pentatónica?

play_pattern_timed scale(:c3, :major_pentatonic, num_octaves: 3), 0.125, release: 0.1

Notas al Azar

Los Acordes y Escalas son una buena manera de restringir una elección aleatoria para hacer algo significativo. Toca esl siguiente ejemplo que agarra notas al azar del acorde de E3 menor:

use_synth :tb303
loop do
  play choose(chord(:E3, :minor)), release: 0.3, cutoff: rrand(60, 120)
  sleep 0.25
end

Intenta cambiar los nombres de acordes y los rangos de corte.

Descubriendo Acordes y Escalas

Para saber cuáles acordes y escalas vienen con Sonic Pi, simplemente cliquea el botón Lang a la izquierda de este tutorial y elige acorde o escala de la lista API. En la información en el panel principal, baja hasta ver una larga lista de acordes y escalas (dependiendo de cuál estés viendo).

¡Diviértete y siempre recuerda que no hay errores, sólo oportunidades!


8.4 - Anillos

Una variación interesante a las listas, son los anillos. Si sabes algo de programación, puedes haberte topado con anillos de buffers o arrays. Aquí sólo iremos con los anillos - es corto y simple.

En la sección anterior de listas, vimos cómo sacar elementos de ellas a través del mecanismo de indexado:

puts [52, 55, 59][1]

Ahora, ¿qué sucede si quieres el índice 100? Bueno, claramente no existe un elemente en el índice 100, ya que sólo hay 3 elementos dentro. Así que Sonic Pi te responderá un nil.

Sin embargo, considera que tienes un contador tal como el pulso actual que se va incrementando. Hagamos nuestro contador y lista:

counter = 0
notes = [52, 55, 59]

We can now use our counter to access a note in our list:

puts notes[counter]

Grandioso, obtuvimos 52. Ahora, incrementemos nuestro contador y obtengamos otra nota:

counter = (inc counter)
puts notes[counter]

Super, obtuvimos 55y después 59. Sin embargo, si lo hacemos de nuevo, se nos acaban los números de la lista y obtenemos nil. Si quisiésemos buclear y volver a comenzar la lista, usaríamos los anillos.

Creando Anillos

Podemos crear anillos de dos maneras: con la función ringy los elementos del anillo como parámetros:

(ring 52, 55, 59)

O podemos tomar una lista normal y convertirla a anillo con el mensaje .ring:

[52, 55, 59].ring

Indexando Anillos

Un anillo puede ser utilizado de la misma manera que una lista, exceptuando que puedes usar índices negativos y mayores al tamaño del anillo mismo, los cuales envolverán y apuntarán siempre a alguno de los elementos del anillo:

(ring 52, 55, 59)[0] #=> 52
(ring 52, 55, 59)[1] #=> 55
(ring 52, 55, 59)[2] #=> 59
(ring 52, 55, 59)[3] #=> 52
(ring 52, 55, 59)[-1] #=> 59

USando Anillos

Usemos una variable para representar el número del pulso actual. Podemos usar esto como un índice a nuestro anillo para agarrar notas a ser tocadas o tiempos de release o cualquier cosa útil que tengamos en nuestro anillo, independientemente del pulso en el que estemos.

Las escalas y acordes son anillos

Algo útil de saber es que las listas regresadas por scale y acorde también son anillos que te permiten las accedas con índices arbitrarios.

Constructores de Anillos

Además de ring hay un número de funciones que construyen anillos por nosotros.

range pide especificar un punto de inicio, final y tamaño del paso. bools permite usar 1s y 0s para representar booleanos. knit permite conectar una secuencia de valores repetidos. spread crea un anillo de booleanos con distribución euclideana.

Mira la documentación de cada uno para más información.


8.5 - Ring Chains

In addition to the constructors such as range and spread another way of creating new rings is to manipulate existing rings.

Chain Commands

To explore this, take a simple ring:

(ring 10, 20, 30, 40, 50)

What if we wanted it backwards? Well we’d use the chain command .reverse to take the ring and turn it around:

(ring 10, 20, 30, 40, 50).reverse  #=> (ring 50, 40, 30, 20, 10)

Now, what if we wanted the first three values from the ring?

(ring 10, 20, 30, 40, 50).take(3)  #=> (ring 10, 20, 30)

Finally, what if we wanted to shuffle the ring?

(ring 10, 20, 30, 40, 50).shuffle  #=> (ring 40, 30, 10, 50, 20)

Multiple Chains

This is already a powerful way of creating new rings. However, the real power comes when you chain a few of these commands together.

How about shuffling the ring, dropping 1 element and then taking the next 3?

Let’s take this in stages:

(ring 10, 20, 30, 40, 50) - our initial ring (ring 10, 20, 30, 40, 50).shuffle - shuffles - (ring 40, 30, 10, 50, 20) (ring 10, 20, 30, 40, 50).shuffle.drop(1) - drop 1 - (ring 30, 10, 50, 20) (ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3) - take 3 - (ring 30, 10, 50)

Can you see how we can just create a long chain of these methods by just sticking them together. We can combine these in any order we want creating an extremely rich and powerful way of generating new rings from existing ones.

Immutability

These rings have a powerful and important property. They are immutable which means that they can not change. This means that the chaining methods described in this section do not change rings rather they create new rings. This means you’re free to share rings across threads and start chaining them within a thread knowing you won’t be affecting any other thread using the same ring.

Available Chain Methods

Here’s a list of the available chain methods for you to play with:

.reverse - returns a reversed version of the ring .sort - creates a sorted version of the ring .shuffle - creates a shuffled version of the ring .pick(3) - returns a ring with the results of calling .choose 3 times .pick - similar to .pick(3) only the size defaults to the same as the original ring .take(5) - returns a new ring containing only the first 5 elements .drop(3) - returns a new ring with everything but the first 3 elements .butlast - returns a new ring with the last element missing .drop_last(3) - returns a new ring with the last 3 elements missing .take_last(6)- returns a new ring with only the last 6 elements .stretch(2) - repeats each element in the ring twice .repeat(3) - repeats the entire ring 3 times .mirror - adds the ring to a reversed version of itself .reflect - same as mirror but doesn’t duplicate middle value .scale(2) - returns a new ring with all elements multiplied by 2 (assumes ring contains numbers only)

Of course, those chain methods that take numbers can take other numbers too! So feel free to call .drop(5) instead of .drop(3) if you want to drop the first 5 elements.


9 - Live Coding (Programación en vivo)

Uno de los aspectos más excitantes de Sonic Pi es que permite escribir y modificar código ‘al vuelo’ para hacer música, así como harías con una guitarra. Una ventaja de esto es que te da más retroalimentación mientras compones (corre un bucle sencillo (juega con él hasta que sea perfecto). Sin embargo, la mayor ventaja es poder ejecutar Sonic Pi en vivo en escena.

En esta sección cubriremos lo fundamental de tornar tu código estático de composiciones en ejecuciones dinámicas.

¡Prepárate!


9.1 - Live Coding (Programación en vivo)

Ya sabemos lo suficiente para comenzar a divertirnos en serio. En esta sección te mostraré cómo comenzar a crear composiciones musicales en vivo y convertirlas en ejecuciones. Para ello necesitamos 3 ingredientes:

Habilidad para escribir código que haga sonidos - CHECK! Habilidad de escribir funciones - CHECK! Hbilidad de usar hilos (nominales) - CHECK!

¡Muy bien, comencemos! Hagamos nuestros primeros sonidos de códigos en vivo Primero necesitamos una función conteniendo el código que necesitamos tocar Comencemos con algo simple. También necesitamos llamadas en bucle a esa función en un hilo:

define :my_loop do
  play 50
  sleep 1
end
in_thread(name: :looper) do
  loop do
    my_loop
  end
end

Si te parece complicado, vuelve a leer las secciones de funciones e hilos. No es tan complicado una vez entiendes bien esos conceptos.

Lo que tenemos es una función que toca la nota 50 y duerme por un pulso. Después definimos un hilo llamado :looper que bucle llamando my_loop repetidamente.

Si corres este código, escucharás la nota 50 una y otra vez…

¡Cambiandolo al vuelo!

Aquí es donde comienza la diversión. Mientras el código aún corre cambia 50 a otro número, digamos 55, y presiona Run otra vez. ¡Woah! ¡cambió en vivo!

No añadió una nueva capa porque usamos hilos nombrados, los que sólo permiten un hilo por cada nombre. El sonido cambió porque redefinimos la función. LE dimos a :my_loopuna nueva definición. CUando el hilo :looper bucleó, simplemente llamó la nueva definición.

Sigue cambiándolo, cambia la nora, el tiempo de pausa. ¿qué tal añadir un use_synth? Por ejemplo, esto:

define :my_loop do
  use_synth :tb303
  play 50, release: 0.3
  sleep 0.25
end

Ahora suena interesante, pero podemos mejorarlo, aún. En vez de tocar la misma nota, hagámoslo con un acorde:

define :my_loop do
  use_synth :tb303
  play chord(:e3, :minor), release: 0.3
  sleep 0.5
end

¿tocamos notas del acorde al azar?:

define :my_loop do
  use_synth :tb303
  play choose(chord(:e3, :minor)), release: 0.3
  sleep 0.25
end

o usando un valor de corte al azar:

define :my_loop do
  use_synth :tb303
  play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
  sleep 0.25
end

Al final, añadamos un poco de batería:

define :my_loop do
  use_synth :tb303
  sample :drum_bass_hard, rate: rrand(0.5, 2)
  play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
  sleep 0.25
end

¡Ahora está volviéndose excitante!

Sin embargo, antes de saltar y comenzar a Live Coding con funciones e hilos, lee la próxima sección sobre live_loop que cambiará la manera en la que codifiques con Sonic Pi para siempre…


9.2 - Bucles en Vivo

Bien, ésta sección del tutorial es la joya de la corona. Si leyeses sólo una sección, debería ser ésta. Si leíste la sección previa sobre los Fundamentos de Live Coding, live_loop es una manera simple de hacer exactamente eso, pero sin tener que escribir tanto.

Si no leíste la sección anterior, live_loop es como mejor se puede tocar con Sonic Pi.

Toquemos algo. Escribe el siguiente código en un buffer nuevo:

live_loop :foo do
  play 60
  sleep 1
end

Presiona el botón de Run. Escucharás un beep básico en cada pulso. Nada muy divertido en ello. Sin embargo, todavía no presiones Stop. Cambia el 60 a 65 y presiona otra vez Run.

¡Woah Se cambió automáticamente sin perder un tan sólo pulso!¡Esto es Live Coding!

Hagámoslo más a bajo, sólo cambiemos el código un poco:

live_loop :foo do
  use_synth :prophet
  play :e1, release: 8
  sleep 8
end

Ahora aprieta Run

Movamos el punto de corte:

live_loop :foo do
  use_synth :prophet
  play :e1, release: 8, cutoff: rrand(70, 130)
  sleep 8
end

Presiona Run otra vez.

Añadamos baterías:

live_loop :foo do
  sample :loop_garzul
  use_synth :prophet
  play :e1, release: 8, cutoff: rrand(70, 130)
  sleep 8
end

Cambiemos la nota de e1 a c1:

live_loop :foo do
  sample :loop_garzul
  use_synth :prophet
  play :c1, release: 8, cutoff: rrand(70, 130)
  sleep 8
end

Ahora deja de leerme y cambia lo que quieras por tu cuenta. ¡Diviértete!


9.3 - Múltiples Bucles en Vivo

Considera el siguiente bucle en vivo:

live_loop :foo do
  play 50
  sleep 1
end

Quizás te preguntas el por qué es importante el nombre foo, la respuesta es que es importante porque significa que este bucle es diferente de TODOS los otros.

Nunca pueden haber dos bucles en vivo con el mismo nombre ejecutándose simultáneamente

Esto significa que si queremos múltiples bucles concurrentes, debemos darles diferentes nombres:

live_loop :foo do
  use_synth :prophet
  play :c1, release: 8, cutoff: rrand(70, 130)
  sleep 8
end
live_loop :bar do
  sample :bd_haus
  sleep 0.5
end

Ahora puedes actualizar y cambiar cada bucle independientemente y funcionará siempre.

Sincronizando bucles en vivo

Una cosa que ya habrás notado es que los bucles en vivo trabajan automáticamente automáticamente con el mecanismo de marca de hilos que exploramos anteriormente. Cada bucle en vivo genera un evento cue Gracias a ello podemos sincronizarlos para asegurar bucles sin pausa.

Considera este código mal sincronizado:

live_loop :foo do
  play :e4, release: 0.5
  sleep 0.4
end
live_loop :bar do
  sample :bd_haus
  sleep 1
end

Veamos si podemos arreglar el timing y sincronizar sin parar. Primero, arreglemos el bucle :foo para hacer el factor de sleep 1 a algo como 0.5:

live_loop :foo do
  play :e4, release: 0.5
  sleep 0.5
end
live_loop :bar do
  sample :bd_haus
  sleep 1
end

Todavía no terminamos, pues notarás que los pulsos no se alinean correctamente. Esto se debe a que los bucles están desfasados out of phase. Arreglemos Esto sincronizándolos entre sí:

live_loop :foo do
  play :e4, release: 0.5
  sleep 0.5
end
live_loop :bar do
  sync :foo
  sample :bd_haus
  sleep 1
end

¡Wow, todo está sincronizado ahora y sin parar!

¡Ahora ve y codifica en vivo con bucles en vivo!


9.4 - Ticking

Algo con lo que seguramente te encontrarás haciendo muchas veces al hacer live coding es buclear a través de anillos (rings), para poner notas a melodías, pausas a ritmos, progresiones de acordes, variaciones timbrales, etc. etc.

Ticking Anillos

Sonic Pi provee una herramienta muy útil para trabajar con anillos dentro de bucles en vivo. Se llama el sistema de tick, que provee la habilidad de tickear a través de anillos. Veamos un ejemplo:

counter = 0
live_loop :arp do
  play (scale :e3, :minor_pentatonic)[counter], release: 0.1
  counter += 1
  sleep 0.125
end

This is equivalent to:

live_loop :arp do
  play (scale :e3, :minor_pentatonic).tick, release: 0.1
  sleep 0.125
end

Aquí, simplemente tomamos la escala pentatónica menor de E3 y tickeamos a cada elemento al añadirles .tick al final de la declaración de escala. Este tick es local al bucle en vivo, por lo que cada bucle debe tener su propio e independiente tick:

live_loop :arp do
  play (scale :e3, :minor_pentatonic).tick, release: 0.1
  sleep 0.125
end
live_loop :arp2 do
  use_synth :dsaw
  play (scale :e2, :minor_pentatonic, num_octaves: 3).tick, release: 0.25
  sleep 0.25
end

Tick

También puedes llamar tick como una función estándar y usar el valor como un índice:

live_loop :arp do
  idx = tick
  play (scale :e3, :minor_pentatonic)[idx], release: 0.1
  sleep 0.125
end

Sin embargo, es mejor llamar .tick al final. La función tick está para cuando quieras hacer cosas sofisticadas con el valor de tick y para cuando quieras hacer más que indexar dentro de los anillos.

Mirar

Lo mágico acerca de tick es que no sólo te da un nuevo índice (o el valor del anillo en ese índice), sino que también te asegura que al próximo llamado de tick, será el próximo valor. Mira los documentos para ver ejemplos de trabajar con tick . Sin embargo, por ahora es importante notar que a veces querrás mirar al valor tick actual sin que aumente, lo cual se logra con la función look. La cual puede ser utilizada como una función estándar o añadiendo .look al final de un anillo. to the end of a ring.

Nombrando los ticks

Finalmente, algunas veces necesitarás más de un tick por bucle en vivo. Esto lo lograrás nombrando a tus ticks:

live_loop :arp do
  play (scale :e3, :minor_pentatonic).tick(:foo), release: 0.1
  sleep (ring 0.125, 0.25).tick(:bar)
end

Aquí estamos utilizando dos ticks, uno para la nota a ser tocada y otro para el tiempo de pausa. Como ambos están en el mismo bucle, debemos separarlos nombrándolos diferentemente. Es lo mismo que hiciéramos con live_loop - pasamos un símbolo prefijado con un :. En el anterior ejemplo, llamamos a un tick :foo y al otro :bar. Si queremos mirarlos sólo debemos pasar el nombre del tick a look.

No lo compliques tanto..

La mayor parte del poder del sistema de tick no es útil al comenzar. No intentes aprender todo en esta sección, enfócate en el tick de un sólo anillo. Eso es lo que más te beneficiará y simplificará tickear dentro de anillos en bucles en vivo.

Mira la documentación de tick, donde tienes muchos ejemplos..


10 - Time State

Often it is useful to have information that is shared across multiple threads or live loops. For example, you might want to share a notion of the current key, BPM or even more abstract concepts such as the current ‘complexity’ (which you’d potentially interpret in different ways across different threads). We also don’t want to lose any of our existing determinism guarantees when doing this. In other words, we’d still like to be able to share code with others and know exactly what they’ll hear when they run it. At the end of Section 5.6 of this tutorial we briefly discussed why we should not use variables to share information across threads due to a loss of determinism (in turn due to race conditions).

Sonic Pi’s solution to the problem of easily working with global variables in a deterministic way is through a novel system it calls Time State. This might sound complex and difficult (in fact, in the UK, programming with multiple threads and shared memory is typically a university level subject). However, as you’ll see, just like playing your first note, Sonic Pi makes it incredibly simple to share state across threads whilst still keeping your programs thread-safe and deterministic..

Meet get and set


10.1 - Set and Get

Sonic Pi has a global memory store called Time State. The two main things you do with it are to set information and get information. Let’s dive deeper…

Set

To store information into the Time State we need two things:

the information we want to store, a unique name (key) for the information.

For example, we might want to store the number 3000 with the key :intensity. This is possible using the set function:

set :intensity, 3000

We can use any name for our key. If information has already been stored with that key, our new set will override it:

set :intensity, 1000
set :intensity, 3000

In the above example, as we stored both numbers under the same key, the last call to set ‘wins’, so the number associated with :intensity will be 3000 as the first call to set is effectively overridden.

Get

To fetch information from the Time State we just need the key we used to set it, which in our case is :intensity. We then just need to call get[:intensity] which we can see by printing out the result to the log:

print get[:intensity] #=> prints 3000

Notice that calls to get can return information that was set in a previous run. Once a piece of information has been set it is available until either the information is overridden (just like we clobbered the :intensity value of 1000 to 3000 above) or Sonic Pi is closed.

Multiple Threads

The main benefit of the Time State system is that it can be safely used across threads or live loops. For example, you could have one live loop setting information and another one getting it:

live_loop :setter do
  set :foo, rrand(70, 130)
  sleep 1
end
live_loop :getter do
  puts get[:foo]
  sleep 0.5
end

The nice thing about using get and set across threads like this is that it will always produce the same result every time you hit run. Go on, try it. See if you get the following in your log:

{run: 0, time: 0.0}
 └─ 125.72265625
{run: 0, time: 0.5}
 └─ 125.72265625
{run: 0, time: 1.0}
 └─ 76.26220703125
{run: 0, time: 1.5}
 └─ 76.26220703125
{run: 0, time: 2.0}
 └─ 114.93408203125
{run: 0, time: 2.5}
 └─ 114.93408203125
{run: 0, time: 3.0}
 └─ 75.6048583984375
{run: 0, time: 3.5}
 └─ 75.6048583984375
 ~~~~
 Try running it a few times - see, it's the same every time. This is
 what we call deterministic behaviour and it's really very important
 when we want to share our music as code and know that the person
 playing the code is hearing exactly what we wanted them to hear (just
 like playing an MP3 or internet stream sounds the same for all
 listeners).
## A Simple Deterministic State System
Back in Section 5.6 we discussed why using variables across threads can
lead to random behaviour. This stops us from being able to reliably
reproduce code such as this:

## An Example of Non-Deterministic Behaviour ## (due to race conditions caused by multiple ## live loops manipulating the same variable ## at the same time). ## ## If you run this code you’ll notice ## that the list that’s printed is ## not always sorted! a = (ring 6, 5, 4, 3, 2, 1)

live_loop :shuffled do a = a.shuffle sleep 0.5 end

live_loop :sorted do a = a.sort sleep 0.5 puts “sorted: “, a end ~~~~

Let’s take a look at how this might look using get and set:

## An Example of Deterministic Behaviour
## (despite concurrent access of shared state)
## using Sonic Pi's new Time State system.
##
## When this code is executed, the list that's
## printed is always sorted!
set :a, (ring 6, 5, 4, 3, 2, 1)
live_loop :shuffled do
  set :a, get[:a].shuffle
  sleep 0.5
end
live_loop :sorted do
  set :a, get[:a].sort
  sleep 0.5
  puts "sorted: ", get[:a]
end

Notice how this code is pretty much identical to the version using a variable before it. However when you run the code, it behaves as you would expect with any typical Sonic Pi code - it does the same thing every time in this case thanks to the Time State system.

Therefore, when sharing information across live loops and threads, use get and set instead of variables for deterministic, reproducible behaviour.


10.2 - Sync

Section 5.7 introduced the functions cue and sync when dealing with the issue of synchronising threads. What it didn’t explain was that it is the Time State system which provides this functionality. It just so happens that set is actually a variation of cue and is built on top of the same core functionality which is to insert information into the Time State system. Additionally, sync is also designed in such a way that it works seamlessly with Time State - any information that we plan to store in Time State we can sync on. In other words - we sync on events yet to be inserted into Time State.

Waiting for Events

Let’s take a quick look at how to use sync to wait for new events to be added to Time State:

in_thread do
  sync :foo
  sample :ambi_lunar_land
end
sleep 2
set :foo, 1

In this example first we create a thread which waits for a :foo event to be added to the Time State. After this thread declaration we sleep for 2 beats and then set :foo to be 1. This then releases the sync which then moves to the next line which is to trigger the :ambi_lunar_land sample.

Note that sync always waits for future events and that it will block the current thread waiting for a new event. Also, it will inherit the logical time of the thread which triggered it via set or cue so it may also be used to sync time.

Passing values into the Future

In the example above we set :foo to 1 which we did nothing with. We can actually get this value from the thread calling sync:

in_thread do
  amp = sync :foo
  sample :ambi_lunar_land, amp: amp
end
sleep 2
set :foo, 0.5

Note that values that are passed through set and cue must be thread safe - i.e. immutable rings, numbers, symbols or frozen strings. Sonic Pi will throw an error if the value you are attempting to store in the Time State is not valid.


10.3 - Pattern Matching

When getting and setting information into the Time State, it’s possible to use more complex keys than basic symbols such as :foo and :bar. You can also use URL style strings called paths such as "/foo/bar/baz". Once we start working with paths, we can then start taking advantage of Sonic Pi’s sophisticated pattern matching system to get and sync with ‘similar’ rather than ‘identical’ paths. Let’s take a look.

Match any path segment

Let’s assume we want to wait for the next event that has three path segments:

sync "/*/*/*"

This will match any Time State event with exactly three path segments, regardless of their names. For example:

cue "/foo/bar/baz" cue "/foo/baz/quux" cue "/eggs/beans/toast" cue "/moog/synths/rule"

However, it will not match paths with fewer or more path segments. The following will not match:

cue "/foo/bar" cue "/foo/baz/quux/quaax" cue "/eggs"

Each * means any content. So we could match paths with just one segment with /* or paths with five segments with /*/*/*/*/*

Matching partial segments

If we know what the segment is going to start or finish with, we can use a * in addition to a partial segment name. For example: "/foo/b*/baz" will match any path that has three segments, the first of which is foo, the last baz and the middle segment can be anything that starts with b. So, it would match:

cue "/foo/bar/baz" cue "/foo/baz/baz" cue "/foo/beans/baz"

However, it wouldn’t match the following:

cue "/foo/flibble/baz" cue "/foo/abaz/baz" cue "/foo/beans/baz/eggs"

You can also place the * at the start of the segment to specify the last characters of a segment: "/foo/*zz/baz" which will match any 3 segment cue or set where the first segment is foo, the last is baz and the middle segment ends with zz such as "cue "/foo/whizz/baz".

Matching Nested Path Segments

Sometimes you don’t know how many path segments you want to match. In these cases you can use the powerful double star: ** such as "/foo/**/baz" which will match:

cue "/foo/bar/baz" cue "/foo/bar/beans/baz" cue "/foo/baz" cue "/foo/a/b/c/d/e/f/baz"

Matching Single Letters

You can use the ? character to match against a single char such as "/?oo/bar/baz" which will match:

cue "/foo/bar/baz" cue "/goo/bar/baz" cue "/too/bar/baz" cue "/woo/bar/baz"

Matching Multiple Words

If you know that a segment may be one of a select number of words, you can use the { and } matchers to specify a list of choices such as "/foo/{bar,beans,eggs}/quux" which will only match the following:

cue "/foo/bar/quux" cue "/foo/beans/quux" cue "/foo/eggs/quux"

Matching Multiple Letters

Finally, you can match against a selection of letters if you use the [ and ] matchers to specify a list of choices such as "/foo/[abc]ux/baz" which will match only:

cue "/foo/aux/baz" cue "/foo/bux/baz" cue "/foo/cux/baz"

You can also use the - character to specify ranges of letters. For example "/foo/[a-e]ux/baz" which will match only:

cue "/foo/aux/baz" cue "/foo/bux/baz" cue "/foo/cux/baz" cue "/foo/dux/baz" cue "/foo/eux/baz"

Combining Matchers

When calling sync or get you are free to combine matchers in any order you see fit to powerfully match any Time State event created by cue or set. Let’s look at a crazy example:

in_thread do
  sync "/?oo/[a-z]*/**/ba*/{quux,quaax}/"
  sample :loop_amen
end
sleep 1
cue "/foo/beans/a/b/c/d/e/bark/quux/"

OSC Pattern Matching

For those curious, these matching rules are based on the Open Sound Control pattern matching specification which is explained in detail here: http://opensoundcontrol.org/spec-1_0


11 - MIDI

Once you’ve mastered converting code to music, you might wonder - what’s next? Sometimes the constraints of working purely within Sonic Pi’s syntax and sound system can be exciting and put you into a new creative position. However, sometimes it is essential to break out of the code into the real world. We want two extra things:

To be able to convert actions in the real world into Sonic Pi events to code with To be able to use Sonic Pi’s strong timing model and semantics to control and manipulate objects in the real world

Luckily there’s a protocol that’s been around since the 80s that enables exactly this kind of interaction - MIDI. There’s an incredible number of external devices including keyboards, controllers, sequencers, and pro audio software that all support MIDI. We can use MIDI to receive data and also use it to send data.

Sonic Pi provides full support for the MIDI protocol enabling you to connect your live code to the real world. Let’s explore it further…


11.1 - MIDI In

In this section we will learn how to connect a MIDI controller to send events into Sonic Pi to control our synths and sounds. Go and grab a MIDI controller such as a keyboard or control surface and let’s get physical!

Connecting a MIDI Controller

In order to get information from an external MIDI device into Sonic Pi we first need to connect it to our computer. Typically this will be via a USB connection, although older equipment will have a 5-pin DIN connector for which you’ll need hardware support for your computer (for example, some sound cards have MIDI DIN connectors). Once you’ve connected your device, launch Sonic Pi and take a look at the IO section of the Preferences panel. You should see your device listed there. If not, try hitting the ‘Reset MIDI’ button and see if it appears. If you’re still not seeing anything, the next thing to try is to consult your operating system’s MIDI config to see if it sees your device. Failing all that, feel free to ask questions in the public chat room: http://gitter.im/samaaron/sonic-pi

Receiving MIDI Events

Once your device is connected, Sonic Pi will automatically receive events. You can see for yourself by manipulating your MIDI device and looking at the cue logger in the bottom right of the application window below the log (if this isn’t visible go to Preferences->Editor->Show & Hide and enable the ‘Show cue log’ tickbox). You’ll see a stream of events such as:

/midi/nanokey2_keyboard/0/1/note_off  [55, 64]
/midi/nanokey2_keyboard/0/1/note_on   [53, 102]
/midi/nanokey2_keyboard/0/1/note_off  [57, 64]
/midi/nanokey2_keyboard/0/1/note_off  [53, 64]
/midi/nanokey2_keyboard/0/1/note_on   [57, 87]
/midi/nanokey2_keyboard/0/1/note_on   [55, 81]
/midi/nanokey2_keyboard/0/1/note_on   [53, 96]
/midi/nanokey2_keyboard/0/1/note_off  [55, 64]

Once you can see a stream of messages like this, you’ve successfully connected your MIDI device. Congratulations, let’s see what we can do with it!

MIDI Time State

These events are broken into two sections. Firstly there’s the name of the event such as /midi/nanokey2_keyboard/0/1/note_on and secondly there’s the values of the event such as [18, 62]. Interestingly, these are the two things we need to store information in Time State. Sonic Pi automatically inserts incoming MIDI events into Time State. This means you can get the latest MIDI value and also sync waiting for the next MIDI value using everything we learned in section 10 of this tutorial.

Controlling Code

Now we’ve connected a MIDI device, seen its events in the cue log and discovered that our knowledge of Time State is all we need to work with the events, we can now start having fun. Let’s build a simple MIDI piano:

live_loop :midi_piano do
  note, velocity = sync "/midi/nanokey2_keyboard/0/1/note_on"
  synth :piano, note: note
end

There’s a few things going on in the code above including some issues. Firstly, we have a simple live_loop which will repeat forever running the code between the do/end block. This was introduced in Section 9.2. Secondly, we’re calling sync to wait for the next matching Time State event. We use a string representing the MIDI message we’re looking for (which is the same as was displayed in the cue logger). Notice that this long string is provided to you by Sonic Pi’s autocompletion system, so you don’t have to type it all out by hand. In the log we saw that there were two values for each MIDI note on event, so we assign the result to two separate variables note and velocity. Finally we trigger the :piano synth passing our note.

Now, you try it. Type in the code above, replace the sync key with a string matching your specific MIDI device and hit Run. Hey presto, you have a working piano! However, you’ll probably notice a couple of problems: firstly all the notes are the same volume regardless of how hard you hit the keyboard. This can be easily fixed by using the velocity MIDI value and converting it to an amplitude. Given that MIDI has a range of 0->127, to convert this number to a value between 0->1 we just need to divide it by 127:

live_loop :midi_piano do
  note, velocity = sync "/midi/nanokey2_keyboard/0/1/note_on"
  synth :piano, note: note, amp: velocity / 127.0
end

Update the code and hit Run again. Now the velocity of the keyboard is honoured. Next, let’s get rid of that pesky pause.

Removing Latency

Before we can remove the pause, we need to know why it’s there. In order to keep all the synths and FX well-timed across a variety of differently capable CPUs, Sonic Pi schedules the audio in advance by 0.5s by default. (Note that this added latency can be configured via the fns set_sched_ahead_time! and use_sched_ahead_time). This 0.5s latency is being added to our :piano synth triggers as it is added to all synths triggered by Sonic Pi. Typically we really want this added latency as it means all synths will be well timed. However, this only makes sense for synths triggered by code using play and sleep. In this case, we’re actually triggering the :piano synth with our external MIDI device and therefore don’t want Sonic Pi to control the timing for us. We can turn off this latency with the command use_real_time which disables the latency for the current thread. This means you can use real time mode for live loops that have their timing controlled by syncing with external devices, and keep the default latency for all other live loops. Let’s see:

live_loop :midi_piano do
  use_real_time
  note, velocity = sync "/midi/nanokey2_keyboard/0/1/note_on"
  synth :piano, note: note, amp: velocity / 127.0
end

Update your code to match the code above and hit Run again. Now we have a low latency piano with variable velocity coded in just 5 lines. Wasn’t that easy!

Getting Values

Finally, as our MIDI events are going straight into the Time State, we can also use the get fn to retrieve the last seen value. This doesn’t block the current thread and returns nil if there’s no value to be found (which you can override by passing a default value - see the docs for get). Remember that you can call get in any thread at any time to see the latest matching Time State value. You can even use time_warp to jump back in time and call get to see past events…

Now You are in Control

The exciting thing now is that you can now use the same code structures to sync and get MIDI information from any MIDI device and do whatever you want with the values. You can now choose what your MIDI device will do!


11.2 - MIDI Out

In addition to receiving MIDI events we can also send out MIDI events to trigger and control external hardware synths, keyboards and other devices. Sonic Pi provides a full set of fns for sending various MIDI messages such as:

Note on - midi_note_on Note off - midi_note_off Control change - midi_cc Pitch bend - midi_pitch_bend Clock ticks - midi_clock_tick

There are many other supported MIDI messages too - check out the API documentation for all the other fns that start with midi_.

Connecting to a MIDI Device

In order to send a MIDI message to an external device, we must first have connected it. Check out the subsection ‘Connecting a MIDI Controller’ in section 11.1 for further details. Note that if you’re using USB, connecting to a device which you’re sending to (rather than receiving from) is the same procedure. However, if you’re using the classic DIN connectors, make sure you connect to the MIDI out port of your computer. You should see your MIDI device listed in the preferences pane.

Sending MIDI events

The many midi_* fns work just like play, sample and synth in that they send a message at the current (logical) time. For example, to spread out calls to the midi_* fns you need to use sleep just like you did with play. Let’s take a look:

midi_note_on :e3, 50

This will send a MIDI note on event to the connected MIDI device with velocity 50. (Note that Sonic Pi will automatically convert notes in the form :e3 to their corresponding MIDI number such as 52 in this case.)

If your connected MIDI device is a synthesiser, you should be able to hear it playing a note. To disable it use midi_note_off:

midi_note_off :e3

Selecting a MIDI device

By default, Sonic Pi will send each MIDI message to all connected devices on all MIDI channels. This is to make it easy to work with a single connected device without having to configure anything. However, sometimes a MIDI device will treat MIDI channels in a special way (perhaps each note has a separate channel) and also you may wish to connect more than one MIDI device at the same time. In more complicated setups, you may wish to be more selective about which MIDI device receives which message(s) and on which channel.

We can specify which device to send to using the port: opt, using the device name as displayed in the preferences:

midi_note_on :e3, port: "moog_minitaur"

We can also specify which channel to send to using the channel: opt (using a value in the range 1-16):

midi_note_on :e3, channel: 3

Of course we can also specify both at the same time to send to a specific device on a specific channel:

midi_note_on :e3, port: "moog_minitaur", channel: 5

MIDI Studio

Finally, a really fun thing to do is to connect the audio output of your MIDI synthesiser to one of the audio inputs of your soundcard. You can then control your synth with code using the midi_* fns and also manipulate the audio using live_audio and FX:

with_fx :reverb, room: 1 do
  live_audio :moog
end
live_audio :moog_trigger do
  use_real_time
  midi (octs :e1, 3).tick, sustain: 0.1
  sleep 0.125
end

(The fn midi is available as a handy shortcut to sending both note on and note off events with a single command. Check out its documentation for further information).


12 - OSC

In addition to MIDI, another way to get information in and out of Sonic Pi is via the network using a simple protocol called OSC - Open Sound Control. This will let you send messages to and from external programs (both running on your computer and on external computers) which opens up the potential for control way beyond MIDI which has limitations due to its 1980s design.

For example, you could write a program in another programming language which sends and receives OSC (there are OSC libraries for pretty much every common language) and work directly with Sonic Pi. What you can use this for is only limited by your imagination.


12.1 - Receiving OSC

By default when Sonic Pi is launched it listens to port 4559 for incoming OSC messages from programs on the same computer. This means that without any configuration, you can send Sonic Pi an OSC message and it will be displayed in the cue log just like incoming MIDI messages. This also means that any incoming OSC message is also automatically added to the Time State which means you can also use get and sync to work with the incoming data - just like with MIDI.

A Basic OSC Listener

Let’s build a basic OSC listener:

live_loop :foo do
  use_real_time
  a, b, c = sync "/osc/trigger/prophet"
  synth :prophet, note: a, cutoff: b, sustain: c
end

In this example we described an OSC path "/osc/trigger/prophet" which we’re syncing on. This can be any valid OSC path (all letters and numbers are supported and the / is used like in a URL to break up the path to multiple words). The /osc prefix is added by Sonic Pi to all incoming OSC messages, so we need to send an OSC message with the path /trigger/prophet for our sync to stop blocking and the prophet synth to be triggered.

Sending OSC to Sonic Pi

We can send OSC to Sonic Pi from any programming language that has an OSC library. For example, if we’re sending OSC from Python we might do something like this:

from pythonosc import osc_message_builder
from pythonosc import udp_client
sender = udp_client.SimpleUDPClient('127.0.0.1', 4559)
sender.send_message('/trigger/prophet', [70, 100, 8])

Or, if we’re sending OSC from Clojure we might do something like this from the REPL:

(use 'overtone.core)
(def c (osc-client "127.0.0.1" 4559))
(osc-send c "/trigger/prophet" 70 100 8)

Receiving from External Machines

For security reasons, by default Sonic Pi does not let remote machines send it OSC messages. However, you can enable support for remote machines in Preferences->IO->Network->Receive Remote OSC Messages. Once you’ve enabled this, you can receive OSC messages from any computer on your network. Typically the sending machine will need to know your IP address (a unique identifier for your computer on your network - kind of like a phone number or an email address). You can discover the IP address of your computer by looking at the IO section of the preferences pane. (If your machine happens to have more than one IP address, hovering the mouse over the listed address will pop up with a list of all known addresses).

Note, some programs such as TouchOSC for iPhone and Android support sending OSC as a standard feature. So, once you’re listening to remote machines and know your IP address you can instantly start sending messages from apps like TouchOSC which enable you to build your own custom touch controls with sliders, buttons, dials etc. This can provide you with an enormous range of input options.


12.2 - Sending OSC

In addition to receiving OSC and working with it using Time State, we can also send out OSC messages in time with our music (just like we can send out MIDI messages in time with our music). We just need to know which IP address and port we’re sending to. Let’s give it a try:

use_osc "localhost", 4559
osc "/hello/world"

If you run the code above, you’ll notice that Sonic Pi is sending itself an OSC message! This is because we set the IP address to the current machine and the port to the default OSC in port. This is essentially the same as posting a letter to yourself - the OSC packet is created, leaves Sonic Pi, gets to the network stack of the operating system which then routes the packed back to Sonic Pi and then it’s received as a standard OSC message and is visible in the cue logger as the incoming message "/osc/hello/world. (Notice how Sonic Pi automatically prefixes all incoming OSC messages with /osc.)

Sending OSC to other programs

Of course, sending OSC messages to ourselves may be fun but it’s not that useful. The real benefit starts when we send messages to other programs:

use_osc "localhost", 123456
osc "/hello/world"

In this case we’re assuming there’s another program on the same machine listening to port 123456. If there is, then it will receive a "/hello/world OSC message with which it can do what it wants.

If our program is running on another machine, we need to know its IP address which we use instead of "localhost":

use_osc "192.168.10.23", 123456
osc "/hello/world"

Now we can send OSC messages to any device reachable to us via our local networks and even the internet!


13 - Multichannel Audio

So far, in terms of sound production, we’ve explored triggering synths and recorded sounds via the fns play, synth and sample. These have then generated audio which has played through our stereo speaker system. However, many computers also have the ability to input sound, perhaps through a microphone, in addition to the ability to send sound out to more than two speakers. Often, this capability is made possible through the use of an external sound card - these are available for all platforms. In this section of the tutorial we’ll take a look at how we can take advantage of these external sound cards and effortlessly work with multiple channels of audio in and out of Sonic Pi.


13.1 - Sound In

One simple (and perhaps familiar) way of accessing sound inputs is using our friend synth by specifying the :sound_in synth:

synth :sound_in

This will operate just like any synth such as synth :dsaw with the exception that the audio generated will be read directly from the first input of your system’s sound card. On laptops, this is typically the built-in microphone, but if you have an external sound card, you can plug any audio input to the first input.

Increasing the Duration

One thing you might notice is that just like synth :dsaw the :sound_in synth only lasts for 1 beat as it has a standard envelope. If you’d like to keep it open for a little longer, change the ADSR envelope settings. For example the following will keep the synth open for 8 beats before closing the connection:

synth :sound_in, sustain: 8

Añadiendo efectos FX

Of course, just like any normal synth, you can easily layer on effects with the FX block:

with_fx :reverb do
  with_fx :distortion do
    synth :sound_in, sustain: 8
  end
end

If you have plugged in a guitar to your first input, you should be able to hear it with distortion and reverb until the synth terminates as expected.

You are free to use the :sound_in synth as many times as you like concurrently (just like you would do with any normal synth). For example, the following will play two :sound_in synths at the same time - one through distortion and one through reverb:

with_fx :distortion do
  synth :sound_in, sustain: 8
end
with_fx :reverb do  
  synth :sound_in, sustain: 8
end

Multiple Inputs

You can select which audio input you want to play with the input: opt. You can also specify a stereo input (two consecutive inputs) using the :sound_in_stereo synth. For example, if you have a sound card with at least three inputs, you can treat the first two as a stereo stream and add distortion and the third as a mono stream and add reverb with the following code:

with_fx :distortion do
  synth :sound_in_stereo, sustain: 8, input: 1
end
with_fx :reverb do  
  synth :sound_in, sustain: 8, input: 3
end

Potential Issues

However, although this is a useful technique, there are a couple of limitations to this approach. Firstly, it only works for a specific duration (due to it having an ADSR envelope) and secondly, there’s no way to switch the FX around once the synth has been triggered. Both of these things are typical requests when working with external audio feeds such as microphones, guitars and external synthesisers. We’ll therefore take a look at Sonic Pi’s solution to the problem of manipulating a (potentially) infinite stream of live audio input: live_audio.


13.2 - Live Audio

The :sound_in synth as described in the previous section provides a very flexible and familiar method for working with input audio. However, as also discussed it has a few issues when working with a single input of audio as a single instrument (such as a voice or guitar). By far the best approach to working with a single continuous stream of audio is to use live_audio.

A Named Audio Input

live_audio shares a couple of core design constraints with live_loop (hence the similar name). Firstly it must have a unique name and secondly only one live_audio stream with that name may exist at any one time. Let’s take a look:

live_audio :foo

This code will act in a similar fashion to synth :sound_in with some key differences: it runs forever (until you explicitly stop it) and you can move it to new FX contexts dynamically.

Working with FX

On initial triggering live_audio works exactly as you might expect it to work with FX. For example, to start a live audio stream with added reverb simply use a :reverb FX block:

with_fx :reverb do
  live_audio :foo
end

However, given that live_audio runs forever (at least until you stop it) it would be pretty limiting if, like typical synths, the live audio was bound within the :reverb FX for its entire existence. Luckily this is not the case and it was designed to be easy to move between different FX. Let’s try it. Run the code above to hear live audio coming directly from the first input of your sound card. Note, if you’re using a laptop, this will typically be out of your built-in microphone, so it’s recommended to use headphones to stop feedback.

Now, whilst you’re still hearing the audio live from the sound card with reverb, change the code to the following:

with_fx :echo do
  live_audio :foo
end

Now, hit Run, and you’ll immediately hear the audio played through the echo FX and no longer through reverb. If you wanted them both, just edit the code again and hit Run:

with_fx :reverb do
  with_fx :echo do
    live_audio :foo
  end
end

It’s important to point out that you can call live_audio :foo from any thread or live loop and it will move the live audio synth to that thread’s current FX context. You could therefore easily have multiple live loops calling live_audio :foo at different times resulting in the FX context being automatically swapped around for some interesting results.

Stopping live audio

Unlike standard synths, as live_audio has no envelope, it will continue running forever (even if you delete the code, just like a function is still defined in memory if you delete the code in the editor). To stop it, you need to use the :stop arg:

live_audio :foo, :stop

It can easily be restarted by calling it without the :stop arg again:

live_audio :foo

Additionally all running live audio synths are stopped when you hit the global Stop button (as with all other running synths and FX).

Stereo input

With respect to audio channels, by default live_audio acts similarly to the :sound_in synth in that it takes a single mono input stream of audio and converts it to a stereo stream using the specified panning. However, just like :sound_in_stereo it’s also possible to tell live_audio to read two consecutive audio inputs and treat them as the left and right channels directly. This is achieved via the :stereo opt. For example, to treat input 2 as the left signal and input 3 as the right signal, you need to configure the input: opt to 2 and enable stereo mode as follows:

live_audio :foo, stereo: true, input: 2

Note that once you have started a live audio stream in stereo mode, you cannot change it to mono without stopping and starting. Similarly, if you start it in the default mono mode, you can’t switch to stereo without starting and stopping the stream.


13.3 - Sound Out

So far in this section we’ve looked at how to get multiple streams of audio into Sonic Pi - either through the use of the :sound_in synth or via the powerful live_audio system. In addition to working with multiple streams of input audio, Sonic Pi can also output multiple streams of audio. This is achieved via the :sound_out FX.

Output contexts

Let’s quickly recap on how Sonic Pi’s synths and FX output their audio to their current FX context. For example, consider the following:

with_fx :reverb do    # C
  with_fx :echo do    # B
    sample :bd_haus   # A
  end
end

The simplest way to understand what’s happening with the audio stream is to start at the innermost audio context and work our way out. In this case, the innermost context is labelled A and is the :bd_haus sample being triggered. The audio for this goes directly into its context which is B - the :echo FX. This then adds echo to the incoming audio and outputs it to its context which is C - the :reverb FX. This then adds reverb to the incoming audio and outputs to its context which is the top level - the left and right speakers (outputs 1 and 2 in your audio card). The audio flows outwards with a stereo signal all the way through.

Sound Out FX

The above behaviour is true for all synths (including live_audio) and the majority of FX with the exception of :sound_out. The :sound_out FX does two things. Firstly it outputs its audio to its external context as described above. Secondly it also outputs its audio directly to an output on your sound card. Let’s take a look:

with_fx :reverb do      # C
  with_fx :sound_out, output: 3 do # B
    sample :bd_haus     # A
  end
end

In this example, our :bd_haus sample outputs its audio to its external context which is the :sound_out FX. This in turn outputs its audio to its external context the :reverb FX (as expected). However, it also outputs a mono mix to the 3rd output of the system’s soundcard. The audio generated within :sound_out therefore has two destinations - the :reverb FX and audio card output 3.

Mono and Stereo out

As we’ve seen, by default, the :sound_out FX outputs a mono mix of the stereo input to a specific channel in addition to passing the stereo feed to the outer context (as expected). If outputting a mono mix isn’t precisely what you want to do, there are a number of alternative options. Firstly, by using the mode: opt you can choose to output just the left or just the right input signal to the audio card. Or you can use the :sound_out_stereo FX to output to two consecutive sound card outputs. See the function documentation for more information and examples.

Direct Out

As we have also seen, the default behaviour for :sound_out and :sound_out_stereo is to send the audio both to their external context (as is typical of all FX) and to the specified output on your soundcard. However, occasionally you may wish to only send to the output on your soundcard and not to the external context (and therefore not have any chance of the sound being mixed and sent to the standard output channels 1 and 2). This is possible by using the standard FX opt amp: which operates on the audio after the FX has been able to manipulate the audio:

with_fx :sound_out, output: 3, amp: 0 do # B
  sample :loop_amen                      # A
end

In the above example, the :loop_amen sample is sent to its outer context, the :sound_out FX. This then sends a mono mix to audio card output 3 and then multiplies the audio by 0 which essentially silences it. It is this silenced signal which is then sent out to the :sound_out’s outer context which is the standard output. Therefore with this code, the default output channels will not receive any audio, and channel 3 will receive a mono mix of the amen drum break.


14 - Conclusiones

Con esto concluye el tutorial introductorio a Sonic Pi. Ojalá hayas aprendido algo por el camino. No te preocupes si crees que no entendiste todo - sólo juega y diviértete y verás que entiendes a tu propio ritmo - Vuelve cuando tengas alguna duda que pueda haber sido cubierta en una de las secciones.

Si tienes preguntas que no están cubiertas en el tutorial, por favor dirígete a Sonic Pi forums y haz tu pregunta. Seguro encuentras alguien amistoso que te eche una mano.

Finalmente, te invito a que estudies el resto de la documentación en el sistema de ayuda. Hay un número de características no cubiertas en el tutorial que esperan a ser descubiertas.

Así que juega, diviértete, comparte código con amigos, muestra tu pantalla y recuerda:

No hay errores, sólo oportunidades.

Sam Aaron


- MagPi Articles

Appendix A collects all the Sonic Pi articles written for the MagPi magazine.

Dive into Topics

These articles aren’t meant to be read in any strict order and contain a lot of cross-over material from the tutorial itself. Rather than try and teach you all of Sonic Pi, they instead each focus on a specific aspect of Sonic Pi and cover it in a fun and accessible way.

Read the MagPi

You can see them in their glorious professionally typeset form in the free PDF downloads of The MagPi here: https://www.raspberrypi.org/magpi/

Suggest a Topic

If you don’t see a topic that interests you covered in these articles - why not suggest one? The easiest way to do that is to tweet your suggestion to @Sonic_Pi. You never know - your suggestion might be the subject of the next article!


- Five Top Tips

1. There are no mistakes

The most important lesson to learn with Sonic Pi is that there really are no mistakes. The best way to learn is to just try and try and try. Try lots of different things out, stop worrying whether your code sounds good or not and start experimenting with as many different synths, notes, FX and opts as possible. You’ll discover a lot of things that make you laugh because they sound just awful and some real gems that sound truly amazing. Simply drop the things you don’t like and keep the things you do. The more ‘mistakes’ you allow yourself to make the quicker you’ll learn and discover your personal coding sound.

2. Use the FX

Say you’ve already mastered the Sonic Pi basics of making sounds with sample, play? What’s next? Did you know that Sonic Pi supports over 27 studio FX to change the sound of your code? FX are like fancy image filters in drawing programs except that instead of blurring or making something black and white, you can add things like reverb, distortion and echo to your sound. Think of it like sticking the cable from your guitar to an effects pedal of your choice and then into the amplifier. Luckily, Sonic Pi makes using FX really easy and requires no cables! All you need to do is to choose which section of your code you’d like the FX added to and wrap it with the FX code. Let’s look at an example. Say you had the following code:

sample :loop_garzul
16.times do
  sample :bd_haus
  sleep 0.5
end

If you wanted to add FX to the :loop_garzul sample, you’d just tuck it inside a with_fx block like this:

with_fx :flanger do
  sample :loop_garzul
end
16.times do
  sample :bd_haus
  sleep 0.5
end

Now, if you wanted to add FX to the bass drum, go and wrap that with with_fx too:

with_fx :flanger do
  sample :loop_garzul
end
with_fx :echo do
  16.times do
    sample :bd_haus
    sleep 0.5
  end
end

Remember, you can wrap any code within with_fx and any sounds created will pass through that FX.

3. Parameterise your synths

In order to really discover your coding sound you’ll soon want to know how to modify and control synths and FX. For example, you might want to change the duration of a note, add more reverb, or change the time between echoes. Luckily, Sonic Pi gives you an amazing level of control to do exactly this with special things called optional parameters or opts for short. Let’s take a quick look. Copy this code into a workspace and hit run:

sample :guit_em9

Ooh, a lovely guitar sound! Now, let’s start playing with it. How about changing its rate?

sample :guit_em9, rate: 0.5

Hey, what’s that rate: 0.5 bit I just added at the end? That’s called an opt. All of Sonic Pi’s synths and FX support them and there’s loads to play around with. They’re also available for FX too. Try this:

with_fx :flanger, feedback: 0.6 do
  sample :guit_em9
end

Now, try increasing that feedback to 1 to hear some crazy sounds! Read the docs for full details on all the many opts available to you.

5. Live Code

The best way to quickly experiment and explore Sonic Pi is to live code. This allows you to start off some code and continually change and tweak it whilst it’s still playing. For example, if you don’t know what the cutoff parameter does to a sample, just play around. Let’s have a try! Copy this code into one of your Sonic Pi workspaces:

live_loop :experiment do
  sample :loop_amen, cutoff: 70
  sleep 1.75
end

Now, hit run and you’ll hear a slightly muffled drum break. Now, change the cutoff: value to 80 and hit run again. Can you hear the difference? Try 90, 100, 110

Once you get the hang of using live_loops you’ll not turn back. Whenever I do a live coding gig I rely on live_loop as much as a drummer relies on their sticks. For more information about live coding check out Section 9 of the built-in tutorial.

5. Surf the random streams

Finally, one thing I love doing is cheating by getting Sonic Pi to compose things for me. A really great way to do this is using randomisation. It might sound complicated but it really isn’t. Let’s take a look. Copy this into a spare workspace:

live_loop :rand_surfer do
  use_synth :dsaw
  notes = (scale :e2, :minor_pentatonic, num_octaves: 2)
  16.times do
    play notes.choose, release: 0.1, cutoff: rrand(70, 120)
    sleep 0.125
  end
end

Now, when you play this, you’ll hear a constant stream of random notes from the scale :e2 :minor_pentatonic played with the :dsaw synth. “Wait, wait! That’s not a melody”, I hear you shout! Well, here’s the first part of the magic trick. Every time we go round the live_loop we can tell Sonic Pi to reset the random stream to a known point. This is a bit like going back in time in the TARDIS with the Doctor to a particular point in time and space. Let’s try it - add the line use_random_seed 1 to the live_loop:

live_loop :rand_surfer do
  use_random_seed 1
  use_synth :dsaw
  notes = (scale :e2, :minor_pentatonic, num_octaves: 2)
  16.times do
    play notes.choose, release: 0.1, cutoff: rrand(70, 120)
    sleep 0.125
  end
end

Now, every time the live_loop loops around, the random stream is reset. This means it chooses the same 16 notes every time. Hey presto! An instant melody. Now, here’s the really exciting bit. Change the seed value from 1 to another number. Say 4923. Wow! Another melody! So, just by changing one number (the random seed), you can explore as many melodic combinations as you can imagine! Now, that’s the magic of code.


- Live Coding (Programación en vivo)

The laser beams sliced through the wafts of smoke as the subwoofer pumped bass deep into the bodies of the crowd. The atmosphere was ripe with a heady mix of synths and dancing. However something wasn’t quite right in this nightclub. Projected in bright colours above the DJ booth was futuristic text, moving, dancing, flashing. This wasn’t fancy visuals, it was merely a projection of Sonic Pi running on a Raspberry Pi. The occupant of the DJ booth wasn’t spinning disks, he was writing, editing and evaluating code. Live. This is Live Coding.

Sam Aaron Live Coding

This may sound like a far fetched story from a futuristic night club but coding music like this is a growing trend and is often described as Live Coding (http://toplap.org). One of the recent directions this approach to music making has taken is the Algorave (http://algorave.com) - events where artists like myself code music for people to dance to. However, you don’t need to be in a nightclub to Live Code - with Sonic Pi v2.6+ you can do it anywhere you can take your Raspberry Pi and a pair of headphones or some speakers. Once you reach the end of this article, you’ll be programming your own beats and modifying them live. Where you go afterwards will only be constrained by your imagination.

Live Loop

The key to live coding with Sonic Pi is mastering the live_loop. Let’s look at one:

live_loop :beats do
  sample :bd_haus
  sleep 0.5
end

There are 4 core ingredients to a live_loop. The first is its name. Our live_loop above is called :beats. You’re free to call your live_loop anything you want. Go crazy. Be creative. I often use names that communicate something about the music they’re making to the audience. The second ingredient is the do word which marks where the live_loop starts. The third is the end word which marks where the live_loop finishes, and finally there is the body of the live_loop which describes what the loop is going to repeat - that’s the bit between the do and end. In this case we’re repeatedly playing a bass drum sample and waiting for half a beat. This produces a nice regular bass beat. Go ahead, copy it into an empty Sonic Pi buffer and hit run. Boom, Boom, Boom!.

Redefining On-the-fly

Ok, so what’s so special about the live_loop? So far it just seems like a glorified loop! Well, the beauty of live_loops is that you can redefine them on-the-fly. This means that whilst they’re still running, you can change what they do. This is the secret to live coding with Sonic Pi. Let’s have a play:

live_loop :choral_drone do
  sample :ambi_choir, rate: 0.4
  sleep 1
end

Now press the Run button or hit alt-r. You’re now listening to some gorgeous choir sounds. Now, whilst it’s still playing, change the rate from 0.4 to 0.38. Hit run again. Woah! Did you hear the choir change note? Change it back up to 0.4 to return back to how it was. Now, drop it to 0.2, down to 0.19 and then back up to 0.4. See how changing just one parameter on the fly can give you real control of the music? Now play around with the rate yourself - choose your own values. Try negative numbers, really small numbers and large numbers. Have fun!

Sleeping is important

One of the most important lessons about live_loops is that they need rest. Consider the following live_loop:

live_loop :infinite_impossibilities do
  sample :ambi_choir
end

If you try running this code, you’ll immediately see Sonic Pi complaining that the live_loop did not sleep. This is a safety system kicking in! Take a moment to think about what this code is asking the computer to do. That’s right, it’s asking the computer to play an infinite amount of choir samples in zero time. Without the safety system the poor computer will try and do this and crash and burn in the process. So remember, your live_loops must contain a sleep.

Combining Sounds

Music is full of things happening at the same time. Drums at the same time as bass at the same time as vocals at the same time as guitars… In computing we call this concurrency and Sonic Pi provides us with an amazingly simple way of playing things at the same time. Simply use more than one live_loop!

live_loop :beats do
  sample :bd_tek
  with_fx :echo, phase: 0.125, mix: 0.4 do
    sample  :drum_cymbal_soft, sustain: 0, release: 0.1
    sleep 0.5
  end
end
live_loop :bass do
  use_synth :tb303
  synth :tb303, note: :e1, release: 4, cutoff: 120, cutoff_attack: 1
  sleep 4
end

Here, we have two live_loops, one looping quickly making beats and another looping slowly making a crazy bass sound.

One of the interesting things about using multiple live_loops is that they each manage their own time. This means it’s really easy to create interesting polyrhythmical structures and even play with phasing Steve Reich style. Check this out:

# Steve Reich's Piano Phase
notes = (ring :E4, :Fs4, :B4, :Cs5, :D5, :Fs4, :E4, :Cs5, :B4, :Fs4, :D5, :Cs5)
live_loop :slow do
  play notes.tick, release: 0.1
  sleep 0.3
end
live_loop :faster do
  play notes.tick, release: 0.1
  sleep 0.295
end

Bringing it all together

In each of these tutorials, we’ll end with a final example in the form of a new piece of music which draws from all of the ideas introduced. Read this code and see if you can imagine what it’s doing. Then, copy it into a fresh Sonic Pi buffer and hit Run and actually hear what it sounds like. Finally, change one of the numbers or comment and uncomment things out. See if you can use this as a starting point for a new performance, and most of all have fun! See you next time…

with_fx :reverb, room: 1 do
  live_loop :time do
    synth :prophet, release: 8, note: :e1, cutoff: 90, amp: 3
    sleep 8
  end
end
live_loop :machine do
  sample :loop_garzul, rate: 0.5, finish: 0.25
  sample :loop_industrial, beat_stretch: 4, amp: 1
  sleep 4
end
live_loop :kik do
  sample :bd_haus, amp: 2
  sleep 0.5
end
with_fx :echo do
  live_loop :vortex do
    # use_random_seed 800
    notes = (scale :e3, :minor_pentatonic, num_octaves: 3)
    16.times do
      play notes.choose, release: 0.1, amp: 1.5
      sleep 0.125
    end
  end
end

- Coded Beats

One of the most exciting and disrupting technical developments in modern music was the invention of samplers. These were boxes that allowed you to record any sound into them and then manipulate and play back those sounds in many interesting ways. For example, you could take an old record, find a drum solo (or break), record it into your sampler and then play it back on repeat at half-speed to provide the foundation for your latest beats. This is how early hip-hop music was born and today it’s almost impossible to find electronic music that doesn’t incorporate samples of some kind. Using samples is a really great way of easily introducing new and interesting elements into your live coded performances.

So where can you get a sampler? Well you already have one - it’s your Raspberry Pi! The built-in live coding app Sonic Pi has an extremely powerful sampler built into its core. Let’s play with it!

The Amen Break

One of the most classic and recognisable drum break samples is called the Amen Break. It was first performed in 1969 in the song “Amen Brother” by the Winstons as part of a drum break. However, it was when it was discovered by early hip-hop musicians in the 80s and used in samplers that it started being heavily used in a wide variety of other styles such as drum and bass, breakbeat, hardcore techno and breakcore.

I’m sure you’re excited to hear that it’s also built right into Sonic Pi. Clear up a buffer and throw in the following code:

sample :loop_amen

Hit Run and boom! You’re listening to one of the most influential drum breaks in the history of dance music. However, this sample wasn’t famous for being played as a one-shot, it was built for being looped.

Beat Stretching

Let’s loop the Amen Break by using our old friend the live_loop introduced in this tutorial last month:

live_loop :amen_break do
  sample :loop_amen
  sleep 2
end

OK, so it is looping, but there’s an annoying pause every time round. That is because we asked it to sleep for 2 beats and with the default BPM of 60 the :loop_amen sample only lasts for 1.753 beats. We therefore have a silence of 2 - 1.753 = 0.247 beats. Even though it’s short, it’s still noticeable.

To fix this issue we can use the beat_stretch: opt to ask Sonic Pi to stretch (or shrink) the sample to match the specified number of beats.

Sonic Pi’s sample and synth fns give you a lot of control via optional parameters such as amp:, cutoff: and release:. However, the term optional parameter is a real mouthful so we just call them opts to keep things nice and simple.

live_loop :amen_break do
  sample :loop_amen, beat_stretch: 2
  sleep 2
end  

Now we’re dancing! Although, perhaps we want to speed it up or slow it down to suit the mood.

Playing with Time

OK, so what if we want to change styles to old school hip hop or breakcore? One simple way of doing this is to play with time - or in other words mess with the tempo. This is super easy in Sonic Pi - just throw in a use_bpm into your live loop:

live_loop :amen_break do
  use_bpm 30
  sample :loop_amen, beat_stretch: 2
  sleep 2
end 

Whilst you’re rapping over those slow beats, notice that we’re still sleeping for 2 and our BPM is 30, yet everything is in time. The beat_stretch opt works with the current BPM to make sure everything just works.

Now, here’s the fun part. Whilst the loop is still live, change the 30 in the use_bpm 30 line to 50. Woah, everything just got faster yet kept in time! Try going faster - up to 80, to 120, now go crazy and punch in 200!

Filtering

Now we can live loop samples, let’s look at some of the most fun opts provided by the sample synth. First up is cutoff: which controls the cutoff filter of the sampler. By default this is disabled but you can easily turn it on:

live_loop :amen_break do
  use_bpm 50
  sample :loop_amen, beat_stretch: 2, cutoff: 70
  sleep 2
end  

Go ahead and change the cutoff: opt. For example, increase it to 100, hit Run and wait for the loop to cycle round to hear the change in the sound. Notice that low values like 50 sound mellow and bassy and high values like 100 and 120 are more full-sounding and raspy. This is because the cutoff: opt will chop out the high frequency parts of the sound just like a lawn-mower chops off the top of the grass. The cutoff: opt is like the length setting - determining how much grass is left over.

Slicing

Another great tool to play with is the slicer FX. This will chop (slice) the sound up. Wrap the sample line with the FX code like this:

live_loop :amen_break do
  use_bpm 50
  with_fx :slicer, phase: 0.25, wave: 0, mix: 1 do
    sample :loop_amen, beat_stretch: 2, cutoff: 100
  end
  sleep 2
end

Notice how the sound bounces up and down a little more. (You can hear the original sound without the FX by changing the mix: opt to 0.) Now, try playing around with the phase: opt. This is the rate (in beats) of the slicing effect. A smaller value like 0.125 will slice faster and larger values like 0.5 will slice more slowly. Notice that successively halving or doubling the phase: opts val tends to always sound good. Finally, change the wave: opt to one of 0, 1, or 2 and hear how it changes the sound. These are the various wave shapes. 0 is a saw wave, (hard in, fade out) 1 is a square wave (hard in, hard out) and 2 is a triangle wave (fade in, fade out).

Bringing it all together

Finally, let’s go back in time and revisit the early Bristol drum and bass scene with this month’s example. Don’t worry too much about what all this means, just type it in, hit Run, then start live coding it by changing opt numbers and see where you can take it. Please do share what you create! See you next time…

use_bpm 100
live_loop :amen_break do
  p = [0.125, 0.25, 0.5].choose
  with_fx :slicer, phase: p, wave: 0, mix: rrand(0.7, 1) do
    r = [1, 1, 1, -1].choose
    sample :loop_amen, beat_stretch: 2, rate: r, amp: 2
  end
  sleep 2
end
live_loop :bass_drum do
  sample :bd_haus, cutoff: 70, amp: 1.5
  sleep 0.5
end
live_loop :landing do
  bass_line = (knit :e1, 3, [:c1, :c2].choose, 1)
  with_fx :slicer, phase: [0.25, 0.5].choose, invert_wave: 1, wave: 0 do
    s = synth :square, note: bass_line.tick, sustain: 4, cutoff: 60
    control s, cutoff_slide: 4, cutoff: 120
  end
  sleep 4
end

- Synth Riffs

Whether it’s the haunting drift of rumbling oscillators or the detuned punch of saw waves piercing through the mix, the lead synth plays an essential role on any electronic track. In last month’s edition of this tutorial series we covered how to code our beats. In this tutorial we’ll cover how to code up the three core components of a synth riff - the timbre, melody and rhythm.

OK, so power up your Raspberry Pi, crack open Sonic Pi v2.6+ and let’s make some noise!

Timbral Possibilities

An essential part of any synth riff is changing and playing with the timbre of the sounds. We can control the timbre in Sonic Pi in two ways - choosing different synths for a dramatic change and setting the various synth opts for more subtle modifications. We can also use FX, but that’s for another tutorial…

Let’s create a simple live loop where we continually change the current synth:

live_loop :timbre do
  use_synth (ring :tb303, :blade, :prophet, :saw, :beep, :tri).tick
  play :e2, attack: 0, release: 0.5, cutoff: 100
  sleep 0.5
end

Take a look at the code. We’re simply ticking through a ring of synth names (this will cycle through each of these in turn repeating the list over and over). We pass this synth name to the use_synth fn (function) which will change the live_loop’s current synth. We also play note :e2 (E at the second octave), with a release time of 0.5 beats (half a second at the default BPM of 60) and with the cutoff: opt set to 100.

Hear how the different synths have very different sounds even though they’re all playing the same note. Now experiment and have a play. Change the release time to bigger and smaller values. For example, change the attack: and release: opts to see how different fade in/out times have a huge impact on the sound. Finally change the cutoff: opt to see how different cutoff values also massively influence the timbre (values between 60 and 130 are good). See how many different sounds you can create by just changing a few values. Once you’ve mastered that, just head to the Synths tab in the Help system for a full list of all the synths and all the available opts each individual synth supports to see just how much power you have under your coding fingertips.

Timbre

Timbre is just a fancy word describing the sound of a sound. If you play the same note with different instruments such as a violin, guitar, or piano, the pitch (how high or low it sounds) would be the same, but the sound quality would be different. That sound quality - the thing which allows you to tell the difference between a piano and a guitar is the timbre.

Melodic Composition

Another important aspect to our lead synth is the choice of notes we want to play. If you already have a good idea, then you can simply create a ring with your notes in and tick through them:

live_loop :riff do
  use_synth :prophet
  riff = (ring :e3, :e3, :r, :g3, :r, :r, :r, :a3)
  play riff.tick, release: 0.5, cutoff: 80
  sleep 0.25
end

Here, we’ve defined our melody with a ring which includes both notes such as :e3 and rests represented by :r. We’re then using .tick to cycle through each note to give us a repeating riff.

Auto Melody

It’s not always easy to come up with a nice riff from scratch. Instead it’s often easier to ask Sonic Pi for a selection of random riffs and to choose the one you like the best. To do that we need to combine three things: rings, randomisation and random seeds. Let’s look at an example:

live_loop :random_riff do
  use_synth :dsaw
  use_random_seed 3
  notes = (scale :e3, :minor_pentatonic).shuffle
  play notes.tick, release: 0.25, cutoff: 80
  sleep 0.25
end

There’s a few things going on - let’s look at them in turn. First, we specify that we’re using random seed 3. What does this mean? Well, the useful thing is that when we set the seed, we can predict what the next random value is going to be - it’s the same as it was last time we set the seed to 3! Another useful thing to know is that shuffling a ring of notes works in the same way. In the example above we’re essentially asking for the ‘third shuffle’ in the standard list of shuffles - which is also the same every time as we’re always setting the random seed to the same value right before the shuffle. Finally we’re just ticking through our shuffled notes to play the riff.

Now, here’s where the fun starts. If we change the random seed value to another number, say 3000, we get an entirely different shuffling of the notes. So now it’s extremely easy to explore new melodies. Simply choose the list of notes we want to shuffle (scales are a great starting point) and then choose the seed we want to shuffle with. If we don’t like the melody, just change one of those two things and try again. Repeat until you like what you hear!

Pseudo Randomisation

Sonic Pi’s randomisation is not actually random it’s what’s called pseudo random. Imagine if you were to roll a dice 100 times and write down the result of each roll onto a piece of paper. Sonic Pi has the equivalent of this list of results which it uses when you ask for a random value. Instead of rolling an actual dice, it just picks the next value from the list. Setting the random seed is just jumping to a specific point in that list.

Finding your Rhythm

Another important aspect to our riff is the rhythm - when to play a note and when not to. As we saw above we can use :r in our rings to insert rests. Another very powerful way is to use spreads which we’ll cover in a future tutorial. Today we’ll use randomisation to help us find our rhythm. Instead of playing every note we can use a conditional to play a note with a given probability. Let’s take a look:

live_loop :random_riff do
  use_synth :dsaw
  use_random_seed 30
  notes = (scale :e3, :minor_pentatonic).shuffle
  16.times do
    play notes.tick, release: 0.2, cutoff: 90 if one_in(2)
    sleep 0.125
  end
end

A really useful fn to know is one_in which will give us a true or false value with the specified probability. Here, we’re using a value of 2 so on average one time every two calls to one_in it will return true. In other words, 50% of the time it will return true. Using higher values will make it return false more often introducing more space into the riff.

Notice that we’ve added some iteration in here with 16.times. This is because we only want to reset our random seed value every 16 notes so our rhythm repeats every 16 times. This doesn’t affect the shuffling as that is still done immediately after the seed is set. We can use the iteration size to alter the length of the riff. Try changing the 16 to 8 or even 4 or 3 and see how it affects the rhythm of the riff.

Bringing it all together

OK, so let’s combine everything we’ve learned together into one final example. See you next time!

live_loop :random_riff do
  #  uncomment to bring in:
  #  synth :blade, note: :e4, release: 4, cutoff: 100, amp: 1.5
  use_synth :dsaw
  use_random_seed 43
  notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle.take(8)
  8.times do
    play notes.tick, release: rand(0.5), cutoff: rrand(60, 130) if one_in(2)
    sleep 0.125
  end
end
 
live_loop :drums do
  use_random_seed 500
  16.times do
    sample :bd_haus, rate: 2, cutoff: 110 if rand < 0.35
    sleep 0.125
  end
end
 
live_loop :bd do
  sample :bd_haus, cutoff: 100, amp: 3
  sleep 0.5
end

- Acid Bass

It’s impossible to look through the history of electronic dance music without seeing the enormous impact of the tiny Roland TB-303 synthesiser. It’s the secret sauce behind the original acid bass sound. Those classic squealing and squelching TB-303 bass riffs can be heard from the early Chicago House scene through to more recent electronic artists such as Plastikman, Squarepusher and Aphex Twin.

Interestingly, Roland never intended for the TB-303 to be used in dance music. It was originally created as a practice aid for guitarists. They imagined that people would program them to play bass lines to jam along to. Unfortunately there were a number of problems: they were a little fiddly to program, didn’t sound particularly good as a bass-guitar replacement and were pretty expensive to buy. Deciding to cut their losses, Roland stopped making them after 10,000 units were sold and after a number of years sitting on guitarist’s shelves, they soon could be found in the windows of second hand shops. These lonely discarded TB-303s were waiting to be discovered by a new generation of experimenters who started using them in ways that Roland didn’t imagine to create new crazy sounds. Acid House was born.

Although getting your hands on an original TB-303 is not so easy you will be pleased to know that you can turn your Raspberry Pi into one using the power of Sonic Pi. Behold, fire up Sonic Pi and throw this code into an empty buffer and hit Run:

use_synth :tb303
play :e1

Instant acid bass! Let’s play around…

- Squelch that Bass

First, let’s build a live arpeggiator to make things fun. In the last tutorial we looked at how riffs can just be a ring of notes that we tick through one after another, repeating when we get to the end. Let’s create a live loop that does exactly that:

use_synth :tb303
live_loop :squelch do
  n = (ring :e1, :e2, :e3).tick
  play n, release: 0.125, cutoff: 100, res: 0.8, wave: 0
  sleep 0.125
end

Take a look at each line.

On the first line we set the default synth to be tb303 with the use_synth fn. On line two we create a live loop called :squelch which will just loop round and round. Line three is where we create our riff - a ring of notes (E in octaves 1, 2, and 3) which we simply tick through with .tick. We define n to represent the current note in the riff. The equals sign just means to assign the value on the right to the name on the left. This will be different every time round the loop. The first time round, n will be set to :e1. The second time round it will be :e2, followed by :e3, and then back to :e1, cycling round forever. Line four is where we actually trigger our :tb303 synth. We’re passing a few interesting opts here: release:, cutoff:, res: and wave: which we’ll discuss below. Line five is our sleep - we’re asking the live loop to loop round every 0.125s or 8 times a second at the default BPM of 60. Line six is the end to the live loop. This just tells Sonic Pi where the end of the live loop is.

Whilst you’re still figuring out what’s going on, type in the code above and hit the Run button. You should hear the :tb303 kick into action. Now, this is where the action is: let’s start live coding.

Whilst the loop is still live, change the cutoff: opt to 110. Now hit the Run button again. You should hear the sound become a little harsher and more squelchy. Dial in 120 and hit run. Now 130. Listen how higher cutoff values make it sound more piercing and intense. Finally, drop it down to 80 when you feel like a rest. Then repeat as many times as you want. Don’t worry, I’ll still be here…

Another opt worth playing with is res:. This controls the level of resonance of the filter. A high resonance is characteristic of acid bass sounds. We currently have our res: set to 0.8. Try cranking it up to 0.85, then 0.9, and finally 0.95. You might find that a cutoff such as 110 or higher will make the differences easier to hear. Finally go crazy and dial in 0.999 for some insane sounds. At a res this high, you’re hearing the cutoff filter resonate so much it starts to make sounds of its own!

Finally, for a big impact on the timbre try changing the wave: opt to 1. This is the choice of source oscillator. The default is 0 which is a sawtooth wave. 1 is a pulse wave and 2 is a triangle wave.

Of course, try different riffs by changing the notes in the ring or even picking notes from scales or chords. Have fun with your first acid bass synth.

- Deconstructing the TB-303

The design of the original TB-303 is actually pretty simple. As you can see from the following diagram there’s only 4 core parts.

TB-303 Design

First is the oscillator wave - the raw ingredients of the sound. In this case we have a square wave. Next there’s the oscillator’s amplitude envelope which controls the amp of the square wave through time. These are accessed in Sonic Pi by the attack:, decay:, sustain: and release: opts along with their level counterparts. For more information read Section 2.4 ‘Duration with Envelopes’ in the built-in tutorial. We then pass our enveloped square wave through a resonant low pass filter. This chops off the higher frequencies as well as having that nice resonance effect. Now this is where the fun starts. The cutoff value of this filter is also controlled by its own envelope! This means we have amazing control over the timbre of the sound by playing with both of these envelopes. Let’s take a look:

use_synth :tb303
with_fx :reverb, room: 1 do
  live_loop :space_scanner do
    play :e1, cutoff: 100, release: 7, attack: 1, cutoff_attack: 4, cutoff_release: 4
    sleep 8
  end
end

For each standard envelope opt, there’s a cutoff_ equivalent opt in the :tb303 synth. So, to change the cutoff attack time we can use the cutoff_attack: opt. Copy the code above into an empty buffer and hit Run. You’ll hear a crazy sound warble in and out. Now start to play. Try changing the cutoff_attack: time to 1 and then 0.5. Now try 8.

Notice that I’ve passed everything through a :reverb FX for extra atmosphere - try other FX to see what works!

- Bringing it all together

Finally, here’s a piece I composed using the ideas in this tutorial. Copy it into an empty buffer, listen for a while and then start live coding your own changes. See what crazy sounds you can make with it! See you next time…

use_synth :tb303
use_debug false
 
with_fx :reverb, room: 0.8 do
  live_loop :space_scanner do
    with_fx :slicer, phase: 0.25, amp: 1.5 do
      co = (line 70, 130, steps: 8).tick
      play :e1, cutoff: co, release: 7, attack: 1, cutoff_attack: 4, cutoff_release: 4
      sleep 8
    end
  end
 
  live_loop :squelch do
    use_random_seed 3000
    16.times do
      n = (ring :e1, :e2, :e3).tick
      play n, release: 0.125, cutoff: rrand(70, 130), res: 0.9, wave: 1, amp: 0.8
      sleep 0.125
    end
  end
end

- Musical Minecraft

Hello and welcome back! In the previous tutorials we’ve focussed purely on the music possibilities of Sonic Pi - (turning your Raspberry Pi into a performance ready musical instrument). So far we’ve learned how to:

Live Code - changing the sounds on-the-fly, Code some huge beats, Generate powerful synth leads, Re-create the famous TB-303 acid-bass sound.

There’s so much more to show you (which we will explore in future editions). However, this month, let’s look at something Sonic Pi can do that you probably didn’t realise: control Minecraft.

- Hello Minecraft World

OK, let’s get started. Boot up your Raspberry Pi, fire up Minecraft Pi and create a new world. Now start up Sonic Pi and re-size and move your windows so you can see both Sonic Pi and Minecraft Pi at the same time.

In a fresh buffer type the following:

mc_message "Hola Minecraft desde Sonic Pi!"

Now, hit Run. Boom! Your message appeared in Minecraft! How easy was that? Now, stop reading this for a moment and play about with your own messages. Have fun!

Screen 0

- Sonic Teleporter

Now let’s do some exploring. The standard option is to reach for the mouse and keyboard and start walking around. That works, but it’s pretty slow and boring. It would be far better if we had some sort of teleport machine. Well, thanks to Sonic Pi, we have one. Try this:

mc_teleport 80, 40, 100

Crikey! That was a long way up. If you weren’t in flying-mode then you would have fallen back down all the way to the ground. If you double-tap space to enter flying-mode and teleport again, you’ll stay hovering at the location you zap to.

Now, what do those numbers mean? We have three numbers which describe the coordinates of where in the world we want to go. We give each number a name - x, y and z:

x - how far left and right (80 in our example) y - how high we want to be (40 in our example) z - how far forward and back (100 in our example)

By choosing different values for x, y and z we can teleport anywhere in our world. Try it! Choose different numbers and see where you can end up. If the screen goes black it’s because you’ve teleported yourself under the ground or into a mountain. Just choose a higher y value to get back out above land. Keep on exploring until you find somewhere you like…

Using the ideas so far, let’s build a Sonic Teleporter which makes a fun teleport sound whilst it whizzes us across the Minecraft world:

mc_message "Preparing to teleport...."
sample :ambi_lunar_land, rate: -1
sleep 1
mc_message "3"
sleep 1
mc_message "2"
sleep 1
mc_message "1"
sleep 1
mc_teleport 90, 20, 10
mc_message "Whoooosh!"

Screen 1

- Magic Blocks

Now you’ve found a nice spot, let’s start building. You could do what you’re used to and start clicking the mouse furiously to place blocks under the cursor. Or you could use the magic of Sonic Pi. Try this:

x, y, z = mc_location
mc_set_block :melon, x, y + 5, z

Now look up! There’s a melon in the sky! Take a moment to look at the code. What did we do? On line one we grabbed the current location of Steve as the variables x, y and z. These correspond to our coordinates described above. We use these coordinates in the fn mc_set_block which will place the block of your choosing at the specified coordinates. In order to make something higher up in the sky we just need to increase the y value which is why we add 5 to it. Let’s make a long trail of them:

live_loop :melon_trail do
  x, y, z = mc_location
  mc_set_block :melon, x, y-1, z
  sleep 0.125
end

Now, jump over to Minecraft, make sure you’re in flying-mode (double tap space if not) and fly all around the world. Look behind you to see a pretty trail of melon blocks! See what kind of twisty patterns you can make in the sky.

- Live Coding Minecraft

Those of you that have been following this tutorial over the last few months will probably have your minds blown at this point. The trail of melons is pretty cool, but the most exciting part of the previous example is that you can use live_loop with Minecraft! For those that don’t know, live_loop is Sonic Pi’s special magic ability that no other programming language has. It lets you run multiple loops at the same time and allows you to change them whilst they run. They are incredibly powerful and amazing fun. I use live_loops to perform music in nightclubs with Sonic Pi - DJs use discs and I use live_loops :-) However, today we’re going to live code both music and Minecraft.

Let’s get started. Run the code above and start making your melon trail again. Now, without stopping the code, just simply change :melon to :brick and hit run. Hey presto, you’re now making a brick trail. How simple was that! Fancy some music to go with it? Easy. Try this:

live_loop :bass_trail do
  tick
  x, y, z = mc_location
  b = (ring :melon, :brick, :glass).look
  mc_set_block b, x, y -1, z
  note = (ring :e1, :e2, :e3).look
  use_synth :tb303
  play note, release: 0.1, cutoff: 70
  sleep 0.125
end

Now, whilst that’s playing start changing the code. Change the block types - try :water, :grass or your favourite block type. Also, try changing the cutoff value from 70 to 80 and then up to 100. Isn’t this fun?

- Bringing it all together

Screen 2

Let’s combine everything we’ve seen so far with a little extra magic. Let’s combine our teleportation ability with block placing and music to make a Minecraft Music Video. Don’t worry if you don’t understand it all, just type it in and have a play by changing some of the values whilst it’s running live. Have fun and see you next time…

live_loop :note_blocks do
  mc_message "This is Sonic Minecraft"
  with_fx :reverb do
    with_fx :echo, phase: 0.125, reps: 32 do
      tick
      x = (range 30, 90, step: 0.1).look
      y = 20
      z = -10
      mc_teleport x, y, z
      ns = (scale :e3, :minor_pentatonic)
      n = ns.shuffle.choose
      bs = (knit :glass, 3, :sand, 1)
      b = bs.look
      synth :beep, note: n, release: 0.1
      mc_set_block b, x+20, n-60+y, z+10
      mc_set_block b, x+20, n-60+y, z-10
      sleep 0.25
    end
  end
end
live_loop :beats do
  sample :bd_haus, cutoff: 100
  sleep 0.5
end

- Bizet Beats

After our brief excursion to the fantastic world of coding Minecraft with Sonic Pi last month, let’s get musical again. Today we’re going to bring a classical operatic dance piece straight into the 21st century using the awesome power of code.

- Outrageous and Disruptive

Let’s jump into a time machine back to the year 1875. A composer called Bizet had just finished his latest opera Carmen. Unfortunately like many exciting and disruptive new pieces of music people initially didn’t like it at all because it was too outrageous and different. Sadly Bizet died ten years before the opera gained huge international success and became one of the most famous and frequently performed operas of all time. In sympathy with this tragedy let’s take one of the main themes from Carmen and convert it to a modern format of music that is also too outrageous and different for most people in our time - live coded music!

- Decoding the Habanera

Trying to live code the whole opera would be a bit of a challenge for this tutorial, so let’s focus on one of the most famous parts - the bass line to the Habanera:

Habanera Riff

This may look extremely unreadable to you if you haven’t yet studied music notation. However, as programmers we see music notation as just another form of code - only it represents instructions to a musician instead of a computer. We therefore need to figure out a way of decoding it.

- Notes

The notes are arranged from left to right like the words in this magazine but also have different heights. The height on the score represents the pitch of the note. The higher the note on the score, the higher the pitch of the note.

In Sonic Pi we already know how to change the pitch of a note - we either use high or low numbers such as play 75 and play 80 or we use the note names: play :E and play :F. Luckily each of the vertical positions of the musical score represents a specific note name. Take a look at this handy look up table:

Notes

- Rests

Music scores are an extremely rich and expressive kind of code capable of communicating many things. It therefore shouldn’t come as much of a surprise that musical scores can not only tell you what notes to play but also when not to play notes. In programming this is pretty much equivalent to the idea of nil or null - the absence of a value. In other words not playing a note is like the absence of a note.

If you look closely at the score you’ll see that it’s actually a combination of black dots with lines which represent notes to play and squiggly things which represent the rests. Luckily Sonic Pi has a very handy representation for a rest: :r, so if we run: play :r it actually plays silence! We could also write play :rest, play nil or play false which are all equivalent ways of representing rests.

- Rhythm

Finally, there’s one last thing to learn how to decode in the notation - the timings of the notes. In the original notation you’ll see that the notes are connected with thick lines called beams. The second note has two of these beams which means it lasts for a 16th of a beat. The other notes have a single beam which means they last for an 8th of a beat. The rest has two squiggly beams which means it also represents a 16th of the beat.

When we attempt to decode and explore new things a very handy trick is to make everything as similar as possible to try and see any relationships or patterns. For example, when we re-write our notation purely in 16ths you can see that our notation just turns into a nice sequence of notes and rests.

Habanera Riff 2

- Re-coding the Habanera

We’re now in a position to start translating this bass line to Sonic Pi. Let’s encode these notes and rests in a ring:

(ring :d, :r, :r, :a, :f5, :r, :a, :r)

Let’s see what this sounds like. Throw it in a live loop and tick through it:

live_loop :habanera do
  play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
  sleep 0.25
end

Fabulous, that instantly recognisable riff springs to life through your speakers. It took a lot of effort to get here, but it was worth it - high five!

- Moody Synths

Now we have the bass line, let’s re-create some of the ambience of the operatic scene. One synth to try out is :blade which is a moody 80s style synth lead. Let’s try it with the starting note :d passed through a slicer and reverb:

live_loop :habanera do
  use_synth :fm
  use_transpose -12
  play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
  sleep 0.25
end
with_fx :reverb do
  live_loop :space_light do
    with_fx :slicer, phase: 0.25 do
      synth :blade, note: :d, release: 8, cutoff: 100, amp: 2
    end
    sleep 8
  end
end

Now, try the other notes in the bass line: :a and :f5. Remember, you don’t need to hit stop, just modify the code whilst the music is playing and hit run again. Also, try different values for the slicer’s phase: opt such as 0.5, 0.75 and 1.

- Bringing it all together

Finally, let’s combine all the ideas so far into a new remix of the Habanera. You might notice that I’ve included another part of the bass line as a comment. Once you’ve typed it all into a fresh buffer hit Run to hear the composition. Now, without hitting stop, uncomment the second line by removing the # and hit run again - how marvellous is that! Now, start mashing it around yourself and have fun.

use_debug false
bizet_bass = (ring :d, :r, :r, :a, :f5, :r, :a, :r)
#bizet_bass = (ring :d, :r, :r, :Bb, :g5, :r, :Bb, :r)
 
with_fx :reverb, room: 1, mix: 0.3 do
  live_loop :bizet do
    with_fx :slicer, phase: 0.125 do
      synth :blade, note: :d4, release: 8,
        cutoff: 100, amp: 1.5
    end
    16.times do
      tick
      play bizet_bass.look, release: 0.1
      play bizet_bass.look - 12, release: 0.3
      sleep 0.125
    end
  end
end
 
live_loop :ind do
  sample :loop_industrial, beat_stretch: 1,
    cutoff: 100, rate: 1
  sleep 1
end
 
live_loop :drums do
  sample :bd_haus, cutoff: 110
  synth :beep, note: 49, attack: 0,
    release: 0.1
  sleep 0.5
end

- Become a Minecraft VJ

Screen 0

Everyone has played Minecraft. You will all have built amazing structures, designed cunning traps and even created elaborate cart lines controlled by redstone switches. How many of you have performed with Minecraft? We bet you didn’t know that you could use Minecraft to create amazing visuals just like a professional VJ.

If your only way of modifying Minecraft was with the mouse, you’d have a tough time changing things fast enough. Luckily for you your Raspberry Pi comes with a version of Minecraft that can be controlled with code. It also comes with an app called Sonic Pi which makes coding Minecraft not only easy but also incredibly fun.

In today’s article we’ll be showing you some of the tips and tricks that we’ve used to create performances in night clubs and music venues around the world.

Let’s get started…

- Getting Started

Let’s start with a simple warm up exercise to refresh ourselves with the basics. First up, crack open your Raspberry Pi and then fire up both Minecraft and Sonic Pi. In Minecraft, create a new world, and in Sonic Pi choose a fresh buffer and write in this code:

mc_message "Comencemos..."

Hit the Run button and you’ll see the message over in the Minecraft window. OK, we’re ready to start, let’s have some fun……

- Sand Storms

When we’re using Minecraft to create visuals we try and think about what will both look interesting and also be easy to generate from code. One nice trick is to create a sand storm by dropping sand blocks from the sky. For that all we need are a few basic fns:

sleep - for inserting a delay between actions mc_location - to find our current location mc_set_block- to place sand blocks at a specific location rrand - to allow us to generate random values within a range live_loop - to allow us to continually make it rain sand

If you’re unfamiliar with any of the built-in fns such as rrand, just type the word into your buffer, click on it and then hit the keyboard combo Control-i to bring up the built-in documentation. Alternatively you can navigate to the lang tab in the Help system and then look up the fns directly along with all the other exciting things you can do.

Let’s make it rain a little first before unleashing the full power of the storm. Grab your current location and use it to create a few sand blocks up in the sky nearby:

x, y, z = mc_location
mc_set_block :sand, x, y + 20, z + 5
sleep 2
mc_set_block :sand, x, y + 20, z + 6
sleep 2
mc_set_block :sand, x, y + 20, z + 7
sleep 2
mc_set_block :sand, x, y + 20, z + 8

When you hit Run, you might have to look around a little as the blocks may start falling down behind you depending on which direction you’re currently facing. Don’t worry, if you missed them just hit Run again for another batch of sand rain - just make sure you’re looking the right way!

Let’s quickly review what’s going on here. On the first line we grabbed Steve’s location as coordinates with the fn mc_location and placed them into the vars x, y, and z. Then on the next lines we used the mc_set_block fn to place some sand at the same coordinates as Steve but with some modifications. We chose the same x coordinate, a y coordinate 20 blocks higher and then successively larger z coordinates so the sand dropped in a line away from Steve.

Why don’t you take that code and start playing around with it yourself? Try adding more lines, changing the sleep times, try mixing :sand with :gravel and choose different coordinates. Just experiment and have fun!

- Live Loops Unleashed

OK, it’s time to get the storm raging by unleashing the full power of the live_loop - Sonic Pi’s magical ability which unleashes the full power of live coding - changing code on-the-fly whilst it’s running!

live_loop :sand_storm do
  x, y, z = mc_location
  xd = rrand(-10, 10)
  zd = rrand(-10, 10)
  co = rrand(70, 130)
  synth :cnoise, attack: 0, release: 0.125, cutoff: co
  mc_set_block :sand, x + xd, y+20, z+zd
  sleep 0.125
end

What fun! We’re looping round pretty quickly (8 times a second) and during each loop we’re finding Steve’s location like before but then generating 3 random values:

xd - the difference for x which will be between -10 and 10 zd - the difference for z also between -10 and 10 co - a cutoff value for the low pass filter between 70 and 130

We then use those random values in the fns synth and mc_set_block giving us sand falling in random locations around Steve along with a percussive rain-like sound from the :cnoise synth.

For those of you new to live loops - this is where the fun really starts with Sonic Pi. Whilst the code is running and the sand is pouring down, try changing one of the values, perhaps the sleep time to 0.25 or the :sand block type to :gravel. Now hit run again. Hey Presto! Things changed without the code stopping. This is your gateway to performing like a real VJ. Keep practising and changing things around. How different can you make the visuals without stopping the code?

- Epic Block Patterns

Screen 1

Finally, another great way of generating interesting visuals is to generate huge patterned walls to fly towards and close by. For this effect we’ll need to move from placing the blocks randomly to placing them in an ordered manner. We can do this by nesting two sets of iteration (hit the Help button and navigate to section 5.2 of the tutorial “Iteration and Loops” for more background on iteration). The funny |xd| after the do means that xd will be set for each value of the iteration. So the first time it will be 0, then 1, then 2… etc. By nesting two lots of iteration together like this we can generate all the coordinates for a square. We can then randomly choose block types from a ring of blocks for an interesting effect:

x, y, z = mc_location
bs = (ring :gold, :diamond, :glass)
10.times do |xd|
  10.times do |yd|
    mc_set_block bs.choose, x + xd, y + yd, z
  end
end

Pretty neat. Whilst we’re having fun here, try changing bs.choose to bs.tick to move from a random pattern to a more regular one. Try changing the block types and the more adventurous of you might want to try sticking this within a live_loop so that the patterns keep changing automatically.

Now, for the VJ finale - change the two 10.times to 100.times and hit Run. Kaboom! A Huge gigantic wall of randomly placed bricks. Imagine how long it would take you to build that manually with your mouse! Double-tap space to enter fly-mode and start swooping by for some great visual effects. Don’t stop here though - use your imagination to conjure up some cool ideas and then use the coding power of Sonic Pi to make it real. When you’ve practised enough dim the lights and put on a VJ show for your friends!


- Surfing Random Streams

Back in episode 4 of this tutorial series we took a brief look at randomisation whilst coding up some sizzling synth riffs. Given that randomisation is such an important part of my live coding DJ sets I thought it would be useful to cover the fundamentals in much greater detail. So, get your lucky hat on and let’s surf some random streams!

- There is no random

The first thing to learn which might really surprise you when playing with Sonic Pi’s randomisation functions is that they’re not actually really random. What does this actually mean? Well, let’s try a couple of tests. First, imagine a number in your head between 0 and 1. Keep it there and don’t tell me. Now let me guess… was it 0.321567? No? Bah, I’m clearly no good at this. Let me have another go, but let’s ask Sonic Pi to choose a number this time. Fire up Sonic Pi v2.7+ and ask it for a random number but again don’t tell me:

print rand

Now for the reveal… was it 0.75006103515625? Yes! Ha, I can see you’re a little sceptical. Perhaps it was just a lucky guess. Let’s try again. Press the Run button again and see what we get… What? 0.75006103515625 again? This clearly can’t be random! You’re right, it’s not.

What’s going on here? The fancy computer science word here is determinism. This just means that nothing is by chance and everything is destined to be. Your version of Sonic Pi is destined to always return 0.75006103515625 in the program above. This might sound pretty useless, but let me assure you that it’s one of the most powerful parts of Sonic Pi. If you stick at it you’ll learn how to rely on the deterministic nature of Sonic Pi’s randomisation as a fundamental building block for your compositions and live coded DJ sets.

- Una melodía aleatoria

When Sonic Pi boots it actually loads into memory a sequence of 441,000 pre-generated random values. When you call a random function such as rand or rrand, this random stream is used to generate your result. Each call to a random function consumes a value from this stream. Therefore the 10th call to a random function will use the 10th value from the stream. Also, every time you press the Run button, the stream is reset for that run. This is why I could predict the result to rand and why the ‘random’ melody was the same every time. Everybody’s version of Sonic Pi uses the exact same random stream which is very important when we start sharing our pieces with each other.

Let’s use this knowledge to generate a repeatable random melody:

8.times do
 play rrand_i(50, 95)
 sleep 0.125
end

Type this into a spare buffer and hit Run. You’ll hear a melody consisting of ‘random’ notes between 50 and 95. When it’s finished, hit Run again to hear exactly the same melody again.

Handy Randomisation Functions

Sonic Pi comes with a number of useful functions for working with the random stream. Here’s a list of some of the most useful:

rand - Simply returns the next value in the random stream rrand - Returns a random value within a range rrand_i - Returns a random whole number within a range one_in - Returns true or false with the given probability dice - Imitates rolling a dice and returns a value between 1 and 6 choose - Elige un valor aleatorio de una lista

Check out their documentation in the Help system for detailed information and examples.

- Resetting the Stream

Whilst the ability to repeat a sequence of chosen notes is essential to allow you to replay a riff on the dance floor, it might not be exactly the riff you want. Wouldn’t it be great if we could try a number of different riffs and choose the one we liked best? This is where the real magic starts.

We can manually set the stream with the fn use_random_seed. In Computer Science, a random seed is the starting point from which a new stream of random values can sprout out and blossom. Let’s try it:

use_random_seed 0
3.times do
  play rrand_i(50, 95)
  sleep 0.125
end

Great, we get the first three notes of our random melody above: 84, 83 and 71. However, we can now change the seed to something else. How about this:

use_random_seed 1
3.times do
  play rrand_i(50, 95)
  sleep 0.125
end

Interesting, we get 83, 71 and 61 . You might notice that the first two numbers here are the same as the last two numbers before - this isn’t a coincidence.

Remember that the random stream is just a giant list of ‘pre-rolled’ values. Using a random seed simply jumps us to a point in that list. Another way of thinking about it is to imagine a huge deck of pre-shuffled cards. Using a random seed is cutting the deck at a particular point. The fabulous part of this is that it’s precisely this ability to jump around the random stream which gives us huge power when making music.

Let’s revisit our random melody of 8 notes with this new stream resetting power, but let’s also throw in a live loop so we can experiment live whilst it’s playing:

live_loop :random_riff do    
  use_random_seed 0
  8.times do
    play rrand_i(50, 95), release: 0.1
    sleep 0.125
  end
end

Now, whilst it’s still playing, change the seed value from 0 to something else. Try 100, what about 999. Try your own values, experiment and play around - see which seed generates the riff you like best.

- Bringing it all together

This month’s tutorial has been quite a technical dive into the workings of Sonic Pi’s randomisation functionality. Hopefully it has given you some insight into how it works and how you can start using randomisation in a reliable way to create repeatable patterns within your music. It’s important to stress that you can use repeatable randomisation anywhere you want. For example, you can randomise the amplitude of notes, the timing of the rhythm, the amount of reverb, the current synth, the mix of an FX, etc. etc. In the future we’ll take a close look at some of these applications, but for now let me leave you with a short example.

Type the following into a spare buffer, hit Run, and then start changing the seeds around, hit Run again (whilst it’s still playing) and explore the different sounds, rhythms and melodies you can make. When you find a nice one, remember the seed number so you can get back to it. Finally, when you’ve found a few seeds you like, put on a live coded performance for your friends by simply switching between your favourite seeds to create a full piece.

live_loop :random_riff do
  use_random_seed 10300
  use_synth :prophet
  s = [0.125, 0.25, 0.5].choose
  8.times do
    r = [0.125, 0.25, 1, 2].choose
    n = (scale :e3, :minor).choose
    co = rrand(30, 100)
    play n, release: r, cutoff: co
    sleep s
  end
end
live_loop :drums do
  use_random_seed 2001
  16.times do
    r = rrand(0.5, 10)
    sample :drum_bass_hard, rate: r, amp: rand
    sleep 0.125
  end
end

- Controlando tu sonido

So far during this series we’ve focussed on triggering sounds. We’ve discovered that we can trigger the many synths built into Sonic Pi with play or synth and how to trigger pre-recorded samples with sample. We’ve also looked at how we can wrap these triggered sounds within studio FX such as reverb and distortion using the with_fx command. Combine this with Sonic Pi’s incredibly accurate timing system and you can produce a vast array of sounds, beats and riffs. However, once you’ve carefully selected a particular sound’s options and triggered it, there’s no ability to mess with it whilst it’s playing right? Wrong! Today you’re going to learn something very powerful - how to control running synths.

Un sonido básico

Hagamos un sonido simple. Arranca Sonic Pi y en un buffer libre escribe lo siguiente:

synth :prophet, note: :e1, release: 8, cutoff: 100

Now press the Run button at the top left to hear a lovely rumbling synth sound. Go ahead, press it again a few times to get a feel for it. OK, done? Let’s start controlling it!

Synth Nodes

A little known feature in Sonic Pi is that the fns play, synth and sample, return something called a SynthNode which represents a running sound. You can capture one of these SynthNodes using a standard variable and then control it at a later point in time. For example, let’s change the value of the cutoff: opt after 1 beat:

sn = synth :prophet, note: :e1, release: 8, cutoff: 100
sleep 1
control sn, cutoff: 130

Let’s look at each line in turn:

Firstly we trigger the :prophet synth using the synth fn as normal. However we also capture the result in a variable called sn. We could have called this variable something completely different such as synth_node or jane - the name doesn’t matter. However, it’s important to choose a name that’s meaningful to you for your performances and for people reading your code. I chose sn as it’s a nice short mnemonic for synth node.

On line 2 we have a standard sleep command. This does nothing special - it just asks the computer to wait for 1 beat before moving onto the next line.

Line 3 is where the control fun starts. Here, we use the control fn to tell our running SynthNode to change the cutoff value to 130. If you hit the Run button, you’ll hear the :prophet synth start playing as before, but after 1 beat it will shift to sound a lot brighter.

Modulatable Options

Most of Sonic Pi’s synths and FX opts may be changed after being triggered. However, this isn’t the case for all of them. For example, the envelope opts attack:, decay:, sustain: and release: can only be set when triggering the synth. Figuring out which opts can and can’t be changed is simple - just head to the documentation for a given synth or FX and then scroll down to the individual option documentation and look for the phrases “May be changed whilst playing” or “Can not be changed once set”. For example, the documentation for the :beep synth’s attack: opt makes it clear that it’s not possible to change it:

Default: 0 Debe ser cero o mayor Can not be changed once set Scaled with current BPM value

Cambios múltiples

Whilst a synth is running you’re not limited to changing it only once - you’re free to change it as many times as you like. For example, we can turn our :prophet into a mini arpeggiator with the following:

notes = (scale :e3, :minor_pentatonic)
sn = synth :prophet, note: :e1, release: 8, cutoff: 100
sleep 1
16.times do
  control sn, note: notes.tick
  sleep 0.125
end

In this snippet of code we just added a couple of extra things. First we defined a new variable called notes which contains the notes we’d like to cycle through (an arpeggiator is just a fancy name for something that cycles through a list of notes in order). Secondly we replaced our single call to control with an iteration calling it 16 times. In each call to control we .tick through our ring of notes which will automatically repeat once we get to the end (thanks to the fabulous power of Sonic Pi’s rings). For a bit of variety try replacing .tick with .choose and see if you can hear the difference.

Note that we can change multiple opts simultaneously. Try changing the control line to the following and listen for the difference:

control sn, note: notes.tick, cutoff: rrand(70, 130)

Sliding

When we control a SynthNode, it responds exactly on time and instantly changes the value of the opt to the new one as if you’d pressed a button or flicked a switch requesting the change. This can sound rhythmical and percussive - especially if the opt controls an aspect of the timbre such as cutoff:. However, sometimes you don’t want the change to happen instantaneously. Instead, you might want to smoothly move from the current value to the new one as if you’d moved a slider or dial. Of course, Sonic Pi can also do this too using the _slide: opts.

Each opt that can be modified also has a special corresponding _slide: opt that allows you to specify a slide time. For example, amp: has amp_slide: and cutoff: has cutoff_slide:. These slide opts work slightly differently than all the other opts in that they tell the synth note how to behave next time they are controlled. Let’s take a look:

sn = synth :prophet, note: :e1, release: 8, cutoff: 70, cutoff_slide: 2
sleep 1
control sn, cutoff: 130

Notice how this example is exactly the same as before except with the addition of cutoff_slide:. This is saying that next time this synth has its cutoff: opt controlled, it will take 2 beats to slide from the current value to the new one. Therefore, when we use control you can hear the cutoff slide from 70 to 130. It creates an interesting dynamic feel to the sound. Now, try changing the cutoff_slide: time to a shorter value such as 0.5 or a longer value such as 4 to see how it changes the sound. Remember, you can slide any of the modifiable opts in exactly this way and each _slide: value can be totally different so you can have the cutoff sliding slowly, the amp sliding fast and the pan sliding somewhere in between if that’s what you’re looking to create…

Bringing it all together

Let’s look at a short example which demonstrates the power of controlling synths after they’ve been triggered. Notice that you can also slide FX just like synths although with a slightly different syntax. Check out section 7.2 of the built-in tutorial for more information on controlling FX.

Copy the code into a spare buffer and take a listen. Don’t stop there though - play around with the code. Change the slide times, change the notes, the synth, the FX and the sleep times and see if you can turn it into something completely different!

live_loop :moon_rise do
  with_fx :echo, mix: 0, mix_slide: 8 do |fx|
    control fx, mix: 1
    notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle
    sn = synth :prophet , sustain: 8, note: :e1, cutoff: 70, cutoff_slide: 8
    control sn, cutoff: 130
    sleep 2
    32.times do
      control sn, note: notes.tick, pan: rrand(-1, 1)
      sleep 0.125
    end
  end
end

- Tracking the Beat

Last month in this series we took a deep technical dive into the randomisation system underpinning Sonic Pi. We explored how we can use it to deterministically add new levels of dynamic control over our code. This month we’re going to continue our technical dive and turn our attention to Sonic Pi’s unique tick system. By the end of this article you’ll be ticking your way through rhythms and riffs on your way to being a live coding DJ.

- Beat Counting

When making music we often want to do a different thing depending on which beat it is. Sonic Pi has a special beat counting system called tick to give you precise control over when a beat actually occurs and even supports multiple beats with their own tempos.

Let’s have a play - to advance the beat we just need to call tick. Open up a fresh buffer, type in the following and hit Run:

puts tick #=> 0

This will return the current beat: 0. Notice that even if you press the Run button a few times it will always return 0. This is because each run starts a fresh beat counting from 0. However, whilst the run is still active, we can advance the beat as many times as we want:

puts tick #=> 0
puts tick #=> 1
puts tick #=> 2

Whenever you see the symbol #=> at the end of a line of code it means that that line will log the text on the right-hand-side. For example, puts foo #=> 0 means the code puts foo prints 0 to the log at that point in the program.

- Checking the Beat

We’ve seen that tick does two things. It increments (adds one) and returns the current beat. Sometimes we just want to look at the current beat without having to increment it which we can do via look:

puts tick #=> 0
puts tick #=> 1
puts look #=> 1
puts look #=> 1

En este código incrementamos el beat dos veces haciendo tick y entonces llamamos look dos veces. Veremos los siguientes valores en el log: 0, 1, 1, 1. Los dos primeros ticks han devuelto 0, después 1 como esperábamos, finalmente los dos looks simplemente devolvieron el ultimo valor del beat dos veces, lo cual ha sido 1.

- Anillos

So now we can advance the beat with tick and check the beat with look. What next? We need something to tick over. Sonic Pi uses rings for representing riffs, melodies and rhythms and the tick system has been specifically designed to work very closely with them. In fact, rings have their own dot version of tick which does two things. Firstly, it acts like a regular tick and increments the beat. Secondly it looks up the ring value using the beat as the index. Let’s take a look:

puts (ring :a, :b, :c).tick #=> :a

.tick is a special dot version of tick which will return the first value of the ring :a. We can grab each of the values in the ring by calling .tick multiple times:

puts (ring :a, :b, :c).tick #=> :a
puts (ring :a, :b, :c).tick #=> :b
puts (ring :a, :b, :c).tick #=> :c
puts (ring :a, :b, :c).tick #=> :a
puts look                   #=> 3

Mira el log y allí verás :a, :b, :c y de nuevo :a. Fíjate que look devuelve 3. Las llamadas a .tick funcionan como si fueran llamadas normales a tick- incrementan el beat local.

- Un Arpegiador de Live Loop

El poder read viene cuando mezclas tick con rings y live_loops. Cuando están combinados tenemos todas las herramientas necesarias para construir y también entender un simple arpegiador. Solo necesitamos cuatro cosas:

Un ring que contiene las notas que queremos repetir. Una forma de incrementar y obtener el beat. La capacidad de tocar una nota en función del beat actual. Una bucle para mantener al arpegiador repitiéndose.

Estos conceptos pueden ser comprobados en el siguiente código:

notes = (ring 57, 62, 55, 59, 64)
live_loop :arp do
  use_synth :dpulse
  play notes.tick, release: 0.2
  sleep 0.125
end

Veamos cada una de estas líneas. Primero definimos nuestro ring de notas que reproduciremos continuamente. Entonces creamos un live_loop llamado :arp que hace loop a nuestro alrededor. Cada vuelta en el live_loop ponemos nuestro synth en :dpulse y entonces tocamos la siguiente nota usando.tick. Recuerda que esto incrementará nuestro contador de beats y usará el último valor del beat como el índice para nuestro ring de notas. Finalmente, esperamos un octavo de beat antes de volver a empezar el loop.

- Múltiples Ritmos Simultáneos

Una cosa que hay que saber es que los ticks son locales al live_loop. Esto quiere decir que cada live_loop tiene su propio contador de beats independiente. Esto es mucho más potente que tener un metrónomo y ritmo global . Veamos como funciona esto:

notes = (ring 57, 62, 55, 59, 64)
with_fx :reverb do
  live_loop :arp do
    use_synth :dpulse
    play notes.tick + 12, release: 0.1
    sleep 0.125
  end
end
live_loop :arp2 do
  use_synth :dsaw
  play notes.tick - 12, release: 0.2
  sleep 0.75
end

- Ritmos que chocan

Una causa de confusiones habituales con el sistema de tick de Sonic Pi es cuando la gente quiere hacer tick en varios rings dentro del mismo live_loop:

use_bpm 300
use_synth :blade
live_loop :foo do
  play (ring :e1, :e2, :e3).tick
  play (scale :e3, :minor_pentatonic).tick
  sleep 1
end

Even though each live_loop has its own independent beat counter, we’re calling .tick twice within the same live_loop. This means that the beat will be incremented twice every time round. This can produce some interesting polyrhythms but is often not what you want. There are two solutions to this problem. One option is to manually call tick at the start of the live_loop and then use .look to look up the current beat in each live_loop. The second solution is to pass a unique name to each call to .tick such as .tick(:foo). Sonic Pi will then create and track a separate beat counter for each named tick you use. That way you can work with as many beats as you need! See the section on named ticks in 9.4 of the built-in tutorial for more information.

- Bringing it all together

Juntemos todo este conocimiento de los ticks, rings y live_loops en un ejemplo final. Como de costumbre, no consideres esto como una pieza acabada. Empieza cambiando cosas y jugando con ellos a ver en que puedes transformarlo. Nos vemos…

use_bpm 240
notes = (scale :e3, :minor_pentatonic).shuffle
live_loop :foo do
  use_synth :blade
  with_fx :reverb, reps: 8, room: 1 do
    tick
    co = (line 70, 130, steps: 32).tick(:cutoff)
    play (octs :e3, 3).look, cutoff: co, amp: 2
    play notes.look, amp: 4
    sleep 1
  end
end
live_loop :bar do
  tick
  sample :bd_ada if (spread 1, 4).look
  use_synth :tb303
  co = (line 70, 130, steps: 16).look
  r = (line 0.1, 0.5, steps: 64).mirror.look
  play notes.look, release: r, cutoff: co
  sleep 0.5
end

- Cortando Samples

When people discover Sonic Pi, one of the first things they learn is how simple it is to play pre-recorded sounds using the sample function. For example, you can play an industrial drum loop, hear the sound of a choir or even listen to a vinyl scratch all via a single line of code. However, many people don’t realise that you can actually vary the speed that the sample is played back at for some powerful effects and a whole new level of control over your recorded sounds. So, fire up a copy of Sonic Pi and let’s get started stretching some samples!

- Sampleos

To modify the playback rate of a sample we need to use the rate: opt:

sample :guit_em9, rate: 0.5

If we specify a rate: of 1 then the sample is played back at the normal rate. If we want to play it back at half speed we simply use a rate: of 0.5:

sample :guit_em9, rate: 0.5

Elegir (choose)

- Acelerando las muestras

In addition to making the sound longer and lower using a small rate, we can use higher rates to make the sound shorter and higher. Let’s play with a drum loop this time. First, take a listen to how it sounds at the default rate of 1:

sample :loop_amen, rate: 1

Now, let’s speed it up a little:

sample :loop_amen, rate: 1.5

Ha! We just moved musical genres from old-skool techno to jungle. Notice how the pitch of each drum hit is higher as well as how the whole rhythm speeds up. Now, try even higher rates and see how high and short you can make the drum loop. For example, if you use a rate of 100, the drum loop turns into a click!

- Reverse Gear

Now, I’m sure many of you are thinking the same thing right now… “what if you use a negative number for the rate?”. Great question! Let’s think about this for a moment. If our rate: opt signifies the speed with which the sample is played back, 1 being normal speed, 2 being double speed, 0.5 being half speed, -1 must mean backwards! Let’s try it on a snare. First, play it back at the normal rate:

sample :elec_filt_snare, rate: 1

Ahora, ejecutado al revés:

sample :elec_filt_snare, rate: -1

Of course, you can play it backwards twice as fast with a rate of -2 or backwards at half speed with a rate of -0.5. Now, play around with different negative rates and have fun. It’s particularly amusing with the :misc_burp sample!

Sample, Rate and Pitch [Sidebar]

One of the effects of rate modification on samples is that faster rates result in the sample sounding higher in pitch and slower rates result in the sample sounding lower in pitch. Another place you may have heard this effect in every day life is when you’re cycling or driving past a beeping pedestrian crossing - as you’re heading towards the sound source the pitch is higher than when you’re moving away from the sound - the so-called Doppler effect. Why is this?

Let’s consider a simple beep which is represented by a sine wave. If we use an oscilloscope to plot a beep, we’ll see something like Figure A. If we plot a beep an octave higher, we’ll see Figure B and an octave lower will look like Figure C. Notice that the waves of higher notes are more compact and the waves of lower notes are more spread out.

A sample of a beep is nothing more than a lot of numbers (x, y, coordinates) which when plotted onto a graph will re-draw the original curves. See figure D where each circle represents a coordinate. To turn the coordinates back into audio, the computer works through each x value and sends the corresponding y value to the speakers. The trick here is that the rate at which the computer works through the x numbers does not have to be the same as the rate with which they were recorded. In other words, the space (representing an amount of time) between each circle can be stretched or compressed. So, if the computer walks through the x values faster than the original rate, it will have the effect of squashing the circles closer together which will result in a higher sounding beep. It will also make the beep shorter as we will work through all the circles faster. This is shown in Figure E.

Finally, one last thing to know is that a mathematician called Fourier proved that any sound is actually lots and lots of sine waves all combined together. Therefore, when we compress and stretch any recorded sound we’re actually stretching and compressing many sine waves all at the same time in exactly this manner.

- Pitch Bending

As we’ve seen, using a faster rate will make the sound higher in pitch and a slower rate will make the sound lower in pitch. A very simple and useful trick is to know that doubling the rate actually results in the pitch being an octave higher and inversely halving the rate results in the pitch being an octave lower. This means that for melodic samples, playing it alongside itself at double/half rates actually sounds rather nice:

sample :bass_trance_c, rate: 1
sample :bass_trance_c, rate: 2
sample :bass_trance_c, rate: 0.5

However, what if we just want to alter the rate such that the pitch goes up one semitone (one note up on a piano)? Sonic Pi makes this very easy via the rpitch: opt:

sample :bass_trance_c
sample :bass_trance_c, rpitch: 3
sample :bass_trance_c, rpitch: 7

If you take a look at the log on the right, you’ll notice that an rpitch: of 3 actually corresponds to a rate of 1.1892 and a rpitch: of 7 corresponds to a rate of 1.4983. Finally, we can even combine rate: and rpitch: opts:

sample :ambi_choir, rate: 0.25, rpitch: 3
sleep 3
sample :ambi_choir, rate: 0.25, rpitch: 5
sleep 2
sample :ambi_choir, rate: 0.25, rpitch: 6
sleep 1
sample :ambi_choir, rate: 0.25, rpitch: 1

- Bringing it all together

Let’s take a look at a simple piece which combines these ideas. Copy it into an empty Sonic Pi buffer, hit play, listen to it for a while and then use it as a starting point for your own piece. See how much fun it is to manipulate the playback rate of samples. As an added exercise try recording your own sounds and play around with the rate to see what crazy sounds you can make.

sample :guit_em9

- Code a Probabilistic Sequencer

rand

- Portabilidad

Dado (dice)

Dado (dice)

Dado (dice)

- Semillas aleatorias

Escuchemos como suena:

rand

rand

- Changing Probabilities

one_in

one_in

rand

- Combining Probabilities

Things get really exciting when you combine multiple samples being triggered with different probabilities. For example:

one_in

Again, run the code above and then start changing the probabilities to modify the rhythm. Also, try changing the samples to create an entirely new feel. For example try changing :drum_cymbal_closed to :bass_hit_c for extra bass!

- Repeatable Rhythms

rand

one_in

One thing I tend to do with this kind of structure is to remember which seeds sound good and make a note of them. That way I can easily re-create my rhythms in future practice sessions or performances.

- Bringing it all together

rand

Elegir (choose)

- Amplitud

This month we’re going to take a deep dive into one of Sonic Pi’s most powerful and flexible audio FX - the :slicer. By the end of this article you will have learned how to manipulate the overall volume of parts of our live coded sound in powerful new ways. This will allow you to create new rhythmic and timbral structures and broaden your sonic possibilities.

Slice that Amp

:prophet

synth :prophet, note: :e1, release: 8, cutoff: 70
synth :prophet, note: :e1 + 4, release: 8, cutoff: 80

Now, let’s pipe it through the :slicer FX:


with_fx :slicer do
  synth :prophet, note: :e1, release: 8, cutoff: 70
  synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
end

Hear how the slicer acts like it’s muting and unmuting the audio with a regular beat. Also, notice how the :slicer affects all the audio generated between the do/end blocks. You can control the speed at which it turns the audio on and off with the phase: opt which is short for phase duration. Its default value is 0.25 which means 4 times a second at the default BPM of 60. Let’s make it faster:

with_fx :slicer, phase: 0.125 do
  synth :prophet, note: :e1, release: 8, cutoff: 70
  synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
end

:dsaw

Duración

Phase duration is the length of time for one on/off cycle. Therefore smaller values will make the FX switch on and off much faster than larger values. Good values to start playing with are 0.125, 0.25, 0.5 and 1.

Control Waves

By default, the :slicer FX uses a square wave to manipulate the amplitude through time. This is why we hear the amplitude on for a period, then immediately off for a period, then back on again. It turns out that the square wave is just one of 4 different control waves that are supported by :slicer. The others are saw, triangle and (co)sine. Take a look at the diagram below to see what these look like. We can also hear what they sound like. For example, the following code uses (co)sine as the control wave. Hear how the sound doesn’t turn on and off abruptly but instead smoothly fades in and out:

with_fx :slicer, phase: 0.5, wave: 3 do
  synth :dsaw, note: :e3, release: 8, cutoff: 120
  synth :dsaw, note: :e2, release: 8, cutoff: 100
end

Have a play with the different wave forms by changing the wave: opt to 0 for saw, 1 for square, 2 for triangle and 3 for sine. See how different waves sound with different phase: opts too.

Each of these waves can be inverted with the invert_wave: opt which flips it on the y axis. For example, in a single phase the saw wave typically starts high, and slowly goes down before jumping back to the top. With invert_wave: 1 it will start low and slowly go up before jumping back down again. Additionally, the control wave can be started at different points with the phase_offset: opt which should be a value between 0 and 1. By playing around with phase:, wave:, invert_wave: and phase_offset opts you can dramatically change how the amplitude is modified through time.

Duración

Setting your levels

By default, :slicer switches between amplitude values 1 (fully loud) and 0 (silent). This can be changed with the amp_min: and amp_max: opts. You can use this alongside the sine wave setting to create a simple tremolo effect:

with_fx :slicer, amp_min: 0.25, amp_max: 0.75, wave: 3, phase: 0.25 do
  synth :saw, release: 8
end

This is just like grabbing the volume knob on your hi-fi and moving it up and down just a little so the sound ‘wobbles’ in and out.

Probabilities

Elegir (choose)

with_fx :slicer, phase: 0.125, probability: 0.6  do
  synth :tb303, note: :e1, cutoff_attack: 8, release: 8
  synth :tb303, note: :e2, cutoff_attack: 4, release: 8
  synth :tb303, note: :e3, cutoff_attack: 2, release: 8
end

Hear how we now have an interesting rhythm of pulses. Try changing the probability: opt to a different value between 0 and 1. Values closer to 0 will have more space between each sound due to the likelihood of the sound being triggered being much lower.

rand

Finally, you can change the ‘resting’ position of the control wave when the probability test fails from 0 to any other position with the prob_pos: opt:

with_fx :slicer, phase: 0.125, probability: 0.6, prob_pos: 1  do
  synth :tb303, note: :e1, cutoff_attack: 8, release: 8
  synth :tb303, note: :e2, cutoff_attack: 4, release: 8
  synth :tb303, note: :e3, cutoff_attack: 2, release: 8
end

Ritmos que chocan

One really fun thing to do is to use :slicer to chop a drum beat in and out:

with_fx :slicer, phase: 0.125 do
  sample :loop_mika
end

This allows us to take any sample and create new rhythmical possibilites which is a lot of fun. However, one thing to be careful about is to make sure that the tempo of the sample matches the current BPM in Sonic Pi otherwise the slicing will sound totally off. For example, try swapping :loop_mika with the loop_amen sample to hear how bad this can sound when the tempos don’t align.

¡Cambiandolo al vuelo!

As we have already seen, changing the default BPM with use_bpm will make all the sleep times and synth envelope durations grow or shrink to match the beat. The :slicer FX honours this too, as the phase: opt is actually measured in beats not seconds. We can therefore fix the issue with loop_amen above by changing the BPM to match the sample:

sample :loop_amen

Bringing it all together

Let’s apply all these ideas into a final example that only uses the :slicer FX to create an interesting combination. Go ahead, start changing it and make it into your own piece!

sample :guit_em9, rate: 0.5

- Programación en directo (Live Coding)

Last month we took a look at five important techniques for mastering live coding - in other words, we explored how we could use Sonic Pi to approach code in the same way we would approach a musical instrument. One of the important concepts that we discussed was practice. This month we’re going to take a deeper dive into understanding why live coding practice is important and how you might start.

Practice regularly

The most important piece of advice is to make sure you practice regularly. As a rule I typically practice for 1-2 hours a day, but 20 mins is just fine when you’re starting out. Little but often is what you’re aiming for - so if you can only manage 10 minutes, that’s a great start.

Practice tip #1 - start to develop a practice routine. Find a nice time in the day that works for you and try and practice at that time as many days of the week as you can. Before long you’ll be looking forward to your regular session.

Learn to Touch Type

If you watch a professional musician performing on stage you’ll likely notice a few things. Firstly, when they play they don’t stare at their instrument. Their fingers, arms and bodies know which keys to press, strings to pluck or drums to hit without them having to think about it too much. This is known as “muscle memory” and although it might sound like something only professionals can do - it’s just the same as when you first learned to walk or ride a bike - practicing through repetition. Live coders use muscle memory to free their minds from having to think about where to move their fingers so they can focus on the music. This is called touch-typing - typing without having to look at the keyboard.

Practice tip #2 - learn how to touch type. There are many apps, websites and even games which can help you achieve this. Find one you like the look of and stick at it until you can code without looking down.

Code whilst standing

The body of a musician is conditioned for playing their instrument. For example, a trumpet player needs to be able to blow hard, a guitar player needs to be able to grip the fretboard with strength and a drummer needs to be able to continually hit the drums for long periods of time. So, what’s physical about live coding? Just like DJs, live coders typically perform whilst standing up and some even dance whilst they code! If you practice live coding whilst sitting at a desk and then have to get up and stand at a gig, you’ll likely find the difference very difficult and frustrating.

Practice tip #3 - stand whilst you practice. The easiest way to do this is to use a standing height desk. However, if like me you don’t have one at home, there’s a couple of low-fi options. The approach I take is to use an ironing board which happens to work rather well. Another is to stack some boxes or large books on a normal desk and place your keyboard on top of that. Also, make sure you stretch before you start practicing and try and dance a little during the session. Remember, nobody is watching you, so have fun and you’ll feel much more natural on stage.

Practice setting up

Most instruments require some assembly and tuning before they can be played. Unless you’re a rockstar with a bus full of roadies, you’ll have to set up your own instrument before your gig. This is often a stressful time and it is easy for problems to occur. One way to help with this is to incorporate the setup process into your practice sessions.

Practice tip #4 - treat setting up as an important part of your practice. For example, have a box or bag that you can keep your Raspberry Pi and keyboard in etc. Before each practice session, take out all the parts, connect everything, and work through the boot process until you have Sonic Pi running and can make sounds. Once you’ve finished practicing, take the time to carefully pack everything away afterwards. This may take some time at first, but before long you’ll be able to setup and pack everything away incredibly quickly without having to think about it.

Experiment Musically

Once you’ve set up and are ready to start making music, you might find yourself struggling to know where to start. One problem many people face is that they might have a good idea of the kinds of sounds they want to make, but are frustrated that they can’t produce them. Some people don’t even know what kind of sounds they want to make! The first thing to do is not to worry - this is very common and happens to every musician - even if they’ve been practicing for a long time. It is much more important to be making sounds you don’t like than not making any sounds at all.

Practice tip #5 - spend time making sounds and music you don’t like. Try to make time to explore new sounds and ideas. Don’t worry that it might sound terrible if it’s not the style you’re looking for. When you’re experimenting like this you increase the chance of stumbling over a sound or combination of sounds which you love! Even if 99% of the sounds you make are bad, that 1% might be the riff or intro to your new track. Forget the things you don’t like and remember the parts you do. This is even easier when you’re making music with code - just hit save!

Hear the Code

rand

Practice tip #6 - write some code into Sonic Pi but don’t hit the Run button. Instead, try to imagine what sound it is going to produce. Then, hit Run, listen, and think about what you got right and what you didn’t. Keep repeating this until it become a natural part of your coding process. When I practice I normally have a good idea of what the code will sound like. However, I still am occasionally surprised, and then I’ll stop and spend some time thinking about why I was wrong. Each time this happens, I learn new tricks which allow me to express myself in new ways.

Remove all distractions

A common problem when practicing is to become distracted with other things. Practicing is hard and requires real discipline regardless of the kind of music you’re making - from jazz to classical to EDM. If you’re struggling to get started or make progress, it’s often too easy to hop on social media, or look something up on the internet etc. If you’ve set yourself a target of 20 minutes of practice, it’s important to try and spend all that time being as productive as possible.

Practice tip #7 - before you start practicing remove as many distractions as possible. For example, disconnect from the internet, put your phone in another room and try to practice in a quiet place where you’re unlikely to be disturbed. Try to focus on coding music and you can return to your distractions when you’ve finished.

Keep a practice diary

When you are practicing, you’ll often find your mind is full of new exciting ideas - new musical directions, new sounds to try out, new functions to write, etc. These ideas are often so interesting that you might stop what you’re doing and start working on the idea. This is another form of distraction!

Practice tip #8 - keep a practice diary by your keyboard. When you get an exciting new idea, temporarily pause your practice session, quickly jot the idea down, then forget about it and carry on practicing. You can then spend some quality time thinking about and working on your ideas after you’ve finished practicing.

Bringing it all together

Try to establish a practice routine which incorporates as many of these ideas as possible. Try to keep the sessions as fun as possible but be aware that some practice sessions will be hard and feel a little like work. However, it will all be worth it once you’ve created your first piece or given your first performance. Remember, practice is the key to success!


- Additive Synthesis

This is the first of a short series of articles on how to use Sonic Pi for sound design. We’ll be take a quick tour of a number of different techniques available for you to craft your own unique sound. The first technique we’ll look at is called additive synthesis. This may sound complicated - but if we expand each word slightly the meaning pops right out. Firstly, additive means a combination of things and secondly synthesis means to create sound. Additive synthesis therefore means nothing more complicated than combining existing sounds to create new ones. This synthesis technique dates back a very long time - for example, pipe organs in the middle ages had lots of slightly different sounding pipes which you could enable or disable with stops. Pulling out the stop for a given pipe ‘added it to the mix’ making the sound richer and more complex. Now, let’s see how we can pull out all the stops with Sonic Pi.

- Simple Combinations

Let’s start with the most basic sound there is - the humble pure-toned sine wave:

synth :sine, note: :d3

Now, let’s see how this sounds combined with a square wave:

synth :sine, note: :d3
synth :square, note: :d3

Notice how the two sounds combine to form a new, richer sound. Of course, we don’t have to stop there, we can add as many sounds as we need. However, we need to be careful with how many sounds we add together. Just like when we mix paints to create new colours, adding too many colours will result in a messy brown, similarly - adding too many sounds together will result in a muddy sound.

- Blending

Let’s add something to make it sound a little brighter. We could use a triangle wave at an octave higher (for that high bright sound) yet only play it at amp 0.4 so it adds something extra to the sound rather than taking it over:

synth :sine, note: :d3
synth :square, note: :d3
synth :tri, note: :d4, amp: 0.4

Now, try creating your own sounds by combining 2 or more synths at different octaves and amplitudes. Also, note that you can play around with each synth’s opts to modify each source sound before it is mixed in for even more combinations of sounds.

- Detuning

So far, when combining our different synths we’ve used either the same pitch or switched octave. How might it sound if we didn’t stick to octaves but instead chose a slightly higher or lower note? Let’s try it:

detune = 0.7
synth :square, note: :e3
synth :square, note: :e3 + detune

If we detune our square waves by 0.7 notes we hear something that perhaps doesn’t sound in tune or correct - a ‘bad’ note. However, as we move closer to 0 it will sound less and less out of tune as the pitches of the two waves get closer and more similar. Try it for yourself! Change the detune: opt value from 0.7 to 0.5 and listen to the new sound. Try 0.2, 0.1, 0.05, 0. Each time you change the value, take a listen and see if you can hear how the sound is changing. Notice that low detune values such as 0.1 produce a really nice ‘thick’ sound, with both slightly different pitches interacting with each other in interesting, often surprising, ways.

:dsaw

- Amplitud

Another way we can finely craft our sound is to use a different envelope and options for each synth trigger. For example this will allow you to make some aspects of the sound percussive and other aspects ring out for a period of time.

detune = 0.1
synth :square, note: :e1, release: 2
synth :square, note: :e1 + detune, amp: 2, release: 2
synth :gnoise, release: 2, amp: 1, cutoff: 60
synth :gnoise, release: 0.5, amp: 1, cutoff: 100
synth :noise, release: 0.2, amp: 1, cutoff: 90

In the example above I have mixed in a noisy percussive element to the sound along with some more persistent background rumbling. This was achieved firstly by using two noise synths with middling cutoff values (90 and 100) using short release times along with a noise with a longer release time but with a low cutoff value (which makes the noise less crisp and more rumbly.)

- Bringing it all together

Let’s combine all these techniques to see if we can use additive synthesis to re-create a basic bell sound. I’ve broken this example into four sections. Firstly we have the ‘hit’ section which is the initial onset part of the bell sound - so uses a short envelope (e.g. a release: of around 0.1). Next we have the long ringing section in which I’m using the pure sound of the sine wave. Notice that I’m often increasing the note by roughly 12 and 24 which are the number of notes in one and two octaves. I have also thrown in a couple of low sine waves to give the sound some bass and depth. Finally, I used define to wrap my code in a function which I can then use to play a melody. Try playing your own melody and also messing around with the contents of the :bell function until you create your own crazy sound to play with!

define :bell do |n| # Triangle waves for the ‘hit’ synth :tri, note: n - 12, release: 0.1 synth :tri, note: n + 0.1, release: 0.1 synth :tri, note: n - 0.1, release: 0.1 synth :tri, note: n, release: 0.2

# Sine waves for the ‘ringing’ synth :sine, note: n + 24, release: 2 synth :sine, note: n + 24.1, release: 2 synth :sine, note: n + 24.2, release: 0.5 synth :sine, note: n + 11.8, release: 2 synth :sine, note: n, release: 2

# Low sine waves for the bass synth :sine, note: n - 11.8, release: 2 synth :sine, note: n - 12, release: 2 end

- Play a melody with our new bell!

bell :e3 sleep 1 bell :c2 sleep 1 bell :d3 sleep 1 bell :g2


- Subtractive Synthesis

This is the second in a series of articles on how to use Sonic Pi for sound design. Last month we looked at additive synthesis which we discovered was the simple act of playing multiple sounds at the same time to make a new combined sound. For example we could combine different sounding synths or even the same synth at different pitches to build a new complex sound from simple ingredients. This month we’ll look at a new technique commonly called subtractive synthesis which is simply the act of taking an existing complex sound and removing parts of it to create something new. This is a technique which is commonly associated with the sound of analog synthesisers of the 1960s and 1970s but also with the recent renaissance of modular analog synths through popular standards such as Eurorack.

Despite this sounding like a particularly complicated and advanced technique, Sonic Pi makes it surprisingly simple and easy - so let’s dive right in.

- Complex Source Signal

For a sound to work well with subtractive synthesis, it typically needs to be fairly rich and interesting. This doesn’t mean we need something hugely complex - in fact, just a standard :square or :saw wave will do:

synth :saw, note: :e2, release: 4

Note que este sonido ya es más interesante y contiene muchas frecuencias diferentes :e2(el segundo Mi del piano) que se añade para crear el timbre. Si esto no tiene mucho sentido para usted, intente compararlo con :beep:

synth :beep, note: :e2, release: 4

As the :beep synth is just a sine wave, you’ll hear a much purer tone and only at :e2 and none of the high crispy/buzzy sounds which you heard in the :saw. It’s this buzziness and variation from a pure sine wave that we can play with when we use subtractive synthesis.

- Filtros

Once we have our raw source signal, the next step is to pass it through a filter of some kind which will modify the sound by removing or reducing parts of it. One of the most common filters used for subtractive synthesis is something called a low pass filter. This will allow all the low parts of the sound through but will reduce or remove the higher parts. Sonic Pi has a powerful yet simple to use FX system that includes a low pass filter, called :lpf. Let’s play with it:

with_fx :lpf, cutoff: 100 do 
  synth :saw, note: :e2, release: 4 
end

If you listen carefully you’ll hear how some of that buzziness and crispiness has been removed. In fact, all the frequencies in the sound above note 100 have been reduced or removed and only the ones below are still present in the sound. Try changing that cutoff: point to lower notes, say 70 and then 50 and compare the sounds.

Of course, the :lpf isn’t the only filter you can use to manipulate the source signal. Another important FX is the high pass filter referred to as :hpf in Sonic Pi. This does the opposite to :lpf in that it lets the high parts of the sound through and cuts off the low parts.

with_fx :hpf, cutoff: 90 do
  synth :saw, note: :e2, release: 4
end

Notice how this sounds much more buzzy and raspy now that all the low frequency sounds have been removed. Play around with the cutoff value - notice how lower values let more of the original bass parts of the source signal through and higher values sound increasingly tinny and quiet.

- [Low Pass Filter] - breakout box

:prophet

- Modulación del filtro

So far we’ve just produced fairly static sounds. In other words, the sound doesn’t change in any way for the entirety of its duration. Often you might want some movement in the sound to give the timbre some life. One way to achieve this is via filter modulation - changing the filter’s options through time. Luckily Sonic Pi gives you powerful tools to manipulate an FX’s opts through time. For example, you can set a slide time to each modulatable opt to specify how long it should take for the current value to linearly slide to the target value:

with_fx :lpf, cutoff: 50 do |fx|
  control fx, cutoff_slide: 3, cutoff: 130
  synth :prophet, note: :e2, sustain: 3.5
end

Let’s take a quick look at what’s going on here. Firstly we start an :lpf FX block as normal with an initial cutoff: of a very low 20. However, the first line also finishes with the strange |fx| at the end. This is an optional part of the with_fx syntax which allows you to directly name and control the running FX synth. Line 2 does exactly this and controls the FX to set the cutoff_slide: opt to 4 and the new target cutoff: to be 130. The FX will now start sliding the cutoff: opt’s value from 50 to 130 over a period of 3 beats. Finally we also trigger a source signal synth so we can hear the effect of the modulated low pass filter.

- Bringing it all together

This is just a very basic taster of what’s possible when you use filters to modify and change a source sound. Try playing with Sonic Pi’s many built-in FX to see what crazy sounds you can design. If your sound feels too static, remember you can start modulating the options to create some movement.

Terminemos diseñando una función que ejecutará un nuevo sonido creado con síntesis sustractiva. Intente descubrir qué es lo que sucede - y para aquellos usuarios avanzados de Sonic Pi- vean si pueden descubrir por qué empaqueté todo en la llamada a at (por favor envíen sus respuestas a @samaaron en Twiter).

Rango aleatorio (rrand)

- Conocimiento Esencial

Esta sección cubre algo muy útil - de hecho esencial - Conocimiento para sacar el mayor partido a tu experiencia con Sonic Pi.

Cubriremos como sacar provecho de muchos atajos disponibles para tí, como compartir tu trabajo y algunos trucos de ejecución con Sonic Pi.


- Usando atajos

Sonic Pi es tanto un instrumento como un ambiente de código. Los atajos te hacen tocar Sonic Pi de una manera mucho más eficiente y natural. Especialmente si tocas en frente de una audiencia en vivo.

Mucho de Sonic Pi puede ser controlado a través del teclado. Mientras te familiarizas trabajando con Sonic Pi, probablemente usarás más y más atajos. personalmente soy del tipo toca-teclea (lo que recomiendo aprender) y me frustra el tener que ir al ratón, ya que me ralentiza. Por ello es que utilizo estos atajos regularmente.

Por tanto, si te aprendes los atajos, utilizarás tu teclado de manera eficiente y codificarás como un profesional en poco tiempo.

Sin embargo no intentes aprender todo al mismo tiempo, sólo intenta recordar los que más utilizas y continua añadiendo otros a tú práctica.

Consistencia a través de las plataformas

Imagina que estás aprendiendo el clarinete. Esperarás que todos los clarinetes de cada constructor tenga controles y digitalizaciones similares. Si no fuese así, sería complicado cambiar de clarinetes y tendrías que usar sólo uno.

Desafortunadamente los tres principales sistemas operativos (Linux, Mac OS X y Windows) vienen con acciones como cortar y pegar determinadas. Sonic Pi intentará honrar estos estándares. Sin embargo priorizaremos consistencia a través de las plataformas dentro de Sonic Pi. Esto significa que te sentirás cómodo y en casa ya sea que toques con la Raspberry Pi, Mac o PC.

Control y Meta

Parte de la noción de consistencia es el nombramiento de los atajos. En Sonic Pi usamos los nombre Control y Meta para referirnos a las dos principales combinaciones de teclas. En todas las plataformas Control es igual. Sin embargo, en Linux y Windows, Meta es la tecla Alt, mientras que en Mac es la tecla Command. Por consistencia, utilizaremos el término Meta - sólo recuerda mapear la tecla apropiada a tu OS.

Abreviaciones

Para mantener las cosas simples y legibles, utilizaremos la abreviación C- para Control más otra tecla y M- por Meta más otra tecla. Por ejemplo, si un atajo te requiere que mantengas apretadas ambas Meta y r, escribiremos elso, así M-r. El - significa que es al mismo tiempo.

Los siguientes son los atajos que encuentro más útiles.

Para y comenzar

En vez de comenzar tu código conel ratón, puedes simplemente presionar M-r. Similarmente puedes pararlo con M-s.

Sin los atajos de navegación estaría perdido. Así que recomiendo que los aprendas. Estos atajos funcional fenomenalmente cuando hayas aprendido a tocar y teclear, ya que usan letras estándar, en vez de requerir que vayas al ratón o las flechas del teclado.

Puedes moverte al inicio de una línea con C-a, al final de la línea con C-e, una línea arriba con C-p, abajo con C-n, un carácter adelante con C-f, y atrás un carácter con C-b. puedes borrar todos los caracteres desde el cursor hasta el final de la línea con C-k.

Código legibles

Para auto-alinear el código, simplemete presiona M-m.

Sistema de ayuda

Para aparecer el sistema de ayuda, presiona M-i. Sin embargo, un atajo mucho más útil es C-i que buscará la palabra debajo del cursor y mostrará los documentos si encuentra algo. ayuda instantánea.

Para una lista completa, mira la sección 10.2 Tabla de Atajos.


- Tabla de Atajos

Este es un resumen de los atajos principales dentro de Sonic Pi. Te remito a la sección 10.1 para motivación.

Convenciones

En esta lista, usaremos la siguiente convención (donde Meta es uno de los Alt en Windows/Linux o Cmd en Mac):

C-a mantén presionado Control y presiona a al mismo tiempo, después suelta. M-r mantén presionado Meta y presiona r al mismo tiempo, después suelta. S-M-z mantén presionado Shift y presiona la tecla Meta, después la tecla z al mismo tiempo, después suelta. C-M-f mantén presionado Control, después presiona Meta, finalmente la tecla f, después suelta.

Manipulación de la aplicación principal

M-r - ejecuta el código M-s - para el código M-i - muestra el sistema de Ayuda M-p - muestra las Preferencias M-{ - Va al buffer de la izquierda M-} - Va al buffer de la derecha M-+ - Incrementa el tamaño del texto del buffer actual M-- - Decrementa el tamaño del texto del buffer actual

Seleccionar/Copiar/Pegar

M-a - Selecciona todo M-c - Copia lo seleccionado al buffer de pegado M-] - Copia lo seleccionado al buffer de pegado M-x - Corta lo seleccionado al buffer de pegado C-] - Corta lo seleccionado al buffer de pegado C-k - Corta hasta el final de la línea M-v - Pega del buffer de pegado al editor C-y - Pega del buffer de pegado al editor C-SPACE - Establece marca. La navegación manipulará ahora la región ressaltada. Usa C-g para escapar

Manipulación de Texto

M-m - Alinea todo el texto Tab - Alinea la línea/selección actual (o lista completa) C-l - Centra el editor M-/ - Comenta la línea actual C-t - Transpone/cambia caracteres M-u - Convierte la siguiente palabra (o selección) a mayúscula. M-l - Convierte la siguiente palabra (o selección) a minúscula.

C-a - Mueve al inicio de la línea C-e - Mueve al final de la línea C-p - Mueve a la línea anterior C-n - Mueve a la línea posterior C-f - Mueve adelante un caracter C-b - Mueve atrás un caracter M-f - Mueve adelante una palabra M-b - Mueve atrás una palabra C-M-n - Mueve abajo la línea o selección C-M-p - Mueve arriba la línea o selección S-M-u - Mueve arriba 10 líneas S-M-d - Mueve abajo 10 líneas M-< - Mueve al inicio del buffer M-> - Mueve al final del buffer

Borrado

C-h - Borra el caracter previo C-d - Borra el caracter posterior

Características avanzadas del Editor

C-i - Muestra documentos para la palabra bajo el cursor M-z - Deshace S-M-z - Rehace C-g - Escapa S-M-f - Cambia al modo de pantalla completa S-M-b - Cambia la visibilidad de los botones S-M-l - Cambia la visibilidad de la bitácora S-M-m - Cambia entre los modos luminoso/Obscuro de pantalla S-M-s - Save contents of buffer to a file S-M-o - Load contents of buffer from a file


- Compartiendo

Sonic Pi se trata de compartir y aprender de todos.

Cuando hayas aprendido a codificar música, compartir tus composiciones es tan sencillo como enviar un correo conteniendo tu código. Por favor comparte tu código con los demás, para que ellos puedan aprender de tu trabajo e inclusive utilizar partes del mismo en nuevas obras.

Si tienes dudas de cuál es la mejor manera de compartir tu trabajo con otros, te recomiendo ponerlo en GitHub y tu música en SoundCloud. Así podrás llegar a mayores audiencias.

Código -> GitHub

GitHub es un sitio para compartir código, utilizado por desarrolladores profesionales y artistas para compartir y colaborar con código. La manera más sencilla de compartir una nueva pieza de código (inclusive de obras no terminadas) es creando un Gist. Un Gist es una manera simple de subir tu código para ser visto por los demás para ver, copiar y compartir.

Audio -> SoundCloud

Otra manera de compartir es grabando el audio y subiéndolo a SoundCloud. Una vez subido, otros pueden comentar y discutir tu obra.También recomiendo poner un enlace al Gist de tu código en la descripción de la pista.

Para grabar tu trabajo, presiona el botón Rec y comenzará inmediatamente. Dale a Run para comenzar tu código si no está ya en ejecución. Cuando estes listo con tu grabación, vuelve a presional el parpadeante botón Rec y te pedirá un nombre para el archivo, que será guardado como WAV, el cual puede ser editado y convertido a MP3 por muchos programas libres (prueba Audacity, por ejemplo).

Esperanza

Te invito a compartir tu trabajo y espero realmente que todos nos enseñemos mutuamente nuevos trucos y movimientos con Sonic Pi. Realmente me interesa ver qué es lo que me mostrarás.


- Ejecutando

Uno de los aspectos más excitantes de Sonic Pi es que usa código como un instrumento musical. Lo que significa que escribir código puede ser visto como una nueva manera de ejecutar música.

Que es lo que llamamos Live Coding.

Muestra tú pantalla

Cuando hagas código en vivo, te recomiendo que muestres tu pantalla a la audiencia. De otra manera es como tocar guitarra escondiendo tus dedos y cuerdas. Cuando practico en casa, uso una Raspberry Pi y un mini proyector en el muro de mi sala. Puedes usar tu TV o uno de los proyectores de tu escuela/trabajo para dar una muestra. ¡Inténtalo que es muy divertido!

Forma una banda

No sólo toques por tí mismo - ¡forma una banda de live coding! Es divertido tocar con otros. Una persona puede hacer pulsos, otra sonidos ambiente, etc. Busca interesantes combinaciones de sonido para hacer.

TOPLAP

Live coding no es completamente nuevo - un puñado de gente lleva haciéndolo por años, típicamente utilizando equipo hecho por ellos mismos. Un buen lugar para encontrar otros live coders es TOPLAP.

Algorave

Otra fuente importante a explorar el mundo de live coding es Algorave. Aqui puedes encontrar todo lo relacionado a música con live codign para nightclubs.


- Minecraft Pi

Sonic Pi soporta una simple API para interactuar con Minecraft Pi - la edición especial de Minecraft instalada en el sistema operativo basado en Linux que trae la Raspberry Pi, elRaspbian.

Sin necesidad de importar librerías

La integración de Minecraft Pi está diseñada para ser extremadamente fácil de usar. Sólo necesitas lanzar Minecraft Pi y crear un mundo. De ahí tienes libertad de usar mc_* fns tanto como utilizasplay y synth. No hay necesidad de importar algo o instalar librerías. Todo está listo para funcionar.

Conexión automática

El API de Minecraft Pi se encarga de manejar tu conexión a la aplicación Minecraft Pi. Esto significa que no tienes algo de lo que preocuparte. Si intentas utilizar el API de Minecraft Pi cuando Minecraft Pi no está en funcionamiento, Sonic Pi te lo dirá. Similarmente, si cierras Minecraft Pi mientras se ejecuta un live_loop que utiliza la API, el bucle se detendrá y te dirá que no se puede conectar. Para reconectar, simplemente lanza Minecraft Pi de nuevo y Sonic Pi detectará automáticamente y recreará la conexión para tí.

Diseñado para ser Live Coded

La API de Minecraft fue diseñada para trabajar dentro de live_loops. Esto significa que es posible sincronizar modificaciones en tus mundos de Minecraft Pi con modificaciones en tu Sonic Pi. Videos instantáneos de música basada en Minecraft! Nota que Minecraft Pi es software alfa y conocido por algunos problemillas. Si encuentras algunos problemas, reinicia Minecraft Pi y continúa como anteriormente. La funcionalidad de conexión automática de Sonic Pi se encargará por tí.

Requiere una Raspberry Pi 2.0

Es recomendable usar una Raspberry Pi 2 si pretendes correr al mismo tiempo Sonic Pi y Minecraft, especialmente si deseas utilizar las capacidades de Sonic Pi.

Soporte API

Por ahora, Sonic Pi soporta las manipulaciones básicas de bloque y ejcutante, que fueron detalladas en la sección 11.1. En futuras versiones se pretende soportar llamadas de eventos disparadas por interacciones de ejecutantes en el mundo.


11.1 - API Básico de Minecraft Pi

Sonic Pi actualmente soporta las siguientes interacciones básicas con Minecraft Pi:

Mostrar mensajes de chat Establecer la posición del usuario Obtener la posición del usuario Establecer el tipo de bloque a una coordenada dada Obtener el tipo de coordenada a una coordenada dada

Veamos cada una de ellas ahora.

Mostrar mensajes de chat

Veamos cuán fácil es controlar Minecraft Pi desde Sonic Pi. Primero, asegúrate de tener abiertos tanto Minecraft Pi como Sonic Pi al mismo tiempo y haber entrado a un mundo de Minecraft en el que puedas caminar.

Escribe lo siguiente en un buffer vacío de Sonic Pi:

mc_message "Hola desde Sonic Pi"

Cuando presiones el botón Run, verás tu mensaje en la ventana de Minecraft. ¡Felicidades, acabas de escribir tu primer código de Minecraft! ¿fácil, no?

Establecer la posición del usuario

Hagamos un poco de magia. Teletransportémonos a alguna parte. Prueba lo siguiente:

mc_teleport 50, 50, 50

Cuando le das al botón Run - ¡boom! Te teletransporta a otro lugar. Lo más usual es que sea un lugar en el cielo y que caigas en un lugar seco o en agua. Ahora, ¿cuáles eran esos números 50, 50, 50? Esas son coordenadas de la posición a la que te quieres teletransportar. Tommos un rato para explorar qué son esas coordenadas y cómo trabajan, porque son muy, muy importantes para progrmar Minecraft..

Coordenadas

Imagina un mapa pirata con una gran X marcando la localización de un tesoro. La localización exacta de X puede ser descrita con dos números - cuán lejos en el mapa de izquierda a derecha y qué tan lejos de arriba a abajo. Por ejemplo 10cm cruzando y 8cm arriba. Estos dos números 10 y 8 son coordenadas. Fácilmente podrías imaginar describir las localizaciones de otros tesoros con otros pares de números. Quizás existe un enorme baúl de oro en 2 cruzando y 9 arriba…

Ahora, en Minecraft dos números no son suficientes. También necesitamos saber qué tan alto nos encontramos. Por lo tanto necesitamos tres números:

Cómo de lejos de derecha a izquierda en el mundo - x Cómo de lejos de frente hacia atrás en el mundo - z Cómo de alto estamos en el mundo - y

Una última cosa: típicamente describimos estas coordenadas en este orden: x, y, z.

Encontrando tus coordenadas actuales

Juguemos con las coordenadas. Navega a algún lugar bonito en el mapa de Minecraft y después pásate a Sonic Pi. Ahora pon el siguiente código:

puts mc_location

Cuando presionas el botón Run verás las coordenadas de tu posición actual en la ventan de la bitácora. Apúntalas, muévete adelante en el mundo y vuelve a probar. ¡Nota que las coordenadas han cambiado! Ahora, yo recomiendo que pases algún tiempo repitiendo esto exactamente - muévete un poco en el mundo, mira las coordenadas y repite. Hazlo hasta que sientas cómo cambian las coordenadas cuando te mueves. Una vez lo entiendas, programar con el APi de Minecraft será un paseo.

¡Construyamos!

Ahora que ya sabes cómo encontrar la posición actual y teletransportarte utilizando las coordenadas, tienes entonces las herramientas necesarias para comenzar a construir cosas en Minecraft con código. Digamos que quieres convertir en vidrio el bloque en las coordenadas 40, 50, 60. Super fácil:

mc_set_block :glass, 40, 50, 60

Haha, fué realmente fácil. Para ver tu trabajo, simplemente teletranspórtate a las cercanías y echa un vistazo:

mc_teleport 35, 50, 60

¡Ahora mira alrededor y deberías ver un bloque de vidrio! Intenta cambiarlo a diamante:

mc_set_block :diamond, 40, 50, 60

Si estabas mirando en la dirección correcta, puedes haberlo visto cambiar. Es el comienzo de algo excitante…

Viendo los bloques

Veamos lo último antes de movernos a algo más envolvente. Si damos un set de coordenadas, podemos preguntarle a Minecraft qué tipo de bloque espeecífico es. Intentémoslo con el bloque de diamante que acabamos de crear:

puts mc_get_block 40, 50, 60

Yey! Es :diamond. Intenta cambiandolo a glass y preguntar otra vez - ¿dice :glass? Estoy seguro que si :-)

Tipos de bloques disponibles

Antes de ponerte a programar en Minecraft Pi como un obseso, podrías ojear la siguiente lista de bloques disponibles:

    :air
    :stone
    :grass
    :dirt
    :cobblestone
    :wood_plank
    :sapling
    :bedrock
    :water_flowing
    :water
    :water_stationary
    :lava_flowing
    :lava
    :lava_stationary
    :sand
    :gravel
    :gold_ore
    :iron_ore
    :coal_ore
    :wood
    :leaves
    :glass
    :lapis
    :lapis_lazuli_block
    :sandstone
    :bed
    :cobweb
    :grass_tall
    :flower_yellow
    :flower_cyan
    :mushroom_brown
    :mushroom_red
    :gold_block
    :gold
    :iron_block
    :iron
    :stone_slab_double
    :stone_slab
    :brick
    :brick_block
    :tnt
    :bookshelf
    :moss_stone
    :obsidian
    :torch
    :fire
    :stairs_wood
    :chest
    :diamond_ore
    :diamond_block
    :diamond
    :crafting_table
    :farmland
    :furnace_inactive
    :furnace_active
    :door_wood
    :ladder
    :stairs_cobblestone
    :door_iron
    :redstone_ore
    :snow
    :ice
    :snow_block
    :cactus
    :clay
    :sugar_cane
    :fence
    :glowstone_block
    :bedrock_invisible
    :stone_brick
    :glass_pane
    :melon
    :fence_gate
    :glowing_obsidian
    :nether_reactor_core