Structures de contrôle du flux

If , elseif, else

Dans un guide traditionnel, vous auriez abordé ces questions au cours de la première heure. J’ai préféré pour ma part vous introduire aux mécaniques les plus suceptibles de vous amener rapidement à créer avant d’aborder des questions plus techniques. Nous allons ici aborder quelques structures du contrôle du flux traditionnelles. Vous allez au début être surpris d’utiliser des conditions, des while loops ou toute autre structure pour faire de la musique. Vous serez ensuite ravis de constater que cela fonctionne très bien, et que cela vous permet de faire beaucoup de choses intéressantes.

Sonic-Pi utilise directement les structures du Ruby. Consulter un guide consacré aux conditions en Ruby vous serait donc tout aussi profitable, et c’est, je le pense, l’un des conseils les plus honnêtes que je puisse vous donner. Je vais ici vous présenter quelques structures que vous pouvez utiliser, à vous ensuite de les tourner à votre avantage.

Les expressions conditionnelles basiques sont très simples :


live_loop :conditions do a = 0 if a == 0 play :c3 elsif a == 1 play :d3 elsif a == 2 play :e3 else play :f3 end sleep 0.5 end

Vous retrouvez ici les traditionnels if / elsif / else présents dans la majorité des langages de programmation. Quelques remarques sur le code ci-dessus. Dans le cas a = 0, une valeur est assignée. = est donc utilisé comme un moyen pour exprimer l’assignation d’un type de donnée à un nom. == est différent : il s’agit d’un comparateur. Ce type de comparateur retourne en interne True ou False, vérifie si une condition est vérifiée ou non. Voici une liste des différents symboles utilisables :

Opérateurs de comparaison :

  • != pour exprimer la différence.
  • < et > pour vérifier deux ordres de grandeur.
  • <= et >= pour vérifier si inférieur ou égal ou supérieur ou égal.
  • <=> renvoie 0 si les deux valeurs sont égales, 1 si le premier opérateur est plus grand, -1 si le premier opérateur est inférieur au second.

if vérifie une condition, elseif n’est lu que dans l’éventualité ou le premier if ne serait pas valide. else exécute une opération dans l’éventualité ou aucune des conditions ne serait vérifiée. Je recommande de toujours d’employer ce dernier dans l’éventualité ou votre code ne répondrait pas aux conditions exprimées en amont. Il vaut mieux avoir une sécurité dans l’éventualité ou vous auriez mal défini vos conditions.

Il est possible d’imbriquer plusieurs conditions les unes dans les autres. Comme pour tout en programmation, il vaut mieux trouver une solution différente si vos conditionnelles sont trop imbriquées. Il doit presque nécessairement exister une manière plus élégante d’exprimer ce que vous cherchez à exprimer.

Par exemple, il est tout à fait possible de vérifier deux conditions du même coup :


a = 0 ; b = 3 if (a == 2 && b == 3) play :c4 else play :d8 end

case

Sam Aaron a été assez clair sur ce point, case n’est pas censé être utilisé avec Sonic-Pi car il n’est pas explicitement supporté. Il est pourtant utilisé en Ruby. Il fonctionne, même si parfois son fonctionnement peut être un peu capricieux. Case est très similaire à if : il vérifie une ou plusieurs conditions. La syntaxe est pourtant différente et conviendra plus spécifiquement à certains types d’utilisation. En voici un exemple, pour choisir dynamiquement quelle partie d’un live_loop jouer :


live_loop :case do ; tick joue = “couplet” case joue when “couplet” play :c2 ; sleep 0.5 play :f2 ; sleep 1 play :g2 ; sleep 1 when “refrain” play :c2 ; sleep 0.5 play :a2 ; sleep 1 play :d2 ; sleep 1 play :g2 ; sleep 1 else play :c2 ; sleep 0.5 play :f2 ; sleep 1 play :g2 ; sleep 1 end end

Vous aurez besoin de déclarer quelle valeur case doit observer avant de décliner les différentes possibilités. Remarquez également la présence d’un else au cas où les choses tourneraient mal pour vous (ici, cela aurait pu être une faute de frappe).

while

While est une autre forme de boucle conditionnelle, qui aura pour fonction de s’exécuter tant qu’une certaine condition ne sera pas remplie. Si cette condition n’est jamais remplie, alors la boucle ne sera jamais rompue. En voici un exemple :


a = 1 while a <= 5 do puts a play :c5 ; sleep 0.25 a += 1 end

Cela peut être utile mais je ne vous recommande pas son usage sauf cas très précis. Il existe d’autres structures de contrôle qui sont bien plus taillées pour une utilisation musicale. Dans certains langages, l’utilisation d’une boucle while sans condition de sortie sert parfois comme mécanisme musical. Puisque nous disposons des live_loops, je pense que nous n’en avons pas besoin.

do do do do do do

Il existe une structure particulière qui permet de répéter x fois une série d’instructions : x.times do. Sa syntaxe est simplissime :


2.times do sample :glitch_perc3 sleep 0.4 end

Je vois difficilement ce que je pourrai vous apprendre de plus sur ce type de structure de contrôle, car il est tout à fait clair et sans détours.

density

Density peut être vu comme un lointain cousin de times do. Son effet est presque similaire à ceci prêt que density est prévu pour conserver le tempo du mieux qu’il peut en multipliant la vitesse d’exécution de chaque itération par un facteur x :


density 2 do sample :perc_door end

Bien utilisé, il peut donner des résultats intéressants sur vos percussions, tout en vous permettant de garder un bon contrôle du flot d’exécution et du tempo. Je l’ai toujours trouvé assez difficile à utiliser, mais je sais que certains en font une utilisation intensive. Cela dépend vraiment de votre manière de coder. J’utilise pour ma part un autre moyen pour parvenir au même effet. Nous verrons cela dans l’article consacré aux modules externes.

at

at est un peu spécial par rapport aux autres opérateurs. Il est pourtant très puissant et peut vous permettre de faire beaucoup de choses. Il exécute un ou une série d’évènements à un moment donné dans le temps à partir du lancement de l’exécution du code. Attention, car toute action exécutée dans un bloc at est considérée comme appartenant à son propre scope. Rien ne peut donc sortir d’un bloc at. Il est préférable que vous étudiez l’exemple suivant pour comprendre le fonctionnement de ce type de structure :


live_loop :at do at [1, 3, 5, 6] do sample :ambi_piano end at [2, 4, 7] do sample :ambi_dark_woosh end sleep 7 end

Vous remarquerez que j’ai toutefois du indiquer la durée totale de mon live_loop à l’aide de sleep. Dans cet exemple, je n’ai indiqué qu’une série de pulsations sur lesquelles exécuter l’action comprise entre la déclaration et la balise de fin end. Je n’en suis pas certain, mais tout laisse à penser que chaque itération d’un live_loop agit comme une réinitialisation du compte des pulsations.

Sonic-Pi est capable de recevoir d’autres arguments au sein d’une déclaration at :


at [1, 3, 6], [:c4, :c5, :g5] do |n| play n end

Vous devez être maintenant familiers avec ce type de déclaration. Nous déclarons notre propre série de paramètres. Il semble qu’il ne soit pas possible de faire passer plus d’un paramètre. Les tick ont une incidence sur le contenu d’un bloc at ce qui devrait vous donner un certain contrôle sur les paramètres qui pourraient se trouver à l’intérieur. .choose fonctionnera également.

Je reviendrais ultérieurement sur at car il y a beaucoup plus à en dire.