catene di markov: un`applicazione alla composizione musicale

CATENE DI MARKOV: UN'APPLICAZIONE
ALLA COMPOSIZIONE MUSICALE
PROGETTO DI METODI MATEMATICI E STATISTICI DI
MARIO ALVISE DI BERNARDO
ANNO ACCADEMICO 2012/2013
•
•
•
•
•
•
•
•
1.Introduzione
2.Cenni sulla composizione algoritmica
◦ 2.1.Il “gioco di dadi musicale” di Mozart
3.Cenni sulle catene di Markov
◦ 3.1.Alcune applicazioni
4.Analisi della catena utilizzata
◦ 4.1.Probabilità di transizione ad un passo: matrice di transizione
◦ 4.2.Grafo associato
◦ 4.3.Calcolo di leggi congiunte
◦ 4.4.Classificazione degli stati
◦ 4.5.Probabilità invarianti
◦ 4.6.Stato stazionario
5.Implementazione
◦ 5.1.Descrizione dell'algoritmo utilizzato
6.Analisi dei risultati
◦ 6.1.Analisi della forma d'onda
7.Allegati
8.Webgrafia
1.INTRODUZIONE
Nella seguente trattazione, vedremo in che modo la statistica può trovare applicazione in
ambito di composizione musicale.
In particolare, verranno prima introdotti separatamente i concetti di composizione
algoritmica musicale e catena di Markov, osservando successivamente, con un
esempio pratico, in che modo sia possibile implementare un algoritmo che permetta di
comporre musica tramite processo markoviano.
Nel trattare la composizione algoritmica, verrà approfondito maggiormente il carattere
aleatorio del comporre tramite casualità (vedremo un esempio storico di musica composta
con l'uso di dadi) a discapito del legame tra la composizione musicale e l'uso del
computer.
Saranno poi allegati due file audio ottenuti da due esecuzioni successive dello stesso
algoritmo e ne saranno evidenziate le differenze date dal carattere aleatorio
dell'implementazione stessa.
2.CENNI SULLA COMPOSIZIONE ALGORITMICA
Si definisce come algoritmico un processo musicale che si svolge, prevalentemente
mediante elaboratore digitale, in base ad un ben determinato schema utilizzato per la
generazione delle strutture musicali. L'oggetto del comporre, in questo caso, non sono gli
eventi sonori quali altezze, durate e timbro, ma il processo stesso di composizione.
Gli algoritmi (intesi come insiemi di regole formali) sono stati utilizzati per secoli per
comporre musica: le procedure utilizzate per intrecciare le voci nel contrappunto
occidentale, ad esempio, possono spesso essere ridotte a determinatezza algoritmica.
Il termine, tuttavia, solitamente indica l'uso di procedure formali per fare musica senza
l'intervento umano, sia attraverso l'introduzione di procedure casuali sia attraverso l'uso
del computer.
Alcuni algoritmi che non hanno alcuna rilevanza musicale immediata vengono utilizzati dai
compositori come ispirazione creativa per la loro musica. Algoritmi come frattali, sistemi
Lindenmayer, modelli statistici e anche dati arbitrari (ad esempio dati del censimento,
coordinate GIS, o le misurazioni del campo magnetico) sono stati utilizzati come materiali
di partenza.
2.1.Il “gioco di dadi musicale” di Mozart
I primi esempi di composizione algoritmica si possono ravvisare nel XVIII secolo, quando
compositori come Bach, Haydn e Haendel iniziarono, per divertimento, a comporre musica
utilizzando i dadi.
Nel 1793 questa tecnica inizia ad avere larga diffusione grazie alla pubblicazione a Berlino
e ad Amsterdam di un "Musikalisches Würfelspiel" ("Gioco di dadi musicale") utilizzabile
per comporre minuetti "senza la minima conoscenza della musica, tirando due dadi".
Il gioco, il cui autore era Wolfgang Amadeus Mozart, ebbe subito un grandissimo
successo: in pochi anni moltissime case editrici europee lo ristamparono, e vennero
pubblicate versioni economiche e di lusso.
Il "Musikalisches Würfelspiel" permetteva di comporre, in modo automatico, un minuetto
strutturato secondo la forma tripartita usata in quell'epoca:
• una prima parte (il minuetto vero e proprio);
• una parte centrale, detta "trio" perché originariamente era assegnata a tre strumenti
solisti;
• una terza parte, che riproponeva il minuetto iniziale.
I minuetti e i trii dell'epoca erano costituiti tipicamente da 16 battute, e la loro struttura
poteva basarsi su schemi abbastanza standard. Fu proprio questa semplicità strutturale a
dar modo a Mozart di poter concepire l'idea di una composizione automatica.
Per comporre il minuetto, il gioco prevedeva l'utilizzo di una tabella con 11 righe e 16
colonne. In ognuna delle caselle risultanti era presente un numero da 1 a 176, che
rimandava ad un libretto nel quale erano trascritte 176 battute composte da Mozart.
Le 16 colonne della tabella corrispondevano alle 16 battute del minuetto. Lanciando, per
ciascuna delle 16 battute, due dadi e sottraendo 1 dal punteggio totale si otteneva un
numero da 1 a 11. Consultando il libretto con il numero presente all'intersezione tra la
colonna del numero di battuta e la riga determinata dal lancio dei dadi, si trovava la battuta
mozartiana da utilizzare.
Seguendo questo procedimento il "giocatore" si ritrovava con un minuetto di 16 battute.
Per quanto riguarda il trio da usare come parte centrale, il procedimento era del tutto
analogo, ma in questo caso la tabella da utilizzare aveva soltanto 6 righe, per cui era
sufficiente un solo dado.
È importante sottolineare che nel lancio di due dadi le 11 combinazioni possibili non hanno
tutte la stessa probabilità: ad esempio il punteggio 7 è il più probabile, poiché si può
ottenere con 6 diverse combinazioni, mentre il 2 o il 12 si ottengono con una sola
combinazione. Alcuni minuetti, quindi, sono più probabili di altri ma non sappiamo se
Mozart abbia tenuto conto di questo, ad esempio facendo corrispondere le battute migliori
ai lanci di dadi più probabili.
Ciò che è certo, è che la bravura di Mozart fu quella di scrivere battute che potessero
adattarsi bene l'una con l'altra, cosa tutt'altro che banale, specie analizzando i possibili
risultati ottenibili. Infatti, per ognuna delle 16 battute del tema principale ci sono 11 battute
possibili: quindi le combinazioni sono 1116. Analogamente, il gioco consente la
composizione di 616 trii. Poiché il minuetto, come forma musicale tripartita, è dato dalla
combinazione di un minuetto e di un trio, abbiamo in tutto 1116 x 616 =
129.629.238.163.050.258.624.287.932.416 diverse composizioni possibili, cioè circa 129
miliardi di miliardi di miliardi!
È
possibile
giocare
al
"Musikalisches
http://sunsite.univie.ac.at/Mozart/dice.
Würfelspiel"
andando
all'indirizzo
3.CENNI SULLE CATENE DI MARKOV
Un processo di Markov è un processo stocastico nel quale la probabilità di transizione che
determina il passaggio ad uno stato di sistema dipende unicamente dallo stato di sistema
immediatamente precedente (proprietà di Markov) e non dal come si è giunti a tale stato
(in quest'ultima ipotesi si parla di processo non markoviano).
Tale processo prende il nome dal matematico russo Andrej Andreevi č Markov che per
primo ne sviluppò la teoria.
In riferimento a un processo stocastico con spazio degli stati e tempo discreti, possiamo
dare la seguente definizione formale:
P( Xn+1 = j | X0, X1, …, Xn ) = P( Xn+1 = j | Xn )
ovvero: se il istema si trova nello stato n, il suo stato al tempo n+1 non dipende dagli stati
ai tempi 0, 1, …, n-1, ma solo dallo stato al tempo n.
3.1.Alcune applicazioni
Il motore di ricerca Google assegna un valore all'importanza di un sito web tramite
l'algoritmo PageRank: quest'ultimo si basa sull'assegnare una probabilità di transizione da
un sito web A a un sito B basata sulla quantità di link che da A conducono a B.
Conoscendo la probabilità di transizione è possibile ottenere la distribuzione stazionaria di
probabilità della catena di Markov formata da tutti i siti web. La distribuzione stazionaria
assegna un valore nell'intervallo [0,1] ad ogni sito (corrispondente alla quantità media di
tempo spesa sul sito da un gran numero di utenti dopo un tempo tendente a infinito): tale
valore, opportunamente riscalato, costituisce il Page Rank del sito. Gran parte della
modellistica di serie temporali in finanza si basa su processi stocastici generati da catene
di Markov.
Modelli di tipo markoviano vengono anche utilizzati nel progetto di reti di
telecomunicazioni; la teoria delle code che ne consegue trova applicazione in molti ambiti:
dalla fila alle poste ai pacchetti in coda in un router.
Le catene di Markov trovano applicazione anche nella composizione algoritmica musicale,
in particolare in linguaggi e ambienti di sviluppo come CSound, Max o SuperCollider. Tale
argomento, verrà approfondito nei prossimi paragrafi.
4.ANALISI DELLA CATENA UTILIZZATA
Data una catena di primo ordine, gli stati del sistema diventano note, e per ciascuno viene
costruito un vettore di probabilità, componendo una matrice di probabilità di transizione.
L'algoritmo produce e manda in output i valori delle note basandosi sui pesi della matrice
di transizione. Tali valori saranno, nell'esempio trattato, frequenza (in Hertz) e valore della
nota.
Note
LA
DO
MI
LA DO MI
0.4 0.3 0.3
0.6 0.25 0.15
0.1 0 0.9
Un esempio con una matrice di prim'ordine.
Pur se non argomento di questa trattazione, è interessante considerare l'utilizzo di catene
di Markov di ordine superiore al primo, che tengono conto sia dello stato attuale che di
quelli precedenti, permettendo così di raggruppare assieme sequenze particolari di note
che saranno occasionalmente interrotte da altri pattern.
Catene di ordine superiore al primo permettono così di generare risultati con una certa
struttura nei fraseggi, a differenza del “vagare senza meta” prodotto da un sistema di
primo ordine.
Note
LA RE
LA LA
0.5 0.5
LA RE
0.3 0.5
LA SOL
1
0
RE RE
0.5 0.25
RE LA 0.75
0
RE SOL 0.9 0.1
SOL SOL 0.4 0.4
SOL LA
0
1
SOL RE 0.15 0.75
SOL
0
0.2
0
0.25
0.25
0
0.2
0
0.1
Un esempio con una matrice di secondo ordine.
4.1.Probabilità di transizione ad un passo: matrice di transizione
La seguente matrice Q descriverà l'evoluzione del sistema: ogni elemento qi,j ci dirà infatti
con quale probabilità il sistema passerà dallo stato i al tempo n, allo stato j al tempo n+1.
0
0
0
0
0
Q=
0
0
0
0
1/3
1
0
0
0
0
0
0
0
0
0
0
1
0
0
¼
0
0
0
0
0
0
0
½
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
¾
1/3
0
½
0
1/3
0
0
0
0
0
2/3
½
0
0
0
0
0
½
0
0
0
½
0
0
0
0
0
0
0
0
0
0
½
0
0
0
0
0
0
0
0
0
0
1
1/3
Ogni riga rappresenta il comportamento dell'i-esimo stato, per questo la somma degli
elementi di una riga è sempre 1.
4.2.Grafo associato
Una rappresentazione alternativa per le catene di Markov prevede l'utilizzo di un grafo
orientato pesato, i cui vertici rappresentano gli stati e i pesi degli archi le probabilità di
transizione. Per ogni stato è indicata la nota, il valore della frequenza in hertz e la durata
relativa, che andrà poi divisa per i bps (beats per second) per ottenere la durata effettiva.
4.3.Calcolo di leggi congiunte
Sia E = {X0, X1, X2, X3, X4, X5, X6, X7, X8, X9} l'insieme degli stati della catena di Markov.
Esso ha cardinalità n = 10. Vogliamo individuare la legge w per X n.
Data v legge di X0, calcoliamo:
w = vQn
Eseguendo il calcolo con Matlab, otteniamo:
w = [ 0.0432 0.0415 0.0398 0.0046 0.0139 0.2271 0.2695 0.1392 0.0794 0.1418 ]
4.4.Classificazione degli stati
Sia E = {X0, X1, X2, X3, X4, X5, X6, X7, X8, X9} l'insieme degli stati della catena di Markov
precedentemente definita e sia C un sottonsieme di stati tale che C ⊂ E.
Non sono presenti sottoinsiemi di stati che siano chiusi, pertanto E è l'unica classe
irriducibile, ovvero per ogni i, j ∈ E, con i ≠ j, esisterà sempre n > 0 tale che qi,j(n) > 0.
Questo significa che, presi due stati qualunque, esisterà un percorso che andrà dallo stato
i allo stato j in n passi.
Essendo E la sola classe irriducibile, e avendo essa cardinalità maggiore di 1, non sono
presenti stati assorbenti, ossia stati che costituiscono da soli una classe irriducibile.
Uno stato i si dice ricorrente se il sistema, essendo stato una volta in i, tornerà in i con
probabilità 1, ovvero pi, i = 1. In caso contrario lo stato si dirà transitorio e pi, i < 1.
Gli stati 0, 1, 2, 7, 8 e 9 sono ricorrenti, mentre gli stati 3, 4, 5 e 6 sono transitori.
La catena è aperiodica. Infatti, dato k ≥ 1, non esiste nessuna m > 1 per cui un qualche
stato j soddisfi la seguente relazione:
P(Xn+s = j | Xn = j) = 0, con s ≠ mk.
Dalla matrice Q risulta evidente che:
• lo stato 0 comunica con lo stato 1;
• lo stato 1 comunica con lo stato 2;
• lo stato 2 comunica con gli stati 3 e 7;
• lo stato 3 comunica con lo stato 4;
• lo stato 4 comunica con gli stati 2 e 5;
• lo stato 5 comunica con gli stati 5 e 6;
• lo stato 6 comunica con gli stati 6 e 7;
• lo stato 7 comunica con gli stati 5 e 8;
• lo stato 8 comunica con lo stato 9;
• lo stato 9 comunica con gli stati 0, 5 e 9.
4.5.Probabilità invarianti
Nessuna delle probabilità su E è invariante o stazionaria.
Infatti è facile verificare che non esiste nessuna v probabilità su E tale che:
v = vQ
Poichè la matrice di transizione Q è regolare, ovvero esiste m intero positivo tale che:
qi, j(m) > 0, per ogni i, j ∈ E
la catena di Markov si dirà regolare. Ne segue che tutti gli stati comunicano tra loro e
quindi la catena è irriducibile e gli stati ricorrenti.
Ma non vale il viceversa.
4.6.Stato stazionario
Studiamo ora la catena di Markov per tempi molto grandi.
Quando l'istante di osservazione è molto lontano dal punto iniziale, la probabilità p j che la
catena si trovi nello stato j non dipende dallo stato iniziale, ovvero, per j = 0, 1, ...:
lim P( Xn=j | X0=i ) = lim qi, j(n) = pj
n→∞
n →∞
Le probabilità limite pj, se esistono, sono dette distribuzione di equilibrio o distribuzioni
dello stato stazionario di una catena di Markov, e la loro somma è 1.
Vediamo se esiste una distrubuzione di equilibrio per la nostra catena.
Per il teorema di Markov, data una catena di Markov avente stati finiti e pari a N e matrice
di transizione Q regolare, allora esiste un'unica probabilità invariante p = (p 1, p2, …, pN) di
Q tale che:
lim qi, j(n) = pj
n→∞
Poiché la nostra catena soddisfa le ipotesi, abbiamo la certezza dell'esistenza di p.
Troviamo p = (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9).
Calcoliamo le equazioni di bilancio.
Per j = 0 si ha:
p0 = p9 / 3
Per j = 1 si ha:
p1 = p0
Per j = 2 si ha:
p2 = p1 + p4 / 4
Per j = 3 si ha:
p3 = p2 / 2
Per j = 4 si ha:
p4 = p3
Per j = 5 si ha:
p5 (2 / 3) = p4 (3 / 4) + p7 / 2 + p9 / 3
Per j = 6 si ha:
p6 / 2 = p5 (2 / 3)
Per j = 7 si ha:
p7 = p2 / 2 + p6 / 2
Per j = 8 si ha:
p8 = p7 / 2
Per j = 9 si ha:
p9 (2 / 3) = p8
L'equazione di normalizzazione è:
p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 = 1
Mettendo a sistema equazioni di bilancio e equazione di normalizzazione si ha:
p0 = p1 =
2 / 43
p2 = p3 = p4 = 0
p5 =
9 / 43
p6 =
12 / 43
p7 =
8 / 43
p8 =
4 / 43
p9 =
6 / 43
Pertanto, la proprietà invariante per la nostra catena è:
p = ( 2 / 43, 2 / 43, 0, 0, 0, 9 / 43, 12 / 43, 8 / 43, 4 / 43, 6 / 43 )
Tali risultati possono essere osservati empiricamente con dei semplici test sul codice
allegato. Basterà infatti inserire un comando che stampi a video lo stato corrente a ogni
passo (chiameremo percorso questo insieme di valori) e calcolare la distribuzione di
frequenza con la funzione FREQUENZA di Excel, usando il percorso come dati e gli stati
possibili (ovvero gli elementi dell'insieme E) come classi.
Per n = 100 otteniamo:
Stato
0
1
2
3
4
5
6
7
8
9
Frequenza
5
5
5
2
2
23
22
18
8
10
Mentre per n = 1000 otteniamo:
Stato
0
1
2
3
4
5
6
7
8
9
Frequenza
36
37
41
17
17
209
297
167
74
105
Per valori molto grandi di n, dunque, la distribuzione di frequenza degli stati della catena
tenderà a stabilizzarsi seguendo la proprietà invariante p.
5.IMPLEMENTAZIONE
Per l'implementazione dell'algoritmo, è stato usato SuperCollider, un linguaggio di
programmazione per la sintesi audio in tempo reale con integrato un ambiente di sviluppo
diviso in due componenti: un server (scsynth) e un client (sclang). Questi componenti
comunicano tramite OSC (Open Sound Control).
5.1.Descrizione dell'algoritmo utilizzato
Iniziamo definendo il sintetizzatore, ossia lo strumento che suonerà il nostro spartito.
Apriamo un Task (questo ci permetterà di gestire il tempo tra l'avvio di una nota e la
successiva tramite la durata effettiva e il comando wait) e usiamo un array per definire la
nostra catena secondo lo schema: [freq, dur_rel, <lista_adiacenza>].
Nella lista di adiacenza indicheremo ogni stato direttamente collegato a quello corrente
con la relativa probabilità: [[stato_1, probabilità_1], [stato_2, probabilità_2], …]
Stabilito un bpm, calcoliamo quindi i bps per poi ottenere la durata effettiva delle note in
secondi. Questo ci permetterà di cambiare la velocità a nostro piacimento modificando
solo il valore bpm.
Inizializziamo il nodo corrente a 0. In questo modo lo stato 0, rappresentato dalla prima
riga della matrice, sarà lo stato iniziale. Apriamo un ciclo do impostando il contatore a 99,
così da avere un totale di n = 100 passi.
A ogni passo, useremo il sintetizzatore per eseguire la nota (o la pausa) dello stato
corrente.
Lo stato successivo viene scelto secondo la seguente procedura:
• viene calcolata la somma dei pesi presenti nella lista di adiacenza dello stato
corrente;
• viene estratto un numero casuale compreso tra 0 e il peso totale;
• se il numero estratto è minore o uguale al primo peso, viene scelto il primo nodo
della lista. Altrimenti, si confronta il numero estratto con il secondo peso più il primo:
se è minore o uguale si sceglie il secondo nodo della lista. In caso contrario si
passa al confronto tra il numero casuale e la somma dei primi tre pesi, e così via.
Lo spartito sarà quindi il percorso definito dal cambiamento degli stati della catena di
Markov.
6.ANALISI DEI RISULTATI
Analizzeremo ora due tracce audio ottenute da due esecuzioni del codice mostrando
come, se pur generate dallo stesso algoritmo, le due tracce presentino notevoli differenze.
Sebbene tali differenze siano già evidenti all'ascolto, saranno mostrati dei grafici ottenuti
col software Audacity.
6.1.Analisi della forma d'onda
La forma d'onda è il profilo generato su un piano cartesiano dalla misurazione di un
segnale rispetto a due grandezze, che nel nostro caso sono il tempo t e il potenziale
elettrico V del segnale, normalizzato tra -1 e 1.
Seguono le forme d'onda osservate nei due canali (stereo) di ciascuna traccia.
Traccia 1.
Traccia 2.
Osservando le creste e gli avvallamenti, è possibile notare come le due tracce siano
composte dagli stessi eventi sonori, ma disposti in maniera diversa.
Ad esempio, le forme d'onda dei suoni eseguiti tra l'istante 0 e l'istante 1 sono le stesse
per entrambe le tracce. In effetti, come si evince dal grafico e dalla matrice di transizione,
la nostra catena forza i passaggi tra gli stati 0 e 1, e tra 1 e 2. Agli istanti successivi le
tracce iniziano a diversificarsi.
Nel file “sc_markov canali separati.mp3” le due tracce vengono eseguite
contemporaneamente su diversi canali stereo, ossia ascoltando il file audio su un sistema
stereo, la prima traccia sarà udibile sulla cassa destra, mentre la seconda sulla cassa
sinistra. Come precedentemente osservato nei grafici, le tracce saranno identiche nel
primo istante di riproduzione, dopodichè inizieranno a differenziarsi.
7.ALLEGATI
•
•
•
•
sc_markov 1.mp3: prima traccia audio generata.
sc_markov 2.mp3: seconda traccia audio generata.
sc_markov canali separati.mp3: mix delle due tracce. È stato attribuito un canale
diverso a ogni traccia così da evidenziarne le differenze.
Catena di Markov.scd: file SuperCollider.
8.WEBGRAFIA
•
•
http://en.wikipedia.org/wiki/Algorithmic_composition
http://web.tiscalinet.it/gruppo_a/fog_txt.html