Vous êtes sur la page 1sur 169

MUS-1323 - Creation musicale en langage Python

Olivier Belanger
25 septembre 2012

Table des mati`


eres
1 Guide dinstallation
1.1 Installation des ressources essentielles
1.1.1 Installer Python . . . . . . . .
1.1.2 Installer WxPython . . . . . .
1.1.3 Installer pyo . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

2 Introduction au langage de programmation


2.1 Concepts generaux de la programmation . .
2.2 Introduction `
a Python . . . . . . . . . . . .
2.3 Compilation et interpretation . . . . . . . .
2.4 Les differents types derreurs . . . . . . . .
2.5 Noms des variables et mots reserves . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

Python
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .

3 Op
erations, types de variables et flux dinstructions
3.1 Calculer avec Python . . . . . . . . . . . . . . . . . . .
3.2 Typage des variables . . . . . . . . . . . . . . . . . . .
3.3 Principaux types de donnees . . . . . . . . . . . . . . .
3.4 Affectation de valeurs . . . . . . . . . . . . . . . . . .
3.5 Sequence dinstructions et execution conditionnelle . .
3.5.1 Sequence dinstructions . . . . . . . . . . . . .
3.5.2 Selection ou execution conditionnelle . . . . . .
3.6 Operateurs de comparaison . . . . . . . . . . . . . . .
3.7 Instructions composees . . . . . . . . . . . . . . . . . .
3.8 Instructions imbriquees . . . . . . . . . . . . . . . . .
3.9 R`egles de syntaxe . . . . . . . . . . . . . . . . . . . . .
3.10 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . .
3.11 Pratique . . . . . . . . . . . . . . . . . . . . . . . . . .
3.11.1 Premiers pas dans lecriture dun script audio .
3.11.2 Lobjet PyoObject . . . . . . . . . . . . . . . .
3.11.3 Creer une chane de traitement de signal . . . .
3.11.4 Instructions conditionnelles . . . . . . . . . . .
3.11.5 Pages de manuel `
a consulter . . . . . . . . . . .
3.11.6 Comment lire le manuel pyo . . . . . . . . . . .
3.11.7 Exemples et exercices . . . . . . . . . . . . . .
3

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

7
7
7
7
8

.
.
.
.
.

9
9
10
11
12
13

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

15
15
16
17
18
19
19
19
20
21
22
22
23
24
24
25
26
27
28
28
29

`
TABLE DES MATIERES

3.11.8 Solution `
a lexercice de conversion de temperature . . . . . . . . . . . . .
4 Les structures de donn
ees
4.1 Chanes de caract`eres : fonctions propres au type string . . . . .
4.1.1 Operations . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.2 Construction dun string avec le symbole pourcentage (%)
4.1.3 Quelques methodes de la classe string . . . . . . . . . . .
4.1.4 Indicage . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.5 La methode len . . . . . . . . . . . . . . . . . . . . . . . .
4.1.6 String de documentation . . . . . . . . . . . . . . . . . .
4.2 Les listes : Operations sur les listes . . . . . . . . . . . . . . . . .
4.2.1 Quelques operations sur les listes . . . . . . . . . . . . . .
4.3 La fonction range . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.4 Pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.4.1 Contr
ole des objets via les param`etres dinitialisation . .
4.4.2 Lire un fichier son sur le disque dur . . . . . . . . . . . .
4.4.3 Gestion de la polyphonie . . . . . . . . . . . . . . . . . .
4.4.4 Utilisation des listes `
a des fins musicales . . . . . . . . . .
4.4.5 Exemples et exercices . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

5 Boucles et importation de modules


5.1 Importation de modules . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Instructions repetitives (while, for) . . . . . . . . . . . . . . . . . . .
5.2.1 Linstruction while . . . . . . . . . . . . . . . . . . . . . . . .
5.2.2 Linstruction for . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 Generateurs de listes (list comprehension) . . . . . . . . . . . . . .
5.4 Pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4.1 Utilisation de la boucle for pour la generation de param`etres
5.4.2 Les generateurs de listes (list comprehension) . . . . . . . .
5.4.3 Variations continues des param`etres `a laide dobjets pyo . .
5.4.4 Exemples et exercices . . . . . . . . . . . . . . . . . . . . . .
5.4.5 Solutions aux exercices sur les lists comprehension . . . . .
6 Les
6.1
6.2
6.3
6.4
6.5
6.6

fonctions
Fonction simple sans param`etre . . . . . . . . . . . . . . . . .
Fonction avec param`etres . . . . . . . . . . . . . . . . . . . .
Valeurs par defaut des param`etres . . . . . . . . . . . . . . .
Variables locales et variables globales . . . . . . . . . . . . . .
Utilisation des fonctions avec retour de valeur . . . . . . . . .
Pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.6.1 Utilisation des fonctions dans un script . . . . . . . .
6.6.2 Appel automatique dune fonction avec lobjet Pattern
6.6.3 Generation dune sequence composee (objet Score) . .

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

32

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

33
33
33
34
34
36
36
36
37
37
37
38
38
39
40
41
43

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

47
47
48
48
50
51
53
53
56
57
59
62

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

65
65
66
66
67
68
69
69
71
73

`
TABLE DES MATIERES

7 Gestion des r
epertoires et r
evision
7.1 Lire et ecrire des fichiers sous Python . . . . . . . . . . . . . . .
7.1.1 Methodes dun objet fichier . . . . . . . . . . . . . . . . .
7.1.2 Exemple concret decriture et de lecture dun fichier texte.
7.2 Revision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

77
77
77
78
81
83
83
83
85
86
87
87
88
91
95

8 Les Dictionnaires
8.1 Le Tuple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2 Le dictionnaire . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2.1 Operations sur les dictionnaires . . . . . . . . . . . . . . .
8.2.2 Construction dun histogramme `a laide dun dictionnaire
8.3 Gestion des evenements dans le temps par lenvoi de triggers . .
8.3.1 Quest-ce quun trigger ? . . . . . . . . . . . . . . . . . . .
8.3.2 Sequence devenements . . . . . . . . . . . . . . . . . . .
8.4 Creation dalgorithmes musicaux . . . . . . . . . . . . . . . . . .
8.5 Exemple : Petit contrepoint algorithmique `a 2 voix . . . . . . . .

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

9 Classes et m
ethodes
9.1 Introduction au concept de classe et dobjets . .
9.2 Definition dune classe simple et de ses attributs
9.3 Definition dune methode . . . . . . . . . . . . .
9.4 La methode constructeur . . . . . . . . . . . .
9.5 Exemple de classe dans un fichier externe . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

97
. 97
. 98
. 99
. 100
. 104

10 Contr
oleurs externes
10.1 Configuration Midi . . . . . . . . . . . . . . . . .
10.2 Synthetiseur Midi . . . . . . . . . . . . . . . . . .
10.3 Generateur de boucles audio controlable en Midi
10.4 Simili-echantillonneur . . . . . . . . . . . . . . .
10.5 Granulateur simple . . . . . . . . . . . . . . . . .
10.6 Contr
ole du granulateur via le protocole OSC . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

107
107
108
110
111
112
112

11 Cr
eation dinterfaces graphiques I
11.1 Introduction `
a la librairie graphique wxPython . . . . . . . . . . . . . .
11.1.1 La gestion de la boucle dexecution . . . . . . . . . . . . . . . . .
11.1.2 Les conteneurs . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11.1.3 Le contenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11.1.4 Interaction entre linterface et les fonctionnalites du programme .
11.1.5 Deux petites ameliorations . . . . . . . . . . . . . . . . . . . . .
11.2 Selecteur deffets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11.3 Synthetiseur FM avec controle Midi et interface graphique . . . . . . . .

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

115
115
116
116
118
121
126
130
133

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

`
TABLE DES MATIERES

12 Cr
eation dinterfaces graphiques II
12.1 Interface de contr
ole `
a 2 dimensions . . .
12.1.1 Preambule . . . . . . . . . . . . . .
12.1.2 Bouton et Dialogue standard . . .
12.1.3 Surface de contr
ole `
a 2 dimensions

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

137
137
137
140
144

13 Retour sur les principaux concepts


153
ements de langage de la programmation orientee objet en Python . . . . . . . 153
13.1 El
13.2 Principes generaux de la programmation musicale avec le module pyo . . . . . . 154
14 Annexes
14.1 Interaction avec lutilisateur . . . . . . . . . . . . . . . . . . . . . . . . . .
14.1.1 La fonction input . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.1.2 La fonction raw input . . . . . . . . . . . . . . . . . . . . . . . . .
14.2 Gestion des exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.2.1 Interception dune exception (permet au programme de continuer)
14.3 Envois de commandes au syst`eme . . . . . . . . . . . . . . . . . . . . . . .
14.4 Lantis`eche Python (Python Cheat Sheet) . . . . . . . . . . . . . . . . . .
14.4.1 Arithmetique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.2 Assignation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.3 Chane de caract`eres (string) . . . . . . . . . . . . . . . . . . . . .
14.4.4 Lecture et ecriture de fichiers . . . . . . . . . . . . . . . . . . . . .
14.4.5 Print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.6 Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.7 Tuple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.8 Dictionnaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.9 Conditions (if... elif... else) . . . . . . . . . . . . . . . . . . . . . . .
14.4.10 Boucle (for, while) . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.11 List comprehension (fabrication de listes) . . . . . . . . . . . . .
14.4.12 Creation de fonctions . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.13 Creation de classes . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.14 Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.15 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.4.16 Mots cles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

155
155
155
156
156
157
158
159
159
159
159
160
161
161
161
162
162
163
164
165
166
166
168
169

Chapitre 1

Guide dinstallation
1.1

Installation des ressources essentielles

En premier lieu, pyo etant un module Python, une distribution de Python doit etre installee
sur le syst`eme. Ensuite, comme pyo comporte des elements graphiques ecrits avec WxPython,
cette librairie doit aussi etre installee sous la distribution de Python.

1.1.1

Installer Python

Installons dabord la distribution officielle de Python, disponible `a cette adresse :


http ://python.org/download/releases/2.7.3
La version courante de Python est 2.7.3, ce qui est tout `a fait raisonnable.
*** Tr`
es important *** ne pas installer Python 3 !
Installer la version 32-bit de Python (pas la version amd64, peut importe votre processeur),
cest le fichier identifie comme suit :
Windows x86 MSI Installer (2.7.3) pour Windows
Mac OS X 32-bit i386/PPC Installer (2.7.3) pour OSX
Suivez les consignes dinstallation !

1.1.2

Installer WxPython

Comme pyo comporte certains elements dinterface graphique ecrit avec WxPython, il faut
maintenant installer cette librairie. Linstalleur est disponible `a ladresse suivante :
http ://www.wxpython.org/download.php#stable
Telecharger linstalleur 32-bit (unicode) qui correspond `a votre version de Python. Soit,
wxPython2.8-win32-unicode-py27 pour Windows
wxPython2.8-osx-unicode-py27 pour OSX
Suivez les consignes dinstallation !
7

1.1.3

CHAPITRE 1. GUIDE DINSTALLATION

Installer pyo

Sous OS X et Windows, telecharger linstalleur le plus recent de pyo correspondant `a votre


syst`eme et votre version de Python `
a cette adresse :
http ://code.google.com/p/pyo/downloads/list
Windows
Suivez les instructions dinstallation. La librairie pyo sera installee sous la distribution
Python, lapplication E-Pyo (IDE specialement configure pour developper des scripts pyo) sera
installee dans le dossier dapplications et un dossier pyo examples sera depose sur le bureau.
OS X
` linterieur de limage disque (fichier .dmg) se trouve linstalleur de pyo, le dossier dexA
emples (que vous pouvez sauvegarder sur votre disque dur) ainsi que lapplication E-Pyo (IDE
specialement configure pour developper des scripts pyo), que vous devez deposer dans votre
dossier Applications.
Un bundle Python pour TextMate est aussi present dans limage disque. Ce bundle ajoute
des fonctionnalites, propres `
a pyo, `
a la gestion des scripts Python dans TextMate (colorisation
des mots cles, acc`es rapide au manuel et aux exemples, Cmd+R pour executer un script, etc.).
Si TextMate est installe sur votre syst`eme, vous navez qu`a deposer le bundle `a lendroit suivant
(creer les dossiers au besoin) :
/Library/Application

Support/TextMate/Bundles/

Le represente le dossier utilisateur.


Vous etes maintenant pret `
a executer un premier script pyo. Ouvrez un script du dossier
dexemples dans lapplication E-Pyo et appuyez sur Ctrl+R (Cmd+R sous OSX). La fenetre du
serveur audio devrait apparatre.
linux (Debian - Ubuntu)
Sous une distribution linux `
a base Debian telle que Ubuntu, executez les lignes suivantes
dans un terminal pour compiler pyo (en version 32-bit et 64-bit) et ses dependances :
sudo aptg e t i n s t a l l l i b p o r t m i d i dev p o r t a u d i o 1 9 dev l i b s n d f i l e dev
sudo aptg e t i n s t a l l l i b l o dev pythondev s u b v e r s i o n
sudo aptg e t i n s t a l l pythontk pythonimagingtk pythonwxgtk2 . 8
svn c h e c k o u t h t t p : / / pyo . g o o g l e c o d e . com/ svn / trunk / pyoreado n l y
cd pyoreado n l y
sudo sh s c r i p t s / c o m p i l e l i n u x w i t h J a c k . sh

Chapitre 2

Introduction au langage de
programmation Python
2.1

Concepts g
en
eraux de la programmation

Un ordinateur ne fait rien dautre que deffectuer des operations simples sur une sequence
de signaux electriques. Ces signaux ne peuvent prendre que deux etats, un potentiel electrique
minimum ou maximum. On considerera generalement ces signaux comme une suite de nombres
ayant comme valeur 0 ou 1. Un syst`eme numerique ainsi limite `a deux chiffres est appele syst`eme
binaire.
Toute information dun autre type devra donc etre convertit au format binaire pour etre
traitee par lordinateur. Ceci est vrai non seulement pour tous les types de fichiers, tels que
les textes, les images, les sons ou les films, mais aussi pour les differents programmes, cest `
a
dire les sequences dinstructions, quon voudra faire executer par lordinateur afin de traiter des
donnees.
Ces nombres binaires forment une longue suite et sont generalement traites par groupe de
8 (octet), 16, 32 ou 64, selon le syst`eme utilise. Des traducteurs automatiques sont donc
necessaires afin de convertir les instructions constituees de chanes de caract`eres, formant des
mots-cles, en une suite de nombres binaires.
Le traducteur sappellera interpr
eteur ou compilateur, selon la methode utilisee pour
effectuer la conversion. Lensemble de mots-cles, associe `a un ensemble de r`egles bien definies,
constituera le langage de programmation. Les r`egles indiqueront au traducteur comment assembler les directives fournies par les mots-cles afin de composer des instructions comprehensibles
par la machine, cest `
a dire une suite de nombres binaires.
Selon le type dinstructions quil comporte, on dira dun langage quil est de bas niveau (ex :
Assembler) ou de haut niveau (ex : Pascal, Perl, Java, Python, ...). Un langage dit de bas niveau
est constitue dinstructions tr`es elementaires, tr`es proches du langage machine. Le langage de
haut niveau offrira des commandes plus compl`etes et plus puissantes. Une seule commande dans
un langage de haut niveau se traduira par plusieurs instructions elementaires. Ce sera le r
ole de
linterpreteur ou du compilateur de traduire ces instructions en langage machine. Les langages
de haut niveau sont toujours beaucoup plus simples `a apprendre et `a utiliser puisquils prennent
en charge une grande partie du travail de programmation.
9

10

CHAPITRE 2. INTRODUCTION AU LANGAGE DE PROGRAMMATION PYTHON

Diff
erents types de programmation :
Programmation s
equentielle : Toutes les lignes du code source sont evaluees une `a la
suite des autres, de la premi`ere a` la derni`ere. Pour executer de nouveau un bout de code
ou sauter plusieurs lignes, il faut avoir recours `a des instructions telles que GOTO ou
JUMP. Ce type de programmation est tr`es difficile `a lire puisquil part dans toutes les
directions. Csound ressemble en quelque sorte `a de la programmation sequentielle.
Programmation proc
edurale : Est basee sur la paradigme dappel de procedure. Une
procedure, aussi appelee fonction, methode ou routine, consiste en une sequence de commandes `
a accomplir. Il est possible dappeler nimporte quelle procedure `a nimporte quelle
etape du programme. Un des avantages de la programmation procedurale est la possibilite
de reutiliser des bouts de code `
a plusieurs reprises sans avoir `a les reecrire `a chaque fois.
Elle permet aussi la creation de programmes modulaires et structures, plus facile `a lire
que la programmation sequentielle. Les langages Perl, Basic et C sont des exemples de
programmation procedurale.
Programmation orient
ee-objet : La base de ce type de programmation est lobjet. Un
objet est une structure de donnees repondant `a un ensemble de messages. Les donnees
qui decrivent la structure de lobjet sont appeles ses attributs, tandis que la reponse
`a la reception dun message est appelee une m
ethode. Les objets sont definis par des
classes, qui peuvent heriter des attributs et methodes de dautres classes. Ce type de
programmation, plus moderne, est tr`es puissante en ce quelle permet la compartimentation
et la redefinition de tous les elements constituant le programme. Java, C++ et Python
sont des langages de programmation oriente-objet.

2.2

Introduction `
a Python

Python est un langage de programmation jeune, dynamique, gratuit et soutenu par une large
communaute de programmeurs. Il est hautement extensible, cest `a dire que lajout de librairies,
ecrites en Python, C ou C++, est extremement simple. Cest un langage interprete, supportant
lapproche modulaire et orientee objet de la programmation.
Principales caract
eristiques du langage :
Python est multi-plateforme, enti`erement supporte sur les principaux syst`emes dexploitation (Mac OS, Windows, MS-DOS, Unix, etc).
Python est gratuit et open source, il est donc permis dutiliser et de modifier le code
source du logiciel.
Python est efficace pour ecrire de petits programmes de quelques lignes tout comme des
programmes tr`es complexes de plusieurs dizaines de milliers de lignes.
Python offre une syntaxe extremement simplifiee, ainsi que des types de donnees hautement
evolues (listes, dictionnaires et autres), permettant decrire des programmes tr`es compacts,


2.3. COMPILATION ET INTERPRETATION

11

lisibles et performants. Un programme Python est generalement de 3 `a 5 fois plus court


que le programme correspondant ecrit en C.
Python g`ere automatiquement ses ressources (memoires, descripteurs de fichiers). Il nest
donc pas necessaire de tenir des references et de sassurer que les objets inutilises sont bel
et bien detruits.
Les pointeurs nexistent pas en Python, ce qui simplifie grandement lecriture des programmes.
Python est un langage orient
e-objet supportant lheritage multiple et le polymorphisme,
cest `
a dire la reutilisation du meme code avec des types de donnees differents.
Le syst`eme de gestion des exceptions de Python est simple `a utiliser et tr`es efficace.
Python est dynamiquement type. Tout objet manipulable poss`ede un type bien defini quil
nest pas necessaire davoir prealablement declare.
Python est un langage interprete. Les programmes sont compiles en instructions portables,
puis executes par une machine virtuelle.
* Les deux derni`eres caracteristiques impliquent forcement un supplement doperations pour le
processeur afin de faire fonctionner le programme correctement. Ceci se traduit par une vitesse
dexecution plus lente par rapport `
a un langage compile.

2.3

Compilation et interpr
etation

Le programme ecrit par le programmeur constitue le code source de lapplication. Pour


executer ce programme, le code source doit etre traduit en code binaire executable par la machine. Comme il a ete dit precedemment, il existe deux techniques pour effectuer cette traduction : linterpretation et la compilation.
Lorsquun programme est interprete, aucun code objet nest produit. Linterpreteur analyse chaque ligne du programme et la transforme en instructions du langage machine qui sont
immediatement executees.
Code source = Interpreteur = Resultat
La compilation dun programme consiste `a traduire `a lavance tout le code source et `a creer
un code objet, dont le langage est beaucoup plus proche de celui de la machine. Celui-ci devient
un fichier executable en tout temps, sans le besoin de passer `a nouveau par le compilateur.
Code source = Compilateur = Code objet = Executeur = Resultat
Linterpretation est ideale dans un contexte dapprentissage ou de developpement dun programme, car elle permet de tester immediatement les modifications apportees au programme
sans avoir `
a compiler de nouveau le code source. Par contre, comme le langage doit etre traduit
en temps reel par linterpreteur, certaines operations peuvent demander beaucoup de temps et

12

CHAPITRE 2. INTRODUCTION AU LANGAGE DE PROGRAMMATION PYTHON

ne pas etre executees suffisamment rapidement au go


ut du programmeur. Dans ce cas, un programme compile sera toujours loption la plus rapide et efficace, puisque le code objet parle un
langage beaucoup plus proche du langage machine.
Certains langages modernes, tel Python, tentent de faire le pont entre les deux techniques.
Lorsque Python recoit un programme source, il commence par le compiler pour produire un
code intermediaire (bytecode), plus pr`es du langage machine, qui sera transmis `a linterpreteur
pour lexecution. Linterpretation du bytecode est plus rapide que celle du code source.
Code source = Compilateur = Bytecode = Interpreteur = Resultat
Avantages :
Le bytecode est portable, il suffit davoir un interpreteur Python sur la machine pour
executer nimporte quel code.
Linterpretation du bytecode est suffisamment rapide, bien quelle soit plus lente que celle
dun veritable code objet, pour la grande majorite des applications.
Linterpreteur est toujours disponible afin de tester rapidement des petits bouts de programme.

2.4

Les diff
erents types derreurs

Lexecution dun programme est une operation extremement capricieuse. La moindre petite
erreur peut faire arreter lexecution. Trois types derreurs peuvent etre rencontrees lors de la
conception dun programme :
Erreurs de syntaxe : Tous les langages de programmation poss`edent leur syntaxe propre.
Celle-ci est generalement tr`es precise et il est important de respecter les r`egles lors de
lecriture des programmes. La moindre faute de syntaxe, telle une virgule mal placee,
provoquera larret du programme et laffichage dun message derreur. Il est tr`es important
de comprendre la structure des messages derreur, car ceux-ci nous donnent generalement
des pistes tr`es utiles pour corriger lerreur qui a ete commise. Par exemple, Python nous
specifiera si lerreur est une erreur de syntaxe et `a quelle ligne du programme elle a ete
detectee.
Erreurs s
emantiques : Lerreur semantique, ou erreur de logique, se produit lorsque
les instructions specifiees sont valides mais ne correspondent pas `a lidee de depart du
programmeur. Le programme sexecute donc parfaitement, mais le resultat obtenu nest
pas celui qui etait attendu. Ces erreurs sont plus compliquees `a corriger. Il faut faire une
analyse detaillee de toutes les parties du programme pour savoir quel bout de code ne
donne pas le resultat escompte. Il existe plusieurs outils Python pour aider le deboguage,
nous en detaillerons quelques-uns en temps et lieu.
Erreurs `
a lex
ecution : Ces erreurs se produisent principalement lorsquun programme,
fonctionnant normalement, essaie dexecuter une commande qui, pour une raison quelconque, nest plus possible. Par exemple, le programme essaie de lire un fichier qui a ete

2.5. NOMS DES VARIABLES ET MOTS RESERV


ES

13

efface du disque dur, ou il tente dimporter une librairie qui nest pas installee sur le
syst`eme. Ces erreurs se nomment des exceptions, et provoquent larret du programme.
Nous verrons divers moyens de gerer les exceptions, afin de permettre `a notre programme
de continuer `
a rouler meme lorsque cette situation arrive.

2.5

Noms des variables et mots r


eserv
es

Le travail dun programme dordinateur consiste principalement `a manipuler des donnees


afin darriver `
a un certain resultat. Ces donnees sont mises en memoire dans le langage `a laide
de variables. Ces variables peuvent etre de differents types (que nous verrons ulterieurement) et
portent un nom arbitraire, donne par le programmeur. Ces noms doivent etre le plus evocateur
possible, afin de faciliter la lecture du programme. Bien que lon acc`ede `a une variable en
lappelant par son nom, il ne sagit en fait que dune reference designant une adresse memoire,
cest `a dire un emplacement dans la memoire vive de lordinateur. Cet emplacement contient la
valeur reelle donnee `
a la variable sous un format binaire. Nimporte quel objet peut etre place en
memoire, que ce soit un nombre entier, un nombre reel, une chane de caract`eres, une liste, un
dictionnaire ou autre. Afin de distinguer ces differents contenus, le langage de programmation
utilise des types de variables, entier, reel, liste, etc. Ce sujet sera couvert au cours 2.
Les noms donnes aux variables sont laisses au soin du programmeur. Ils doivent par contre
respecter quelques r`egles, voici celles en vigueur dans le langage Python :
1. Un nom de variable peut etre compose de lettres et de chiffres, mais doit toujours commencer par une lettre.
2. Le seul caract`ere special autorise est le souligne ( ). Les lettres accentuees, les cedilles, les
espaces et les caract`eres speciaux tels que #, $, @, etc, sont interdits. La raison est que
ces caract`eres font dej`
a partie de la syntaxe de Python et ont un role particulier `a jouer.
Par exemple, le caract`ere # indique le debut dun commentaire, cest `a dire une ligne qui
ne sera pas executee par le programme.
3. La casse (majuscule et minuscule) est significative. Tempo et tempo sont donc deux variables distinctes !
Par convention, les noms de variables commencent avec une minuscule et nutilisent les
majuscules que pour augmenter la lisibilite du code (ex : listOfScales). Il est tr`es important
quun nom de variable soit le plus evocateur possible, afin de rendre votre code plus lisible pour
autrui.
Dans le langage Python, il y a 32 mots reserves qui ne peuvent etre utilises comme nom de
variable puisquils sont dej`
a utilises par le langage lui-meme et ont chacun une fonctionnalite
propre. Ils sont listes dans le tableau de la page suivante.

14

CHAPITRE 2. INTRODUCTION AU LANGAGE DE PROGRAMMATION PYTHON

and
del
for
is
raise
True

assert
elif
from
lambda
return
False

break
else
global
not
try

class
except
if
or
while

continue
exec
import
pass
yield

def
finally
in
print
None

Chapitre 3

Op
erations, types de variables et flux
dinstructions
3.1

Calculer avec Python

Dans le langage Python, un nombre peut etre exprime sous differents formats. Il peut etre
soit entier, avec une resolution de 32 bits, soit entier long, avec une resolution infinie ou un
nombre reel, souvent appele nombre `a virgule flottante.
Integer : 12, -234, 0, ...
Long integer : 5432345734543L (on ajoute le suffixe L)
Float : 0.005, 13.4654, -4.321, ...
Il faut garder en memoire que la precision dun nombre est dependante de la quantite de bits
utilises pour representer ce nombre. Dans le cas des nombres reels, la valeur utilisee sera presque
toujours une approximation de la valeur demandee. Si vous tapez le nombre 3.23456 dans un
interpreteur Python, voici ce que vous obtenez :
>>> 3 . 2 3 4 5 6
3.2345600000000001

Python est tout de meme un environnement de calcul extremement precis, les nombres
reels etant toujours representes avec 64 bits. On constate que lapproximation est vraiment tr`es
proche de la valeur demandee. Python utilise les operateurs standards pour exprimer les formules
mathematiques :

Multiplication : *
Division : / ( 5/2 = 2, 5/2. = 2.5 )
Addition : +
soustraction : -

Pour quune division retourne un nombre reel, au moins une des deux valeurs doit etre un
nombre reel. Il suffit dajouter un point pour convertir un nombre entier en nombre reel.

15


16 CHAPITRE 3. OPERATIONS,
TYPES DE VARIABLES ET FLUX DINSTRUCTIONS

Deux autres operateurs sont disponibles, lexposant et le modulo.


Exposant : ** ( 2**4 = 16 )
Modulo : %
Loperateur modulo retourne le restant dune division dun nombre par un autre.
>>> 3 % 2
1
>>> 12 % 5
2
>>> 12 % 6
0

Dans lenvironnement Python, lordre de priorite standard est respecte. Il peut etre memoriser
avec lexpression mnemonique PEMDAS (parenth`ese, exposant, multiplication, division, addition, soustraction). Dans le cadre dune expression complexe, les parenth`eses sont toujours
calculees en premier, ensuite ce sont les exposants, puis les multiplications et les divisions, qui
ont le meme ordre de priorite, et enfin les additions et les soustractions. Une simple erreur
dinattention dans lordre des priorites peut entraner des resultats fort differents :
>>> 3 . 1 4 1 5 9 4 2 .
50.26544
>>> ( 3 . 1 4 1 5 9 4 ) 2 .
157.913406496

3.2

Typage des variables

Dans plusieurs langages tels C ou Java, il est obligatoire de declarer les variables que lon
compte utiliser, ainsi que leur type (cest `a dire que le typage est statique), avant de leur assigner
un contenu. Une variable ne peut changer de type en cours dexecution et nacceptera pas une
valeur qui ne correspond pas `
a son type. Voici un exemple en C o`
u lon a deux variables que
lon veut additionner ensembles :
int a = 5;
int b = 7;
int result ;
result = a + b;

Sous Python, le typage des variables est dynamique, cest `a dire que Python se charge
automatiquement dattribuer le type qui correspond le mieux `a toutes les variables specifiees
dans votre programme. La meme operation en Python donnerait :
a = 5
b = 7
result = a + b

Le type entier sera automatiquement attribue aux variables a et b tandis que la variable
result se verra attribuer un type selon le resultat de laddition (dans cet exemple, un entier).


3.3. PRINCIPAUX TYPES DE DONNEES

17

Cette methode est un peu plus lente `a executer, puisque chaque fois que Python rencontre une
variable, il doit determiner son type. Par contre, elle est extremement flexible et permettra de
gerer des structures de donnees hautement sophistiquees telles que les listes et les dictionnaires.
Nous reviendrons plus tard sur ces types de donnees. Ainsi, sous Python, une variable peut tr`es
bien contenir un entier au debut du programme et, en cours de route, devenir une liste ou un
string.

3.3

Principaux types de donn


ees

Le module types, que lon peut importer dans un programme, contient des constantes pour
tous les types possibles en Python. Une constante est une valeur fixe que lon peut utiliser
nimporte o`
u dans un programme. Dans ce cas-ci, on pourrait utiliser les constantes du module
types pour tester des conditions sur le type des variables utilisees. Nous y reviendrons un peu
plus tard. Pour linstant, voyons les principaux types de donnees accessibles sous Python :

NoneType : Type de la valeur nulle None


IntType : Un nombre entier
FloatType : Un nombre reel
LongType : Un nombre entier de type long
StringType : Une chane de caract`eres
TupleType : Une liste entre parenth`ese (1, 2, 3, 4)
ListType : Une liste [1, 2, 3, 4]
DictType : Un dictionnaire
FunctionType : Une fonction
ClassType : Une classe (servant `a creer des objets)
InstanceType : Un objet cree `a partir dune classe
MethodType : Une methode contenue dans une classe
ModuleType : Un module qui a ete importe (fichier contenant des fonctions)
FileType : Un fichier ouvert dans Python avec la fonction open()

La fonction type permet de savoir quel est le type dune variable :


>>> a = 3
>>> ty pe ( a )
<ty pe i n t >
>>> import t y p e s
>>> ty pe ( a ) == t y p e s . IntType
True
>>> l = [ 1 , 2 , 3 , 4 , 5 ]
>>> ty pe ( l )
<ty pe l i s t >
>>> i f type ( l ) == t y p e s . ListType :
...
print I c i s i n s e r e l e s actions sur l e s l i s t e s !
. . . else :
...
p r i n t C e t t e v a r i a b l e n e s t pas une l i s t e
...
I c i s i n s e r e l e s actions sur l e s l i s t e s !


18 CHAPITRE 3. OPERATIONS,
TYPES DE VARIABLES ET FLUX DINSTRUCTIONS

Le type string sous Python poss`ede une syntaxe particuli`ere. Il peut etre delimite par des
guillemets simples ( ) ou des guillemets doubles ( ). Les deux syntaxes sont tout `a fait
equivalentes mais cela permet dintroduire facilement un string dans un string !
>>> C e c i
Ceci e s t
>>> C e c i
Ceci e s t
>>> C e c i
Ceci e s t

3.4

e s t un s t r i n g
un s t r i n g
e s t a u s s i un s t r i n g
a u s s i un s t r i n g
e s t un s t r i n g dans un s t r i n g
un s t r i n g dans un s t r i n g

Affectation de valeurs

Lassignation dune valeur `


a une variable seffectue avec le symbole =. Il ne sagit en aucun
cas dune egalite dans le sens mathematique du terme. Cela veut simplement dire que nous avons
depose le contenu x dans la variable y. Le nom de la variable represente un espace memoire dans
lordinateur o`
u est enregistre en format binaire la valeur affectee. Pour tester la relation degalite
entre deux variables, on utilise le symbole ==, qui fait partie dun groupe de symboles appeles
op
erateurs de comparaison, nous y reviendrons.
n = 10

Lorsque nous assignons une valeur `a une variable, comme dans lexemple ci-dessus, cette
instruction a pour effet de realiser plusieurs operations dans la memoire de lordinateur :
1. Creer et memoriser un nom de variable
2. Lui attribuer un type bien determine
3. Creer et memoriser une valeur particuli`ere `a lendroit assigne

4. Etablir
un lien (par un syst`eme interne de pointeurs) entre le nom de la variable et lespace
memoire de la valeur
Affectations multiples
Sous Python, on peut assigner la meme valeur `a plusieurs variables en meme temps :
a = b = c = 1

Trois variables, a, b et c, ont ete creees et poss`edent toutes la valeur 1.


Affectations parall`
eles
On peut aussi affecter plusieurs valeurs `a plusieurs variables en meme temps :
a, b = 0, 1

La valeur 0 a ete affectee `


a la variable a tandis que la valeur 1 a ete affectee `a la variable b.

3.5. SEQUENCE
DINSTRUCTIONS ET EXECUTION
CONDITIONNELLE

3.5
3.5.1

19

S
equence dinstructions et ex
ecution conditionnelle
S
equence dinstructions

Un programme informatique est toujours une serie dactions `a effectuer dans un certain ordre.
La structure de ces actions et lordre dexecution constituent un algorithme. Les structures de
controle sont des instructions qui determinent lordre dans lequel les actions seront effectuees. Il
existe trois types de structures : la s
equence, la s
election et la r
ep
etition. Nous elaborerons
sur la repetition au prochain cours.
Si votre programme ne contient pas dinstructions de s
election ou de r
ep
etition, les lignes
seront executees dans lordre, de la premi`ere `a la derni`ere. Lorsque Python rencontre une instruction conditionnelle, par exemple linstruction if, il pourra prendre differents chemins selon
le resultat de la condition.

3.5.2

S
election ou ex
ecution conditionnelle

Lexecution dun programme complexe sera influencee en cours de route par differents facteurs, tels que les reponses fournies par lutilisateur `a certaines questions ou letat de certaines
variables du programme. Cest avec des instructions conditionnelles, placees `a des endroits precis,
que lon specifie au programme de prendre tel ou tel chemin selon letat des donnees. Une instruction conditionnelle commence la ligne avec le mot cle if et la termine avec le symbole deux-points
:. Ce symbole marque le debut dune sequence de controle qui peut etre une condition, une
boucle, la definition dune fonction ou dune classe, etc. La ligne qui vient ensuite doit etre
indentee pour specifier `
a Python que cette instruction ne doit etre executee que dans certaines
circonstances.
Par convention, lindentation correspond `a 4 espaces vides laisses au debut de la ligne. Faites
attention, la touche de tabulation, selon lediteur que vous utilisez, gen`ere soit un caract`ere tab
(generalement equivalent `
a 4 espaces vides), soit 4 caract`eres despacement. Ces deux types de
caract`eres ne sont pas encodes de la meme facon par le langage et peuvent creer des conflits
puisque Python ne considerera pas les lignes au meme niveau dindentation, meme si visuellement
tout parait impeccable. La plupart des editeurs intelligents poss`edent loptions de remplacer
automatiquement les caract`eres tab par 4 espaces vides.
Voici une instruction if simple, notez le changement de prompt (invite de commandes) de
linterpreteur Python au debut de la ligne !
>>> a = 1
>>> i f a == 1 :
...
p r i n t a vaut 1
...
a vaut 1

Les trois points, que lon appelle prompt secondaire signifient que nous entrons dans un bloc
dinstructions que nous devons indenter. Comme la condition sest averee vrai, la ligne suivant
celle du if a ete executee et linterpreteur a affiche a vaut 1. Si la condition setait averee fausse,
cette ligne naurait tout simplement pas ete executee.


20 CHAPITRE 3. OPERATIONS,
TYPES DE VARIABLES ET FLUX DINSTRUCTIONS

Il est possible de specifier un autre chemin, avec linstruction else, pour le cas o`
u une condition serait fausse :
>>> a = 0
>>> i f a == 1 :
...
p r i n t a vaut 1
. . . else :
...
p r i n t a ne vaut pas 1
...
a ne vaut pas 1

Notez bien les deux-points apr`es les instructions if et else pour signifier lentree dans un
bloc dinstructions `
a indenter. Notre programme definit maintenant deux chemins possibles en
fonction de letat de la variable a au moment dexecuter ces lignes. Linstruction elif permet
de complexifier une condition et de definir plusieurs actions differentes en fonction de plusieurs
conditions :
>>> a = 0
>>> i f a > 0 :
...
print a
. . . e l i f a < 0:
...
print a
. . . else :
...
print a
...
a est ni p o s i t i f

est p o s i t i f
est negatif
e s t n i p o s i t i f n i n e g a t i f , a vaut donc 0
n i n e g a t i f , a vaut donc 0

Une condition peut contenir autant de elif que necessaire, mais une seule instruction if et
une seule instruction else.

3.6

Op
erateurs de comparaison

Les operateurs de comparaison servent `a tester la relation entre les differentes variables dun
programme. Selon le resultat obtenu, on peut decider de faire bifurquer le flux dinstructions
pour operer dune certaine facon plut
ot que dune autre. Les differents operateurs de comparaison
sont :
==

egalite

!=

inegalite

<

plus petit que

>

plus grand que

<=

plus petit ou egal

>=

plus grand ou egal


3.7. INSTRUCTIONS COMPOSEES

21

Exemples :
a = 10
i f a <= 1 0 :
p r i n t a e s t p l u s p e t i t ou e g a l a 10
e l i f a > 10:
p r i n t a e s t p l u s grand que 10
else :
p r i n t S i un j o u r vous o b t e n e z c e t t e r e p o n s e , f a i t e s l e moi s a v o i r !

Plus tard dans la session, avec les connaissances que vous aurez acquises, reprenez ce script
et essayez dobtenir la reponse suivant linstruction else !
a = 7
i f ( a % 2)
print
print
else :
print

== 0 :
a e s t un nombre p a i r
p a r c e que l e r e s t a n t de s a d i v i s i o n par 2 e s t 0
a e s t un nombre i m p a i r

Notez bien le signe ( == ) pour tester legalite entre deux valeurs. Le signe egal seul ( =
) est utilise pour laffectation dune valeur `a une variable.

3.7

Instructions compos
ees

Le dernier exemple sur les operateurs de comparaison constitue un premier bloc dinstructions, ou instructions composees. Sous Python, il y a deux r`egles essentielles `a respecter pour
construire un bloc dinstructions :
1. La ligne qui annonce le bloc, len-t
ete, se termine toujours par un double point.
Les mots-cle suivants annonce un bloc dinstructions : if, elif, else, for, while, def, class,
with, try, except.
2. Les lignes qui constituent le bloc dinstructions doivent
etre indent
ees exactement au m
eme niveau (compter 4 espaces vides).
a = 5
i f a > 0:
print
print
else :
print
print
print

# l i g n e d ent e t e
a est p o s i t i f
c a r i l e s t p l u s grand que 0
a est soit negatif
s o i t nul
c a r i l peut e t r e p l u s p e t i t ou e g a l a 0

Toutes les lignes dun bloc dinstructions doivent absolument etre au meme niveau dindentation. On appelle ces instructions un bloc logique, car chacune delle ne sera toujours executee
que si la condition le permet. Quoiquil advienne, elle subiront toujours le meme sort.
Petit rappel : noubliez pas que Python nencode pas de la meme facon un caract`ere de
tabulation et un caract`ere despacement !


22 CHAPITRE 3. OPERATIONS,
TYPES DE VARIABLES ET FLUX DINSTRUCTIONS

3.8

Instructions imbriqu
ees

Afin de realiser des structures decisionnelles complexes, vous aurez probablement `a imbriquer
les unes dans les autres plusieurs instructions composees.
i f a >= 0 :
i f ( a % 2 ) == 0 :
i f a < 100:
p r i n t a e s t une v a l e u r
else :
p r i n t a e s t une v a l e u r
a = a % 100
else :
i f a < 100:
p r i n t a e s t une v a l e u r
a = a + 1
else :
p r i n t a e s t une v a l e u r
a = ( a % 100) + 1
else :
print a est negatif
a = 0

p a i r e n t r e 0 e t 100
p a i r p l u s grande que 100

i m p a i r e n t r e 0 e t 100

i m p a i r p l u s grande que 100

- Quelles sont les valeurs possibles pour la variable a `a la sortie de ce bloc dinstructions
imbriquees ?

3.9

R`
egles de syntaxe

Sous Python, cest la mise en page de votre programme qui definit les limites des blocs
dinstructions. Cette r`egle, en plus de simplifier grandement la syntaxe, oblige le programmeur
`a ecrire du code propre, facile `
a lire pour quelquun qui nen est pas lauteur. Certains langages
tels que le C ou le Java utilisent des symboles pour delimiter les blocs, generalement des
accolades. Ceci permet de ne pas se soucier de lindentation du programme et gen`ere souvent
du code pratiquement illisible, hormis pour le programmeur qui la ecrit. En Python, ce sont
les niveaux dindentation qui delimitent les blocs constituants les conditions, les boucles, les
fonctions et autres instructions composees.
# Bloc 1
....
l i g n e d ent e t e :
# Bloc 2
....
l i g n e d ent e t e :
# Bloc 3
....
# Bloc 2 ( s u i t e )
....
# Bloc 1 ( s u i t e )
....

En Python, une ligne dinstruction se termine avec le retour de chariot (ce qui evite lemploi du point-virgule, rencontre dans de nombreux langages !). Nous verrons plus loin comment

3.10. EXERCICE

23

etendre une instruction sur plusieurs lignes. Il est aussi possible de terminer une ligne avec un
commentaire. Un commentaire est tout ce qui se trouve entre le symbole di`ese ( # ) et le retour
de chariot. Ce texte sert de guide ou dexplication sur les differentes parties du programme et
sera compl`etement ignore par linterpreteur lors de lexecution.
Il est tr`es important de bien commenter le programme `a toutes les etapes de la construction,
afin de vous y retrouver quelques annees plus tard quand vous aurez `a reorganiser votre code.
Les commentaires sont des guides tr`es precieux pour un programmeur qui, nayant pas participe
au developpement, voudrait apporter sa touche au programme. Il doit pouvoir comprendre
rapidement quelles sont les directions que prend le flux dinstructions.
` noter : Un bon commentaire nest pas celui qui dit comment cest fait... mais plutot celui
A
qui dit pourquoi cest fait ! Nous aurons loccasion den rediscuter.

3.10

Exercice

Calcul et condition
Sachant que la conversion de temperature seffectue comme suit :
C `a F > on multiplie par 9, ensuite on divise par 5, puis on ajoute 32
F `a C > on soustraie 32, ensuite on multiplie par 5, puis on divise par 9
1. Assigner une valeur en Fahrenheit `a une variable f.
2. Ensuite, effectuer une conversion de Fahrenheit `a Celcius, assigner le resultat `a une variable
c et afficher la temperature en Celcius.
3. Puis, construire un bloc dinstructions conditionnelles qui affichera lune des phrases suivantes, selon la temperature en Celcius :
Surement de la glace.
En etat debulition.
Cette eau est ni trop chaude ni trop froide.
Attention, la precision mathematique est de rigueur ainsi que le respect de la syntaxe des
phrases `a afficher. De plus, votre script doit fonctionner impeccablement dans tous les cas de
figure. Testez-le bien !
Tentez de realiser lexercice avant de consulter la solution en page 32.


24 CHAPITRE 3. OPERATIONS,
TYPES DE VARIABLES ET FLUX DINSTRUCTIONS

3.11

Pratique

3.11.1

Premiers pas dans l


ecriture dun script audio

Tout script desirant utiliser les fonctionnalites de la librairie pyo doit dabord importer le
module. Nous reviendrons plus loin sur les differentes facons dimporter un module, pour linstant
nous allons utiliser la ligne suivante pour avoir un acc`es direct `a toutes les classes et fonctions
presentent dans la librairie. Letoile signifie tous les elements !
from pyo import

Autre etape indispensable : Creer un serveur audio. Le serveur assure la communication


audio avec la carte de son et cest aussi lui qui g`ere lhorloge, cest-`a-dire le defilement des
echantillons dans le temps. Un moteur audio fonctionne toujours par groupe dechantillons,
cest-`a-dire quil calcul tout un bloc dechantillons pour un objet donne avant de calculer le bloc
de lobjet suivant. La longueur de ce bloc est appele buffer size. Le buffer size aura une incidence
sur la charge en CPU ainsi que sur la latence du syst`eme, cest-`a-dire le delai induit par le calcul
des blocs dechantillons. Dans un premier temps, nous fonctionnerons avec les valeurs par defaut
du serveur, que nous initialiserons comme suit :
s = S e r v e r ( ) . boot ( )

Lobjet Server sans param`etre utilisera les valeurs definies par defaut. La methode boot, nous
detaillerons les classes et methodes plus loin, indique au serveur dinitialiser la communication
audio. Lhorloge du serveur nest pas encore demarree mais il est maintenant pret `a accueillir
des objets qui effectuent des processus sur le son. Il est essentiel quun serveur existe avant de
creer des objets pyo !
` partir du moment o`
A
u un serveur est active, tous les objets pyo qui seront crees seront
automatiquement comptabilises par le serveur, qui calculera les blocs dechantillons selon lordre
de creation des objets. Cest ici que nous pouvons definir notre chane de traitement de signal.
Commencons par lexemple classique, une onde sinusodale `a 1000 Hertz :
a = S i n e ( ) . out ( )

Nous reviendrons dans quelques instants sur les notions de base des objets audio !
Nous avons maintenant un serveur pret `a calculer un signal, il ne reste qu`a demarrer le
serveur. Nous utiliserons linterface graphique incluse dans lobjet Server pour faciliter cette
tache. On appelle cette interface avec la methode gui :
s . gui ( l o c a l s () )

`
Nous verrons en temps et lieu lutilite dajouter locals() `a linterieur des parenth`eses. A
lexecution du script, cette ligne provoquera laffichage de la fenetre offrant des controles de base
sur le serveur, tel que le depart et larret de lhorloge, un bouton denregistrement sur le disque
dur et un contr
ole du volume global.

3.11. PRATIQUE

25

Notre premier script ressemblera donc `a ceci :


1
2
3
4

from pyo import


s = S e r v e r ( ) . boot ( )
a = S i n e ( ) . out ( )
s . gui ( l o c a l s () )

scripts/chapitre 03/01 play sine.py

3.11.2

Lobjet PyoObject

Lobjet PyoObject est `


a la base (classe parente) de presque tous les objets disponibles dans
la librairie. Les fonctionnalites de cet objet peuvent donc etre appliquees `a tous les objets qui
en decoulent (classe enfant). Plus tard, nous explorerons plus en detail lheritage de classe. Pour
linstant, considerons que tout objet, si sa page de manuel contient la ligne suivante,
Parentclass : PyoObject
a acc`es aux fonctionnalites de cette classe.
M
ethodes
Quelques methodes qui sappliques `a la majorite des objets de la libraire :
` noter
obj.play() : La methode play demarre le calcul des echantillons de lobjet donne. A
que play nenvoie pas de son `
a la sortie audio.
obj.stop() : La methode stop arrete le calcul des echantillons de lobjet donne. Elle permet
deconomiser du CPU si lobjet ne sert pas durant une certaine periode.
obj.out() : La methode out demarre le calcul des echantillons de lobjet donne et indique
aussi que le signal genere par lobjet doit etre achemine `a la sortie audio. Si un nombre
entier est donne entre les parenth`eses de la methode, il indique le canal de sortie, en
commencant `
a 0. Dans un syst`eme stereo, 0 indique le canal de gauche et 1 indique le
canal de droite.


26 CHAPITRE 3. OPERATIONS,
TYPES DE VARIABLES ET FLUX DINSTRUCTIONS

obj.ctrl() : La methode ctrl affiche une fenetre o`


u des potentiom`etres sont assignes aux
param`etres de contr
ole de lobjet donne. Cette fenetre nous permettra, dans un premier
temps, dexplorer rapidement limpact des param`etres sur le signal sonore genere.
Dans le script precedent, inserer
a . ctrl ()

juste apr`es linitialisation de lobjet a, affichera la fenetre suivante :

3.11.3

Cr
eer une chane de traitement de signal

Tous les objets servant `


a modifier le signal (ex. : filtres et effets) ont un premier param`etre
qui sappelle input. Un objet de type PyoObject doit absolument etre donne `a ce param`etre.
Lobjet modificateur recuperera le signal de lobjet en input et lui appliquera un algorithme de
transformation afin de genere son propre signal audio. Ce signal pourra etre envoye `a la sortie
audio, ou bien `
a un autre objet de transformation. Exemple :
1
2
3
4
5
6
7
8
9

from pyo import


s = S e r v e r ( ) . boot ( )
fm = FM( )
fm . c t r l ( )
f i l t = Tone ( fm ) . out ( )
f i l t . ctrl ()
harmo = Harmonizer ( f i l t ) . out ( 1 )
harmo . c t r l ( )
s . gui ( l o c a l s () )

scripts/chapitre 03/02 dsp chain.py


Objets `
a explorer :
G
en
erateurs : Sine, FM, SineLoop, LFO, Rossler
Filtres : Tone
Effets : Chorus, Disto, Freeverb, Harmonizer, FreqShift
Creer diverses chanes de traitement, constituees dun generateur suivi dun ou plusieurs
effets, et explorer avec les potentiom`etres afin de vous familiariser avec le syst`eme et les sonorites.
Attention aux volumes !

3.11. PRATIQUE

3.11.4

27

Instructions conditionnelles

Il est courant dutiliser une instruction conditionnelle dans le but dorienter un programme
dans une direction particuli`ere en modifiant seulement une variable. Par exemple, au lieu de
modifier le programme `
a chaque nouvelle source que lon veut explorer, on peut creer une
instruction conditionnelle o`
u chacune des sources correspondra `a une condition particuli`ere. Les
conditions seront effectuees sur des nombres entiers :
src = 1
i f s r c == 0 :
s o u r c e = S i n e ( ) . out ( )
e l i f s r c == 1 :
s o u r c e = FM( ) . out ( )
e l i f s r c == 2 :
s o u r c e = SineLoop ( ) . out ( )
source . c t r l ()

Selon la valeur que lon donne `


a la variable src avant dexecuter le script, la variable source
representera une onde sinusodale, une modulation de frequence ou une onde sinusodale bouclee.
Si on applique le meme principe aux effets, on obtient :
1
2

from pyo import


s = S e r v e r ( ) . boot ( )

3
4
5

src = 1
fx = 0

6
7
8
9
10
11
12

i f s r c == 0 :
s o u r c e = S i n e ( ) . out ( )
e l i f s r c == 1 :
s o u r c e = FM( ) . out ( )
e l i f s r c == 2 :
s o u r c e = SineLoop ( ) . out ( )

13
14

source . c t r l ()

15
16
17
18
19
20
21

i f f x == 0 :
e f f e t = Chorus ( s o u r c e ) . out ( 1 )
e l i f f x == 1 :
e f f e t = Harmonizer ( s o u r c e ) . out ( 1 )
e l i f f x == 2 :
e f f e t = D i s t o ( s o u r c e ) . out ( 1 )

22
23

e f f e t . ctrl ()

24
25

s . gui ( l o c a l s () )

scripts/chapitre 03/03 conditions.py


28 CHAPITRE 3. OPERATIONS,
TYPES DE VARIABLES ET FLUX DINSTRUCTIONS

3.11.5

Pages de manuel `
a consulter
Server
SineLoop
Disto

3.11.6

PyoObject
LFO
Freeverb

Sine
Tone
Harmonizer

FM
Chorus
FreqShift

Comment lire le manuel pyo

Les page du manuel sont separes par objet. Chaque page peut contenir jusqu`a 7 sections.
Voici une description sommaire de chaque section :
Section Titre
La premi`ere ligne suivant le nom de lobjet est toujours la ligne dintitialisation, cest-`a-dire
le moment o`
u lon cree un objet que lon assigne `a une variable. On y retrouve les param`etres
regissant le comportement de lobjet ainsi que leur valeur par defaut, sil y a lieu. Ensuite vient
une description du processus effectue par lobjet, puis sa classe parente, sil y a lieu. Si lobjet
poss`ede une classe parente, toutes les fonctionnalites de celle-ci sappliquent `a lobjet courant.
Section Param`
etres
Description detaillee de chacun des param`etres de lobjet. Suivant le nom du param`etre, il
y a toujours les types possibles pour ce dernier (ex : PyoObject, float, string, etc.). Il est tr`es
important de respecter les types permis pour un param`etre. Sil ny a pas la mention optional,
cela signifie quil est obligatoire de fournir une valeur au param`etre. Le param`etre input des
objets qui transforment le signal (les effets) en est un bon exemple, lobjet attend un signal `
a
transformer !
Param`etre obligatoire dont le seul type permis est le PyoObject :
i n p u t : PyoObject
I n put s i g n a l .

Param`etre optionnel acceptant les nombres reels (float) ou les PyoObject. Si le param`etre nest
pas specifie, la valeur -7.0 sera utilisee :
t r a n s p o : f l o a t o r PyoObject , o p t i o n a l
T r a n s p o s i t i o n f a c t o r i n s e m i t o n e . D e f a u l t s t o 7.0.

Section M
ethodes
Ici sont listees toutes les methodes permises sur un objet (auxquelles il faut bien sur ajouter
les methodes de la classe parente !).
a = Harmonizer ( i n p u t ) . out ( )
a . setTranspo (5)

a.setTranspo(5) remplace la valeur de transposition actuelle de lobjet et lui assigne 5.0.

3.11. PRATIQUE

29

Section Attributs
Donne la liste des attributs dun objet (en plus des attributs de la classe parente). Un attribut
peut etre appele directement sur un objet sans passer par la methode associee. Nous reviendrons
plus tard sur lutilisation des methodes et des attributs.
Lexemple suivant effectue la meme operation que lexemple precedent.
a = Harmonizer ( i n p u t ) . out ( )
a . transpo = 5

Section Exemple
Cette section fournit un exemple dutilisation de lobjet dans un processus simple. Le script
peut etre appele en ligne de commande comme suit :
>>> from pyo import
>>> example ( Harmonizer )

Nhesitez pas `
a vous en inspirer !
Section Notes
Si lobjet comporte certaines particularites qui lui sont propres, elles seront detaillees dans
cette section. Par exemple, cest ici que sera specifie si un objet ne poss`ede pas de methode out
(les signaux que lon ne veut surtout pas envoyer dans les haut-parleurs) ou les attributs mul et
add.
Section D
etail des m
ethodes
Reprend les sections Titre et Param`etres pour chacune des methodes de lobjet.

3.11.7

Exemples et exercices

Tous les exercices proposes dans ces pages ont pour but de vous guider dans lelaboration
dune librairie personnelle de processus sonores que vous utiliserez lors de la realisation des
travaux. Il est donc tr`es important de suivre les etapes consciencieusement, afin de bien maitriser
les differentes techniques, et de conserver tous vos essais. Vous devrez reguli`erement reprendre
ces bouts de code pour les etoffer.
La seule et unique recette efficace pour lapprentissage dun langage de programmation est la
pratique. Prendre le temps necessaire pour comprendre et assimiler ces exercices simples fera
en sorte que la realisation de processus plus compliques (et de ce fait, plus interessant !) vous
semblera beaucoup plus aisee.


30 CHAPITRE 3. OPERATIONS,
TYPES DE VARIABLES ET FLUX DINSTRUCTIONS

Exploration de sonorit
es `
a partir de sources
el
ementaires de synth`
ese.
Exercices :
En utilisant les objets proposes precedemment (generateurs, filtres et effets de la page Premier pas), explorer diverses chanes de traitement de votre composition.
1. Vous pouvez creer autant dobjets que necessaires, cest-`a-dire plusieurs sources et/ou
plusieurs effets connectes en cascade ou en parall`ele.
2. Utilisez les valeurs par defaut pour linitialisation des objets. Le seul argument `a specifier
est linput audio pour les effets. Vous pouvez aussi specifier un canal de sortie `a la methode
out(). Exemple, out(1) pour acheminer le signal vers le haut-parleur de droite.
3. Affichez la fenetre de contr
ole (avec la methode ctrl()) pour varier la valeur des differents
param`etres.
4. Attention au volume ! Le comportement par defaut des objets est de jouer `a pleine puissance. Pour linstant, nous allons simplement reduire le volume du serveur, qui agit sur le
signal final. Observez comment lexemple suivant initialise le serveur `a une amplitude de
-20 dB !
5. Vous etes libre de garder toutes vos experimentations dans un seul script et de naviguer
dune `
a lautre `
a laide dune condition (comme dans lexemple suivant) ou de travailler
sur des fichiers independants, cest selon votre aisance.
Exemples :
Le script suivant propose trois chanes de traitement avec des schemas de connexion differents.
Le premier exemple est constitue dune source et de deux effets connectes en cascade o`
u lon
ecoute que le resultat final. Le deuxi`eme propose une source connectee en parall`ele `a deux effets
(chacun des effets est achemine vers un haut-parleur) et le dernier est bati avec trois sources
additionnees en entree dun seul effet.

3.11. PRATIQUE

1
2
3
4
5

31

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

Exemples de c h a i n e s de t r a i t e m e n t . Aucun p a r a m e t r e s a l i n i t i a l i s a t i o n .
E x p l o r a t i o n avec l a f e n e t r e c t r l .

6
7
8

Exemple no 1 : C o n n e c t i o n s en c a s c a d e :
s i n e > d i s t o > c h o r u s

9
10
11
12

Exemple no 2 : C o n n e c t i o n s en p a r a l l e l e ( multi e f f e t s ) :
s i n e l o o p > f r e q s h i f t
> f r e q s h i f t

13
14
15
16
17

Exemple
lfo
lfo
lfo

no
1
2
3

3 : C o n n e c t i o n s en p a r a l l e l e ( multi s o u r c e s ) :
>
> h a r m o n i z e r
>

18
19
20

from pyo import

21
22
23

s = S e r v e r ( a u d i o= p o r t a u d i o ) . boot ( )
s . amp = . 1 # i n i t i a l i s e l e s e r v e u r a 20 dB

24
25

exemple = 1 # m o d i f i e r c e t t e v a r i a b l e pour c h a n g e r d exemple

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

i f exemple == 1 :
src = Sine ()
src . ctrl ()
d i s t = Disto ( src )
dist . ctrl ()
c h o r = Chorus ( d i s t ) . out ( )
chor . c t r l ( )
e l i f exemple == 2 :
s r c = SineLoop ( )
src . ctrl ()
f s h i f = F r e q S h i f t ( s r c ) . out ( )
f s h i f . ctrl ()
f s h i f 2 = F r e q S h i f t ( s r c ) . out ( 1 )
fshif2 . ctrl ()
e l i f exemple == 3 :
s r c 1 = LFO( ) . out ( )
src1 . c t r l ()
s r c 2 = LFO( ) . out ( )
src2 . c t r l ()
s r c 3 = LFO( ) . out ( )
src3 . c t r l ()
harm = Harmonizer ( s r c 1+s r c 2+s r c 3 ) . out ( 1 )
harm . c t r l ( )

50
51

s . gui ( l o c a l s () )

scripts/chapitre 03/04 examples.py


32 CHAPITRE 3. OPERATIONS,
TYPES DE VARIABLES ET FLUX DINSTRUCTIONS

3.11.8
1

Solution `
a lexercice de conversion de temp
erature

f = 500

2
3

c = ( f 32) 5 . / 9

4
5

print c

6
7
8
9
10
11
12

i f c <= 0 :
p r i n t Surement de l a g l a c e
e l i f c >= 1 0 0 :
p r i n t En e t a t d e b u l i t i o n
else :
p r i n t C e t t e eau e s t n i t r o p chaude n i t r o p f r o i d e

scripts/chapitre 03/05 exercice.py

Chapitre 4

Les structures de donn


ees
4.1

Chanes de caract`
eres : fonctions propres au type string

Un string est une constante, cest `a dire quil est immuable (il ne peut etre modifie). Pour
modifier un string il faut obligatoirement en creer un nouveau. Il peut etre delimite soit par des
guillemets simples (), soit par des guillemets doubles ().
s 1 = C e c i e s t un s t r i n g
s 2 = C e c i e s t a u s s i un s t r i n g

Les guillemets simples et doubles sont equivalents, mais peuvent servir `a introduire un string
dans un string, comme dans lexemple ci-dessous :
>>> p r i n t C e c i e s t un s t r i n g dans un s t r i n g
C e c i e s t un s t r i n g dans un s t r i n g

4.1.1

Op
erations

Comme pour laffectation dun nombre, laffectation dun string `a une variable seffectue avec
le symbole egal ( = ) :
s t r = C e c i e s t un s t r i n g

La concatenation de deux strings, pour creer un seul string contenant les deux elements,
seffectue avec le symbole plus ( + ) :
>>> s t r = H e l l o + world !
>>> s t r
H e l l o world !

On peut creer un string qui contient plusieurs repetitions dun autre string avec le symbole
etoile ( * ) :
>>> s t r = a l l o 3
>>> s t r
alloalloallo

33


CHAPITRE 4. LES STRUCTURES DE DONNEES

34

4.1.2

Construction dun string avec le symbole pourcentage (%)

Si le symbole % apparat dans un string suivi dune des lettres d, f, s, e, x, cela indique
que lon veut remplacer ce symbole par une variable de notre script. Il faudra donc faire suivre
le string dun autre symbole %, puis de la variable ou des variables que lon desire introduire
dans le string. Si plus dune variable doivent etre specifiees, il faut les placer entre parenth`eses.
Les lettres apr`es le symbole % signifient que lon veut introduire :
d = un entier
f = un nombre reel
s = un string
e = un nombre en format exponentiel
x = un nombre en format hexadecimal
>>> a , b ,
>>> p r i n t
1 , 3 et 7
>>>
>>> a , b ,
>>> p r i n t
1.020000 ,
>>>
>>> a , b ,
>>> p r i n t
B i l l , Bob

c = 1, 3, 7
%d , %d e t %d s o n t d e s nombres p r e m i e r s % ( a , b , c )
s o n t d e s nombres p r e m i e r s
c = 1.02 , 3.2 , 7.67
%f , %f e t %f s o n t d e s nombres r e e l s % ( a , b , c )
3 . 2 0 0 0 0 0 e t 7 . 6 7 0 0 0 0 s o n t d e s nombres r e e l s
c = B i l l , Bob , Joe
%s , %s e t %s s o n t probablement a m e r i c a i n s % ( a , b , c )
e t Joe s o n t probablement a m e r i c a i n s

` noter que les nombres reels ont 6 valeurs decimales par defaut. On peut modifier ce nombre
A
en inserant un point, puis le nombre de decimales que lon desire, entre le signe % et la lettre f :
>>> a , b , c = 1 . 0 2 1 2 , 3 . 2 , 7 . 6 7
>>> p r i n t %.2 f , %.2 f e t %.2 f s o n t d e s nombres r e e l s % ( a , b , c )
1 . 0 2 , 3 . 2 0 e t 7 . 6 7 s o n t d e s nombres r e e l s

Ceci peut aussi sappliquer pour indiquer avec combien de chiffres on veut representer un
entier ou pour restreindre le nombre de caract`eres possibles `a linsertion dun chiffre dans un
string.

4.1.3

Quelques m
ethodes de la classe string

upper() : convertit tous les caract`eres en majuscules


>>> a = a l l o
>>> a = a . upper ( )
>>> a
ALLO

lower() : convertit tous les caract`eres en minuscules


>>> a = ALLO
>>> a = a . l o w e r ( )
>>> a
allo

`
4.1. CHAINES DE CARACTERES
: FONCTIONS PROPRES AU TYPE STRING

35

capitalize() : Assure que la premi`ere lettre est une majuscule


>>> a = a l l o
>>> a = a . c a p i t a l i z e ( )
>>> a
Allo

replace(old, new) : remplace toutes les occurrences de old par new.


>>> a = a l l o
>>> a = a . r e p l a c e ( l , b )
>>> a
abbo

find(sub) : retourne lindex de la premi`ere occurrence de sub, retourne -1 si sub nexiste pas.
>>> a = Bonjour t o u t l e monde !
>>> a . f i n d ( j o u r )
3

join(seq) : retourne un string qui contient la concatenation de tous les elements de seq. Lelement
separateur est le string sur lequel est applique la methode.
>>> a = a l l o
>>> b = . j o i n ( a )
>>> b
a l l o

split(sep) : retourne une liste des mots contenus dans le string en utilisant sep comme separateur.
>>> a = Bonjour t o u t l e monde !
>>> b = a . s p l i t ( )
>>> b
[ Bonjour , t o u t , l e , monde ! ]

Pour le detail des methodes de la classe string, se referer `a la documentation de Python.


CHAPITRE 4. LES STRUCTURES DE DONNEES

36

4.1.4

Indicage

On peut facilement obtenir un caract`ere ou une chane de caract`eres contenu dans un string
avec la methode dindicage. Comme pour tous les elements consideres comme des sequences
(string, liste, tuple), on acc`ede aux elements de la sequence en specifiant entre crochets lindex
que lon desire obtenir. Une valeur simple retournera le caract`ere `a cette position dans le string,
tandis que 2 valeurs separees par les deux-points ([2 :8]) retournera un string contenant la
sous-chane de caract`eres specifiee :
>>> a = Bonjour t o u t l e monde !
>>> a [ 0 ]
B
>>> a [ 5 ]
u
>>> a [ 2 : 1 0 ]
njour to
>>> a [ : 1 0 ] # du debut j u s q u a l a p o s i t i o n 10
Bonjour t o
>>> a [ 1 6 : ] # de l a p o s i t i o n 16 j u s q u a l a f i n
monde !
>>> a [ 1] # d e r n i e r e p o s i t i o n
!
>>> a [ : 4 ] # du debut a l a f i n moins l e s 4 d e r n i e r e s p o s i t i o n s
Bonjour t o u t l e mo

4.1.5

La m
ethode len

len(string) : la fonction len() retourne le nombre de caract`eres, incluant les espaces vides, dans
un string :
>>> a = Bonjour t o u t l e monde !
>>> l e n ( a )
22

4.1.6

String de documentation

Un string entre guillemets triples ( ou ) `a la ligne suivant la declaration dune fonction


sera enregistre dans la variable doc de la fonction.
>>> d e f p u i s s a n c e ( x , exp =2) :
...
C a l c u l e e t r e t o u r n e l a v a l e u r de x a l a p u i s s a n c e exp
...
r e t u r n x exp
...
>>> p u i s s a n c e . d o c
C a l c u l e e t r e t o u r n e l a v a l e u r de x a l a p u i s s a n c e exp


4.2. LES LISTES : OPERATIONS
SUR LES LISTES

4.2

37

Les listes : Op
erations sur les listes

Une liste consiste simplement en une suite de valeurs separees par des virgules et placees
entre crochets []. Les elements dans une liste peuvent etre de differents types (nombre, string,
liste, tuple, dictionnaire, fonction, objet, ...) et peuvent etre melanges. La liste est alterable,
cest `a dire que lon peut modifier ses elements sans avoir `a creer une nouvelle liste.
>>>
>>>
>>>
[1 ,

a = [3 , 5 , 2 , 8 , 7 , 5 , 1]
a . sort ()
a
2 , 3 , 5 , 5 , 7 , 8]

4.2.1

Quelques op
erations sur les listes
list1 + list2 : concatenation de list1 et list2
list[i] : retourne lelement `
a la position i
list[i :j] : retourne une liste contenant les elements entre les positions i et j
len(list) : retourne la longueur de la liste
del list[i] : elimine lelement `a la position i
list.append(val) : ajoute lelement val `a la fin de la liste
list.extend(list) : ajoute une liste `a la fin dune liste
list.sort() : met dans lordre les elements dune liste
list.reverse() : inverse les elements dune liste
list.insert(i, val) : ins`ere val `a la position i
list.count(val) : retourne le nombre doccurrences de val dans une liste
list.pop() : retourne et elimine la derni`ere valeur dune liste
val in list : retourne True si lelement val est present dans la liste

Tr`es bon tutoriel sur les listes dans la documentation Python :

4.3

La fonction range

La fonction range est tr`es utile pour creer rapidement une liste dentiers. Elle permet, entre
autre, de boucler sur un certain nombre de valeurs `a linterieur dune boucle for.
>>> r a n g e ( 5 )
[0 , 1 , 2 , 3 , 4]
>>> f o r i i n r a n g e ( 5 ) :
...
print i
...
0
1
2
3
4

Nous elaborerons sur la construction des instructions repetitives au prochain cours.


CHAPITRE 4. LES STRUCTURES DE DONNEES

38

Arguments de la fonction range


Si un seul argument est donne `
a la fonction range, il sera considere comme la valeur maximum
et la liste commencera `
a 0. Si deux arguments sont donnes `a la fonction, ils representent la valeur
minimum et la valeur maximum. Ce qui generera une liste de la valeur minimum `a la valeur
maximum - 1. Un troisi`eme argument peut etre donne pour specifier le pas, cest `a dire de
combien de valeurs on avance `
a chaque element de la liste.
>>> r a n g e ( 2 , 1 0 )
[2 , 3 , 4 , 5 , 6 , 7 , 8 , 9]
>>> r a n g e ( 2 , 1 0 , 2 )
[2 , 4 , 6 , 8]
>>> r a n g e ( 1 0 , 5 0 , 5 )
[ 1 0 , 15 , 20 , 25 , 30 , 35 , 40 , 45]

4.4
4.4.1

Pratique
Contr
ole des objets via les param`
etres dinitialisation

Nous venons tout juste de voir comment modifier le comportement de la fonction range en
lui donnant des arguments entre les parenth`eses. Le comportement des objets de la librairie pyo
peut egalement etre regit de cette facon. Il y a cependant quelques r`egles `a respecter :
1 - Si les noms des arguments ne sont pas sp
ecifi
es, ces derniers doivent
etre donn
es
dans lordre.
Suivant cette methode, considerant que lordre des arguments de lobjet Sine est :
freq, phase, mul, add
Pour assigner une valeur damplitude de 0.5 (argument mul), on doit specifier tous les arguments
qui le prec`ede :
a = Sine (1000 , 0 , . 5 )

2 - Certains arguments peuvent


etre omis ou lordre peut
etre m
elang
e seulement
si on sp
ecifie le nom des arguments en leur affectant une valeur.
a = S i n e ( mul =.5)
b = S i n e ( mul =.3 , f r e q =500)

3 - On peut m
elanger les 2 m
ethodes, mais d`
es quun argument est d
ument nomm
e,
lordre est consid
er
e comme
etant bris
e et lon doit sp
ecifier le nom pour le reste
des arguments.
a = S i n e ( mul =.5)
b = Harmonizer ( a , 12 , mul =.3 , f e e d b a c k =0.5)

4.4. PRATIQUE

39

Le manuel devient donc un outil indispensable lors de lecriture dun scripts. Vous pouvez
consulter le manuel en ligne si vous etes connecte sur le web ou bien utiliser le syst`eme daide
integre de Python en appelant la methode help :
>>> from pyo import
>>> h e l p ( S i n e )
Help on c l a s s S i n e i n module p y o l i b . g e n e r a t o r s :
...

La librairie pyo fournit aussi une fonction class args permettant dobtenir rapidement les
param`etres dinitialisation dun objet ainsi que leur valeur par defaut :
>>> from pyo import
>>> c l a s s a r g s ( S i n e )
S i n e ( f r e q =1000 , phase =0, mul=1, add=0)

Une bonne habitude est de toujours avoir un interpreteur ouvert lorsque lon ecrit un script !
En prime, vous pouvez ecouter les exemples du manuel avec la fonction example :
>>> from pyo import
>>> example ( S i n e )
import time
from pyo import
s = S e r v e r ( ) . boot ( )
s . start ()
s i n e = S i n e ( f r e q =500) . out ( )
time . s l e e p ( 5 . 0 0 0 0 0 0 )
s . stop ()
time . s l e e p ( 0 . 2 5 )
s . shutdown ( )

4.4.2

Lire un fichier son sur le disque dur

Nous allons maintenant experimenter avec lobjet SfPlayer qui permet de lire un fichier son
sauvegarde sur le disque dur.
>>> from pyo import
>>> c l a s s a r g s ( S f P l a y e r )
S f P l a y e r ( path , s p e e d =1 , l o o p=F a l s e , o f f s e t =0, i n t e r p =2 , mul=1 , add=0)

Largument path est obligatoire puisque quaucune valeur ne lui est assigne par defaut. On
specifie le chemin vers le son `
a laide dun string en utilisant la syntaxe en vigueur sur les
syst`emes Unix, cest-`
a-dire en separant les elements hierarchiques par le symbole /.
/Users/olivier/Desktop/snds/baseballmajeur s.aif
>>>
>>>
>>>
>>>

from pyo import


s = S e r v e r ( ) . boot ( )
s . start ()
a = S f P l a y e r ( path= / U s e r s / o l i v i e r / Desktop / s n d s / b a s e b a l l m a j e u r s . a i f ) . out ( )


CHAPITRE 4. LES STRUCTURES DE DONNEES

40

Sur la plateforme Windows, python se chargera de convertir votre string dans le bon format
avant daller chercher le son sur le disque. Nous y ecrierions donc :
C :/Documents and Settings/olivier/Desktop/snds/baseballmajeur s.aif
Les param`etres optionnels permettent de controler respectivement :
speed : La vitesse de lecture (0.5 = deux fois plus lent, 2 = deux fois plus vite)
loop : Si le son est lu en boucle ou non (True = lu en boucle, False = lu une seule fois)
offset : Le point de depart, en secondes, dans le fichier son (2 = la lecture commence `a 2
secondes dans le fichier)
interp : La qualite de linterpolation `a la lecture (ny touchez pas pour linstant !)
mul : Le facteur damplitude (0.5 = deux fois moins fort)
` ne pas modifier
add : La valeur `
a ajouter `
a chacun des echantillons apr`es la lecture (A
dans le cas dune lecture de fichier son sous risque dendommager vos haut-parleurs et vos
oreilles !)
Exercice
Faire jouer un son en boucle et lui appliquer une chane de traitements sonores choisis
parmi ceux introduits au cours precedent. Gerer les param`etres des effets via les arguments `
a
linitialisation.

4.4.3

Gestion de la polyphonie

Si, `a lexercice precedent, vous avez charge un son stereo, vous avez pu remarquer que du
signal etait envoye aux deux haut-parleurs. Ceci est du au fait que chaque objet de la librairie
pyo est en mesure de gerer plusieurs streams audio `a la fois. Un stream est un objet interne de
la librairie charge de vehiculer un canal de son monophonique. Chaque objet g`ere son audio via
un ou plusieurs streams, qui sont recuperes par le serveur et achemines vers une sortie de la
carte de son. La methode len, applicable aux listes, peut aussi etre appelee avec un objet pyo
en argument. Elle retournera le nombre de streams geres par lobjet.
>>>
>>>
>>>
>>>
>>>
2

from pyo import


s = S e r v e r ( ) . boot ( )
s . start ()
a = S f P l a y e r ( path= / U s e r s / o l i v i e r / Desktop / s n d s / b a s e b a l l m a j e u r s . a i f ) . out ( )
len (a)

En ce qui concerne la distribution des streams dun objet vers les sorties audio, le comportement par defaut (modifiable via les arguments de la methode out) est dalterner la sortie, en
fonction du nombre de sorties disponibles, `a chaque nouveau stream. En debutant `a 0, un son
stereo sera repartit sur les sortie 0 et 1, cest-`a-dire le premier stream `a gauche et le second `
a
droite.

4.4. PRATIQUE

41

Arguments de la m
ethode out
chnl : Le canal o`
u sera envoye le premier stream de lobjet.
inc : De combien de canaux on avance `a chaque nouveau stream.
Dans un environnement multi-canaux, ces param`etres peuvent etre manipules de facon tr`es
subtile. En stereo, les valeurs par defaut (chnl=0, inc=1) sont generalement les plus coherentes !
On peut convertir le nombre de canaux dun objet avec la methode mix comme suit :
>>> a = S i n e ( )
>>> l e n ( a )
1
>>> b = a . mix ( 2 )
>>> l e n ( b )
2
>>> p r i n t b
< I n s t a n c e o f Mix c l a s s >
>>> c = S f P l a y e r ( / U s e r s / o l i v i e r / Desktop / s n d s / b a s e b a l l m a j e u r s . a i f )
>>> l e n ( c )
2
>>> d = c . mix ( 1 )
>>> l e n ( d )
1
>>> p r i n t d
< I n s t a n c e o f Mix c l a s s >
>>>

Notez que b et d sont de nouveaux objets de la classe Mix qui ont ete crees par lappel de la
methode mix. Ils recoivent les signaux de a et c, effectuent la conversion et g`erent de nouveaux
streams... a et c restent intacts.

4.4.4

Utilisation des listes `


a des fins musicales

Chaque objet de la librairie pyo prend un certain nombre darguments afin de definir son
comportement. Par exemple, le param`etre path de lobjet SfPlayer prendra un lien vers un
fichier son sur le disque dur. Rappelons la ligne pour jouer un son `a partir du disque dur :
a = S f P l a y e r ( / U s e r s / o l i v i e r / Desktop / s n d s / b a s e b a l l m a j e u r s . a i f )

Un concept tr`es puissant en programmation, appele list expansion, consiste en la possibilite


dutiliser une liste comme valeur `
a un argument. Cest un concept generalise `a tous les param`etres
des objets pyo (sauf mention contraire dans le manuel !), afin de decupler les processus sonores
sans avoir `
a repeter sans cesse les memes lignes de code. Ainsi, pour creer un decalage progressif
de la lecture dun son, on executerait le code suivant.
1
2
3
4
5

from pyo import


s = S e r v e r ( ) . boot ( )
a = S f P l a y e r ( path= / U s e r s / o l i v i e r / Desktop / s n d s / b a s e b a l l m a j e u r s . a i f ,
s p e e d = [ 1 , 1 . 0 0 5 , 1 . 0 0 7 , . 9 9 2 ] , l o o p=True , mul =.25) . out ( )
s . gui ( l o c a l s () )

scripts/chapitre 04/01 snd chorus.py


CHAPITRE 4. LES STRUCTURES DE DONNEES

42

La fonction range, vue un peu plus tot, pourrait servir `a creer une suite dharmoniques :
1
2
3
4

from pyo import


s = S e r v e r ( ) . boot ( )
a = S i n e ( f r e q=r a n g e ( 1 0 0 , 1 0 0 0 , 1 0 0 ) , mul = [ . 5 , . 3 5 , . 2 , . 1 4 , . 1 , . 0 7 , . 0 5 , . 0 3 , . 0 1 ] ) . out ( )
s . gui ( l o c a l s () )

scripts/chapitre 04/02 serie harmonique.py


Un objet qui recoit une liste comme valeur dun de ses arguments creera le nombre de streams
necessaires afin de calculer le rendu sonore desire. Si, pour un meme objet, plusieurs arguments
recoivent une liste en entree, la plus longue liste sera utilisee pour generer le nombre de streams
necessaires. Les valeurs des listes plus courtes seront utilisees dans lordre, avec bouclage lorsque
la fin de la liste est atteinte. Utiliser des listes de differentes longueurs pour les arguments dun
objet produira un resultat sonore riche et varie puisque les combinaisons de param`etres seront
differentes pour chaque instance du processus sonore.
1
2
3
4
5

from pyo import


s = S e r v e r ( ) . boot ( )
a = FM( c a r r i e r = [ 5 0 , 7 4 . 6 , 1 0 1 , 1 2 5 . 5 ] , r a t i o = [ 1 . 5 0 1 , 2 . 0 2 , 1 . 0 0 5 ] ,
i n d e x = [ 6 , 5 , 4 , 7 , 6 , 5 , 9 , 6 , 5 , 8 , 5 , 6 ] , mul =.05) . out ( )
s . gui ( l o c a l s () )

scripts/chapitre 04/03 fm stack.py


Les listes donnees aux arguments de lobjet FM etant de longueur differentes, la plus grande
est utilisee pour determiner le nombre de streams de lobjet, cest-`a-dire 12 (longueur de la liste
donnee `a largument index). En bouclant sur les valeurs des plus petites listes, nous obtenons
12 modulations de frequence avec comme param`etres :
FM
1
2
3
4
5
6
7
8
9
10
11
12

carrier
50
74.6
101
125.5
50
74.6
101
125.5
50
74.6
101
125.5

ratio
1.501
2.02
1.005
1.501
2.02
1.005
1.501
2.02
1.005
1.501
2.02
1.005

index
6
5
4
7
6
5
9
6
5
8
5
6

Distribution des valeurs aux arguments des differentes modulation de frequence.

4.4. PRATIQUE

43

Mise en garde
Un objet pyo etant considere comme une liste, il est tr`es facile de creer une surcharge de
calcul pour le processeur en demandant de creer plusieurs instances dun effet dej`a couteux (une
reverberation par exemple) sur un signal. La solution sera de passer un mix de tous les signaux
(streams) de la source `
a leffet. Prenons comme exemple notre lecture decalee (4 lectures stereo) :
from pyo import
s = S e r v e r ( ) . boot ( )
s . start ()
a = S f P l a y e r ( / U s e r s / o l i v i e r / Desktop / s n d s / b a s e b a l l m a j e u r s . a i f , s p e e d
= [ 1 , 1 . 0 0 5 , 1 . 0 0 7 , . 9 9 2 ] , l o o p=True , mul =.25)
>>> l e n ( a )
8
>>> b = F r e e v e r b ( a ) . out ( )
>>> l e n ( b )
8
>>>
>>>
>>>
>>>

CPU : 20%
from pyo import
s = S e r v e r ( ) . boot ( )
s . start ()
a = S f P l a y e r ( / U s e r s / o l i v i e r / Desktop / s n d s / b a s e b a l l m a j e u r s . a i f , s p e e d
= [ 1 , 1 . 0 0 5 , 1 . 0 0 7 , . 9 9 2 ] , l o o p=True , mul =.25)
>>> l e n ( a )
8
>>> b = F r e e v e r b ( a . mix ( 2 ) ) . out ( )
>>> l e n ( b )
2
>>>
>>>
>>>
>>>

CPU : 16%

4.4.5

Exemples et exercices

Exercices

1. Ecrire
un script jouant 5 ondes sinusodales de frequences croissantes {400, 500, 600, 700,
800} et damplitudes decroissantes {.5, .25, .12, .06, .03}. Les 5 ondes sinusodales doivent
etre generees avec une seule ligne de code !
2. Reprendre les exercices du cours precedents (chanes de traitement `a partir de sources
de synth`ese) et eliminer la methode ctrl() en donnant des arguments `a linitialisation des
objets. Generer plusieurs sonorites avec une meme chane de traitement simplement en
modifiant les param`etres dinitialisation (voir exemple 1 ci-dessous).
3. Magnifier les sons de lexercice numero 2 en utilisant le potentiel des listes en argument
(voir exemple 2 ci-dessous).
4. Creer une chane de traitement sur une lecture de fichier son. Tester avec differents sons
et differentes valeurs aux arguments des objets.
Sauvegardez vos scripts (avec lextension .py) et apportez-les au prochain cours, nous prendrons
un temps pour ecouter et repondre aux questions !

44

CHAPITRE 4. LES STRUCTURES DE DONNEES

Exemples
Exemple numero 1 : Specification des arguments `a linitialisation des objets.
1
2
3
4

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

S p e c i f i c a t i o n d e s arguments a l i n i t i a l i s a t i o n d e s o b j e t s .

5
6
7
8
9
10
11
12

T r o i s s o n o r i t e s s u r l a b a s e de l exemple no 3 du c o u r s p r e c e d e n t :

Exemple no 3 : C o n n e c t i o n s en p a r a l l e l e ( multi s o u r c e s ) :
l f o 1 >
l f o 2 > h a r m o n i z e r
l f o 3 >

13
14
15
16

Exemple no 1 :
Accord c o n s o n a n t avec une l e g e r e d e v i a t i o n d e s f r e q u e n c e s
pour c r e e r un e f f e t de modulation .

17
18
19
20

Exemple no 2 :
F r e q u e n c e s d e s LFOs t r e s r a p p r o c h e e s e t h a r m o n i s a t i o n de
1/10 e de demiton avec f e e d b a c k pour c r e e r un e f f e t de f l a n g e .

21
22
23

Exemple no 3 :
Desaccord t o t a l , s o n o r i t e s e r a p p r o c h a n t du b r u i t .

24
25
26

from pyo import

27
28

s = S e r v e r ( ) . boot ( )

29
30

exemple = 1 # m o d i f i e r c e t t e v a r i a b l e pour c h a n g e r d exemple

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

i f exemple == 1 :
s r c 1 = LFO( f r e q =100 , s h a r p =.5 , mul =.1) . out ( )
s r c 2 = LFO( f r e q =150.5 , s h a r p =.25 , mul =.1) . out ( )
s r c 3 = LFO( f r e q =200.78 , s h a r p =.15 , mul =.1) . out ( )
harm = Harmonizer ( s r c 1+s r c 2+s r c 3 , t r a n s p o =7) . out ( 1 )
e l i f exemple == 2 :
s r c 1 = LFO( f r e q =100 , s h a r p =.75 , mul =.1) . out ( )
s r c 2 = LFO( f r e q =99.8 , s h a r p =.75 , mul =.1) . out ( )
s r c 3 = LFO( f r e q =100.3 , s h a r p =.75 , mul =.1) . out ( )
harm = Harmonizer ( s r c 1+s r c 2+s r c 3 , t r a n s p o =0.1 , f e e d b a c k =.8 , mul =.6) . out ( 1 )
e l i f exemple == 3 :
s r c 1 = LFO( f r e q =100 , s h a r p =.75 , mul =.1) . out ( )
s r c 2 = LFO( f r e q =123 , s h a r p =.65 , mul =.1) . out ( )
s r c 3 = LFO( f r e q =178 , s h a r p =.5 , mul =.1) . out ( )
harm = Harmonizer ( s r c 1+s r c 2+s r c 3 , t r a n s p o =2.33 , f e e d b a c k =.5) . out ( 1 )

47
48

s . gui ( l o c a l s () )

scripts/chapitre 04/04 arguments.py

4.4. PRATIQUE

45

Exemple numero 2 : Elargissement


des sonorites `a laide de listes en argument.
1
2
3
4

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

G r o s s i s s e m e n t d e s s o n o r i t e s a l a i d e de l i s t e s en argument .

5
6

Sur l a b a s e d e s t r o i s s o n o r i t e s de l exemple p r e c e d e n t .

7
8
9

Exemple no 1 :
Chorus s u r chaque s o u r c e s + m u l t i p l e s h a r m o n i s a t i o n s .

10
11
12
13
14

Exemple no 2 :
F r e q u e n c e s d e s LFOs t r e s r a p p r o c h e e s , s u r 3 f r e q u e n c e s
e t l e g e r e s h a r m o n i s a t i o n s avec f e e d b a c k pour c r e e r un
e f f e t de f l a n g e .

15
16
17

Exemple no 3 :
Desaccord t o t a l , e n c o r e p l u s p r o c h e du b r u i t .

18
19
20

from pyo import

21
22

s = S e r v e r ( ) . boot ( )

23
24

exemple = 1 # m o d i f i e r c e t t e v a r i a b l e pour c h a n g e r d exemple

25
26
27
28
29
30

31
32
33
34
35

36
37
38
39
40

i f exemple == 1 :
s r c 1 = LFO( f r e q = [ 1 0 0 , 1 0 0 . 0 3 , 9 9 . 9 5 , 9 9 . 9 1 ] , s h a r p =.5 , mul =.05) . out ( )
s r c 2 = LFO( f r e q = [ 1 5 0 . 4 1 , 1 5 0 . 5 , 1 5 0 . 7 8 , 1 5 0 . 9 8 ] , s h a r p =.25 , mul =.05) . out ( )
s r c 3 = LFO( f r e q = [ 2 0 0 . 7 8 , 2 0 1 , 2 0 1 . 3 , 2 0 2 . 1 ] , s h a r p =.15 , mul =.05) . out ( )
harm = Harmonizer ( s r c 1+s r c 2+s r c 3 , t r a n s p o =[ 12 , 7 ,5 ,7] , mul = [ 1 , . 7 , . 5 , . 4 ] ) . out
()
e l i f exemple == 2 :
s r c 1 = LFO( f r e q = [ 1 0 0 , 3 0 0 , 5 0 0 ] , s h a r p =.75 , mul = [ . 1 , . 0 2 , . 0 1 5 ] ) . out ( )
s r c 2 = LFO( f r e q = [ 9 9 . 8 , 3 0 0 . 3 , 5 0 0 . 5 ] , s h a r p =.75 , mul = [ . 1 , . 0 2 , . 0 1 5 ] ) . out ( )
s r c 3 = LFO( f r e q = [ 1 0 0 . 3 , 2 9 9 . 7 6 , 4 9 9 , 6 5 ] , s h a r p =.75 , mul = [ . 1 , . 0 2 , . 0 1 5 ] ) . out ( )
harm = Harmonizer ( s r c 1+s r c 2+s r c 3 , t r a n s p o = [ 0 . 0 7 , 0 . 0 4 , 0 . 1 ] , f e e d b a c k =.8 , mul
=.4) . out ( 1 )
e l i f exemple == 3 :
s r c 1 = LFO( f r e q = [ 1 0 0 , 2 7 6 , 4 2 1 , 5 1 1 ] , s h a r p =.75 , mul = [ . 1 , . 0 3 , . 0 2 , . 0 1 ] ) . out ( )
s r c 2 = LFO( f r e q = [ 1 2 3 , 3 2 4 , 3 8 9 , 4 8 8 ] , s h a r p =.65 , mul = [ . 1 , . 0 3 , . 0 2 , . 0 1 ] ) . out ( )
s r c 3 = LFO( f r e q = [ 1 7 8 , 2 6 5 , 4 4 4 , 5 6 1 ] , s h a r p =.5 , mul = [ . 1 , . 0 3 , . 0 2 , . 0 1 ] ) . out ( )
harm = Harmonizer ( s r c 1+s r c 2+s r c 3 , t r a n s p o = [ 3 . 7 6 , 2 . 3 3 ] , f e e d b a c k =.5) . out ( 1 )

41
42

s . gui ( l o c a l s () )

scripts/chapitre 04/05 list in args.py

46

CHAPITRE 4. LES STRUCTURES DE DONNEES

Chapitre 5

Boucles et importation de modules


5.1

Importation de modules

Il est impossible dimporter automatiquement toutes les fonctions disponibles sous Python
d`es louverture du logiciel, car il en existe virtuellement une infinite. Les fonctions integrees
representent celles qui risquent detre utilisees le plus souvent. Toutes les autres fonctions sont
regroupees par th`emes dans des fichiers .py qui peuvent etre importes en tant que modules
(pyo est un module). Pour utiliser les fonctions contenues dans un module, il faut absolument
importer ce module. Il existe deux formes dimportation sous Python.
Premi`
ere forme : importer un module au complet
import sys , time
p r i n t s y s . path
p r i n t time . time ( )

Lattribut path du module sys, ainsi que la fonction time du module time sont alors accessibles. Comme cest le module lui-meme qui a ete importe, il faut appeler lattribut ou la fonction
en specifiant dabord le nom du module (module.fonction).
Deuxi`
eme forme : importer des
el
ements dun module
from random import r a n d i n t , un ifo rm
print randint (100 ,200)
p r i n t u ni fo rm ( 0 , 1 )

Ici, seulement les fonctions randint et uniform du module random ont ete importees. Elles
peuvent donc etre utilisees sans specifier le nom du module auquel elles appartiennent.
Importer toutes les fonctions dun module
from random import

Letoile signifie tous !


47

48

CHAPITRE 5. BOUCLES ET IMPORTATION DE MODULES

Modifier le nom de r
ef
erence
On peut ausssi modifier le nom de reference dun module (principalement pour alleger la
syntaxe) avec le mot-cle as. Dans lexemple ci-dessous, toutes les fonctions du module wx.html
pourront etre appelees avec la syntaxe html.fonction.
import wx . html a s html
win = html . HtmlWindow ( )

La fonction dir(module) renvoie la liste des attributs et des fonctions appartenant `a un


module.
>>> import math
>>> d i r ( math )
[ doc ,
file
, n a m e , a c o s , a s i n , atan , atan2 , c e i l , c o s
, cosh , degrees ,
e , exp , f a b s , f l o o r , fmod , f r e x p , hypot , l d e x p , l o g , l o g 1 0 ,
modf , p i , pow ,
r a d i a n s , s i n , s i n h , s q r t , tan , tanh ]
>>>

5.2

Instructions r
ep
etitives (while, for)

Nous avons dej`


a explore 2 des 3 principaux types de structures de controle en programmation,
la s
equence et linstruction conditionnelle. Nous allons maintenant elaborer sur le troisi`eme
type, la r
ep
etition. Deux methodes pour programmer des boucles seront presentees ici, linstruction while, permettant de creer des boucles ayant une duree indeterminee, et linstruction
for, permettant de naviguer de facon cyclique sur tous les elements dun groupe.

5.2.1

Linstruction while

Prenons un exemple simple :


a = 0
while a < 10:
# bloc d instructions
print a
a += 1
# s u i t e du programme

Une variable a est dabord initialisee. Ensuite linstruction while est appelee suivie dune
condition (ne pas oublier les deux-points qui indiquent le debut dun bloc instructions). while,
qui veut dire tant que, signifie que tant que la condition est respectee, le bloc dinstructions
qui suit (notez lindentation) doit etre repete en boucle. Voyons dans le detail :
1. linstruction while evalue la condition. Si elle est fausse, tout le bloc est ignore et le
programme saute `
a la ligne suivant le bloc. Si la condition est vraie, le programme execute
les instructions du bloc :
2. la valeur de la variable a est affichee.

ETITIVES

5.2. INSTRUCTIONS REP


(WHILE, FOR)

49

3. la variable a est incrementee de 1.


4. linstruction while est ensuite reevaluee en fonction de la nouvelle valeur de la variable a.
Si la condition est encore vrai, le bloc est execute `a nouveau, jusqu`a ce que la condition
sav`ere fausse.
Il est donc tr`es important, afin de ne pas creer de boucles infinies, quil y ait au moins une
variable de la condition qui soit modifiee `a linterieur du bloc dinstructions de la boucle. Sous
certaines conditions, des boucles infinies peuvent etre definies dans un programme. Dans ce cas,
une action de lutilisateur, ou une commande envoyee lorsque lon quitte le programme, met fin
`a la boucle.
Si une variable est utilisee dans la condition dune instruction while, elle doit obligatoirement
etre definie avant dexecuter cette instruction.
Les valeurs booleennes True et False peuvent servir `a creer une boucle infinie, ou de facon
plus commune, `
a activer ou desactiver un bloc de code dans un programme.
w h i l e True :
# La c o n d i t i o n e s t t o u j o u r s v r a i . . .
i f False :
# Ces i n s t r u c t i o n s ne s e r o n t j a m a i s e x e c u t e e s , r e m p l a c e r par :
i f True :
# Reactive l e bloc d i n s t r u c t i o n s

Creation dune table des carres et des cubes des nombres de 1 `a 10 :


>>> a = 0
>>> w h i l e a < 1 0 :
...
a += 1
...
p r i n t a , a 2 , a 3
...
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000

Nous allons maintenant creer un programme permettant dafficher les nombres de la suite de
Fibonacci (o`
u une valeur est la somme des 2 valeurs precedentes). Laffichage arretera lorsquun
certain seuil (defini par lutilisateur) sera atteint.
1
2
3
4
5

s e u i l = 100
a = b = 1
while b < s e u i l :
print b ,
a , b = b , a+b

scripts/chapitre 05/01 fibonacci.py

50

CHAPITRE 5. BOUCLES ET IMPORTATION DE MODULES

Ce programme retournera le resultat suivant :


1 2 3 5 8 13 21 34 55 89

Il y a plusieurs aspects interessants dans ce petit programme :


1. Affectations multiples permettant de donner la valeur 1 aux variables a et b simultanement.
2. Notez la virgule terminant la ligne de linstruction print. Elle elimine le retour de chariot
insere automatiquement par le mot-cle print, permettant ainsi dafficher plusieurs valeurs
sur une meme ligne.
3. Affectations parall`eles `
a linterieur de la boucle ( a, b = b, a+b ). Dun seul coup, on
modifie letat des deux variables (a et b).

5.2.2

Linstruction for

Linstruction for sert `


a naviguer de facon cyclique sur tous les membres dun groupe,
habituellement une liste. Chaque membre sera assigne, `a tour de role, `a une variable pouvant
etre utilisee `
a linterieur de la boucle. La syntaxe dune boucle for est tr`es simple :
>>> f o r i i n r a n g e ( 5 ) :
...
print i ,
...
0 1 2 3 4

La fonction range, avec un seul argument, retourne une liste contenant les valeurs de 0 `a la
valeur en argument - 1. Si deux arguments sont presents, ils representeront la valeur de depart
et la valeur darrivee (non comprise) de la liste. Un troisi`eme argument peut etre utilise pour
definir le pas, cest `
a dire la valeur de lincrement entre chaque membre de la liste.
>>>
[0 ,
>>>
[5 ,
>>>
[0 ,

range (5)
1 , 2 , 3 , 4]
range (5 , 10)
6 , 7 , 8 , 9]
range ( 0 , 1 0 , 2 )
2 , 4 , 6 , 8]

La boucle for est tr`es utile pour appliquer une transformation sur toutes les valeurs dune
liste :
>>> l i s t 1 = [ 2 , 4 , 6 , 8 , 1 0 ]
>>> l i s t 2 = [ ]
>>> f o r i i n l i s t 1 :
...
# i prend l a v a l e u r de chaque e l e m e n t de l a l i s t e a t o u r de r o l e
...
l i s t 2 . append ( i 2 )
...
>>> p r i n t l i s t 2
[4 ,16 ,36 ,64 ,100]

La methode append fait partie des methodes de la classe list et permet dajouter une valeur
`a la fin de la liste sur laquelle est appliquee la methode. On utilise une methode `a laide de la
syntaxe objet.methode().

ERATEURS

5.3. GEN
DE LISTES (LIST COMPREHENSION)

51

Variante du programme precedant, en utilisant la longueur de la liste :


>>> l i s t 1 = [ 2 , 4 , 6 , 8 , 1 0 ]
>>> f o r i i n r a n g e ( l e n ( l i s t 1 ) ) :
...
# i e s t un i n d e x dans l a l i s t e , 0 > l e n ( l i s t 1 ) 1
...
l i s t 1 [ i ] = l i s t 1 [ i ]2
...
>>> p r i n t l i s t 1
[4 ,16 ,36 ,64 ,100]

len est une fonction integree de Python qui retourne le nombre delements contenus dans
un groupe (liste, tuple, dictionnaire, chane de caract`eres) donne en argument. Cette variante
constitue ce que lon appelle une action destructive sur un ensemble (in-place modification), les
valeurs de la liste sont directement remplacees sans avoir recours `a une seconde liste.

5.3

G
en
erateurs de listes (list comprehension)

La fabrication de listes est une des fonctionnalites les plus puissantes du langage Python. Elle
permet de creer des listes complexes tr`es rapidement par une utilisation particuli`ere de la boucle
for. Les list comprehension sont delimitees par des crochets et consistent en une expression
suivie dune boucle for, avec possibilite dimbriquer plusieurs boucles for ou expressions if.
[

expression boucle condition ( optionel ) ]

Les crochets indique la creation dune nouvelle liste.


expression est le bloc dinstructions de la boucle for (habituellement une expression
mathematique).
boucle est linstruction repetitive for permettant dexecuter lexpression un certain nombre de fois.
condition est un param`etre optionnel permettant de specifier sous quelles conditions
lexpression doit etre executee.
G
en
erateur simple
>>>
>>>
[0 ,
>>>
>>>
>>>
[0 ,

m a l i s t = [ i f o r i in range (20) ]
ma list
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19]
c a r r e s = [ i i f o r i in range (5) ]
carres
1 , 4 , 9 , 16]

G
en
erateur avec boucles for imbriqu
ees
>>> m a l i s t = [ [ i , j ] f o r i i n r a n g e ( 3 ) f o r j i n r a n g e ( 3 ) ]
>>> m a l i s t
[[0 , 0] , [0 , 1] , [0 , 2] , [1 , 0] , [1 , 1] , [1 , 2] , [2 , 0] , [2 , 1] , [2 , 2]]

Dans cet exemple, pour chaque tour de boucle de la variable i, la boucle de la variable j est
executee trois fois. La version longue de la creation de cette liste secrirait comme suit :

52

CHAPITRE 5. BOUCLES ET IMPORTATION DE MODULES

ma liste = [ ]
f o r i in range (3) :
f o r j in range (3) :
m a l i s t e . append ( [ i , j ] )
print ma liste

G
en
erateur avec une condition
Dans le cas dun generateur avec condition, lexpression sera executee (et le resultat sera
ajoute `a la liste) seulement pour les tours de boucle o`
u la condition est respectee.
>>> m a l i s t = [ [ i , j ] f o r i i n r a n g e ( 3 ) f o r j i n r a n g e ( 3 ) i f j != 1 ]
>>> m a l i s t
[[0 , 0] , [0 , 2] , [1 , 0] , [1 , 2] , [2 , 0] , [2 , 2]]

Version longue :
ma liste = [ ]
f o r i in range (3) :
f o r j in range (3) :
i f j != 1 :
m a l i s t e . append ( [ i , j ] )
print ma liste

Temps dex
ecution
Un des grands avantages des generateurs de listes est loptimisation du code sous-jacent qui
ameliore de facon notable la performance du programme. Petit exemple qui demontre le temps
requis pour creer une liste contenant un million dentiers :
import time
num = 1000000
# l i s t comprehension
t = time . time ( )
l = [ i f o r i i n r a n g e (num) ]
p r i n t time . time ( ) t # 0 . 1 9 3 0 9 7 1 1 4 5 6 3 s e c .
# boucle for
t = time . time ( )
l = []
f o r i i n r a n g e (num) :
l . append ( i )
p r i n t time . time ( ) t # 0 . 2 9 9 5 8 0 0 9 7 1 9 8 s e c .
# t o u j o u r s u t i l i s e r une f o n c t i o n b u i l t i n s i d i s p o n i b l e !
t = time . time ( )
l = r a n g e (num)
p r i n t time . time ( ) t # 0 . 0 4 0 6 4 2 0 2 3 0 8 6 5 s e c .

5.4. PRATIQUE

5.4
5.4.1

53

Pratique
Utilisation de la boucle for pour la g
en
eration de param`
etres

Quelques exemples dutilisation de la boucle for pour faciliter la construction de listes de


param`etres.
G
en
eration dune synth`
ese additive par laddition dondes sinusodales dont les
fr
equences sont des multiples entiers dune fr
equence fondamentale.
Les incontournables :
from pyo import
s = S e r v e r ( ) . boot ( )

Creation de listes vides o`


u seront ajoutees les valeurs assignees aux param`etres de frequence
et damplitude :
freqs = [ ]
amps = [ ]

On definit une frequence fondamentale :


fo nd = 50

` linterieur dune boucle for, nous allons remplir nos listes en appliquant de simples fonctions
A
mathematiques sur la variable i (qui prendra tour `a tour les valeurs de 1 `a 20) :
f o r i in range (1 ,21) :
f r e q s . append ( i fond )
amps . append ( 0 . 3 5 / i )

Affichage des listes remplies :


p r i n t Frequences :
p r i n t Amplitudes :

, freqs
, amps

En donnant nos listes aux param`etres dun objet Sine, nous creons autant doscillateurs quil
y a de valeurs dans les listes :
a = S i n e ( f r e q=f r e q s , mul=amps ) . out ( )

Autre incontournable :
s . gui ( l o c a l s () )

Questions :
Que doit-on faire pour obtenir une frequence fondamentale differente ?
Que doit-on faire pour ajouter ou enlever des harmoniques ?

54

1
2
3
4
5

CHAPITRE 5. BOUCLES ET IMPORTATION DE MODULES

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

Exercice boucle for ,


s e r i e de f r e q u e n c e s e t d a m p l i t u d e s .

6
7
8

from pyo import

9
10

s = S e r v e r ( ) . boot ( )

11
12
13

freqs = [ ]
amps = [ ]

14
15
16
17
18

fo nd = 50
f o r i in range (1 ,21) :
f r e q s . append ( i fond )
amps . append ( 0 . 3 5 / i )

19
20
21

p r i n t Frequences :
p r i n t Amplitudes :

, freqs
, amps

22
23

a = S i n e ( f r e q=f r e q s , mul=amps ) . out ( )

24
25

s . gui ( l o c a l s () )

scripts/chapitre 05/02 boucle for 1.py

Modification de lexemple pr
ec
edant afin de lui donner un peu plus de naturel...
Le principal defaut de ce type dalgorithme est la trop grande precision des valeurs. Aucun
son naturel ne peut produire des harmoniques aussi justes et cest justement dans les infimes
variations que le son prend vie. Il faut donc trouver un moyen de desaccorder les harmoniques
les unes par rapport aux autres. Pour ce faire, nous allons nous en remettre au hasard ainsi
quau module python random, generateur de hasard par excellence !
Commencons par importer le module random :
import random

Nous allons ensuite modifier notre boucle for afin dinclure une leg`ere variation de la frequence
de chaque harmonique :
dev = random . u nif or m ( 0 . 9 8 , 1 . 0 2 )
f r e q s . append ( i fond dev )

La fonction uniform du module random demande 2 param`etres qui sont respectivement la


valeur minimum possible et la valeur maximum possible. Chaque fois que la fonction est appelee,
une nouvelle valeur est pigee dans lambitus permis. On multiplie la frequence de loscillateur
par cette valeur pour creer une leg`ere deviation.
Testez differents ambitus de deviation afin de constater limpact sur le son !

5.4. PRATIQUE

1
2
3
4
5

55

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

Exercice boucle for , version 2 ,


s e r i e de f r e q u e n c e s e t d a m p l i t u d e s .

6
7
8
9

from pyo import


import random

10
11

s = S e r v e r ( ) . boot ( )

12
13
14

freqs = [ ]
amps = [ ]

15
16
17
18
19
20

fo nd = 50
f o r i in range (1 ,21) :
dev = random . u nif orm ( . 9 8 , 1 . 0 2 )
f r e q s . append ( i fond dev )
amps . append ( 0 . 3 5 / i )

21
22
23

p r i n t Frequences :
p r i n t Amplitudes :

, freqs
, amps

24
25

a = S i n e ( f r e q=f r e q s , mul=amps ) . out ( )

26
27

s . gui ( l o c a l s () )

scripts/chapitre 05/03 boucle for 2.py

Synth`
ese par modulation de fr
equence en utilisant quelques une des fonctions offertes par le module random.
Le script suivant utilise des generateurs de distributions aleatoires controlees, accessibles via
le module random, pour creer une sonorite de synth`ese par modulation de frequence differente
chaque fois que le script est execute.
random.triangular(min, max) : Distribution triangulaire (favorise les valeurs medianes)
entre min et max.
random.choice(seq) : Pige une valeur au hasard dans la liste donnee au param`etre seq.
random.randint(min, max) : Pige un entier au hasard entre min et max.
Consultez le manuel Python pour une description detaillee des fonctions du module random.

56

1
2
3
4

CHAPITRE 5. BOUCLES ET IMPORTATION DE MODULES

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

Cours 4 e x e r c i c e b o u c l e f o r , FM synth .

5
6
7
8

from pyo import


import random

9
10

s = S e r v e r ( ) . boot ( )

11
12
13
14
15
16
17
18

car
rat
ind
for

= []
= []
= []
i in range (10) :
c a r . append ( random . t r i a n g u l a r ( 1 5 0 , 1 5 5 ) )
r a t . append ( random . c h o i c e ( [ . 2 5 , . 5 , 1 , 1 . 2 5 , 1 . 5 , 2 ] ) )
i n d . append ( random . r a n d i n t ( 2 , 6 ) )

19
20
21
22

print Carrier : , car


p r i n t Ratio : , r a t
p r i n t Index : , i n d

23
24

fm = FM( c a r r i e r=car , r a t i o=r a t , i n d e x=ind , mul =.05) . out ( )

25
26

s . gui ( l o c a l s () )

scripts/chapitre 05/04 boucle for FM.py

5.4.2

Les g
en
erateurs de listes (list comprehension)

Parfois, les operations necessaires `


a la generation dune liste ne necessite pas plusieurs lignes
de code. Il est alors possible dinserer lexpression `a meme un generateur de liste. Cette technique
permet par exemple de creer un immense chorus en une seule ligne :
a = FM( [ random . un ifo rm ( 2 4 0 , 2 6 0 ) f o r i i n r a n g e ( 2 0 0 ) ] , mul =.005) . out ( )

200 synth`eses FM ont ete crees par cette ligne.


On pourrait reproduire lexemple de synth`ese par modulation de frequence `a laide des
generateurs de listes :
1
2

from pyo import


import random

3
4

s = S e r v e r ( ) . boot ( )

5
6
7
8

fm = FM( c a r r i e r =[random . t r i a n g u l a r ( 1 5 0 , 1 5 5 ) f o r i i n r a n g e ( 1 0 ) ] ,
r a t i o =[random . c h o i c e ( [ . 2 5 , . 5 , 1 , 1 . 2 5 , 1 . 5 , 2 ] ) f o r i i n r a n g e ( 1 0 ) ] ,
i n d e x =[random . r a n d i n t ( 2 , 6 ) f o r i i n r a n g e ( 1 0 ) ] , mul =.05) . out ( )

9
10

s . gui ( l o c a l s () )

scripts/chapitre 05/05 listComp FM.py

5.4. PRATIQUE

57

Exercices
1 - Dans le script suivant, vous devez remplacer les 3 lignes vides (...) de facon `a ce que
votre script gen`ere un chorus de 10 voix (vitesses leg`erement differentes) par la lecture dun son
en boucle sur le disque dur. Vous devez creer un mix mono `a partir du chorus et ensuite lui
appliquer une harmonisation `
a 3 voix comportant loctave inferieur (-12), la tierce superieure
(4) et la quinte superieure (7). Faites attention aux amplitudes ! La repartition des voix se fait
comme suit :
` gauche : Le chorus original et la quinte superieure.
A
` droite : Loctave inferieur et la tierce superieure.
A
from pyo import
from random import uni for m
s = S e r v e r ( ) . boot ( )
...
...
...
s . gui ( l o c a l s () )

2.1 - Sachant quune onde carree nest composee que dharmoniques impairs dont les amplitudes correspondent `
a linverse de leur rang, quels seraient les generateurs de listes qui nous
permettraient dobtenir les frequences et les amplitudes correspondantes dun tel son ?
Pour une fondamentale de 100 Hz, on veut les composantes suivantes :
100
300
500
700
...

Hz,
Hz,
Hz,
Hz,

amplitude
amplitude
amplitude
amplitude

=
=
=
=

1
1/3.
1/5.
1/7.

2.2 - Transformez vos generateurs de listes afin de creer un chorus de cette note... !
Les solutions en page 62.

5.4.3

Variations continues des param`


etres `
a laide dobjets pyo

Un son naturel nest pas statique, il est generalement en constante evolution. Que ce soit par
de leg`eres variations de frequence ou damplitude, le timbre dun son varie au cours du temps.
Nous allons maintenant commencer `a utiliser des objets pyo dans le but de creer des trajectoires
de controle, cest-`
a-dire des signaux audio non pas destines `a lenvoi vers les haut-parleurs mais
plutot `a creer des variations de param`etres dans le temps. Lutilisation en est fort simple. Si le
manuel specifie quun argument accepte les floats ou les PyoObjects, alors il est permis de
lui donner un objet pyo prealablement cree. Pour donner une leg`ere variation de frequence `
a un
oscillateur, le script suivant cree un objet qui gen`ere des valeurs aleatoires continues (Randi)
que lon assigne `
a largument freq dun oscillateur :

58

1
2

CHAPITRE 5. BOUCLES ET IMPORTATION DE MODULES

from pyo import


s = S e r v e r ( ) . boot ( )

3
4
5

rnd = Randi ( min=390 , max=410 , f r e q =4)


a = S i n e ( f r e q=rnd , mul =.5) . out ( )

6
7

s . gui ( l o c a l s () )

scripts/chapitre 05/09 randi.py


4 fois par seconde, Randi pige une nouvelle valeur entre 390 et 410 et interpole lineairement
de la valeur courante `
a la valeur pigee.
G
en
eration dune note chorussee
Il faut se rappeler quun objet pyo est considere comme une liste (la longueur de la liste

correspond au nombre de streams audio quil contient). Etant


considere comme une liste, si on
assigne `a un argument un objet audio dune longueur x, lobjet nouvellement cree contiendra
lui aussi x streams audio. Cest une arme `a double tranchant ! Il est tr`es facile de saturer le
processeur par une demultiplication des calculs mais il est aussi tr`es aise de construire des
sonorites complexes en quelques lignes. Voici un exemple dune note chorussee :
1
2

from pyo import


import random

3
4

s = S e r v e r ( ) . boot ( )

5
6
7
8

f r = Randi ( min=295 , max=300 , f r e q =[random . uni for m ( 2 , 8 ) f o r i i n r a n g e ( 1 0 0 ) ] )


s i n e s = SineLoop ( f r , f e e d b a c k =.08 , mul =.01) . out ( )
print len ( sines )

9
10

s . gui ( l o c a l s () )

scripts/chapitre 05/10 var freqs.py


Lobjet Randi, en recevant une liste de 100 valeurs `a largument freq, creera 100 variations
aleatoires. En assignant cet objet au param`etre freq dun oscillateur, celui-ci gen`erera automatiquement 100 oscillateurs de frequences differentes. Prenez garde `a lamplitude !
Un exemple similaire, cette fois-ci les variations sont appliquees `a lamplitude de 10 oscillateurs :
1
2

from pyo import


import random

3
4

s = S e r v e r ( ) . boot ( )

5
6
7

amp = Randi ( min=0, max=.05 , f r e q =[random . un ifo rm ( . 2 5 , 1 ) f o r i i n r a n g e ( 1 0 ) ] )


s i n e s = SineLoop ( f r e q =[ i 100+50 f o r i i n r a n g e ( 1 0 ) ] , f e e d b a c k =.03 , mul=amp) . out ( )

8
9

s . gui ( l o c a l s () )

scripts/chapitre 05/11 var amps.py

5.4. PRATIQUE

59

Exercices
1. Pour les deux exemples precedents, testez differentes valeurs aux arguments min, max et
freq des objets Randi afin de figurer limpact de chacun sur le resultat sonore.
2. Remplacez les objets Randi par des objets Randh, quelle est la difference ?
G
en
eration de nombres al
eatoires pr
ed
etermin
es
Il est parfois desirable de pouvoir predire, dans une certaine mesure, la teneur dune generation
aleatoire. La generation dune harmonie est un cas de figure o`
u les valeurs de frequence ne peuvent pas etre simplement soumises au hasard. Lobjet Choice nous permet de specifier, `a laide
dune liste, les valeurs qui pourront sortir de la pige. Voici un petit exemple, `a 4 voix de polyphonie, o`
u les frequences sont restreintes `a des notes de la gamme de Do majeur :
1

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5
6
7

p i t s = [ midiToHz (m) f o r m i n [ 3 6 , 4 3 , 4 8 , 5 5 , 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]
c h o i x = Choice ( c h o i c e=p i t s , f r e q = [ 1 , 2 , 3 , 4 ] )
s i n e s = SineLoop ( f r e q=c h o i x , f e e d b a c k =.05 , mul =.1) . out ( )

8
9

s . gui ( l o c a l s () )

scripts/chapitre 05/12 carillon.py


La fonction midiToHz convertit une valeur de note Midi (un entier entre 0 et 127) en la
frequence correspondante en Hertz.

5.4.4

Exemples et exercices

Exercices
1. Reprendre les exercices precedents et remplacer les sources sonores pour tester avec differentes
sonorites.
2. Appliquer des generateurs aleatoires sur les differents param`etres de controle des sources.
Explorer les objets de la categories randoms de pyo.
* Attention * Cest `
a partir dici que cest dangereux pour vos oreilles ! Verifiez `
a bas
volume si vos automations ne provoquent pas des ecarts dynamiques trop grands.
3. Completer les chanes de traitement par lajout deffets. Les categories filters, effects et
dynamics offrent plusieurs processus de transformation du signal.
Exemples
Lexemple ci-dessous se base sur les 4 voix de polyphonie, avec pige de frequences aleatoires
sur la gamme de Do, de la page precedente.
p i t s = [ midiToHz (m) f o r m i n [ 3 6 , 4 3 , 4 8 , 5 5 , 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]
c h o i x = Choice ( c h o i c e=p i t s , f r e q = [ 1 , 2 , 3 , 4 ] )
s i n e s = SineLoop ( f r e q=c h o i x , f e e d b a c k =.05 , mul =.1) . out ( )

60

CHAPITRE 5. BOUCLES ET IMPORTATION DE MODULES

Dans un premier, doublons la source `a laide dun generateur de synth`ese par modulation de
frequence (FM). En prime, un petit portamento a ete ajoute aux changements de frequences
afin deliminer les clics potentiels.
p i t s = [ midiToHz (m) f o r m i n [ 3 6 , 4 3 , 4 8 , 5 5 , 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]
c h o i x = Choice ( c h o i c e=p i t s , f r e q = [ 1 , 2 , 3 , 4 ] )
# P e t i t t r u c , un portamento s u r l e s changements de f r e q u e n c e e l i m i n e l e s c l i c s !
c h p o r t = Port ( c h o i x , r i s e t i m e =.001 , f a l l t i m e =.001)
s i n e s = SineLoop ( f r e q=c h p o r t , f e e d b a c k =.05 , mul =.1) . out ( )
# Seconde s o u r c e , s y n t h e s e FM
fms = FM( c a r r i e r=c h p o r t , r a t i o =1.0025 , i n d e x =4 , mul =.025) . out ( )

Ajoutons deux automations sur le feedback du SineLoop et sur lindex de la modulation de


frequence. Les deux LFO sont en inversion de phase afin dalterner la predominance dune source
par rapport `
a lautre.
p i t s = [ midiToHz (m) f o r m i n [ 3 6 , 4 3 , 4 8 , 5 5 , 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]
c h o i x = Choice ( c h o i c e=p i t s , f r e q = [ 1 , 2 , 3 , 4 ] )
c h p o r t = Port ( c h o i x , r i s e t i m e =.001 , f a l l t i m e =.001)
# LFO, en phase , s u r l e f e e d b a c k du SineLoop
l f f e e d = S i n e ( f r e q =0.1 , mul =.07 , add =.07)
s i n e s = SineLoop ( f r e q=c h p o r t , f e e d b a c k=l f f e e d , mul =.1) . out ( )
# LFO, h o r s phase , s u r l i n d e x de l a FM
l f i n d = S i n e ( f r e q =0.1 , phase =0.5 , mul=3, add=3)
fms = FM( c a r r i e r=c h p o r t , r a t i o =1.0025 , i n d e x=l f i n d , mul =.025) . out ( )

Ajoutons maintenant un premier effet, un effet de flange, cree `a laide du ligne de delai
dont le temps de delai varie dans le temps. Tout dabord, il ne faut pas oublier de mixer les
streams audio en stereo si necessaire (nous avons 4 voix de polyphonie) et de sommer les sources.
Puis nous ajoutons le delai avec un LFO sinusodal sur le param`etre delay, ce qui aura pour effet
un balayage du spectre par un filtre en peigne. Notez que les methodes out() ont ete retirees des
objets SineLoop et FM pour nagir que sur la somme des deux sources.
p i t s = [ midiToHz (m) f o r m i n [ 3 6 , 4 3 , 4 8 , 5 5 , 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]
c h o i x = Choice ( c h o i c e=p i t s , f r e q = [ 1 , 2 , 3 , 4 ] )
c h p o r t = Port ( c h o i x , r i s e t i m e =.001 , f a l l t i m e =.001)
l f f e e d = S i n e ( f r e q =0.1 , mul =.07 , add =.07)
s i n e s = SineLoop ( f r e q=c h p o r t , f e e d b a c k=l f f e e d , mul =.1)
l f i n d = S i n e ( f r e q =0.1 , phase =0.5 , mul=3, add=3)
fms = FM( c a r r i e r=c h p o r t , r a t i o =1.0025 , i n d e x=l f i n d , mul =.025)
# A d d i t i o n du mix s t e r e o d e s deux s o u r c e s
s r c s u m = s i n e s . mix ( 2 ) + fms . mix ( 2 )
# D e l a i avec LFO s u r l e temps de d e l a i pour c r e e r un e f f e t de f l a n g e
l f d e l = S i n e ( . 1 , mul =.003 , add =.005)
comb = Delay ( src sum , d e l a y=l f d e l , f e e d b a c k =.5) . out ( )
# Envoie l a somme aux hautp a r l e u r s
s r c s u m . out ( )

Finalement, on dirige le signal vers une reverberation qui assumera la balance entre le signal
original et le signal reverbere ainsi que lenvoie au haut-parleurs. Voici la version finale de notre
programme :

5.4. PRATIQUE

61

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5

p i t s = [ midiToHz (m) f o r m i n [ 3 6 , 4 3 , 4 8 , 5 5 , 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]

6
7
8

c h o i x = Choice ( c h o i c e=p i t s , f r e q = [ 1 , 2 , 3 , 4 ] )
c h p o r t = Port ( c h o i x , r i s e t i m e =.001 , f a l l t i m e =.001)

9
10
11

l f f e e d = S i n e ( f r e q =0.1 , mul =.07 , add =.07)


s i n e s = SineLoop ( f r e q=c h p o r t , f e e d b a c k=l f f e e d , mul =.1)

12
13
14

l f i n d = S i n e ( f r e q =0.1 , phase =0.5 , mul=3, add=3)


fms = FM( c a r r i e r=c h p o r t , r a t i o =1.0025 , i n d e x=l f i n d , mul =.025)

15
16

s r c s u m = s i n e s . mix ( 2 ) + fms . mix ( 2 )

17
18
19

l f d e l = S i n e ( . 1 , mul =.003 , add =.005)


comb = Delay ( src sum , d e l a y=l f d e l , f e e d b a c k =.5)

20
21
22
23
24

# Sommation d e s s o u r c e s e t du d e l a i
out sum = s r c s u m + comb
# Envoie v e r s l e r e v e r b e e t s o r t i e du s i g n a l
r e v = WGVerb( out sum , f e e d b a c k =.8 , c u t o f f =3500 , b a l =.4) . out ( )

25
26

s . gui ( l o c a l s () )

scripts/chapitre 05/13 exemple final.py

62

5.4.5
1
2
3
4

CHAPITRE 5. BOUCLES ET IMPORTATION DE MODULES

Solutions aux exercices sur les lists comprehension

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

S o l u t i o n pour l e x e r c i c e 1 s u r l e s

l i s t s comprehension .

5
6
7
8

from pyo import


from random import uni for m

9
10

s = S e r v e r ( ) . boot ( )

11
12
13
14
15

s f = S f P l a y e r (SNDS PATH+ / t r a n s p a r e n t . a i f , l o o p=True , mul =.07 ,


s p e e d =[ uni for m ( . 9 9 , 1 . 0 1 ) f o r i i n r a n g e ( 1 0 ) ] ) . mix ( 1 )
s f . out ( )
harm = Harmonizer ( s f , t r a n s p o = [ 1 2 , 7 , 4 ] , mul =.4) . out ( 1 )

16
17

s . gui ( l o c a l s () )

scripts/chapitre 05/06 ex 1 listComp.py

1
2
3
4

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

S o l u t i o n pour l e x e r c i c e 2 . 1 s u r l e s

l i s t s comprehension .

5
6
7
8

from pyo import


from random import uni for m

9
10

s = S e r v e r ( ) . boot ( )

11
12
13
14
15
16
17

max harms = 20
f r e q s = [ i 100 f o r i i n r a n g e ( max harms ) i f ( i %2) == 1 ]
amps = [ 0 . 3 5 / i f o r i i n r a n g e ( max harms ) i f ( i %2) == 1 ]
p r i n t Frequences : , f r e q s
p r i n t Amplitudes : , amps
a = S i n e ( f r e q=f r e q s , mul=amps ) . mix ( 1 ) . out ( )

18
19

s . gui ( l o c a l s () )

scripts/chapitre 05/07 ex 2 1 listComp.py

5.4. PRATIQUE

1
2
3
4

63

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

S o l u t i o n pour l e x e r c i c e 2 . 2 s u r l e s

l i s t s comprehension .

5
6
7
8

from pyo import


from random import uni for m

9
10

s = S e r v e r ( ) . boot ( )

11
12

max harms = 20

13
14
15

f r e q s = [ i 100 un ifo rm ( . 9 9 , 1 . 0 1 )
f o r i i n r a n g e ( max harms ) f o r j i n r a n g e ( 1 0 ) i f ( i %2) == 1 ]

16
17

amps = [ 0 . 0 3 5 / i f o r i i n r a n g e ( max harms ) f o r j i n r a n g e ( 1 0 ) i f ( i %2) == 1 ]

18
19
20

p r i n t Frequences : , f r e q s
p r i n t Amplitudes : , amps

21
22

a = S i n e ( f r e q=f r e q s , mul=amps ) . mix ( 1 ) . out ( )

23
24

s . gui ( l o c a l s () )

scripts/chapitre 05/08 ex 2 2 listComp.py

64

CHAPITRE 5. BOUCLES ET IMPORTATION DE MODULES

Chapitre 6

Les fonctions
Ce cours elabore sur la creation de fonctions personnalisees et lutilisation de celles-ci `
a
linterieur dun script.

6.1

Fonction simple sans param`


etre

Creer une fonction consiste `


a regrouper un certain nombres doperations, reliees entre elles,
effectuant un processus particulier. Une fonction prealablement definie peut-etre appelee nimporte o`
u dans un script, permettant une ecriture compacte et efficace des programmes. Le
groupe doperations peut ne comporter que quelques lignes ou etre un regroupement complexe
doperations setendant sur plusieurs centaines de lignes. Voici un exemple simple de fonction
sans param`etre et son utilisation dans un script :
from math import s q r t
def racine carree
print racine
print racine
print racine

2 4 () :
c a r r e e de 2 : %f % s q r t ( 2 )
c a r r e e de 3 : %f % s q r t ( 3 )
c a r r e e de 4 : %f % s q r t ( 4 )

racine carree 2 4 ()

Noter la creation dun bloc dinstructions avec les deux-points terminant la ligne den-tete
et lindentation du bloc.
Cette fonction ne fait quimprimer les racines carrees des nombres 2 `a 4, mais elle illustre
dej`a la syntaxe de base necessaire `
a la creation dune fonction. Celle-ci commence toujours par le
mot-cle def suivit du nom de la fonction et de parenth`eses (nous verrons plus loin quelles ne sont
pas toujours vides). Les deux-points terminent la ligne den-tete et toutes les lignes indentees
qui suivent constituent le bloc dinstructions qui sera execute chaque fois que la fonction sera
appelee. Pour terminer la construction de la fonction, il suffit de revenir `a la ligne dindentation
principale.
65

66

6.2

CHAPITRE 6. LES FONCTIONS

Fonction avec param`


etres

Lors de la creation dune fonction, il est possible de specifier des param`etres en leur attribuant
un argument entre les parenth`eses. Les arguments prendront les valeurs donnees lors de lappel
de la fonction et pourront etre utilises comme des variables normales dans lexecution du bloc
dinstructions. Ceci permet dappliquer une suite doperations sur differentes valeurs simplement
en variant les param`etres donnes `
a lappel.
from math import s q r t
def racine carree (x) :
p r i n t r a c i n e c a r r e e de %f : %f % ( x , s q r t ( x ) )
racine carree (25)
racine carree (12)

Si plus dun param`etre sont necessaires au bon deroulement de la fonction, il suffit de les
separer par une virgule entre les parenth`eses.
from math import s q r t
d e f r a c i n e s c a r r e ( mini , maxi ) :
p r i n t l e s r a c i n e s c a r r e e s d e s nombre e n t r e %d e t %d s o n t : % ( mini , maxi )
f o r i i n r a n g e ( mini , maxi ) :
print sqrt ( i ) ,
r a c i n e s c a r r e (5 , 10)

6.3

Valeurs par d
efaut des param`
etres

Une fonctionnalite particuli`erement interessante consiste `a donner des valeurs par defaut
aux param`etres dune fonction. Ceci permet domettre certains param`etres lors de lappel sans
creer derreurs dexecution. Une fonction peut donc etre creee en donnant beaucoup de latitude
` la creation
`a lutilisateur tout en lui permettant de lutiliser dans des variantes plus simples. A
de la fonction, on attribue une valeur par defaut `a un param`etre en faisant suivre largument
correspondant du signe = puis de la valeur desiree.
d e f p u i s s a n c e ( x , exp =2) :
p r i n t %.2 f e x p o s a n t %.2 f donne : %.2 f % ( x , exp , pow ( x , exp ) )
puissance (5)
puissance (2 , 16)
p u i s s a n c e ( 2 , exp =32)
p u i s s a n c e ( x=3 , exp =2)
p u i s s a n c e ( exp =3 , x=2)

On constate quil y a plusieurs facons differentes dappeler cette fonction. On peut specifier
seulement le param`etre sans valeur par defaut, ou bien specifier les deux valeurs (la valeur
donnee `a largument exp remplace la valeur par defaut). Il est aussi possible de faire directement
reference `a la variable dont on veut specifier la valeur avec la syntaxe nom de la variable=valeur.

6.4. VARIABLES LOCALES ET VARIABLES GLOBALES

67

Quelques r`
egles `
a respecter
1. Lors de la definition dune fonction, les param`etres sans valeur par defaut doivent preceder
les param`etres avec valeur par defaut.
2. Lors de lappel, si on ne fait pas reference aux noms des variables, les valeurs doivent etre
specifiees dans lordre.
3. Lors de lappel, on ne peut definir un param`etre en specifiant le nom de la variable et ensuite
attribuer une valeur `
a un param`etre sans specifier explicitement son nom. Lorsquun nom
de variable est donne, lordre des param`etres nest plus respecte, alors linterpreteur ne
saura pas `
a quel param`etre attribuer la valeur.

6.4

Variables locales et variables globales

` ce moment-ci, il est important de comprendre comment se partage les espaces de noms en


A
Python. Les espaces de noms sont des registres o`
u sont enregistrees les variables specifiques `
a
certains environnements, par exemple les differentes fonctions et classes. Afin deviter les conflits
entre des variables portant le meme nom, linterpreteur parcours les espaces de noms dans un
ordre precis pour identifier les differentes variables. En r`egle generale, linterpreteur recherche
dans lespace le plus local possible, et sil ne trouve pas la variable demandee, il remonte les
etages jusqu`
a lespace de noms global. Nous aurons loccasion dy revenir et dapprofondir un
peu plus ce sujet lorsque nous parlerons des classes et des objets. Pour linstant, deux types de
variables nous interessent plus particuli`erement, les variables locales et les variables globales.
Une variable globale est une variable definie au premier niveau dindentation dun script,
donc accessible nimporte o`
u dans le script, tandis quune variable locale est une variable definie
`a linterieur dune fonction et nest accessible que dans la fonction elle-meme. Il est donc tout `
a
fait possible quune variable initialisee au debut dun script porte un nom x, et quune variable
portant le meme nom soit definie `
a linterieur dune fonction, et ce, sans creer de conflit. Il faut
cependant avoir conscience de lespace de noms o`
u lon se trouve afin de savoir quelle est la
valeur reelle de la variable que lon utilise. Petit exemple :
>>>
>>>
...
...
>>>
>>>
1

a = 1
def f () :
a = 2
f ()
print a

Dans cet exemple, une variable a est initialisee `a la valeur 1, puis une fonction, donnant
la valeur 2 `
a une variable a, est appelee. Ensuite, la valeur de la variable a est affichee et on
constate quelle est de 1, et non de 2, meme si la derni`ere operation effectuee sur une variable
a est une affectation de la valeur 2. La raison est que ces deux variables ne font pas partie du
meme espace de noms, la premi`ere fait partie de lespace de noms global du script, tandis que
la deuxi`eme fait partie de lespace local de la fonction. Ce sont donc deux variables distinctes.

68

>>>
>>>
...
...
...
>>>
2
>>>
1

CHAPITRE 6. LES FONCTIONS

a = 1
def f () :
a = 2
print a
f ()
print a

Bien que la variable definie dans la fonction ne soit pas accessible de lexterieur, le contraire
est tout `a fait possible. Cest `
a dire quil est permis dacceder `a la valeur dune variable faisant
partie de lespace de noms global `
a linterieur dune fonction, sans pouvoir la modifier... pour
linstant.
>>> a = 1
>>> d e f f ( ) :
...
print a
...
>>> f ( )
1

Si lon desire agir sur le contenu dune variable globale `a linterieur dune fonction, il faut
la declarer variable globale `
a linterieur meme de la fonction. Cette declaration sop`ere avec
le mot-cle global et indique `
a linterpreteur de ne pas creer une nouvelle variable locale mais
dutiliser, et de modifier, la variable globale.
>>>
>>>
...
...
...
>>>
>>>
2

6.5

a = 1
def f () :
global a
a = 2
f ()
print a

Utilisation des fonctions avec retour de valeur

Lutilite principale dune fonction est deffectuer des operations sur des param`etres et de
fournir un resultat. Ce resultat peut etre retourne par la fonction et place en memoire dans une
autre variable, pouvant etre utilisee telle quelle dans la suite du programme. Lorsque le mot-cle
return est rencontre dans une fonction, celui-ci termine la fonction et retourne la ou les valeurs
qui le suivent, sil y en a. On peut affecter, avec le symbole =, le retour dune fonction `a une
variable. Cette operation est illustree dans lextrait suivant.

6.6. PRATIQUE

>>>
>>>
...
...
>>>
>>>
1
>>>
>>>
2

69

a = 0
def increment ( x ) :
return x + 1
a = increment ( a )
print a
a = increment ( a )
print a

Le retour dune fonction peut etre une valeur de nimporte quel type, par exemple, une liste :
a = 16
d e f l i s t e p u i s s a n c e 2 ( exp ) :
exposants = [ ]
f o r i i n r a n g e ( 1 , exp +1) :
e x p o s a n t s . append ( i 2 )
return exposants
maListe = l i s t e p u i s s a n c e 2 ( a )

6.6
6.6.1

Pratique
Utilisation des fonctions dans un script

Nous allons maintenant explorer linteraction avec le signal audio dun script `a laide de
fonctions prealablement definies. Comme premier exemple, nous allons definir 3 sources sonores
(un son, une synth`ese FM et une synth`ese additive) qui seront activees `a tour de role par lappel
dune fonction. Les trois sources :
1
2
3

from pyo import


import random
s = S e r v e r ( ) . boot ( )

4
5
6
7
8
9
10
11
12

# l e c t u r e d un f i c h i e r son
snd = S f P l a y e r (SNDS PATH + / a c c o r d . a i f , s p e e d = [ . 9 9 8 , 1 . 0 0 3 ] ,
l o o p=True , mul =.35) . s t o p ( )
# s y n t h e s e FM
fm = FM( c a r r i e r = [ 9 9 , 9 9 . 7 , 1 0 0 , 1 0 0 . 4 , 1 0 0 . 9 ] , r a t i o =.4987 , i n d e x =8, mul =.1) . s t o p ( )
# synthese additive
adsyn = SineLoop ( f r e q =[random . u nif or m ( 1 4 5 , 1 5 5 ) f o r i i n r a n g e ( 2 0 ) ] ,
f e e d b a c k =.15 , mul =.05) . s t o p ( )

13
14

s . gui ( l o c a l s () )

scripts/chapitre 06/01 interaction 1.py


Notez lappel de la methode stop sur chacune des sources. Ceci aura pour effet de ne pas
lancer le calcul des echantillons automatiquement (la methode play est presque toujours appelee
d`es la creation dun objet).

70

CHAPITRE 6. LES FONCTIONS

Utilisation de lentr
ee-texte dans la fen
etre du serveur
Maintenant que nous avons connaissance des espaces de noms de Python, nous pouvons
eclaircir largument de la methode gui de lobjet Server. locals est une fonction integree de
Python qui retourne toutes les variables jusqualors definies dans lespace de noms courant
(lespace de noms du script dans la plupart des cas). Ainsi, toutes les variables definies avant
lappel de la fenetre du serveur sont connues de lentree-texte, qui est ni plus ni moins quune
extension de linterpreteur. Il est donc possible de lancer de nouvelles commandes `a partir de cet
outils. Cela servira `
a modifier letat de certains objets ou `a lancer des fonctions prealablement
definies. Par exemple, pour demarrer le calcul de la synth`ese FM, on ecrira, suivi de la touche
 enter  :
fm . out ( )

Ajoutons une fonction `


a notre script permettant de demarrer une source tout en arretant
celle qui jouait precedemment. Un argument servira `a determiner quelle source doit jouer. Cette
fonction sins`ere apr`es la definition des sources et avant laffichage de la fenetre du serveur.
1
2
3

from pyo import


import random
s = S e r v e r ( ) . boot ( )

4
5
6
7
8
9
10
11
12

# l e c t u r e d un f i c h i e r son
snd = S f P l a y e r (SNDS PATH + / a c c o r d . a i f , s p e e d = [ . 9 9 8 , 1 . 0 0 3 ] ,
l o o p=True , mul =.35) . s t o p ( )
# s y n t h e s e FM
fm = FM( c a r r i e r = [ 9 9 , 9 9 . 7 , 1 0 0 , 1 0 0 . 4 , 1 0 0 . 9 ] , r a t i o =.4987 , i n d e x =8, mul =.1) . s t o p ( )
# synthese additive
adsyn = SineLoop ( f r e q =[random . uni for m ( 1 4 5 , 1 5 5 ) f o r i i n r a n g e ( 2 0 ) ] ,
f e e d b a c k =.15 , mul =.05) . s t o p ( )

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# s r c > { snd , fm , adsyn }


d e f p l a y ( s r c= snd ) :
i f s r c == snd :
snd . out ( )
fm . s t o p ( )
adsyn . s t o p ( )
e l i f s r c == fm :
snd . s t o p ( )
fm . out ( )
adsyn . s t o p ( )
e l i f s r c == adsyn :
snd . s t o p ( )
fm . s t o p ( )
adsyn . out ( )

28
29

s . gui ( l o c a l s () )

scripts/chapitre 06/02 interaction 2.py


Afin dadoucir les entrees et sorties de son dans notre programme, nous allons appliquer une
enveloppe damplitude `
a chacune de nos sources. Lobjet Fader permet de definir un temps de
montee (declenche par la methode play) et un temps de chute (declenche par la methode stop)

6.6. PRATIQUE

71

dun contr
ole damplitude qui sera assigne `a largument mul de la source. Nul besoin dappeler
la methode stop sur les objets Fader, cest un des rares cas o`
u la methode play nest pas appelee
automatiquement `
a la creation de lobjet. Cette fois-ci, nous laisserons les sources jouer en
permanence et ne contr
olerons que les amplitudes via la fonction de controle.
1
2
3

from pyo import


import random
s = S e r v e r ( ) . boot ( )

4
5
6
7
8
9
10
11
12
13

snd amp = Fader ( f a d e i n =5, f a d e o u t =5 , dur =0)


snd = S f P l a y e r (SNDS PATH + / a c c o r d . a i f , s p e e d = [ . 9 9 8 , 1 . 0 0 3 ] ,
l o o p=True , mul=snd amp . 3 5 ) . out ( )
fm amp = Fader ( f a d e i n =5 , f a d e o u t =5 , dur =0)
fm = FM( c a r r i e r = [ 9 9 , 9 9 . 7 , 1 0 0 , 1 0 0 . 4 , 1 0 0 . 9 ] , r a t i o =.4987 , i n d e x =8,
mul=fm amp . 1 ) . out ( )
adsyn amp = Fader ( f a d e i n =5 , f a d e o u t =5 , dur =0)
adsyn = SineLoop ( f r e q =[random . u nif or m ( 1 4 5 , 1 5 5 ) f o r i i n r a n g e ( 2 0 ) ] ,
f e e d b a c k =.15 , mul=adsyn amp . 0 5 ) . out ( )

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# s r c > { snd , fm , adsyn }


def play ( s r c ) :
i f s r c == snd :
snd amp . p l a y ( )
fm amp . s t o p ( )
adsyn amp . s t o p ( )
e l i f s r c == fm :
snd amp . s t o p ( )
fm amp . p l a y ( )
adsyn amp . s t o p ( )
e l i f s r c == adsyn :
snd amp . s t o p ( )
fm amp . s t o p ( )
adsyn amp . p l a y ( )

29
30

s . gui ( l o c a l s () )

scripts/chapitre 06/03 interaction 3.py

6.6.2

Appel automatique dune fonction avec lobjet Pattern

Le processus de lobjet Pattern est dappeler une fonction de facon cyclique. Largument
function prend le nom dune fonction prealablement definie (notez bien quil ny a pas de parenth`eses, cest une reference et non un appel) et largument time, le temps ecoule entre chaque
appel. Voici comment nous allons creer cet objet :
pat = P a t t e r n ( f u n c t i o n=play , time =6) . p l a y ( )

La fonction play sera appelee `


a toutes les 6 secondes, sans param`etre. Nous allons donc devoir
modifier cette derni`ere afin deliminer le param`etre qui pointe sur une source. Nous allons plut
ot
creer un mecanisme qui pige une source au hasard :

72

CHAPITRE 6. LES FONCTIONS

l a s t = None
def play ( ) :
global last
s r c = random . c h o i c e ( [ snd , fm , adsyn ] )
w h i l e s r c == l a s t :
s r c = random . c h o i c e ( [ snd , fm , adsyn ] )
last = src
i f s r c == snd :
....

Plusieurs elements `
a noter ici. Premi`erement, apr`es avoir choisi un string au hasard dans
la liste des choix possibles (noubliez pas dimporter le module random), on pose une condition
dans une boucle while pour sassurer que la pige nest pas identique `a la precedente. La boucle
executera une nouvelle pige jusqu`
a ce que src ne soit pas egal `a last. Ensuite, on remplace le
contenu de la variable globale last par la nouvelle pige pour preparer la prochaine condition.
1
2
3

from pyo import


import random
s = S e r v e r ( ) . boot ( )

4
5
6
7
8
9

10
11
12

snd amp = Fader ( f a d e i n =5, f a d e o u t =5 , dur =0)


snd = S f P l a y e r (SNDS PATH + / a c c o r d . a i f , s p e e d = [ . 9 9 8 , 1 . 0 0 3 ] ,
l o o p=True , mul=snd amp . 3 5 ) . out ( )
fm amp = Fader ( f a d e i n =5 , f a d e o u t =5 , dur =0)
fm = FM( c a r r i e r = [ 9 9 , 9 9 . 7 , 1 0 0 , 1 0 0 . 4 , 1 0 0 . 9 ] , r a t i o =.4987 , i n d e x =8, mul=fm amp . 1 ) .
out ( )
adsyn amp = Fader ( f a d e i n =5 , f a d e o u t =5 , dur =0)
adsyn = SineLoop ( f r e q =[random . uni for m ( 1 4 5 , 1 5 5 ) f o r i i n r a n g e ( 2 0 ) ] ,
f e e d b a c k =.15 , mul=adsyn amp . 0 5 ) . out ( )

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

l a s t = None
def play ( ) :
global last
s r c = random . c h o i c e ( [ snd , fm , adsyn ] )
w h i l e s r c == l a s t :
s r c = random . c h o i c e ( [ snd , fm , adsyn ] )
last = src
i f s r c == snd :
snd amp . p l a y ( )
fm amp . s t o p ( )
adsyn amp . s t o p ( )
e l i f s r c == fm :
snd amp . s t o p ( )
fm amp . p l a y ( )
adsyn amp . s t o p ( )
e l i f s r c == adsyn :
snd amp . s t o p ( )
fm amp . s t o p ( )
adsyn amp . p l a y ( )

33
34

pat = P a t t e r n ( f u n c t i o n=play , time =6) . p l a y ( )

35
36

s . gui ( l o c a l s () )

scripts/chapitre 06/04 interaction 4.py

6.6. PRATIQUE

73

Les variables definies `


a linterieur dune fonction sont automatiquement detruites lorsque
lexecution de la fonction est terminee, il est donc necessaire de declarer la variable last au
premier niveau dindentation du script. De cette facon, elle sera disponible pour toute la duree
de vie du programme. Par contre, comme nous voulons la modifier `a linterieur de la fonction,
nous devons la declarer comme etant une variable globale. Si on omet la ligne global last, une
nouvelle variable locale `
a la fonction sera creee et ne sera plus disponible au prochain appel.

6.6.3

G
en
eration dune s
equence compos
ee (objet Score)

Lobjet Score permet dorganiser le deroulement dune suite devenements dans le temps.
Largument input attend un signal audio, contenant des entiers, qui peut etre generer soit avec
un objet Counter pour creer un deroulement sequentielle, soit avec un objet RandInt pour
creer un deroulement aleatoire. Un deuxi`eme argument (fname) specifie le nom generique des
fonctions qui seront appelees. Lorsque Score recoit un nouvel entier, la fonction portant le nom
donne en fname, avec comme suffixe lentier en question, est appelee. Voici un script qui illustre
la structure dune organisation sequentielle :
1
2

from pyo import


s = S e r v e r ( ) . boot ( )

3
4
5

def event 0 () :
p r i n t Appel de l a f o n c t i o n 0

6
7
8

def event 1 () :
p r i n t Appel de l a f o n c t i o n 1

9
10
11

def event 2 () :
p r i n t Appel de l a f o n c t i o n 2

12
13
14

def event 3 () :
p r i n t Appel de l a f o n c t i o n 3

15
16
17
18

met = Metro ( time =1) . p l a y ( )


count = Counter ( met , min=0, max=4)
s c o r e = S c o r e ( count , fname= e v e n t )

19
20

s . gui ( l o c a l s () )

scripts/chapitre 06/05 score.py

Variante, avec lobjet Score, de lexercice pr


ec
edemment cr
e
e avec lobjet Pattern
Reprenons nos 3 sources de lexercice precedent et, cette fois-ci, organisons les evenements
dans le temps. Nous allons tout dabord creer une fonction independante pour le controle de
chacune des sources. Nous en profiterons pour glisser un petit element de hasard `a chaque fois
quune source doit demarrer. Si la fonction est appelee avec la valeur 1 en argument (valeur par
defaut), le son joue, sinon, il arrete :

74

CHAPITRE 6. LES FONCTIONS

d e f p l a y s n d ( s t a t e =1) :
i f s t a t e == 1 :
snd . s p e e d = [ random . c h o i c e ( [ . 5 , . 6 7 , . 7 5 , 1 , 1 . 2 5 , 1 . 5 ] ) f o r i i n r a n g e ( 2 ) ]
snd amp . p l a y ( )
else :
snd amp . s t o p ( )
d e f p l a y f m ( s t a t e =1) :
i f s t a t e == 1 :
f r e q = random . r a n d i n t ( 0 , 7 ) 25+50
fm . c a r r i e r = [ f r e q random . u nif orm ( . 9 9 , 1 . 0 1 ) f o r i i n r a n g e ( 5 ) ]
fm amp . p l a y ( )
else :
fm amp . s t o p ( )
d e f p l a y a d s y n ( s t a t e =1) :
i f s t a t e == 1 :
f r e q = random . r a n d i n t ( 0 , 7 ) 25+50
adsyn . f r e q = [ f r e q random . u nif orm ( . 9 9 , 1 . 0 1 ) f o r i i n r a n g e ( 2 0 ) ]
adsyn amp . p l a y ( )
else :
adsyn amp . s t o p ( )

On definit ensuite les fonctions qui seront appelees `a tour de role, ce qui constituera notre
sequence devenements :
def event 0 () :
play fm ( )
def event 1 () :
pass
def event 2 () :
play snd ()
def event 3 () :
play adsyn ()
play fm (0)
def event 4 () :
pass
def event 5 () :
play snd (0)
play fm ( )
def event 6 () :
play adsyn (0)
def event 7 () :
play snd ()
def event 8 () :
play fm (0)
play adsyn ()
def event 9 () :
pass
def event 10 () :
play snd (0)
play adsyn (0)
met . s t o p ( )

6.6. PRATIQUE

75

Finalement, un metronome envoie des clicks `a un objet Counter, qui avance de 1 `a chaque
nouveau click, et le compte est donne `a un objet Score qui appelle les differentes fonctions `
a
tour de r
ole.
met = Metro ( time =5) . p l a y ( )
count = Counter ( met , min=0, max=11)
s c o r e = S c o r e ( count , fname= e v e n t )

Au prochain cours, nous elaborerons plus en detail sur le concept de trigger, le signal audio
qui est au coeur de la synchronicite des evenements dans pyo. Ce signal est genere, entre autre,
par lobjet Metro.
1
2

from pyo import


s = S e r v e r ( ) . boot ( )

3
4
5
6
7
8
9
10
11
12

snd amp = Fader ( f a d e i n =5, f a d e o u t =5 , dur =0)


snd = S f P l a y e r (SNDS PATH + / a c c o r d . a i f , s p e e d = [ . 9 9 8 , 1 . 0 0 3 ] ,
l o o p=True , mul=snd amp . 3 5 ) . out ( )
fm amp = Fader ( f a d e i n =5 , f a d e o u t =5 , dur =0)
fm = FM( c a r r i e r = [ 9 9 , 9 9 . 7 , 1 0 0 , 1 0 0 . 4 , 1 0 0 . 9 ] , r a t i o =.4987 ,
i n d e x =8 , mul=fm amp . 1 ) . out ( )
adsyn amp = Fader ( f a d e i n =5 , f a d e o u t =5 , dur =0)
adsyn = SineLoop ( f r e q =[random . u nif or m ( 1 4 5 , 1 5 5 ) f o r i i n r a n g e ( 2 0 ) ] ,
f e e d b a c k =.15 , mul=adsyn amp . 0 5 ) . out ( )

13
14
15
16
17
18
19

d e f p l a y s n d ( s t a t e =1) :
i f s t a t e == 1 :
snd . s p e e d = [ random . c h o i c e ( [ . 5 , . 6 7 , . 7 5 , 1 , 1 . 2 5 , 1 . 5 ] ) f o r i i n r a n g e ( 2 ) ]
snd amp . p l a y ( )
else :
snd amp . s t o p ( )

20
21
22
23
24
25
26
27

d e f p l a y f m ( s t a t e =1) :
i f s t a t e == 1 :
f r e q = random . r a n d i n t ( 0 , 7 ) 25+50
fm . c a r r i e r = [ f r e q random . u nif orm ( . 9 9 , 1 . 0 1 ) f o r i i n r a n g e ( 5 ) ]
fm amp . p l a y ( )
else :
fm amp . s t o p ( )

28
29
30
31
32
33
34
35

d e f p l a y a d s y n ( s t a t e =1) :
i f s t a t e == 1 :
f r e q = random . r a n d i n t ( 0 , 7 ) 25+50
adsyn . f r e q = [ f r e q random . u nif orm ( . 9 9 , 1 . 0 1 ) f o r i i n r a n g e ( 2 0 ) ]
adsyn amp . p l a y ( )
else :
adsyn amp . s t o p ( )

36
37
38
39
40
41
42

def event 0 () :
play fm ( )
def event 1 () :
pass
def event 2 () :
play snd ()

76

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

CHAPITRE 6. LES FONCTIONS

def event 3 () :
play adsyn ()
play fm (0)
def event 4 () :
pass
def event 5 () :
play snd (0)
play fm ( )
def event 6 () :
play adsyn (0)
def event 7 () :
play snd ()
def event 8 () :
play fm (0)
play adsyn ()
def event 9 () :
pass
def event 10 () :
play snd (0)
play adsyn (0)
met . s t o p ( )

64
65
66
67

met = Metro ( time =5) . p l a y ( )


count = Counter ( met , min=0, max=11)
s c o r e = S c o r e ( count , fname= e v e n t )

68
69

s . gui ( l o c a l s () )

scripts/chapitre 06/06 score audio.py


Bonus : petit exemple de lutilisation de lobjet Pattern controlant une banque de filtres.
1
2

from pyo import


import random

3
4

s = S e r v e r ( ) . boot ( )

5
6
7

a = N o i s e ( mul =.3)
b = Biquad ( a , [ 2 5 0 , 7 0 0 , 1 8 0 0 , 3 0 0 0 ] , q=40 , type =2 , mul=4) . out ( )

8
9
10
11
12
13
14

d e f change ( ) :
f 1 = random . un if orm ( 2 0 0 , 5 0 0 )
f 2 = random . un if orm ( 5 0 0 , 1 0 0 0 )
f 3 = random . un if orm ( 1 0 0 0 , 2 0 0 0 )
f 4 = random . un if orm ( 2 0 0 0 , 4 0 0 0 )
b . f r e q = [ f1 , f2 , f3 , f 4 ]

15
16
17

l f o = S i n e ( . 1 , mul =.5 , add =.75)


pat = P a t t e r n ( change , time=l f o ) . p l a y ( )

18
19

s . gui ( l o c a l s () )

scripts/chapitre 06/07 pattern filtres.py

Chapitre 7

Gestion des r
epertoires et r
evision
7.1

Lire et
ecrire des fichiers sous Python

La fonction open retourne un objet avec lequel on peut lire ou ecrire un fichier sur le disque.
Deux arguments sont necessaires, le premier est un string indiquant le nom du fichier `a lire ou `
a
ecrire, tandis que le deuxi`eme indique le mode, cest `a dire la facon dont on veut interagir avec
le fichier. Si le fichier `
a lire se trouve dans le repertoire courant, il peut etre appele simplement
par son nom, sinon, il faut donner le lien au complet. Le repertoire courant est celui dans lequel
a ete lance la commande python et peut etre retrouve avec la methode getcwd du module os
(os.getcwd()). Les modes possibles, identifies par un string, sont :
r : Ouvre un fichier en lecture seulement.
w : Ouvre un fichier en ecriture seulement (Si un fichier du meme nom existe dej`a, il sera
efface).
a : Ouvre un fichier en mode dajout. Les nouvelles donnees seront ajoutees `a la suite
des donnees dej`
a presentes.
r+ : Ouvre un fichier en lecture et en ecriture.
Sur les syst`emes Windows et Macintosh, si un b est ajoute au mode, le fichier sera ouvert
en format binaire. Ce qui donne les modes rb, wb et r+b.

7.1.1

M
ethodes dun objet fichier

La methode read retourne un string contenant tout le texte contenu dans le fichier. Si la
lecture est dej`
a rendue `
a la fin du fichier, la methode read retourne un string vide.
>>> f = open ( m o n f i c h i e r . t x t , r )
>>> f . r e a d ( )
C e c i e s t l a p r e m i e r e l i g n e du f i c h i e r . \ nEt c e c i e s t l a s e c o n d e ! \ n
>>> f . r e a d ( )

>>>

77

CHAPITRE 7. GESTION DES REPERTOIRES


ET REVISION

78

` noter le symbole du retour de chariot. **


** A
\n

La methode readline lit et retourne une ligne du fichier `a la fois. Comme pour la methode
read , si la lecture est rendue `
a la fin du fichier, un string vide sera retourne.
>>> f = open ( m o n f i c h i e r . t x t , r )
>>> f . r e a d l i n e ( )
C e c i e s t l a p r e m i e r e l i g n e du f i c h i e r . \ n
>>> f . r e a d l i n e ( )
Et c e c i e s t l a s e c o n d e ! \ n
>>> f . r e a d l i n e ( )

>>>

Il est possible de lire toutes les lignes dun fichier et de les memoriser sous forme de liste avec
la methode readlines.
>>> f = open ( m o n f i c h i e r . t x t , r )
>>> f . r e a d l i n e s ( )
[ C e c i e s t l a p r e m i e r e l i g n e du f i c h i e r . \ n , Et c e c i e s t l a s e c o n d e ! \ n ]
>>>

La methode write permet decrire des lignes dans un fichier.


>>> f = open ( m o n f i c h i e r . t x t , w )
>>> f . w r i t e ( H e l l o world ! \ n )
>>>

Lorsque les operations sur un fichier sont terminees, il faut refermer le fichier avec la methode
close.
>>> f = open ( m o n f i c h i e r . t x t , w )
>>> f . w r i t e ( H e l l o world ! \ n )
>>> f . c l o s e ( )
>>> f = open ( m o n f i c h i e r . t x t , r )
>>> s t r = f . r e a d ( )
>>> s t r
H e l l o world ! \ n
>>> f . c l o s e ( )

7.1.2

Exemple concret d
ecriture et de lecture dun fichier texte.

Lexemple suivant illustre la sauvegarde dune sequences de notes, generee `a laide dun
algorithme, dans un fichier texte et la relecture de celui-ci `a des fins musicales. Lavantage de
sauvegarder la sequence dans un fichier texte est que si la sequence generee est interessante, elle
est toujours accessible en format texte, meme apr`es avoir quitte le programme.


7.1. LIRE ET ECRIRE
DES FICHIERS SOUS PYTHON

1
2
3
4
5
6
7
8
9
10

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
###########################################################################
# E c r i t u r e e t l e c t u r e de f i c h i e r s u r l e d i s q u e dur .
#
# 1 G e n e r a t i o n de 4 m e l o d i e s de 16 n o t e s chacune dans un f i c h i e r .
#
# 2 R e l e c t u r e du f i c h i e r e t c o n v e r s i o n d e s l i g n e s en l i s t e d e n t i e r s .
#
# 3 P e t i t a l g o q u i b o u c l e s u r l e s l i s t e s de n o t e s e t c o n t r o l e un synth . #
###########################################################################
from pyo import
import random

11
12

s = S e r v e r ( ) . boot ( )

13
14
15
16
17
18
19

# Do mineur harmonique ( on p i g e l e s n o t e s dans c e t t e l i s t e a l a i d e d un i n d e x )


scale = [36 ,38 ,39 ,41 ,43 ,44 ,47 ,48 ,50 ,51 ,53 ,55 ,56 ,59 ,60 ,62 ,63 ,65 ,67 ,68 ,71 ,72]
# R e f e r e n c e a l a l o n g u e u r de l a l i s t e 1 p a r c e que r a n d i n t i n c l u s l e maximum
maxn = l e n ( s c a l e ) 1
# Index de d e p a r t pour l a g e n e r a t i o n d e s m e l o d i e s
i n d e x = random . r a n d i n t ( 0 , maxn )

20
21
22
23
24
25
26
27
28

# F o n c t i o n de marche a l e a t o i r e ( r e t o u r n e +/ 3 par r a p p o r t a l i n d e x p r e c e d e n t )
d e f drunk ( ) :
g l o b a l index
i n d e x += random . r a n d i n t ( 3 ,3)
i f index < 0 :
i n d e x = abs ( i n d e x )
e l i f i n d e x > maxn :
i n d e x = maxn ( i n d e x maxn )

29
30
31
32
33
34
35
36
37
38

# o uv re un f i c h i e r en mode e c r i t u r e
f = open ( n o t e s . t x t , w )
# g e n e r e 4 l i g n e s de 16 v a l e u r s
f o r i in range (4) :
f o r j in range (16) :
# change l a v a r i a b l e g l o b a l e i n d e x
drunk ( )
f . write ( s t r ( index ) + )
f . w r i t e ( \n )

39
40
41

# f erm e l e f i c h i e r
f . close ()

42
43
44
45
46
47
48

# o uv re l e f i c h i e r en mode l e c t u r e e t r e c u p e r e l e s m e l o d i e s
f = open ( n o t e s . t x t , r )
# chaque l i g n e e s t un e l e m e n t ( l i s t e de 1 6 ) d une l i s t e
mel list = f . readlines ()
# on f erme l e f i c h i e r
f . close ()

49
50
51
52
53
54

# on
mel
# on
mel
# on

e n l e v e l e s r e t o u r s de c h a r i o t
l i s t = [ l . r e p l a c e ( \n , ) f o r l i n m e l l i s t ]
s e p a r e l e s donnees dans chaque l i s t e
l i s t = [ l . s p l i t () for l in m e l l i s t ]
c o n v e r t i t l e s s t r i n g s en e n t i e r s

79

80

55
56
57

CHAPITRE 7. GESTION DES REPERTOIRES


ET REVISION

f o r i in range (4) :
f o r j in range (16) :
mel list [ i ] [ j ] = int ( mel list [ i ] [ j ])

58
59

# m e l l i s t c o n t i e n t 4 l i s t e s de 16 i n d e x pour p o i n t e r dans l a l i s t e s c a l e

60
61
62
63
64
65
66
67
68
69
70

############# P r o c e s s u s a u d i o ( synth o l d s c h o o l ) ###############


# Enveloppe d a m p l i t u d e
f = Fader ( f a d e i n =.005 , f a d e o u t =.05 , dur =.25 , mul =.1)
# 10 f r e q u e n c e s b i d o n s ( pour i n i t i a l i s e r un c h o r u s )
freqs = [100]10
# 10 ondes c a r r e e s
a = LFO( f r e q=f r e q s , s h a r p =.75 , type =2, mul=f )
# synth > d i s t o > r e v e r b
pha = D i s t o ( a . mix ( 2 ) , d r i v e =.85 , s l o p e =.95 , mul =.2)
r e v = WGVerb( pha , f e e d b a c k =.75 , c u t o f f =3000 , b a l =.2) . out ( )

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

############# S e c t i o n c o n t r o l e s ###############
mel = 0 # l a q u e l l e d e s 4 m e l o d i e s
count = 0 # compte d e s temps dans l a m e l o d i e
d e f new note ( ) :
g l o b a l mel , count
# recupere l index courant
i n d = m e l l i s t [ mel ] [ count ]
# r e c u p e r e l a n o t e midi dans l a l i s t e s c a l e
midi = s c a l e [ i n d ]
# c a l c u l de l a f r e q u e n c e en Hertz
f r e q =midiToHz ( midi )
# c h o r u s de 10 n o t e s a u t o u r de l a f r e q u e n c e
f r e q s = [ f r e q random . u nif or m ( . 9 9 , 1 . 0 1 ) f o r i i n r a n g e ( 1 0 ) ]
# Amplitude p l u s grande aux 4 temps ( a c c e n t s u r l e s temps f o r t s )
i f ( count % 4 ) == 0 :
f . mul = . 1
else :
f . mul = . 0 3
# i n c r e m e n t e l e compte
count += 1
# a c t i o n s a l a f i n de l a mesure
i f count == 1 6 :
# r e m e t t r e l e compte a 0
count = 0
# 50% du temps on p i g e une n o u v e l l e m e l o d i e
i f random . r a n d i n t ( 0 , 1 ) == 0 :
mel = random . r a n d i n t ( 0 , 3 )
p r i n t n o u v e l l e l i s t e d i n d e x : , mel
# a s s i g n e l e s f r e q u e n c e s e t demarre l e n v e l o p p e
a . freq = freqs
f . play ( )

103
104
105

# A p p e l l e new note 4 f o i s par s e c o n d e


pat = P a t t e r n ( time =.25 , f u n c t i o n=new note ) . p l a y ( )

106
107

s . gui ( l o c a l s () )

scripts/chapitre 07/01 fichier texte.py


7.2. REVISION

7.2

81

R
evision

Generateur de grains avec delais recursifs. Ce script utilise tous les aspects developpes

jusquici. Etudiez
chaque partie attentivement !
1
2
3

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import

4
5

s = S e r v e r ( ) . boot ( )

6
7
8
9
10
11
12

#########################################################################
### SNDS PATH e s t un s t r i n g pr o v e na n t du module pyo q u i p o i n t e s u r l e ###
### d o s s i e r ou s o n t i n s t a l l e s l e s s o n s f o u r n i s avec pyo . N u t i l i s e r
###
### j a m a i s c e t t e c o n s t a n t e pour l i r e vos p r o p r e s o n s .
###
#########################################################################
son = SNDS PATH+ / t r a n s p a r e n t . a i f

13
14
15
16

# Garde en memoire l a d u r e e du son ( 2 e e l e m e n t de l a l i s t e que r e t o u r n e s n d i n f o )


s o n d u r = s n d i n f o ( son ) [ 1 ]
p r i n t Duree du son : , s o n d u r

17
18
19
20
21

# L i s t e de n o t e s midi pour l e s t r a n s p o s i t i o n p e r m i s e s
mnotes = [ 4 8 , 5 0 , 5 3 , 5 5 , 5 7 , 6 0 , 6 2 , 6 5 , 6 7 , 6 9 , 7 2 ]
# C o n v e r s i o n en f a c t e u r de t r a n s p o s i t i o n a u t o u r de l a n o t e 60
t r a n s p o s = [ midiToTranspo ( x ) f o r x i n mnotes ]

22
23
24
25
26

####### P r o c e s s u s a u d i o #######
# Enveloppe e t l e c t u r e du g r a i n
f = Fader ( f a d e i n =.005 , f a d e o u t =.01 , dur =.02)
s f = S f P l a y e r ( son , s p e e d =1, mul=f )

27
28
29
30
31
32
33
34

# Banque de d e l a i s ( 4 d e l a i s e t f e e d b a c k d i f f e r e n t s )
d l s = Delay ( s f , d e l a y = [ . 1 , . 2 , . 3 , . 4 ] , f e e d b a c k = [ . 2 5 , . 5 , . 3 5 , . 7 5 ] ,
maxdelay =1, mul =.25)
# D i s p o s i t i o n dans l e s p a c e s t e r e o de chacun d e s d e l a i s
pan = Pan ( d l s , pan = [ 0 , . 3 3 , 1 , . 6 6 ] , s p r e a d =.25)
# Reverbe g e n e r a l e , mix ( 2 ) pour une r e v e r b e s t e r e o
r e v = WGVerb( pan . mix ( 2 ) , f e e d b a c k =.8 , c u t o f f =4000 , b a l =.15) . out ( )

35
36
37
38
39
40
41
42
43

####### S e c t i o n c o n t r o l e #######
# g e s t i o n d e s methodes de c o n t r o l e
offset meth = 0
speed meth = 0
# P o s i t i o n du g r a i n dans l e son ( s e c o n d e s ) pour l a methode 1 s u r l o f f s e t
start = 0
# I n c r e m e n t s u r l a p o s i t i o n , en s e c o n d e . Applique a chaque a p p e l de new stream
s t a r t i n c = 0.01

44
45
46
47
48
49

d e f new stream ( ) :
g l o b a l s t a r t # v a r i a b l e g l o b a l e p u i s q u e qu on veut l a m o d i f i e r
# s i o f f s e t m e t h == 0 , on p i g e un p o i n t de l e c t u r e au h a s a r d
# s i n o n , on avance dans l e son en f o n c t i o n de l i n c r e m e n t . On ne
# d e c l a r e pas l i n c r e m e n t g l o b a l p u i s q u on ne l e m o d i f i e pas !

CHAPITRE 7. GESTION DES REPERTOIRES


ET REVISION

82

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

i f o f f s e t m e t h == 0 :
s f . o f f s e t = random . u nif or m ( 0 , s o n d u r .1)
else :
s t a r t += 0 . 0 0 5
i f s t a r t >= ( s o n d u r .1) : # Rendu a l a f i n du son , on r e v i e n t au debut
start = 0
sf . offset = start
# s i speed meth == 0 , on p i g e dans l a l i s t e de t r a n s p o s
# s i n o n , on p i g e une l e g e r e d e v i a t i o n a u t o u r de 1
i f speed meth == 0 :
s f . s p e e d = random . c h o i c e ( t r a n s p o s )
else :
s f . s p e e d = random . u nif orm ( . 9 9 , 1 . 0 1 )
# N o u v e l l e d u r e e de g r a i n
f . dur = random . u nif orm ( . 0 2 , . 1 )
# Af fic hage des n o u v e l l e s v a l e u r s
p r i n t o f f s e t : %.2 f , s p e e d : %.2 f , dur : %.2 f % ( s f . o f f s e t , s f . speed , f . dur )
# On l a n c e l a l e c t u r e du son e t de l e n v e l o p p e
s f . play ( )
f . play ( )

70
71
72
73
74
75

# V a r i a t i o n s s u r l a f r e q u e n c e d e s a p p e l s de l a f o n c t i o n new stream
vtime = Choice ( c h o i c e = [ . 2 , . 4 , . 8 , 1 . 2 , 2 . 4 ] , f r e q = 1 . / 2 . 4 )
# P a t t e r n a p p e l l e de f a c o n p e r i o d i q u e l a f o n c t i o n donnee en argument
# ( new stream s a n s p a r e n t h e s e s ) , demarre l e P a t t e r n avec p l a y ( )
pat = P a t t e r n ( time=vtime , f u n c t i o n=new stream ) . p l a y ( )

76
77

s . gui ( l o c a l s () )

scripts/chapitre 07/02 grains delay.py

Chapitre 8

Les Dictionnaires
Deux nouveaux types de donnees sont presentes dans ce chapitre : le tuple et le dictionnaire.

8.1

Le Tuple

Un tuple, tout comme la liste, est une suite de valeurs separees par des virgules. Par contre,
un tuple est delimite par des parenth`eses et est immuable. Particuli`erement utile pour creer des
listes qui ne doivent en aucun cas etre modifiees, le tuple est aussi plus rapide dacc`es que la
liste.
>>> tup = ( 2 1 , 2 2 , 2 3 , 2 4 , 2 5 , 2 6 )
>>> tup [ 0 ]
21
>>> tup [ 2 : 5 ]
(23 ,24 ,25)
>>> tup2 = ( 2 1 , 1 . 3 3 , b o n j o u r , [ 1 , 2 , 3 ] )
>>> tup2 [ 1 ]
1.330000000000001
>>> tup2 [ 2 : 4 ]
( bonjour , [ 1 , 2 , 3 ] )
>>> tup2 [ 1 ] = A l l o
Traceback ( most r e c e n t c a l l l a s t ) :
F i l e <s t d i n > , l i n e 1 , i n <module>
TypeError : t u p l e o b j e c t d o e s not s u p p o r t item a s s i g n m e n t

8.2

Le dictionnaire

Le dictionnaire est une table de donnees, definie entre accolades {}, sur base de pairs cle valeur. Les pairs sont separees par des virgules et la cle est separee de sa valeur par le symbole
deux-points ( : ).
m o n d i c t = { 1 : 1 0 0 , 2 : 1 0 1 , 3 : 102}

83

84

CHAPITRE 8. LES DICTIONNAIRES

Tous les objets valides en Python peuvent servir de cle dans un dictionnaire (entier, decimale,
string, liste, tuple, objet, function, etc.) On acc`ede aux valeurs dans un dictionnaire en lappelant
et en lui donnant la cle entre crochets.
>>> m o n d i c t = { un : 1 2 3 ,
12: [1 ,2 ,3 ,4 ,5 ,6] ,
( 1 , 2 ) : H e l l o World ! }
>>> p r i n t m o n d i c t [ un ]
123
>>> p r i n t m o n d i c t [ 1 2 ]
[1 ,2 ,3 ,4 ,5 ,6]
>>> p r i n t m o n d i c t [ ( 1 , 2 ) ]
H e l l o world !

Pour des cles qui sont de simples strings, il est possible de specifier les pairs cle-valeur en
donnant des mots-cles `
a la methode constructeur (cet aspect sera eclaircie au prochain cours
lorsque nous aborderons le concept de classe) de la classe dictionnaire.
>>> m o n d i c t = d i c t ( Montreal =514 , Quebec =418 , S h e r b r o o k e =819)
>>> p r i n t m o n d i c t
{ Montreal : 5 1 4 , Quebec : 4 1 8 , S h e r b r o o k e : 819}

Un dictionnaire nest pas une sequence, les elements ne sont donc pas classes en ordre, ce
qui signifie quil est impossible de predire lordre darrive des elements, dans une boucle for par
exemple.
>>> f o r c l e i n m o n d i c t . k e y s ( ) :
...
p r i n t cle , mon dict [ c l e ]
...
S h e r b r o o k e 819
Quebec 418
Montreal 514

La methode keys, qui retourne une liste contenant toutes les cles du dictionnaire, peut facilement etre utilisee pour faire le tour de tous les elements du dictionnaire. Si lordre est important,
il suffit de remettre la liste en ordre croissant avec la fonction sorted.
>>> f o r c l e i n s o r t e d ( m o n d i c t . k e y s ( ) ) :
...
p r i n t cle , mon dict [ c l e ]
...
Montreal 514
Quebec 418
S h e r b r o o k e 819

8.2. LE DICTIONNAIRE

8.2.1

85

Op
erations sur les dictionnaires

Quelques operations sur un dictionnaire :


Ajout delements :
>>> d i c t = { Montreal : 5 1 4 , Quebec : 418}
>>> d i c t [ S h e r b r o o k e ] = 819
>>> p r i n t d i c t [ S h e r b r o o k e ]
819

Suppression delements :
>>> d e l d i c t [ Quebec ]
>>> d i c t
{ Montreal : 5 1 4 , S h e r b r o o k e : 819}

Lister des cles ou des valeurs :


>>> d i c t . k e y s ( )
[ Montreal , S h e r b r o o k e ]
>>> d i c t . v a l u e s ( )
[514 , 819]

Lister tous les elements :


>>> d i c t . i t e m s ( )
[ ( Montreal , 5 1 4 ) , ( S h e r b r o o k e , 8 1 9 ) ]

Tester la presence dune cle :


>>> d i c t . h a s k e y ( Montreal )
True
>>> S h e r b r o o k e i n d i c t
True

Copier un dictionnaire (creer une copie independante) :


>>> n e w d i c t = d i c t . copy ( )
>>> n e w d i c t [ Quebec ] = 418
>>> p r i n t n e w d i c t
{ Montreal : 5 1 4 , Quebec : 4 1 8 , S h e r b r o o k e : 819}
>>> p r i n t d i c t
{ Montreal : 5 1 4 , S h e r b r o o k e : 819}

` noter que la methode copy() fonctionne seulement avec des dictionnaires relativement
A
simples, cest-`
a-dire des dictionnaires qui ne contiennent pas de conteneurs parmi leurs items.
Si, par exemple, une liste est associee `a une cle quelconque dans le dictionnaire, comme la copie
nest pas recursive, la liste ne sera pas independante de la liste du dictionnaire `a la source. Ceci
implique quune modification appliquee `a la liste se refl`etera dans les deux dictionnaires, bien
que ceux-ci soient independants. La liste demeure un seul objet en memoire avec deux references
pointant sur cet espace-memoire.

86

CHAPITRE 8. LES DICTIONNAIRES

>>> d1 = { p1 : [ 0 , 2 , 5 , 7
>>> d2 = d1 . copy ( )
>>> p r i n t d1 = , d1
d1 = { p1 : [ 0 , 2 , 5 , 7 ,
>>> d2 [ p1 ] [ 4 ] = 9
>>> p r i n t d2 = , d2
d2 = { p1 : [ 0 , 2 , 5 , 7 ,
>>> p r i n t d1 = , d1
d1 = { p1 : [ 0 , 2 , 5 , 7 ,

,10]}

10]}

9]}
9]}

La solution `
a ce probl`eme consiste `a faire appel au module copy, dans lequel on trouvera la
fonction deepcopy permettant de copier de facon recursive des structures complexes. Avec cette
fonction, non seulement le conteneur principal est copie, mais aussi tous les conteneurs qui se
trouvent parmi les items du dictionnaire.
>>> import copy
>>> d1 = { p1 : [ 0 , 2 , 5 , 7 , 1 0 ] }
>>> d2 = copy . deepcopy ( d1 )
>>> p r i n t d1 = , d1
d1 = { p1 : [ 0 , 2 , 5 , 7 , 1 0 ] }
>>> d2 [ p1 ] [ 4 ] = 9
>>> p r i n t d2 = , d2
d2 = { p1 : [ 0 , 2 , 5 , 7 , 9 ] }
>>> p r i n t d1 = , d1
d1 = { p1 : [ 0 , 2 , 5 , 7 , 1 0 ] }

Tutoriel sur les differentes structures de data.

8.2.2

Construction dun histogramme `


a laide dun dictionnaire

En supposant la phrase suivante : la programmation en python est vraiment amusante.


La construction dun histogramme, representant la frequence de repetition de chacune des
lettres, est tr`es simple `
a faire si on se base sur un dictionnaire.
>>> t e x t = l a programmation en python e s t v ra i me nt amusante
>>> l e t t r e s = {}
>>> f o r c i n t e x t :
...
l e t t r e s [ c ] = l e t t r e s . get ( c , 0) + 1
...
>>> p r i n t l e t t r e s
{ a : 6 , : 6 , e : 4 , g : 1 , i : 2 , h : 1 ,
m : 4 , l : 1 , o : 3 , n : 5 , p : 2 , s : 2 ,
r : 3 , u : 1 , t : 5 , v : 1 , y : 1}

Dans un premier temps, nous creons un dictionnaire vide : lettres. Ensuite, nous parcourons
la chane de caract`eres, element par element. Pour chaque caract`ere, nous appelons la methode
get de la classe dictionnaire. Cette methode retourne la valeur associee `a la cle indiquee au
premier param`etre. Si cette cle nest pas presente, la methode renvoie une valeur par defaut
definie au deuxi`eme param`etre, dans ce cas-ci, la valeur 0. Ainsi, pour chaque caract`ere, nous
questionnons le dictionnaire afin de savoir combien de fois a passe ce caract`ere depuis le debut de
la boucle, nous ajoutons 1 `
a la reponse et remplacons par cette valeur lancienne valeur associee
`a ce caract`ere.

ENEMENTS

8.3. GESTION DES EV


DANS LE TEMPS PAR LENVOI DE TRIGGERS 87

Si on veut obtenir le resultat pour chaque lettre dans lordre alphabetique, il suffit de convertir
notre dictionnaire en une liste de tuples, avec la methode items, puis de passer la liste dans la
fonction sorted, pour les placer dans lordre :
>>> l e t t r e s t r i e e s = s o r t e d ( l e t t r e s . i t e m s ( ) )
>>> p r i n t l e t t r e s t r i e e s
[ ( , 6) , ( a , 6) , ( e , 4) , ( g , 1) , ( h , 1) , ( i , 2) ,
( l , 1 ) , ( m , 4 ) , ( n , 5 ) , ( o , 3 ) , ( p , 2 ) , ( r , 3 ) ,
( s , 2) , ( t , 5) , ( u , 1) , ( v , 1) , ( y , 1) ]

8.3
8.3.1

Gestion des
ev
enements dans le temps par lenvoi de triggers
Quest-ce quun trigger ?

Un trigger, ou trig, est une impulsion, cest-`a-dire un signal audio dans lequel un echantillon
ayant une valeur de 1.0 est entoure dechantillons de valeurs 0.0. La raison detre de ce type
de signal est de pourvoir pyo dun syst`eme de gestion des evenements `a haute resolution temporelle. Un trigger etant un signal audio, il possible de creer des traitements parall`eles avec une
synchronisation `
a lechantillons pr`es. Il y a deux types dobjets dans la categorie triggers, les
objets qui gen`erent des trigs et ceux qui y reagissent.
Objets g
en
erant des trigs

Beat gen`ere une sequence de trigs de facon algorithmique.


Change envoie un trig lorsquun signal audio en entree change de valeur.
Cloud envoie des trigs, sans rythmique particuli`ere, en fonction dun param`etre de densite.
Metro gen`ere des trigs de facon synchrone.
Select envoie un trig lorsque le signal en entree correspond `a un entier donne en argument.
Thresh envoie un trig lorsquun signal en entree croise un seuil donnee en argument.
Trig envoie un seul trig `
a lappel de la methode play.

Objets r
eagissant aux trigs

Counter incremente un compte dentier.


TrigChoice pige une valeur dans une liste donnee en argument.
TrigEnv demarre la lecture dune table dechantillons.
TrigExpseg demarre la lecture dune enveloppe exponentielle.
TrigFunc appelle une fonction python.
TrigLinseg demarre la lecture dune enveloppe lineaire.
TrigRand gen`ere une valeur pseudo-aleatoire.
TrigXnoise gen`ere une valeur selon differents algorithmes pseudo-aleatoires.
TrigXnoiseMidi gen`ere une note Midi selon differents algorithmes pseudo-aleatoires.

Consulter la categorie triggers du manuel pyo pour une liste compl`ete des objets participant `
a
la gestion des trigs.

88

CHAPITRE 8. LES DICTIONNAIRES

8.3.2

S
equence d
ev
enements

Dans un premier temps, nous nous concentrerons sur les objets permettant de creer des
sequences devenements, cest-`
a-dire Metro et Beat. Voici, avec un metronome, comment changer
de facon periodique, la frequence dun oscillateur :
1

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5
6
7
8

# Ne pas o u b l i e r d a p p e l e r l a methode . p l a y ( ) pour l e s o b j e t s Metro e t Beat


met = Metro ( time =.125) . p l a y ( )
t = TrigRand ( met , min=400 , max=1000)
a = SineLoop ( f r e q=t , f e e d b a c k =0.05 , mul =.3) . out ( )

9
10

s . gui ( l o c a l s () )

scripts/chapitre 08/01 metro rand.py


Meme procede mais cette fois-ci en pigeant les valeurs dans une gamme predefinie :
1

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5
6
7
8

n o t e s = [ midiToHz ( x ) f o r x i n [ 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]
met = Metro ( time =.125) . p l a y ( )
t = T r i g C h o i c e ( met , c h o i c e=n o t e s , p o r t =0.005)
a = SineLoop ( f r e q=t , f e e d b a c k =0.07 , mul =.3) . out ( )

9
10

s . gui ( l o c a l s () )

scripts/chapitre 08/02 metro choice.py


Lobjet TrigChoice agit de la meme facon que lobjet Choice. Par contre, il attend un trig
pour piger une valeur au lieu deffectuer sa pige en fonction dune frequence donnee. Largument
port permet de specifier un temps de rampe entre la valeur actuelle et la valeur pigee.
Utilisation d
echantillons plac
es en m
emoire dans une table
Afin dobtenir leffet dune nouvelle note jouee, il est necessaire dappliquer une enveloppe
damplitude sur le signal. Lobjet TrigEnv permet de demarrer la lecture du contenu dune table
dechantillons sur reception dun trig (nous elaborerons plus en detail sur le type PyoTableObject
prochainement). Nous utiliserons ici quelques objets de la classe PyoTableObject afin de mettre
en memoire differentes enveloppes damplitude.
LinTable Construit une enveloppe `a partir de segments de droite.
ExpTable Construit une enveloppe `a partir de segments exponentiels.
HannTable Gen`ere une enveloppe en forme de cloche (Hanning).
LinTable et ExpTable attendent une liste de tuples representant chacun des points de lenveloppe.
# Enveloppe ADSR ( a t t a c k decay s u s t a i n r e l e a s e )
env = LinTable ( [ ( 0 , 0 ) , ( 1 0 0 , 1 ) , ( 5 0 0 , . 5 ) , ( 5 0 0 0 , . 5 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)

ENEMENTS

8.3. GESTION DES EV


DANS LE TEMPS PAR LENVOI DE TRIGGERS 89

La premi`ere valeur du tuple represente lemplacement, en echantillons, o`


u situer le point et
la deuxi`eme valeur est lamplitude du point. Ainsi, dans lexemple precedent, pour une table de
8192 echantillons, nous avons les points suivants :

point
point
point
point
point

1
2
3
4
5

:
:
:
:
:

valeur
valeur
valeur
valeur
valeur

0`
a lechantillon 0 (premier emplacement).
1`
a lechantillon 100 (fin de lattaque).
0.5 `
a lechantillon 500 (fin du decay).
0.5 `
a lechantillon 5000 (fin de la tenue).
0`
a lechantillon 8191 (Relache jusqu`a la fin de la table).

Ajoutons lenveloppe dans le script precedent.


1

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5
6

env = LinTable ( [ ( 0 , 0 ) , ( 1 0 0 , 1 ) , ( 5 0 0 , . 5 ) , ( 5 0 0 0 , . 5 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)


n o t e s = [ midiToHz ( x ) f o r x i n [ 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]

7
8
9
10
11

met
t =
amp
a =

= Metro ( time =.125) . p l a y ( )


T r i g C h o i c e ( met , c h o i c e=n o t e s , p o r t =0.005)
= TrigEnv ( met , t a b l e=env , dur =.125 , mul =.5)
SineLoop ( f r e q=t , f e e d b a c k =0.07 , mul=amp) . out ( )

12
13

s . gui ( l o c a l s () )

scripts/chapitre 08/03 metro env.py


Vous pouvez aisement tester leffet dune enveloppe exponentielle en remplacant LinTable
par ExpTable. Pour obtenir une enveloppe en forme de cloche, il suffit simplement de creer un
objet HannTable sans param`etre. Dans le script suivant, un deuxi`eme metronome, beaucoup
plus lent, a ete ajoute pour declencher une enveloppe globale sur la generation de notes.
1

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5
6

env = LinTable ( [ ( 0 , 0 ) , ( 1 0 0 , 1 ) , ( 5 0 0 , . 5 ) , ( 5 0 0 0 , . 5 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)


g l o b e n v = HannTable ( )

7
8

n o t e s = [ midiToHz ( x ) f o r x i n [ 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]

9
10
11

globmet = Metro ( time =5) . p l a y ( )


globamp = TrigEnv ( globmet , t a b l e=globenv , dur =5)

12
13
14
15
16

met
t =
amp
a =

= Metro ( time =.125) . p l a y ( )


T r i g C h o i c e ( met , c h o i c e=n o t e s , p o r t =0.005)
= TrigEnv ( met , t a b l e=env , dur =.125 , mul =.5)
SineLoop ( f r e q=t , f e e d b a c k =0.07 , mul=amp globamp ) . out ( )

17
18

s . gui ( l o c a l s () )

scripts/chapitre 08/04 metro env glob.py

90

CHAPITRE 8. LES DICTIONNAIRES

Un des principaux dilemmes en synth`ese et traitement des sons est la gestion de la polyphonie,
cest-`a-dire la duplication des processus. Un exemple rapide pour demontrer limportance de
la polyphonie consiste simplement `
a allonger la duree de lenveloppe du script precedent `a .25
seconde afin dobtenir des notes plus longues, qui se chevauchent. Quen est-il du resultat sonore ?
Il y a des clics dans le son puisque lon redemarre une enveloppe qui navait pas encore
terminee sa course. Pour allonger les notes et creer un chevauchement, il faut absolument avoir
plus dune instance du meme processus. Cela assurera quune enveloppe est bien terminee avant
detre relancee, evitant ainsi une discontinuite dans la trajectoire damplitude.
Les objets qui gen`erent des sequences de trigs (Metro, Beat et Cloud) ont tous un argument
poly permettant de definir combien de streams audio seront asservis `a une generation dimpulsions.
>>> a = Metro ( time =.125 , p o l y =4)
>>> p r i n t l e n ( a )
4
>>>

Si notre metronome g`ere 4 streams de polyphonie, la suite dobjets qui en decoulent g`ereront
forcement au moins 4 streams de polyphonie chacun. On peut donc dupliquer un processus
sonore au complet simplement en specifiant un certain nombre de voix de polyphonie `a lobjet
Metro. Pour une duree denveloppe de .25 seconde, nous avons besoin de seulement 2 voix de
polyphonie.
1

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5
6

env = LinTable ( [ ( 0 , 0 ) , ( 1 0 0 , 1 ) , ( 5 0 0 , . 5 ) , ( 5 0 0 0 , . 5 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)


g l o b e n v = HannTable ( )

7
8

n o t e s = [ midiToHz ( x ) f o r x i n [ 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]

9
10
11

globmet = Metro ( time =5) . p l a y ( )


globamp = TrigEnv ( globmet , t a b l e=globenv , dur =5)

12
13
14
15
16

met
t =
amp
a =

= Metro ( time =.125 , p o l y =2) . p l a y ( )


T r i g C h o i c e ( met , c h o i c e=n o t e s , p o r t =0.005)
= TrigEnv ( met , t a b l e=env , dur =.125 , mul =.5)
SineLoop ( f r e q=t , f e e d b a c k =0.07 , mul=amp globamp ) . out ( )

17
18

s . gui ( l o c a l s () )

scripts/chapitre 08/05 metro stereo.py


Lecture dun fichier sonore plac
e en m
emoire dans une table
Avec lobjet TrigEnv, il est tr`es simple de faire jouer un son en boucle `a une frequence
determinee par la vitesse dun metronome. Nous allons cette fois-ci placer un son dans une table
avec lobjet SndTable et activer la lecture avec une sequence de trigs. La methode getDur de
lobjet SndTable permet de recuperer la longueur de la table en secondes.


8.4. CREATION
DALGORITHMES MUSICAUX

91

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5
6
7

snd = SndTable (SNDS PATH + / a c c o r d . a i f )


dur = snd . getDur ( )
p r i n t Duree : , dur

8
9
10

met = Metro ( time=dur 2 ) . p l a y ( )


out = TrigEnv ( met , t a b l e=snd , dur=dur ) . out ( )

11
12

s . gui ( l o c a l s () )

scripts/chapitre 08/06 sndtable.py


On peut changer la hauteur du son en modifiant la duree de lecture de la table :
snd = SndTable (SNDS PATH + / a c c o r d . a i f )
dur = snd . getDur ( )
p r i n t Duree : , dur
met = Metro ( time=dur 2 ) . p l a y ( )
out = TrigEnv ( met , t a b l e=snd , dur=dur 2 ) . out ( )

Si la duree de lecture de la table depasse la vitesse du metronome, on ajoute des voix de


polyphonie afin deviter les clics !
snd = SndTable (SNDS PATH + / a c c o r d . a i f )
dur = snd . getDur ( )
p r i n t Duree : , dur
met = Metro ( time=dur 2 , p o l y =2) . p l a y ( )
out = TrigEnv ( met , t a b l e=snd , dur=dur 2 . 5 ) . out ( )

8.4

Cr
eation dalgorithmes musicaux

Rythme
Dans cette section, nous allons explorer certains objets dalgorithmie disponibles dans la
librairie pyo. Reprenons un script similaire `a lexemple de la page precedente, cest-`a-dire un
metronome qui active une enveloppe damplitude et pige une nouvelle frequence pour un oscillateur.
f r e q s = [ midiToHz ( x ) f o r x i n [ 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]
env = LinTable ( [ ( 0 , 0 ) , ( 3 0 0 , 1 ) , ( 1 0 0 0 , . 5 ) , ( 3 0 0 0 , . 5 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)
met = Metro ( time =.125) . p l a y ( )
amp = TrigEnv ( met , t a b l e=env , dur =.125 , mul =.5)
f r = T r i g C h o i c e ( met , c h o i c e=f r e q s )
o s c = SineLoop ( f r e q=f r , f e e d b a c k =.08 , mul=amp) . out ( )

92

CHAPITRE 8. LES DICTIONNAIRES

Nous allons dans un premier temps utiliser lobjet Beat qui est concu pour generer des
sequences rythmiques de facon algorithmique en fonction de poids donnes en argument. Les
param`etres w1, w2 et w3 contr
olent respectivement le pourcentage de chance detre present des
temps forts, intermediaires et faibles. Le param`etre taps indique le nombre de temps dans la
mesure (1 temps = une duree donnee au param`etre time). Par exemple, pour obtenir une mesure
en 4/4 ne contenant que les temps forts (les noires), on ecrirait ceci :
met = Beat ( time =.125 , t a p s =16 , w1=100 , w2=0, w3=0)

Pour rajouter 50% des temps intermediaires (les croches) :


met = Beat ( time =.125 , t a p s =16 , w1=100 , w2=50 , w3=0)

Et Finalement, 30% des temps faibles (toutes les double-croches restantes) :


met = Beat ( time =.125 , t a p s =16 , w1=100 , w2=50 , w3=30)

Remplacons le metronome du script par un objet Beat :


f r e q s = [ midiToHz ( x ) f o r x i n [ 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]
env = LinTable ( [ ( 0 , 0 ) , ( 3 0 0 , 1 ) , ( 1 0 0 0 , . 5 ) , ( 3 0 0 0 , . 5 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)
met = Beat ( time =.125 , t a p s =16 , w1=90 , w2=50 , w3=30) . p l a y ( )
amp = TrigEnv ( met , t a b l e=env , dur =.125 , mul =.5)
f r = T r i g C h o i c e ( met , c h o i c e=f r e q s )
o s c = SineLoop ( f r e q=f r , f e e d b a c k =.08 , mul=amp) . out ( )

Ce script gen`erera une nouvelle sequence rythmique `a chaque execution. Une nouvelle particularite est `a noter ici. Lobjet Beat ne donne pas que des trigs comme signaux, il retourne aussi
dautres informations utiles sous la forme de streams audio. On acc`ede aux differents streams
en utilisant une syntaxe similaire `
a celle des dictionnaires, en appelant linfo desiree, en format
string, entre crochets. Voici les differents appels possibles :
obj[dur] : Signal audio contenant la duree de la note courante, cest-`a-dire le temps
avant le prochain trig.
obj[amp] : Signal audio contenant lamplitude de la note courante, en fonction des
temps forts, intermediaires et faibles.
obj[end] : Signal audio contenant un seul trig sur le dernier temps de la mesure. Il peutetre utilise pour sassurer que les changements de rythme arrivent bien au debut dune
mesure.
Nous allons inserer dans notre script les signaux de duree et damplitude afin que notre
algorithme se comporte de facon un peu plus coherente :
f r e q s = [ midiToHz ( x ) f o r x i n [ 6 0 , 6 2 , 6 4 , 6 5 , 6 7 , 6 9 , 7 1 , 7 2 ] ]
env = LinTable ( [ ( 0 , 0 ) , ( 3 0 0 , 1 ) , ( 1 0 0 0 , . 5 ) , ( 3 0 0 0 , . 5 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)
met = Beat ( time =.125 , t a p s =16 , w1=90 , w2=50 , w3=30) . p l a y ( )
amp = TrigEnv ( met , t a b l e=env , dur=met [ dur ] , mul=met [ amp ] )
f r = T r i g C h o i c e ( met , c h o i c e=f r e q s )
o s c = SineLoop ( f r e q=f r , f e e d b a c k =.08 , mul=amp 0 . 5 ) . out ( )


8.4. CREATION
DALGORITHMES MUSICAUX

93

M
elodie
Maintenant que nous avons gere les accents et les durees, laissons de cote laspect rythmique pour ameliorer laspect melodique de notre algorithme. Une melodie est rarement constituee de notes pigees au hasard, meme si la pige seffectue `a linterieur dune gamme. En
r`egle generale, une melodie est constituee de mouvements (souvent conjoints) vers le haut et
vers le bas qui peuvent setaler sur plusieurs notes. On y retrouvera aussi des repetitions de
certains motifs. Cest donc dire que notre objet TrigChoice ne rempli pas vraiment son r
ole
melodique, il est trop hasardeux ! Il y a deux objets dans la librairie qui sont plus adequats pour
generer des cellules melodiques, TrigXnoise et TrigXnoiseMidi. Comme nous desirons generer
des notes sur des gammes temperees, nous utiliserons TrigXnoiseMidi, qui gen`ere dabord sa
melodie en notes Midi, puis peut, sur demande, convertir automatiquement en Hertz. Cet objet
implemente differents types de distributions aleatoires controlees pouvant servir `a generer des
motifs melodiques de toutes sortes. Pour en savoir plus sur les distributions aleatoires contr
olees
(qui est un peu hors du contexte de ce cours), voici un excellent site avec des schemas representant
les courbes de distributions des algorithmes les plus populaires :
Gallery of distributions
Lalgorithme qui nous interesse dans le present contexte est le numero 12, un generateur de
segments de melodie en boucle. Remplacons la ligne du TrigChoice par la ligne suivante :
f r = T r i g X n o i s e M i d i ( met , d i s t =12 , x1 =1 , x2 =.3 , s c a l e =1, mrange =(60 ,84) )

Largument dist indique le numero de distribution `a utiliser, consultez la liste des algorithmes
disponibles dans le manuel. Les arguments x1 et x2 changent de role en fonction de lalgorithme
choisi. Dans ce cas-ci, ils representent la valeur maximale possible (en fonction de lambitus
Midi) et la plus grande distance possible entre 2 hauteurs de note. Largument scale indique le
format desire pour les valeurs obtenues (0 = Midi, 1 = Hertz) et largument mrange est un tuple
indiquant le registre Midi dans lequel doit se restreindre la pige.
Notre script donne maintenant un profil melodique plus coherent, par contre, nous avons
perdu notre gamme. Toutes les notes entre 60 et 84 sont maintenant legales. Une technique
rudimentaire mais efficace pour pallier `a ce probl`eme consiste `a choisir la note de la gamme la
plus proche de la note pigee. Lobjet Snap effectue cette tache :
f r = T r i g X n o i s e M i d i ( met , d i s t =12 , x1 =1 , x2 =.3 , s c a l e =0, mrange =(60 ,84) )
f r s n a p = Snap ( f r , c h o i c e = [ 0 , 2 , 3 , 5 , 7 , 8 , 1 1 ] , s c a l e =1)
o s c = SineLoop ( f r e q=f r , f e e d b a c k =.08 , mul=amp . 5 ) . out ( )

Lobjet Snap fonctionne avec des notes Midi, il ne faut donc pas oublier de remettre largument scale `
a 0, pour envoyer des notes Midi. Cest maintenant lobjet Snap qui se chargera de la
conversion en Hertz, en passant la valeur 1 `a son propre argument scale. Au param`etre choice,
on donnera une liste representant le premier octave de la gamme desiree.
Le script en entier est liste `
a la page suivante.

94

CHAPITRE 8. LES DICTIONNAIRES

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5

env = LinTable ( [ ( 0 , 0 ) , ( 3 0 0 , 1 ) , ( 1 0 0 0 , . 5 ) , ( 3 0 0 0 , . 5 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)

6
7

met = Beat ( time =.125 , t a p s =16 , w1=90 , w2=50 , w3=30) . p l a y ( )

8
9

amp = TrigEnv ( met , t a b l e=env , dur=met [ dur ] , mul=met [ amp ] )

10
11
12

f r = T r i g X n o i s e M i d i ( met , d i s t =12 , x1 =1 , x2 =.3 , s c a l e =0, mrange =(48 ,85) )


f r s n a p = Snap ( f r , c h o i c e = [ 0 , 2 , 3 , 5 , 7 , 8 , 1 1 ] , s c a l e =1)

13
14

o s c = SineLoop ( f r e q=f r s n a p , f e e d b a c k =.08 , mul=amp . 5 ) . out ( )

15
16

s . gui ( l o c a l s () )

scripts/chapitre 08/07 simple algo.py

Harmonie
Pour creer un contrepoint `
a deux voix, il suffit de dupliquer le generateur en place et de
modifier les param`etres afin de jouer sur des registres et des rythmiques interessantes...
1

from pyo import

2
3

s = S e r v e r ( ) . boot ( )

4
5

env = LinTable ( [ ( 0 , 0 ) , ( 3 0 0 , 1 ) , ( 1 0 0 0 , . 5 ) , ( 3 0 0 0 , . 5 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)

6
7
8
9
10
11

met = Beat ( time =.25 , t a p s =16 , w1=50 , w2=70 , w3=50) . p l a y ( )


amp = TrigEnv ( met , t a b l e=env , dur=met [ dur ] , mul=met [ amp ] )
f r = T r i g X n o i s e M i d i ( met , d i s t =12 , x1 =1 , x2 =.3 , s c a l e =0, mrange =(48 ,73) )
f r s n a p = Snap ( f r , c h o i c e = [ 0 , 2 , 3 , 5 , 7 , 8 , 1 1 ] , s c a l e =1)
o s c = SineLoop ( f r e q=f r s n a p , f e e d b a c k =.08 , mul=amp . 5 ) . out ( )

12
13
14
15
16
17

met2 = Beat ( time =.25 , t a p s =16 , w1=100 , w2=40 , w3=0) . p l a y ( )


amp2 = TrigEnv ( met2 , t a b l e=env , dur=met2 [ dur ] , mul=met2 [ amp ] )
f r 2 = T r i g X n o i s e M i d i ( met2 , d i s t =12 , x1 =1 , x2 =.3 , s c a l e =0, mrange =(36 ,61) )
f r s n a p 2 = Snap ( f r 2 , c h o i c e = [ 0 , 2 , 3 , 5 , 7 , 8 , 1 1 ] , s c a l e =1)
o s c 2 = SineLoop ( f r e q=f r s n a p 2 , f e e d b a c k =.08 , mul=amp2 . 5 ) . out ( 1 )

18
19

s . gui ( l o c a l s () )

scripts/chapitre 08/08 stereo algo.py

` 2 VOIX
8.5. EXEMPLE : PETIT CONTREPOINT ALGORITHMIQUE A

8.5
1
2
3
4

Exemple : Petit contrepoint algorithmique `


a 2 voix

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import
import random

5
6

s = S e r v e r ( ) . boot ( )

7
8
9
10

TIME = . 2 # Duree d un tap


# D i c t i o n n a i r e de modes pour l e c h o i x d e s n o t e s
SCLS = { p1 : [ 0 , 2 , 5 , 7 , 9 ] , p2 : [ 0 , 3 , 5 , 7 , 1 0 ] , p3 : [ 0 , 2 , 7 , 8 , 1 1 ] }

11
12
13

# Envelope d a m p l i t u d e
env = LinTable ( [ ( 0 , 0 ) , ( 3 0 0 , 1 ) , ( 1 0 0 0 , . 7 ) , ( 6 0 0 0 , . 7 ) , ( 8 1 9 1 , 0 ) ] , s i z e =8192)

14
15
16

# 8 r a n d i s a m u l t i p l i e r aux n o t e s pour c r e e r un c h o r u s
cho = Randi ( min =.99 , max=1.01 , f r e q =[random . uni for m ( 1 , 3 ) f o r i i n r a n g e ( 8 ) ] )

17
18
19
20
21
22

met = Beat ( time=TIME, t a p s =16 , w1=70 , w2=70 , w3=50) . p l a y ( )


amp = TrigEnv ( met , t a b l e=env , dur=met [ dur ] , mul=met [ amp ] )
f r = T r i g X n o i s e M i d i ( met , d i s t =12 , x1 =1 , x2 =.33 , s c a l e =0 , mrange =(48 ,85) )
f r s n a p = Snap ( f r , c h o i c e=SCLS [ p1 ] , s c a l e =1)
o s c = LFO( f r e q=f r s n a p cho , s h a r p =.75 , type =3 , mul=amp 0 . 1 ) . mix ( 2 )

23
24
25
26
27
28

met2 = Beat ( time=TIME, t a p s =16 , w1=100 , w2=40 , w3=20) . p l a y ( )


amp2 = TrigEnv ( met2 , t a b l e=env , dur=met2 [ dur ] , mul=met2 [ amp ] )
f r 2 = T r i g X n o i s e M i d i ( met2 , d i s t =12 , x1 =1, x2 =.5 , s c a l e =0 , mrange =(36 ,61) )
f r s n a p 2 = Snap ( f r 2 , c h o i c e=SCLS [ p1 ] , s c a l e =1)
o s c 2 = LFO( f r e q=f r s n a p 2 cho , s h a r p =.75 , type =3 , mul=amp2 0 . 1 ) . mix ( 2 )

29
30

r e v = WGVerb( o s c+osc2 , f e e d b a c k =.7 , c u t o f f =4000 , b a l =.15) . out ( )

31
32
33
34

d e f newbeat ( ) : # Genere de n o u v e l l e s s e q u e n c e s r y t h m i q u e s
met . new ( )
met2 . new ( )

35
36
37
38
39
40
41
42
43
44
45

d e f change ( ) : # a c t i o n s a l a f i n de chaque
p r i n t f i n de l a mesure
i f ( random . r a n d i n t ( 0 , 1 0 0 ) < 2 5 ) : # 25%
gamme = random . c h o i c e ( [ p1 , p2 ,
f r s n a p . c h o i c e = SCLS [ gamme ]
f r s n a p 2 . c h o i c e = SCLS [ gamme ]
p r i n t N o u v e l l e gamme : , gamme
i f ( random . r a n d i n t ( 0 , 1 0 0 ) < 2 0 ) : # 20%
p r i n t Change de rythme
newbeat ( )

mesure
de chance de p i g e r une n o u v e l l e gamme
p3 ] )

de chance de p i g e r un nouveau rythme

46
47
48

# A p p e l l e l a f o n c t i o n change a chaque f i n de mesure


ch = TrigFunc ( met [ end ] , change )

49
50

s . gui ( l o c a l s () )

scripts/chapitre 08/09 contrepoint.py

95

96

CHAPITRE 8. LES DICTIONNAIRES

Chapitre 9

Classes et m
ethodes
9.1

Introduction au concept de classe et dobjets

Le concept de classe est un des elements les plus importants de la programmation orientee
objet (Object Oriented Programming ou OOP). Un objet est une instance creee `a partir dune
classe, cest-`
a-dire de la definition dun type particulier dobjet. La definition dun objet, par le
mot-cle class, consiste en un regroupement de tous les attributs et methodes lies `a la gestion dun
` partir de cette definition, il est possible de creer autant dobjets independants
processus donne. A
quil est necessaire au bon fonctionnement du programme. Ce type de programmation permet de
construire des programmes complexes en organisant un ensemble dobjets, ayant chacun leur r
ole
`a jouer, qui interagissent entre eux. Cette approche de la programmation est benefique par le fait
que les differents objets peuvent etre construits independamment les uns des autres sans quil
ny ait de risque dinterference, gr
ace au concept dencapsulation. En effet, les fonctionnalites
internes de lobjet ainsi que les variables quil utilise pour effectuer sa tache sont enfermees
`a linterieur de lobjet. Pour y avoir acc`es de lexterieur, il faut utiliser des procedures bien
definies, ce qui minimise les risques de conflit.
Les concepts suivants debordent un peu le cadre de ce cours, mais il est bon den connatre
lexistence. Il est possible de creer une classe `a partir de la definition dune autre classe, cest-`
adire de reutiliser des morceaux de code dej`a ecrits pour creer une fonctionnalite nouvelle, plus
specifique. Cela est possible gr
ace aux concepts dh
eritage et de polymorphisme.
Le mecanisme dh
eritage permet de construire une classe enfant `a partir dune classe
parente. La classe enfant herite ainsi des proprietes de son ancetre, auxquelles on peut
ajouter dautres fonctionnalites.
Le polymorphisme permet dattribuer des comportements differents, lors de lappel
dune fonction par exemple, `
a des objets derivant les uns des autres, ou au meme objet en fonction dun certain contexte.

97


CHAPITRE 9. CLASSES ET METHODES

98

9.2

D
efinition dune classe simple et de ses attributs

Une classe est creee avec linstruction class suivit du nom que lon desire lui donner (par
convention, les noms de classe debutent toujours par une lettre majuscule). Une classe etant
une instruction composee, il est donc necessaire de terminer la ligne den-tete par le symbole
deux-points ( : ) et dindenter tout le code constituant le corps de la classe. Contrairement
`a la definition dune fonction, le nom dune classe nest pas forcement suivit dune paire de
parenth`eses. En fait, celles-ci sont necessaires seulement lorsque lon veut designer une classe
parente `a la classe que lon construit, sujet qui ne sera pas couvert dans ce cours. Voici un
exemple de definition dune classe qui nous servira `a creer des notes en format Midi :
c l a s s Note :
I n s t a n c e d une n o t e Midi

Cette classe, bien quinutile pour linstant, nous permet dej`a de creer des objets Note. Puisque
quaucune fonctionnalite nest encore definie `a linterieur de la classe, la seule operation pertinente serait dappeler le contenu de la variable de documentation creee automatiquement par
Python !
>>> n = Note ( )
>>> p r i n t n . d o c
I n s t a n c e d une n o t e Midi

Deux details `
a noter :
La creation dun objet se fait par lappel de la classe suivit dune paire de parenth`eses
(nous verrons plus tard que des arguments peuvent etre donnes `a la creation dun objet).
Cet appel retourne un objet que lon peut affecter `a une variable `a laide du symbole egal
( = ).
Pour avoir acc`es aux attributs ou aux methodes dun objet, on utilise la syntaxe objet.attribut ou objet.methode(). Le point specifie `a linterpreteur de chercher tel attribut
ou telle methode appartenant `
a tel objet.
Reprenons la classe Note et donnons-lui quelques attributs par defaut, par exemple la hauteur
et la velocite dune note Midi.
c l a s s Note :
I n s t a n c e d une n o t e Midi
p i t c h = 48
v e l o c i t y = 127

D`es lors, tout objet cree `


a partir de cette classe possedera deux attributs, pitch et velocity,
avec comme valeurs respectives 48 et 127. Il sera desormais possible de consulter ou de modifier
les attributs de chacun des objets crees, independamment les uns des autres.

9.3. DEFINITION
DUNE METHODE

99

>>> n1 = Note ( )
>>> p r i n t n1 . p i t c h , n1 . v e l o c i t y
48 127
>>> n2 = Note ( )
>>> n1 . p i t c h , n1 . v e l o c i t y = 6 0 , 100
>>> p r i n t n1 . p i t c h , n1 . v e l o c i t y
60 100
>>> p r i n t n2 . p i t c h , n2 . v e l o c i t y
48 127

Nous venons de voir comment definir notre propre classe permettant de creer des objets.
La fonctionnalite dun objet est generalement definie par les methodes dont la classe est constituee. Dans la prochaine section, nous allons voir les etapes pour creer nos propres methodes
et comment utiliser ces methodes pour modifier le comportement dun objet.

9.3

D
efinition dune m
ethode

On definit une methode comme on definit une fonction, avec deux differences cependant :
La definition dune methode doit toujours etre encapsulee `a linterieur dune classe, cest`a-dire quelle doit faire partie du bloc dinstructions definissant la classe.
Le premier param`etre utilise par une methode doit toujours etre une reference dinstance.
Par convention, le mot reserve self est utilise pour designer linstance. Cela veut dire quil
doit toujours y avoir au moins un param`etre entre les parenth`eses lors de la definition
dune methode.
c l a s s Note :
I n s t a n c e d une n o t e Midi
d e f maFonction ( s e l f ) :
p r i n t Je s u i s une methode de l a c l a s s e Note
print s e l f

>>> n = Note ( )
>>> n . maFonction ( )
Je s u i s une methode de l a c l a s s e Note
< b u i l t i n . Note i n s t a n c e a t 0 x 1 c 0 f 1 f 3 0 >

Lors de lappel de la fonction maFonction, on constate que self correspond bien `a une instance
de la classe Note.
` noter :
A
Bien que la definition de la methode maFonction comporte un argument entre les parenth`eses,
lappel se fait sans argument. Ceci est du au fait que lors de lappel dune methode avec la
syntaxe objet.methode(), lobjet est lui-meme automatiquement donne comme premier argument
`a la methode, do`
u la definition avec self en argument. Si la methode necessite des arguments
particuliers, ils seront ajoutes dans la definition `a la suite de largument self. Lappel se fera de
facon standard, comme pour une fonction, toujours en ignorant le premier argument (self).


CHAPITRE 9. CLASSES ET METHODES

100

c l a s s Note :
I n s t a n c e d une n o t e Midi
def fonctionAvecArgs ( s e l f , x , y) :
print s e l f
print x , y
>>> n = Note ( )
>>> n . f o n c t i o n A v e c A r g s ( 1 0 , 2 0 )
< b u i l t i n . Note i n s t a n c e a t 0 x 1 c 0 f 1 f 3 0 >
10 20

Il existe une methode, qui est automatiquement appelee `a la creation dun objet, permettant
dinitialiser des variables dinstances, cest la methode constructeur.

9.4

La m
ethode constructeur

La methode constructeur est une methode particuli`ere qui est appelee automatiquement
lors de la creation dun objet. Cette methode doit obligatoirement sappeler init (deux
caract`eres souligne, le mot init, puis deux autres caract`eres souligne).
c l a s s Note :
I n s t a n c e d une n o t e Midi
def
init ( self ) :
s e l f . p i t c h = 48
s e l f . v e l o c i t y = 127
d e f g e t No te ( s e l f ) :
Retourne l a n o t e Midi
return ( s e l f . pitch , s e l f . v e l o c i t y )

Dans le code ci-dessus, on constate que les attributs sont maintenant initialises `a linterieur
de la methode constructeur. On constate aussi que le nom de ces attributs est precede du mot
self et dun point. Cela permet de definir des variables dinstance, cest `a dire des variables qui
appartiennent `
a lobjet cree et qui seront accessibles nimporte o`
u `a linterieur de lobjet. Ainsi,
la fonction getNote peut retourner les valeurs de hauteur et de velocite puisquelle a acc`es aux
variables dinstance de lobjet. Si plusieurs instances sont creees `a partir dune meme classe, les
variables dinstance sont independantes dun objet `a lautre. Il est donc possible de modifier la
variable self.pitch sans risque dinterference avec la hauteur de note Midi des autres instances
de la classe.
Donnons maintenant une fonctionnalite propre `a notre classe. En plus de retourner la note
Midi telle quelle, nous allons definir deux autres fonctions. La premi`ere effectuera la conversion
de la hauteur Midi en cycles par seconde (Hertz) tandis que la deuxi`eme transposera la velocite
en amplitude normalisee entre 0 et 1.


9.4. LA METHODE
CONSTRUCTEUR

101

c l a s s Note :
I n s t a n c e d une n o t e Midi
def
init ( self ) :
s e l f . p i t c h = 48
s e l f . v e l o c i t y = 127
d e f g et No te ( s e l f ) :
Retourne l a n o t e Midi
return ( s e l f . pitch , s e l f . v e l o c i t y )
d e f mtof ( s e l f ) :
Retourne l a f r e q u e n c e en Hertz de l a n o t e
r e t u r n 8 . 1 7 5 7 9 8 pow ( 1 . 0 5 9 4 6 3 3 , s e l f . p i t c h )
d e f vtoa ( s e l f ) :
Retourne l a m p l i t u d e de l a n o t e e n t r e 0 e t 1
return s e l f . velocity / 127.

Dans le cas o`
u lon desirerait specifier les valeurs de hauteur et de velocite de la note au
moment de la creation de lobjet, il suffirait de donner ces valeurs en param`etres `a la creation
et de les recuperer dans la methode constructeur, en placant des arguments `a la suite de la
variable dinstance.
>>> c l a s s Note :
...
I n s t a n c e d une n o t e Midi
...
def
i n i t ( s e l f , pit , vel ) :
...
s e l f . pitch = pit
...
s e l f . velocity = vel
...
>>> n = Note ( 3 6 , 1 1 7 )

Voici un petit exemple dutilisation de la classe Note afin de generer une melodie.
1
2

from pyo import


import random

3
4
5
6
7
8

c l a s s Note :
Conteneur pour n o t e Midi
def
i n i t ( s e l f , pit , vel ) :
s e l f . pitch = pit
s e l f . velocity = vel

9
10
11
12

d e f g et No te ( s e l f ) :
Retourne l a n o t e Midi
return ( s e l f . pitch , s e l f . v e l o c i t y )

13
14
15
16

d e f mtof ( s e l f ) :
Retourne l a f r e q u e n c e en Hertz de l a n o t e
r e t u r n 8 . 1 7 5 7 9 8 pow ( 1 . 0 5 9 4 6 3 3 , s e l f . p i t c h )

17
18
19
20

d e f vtoa ( s e l f ) :
Retourne l a m p l i t u d e de l a n o t e e n t r e 0 e t 1
return s e l f . velocity / 127.

102

CHAPITRE 9. CLASSES ET METHODES

21
22
23

num notes = 200


notes list = []

24
25
26
27
28
29

f o r i i n r a n g e ( num notes ) :
# P i g e a l e a t o i r e d une v a l e u r p a i r e e n t r e 48 e t 101
p i t = random . r a n d r a n g e ( 4 8 , 8 5 , 2 )
v e l = random . r a n d i n t ( 1 0 , 3 0 )
n o t e s l i s t . append ( Note ( p i t , v e l ) )

30
31

s = S e r v e r ( ) . boot ( )

32
33
34
35

# I n i t i a l i s a t i o n de l i s t e s v i d e s pour g a r d e r l e s r e f e r e n c e s aux o b j e t s a u d i o
fades = [ ]
oscs = [ ]

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

### I n i t i a l i s a t i o n d e s n o t e s ###
# a r g s : d e l a y = d e l a i avant d a c t i v e r l o b j e t , dur = temps d a c t i v a t i o n de
# l o b j e t ( l a methode s t o p ( ) e s t a p p e l e e automatiquement )
f o r i i n r a n g e ( num notes ) :
# Recupere un o b j e t Note
note = n o t e s l i s t [ i ]
# Temps de d e p a r t de l a n o t e
start = i .125
# Enveloppe d a m p l i t u d e . L a m p l i t u d e e s t r e c u p e r e e par l a methode vtoa ( )
f = Fader ( f a d e i n =.01 , f a d e o u t =.99 , dur =1,
mul=n o t e . vtoa ( ) ) . p l a y ( d e l a y=s t a r t , dur =1)
# O s c i l l a t e u r s . La f r e q u e n c e e s t r e c u p e r e e par l a methode mtof ( )
o s c = SineLoop ( f r e q=n o t e . mtof ( ) , f e e d b a c k =.05 ,
mul=f ) . out ( i %2, d e l a y=s t a r t , dur =1)
# Ajoute l e s o b j e t s dans l e s l i s t e s
f a d e s . append ( f )
o s c s . append ( o s c )

54
55

s . gui ( l o c a l s () )

scripts/chapitre 09/01 classe note 1.py


Cette technique nous permet de gerer la generation des notes en pur Python, environnement
tr`es puissant en ce qui concerne lalgorithmie. Dans le script suivant, nous allons remplacer
la boucle qui pige des valeurs aleatoires pour la hauteur et la velocite par une boucle un peu
plus raffinee. Au lieu de piger des hauteurs dans le hasard le plus complet, nous allons creer une
marche aleatoire en ajoutant une petite valeur `a la hauteur precedente, minimisant ainsi les sauts
dans la melodie. Pour la velocite, nous allons imposer des accents en donnant systematiquement
une velocite elevee `
a la premi`ere note de chaque groupe de 4. Le script suivant remplace la
boucle de generation de notes par notre nouvel algorithme.


9.4. LA METHODE
CONSTRUCTEUR

1
2

103

from pyo import


import random

3
4
5
6
7
8

c l a s s Note :
Conteneur pour n o t e Midi
def
i n i t ( s e l f , pit , vel ) :
s e l f . pitch = pit
s e l f . velocity = vel

9
10
11
12

d e f g et No te ( s e l f ) :
Retourne l a n o t e Midi
return ( s e l f . pitch , s e l f . v e l o c i t y )

13
14
15
16

d e f mtof ( s e l f ) :
Retourne l a f r e q u e n c e en Hertz de l a n o t e
r e t u r n 8 . 1 7 5 7 9 8 pow ( 1 . 0 5 9 4 6 3 3 , s e l f . p i t c h )

17
18
19
20

d e f vtoa ( s e l f ) :
Retourne l a m p l i t u d e de l a n o t e e n t r e 0 e t 1
return s e l f . velocity / 127.

21
22
23

num notes = 200


notes list = []

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

p i t = 64 # I n i t i a l i s a t i o n de l a h a u t e u r de d e p a r t
f o r i i n r a n g e ( num notes ) :
# Marche a l e a t o i r e . Ajoute une v a l e u r p a i r e e n t r e 4 e t 5 au d e r n i e r p i t c h
p i t = random . r a n d r a n g e ( 4 , 5 , 2 ) + p i t
# Impose d e s l i m i t e s
i f pit < 48:
p i t = 48
e l i f pit > 84:
p i t = 84
i f ( i % 4 ) == 0 :
v e l = 40 # Temps f o r t s
else :
v e l = random . r a n d i n t ( 8 , 2 5 ) # Temps f a i b l e s
n o t e s l i s t . append ( Note ( p i t , v e l ) )

39
40

s = S e r v e r ( ) . boot ( )

41
42
43
44
45
46

47

48
49

fades , oscs = [ ] , [ ]
f o r i i n r a n g e ( num notes ) :
note = n o t e s l i s t [ i ]
start = i .125
f = Fader ( f a d e i n =.01 , f a d e o u t =.99 , dur =1, mul=n o t e . vtoa ( ) ) . p l a y ( d e l a y=s t a r t ,
dur =1)
o s c = SineLoop ( f r e q=n o t e . mtof ( ) , f e e d b a c k =.05 , mul=f ) . out ( i %2, d e l a y=s t a r t ,
dur =1)
f a d e s . append ( f )
o s c s . append ( o s c )

50
51

s . gui ( l o c a l s () )

scripts/chapitre 09/02 classe note 2.py


CHAPITRE 9. CLASSES ET METHODES

104

9.5

Exemple de classe dans un fichier externe

Le principe de se creer une librairie personnelle consiste `a ecrire un module contenant une
collection de classes que lon peut importer `a volonte dans nos scripts. Voici un exemple de
module contenant une classe generant des particules de son.
1

from pyo import

2
3
4
5
6
7
8
9
10
11
12
13

class Particule :
def
i n i t ( s e l f , input , time =.125 , q=20 ,
maxdur =.2 , f r a n g e = [ 3 5 0 , 1 0 0 0 0 ] , p o l y =12) :
# Enveloppe d a m p l i t u d e
s e l f . t a b l e = LinTable ( [ ( 0 , 0 ) , ( 1 0 0 , 1 ) , ( 5 0 0 , . 3 ) , ( 8 1 9 1 , 0 ) ] )
# InputFader permet de f a i r e d e s c r o s s f a d e s s u r l e son s o u r c e
s e l f . i n p u t = InputFader ( i n p u t )
# Tous l e s p a r a m e t r e s v a r i a b l e s s o n t c o n v e r t i s en a u d i o
s e l f . time = S i g ( time )
s e l f . q = Sig (q)
s e l f . maxdur = S i g ( maxdur )

14
15
16
17
18
19
20
21
22
23
24

# G e n e r a t i o n de t r i g s
s e l f . metro = Metro ( s e l f . time , p o l y=p o l y ) . p l a y ( )
# P i g e de v a l e u r s de f r e q u e n c e e t de d u r e e
s e l f . f r e q = TrigRand ( s e l f . metro , min=f r a n g e [ 0 ] , max=f r a n g e [ 1 ] )
s e l f . dur = TrigRand ( s e l f . metro , min =.01 , max= s e l f . maxdur )
# L e c t u r e de l e n v e l o p p e d a m p l i t u d e
s e l f . amp = TrigEnv ( s e l f . metro , t a b l e= s e l f . t a b l e , dur= s e l f . dur )
# Particule f i l t r e e
s e l f . f i l t r e = Biquadx ( s e l f . input , f r e q= s e l f . f r e q , q= s e l f . q ,
type =2, s t a g e s =2, mul= s e l f . amp)

25
26
27
28
29

d e f out ( s e l f ) :
Envoie l e son aux hautp a r l e u r s e t r e t o u r n e l o b j e t l u i meme .
s e l f . f i l t r e . out ( )
return s e l f

30
31
32
33
34

d e f getOut ( s e l f ) :
Retourne l o b j e t a u d i o q u i g e n e r e l e s i g n a l de s o r t i e de l a
c l a s s e a f i n de p o u v o i r l i n c l u r e dans une c h a i n e de t r a i t e m e n t .
return s e l f . f i l t r e

35
36
37

d e f s e t I n p u t ( s e l f , x , f a d e t i m e =.05) :
s e l f . input . setInput (x , fadetime )

38
39
40

d e f setTime ( s e l f , x ) :
s e l f . time . v a l u e = x

41
42
43

d e f setQ ( s e l f , x ) :
s e l f . q . value = x

44
45
46

d e f setMaxDur ( s e l f , x ) :
s e l f . maxdur . v a l u e = x

scripts/chapitre 09/malibrairie.py

9.5. EXEMPLE DE CLASSE DANS UN FICHIER EXTERNE

105

Ensuite, il suffit dimporter malibrairie dans un script pour avoir acc`es aux classes qui
y sont definies. Dans un second fichier (situe dans le meme dossier que malibrairie.py afin
deviter les probl`emes), on importe et on utilise la classe Particule :
1
2
3
4
5

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import
from m a l i b r a i r i e import P a r t i c u l e
import random

6
7

s = S e r v e r ( ) . boot ( )

8
9
10
11
12

### D i f f e r e n t e s s o u r c e s s o n o r e s ###
a = Noise ( . 3 )
a1 = SineLoop ( f r e q =50 , f e e d b a c k =.2 , mul=1)
a2 = FM( c a r r i e r =100 , r a t i o =5.67 , i n d e x =20 , mul =.3)

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

### 5 e xemples d u t i l i s a t i o n de l a c l a s s e P a r t i c u l e ###


which = 0
i f which == 0 :
b = P a r t i c u l e ( a , time =.125 , q=2 , maxdur =.5) . out ( )
e l i f which == 1 :
q l f o = S i n e ( . 1 , mul=5 , add=6)
b = P a r t i c u l e ( a , time =.125 , q=q l f o , maxdur =.25) . out ( )
e l i f which == 2 :
t l f o = S i n e ( . 1 5 , mul =.1 , add =.15)
q l f o = S i n e ( . 1 , mul=5 , add=6)
b = P a r t i c u l e ( a , time=t l f o , q=q l f o , maxdur =.25) . out ( )
e l i f which == 3 :
b = P a r t i c u l e ( i n p u t=a , time =.25 , q=10 , maxdur =.5 , f r a n g e = [ 3 5 0 , 1 0 0 0 ] ) . out ( )
c = P a r t i c u l e ( a , time =.125 , q=5 , maxdur =.25 , f r a n g e = [ 2 0 0 0 , 1 0 0 0 0 ] ) . out ( )
e l i f which == 4 :
t l f o = S i n e ( . 1 5 , mul =.1 , add =.15)
q l f o = S i n e ( . 1 , mul=5 , add=6)
b = P a r t i c u l e ( a , time=t l f o , q=q l f o , maxdur =.25)
d = Delay ( b . getOut ( ) . mix ( 2 ) , d e l a y =.5 , f e e d b a c k =.75)
c = F r e e v e r b ( d , s i z e =.8 , damp=.9 , b a l =.4) . out ( )

34
35
36
37
38
39
40
41
42

d e f change ( ) :
y = random . r a n d i n t ( 0 , 2 )
i f y == 0 :
b . setInput ( a , 2)
e l i f y == 1 :
b . s e t I n p u t ( a1 , 2 )
e l i f y == 2 :
b . s e t I n p u t ( a2 , 2 )

43
44
45

# pat . p l a y ( ) a c t i v e l e changement de s o u r c e automatique


pat = P a t t e r n ( change , 5 )

46
47

s . gui ( l o c a l s () )

scripts/chapitre 09/03 classe particule.py

106

CHAPITRE 9. CLASSES ET METHODES

Chapitre 10

Contr
oleurs externes
La manipulation des processus audio via des controleurs externes est tr`es efficace pour produire des variations de param`etres aux contours naturels. Deux protocoles de communication
seront explores dans ce chapitre. Nous allons tout dabord nous attarder au protocole Midi qui
permettra la creation de synthetiseurs virtuels simples et efficaces. Puis, nous elaborerons sur
le protocole OSC (Open Sound Control ) qui offre un controle du data plus generalise que le
protocole Midi.

10.1

Configuration Midi

Pour utiliser une interface Midi dans un script python, il faut dabord sassurer que le serveur
audio (cest lobjet Server qui se charge des entrees/sorties Midi) recoit bien le data de linterface
desiree. Deux fonctions sont disponibles pour tester la configuration Midi :
pm list devices() affiche lensemble des interfaces connectees au syst`eme.
pm get default input() retourne le numero de linterface par defaut.
>>> p m l i s t d e v i c e s ( )
MIDI d e v i c e s :
0 : IN , name : IAC D r i v e r Bus 1 , i n t e r f a c e : CoreMIDI
1 : IN , name : K e y s t a t i o n Port 1 , i n t e r f a c e : CoreMIDI
2 : OUT, name : IAC D r i v e r Bus 1 , i n t e r f a c e : CoreMIDI
3 : OUT, name : K e y s t a t i o n Port 1 , i n t e r f a c e : CoreMIDI
>>> p m g e t d e f a u l t i n p u t ( )
0

Si linterface Midi par defaut nest pas linterface desiree, il suffit de donner le numero
de linterface `
a la methode setMidiInputDevice() de lobjet Server avant dappeler la methode
boot(). Avec la configuration ci-dessus, pour utiliser le clavier Midi Keystation, on doit specifier
linterface numero 1 :
from pyo import
s = Server ()
s . setMidiInputDevice (1)
s . boot ( )

107


CHAPITRE 10. CONTROLEURS
EXTERNES

108

10.2

Synth
etiseur Midi

Ce script implemente une classe generant un son de synth`ese sur reception de notes Midi.
1
2
3

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import

4
5
6
7
8

c l a s s Synth :
def
i n i t ( s e l f , t r a n s p o =1) :
# F a c t e u r de t r a n s p o s i t i o n
s e l f . transpo = Sig ( transpo )

9
10
11

# R e c o i t l e s n o t e s Midi e t l e s a s s i g n e s s u r 10 v o i x de p o l y p h o n i e
s e l f . n o t e = Note in ( p o l y =10 , s c a l e =1, f i r s t =0 , l a s t =127)

12
13
14
15
16

# Traitement d e s v a l e u r s de h a u t e u r e t d a m p l i t u d e d e s n o t e s Midi
s e l f . p i t = s e l f . note [ pitch ] s e l f . transpo
s e l f . amp = MidiAdsr ( s e l f . n o t e [ v e l o c i t y ] , a t t a c k =0.001 ,
decay =.1 , s u s t a i n =.7 , r e l e a s e =2 , mul =.1)

17
18
19
20
21
22
23

# Chorus de 4 o s c i l l a t e u r s , mixes en mono pour e v i t e r


# l a l t e r n a n c e panoramique d e s 10 v o i x de p o l y p h o n i e
s e l f . o s c 1 = SineLoop ( s e l f . p i t , f e e d b a c k =0.12 , mul= s e l f . amp) . mix ( 1 )
s e l f . o s c 2 = SineLoop ( s e l f . p i t . 9 9 7 , f e e d b a c k =0.12 , mul= s e l f . amp) . mix ( 1 )
s e l f . o s c 3 = SineLoop ( s e l f . p i t . 9 9 4 , f e e d b a c k =0.12 , mul= s e l f . amp) . mix ( 1 )
s e l f . o s c 4 = SineLoop ( s e l f . p i t 1 . 0 0 2 , f e e d b a c k =0.12 , mul= s e l f . amp) . mix ( 1 )

24
25
26

# Mixage s t e r e o
s e l f . mix = ( s e l f . o s c 1+ s e l f . o s c 2+ s e l f . o s c 3+ s e l f . o s c 4 ) . mix ( 2 )

27
28
29
30
31

d e f out ( s e l f ) :
A c t i v e l e n v o i du s i g n a l aux s o r t i e s e t r e t o u r n e l o b j e t l u i meme .
s e l f . mix . out ( )
return s e l f

32
33
34
35

def sig ( s e l f ) :
Retourne l o b j e t q u i p r o d u i t l e s i g n a l f i n a l de l a c h a i n e a u d i o .
r e t u r n s e l f . mix

36
37
38
39
40
41

# C o n f i g u r a t i o n a u d i o / midi
idev = pm get default input ()
s = Server ()
s . s e t M i d i I n p u t D e v i c e ( i d e v ) # Changer i d e v en f o n c t i o n de v o t r e c o n f i g u r a t i o n
s . boot ( )

42
43
44

a1 = Synth ( ) # o c t a v e r e e l
a2 = Synth ( . 5 ) # o c t a v e i n f e r i e u r

45
46
47

# La Somme d e s s i g n a u x d e s s y n t h s p a s s e dans une r e v e r b e r a t i o n


r e v = WGVerb( a1 . s i g ( )+a2 . s i g ( ) , f e e d b a c k =.8 , c u t o f f =3500 , b a l =.3) . out ( )

48
49

s . gui ( l o c a l s () )

scripts/chapitre 10/01 midi synth.py


10.2. SYNTHETISEUR
MIDI

109

Deux nouveaux objets sont introduit ici, Notein et MidiAdsr. Le premier recoit les notes du
clavier Midi et gen`ere deux streams audio distincts par note, un pour la hauteur (self.note[pitch] )
et un pour lamplitude (self.note[velocity] ). Le second gen`ere une enveloppe ADSR classique
en fonction de la velocite de la note. Voici une version leg`erement bonifiee de notre programme !
1
2
3
4

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import
from random import uni for m

5
6
7
8
9
10
11
12

c l a s s Synth :
def
i n i t ( s e l f , t r a n s p o =1) :
s e l f . transpo = Sig ( transpo )
s e l f . n o t e = Not ein ( p o l y =8, s c a l e =1 , f i r s t =0, l a s t =127)
s e l f . p i t = s e l f . note [ pitch ] s e l f . transpo
s e l f . amp = MidiAdsr ( s e l f . n o t e [ v e l o c i t y ] , a t t a c k =0.001 ,
decay =.1 , s u s t a i n =.7 , r e l e a s e =1 , mul =.3)

13
14
15
16
17

self
self
self
self

. osc1
. osc2
. osc3
. osc4

=
=
=
=

LFO( f r e q= s e l f
LFO( f r e q= s e l f
LFO( f r e q= s e l f
LFO( f r e q= s e l f

. p i t , s h a r p =0.25 , mul= s e l f . amp) . mix ( 1 )


. p i t 0 . 9 9 7 , s h a r p =0.25 , mul= s e l f . amp) . mix ( 1 )
. p i t 1 . 0 0 4 , s h a r p =0.25 , mul= s e l f . amp) . mix ( 1 )
. p i t 1 . 0 0 9 , s h a r p =0.25 , mul= s e l f . amp) . mix ( 1 )

18
19
20

# Mix s t e r e o ( o s c 1 e t o s c 3 a gauche , o s c 2 e t o s c 4 a d r o i t e )
s e l f . mix = Mix ( [ s e l f . o s c 1+ s e l f . osc3 , s e l f . o s c 2+ s e l f . o s c 4 ] , v o i c e s =2)

21
22
23
24

# D i s t o r t i o n avec LFO s u r l e d r i v e
s e l f . l f o = S i n e ( f r e q=uni for m ( . 2 , . 4 ) , mul =0.45 , add =0.5)
s e l f . d i s t o = D i s t o ( s e l f . mix , d r i v e= s e l f . l f o , s l o p e =0.95 , mul =.2)

25
26
27
28

d e f out ( s e l f ) :
s e l f . d i s t o . out ( )
return s e l f

29
30
31

def sig ( s e l f ) :
return s e l f . disto

32
33
34
35
36

idev = pm get default input ()


s = Server ()
s . setMidiInputDevice ( idev )
s . boot ( )

37
38
39
40
41

# r o u e de modulation = a m p l i t u d e du v i b r a t o
c t l = M i d i c t l ( 1 , m i n s c a l e =0, m axsca le =.2)
bend = Bendin ( brange =2, s c a l e =1) # P i t c h bend
l f = S i n e ( f r e q =5, mul=c t l , add=1) # V i b r a t o

42
43
44
45

a1 = Synth ( l f bend )
comp = Compress ( a1 . s i g ( ) , t h r e s h =20, r a t i o =6)
r e v = WGVerb( comp , f e e d b a c k =.8 , c u t o f f =3500 , b a l =.3) . out ( )

46
47

s . gui ( l o c a l s () )

scripts/chapitre 10/02 midi synth 2.py


CHAPITRE 10. CONTROLEURS
EXTERNES

110

Ce programme presente deux nouveaux objets de la librairie Midi, Midictl, pour recuperer
les valeurs dun contr
oleur continu, et Bendin, pour recuperer les valeurs du controleur Pitch
Bend.

10.3

G
en
erateur de boucles audio contr
olable en Midi

La classe suivante lit un ou plusieurs fichiers sons en boucle et offre le controle sur les
transpositions via le clavier Midi.
1
2
3

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import

4
5
6
7
8
9
10
11
12

c l a s s SndSynth :
def
i n i t ( s e l f , path , f i r s t =0 , l a s t =127) :
# P l a c e l e son en memoire
s e l f . t a b l e = SndTable ( path )
# s c a l e =2 c o n v e r t i t l e s n o t e s midi en f a c t e u r s de t r a n s p o s i t i o n
s e l f . n o t e i n = N ote in ( p o l y =10 , s c a l e =2, f i r s t =f i r s t , l a s t=l a s t )
s e l f . transpo = s e l f . notein [ p i t c h ] s e l f . t a b l e . getRate ( )
s e l f . amp = Port ( s e l f . n o t e i n [ v e l o c i t y ] , r i s e t i m e =0.001 , mul =.5)

13
14
15
16

# Osc > l i t une t a b l e en b o u c l e


s e l f . o s c = Osc ( s e l f . t a b l e , f r e q= s e l f . t r a n s p o , mul= s e l f . amp) . mix ( 1 )
s e l f . mix = s e l f . o s c . mix ( 2 )

17
18
19
20

d e f out ( s e l f ) :
s e l f . mix . out ( )
return s e l f

21
22
23

def sig ( s e l f ) :
r e t u r n s e l f . mix

24
25
26
27
28

idev = pm get default input ()


s = Server ()
s . setMidiInputDevice ( idev )
s . boot ( )

29
30
31
32
33
34
35
36

# C l a v i e r Midi s e p a r e en r e g i o n s par t i e r c e mineure


# a u t o u r d e s n o t e s 6 0 , 6 3 , 6 6 , 6 9 , 7 2 , 75
li = []
f o r i in range (1 , 7) :
f i l e n a m e = s n d %i . a i f % i
c e n t r a l k e y = 57 + i 3
l i . append ( SndSynth ( f i l e n a m e , f i r s t =c e n t r a l k e y 1, l a s t=c e n t r a l k e y +1) . out ( ) )

37
38

s . gui ( l o c a l s () )

scripts/chapitre 10/03 midi synth snd.py


10.4. SIMILI-ECHANTILLONNEUR

10.4

111

Simili-
echantillonneur

Cette classe permet le declenchement et la transposition de lectures de sons via le clavier Midi.
Lobjet Compare est utilise pour detecter les noteons et generer les trigs servant `a activer les
lectures de table.

1
2
3

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import

4
5
6
7
8
9
10
11

c l a s s SndSynth :
def
i n i t ( s e l f , path , f i r s t =0 , l a s t =127) :
s e l f . t a b l e = SndTable ( path )
s e l f . n o t e i n = N ote in ( p o l y =10 , s c a l e =2, f i r s t =f i r s t , l a s t=l a s t )
# Duree de l e c t u r e de l a t a b l e = d u r e e t a b l e / f a c t e u r t r a n s p o
s e l f . dur = s e l f . t a b l e . getDur ( ) / s e l f . n o t e i n [ p i t c h ]
s e l f . amp = Port ( s e l f . n o t e i n [ v e l o c i t y ] , r i s e t i m e =0.001 , mul =.5)

12
13
14
15
16
17

# S i l a v e l o c i t e de l a n o t e > 0 ( noteon ) , Compare e n v o i e un 1


# S i l a comparaison e s t f a u s s e ( n o t e o f f ) , Compare e n v o i e 0
s e l f . comp = Compare ( s e l f . n o t e i n [ v e l o c i t y ] , comp=0, mode=> )
# S e l e c t e n v o i e un t r i g l o r s q u i l v o i t un 1 p a s s e r
s e l f . t r i g = S e l e c t ( s e l f . comp , v a l u e =1)

18
19
20
21

s e l f . snd = TrigEnv ( s e l f . t r i g , t a b l e= s e l f . t a b l e , dur= s e l f . dur ,


mul= s e l f . amp) . mix ( 1 )
s e l f . mix = s e l f . snd . mix ( 2 )

22
23
24
25

d e f out ( s e l f ) :
s e l f . mix . out ( )
return s e l f

26
27
28

def sig ( s e l f ) :
r e t u r n s e l f . mix

29
30
31
32
33

idev = pm get default input ()


s = Server ()
s . setMidiInputDevice ( idev )
s . boot ( )

34
35
36
37
38
39
40

# C l a v i e r Midi s e p a r e en r e g i o n s par o c t a v e e n t r e l e s DOs


li = []
f o r i in range (1 , 7) :
f i l e n a m e = s n d %i . a i f % i
f i r s t k e y = i 12 + 24
l i . append ( SndSynth ( f i l e n a m e , f i r s t =f i r s t k e y , l a s t=f i r s t k e y +11) . out ( ) )

41
42

s . gui ( l o c a l s () )

scripts/chapitre 10/04 midi synth snd 2.py


CHAPITRE 10. CONTROLEURS
EXTERNES

112

10.5

Granulateur simple

Est presente ici un granulateur de fichiers sons qui servira de pretexte au controle de
param`etre via le protocole OSC (Open Sound Control).
1
2
3

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import

4
5

s = S e r v e r ( ) . boot ( )

6
7
8
9

env = HannTable ( )
t a b l e = SndTable ( Beethoven . a i f )
durInSamps = t a b l e . getDur ( ) s . getSamplingRate ( )

10
11
12
13
14
15
16
17

# exemple 0 > changement de v i t e s s e s a n s t o u c h e r a l a h a u t e u r


# exemple 1 > p o s i t i o n de l e c t u r e a l e a t o i r e
ex = 0
i f ex == 0 :
pos = Phasor ( f r e q=t a b l e . g e t R a t e ( ) 0 . 2 5 , mul=durInSamps )
e l i f ex == 1 :
pos = Randh ( min=0, max=durInSamps , f r e q =100)

18
19
20

pit = [1. , 1.002]


dur = N o i s e ( mul =.002 , add =.1)

# l e g e r e s v a r i a t i o n s de l a d u r e e d e s g r a i n s

21
22
23
24
25
26
27
28

g r a i n = G r a n u l a t o r ( t a b l e=t a b l e ,
env=env ,
p i t c h=p i t ,
pos=pos ,
dur=dur ,
g r a i n s =32 ,
b a s e d u r =.1 ,

29

#
#
#
#
#
#
#
#

t a b l e contenant l e s e c h a n t i l l o n s
enveloppe des g r a i n s
pitch g l o b a l des g r a i n s
p o s i t i o n de l e c t u r e , en e c h a n t i l l o n s
d u r e e d e s g r a i n s en s e c o n d e s
nombre de g r a i n s
d u r e e de r e f e r e n c e pour l e s g r a i n s
( s i dur == basedur , pas de t r a n s p o )

mul =.1) . out ( )

30
31
32

s . gui ( l o c a l s () )

scripts/chapitre 10/05 granulateur.py

10.6

Contr
ole du granulateur via le protocole OSC

Pour lexemple suivant, nous utiliserons deux scripts python. Le premier reprend le granulateur de lexemple precedent et modifie les controles pour recevoir des donnees via le protocole
OSC. Le second script contr
ole la position de lecture ainsi que la duree des grains du granulateur en propageant les donnees sur le numero de port quecoute le premier script. Les donnees
de controle, dans un envoie OSC, sont identifiees `a laide dun syst`eme dadresses. Les adresses,
specifiees en format string, utilisent la syntaxe des paths Unix, avec la barre oblique ( / ) comme
separateur. Exemple : /data/freq, /data/amp, etc.


10.6. CONTROLE
DU GRANULATEUR VIA LE PROTOCOLE OSC

1
2
3

113

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import

4
5

s = S e r v e r ( ) . boot ( )

6
7
8

t a b l e = SndTable ( Beethoven . a i f )
env = HannTable ( )

9
10
11

# Regarde l e p o r t 9000 aux d e s t i n a t i o n s / pos e t / rand


r e c = OscReceive ( p o r t =9000 , a d d r e s s =[ / pos , / rand ] )

12
13
14
15

# r e c [ / pos ] > p o s i t i o n de l e c t u r e
# r e c [ / rand ] > random pour l a d u r e e d e s g r a i n s
pos = Port ( r e c [ / pos ] , r i s e t i m e =.05 , f a l l t i m e =.05 , mul=t a b l e . getDur ( ) 4 4 1 0 0 . )

16
17

pit = [1. , 1.002]

18
19
20

# l e g e r e s v a r i a t i o n s de l a d u r e e d e s g r a i n s
dur = N o i s e ( mul=C l i p ( r e c [ / rand ] , min=0, max=.09) , add =.1)

21
22
23
24
25
26
27
28
29

g r a i n = G r a n u l a t o r ( t a b l e=t a b l e ,
env=env ,
p i t c h=p i t ,
pos=pos ,
dur=dur ,
g r a i n s =32 ,
b a s e d u r =.1 ,
mul =.1) . out ( )

#
#
#
#
#
#
#

t a b l e contenant l e s e c h a n t i l l o n s
enveloppe des g r a i n s
pitch g l o b a l des g r a i n s
p o s i t i o n de l e c t u r e , en e c h a n t i l l o n s
d u r e e d e s g r a i n s en s e c o n d e s
nombre de g r a i n s
d u r e e de r e f e r e n c e pour l e s g r a i n s

30
31

s . gui ( l o c a l s () )

scripts/chapitre 10/06 osc receive.py


1
2
3

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
from pyo import

4
5

s = S e r v e r ( ) . boot ( )

6
7
8

# Un l f o q u i c o n t r o l e l a p o s i t i o n de l e c t u r e n o r m a l i s e e e n t r e 0 e t 1
l f o = S i n e ( . 0 5 , mul =.25 , add =.5)

9
10
11
12

# C o n t r o l e manuel s u r l a t r a n s p o s i t i o n par g r a i n
rnd = S i g ( 0 )
rnd . c t r l ( t i t l e = T r a n s p o s i t i o n par g r a i n )

13
14
15
16

# Envoie l e s c o n t r o l e s s u r l e p o r t 9000 aux d e s t i n a t i o n s / pos e t / rand


# h o s t e s t l a d r e s s e IP de l a machine c i b l e e . 1 2 7 . 0 . 0 . 1 = machine l o c a l e
send = OscSend ( [ l f o , rnd ] , p o r t =9000 , a d d r e s s =[ / pos , / rand ] , h o s t= 1 2 7 . 0 . 0 . 1 )

17
18

s . gui ( l o c a l s () )

scripts/chapitre 10/07 osc send.py

114

CHAPITRE 10. CONTROLEURS


EXTERNES

Chapitre 11

Cr
eation dinterfaces graphiques I
11.1

Introduction `
a la librairie graphique wxPython

Le langage de programmation Python en lui-meme ne permet pas la creation dinterfaces


graphiques. Par contre, il existe un certain nombre de modules donnant acc`es `a des librairies
concues expressement pour le developpement dinterfaces homme-machine. Les deux librairies les
plus courantes aujourdhui sont pyQT et wxPython. Elles offrent toutes deux une vaste gamme de
classes permettant limplementation des comportements standards dun logiciel. Elles ont aussi
lavantage detre multi-plateformes, cest-`a-dire que le meme code va etre execute correctement
sous les differents syst`emes dexploitation les plus repandus (Windows, Mac OS et Linux). Pour
cette introduction au design dinterfaces graphiques, nous allons utiliser la librairie wxPython,
que vous devez installer independamment sur votre syst`eme si ce nest dej`a fait.
Les ressources
Le site web officiel de wxPython
La page de telechargement de wxPython
La documentation classe par classe de wxPython
Mise en garde
Sur la page de telechargement de wxPython, vous avez le choix entre la version ansi et
la version unicode pour les differentes versions de python. Il est recommande dinstaller la
version unicode car elle permet la gestion des accents et autres caract`eres qui ne font pas
partie de la grammaire anglophone.
Les 4
etapes essentielles de la construction dune interface graphique sont :

La gestion de la boucle dexecution principale du logiciel.


Les conteneurs, cest-`
a-dire la fenetre et les panneaux o`
u sera exposee linterface.
Le contenu, cest-`
a-dire les objets offrant une interaction avec lutilisateur.
Linteraction entre la manipulation des objets et les fonctionnalites du programme, sous
la forme de methodes.
115


CHAPITRE 11. CREATION
DINTERFACES GRAPHIQUES I

116

11.1.1

La gestion de la boucle dex


ecution

La gestion de la boucle principale se fait par le biais dun objet wx.App ou dun de ses derives.
Lobjet wx.PySimpleApp, qui initialise les comportements de base du logiciel, permet de mettre
en place une application wx tr`es rapidement. Un point important, qui vaut pour toute librairie
dinterface graphique, est que cette derni`ere prendra eventuellement possession de la boucle
dexecution de python, permettant ansi au logiciel de rester actif pour une duree indeterminee.
wx prend possession de la boucle `
a partir du moment o`
u la methode MainLoop est appelee sur
un objet de la classe wx.App. Cet appel est en general `a la derni`ere ligne du script principal
puisque les lignes suivantes ne seront pas executees tant que linterface naura pas quitte.
Le script suivant commence par importer la librairie wx, puis declare un objet wx.PySimpleApp.
Un objet de la classe wx.App doit absolument exister avant de commencer `a construire des objets
dinterfaces. Une fenetre est ensuite creee (wx.Frame) et affichee `a lecran (methode Show). Nous
detaillerons les conteneurs dans le script suivant. Enfin, lorsque tout est en place, on appelle
la methode MainLoop sur notre objet wx.App. La boucle dexecution passe alors aux mains de
notre application et attend de recevoir des evenements pour executer diverses fonctions.
1

import wx

2
3

app = wx . PySimpleApp ( )

4
5
6

mainFrame = wx . Frame ( None , t i t l e = Simple App )


mainFrame . Show ( )

7
8

app . MainLoop ( )

scripts/chapitre 11/01 mainloop.py


` lexecution de ce script une fenetre comme celle-ci devrait apparatre `a lecran :
A

11.1.2

Les conteneurs

La boucle dexecution du programme est maintenant sous le controle de linterface tant que
celle-ce ne quitte pas. Un conteneur a dej`a ete cree puisquune interface graphique ne peut vivre

` LA LIBRAIRIE GRAPHIQUE WXPYTHON


11.1. INTRODUCTION A

117

sans au moins une fenetre affichee `


a lecran. Nous utiliserons 2 objets de la librairie wx en guise de
conteneur. Le premier (wx.Frame) constitue le cadre principal de notre application, cest-`
a-dire
la fenetre delimitant lespace occupe par notre application `a lecran. Dans cette fenetre, nous
allons creer un ou plusieurs panneaux (wx.Panel) o`
u seront affiches tous les elements dinterface
de notre programme.
Les objets fournis dans une librairie graphique constituent generalement une base `a partir
de laquelle nous pouvons construire une interface avec ses fonctionnalites propres. La technique
la plus repandue consiste `
a creer des classes derivees dune classe de la librairie. Nous allons
donc definir notre propre classe (MyFrame) pour afficher le cadre de lapplication. Remarquez
que la classe wx.Frame est donnee entre parenth`eses comme classe parente `a la classe MyFrame.
Notre methode init recevra les param`etres necessaires `a la creation de la fenetre et les fera
immediatement suivre `
a lappel de la methode init de la classe wx.Frame. Pour quune classe
enfant poss`ede bien toutes les caracteristiques de la classe parente, la methode init de la
classe parente doit etre appelee. Une fois le cadre bien installe, nous allons creer un panneau,
avec lobjet wx.Panel, qui servira a` accueillir les objets dinterface de notre application. La
methode SetBackgroundColour permet de specifier une couleur de fond `a notre panneau.
1

import wx

2
3
4
5
6
7

c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , parent , t i t l e , pos , s i z e ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #000000 )

8
9

app = wx . PySimpleApp ( )

10
11
12

mainFrame = MyFrame( None , t i t l e = Simple App , pos =(100 ,100) , s i z e =(500 ,300) )
mainFrame . Show ( )

13
14

app . MainLoop ( )

scripts/chapitre 11/02 conteneurs.py


Notre application ressemble maintenant `a ceci :


CHAPITRE 11. CREATION
DINTERFACES GRAPHIQUES I

118

Arguments `
a linitialisation de lobjet wx.Frame
self : Lobjet lui-meme passer directement par lappel de la methode. Ne jamais le specifier
lors de lexecution.
parent : Le conteneur dans lequel notre objet est cree. Si cest une fenetre principale, qui
na donc pas de conteneur, on passe None. Notez qu`a la creation du panneau (wx.Panel),
self est bel et bien donne comme premier argument, indiquant au panneau quil est cree
`a linterieur de la fenetre.
id : Identificateur unique de lobjet. -1 indique `a wx de piger automatiquement un identificateur unique.
title : Chane de caract`eres affichee dans la barre de titre de la fenetre.
pos : Tuple indiquant la position (x, y) `a lecran en pixels. (0, 0) est le coin en haut `
a
gauche.
size : Tuple indiquant la taille (x, y) de la fenetre en pixels.

11.1.3

Le contenu

Le contenu comprend tous les objets graphique affiches `a linterieur des panneaux. Nous
utiliserons dans cette introduction le texte statique (wx.StaticText), le bouton `a deux etats
(wx.ToggleButton), le menu deroulant (wx.Choice) et le potentiom`etre (wx.Slider). Les param`etres
dinitialisation varieront en fonction des differents objets, sauf pour les deux premiers arguments,
qui seront toujours le conteneur dans lequel placer lobjet et lidentificateur unique.
Ajoutons `
a notre interface un bouton `a deux etats qui nous permettra de demarrer et darreter
le serveur audio de notre application.
Arguments `
a linitialisation de lobjet wx.StaticText
parent : Le conteneur dans lequel notre objet est cree.
id : Identificateur unique de lobjet.
label : La chane de caract`eres affichee.
pos : Tuple indiquant la position (x, y) `a linterieur du conteneur.
size : Tuple indiquant la taille (x, y) de lobjet. wx.DefaultSize indique de prendre une
taille par defaut en fonction de la longueur du texte `a afficher.
Arguments `
a linitialisation de lobjet wx.ToggleButton
parent : Le conteneur dans lequel notre objet est cree.
id : Identificateur unique de lobjet.
label : La chane de caract`eres affichee `a linterieur du bouton.
pos : Tuple indiquant la position (x, y) `a linterieur du conteneur.
size : Tuple indiquant la taille (x, y) de lobjet. wx.DefaultSize indique de prendre une
taille par defaut en fonction de la longueur du texte `a afficher.

` LA LIBRAIRIE GRAPHIQUE WXPYTHON


11.1. INTRODUCTION A

1
2

119

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

3
4

import wx

5
6
7
8
9
10

c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , parent , t i t l e , pos , s i z e ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )

11
12

13

s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio , pos


=(28 ,10) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f , pos
=(10 ,28) , s i z e=wx . D e f a u l t S i z e )

14
15

app = wx . PySimpleApp ( )

16
17
18

mainFrame = MyFrame( None , t i t l e = Simple App , pos =(100 ,100) , s i z e =(500 ,300) )
mainFrame . Show ( )

19
20

app . MainLoop ( )

scripts/chapitre 11/03 togglebutton.py


Voici letat de notre interface :

Ajoutons maintenant un menu deroulant afin de selectionner un son dans une liste predefinie.
Argument sp
ecifique `
a lobjet wx.Choice
choices : Liste de strings (que lon pourra recuperer pour changer le son source).


CHAPITRE 11. CREATION
DINTERFACES GRAPHIQUES I

120

1
2

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

3
4

import wx

5
6
7
8
9
10

c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , parent , t i t l e , pos , s i z e ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )

11
12
13
14
15

s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,


pos =(28 ,10) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) , s i z e=wx . D e f a u l t S i z e )

16
17
18
19
20
21
22
23

# L i s t e de son c o n t e n u s dans l e meme d o s s i e r que l e s c r i p t


snds = [ snd 1 . a i f , snd 2 . a i f , snd 3 . a i f ,
snd 4 . a i f , snd 5 . a i f , snd 6 . a i f ]
s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= C h o i s i r un son . . . , pos =(10 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,78) ,
s i z e=wx . D e f a u l t S i z e , c h o i c e s=s n d s )

24
25

app = wx . PySimpleApp ( )

26
27
28

mainFrame = MyFrame( None , t i t l e = Simple App , pos =(100 ,100) , s i z e =(500 ,300) )
mainFrame . Show ( )

29
30

app . MainLoop ( )

scripts/chapitre 11/04 popupmenu.py


Le menu apparat maintenant dans notre interface :

` LA LIBRAIRIE GRAPHIQUE WXPYTHON


11.1. INTRODUCTION A

121

Petit truc !
Le module os contient un certain nombre de fonctions utilitaires. Deux de ces fonctions nous
seront particuli`erement utiles afin de peupler notre menu avec tous les sons presents dans le
dossier o`
u se trouve notre script au moment de lexecution.
os.listdir(path) retourne une liste de tous les noms de fichiers dans le repertoire donne en
argument.
os.getcwd() retourne le repertoire courant (generalement celui do`
u est execute le script).
Le generateur de liste suivant exprime donc :
 Pour tous les fichiers dans le r
epertoire courant, tu ajoutes le fichier `a la liste seulement si ses
4 derniers caract`eres sont bien .aif 
s n d s = [ f f o r f i n o s . l i s t d i r ( o s . getcwd ( ) ) i f f [ 4 : ] == . a i f ]

Variante qui inclut dans le menu les sons avec les extensions .wav et .aif.
s n d s = [ f f o r f i n o s . l i s t d i r ( o s . getcwd ( ) ) i f f [ 4 : ] i n [ . wav , . a i f ] ]

11.1.4

Interaction entre linterface et les fonctionnalit


es du programme

Linteraction entre la manipulation des objets et les modifications `a apporter au programme


seffectue `
a laide dun syst`eme devenements auxquels sont associees des methodes.
Les evenements en wx sont des constantes sous la forme wx.EVT EVENTTYPE. Par exemple, le type devenement envoye lors de la manipulation dun toggle est wx.EVT TOGLEBUTTON.
Pour le menu, ce sera wx.EVT CHOICE.
On lie un evenement `
a une methode `a laide de la methode Bind de la classe wx.EvtHandler
(classe parente d`
a peu pr`es tous les objets wx).
o b j . Bind ( event , h a n d l e r )

La methode appelee (handler) recevra en argument un objet derive de la classe wx.Event


contenant les informations sur laction qui a genere levenement. Dans lexemple ci-dessous,
la methode handleAudio, qui sera appelee lors de la manipulation du toggle, prend donc 2
arguments : lobjet lui-meme (self ) ainsi que levenement genere (evt).
d e f handleAudio ( s e l f , e v t ) :
p r i n t e v t . GetInt ( )

Attachons maintenant une methode `a chacun des objets de notre interface. Manipulez les
objets et observez le retour dans la console.


CHAPITRE 11. CREATION
DINTERFACES GRAPHIQUES I

122

1
2

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

3
4

import wx , o s

5
6
7
8
9
10

c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , parent , t i t l e , pos , s i z e ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )

11
12
13
14
15

s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,


pos =(28 ,10) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) , s i z e=wx . D e f a u l t S i z e )

16
17
18

# Un e v e n t du t o g g l e a p p e l l e l a methode s e l f . handleAudio
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

19
20
21
22

# o s . l i s t d i r ( path ) r e t o u r n e t o u s l e s f i c h i e r s dans l e d o s s i e r path


# o s . getcwd ( ) r e t o u r n e l e r e p e r t o i r e c o u r a n t .
s n d s = [ f f o r f i n o s . l i s t d i r ( o s . getcwd ( ) ) i f f [ 4 : ] i n [ . wav , . a i f ] ]

23
24
25
26
27

s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,


l a b e l= C h o i s i r un son . . . , pos =(10 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,78) ,
s i z e=wx . D e f a u l t S i z e , c h o i c e s=s n d s )

28
29
30

# Un e v e n t du menu a p p e l l e l a methode s e l f . setSound


s e l f . popup . Bind (wx . EVT CHOICE, s e l f . setSound )

31
32
33
34

d e f handleAudio ( s e l f , e v t ) :
# e v t . GetInt ( ) r e t o u r n e 1 s i l e t o g g l e e s t a on , 0 s i l e s t a o f f
p r i n t e v t . GetInt ( )

35
36
37
38

d e f setSound ( s e l f , e v t ) :
# e v t . G e t S t r i n g ( ) r e t o u r n e l e s t r i n g s e l e c t i o n n e dans l e menu
print evt . GetString ()

39
40

app = wx . PySimpleApp ( )

41
42
43

mainFrame = MyFrame( None , t i t l e = Simple App , pos =(100 ,100) , s i z e =(500 ,300) )
mainFrame . Show ( )

44
45

app . MainLoop ( )

scripts/chapitre 11/05 eventhandler.py


Notre interface est maintenant prete pour manipuler un processus audio. Dans un premier
temps, nous allons ecrire un petit script audio qui lit une table en boucle. Nous lecrirons dans
lespace de noms global afin que nos objets pyo soit accessibles de partout. Ensuite, il ne restera
qu`a modifier les methodes appelees par les evenements pour controler le processus audio en
cours.

` LA LIBRAIRIE GRAPHIQUE WXPYTHON


11.1. INTRODUCTION A

1
2

123

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

3
4
5

import wx , o s
from pyo import

6
7

s = S e r v e r ( ) . boot ( )

8
9
10
11
12

# L e c t e u r de son en b o u c l e
t a b l e = SndTable ( s n d 1 . a i f )
o s c = Osc ( t a b l e , f r e q=t a b l e . g e t R a t e ( ) )
mix = o s c . mix ( 2 ) . out ( )

13
14
15
16
17
18

c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , parent , t i t l e , pos , s i z e ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )

19
20
21
22
23
24

s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,


pos =(28 ,10) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

25
26
27
28
29
30
31

s n d s = [ f f o r f i n o s . l i s t d i r ( o s . getcwd ( ) ) i f f [ 4 : ] i n [ . wav , . a i f ] ]
s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= C h o i s i r un son . . . , pos =(10 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,78) ,
s i z e=wx . D e f a u l t S i z e , c h o i c e s=s n d s )
s e l f . popup . Bind (wx . EVT CHOICE, s e l f . setSound )

32
33
34
35
36
37

d e f handleAudio ( s e l f , e v t ) :
i f e v t . GetInt ( ) == 1 :
s . start ()
else :
s . stop ()

38
39
40
41

d e f setSound ( s e l f , e v t ) :
t a b l e . sound = e v t . G e t S t r i n g ( )
osc . f r e q = t a b l e . getRate ( )

42
43
44

app = wx . PySimpleApp ( )

45
46
47

mainFrame = MyFrame( None , t i t l e = Simple App , pos =(100 ,100) , s i z e =(500 ,300) )
mainFrame . Show ( )

48
49

app . MainLoop ( )

scripts/chapitre 11/06 audio connections.py


CHAPITRE 11. CREATION
DINTERFACES GRAPHIQUES I

124

Un peu plus de contr


ole
Les 4 etapes principales de la creation dune interface graphique sont maintenant en place.
Les 2 derni`eres simbriqueront `
a chaque nouveau controle insere dans linterface. Un param`etre
quil serait interessant de manipuler est la hauteur du son. Un potentiom`etre est tout indique
pour accomplir cette t
ache. dabord on cree un objet wx.Slider auquel on attache une nouvelle
methode. Notez bien que lobjet wx.Slider ne g`ere que des valeurs enti`eres.
# Texte e x p l i c a t i f s u r l e r o l e du p o t e n t i o m e t r e
s e l f . p i t T e x t = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= P i t c h : 1 . 0 ,
pos =(140 ,60) , s i z e=wx . D e f a u l t S i z e )
# wx . S l i d e r f o n c t i o n n e t o u j o u r s en e n t i e r
s e l f . p i t = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =1000 , minValue =500 ,
maxValue =2000 , pos =(140 ,82) , s i z e=wx . D e f a u l t S i z e )
# On a t t a c h e l a methode s e l f . c h a n g e P i t c h a l evenement wx . EVT SLIDER
s e l f . p i t . Bind (wx . EVT SLIDER , s e l f . c h a n g e P i t c h )

Arguments `
a linitialisation de lobjet wx.Slider
parent : Le conteneur dans lequel notre objet est cree.
id : Identificateur unique de lobjet.
value : Valeur du potentiom`etre `a linitialisation (entier seulement).
minValue : Valeur minimum du potentiom`etre (entier seulement).
maxValue : Valeur maximum du potentiom`etre (entier seulement).
pos : Tuple indiquant la position en pixels dans le conteneur.
size : Tuple indiquant la taille (x, y) de lobjet en pixels.
Ensuite, on cree la methode self.changePitch qui prendra le retour de evt.GetInt() (un entier
representant la valeur du potentiom`etre) afin de modifier lattribut freq de notre oscillateur.
def changePitch ( s e l f , evt ) :
# M a n i p u l a t i o n d e s v a l e u r s pour o b t e n i r un f l o a t e n t r e . 5 e t 2 .
x = e v t . GetInt ( ) 0 . 0 0 1
# S e t L a b e l ( ) permet de m o d i f i e r l e t e x t e a f f i c h e au d e s s u s du p o t e n t i o m e t r e
s e l f . p i t T e x t . S e t L a b e l ( P i t c h : %.3 f % x )
# On m u l t i p l i e n o t r e f a c t e u r de p i t c h par l a f r e q u e n c e
# a l a q u e l l e l a t a b l e e s t l u e a sa hauteur o r i g i n a l e
osc . f r e q = t a b l e . getRate ( ) x

La methode setSound doit etre ajustee pour tenir compte de la valeur du potentiom`etre lors
des changements de sons :
d e f setSound ( s e l f , e v t ) :
# wx . S l i d e r . GetValue ( ) r e t o u r n e l a v a l e u r c o u r a n t e du p o t e n t i o m e t r e
x = s e l f . p i t . GetValue ( ) 0 . 0 0 1
t a b l e . sound = e v t . G e t S t r i n g ( )
osc . f r e q = t a b l e . getRate ( ) x

On colle les morceaux ensembles et on obtient :

` LA LIBRAIRIE GRAPHIQUE WXPYTHON


11.1. INTRODUCTION A

1
2
3
4

125

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
import wx , o s
from pyo import

5
6
7
8
9

s = S e r v e r ( ) . boot ( )
t a b l e = SndTable ( s n d 1 . a i f )
o s c = Osc ( t a b l e , f r e q=t a b l e . g e t R a t e ( ) )
mix = o s c . mix ( 2 ) . out ( )

10
11
12
13
14
15
16
17
18
19
20

c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , parent , t i t l e , pos , s i z e ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )
s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,
pos =(28 ,10) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

21
22
23
24
25
26
27
28
29
30
31
32

s n d s = [ f f o r f i n o s . l i s t d i r ( o s . getcwd ( ) ) i f f [ 4 : ] i n [ . wav , . a i f ] ]
s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= C h o i s i r un son . . . , pos =(10 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,78) ,
s i z e=wx . D e f a u l t S i z e , c h o i c e s=s n d s )
s e l f . popup . Bind (wx . EVT CHOICE, s e l f . setSound )
s e l f . p i t T e x t = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= P i t c h : 1 . 0 ,
pos =(140 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . p i t = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =1000 , minValue =500 ,
maxValue =2000 , pos =(140 ,82) , s i z e=wx . D e f a u l t S i z e )
s e l f . p i t . Bind (wx . EVT SLIDER , s e l f . c h a n g e P i t c h )

33
34
35
36
37
38

d e f handleAudio ( s e l f , e v t ) :
i f e v t . GetInt ( ) == 1 :
s . start ()
else :
s . stop ()

39
40
41
42
43

d e f setSound ( s e l f , e v t ) :
x = s e l f . p i t . GetValue ( ) 0 . 0 0 1
t a b l e . sound = e v t . G e t S t r i n g ( )
osc . f r e q = t a b l e . getRate ( ) x

44
45
46
47
48

def changePitch ( s e l f , evt ) :


x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . p i t T e x t . S e t L a b e l ( P i t c h : %.3 f % x )
osc . f r e q = t a b l e . getRate ( ) x

49
50
51
52
53

app = wx . PySimpleApp ( )
mainFrame = MyFrame( None , t i t l e = Simple App , pos =(100 ,100) , s i z e =(500 ,300) )
mainFrame . Show ( )
app . MainLoop ( )

scripts/chapitre 11/07 pitch slider.py


CHAPITRE 11. CREATION
DINTERFACES GRAPHIQUES I

126

11.1.5

Deux petites am
eliorations

Cr
eation dune classe pour le processus audio
En debut de script, au lieu de definir notre processus audio dans lespace de noms global,
nous allons nous creer une petite classe dans le but de controler le processus `a partir dun objet.
Le serveur sera laisse `
a lexterieur de la classe, ce qui laissera la possibilite de creer plusieurs
instances de la classe Audio tout en ayant quun seul serveur. Ensuite, vers la fin du script,
avant la creation de linterface, on cree un objet `a partir de notre classe Audio et on le donne
en argument `
a linterface afin de pouvoir interagir entre les deux.
1
2

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

3
4
5

import wx , o s
from pyo import

6
7
8
9

# On l a i s s e l e s e r v e u r a l e x t e r i e u r p u i s q u on
# ne peut c r e e r p l u s d un s e r v e u r par s c r i p t
s e r v e r = S e r v e r ( ) . boot ( )

10
11
12
13
14
15

c l a s s Audio :
def
init ( self ) :
s e l f . t a b l e = SndTable ( s n d 1 . a i f )
s e l f . o s c = Osc ( s e l f . t a b l e , f r e q= s e l f . t a b l e . g e t R a t e ( ) )
s e l f . mix = s e l f . o s c . mix ( 2 ) . out ( )

16
17
18
19
20
21
22
23

c l a s s MyFrame(wx . Frame ) :
# Nouvel argument a u d i o
def
i n i t ( s e l f , parent , t i t l e , pos , s i z e , a u d i o ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
s e l f . audio = audio
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )

` LA LIBRAIRIE GRAPHIQUE WXPYTHON


11.1. INTRODUCTION A

127

24
25
26
27
28
29

s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,


pos =(28 ,10) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

30
31
32
33
34
35
36

s n d s = [ f f o r f i n o s . l i s t d i r ( o s . getcwd ( ) ) i f f [ 4 : ] i n [ . wav , . a i f ] ]
s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= C h o i s i r un son . . . , pos =(10 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,78) ,
s i z e=wx . D e f a u l t S i z e , c h o i c e s=s n d s )
s e l f . popup . Bind (wx . EVT CHOICE, s e l f . setSound )

37
38
39
40
41
42

s e l f . p i t T e x t = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= P i t c h : 1 . 0 ,
pos =(140 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . p i t = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =1000 , minValue =500 ,
maxValue =2000 , pos =(140 ,82) , s i z e=wx . D e f a u l t S i z e )
s e l f . p i t . Bind (wx . EVT SLIDER , s e l f . c h a n g e P i t c h )

43
44
45
46
47
48

d e f handleAudio ( s e l f , e v t ) :
i f e v t . GetInt ( ) == 1 :
server . start ()
else :
server . stop ()

49
50
51
52
53

d e f setSound ( s e l f , e v t ) :
x = s e l f . p i t . GetValue ( ) 0 . 0 0 1
s e l f . a u d i o . t a b l e . sound = e v t . G e t S t r i n g ( )
s e l f . audio . osc . f r e q = s e l f . audio . t a b l e . getRate ( ) x

54
55
56
57
58

def changePitch ( s e l f , evt ) :


x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . p i t T e x t . S e t L a b e l ( P i t c h : %.3 f % x )
s e l f . audio . osc . f r e q = s e l f . audio . t a b l e . getRate ( ) x

59
60

app = wx . PySimpleApp ( )

61
62
63
64
65

66

# C r e a t i o n d un o b j e t de l a c l a s s e Audio
a u d i o = Audio ( )
# On p a s s e n o t r e o b j e t en argument au Frame
mainFrame = MyFrame( None , t i t l e = Simple App , pos =(100 ,100) , s i z e =(500 ,300) , a u d i o
=a u d i o )
mainFrame . Show ( )

67
68

app . MainLoop ( )

scripts/chapitre 11/08 classe audio.py

Lavantage dutiliser une classe audio plutot que dinserer le processus sonore au niveau global
du script est quil devient beaucoup plus facile de dupliquer les elements. Il suffit simplement de
creer plus dun objets de la classe Audio.


CHAPITRE 11. CREATION
DINTERFACES GRAPHIQUES I

128

Duplication des
el
ements pour cr
eer une st
er
eophonie
1
2

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

3
4
5

import wx , o s
from pyo import

6
7

s e r v e r = S e r v e r ( ) . boot ( )

8
9
10
11
12
13

c l a s s Audio :
def
i n i t ( s e l f , out =0) :
# Nouvel argument , out , pour s p e c i f i e r l e c a n a l de s o r t i e
s e l f . t a b l e = SndTable ( s n d 1 . a i f )
s e l f . o s c = Osc ( s e l f . t a b l e , f r e q= s e l f . t a b l e . g e t R a t e ( ) ) . out ( out )

14
15
16
17
18
19
20
21

c l a s s MyFrame(wx . Frame ) :
# 2 arguments pour l e s o b j e t s a u d i o
def
i n i t ( s e l f , parent , t i t l e , pos , s i z e , audioL , audioR ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
# v a r i a b l e d i n s t a n c e pour chaque o b j e t a u d i o
s e l f . audioL = audioL
s e l f . audioR = audioR

22
23
24

s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )

25
26
27
28
29
30

s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,


pos =(28 ,10) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

31
32

s n d s = [ f f o r f i n o s . l i s t d i r ( o s . getcwd ( ) ) i f f [ 4 : ] i n [ . wav , . a i f ] ]

33
34
35
36
37
38
39

# I n t e r f a c e c a n a l de gauche
s e l f . popupTextL = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= C h o i s i r un son . . . , pos =(10 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . popupL = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,78) ,
s i z e=wx . D e f a u l t S i z e , c h o i c e s=s n d s )
s e l f . popupL . Bind (wx . EVT CHOICE, s e l f . setSoundL )

40
41
42
43
44
45

s e l f . pitTextL = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= P i t c h : 1 . 0 ,


pos =(140 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . p i t L = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =1000 , minValue =500 ,
maxValue =2000 , pos =(140 ,82) , s i z e=wx . D e f a u l t S i z e )
s e l f . p i t L . Bind (wx . EVT SLIDER , s e l f . changePitchL )

46
47
48
49
50
51
52

# I n t e r f a c e c a n a l de d r o i t e
s e l f . popupTextR = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= C h o i s i r un son . . . , pos =(10 ,160) , s i z e=wx . D e f a u l t S i z e )
s e l f . popupR = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,178) ,
s i z e=wx . D e f a u l t S i z e , c h o i c e s=s n d s )
s e l f . popupR . Bind (wx . EVT CHOICE, s e l f . setSoundR )

` LA LIBRAIRIE GRAPHIQUE WXPYTHON


11.1. INTRODUCTION A

129

53
54
55
56
57
58

s e l f . pitTextR = wx . S t a t i c T e x t ( s e l f . panel , i d =1,


l a b e l= P i t c h : 1 . 0 , pos =(140 ,160) , s i z e=wx . D e f a u l t S i z e )
s e l f . pitR = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =1000 , minValue =500 ,
maxValue =2000 , pos =(140 ,182) , s i z e=wx . D e f a u l t S i z e )
s e l f . pitR . Bind (wx . EVT SLIDER , s e l f . changePitchR )

59
60
61
62
63
64

d e f handleAudio ( s e l f , e v t ) :
i f e v t . GetInt ( ) == 1 :
server . start ()
else :
server . stop ()

65
66
67
68
69
70

d e f setSoundL ( s e l f , e v t ) :
Changement de son , c a n a l de gauche .
x = s e l f . p i t L . GetValue ( ) 0 . 0 0 1
s e l f . audioL . t a b l e . sound = e v t . G e t S t r i n g ( )
s e l f . audioL . o s c . f r e q = s e l f . audioL . t a b l e . g e t R a t e ( ) x

71
72
73
74
75
76

d e f changePitchL ( s e l f , e v t ) :
Changement de v i t e s s e de l e c t u r e , c a n a l de gauche .
x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . pitTextL . S e t L a b e l ( P i t c h : %.3 f % x )
s e l f . audioL . o s c . f r e q = s e l f . audioL . t a b l e . g e t R a t e ( ) x

77
78
79
80
81
82

d e f setSoundR ( s e l f , e v t ) :
Changement de son , c a n a l de d r o i t e .
x = s e l f . pitR . GetValue ( ) 0 . 0 0 1
s e l f . audioR . t a b l e . sound = e v t . G e t S t r i n g ( )
s e l f . audioR . o s c . f r e q = s e l f . audioR . t a b l e . g e t R a t e ( ) x

83
84
85
86
87
88

d e f changePitchR ( s e l f , e v t ) :
Changement de v i t e s s e de l e c t u r e , c a n a l de d r o i t e .
x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . pitTextR . S e t L a b e l ( P i t c h : %.3 f % x )
s e l f . audioR . o s c . f r e q = s e l f . audioR . t a b l e . g e t R a t e ( ) x

89
90

app = wx . PySimpleApp ( )

91
92
93
94

# 2 o b j e t s Audio , c a n a l de s o r t i e en argument
audioL = Audio ( )
audioR = Audio ( 1 )

95
96
97
98
99

# On p a s s e l e s 2 o b j e t s a l i n t e r f a c e
mainFrame = MyFrame( None , t i t l e = Simple App , pos =(100 ,100) , s i z e =(320 ,280) ,
audioL=audioL , audioR=audioR )
mainFrame . Show ( )

100
101

app . MainLoop ( )

scripts/chapitre 11/09 stereo.py


CHAPITRE 11. CREATION
DINTERFACES GRAPHIQUES I

130

11.2
1
2
3
4

S
electeur deffets

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
import wx
from pyo import

5
6
7

s = S e r v e r ( ) . boot ( )
s . amp = 0 . 5

8
9
10
11
12

c l a s s FxSwitch :

C l a s s e a u d i o FxSwitch . R e c o i t un i n p u t a u d i o e t d i r i g e l e s i g n a l
v e r s un d e s q u a t r e s e f f e t s d i s p o n i b l e s .

13
14

Parametres :

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

i n p u t : PyoObject
Signal source a modifier .
f x : s t r i n g { Delay , D i s t o , Chorus , Reverb } , o p t i o n e l
S e l e c t i o n i n i t i a l e de l e f f e t .

def
i n i t ( s e l f , input , f x= Delay ) :
# R e f e r e n c e s d e s v a r i a b l e s r e c u e s en argument
s e l f . input = input
s e l f . fx = fx
# C o n v e r s i o n d e s p a r a m e t r e s en a u d i o ( S i g ) avec portamento ( To )
s e l f . p1 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)
s e l f . p2 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)
# Les 4 e f f e t s d i s p o n i b l e s ( Notez l a p p e l de l a methode s t o p ( ) )
s e l f . d e l a y = Delay ( s e l f . input , d e l a y= s e l f . p1 , f e e d b a c k= s e l f . p2 ) . s t o p ( )
s e l f . d i s t o = D i s t o ( s e l f . input , d r i v e= s e l f . p1 , s l o p e= s e l f . p2 ,
mul =.5) . s t o p ( )
s e l f . c h o r u s = Chorus ( s e l f . input , depth= s e l f . p1 , f e e d b a c k= s e l f . p2 ,
mul =1.5) . s t o p ( )
s e l f . r e v e r b = F r e e v e r b ( s e l f . input , s i z e= s e l f . p1 , damp= s e l f . p2 ) . s t o p ( )


11.2. SELECTEUR
DEFFETS

35
36
37
38
39

# D i c t i o n n a i r e a s s o c i a n t l e s o b j e t s a u d i o a un s t r i n g pour u s a g e f u t u r
s e l f . f x d i c t = { Delay : s e l f . d e l a y , D i s t o : s e l f . d i s t o ,
Chorus : s e l f . chorus , Reverb : s e l f . r e v e r b }
# On f a i t j o u e r l o b j e t donne a l argument f x
s e l f . f x d i c t [ f x ] . out ( )

40
41
42
43
44
45
46
47
48

d e f changeFx ( s e l f , f x ) :
Methode a p p e l e e par l e menu C h o i s i r un e f f e t
# Arrete l e f f e t courant
s e l f . f x d i c t [ s e l f . fx ] . stop ()
# Demarre l e n o u v e l e f f e t
s e l f . f x d i c t [ f x ] . out ( )
# Remplace l a r e f e r e n c e a l e f f e t a c t i f
s e l f . fx = fx

49
50
51
52
53

d e f changeP1 ( s e l f , x ) :
A s s i g n e une n o u v e l l e v a l e u r ( s l i d e r 1 ) au SigTo q u i
c o n t r o l e l e p r e m i e r parametre d e s e f f e t s .
s e l f . p1 . v a l u e = x

54
55
56
57
58

d e f changeP2 ( s e l f , x ) :
A s s i g n e une n o u v e l l e v a l e u r ( s l i d e r 2 ) au SigTo q u i
c o n t r o l e l e deuxieme parametre d e s e f f e t s .
s e l f . p2 . v a l u e = x

59
60
61
62
63
64
65
66
67
68
69
70
71
72

c l a s s MyFrame(wx . Frame ) :
I n t e r f a c e g r a p h i q u e .
Le parametre s w i t c h e r a t t e n d un o b j e t de l a c l a s s e FxSwitch .
def
i n i t ( s e l f , p a r e n t=None , t i t l e =Fx S w i t c h e r ,
pos =(100 ,100) , s i z e =(400 ,140) , s w i t c h e r=None ) :
# Appel de l a methode
init
de l a c l a s s e p a r e n t e en
# l u i p a s s a n t l e s arguments p r o p r e s a l a f e n e t r e .
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
# R e f e r e n c e de l o b j e t FxSwitch
s e l f . switcher = switcher
# C r e a t i o n du panneau
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )

73
74
75
76
77
78
79

# Toggle pour c o n t r o l e r l a c t i v a t i o n du s e r v e u r
s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,
pos =(28 ,10) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) , s i z e=wx . D e f a u l t S i z e )
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

80
81
82
83
84
85
86
87
88

# Menu pour l e c h o i x de l e f f e t
f x s = [ Delay , D i s t o , Chorus , Reverb ]
s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= C h o i s i r un e f f e t , pos =(10 ,60) , s i z e=wx . D e f a u l t S i z e )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,78) ,
s i z e=wx . D e f a u l t S i z e , c h o i c e s=f x s )
s e l f . popup . Bind (wx . EVT CHOICE, s e l f . changeFx )

131

132

89
90
91
92
93
94
95

CHAPITRE 11. CREATION


DINTERFACES GRAPHIQUES I

# Parametre 1
p 1 l a b e l = d e l a y , d r i v e , depth o r s i z e : 0 . 5 0 0
s e l f . p 1 t e x t = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l=p 1 l a b e l ,
pos =(140 ,10) , s i z e =(250 ,20) )
s e l f . p1 = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =500 , minValue =0 ,
maxValue =1000 , pos =(140 ,32) , s i z e =(250 ,20) )
s e l f . p1 . Bind (wx . EVT SLIDER , s e l f . changeP1 )

96
97
98
99
100
101
102
103

# Parametre 2
p 2 l a b e l = f e e d , s l o p e , f e e d o r damp : 0 . 5 0 0
s e l f . p 2 t e x t = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l=p 2 l a b e l ,
pos =(140 ,60) , s i z e =(250 ,20) )
s e l f . p2 = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =500 , minValue =0 ,
maxValue =1000 , pos =(140 ,82) , s i z e =(250 ,20) )
s e l f . p2 . Bind (wx . EVT SLIDER , s e l f . changeP2 )

104
105
106
107
108
109
110

d e f handleAudio ( s e l f , e v t ) :
R e c o i t un ToggleEvent e t demarre ou a r r e t e l e s e r v e u r a u d i o .
i f e v t . GetInt ( ) == 1 :
s . start ()
else :
s . stop ()

111
112
113
114

d e f changeFx ( s e l f , e v t ) :
R e c o i t un ChoiceEvent e t change l e f f e t entendu .
s e l f . s w i t c h e r . changeFx ( e v t . G e t S t r i n g ( ) )

115
116
117
118
119
120

d e f changeP1 ( s e l f , e v t ) :
R e c o i t un S l i d e r E v e n t e t m o d i f i e l e parametre 1 de l e f f e t entendu .
x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . p 1 t e x t . S e t L a b e l ( d e l a y , d r i v e , depth o r s i z e : %.3 f % x )
s e l f . s w i t c h e r . changeP1 ( x )

121
122
123
124
125
126

d e f changeP2 ( s e l f , e v t ) :
R e c o i t un S l i d e r E v e n t e t m o d i f i e l e parametre 2 de l e f f e t entendu .
x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . p 2 t e x t . S e t L a b e l ( f e e d , s l o p e , f e e d o r damp : %.3 f % x )
s e l f . s w i t c h e r . changeP2 ( x )

127
128
129

# Objet d e r i v e de l a c l a s s e wx . App ( o b l i g a t o i r e )
app = wx . PySimpleApp ( )

130
131
132
133
134

# S o u r c e s o n o r e a t r a i t e r ( Changer l a s o u r c e s o n o r e )
s r c = S f P l a y e r ( f l u t e . a i f , l o o p=True ) . mix ( 2 ) . p l a y ( )
# Gestionnaire des e f f e t s
f x s w i t c h = FxSwitch ( s r c )

135
136
137
138
139
140

# C r e a t i o n de l a f e n e t r e . R e c o i t a l argument s w i t c h e r un o b j e t FxSwitch
mainFrame = MyFrame( s w i t c h e r=f x s w i t c h )
mainFrame . Show ( )
# P r i s e du c o n t r o l e de l a b o u c l e d e x e c u t i o n par wxPython
app . MainLoop ( )

scripts/chapitre 11/10 fx switch.py

11.3. SYNTHETISEUR
FM AVEC CONTROLE
MIDI ET INTERFACE GRAPHIQUE 133

11.3

Synth
etiseur FM avec contr
ole Midi et interface graphique

Pour utiliser ce script, vous devez avoir un clavier Midi connecte `a votre ordinateur !
1
2
3
4

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
import wx
from pyo import

5
6
7
8
9
10

# A f f i c h e l e s i n t e r f a c e s Midi d i s p o n i b l e s
pm list devices ()
# I n t e r f a c e Midi par d e f a u t
idef = pm get default input ()
p r i n t I n t e r f a c e Midi par d e f a u t : %d\n % i d e f

11
12
13
14
15
16
17
18

# S i l i n t e r f a c e Midi par d e f a u t n e s t pas l a bonne


# r e m p l a c e z i d e f par l e numero de v o t r e i n t e r f a c e
# dans l a methode s e t M i d i I n p u t D e v i c e .
s = Server ()
s . setMidiInputDevice ( i d e f )
s . boot ( )
s . amp = 0 . 5

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

c l a s s FmSynth :
def
init ( self ) :
s e l f . n o t e = Not ein ( s c a l e =1)
s e l f . amp = Port ( s e l f . n o t e [ v e l o c i t y ] , r i s e t i m e =.001 , f a l l t i m e =1)
s e l f . r a t i o = SigTo ( v a l u e =.25 , time =.05 , i n i t =.25)
s e l f . i n d e x = SigTo ( v a l u e =5 , time =.05 , i n i t =5)
s e l f . i n d e x L i n e = s e l f . amp s e l f . i n d e x
s e l f . fm1 = FM( c a r r i e r= s e l f . n o t e [ p i t c h ] , r a t i o= s e l f . r a t i o ,
i n d e x= s e l f . i n d e x L i n e , mul= s e l f . amp 0 . 1 ) . mix ( )
s e l f . fm2 = FM( c a r r i e r= s e l f . n o t e [ p i t c h ] . 9 9 7 , r a t i o= s e l f . r a t i o ,
i n d e x= s e l f . i n d e x L i n e , mul= s e l f . amp 0 . 1 ) . mix ( )
s e l f . fm3 = FM( c a r r i e r= s e l f . n o t e [ p i t c h ] . 9 9 5 , r a t i o= s e l f . r a t i o ,
i n d e x= s e l f . i n d e x L i n e , mul= s e l f . amp 0 . 1 ) . mix ( )
s e l f . fm4 = FM( c a r r i e r= s e l f . n o t e [ p i t c h ] 1 . 0 0 2 , r a t i o= s e l f . r a t i o ,
i n d e x= s e l f . i n d e x L i n e , mul= s e l f . amp 0 . 1 ) . mix ( )
s e l f . mix = Mix ( [ s e l f . fm1 , s e l f . fm2 , s e l f . fm3 , s e l f . fm4 ] , v o i c e s =2)
s e l f . f i l t = Biquad ( s e l f . mix , f r e q =2000 , q=1, type =0) . out ( )

37
38
39
40
41
42
43
44

c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , p a r e n t=None , t i t l e =u S y n t h e t i s e u r FM ,
pos =(100 ,100) , s i z e =(550 ,300) , synth=None ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
s e l f . synth = synth
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DAD3D0 )

45
46
47
48
49
50
51

s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,


pos =(28 ,10) )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) )
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

134

52
53
54
55
56
57

CHAPITRE 11. CREATION


DINTERFACES GRAPHIQUES I

f i l t e r t y p e s = [ Lowpass , Highpass , Bandpass , Bandstop ]


s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l=Type du f i l t r e , pos =(10 ,60) )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,78) ,
s i z e=wx . D e f a u l t S i z e , c h o i c e s=f i l t e r t y p e s )
s e l f . popup . Bind (wx . EVT CHOICE, s e l f . c h a n g e F i l t e r T y p e )

58
59
60
61
62
63
64

a t t l a b e l = Temps d a t t a q u e : 0 . 0 0 1 s e c
s e l f . t e x t A t t = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l=a t t l a b e l ,
pos =(140 ,10) , s i z e =(250 ,20) )
s e l f . s l i d e r A t t = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =1, minValue =1,
maxValue =2000 , pos =(140 ,32) , s i z e =(400 ,20) )
s e l f . s l i d e r A t t . Bind (wx . EVT SLIDER , s e l f . changeAttack )

65
66
67
68
69
70
71

r e l l a b e l = Temps de r e l a c h e : 1 . 0 0 0 s e c
s e l f . t e x t R e l = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l=r e l l a b e l ,
pos =(140 ,60) , s i z e =(250 ,20) )
s e l f . s l i d e r R e l = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =1000 , minValue =1 ,
maxValue =10000 , pos =(140 ,82) , s i z e =(400 ,20) )
s e l f . s l i d e r R e l . Bind (wx . EVT SLIDER , s e l f . c h a n g e R e l e a s e )

72
73
74
75
76
77
78

r a t l a b e l = FM R a t i o : 0 . 2 5 0 0
s e l f . t e x t R a t i o = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l=r a t l a b e l ,
pos =(140 ,110) , s i z e =(250 ,20) )
s e l f . s l i d e r R a t i o = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =250 , minValue =0 ,
maxValue =2000 , pos =(140 ,132) , s i z e =(400 ,20) )
s e l f . s l i d e r R a t i o . Bind (wx . EVT SLIDER , s e l f . c h a n g e R a t i o )

79
80
81
82
83
84
85

i n d l a b e l = FM Index : 5 . 0 0 0
s e l f . t e x t I n d e x = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l=i n d l a b e l ,
pos =(140 ,160) , s i z e =(250 ,20) )
s e l f . s l i d e r I n d e x = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =5000 , minValue =0 ,
maxValue =50000 , pos =(140 ,182) , s i z e =(400 ,20) )
s e l f . s l i d e r I n d e x . Bind (wx . EVT SLIDER , s e l f . changeIndex )

86
87
88
89
90
91
92

f i l t l a b e l = Frequence du f i l t r e : 2000 Hz
s e l f . t e x t F r e q = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= f i l t l a b e l ,
pos =(140 ,210) , s i z e =(250 ,20) )
s e l f . s l i d e r F r e q = wx . S l i d e r ( s e l f . panel , i d =1, v a l u e =2000 , minValue =100 ,
maxValue =10000 , pos =(140 ,232) , s i z e =(400 ,20) )
s e l f . s l i d e r F r e q . Bind (wx . EVT SLIDER , s e l f . changeFreq )

93
94
95
96
97
98

d e f handleAudio ( s e l f , e v t ) :
i f e v t . GetInt ( ) == 1 :
s . start ()
else :
s . stop ()

99
100
101
102
103
104
105

def changeFilterType ( s e l f , evt ) :


typ = e v t . G e t S t r i n g ( )
i f typ == Lowpass :
s e l f . synth . f i l t . type = 0
e l i f typ == Highpass :
s e l f . synth . f i l t . type = 1

11.3. SYNTHETISEUR
FM AVEC CONTROLE
MIDI ET INTERFACE GRAPHIQUE 135

106
107
108
109

e l i f typ == Bandpass :
s e l f . synth . f i l t . type = 2
e l i f typ == Bandstop :
s e l f . synth . f i l t . type = 3

110
111
112
113
114

d e f changeAttack ( s e l f , e v t ) :
x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . t e x t A t t . S e t L a b e l ( Temps d a t t a q u e : %.3 f s e c % x )
s e l f . synth . amp . r i s e t i m e = x

115
116
117
118
119

def changeRelease ( s e l f , evt ) :


x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . t e x t R e l . S e t L a b e l ( Temps de r e l a c h e : %.3 f s e c % x )
s e l f . synth . amp . f a l l t i m e = x

120
121
122
123
124

def changeRatio ( s e l f , evt ) :


x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . t e x t R a t i o . S e t L a b e l ( FM R a t i o : %.3 f % x )
s e l f . synth . r a t i o . v a l u e = x

125
126
127
128
129

d e f changeIndex ( s e l f , e v t ) :
x = e v t . GetInt ( ) 0 . 0 0 1
s e l f . t e x t I n d e x . S e t L a b e l ( FM Index : %.3 f % x )
s e l f . synth . i n d e x . v a l u e = x

130
131
132
133
134

d e f changeFreq ( s e l f , e v t ) :
x = e v t . GetInt ( )
s e l f . t e x t F r e q . S e t L a b e l ( Frequence du f i l t r e
s e l f . synth . f i l t . f r e q = x

: %d Hz % x )

135
136

app = wx . PySimpleApp ( )

137
138
139
140

synth = FmSynth ( )
mainFrame = MyFrame( synth=synth )
mainFrame . Show ( )

141
142

app . MainLoop ( )

scripts/chapitre 11/11 fm synth.py

136

CHAPITRE 11. CREATION


DINTERFACES GRAPHIQUES I

Chapitre 12

Cr
eation dinterfaces graphiques II
12.1

Interface de contr
ole `
a 2 dimensions

12.1.1

Pr
eambule

Le projet du jour consiste `


a modifier le script qui permet dalterner leffet applique sur une
source sonore (scripts/chapitre 11/10 fx switch.py) afin de lui conferer un peu plus de flexibilite.
Nous verrons dabord comment afficher un dialogue standard pour selectionner le son `a la source
de leffet puis, dans un deuxi`eme temps, nous elaborerons un petit controleur `a 2 dimensions
qui rendra la manipulation des param`etres plus interessante.
La classe audio

Etablissons
dabord notre classe audio en se basant sur la classe FxSwitch, leg`erement modifiee. Lobjet cree `
a partir de la classe FxSwitch peut etre manipuler via lextension de linterpreteur dans la fenetre du serveur.
1
2

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8

3
4

from pyo import

5
6
7

s = S e r v e r ( ) . boot ( )
s . amp = 0 . 5

8
9
10
11
12
13
14
15
16
17
18
19

c l a s s FxSwitch :
def
i n i t ( s e l f , f x= Delay ) :
# g a r d e une r e f e r e n c e a l e f f e t
s e l f . fx = fx
# l i s t e c o n t e n a n t 2 f o i s l e meme son mono pour c r e e r une t a b l e s t e r e o
s e l f . t a b l e = SndTable ( [ SNDS PATH+ / t r a n s p a r e n t . a i f ] 2 )
# l e c t u r e de l a t a b l e en b o u c l e
s e l f . i n p u t = Osc ( s e l f . t a b l e , f r e q= s e l f . t a b l e . g e t R a t e ( ) )
# e n t r e e d e s 2 p a r a m e t r e s avec un portamento de 50 ms .
s e l f . p1 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)
s e l f . p2 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)

20

137


CHAPITRE 12. CREATION
DINTERFACES GRAPHIQUES II

138

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# les 5 effets disponibles .


# Notez l a p p e l . s t o p ( ) pour d e s a c t i v e r l e s p r o c e s s u s a l i n i t
s e l f . d e l a y = Delay ( s e l f . input , d e l a y= s e l f . p1 , f e e d b a c k= s e l f . p2 ) . s t o p ( )
s e l f . d i s t o = D i s t o ( s e l f . input , d r i v e= s e l f . p1 , s l o p e= s e l f . p2 ,
mul =.5) . s t o p ( )
s e l f . d e g r a d e = Degrade ( s e l f . input , b i t d e p t h=S i g ( s e l f . p1 , mul=20 , add=2) ,
s r s c a l e=S i g ( s e l f . p2 , mul =.99 , add =.01) ,
mul =1.5) . s t o p ( )
s e l f . r e v e r b = WGVerb( s e l f . input , f e e d b a c k= s e l f . p1 ,
c u t o f f=S i g ( s e l f . p2 , mul =10000 , add =250) ) . s t o p ( )
s e l f . harmo = Harmonizer ( s e l f . input ,
t r a n s p o=S i g ( s e l f . p1 , mul=24 , add=12) ,
f e e d b a c k= s e l f . p2 ) . s t o p ( )
# d i c t i o n n a i r e pour p o i n t e r s u r l o b j e t de l e f f e t c o u r a n t
s e l f . f x d i c t = { Delay : s e l f . d e l a y , D i s t o : s e l f . d i s t o ,
Degrade : s e l f . degrade , Reverb : s e l f . r e v e r b ,
Harmonizer : s e l f . harmo}
# a p p e l l e l a methode out ( ) s u r l e f f e t donne en argument
s e l f . f x d i c t [ f x ] . out ( )

40
41
42
43
44
45
46
47

d e f changeFx ( s e l f , f x ) :
# Arrete l e f f e t courant
s e l f . f x d i c t [ s e l f . fx ] . stop ()
# Demarre l e n o u v e l e f f e t
s e l f . f x d i c t [ f x ] . out ( )
# Remplace l a r e f e r e n c e a l e f f e t a c t i f
s e l f . fx = fx

48
49
50
51
52
53

d e f changeTable ( s e l f , snd ) :
# p l a c e un nouveau son dans l a t a b l e
s e l f . t a b l e . sound = snd
# a j u s t e l a v i t e s s e de l e c t u r e en f o n c t i o n de l a d u r e e du nouveau son
s e l f . input . f r e q = s e l f . t a b l e . getRate ( )

54
55
56

d e f changeP1 ( s e l f , x ) :
s e l f . p1 . v a l u e = x

57
58
59

d e f changeP2 ( s e l f , x ) :
s e l f . p2 . v a l u e = x

60
61

f x s w i t c h = FxSwitch ( )

62
63

s . gui ( l o c a l s () )

scripts/chapitre 12/01 classe fxswitch.py

Linterface graphique de base


Letape suivante consiste `
a ajouter une interface graphique de base, cest-`a-dire un objet
application (wx.App), une fenetre principale (wx.Frame), un panneau (wx.Panel), un bouton
pour controler lactivation du serveur (wx.ToggleButton) et un menu pour changer leffet entendu
(wx.Choice).


` 2 DIMENSIONS
12.1. INTERFACE DE CONTROLE
A

1
2
3
4

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
import wx
from pyo import

5
6
7

s = S e r v e r ( ) . boot ( )
s . amp = 0 . 5

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

c l a s s FxSwitch :
def
i n i t ( s e l f , f x= Delay ) :
s e l f . fx = fx
s e l f . t a b l e = SndTable ( [ SNDS PATH+ / t r a n s p a r e n t . a i f ] 2 )
s e l f . i n p u t = Osc ( s e l f . t a b l e , f r e q= s e l f . t a b l e . g e t R a t e ( ) )
s e l f . p1 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)
s e l f . p2 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)
s e l f . d e l a y = Delay ( s e l f . input , d e l a y= s e l f . p1 , f e e d b a c k= s e l f . p2 ) . s t o p ( )
s e l f . d i s t o = D i s t o ( s e l f . input , d r i v e= s e l f . p1 , s l o p e= s e l f . p2 ,
mul =.5) . s t o p ( )
s e l f . d e g r a d e = Degrade ( s e l f . input , b i t d e p t h=S i g ( s e l f . p1 , mul=20 , add=2) ,
s r s c a l e=S i g ( s e l f . p2 , mul =.99 , add =.01) ,
mul =1.5) . s t o p ( )
s e l f . r e v e r b = WGVerb( s e l f . input , f e e d b a c k= s e l f . p1 ,
c u t o f f=S i g ( s e l f . p2 , mul =10000 , add =250) ) . s t o p ( )
s e l f . harmo = Harmonizer ( s e l f . input ,
t r a n s p o=S i g ( s e l f . p1 , mul=24 , add=12) ,
f e e d b a c k= s e l f . p2 ) . s t o p ( )
s e l f . f x d i c t = { Delay : s e l f . d e l a y , D i s t o : s e l f . d i s t o ,
Degrade : s e l f . degrade , Reverb : s e l f . r e v e r b ,
Harmonizer : s e l f . harmo}
s e l f . f x d i c t [ f x ] . out ( )

31
32
33
34
35

d e f changeFx ( s e l f , f x ) :
s e l f . f x d i c t [ s e l f . fx ] . stop ()
s e l f . f x d i c t [ f x ] . out ( )
s e l f . fx = fx

36
37
38
39

d e f changeTable ( s e l f , snd ) :
s e l f . t a b l e . sound = snd
s e l f . input . f r e q = s e l f . t a b l e . getRate ( )

40
41
42

d e f changeP1 ( s e l f , x ) :
s e l f . p1 . v a l u e = x

43
44
45

d e f changeP2 ( s e l f , x ) :
s e l f . p2 . v a l u e = x

46
47
48
49
50
51

# c r e a t i o n du c o n t e n e u r p r i n c i p a l en d e r i v a n t l a c l a s s e wx . Frame
c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , p a r e n t=None , t i t l e =Fx S w i t c h e r , pos =(100 ,100) ,
s i z e =(600 ,500) , s w i t c h e r=None ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )

52
53
54

# r e f e r e n c e a l o b j e t FxSwitch que l on d e s i r e c o n t r o l e r
s e l f . switcher = switcher

139


CHAPITRE 12. CREATION
DINTERFACES GRAPHIQUES II

140

55

# panneau ou p l a c e r l e s c o n t r o l e s
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )

56
57
58
59

# Toggle pour c o n t r o l e r l a c t i v a t i o n du s e r v e u r
s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,
pos =(28 ,10) )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) )
# une a c t i o n s u r l e t o g g l e a p p e l l e l a methode s e l f . handleAudio
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

60
61
62
63
64
65
66
67

# Menu pour l e c h o i x de l e f f e t
f x s = [ Delay , D i s t o , Degrade , Reverb , Harmonizer ]
s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= Choose FX , pos =(10 ,100) )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,118) , c h o i c e s=f x s )
# une a c t i o n s u r l e menu a p p e l l e l a methode s e l f . changeFx
s e l f . popup . Bind (wx . EVT CHOICE, s e l f . changeFx )

68
69
70
71
72
73
74
75
76
77
78
79
80

d e f handleAudio ( s e l f , e v t ) :
i f e v t . GetInt ( ) == 1 :
s . start ()
else :
s . stop ()

81
82
83
84

d e f changeFx ( s e l f , e v t ) :
# e v t . G e t S t r i n g ( ) r e t o u r n e l e t e x t e de l e l e m e n t c h o i s i
s e l f . s w i t c h e r . changeFx ( e v t . G e t S t r i n g ( ) )

85
86

app = wx . PySimpleApp ( )

87
88

f x s w i t c h = FxSwitch ( )

89
90
91

mainFrame = MyFrame( s w i t c h e r=f x s w i t c h )


mainFrame . Show ( )

92
93

app . MainLoop ( )

scripts/chapitre 12/02 base frame.py

12.1.2

Bouton et Dialogue standard

Nous allons maintenant inclure 2 nouvelles fonctionnalites qui permettront `a lutilisateur de


naviguer dans sa propre hierarchie de fichiers afin de choisir le son qui sera utilise comme source
dans les effets.
Lobjet wx.Button permet dajouter un bouton dans un panneau avec possibilite de specifier
le texte inscrit sur le bouton lui-meme. Le fonctionnement du bouton est tr`es simple, `a chaque
fois que lon clique dessus, il envoie un ev`enement wx.EVT BUTTON. La methode liee `a cet
ev`enement aura pour r
ole de faire apparatre un dialogue standard pour la selection de fichier.


` 2 DIMENSIONS
12.1. INTERFACE DE CONTROLE
A

141

On cree un dialogue avec lobjet wx.FileDialog dont la methode ShowModal() provoquera


laffichage `
a lecran. Le comportement de cet objet est particulier puisque laffichage du dialogue bloque lexecution du code jusqu`a ce que la methode ShowModal() retourne le resultat
des operations (Open, Save, Cancel, etc.). Le code suivant la ligne o`
u est affiche le dialogue
sera donc execute seulement apr`es avoir clique sur un des boutons offerts dans la fenetre, ce qui
laisse le temps `
a lutilisateur de choisir son fichier avant que la methode ne traite linformation.
`
A linitialisation du dialogue, il est possible de specifier le message `a lintention de lutilisateur `
a
largument message. Les arguments defaultDir et defaultFile permettent de specifier respectivement le dossier o`
u pointe le dialogue `a louverture ainsi quun nom de fichier par defaut (pour
un dialogue de sauvegarde).
Quelques constantes de WxPython concernant les dialogues
wx.FD OPEN donne `
a largument style de lobjet wx.FileDialog configure ce dernier
pour la selection de fichier.
wx.FD SAVE donne `
a largument style de lobjet wx.FileDialog configure ce dernier pour
la sauvegarde de fichier.
wx.ID OK est une constante numerique, retournee par les dialogues, correspondant aux
boutons Open et Save.
wx.ID CANCEL est une constante numerique, retournee par les dialogues, correspondant au bouton Cancel.
Lorsque lutilisateur `
a fait son choix, le path du fichier choisi peut etre recupere, en format
string, `a laide de la methode GetPath() du dialogue. Apr`es avoir recupere les informations utiles,
il ne faut pas oublier dappeler la methode Destroy() sur le dialogue afin de le detruire ainsi que
ses ressources.
Largument wildcard de lobjet wx.FileDialog est fort pratique pour filtrer les fichiers que
lutilisateur peut selectionner. Un string specifiant le type de fichier ainsi que son extension doit
etre fourni. Voici un exemple pour ne permettre que les fichiers AIFF :
w i l d c a r d = AIFF ( . a i f ) | . a i f

On separe, avec une barre verticale, le message `a afficher dans le menu (AIFF (*.aif)) de la
liste des fichiers filtres (*.aif), letoile signifiant tous les fichiers se terminant par .aif.
On peut donner plus dun choix de type de fichier, en ajoutant des pairs type|extensions,
ainsi que plusieurs extensions possibles pour un type donne, en les separant par un point-virgule.
w i l d c a r d = A l l f i l e s | . | AIFF | . a i f ; . a i f f ; . AIF | Wave | . wav ; . wave ; .WAV

Le symbole \ permet de poursuivre un string sur la ligne suivante. Voici une version plus
elegante !
wildcard = All f i l e s | . | \
AIFF f i l e | . a i f ; . a i f f ; . a i f c ; . AIF ; . AIFF ; . A i f ; . A i f f | \
Wave f i l e | . wav ; . wave ; .WAV; .WAVE; . Wav ; . Wave

Voici notre programme modifie :


CHAPITRE 12. CREATION
DINTERFACES GRAPHIQUES II

142

1
2
3
4

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
import wx
from pyo import

5
6
7

s = S e r v e r ( ) . boot ( )
s . amp = 0 . 5

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

c l a s s FxSwitch :
def
i n i t ( s e l f , f x= Delay ) :
s e l f . fx = fx
s e l f . t a b l e = SndTable ( [ SNDS PATH+ / t r a n s p a r e n t . a i f ] 2 )
s e l f . i n p u t = Osc ( s e l f . t a b l e , f r e q= s e l f . t a b l e . g e t R a t e ( ) )
s e l f . p1 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)
s e l f . p2 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)
s e l f . d e l a y = Delay ( s e l f . input , d e l a y= s e l f . p1 , f e e d b a c k= s e l f . p2 ) . s t o p ( )
s e l f . d i s t o = D i s t o ( s e l f . input , d r i v e= s e l f . p1 , s l o p e= s e l f . p2 ,
mul =.5) . s t o p ( )
s e l f . d e g r a d e = Degrade ( s e l f . input , b i t d e p t h=S i g ( s e l f . p1 , mul=20 , add=2) ,
s r s c a l e=S i g ( s e l f . p2 , mul =.99 , add =.01) ,
mul =1.5) . s t o p ( )
s e l f . r e v e r b = WGVerb( s e l f . input , f e e d b a c k= s e l f . p1 ,
c u t o f f=S i g ( s e l f . p2 , mul =10000 , add =250) ) . s t o p ( )
s e l f . harmo = Harmonizer ( s e l f . input ,
t r a n s p o=S i g ( s e l f . p1 , mul=24 , add=12) ,
f e e d b a c k= s e l f . p2 ) . s t o p ( )
s e l f . f x d i c t = { Delay : s e l f . d e l a y , D i s t o : s e l f . d i s t o ,
Degrade : s e l f . degrade , Reverb : s e l f . r e v e r b ,
Harmonizer : s e l f . harmo}
s e l f . f x d i c t [ f x ] . out ( )

31
32
33
34
35

d e f changeFx ( s e l f , f x ) :
s e l f . f x d i c t [ s e l f . fx ] . stop ()
s e l f . f x d i c t [ f x ] . out ( )
s e l f . fx = fx

36
37
38
39

d e f changeTable ( s e l f , snd ) :
s e l f . t a b l e . sound = snd
s e l f . input . f r e q = s e l f . t a b l e . getRate ( )

40
41
42

d e f changeP1 ( s e l f , x ) :
s e l f . p1 . v a l u e = x

43
44
45

d e f changeP2 ( s e l f , x ) :
s e l f . p2 . v a l u e = x

46
47
48
49
50

c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , p a r e n t=None , t i t l e =Fx S w i t c h e r , pos =(100 ,100) ,
s i z e =(600 ,500) , s w i t c h e r=None ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )

51
52
53
54

s e l f . switcher = switcher
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )


` 2 DIMENSIONS
12.1. INTERFACE DE CONTROLE
A

143

55
56
57
58
59
60

s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,


pos =(28 ,10) )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) )
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

61
62
63
64
65
66

# Bouton pour o u v r i r un d i a l o g u e s t a n d a r d e t s e l e c t i o n n e r un nouveau son


s e l f . chooseButton = wx . Button ( s e l f . panel , i d =1, l a b e l=Load snd . . . ,
pos =(10 ,65) )
# une a c t i o n s u r l e bouton a p p e l l e l a methode s e l f . loadSnd
s e l f . chooseButton . Bind (wx .EVT BUTTON, s e l f . loadSnd )

67
68
69
70
71
72

f x s = [ Delay , D i s t o , Degrade , Reverb , Harmonizer ]


s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= Choose FX , pos =(10 ,100) )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,118) , c h o i c e s=f x s )
s e l f . popup . Bind (wx . EVT CHOICE, s e l f . changeFx )

73
74
75
76
77
78

d e f handleAudio ( s e l f , e v t ) :
i f e v t . GetInt ( ) == 1 :
s . start ()
else :
s . stop ()

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

d e f loadSnd ( s e l f , e v t ) :
# f i l t r a g e des f i c h i e r s d i s p o n i b l e s
wildcard = All f i l e s | . | \
AIFF f i l e | . a i f ; . a i f f ; . a i f c ; . AIF ; . AIFF ; . A i f ; . A i f f | \
Wave f i l e | . wav ; . wave ; .WAV; .WAVE; . Wav ; . Wave
# c r e a t i o n d un d i a l o g u e s t a n d a r d pour l a s e l e c t i o n d un f i c h i e r
d l g = wx . F i l e D i a l o g ( s e l f , message= Choose a new s o u n d f i l e . . . ,
w i l d c a r d=w i l d c a r d , s t y l e=wx . FD OPEN)
# l a methode ShowModal ( ) a f f i c h e l a f e n e t r e en p r e m i e r p l a n c o u r a n t e e t
# b l o q u e l e x e c u t i o n j u s q u a c e que l u t i l i s a t e u r a p p u i e OK ou Cancel
i f d l g . ShowModal ( ) == wx . ID OK :
# r e c u p e r e l e path du f i c h i e r s e l e c t i o n n e
path = d l g . GetPath ( )
i f path != :
# a p p e l l e l a methode changeTable avec l e nouveau son en argument
s e l f . s w i t c h e r . changeTable ( path )
# quand t o u t e s t termine , on d e t r u i t l e d i a l o g u e
dlg . Destroy ( )

98
99
100

d e f changeFx ( s e l f , e v t ) :
s e l f . s w i t c h e r . changeFx ( e v t . G e t S t r i n g ( ) )

101
102
103
104
105
106

app = wx . PySimpleApp ( )
f x s w i t c h = FxSwitch ( )
mainFrame = MyFrame( s w i t c h e r=f x s w i t c h )
mainFrame . Show ( )
app . MainLoop ( )

scripts/chapitre 12/03 bouton dialogue.py


CHAPITRE 12. CREATION
DINTERFACES GRAPHIQUES II

144

12.1.3

Surface de contr
ole `
a 2 dimensions

Nous voici rendu `


a letape dimplementer une surface de controle nous permettant de modifier
` laide dun panneau et dune surface de dessin,
les 2 param`etres des effets dun seul mouvement. A
nous allons utiliser la position de la souris en abscisse pour controler le premier effet et la position
en ordonnee pour contr
oler le second.
Commencons dabord par creer une nouvelle classe (Surface) derivee de la classe wx.Panel.
Cette etape est necessaire puisquil faut un conteneur independant du conteneur principal afin
de specifier les dimensions de la surface de dessin.
c l a s s S u r f a c e (wx . Panel ) :
def
i n i t ( s e l f , parent , pos , s i z e ) :
wx . Panel .
i n i t ( s e l f , parent , pos=pos , s i z e=s i z e )

Plusieurs ev`enements seront pris en compte dans cette classe. Dabord, un ev`enement essentiel pour tout programme qui dessine des formes `a lecran, wx.EVT PAINT. Cet ev`enement
survient chaque fois que lon demande au panneau de rafraichir son contenu visuel, en appelant
sa methode self.Refresh(). Ainsi, chaque fois que lon desire dessiner `a lecran, on doit provoquer
un ev`enement wx.EVT PAINT.
Dans un second temps, on desire etre informe sur les differents mouvements de la souris sur
le panneau. Les ev`enements wx.EVT LEFT DOWN, lorsque le bouton gauche de la souris est enfonce, wx.EVT LEFT UP, lorsque le bouton gauche de la souris est relache et wx.EVT MOTION,
lorsque la souris se deplace se verront assigner chacun une methode `a linterieur desquelles nous
allons organiser notre dessin.
c l a s s S u r f a c e (wx . Panel ) :
def
i n i t ( s e l f , parent , pos , s i z e ) :
wx . Panel .
i n i t ( s e l f , parent , pos=pos , s i z e=s i z e )
# S i l a s o u r i s n e s t pas e n f o n c e e , l a p o s i t i o n e s t None ( f a c i l e a f i l t r e r )
s e l f . pos = None
# P o s i t i o n du c e r c l e r e p r e s e n t a n t l a p o s i t i o n c o u r a n t e
s e l f . circlePos = (200 ,200)
# wx . EVT PAINT e s t envoye par l a methode s e l f . R e f r e s h ( )
s e l f . Bind (wx . EVT PAINT, s e l f . OnPaint )
# bouton gauche de l a s o u r i s e n f o n c e
s e l f . Bind (wx .EVT LEFT DOWN, s e l f . OnMouseDown )
# bouton gauche de l a s o u r i s r e l a c h e e
s e l f . Bind (wx . EVT LEFT UP , s e l f . OnMouseUp )
# deplacement de l a s o u r i s s u r l a s u r f a c e
s e l f . Bind (wx .EVT MOTION, s e l f . OnMotion )

Observons dans le detail le comportement de nos differentes methodes.


OnMouseDown
Premi`erement, on veut capturer la souris, cest-`a-dire que lorsque lon enfonce le bouton de
gauche tout en etant au-dessus du panneau, on interdit linteraction avec les autres elements
graphiques afin deviter les conflits. Ensuite, on garde la position du pointeur en memoire afin
de savoir o`
u la souris se trouve `
a letape du dessin. Enfin, on demande de rafraichir lecran.


` 2 DIMENSIONS
12.1. INTERFACE DE CONTROLE
A

145

d e f OnMouseDown ( s e l f , e v t ) :
# CaptureMouse soumet l a s o u r i s a l o b j e t t a n t que
# ReleaseMouse ( ) n e s t pas a p p e l e e
s e l f . CaptureMouse ( )
# e v t . G e t P o s i t i o n ( ) r e t o u r n e l a p o s i t i o n du p o i n t e u r en p i x e l ( x , y )
s e l f . pos = e v t . G e t P o s i t i o n ( )
# s e l f . R e f r e s h ( ) e n v o i e un evenement wx . EVT PAINT pour r a f r a i c h i r l e c r a n
s e l f . Refresh ()

OnMouseUp
Cette methode a un r
ole `
a jouer seulement si la souris a ete enfoncee au dessus du panneau,
cest-`a-dire que self.CaptureMouse() a ete appelee. Si cest bien le cas, on relache la souris, on
reinitialise la position et on rafrachit lecran.
d e f OnMouseUp ( s e l f , e v t ) :
# s e l f . HasCapture ( ) r e t o u r n e True s i l a s o u r i s e s t s o u m i s e a l o b j e t
i f s e l f . HasCapture ( ) :
# relache la souris
s e l f . ReleaseMouse ( )
# r e i n i t i a l i s e la position
s e l f . pos = None
# r a f r a i c h i t l ecran
s e l f . Refresh ()

OnMotion
Dans cette methode, on garde la trace des deplacements du pointeur, toujours si le panneau a
bien pris le contr
ole de la souris, et on rafrachit systematiquement lecran. Il faut faire attention
que le pointeur nenvoie pas des valeurs en dehors des limites du panneau !
d e f OnMotion ( s e l f , e v t ) :
OnMotion e s t a p p e l e e chaque f o i s que l a s o u r i s s e d e p l a c e s u r l e panneau
i f s e l f . HasCapture ( ) :
# t a i l l e du panneau , t u p l e (X, Y)
w, h = s e l f . G e t S i z e ( )
# p o s i t i o n c o u r a n t e de l a s o u r i s , t u p l e (X, Y)
s e l f . pos = e v t . G e t P o s i t i o n ( )
# l i m i t e l e s v a l e u r de p o s i t i o n e n t r e 0 e t l a t a i l l e en X ou en Y
i f s e l f . pos [ 0 ] < 0 :
s e l f . pos [ 0 ] = 0
e l i f s e l f . pos [ 0 ] > w :
s e l f . pos [ 0 ] = w
i f s e l f . pos [ 1 ] < 0 :
s e l f . pos [ 1 ] = 0
e l i f s e l f . pos [ 1 ] > h :
s e l f . pos [ 1 ] = h
# r a f r a i c h i t l ecran
s e l f . Refresh ()


CHAPITRE 12. CREATION
DINTERFACES GRAPHIQUES II

146

OnPaint
Cest dans cette methode, appelee chaque fois que lecran est rafrachit, que lon dessine
des formes sur le panneau. Pour bien illustrer la position du pointeur, nous allons dessiner une
grande croix, une ligne sur toute la hauteur et une sur toute la largeur, dont le croisement se
fera `a lendroit precis o`
u se trouve le pointeur. Par fantaisie, nous ajouterons un cercle rouge
autour du point central.
Premi`
ere r`
egle
On dessine toujours sur un objet derive de la classe wx.DC, qui, dans le cas dun dessin
provoque par un wx.EVT PAINT, doit absolument etre un objet wx.PaintDC ou wx.AutoBufferedPaintDC.
Ce dernier est preferable puisquil permet un rafraichissement decran plus fluide sous Windows
et linux. Cependant, il necessite lappel de la methode SetBackgroundStyle sur notre panneau
avec comme argument wx.BG STYLE CUSTOM.
c l a s s S u r f a c e (wx . Panel ) :
def
i n i t ( s e l f , parent , pos , s i z e , c a l l b a c k=None ) :
wx . Panel .
i n i t ( s e l f , parent , pos=pos , s i z e=s i z e )
s e l f . S e t B a c k g r o u n d S t y l e (wx . BG STYLE CUSTOM)

Seconde r`
egle
Un objet wx.PaintDC doit toujours etre recreee chaque fois que la methode est appelee, donc
on ne garde pas de reference de classe pour cet objet (la variable ne commence pas par self).
Deux outils essentiels au dessin sont la brosse (wx.Brush) et le crayon (wx.Pen). Le premier
permet de specifier la couleur utilisee pour remplir les formes tandis que le second determine la
couleur et lepaisseur des lignes de contour.
Arguments `
a linitialisation de lobjet wx.Brush
colour : Couleur de la brosse (specifier en hexadecimal ou `a laide dun objet wx.Color ).
style : Style de la brosse (solide par defaut). Voir le manuel pour les differents styles
possibles.
Arguments `
a linitialisation de lobjet wx.Pen
colour : Couleur du crayon (specifier en hexadecimal ou `a laide dun objet wx.Color ).

width : Epaisseur
de la ligne en pixels.
style : Style du crayon (solide par defaut). La liste des differents styles possibles est
accessible via la documentation wxwidgets.
Dans lordre, la methode suivante dessine un rectangle aux dimensions du panneau afin de
controler la couleur du fond et un quadrillage aux 50 pixels. Ensuite, si la position nest pas
None, on trace deux lignes qui se croisent `a la position du pointeur puis, `a la toute fin, on
dessine un cercle centre sur la derni`ere position connue et on affiche les coordonnees du pointer.
Notez bien le changement de couleur de la brosse avant de dessiner le cercle !


` 2 DIMENSIONS
12.1. INTERFACE DE CONTROLE
A

147

d e f OnPaint ( s e l f , e v t ) :
w, h = s e l f . G e t S i z e ( )
# on d e s s i n e s u r un o b j e t wx . PaintDC
dc = wx . AutoBufferedPaintDC ( s e l f )
# s p e c i f i e l a c o u l e u r de l a b r o s s e c o u r a n t e ( pour l i n t e r i e u r d e s f o r m e s )
dc . SetBrush (wx . Brush ( #444444 ) )
# d e s s i n e un r e c t a n g l e aux d i m e n s i o n s du panneau
dc . DrawRectangle ( 0 , 0 , w, h )
# s p e c i f i e l a c o u l e u r du crayon pour l e c a d r i l l a g e
dc . SetPen (wx . Pen ( #666666 , 1 ) )
# on d e s s i n e un q u a d r i l l a g e aux 50 p i x e l s . . .
f o r i in range (0 , 400 , 50) :
dc . DrawLine ( 0 , i , w, i )
dc . DrawLine ( i , 0 , i , h )
# s p e c i f i e l a c o u l e u r du crayon pour l a c r o i x
dc . SetPen (wx . Pen ( #AAAAAA , 1 ) )
# s i s e l f . pos n e s t pas None , on d e s s i n e une c r o i x a l a p o s i t i o n c o u r a n t e
i f s e l f . pos != None :
# a j u s t e l a p o s i t i o n du c e r c l e
s e l f . c i r c l e P o s = s e l f . pos
# d e s s i n e une l i g n e h o r i z o n t a l a l a h a u t e u r Y
dc . DrawLine ( 0 , s e l f . pos [ 1 ] , w, s e l f . pos [ 1 ] )
# d e s s i n e une l i g n e v e r t i c a l a l a l a r g e u r X
dc . DrawLine ( s e l f . pos [ 0 ] , 0 , s e l f . pos [ 0 ] , h )
# conversion des p o s i t i o n s X et Y entre 0 et 1
x = s e l f . pos [ 0 ] / f l o a t (w)
y = 1 . s e l f . pos [ 1 ] / f l o a t ( h )
# a f f i c h e l a p o s i t i o n n o r m a l i s e e du p o i n t e u r
dc . DrawText ( %.3 f , %.3 f % ( x , y ) , 1 0 , 1 0 )
# a p p e l du c a l l b a c k pour acheminer l e s v a l e u r s v e r s l e p r o c e s s u s a u d i o
s e l f . callback (x , y)
# n o u v e l l e c o u l e u r de b r o s s e pour l e c e r c l e
dc . SetBrush (wx . Brush ( #AA0000 ) )
# d e s s i n e un c e r c l e c e n t r e s u r l a p o s i t i o n c o u r a n t e
dc . DrawCircle ( s e l f . c i r c l e P o s [ 0 ] , s e l f . c i r c l e P o s [ 1 ] , 5 )

Vous aurez probablement note la conversion des valeurs de position entre 0 et 1 puis lappel
dune methode appelee self.callback. Cette methode, qui nexiste pas encore, sera donnee `
a
linitialisation de lobjet Surface par notre fenetre principale. Cest par cette methode que nous
acheminerons les valeurs vers lobjet qui gen`ere le processus audio. La methode init de notre
classe varie donc leg`erement :
c l a s s S u r f a c e (wx . Panel ) :
def
i n i t ( s e l f , parent , pos , s i z e , c a l l b a c k ) :
wx . Panel .
i n i t ( s e l f , parent , pos=pos , s i z e=s i z e )
s e l f . S e t B a c k g r o u n d S t y l e (wx . BG STYLE CUSTOM)
s e l f . callback = callback
s e l f . pos = None
...
...

Nous devons maintenant ajouter une methode `a notre classe MyFrame. Cette methode doit
recevoir 2 arguments, un pour la position normalisee en X et un pour la position normalisee en
Y. Elle na pour but que de transferer les valeurs vers notre objet audio :


CHAPITRE 12. CREATION
DINTERFACES GRAPHIQUES II

148

d e f changeParams ( s e l f , x , y ) :
# f o n c t i o n a p p e l e e par l e c a l l b a c k de l a s u r f a c e de c o n t r o l e
s e l f . s w i t c h e r . changeP1 ( x )
s e l f . s w i t c h e r . changeP2 ( y )

` la toute fin de la
Ne reste plus qu`
a creer un objet Surface dans notre fenetre principale. A
methode init de la classe MyFrame, on ajoute la ligne suivante :
s e l f . s u r f a c e = S u r f a c e ( s e l f . panel , pos =(150 ,28) , s i z e =(400 ,400) ,
c a l l b a c k= s e l f . changeParams )

* Notez le passage en argument de la reference (et non pas lappel car il ny a pas de
parenth`eses) `
a la methode self.changeParams. Cest bien lobjet self.surface qui se chargera des
appels.
Voici donc notre programme avec lajout de la surface de controle :
1
2
3
4

#! / u s r / b i n / env python
# e n c o d i n g : u t f 8
import wx
from pyo import

5
6
7

s = S e r v e r ( ) . boot ( )
s . amp = 0 . 5

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

c l a s s FxSwitch :
def
i n i t ( s e l f , f x= Delay ) :
s e l f . fx = fx
s e l f . t a b l e = SndTable ( [ SNDS PATH+ / t r a n s p a r e n t . a i f ] 2 )
s e l f . i n p u t = Osc ( s e l f . t a b l e , f r e q= s e l f . t a b l e . g e t R a t e ( ) )
s e l f . p1 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)
s e l f . p2 = SigTo ( v a l u e =0.5 , time =0.05 , i n i t =0.5)
s e l f . d e l a y = Delay ( s e l f . input , d e l a y= s e l f . p1 , f e e d b a c k= s e l f . p2 ) . s t o p ( )
s e l f . d i s t o = D i s t o ( s e l f . input , d r i v e= s e l f . p1 , s l o p e= s e l f . p2 ,
mul =.5) . s t o p ( )
s e l f . d e g r a d e = Degrade ( s e l f . input , b i t d e p t h=S i g ( s e l f . p1 , mul=20 , add=2) ,
s r s c a l e=S i g ( s e l f . p2 , mul =.99 , add =.01) ,
mul =1.5) . s t o p ( )
s e l f . r e v e r b = WGVerb( s e l f . input , f e e d b a c k= s e l f . p1 ,
c u t o f f=S i g ( s e l f . p2 , mul =10000 , add =250) ) . s t o p ( )
s e l f . harmo = Harmonizer ( s e l f . input ,
t r a n s p o=S i g ( s e l f . p1 , mul=24 , add=12) ,
f e e d b a c k= s e l f . p2 ) . s t o p ( )
s e l f . f x d i c t = { Delay : s e l f . d e l a y , D i s t o : s e l f . d i s t o ,
Degrade : s e l f . degrade , Reverb : s e l f . r e v e r b ,
Harmonizer : s e l f . harmo}
s e l f . f x d i c t [ f x ] . out ( )

31
32
33
34
35

d e f changeFx ( s e l f , f x ) :
s e l f . f x d i c t [ s e l f . fx ] . stop ()
s e l f . f x d i c t [ f x ] . out ( )
s e l f . fx = fx

36
37

d e f changeTable ( s e l f , snd ) :


` 2 DIMENSIONS
12.1. INTERFACE DE CONTROLE
A

38
39

149

s e l f . t a b l e . sound = snd
s e l f . input . f r e q = s e l f . t a b l e . getRate ( )

40
41
42

d e f changeP1 ( s e l f , x ) :
s e l f . p1 . v a l u e = x

43
44
45

d e f changeP2 ( s e l f , x ) :
s e l f . p2 . v a l u e = x

46
47
48
49
50
51
52
53

# S u r f a c e de c o n t r o l e d e s p a r a m e t r e s
# La c l a s s e e s t un d e r i v e de wx . Panel p u i s q u e qu i l
# f a u t d e s s i n e r s u r une s u r f a c e q u e l c o n q u e !
c l a s s S u r f a c e (wx . Panel ) :
def
i n i t ( s e l f , parent , pos , s i z e , c a l l b a c k ) :
wx . Panel .
i n i t ( s e l f , parent , pos=pos , s i z e=s i z e )
s e l f . S e t B a c k g r o u n d S t y l e (wx . BG STYLE CUSTOM)

54
55
56
57
58
59
60
61

# r e f e r e n c e a l argument c a l l b a c k q u i e s t l a f o n c t i o n a a p p e l e r
# quand on d e p l a c e l e p o i n t e u r s u r l a s u r f a c e
s e l f . callback = callback
# S i l a s o u r i s n e s t pas e n f o n c e e , l a p o s i t i o n e s t None ( f a c i l e a f i l t r e r )
s e l f . pos = None
# P o s i t i o n du c e r c l e r e p r e s e n t a n t l a p o s i t i o n c o u r a n t e
s e l f . circlePos = (200 ,200)

62
63
64
65
66
67
68
69
70
71

### a s s i g n a t i o n de methodes a c e r t a i n s evenements ###


# wx . EVT PAINT e s t envoye par l a methode s e l f . R e f r e s h ( )
s e l f . Bind (wx . EVT PAINT, s e l f . OnPaint )
# bouton gauche de l a s o u r i s e n f o n c e
s e l f . Bind (wx .EVT LEFT DOWN, s e l f . OnMouseDown )
# bouton gauche de l a s o u r i s r e l s c h e
s e l f . Bind (wx . EVT LEFT UP , s e l f . OnMouseUp )
# deplacement de l a s o u r i s s u r l a s u r f a c e
s e l f . Bind (wx .EVT MOTION, s e l f . OnMotion )

72
73
74
75
76
77
78
79
80

d e f OnMouseDown ( s e l f , e v t ) :
# CaptureMouse soumet l a s o u r i s a l o b j e t t a n t que
# ReleaseMouse ( ) n e s t pas a p p e l e e
s e l f . CaptureMouse ( )
# e v t . G e t P o s i t i o n ( ) r e t o u r n e l a p o s i t i o n du p o i n t e u r en p i x e l ( x , y )
s e l f . pos = e v t . G e t P o s i t i o n ( )
# s e l f . R e f r e s h ( ) e n v o i e un evenement wx . EVT PAINT pour r a f r a i c h i r l e c r a n
s e l f . Refresh ()

81
82
83
84
85
86
87
88
89
90
91

d e f OnMouseUp ( s e l f , e v t ) :
# s e l f . HasCapture ( ) r e t o u r n e True s i l a s o u r i s e s t s o u m i s e a l o b j e t
i f s e l f . HasCapture ( ) :
# relache la souris
s e l f . ReleaseMouse ( )
# r e i n i t i a l i s e la position
s e l f . pos = None
# r a f r a i c h i t l ecran
s e l f . Refresh ()

150

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

CHAPITRE 12. CREATION


DINTERFACES GRAPHIQUES II

d e f OnMotion ( s e l f , e v t ) :
OnMotion e s t a p p e l e e chaque f o i s que l a s o u r i s s e d e p l a c e s u r l e panneau
i f s e l f . HasCapture ( ) :
# t a i l l e du panneau , t u p l e (X, Y)
w, h = s e l f . G e t S i z e ( )
# p o s i t i o n c o u r a n t e de l a s o u r i s , t u p l e (X, Y)
s e l f . pos = e v t . G e t P o s i t i o n ( )
# l i m i t e l e s v a l e u r de p o s i t i o n e n t r e 0 e t l a t a i l l e en X ou en Y
i f s e l f . pos [ 0 ] < 0 :
s e l f . pos [ 0 ] = 0
e l i f s e l f . pos [ 0 ] > w :
s e l f . pos [ 0 ] = w
i f s e l f . pos [ 1 ] < 0 :
s e l f . pos [ 1 ] = 0
e l i f s e l f . pos [ 1 ] > h :
s e l f . pos [ 1 ] = h
# r a f r a i c h i t l ecran
s e l f . Refresh ()

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

d e f OnPaint ( s e l f , e v t ) :
w, h = s e l f . G e t S i z e ( )
# on d e s s i n e s u r un o b j e t wx . PaintDC
dc = wx . AutoBufferedPaintDC ( s e l f )
# s p e c i f i e l a c o u l e u r de l a b r o s s e c o u r a n t e ( i n t e r i e u r d e s f o r m e s )
dc . SetBrush (wx . Brush ( #444444 ) )
# d e s s i n e un r e c t a n g l e aux d i m e n s i o n s du panneau
dc . DrawRectangle ( 0 , 0 , w, h )
# s p e c i f i e l a c o u l e u r du crayon pour l e c a d r i l l a g e
dc . SetPen (wx . Pen ( #666666 , 1 ) )
# on d e s s i n e un q u a d r i l l a g e aux 50 p i x e l s . . .
f o r i in range (0 , 400 , 50) :
dc . DrawLine ( 0 , i , w, i )
dc . DrawLine ( i , 0 , i , h )
# s p e c i f i e l a c o u l e u r du crayon pour l a c r o i x
dc . SetPen (wx . Pen ( #AAAAAA , 1 ) )
# s i s e l f . pos n e s t pas None , on d e s s i n e une c r o i x a l a p o s i t i o n c o u r a n t e
i f s e l f . pos != None :
# a j u s t e l a p o s i t i o n du c e r c l e
s e l f . c i r c l e P o s = s e l f . pos
# d e s s i n e une l i g n e h o r i z o n t a l a l a h a u t e u r Y
dc . DrawLine ( 0 , s e l f . pos [ 1 ] , w, s e l f . pos [ 1 ] )
# d e s s i n e une l i g n e v e r t i c a l a l a l a r g e u r X
dc . DrawLine ( s e l f . pos [ 0 ] , 0 , s e l f . pos [ 0 ] , h )
# conversion des p o s i t i o n s X et Y entre 0 et 1
x = s e l f . pos [ 0 ] / f l o a t (w)
y = 1 . s e l f . pos [ 1 ] / f l o a t ( h )
# a f f i c h e l a p o s i t i o n n o r m a l i s e e du p o i n t e u r
dc . DrawText ( %.3 f , %.3 f % ( x , y ) , 1 0 , 1 0 )
# a p p e l du c a l l b a c k pour acheminer l e s v a l e u r s v e r s l e p r o c e s s u s a u d i o
s e l f . callback (x , y)
# n o u v e l l e c o u l e u r de b r o s s e pour l e c e r c l e
dc . SetBrush (wx . Brush ( #AA0000 ) )
# d e s s i n e un c e r c l e c e n t r e s u r l a p o s i t i o n c o u r a n t e
dc . DrawCircle ( s e l f . c i r c l e P o s [ 0 ] , s e l f . c i r c l e P o s [ 1 ] , 5 )


` 2 DIMENSIONS
12.1. INTERFACE DE CONTROLE
A

146
147
148
149
150
151
152
153

c l a s s MyFrame(wx . Frame ) :
def
i n i t ( s e l f , p a r e n t=None , t i t l e =Fx S w i t c h e r , pos =(100 ,100) ,
s i z e =(600 ,500) , s w i t c h e r=None ) :
wx . Frame .
i n i t ( s e l f , parent , i d =1, t i t l e =t i t l e , pos=pos , s i z e=s i z e )
s e l f . switcher = switcher
s e l f . p a n e l = wx . Panel ( s e l f )
s e l f . p a n e l . SetBackgroundColour ( #DDDDDD )

154
155
156
157
158
159

s e l f . onOffText = wx . S t a t i c T e x t ( s e l f . panel , i d =1, l a b e l= Audio ,


pos =(28 ,10) )
s e l f . onOff = wx . ToggleButton ( s e l f . panel , i d =1, l a b e l= on / o f f ,
pos =(10 ,28) )
s e l f . onOff . Bind (wx .EVT TOGGLEBUTTON, s e l f . handleAudio )

160
161
162
163

s e l f . chooseButton = wx . Button ( s e l f . panel , i d =1, l a b e l=Load snd . . . ,


pos =(10 ,65) )
s e l f . chooseButton . Bind (wx .EVT BUTTON, s e l f . loadSnd )

164
165
166
167
168
169

f x s = [ Delay , D i s t o , Degrade , Reverb , Harmonizer ]


s e l f . popupText = wx . S t a t i c T e x t ( s e l f . panel , i d =1,
l a b e l= Choose FX , pos =(10 ,100) )
s e l f . popup = wx . Choice ( s e l f . panel , i d =1, pos =(8 ,118) , c h o i c e s=f x s )
s e l f . popup . Bind (wx . EVT CHOICE, s e l f . changeFx )

170
171
172
173

# c r e e un o b j e t S u r f a c e pour l e c o n t r o l e d e s p a r a m e t r e s
s e l f . s u r f a c e = S u r f a c e ( s e l f . panel , pos =(150 ,28) , s i z e =(400 ,400) ,
c a l l b a c k= s e l f . changeParams )

174
175
176
177
178
179

d e f handleAudio ( s e l f , e v t ) :
i f e v t . GetInt ( ) == 1 :
s . start ()
else :
s . stop ()

180
181
182
183
184
185
186
187
188
189
190
191

d e f loadSnd ( s e l f , e v t ) :
wildcard = All f i l e s | . | \
AIFF f i l e | . a i f ; . a i f f ; . a i f c ; . AIF ; . AIFF ; . A i f ; . A i f f | \
Wave f i l e | . wav ; . wave ; .WAV; .WAVE; . Wav ; . Wave
d l g = wx . F i l e D i a l o g ( s e l f , message= Choose a new s o u n d f i l e . . . ,
w i l d c a r d=w i l d c a r d , s t y l e=wx . FD OPEN)
i f d l g . ShowModal ( ) == wx . ID OK :
path = d l g . GetPath ( )
i f path != :
s e l f . s w i t c h e r . changeTable ( path )
dlg . Destroy ( )

192
193
194

d e f changeFx ( s e l f , e v t ) :
s e l f . s w i t c h e r . changeFx ( e v t . G e t S t r i n g ( ) )

195
196
197
198
199

d e f changeParams ( s e l f , x , y ) :
# f o n c t i o n a p p e l e e par l e c a l l b a c k de l a s u r f a c e de c o n t r o l e
s e l f . s w i t c h e r . changeP1 ( x )
s e l f . s w i t c h e r . changeP2 ( y )

151

152

CHAPITRE 12. CREATION


DINTERFACES GRAPHIQUES II

200
201

app = wx . PySimpleApp ( )

202
203

f x s w i t c h = FxSwitch ( )

204
205
206

mainFrame = MyFrame( s w i t c h e r=f x s w i t c h )


mainFrame . Show ( )

207
208

app . MainLoop ( )

scripts/chapitre 12/04 final.py

Chapitre 13

Retour sur les principaux concepts


13.1

ements de langage de la programmation orient


El
ee objet
en Python

Syntaxe des noms de variables


Typage des variables
Affectation de valeurs
Operateurs de comparaison
Sequence dinstructions et execution conditionnelle
Instructions imbriquees
R`egles de syntaxe
Les chanes de caract`eres (string)
Les operations sur les listes
La fonction range
Importation de modules
Instructions repetitives
Les generateurs de listes
Les fonctions
Variables locales et variables globales
Les dictionnaires
Les classes

153

154

CHAPITRE 13. RETOUR SUR LES PRINCIPAUX CONCEPTS

13.2

Principes g
en
eraux de la programmation musicale avec le
module pyo

Premier pas
Server
PyoObject
PyoTableObject
Comment lire le manuel pyo
Les param`etres dinitialisation
SfPlayer et les paths
Gestion de la polyphonie
Utilisation des listes `
a des fins musicales
variations continues des param`etres
Utilisation des fonctions dans un script (object Pattern)
Generation dune sequence composee (object Score)
Gestion du temps par lenvoi de triggers
Exemples musicaux
Exemple de classe audio

Chapitre 14

Annexes
14.1

Interaction avec lutilisateur

Lorsque lon demarre lenvironnement Python, une banque de fonctions integrees sont accessibles immediatement. Ce sont les fonctions built-in, dont font partie range, len et type que
nous avons dej`
a rencontrees. Il existe, dans ce module, deux fonctions permettant `a lutilisateur
dinteragir avec le programme en cours dexecution. Ce sont les fonctions input et raw input.

14.1.1

La fonction input

Lorsque Python rencontre cette fonction, il arrete lexecution du programme et attend que
lutilisateur inscrive une valeur et tape la touche Return. La valeur est memorisee dans une
variable et le type le plus approprie lui est assigne. Un argument, sous la forme dune chane
de caract`eres, doit etre donne `
a la fonction input afin de guider la reponse de lutilisateur. Elle
sera affichee `
a lecran juste avant le curseur en attente.
>>> prenom = i n p u t ( E n t r e z v o t r e prenom : )
E n t r e z v o t r e prenom : O l i v i e r # ( on i n s c r i t une v a l e u r p u i s <Return >)
>>> p r i n t prenom
Olivier
>>> ty pe ( prenom )
<ty pe s t r >
>>> v a l = i n p u t ( E n t r e z un nombre : )
E n t r e z un nombre : 1000
>>> p r i n t v a l
1000
>>> ty pe ( v a l )
<ty pe i n t >

Notez lutilisation des guillemets `a la ligne Entrez votre prenom. Sans lusage des guillemets,
linterpreteur cherchera une variable Olivier et sil nen trouve pas, il rapportera une erreur.

155

156

14.1.2

CHAPITRE 14. ANNEXES

La fonction raw input

La fonction raw input offre plus de flexibilite pour lutilisateur. Avec cette fonction, nul
besoin de se soucier du type de la reponse donnee `a la question, la fonction convertit automatiquement en string la valeur obtenue.
>>> prenom = r a w i n p u t ( E n t r e z v o t r e prenom :
E n t r e z v o t r e prenom : O l i v i e r
>>> p r i n t prenom
Olivier
>>> ty pe ( prenom )
<ty pe s t r >
>>> v a l = r a w i n p u t ( E n t r e z un nombre : )
E n t r e z un nombre : 1000
>>> p r i n t v a l
1000
>>> ty pe ( v a l )
<ty pe s t r >

On trouvera les fonctions int et float parmi les fonctions integrees. Elles servent respectivement `a convertir un string en nombre entier ou en nombre reel.
>>> v a l = r a w i n p u t ( E n t r e z un nombre :
E n t r e z un nombre : 1000
>>> ty pe ( v a l )
<ty pe s t r >
>>> v a l = i n t ( v a l )
>>> ty pe ( v a l )
<ty pe i n t >

14.2

Gestion des exceptions

Lorsquune erreur survient dans le deroulement des instructions, une exception est signalee.
Le programme arrete et un message derreur est affiche. Il est parfois essentiel deffectuer des
operations qui peuvent, sous certaines circonstances, saverer impossibles `a executer. Le syst`eme
de gestion des exceptions sous Python est simple et permet facilement dattraper les exceptions
avant quelles narretent lexecution du programme. Un autre chemin peut alors etre specifie
pour les cas o`
u une operation aurait echoue. Voici un exemple o`
u le programme arrete lorsque
lon essaie douvrir un fichier inexistant :
>>> f = open ( new . t x t , r )
Traceback ( most r e c e n t c a l l l a s t ) :
F i l e <s t d i n > , l i n e 1 , i n <module>
IOError : [ Errno 2 ] No such f i l e o r d i r e c t o r y :

new . t x t

14.2. GESTION DES EXCEPTIONS

14.2.1

157

Interception dune exception (permet au programme de continuer)

En introduisant notre operation dans un bloc dinstructions try - except, le programme


tentera dexecuter la commande dans le bloc try et, en cas dechec, executera plutot les commandes inscrites dans le bloc except. Dans lexemple suivant, le programme tente douvrir
le fichier new.txt. Sil reussit, il saute le bloc except et poursuit le deroulement normal du
programme. Sil echoue, il commence par afficher le message de lerreur survenue et il ouvre
ensuite un fichier qui se nomme default.txt, en le placant dans la variable o`
u devait se trouver
le fichier new.txt. Le programme peut continuer `a rouler avec les informations se trouvant dans
default.txt, prevu pour les cas de catastrophe.
try :
f = open ( new . t x t , r )
e x c e p t IOError , msg :
p r i n t msg
f = open ( d e f a u l t . t x t , r )

La constante IOError placee apr`es le mot cle except indique au bloc de nintercepter que
ce type derreur. Dans un premier temps, il est plus prudent de ne rien indiquer apr`es le mot
cle, le bloc interceptera alors toutes les exceptions possibles.
try :
f = open ( new . t x t , r )
except :
f = open ( d e f a u l t . t x t , r )

Une clause else peut etre rajoutee `a la suite de la clause except. Cette clause ne sera
executee que si le try fonctionne.
Si la clause finally est ajoutee `a la toute fin du bloc, elle sera executee peut importe le
resultat de loperation precedente.
try :
f = open ( new . t x t , r )
except :
f = open ( d e f a u l t . t x t , r )
else :
p r i n t Le f i c h i e r new . t x t e x i s t e b i e n
finally :
p r i n t Fin du b l o c

158

14.3

CHAPITRE 14. ANNEXES

Envois de commandes au syst`


eme

Il existe plusieurs techniques pour envoyer des commandes au syst`eme, certaines etant
dependantes de la plate-forme sur laquelle le script Python est execute. Nous ne ferons ici
quun survol dune technique simple, fonctionnant sur toutes les plate-formes, cest `a dire la
fonction system du module os.
La commande os.system fonctionne tr`es bien pour des operations simples ne necessitant
aucun retour dans le programme Python. La commande suivante permet de demarrer le logiciel
QuickTime `
a partir dun interpreteur Python :
>>> import o s
>>> o s . system ( open / A p p l i c a t i o n s / QuickTime \ P l a y e r . app )

La commande suivante donnera la liste des fichiers presents dans le repertoire courant, avec
les informations detaillees, et sauvera le tout dans le fichier repertoire.txt :
>>> o s . system ( l s a l > r e p e r t o i r e . t x t )

Les module os et os.path regorgent de fonctions permettant de gerer les repertoires sur le
disque. Des operations telles que renommer ou creer un dossier, construire des liens (paths) vers
des fichiers ou changer les permissions doivent, dans la mesure du possible, etre effectuees avec
les fonctions generiques de Python, afin dassurer le caract`ere portable du programme. En effet,
la syntaxe netant pas la meme sur les differents syst`emes, il est preferable de laisser cette charge
`a Python, qui sassurera detre conforme `a la plate-forme sur laquelle il est lance. Ainsi, pour
ouvrir un fichier, la fonction os.path.join permet de construire le lien vers un fichier sans gerer
la syntaxe :
>>> import o s . path
>>> f = open ( o s . path . j o i n ( R e s o u r c e s , d e f a u l t . py ) , r )
>>> f . r e a d ( )
s e t G l o b a l D u r a t i o n ( 1 2 ) \n\ nplaySound ( ) \n\ n s t a r t C s o u n d ( ) \n

On peut donner autant de niveaux que necessaires `a la fonction os.path.join, en format string,
separes par des virgules.
Pour lancer des operations syst`emes plus complexes, il faudra utiliser les fonctions du module
subprocess, qui remplace tous les appels syst`eme depuis Python 2.5.

`
14.4. LANTISECHE
PYTHON (PYTHON CHEAT SHEET)

14.4

Lantis`
eche Python (Python Cheat Sheet)

14.4.1

Arithm
etique

159

Types
Integer : 12, -234, 0, ...
Long integer : 54323457L (on ajoute le suffixe L)
Float : 0.005, 13.4654, -4.321, ...
Op
erateurs
Exposant : ** ( 2**4 = 16 )
Multiplication : *
Division : / ( 5/2 = 2, 5/2. = 2.5 )
Addition : +
soustraction : Modulo : %
Ordre de priorite : PEMDAS
(parenth`ese, exposant, multiplication, division, addition, soustraction)
Expressions abr
eg
ees
a += 1 a = a + 1
a = 5 a = a 5

14.4.2

Assignation

Le symbole = permet dassigner une valeur `a une variable.


La relation degalite est indiquee par le symbole ==. (voir Conditions 14.4.9)
Assignation simple
a = 25 (assigne la valeur 25 `
a la variable a)
Assignations multiples
a = b = c = 1 (assigne la valeur 1 aux variables a, b et c)
Assignations parall`
eles
a, b = 1, 2 (assigne la valeur 1 `
a la variable a et la valeur 2 `a la variable b)

14.4.3

Chane de caract`
eres (string)

Un string est une constante ; pour modifier un string il faut en creer un autre. Il peut etre
delimite par des guillemets simples () ou des guillemets doubles (). Les guillemets triples (
ou ) servent `
a definir un string de documentation.

160

CHAPITRE 14. ANNEXES

Op
erations
Assignation (=) : str = Ceci est un string
Concatenation (+) : Hello + world ! = Hello world !
Repetition (*) : 3 * allo = alloalloallo
Les guillemets simples et doubles sont equivalents, mais peuvent servir `a introduire un string
dans un string :
>>> p r i n t C e c i e s t un s t r i n g dans un s t r i n g
C e c i e s t un s t r i n g dans un s t r i n g

Construction dun string avec lop


erateur modulo
>>> a , b , c = 1 , 3 , 7
>>> p r i n t %d , %d e t %d s o n t d e s nombres p r e m i e r s % ( a , b , c )
1 , 3 e t 7 s o n t d e s nombres p r e m i e r s

Quelques op
erations sur les strings
>>> a = a l l o
>>> a . c a p i t a l i z e ( )
ALLO
>>> . j o i n ( a )
A L L O
>>> a . r e p l a c e ( L , B )
ABBO
>>> a . r e p l a c e ( O , A )
ABBA
>>> . j o i n ( a ) . s p l i t ( )
[ A , B , B , A ]
>>> a [ 0 ]
A
>>>a [ 1 : 3 ]
BB

14.4.4

Lecture et
ecriture de fichiers

Ouvrir un fichier en lecture


f = open ( U s e r s / o l i p e t / m o n f i c h i e r . t x t , r )
for l i n e in f . readlines () :
print line
f . close ()

Ouvrir un fichier en
ecriture
f = open ( U s e r s / o l i p e t / m o n f i c h i e r . t x t , w )
f . w r i t e ( H e l l o world ! )
f . close ()

`
14.4. LANTISECHE
PYTHON (PYTHON CHEAT SHEET)

14.4.5

161

Print

La commande print permet dafficher des valeurs dans le stdout ou dans linterpreteur.
>>> a = 25
>>> p r i n t a
25
>>> p r i n t H e l l o world !
H e l l o world !
>>> p r i n t L a d d i t i o n de 2 + 2 donne : %d % (2+2)
L a d d i t i o n de 2 + 2 donne 4

Inclure les lignes suivantes dans votre script pour faire suivre le stdout vers un fichier de votre
choix.
import s y s
s y s . s t d o u t = open ( o u t p u t l o g . t x t , w )

14.4.6

Liste

Une liste consiste simplement en une suite de valeurs separees par des virgules et placees
entre crochets []. Les elements dans une liste peuvent etre de differents types (nombre, string,
liste, tuple, dictionnaire, fonction, objet, ...). La liste est alterable, cest `a dire que lon peut
modifier ses elements sans avoir `
a creer une nouvelle liste. Voici quelques operations sur les
listes :

list1 + list2 : concatenation de list1 et list2


list[i] : retourne lelement `
a la position i
list[i :j] : retourne une liste contenant les elements entre les positions i et j
len(list) : retourne la longueur de la liste
del list[i] : elimine lelement `
a la position i
list.append(val) : ajoute lelement val `a la fin de la liste
list.extend(list) : ajoute une liste `a la fin dune liste
list.sort() : met dans lordre les elements dune liste
list.reverse() : inverse les elements dune liste
list.insert(i, val) : ins`ere val `
a la position i
list.count(val) : retourne le nombre doccurrences de val dans une liste
list.pop() : retourne et elimine la derni`ere valeur dune liste
val in list : True si lelement val est present dans la liste

14.4.7

Tuple

Un tuple, tout comme la liste, est une suite de valeurs separees par des virgules. Par contre,
un tuple est delimite par des parenth`eses et est immuable. Particuli`erement utile pour creer des
listes qui ne doivent en aucun cas etre modifiees, le tuple est aussi plus rapide dacc`es que la
liste.

162

14.4.8

CHAPITRE 14. ANNEXES

Dictionnaire

Le dictionnaire est une table de donnees sur base de pairs cle - valeur. Un dictionnaire est
defini entre accolades {}. Les pairs sont separees par des virgules et la cle est separee de sa valeur
par le symbole deux-points ( :).
m o n d i c t = { un : 1 2 3 ,
12: [1 ,2 ,3 ,4 ,5 ,6] ,
( 1 , 2 ) : H e l l o World ! }
>>> p r i n t m o n d i c t [ un ]
123
>>> p r i n t m o n d i c t [ 1 2 ]
[1 ,2 ,3 ,4 ,5 ,6]
>>> p r i n t m o n d i c t [ ( 1 , 2 ) ]
H e l l o world !

Quelques operations sur un dictionnaire :


>>> d i c t = { Montreal : 5 1 4 , Quebec : 418}
>>> d i c t [ S h e r b r o o k e ] = 819
>>> p r i n t d i c t [ S h e r b r o o k e ]
819
>>> d e l d i c t [ Quebec ]
>>> d i c t
{ Montreal : 5 1 4 , S h e r b r o o k e : 819}
>>> d i c t . k e y s ( )
[ Montreal , S h e r b r o o k e ]
>>> d i c t . h a s k e y ( Montreal )
True
>>> S h e r b r o o k e i n d i c t
True

Pour des cles qui sont de simples strings, il est possible de specifier les pairs cle-valeur en
donnant des mots-cles `
a la fonction constructeur de la classe dictionnaire.
>>> m o n d i c t = d i c t ( Montreal =514 , Quebec =418 , S h e r b r o o k e =819)
>>> p r i n t m o n d i c t
{ Montreal : 5 1 4 , Quebec : 4 1 8 , S h e r b r o o k e : 819}

Les elements ne sont pas classes en ordre dans un dictionnaire, ce qui signifie quil est
impossible de predire lordre darrive des elements dans une boucle for.

14.4.9

Conditions (if... elif... else)

Op
erateurs de comparaison
< : plus petit que
<= : plus petit ou egal `
a
> : plus grand que
>= : plus grand ou egal `
a
== : est egal `
a
! = : nest pas egal `
a

`
14.4. LANTISECHE
PYTHON (PYTHON CHEAT SHEET)

163

Syntaxe
Les blocs doperations sont delimites par lindentation du programme :
i f a < 0:
p r i n t a e s t p l u s p e t i t que 0 , a prend l a v a l e u r 0
a = 0
e l i f a > 100:
p r i n t a e s t p l u s grand que 1 0 0 , a prend l a v a l e u r 100
a = 100
else :
p r i n t a e s t c o m p r i s e n t r e 0 e t 100

Utilisation de and, or et not :


i f a >= 0 and a <= 1 0 0 :
p r i n t a e s t c o m p r i s e n t r e 0 e t 100 i n c l u s i v e m e n t
i f a < 0 or a > 100:
p r i n t a e s t s o i t p l u s p e t i t que 0 , s o i t p l u s grand que 100
i f not a == 0 :
p r i n t a ne vaut pas 0
i f a != 0 :
p r i n t a ne vaut pas 0
i f a not i n [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 1 0 ] :
p r i n t a n e s t pas une v a l e u r e n t r e 1 e t 10

14.4.10

Boucle (for, while)

La boucle for sert `


a incrementer dans les membres dune sequence (liste, tuple, dictionnaire).
>>> f o r
...
...
0
1
2
3
4
>>> f o r
...
...
Paul
Jack
Joe

i in range (5) :
print i

name i n [ Paul , Jack , Joe ] :


p r i n t name

164

CHAPITRE 14. ANNEXES

Boucle for sur les cles dun dictionnaire :


>>> d i c t = { j a u n e : c i t r o n , r o u g e :
>>> f o r key i n d i c t . k e y s ( ) :
...
p r i n t key , d i c t [ key ]
...
jaune c i t r o n
rouge f r a i s e
vert lime

f r a i s e , vert :

lime }

La boucle while sert `


a construire une boucle de longueur indeterminee.
>>> var = 1
>>> w h i l e var > 0 :
...
var = random . r a n d i n t ( 0 , 1 0 0 )

14.4.11

List comprehension (fabrication de listes)

La fabrication de listes est une des fonctionnalite les plus puissantes du langage Python. Elle
permet de creer des listes complexes tr`es rapidement par une utilisation particuli`ere de la boucle
for. Les list comprehension sont delimitees par des crochets.
G
en
erateur simple
>>> m a l i s t = [ i f o r i i n r a n g e ( 2 0 ) ]
>>> m a l i s t
[ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19]

G
en
erateur avec boucles for imbriqu
ees
>>> m a l i s t = [ ( i , j ) f o r i i n r a n g e ( 3 ) f o r j i n r a n g e ( 3 ) ]
>>> m a l i s t
[ ( 0 , 0) , (0 , 1) , (0 , 2) , (1 , 0) , (1 , 1) , (1 , 2) , (2 , 0) , (2 , 1) , (2 , 2) ]

G
en
erateur avec conditions
>>> m a l i s t = [ ( i , j ) f o r i i n r a n g e ( 3 ) f o r j i n r a n g e ( 3 ) i f j != 1 ]
>>> m a l i s t
[ ( 0 , 0) , (0 , 2) , (1 , 0) , (1 , 2) , (2 , 0) , (2 , 2) ]

`
14.4. LANTISECHE
PYTHON (PYTHON CHEAT SHEET)

14.4.12

165

Cr
eation de fonctions

Une fonction est definie par le mot-cle def. Toutes les lignes suivantes qui sont au niveau
dindentation superieur feront partie de la fonction.
Fonction simple
>>> d e f m a f o n c t i o n ( ) :
...
print fonction simple
...
>>> m a f o n c t i o n ( )
fonction simple
>>> d e f c a r r e ( x ) :
...
p r i n t xx
...
>>> c a r r e ( 2 )
4

Fonction avec arguments poss


edant une valeur par d
efaut
Les arguments qui ont une valeur par defaut doivent toujours etre apr`es les arguments sans
valeur par defaut.
>>>
...
...
>>>
4
>>>
8
>>>
81

d e f p u i s s a n c e ( x , exp =2) :
p r i n t x exp
puissance (2)
puissance (2 , 3)
p u i s s a n c e ( x=3 , exp =4)

Fonction avec valeur de retour


Une fonction avec le mot-cle return permet de recuperer une valeur `a la sortie dune fonction.
>>> d e f p u i s s a n c e ( x , exp =2) :
...
r e t u r n x exp
...
>>> a = p u i s s a n c e ( 2 , 3 )
>>> a
8

String de documentation
Un string entre triple guillemets `a la ligne suivant la declaration de la fonction sera enregistre
dans la variable doc de la fonction.

166

CHAPITRE 14. ANNEXES

>>> d e f p u i s s a n c e ( x , exp =2) :


...
C a l c u l e e t r e t o u r n e l a v a l e u r de x a l a p u i s s a n c e exp
...
r e t u r n x exp
...
>>> p u i s s a n c e . d o c
C a l c u l e e t r e t o u r n e l a v a l e u r de x a l a p u i s s a n c e exp

14.4.13

Cr
eation de classes

Une classe est une collection de methodes referant `a lobjet defini par la variable self en
premier argument. Une classe permet de creer plusieurs objets similaires mais compl`etement
independants les uns des autres.
La m
ethode constructeur
Cest la methode qui sera executee `
a la creation de lobjet (

init

).

c l a s s Cercle :
def
init ( self , r) :
s e l f . rayon = r

Les autres m
ethodes de lobjet ont acc`es aux variables commencant par lobjet lui-meme
(self).
import math
c l a s s Cercle :
def
init ( self , r) :
s e l f . rayon = r
def circonference ( s e l f ) :
r e t u r n math . p i ( 2 s e l f . rayon )
def aire ( s e l f ) :
r e t u r n math . p i s e l f . rayon 2

Pour utiliser les methodes dune classe, il suffit de creer un objet et dappeler ses methodes
avec la syntaxe objet.methode(). Par exemple, considerant que la classe precedente a ete sauvegardee dans le fichier Cercle.py :
>>> from C e r c l e import C e r c l e
>>> a = C e r c l e ( 4 )
>>> a . c i r c o n f e r e n c e ( )
25.132741228718345
>>> a . a i r e ( )
50.26548245743669

14.4.14

Module

Un module est une collections de fonctions reunies dans un fichier .py.


Pour utiliser ces fonctions il faut dabord importer le module.

`
14.4. LANTISECHE
PYTHON (PYTHON CHEAT SHEET)

Premi`
ere forme : importer un module
import sys , time
p r i n t s y s . path
p r i n t time . time ( )

Deuxi`
eme forme : importer des
el
ements dun module
from random import r a n d i n t , un ifo rm
print randint (100 ,200)
p r i n t u ni fo rm ( 0 , 1 )

Importer toutes les fonctions dun module


from random import

Modifier le nom de r
ef
erence
import wx . html a s html
win = html . HtmlWindow ( )

Cr
eer ses propres modules
Dans le fichier monmodule.py :
Mon module de f o n c t i o n s
d e f un ( ) :
p r i n t f o n c t i o n un
d e f deux ( x ) :
p r i n t l e c a r r e de %d e s t : %d % ( x , xx )

Dans un interpreteur :
>>> import monmodule
>>> monmodule . un ( )
f o n c t i o n un
>>> monmodule . deux ( 2 )
l e c a r r e de 2 e s t : 4
>>> d i r ( monmodule )
[ builtins
, doc ,
>>> monmodule . d o c
Mon module de f o n c t i o n s

file

name

, un , deux ]

La fonction dir() renvoi la liste des attributs et des fonctions appartenant au module.

167

168

14.4.15

CHAPITRE 14. ANNEXES

Exceptions

Lorsquune erreur survient dans le deroulement des instructions, une exception est signalee.
Le programme arrete et un message derreur est affiche.
>>> f = open ( new . t x t , r )
Traceback ( most r e c e n t c a l l l a s t ) :
F i l e <s t d i n > , l i n e 1 , i n <module>
IOError : [ Errno 2 ] No such f i l e o r d i r e c t o r y :

new . t x t

Interception dune exception (permet au programme de continuer `


a rouler)
try :
f = open ( new . t x t , r )
e x c e p t IOError , msg :
p r i n t msg
f = open ( d e f a u l t . t x t , r )

`
14.4. LANTISECHE
PYTHON (PYTHON CHEAT SHEET)

14.4.16

Mots cl
es

and
assert
break
class
continue
def
del
if
elif
else
try
except
finally
exec
for
from
global
import
in
is
lambda
not
or
pass
print
raise
return
while
yield
None
True
False

et, permet de combiner des conditions


outil de deboguage, affiche les erreurs de declaration
permet de sortir dune boucle avant la fin
demarre la definition dune classe
avance directement `a la prochaine iteration dune boucle
demarre la definition dune fonction ou dune methode
elimine un objet et sa reference
demarre une condition
rajoute une possibilite dans une declaration conditionnelle
execution si aucune condition na ete respectee
tentative dexecuter des instructions
si try na pas reussi, permet dintercepter des exceptions
execution `
a la fin dun bloc try... except... finally (optionnel)
execution dynamique de code Python
declare une boucle
designe un module duquel importer des classes ou des fonctions
declare une variable globale
importe des modules, des classes ou des fonctions
permet de tester lappartenance dune variable `a un groupe
permet de tester lidentite dune variable
creation dune fonction anonyme
negation, permet des conditions negatives, ex. if a not in list
ou, permet de combiner des conditions
passe tout droit, aucune execution
affiche des valeurs
affiche des messages derreur ou dexception
met fin `
a une fonction et, si necessaire, retourne une valeur
declare une boucle `a duree indeterminee
g`ele letat dun generateur jusquau prochain appel next
valeur nulle
booleen vrai
booleen faux

169

Vous aimerez peut-être aussi