Bienvenue à Sonic Pi. Heureusement vous êtes excité pour commencer à faire des sons délirants comme je le suis pour vous le montrer. Ça va être réellement un parcours amusant où vous allez tout apprendre de la musique, de la synthèse, de la programmation, de l’interprétation et plus encore.
Mais attendez, comme je suis impoli ! Je me présente. Je suis Sam Aaron - le gars qui a créé Sonic Pi. Vous pouvez me joindre à @samaaron sur Twitter et je serai plus qu’heureux de vous saluer. Vous pourriez aussi être intéressé par mon orchestre “Live Coding” Meta-eX où j’interprète de la musique avec du code devant un public. Vous pouvez trouver un de mes morceaux Meta-eX dans les exemples.
Si vous avez des observations ou des idées pour améliorer Sonic Pi - Faîtes m’en part s’il vous plait - les retours sont tellement utiles. Vous ne le savez probablement pas, mais votre idée pourrait être la prochaine fonctionnalité importante !
Finalement, ce tutoriel est divisé en sections groupées par catégories. Même si je l’ai écrit pour avoir une progression d’apprentissage facile du début jusqu’à la fin, sentez-vous vraiment libre de plonger dans l’une ou l’autre section comme cela vous convient. Si vous pensez qu’il manque quelque chose, n’hésitez pas à me le faire savoir et je le prendrai en compte dans une prochaine version.
OK, démarrons…
Un des aspects les plus passionnants de Sonic Pi est qu’il vous permet d’écrire et de modifier du code en “live” pour faire de la musique, juste comme si vous jouiez de la guitare. Cela veut dire qu’au moyen de quelque expérience, vous pouvez prendre Sonic PI sur scène et jouez avec.
Avant que vous ne plongiez dans les détails réels du fonctionnement de Sonic Pi dans la suite de ce tutoriel, j’aimerais vous faire part d’une expérience montrant à quoi ressemble le code en “live”. Ne vous inquiétez pas si vous ne comprenez pas beaucoup ou rien de ceci. Essayez juste de rester assis sur votre siège et de profiter…
Démarrons, copiez le code suivant dans un “buffer” libre :
live_loop :flibble do
sample :bd_haus, rate: 1
sleep 0.5
end
Maintenant, pressez le bouton Run
et vous entendrez un joli battement de
grosse caisse. Si vous souhaitez arrêter le son à un moment quelconque,
pressez simplement le bouton Stop
. Plutôt, ne le pressez pas encore…
A la place, suivez les étapes suivantes :
sleep
de 0.5
à quelque chose plus élevé comme 1
Run
Ok, c’était assez simple. Ajoutons quelque chose au mixage. Au dessus de
sample :bd_haus
ajoutez la ligne sample :ambi_choir, rate: 0.3
. Votre
code devrait ressembler à ceci :
live_loop :flibble do
sample :ambi_choir, rate: 0.3
sample :bd_haus, rate: 1
sleep 1
end
Maintenant, exécutez-le. Changez les “rates” - Que se passe-t-il lorsque
vous utilisez des valeurs élevées ou des valeurs négatives ? Regardez ce
qui se passe quand vous changez légèrement la valeur de rate:
pour
l’échantillon :ambi_choir
(disons 0.29). Que se passe-t-il lorsque vous
choisissez une valeur véritablement petite de sleep
? Regardez si vous
arrivez à le faire aller si vite au point que votre ordinateur s’arrêtera
avec une erreur parce que ne pouvant plus continuer comme cela (si cela arrive,
choisissez juste une durée sleep
plus grande et pressez Run
à nouveau).
Essayez de commenter une des lignes sample
en ajoutant un #
au début :
live_loop :flibble do
sample :ambi_choir, rate: 0.3
# sample :bd_haus, rate: 1
sleep 1
end
Remarquez comment cela indique à l’ordinateur de l’ignorer, ainsi nous ne l’entendons pas. On l’appelle commentaire. Dans Sonic Pi, nous pouvons utilisez des commentaires pour enlever ou additionner des choses au mixage.
Finalement, je vous laisse avec quelque chose de sympa à jouer. Prenez le code ci-dessous et copiez-le dans un autre “buffer”. Maintenant essayez de le comprendre bien plus que de voir qu’il y a deux boucles - ainsi deux choses marchent en même temps. Maintenant, faites ce que vous faites le mieux - expérimenter et jouez. Voici quelques suggestions :
rate:
pour entendre changer
le son de l’échantillon.sleep
et découvrez que les 2 boucles
peuvent tourner à différentes cadences.#
) et apprécier
le son de la guitare joué en fond.mix:
avec des nombres
entre 0
(pas dans le mixage) et 1
(entièrement dans le mixage).Rappelez-vous de presser Run
et vous entendrez le changement la fois
suivante où la boucle tournera. Si vous êtes dans le pétrin, ne vous
inquiétez pas - pressez Stop
, effacez le code dans le “buffer”,
collez une copie originale et vous serez prêt à improviser à nouveau.
En faisant des fautes, c’est ainsi que vous apprendrez le plus vite…
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
Maintenant, continuez à jouer et à expérimenter jusqu’à ce que votre curiosité sur comment ça fonctionne s’avive réellement et vous commencerez à vous demander quoi d’autre puis-je faire avec ceci. Vous êtes maintenant prêt à lire le reste du tutoriel.
Aussi, qu’attendez-vous…
Sonic Pi a une interface très simple pour coder de la musique. Passons
un peu de temps à l’explorer.
Ces boutons roses sont les principaux contrôles pour démarrer et arrêter les sons. Il y a le bouton Run pour exécuter le code présent dans l’éditeur, Stop pour arrêter tous les codes en cours d’exécution, Save pour sauvegarder le code dans un fichier externe et Record pour créer un enregistrement du son (un fichier WAV) en cours de jeu.
Ces boutons oranges vous permettent de piloter l’éditeur de code. Les boutons Size + et Size - vous permettent d’agrandir ou de rétrécir le texte. Le bouton Align vous arrangera votre code pour lui donner une présentation plus professionnelle.
Ces boutons bleus vous donnent accès à l’information, à l’aide et aux préférences. Le bouton Info ouvre la fenêtre d’information qui contient de l’information sur Sonic Pi lui-même - le noyau de l’équipe, l’historique, les contributeurs, et la communauté. Le bouton Help active le système d’aide (G) et le bouton Prefs active la fenêtre des préférences qui vous permet de contrôler quelques paramètres systèmes basiques.
C’est une zone dans laquelle vous écrirez votre code et composerez / interpréterez de la musique. C’est un simple éditeur de texte où vous pourrez écrire votre code, l’effacer, couper et coller, etc. Pensez à lui comme à une version très basique de Word ou de Google Docs. L’éditeur coloriera automatiquement les mots selon leur signification dans le code. Ceci peut paraître étrange au début, mais vous le trouverez vite très utile. Par exemple, vous saurez que quelque chose est un nombre parce qu’elle sera bleue.
Sonic Pi supporte quelques préférences ajustables qui peuvent être accédées en pressant le bouton Prefs à droite des boutons Info et Help. Cela activera l’affichage du panneau des préférences qui inclut un nombre d’options modifiables. Par exemple pour forcer le mode mono, inverser la stéréo, activer le mode verbeux de la trace et aussi régler un curseur de volume et le sélecteur audio du Raspberry Pi (par défaut, il est sur “auto”. Si vous n’entendez plus le son de votre Pi en étant branchés sur la prise jack, modifiez ce paramètre).
Quand vous exécutez votre code, l’information sur ce que le programme est en train de faire est affichée dans le visualisateur de la trace. Par défaut, vous verrez un message pour chaque son que vous créez avec l’heure exacte à laquelle le son a été déclenché. C’est très utile pour déboguer votre code et comprendre ce qu’il fait.
Finalement, un des aspects les plus importants de l’interface de Sonic Pi est le système d’aide qui apparaît au bas de la fenêtre. Il peut être activé ou désactivé en cliquant sur le bouton Help bleu. Le système d’aide contient de l’aide et de l’information sur tous les aspects de Sonic Pi, y compris ce tutoriel, une liste des synthétiseurs, des échantillons (“samples”), des exemples, et des effets (“FX”) disponibles, et une liste complète de toutes les fonctions que Sonic Pi fournit pour coder de la musique.
Sonic Pi vous encourage à apprendre à la fois sur la programmation et sur la musique au travers du jeu et de l’expérimentation. La plus importante chose est que vous vous amusiez, et avant que vous vous en rendiez compte, vous aurez appris comment coder, composer et interpréter sans le faire exprès.
Alors que nous abordons ce sujet, laissez-moi vous donner un petit conseil. J’ai appris pendant des années à coder de la musique en “live” - il n’y a pas de fautes, seulement des opportunités. C’est ce que j’ai souvent entendu à propos du jazz mais cela fonctionne aussi avec le codage en “live”. Peu importe votre niveau d’expérience - du débutant complet jusqu’à “l’algoraver” (codeur de musique) chevronné, vous exécuterez un jour un code qui aura une sortie totalement inattendue. Cela pourrait sonner extrêmement “cool” - auquel cas continuez avec. Toutefois, cela pourrait aussi sonner discordant et à côté de la plaque. Peu importe ce qui se passe - ce qui importe est ce que vous allez faire avec ensuite. Prenez le son, manipulez-le et transformez-le en quelque chose de génial. Le public deviendra déchaîné.
Quand vous apprenez, il est tentant de vouloir faire des choses étonnantes immédiatement. Cependant, conservez l’idée et voyez-la comme un but distant à atteindre plus tard. Pour l’instant, pensez à la chose la plus simple que vous pourriez écrire qui serait amusante et gratifiante, c’est un petit pas vers la chose étonnante que vous avez en tête. Une fois que vous avez l’éclairage sur cette simple étape, essayez de la construire, jouez avec et pensez aux nouvelles idées que cela vous donne. Sous peu, vous serez trop occupé à vous amuser et à faire de réels progrès.
Assurez-vous simplement de partager votre travail avec les autres !
OK, assez d’introduction, plongeons dans les sons.
Dans cette section, nous allons couvrir les bases du déclenchement et de la manipulation des “synths”. “Synth” ou “synthé” sont les abréviations de synthétiseur, lequel est un mot fantaisiste pour quelque chose qui crée des sons. Typiquement, les synthétiseurs sont assez compliqués à utiliser - particulièrement les synthés analogiques avec beaucoup de “patches” et de modules à connecter. Toutefois, Sonic Pi vous offre beaucoup de cette puissance d’une manière très simple et abordable.
Ne soyez pas dupe de l’immédiate simplicité de l’interface de Sonic Pi. Vous pouvez aller très en profondeur dans une manipulation très sophistiquée des sons si c’est votre dada. Tenez bien vos chapeaux…
Jetez un œil sur le code suivant :
play 70
C’est là que tout commence. Allez de l’avant, copiez et collez-le dans la fenêtre de code en haut de l’application (le grand espace blanc en dessous du bouton Run). Maintenant, pressez Run…
Intense. Pressez-le une nouvelle fois. Et encore. Et encore…
Woah, fou, je suis sûr que vous pourrez continuer à faire cela toute la journée. Mais attendez, avant que vous ne vous perdiez dans un flot infini de beeps, essayez de changer le nombre :
play 75
Entendez-vous la différence ? Essayez un nombre plus petit :
play 60
Ainsi, des nombres plus petits font des beeps plus grave et des nombres
plus grands font des beeps plus aigus. Juste comme sur un piano, les
touches de la partie basse (côté main gauche) font des notes plus graves
et celles de la partie haute (côté main droite) font des notes plus
aiguës. En fait, les nombres représentent réellement l’ordre des notes
sur le piano. play 47
signifie réellement “joue la 47ème note” sur le
piano. Ce qui signifie que play 48
désigne la note supérieure (la note
suivante vers la droite). Il faut juste noter que le 4ème octave du Do
(C en notation anglaise) est identifié par le nombre 60. Poursuivez et
jouez-le : play 60
Ne vous inquiétez pas si cela ne signifie rien pour vous - c’est ce qu’il m’est arrivé au début quand j’ai commencé. Tout ce qui importe maintenant est que vous sachiez que les petits nombres font des beeps graves et que les grands nombres font des beeps aigus.
Jouez une note est vraiment plaisant, mais en jouer plusieurs en même temps est encore mieux. Essayez-le :
play 72
play 75
play 79
Jazzy ! Ainsi quand vous écrivez plusieurs play
s, ils sont tous joués
en même temps. Essayez-le vous-même - quels sont les nombres qui sonnent
bien ensemble ? Lesquels sonnent terrible ? Expérimentez, explorez et trouvez
ce qui est bien pour vous.
Ainsi, jouer des notes et des accords est plaisant - mais comment
jouer une mélodie ? Que faire si vous voulez jouer une note après une
autre et pas en même temps ? Eh bien, c’est facile, vous avez juste
besoin de sleep
entre les notes :
play 72
sleep 1
play 75
sleep 1
play 79
Comme c’est charmant, un petit arpège. Alors que signifie le 1
dans
sleep 1
? Eh bien, cela représente la durée du sleep. Ça signifie
réellement “dors pendant un temps musical”, mais pour l’instant nous pouvons
penser qu’il s’agit de dormir pendant 1 seconde. Alors que faire si nous
voulons que notre arpège soit un peu plus rapide ? Eh bien, nous devons
utiliser des valeurs de sleep plus petites. Quel résultat pour la moitié,
c’est-à-dire 0.5
:
play 72
sleep 0.5
play 75
sleep 0.5
play 79
Remarquez comment ça joue plus rapidement. Maintenant, essayez vous-même, changez les durées - utilisez différentes durées et différentes notes.
Une chose à essayer est les notes intermédiaires comme play 52.3
et
play 52.63
. Il n’est absolument pas nécessaire de coller aux notes
standardisées. Jouez et faites-vous plaisir.
Ceux qui connaissent déjà la notation musicale (ne vous inquiétez pas si
ce n’est pas votre cas - vous n’en n’avez pas besoin pour vous amuser)
pourraient aimer écrire une mélodie en utilisant les noms des notes comme
“Do” ou “Fa#” plutôt que des nombres. Sonic Pi a ce qu’il faut, mais en
notation anglaise (A
pour “La”, B
pour “Si”, C
pour “Do”, D
pour
“Ré”, E
pour “Mi”, F
pour “Fa”, G
pour “Sol”). Vous pouvez faire
la chose suivante :
play :C
sleep 0.5
play :D
sleep 0.5
play :E
Notez de mettre des deux-points :
devant votre nom de note de manière
qu’elle apparaisse en rose. Vous pouvez également spécifier l’octave en
ajoutant un nombre derrière le nom de la note :
play :C3
sleep 0.5
play :D3
sleep 0.5
play :E4
Si vous voulez faire un dièse, ajoutez un s
(pour “sharp”) derrière le nom
de la note, comme play :Fs3
et si vous vouler faire un bémol, ajoutez un
b
comme play :Eb3
.
Maintenant défoulez-vous et faites-vous plaisir en faisant vos morceaux.
De la même manière qu’il vous permet de contrôler chaque note ou chaque échantillon à jouer, Sonic Pi fournit un large éventail de paramètres pour confectionner ou contrôler les sons. Nous couvrirons beaucoup d’entre eux dans ce tutoriel et il y a une documentation exhaustive pour chacun d’eux dans le système d’aide. Toutefois pour l’instant, nous allons introduire deux des plus utiles : amplitude et pan. Regardons en premier ce que les paramètres sont réellement.
Sonic Pi supporte la notion de paramètres pour ses synthés. Les paramètres
sont des informations de contrôle que vous passez à play
et qui modifient
et contrôlent les aspects du son que vous entendez. Chaque synthé a son propre
jeu de paramètres pour ajuster finement ses sons. Cependant, il y a un
ensemble commun de paramètres partagés par beaucoup de sons comme amp:
et
les paramètres d’enveloppe (couverts dans une autre section).
Les paramètres ont deux parties principales, leur nom (le nom du contrôle)
et leur valeur (la valeur que vous voulez affecter au contrôle). Par exemple,
vous pourriez avoir un paramètre appelé cheese:
et vouloir lui affecter
la valeur 1
.
Les paramètres sont passés aux appels à play
en utilisant une virgule ,
et ensuite le nom du paramètre comme amp:
(n’oubliez pas les deux-points
:
) et ensuite un espace et la valeur du paramètre. Par exemple :
play 50, cheese: 1
(Notez que cheese:
n’est pas un paramètre valide, il est juste utilisé
pour l’exemple).
Vous pouvez passer plusieurs paramètres en les séparant par une virgule :
play 50, cheese: 1, beans: 0.5
L’ordre des paramètres n’est pas imposé, ainsi, ce qui suit est identique :
play 50, beans: 0.5, cheese: 1
Les paramètres qui ne sont pas reconnus par le synthé sont simplement ignorés
(comme cheese
et beans
qui sont clairement des noms de paramètres ridicules !)
Si vous utilisez accidentellement 2 fois le même paramètre avec des valeurs
différentes, la dernière gagne. Par exemple, beans:
aura ici la valeur 2
plutôt que 0.5 :
play 50, beans: 0.5, cheese: 3, eggs: 0.1, beans: 2
Beaucoup de choses dans Sonic Pi acceptent des paramètres, aussi passez
un peu de temps à apprendre comment les utiliser et vous serez au point !
Jouons avec notre premier paramètre : amp:
.
L’amplitude est la représentation informatique du volume d’un son. Une amplitude élevée produit un son fort et une amplitude basse produit un son faible. A la manière dont Sonic Pi utilise des nombres pour représenter les durées et les notes, des nombres sont aussi utilisés pour représenter l’amplitude. Une amplitude 0 est le silence (vous n’entendez rien) tandis qu’une amplitude de 1 désigne le volume normal. Vous pouvez monter l’amplitude à 2, 10, 100. Toutefois, vous devez noter que lorsque l’amplitude globale de tous les sons devient trop élevée, Sonic Pi utilise ce qui est appelé un compresseur pour l’aplatir, de manière à s’assurer que le volume ne soit pas trop fort pour vos oreilles. Cela peut fréquemment rendre le son distordu et étrange. Aussi essayez d’utiliser des amplitudes basses, c’est-à-dire dans l’intervalle 0 à 0.5 pour éviter la compression.
Pour changer l’amplitude d’un son, vous pouvez utiliser le paramètre
amp:
. Par exemple, pour jouer à moitié amplitude, passez 0.5 :
play 60, amp: 0.5
Pour jouer à double amplitude, passez 2 :
play 60, amp: 2
Le paramètre amp:
ne modifie que l’appel au play
auquel il est associé.
Aussi, dans l’exemple suivant, le premier appel à play est à moitié
volume et le second revient à la valeur par défaut (1) :
play 60, amp: 0.5
sleep 0.5
play 65
Bien entendu, vous pouvez utiliser différentes valeurs de amp:
pour
chaque appel à play :
play 50, amp: 0.1
sleep 0.25
play 55, amp: 0.2
sleep 0.25
play 57, amp: 0.4
sleep 0.25
play 62, amp: 1
Un autre paramètre agréable à utiliser est pan:
qui contrôle la
balance du son en stéréo. Balancer un son vers la gauche signifie que
votre oreille va l’entendre sortir du haut-parleur de gauche, et le
balancer vers la droite que vous l’entendrez sortir par le haut-parleur
de droite. Pour nos valeurs, nous utilisons -1 pour représenter
complètement à gauche, 0 pour représenter le centre et 1 pour représenter
complètement à droite dans le champ stéréo. Bien entendu, vous êtes libre
d’utiliser toute valeur entre -1 et 1 pour contrôler le positionnement
précis de votre son.
Jouons un beep à destination du haut-parleur de gauche :
play 60, pan: -1
Maintenant, jouons-le à destination du haut-parleur de droite :
play 60, pan: 1
Finalement, jouons-le à destination du centre des deux (la position par défaut) :
play 60, pan: 0
Maintenant, allez et prenez plaisir à changer l’amplitude et la balance de vos sons !
Jusqu’à maintenant, nous nous sommes bien amusés à faire des beeps. Cependant, vous commencez probablement à être ennuyé par le bruit basique du beep. Sonic Pi n’a-t-il que cela à offir en tout et pour tout ? Il y a certainement plus dans le codage en “live” que de jouer seulement des beeps. Oui, et dans cette section nous allons explorer l’étendue des sons que Sonic Pi a à offrir.
Sonic Pi dispose d’un lot d’instruments qu’il appelle synths raccourci pour synthétiseurs. Tandis que les échantillons (samples) représentent des sons pré-enregistrés, les synthés (synths) sont capables de générer des nouveaux sons en fonction de la façon dont vous les contrôlez (ce que nous explorerons plus tard dans ce tutoriel). Les synthés de Sonic Pi sont très puissants et expressifs, et vous aurez grand plaisir à les explorer et à jouer avec. En premier lieu, apprenons à sélectionner le synthé en cours à utiliser.
Un son sympathique est l’onde en dent de scie (saw) - essayons-le :
use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
play 62
sleep 0.25
Essayons un autre son - le prophet :
use_synth :prophet
play 38
sleep 0.25
play 50
sleep 0.25
play 62
sleep 0.25
Comment combiner deux sons. D’abord l’un après l’autre :
use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
use_synth :prophet
play 57
sleep 0.25
Maintenant en même temps :
use_synth :tb303
play 38
sleep 0.25
use_synth :dsaw
play 50
sleep 0.25
use_synth :prophet
play 57
sleep 0.25
Notez que la commande use_synth
n’agit que sur les appels suivants à
play
. Pensez à elle comme un gros commutateur - les nouveaux appels
à play
vont jouer tout synthé qui est désigné “en cours”. Vous pouvez
enclencher le commutateur sur un nouveau synthé avec use_synth
.
Pour voir quels synthés Sonic Pi met à votre disposition pour jouer, jetez un œil sur les options de Synths dans le menu horizontal tout à fait en bas (à gauche de Fx). Il y en a 33 au choix. Voici mes préférés :
:prophet
:dsaw
:fm
:tb303
:pulse
Maintenant jouez en commutant les synthés au cours de votre jeu. Prenez plaisir à combiner des synthés pour faire de nouveaux sons et aussi en untilisant différents synthés selon les sections de votre musique.
Dans une section précédente, nous avons vu comment nous pouvions utiliser la commande sleep pour contrôler le moment du déclenchement de nos sons. Toutefois, nous n’avons pas encore été capables de contrôler la durée des sons.
Dans le but de nous offrir des moyens simples mais puissants de contrôle de durée de nos sons, Sonic Pi fournit la technique d’enveloppe d’amplitude ADSR (nous expliquerons ce que ADSR signifie plus loin dans cette section). Une enveloppe d’amplitude offre deux moyens utiles de contrôle :
La durée est le temps pendant lequel le son se maintient. Une longue durée signifie que vous entendez le son plus longtemps. Les sons de Sonic Pi ont tous une enveloppe d’amplitude, et la durée totale de cette enveloppe est la durée du son. Ainsi, en contrôlant l’enveloppe, vous contrôlez la durée.
L’enveloppe ADSR non seulement contrôle la durée, mais vous donne aussi un contrôle fin sur l’amplitude du son. Tous les sons commencent et finissent par le silence, avec une part non silencieuse entre. Les enveloppes vous permettent de faire évoluer ou de maintenir l’amplitude des parties non-silencieuses du son. C’est comme si vous donniez à quelqu’un des instructions sur comment augmenter ou diminuer le volume d’une musique. Par exemple, vous pourriez demander à quelqu’un de commencer en silence, d’augmenter lentement le volume jusqu’au maximum, le maintenir un moment, puis revenir rapidement au silence. Sonic Pi vous permet de programmer ceci avec les enveloppes.
Comme nous l’avions vu dans une section précédente, une amplitude de 0 est le silence et une amplitude de 1 est le volume normal.
Par défaut, tous les synthés ont une durée de “release” de 1. Ce qui
signifie qu’ils ont une durée d’un temps musical (qui par défaut est 1 seconde)
avant extinction. Nous pouvons changer cette durée en passant l’argument
release:
à nos appels à play
. Par exemple, pour faire jouer un synthé
pendant 2 temps, nous spécifions un release:
de 2
:
play 60, release: 2
Nous pouvons faire jouer un synthé pendant une très courte durée en utilisant une durée de “release” très petite :
play 60, release: 0.2
Ainsi, qu’est-ce que la durée de “release” ? C’est la durée que prend le son pour passer de l’amplitude totale (typiquement une valeur de 1) à l’amplitude 0. C’est appelé la phase d’extinction et c’est une transition linéaire (une courbe en ligne droite). Le schéma suivant illustre cette transition :
La ligne verticale à gauche du schéma montre que le son part de
l’amplitude 0, mais monte jusqu’à l’amplitude totale immédiatement
(c’est la phase d’attaque que nous couvrirons en suivant). Une fois à
l’amplitude totale, il évolue en ligne droite jusqu’à zéro en
prenant le temps spécifié par release:
. Des durées de “release”
longues produisent des fondus d’extinction de synthé longs.
Vous pouvez ainsi changer la durée de vos sons en changeant la durée d’extinction. Jouez un moment en ajoutant des durées de “release” à votre musique.
Par défaut, la phase d’attaque est fixée à 0 pour tous les synthés, ce qui
signifie qu’ils évoluent de l’amplitude 0 à l’amplitude 1 immédiatement.
Cela donne initialement au synthé un son percussif. Toutefois, vous
pouvez souhaiter une montée progressive de votre son. Ceci peut être
obtenu avec l’argument attack:
. Essayez des montées progressives de
quelques sons :
play 60, attack: 2
sleep 3
play 65, attack: 0.5
Vous pouvez utiliser des arguments multiples en même temps. Par exemple, pour une attaque courte et une lente extinction, essayez :
play 60, attack: 0.7, release: 4
Cette courte attaque et cette lente extinction sont illustrées dans le schéma suivant :
Bien entendu, vous pouvez inverser les choses. Essayez une attaque longue et une exctinction rapide :
play 60, attack: 4, release: 0.7
Finalement, vous pouvez aussi avoir à la fois une attaque et une exctinction rapides pour des sons plus courts :
play 60, attack: 0.5, release: 0.5
En plus de spécifier des durées d’attaque et d’extinction, vous pouvez aussi spécifier une durée de soutien. C’est la durée pendant laquelle le son est maintenu à l’amplitude totale entre les phases d’attaque et d’extinction.
play 60, attack: 0.3, sustain: 1, release: 1
La durée de soutien est utile pour des sons importants auxquels vous voulez donner une présence permanente dans le mixage avant d’entrer dans une optionnelle phase d’extinction. Bien entendu, c’est entièrement valide de fixer à la fois les arguments d’attaque et d’extinction à 0 et d’utiliser seulement le soutien pour n’avoir absolument pas de montée et d’extinction progressives. Cependant, faites attention, une durée d’extinction de 0 peut produire des clics dans l’écoute et c’est souvent mieux d’utiliser une très petite valeur comme 0.2.
Finalement, pour les cas où vous aurez besoin d’un niveau de
contrôle supplémentaire, vous pourrez aussi spécifier une durée de
déclin. C’est la phase de l’enveloppe qui s’intercale entre les phases
d’attaque et de soutien et qui spécifie la durée pendant laquelle l’amplitude va
descendre du niveau attack_level
jusqu’au niveau sustain_level
.
Par défaut, l’argument “decay” est à 0 et à la fois les niveaux “attack” et
“sustain” sont à 1. Ainsi vous aurez besoin de les spécifier en plus
de la durée de déclin pour obtenir un effet :
play 60, attack: 0.1, attack_level: 1, decay: 0.2, sustain_level: 0.4, sustain: 1, release: 0.5
Ainsi pour résumer, les enveloppes de Sonic Pi ont les phases suivantes :
attack_level
,attack_level
jusqu’au niveau sustain_level
,sustain_level
,sustain_level
au niveau 0Il est important de noter que la durée d’un son est la somme des durées de chacune de ces phases. Ainsi le son suivant aura une durée de 0.5 + 1 + 2 + 0.5 = 4 temps musicaux :
play 60, attack: 0.5, decay: 1, sustain_level: 0.4, sustain: 2, release: 0.5
Maintenant, allez et jouez un moment en ajoutant des enveloppes à vos sons.
Un autre grand moyen de développer votre musique est d’utiliser des sons pré-enregistrés. Dans la grande tradition hip-hop, on appelle ces sons pré-enregistrés samples. Aussi, si vous prenez un micro à l’extérieur, et allez enregistrer le son de la pluie frappant une toile, vous avez tout simplement créé un “sample”.
Sonic Pi vous offre des tas de choses amusantes à faire avec les “samples”. Non seulement il est livré avec plus de 90 échantillons du domaine public, prêts pour faire un boeuf, mais il vous permet de jouer et de manipuler les vôtres propres. Allons voir…
Jouer des beeps est seulement un début. Une chose qui est très plaisante est de déclencher des échantillons pré-enregistrés. Essayez-le :
sample :ambi_lunar_land
Sonic Pi inclut beaucoup d’échantillons à jouer. Vous pouvez les
utiliser juste comme vous utilisez la commande play
. Pour jouer des
échantillons et des notes multiples, écrivez-les simplement les uns
après les autres :
play 36
play 48
sample :ambi_lunar_land
sample :ambi_drone
Si vous voulez les espacer dans le temps, utilisez la commande sleep
:
sample :ambi_lunar_land
sleep 1
play 48
sleep 0.5
play 36
sample :ambi_drone
sleep 1
play 36
Notez que Sonic Pi n’attend pas la fin d’un son pour démarrer le
suivant. La commande sleep
décrit uniquement la séparation du
déclenchement des sons. Ceci vous permet de superposer les sons en
couches en créant d’intéressants effets de chevauchement. Plus tard
dans ce tutoriel, nous jetterons un œil sur le contrôle de la durée
de ces sons avec des enveloppes.
Il y a deux manière de découvrir l’étendue des échantillons fournis par Sonic Pi. En premier lieu, on peut utiliser le système d’aide. Cliquez sur “Échantillons” dans le menu horizontal du bas, choisissez votre catégorie et vous verrez une liste des sons disponibles.
Alternativement, vous pouvez utiliser le système d’auto-complétion.
Tapez simplement le début d’un groupe d’échantillons comme :
sample :ambi_
et vous verrez apparaître une liste de noms
d’échantillons qui vous permettra d’en sélectionner un. Essayez les
préfixes de catégorie suivants :
:ambi_
:bass_
:elec_
:perc_
:guit_
:drum_
:misc_
:bd_
Maintenant commencez à introduire des échantillons dans vos compositions !
Comme nous l’avons vu avec les synthés, nous pouvons aisément contrôler
nos sons avec des paramètres. Les “Samples” supportent exactement le
même mécanisme de paramètrage. Revisitons nos amis amp:
et pan:
.
Vous pouvez changer l’amplitude des échantillons avec exactement la même approche que vous avez utilisée pour les synthés :
sample :ambi_lunar_land, amp: 0.5
Nous pouvons aussi utiliser le paramètre pan:
avec les
échantillons. Par exemple, voici comment nous jouerions l’amen au
début vers la droite, puis à motié parcours, vers la gauche :
sample :loop_amen, pan: -1
sleep 0.877
sample :loop_amen, pan: 1
Notez que 0.877 est la moitié de la durée en secondes de l’échantillon
:loop_amen
.
Finalement, notez que si vous fixez des valeurs par défaut avec
use_synth_defaults
(que nous détaillerons plus tard), ils seront
ignorés par sample
.
Maintenant que nous pouvons jouer une variété de synthés et d’échantillons pour créer une musique, il est temps d’apprendre comment modifier à la fois les synthés et les échantillons pour faire de la musique encore plus originale et intéressante. En premier, explorons la faculté d’étirer et de compresser les échantillons.
Les échantillons (“samples”) sont des sons pré-enregistrés stockés à l’aide de nombres qui représentent comment se déplace la membrane du haut-parleur pour reproduire le son. La membrane du haut-parleur peut avancer et reculer, et ainsi les nombres ont juste besoin de représenter la distance d’avancée ou de recul que la membrane doit avoir pour chaque moment dans le temps. Pour être capable de reproduire fidèlement un son enregistré, un échantillon a typiquement besoin de stocker des milliers de nombres par seconde. Sonic Pi prend cette liste de nombres et en alimente à la bonne vitesse l’ordinateur pour faire avancer et reculer comme il le faut la membrane de son haut-parleur pour reproduire le son. Cependant, c’est aussi amusant de changer la vitesse à laquelle est alimenté le haut-parleur pour changer le son.
Jouons avec un des sons d’ambiance : :ambi_choir
. Pour le jouer avec
la vitesse par défaut, vous pouvez passer un argument rate:
au sample
:
sample :ambi_choir, rate: 1
Ceci le joue à la vitesse normale (1), aussi rien de spécial pour
l’instant. Cependant, vous êtes libre de changer ce nombre pour une
autre valeur. Que dire de 0.5
:
sample :ambi_choir, rate: 0.5
Wooh ! Que se passe-t-il ici ? Eh bien, deux choses. Premièrement, l’échantillon est joué pendant 2 fois plus de temps, deuxièmement le son est a un octave en-dessous. Explorons ces choses un peu plus en détails.
Un échantillon qui est amusant à étirer ou à compresser est Amen. A vitesse normale, on pourrait imaginer de l’insérer dans une piste de batterie et de basse :
sample :loop_amen
Toutefois en modifiant la vitesse on peut changer de genre. Essayez de réduire de moitié la vitesse pour une vieille école hip-hop :
sample :loop_amen, rate: 0.5
Si nous l’accélérons, nous entrons dans le territoire de la jungle :
sample :loop_amen, rate: 1.5
Maintenant pour notre astuce finale - voyons ce qui se passe lorsque nous utilisons un “rate” négatif :
sample :loop_amen, rate: -1
Wooh ! Il le joue à l’envers ! Maintenant, essayez de jouer avec des tas d’échantillons différents. Essayez des vitesses très rapides et des vitesses insensément lentes. Voyez quels sons intéressants vous pouvez produire.
Un moyen imagé d’assimiler les échantillons est de penser aux ressorts.
La vitesse de lecture est comme l’étirement et la compression du ressort.
Si vous jouez l’échantillon à la vitesse 2, vous compressez le ressort
à la moitié de sa longueur normale. Ainsi l’échantillon met la
moitié du temps à être joué puisqu’il est plus court. Si vous jouez
l’échantillon à la moitié de la vitesse, vous étirez le ressort au
double de sa longueur. Ainsi l’échantillon met deux fois plus de temps
à être joué puisqu’il est plus long. Plus vous compressez (vitesse
plus élevée), plus il devient court, plus vous étirez (vitesse plus
lente), plus il devient long.
Compresser un ressort augmente sa densité (le nombre de spires par cm) - ceci est similaire à l’échantillon sonnant plus aigu. Étirer le ressort diminue sa densité, c’est similaire à un son plus grave.
(Cette section est fournie pour ceux que les détails intéressent. Soyez libre de la sauter…)
Comme nous l’avons vu ci-dessus, un échantillon est représenté par une longue liste de nombres qui représentent la position où devrait être la membrane du haut-parleur dans le temps. Nous pouvons prendre cette liste de nombres et l’utiliser pour tracer un graphique qui ressemblerait à ceci :
Vous devriez avoir déjà vu des images comme cela. C’est appelé la forme d’onde d’un échantillon. C’est juste un graphique de nombres. Typiquement, une forme d’onde comme cela aura 44100 points de données par seconde (en application du théorème d’échantillonnage de Nyquist-Shannon). Ainsi, si l’échantillon dure 2 secondes, la forme d’onde sera représentée par 88200 nombres qui alimenteront le haut-parleur à la vitesse de 44100 points par seconde. Bien sûr, nous pouvons l’alimenter à une vitesse double qui serait de 88200 points par seconde. Ceci prendrait ainsi une seconde à être joué. Nous pourrions aussi le jouer à la moitié de la vitesse qui serait donc de 22050 points par seconde, en prenant 4 secondes pour être joué.
La durée d’un échantillon est affecté par la vitesse de jeu :
On peut représenter ceci avec la formule :
nouvelle_durée = (1 / rate) * durée_normale
Changer la vitesse de jeu affecte aussi la hauteur du son. La fréquence ou le ton d’une forme d’onde est déterminé par la vitesse à laquelle elle monte et descend. Notre cerveau curieusement change le mouvement rapide de la membrane du haut-parleur en notes hautes et le mouvement lent en notes basses. C’est pourquoi vous pouvez quelquefois voir un gros haut-parleur de basse bouger en émettant une super basse - il va et vient beaucoup moins vite qu’un haut-parleur produisant des notes plus aiguës.
Si vous prenez une forme d’onde et que vous la compressez, elle va
monter et descendre plus de fois par seconde. Ceci va faire un son
plus aigu. On en déduit que doubler le montant des mouvements de
montée et descente (oscillations) double la fréquence. Ainsi, jouer
votre échantillon à double vitesse double la fréquence que vous entendez.
De même, diminuer de moitié la vitesse va diminuer de moitié la fréquence.
D’autres vitesses affecterons la fréquence dans le même sens.
Il est aussi possible de modifier la durée et l’amplitude d’un
échantillon en utilisant une enveloppe ADSR. Toutefois, ceci fonctionne
d’une manière légèrement différente de l’enveloppe ADSR applicable
aux synthés. Les enveloppes d’échantillon permettent uniquement de
réduire l’amplitude et la durée de l’échantillon - et jamais de les
augmenter. Le jeu de l’échantillon s’arrêtera soit quand
l’échantillon arrivera à sa fin, soit quand la fin l’enveloppe sera
atteinte. Donc si vous utilisez une phase de release:
très longue, cela
n’allongera pas la durée de l’échantillon.
Retournons à notre fidèle ami Amen :
sample :loop_amen
Sans paramètres, nous entendons la totalité de l’échantillon à son
amplitude totale. Si nous voulons une attaque progressive, nous pouvons
utiliser le paramètre attack:
:
sample :loop_amen, attack: 1
Pour une attaque plus courte, choisissez une valeur attack:
plus
petite :
sample :loop_amen, attack: 0.3
Où le comportement de l’enveloppe ADSR diffère de l’enveloppe standard des synthés est dans la valeur de sustain. Dans l’enveloppe standard des synthés, la valeur par défaut du soutien est 0 à moins que vous ne la fixiez manuellement. Avec les échantillons, la valeur par défaut du soutien est une valeur auto-magique - le temps qu’il reste pour finir l’échantillon. C’est pour cela que nous entendons l’échantillon en entier quand une valeur n’est pas spécifiée. Si les valeurs de l’attaque, du déclin, du soutien et de l’extinction sont toutes à 0, nous n’entendrons pas le moindre gazouillis. Donc, de la longueur de l’échantillon, Sonic Pi déduit les éventuelles durées d’attaque, de déclin et d’extinction et utilise le résultat pour votre durée de soutien. Si la somme des durées d’attaque, de déclin et d’extinction est supérieure à la durée de l’échantillon, le soutien est simplement fixé à 0.
Pour explorer ceci, regardons notre Amen de manière plus détaillée. Si nous demandons à Sonic Pi quelle est la longueur de l’échantillon :
print sample_duration :loop_amen
Il affichera 1.753310657596372
, ce qui est la longueur de
l’échantillon en secondes. Arrondissons-le ici à 1.75
par
commodité. Maintenant si nous fixons l’extinction à 0.75
, quelque
chose de surprenant va se passer :
sample :loop_amen, release: 0.75
La première seconde de l’échantillon va être jouée à l’amplitude totale avant de s’estomper progressivement sur une durée de 0.75 secondes. C’est l’auto-soutien en action. Par défaut, la phase d’extinction fonctionne de manière à s’achever à la fin de l’échantillon. Si notre échantillon avait 10.75 secondes de longueur, il serait joué 10 seconde à l’amplitude totale avant de s’estomper progressivement pendant 0.75 secondes.
Rappelez-vous : par défaut, la phase release:
amène à l’extinction
complète à la fin de l’échantillon.
On peut utiliser à la fois les paramètres attack:
et release:
ensemble grâce au comportement du soutien automatique pour des attaques
et des extinctions progressives :
sample :loop_amen, attack: 0.75, release: 0.75
Comme la durée totale de l’échantillon est de 1.75 s et que la somme des phases d’attaque et d’extinction fait 1.5 s, le soutien est automatiquement ajusté à 0.25 s. Ceci nous permet de programmer facilement une attaque et une extinction progressives de l’échantillon.
Nous pouvons facilement revenir au comportement normal de l’enveloppe
ADSR des synthés en fixant manuellement sustain:
à une valeur comme 0 :
sample :loop_amen, sustain: 0, release: 0.75
Maintenant, notre échantillon n’est joué que pendant 0.75 s au total.
Avec les valeurs 0 par défaut pour attack:
et decay:
,
l’échantillon monte directement à l’amplitude totale, se maintient là
pendant 0 s et redescend progressivement à l’amplitude 0 pendant une
durée de 0.75 s.
Nous pouvons utiliser ce comportement pour obtenir de bons effets en
transformant un échantillon qui sonne longtemps en versions plus
percussives. Intéressons-nous à l’échantillon :drum_cymbal_open
:
sample :drum_cymbal_open
Vous pouvez entendre la cymbale sonnant pendant une certaine durée. Toutefois, nous pouvons utiliser notre enveloppe pour la rendre plus percussive :
sample :drum_cymbal_open, attack: 0.01, sustain: 0, release: 0.1
Vous pouvez émuler la frappe de la cymbale suivie d’un étouffement en augmentant la phase de soutien :
sample :drum_cymbal_open, attack: 0.01, sustain: 0.3, release: 0.1
Maintenant allez et prenez plaisir à mettre des enveloppes sur vos échantillons. Essayez aussi de changer la vitesse pour des résultats vraiment intéressants.
Cette section va conclure notre exploration du lecteur d’échantillons de Sonic Pi. Faisons un rapide résumé. Jusqu’à maintenant nous avons vu comment lire des échantillons :
sample :loop_amen
Nous avons ensuite vu comment changer la vitesse de lecture des échantillons en les jouant par exemple à moitié vitesse :
sample :loop_amen, rate: 0.5
Ensuite, nous avons vu comment nous pouvions obtenir une attaque progressive (faisons-le à moitié vitesse) :
sample :loop_amen, rate: 0.5, attack: 1
Nous avons aussi vu comment nous pouvions utiliser le début d’un
échantillon de manière percussive en donnant à sustain:
une valeur
explicite et en assignant des valeurs faibles à la fois à attack:
et
à release:
:
sample :loop_amen, rate: 2, attack: 0.01, sustain: 0, release: 0.35
Toutefois ne serait-il pas sympathique de ne pas avoir à toujours démarrer au début de l’échantillon ? Ne serait-ce pas également sympathique de ne pas avoir à finir toujours à la fin de l’échantillon ?
Il est possible de choisir un point arbitraire de départ dans l’échantillon au moyen d’une valeur comprise entre 0 et 1 où 0 est le début de l’échantillon et 1 la fin et 0.5 le milieu. Essayons de jouer seulement la dernière moitié de “Amen” :
sample :loop_amen, start: 0.5
Ou pour le dernier quart de l’échantillon :
sample :loop_amen, start: 0.75
De manière similaire, il est possible de choisir un point de terminaison arbitraire au moyen d’une valeur comprise entre 0 et 1. Terminons l’“Amen” à la moitié de son parcours :
sample :loop_amen, finish: 0.5
Bien sûr, nous pouvons combiner ces deux paramètres pour jouer des segments arbitraires. Comment jouer uniquement une petite section au milieu :
sample :loop_amen, start: 0.4, finish: 0.6
Que se passe-t-il si nous choisissons une position de départ postérieure au point de terminaison ?
sample :loop_amen, start: 0.6, finish: 0.4
Cool ! Ça joue à l’envers !
Nous pouvons combiner cette nouvelle possibilité avec l’ami rate:
pour jouer des segments arbitraires. Par exemple, nous pouvons jouer une
très petite section d’“Amen” très lentement :
sample :loop_amen, start: 0.5, finish: 0.7, rate: 0.2
Finalement, nous pouvons combiner tout ceci avec nos enveloppes ADSR pour produire des résultats intéressants :
sample :loop_amen, start: 0.5, finish: 0.8, rate: -0.2, attack: 0.3, release: 1
Maintenant allez et jouez un moment en triturant les échantillons avec ces choses amusantes.
Bien que les échantillons fournis en interne puissent vous motiver et vous faire démarrer rapidement, vous pourriez souhaiter d’expérimenter d’autres sons pré-enregistrés dans votre musique. Sonic Pi supporte complètement cela. En premier lieu toutefois ayons une rapide discussion sur la portabilité de votre oeuvre.
Quand vous composez votre morceau uniquement avec des synthés et des échantillons internes, le code est tout ce dont vous avez besoin pour reproduire fidèlement votre musique. Pensez à cela un instant - C’est étonnant ! Un simple morceau de texte que vous pouvez envoyer par mail ou coller dans un Gist représente tout ce que vous avez besoin pour reproduire vos sons. Cela le rend vraiment facile à partager avec vos amis puisqu’ils ont juste besoin de se procurer le code.
Toutefois, si vous commencez à utiliser vos propres échantillons pré-enregistrés, vous perdez cette portabilité. C’est parce que non seulement les autres ont besoin de votre code, mais aussi de vos échantillons. Ceci limite la capacité pour les autres de manipuler, triturer et expérimenter votre oeuvre. Bien entendu, ceci ne devrait pas vous faire arrêter d’utiliser vos propres échantillons, c’est juste quelque chose à prendre en compte.
Alors comment jouez-vous n’importe quel fichier WAV, AIFF ou FLAC sur votre
ordinateur ? Tout ce dont vous avez besoin est de passer le chemin de ce
fichier à sample
:
sample "/home/sam/Desktop/my-sound.wav"
Sonic Pi chargera automatiquement et jouera votre échantillon. Vous pouvez
aussi passer tous les paramètres que vous avez l’habitude de passer
à sample
:
sample "/home/sam/Desktop/my-sound.wav", rate: 0.5, amp: 0.3
Note: cette section du tutoriel couvre le sujet avancé de travailler avec des grands dossiers de vos propres samples. Ce sera le cas si vous avez téléchargé ou acheté vos propre paquets de samples et souhaitez les utiliser dans Sonic Pi.
N’hésitez pas à sauter cette section si vous vous contentez des samples fournis dans Sonic Pi.
Quand on travaille avec de grands dossiers de samples externes il peut être ennuyeux de taper le chemin entier chaque fois qu’on veut déclencher un sample particulier.
Par exemple, imaginons que vous avez le dossier suivant sur votre machine :
/path/to/my/samples/
Quand on regarde dans ce dossier on voit les samples suivants :
100_A#_melody1.wav
100_A#_melody2.wav
100_A#_melody3.wav
120_A#_melody4.wav
120_Bb_guit1.wav
120_Bb_piano1.wav
Typiquement pour jouer le sample de piano on peut utiliser le chemin complet :
sample "/path/to/my/samples/120_Bb_piano1.wav"
Si on veut jouer le sample de guitare on peut aussi utiliser son chemin complet :
sample "/path/to/my/samples/120_Bb_guit.wav"
Cependant ces deux appels de samples nous forcent à connaître le nom de chacun des samples de notre dossier. Et si on voulait juste écouter chaque sample à son tour rapidement ?
Si on veut jouer le premier sample d’un dossier on peut juste passer
le nom du dossier à sample
et l’index 0
comme suit :
sample "/path/to/my/samples/", 0
On peut même construire un raccourci vers notre chemin de dossier en utilisant une variable :
samps = "/path/to/my/samples/"
sample samps, 0
Maintenant, si on veut jouer le deuxième sample de notre dossier, on peut juste incrémenter notre index :
samps = "/path/to/my/samples/"
sample samps, 1
Remarquez qu’on n’a plus besoin de connaître le nom des samples du dossier : on doit juste connaître le dossier lui-même (ou avoir un raccourci vers lui). Si on demande un index qui est plus grand que le nombre de samples, il va juste boucler comme pour les anneaux. Ainsi, quel que soit le nombre qu’on utilise on a la garantie de récupérer un des samples de ce dossier.
D’habitude indexer suffit, mais parfois on a besoin de plus de puissance pour trier et organiser nos samples. Heureusement de nombreux paquets de samples ajoutent des informations utiles dans les noms de fichiers. Jetons un autre oeil aux noms de fichier des samples de notre dossier :
100_A#_melody1.wav
100_A#_melody2.wav
100_A#_melody3.wav
120_A#_melody4.wav
120_Bb_guit1.wav
120_Bb_piano1.wav
Remarquez que dans ces noms de fichier nous avons pas mal d’informations. On a le BPM du sample (nombre de battements par minute) au début. Donc le sample de piano est à 120 BPM et nos trois premières mélodies sont à 100 BPM. Nos noms de samples contiennent aussi la clef. Donc le sample de guitare est en Bb (si bémol) et les mélodies sont en A# (la dièse). Cette information est très utile pour mélanger ces samples avec le reste de notre code. Par exemple, on sait qu’on ne peut jouer le sample de piano que dans du code qui est à 120 BPM et dans la clef de Bb.
Il se trouve qu’on peut utiliser cette convention de nommage
particulière de nos ensembles de samples dans le code pour nous aider
à ne garder que ceux qu’on veut. Par exemple, si nous travaillons à
120 BPM, on peut ne garder que les samples qui contiennent la chaîne
"120"
avec le code suivant :
samps = "/path/to/my/samples/"
sample samps, "120"
Cela jouera le premier sample qui correspond. Si on veut le deuxième, on n’a qu’à utiliser l’index :
samps = "/path/to/my/samples/"
sample samps, "120", 1
On peut même utiliser de multiples filtres en même temps. Par exemple, si on veut un sample dont le nom de fichier contient à la fois les sous-chaînes “120” et “A#”, on peut le trouver facilement avec le code suivant :
samps = "/path/to/my/samples/"
sample samps, "120", "A#"
Enfin, on a toujours la possibilité d’ajouter nos options habituelles
lors de l’appel à sample
:
samps = "/path/to/my/samples/"
sample samps, "120", "Bb", 1, lpf: 70, amp: 2
Le système de pré-argument de filtre de samples comprend deux types d’information : les sources et les filtres. Les sources sont des informations utilisées pour créer la liste des candidats potentiels. Une source peut prendre deux formes :
La fonction sample
va d’abord rassembler toutes les sources et les
utiliser pour créer une grande liste de candidats. Cette liste est
construite en ajoutant d’abord tous les chemins valides et puis en
ajoutant tous les fichiers valides .flac
, .aif
, .aiff
, .wav
,
et .wave
contenus dans les dossiers.
Par exemple, regardez le code suivant :
samps = "/path/to/my/samples/"
samps2 = "/path/to/my/samples2/"
path = "/path/to/my/samples3/foo.wav"
sample samps, samps2, path, 0
Ici nous combinons les contenus des samples de deux dossiers en y
ajoutant un sample en particulier. Si "/path/to/my/samples/"
contient
trois samples et "/path/to/my/samples2/"
en contient douze, on
aurait seize samples potentiels à indexer et filtrer (3 + 12 + 1).
Par défaut, seuls les fichiers de samples d’un dossier sont rassemblés
dans la liste de candidats. Parfois vous pourriez avoir un certain
nombre de dossiers imbriqués dans lesquels vous aimeriez chercher et
filtrer. Vous pouvez faire une recherche récursive dans tous les
samples de tous les sous-dossiers d’un dossier en particulier en
ajoutant **
à la fin du chemin :
samps = "/path/to/nested/samples/**"
sample samps, 0
Attention parce que chercher dans un très grand ensemble de dossiers peut prendre beaucoup de temps. Cela dit, le contenu des dossiers sources est mis en cache, donc le retard n’arrivera que la première fois.
Une fois qu’on a une liste de candidats on peut utiliser les types de filtres suivants pour réduire la sélection :
"foo"
: les chaînes vont filtrer sur les occurrences de sous-chaîne dans le nom du fichier (moins le chemin du dossier et l’extension)/fo[oO]/
: les expressions régulières filtrent sur des motifs du nom du fichier (moins le chemin du dossier et l’extension):foo
: les mots-clefs filtrent les candidats si le mot-clef correspond exactement au nom du fichier (moins le chemin du dossier et l’extension)lambda{ "foo" }
: les procédures sans argument seront appelées automatiquement et leur résultat sera traité comme une source ou un filtrelambda{|a| ... }
: les procédures avec un argument seront traitées comme un filtre de candidat ou une fonction génératrice. On lui passera la liste des candidats actuels et elle doit retourner une nouvelle liste de candidats (une liste de chemins valides vers des fichiers de samples)1
: Les nombres sélectionnent le candidat avec cet index (en bouclant comme un anneau si nécessaire)Enfin vous pouvez utiliser des listes partout où on peut placer une
source ou un filtre. La liste sera automatiquement aplatie et son
contenu sera traité comme des sources et filtres. Ainsi les appels
suivants à sample
sont sémantiquement équivalents :
sample "/path/to/dir", "100", "C#"
sample ["/path/to/dir", "100", "C#"]
sample "/path/to/dir", ["100", "C#"]
sample ["/path/to/dir", ["100", ["C#"]]]
C’était une section avancée pour les gens qui ont besoin de vraie puissance pour manipuler et utiliser des paquets de samples. Si la plupart de cette section n’avait pas trop de sens pour vous, ne vous inquiétez pas. Vous n’avez probablement pas encore besoin de cette fonctionnalité. Mais vous vous rendrez compte quand vous en aurez besoin et vous pourrez revenir et relire ceci quand vous commencerez à travailler avec de grands dossiers de samples.
Un grand moyen d’ajouter de l’intérêt à votre musique est d’utiliser quelques nombres aléatoires (“random”). Sonic Pi a des fonctions remarquables pour ajouter de l’aléatoire à votre musique, mais avant de commencer, nous devons apprendre une vérité choquante : dans Sonic Pi aléatoire n’est pas vraiment aléatoire. Qu’est-ce qu’ici-bas cela signifie ? Eh bien, voyons-le.
Une fonction vraiment utile est rrand
qui vous donnera une valeur
aléatoire comprise entre deux nombres - un min et un max. (rrand
est l’abréviation de “ranged random”). Essayons de jouer une note
aléatoire :
play rrand(50, 100)
Ooh, une note aléatoire a été jouée. La note 77.4407
a été
jouée - une note aléatoire sympathique entre 50 et 100. Wooh ,
attendez, est-ce que je viens juste de prédire exactement la note que
vous avez obtenue ? Quelque chose de louche se passe ici. Essayez
d’exécuter le code une nouvelle fois. Quoi ? 77.4407
a encore été
choisi ? Ce ne peut être aléatoire !
La réponse est que ce n’est pas vraiment aléatoire, c’est pseudo-aléatoire. Sonic Pi vous donne une suite d’un semblant de nombres aléatoires de manière reproductible. C’est très utile pour s’assurer que la musique que vous avez créée sur votre machine sonnera de façon identique sur n’importe quelle autre machine - même si vous utilisez de l’aléatoire dans votre composition.
Bien sûr, dans un morceau de musique donné, si 77.4407
était choisi
‘aléatoirement’ à chaque fois, ce ne serait pas très intéressant. Ce
n’est cependant pas le cas. Essayez ce qui suit :
loop do
play rrand(50, 100)
sleep 0.5
end
Oui ! ça sonne aléatoire finalement. A l’intérieur d’un run donné, des appels successifs à des fonction aléatoires retournent des valeurs aléatoires. Cependant, une nouvelle exécution produira exactement la même séquence de valeurs aléatoires et sonnera exactement pareil. C’est comme si tout le code de Sonic Pi revenait en arrière exactement au même point de départ chaque fois que le bouton “Run” était pressé. C’est le jour de la marmotte de la synthèse musicale.
Une agréable illustration de la randomisation en action est l’exemple
des cloches hantées en faisant boucler l’échantillon :perc_bell
avec
une vitesse et un temps de repos aléatoires entre les sons de cloche :
loop do
sample :perc_bell, rate: (rrand 0.125, 1.5)
sleep rrand(0.2, 2)
end
Un autre exemple sympathique de randomisation est de modifier la limite
d’un son de synthé aléatoirement. Un synthé super pour essayer cela
est l’émulateur du :tb303
:
use_synth :tb303
loop do
play 50, release: 0.1, cutoff: rrand(60, 120)
sleep 0.125
end
Alors que faire si vous n’aimez pas cette particulière séquence de
nombres aléatoires que fournit Sonic Pi ? Eh bien, c’est tout à fait
possible de choisir un point de départ via use_random_seed
. Il est
établi que la tête de série par défaut est 0, aussi choisissez une
autre tête de série pour une expérience aléatoire différente !
Envisagez ce qui suit :
5.times do
play rrand(50, 100)
sleep 0.5
end
Chaque fois que vous exécuterez ce code, vous entendrez la même séquence de 5 notes. Pour obtenir une séquence différente, changez simplement la tête de série :
use_random_seed 40
5.times do
play rrand(50, 100)
sleep 0.5
end
Ceci va produire une séquence différente de 5 notes. En changeant le tête de série et en écoutant les résultats, vous pouvez trouver quelque chose que vous aimez - et quand vous le partagerez avec d’autres, ils entendront exactement ce que vous avez aussi écouté.
Jetons un œil sur d’autres fonctions de randomisation utiles.
Une chose très commune est de choisir un item aléatoirement dans une
liste d’items connus. Par exemple, je peux vouloir jouer une note parmi
les suivantes : 60, 65 ou 72. Je peux y arriver avec choose
qui me
choisit un item dans une liste. En premier, je dois mettre mes nombres
dans une liste, ce qui est réalisé en les encadrant entre crochets et
en les séparant avec des virgules : [60, 65, 72]
. Ensuite, j’ai juste
besoin de leur passer choose
:
choose([60, 65, 72])
Écoutons comment cela sonne :
loop do
play choose([60, 65, 72])
sleep 1
end
Nous avons déja vu rrand
, mais examinons-le encore. Il retourne un
nombre aléatoire entre 2 valeurs exclues. Cela signifie qu’il ne
retournera jamais soit la borne basse, soit la borne haute - toujours
quelque chose entre les deux. Le nombre sera toujours un nombre
flottant - ce qui signifie que ce n’est pas un nombre entier, mais une
fraction de nombre. Exemple de flottants retournés par rrand(20, 110)
:
Occasionnellement, vous désirez un nombre entier aléatoire, pas un
flottant. C’est là que rrand_i
arrive à la rescousse. Il fonctionne
de façon similaire à rrand
sauf qu’il peut retourner potentiellement
les valeurs minimales et maximales comme valeurs aléatoires (ce qui
signifie que c’est inclusif plutôt qu’exclusif des bornes). Exemple de
nombres retournés par rrand_i(20, 110)
:
Cette fonction va retourner un flottant aléatoire entre 0 (inclus) et
la valeur maximale que vous spécifiez (exclue). Par défaut, elle
retourne une valeur entre 0 et 1. C’est par conséquent utile pour
choisir une valeur de amp:
aléatoire :
loop do
play 60, amp: rand
sleep 0.25
end
Similaire à la relation entre rrand_i
et rrand
, rand_i
retournera
un nombre entier compris entre 0 et la valeur maximale que vous
spécifierez.
Quelquefois, vous souhaitez émuler un jet de dés - c’est un cas
particulier de rrand_i
où la valeur minimale est toujours 1. Un appel
à dice
nécessite que vous spécifiez le nombre de faces du dé. Un
dé standard a 6 faces, donc dice(6)
agira de manière très similaire -
retournant l’une des valeurs 1, 2, 3, 4, 5, ou 6. Cependant, juste
comme dans des jeux de rôle fantaisistes, vous pourriez trouver des
dés à 4 faces, ou à 12 faces, peut-être même à 120 faces !
Finalement, vous pouvez souhaiter simuler la chance que vous avez de
tomber sur le nombre le plus élevé d’un dé, soit 6 pour un dé standard.
Ainsi one_in
retourne vrai (“true”) avec une probabilité de 1 sur le
nombre de faces du dé. Par conséquent one_in(6)
retournera vrai avec
une probabilité de 1 sur 6 ou faux (“false”) autrement. Les valeurs
True et False sont très utiles pour les ordres if
que nous couvrirons
dans une section suivante de ce tutoriel.
Maintenant allez et introduisez de l’aléatoire dans votre code !
Maintenant que vous avez appris les bases de la création des sons avec
play
et sample
et la création de mélodies simples et de rythmes
avec sleep
entre les sons, vous pourriez être en train de vous
demander ce que le monde du code peut vous offrir en plus…
Eh bien, vous y êtes et pour un voyage passionnant ! Il ressort que les structures de programmation de base telles les boucles, les conditionnels, les fonctions, les fils (“threads”) vont vous procurer des outils puissants et étonnants pour exprimer vos idées musicales.
Plongeons dans les bases…
Une structure que vous verrez souvant dans Sonic Pi est le bloc. Les blocs vous permettent de faire des choses utiles avec de grands morceaux de code. Par exemple, avec les paramètres des synthés et des échantillons, nous sommes capables de changer sur une seule ligne quelque chose qui s’est passé. Cependant, nous souhaitons quelquefois faire quelque chose de significatif sur un certain nombre de lignes de code. Par exemple, nous souhaiterions les faire boucler, leur ajouter de la réverbération, les exécuter seulement une fois sur 5, etc. Considérez le code suivant :
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
Pour faire quelque chose avec un morceau de code, nous devons dire à
Sonic Pi où commence le bloc et où il finit. Nous utilisons do
pour le début et end
pour la fin. Par exemple :
do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Toutefois, ce n’est pas encore complet et ne fonctionnera pas
(essayez-le et vous obtiendrez une erreur) puique nous n’avons pas dit
à Sonic Pi ce que nous voulions faire avec ce bloc do/end. On le dit
à Sonic Pi en écrivant du code spécial avant le do
. Nous verrons un
certain nombre de ces bouts de code spéciaux plus tard dans ce tutoriel.
Pour l’instant, il est important de savoir que d’encadrer votre code entre
do
et end
dit à Sonic Pi que vous voulez faire quelque chose de
spécial avec ce morceau de code.
Jusqu’à maintenant nous avons passé beaucoup de temps à rechercher les
différents sons que vous pouvez faire avec des blocs de play
et de
sample
. Nous avons aussi appris comment déclencher ces sons dans le
temps en utilisant sleep
.
Comme vous vous en êtes probablement rendu compte, il y a beaucoup de plaisir à avoir avec la construction de ces blocs de base. Toutefois, une dimension totalement nouvelle de plaisir se découvre quand vous commencez à utiliser la puissance du code pour structurer votre musique et vos compositions. Dans les quelques sections suivantes, nous allons explorer quelques uns de ces nouveaux outils puissants. En premier, découvrons l’itération et les boucles.
Avez-vous écrit du code que vous aimeriez répéter quelques fois ? Par exemple, vous pourriez avoir quelque chose comme ceci :
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
Que faire si nous voulions répéter ceci 3 fois ? Eh bien, nous pourrions faire simple et juste le copier et le coller trois fois : ~~~~ 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 ~~~~
Maintenant, c’est beaucoup de code ! Que se passe-t-il si nous voulions
changer l’échantillon en :elec_plip
? Vous aller devoir trouver tous
les endroits avec l’original :elec_blup
et les modifier un par un.
De façon plus importante, que faire si vous voulez répéter le bout de
code original 50 fois ou 1000 fois ? Ça ferait alors beaucoup de code,
et beaucoup de lignes de code à modifier si vous vouliez faire un
changement.
En fait, répéter le code devrait être aussi facile que de dire fais
ceci trois fois. Eh bien, c’est presque cela. Souvenez-vous de notre
vieil ami le bloc de code. Nous pouvons l’utiliser pour marquer le
début et la fin du code que nous aimerions répéter trois fois. Nous
utilisons alors le code spécial 3.times
. Ainsi, à la place d’écrire
fais cela trois fois, nous écrivons 3.times do
- Ce n’est pas trop
dur. Rappelez-vous juste d’écrire end
à la fin du code que vous
devez répéter :
3.times do
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
end
Alors, est-ce que ce n’est pas plus propre que de copier-coller ! Nous pouvons l’utiliser pour créér beaucoup de chouettes structures répétitives.
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
Nous pouvons mettre des itérations à l’intérieur d’autres itérations pour créér des motifs intéressants. Par exemple :
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
Si vous voulez répéter quelque chose un grand nombre de fois, vous
pourriez vous trouvez en situation d’utiliser des nombres vraiment
grands comme 1000.times do
. Dans ce cas, vous feriez probablement
mieux de demander à Sonic Pi de répéter à jamais (au moins jusqu’à
ce que vous pressiez le bouton stop !). Bouclons l’échantillon amen à
jamais :
loop do
sample :loop_amen
sleep sample_duration :loop_amen
end
La chose importante à savoir à propos des boucles est qu’elles se comportent comme des trous noirs pour le code. Une fois que le code est entré dans une boucle, il ne peut pas en sortir tant que vous n’avez pas pressé stop - il va juste tourner en rond dans la boucle à jamais. Ce qui signifie que si vous avez du code après la boucle, vous ne l’entendrez jamais. Par exemple, la cymbale suivant cette boucle ne sera jamais jouée :
loop do
play 50
sleep 1
end
sample :drum_cymbal_open
Maintenant, structurez votre code avec des itérations et des boucles !
Une situation commune dans laquelle vous vous trouverez probablement est
de non seulement jouer une note aléatoire (voir la précédente section
sur l’aléatoire) mais de prendre une décision aléatoire basée sur le
résultat de l’exécution d’un code ou de tel autre code. Par exemple,
vous pourriez vouloir jouer aléatoirement un tambour ou une cymbale.
Nous pouvons y parvenir avec un ordre if
(si).
Ainsi, faisons sauter une pièce : si c’est pile, joue un tambour, si
c’est face, joue une cymbale. Facile. Nous pouvons émuler le saut d’une
pièce avec notre fonction one_in
(introduite dans la section traitant
de l’aléatoire) en spécifiant une probabilité de 1 sur 2 :
one_in(2)
. Nous pouvons alors en utiliser le résultat pour décider
entre deux bouts de code, le code pour jouer le tambour et le code pour
jouer la cymbale :
loop do
if one_in(2)
sample :drum_heavy_kick
else
sample :drum_cymbal_closed
end
sleep 0.5
end
Notez que les ordres if
ont trois parties :
Typiquement, dans les langages de programmation, la notion de oui est
représenté par le terme true
(vrai) et la notion de non par le terme
false
(faux). Nous avons donc besoin de trouver une question qui nous
donnera une réponse vraie ("true")
ou fausse ("false")
, ce qui est
exactement ce que fait one_in
.
Notez comment le premier choix est encadré entre le if
et le else
,
et le second choix est encadré entre le else
et le end
. Juste comme
pour les blocs do/end, vous pouvez mettre plusieurs lignes dans chacun
de ces endroits. Par exemple :
loop do
if one_in(2)
sample :drum_heavy_kick
sleep 0.5
else
sample :drum_cymbal_closed
sleep 0.25
end
end
Cette fois nous “dormons” pour une durée différente et dépendante du choix qui est fait.
Quelquefois, nous voulons optionnellement exécuter seulement une ligne
de code. C’est possible en plaçant if
à la fin et la question à la
suite. Par exemple :
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
Ceci va jouer des accords de différents nombres avec la chance pour chaque note d’être jouée avec une probabilité différente.
(“thread” = terme technique intraduisible et dont la traduction la plus proche est “fil”)
Ainsi vous avez fait votre géniale ligne de basse et un super motif de batterie. Comment les jouez-vous en même temps ? Une solution est de les intercaler manuellement - joue quelques basses, puis quelques sons de batterie, puis encore des basses… Cependant, la synchronisation devient rapidement dure à concevoir, en particulier quand vous commencez à intercaler plus d’éléments.
Et si Sonic Pi pouvait vous synchroniser les choses automatiquement… Eh bien, il le peut, et vous le faites avec une chose spéciale appelée thread.
Pour garder cet exemple simple, vous devez imaginer que ceci est un super motif de batterie et une géniale ligne de basse :
loop do
sample :drum_heavy_kick
sleep 1
end
loop do
use_synth :fm
play 40, release: 0.2
sleep 0.5
end
Comme nous en avons parlé précédemment, les boucles sont comme des trous noirs pour un programme. Dès que vous êtes entré dans une boucle, vous ne pouvez jamais en sortir à moins de presser stop. Comment pouvons-nous jouer les deux boucles en même temps ? Nous devons dire à Sonic Pi que nous voulons démarrer quelque chose en même temps que le reste du code. C’est là que les threads arrivent à la rescousse.
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
En encadrant la première boucle dans un bloc in_thread
do/end, nous
disons à Sonic Pi d’exécuter le contenu du bloc do/end exactement
en même temps que l’ordre suivant le bloc do/end (qui se trouve être
la seconde boucle). Essayez-le et vous entendrez à la fois la batterie
et la ligne de basse synchronisées !
Maintenant, que faire si nous voulons ajouter un synthé par-dessus. quelque chose comme :
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
Maintenant, nous avons le même problème qu’avant. La première boucle
est jouée en même temps que la seconde grâce au in_thread
.
Toutefois, la troisième boucle n’est jamais atteinte. Nous avons donc
besoin d’un nouveau 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
Ce qui peut vous surprendre est que quand vous pressez le bouton Run, vous êtes réellement en train de créér un nouveau thread pour l’exécution du code. C’est pour cela qu’en le pressant de multiples fois, vous superposerez des couches de sons les unes sur les autres. Comme les “runs” sont eux-même des threads, ils intercaleront les sons automatiquement pour vous.
Etudiant comment maîtriser Sonic Pi, vous apprendrez que les threads
sont les composants les plus importants de votre musique.
L’une des responsabilités importantes qu’ils ont est d’isoler la notion
de paramètres courants vis à vis des autres threads. Qu’est-ce que
cela signifie ? Eh bien, quand vous commutez les synthés avec use_synth
,
vous ne commutez réellement que le synthé dans le thread courant -
aucun autre thread n’aura son synthé commuté. Voyons cela en action :
play 50
sleep 1
in_thread do
use_synth :tb303
play 50
end
sleep 1
play 50
Notez comme que le son du milieu était différent des autres. L’ordre
use_synth
affecte uniquement le thread dans lequel il était et pas le
thread principal et extérieur du run.
Quand vous créez un nouveau thread avec in_thread
, le nouveau thread
hérite automatiquement de tous les paramètres courants du thread
courant. Voyons cela :
use_synth :tb303
play 50
sleep 1
in_thread do
play 55
end
Notez que la seconde note est jouée avec le synthé :tb303
bien
qu’elle soit jouée depuis un thread distinct. L’un quelconque des
paramètres modifiés avec les différentes fonctions use_*
se
comportera exactement de la même manière.
Quand les threads sont créés, ils héritent de tous les paramètres de leur parent mais dès lors, ils ne partagent plus aucun changement.
Finalement, nous pouvons donner des noms à nos threads :
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
Regardez le panneau “trace” quand vous exécutez ce code. Regardez comment le “trace” rapporte le nom du thread avec le message.
[Run 36, Time 4.0, Thread :bass]
|- synth :prophet, {release: 0.6, note: 47}
Une dernière chose à savoir au sujet des threads nommés est que seul un thread d’un nom donné peut être en cours d’exécution au même moment. Explorons ceci. Considérez le code suivant :
in_thread do
loop do
sample :loop_amen
sleep sample_duration :loop_amen
end
end
Allez de l’avant et collez cela dans un buffer et pressez le bouton “run”. Pressez-le encore quelquefois. Ecoutez la cacaphonie des échantillons amen bouclant de façon désynchronisée. Ok, vous pouvez maintenant presser “stop”.
C’est le comportement que nous avons vu encore et encore - si vous pressez le bouton “run”, le son s’étend au dessus de tout son existant. Donc, si vous avez une boucle et que vous pressez le bouton “run” trois fois, vous aurez trois couches de boucles jouant simultanément.
Cependant, avec les threads nommés, c’est différent :
in_thread(name: :amen) do
loop do
sample :loop_amen
sleep sample_duration :loop_amen
end
end
Essayez de presser le bouton “run” plusieurs fois avec ce code. Vous entendrez seulement une boucle de l’échantillon amen. Vous allez aussi voir ceci dans la trace :
==> Skipping thread creation: thread with name :amen already exists.
(sautant la création d'un thread : le thread avec le nom :amen existe déjà.)
Sonic Pi vous dit qu’un thread avec le nom :amen
est déjà en train
d’être joué, donc il ne va pas en créer un autre.
Ce comportement peut ne pas vous sembler utile immédiatement - mais il sera très pratique quand nous commencerons à coder en “live”…
Une fois que vous commencez à écrire beaucoup de code, vous pouvez souhaiter trouver le moyen d’organiser et de structurer les choses pour les rendre plus ordonnées et faciles à comprendre. Les fonctions sont un moyen très puissant pour le faire. Elles vous donnent la capacité de donner un nom à un morceau de code. Jetons-y un œil.
define :foo do
play 50
sleep 1
play 55
sleep 2
end
Ici, nous avons défini une nouvelle fonction appelée foo
. Nous
faisons cela avec notre vieil ami, le bloc do/end et le mot magique
define
suivi par le nom que nous voulons donner à notre fonction.
Nous ne sommes pas tenus de l’appeler foo
, nous aurions pu l’appeler
avec n’importe quel nom que nous voulions, comme bar
, baz
ou
idéalement quelque chose de significatif pour vous comme
section_principale
ou lead_riff
.
Rappelez-vous d’ajouter un deux-points :
devant le nom de votre
fonction quand vous la définissez.
Une fois que nous avons défini notre fonction, nous pouvons l’appeler simplement en écrivant son nom :
define :foo do
play 50
sleep 1
play 55
sleep 0.5
end
foo
sleep 1
2.times do
foo
end
Nous pouvons même utiliser foo
à l’intérieur de blocs d’itération
ou n’importe où nous aurions pu écrire play
ou sample
. Ceci nous
donne un super moyen de nous exprimer et de créér de nouveaux mots
significatifs à utiliser dans nos compositions.
Pour le moment, chaque fois que nous avons pressé le bouton Run, Sonic Pi a démarré d’un état complètement vierge. Il ne savait rien à part ce qui était dans le buffer. Vous ne pouviez pas référencer du code d’un autre buffer ou d’un autre thread. Toutefois, les fonctions changent cela. Quand vous définissez une fonction, Sonic Pi s’en rappelle. Essayons-le. Effacez tout le code dans votre buffer et remplacez-le par :
foo
Pressez le bouton Run et écoutez votre fonction qui est jouée. Où le
code est-il allé ? Comment Sonic Pi sait-il quoi jouer ? Sonic Pi s’est
simplement souvenu de votre fonction - ainsi, même après l’avoir
effacée de votre buffer, il se rappelle de ce que vous avez
tapé. Ce comportement fonctionne uniquement avec les fonctions créées
en utilisant define
(et defonce
).
Vous pourriez être intéressé à savoir que juste comme vous pouvez
passer les valeurs min et max à rrand
, vous pouvez apprendre à vos
fonctions à accepter des arguments. Jetons-y un œil.
define :my_player do |n|
play n
end
my_player 80
sleep 0.5
my_player 90
Ce n’est pas très excitant, mais ça illustre le point. Nous avons
créé notre propre version de play
appelée my_player
et qui est
paramétrée.
Les paramètres doivent être placés après le do
du bloc do/end de
define
, entourés par des barres verticales |
et séparés par des
virgules ,
. Vous pouvez utiliser tout mot que vous souhaitez pour les
noms de paramètres.
La magie se passe à l’intérieur du bloc do/end de define
. Vous
pouvez utiliser les noms de paramètres comme si c’étaient des valeurs
réelles. Dans cet exemple, je joue la note n
. Vous pouvez considérer
les paramètres comme une sorte de promesse qui fait que, lorsque le code
s’exécute, ils sont remplacés par des valeurs réelles. Vous faites
ceci en passant un argument à la fonction quand vous l’appelez. Je le
fais avec my_player 80
pour jouer la note 80. À l’intérieur de la
définition de la fonction, n
est alors remplacé par 80, donc
play n
est changé en play 80
. Quand je l’appelle une nouvelle fois
avec my_player 90
, n
est alors remplacé par 90, donc play n
est
changé en play 90
.
Voyons un exemple plus intéressant :
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
Ici j’ai utilisé repeats
comme si c’était un nombre dans la ligne
repeats.times do
. J’ai aussi utilisé root
comme si c’était un nom de
note dans mon appel à play
.
Voyez comme nous sommes capables d’écrire quelque chose de très expressif et facile à lire en déplaçant beaucoup de notre logique à l’intérieur d’une fonction !
Une chose utile à faire dans votre code est d’attribuer des noms aux
choses. Sonic Pi rend cela très facile, vous écrivez le nom que vous
voulez utiliser, un signe égal (=
), puis la chose dont vous voulez
vous rappeler :
sample_name = :loop_amen
Ici, nous nous sommes ‘rappelés’ du symbole :loop_amen
dans la variable
sample_name
. Nous pouvons maintenant utiliser sample_name
partout
où nous aurions utilisé :loop_amen
. Par exemple :
sample_name = :loop_amen
sample sample_name
Il y a trois raisons principales pour utiliser des variables dans Sonic Pi : communication de la signification, gestion de la répétition et capture des résultats des choses.
Quand vous écrivez du code, c’est facile de ne penser qu’à dire à l’ordinateur comment faire le boulot - tant que l’ordinateur comprend, c’est OK. Toutefois, il est important de se rappeler qu’il n’y a pas que l’ordinateur qui lit le code. D’autres personnes peuvent aussi le lire et essayer de comprendre ce qu’il fait. En outre, il est probable que vous ayez à lire votre propre code dans le futur et à essayer de comprendre ce qui s’y passe. Bien que cela puisse vous sembler évident maintenant, ce pourrait ne pas être si évident pour les autres et pour vous-même dans le futur.
Un moyen d’aider les autres à comprendre ce que fait votre code est d’écrire des commentaires (comme nous l’avons vu dans une section précédente). Une autre façon est d’utiliser des noms de variables significatifs. Regardez ce code :
sleep 1.7533
Pourquoi utilise-t-il le nombre 1.7533
? D’où est-il venu ? Qu’est-ce
que cela signifie ? En revanche, regardez ce code :
loop_amen_duration = 1.7533
sleep loop_amen_duration
Maintenant,; il est beaucoup plus clair que 1.7533
signifie la durée
de l’échantillon :loop_amen
! Bien sûr, vous pourriez dire pourquoi
ne pas simplement écrire :
sleep sample_duration(:loop_amen)
Qui, bien entendu, est un moyen très sympathique de communiquer l’intention du code.
Vous voyez souvent beaucoup de répétitions dans votre code et quand vous voulez changer les choses, vous devez les changer à beaucoup d’endroits. Jetez un œil à ce code :
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)
Nous sommes en train de faire beaucoup de choses avec :loop_amen
!
Que faire si nous voulons écouter comment ça sonne avec un autre
échantillon tel que :loop_garzul
? Nous aurons à trouver et
remplacer tous les :loop_amen
par :loop_garzul
. Ce serait bien si
vous disposiez de beaucoup de temps - mais que faire si vous œuvrez sur
scène ? Quelquefois, vous n’aurez pas le luxe de temps disponible - en
particulier si vous voulez que les gens continuent à danser.
Et si vous aviez écrit votre code comme ceci :
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)
Maintenant, ça fait exactement la même chose qu’au dessus (essayez-le).
Ça nous procure aussi la capacité de changer juste une ligne :
sample_name = :loop_amen
en sample_name = :loop_garzul
et la magie
des variables nous le change dans beaucoup d’endroits.
Finalement, une bonne motivation pour utiliser des variables est de capturer les résultats des choses. Par exemple, vous pouvez vouloir faire des choses avec la durée d’un échantillon :
sd = sample_duration(:loop_amen)
Nous pouvons maintenant utiliser sd
partout où nous avons besoin de
la durée de l’échantillon :loop_amen
.
Plus important peut-être, une variable nous permet de capturer le
résultat d’un appel à play
ou sample
:
s = play 50, release: 8
Maintenant, nous avons capturé et mémorisé s
comme une variable, ce
qui nous permet de contrôler le synthé pendant qu’il est actif :
s = play 50, release: 8
sleep 2
control s, note: 62
Nous verrons le contrôle des synthés en plus détaillé dans une prochaine section.
Une fois que vous êtes suffisamment avancés en codage “live” avec un certain nombre de fonctions et de threads en simultanéité, vous avez probablement remarqué que c’est plutôt facile de faire une faute dans l’un des threads et qui lui met fin. Ce n’est pas un gros problème car vous pouvez facilement redémarrer le thread en pressant Run. Toutefois, quand vous redémarrez le thread, il se trouve alors déphasé avec les threads d’origine.
Comme nous en avons discuté auparavant, les nouveaux threads créés
avec in_thread
héritent de tous les paramètres du thread parent.
Ceci inclut l’heure actuelle. Ce qui signifie que les threads sont
toujours en phase entre eux quand ils sont démarrés simultanément.
Toutefois quand vous démarrez un thread tout seul, il démarre avec sa propre heure qui n’est probablement pas en phase avec l’un quelconque des autres threads en cours d’exécution.
Sonic Pi fourni une solution à ce problème avec les fonctions cue
et
sync
.
cue
nous permet d’envoyer nos messages de battement de coeur à tous
les autres threads. Par défaut, les autres threads ne sont pas
intéressés et ignorent ces messages de battement de coeur. Cependant,
vous pouvez leur déclarer de l’intérêt avec la fonction sync
.
La chose importante à laquelle il faut être attentif est similaire à
sleep
, en ce sens que cela arrête le thread courant en l’empêchant de
faire quoi que ce soit pendant un moment. Toutefois, avec sleep
, vous
spécifiez combien de temps vous voulez attendre tandis qu’avec sync
,
vous ne savez pas combien de temps vous allez attendre - étant donné
que sync
attend le cue
suivant d’un autre thread, ce qui peut être
court ou long.
Explorons ceci en un peu plus de détail :
in_thread do
loop do
cue :tick
sleep 1
end
end
in_thread do
loop do
sync :tick
sample :drum_heavy_kick
end
end
Nous avons ici deux threads - l’un agissant comme un métronome, ne
jouant aucun son mais envoyant des messages de battement de coeur
tick
à chaque temps. Le second thread se synchronise sur les messages
tick
et quand il en reçoit un, il hérite de l’heure du thread cue
et continue de jouer.
Par conséquent, nous entendons l’échantillon :drum_heavy_kick
exactement quand l’autre thread envoie le message tick
, même si les
deux threads n’ont pas démarré leur exécution en même temps :
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
Ce vilain appel à sleep
mettrait typiquement le second thread en
déphasage avec le premier. Cependant, comme nous utilisons cue
et
sync
, nous synchronisons automatiquement les threads en évitant un
décalage de temps accidentel.
Vous êtes libre d’utiliser n’importe quel nom que vous aimeriez pour
vos messages cue
. Vous devez juste vous assurer que tout autre thread
se synchronise sur le bon nom - autrement il attendrait à jamais (au
moins jusqu’à ce que vous pressiez le bouton Stop).
Jouons avec quelques noms de 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
Ici, nous avons une boucle principale cue
qui envoie aléatoirement un
des battements de coeur nommés :foo
, :bar
ou :baz
. Nous avons
aussi ensuite trois boucles en thread se synchronisant sur ces noms
indépendamment et jouant un échantillon différent. Il est clair
que nous entendons un son à chaque demi-temps puisque chacun des
threads sync
est aléatoirement synchronisé avec le thread cue
et
joue son échantillon.
Ceci, bien entendu, marche aussi si vous ordonnez les threads en sens
inverse puisque les threads sync
restent en attente du cue
suivant.
Un des aspects les plus gratifiants et sympathiques de Sonic Pi est la capacité d’ajouter des effets de studio à vos sons. Par exemple, vous pouvez vouloir ajouter de la réverbération à des parties de votre œuvre, ou de l’écho et peut-être même de la distorsion ou du trémolo à vos lignes de basse.
Sonic Pi fournit un moyen très simple mais cependant puissant pour ajouter des effets (FX). Il vous autorise même à les chaîner (ainsi vous pouvez passer vos sons dans la distorsion, puis dans l’écho, puis dans la réverbération) et aussi à contrôler chaque unité FX individuellement avec des paramètres (d’une façon similaire à la spécification des paramètres pour les synthés et les échantillons). Vous pouvez même modifier les paramètres d’un FX pendant qu’il est encore en train d’agir. Ainsi, par exemple, vous pouvez augmenter la réverbération de vos basses tout au long de la piste…
Si tout ceci paraît un tantinet compliqué, ne vous inquiétez pas. Une fois que vous aurez joué un peu avec, tout deviendra complètement clair. Avant qu’il en soit ainsi, faisons une simple analogie avec des pédales FX de guitare. Il y a des tas de sortes de pédales FX que vous pouvez acheter. Quelques unes ajoutent de la réverbération, d’autres de la distorsion, etc. Un guitariste va brancher sa guitare à une pédale FX - de distorsion par exemple - puis prendre un autre câble pour lui connecter (chaîner) une pédale de réverbération. La sortie de la pédale de réverbération pourra alors être branchée à l’amplificateur :
Guitare -> Distorsion -> Réverbération -> Amplificateur
Cela s’appelle le chaînage des FX. Sonic Pi supporte exactement cela. De plus, chaque pédale a souvent des molettes et des curseurs pour vous permettre de contrôler le montant de la distorsion, de la réverbération, de l’écho, etc. à appliquer. Sonic Pi supporte aussi ce type de contrôle. Finalement, vous pouvez imaginer un guitariste jouant pendant que quelqu’un joue avec les contrôles FX même s’ils sont en train d’agir. Sonic Pi supporte aussi ceci - mais au lieu d’avoir besoin de quelqu’un d’autre pour contrôler les choses pour vous, c’est l’ordinateur qui intervient.
Explorons les FX !
Dans cette section, nous allons regarder un couple de FX : réverbération et écho. Nous allons voir comment les utiliser, comment contrôler leurs paramètres et comment les chaîner.
Le système des FX de Sonic Pi utilise les blocs. Donc, si vous n’avez pas lu la section 5.1, vous pourriez vouloir lui jeter un œil et puis revenir ici.
Si nous voulons utiliser la réverbération, nous écrivons with_fx :reverb
en tant qu’entête particulière de notre bloc, comme ceci :
with_fx :reverb do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Maintenant exécutez ce code et vous l’entendrez joué avec réverbération. Ça sonne bien, n’est-ce pas ! Toute chose sonne plutôt agréablement avec de la réverbération.
Maintenant, voyons ce qui se passe si nous avons du code en dehors du bloc do/end :
with_fx :reverb do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
sleep 1
play 55
Remarquez que le dernier play 55
n’est pas joué avec de la
réverbération. C’est parce qu’il est en dehors du bloc do/end, ainsi
le FX de réverbération n’agit pas sur lui.
Similairement, si vous placez des sons avant le bloc do/end, ils ne seront pas non plus affectés :
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
Il y a beaucoup de FX au choix. Que dire au sujet de l’écho ?
with_fx :echo do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Un des puissants aspects des blocs FX de Sonic Pi est qu’on peut leur
passer des paramètres de manière similaire aux paramètres que nous
avons déjà vus avec play
et sample
. Par exemple, un paramètre
sympa d’écho avec lequel jouer est phase:
. Il représente la durée
d’un écho en temps musicaux. Faisons l’écho plus lent :
with_fx :echo, phase: 0.5 do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Faisons aussi l’écho plus rapide :
with_fx :echo, phase: 0.125 do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Faisons décroître l’écho plus longuement en spécifiant la durée de decay:
à 8 temps :
with_fx :echo, phase: 0.5, decay: 8 do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Un des aspects les plus puissants des blocs FX est que vous pouvez les imbriquer. Ce qui vous permet de chaîner facilement les FX entre eux. Par exemple, que faire si vous vouliez jouer du code avec de l’écho et ensuite de la réverbération ? Facile, mettez simplement l’un à l’intérieur de l’autre :
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
Pensez à du son provenant de l’intérieur et se propageant vers
l’extérieur. Le son de tout le code situé dans le bloc intérieur dont
play 50
est d’abord envoyé vers le FX écho et le son produit par le FX
écho est à son tour envoyé vers le FX réverbération.
Nous pouvons utiliser des imbrications très profondes pour des résultats délirants. Toutefois, soyez averti, les FX peuvent utiliser beaucoup de ressources et quand vous les imbriquez, vous allez effectivement faire agir de multiples FX simultanément. Donc soyez économe avec l’utilisation des FX, en particulier sur des plateformes peu puissantes telles que le Raspberry Pi.
Sonic Pi est livré avec un grand nombre de FX avec lesquels vous pouvez jouer. Pour trouver ceux qui sont disponibles, cliquez sur “FX” dans le menu horizontal du système d’aide et vous verrez une liste des options disponibles. Voici une liste de mes préférés :
Maintenant, défoulez-vous et ajoutez des effets partout pour obtenir d’étonnants sons nouveaux !
Bien qu’ils paraissent trompeusement simples extérieurement, les FX sont réellement des bêtes plutôt complexes à l’intérieur. Leur simplicité incite souvent les gens à en abuser dans leurs morceaux. Ce peut être sympathique si vous avez une machine puissante, mais si - comme moi - vous utilisez un Raspberry Pi pour improviser, vous devez prendre garde à la somme de travail que vous lui demandez de faire si vous voulez vous assurer que la cadence reste fluide.
Considérez ce code :
loop do
with_fx :reverb do
play 60, release: 0.1
sleep 0.125
end
end
Dans ce code, nous jouons la note 60 avec une durée d’extinction très courte, c’est donc une note courte. Nous voulons aussi de la réverbération, alors nous l’avons imbriqué dans un bloc de réverbération. Jusqu’à maintenant, tout est bon. Sauf que…
Regardons ce que fait le code. En premier lieu, nous avons une boucle
(loop
), ce qui signifie que tout ce qui est à l’intérieur est
répété sans fin. Ensuite, nous avons un bloc with_fx
. Ceci veut dire
que nous allons créer un nouvel FX de réverbération chaque fois que
nous bouclons. C’est comme si nous disposions d’une pédale de
réverbération distincte à chaque fois que nous pincions une corde sur
une guitare. C’est super de pouvoir faire ça, mais ce n’est pas
toujours ce que vous voulez. Par exemple, ce code va avoir du mal à
s’exécuter comme il faut sur un Raspberry Pi. Tout le travail de création
de la réverbération puis d’attente jusqu’à ce qu’elle doive être
stoppée et enlevée est complètement pris en charge par with_fx
pour
vous, mais ceci prend de la puissance du microprocesseur (CPU) qui peut
être précieuse.
Comment le faire d’une manière plus proche d’une installation traditionnelle où notre guitariste n’a qu’une pédale de réverbération dans laquelle passent tous les sons ? Simple :
with_fx :reverb do
loop do
play 60, release: 0.1
sleep 0.125
end
end
Nous mettons notre boucle à l’intérieur du bloc with_fx
. De cette
façon, nous créons seulement une unique réverbération pour toutes les
notes jouées dans notre boucle. Ce code est beaucoup plus efficace et
fonctionnerait bien sur un Raspberry Pi.
Un compromis est d’utiliser with_fx
sur une itération à l’intérieur
d’une boucle :
loop do
with_fx :reverb do
16.times do
play 60, release: 0.1
sleep 0.125
end
end
end
De cette façon, nous avons remonté le with_fx
en dehors de la partie
la plus intérieure de la boucle, et nous créons maintenant une
nouvelle réverbération toutes les 16 notes.
C’est quelque chose que l’on fait si souvent que with_fx
supporte
une option pour faire exactement cela sans devoir écrire le bloc
16.times
:
loop do
with_fx :reverb, reps: 16 do
play 60, release: 0.1
sleep 0.125
end
end
Les deux exemples reps: 16
et 16.times do
se comporteront de la
même manière. L’exemple avec reps: 16
répète en fait le code dans le
bloc do/end
seize fois donc vous pouvez choisir l’un ou l’autre en
fonction de vos préférences.
Rappelez-vous, il n’y a pas de fautes, juste des possibilités. Toutefois, certaines de ces approches donneront un son différent et auront des caractéristiques de performance différentes. Donc, jouez et utilisez l’approche qui sonne le mieux pour vous tout en restant dans les contraintes de performance de votre plateforme.
Pour l’instant, nous avons regardé comment déclencher des sons de synthé et des échantillons, et aussi comment changer leur paramètres par défaut comme amplitude, balance, paramètres d’enveloppe, et plus. Chaque son émis est essentiellement son propre son avec son propre ensemble de paramètres fixés pour la durée du son.
Ne serait-ce pas sympathique si nous pouvions changer les paramètres d’un son pendant qu’il est encore en train d’être joué, juste comme vous pourriez tendre une corde de guitare pendant qu’elle est en train de vibrer ?
Vous êtes chanceux - cette section va vous montrer précisément comment le faire.
Pour l’instant, nous nous sommes seulement préoccupés de déclencher de nouveaux sons et effets (FX). Toutefois, Sonic Pi nous offre la capacité de manipuler et de contrôler les sons pendant qu’il sont joués. Nous le faisons en utilisant une variable pour mémoriser la référence à un synthé.
s = play 60, release: 5
Ici, nous avons une variable locale d’exécution s
qui représente le
synthé jouant la note 60. Notez que c’est local à l’exécution -
vous ne pouvez pas y accéder depuis d’autres exécutions comme les
fonctions.
Une fois que nous avons s
, nous pouvons commencer à le contrôler via
la fonction 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
La chose à remarquer est que nous ne sommes pas en train de déclencher 4 synthés différents - Nous en déclenchons seulement un et puis nous changeons ensuite 3 fois la hauteur, pendant qu’il joue.
Nous pouvons passer n’importe quel paramètre standard à control
,
vous pouvez donc contrôler des choses telles que amp:
, cutoff:
ou
pan
.
Quelques paramètres ne peuvent pas être contrôlés une fois que le synthé joue. C’est le cas pour tous les paramètres d’enveloppe ADSR. Vous pouvez trouver quels paramètres sont contrôlables en regardant leur documentation dans le système d’aide. Si la documentation dit Can not be changed once set (ne peut être modifié une fois attribué), vous savez que ce n’est pas possible de contrôler le paramètre après que le synthé ait commencé à jouer.
Il est aussi possible de contrôler les FX, bien que ce soit accompli d’une manière légèrement différente :
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
Au lieu d’utiliser une variable, nous utilisons le paramètre cible
d’un bloc do/end. A l’intérieur des barres verticales |
, nous devons
attribuer un nom unique à notre FX en cours, nom que nous référençons
alors depuis l’intérieur du bloc do/end.
Maintenant, allez et contrôlez des synthés et des FX !
Pendant l’exploration des arguments de pilotage des synthés et des FX,
vous pourriez avoir remarqué qu’il y a un certain nombre de paramètres
finissant par _slide
. Vous avez peut-être même essayé de les appeler et
n’avez constaté aucun effet. C’est parce que ce ne sont pas des
paramètres normaux, ce sont des paramètres spéciaux qui n’agissent
que quand vous contrôlez les synthés comme cela est décrit
dans la section précédente.
Considérez l’exemple suivant :
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
Ici, vous pouvez entendre la hauteur du son changer instantanément
après l’appel à control
. Toutefois, nous pourrions souhaiter que la
hauteur glisse entre les changements. Comme nous sommes en train de
contrôler le paramètre note:
, pour ajouter un glissement, nous
devons fixer le paramètre note_slide
du synthé :
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
Maintenant, nous entendons la hauteur des notes glisser entre les
appels à control
. Ça sonne agréablement, n’est-ce pas ? Vous pouvez
accélérer le glissement en utilisant une durée plus courte comme
note_slide: 0.2
ou le ralentir en utilisant une durée de glissement
plus longue.
Chaque paramètre qui peut être contrôlé a un paramètre correspondant
avec _slide
à votre disposition.
Une fois que vous avez fixé un paramètre _slide
à un synthé en
cours de jeu, il sera mémorisé et appliqué à chaque fois que le
paramètre correspondant sera utilisé. Pour arrêter le glissement,
vous devez fixer la valeur de _slide
à 0 avant l’appel suivant à
control
.
Il est aussi possible de faire glisser les paramètres FX :
with_fx :wobble, phase: 1, phase_slide: 5 do |e|
use_synth :dsaw
play 50, release: 5
control e, phase: 0.025
end
Maintenant ayez du plaisir à faire glisser les choses pour obtenir des transitions douces et un contrôle fluide…
Un outil très utile de la boîte à outil d’un programmeur est la structuration des données.
Quelquefois, vous souhaiteriez représenter et utiliser plus d’une seule chose à la fois, vous pourriez trouver utile de disposer d’une série de notes à jouer l’une après l’autre. Les langages de programmation offrent des structures de données pour autoriser précisément ceci.
Il y a beaucoup de structures de données passionnantes et exotiques à disposition des programmeurs - et on en invente toujours de nouvelles. Cependant, pour l’instant nous avons seulement et réellement besoin de nous intéresser à une structure de données très simple - la liste.
Regardons-la de manière plus détaillée. Nous allons décrire sa forme basique et ensuite montrer comment l’utiliser pour représenter des gammes et des accords.
Dans cette section, nous allons voir une structure de données qui est très utile - la liste. Nous l’avons rencontrée brièvement auparavant dans la section sur la randomisation quand nous choisissions aléatoirement des notes à jouer dans une liste :
play choose([50, 55, 62])
Dans cette section, nous allons explorer l’utilisation des listes
également pour représenter des accords et des gammes. En premier lieu,
récapitulons comment nous jouerions un accord. Souvenez-vous que si
nous n’utilisons pas sleep
, les sons arrivent tous au même moment :
play 52
play 55
play 59
Regardons une autre façon d’écrire ce code.
Une option est de placer toutes les notes dans une liste : [52, 55, 59]
.
Notre sympathique fonction play
est assez évoluée pour savoir
comment jouer une liste de notes. Essayez-le :
play [52, 55, 59]
Ooh, c’est déjà plus agréable à lire. Jouer une liste de notes ne vous empêche pas d’utiliser n’importe quel paramètre des spécifications :
play [52, 55, 59], amp: 0.3
Bien sûr, vous pouvez aussi utiliser les noms traditionnels des notes (en notation anglaise) à la place des nombres de la norme MIDI :
play [:E3, :G3, :B3]
Maintenant, ceux qui sont assez chanceux pour avoir étudié quelques notions de solfège, pourraient reconnaître l’accord de Mi mineur joué à la 3ème octave.
Une autre caractéristique très utile d’une liste est d’en extraire de l’information. Ceci peut paraître étrange, mais ce n’est pas plus compliqué que de tourner les pages d’un livre jusqu’à la page 23. Avec une liste, vous diriez : quel est l’élément à l’index 23 ? La seule chose étrange est qu’en programmation, les index commencent généralement à 0 et non pas 1.
Avec les index de liste, nous ne comptons pas 1, 2, 3… mais 0, 1, 2…
Regardons ceci en un peu plus de détails. Jetez un œil sur cette liste :
[52, 55, 59]
Il n’y a rien là de particulièrement effrayant. Maintenant,
quel est le second élément de la liste ? Oui, bien sûr, c’est 55
.
C’était facile. Regardons si nous pouvons obtenir la réponse de
l’ordinateur :
puts [52, 55, 59][1]
OK, ça semble un peu bizarre si vous n’avez jamais vu quelque chose de
la sorte auparavant. Faites-moi confiance toutefois, ce n’est pas trop
dur. Il y a trois parties dans la ligne ci-dessus : le mot puts
,
notre liste 52, 55, 59
et notre index [1]
. En premier, nous disons
puts
parce que nous voulons que Sonic Pi nous affiche la réponse dans
le panneau “trace”. Ensuite, nous lui donnons notre liste, et enfin notre
index qui demande le second élément. Nous devons encadrer notre index
avec des crochets et parce que le compte commence à 0, l’index pour le
second élément est 1
. Regardez :
# index : 0 1 2
[52, 55, 59]
Essayez d’exécuter le code puts [52, 55, 59][1]
et vous verrez 55
apparaître dans le panneau “trace”. Changez l’index 1
par d’autres
valeurs, essayez des listes plus longues et pensez à la façon dont
vous pourriez utiliser une liste dans votre prochaine improvisation
avec du code. Par exemple, quelles structures musicales pourraient être
représentées par une série de nombres…
Sonic Pi incorpore le support des noms d’accord, lequel retourne des listes. Essayez-le vous-même :
play chord(:E3, :minor)
Maintenant, nous avons vraiment progressé. Ça parait beaucoup plus joli que les listes brutes (et c’est plus facile à lire pour les autres). Alors quels autres accords Sonic Pi supporte-t-il ? Eh bien, un tas. Essayez quelques uns parmi ceux-ci :
chord(:E3, :m7)
chord(:E3, :minor)
chord(:E3, :dim7)
chord(:E3, :dom7)
Nous pouvons facilement changer les accords en arpèges avec la fonction
play_pattern
:
play_pattern chord(:E3, :m7)
OK, ce n’est pas si plaisant - ça le joue vraiment lentement.
play_pattern
va jouer chaque note de la liste en le séparant par un
appel à sleep 1
entre chaque appel à play
. Nous pouvons utiliser
une autre fonction play_pattern_timed
pour spécifier nos propres
durées et accélérer les choses :
play_pattern_timed chord(:E3, :m7), 0.25
Nous pouvons même passer une liste de durées qui seront traitées de façon circulaire :
play_pattern_timed chord(:E3, :m13), [0.25, 0.5]
Ceci est équivalent à :
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
Que préférez-vous écrire ?
Sonic Pi supporte un large éventail de gammes. Comment faire pour jouer une gamme majeure de Do3 (C3) ?
play_pattern_timed scale(:c3, :major), 0.125, release: 0.1
Nous pouvons même demander plusieurs octaves :
play_pattern_timed scale(:c3, :major, num_octaves: 3), 0.125, release: 0.1
Comment obtenir toutes les notes d’une gamme pentatonique ?
play_pattern_timed scale(:c3, :major_pentatonic, num_octaves: 3), 0.125, release: 0.1
Les accords et les gammes sont un grand moyen de contraindre un choix aléatoire à quelque chose de significatif. Jouez un instant avec cet exemple qui prend des notes aléatoirement dans l’accord mineur de Mi3 :
use_synth :tb303
loop do
play choose(chord(:E3, :minor)), release: 0.3, cutoff: rrand(60, 120)
sleep 0.25
end
Essayez de modifier cet exemple avec quelques noms d’accord différents et des plages de cutoff différentes.
Pour trouver quelles gammes et quels accords sont supportés par Sonic
Pi, cliquez sur le bouton “Lang” du menu horizontal à gauche et au bas
de la fenêtre, et choisissez soit “chord” (accord) ou “scale” (gamme)
dans la liste du dessus. Dans le panneau d’information, faites défiler
l’affichage vers le bas jusqu’à voir une longue liste d’accords ou de
gammes (selon ce que vous êtes en train de chercher).
Faites-vous plaisir et rappelez-vous : il n’y a pas de fautes, que des opportunités.
Un parcours circulaire intéressant sur les listes est fourni par les anneaux (“rings”). Si vous avez quelques connaissances en programmation, vous pourriez avoir eu affaire aux “ring buffers” ou aux “ring arrays”. Ici, nous allons juste voir les “rings” - c’est court et simple.
Dans la section précédente sur les listes, nous avons vu comment nous pouvions aller en chercher des éléments en utilisant le mécanisme d’indexage :
puts [52, 55, 59][1]
Maintenant, qu’arrive-t-il si vous voulez l’index 100
? Eh bien,
c’est clair qu’il n’y a pas d’élément à l’index 100 puisque la liste
ne contient que trois éléments. Alors Sonic Pi retournera nil
(qui
veut dire “rien”).
Maintenant, imaginons que nous ayons un compteur tel que celui des temps musicaux et qui s’incrémente continuellement. Créons notre compteur et notre liste :
counter = 0
notes = [52, 55, 59]
Nous pouvons maintenant utiliser notre compteur pour accéder à une note de notre liste :
puts notes[counter]
Super, nous avons obtenu 52
. Maintenant, incrémentons notre compteur
et obtenons une autre note :
counter = (inc counter)
puts notes[counter]
Super, nous obtenons maintenant 55
et si nous le faisons une nouvelle
fois, nous obtenons 59
. Toutefois, si nous le faisons encore une
nouvelle fois, nous allons nous trouver en dehors des nombres de notre
liste et obtenir nil
. Que faire si nous voulions juste boucler en
revenant en arrière et recommencer au début de la liste ? C’est pour
cela que les anneaux (“rings”) sont faits.
Nous pouvons créer des anneaux de deux façons. Ou bien nous utilisons la
fonction ring
avec les élements de l’anneau comme paramètres :
(ring 52, 55, 59)
Ou bien nous pouvons prendre une liste normale et la convertir en
anneau en lui envoyant le message .ring
:
[52, 55, 59].ring
Une fois que nous avons un anneau, nous pouvons l’utiliser de la même manière que nous utiliserions une liste normale avec l’exception que nous pouvons utiliser des index négatifs ou des index qui sont plus grands que la taille de l’anneau, et ils vont boucler tout autour jusqu’à pointer sur un des éléments de l’anneau :
(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
Mettons que nous utilisions une variable pour représenter le numéro de battement courant. Nous pouvons l’utiliser comme un index de notre anneau pour aller chercher les notes à jouer, ou les durées d’extinction ou n’importe quelle chose utile que nous avons mémorisée dans notre anneau sans se préoccuper de la valeur du numéro de battement en cours.
Une chose utile à savoir est que les listes retournées par scale
et
chord
sont aussi des anneaux et cela vous autorise à les accéder
avec des valeurs d’index arbitraires.
En sus de ring
, il y a un certain nombre de fonctions qui vous
construiront un anneau.
range
vous invite à spécifier un point de départ, un point de
fin, et la taille du pas.bools
vous permet d’utiliser des 1
s et 0
s pour représenter les
booléens de manière condensée.knit
vous permet de créer une séquence de valeurs dupliquées.spread
crée un anneau de booléens avec une distribution euclidienne.Jetez un œil à leur documentation respective pour plus d’information.
En plus des constructeurs comme range
et spread
, une autre façon
de créer de nouveaux anneaux est de manipuler des anneaux existants.
Pour explorer ceci, prenons un anneau simple :
(ring 10, 20, 30, 40, 50)
Et si on voulait son inverse ? Eh bien on utiliserait la commande
de chaîne .reverse
pour prendre l’anneau et l’inverser :
(ring 10, 20, 30, 40, 50).reverse #=> (ring 50, 40, 30, 20, 10)
Et si on voulait les trois premières valeurs de l’anneau ?
(ring 10, 20, 30, 40, 50).take(3) #=> (ring 10, 20, 30)
Enfin, et si on voulait mélanger l’anneau ?
(ring 10, 20, 30, 40, 50).shuffle #=> (ring 40, 30, 10, 50, 20)
C’est déjà une manière puissante de créer de nouveaux anneaux. Ceci dit la vraie puissance vient quand on enchaîne quelques unes de ces commandes à la suite.
Et si on mélangeait l’anneau, on lâchait un élément puis on en prenait les trois suivants ?
Regardons ceci par étapes :
(ring 10, 20, 30, 40, 50)
- notre anneau initial(ring 10, 20, 30, 40, 50).shuffle
- mélange - (ring 40, 30, 10, 50, 20)
(ring 10, 20, 30, 40, 50).shuffle.drop(1)
- en lâche un - (ring 30, 10, 50, 20)
(ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3)
- en prend trois - (ring 30, 10, 50)
Vous voyez comme on peut créer une longue chaîne de ces méthodes juste en les collant à la suite. On peut les combiner dans l’ordre qu’on veut, ce qui crée une manière extrêmement riche et puissante de générer de nouveaux anneaux à partir d’anneaux existants.
Ces anneaux ont une propriété puissante et importante. Ils sont immutables, ce qui veut dire qu’ils ne peuvent pas changer. Cela veut dire que les méthodes de chaîne décrites dans cette section ne changent pas les anneaux, elles créent plutôt de nouveaux anneaux. Cela veut dire que vous êtes libres de partager des anneaux entre fils et de les chaîner dans un fil en sachant que vous n’affecterez aucun autre fil qui utilise le même anneau.
Voici une liste des méthodes de chaîne disponibles :
.reverse
- retourne une version inversée de l’anneau.sort
- crée une version triée de l’anneau.shuffle
- crée une version mélangée de l’anneau.pick(3)
- retourne un anneau avec le résultat de trois appels à .choose
.pick
- similaire à .pick(3)
mais la taille correspond à la taille de l’anneau initial.take(5)
- retourne un nouvel anneau contenant uniquement les cinq premiers éléments.drop(3)
- retourne un nouvel anneau avec tout sauf les trois premiers éléments.butlast
- retourne un nouvel anneau sans le dernier élément.drop_last(3)
- retourne un nouvel anneau sans les trois derniers éléments.take_last(6)
- retourne un nouvel anneau avec les six derniers éléments seulement.stretch(2)
- répète chaque élément dans l’anneau deux fois.repeat(3)
- répète l’anneau entier trois fois.mirror
- ajoute l’anneau à une version inversée de lui-même.reflect
- comme mirror mais sans dupliquer la valeur du milieuEvidemment, les méthodes de chaîne qui prennent des nombres peuvent
prendre d’autres nombres aussi ! N’hésitez donc pas à appeler
.drop(5)
au lieu de .drop(3)
si vous voulez lâcher les cinq
premiers éléments.
Un des aspects les plus passionnants de Sonic Pi est qu’il vous permet d’écrire et de modifier du code en “live” pour faire de la musique, juste comme vous le feriez avec une guitare. Un avantage de cette approche est qu’il vous procure plus de feedback pendant que vous composez (avoir une simple boucle en cours d’exécution et continuer à l’ajuster jusqu’à qu’elle sonne parfaitement). Cependant, le principal avantage est que vous pouvez amener Sonic Pi sur scène et donner un concert avec.
Dans cette section, nous allons couvrir les fondamentaux du changement de vos compositions en interprétations dynamiques avec du code statique.
Tenez-vous bien…
Maintenant nous en avons suffisamment appris pour commencer réellement à prendre du plaisir. Dans cette section, nous allons mettre en pratique toutes les sections précédentes et vous montrer comment commencer à faire vos compositions musicales en “live” et les transformer en interprétations. Pour cela, nous aurons besoin de trois ingrédients principaux :
D’accord, allons-y. Codons en “live” nos premiers sons. En premier lieu, nous avons besoin d’une fonction contenant le code que nous voulons jouer. Commençons simple. Nous voulons aussi une boucle d’appels à cette fonction dans un thread :
define :my_loop do
play 50
sleep 1
end
in_thread(name: :looper) do
loop do
my_loop
end
end
Si ça vous semble un petit peu trop compliqué, revenez en arrière et relisez les sections sur les fonctions et les threads. Ce n’est pas trop compliqué si vous avez déjà emmagasiné ces choses dans votre tête.
Ce que nous avons ici est une définition de fonction qui joue juste la
note 50 et qui dort pendant un temps musical. Nous définissons ensuite un
thread nommé :looper
qui simplement boucle en appelant my_loop
de
manière répétitive.
Si vous exécutez ce code, vous entendrez la note 50 répétée encore et encore…
Maintenant, c’est là que le plaisir commence. Pendant que le code est encore en cours d’exécution changez 50 en un autre nombre, disons 55, ensuite pressez le bouton “Run” une nouvelle fois. Woah ! C’est modifié ! En “live” !
Une nouvelle couche n’a pas été ajoutée parce que nous avons utilisé
des threads nommés et que seul un thread est permis pour chaque nom. En
outre, le son a changé parce que nous avons redéfini la fonction.
Nous avons donné à :my_loop
une nouvelle définition. Quand le thread
:looper
a rebouclé, il a simplement appelé la nouvelle définition.
Essayez de le modifier encore, changez la note, changer la durée de
sleep. Comment faire pour ajouter un ordre use_synth
? Par exemple,
changez-le en :
define :my_loop do
use_synth :tb303
play 50, release: 0.3
sleep 0.25
end
Maintenant, ça sonne plutôt intéressant, mais on peut le pimenter un peu plus. Au lieu de jouer la même note encore et encore, essayez de jouer un accord :
define :my_loop do
use_synth :tb303
play chord(:e3, :minor), release: 0.3
sleep 0.5
end
Comment faire pour jouer des notes de l’accord aléatoirement :
define :my_loop do
use_synth :tb303
play choose(chord(:e3, :minor)), release: 0.3
sleep 0.25
end
Ou utiliser une valeur de cutoff aléatoire :
define :my_loop do
use_synth :tb303
play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
sleep 0.25
end
Finalement, ajoutons quelques notes de batterie :
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
Maintenant, les choses commencent à devenir passionnantes !
Toutefois, avant que vous bondissiez et que vous vous lanciez dans le
codage en “live” avec des fonctions et des threads, arrêtez ce que vous
êtes en train de faire et lisez la section suivante sur live_loop
qui
va vous changer à jamais votre façon de coder dans Sonic Pi…
Ok, ainsi cette section est la véritable perle. Si vous ne lisez qu’une
section, ce devrait être celle-ci. Si vous avez lu la section
précédente sur les fondamentaux du codage en “live”, live_loop
est
une manière simple de faire exactement la même chose mais sans avoir
tant à écrire.
Si vous n’avez pas lu la section précédente, live_loop
est la
meilleure façon d’improviser avec Sonic Pi.
Jouons. Ecrivez le code suivant dans un buffer :
live_loop :foo do
play 60
sleep 1
end
Maintenant pressez le bouton “Run”. Vous entendez un beep basique à
chaque temps. Rien de plaisant pour l’instant. Toutefois, ne pressez
pas tout de suite le bouton “Stop”. Changez le 60
en 65
et pressez
“Run” à nouveau.
Woah ! Ça a changé automatiquement sans manquer un temps. C’est du codage en “live”.
Pourquoi ne pas le modifier pour ressembler plus à une basse ? Modifiez juste votre code pendant que ça joue :
live_loop :foo do
use_synth :prophet
play :e1, release: 8
sleep 8
end
Puis pressez “Run”.
Faisons bouger le cutoff aléatoirement :
live_loop :foo do
use_synth :prophet
play :e1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
Puis pressez “Run” à nouveau.
Ajoutez de la batterie :
live_loop :foo do
sample :loop_garzul
use_synth :prophet
play :e1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
Changez la note de e1
en c1
:
live_loop :foo do
sample :loop_garzul
use_synth :prophet
play :c1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
Maintenant, arrêtez de me suivre et jouez vous-même ! Prenez du plaisir !
Considérez la boucle en “live” suivante :
live_loop :foo do
play 50
sleep 1
end
Vous pouvez vous être demandé pourquoi elle avait besoin du nom :foo
.
Ce nom est important parce qu’il signifie que cette boucle est
différente des autres boucles en “live”.
Il ne peut y avoir deux boucles en “live” en cours d’exécution avec le même nom
Ce qui signifie que si nous voulons de multiples boucles en “live” s’exécutant en simultané, nous devons simplement leur donner des noms différents :
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
Vous pouvez maintenant modifier et changer chaque boucle indépendamment et simplement tout fonctionne.
Une chose que vous pourriez avoir déjà remarqué est que ces boucles
en “live” fonctionnent automatiquement avec le mécanisme de thread que
nous avons exploré précédemment. Chaque fois qu’une “live loop”
boucle, elle génère un nouvel événement cue
avec le même nom que
la boucle. Par conséquent, nous pouvons nous sync
sur ces cues pour
garantir que ces boucles soient synchronisées sans avoir à arrêter
quoi que ce soit.
Considérez ce code mal synchronisé :
live_loop :foo do
play :e4, release: 0.5
sleep 0.4
end
live_loop :bar do
sample :bd_haus
sleep 1
end
Voyons si nous pouvons corriger le timing et synchroniser sans arrêter
l’exécution. Corrigeons la boucle :foo
pour l’aligner sur le facteur
de sleep de 1 - quelque chose comme 0.5
fera l’affaire :
live_loop :foo do
play :e4, release: 0.5
sleep 0.5
end
live_loop :bar do
sample :bd_haus
sleep 1
end
Cependant, nous n’avons pas encore tout à fait fini - vous remarquerez que les temps ne battent pas ensemble correctement. C’est parce que les boucles sont déphasées. Corrigeons cela en les synchronisant :
live_loop :foo do
play :e4, release: 0.5
sleep 0.5
end
live_loop :bar do
sync :foo
sample :bd_haus
sleep 1
end
Wow, tout est maintenant parfaitement en phase - tout cela sans arrêter.
Maintenant, allez de l’avant et codez en “live” avec des “live loops” !
Il est probable que vous vous trouverez quelquefois en train d’en faire des tas quand votre codage en “live” consistera à boucler au travers d’anneaux. Vous mettrez des notes dans des anneaux (“rings”) pour les mélodies, des “sleeps” pour les rythmes, des progressions d’accords, des variations de timbre, etc. etc.
Sonic Pi fournit un outil très pratique pour travailler avec des anneaux
(“rings”) à l’intérieur des live_loop
s. Il s’agit du système d’avance
automatique (“tick”). Dans la section sur les anneaux on parlait d’un
compteur qui augmente constamment, comme un nombre courant de
battement. “Tick” implémente justement cette idée. Il vous fournit
la capacité de parcourir des anneaux.
Regardons un exemple :
counter = 0
live_loop :arp do
play (scale :e3, :minor_pentatonic)[counter], release: 0.1
counter += 1
sleep 0.125
end
C’est l’équivalent de :
live_loop :arp do
play (scale :e3, :minor_pentatonic).tick, release: 0.1
sleep 0.125
end
Ici, nous prenons simplement la gamme mineure pentatonique de Mi3 et
nous la parcourons élement par élément. C’est réalisé en ajoutant .tick
à la fin de la déclaration de la gamme. Ce “tick” est local à la
boucle live, ainsi chaque boucle live a son propre “tick” indépendant :
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
Vous pouvez également appeler tick
comme une fonction standard et
utiliser sa valeur de retour comme un index :
live_loop :arp do
idx = tick
play (scale :e3, :minor_pentatonic)[idx], release: 0.1
sleep 0.125
end
Cependant, c’est plus joli d’appeler .tick
à la fin. La fonction .tick
est faite pour les cas où vous voulez faire des fantaisies avec la valeur
retournée ou utiliser les “ticks” pour autre chose que l’indexation des
anneaux.
La chose magique apportée par “tick” est que non seulement un nouvel
index est retourné (ou la valeur de l’anneau à cet index) mais qu’il
garantit que la fois suivante où vous l’appellerez, vous obtiendrez la
valeur suivante. Jetez un œil sur les exemples de la documentation de
.tick
pour voir les différentes façons de l’employer. Toutefois,
pour le moment, il est important de souligner que quelquefois, vous
voulez juste obtenir la valeur courante de “tick” sans l’incrémenter.
Ceci est disponible via la fonction look
. Vous pouvez appeler look
comme une fonction standard ou ajouter .look
à la fin d’un anneau.
Finalement, vous avez quelquefois besoin de plus d’un “tick” par boucle live. C’est réalisé en donnant un nom à vos “ticks” :
live_loop :arp do
play (scale :e3, :minor_pentatonic).tick(:foo), release: 0.1
sleep (ring 0.125, 0.25).tick(:bar)
end
Ici, nous utilisons deux “ticks”, un pour la note à jouer et un autre
pour la durée de “sleep”. Comme ils sont tous deux dans la même
boucle, pour les maintenir indépendants, nous devons leur donner des
noms uniques. C’est exactement le même genre de solution que dans le cas
du nommage des live_loop
s - nous passons simplement un symbole précédé
d’un :
. Dans l’exemple ci-dessus, nous avons appelé un “tick” :foo
et l’autre :bar
. Si nous voulons juste connaître leur valeur, nous
devons aussi passer le nom du “tick” à look
.
La plupart de la puissance du système des “ticks” n’est pas utile quand
vous débutez. N’essayez pas et n’apprenez pas tout de cette section.
Concentrez-vous seulement sur le parcours d’un simple anneau. Cela vous
procurera la plus grande part de la joie et de la simplicité du
parcours des anneaux dans vos live_loop
s.
Jetez un œil sur la documentation des tick
s où se trouvent de nombreux
exemples utiles, et joyeux parcours automatiques !
Cette section va couvrir des connaissances très utiles - en vérité essentielles - pour obtenir le meilleur de votre expérimentation de Sonic Pi.
Nous couvrirons comment prendre avantage des nombreux raccourcis clavier mis à votre disposition, comment partager votre travail et quelques trucs sur l’interprétation musicale avec Sonic Pi.
Sonic Pi est plus un instrument qu’un environnement de programmation. Les raccourcis peuvent cependant rendre votre jeu avec Sonic Pi plus efficace et naturel - particulièrement quand vous jouez en “live” devant un auditoire.
La plus grande part de Sonic Pi peut être contrôlée au moyen du clavier. Au fur et à mesure que vous deviendrez plus familier dans la pratique et l’interprétation avec Sonic Pi, vous commencerez probablement à utiliser de plus en plus de raccourcis. Personnellement, je tape sans regarder le clavier (je recommande que vous appreniez à le faire aussi) et je me sens frustré quand j’ai besoin d’attraper la souris parce que ça me retarde. J’utilise donc tous ces raccourcis très régulièrement.
Par conséquent, si vous apprenez les raccourcis, vous saurez utiliser efficacement votre clavier et vous coderez en “live” comme un pro.
Toutefois, n’essayez pas de les apprendre tous à la fois, essayez et souvenez-vous simplement de ceux que vous utilisez le plus et continuez à en ajouter en supplément à votre pratique.
Imaginez que vous appreniez la clarinette. Vous vous attendriez à ce que toutes les clarinettes aient les mêmes contrôles et le même doigté. Si elles ne l’avaient pas, vous passeriez un moment pénible à basculer entre différentes clarinettes et vous seriez enclin à rester toujours avec la même.
Malheureusement, les trois systèmes d’exploitation principaux (Linux, Mac OS X et Windows) se présentent avec leurs propres standards par défaut pour des actions telles que copier/coller. Sonic Pi va essayer d’honorer ces standards. Toutefois la priorité est de favoriser la compatibilité entre plateformes avec Sonic Pi plutôt que de tenter de se conformer aux standards d’une plateforme donnée. Ceci signifie que quand vous apprenez les raccourcis de jeu avec Sonic Pi sur votre Raspberry Pi, vous pouvez passer au Mac ou au PC et vous retrouver en terre connue.
Une part de la notion de compatibilité est l’appellation des raccourcis. Dans Sonic Pi, nous utilisons les termes Control et Meta pour se référer aux deux combinaisons de touches principales. Sur toutes les plateformes Control (Ctrl) est identique. Toutefois, sur Linux et Windows, Meta est en réalité la touche Alt alors que sur Mac, Meta est la touche Command (Cmd). Pour la compatibilité, nous utiliserons le terme Meta - rappelez-vous juste de le faire correspondre à la touche appropriée sur votre système d’exploitation.
Pour conserver les choses simples et lisibles, nous utiliserons les abréviations C- pour Control plus une autre touche et M- pour Meta plus une autre touche. Par exemple, si un raccourci consiste à maintenir enfoncées à la fois meta et r, nous l’écrirons M-r. Le - veut dire simplement “en même temps que”.
Voici ci-dessous les raccourcis que j’estime les plus utiles :
Au lieu de toujours attraper la souris pour exécuter votre code, vous
pouvez simplement presser M-r
. Similairement, pour stopper
l’exécution de votre code, vous pouvez presser M-s
.
Je suis vraiment perdu sans les raccourcis de navigation. Je recommande donc vivement que vous passiez du temps à les apprendre. Ces raccourcis fonctionnent aussi extrèmement bien quand vous apprenez à taper sans regarder le clavier parce qu’ils utilisent des lettres standards sans nécessiter de déplacer votre main jusqu’à la souris ou jusqu’aux touches flèches de votre clavier.
Vous pouvez vous déplacer au début de la ligne avec C-a
, à la fin
de la ligne avec C-e
, à la ligne du dessus avec C-p
, à la ligne du
dessous avec C-n
, avancer d’un caractère avec C-f
, reculer d’un
caractère avec C-b
. Vous pouvez même effacer tous les caractères depuis
le curseur jusqu’à la fin de la ligne avec C-k
.
Pour aligner et indenter automatiquement vos lignes de code, pressez M-m
.
Pour afficher/cacher le système d’aide vous pouvez presser M-i
.
Toutefois un raccourci plus utile à connaître est C-i
. Il détecte
le mot où se trouve le curseur et affiche la documentation le
concernant s’il la trouve. Aide instantanée !
Pour une liste complète, jetez un œil à la section 10.2 - Antisèche des raccourcis.
Ce qui suit est un récapitulatif des principaux raccourcis clavier disponibles avec Sonic Pi. Voyez S.V.P. la section 10.1 pour la motivation et le contexte.
Dans cette liste, nous utilisons les conventions suivantes (où Meta est la touche Alt pour Windows/Linux et Cmd sur Mac) :
C-a
signifie maintenir la touche Control enfoncée puis presser la touche a, puis relacher les deux en même temps.M-r
signifie maintenir la touche Meta enfoncée puis presser la touche r, puis relacher les deux en même temps.S-M-z
signifie maintenir les touches Majuscule et Meta enfoncées puis presser la touche z, puis les relacher toutes en même temps.C-M-f
signifie maintenir les touches Control et Meta enfoncées puis presser la touche f, puis les relacher toutes en même temps.M-r
- Exécute le codeM-s
- Arrête le codeM-i
- Affiche/cache le système d’aideM-p
- Affiche/cache les préférencesM-<
- Bascule sur le buffer de gaucheS-M-<
- Bascule sur le buffer de droiteM-+
- Augmente la taille du texte du buffer courantM--
- Diminue la taille du texte du buffer courantM-a
- Sélectionne toutM-c
- Copie la sélection dans le presse-papierM-x
- Coupe la sélection et la copie dans le presse-papierC-k
- Coupe jusqu’à la fin de la ligne et le copie dans le presse-papierM-v
- Colle depuis le presse-papierC-y
- Colle depuis le presse-papierC-SPACE
- Pose une marque. La navigation surligne et sélectionne la région depuis la marque.
Utilisez C-g
pour sortir.M-m
- aligne et indente tout le texteTab
- aligne et indente la ligne courante ou la sélection (ou sélectionne l’auto-complétion)C-l
- Centre l’éditeurM-/
- Commente / décommente la ligne courante ou la sélectionC-t
- Intervertit les caractères sélectionnésM-u
- Convertit le mot suivant (ou la sélection) en majuscule.M-l
- Convertit le mot suivant (ou la sélection) en minuscule.C-a
- Déplace au début de la ligneC-e
- Déplace à la fin de la ligneC-p
- Déplace à la ligne précédenteC-n
- Déplace à la ligne suivanteC-f
- Avance d’un caractèreC-b
- Recule d’un caractèreM-f
- Avance d’un motM-b
- Recule d’un motC-M-n
- Déplace la ligne ou la sélection vers le basC-M-p
- Déplace la ligne ou la sélection vers le hautS-M-u
- Déplace 10 lignes vers le hautS-M-d
- Déplace 10 lignes vers le basC-h
- Supprime le caractère précédentC-d
- Supprime le caractère suivantC-i
- Affiche la documentation du mot où se trouve le curseurM-z
- DéfaitS-M-z
- RefaitC-g
- SortS-M-f
- Bascule en mode plein écranS-M-b
- Affiche/cache les boutonsS-M-l
- Affiche/cache le panneau “trace”S-M-m
- Bascule entre l’affichage clair et sombreSonic Pi a tout ce qu’il faut pour étudier et partager avec les autres.
Une fois que vous avez appris comment coder de la musique, partager vos compositions est aussi simple que d’envoyer un mail contenant votre code. S.V.P. partagez votre code avec les autres, ainsi ils pourront apprendre de votre travail et même en utiliser des parties dans un nouveau “mashup”.
Si vous n’êtes pas sûr de connaître le meilleur moyen de partager votre travail avec les autres, je vous recommande de mettre votre code sur GitHub et votre musique sur SoundCloud. De cette manière vous pourrez atteindre un grand auditoire.
GitHub est un site pour partager et travailler avec du code. Il est utilisé aussi bien par des développeurs professionnels que par des artistes pour partager et collaborer avec du code. La manière la plus simple pour partager un morceau de code (ou même un morceau non terminé) est de créer un Gist. Un Gist est un moyen simple de déposer votre code afin que les autres y aient accès de manière simple : voir, copier, et partager.
Une autre façon importante de partager votre travail est d’enregistrer l’audio et de déposer l’enregistrement sur SoundCloud. Une fois que vous avez déposé votre morceau, les autres peuvent commenter et discuter votre travail. Je vous recommande aussi de placer un lien vers le Gist de votre code dans la description de la piste.
Pour enregistrer votre travail, pressez le bouton Rec
de la barre
d’outils, et l’enregistrement démarre immédiatement. Pressez Run
pour lancer votre code s’il n’est pas encore démarré. Quand votre
enregistrement devra être arrêté, pressez le bouton Rec
clignotant
à nouveau, et il vous sera demandé d’entrer un nom de fichier.
L’enregistrement sera sauvegardé dans le format d’un fichier WAV,
lequel peut être modifié et converti en MP3 par n’importe quel
programme gratuit (essayez Audacity par exemple).
Je vous encourage à partager votre travail et espère vraiment que nous allons tous nous apprendre de nouvelles astuces et progresser avec Sonic Pi. Je suis réellement enthousiaste de ce que vous allez avoir à me montrer.
Un des aspects les plus passionnants de Sonic Pi est qu’il vous permet d’utiliser le code comme un instrument de musique. Ce qui signifie qu’écrire du code en “live” peut maintenant être considéré comme une nouvelle manière d’interpréter de la musique.
Nous appelons ceci codage en “live”.
Quand vous codez en “live”, je vous recommande de montrer votre écran à votre auditoire. Autrement, c’est comme jouer de la guitare, mais en cachant vos doigts et les cordes. Quand je pratique à la maison, j’utilise un Raspberry Pi et un mini projecteur sur le mur de mon salon. Vous pouvez utiliser votre TV ou une de vos lampes de bureau pour faire un “show”. Essayez-le, c’est beaucoup de plaisir.
Ne jouez pas juste pour vous seul - formez un orchestre de codage en “live”. C’est beaucoup de plaisir que d’improviser avec d’autres. Une personne pourrait faire la rythmique, une autre faire le fond ambiant, etc. Recherchez les combinaisons de sons que vous pouvez avoir ensemble.
Le codage en “live” n’est pas totalement nouveau - un petit nombre de personnes l’on pratiqué maintenant depuis quelques années, typiquement en utilisant des systèmes sur mesure qu’ils avaient élaborés eux-mêmes. Un super site à visiter pour trouver plus d’informations sur les codeurs en “live” et leurs systèmes est TOPLAP.
Une autre super ressource pour explorer le monde du codage en “live” est Algorave. Vous trouverez là tout sur une branche spécifique du codage en “live” pour faire de la musique dans les boîtes de nuit.
Sonic Pi supporte maintenant une simple API (interface de programmation) pour interagir avec Minecraft Pi - l’édition spéciale de Minecraft qui est installée par défaut avec le système d’exploitation Raspbian Linux du Raspberry Pi.
L’intégration avec Minecraft Pi a été conçue pour être extrêmement
simple à utiliser. Tout ce dont vous avez besoin est de lancer
Minecraft Pi et de créer un nouveau monde. Il vous est alors possible
d’utiliser les fonctions mc_*
juste comme vous pourriez utiliser
play
et synth
. Il n’y a pas besoin d’importer quoi que ce soit ou
d’installer des bibliothèques - c’est tout prêt à utiliser et à
fonctionner sans autre procès.
L’API à Minecraft Pi se préoccupe de la gestion de votre connexion à
l’application Minecraft Pi. Ce qui signifie que vous n’avez pas besoin
de vous en inquiéter. Si vous essayez d’utiliser l’API à Minecraft Pi
quand Minecraft Pi n’est pas démarré, Sonic Pi vous en avertira
poliment. Similairement, si vous arrêtez Minecraft Pi quand vous êtes
encore en train d’exécuter une live_loop
qui utilise l’API, la boucle
s’arrêtera et vous avertira poliment de l’impossibilité de se
connecter. Pour vous reconnecter, relancer simplement Minecraft Pi,
Sonic Pi le détectera automatiquement et recréera la connection pour
vous.
L’API à Minecraft a été conçue pour fonctionner sans heurt à l’intérieur
des live_loop
s. Ce qui signifie qu’il est possible de synchroniser
des modifications de vos mondes de Minecraft Pi avec des modifications
de vos sons de Sonic Pi. Des vidéos sur le vif avec musique basée
sur Minecraft ! Notez cependant que Minecraft Pi est un logiciel en
phase alpha et qu’il est connu pour être légèrement bogué. Si vous
rencontrez un problème quelconque, relancez simplement Minecraft Pi et
continuez comme avant. La fonctionnalité de connexion automatique de
Sonic Pi prendra soin des choses pour vous.
Il est vivement recommandé d’utiliser un Raspberry Pi 2 si vous voulez
exécuter à la fois Sonic Pi et Minecraft en même temps
- particulièrement si vous voulez utiliser les capacités sonores de
Sonic Pi.
À cette étape, Sonic Pi supporte les manipulations basiques des joueurs et des blocs qui sont détaillées dans la section 11.1. Le support pour les callbacks d’évènements générés par les interactions des joueurs dans le monde est planifié pour une version future.
Sonic Pi supporte actuellement les interactions basiques suivantes avec Minecraft Pi :
Voyons chacune d’elles tour à tour.
Voyons juste comme c’est facile de contrôler Minecraft Pi depuis Sonic Pi. Assurez-vous d’abord que vous avez Minecraft Pi et Sonic Pi actifs en même temps et assurez-vous aussi que vous êtes entré dans un monde de Minecraft et que vous pouvez vous y déplacer.
Dans un buffer vierge de Sonic Pi, entrez le code suivant :
mc_message "Hello from Sonic Pi"
Quand vous pressez le bouton Run, vous verrez votre message clignoter dans la fenêtre de Minecraft. Félicitations, vous avez écrit votre premier code Minecraft ! C’était facile, n’était-ce pas ?
Maintenant, essayons un peu de magie. Téléportons-nous quelque-part ! Essayez le code suivant :
mc_teleport 50, 50, 50
Quand vous pressez le bouton Run - boum ! Vous avez été intantanément
transporté à un nouvel endroit. Le plus probablement, c’était dans le
ciel et vous êtes tombé soit sur la terre ferme, soit dans l’eau.
Maintenant, quels sont ces nombres : 50, 50, 50
? Ce sont les
coordonnées de l’endroit où vous essayiez d’être téléporté.
Prenons un bref moment pour explorer ce que sont ces coordonnées et
comment elles fonctionnent parce qu’elles sont réellement, réellement
importantes pour programmer Minecraft.
Imaginez une carte de pirate avec un grand X
marquant l’emplacement
d’un trésor. L’emplacement exact du X
peut être décrit avec deux
nombres - à quelle distance du bord gauche de la carte en allant vers la
droite et à quelle distance du bord inférieur de la carte en allant vers
le haut il se trouve. Par exemple, 10cm
en horizontal et 8cm
en
vertical. Ces deux nombres 10
et 8
sont des coordonnées. Vous
pourriez imaginer aisément le description des endroits d’autres cachettes
de trésor avec d’autres paires de nombres. Peut-être y-a-t-il un gros
coffre d’or à 2
en horizontal et à 9
en vertical…
Maintenant, dans Minecraft, deux nombres ne sont pas tout à fait suffisants. Nous devons aussi savoir à quelle hauteur nous sommes. Nous avons donc besoin de trois nombres :
x
z
y
Une chose en plus - nous décrivons habituellement ces trois
coordonnées dans l’ordre x
, y
, z
.Jouons avec les coordonnées. Naviguez vers un bel endroit de la carte de Minecraft et puis basculez sur Sonic Pi. Maintenant, entrez le code suivant :
puts mc_location
Quand vous pressez le bouton Run, vous voyez les coordonnées de votre position courante affichées dans le panneau “trace”. Prenez en note, puis déplacez-vous dans le monde et essayez à nouveau. Notez comme les coordonnées ont changé ! Maintenant, je vous recommande de passer quelque temps à refaire exactement cela - vous déplacer un peu dans le monde, regarder les coordonnées et recommencer. Faites cela jusqu’à ce que vous commenciez à être à l’aise sur la manière dont changent les coordonnées quand vous vous déplacez. Une fois que vous avez compris comment fonctionnent les coordonnées, programmer avec l’API à Minecraft sera du gâteau.
Maintenant que vous savez comment trouver la position courante et vous
téléporter en utilisant les coordonnées, vous avez tous les outils
dont vous avez besoin pour commencer à construire des choses dans
Minecraft avec du code. Disons que vous voulez faire du bloc avec les
coordonnées 40
, 50
, 60
un bloc “glass” (de verre). C’est super facile :
mc_set_block :glass, 40, 50, 60
Ha ha, c’était vraiment facile. Pour voir le résultat de votre travail pratique, téléportez-vous aux alentours et regardez :
mc_teleport 35, 50, 60
Maintenant, tourner autour de vous et vous devriez voir votre bloc de verre ! Essayez de le changer en diamant :
mc_set_block :diamond, 40, 50, 60
Si vous regardiez dans la bonne direction, vous auriez même pu voir le changement devant vos yeux ! C’est le début de quelquechose de passionnant…
Regardons une dernière chose avant d’aller vers quelque chose d’un peu plus compliqué. Étant donné un jeu de coordonnées, nous pouvons demander à Minecraft quel est le type d’un bloc spécifique à cet endroit. Essayons-le avec le bloc de diamant que vous venez de créer :
puts mc_get_block 40, 50, 60
Ouais ! C’est :diamond
. Essayez de le faire revenir au verre et
demandez à nouveau - Dit-il vraiment :glass
maintenant ? je suis
certain que oui :-)
Avant que vous alliez vers un déchaînement de codage de Minecraft Pi, vous pourriez trouver utile cette liste des types de blocs disponibles :
:air
:stone
:grass
:dirt
:cobblestone
:wood_plank
:sapling
:bedrock
:water_flowing
:water
:water_stationary
:lava_flowing
:lava
:lava_stationary
:sand
:gravel
:gold_ore
:iron_ore
:coal_ore
:wood
:leaves
:glass
:lapis
:lapis_lazuli_block
:sandstone
:bed
:cobweb
:grass_tall
:flower_yellow
:flower_cyan
:mushroom_brown
:mushroom_red
:gold_block
:gold
:iron_block
:iron
:stone_slab_double
:stone_slab
:brick
:brick_block
:tnt
:bookshelf
:moss_stone
:obsidian
:torch
:fire
:stairs_wood
:chest
:diamond_ore
:diamond_block
:diamond
:crafting_table
:farmland
:furnace_inactive
:furnace_active
:door_wood
:ladder
:stairs_cobblestone
:door_iron
:redstone_ore
:snow
:ice
:snow_block
:cactus
:clay
:sugar_cane
:fence
:glowstone_block
:bedrock_invisible
:stone_brick
:glass_pane
:melon
:fence_gate
:glowing_obsidian
:nether_reactor_core
Ceci conclut ce tutoriel d’introduction à Sonic Pi. Heureusement, vous avez appris quelque chose tout au long. Ne vous inquiétez pas si vous pensez ne pas avoir tout compris - jouez simplement et prenez du plaisir, vous vous approprierez les choses à votre rythme. N’hésitez pas à replonger en arrière quand vous avez une question qui pourrait être couverte par une des sections.
Si vous avez des questions qui n’ont pas été couvertes dans le tutoriel, alors allez S.V.P. sur Sonic Pi forums et poser vos questions ici. Vous trouverez quelqu’un qui désirera vous tendre amicalement la main.
Enfin, je vous invite aussi à regarder en profondeur le reste de la documentation de ce système d’aide. Il y a un nombre de fonctionnalités qui n’ont pas été couvertes dans ce tutoriel et qui sont en attente de votre découverte.
Donc, jouez, prenez du plaisir, partagez votre code, produisez-vous devant vos amis, montrez vos écrans et rappelez-vous :
Il n’y a pas de fautes, que des opportunités
L’appendice A rassemble tous les articles Sonic Pi écrits pour le magazine MagPi.
Ces articles ne sont pas destinés à être lus dans un ordre particulier et contiennent beaucoup de choses qui sont aussi dans le tutoriel. Plutôt que d’essayer de vous apprendre tout Sonic Pi, chacun se focalise plutôt sur un aspect particulier de Sonic Pi et le couvre d’une manière amusante et accessible.
Vous les trouverez avec leur présentation très professionnelle dans les PDFs gratuits en téléchargement ici : https://www.raspberrypi.org/magpi/
Si vous ne trouvez pas de sujet qui vous intéresse parmi ceux couverts dans ces articles, pourquoi ne pas en suggérer un ? La manière la plus simple de faire cela est de tweeter votre suggestion à @Sonic_Pi. On ne sait jamais, votre suggestion sera peut-être le sujet du prochain article !
La plus importante leçon à apprendre avec Sonic Pi c’est qu’il n’y a vraiment pas d’erreur. La meilleure façon d’apprendre c’est juste d’essayer, essayer, et essayer. Essayez beaucoup de choses différentes, ne vous inquiétez pas de savoir si votre code sonne bien ou pas et commencez par expérimenter avec le plus de synthés, notes, effets et options possibles. Vous découvrirez beaucoup de choses qui vous feront rire parce qu’elles ne sonnent pas bien du tout et aussi quelques joyaux qui sonnent magnifiquement bien. Débarrassez-vous ensuite de ce que vous n’aimez pas et gardez les choses qui vous plaisent. Plus vous vous permettrez de faire des erreurs et plus vous apprendrez et découvrirez votre son de code personnel.
Disons que vous maîtrisez déjà les bases de Sonic Pi pour créer des
sons avec sample
et play
. Qu’est-ce qui vient ensuite ? Savez-vous
que Sonic Pi supporte plus de 27 effets studio pour changer le son de
votre code ? Les effets sont comme des filtres pour images dans les
programmes de dessin, mais à la place de rendre l’image floue ou noir
et blanc, on peut ajouter de la reverb, de la distorsion ou de l’écho
au son. On peut voir ça comme brancher le câble d’une guitare dans une
pédale d’effet puis dans un ampli. Heureusement Sonic Pi rend
l’utilisation d’effets très simple et n’a pas besoin de câble. Tout
ce dont vous avez besoin c’est de choisir à quelle section de votre
code ajouter l’effet puis de l’entourer avec le code de l’effet.
Prenons un exemple. Disons que vous avez le code suivant :
sample :loop_garzul
16.times do
sample :bd_haus
sleep 0.5
end
Si vous voulez ajouter un effet au sample :loop_garzul
, il suffit de
le mettre dans un bloc with_fx
comme ceci :
with_fx :flanger do
sample :loop_garzul
end
16.times do
sample :bd_haus
sleep 0.5
end
Maintenant si voulez ajouter un effet au tambour basse, enveloppez-le
aussi dans 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
Rappelez-vous, vous pouvez entourer n’importe quel code dans
with_fx
et tous les sons créés passeront dans cet effet.
Pour découvrir vraiment votre son de code vous voudrez savoir comment modifier et contrôler les synthés et effets. Par exemple, vous voudrez peut-être changer la durée d’une note, ajouter plus de reverb, ou changer la durée entre échos. Heureusement, Sonic Pi vous donne un niveau de contrôle incroyable pour faire cela avec des paramètres optionnels ou opts pour faire court. Regardons ça rapidement. Copiez ce code dans un buffer et exécutez-le :
sample :guit_em9
Oh, un joli son de guitare ! Commençons à jouer un peu avec. Et si on changeait sa fréquence ?
sample :guit_em9, rate: 0.5
Hé, qu’est-ce que ce rate: 0.5
que j’ai ajouté à la fin ? C’est ce
qu’on appelle une opt. Tous les synthés et samples de Sonic Pi les
supportent et il y en a beaucoup avec lesquels on peut jouer. Ils
sont disponibles pour les effets aussi. Essayez ceci :
with_fx :flanger, feedback: 0.6 do
sample :guit_em9
end
Maintenant essayez d’augmenter ce feedback à 1 pour entendre des sons fous ! Lisez la documentation pour des détails complets sur les nombreuses opts disponibles.
La meilleure manière d’expérimenter rapidement et d’explorer Sonic Pi est de coder de manière interactive. Cela vous permet de partir d’un peu de code et de le changer de manière continue pendant qu’il est en train de s’exécuter. Par exemple, si vous ne savez pas ce que le paramètre cutoff fait à un sample, jouez avec. Essayons ! Copiez ce code dans un de vos buffers Sonic Pi :
live_loop :experiment do
sample :loop_amen, cutoff: 70
sleep 1.75
end
Maintenant cliquez sur ‘Run’ et vous entendrez un rhythme de batterie
un peu étouffé. Maintenant changez la valeur de cutoff:
en 80
et
cliquez à nouveau sur ‘Run’. Entendez-vous la différence ? Essayez
90
, 100
, 110
…
Quand vous aurez pris la main à utiliser des live_loop
, vous ne
pourrez plus vous en passer. Quand je donne un concert de live coding
je m’appuie autant sur live_loop
qu’un batteur sur ses baguettes.
Pour plus d’informations à propos du live coding regardez la section
9 du tutoriel inclus dans Sonic Pi.
Enfin, une chose que j’adore faire est de tricher en faisant que Sonic Pi compose des choses pour moi. Une manière géniale de faire ça est d’utiliser l’aléatoire. Cela peut paraître compliqué mais ça ne l’est pas du tout. Regardons. Copiez ceci dans 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
Maintenant, quand vous jouez cela, vous entendrez une suite continue
de notes aléatoires de la gamme :e2 :minor_pentatonic
jouée avec le
synthé :dsaw
. “Attendez, attendez ! Ce n’est pas une mélodie”, vous
entends-je crier ! Eh bien, voici la première partie du tour de magie.
Chaque fois que l’on recommence le live_loop
on peut dire à Sonic Pi
de fixer la suite aléatoire à un point connu. C’est un peu comme
voyager dans le temps. Essayons ceci : ajoutez la ligne
use_random_seed 1
au 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
Maintenant, chaque fois que la live_loop
boucle, la suite aléatoire
est réinitialisée. Cela veut dire qu’elle contient exactement les même
16 notes à chaque fois. Et voilà ! Une mélodie de composée. Et
maintenant voici la partie excitante. Changez la valeur de 1
en un
autre nombre. Par exemple 4923
. Ouaou, une autre mélodie ! Donc, en
changeant juste un nombre (la graine aléatoire), on peut explorer
autant de combinaisons mélodiques qu’on peut imaginer ! C’est ça la
magie du code.
Les rayons lasers perçaient à travers les bouffées de fumée et les baffles transmettaient des basses profondes dans les corps de la foule. L’atmosphère était remplie d’un mélange de synthés et de danse. Il y avait pourtant quelque chose d’étrange dans cette boîte de nuit. Du texte futuriste était projeté au dessus de la cabine du DJ, bougeant, dansant, clignotant. Ce n’étaient pas de belles visualisations, c’était juste une projection de Sonic Pi tournant sur un Raspberry Pi. La personne dans la cabine de DJ n’était pas en train de tourner des disques, elle écrivait, éditait et évaluait du code. En direct. C’est ça le Live Coding.
Cela peut sonner comme une histoire tirée par les cheveux dans une boîte de nuit futuriste mais coder de la musique comme cela est une tendance qui se développe et qu’on appelle souvent Live Coding (programmation interactive) (http://toplap.org). Une des directions récentes que cette approche de la musique a prise est l’Algorave (http://algorave.com) : des événements où des artistes comme moi codent de la musique pour que les gens dansent. Cependant vous n’avez pas besoin d’une boîte de nuit pour coder en live : avec Sonic Pi version 2.6 et plus vous pouvez le faire dans n’importe quel endroit où vous pouvez prendre votre Raspberry Pi et un casque ou des haut-parleurs. Quand vous aurez atteint la fin de cet article, vous saurez programmez vos rythmes et les modifier en direct. Où vous irez ensuite ne sera limité que par votre imagination.
La clef de la programmation interactive est la maîtrise de la
live_loop
. En voici une :
live_loop :beats do
sample :bd_haus
sleep 0.5
end
Il y a quatre ingrédients principaux dans une live_loop
. La première
est son nom. Notre live_loop
s’appelle ici :beats
. Vous pouvez
donner le nom que vous voulez à votre live_loop
. Défoulez-vous.
Soyez créatifs. J’utilise souvent des noms qui communiquent à
l’audience qu’est-ce que la musique va faire. Le deuxième ingrédient
est le mot do
qui marque où la live_loop
commence. Le troisième
est le mot end
qui marque où la live_loop
finit, et enfin il y a
le corps de la live_loop
qui décrit ce que la boucle va répéter :
c’est la partie entre do
et end
. Dans ce cas on joue en boucle un
sample de tambour basse et on attend un demi temps. Cela produit un
beau rythme régulier de basse. Allez, copiez-le dans un buffer vide de
Sonic Pi et cliquez sur ‘Run’. Boum, boum, boum !
OK, qu’est-ce qu’elle a de si spécial, cette live_loop
? Jusqu’ici
on dirait que c’est juste une boucle ! Eh bien, la beauté des
live_loop
s c’est qu’on peut les redéfinir à la volée. Cela veut
dire que pendant qu’elles sont en train de tourner, on peut changer ce
qu’elles font. C’est le secret de la programmation interactive avec
Sonic Pi. Essayons :
live_loop :choral_drone do
sample :ambi_choir, rate: 0.4
sleep 1
end
Maintenant cliquez le bouton ‘Run’ ou tapez ‘alt-r’. Vous entendez
maintenant de beaux sons de chorale. Ensuite, alors qu’il est encore
en train de jouer, changer la fréquence de 0.4
en 0.38
. Cliquez à
nouveau sur ‘Run’. Ouaou ! Vous avez entendu le choeur changer de
note ? Ecrivez à nouveau 0.4
pour revenir comme avant. Puis 0.2
,
puis 0.19
, puis à nouveau 0.4
. Voyez-vous comment juste changer un
paramètre à la volée vous donne un réel contrôle sur la musique ?
Maintenant jouez vous-même avec la fréquence, choisissez vos propres
valeurs. Essayez des nombres négatifs, de très petits nombres et de
grands nombres. Amusez-vous !
Une des leçons les plus importantes avec les live_loop
c’est
qu’elles ont besoin de se reposer. Prenons par exemple cette
live_loop
:
live_loop :infinite_impossibilities do
sample :ambi_choir
end
Si vous essayez d’exécuter ce code, vous verrez immédiatement que
Sonic Pi se plaint que la live_loop
n’a pas dormi. C’est un
mécanisme de sécurité qui se met en place. Prenons un moment pour
penser à ce que ce code demande à l’ordinateur de faire. C’est cela,
on demande à l’ordinateur de jouer un nombre infini de samples de
chorale dans un temps nul. Sans le mécanisme de sécurité le pauvre
ordinateur essaierait de faire ça et exploserait. Souvenez-vous en
bien : vos live_loop
s doivent contenir un appel à sleep
.
La musique est pleine de choses qui arrivent en même temps. La
batterie en même temps que la basse, en même temps que du chant, en
même temps que des guitares… En informatique on appelle ça la
concurrence et Sonic Pi nous donne une manière étonnamment simple de
jouer des choses en même temps. Il suffit d’utiliser plus qu’une
live_loop
!
live_loop :beats do
sample :bd_tek
with_fx :echo, phase: 0.125, mix: 0.4 do
sample :drum_cymbal_soft, sustain: 0, release: 0.1
sleep 0.5
end
end
live_loop :bass do
use_synth :tb303
synth :tb303, note: :e1, release: 4, cutoff: 120, cutoff_attack: 1
sleep 4
end
Ici nous avons deux live_loop
s, une qui tourne rapidement pour faire
un rythme et une qui boucle lentement pour faire un son fou de basse.
Une des choses intéressantes quand on utilise plusieurs live_loop
s
c’est que chacune gère son propre temps. Cela veut dire qu’il est très
facile de créer des structures polyrythmiques intéressantes et même de
jouer avec la phase dans le style de Steve Reich. Par exemple :
# La phase piano de Steve Reich
notes = (ring :E4, :Fs4, :B4, :Cs5, :D5, :Fs4, :E4, :Cs5, :B4, :Fs4, :D5, :Cs5)
live_loop :slow do
play notes.tick, release: 0.1
sleep 0.3
end
live_loop :faster do
play notes.tick, release: 0.1
sleep 0.295
end
Dans chacun de ces tutoriels, nous finirons avec un exemple qui montre un nouveau morceau de musique qui utilise toutes les idées introduites. Lisez ce code et essayez d’imaginer ce qu’il fait. Ensuite, copiez-le dans un buffer frais de Sonic Pi et cliquez ‘Run’ pour entendre comment il sonne. Enfin changez un des nombres ou commentez / décommentez des parties. Voyez si vous pouvez prendre ça comme point de départ d’une nouvelle performance, et surtout amusez-vous ! A la prochaine…
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
Une des évolutions techniques les plus excitantes et disruptives dans la musique moderne a été l’invention des samplers. C’étaient des boîtes qui permettaient d’enregistrer n’importe quels sons dedans et de les manipuler et jouer de nombreuses manières intéressantes. Par exemple, on pouvait prendre un vieux disque, trouver un solo de batterie (ou un break), l’enregistrer dans le sampler et ensuite le jouer deux fois moins vite pour créer la fondation de vos derniers rythmes. C’est ainsi que la musique hip-hop est née et aujourd’hui il est presque impossible de trouver de la musique électronique qui n’incorpore pas de samples. Utiliser des samples est une très bonne manière d’introduire facilement des éléments nouveaux et intéressants dans vos performances de live coding.
Comment pouvez-vous vous procurer un sampler ? Eh bien, vous en avez déjà un : c’est votre Raspberry Pi ! L’application de live coding Sonic Pi comprend un sampler très puissant. Jouons avec !
Un des samples de break de batterie les plus classiques et reconnaissables s’appelle le break Amen. Il a été joué pour la première fois en 1969 dans la chanson “Amen Brother” des Winstons dans un break de batterie. Cependant c’est quand il a été découvert par les premiers musiciens de hip-hop dans les années 80 et utilisé dans des samplers qu’il a commencé à être très utilisé dans des styles aussi variés que le drum and bass, le breakbeat, la techno hardcore et le breakcore.
Je suis sûr que vous êtes ravis d’entendre qu’il est aussi inclus dans Sonic Pi. Choisissez un buffer vide et copiez-y ce code :
sample :loop_amen
Cliquez sur Run et boum ! Vous ententez l’un des breaks de batterie les plus influents de l’histoire de la musique dance. Ceci dit, ce sample n’est pas célèbre pour être joué juste une fois, il est fait pour être joué en boucle.
Jouons le break Amen en boucle en utilisant notre vieille amie la
live_loop
, introduite dans le tutoriel du mois dernier :
live_loop :amen_break do
sample :loop_amen
sleep 2
end
OK, ça boucle, mais il y a une pause ennuyeuse à chaque fois. C’est
parce qu’on a demandé d’attendre 2
temps et avec le nombre par défaut
de 60 BPM (battements par minute), le sample :loop_amen
ne dure que
1.753
temps. Nous avons donc un silence de 2 - 1.753 = 0.247
temps. Même s’il est court, c’est notable.
Pour corriger ce problème on peut utiliser l’option beat_stretch
pour demander à Sonic Pi d’étirer (ou rétrécir) le sample pour
correspondre au temps spécifié.
[Breakout box start] Les fonctions sample
et synth
de Sonic Pi
vous donnent beaucoup de contrôle via des paramètres optionnels comme
amp:
, cutoff:
et release:
. Cela dit le terme paramètre
optionnel
est très long à dire donc on les appelle juste opts pour
rester simple.
[Breakout box end]
live_loop :amen_break do
sample :loop_amen, beat_stretch: 2
sleep 2
end
Maintenant on peut danser ! Quoique, peut-être qu’on veut l’accélérer ou le ralentir en fonction de l’ambiance.
OK, et si on voulait changer de style pour faire du hip hop old school
ou du breakcore ? Une manière simple de faire ça est de jouer avec le
temps : ou en d’autres mots jouer avec le tempo. C’est très facile
avec Sonic Pi : il suffit d’appeler use_bpm
dans votre boucle
interactive :
live_loop :amen_break do
use_bpm 30
sample :loop_amen, beat_stretch: 2
sleep 2
end
Pendant que vous rappez sur ces rythmes lents, remarquez que nous
avons toujours un repos de 2 et que notre BPM vaut 30, mais tout est
bien synchronisé. L’option beat_stretch
marche avec le BPM courant
pour s’assurer que tout fonctionne bien.
Maintenant voici la partie amusante. Alors que la boucle est en train
de tourner, changez le 30
dans la ligne use_bpm 30
en 50
. Oh,
tout est devenu plus rapide, mais toujours synchro ! Essayez d’aller
plus vite : jusque 80, jusque 120, ou même, soyons fous, 200 !
Maintenant qu’on peut jouer des samples en boucle de manière
interactive, regardons les options les plus amusantes proposées par le
synthé sample
. La première est le cutoff:
qui contrôle le filtre
de coupure du sampler. Par défaut il est désactivé mais on peut
facilement l’activer :
live_loop :amen_break do
use_bpm 50
sample :loop_amen, beat_stretch: 2, cutoff: 70
sleep 2
end
Allez-y, changez la valeur de l’option cutoff:
. Par exemple
montez-la à 100, cliquez sur Run et attendez la prochaine boucle
pour entendre la différence dans le son. Remarquez que des valeurs
basses comme 50 sonnent plus doux et bas et que des hautes valeurs
comme 100 ou 120 sonnent plus plein et râpeux. C’est parce que
l’option cutoff:
va couper les parties haute-fréquence du son tout
comme une tondeuse coupe le haut de la pelouse. L’option cutoff:
est comme le réglage de la longueur : cela détermine combien il reste
d’herbe.
Un autre super outil avec lequel on peut jouer est l’effet slicer.
Il va couper le son en tranches. Entourez la ligne de sample
avec le
code de l’effet ainsi :
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
Remarquez comme le son bondit un peu plus de haut en bas. (Vous pouvez
entendre le son original sans l’effet en changeant l’option mix:
en
0
.) Maintenant essayez de modifier la valeur de l’option phase:
.
C’est la fréquence (en battements) de l’effet de coupe. Une plus
petite valeur comme 0.5
va couper plus rapidement et une plus grande
valeur comme 0.5
va couper plus lentement. Remarquez que si on
divise ou multiplie successivement par deux l’option phase:
cela
sonne généralement bien. Enfin, choisissez une valeur pour l’option
wave:
entre 0, 1 et 2 et écoutez comment le son change. Ce sont
différentes formes d’onde. 0 est une onde scie (elle commence fort et
finit en fondu), 1 est une onde carrée (commence et finit fort) et 2
est une onde en triangle (commence en fondu, finit en fondu).
Enfin, revenons dans le temps et revisitons la jeune scène de drum and bass de Bristol avec l’exemple de ce mois. Ne vous inquiétez pas trop de tout ce que cela signifie, tapez le, cliquez sur Run, puis commencez à coder interactivement en changement les valeurs des options et voyez où cela vous amène. Partagez ce que vous créez ! A la prochaine…
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
Que ce soit la dérive hantée d’oscillateurs grondants ou le coup de poing désaccordé des ondes scies perçant à travers le mix, le synthé principal joue un rôle essentiel dans chaque piste électronique. Dans l’édition du mois dernier de cette série de tutoriels nous avons couvert comment coder nos rythmes. Dans ce tutoriel nous verrons comment coder les trois composants principaux d’un riff de synthé : le timbre, la mélodie et le rythme.
OK, allumez votre Raspberry Pi, ouvrez Sonic Pi (version 2.6 ou plus) et faisons du bruit !
Une partie essentielle de n’importe quel riff de synthé est de jouer avec le timbre des sons. On peut contrôler le timbre dans Sonic Pi de deux manières : en choisissant différents synthés pour un changement dramatique et en définissant les diverses options des synthés pour des modifications plus subtiles. On peut aussi utiliser des effets, mais ce sera pour un autre tutoriel…
Créons une boucle interactive simple où l’on modifiera en continu le synthé courant :
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
Regardez ce code. On parcourt (avec tick
) juste un anneau de noms de
synthés (on boucle sur chacun d’eux à leur tour puis on répéte la
liste encore et encore). On passe ce nom de synthé à la fonction (fn)
use_synth
, ce qui changera le synthé courant de la live_loop
. On
joue aussi la note :e2
(E (ou Mi) à la deuxième octave), avec un
temps de relâche de 0.5 battement (une demi seconde au BPM par défaut
de 60) et avec l’option :cutoff
fixée à 100.
Vous entendez que les différents synthés ont des sons très différents
même s’ils jouent tous la même note. Maintenant expérimentez et jouez.
Changez le temps de relâche en lui donnant des valeurs plus grandes et
plus petites. Par exemple, changez les options attack:
et release:
pour voir comme des temps différents de fondu d’entrée et de sortie
ont un grand effet sur le son. Enfin changez l’option cutoff:
pour
voir comment différentes valeurs de coupure ont une influence massive
sur le timbre (des valeurs entre 60 et 130 sont bonnes). Voyez combien
de sons vous pouvez créer juste en changeant quelques valeurs. Une
fois que vous maîtrisez cela, allez dans l’onglet Synthés dans le
système d’aide pour voir la liste entière des synthés et des options
que chacun d’eux supporte pour voir l’étendue du pouvoir que vous avez
au bouts de vos doigts de codeur.
Le timbre est juste un mot savant pour décrire comment sonne un son. Si vous jouez la même note avec différents instruments comme un violon, une guitare, ou un piano, la fréquence (si elle sonne haut ou bas) sera la même, mais la qualité du son sera différente. La qualité du son, ce qui fait qu’on peut différencier un piano et une guitare, c’est le timbre.
Un autre aspect important de notre synthé principal est le choix de notes que l’on veut jouer. Si vous avez déjà une bonne idée, alors vous pouvez juste créer un anneau avec vos notes et les parcourir :
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
Ici nous avons défini une mélodie avec un anneau qui inclut des notes
comme :e3
et des silences représentés par :r
. On utilise ensuite
.tick
pour jouer chaque note à son tour, ce qui nous donne un riff
qui se répète.
Ce n’est pas toujours facile d’inventer un riff sympa. C’est souvent plus simple de demander à Sonic Pi une sélection de riffs aléatoires et de choisir celui que l’on préfère. Pour faire cela on doit combiner trois choses : des anneaux, de l’aléatoire et des graines aléatoires. Regardons un exemple :
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
Plusieurs choses se passent : regardons les une par une. On commence par spécifier la graine aléatoire 3. Qu’est-ce que cela signifie ? Eh bien, c’est utile parce que quand on définit la graine, on sait prédire quelle sera la prochaine valeur aléatoire : ce sera la même que la dernière fois qu’on a choisi la graine 3 ! Une autre chose utile à savoir est que mélanger un anneau de notes fonctionne de la même façon. Dans l’exemple ci-dessus c’est comme si on demandait le ‘troisième mélange’ dans la liste standard de mélanges : il sera le même chaque fois comme on définit toujours la graine aléatoire à la même valeur avant le mélange. Enfin on parcourt juste nos notes mélangées pour jouer le riff.
Maintenant, c’est ici qu’on commence à s’amuser. Si on change la valeur de la graine aléatoire, par exemple en 3000, on a un mélange entièrement différent des notes. Ainsi il est très facile d’explorer de nouvelles mélodies. Il suffit de choisir la liste de notes que l’on veut mélanger (les gammes sont un très bon endroit pour commencer) et ensuite de choisir la graine avec laquelle on veut les mélanger. Si on n’aime pas la mélodie, on peut juste changer une de ces deux choses et essayer à nouveau. Répétez jusqu’à ce que vous aimiez ce que vous entendez !
L’aléatoire de Sonic Pi n’est pas vraiment aléatoire, on appelle ça du pseudo aléatoire. Imaginez que vous jetez un dé 100 fois et que vous écrivez le résultat de chaque jet sur une feuille de papier. Sonic Pi a l’équivalent de cette liste de résultats qu’il utilise quand on demande une valeur aléatoire. Au lieu de jeter un vrai dé, il prend juste la valeur suivante dans la liste. Définir la graine aléatoire revient à sauter à un endroit particulier de cette liste.
Un autre aspect important de notre riff est le rythme : quand jouer
une note et quand ne pas le faire. Comme on a vu, on peut utiliser
:r
dans nos anneaux pour insérer des silences. Une autre manière
puissante consiste à utiliser des ‘spreads’ que l’on couvrira dans un
futur tutoriel. Aujourd’hui nous allons utiliser l’aléatoire pour nous
aider à trouver notre rythme. Au lieu de jouer toutes les notes on
peut utiliser une condition pour jouer une note avec une probabilité
donnée. Voyons cela :
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
Une fonction très utile à connaître est one_in
qui nous donne une
valeur true
ou false
(vrai ou faux) avec la probabilité spécifiée.
Ici nous utilisons une valeur de 2 donc en moyenne un appel sur deux à
one_in
retournera true
. En d’autres termes, elle retournera true
50% du temps. Si on choisit des valeurs plus grandes elle retournera
false
plus souvent ce qui mettra plus d’espace dans notre riff.
Remarquez qu’on a introduit un peu d’itération ici avec 16.times
.
C’est parce qu’on ne veut redéfinir notre valeur de graine aléatoire
que toutes les 16 notes pour que notre rythme se répète toutes les 16
fois. Cela n’affecte pas le mélange comme il est toujours fait juste
après avoir défini la graine. On peut utiliser la longueur d’itération
pour modifier la longueur de notre riff. Essayez de changer le 16 en 8
ou même en 4 ou 3 et voyez comment cela affecte le rythme du riff.
OK, combinons tout ce que nous avons appris dans un dernier exemple. A la prochaine !
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
Il est impossible de regarder l’histoire de la musique de danse électronique sans voir l’énorme impact du petit synthétiseur Roland TB-303. C’est la sauce secrète derrière le son original de basse acide. On entend ces riffs de basse classiques crissants et pataugeants depuis la jeune scène de house de Chicago jusqu’à des artistes plus récents comme Plastikman, Squarepusher et Aphex Twin.
Il est intéressant de savoir que Roland n’avait pas l’intention que le TB-303 soit utilisé dans de la musique pour danser. Il a été créé à l’origine comme une aide de travail pour les guitaristes. Ils ont imaginé que les gens les programmeraient pour jouer des lignes de basse d’accompagnement. Malheureusement il y avait un certain nombre de problèmes : ils étaient un peu compliqués à programmer, ne sonnaient pas particulièrement bien comme remplacement de guitare basse et ils étaient assez chers. Décidant d’arrêter les frais, Roland a cessé d’en fabriquer après en avoir vendu 10’000 unités et après un certain nombres d’années à rester sur les étagères des guitaristes, ils se retrouvés dans les vitrines des magasins d’occasion. C’est pauvres TB-303 rejetés attendaient d’être découverts par une nouvelle génération d’expérimentateurs qui ont commencé à les utiliser dans des manières que Roland n’avait pas imaginées pour créer des sons fous. La house acide était née.
Même si se procurer un TB-303 original n’est pas si facile vous serez heureux d’apprendre que vous pouvez transformer votre Raspberry Pi en TB-303 en utilisant la puissance de Sonic Pi. Lancez Sonic Pi, copiez ce code dans un buffer vide et cliquez sur ‘Run’ :
use_synth :tb303
play :e1
Instant acid bass! Let’s play around…
Commençons par construire un arpège interactif pour rendre les choses amusantes. Dans le dernier tutoriel nous avons vu comment des mélodies peuvent être juste un anneau de notes qu’on joue les unes après les autres, en répétant quand on arrive à la fin. Créons une boucle interactive qui fait cela :
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
Regardons chaque ligne.
A la première ligne choisit tb303
comme synthé par défaut avec la
fonction use_synth
.
A la deuxième ligne on crée une boucle interactive du nom de
:squelch
qui va juste boucler encore et encore.
A la troisième ligne on crée notre mélodie : un anneau de notes (E
ou Mi aux octaves 1, 2 et 3) et on le parcourt simplement avec
.tick
. On définit n
pour représenter la note courante de la
mélodie. Le signe égal veut juste dire qu’on affecte la valeur à
droite au nom à gauche. Cette valeur sera différente à chaque
boucle. La première fois n
aura la valeur :e1
. La deuxième fois
ce sera :e2
, puis :e3
, puis de nouveau :e1
, en bouclant à
l’infini.
A la ligne quatre on joue notre synthé :tb303
. On lui passe
quelques options intéressantes : release:
, cutoff:
, res:
et
wave:
que l’on décrira plus bas.
La ligne cinq est notre sleep
: on demande à la boucle
interactive de boucler toutes les 0.125
secondes ou 8 fois par
seconde au BPM par défaut de 60
La ligne six est la fin de la boucle interactive. Le mot end
indique juste à Sonic Pi où se termine la boucle interactive.
Alors que vous êtes encore en train de vous familiariser avec ce qui
se passe, tapez le code ci-dessous et cliquez sur le bouton ‘Run’.
Vous devriez entendre le :tb303
entrer en action. C’est ici le coeur
de l’action : commençons à programmer de manière interactive.
Pendant que la boucle tourne, changez l’option cutoff:
en 110
.
Puis cliquez à nouveau sur le bouton ‘Run’. Vous devriez entendre le
son devenir un peu plus dur et sec. Montez à 120
et cliquez sur
‘Run’. Puis 130
. Ecoutez comme les valeurs hautes de coupure rendent
le son plus perçant et intense. Enfin, descendez à 80
quand vous
sentirez que vous voulez un peu de repos. Puis répétez ça autant que
vous voulez. Pas d’inquiétude, je serai toujours là…
Une autre option qui vaut le coup d’être utilisée est res:
. Elle
contrôle le niveau de résonance du filtre. Une haute résonance est
caractéristique des sons de basse acide. Nous avons pour le moment une
res:
de 0.8
. Essayez de la monter à 0.85
, puis 0.9
, et enfin
0.95
. Un cutoff de 110
ou plus peut permettre d’entendre plus
facilement les différences. Enfin défoulez-vous et montez jusque
0.999
pour avoir des sons déments. Avec une res
aussi haute vous
entendez le filtre de coupure résonner tant qu’il commence à faire ses
propres sons.
Enfin pour avoir un grand impact sur le timbre essayez de mettre
l’option wave:
à 1
. C’est le choix de l’oscillateur source. La
valeur par défaut est 0
qui est une onde en dents de scie.
Bien sûr, essayez différentes mélodies en changeant les notes dans l’anneau ou même en choisissant des notes de gammes ou d’accords. Amusez-vous bien avec votre premier synthé de basse acide.
Le design du TB-303 original était en fait assez simple. Comme vous pouvez le voir sur le diagramme suivant il n’y a que quatre parties principales.
En premier on a l’onde oscillatoire : les ingrédients de base du son.
Dans ce cas nous avons une onde carrée. Ensuite on a l’enveloppe
d’amplitude de l’oscillateur qui contrôle l’amplitude de l’onde carrée
au cours du temps. On peut y accéder dans Sonic Pi avec les options
attack:
, decay:
, sustain:
et release:
ainsi que leur niveau
correspondant. Pour plus d’informations lisez la Section 2.4 ‘Durée
avec enveloppes’ dans le tutoriel inclus dans Sonic Pi. On passe
ensuite notre onde carrée enveloppée dans un filtre passe bas
résonant. Cela coupe les hautes fréquences et a un bel effet de
résonance. Et c’est ici que ça devient amusant. La valeur de coupure
de ce filtre est aussi contrôlée par sa propre enveloppe ! Cela veut
dire que nous avons un contrôle incroyable sur le timbre du son en
jouant avec ces deux enveloppes. Jetons-y un oeil :
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
Pour chaque option standard d’enveloppe, il y a une option cutoff_
équivalente dans le synthé :tb303
. Donc, pour changer le temps
d’attaque de la coupure on peut utiliser l’option :cutoff_attack
.
Copiez le code ci-dessus dans un buffer vide et cliquez sur ‘Run’.
Vous entendrez un son fou entrer et sortir. Maintenant essayez de
jouer avec. Essayez de changer la durée de cutoff_attack:
en 1
puis en 0.5
. Puis essayez 8
.
Remarquez que j’ai passé tout cela à travers un effet :reverb
pour
plus d’atmosphère : essayez d’autres effets pour voir ce qui marche !
Enfin voici un morceau que j’ai composé en utilisant les idées de ce tutoriel. Copiez le dans un buffer vide, écoutez un peu, puis commencez à programmer interactivement vos changements. Voyez quels sons fous vous pouvez faire avec ! A la prochaine…
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
Bonjour et bienvenue à nouveau ! Dans les tutoriels précédents nous nous somes concentrés exclusivement sur les possibilités mnusicales de Sonic Pi, en transformant votre Raspberry Pi en instrument de musique prêt à l’emploi. Jusqu’ici nous avons appris comment :
Il y a tellement plus à vous montrer, et nous l’explorerons dans de futures éditions. Cependant, ce mois-ci, nous allons regarder une chose que Sonic Pi sait faire et que vous n’avez probablement pas remarquée : contrôler Minecraft.
OK, commençons. Démarrez votre Raspberry Pi, lancez Minecraft Pi et créez un nouveau monde. Maintenant démarrez Sonic Pi et déplacez vos fenêtres de manière à pouvoir voir Sonic Pi et Minecraft Pi en même temps.
Dans un buffer disponible tapez ce qui suit :
mc_message "Hello Minecraft from Sonic Pi!"
Maintenant cliquez sur ‘Run’. Boum ! Votre message est apparu dans Minecraft ! C’était facile, non ? Maintenant arrêtez un moment de lire ceci et jouez un peu avec vos propres messages. Amusez-vous !
Explorons un peu. L’option standard est de saisir la souris et le clavier et de commencer à se promener. Ca marche, mais c’est assez lent et ennuyeux. Ce serait beaucoup mieux si on avait une sorte de machine de téléportation. Eh bien, grâce à Sonic Pi, on en a une. Essayez ceci :
mc_teleport 80, 40, 100
Oh ! On est monté bien haut. Si vous n’étiez pas en mode volant vous avez du retomber jusqu’au sol. Si vous double-tapez Espace pour entrer en mode volant et vous téléportez à nouveau, vous resterez en l’air à l’endroit où vous vous êtes déplacés.
Maintenant, qu’est-ce que ces nombres signifient ? Nous avons trois nombres qui décrivent les coordonnées de l’endroit du monde où vous voulez vous déplacer. On donne à chacun de ces nombres un nom : x, y et z.
En choisissant différentes valeurs pour x, y, et z, on peut se téléporter n’importe où dans notre monde. Essayez ! Choisissez différents nombres et regardez où vous vous retrouvez. Si l’écran devient noir c’est que vous vous êtes téléportés sous terre ou dans une montagne. Choisissez juste une valeur de y plus grande pour vous retrouver au-dessus de la terre. Continuez à explorer jusqu’à ce que vous trouviez un endroit qui vous plaise…
En utilisant les idées vues jusqu’ici, construisons un téléporteur sonique qui fera un son amusant de téléportation quand il nous fera voyager à travers le monde de 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!"
Maintenant que vous avez trouvé un endroit sympathique, commençons à construire. Vous pourriez faire comme vous en avez l’habitude et commencer à cliquer furieusement la souris pour placer des blocs sous le curseur. Ou vous pourriez utiliser la magie de Sonic Pi. Essayez ceci :
x, y, z = mc_location
mc_set_block :melon, x, y + 5, z
Maintenant regardez vers le haut ! Il y a un melon dans le ciel !
Prenez un moment pour regarder le code. Qu’est-ce qu’on a fait ? Sur
la première ligne on a attrapé l’emplacement actuel de Steve dans les
variables x, y et z. Elles correspondent aux coordonnées décrites
ci-dessus. Nous utilisons ces coordonnées dans la fonction
mc_set_block
qui va placer le bloc de votre choix aux coordonnées
spécifiées. Pour placer quelque chose plus haut dans le ciel on doit
juste augmenter la valeur de y, c’est pour ça qu’on lui ajoute 5.
Faisons un chemin de melons :
live_loop :melon_trail do
x, y, z = mc_location
mc_set_block :melon, x, y-1, z
sleep 0.125
end
Maintenant sautez dans Minecraft, assurez-vous d’être en mode volant (tapez deux fois sur Espace sinon) et volez autour du monde. Regardez derrière vous pour voir un beau chemin de blocs de melon ! Voyez quels dessins tordus vous pouvez faire dans le ciel.
Ceux d’entre vous qui ont suivi ce tutoriel pendant les derniers mois
doivent être bien étonnés. Le chemin de melons est assez cool, mais la
partie la plus excitante de l’exemple précédent est qu’on peut
utiliser la live_loop
avec Minecraft ! Pour ceux qui ne savent pas,
la live_loop
est la faculté magique et spéciale de Sonic Pi qu’aucun
autre langage de programmation ne possède. Elle vous permet d’exécuter
des boucles multiples en même temps et vous permet de les modifier
pendant qu’elles tournent. Elles sont incroyablement puissantes et
amusantes. J’utilise les live_loop
s pour jouer de la musique dans
des boîtes de nuit avec Sonic Pi : les DJs utilisent des disques et
moi j’utilise des live_loop
s :-) Cependant aujourd’hui nous allons
programmer de manière interactive de la musique et Minecraft.
Commençons. Exécutez le code ci-dessus et commencez à faire votre
chemin de melons de nouveau. Maintenant, sans arrêter le code, changez
simplement :melon
en :brick
et cliquez sur Run
. Eh voilà, vous
construisez maintenant un chemin de briques. C’était simple, non ?
Un peu de musique pour accompagner ça ? Facile. Essayez ceci :
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
Maintenant pendant que ça joue commencez à modifier le code. Changez
les types de bloc : essayez :water
, :grass
ou votre type de bloc
préféré. Aussi, essayez de changer la valeur de coupure de 70
à 80
puis jusque 100
. N’est-ce pas amusant ?
Rassemblons tout ce que nous avons vu jusqu’ici avec un peu de magie en plus. Combinons notre faculté de téléportation avec placement de blocs et la musique pour faire une vidéo de musique Minecraft. Ne vous inquiétez pas si vous ne comprenez pas tout, tapez juste le code et jouez ensuite à modifier quelques-unes des valeurs pendant qu’il s’exécute. Amusez-vous bien et à la prochaine…
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
Après notre briève excursion dans le monde fantastique de la programmation Minecraft avec Sonic Pi le mois dernier, penchons nous sur la musique à nouveau. Aujourd’hui nous allons amener un morceau classique de danse d’opéra droit dans le 21e siècle en utilisant la puissance fantastique du code.
Sautons dans une machine à remonter le temps jusqu’en 1875. Un compositeur nommé Bizet avait juste terminé son dernier opéra : Carmen. Malheureusement comme beaucoup de nouveaux morceaux excitants et perturbateurs les gens ne l’aimaient pas du tout au début parce qu’il était trop scandaleux et différent. Malheureusement Bizet est mort dix ans avant que l’opéra ne connaisse un grand succès international et ne devienne un des opéras les plus connus et les plus fréquemment interprétés de tous les temps. Par sympathie pour cette tragédie nous allons prendre un des thèmes principaux de Carmen et nous allons le convertir dans un format moderne de musique qui est aussi trop scandaleux et différent pour la plupart des gens de notre époque : la musique codée interactive !
Essayez de programmer un opéra entier de manière interactive serait un peu ambitieux pour ce tutoriel, concentrons nous sur une des ses plus célèbres parties : la ligne de basse de la Habanera :
Cela peut vous sembler complètement illisible si vous n’avez pas étudié la notation musicale. Cependant, en tant que programmeurs nous voyons la notation musicale comme juste une autre forme de code, elle représente juste des instructions pour un musicien au lieu d’un ordinateur.
Les notes sont arrangées de gauche à droite comme les mots dans ce magasine mais elles ont aussi différentes hauteurs. La hauteur sur la partition représente la hauteur d’une note. Plus une note est haut sur la partition, plus sa hauteur est grande.
Dans Sonic Pi nous savons déjà comment changer la hauteur d’une note :
on peut utiliser des grands ou petits nombres comme play 75
et
play 80
ou on peut utiliser les noms des notes : play :E
et
play :F
. Heureusement chacune des positions verticales sur la
partition représente un nom de note en particulier. Jetez un oeil à
cette table de correspondance bien pratique :
Les partitions sont une sorte de code extrêmement riche et expressif
capable de communiquer de nombreuses choses. Cela ne devrait donc pas
nous surprendre que les partitions peuvent non seulement nous dire
quelles notes jouer mais aussi quand ne pas jouer de note. En
programmation c’est à peu près l’équivalent de l’idée de nil
ou
null
: l’absence de valeur. En d’autres mots ne pas jouer une note
c’est comme une absence de note.
Si vous regardez de près la partition vous verrez que c’est en fait
une combinaison de ronds noirs avec des barres qui représentent les
notes à jouer et des choses ondulées qui représentent les silences.
Heureusement, Sonic Pi a une notation très pratique pour un silence :
:r
, donc si on exécute play :r
il jouera en fait un silence ! On
pourrait aussi écrire play :rest
, play nil
ou play false
qui
sont autant de manières équivalentes de représenter un silence.
Enfin il y a une dernière chose à apprendre à décoder dans la notation : la notion du temps. Dans la notation originale vous verrez que les notes sont liées par des traits épais. La deuxième note a deux de ces traits ce qui veut dire qu’elle dure un 16e de temps. Les autres notes ont un seul trait ce qui veut dire qu’elles durent un 8e de temps. Le silence a aussi deux traits ondulés ce qui veut dire qu’il représente aussi un 16e de temps.
Quand on essaie de décoder et d’explorer de nouvelles choses un truc très pratique est de rendre tout le plus semblable possible pour essayer de voir des relations ou modèles. Par exemple quand on réécrit notre notation uniquement en double-croches on peut voir que notre notation devient une séquence agréable de notes et de silences.
Nous sommes maintenant prêts a traduire cette ligne de basse dans Sonic Pi. Encodons ces notes et silences dans un anneau :
(ring :d, :r, :r, :a, :f5, :r, :a, :r)
Voyons ce que ça donne. Jetons ça dans une boucle interactive et parcourons-là :
live_loop :habanera do
play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
sleep 0.25
end
Fabuleux, cette mélodie qu’on reconnait immédiatement prend vie dans vos haut-parleurs. On a fait des efforts pour en arriver là, mais ça valait la peine, bravo !
Maintenant qu’on a la ligne de basse, essayons de re-créer une partie
de l’ambiance de la scène d’opéra. Un synthé à essayer est :blade
qui est un synthé style années 80. Essayons le avec la note de départ
:d
passée dans un slicer et de la 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
Maintenant essayez les autres notes de la ligne de basse : :a
et
:f5
. Souvenez-vous que vous n’avez pas besoin de cliquer sur ‘Stop’,
vous pouvez juste modifier le code pendant que la musique tourne et
ensuite cliquer sur ‘Run’ à nouveau. Aussi essayez différentes valeurs
pour l’option phase:
du slicer comme 0.5
, 0.75
et 1
.
Enfin, combinons toutes les idées vues jusqu’ici dans un nouveau remix
de la Habanera. Vous remarquerez peut-être que j’ai inclus une autre
partie de la ligne de basse en commentaire. Quand vous aurez tout tapé
dans un buffer de libre cliquez sur ‘Run’ pour entendre la
composition. Maintenant, sans cliquer sur ‘Stop’, décommentez la
seconde ligne en enlevant le #
et cliquez sur ‘Run’ à nouveau :
c’est merveilleux, non ? Maintenant amusez-vous à le modifier vous-même.
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
Tout le monde a joué à Minecraft. Vous aurez tous construit des structures incroyables, conçu des pièges rusés et même créé des lignes de chariots raffinées contrôlées par des interrupteurs de pierre rouge. Mais qui parmi vous s’est produit avec Minecraft ? On parie que vous ne saviez pas que vous pouvez utiliser Minecraft pour créer des animations visuelles incroyables tout comme un VJ professionnel.
Si votre seule possibilité de modifier Minecraft était d’utiliser la souris, vous auriez du mal à changer les choses suffisamment vite. Heureusement pour vous votre Raspberry Pi a une version de Minecraft qui peut être contrôlée avec du code. Il contient aussi une application nommée Sonic Pi qui rend la programmation Minecraft non seulement facile mais aussi incroyablement amusante.
Dans l’article d’aujourd’hui nous allons vous montrer quelques trucs et astuces que nous avons utilisés pour créer des spectacles dans des boîtes de nuit et salles de concert autour du monde.
Commençons…
Commençons avec un simple exercice d’échauffement pour nous rappeler les bases. Commencez par allumer votre Raspberry Pi et lancer Minecraft et Sonic Pi. Dans Minecraft, créez un nouveau monde, et dans Sonic Pi choisissez un buffer de libre et écrivez-y ce code :
mc_message "Let's get started..."
Cliquez sur le bouton ‘Run’ et vous verrez le message dans la fenêtre Minecraft. OK, on est prêt à démarrer, on va s’amuser…
Quand on utilise Minecraft pour créer des visuels on essaie de penser à des choses qui auront l’air intéressantes et qui seront aussi faciles à générer avec du code. Un truc sympa est de créer une tempête de sable en laissant tomber des bloc de sable du ciel. Pour cela on a juste besoin de quelques fonctions simples :
sleep
: pour insérer un délai entre des actionsmc_location
: pour trouver notre emplacement courantmc_set_block
: pour positionner des blocs de sable à un endroit particulierrrand
: pour nous permetre de générer des valeurs aléatoires dans un intervallelive_loop
: pour nous permettre de faire pleuvoir du sable en continuSi vous ne connaissez pas une des ces fonctions comme rrand
, vous
pouvez juste taper le mot dans votre buffer, cliquer dessus, puis
taper Control-i
sur le clavier pour ouvrir la documentation. Vous
pouvez aussi aller dans l’onglet lang du système d’aide puis
y chercher directement les fonctions et toutes sortes d’autres choses
excitantes que vous pouvez faire.
Commençons par faire tomber un peu de pluie avant de laisser la tempête complète éclater. Récupérez votre emplacement courant et utilisez-la pour créer quelques blocs de sable dans le ciel pas loin :
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
Après avoir cliqué sur ‘Run’, vous devrez peut-être un peu regarder autour de vous car les blocs peuvent commencer par tomber derrière vous, suivant dans quelle direction vous êtes pour le moment. N’ayez pas peur, si vous les avez raté, cliquez à nouveau sur ‘Run’ pour créer encore un peu de pluie de sable, assurez-vous juste de regarder dans la bonne direction.
Parcourons rapidement ce qui se passe ici. Sur la première ligne nous
avons récupéré l’emplacement Steve en coordonnées avec la fonction
mc_location
et les avons placées dans les variables x
, y
et z
.
Puis sur les lignes suivantes nous avons utilisé la fonction
mc_set_block
pour placer un peu de sable aux mêmes coordonnées que
Steve mais avec quelques modifications. On a utilisé la même
coordonnée x, une coordonnée y 20 blocs plus haut et des coordonnées z
successivement plus larges pour que le sable tombe dans une ligne en
s’éloignant de Steve.
Et si vous preniez ce code et commenciez à jouer avec ? Essayez
d’ajouter plus de lignes, de changer la durée d’attente, essayez de
mélanger du :sand
avec du :gravel
et choisissez différentes
coordonnées. Expérimentez et amusez-vous !
OK, il est l’heure de lancer la tempête en déchaînant la puissance
complète de la live_loop
: la capacité magique de Sonic Pi qui
montre la puissance entière de la programmation interactive : changer
le code à la volée pendant qu’il est en train de s’exécuter !
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
Qu’est-ce que c’est amusant ! On boucle assez vite (8 fois par seconde) et pendant chaque boucle on trouve l’emplacement de Steve comme avant mais on génère ensuite trois valeurs aléatoires :
xd
: la différence pour x qui sera entre -10 et 10zd
: la différence pour z, aussi entre -10 et 10co
: une valeur de coupure pour le filtre passe-bas, entre 70 et 130On utilise ensuite ces valeurs aléatoires dans les fonctions synth
et mc_set_block
ce qui nous donne du sable qui tombe dans des
endroits aléatoires autour de Steve ainsi qu’un son percussif
semblable à de la pluie, joué le synthé :cnoise
.
Pour ceux d’entre vous qui ne connaissaient pas les boucles
interactives : c’est là qu’on commence vraiment à s’amuser avec Sonic
Pi. Pendant que le code tourne et que le sable pleut, essayez de
changer une des valeurs, peut-être la valeur d’attente à 0.25
ou
le type de bloc :sand
en :gravel
. Ensuite cliquez sur ‘Run’ à
nouveau. Et voilà ! Les choses changent sans que le code ne s’arrête.
C’est votre passerelle pour vous produire comme un vrai VJ. Continuez
à vous exercer à changer des choses. Jusqu’où arrivez-vous à modifier
les visuels sans arrêter le code ?
Enfin une autre super façon de générer des visuels intéressants est de
générer des énormes murs de motifs vers lesquels voler. Pour cet effet
nous allons devoir passer d’un placement aléatoire de blocs à un
placement de manière ordonnée. On peut faire cela en imbriquant deux
itérations (cliquez sur le bouton ‘Aide’ et allez dans la section 5.2
du tutoriel “Itération et boucles” pour plus d’informations sur
l’itération). L’étrange |xd|
après le do
veut dire que xd
prendra une valeur à chaque boucle de l’itération. La première fois il
vaudra 0
, puis 1
, puis 2
, etc. En imbriquant deux itérations
comme cela on peut générer toutes les coordonnées d’un carré. On peut
ensuite choisir aléatoirement des types de blocs d’un anneau de blocs
pour obtenir un effet intéressant :
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
Pas mal. Pendant qu’on s’amuse ici, essayez de changer bs.choose
en
bs.tick
pour passer d’un motif aléatoire à un motif plus régulier.
Essayez de changer les types de blocs et les plus aventureux parmi
vous voudrons peut-être mettre ce code dans une live_loop
pour que
les modifs continuent à changer automatiquement.
Enfin, pour la fin du set du VJ, changez les deux 10.times
en
100.times
et cliquez sur ‘Run’. Boum ! Un énorme mur géant de
briques aléatoires. Imaginez combien de temps ça vous aurait pris de
construire ça avec votre souris ! Double-tapez la touche Espace pour
entrer en mode volant et commencez à planer pour obtenir de super
effets visuels. Ne vous arrêtez pas là, utilisez votre imagination
pour trouver des idées sympa et utilisez ensuite la puissance de
programmation de Sonic Pi pour le réaliser. Quand vous vous serez
suffisamment exercés, baissez la lumière et donnez un spectacle de VJ
pour vos amis !
Dans le quatrième épisode de cette série de tutoriels nous avons jeté un oeil brièvement à l’aléatoire en codant des riffs grésillants de synthé. Vu comme l’aléatoire est une partie très importante de mes performances de live coding j’ai pensé qu’il serait utile d’en couvrir les bases plus en détail. Mettez votre casquette et surfons sur des flux aléatoires !
La première chose à apprendre qui pourrait vraiment vous surprendre en
jouant avec les fonctions aléatoires de Sonic Pi c’est qu’elles ne
sont en fait pas vraiment aléatoires. Qu’est-ce que cela signifie ?
Eh bien, faisons quelques essais. Commencez par imaginer un nombre
dans votre tête entre 0 et 1. Gardez-le en tête et ne me le dites pas.
Maintenant, laissez-moi deviner… est-ce que c’était 0.321567
?
Non ? Bah, je ne suis clairement pas bon à ce jeu. Essayons encore une
fois, mais demandons à Sonic Pi de choisir un nombre cette fois.
Lancez Sonic Pi version 2.7 ou plus et demandez lui un nombre
aléatoire mais de nouveau ne me dites pas le résultat.
print rand
Et maintenant pour le truc… est-ce que c’était 0.75006103515625
?
Oui ! Ha, je vois que vous êtes un peu sceptique. C’était peut-être
juste de la chance. Essayons encore. Cliquez sur ‘Run’ à nouveau et
regardons ce qu’on obtient… Quoi ? Encore 0.75006103515625
? Ca ne
peut clairement pas être aléatoire ! Vous avez raison, ça ne l’est pas.
Qu’est-ce qui se passe ici ? Le mot savant d’informatique pour ceci
est le déterminisme. Cela veut juste dire que rien n’a lieu par hasard
et que tout a sa destinée. Votre version de Sonic Pi a le destin de
toujours retourner 0.75006103515625
dans le programme ci-dessus.
Cela peut sembler assez inutile, mais laissez moi vous assurer que
c’est une des parties les plus puissantes de Sonic Pi. Si vous
persévérez vous apprendrez comment compter sur la nature
déterministique de l’aléatoire dans Sonic Pi comme un bloc de
construction fondamental pour vos compositions et performances de live
coding.
Quand Sonic Pi démarre il charge en fait en mémoire une séquence de
441 000 valeurs aléatoires pré-générées. Quand vous appelez une
fonction aléatoire comme rand
ou rrand
, ce flux aléatoire est
utilisé pour générer votre résultat. Chaque appel à une fonction
aléatoire consomme une valeur de ce flux. Ainsi le dixième appel à une
fonction aléatoire utilisera la dixième valeur du flux. Aussi, chaque
fois que vous cliquez sur le bouton ‘Run’, le flux est réinitialisé
pour cette exécution. C’est pour cela que j’ai pu prédire le résultat
de rand
et pourquoi la mélodie ‘aléatoire’ était la même à chaque
fois. La version de Sonic Pi de chacun utilise exactement le même flux
aléatoire ce qui est très important quand on commence à partager nos
morceaux.
Utilisons cette connaissance pour générer une mélodie aléatoire répétable :
8.times do
play rrand_i(50, 95)
sleep 0.125
end
Tapez ceci dans un buffer de libre et cliquez sur ‘Run’. Vous entendrez une mélodie de notes aléatoires entre 50 et 95. Quand elle aura fini, cliquez sur ‘Run’ à nouveau pour entendre exactement la même mélodie à nouveau.
start breakout box ## Des fonctions aléatoires pratiques
Sonic Pi contient un certain nombre de fonctions utiles pour travailler avec le flux aléatoire. Voici une liste des plus utiles :
rand
: retourne simplement la prochaine valeur dans le flux aléatoirerrand
: retourne une valeur aléatoire dans un intervallerrand_i
: retourne une valeur entière aléatoire dans un intervalleone_in
: retourne vrai ou faux pour une probabilité donnéedice
: imite un jet de dé et retourne une valeur entre 1 et 6choose
: choisit une valeur aléatoire dans une listeRegardez leur documentation dans le système d’aide pour des informations détaillées et des exemples.
end breakout box
Même si la capacité de répéter une séquence de notes choisies est essentielle pour vous permettre de rejouer une mélodie sur la piste de danse, ça pourrait ne pas être exactement la mélodie que vous souhaitez. Ne serait-ce pas génial si on pouvait essayez différentes mélodies et choisir celle qu’on préfère ? C’est ici que la vraie magie commence.
On peut régler le flux manuellement avec la fonction
use_random_seed
. En informatique, une graine aléatoire est le point
de départ à partir duquel un nouveau flux de valeurs aléatoires peut
fleurir. Essayons-le :
use_random_seed 0
3.times do
play rrand_i(50, 95)
sleep 0.125
end
Super, on récupère les trois premières notes de notre mélodie
aléatoire ci-dessus : 84
, 83
et 71
. Cependant on peut
maintenant changer la graine. Par exemple :
use_random_seed 1
3.times do
play rrand_i(50, 95)
sleep 0.125
end
Intéressant, on obtient 83
, 71
et 61
. Vous avez peut-être
remarqué que les deux premiers nombres ici sont les mêmes que les deux
derniers nombres d’avant : ce n’est pas une coïncidence.
Rappelez-vous que le flux aléatoire est juste une liste géante de valeurs pré-choisies. Choisir une graine aléatoire nous déplace juste en un point de la liste. Une autre manière de voir ça est d’imaginer un énorme jeu de cartes pré-mélangées. Utiliser une graine aléatoire, c’est couper le jeu en un point particulier. Ce qui est fabuleux avec ça c’est qu’on peut se déplacer dans le flux aléatoire, ce qui nous donne un énorme pouvoir quand on fait de la musique.
Revisitons notre mélodie aléatoire de huit notes avec cette nouvelle capacité de réinitialiser le flux, et mettons là dans une boucle interactive pour pouvoir expérimenter pendant qu’elle joue :
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
Maintenant, pendant qu’elle est en train de jouer, changez la valeur
de la graine de 0
en quelque chose d’autre. Essayez 100
, ou
pourquoi pas 999
. Essayez vos propres valeurs, expérimentez et
amusez-vous : voyez quelle graine génère la mélodie que vous préférez.
Le tutoriel de ce mois a été un plongeon bien technique dans les entrailles de la fonctionnalité aléatoire de Sonic Pi. J’espère que cela vous a montré un peu comment elle marche et comment vous pouvez commencer à utiliser de l’aléatoire de manière fiable pour créer des motifs reproductibles dans votre musique. Il est important de souligner qu’on peut utiliser de l’aléatoire reproductible où on veut. Par exemple, on peut rendre aléatoire l’amplitude des notes, le mix d’un effet, etc. Dans l’avenir nous regarderons de plus près certaines de ces applications, mais pour le moment je vais vous laisser avec un exemple court.
Tapez le code suivant dans un buffer disponible, cliquez sur ‘Run’ et commencez à modifier les graines, cliquez sur ‘Run’ de nouveau (pendant que le code tourne) et explorez les différents sons, rythmes et mélodies que vous pouvez créer. Quand vous en trouvez une qui sonne bien, notez la graine pour pouvoir y revenir plus tard. Enfin, quand vous aurez trouvé quelques graines qui vous plaisent, donnez un concert de live coding à vos amis en changeant simplement entre vos graines préférées pour créer un morceau entier.
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
Jusqu’ici dans cette série nous nous sommes concentrés sur le
déclenchement de sons. Nous avons découvert qu’on pouvait déclencher
les nombreux synthés présents dans Sonic Pi avec play
ou synth
et
comment déclencher des samples pré-enregistrés avec sample
. Nous
avons aussi vu comment on pouvait entourer ces sons dans des effets
studio tels que la reverb et la distorsion en utilisant la commande
with_fx
. En combinant cela avec le système de chronométrage
incroyablement précis de Sonic Pi on peut produire un vaste ensemble
de sons, rythmes et mélodies. Cependant, une fois qu’on a
soigneusement sélectionné les options d’un son en particulier et qu’on
l’a déclenché, on ne peut plus le modifier pendant qu’il est joué,
c’est ça ? Non ! Aujourd’hui vous allez apprendre quelque chose de
très puissant : comment contrôler des synthés qui sont en train d’être
joués.
Créons un simple son agréable. Lancez Sonic Pi et tapez le code suivant dans un buffer disponible :
synth :prophet, note: :e1, release: 8, cutoff: 100
Maintenant cliquez sur le bouton ‘Run’ en haut à gauche pour entendre un beau son de synthé grondant. Allez-y, cliquez à nouveau dessus quelques fois pour vous habituer. OK, fini? Commençons à le contrôler !
Une fonctionnalité peu connue de Sonic Pi est que les fonctions
play
, synth
et sample
retournent ce qu’on appelle un SynthNode
qui représente un son en train d’être joué. Vous pouvez capturer un de
ces SynthNode
s en utilisant une variable standard et le contrôler
ensuite dans le futur. Par exemple, changeons la valeur de l’option
cutoff:
après un battement :
sn = synth :prophet, note: :e1, release: 8, cutoff: 100
sleep 1
control sn, cutoff: 130
Regardons chaque ligne une par une :
On commence par déclencher le synthé :prophet
en utilisant la
fonction synth
habituelle. Cependant on capture aussi le résultat
dans une variable nommée sn
. On aurait pu appeler cette variable
complètement différemment comme par exemple synth_node
ou jane
:
le nom n’a pas d’importance. Enfin il est important de choisir un nom
qui a du sens pour vous pour vos performances et pour les gens qui
lisent votre code. J’ai choisi sn
parce que c’est un bon petit moyen
mnémotechnique pour ‘synth node’.
A la ligne 2 on a une commande sleep
standard. Ca ne fait rien de
spécial : ça demande juste à l’ordinateur d’attendre un battement
avant d’avancer à la ligne suivante.
C’est à la ligne 3 qu’on commence à s’amuser. Ici on utilise la
fonction control
pour dire à notre SynthNode
courant de changer la
valeur de coupure en 130
. Si vous cliquez sur le bouton ‘Run’, vous
entendrez le synthé :prophet
commencer à jouer comme avant, mais
après un battement il changera et sonnera beaucoup plus clair.
** Breakout Box Start ** Options modulables
La plupart des options des synthés et effets de Sonic Pi peuvent être
modifiées après avoir été déclenchées. Cependant, ce n’est pas le cas
pour toutes. Par exemple, les options d’enveloppe attack:
, decay:
,
sustain:
et release:
ne peuvent être définies que quand on
déclenche le synthé. Pour savoir quelles options peuvent être
modifiées ou non, c’est simple : allez voir la documentation d’un
synthé ou effet et regardez la documentation des options individuelles
et cherchez les phrases “May be changed whilst playing” (Peut être
modifiée en jouant) ou “Can not be changed once set” (ne peut pas être
modifiée une fois définie). Par exemple, la documentation de l’option
attack:
du synthé :beep
indique clairement qu’on ne peut pas la
modifier ultérieurement :
Pendant qu’un synthé est joué vous n’êtes pas limités à ne le changer
qu’une fois : vous êtes libres de le modifier autant que vous le
souhaitez. Par exemple, on peut transformer notre :prophet
en petit
arpégiateur avec le code suivant :
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
Dans cet extrait de code nous avons juste introduit quelques choses en
plus. On commence par définir une nouvelle variable appelée notes
qui contient les notes qu’on aimerait parcourir en boucle (un
arpégiateur est juste un mot savant pour quelque chose qui parcourt en
boucle une liste de notes dans un ordre donné). Ensuite on déplace
notre appel à control
dans une itération en l’appelant 16 fois. A
chaque appel à control
on parcourt notre anneau de notes
qui va se
répéter automatiquement quand on arrivera à sa fin (grâce à la
puissance fabuleuse des anneaux de Sonic Pi). Pour un peu de variété
essayez de remplacer .tick
par .choose
et tentez d’entendre la
différence.
Notez qu’on peut modifier plusieurs options en même temps. Essayez de changer la ligne de contrôle en la suivante et écoutez la différence :
control sn, note: notes.tick, cutoff: rrand(70, 130)
Quand on contrôle un SynthNode
, il répond exactement à ce moment-là
et change immédiatement la valeur de l’option comme si vous aviez
pressé un bouton ou actionné un interrupteur pour demander la
modification. Cela peut sonner rythmique et percussif, notamment si
l’option contrôle un aspect du timbre comme cutoff:
. Cependant, on
n’a pas toujours envie que la modification arrive immédiatement. On a
parfois envie de se déplacer en douceur de la valeur courante à la
nouvelle, comme si on avait déplacé un curseur. Bien sûr, Sonic Pi
sait aussi faire cela en utilisant les options _slide:
Chaque option qui peut être modifiée a aussi une option spéciale
correspondante _slide:
qui vous permet de définir un temps de
transition. Par exemple, amp:
a amp_slide:
et cutoff:
a
cutoff_slide:
. Ces options de transition marchent un peu
différemment de toutes les autres options parce qu’elles disent à la
note de synthé comment se comporter la prochaine fois qu’elle seront
contrôlées. Voyons ça :
sn = synth :prophet, note: :e1, release: 8, cutoff: 70, cutoff_slide: 2
sleep 1
control sn, cutoff: 130
Remarquez que cet exemple est exactement le même qu’avant sauf qu’on a
ajouté cutoff_slide:
. Ceci indique que la prochaine fois que
l’option cutoff:
de ce synthé sera contrôlée, il mettra deux
battements pour passer de sa valeur courante à la nouvelle valeur.
Par conséquent, quand on utilise control
vous pouvez entendre la
coupure changer graduellement de 70 à 130. Cela crée une sensation
dynamique intéressante pour le son. Maintenant essayez de changer la
durée de cutoff_slide:
en une valeur plus courte comme 0.5 ou une
valeur plus longue comme 4 pour voir comment ça change le son.
Souvenez-vous que vous pouvez transitionner chacune des options
modifiables de cette même manière, et chaque valeur de _slide:
peut
être complètement différente donc vous pouvez avoir une transition
lente de la coupure, une transition rapide de l’amplitude, et une
transition de la stéréo un peu entre les deux si c’est ce que vous
avez envie de créer.
Regardons un court exemple qui montre la puissance du contrôle des synthés après leur déclenchement. Remarquez que vous pouvez aussi transitionner les effets comme les synthés, mais avec une syntaxe légèrement différente. Regardez la section 7.2 du tutoriel inclus dans Sonic Pi pour plus d’information sur le contrôle des effets.
Copiez le code dans un buffer de libre et écoutez. Ne vous arrêtez pas là : jouez à modifier le code. Changez les durées de transition, changez les notes, le synthé, l’effet et les durées d’attente et voyez si vous pouvez le transformer en quelque chose de complètement différent !
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
Le mois dernier dans cette série nous avons regardé en détail comment fonctionne le système de gestion de l’aléatoire de Sonic Pi. On a exploré comment on peut l’utiliser de manière déterministe pour avoir de nouveaux niveaux de contrôle dynamique sur notre code. Ce mois-ci nous allons continuer notre exploration technique et regarder le système unique de ‘tick’ de Sonic Pi. D’ici la fin de cet article vous parcourrez des rythmes et mélodies sur votre chemin pour devenir un DJ de programmation interactive.
Quand on fait de la musique on a souvent envie de faire quelque chose
de différent en fonction du temps sur lequel on est. Sonic Pi a un
système spécial pour compter les temps appelé tick
pour vous donner
un contrôle précis sur quand est-ce qu’un battement arrive réellement
et il supporte même des battements multiples avec leur propre tempo.
Amusons-nous : pour avancer le temps on a juste besoin d’appeler
tick
. Ouvrez un buffer libre, tapez le code suivant et cliquez sur
le bouton ‘Run’ :
puts tick #=> 0
Cela retournera le battement courant : 0
. Remarquez que même si
vous cliquez plusieurs fois sur le bouton ‘Run’, il retournera
toujours 0
. Cela parce que chaque exécution commence avec un
compteur qui part de 0. Cependant, pendant que le programme tourne, on
peut avancer le compteur autant qu’on veut :
puts tick #=> 0
puts tick #=> 1
puts tick #=> 2
On a vu que tick
fait deux choses. Il incrémente (ajoute un) et
retourne le compteur courant. Parfois on veut juste regarder le
battement courant sans devoir l’incrémenter et on peut faire cela via
look
.
puts tick #=> 0
puts tick #=> 1
puts look #=> 1
puts look #=> 1
Dans ce code on incrémente le compteur deux fois puis on appelle
look
deux fois. On verra les valeurs suivantes dans le log : 0
,
1
, 1
, 1
. Les deux premiers tick
s ont retourné 0
et 1
,
comme attendu, puis les deux look
s ont juste retourné la dernière
valeur du compteur deux fois, donc 1
.
On peut donc avancer le compteur avec tick
et en connaître la valeur
avec look
. Qu’est-ce qui vient suite ? On a besoin de quelque chose
à parcourir. Sonic Pi utilise les anneaux pour représenter les
mélodies et rythmes et le système de tick a été conçu spécialement
pour fonctionner avec eux. En fait, les anneaux ont leur propre
version de tick
qui fait deux choses. D’un côté elle agit comme un
tick normal et incrémente le compteur. D’un autre, elle donne une
valeur de l’anneau en utilisant le compteur comme index. Voyons cela :
puts (ring :a, :b, :c).tick #=> :a
.tick
est une version spéciale avec un point de tick
qui nous
retourne la première valeur de l’anneau: : :a
. On peut attraper
chacune des notes de l’anneau en appelant :tick
plusieurs fois :
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
Regardez le log et vous verrez :a
, :b
, :c
et puis de nouveau
:a
. Remarquez que look
retourne 3
. Les appels à .tick
se
comportent comme les appels à tick
: ils incrémentent le compteur
local.
La véritable puissance vient quand on mélange tick
avec des anneaux
et des live_loop
s. En les combinant on a tous les outils dont on a
besoin pour construire et comprendre un arpégiateur simple. On a juste
besoin de quatre choses :
Ces concepts se retrouvent tous dans le code suivant :
notes = (ring 57, 62, 55, 59, 64)
live_loop :arp do
use_synth :dpulse
play notes.tick, release: 0.2
sleep 0.125
end
Regardons chacune de ces lignes. On commence par définir notre anneau
de notes que nous allons jouer en continu. On crée ensuite une
live_loop
nommée :arp
qui va boucler pour nous. A chaque itération
de la live_loop
on choisit un synthé :dpulse
et on joue ensuite la
note suivante de notre anneau en utilisant .tick
. Souvenez-vous que
cela va incrémenter notre compteur de temps et en utiliser la valeur
comme index dans notre anneau de notes. Enfin on attend un huitième de
temps avant de recommencer la boucle.
Une chose très importante à savoir est que les tick
s sont liés à la
live_loop
. Cela veut dire que chaque live_loop
a son propre
compteur indépendant. C’est beaucoup plus puissant que d’avoir un
métronome et battement global. Regardons ce que cela donne :
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
Une grande source de confusion dans le système de tick de Sonic Pi est
quand on veut parcourir plusieurs anneaux dans le même 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
Même si chaque live_loop
a son compteur indépendant, ici on appelle
.tick
deux fois dans la même live_loop
. Cela veut dire que le
compteur sera incrémenté deux fois à chaque boucle. Cela peut produire
des polyrythmes intéressants mais ce n’est souvent pas ce que l’on
souhaite. Il y a deux solutions à ce problème. Une option est
d’appeler tick
manuellement au début de la live_loop
puis
d’utiliser look
pour chercher la valeur courante du compteur dans
chaque live_loop
. La seconde solution est de passer un nom unique
à chaque appel à .tick
, comme par exemple .tick(:foo)
. Sonic Pi
créera alors un compteur séparé pour chaque tick nommé que vous
utiliserez. Ainsi on peut travailler avec autant de compteurs que
nécessaire ! Lisez le section 9.4 sur les ticks nommés dans le
tutoriel inclus dans Sonic Pi pour plus d’informations.
Combinons nos connaissances sur les tick
s, ring
s (anneaux) et
live_loop
s pour un dernier exemple amusant. Comme d’habitude, ne
traitez pas ceci comme un morceau terminé. Commencez à changer des
choses et amusez-vous avec et voyez en quoi vous pouvez le
transformer. A la prochaine…
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