Accueil Floss Manuals francophone

Puredata

Le flot des données

La programmation graphique avec Pure Data est relativement intuitive, mais certaines notions dans la manière dont les informations s'écoulent peuvent parfois dérouter et rendre la compréhension des patchs difficile pour l'œil néophyte. Nous allons donc introduire ici plusieurs particularités relatives au flot des données dans le langage de dataflow qu'offre Pure Data.

Pure Data fonctionne suivant la logique de la « chute d'eau », c'est-à-dire que les données partent du haut pour transiter vers le bas. Les entrées (inlets) sont donc sur le haut des boîtes, les sorties (outlets) sur le bas. Le transit des données est instantané : il n'y a pas de délai entre l'entrée d'une donnée et sa sortie dans la boîte suivante. 

L'ordre des opérations

L'ordre dans lequel les messages entrent et sortent des boîtes est important. L'ordre des opérations dans Pure Data est déterminé par les règles suivantes : 

  1. Entrées chaudes / entrées froides
  2. Ordre des connexions
  3. La priorité du parcours en profondeur des messages

1. Entrées chaudes / entrées froides

Une distinction existe entre l'entrée de gauche et les autres entrées (à droite) d'un objet : l'entrée de gauche est appelée « entrée chaude » parce qu'un envoi de données dans cette entrée entraîne directement le déclenchement de l'opération et la sortie du résultat. L'envoi dans les entrées « froides » de droite, par contre, ne déclenche pas d'action sur l'objet. Cela permet par exemple de stocker des paramètres qui seront utilisés lors du prochain déclenchement de l'objet par l'arrivée de données dans l'entrée chaude (comme un "bang").

hotcold.png

2. Ordre des connexions

Quand un objet effectue une action, et si des messages doivent passer par plusieurs de ses « sorties », ce sera toujours la sortie la plus à droite qui produira un message en premier. Ses autres messages à envoyer le seront de droite à gauche jusqu'à la sortie la plus à gauche.  Plusieurs connexions à une entrée (inlet) ne pose pas de problèmes sauf lorsque l'ordre des opérations est important.  Lorsqu'une sortie a plusieurs connexions, nous ne pouvons pas déterminer l'ordre des opérations.  Pure Data garde une mémoire de l'ordre dans lequel les connexions ont été créés mais ne permet pas de visualiser la priorité d'envoi des messages. L'objet [trigger] permet de contrôler l'ordre d'envoi des informations des sorties de droite à gauche et permet de convertir le type de donnée relayée (voir chapitre : « Quelques objets utiles »).

PureData_DataFlow_triggersimple_en.png

3. La priorité du parcours en profondeur des messages

Dans le cas de plusieurs connexions sortantes depuis un [trigger] ou d'une sortie (outlet) d'un autre objet,  une opération n'est considérée "terminée" que lorsque toutes les suivantes qui appartiennent à la même branche le sont.

Dans cet exemple, suivez le chemin de l'ordre des opérations avec votre doigt. Les règles de l'ordre d'exécution de droite à gauche de l'objet [trigger] et celle du parcours en profondeur s'appliquent. Ici, le résultat des opérations sera toujours le même nombre qu'en entrée.

 PureData_DataFlow_depthfirst0_en.png

Les messages

Dans Pure Data, les objets communiquent les uns avec les autres en utilisant des messages partant généralement de la sortie (ou "outlet") d'un objet vers l'entrée (ou "inlet") d'un autre. Ces messages sont transportés à travers les lignes noires appelées « ficelles ». Ces messages sont généralement des « requêtes » c'est-à-dire qu'ils demandent à l'objet d'opérer une action comme « ouvrir un fichier », de faire un calcul (addition, soustraction, etc.) ou de stocker des données. Mis à part les signaux audio (objet + ~ avec ficelle épaisse) toutes les autres données en Pure Data sont des messages.

Les messages sont composés d’un ou plusieurs éléments de données appelés atomes.

Il existe plusieurs types d'atomes dans Pure Data, mais les plus importants sont les suivants :

  • numériques - des nombres comme "3", "4.5", ou "5.55556e+06"
  • symboliques - en général un mot qui ne peut être interprété comme un nombre, et qui ne contient pas d'espace, par exemple "blablah", "fichier02" ou "reset".

(N.B. : attention utiliser le point à la place de la virgule pour les nombres avec des décimales.)

Les messages commencent par un atome symbolique appelé sélecteur, qui peut être suivi par zéro ou plus d'atomes, appelés éléments du message (tous séparés par des espaces). Hormis deux exceptions bien pratiques expliquées ci-dessous, les messages Pure Data adhèrent à la forme : sélecteur élément1 élément2 élément3 (etc.).

Le sélecteur du message permet à l'objet de savoir ce qu'il doit faire : quand un message arrive à l'une de ses entrées, l'objet vérifie le sélecteur et choisit l'action appropriée (ou méthode). Chaque objet a sa ou ses méthodes particulières. Un objet peut ainsi accepter un message constitué du sélecteur "set" suivi d'un atome numérique, ce qui permettra de sauvegarder cette valeur. Un autre objet peut accepter un message constitué du seul sélecteur "clear" (sans élément) comme méthode permettant « d'oublier » les données actuellement en mémoire. Pour savoir ce qu'un objet accepte comme messages, il suffit de faire un clic-droit sur l'objet et de choisir help depuis le menu contextuel.

Les objets de Pd impriment un message d'erreur dans la console à chaque fois qu'ils reçoivent une commande incomprise. [change] par exemple, n'accepte que les nombres et le symbole "set". Si on lui adresse le message [Nicolas est nerveux<, un message d'erreur nous fera savoir que le sélecteur "Nicolas" n'est pas compris, qu'il n'y a pas de méthode lui correspondant : "error: change: no method for 'Nicolas'." Pour les entrées froides (celles de droite), l'erreur fera référence au sélecteur incorrect : "error: inlet: expected 'float' but got 'Nicolas'."

Types de messages standards

Différentes personnes créent des objets pour Pure Data, les désignant pour accepter des messages dont les sélecteurs sont formatés selon leurs besoins, ce qui rend souvent difficile pour l'utilisateur de savoir quel type de sélecteur l'objet accepte. Heureusement, il existe quelques types de messages standards :

messages-def_3.png

  • message float- le mot "float" (pour "floating point numbers" = « nombre à virgule flottante » - c'est à dire « nombre réel ») avec un élément numérique comme "float -5", par exemple.
  • message symbol - le mot "symbol" suivit par un mot, par exemple "symbol blablah."
  • list - le mot "list" suivit par un groupe de nombres et/ou symboles et/ou pointeurs.
  • bang - le simple mot "bang" utilisé pour envoyer une impulsion.
  • pointer - référence à des données enregistrées dans des structures de données graphiques.

Les messages standards ci-dessus simplifient les opérations communes de Pd. Par exemple, si un objet produit une opération arithmétique simple, on peut facilement en déduire qu'il acceptera des nombres en entrée.

Pour plus de facilité d'écriture, ces messages peuvent la plupart du temps se passer de sélecteur ; les objets les prendront et comprendront leur type de manière « implicite », permettant d'écrire des patchs beaucoup plus rapidement.

Connexions sans ficelle

Il est possible de connecter des composants ensemble et d'envoyer des messages sans utiliser de ficelle : on utilise alors la fonction des objets [send] et [receive] qui vont agir comme émetteurs et récepteurs.

Lors de la création des objets, on ajoute un mot-clé qui sera le nom du fil virtuel reliant l'émetteur et le(s) récepteur(s). Ceci fonctionne sur toute la session Pure Data en cours comme lien entre tous les patchs, les sous-patchs et les abstractions (voir le chapitre Organisation des objets) qui sont ouverts. Il faut donc faire attention au mot-clé employé pour être certain du chemin pris par les données.

Il est également possible de réaliser cette opération en utilisant les propriétés des composants (clic droit, "Properties") et en éditant les champs "send symbol" ou "receive symbol" avec l'étiquette désiré. Ceci supprime l'entrée/sortie concernée, et la remplace par un envoi sans fil. Cette méthode est pratique, mais nécessite plus d'attention lors de la relecture du patch, puisque les sources/destinations ne sont dès lors plus visibles dans la fenêtre.

Un message peut également envoyer ses données sans ficelle, en utilisant une syntaxe spécifique : si un message contient un point-virgule + retour à la ligne, la suite du message est interprétée comme un [send] avec le premier argument comme étiquette et le second comme valeur.  Plusieurs lignes précédées d'un ";" peuvent être combinées pour envoyer des messages à plusieurs [receive] différents.

send-receive_1.png

Le signe $

On veut parfois réserver une place dans les arguments d'un objet ou dans un message pour une valeur qui sera déterminée ultérieurement. Pour cela, on utilise le signe $ (dollar).

Ce signe a un usage différent selon qu'on l'utilise dans un objet ou un message.

dollar_args_in_boxes.png

Dans un message

Une boîte message accepte les variables $n (avec n > 0) et les substitue par la valeur attribuée à l'index de l'atome dans une liste reçue. La substitution est purement locale et correspond uniquement à la liste reçue, contrairement à l'utilisation dans un objet où les $n correspondent à des arguments du patch.

reordonne.png

Dans un objet

De la même manière qu'un objet accepte des arguments, une abstraction peut en accepter pour les utiliser à l'intérieur. Les arguments sont passés dans l'ordre, et sont accessibles par l'usage de $n avec n correspondant à la position de l'argument dans la déclaration de l'abstraction.

Par exemple, cette abstraction multiplie la valeur entrée à droite par les 2 arguments lorsqu'on lui envoie un bang à gauche :

dollarex1.png

Le signe dollar $n utilisé dans un objet fera donc toujours référence aux arguments de l'abstraction à laquelle il appartient, contrairement à l'usage dans les messages.

Alors que  , , etc. représentent le premier, second, etc. argument de l'abstraction, il y en a un spécial qui est très utile dans Pure Data. est une variable qui est remplacée de manière interne par un nombre unique de 4 chiffres propre à chaque patch et instance d'abstraction. En d'autres termes, Pd fait en sorte que chaque instance d'abstraction reçoive un nombre unique mémorisé dans la variable . L'utilité en est démontrée dans l'abstraction suivante, qui utilise des lignes de délais, lesquelles ne peuvent avoir le même nom dans plusieurs instances de la même abstraction, sous peine de conflit.

delay_dollar.png 

Les lignes de délais dans les instances de l'abstraction [localdelay] sont donc nommées ici 1021-dline et 1022-dline.

Bien qu'on appelle souvent une variable construite avec -quelquechose « variable locale », il est tout à fait possible d'y accéder depuis l'espace de variable globale simplement en trouvant par quoi a été remplacé , comme ci-dessus. C'est donc uniquement l'assignation qui est locale, pas la variable construite.