3 points par GN⁺ 2024-08-11 | 1 commentaires | Partager sur WhatsApp
  • Sonic Pi est présenté comme un environnement permettant de créer de la musique sans instruments ni matériel, avec un DSL basé sur Ruby dans lequel on peut écrire directement notes, accords, gammes et timings
  • En utilisant les fonctions, tableaux, conditions, boucles et portées de Ruby, on peut combiner play, sleep, play_pattern_timed, chord et scale pour construire de façon concise des motifs répétitifs et des arpèges
  • En combinant in_thread, ring, flatten, l’opérateur splat et with_fx, on peut exécuter plusieurs « instruments » en même temps et superposer des notes empilées et des rythmes différents
  • Le réglage de attack, decay, sustain et release dans l’enveloppe ADSR vise moins à reproduire fidèlement un vrai chœur qu’à ajuster la durée de maintien et la séparation
  • live_loop permet de mettre à jour du code en cours de lecture et de l’exécuter en boucle, faisant de Sonic Pi un outil de performance live et invitant à voir le code comme un texte lisible autant que comme un acte de création

Sonic Pi contrôlé par le code

  • Contrairement aux applications audio classiques, Sonic Pi est un synthétiseur logiciel contrôlé uniquement par du code
  • Son langage de contrôle est un langage dédié à un domaine (DSL) qui étend Ruby et mappe les concepts musicaux et audio sur la syntaxe Ruby
  • Les éléments de base sont composés de valeurs Ruby et de fonctions Sonic Pi
    • Les noms de notes comme :c4 sont utilisés comme symboles correspondant aux codes MIDI associés
    • On peut créer un accord en passant une note fondamentale et une structure d’accord en arguments, comme chord(:d3, :maj7)
    • play joue une note, et sleep de Ruby sert à contrôler les intervalles de temps
    • play_pattern_timed reçoit une liste de notes et un intervalle de temps, ce qui réduit le code nécessaire à la lecture répétée
  • L’objectif de l’exemple est de créer en code un accompagnement de démonstration avec les seules fonctions de base de Sonic Pi, sans MIDI externe ni samples
  • Après installation de l’application Sonic Pi, on peut coller l’exemple de code pour le suivre ; la documentation du langage et les tutoriels sont également fournis par défaut

Créer des motifs répétitifs avec la syntaxe Ruby

  • L’exemple de base change le BPM avec use_bpm 70 et utilise un synthétiseur pulse avec use_synth :pulse au lieu de l’onde sinusoïdale par défaut
  • En répétant play :c2 et sleep 0.25, on peut jouer les notes dans l’ordre ; avec play_pattern_timed [ :c3, :d3, :e3, :g3 ], 0.25, on peut écrire la même structure plus brièvement
  • Comme le langage de contrôle repose sur Ruby, on peut abstraire les motifs avec des fonctions et des boucles
    • La fonction arpeggiate reçoit une note fondamentale et une option indiquant éventuellement le mode mineur, puis crée un motif montant et descendant
    • Une boucle 4.times exécute le même motif sur plusieurs octaves
    • Une condition modifie la tierce en mode mineur, et map sur un tableau ajoute des intervalles à la note fondamentale pour générer la liste des notes
  • On peut d’abord définir les options par défaut du synthétiseur avec use_synth_defaults amp: 0.1, ou passer directement des options à play ou play_pattern_timed
  • En Ruby, les parenthèses d’appel de fonction sont optionnelles, mais dans des cas comme play chord(:a3, maj7), il peut être nécessaire de clarifier la séparation

Exécution parallèle et layering

  • Les blocs in_thread do servent à exécuter du code en parallèle dans Sonic Pi
  • En plaçant différents blocs in_thread, on peut faire jouer simultanément deux « instruments » distincts
    • Un thread peut prendre en charge un motif d’arpège
    • Un autre thread peut jouer une mélodie séparée avec use_synth :saw, un tableau de mélodie et un tableau de rythmes
  • play_pattern_timed peut recevoir non seulement une liste de notes, mais aussi une liste d’intervalles de temps
    • [1] * 2 allonge le tableau en répétant son contenu, comme [1, 1]
    • Les tableaux imbriqués n’étant pas acceptés tels quels par play_pattern_timed, on les aplatit en un tableau à un seul niveau avec flatten
  • Pour créer des notes empilées comme dans un chœur, on peut regrouper plusieurs notes avec ring(:c5, :e5)
  • Comme flatten peut aussi fusionner les listes internes à ring, on utilise dans ce cas l’opérateur splat * pour déplier le contenu d’une liste dans le tableau parent

Portée, effets et construction des parties de chœur

  • Avec des in_thread imbriqués, on peut partager des fragments rythmiques de la portée externe tout en réutilisant les mêmes noms de variables dans chaque thread interne
  • Si l’on sépare des parties comme soprano et alto dans des threads distincts, chaque bloc a sa propre portée et n’accède pas directement aux variables des autres
  • with_fx :reverb, mix: 0.2 crée un bloc d’effet ; le flux du signal part de la couche la plus interne et se déplace vers la chaîne d’effets externe
  • mix indique le degré de mélange entre signal wet et signal dry
    • Le signal wet est le signal auquel l’effet a été appliqué
    • Le signal dry est le signal sans effet
  • Envelopper tout un groupe dans un seul effet peut s’utiliser d’une manière proche d’un bus dans une DAW, mais les routages plus profonds sont manuels et, à cause de la portée, doivent généralement être structurés de haut en bas
  • Sonic Pi se manipule plus naturellement comme un instrument que comme un outil de production sophistiqué

Ajuster la durée des notes avec l’enveloppe ADSR

  • play_pattern_timed ajoutant une valeur de sustain, on peut ajuster directement la durée de maintien des accords longs et courts
  • attack, decay, sustain et release décrivent la manière dont le volume évolue dans le temps : c’est l’enveloppe ADSR
    • attack est le temps nécessaire pour passer de 0 au premier pic, correspondant à l’attaque initiale, comme lorsqu’on pince une corde de guitare ou qu’un marteau de piano frappe la corde
    • decay est le temps de descente depuis le premier pic, correspondant à la phase où le son diminue progressivement même si l’on maintient une touche de piano ou une corde de guitare
    • sustain est le temps pendant lequel le son est maintenu à un volume stable, comme une corde frottée à l’archet ou une voix tenue
    • release est le temps nécessaire pour que le son devienne effectivement silencieux après avoir été relâché
  • Tous les sons ne possèdent pas tous les éléments ADSR
    • Un son de synthétiseur étant généré, il n’a pas nécessairement de montée initiale ni de résonance résiduelle
    • Pour les instruments naturels, la proportion des éléments varie selon la manière de jouer
  • La simulation de chœur de l’exemple se concentre moins sur le réalisme que sur le fait de maintenir les notes pendant une durée précise et de créer une légère séparation entre les accords
  • La fonction choral_rings notes, sus reçoit une liste de notes et une durée de maintien, les joue ensemble avec ring(*notes), calcule sustain et release, puis attend l’événement suivant avec sleep sus

Faire du live coding avec live_loop

  • live_loop permet d’exécuter du code en boucle indéfiniment
  • Sonic Pi est un outil largement conçu pour la performance live, et le code à l’intérieur de live_loop s’exécute jusqu’à l’arrêt du programme
  • On peut modifier le contenu d’une boucle pendant la lecture ; si l’on relance la commande de démarrage, la boucle mise à jour s’applique à partir de l’itération suivante
  • Les anciennes boucles in_thread externes peuvent être remplacées par une forme live_loop :some_unique_name
  • Comme la chaîne d’effets est recréée à chaque tour de boucle, il est moins coûteux en ressources de placer les effets en dehors de live_loop lorsqu’on les accumule
  • L’exemple final est composé de live_loop :harp et live_loop :choir
    • La boucle :harp utilise le synthétiseur :square et un motif d’arpège de longueur 0.25
    • La boucle :choir joue les accords de chœur avec le synthétiseur :saw, sleep 64, with_fx :reverb, mix: 0.75 et des appels à la fonction choral_rings

Voir la programmation comme un acte créatif

  • Le travail technique est généralement discuté du point de vue de l’informatique, mais la programmation peut aussi être un art
  • Elle n’est pas artistique uniquement lorsqu’elle produit intentionnellement des résultats créatifs, comme la génération audio ou les mises en page CSS
  • Le code n’est pas seulement une suite d’instructions optimisées pour la machine, mais aussi un texte organisé lu par d’autres personnes et par notre futur soi
  • Un bon code est un code écrit de façon à être compris d’un coup d’œil par quelqu’un d’autre, ou par soi-même six mois plus tard
  • Parfois, l’art du code devient une fin en soi, et l’exemple de Sonic Pi illustre ce point par la création musicale

1 commentaires

 
GN⁺ 2024-08-11
Avis sur Hacker News
  • Si vous vous intéressez au live coding, Glicol (https://glicol.org) vaut aussi le détour
    Il y a aussi TidalCycles, et la capacité de Haskell comme de Ruby à créer des DSL est vraiment remarquable
    Glicol se concentre sur une syntaxe inspirée des synthétiseurs, la rapidité de composition et la facilité du sound design. L’idée est de concevoir un DSL qui permette de réutiliser ses habitudes de programmation existantes sans rester enfermé dans un langage précis

  • Il y a quelques années, j’ai vu sur YouTube une vidéo de quelqu’un qui recréait le THX Deep Note avec Sonic Pi
    Au début, il n’expliquait pas ce qu’il allait créer ; il fabriquait une seule « note » sonore et l’appelait une abeille. Il ajustait peu à peu ce son d’abeille et le faisait écouter, puis à la fin il disait quelque chose comme : « créons quelques centaines de ces abeilles et voyons ce que ça donne dans une ruche » ; et à ce moment-là, Deep Note apparaissait
    Cette vidéo était vraiment excellente, mais je ne l’ai jamais retrouvée depuis. Si quelqu’un connaît le lien, ce serait sympa de le partager

  • Je pense que c’est l’un des cas où Ruby brille. Grâce à la métaprogrammation, on peut rendre la syntaxe presque semblable à de l’anglais

    • C’est vrai, mais le DSL de Sonic Pi donne plutôt une impression légèrement plus proche de Lisp que du langage naturel
    • C’est bien de la métaprogrammation
  • Il y a quelques années, j’ai vu Sam Aaron, c’est-à-dire le créateur de Sonic Pi, donner une performance live avec Sonic Pi
    À chaque modification du code en temps réel, la musique continuait d’évoluer, et c’était vraiment bon

    • J’ai aussi rencontré Sam. Vers 2008-2010, après une présentation à Clojure Conj, on a dîné ensemble ; déjà à l’époque, c’était quelqu’un de vraiment sympa et sa présentation était excellente
  • Si vous voulez des exemples d’artistes qui utilisent Sonic Pi, j’ai découvert DJ_Dave il y a quelque temps, et je pense que c’est un bon exemple d’une musicienne talentueuse et expérimentée qui exploite bien cet outil
    Elle a aussi fait un AMA sur Reddit auparavant, et il semble qu’il y ait aussi des travaux sur GitHub
    [1] https://www.youtube.com/watch?v=JiQHclg_648
    [2] https://www.reddit.com/r/audius/comments/19dxmy6/hey_audius_...
    [3] https://github.com/algorave-dave

  • En tant que développeur Ruby, je trouve ça vraiment cool. Ça pourrait être amusant pour de la musique générative algorithmique, et j’avais envie de transformer les événements d’un dépôt git bruyant en une forme de musique algorithmique ; ça semble bien adapté
    Mais du point de vue d’un musicien qui possède plusieurs instruments à clavier, si je veux composer un morceau, je peux jouer sur un clavier MIDI ou enregistrer un instrument acoustique puis le boucler ; je ne vois donc pas trop pourquoi je coderais une séquence musicale en Ruby. Je comprends qu’on puisse saisir ce qu’on veut via un DSL Ruby, mais difficile de dire que l’expérience utilisateur soit meilleure qu’avec un clavier de piano
    Autrement dit, je ne pense pas que j’utiliserais ça pour remplacer Logic. C’est bien sûr une préférence personnelle
    Référence : http://listen.hatnote.com/

    • Cela dit, à certains égards, un DSL Ruby exprime l’intention plus clairement qu’une séquence MIDI
      En pratique, il arrive de penser « maintenant un arpège en do mineur, maintenant un arpège en fa majeur », et c’est appréciable de pouvoir composer cette intention très explicitement sous forme de fonction
    • Sonic Pi semble davantage axé sur la musique générée par algorithme, en particulier le live coding, que sur un outil de composition généraliste
      Le point essentiel semble plutôt être de générer par algorithme que de jouer chaque note une par une
      Cela dit, exploiter de manière intéressante un outil qu’on n’utiliserait pas normalement, à cause de contraintes inhabituelles, correspond assez bien aux centres d’intérêt de Hacker News
    • Ça peut convenir à un théoricien de la musique qui manque de coordination et de motricité fine
    • Comme l’article original le laissait entendre, c’est surtout une question de contraintes pratiques
      J’ai un clavier que j’aime bien et, en théorie, je pourrais l’utiliser pour ce travail, mais pour des raisons personnelles compliquées, tous mes instruments sont au garde-meuble pour un moment
  • Il y a quelques jours justement, je pensais à Sonic Pi et j’ai regardé quelques vidéos en ligne
    Je n’avais fait que le tester brièvement il y a quelques années, à l’époque j’avais essayé de reproduire des classiques comme Old MacDonald et Hot Cross Buns

  • Si vous cherchez d’autres approches de la programmation musicale, ce n’est pas du live, mais scamp[0] pour Python vaut aussi le coup d’œil
    Son créateur a publié sur YouTube beaucoup de vidéos de travaux réalisés avec, par exemple la vidéo Fourier Elise[1]
    [0] http://scamp.marcevanstein.com/
    [1] https://www.youtube.com/watch?v=zq32bIud3OM

  • Les commentaires HTML ne semblent pas fonctionner. On dirait que l’éditeur a remplacé les deux traits d’union -- par un seul tiret cadratin

    • Bien vu. En fait, j’ai lancé un rechercher/remplacer un peu trop vite et j’ai laissé passer ce genre de choses à quelques endroits XD
  • Je recommande aussi mon live coder Sonic Pi préféré, alsoknownasrox
    https://www.youtube.com/watch?v=wXIvXrBQFkE