L’avantage d’un format structuré de partition numérique comme celui proposé par MusicXML est qu’il est facile d’y appliquer des requêtes de recherche afin d’en extraire un certain nombre d’informations utiles : méta-informations : style, compositeur.., ainsi que les notes elles-mêmes bien évidemment.
Nous proposons ici d’utiliser le langage XQuery, qui sert à adresser des requêtes sur tout type de document XML, et donc en ce qui nous concerne, MusicXML.
Cet article ne propose pas une introduction à ce langage, de nombreux sites font cela très bien, cependant pour rendre le reste de l’article compréhensible, voici quelques notions très très basiques d’XQuery:
//elem
–> renvoie tous les elem quelque soit leur position dans l’arbre XML
//elem/text()
–> renvoie les valeurs de chaque elem (si c’est une feuille)
//elem/[@attr="val"]
–> renvoie l’élément elem ayant l’attribut attr de valeur val
data(//elem/@attr)
–> renvoie la valeur de l’attribut attr de l’élément elem
Voici quelques requêtes élémentaires pour extraire des informations simples d’un morceau (il est nécessaire d’avoir des notions préalables de MusicXML, que vous trouverez dans MusicXML):
Table des matières
Titre du morceau
//work/work-title/text()
Compositeur
//identification/creator[@type="composer"]/text ()
Tempo
data(//sound/@tempo)
sous-entendu à la noire.
Attention : il peut y avoir plusieurs tempos dans le morceau, ou celui-ci peut être inexistant..
Nombre d’instruments
count(//part)
Signature rythmique
concat(//beats/text(), "/", //beat-type/text())
qui pourrait renvoyer 4/4 par exemple
Attention : il peut y avoir plusieurs signatures rythmiques sur une part, sachant qu’il peut y avoir plusieurs parts.
Pour extraire les signatures rythmiques de la part P1, la requête serait :
for $t in //part[@id="P1"]//time
return concat($t/beats/text(), "/", $t/beat-type/text())
qui pourrait renvoyer par exemple:
4/4
6/8
4/4
Morceau pour piano seul ?
//instrument-name/text() = "Piano" and (count(//part) eq 1 and (//staff/text() = "1" and //staff/text() = "2"))
renvoie true ou false.
Tonalité
La tonalité est représentée par le nombre de dièses ou de bémols à la clef. L’élément fifths se réfère à la position de la clef sur le cycle des quintes. Ainsi, la clef de Do (sans altérations) a une valeur de fifths 0. La clef de Fa (1 bémol) a une valeur de -1, et la clef de Sol (1 dièse), une valeur de 1.
Tonalité | Fifths |
---|---|
Do | 0 |
Fa | -1 |
Sib | -2 |
Mib | -3 |
Lab | -4 |
Réb | -5 |
Solb | -6 |
Sol | 1 |
Ré | 2 |
La | 3 |
Mi | 4 |
Si | 5 |
Fa# | 6 |
La requête est:
for $x in //key/fifths
return if ($x/text() = 0) then "Do"
else if ($x/text() = "-1") then "Fa"
else if ($x/text() = "-2") then "Sib"
else if ($x/text() = "-3") then "Mib"
else if ($x/text() = "-4") then "Lab"
else if ($x/text() = "-5") then "Réb"
else if ($x/text() = "-6") then "Solb"
else if ($x/text() = "1") then "Sol"
else if ($x/text() = "2") then "Ré"
else if ($x/text() = "3") then "La"
else if ($x/text() = "4") then "Mi"
else if ($x/text() = "5") then "Si"
else if ($x/text() = "6") then "Fa#"
else "Tonalité indéterminée"
Attention : comme évoqué plus haut, il y a une valeur retournée par part.
Enfin, cette requête ne dit pas si la tonalité est majeure ou mineure.
Utiliser pour cela :
//key//mode/text()
qui vaut « minor » ou « major »
Durée
On peut facilement aller plus loin dans l’utilisation d’XQuery. Pour terminer cette présentation, voici un petit morceau de code permettant d’estimer la durée d’un morceau simple ayant une seule indication de tempo et une seule signature rythmique.
La durée du morceau est calculée selon : tempo x sign ryth x nb mesures
Exemple :
- Si tempo=100 à la noire (100 noires/minute), mesure 4/4 et morceau de 80 mesures
- Durée = 4 x 80 noires = 320 noires / 100 = 3,2 minutes = 3mn 12s
La requête est la suivante:
let $nbmes := count(//measure)
let $mytempo := data(//sound/@tempo)[1] (: on suppose 1 seul ; tjrs à la noire :)
let $nbdetempsparmes := //time/beats/text()[1] (: on suppose 1 seul :)
let $typedetemps := //time/beat-type/text()[1] (:on suppose 1 seul:)
let $rapportalanoire := $typedetemps div 4
let $nbmindec := ($nbmes * $nbdetempsparmes) div ($mytempo * $rapportalanoire)(:en minutes:)
let $nbsecdec := $nbmindec mod 1
let $nbmin := floor($nbmindec)
let $nbsec := floor($nbsecdec * 60)
return concat($nbmin , "mn", $nbsec , "s")
Conclusion
Nous avons vu qu’il était possible à l’aide d’un code XQuery très concis d’extraire des informations utiles d’une partition MusicXML.
La maîtrise de l’extraction des informations de la partition nécessite des aptitudes poussées en programmation, néanmoins, on a pu voir que MusicXML était suffisamment bien structuré pour l’autoriser et qu’ XQuery, langage trop méconnu, était un bon candidat pour ce type de besoin.
Il ne vous reste plus qu’à vous y mettre 🙂