1 - Bine ai venit, prietene :)

Bine ai venit. Sper ca esti la fel de nerabdator sa incepi sa creezi sunete interesante pe cat sunt eu sa iti arat cum. Va fi o experienta cu adevarat amuzanta, pe parcursul careia vei invata despre muzica, sinteza sunetelor, programare, compozitie, interpretare si multe altele.

Dar, stai, am fost cam nepoliticos! Sa ma prezint - sunt Sam Aaron - tipul care a creat Sonic Pi. Ma poti gasi la @samaaron pe Twitter si voi fi incantat sa te salut. S-ar putea sa te intereseze sa afli mai multe despre sesiunile mele de Pogramare live in care programez in Sonic Pi in direct in fata spectatorilor.

Daca ai idei sau sugestii pentru imbunatatirea Sonic Pi, te rog sa mi le transmiti - feedback-ul este foarte de folos. Nu se stie, poate ideea ta se va transforma intr-o functionalitate de scucces!

Tutorialul este impartit in sectiuni grupate pe categorii. Desi eu l-am scris ca sa permita ofere o trecere lina de la inceput la sfarsit, poti sa mergi direct la sectiunile care te intereseaza. Daca ti se pare ca ceva lipseste, anunta-ma si voi lua in considerare ideea ta pentru versiunile viitoare.

A urmari pe cineva in timp ce programeaza live este o buna metoda de a invata. Eu transmit live in mod regulat sesiunile mele la https://youtube.com/samaaron, deci te rog sa treci pe acolo, sa ne salutam si sa iti raspund la intrebari :)

Sa incepem…


1.1 - Programare live

Una din chestiile cele mai tari legate de Sonic Pi este ca iti permite sa scrii si sa modifici codul in direct pentru a crea muzica, la fel ca atunci cand canti in direct la chitara. Asta inseamna ca dupa ce exersezi putin, poti lua Sonic Pi pe scena si sa interpretezi cu el.

Elibereaza-ti mintea

Inainte de a trece la detaliile despre cum functioneaza Sonic Pi, as vrea sa experimentezi ce inseamna sa programezi live. Nu te speria daca nu intelegi prea multe din asta. Tine-te bine in scaun si bucura-te de muzica…

O bucla live

Sa incepem. Copiaza codul de mai jos intr-un buffer gol:

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

Acum, apasa butonul ‘Executa’ si vei auzi un ritm de toba bass. Daca la un moment dat vrei sa opresti sunetul, apasa pe butonul ‘Stop’. Dar deocamdata nu-l apasa… Mai bine urmeaza pasii astia:

Asigura-te ca sunetul de toba bass inca se aude Schimba valoarea ‘sleep’ din ‘0.5’ in ceva mai mare, cum ar fi ‘1’. Apasa din nou pe ‘Executa’ Observi ca viteza s-a schimbat. Tine minte momentul asta, e prima data cand ai programat live, dar probabil nu va fi ultima…

OK, a fost destul de simplu. Sa mai adaugam ceva. Deasupra liniei ‘sample :bd_haus’ adauga linia sample :ambi_choir, rate: 0.3. Codul ar trebui sa arate asa acum:

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

Acum poti sa te joci. Schimba valorile pentru ritm - ce se intampla cand folosesti valori mai mari sau mai mici, sau valori negative? Vezi ce se intampla cand schimbi ‘rate:’ pentru ‘:ambi_choir’ doar putin (sa zicem la 0.29). Ce se intampla daca alegi o valoare foarte mica pentru ‘sleep’? Vezi daca poti sa il faci sa se miste atat de repede incat calculatorul sa dea o eroare fiindca nu poate tine pasul (in cazul asta alege o valoare mai mare prentru ‘sleep si apasa din nou ‘Run’).

Incearca sa transformi in comentariu una dintre liniile ‘sample’ adaugand un ‘#’ la inceput:

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

Observi ca i-am spus calculatorului sa ignore acea linie, deci nu o vom auzi. Acesta se numeste comentariu. In Sonic Pi putem folosi comentariile pentru a adauga sau inlatura sunete.

La final, iti voi lasa ceva distractiv cu care sa te joci. Ia codul de mai jos si copiaza-l intr-un buffer gol. Deocamdata nu incerca sa intelegi prea mult, remarca doar ca sunt doua bucle - deci doua lucruri care se reiau in acelasi timp. Acum fa ceea ce faci cel mai bine - experimenteaza si joaca-te cu codul. Uite cateva sugestii:

Incearca sa schimbi valorile afisate cu albastru pentru ‘rate:’ si vezi cum se schimba sunetul. Incearca sa schimbi valorile pentru ‘sleep:’ (pauza) si vei observa cum cele doua bucle se reiau cu frecvente diferite. Incearca sa inlaturi semnul pentru comentariu (‘#’) de la linia sample si delecteaza-te cu sunetul de chitara redat de la coada la cap. Incearca sa schimbi oricare dintre valorile pentru ‘mix:’ afisate cu albastru cu numere intre ‘0’ (nu intra in mix) si ‘1’ (intra complet in mix).

Tine minte sa apesi ‘Executa” si vei auzi schimbarea data viitoare cand se reia bucla. Daca ramai blocat, nu te panica - apasa ‘Opreste’, sterge codul din buffer, adu o noua copie si esti gata sa improvizezi din nou. Facand greseli vei invata cel mai rapid…

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

Continua sa te joci si sa experimentezi pana cand vei deveni curios cum merge de fapt chestia asta si te vei intreba ce altceva mai poti face cu ea. Acum esti pregatit sa citesti restul tutorialului.

Deci, ce mai astepti?


1.2 - Interfata Sonic Pi

Sonic Pi are o interfata foarte simpla pentru a programa muzica. Hai sa o descoperim.

Interfata Sonic Pi

A - Control Redare B - Control Editor C - Informatii si Ajutor D - Editor Cod E - Panou Optiuni F - Vizualizare Jurnal G - Sistem Ajutor H - Vizualizare Osciloscop I - Cue Viewer

A. Control Redare

Butoanele roz sunt pentru pornirea/oprirea sunetelor. Butonul ‘Executa’ este pentru pornirea codului din editor, ‘Opreste’ pentru oprire, ‘Salveaza’ pentru salvarea intr-un fisier extern si ‘Inregistreaza’ pentru a crea un fisier WAV pornind de la sunetele care sunt redate.

B. Control Editor

These orange buttons allow you to manipulate the code editor. The Size + and Size - buttons allow you to make the text bigger and smaller.

C. Informatii si Ajutor

Butoanele albastre iti dau acces la informatii, ajutor si optiuni. Butonul Info deschide fereastra de informatii despre Sonic Pi - echipa de baza, istoric, colaboratori si comunitate. Butonul Help comuta afisarea sistemului de ajutor (G), iar butonul Optiuni comuta afisarea unei ferestre in care poti modifica anumiti parametri de sistem.

D. Editor de Cod

Aceasta este zona in care vei scrie cod si vei compune/reda muzica. Este un editor de text simplu in care poti scrie cod, poti sa il stergi, sa copiezi/lipesti bucati din el, etc. Este un fel de versiune limitata de Word sau Google Docs. Editorul afiseaza automat anumite cuvinte cu culori, in functie de sensul lor in cadrul codului. Poate parea ciudat la inceput, dar in curand vei vedea ca e foarte util. De exemplu, vei recunoaste un numar dupa faptul ca este albastru.

E. Panou de Optiuni

Sonic Pi permite schimbarea anumitor parametri la care se poate ajunge apasand butonul optiuni in zona Informatii si Ajutor. Acesta va comuta afisarea Panoului Optiuni care contine un numar de parametri ce pot fi schimbati. Exemple de astfel de parametri sunt: forteaza modul mono, inversare canale stereo, comutare nivel de detaliu jurnal. Exista si un potentiometru de volum si selectie de iesire audio pentru Raspberry Pi.

F. Afisare Jurnal

Cand rulezi codul din buffer, in zona de afisare a jurnalului se afiseaza informatii despre ce face programul la un moment dat. Implicit, vei vedea un mesaj pentru fiecare sunet pe care il creezi, cu momentul exact in care a fost activat. Acest lucru este foarte util cand vrei sa iti depanezi codul sau sa intelegi ce face codul tau.

G. Sistem Ajutor

In sfarsit, una dintre cele mai importante parti ale interfetei Sonic Pi este reprezentata de sistemul de ajutor care apare in partea de jos a ferestrei. Aceasta poate fi afisata/ascunsa apasand pe butonul albastru Ajutor. Sistemul de ajutor contine informatii utile despre toate elementele Sonic Pi, inclusiv acest tutorial, o lista a sintetizatoarelor disponibile, sample-uri, exemple, efecte (FX) si o lista a tuturor functiilor pe care Sonic Pi le ofera pentru programarea muzicii.

H. Osciloscop

Osciloscopul ofera o reprezentare grafica a sunetelor pe care le auzi. Poti sa observi cum unda fierastrau chiar arata ca niste dinti de fierastrau si cum banalul bip este o unda sinusoidala. Poti observa de asemenea diferenta intre sunetele slabe si cele puternice urmarind dimensiunea liniilor. Exista 3 osciloscoape cu care te poti juca - cel implicit combina canalele stanga si dreapta, cel stereo afiseaza separat fiecare canal, iar al treilea prezinta relatia de faza intre cele doua canale folosind Curbele lui Lissajous (https://en.wikipedia.org/wiki/Lissajous_curve) si permite crearea de imagini interesante folosind sunetul.

I. Cue Viewer

All internal and external events (called cues in Sonic Pi) are automatically logged in the Cue Viewer. For example, if you have a MIDI controller connected and press one of its buttons, you’ll see a new cue event in the Cue Viewer telling you the name of the controller and which button you pressed. Once you’ve mastered the basics of making and producing sounds, you’ll start to want to cue sounds or whole sections of sounds based on events such as these. A cue event is just an indication that something happened. For example, every time a live loop spins round, it sends a cue event out which is logged in the Cue Viewer. Also, external events such as MIDI messages from connected MIDI equipment and OSC messages from other programs or computers are also displayed in the Cue Viewer. It is also possible to directly generate cue events using the cue function. Anything that appears in the Cue Viewer can be used to trigger something happening. This is covered in more detail in Sections 10 to 12 of this tutorial.


1.3 - Invatarea prin joaca

Sonic Pi incurajeaza invatarea programarii si muzicii prin joaca si incercari. Cel mai important este sa te distrezi, iar fara sa iti dai seama vei invata sa programezi, sa compui si sa interpretezi.

Nu exista greseli

Daca tot suntem la subiectul acesta, da-mi voie sa-ti spun un lucru pe care l-am descoperit de-a lungul anilor in care am programat muzica live - nu exista greseli, doar oportunitati. Acest lucru il aud adesea in legatura cu jazzul, dar se aplica la fel de bine si la programarea live. Indiferent de nivelul de experienta - de la incepator la Algoraver avansat, vei executa cod care va avea un rezultat complet neasteptat. S-ar putea sa fie incredibil de reusit - caz in care trebuie sa il pastrezi. Totusi, s-ar putea si sa sune foarte strident si nelalocul lui. Nu conteaza ca se intampla - conteaza ce faci mai departe cu el. Ia sunetul, modifica-l si transforma-l in ceva minunat. Multimea va innebuni.

Incepe simplu

Cand inveti este tentant sa faci lucruri incredibile acum. Totusi, stapaneste-ti imboldul si considera asta ca un tel pe care sa il atingi mai tarziu. Acum, gandeste-te la cel mai simplu lucru pe care l-ai putea crea, care ar putea fi amuzant dar te-ar aduce cu un pas mai aproape de tinta pe care ti-ai propus-o. Cand te-ai decis asupra acestui pas simplu, incearca si construieste-l, joaca-te cu el si vezi ce idei iti mai inspira. Nu va dura mult si vei fi ocupat sa te distrezi si sa progresezi cu adevarat.

Ai grija sa impartasesti creatia ta cu altii!


2 - Sintetizatoare

OK, destul cu introducerea - sa trecem la sunete.

In aceasta sectiune vom discuta bazele lucrului cu sintetizatoare. De multe ori se foloseste varianta synth, forma prescurtata a cuvantului din engleza (synthesiser), care este un nume mai dichisit pentru ceva care creeaza sunete. De obicei, sintetizatoarele sunt complicat de folosit - mai ales cele analogice cu multe cabluri si module. Totusi, Sonic Pi iti ofera accesul la aceste instrumente puternice intr-o maniera usor de abordat.

Nu te lasa pacalit de simplitatea aparenta a interfetei Sonic Pi. Poti patrunde foarte adanc in manipularea foarte sofisticata sunetelor daca asta iti doresti. Tine-te bine…


2.1 - Primele tale beep-uri

Priveste codul de mai jos:

play 70

De aici incepe totul. Da-i drumul, copiaza acest cod si lipeste-l in fereastra din partea de sus a aplicatiei (spatiul mare alb de sub butonul Executa). Acum, apasa Executa…

Beep!

Intens. Apasa din nou. Si din nou. Si din nou…

Uau, nebunie! Sunt sigur ca ai putea face asta toata ziua. Dar stai, inainte sa te pierzi intr-un sir infinit de beep-uri, incearca sa schimbi numarul:

play 75

Auzi diferenta? Incearca un numar mai mic:

play 60

So, lower numbers make lower pitched beeps and higher numbers make higher pitched beeps. Just like on a piano, the keys at the lower part of the piano (the left hand side) play lower notes and the keys on the higher part of the piano (the right hand side) play higher notes.

play 60

Nu te speria daca treburile astea nu-ti spun nimic - nici mie nu-mi spuneau cand am inceput. Tot ce conteaza acum este ca stii ca “numerele mai mici produc note mai joase* si numerele mai mari produc note mai inalte.

Acorduri

Sa canti o nota este destul de distractiv, dar sa canti mai multe in acelasi timp este si mai bine. Incearca:

play 72
play 75
play 79

Super! Deci, cand scrii mai multe instructiuni ‘play’, toate sunt executate in acelasi timp. Incearca si tu - ce numere suna mai bine impreuna? Care suna groaznic? Experimenteaza, exploreaza si descopera singur.

Melodie

Deci, redarea notelor si a acordurilor este distracitva - dar care e treaba cu melodiile? Ce-ar fi daca ai vrea sa canti notele una dupa alta si nu in acelasi timp? Ei bine, este usor, trebuie doar sa faci o pauza intre note, folosind instructiunea ‘sleep’ (somn):

play 72
sleep 1
play 75
sleep 1
play 79

Ce dragut, un mic arpegiu. Ce inseamna ‘1’ in instructiunea ‘sleep 1’? Ei bine, inseamna durata pauzei. De fapt, inseamna o pauza cu durata de o masura, dar pentru moment putem sa ne gandim la ea ca la o pauza de 1 secunda. Deci, ce facem daca vrem sa facem arpegiul putin mai rapid? Trebuie sa folosim valori mai mici pentru pauze. Ce-ar fi sa incercam cu o jumatate, adica ‘0.5’:

play 72
sleep 0.5
play 75
sleep 0.5
play 79

Observi ca acum canta mai rapid. Acum, incearca singur, schimba valorile pentru pauze si pentru note.

Un lucru pe care ar trebui sa-l incerci este sa redai note intermediare cum ar fi ‘play 52.3’ sau ‘play 52.63’. Nu esti absolut deloc obligat sa folosesti notele standard. Distreaza-te putin schimband valorile.

Numele notelor traditionale

Cei care deja stiu notatia muzicala (nu te ingrijora daca tu nu o stii - nu ai nevoie de ea ca sa te distrezi) pot incerca sa scrie o melodie folosind numele notelor, cum ar fi C (Do) sau F# (Fa#) in locul numerelor. Sonic Pi are grija de tine in acesta caz. Poti incerca asta:

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

Nu uita sa pui doua puncte ‘:’ in fata numelui notei astfel incat sa apara afisat cu roz. De asemenea, poti specifica octava dorita, adaugand un numar dupa numele notei:

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

Daca vrei sa faci marchezi un diez (sharp in engleza), adauga un ‘s’ dupa numele notei: play :Fs3. Pentru bemol (flat in engleza), adauga un ‘b’: play :Eb3.

Acum dezlantuie-te si distreaza-te cu propriile tale melodii.


2.2 - Optiuni sintetizatoare: Amp (amplitudine) si Pan (pozitionare)

Pe langa faptul ca permite alegerea notelor sau sample-urilor pe care le va reda, Sonic Pi ofera o gama larga de optiuni pentru modificarea sunetelor. Vom acoperi mare parte dintre acestea in tutorial si exista o documentatie bogata pentru fiecare dintre ele in sistemul de help (ajutor). Deocmandata, vom face cunostinta cu doua dintre cele mai utile: amplitudinea (amp) si pozitionarea (pan). Pentru inceput, sa privim putin ce inseamna de fapt optiunile.

Optiuni

Sonic Pi ofera suport pentru optiuni (sau opts - prescurtarea din engleza) pentru sintetizatoare. Optiunile sunt parametri pe care ii trasnmiti comenzii ‘play’ pentru a modifica si controla diferite caracteristici ale sunetului pe care il vei auzi. Fiecare sintetizator are setul sau de optiuni pentru a regla fin sunetul. Totusi, exista si seturi de optiuni comune care se aplica multor sunete, cum ar fi ‘amp:’ si optiunile legate de anvelopa sunetului (prezentate in alta sectiune).

Optiunile au doua componente majore, numele parametrului si valoarea acestuia. De exemplu, ai putea avea o optiune numita ‘cheese:’ si ai dori sa ii atribui valoarea ‘1’.

Optiunile sunt transmise catre comanda ‘play’ folosind virgula ‘,’ si apoi numele optiunii, cum ar fi ‘amp:’ (nu uita ‘:’), apoi un spatiu si valoarea pentru optiune. De exemplu:

play 50, cheese: 1

(‘cheese:’ nu reprezinta o optiune reala, o folosim doar ca exemplu).

Poti transmite mai multe optiuni, separandu-le prin virgula:

play 50, cheese: 1, beans: 0.5

Ordinea optiunilor nu conteaza, deci urmatoarea linie are acelasi efect:

play 50, beans: 0.5, cheese: 1

Optiunile care nu sunt recunoscute de sintetizator sunt ignorate (cum este cazul cu ‘cheese’ si ‘beans’ care sunt evident niste nume inventate!)

Daca din greseala folosesti aceeasi optiune de doua ori, cu valori diferite, ultima castiga. De exemplu, pentru ‘beans:’ valoarea luata in calcul va fi 2, nu 0.5:

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

Mai multe elemente din Sonic Pi accepta optiuni, deci acorda-le putina atentie si invata cum sa le folosesti, pentru ca iti va fi de folos! Sa ne jucam putin cu prima optiune: ‘amp:’.

Amplitudinea

Amplitudinea spune computerului care este taria sunetului pe care o doresti. O amplitudine mare produce un sunet puternic, iar o amplitudine mica produce un sunet slab. Asa cum Sonic Pi foloseste numere pentru a reprezenta durate si note, tot la fel foloseste numere pentru a reprezenta amplitudinea. Amplitudinea 0 inseamna liniste (nu vei auzi nimic), in timp ce amplitudineea 1 inseamna volum normal. Poti creste amplitudinea mai mult, la 2, 10, 100. Totusi, vei observa ca atunci cand amplitudinea globala a sunetelor devine prea mare, Sonic Pi foloseste un asa numit compresor pentru a le reduce si a se asigura ca nu devin prea puternice pentru urechile tale. De obicei aceasta face ca sunetele sa fie neclare si ciudate. Incearca deci sa folosesti amplitudini joase, adica in intervalul 0 - 0.5, pentru a evita compresia.

Sa crestem amplitudinea

Pentru a schimba amplitudinea unui sunet, poti folosi optiunea ‘amp:’. De exemplu, pentru a reda sunetul cu amplitudinea la jumatate, da-i valoarea 0.5:

play 60, amp: 0.5

Pentru a-l reda la amplitudine dubla, da-i valoarea 2:

play 60, amp: 2

Optiunea ‘amp:’ are efect doar in cadrul instructiunii ‘play’ din care face parte. Deci, in acest exemplu, primul play va fi cu volumul la jumatate, iar al doilea va reveni la valoarea implicita (1):

play 60, amp: 0.5
sleep 0.5
play 65

Desigur, se pot folosi valori diferite pentru ‘amp:’ pentru fiecare instructiune 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

Pozitionare (panning)

Alta optiune interesanta este ‘pan:’ care controleaza pozitionarea sunetului in stereo. Pozitionarea unui catre stanga va face sa il auzi mai puternic in difuzorul din stanga, iar pozitionarea la dreapta inseamna ca il vei auzi mai puternic in difuzorul din dreapta. In Sonic Pi vom folosi -1 pentru a reprezenta un sunet care se aude doar in stanga, 0 pentru un sunet pozitionat central si 1 pentru un sunet care se aude doar in dreapta. Desigur, poti utiliza orice valoare intre -1 si 1 ca sa controlezi exact pozitia sunetului.

Sa redam un beep in difuzorul din stanga:

play 60, pan: -1

Acum, sa-l redam in difuzorul din dreapta:

play 60, pan: 1

La final sa-l redam inapoi in centru (in pozitia implicita):

play 60, pan: 0

Acum, distreaza-te schimband amplitudinea si pozitionarea sunetelor!


2.3 - Alegerea sintetizatorului

Pana acum ne-am distrat folosind beep-uri. Totusi, probabil ca te-ai plictisit de ele. Doar atat poate Sonic Pi? Sigur programarea live trebuie sa insemne si altceva decat redarea de beep-uri… Da, mai inseamna si altceva si in aceasta sectiune vom explora gama larga de sunete pe care le ofera Sonic Pi.

Sintetizatoare

Sonic Pi are mai multe instrumente pe care le numeste synths - prescurtarea de la synthesisers (sintetizatoare). Daca sample-urile reprezinta sunete pre-inregistrate, sintetizatoarele sunt capabile sa genereze sunete noi pe care le poti controla (si pe care le vom explora mai tarziu in acest tutorial). Sintetizatoarele din Sonic Pi sunt instrumente foarte puternice si expresive si iti va placea sa le explorezi si sa te joci cu ele. Mai intai, sa invatam cum alegem sintetizatorul pe care vrem sa-l folosim.

Zumzet de fierastraie si profeti

Un sunet interesant este sunetul fierastrau - sa il incercam:

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

Sa incercam alt sunet - profetul:

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

Ce-ar fi sa le combinam? Mai intai unul dupa altul:

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

Now multiple sounds at the same time (by not sleeping between successive calls to play):

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

Observi ca instructiunea ‘use_synth’ afecteaza doar urmatoarele comenzi ‘play’. Poti sa o vezi ca pe un comutator global - urmatoarele comenzi ‘play’ vor rula oricare ar fi sintetizatorul selectat. Pentru a-l trece la o noua pozitie folosesti ‘use_synth’.

Descopera sintetizatoarele

Pentru a vedea ce sintetizatoare iti ofera Sonic Pi, sa aruncam o privire la optiunea Sintetizatoare din meniul vertical din stanga (deasupra FX). Sunt peste 20 din care poti sa alegi. Iata cateva dintre favoritele mele:

:prophet :dsaw :fm :tb303 :pulse

Acum joaca-te cu schimbarea sintetizatorului in timpul muzicii. Distreaza-te putin combinand sintetizatoarele pentru a crea noi sunete sau folosind diferite sintetizatoare pentru sectiuni diferite din melodie.


2.4 - Durata folosind anvelope

Intr-o sectiune anterioara am vazut cum putem folosi comanda ‘sleep’ pentru a controla cand incep sunetele. Dar nu am reusit inca sa controlam durata sunetelor.

Pentru a ne oferi un mod simplu dar puternic pentru controlul duratei sunetelor, Sonic Pi foloseste notiunea de anvelopa de amplitudine ADSR (vom vorbi mai tarziu in aceasta sesiune despre ce inseamna ADSR). O anvelopa de amplitudine ofera doua posibilitati de control foarte utile:

controlul asupra duratei unui sunet controlul asupra amplitudinii unui sunet

Durata

Durata reprezinta lungimea perioadei in care se aude sunetul. O durata mai mare inseamna ca vei auzi sunetul pentru mai mult timp. Toate sunetele din Sonic Pi au o anvelopa de amplitudine controlabila, iar durata totala a anvelopei reprezinta durata sunetului. Ca urmare, controland anvelopa, controlezi durata.

Amplitudinea

Anvelopa ADSR nu controleaza doar durata, iti ofera si un control fin asupra amplitudinii sunetului. Toate sunetele audibile incep si se termina silentios si contin perioade audibile intre aceste limite. Anvelopele iti permit sa determini cum evolueaza amplitudinea partilor nesilentioase. Este ca si cum ai da cuiva instructiuni cum sa regleze in sus si in jos volumul amplificatorului de chitara. De exemplu, ai putea cere cuiva “sa inceapa in liniste, sa dea usor volumul mai tare, sa il mentina un timp, apoi sa-l coboare rapid”. Sonic Pi iti permite sa programezi precis acest comportament folosind anvelopele.

Ca o scurta recapitulare: asa cum am vazut mai devreme, amplitudinea 0 reprezinta lipsa sunetului, iar 1 este volumul normal.

Acum, sa luam pe rand fiecare parte a anvelopei.

Faza Release

Singura parte a anvelopei care este folosita implicit este cea de release. Aceasta reprezinta timpul necesar sunetului sintetizatorului sa se stinga. Toate sintetizatoarele au un timp de release 1 care inseamna ca implicit durata este de 1 bataie (la ritmul de 60 BPM - batai pe minut - asta inseamna o secunda):

play 70

Nota se va auzi timp de 1 secunda. Incearca sa cronometrezi :) Aceasta reprezinta o prescurtare a versiunii mai lungi si mai explicite:

play 70, release: 1

Observi ca suna exact la fel (sunetul dureaza o secunda). Totusi, acum este foarte usor sa schimbi durata modificand valoarea pentru parametrul ‘release:’:

play 60, release: 2

Putem face sintetizatorul sa scoata un sunet foarte scurt folosind o valoare foarte mica pentru timpul de release:

play 60, release: 0.2

Durata stingerii sunetului se numeste faza de release si implicit presupune o tranzitie liniara (adica in linie dreapta). Diagrama urmatoare ilustreaza aceasta tranzitie:

release envelope

Linia verticala din extremitatea stanga a diagramei arata ca sunetul incepe la amplitudine 0, dar urca la amplitudinea maxima imediat (acesta este faza de atac, pe care o vom prezenta in continuare). Odata ajuns la amplitudine maxima, va cobori in linie dreapta pana la zero, intr-un interval de timp dat de ‘release:’. Timpi de release mai lungi produc o stingere mai lenta a sunetului.

Vei putea deci schimba durata sunetului schimband timpul de release. Joaca-te adaugand valori pentru timpul de release la melodia ta.

Faza de atac

Implicit, faza de atac este 0 pentru toate sintetizatoarele, ceea ce inseamna ca ele trec de la amplitudine 0 la 1 instantaneu, ceea ce da sintetizatorului un sunet intial percutant. Totusi, ai putea sa-ti doresti ca sunetul sa intre progresiv (fade in). Acest lucru se poate obtine folosind optiunea ‘attack:’. Incearca sa introduci progresiv niste sunete:

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

Poti folosi mai multe optiuni in acelasi timp. De exemplu, pentru un atac scurt si un release lung, incearca:

play 60, attack: 0.7, release: 4

Acest atac scurt urmat de release lung este ilustrat in diagrama urmatoare:

anvelopa atac release

Desigur, poti incerca si invers - un atac lung si un release scurt:

play 60, attack: 4, release: 0.7

anvelopa atac lung release scurt

In fine, poti avea atat atac scurt, cat si release scurt, pentru sunete de scurta durata.

play 60, attack: 0.5, release: 0.5

anvelopa atac scurt release scurt

Faza Sustain (mentinere)

Pe langa specificarea timpilor de atac si release, poti specifica si timpul cat sunetul este sustinut, pentru a controla faza sustain. Aceasta reprezinta perioada de timp in care sunetul este mentinut la amplitudine maxima intre fazele de atac si release.

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

![anvelopa ASR]images/tutorial/env-attack-sustain-release.png)

Timpul de mentinere este util pentru sunetele importante a caror prezenta in mix vreti sa fie remarcata inainte de a intra in faza optionala de release. Desigur, este corect si sa specificati atat pentru ‘attack:’ cat si pentru ‘release:’ valoarea 0 si sa folositi doar faza de sustain fara a avea intrarea si iesirea progresiva a sunetului. Totusi, trebuie sa stiti ca folosind valoarea 0 pentru release puteti avea pacanituri in sunet si este mai bine in general sa folositi o valoare foarte mica, cum ar fi 0.2.

Faza Decay (declin)

Pentru si mai mult control puteti specifica si un timp de declin (Decay). Aceasta este o faza a anvelopei care este incadrata de fazele de atac si mentinere si specifica timpul in care amplitudinea coboara de la nivelul de atac - ‘attack level:’ la nivelul de declin - ‘decay_level:’ (care va fi setat automat la nivelul de mentinere - ‘sustain_level:’ daca nu ii dati o valoare explicita). Implicit, valoarea pentru ‘decay:’ este 0 si atat nivelul de atac cat si cel de mentinere au valoarea 1, deci va trebui sa le dati valori explicite pentru ca timpul de declin sa aiba efect:

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

anvelopa ADSR

Nivelul de declin

Inca un truc: desi ‘decay_level:’ are implicit aceeasi valoare cu ‘sustain_level:’, poti sa le atribui valori diferite pentru a avea un control mai bun asupra anvelopei. Acest lucru iti permite sa creezi anvelope precum cea care urmeaza:

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

anvelopa ASR

Poti de asemenea sa alegi pentru ‘decay_level:’ o valoare mai mare decat cea pentru ‘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

anvelopa ASR

Anvelope ADSR

In concluzie, in Sonic Pi anvelopele ADSR au urmatoarele faze:

attack (atac) - timpul de la amplitudine 0 la ‘attack_level’ (nivelul de atac), decay (declin) - timpul de trecere de la amplitudinea nivelului de atac la cea a nivelului de declin - ‘decay_level’, sustain (sustinut) - timpul de trecere de la amplitudinea nivelului de declin la cea a nivelului sustinut - ‘sustain_level’, release (eliberare) - timpul de trecere de la amplitudinea nivelului sustinut la 0

Este important de retinut ca durata sunetului este suma timpilor pentru toate aceste faze. Ca urmare, urmatorul sunet va avea o durata de 0.5 + 1 + 2 + 0.5 = 4 batai:

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

Acum joaca-te adaugand anvelope sunetelor tale…


3 - Esantioane

O alta cale de a-ti imbogati muzica este sa folosesti sunete pre-inregistrate. In buna traditie hip-hop, aceste sunete se numesc esantioane (samples). Deci, daca iesi cu microfonul afara si inregistrezi sunetul discret al ploii lovind o copertina, tocmai ai creat un esantion.

Sonic Pi iti permite sa faci o gramada de chestii interesante cu esantioanele. Nu doar ca vine cu peste 90 de esantioane din domeniul public (cu utilizare gratuita), dar iti permite si sa creezi si sa modifici propriile esantioane. Sa trecem la treaba…


3.1 - Activarea esantioanelor

Redarea de beep-uri este doar inceputul. Un lucru mult mai interesant este sa redai esantioane deja inregistrate. Incearca asta:

sample :ambi_lunar_land

Sonic Pi contine multe esantioane cu care te poti juca. Poti sa le folosesti la fel cum folosesti comanda ‘play’. Pentru a reda mai multe esantioane si note, scrie-le unele dupa altele:

play 36
play 48
sample :ambi_lunar_land
sample :ambi_drone

Daca vrei sa lasi pauze intre ele, foloseste comanda ‘sleep’:

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

Observi ca Sonic Pi nu asteapta ca un sunet sa se termine inainte de a-l porni pe urmatorul. Comanda ‘sleep’ separa doar activarea (triggering) sunetelor. Aceasta permite combinarea sunetelor creand efecte de suprapunere interesante. Pe parcursul acestui tutorial vom arunca o privire asupra controlului duratei sunetelor folosind anvelopele.

Explorarea esantioanelor

Exista doua moduri de a explora esantioanele oferite de Sonic Pi. Primul presupune folosirea acestui sistem de ajutor. Fa click pe Esantioane in meniul vertical din marginea stanga, alege categoria dorita si vei vedea o lista cu sunetele disponibile.

O metoda alternativa este sa folosesti sistemul de completare automata. Scrie inceputul unui grup de esantioane, cum ar fi: ‘sample :ambi_’ si vei vedea o lista derulanta cu numele esantioanelor, din care poti alege ce doresti. Incearca aceste categorii de prefixe:

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

Acum poti incepe sa combini esantioanele pentru a crea compozitii!


3.2 - Parametri Esantioane: Amplitudine (Amp) si Pozitionare (Pan)

Asa cum am vazut la sintetizatoare, putem controla cu usurinta sunetele folosind diferiti parametri. Esantioanele suporta exact acelasi model de parametri. Sa-i revedem pe vechii prieteni - ‘amp:’ si ‘pan:’.

Amplificarea esantioanelor

Poti schimba amplitudinea esantioanelor folosind aceeasi metoda ca in cazul sintetizatoarelor:

sample :ambi_lunar_land, amp: 0.5

Pozitionarea esantioanelor

Putem folosi parametrul ‘pan:’ pentru esantioane. De exemplu, iata cum am putea reda esantionul amen in stanga, iar la jumatatea duratei sa il redam si in dreapta:

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

0.877 reprezinta jumatate din durata esantionului :loop_amen in secunde.

De retinut ca daca ai setat niste valori implicite pentru sintetizatoare folosind ‘use_synth_defaults’ (despre care vom discuta mai tarziu), acestea vor fi ignorate de ‘sample’.


3.3 - Comprimarea/Intinderea esantioanelor

Acum, ca putem folosi o multime de sintetizatoare si esantioane pentru a crea muzica, este timpul sa invatam cum putem sa le modificam si pe unele si pe celelalte pentru a individualiza muzica si a o face mai interesanta. Mai intai, sa exploram posibilitatea de a intinde si a comprima esantioanele.

Reprezentarea esantioanelor

Esantioanele sunt sunete deja inregistrate memorate sub forma de numere care reprezinta miscarea pe care conul difuzorului o face pentru a reproduce sunetele. Conul difuzorului se poate misca inainte si inapoi, deci aceste numere trebuie sa reprezinte cat de mult trebuie sa fie deplasat conul la fiecare moment. Pentru a putea reproduce cu fidelitate un sunet inregistrat esantionul trebuie sa contina in general mii de numere pentru fiecare secunda! Sonic Pi ia aceasta lista de numere si o trimite cu viteza potrivita pentru a misca difuzorul computerului inainte si inapoi exact in modul necesar pentru a reproduce sunetul. Totusi, poate fi distractiv sa schimbi viteza cu care aceste numere sunt trimise catre difuzor pentru a schimba sunetul.

Schimbarea vitezei de redare

Sa ne jucam cu unul dintre sunetele ambientale: ‘:ambi_choir’. Pentru a-l reda la viteza normala, puteti sa transmiteti parametrul ‘rate’ pentru ‘sample’:

sample :ambi_choir, rate: 1

Aceasta linie reda esantionul cu viteza normala (1), deci nu este nimic special deocamdata. Totusi, putem schimba acest numar cu un altul. Sa zicem ‘0.5’:

sample :ambi_choir, rate: 0.5

Oho! Ce se intampla aici? Ei bine, doua lucruri. In primul rand, esantionul va dura de doua ori mai mult, iar in al doilea rand, sunetul este cu o octava mai jos. Sa examinam aceste lucruri mai in detaliu.

Intinderea

Un esantion cu care ne putem distra lungindu-l sau comprimandu-l este Amen. La viteza normala, am putea sa-l adaugam la o pista toba & bass:

sample :loop_amen

Schimbandu-i viteza insa, putem sa schimbam stilul. Incearca viteza redusa la jumatate pentru un hip-hop de moda veche:

sample :loop_amen, rate: 0.5

Daca il facem mai rapid, intram in zona jungle:

sample :loop_amen, rate: 1.5

Iar acum ultimul truc - sa vedem ce se intampla daca folosim o viteza negativa:

sample :loop_amen, rate: -1

Hei, sunetul este redat de la coada la cap! Acum incearca sa te joci cu diferite esantioane la viteze diferite. Incearca viteze foarte mari. Incearca viteze enervant de mici. Vezi ce sunete interesante poti obtine.

O explicatie simpla a vitezei de redare a esantioanelor

Un mod de a vedea lucrurile este sa te gandesti la esantioane ca la niste arcuri. Modificarea vitezei de redare este asemanatoare cu alungirea sau comprimarea arcului. Daca redai esantionul cu o viteza dubla, comprimi arcul la jumatate din lungimea sa normala. Ca urmare, esantionul va dura jumatate din durata normala, fiind mai scurt. Daca redai esantionul la jumatate din viteza normala, intinzi arcul la o lungime dubla. Esantionul va dura de doua ori mai mult, fiind mai lung. Cu cat il comprimi mai tare (viteza mai mare), cu atat devine mai scurt. Cu cat il intinzi mai mult (viteza mai mica), cu atat devine mai lung.

Comprimarea unui arc il face mai dens (creste numarul de spire pe cm) - acest lucru este similar cu un esantion care va contine sunete care variaza mai des. Intinderea arcului scade densitatea de spire si este similara cu un sunet care variaza mai lent.

Matematica din spatele vitezei de redare a esantioanelor

(Aceasta sectiune se adreseaza celor care sunt interesati de detalii. Poti sari peste ea daca doresti…)

Dupa cum am vazut mai sus, un esantion este reprezentat de o lista lunga de numere care specifica unde trebuie sa se afle speakerul la fiecare moment de timp. Putem lua aceasta lista de numere si sa trasam un grafic care ar arata similar cu acesta:

grafic esantion

Probabil ai mai vazut imagini ca aceasta inainte. Se numeste forma de unda a unui esantion. Este doar un grafic pe baza unor numere.Uzual, o astfel de forma de unda va avea 44100 puncte de date pentru fiecare secunda (acest lucru este impus de Teorema eșantionării Nyquist–Shannon). Deci, daca un esantion dureaza 2 secunde, forma de unda va fi reprezentata de 88200 de numere care vor fi trimise difuzorului cu o viteza de 44100 de puncte pe secunda. Desigur, am putea sa trimitem datele cu o viteza dubla, de 88200 de puncte pe secunda. Aceasta ar face ca redarea sa dureze 1 secunda. Am putea de asemenea sa redam 22050 puncte pe secunda, durata fiind in acest caz de 4 secunde.

Durata unui esantion este influentata de viteza de redare:

Dublarea vitezei de redare injumatateste durata, Injumatatirea vitezei de redare dubleaza durata, Reducand viteza la un sfert durata creste de patru ori, Reducand viteza de 10 ori, durata va fi de 10 ori mai mare.

Putem reprezenta aceasta regula prin formula:

durata_esantion_noua = ( 1 / viteza) * durata_esantion 

Schimbarea vitezei de redare influenteaza si tonalitatea esantionului. Frecventa formei de unda este determinata de cat de repede se misca in sus si in jos. Creierul nostru transforma cumva miscarea rapida a difuzorului in sunete in alte si miscarea lenta in sunete joase. De aceea uneori poti vedea cum un difuzor mare de bas se misca atunci cand reda un sunet cu frecvente foarte joase - se misca mult mai lent inainte si inapoi decat un difuzor care produce sunete inalte.

Daca iei o forma de unda si o comprimi, vor exista mai multe miscari in sus si in jos intr-o secunda. Aceasta va face sunetul sa aiba o tonalitate mai inalta. Dublarea miscarilor in sus si in jos (oscilatii) dubleaza frecventa. Deci, redarea unui esantion cu viteza dubla va dubla frecventa pe care o auzi. De asemenea, injumatatirea vitezei va injumatati frecventa. Alte viteze de redare vor modifica frecventa corespunzator.


3.4 - Anvelope pentru esantioane

Este posibil sa modificam durata si amplitudinea unui esantion folosind o anvelopa ADSR. Totusi, functionarea va fi putin diferita fata de anvelopa ADSR folosita pentru sintetizatoare. Anvelopele pentru esantioane permit doar reducerea amplitudinii si duratei unui esantion - nu si marirea acestora. Esantionul se va opri fie cand s-a epuizat continutul sau fie cand s-a terminat anvelopa - in functie de care eveniment se produce primul. Deci, daca folosesti un ‘release:’ foarte lung, nu vei putea mari durata esantionului.

Anvelopa Amen

Sa ne intoarcem la esantionul cunoscut - Amen Break:

sample :loop_amen

Fara parametri, auzim esantionul intreg, la amplitudine intreaga. Daca vrem sa-l pornim treptat pe durata de 1 secunda, putem folosi parametrul ‘attack:’:

sample :loop_amen, attack: 1

Pentru o intrare mai rapida, alege un timp de atac mai mic:

sample :loop_amen, attack: 0.3

Auto mentinere

Anvelopa ADSR se comporta diferit data de cea pentru sintetizatoare in ceea ce priveste valoarea sustain (de mentinere). In cazul anvelopei standard pentru sintetizatoare, ‘sustain:’ avea implicit valoarea 0 daca nu il modificai manual. In cazul esantioanelor, ‘sustain:’ este calculat automagic ca timpul ramas de redat din sample. De aceea vom auzi intregul esantion daca nu transmitem valori. Daca valorile pentru attack, decay, sustain si release ar fi toate 0 nu am auzi nimic. Sonic Pi calculeaza cat de lung este esantionul, scade valorile pentru attack, decay si release si foloseste rezultatul ca valoare pentru sustain. Daca valorile pentru attack, decay si release depasesc durata esantionului, valoarea pentru sustain va fi 0.

Stingerea sunetului (fade out)

Pentru a examina acest comportament, sa privim mai cu atentie esantionul Amen break. Daca cerem Sonic Pi sa ne spuna cat este de lung:

print sample_duration :loop_amen

Va afisa 1.753310657596372 care reprezinta lungimea esantionului in secunde. Sa rotunjim valoarea la ‘1.75’ pentru comoditate. Acum, daca setam valoarea pentru release la ‘0.75’, se va intampla un lucru surprinzator:

sample :loop_amen, release: 0.75

Va fi redata prima secunda a esantionului la amplitudine intreaga, apoi acesta se va stinge pe o durata de 0.75 secunde. Acest lucru arata cum functioneaza auto mentinerea. Implicit, valoarea pentru release se scade de la sfarsitul esantionului. Daca lungimea acestuia ar fi fost 10.75 secunde, ar fi fost redate primele 10 secunde la amplitudine intreaga apoi ar fi urmat stingerea pe o durata de 0.75s.

Tine minte: implicit, ‘release:’ actioneaza la sfarsitul esantionului.

Intrarea progresiva (fade in) si stingerea treptata (fade out)

Putem folosi ‘attack:’ si ‘release:’ impreuna cu auto mentinerea pentru a avea atat o intrare progresiva cat si o stingere treptata pentru esantion:

sample :loop_amen, attack: 0.75, release: 0.75

Cum durata completa a esantionului este de 1.75s si fazele de atac si eliberare impreuna au 1.5s, durata de mentinere este stabilita automat la 0.25s. Acest lucru ne ajuta sa realizam usor intrarea progresiva si stingerea treptata a esantionului.

Faza de mentinere specificata explicit

Putem reveni cu usurinta la comportamentul ADSR normal pentru sintetizatoare atribuind explicit o valoare pentru ‘sustain:’, cum ar fi 0:

sample :loop_amen, sustain: 0, release: 0.75

Acum, esantionul nostru dureaza doar 0.75s in total. Cu valorile implicite pentru ‘attack:’ si ‘decay:’ egale cu 0, esantionul intra direct cu amplitudinea maxima, este mentinut astfel pentru 0s, apoi urmeaza coborarea la amplitudine 0 pe durata fazei de release - 0.75s.

Talere

Putem folosi acest comportament pentru a transforma esantioane lungi in versiuni mai scurte si mai percutante. Sa luam ca exemplu esantionul :drum_cymbal_open:

sample :drum_cymbal_open

Poti auzi sunetul talerului continuand o anumita perioada de timp. Totusi, putem folosi anvelopa pentru a il face mai percutant:

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

Poti simula lovirea unui taler si apoi amortizarea lui crescand durata de mentinere:

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

Acum distreaza-te aplicand anvelope esantioanelor. Incearca sa schimbi si viteza de redare pentru efecte cu adevarat interesante.


3.5 - Esantioane partiale

Aceasta sectiune va incheia explorarea player-ului de esantioane din Sonic Pi. Sa facem o scurta recapitulare. Pana acum am vazut cum putem porni esantioanele:

sample :loop_amen

Apoi am vazut cum putem schimba viteza de redare a esantioanelor, cum ar fi ascultandu-le la jumatate din viteza initiala:

sample :loop_amen, rate: 0.5

Apoi, am vazut cum putem introduce progresiv un esantion (sa facem asta la jumatate din viteza):

sample :loop_amen, rate: 0.5, attack: 1

Am vazut de asemenea cum putem sa folosim un start mai percutant al esantionului, dand o valoare explicita pentru ‘sustain:’ si atribuind valori mici pentru fazele de attack si release:

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

Totusi, nu ar fi frumos daca nu ar trebui sa pornim mereu de la inceputul esantionului? Nu ar fi frumos daca nu ar trebui sa mergem mereu pana la sfarsitul esantionului?

Alegerea punctului de pornire

Putem alege un punct de pornire arbitrar in esantion specificand un numar intre 0 si 1, unde 0 este inceputul acestuia, 1 sfarsitul, iar 0.5 este la jumatatea esantionului. Sa incercam sa redam doar a doua jumatate din amen break:

sample :loop_amen, start: 0.5

Ce-ar fi sa incercam ultimul sfert din esantion:

sample :loop_amen, start: 0.75

Alegerea punctului de oprire

Asemanator, este posibil sa alegem un punct de oprire arbitrar in cadrul esantionului , ca o valoare intre 0 si 1. Sa oprim amen break la jumatate:

sample :loop_amen, finish: 0.5

Precizarea inceputului si sfarsitului

Desigur, putem combina aceste 2 valori pentru a reda segmente arbitrare din fisierul audio. Cum ar fi doar o mica bucata de la mijloc:

sample :loop_amen, start: 0.4, finish: 0.6

Ce se intampla daca alegem o pozitie de inceput dupa pozitia de sfarsit?

sample :loop_amen, start: 0.6, finish: 0.4

Super! Este redat de la coada la cap!

In combinatie cu viteza

Putem combina aceasta posibilitate de a reda segmente audio arbitrare cu parametrul deja cunoscut ‘rate:’ (viteza de redare). De exemplu, putem reda o bucata foarte mica de la mijlocul esantionului amen break foarte lent:

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

In combinatie cu anvelopele

In fine, putem combina toate acestea cu anvelopele ADSR pentru a produce rezultate interesante:

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

Acum poti sa te joci modeland esantioanele cu ajutorul acestor chestii distractive…


3.6 - Esantioane externe

Desi esantioanele care vin impreuna cu Sonic Pi te pot ajuta sa incepi rapid sa experimentezi, ai putea incerca si cu alte sunete inregistrate. Sonic Pi ofera suport complet pentru acest lucru. Totusi, sa discutam pe scurt despre portabilitatea creatiei tale.

Portabilitatea

Cand compui o piesa bazata doar pe sintetizatoarele si esantioanele incluse in program, codul este tot ce iti trebuie ca sa reproduci fidel muzica ta. Gandeste-te putin - asta este un lucru uimitor! O simpla bucata de text pe care o poti trimite prin email sau pe care o poti incarca intr-un Gist este tot ce iti trebuie ca sa reproduci sunetele tale. Asta le face usor de impartasit cu prietenii tai, deoarece ei au nevoie doar de bucata de cod.

Totusi, daca incepi sa folosesti propriile esantioane, vei pierde aceasta portabilitate, deoarece pentru a reproduce piesa ta alte persoane vor avea nevoie nu doar de cod, ci si de acele esantioane. Acest lucru limiteaza posbilitatile altora de a modifica si de a face experimente cu creatia ta. Desigur, asta nu inseamna ca nu trebuie sa folosesti propriile esantioane, este doar un lucru de care trebuie sa tii cont.

Esantioane salvate loca

Cum poti reda un fisier oarecare WAV, AIFF sau FLAC din computerul tau? Tot ce trebuie sa faci este sa transmiti calea catre acest fisier pentru ‘sample’:

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

Sonic Pi va incarca automat si va reda acest esantion. Poti de asemenea sa folosesti toti parametrii standard pe care ai invatat sa-i folosesti cu ‘sample’:

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

3.7 - Pachete de esantioane

Nota: aceasta sectiune din tutorial se refera la situatia in care vrei sa folosesti foldere mai cu propriile esantioane. Acest lucru se va intampla daca ai descarcat sau cumparat un pachet de esantioane si vrei sa-l foloseti cu Sonic Pi.

Poti sa sari peste aceasta sectiune daca esti multumit cu esantioanele deja incluse in program.

Cand lucrezi cu foldere mari de esantioane externe poate fi dificil sa scrii de fiecare data calea completa cand vrei sa incarci un anumit esantion.

De exemplu, sa spunem ca ai folderul de mai jos in calculatorul tau:

/path/to/my/samples/

Inauntrul folderului gasim urmatoarele esantioane:

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

In mod normal, pentru a reda esantionul de pian putem folosi calea completa:

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

Daca vrem ca apoi sa redam esantionul de chitara putem folosi de asemenea calea completa:

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

Totusi, ambele apeluri ale comenzii sample cer ca noi sa stim numele esantioanelor din folder. Cum ar fi daca am dori sa ascultam fiecare esantion pe rand?

Indexarea pachetelor de esantioane

Daca vrem sa redam primul esantion dintr-un folder trebuie doar sa transmitem catre comanda ‘sample’ numele folderului si indexul ‘0’ ca mai jos:

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

Putem crea o scurtatura catre folder folosind o variabila:

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

Acum, daca dorim sa redam al doilea esantion din folder, trebuie doar sa adaugam 1 la index:

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

Observi ca nu mai este nevoie sa stim numele esantioanelor din folder - trebuie doar sa stim numele folderului (sau sa avem o scurtatura catre el). Daca cerem un index mai mare decat numarul de esantioane, va relua numaratoarea de la inceputul listei. Astfel, orice numar vom folosi, avem garantia ca vom obtine un esantion din acel folder.

Filtrarea pachetelor de esantioane

De obicei indexarea este suficienta, dar uneori avem nevoie de o metoda mai puternica de sortare si organizare a esantioanelor. Din fericire, multe pachete de esantioane contin informatii utile in numele fisierelor. Sa mai aruncam o privire la numele fisierelor din folderul nostru:

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

Observi ca in aceste nume de fisiere avem cateva informatii. In primul rand, avem ritmul in BPM (batai pe minut) la inceput. Deci, esantionul de pian este la 120 BPM si primele trei melodii sunt la 100 BPM. De asemenea, numele esantioanelor contin cheia. Esantionul de chitara este in Bb, iar melodiile in A#. Aceasta informatie este foarte utila cand combini aceste esantioane cu restul codului. De exemplu, stim ca putem reda esantionul de pian doar cu cod care este la 120 BPM si in cheia Bb.

Se pare ca putem folosi aceasta conventie de numire a esantioanelor in codul nostru pentru a le filtra pe cele pe care le vrem. De exemplu, daca lucram la 120 BPM, putem aplica un filtru care retine toate esantioanele al caror nume contine sirul ‘“120”’ astfel:

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

Aceasta va reda primul esantion care se potriveste. Daca dorim sa il redam pe al doilea trebuie sa folosim un index:

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

Putem chiar folosi mai multe filtre in acelasi timp. De exemplu, daca vrem un esantion al carui nume contine atat subsirurile “120” cat si “A#”, putem sa-l gasim usor astfel:

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

Putem de asemenea sa adaugam parametrii obisnuiti pentru ‘sample’:

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

Surse

Sistemul de filtrare a esantioanelor intelege doua tipuri de informatii: surse si fltre. Sursele sunt informatii utilizate pentru a crea liste de potentiali candidati. O sursa poate lua doua forme:

“/path/to/samples” - un sir reprezentand o cale valida catre un folder “/path/to/samples/foo.wav” - un sir reprezentand o cale valida catre un esantion

Functia ‘sample’ va aduna mai intai toate sursele si le va folosi pentru a crea o lista mare de candidati. Lista este construita adaugand mai intai toate caile valide si apoi adaugand toate fisierele ‘.flac’, ‘.aif’, ‘.aiff’, ‘.wav’ sau ‘.wave’ din aceste foldere.

De exemplu, sa aruncam o privire la codul acesta:

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

Aici am combinat continutul a doua foldere cu esantioane, apoi am adaugat inca un esantion individual. Daca "/path/to/my/samples/" contine 3 esantioane, iar "/path/to/my/samples2/" contine 12, avem 16 esantioane de indexat si de filtrat (3 + 12 + 1).

Implicit, doar esantioanele din folder sunt adaugate la lista de candidati. Uneori ai putea avea si subfoldere in care ai vrea sa cauti. Poti sa efectuezi o cautare recursiva a tuturor esantioanelor din toate subfolderele unui anumit folder, adaugand ‘**’ la sfarsitul caii:

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

Ai grija totusi, cautarea printr-un set mare de foldere poate dura foarte mult. Continutul tututor folderelor este pastrat in cache, deci intarzierea sa va manifesta doar prima data.

O observatie de final - sursele trebuie sa treaca inainte. Daca nicio sursa nu este specificata, setul de esantioane incluse in Sonic Pi va fi selectat ca lista implicita de candidati.

Filtre

Odata ce ai lista de candidati, poti folosi urmatoarele tipuri de filtre pentru a reduce selectia:

‘“foo”’ Siruri - filtrarea dupa un subsir care apare in numele fisierului (fara cale sau extensie). /fo[oO]/ Expresii regulate - filtrarea se face prin compararea numelui fisierului (fara cale sau extensie) cu un sablon. ‘:foo’ Cuvinte cheie - se verifica daca numele fisierului (fara cale sau extensie) se potriveste cu cuvantul cheie. lambda{|a| ... } Proceduri cu un argument vor fi tratate ca filtre. Vor primi lista curenta de candidati si trebuie sa intoarca o noua lista (continand cai valide catre esantioane). ‘1’ Numere - vor selecta candidatul cu indexul respectiv (cu reluarea numararii de la inceput daca este cazul).

De exemplu, putem filtra toate esantioanele dintr-un folder care contin sirul ‘“foo”’ si sa redam primul esantion care se potriveste, la jumatate din viteza normala:

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

Cauta in help (sistemul de ajutor) exemple mai detaliate de utilizare. Observa cum este respectata ordinea filtrelor.

Combinatii

Poti folosi liste oriunde poti folosi o sursa sau un filtru. Lista va fi normalizata automat si continutul va fi tratat ca sursele si filtrele obisnuite. Ca urmare, urmatoarele apeluri ale functiei ‘sample’ sunt echivalente semantic:

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

Concluzie

Aceasta a fost o sectiune avansata pentru cei care au nevoie de posibiltatea de a manevra pachete de esantioane. Daca n-ai inteles mare lucru din sectiunea asta, nu te ingrijora. Probabil inca nu ai nevoie de functionalitatea asta. Totusi, cand vei avea nevoie de ea vei sti ca exista si te vei putea intoarce sa recitesti aceasta parte cand vei lucra cu foldere mari cu esantioane.


4 - Randomizare

O modalitate de a face muzica ta mai interesanta este sa adaugi niste numere aleatoare (random). Sonic Pi ofera functii puternice pentru adaugarea unui caracter aleatoriu muzicii, dar inainte de a incepe trebuie sa aflam un lucru socant: in Sonic Pi aleator nu inseamna cu adevarat aleator. Ce naiba mai inseamna si asa? Ei bine, sa vedem.

Repetabilitate

O functie cu adevarat utila este ‘rrand’, care va intoarce o valoare aleatoare intre doua numere - un min si un max. (‘rrand’ este prescurtarea de la ranged random - aleator intr-un interval). Sa incercam sa redam o nota aleatoare:

play rrand(50, 95)

O, a cantat o nota aleatoare. A cantat nota ‘83.7527’. O nota draguta aleasa aleator intre 50 si 95. Hei, stai asa, tocmai am prezis nota exacta pe care ai obtinut-o si tu? Ceva nu e in regula aici. Incearca sa mai executi codul o data. Ce? A ales 83.7527 din nou? Asta nu poate fi aleator!

Raspunsul este ca nu este cu adevarat aleator, ci pseudo-aleator. Sonic Pi va genera numere aparent aleatoare intr-un mode repetabil. Acest lucru este util daca vrei sa te asiguri ca muzica pe care ai creat-o pe calculatorul tau va suna identica pe oricare alt calculator - chiar si atunci cand ai introdus un pic de aleatorism in compozitia ta.

Desigur, intr-o piesa oarecare, daca alege mereu ‘aleator’ valoarea 83.7527, nu este prea interesant. Totusi, nu se intampla asa. Incearca asta:

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

Da! In fine, suna aleator. In cadrul unei executii a codului, apelurile succesive ale functiilor vor intoarce valori aleatoare. Totusi, la urmatoarea rulare vor fi generate aceleasi numere aleatoare si sunetul va fi exact la fel. Este ca si cand Sonic Pi s-ar intoarce in timp exact in acelasi punct de fiecare data cand apesi butonu Executa (Run). Este Ziua Cartitei pentru compozitia muzicala!

Clopotele bantuite

Un ilustrare draguta a aleatorismului este exemplul cu clopotele bantuite care reda in bucla esantionul :perc_bell folosind valori aleatoare pentru viteza si pentru durata pauzelor intre sunete:

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

Intrerupere (cutoff) aleatoare

Un alt exemplu de utilizare a randomizarii este modificarea aleatoare a momentului de cutoff pentru un sintetizator. Un sintetizator potrivit pentru a incerca asta este emulatorul ‘:tb303’:

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

Valoarea de initializare (seed) a secventei aleatoare

Deci, ce faci faca nu-ti place o anumita secventa de numere aleatoare produsa de Sonic Pi? Ei bine, este posibil sa alegi un alt punct de pornire folosind ‘use_random_seed’. Valoarea implicita este 0, deci alege o alta valoare pentru seed si vei avea o secventa aleatoare diferita!

Priveste aceasta bucata de cod:

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

De fiecare data cand vei exexuta acest cod, vei auzi aceeasi secventa de 5 note. Pentru a obtine o secventa diferita schimba valoarea pentru seed:

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

Aceasta va produce o alta secventa de 5 note. Schimband valoarea de initializare si ascultand rezultatul poti gasi ceva ce iti place - iar cand vei transmite altora piesa, ei vor auzi exact acelasi lucru pe care l-ai auzit si tu.

Sa aruncam o privire si asupra altor functii utile pentru numere aleatoare.

choose (alege)

O situatie des intalnita este cea in care vrem sa alegem un element la intamplare dintr-o lista predefinita. De exemplu, vreau sa redau o nota dintre urmatoarele: 60, 65 sau 72. Poti face acest lucru folosind ‘choose’ care imi permite sa aleg un element dintr-o lista. Mai intai, trebuie sa trec numerele intr-o lista, introducandu-le intre paranteze patrate si separandu-le cu virgule: ‘[60, 65, 72]’. Apoi le transmit functiei ‘choose’:

choose([60, 65, 72])

Sa ascultam sunetul obtinut:

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

rrand

Am discutat deja despre functia ‘rrand’, dar sa ne mai oprim putin asupra ei. Functia intoarce un numar aleator dintr-un interval deschis. Asta inseamna ca nu va intoarce niciodata valoarea minima sau pe cea maxima - intotdeauna va fi un numar intre cele doua. Numarul va fi intotdeauna de tipul float (cu virgula mobila) - insemnand ca nu este un numar intreg, ci are si o parte zecimala. Exemple de numere de tip float returnate de ‘rrand(20, 110)’:

87.5054931640625 86.05255126953125 61.77825927734375

rrand_i

Vor fi si situatii in care vei dori un numar aleator intreg, nu unul cu virgula. Aici intervine ‘rrand_i’. Functioneaza la fel ca ‘rrand’, doar ca poate returna si valorile minima sau maxima (foloseste un interval inchis de valori). Exemple de numere returnate de rrand_i(20, 110):

88 86 62

rand

Va returna un numar tip float intre 0 (inclusiv) si valoarea maxima pe care o specifici (exclusiv). Implicit va returna o valoare intre 0 si 1. Este deci util pentru alegerea aleatoare a valorilor pentru ‘amp:’:

loop do
  play 60, amp: rand
  sleep 0.25
end

rand_i

Asemanator cu ‘rrand_i’ pentru ‘rrand’, exista ‘rand_i’ care va returna o valoare intreaga intre 0 si valoarea maxima pe care i-o transmiti.

dice

Uneori vrei sa simulezi ca dai cu zarul - este un caz particular pentru ‘rrand_i’ in care valoarea minima este mereu 1. Un apel al functiei ‘dice’ cere sa specifici numarul de fete ale zarului. Un zar standard are 6 fete, deci ‘dice(6)’ va avea un comportament asemanator - va returna valorile 1, 2, 3, 4, 5 sau 6. Totusi, la fel ca in jocurile fantasy ai putea considera util un zar cu 4 fete, sau cu 12, sau 20 - poate chiar cu 120 de fete!

one_in

In fine, poate doresti sa emulezi obtinerea scorului maxim la un zar, cum ar fi 6 in cazul celui standard. ‘one_in’ returneaza true cu o probabilitate de 1 din numarul de fete ale zarului. Astfel, ‘one_in(6)’ va returna true cu probabilitate de 1 din 6 si false in celelalte cazuri. True si false (adevarat si fals) sunt valori utile pentru instructiunile ‘if’ (daca) despre care vom vorbi mai tarziu in acest tutorial.

Acum, poti incepe sa zapacesti codul tau cu putin aleatorism!


5 - Structuri de programare

Acum ca ai invatat bazele producerii de sunete folosind ‘play’ si ‘sample’ si crearea de melodii simple folosind ‘sleep’ (pauza) intre sunete, ai putea sa te intrebi ce iti mai poate oferi lumea programarii…

Ei bine, te asteapta lucruri interesante.Se pare ca structurile de baza din programare, cum ar fi buclele, conditiile, functiile si firele de executie iti ofera niste unelte incredibil de puternice pentru a-ti manifesta talentul muzical.

Sa ramanem la elementele de baza…


5.1 - Blocuri

O structura pe care o vei intalni adesea in Sonic Pi este blocul. Blocurile iti permit sa faci lucruri utile cu bucati mari de cod. De exemplu, cu comanda synth si cativa parametri am reusit sa schimbam ceva ce a influentat o singura linie. Totusi, uneori vrem sa facem astfel de modificari care sa influenteze mai multe linii de cod. De exemplu, am putea dori sa le reluam in bucla (loop), sa adaugam un efect reverb, sa le rulam doar 1 data din 5, etc. Sa analizam codul urmator:

play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62

Pentru a actiona asupra unei bucati de cod, trebuie sa transmitem catre Sonic Pi unde incepe si unde se termina. Folosim ‘do’ pentru inceput si ‘end’ pentru sfarsit. De exemplu:

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

Totusi, nu este inca suficient si bucata respectiva nu functioneaza (incearca sa o executi si vei primi un mesaj de eroare) deoarece nu am transmis Sonic Pi ce vrem sa faca cu acest bloc do/end. Putem transmite acest lucru catre Sonic Pi scriind comenzi specifice inainte de ‘do’. Vom vedea mai multe astfele de bucati de cod mai tarziu pe parcursul tutorialului. Pentru moment este important de stiut ca delimitand o parte din cod cu ‘do’ si ‘end’ Sonic Pi va sti ca vrei sa faci ceva special cu acea bucata.


5.2 - Iteratii si bucle

Pana acum am petrecut mare parte din timp analizand diferite sunete pe care le poti crea folosind comenzi ‘play’ si ‘sample’. Am invatat de asemenea cum putem alege momentul cand pornim aceste sunete folosind ‘sleep’.

Dupa cum ai observat probabil, poti face o gramada de chestii interesante folosind aceste blocuri de baza. Folosind puterea programarii pentru a-ti structura muzica si compozitiile ti se vor deschide insa noi perspective. In urmatoarele sectiuni vom explora cateva dintre aceste unelte noi si puternice. Sa incepem cu iteratiile si buclele.

Repetitia

Ai scris vreo bucata de cod pe care ai vrea sa o repeti de cateva ori? De exemplu, ai putea avea ceva de genul:

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

Cum ar fi daca ai vrea sa se repete de 3 ori? Ei bine, putem face ceva simplu - o copiem si apoi o lipim de 3 ori:

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

E ceva cod acolo! Ce se intampla daca vrei sa schimbi esantionul cu ‘:elec_plip’? Va trebui sa gasesti toate locurile in care apare cel initial - ‘:elec_blup’ si sa il inlocuiesti peste tot. Mai mult, ce s-ar intampla daca ai vrea sa repeti bucata initiale de 50 de ori sau chiar de 1000? Atunci chiar ar fi o gramada de cod si deci o gramada de linii pe care ar trebui sa le modifici daca ai vrea sa faci o schimbare.

Iteratia

De fapt, repetarea unei bucati de cod ar trebui sa fie la fel de simpla ca a spune fa asta de trei ori. Cam asa si este. Iti aduci aminte de prietenul nostru - blocul de cod? Putem sa-l folosim pentru a marca inceputul si sfarsitul codului pe care vrem sa-l repetam de trei ori. Apoi vom folosi comanda speciala ‘3.times’. Deci, in loc sa scriem fa asta de trei ori (do this three times), scriem 3.times do - nu pare prea greu. Tine minte sa scrii ‘end’ la sfarsitul codului care vrei sa se repete:

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

Nu-i asa ca e mult mai curat decat metoda copy/paste? Putem folosi blocurile pentru a crea mai multe structuri repetitive:

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

Iteratii in cadrul altor iteratii

Putem pune iteratii inauntrul altor iteratii pentru a crea niste midele interesante. De exemplu:

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

Reluarea in bucla

Daca vrei ca o bucata sa se repete de multe ori, ai putea fi nevoit sa folosesti numere foarte mari, de exemplu 1000.times do. In acest caz, probabil ca e mai bine sa ceri Sonic Pi sa repete la infinit (sau macar pana cand apesi butonul de oprire!). Sa redam amen break in bucla la infinit:

loop do
  sample :loop_amen
  sleep sample_duration :loop_amen
end

Un lucru de tinut minte este ca aceste bucle actioneaza ca niste gauri negre pentru cod. Odata ce codul ajunge la bucla (loop), el nu o va parasi niciodata daca nu apesi pe butonul de oprire - pur si simplu va relua la nesfarsit bucla. Asta inseamna ca daca ai cod scris dupa loop, nu il vei auzi niciodata. De exemplu, talerul de dupa loop nu va fi redat niciodata:

loop do
  play 50
  sleep 1
end
sample :drum_cymbal_open

Acum poti incepe sa-ti structurezi codul folosind iteratii si bucle!


5.3 - Conditii

Ai putea dori nu doar sa redai o nota aleatoare (vezi sectiunea precedenta pentru aleatorism), dar si sa iei o decizie aleatoare si pe baza rezultatului ei sa executi o bucata de cod sau alta. De exemplu, ai putea dori sa redai la intamplare o toba sau un taler. Putem obtine acest lucru folosind instructiunea ‘if’.

Datul cu banul

Deci, sa dam cu banul: daca iese cap, redam toba, daca este pajura, redam talerul. Usor. Putem simula datul cu banul cu functia ‘one_in’ (prezentata in sectiunea despre aleatorism) specificand o probabilitate de 1 din 2: one_in(2). Putem apoi folosi rezultatul pentru a decide intre doua bucati de cod, cea pentru toba si cea pentru taler:

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

Instructiunea ‘if’ are trei parti:

Intrebarea care trebuie pusa Prima optiune pentru codul de executat (daca raspunsul la intrebare este da) A doua optiune pentru codul de executat (daca raspunsul la intrebare este nu)

In general, in limbajele de programare, raspunsul da este reprezentat prin termenul ‘true’ (adevarat), iar raspunsul nu este reprezentat prin termenul ‘false’ (fals). Deci trebuie sa gasim o intrebare la care raspunsul este ‘true’ sau ‘false’, adica exact ceea ce face ‘one_in’.

Prima optiune este delimitata de ‘if’ si ‘else’, in timp ce a doua este delimitata de ‘else’ si ‘end’. La fel ca in cazul blocurilor do/end, poti pune mai multe linii de cod in oricare dintre cele doua locuri. De exemplu:

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

De data asta vom face pauze de durate diferite in functie de algerile pe care le facem.

If simplu

Uneori vrem ca o instructiune unica sa se execute optional. Acest lucru este posibil prin adaugarea unui ‘if’ si a conditiei la sfarsit. De exemplu:

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

Acest cod va reda acorduri cu componente diferite, cu probabilitati diferite pentru fiecare nota de a face parte din acestea.


5.5 - Fire de executie

Sa zicem ca ai obtinut un bass incredibil si un beat pe masura. Cum le redai in acelasi timp? O solutie este sa combini liniile manual - redai un pic de bas, apoi putin toba, iarasi bas… Dar potrivirea timpilor va deveni rapid greu de gestionat, mai ales daca mai ai de introdus si alte elemente.

Dar daca Sonic Pi ar putea sa faca automat intreteserea sunetelor? Ei bine, chiar poate si acest lucru se realizeaza folosind ceea ce se numeste thread (fir de executie).

Bucle infinite

Pentru simplitate, vom considera ca acestea sunt basul incredibil si beatul pe masura:

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

Asa cum am discutat, buclele sunt gauri negre pentru program. Odata intrat intr-o bucla (loop) nu mai poti sa iesi decat apasand pe stop. Cum redam cele doua bucle in acelasi timp? Trebuie sa instruim Sonic Pi sa porneasca ceva in acelasi timp cu restul codului. Aici intervin firele de executie.

Salvarea oferita de firele de executie (threads)

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

Introducand prima bucla intr-un bloc do/end ‘in_thread’, spunem Sonic Pi sa ruleze continutul blocului do/end exact in acelasi timp cu instructiunea care urmeaza dupa blocul respectiv (care se intampla sa fie a doua bucla). Incearca si vei auzi atat tobele cat si basul in acelasi timp!

Cum ar fi daca am vrea sa adaugam si un sintetizator pe deasupra? Ceva gen:

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

Avem aceeasi problema ca mai inainte. Prima bucla este redata in acelasi timp cu a doua datorita instructiunii ‘in_thread’. Totusi, a treia bucla nu este redata niciodata. Trebuie deci sa folosim un nou thread:

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

Rularea ca fire de executie

S-ar putea sa te surprinda faptul ca atunci cand apesi butonul Executa (Run), de fapt creezi un nou fir de executie pentru cod. De aceea, apasarea repetata a butonului va face ca sunetele sa se suprapuna. Cum rularile codului sunt fire de executie, ele vor imbina automat sunetele pentru tine.

Domeniu

Pe masura ce inveti cum sa stapanesti Sonic Pi, vei invata ca firele de executie sunt cele mai importante blocuri din care este construita muzica. Unul dintre cele mai importante roluri pe care le au este sa izoleze setarile curente de celelalte fire. Ce inseamna asta? Ei bine, cand schimbi sintetizatorul folosind ‘use_synth’, acest lucru se refera doar la firul curent - in niciun alt thread sintetizatorul nu va fi schimbat. Sa vedem un exemplu:

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

Ai observat ca sunetul de la jumatate este diferit de celelalte? Comanda ‘use_synth’ a afectat doar thread-ul din care face parte, nu si thread-ul principal.

Mostenire

Cand creezi un nou thread folosind ‘in_thread’, acesta va mosteni automat toate setarile de la thread-ul curent. Sa vedem:

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

Ai observat ca a doua nota a fost redata folosind sintetizatorul ‘:tb303’ desi a fost redata intr-un thread separat? Oricare dintre parametrii modificati cu diferitele functii ‘use*’ se va comporta in acelasi mod.

Cand un thread este creat, va mosteni toate setarile de la thread-ul parinte, dar nu va transmite inapoi nicio modificare.

Numele thread-urilor

Putem da nume thread-urilor noastre:

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

Priveste panoul continand jurnalul cand executi codul acesta. Ai observat ca in jurnal apare numele thread-ului?

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

Un singur thread poate avea un anumit nume

Un ultim lucru de retinut despre thread-uri este ca un singur thread cu un anumit nume poate rula la un moment dat. Sa exprimentam folosind urmatorul cod:

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

Incearca sa copiezi codul asta intr-un buffer si apasa pe butonul Run. Apasa din nou de mai multe ori. Asculta cacofonia de amen break care se reiau si se suprapun. Ok, acum apasa pe Stop.

Acesta este comportamentul pe care l-am vazut de mai multe ori - apesi pe Run si sunetele se suprapun peste cele deja existente. Deci daca ai o bucla si apesi pe Run de trei ori, vei avea trei randuri de bucle care sunt redate concomitent.

Totusi, folosind thread-urile cu nume, lucrurile stau diferit:

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

Incearca sa apesi butonul Run de mai multe ori pentru acest cod. Vei auzi o singura bucla cu amen break. De asemenea, vei observa asta in jurnal:

==> Skipping thread creation: thread with name :amen already exists.

Sonic Pi iti spune ca exista deja un thread cu numele ‘:amen’ care ruleaza, deci nu va crea un altul.

Acest comportament poate ca nu pare util pentru moment, dar va fi folositor cand vei incepe sa programezi in direct…


5.5 - Functii

Dupa ce vei incepe sa scrii serios la cod, vei dori sa gasesti o cale sa organizezi si sa structurezi lucrurile astfel incat sa arate mai curat si sa fie usor de inteles. Functiile ofera o unealta foarte utila pentru aceasta. Ele ne ofera posibilitatea sa dam un nume unei bucati de cod. Sa aruncam o privire.

Definirea functiilor

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

Aici am definit o functie noua, numita ‘foo’. Pentru asta folosim blocul do/end si cuvantul magic ‘define’ (defineste) urmat de numele pe care vrem sa-l dam functiei. Nu suntem obligati sa o numim ‘foo’, puteam sa ii spunem si ‘bar, ‘baz’ sau, mai bine, un nume care chiar inseamna ceva, gen ‘sectiune_principala’ sau ‘lead_riff’.

Tine minte sa treci intotdeauna doua puncte ‘:’ inaintea numelui functiei cand o definesti.

Apelarea functiilor

Odata ce am definit o functie, putem sa o apelam doar scriindu-i numele:

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

Putem folosi ‘foo’ in interiorul unor iteratii sau oriunde am fi folosit ‘play’ sau ‘sample’. Aceasta ne ofera un mod interesat de a ne exprima si de a crea cuvinte noi pe care sa le folosim in compozitii.

Functiile sunt memorate intre executii

Pana acum, de fiecare data cand ai apasat butonul Run, Sonic Pi a pornit de la zero. Nu stie nimic in afara de ceea ce se afla in buffer. Nu poti sa faci referire la codul din alt buffer sau din alt thread. Functiile schimba acest lucru. Cand definesti o functie, Sonic Pi o tine minte. Sa incercam. Sterge tot codul din buffer si inlocuieste-l cu:

foo

Apasa butonul Run si vei auzi functia cantand. Unde s-a dus codul? Cum a stiut Sonic Pi ce sa cante? Sonic Pi a memorat functia ta - deci si dupa ce ai sters-o din buffer, tine minte ce ai scris acolo. Acest comportament este valabil doar pentru functiile create folosind ‘define’ (si ‘defonce’).

Functii cu parametri

Asa cum poti transmite functiei ‘rrand’ valorile pentru min si max, poti invata functiile tale sa accepte argumente. Sa aruncam o privire:

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

Nu e prea palpitant, dar ilustreaza ce am spus. Am creat propria versiune pentru ‘play’, numita ‘my_player’, care accepta un argument.

Argumentele (parametrii functiei) trebuie sa urmeze dupa ‘do’ din blocul do/end ‘define’, incadrati de bare verticale ‘ ’ si separati de virgule ‘,’. Poti utiliza ce cuvinte vrei pentru numele parametrilor.

Partea magica se afla in interiorul blocului do/end ‘define’. Poti folosi numele parametrilor ca si cum ar fi valori reale. In acest exemplu, redau nota ‘n’. Poti considera parametrii ca un fel de promisiune ca la momentul executiei codului ei vor fi inlocuiti cu valori reale. Acest lucru se face transmitand parametrii functiei cand o apelezi. Eu am facut asta in linia ‘my_player 80’ pentru a reda nota 80. In cadrul definitiei functiei, ‘n’ este acum inlocuit cu 80, deci ‘play n’ se transforma in ‘play 80’. Cand voi apela din nou functia cu ‘my_player 90’, ‘n’ va fi inlocuit cu 90, deci ‘play n’ va deveni ‘play 90’.

Sa vedem un exemplu mai interesant:

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

Aici am folosit ‘repeats’ ca si cum ar fi fost un numar in linia ‘repeats.times do’. De asemenea am folosit ‘root’ ca si cand ar fi fost numele unei note cand am apelat ‘play’.

Iata cum am reusit sa scriem ceva foarte expresiv si usor de citit mutand o parte din cod intr-o functie!


5.6 - Variabile

Un lucru util pe care il putem face in cadrul codului nostru este sa cream nume pentru obiecte. In Sonic Pi asta se face foarte usor, scrii un nume pe care vrei sa-l folosesti, semnul egal (‘=’), apoi obiectul pe care vrei sa-l memorezi:

sample_name = :loop_amen

Aici, am ‘memorat’ simbolul ‘:loop_amen’ in variabila ‘sample_name’. Putem folosi ‘sample_name’ oriunde am fi folosit ‘:loop_amen’. De exemplu:

sample_name = :loop_amen
sample sample_name

Exista trei motive principale pentru utilizarea variabilelor in Sonic Pi: comunicarea rolului, gestiunea repetitiilor si stocarea rezultatului unor actiuni.

Comunicarea rolului

Cand scrii cod e usor sa te gandesti doar ca tu ii spui calculatorului sa faca un anumit lucru - cat timp computerul intelege este OK. Totusi, e important sa te gandesti ca nu doar computerul citeste codul. Alte persoane ar putea sa il citeasca de asemenea si sa incerce sa inteleaga despre ce este vorba. De asemenea, e posibil ca tu sa iti recitesti propriul cod mai tarziu si sa vrei sa intelegi cum functioneaza. Desi ar putea sa ti se para evident acum, acest lucru ar putea sa nu fie valabil pentru altii sau chiar pentru tine in viitor!

Un mod de a-i ajuta pe altii sa inteleaga ce face codul tau este sa scrii comentarii (asa cum am vazut intr-o sectiune anterioare). Alt mod este sa folosesti variabile cu nume alese conform rolului lor. Priveste acest cod:

sleep 1.7533

De ce foloseste acest numar, 1.7533? De unde vine acest numar? Ce inseamna? Priveste acum acest cod:

loop_amen_duration = 1.7533
sleep loop_amen_duration

Acum este mult mai clar ce inseamna 1.7533: este durata esantionului ‘:loop_amen’! Desigur, ai putea spune ca e mai simplu sa scrii:

sleep sample_duration(:loop_amen)

Care este, desigur, un mod potrivit de a comunica scopul codului respectiv.

Gestionarea repetitiilor

Adesea poti vedea multe repetitii in cod si cand vrei sa schimbi ceva trebuie sa schimbi intr-o multime de locuri. Priveste acest cod:

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)

Folosim in multe locuri ‘:loop_amen!’ Sa presupunem ca vrem sa auzim cum ar suna daca am folosi un alt esantion, cum ar fi ‘:loop_garzul’. Ar trebui sa inlocuim peste tot :loop_amen cu :loop_garzul. Ar putea fi OK daca ai avea o gramada de timp la dispozitie, dar daca interpretezi live pe scena? Uneori nu iti permiti luxul de a pierde timpul, mai ales cand vrei ca lumea sa danseze in continuu.

Daca ai fi scris codul astfel:

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)

Codul ar face acelasi lucru ca cel de mai sus (poti incerca). Dar ne da si posibilitatea de a modifica o singura linie din sample_name = :loop_amen in sample_name = :loop_garzul, ceea ce va schimba esantionul redat in mai multe locuri folosind magia variabilelor.

Stocarea rezultatelor

In fine, un motiv bun pentru a utiliza variabilele este acela ca ajuta la stocarea rezultatelor. De exemplu, ai putea dori sa faci anumite lucruri cu durata esantionului:

sd = sample_duration(:loop_amen)

Acum putem folosi ‘sd’ oriunde avem nevoie de durata esantionului ‘:loop_amen’.

Poate mai important, o variabila ne permite sa stocam rezultatul unui apel al unei functii ‘play’ sau ‘sample’:

s = play 50, release: 8

Acum am memorat ‘s’ ca o variabila, ceea ce ne permite sa controlam sintetizatorul in timpul functionarii:

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

Vom intra in detalii privind controlul sintetizatoarelor intr-o sectiune ulterioara.

Variabile

Variabilele sunt foarte utile pentru a atribui nume diferitelor obiecte si pentru a pastra rezultatul unor calcule, dar este important sa stiti ca ele ar trebui in general sa fie folosite doar local in cadrul unui thread. De exemplu, nu faceti asta:

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

In exemplul de mai sus am atribuit unei variabile a o lista circulara de numere si apoi am folosit-o in doua live-loop-uri separate. In prima bucla sortam lista (la (ring 1, 2, 3, 4, 5, 6)) si apoi o afisam in jurnal. Daca rulezi codul, vei vedea ca lista printata nu este intotdeauna sortata!. Lucrul acesta ar putea sa te surprinda - mai ales ca uneori lista este sortata, iar alteori nu. Acesta comportament este denumit nedeterminist si este rezultatul unei probleme neplacute cunoscuta ca race-condition. Aceasta problema apare datorita faptului ca a doua bucla incearca de asemenea sa manipuleze lista (in acest caz prin aleatorizarea ei), iar in momentul in care aceasta este tiparita, uneori tocmai a fost sortata iar alteori tocmai a fost amestecata. Cele doua bucle sunt in competitie pentru a efectua operatii diferite cu aceeasi variabila si de fiecare data o alta bucla ‘castiga’.

Exista doua solutii pentru aceasta problema. Prima ar fi nu utiliza aceeasi variabila in mai multe bucle live sau thread-uri. De exemplu, codul de mai jos va afisa intotdeauna lista sortata deoarece fiecare bucla are propria variabila:

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

Totusi, uneori chiar vrem sa folosim in comun diferite obiecte in cadrul unor thread-uri diferite. De exemplu: cheia curenta, ritmul, sintetizatorul etc. In aceste cazuri, solutia este folosirea sistemului de stari din Sonic Pi, folosind functiile get si set care asigura consistenta la nivel de thread. Acesta va fi prezentat in sectiunea 10.


5.7 - Sincronizarea firelor de executie

Cand ai devenit suficient de avansat sa programezi live cu un numar de functii si thread-uri simultane, ai observat probabil ca este destul de usor sa faci o greseala intr-un thread astfel incat sa il blochezi. Asta nu e o mare problema, fiindca poti reporni usor thread-ul apasand pe Run. Totusi, daca repornesti un thread el va fi decalat fata de thread-urile originale.

Mostenirea pozitiei in timp

Asa cum am discutat anterior, thread-urile noi create cu ‘in_thread’ mostenesc toti parametrii de la thread-ul parinte. Asta include si pozitia in timp. Acest lucru inseamna ca thread-urile sunt mereu aliniate in timp daca au pornit simultan.

Totusi, daca pornesti un thread de sine statator, el va porni cu timpul sau propriu care este putin probabil sa fie sincronizat cu cel al altor thread-uri care ruleaza la momentul respectiv.

Marcaje de timp si sincronizare

Sonic Pi ofera o solutie pentru aceast problema cu functiile ‘cue’ (marcaj de timp) si ‘sync’ (sincronizare).

‘cue’ ne permite sa transmitem mesaje referitoare la tact catre alte thread-uri. Implicit celelalte thread-uri nu sunt interesate si vor ignora aceste mesaje. Totusi, poti sa le determini cu usurinta sa devina interesate folosind functia ‘sync’.

Trebuie sa fii constient ca ‘sync’ este oarecum similar cu ‘sleep’ prin aceea ca opreste thread-ul curent sa faca orice pentru o anumita perioada de timp. Totusi, cu ‘sleep’ tu decizi cat vrei sa dureze pauza, in timp ce cu ‘sync’ nu stii cat timp va dura asteptare, deoarece ‘sync’ asteapta urmatorul ‘cue’ de la alt thread, care poate sosi mai devreme sau mai tarziu.

Sa examinam acest lucru mai in detaliu:

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

Aici avem doua thread-uri, unul actionand ca un metronom, fara sa redea vreun sunet, dar trimitand mesaje ‘:tick’ corespunzator tactului la fiecare bataie. Al doilea thread este sincronizat cu mesajele ‘tick’ si cand primeste unul mosteneste timpul din thread-ul ‘cue’ continuand sa ruleze.

Ca urmare, vom auzi esantionul :drum_heavy_kick exact cand cealalt thread trimite mesajul ‘:tick’, chiar daca cele doua thread-uri nu au fost pornite in acelasi timp:

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

Acel apel buclucas al functiei ‘sleep’ ar face in mod normal ca al doilea thread sa fie defazat fata de primul. Totusi, folosind ‘cue’ si ‘sync’, putem sincroniza automat thread-urile trecand peste decalajele accidentale.

Nume pentru marcajele de timp

Esti liber sa folosesti ce nume doresti pentru mesajele ‘cue’, nu doar ‘:tick’. Trebuie doar sa te asiguri ca celelalte thread-uri se sincronizeaza dupa numele corect - in caz contrar ar putea astepta la infinit (sau pana cand apesi butonul Stop).

Sa ne jucam putin cu numele pentru marcajele ‘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

Aici avem o bucla ‘cue’ principala care trimite aleator un tact dintre :foo, :bar si :baz. Avem apoi trei thread-uri de tip bucla care se sincronizeaza fiecare cu unul dintre cele trei nume si redau fiecare un alt esantion. Efectul final este ca auzim un sunet la fiecare 0.5 batai deoarece de fiecare data unul dintre thread-urile ‘sync’ se va sincroniza cu thread-ul ‘cue’ si va reda propriul esantion.

Acest lucru va fi valabil desigur si daca schimbi ordinea thread-urilor, deoarece thread-urile ‘sync’ vor sta si vor astepta pur si simplu urmatorul ‘cue’.


6 - Efecte de studio

Una dintre caracteristicile cele mai atractive ale Sonic Pi este posibilitatea de a adauga cu usurinta efecte de studio sunetelor. De exemplu, ai putea dori sa adaugi un efect de reverb anumitor parti din piesa ta, sau un ecou, sau chiar distort sau wobble asupra basului.

Sonic Pi ofera o cale foarte simpla dar foarte puternica pentru adaugarea efectelor. Iti permite chiar sa le inlantuiesti (astfel incat poti sa aplici sunetelor tale o distorsiune, apoi un ecou, apoi o reverberatie si sa controlezi fiecare efect individual folosind parametri (intr-un mod similar cu transmiterea parametrilor pentru sintetizatoare si esantioane). Poti chiar modifica parametrii pentru efecte in timp ce ruleaza. De exemplu, poti creste reverberatia pentru bas pe durata unui track…

Pedala de chitara

Daca suna putin complicat, nu te ingrijora. Dupa ce te vei juca putin cu ele va deveni destul de clar. Inainte sa faci asta, putem sa facem o analogie cu pedalele pentru chitara. Exista multe feluri de pedale pentru efecte pe care le poti cumpara. Unele adauga reverb, altele distort, etc. Un chitarist va conecta chitara sa la o pedala de efecte - sa zicem la cea de distorsiune - , apoi va lua alt cablu si va conecta (inlantui) si o pedala de reverb. Iesirea de la pedala reverb poate fi conectata la amplificator:

Chitara -> Distorsiune -> Reverberatie -> Amplificator

Aceasta se numeste o inlanuire de efecte. Sonic Pi suporta acest mod de lucru. In plus, fiecare pedala are adesea butoane si potentiometre pentru a-ti permite controlul asupra efectului pe care il aplici. Sonic Pi suporta si acest tip de control. Acum sa ne imaginam un chitarist care canta in timp ce cineva se joaca cu controlul efectelor chiar in timp ce acestea actioneaza. Sonic Pi suporta si acest mod, dar in loc sa fie nevoie de altcineva care sa controleze lucrurile pentru tine, computerul este cel care preia acest rol.

Sa exploram efectele (FX)!


6.1 - Adaugarea de efecte

In aceasta sectiune vom discuta despre doua efecte: reverb si echo. Vom vedea cum le putem folosi, cum sa le controlam parametrii si cum sa le inlantuim.

Sonic Pi foloseste blocuri pentru efecte. Deci, daca nu ai citit sectinea 5.1, ar fi bine sa arunci o privire asupra ei si apoi sa revii.

Reverb (reverberatie)

Daca vrem sa folosim efectul reverb adaugam codul special ‘with_fx :reverb’ la inceputul blocului:

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

Acum executa acest cod si vei auzi cum este redat cu efectul reverb. Suna bine, nu? Aproape orice suna bine cu reverb.

Acum sa vedem ce se intampla daca avem cod in afara blocului do/end:

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

Observi ca la sfarsit ‘play 55’ este redat fara reverb. Asta se intmpla deoarece este in afara blocului do/end, deci nu este influentat de efectul reverb.

La fel, daca ai sunete generate inainte de blocul do/end, nici ele nu sunt influentate:

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

Echo (ecou)

Exista multe efecte pe care le poti aplica. Ce-ar fi sa incercam putin ecou?

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

Una dintre caracteristicile importante ale efectelor din Sonic Pi este ca permit specificarea de parametri asemanatori cu cei pentru ‘play’ sau ‘sample’. De exemplu, un parametru interesant pentru echo este ‘phase:’ care reprezinta durata ecoului in batai. Sa facem ecoul mai lent:

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

Acum sa facem ecoul mai rapid:

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

Sa facem acum ca ecoul sa se atenueze mai lent adaugand parametrul ‘decay:’ cu durata de 8 batai:

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

Efecte in efecte

Un aspect important legat de blocurile de efecte este poti fi continute unele in altele. Asta inseamna ca efectele pot fi inlantuite cu usurinta. De exemplu, daca vrei sa redai o parte din cod cu echo apoi cu reverb, poti face asta foarte simplu, punandu-le unul in interiorul celuilalt:

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

Imagineaza-ti fluxul audio dinspre interior spre exterior. Sunetul din toata bucata de cod din blocul do/end din interior, cum ar fi ‘play 50’, este trimis mai intai catre efectul echo, iar sunetul efectului echo este apoi trimis catre efectul reverb.

Putem folosi inlantuirea pe mai multe niveluri pentru rezultate cat mai surprinzatoare. Dar, ai grija, efectele consuma multe resurse, iar atunci cand le inlantuiesti de fapt se executa mai multe efecte in acelasi timp. Deci, fii grijuliu cu folosirea efectelor mai ales pe platforme hardware mai putin puternice, cum ar fi Raspberry Pi.

Explorarea efectelor

Sonic Pi vine cu un mare numar de efecte cu care te poti juca. Pentru a vedea care sunt cele disponibile, fa click pe Efecte in marginea din stanga a sistemului de ajutor si vei vedea lista de optiuni. Iata o lista cu preferatele mele:

wobble, reverb, echo, distortion, slicer

Acum te poti dezlantui adaugand efecte peste tot, pentru sunete incredibile!


6.2 - Efectele in viata reala

Desi par simple vazute din afara, efectele sunt niste unelte foarte complexe la interior. Simplitatea lor determina adesea utilizatorii sa exagereze cu folosirea lor in piese. Asta nu e o mare problema daca ai o masina puternica, dar daca folosesti ca mine un Raspberry Pi pentru improvizatii pe scena, trebuie sa ai grija cat de multe ii ceri daca vrei sa fii sigur ca poate tine pasul.

Sa ne uitam la codul de mai jos:

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

Aici redam nota 60 cu un release foarte scurt, deci este o nota scurta. Vrem sa aiba reverberatie, deci am inclus-o intr-un bloc reverb. Toate bune pana aici. Numai ca…

Sa privim ce face codul. Mai intai avem o bucla (‘loop’), ceea ce inseamna ca tot ce se afla in interiorul ei este repetat la nesfarsit. Apoi avem un bloc ‘with_fx’. Asta inseamna ca vom crea un nou efect reverb de fiecare data cand bucla se reia. E ca si cand ai avea o pedala de efecte separata pentru fiecare ciupire a corzii unei chitare. E tare ca poti face asta, dar nu e ce-ti doresti intotdeauna. De exemplu, acest cod va fi redat cu dificultate de un Raspberry Pi. Toata munca de crearea a efectului reverb si apoi asteptarea pana cand trebuie oprit si anulat este gestionata de ‘with_fx’ pentru tine, dar consuma din timpul pretios al procesorului.

Cum putem face sa se comporte similar cu o configuratie uzuala in care chitaristul are o singura pedala pentru reverb care controleaza toate sunetele? Simplu:

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

Punem bucla in interiorul blocului ‘with_fx’. In felul asta cream un singur reverb pentru toate notele redate in bucla. Acest cod este mult mai eficient si va functiona fara probleme pe un Raspberry Pi.

O solutie de compromis este sa folosim ‘with_fx’ cu un bloc de iteratii in cadrul unei bucle:

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

In felul asta am ridicat cu un nivel ‘with_fx’ din interiorul buclei si cream un reverb nou la fiecare 16 note.

Este un lucru atat de des intalnit, incat ‘with_fx’ ofera suport pentru un parametru care face exact asta, fara a fi nevoie sa scrii blocul ‘16.times’:

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

Ambele exemple, cel cu reps: 16 si cel cu 16.times do, se comporta la fel. In mare, reps: 16codul din blocul do/end de 16 ori, deci poti folosi oricare dintre cele doua forme in functie de preferintele personale.

Cum spuneam, nu exista greseli, ci doar posibilitati. Totusi, unele dintre abodari pot crea sunete diferite si pot avea un impact diferit asupra performantelor. Deci te poti juca incercand sa gasesti metoda care suna cel mai bine pentru tine, tinand cont in acelasi timp de constrangerile legate de performantele sistemului.


7 - Controlul sunetelor in timpul redarii

Pana acum am vazut cum putem porni sintetizatoare sau esantioane si cum le putem modifica valorile implicite pentru parametri ca amplitudine, pozitionare, anvelopa si altele. Fiecare sunet in curs de redare este independent, avand propria lista de parametri valabili pe toata durata lui.

N-ar fi interesant daca ai putea schimna parametrii unui sunet in timp ce este redat, exact cum ai putea apasa pe o coarda de la chitara in timp ce inca vibreaza?

Se pare ca ai noroc - exact despre asta vom vorbi in aceasta sectiune.


7.1 - Controlul sintetizatorului in timpul redarii

Pana acum ne-am concentrat doar pe pornirea sunetelor si efectelor. Totusi, Sonic Pi ne da posibilitatea sa manipulam sunetele si in timpul redarii. Vom face asta folosind o variabila care memoreaza o referinta la un sintetizator:

s = play 60, release: 5

Aici avem o variabila locala (in cadrul unui Run) ‘s’ care reprezinta sintetizatorul ce reda nota 60. Aceasta variabila locala nu poate fi accesata din alte blocuri, cum ar fi functii.

Din momentul in care il avem pe ‘s’, putem incepe sa il controlam folosind functia ‘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

Un amanunt important este ca nu pornim 4 sintetizatoare diferite, ci pornim doar unul apoi ii schimbam tonalitatea de 3 ori, in timp ce canta.

Putem transmite orice parametru standard catre ‘control’, deci poti controla valori ca ‘amp:’, ‘cutoff:’, sau ‘pan:’.

Parametri care nu pot fi controlati

Unii parametri nu pot fi controlati odata ce sintetizatorul a fost pornit. Asa sta treaba pentru toti parametrii anvelopei ADSR. Poti vedea ce poate fi controlat cautand in documentatia pentru fiecare parametru in sistemul de ajutor. Daca documentatia spune Nu poate fi schimbat odata setat, vei sti ca nu este posibil sa controlezi acest parametru dupa pornirea sintetizatorului.


7.2 - Controlul efectelor

Este posibil sa controlezi si efectele, dar acest lucru se face intr-un mod usor diferit:

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
In loc sa folosim o variabila, folosim parametrii delimitati de bare - ‘ ’ - din cadrul blocurilor do/end. Trebuie sa specificam intre bare un nume unic pentru efectul care se executa, putand apoi folosi acest nume in cadrul blocului do/end care-l contine. Acest comportament este identic cu cel al functiilor cu parametri.

Acum poti sa te joci controland niste sintetizatoare si efecte in timpul redarii!


7.3 - Optiuni de modificare progresiva sau alunecare (sliding)

Cand am discutat despre sintetizatoare si efecte ai observat probabil ca exista anumiti parametri al caror nume se termina cu ‘_slide’. Poate chiar ai incercat sa ii folosesti si nu ai remarcat niciun efect. Asta se intampla pentru ca nu sunt parametri normali, ci optiuni speciale care sunt active doar cand controlezi sintetizatoarele asa cum am explicat in sectiunea precedenta.

Sa analizam exemplul urmator:

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

Aici, poti auzi tonalitatea sintetizatorului schimbandu-se imediat dupa fiecare apel al functiei ‘control’. Totusi, am dori ca tonalitatea sa alunece (slide) intre schimbari. Deoarece controlam parametrul ‘note:’, pentru a adauga alunecarea, trebuie sa modificam parametrul ‘note_slide’ al sintetizatorului:

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

Acum vom auzi notele deformate intre apelurile ‘control’. Suna bine, nu? Poti grabi alunecarea folosind un timp mai scurt, cum ar fi ‘note_slide: 0.2’ sau sa o incetinesti folosind un timp mai mare.

Fiecare parametru care poate fi controlat are asociat si un parametru ‘_slide’ cu care te poti juca.

Alunecarea este persistenta

Odata ce ai setat un parametru ‘_slide’ pentru un sintetizator care canta, el va fi retinut de fiecare data cand faci sa alunece resprectivul parametru. Pentru a opri alunecarea trebuie sa setezi ‘_slide’ la 0 inainte de urmatorul apel ‘control’.

Modificarea progresiva a parametrilor efectelor

Si parametrii efectelor pot fi modificati progresiv:

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

Acum te poti juca cu alunecarea pentru tranzitii line…


8 - Structuri de date

O unealta foarte utila din trusa oricarui programator este structura de date.

Uneori ai putea dori sa reprezinti si sa folosesti mai mult decat o singura valoare. De exemplu, ti-ar fi util sa ai un sir de note pe care sa le redai una dupa alta. Limbajele de programare au structuri de date care permit acest lucru.

Exista multe structuri de date care mai de care mai exotice si mai interesante si altele noi continua sa apara. Totusi, pentru moment ne vom opri la una foarte simpla - lista.

Sa privim mai in detaliu. Vom discuta intai despre forma sa uzuala iar apoi vom vede cum poate fi folosita pentru a reprezenta game si acorduri.


8.1 - Listele

In aceasta sectiune vom discuta despre o structura de date foarte utila - lista. Am intalnit-o in treacat in sectiunea despre aleatorism cand am ales pentru redare o nota la intamplare dintr-o lista:

play choose([50, 55, 62])

In aceasta sectiune vom vedea cum putem folosi listele pentru a reprezenta acorduri si game. Mai intai sa ne amintim cum putem canta un acord. Retine ca in lipsa comenzii ‘sleep’, toate sunetele sunt redate in acelasi timp:

play 52
play 55
play 59

Sa vedem si alte moduri de a scrie aceste instructiuni.

Redarea unei liste

O varianta ar fi sa punem toate notele intr-o lista: [52, 55, 59]. Functia ‘play’ este suficient de desteapta sa stie cum sa redea o lista de note. Incearca:

play [52, 55, 59]

Oho, deja este mai placut de citit. Redarea unei liste de note nu te impiedica sa folosesti parametrii cu care esti obisnuit:

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

Desigur, poti sa folosesti si numele notelor in loc de numere MIDI:

play [:E3, :G3, :B3]

Cei dintre voi care au fost suficient de norocosi sa studieze teorie muzicala au recunoscut probabil acordul E Minor redat in octava a treia.

Accesul la o lista

O alta caracteristica utila a unei liste este posibilitatea de a extrage informatia din ea. Asta suna putin cam ciudat, dar nu este mai complicat decat ar fi daca cineva ti-ar cere sa deschizi o carte la pagina 23. In cazul listei ai intreba ce element este la indexul 23. Singurul lucru cu adevara ciudat este ca in programare indexul porneste de la 0, nu de la 1.

In cazul indexului unei liste nu numaram 1, 2, 3…, ci 0, 1, 2…

Sa analizam acest lucru mai in detaliu. Priveste lista aceasta:

[52, 55, 59]

Nu e nimic de speriat aici. Acum, spune care este al doilea element din lista. Desigur, este ‘55’. A fost usor. Sa vedem daca putem sa facem computerul sa ne raspunda:

puts [52, 55, 59][1]

OK, poate parea putin ciudat daca nu ai mai vazut asa ceva inainte. Dar ai incredere in mine, nu e chiar asa de greu. Exista trei parti in linia de mai sus: cuvantul ‘puts’, lista 52, 55, 59 si indexul nostru ‘[1]’. Mai intai spunem ‘puts’ care inseamna ca vrem ca Sonic Pi sa afiseze rezultatul in jurnal. Apoi, transmitem lista noastra si la final indexul care cere al doilea element. Indexul se trece incadrat de paranteze patrate, iar deoarece numaratoarea incepe de la ‘0’. indexul pentru cel de-al doilea element este ‘1’. Priveste:

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

Incearca sa executi puts [52, 55, 59][1] si vei vedea ca in jurnal apare ‘55’. Schimba indexul din ‘1’ in alta valoare, incearca liste mai lungi si gandeste-te cum ai putea utiliza o lista data viitoare cand improvizezi. De exemplu, ce structuri muzicale pot fi reprezentate ca serii de numere…


8.2 - Acorduri

Sonic Pi ofera suport pentru denumirile standard ale acordurilor. Incearca singur:

play chord(:E3, :minor)

Asa mai merge. Acum arata mai bine decat o lista bruta (si e mai usor de citit pentru altii). Ce alte acorduri mai suporta Sonic Pi? Ei bine, o multime. Incearca-le pe acestea:

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

Arpegii

Putem transforma usor acordurile in arpegii cu functia ‘play_pattern’:

play_pattern chord(:E3, :m7)

Ok, n-a sunat prea bine, a cantat prea incet. ‘play_pattern’ reda toate notele din lista cu pauze de 1 secunda intre ele. Putem folosi o alta functie - ‘play_pattern_timed’ pentru a specifica propriul nostru ritm si a grabi putin lucrurile:

play_pattern_timed chord(:E3, :m7), 0.25

Putem sa ii transmitem o lista de intervale de timp care va fi citita circular (dupa ultima valoare o reia de la inceput):

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

Aceasta linie este echivalenta cu:

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

Cum preferi sa scrii?


8.3 - Game

Sonic Pi ofera suport pentru o multime de game. Hai sa cantam gama C3 major.

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

Putem chiar cere mai multe octave:

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

Sau toate notele dintr-o gama pentatonica.

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

Note aleatoare

Acordurile si gamele ajuta la restrangerea domeniului din care se face o selectie aleatoare la valori utile. Incearca acest exemplu care alege note aleatoare din acordul E3 minor:

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

Incearca sa schimbi numele acordului si intervalul pentru cutoff.

Explorarea acordurilor si gamelor

Pentru a vedea ce game si acorduri sunt suportate de Sonic Pi apasa pe butonul Lang din marginea din stanga a acestui tutorial apoi alege fie chord fie scale din lista. In panoul principal deruleaza informatiile pana cand ajungi la o lunga lista de acorduri sau scale (in functie de ce ai ales).

Exploreaza si tine minte: nu exista greseli, doar oportunitati.


8.4 - Liste circulare

Un tip special de lista este lista circulara. Daca stii ceva programare, ai intalnit probabil buffere circulare sau siruri circulare. Aici vor fi numite doar ring (inel) - un nume scurt si simplu.

In sectiunile precedente referitoare la liste am vazut cum putem citi elemente din ele folosind mecanismul de indexare:

puts [52, 55, 59][1]

Ce se intampla daca doresti indexul ‘100’? Ei bine, este evident ca nu exista un element la indexul 100 deoarece lista are doar trei elemente in ea. Deci Sonic Pi va returna ‘nil’ adica nimic.

Sa ne imaginam insa ca ai un contor cum ar fi bataia curenta, care creste continnuu. Sa cream contorul si lista:

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

Putem acum folosi contorul pentru a citi o nota din lista:

puts notes[counter]

Super, am obtinut ‘52’. Acum, sa incrementam contorul si sa citim o alta nota:

counter = (inc counter)
puts notes[counter]

Am obtinut ‘55’ si daca mai incercam o data obtinem ‘59’. Totusi, daca incercam din nou vom ramane fara numere in lista si vom obtine ‘nil’. Dar daca am dori sa o luam pur si simplu de la inceputul listei din nou? Pentru asta exista listele circulare.

Crearea listelor circulare

Putem crea liste circulare in doua moduri. Fie folosim functia ‘ring’ cu elementele din lista ca parametri:

(ring 52, 55, 59)

Sau putem lua o lista normala si sa o transformam intr-una circulara trimitandu-i mesajul ‘.ring’:

[52, 55, 59].ring

Indexarea listelor circulare

Putem folosi o lista circulara la fel ca pe una normala cu diferenta ca putem folosi indecsi negativi sau mai mari decat lungimea listei si vom obtine intotdeauna un element din lista:

(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

Folosirea listelor circulare

Sa presupunem ca folosim o variabila care reprezinta numarul bataii curente. Putem folosi acest numar ca index in lista circulare pentru a aduce nota care urmeaza sa fie redata, sau timpul de release sau orice altceva ce am memorat in lista respectiva, indiferent de bataia la care s-a ajuns.

Gamele si acordurile sunt liste circulare

E util de stiut ca listele returnate de ‘scale’ si ‘chord’ sunt liste circulare si pot fi citite folosind orice valori pentru indecsi.

Constructori pentru listele circulare

Pe langa ‘ring’ exista si alte functii care pot construi o lista circulara pentru noi.

‘range’ iti cere sa specifici un punct de inceput, unul de sfarsit si dimensiunea pasului. ‘bools’ iti permite sa folosesti ‘0’ si ‘1’ pentru a reprezenta valori booleene. ‘knit’ iti permite sa tesi o secventa de valori care se repeta. ‘spread’ creeaza o lista circulara cu distributie euclidiana.

Poti cauta mai multe informatii in documentatia pentru functiile respective.


8.5 - Definirea listelor circulare folosind comenzi inlantuite

Pe langa utilizarea constructorilor gen ‘range’ sau ‘spread’, o alta metoda de a crea noi liste circulare se bazeaza pe folosirea unora deja existente.

Comenzi inlantuite

Pentru explorarea lor, luam ca exemplu o lista circulara simpla:

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

Daca dorim sa obtinem o lista circulara intoarsa pe dos, putem folosi comanda ‘.reverse’ pentru a obtine elementele in ordine inversa,:

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

Dar daca dorim primele trei valori din lista?

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

In fine, ce facem daca dorim sa amestecam valorile din lista?

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

Inlantuiri multiple

Deja avem o metoda foarte buna pentru a crea noi liste circulare. Totusi, lucrurile devin cu adevarat interesante cand inlantuim mai multe comenzi de acest fel.

Cum facem sa amestecam lista, sa eliminam primul element si apoi sa le oprim pe primele 3?

Vom face asta in etape:

(ring 10, 20, 30, 40, 50) - lista circulara initiala (ring 10, 20, 30, 40, 50).shuffle - o amestecam - (ring 40, 30, 10, 50, 20) (ring 10, 20, 30, 40, 50).shuffle.drop(1) - eliminam 1 - (ring 30, 10, 50, 20) (ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3) - oprim 3 - (ring 30, 10, 50)

Am creat un lant cu aceste metode doar punandu-le una dupa alta. Putem combina aceste metode in orice ordine dorim obtinand astfel o metoda foarte puternica de a genera noi liste circulare pe baza unora deja existente.

Invariabilitatea

Aceste liste circulare au o proprietate importanta. Ele sunt invariante, ceea ce inseamna ca nu pot fi schimbate. Metodele inlantuite descrise in aceasta sectiune nu schimba listele ci creeaza noi liste. Astfel, poti folosi acelease liste in diferite thread-uri si poti adauga comenzi inlantuite in cadrul unui thread stiind ca nu va exista un impact asupra altui thread care foloseste aceeasi lista inlantuita.

Metode disponibile pentru transformari inlantuite

Iata o lista a metodelor disponibile pentru aceste transformari inlantuite:

.reverse - intoarce o versiune a listei cu elementele in ordine inversa .sort - creeaza o versiune sortata a listei .shuffle - creeaza o versiune amestecata a listei .pick(3) - intoarce o lista cu rezultatul apelarii metodei .choose de 3 ori .pick(3) - intoarce o lista cu rezultatul apelarii metodei .choose de 3 ori .take(5) - returneaza o lista noua continand doar primele 5 elemente .drop(3) - returneaza o lista noua cu toate elementele in afara de primele 3 .butlast - returneaza o lista noua fara ultimul element .drop_last(3) - returneaza o lista noua fara ultimele 3 elemente .take_last(6)- returneaza o lista doar cu ultimele 6 elemente .stretch(2) - repeta fiecare element din lista de 2 ori .repeat(3) - repeta toata lista de 3 ori .mirror - adauga la lista o versiune inversata a acesteia .reflect - la fel ca mirror, dar valoarea din mijoc nu este duplicata .scale(2) - returneaza o lista cu toate elementele inmultite cu 2 (presupune ca lista contine doar numere)

Desigur, acele metode care accepta parametri, pot primi si alte numere decat cele din exemplu! Deci poti incerca de exemplu sa apelezi .’drop(5)’ in loc de ‘.drop(3)’ daca vrei sa elimini primele 5 elemente.


9 - Programare live

Una dintre cele mai interesante caracteristici ale Sonic Pi este ca iti prmite sa scrii si sa modifici codul live pentru a crea muzica, asa cum ai interpreta live la chitara. Un avantaj al acestei abordari este ca poti avea feedback pe masura ce compui (porneste o bucla simpla si fa reglajele pana cand suna perfect). Cel mai mare avantaj este insa ca poti sa iei Sonic Pi pe scena si sa improvizezi cu ajutorul lui.

In aceasta sectiune vom studia bazele transformarii codului static in interpretari dinamice.

Tineti-va bine…


9.1 - Programare live

Acum stim deja suficient pentru a incepe cu adevarat sa facem ceva interesant. In aceasta sectiune vom construi pe baza a ceea ce am invatat in sectiunile precedente si iti voi arata cum poti incepe sa compui muzica live si sa o transformi in interpretare pe scena. Pentru asta avem nevoie de 3 lucruri:

Priceperea de a scrie cod care produce sunete - PREZENTA! Priceperea de a scrie functii - PREZENTA! Priceperea de a folosi thread-uri (cu nume) - PREZENTA!

In regula, sa-i dam bataie! Sa programam live primele noastre sunete. Mai intai avem nevoie de o functie care contine codul pe care vrem sa-l executam. Sa incepem cu ceva simplu. Vrem de asemenea sa reluam in bucla apelurile catre aceasta functie intr-un thread:

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

Daca ti se pare putin complicat, te poti intoarce sa recitesti sectiunile despre functii si thread-uri. Nu este prea complicat daca deja ai studiat aceste lucruri.

Avem aici definitia unei functii care doar reda nota 50 si face pauza pe durata unei batai. Apoi definim un thread denumit ‘:looper’ care doar reia in bucla apelul ‘my_loop’.

Daca rulezi acest cod, vei auzi nota 50 repetata iar si iar…

Sa schimbam putin

Acum incepe partea distractiva. In timp ce codul inca ruleaza schimba 50 cu alt numar, sa zicem 55, apoi apasa pe butonul Run din nou. S-a schimbat! In direct!

Nu s-a adaugat un nou strat deoarece folosim un thread-uri cu denumire, ceea ce permite sa se execute un singur thread pentru fiecare nume. De asemenea, sunetul s-a schimbat pentru ca am redefinit functia. Am dat o noua definitie pentru ‘:my_loop’. Cand thread-ul ‘:looper’ a reluat bucla, a apelat noua definitie.

Incearca sa-l schimbi din nou, schimba nota, schimba timpul pentru pauza. Ce-ar fi sa adaugi o instructiune ‘use_synth’? De exemplu, schimba cu:

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

Acum suna destul de interesant, dar putem sa-l facem si mai colorat. In loc sa redam aceeasi nota iar si iar, incerca sa redai un acord:

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

Ce-ar fi sa redam aleator notele dintr-un acord:

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

Sau sa alegem o valoare aleatoare pentru cutoff:

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

La final, sa adaugam niste tobe:

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

Acum lucrurile devin incitante!

Totusi, inainte sa incepi sa programezi live folosind functii si thread-uri, opreste-te putin si citeste sectiunea urmatoare despre ‘live_loop’ care va schimba pentru totdeauna modul in care programezi cu Sonic Pi…


9.2 - Bucle live

Ok, deci aceasta sectiune a tutorialului este adevarata nestemata. Daca ai citi o singura sectiune, aceasta ar trebui sa fie. Daca ai cititi sectiunea precedenta, despre Bazele programarii live, ‘live_loop’ reprezinta o cale simpla de a face exact acelasi lucru, fara insa a scrie le fel de mult.

Daca nu ai citit sectiunea precedenta, ‘live_loop’ este cel mai bun mode de a improviza folosind Sonic Pi.

Sa ne jucam acum. Scrie codul acesta intr-un buffer nou:

live_loop :foo do
  play 60
  sleep 1
end

Acum apasa butonul Run. Vei auzi un beep obisnuit la fiecare bataie. Nimic interesant deocamdata. Totusi, nu apasa pe Stop inca. Schimba ‘60’ cu ‘65’ si apasa pe Run din nou.

Hei, s-a schimbat automat fara sa piarda nicio bataie. Aceasta este programarea live.

Hai sa schimbam sa fie mai spre bas. Schimba codul in timp ce se executa:

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

Apoi apasa Run.

Sa facem valoarea pentru cutoff sa se schimbe:

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

Apasa Run din nou.

Adauga niste tobe:

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

Schimba nota din ‘e1’ in ‘c1’:

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

Acum nu mai tine cont de sfaturile mele si joaca-te cum vrei! Distreaza-te!


9.3 - Bucle live multiple

Sa privim bucla live de mai jos:

live_loop :foo do
  play 50
  sleep 1
end

Te-ai putea intreba de ce trebuie sa se numeasca ‘:foo’. Acest nume este important deoarece ne spune ca aceasta bucla live este diferita de toate celelalte.

Nu pot exista doua bucle live cu acelasi nume care ruleaza in acelasi timp.

Asta inseamna ca daca vrem sa avem mai multe bucle live care ruleaza in acelasi timp, trebuie sa le dam nume diferite:

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

Acum poti modifica fiecare bucla live in mod independent si totul va continua sa functioneze.

Sincronizarea buclelor live

Un lucru pe care poate l-ai remarcat este ca buclele live folosesc automat mecanismul de marcaje pentru thread-uri pe care l-am vazut anterior. De fiecare data cand bucla live se reia, genereaza un nou eveniment ‘cue’ cu numele buclei. Putem deci sa ne sincronizam (‘sync’) cu aceste marcaje pentru a ne asigura ca buclele noastre sunt in faza fara sa oprim ceva.

Sa analizam acest cod sincronizat gresit:

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

Sa vedem cum putem repara timing-ul si sa facem sincronizarea fara sa il oprim. Mai intai sa corectam bucla ‘:foo’ astfel incat pentru pauza sa avem o valoare care intra de un numar intreg de ori in 1 - ceva gen ‘0.5’ ar merge:

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

Nu am terminat, totusi. Vei observa ca bataile nu se aliniaza corect. Asta se intampla deoarece buclele sunt defazate. Sa corectam aceasta problema sincronizandu-le una cu alta:

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

Totul este acum perfect sincronizat - fara sa fim nevoiti sa ne oprim.

Acum, mergi mai departe si programeaza live cu bucle live!


- Tactul

Un lucru pe care il vei face adesea cand vei programa live va fi sa parcurgi in bucla liste circulare. Vei pune in aceste liste note pentru melodii, pauze pentru ritm, progresii ale acordurilor, variatii de timbru, etc.

Tactul pentru liste circulare

Sonic Pi ofera o unealta foarte la indemana pentru folosirea listelor circulare in bucle live. Este sistemul de tact. In sectiunea despre listele circulare am discutat despre contorul care creste constant, la fel ca numarul bataii curente. Tactul implementeaza aceasta idee. El iti ofera posibilitatea de a parcurge listele circulare in ritm. Sa privim un exemplu:

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

Acesta este echivalent cu:

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

Aici am ales gama pentatonica E3 minor si redam fiecare element. Acest lucru este realizat adaugand ‘.tick’ la sfarsitul declaratiei gamei. Acest tact este local pentru bucla live, deci fiecare bucla poate avea tactul sau independent:

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

Tactul (tick)

Poti apela ‘tick’ la fel ca o functie standard si sa folosesti valoare ca index:

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

Totusi, e mai dragut sa apelezi ‘.tick’ la sfarsit. Functia ‘tick’ poate fi folosita cand vrei sa faci chestii exotice cu valoarea pentru tick si pentru cand vrei sa folosesti aceasta valoare pentru altceva decat pentru indexul dintr-o lista circulara.

Look (priveste)

Partea magica legata de tick este ca nu reda doar un index nou (sau valoarea din lista de la indexul respectiv) ci are grija ca data viitoare cand apelezi functia sa intoarca valoarea urmatoare. Citeste exemplele din documentatia pentru ‘tick’ pentru mai multe moduri de a-l folosi. Totusi, pentru moment este important sa remarcam ca uneori ai putea dori sa vezi care este valoarea curenta fara sa o incrementezi. Acest lucru se poate face folosind functia ‘look’. Poti apela ‘look’ ca pe o functie standard sau adaugand ‘.look’ la sfarsitul listei circulare.

Nume pentru tact

Uneori vei avea nevoie de mai mult de un tact intr-o bucla live. Acest lucru se poate realiza dandu-i un nume tactului:

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

Aici folosim doua tacturi, unul pentru nota care va fi redata si un altul pentru durata pauzei. Cum ambele sunt in aceeasi bucla live, pentru a le delimita trebuie sa le dam nume unice. Este la fel cu numele pentru buclele live - scriem un nume cu ‘:’ la inceput. In exemplul de mai sus am denumit un tact ‘:foo’ iar pe celalalt ‘:bar’. Daca vrem sa vedem valorile acestora trebuie sa transmitem numele tactului catre functia ‘look’.

Nu complica lucrurile

Multe dintre avantajele sistemului de tacturi nu sunt evidente de la inceput. Nu incerca sa inveti totul din aceasta sectiune. Concentreaza-te pe tactul pentru o singura lista circulara. Asta iti va permite sa beneficiezi de cea mai mare parte din placerea de a folosi un tact pentru parcurgerea listelor circulare in buclele live.

Studiaza documentatia pentru ‘tick’ unde vei gasi multe exemple folositoare. Spor la ticait!


10 - Time State

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

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

Meet get and set


10.1 - Set and Get

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

Set

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

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

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

set :intensity, 3000

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

set :intensity, 1000
set :intensity, 3000

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

Get

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

print get[:intensity] #=> prints 3000

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

Fire de executie

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

rrand

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

{run: 0, time: 0.0}
 └─ 125.72265625
{run: 0, time: 0.5}
 └─ 125.72265625
{run: 0, time: 1.0}
 └─ 76.26220703125
{run: 0, time: 1.5}
 └─ 76.26220703125
{run: 0, time: 2.0}
 └─ 114.93408203125
{run: 0, time: 2.5}
 └─ 114.93408203125
{run: 0, time: 3.0}
 └─ 75.6048583984375
{run: 0, time: 3.5}
 └─ 75.6048583984375

Try running it a few times - see, it’s the same every time. This is what we call deterministic behaviour and it’s really very important when we want to share our music as code and know that the person playing the code is hearing exactly what we wanted them to hear (just like playing an MP3 or internet stream sounds the same for all listeners).

A Simple Deterministic State System

rand

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

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

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

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

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


10.2 - Sync

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

Waiting for Events

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

sample :ambi_lunar_land

foo

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

Passing values into the Future

foo

sample :ambi_lunar_land

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


10.3 - Pattern Matching

foo

Match any path segment

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

sync "/*/*/*"

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

foo foo cue "/eggs/beans/toast" cue "/moog/synths/rule"

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

foo foo cue "/eggs"

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

Matching partial segments

foo

foo foo foo

However, it wouldn’t match the following:

foo foo foo

foo

Matching Nested Path Segments

foo

foo foo foo foo

Matching Single Letters

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

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

Matching Multiple Words

foo

foo foo foo

Matching Multiple Letters

foo

foo foo foo

foo

foo foo foo foo foo

Combining Matchers

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

sample :loop_amen

OSC Pattern Matching

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


11 - MIDI

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

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

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

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


11.1 - MIDI In

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

Connecting a MIDI Controller

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

Receiving MIDI Events

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

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

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

MIDI Time State

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

Controlul efectelor

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

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

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

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

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

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

Removing Latency

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

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

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

Inceputul

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

Now You are in Control

choose (alege)


11.2 - MIDI Out

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

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

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

Connecting to a MIDI Device

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

Sending MIDI events

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

midi_note_on :e3, 50

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

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

midi_note_off :e3

Selecting a MIDI device

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

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

midi_note_on :e3, port: "moog_minitaur"

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

midi_note_on :e3, channel: 3

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

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

MIDI Studio

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

reverb,

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


12 - OSC

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

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


12.1 - Receiving OSC

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

A Basic OSC Listener

Let’s build a basic OSC listener:

foo

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

Sending OSC to Sonic Pi

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

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

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

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

Receiving from External Machines

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

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


12.2 - Sending OSC

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

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

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

Sending OSC to other programs

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

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

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

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

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

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


13 - Multichannel Audio

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


13.1 - Sound In

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

synth :sound_in

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

Durata

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

synth :sound_in, sustain: 8

Adaugarea de efecte

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

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

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

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

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

Inlantuiri multiple

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

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

Potential Issues

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


13.2 - Programare live

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

A Named Audio Input

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

foo

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

Working with FX

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

foo

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

reverb,

foo

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

foo

foo

Stopping live audio

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

foo

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

foo

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

Stereo input

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

foo

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


13.3 - Sound Out

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

Output contexts

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

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

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

Sound Out FX

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

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

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

Mono and Stereo out

choose (alege)

Direct Out

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

sample :loop_amen

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


12 - Concluzii

Aici se incheie tutorialul introductiv pentru Sonic Pi. Sper ca ai invatat ceva pe parcursul lui. Nu fi ingrijorat daca este ceva ce nu ai inteles - foloseste programul, distreaza-te si sigur vei ajunge sa il stapanesti in timp. Te poti intoarce oricand ai o nelamurire legata de ceva ce este descris intr-una dintre aceste sectiuni.

Daca ai nelamuriri legate de ceva ce nu este descris aici, te rog sa intri pe Forumul Sonic Pi si intreaba acolo. Sigur vei da peste cineva dispus sa-ti intinda o mana de ajutor.

Te invit de asemenea sa zabovesti asupra restului documentatiei din sistemul de ajutor. Exista mai multe functionalitati care nu au fost descrise in acest tutorial si care asteapta sa le descoperi.

Deci joaca-te, distreaza-te, impartaseste si altora creatiile tale, canta impreuna cu prietenii tai, arata imaginea de pe ecran si, mai ales, tine minte:

Nu exista erori, doar oportunitati

Sam Aaron


- Articole din MagPi

Anexa A regrupeaza toate articolele despre Sonic Pi scrise pentru revista MagPi.

Concentreaza-te pe subiect

Aceste articole nu sunt gandite sa fie citite intr-o ordine stricta si contin informatii care se refera la subiecte inrudite extrase chiar din acest tutorial. Ele nu-si propun sa te invete totul despre Sonic Pi, ci se concentreaza fiecare pe un domeniu specific pe care incearca sa-l prezinte intr-un mod amuzant si accesibil.

Citeste MagPi

Le poti vedea intr-o forma spectaculoasa pregatite pentru tipar in PDF-uri care pot fi descarcate gratuit de aici: https://www.raspberrypi.org/magpi/

Sugereaza un subiect

Daca nu vezi nimic interesant in aceste articole, poti sugera tu un subiect. Cel mai simplu este sa trasnmiti sugestia ta prin twitter la @Sonic_Pi. Nu se stie niciodata, poate sugestia ta va fi la baza urmatorului articol!


- Cele mai bune 5 trucuri

1. Nu exista greseli

Cea mai importanta lectie pe care trebuie sa o inveti despre Sonic Pi este ca nu exista greseli. Cea mai buna metoda de a invata este sa incerci iar si iar. Incerca diferite variante, nu te concentra pe cum arata codul si experimenteaza cu cat mai multe sintetizatoare, note, efecte si parametri pentru acestea. Vei descoperi o gramada de combinatii care te vor face sa razi pentru ca suna caraghios dar si adevarate nestemate care suna incredibil. Arunca la cos ce nu-ti place si pastreaza ce e reusit. Cu cat indraznesti sa faci mai multe ‘greseli’ cu atat mai repede vei invata si-ti vei descoperi stilul personal.

2 Foloseste efectele

Stapanesti deja bazele Sonic Pi pentru a crea sunete cu ‘sample’ si ‘play’? Ce urmeaza? Stiai ca Sonic Pi ofera suport pentru mai mult de 27 de efecte de studio pentru a schimba felul in care suna programul tau? Efectele sunt ca niste filtre de imagine fanteziste, doar ca in loc sa incetosezi imaginea sau sa o faci alb/negru poti adauga sunetului reverberatii, distorsiuni sau ecou. E ca si cum ai conecta iesirea de la chitara la pedala de efecte preferata si apoi la amplificator. Din fericire, Sonic Pi face aplicarea efectelor si mai simpla, fara cabluri! Tot ce trebuie sa faci este sa decizi la ce bucata de cod vrei sa aplici efectul si sa o incadrezi cu codul speficic pentru acesta. Sa vedem un exemplu. Sa spunem ca ai urmatorul cod:

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

Daca vrei sa adaugi un efect la esantionul :loop_garzul, trebuie doar sa-l introduci in interiorul unui bloc ‘with_fx’ ca mai jos:

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

Acum, daca vrei sa adaugi un efect la toba bas, introdu-o si pe aceasta intr-un ‘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

Retine, poti impacheta orice cod intr-un bloc ‘with_fx’ si toate sunetele create vor fi transformate de acel efect.

3. Modifica parametrii sintetizatoarelor

Pentru a-ti descoperi stilul personal vei dori desigur sa afli cum sa modifici si sa controlezi sintetizatoarele si efectele. De exemplu, ai putea dori sa modifici durata unei note, sa adaugi mai mult reverb sau sa schimbi duratele dintre ecouri. Din fericire, Sonic Pi iti ofera un nivel de control incredibil pentru a realiza exact aceste lucruri folosind parametrii optionali (opts). Sa aruncam o privire rapida. Copiaza acest cod intr-un buffer si apasa Run:

sample :guit_em9

O, un minunat sunet de chitara. Acum, sa ne jucam cu el. Ce-ar fi sa-i schimbam viteza de redare?

sample :guit_em9, rate: 0.5

Hei, ce e chestia aia de la sfarsit - ‘rate: 0.5’? Acesta este un parametru optional. Toate sintetizatoarele si efectele suporta astfel de parametri si exista o multime din care poti alege. Iata cum ii poti folosi pentru un efect:

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

Acum incearca sa modifici in 1 valoarea pentru feedback, ca sa auzi niste sunete traznite! Citeste documentatia pentru mai multe detalii despre multimea de parametri disponibili.

5. Programeaza live

Cea mai buna metoda de a exersa este sa programezi live. Asta iti permite sa incepi de la o bucata oarecare de cod si sa o modifici si sa o reglezi in timp ce ruleaza. De exemple, daca nu stii ce face parametrul cutoff pentru un esantion, joaca-te cu el. Sa incercam! Copiaza acest cod intrun buffer din Sonic Pi:

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

Acum apasa pe Run si vei auzi o bataie de toba infundata. Acum, schimba valoarea pentru ‘cutoff:’ la ‘80’ si apasa din nou pe Run. Auzi diferenta? Incearca 90, 100, 110

Odata ce ai prins miscarea cu ‘live_loop’ nu vei mai renunta la el. De cate ori improvizez live ma bazez pe ‘live_loop’ la fel cum un tobosar se bazeaza pe betele lui. Pentru mai multe informatii despre programarea live vezi sectiunea 9 din tutorial.

5. Lasa-te purtat de curenti la intamplare

Un alt lucru pe care imi place sa-l fac este sa trisez putin lasand Sonic Pi sa compuna pentru mine. Un mod foarte interesant de a face asta este sa folosesti randomizarea. Poate suna complicat, dar chiar nu este. Sa aruncam o privire. Copiaza asta intr-un buffer:

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

Acum, cand vei reda asta, vei auzi un sir constant de note din gama :e2 :minor_pentatonicredate de sintetizatorul :dsaw. “Stai, stai! Asta nu este o melodie”, parca te aud strigand! Ei bine, asta este prima parte a unui truc magic. De fiecare data cand reluam bucla ‘live_loop’ putem cere Sonic Pi sa readuca sirul aleator la un punct prestabilit. E ca si cum te-ai intoarce in timp folosind TARDIS - masina timpului din Doctor Who - la un anumit punct in timp si spatiu. Sa incercam: adauga linia use_random_seed 1 la 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

Acum, de fiecare data cand se reia bucla ‘live_loop’, sirul aleator este resetat. Asta inseamna ca va alege aceleasi 16 note de fiecare data. A fost rapid! Am obtinut instantaneu o melodie. Acum urmeaza partea si mai incitanta. Schimba valoarea pentru seed din ‘1’ in alt numar. Sa zicem ‘4923’. Uau! Alta melodie! Deci schimband un singur numar (cel care initializeaza secventa aleatoare) poti explora atatea combinatii melodice cate iti poti imagina! Aceasta este magia programarii.


- Programare live

Fasciculele laser taiau norii grosi de fum in timp ce subwooferul pompa injecta un bas puternic in multime. Atmosfera era incalzita de un mix de sintetizatoare si de dansatori. Totusi ceva nu era chiar in regula in club. Proiectat in culori stralucitoare deasupra cabinei DJ-ului era un text care se schimba, clipea si dansa. Nu erau niste efecte vizuale traznite, ci proiectia ecranului Sonic Pi ruland pe un Raspberry Pi. Ocupantul cabinei DJ-ului nu invartea discuri ci scria, modifica si evalua codul. In direct. Asta e Programarea Live.

Sam Aaron Programand live

Poate parea o poveste trasa de par dintr-un club din viitor, dar crearea muzicii prin cod ca mai sus este pe un trend crescator si este adesea descrisa ca Programare Live (http://toplap.org). Una dintre directiile spre care se indreapta in prezent acest mode de a face muzica este Algorave (http://algorave.com) - spectacole in care artisti ca mine programeaza muzica pe care lumea danseaza. Totusi, nu trebuie sa fii neaparat intr-un club ca sa programezi live - cu Sonic Pi poti sa faci asta oriunde poti sa iei cu tine un Raspberry Pi si o pereche de casti sau niste difuzoare. Cand vei fi ajuns la sfarsitul acestui articol, vei fi in stare sa programezi propriile ritmuri si sa le modifici pe viu. Ce vei face dupa aceea depinde doar de imaginatia ta.

Bucla live

Cheia programarii live este sa stapanesti ‘live_loop’. Sa aruncam o privire:

live_loop :beats do
  sample :bd_haus
  sleep 0.5
end

Exista 4 elemente de baza intr-un ‘live_loop’. Primul este numele. Bucla noastra de mai sus se numeste ‘:beats’. Poti sa denumesti bucla cum vrei. Lasa-te purtat de imaginatie, fii creativ. Eu folosesc adesea nume care transmit ceva audientei despre muzica pe care o produc. Al doilea element este cuvantul cheie ‘do’ care marcheaza inceputul buclei. Al treilea este cuvantul cheie ‘end’ care marcheaza sfarsitul buclei si, in fine, exista continutul care arata ceea ce se va repeta in bucla respectiva - partea dintre ‘do’ so ‘end’. In acest caz am redat in mod repetat un esantion de toba bas si am asteptat jumatate de bataie. Asta produce un bas regulat. Copiaza textul intr-un buffer Sonic Pi si apasa Run. Boom, Boom, Boom!

Redefinirea din mers

Ok, deci ce e asa special la o bucla ‘live_loop’? Pana acum pare sa fie doar o bucla obisnuita cu un nume mai pompos. Ei bine, frumusetea buclelor de tip ‘live_loop’ este ca pot fi redefinite din mers. Asta inseamna ca poti schimba ce fac in timp ce ele se executa. Acesta este secretul programarii live cu Sonic Pi. Sa ne jucam putin:

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

Acum apasa butonul Run sau combinatia ‘M-r’. Poti asculat niste sunete corale minunate. In timp ce canta, schimba viteza de la ‘0.4’ la ‘0.38’. Apasa din nou Run. Uau! Ai auzit cum s-a schimbat tonalitatea corului? Schimba la loc cu ‘0.4’ ca sa fie ca la inceput. Acum, coboara la ‘0.2’, apoi la ‘0.19’ si revino la ‘0.4’. Observi ca schimbarea din mers a unui singur parametru poate sa iti ofere un control real asupra muzicii. Acum joca-te cu viteza de redare - alege valorile pe care le doresti. Incearca numere negative, numere foarte mici sau numere mari. Savureaza rezultatul!

Pauzele sunt importante

Una dintre cele mai importante lectii despre ‘live_loop’ este ca are nevoie de pauze. Sa luam urmatorul ‘live_loop’:

live_loop :infinite_impossibilities do
  sample :ambi_choir
end

Daca incerci sa rulezi acest cod, vei observa imediat ca Sonic Pi se plange ca ‘live_loop’ nu a facut nicio pazua (sleep). Acesta este sistemul de siguranta care s-a activat! Sa ne gandim putin ce cere codul respectiv computerului. Asa e, ii cere computerului sa redea la nesfarsit esantioane corale de lungime zero. Fara sistemul de siguranta bietul computer ar incerca sa redea o infinitate de esantioane si ar lua-o razna. Deci, tine minte, orice ‘live_loop’ trebuie sa contina un ‘sleep’.

Combinarea sunetelor

Muzica inseamna multe lucruri care se intampla in acelasi timp. Tobele in acelasi timp cu basul, in acelasi timp cu vocea, in acelasi timp cu chitarele… In lumea computerelor acestea se numesc procese concurente iar Sonic Pi ne ofera o cale uimitor de simpla pentru a face mai multe lucruri in acelasi timp. Pur si simplu folosim mai multe ‘live_loop’ in acelasi timp!

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

Aici avem doua bucle ‘live_loop’, una rapida care genereaza batai de taler si alta mai lenta cu un sunet dement de bas.

Interesant cu buclele ‘live_loop’ multiple este ca fiecare isi gestioneaza separat timpul. Asta insemana ca este foarte usoe sa creezi structuri poliritmice interesante si chiar sa te joci cu fazele in stilul Steve Reich. Asculta asta:

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

Sa punem totul cap la cap

In fiecare dintre aceste tutoriale incheiem cu un exemplu final sub forma unei noi piese muzicale care se bazeaza pe ideile prezentate. Citeste codul acesta si incearca sa-ti imaginezi ce face. Apoi, copiaza-l intr-un buffer nou in Sonic Pi si apasa Run ca sa vezi cum suna de fapt. Schimba apoi unul dintre numere sau transforma o parte din cod in comentariu. Vezi daca poti folosi rezultatul ca un punct de plecare pentru o noua piesa si, in primul rand, simte muzica! Ne vedem data viitoare…

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

- Beat-uri programate

Una dintre cele mai incitante si mai revolutionare inventii in muzica moderna a fost sampler-ul. Acesta este o cutie care iti permite sa inregistrezi orice sunet pe car apoi il poti manipula si reda in diferite moduri interesante. De exemplu, poti sa iei o inregistrare veche, sa gasesti un solo de toba (break), sa o memorezi in sampler si apoi sa o redai in bucla la viteza injumatatita ca sa ai baza pentru cel mai nou beat al tau. Asa s-a nascut muzica hip-hop iar astazi este aproape imposibil sa gasesti muzica electronica in care nu exista macar un tip de esantion (sample). Folosirea esantioanelor este o metoda foarte buna de a introduce elemente noi si interesante in interpretarea bazata pe programare live.

De unde putem lua un sampler? Ai deja unul - este Raspberry Pi! Aplicatia Sonic Pi pentru programare live care vine preinstalata are inclus in nucleu un sampler foarte puternic. Sa ne jucam cu el!

Amen Break

Unul dintre solourile de toba cele mai usor de recunoscut se numeste Amen Break. A fost interpretat prima data in 1969 in piesa “Amen Brother” de Winstons ca parte a soloului de toba. Dar abia cand a fost descoperit de muzicienii de la inceputurile hip-hop-ului in anii 80 si a fost fost folosit in samplere a inceput sa fie folosit din greu in multe alte stiluri, cum ar fi drum & bass, breakbeat, hardcore techno sau breakcore.

Sunt sigur ca te bucuri sa afli ca este inclus si in Sonic Pi. Goleste un buffer si pune acolo urmatorul cod:

sample :loop_amen

Apasa Run si boom! Asculti unul dintre solourile de toba cu cea mai mare influenta din istoria muzicii dance. Totusi, acest esantion nu a devenit faimos pentru redarea normala, el a fost construit pentru redarea in bucla.

Intinderea unui beat

Sa redam in bucla Amen Break folosind vechea noastra cunostinta ‘live_loop’ prezentata in acest tutorial:

live_loop :amen_break do
  sample :loop_amen
  sleep 2
end

Ok, acum se repeta, dar exista o pauza deranjanta de fiecare data. Asta se intampla deoarece am cerut o pauza de ‘2’ batai iar la ritmul implicit de 60 BPM esantionul ‘:loop_amen’ dureaza ‘1.753’ batai. Avem deci liniste timp de ‘2 - 1.753 = 0.247’ batai. Desi dureaza putin, este sesizabila.

Pentru a rezolva aceasta problema putem folosi parametrul ‘beat_strecth: pentru a cere Sonic Pi sa intinda (sau sa comprime) esantionul astfel incat sa aiba numarul specificat de batai.

Functiile ‘sample’ si ‘synth’ din Sonic Pi iti ofera un control puternic prin intermediul parametrilor optionali ca amp:, cutoff: si release:. Totusi, numele de parametru optional este destul de lung si il putem prescurta folosind opt pentru simplitate.

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

Acum dansam! S-ar putea totusi sa dorim sa marim sau sa scadem viteza pentru a se potrivi cu atmosfera.

Sa ne jucam cu timpul

Ce facem daca vrem sa schimbam stilul in hip hop clasic sau breakcore? O metoda simpla este sa ne jucam cu timpul - cu alte cuvinte sa umblam la tempo. E foarte usor sa faci asta in Sonic Pi - doar adaugi o comanda ‘use_bpm’ in bucla live:

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

Cat timp asculti ritmul asta lent, ai timp sa remarci ca pauza este tot de 2, dar acum avem 30 BPM si totusi totul este sincronizat. Parametrul ‘beat_stretch’ tine cont de noul ritm pentru a se asigura ca totul functioneaza.

Acum urmeaza partea cu adevarat interesanta. In timp ce bucla este inca live, schimba ‘30’ din linia ‘use_bpm 30’ in ‘50’. Uau, totul a devenit mai rapdi dar a ramas sincronizat. Incearca ceva mai rapid - urca la 80, la 120, fa o nebunie si pune 200!

Filtrarea

Acum putem reda esantioane in bucle live, sa vedem care sunt cei mai interesanti parametri pentru ‘sample’. Primul este ‘cutoff:’ care controleaza filtrul de cutoff al sampler-ului (care taie frecventele mai inalte decat limita stabilita). Implicit este dezactiva, dar il poti porni cu usurinta:

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

Modifica parametrul ‘cutoff’. De exemplu, mareste-l la 100, apasa Run si asteapta ca bucla sa se reia ca sa auzi care este efectul modificarii. Vei observa ca valori mici, ca 50, suna infundat si mai spre bas, iar valorile gen 100 sau 120 au un sunet mai complet si mai clar. Asta deoarece parametrul ‘cutoff:’ va duce la tairea partilor de frecventa inalta din sunet, asa cum masina de tuns taie varful firelor de iarba. Parametrul ‘cutoff:’ este asemanator cu lungimea la care este setata masina de tuns - spune cat sa ramana din firele de iarba.

Slicing

O alta unealta cu care ne putem juca este efectul slicer. Acest taie (slice) sunetul in bucatele. Incadreaza linia ‘sample’ cu codul pentru efect ca mai jos:

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

Observi ca sunetul variaza in sus si in jos ceva mai mult. (Poti asculta sunetul original, fara efect, schimband valoarea pentru ‘mix:’ cu ‘0’). Acum, incearca sa te joci cu parametrul ‘phase:’. Acesta reprezinta frecventa (in batai) cu care se aplica efectul slicing. O valoare mai mica, gen ‘0.125’, va taia sunetul mai rapid, iar valori mai mari, gen ‘0.5’ vor face taierea mai lenta. Observi ca injumatatind sau dubland de mai multe ori valoarea pentru ‘phase:’ sunetul va suna mereu bine. La final, schimba valoarea ‘wave:’ in 0, 1 sau 2 pentru a auzi cum schimba sunetul. Acestea sunt diferite forme pentru semnal. 0 inseamna forma de fierastrau (crestere brusca, scadere lenta), 1 inseamna patrat (crestere brusca, scadere brusca), iar 2 inseamna triunghi (crester lenta, scadere lenta).

Sa punem totul cap la cap

Acum sa facem o calatorie in timp si sa ne intoarcem in Bristol la inceputurile curentului drum and bass cu exemplul de luna aceasta. Nu-ti bate capul cu ce inseamna asta, doar introdu codul, apasa Run si incepe sa-l modifici live jucandu-te cu valorile pentru parametri ca sa vezi ce iese. Te rog sa arati si altora ce ai reusit sa creezi. Pe data viitoare…

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

- Riff-uri (fraze melodice) pentru sintetizatoare

Fie ca este vorba de sunetul obsedant al unui oscilator sau de punch-ul unei unde in dinti de fierastrau care razbate din mix, sintetizatorul principal are un rol esential in orice piesa electronica. Luna trecuta am vorbit in acest tutorial despre cum putem coda un beat. Acum vom vorbi despre cum putem coda cele trei componente de baza ale riff-ului pentru sintetizator: timbrul, melodia si ritmul.

Asadar, porneste Raspberry Pi, deschide Sonic Pi v2.6+ si sa facem galagie!

Controlul timbrului

O parte esentiala a unui riff pentru sintetizator este modificarea timbrului sunetelor. Putem controla timbrul in Sonic Pi in doua feluri - alegand sintetizatoare diferite pentru o schimbare masiva sau modificand diferiti parametri ai sintetizatorului pentru schimbari mai subtile. Putem folosi si efectele, dar acesta este subiectul altui tutorial…

Sa cream o bucla live simple in care schimbam in continuu sintetizatorul curent:

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

Arunca o privire asupra codului. Pur si simplu parcurgem ritmic o lista circulara de nume de sintetizatoare (fiecare dintre acestea va fi selectat pe rand, reluand lista de la inceput cand se termina). Acest nume de sintetizator este transmis functiei ‘use_synth’ care schimba sintetizatorul curent din bucla live. De asemenea, redam nota ‘:e2’ (E din a doua octava), cu un timp de release de 0.5 batai (jumatate de secunda la viteza implicita de 60 BPM) si cu un ‘cutoff:’ setat la 100.

Poti auzi cum diferite sintetizatoare au sunete foarte diferite chiar daca redau toate aceeasi nota. Acum experimenteaza si distreaza-te. Schimba timpul de release cu valori mai mici sau mai mari. Schimba parametrii ‘attack:’ si ‘release:’ pentru a vedea cum timpi diferiti de fade in/fade out pot avea un impact foarte mare asupra sunetului. Apoi schimba valoarea pentru ‘cutoff:’ si vei vede ca are o influenta foarte importanta asupra timbrului (iti recomand valori intre 60 si 130). Vei vedea cat de multe sunete diferite poti crea schimband doar cateva valori. Odata ce stapanesti aceste schimbari mergi la panoul Sintetizatoare (Synths) din sistemul de ajutor pentru o lista completa a sintetizatoarelor si a tuturor parametrilor pe care ii suporta fiecare dintre acestea pentru a vedea ce puteri magice poti controla cu degetele tale de programator.

Timbrul

Timbru este un nume pompos pentru un cuvant care descrie sunetul unui sunet. Daca redai aceeasi nota cu instrumente diferite, cum ar fi o vioara, o chitara sau un pian, inaltimea sunetului va fi aceeasi, dar calitatea sunetului va fi diferita. Aceasta calitate a sunetului - lucrul care iti permite sa sesizezi diferenta dintre un pian si o chitara este timbrul.

Compozitia melodica

Un alt element important pentru sintetizatorul principal este alegerea notelor pe care vrem sa le redea. Daca ai deja o idee, poti sa creezi pur si simplu o lista circulare cu notele si sa o parcurgi pas cu pas:

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

Aici am definit melodia printr-o lista care contine atat note, cum ar fi ‘:e3’, cat si pauze, cum ar fi ‘:r’. Apoi folosim ‘.tick’ pentru a parcurge toate notele ciclic, obtinand un riff care se repeta.

Generarea automata a melodiei

Nu e mereu simplu sa produci un riff interesant pornind de la zero. E mai usor uneori sa ceri Sonic Pi o selectie de riff-uri aleatoare dintre care sa-l alegi pe cel care iti place cel mai mult. Pentru asta vom combina 3 lucruri: liste circulare, randomizarea si initializarea unui sir aleator folosind un seed. Sa vedem un exemplu:

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

Aici se petrec mai multe lucruri. Sa le luam pe rand. In primul rand am ales pentru initializarea sirului valoarea 3. Ce inseamna asta? Cand alegem valoarea de initializare (seed = samanta) putem prezice care va fi urmatoarea valoare aleatoare dintr-un sir - va fi la fel ca si ultima data cand am folosit numarul 3 pentru seed! Alt lucru de retinut este ca amestecarea notelor dintr-o lista functioneaza la fel. In exemplul de mai sus cerem de fapt ‘a treia varianta de amestecare’ in lista predefinita de variante - care va fi de asemenea la fel de fiecare data cand vom alege acelasi seed. La final, parcurgem ciclic notele amestecate pentru a canta riff-ul.

Acum incepe partea distractiva. Daca schimbam valoare pentru seed cu alta valoare, sa zicem 3000, obtinem o varianta complet diferita de amestecare a notelor. Deci este extrem de usor sa incercam noi melodii. Pur si simplu alegem lista de note pe care vrem sa le amestecam (gamele sunt un bun punct de pornire) si apoi alegem seed-ul pentre amestecare. Daca nu ne place melodia, doar schimbam unul dintre aceste lucruri si incercam din nou. Repetam pana ne place ce auzim!

Pseudo-randomizarea

Randomizarea in Sonic Pi nu da rezultate cu adevarat aleatoare, ci pseudo-aleatoare. Imagineaza-ti ca dai cu zarul de 100 de ori si scrii rezultatul de fiecare data pe o foaie de hartie. Sonic Pi foloseste ceva echivalent cu aceste liste de rezultate atunci cand ceri o valoare aleatoare. In loc sa dea cu zarul, doar alege urmatoarea valoare din lista. Alegerea seed-ului pentru sirul aleator inseamna deplasarea la o anumita pozitie din lista.

Gaseste-ti ritmul

Alt element important al riff-ului este ritmul - cand a redai si cand sa nu redai o nota. Dupa cum am vazut mai sus, putem folosi ‘:r’ in listele de note pentru a insera pauze. Alta metoda foarte versatila este folosirea spread-urilor pe care o vom prezenta intr-un tutorial viitor. Astazi vom folosi randomizarea care ne va ajuta sa ne gasim ritmul dorit. In loc sa redam fiecare nota, putem folosi o instructiune conditionala pentru a reda o nota cu probabilitatea aleasa. Sa aruncam o privire:

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

O functie pe care este foarte util sa o stii este ‘one_in’ care va returna o valoare de adevar (‘true’ sau ‘false’) cu probabilitatea ceruta de noi. Aici folosim valoarea 2, deci in medie functia ‘one_in’ va returna ‘true’ o data la fiecare doua apeluri. Cu alte cuvinte, in 50% dintre cazuri va returna ‘true’. Folosind valori mai mari, vom obtine rezultatul ‘false’ mai des, introducand mai multe pauza in riff.

Ai observat ca am adaugat o iteratie folosind ‘16.times’. Asta deoarece vrem sa resetam sirul pseudoaleator doar o data la fiecare 16 note, astfel incat ritmul nostru sa se repete de 16 ori. Aceasta nu influenteaza amestecarea notelor deoarecea aceasta este realizata imediat dupa ce valoarea de initializare pentru sirul plseudoaleator este stabilita. Putem folosi dimensiunea iteratiei pentru a modifica lungimea riff-ului. Schimba din 16 in 8 sau chiar 4 sau 3 pentru a vedea cum afecteaza ritmul riff-ului.

Sa punem totul cap la cap

OK, sa punem cap la cap ce am invatat intr-un exemplu final. Ne vedem data viitoare!

live_loop :random_riff do
  #  uncomment to bring in:
  #  synth :blade, note: :e4, release: 4, cutoff: 100, amp: 1.5
  use_synth :dsaw
  use_random_seed 43
  notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle.take(8)
  8.times do
    play notes.tick, release: rand(0.5), cutoff: rrand(60, 130) if one_in(2)
    sleep 0.125
  end
end
 
live_loop :drums do
  use_random_seed 500
  16.times do
    sample :bd_haus, rate: 2, cutoff: 110 if rand < 0.35
    sleep 0.125
  end
end
 
live_loop :bd do
  sample :bd_haus, cutoff: 100, amp: 3
  sleep 0.5
end

- Basul acid

Este imposibil sa treci in revista istoria muzicii dance electronice fara sa remarci impactul major al micutului sintetizator Roland TB-303. Este ingredientul secret din sunetul acid bass original. Acele clasice riff-uri de bas scartaite produse de TB-303 pot fi intalnite de la inceputurile Chicago House pana mai aproape de zilele noastre la artisti ca Plastikman, Squarepusher si Aphex Twin.

Este interesant de stiut ca Roland nu a a gandit TB-303 pentru a fi utilizat in muzica dance. A fost creat initial ca un ajutor pentru chitaristii care exerseaza. Ei si-au imaginat ca utilizatorii vor programa sintetizatorul sa redea linia de bas si vor improviza alaturi de el. Din nefericie, au existat o serie de probleme: erau cam complicat de programat, nu sunau foarte bine ca inlocuitor de chitara bas si erau destul de scumpe. Ca sa-si limiteze pierderile, Roland a decis sa opreasca productia duoa ce a vandut 10000 de bucati si dupa ce au zacut cativa ani nefolosite prin dulapurile chitaristilor au inceput sa apara in vitrinele magazinelor second hand. Aceste TB-303 abandonat asteptau sa fie descoperite de o noua generatie de inovatori care au inceput sa le foloseasca in moduri la care Roland nu se gandise si sa creeze sunete noi incitante. Asa s-a nascut Acid House.

Daca sa pui mana pe un TB-303 nu e prea usor, te vei bucura sa afil ca poti sa iti transformi Raspberry Pi intr-un astfel de sintetizatori folosind puterea Sonic Pi. Pornest Sonic Pi si copiaza codul asta intr-un buffer gol, apoi apasa Run:

use_synth :tb303
play :e1

Am obtinut pe loc acid bass. Sa ne jucam putin…

Sa scartaie basul

Mai intai, sa construim un generator live de arpegii pentru a face lucrurile mai distractive. In tutorialul precedent am vazut cum riff-urile pot fi doar liste de note care se repeta una cate una, luand-o de la capat cand ajungem la sfarsit. Sa cream o bucla live care face exact acest lucru:

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

Sa privim fiecare linie.

Pe prima linie alegem ca sintetizatorul implicit sa fie ‘tb303’, folosind functia ‘use_synth’. Pe linia a doua cream o bucla live numita ‘:squelch’ care se va relua iar si iar. Linia a treia este locul unde cream riff-ul - o lista de note (E in octavele 1, 2 si 3) pe care o parcurgem ciclic folosind ‘.tick’. Definim ‘n’ pentru a reprezenta nota curent din riff. Semnul egal inseamna ca atribuim valoarea din drepata numelui din stanga sa. Aceasta va fi diferita la fiecare trecere. Prima data, ‘n’ va avea valoarea ‘:e1’. A doua oara va fi ‘:e2;, urmata de ‘:e3’ si apoi iar ‘:e1’, reluandu-se la infinit. Linia patru este locul in care pornim cu adevarat ‘:tb303’ Sunt folositi cativa parametri interesanti aici: ‘release:’, ‘cutoff:, ‘res:’ si ‘wave:’, pe care ii discutam in continuare. Linia 5 este cea in care cerem pauza (‘sleep’) - cerem buclei sa se reia la fiecare ‘0.125’secunde sau de 8 ori pe secunda la viteza implicita de 60 BPM. Linia 6 este sfarsitul (‘end’) buclei live. Ea spune Sonic Pi unde se termina partea care se repeta in bucla.

Cat timp incerci sa intelegi ce se intampla, scrie codul de mai sus si apasa butonul Run. Ar trebui sa auzi cum ‘:tb303’ intra in actiune. Aici este toata distractia, sa incepem sa programam live!

In timp ce se executa bucla, schimba valoarea pentru ‘cutoff:’ la ‘110’. Acum apasa pe Run din nou. Ar trebui sa auzi cum sunetul devine putin mai dur si mai scartait. Scrie ‘120’ si apasa pe Run. Apoi ‘130’. Asculta cum o valoare mai mare pentru cutoff face sunetul mai intens si mai patrunzator. Coboara valoarea la ‘80’ cand simti ca e nevoie de o pauza. Apoi repeta de cate ori doresti. Nu te teme, voi fi tot aici…

Un alt parametru cu care te poti juca este’res:’. Acesta controleaza nivelul de rezonanta al filtrului. O rezonanta inalta este o caracteristica a sunetelor acid bass. Acum avem valoarea pentru ‘res:’ setata la ‘0.8’. Incearca sa o maresti putin la ‘0.85’, apoi la ‘0.9’ si in final la 0.95’. Vei constata ca o valoare pentru cutoff gen ‘110’ sau mai ridicata va face diferentele mai usor de auzit. Fa o nebunie si introdu ‘0.999’ pentru niste sunete traznite. La o valoare atat de ridicata pentru ‘res’ vei auzi cum filtrul cutoff rezoneaza atata de mult incat incepe sa scoata propriile sunete!

In fine, un impact puternic asupra timbtului il are schimbarea valorii pentru ‘wave:’ in ‘1’. Aceasta este alegerea oscilatorului sursa. Valoarea ‘0’ este pentru unda dinte de fierastrau, ‘1’ este pentru impulsuri rectangulare, iar ‘2’ pentru o forma de unda triunghiulara.

Desigur, poti incerca diferite riff-uri schimband notele din lista sau chiar alegand notele din game sau acorduri. Distreaza-te cu primul tau sintetizator acid bass.

Disectia TB-303

Designul TB-303 original este de fapt destul de simplu. Dupa cum vezi in diagrama urmatoare sunt doar 4 componente de baza.

Designul TB-303

Prima este unda produsa de oscilator - materia prima pentru sunet. In cazul acesta avem o unda rectangulara. Apoi este anvelopa de amplitudine a oscilatorului care controleaza amplitudineea undei rectangulare in timp. Acestea sunt accesibile in Sonic Pi folosind ‘attack:’, ‘decay:’, ‘sustain:’ si ‘release:’ impreuna cu nivelele lor. Pentru mai multe informatii citeste sectiunea 2.4 ‘Anvelopa de timp’ din tutorialul inclus in program. Trecem apoi unda rectangulara careia i-a fost aplicata anvelopa printr-un filtru rezonant ‘trece jos’ (low pass). Acesta taie frecventele inalte si are si un efect placut de rezonanta. Aici incepe partea interesanta. Valoarea de cutoff pentru acest filtrul are propria sa anvelopa. Aste ne ofera un control incredibil asupra timbrului sunetului prin modificarea ambelor anvelope. Sa aruncam o privire:

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

Pentru fiecare parametru al anvelopei standard exista un echivalent pentru ‘cutoff_’ in cazul sintetizatorului ‘:tb303’. Deci, pentru a shimba timpul de atac pentru cuttof putem folosi parametrul ‘cutoff_attack’. Copiaza codul de mai sus intr-un buffer gol si apasa Run. Vei auzi un sunet ca un ciripit. Incearca sa schimbi timpul pentru ‘cutoff_attack’ in ‘1’ si apoi in ‘0.5’. Acum incearca ‘8’.

Observi ca am trecut totul printr-un efect ‘:reverb’ pentru atmosfera. Incearca alte efecte pentru a vedea ce se intampla!

Sa punem totul cap la cap

La final iata o piesa pe care am compus-o folosind ideile prezentate in acest tutorial. Copiaz-o intr-un buffer gol, asculta pentru un timp apoi incepe sa programezi live aducand propriile modificari. Vezi ce sunete interesante poti produce din ea! Ne vedem data viitoare…

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 muzical

Salut, bine ati revenit! In precedentele tutoriale ne-am concentrat doar pe functionalitatile muzicale ale Sonic Pi (transformarea Raspberry Pi intr-un instrument muzical gata pentru interpretare). Pana acum am invatat cum sa:

Programam live - schimband sunetele din mers, Programam niste beat-uri geniale, Generam melodii cool folosind sintetizatoarele, Re-cream vestitul sunet acid-bass al sintetizatorului TB-303.

Am insa mult mai multe sa va arat (si voi continua sa fac asta in numerele viitoare). Luna asta, insa, am sa va arat ceva ce Sonic Pi stie sa faca dar probabil nici nu va ganditi: sa controleze Minecraft.

Salut lume Minecraft!

OK, sa incepem. Porneste Rasberry Pi, lanseaza Minecraft Pi si creeaza o lume noua. Acum porneste Sonic Pi si redimensioneaza si aseaza ferestrele astfel incat sa vezi atat Sonic Pi cat si Minecraft Pi in acelasi timp.

Intr-un buffer nou scrie asta:

mc_message "Hello Minecraft from Sonic Pi!"

Acum, apasa Run. Boom! Mesajul tau a aparut in Minecraft! Cat de greu a fost? Acum, opreste-te putin din citit acest tutorial si joaca-te putin cu propriile mesaje. Distreaza-te!

Imaginea 0

Teleportare sonica

Acum sa exploram putin. Varianta obisnuita este sa iei mouse-ul si tastatura si sa incepi sa te plimbi in jur. Merge, dar este incet si plictisittor. Ar fi mult mai bine daca ai avea o masina care ar putea sa te teleporteze. Ei bine, Sonic Pi are una. Incearca asta:

mc_teleport 80, 40, 100

Genial! Ai ajuns sus, departe. Daca nu aveai activat modul de zbor ai cazut inapoi pana pe pamant. Daca apeste de doua ori rapid pe spatiu ca asa comuti in modul de zbor si te teleportezi din nou, vei incepe sa plutesti din pozitia in care ai aparut.

Acum sa vedem ce inseamna acele numere. Avem trei numere care descriu coordonatele locului din lume in care ne aflam. Fiecare numar are un nume - x, y si z:

x - cat de departe la stanga sau la dreapta (80 in exemplul nostru) y - cat de sus vrem sa ajungem (40 in exemplul nostru) z - cat de departe inainte sau inapoi (100 in exemplul nostru)

Alegand diferite valori pentru x, y sau z, putem sa ne teleportam oriunde in lumea noastra. Incearca! Alege numere diferite si vezi unde ajungi. Daca ecranul devine negru inseamna ca te-ai teleportat sub pamant sau intr-un munte. Alege o valoare mai mare pentru y si vei iesi din nou deasupra solului. Continua sa explorezi pana gasesti un loc care iti place…

Folosind ideile de pana acum, sa construim o masina de teleportat care scoate un sunet haios cand te deplaseaza in lumea 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!"

Imaginea 1

Blocuri magice

Ai gasit un loc interesant, acum sa incepem sa construim. Ai putea face ca pana acum sa incepi sa faci click in disperare cu mouse-ul pentru a plasa blocuri la pozitia cursorului. Sau ai putea sa folosesti puterile magice ale Sonic Pi. Incearca asta:

x, y, z = mc_location
mc_set_block :melon, x, y + 5, z

Acum priveste in sus! E un pepene pe cer! Priveste o clipa la cod. Ce am facut? Pe prima linia am aflat pozitia curenta a lui Steve in variabilele x, y si z. Acestea corespund coordonatelor descrise anterior. Folosim aceste coordonate in functia ‘mc_set_block’ care plaseaza blocul pe care l-ai ales la coordonatele specificate. Pentru a construi ceva mai sus in cer trebuie sa marim valoarea pentru y, motiv pentru care am adaugat 5 la ea. Sa construim o poteca:

live_loop :melon_trail do
  x, y, z = mc_location
  mc_set_block :melon, x, y-1, z
  sleep 0.125
end

Acum, mergi in fereastra Minecraft, asigura-te ca esti in modul de zbor (apasa de doua ori pe bara de spatiu in caz contrar) si zboara la intamplare. Priveste in urma ta si vei vedea o poteca formata din pepeni. Incearca sa creezi modele cat mai introtocheate pe cer.

Programare live in Minecraft

Cei care au urmarit acest tutorial pe parcursul ultimelor lui sunt probabil dati pe spate. Poteca din pepeni este interesanta, dar cel mai surprinzator este ca poti folosi ‘live_loop’ cu Minecraft! Pentru cei care nu stiu, ‘live_loop’ este o putere magica a Sonic Pi pe care niciun alt limbaj de programare nu o are. Iti permite sa rulezi mai multe bucle in acelasi timp si te lasa sa le schimbi in timp ce ruleaza. Sunt incredibil de puternice si foarte distractive. Eu folosesc ‘live_loop’ pentru a canta in cluburi cu Sonic Pi. DJ-ii folosesc discuri, eu folosesc bucle live :) Dar astazi vom programa live si muzica si Minecraft.

Sa incepem. Ruleaza codul de mai sus si incepe sa construiesti poteca din pepeni din nou. Acum, fara sa opresti codul, schimba ‘:melon’ cu ‘:brick’ si apasa pe Run. Acum lasi in urma ta o poteca din caramizi. Cat de simplu a fost! Ti-ar placea sa ai si niste muzica in timp ce faci asta? E usor. Incearca:

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

Acum, in timp ce ruleaza, incepe sa schimbi codul. Schimba tipul de blocuri - incearca ‘:water’, ‘:grass’ sau blocul tau favorit. In acelasi timp incearca sa schimbi valoarea pentru cutoff din ‘70’ in ‘80 si apoi in ‘100’ Nu-i asa ca este distractiv?

Sa punem totul cap la cap

Imaginea 2

Sa punem cap la cap ce am vazut pana acum si sa mai adaugam putina magie. Sa combinam abilitatea de a ne teleporta cu plasarea de blocuri si cu muzica pentru a realiza un videoclip Minecraft. Nu te ingrijora daca nu intelegi totul, doar scrie codul asta si joaca-te cu el schimband niste valori in timp ce este redat. Distreaza-te! Ne vedem data viitoare…

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

- Beat-uri Bizet

Dupa scurta noastr incursiune in fantastica lumea a programarii Minecraft folosind Sonic Pi de luna trecuta, sa revenim la muzica. Astazi vom aduce o bucata de dans dintr-o opera clasica direct in secolul 21 folosind puterea codului.

Scandalos si tulburator

Sa calatorim inapoi in timp in anul 1875. Un compozitor pe nume Bizet tocmai a terminat ultima sa opera, Carmen. Din pacate, la fel ca in cazul multor altor piese incitante si neobisnuite, lumea nu a apreciat-o la inceput deoarece era scandalos de diferita. In mod tragic, Bizeta a murit cu zece ani inainte ca opera sa obtine un succes international imens si sa devina una dintre cele mai faimoase si cele mai frecvent interpretate opere din toate timpurile. Ca un semn de compasiune sa luam una dintre temele principale din Carmen si sa o convertim intr-un format modern care este de asemenea scandalos si diferit pentru majoritatea oamenilor din vremea nostra - muzica programata live!

Decodarea Habanerei

Sa incercam sa scriem cod pentru intreaga opera ar fi o provocare serioasa pentru acest tutorial, mai bine sa ne concentram asupra uneia dintre cele mai faimoase parti - linia de bas din Habanera:

Riff Habanera

S-ar putea sa ti se para ca e in pasareasca daca nu ai studiat notatia muzicala inca. Totusi, ca programatori vedem notatia muzicala ca pe o alta forma de cod - doar ca reprezinta instructiuni pentru un muzician, nu pentru un computer. Trebuie deci sa gasim o cale sa o decodam.

Notele

Notele sunt aranjate de la stanga la dreapta, la fel cu cuvintele din aceasta revista, dar au inaltimi diferite. Inaltimea pe portativ reprezinta tonalitatea notei. Cu cat e mai sus nota pe portativ, cu atat tonalitatea notei va fi mai sus.

In Sonic Pi stim deja sa modificam tonalitatea notei - fie folosim numere mai mari sau mai mici, cum ar fi ‘play 75’ si ‘play 80’, fie folosim numele notelor: ‘play: E’ si ‘play:F’. Din fericire, fiecare dintre pozitiile verticale de pe portativ reprezinta o anumita nota. Priveste acest tabel util pentru cautare rapida:

Notele

Pauzele

Partiturile muzicale reprezinta un tip de cod foarte bogat si expresiv capabil sa comunice multe lucruri. Nu ar trebui deci sa fie o surpriza ca partiturile pot sa-ti spuna nu doar ce note sa canti, ci si cand nu trebuie sa canti nicio nota. In programare acest lucru este echivalent cu folosirea ‘nil’ sau ‘null’ - absenta unei valori. Cu alte cuvinte, a nu canta nicio nota inseamna absenta unei note.

Daca privesti cu atentie partitura vei observa ca este de fapt o combinatie de puncte negre cu linii care reprezinta notele ce vor fi redate si niste chesti serpuite care reprezinta pauzele. Din fericire Sonic Pi are o reprezentare foarte comoda pentru pauze: ‘:r’, deci daca dam comanda: ‘play :r’ va reda de fapt liniste… Putem de asemenea sa scriem ‘play :rest’, ‘play nil’ sau ‘play false’ care sunt toate moduri echivalente de a reprezenta pauzele.

Ritmul

Mai este un ultim lucru pe care trebuie sa inveti sa-l decodezi in notatie - tempoul pentru note. In imaginea initiala vei vedea ca notele sunt conectate cu niste linii groase. A doua nota are doua astfel de linii, ceea ce inseamna ca tine o saisprezecime de masura. Celelalte note au o singura linie, ceea ce inseamna ca dureaza o optime. Pauza are si ea doua linii serpuite care inseamna ca dureaza tot o saisprezecime de masura.

Cand incercam sa decodam si sa exploram efectul unor modificari cel mai bine ar fi sa incercam sa facem totul cat mai asemanator si sa incercam sa vedem ce legaturi putem face. De exemplu, cand rescriem partitura noastra in saisprezecimi poti vede cum se transforma intr-o secventa draguta de note si pauze.

Riff-ul Habanera 2

Rescrierea bucatii Habanera

Suntem acum in masura sa transpunem aceasta line de bas in Sonic Pi. Sa codam aceste note si pauze intr-o lista circulara:

(ring :d, :r, :r, :a, :f5, :r, :a, :r)

Sa vedem cum suna. Pune asta intr-o bucla live si fa o parcurgere ciclica:

live_loop :habanera do
  play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
  sleep 0.25
end

Excelent, acest riff inconfundabil capata viata in difuzoarele tale. A fost foarte greu sa ajungem aici, dar a meritat - bate palma!

Sintetizatoare de atmosfera

Avem linia de bas, sa recream o parte din atmosfera scenei de opera. Un sintetizatot care merita incercat este ‘:blade’ care este un sintetizator in genul anilor 80. Sa-l incercam trecand nota ‘:d’ de la inceput printr-un slicer si un efect reverb:

live_loop :habanera do
  use_synth :fm
  use_transpose -12
  play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
  sleep 0.25
end
with_fx :reverb do
  live_loop :space_light do
    with_fx :slicer, phase: 0.25 do
      synth :blade, note: :d, release: 8, cutoff: 100, amp: 2
    end
    sleep 8
  end
end

Acum, incearca alte note in linia de bas: ‘:a’ si ‘:f5’. Tine minte, nu e nevoie sa apesi pe Stop, doar modifici codul in timp ce se aude muzica si apesi pe Run din nou. De asemenea, incearca diferite valori pentru parametru ‘phase:’ al slicer-ului, cum ar fi 0.5, 0.75 si 1.

Sa punem totul cap la cap

La final, sa combinam toate aceste idei intr-un nou remix dupa Habanera. Poate ai observat ca am inclus o alta parte din linia de bas sub forma de comentariu. Dupa ce ai copiat totul intr-un buffer nou apasa Run si asculta compozitia. Acum, fara sa apesi pe stop, sterge simbolul de comentariu ‘#’ din fata celei de a doua linii si apasa Run din nou - nu e minunat? Acum poti sa-l modifici cum vrei si sa te distrezi.

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

- Cum sa devii un VJ Minecraft

Imaginea 0

Toata lumea a jucat Minecraft. Toti ati construit structuri impresionante, ati gandit capcane iscusite si probabil ati creat trasee pentru minecart controlate de comutatoare si circuite din redstone. Cati dintre voi ati interpretat muzica in Minecraft. Pariez ca nu stiati ca puteti folosi Minecraft ca sa creati efecte vizuale impresionante, la fel ca un VJ profesionist.

Daca singurul mod in care ai schimbat ceva in Minecraft a fost cu ajutorul mouse-ului, probabil te-ai chinuit destul de mult sa schimbi lucrurile suficient de rapid. Din fericire pentru tine Raspberry Pi iti vine in ajutor cu o versiune de Minecraft care poate fi controlata prin intermediul programarii. Vine de asemenea cu o aplicatie numita Sonic Pi care face programarea in Minecraft nu doar foarte facila ci si incredibil de distractiva.

In articolul de azi iti voi arata cateva trucuri pe care le-am folosit pentru interpretarile din cluburile de noapte sau scene muzicale din toata lumea.

Sa incepem…

Inceputul

Sa incepem cu un exercitiu usor de incalzire pentru a ne reaminti lucrurile de baza. Pentru inceput, porneste Raspberry Pi si apoi lanseaza atat Minecraft cat si Sonic Pi. In Minecraft, creeaza o lume noua, iar in Sonic Pi alege un buffer gol si scrie codul de mai jos:

mc_message "Sa incepem..."

Apasa butonul Run si vei vedea un mesaj in fereastra Minecraft. OK, suntem gata sa incepem, hai sa ne distram…

Furtuna de nisip

Cand folosim Minecraft pentru a crea efecte vizuale incercam sa ne gandim ce va arata interesant si va fi si usor de generat prin cod. Un truc haios este sa creezi o furtuna de nisip lasand sa cada blocuri de nisip din cer. Pentru asta avem nevoie doar de cateva functii de baza:

‘sleep’ - pentru a insera o pauza intre actiuni ‘mc_location’ - pentru a afla pozitia noastra curenta ‘mc_set_block’ - pentru a plasa blocuri de nisip la o anumita pozitie ‘rrand’ - pentru a genera valori aleatoare intr-un anumit interval ‘live_loop’ - pentru a face ca ploaia de nisip sa cada in continuu

Daca nu esti familiarizat cu vreuna dintre functiile de mai sus, cum ar fi ‘rrand’, scrie numele ei intr-un buffer, fa click pe el si apoi apasa combinatia de taste ‘Control-i’ pentru a afisa informatiile despre functie din documentatia interna. O alta varianta ar fi sa mergi la panoul lang din sistemul de ajutor si sa cauti direct functia alaturi de alte chestii incitante pe care le poti face.

Sa facem sa ploua putin inainte sa se dezlantuie furtuna cu toata forta. Vezi care este pozitia curenta si folosteste-o ca sa creezi cateva blocuri de nisip sus pe cer, in apropiere:

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

Cand apesi pe Run va trebui sa te uiti putin in jurul tau deoarece blocurile ar putea incepe sa cada in spatele tau, in functie de directia in care te uitai. Nu te ingrijora daca le-ai ratat, apasa Run din nou pentru inca un lot de ploaie de nisip - doar asigura-te ca te uiti in directia potrivita!

Sa trecem rapid in revista ce se intampla aici. Pe prima linia am citit pozitia lui Steve sub forma de coordonate, folosind functia ‘mc_location’, si le-am pus in variabilele ‘x’, ‘y’ si ‘z’. Apoi, pe liniile urmatoare am folosit ‘mc_set_block’ pentru a crea niste blocuri de nisip la aceleasi coordonate cu ale lui Steve, dar cu niste modificari. Alegem aceeasi valoare pentru x, o valoare pentru y mai mare cu 20 (adica mai sus) si apoi valori care cresc succesiv pentru z astfel incat nisipul sa cada pe o linie care se indeparteaza de Steve.

Ce-ar fi sa te joci putin modificand codul? Incearca sa adaugi mai multe linii, sa schimbi valoarea pentru ‘sleep’, sa amesteci ‘:sand’ cu ‘:gravel’ si sa alegi coordonate diferite. Experimenteaza si distreaza-te!

Puterea buclelor live

OK, e timpul sa pornim furtuna folosind forta ‘live_loop’ - bagheta magica a Sonic Pi care permite folosirea la maxim a puterii programarii live prin modificarea codului in timp ce ruleaza!

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

Ce distractiv! Parcurgem bucla rapid (de 8 ori pe secunda) si la fiecare trecere citim pozitia lui Steve la fel ca mai inainte, iar apoi generam 3 valori aleatoare:

‘xd’ - diferenta pe axa x care va fi intre -10 si 10 ‘zd’ - diferenta pe axa z, de asemenea intre -10 si 10 ‘co’ - valoarea de cutoff pentru filtrul trece jos, intre 70 si 130

Folosim apoi aceste valori in functiile ‘synth’ si ‘mc_set_block’ obtinand nisipul care cade in pozitii aleatoare in jurul lui Steve impreuna cu un sunet asemanator cu cel al ploii generat de sintetizatorul ‘:cnoise’.

Daca nu stii inca ce sunt buclele live - ele sunt cele care dau tot farmecul cand folosim Sonic Pi. In timp ce codul ruleaza si nisipul cade, incearca sa schimbi una dintre valori, de exemplu valoare pentru pauza la ‘0.25’ sau tipul blocurilor din ‘:sand’ in ‘:gravel’. Acum apasa run din nou. Super! Lucrurile s-au schimbat fara a opri programul. Asta este modalitatea prin care poti sa te manifesti ca un VJ adevarat. Continua sa exersezi si sa schimbi parametrii. Cat de mult poti schimba efectele vizuale fara a opri executia?

Modele de blocuri spectaculoase

Imaginea 1

O alta metoda de a genera imagini interesante este sa generezi pereti imensi cu model care se deplaseaza. Pentru acest efect trebuie sa trecem de la plasarea de blocuri aleator la plasarea lor intr-o ordine prestabilita. Putem face asta creand o iteratie in iteratie (apasa pe butonul Help si mergi la sectiunea 5.2 a tutorialului, “Iteratii si bucle” pentru mai multe informatii despre iteratii). Simpaticul ‘ xd ’ de dupa do inseamna ca ‘xd’ va fi setat pentru fiecare valoare a iteratiei. Deci prima fata va fi 0, apoi 1, apoi 2 … etc. Introducand o iteratie intr-o alta ca aici putem genera toate coordonatele dintr-un patrat. Putem apoi alege aleator tipurile de blocuri dintr-o lista circulara pentru un efect interesant:
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

Simplu dar elegant. Cat ne distram aici, incearca sa schimbi bs.choose in bs.tick pentru a trece de la un model aleator la unul mai regulat. Incearca sa schimbi tipurile blocurilor si daca esti mai indraznet ai putea pune asta intr-un ‘live_loop’ astfel incat modelul sa se schimbe automat.

Acum, pentru trucul tau special de VJ, schimba cele 2 10.times in 100.times si apasa Run. Kaboom! Un perete gigant de caramizi plasate aleator. Imagineaza-ti cat timp ti-ar lua sa il construiesti manual cu mouse-ul! Apasa de doua ori rapid pe spatiu pentru a activa modul de zbor si incepe sa te plimbi pentru ca efectul vizual sa fie si mai interesant. Nu te opri aici, foloseste-ti imaginatia si incearca sa iti aplici ideile folosind puterea programarii in Sonic Pi. Cand consideri ca ai exersat suficient, redu lumina si pune in scena un show pentru prietenii tai!


- Navigand pe curenti aleatori

In episodul 4 al acestui serial de tutoriale am aruncat o privire asupra randomizarii in timp ce am programat cateva riff-uri incitante. Tinand cont ca randomizarea este o parte atat de importanta a interpretarilor mele live, m-am gandit ca ar fi util sa vorbim mai in detaliu despre elementele ei de baza. Deci, ia-ti amuleta norocoasa si sa navigam pe curenti aleatori!

Nu exista aleator

Primul lucru pe care trebuie sa-l inveti si care s-ar putea sa ti se para surprinzator cand te joci cu functiile de randomizare este ca de fapt nu sunt chiar aleatoare. Ce inseamna asta? Ei bine, sa facem niste teste. Mai intai, gandeste-te la un numar intre 0 si 1. Tine-l minte fara sa mi-l spui. Acum, sa incerc sa-l ghicesc… era ‘0.321567’? Nu? Bleah, e evident ca nu-s bun la jocul asta. Hai sa mai incerc o data, dar sa lasam Sonic Pi sa aleaga numarul de data asta. Porneste Sonic Pi v2.7+ si cere-i un numar aleator, din nou fara sa mi-l spui mie:

print rand

Acum sa vedem… era 0.75006103515625? Da! Ha, ha, vad ca esti putin neincrezator. Poate a fost doar chestie de noroc. Hai sa incercam din nou. Apasa butonul Run si vezi ce primesti… Ce? Din nou 0.75006103515625? E clar ca nu este aleator! Ai dreptate, nu este.

Ce se intampla aici? Cuvantul elevat folosit in lumea calculatoarelor pentru asta este determinism. Asta inseamna ca nimic nu este la intamplare ci totul este bazat pe predestinare. Versiunea ta de Sonic Pi este predestinata sa returneze mereu 0.75006103515625 in programul de mai sus. Asta pare sa fie o chestie inutila, dar crede-ma ca este una dintre partile cele mai tari din Sonic Pi. Daca te tii de ea vei invata cum sa te bazezi pe natura determinista a randomizarii in Sonic Pi ca bloc de baza pentru constructia compozitiilor tale sau a interpretarii live ca DJ.

O melodie aleatoare

Cand Sonic Pi porneste, incarca in memorie o secventa de 441 000 valori aleatoare pre-calculate. Cand apelezi o functie pentru numere aleatoare, cum ar fi ‘rand’ sau ‘rrand’, acest sir aleator este folosit pentru a genera rezultatul asteptat. Fiecare apel al unei functii pentru numere aleatoare consuma o valoare din sir. Deci al zecelea apel al unei functii pentru numere aleatoare va folosi a zecea valoare din sir. De asemenea, de fiecare data cand apesi pe butonul Run, sirul este resteat pentru acea executie. Acesta este motivul pentru care am reusit sa prezic rezultatul functiei ‘rand’, iar melodia ‘random’ a sunat mereu la fel. Versiunea Sonic Pi a fiecaruia dintre voi foloseste exact acelasi sir de valori aleatoare, ceea ce este foarte important cand impartasesti creatiile tale cu altii.

Sa ne folosim de ce am aflat ca sa generam o melodie aleatoare repetabila:

8.times do
 play rrand_i(50, 95)
 sleep 0.125
end

Copiaza codul asta intr-un buffer gol si apasa Run. Vei auzi o melodie constand in note ‘aleatoare’ intre 50 si 95. Cand se termina, apasa din nou pe Run ca sa auzi exact aceeasi melodie din nou.

Functii utile pentru randomizare

Sonic Pi contine o serie de functii utile pentru a lucra cu sirul aleator. Iata o lista cu cateva dintre cele mai folositoare:

‘rand’ - returneaza urmatoarea valoare din sirul aleator ‘rrand’ - returneaza o valoare aleatoare intr-un interval ‘rrand_i’ - returneaza un numar intreg intr-un interval ‘one_in’ - returneaza ‘true’ sau ‘false’ cu o probabilitate specificata ‘dice’ - imita datul cu zarul si returneaza o valoare intre 1 si 6 ‘choose’ - alege o valoare aleatoare dintr-o lista

Verifica documentatia pentru aceste functii in sistemul de ajutor pentru informatii detaliate si exemple.

Resetarea sirului aleator

Chiar daca abilitatea de a repeta o secventa de note este esentiala pentru a-ti permite sa redai din nou un riff pe ringul de dans, s-ar putea sa nu fie exact riff-ul pe care ti l-ai dorit. N-ar fi interesant daca am putea incerca mai multe riff-uri si sa-l alegem pe cel care a sunat cel mai bine? Aici incepe magia.

Putem seta manual sirul folosind functia ‘use_random_seed’. In lumea computerelor, seed este valoarea de initializare a sirului aleator sau punctul de pornire din care poate porni un nou sir de valori aleatoare. Sa incercam:

use_random_seed 0
3.times do
  play rrand_i(50, 95)
  sleep 0.125
end

Super, avem primele trei note ale melodiei noastre aleatoare de mai sus: ‘84’, ‘83’ si ‘71’. Am putea insa schimba seed-ul cu altceva. Sa incercam asta:

use_random_seed 1
3.times do
  play rrand_i(50, 95)
  sleep 0.125
end

Interesant, am obtinut ‘83’, ‘71’ si ‘61’. Probabil ai observat ca primele doua numere sunt aceleasi ca ultimele doua numere de data trecuta - nu este o coincidenta.

Iti aduci aminte ca sirul aleator este doar o lista gigantica de valori ‘pre-generate’. Folosirea unui seed inseamna pur si simplu pozitionarea in aceasta lista. Un alt mod de a vedea acest lucru este sa iti imaginezi un pachet enorm de carti amestecate. Folosirea unui seed este la fel cu a taia pachetul de carti intr-o anumita pozitie. Partea cea mai frumoasa este ca tocmai aceasta abilitate de a te pozitiona precis in sirul aletor ne da o mare putere cand cream muzica.

Sa revenim la melodia noastra aleatoare din 8 note inarmati cu aceasta abilitate de a reseta sirul aleator, dar hai sa adaugam si o bucla live ca sa putem experimenta in timp ce canta muzica:

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

Acum, in timp ce canta, schimba valoarea pentru seed din ‘0’ in altceva. Incearca ‘100’, sau ‘999’. Incearca propriile valori, experimenteaza si joaca-te. Vezi ce seed genereaza riff-ul care iti place cel mai mult.

Sa punem totul cap la cap

Tutorialul de luna asta a fost o incursiune tehnica in modul de functionare a randomizarii in Sonic Pi. Sper ca ti-ai putut crea o idee despre cum functioneaza si cum te poti folosi de randomizare intr-un mod fiabil pentru a crea secvente repetabile in muzica ta. E important sa evidentiem ca poti folosi randomizarea repetabile oriunde doresti. De exemplu, poti randomiza amplitudinea notelor, tempoul pentru ritm, valoarea pentru reverb, sintetizatorul curent, mixul pentru un efect, etc etc. Intr-un episod viitor vom privi mai indeaproape cateva dintre aceste utilizari, dar deocamdata iti voi prezenta un scurt exemplu.

Scrie codul de mai jos intr-un buffer gol, apasa Run, apoi incepe si schimba seed-ul, apasa din nou Run (cat timp inca ruleaza) si incearca diferitele sunete, ritmuri si melodii pe care le poti obtine. Cand gasesti ceva dragut, tine minte seed-ul pentru a putea reveni la el. Dupa ce ai gasit mai multe seed-uri care iti plac, poti sa realizezi o interpretare live pentru prietenii tai schimband intre diferitele valori pentru a crea o piesa completa.

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

- Controlul sunetului

Pana acum in aceasta serie de tutoriale ne-am concentrat pe pornirea sunetelor. Am descoperit ca putem porni un sintetizator din multele incluse in Sonic Pi folosind ‘play’ sau ‘synth’ sau un esantion pre-inregistrat folosind ‘smple’. De asemenea am vazut cum putem trece aceste sunete prin efecte de studio ca reverb sau distorsion folosind comanda ‘with_fx’. Combina toate aceste cu sistemul foarte precis de pozitionare in timp al Sonic Pi si poti produce o gama vasta de sunete, beat-uri si riff-uri. Dar dupa ce ai selectat cu grija optiunile pentru un anumit sunet si l-ai pornit, nu mai exista nicio posibilitate sa il modifici, nu? Gresit! Astazi vei descoperi o functionalitate foarte puternica - controlul sintetizatorului in timpul redarii.

A Sunetul de baza

Sa cream un sunet simplu si dragut. Porneste Sonic Pi si scrie asta intr-un buffer gol:

synth :prophet, note: :e1, release: 8, cutoff: 100

Acum apasa butonul Run din stanga sus ca sa auzi un sunet dragut de sintetizator. Continua, mai apasa de cateva ori butonul ca sa incepi sa il simti. Gata? Sa incepem sa-l controlam!

SynthNode

O caracteristica putin cunoscuta a Sonic Pi este aceea ca functiile ‘play’, ‘synth’ si ‘sample’ returneaza ceea ce se numeste un ‘SynthNode’ care reprezinta un sunet in curs de redare. Poti memora un astfel de ‘SynthNode’ intr-o variabila si apoi sa il controlezi mai tarziu. De exemplu, sa schimbam valoarea pentru parametrul ‘cutoff:’ dupa o masura:

sn = synth :prophet, note: :e1, release: 8, cutoff: 100
sleep 1
control sn, cutoff: 130

Sa privim fiecare linie pe rand:

Mai intai lansam sintetizatorul ‘:propher’ folosind functia ‘synth’ ca de obicei. Dar in acelasi timp memoram si rezultatul intr-o variabila numita ‘sn’. Puteam sa-i dam orice alt nume variabilie, cum ar fi ‘synth_node’ sau ‘jane’ - numele nu conteaza. Totusi, este important sa alegi un nume care iti spune ceva pentru cand interpretezi live se pentru alte persoane care ar putea citi codul tau. E am ales ‘sn’ pentru ca este o prescurtare draguta pentru SynthNode.

Pe linia a doua avem o comanda ‘sleep’ obisnuita. Nu face nimic special, doar ii cere computerului sa astepte o masura inainte sa treaca la linia urmatoare.

Linia 3 este cea in care se intampla totul. Aici am folosit functia ‘control’ pentru a spune sintetizatorului sa schimbe valoarea de cutoff in ‘130’ in timp ce ruleaza. Daca apesi butonul Run, vei auzi cum sintetizatorul ‘:prophet’ incepe sa cante ca mai inainte, dar dupa o masura va incepe sa sune mult mai clar.

Parametri modulabili

Multi dintre parametrii pentru sintetizatoarele si efectele din Sonic Pi pot fi schimbati dupa ce au fost pornite. Nu este insa cazul pentru toate. De exemplu, parametrii anvelopei attack:, decay:, sustain: si release: pot fi specificati doar cand se porneste sintetizatorul. E destul de usor sa afli care parametri pot si care nu pot fi schimbati - mergi la documentatia unui anumit sintetizator sau efect si deruleaza in jos pana la informatiile despre parametrii individuali si cauta fraza “Poate fi schimbat in timpul rularii”, respectiv “Nu mai poate fi schimbat odata setat”. De exemplu, documentatia pentru parametrul ‘attack:’ al sintetizatorului ‘:beep’ spune clar ca nu este posibil sa il schimbi:

Implicit: 0 Trebuie sa fie zero sau mai mare Nu poate fi schimbat odata setat Modificat proportional cu viteza BPM

Schimbari multiple

In timp ce un sintetizator ruleaza poti sa il schimbi de cate ori vrei. De exemplu, putem transforma sintetizatorul ‘:prophet’ intr-un generator de arpegii folosind:

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 aceasta bucata de cod am adaugat cateva chestii in plus. Am definit o noua variabila, numita ‘notes’, care contine notele pe care vrem sa le reda in mod repetat (un generator de arpegii chiar asta inseamna - ceva ce reda notele dintr-o lista circulara in ordine). Apoi am inlocuit apelul individual al functiei ‘control’ cu o iteratie care o apeleaza de 16 ori. La fiecare apel al functiei folosim ‘.tick’ pentru a parcurge lista ‘notes’ care se va repeta automat cand ajungem la sfarsit (gratie minunatelor liste circulare din Sonic Pi). Pentru putina varietate incearca sa inlocuiesti ‘.tick’ cu ‘.choos’ si vezi daca remarci diferenta.

Ai observat ca putem schimba mai multi parametri simultan. Incearca sa schimbi linia in care apare functia control cu aceasta si asculta diferentele:

control sn, note: notes.tick, cutoff: rrand(70, 130)

Sliding

Cand controlam un ‘SynthNode’, el raspunde imediat si schimba instantaneu valoarea parametrului cu cea noua ca si cand ai fi apasat un buton sau ai fi intors de un comutator pentru a cere modificarea. Asta genereaza un sunet ritmic si percutant - mai ales daca parametrul controleaza ceva legat de timbru, cum ar fi ‘cutoff:’. Totusi, uneoi nu vrei ca schimbarea sa se produca instantaneu. In schimb, ti-ai dori o trecere lina de la valoarea curenta la noua valoare ca si cand ai fi miscat un cursor. Desigur, Sonic Pi poate face si acest lucru, folosind parametrii ‘_slide’.

Fiecare parametru care poate fi modificat are asociat si un parametru ‘_slide:’ care permite specificarea timpului in care se face modificarea graduala. De exemplu, pentru ‘amp:’ avem amp_slide:, iar pentru cutoff: avem cutoff_slide:. Acesti parametri functioneaza putin diferit de ceilalti prin aceea ca spun sintetizatorului cum sa actioneze data viitoare cand primesc o comanda de control. Sa aruncam o privire:

sn = synth :prophet, note: :e1, release: 8, cutoff: 70, cutoff_slide: 2
sleep 1
control sn, cutoff: 130

Observi ca exemplul este la fel cu cel dinainte cu exceptia faptului ca am adaugat cutoff_slide:. Aceasta face ca data viitoare cand i se cere sintetizatorului sa schimbe valoarea de cutoff, el sa faca trecea de la valoarea veche la cea noua gradual, pe durata a 2 masuri. Ca urmare, cand vei folosi ‘control’ vei auzi cum ‘cutoff’ trece lin de la 70 la 130, ceea ce da sunetului un aer dinamic. Acum incearca sa schimbi valoarea pentru ‘cutoff_slide’ cu una mai mica, cum ar fi 0.5 sau o valoare mai mare, cum ar fi 4, pentru a observa cum se modifica sunetul. Tine minte, in acelasi mod poti face sa varieze treptat orice parametru modificabil, iar fiecare valoare ‘_slide:’ poate fi complet diferita astfel. De exemplu cutoff poate sa se schimbe lent, amplitudinea mai rapid, iar pozitionarea cu o viteza intre cele doua, daca asta iti doresti…

Sa punem totul cap la cap

Sa analizam putin un scurt exemplu care ne arata puterea controlarii sintetizatoarelor dupa ce au fost pornite. Observi ca pot fi modificate treptat si efectele la fel ca sintetizatoarele, dar cu o sintaxa putin diferita. Citeste sectiunea 7.2 a tutorialului pentru mai multe informatii despre controlul efectelor.

Copiaza codul intr-un buffer gol si asculta. Nu te opri aici, joca-te putin cu codul. Schimba valorile pentru ‘_slide:’, schimba notele, sintetizatorul, efectele si duratele pentru pauze si vezi cum poti sa schimbi sunetul in ceva cu totul diferit!

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

- Urmarirea ritmului

In episodul de luna trecuta am facut o incursiune tehnica in sistemul de randomizare din Sonic Pi. Am explorat cum il putem folosi pentru a adauga un nou nivel de control dinamic in codul nostru intr-un mod determinist. Luna asta vom continua sa studiem detaliile tehnice si ne vom indrepta atentia asupra sistemului de tact unic in Sonic Pi. La sfarsitul acestui articol vei putea sa urmaresti comanzi ritmurile si riff-urile si vei fi cu un pas mai aproape sa devii un DJ care programeaza live.

Numararea masurilor

Cand facem muzica ne dorim adesea sa facem lucruri diferite in functie de masura la care am ajuns. Sonic Pi are un sistem special de contorizare a masurilor, numit ‘tick’, care iti ofera un control precis asupra momentului in care incepe masura si suporta chiar mai multe tempo-uri in paralel.

Sa ne jucam putin, pentru a trece la masura urmatoare trebuie doar sa apelezi ‘.tick’. Deschide un buffer nou si scrie codul de mai jos apoi apasa Run:

puts tick #=> 0

Va fi afisata masura curenta: ‘0’. Poti observa ca daca apesi pe Run de mai multe ori, de fiecare data va returna ‘0’. Asta se intampla deoarece la fiecare Run numaratoarea masurilor incepe de la 0. In timpul rularii insa, putem avansa la urmatoarea masura de cate ori vrem:

puts tick #=> 0
puts tick #=> 1
puts tick #=> 2

De cate ori observi simbolul ‘#=>’ la sfarsitul unei linii de cod, inseamna ca linia va determina scrierea in jurnal a partii care urmeaza. De exemplu, ‘puts foo#=> 0’ inseamna ca instructiunea ‘puts foo’ scrie ‘0’ in jurnal la acel punct din program.

Schimbarea masurii

Am vazut ca ‘tick’ face doua lucruri. Incrementeaza (creste cu 1) valoarea masurii curente si returneaza noua valoare. Uneori vrem doar sa vedem valoarea curenta, fara sa trecem la masura urmatoare, ceea ce poate fi realizat cu ajutorul ‘look’:

puts tick #=> 0
puts tick #=> 1
puts look #=> 1
puts look #=> 1

In acest cod generam un tact de 2 ori si afisam valoarea cu ‘.tick’, apoi doar analizam valoarea de 2 ori cu ‘.look’. Vom vedea urmatoarele valori: 0, 1, 1, 1. Primele 2 utilizari ale functiei ‘tick’ returneaza ‘0’ si apoi ‘1’, cum era de astepta, apoi cele 2 functii ‘look’ returneaza ultima valoare care este ‘1’.

Liste circulare

Deci acum putem trece la masura urmatoare folosind ‘tick’ si sa vedem unde am ajuns folosind ‘look’. Ce urmeaza? Trebuie sa avem ceva ce poate fi parcurs pas cu pas. Sonic Pi foloseste liste circulare pentru a reprezenta riff-uri, melodii si ritmuri, iar sistemul de tact a fost gandit special pentru a lucra strans cu acestea. De fapt, listele circulare au propriile versiuni de tip sufix pentru functia ‘tick’, care realizeaza doua lucruri. In primul rand actioneaza ca un tick obisnuit si trec la masura urmatoare, iar in al doilea rand parcurg listele circulare folosind numarul masurii ca index. Sa aruncam o privire:

puts (ring :a, :b, :c).tick #=> :a

‘.tick’ este o versiune speciala de tip sufix a functiei ‘.tick’, care va returna prima valoare din lista ‘:a’. Putem obtine fiecare dintre valorile din lista apeland ‘.tick’ de mai multe ori:

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

Urmareste jurnalul si vei vedea :a, :b, :c si iarasi :a. Observi ca ‘look’ returneaza valoarea ‘3’. Apelurile ‘.tick’ functioneaza la fel ca cele ale functiei ‘tick’ obisnuite’ - incrementeaza numarul masurii curente.

Creator de arpegii intr-o bucla live

Adevarata distractie incepe cand combinam ‘tick’ cu listele circulare si cu buclele live. Cand punem aceste lucruri impreuna avem tot ce ne trebuie pentru a construi si a intelege un generatori simplu de arpegii. Avem nevoie de doar patru lucruri:

O lista circulara care contine notele pe care vrem sa le repetam. O modalitate de a incrementa si de a obtine numarul masurii curente. Capacitatea de a reda o nota care depinde de masura curenta. O structura de tip bucla care face ca generatorul sa repete arpegiile.

Toate aceste concepte pot fi intalnite in codul urmator:

notes = (ring 57, 62, 55, 59, 64)
live_loop :arp do
  use_synth :dpulse
  play notes.tick, release: 0.2
  sleep 0.125
end

Sa privim fiecare dintre aceste linii. Mai intai definim lista de note pe care le vom reda in continuu. Apoi cream o bucla live numita ‘:arp’ care se ocupa de repetarea instructiunilor pentru noi. De fiecare data cand intram in bucla algem sintetizatorul ‘:dpulse’ si apoi redam urmatoarea nota din lista cu ajutorul ‘.tick’. Tine minte ca acest lucru va duce la incrementarea numarului masurii curente si va folosi aceasta valoare ca index in lista cu notele. La final asteptam o optime de masura inainte de a relua bucla.

Ritmuri multiple

Un lucru important de stiut este ca tactul este local pentru o bucla live. Asta inseamna ca fiecare ‘live_loop’ are propriul contor pentru masura. Acest lucru ne ofera mai multa flexibilitate decat un metronom global si un tempo global. Sa vedem cum functioneaza:

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

Conflicte de numarare

O sursa de confuzii si erori in utilizarea sistemului de tact din Sonic Pi este folosirea unui tick pentru mai multe liste in acelasi ‘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

Fiecare ‘live_loop’ are propriul contor pentru masura, dar noi apelam ‘.tick’ de doua ori in cadrul aceleiasi bucle. Asta inseamna ca numarul masurii curente va fi incrementat de doua ori la fiecare trecere. Uneori pot aparea sunete poliritmice interesante, dar nu asta ne dorim in general. Exista doua solutii pentru aceasta problema. O varianta ar fi sa apelam ‘tick’ la inceputul buclei live si apoi sa folosim ‘look’ pentru a vedea care este valoarea curenta. A doua ar fi sa transmitem un nume unic la fiecare dintre cele 2 apeluri ale functiei ‘.tick’, cum ar fi ‘.tick(:foo)’. Sonic Pi va crea si va urmari un contor separat pentru fiecare nume pe care il folosesti. In felul asta poti lucra cu oricate tacturi ai nevoie. Vezi sectiunea 9.4 din tutorial pentru mai multe informatii despre folosirea de nume pentru tacturi.

Sa punem totul cap la cap

Sa punem cap la cap cunostintele noastre despre tact, liste circulare si bucle live pentru un exemplu final. Ca de obicei, nu trebuie sa tratezi asta ca pe o bucata finisata. Poti schimba ce doresti ca sa vezi in ce o poti transforma. Ne vedem data viitoare…

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

- Slicing cu esantioane

In episodul 3 al acestei serii despre Sonic Pi am vazut cum putem reda in bucla, intinde sau comprima si filtra unul dintre cele mai faimoase solo-uri de toba din toate timpurile - Amen Break. In acest tutorial o sa mergem cu un pas mai departe si o sa vedem cum putem sa il maruntim (slice), sa amestecam bucatile si sa le combinam la loc in alta ordine. Daca ti se pare o chestie putin traznita, nu te ingrijora, lucrurile vor deveni mai clare in curand si vei stapani o noua unealta puternica pentru interpretarile live folosind Sonic Pi.

Sunetul ca date

Inainte sa incepem, sa explicam putin cum functioneaza esantioanele. Pana acum sper ca te-ai jucat deja cu sampler-ul din Sonic Pi. Daca nu, nu exista un moment mai potrivit decat acesta! Porneste Raspberry Pi, lanseaza Sonic Pi din meniul Programming, scrie codul urmator intr-un buffer gol si apasa butonul Run pentru a auzi un beat de toba pre-inregistrat:

sample :loop_amen

O inregistrare a unui sunet este reprezentata sub forma de date - o multime de numere intre -1 si 1 care reprezinta limitele undei sonore. Daca redam aceste numere in ordine, obtinem sunetul original. Dar ce ne opreste sa le redam intr-o alta ordine, pentru a crea alte sunete?

Cum sunt inregistrate de fapt esantioanele? O sa ti se para simplu dupa ce intelegi bazale fizicii sunetului. Cand produci un sunet, de exemplu lovind in toba, acesta se propaga prin aer la fel cum se increteste suprafata apei cand arunci o piatra in ea. Cand aceste unduiri ajung la urechea noastra, timpanul se misca in ritm cu ele si converteste aceste miscari in sunetul pe care il auzim. Daca dorim sa inregistram si sa redam sunetul, trebuie deci sa capturam, sa stocam si sa reproducem aceste unduiri. O metoda este sa folosim un microfon care actioneaza ca un timpan si se misca inainte si inapoi cand unda ajunge la el. Microfonul converteste apoi pozitia respectiva intr-un semnal electric care este masurat de multe ori intr-o secunda. Aceste masuratori sunt reprezentate sub forma unei serii de numere intre -1 si 1.

Daca am incerca sa gasim o reprezentare vizuala a sunetului ar fi un grafic simplu cu timpul pe axa x si pozitia microfonului/difuzorului pe axa y, avand valori intre -1 si 1. Poti vede un exemplu de astfel de grafic in partea de sus a diagramei.

Redarea unei parti dintr-un esantion

Cum procedam deci pentru a cere Sonic Pi sa redea un esantion intr-o ordine diferita. Pentru a raspunde la aceasta intrebare trebuie sa analizam parametrii ‘start:’ si ‘finish:’ pentru ‘sample’. Acestia ne permit sa controlam pozitia de inceput si de final pentru numerele reprezentand esantionul care vor fi redate. Valorile pentru ambii parametri sunt reprezentate de numere intre ‘0’ (inceputul esantionului) si ‘1’ (sfarsitul sau). Deci, pentru a reda prima jumatate din Amen Break, trebuie sa setam valoarea ‘0.5’ pentru ‘finish:’:

sample :loop_amen, finish: 0.5

Putem adauga si o valoare pentru ‘start:’ ca sa redam o sectiune si mai mica din esantion:

sample :loop_amen, start: 0.25, finish: 0.5

Ca sa te distrezi, poti alege o valoare mai mica pentru ‘finish:’ decat pentru ‘start:’ si respectiva sectiune va fi redata invers:

sample :loop_amen, start: 0.5, finish: 0.25

Schimabarea ordinii de redare a esantionului

Acum ca stim ca un esantion este doar o lista de numere care pot fi redate in orice ordine si stim si cum sa redam doar o anumita parte din esantion, putem incepe sa ne distram redand un esantion in ordine ‘gresita’.

Slicing Amen

Sa ne uitam putin la Amen Break si sa il taiem in 8 felii egale apoi sa le amestecam. Priveste diagrama: sus A) reprezinta graficul datelor din esantionul initial. Taierea lui in 8 bucati ne da B) - observi ca am colorat diferit fiecare dintre cele 8 felii pentru a le distinge mai usor. Deasupra poti vedea valorile de inceput si de sfarsit pentru fiecare felie. In fine, C) reprezinta una dintre re-aranjarile posibile pentru cele 8 felii. Putem reda aceste numere pentru a crea un nou beat. Sa privim codul care face acest lucru:

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

Alegem aleator o felie pentru redare folosind un numar aleator intre 0 si 7 (adu-ti aminte ca incepem numerotarea de la 0). Sonic Pi are o functie foarte utila pentru acest lucru: ‘rand_i(8)’. Memoram apoi acest index aleator in variabila ‘slice_idx’. Definim marimea feliei - ‘slice_size’ ca fiind 1/8 sau 0.125. Variabila ‘slice_size’ ne este utila pentru a converti ‘slice_idx’ intr-o valoare intre 0 si 1, ca sa o putem folosi pentru parametrul ‘start:’. Calculam pozitia de start ‘s’ inmultind ‘slice_idx’ cu ‘slice_size’. Calculam pozitia de final ‘f’ adaugand ‘slice_size’ la valoarea pozitiei de start ‘s’. Acum putem reda felia din esantion transmitand ‘s’ si ‘f’ ca valori pentru parametrii ‘start:’ si ‘finish:’ cand apelam ‘sample’. Inainte sa redam urmatoarea felie trebuie sa stim cat de mult trebuie sa dureze pauza, care trebuie sa fie la fel de lunga ca durata unei felii din esantion. Din fericire, Sonic Pi ne ofera functia ‘sample_duration’ care accepta aceiasi parametri ca ‘sample’ si returneaza durata. Apeland deci ‘sample_duration’ cu parametri ‘start:’ si ‘finish:’, putem afla durata unei felii de esantion. Introducem toate acestea intr-o bucla live ca sa putem alege in continuu noi felii aleatoare pentru redare.

Sa punem totul cap la cap

Sa punem cap la cap tot ce am vazut pana acum intr-un exemplu final care arata cum putem folosi o abordare asemanatoare pentru a combina beat-uri sectionate aleator (sliced) cu niste bas pentru a obtine punctul de pornire pentru o pista interesanta. Acum este randul tau - ia codul de mai jos si modifica-l cum iti place tie pentru a crea ceva nou…

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

- Programeaza un Sequencer probabilistic

Intr-un episod precedent am explorat randomizarea pentru a introduce varietate, surpriza si schimbare in interpretarile bazate pe programarea live. De exemplu, am ales la intamplare note dintr-o scala pentru a crea melodii fara sfarsit. Azi vom invata o tehnica noua care foloseste randomizarea pentru ritm - beat-uri probabilistice!

Probabilitati

Inainte sa incepem sa cream noi beat-uri si ritmuri de sintetizator, trebuie sa discutam putin despre bazele probabilitatilor. Poate suna putin complicat, chiar infricosator, dar este la fel de simplu ca a da cu zarul, serios! Cand iei un zar obisnuit cu 6 fete si il rostogolesti, ce se intampla de fapt? Ei bine, in primul rand vei obtine un 1, 2, 3, 4, 5 sau 6, fiecare dintre acestea avand aceeasi sansa sa apara. De fapt, tinand cont de faptul ca zarul are 6 fete, vei obtine in medie un 1 la fiecare 6 aruncari (daca arunci zarul de un numar de ori suficient de mare). Asta inseamana ca ai o sansa din sase sa abtii un 1. Putem simula datul cu zarul in Sonic Pi folosind functia ‘dice’. Sa dam cu zarul de 8 ori:

8.times do
  puts dice
  sleep 1
end

Observi cum in log apar valori intre 1 si 6, ca si cum am fi dat cu zarul.

Beat-uri aleatoare

Acum sa ne imaginam ca ai o toba si de fiecare data cand te pregatesti sa o lovesti dai cu zatul. Daca obtii 1, lovesti toba, iar daca obtii altceva, nu o lovesti. Acum ai o toba automata care merge cu probabilitatea 1/6! Sa ascultam sunetul obtinut:

live_loop :random_beat do
  sample :drum_snare_hard if dice == 1
  sleep 0.125
end

Sa parcurgem rapid fiecare linie ca sa ne asiguram ca totul este clar. Mai intai cream o noua bucla live numita ‘:random_beat’ care va repeta in continuu cele doua linii dintre ‘do’ si ‘end’. Prima dintre aceste linii este un apel ‘sample’ care va reda un sunet pre-inregistrat (‘:drum_snare_hard’ in cazul acesta). Aceasta linie are insa o conditie la sfarsit, introdusa de un ‘if’ (daca). Aceasta inseamna ca linia se va executa doar daca acea conditie care urmeaza dupa ‘if’ este indeplinita. Conditia in acest caz este ‘dice == 1’. Este apelata functia ‘dice’ care, asa cum am vazut, returneaza o valoare intre 1 si 6. Apoi folosim operatorul ‘==’ pentru a verifica daca aceasta valoare este ‘1’. Daca este ‘1’, atunci conditia este indeplinita (are valoarea ‘true’, adica adevarat) si este redat sunetul de toba mica, daca nu este ‘1’ conditia nu este indeplinita si instructiunea sunetul nu este redat. A doua linie introduce o pauza simpla de ‘0.125’ secunde inainte de a da din nou cu zarul.

Schimbarea probabilitatilor

Cei care ati jucat jocuri de tip RPG (role playing games) sunteti probabil familiari cu zarurile cu forme ciudate si cu numar diferit de fete. De exemplu, exista un zar in forma de tetraedru care are 4 fete, dar si zaruri cu 20 de fete in forma de icosaedru. Numarul de fete ale zarului schimba probabilitatea de a obtine un 1. Cu cat sunt mai putine fete, cu atat e mai probabil sa obtii un 1, iar cu cat sunt mai multe, cu atat este mai putin probabil. De exemplu, pentru un zar cu 4 fete ai 1 sansa din 4, iar pentru zarul cu 20 de fete ai 1 sansa din 20. Din fericire, Sonic Pi are o functie ‘one_in’ foarte la indemana pentru a descrie exact acest lucru. Sa ne jucam:

live_loop :different_probabilities do
  sample :drum_snare_hard if one_in(6)
  sleep 0.125
end

Incepe cu bucla live de mai sus si vei auzi ritmul aleator deja cunoscut. Nu opri insa codul care ruleaza. In schimb, modifica ‘6’ cu o valoare diferita, cum ar fi ‘2’ sau ‘20’ si apasa din nou butonul ‘Run’. Observi ca un numar mai mic inseamna ca sunetul de toba mica se va auzi mai des, iar un numar mai mare inseamna ca sunetul se va auzi mai rar. Acum creezi muzica folosind probabilitatile!

Combinarea probabilitatilor

Lucrurile pot deveni cu adevarat interesante cand combini mai multe esantioane care sunt redate cu probabilitati diferite. De exemplu:

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

Executa codul de mai sus si apoi schimba probabilitatile pentru a modifica ritmul. De asemenea, incerca sa schimbi esantioanele pentru a crea ceva cu totul diferit. De exemplu, schimba :drum_cymbal_closed cu :bass_hit_c pentru mai mult bas!

Ritmuri repetabile

In continuare, putem apela la vechiul nostru prieten ‘use_random_seed’ pentru a reseta sirul aleator dupa fiecare 8 iteratii pentru a crea un beat regulat. Scrie codul de mai jos pentru a auzi un ritm mai regulat care se repeta. Dupa ce se aude beat-ul, incearca sa schimbi valoarea de initializare (random seed) din 1000 in altceva. Observi ca numere diferite vor produce beat-uri diferite.

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

Un lucru pe care il fac de obicei cu acest tip de structura este sa vad ce valoare de initializare suna mai bine si sa o notez. In felul asta pot recrea usor ritmurile mele in viitor cand exersez sau interpretez live.

Sa punem totul cap la cap

In fine, putem adauga niste bas aleator pentru a crea un continut melodic placut. Putem folosi metoda probabilistica de redare a esantioanelor pe care tocmai am descoperit-o. Dar nu lasa lucrurile asa - modifica numerele si creeaza propria ta melodie folosind puterea probabilitatilor!

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

- Modulatia in amplitudine

Luna asta vom analiza in detaliu unul dintre cele mai puternice efecte audio ale Sonic Pi - ‘:slicer’. La sfarsitul acestui articol vei sti sa modifici volumul global al diferitelor parti din sunetul programat live in moduri noi foarte puternice. Asta iti va permita se creezi noi structuri ritmice si timbrale si sa iti largesti capacitatea de exprimare.

Modifica amplitudinea cu ‘:slicer’

Ce face de fapt efectul ‘:slicer’? Poti sa iti imaginezi ca cineva se joaca cu volumul la televizorul tau sau la amplificatorul audio. Sa aruncam o privire, dar mai intai sa ascultam murmurul produs de bucata asta de cod care foloseste sintetizatorul ‘:prophet’:

synth :prophet, note: :e1, release: 8, cutoff: 70
synth :prophet, note: :e1 + 4, release: 8, cutoff: 80

Acum, sa il trecem printr-un efect ‘:slicer’:


with_fx :slicer do
  synth :prophet, note: :e1, release: 8, cutoff: 70
  synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
end

Observa cum efectul slicer actioneaza ca si cand ar opri/porni sunetul intr-un ritm regulat. De asemenea, vei vedea ca ‘:slicer’ afecteaza toate sunetele generate intre blocurile ‘do’/’end’. Poti controla viteza cu care porneste si opreste sunetul cu parametrul ‘phase:’ care este o prescurtare de la durata fazei. Valoarea implicita este ‘0.25’ ceea ce inseamna de 4 ori pe secunda la BPM implicit de 60. Sa il facem mai rapid:

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

Acum, joaca-te cu diferite durate pentru ‘phase:’. Incearca valori mai mari sau mai mici. Vezi ce se intampla cand alegi o durata foarte scurta. De asemenea, incearca diferite sintetizatoare, cum ar fi ‘:beep’ sau ‘:dsaw’ si note diferite. Priveste diagrama urmatoare pentru a vedea cum schimba diferitele valori pentru ‘:phase’ numarul de schimbari de amplitudine intr-un beat.

Duratele fazei

Durata fazei este timpul pentru un ciclu pornit/oprit. Ca urmare, valori mai mici vor face efectul sa comute mai rapid decat valori mai mari. Valori cu care ai putea experimenta sunt 0.125, 0.25, 0.5 si 1.

Forma de unda de control

Implicit, efectul ‘:slicer’ foloseste o forma de unda dreptunghiulara pentru a modifica amplitudinea in timp. De acceea auzim sunetul o perioada, apoi imediat dispare, apoi apare din nou. Forma de unda dreptunghiulara este doar una dintre cele 4 care pot fi folosite de catre ‘:slicer’. Celelalte sunt tip dinti de fierastrau, triunghiulara si (co)sinusoidala. Priveste diagrama de mai jos pentru a vedea cum arata diecare. Putem sa si auzim cum suna fiecare. De exemplu, codul de mai jos foloseste forma de unda co(sinusoidala) pentru control. Observi ca sunetul nu se opreste/porneste brusc ci are un efect de fade out/fade in:

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

Joaca-te cu diferite forme de unda schimband parametrul ‘wave:’ la ‘0’ pentru dinti de fierastrau, ‘1’ pentru patrata, ‘2’ pentru triunghiulara si ‘3’ pentru sinusoidala. Observa de asemenea cum suna diferitele forme de unda cu valori diferite pentru ‘phase:’.

Fiecare dintre aceste forme de unda poate fi inversata folosind parametrul ‘invert_wave:’ care o oglindeste fata de axa y. De exemplu, pe parcursul unei singure faze unda dinti de fierastrau porneste in general de sus si coboara incet pentru ca apoi sa sara instantaneu din nou la valoarea maxima. Folosind ‘invert_wave: 1’, ea va porni de jos si va creste progresiv inainte de a reveni instantaneu la valoarea minima. In plus, forma de unda poate porni din diferite puncte, folosind parametrul ‘phase_offset:’ care trebuie sa aiba o valoare intre ‘0’ si ‘1’. Jucandu-te cu parametrii phase:, wave:, invert_wave: si phase_offset poti schimba semnificativ modul in care amplitudinea este modificata in timp.

Duratele fazelor

Stabilirea nivelului

Implicit, ‘:slicer’ comuta intre valorile ‘1’ (sunet la maximum) si ‘0’ (oprit complet) pentru amplitudine. Acestea pot fi schimbate folosind parametrii amp_min: si amp_max:. Poti folosi acesti parametri impreuna cu o unda sinusoidala pentru a crea un efect simplu de tremolo:

with_fx :slicer, amp_min: 0.25, amp_max: 0.75, wave: 3, phase: 0.25 do
  synth :saw, release: 8
end

Este ca si cum ai roti putin la stanga si la dreapta butonul de volum de la amplificatorul tau audio pentru ca taria sunetului sa oscileze putin.

Probabilitati

Una dintre caracteristicile importante ale efectului ‘:slicer’ este posibilitatea de a folosi probabilitatile pentru a alege daca activeaza sau nu modificarea de amplitudine. Inainte ca ‘:slicer’ sa inceapa o noua faza, el da cu zarul si pe baza rezultatului fie foloseste forma de unda selectata fie mentine amplitudinea la 0. Sa ascultam:

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

Observi ca acum avem un ritm interesant de impulsuri. Incearca sa setezi parametrul “probability:’ la o valoare intre ‘0’ si ‘1’. Valorile mai apropiate de 0 vor duce la pauze mai mari intre sunete deoarece probabilitatea ca sunetul sa fie redat este mult mai mica.

Un alt lucru de remarcat este ca sistemul de probabilitati din acest efect este la fel ca sistemul de randomizare accesibil prin intermediul functiilor ca ‘rand’ si ‘shuffle’. Ambele sunt complet deterministe. Aceasta inseamna ca de fiecare data cand apesi pe Run vei auzi exact acelasi ritm de impulsuri pentru o probabilitate data. Daca vrei sa schimbi acest lucru poti folosi parametrul ‘seed:’ pentru a selecta un punct de pornire diferit in secventa de numere aleatoare. Acest parametru functioneaza exact ca use_random_seed, dar afecteaza doar acest efect particular.

In fine, poti schimba pozitia de “repaus” a undei de control pentru cazul in care testul probabilistic esueaza (deci nu se initiaza modificarea amplitudinii conform formei de unda) de la ‘0’ la orice alta valoare, folosind parametrul ‘prob_pos:’:

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

Crearea de beat-uri folosind slicing

Un lucru cu adevarat amuzant este sa folosesti ‘:slicer’ pentru a cioparti un beat de toba:

with_fx :slicer, phase: 0.125 do
  sample :loop_mika
end

Acest lucru ne permite sa luam orice esantion si sa cream noi ritmuri, ceea ce este chiar distractiv. Totusi, un lucru de care trebuie sa tinem seama este ca tempo-ul esantionului trebuie sa fie acelasi cu BPM curent din Sonic Pi, altfel slicing-ul va suna total anapoda. De exemplu, incearca sa schimbi :loop_mika cu loop_amen pentru a auzi cat de rau suna cand tempo-urile nu coincid.

Schimbarea tempo-ului

Dupa cum am vazut, modificarea BPM implicit cu ‘use_bpm’ va faca ca toate pauzele sau duratele anvelopelor pentru esantioane sa creasca sau sa scada pentru a se potrivi cu beat-ul. Efectul ‘:slicer’ respecta aceeasi regula, parametrul ‘phase:’ fiind de fapt masurat in masuri, nu in secunde. Putem deci corecta problema de mai sus cu ‘loop_amen’ schimband BPM pentru a se potrivi cu cel al esantionului:

use_sample_bpm :loop_amen
with_fx :slicer, phase: 0.125 do
  sample :loop_amen
end

Sa punem totul cap la cap

Sa aplicam toate aceste idei intr-un exemplu final care foloseste doar efectul ‘:slicer’ pentru a crea o combinatie interesanta. Da-i drumul, modifica-l si transforma-l in propria ta piesa!

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

- Cinci tehnici de programare live

In tutorialul de luna aceasta vom vedea cum putem sa tratam Sonic Pi ca pe un instrument adevarat. Va trebui deci sa incepem sa ne gandim la cod intr-un mod complet diferit. Cei care programeaza live se gandesc la cod intr-un mod similar cu cel in care violonistul se gandeste la arcus. De fapt, asa cum violonistul poate aplica tehnici diferite de manuire a arcusului pentru a crea sunete diferite (miscari lungi si lente vs lovituri scurte si rapide), vom vedea ca Sonic Pi permite tehnici diferite de programare live dintre care vom analiza 5. La sfarsitul acestui tutorial vei putea incepe sa exersezi pentru propriile interpretari live.

1. Memorati scurtaturile de la tastatura (shortcuts)

Primul sfat pentru a putea programa live cu Sonic Pi este sa incepi sa folosesti shortcut-uri. De exemplu, in loc sa pierzi timp pretios ca sa iei mouse-ul, sa il muti deasupra butonului Run si sa faci click, poti apasa ‘Alt’ si ‘r’ in acelasi timp, ceea ce este mai rapid si iti tine degetele deasupra tastaturii, pregatite pentru ce ai de introdus. Poti descoperi care sunt scurtaturile pentru butoanele principale deplasand cursorul mouse-ului deasupra lor. Vezi sectiunea 10.2 a tutorialului inclus in program pentru lista completa de scurtaturi.

Cand interpretati, un lucru haios pe care il puteti face este sa adaugati un pic de stil prin miscarea mainilor cand apasati scurtaturile. De exemplu, este bine sa comunicati audientei cand va pregatiti sa faceti o schimbare - deci ornati putin miscarea cand apasati ‘Alt-r’ exact cum un chitarist ar face-o cand reda un acord de forta.

2. Stratificati manual sunetele

Acum puteti porni codul instantaneu cu ajutorul tastaturii si puteti folosi aceasta abilitate pentru a doua tehnica - stratificarea manuala a sunetelor. In loc sa ‘compuneti’ folosind o multime de apeluri ‘play’ si ‘sample’ separate de apeluri ‘sleep’ pentru pauze, vom avea un apel ‘play’ pe care il vom declansa manual folosind ‘Alt-r’. Sa incercam. Scrie codul de mai jos intr-un buffer nou:

synth :tb303, note: :e2 - 0, release: 12, cutoff: 90

Acum, apasa ‘Run’ si, in timp ce sunetul este redat, schimba codul pentru a cobori patru note, modificandu-l in:

synth :tb303, note: :e2 - 4, release: 12, cutoff: 90

Acum, apasa ‘Run’ din nou, pentru a auzi ambele sunete redate in acelasi timp. Aceasta deoarece apasarea butonului ‘Run’ in Sonic Pi duce la executarea codului imediat, fara a astepta ca sunetul dinainte sa se termine. Asta inseamna ca poti adauga manual cu usurinta noi straturi sunetului cu modificari mai mici sau mai mari intre doua lansari in executie. De exemplu, incearca sa schimbi atat parametrul ‘note:’ cat si ‘cutoff:’, apoi reporneste.

Poti incerca aceasta tehnica si cu esantioane abstracte lungi. De exemplu:

sample :ambi_lunar_land, rate: 1

Incearca sa pornesti esantionul apoi injumatateste de fiecare data parametrul ‘rate:’ inainte de a apasa din nou pe ‘Run’, de la ‘1’ la ‘0.5’ la ‘0.25’ la ‘0.125’ si apoi chiar la valori negative cum ar fi ‘-0.5’. Asterne straturile de sunet unul peste altul si vezi la ce poti ajunge. Apoi, incearca sa adaugi efecte.

Cand interpretezi, lucrul cu linii simple de cod in modul acesta inseamna ca audienta care ia prima data contact cu Sonic Pi are o buna sansa sa urmareasca ce faci si sa faca legatura intre codul pe care il citesc si sunetele pe care le aud.

3. Stapaneste buclele live

Cand lucrezi cu muzica mai ritmata, poate fi adesea dificil sa pornesti totul manual si sa pastrezi sincronizarea. De aceea, e mai bine sa sa folosesti ‘live_loop’. Aceasta asigura repetarea codului in timp ce iti da posibilitatea sa modifici codul pentru urmatoarea executie a buclei. De asemenea, se va executa in acelasi timp cu alte bucle live, ceea ce inseamna ca straturile de sunet vor fi sincronizate. Arunca o privire la sectiunea 9.2 din tutorial pentru mai multe informatii despre lucrul cu buclele live.

Cand interpretezi, tine minte sa folosesti parametrul ‘sync:’ al ‘live_loop’ pentru a permite revenirea dupa probleme de rulare care opresc bucla live din cauza unor erori. Daca ai deja parametrul ‘sync:’ legat de o alta bucla live valida, atunci poti sa remediezi cu usurinta eroarea si sa rulezi din nou codul pentru a reporni sunetul fara sa pierzi un beat.

4. Foloseste Mixerul principal

Unul dintre cele mai bine pastrate secrete ale Sonic Pi este ca are un mixer principal prin care trec toate sunetele. Mixerul are incorporate atat un filtru trece jos cat si unul trece sus, deci puteti face cu usurinta modificari globale asupra sunetului. Functionalitatile mixerului principal pot fi accesate folosind functia ‘set_mixer_control!’. De exemplu, in timp ce se executa o bucata de cod care produce sunete, introdu comanda de mai jos intr-un buffer gol si apasa ‘Run’:

set_mixer_control! lpf: 50

Dupa ce executi aceasta instructiune, tuturor sunetelor existente si viitoare li se va aplica un filtru trece jos si vor fi in consecinta mai inabusite. Retine ca aceasta inseamna ca valorile pe care le-am setat pentru mixer voi fi mentinute pana cand le schimbam din nou. Totusi, daca vrei, poti sa resetezi oricand mixerul la starea implicita cu ‘reset_mixer!’. Cativa dintre parametrii suportati in acest moment sunt: pre_amp:, lpf: hpf: si amp:. Pentru lista completa, vezi documentatia pentru set_mixer_control!.

Foloseste parametrii ‘*_slide’ ai mixerului pentru a face sa varieze una sau mai multe valori in timp. De exemplu, pentru a face ca filtrul trece jos sa coboare lin de la valoarea curenta la 30, foloseste:

set_mixer_control! lpf_slide: 16, lpf: 30

Poti apoi sa cresti rapid la o valoare mai ridicata cu:

set_mixer_control! lpf_slide: 1, lpf: 130

Cand interpretezi, este util sa pastrezi un buffer liber pentru a lucra cu mixerul in acest mod.

5. Exerseaza

Cea mai importanta tehnica pentru programarea live este exersarea. Caracteristica cea mai intalnita intre muzicienii profesionisti de toate tipurile este ca ei exerseaza cantatul la instrumentele lor - adesea multe ore pe zi. Exersarea este la fel de importanta pentru un programator live ca si pentru un chitarist. Repetitia permite degetelor tale sa memoreze anumite sabloane si modificari frecvente astfel incat sa le poti introduce de la tastatura si sa lucrezi cu ele mai fluent. Exersarea iti ofera de asemenea posibilitatea sa explorezi sunete si secvente de cod noi.

Cand interpretezi, vei descoperi ca iti va fi cu atat mai usor cu cat ai exersat mai mult. Exersarea iti va oferi de asemenea o experienta utila. Aceasta te va ajuta sa intelegi ce tipuri de modificari vor fi mai interesante si vor merge mai bine cu sunetele curente.

Sa punem totul cap la cap

Luna aceasta, in loc sa iti dau un exemplu final care combina toate elementele discutate, mai bine sa ne distram stabilind o provocare. Vezi daca poti sa petreci o saptamana exersand cate una dintre aceste tehnici in fiecare zi. De exemplu, intr-o zi exersezi lansarea manuala a sunetelor, in ziua urmatoare incerci niste bucle live simple, iar in urmatoare te joci cu mixerul principal. Apoi repeti. Nu te ingrijoar daca simti ca esti lent si neindemanatic la inceput - continua sa exersezi si fara sa iti dai seama vei ajuge sa programezi live in fata unei audiente reale.


- 8 Sfaturi pentru a exersa programarea live

Luna trecuta am aruncat o privire asupra a cinci tehnici importante pentru a stapani programarea live - cu alte cuvinte, am explorat cum am putea folosi Sonic Pi pentru a aborda programarea asa cum abordam un instrument muzical. Unul dintre cele mai importante concepte pe care le-am discutat a fost exersarea. Luna aceasta vom vedea mai in amanunt de ce este importanta exersarea in programarea live si cum ai putea incepe.

Exerseaza regulat

Cel mai important sfat este sa te asiguri ca exersezi regulat. De regula eu exersez cam 1-2 ore pe zi, dar 20 de minute sunt de ajuns pentru inceput. Putin si des ar trebui sa fie ceea ce urmaresti la inceput - deci daca nu reusesti decat 10 minute, este un inceput bun.

Sfatul nr 1 - incepe sa-ti creezi un program pentru exersare. Gaseste o ora din zi care iti convine si incearca sa exersezi cat de multe zile poti la acea ora. Dupa un timp vei ajunge sa astepti cu nerabdare sesiunea de practica programata.

Invata sa tastezi in orb

Daca privesti un muzician profesionist interpretand pe scena vei observa probabil cateva lucruri. In primul rand, cand canta el nu se uita la instrument. Degetele lui, bratele si corpul stiu pe ce clapa sa apese, ce coarda sa ciupeasca sau ce toba sa loveasca, fara ca ei sa trebuiasca sa se gandeasca la asta prea mult. Aceasta este cunoscuta drept “memoria muschilor” si desi suna ca un lucru pe care doar profesionistii il pot face - este acelasi lucru ca atunci cand ati invatat sa mergeti pe jos sau pe bicicleta - exersarea prin repetitie. Programatorii live folosesc memoria muschilor pentru a-si elibera mintea de nevoia de a se gandi unde sa isi miste degetele, astfel incat se pot concentra asupra muzicii. Aceasta se numeste tastare in orb - apasarea tastelor fara a fi nevoit sa privesti la tastatura.

Sfatul nr 2 - invata sa tastezi in orb. Exista multe aplicatii, site-uri web sau chiar jocuri care te pot ajuta sa faci asta. Gaseste ceva care iti place si insista pana cand poti sa scrii cod fara sa te uiti la tastatura.

Programeaza in picioare

Corpul unui muzician este adaptat pentru interpretarea la instrumentul pe care si l-a ales. De exemplu, un trompetist trebuie sa poata sufla puternic, un chitarist trebuie sa poata tine griful cu putere iar tobosarul trebuie sa poata lovi in continuu tobele pentru perioade lungi de timp. Dar unde este partea fizica in programarea live? La fel ca un DJ, un programator live de obicei interpreteaza in timp ce sta in picioare, uneori chiar dansand in timp ce scrie cod! Daca exersezi programarea live in timp ce stai asezat in fata biroului si apoi vei fi nevoit sa stai in picioare pentru o interpretare in fata audientei, schimbarea pozitiei ti se va parea dificila si frustranta.

Sfatul nr 3 - stai in picioare cand exersezi. Cel mai usor este sa folosesti un birou mai inalt la care se poate lucra in picioare. Daca nu ai unul acasa (cum este si cazul meu), exista cateva optiuni la indemana. Eu folosesc o masa de calcat care se potriveste destul de bine. Alta varianta ar fi sa pui niste carti sau cutii sub tastatura ca sa ajunga la inaltimea potrivita. Ai grija sa faci cateva miscari de incalzire inainte sa incepi sa exersezi si incearca sa dansezi putin in timpul sesiunii. Tine minte, nimeni nu te priveste, deci poti sa te distrezi si te vei simti mult mai natural pe scena.

Exerseaza pregatirea echipamentelor

Majoritatea instrumentelor muzicale necesita o parte de asamblare si reglaje inainte sa poti canta la ele. Daca nu esti cumva un star rock cu un autocar plin de tehnicieni dupa tine, va trebui sa iti pregatesti singur instrumentul inainte de interpretare. Adesea asta reprezinta o parte stresanta si care poate crea probleme. Un mod de a te pregati pentru acest lucru este sa incluzi partea de pregatire a echipamentelor in programul de exersare.

Sfatul nr 4 - trateaza pregatirea echipamentelor ca pe o parte importanta a exersarii. De exemplu, alege o cutie sau o geanta in care poti tine Raspberry Pi, tastatura si ce iti mai este necesar. Inainte de fiecare sesiune de repetitii, scoate componentele, conecteaza-le si porneste totul pana cand vezi Sonic Pi pe ecran, pregatit sa scoata sunete. Dupa ce termini repetitia, impacheteaza totul cu grija la loc. Aceasta iti va lua ceva timp la inceput, dar in curand vei fi capabil sa pui totul in functiune sau sa impachetezi foarte rapid, fara sa te mai gandesti cum se face asta.

Experimenteaza

Odata ce totul este pregatit si poti incepe sa creezi muzica, s-ar putea sa nu stii de unde sa incepi. O problema care apare adesea este ca poti sa stii cam ce sunete vrei sa produci, dar esti frustrat fiindca nu stii cum anume sa faci asta. Uneori s-ar putea chiar sa nu stii nici ce sunete vrei sa produci! Cel mai important este sa nu te ingrijorezi - acest lucru se intampla oricarui muzician - chiar daca exerseaza de mult timp. Este mult mai bine sa creezi sunete care nu iti plac decat sa nu creezi nimic.

Sfatul nr 5 - petrece suficient timp creand sunete si muzica chiar daca sunt nereusite. Fa-ti timp sa explorezi noi sunete si idei. Nu te ingrijora ca ar putea suna groaznic sau nu ar fi stilul pe care il cauti. Cand experimentezi in felul asta cresc sansele de a da peste un sunet sau o combinatie de sunete de care te vei indragosti! Chiar daca 99% dintre sunetele pe care le produci sunt aiurea, restul de 1% ar putea fi exact riff-ul sau introducerea pentru o noua piesa. Uita ce nu ti-a placut si retine doar restul. Acest lucru este foarte usor cand faci muzica folosind programarea - doar apesi pe ‘Save’!

Asculta codul

Multi muzicieni pot privi o partitura si sa “auda” muzica fara a fi nevoiti sa o cante. Aceasta abilitate este foarte utila si merita sa o folositi cand exersati programarea live. Este important sa intelegeti macar partial cum va suna bucata de cod. Nu e nevoie sa fiti capabili sa o auziti exact, dar e bine sa stiti macar daca va fi o bucata rapida, lenta, zgomotoasa, ritmica, melodica, aleatoare, etc. Scopul final este sa puteti reversa procesul - sa imaginati muzica in minte si sa stiti cum sa scrieti codul care o va crea. Acest lucru poate lua mult timp, dar odata ce veti stapani procesul, veti putea improviza pe scena ca sa va exprimati fluent ideile.

Sfatul nr 6 - scrie o bucata de cod in Sonic Pi si nu apasa pe ‘Run’. Incearca sa iti imaginezi ce sunet va produce. Apoi, apasa ‘Run’, asculta si gandeste-te ce s-a potrivit si ce nu cu ce ti-ai imaginat. Repeta acest exercitiu pana cand va deveni o parte naturala a modului tau de a programa. Cand repet am in mod normal o idee destul de clara despre cum va suna. Totusi, uneori poti fi surprins si atunci ma opresc si ma gandesc de ce suna altfel decat mi-am imaginat. De fiecare data cand se intampla acest lucru, invat noi trucuri care imi permit sa ma exprim muzical in noi moduri.

Inlatura orice te poate distrage

O problema uzuala cand exersezi este sa fii distras de alte lucruri. Sa exersezi este dificil si necesita disciplina indiferent ce fel de muzica creezi - ca este jazz sau clasica sau dance. Daca nu reusesti sa faci progrese in timpul repetitiei e foarte usor sa treci rapid la social media sau sa cauti ceva pe Internet. Daca ti-ai propus insa sa repeti 20 de minute, e important sa respecti acest lucru si sa petreci tot acest timp fiind cat poti de productiv.

Sfatul nr 7 - inainte de a incepe sa repeti inlatura tot ce te poate distrage. De exemplu, deconecteaza-te de la Internet, du-ti telefonul in alta camera si incearca sa exersezi intr-un loc linistit unde este putin probabil sa fii deranjat. Incearca sa te concentrezi pe crearea de muzica si te vei putea intoarce la celelalte lucruri cand termini.

Tine un jurnal al repetitiilor

Cand exersezi mintea ta poate fi inundata de idei noi si incitante - noi directii muzicale, noi sunete pe care sa le incerci, functii noi pe care sa le scrii etc. Aceste idei sunt adesea atat de interesante incat ai putea sa te opresti din ce faci ca sa incepi sa lucrezi la ceva nou. Aceasta este alta forma de a fi distras!

Sfatul nr 8 - tine un jurnal al repetitiilor langa tastatura. Cand ai o idee noua si interesanta, fa o pauza, noteaza-ti rapid ideea pe hartie, apoi continua cu ceea ce faceai. Vei putea sa te gandesti pe indelete si sa lucrezi la acea idee dupa ce termini de exersat.

Sa punem totul cap la cap

Incearca sa iti stabilesti un program de repetitii care sa includa cat mai multe dintre aceste idei. Fa sesiunile cat se poate de placute, dar fii constient ca unele dintre ele vor fi dificile si vei simti ca ai de muncit. Dar iti vei da seama ca a meritat cand vei produce prima ta piesa sau vei sustine prima interpretare live. Tine mine, repetitia este cheia succesului!


- Comprimarea/Intinderea esantioanelor

Cand cineva ia contact prima data cu Sonic PI, unul dintre primele lucruri pe care le descopera este cat de simplu este sa redai sunete pre-inregistrate folosind functia ‘sample’. De exemplu, poti reda in bucla un sunet de toba, sa auzi vocile unui cor sau chiar sa asculti niste efecte obtinute prin manipularea discurilor de vinil printr-o singura linie de cod. Totusi, sunt multi cei care nu realizeaza ca pot modifica viteza la care este redat esantionul pentru a obtine niste efecte interesante si a controla mai bine sunetul inregistrat. Deci, porneste Sonic Pi si hai sa incepem sa ne jucam cu viteza esantioanelor!

Incetinirea esantioanelor

Pentru a modifica viteza de redare a esantionului, trebuie sa folosim parametrul ‘rate:’

sample :guit_em9, rate: 1

Daca specificam valoarea ‘1’ pentru ‘rate:’, esantionul va fi redat la viteza normala. Daca vrem sa fie redat cu o viteza injumatatita, folosim valoarea ‘0.5’ pentru ‘rate:’:

sample :guit_em9, rate: 0.5

Observi ca aceasta va avea doua efecte. In primul rand esantionul va contine sunete mai joase si in al doilea rand redarea sa va dura de doua ori mai mult (vezi in bara laterala o explicatie pentru acest lucru). Putem alege valori din ce in ce mai mici pentru ‘rate:’, pana spre ‘0’, ‘0.25’ avand viteza un sfert din cea initiala, ‘0.1’ o zecime, etc. Incearca sa te joci cu niste valori mai joase si sa vezi cum sunetul e transforma intr-un huruit cu tonuri grave.

Redarea esantioanelor cu viteza marita

In afara de a face sunetul sa dureze mai mult si sa fie mai grav, putem sa il facem si mai scurt, dar mai acut, folosind valori mai mare pentru ‘rate:’. Sa ne jucam cu un sunet de toba de data asta. Mai intai, sa ascultam cum suna la viteza normala:

sample :loop_amen, rate: 1

Acum, sa il redam putin mai rapid:

sample :loop_amen, rate: 1.5

Ha! Tocmai am schimbat genul muzical din old-skool techno in jungle. Observi ca tonalitatea pentru fiecare bataie de toba este mai inalta si tot ritmul este mai rapid, Acum, incearca viteze chiar mai mari si vezi cat de scurt si inalt poti face sunetul de toba. De exemplu, daca folosesti ‘100’ pentru ‘rate:’, sunetul se transforma intr-un click!

Marsarier

Sunt sigur ca multi dintre voi va ganditi acum… “dar daca as folosi o valoare negativa pentru viteza?”. Buna intrebare! Sa ne gandim putin la acest lucru. Daca parametrul ‘rate:’ semnifica viteza cu care sunetul este redat, ‘1’ fiind viteza normala, ‘2’ fiind viteza dubla, ‘0.5’ viteza injumatatita, ‘-1’ trebuie sa insemne redare inversa! Sa incercam cu un sunet de toba. Mai intai, reda-l la viteza normala:

sample :elec_filt_snare, rate: 1

Acum, reda-l de la coada la cap:

sample :elec_filt_snare, rate: -1

Desigur, il poti reda invers cu viteza dubla folosind valoarea ‘-2’ sau cu viteza injumatatita folosind valoarea ‘-0.5’ pentru ‘rate:’. Acum joaca-te cu diferite viteze negative si distreaza-te. Este amuzant in special daca folosesti esantionul ‘:misc_burp’!

Esantion, Viteza si Tonalitate [Bara laterala]

Unul dintre efectele modificarii vitezei esantioanelor este ca o redare mai rapida produce sunete mai inalte, iar una mai lenta duce la sunete mai joase. Acest efect poate fi intalnit in viata de zi cu zi cand mergi cu bicicleta si treci pe langa un semafor cu semnalizare sonora - cand te apropii de sursa sunetului tonalitatea este ma inalta decat atunci cand te indepartezi - efectul Doppler. De ce se intampla asta?

Sa analizam un sunet simplu reprezentat ca o unda sinusoidala. Daca folosim un osciloscop pentru a vizualiza sunetul vom vedea ceva ca in figura A. Daca reprezentam un sunte mai inalt cu o octava, vom vedea figura B, iar cu o octava mai jos va arata ca in figura C. Observam ca undele pentru notele mai inalte sunt ai compacte, iar undele pentru notele mai joase sunt mai extinse.

Un esantion pentru un sunet reprezinta doar un set de numere (coordonate x, y) care atunci cand sunt afisate grafic redeseneaza curbele initiale. Vezi figura D unde fiecare cerc reprezinta o coordonata. Pentru a transforma aceste coordonate inapoi in sunet, computerul parcurge fiecare coordonata x si trimite valoarea y corespunzatoare la difuzoare. Interesant este ca viteza cu care computerul parcurge valorile pentru x nu trebuie sa fie aceeasi cu cea cu care au fost inregistrate. Deci, cand computerul parcurge valorile pentru x mai rapid decat la inregistrare, efectul va fi de inghesuire a cercurilor, ceea ce va duce la un sunet mai inalt. Sunetul va fi deasemenea mai scurt, deoarece vom parcurge aceste valori mai repede. Acest lucru este aratat in figura E.

Un ultim lucru pe care trebuie sa-l stii este ca un matematician numit Fourier a demonstrat ca fiecare sunet este de fapt format dintr-o multime de unde sinusoidale combinate. Ca urmare, cand comprimam sau extindem un sunet inregistrat, de fapt comprimam sau extindem in acelasi timp mai multe unde sinusoidale in modul descris anterior.

Modificarea tonalitatii

Asa cum am vazut, folosind o viteza de redare mai mare vom obtine un sunet cu o tonalitate mai inalta, iar o viteza mai mica va crea un sunet mai grav. O regula simpla spune ca dublarea vitezei va duce la un sunet cu o octava mai sus si invers, injumatatirea vitezei duce la un sunet cu o octava mai jos. Aceasta inseamna ca pentru esantioanele melodice redarea lor in paralel la viteza normala, dubla si injumatatita va suna chiar interesant:

sample :bass_trance_c, rate: 1
sample :bass_trance_c, rate: 2
sample :bass_trance_c, rate: 0.5

Totusi, ce ar trebui sa facem daca am dori doar sa schimbam viteza astfel incat sa crestem tonalitatea cu un semiton (cu o nota mai sus la pian)? Sonic Pi face acest lucru foarte usor folosind parametrul ‘rpitch:’:

sample :bass_trance_c
sample :bass_trance_c, rpitch: 3
sample :bass_trance_c, rpitch: 7

Daca arunci o privire la jurnalul din partea dreapta, vei observa ca o valoare de ‘3’ pentru ‘rpitch:’ corespunde unei viteze (‘rate:’) de 1.1892 iar o valoare rpitch: de 7 corespunde unui ‘rate:’ de 1.4983. In fine, putem chiar combina parametrii rate: si 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

Sa punem totul cap la cap

Sa aruncam o privire la o bucata simpla care combina aceste idei. Copiaza codul intr-un buffer gol, apasa play si asculta putin apoi foloseste-l ca punct de pornire pentru propria ta piesa. Vezi cat de distractiv este sa modifici viteza de redare a esantioanelor. Ca exercitiu suplimentar, incearca sa inregistrezi propriile sunete si joca-te cu viteza de redare pentru a vedea ce sunete interesante poti obtine.

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

- Sinteza aditiva

Acesta este primul dintr-o scurta serie de articole despre cum sa utilizezi Sonic Pi pentru design de sunet. Vom face un tur rapid al catorva tehnici pe care le ai la dispozitie pentru a crea propriile sunete unice. Prima tehnica pe care o vom analiza se numeste sinteza aditiva. Poate suna complicat, dar daca explicam putin fiecare cuvant, va fi foarte usor de inteles. In primul rand, aditiv inseamna o combinatie de element, iar sinteza inseamna crearea de sunete. Sinteza aditiva inseamna deci nici mai mult nici mai putin decat combinarea unor sunete existente pentru a crea unele noi. Aceasta tehnica de sinteza dateaza de foarte mult timp - de exemplu orgile din evul mediu aveau o multime de tuburi care sunau diferit si care puteau fi activate sau dezactivate folosind parghii. Tragand de parghia pentru un anumit tub, acesta era ‘adaugat in combinatie’ facand sunetul mai bogat si mai complex. Acum, sa vedem cum putem trage de aceste parghii cu Sonic Pi.

Combinatii simple

Sa incepem cu cel mai simplu sunet - unda sinusoidala pura:

synth :sine, note: :d3

Acum, sa vedem cum suna impreuna cu o unda rectangulara:

synth :sine, note: :d3
synth :square, note: :d3

Ai observat cum cele doua sunete s-au combinat intr-unul nou, mai bogat. Desigur, nu trebuie sa ne oprim aici, putem adauga cate sunete ne trebuie. Totusi, trebuie sa avem grija cate sunete suprapunem. Asa cum atunci cand amestecam vopsele pentru a obtine noi culori, daca punem prea multe culori vom obtine un fel de maroniu murdar, in mod asemanator, amestecarea prea multor sunete va crea un nou sunet lipsit de claritate.

Amestecarea

Sa adaugam ceva care va face sunetul mai viu. Am putea folosi o unda triunghiulara cu o octava mai sus (pentru un sunet viu inalt), dar sa o redam la o amplitudine de ‘0.4’ astfel incat doar va adauga ceva sunetului in loc sa-l acapareze cu totul:

synth :sine, note: :d3
synth :square, note: :d3
synth :tri, note: :d4, amp: 0.4

Acum, incearca sa creezi propriile tale sunete combinand 2 sau mai multe sintetizatoare in octave si cu amplitudini diferite. De asemenea, observa ca poti sa te joci cu fiecare dintre parametrii sintetizatoarelor pentru a modifica fiecare sunet sursa inainte de a-l adauga la mix pentru si mai multe combinatii de sunete.

Dezacordarea

Pana acum, cand am combinat diferite sintetizatoare, fie am folosit aceeasi inaltime, fie am schimbat octava. Cum ar suna daca nu am respecta octavele ci am alege o nota putin mai inalta sau mai joasa? Sa incercam:

detune = 0.7
synth :square, note: :e3
synth :square, note: :e3 + detune

Daca decalam cele 2 unde rectangulare cu 0.7 note putem auzi ceva ce probabil nu suna corect, ci dezacordat - o nota ‘gresita’. Totusi, pe masura ce ne apropiem de 0 va suna din ce in ce mai putin dezacordat, inaltimile celor doua unde devenind mai apropiate si mai asemanatoare. Incearca! Schimba valoarea pentru ‘detune:’ din ‘0.7’ in ‘0.5’ si asculta noul sunet. Incearca 0.2, 0.1, 0.05, 0. De fiecare data cand schimbi valoarea, asculta si incearca sa auzi cum se schimba sunetul. Observa ca un dezacord minor, cum ar fi cu ‘0.1’ produce un sunet ‘plin’, cele doua inaltimi usor diferite interactionand in moduri interesante, adesea surprinzatoare.

Unele dintre sintetizatoarele incluse au deja parametrul ‘detune:’ care face exact acelasi lucru pentru un singur sintetizator. Joaca-te cu parametrul detune: pentru :dsaw, :dpulse si :dtri.

Modelarea amplitudinii

O alta metoda prin care poti fasona sunetul este sa folosesti anvelope si parametri diferiti pentru fiecare sintetizator. De exemplu, aceasta iti va permite sa faci anumite parti ale sunetului mai percutante iar altele mai rasunatoare pentru un timp.

detune = 0.1
synth :square, note: :e1, release: 2
synth :square, note: :e1 + detune, amp: 2, release: 2
synth :gnoise, release: 2, amp: 1, cutoff: 60
synth :gnoise, release: 0.5, amp: 1, cutoff: 100
synth :noise, release: 0.2, amp: 1, cutoff: 90

In exemplul de mai sus am combinat un element zgomotos percutant alaturi de un huruit de fundal mai persistent. Am realizat asta in primul rand folosind doua sintetizatoare de zgomot cu valorii medii de cutoff (90 si 100) si timp de release scurt, alaturi de un zgomot cu release mai lung, dar cu o valoare de cutoff mai joasa (care face zgomotul mai putin clar si mai huruitor).

Sa punem totul cap la cap

Sa combinam toate aceste tehnici pentru a vedea daca putem folosi sinteza aditiva pentru a re-crea un sunet de clopot simplu. Am impartit acest exemplu in 4 sectiuni. In primul rand avem sectiunea ‘hit’ (lovitura) care reprezinta partea de atac a sunetului de clopot - deci utilizeaza o anvelopa scurta (de exemplu un ‘release:’ de aproximativ ‘0.1’). Apoi avem sectiunea mai lunga a sunetului de clopot in care folosesc o unda sinusoidala. Observi ca adesea cresc nota cu ‘12’ sau ‘24’, ceea ce reprezinta numarul de note din una, respectiv doua octave. Am mai adaugat si doua unde sinusoidale joase, pentru a da sunetului niste bass si profunzime. La final, am folosit ‘define’ pentru a ingloba codul intr-o functie pe care o pot apoi folosi pentru a canta o melodie. Incearca sa canti propria melodie si sa modifici continutul functiei ‘:bell’ pana cand obtii niste sunete super tari cu care sa te joci!

Canta o melodie cu noul tau clopot!

- Sinteza substractiva

Acesta este al doilea articol dintr-o serie referitoare la felul in care poti dolosi Sonic Pi pentru design de sunet. Luna trecuta am vorbit despre sinteza aditiva care inseamna pur si simplu redarea mai multor sunete in acelasi timp pentru ca crea un sunet combinat. De exemplu, putem combina diferite sintetizatoare, sau chiar sunete de la acelasi sintetizator la intaltimi diferite pentru a crea un sunet nou, complex, pornind de la ingrediente simple. Luna aceasta vom descoperi o noua tehnica, numita sinteza substractiva care inseamna ca pornim de la un sunet complex si extragem parti din el pentru a crea ceva nou. Aceasta tehnica este asociata de obicei cu sunetul sintetizatoarelor analogice din anii ‘60 si ‘70, dar si cu recenta revigorare a sintetizatoarelor analogice modulare prin standarde populare, cum ar fi Eurorack.

Desi suna ca o tehnica avansata si complicata, Sonic Pi face utilizarea ei surprinzator de facila. Sa intram direct in subiect.

Semnal sursa complex

Pentru ca un sunet sa fie potrivit pentru sinteza substractiva, trebuie sa fie destul de bogat si interesant. Asta nu inseamna ca avem nevoie de ceva extrem de complex - de fapt, e suficienta o unda standard dreptunghiulara (:square) sau triunghiulara (:saw):

synth :saw, note: :e2, release: 4

Observi ca sunetul este deja destul de interesant si contine mult frecvente diferite mai sus de ‘:e2’ (al doilea Mi la un pian) care se combina pentru a crea timbrul. Daca nu intelegi mare lucru din asta, incearca sa il compari cu un ‘:beep’:

synth :beep, note: :e2, release: 4

Cum sintetizatorul ‘:beep’ este o unda simpla sinusoidala, vei auzi un sunet mult mai pur, doar ‘:e2’ fara nimic din sunetele mai inalte si mai bazaitoare care se aud la ‘:saw’. Cu acest zumzet care face diferenta fata de o unda sinusoidala ne putem juca pentru a aplica sinteza substractiva.

Filtre

Odata ce avem sunetul brut, urmatorul pas este sa-l trecem printr-un filtru care il va modifica scotand sau atenuand anumite parti din el. Unul dintre filtrele cele mai folosite in sinteza substractiva este ceea ce se numeste filtrul trece-jos. Acesta permite componentelor joase din sunet sa treaca, dar le scoate sau le atenueaza pe cele inalte. Sonic Pi are un sistem de efecte (FX) foarte simplu dar foarte puternic care include un filtru trece-jos, numit ‘:lpf’ (low-pass filter). Sa ne jucam cu el:

with_fx :lpf, cutoff: 100 do
  synth :saw, note: :e2, release: 4
end

Daca asculti cu atentie vei observa ca o parte din zumzet a disparut. De fapt, toate frecventele din sunet mai sus de nota ‘100’ au fost reduse sau eliminate si au ramas in sunet doar cele mai joase. Incearca sa schimbi aceasta valoare de ‘cutoff:’ la o nota mai joasa, sa zicem ‘70’, apoi ‘50’ si apoi compara sunetele.

Desigur, ‘:lpf’ nu este singurul filtru pe care il poti folosi pentru a modifica semnalul sursa. Un alt efect important care poate fi aplicat in Sonic Pi este filtrul trece-sus, numit ‘:hpf’ (high pass filter). Acesta actioneaza invers decat ‘:lpf’ prin aceea ca lasa sa treaca partile inalte ale sunetului si le taie pe cele joase.

with_fx :hpf, cutoff: 90 do
  synth :saw, note: :e2, release: 4
end

Observi ca sunetul a devenit mai zumzaitor si mai strident prin eliminarea sunetelor de frecventa joasa. Joaca-te cu valoarea de cutoff - observa cum valorile mai joase lasa sa treaca mai mult din partile de bass originale, iar valorile mai mari fac sunetul mai “subtire” si mai linistit.

Low Pass Filter

Filtrul trece-jos este o parte foarte importanta a fiecarui instrument de sinteza substractiva si merita sa aruncam o privire mai atenta asupra felului in care functioneaza. Aceasta diagrama arata aceeasi unda sonora (sintetizatorul ‘:prophet’) filtrata in mod diferit. In partea de sus, sectiunea A arata unda audio fara filtrare. Se observa ca forma de unda este foarte ascutita si contine multe variatii bruste. Aceste unghiuri ascutite produce bazaitul de tonalitate inalta din sunet. Sectiunea B arata cum actioneaza filtrul trece-jos - se observa ca unda este mai putin ascutita si mai rotunjita fata de cea dinainte. Asta inseamna ca sunetul va avea mai putine frecvente inalte si va suna mai cuminte. Sectiunea C arata filtrul trece-jos cu o frecventa de taiere destul de coborata - asta inseamna ca si mai multe dintre frecventele inalte au fost eliminate iar unda va fi si mai rotunjita. In fine, poti observa ca marimea undei (care reprezinta amplitudinea), scade de la A la C. Sinteza substractiva functioneaza prin elimnarea de parti din semnal, ceea ce inseamna ca amplitudinea globala scade cu atat mai mult cu cat filtrarea este mai intensa.

Flitrarea modulata

Pana acum am produs sunete destul de statice. Cu alte cuvinte, sunetul nu se schimba in niciun fel pe toata durata sa. Uneori ai putea avea nevoie de o variatie a sunetului pentru a da viata timbrului. Un mod de a realiza acest lucru este sa aplici o filtrare modulata - adica sa schimbi parametrii filtrului in timp. Din fericire, Sonic Pi iti ofera unelte puternice pentru a manipula parametrii efectelor in timp. De exemplu, poti sa alegi un timp de variatie pentru fiecare parametru modulabil pentru a spune cat timp trebuie sa treaca pentru ca valoarea curenta sa se modifice liniar (slide) in valoarea tinta:

with_fx :lpf, cutoff: 50 do |fx|
  control fx, cutoff_slide: 3, cutoff: 130
  synth :prophet, note: :e2, sustain: 3.5
end
Sa vedem ce se petrece aici. Mai intai, pornim un flitru trece-jos cu o valoare foarte coborata (‘50’) pentru ‘cutoff:’. Totusi, prima linie se termina in mod ciudat cu ‘ fx ’. Aceasta reprezinta o parte optionala din sintaxa pentru ‘with_fx’ care iti permite sa numesti si sa controlezi direct efectele care ruleaza. Linia 2 face exact acest lucru si controleaza efectul stabilindu-i timpul de glisare (‘cutoff_slide’) la 3 si valoarea tinta pentru ‘cutoff:’ la ‘130’. Valoarea pentru ‘cutoff:’ pentru acest efect va creste liniar de la ‘50’ la ‘130’ pe durata a 3 batai. La final vom proni un semnal sursa de la un sintetizator pentru a putea auzi efectul filtrului trece-jos modulat.

Sa punem totul cap la cap

Acesta este doar un exemplu simplu pentru ce se poate obtine folosind filtrele pentru modificarea unor sunete. Incearca sa te joci cu multitudinea de efecte incluse in Sonic Pi si vezi ce sunete cool poti crea. Daca sunetul tau pare prea monoton, aminteste-ti ca poti modula parametrii sai pentru a ii da viata.

Sa incheiem creand o functie care va reda un sunet nou creat prin sinteza substractiva. Incearca sa-ti dai seama singur ce se petrece aici, iar daca esti un utilizator Sonic Pi avansat, spune-mi daca stii de ce am inglobat totul intr-un apel ‘at’ (te rog sa trimiti mesajul la @samaaron pe 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

- Creative coding in the classroom with Sonic Pi

(This article was published in issue 9 of the Hello World Magazine)

Code is one of the most creative media that humans have created. The initially obscure symbols of parentheses and lambdas are not just deeply rooted in science and mathematics, they are the closest we have managed to get to casting the same kind of magical spells as Gandalf and Harry Potter. I believe that this provides a powerful means of engagement in our learning spaces. Through the magic of code we are able to conjure up individually meaningful stories and learning experiences.

We are surrounded by magical experiences. From the sleight of hand of a stage magician making the ball disappear into thin air, to the wonder of seeing your favourite band perform on a big stage. It is these “wow” moments that inspire us to pick up a magic book and learn the French Drop or to start jamming power chords on an old guitar. How might we create similarly deep and lasting senses of wonder that will motivate people to practice and learn the fundamentals of programming?

Musical Engines and Notation

The histories of music and computers have been intricately woven together since the inception of computing machines, or “engines” as Charles Babbage’s powerful analytical engine was called. Back in 1842 the Mathematician Ada Lovelace, who worked very closely with Babbage, saw the creative potential of these engines. Whilst these first engines had originally been designed to accurately solve hard maths problems, Ada dreamt about making music with them:

”..the engine might compose elaborate and scientific pieces of music of any degree of complexity or extent.” Ada Lovelace, 1842.

Of course, today in 2019 much of our music, regardless of genre, has either been composed, produced or mastered with a digital computer. Ada’s dream came true. It is even possible to trace the history back even further. If you see coding as the art of writing sequences of special symbols that instruct a computer to do specific things, then musical composition is a very similar practice. In Western music, the symbols are black dots positioned on a stave of lines that tell the musician which notes to play and when. Intriguingly, if we trace the roots of Western music notation back to the Italian Benedictine monk, Guido d’Arezzo, we find that the dots and lines system that modern orchestras use is just one of a number of notation systems he worked on. Some of the others were much closer to what we might now see as code.

In education, magical meaningful experiences with computers and programming languages have been explored since the late ’60s. Computer education pioneers Seymour Papert, Marvin Minsky and Cynthia Solomon explored simple Lisp-based languages that moved pens over large pieces of paper. With just a few simple commands it was possible to program the computer to draw any picture. They even experimented by extending their Logo language from drawing to music. Papert wrote about learning through experiencing the reconstruction of knowledge rather than its transmission. Getting people to play with things directly was an important part of his group’s work.

Sonic Pi Performances

Programare live

Sonic Pi has been used to perform in a wide range of venues such as school halls, nightclubs, outdoor stages at musical festivals, college chapels and prestigious music venues. For example the amazing Convo project which brought 1000 children together in the Royal Albert Hall to perform an ambitious new composition by composer Charlotte Harding. The piece was written for traditional instruments, choirs, percussion and Sonic Pi code. The pop-artist Jylda also performed with Sonic Pi in the Sage Gateshead for the Thinking Digital Conference, where she created a unique live-coded improvised remix of her song Reeled.

Sonic Pi in the Royal Albert Hall Sonic Pi used as one of the instruments as part of Convo at the Royal Albert Hall. Photo credit: Pete Jones.

Live coding in the classroom

Sonic Pi is a code-based music creation and performance tool that builds on all of these ideas. Unlike the majority of computing education software, it is both simple enough to use for education and also powerful enough for professionals. It has been used to perform in international music festivals, used to compose in a range of styles from classical, EDM and heavy metal, and was even reviewed in the Rolling Stone magazine. It has a diverse community of over 1.5 million live coders with a variety of backgrounds all learning and sharing their ideas and thoughts through the medium of code. It is free to download for Mac, PC and Raspberry Pi and includes a friendly tutorial that assumes you know nothing about either code or music.

Sonic Pi was initially conceived as a response to the UK’s newly released Computing curriculum in 2014. The goal was to find a motivating and fun way to teach the fundamentals of programming. It turns out that there is a lot in common and it’s huge fun to explain sequencing as melody, iteration as rhythm, conditionals as musical variety. I developed the initial designs and first iterations of the platform with Carrie Anne Philbin, who brought a teacher’s perspective to the project. Since then, Sonic Pi has undergone iterative improvements thanks to the feedback gained from observing learners and collaborating directly with educators in the classroom. A core design philosophy was to never add a feature that couldn’t be easily taught to a 10 year old child. This meant that most ideas had to be heavily refined and reworked until they were simple enough. Making things simple whilst keeping them powerful continues to be the hardest part of the project.

In order to provide the magical motivation, Sonic Pi’s design was never limited to a pure focus on education. Ideally there would be famous musicians and performers using Sonic Pi as a standard instrument alongside guitars, drums, vocals, synths, violins, etc. These performers would then act as motivational role models demonstrating the creative potential of code. For this to be possible sufficient focus and effort therefore had to be placed on making it a powerful instrument whilst still keeping it simple enough for 10 year olds to pick up. In addition to educators, I also worked directly with a variety of different artists in classrooms, art galleries, studios and venues in the early stages of Sonic Pi’s development. This provided essential feedback which enabled Sonic Pi to grow and ultimately flourish as a tool for creative expression.

There were a number of exciting and unexpected side effects of this dual focus on education and professional musicians. Many of the features are beneficial to both groups. For example, a lot of effort has been put into making error messages more friendly and useful (rather than being a huge complicated mess of jargon). This turns out to be very useful when you write a bug while performing in front of thousands of people. Additionally, functionality such as playing studio quality audio samples, adding audio effects, providing access to live audio from the microphone all turn out to make the learning experience more fun, rewarding and ultimately meaningful.

The Sonic Pi community continues to grow and share amazing code compositions, lesson plans, musical algorithms, and much more. Much of this happens on our friendly forum in_thread (in-thread.sonic-pi.net) which is home to a very diverse group of people that includes educators, musicians, programmers, artists and makers. It is a real joy to see people learn to use code to express themselves in new ways and for that in turn to inspire others to do the same.

- Some fun capabilities

From a Computer Science perspective, Sonic Pi provides you with the building blocks to teach you the basics as found in the UK’s curriculum such as sequencing, iteration, conditionals, functions, data structures, algorithms, etc. However, it also builds on a number of important and relevant concepts which have become adopted in mainstream industry such as concurrency, events, pattern matching, distributed computing and determinism - all whilst keeping things simple enough to explain to a 10 year old child.

Getting started is as simple as:

play 70

A melody can be constructed with one more command, sleep:

play 72
sleep 0.5
play 75
sleep 0.5
play 79

In this example, we play the note 70 (roughly the 70th note on a piano), wait for 1 second, play note 72, wait for half a second and then play note 75. What’s interesting here is that with just two commands we have access to pretty much all of Western notation (which notes to play and when) and learners can code any melody they’ve ever heard. This leads to huge variety in expressive outcomes whilst focussing on the same computing concept: sequencing in this case.

Taking ideas from the professional music world, we can also play back any recorded sound. Sonic Pi can play any audio file on your computer but also has a number of sounds built-in to make things easy to get started:

sample :loop_amen

This code will play back the drum break which was a pillarstone to early hip-hop, Drum and Bass and Jungle. For example, a number of early hip-hop artists played this drum break back at half speed to give it a more laid-back feeling:

sample :loop_amen, rate: 0.5

In the 90s a number of music scenes burst out of new technology which enabled artists to take drum breaks like this apart and reassemble in a different order. For example:

sample :loop_amen

rand


- Cunostinte esentiale

Aceasta sectiune se va ocupa de cateva cunostinte foarte utile, esentiale de fapt pentru a beneficia din plin de experienta Sonic Pi.

Vom vedea cum poti sa folosesti multe dintre combinatiile de taste disponibile, cum sa impartasesti creatiile tale si cateva trucuri pentru interpretarea folosind Sonic Pi.


10.1 - Folosirea combinatiilor de taste

Sonic Pi este un instrument in aceeasi masura in care este si un mediu de programare. Combinatiile de taste pot face interpretarea folosind Sonic Pi mai eficienta si mai naturala, mai ales cand canti live in fata unei audiente.

Sonic Pi poate fi controlat aproape complet folosind tastatura. Pe masura ce devii mai familiar cu interpretarea folosind Sonic Pi, probabil vei incepe sa folosesti din ce in ce mai mult combinatiile de taste. Eu personal tastez fara sa privesc tastatura (iti recomand sa incerci si tu sa inveti) si ma simt frustrat cand trebuie sa intind mana dupa mouse, deoarece ma incetineste. Ca urmare, eu folosesc aceste combinatii de taste in mod regulat!

Ca urmare, daca inveti combinatiile de taste, vei invata sa folosesti eficient tastatura si vei programa live ca un profesionist cat de curand.

Totusi, nu incerca sa le inveti pe toate odata, incearca doar sa le memorezi pe cele pe care le utilizezi cel mai des si continua sa adaugi si altele pe parcurs.

Coerenta intre diferite platforme

Imagineaza-ti ca ai invatat sa canti la clarinet. Te-ai astepta ca toate clarinetele sa aiba clape si inele asemanatoare. Daca nu ar avea, ti-ar fi greu sa treci de la un clarinet la altul si ai fi foratat sa folosesti mereu aceeasi marca.

Din pacate, cele trei sisteme de operare cele mai raspandite (Linux, Mac OS X si Windows) vin cu propriile combinatii implicite pentru diferite actiuni cum ar fi pentru copy/paste, etc. Sonic Pi va incerca sa respecte aceste standarde. Totusi, prioritate are coerenta intre platforme in cadrul Sonic Pi, nu respectarea standardelor unei anumite platforme. Asta inseamna ca daca ai invatat combinatiile folosind Sonic Pi pe Raspberry Pi, poti trece la versiunea de Mac sau PC si sa te simti ca acasa.

Control si Meta

Notiunea de coerenta acopera si numele folosite pentru combinatiile de taste. In Sonic Pi folosim Control si Meta pentru a ne referi la 2 taste importante care fac parte din aceste combinatii. Pe toate platformele Control este la fel. In schimb, in Linux si Windows Meta este reprezentat de tasta Alt, iar pe Mac de tasta Command. Pentru coerenta vom folosi termenul Meta - tine minte sa il inlocuiesti cu tasta corespunzatoare pe sistemul tau de operare.

Abrevieri

Pentru a pastra lucrurile simple si usor de citit, vom folosi abrevierile C- pentru Control plus alta tasta si M- pentru Meta plus alta tasta. De exemplu, daca o combinatie cere sa apesi Meta si r, o vom nota ‘M-r’. - inseamna in acest caz “in acelasi timp cu”.

In continuare sunt cateva dintre combinatiile pe care le consider cele mai utile.

Oprirea si pornirea

In loc sa iei de fiecare data mouse-ul ca sa apesi pe butonul Run, poti apasa ‘M-r’. La fel, pentru a opri executia codului poti apasa ‘M-s’.

Personal sunt pierdut fara aceste combinatii de taste. De aceea iti recomand cu caldura sa te apleci putin asupra lor. Aceste scurtaturi functioneaza foarte bine si cand inveti sa tastezi fara sa privesti tastatura deoarece folosesc litere obisnuite si nu e nevoie sa-ti misti mana dupa mouse sau dupa tastele sageti.

Poti merge la inceputul liniei cu ‘C-a’, la sfarsit cu ‘C-e’, mai sus cu o linie cu ‘C-p’, mai jos cu o linie cu ‘C-n’, inainte cu un caracter cu ‘C-f’ si inapoi cu un caracter cu ‘C-b’. Poti sterge toate caracterele de la cursor pana la sfarsitul liniei cu ‘C-k’.

Cod mai ordonat

Pentru auto-alinierea codului apasa ‘M-m’.

Sistem de ajutor (help)

Pentru a activa/dezactiva sistemul de ajutor poti apasa ‘M-i’. O scurtatura mai utila este ‘C-i’ care va cauta cuvantul din spatele cursorului si va afisa documentatia aferenta daca il gaseste. Ajutor instantaneu!

Pentru lista completa arunca o privire la sectiunea 10.2 Tabel de combinatii de taste.


10.2 - Tabel de combinatii de taste

Ceea ce urmeaza este un rezumat al principalelor combinatii de taste disponibile in Sonic Pi. Vezi sectiunea 10.1 pentru explicatii.

Conventii

In aceasta lista folosim urmatoarele conventii (unde Meta este Alt pentru Windows/Linux sau Cmd pentru Mac):

‘C-a’ inseamna sa tii apasata tasta Control apoi sa apesi tasta a astfel incat sa fie ambele apasate simultan, apoi sa le eliberezi. ‘M-r’ inseamna sa tii apasata tasta Meta apoi sa apesi tasta r astfel incat sa fie ambele apasate simultan, apoi sa le eliberezi. ‘S-M-z’ inseamna sa tii apasata tasta Shift, apoi tasta Meta, apoi sa apesi tasta z astfel incat sa fie toate apasate simultan, apoi sa le eliberezi. ‘C-M-f’ inseamna sa tii apasata tasta Control, apoi tasta Meta, apoi sa apesi tasta f astfel incat sa fie toate apasate simultan, apoi sa le eliberezi.

Controlul aplicatiei principale

M-r - Executa codul (Run) M-s - Opreste codul (Stop) ‘M-i’ - Activeaza/dezactiveaza sistemul de ajutor (help) M-p - Activeaza/dezactiveaza optiunile M-{ - Comuta la buffer-ul din stanga M-} - Comuta la buffer-ul din dreapta M-+ - Creste dimensiunea textului in buffer-ul curent M-- - Micsoreaza dimensiunea textului in buffer-ul curent

Selectie/Copy/Paste

‘M-a’ - Selecteaza tot M-c - Copiaza selectia in memorie M-] - Copiaza selectia in memorie M-x - Muta selectia in memorie (cut) C-] - Muta selectia in memorie (cut) C-k - Muta in memorie (cut) totul pana la sfarsitul liniei M-v - Aduce din memorie (paste) in editor C-y - Aduce din memorie (paste) in editor ‘C-SPATIU’ - Trece in mod evidentiere. Comenzile de navigare vor actiona in zona evidentiata. Foloseste ‘C-g’ ca sa revii in modul normal.

Manipularea textului

‘M-m’ - Aliniaza tot textul Tab - Aliniaza linia sau selectia curenta (sau trece in modul auto-completare) C-l - Centreaza editorul M-/ - Transforma linia sau selectia curenta in comentariu/revine la text normal C-t - Inverseaza ordinea caracterelor M-u - Converteste urmatorul cuvant (sau selectie) la majuscule. M-l - Converteste urmatorul cuvant (sau selectie) la litere mici.

C-a - Merge la inceputul liniei C-e - Merge la sfarsitul liniei C-p - Merge la linia precedenta C-n - Merge la linia urmatoare C-f - Merge inainte un caracter C-b - Merge inapoi un caracter M-f - Merge inainte un cuvant M-b - Merge inapoi un cuvant C-M-n - Muta linia sau selectia in jos C-M-p - Muta linia sau selectia in sus S-M-u - Merge in sus 10 linii S-M-d - Merge in jos 10 linii M-< - Merge la inceputul buffer-ului M-> - Merge la sfarsitul buffer-ului

Stergerea

C-h - Sterge caracterul precedent C-d - Sterge caracterul urmator

Functii avansate ale editorului

C-i - Arata documentatia pentru cuvantul de la pozitia cursorului M-z - Undo (anuleaza ultima modificare) S-M-z - Redo (reface ultima modificare) C-g - Escape (Revine la modul anterior) S-M-f - Activeaza/dezactiveaza modul ecran complet S-M-b - Afiseaza/ascunde butoanele S-M-l - Afiseaza/ascunde jurnalul (log) S-M-m - Comuta intre modurile luminos/intunecat S-M-s - Salveaza continutul bufferului intr-un fisier S-M-o - Incarca dintr-un fisier continutul bufferului


10.3 - Impartasirea creatiilor

Sonic Pi inseamna si impartasirea creatiilor sau sa inveti de la altii.

Dupa ce vei invata cum sa programezi muzica, vei putea trasmite altora creatiile tale printr-un simplu email care contine codul. Te rog sa impartasesti si altora creatiile tale astfel incat ei sa poata invata de la tine si chiar sa foloseasca anumite parti intr-un aranjament nou.

Daca nu te-au decis inca in ce fel sa partajezi creatiile tale, iti recomand sa incarci codul pe GitHub, iar muzica pe SoundCloud. In felul acesta te vei adresa unei audiente foarte largi.

Cod -> GitHub

GitHub este un site pentru partajarea codui si pentru lucrul in comun. Este folosit atat de programatori profesionisti cat si de artisiti pentru a-si face cunoscuta munca sau pentru proiecte in comun. Cel mai simplu mode de a partaja o bucata de cod (chiar si o piesa neterminata) este sa creezi un Gist. Un Gist reprezinta o cale facile de a-ti incarca codul astfel incat altii sa-l poata vedea, copia si partaja.

Audio -> SoundCloud

O alta cale de a impartasi cu altii creatiile tale este sa inregistrezi sunetul si sa il incarci pe SoundCloud. Odata ce ai incarcat o piesa, alti utilizatori vor putea sa o asculte si sa discute pe marginea ei. Iti recomand sa treci in descrierea piesei si un link catre un Gist care contine codul.

Pentru a inregistra o piesa, apasa pe butonul ‘Rec. Apasa ‘Run’ in cazul in care codul nu ruleaza deja. Cand ai terminat de inregistrat, apasa din nou butonul ‘Rec’ (care clipeste acum) si ti se va cere un nume pentru fisier. Inregistrarea va fi salvata ca fisier WAV, care poate fi modificat sau convertit in MP3 folosind unul dintre programele disponibile, multe gratuite. Poti incearca Audacity, de exemplu.

Speranta

Te incurajez sa-ti impartasesti creatiile si sper ca vom invata unii de la altii noi trucuri cu Sonic Pi. Sunt foarte curios sa vad ce vei avea sa ne arati.


10.4 - Interpretarea

Unul dintre cele mai mari avantaje ale Sonic Pi este ca iti permite sa folosesti programarea ca pe un instrument muzical. Asta inseamna ca scrierea de cod live poate fi vazuta ca o noua metoda de a interpreta muzica in fata audientei.

Numim asta Programare live.

Arata imaginea de pe ecran

Iti recomand sa arati imaginea de pe ecran atunci cand programezi live. Altfel ar fi ca si cand ai canta la chitara ascunzandu-ti degetele si coardele. Cand exersez acasa folosesc un Raspberry Pi si un mini proiector ca sa vad imaginea pe peretele din living. Poti sa folosesti televizorul sau un proiector de la scoala sau de la birou ca sa arati imaginea. Incearca asta, e foarte distractiv.

Creeaza o formatie

Don’t just play on your own - form a live coding band! It’s a lot of fun jamming with others. One person could do beats, another ambient background, etc. Use the live_audio functionality to combine code with traditional instruments such as a guitar or a microphone.

See what interesting combinations of sounds you can create with code.

TOPLAP

Programarea live nu este ceva complet nou, cateva persoane fac deja aste de cativa ani folosind de regula sisteme personalizate pe care si le-au construit singuri. Poti descoperi mai multe despre altii care practica programarea live si sistemele lor la TOPLAP.

Algorave

Un alt loc in care poti afla mai multe despre lumea programarii live este Algorave. Aici poti afla totul despre o ramura a programarii live specializata pe crearea de muzica in cluburi.


- Minecraft Pi

Sonic Pi suporta acum un API simplu pentru a interactiona cu Minecraft Pi - versiunea speciala a Minecraft care este instalata implicita pe sistemul de operare Raspbian (bazat pe Linux) pentru Raspberry Pi.

Nu este nevoie sa importi biblioteci

Integrarea cu Minecraft Pi a fost gandita sa fie extrem de simplu de utilizat. Tot ce trebuie sa faci este sa pornesti Minecraft Pi si sa creezi o lume. Apoi poti folosi functiile ‘mc_*’ la fel cum folosesti ‘play’ sau ‘synth’. Nu e nevoie sa importi nimic sau sa instalezi vreo bibilioteca de functii - totul este inclus si poate fi pornit imediat.

Conectarea automata

Interfata de programare (API) pentru Minecraft Pi se ocupa de conectarea la aplicatia Minecraft Pi. Asta inseamna ca nu trebuie sa-ti mai bati tu capul cu asta. Daca incerci sa folosesti API-ul cand Minecraft Pi nu este pornit, Sonic Pi te va informa politicos despre acest lucru. La fel, daca inchizi Minecraft Pi in timp ce inca ruleaza un ‘live_loop’ care foloseste API-ul, bucla se va opri si iti va spune frumos ca nu poate sa se conecteze. Pentru a te reconecta, trebuie doar sa pornesti Minecraft Pi si Sonic Pi va detecta acest lucru automat si va reface conexiunea.

Facut pentru programarea live

API-ul pentru Minecraft Pi este facut sa mearga de la sine cu buclele live. Asta inseamna ca este posibil sa sincronizezi modificarile din lumea Minecraft Pi cu modificarile sunetelor din Sonic Pi. Poti obtine instantaneu videoclipuri muzicale bazate pe Minecraft! Tine cont totusi ca Minecraft Pi este un program inca in versiune alfa si este cunoscut pentru faptul ca mai are buguri. Daca intampini probleme, reporneste Minecraft Pi si continua de unde ai ramas. Functia de reconectare automata din Sonic Pi se va ocupa de restul.

Este nevoie de un Raspberry Pi cel putin versiunea 2.0

Este recomandat sa folosesti macar un Raspberry Pi 2 daca vrei sa rulezi atat Sonic Pi cat si Minecraft in acelasi timp, mai ales daca vrei sa folosesti partea de sunet din Sonic Pi.

Suportul pentru API

In aceasta faza Sonic Pi ofera suport pentru modificari de baza legate de blocuri sau de jucator, asa cum sunt descrise in sectiunea 11.1. Suportul pentru functii care se executa cand actiunile jucatorului genereaza anumite evenimente este planificat pentru o versiune urmatoare.


11.1 - Functii de baza din API-ul pentru Minecraft Pi

In acest moment Sonic Pi ofera suport pentru urmatoarele interactiuni cu Minecraft Pi:

Afisarea de mesaje in fereastra de chat Modificarea pozitiei jucatorului Aflarea pozitiei jucatorului Modificarea blocului aflat la anumite coordonate Aflarea tipului blocului aflat la anumite coordonate

Sa le analizam pe rand.

Afisarea de mesaje in fereastra de chat

Sa vedem cat de usor este sa controlezi Minecraft Pi folosind Sonic Pi. Mai intai asigura-te ca atat Minecraft Pi cat si Sonic Pi sunt pornite si ca ai intrat intr-o lume Minecraft si poti sa te deplasezi in interiorul ei.

Intr-un buffer gol din Sonic Pi introdu urmatorul cod:

mc_message "Hello from Sonic Pi"

Cand apesi pe Run vei vedea mesajul tau aparand in fereastra Minecraft. Felicitari, ai scris prima linie de cod pentru Minecraft! A fost simplu, nu?

Modificarea pozitiei jucatorului

Acum sa incercam o mica magie. Sa ne teleportam undeva. Incearca asta:

mc_teleport 50, 50, 50

Apasa pe Run si … minune! Ai fost teleportat instantaneu intr-un nou loc. Cel mai probabul era undeva in vazduh si ai cazut intre timp pe sol sau in apa. Acum sa vedem ce reprezinta numerele astea: 50, 50, 50. Sunt coordonatele locului in care incerci sa te teleportezi. Sa discutam putin despre ce inseamna coordonatele si cum functioneaza, deoarece sunt foarte importante pentru programarea in Minecraft.

Coordonate

Sa ne imaginam o harta a piratilor cu un ‘X’ care marcheaza locul in care se afla o comoara. Pozitia exacta a ‘X’-ului poate fi descrisa cu doua numere - cat de departe este de marginea din stanga si cat de departe de marginea de jos. De exemplu: ‘10 cm’ la dreapta si ‘8 cm’ in sus. Aceste doua numere, ‘10’ si ‘8’ sunt coordonatele. Poti sa-ti imaginezi usor cum ai descrie pozitiile altor cufere folosind alte perechi de numere. Poate un cufar cu mult aur se afla la ‘2’ la dreapta si ‘9’ in sus…

In Minecraft doua numere nu sunt suficiente. Trebuie sa stim si inaltimea la care ne aflam, deci avem nevoie de trei numere:

Cat de departe pe directia stanga-dreapta: ‘x’ Cat de departe pe directia inainte-inapoi: ‘z’ Cat de sus ne aflam in lume: ‘y’

Inca un lucru: de obicei trecem aceste coordonate in ordinea asta - ‘x’, ‘y’, ‘z’.

Aflarea coordonatelor curente

Sa ne jucam putin cu coordonatele. Mergi intr-un loc dragut in lumea Minecraft si apoi revino la fereastra Sonic Pi. Introdu textul asta:

puts mc_location

Cand vei apasa pe butonul Run vei vedea coordonatele pozitiei curente afisate in fereastra jurnal. Priveste-le, apoi deplaseaza-te in lumea Minecraft si incearca din nou. Vei observa cum coordonatele s-au schimbat. Iti recomand sa repeti de cateva ori testul asta - te deplasezi putin in lumea Minecraft, vezi care sunt coordonatele, apoi reiei. Fa asta pana cand incepi sa simti in ce fel se schimba coordonatele atunci cand te deplasezi. Odata ce ai inteles cum functioneaza coordonatele, programarea cu API-ul Minecraft va fi floare la ureche.

Sa construim!

Acum ca stii sa afli pozitia curenta si sa te teleportezi folosind coordonatele, ai toate uneltele necesare pentru a incepe sa construiesti diferite lucruri in Minecraft prin programare. Sa spunem ca vrei ca blocul de la coordonatele 40, 50, 60 sa fie din sticla. E foarte usor:

mc_set_block :glass, 40, 50, 60

Ha, ha, a fost chiar usor. Ca sa vezi ce-ai mesterit teleporteaza-te in apropiere si arunca o privire:

mc_teleport 35, 50, 60

Acum intoarce-te si ar trebui sa vezi blocul de sticla! Incearca sa-l transformi in diamant:

mc_set_block :diamond, 40, 50, 60

Daca te uitai in directia potrivita ai vazut chiar cum se schimba in fata ochilor tai! Acesta este inceputul unei aventuri incitante…

Sa aruncam o privire asupra blocurilor

Sa mai vedem un singur lucru inainte de a trece la ceva mai complicat. Avand un set de coordonate putem cere Minecraft sa ne spuna ce tip de bloc se afla acolo. Sa incercam cu blocul de diamant pe care tocmai l-ai creat:

puts mc_get_block 40, 50, 60

Da! Este ‘:diamond’ (diamant). Incearca sa-l transformi iar in sticla si intreaba din nou. A raspuns ‘:glass’ (sticla)? Sunt sigur ca da :)

Tipurile de blocuri disponibile

Inainte sa te dezlantui programand in Minecraft Pi, ai putea considera utila lista aceasta cu tipurile de blocuri disponibile:

    :air
    :stone
    :grass
    :dirt
    :cobblestone
    :wood_plank
    :sapling
    :bedrock
    :water_flowing
    :water
    :water_stationary
    :lava_flowing
    :lava
    :lava_stationary
    :sand
    :gravel
    :gold_ore
    :iron_ore
    :coal_ore
    :wood
    :leaves
    :glass
    :lapis
    :lapis_lazuli_block
    :sandstone
    :bed
    :cobweb
    :grass_tall
    :flower_yellow
    :flower_cyan
    :mushroom_brown
    :mushroom_red
    :gold_block
    :gold
    :iron_block
    :iron
    :stone_slab_double
    :stone_slab
    :brick
    :brick_block
    :tnt
    :bookshelf
    :moss_stone
    :obsidian
    :torch
    :fire
    :stairs_wood
    :chest
    :diamond_ore
    :diamond_block
    :diamond
    :crafting_table
    :farmland
    :furnace_inactive
    :furnace_active
    :door_wood
    :ladder
    :stairs_cobblestone
    :door_iron
    :redstone_ore
    :snow
    :ice
    :snow_block
    :cactus
    :clay
    :sugar_cane
    :fence
    :glowstone_block
    :bedrock_invisible
    :stone_brick
    :glass_pane
    :melon
    :fence_gate
    :glowing_obsidian
    :nether_reactor_core