Requêtes XQuery simples sur une partition MusicXML

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):

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
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 🙂

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *