Vous êtes sur la page 1sur 39

Les m elodies de Markov

Melchior Fracas, Paul Fournel 7 Juin 2013

Table des mati` eres


Introduction 1 Connaissance musicales pr eliminaires 2 M ethodologie et outils num eriques 2.1 Analyse th eorique . . . . . . . . . . . . . . . 2.2 Traitement des donn ees . . . . . . . . . . . . 2.2.1 Format Lilypond . . . . . . . . . . . . 2.2.2 Format MIDI . . . . . . . . . . . . . . 2.3 Stockage dans une base de donn ee SQL . . . 2.3.1 Impl ementation de la base de donn ees 2.3.2 Acc` es ` a la base de donn ees depuis R . 2.4 Analyse des donn ees en R . . . . . . . . . . . 3 R esultats 3.1 Matrice markovienne et test du 2 . . . . 3.1.1 Explication du test statistique . . 3.1.2 R esultat du test statistique . . . . 3.2 Di erentes m ethodes de comparaison . . . 3.2.1 Comparaison des normes . . . . . 3.2.2 Comparaison des distances . . . . 3.2.3 M ethode . . . . . . . . . . . . . . . 3.2.4 R esultats par auteurs/types/styles 3.2.5 Conclusion de la classication . . . Conclusion R ef erences Annexes Code SQL . . . Code PHP . . . Code Javascript Code R . . . . 3 4 6 6 9 9 10 10 10 10 11 12 12 12 14 14 14 14 15 15 19 19 21 22 22 22 23 31

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

Introduction
Lobjectif de cette etude est de mod eliser les m elodies des morceaux de musique par des cha nes de Markov. Cette id ee repose sur le postulat que les compositeurs utilisent une palette de notes et sen servent ensuite pour composer lensemble des morceaux de leur uvre. Cette etude repose sur des travaux qui ont d ej` a montr e que lon peut classier les morceaux de musique par leur entropie [6]. Xenakis dans son livre Musique Formelles tente de mettre au point un nouveau type de composition utilisant les math ematiques. On peut noter que dans lhistoire certaines populations ont aussi eu recours aux math ematiques pour r ealiser leurs uvres musicales. Pour ne citer quun seul exemple, ` a Bali la musique traditionnelle a largement recours au modulo pour composer. Ainsi, certaines phrases m elodiques sont r ep et ees en boucles, mais ne se retrouvent quau bout dun certain nombre dit erations. Il sagit du th eor` eme des restes chinois. Nous esp erons donc, apr` es avoir mod elis e les transitions dun grand nombre de morceaux de musique, obtenir un outil ecace pour reconnaitre lauteur, le type, ou l epoque dun morceau de musique inconnu. Loutil pourrait aussi permettre de g en erer un morceau de musique selon une certaine combinaison type/auteur/ epoque ; et une derni` ere application serait de regrouper les auteurs par similitudes entre leurs uvres. Merci ` a Madame Bienvenue de nous avoir accompagn e pendant le TER.

Connaissance musicales pr eliminaires

An de comprendre cette etude, il est n ecessaire de comprendre les bases du solf` ege et de lharmonie. Cette partie sadresse aussi aux lecteurs non-musiciens. D enition (m elodie) : Dans tout syst` eme musical, la m elodie d esigne une variation dans la hauteur et la dur ee des notes. G en eralement le compositeur utilise les hauteurs qui font partie dun ensemble nomm e gamme. D enition (gamme et tonalit e) : une gamme est une progression de hauteur codi ee. Chaque culture a d eni ses propres gammes. Voici par exemple la gamme majeure tr` es souvent utilis ee en musique occidentale.

Figure 1 Gamme majeure Le ton correspond ` a un intervalle en Hertz ton temp er e = 2 12 = 1.059463 N ; ou N est la note pr ec edente situ ee un demi-ton plus bas avec comme unit e, le Hertz. La tonalit e est la progression en termes de notes si lon xe le degr e I de la gamme. Par exemple en xant do, on obtiendra :
1 2
1

Figure 2 Gamme de Do majeure Ou encore en xant un fa :

Figure 3 Gamme de Fa majeure Un math ematicien peut comprendre lharmonie occidentale comme un ensemble en bijection avec Z/7Z. On distingue 12 notes di erentes en ne prenant

pas en compte les octaves (m eme notes r ep et e 12 demi-tons plus haut).

Figure 4 Gamme de Fa majeure Nous avons donc autant de tonalit es que de notes modulo 12. Si la note est trop aigu e, on se ram` enera ` a son equivalent grave. Pour pouvoir comparer les notes les unes avec les autres il est essentiel de se ramener ` a la m eme tonalit e. Nous choisissons arbitrairement et par simplicit e la tonalit e de Do majeur pour transposer le morceau. Il est n ecessaire de transposer les partitions pour mener notre etude, car chaque degr e de la gamme poss` ede une fonction. Ainsi une m eme note dans deux tonalit es di erentes naura pas la m eme fonction. Ainsi une m eme transition naura pas le m eme r ole. De la m eme mani` ere que quand on veut comparer deux espaces anes on se ram` ene aux espaces vectoriels g en erateurs, pour comparer deux partitions on se ram` enera ` a la tonalit e de Do majeur.

2
2.1

M ethodologie et outils num eriques


Analyse th eorique

Lobjectif de cette etude est donc de mod eliser les morceaux de musique math ematiquement. Lhypoth` ese etant que chaque compositeur utilise chaque transition entre deux notes de mani` ere statistiquement signicative, les cha nes de Markov sont a priori un choix valable pour cette mod elisation. Une partition de musique dun morceau nous donne plusieurs composantes : la m elodie, le rythme, mais aussi di erentes informations sur linterpr etation. Comme dans toute mod elisation, il est n ecessaire de simplier les param` etres pour ne garder que ceux qui sont cons equents quant ` a lobjectif. Nous avons d ecid e de nen garder que deux : la hauteur des notes et la notion du rythme. Par souci de simplicit e de traitement des donn ees, il est pr ef erable que chaque etat de la chaine de Markov soit un scalaire plut ot quun vecteur ` a plusieurs dimensions. Nous avons donc choisi de mod eliser le rythme en r ep etant la note autant de fois que sa valeur rythmique. Ce gain en simplicit e nous fais perdre une partie de linformation. Par exemple, deux croches sont cod ees de la m eme mani` ere quune noire. On prendra pour unit e le quart de temps.

Figure 5 Deux gures rythmiques Dans les deux cas, on obtient le codage [7,7,7,7]. Pour pouvoir exploiter les partitions, il est n ecessaire davoir les donn ees au format num erique et sous forme compr ehensible par notre algorithme sous le logiciel R. Comme cela a et e dit pr ec edemment, an de simplier le mod` ele, nous avons choisi de ne prendre en consid eration que la note et non loctave. Un Do grave sera donc cod e de la m eme mani` ere quun Do aigu. Le codage choisi est donn e par le tableau ci-dessous.

Do Do# Re Re# Mi Fa Fa# Sol Sol# La La# Si Silence .

0 1 2 3 4 5 6 7 8 9 10 11 1

Sous R, lencodage di` ere de 1 pour ne pas avoir car les index commencent a 1 et non ` ` a 0 comme en Javascript. Do Do# Re Re# Mi Fa Fa# Sol Sol# La La# Si Silence 1 2 3 4 5 6 7 8 9 10 11 12 13

Une partition sera donc repr esent ee de cette mani` ere : V1 = c(9, 9, 9, 9, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 11, 11, 9, 9, 8, 8, 11, 11, 2, 2, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 2, 2, 0, 0, 11, 11, 2, 2, 4, 4, 8, 8, 11, 11, 11, 11, 11, 11, 4, 4, 4, 4, 2, 2, 0, 0, 11, 11, 0, 0, 2, 2, 4, 4, 0, 0, 9, 9, 9, 9, 7, 7, 7, 7, 5, 5, 5, 5, 4, 4, 4, 4, 5, 5, 9, 9, 0, 0, 4, 4, 9, 9, 9, 9, 9, 9, 7, 7, 5, 5, 4, 4, 2, 2, 0, 0, 11, 11, 2, 2, 5, 5, 9, 9, 7, 7, 4, 4, 5, 5, 2, 2, 0, 0, 11, 11, 2, 2, 5, 5, 4, 4, 7, 7, 11, 11, 2, 2, 7, 7, 7, 7, 7, 7, 5, 5, 4, 4, 2, 2, 0, 0, 11, 11, 9, 9, 0, 0, 4, 4, 7, 7, 5, 5, 2, 2, 4, 4, 0, 0, 11, 11, 0, 0, 4, 4, 0, 0, 2, 2, 5, 5, 9, 9, 0, 0, 5, 5, 5, 5, 5, 5, 4, 4, 2, 2, 0, 0, 11, 11, 2, 2, 4, 4, 7, 7, 11, 11, 2, 2, 7, 7, 4, 4, 11, 11, 2, 2, 0, 0, 4, 4, 9, 9, 10, 10, 9, 9, 4, 4, 5, 5, 9, 9, 2, 2, 5, 5, 4, 4, 7, 7, 5, 5, 2, 2, 9, 9, 0, 0, 11, 11, 6, 6, 7, 7, 11, 11, 2, 2, 9, 9, 11, 11, 7, 7, 5, 5, 2, 2, 11, 11, 5, 5, 0, 0, 0, 0, 4, 4, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 4, 4, 2, 2, 1, 1, 4, 4, 5, 5, 7, 7, 9, 9, 7, 7, 5, 5, 4, 4, 1, 1, 10, 10, 9, 9, 7, 7, 5, 5, 4, 4, 2, 2, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 5, 5, 4, 4, 3, 3, 6, 6, 7, 7, 9, 9, 11, 11, 9, 9, 7, 7, 6, 6, 3, 3, 0, 0, 11, 11, 9, 9, 7, 7, 6, 6, 4, 4, 7, 7, 0, 0, 11, 11, 0, 0, 3, 3, 4, 4, 0, 0, 9, 9, 7, 7, 6, 6, 9, 9, 3, 3, 6, 6, 9, 9, 9, 9, 9, 9, 7, 7, 6, 6, 4, 4, 3, 3, 4, 4, 7, 7, 11, 11, 4, 4, 7, 7, 11, 11, 11, 11, 11, 11, 7, 7, 6, 6, 4, 4, 3, 3, 4, 4, 9, 9, 0, 0, 4, 4, 9, 9, 0, 0, 0, 0, 0, 0, 11, 11, 9, 9, 7, 7, 6, 6, 9, 9, 11, 11, 9, 9, 7, 7, 6, 6, 4, 4, 7, 7, 6, 6, 4, 4, 9, 9, 6, 6, 4, 4, 3, 3, 7, 7, 4, 4, 2, 2, 0, 0, 8, 8, 2, 2, 0, 0, 11, 11, 9, 9, 0, 0, 11, 11, 9, 9, 3, 3, 9, 9, 11, 11, 0, 0, 6, 6, 0, 0, 11, 11, 9, 9, 3, 3, 9, 9, 7, 7, 6, 6, 4, 4, 6, 6, 7, 7, 11, 11, 4, 4, 6, 6, 7, 7, 4, 4, 11, 11, 7, 7, 4, 4, 2, 2, 1, 1, 4, 4, 7, 7, 9, 9, 10, 10, 10, 10, 10, 10, 9, 9, 7, 7, 5, 5, 7, 7, 4, 4, 5, 5, 4, 4, 5, 5, 9, 9, 2, 2, 10, 10, 0, 0, 2, 2, 4, 4, 2, 2, 0, 0, 10, 10, 9, 9, 7, 7, 9, 9, 0, 0, 5, 5, 2, 2, 4, 4, 5, 5, 8, 8, 5, 5, 4, 4, 2, 2, 0, 0, 11, 11, 0, 0, 4, 4, 9, 9, 5, 5, 7, 7, 9, 9, 11, 11, 9, 9, 7, 7, 5, 5, 4, 4, 2, 2, 4, 4, 7, 7, 0, 0, 9, 9, 11, 11, 0, 0, 2, 2, 0, 0, 11, 11, 9, 9, 8, 8, 2, 2, 0, 0, 11, 11, 4, 4, 11, 11, 0, 0, 2, 2, 8, 8, 5, 5, 4, 4, 2, 2, 0, 0, 2, 2, 4, 4, 8, 8, 9, 9, 4, 4, 2, 2, 0, 0, 4, 4, 0, 0, 11, 11, 9, 9, 3, 3, 9, 9, 11, 11, 0, 0, 4, 4, 0, 0, 11, 11, 9, 9, 3, 3, 0, 0, 11, 11, 9, 9, 8, 8, 6, 6, 8, 8, 11, 11, 4, 4, 11, 11, 8, 8, 11, 11, 4, 4, 2, 2, 0, 0, 11, 11, 0, 0, 11, 11, 0, 0, 4, 4, 9, 9, 4, 4, 0, 0, 4, 4, 9, 9, 7, 7, 5, 5, 4, 4, 2, 2, 0, 0, 2, 2, 8, 8, 11, 11, 8, 8, 2, 2, 8, 8, 4, 4, 2, 2, 0, 0, 11, 11, 9, 9, 4, 4, 9, 9, 11, 11, 0, 0, 9, 9, 4, 4, 0, 0, 9, 9, 7, 7, 5, 5, 4, 4, 2, 2, 4, 4, 5, 5, 9, 9, 10, 10, 0, 0, 2, 2, 4, 4, 5, 5, 2, 2, 10, 10, 2, 2, 0, 0, 2, 2, 4, 4, 8, 8, 9, 9, 11, 11, 0, 0, 2, 2, 4, 4, 0, 0, 9, 9, 0, 0, 11, 11, 0, 0, 2, 2, 5, 5, 4, 4, 6, 6, 8, 8, 9, 9, 11, 11, 5, 5, 2, 2, 5, 5, 8, 8, 8, 8, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 4, 4, 2, 2, 0, 0, 11, 11, 9, 9, 11, 11, 0, 0, 9, 9, 4, 4, 0, 0, 9, 9, 4, 4, 0, 0, 9, 9, 3, 3, 3, 3, 0, 0, 0, 0) ;

Ce vecteur correspond ` a la partition :

Figure 6 Morceau traduit

2.2

Traitement des donn ees

Traditionnellement les partitions ont et e ecrites sur du papier ` a musique. Nous avons besoin de donn ees num eriques. La premi` ere partie de notre etude a donc et e dobtenir les partitions dans un format intelligible sous le logiciel R et dans les contraintes que nous nous sommes x ees. 2.2.1 Format Lilypond

Le format Lilypond[4] permet dencoder des partitions avec un langage tr` es proche de celui du latex. Chaque note est d enit par sa hauteur et son rythme. Peuvent ensuite venir sajouter toute une palette de nuances (liaison, p edale, paroles, etc.). Nous avons donc construit un parseur (traducteur) en JavaScript qui permet, a ` partir dun chier Lilypond (*.ly) dexporter une chaine de caract` ere qui repr esente notre suite d etats sous R.

Le parseur repose principalement sur lextraction des hauteurs de notes gr ace aux expressions r eguli` eres [2]. Ce parseur nest ecace quau traitement de notes pures ; il faut pr e-enregistrer tous les signes possibles, au risque de faire une erreur lors de la rencontre dun signe inconnu. Ainsi il nest exploitable que pour un nombre limit e de partitions. Puisque le projet repose sur la num erisation dun grand nombre de partitions dans la base de donn ees, nous avons mis au point un deuxi` eme parseur qui utilise le format MIDI.

2.2.2

Format MIDI

Le format midi est un type dencodage des notes en hexad ecimal. Cod e sur 8bits, on retrouve la hauteur de la note ainsi que sa dur ee. Le parseur utilise une biblioth` eque JavaScript [1] qui transforme un chier midi en un objet contenant lensemble des notes. Les notes sont elles-m eme des objets, dont les caract eristiques sont le volume, la hauteur, la dur ee. Le parseur analyse ainsi chaque note et rep` ere les notes et les silences. Les limites de ce parseur sont quil ny a plusieurs fa cons dencoder une m eme phrase rythmique. Ainsi, les notes de volumes nulles peuvent, soit etre interpr et ees comme des silences, soit comme des nuances. Les deux parseurs bien que perfectibles permettent de couvrir un grand nombre de partitions di erentes. Si cette etude etait pouss ee, il serait possible de construire un parseur plus performant couvrant la quasi totalit e des partitions. Les partitions proviennent de la base de donn ee du projet libre de droit Mutopia [5].

2.3

Stockage dans une base de donn ee SQL

Pour pouvoir utiliser nos donn ees de mani` ere rapide, il etait primordial dutiliser une base de donn ees. Gr ace ` a cette technologie nous pouvons faire des requ etes sur plusieurs param` etres ` a la fois. Notre objectif etait de construire une unique base de donn ees accessible depuis un terminal R connect e` a internet.

2.3.1

Impl ementation de la base de donn ees

La base de donn ees est impl ement ee en SQL sur un serveur Linux en ligne. Il ny a quune seule table. Une partition est r ef erenc ee par son nom, son auteur, type, son instrument et sa r ef erence internationale. 2.3.2 Acc` es ` a la base de donn ees depuis R

Pour pouvoir utiliser cette base de donn ees depuis le terminal de commande R, nous avons construit une page php sur le serveur distant qui permet d ecouter et dacher les requ etes SQL.

10

Figure 7 Extrait de la base de donn ee SQL Dans R, nous avons elabor e une biblioth` eque de fonctions permettant dacc eder a cette page php et ainsi dex ` ecuter des commandes SQL sur le serveur Linux.

2.4

Analyse des donn ees en R

On doit analyser sous R un vecteur de nombres correspondants ` a chaque note, de type : V1 = c(-1,11,11,10,10,9,.....,11,11,11,11,8,8,5,5,... ) Il faut maintenant compter les transitions de chaque vecteur, on va avoir de mani` ere assez evidente lalgorithme : for (i in 1:length(Partition)-1){ w=Partition[i] q=Partition[i+1] Observ[w,q]=Observ[w,q]+1 } Ainsi, on prend la premi` ere note, et on regarde la deuxi` eme note. On peut donc incr ementer de 1 la transition premi` ere note, deuxi` eme note cest ` a dire la case de la matrice sur la ligne premi` ere note (re# correspondrait ` a la quatri` eme ligne) et sur la colonne deuxi` eme note. On r eit` ere ensuite en se pla cant sur la deuxi` eme case ; et ainsi de suite. Cet algorithme est utilis e dans la fonction getMarkov de notre biblioth` eque.

11

R esultats

Commentaire pr eliminaire : il est utile de rappeler que lhypoth` ese faite au d epart etait quil y a une corr elation entre la progression de notes dun morceau et un compositeur. Les di erentes etudes statistiques que nous avons men ees sur notre base de donn ees ne laisse pas ` a penser quil y a un lien. Il est possible que dautres mod` eles soient plus performants.

3.1

Matrice markovienne et test du 2

La mod elisation d ecrite dans la partie pr ec edente nous permet dobtenir une matrice markovienne de transition.

Figure 8 Matrice Markovienne g en er ee par lensemble des partitions de Bach En rouge : probabilit e de passer ` a RE ` a partir de DO : 6,9% 3.1.1 Explication du test statistique

On constate quil y a une forte concentration des transitions sur les termes diagonaux. On peut expliquer ce ph enom` ene par lencodage rythmique des partitions. On a donc une matrice g en er ee par lensemble des partitions dun compositeur et une matrice dobservation g en er ee par seulement un morceau myst` ere. On souhaite donc construire un test statistique dont les hypoth` eses sont les suivantes :

12

H0 , la partition myst` ere est bien du compositeur. H1 , la partition myst` ere nest pas du compositeur. Puisque chaque ligne dune matrice de transition correspond ` a une loi de probabilit e discr` ete, pour chacune on peut utiliser un test du 2 dad equation ` a une loi. Puisque que lon souhaite que toutes les lignes de la matrice suivent la loi correspondante et puisque quune somme de loi du 2 reste une loi du 2 , on peut sommer les r esultats et ainsi obtenir une loi du 2 dont le degr e de libert e est la somme des degr es des libert es des lois pr ec edentes. Voici limpl ementation sous R : chi2m = function(A,B){ # Une fonction pour g en erer une paritition # Parametres : # * A une matrice de probabilit e (Matrix) # * B une matrice dobservation (Matrix) res = rep(0,12); degLib = rep(0,12); ChiFractile = rep(0,12); for (i in (1:12)){ stat=0; newA = A[i,][(A[i,]!=0)] newB = B[i,][(A[i,]!=0)] Ni = sum(newB) if(Ni!=0){ stat = sum((newB-Ni*newA)^2/(Ni*newA)) degLib[i]=length(newA) ChiFractile[i] = qchisq(.05, df=degLib[i]) res[i] = stat; } } list(stattot = sum(res), statArray = res, frac = + ChiFractile, k = degLib, ktot=sum(degLib), + fractot=qchisq(.05, df=sum(degLib))) }

13

3.1.2

R esultat du test statistique

Figure 9 R esultat de la fonction dequiestce On a 43 bons r esultats sur 100, r esultat qui est bien plus grand que le hasard puisque la base de donn ees comporte 6 auteurs.

3.2
3.2.1

Di erentes m ethodes de comparaison


Comparaison des normes

Dans un deuxi` eme temps, on etudie simplement la norme des di erences entre la matrice du morceau dont lauteur est ` a trouver et celles des compositeurs de notre base de donn ees.

Figure 10 R esultat de la fonction dequiestce2 avec les normes On obtient 24 r esultats justes. Avec des r esultats particuli` erement juste pour Bach et Mozart. 13 partitions de Bach sur les 35 de notre base de donn ees et 7 partitions de Mozart sur les 18 de notre base de donn ees. 3.2.2 Comparaison des distances

On calcule les distances entre la matrice dun morceau particulier et celle de chaque auteur dans la base de donn ees. On utilise la distance suivante : d(A,B) = (A B ) A, B MRn

On regarde ensuite laquelle de ces distance est la plus petite, et on suppose que la distance est la plus petite avec lauteur du morceau. Avec ce raisonnement, sur 100 auteurs de la base de donn ees, on obtient 20 r esultats justes (o` u le morceau est bien reconnu par le logiciel) : On remarque que cette technique marche toujours avec Bach (encore 13 sur 35), mais aussi avec Schumann (3 sur 6). On voit d ej` a que les auteurs peuvent avoir leurs sp ecicit es, par exemple une variance elev ee d ecart (des morceaux tr` es di erents les uns des autres) ; qui font que certaines techniques marchent sur certains morceaux, mais pas sur dautres. 14

Figure 11 R esultat de la fonction dequiestce3 avec les distances On voit enn que le test du deux nous fourni de meilleurs r esultats que des tests plus simples. 3.2.3 M ethode

Pour la classication, on a besoin dune matrice recensant les distances entre chaque el ement. On a encore besoin de d enir une distance entre deux matrices, on r eutilise donc la distance vu pr ec edemment. On r ecup` ere ensuite toutes les matrices de transition, et on calcule la matrice des distances entre tous les el ements : for (i in (1:n_bdd)){ for (j in (1:n_bdd)){ MD[i,j] = dist_mat(G[,,i],G[,,j]) } } On peut ensuite utiliser le package cluster de R qui dessine larbre de classication ` a partir de la matrice de distance. 3.2.4 R esultats par auteurs/types/styles

15

Figure 12 Classication par auteur 16

Figure 13 Classication par type 17

Figure 14 Classication par style 18

3.2.5

Conclusion de la classication

M eme si on ne voit pas de gros clusters se dessiner, on aper coit tout de m eme des regroupements de certains morceaux dans larbre. En se r ef erant aux morceaux de la base de donn ees, on peut en d eduire que lors de la composition, un compositeur peut se sentir dune certaine veine, et la garder sur plusieurs morceaux. Du premier arbre, on peut tirer que les morceaux de H andel sont souvent group es par deux, et quils se m elangent parfois avec Bach ou Mozart. Cependant, Bach et Mozart etant les deux auteurs les plus souvent pr esents dans notre base de donn ees, on ne peut pas vraiment tirer de conclusions. On aper coit aussi un morceau de Chopin qui semble saccorder parfaitement avec deux Bach, on peut imaginer une certaine inspiration de Chopin lors de la composition du morceau. Enn, un certain corpus de Bach regroupe quatre partitions dans un cluster particulier, on peut imaginer que, si un cinqui` eme morceau de ce corpus venait a ` etre d ecouvert, il sacherait dans ce cluster et on aurait un bon indice pour attribuer la paternit e de ce morceau. Des deuxi` eme et troisi` eme arbres, on d ecouvre quelques groupements de sonates, ou de morceaux baroques, mais il parait dicile den tirer des conclusions, dune part par la multiplicit e des types (aria, sonate, etc...) et le peu de genres dont nous disposons (baroque, classique, romantic).

Conclusion
Nous tenons avant tout ` a souligner la vitalit e dutiliser dune base de donn ees d` es quon traite des relev es ; laccessibilit e des requ etes rendant le travail beaucoup, beaucoup plus simple. La reconnaissance dauteur, sans etre un succ` es int egral, nous apporte des r esultats satisfaisants (43%), am eliorables en etoant plus la base de donn ees, et/ou en augmentant la qualit e de lencodage des partitions. Lensemble tr` es restreint des notes de musique, sans prendre en compte ni le rythme, ni les accords, nuances, etc... cr ee une grande confusion dans la reconnaissance des morceaux. Les transitions seules ne susent donc pas vraiment ` a mod eliser de la musique, on peut donc sorienter au choix vers : une impl ementation du rythme, ou bien une etude des transitions coupl ee ` a une etude de la fr equence des notes. Enn, la repr esentation des donn ees faisant malgr e tout apparaitre certains groupes, on peut se demander si la classication ne serait pas am elior ee avec une autre distance ; une piste serait la distance Kullback-Leibler.[3] Nous avons d evelopp e le g en erateur de musique que nous avions mentionn e

19

dans lintroduction, cependant, il ne permet pas encore davoir une sortie audio du morceau g en er e et donc napporte pas de r esultats ` a notre etude.

Figure 15 50 etats/notes simul es ` a partir de la matrice de transition de Bach

Figure 16 Partition correspondante au morceau simul e Enn, nous voulions proc eder ` a un essai de d e de connaissances entre notre reconnaissance dauteur et la culture d etudiants en musicologie. Nous avons donc cr e e un sondage ` a ces ns, h elas, les r esultats ne sont pas exploitables puisque nous avons seulement 21 r eponses ` a notre sondage en ligne, pourtant largement dius e. Les r esultats tournent autour de 50-60% de bonnes r eponses (contre 43% pour notre test du Chi-deux).

20

R ef erences
[1] Colxi. Js midi parser, Mars 2013. [2] Bernard Desgraupes. Introduction aux expressions r eguli` eres. Vuibert, 2008. [3] Yi-Wen Liu. Composer identication by comparing kullback-leibler distances, Juin 2002. [4] projet GNU. Lilypond... la notation musicale pour tous, Mars 2013. [5] projet GNU. The mutopia project : Free sheet music for everyone, Mars 2013. [6] Iannis Xenakis. Musiques Formelles. La revue musicale - Richard Masse Paris, 1963.

21

Annexes
Code SQL CREATE TABLE partitions ( id int(11) NOT NULL AUTO_INCREMENT, ref varchar(255) COLLATE latin1_general_ci NOT NULL, titre varchar(255) COLLATE latin1_general_ci NOT NULL, auteur varchar(255) COLLATE latin1_general_ci NOT NULL, date int(11) NOT NULL, style varchar(255) COLLATE latin1_general_ci NOT NULL, type varchar(255) COLLATE latin1_general_ci NOT NULL, instrument varchar(255) COLLATE latin1_general_ci NOT NULL, notes text COLLATE latin1_general_ci NOT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM AUTO_INCREMENT=117 DEFAULT CHARSET=latin1; --- Contenu de la table partitions -INSERT INTO partitions VALUES (1, BWV 1008, Bach - Cello Suite II, Bach, 1721, baroque, prelude, cello, V1 = c(9, 9, 9, 9, 0, 0, 0...); Code PHP <?php $compositeur = (isset($_GET["compositeur"]) ? $_GET["compositeur"]:); $periode = (isset($_GET["periode"]) ? $_GET["periode"]:); $id = (isset($_GET["id"]) ? $_GET["id"]:); $where = ; $something = false; if($compositeur != * & $compositeur != ){ $where .= "auteur=".$compositeur." AND "; $something = true; } if($periode != * & $periode != ){ $where .= "periode=".$periode." AND "; $something = true; } if($id != * & $id != ){ $where .= "id=".$id." AND "; $something = true; }

22

if($something){ $where = substr_replace($where ,"",-5); $sql = "SELECT notes FROM partitions WHERE ".$where; }else{ $sql = "SELECT notes FROM partitions"; } $hostname $username $password $dbname = = db******.db.1and1.com; = dbo*****; = *******; db*****;

// connect to the server and select a database $dbh = mysqli_connect($hostname,$username,$password,$dbname) or die("Problem connecting: ".mysqli_error()); //run a query, returning a result set $result = mysqli_query($dbh,$sql); // loop through the result set and display the results while ($row = mysqli_fetch_assoc($result)){ echo $row[notes]; } //free the memory and close the connection mysqli_free_result($result); mysqli_close($dbh); ?> Code Javascript

// Extracteur MIDI <!doctype html> <html> <head> </head> <body> <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script> Simple example for JSMIDIParser <br/> <input type="file" id="filereader"/> <div id="mesnotes"></div> <input type="button" id="transpo" value="Transposer" /> <div id="mesnotestranspo"></div> <script src="JSMIDIParser.js"></script> <script> //d efinition de la fonction modulo Number.prototype.mod = function(n) { return ((this%n)+n)%n; } 23

var original = []; var morceauTranspo = []; //midiToNotes = [c,c#, d, d#, e, f, f#, g, g#, a, a#, b]; midiToNotes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; function MyCallback(obj){ //valeur de la noire ? timeDivision = obj[timeDivision]/4; console.log(obj[timeDivision]+|+timeDivision); piste = obj[track][1][event]; console.log(piste.length); console.log("%o", obj); $("#mesnotes").append(A = c(); noteTmp = 0; veloTmp = 0; $.each(piste, function(index, value) { if(value[type]<20){ if(value[data].length>1 & value[deltaTime]>0){ //alert(value[type]+|+veloTmp+|+noteTmp); if(value[data][0]==noteTmp & veloTmp>0){ note = midiToNotes[value[data][0]%12]; octave = Math.floor(value[data][0]/12); //$("#mesnotes").append(note+-+octave + : + value[deltaTime]+<br>); }else{ note = -1; octave = 0; } repetitions = Math.floor(value[deltaTime]/timeDivision); for(var i=0;i<repetitions;i++){ $("#mesnotes").append(""+note+","); original.push(note) } } noteTmp = value[data][0]; veloTmp = value[data][1]; } }); $("#mesnotes").append();); console.log(original); }; // JSMIDIParser JSMIDIParser.IO(filereader, MyCallback); $("#transpo").click(function(){ // Pour changer la clef clef = c; 24

switch(clef){ case ces: transpo = 11; break; //dob emol case c: transpo = 0; break; // do case cis: transpo = 1; break; //do# case des: transpo = 1; break; case d: transpo = 2; break; case dis: transpo = 3; break; case ees: transpo = 3; break; case e: transpo = 4; break; case eis: transpo = 5; break; case fes: transpo = 4; break; case f: transpo = 5; break; case fis: transpo = 6; break; case ges: transpo = 6; break; case g: transpo = 7; break; case gis: transpo = 8; break; case aes: transpo = 8; break; case a: transpo = 9; break; case ais: transpo = 10; break; case bes: transpo = 10; break; case b: transpo = 11; break; case bis: transpo = 0; break; default: break; } $("#mesnotestranspo").append(V1 = c(); $.each(original, function( key, value ) { //On transpose if(value!=-1){ value = (value-transpo).mod(12); } $("#mesnotestranspo").append(value+","); morceauTranspo.push(value); }); $("#mesnotestranspo").append();); console.log(morceauTranspo); }); </script> <body> </html> // Extracteur lilypond <html> <head> <title>Extraction des Notes</title> <style type="text/css"> #exec { cursor:pointer; margin:5px 0 5px 0; border:1px black solid; 25

border-radius:2px; width:50px; text-align:center; } #lilyIn{ width:800px; height:300px; } #out{ width:90%; word-wrap:break-word; } </style> </head> <body> <H2>Traitement dun fichier Lilypond</H2> <textarea id="lilyIn" cols="" rows=""></textarea><br> <input type="radio" name="mode" value="normal" checked> Mode normal<br> <input type="radio" name="mode" value="notes"> Mode notes<br> <div <div <div <div <div id="exec">Extract</div><br /> id="langue"></div> id="test"></div> id="box"></div> id="out">output text...</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script> <script> // definition de la fonction modulo Number.prototype.mod = function(n) { return ((this%n)+n)%n; }

// On ecoute le click sur le div #exec $("#exec").click(function(){ // Code Javascript pour extraire les notes //1. On recupere ce quil y a dans la textbox $("#out").html(); var mychar = $("#lilyIn").val();

var langue = mychar.match(/\include "(.*).ly"/, ); if(langue != null){ $("#langue").html("Encodage : "+langue[1]); 26

codage = langue[1]; }else{ $("#langue").html("Encodage : default"); codage = "default"; } var resClef = mychar.match(/\\key ([a-z]+) \\([a-z]{5})/); var clef = []; if(resClef != null){ clef[0] = resClef[1]; clef[1] = resClef[2]; $("#langue").append(" et clef : "+clef); }else{ clef[0] = "c"; clef[1] = "major"; $("#langue").append(" et clef : "+clef); } mychar = mychar.replace(/\include "(.*).ly"/g, );

mychar = mychar.replace(/\\version(.*)"(.*)"/g, ); // On supprime les commentaires mychar = mychar.replace(/%[^(\n)]+\n/g, ); // On supprime les saut de ligne et les tabs mychar = mychar.replace(/\s{2,}/g, );

//**************************************// // Suppression header & autres // //**************************************// function delete_stuff(maRegex1, maRegex2){ mycIndex = mychar.search(maRegex1); mychar2 = mychar.substring(mycIndex, mychar.length); // On identifie les couple de {} var memoireAcoOuvrante = [0]; var memoireAcoFermante = []; var i=mychar2.indexOf("{")+1+mycIndex; while(memoireAcoFermante.length != memoireAcoOuvrante.length){ if(mychar[i]=={){ memoireAcoOuvrante.push(i); } if(mychar[i]==}){ memoireAcoFermante.push(i); } i++; } mychar = mychar.split(); 27

$.each(memoireAcoOuvrante, function( key, value ) { if(key>0){ mychar[value] = $; } }); $.each(memoireAcoFermante, function( key, value ) { if(key<memoireAcoFermante.length-1){ mychar[value] = "$"; } }); mychar = mychar.join(); mychar = mychar.replace(maRegex2, ); } delete_stuff(/\\header[^{]*\{/g, /\\header(\s)*([^{]*)\{[^}]*\}/); delete_stuff(/\\score[^{]*\{/g, /\\score(\s)*([^{]*)\{[^}]*\}/); //**************************************// // Extraction des Voix // //**************************************// var k=0; var resVoix = []; if($(input[name=mode]:checked).val()==normal){ while(mychar.search(/([a-z]+(\s))=((.*)\{)/g) != -1){ mycIndex = mychar.search(/([a-z]+(\s)*)=((.*?){)/g); mychar = mychar.substring(mycIndex, mychar.length); // On identifie les couple de {} var memoireAcoOuvrante = [0]; var memoireAcoFermante = []; var i=mychar.indexOf("{")+1; while(memoireAcoFermante.length != memoireAcoOuvrante.length){ if(mychar[i]=={){ memoireAcoOuvrante.push(i); } if(mychar[i]==}){ memoireAcoFermante.push(i); } i++; } mychar = mychar.split(); $.each(memoireAcoOuvrante, function( key, value ) { if(key>0){ mychar[value] = $; } }); $.each(memoireAcoFermante, function( key, value ) { 28

if(key<memoireAcoFermante.length-1){ mychar[value] = "$"; } }); mychar = mychar.join();

res = mychar.match(/([a-z]+(\s)*)=([^{]*)\{[^}]*\}/); mychar = mychar.replace(/([a-z]+(\s)*)=([^{]*)\{[^}]*\}/, ); /*$.each(res, function( key, value ) { $("#out").append(key+:+value+<br>); });*/

resVoix[k] = res[0]; //k=0 k++; } }else{ resVoix[0] = mychar; } $.each(resVoix, function( key, value ) { value = value.replace(/([a-z]+(\s))=((.*)\{)/, ) value = value.replace(/\\key ./g, ); value = value.replace(/((\\[\w]+[\s]*)|("(^")"))/g, ); value = value.replace(/"(?:[^\\"]+|\\.)*"/g, ); value = value.replace(/#style = #single-digit/g, ); value = value.replace(/Staff.TimeSignature/g, ); value = value.replace(/(volta [1-9])|(volta)/g, ); value = value.replace(/Adagio/g, );

//alert(value); if(codage==english){ res = value.match(/(([a-g][,]*flat)|([a-g][,]*sharp)|([a-g][,]*ss)|([a-g][,]*ff)|( }else{ res = value.match(/(([a-gr]isis[,]*(\d)*(\.)*)|([a-gr]eses[,]*(\d)*(\.)*)|([a-gr]is[ } voix = parseInt(key)+1; out=V+voix+ = c(; var repetitions = 4; $.each(res, function( key, value ) {

if(value.match(/[0-9]+/g)){ rythme = value.match(/[0-9]+/g); if(value.match(/\./)){ repetitions = (32/rythme)*1.5; 29

}else{ repetitions = (32/rythme); } } dieses = value.split("is").length - 1; bemols = value.split("es").length - 1; switch(value.substr(0,1)){ case r: note = -1; break; case c: note = 0; break; case d: note = 2; break; case e: note = 4; break; case f: note = 5; break; case g: note = 7; break; case a: note = 9; break; case b: note = 11; break; default: break; } //On transpose if(note!=-1){ if(clef[1]==minor){ switch(clef[0]){ case ces: transpo = 2; break; case c: transpo = 3; break; case cis: transpo = 4; break; case des: transpo = 4; break; case d: transpo = 5; break; case dis: transpo = 6; break; case ees: transpo = 6; break; case e: transpo = 7; break; case eis: transpo = 8; break; case fes: transpo = 7; break; case f: transpo = 8; break; case fis: transpo = 9; break; case ges: transpo = 9; break; case g: transpo = 10; break; case gis: transpo = 11; break; case aes: transpo = 11; break; case a: transpo = 0; break; case ais: transpo = 1; break; case bes: transpo = 1; break; case b: transpo = 2; break; case bis: transpo = 3; break; default: break; } }else{ switch(clef[0]){ case ces: transpo = 11; break; 30

case c: transpo = case cis: transpo case des: transpo case d: transpo = case dis: transpo case ees: transpo case e: transpo = case eis: transpo case fes: transpo case f: transpo = case fis: transpo case ges: transpo case g: transpo = case gis: transpo case aes: transpo case a: transpo = case ais: transpo case bes: transpo case b: transpo = case bis: transpo default: break; } }

0; break; = 1; break; = 1; break; 2; break; = 3; break; = 3; break; 4; break; = 5; break; = 4; break; 5; break; = 6; break; = 6; break; 7; break; = 8; break; = 8; break; 9; break; = 10; break; = 10; break; 11; break; = 0; break;

note = (note+dieses-bemols-transpo).mod(12); } for(var i=0;i<repetitions;i++){ out += + note + , ; } }); out = out.substring(0, out.length - 2); out += ");"; $("#out").append(out+<br>) }); }); </script> </body> </html>

Code R ##################################### # Importer Partition depuis Bdd Web # ##################################### # Import de la bibliotheque RCurl 31

library("RCurl") library("RJSONIO") getMarkov <- function(compositeur, periode, style, id){ # Une fonction pour aller chercher dans la bdd et g en erer une matrice de transition # Parametres : # * compositeur (String) # * periode (String), (exemple: "1650 to 1793" ou "<1890" ou ">1500" # * style (Sting) # Note: pour ne pas d efinir un parametre, utiliser "*" # # Valeurs retour : # * M une matrice de transition # * O une matrice dobservation root = "http://ter.isgeek.eu/getbdd.php?" compositeurS = paste("compositeur=",compositeur, sep = "") periodeS = paste("periode=",periode, sep = "") styleS = paste("style=",style, sep = "") idS = paste("id=",id, sep = "") where = paste(compositeurS, periodeS, styleS, idS, sep = "&") link = paste(root, where, sep = "") # On int eroge la bdd sur le serveur web linkContent = getURLContent(link) # On extrait les partitions une par une Notes = strsplit(linkContent[1],;); A = Notes[[1]] n = length(A)

Observ=matrix(0,12,12) ObservT=matrix(0,12,12) for(i in 1:n) { # A chaque it eration la partition est dans Partition Partition = eval(parse(text=A[i])) Partition[which(Partition!=-1)] Partition=Partition+1 # A chaque it eration, on somme lobservation des transitions # de la matrice g en er ee par la partition en cours ` a celle # de la matrice totale for (k in 1:length(Partition)-1){ w=Partition[k] q=Partition[k+1] Observ[w,q]=Observ[w,q]+1 } 32

ObservT = ObservT + Observ } # Markov va contenir la matrice de transition finale Markov = ObservT for (k in (1:12)){ quot=sum(Markov[k,]) if (quot != 0){ Markov[k,]=Markov[k,]/quot } } #Markov = round(Markov,3) list(M = Markov, O = ObservT, Nb = n, Url = link ) } # fin de la fonction getMarkov

getNotes <- function(compositeur, periode, style, id){ # Une fonction pour aller chercher dans la bdd et g en erer une matrice de transition # Parametres : # * compositeur (String) # * periode (String), (exemple: "1650 to 1793" ou "<1890" ou ">1500" # * style (Sting) # Note: pour ne pas d efinir un parametre, utiliser "*" # # Valeurs retour : # * Un vecteur de notes #compositeur=Bach; periode=*;style=*;id=*; root = "http://ter.isgeek.eu/getbdd.php?" compositeurS = paste("compositeur=",compositeur, sep = "") periodeS = paste("periode=",periode, sep = "") styleS = paste("style=",style, sep = "") idS = paste("id=",id, sep = "") where = paste(compositeurS, periodeS, styleS, idS, sep = "&") link = paste(root, where, sep = "") # On int eroge la bdd sur le serveur web linkContent = getURLContent(link) # On extrait les partitions une par une Notes = strsplit(linkContent[1],;); A = Notes[[1]] n = length(A) Notes = NA for(i in 1:n) { # A chaque it eration la partition est dans Partition Partition = eval(parse(text=A[i])) 33

Partition = Partition[which(Partition!=-1)] Partition=Partition+1 Notes = c(Notes, Partition) } Notes; } # fin de la fonction getNotes

SQLQuery <- function(sql){ # Executer une requete SQL sur un serveur en lign # Parametres : # * sql (String) # Note: pour ne pas d efinir un parametre, utiliser "*" # # Valeurs retour : # * variable dataframe de donn ees sql = gsub("\\s","%20", sql) link = paste("http://ter.isgeek.eu/bddacces.php?sql=", sql, sep = "") linkContent = getURLContent(link) h = basicJSONHandler() x = fromJSON(linkContent, h) #print(linkContent) data.frame(x) ## Pour d ebuger en cas derreur #linkContent } generationPartition = function(x0, P, n){ # Une fonction pour g en erer une paritition # Parametres : # * x0 (Int) # * P (Matrix) de Markov # * n (Int) le nombre de note ` a g en erer # # Valeurs retour : # * X un vecteur qui contient les notes X = rep(NA, n) Hasard = runif(n) X[1]=x0 for(i in 2:n){ s=P[X[i-1], 1]; j=2 while(Hasard[i]>s){ s=s+P[X[i-1], j] j=j+1 } 34

X[i]=j-1 } return(X) }# fin de la fonction generationPartition chi2m = function(A,B){ # Une fonction pour g en erer une paritition # Parametres : # * A une matrice de probabilit e (Matrix) # * B une matrice dobservation (Matrix) res = rep(0,12); degLib = rep(0,12); ChiFractile = rep(0,12);

for (i in (1:12)){ stat=0; newA = A[i,][(A[i,]!=0)] newB = B[i,][(A[i,]!=0)] Ni = sum(newB) if(Ni!=0){ stat = sum((newB-Ni*newA)^2/(Ni*newA)) degLib[i]=length(newA) ChiFractile[i] = qchisq(.05, df=degLib[i]) res[i] = stat; } } list(stattot = sum(res), statArray = res, frac = ChiFractile, k = degLib, ktot=sum(degLi }

# D emonstration # Bibliotheques n ec essaire au bon fonctionnement library("cluster") install.packages("ade4"); library(ade4); # r ecup eration des parittions dans la base de donn ees Bach = getMarkov(Bach, *, *, *); Chopin = getMarkov(Chopin, *, *, *); Handel = getMarkov(Handel, *, *, *); Haydn = getMarkov(Haydn, *, *, *); Mozart = getMarkov(Mozart, *, *, *); Schumann = getMarkov(Schumann, *, *, *); Myst = getMarkov(*, *, *, 44);

# Automatisons. 35

# Test avec le Chi2 # ----------------dequiestce = function(id){ atester = getMarkov(*, *, *, id) B = chi2m(Bach$M,atester$M); HA = chi2m(Handel$M,atester$M); H = chi2m(Haydn$M,atester$M); C = chi2m(Chopin$M,atester$M); M = chi2m(Mozart$M,atester$M); S = chi2m(Schumann$M,atester$M); l = c(B$stattot,HA$stattot,H$stattot,C$stattot,M$stattot,S$stattot) a = which(l==min(l)) auteurs = c(Bach,Handel,Haydn,Chopin,Mozart,Schumann); auteurs[a] } dequiestce(2) #OK # On r ecup` ere lensemble des ids sql = "SELECT id FROM partitions ORDER BY id"; v = SQLQuery(sql); w = rep(NA,length(v)); for (i in (1:(length(v)))){ w[i] = as.integer(as.vector(v[,i])) } # On r ecup` ere le vecteur des noms des auteurs nom = SQLQuery("SELECT auteur FROM partitions ORDER BY id"); z = rep(NA,length(v)); for(i in (1:(length(v)))){ z[i] = as.character(as.vector(nom[,i])) } res = rep(NA,length(v)); # On teste lensemble de la base de donn ees k = 1; for (i in w){ res[k] = (dequiestce(i) == z[k]) k = k + 1; } l = which(res == TRUE) z[l] # Test avec la norme # -----------------dequiestce2 = function(id){ 36

atester = getMarkov(*, *, *, id) B = norm(Bach$M-atester$M) C = norm(Chopin$M-atester$M) HA = norm(Handel$M-atester$M) H = norm(Haydn$M-atester$M) M = norm(Mozart$M-atester$M) S = norm(Schumann$M-atester$M) l = c(B,C,HA,H,M,S); a = which(l==min(l)); auteurs = c(Bach,Handel,Haydn,Chopin,Mozart,Schumann); auteurs[a] } dequiestce2(2) #Ok res2 = rep(NA,length(v)); k = 1; for (i in w){ res2[k] = (dequiestce2(i)==z[k]) k = k + 1; } l = which(res2==TRUE) length(which(res2==TRUE)) z[l] # Test avec la fonction distance # -----------------------------dist_mat = function(A,B){ C = A - B; C = C*C; res = sqrt(sum(C)) res; } # Avec la meme formule que le cluster.

dequiestce3 = function(id){ atester = getMarkov(*, *, *, id) B = dist_mat(Bach$M,atester$M) C = dist_mat(Chopin$M,atester$M) HA = dist_mat(Handel$M,atester$M) H = dist_mat(Haydn$M,atester$M) M = dist_mat(Mozart$M,atester$M) S = dist_mat(Schumann$M,atester$M) l = c(B,C,HA,H,M,S); a = which(l==min(l)); auteurs = c(Bach,Handel,Haydn,Chopin,Mozart,Schumann); auteurs[a] 37

} dequiestce3(1) res3 = rep(NA,length(v)); k=1; for (i in w){ res3[k] = (dequiestce3(i)==z[k]) k = k+1; } l = which(res3==TRUE) length(which(res3==TRUE)) z[l]

############################################## # Classification de toute les parititons # # pr esentes dans la base de don ees # ##############################################

# r ecuperer tous les "id" sql = "SELECT id FROM partitions ORDER BY id" v = SQLQuery(sql) n_bdd = length(v) G = array(NA, c(12,12,n_bdd)) w = rep(NA,length(v)) for (i in (1:length(v))){ w[i]=as.integer(as.vector(v[,i])) } # remplissage dun tableau de matrice i = 1; k = 1; for (i in w){ temp = getMarkov(*, *, *, i); G[,,k] = temp$M; k = k+1 } ##On fait la matrice des distances MD = matrix(0,n_bdd,n_bdd); for (i in (1:n_bdd)){ for (j in (1:n_bdd)){ MD[i,j] = dist_mat(G[,,i],G[,,j]) } } # Ward Hierarchical Clustering 38

d = as.dist(MD) fit = hclust(d, method="ward") plot(fit) # display dendogram groups = cutree(fit, k=5) # cut tree into 5 clusters rect.hclust(fit, k=5, border="red")

nom = SQLQuery("SELECT auteur FROM partitions ORDER BY id"); z = rep(NA,length(v)); for (i in (1:(length(v)))){ z[i]=as.character(as.vector(nom[,i])) } fit$labels = z[fit$order] plot(fit)

type = SQLQuery("SELECT type FROM partitions ORDER BY id"); z = rep(NA,length(v)); for (i in (1:(length(v)))){ z[i] = as.character(as.vector(type[,i])) } fit$labels=z[fit$order] plot(fit)

style = SQLQuery("SELECT style FROM partitions ORDER BY id"); z = rep(NA,length(v)); for (i in (1:(length(v)))){ z[i]=as.character(as.vector(style[,i])) } fit$labels=z[fit$order] plot(fit)

############################################## # G en eration dune partition de musique # # ` a partir de la matrice Markovienne de Bach # ############################################## T = getMarkov(Bach, *, *, *); P=T$M X = generationPartition (1, P, 50) Notes = c(c,c#, d, d#, e, f, f#, g, g#, a, a#, b); midiToNotes = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); Notes[X]

39