Benvenuto in Sonic Pi. Spero tu non veda l’ora di cominciare a creare i tuoi suoni almeno quanto io sono impaziente di mostrarti come si fa. Sarà un viaggio veramente divertente nel quale imparerai tutto su musica, sintesi, programmazione, composizione, performance e altro.
Un momento, non mi sono nemmeno presentato! Sono Sam Aaron - il tipo che ha realizzato Sonic Pi. Mi puoi trovare su Twitter @samaaron e mi farà molto piacere conoscerti. Magari ti interessa sapere qualcosa di più anche delle mie Live Coding Performances dove scrivo codice dal vivo con Sonic PI davanti al pubblico.
Se hai qualche suggerimento o idea per migliorare Sonic PI, mi raccomando, fammela sapere: il tuo feedback è un aiuto importante. Non si può mai sapere, la tua idea potrebbe essere la prossima “big feature”!
Questo tutorial è suddiviso in sezioni raggruppate in categorie. Anche se l’ho pensato per un apprendimento facile e progressivo dall’inizio alla fine, sentiti libero di passare da un argomento all’altro senza seguire necessariamente l’ordine del tutorial. Se pensi che manchi qualcosa, fammelo sapere e io prenderò in considerazione il tuo suggerimento per una prossima versione.
Infine, guardare gli altri che fanno live coding è un ottimo modo per imparare. Faccio regolarmente dirette streaming on line su http://youtube.com/samaaron quindi passa per un saluto e fammi tante domande :-)
Ok, possiamo cominciare…
Uno degli aspetti più divertenti di Sonic Pi è che ti permette di scrivere e modificare codice live per fare musica, proprio come se suonassi una chitarra dal vivo. Questo significa che dopo un po’ di pratica puoi salire sul palco ed esibirti con Sonic Pi.
Prima di entrare nel vivo del funzionamento di Sonic Pi, vorrei farti capire meglio cosa vuol dire programmare dal vivo. Per il momento non ti preoccupare se non capisci molto (o anche nulla) di quello che vedremo. Mettiti solo comodo e divertiti…
Allora cominciamo, copia il codice qui di seguito in uno dei buffer vuoti:
live_loop :flibble do
sample :bd_haus, rate: 1
sleep 0.5
end
Ora premi il tasto Run
e sentirai un bel suono di cassa che batte a tempo. Per fermare il suono basta premere sul tasto Stop
. Però, per il momento, non premerlo ancora… Segui invece questi passaggi:
sleep
da 0.5
a qualcosa di più grande, ad esempio: 1
.Run
Ok, fin qui era abbastanza semplice. Adesso aggiungi qualcos’altro al mix. Sopra sample :bd_haus
aggiungi l’istruzione sample :ambi_choir, rate: 0.3
. Il tuo codice dovrebbe apparire così:
live_loop :flibble do
sample :ambi_choir, rate: 0.3
sample :bd_haus, rate: 1
sleep 1
end
E adesso, sbizzarrisciti. Cambia il parametro rate:
- cosa succede se usi valori grandi, o piccoli, o negativi? Guarda cosa succede se cambi il valore di rate:
del campione :ambi_choir
anche di pochissimo (diciamo 0.29). Cosa succede se scegli un valore molto piccolo per sleep
? Prova a farlo così velocemente da provocare un errore, perché il computer non riesce a stargli dietro (se succede, basta scegliere un valore di sleep
più grande e premere di nuovo Run
).
Prova a inserire all’inizio di una delle istruzioni sample
un #
:
live_loop :flibble do
sample :ambi_choir, rate: 0.3
# sample :bd_haus, rate: 1
sleep 1
end
Fai caso a come il #
dice al computer di ignorare quello che c’è scritto dopo, e di conseguenza non sentiamo più il campione. In Sonic Pi possiamo usare i commenti per togliere o reinserire elementi al mix.
Infine, ecco qualcosa di divertente con cui giocare. Prendi il codice qui sotto e copialo in un buffer vuoto. Poi, non cercare di capire altro, se non che ci sono due loop - due cose che suonano nello stesso tempo. Quindi, fai quello che sai fare meglio: provare e sperimentare. Ecco alcuni suggerimenti:
rate:
e ascolta il suono del campione che cambia.sleep
e senti come tutti e due i loop possono girare a differenti velocità.#
) e goditi il suono della chitarra al contrario.mix
con numeri che vanno da 0
(tutto fuori dal mix) a 1
(tutto nel mix).Ricordati di premere Run
e sentirai il cambiamento non appena il loop viene suonato di nuovo. Se fai qualche errore, non preoccuparti: premi stop
, cancella il codice nel buffer, copia di nuovo il codice originale e sei pronto per ricominciare. Sbagliare è il modo più veloce per imparare…
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
Suona e fai esperimenti finché non avrai soddisfatto la tua curiosità su come funziona tutto questo e avrai cominciato a chiederti che altro ci puoi fare. A quel punto sarai pronto per proseguire con il tutorial.
Allora, che aspetti?
Sonic Pi ha un’interfaccia molto semplice per programmare la musica. Diamogli un’occhiata.
Questi tasti rosa sono i controlli principali per far partire o fermare i suoni. Il tasto Run esegue il codice che hai scritto nell’editor, Stop ferma tutto il codice in esecuzione, Save per salvare il codice in un file esterno e Record per registrare (in un file WAV) i suoni riprodotti.
Questi pulsanti arancioni ti permettono di modificare l’interfaccia. I pulsanti Size + e Size - ti permettono di ingrandire o rimpicciolire il testo.
Questi tasti blu ti danno accesso alle informazioni, all’aiuto e alle opzioni. Il tasto Info apre la finestra delle informazioni che contiene le notizie su Sonic Pi, il team di sviluppo, la storia, i collaboratori e la community. Il tasto Help apre e chiude l’help (G) e il tasto Prefs apre e chiude la finestra delle opzioni che ti permette di modificare alcune impostazioni di base del programma.
Questa è l’area dove scriverai il tuo codice e comporrai/eseguirai la tua musica. È un semplice editor di testo dove puoi scrivere le tue istruzioni, cancellarle, copiarle e incollarle etc. Pensalo come una versione molto elementare di Word o Google Docs. L’editor cambia il colore delle parole sulla base del loro significato nel linguaggio. Questo all’inizio può sembrare strano, ma presto ti accorgerai che è molto utile. Per esempio, qualunque testo colorato di blu è sicuramente un numero.
Attraverso il tasto prefs nel gruppo di tasti Info e Help, puoi accedere alle opzioni di configurazione di Sonic Pi. Questo tasto ti permette di aprire e chiudere la finestra delle preferenze che possono essere modificate. Per esempio, forzare la modalità mono, invertire i canali stereo, modificare il livello di dettaglio dei messaggi di log e c’è anche un cursore per il livello del suono in uscita e un selettore audio se stai usando un Raspberry Pi.
Quando i tuoi programmi girano, le informazioni su cosa stiano facendo vengono visualizzate nella finestra di log. Di default, noterai che c’è un messaggio per ogni suono che generi e che riporta il tempo esatto in cui il suono viene prodotto. Vedrai che questo ti sarà molto utile quando dovrai fare il debug, ovvero individuare gli errori, del tuo codice o capire cosa sta facendo il tuo programma.
Infine, una delle parti più importanti dell’interfaccia di Sonic Pi è la sezione Help che appare in basso nella finestra del programma. Puoi attivarla o disattivarla usando il tasto Help. La sezione Help contiene aiuti e informazioni su tutti gli aspetti di Sonic Pi, compreso questo tutorial, una lista dei sintetizzatori e dei campioni disponibili, esempi, effetti (FX) ed una lista completa di tutte le funzioni e le istruzioni disponibili nel linguaggio di Sonic Pi.
Il visualizzatore di segnale ti permette di “guardare” il suono che stai ascoltando. Poi osservare facilmente che l’onda a dente di sega ha davvero la forma di una sega e che il beep è una curva della funzione seno. Puoi inoltre distinguere i suoni forti dai suoni deboli osservando la grandezza delle linee. Ci sono tre sezioni a disposizione: la predefinita è dedicata alla combinazione dei canali destro e sinistro, poi c’è quella che permette di visualizzare i due canali separatamente e infine c’è la sezione che mostra la “figura di Lissajous”. Quest’ultima indica la relazione parametrica fra canale sinistro e canale destro, inoltre ti permette di disegnare delle forme geometriche con il suono (https://en.wikipedia.org/wiki/Lissajous_curve).
Tutti gli eventi interni ed esterni (denominati cues in Sonic Pi) sono automaticamente registrati nel Cue Viewer. Ad esempio, se hai un controller MIDI collegato e premi uno dei suoi tasti, vedrai un nuovo evento cue nel Cue Viewer che mostra il nome del controller e il valore del tasto premuto. Una volta acquisita la padronanza base per creare e riprodurre suoni, comincerai a volere gestire i suoni o intere sezioni di suoni sulla base di eventi come questi. Un evento cue è in pratica un’indicazione che qualcosa è avvenuto. Ad esempio, per ogni volta che un loop ricomincia da capo manda un evento cue che viene registrato nel Cue Viewer. Inoltre, eventi esterni come gli eventi MIDI da una periferica MIDI collegata oppure eventi OSC provenienti da altri programmi o computer sono anch’essi mostrati nel Cue Viewer. E’ inoltre possibile generare eventi cue usando la funzione ‘cue’. Qualunque cosa appaia nel Cue Viewer può essere usato per innescare qualcosa. Questo è spiegato con maggiori dettagli nelle sezioni da 10 a 12 di questo tutorial.
Sonic PI ti incoraggia ad imparare sia l’informatica che la musica suonando e sperimentando. La cosa più importante è che, mentre ti diverti, senza accorgertene impari a programmare, a comporre e a esibirti.
Già che ne stiamo parlando, permettimi di darti una dritta che ho imparato in anni di live coding in musica: non esistono errori, ma solo opportunità. È una cosa che ho spesso sentito dire a proposito del jazz, ma funziona altrettanto bene con il live coding. Non importa quanto tu sia esperto - un principiante o un Algoraver navigato: ti capiterà sempre di eseguire del codice dal risultato completamente inaspettato. Potrebbe suonare maledettamente bene, e allora vai tranquillo. Ma potrebbe suonare anche totalmente cacofonico e sballato. Non è importante quello che è venuto fuori, ma quello che ci farai subito dopo. Prendi il suono, manipolalo e modellalo fino a farlo diventare qualcosa di spettacolare. Il pubblico impazzirà.
Mentre si sta imparando, si è tentati di fare subito cose straordinarie. Metti da parte questo obiettivo e consideralo come qualcosa da raggiungere più in là. Per adesso, pensa piuttosto che la cosa più semplice che potresti scrivere con divertimento e soddisfazione è un piccolo passo verso ciò che hai in mente. Una volta che hai un’idea su quel piccolo passo, prova a realizzarlo, suonalo e vedi quali nuove idee ti suggerisce. Sarai ben presto troppo occupato a divertirti e a fare progressi concreti.
Accertati sempre di condividere il tuo lavoro con gli altri!
OK, di introduzione ne abbiamo abbastanza - cominciamo a produrre qualche suono.
In questa parte vedremo le basi dell’utilizzo dei synth. Synth è l’abbreviazione di synthesizer (sintetizzatore), che è una strana parola per indicare un generatore di suoni. Di solito i synth sono abbastanza complicati da usare - specialmente quelli analogici che sono formati da tanti moduli collegati fra di loro da decine di cavi. Sonic Pi, invece, permette gran parte di quella potenzialità, ma in modo semplice e intuitivo.
Non farti ingannare dall’apparente semplicità dell’interfaccia di Sonic Pi. Potrai arrivare a padroneggiare tecniche molto potenti di manipolazione del suono, se non ti mancherà la passione. Reggiti forte alla sedia…
Dai un’occhiata a questa istruzione:
play 70
È da qui che comincia tutto. Copiala e incollala nella finestra del codice in alto (il grande spazio bianco sotto il tasto Run). Ora, premi Run…
Forte, no?. Premilo ancora. E ancora. E ancora…
Wow, pazzesco, sono sicuro che potresti continuare così per tutto il giorno. Ma aspetta, prima di perderti in un flusso infinito di beep, prova a cambiare il numero:
play 75
Senti la differenza? Prova con un numero più piccolo:
play 60
Quindi, abbassare il numero produce suoni più gravi mentre alzarlo li rende più acuti. Proprio come in un pianoforte: i tasti nella parte più bassa (quelli a sinistra) producono note più gravi mentre i tasti nella parte alta (quella a sinistra) producono note più acute.
A quanto pare, il Do nella quarta ottava (che si scrive C nella notazione inglese) è identificato dal numero 60. play 60
, quindi, suona il Do nella 4a ottava. Per suonare il tasto successivo sulla destra, devi aggiungere 1 a 60: scrivendo play 61
, che in questo caso rappresenta il tasto nero del Do diesis. Per suonare un Re, il tasto bianco successivo procedendo verso destra, scrivi play 62
.
Non ti preoccupare se ti sembra che non abbia alcun senso: nemmeno per me lo aveva quando ho cominciato. Tutto quello che ti serve di sapere per ora è che numeri piccoli fanno beep più gravi e numeri grandi fanno beep più acuti.
Suonare una nota è divertente, ma suonarne tante contemporaneamente può esserlo anche di più. Prova:
play 72
play 75
play 79
Forte! Quindi, quando scrivi tanti play
, suonano tutti contemporaneamente. Prova da solo: quali numeri suonano bene insieme? Quali invece stridono? Sperimenta, esplora e scopri da solo.
Quindi, suonare note e accordi è divertente, ma che ne dici di provare con una melodia? Ovvero, come si fa a far suonare una nota dopo l’altra e non tutte insieme? Beh, è facile, basta fare una pausa (sleep
) tra le note:
play 72
sleep 1
play 75
sleep 1
play 79
Che bello, un piccolo arpeggio. Ma che significa quell’ 1
in sleep 1
? Quel numero indica la durata dello sleep. Vuol dire: “fermati per un beat”, ma per il momento pensiamo che significhi uno stop di un secondo. E se invece volessimo suonare il nostro arpeggio un po’ più velocemente? Basta usare valori più piccoli per l’istruzione sleep
. Che ne dici della metà, 0.5
?
play 72
sleep 0.5
play 75
sleep 0.5
play 79
Hai notato che suona più veloce? Ora prova, da solo, a cambiare note e tempi.
Una cosa che puoi provare sono i valori intermedi per le note, come play 52.3
oppure play 52.63
. Non c’è nessun bisogno, infatti, di limitarsi ai valori interi delle note. Divertiti a provare da solo.
(N.d.T. in inglese le note si chiamano con le lettere dell’alfabeto e cominciano dal La invece che dal Do. Quindi A = La, B = Si, C = Do, D = Re, E = Mi, F = Fa, G = Sol.) Se già conosci un po’ di notazione musicale (se non la conosci non ti preoccupare, per il momento non è necessaria per divertirsi) potresti voler scrivere una melodia usando i nomi delle note come C e F# invece dei numeri. Sonic Pi ha pensato anche a questo. Puoi fare così:
play :C
sleep 0.5
play :D
sleep 0.5
play :E
Non dimenticare i due punti :
prima del nome della nota in modo che diventi rosa. Puoi anche specificare l’ottava indicando un numero dopo il nome della nota:
play :C3
sleep 0.5
play :D3
sleep 0.5
play :E4
Se ti serve una nota col diesis (in inglese sharp), aggiungi una s
dopo il nome della nota come in play :Fs3
o se ti serve col bemolle (in inglese flat) aggiungi una b
come in play :Eb3
.
Esiste inoltre una comoda scorciatoia per la pausa (un modo nel linguaggio musicale per indicare di suonare nulla invece che una nota) usando :r
, :rest
or nil
.
Ora puoi sbizzarrirti a far suonare note, accordi e melodie.
Oltre a permetterti di controllare quale nota o quale campione suonare, Sonic Pi fornisce un insieme completo di parametri per inventare e controllare il suono. Ne incontreremo molti in questo tutorial e puoi trovare una trattazione completa nell’help. Per il momento, però, ne introdurremo due tra i più utili: ampiezza e bilanciamento (in inglese amplitude e pan). Prima di tutto diamo un’occhiata a cosa sono effettivamente i parametri.
Sonic Pi usa il concetto di parametro per i suoi synth. I parametri sono quantità che vengono passati all’istruzione play
e che controllano e modificano caratteristiche del suono che ascolti. Ogni synth ha il suo gruppo di parametri per controllare in modo dettagliato il suono generato, ma comunque molti synth hanno in comune alcuni parametri come per esempio amp:
e quelli che riguardano l’inviluppo (trattati in un paragrafo successivo).
I parametri hanno due parti, il nome (ovvero il nome del controllo) e il valore (il valore a cui vuoi impostare il controllo). Per esempio, potresti avere un parametro che si chiama cheese:
e volerlo impostare al valore 1
.
I parametri sono passati alle istruzioni play
usando una virgola ,
seguita dal nome del parametro, per esempio amp:
(non dimenticare i due punti :
) e quindi da uno spazio e dal valore del parametro. Per esempio:
play 50, cheese: 1
(Nota bene che cheese:
non è un parametro valido, è solo per fare un esempio).
Puoi passare più parametri in una volta separandoli con una virgola:
play 50, cheese: 1, beans: 0.5
L’ordine dei parametri non conta, quindi questa istruzione ha lo stesso effetto di quella precedente:
play 50, beans: 0.5, cheese: 1
I parametri che non sono riconosciuti dal synth vengono ignorati (come cheese
e beans
che sono ovviamente nomi assurdi per dei parametri!)
Se per sbaglio usi lo stesso parametro due volte con diversi valori, l’ultimo vince. Per esempio beans
in questa istruzione avrà il valore 2 invece di 0.5:
play 50, beans: 0.5, cheese: 3, eggs: 0.1, beans: 2
Molte cose in Sonic Pi accettano parametri, quindi passa un po’ di tempo a capire come usarli e sarai pronto! Giochiamo un po’ con il nostro primo parametro amp:
.
L’ampiezza è una rappresentazione digitale del volume di un suono. Un’ampiezza elevata produce un suono forte mentre un valore basso di ampiezza produce un suono debole. Come Sonic Pi usa numeri per rappresentare il tempo e le note, allo stesso modo usa numeri per rappresentare anche l’ampiezza. Un’ampiezza di valore 0 equivale al silenzio (non si sentirà nulla) mentre un’ampiezza di valore 1 equivale al volume normale. Puoi anche forzare l’ampiezza a valori più alti (2, 10, 100), ma vedrai che quando l’ampiezza complessiva di tutti i suoni diventa troppo alta, Sonic Pi usa il cosiddetto compressore per riportarla di nuovo a valori tali da non risultare troppo alti per le orecchie. Ciò può rendere il suono confuso e strano. Perciò prova ad usare ampiezze basse, diciamo tra 0 e 0.5, per evitare la compressione.
Per cambiare l’ampiezza di un suono, puoi usare il parametro amp:
. Ad esempio, per suonare alla metà del volume, dai un valore di 0.5:
play 60, amp: 0.5
Per suonare ad ampiezza doppia, dai un valore di 2:
play 60, amp: 2
Il parametro amp:
modifica soltanto la chiamata a play
a cui è associato. Così, ad esempio, la prima chiamata a play
è a metà volume, mentre la seconda è di nuovo sul valore di default:
play 60, amp: 0.5
sleep 0.5
play 65
Naturalmente puoi usare differenti valori per amp:
per ogni 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
Un altro parametro divertente è pan:
, che controlla la collocazione del suono (panning) sul fronte stereofonico. Bilanciare il suono a sinistra significa sentirlo solo dalla cassa di sinistra mentre, spostarlo a destra significa sentirlo dalla cassa di destra. In Sonic Pi usiamo un -1 per posizionare il suono tutto a sinistra, 0 per posizionare il suono al centro e 1 per posizionare il suono tutto a destra. Ovviamente siamo liberi di usare qualsiasi parametro tra -1 e 1 per controllare l’esatto posizionamento del nostro suono.
Facciamo suonare un beep dall’altoparlante a sinistra:
play 60, pan: -1
Ora, dall’altoparlante a destra:
play 60, pan: 1
Infine, facciamolo suonare al centro (che è la posizione di default):
play 60, pan: 0
E adesso divertiti a cambiare le ampiezze e il panning dei tuoi suoni!
Finora ci siamo divertiti un sacco con i beep. Ma probabilmente questi semplici beep staranno cominciando ad annoiarti. È tutto qui quello che Sonic Pi ha da offrire? Ci sarà qualcosa di più nel live coding che suonare dei beep! Certo che c’è, e in questa sezione esploriamo la vasta gamma di suoni che offre Sonic Pi.
Sonic Pi offre una ampia gamma di strumenti chiamati synth, forma abbreviata per sintetizzatori. Mentre i sample contengono suoni pre-registrati, i synth sono in grado di generare nuovi suoni in base a come li controlli (cosa che esploreremo più in là nel tutorial). I synth di Sonic Pi sono molto potenti ed espressivi e ti divertirai molto nell’esplorarne le possibilità e nel suonarli. Per prima cosa, impariamo a selezionare il synth da suonare.
Un suono divertente è il dente di sega. Proviamolo:
use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
play 62
Adesso proviamo un altro suono - il prophet:
use_synth :prophet
play 38
sleep 0.25
play 50
sleep 0.25
play 62
E se combinassimo insieme due suoni? Prima uno, poi l’altro:
use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
use_synth :prophet
play 57
Ora riproduciamo più suoni contemporaneamente (non mettendo sleep tra chiamate successive di play
):
use_synth :tb303
play 38
use_synth :dsaw
play 50
use_synth :prophet
play 57
Nota che il comando use_synth
influenza soltanto le chiamate seguenti a play
. Pensalo come un grande switch - le nuove chiamate a play
useranno qualsiasi sintetizzatore sia in uso in quel momento. Puoi regolare lo switch su un nuovo synth con l’istruzione use_synth
.
Per vedere quali sintetizzatori Sonic Pi mette a tua disposizione, dai un’occhiata all’opzione Synths nel menu in basso in questa schermata di aiuto (tra Esempi e FX). Ce ne sono più di 20 tra cui scegliere. Ecco qui sotto soltanto alcuni dei miei preferiti:
:prophet
:dsaw
:fm
:tb303
:pulse
Ora divertiti a cambiare i synth mentre fai la tua musica. Divertiti a combinare i synth per fare nuovi suoni e ad usare synth differenti in diverse sezioni della tua musica.
Nelle sezioni precedenti, abbiamo visto come usare il comando sleep
per controllare l’attacco della nota, ma non siamo ancora in grado di controllare la durata dei suoni.
Per dotarci di uno strumento semplice ma potente per controllare le durate dei suoni, Sonic Pi implementa il concetto di inviluppo ADSR (ci occuperemo più oltre in questa stessa sezione di cosa voglia dire ADSR). Un inviluppo di ampiezza permette di gestire due utili aspetti del controllo:
La durata è il tempo che un suono… dura! Una durata più lunga significa che sentirai il suono per un tempo più lungo. Tutti i suoni in Sonic Pi hanno un inviluppo di ampiezza controllabile, e la durata di tale inviluppo corrisponde alla durata del suono. Quindi, controllando l’inviluppo, controlli allo stesso tempo la durata.
L’inviluppo ADSR non controlla soltanto la durata, ma fornisce anche un controllo accurato dell’ampiezza del suono. Tutti i suoni udibili iniziano dal silenzio e finiscono nel silenzio, e contengono una parte non-silenziosa nel mezzo. Gli inviluppi ti permettono di variare e mantenere l’ampiezza della parte non-silenziosa del suono. È come dare a qualcuno istruzioni su come e quanto alzare e abbassare il volume dell’amplificatore della chitarra. Per esempio, potresti chiedere a questa persona di iniziare dal silenzio, alzare il volume lentamente fino al massimo, mantenerlo per un po’ e riabbassarlo di colpo. Sonic Pi ti permette di controllare con precisione questo tipo di comportamento mediante gli inviluppi.
Tanto per riassumere: come abbiamo visto prima, una ampiezza di 0 equivale a silenzio e un’ampiezza 1 è il volume normale.
Ora, diamo un’occhiata alle parti da cui l’inviluppo è composto.
L’unica parte dell’inviluppo che viene usata di default è il rilascio (release). Si tratta del tempo che il suono di un synth impiega a sfumare. Tutti i synth hanno un tempo di rilascio impostato a 1, il che vuol dire che, di default, hanno la durata di 1 beat (che a sua volta, al tempo di default di 60BPM, equivale a 1 secondo):
play 70
La nota resterà udibile per 1 secondo. Prova a verificare tu stesso. Questa era la forma breve in luogo di quella più lunga ed esplicita:
play 70, release: 1
Nota come il suono abbia esattamente la stessa durata di prima (il suono dura un secondo). Ma ora è molto facile cambiare la durata modificando il valore dell’opzione release:
:
play 60, release: 2
Possiamo anche far suonare il synth per una durata molto breve usando un valore molto piccolo del tempo di rilascio:
play 60, release: 0.2
La durata del rilascio di un suono è chiamata fase di rilascio e, di default, è una transizione lineare (cioè segue una linea retta), Il seguente diagramma illustra questa transizione:
La linea verticale sulla sinistra del diagramma indica che il suono comincia ad ampiezza 0, ma sale ad ampiezza massima immediatamente (questa è la fase di attacco, di cui ci occuperemo dopo). Raggiunta l’ampiezza massima, scende con una linea diritta fino a zero, e per fare questo impiega esattamente il tempo specificato da release:
. Valori di release più lunghi producono dissolvenze più lente.
Ora poi cambiare la durata dei suoni cambiando il tempo di rilascio. Divertiti ad aggiungere i tempi di rilascio alle note della tua musica.
Di default, la fase d’attacco è 0 per tutti i synth, il che significa che questi salgono da ampiezza 0 a 1 immediatamente. Ciò conferisce ai synth un timbro percussivo. Tuttavia, potresti volere che il suono raggiunga l’ampiezza 1 più lentamente (fade in). Puoi ottenere questo risultato con l’opzione attack:
:
play 60, attack: 2
sleep 3
play 65, attack: 0.5
Puoi usare opzioni multiple contemporaneamente. Per esempio, per un attacco corto e un rilascio lungo, prova così:
play 60, attack: 0.7, release: 4
Un inviluppo con attacco corto e rilascio lungo è illustrato nel diagramma seguente:
È ovvio che puoi fare anche l’inverso. Prova un attacco lungo e un rilascio corto:
play 60, attack: 4, release: 0.7
Infine, puoi anche impostare un tempo corto sia per l’attacco che per il rilascio, per avere suoni più brevi.
play 60, attack: 0.5, release: 0.5
Oltre ai tempi di attacco e rilascio, puoi specificare anche un tempo di sostegno (sustain) per controllare la fase di sostegno. Essa corrisponde al tempo in cui il suono è mantenuto ad ampiezza fissa dopo l’attacco e prima del rilascio.
play 60, attack: 0.3, sustain: 1, release: 1
Il tempo di sostegno è utile per suoni a cui vuoi dare maggior presenza nel mix prima di inserire una fase, opzionale, di rilascio. Naturalmente, è del tutto valido anche impostare sia l’attacco che il rilascio a 0 per non avere alcun tipo di dissolvenza né in entrata né in uscita. Bada però che un tempo di rilascio uguale a 0 genera dei click, ed è meglio usare valori molto piccoli come 0.2.
Per un ulteriore livello di controllo, puoi specificare anche un tempo di decadimento. Si tratta di una fase dell’inviluppo che si trova tra attacco e sostegno e specifica il tempo in cui l’ampiezza scende da attack_level:
(livello d’attacco) a decay_level:
(livello di decadimento). Di default, l’opzione decay:
ha valore 0 e sia il livello di attacco che il livello di sostegno sono impostati su 1, e ciò significa che dovrai impostarne il valore in modo esplicito se vuoi che il tempo di decadimento sortisca qualche effetto:
play 60, attack: 0.1, attack_level: 1, decay: 0.2, sustain_level: 0.4, sustain: 1, release: 0.5
Un’altra possibilità è impostare esplicitamente i valori di decay_level:
e sustain_level:
(anche se di default sono uguali) per avere pieno controllo sull’inviluppo. Ciò consente di creare inviluppi nel modo seguente:
play 60, attack: 0.1, attack_level: 1, decay: 0.2, decay_level: 0.3, sustain: 1, sustain_level: 0.4, release: 0.5
È possibile anche impostare un decay_level:
più alto del 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
Riassumendo, gli inviluppi di Sonic Pi hanno le seguenti fasi:
attack_level
,attack_level
a decay_level
,decay_level
a sustain_level
,sustain_level
a 0È importante sottolineare che la durata di un suono è pari alla somma dei tempi di ciascuna di queste quattro fasi. Quindi, il suono seguente avrà una durata pari a 0.5 + 1 + 2 + 0.5, ovvero 4 beat:
play 60, attack: 0.5, attack_level: 1, decay: 1, sustain_level: 0.4, sustain: 2, release: 0.5
E adesso datti da fare ad aggiungere gli inviluppi ai tuoi suoni…
Un altro modo molto interessante per creare musica è quello di usare suoni pre-registrati. Nella grande tradizione hip-hop li chiamiamo campioni (in inglese, samples). Quindi, se ti armi di microfono e vai in giro a registrare, per esempio, il suono leggero della pioggia su una tela, hai appena creato un campione.
Con Sonic Pi puoi fare un sacco di cose divertenti coi campioni: ci sono più di 90 campioni di pubblico dominio, pronti per i tuoi mix, ma il programma ti permette anche di suonare e trasformare quelli creati da te. Vediamo subito come…
Fare i beep è soltanto l’inizio. Una cosa molto divertente è suonare campioni pre-registrati. Prova questo:
sample :ambi_lunar_land
In Sonic Pi troverai molti campioni precaricati coi quali lavorare. Puoi usarli nello stesso modo in cui usi il comando play
. Per suonare insieme note e campioni ti basta scrivere le istruzioni una dopo l’altra:
play 36
play 48
sample :ambi_lunar_land
sample :ambi_drone
Se vuoi distribuirli nel tempo, usa l’istruzione sleep
:
sample :ambi_lunar_land
sleep 1
play 48
sleep 0.5
play 36
sample :ambi_drone
sleep 1
play 36
Forse avrai notato come Sonic Pi non aspetta la fine di un suono per farne partire un altro? L’istruzione sleep
determina solo la separazione degli attacchi dei suoni. Questo ti permette di sovrapporre facilmente i suoni creando interessanti effetti d’insieme. Più avanti nel tutorial vedremo come controllare la durata dei suoni con gli inviluppi.
Ci sono due modi per esplorare la varietà di campioni forniti da Sonic Pi. Primo, puoi usare l’help del programma. Fai click su Samples nel menu verticale in basso a sinistra, scegli la categoria e lì vedrai la lista dei suoni disponibili.
Altrimenti puoi usare il sistema di autocompletamento. Prova a scrivere la prima parte del nome di un gruppo di campioni, come: sample: ambi_
e vedrai che apparirà un menu a tendina con i nomi dei campioni tra i quali potrai scegliere. Prova con questi prefissi di categoria:
:ambi_
:bass_
:elec_
:perc_
:guit_
:drum_
:misc_
:bd_
Ora puoi cominciare a mixare campioni per realizzare le tue composizioni!
Come abbiamo visto con i sintetizzatori, possiamo facilmente controllare i nostri suoni con i parametri. I campioni supportano esattamente lo stesso meccanismo di parametrizzazione. Torniamo dai nostri amici amp:
e pan:
.
Puoi cambiare l’ampiezza dei campioni con lo stesso sistema che hai usato per i synth:
sample :ambi_lunar_land, amp: 0.5
Sui campioni possiamo usare anche il parametro pan:
. Per esempio, ecco come faremmo per suonare un loop di batteria due volte passando dall’orecchio sinistro al destro:
sample :loop_amen, pan: -1
sleep 0.877
sample :loop_amen, pan: 1
Osserva che 0.877 è metà della durata in secondi del campione :loop_amen
.
Ricorda infine che, se imposti alcuni parametri di default dei synth con use_synth_defaults
(di cui parleremo più in là), questi saranno ignorati dall’istruzione sample
.
Finora abbiamo imparato a suonare una varietà di synth e campioni per fare un po’ di musica. È tempo di imparare a modificare sia i synth che i campioni per rendere la musica ancora più originale e interessante. Prima di tutto, esploriamo la capacità di Sonic Pi di stirare (in inglese, stretch) e schiacciare i suoni.
I campioni sono suoni pre-registrati immagazzinati come dati numerici che rappresentano come muovere il cono dell’altoparlante per riprodurre il suono. Il cono dell’altoparlante può muoversi in dentro e in fuori, quindi i numeri devono rappresentare lo stato (cioè quanto in dentro o quanto in fuori) in cui si deve trovare il cono dell’altoparlante in ogni istante. Per riprodurre fedelmente un suono registrato, un campione ha bisogno tipicamente di alcune migliaia di numeri al secondo! Sonic Pi prende questa lista di numeri e li riproduce alla velocità opportuna per creare il movimento in dentro e in fuori della membrana degli altoparlanti del computer, esattamente nel modo richiesto per riprodurre quel dato suono. Ma è divertente anche cambiare la velocità con cui i numeri sono inviati agli altoparlanti, in modo da cambiare anche il suono.
Proviamo a suonare uno dei nostri suoni ambient: :ambi_choir
. Per suonarlo alla velocità di default, puoi passare un argomento rate:
all’istruzione sample:
:
sample :ambi_choir, rate: 1
Questa istruzione fa suonare il campione a velocità normale (1), e per il momento non succede niente di speciale. Ma siamo liberi di cambiare quel numero in qualcos’altro. Proviamo con 0.5:
:
sample :ambi_choir, rate: 0.5
Forte! Che cosa sta succedendo? Essenzialmente due cose. Primo, il campione ci mette il doppio a suonare; secondo, il suono è un’ottava sotto. Esploriamo la cosa nel dettaglio.
Un campione divertente da stirare e comprimere è il loop di batteria Amen Break. A velocità normale, potremmo immaginare di buttarlo dentro una traccia drum’n bass:
sample :loop_amen
Ma, cambiando la velocità, ecco che possiamo anche cambiare genere. Proviamo a mezza velocità per un hip-hop vintage:
sample :loop_amen, rate: 0.5
Se aumentiamo la velocità, entriamo nel territorio del jungle:
sample :loop_amen, rate: 1.5
Adesso, come ultimo effetto a sorpresa, vediamo che succede se usiamo una velocità negativa:
sample :loop_amen, rate: -1
Wow! Suona al contrario! Proviamo a suonare molti campioni diversi a velocità diverse. Provatene di molto veloci o di lentissime. Guarda che suoni interessanti puoi creare.
Un modo utile di pensare i campioni è pensarli come molle. La velocità di lettura corrisponde a comprimere e distendere la molla. Se suoni con una velocità 2, stai comprimento la molla a metà della sua lunghezza normale, quindi il campione dura circa metà del tempo, essendo più corto. Se invece suoni il campione a metà velocità, stai distendendo la molla fino a raddoppiarne la lunghezza; di conseguenza il campione dura due volte il tempo normale, essendo più lungo. Più comprimi (velocità maggiori), più corto diventa il suono; più distendi (velocità più basse) più il suono diventa lungo.
Comprimere la molla ne aumenta la densità (numero di giri della molla per centimetro) analogamente al campione che suona più acuto. Allungare la molla fa diminuire la densità, analogamente al campione che suona più grave.
(Questa parte è per quelli che sono interessati ai dettagli. Sentitevi liberi di saltarla…)
Come abbiamo visto, un campione è rappresentato da una lunga lista di numeri che rappresentano come la membrana dell’altoparlante deve muoversi nel tempo. Possiamo usare questa lista di numeri per tracciare un grafico simile a questo:
Potreste aver già visto immagini come questa prima d’ora. Si tratta della forma d’onda del campione. È semplicemente un grafico dei numeri. Tipicamente, una forma d’onda come questa avrà 44100 punti per ogni secondo (ciò è una conseguenza del teorema del campionamento di Nyquist-Shannon). Così, se il campione dura 2 secondi, la forma d’onda sarà rappresentata da 88200 numeri che vengono inviati all’altoparlante, opportunamente convertiti in segnale elettrico, alla velocità di 44100 numeri al secondo. Potremmo naturalmente farlo a frequenza doppia (88200 numeri al secondo), e ci vorrebbe solo un secondo per suonarli tutti. Potremmo anche dimezzare la frequenza a 22050 numeri al secondo, e in quel caso ci vorrebbero 4 secondi per suonare tutta la lista di numeri.
La durata di un campione dipende dalla velocità di lettura del dato digitale:
Possiamo rappresentare questo concetto con la seguente formula:
nuova_durata_campione = (1 / velocità) * durata_del_campione
Cambiare la velocità di lettura influisce anche sul pitch del campione. La frequenza, o pitch di una forma d’onda, è determinata da quanto velocemente essa oscilla. Il nostro cervello interpreta un’oscillazione veloce come note acute e un’oscillazione lenta come note gravi. Ecco perché a volte puoi perfino veder muovere il cono di un grosso altoparlante che emette frequenze molto basse: in effetti, sta effettuando il suo movimento in dentro e in fuori a una velocità molto più bassa di quella di un altoparlante che produce note acute.
Se prendi una forma d’onda e la comprimi, quella oscillerà un numero maggiore di volte al secondo. Ciò renderà il suono più acuto. Comprendiamo allora che raddoppiare il numero di oscillazioni raddoppia la frequenza. Così, suonare il tuo campione a velocità doppia raddoppia la frequenza che ascolti. E dimezzare la velocità dimezza la frequenza. Diverse variazioni di velocità influiranno sulla frequenza in proporzione.
È possibile anche modificare la durata e l’ampiezza di un campione adoperando un inviluppo ADSR. Questo funziona però in modo lievemente differente dall’ADSR disponibile nei synth. Gli inviluppi dei campioni ti permettono soltanto di ridurre l’ampiezza e la durata di un campione, ma mai di aumentarle. Il campione si fermerà o quando sarà stato suonato tutto oppure quando sarà completato l’inviluppo, quale delle due cose accada per prima. Quindi, anche se usi un tempo di rilascio (release:
) molto lungo, non per questo aumenterai la durata del campione.
Torniamo al nostro amico fidato, il loop di batteria Amen:
sample :loop_amen
Senza parametri, ascoltiamo il campione intero ad ampiezza piena. Se vogliamo creare un fade-in (dissolvenza in entrata) di 1 secondo, possiamo usare il parametro attack:
(tempo di attacco):
sample :loop_amen, attack: 1
Per un fade-in più corto, impostiamo un tempo di attacco più corto:
sample :loop_amen, attack: 0.3
La fase dell’inviluppo in cui il comportamento dell’ADSR differisce, per i campioni, da quello standard dei synth, è il tempo di sustain:
(sostegno). Negli inviluppi standard dei synth, esso è impostato di default su 0 a meno che non venga impostato manualmente su un valore diverso. Con i campioni, il sustain si imposta su un valore automagico, cioè il tempo necessario ad eseguire il resto del campione. Ecco perché sentiamo l’intero campione quando non impostiamo alcun valore. Se attacco, decadimento, sostegno e rilascio fossero tutti impostati su 0, non sentiremmo un bel niente. Sonic Pi calcola perciò la lunghezza del campione, ne sottrae eventuali tempi di attacco, decadimento e rilascio, e usa il risultato come tempo di sostegno. Se attacco, decadimento e rilascio sommati durano più della durata effettiva del campione, il sustain è lasciato, semplicemente, a 0.
Per esaminare questo aspetto, consideriamo il nostro loop Amen più in dettaglio. Se chiediamo a Sonic Pi quanto dura il campione:
print sample_duration :loop_amen
lui stamperà 1.753310657596372
, che è la lunghezza del campione in secondi. Per comodità, arrotondiamolo a 1.75
. Adesso, se impostiamo il rilascio a 0.75
, ecco cosa accade:
sample :loop_amen, release: 0.75
Suonerà il primo secondo del campione ad ampiezza piena prima di dissolvere in un tempo di 0.75 secondi. Ecco l’autosustain in azione. Di default, il rilascio funziona sempre contando a ritroso dalla fine del campione. Se il nostro campione fosse di 10.75 secondi, suonerebbe i primi 10 secondi ad ampiezza piena prima di dissolvere in 0.75 secondi.
Ricorda: di default il tempo di rilascio va contato dalla fine del campione.
Possiamo usare insieme sia attack:
che release:
con l’autosustain per avere sia il fade in che il fade out sulla durata del campione:
sample :loop_amen, attack: 0.75, release: 0.75
Dal momento che la durata completa del campione è 1.75 secondi e i nostri tempi di attacco e rilascio durano complessivamente 1.5 secondi, il sustain è impostato automaticamente a 0.25 secondi. Ciò permette di applicare le dissolvenze al campione con grande facilità.
Possiamo benissimo tornare al comportamento normale dell’ADSR dei synth impostando sustain:
manualmente su un valore, ad esempio 0:
sample :loop_amen, sustain: 0, release: 0.75
Adesso il nostro campione suona per soli 0.75 secondi totali. Con il valore di default 0 per attack:
e decay:
, il campione va immediatamente alla massima ampiezza, tiene il suono per…0 secondi e poi se ne va ad ampiezza 0 con un tempo di rilascio di 0.75 secondi.
Possiamo servirci di questo comportamento come effetto per trasformare campioni lunghi in versioni corte e più percussive dello stesso campione. Consideriamo il campione :drum_cymbal_open
:
sample :drum_cymbal_open
Puoi sentire il suono del piatto riusuonare per un certo tempo. Tuttavia, possiamo usare il nostro inviluppo per rendere il suono più percussivo:
sample :drum_cymbal_open, attack: 0.01, sustain: 0, release: 0.1
Puoi emulare il colpo di piatto e il successivo smorzamento aumentando il tempo di sostegno:
sample :drum_cymbal_open, attack: 0.01, sustain: 0.3, release: 0.1
E adesso divertiti ad applicare gli inviluppi ai campioni. Prova a cambiare anche la velocità di lettura per risultati davvero interessanti.
Con questa sezione si conclude la nostra esplorazione su come Sonic Pi gestisce i campioni audio. Facciamo un breve riassunto. Finora abbiamo visto come avviare l’esecuzione di un campione:
sample :loop_amen
Quindi abbiamo visto come cambiare la velocità di lettura dei campioni in modo da farli suonare a velocità dimezzata:
sample :loop_amen, rate: 0.5
Abbiamo visto come inserire un fade-in all’inizio del campione (ora facciamolo a velocità dimezzata):
sample :loop_amen, rate: 0.5, attack: 1
Abbiamo visto anche come dare al campione un attacco percussivo dando un valore di sustain:
esplicito (zero) e impostando attacco e rilascio su valori molto corti:
sample :loop_amen, rate: 2, attack: 0.01, sustain: 0, release: 0.35
Ma non sarebbe bello se non dovessimo suonare il campione sempre dall’inizio? E non sarebbe altrettanto bello non doverlo suonare sempre fino alla fine?
È possibile scegliere un punto d’inizio a piacere nell’esecuzione del campione come valore associato al parametro start:
compreso tra 0 e 1, dove 0 corrisponde all’inizio del campione, 1 alla fine e 0.5 esattamente a metà. Proviamo a suonare soltanto la seconda metà del nostro solito loop di batteria:
sample :loop_amen, start: 0.5
Ed ecco l’ultimo quarto soltanto:
sample :loop_amen, start: 0.75
In modo simile è possibile scegliere a piacere un punto finale all’interno del campione impostando un valore tra 0 e 1 per il parametro finish:
. Eseguiamo il loop di batteria fino a metà campione:
sample :loop_amen, finish: 0.5
È possibile, naturalmente, combinare queste due istruzioni per eseguire a piacere un frammento del file audio. Ecco come eseguire una piccola porzione al centro del file:
sample :loop_amen, start: 0.4, finish: 0.6
Ma cosa succede se scegliamo un punto d’inizio collocato dopo il punto finale?
sample :loop_amen, start: 0.6, finish: 0.4
Forte! Suona all’indietro!
Possiamo combinare questa nuova possibilità di suonare frammenti a scelta di un file audio con la nostra vecchia conoscenza rate:
, la velocità di lettura. Possiamo ad esempio eseguire un frammento brevissimo del loop di batteria ad una velocità molto bassa:
sample :loop_amen, start: 0.5, finish: 0.7, rate: 0.2
Possiamo infine combinare tutto questo con gli inviluppi ADSR per ottenere risultati interessanti:
sample :loop_amen, start: 0.5, finish: 0.8, rate: -0.2, attack: 0.3, release: 1
E ora sbizzarriamoci a creare mix di campioni manipolati in tutti questi fantastici modi…
Con i campioni compresi in Sonic Pi puoi cominciare a lavorare subito. Tuttavia, arriverai a voler sperimentare inserendo altri suoni registrati nella tua musica. Prima però discutiamo brevemente sulla portabilità del tuo pezzo.
Quando componi un pezzo soltanto con i synth e i campioni compresi in Sonic Pi, tutto ciò di cui hai bisogno per riprodurre fedelmente la tua musica è il codice. Pensaci un attimo - è straordinario! Un semplice frammento di testo che puoi inviare per email o depositare in un [Gist] (https://gist.github.com) è tutto quello che ti serve per riprodurre i tuoi suoni. Ciò rende davvero facile condividerli con i tuoi amici, perché tutto quello di cui anche loro hanno bisogno è il codice.
Tuttavia, se cominci ad usare campioni tuoi, perdi la portabilità. Questo perché, per riprodurre la tua musica, le altre persona non hanno bisogno soltanto del codice, ma anche dei campioni. Ciò limita la possibilità per gli altri di manipolare, creare mix e sperimentare con il tuo lavoro. Naturalmente questo non deve impedirti di usare suoni tuoi: è solo un fatto da tenere in considerazione.
Ma insomma come si fa a suonare un qualsiasi file WAV o AIFF residente nel tuo computer? Devi soltanto passare il percorso di quel file all’istruzione sample
:
# Raspberry Pi, Mac, Linux
sample "/Users/sam/Desktop/my-sound.wav"
# Windows
sample "C:/Users/sam/Desktop/my-sound.wav"
In questo modo Sonic Pi carica automaticamente il campione e lo suona. A quel punto puoi passare tutti i parametri standard che hai usato finora con 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
Nota: questa sezione del tutorial copre argomenti avanzati e spiega come lavorare con directory contenenti molti sample. Questo, ad esempio, può accadere se hai scaricato o comprato dei sample pack e vuoi utilizzarli con Sonic Pi.
Sentiti libero di saltare questa sezione se i campioni già presenti in Sonic Pi ti sono sufficienti.
Quando lavori con cartelle piene di file esterni, può essere scomodo digitare l’intero percorso ogni volta che vuoi lanciare un singolo campione.
Per esempio, facciamo finta che tu abbia questa cartella sul tuo computer:
/path/to/my/samples/
Quando guardiamo all’interno di quella cartella, troviamo i seguenti campioni:
100_A#_melody1.wav
100_A#_melody2.wav
100_A#_melody3.wav
120_A#_melody4.wav
120_Bb_guit1.wav
120_Bb_piano1.wav
Di solito, per suonare i campioni di pianoforte dovremmo usare il percorso completo:
sample "/path/to/my/samples/120_Bb_piano1.wav"
Se volessimo usare anche i campioni di chitarra, anche in questo caso dovremmo usare il percorso completo:
sample "/path/to/my/samples/120_Bb_guit.wav"
Purtroppo, per caricare questi campioni è necessario conoscere i nomi dei campioni all’interno della nostra cartella. E se volessimo ascoltare velocemente ciascun sample a turno?
Se vogliamo suonare il primo campione in una cartella, dobbiamo semplicemente passare il nome della cartella al comando sample
e l’indice 0
in questo modo:
sample "/path/to/my/samples/", 0
Se vogliamo, possiamo anche creare una scorciatoia per la nostra cartella utilizzando una variabile:
samps = "/path/to/my/samples/"
sample samps, 0
Ora, se vogliamo suonare il secondo sample nella directory, dobbiamo aggiungere 1 al nostro indice:
samps = "/path/to/my/samples/"
sample samps, 1
Puoi notare come non sia più necessario conoscere i nomi dei campioni nella cartella, dobbiamo solo conoscere la posizione della cartella stessa (o avere una scorciatoia). Se proviamo a utilizzare un indice maggiore del numero dei campioni, ripartirà semplicemente da capo come nei Rings. Per cui, indipendentemente dal numero usato, abbiamo la sicurezza che verrà utilizzato un campione in quella cartella.
Di solito è sufficiente indicizzare, ma qualche volta abbiamo bisogno di maggiore potenza per organizzare i nostri campioni. Per fortuna molti pacchetti di campioni aggiungono informazioni nei nomi dei file. Diamo ancora un’occhiata ai campioni nella nostra cartella:
100_A#_melody1.wav
100_A#_melody2.wav
100_A#_melody3.wav
120_A#_melody4.wav
120_Bb_guit1.wav
120_Bb_piano1.wav
Puoi notare come i nomi dei file hanno molte informazioni. Per iniziare abbiamo il BPM del sample (beat per minuto) all’inizio del nome. PEr cui se il campione del pianoforte è a 120BPM mentre le nostre tre melodie sono a 100BPM. In aggiunta, il nome dei campioni contiene anche la tonalità: il campione di chitarra è in Bb (Si bemolle) e le melodie in A# (La diesis). Questa informazione è molto utile per mixare questi sample con il nostro codice. Per esempio, sappiamo che possiamo suonare il campione del piano se il nostro codice è a 120BPM e in tonalità di Bb.
È possibile usare questa convenzione sui nomi dei file del nostro set di campioni nel codice per aiutarci a filtrare quelli che vogliamo. Per esempio, se stiamo lavorando a 120BPM, possiamo visualizzare tutti i campioni che contengono la stringa "120"
come segue:
samps = "/path/to/my/samples/"
sample samps, "120"
Questo farà suonare il primo risultato. Se volessimo il secondo, possiamo usare l’indice:
samps = "/path/to/my/samples/"
sample samps, "120", 1
Possiamo anche usare più filtri contemporaneamente. Per esempio, se vogliamo utilizzare i campioni il cui nome contenga sia “120” che “A#” possiamo farlo usando questo codice:
samps = "/path/to/my/samples/"
sample samps, "120", "A#"
Infine, possiamo sentirci liberi di usare i parametri di sample
che abbiamo già visto:
samps = "/path/to/my/samples/"
sample samps, "120", "Bb", 1, lpf: 70, amp: 2
Il sistema di filtro dei campioni capisce due tipi di informazioni: la fonte e i filtri. Le fonti sono informazioni usate per creare la lista dei potenziali candidati. Una fonte può avere due forme:
La funzione sample
raccoglierà per prima cosa tutte le fondi e le userà per creare una lunga lista di possibili candidati. Questa lista viene costruita aggiungendo tutti i percorsi e tutti i file con estensione .flac
, .aif
, .aiff
, .wav
, .wave
contenuti all’interno della cartella.
Per esempio, diamo un’occhiata a questo codice:
samps = "/path/to/my/samples/"
samps2 = "/path/to/my/samples2/"
path = "/path/to/my/samples3/foo.wav"
sample samps, samps2, path, 0
In questo caso stiamo combinando il contenuto dei campioni all’interno di due cartelle e aggiungendo un campione specifico. Se "/path/to/my/samples/"
contiene 3 campioni e "/path/to/my/samples2/"
ne contiene 12, abbiamo 16 potenziali campioni da indicizzare e filtrare (3 + 12 + 1).
Per impostazione predefinita, sono inclusi nella lista dei candidati solo i campioni contenuti in una cartella. E’ possibile talvolta che in una serie di cartelle di campioni annidate, si voglia eseguire una ricerca e applicarvi dei filtraggi. Pertanto, è possibile eseguire una ricerca ricorsiva per tutti i campioni contenuti in ogni sottocartella di una data cartella aggiungendo **
alla fine del percorso:
samps = "/path/to/nested/samples/**"
sample samps, 0
Fai attenzione quindi, perché la ricerca all’interno di un gruppo di cartelle ampio può impegare parecchio tempo ad essere portata a termine. Comunque, il contenuto di tutte le cartelle sorgenti sono memorizzati nella cache, quindi soltanto la prima volta la ricerca impiegherà più tempo.
Infine, tieni presente che la sorgente deve essere inserita prima. Ne nessuna sorgente viene indicata, allora il gruppo di campioni già presenti nel sistema verrà selezionato automaticamente per la sessione.
Quando avrai ottenuto una lista di campioni da usare durante la sessione, puoi quindi utilizzare le seguenti chiavi per ridurne ulteriormente il numero:
"foo"
filtrerà le occorrenze all’interno del nome del file (cartella di percorso ed estensione escluse)./fo[oO]/
filtrerà il pattern riconosciuto nel nome del file (cartella di percorso ed estensione esclusi).:foo
filtrerà i vari file candidati se la parola chiave avrà riscontro diretto nel nome del file (cartella di percorso ed estensione esclusi).lambda{|a| ... }
(ndT: in Ruby i Procs sono blocchi di codice legati a variabili locali) con un argomento saranno trattati come filtri o funzioni di generazione. La lista dei file correnti candidati deve essere passata all’oggetto che restituirà una nuova lista di candidati (una lista di percorsi validi ai file).1
selezioneranno il file candidato a quell’indice (ripartendo dall’inizio se necessario).Per esempio, possiamo filtrare tutti i campioni in una cartella che contengono la stringa "foo"
e riproduttre il primo risultato a metà della velocità:
sample "/path/to/samples", "foo", rate: 0.5
Vedi il capitolo relativo ai sample
nel manuale per altri esempi di utilizzo. Attenzione: verrà rispettato l’ordine dei filtri.
Infine, puoi usare delle liste sia al posto delle fonti che dei filtri. Le liste saranno automaticamente appiattite e il loro contenuto sarà trattato come una fonte o un filtro. Per questo motivo, i seguenti esempi su sample
sono equivalenti a livello semantico:
sample "/path/to/dir", "100", "C#"
sample ["/path/to/dir", "100", "C#"]
sample "/path/to/dir", ["100", "C#"]
sample ["/path/to/dir", ["100", ["C#"]]]
Questa era una sezione per coloro che hanno bisogno di manipolare e usare i pacchetti di campioni in modo avanzato. Se per te questa sezione non aveva alcun senso, non ti preoccupare. Probabilmente non hai ancora bisogno di utilizzare queste funzionalità. In ogni caso ora sai dove si trova questa sezione e potrai tornare indietro a rileggerla quando ne avrai bisogno.
Un modo molto efficace per rendere interessante la tua musica è utilizzare numeri casuali. Sonic Pi ha delle funzioni che ti permettono di introdurre un po’ di casualità all’interno della tua musica ma, prima di cominciare, dovete conoscere un’importante verità: in Sonic Pi i numeri casuali non sono veramente casuali. Che significa? Vediamo insieme.
Una delle funzioni per avere numeri casuali è rrand
che restituisce un valore compreso tra due numeri, un minimo e un massimo. (rrand
è l’abbreviazione di ranged random, ovvero una casualità tra una serie di valori). Proviamo a suonare una nota casuale:
play rrand(50, 95)
Wow, abbiamo suonato una nota a caso. La nota suonata è 83.7527
. Un numero casuale tra 50 e 95. Ehi, un momento, ho appena predetto il valore esatto della nota casuale che hai suonato anche tu? Sta succedendo qualcosa di strano. Prova a eseguire nuovamente il codice. È uscito ancora 83.7527
? Non può essere casuale!
La risposta è che non è realmente casuale, è pseudo-random. Sonic Pi restituirà sempre dei valori pseudo-casuali in un modo ripetibile. Questo è utile per essere sicuri che la musica create sulla nostra macchina suonerà identica su qualsiasi altro computer, anche utilizzando un po’ di casualità nella nostra composizione.
Ovviamente, in un brano musicale, se venisse scelto in modo “casuale” sempre il valore 83.7527
non sarebbe interessante. Comunque non sempre restituirà quel risultato. Prova con il seguente codice:
loop do
play rrand(50, 95)
sleep 0.5
end
Evviva! Finalmente suona casuale. Se richiamiamo più volte la funzione random, otterremo in cambio valori davvero casuali. Ricorda comunque che al successivo avvio, otterremo la stessa sequenza di numeri casuali per cui suonerà esattamente nello stesso modo. È come se il codice scritto in Sonic Pi andasse indietro nel tempo tornando allo stesso punto di inizio ogni volta che premiamo il pulsante di avvio. È il giorno della marmotta nella sintesi musicale!
Un bell’esempio dell’utilizzo di valori casuali è nel seguente codice, chiamato “Campane stregate” che esegue una ripetizione del campione :perc_bell
con valori casuali di velocità (rate) e pausa (sleep) tra i vari suoni di campana:
loop do
sample :perc_bell, rate: (rrand 0.125, 1.5)
sleep rrand(0.2, 2)
end
Un altro esempio sull’utilizzo di valori casuali può essere applicato al taglio di frequenze su un sintetizzatore. Un ottimo synth con cui provarlo è l’emulatore :tb303
:
use_synth :tb303
loop do
play 50, release: 0.1, cutoff: rrand(60, 120)
sleep 0.125
end
E se non ci piacesse la sequenza casuale generata da Sonic Pi? Ovviamente è possibile scegliere un punto di partenza diverso utilizzando use_random_seed
. Il seme di default è 0; puoi utilizzare semi differenti per ottenere effetti casuali diversi!
Prova con questo esempio:
5.times do
play rrand(50, 100)
sleep 0.5
end
Ogni volta che avvierai questo codice, sentirai la stessa sequenza di 5 note. Per avere una sequenza differente, proviamo a cambiare il seme:
use_random_seed 40
5.times do
play rrand(50, 100)
sleep 0.5
end
Questo codice produrrà una sequenza di 5 note diversa dalla precedente. Cambiando il seme e ascoltando il risultato ottenuto possiamo trovare qualcosa che ci piace e quando lo condivideremo con altre persone, loro ascolteranno sempre la stessa identica cosa.
Allora, diamo un’occhiata ad alcune funzioni casuali.
Un’opzione molto utile è quella di scegliere in oggetto a caso da una lista di oggetti già conosciuti. Per esempio, potrei voler suonare una nota dal seguente elenco: 60, 65, 72. Posso ottenere questo risultato con la funzione ‘choose’ che mi permette di scegliere un oggetto da una lista. Prima di tutto, devo mettere i miei numeri in una lista che può essere creata inserendo i numeri all’interno di parentesi quadre, separati da virgole. Così: ‘[60,65,72]’. Successivamente, è sufficiente attivare la funzione ‘choose’:
choose([60, 65, 72])
Ascoltiamo che cosa ne è venuto fuori:
loop do
play choose([60, 65, 72])
sleep 1
end
Abbiamo già visto la funzione ‘rrand’, ma proviamo a riavviarla di nuovo. Il risultato è un numero casuale contenuto all’interno di due valori. Questo significa che non otterremo mai il valore esatto dei due numeri estremi ma sempre numeri contenuti in questo intervallo. I numeri saranno sempre dei numeri decimali, ovvero non dei numeri interi ma piuttosto delle frazioni di un numero. Per esempio, proviamo a osservare i numeri che escono da: ‘rrand(20,110)’:
Può capitare di avere bisogno di un numero casuale che sia intero e non decimale. Qui entra in gioco la funzione rrand_i
. Funziona in modo simile a rrand
con la differenza che può restituire il valore minimo e massimo come possibili valori (si tratta, infatti, di una funzione inclusiva). Questi sono degli esempi di valori restituiti da rrand_i(20, 110)
:
Questa funzione restituirà un numero compreso tra 0 (incluso) e il valore massimo specificato (escluso). Di default restituirà un valore compreso tra 0 e 1. Ad esempio, può essere usata per scegliere un valore casuale per amp:
:
loop do
play 60, amp: rand
sleep 0.25
end
Dal momento che rrand_i
e rrand
si comportano in modo simile, rand_i
restituirà un numero intero compreso tra 0 e il valore massimo specificato.
A volte vuoi simulare il lancio di un dato. Questo è un caso specifico della funzione rrand_i
dove il valore più basso è sempre 1. Quando utilizziamo la funzione dice
dobbiamo specificare il numero di facce del dado. Un dado comune ha 6 facce, quindi dice(6)
può restituire i valori 1, 2, 3, 4, 5 oppure 6. Ciononostante, come avviene nei giochi di ruolo fantasy, può capitare di usare dadi a 4 facce, a 12, 20 oppure a 120!
Infine può capitare di voler simulare l’uscita del punteggio più alto di un dado (6, nel caso di un dado comune). La funzione one_in
restituisce true con una probabilità di uno sul numero di facce del dado. Di conseguenza one_in(6)
restituirà true con una probabilità di 1/6 e false negli altri casi. I valori true e false sono molto utili quando si utilizzano i costrutti if
di cui parleremo più avanti.
È arrivato il momento di sperimentare un po’ di casualità nel tuo codice!
Adesso che hai imparato come creare i suoni attraverso l’uso delle funzioni ‘play’ e ‘sample’ e che hai creato semplici melodie e ritmi utilizzando la funzione ‘sleep’ combinata con le precedenti, ti starai chiedendo che cos’altro può offrirti il mondo della programmazione…
Bene, ti aspetta qualcosa di davvero eccitante! Ci risulta che le strutture basilari della programmazione, come i concetti di loop, condizionali, funzioni e catene ti mettono in mano degli strumenti davvero potenti per esprimere le tue idee musicali.
Cominciamo a vedere come funzionano questi elementi di base…
Una struttura che vedrai molto spesso utilizzando Sonic Pi è il blocco. I blocchi ci permettono di fare delle cose molto utili con pezzi di codice notevolmente lunghi. Per esempio, abbiamo visto come con i parametri dei sintetizzatori e dei campioni eravamo in grado di cambiare qualcosa che accadeva soltanto all’interno di una singola linea di programma. Però a volte potremmo voler fare qualcosa che abbia effetto su diverse linee di programma e non una sola. Per esempio, potremmo volerle mettere in loop, aggiungerci un riverbero, avviarlo soltanto una volta ogni cinque cicli e così via. Prendi in considerazione il codice che segue:
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
Per fare qualcosa con un pezzo di codice, dobbiamo dire a Sonic Pi dove il blocco inizia e finisce. Per indicare l’inizio, il linguaggio di Sonic Pi utilizza il termine ‘do’ mentre per indicare la fine utilizza il termine ‘end’. Per esempio:
do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Tuttavia, questo ancora non è completo e infatti non è funzionante (prova tu stesso/a ad avviarlo e otterrai un errore). Infatti non abbiamo detto a Sonic Pi cosa deve fare con il blocco in questione. Dobbiamo indicare l’azione da compiere scrivendo un codice particolare dopo il ‘do’. Vedremo una serie di esempi in seguito, all’interno di questa guida. Per il momento è importante sapere che avvolgendo il codice all’interno di ‘do’ e ‘end’ comunichi a Sonic Pi la tua intenzione di fare qualcosa di particolare con quelle linee di codice.
Fino a questo momento, abbiamo passato molto tempo a spiegare i differenti suoni che puoi ottenere utilizzando le funzioni ‘play’ e ‘sample’. Hai anche imparato come scansionare il tempo tra i suoni attraverso la funzione ‘sleep’.
Come avrai probabilmente scoperto, puoi divertirti un sacco con questi blocchi basilari. Tuttavia, quando comincerai a utilizzare il potere del codice per strutturare le tue composizioni e la tua musica, tutta una nuova dimensione di divertimento ti si aprirà davanti. Nelle prossime sezioni, illustreremo alcuni di questi potenti strumenti. I primi saranno le iterazioni e gli anelli.
Hai mai scritto una stringa di codice che ti piacerebbe ripetere alcune volte? Per esempio, qualcosa tipo:
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
Che cosa dobbiamo fare se vogliamo ripetere questo codice tre volte? Bene, potremmo semplicemente copiarlo e incollarlo per tre volte di seguito:
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
Certo che è proprio un codice lunghissimo! Che cosa accadrebbe se tu volessi cambiare il campione indicato con ‘elec_plip’? Dovresti trovare tutti i punti in cui è menzionato l’originale, cioè ‘elec_blup’, e cambiarlo. Ma ancora peggio, che cosa accadrebbe se tu volessi ripetere il codice originale per 50 o adirittura 1000 volte? A questo punto avresti un codice enorme, con un sacco di linee da variare se tu volessi effettuare un qualsiasi cambiamento.
Ripetere più volte una o più stringhe di codice può essere semplice come dire fai questo tre volte. Alla fine, è proprio questo che faremo. Ti ricordi del nostro vecchio amico chiamato blocco di codice? Possiamo utilizzarlo per indicare l’inizio e la fine di un gruppo di codice che vogliamo ripetere per tre volte. Quindi, invece di scrivere fai questo tre volte, noi scriveremo ‘3.times do’. Non è troppo difficile, vero? Devi solo ricordare di scrivere ‘end’ alla fine del codice che vuoi ripetere:
3.times do
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
end
Non è molto più facile che fare copia e incolla? Possiamo usare questa struttura per creare un sacco di strutture interessanti fatte con la ripetizione:
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
Possiamo anche mettere le iterazioni una dentro l’altra per creare delle strutture interessanti. Per esempio:
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
Se volessi che un blocco di codice si ripetesse tante volte, potresti trovare utile l’utilizzo di numeri grandi come ‘1000.times do’. In questi casi, però, faresti forse meglio a dire a Sonic Pi di ripetere il blocco all’infinito (o almeno finché non premi stop!). Proviamo a creare un anello con il campione amen_break:
loop do
sample :loop_amen
sleep sample_duration :loop_amen
end
Un’aspetto importante da sapere degli anelli è che essi si comportano come dei buchi neri per il codice. Infatti, una volta che il codice entra in un anello, non riesce più a uscirne finché non premi stop. Il codice continuerà a girare in cerchio all’infinito. Quindi, se hai scritto del codice successivamente a un anello, questo non verrà mai eseguito. Nel caso seguente il piatto scritto dopo l’anello non suonerà mai:
loop do
play 50
sleep 1
end
sample :drum_cymbal_open
Adesso puoi cominciare a strutturare il tuo codice inserendo le iterazioni e gli anelli, vai!
Una cosa che probabilmente vorrai fare è non soltanto suonare note casuali (se vuoi riguardati la sezione precedente sulla casualità) ma anche prendere decisioni casuali e basate sul risultato ottenuto da una o un’altra stringa di codice precisa. Per esempio, potresti voler suonare in maniera casuale un tamburo o un piatto. Possiamo ottenere quanto detto sopra utilizzando la funzione ‘if’.
Quindi, tiriamo una moneta: se fosse testa, suona un tamburo, se fosse croce, suona un piatto. Facile no? Possiamo imitare il comportamento del lancio di una moneta con la funzione ‘one_in’ (introdotto nella sezione sulla casualità) specificando la probabilità di 1 ogni 2: ‘one_in(2)’. Possiamo quindi utilizzare i risultati di questa funzione per decidere quali di due stringhe di codice scegliere, quello del tamburo o quello del piatto:
loop do
if one_in(2)
sample :drum_heavy_kick
else
sample :drum_cymbal_closed
end
sleep 0.5
end
Tieni conto che la struttura di ‘if’ è composta di tre parti:
Di solito all’interno dei linguaggi di programmazione, la nozione di sì è definita come ‘vera’, mentre la nozione di no è definita come ‘falsa’. Quindi dobbiamo trovare una domanda che ci dia una risposta ‘vera’ o ‘falsa’, il che è esattamente quello che la funzione ‘one_in’ fa.
Fai caso a come la prima scelta è inclusa tra la parola ‘if’ e la parola ‘else’ e invece la seconda scelta è tra ‘else’ e ‘end’. Funziona ugualmente alla struttura ‘do/end’, dove puoi inserire più linee di codice in ogni posizione. Per esempio:
loop do
if one_in(2)
sample :drum_heavy_kick
sleep 0.5
else
sample :drum_cymbal_closed
sleep 0.25
end
end
Nel caso precedente, abbiamo creato suoni di lunghezza diversa attraverso la funzione ‘sleep’ a seconda della scelta eseguta.
A volte puoi aver bisogno di creare un’opzione per eseguire una linea di codice. Puoi fare questo costruendo la struttura di ‘if’ e ponendo la domanda alla fine. Per esempio:
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
Il codice scritto precedentemente suonerà un accordo composto da un numero sempre differente di note dipendente dal grado diverso di probabilità attribuito all’esecuzione di ogni nota.
Quindi per il momento hai creato un ritmo coinvolgente e un basso che ti entra dentro. Come puoi fare a suonarli contemporaneamente? Una delle soluzioni è di intrecciarli a mano: suona un po’ di bassi, poi qualche colpo di batteria, poi ancora bassi…Tuttavia, la loro sincronizzazione può diventare presto difficile, specialmente quando cominci ad aggiungere numerosi elementi.
Che ne dici se Sonic Pi intrecciasse i vari strumenti per te, automaticamente? Bene, non ci crederai ma Sonic Pi può farlo per te! E lo può fare utilizzando una funzione speciale chiamata thread, ovvero tessitura.
Per fare un esempio semplice, devi immaginarti che il codice che segue sia un basso che pompa e un ritmo coinvolgente:
loop do
sample :drum_heavy_kick
sleep 1
end
loop do
use_synth :fm
play 40, release: 0.2
sleep 0.5
end
Come abbiamo detto in precedenza, gli anelli sono delle specie di buchi neri per il programma. Una volta che entri all’interno di un anello non puoi più uscirne finché non premi stop. Quindi, come facciamo a suonare entrambi gli anelli contemporaneamente? Dobbiamo dire a Sonic Pi che vogliamo iniziare diverse parti di codice nello stesso momento. Questo è quello che fa la funzione thread.
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
Abbiamo messo all’interno di una struttura ‘in_thread’, composta da un blocco do/end, il primo anello. Questo comunica a Sonic Pi di eseguire il contenuto di questo blocco esattamente nello stesso momento del codice presente dopo il blocco (che in questo caso è il secondo anello). Prova a eseguirlo e potrai sentire sia la batteria sia il basso contemporaneamente!
Proviamo adesso a inserire un synth all’inizio:
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
Ci ritroviamo con lo stesso problema di prima. Il primo anello è suonato contemporaneamente al secondo, grazie a ‘in_thread’. Però il terzo anello non viene mai eseguito. Dobbiamo quindi aggiungere un altro ‘filo’ al tessuto:
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
Potrebbe sorprenderti il fatto che, quando premi il bottone ‘run’, in realtà stai creando un nuovo filo di codice da eseguire. Questo spiega perché quando premi il tasto più volte, il suono si sovrappone a quello che che è già in esecuzione. Visto che ogni esecuzione è un filo di codice, questi fili vengono intrecciati automaticamente.
Via via che scoprirai tutti i segreti di Sonic Pi, imparerai come questi ‘tessuti’ di suoni sono in realtà i mattoni principali con cui costruire la tua musica. Uno dei compiti principali di questi tessuti è quello di isolare la nozione di impostazioni correnti da quello degli altri orditi. Che cosa significa? Per esempio, quando associ un synth a un blocco utilizzando ‘use_synth’ stai associandolo soltanto a quel blocco e non ad altri. Vediamo un esempio:
play 50
sleep 1
in_thread do
use_synth :tb303
play 50
end
sleep 1
play 50
Hai sentito come il suono di mezzo era differente dagli altri? La funzione ‘use_synth’ aveva effetto soltanto sul blocco in cui era incluso e non sugli altri blocchi all’esterno.
Quando crei un nuovo filone, un nuovo ordito utilizzando ‘in_thread’, quest’ultimo erediterà automaticamente tutte le impostazioni correnti da quello precedente. Prova a dare un’occhiata qui:
use_synth :tb303
play 50
sleep 1
in_thread do
play 55
end
Hai visto che la seconda nota è suonata con il timbro del synth ‘:tb303’ nonostante questo appartenesse a un altro blocco? Qualsiasi impostazione che viene modificata utilizzando la stringa ‘use_*’ si comporterà nello stesso modo.
Quando i fili di codice vengono creati, ereditano tutte le impostazioni dai fili ‘genitori’, ovvero quelli che li hanno generati. Tuttavia, le modifiche effettuate nel codice ‘figlio’ non hanno nessun effetto sui ‘genitori’.
Per concludere, se vogliamo, possiamo dare dei nomi ai nostri fili di codice:
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
Dai uno sguardo alla sezione di destra quando esegui questo codice. Qui vengono visualizzati tutti i codici eseguiti. Vedi come questo ‘diario’ riporta il nome del filo da noi creato accoppiato con il messaggio?
[Run 36, Time 4.0, Thread :bass]
|- synth :prophet, {release: 0.6, note: 47}
Un’ultima cosa da sapere a proposito dei nomi è che non possono essere eseguiti due fili con lo stesso nome contemporaneamente. Proviamo a dare un’occhiata a questa caratteristica. Leggi il codice seguente:
in_thread do
loop do
sample :loop_amen
sleep sample_duration :loop_amen
end
end
Vai avanti e incollalo all’interno di una finestra e premi Run. Prova a premerlo ancora un paio di volte. Ascolta per un po’ la cacofonia creata da più campioni ‘amen_break’ che suonano contemporaneamente ma fuori tempo. Bene, adesso puoi premere stop.
Questo è il comportamento che abbiamo osservato numerose volte, ovvero: se premi Run, i suoni si sovrappongono agli altri già in esecuzione. Quindi, se hai un anello e premi Run tre volte, otterrai tre strati di suono che sono eseguiti contemporaneamente.
Con i fili ai quali è stato attribuito un nome, è tutta un’altra cosa:
in_thread(name: :amen) do
loop do
sample :loop_amen
sleep sample_duration :loop_amen
end
end
Prova a premere Run numerose volte inserendo questo codice. Potrai ascoltare un solo ‘amen_break’. Puoi verificare il perché leggendo nella finestra a destra:
Visualizzerai questo messaggio ==> Skipping thread creation: thread with name :amen already exists.
Sonic Pi, che parla inglese, ti sta dicendo che il filo di codice chiamato ‘:amen’ è già in esecuzione, quindi non ne può creare un altro.
Questo comportamento potrebbe non sembrarti particolarmente utile adesso, ma invece lo sarà quando cominceremo a fare live coding, ovvero a suonare dal vivo…
Quando cominci ad avere dei codici molto lunghi, potresti sentire il bisogno di organizzare e strutturare le cose per renderle più pulite e chiare da comprendere. Le funzioni sono un modo molto efficace per farlo. Ci consentono di dare un nome a un insieme di linee. Diamo un’occhiata a questa possibilità.
define :foo do
play 50
sleep 1
play 55
sleep 2
end
Qui sopra, abbiamo definito una nuova funzione chiamandola ‘foo’. L’abbiamo fatto usando la nostra vecchia conoscenza, il blocco do/end, accoppiato alla parola magica ‘define’, seguita dal nome che abbiamo voluto dare alla funzione. Non dobbiamo per forza chiamarla ‘foo’ ma possiamo usare un nome qualsiasi, come ‘bar’, ‘baz’ o qualsiasi cosa che ci aiuti a ricordarne il ruolo, come ‘sezione_principale’ o ‘riff_principale’. Si può usare un termine in qualsiasi lingua.
Ricorda sempre di anteporre i due punti ‘:’ al nome della funzione quando vai a definirla.
Una volta che abbiamo definito la nostra funzione, possiamo poi richiamarla semplicemente scrivendo il suo nome:
define :foo do
play 50
sleep 1
play 55
sleep 0.5
end
foo
sleep 1
2.times do
foo
end
Possiamo utilizzare ‘foo’ anche dentro un blocco di iterazione o ovunque abbiamo scritto ‘play’ o ‘sample’. Questo ci permette di esprimere i nostri pensieri musicali e di creare delle parole con un senso preciso da utilizzare nelle nostre composizioni.
Fin qui, ogni volta che hai premuto Run, Sonic Pi ha iniziato da zero. Il sistema non conosceva niente più di quello che era scritto della finestra. Non puoi richiamare un codice tra una finestra e l’altra o tra un gruppo di codice e l’altro. Le funzioni sono diverse. Quando ne hai definita una, Sonic Pi si ricorda di lei. Prova. Cancella tutto il codice che hai scritto e sostituiscilo con questo:
foo
Premi Run e ascolta la fuzione in esecuzione. Dov’è finito il codice? Come fa Sonic Pi a sapere cosa eseguire? Sonic Pi, semplicemente, si ricorda della tua funzione, quindi anche se l’ha cancellata dalla finestra, si ricorda che cosa avevi digitato. Tutto ciò funziona soltanto se le funzioni sono state create utilizzando ‘define’ (e ‘defonce’).
Potresti essere interessato/a a sapere che, nello stesso modo in cui puoi passare da valori minimi a massimi o addittura casuali (‘rrand’), puoi insegnare alle tue funzioni ad accettare degli argomenti. Prova a dare un’occhiata a quanto segue:
define :my_player do |n|
play n
end
my_player 80
sleep 0.5
my_player 90
Quanto presentato non è molto eccitante, ma illustra bene la questione. Abbiamo creato la nostra personale versione di ‘play’ chiamata ‘my_player’ che è stata poi sottoposta a dei parametri.
I parametri devono essere scritti successivmente al ‘do’ del blocco do/end ‘define’. Devono essere inclusi nelle barre verticali ‘ | ’ ed essere separati dalle virgole ‘,’. Puoi usare una qualsiasi parola a tuo piacimento per dare il nome ai parametri. |
La magia accade sempre all’interno del blocco do/end ‘define’. Puoi usare anche i nomi dei parametri come se fossero dei valori reali. Nell’esempio precedente noi stavamo suonando la nota ‘n’. Puoi considerare i parametri come una sorta di promessa che quando il codice è in esecuzione, essi verranno sostituiti con valori reali. Puoi fare ciò passando un parametro a una funzione quando lo richiami. Scrivendo il codice precedente, quanto detto è stato ottenuto digitando ‘my_player 80’ per suonare la nota corrispondente. All’interno della definizione della funzione, ‘n’ è sostituito con 80. Quindi se scrivi ‘play n’ la n verrà sostituita con 80. Se richiamassi di nuovo questa funzione scrivendo ‘my_player 90’, il valore n diventerebbe 90 e quindi scrivendo ‘play n’ otteniamo questa volta lo stesso suono di ‘play 90’.
Ma guardiamo un esempio più interessante:
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
Qui abbiamo digitato ‘repeats’ come se fosse un numero nella linea ‘repeats.times do’. Abbiamo inserito ‘roots’ come se fosse un nome di una nota all’interno dell’esecuzione di ‘play’.
Guarda come, grazie alle funzioni, riusciamo a scrivere qualcosa di molto espressivo, semplice da leggere e che compatta tutti i nostri ragionamenti!
Una cosa che può risultarti utile è quella di creare nomi da assegnare alle cose. Sonic Pi rende questo processo molto semplice: basta che scrivi il nome desiderato, il segno uguale (‘=’), e dopo la cosa che vuoi ricordarti:
sample_name = :loop_amen
Nell’esempio sopra ci siamo ‘ricordati’ il simbolo ‘:loop_amen’ grazie alla variabile ‘sample_name’. Adesso, possiamo utilizzare ‘sample_name’ ovunque avremmo usato ‘:loop_amen’. Ecco un esempio:
sample_name = :loop_amen
sample sample_name
Ci sono tre ragioni principali che rendono utile l’impiego di variabili in Sonic_Pi: comunicare significati, organizzare le ripetizioni e catturare i risultati delle cose.
Quando programmi è facile pensare semplicemente che stai dicendo al computer come fare qualcosa. E finché il computer capisce, va tutto bene! Tuttavia, è importante tenere a mente che non solo il computer legge il codice,ma anche altre persone potrebbero farlo per capire cosa sta succedendo. Inoltre, è probabile che tu stesso/a andrai prima o poi a rileggere il tuo codice e cercare di capire a che cosa serve. Anche se adesso qualche passaggio ti sembra ovvio, potrebbe non esserlo per qualcun altro o per te stesso/a nel futuro!
Un modo per aiutare gli altri a comprendere il tuo programma è scrivere commenti (come abbiamo visto nella sezione precedente. Un altro modo è usare dei nomi di variabili che abbiano un significato. Per esempio, guarda il codice seguente:
sleep 1.7533
Perché in questo codice è scritto il numero ‘1,7533’? Da dove salta fuori? Che cosa significa? Guarda invece questo codice:
loop_amen_duration = 1.7533
sleep loop_amen_duration
Adesso è molto più chiaro a cosa si riferisce ‘1,7533’:è la durata del campione ‘:loop_amen’! Adesso, potresti domandarti perché non scrivere semplicemente:
sleep sample_duration(:loop_amen)
Questa è certamente un modo molto semplice e carino di comunicare lo scopo di un codice.
Spesso può succedere che nel codice ci siano molte ripetizioni e quando vuoi cambiare qualcosa, è necessario farlo in molti punti. Guarda questo esempio:
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)
Facciamo un sacco di cose con :loop_amen
! E se volessimo sentire la stessa cosa ma con un loop diverso come, ad esempio, :loop_garzul
? Saremmo costretti a trovare e rimpiazzare tutti i :loop_amen
con :loop_garzul
. Potresti farlo se avessi a disposizione molto tempo ma se ti stai esibendo su un palco? Spesso non hai il lusso di avere molto tempo, specialmente se non vuoi che la gente smetta di ballare.
E se avessimo scritto il codice in questo modo:
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)
Questo codice fa esattamente la stessa cosa di quello di prima (prova) ma ci dà la possibilità di cambiare una riga di codice sample_name = :loop_amen
in sample_name = :loop_garzul
e, grazie a questa variabile magica, verrà cambiato dappertutto.
Un buon motivo per utilizzare le variabili è la possibilità di catturare i risultati delle cose. Per esempio, magari vuoi provare a lavorare con la durata di un sample:
sd = sample_duration(:loop_amen)
Ora possiamo usare sd
in ogni punto dove abbiamo bisogno della durata del camptione :loop_amen
.
Un risultato ancora più importante, forse, è che una variabile ci permette di catturare il risultato quando chiamiamo play
o sample
:
s = play 50, release: 8
Ora che abbiamo catturato s
come variabile, possiamo controllare il sintetizzatore mentre sta funzionando:
s = play 50, release: 8
sleep 2
control s, note: 62
Vedremo come controllare i sintetizzatori in modo più dettagliato più tardi in questa sezione.
Mentre le variabili sono ottime per assegnare nomi alle cose ed acquisire i relativi risultati, è importante sapere che dovrebbero essere generalmente usate in locale all’interno di un thread. Per esempio, non fare questo:
a = (ring 6, 5, 4, 3, 2, 1)
live_loop :sorted do
a = a.sort
sleep 0.5
puts "sorted: ", a
end
live_loop :shuffled do
a = a.shuffle
sleep 0.5
end
Nell’esempio di sopra, assegniamo un cerchio di numeri a un variabile a
e poi l’usiamo in due live_loop
(cicli dinamici) diversi. Nel primo live_loop
, ogni 0.5
secondi, ordiniamo il cerchio (a (ring 1,2,3,4,5,6)
) e lo stampiamo sul log. Se esegui il codice, trovi che l’elenco stampato non è sempre ordinato!. Questo forse ti sorprenderà — specialmente che a volte l’elenco viene stampato in ordine e a volte no. Questo si chiama comportamento “non-deterministico” ed è il risultato di un problema piuttosto difficile che si chiama “condizione di gara”. Il problema è dovuto al fatto che anche il secondo ciclo sta manipolando l’elenco (in questo caso, rimescolandolo) e al punto che l’elenco viene stampato, alcune volte è appena stato ordinato ed alcune volte è appena stato rimescolato. Entrambi i cicli fanno una gara di fare qualcosa differente con lo stesso variabile ed ogni volta “vince” un ciclo diverso.
Esistono due soluzioni a questo. Prima, non usare lo stesso variable in cicli o thread molteplici. Per esempio, il codice seguente sempre stamperà un elenco ordinato perché ogni ciclo ha un proprio variabile:
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
Comunque, a volte vogliamo condividere cose fra diversi thread. Per esempio, la chiave attuale, BPM, sintetizzatore, ecc. In questi casi, la soluzione è usare il sistema speciale di stato “thread-safe” (sicuro per i thread) di Sonic Pi attraverso le funzioni get
e set
. Questo si descrive dopo, nella sezione 10.
Raggiungendo un livello avanzato di live coding e usando molte funzioni e thread simultaneamente, ti sarai accordo che è semplice fare un errore che ferma un thread. Non è un problema perché puoi sempre farlo ripartire premendo Run ma, quando si riavvierà, sarà fuori tempo rispetto al thread originale.
Come abbiamo discusso in precedenza, i nuovi thread creati con in_thread
ereditano le impostazioni dal thread principale. Questo include, ovviamente, anche il tempo. Questo significa che i thread sono sempre a tempo quando partono in simultanea.
Tuttavia, quando fai partire un thread da solo, questo partirà con il suo tempo ed è davvero improbabile che sia sincronizzato con gli altri thread.
Sonic Pi offre una soluzione a questo problema con le funzioni cue
e sync
.
La funzione cue
ci permette di inviare il messaggio del cuore pulsante a tutti gli altri thread. Di default, gli altri thread non sono interessati a ricevere questo messaggio e lo ignorano. È possibile, però, attivare l’interesse al segnale utilizzando la funzione sync
.
La cosa importante da sapere è che sync
funziona in modo simile a sleep
nel senso che ferma il thread corrente per un certo periodo di tempo. La differenza è che con sleep
specifichiamo quanto tempo aspettare mentre con sync
non è possibile sapere quando aspetterà dal momento che sync
aspetta il segnale cue
da un altro thread che potrebbe essere vicino oppure lontano nel tempo.
Proviamo ad andare nel dettaglio:
in_thread do
loop do
cue :tick
sleep 1
end
end
in_thread do
loop do
sync :tick
sample :drum_heavy_kick
end
end
Qui abbiamo due thread, uno che si comporta come un metronomo e non riproduce alcun suono ma invia il segnale :tick
a ogni battito. Il secondo thread è sincronizzato al messaggio tick
e quando ne riceve uno, eredita il tempo del thread cue
e continua a funzionare.
Di conseguenza, sentiremo il campione :drum_heavy_kick
esattamente nel momento in cui l’altro thread invia il messaggio :tick
, anche se i due thread non vengono avviati in contemporanea:
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
Quella chiamata a sleep
normalmente manderebbe il secondo thread fuori fase rispetto al primo, ma, dal momento che usiamo cue
e sync
, sincronizziamo automaticamente i thread bypassando ogni possibile deviazione di tempo.
Sei libero di usare tutti i nomi che vuoi per i messaggi cue
, non solo :tick
. Devi solo assicurarti che tutti i thread siano sincronizzati sullo stesso nome, altrimenti aspetteranno all’infinito (o, fino alla pressione del pulsante di Stop).
Facciamo qualche prova con diversi nomi per 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
Qui abbiamo un loop principale cue
che in modo casuale invia segnali chiamati :foo
, :bar
o :baz
. Abbiamo poi tre thread di loop con suoni differenti, ciascuno dei quali si sincronizza con quei segnali in modo indipendente. L’effetto rete fa si che sentiamo un suono ogni 0.5 battiti dal momento che ciascuno dei thread sync
è sincronizzato in modo casuale con i thread cue
che riproducono il campione.
Questo ovviamente funziona se ordini i thread al contrario dal momento che i thread sync
aspetteranno di ricevere il cue
successivo.
Uno degli aspetti più gratificante e divertente di Sonic Pi è la possibilità di aggiungere effetti ai tuoi suoni in modo semplice. Per fare un esempio, può succedere che tu voglia aggiungere un po’ di riverbero ad alcune parti del tuo brano, oppure un po’ di echo oppure distorsione e tremolo alle tue linee di basso.
Sonic Pi ti permette di aggiungere potenti effetti in modo semplice. Ti consente di collegarli in catena tra loro (così puoi passare il tuo suono prima dal distorsore, poi dall’echo e, infine, dal riverbero) e di controllare i parametri di ciascuno individualmente (in modo simile a come abbiamo fatto con synth e campioni). È possibile modificare i parametri dell’effetto mentre sta funzionando per cui, ad esempio, puoi aumentare il riverbero sul basso mentre riproduci la traccia…
Se tutto questo ti sembra complicato, non preoccuparti. Quando comincerai a giocare con gli effetti, diventerà tutto più chiaro. Prima di cominciare è giusto fare un’analogica con gli effetti per chitarra. Ci sono una miriade di pedali che puoi comprare: alcuni aggiungono riverbero, altri distorsione ecc… Un chitarrista connetterà la sua chitarra in un pedale (per esempio il distorsore), poi prenderà un altro cavo e collegherà in catena un pedale di riverbero. L’output del riverberò può, infine, essere collegato dentro l’amplificatore:
Guitar -> Distortion -> Reverb -> Amplifier
Questo processo è chiamato catena di effetti. Sonic Pi si comporta esattamente in questo modo. Spesso i pedali hanno manopole che permettono di controllare quanta distorsione, riverbero, echo, ecc… applicare al suono. Sonic Pi supporta anche questo tipo di controlli. Infine, puoi immaginare un chitarrista che suona mentre qualcun altro gioca con gli effetti. Sonic Pi ti permette di fare anche questo ma invece di avere qualcun altro a controllare le cose al posto tuo, ci pensa il computer.
Esploriamo gli effetti!
In questa sezione, analizzeremo un paio di effetti: riverbero e echo. Vedremo insieme come usarli, come controllare i loro parametri e come collegarli in sequenza.
Il sistema di effetti di Sonic Pi utilizza dei blocchi. Se non hai ancora letto la sezione 5.1, ti consiglio di dargli un’occhiata veloce prima di andare avanti.
Se vogliamo usare un riverbero, scriviamo with_fx :reverb
nel nostro blocco di codice, così:
with_fx :reverb do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Prova a suonare questo codice e sentirai che c’è del riverbero. Suona bene, vero? Tutto suona bene con un po’ di riverbero.
Ora vediamo cosa succedete se abbiamo del codice al di fuori del blocco 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 come la nota finale play 55
viene riprodotta senza riverbero. Questo perché è fuori dal blocco do/end, quindi non viene catturata dal riverbero.
Allo stesso modo, se riproduci un suono prima del blocco do/end, anche questi non verranno catturati dall’effetto:
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
Ci sono molti effetti da cui scegliere. Perché non provare con un po’ di echo?
with_fx :echo do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Uno delle caratteristiche più importanti dei blocchi di codice degli effetti è che possiamo passargli dei parametri come abbiamo già visto con play
e sample
. Per esempio, un parametro dell’echo con cui giocare è phase:
che rappresenta la durata dell’echo in battiti. Rendiamo l’effetto più lento:
with_fx :echo, phase: 0.5 do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Ora rendiamolo più veloce:
with_fx :echo, phase: 0.125 do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Facciamo in modo che l’echo abbia un fade out più lungo impostando il valore di decay:
a 8 battiti:
with_fx :echo, phase: 0.5, decay: 8 do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Un’altra caratteristica molto importante è la possibilità di nidificare gli effetti. Questo ci permette di collegare in modo semplice un effetto all’altro. Se volessimo, ad esempio, suonare un po’ di codice con l’eco e il riverbero? Facile! Inseriamo un effetto dentro l’altro:
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
Pensa all’audio che passa dall’uno all’altro. Il suono del codice all’interno del blocco do/end (ad esempio play 50
) è inviato prima all’echo e poi, il suono effettato, è inviato al riverbero.
Possiamo andare a fondo con la nidificazione per generare risultati assurdi. Attenzione, però, gli effetti potrebbero richiedere molte risorse: quando nidifichi un’effetto dentro un altro, stai, di fatto, utilizzando più effetti contemporaneamente. Sii parco con gli effetti, specialmente se utilizzi piattaforme con poca potenza di calcolo come il Raspberry Pi.
Sonic Pi ha al suo interno un gran numero di effetti con cui puoi giocare. Per scoprire quelli che puoi usare, clicca su FX nella parte più a sinistra di questo help. Questi sono i miei preferiti:
Ora sbizzarrisciti con gli effetti e inseriscili ovunque per ottenere nuove sonorità!
Anche se dall’esterno possono sembrare semplici, gli effetti sono, in realtà, molto complessi al loro interno. Data la loro semplicità di utilizzo, spesso le persone ne abusano. Questo potrebbe non essere un problema se hai una macchina potente ma se, come me, usi un Rasberry Pi, devi fare attenzione a quante risorse chiedi alla macchina se vuoi essere sicuro che non ci siano interruzioni.
Guarda questo esempio:
loop do
with_fx :reverb do
play 60, release: 0.1
sleep 0.125
end
end
Con questo codice suoniamo la nota 60 con un tempo di rilascio molto breve. Siccome vogliamo del riverbero, abbiamo aggiunto un blocco di codice. Fin qui tutto bene, anche se…
Proviamo a vedere cosa fa esattamente il codice. Per prima cosa abbiamo un loop
che significa che tutto quello che c’è al suo interno viene ripetuto all’infinito. Poi abbiamo un blocco with_fx
. Questo significa che verrà creato un nuovo riverbero ogni ripetizione del loop. È come, sulla chitarra, avere un pedale del riverbero diverso per ogni corda. È figo poterlo fare ma non sempre è quello che vogliamo. Per esempio questo codice fa fatica a girare su un Raspberry Pi. La creazione del riverbero, l’utilizzo e il suo spegnimento sono gestiti da with_fx
e questo potrebbe consumare preziosa potenza di calcolo.
Come possiamo fare per rendere il setup simile a quello dei chitarristi che hanno un pedale di riverbero dentro cui passa tutto il segnale? Molto semplice:
with_fx :reverb do
loop do
play 60, release: 0.1
sleep 0.125
end
end
Dobbiamo spostare il loop dentro il blocco with_fx
. In questo modo creiamo un solo riverbero per tutte le note suonate nel nostro loop. Questo codice è molto più efficiente e funziona a meraviglia su un Rasberry Pi.
Un compromesso potrebbe essere usare with_fx
in un’iterazione dentro a un loop:
loop do
with_fx :reverb do
16.times do
play 60, release: 0.1
sleep 0.125
end
end
end
In questo modo abbiamo tolto with_fx
dalla parte interna del loop
e creiamo un riverbero ogni 16 note.
Questo è un modo di fare talmente comune che with_fx
lo supporta come opzione senza la necessità di scrivere un blocco di ripetizione 16.times
:
loop do
with_fx :reverb, reps: 16 do
play 60, release: 0.1
sleep 0.125
end
end
I blocchi di codice con reps: 16
e 16.times do
funzionano allo stesso modo. Quello con reps: 16
in pratica ripete il codice nel blocco do/end
16 volte per cui puoi usare entrambi i sistemi in modo intercambiabile scegliendo quello che preferisci.
Ricorda: non ci sono errori, solo possibilità. Tuttavia alcuni di questi approcci genereranno suoni e performance differenti. Fai un po’ di prove e trova l’approccio che, secondo te, suona meglio tenendo sempre in considerazione la questione delle performance della tua piattaforma.
Finora abbiamo visto come lanciare synth e campioni e come cambiare i loro parametri di default come il volume, il pan, l’inviluppo ecc… Ogni suono lanciato è, essenzialmente, un singolo suono con la sua lista di opzioni di durata.
Non sarebbe bello poter cambiare i parametri di un suono mentre viene riprodotto, proprio come se stessimo facendo un bending sulla corda di una chitarra?
Siete fortunati, questa sezione vi spiegherà esattamente come farlo.
Finora ci siamo preoccupati solo di lanciare nuovi suoni ed effetti. Ciononostante Sonic Pi ci dà la possibilità di manipolare e controllare tutti i suoni in riproduzione. Lo possiamo fare utilizzando una variabile:
s = play 60, release: 5
Qui abbiamo una variabile locale s
che rappresenta il sintetizzatore che suona la nota 60. Nota bene: si tratta di una variabile locale che non può essere richiamata da altre funzioni.
Ora che abbiamo s
, possiamo cominciare a controllarlo utilizzando la funzione 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
Notiamo come non stiamo utilizzando 4 synth differenti, stiamo utilizzando un solo sintetizzatore cambiando il pitch della nota 3 volte mentre sta suonando.
Possiamo passare tutti i parametri standard attraverso control
, per cui possiamo controllare cose come amp:
, cutoff:
oppure pan:
.
Alcuni parametri non possono essere modificati una volta che il synth è partito, per esempio l’inviluppo ADSR. Puoi scoprire quali parametri puoi modificare guardando nella documentazione. Se trovi scritto non può essere modificato una volta impostato, saprai che non puoi modificarlo una volta avviato il synth.
È possibile controllare anche gli effetti, anche se bisogna farlo in modo leggermente differente:
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
Invece di utilizzare una variabile, utilizziamo un parametro di riferimento nel blocco do/end. Dentro le barre |
, dobbiamo specificare un nome univoco per ogni effetto che poi richiamiamo all’interno del blocco do/end. Questo comportamento è identico all’utilizzare funzioni parametrizzate.
Ora prova a controllare qualche synth ed effetto!
Esplorando i parametri dei synth e degli effetti avrai notato come alcuni di essi terminano con _slide
. Magari hai anche provato a richiamarli ma senza alcun risultato. Questo succede perché, a differenza dei normali parametri, funzionano solo quando controlli il synth come discusso nella sezione precedente.
Considera il seguente esempio:
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
Puoi sentire il pitch del sintetizzatore cambiare a ogni chiamata di control
. Può capire, però, che ci sia uno slide tra i vari cambiamenti. Siccome stiamo controllando il parametro note:
, per aggiungere lo scorrimento, dobbiamo impostare il parametro note_slide
:
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
Ora sentiamo che la nota viene “piegata” ogni volta che control
viene richiamato. Suona bene, vero? Possiamo velocizzare lo slide utilizzando un tempo inferiore come note_slide: 0.2
o rallentarlo usando valori più lunghi.
Ogni parametro che puoi controllare, ha un parametro corrispettivo _slide
con cui puoi giocare.
Ogni volta che imposti un parametro _slide
su un synth in riproduzione, verrà ricordato e usato ogni volta che scorri il parametro corrispondente. Per fermare lo slide, devi impostare il valore di _slide
a 0 prima del successivo control
.
È possibile controllare lo scorrimento degli effetti:
with_fx :wobble, phase: 1, phase_slide: 5 do |e|
use_synth :dsaw
play 50, release: 5
control e, phase: 0.025
end
Ora possiamo divertirci utilizzando lo scorrimento per creare transizioni più fluide…
Uno strumento molto utile nella cassetta degli attrezzi di un programmatore sono le strutture di dati.
Può capitare che tu voglia rappresentare o usare più di una cosa. Per esempio, può essere utile avere una serie di note che suonano una dopo l’altra. I linguaggi di programmazione utilizzano le strutture di dati proprio per questo.
Ci sono moltissime strutture di dati a disposizione dei programmatori e le persone continuano a inventarsene di nuove. Tuttavia, per il momento, prendiamo in considerazione una struttura semplice: la lista.
Andiamo nel dettaglio: capiremo la sua forma base e come utilizzare le liste per scale e accordi.
In questa sezione analizzeremo come funziona una lista come struttura di dati. Ne abbiamo accennato in precedenza nella sezione relativa alla casualità quando abbiamo scelto di suonare una nota in modo casuale da una lista:
play choose([50, 55, 62])
In questa sezione esploreremo come utilizzare le liste per accordi e scale. Prima ripassiamo come possiamo suonare un accordo: ricordi che se non usiamo sleep, tutti i suoni vengono riprodotti in contemporanea:
play 52
play 55
play 59
Proviamo a trovare altri modi di rappresentare questo codice.
Un’opzione è di inserire tutte le note in una lista: [52, 55, 59]
. La nostra amata funzione play
è così furba da sapere come suonare una lista di note. Provala:
play [52, 55, 59]
Ooh, si legge molto più facilmente. Suonare una lista di note non ti deve fermare dall’usare i parametri:
play [52, 55, 59], amp: 0.3
Ovviamente puoi usare anche i nomi delle note tradizionali invece che numeri MIDI:
play [:E3, :G3, :B3]
Ora, quelli di voi che hanno avuto la fortuna di studiare un po’ di teoria musicale, riconosceranno quell’accordo come Mi minore (E Minor NdT), suonato nella terza ottava.
Un’altra caratteristica utile delle liste è la possibilità di ottenere informazioni da essa. Può sembrare un po’ strano ma non è molto più complicato che chiedere a qualcuno di aprire un libro a pagina 23. Con una lista, chiederai: qual è l’elemento all’indice 23? L’unica cosa strana è che nei linguaggi di programmazioni gli indici iniziano da 0 e non da 1.
Con gli indici nelle liste non contiamo 1, 2, 3… ma 0, 1, 2…
Proviamo a capirci di più, guarda questo esempio di lista:
[52, 55, 59]
Non c’è niente di spaventoso. Qual è il secondo elemento in quella lista? Ovviamente è 55
. Facile. Vediamo se riusciamo a far rispondere il computer al posto nostro:
puts [52, 55, 59][1]
Ok, sembra qualcosa di strano che non abbiamo mai visto prima. Credimi, non c’è nulla di difficile. Ci sono tre sezioni nella linea qui sopra: la parola puts
, la nostra lista 52, 55, 59
, e il nostro indice [1]
. Per prima cosa, usiamo puts
perché vogliamo che Sonic Pi stampi nel log una risposta. Poi, gli diamo la nostra lista e, infine, l’indice richiede il secondo elemento in essa. Dobbiamo inserire il nostro indice tra parentesi quadre perché il conteggio inizia a 0, l’indice per il secondo elemento sarà 1
. Guarda:
# indexes: 0 1 2
[52, 55, 59]
Prova a far girare il codice puts [52, 55, 59][1]
e vedrai 55
comparire nel log. Prova a cambiare l’indica 1
con altri valori, prova ad allungare la lista e pensa a come usare una lista nei tuoi prossimi esperimenti. Per esempio, quale struttura musicale può essere rappresentata da una serie di numeri…
Sonic Pi supporta anche l’uso dei nomi di accordi. Prova tu stesso/a:
play chord(:E3, :minor)
Stiamo ottenendo davvero dei bei risultati, e il codice appare molto più ordinato e piacevole di una semplice lista di elementi (oltre che essere più facilmente leggibile dalle altre persone). Quindi, quali altri accordi supporta Sonic Pi? In realtà, ne supporta molti. Prova a digitare quello che segue:
chord(:E3, :minor)
chord(:E3, :dim7)
chord(:E3, :dom7)
Possiamo semplicemente suonare gli accordi in forma di arpeggio usando la funzione ‘play_pattern’:
play_pattern chord(:E3, :m7)
Ok, that’s not so fun - it played it really slowly. play_pattern
will play each note in the list with a call to sleep 1
after each call to play
. We can use another function play_pattern_timed
to specify our own timings and speed things up:
play_pattern_timed chord(:E3, :m7), 0.25
Possiamo anche inserire una lista di durate che verrà trattata come un circolo, ovvero ripetendola ad anello:
play_pattern_timed chord(:E3, :m13), [0.25, 0.5]
Quanto scritto è equivalente a:
play 52, sustain: 0.25
sleep 0.25
play 55, sustain: 0.5
sleep 0.5
play 59, sustain: 0.25
sleep 0.25
play 62, sustain: 0.5
sleep 0.5
play 66, sustain: 0.25
sleep 0.25
play 69, sustain: 0.5
sleep 0.5
play 73, sustain: 0.25
sleep 0.25
Quale preferisci scrivere?
Note that play_pattern
and play_pattern_timed
alter the sustain of the notes to fill the times. You can remove this behavior by setting the sustain:
opt to 0
:
play_pattern_timed chord(:E3, :m13), [0.25, 0.5], sustain: 0
Sonic Pi supporta anche una larga tipologia di scale. Che ne pensi di provare a suonare una scala di Do3 maggiore (C3 nel sistema anglossassone)?
play_pattern_timed scale(:c3, :major), 0.125, release: 0.1
Possiamo anche chiere di eseguire altre ottave:
play_pattern_timed scale(:c3, :major, num_octaves: 3), 0.125, release: 0.1
Proviamo invece a suonare tutte le note in una scala pentatonica?
play_pattern_timed scale(:c3, :major_pentatonic, num_octaves: 3), 0.125, release: 0.1
Gli accordi e le scale sono degli utilissimi strumenti per limitare la scelta di elementi casuali all’interno di qualcosa di significativo. Prova a suonare questo esempio che seleziona note casuali all’interno di una scala di Mi3 maggiore (E3):
use_synth :tb303
loop do
play choose(chord(:E3, :minor)), release: 0.3, cutoff: rrand(60, 120)
sleep 0.25
end
Prova a cambiare il nome dell’accordo e i limiti all’interno di cui vengono selezionate le note.
Per scoprire quali scale e accordi sono supportati da Sonic Pi, clicca semplicemente sul bottone ‘Lang’ a sinistra di questa guida e quindi scegli gli accordi o le scale all’interno della lista. All’interno delle informazioni del pannello principale, scorri verso il basso il cursore finché non verdrai una lunga lista di accordi e di scale.
Divertiti! E ricorda sempre: non ci sono errori, soltanto opportunità.
Un’altra opzione interessante sulle liste standard sono gli anelli (ring). Se conosci un po’ di programmazione, potresti aver incontrato anelli buffer o anelli array. Qui, per comodità e semplicità, utilizzeremo solo anelli.
Nella sezione precedente abbiamo visto come accedere agli elementi di una lista utilizzando il sistema dell’indice:
puts [52, 55, 59][1]
Ora, cosa succede se vogliamo l’indice 100
? Beh, ovviamente non c’è nessun elemento all’indice 100 perché la lista contiene solo 3 elementi. Sonic Pi restituirà nil
che significa nulla.
Tuttavia, consideriamo di avere un contatore come, ad esempio, la pulsazione corrente che viene incrementata di continuo. Creiamo il nostro contatore e la nostra lista:
counter = 0
notes = [52, 55, 59]
Possiamo usare il nostro contatore per accedere alle note nella lista:
puts notes[counter]
Bene, abbiamo 52
. Ora, incrementiamo il nostro contatore per ottenere un’altra nota:
counter = (inc counter)
puts notes[counter]
Fantastico, ora abbiamo 55
e se lo facciamo di nuovo otteniamo 59
. Se, però, lo facciamo ancora, non avremo più numeri nella nostra lista e otterremo nil
. E se volessimo tornare all’inizio della lista e ricominciare da capo? A questo servono gli anelli.
Abbiamo due modi per creare un anello. Possiamo usare ring
come funzione dell’elemento o ring come parametro:
(ring 52, 55, 59)
Oppure possiamo prendere una normale lista e convertirla in un anello inviando il messaggio .ring
:
[52, 55, 59].ring
Quando abbiamo un anello, possiamo usarlo esattamente come abbiamo fatto con le normali liste con l’eccezione che possiamo usare indici che sono negativi oppure di grandezza maggiore rispetto all’anello perché ripartiranno da capo e punteranno sempre a un elemento dell’anello:
(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
Diciamo che vogliamo utilizzare una variabile per rappresentare il battito corrente. Possiamo usarla come indice nel nostro anello per scegliere le note da suonare o i tempi di rilascio oppure qualsiasi altra cosa che abbiamo salvato nel nostro anello, indipendentemente dal numero di battiti in cui siamo.
Una cosa interessante da sapere è che liste restituite da scale
e chord
sono anche anelli e ci possiamo accedere con indici arbitrari.
Oltre a ring
ci sono una serie di altre funzioni che costruiranno un anello per noi.
range
ci invita a specificare un punto di partenza, uno di fine e la grandezza dei passi.bools
ci permette di usare 1
e 0
per rappresentare variabili booleane.knit
ci consente di unire una sequenza di valori ripetuti.spread
crea un anello di booleani con una distribuzione euclidea.Dai un’occhiata alla relativa documentazione per maggiori informazioni a riguardo.
In aggiunta ai costrutti tipo range
e spread
, un altro modo di creare nuovi anelli è manipolando anelli esistenti.
Per capirci di più, prendiamo un semplice anello:
(ring 10, 20, 30, 40, 50)
Se volessimo riprodurlo al contrario? Beh, utilizzeremo il comando .reverse
per girare quell’anello:
(ring 10, 20, 30, 40, 50).reverse #=> (ring 50, 40, 30, 20, 10)
Ora, se volessimo solo i primi tre valori dell’anello?
(ring 10, 20, 30, 40, 50).take(3) #=> (ring 10, 20, 30)
Infine, se volessimo dei valori casuali?
(ring 10, 20, 30, 40, 50).shuffle #=> (ring 40, 30, 10, 50, 20)
Questo è già un modo per creare nuovi anelli. Tuttavia il vero potere arriva quando concateniamo assieme alcuni comandi.
Se volessimo mescolare l’anello, rimuovere 1 elemento e poi prendere i successivi 3?
Analizziamo passo dopo passo:
(ring 10, 20, 30, 40, 50)
- il nostro anello inziale(ring 10, 20, 30, 40, 50).shuffle
- mescoliamo - (ring 40, 30, 10, 50, 20)
(ring 10, 20, 30, 40, 50).shuffle.drop(1)
- rimuoviamo il primo elemento - (ring 30, 10, 50, 20)
(ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3)
- prendiamo gli ultimi tre - (ring 30, 10, 50)
Come puoi vedere, possiamo creare una lunga catena di questi metodi semplicemente collegandoli insieme. Possiamo farlo in qualsiasi ordine vogliamo per creare nuovi anelli partendo da anelli già esistenti.
Questi anelli hanno una proprietà molto potente e importante. Sono immutabili, il che significa che non possono cambiare. Questo significa che i metodi di concatenazione descritti in questa sezione non cambiano gli anelli ma ne creano di nuovi. Puoi condividere anelli tra i vari thread e cominciare a concatenarli all’interno del thread sapendo che non andrai a modificare gli altri thread in cui viene usato lo stesso anello.
Questa è una lista dei metodi di concatenazione a tua disposizione:
.reverse
- restituisce un anello invertito.sort
- crea una versione ordinata dell’anello.shuffle
- crea una versione mescolata dell’anello.pick(3)
- restituisce un anello con i risultati della chiamata di .choose
3 volte.pick(3)
- restituisce un anello con i risultati della chiamata di .choose
3 volte.take(5)
- restituisce un anello che contiene solo i primi 5 elementi.drop(3)
- restituisce un nuovo anello con tutti gli elementi eccetto i primi 3.butlast
- restituisce un nuovo anello senza l’ultimo elemento.drop_last(3)
- restituisce un anello senza gli ultimi 3 elementi.take_last(6)
- restituisce un nuovo anello con soltanto gli ultimi 6 elementi.stretch(2)
- ripete ogni elemento nell’anello due volte.repeat(3)
- ripete l’intero anello 3 volte.mirror
- aggiunge all’anello una versione invertita di se stesso.reflect
- come mirror ma non duplica il valore di mezzo.scale(2)
- restituisce un nuovo anello con tutti gli elementi moltiplicati per 2 (suppone che l’anello contiene solo numeri)Ovviamente, questi metodi di concatenazione accettano anche altri valori! Sentiti libero di chiamare .drop(5)
invece che .drop(3)
se vuoi rimuovere i primi 5 elementi.
Uno degli aspetti più interessanti di Sonic Pi è la possibilità di scrivere e modificare il codice live per creare musica, come se stessi suonando una chitarra. Un vantaggio di questo approccio è avere più feedback mentre componi (ad esempio riproducendo continuamente un loop e continuando a modificarlo finché non suona perfetto). Ovviamente il più grande vantaggio è poter usare Sonic Pi su un palco.
In questa sezione copriremo gli aspetti fondamentali per trasformare la composizione statica in una performance dinamica.
Tieniti forte…
Ora abbiamo imparato abbastanza per cominciare a divertirci. In questa sezione tireremo le somme delle cose viste fino ad ora e ti mostrerò come comporle live e trasformarle in una performance. Abbiamo bisogno di 3 ingredienti:
Ok, cominciamo. Programmiamo live i nostri primi suoni. Per prima cosa abbiamo bisogno di una funzione che contenga il codice che vogliamo suonare. Cominciamo in modo semplice: vogliamo, ovviamente, richiamare di continuo quella funzione in un thread:
define :my_loop do
play 50
sleep 1
end
in_thread(name: :looper) do
loop do
my_loop
end
end
Se ti sembra troppo complicato, torna indietro per rileggere le sezioni relative alle funzioni e ai thread. Non è troppo complicato se hai capito come funzionano queste cose.
Qui abbiamo la definizione di una funzione che suona la nota 50 e si ferma per un battito. Dopodiché definiamo un thread chiamato :looper
che non fa altro che ripetersi chiamando my_loop
.
Se riproduci questo codice, sentirai la nota 50 ripetersi…
Ora è dove cominciamo a divertirci. Mentre il codice sta ancora funzionando cambia 50 in un altro numero, per esempio 55, e premi il pulsante Run di nuovo. Visto? È cambiato! Live!
Non ha aggiunto un nuovo livello perché utilizziamo thread con un nome ed è possibile avere un solo thread per ciascun nome. Inoltre il suono cambia perché ridefiniamo la funzione. Abbiamo dato a :my_loop
una nuova definizione. Quando il thread :looper
si ripete, semplicemente chiama una nuova definizione.
Prova a cambiarlo ancora, cambia la nota, cambia il tempo di pausa. E se aggiungessimo use_synth
? Per esempio cambiamolo in:
define :my_loop do
use_synth :tb303
play 50, release: 0.3
sleep 0.25
end
Ora comincia a diventare interessante, ma possiamo renderlo ancora meglio. Invece di suonare sempre la stessa nota, suoniamo un accordo:
define :my_loop do
use_synth :tb303
play chord(:e3, :minor), release: 0.3
sleep 0.5
end
Perché non suonare note casuali prese dall’accordo:
define :my_loop do
use_synth :tb303
play choose(chord(:e3, :minor)), release: 0.3
sleep 0.25
end
O usando un valore casuale per il cutoff:
define :my_loop do
use_synth :tb303
play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
sleep 0.25
end
Infine, aggiungiamo un po’ di batteria:
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
Ora si che sta diventando interessante!
Ora, prima di cominciare a programmare dal vivo con funzioni e thread, fermati un secondo e leggi la prossima sezione su live_loop
che cambierà per sempre il modo in cui programmi in Sonic Pi…
Ok, questa sezione del tutorial è la vera gemma. Se hai deciso di leggere una sola sezione, dovrebbe essere questa. Se hai letto la precedente, live_loop
è un modo più semplice di fare esattamente la stessa cosa evitando troppe preoccupazioni.
Se non hai letto la sezione precedente, live_loop
è il modo migliore per improvvisare con Sonic Pi.
Ok, suoniamo. Prova a scrivere il seguente codice in un buffer:
live_loop :foo do
play 60
sleep 1
end
Ora premi il pulsante Run, sentirai un beep di base ogni battito. Niente di divertente. Ora, però, non premere Stop. Cambia 60
in 65
e premi Run di nuovo.
Whoah! È cambiato automaticamente senza perdere un colpo. Questo è live coding.
Perché non cambiarlo per farlo suonare più basso? Aggiorna il tuo codice mentre sta suonando:
live_loop :foo do
use_synth :prophet
play :e1, release: 8
sleep 8
end
Poi premi Run.
Giochiamo un po’ con il cutoff:
live_loop :foo do
use_synth :prophet
play :e1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
Premi run di nuovo.
Aggiungiamo un po’ di batteria:
live_loop :foo do
sample :loop_garzul
use_synth :prophet
play :e1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
Cambia la nota da e1
a c1
:
live_loop :foo do
sample :loop_garzul
use_synth :prophet
play :c1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
Ora smettila di ascoltarmi e prova a fare da solo! Divertiti!
Guarda questo live loop:
live_loop :foo do
play 50
sleep 1
end
Forse ti stai chiedendo perché c’è il nome :foo
. L’aggiunta del nome è importante perché significa che questo live loop è diverso da tutti gli altri.
Non possono esistere due live loop con lo stesso nome.
Questo significa che se vogliamo avere più live loop, dobbiamo assegnare loro nomi differenti:
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
Ora puoi aggiornare e cambiare ciascun live loop indipendentemente e tutto funziona.
Una cosa che potresti aver notate è che i live loop lavora automaticamente con il sistema dei cue (segnali di sincronizzazione) che abbiamo visto in precedenza. Ogni volta che il live loop parte, genera un nuovo evento cue
con il nome del live loop. Possiamo, di conseguenza, usare sync
con uno di questi cue per essere sicuri che i loop siano sincronizzati tra loro senza fermare nulla.
Prendiamo in esame questo codice mal sincronizzato:
live_loop :foo do
play :e4, release: 0.5
sleep 0.4
end
live_loop :bar do
sample :bd_haus
sleep 1
end
Vediamo se riusciamo a sistemare il timing e la sincronizzazione senza stoppare. Per prima cosa, sistemiamo il loop :foo
cambiamo il fatto di sleep 1 a qualcosa tipo 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
Non abbiamo ancora finito del tutto, avrai notato come i battiti non siano perfettamente allineati. Questo perché i loop sono fuori fase. Sistemiamo il problema sincronizzandoli tra loro:
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, ora è tutto a tempo, senza aver fermato nulla.
Ora, andiamo avanti e programmiamo live con live loop!
Una cosa che ti troverai a fare spesso programmando live è utilizzare gli anelli. Inserirai note dentro anelli per le melodie, sleep per il ritmo, progressioni armoniche, variazioni di timbro, ecc…
Sonic Pi ha uno strumento veramente utile per lavorare con gli anelli all’interno dei live_loop
. È chiamato sistema di ticchettio (tick system NdT). Nella sezione relativa agli anelli, abbiamo parlato del contatore che cresce costantemente, come, ad esempio, il numero di battiti. Il ticchettio implementa questa idea. Ci permette di usare il ticchettio con gli anelli. Vediamo un esempio:
counter = 0
live_loop :arp do
play (scale :e3, :minor_pentatonic)[counter], release: 0.1
counter += 1
sleep 0.125
end
Questo equivale a:
live_loop :arp do
play (scale :e3, :minor_pentatonic).tick, release: 0.1
sleep 0.125
end
Qui stiamo utilizzando la scala minore pentatonica di E3 ticchettando con ogni elemento. Possiamo farlo utilizzando .tick
alla fine della dichiarazione della scala. Questo tick è locale in relazione al live loop per cui ogni loop può avere il suo tick indipendente:
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
You anche usare tick
come una funzione standard e usare il suo valore come un indice:
live_loop :arp do
idx = tick
play (scale :e3, :minor_pentatonic)[idx], release: 0.1
sleep 0.125
end
Tuttavia, è meglio chiamare .tick
alla fine. La funzione tick
viene usata quando vuoi fare cose particolari con il valore di tick e quando vuoi usare il valore dei tick per altre cose rispetto all’indice negli anelli.
La cosa magica riguardo tick è che non solo restituisce un nuovo indice (o il valore dell’anello a quell’indice) ma fa in modo che quando viene chiamato successivamente, restituirà il valore successivo. Dai un’occhiata agli esempi nella documentazione relativa a tick
per capire come lavorarci. A volte può capitare di voler vedere il valore di tick in quel momento senza incrementarlo. Questo è possibile grazie alla funzione look
. Puoi chiamare look
come una funzione standard oppure aggiungendo .look
alla fine di un anello.
Infine, a volte hai bisogno di avere più di un tick per live loop. Questo può essere fatto assegnando un nome ai tick:
live_loop :arp do
play (scale :e3, :minor_pentatonic).tick(:foo), release: 0.1
sleep (ring 0.125, 0.25).tick(:bar)
end
Qui usiamo due tick: uno per le note da suonare e un altro per il tempo di sleep. Siccome sono entrambi all’interno dello stesso live loop, per tenerli separati dobbiamo assegnargli nomi unici. È lo stesso identico procedimento che abbiamo visto nel nominare i live_loop
: usiamo un simbolo anticipato da :
. Nell’esempio qui sopra, abbiamo chiamato un tick :foo
e l’altro :bar
. Se vogliamo usare look
dobbiamo chiamarli col nome corretto.
Gran parte della potenza di questo sistema di tick non è utile quando stai cominciando. Non provare a imparare tutto quello di cui abbiamo parlato in questa sezione. Per il momento concentrati sul ticchettio all’interno di uno stesso anello. Questo sarà sufficiente per darti la gioia di usare i tick all’interno dei tuoi live_loop
.
Dai un’occhiata alla documentazione alla voce tick
, troverai molti esempi a riguardo!
È spesso utile avere informazioni che si condividono attraverso vari thread o cicli vivi. Per esempio, forse vuoi condividere l’idea della chiave attuale, BPM, o anche concetti più astratti come la “complessità” attuale (che si potrebbe interpretare diversamente in diversi thread). Non vogliamo nemmeno perdere le garanzie deterministiche quando facciamo questo. Cioè, vorremmo condividere il nostro codice con gli altri e sapere esattamente ciò che sentiranno quando lo eseguono. Alla fine della Sezione 5.6 di questa lezione, abbiamo trattato in breve la ragione perché non dobbiamo usare variabili per condividere informazioni attraverso i thread, dovuta alla perdita del determinismo (a sua volta dovuta alle condizioni di gara).
La soluzione di Sonic Pi al problema di lavorare facilmente con variabili globali in un modo deterministico è con un sistema nuovo chiamato Time State (stato temporale). Può sembrare complesso e difficile (infatti, nel Regno Unito, programmazione con thread molteplici e memoria condivisa è tipicamente una matteria al livello universitario). Ma, come vedrai, simile a suonare la prima nota, Sonic Pi facilita molto la condivisione di stato attraverso vari thread mentre mantiene i tuoi programmi thread-safe e deterministici*.
Ti presento get
e set
…
Sonic Pi ha un archivio globale di memoria chiamato Time State. Le due cose principali che fai con questo sono set
(impostare) e get
(richiamare) informazioni. Immergiamoci di più…
Per impostare informazioni nel Time State abbiamo bisogno di due cose:
Per esempio, forse vogliamo impostare il numero 3000
sotto la chiave :intensity
. Questo è possibile utilizzano la funzione set
:
set :intensity, 3000
Possiamo usare qualsiasi nome per la chiave. Se si sono già impostate informazioni con quella chiave, il nuovo set
le sostituisce:
set :intensity, 1000
set :intensity, 3000
Nell’esempio sopra, visto che abbiamo memorizzato tutti e due i numeri sotto la stessa chiave, “vince” l’ultima chiamata di set
, così il numero associato con :intensity
sarà 3000
perché la prima chiamata di set
è in effetti soprascritta.
Per recuperare informazioni dal Time State abbiamo bisogno solamente della chiave usata per fare il set
; in questo caso, :intensity
. Poi, basta che chiamiamo get[:intensity]
, che possiamo verificare facilmente stampandone il risultato sul log:
print get[:intensity] #=> stampa 3000
Nota che le chiamate a get
possono restituire informazioni che erano set
da una esecuzione precedente. Una volta impostata una informazione con set
, è disponibile fino a quando non viene soprascritta (come sopra abbiamo rimpiazzato il valore 1000
di :intensity
con 3000
) o fino a quando non viene chiuso Sonic Pi.
Il beneficio principale del sistema Time State è che si può usare senza rischi attraverso thread o cicli vivi. Per esempio, puoi avere un ciclo vivo che imposta informazioni ed un altro che le recupera:
live_loop :setter do
set :foo, rrand(70, 130)
sleep 1
end
live_loop :getter do
puts get[:foo]
sleep 0.5
end
Una cosa bella dell’uso di get
e set
in questo modo attraverso i thread è che genera sempre lo stesso risultato ogni volta che premi “Run”. Dai, provalo. Vedi se ottieni il seguente nel tuo 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
Prova ad eseguire alcune volte — vedi, è uguale ogni volta. Questo si chiama comportamento deterministico ed è importantissimo quando vogliamo condividere la nostra musica in forma di codice e sapere che la persona che la esegue sente esattamente quello che abbiamo voluto che sentisse (come un MP3 o un flusso di internet suona lo stesso per tutti gli ascoltatori).
Nella Sezione 5.6 abbiamo parlato della ragione perché usare variabili attraverso thread può causare comportamento casuale. Questo ci blocca da potere riprodurre code come questo in maniera affidabile:
## Un Esempio di Comportamento Non-Deterministico
## (dovuto a condizioni di gara causate da vari
## cicli vivi che manipolano lo stesso variabile allo
## stesso tempo).
##
## Se esegui questo codice noterai
## che l'elenco che viene stampato non
## è sempre in ordine!
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
Guardiamo come possiamo fare questo con get
e set
:
## Un Esempio di Comportamento Deterministico
## (nonostante accesso concorrente dello
## stato condiviso) usando il nuovo sistema
## Time State di Sonic Pi.
##
## Quando questo codice si esegue, l'elenco che
## viene stampato è sempre in ordine!
##
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
Nota che questo codice è quasi uguale alla versione prima che usava un variabile. Ma quando esegui questo codice, si comporta come si aspetta con qualsiasi codice tipico di Sonic Pi — fa la stessa cosa ogni volta in questo caso, grazie al sistema Time State.
Dunque, quando si condividono informazioni fra cicli vivi e thread, usa get
e set
invece di variabili per avere comportamento deterministico e riproducibile.
La sezione 5.7 ha introdotto le funzioni cue
e sync
, questo quando c’è da risolvere la questione della sincronizzazione dei thread. Quello che non ha chiarito però è che si tratta proprio del sistema Time State che fornisce questa funzionalità. Si dà il caso che set
è in realtà una variazione di cue
: esso è costruito sopra la stessa funzionalità di base, cioè quella di inserire informazioni nel sistema Time State. Inoltre, sync
è anche progettato in modo tale che funzioni perfettamente con Time State - qualsiasi informazione abbiamo intenzione di memorizzare in Time State, con cui possiamo sincronizzarci. In altre parole - ci “sincronizziamo” sugli eventi ancora da inserire in Time State.
Diamo un rapido sguardo a come usare sync
per attendere che nuovi eventi siano aggiunti al Time State:
in_thread do
sync :foo
sample :ambi_lunar_land
end
sleep 2
set :foo, 1
foo
Nota che sync
attende sempre gli eventi futuri e che bloccherà il thread attuale in attesa di un nuovo evento. Inoltre, erediterà il tempo logico del thread che lo ha innescato tramite set
o cue
, così che può anche essere usato per la sincronizzazione del tempo.
foo
in_thread do
amp = sync :foo
sample :ambi_lunar_land, amp: amp
end
sleep 2
set :foo, 0.5
Nota che i valori che vengono passati attraverso set
e cue
devono essere “thread safe” - ad esempio: anelli immutabili, numeri, simboli o stringhe fissate. Sonic Pi lancia un errore se il valore che stai tentando di memorizzare nel Time State è non valido.
foo
Supponiamo di voler attendere il prossimo evento che ha un percorso con tre segmenti:
sync "/*/*/*"
Questo corrisponderà a qualsiasi evento Time State con esattamente tre segmenti, questo indipendentemente dal loro nome. Per esempio:
cue "/foo/bar/baz"
cue "/foo/baz/quux"
cue "/eggs/beans/toast"
cue "/moog/synths/rule"
Tuttavia, non corrisponderà a percorsi con meno o più segmenti. I seguenti non corrisponderanno:
cue "/foo/bar"
cue "/foo/baz/quux/quaax"
cue "/eggs"
Ogni *
significa qualsiasi contenuto. In questo modo possiamo abbinare i percorsi con un solo segmento con /*
oppure quelli con cinque segmenti con /*/*/*/*/*
foo
cue "/foo/bar/baz"
cue "/foo/baz/baz"
cue "/foo/beans/baz"
Tuttavia, non corrisponderebbe a quanto segue:
cue "/foo/flibble/baz"
cue "/foo/abaz/baz"
cue "/foo/beans/baz/eggs"
foo
foo
cue "/foo/bar/baz"
cue "/foo/bar/beans/baz"
cue "/foo/baz"
cue "/foo/a/b/c/d/e/f/baz"
È possibile utilizzare il carattere ?
per trovare una corrispondenza con un singolo carattere, ad esempio "/?oo/bar/baz"
che corrisponderà:
cue "/foo/bar/baz"
cue "/goo/bar/baz"
cue "/too/bar/baz"
cue "/woo/bar/baz"
Se sai che un segmento potrebbe essere uno di un numero selezionato di parole, puoi usare l’operatore {
and }
per specificare una lista di scelte come "/foo/{bar,beans,eggs}/quux"
che troverà corrispondenza solo con:
cue "/foo/bar/quux"
cue "/foo/beans/quux"
cue "/foo/eggs/quux"
Infine, puoi cercare corrispondenze in una selezione di lettere se usi {
and }
per specificare una lista di scelte come ad esempio "/foo/[abc]ux/baz"
che corrisponderà solo a:
cue "/foo/aux/baz"
cue "/foo/bux/baz"
cue "/foo/cux/baz"
Puoi anche usare il carattere -
per specificare un intervallo di lettere. Ad esempio "/foo/[a-e]ux/baz"
che corrisponderà solo a:
cue "/foo/aux/baz"
cue "/foo/bux/baz"
cue "/foo/cux/baz"
cue "/foo/dux/baz"
cue "/foo/eux/baz"
Nelle chiamate sync
o get
sei libero di combinare i parametri di confronto in qualunque ordine per intercettare qualunque evento Time State creato da cue
o set
. Diamo un’occhiata a un esempio inverosimile:
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/"
For those curious, these matching rules are based on the Open Sound Control pattern matching specification which is explained in detail here: https://opensoundcontrol.stanford.edu/spec-1_0.html
Una volta che padroneggi la conoscenza per convertire il codice in musica, potresti chiederti - cosa posso fare dopo? Qualche volta i vincoli di lavorare puramente all’interno della sintassi di Sonic Pi e del suo sistema audio possono essere eccitanti e metterti in una nuova posizione creativa. Tuttavia, qualche volta è necessario uscire dal codice verso il mondo reale. Vogliamo quindi 2 cose extra:
Fortunatamente esiste un protocollo disponibile dagli anni 80 che permette esattamente questo tipo di interazione - MIDI. C’è un numero incredibile di dispositivi esterni che includono tastiere, controller, sequencers e software audio professionale che supportano il MIDI. Possiamo usare il MIDI per ricevere e inviare dati.
Sonic Pi offre pieno supporto al protocollo MIDI permettendoti di connettere il codice live al mondo reale. Esploriamolo più in dettaglio…
In questa sezione impareremo a collegare un controller MIDI per mandare eventi a Sonic Pi per controllare i nostri synths e suoni. Procurati un controller MIDI come una tastiera o una superficie di controllo e andiamo sul fisico!
Per poter ricevere informazioni da un dispositivo MIDI esterno in Sonic Pi dobbiamo innanzitutto collegarlo al nostro computer. Tipicamente questo avviene via USB anche se dispositivi più vecchi possono avere il connettore DIN a 5 pin, per il quale servirà hardware specifico (ad esempio una scheda audio con connettori MIDI DIN). Una volta collegato il dispositivo, lancia Sonic Pi e controlla la sezione IO nel pannello preferenze. Dovresti vedere il tuo dispositivo elencato qui. Se non è così, prova a premere il tasto ‘Reset MIDI’ e controlla se compare. Se ancora non vedi la periferica, la prossima cosa da fare è controllare la configurazione MIDI del tuo sistema operativo e controllare se rileva il tuo dispositivo. Se nessuna di queste cose funziona, sentiti libero di chiedere aiuto nel nostro forum https://in-thread.sonic-pi.net
Una volta che il tuo dispositivo è connesso, Sonic Pi riceverà automaticamente gli eventi. Puoi vederlo da te manipolando il tuo dispositivo MIDI e controllando il cue logger nella sezione inferiore destra della finestra applicazione sotto il registro eventi (se non fosse visibile vai su Preferenze->Editor->Show & Hide e abilita ‘Show cue log’). Vedrai un flusso di eventi come:
/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]
Una volta che riesci a vedere un flusso di dati come questo significa che hai collegato correttamente la tua periferica MIDI. Congratulazioni, ora vediamo cosa ci puoi fare!
Questi eventi si dividono in due sezioni. Prima c’è il nome dell’evento come ad esempio /midi:nanokey2_keyboard:0:1/note_on
seguito dal valore degli eventi come ad esempio [18, 62]
. Nota interessante, queste sono le 2 cose di cui abbiamo bisogno per salvare le informazioni nel Time State. Sonic Pi inserisce automaticamente gli eventi MIDI in ingresso nel Time State. Questo significa che puoi ottenere il valore dell’ultimo evento MIDI e allo stesso tempo aspettare l’evento successivo usando quanto imparato nella sezione 10 di questo tutorial.
Ora che abbiamo connesso un dispositivo MIDI, visto gli eventi nel cue log e scoperto che la conoscenza del Time State è tutto ciò che ci serve per lavorare con gli eventi, possiamo ora cominciare a divertirci. Costruiamo un piano MIDI semplice:
live_loop :midi_piano do
note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
synth :piano, note: note
end
Ci sono alcune cose che succedono nel codice riportato sopra, inclusi alcuni problemi. Innanzitutto abbiamo un semplice live_loop
che si ripete all’infinito eseguendo il codice fra i blocchi do
/end
. Questo è stato introdotto nella sezione 9.2. Secondariamente, stiamo chiamando sync
per attendere il prossimo evento Time State corrispondente. Usiamo una stringa che rappresenta il messaggio MIDI che stiamo cercando (che è lo stesso mostrato nel cue logger). Nota che questa lunga stringa è fornita dal sistema di auto completamento di Sonic Pi, quindi non è necessario digitarla tutta a mano. Nel registro abbiamo visto che c’erano due valori per ogni evento MIDI note, quindi assegnamo il risultato a due diverse variabili note
e velocity
. Infine triggeriamo il synth :piano
passandogli la nostra nota.
Ora prova tu. Modifica il codice sopra, sostituisci la chiave sync con una stringa che corrisponda alla tua specifica periferica MIDI e premi Run. Hey presto, hai un piano funzionante! Tuttavia, probabilmente noterai un paio di problemi: primo, tutte le note escono allo stesso volume indipendentemente dalla forza applicata sulla tastiera. Questo può essere sistemato facilmente usando il valore MIDI velocity e convertendolo in amplitude. Dato che MIDI ha un intervallo di 0->127, per convertire questo numero in un valore compreso fra 0->1 dobbiamo dividerlo per 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
Aggiorna il codice e premi Run di nuovo. Ora la velocity della tastiera dovrebbe essere rispettata. Ora, liberiamoci di quella fastidiosa latenza.
Prima di poter rimuovere la latenza, dobbiamo capire da cosa è causata. Al fine di mantenere tutti i synth e gli effetti ben sincronizzati su tutte le possibili CPU e relative capacità, Sonic Pi programma l’audio in anticipo di 0.5 secondi come valore predefinito. (Notare che questa latenza aggiuntiva può essere configurata attraverso le funzioni set_sched_ahead_time!
e use_sched_ahead_time
). Questa latenza di 0.5s viene aggiunta al nostro synth :piano
perchè viene aggiunta a tutti i synth triggerati da Sonic Pi. Tipicamente desideriamo questa latenza perchè significa avere tutti i synth ben sincronizzati. Tuttavia questo ha senso solo per i synth gestiti a codice usando play
e sleep
. In questo caso stiamo triggerando il synth :piano
con un dispositivo MIDI esterno e di conseguenza non vogliamo che Sonic Pi controlli la sincronizzazione per noi. Possiamo spegnere questa latenza usando il comando use_real_time
che disabilita la latenza per il thread corrente. Questo significa che puoi usare il modo real time per i live loop che hanno la loro sincronizzazione controllata dai sync
con i dispositivi esterni e mantenere la latenza predefinita per tutti gli altri live loop. Vediamo:
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
Aggiorna il tuo codice per allinearlo al codice sopra e premi Run di nuovo. Ora abbiamo un piano a bassa latenza con velocity variabile codificato in appena 5 righe. Facile vero!
Finalmente, ora che i nostri eventi MIDI vanno dritti nel Time State, possiamo anche usare la funziona get
per recuperare l’ultimo messaggio passato. Questo non blocca il thread corrente e restituisce nil
se nessun valore viene trovato (cosa che può essere superata passando un valore di default - vedi la documentazione per get
). Ricorda che puoi chiamare get
in qualunque thread in qualunque momento per vedere l’ultimo evento corrispondente al valore nel Time State. Puoi anche usare time_warp
per tornare indietro nel tempo e chiamare get
per vedere gli eventi passati…
choose (scegli)
In aggiunta alla ricezione degli eventi MIDI, possiamo anche inviare eventi MIDI per controllare synth esterni, tastiere e altri dispositivi. Sonic Pi fornisce un set completo di funzioni per mandare vari eventi MIDI come ad esempio:
midi_note_on
midi_note_off
midi_cc
midi_pitch_bend
midi_clock_tick
Ci sono inoltre molti altri messaggi MIDI supportati - Controlla la documentazione API per tutte le altre funzioni che cominciano per midi_
.
Per poter inviare messaggi MIDI a un dispositivo esterno, dobbiamo prima averlo collegato. Controlla la sotto-sezione “Collegamento di un Controller MIDI” nella sezione 11.1 per ulteriori dettagli. Nota che se stai usando la porta USB, il collegamento di un dispositivo per l’invio (e la ricezione) segue la stessa procedura. Tuttavia, se stai usando il classico connettore DIN, assicurati di aver collegato il dispositivo alla porta MIDI Out del tuo computer. Dovresti vedere il tuo dispositivo MIDI elencato nel pannello preferenze.
Le molte funzioni midi_*
funzionano esattamente come play,
sample e
synth, mandando un messaggio al tempo (logico) corrente. Per esempio, per distribuire chiamate alla funzione
midi_* dovrai usare
sleep come hai fatto per
play`. Diamo un’occhiata:
midi_note_on :e3, 50
Questo invierà un evento MIDI note on al dispositivo MIDI connesso con velocity 50. (Nota che Sonic Pi convertirà le note dal formato :e3
al loro numero MIDI corrispondente come ad esempio 52 in questo caso.)
Se il dispositivo collegato è un sintetizzatore, dovresti sentirlo suonare una nota. Per disabilitarla, usa midi_note_off
:
midi_note_off :e3
Come impostazione predefinita, Sonic Pi manda ogni messaggio MIDI a tutti i dispositivi connessi su tutti i canali MIDI. Questo è per rendere semplice lavorare con un singolo dispositivo connesso senza dover configurare nulla. Tuttavia, talvolta un dispositivo MIDI gestirà i canali MIDI in un modo particolare (magari ogni nota ha un canale separato) e magari avresti bisogno di collegare più di un dispositivo contemporaneamente. In allestimenti più complessi, potresti voler essere più selettivo riguardo a quale dispositivo MIDI riceve quale messaggio attraverso quale canale.
Possiamo specificare a quale dispositivo inviare usando l’opzione port:
, usando il nome dispositivo come è mostrato nelle preferenze:
midi_note_on :e3, port: "moog_minitaur"
Possiamo anche specificare in quale canale inviare usando l’opzione channel:
(usando un valore compreso nell’intervallo 1-16):
midi_note_on :e3, channel: 3
Naturalmente possiamo specificare entrambe le cose contemporaneamente, per un dispositivo specifico su un canale specifico:
midi_note_on :e3, port: "moog_minitaur", channel: 5
Infine, una cosa veramente divertente da fare è collegare l’uscita audio del tuo sintetizzatore MIDI a uno degli ingressi della tua scheda audio. Puoi a quel punto controllare il tuo sintetizzatore usando le funzioni midi_*
e allo stesso tempo manipolare l’audio usando live_audio
ed effetti:
with_fx :reverb, room: 1 do
live_audio :moog
end
live_loop :moog_trigger do
use_real_time
midi (octs :e1, 3).tick, sustain: 0.1
sleep 0.125
end
(La funzione midi
è disponibile con una comoda scorciatoia per mandare sia eventi note on che note off con un comando singolo. (Controlla questa documentazione per ulteriori informazioni).
In aggiunta al MIDI, un altro modo per ottenere informazioni da e verso Sonic Pi è via rete usando un semplice protocollo chiamato OSC - Open Sound Control. Questo ti permetterà di inviare messaggi a e da programmi esterni (sia che siano in esecuzione sul tuo computer o computer esterni) il che apre a un potenziale molto più avanzato rispetto al MIDI che risente di limitazioni derivante dalla sua concezione risalente agli anni 80.
Per esempio puoi scrivere un programma con un altro linguaggio di programmazione che invia e riceve OSC (ci sono librerie OSC per praticamente ogni linguaggio comune) e interagisce direttamente con Sonic Pi. Le possibili applicazioni di questo sono limitate solo dalla tua immaginazione.
Time State
Costruiamo un listener OSC basico:
live_loop :foo do
use_real_time
a, b, c = sync "/osc/trigger/prophet"
synth :prophet, note: a, cutoff: b, sustain: c
end
In questo esempio viene descritto un percorso OSC "/osc*/trigger/prophet"
col quale ci stiamo sincronizzando. Questo può essere un qualunque percorso OSC valido (tutte le lettere e numeri sono supportati e la /
è usata come in un URL per separare il percorso in parole multiple.) Il prefisso /osc
viene aggiunto da Sonic Pi a tutti i messaggi OSC in ingresso, quindi dobbiamo mandare un messaggio OSC con un percorso /trigger/prophet
per fare in modo che il nostro sync
interrompa il blocco e il sintetizzatore prophet sia innescato.
Possiamo inviare OSC a Sonic Pi da qualunque linguaggio di programmazione che abbia una libreria OSC. Ad esempio, se stiamo mandando OSC da Python potremmo fare qualcosa tipo questo:
from pythonosc import osc_message_builder
from pythonosc import udp_client
sender = udp_client.SimpleUDPClient('127.0.0.1', 4560)
sender.send_message('/trigger/prophet', [70, 100, 8])
Oppure, se stiamo inviando OSC da Clojure potremmo fare qualcosa di questo tipo dal REPL:
(use 'overtone.core)
(def c (osc-client "127.0.0.1" 4560))
(osc-send c "/trigger/prophet" 70 100 8)
Per ragioni di sicurezza, Sonic Pi non permette per default che macchine remote gli mandino messaggio OSC. Tuttavia, puoi abilitare il supporto per macchine esterne in Preferences->IO->Networked OSC->Allow OSC da altri computer. Una volta abilitato questo, puoi ricevere messaggi OSC da qualunque computer nel tuo network. Tipicamente la macchina che invia dovrà conoscere il tuo l’indirizzo IP (un identificatore univoco per il tuo computer nella tua rete - tipo un numero di telefono o un indirizzo email). Puoi scoprire l’indirizzo ip del tuo computer guardando nella sezione IO nel pannello preferenze. (Nel caso la tua macchina avesse più di un indirizzo ip, passando col mouse sopra l’indirizzo mostrato comparirà elenco con tutti gli indirizzi conosciuti).
Nota: alcuni programmi tipo TouchOSC per iPhone e Android supportano invio di OSC come caratteristica standard. Quindi, una volta che sei in ascolto di macchine remote e conosci il tuo indirizzo IP, puoi istantaneamente cominciare a mandare messaggi da app come TouchOSC che ti permette di costruire la tua superficie di controllo personalizzata con slider, bottoni, tasti ecc. Con questo puoi ottenere un’enorme gamma di opzioni.
In aggiunta al ricevere OSC e lavorarci usando Time State, possiamo anche inviare messaggi OSC a tempo con la nostra musica (esattamente come possiamo inviare messaggi MIDI a tempo con la nostra musica). Dobbiamo solo conoscere a quale indirizzo IP e porta stiamo inviando. Proviamolo:
use_osc "localhost", 4560
osc "/hello/world"
Se esegui il codice sopra, noterai che Sonic Pi sta mandando a sé stesso un messaggio OSC! Questo perché abbiamo impostato l’indirizzo IP alla macchina locale e la porta OSC predefinita. Questo è esattamente come mandare una lettera a sé stessi - il pacchetto OSC viene creato, lascia Sonic Pi, va alla struttura network del tuo sistema operativo la quale ruota indietro il pacchetto verso Sonic pi che poi lo riceve come messaggio OSC standard ed è visibile nel registro cue come messaggio in ingresso /osc:127.0.0.1:4560/hello/world
. (Nota come Sonic Pi aggiunga automaticamente prefisso /osc
a tutti i messaggi OSC in ingresso seguito da nome host e porta dell’inviante.)
Naturalmente, mandare messaggi OSC a noi stessi potrebbe essere divertente ma non è molto utile. I veri benefici cominciano quando mandiamo messaggi ad altri programmi:
use_osc "localhost", 123456
osc "/hello/world"
In questo caso stiamo assumendo che ci sia un altro programma sulla stessa macchina in ascolto sulla porta 123456. Se c’è, allora riceverà un messaggio OSC "/hello/world
col quale può fare ciò che vuole.
Se il nostro programma sta girando su un’altra macchina, dovremo conoscere il suo indirizzo IP che useremo al posto di "localhost"
:
use_osc "192.168.10.23", 123456
osc "/hello/world"
Ora possiamo inviare messaggi OSC a qualunque dispositivo che possiamo raggiungere nella nostra rete locale e anche su internet!
Fino a ora, in termini di produzione audio, abbiamo esplorato l’innesco di sintetizzatori e riprodotto suoni attraverso le funzioni play
, synth
e sample
. Queste hanno quindi generato audio che è stato riprodotto attraverso il nostro sistema di diffusori stereo. Tuttavia, molti computer hanno anche la possibilità di gestire audio in ingresso, magari attraverso un microfono, in aggiunta alla possibilità di mandare audio a più di due diffusori. Spesso, questa capacità è resa possibile grazie all’uso di schede audio esterne - queste sono disponibili per tutte le piattaforme. in questa sezione del tutorial daremo un’occhiata a come possiamo sfruttare queste schede audio esterne e lavorare facilmente con canali audio multipli in ingresso. e in uscita da Sonic Pi.
Un modo semplice (e magari familiare) per accedere ai suoni in ingresso è usare il nostro amico synth
specificando il synth :sound_in
:
synth :sound_in
Questo opererà proprio come qualunque altro synth tipo synth :dsaw
con l’eccezione che l’audio generato sarà letto direttamente dal primo ingresso della tua scheda audio di sistema. Sui computer portatili, questo è tipicamente il microfono integrato, ma se hai una scheda audio esterna, puoi collegare qualunque sorgente audio al primo ingresso.
Una cosa che potresti notare è che, proprio come synth :dsaw
il synth :sound_in
dura solo 1 beat in quanto ha un envelope standard. Se vuoi tenerlo aperto un po’ più a lungo, cambia le impostazioni ADSR envelope. Ad esempio, quanto segue terrà il synth aperto per 8 beat prima di chiudere la connessione:
synth :sound_in, sustain: 8
Naturalmente, come per qualunque altro synth normale, puoi aggiungere facilmente effetti tramite il blocco FX:
with_fx :reverb do
with_fx :distortion do
synth :sound_in, sustain: 8
end
end
Se hai collegato una chitarra al tuo primo ingresso, dovresti riuscire a sentirla con distorsione e riverbero fino a che il synth termina come atteso.
Sei libero di usare il synth :sound_in
quante volte vuoi contemporaneamente (proprio come faresti con qualunque altro synth). Ad esempio, quanto segue suonerà due synth :sound_in
simultaneamente - uno con distorsione e uno con riverbero:
with_fx :distortion do
synth :sound_in, sustain: 8
end
with_fx :reverb do
synth :sound_in, sustain: 8
end
Puoi selezionare quale ingresso audio far suonare attraverso l’opzione input:
. Puoi anche specificare un ingresso stereo (2 ingressi paralleli) usando il synth :sound_in_stereo
. Per esempio, se hai una scheda audio con almeno 3 ingressi, puoi trattare i primi 2 come un flusso stereo e aggiungere distorsione, e il terzo come un flusso mono con riverbero aggiunto con il seguente codice:
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
Anche se è una tecnica molto utile, ci sono un paio di limitazioni a questo approccio. Innanzitutto funziona solo per una specifica durata (in seguito al fatto che ha un envelopre ADSR) e secondariamente non c’è modo di cambiare l’effetto una volta che il synth è stato aperto. Entrambe queste cose sono tipicamente richieste quando si lavora con sorgenti audio esterne come microfoni, chitarre e sintetizzatori esterni. Daremo tuttavia un’occhiata alle soluzioni di Sonic Pi a questo problema di manipolazione di un (potenzialmente) infinito flusso di ingresso audio live_audio
.
Il synth :sound_in
, come descritto nella sezione precedente, fornisce un metodo molto semplice e flessibile per lavorare con audio in ingresso. Tuttavia, come già discusso, ha qualche problema quando si lavora con un singolo ingresso audio come singolo strumento (come una voce o una chitarra). Di gran lunga il miglior approccio per un singolo flusso di audio continuo è l’uso di live_audio
.
live_audio
condivide un paio di restrizioni di base con live_loop
(da qui il nome simile). Innanzitutto deve avere un nome univoco e secondariamente solo un flusso live_audio
per volta con quel nome può esistere nello stesso momento. Diamo un’occhiata:
live_audio :foo
Questo codice si comporterà in modo analogo a synth :sound_in
con alcune differenze chiave: viene eseguito per sempre (fino a che non lo interrompi esplicitamente) e puoi “spostarlo” a un nuovo contesto di effetti dinamicamente.
All’innesco iniziale live_audio
funziona esattamente come ti aspetteresti che funzioni con FX. Ad esempio, per avviare un flusso audio con aggiunta di riverbero semplicemente usa il blocco FX :reverb
:
with_fx :reverb do
live_audio :foo
end
Tuttavia, dato che live_audio
gira per sempre (almeno fino a quando lo fermi) sarebbe piuttosto limitante se, come tipicamente i synth, fosse chiuso dentro un blocco FX :reverb
per la sua intera esistenza. Fortunatamente non è questo il caso in quanto è stato progettato per essere semplice spostarsi su un FX diverso. Proviamo. Esegui il codice sopra per sentire l’audio dal vivo proveniente dal primo ingresso della tua scheda audio. Nota, se stai usando un portatile, questo sarà tipicamente il microfono integrato quindi è consigliabile usare le cuffie per prevenire il feedback.
reverb,
with_fx :echo do
live_audio :foo
end
Ora, premi Run, e sentirai immediatamente l’audio riprodotto attraverso un FX echo e non più attraverso riverbero. Se li avessi voluti entrambi, semplicemente modifica il codice nuovamente e premi Run:
with_fx :reverb do
with_fx :echo do
live_audio :foo
end
end
foo
A differenza dei synth standard, dato che live_audio
non ha un envelope, continuerà a girare all’infinito (anche se cancelli il codice, come una funzione rimane definita in memoria se cancelli il codice nell’editor). Per fermarlo devi usare l’arg :stop
:
live_audio :foo, :stop
Può essere facilmente riavviato chiamandolo senza l’arg :stop
:
live_audio :foo
Addizionalmente, tutti i synth live audio vengono arrestati quando premi il pulsante Stop globale (come per tutti gli altri synth e FX in esecuzione).
Rispetto ai canali audio, di default live_audio
si comporta in modo simile al synth :sound_in
in quanto prende un flusso audio mono e lo converte in un flusso stereo usando un panning specifico. Tuttavia, come :sound_in_stereo
è possibile dire a live_audio
di leggere 2 ingressi audio consecutivi e trattarli come canali destro e sinistro direttamente. Questo si ottiene attraverso l’opzione :stereo
. Ad esempio, per trattare ingresso 2 come segnale sinistro e ingresso 3 come segnale destro, devi configurare l’opzione input:
a 2 e abilitare modalità stereo come segue:
live_audio :foo, stereo: true, input: 2
Notare che dopo aver avviato lo stream audio in modalità stereo, non puoi cambiarla a mono senza fermarla e riavviarla. Similmente, se avvi nella modalità mono di default, non puoi passare a stereo senza fermare e riavviare il flusso.
Fino a qui abbiamo visto come ottenere flussi audio multipli in Sonic pi - sia attraverso l’uso del synth :sound_in
sia attraverso il potente sistema live_audio
. In aggiunta all’uso di flussi audio multipli in ingresso, Sonic Pi può erogare flussi audio multipli in uscita. Questo si ottiene tramite l’FX :sound_out
.
Facciamo un rapido riepilogo di come i synth ed FX di Sonic pi erogano il loro audio nel loro contesto FX corrente. Ad esempio, consideriamo quanto segue:
with_fx :reverb do # C
with_fx :echo do # B
sample :bd_haus # A
end
end
Il modo più semplice per capire cosa succede al flusso audio è cominciare dal contesto audio più annidato e man mano valutarne i contorni. In questo caso l’oggetto più annidato è etichettato A
ed è il sample :bd_haus
che viene triggerato. L’audio di questo va direttamente nel suo contesto che è B
- ovvero :echo
FX. Questo aggiunge echo all’audio in arrivo e lo eroga nel suo contesto che è C
- ovvero :reverb
FX. Questo aggiunge quindi riverbero al flusso audio in ingresso e lo eroga nel suo contesto che è il livello più alto - ovvero diffusori sinistro e destro (uscita 1 e 2 della tua scheda audio). L’audio fluisce in uscita in un segnale stereo direttamente.
Il comportamento sopra è vero per tutti i synth (incluso live_audio
) e la maggioranza degli FX ad eccezione di :sound_out
. L’FX :sound_out
fa due cose. Innanzitutto eroga il proprio audio nel suo contesto esterno come descritto sopra. Secondariamente eroga anche il proprio audio direttamente verso un’uscita della tua scheda audio. Diamo un’occhiata:
with_fx :reverb do # C
with_fx :sound_out, output: 3 do # B
sample :bd_haus # A
end
end
In questo esempio, il nostro sample :bd_haus
eroga il proprio audio nel suo contesto esterno che è l’FX :sound_out
. Questo a sua volta eroga il proprio audio al suo contesto esterno :reverb
FX (come atteso). Tuttavia eroga anche un mix mono alla terza uscita della scheda audio di sistema. L’audio generato all’interno di :sound_out
tuttavia ha due destinazioni - l’FX :reverb
e l’uscita 3.
choose (scegli)
Come abbiamo visto, il comportamento di default per :sound_out
e :sound_out_stereo
è mandare audio sia nel loro contesto esterno (come tipicamente tutti gli FX) e a un’uscita specifica della scheda audio. Tuttavia, occasionalmente potresti voler mandare solo all’uscita della tua scheda audio e non al contesto esterno (e di conseguenza evitare che il suono sia mixato e mandato alle uscite standard 1 e 2). Questo è possibile usando l’opzione FX standard amp:` che interviene sull’audio dopo che l’FX ha potuto manipolare l’audio:
with_fx :sound_out, output: 3, amp: 0 do # B
sample :loop_amen # A
end
Nell’esempio sopra, il sample :loop_amen
viene mandato al suo contesto esterno, l’FX :sound_out
. Questo a sua volta manda un mix mono all’uscita 3 della scheda audio dopo di che l’audio per 0, cosa che in pratica lo silenzia. E’ proprio questo segnale silenziato che viene inviato al contesto esterno :sound_out, che è a sua volta l'output standard. Quindi con questo codice, i canali di uscita audio predefiniti non riceveranno alcun audio, mentre il canale 3 riceverà un mix mono del break di batteria
amen` .
Abbiamo concluso il tutorial introduttivo di Sonic Pi. Spero che tu abbia imparato qualcosa. Non ti preoccupare se non hai capito tutto nel dettaglio, suona e divertiti. Sentiti libero di tornare indietro quando ti vengono domande su sezioni di cui abbiamo parlato in questo tutorial.
Se hai delle domande su argomenti di cui non abbiamo parlato, iscrivi al Sonic Pi forum e chiedi pure lì. Troverai qualcuno felice di darti una mano.
Infine, ti invito a dare un’occhiata al resto della documentazione presente in questo help. Ci sono cose di cui non abbiamo parlato che non vedono l’ora di essere scoperte.
Per cui suona, divertiti, condividi il tuo codice, esibisciti per i tuoi amici, mostra il tuo schermo e ricorda:
Non ci sono errori, solo opportunità.
L’appendice A contiene una raccolta di tutti gli articoli su Sonic Pi scritti per il magazine MagPi.
Questi articoli non sono pensati per essere letti in un ordine specifico dal momento che contengono materiale che copre vari argomenti. Invece che provare a insegnarti a usare Sonic Pi per intero, ciascuno si concentra su un aspetto specifico di Sonic Pi e cerca di coprirlo in modo accessibile.
Puoi vederli nella loro forma professionale in PDF gratuito qui: https://www.raspberrypi.org/magpi/
Se non trovi un argomento di tuoi interesse in questi articoli, perché non suggerirne uno? Il modo più semplice è di twittare a @Sonic_Pi. Non si può mai sapere, magari il tuo suggerimento diventerà il prossimo articolo!
La lezione più importante da imparare con Sonic Pi è che non ci sono errori. Il modo migliore di imparare è provando. Prova un sacco di cose, smettila di preoccuparti se il tuo codice suona bene o no e prova diversi synth, note, effetti e parametri. Scoprirai un sacco di cose che ti faranno divertire perché suonano in modo orribile e alcune gemme preziose che suoneranno incredibilmente. Semplicemente elimina le cose che non ti piacciono e tieni quelle che ti piacciono. Più ‘errori’ ti permetti di fare, più velocemente imparerai.
Scommetto che hai imparato a utilizzare le funzioni di base di Sonic Pi come sample
e play
. Cosa c’è dopo? Lo sapevi che Sonic Pi ha al suo interno più di 27 effetti per cambiare il suono del tuo codice? Gli effetti sono come i filtri nei programmi di grafica solo che invece di sfocare l’immagine o trasformarla in bianco e nero aggiungono riverbero, distorsione, echo. Pensali come se stessi collegando un pedale da chitarra all’amplificatore. Per fortuna Sonic Pi rende l’utilizzo degli FX super semplice e non richiede cavi! Tutto quello che devi fare è prendere una sezione di codice e racchiuderla dentro un effetto. Proviamo con un esempio:
sample :loop_garzul
16.times do
sample :bd_haus
sleep 0.5
end
Se vuoi aggiungere un effetto al campione :loop_garzul
, metti tutto dentro il blocco with_fx
:
with_fx :flanger do
sample :loop_garzul
end
16.times do
sample :bd_haus
sleep 0.5
end
Ora, se vuoi aggiungere un effetto alla cassa della batteria, inserisci anche quella dentro with_fx
:
with_fx :flanger do
sample :loop_garzul
end
with_fx :echo do
16.times do
sample :bd_haus
sleep 0.5
end
end
Ricorda: puoi inserire qualsiasi codice dentro with_fx
e ogni suono creato passerà attraverso quell’effetto.
Per scoprire i tuoi suoni, avrai presto bisogno di modificar e controllare i tuoi synth e gli effetti. Per esempio, magari vuoi cambiare la lunghezza di una nota, aggiungere più riverbero, cambiare il tempo tra le ripetizioni dell’eco. Sonic Pi ti permette di avere un grande livello di controllo attraverso i parametri opzionali. Vediamo velocemente come fare. Copia il seguente codice e premi Run:
sample :guit_em9
Ooh, un bellissimo suono di chitarra. Ora cominciamo a giocarci. Perché non cambiare la velocità?
sample :guit_em9, rate: 0.5
Hey, cos’è quel rate: 0.5
che ho appena aggiunto alla fine? È un parametro. Tutti i synth e gli effetti in Sonic Pi li supportano e ce ne sono un sacco con cui giocare. Sono disponibili anche per gli effetti; prova questo:
with_fx :flanger, feedback: 0.6 do
sample :guit_em9
end
Ora, prova ad aumentare il feedback a 1 per sentire dei suoni assurdi. Leggi la documentazione per tutti i dettagli sui parametri che puoi utilizzare.
Il modo migliore per sperimentare velocemente con Sonic Pi è attraverso il live code. Questo ti permette di partire con del codice e continuare a cambiarlo mentre continua a funzionare. Per esempio, se non sai cosa fa il parametro di cutoff a un campione, prova a usarlo. Copia questo codice in un workspace:
live_loop :experiment do
sample :loop_amen, cutoff: 70
sleep 1.75
end
Ora previ run e sentirai un suono di batteria soffocato. Ora cambia il valore di cutoff:
a 80
e premi di nuovo run. Riesci a sentire la differenza? Ora prova 90
, 100
, 110
…
Una volta che capisci come usare live_loop
non tornerai più indietro. Ogni volta che faccio una performance, mi baso completamente su live_loop
tanto quanto un batterista si affida alle sue bacchette. Per maggiori informazioni sul live coding, guarda la sezione 9 del tutorial all’interno di Sonic Pi.
Una delle cose che amo fare con Sonic Pi è fare in modo che componga al posto mio. Un ottimo modo per farlo è utilizzare la casualità. Può sembrare complicato ma non lo è per niente. Dai un’occhiata a questo codice:
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
Ora, quando suoni questo, sentirai un flusso costante di nome della scala :e2 :minor_pentatonic
suonate con un synth :dsaw
. Vi sento gridare: “Aspetta un momento, quella non è una melodia”. Beh, questa è la prima parte del mio trucco magico. Ogni volta che riproduciamo dall’inizio live_loop
possiamo dire a Sonic Pi di resettare il flusso casuale. È come andare indietro nel tempo. Prova questo, aggiungi la linea use_random_seed 1
al 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
Ogni volta che il live_loop
ricomincerà, i numeri random saranno resettati. Questo significa che sceglierà sempre le stesse 16 note ogni volta. Voilà, una melodia. Ora, questa è la parte interessante. Cambia il valore del seme da 1
a, diciamo, 4923
. Wow! Un’altra melodia! Semplicemente cambiando un numero (quello del seme), puoi esplorare tutte le combinazioni di melodie che vuoi. Questa è magia.
I raggi laser attraverso il fumo, il subwoofer che pompa i bassi nella folla. L’atmosfera riempita da sintetizzatori e persone che ballano. Tuttavia c’è qualcosa che non va in questo club. Proiettato sopra alla testa del DJ c’è del testo e non dei normali visual. È la proiezione di Sonic Pi che sta girando su Raspberry Pi. La persona che occupa la cabina del DJ non sta usando dei dischi ma sta scrivendo e modificando del codice. Live. Questo è il Live Coding.
Questa può sembrare una storia di una notte in un club futuristico ma programmare musica è un trend in crescita ed è spesso descritto come Live Coding (http://toplap.org). Uno delle direzioni più recenti che ha preso questo approccio alla musica è l’Algorave (http://algorave.com), eventi dove gli artisti come me programmano musica affinché le persone possano ballare. Non è necessario, però, che tu sia in un nightclub per fare del live coding; con Sonic Pi v.2.6+ puoi farlo ovunque ti porti il tuo Rasberry Pi, un paio di cuffie e delle casse. Quando raggiungerai la fine di questo articoli, saprai programmare e modificare il tuo personalissimo beat. Il punto di arrivo dipenderà solo dalla tua immaginazione.
La chiave per programmare live con Sonic Pi è capire il funzionamento di live_loop
. Proviamo a vederne uno:
live_loop :beats do
sample :bd_haus
sleep 0.5
end
Ci sono 4 ingredienti principali nel live_loop
. Il primo: il suo nome. Il nostro live_loop
qui sopra si chiama :beats
. Sei libero di chiamare il tuo live_loop
come vuoi. Sii creativo. Io spesso utilizzo nomi che comunichino qualcosa riguardo alla musica che stanno producendo alle persone tra il pubblico. Il secondo ingrediente è la parola do
che indica dove comincia il live_loop
; il terzo è la parola end
che indica dove finisce e, infine, c’è il corpo del live_loop
che descrive quello che verrà ripetuto: tutto ciò che è compreso tra do
e end
. In questo caso stiamo suonando in modo ripetitivo un campione di cassa della batteria con mezza misura di pausa. Questo produce un beat regolare. Vai avanti, copia il codice in un buffer vuoto in Sonic Pi e premi run. Boom, boom, boom!.
Ok, cosa c’è di così importante in live_loop
? Fin qui sempre un normale loop
! Beh, la bellezza del live_loop
è che puoi modificarli al volo. Questo significa che mentre stanno ancora andando, puoi cambiare il loro comportamento. Questo è il segreto del live coding in Sonic Pi. Proviamo:
live_loop :choral_drone do
sample :ambi_choir, rate: 0.4
sleep 1
end
Ora premi il pulsante Run oppure la scorciatoia Alt-r
. Ora stai ascoltato il bellissimo suono di un coro. Ora, mentre sta suonando, cambia il valore rate da 0.4
a 0.38
. Premi Run di nuovo. Hai sentito il cambio di nota? Cambialo di nuovo a 0.4
per farlo tornare com’era. Ora, abbassalo a 0.2, poi a
0.19 e poi riportalo a
0.4. Guarda come cambiando un parametro al volo hai il controllo della musica? Ora prova a modificare lo stesso parametro a tuo piacimento. Prova anche con numeri negativi. Divertiti!
Una delle lezioni più importanti riguardo a live_loop
è che devono riposarsi. Guarda questo codice:
live_loop :infinite_impossibilities do
sample :ambi_choir
end
Se provi a far funzionare questo codice, Sonic Pi si lamenterà subito che live_loop
non si ferma. Questo è un sistema di sicurezza! Prenditi un secondo per analizzare cosa questo codice sta chiedendo al computer di fare. Giusto, sta chiedendo di suonare un numero infinito di campioni di coro senza pausa. Senza il sistema di sicurezza il computer proverebbe ad eseguirlo e crasherebbe nel tentativo. Ricorda: i live_loop
devono contenere sleep
.
La musica è fatta di cose che accadono nello stesso momento. Batteria, basso, voce, chitarre… tutto in contemporanea. In informatica questo lo chiamiamo concordanza e Sonic Pi lo fa in modo molto semplice. È sufficiente usare più di un 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
Qui abbiamo due live_loop
, uno che crea beat velocemente e un altro, più lento, che produce strani suoni di basso.
Una delle cose interessanti riguardo i live_loop
è che possono gestire individualmente il loro tempo. Questo vuol dire che è molto semplice creare strutture poliritmiche interessanti o suonare sfasati nello stile di Steve Reich. Ascolta questo:
# Piano Phase di Steve Reich
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
In ognuno di questi tutorial, finiremo con un esempio di musica che deriva dalle idee che abbiamo introdotto oggi. Leggi il codice e cerca di immaginare il risultato. Poi copialo in un buffer vuoto di Sonic Pi e premi Run e ascolta come suona. Infine, cambia uno dei numeri o utilizza i commenti. Prova a capire se puoi usarli come punti di partenza per una performance e, soprattutto, divertiti! A presto…
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
Tra gli sviluppi tecnologici che hanno avuto maggiore impatto nel mondo della musica moderna, c’è sicuramente l’invenzione dei campionatori. Inizialmente i campionatori erano degli scatolotti in grado di registrare e mantenere al proprio interno un qualsiasi suono, in maniera da poterlo manipolare e riprodurre in tanti modi diversi. Per esempio, potevi prendere una vecchia canzone, individuare un assolo di batteria, registrarlo all’interno del campionatore, e successivamente riprodurlo in ripetizione continua ad una velocità dimezzata. Questo è esattamente il modo con cui sono stati creati i primi beat hip hop e oggi è praticamente impossibile travare nella musica elettronica una canzone che non contenga in qualche modo dei “campioni”. L’utilizzo dei campioni è l’ideale per introdurre in maniera semplice e veloce interessanti elementi nella tua esibizione di live coding.
Ma quindi dove lo troviamo un campionatore? Beh, in realtà ne abbiamo già uno. E’ nel nostro Raspberry Pi! Nel cuore di Sonic Pi è integrato un campionatore molto potente: proviamo a giocarci un po’!
Uno dei campioni di batteria più conosciuti e maggiormente riconoscibili è L’Amen Break. L’Amen Break è contenuto in una canzone del 1969 intitolata “Amen Brother” eseguita dalla band americana The Winstons. “Break” in Inglese significa pausa e nella musica rappresenta un interludio strumentale che collega due parti di una canzone. Questo particolare Break fu scoperto all’inizio negli anni 80 da dei musicisti hip hop e da lì utilizzato in una grande varietà di generi musicali come drum and bass, breakbeat, hardcore techno and breakcore.
Sarai contento di sapere che questo particolare campione è già incluso in Sonic Pi. Ripulisci un buffer e scrivici dentro il seguente codice:
sample :loop_amen
Premi Run e bum! Stai ascoltando uno dei più influenti campioni di batteria della storia della musica dance! Tuttavia, questo campione non è famoso per essere suonato singolarmente, bensì per essere riprodotto all’interno di un loop.
Eseguiamo l’Amen Break in loop facendoci aiutare dal nostro vecchio amico live_loop
, già introdotto in questo tutorial:
live_loop :amen_break do
sample :loop_amen
sleep 2
end
Ok, è in loop, ma c’è una fastidiosa pausa ad ogni ripetizione. Questo è perché abbiamo chiesto uno sleep pari a 2
battute e con una velocità predefinita di 60 BPM, il nostro campione :loop_amen
dura soltanto 1.753
battute. Quindi abbiamo un silenzio di 2 - 1.753 = 0.247
battute. Anche se è breve, risulta ben evidente.
Per risolvere questo problema, possiamo usare beat_stretch:
chiedendo a Sonic Pi di “streatchare” (stiracchiare) il campione, in modo da farlo durare uno specifico numero di battute.
Le funzioni sample
e synth
ti danno la possibilità di avere un grande controllo attraverso i parametri opzionali amp:
, cutoff:
e release:
. Tuttavia, il termine “parametri opzionali” è lungo e complicato da dire, quindi utilizzeremo la parola opts.
live_loop :amen_break do
sample :loop_amen, beat_stretch: 2
sleep 2
end
Adesso si che si balla! Anche se, forse vorremmo rallentare o accelerare il ritmo per adattarlo al nostro umore.
Bene, quindi che dobbiamo fare se vogliamo cambiare stile e passare all’hip hop old school o al breakcore? Un modo semplice è di giocare con il tempo, o meglio incasinare il tempo. Con Sonic Pi è facilissimo, basta infilare un ‘use_bpm’ dentro il tuo live loop:
live_loop :amen_break do
use_bpm 30
sample :loop_amen, beat_stretch: 2
sleep 2
end
Mentre stai rappando sopra questi ritmi lenti, fai caso a come il programma rimanga fermo per 2 battiti (sleep 2) e i nostri bpm sono a 30. Quindi tutto è a tempo. L’opzione ‘beat_stretch’ funziona con i bpm di riferimento per fare in modo che tutto torni.
Quindi, qui sta la parte divertente. Mentre il loop è ancora in azione, cambia il numero ‘30’ con ‘50’ dentro ‘use_bpm 30’. Wow, tutto va più veloce e comunque rimane a tempo! Prova ad andare ancora più veloce, inserendo 80 o 120 e ora fai impazzire il computer e spacca a 200!
Adesso che abbiamo imparato a mettere i campioni nel live loop, diamo un’occhiata ad alcune delle opzioni più divertenti del synth ‘sample’. Il primo è ‘cutoff:’, che controlla il filtro di taglio del campionatore. Di norma è disabilitato ma puoi facilmente attivarlo:
live_loop :amen_break do
use_bpm 50
sample :loop_amen, beat_stretch: 2, cutoff: 70
sleep 2
end
Vai avanti e cambia il ‘cutoff:’. Per esempio, aumentalo a 100, premi Run e aspetta che il loop torni all’inizio per ascoltare il risultato sonoro. I valori più bassi, tipo 50, suonano più bassi e caldi mentre valori alti tipo 100 o 120 sono più secchi. Ciò accade perché l’opzione ‘cutoff:’ taglia le frequenze alte nello stesso modo in cui una falciatrice taglia l’erba. Il valore di ‘cutoff:’ è come regolare l’altezza della falciatrice e determina quanto l’erba deve essere tagliata.
Un altro strumento divertente è l’effetto slicer. Questo affetterà (slice in inglese) il suono. Avvolgi la linea di ‘sample’ dentro il codice di effetto, così:
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
Fai caso a come il suono salta sù e giù (se vuoi sentire il suono originale, senza effetti, cambia il valore di ‘mix:’ a 0). Adesso, proviamo a giocare con i valori di ‘phase:’. Questa è la frequenza (in battiti) dell’effetto di affettamento. Un valore piccolo, tipo ‘0.125’, affetterà più velocemente e uno più grande, tipo ‘0.5’, più lentamente. Senti come il dimezzamento o il raddoppiamento dei valori di ‘phase:’ tendono sempre a suonare piacevoli. Infine, cambia il valore di ‘wave:’ a 0, 1 o 2 e ascolta la differenza. I diversi numeri rappresentato le differenti forme d’onda. 0 è un’onda a dente di sega (attacco veloce e rilascio lento), 1 è un’onda quadrata ( attacco e rilascio veloce), 2 infine è un’onda triangolare (attacco e rilascio lento).
Infine, andiamo indietro nel tempo al primo periodo drum and bass di Bristol con questo esempio. Non ti preoccupare troppo di cosa significa questa frase. Digita il codice, premi Run e comincia a fare live coding cambiando i valori delle opzioni e osserva i risultati. Mi raccomando, condividi quello che hai ottenuto. Ci vediamo la prossima volta…
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
Sia che siano i minacciosi scivolamenti i oscillatori rumorosi, sia che siano i colpi scordati di onde a dente di sega che trapuntano il suono, il synth principale gioca un ruolo essenziale in ogni brano elettronico. Nell’edizione del mese scorso, in questa guida abbiamo trattato le modalità di programmazione dei ritmi. In questa edizione tratteremo invece di come programmare tre componenti centrali di un riff fatto con il synth: il timbro, la melodia e il ritmo.
Bene, allora accendiamo il Raspberry Pi, apriamo Sonic Pi in versione 2.6 o più recente, e mettiamoci a fare un po’ di rumore!
Una parte essenziale di ogni riff fatto con il synth è di cambiare il timbro dei suoni e giocarci. In Sonic Pi, il timbro può essere controllato in due modi: cambiando totalmente synth per avere delle modifiche più radicali, cambiando le varie caratteristiche del synth che siamo utilizzando per avere delle modifiche più raffinate e precise. Possiamo utilizzare anche FX, ma questo è spiegato in un’altra guida…
Creiamo un semplice live loop dove continuiamo a cambiare il sintetizzatore usato:
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
Dai uno sguardo al codice. Siamo semplicemente scorrendo attraverso una serie di nomi di synth (quando arriverai in fondo, la lista riparte da capo). Ogni nome viene selezionato attraverso la funzione ‘use_synth’, che cambierà anche il synth utilizzato all’interno del ‘live_loop’ corrente. Stiamo suonando anche la nota ‘:e2’ (E, o ‘Mi’ nel sistema italiano, alla seconda ottava), con un rilascio della nota di 0,5 battiti (mezzo secondo con i BPM preimpostati a 60) e il livello di ‘cutoff:’ impostato a 100.
Ascolta adesso come i diversi synth hanno un suono radicalmente diverso, anche se tutti suonano la stessa nota. Prova a sperimentare, cambiando il tempo di rilascio della nota (‘release:’) o cambiando anche il tempo di attacco (‘attack:’) così da capire come questi parametri hanno un forte impatto sul suono. Infine, prova a cambiare il ‘cutoff:’ per vedere come diversi valori cambiano il timbro (i valori tra 60 e 130 sono i migliori). Fai caso a quanti differenti suoni puoi creare semplicemente modificando alcuni valori. Quando avrai imparato a gestirli, vai alla scheda Synth dentro il sistema Help e qui troverai tutti i synth a disposizione e tutti i parametri che ogni synth supporta. Così ti renderai conto di quanto potenti possono essere le tue dita programmatrici.
Timbro è solo un bella parola per descrivere il suono di un suono. Se, infatti, provi a suonare la stessa nota con strumenti differenti come, ad esempio, il violino, la chitarra, il pianoforte, il pitch (l’altezza della nota) sarà lo stesso ma la qualità sonora sarà diversa. Questa qualità sonora, quella che ti permette di distinguere un pianoforte da una chitarra è il timbro.
Un’altro aspetto importante per il nostro synth lead è la scelta delle note che vogliamo suonare. Se hai già un’idea a riguardo, puoi creare semplicemente un ring con le note e utilizzare il tick per scorrere da una all’altra:
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
In questo esempio abbiamo definito la nostra melodia con un anello che include sia note come, ad esempio :e3
che pause rappresentate da :r
. Usiamo .tick
per scorrere tra le note e avere un riff che si ripete.
Spesso non è semplice trovare un buon riff partendo da zero. Spesso è più semplice chiedere a Sonic Pi una selezione di riff casuale per scegliere il migliore. Per fare una cosa del genere, abbiamo bisogno di tre cose: anelli, casualità e seme di casualità. Proviamo a vedere un esempio:
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
Qui succedono un po’ di cose… cerchiamo di andare con ordine. Per prima cosa specifichiamo che stiamo usando 3 come seme di casualità. Cosa significa? La cosa importante è sapere che quando utilizziamo un seme, possiamo fare una predizione su quello che sarà il prossimo numero casuale. Un’altro punto importante è che mescolare un anello di note funziona nello stesso modo. Nell’esempio qui sopra stiamo semplicemente chiedendo la il terzo mescolamento nella lista standard dei mescolamenti (che sarà sempre la stessa quando impostiamo lo stesso seme prima di mescolare). Infine utilizziamo il tick per scorrere tra le note per suonare il riff.
Qui comincia il bello. Se cambiamo il seme a, per esempio, 3000, otterremo un mescolamento completamente differente. Così diventa semplice esplorare nuove melodie:è sufficiente scegliere una lista di note che vogliamo mescolare (le scale sono un ottimo punto di partenza) e poi scegliere il seme con cui le vogliamo mescolare. Se non ci piace la melodia, basta cambiare una delle due cose e riprovare finché non sentiamo qualcosa che ci piace.
La casualità in Sonic Pi non è realmente casuale ma è quello che si chiama pseudo-random. Immagina di lanciare un dado 100 volte e scrivere il risultato di ogni lancio su un foglio di carta. Sonic Pi ha lo stesso numero di possibili risultati quando gli chiediamo un numero casuale ma, invece che lanciare un dado, prendere il valore successivo in lista. Impostando un seme stabiliamo un punto specifico di inizio da quella lista.
Un altro aspetto importante del riff è il ritmo ovvero quando suonare una nota e quando no. Come abbiamo visto in precedenza, possiamo usare :r
nel nostro anello per aggiungere le pause. Un’altra possibilità è l’utilizzo degli spread che vedremo in futuro. Oggi continueremo a usare la casualità per trovare il nostro ritmo. Invece che suonare ogni nota, possiamo usare una condizione per far sì che suoni con una certa probabilità. Diamo un’occhiata:
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
Una funzione molto utile da conoscere è one_in
che restituisce il valore true
o false
con la probabilità specificata. Qui stiamo usando un valore 2 quindi one_in
restituirà true
una volta su due. In altre parole, il 50% delle volte avremo true
. Utilizzando valori più alti, alzeremo le probabilità che ritorni false
aumentando gli spazi nel riff.
Da notare che abbiamo usato l’iterazione 16.times
. Questo perché vogliamo resettare il nostro valore di seme ogni 16 così per cui il nostro ritmo si ripeterà per 16 volte. Questo non ha effetti sul mescolamento perché viene eseguito immediatamente appena è impostato il seme. Possiamo modificare le quantità di ripetizioni nell’iterazione per allungare il riff. Prova a cambiare il valore da 16 a 8 oppure 4 o 3 per vedere come cambia il ritmo del riff.
Ok, mettiamo insieme tutto quello che abbiamo imparato oggi in un ultimo esempio. Alla prossima!
live_loop :random_riff do
# togli il cancelletto che serve per i commenti per attivare la funzione:
# 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
È impossibile ripercorrere la storia della musica elettronica senza riscontrare l’impatto del piccolo sintetizzatore Roland TB-303. È l’ingrediente segreto alle spalle del suono acid bass. I riff creati con il TB-303 si sentono dai primi brani della scena House di Chicago fino ad artisti più recenti come Plastikman, Squarepusher e Aphex Twin.
La cosa interessante è che la Roland non aveva creato la TB-303 per la dance music. Originariamente era pensata come strumento di aiuto per i chitarristi: potevano programmare delle linee di basso per improvvisarci sopra. Purtroppo c’erano una serie di problemi: era difficile da programmare, non aveva dei suoni di basso convincenti e costava parecchio. Decisi a limitare le perdite, Roland ha chiuso la produzione a 10.000 unità vendute dopo aver passato molti anni sugli scaffali dei chitarristi. Presto, però, avrebbero avuto vita nuova nei negozi dell’usato. Quelle TB-303 aspettavano solo di essere riscoperte da una nuova generazione di sperimentatori che hanno cominciato a utilizzarle in modi diversi da quelli pensati da Roland per creare nuovi suoni. E così è nata l’Acid House.
Anche se non è così semplice mettere le mani su una TB-303 originale, puoi far si che il tuo Raspberry Pi ne diventi una grazie alla potenza di Sonic Pi. Apri il programma e scrivi questo codice e premi Run:
use_synth :tb303
play :e1
Acid bass istantaneo! Proviamo a smanettare un po’…
Per prima cosa, costruiamo un arpeggiatore. Nell’ultimo tutorial abbiamo visto come i riff possano essere semplicemente degli anelli di note suonate in sequenza e ripetute. Creiamo un live loop che faccia esattamente questo:
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
Guarda ogni linea di codice.
tb303
con la funzione use_synth
.:squelch
che continua a ripetersi..tick
. Definiamo n
affinché rappresenti la nota corrente del riff. Il simbolo di uguale significa: assegna il valore a destra al nome sulla sinistra. Questa sarà diversa ogni volta che il loop si ripete. La prima volta n
sarà :e1
, la seconda :e2
seguita da :e3
e poi dall’inizio.:tb303
. Passiamo una serie di parametri interessanti: release:
, cutoff:
, res:
, e wave:
che discuteremo più avanti.sleep
(stiamo chiedendo al nostro loop di ripetersi ogni 0.125
secondi o 8 volte al secondo a 60BPM).end
del live loop. Questo dice a Sonic Pi dove finisce il live loop.Anche se stai ancora cercando di capire che sta succedendo, scrivi il codice sopra e premi Run. Dovresti sentire il battito del ‘:tb303’ in azione. Quindi, ecco dove sta l’azione: cominciamo a fare live coding.
Anche se il loop è ancora attivo, cambia il valore di ‘cutoff:’ a ‘110’ e premi di nuovo Run. Dovresti sentire il suono divenare un po’ più ruvido e gracchiante. Digita ‘120’ e premi Run e poi ‘130’ e di nuovo Run. Ascolta i cambiamenti nel suono provocati da queste variazioni. Infine, prova a mettere un valore più basso, tipo ‘80’. Quindi poi ripeti questi cambiamenti con i numeri che vuoi e quante volte vuoi. Non preoccuparti, io ti aspetto qui…
Un’altra caratteristica con cui vale la pena giocare è ‘res:’. Questo parametro controlla la risonanza del filtro. Una risonanza alta è caratteristica dei suoni bassi un po’ acidi. Adesso abbiamo impostato questo parametro a ‘0.8’. Prova ad aumentarlo progressivamente a ‘0.85’. ‘0.90’, ‘0.95’. Se metti il valore di cutoff a ‘110’ o di più, le variazioni si percepiscono meglio. Infine, prova a fare una pazzia e metti ‘0.999’ come valore di risonanza. A valori così alti di risonanza, puoi sentire il filtro passa-alto, di cui imposti il valore di cutoff, che comincia a risuonare così tanto che si metterà a fare suoni esso stesso, senza che tu intervenga!
Infine, per avere variazioni significative del timbro, prova a cambiare ‘wave:’, ovvero forma d’onda, mettendo ‘1’. Questo parametro infatti ti permette di variare l’oscillatore che genera il suono. Quello preimpostato è ‘0’, cioè un generatore di onda a dente di sega. Il numero ‘1’ è un generatore di impulsi e infine ‘2’ è un generatore di onda triangolare.
Quindi, adesso puoi senz’altro provare differenti giri di note cambiando i suoni all’interno dell’anello o anche prendere note da scale o accordi. Divertiti con il tuo primo sintetizzatore di bassi acidi.
Il progetto del TB-303 originale è piuttosto semplice. Compe potrai notare dal diagramma che segue, ci sono soltanto 4 parti principali.
Il primo è l’oscillatore d’onda, ovvero l’ingrediente base del suono. In questo caso noi abbiamo un oscillatore di onda quadra. Sussessivamente, abbiamo ampiezza dell’inviluppo dell’oscillatore, che controlla l’ampiezza dell’onda quadra nel tempo. Questa dimensione è accessibile da Sonic Pi mediante i parametri ‘attack:’, ‘decay:’, ‘sustain:’ e ‘release:’. Per maggiori informazioni, leggi la sezione 2.4 ‘Durata degli inviluppi’ all’interno della guida. Poi facciamo passare la nostra onda attraverso un filtro passa-basso. Questo taglia le frequenze più acute e dà al suono quella risonanza particolare. E qui comincia il bello. Infatti il valore di taglio (cutoff) del filtro è anche determinato dal suo stesso inviluppo! Questo significa che abbiamo un controllo straodinario sul timbro del suono se giochiamo con entrambi gli inviluppi. Dai un’occhiata sotto:
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
Per ogni opzione di inviluppo abbiamo un valore di taglio (cutoff) equivalente che possiamo impostare all’interno del synth ‘:tb303’. Quindi, per cambiare il tempo di attacco del valore di taglio possiamo usare il parametro ‘cutoff_attack:’. Copia il codice sopra e incollalo in una finestra vuota. Poi premi Run. Sentirai un suono impazzito che ribolle. Quindi, cominciamo adesso a suonare. Prova a cambiare il valore di ‘cutoff_attack:’ a ‘1’ e poi a ‘0.5’. Adesso prova ‘8’.
Come avrai visto, abbiamo fatto passare tutto il segnale attraverso un effetto di reverbero con ‘:reverb’, ottenendo una bella ambientazione sonora. Provane altri per vedere che succede!
Infine, ecco qui un brano che ho composto usando le idee di questa guida. Copialo e incollalo dentro una finestra vuota, prova ad ascoltarlo per un po’ e poi comincia a fare i tuoi cambiamenti senza fermare il processo, facendo live coding. Ascolta i magnifici suoni che puoi produrre in questo modo! Ci vediamo la prossima volta…
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
Minecraft Pi
Ciao, bentornato/a! Nella guida precedente ci siamo concentrati maggiormente sulle possibilità musicali di Sonic Pi, ovvero far diventare il tuo Raspberry Pi uno strumento musicale pronto all’uso. Fino ad ora, abbiamo imparato a:
C’è anche molto altro che vorrei mostrarti e che tratteremo in edizioni future di questa guida. Comunque, questo mese, diamo un’occhiata a qualcosa che Sonic Pi può fare e della quale probabilmente non sei a conoscenza: controllare Minecraft.
Bene, cominciamo allora. Accendi il tuo Raspberry Pi e avvia il tuo Minecraft Pi creando un nuovo mondo. Quando hai fatto, avvia Sonic Pi, ridimensiona e sposta la finestra in modo tale da riuscire a vedere le due finestre contemporaneamente.
In una finestra vuota di Sonic Pi inserisci il codice seguente:
mc_message "Hello Minecraft from Sonic Pi!"
Adesso premi Run. Booom! Il tuo messaggio è apparso dentro Minecraft! E’ stato facile, vero? Adesso, smetti per un momento di leggere e mettiti a giocare scrivendo alcuni messaggi a tuo piacimento. Goditela!
Adesso, mettiamoci un attimo a esplorare. Solitamente utilizziamo il mouse e la tastiera per camminare in giro. Funziona, è vero, ma è piuttosto lento e noioso. Sarebbe molto meglio avere una sorta di macchina del teletrasporto. Beh, grazie a Sonic Pi, ce l’abbiamo. Prova il codice seguente:
mc_teleport 80, 40, 100
Perbacco! Era una strada lunga. Se non fossi stato in modalità volante saresti ricaduto giù a terra. Se tocchi due volte lo spazio per entrare in modalità volo e teletrasportarti di nuovo, rimarrai a fluttuare nel posto che hai toccato.
Allora, cosa significano quei numeri? Abbiamo tre numeri che descrivono le coordinate del posto nel mondo in cui vogliamo andare. Diamo a ogni numero un nome: x, y e z:
Scegliendo differenti valori per x, y e z possiamo teletrasportarci ovunque nel nostro mondo. Prova! Scegli dei numeri diversi e guarda dove vai a finire. Se lo schermo diventa nero è perché ti sei teletrasportato/a sotto terra o in una montagna. Scegli un numero di y più alto e vedrai che tornerai in superficie. Continua a esplorare finché non trovi un posto che ti piace…
Usa le idee spiegate fino a ora e costruisci un Teletrasporto Sonico che rende divertente spostare dei suoni mentre ci spara in giro nel mondo di Minecraft:
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!"
Adesso che hai finalmente trovato un posto bello, comincia a costruire. Puoi fare quello che fai di solito e cominciare a cliccare il mouse furiosamente per mettere i blocchi sotto il cursore. Oppure, puoi utilizzare la magia di Sonic Pi. Prova questo codice:
x, y, z = mc_location
mc_set_block :melon, x, y + 5, z
Guarda in alto! C’è un melone nel cielo! Guarda un attimo il codice. Che cosa abbiamo fatto? Nella prima riga abbiamo preso la posizione attuale di Steve e codificata come variable di x, y e z. Queste lettere corrispondono alle coordinate descritte in precedenza. Abbiamo usato queste coordianate nella funzione ‘mc_set_block’ che pone il blocco scelto nel luogo indicato dalle coordinate. Per porre qualcosa nel cielo, dobbiamo soltanto incrementare il valore di y. E’ per questo che abbiamo aggiunto 5. Proviamo a fare una lunga striscia di meloni:
live_loop :melon_trail do
x, y, z = mc_location
mc_set_block :melon, x, y-1, z
sleep 0.125
end
Quindi, torniamo a Minecraft, assicurati di essere in modalità volo (tocca due volte spazio se non lo sei) e vola intorno al mondo. Guarda in giù e vedrai una bellissima scia di meloni. Guarda che belle figure intrecciate che puoi fare nel cielo.
Coloro che hanno seguito questa guida durante gli ultimi mesi avranno probabilmente la mente già aperta. La scia di meloni è molto bella, ma la parte più interessante dell’esempio precedente è il poter fare un ‘live_loop’ con Minecraft! Per chi non lo sapesse, ‘live_loop’ è un’abilità magica di Sonic Pi che nessun altro linguaggio di programmazione ha. Ti permette di far girare numerosi loop contemporaneamente e di cambiarli mentre sono in esecuzione. Sono incredibilmente potenti e fonte di estremo divertimento. Io uso i ‘live_loop’ per suonare musica nei locali con Sonic Pi; i DJ usano i dischi e io uso i ‘live_loop’ :-). Comunque, oggi andremo a programmare dal vivo sia la musica sia Minecraft.
Iniziamo. Esegui il codice sopra e inizia nuovamente a costruire la tua scia di meloni. Adesso, senza fermare l’esecuzione, cambia ‘:melon’ con ‘:brick’ (mattone) e premi Run. Bravo! Adesso stai facendo una scia di mattoni. Semplice no?! Vuoi aggiungere anche un po’ di musica? Facile, prova questo:
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
Ora, mentre la musica sta suonando, tu comincia a cambiare il codice. Cambia i tipi di blocco: prova ‘:water’, ‘:grass’ o la tua categoria di blocchi preferita. Cambia anche il valore ‘cutoff:’ da ‘70’ a ‘80’ e successivamente anche a ‘100’. Non è divertente?
Combiniamo tutto quello che abbiamo visto finora aggiungendo un tocco di ulteriore magia. Associamo la nostra abilità di teletrasportarci, il posizionamento dei blocchi e la musica per fare una sorta di video musicale di Minecraft. Non ti preoccupare se non riesci a capire tutto. Digita soltanto il testo e divertiti cambiando alcuni valori mentre il codice è in esecuzione. Divertiti e ci vediamo la prossima volta…
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
Dopo la nostra breve trattazione del fantastico mondo del controllo di Minecraft attraverso Sonic Pi dello scorso mese, ricominciamo a fare musica. Oggi, ci occuperemo di creare un fantastico pezzo dance del 21° secolo usando le meravigliose proprietà del codice.
Torniamo indetro al 1875. Un compositore chiamato Bizet aveva appena terminato la sua ultima opera, Carmen. Sfortunatamente, come molti pezzi che rompevano gli schemi preesistenti, le persone non apprezzarono questa opera perché fu considerata oltraggiosa e troppo fuori dai canoni. Purtroppo, Bizet morì dieci anni prima di vedere il suo lavoro salire al successo internazionale, diventando una delle opere più famose ed eseguite della storia della musica. Per onorare questa tragedia, prendiamo una delle melodie più famose della Carmen e rivisitiamola in chiave moderna rendendola anche noi oltraggiosa e differente dai canoni prestabiliti a noi contemporanei. La suoneremo attraverso il live coding!
Suonare con il live coding l’intera opera sarebbe una cosa un po’ difficile da far entrare in questa guida, quindi focalizziamoci soltanto sulle parti più famose. In questo caso, prendiamo la linea di basso dell’Habanera:
Questa cosa potrebbe sembrare particolarmente difficile da leggere se non hai studiato la notazione musicale. Tuttavia, noi programmatori consideriamo la notazione musicale come una forma diversa di codice. Infatti essa rappresenta delle istruzioni destinate a un musicista invece che a un computer. Quindi, dobbiamo solo capire come riuscire a decodificarla.
Le note sono organizzate da destra a sinistra, in modo simile alle parole di questa rivista. Però, esse hanno anche differenti altezze. La posizione verticale della nota rappresenta anche quanto essa è acuta o grave. Più è posta in alto nel pentagramma, più la nota sarà acuta.
Abbiamo già visto come cambiare l’altezza di una nota in Sonic Pi. Possiamo usare sia numeri più o meno alti come ‘play 75’ o ‘play 80’, sia i nomi delle note in notazione alfabetica come ‘play :E’ e ‘play :F’ (ovvero suona Mi e suona Fa in notazione italiana). Fortunatamente, ogni posizione della nota nella partitura rappresenta il nome di una specifica nota. Dai un’occhiata a questa tabella:
La partitura musicale è un tipo di codice molto ricco ed espressivo, capace di comunicare molte cose. Non dovrebbe essere troppo soprendente quindi scoprire che essa non solo ti dice quale nota suonare ma anche quando non devi suonarne. Nei linguaggi di programmazione, questo aspetto somiglia all’idea di ‘nil’ o ‘null’, ovvero l’assenza di un valore. In altre parole, non suonare una nota significa l’assenza di una nota.
Se guardi attentamente la partitura, ti accorgerai che è formata da una combinazione di punti neri dotati di linee che rappresentano la nota da suonare e delle cose strambe che rappresentano le pause. Fortunatamente, Sonic Pi ha una rappresentazione molto pratica delle pause: ‘:r’. Quindi se eseguiamo l’istruzione ‘plat :r’, Sonic Pi suonerà il silenzio! Possiamo anche scrivere ‘play :rest’, ‘play nil’ o ‘play false’, che sono tutti equivalenti alla prima.
Infine c’è un’ultima cosa da imparare: come decodificare la notazione ovvero il timing delle note. Nella notazione originale, puoi vedere che le note sono connesse da linee spesse chiamate codette (o stanghette). La seconda nota ha due stanghette quindi dura 1/16. Le altre note hanno una singola stanghetta che indica una durata di 1/8. La pausa ha anch’essa due stanghette infatti ha una durata di 1/16.
Quando proviamo a decodificare o esplorare nuove cose, un trucco è rendere tutto il più simile possibile per vedere eventuali relazioni o pattern. Per esempio, quando riscriviamo tutto con note da 1/16 puoi notare come la notazione diventi una bella sequenza di note e pause.
Stiamo per tradurre questa linea di basso in Sonic Pi. Codifichiamo queste note e pause in un anello:
(ring :d, :r, :r, :a, :f5, :r, :a, :r)
Proviamo a sentire come suona. Inseriamo tutto in un live loop con un tick per scorrere:
live_loop :habanera do
play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
sleep 0.25
end
Fantastico, il riff che suona dalle casse è istantaneamente riconoscibile. È stato molto faticoso arrivare fino a qui ma ne valeva la pena. Batti un cinque!
Ora che abbiamo la linea di basso, ricreiamo l’ambientazione della scene lirica. Un synth da provare è :blade
che è un sintetizzatore malinconico degli anni ‘80. Proviamolo facendo passare la nota iniziale :d
attraverso uno slicer e un riverbero:
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
Ora, proviamo con le altre note nella linea di basso: :a
e :f5
. Ricorda: non devi premere stop, puoi modificare il codice mentre la musica sta suonando e premere Run di nuovo. Prova anche a cambiare i valori (ad esempio 0.5
, 0.75
e 1
) del parametro phase:
dello slicer.
Infine, combiniamo tutte le idee che abbiamo avuto fino ad ora per un remix dell’Habanera. Come puoi notare, ho aggiunto un’altra linea di basso come un commento. Una volta scritto tutto in un buffer vuoto, premi Run e senti come suona la composizione. Ora, senza premere stop togli il commento dalla seconda linea rimuovendo il #
e poi premi di nuovo Run. Quando è figo? Ora prova a fare un po’ di cambiamenti e divertiti.
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
Minecraft Pi
Tutti abbiamo giocato a Minecraft. Probabilmente avrai costruito strutture grandiose, disegnato trappole e creato linee di carrelli elaborate attraverso gli switch. Ma quanti di voi si sono esibiti con Minecraft? Scommetto che non sapevate di poter usare Minecraft per creare visual incredibili come un VJ professionista.
Se l’unico modo di modificare Minecraft fosse il mouse, faresti molta fatica a cambiare le cose velocemente. Per fortuna, il tuo Raspberry Pi ha una versione di Minecraft che può essere controllare con il codice. E c’è anche un’app chiamata Sonic Pi che rende programmare Minecraft facile e divertente.
Nell’articolo di oggi, ti mostrerò qualche trucchetto che abbiamo usato per esibirci in night club e locali in giro per il mondo.
Cominciamo…
Partiamo da un semplice esercizio di riscaldamento per ricordarci le basi. Per prima cosa, apri sul tuo Raspberry Pi sia Minecraft che Sonic Pi. In Minecraft crea un nuovo mondo e in Sonic Pi scegli un buffer vuoto e incolla questo codice:
mc_message "Let's get started..."
Premi Run e vedrai un messaggio nella finestra di Minecraft. Ok, siamo pronti per partire e divertici…
Quando usiamo Minecraft per creare visual, dobbiamo pensare a qualcosa che sia interessante da vedere e semplice da generare. Un semplice trucco è creare una tempesta di sabbia facendo cadere blocchi di sabbia dal cielo. Per farlo, abbiamo bisogno di semplici funzioni:
sleep
- per inserire una pausa tra le azionimc_location
- per trovare la nostra posizione attualemc_set_block
- per piazzare blocchi di sabbia in una posizione specificarrand
- per generare valori casuali all’interno di un rangelive_loop
- per avere una continua pioggia di sabbiaSe non sei a conoscenza di qualcuna di queste funzioni come, ad esempio, rrand
, scrivi la parola nel buffer, fai click su di essa e poi premi Control-i
per aprire la documentazione relativa. In alternativa puoi accedere alla tab lang nell’aiuto e cercare direttamente la funzione.
Proviamo con un po’ di pioggia prima di fare una vera tempesta. Otteniamo la posizione correte per creare qualche blocco di sabbia nel cielo:
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
Quando premi Run prova a guardarti intorno perché i blocchi potrebbero scendere dietro di te in base a dove stai guardando. Non ti preoccupare, se te li sei persi, premi Run di nuovo… basta essere sicuri di guardare nella giusta direzione!
Analizziamo velocemente cosa sta succedendo. Nella prima linea abbiamo preso la posizione di Steve come coordinate per la funzione mc_location
e le abbiamo inserite nelle variabili x
, y
, e z
. Poi, nella riga successiva, abbiamo usato mc_set_block
per piazzare un po’ di sabbia nelle stesse coordinate con una leggera modifica: abbiamo scelto la stessa x mentre y e z con valori di 20 blocchi maggiori per far si che i blocchi di sabbia cadessero in linea lontano da Steve.
Perché non provi a modificare un po’ questo codice? Aggiungi un po’ di righe, cambia i tempi di pausa, prova a modificare :sand
con :gravel
e scegli coordinate different. Sperimenta e divertiti!
Ok, è tempo di fare un vera e propria tempesta utilizzando la potenza di live_loop
, una delle funzioni magiche di Sonic Pi che ci permette di esplorare tutta la potenza del live coding: modificare il codice mentre sta funzionando!
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
Che divertimento! Stiamo ripetendo tutto abbastanza velocemente (8 volte al secondo) e ad ogni loop cerchiamo la posizione di Steve ma stavolta generiamo 3 valori casuali:
Quindi usiamo quei valori casuali nelle funzioni ‘synth’ e ‘mc_set_block’ per creare della sabbia che cade in luoghi casuali intorno a Steve insieme a un suono percussivo di pioggia prodotto dal synth ‘:cnoise’.
Per quelli e quelle che ancora non conoscono i live loop, posso dirvi che è proprio qui che ci si comincia a divertire con Sonic Pi. Mentre il codice è in esecuzione e la sabbia sta cadendo, prova a cambiare uno dei valori, magari il tempo di sleep a ‘0.25’ oppure la tipologia di blocco da ‘:sand’ a ‘:gravel’. Premi di nuovo Run. Hey, facile! Le cose sono cambiate senza arrestare l’esecuzione. Questo è il tuo primo passo nella carriera di VJ! Continua a fare pratica e a cambiare le cose. Quanto puoi cambiare le immagini senza arrestare l’esecuzione del codice?
Infine, un altro modo molto divertente di generare delle immagini interessanti è di creare enormi muri con diverse combinazioni di blocchi sopra cui volare e avvicinarsi. Per creare questo effetto, dobbiamo smettere di posizionare i blocchi casualmente, mettendoli invece in maniera ordinata. Possiamo farlo intrecciando due gruppi di iterazioni diverse (premi il tasto Help e vai alla sezione 5.2, “Iterazione e loop” per maggiori informazioni sull’iterazione). Il valore ‘ | xd | ’ posizionato dopo il ‘do’ significa che ‘xd’ sarà il valore stabilito per ogni iterazione. Quindi, la prima volta sarà 0, poi 1, 2 e così via. Intrecciando due iterazioni tra loro in questo modo possiamo generare tutte le coordinate di un quadrato. Così, poi possiamo scegliere casualmente i tipi di blocco per creare degli effetti interessanti: |
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
Abbastanza chiaro. Mentre ci divertiamo qui, proviamo a cambiare ‘bs.choose’ con ‘bs.tick’ per spostarci da uno schema casuale a uno più regolare. Prova a cambiare anche il tipo di blocco e i più coraggiosi possono anche provare a includere tutto in un ‘live_loop’ così che la struttura continuerà a cambiare automaticamente.
Quindi, per un gran finale da VJ, cambia i due ‘10.times’ con ‘100.times’ e premi Run. Booom! Un muro gigantesco di blocchi posti casualmente! Immaginati quando tempo potresti impiegare a costruire una cosa del genere usando solo il mouse! Premi due volte lo spazio per entrare in modalità volante e comincia a sorvolare tutto per creare un fantastico effetto visivo. Non fermarti qui, usa la tua immaginazione per dar forma alle tue idee e poi utilizza il potere del codice di Sonic Pi per realizzarle. Quando avrai fatto pratica a sufficienza, abbassa le luci e organizza uno spettacolo visuale per i tuoi amici!
Tornando indietro all’episodio 4 di questo tutorial, avevamo dato un breve sguardo alla randomizzazione mentre programmavamo alcuni riff di synth. Considerando che la randomizzazione è una parte importante della mia pratica musicale live code DJ, ho pensato che fosse utile di trattare i fondamentali di questo aspetto più nel dettaglio. Quindi, mettiti comodo e partiamo sulle strade della randomizzazione!
La prima cosa da imparare, e che potrebbe sorprenderti quando suoni le funzioni random di Sonic PI, è che in realtà esse non sono davvero casuali. Che significa questo? Proviamo a fare un paio di prove. Primo: prova a pensare un numero tra 0 e 1. Tienitelo in mente e non dirmelo. Provo a indovinare…Era ‘0.321567’? No? Bah, non sono molto bravo allora. Fammi fare un altro tentativo, ma stavolta fai scegliere il numero a Sonic Pi. Avvia il programma e chiedigli un numero casuale; ma anche stavolta non dirmelo:
print rand (stampa i numeri casuali)
Quindi riproviamoci…era 0.75006103515625
? Sì! Riesco a vedere il tuo scetticismo. Forse era solo fortuna. Riproviamo. Premi di nuovo Run e vediamo che cosa esce…Cosa, 0.75006103515625
di nuovo? Questo non può essere sicuramente casuale! Sì, hai ragione, non lo è.
Che sta succedendo? La parola usata in informatica è determinismo. Questo significa che niente è casuale e tutto è destinato a esserlo. La tua versione di Sonic Pi è destinata sempre a restituire il numero 0.75006103515625
se esegui il programma scritto sopra. Questo potrebbe sembrarti piuttosto inutile, ma ti assicuro che invece è uno degli aspetti più utili di Sonic Pi. Se ti applichi un po’ imparerai come rapportarti alla natura deterministica della randomizzazione di Sonic Pi e capirai che questo aspetto è fondamentale per le tue composizioni e le tue performance da DJ.
Quando Sonic Pi si avvia, in realtà carica nella memoria una sequenza di 441000 valori casuali già generati. Quando richiami una funzione che genera casualità, come ‘rand’ o ‘rrand’, questo flusso casuale è usato per generare il tuo risultato. Ogni richiamo di una funzione di questo tipo prende i valori da questo flusso. Quindi la decima chiamata di una funzione random userà il decimo valore di quel flusso. Inoltre, ogni volta che premi Run, il flusso riparte da zero. Questo è il motivo per cui sono riuscito a predire il risultato prima ed è anche il motivo per cui una melodia ‘casuale’ è sempre uguale ogni volta. Ogni versione di Sonic Pi usa lo stesso flusso di valori casuali. Questo è molto importante quando cominciamo a condividere i nostri brani musicali tra noi.
Usiamo quanto appena imparato per generare una melodia casuale ripetibile:
8.times do
play rrand_i(50, 95)
sleep 0.125
end
Digita il codice sopra in una finestra vuota e premi Run. Ascolterai una melodia di note ‘casuali’ incluse tra 50 e 95. Quando è terminata, premi di nuovo Run e sentirai esattamente la stessa melodia.
Sonic Pi viene fornito con una serie di funzioni utili per lavorare con il flusso di dati casuali. Eccoti una lista di alcune delle migliori:
Dai un’occhiata alla loro documentazione nella sezione Help se vuoi maggiori informazioni o degli esempi.
L’abilità di ripetere una sequenza di note predeterminate è essenziale per riprodurre un riff mentre suoni. Tuttavia, quello che senti potrebbe non essere esattamente il riff a cui avevi pensato. Non sarebbe bello poter provare alcuni differenti riff e scegliere quello preferito? Qui è dove la magia ha inizio.
Possiamo regolare il flusso usando la funzione ‘use_random_seed’. In informatica, un random seed, ovvero un generatore di numeri casuali, ha un punto di inizio dal quale il flusso di valori causali parte. Prova quanto segue:
use_random_seed 0
3.times do
play rrand_i(50, 95)
sleep 0.125
end
Bene! Abbiamo ottenuto le prime tre note della nostra melodia casuale: ‘84’, ‘83’ e ‘71. Tuttavia, se vogliamo possiamo cambiare questa serie. Prova a eseguire questo:
use_random_seed 1
3.times do
play rrand_i(50, 95)
sleep 0.125
end
Interessante, abbiamo ottenuto ‘83’, ‘71’ e ‘61’. Forse noterai che le prime due cifre di questa serie sono le stesse delle ultime due appartenenti alla serie precedente. E non è una coincidenza.
Ricordati che il flusso di dati casuali è semplicemente una lista gigante di valori già predeterminati. Eseguendo ‘use_random_seed’ scegliamo da dove partire. Un’altra immagine che può renderti l’idea è un enorme mazzo di carte già mischiato. Usando questa funzione, noi scegliamo dove tagliare il mazzo. La cosa eccitante di questa funzione è proprio la sua abilità di saltare al punto del flusso che vogliamo, dandoci infinite possibilità musicali.
Riguardiamo brevemente la nostra melodia casuale di 8 note implementando questa funzione. Prima però inserisci il codice all’interno di un live loop, così possiamo effettuare modifiche mentre la melodia continua a suonare:
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
Adesso, mentre sta ancora suonando, cambia il valore della funzione da ‘0’ a qualcos’altro. Prova ‘100’ oppire ‘999’. Prova anche valori a tua scelta, sperimenta e divertiti. Valuta qual’è il riff che ti piace di più.
Il tutorial di questo mese è stato un bel tuffo nelle funzioni di casualità utilizzabili in Sonic Pi. Spero di essere riuscito a darvi un’idea di come funziona e di aver suggerito un punto di partenza per usare la casualità in modo affidabile per creare pattern ripetitivi nella tua musica. È importante ribadire che puoi usare questa casualità ripetute dovunque tu voglia. Per esempio lo puoi fare per il volume delle note, il tempo di un ritmo, la quantità di riverbero, il synth corrente, il mix di un effetto ecc… In futuro vedremo alcune di queste applicazioni in dettaglio ma, per oggi, vi lascio con un piccolo esempio.
Scrivi il seguente codice in un buffer vuoto, premi Run e prova a cambiare il valore di seed. Premi Run di nuovo (mentre sta andando) e esplora le differenze sonore, di ritmo e di melodia che riesci a fare. Quando ne trovi una bella, ricordati del numero di seed per poterla risuonare. Infine, quando hai trovato un secondo valore di seed che produce risultati interessanti, fai una performance per i tuoi amici cambiando semplicemente tra un valore di seed e l’altro.
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
Fino ad ora ci siamo concentrati su come far partire suoni. Abbiamo scoperto che possiamo usare i synth inclusi in Sonic Pi utilizzando play
o synth
e come far suonare suoni pre-registrati con sample
. Abbiamo anche imparato come aggiungere degli effetti a questi suoni come, ad esempio, il riverbero, utilizzando il comando with_fx
. Combinando tutte queste cose con la gestione del tempo di Sonic Pi, puoi produrre una grande quantità di suoni, beat e riff. Però, una volta lanciata un’opzione di un suono, non c’è modo di controllarla, giusto? Sbagliato! Oggi impareremo qualcosa di molto importante: come controllare i synth mentre suonano.
Creiamo un suono semplice. Apri Sonic Pi e scrivi questo codice:
synth :prophet, note: :e1, release: 8, cutoff: 100
Ora premi il pulsante Run in alto a sinistra per ascoltare il suono. Ok, premilo un altro paio di volte per sentire come suona. Fatto? Bene, ora cominciamo a controllarlo!
Una cosa di Sonic Pi che conoscono in pochi è che le funzioni play
, synth
e sample
restituiscono una cosa chiamata SynthNode
che rappresenta un suono riprodotto. È possibile controllare questi SynthNode
usando una variabile e poi controllarla successivamente. Proviamo a cambiare il valore di cutoff:
dopo 1 beat:
sn = synth :prophet, note: :e1, release: 8, cutoff: 100
sleep 1
control sn, cutoff: 130
Guardiamo ogni linea di codice:
Per prima cosa abbiamo suonato il synth :prophet
utilizzando la normale funzione synth
. Abbiamo, però, catturato il risultato in una variable chiamata sn
. Avremmo potuto usare qualsiasi nome come, ad esempio, synth_note
, o jane
. Non avrebbe fatto differenza. È importante, però, scegliere nomi che abbiano un senso per la performance e per le persone che leggono il tuo codice. Io ho scelto sn
perché è diminutivo facile da ricordare per synth node.
Nella seconda linea abbiamo un comando sleep
normalissimo; non fa nulla di speciale se non dire al computer di aspettare 1 beat prima di andare avanti.
La linea 3 è dove comincia il divertimento. Ora usiamo la funzione control
per dire al nostro SynthNode
di cambiare il valore di cutoff a 130
. Se premi Run sentirai il :prophet
suonare come prima ma, dopo 1 beat, il suono diventerà molto più chiaro.
Opzioni modulabili
La maggior parte dei valori dei synth e degli effetti di Sonic Pi possono essere cambiati. Non è così per tutto, però. Per esempio i valori di inviluppo: attack:
, decay:
, sustain:
e release:
possono essere impostati prima dell’avvio del synth. Capire quali opzioni è possibile cambiare in corso d’opera è semplice, controlla nella documentazione per cercare la frase: “Può cambiare mentre sta suonando” oppure “Non può essere cambiato una volta impostato”. Per esempio guardando la documentazione relativa al parametro attack:
del synth :beep
dice chiaramente che non può essere modificato:
Finché un synth sta suonando, non sei limitato al cambiarlo una volta sola; puoi farlo quante volte vuoi. Per esempio possiamo trasformare il nostro :prophet
in un piccolo arpeggiatore così:
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 questo codice, abbiamo aggiunto un paio di cose in più. Per prima cosa abbiamo una variabile chiamata notes
che contiene le note che vogliamo riprodurre (arpeggiatore è il nome carino che viene dato a qualcosa che suona delle note in ciclo). Seconda cosa: rimpiazziamo la nostra chiamata a control
con un’interazione di 16 volte. In ogni chiamata a control
usiamo .tick
per il nostro anello di notes
che si ripeterà automaticamente. Per un po’ di varietà, prova a sostituire .tick
con .choose
e vedi se senti la differenza.
Ora che puoi controllare più parametri simultaneamente, prova a cambiare la linea di controllo con questo codice:
control sn, note: notes.tick, cutoff: rrand(70, 130)
Quando controlliamo un SynthNode
, risponde esattamente a tempo cambiando immediatamente il valore di un parametro come se avessi premuto un bottone. Questo può dare un suono percussivo, specialmente se il parametro controlla un aspetto del timbro come il cutoff:
. Tuttavia a volte non vuoi che il cambiamento sia istantaneo; a volte vorresti che fosse graduale, come utilizzando uno slider. Ovviamente Sonic Pi ti permette di farlo usando il parametro _slide:
.
Ogni parametro che può essere modificato ha un corrispondente con _slide:
che permette di impostare un tempo. Per esempio amp:
ha amp_slide:
e cutoff:
ha cutoff_slide:
. Questi parametri funzionano in modo leggermente diverso dagli altri perché dicono al synth come comportarsi la volta successiva che vengono controllati. Diamo un’occhiata:
sn = synth :prophet, note: :e1, release: 8, cutoff: 70, cutoff_slide: 2
sleep 1
control sn, cutoff: 130
Nota come questo esempio sia esattamente come lo stesso di prima con la sola aggiunta di cutoff_slide:
. Questo significa che quando modificheremo il parametro cutoff:
impiegherà 2 secondi per andare dal valore attuale al successivo. Possiamo usare control
per sentire lo slide tra 70 e 130. Questo crea una dinamica interessante del suono. Ora prova a cambiare il valore cutoff_slide:
su un intervallo di tempo più breve come 0.5 oppure più lungo come 4 e vedi come cambia il suono. Ricorda che puoi usare slide per ogni parametro modificabile e ciascuno _slide:
può avere parametri differenti per cui puoi avere un cutoff lento e un amp veloce e un pan che sta tra i due.
Proviamo a guardare a un breve esempio che dimostra la potenza del controllo dei synth. Nota come puoi controllare anche gli effetti cambiando leggermente la sintassi. Rileggiti la sezione 7.2 dei tutorial per maggiori informazioni sugli effetti.
Copia il codice su un buffer vuoto e ascoltalo. Non fermarlo, metti mano al codice. Cambia i tempi di slide, cambia le note, i synth, gli effetti e i tempi di sleep. Vedi se riesci a creare qualcosa di totalmente differente!
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
Il mese scorso in questa serie abbiamo parlato in modo approfondito della casualità alla base di Sonic pi. Abbiamo capito come poterla sfruttare in modo deterministico per aggiungere nuovi livelli di controllo del nostro codice. Questo mese continueremo questa analisi approfondendo il sistema di tick di Sonic Pi. Alla fine di questo articolo utilizzerai i tick per i tuoi ritmi e nei tuoi riff per diventare un DJ live coder.
Quando facciamo musica spesso vogliamo che accada qualcosa in base al beat in cui ci troviamo. Sonic Pi ha un sistema di conteggio chiamato tick
per avere totale controllo di dove ci troviamo nella battuta e, ovviamente, supporta beat multipli ciascuno col suo tempo.
Diamoci da fare, per avanzare nel beat dobbiamo solo chiamare tick
. Apriamo un buffer vuoto, scriviamo il seguente codice e premiamo su Run:
puts tick #=> 0
Ci verrà restituito il beat corrente, quindi 0
. Nota come anche premendo Run più volte il risultato sarà sempre 0
. Questo perché ad ogni avvio, il beat riparte da 0. Tuttavia, mentre Run è ancora attivo, possiamo avanzare nel beat tutte le volte che vogliamo:
puts tick #=> 0
puts tick #=> 1
puts tick #=> 2
Quando vedi il simbolo #=>
alla fine di una riga vuol dire che quella linea di codice restituirà del testo nel log nella parte destra. Per esempio puts foo #=> 0
significa che il codice puts foo
scriverà 0
nel log.
Abbiamo visto che tick
fa due cose: incrementa di uno il beat e restituisce il valore corrente. A volte vogliamo solo vedere il valore corrente senza incrementalo. Possiamo farlo usando look
:
puts tick #=> 0
puts tick #=> 1
puts look #=> 1
puts look #=> 1
In questo codice usiamo il tick per aumentare la pulsazione due volte e poi usiamo look
, anch’esso due volte. Nel log vedremo questi valori: 0
, 1
, 1
, 1
. I primi due tick restituiscono 0
e 1
come ci aspettiamo i due look
restituiscono l’ultimo valore due volte, ovvero 1
.
Quindi ora possiamo avanzare nel tempo con tick
e controllare il beat con look
. Cosa possiamo fare ancora? Dobbiamo avere qualcosa con cui usare tick. Sonic Pi utilizza gli anelli (ring) per rappresentare i riff, melodie e ritmi e il sistema dei tick è stato pensato per lavorare con essi. Di fatto gli anelli hanno la loro versione di tick
che fa due cose. Innanzitutto funziona come un tick normale e incrementa il beat. In secondo luogo guarda il valore del ring utilizzano il valore del beat come indice. Diamo un’occhiata:
puts (ring :a, :b, :c).tick #=> :a
.tick
è una versione speciale di tick
che ritornerà il primo valore del ring :a
. Possiamo prendere ciascun valore del ring chiamando .tick
più volte:
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
Prova a guarda il log e vedrai :a
, :b
, :c
e poi di nuovo :a
. Nota come look
restituisce 3
. Le chiamate a .tick
funzionano come normali chiamate di tick
, incrementano il beat locale.
La vera potenza viene fuori quando utilizziamo tick
con ring e live_loop
. Quando combiniamo queste cose abbiamo tutti gli strumenti per costruite un semplice arpeggiatore. Abbiamo bisogno di quattro cose:
Tutti questi concetti possono essere ritrovati in questo codice:
notes = (ring 57, 62, 55, 59, 64)
live_loop :arp do
use_synth :dpulse
play notes.tick, release: 0.2
sleep 0.125
end
Guardiamo ciascuna linea di codice. Per prima cosa definiamo un ring di note che continuerà a suonare. Dopodiché creiamo un live_loop
chiamato :arp
che continuerà a ripetersi. Ogni volta che si ripete il live_loop
, impostiamo il synth per essere :dpulse
e poi suonando la nota successiva usando .tick
. Ricorda che questo incrementerà il nostro contatore di beat e userà l’ultimo valore di beat come indice nel nostro anello. Alla fine, aspettiamo per 1/8 di beat prima di ricominciare da capo.
Una cosa importante da sapere è che i tick
valgono localmente nel live_loop
. Questo significa che ciascun live_loop
ha il suo contatore beat indipendente. Questa cosa è molto più potente che avere un metronomo globale e un beat. Proviamo a vederlo in azione:
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
Una cosa che causa confusione con il sistema di tick di Sonic Pi è che le persone vogliono utilizzare il tick in più ring nello stesso 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
Anche se ciascun live_loop
ha il suo beat counter indipendente, stiamo chiamando .tick
due volte all’interno dello stesso live_loop
. Questo significa che il beat verrà incrementato due volte ogni loop. Questo può generare dei poliritmi interessanti ma spesso non è quello che vogliamo. Ci sono due soluzioni per questo problema. Una è chiamare tick
all’inizio del live_loop
per poi usare .look
per controllare il valore; la seconda è dare un nome a ogni chiamata .tick
come, ad esempio .tick(:foo)
. Sonic Pi creerà e terrà traccia di un contatore di beat per ciascun nome che utilizzerai. In questo modo puoi lavorare con quanti beat tu voglia! Prova a vedere la sezione 9.4 dei tutorial per maggiori informazioni.
Mettiamo insieme tutto quello che abbiamo imparato su tick
, ring
e live_loop
per un ultimo esempio. Come al solito, non trattarlo come un pezzo finito. Prova a cambiare le cose e a giocare con questo codice per vedere cosa riesci a combinare. Alla prossima…
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
Nel terzo episodio di questa serie su Sonic Pi, abbiamo visto come loopare, allungare e filtrare uno dei più famosi break di batteria di tutti i tempi. L’Amen Break. In questo tutorial faremo un passo in avanti per vedere come tagliuzzarlo, riordinare i pezzi e incollare di nuovo tutto insieme in un ordine completamente nuovo. Se ti sembra un po’ pazzo, non ti preoccupare; diventerà tutto chiaro non appena capirei come usare un nuovo strumento per i tuoi set di live coding.
Prima di cominciare, prendiamo un momento per analizzare come lavorare con i campioni. Fino ad ora, avrai utilizzato il campionatore di Sonic Pi. Se non l’hai fatto, è il momento di cominciare! Accendi il tuo Rasberry Pi, apri Sonic Pi dal menu Programming e scrivi il seguente codice in un buffer vuoto e poi premi il pulsante Run per sentire un beat di batteria pre-registrato:
sample :loop_amen
Una registrazione di un suono può essere rappresentato come un flusso di dati: un sacco di numeri compresi tra -1 e 1 che rappresentano i picchi e, più in generale, l’onda sonora. Se suoniamo questi numeri in ordine, otteniamo il suono originale. Ma se decidessimo di suonarli in un ordine diverso per creare un nuovo suono?
Come sono registrati i campioni? È una cosa abbastanza semplice una volta capita la fisica del suono. Quando produci un suono, per esempio colpendo una batteria, il rumore viaggia attraverso l’aria in modo simile al comportamento delle increspature della superficie del lago quando lanci un sasso. Quando queste increspature raggiungono le tue orecchie, il timpano si muove per simpatia e converte questi movimento nel suono che tu ascolti. Se vogliamo registrare e riprodurre un suono, dobbiamo catturare, salvare e riprodurre quelle increspature. Possiamo usare un microfono che agisce come un timpano e si muove avanti e indietro quando il suono lo colpisce. Il microfono converte la sua posizione in un un segnale elettrico che viene misurato molte volte al secondo. Queste misurazioni sono poi rappresentate da una serie di valori compresi tra -1 e 1.
Se dovessimo rappresentare graficamente il suono, risulterebbe un grafico di dati con il tempo sull’asse x e la posizione del microfono/speaker come un valore tra -1 e 1 sull’asse y. Puoi vedere un esempio di questo grafico in cima al diagramma.
Quindi, come programmiamo Sonic Pi per suonare un campione in ordine differente? Per rispondere a questa domanda, dobbiamo dare un’occhiata ai parametri start:
e finish:
di sample
. Questi valori ci permettono di controllare la posizione iniziale della riproduzione dei numeri che rappresentano i suoni. I valori di questi parametri possono essere rappresentati da numeri compresi tra 0
e 1
dove 0
rappresenta l’inizio del campione e 1
la fine. Per cui, per suonare la prima metà dell’Amen Break, è sufficiente specificare un valore di finish:
pari a 0.5
:
sample :loop_amen, finish: 0.5
Possiamo aggiungere un valore start:
per suonare una porzione del campione:
sample :loop_amen, start: 0.25, finish: 0.5
Per puro divertimento, puoi avere il parametro finish:
che sia prima di start:
e il campione suonerà al contrario:
sample :loop_amen, start: 0.5, finish: 0.25
Ora che abbiamo capito che i campioni sono un semplice elenco di numeri che possono essere riprodotti in qualsiasi ordine e abbiamo capito come riprodurre una parte specifica; ora possiamo divertirci suonando un campione in un ordine ‘sbagliato’.
Prendiamo il nostro Amen Break e tagliamolo in 8 parti uguali e poi riordiniamo i vari pezzi. Dai un’occhiata all’immagine; all’inizio A) rappresenta il grafico dei nostri dati originali. Tagliarlo in 8 parti diventa B) - nota come abbiamo assegnato un colore differente a ciascun pezzo per aiutarci a distinguerli. Puoi vedere i valori di inizio e di fine di ciascun pezzo all’inizio. Infine C) è una possibilità di riordinare i pezzi. Poi possiamo suonarlo per creare un nuovo beat. Dai un’occhiata a questo codice:
live_loop :beat_slicer do
slice_idx = rand_i(8)
slice_size = 0.125
s = slice_idx * slice_size
f = s + slice_size
sample :loop_amen, start: s, finish: f
sleep sample_duration :loop_amen, start: s, finish: f
end
rand_i(8)
. Dopodiché salviamo il valore di indice nella variabile slice_idx
.slice_size
che è 1/8 o 0.125. Il parametro slice_size
è necessario per noi per convertire slice_idx
in un valore compreso tra 0 e 1 per poterlo usare come parametro di start:
.s
moltiplicando l’indice slice_idx
per la dimensione slice_size
.f
aggiungendo la dimensione della sottosequenza slice_size
alla posizione iniziale s
.s
e f
dentro i parametri start:
e finish:
di sample
.sleep
che dovrebbe essere uguale alla durata del pezzo del campione. Per fortuna Sonic Pi ha la funzione sample_duration
che accetta gli stessi parametri di sample
e restituisce il valore della durata. Per cui, passando il valore sample_duration
ai parametri start:
e finish:
, possiamo conoscere la durata di un singolo pezzo.live_loop
per poter continuare a scegliere di suonare un pezzo casualmente.Combiniamo tutto quello che abbiamo visto fino ad ora in un ultimo esempio che rappresenti come usare un approccio simile per combinare pezzi di campione con una nuova linea di basso per creare l’inizio di una traccia. Ora è il tuo turno, prendi il codice qui sotto come punto di partenza e vedi se puoi trovare la tua strada per creare qualcosa di nuovo…
live_loop :sliced_amen do
n = 8
s = line(0, 1, steps: n).choose
f = s + (1.0 / n)
sample :loop_amen, beat_stretch: 2, start: s, finish: f
sleep 2.0 / n
end
live_loop :acid_bass do
with_fx :reverb, room: 1, reps: 32, amp: 0.6 do
tick
n = (octs :e0, 3).look - (knit 0, 3 * 8, -4, 3 * 8).look
co = rrand(70, 110)
synth :beep, note: n + 36, release: 0.1, wave: 0, cutoff: co
synth :tb303, note: n, release: 0.2, wave: 0, cutoff: co
sleep (ring 0.125, 0.25).look
end
end
In un precedente episodio della serie su Sonic Pi abbiamo scoperto il potere della randomizzazione, utile a introdurre varietà e sorpresa durante le nostre sessioni di live coding. Per esempio, abbiamo scelto a caso delle note da una scala per comporre melodie infinite. Oggi impareremo una nuova tecnica che usa la randomizzazione per i beat del ritmo!
Prima di cominciare a creare ritmi e synth, facciamo una breve panoramica su concetti base di probabilità. Detta così può sembrare complicato e spaventoso ma, in realtà, è tanto semplice quanto lanciare un dado. Quando lanci un normale dado a 6 facce in un gioco da tavolo cosa succede? Al primo tentativo i numeri 1, 2, 3, 4, 5 e 6 avranno tutti la stessa probabilità di uscire. Di fatto, essendo un dado a 6 facce, in media (se lo lanci molte volte) ti uscirà il numero 1 ogni 6 lanci. Questo significa avere una possibilità di 1 su 6 che esca 1. Possiamo simulare lo stesso comportamento in Sonic Pi utilizzando la funzione dice
. Lanciamone uno 8 volte:
8.times do
puts dice
sleep 1
end
Nota come il log mostri valori tra 1 e 6 esattamente come se avessimo lanciato un vero dado.
Ora, immagina di avere una batteria e che ogni volta che stai per colpirla decidi di lanciare un dado. Se esce 1, colpisci la batteria altrimenti no. Ora abbiamo una drum machine probabilistica che funziona con una probabilità di 1/6. Proviamo a sentire il risultato:
live_loop :random_beat do
sample :drum_snare_hard if dice == 1
sleep 0.125
end
Guardiamo ogni riga di codice per essere sicuri che sia tutto chiaro. Per prima cosa creiamo un nuovo live_loop
chiamato :random_beat
che si ripeterà continuamente tra le righe do
e end
. La prima di queste righe è una chiamata a sample
che riprodurrà un suono preregistrato (in questo caso il suono :drum_snare_hard
). Tuttavia questa riga ha una condizione if
alla fine. Questo significa che la linea verrà eseguita se la condizione che è scritta alla destra di if
risulterà true
(vero). In questo caso: dice == 1
. Questa è una chiamata alla funzione dice
che, come abbiamo visto, restituisce un valore tra 1 e 6. Usiamo l’operatore ==
per verificare se il valore è uguale a 1
. Se è così, la condizione restituisce true
e viene riprodotto il suono di rullante, se il numero è diverso da 1
restituisce false
e il rullante viene saltato. La seconda linea aspetta semplicemente che passino 0.125
secondi prima di lanciare nuovamente il dado.
Quelli di voi che hanno fatto giochi di ruolo sanno che esistono dadi di diverse forme e con differenti numeri di facce. Per esempio esiste il dato a forma di tetraedro che ha solo 4 lati oppure l’icosaedro che, invece, ha 20 facce. Il numero di facce determina il cambiamento nella probabilità che esca 1. Minore è il numero di facce, più probabilità hai che esca 1. Per esempio in un dato a 4 facce, c’è 1 possibilità su 4 mentre in quello da 20 è 1 su 20. Per fortuna Sonic Pi ha la funzione one_in
che descrive esattamente questo. Proviamo:
live_loop :different_probabilities do
sample :drum_snare_hard if one_in(6)
sleep 0.125
end
Facendo partire il live loop qui sopra, sentirai un ritmo casuale familiare. Ora: non fermare la musa ma cambia il 6
con un valore diverso come 2
o 20
e premi nuovamente Run
. Nota come più basso è il numero più frequentemente senti il suono di rullante mentre più è alto il numero minori sono le probabilità che venga suonato. Stai creando musica con le probabilità!
Le cose si fanno davvero interessanti quando diversi campioni vengono avviati con diverse probabilità. Per esempio:
live_loop :multi_beat do
sample :elec_hi_snare if one_in(6)
sample :drum_cymbal_closed if one_in(2)
sample :drum_cymbal_pedal if one_in(3)
sample :bd_haus if one_in(4)
sleep 0.125
end
Prova a far partire il codice qui sopra cambiando ancora una volta le probabilità per modificare il ritmo. Puoi provare anche a cambiare il sample per cambiare completamente il sentimento. Modifica :drum_cymbal_closed
in :bass_hit_c
per avere del basso extra!
Infine, possiamo usare il caro vecchio use_random_seed
per resettare il flusso casuale dopo 8 iterazioni per creare un beat regolare. Scrivi il seguente codice per sentire un ritmo più regolare e ripetitivo. Una volta ascoltato, prova a cambiare il valore di seed da 1000
a un altro numero. Nota come numeri differenti generato beat diversi.
live_loop :multi_beat do
use_random_seed 1000
8.times do
sample :elec_hi_snare if one_in(6)
sample :drum_cymbal_closed if one_in(2)
sample :drum_cymbal_pedal if one_in(3)
sample :bd_haus if one_in(4)
sleep 0.125
end
end
Solitamente, con questo tipo struttura bisogna ricordarsi quali semi suonano bene e prenderne nota. In questo modo, posso facilmente riproporre dei ritmi che ho già creato in concerti futuri.
Infine possiamo aggiungere un suono di basso casuale per dare un po’ di contenuto melodico. Ricorda che possiamo usare il sistema di sequenze probabilistiche che abbiamo appena scoperto non solo per i sample ma anche per i sintetizzatori. Non lasciarlo così com’è, cambia i numeri e crea la tua traccia con la potenza delle probabilità!
live_loop :multi_beat do
use_random_seed 2000
8.times do
c = rrand(70, 130)
n = (scale :e1, :minor_pentatonic).take(3).choose
synth :tb303, note: n, release: 0.1, cutoff: c if rand < 0.9
sample :elec_hi_snare if one_in(6)
sample :drum_cymbal_closed if one_in(2)
sample :drum_cymbal_pedal if one_in(3)
sample :bd_haus, amp: 1.5 if one_in(4)
sleep 0.125
end
end
Questo mese scopriremo tutti i segreti di uno degli effetti più potenti e flessibili di Sonic Pi: lo :slicer
. Alla fine di questo articolo avrete imparato come manipolare il volume generale di alcune parti dei suoni programmati dal vivo. Questo vi permetterà di creare nuove strutture ritmiche e timbriche e di allargare le possibilità sonore.
Cosa fa esattamente l’effetto :slicer
? Possiamo pensarlo come qualcuno che gioca con il controllo del volume della vostra TV o impianto hi-fi. Prima di approfondire il discorso, ascoltate il suono profondo del synth :prophet
generato con questo codice:
synth :prophet, note: :e1, release: 8, cutoff: 70
synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
Ora inseriamo l’effetto :slicer
:
with_fx :slicer do
synth :prophet, note: :e1, release: 8, cutoff: 70
synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
end
Visto come lo slicer agisce? Sembra che silenzi e poi riattivi l’audio con un ritmo regolare. Sembra anche che ‘:slicer’ abbia effetto sul suono generato dal codice scritto tra i blocchi ‘do’ e ‘end’. Puoi controllare la velocità a cui il suono viene spento e riacceso con lopzione ‘phase:’ che è l’abbreviazione di durata di fase in inglese (phase duration). Il valore predefinito è ‘0.25’, il che significa che lo status cambia 4 volte al secondo quando i BPM sono a 60. Proviamo a mandarlo più veloce:
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
Ora, prova a suonare con differenti valori di ‘:phase’. Prova valori più lunghi o più brevi. Guarda cosa accade quando scegli valori molto brevi. Poi, prova anche a cambiare synth, tipo ‘:beep’ oppure ‘:dsaw’ e anche note differenti. Osserva il diagramma seguente per capire come valori di ‘:phase’ diversi cambino il numero di cambiamenti di ampiezza per ogni battito.
La durata di una fase corrisponde alla durata del tempo per un ciclo on/off. Pertanto valori più piccoli porteranno ad un passaggio molto più veloce da on a off rispetto a valori più grandi. Dei buoni valori di partenza sono 0.125
, 0.25
, 0.5
e 1
.
Di base, l’effetto ‘:slicer’ usa un’onda quadra per cambiare l’ampiezza d’onda nel tempo. Questo è il motivo per cui sentiamo il suono per un periodo e successivamente questo scompare per poi ricomparire e così via. Però l’effetto ‘:slicer’ può usare 4 diverse forme d’onda per modificare il suono, che sono la dente di sega, la triangolare e la cosinusoidale. Dai un’occhiata al diagramma sotto per capire la loro forma. Possiamo anche ascoltare il loro effetto. Per esempio, se digiti il codice seguente userai l’onda cosinusoidale come onda di controllo. Infatti, in questo caso il suono non si spegne e accende a scatti, ma in maniera progressiva e senza brusche interruzioni:
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
Suona provando a cambiare le forme d’onda attraverso l’opzione ‘wave:’: ‘0’ sta per dente di sega, ‘1’ per onda quadra, ‘2’ per triangolare e ‘3’ per sinusoidale. Prova anche a variare la fase attraverso ‘phase:’ a ogni forma d’onda per sentire come cambia il suono.
Ognuna di queste onde può essere invertita utilizzando l’opzione ‘invert_wave:’ che la ribalta sull’asse y. Per esempio, durante un ciclo normale l’onda a dente di sega parte dall’alto e si dirige lentamente verso il basso raggiungendo il punto in cui immediatamente ritorna al valore massimo. Invertendo la forma d’onda con ‘invert_wave:1’, l’onda partirà dal valore minimo ed andrà lentamente verso il valore massimo fino a quando ricadrà improvvisamente al valore minimo. Un’altra opzione è ‘phase_offset:’ per mezzo del quale possiamo far iniziare l’onda da un punto qualsiasi. Il valore inserito deve essere tra ‘0’ e ‘1’. Quindi, giocando con i valori di ‘phase:’, wave:’, ‘invert_wave:’ e ‘phase_offset:’ puoi cambiare, e di molto, il comportamento dell’ampiezza dell’onda nel tempo.
Di base, ‘:slicer’ passa dai valore ‘1’ (volume massimo) e ‘0’ (silenzioso). Questi valori possono essere cambiati per mezzo delle opzione ‘amp_min’ e ‘amp_max’. Puoi cambiare questi valori accoppiandoli con un’onda sinusoidale per creare un effetto tremolo:
with_fx :slicer, amp_min: 0.25, amp_max: 0.75, wave: 3, phase: 0.25 do
synth :saw, release: 8
end
Succederebbe praticamente la stessa cosa se prendessi il controllo del volume del tuo impianto stereo e lo muovessi in su e giù facendo ondeggiare il suono.
Una delle caratteristiche più divertenti di ‘:slicer’ è la possibilità di usare la probabilità per decidere se accendere o spegnere lo slicer. Con questa possibilità, il sistema lancia un dado prima di ogni fase e agisce seguendo il valore che viene fuori. Prova a digitare e eseguire quanto segue:
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
Abbiamo ottenuto un interessante ritmo di impulsi. Prova a cambiare l’opzione ‘probability:’ (probabilità) con un valore tra ‘0’ e ‘1’. Più ti avvicini allo ‘0’, più i suoni saranno spaziati tra loro perché la probabilità di accensione dell’effetto risulta più bassa.
Il sistema delle probabilità usato negli effetti è lo stesso utilizzato per la randomizzazione in funzioni come ‘rand’ e ‘shuffle’. Sono entrambi completamente deterministici. Ciò significa che tutte le volte che premi Run, sentirai sempre la stessa sequenza per una data probabilità. Se volessi cambiare la sequenza ottenuta puoi usare l’opzione ‘seed:’ cambiando il seme di riferimento. Funziona esattamente come ‘use_random_seed’, soltanto in questo caso si agisce su quel particolare effetto e basta.
Infine, con l’opzione ‘prob_pos:’ puoi cambiare la posizione di riposo dell’onda di controllo quando il test di probabilità fallisce tra il valore ‘0’ e un altro qualsiasi punto:
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
Una cosa davvero molto divertente è usare ‘:slicer’ per affettare un beat di batteria:
with_fx :slicer, phase: 0.125 do
sample :loop_mika
end
Questo ci permette di creare nuove possibilità ritmiche utilizzando un qualsiasi campione, il che è piuttosto divertente. Tuttavia, bisogna star attenti a che la durata dei campioni sia coerente con i BPM impostati in Sonic Pi, altrimenti l’azione di affettamento non funzionerà. Per esempio, prova a cambiare da ‘:loop_mika’ a ‘:loop_amen’ e ascolta come suona male quando la durata non coincide.
Come abbiamo già visto, cambiare i BPM preimpostati con ‘use_bpm’ farà anche cambiare i tempi di ‘sleep’ e gli le durate degli inviluppi coerentemente al nuovo valore. L’effetto ‘:slicer’ si comporta nello stesso modo e l’opzione ‘phase:’ è in realtà misurata in battiti e non in secondi. Quindi possiamo risolvere il problema di ‘loop_amen’ appena visto cambiando i BPM e farli coincidere con quelli del campione:
use_sample_bpm :loop_amen
with_fx :slicer, phase: 0.125 do
sample :loop_amen
end
Quindi, applichiamo le idee esposte sopra nell’esempio finale che utilizza soltanto l’effetto ‘:slicer’ per creare una combinazione interessante. Vai avanti, cambia quanto scritto e componi il tuo brano personale!
live_loop :dark_mist do
co = (line 70, 130, steps: 8).tick
with_fx :slicer, probability: 0.7, prob_pos: 1 do
synth :prophet, note: :e1, release: 8, cutoff: co
end
with_fx :slicer, phase: [0.125, 0.25].choose do
sample :guit_em9, rate: 0.5
end
sleep 8
end
live_loop :crashing_waves do
with_fx :slicer, wave: 0, phase: 0.25 do
sample :loop_mika, rate: 0.5
end
sleep 16
end
Nella guida di questo mese ti spiegheremo che Sonic Pi può essere utilizzato come un vero strumento musicale. Quindi dobbiamo cominciare a pensare al codice in un modo completamente diverso. I live coder pensano al codice più o meno nello stesso modo in cui un violinista pensa al suo archetto. Infatti, come il violinista può usare diverse tecniche esecutive per creare suoni diversi (movimento lento e colpetti veloci per esempio), noi esploreremo qui 5 regole di base del live coding che si possono eseguire su Sonic Pi. Alla fine di questo articolo, tu sarai capace di eseguire la tua musica per mezzo del live coding.
Uno dei primi consigli da seguire a proposito del live coding, è quello di cominciare ad usare le combinazioni di tasti (shortcut). Ad esempio, invece di perdere tempo cercando il mouse, muoverlo sul bottone Run e cliccarlo, puoi semplicemente premere alt
e r
contemporaneamente. Oltre ad essere molto più veloce, le tue dita saranno già sulla tastiera pronte a digitare il prossimo comando. Puoi vedere ognuna delle combinazioni per le funzioni principali andando con il cursore del mouse sopra il pulsante relativo alla funzione stessa. Oppure, al paragrafo 10.2 del tutorial puoi trovare l’intera lista.
Mentre stai suonando, una cosa divertente da fare è dare un po’ di enfasi al movimento delle braccia quando effettui una combinazione di tasti. Ad esempio, è sempre buona cosa comunicare agli spettatori quando stai per introdurre un cambiamento, quindi amplifica il gesto quando digiti alt-r
, al pari di un chitarrista che dà una potente pennata.
Ora puoi far partire codice istantaneamente con la tastiera, puoi usare subito questa abilità per la nostra seconda tecnica che consiste nello stratificare suoni in modo manuale. Invece di ‘comporre’ usando molte chiamate a play
e sample
separate da sleep
avremo un’unica chiamata a play
che avvieremo automaticamente usando alt-r
. Proviamo! Inserisci questo codice in un buffer vuoto:
synth :tb303, note: :e2 - 0, release: 12, cutoff: 90
Ora, premi Avvia
e, mentre il suono viene riprodotto, modifica il codice in modo da eliminare quattro note cambiando il seguente codice:
synth :tb303, note: :e2 - 4, release: 12, cutoff: 90
Ora, premi Avvia
di nuovo per sentire entrambi i suoni nello stesso momento. Questo perché il pulsante Avvia
di Sonic Pi non aspetta di finire di eseguire il codice già avviato ma, invece, fa partire il codice già avviato nello stesso momento. Questo vuol dire che puoi stratificare molti suoni semplicemente e manualmente con piccole modifiche tra un avvio e l’altro. Per esempio, prova a cambiare note:
e cutoff:
e a rilanciare il codice.
Puoi usare questa tecnica con campioni lunghi. Per esempio:
sample :ambi_lunar_land, rate: 1
Prova facendo partire il campione e, poi, abbassa progressivamente il valore di rate:
da 1
a 0.5
a 0.25
fino a 0.125
premendo continuamente Avvia
. Prova anche con valori negativi come -0.5
. Stratifica i suoni e vedi dove puoi arrivare. Prova anche ad aggiungere degli effetti.
Quando ti esibisci, lavorare con linee di codice molto semplice può aiutare il pubblico che non ha mai visto Sonic Pi a seguire quello che stai facendo riuscendo a collegare quanto stati scrivendo con quello che sentono.
Quando si lavora con della musica più ritmata, può risultare spesso difficile sincronizzare tutto e mantenere un buon tempo. In questi casi è preferibile utilizzare un ‘live_loop’. Oltre a garantire la ripetizione al tuo codice, ti dà la possibilità di modificarlo, aggiornandolo per la prossima iterazione. Inoltre, allo stesso tempo altri live_loop
possono essere eseguiti, il che significa che è possibile sovrapporli fra loro, o a istruzioni manuali. Dai un’occhiata alla sezione 9.2 del tutorial per ulteriori informazioni sull’utilizzo dei live loop.
Quando esegui un’esecuzione dal vivo, ricordarti di utilizzare nel live_loop
l’opzione sync:
in modo da rimediare ad eventuali errori di runtime che possono interrompere l’esecuzione in loop del tuo brano. Se hai già introdotto un sync:
che punta a un altro valido live_loop
, allora si può rapidamente correggere l’errore, eseguendo nuovamente il codice e ripartire senza perdere il tempo.
Uno dei segreti meglio custoditi di Sonic Pi è che esiste un mixer principale attraverso il quale confluiscono tutti i suoni. Questo mixer ha di fabbrica sia un filtro passa-basso che un filtro passa-alto, quindi è possibile operare facilmente delle modifiche globali al suono in uscita. Le funzionalità del mixer principale sono accessibili tramite la funzione set_mixer_control!
. Ad esempio, mentre del codice è in esecuzione e sta suonando, basta inserire la funzione in un buffer vuoto ed eseguire Run
:
set_mixer_control! lpf: 50
Dopo l’esecuzione di questo codice, verrà attivato un filtro passa basso, ottenendo un suono finale più “ovattato”. Nota bene che i nuovi parametri del mixer principale verranno mantenuti finché non deciderai di modificarli nuovamente. Tuttavia, è possibile reimpostare in qualsiasi momento il mixer al suo stato predefinito con la funzione reset_mixer!
. Alcune delle opzioni attualmente supportate sono: pre_amp:
, lpf:
hpf:
, e amp:
. Per l’elenco completo, dai un’occhiata alla documentazione relativa a set_mixer_control!
.
Utilizza l’opzione ‘ * _slide’ del mixer per far scorrere uno o molti valori delle opzioni nel tempo. Ad esempio, per far scorrere lentamente i valori del filtro passa-basso del mixer dal valore corrente a 30, prova a digitare il codice seguente:
set_mixer_control! lpf_slide: 16, lpf: 30
Puoi scorrere velocemente a un valore più alto così:
set_mixer_control! lpf_slide: 1, lpf: 130
Quanto ti esibisci può tornare utile tenere un buffer disponibile per lavorare con il mixer in questo modo.
La tecnica più importante di live coding è fare pratica. La qualità più comune tra i musicisti professionisti di qualsiasi tipo è che fanno pratica con il loro strumento spesso per molte ore al giorno. Esercitarsi è importante per un live coder tanto quanto per un chitarrista. Fare esercizio permette alle tue dita di memorizzare alcuni pattern e modifiche comuni per cui puoi digitare e lavorare in modo più fluido. L’esercizio ti dà anche l’opportunità di esplorare nuovi suoni e codici.
Quando ti esibisci, scoprirai che più esercizio fai, più sarà semplice rilassarsi durante il concerto. La pratica ti permetterà di avere un catalogo di esperienze da cui prendere spunto. Questo ti permette di capire che tipo di modifiche saranno interessanti e quali funzioneranno bene con i suoni che stai utilizzando in quel momento.
Questo mese, invece di presentare un esempio riassuntivo delle cose già fatte, iniziamo con una sfida. Prova a vedere se riesci a esercitarti tutti i giorni della settimana con gli esercizi che ti fornirò. Ad esempio, un giorno fai pratica con i trigger manuali, il successivo crea quale ‘live_loop’, quelo ancora dopo esercitati con il mixer principale, e così via. Poi ripeti tutto da capo. Non preoccuparti se ti senti lento/a o goffo/a in un primo momento - basta che ti eserciti ogni giorno e prima di rendertene conto sarai davanti a un pubblico vero e suonerai come una rockstar, o meglio come una live coding star.
Il mese scorso abbiamo dato un’occhiata alle cinque tecniche più importanti per impadronirsi e impratichirsi nel live coding. In altre parole, abbiamo visto come usare Pi Sonic per approcciarsi alla programmazione musicale nello stesso modo in cui ci approcceremmo a uno strumento musicale. Uno dei concetti importanti che abbiamo trattato è stato quello della pratica. Questo mese ci occuperemo invece di capire perché la pratica continua di live coding è importante e come dovresti cominciare.
Il consiglio più importante è quello di assicurarti di fare pratica regolarmente. Come regola, posso dirti che io in genere mi esercito per 1-2 ore al giorno, ma anche 20 minuti per iniziare possono andare bene. “Poco ma spesso” è l’obbiettivo al quale puntare - quindi se hai a disposizione solo 10 minuti, è comunque un ottimo inizio.
Consiglio pratico n.1 - inizia a sviluppare la routine di fare pratica. Trovati un momento piacevole e rilassante del giorno e fai pratica ogni volta che puoi. In poco tempo, non vedrai l’ora di arrivare alla tua sessione di pratica.
Se osservi un musicista professionista mentre suona sul palco noterai sicuramente alcuni aspetti. In primo luogo, quando suona non guarda il proprio strumento. Le sue dita, braccia e il corpo in generale conoscono le azioni da compiere senza bisogno di pensarci su troppo tempo. Questa abilità è chiamata “memoria muscolare” e anche se potrebbe sembrare qualcosa che solo i professionisti riescono a fare, in realtà questo processo funziona semplicemente come quando hai imparato per la prima volta a camminare o andare in bicicletta: hai fatto pratica attraverso la ripetizione. I e le live coder utilizzano la memoria muscolare per liberare le loro menti dal pensiero della gestione del movimento delle loro dita, in modo che possano concentrarsi sulla musica. Questa abilità è chiamata touch-type in inglese, e corrisponde all’abilità di digitare sulla tastiera senza il bisogno di guardarla.
Consiglio pratico n.2 - imparare a dattilografare. Ci sono molte applicazioni, siti web e anche i giochi che ti possono aiutare a raggiungere questo obiettivo. Trova quello che ti piace di più e rimanici incollato/a finché non riuscirai a programmare senza guardare la tastiera.
Il corpo di un musicista si adatta alla pratica del proprio strumento. Ad esempio, un suonatore di tromba deve essere in grado di soffiare forte, un chitarrista ha bisogno di essere in grado di afferrare il manico con forza e un batterista deve essere in grado di suonare continuamente la batteria per lunghi periodi di tempo. Quindi, qual’è l’aspetto fisico nel live coding? Proprio come i e le DJ, i e le live coder in genere suonano stando in piedi e alcuni/e riescono anche a ballare mentre suonano! Se si fa pratica di live coding seduti a una scrivania, dopo sarà difficile adattarsi a suonare in piedi ad un concerto. Probabilmente troverai le due situazioni molto diverse tra loro e non sarà facile passare dall’una all’altra.
Consiglio pratico n.3 - stai in piedi mentre fai pratica. Il modo più semplice per farlo consiste nell’utilizzare una scrivania che tenga la tastiera all’altezza giusta di quando stai in piedi. Tuttavia, se come me non hai una a casa, ti posso dare un paio di consigli semplici ma efficaci. Il primo è quello di utilizzare un asse da stiro, che sembra funzionare piuttosto bene. Un altro è quello di impilare alcune scatole o libri di grandi dimensioni su una normale scrivania e posizionare la tastiera in cima alla torre. Inoltre, ti consiglio di fare un po’ di allungamenti prima di iniziare a suonare e prova anche a muoverti a ritmo durante la sessione. Ricordati, nessuno ti sta guardando, quindi divertiti e comportati naturalmente. Questo ti aiuterà anche quando sarai sul palco.
Molti strumenti musicali richiedono di essere assemblati e accordati prima di essere suonati. Almeno che non tu sia già una rockstar, con un autobus pieno di assistenti, dovrai preparare tutto da solo/a prima del tuo concerto. Di solito, questo è un momento piuttosto stressante ed è facile che emergano problemi. Una soluzione che può aiutarti è quella di incorporare nella pratica quotidiana anche la preparazione della strumentazione.
Consiglio pratico n.4. Inserisci il set-up nella tua routine di pratica quotidiana. Per esempio, procurati una scatola o una borsa in cui tenere il tuo Raspberry Pi, la tastiera ecc. Prima di ogni sessione di pratica, tira fuori tutte le parti, connettile e avvia il tutto fino a che non otterrai la schermata iniziale di Sonic Pi. Poi, quando avrai finito la tua sessione di pratica, lasciati il tempo di mettere tutto a posto con cura. All’inizio questa operazione potrebbe portarti via un po’ di tempo, ma poi diventerai pratico/a anche in questo e tutto sarà molto più facile e veloce. Non ci dovrai nemmeno pensare mentre lo fai.
Quando avrai sistemato tutto e sarai pronto/a per iniziare a suonare, potresti ritrovarti spaesato/a e non sapere dove cominciare. Molte persone hanno questo problema: trovare una buona idea da cui cominciare oppure avere una buona idea ma non sapere come realizzarla. Alcune persone addirittura non hanno proprio idea di che suoni vogliono fare! La prima cosa da fare è non preoccuparsi. Infatti è una situazione molto comune e succede ad ogni musicista, anche se hanno una lunga esperienza. E’ comunque molto meglio fare un suono che non ti piace piuttosto che non farne nessuno.
Consiglio pratico n. 5. Passa del tempo a fare suoni e musica che non ti piacciono. Prenditi il tempo di esplorare nuove idee e nuovi suoni. Non ti preoccupare se ti sembrano orribili o se non sono nello stile che volevi ottenere. Quando sperimenti in questo modo incrementi le possibilità di imbatterti in suoni o combinazioni di essi che potresti amare! Anche se il 99% dei suoni che fai sono brutti, quell’1% potrebbe contenere un riff da inserire nel tuo nuovo brano. Dimenticati delle cose che non ti piacciono e ricordati di quelle che ti piacciono. Far ciò è anche più facile quando suoni con il codice. Infatti, puoi semplicemente premere salva!
Molti musicisti riescono a guardare uno spartito e “ascoltare” la musica nella propria testa senza aver bisogno di suonarla. Si tratta di una capacità davvero molto utile e vale la pena provare a trasferirla nei propri esercizi di live coding. In verità, la cosa veramente importante è avere idea di cosa una determinata istruzione andrà a suonare. Non è necessario essere in grado di immaginarlo esattamente, ma sapere perlomeno se sarà un qualcosa di veloce, lento, forte, ritmico, melodico, casuale, eccetera. L’obbiettivo è poter invertire il processo, immaginando quello che si vuol suonare e quindi decidere quali istruzioni andare a scrivere. Può volerci molto tempo per perfezionare questo processo, ma appena ci riesci, sarai in grado di improvvisare ed esprimere le tue idee sul palco in modo del tutto spontaneo.
Consiglio pratico n. 6. Scrivi codice dentro Sonic Pi ma non premere Run. Prova invece ad immaginarti che suono potrebbe produrre quel codice. Solo dopo premi Run, ascolta e prova a pensare a cosa hai fatto di giusto e di sbagliato. Continua a fare questo passaggio finché non diventa un’azione naturale della tua attività di programmazione. Quando io mi esercito, di solito ho un’idea piuttosto precisa di come quel pezzo di codice suonerà. Tuttavia, riesco ancora a volte a sorprendermi. In questi casi fermo il processo e cerco di capire perché ho pensato una cosa e n’è successa un’altra. Tutte le volte che succede questo, riesco a imparare nuovi trucchi che mi permettono di esprimermi in modi nuovi.
Un problema comune quando fai pratica è quello di essere distratti da altre cose. Far pratica è un’attività difficile e richiede una grande dose di disciplina, qualsiasi sia il tipo di musica che fai: jazz, classica o EDM. Se ti stai fortemente impegnando a iniziare oppure a migliorare le tue abilità, è spesso anche troppo facile andare sui social o cercare cose su internet. Se decidi di fare 20 minuti di pratica, è importante che questi 20 minuti siano dedicati totalmente a quell’attività e che siano il più produttivi possibile.
Consiglio pratico n.7. Prima di iniziare a fare pratica, cerca di eliminare quanti più elementi di distrazione possibile. Per esempio, disconnetti da internet, metti il telefono in un’altra stanza e cerca un posto per fare pratica in cui difficilmente verrai disturbato. Cerca di focalizzarti sulla tua attività di live coding e poi successivamente potrai tornare alle tue distrazioni quando avrai finito.
Mentre stai facendo pratica, spesso potresti avere in mente molte idee nuove ed eccitanti. Per esempio nuove direzioni musicali, nuovi suoni, nuove funzioni ecc. Queste idee a volte possono essere talmente interessanti che potresti fermarti e provare a realizzarle. Comunque, anche questa è una forma di distrazione!
Consiglio pratico n.8. Tieni un diario della tua pratica vicino alla tastiera. Quando hai delle idee che ti piacciono particolarmente, ferma un attimo la tua sessione di pratica e sbozza velocemente l’idea sul diario. Appena finito, dimenticatela e vai avanti con la sessione. Potrai quindi tornare indietro successivamente su quell’idea e pensarci con maggiore attenzione.
Cerca di mettere a punto una routine di pratica che includa queste idee nel più gran numero possibile. Cerca di rendere le sessioni il più divertenti possibile ma sii sempre consapevole che alcune sessioni saranno dure e sentirai di aver svolto un lavoro insoddisfacente. Tuttavia, tutto ti sarà stato utile quando avrai creato il tuo primo brano o avrai eseguito il tuo primo concerto. Ricordati, la pratica è la chiave per il successo!
Quando le persone scoprono Sonic Pi, una delle prime cose che impara è quanto sia semplice riprodurre suoni pre-registrati usando la funzione sample
. Ad esempio, puoi suonare un loop di tamburo industriale, ascoltare il suono di un coro o anche ascoltare un graffio di vinile tutto attraverso una singola riga di codice. Tuttavia, molte persone non si rendono conto che è possibile effettivamente variare la velocità, il campione viene riprodotto per alcuni effetti potenti e un nuovo livello di controllo sui suoni registrati. Quindi, scarica una copia di Sonic Pi e iniziamo a giocare con alcuni campioni!
Per modificare la frequenza di riproduzione di un campione dobbiamo utilizzare il rate:
opt:
sample :guit_em9, rate: 1
Se si specifica un rate:
di 1
allora il campione viene riprodotto alla velocità normale. Se vogliamo riprodurlo ad una velocità dimezzata, usiamo semplicemente una rate:
di 0.5
:
sample :guit_em9, rate: 0.5
Tieni conto che questo ha un duplice effetto sul suono. In primo luogo il campione suonerà più basso, più grave e in secondo luogo ci metterà il doppio ad essere riprodotto (dai un’occhiata alla barra laterale per una spiegazione più approfondita). Possiamo addirittura scegliere anche dei valori ancora più bassi avvicinandoci allo ‘0’. Per esempio ‘0.25’ è un quarto della velocità originale, ‘0.1’ è un decimo e così via. Prova a suonare i campioni utilizzando numeri bassi e osserva come puoi trasformare il suono in una specie di basso ruggito.
Oltre a prolungare ed abbassare i suoni mediante l’abbassamento del valore di rate, possiamo utilizzare dei valori più alti per accorciare e rendere più acuti i suoni. Proviamo a riprodurre un loop di batteria stavolta. Per prima cosa, prova ad ascoltare come suona alla velocità normale: ‘1’:
sample :loop_amen, rate: 1
Ora acceleriamoli un pò:
sample :loop_amen, rate: 1.5
Ha! Ci siamo appena spostati di genere musicale dalla techno vecchia scuola alla jungle. Nota come l’intonazione di ogni colpo di batteria è più alta e come l’intera sezione ritmica accelera. Ora, prova rate ancora più alte e verifica quanto alto e corto puoi rendere il loop di batteria. Ad esempio, se usi un rate di 100
, il loop di batteria diventa un click!
Ora, sono sicuro che molti di voi stanno pensando la stessa cosa adesso … “cosa succede se si utilizza un numero negativo per il rate?”. Grande domanda! Pensiamo a questo per un momento. Se il nostro rate:
opt significa la velocità con cui viene riprodotto il campione, 1
è la velocità normale, 2
è doppia velocità, 0.5
è mezza velocità, -1
deve significare all’indietro! Proviamolo su un rullante. Innanzitutto, riprodurlo al ritmo normale:
sample :elec_filt_snare, rate: 1
Adesso fallo andare all’incontrario:
sample :elec_filt_snare, rate: -1
Naturalmente, puoi riprodurlo al contrario al doppio della velocità con il rate a -2
oppure al contrario a mezza velocità con un rate a -0.5
. Ora, prova a giocare con differenti rate negativi e divertiti. E’ particolarmente divertente con il sample :misc_burp
!
Uno degli effetti del cambio di frequenza sui campioni è che frequenze più veloci portano i campioni a suonare più acuti e frequenze più lente portano i campioni a suonare più gravi in intonazione. Un altro contesto in cui potresti aver sentito questo effetto nella vita di tutti i giorni è quando passi in bicicletta o in macchina vicino al cicalino di un attraversamento pedonale - quando ti stai avvicinando l’intonazione è più alta di quando ti stai allontanando - il così detto effetto Doppler. Perché accade?
Consideriamo un semplice beep che è rappresentato da un’onda sinusoidale. Se usiamo un oscilloscopio per tracciare un beep, vedremmo qualcosa tipo la Figura A. Se tracciamo un beep un ottava più in alto, vedremo la Figura B e un ottava più in basso sarà come nella Figura C. Nota che le forme d’onda di note più alte sono più compatte mentre le forme d’onda di note più basse sono più dilatate.
Il campione di un beep non è altro che un insieme di molti numeri (coordinate, x,y) le quali quando tracciate in un grafico ridisegneranno le curve originali. Vedi la figura D in cui ogni cerchio rappresenta una coordinata. Per riconvertire le coordinate in audio, il computer valuta ogni valore di x e lo manda manda il corrispondente valore di y ai diffusori. Il trucco qui sta nel fatto che la frequenza alla quale il computer lavora i numeri x non deve essere la stessa frequenza alla quale sono stati registrati. In altre parole, lo spazio (che rappresenta un intervallo di tempo) fra ogni cerchio può essere allungato o compresso. Così, se il computer processa i valori di x più velocemente della frequenza originale, avrà l’effetto di schiacciare i cerchi più vicini tra loro, il che risulterà in un segnale acustico più acuto. Causerà inoltre un beep più corto in quanto processeremo tutti i cerchi più velocemente. Questo è mostrato nella figura E.
Infine, un’ultima cosa da sapere è che un matematico chiamato Fourier ha provato che ogni suono è in effetti costituito da moltissime onde sinusoidali combinate insieme. Quindi, quando comprimiamo e allunghiamo qualunque suono registrato, stiamo in realtà comprimendo e allungando molte onde sinusoidali simultaneamente in questo modo.
Come abbiamo visto, una frequenza più veloce porterà a un suono più alto in intonazione e una frequenza più lenta porterà a suono più basso in intonazione. Un trucchetto molto semplice e veloce consiste nel sapere che a un raddoppio della frequenza corrisponde un’intonazione più alta di un’ottava e, inversamente, il dimezzamento della frequenza corrisponde un’intonazione più bassa di un’ottava. Questo significa che per i sample melodici, riprodurli su sè stessi al doppio o alla metà della loro frequenza li fa suonare piuttosto bene:
sample :bass_trance_c, rate: 1
sample :bass_trance_c, rate: 2
sample :bass_trance_c, rate: 0.5
Tuttavia, come dobbiamo procedere se vogliamo alterare la frequenza in modo che alzi di un semitono (una nota più avanti sul piano)? Sonic Pi rende questo molto semplice attraverso l’opzione rpitch:
:
sample :bass_trance_c
sample :bass_trance_c, rpitch: 3
sample :bass_trance_c, rpitch: 7
Se dai un’occhiata al registro eventi sulla destra, noterai che un rpitch:
di 3
corrisponde in effetti a una frequenza di 1.1892
mentre rpitch:
di 7
corrisponde a una frequenza di 1.4983
. Infine possiamo anche combinare le opzioni rate:
e rpitch:
:
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
Diamo un’occhiata a un semplice brano che combina queste idee. Copia in un buffer Sonic Pi vuoto, premi play, ascolta per un po’ e poi usalo come punto di partenza per il tuo brano personale. Guarda quanto è divertente manipolare la frequenza di riproduzione dei sample. Come esercizio aggiuntivo prova a registrare dei tuoi suoni a giocare con le frequenze per vedere che razza di suoni selvaggi puoi creare.
live_loop :beats do
sample :guit_em9, rate: [0.25, 0.5, -1].choose, amp: 2
sample :loop_garzul, rate: [0.5, 1].choose
sleep 8
end
live_loop :melody do
oct = [-1, 1, 2].choose * 12
with_fx :reverb, amp: 2 do
16.times do
n = (scale 0, :minor_pentatonic).choose
sample :bass_voxy_hit_c, rpitch: n + 4 + oct
sleep 0.125
end
end
end
Questo è il primo di una breve serie di articoli su come usare Sonic Pi per il Sound Design. Faremo un rapido tour attraverso un certo numero di tecniche che sono disponibili per creare il tuo suono unico. La prima tecnica che vedremo è chiamata sintesi additiva”. Potrebbe sembrare complicato - ma se riflettiamo brevemente sulle parole, il significato esce fuori subito. Innanzitutto additivo significa una combinazione di cose e secondariamente sintesi significa creare suono. Sintesi additiva significa quindi niente di più complesse che *combinare suoni esistenti per crearne di nuovi. Questa tecnica di sintesi risale a molto tempo fa - ad esempio gli organi a canne nel medio evo avevano molte canne dai suoni diversi che potevi abilitare o disabilitare con degli appositi blocchi. Rimuovendo il blocco di una certa canna ‘la aggiungeva al mix’ creando un suono più ricco e complesso. Ora, vediamo come possiamo rimuovere questi blocchi con Sonic Pi.
Cominciamo con il suono più basico che ci sia - l’umile e pura onda sinusoidale:
synth :sine, note: :d3
Ora, vediamo questo suono combinato con un’onda quadra:
synth :sine, note: :d3
synth :square, note: :d3
Nota come i due suoni combinati formano un nuovo e più ricco suono. Naturalmente, non dobbiamo fermarci qui, possiamo aggiungere tutti i suoni di qui abbiamo bisogno. Tuttavia, dobbiamo anche stare attenti a quanti suoni aggiungiamo insieme. Proprio come quando combiniamo pitture per creare nuovi colori, aggiungendone troppi otteniamo un paciugo marrone, similmente aggiungendo troppi suoni otterremo un suono impastato.
Aggiungiamo qualcosa per ottenere un suono più chiaro. Possiamo usare un’onda triangolare in un’ottava più alta (per ottenere quel suono più chiaro) solo però riprodotta con amp 0.4
in modo che aggiunga un extra al suono senza però coprirlo:
synth :sine, note: :d3
synth :square, note: :d3
synth :tri, note: :d4, amp: 0.4
Ora, prova a creare i tuoi suoni combinando 2 o più synth in ottave e amplificazioni differenti. Nota anche come puoi giocare con le opzioni di ciascun synth per modificare ogni sorgente sonora prima del mix per ottenere ulteriori combinazioni di suoni.
Fino a ora, combinando i nostri diversi synth abbiamo usato la stessa intonazione o cambiato ottava. Come suonerebbe se non cambiassimo solo le ottave ma invece applicassimo una nota lievemente più alta o più bassa? Proviamo:
detune = 0.7
synth :square, note: :e3
synth :square, note: :e3 + detune
Se applichiamo una scordatura alle nostre onde quadre di 0.7 note, sentiremo forse qualcosa che non suona corretto o intonato - una ‘brutta’ nota. Tuttavia, muovendoci più vicini allo 0 suonerà sempre meno stonata man mano che l’intonazione delle 2 onde si avvicina e diventa simile. Prova tu stesso! Modifica l’opzione detune:
da 0.7
a 0.5
e ascolta il nuovo suono. Prova 0.2
, 0.1
, 0.05
, 0
. Ogni volta che cambi il valore, ascolta e nota come cambia il suono. Nota che una scordatura più bassa come 0.1
produce un suono ‘denso’ molto bello, con entrambi i suoni lievemente alterati che interagiscono fra loro vengono fuori combinazioni interessanti e spesso sorprendenti.
:dsaw
Un altro modo con cui possiamo finemente modellare il suono consiste nell’usare differenti envelope e opzioni per ogni innesco dei synth. Ad esempio questo vi permetterà di gestire alcuni aspetti percussivi del suono ed altri aspetti che riguardano la durata nel tempo.
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
Nell’esempio sopra, ho mixato un elemento di rumore percussivo con un brontolio persistente in sottofondo. Questo è stato ottenuto innanzitutto usando 2 synth rumore con valori cutoff intermedi (90
e 100
) usando tempi di rilascio brevi insieme a rumori con un rilascio più lungo ma con un valore cutoff più basso (il che rende il rumore meno nitido e più rumoroso.)
Combiniamo tutte queste tecniche per vedere se possiamo usare la sintesi additiva per creare un suono basico di campana. Ho diviso questo esempio in 4 sezioni. Prima abbiamo la sezione ‘hit’ che è la parte iniziale del suono della campana - quindi usa un inviluppo corto (e.g. una release:
di circa 0.1
). Poi abbiamo la lunga sezione di risonanza nella quale uso il suono puro dell’onda sinusoidale. Nota che spesso aumento la nota di circa 12
e 24
che sono il numero di note in una e due ottave. Ho anche inserito un paio di onde sinusoidali basse per dare al suono un po’ di bassi e profondità. Infine, ho usato define
per racchiudere il mio codice in una funzione che posso quindi utilizzare per suonare una melodia. Prova a suonare la tua melodia e anche a incasinare i contenuti della funzione :bell
finché non crei il tuo suono divertente con cui suonare!
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
Questo è il secondo di una serie di articoli su come utilizzare Sonic Pi per il sound design. Il mese scorso abbiamo esaminato la sintesi additiva che abbiamo scoperto fosse il semplice atto di suonare più suoni contemporaneamente per creare un nuovo suono combinato. Ad esempio, potremmo combinare sintetizzatori con diversi suoni o anche lo stesso sintetizzatore a diverse intonazioni per costruire un nuovo suono complesso da ingredienti semplici. Questo mese esamineremo una nuova tecnica comunemente chiamata sintesi sottrattiva che è semplicemente consiste nel prendere un suono complesso esistente e rimuoverne parti per creare qualcosa di nuovo. Questa è una tecnica comunemente associata al suono dei sintetizzatori analogici degli anni ‘60 e ‘70, ma anche alla recente rinascita dei sintetizzatori analogici modulari attraverso standard popolari come Eurorack.
Nonostante sembri una tecnica particolarmente complicata e avanzata, Sonic Pi la rende sorprendentemente semplice, quindi entriamoci subito.
Affinché un suono funzioni bene con la sintesi sottrattiva, in genere deve essere sufficientemente ricco e interessante. Questo non significa che abbiamo bisogno di qualcosa di estremamente complesso - infatti, solo un’onda standard :square
o :saw
produrrà:
synth :saw, note: :e2, release: 4
Nota che questo suono è già piuttosto interessante e contiene molte frequenze diverse sopra :e2
(il secondo MI su un pianoforte) che si aggiungono per creare il timbro. Se ti sembra che non abbia molto senso, prova a confrontarlo con :beep
:
synth :beep, note: :e2, release: 4
Poiché il synth :beep
è solo un’onda sinusoidale, sentirai un tono molto più puro e solo a :e2
e nessuno dei suoni acuti e nitidi che hai sentito con :saw
. Questa vivacità e variazione da un’onda sinusoidale pura costituiscono il materiale con cui possiamo giocare quando utilizziamo la sintesi sottrattiva.
Una volta che abbiamo il nostro segnale sorgente grezzo, il passo successivo è farlo passare attraverso un filtro di qualche tipo che modificherà il suono rimuovendo o riducendone alcune parti. Uno dei filtri più comuni utilizzati per la sintesi sottrattiva è il cosiddetto filtro passa basso. Ciò consentirà il passaggio di tutte le parti basse del suono, ma ridurrà o rimuoverà le parti più alte. Sonic Pi ha un sistema FX potente ma comunque semplice da usare che include un filtro passa basso, chiamato :lpf
. Giochiamoci un po’:
with_fx :lpf, cutoff: 100 do
synth :saw, note: :e2, release: 4
end
Se ascolti attentamente, sentirai come un po’ di quel brusio e quella nitidezza sono state rimosse. Infatti, tutte le frequenze nel suono sopra la nota 100
sono state ridotte o rimosse e solo quelle sotto sono ancora presenti nel suono. Prova a cambiare quel “cutoff:” punta alle note più basse, diciamo dì “70” e poi “50” e confronta i suoni.
Naturalmente, :lpf
non è l’unico filtro che puoi usare per manipolare il segnale sorgente. Un altro effetto importante è il filtro passa alto denominato :hpf
in Sonic Pi. Questo fa l’opposto di :lpf
in quanto lascia passare le parti alte del suono e taglia le parti basse.
with_fx :hpf, cutoff: 90 do
synth :saw, note: :e2, release: 4
end
Nota come questo suona con molto più ronzio e in modo roco ora che tutti i suoni a bassa frequenza sono stati rimossi. Prova a cambiare il valore di cutoff: nota come valori più bassi lasciano passare più parti dei bassi originali del segnale sorgente e valori più alti suonano sempre più metallici e silenziosi.
:prophet
Finora abbiamo appena prodotto suoni abbastanza statici. In altre parole, il suono non cambia in alcun modo per tutta la sua durata. Spesso potresti volere un po’ di movimento nel suono per dare vita al timbro. Un modo per ottenere ciò è tramite la modulazione del filtro - modificando le opzioni del filtro nel tempo. Fortunatamente Sonic Pi ti offre potenti strumenti per manipolare le opzioni di un FX nel tempo. Ad esempio, puoi impostare un tempo di transizione per ciascuna opzione modulabile per specificare quanto tempo dovrebbe impiegare il valore corrente per scorrere linearmente fino al valore di destinazione:
with_fx :lpf, cutoff: 50 do |fx|
control fx, cutoff_slide: 3, cutoff: 130
synth :prophet, note: :e2, sustain: 3.5
end
Diamo una rapida occhiata a cosa sta succedendo qui. Innanzitutto iniziamo un blocco FX :lpf
normale con un cutoff:
iniziale basso di un 50
. Tuttavia, la prima riga termina anche con uno strano |fx|
alla fine. Questa è una parte opzionale della sintassi with_fx
che ti permette di denominare e controllare direttamente il synth FX in esecuzione. La riga 2 fa esattamente questo e controlla l’FX per impostare opzione cutoff_slide:
a 3 e il nuovo valore di destinazione cutoff:
a 130
. L’FX ora inizierà a muovere il valore di cutoff:
da 50
a 130
lungo un periodo di 3 battiti. Infine attiviamo anche un sintetizzatore del segnale sorgente in modo da poter ascoltare l’effetto del filtro passa basso modulato.
Questo è solo un assaggio molto semplice di ciò che è possibile ottenere quando si utilizzano i filtri per modificare e cambiare un suono sorgente. Prova a giocare con i numerosi effetti integrati di Sonic Pi per vedere quali suoni divertenti puoi progettare. Se il tuo suono sembra troppo statico, ricorda che puoi iniziare a modulare le opzioni per creare un po’ di movimento.
Concludiamo progettando una funzione che riprodurrà un nuovo suono creato con sintesi sottrattiva. Guarda se riesci a capire cosa sta succedendo qui - e per gli utenti avanzati di Sonic Pi - guardate se riuscite a capire perché ho racchiuso tutto in una chiamata a at
(per favore inviate le risposte a @samaaron su Twitter).
define :subt_synth do |note, sus|
at do
with_fx :lpf, cutoff: 40, amp: 2 do |fx|
control fx, cutoff_slide: 6, cutoff: 100
synth :prophet, note: note, sustain: sus
end
with_fx :hpf, cutoff_slide: 0.01 do |fx|
synth :dsaw, note: note + 12, sustain: sus
(sus * 8).times do
control fx, cutoff: rrand(70, 110)
sleep 0.125
end
end
end
end
subt_synth :e1, 8
sleep 8
subt_synth :e1 - 4, 8
(Questo articolo è stato pubblicato in issue 9 di Hello World Magazine)
Il codice programmazione è uno dei media più creativi che gli esseri umani abbiano creato. I simboli inizialmente oscuri di parentesi e lambda non sono solo profondamente radicati nella scienza e nella matematica, sono i più vicini che siamo riusciti a ottenere per lanciare lo stesso tipo di incantesimi come Gandalf e Harry Potter. Credo che questo fornisca un potente mezzo di coinvolgimento nei nostri spazi di apprendimento. Attraverso la magia del codice siamo in grado di evocare storie ed esperienze individuali di apprendimento significative.
Siamo circondati da esperienze magiche. Dal gioco di prestigio di un mago del palcoscenico che fa sparire la palla nel nulla, alla meraviglia di vedere la tua band preferita esibirsi su un grande palco. Sono questi momenti “wow” che ci ispirano a prendere in mano un libro magico e imparare il French Drop o ad iniziare a suonare power chords su una vecchia chitarra. Come potremmo creare sensi di meraviglia altrettanto profondi e duraturi che motiveranno le persone a esercitarsi e ad apprendere i fondamenti della programmazione?
Storie di musica e di computer sono state intrecciate fin dall’inizio delle macchine computazionali, o “motori”, come veniva chiamato il potente motore analitico di Charles Babbage. Già nel 1842 la matematica Ada Lovelace, che lavorò a stretto contatto con Babbage, vide il potenziale creativo di questi motori. Mentre questi primi motori erano stati originariamente progettati per risolvere accuratamente problemi di matematica complessi, Ada sognava di fare musica con loro:
“…il motore potrebbe comporre brani musicali elaborati e scientifici di qualsiasi grado di complessità o estensione.” Ada Lovelace, 1842.
Naturalmente, oggi nel 2019 gran parte della nostra musica, indipendentemente dal genere, è stata composta, prodotta o masterizzata con un computer digitale. Il sogno di Ada si è avverato. È anche possibile risalire ulteriormente alla storia. Se vedi la programmazione come l’arte di scrivere sequenze di simboli speciali che forniscono istruzioni a un computer per fare cose specifiche, allora la composizione musicale è una pratica molto simile. Nella musica occidentale, i simboli sono punti neri posizionati su un pentagramma di linee che indicano al musicista quali note suonare e quando. Curiosamente, se facciamo risalire le radici della notazione musicale occidentale al monaco benedettino italiano Guido d’Arezzo, scopriamo che il sistema di punti e linee utilizzato dalle orchestre moderne è solo uno dei numerosi sistemi di notazione su cui ha lavorato. Alcuni degli altri erano molto più vicini a quello che ora potremmo vedere come codice di programmazione.
Get
Programmare dal vivo
Sonic Pi è stato utilizzato per esibirsi in una vasta gamma di luoghi come aule scolastiche, discoteche, palchi all’aperto in festival musicali, cappelle universitarie e prestigiosi locali musicali. Ad esempio lo straordinario progetto Convo che ha riunito 1000 bambini nella Royal Albert Hall per eseguire una nuova ambiziosa composizione della compositrice Charlotte Harding. Il pezzo è stato scritto per strumenti tradizionali, cori, percussioni e codice Sonic Pi. L’artista pop Jylda si è anche esibita con Sonic Pi al Sage Gateshead per la Conferenza Thinking Digital, dove ha creato un remix unico e improvvisato dal vivo della sua canzone Reeled.
Sonic Pi usato come uno degli strumenti come parte del Convo presso la Royal Albert Hall. Foto: Pete Jones.
Sonic Pi è uno strumento di creazione e performance musicale basato su codice che si basa su tutte queste idee. A differenza della maggior parte dei software didattici, è sia abbastanza semplice da usare per l’istruzione che anche abbastanza potente per i professionisti. È stato utilizzato per esibirsi in festival musicali internazionali, per comporre in una vasta gamma di stili dalla classica, all’EDM e all’heavy metal ed è stato persino recensito sulla rivista Rolling Stone. Ha una comunità diversificata di oltre 1,5 milioni di programmatori live con una varietà di background che apprendono e condividono idee e pensieri attraverso il codice di programmazione. È scaricabile gratuitamente per Mac, PC e Raspberry Pi e include un tutorial amichevole che presuppone che tu non sappia nulla né di programmazione né di musica.
Sonic Pi è stato inizialmente concepito come una risposta al curriculum di informatica pubblicato nel Regno Unito nel 2014. L’obiettivo era trovare un modo motivante e divertente per insegnare i fondamenti della programmazione. Si scopre che c’è molto in comune ed è molto divertente spiegare il sequenziamento come melodia, l’iterazione come ritmo, i condizionali come varietà musicale. Ho sviluppato i progetti iniziali e le prime iterazioni della piattaforma con Carrie Anne Philbin, che ha portato il punto di vista di un insegnante al progetto. Da allora, Sonic Pi ha subito miglioramenti iterativi grazie al feedback ottenuto osservando gli studenti e collaborando direttamente con gli educatori in classe. Una filosofia di base nella progettazione era quella di non aggiungere mai una caratteristica che non potesse essere insegnata facilmente a un bambino di 10 anni. Ciò significava che la maggior parte delle idee doveva essere pesantemente rifinita e rielaborata fino a renderla abbastanza semplice. Rendere le cose semplici pur mantenendole potenti continua a essere la parte più difficile del progetto.
Al fine di fornire la motivazione magica, il design di Sonic Pi non si è mai limitato a un puro scopo di istruzione. Idealmente ci sarebbero musicisti e artisti famosi che usano Sonic Pi come strumento standard insieme a chitarre, batteria, voce, sintetizzatori, violini, ecc. Questi artisti agirebbero quindi come modelli motivazionali dimostrando il potenziale creativo del codice di programmazione. Affinché ciò fosse possibile, è stato quindi necessario dedicare sufficiente attenzione e sforzo per renderlo uno strumento potente pur mantenendolo abbastanza semplice da poter essere assimilato dai bambini di 10 anni. Oltre agli educatori, ho anche lavorato direttamente con una varietà di artisti diversi in classi, gallerie d’arte, studi e luoghi nelle prime fasi dello sviluppo di Sonic Pi. Ciò ha fornito un feedback essenziale che ha consentito a Sonic Pi di crescere e, infine, prosperare come strumento per l’espressione creativa.
Ci sono stati una serie di effetti collaterali eccitanti e inaspettati di questa doppia attenzione all’istruzione e ai musicisti professionisti. Molte delle caratteristiche sono vantaggiose per entrambi i gruppi. Ad esempio, è stato fatto un grande sforzo per rendere i messaggi di errore più amichevoli e utili (piuttosto che essere un enorme complicato pasticcio di gergo). Questo risulta essere molto utile quando scrivi un bug mentre ti esibisci di fronte a migliaia di persone. Inoltre, funzionalità come la riproduzione di campioni audio di qualità da studio, l’aggiunta di effetti audio, l’accesso all’audio dal vivo dal microfono, rendono l’esperienza di apprendimento più divertente, gratificante e, in definitiva, significativa.
La community di Sonic Pi continua a crescere e a condividere incredibili composizioni di codici, piani formativi, algoritmi musicali e molto altro. Gran parte di questo accade nel nostro amichevole forum in_thread (in-thread.sonic-pi.net) che ospita un gruppo molto diversificato di persone che include educatori, musicisti, programmatori, artisti e creatori. È una vera gioia vedere le persone imparare a usare il codice per esprimersi in modi nuovi e questo a sua volta ispira gli altri a fare lo stesso.
Dal punto di vista dell’informatica, Sonic Pi ti fornisce i fondamenti di conoscenza per insegnarti le nozioni di base che si trovano nel curriculum del Regno Unito come sequenziamento, iterazione, condizionali, funzioni, strutture dati, algoritmi, ecc. Tuttavia, si basa anche su un numero di concetti importanti e rilevanti che sono stati adottati nell’industria tradizionale come concorrenza, eventi, comparazione di pattern, calcolo distribuito e determinismo, il tutto mantenendo le cose abbastanza semplici da poter essere spiegate a un bambino di 10 anni.
Get
play 70
Una melodia può essere costruita con un ulteriore comando, sleep:
play 72
sleep 0.5
play 75
sleep 0.5
play 79
In questo esempio, suoniamo la nota 70 (all’incirca la settantesima nota su un pianoforte), attendiamo 1 secondo, suoniamo la nota 72, attendiamo mezzo secondo e quindi suoniamo la nota 75. La cosa interessante qui è che con solo due comandi abbiamo l’accesso a praticamente tutta la notazione occidentale (quali note suonare e quando) e gli studenti possono programmare qualsiasi melodia che abbiano mai sentito. Ciò porta a un’enorme varietà di risultati espressivi mentre ci si concentra sullo stesso concetto di calcolo: il sequenziamento in questo caso.
Prendendo spunti dal mondo della musica professionale, possiamo anche riprodurre qualsiasi suono registrato. Sonic Pi può riprodurre qualsiasi file audio sul tuo computer, ma ha anche una serie di suoni integrati per rendere le cose facili subito dall’inizio:
sample :loop_amen
Questo codice riprodurrà un ritmo di batteria che è stato una pietra miliare del primo hip-hop, Drum and Bass e Jungle. Ad esempio, un certo numero di primi artisti hip-hop hanno suonato questo ritmo di batteria a velocità dimezzata per dargli un andamento più rilassato:
sample :loop_amen, rate: 0.5
Negli anni ‘90 una serie di scene musicali sono esplose grazie alla nuova tecnologia che ha consentito agli artisti di smontare le parti di batteria come questa e di riassemblarle in un ordine diverso. Per esempio:
sample :loop_amen
rand
Questa sezione copre alcune informazioni essenziali per ottenere il massimo da Sonic Pi.
Vedremo insieme le scorciatoie da tastiera che puoi utilizzare, come condividere il tuo lavoro e qualche consiglio su come esibirti con Sonic Pi.
Sonic Pi è uno strumento così come è un ambiente di sviluppo. Le scorciatoie possono rendere l’esperienza di Sonic Pi più efficace e naturale, soprattutto se suoni live di fronte a un pubblico.
Sonic Pi può essere controllato in larga parte grazie alla tastiera. Familiarizzando con Sonic Pi, comincerai a utilizzare sempre di più le scorciatoie. Io suono con la tastiera (e vi consiglio di imparare a farlo) e mi ritrovo ad essere frustrato ogni volta che devo usare il mouse perché mi rallenta. Per questo uso queste scorciatoie regolarmente!
Se impari a utilizzare le scorciatoie, programmerai live come un professionista in men che non si dica.
Mi raccomando: non provare a impararli tutti in una volta, cerca di ricordare quelli che usi più spesso e di aggiungerne qualcuno a mano a mano che ti eserciti.
Immagina se stessi imparando a suonare il clarinetto. Ti aspetteresti che ogni clarinetto abbia gli stessi controlli e la stessa ditteggiatura. Se così non fosse, faresti fatica a suonare clarinetti diversi e saresti costretto a usarne soltanto uno.
Sfortunatamente ci sono tre sistemi operativi principalmente: Linux, Max OSX e Windows che hanno le loro funzioni standard per azioni come taglia e incolla, ecc… Sonic Pi cerca di rispettare questi standard. Tuttavia la priorità è mantenere una coerenza tra le piattaforme all’interno di Sonic Pi invece che adattarsi agli standard di ciascuna piattaforma. Questo significa che quando impari le scorciatoie usando Sonic Pi sul tuo Raspberry Pi, puoi spostarti su Mac o PC e sentirti a casa.
La prima parte relativa alla coerenza è relativa ai nomi delle abbreviazioni. In Sonic Pi usiamo i nome Controllo e Meta per fare riferimento a due combinazioni di tasti. Su tutte le piattaforme Controllo è lo stesso invece su Linux e Windows Meta è il tasto Alt mentre su Mac Meta è il tasto Command. Per coerenza useremo il termina Meta, ricordati solo di mapparlo nel modo corretto con la tastiera del tuo sistema operativo.
Per semplicità utilizzeremo delle abbreviazioni C- per Controllo e M- per Meta. Per esempio se per una scorciatoia devi tenere premuti contemporaneamente Meta e r noi scriveremo M-r. Il - indica “premi insieme.”
Questi sono alcune delle scorciatoie più utili.
Invece che andare alla ricerca del mouse per far funzionare il tuo codice, puoi premere M-r
. Allo stesso modo, per fermare premi M-s
.
Io mi sento davvero perso senza le scorciatoie di navigazione. Per questo ti consiglio di investire parte del tuo tempo per impararle. Queste scorciatoie funzionano molto bene quando vuoi muoverti solo utilizzando la tastiera invece che muovendo il mouse o le frecce sulla tastiera.
Puoi muoverti all’inizio della riga con C-a
, alla fine della riga con C-e
, alla riga precedente C-p
oppure su quella successiva C-n
, avanti di un carattere C-f
oppure indietro di uno C-b
. Puoi anche eliminare tutti i caratteri partendo dalla posizione del cursore fino alla fine della riga con C-k
.
Per allineare automaticamente il codice, premi semplicemente ‘M-m’.
Per aprire il pannello di aiuto, puoi premere M-i
. Tuttavia è importante conoscere anche la scorciatoia C-i
che ti aiuta a trovare nella documentazione la parola che si trova sotto il cursore per un aiuto immediato!
Per una lista completa, dai un’occhiata alla sezione 10.2 con il riassunto di tutte le scorciatoie.
Quello che segue è un riassunto delle principali scorciatoie disponibili in Sonic Pi. Dai un’occhiata alla sezione 10.1 per avere un background in merito.
In questa lista vengono usate le seguenti convenzioni (dove Meta è Alt su Windows/Linux o Cmd su Mac):
C-a
significa tieni premuto Control e il tasto a contemporaneamente.M-r
significa tieni premuti il tasto Meta e poi premi r.S-M-z
vuol dire premi contemporaneamente Shift, Meta e il tasto z.C-M-f
significa premi Control, Meta e f contemporaneamente.M-r
- Avvia il codiceM-s
- Ferma il codiceM-i
- Apri/Chiudi il sistema di aiutoM-p
- Apri/Chiudi le preferenzeM-{
- Sposta il buffer a sinistraM-}
- Sposta il buffer a destraS-M-0
- Passa al buffer 0S-M-1
- Passa al buffer 1S-M-9
- Passa al buffer 9M-+
- Ingrandisci la dimensione carattere del buffer correnteM--
- Diminuisci la grandezza dei caratteri nel buffer correnteM-a
- Seleziona tuttoM-c
- CopiaM-]
- CopiaM-x
- TagliaC-]
- TagliaC-k
- Taglia fino alla fine della rigaM-v
- IncollaC-y
- IncollaC-SPACE
- Imposta un segnalibro. La navigazione controllerà la regione selezionata. Premi C-g
per uscire.M-m
- Allinea il testoTab
- Allinea la linea corrente (oppure seleziona l’autocompletamento)C-l
- Centra l’editorM-/
- Commenta/Scommenta la linea correnteC-t
- Trasponi/scambia caratteriM-u
- Converti la parola successiva in maiuscolo.M-l
- Converti la parola successiva in minuscolo.C-a
- Spostati all’inizio della rigaC-e
- Spostati alla fine della rigaC-p
- Spostati alla linea precedenteC-n
- Spostati su quella successivaC-f
- Spostati avanti di un carattereC-b
- Spostati indietro di un carattereM-f
- Spostati avanti di una parolaM-b
- Spostati indietro di una parolaC-M-n
- Sposta linea o selezione in bassoC-M-p
- Sposta linea o selezione in altoS-M-u
- Spostati in su di 10 righeS-M-d
- Spostati in giù di 10 righeM-<
- Spostati all’inizio del bufferM->
- Spostati alla fine del bufferC-h
- Cancella il carattere precedenteC-d
- Cancella il carattere successivoS-M-s
- Salva il contenuto del buffer in un fileS-M-o
- Carica il contenuto del buffer da un fileSonic Pi è molto incentrato sulla condivisione e sull’apprendimento in compagnia.
Una volta che avrai imparato a codificare la musica, condividere le tue composizioni sarà semplice come mandare delle email contenenti il tuo programma. Per favore, condividi il tuo codice con gli altri in modo tale da fagli imparare dal tuo lavoro e anche riutilizzarne delle parti all’interno di nuovi brani.
Se non sai quale sia il modo migliore per condividere il tuo lavoro con gli/le altri/e, ti consiglio di metterlo su GitHub. La tua musica invece può essere messa su SoundCloud. In questo modo potrai raggiungere facilmente un pubblico molto vasto.
GitHub è un sito per condividere e lavorare sul codice. E’ utilizzato da sviluppatori professionisti ma anche da artisti per condividere e collaborare. Il modo più semplice per condividere un nuovo programma (anche un brano non completo) è quello di creare una Gist. Gist è un modo facile di caricare il tuo codice in un modo che gli altri possano vederlo, copiarlo e condividerlo a loro volta.
Un altro modo in cui puoi condividere il tuo lavoro è di registrare l’audio e di caricarlo su SoundCloud. Una volta che avrai caricato il tuo brano, gli altri utenti possono commentarlo. Ti raccomando di mettere un collegamento al tuo Gist nella descrizione del brano.
Per registrare il tuo lavoro, premi il tasto ‘Rec’ in alto e la registrazione comincerà immediatamente. Premi anche ‘Run’ per iniziare a suonare, se non l’hai già fatto. Quando hai finito di registrare, basta semplicemente premere nuovamente il bottone lampeggiante ‘Rec’ e ti apparirà una piccola finestra per inserire il nome desiderato. Il brano sarà salvato in formato WAV, che poi può essere modificato e convertito in MP3. Ci sono molti programmi validi e gratuiti per far questo (prova Audacity per esempio).
Ti incoraggio a condividere il tuo lavoro e spero veramente che riusciremo a insegnarci l’un l’altro nuove scorciatoie e tecniche per utilizzare Sonic Pi. Sono molto ansioso di vedere cosa mi vorrai mostrare.
Uno degli aspetti più eccitanti di Sonic Pi è che ti permette di usare il codice come uno strumento musicale. Questo significa che scrivere codice live può essere visto come un modo nuovo di esibirsi.
Noi lo chiamiamo Live Coding.
Quando programmi live, ti consiglio di mostrare lo schermo al tuo pubblico. Altrimenti sarebbe come suonare la chitarra nascondendo le dita. Quando faccio pratica, uso un Raspberry Pi con collegato un piccolo proiettore in salotto. Puoi usare la TV o un proiettore per fare il tuo show. Provaci, è molto divertente.
Non limitarti a suonare da solo: forma una band di programmazione dal vivo! È molto divertente suonare con gli altri. Una persona potrebbe suonare ritmi, un’altra sottofondo ambientale, ecc. Usa la funzionalità live_audio
per combinare il codice con strumenti tradizionali come una chitarra o un microfono.
Guarda quali combinazioni di suoni interessanti puoi creare col codice di programmazione.
La programmazione live non è un concetto nuovo: un piccolo gruppo di persone lo fa da anni (usando sistemi costruiti su misura). Un ottimo posto per scoprire di più è TOPLAP.
Un’altra importante risorsa per esplorare il live coding è il mondo degli Algorave. Sul sito puoi trovare tutte le informazioni su eventi di live coding in locali.