You are on page 1of 70

UNIVERSIT DEGLI STUDI DI TORINO

Corso di laurea in Informatica


Anno accademico 2004/2005

ANALISI E IMPLEMENTAZIONE DI UN SISTEMA FORMALE PER LA


COMPOSIZIONE MUSICALE

Relatore

Candidato

Prof. Vincenzo Lombardo

Stefano Dobrilla
Matricola n. 177725

INDICE
1INTRODUZIONE...................................................................................................................................................................1
1.1ORIGINI DELLA SINTESI GRANULARE.........................................................................................................................................1
1.2 LA COMPOSIZIONE BASATA SULLA SINTESI GRANULARE.............................................................................................................1
1.3POSSIBILI APPROCCI ALLA SINTESI GRANULARE..........................................................................................................................2
1.4GEOGRAPHY.........................................................................................................................................................................4
1.5SCOPO DELLA TESI.................................................................................................................................................................6
2ANALISI DI GEOGRAPHY................................................................................................................................................7
2.1IL LIVELLO-1........................................................................................................................................................................7
2.1.1Definizione 1: Evento...............................................................................................................................................7
2.1.2Definizione 2: Track.................................................................................................................................................8
2.1.3Definizione 3: Grain Generator..............................................................................................................................8
2.1.4Definizione 4: Vertice..............................................................................................................................................9
2.1.5Definizione 5: Arco..................................................................................................................................................9
2.1.6Definizione 6: Peso di un arco................................................................................................................................9
2.1.7Definizione 7: Graph Actant.................................................................................................................................10
2.1.8Esempio di Grain Generator.................................................................................................................................10
2.1.9Processo di generazione di track..........................................................................................................................10
2.1.10Conclusioni...........................................................................................................................................................12
2.2IL LIVELLO-2......................................................................................................................................................................12
2.2.1Definizione 8: Control Space................................................................................................................................12
2.2.2Definizione 10: Traiettoria....................................................................................................................................12
2.2.3Definizione 11: Space Actant................................................................................................................................12
2.2.4Definizione 12: Angolo di orientamento di sa.....................................................................................................13
2.2.5Esempi di control space.........................................................................................................................................14
2.3LA GENERAZIONE DELLO SCORE............................................................................................................................................15
2.3.1Definizione 13: Grano...........................................................................................................................................16
2.3.2Definizione 14: Score.............................................................................................................................................17
2.3.3Esecuzione del control space................................................................................................................................17
2.3.4Esempio di score....................................................................................................................................................19
2.3.5Conclusioni.............................................................................................................................................................20
2.4CONCLUSIONI GENERALI.......................................................................................................................................................20
3OBJECT ORIENTED ANALYSIS (OBJECT MODELING)......................................................................................21
3.1LIVELLO-1..........................................................................................................................................................................21
3.1.1Oggetti.....................................................................................................................................................................21
3.1.2Strutture..................................................................................................................................................................21
3.1.3Attributi...................................................................................................................................................................21
3.1.4Associazioni............................................................................................................................................................22
3.1.5Servizi......................................................................................................................................................................22
3.2LIVELLO-2..........................................................................................................................................................................22
3.2.1Oggetti.....................................................................................................................................................................22
3.2.2Strutture..................................................................................................................................................................23
3.2.3Attributi...................................................................................................................................................................23
3.2.4Associazioni............................................................................................................................................................24
3.2.5Servizi......................................................................................................................................................................24
4REQUIREMENTS SPECIFICATION DOCUMENT...................................................................................................27
4.1 INTRODUCTION...................................................................................................................................................................27
4.1.1Purpose...................................................................................................................................................................27
4.1.2Definitions, Acronyms, Abbreviations..................................................................................................................27
4.1.3Notational Conventions.........................................................................................................................................27
4.2OVERALL DESCRIPTION........................................................................................................................................................27
4.2.1Product Perspective...............................................................................................................................................27
4.2.2Product Functions Overview.................................................................................................................................28
4.3SPECIFIC REQUIREMENTS......................................................................................................................................................28
4.3.1Inputs and Outputs.................................................................................................................................................28
4.3.2Functional Requirements.......................................................................................................................................37

4.3.3External Interface Requirements..........................................................................................................................37


4.3.4Design Contraints..................................................................................................................................................37
5OBJECT ORIENTED DESIGN.........................................................................................................................................38
5.1OBJECT MODELING..............................................................................................................................................................38
5.2DYNAMIC MODELING..........................................................................................................................................................38
5.3FUNCTIONAL MODELING......................................................................................................................................................38
5.4IMPLEMENTATION CONCERNS................................................................................................................................................40
5.5DETAILED DESIGN...............................................................................................................................................................40
5.5.1GAct.........................................................................................................................................................................41
5.5.2Shifting Vector........................................................................................................................................................41
5.5.3Trajectory................................................................................................................................................................46
5.5.4Vertex......................................................................................................................................................................49
5.6CONCLUSIONI......................................................................................................................................................................49
6CONCLUSIONI....................................................................................................................................................................50
7BIBLIOGRAFIA..................................................................................................................................................................51
8APPENDICE..........................................................................................................................................................................53

1Introduzione
1.1 Origini della sintesi granulare
noto che la luce caratterizzata da una natura duale, cio pu essere descritta in termini di
propriet ondulatorie o in termini di propriet particellari: nel primo caso, la luce vista come
unonda, nel secondo caso, viene vista come un insieme di particelle (fotoni).
Oggi sappiamo che il suono non caratterizzato da una tale natura duale (il suono unonda); in
passato, per, sono state avanzate visioni atomistiche del suono come particelle sonore: lo studioso
olandese I. Beekman (1588-1637) nel 1616 propose una teoria corpuscolare del suono (vedi [3], e
[7]), secondo la quale qualunque oggetto in grado di vibrare e di emettere un suono (ad esempio
una corda) taglierebbe laria circostante in corpuscoli sferici di aria proiettati in tutte le direzioni;
sempre secondo Beekman, quando questi corpuscoli urtano contro il timpano, si percepisce il
suono.
Sebbene questa teoria delle particelle sonore non abbia attualmente valenza scientifica, essa
importante perch pone le basi per la definizione e la comprensione della sintesi granulare.
La nozione di un approccio granulare (o quantistico) al suono compare per la prima volta nel
1946-47 in due articoli del fisico britannico D. Gabor (vedi [10], [11]), nei quali viene avanzata una
nuova teoria, ispirata dalla fisica quantistica, secondo la quale qualunque suono pu essere descritto
da una rappresentazione granulare, ovvero da unappropriata sequenza di unit di informazione
acustica di durata quasi istantanea. Questa ipotesi fu verificata matematicamente da M. Bastiaans
negli anni Ottanta (vedi [1], [2]).
Negli anni Sessanta, anche linventore della cibernetica N. Wiener [31], e il teorico
dellinformazione A. Moles [19] hanno avanzato non solo rappresentazioni granulari del suono, ma
anche ipotesi sulla natura discreta della percezione e del campo sonoro.
Ad unorigine teorica della sintesi granulare, si affianca unorigine estetica: nel 1960, I. Xenakis fu
il primo a definire una teoria per la composizione basata sui grani, che nasceva dal seguente lemma:
Qualunque suono, anche una variazione musicale continua, concepito come un assemblaggio di
un gran numero di suoni elementari adeguatamente disposti nel tempo. Nellattacco, sostegno e
decadimento di un suono complesso, appaiono migliaia di suoni puri in un pi o meno breve
intervallo di tempo t [32]. Nonostante Xenakis fosse riuscito a riprodurre suoni granulari per
mezzo di generatori di tono analogici (si ascolti la composizione Analogique A-B per orchestra
darchi e nastro magnetico), la sua visione non pot attuarsi per la mancanza della tecnologia
necessaria.
Solo pi tardi, nel 1974, il ricercatore e compositore C. Roads sviluppa la prima implementazione
per calcolatore della sintesi granulare [21], in cui il metodo di lavoro composizionale pu essere
paragonato alla tecnica pittorica pointilliste, dove ai puntini di colore corrispondono i grani (di
suono).Roads usa questa implementazione in molte sue composizioni, tra le quali citiamo nscore
(1980), Field (1981), e Clang-tint (1993). In seguito, sono state proposte diverse
implementazioni della sintesi granulare: oltre a Roads, importante citare il compositore canadese
B. Truax, per il contributo dato per la definizione di tecniche alternative per il controllo della sintesi
granulare. Le tecniche proposte da Xenakis, Roads e Truax saranno descritte nel paragrafo 1.3.

1.2

La composizione basata sulla sintesi granulare

La sintesi del suono un processo di generazione di flussi di campioni in modo algoritmico.


La sintesi granulare un termine generale che include vari tipi di tecniche di sintesi basate su una
rappresentazione granulare del suono. In generale, gli eventi sonori sono costruiti partendo da
1

elementi sonori elementari, i grani, di durata molto breve (tipicamente dai 5 ai 150 millisecondi).
Le ristrette dimensioni di un grano lo rendono appena percepibile allorecchio umano: diventa
difficile catturare e distinguere le caratteristiche di durata, frequenza, ampiezza e forma donda di
un grano.
Per comprendere in che cosa consiste una composizione musicale basata sulla sintesi granulare,
utile ricorrere ad una metafora, immaginando una tela pointilliste, dove ciascun puntino di colore
rappresenta un singolo grano della composizione. Quando la fruizione di un quadro siffatto avviene
ad una opportuna distanza, losservatore percepisce la composizione nel suo insieme, dimenticando
la struttura puntiforme; analogamente, nella composizione musicale basata sulla sintesi granulare,
quando i grani si susseguono a breve distanza temporale, lascoltatore percepisce un suono
continuo.
Daltro canto, in entrambi i casi, sia in campo pittorico, sia in campo musicale, il risultato finale
risente della particolare tecnica usata: un quadro puntinista mantiene pur sempre un certo effetto di
rarefazione dellimmagine, mentre una composizione musicale basata sulla sintesi granulare, in
generale d origine a materiali sonori molto densi e pulviscolari (si pensi ad un rullo di tamburo).
Continuando la metafora, chiaro che il pittore puntinista, oltre a concentrarsi sul singolo puntino
di colore, deve soprattutto concentrarsi sulla composizione nel suo insieme.
Nellambito della sintesi granulare, questa difficolt del muoversi dal livello del singolo grano (la
microstruttura della composizione), al livello composizionale (la macrostruttura della
composizione), possibilmente passando attraverso il livello delle note (la ministruttura della
composizione) e il livello del ritmo (la mesostruttura della composizione), una delle principali
difficolt che incontra il compositore [32].
Infatti, la complessit del suono generato dalla sintesi granulare deriva dalla quantit di dati
necessari per descrivere i singoli grani di cui il suono stesso composto: se n il numero di
parametri per ciascun grano, e d il numero medio di grani al secondo (densit media), occorrono
dn valori di parametro per specificare un secondo di musica [23]. Dal momento che d tipicamente
varia dallordine della decina allordine della migliaia, chiaro che per lo scopo di controllo sulla
macrostruttura della composizione, diventa necessaria ununit di alto livello per lorganizzazione
dei grani (cio, ununit di controllo che va oltre i dettagli microstrutturali dalla composizione), con
lo scopo di aiutare il compositore a comporre in modo intuitivo e relativamente immediato grandi
quantit di grani, e ad avere una visione dinsieme del prodotto compositivo.
Ciascuna di tali unit di controllo implementa quindi una particolare tecnica/metodo di
organizzazione del processo compositivo basato sulla sintesi granulare. Nel prossimo paragrafo
descriveremo brevente le principali tecniche proposte.

1.3 Possibili approcci alla sintesi granulare


Negli ultimi trentanni (dalle prime esperienze di I. Xenakis in poi) sono state sviluppate diverse
tecniche, ciascuna delle quali porta a risultati composizionali e timbrici completamente diversi
rispetto alle altre. In generale, si distinguono due principali approcci: un cosiddetto approccio
notale ( note approach) ed un approccio stocastico (stochastic approach) [30].
Il primo di tali approcci orientato alle note, ovvero il suo principio che la microstruttura (il
livello dei grani) incorporata nella ministruttura (il livello delle note) della composizione: in
questo modo la granularit (la microstruttura) va a incidere soltanto sul timbro di ogni nota (o
meglio, sul timbro di ogni oggetto sonoro a livello ministrutturale), mentre non ha alcuna rilevanza
a livello composizionale (macrostrutturale). Questo fa s che permanga la separazione logica,
propria della composizione tradizionale, tra suono (o meglio, timbro) e struttura [29] (si pensi alla
musica tonale, cio alla teoria su cui si basa tutta la produzione musicale occidentale che va dalla
seconda met del Seicento alla seconda met dellOttocento e oltre). Lapproccio notale trova
2

quindi spazio in tutte quelle applicazioni che si limitano a granularizzare oggetti sonori
preesistenti, come i moduli grain-based di applicazioni DSP [23].
Contrariamente allapproccio notale, lapproccio stocastico alla sintesi granulare fa s che nel
processo di sintesi sia gi insita una propria valenza formale a livello compositivo: il principio di
tale approccio sta nellunire suono e struttura ([29]: 120), annullando la netta linea di confine tra
microstruttura e macrostruttura. Diverse sono le metodologie stocastiche per il controllo della
sintesi granulare proposte da autori come Xenakis, Truax e Roads; al fine di dare una visione
dinsieme di tali metodologie, utile per comprendere pi a fondo il caso di studio di questa tesi,
introduciamo in modo intuitivo le tecniche proposte da tali autori.
La tecnica di Xenakis, descritta in [32], si basa sul concetto di screen: uno screen una griglia che
modella il campo delludibile in modo simile al diagramma di Fletcher-Munson (vedi la Figura 1).
In uno screen ogni colonna rappresenta un intervallo di frequenza, e ogni riga indica unintensit
sonora: in questo caso, un grano risulta essere una singola cella dello screen. In uno screen vengono
quindi disseminati i grani. Una sequenza di screen (detta book), in cui ciascuno screen ha una
durata di tempo fissa, forma levoluzione di un suono complesso. In generale, per riempire gli
screen con i grani possono essere usati algoritmi generativi di ogni tipo; la tecnica di Xenakis
prevede che i grani siano sparsi in modo casuale allinterno di ciascuno screen, e che nuovi screen
possano essere costruiti attraverso operazioni simili alle operazioni insiemistiche (intersezione,
unione, complemento, ecc.).

Figura 1: il grafico a sinistra il diagramma di Fletcher-Munson, detto anche delle curve isofone, in cui le ascisse sono
le frequenze (in Hz), le ordinate sono le intensit (in dB). Considerando convenzionalmente con valore 0 dB la pressione
necessaria per raggiungere la soglia di udibilit per la frequenza di 1000 HZ, il diagramma esprime come lintensit
della sensazione uditiva (soggettiva) per le diverse frequenze vari in modo non lineare rispetto al variare della pressione
acustica (da [23]:1057). A destra mostrato come uno screen modella il campo delludibile allinterno del diagramma di
Fletcher-Munson: le celle nere di tale screen sono grani, ciascuno dei quali rientra in un certo intervallo di frequenza
(F) e di intensit (G) (da [32]).

La tecnica proposta da Truax (vedi [28] e [29]), rientra in ci che in letteratura viene definita QuasiSynchronous Granular Synthesis (QSGS, [22], [23], [24]), secondo la quale una composizione
formata da uno o pi flussi di grani, in cui i grani sono separati da un intervallo di tempo variabile,
irregolare. I parametri di ogni flusso di grani sono controllati mediante maschere di tendenza, che
specificano landamento qualitativo dei parametri nello scorrere del tempo: ad esempio, lintervallo
di frequenza o ampiezza in cui rientrano i grani del flusso, la densit dei grani nel flusso (numero di
grani nellunit di tempo), linsieme di forme donda dei grani nel flusso, ecc. La forza di questa
tecnica sta nel fatto che il controllo viene definito a livello dei flussi (non dei grani), rendendo il
processo compositivo semplice ed intuitivo: analogamente a quanto viene tradizionalmente fatto
3

sulle composizioni polifoniche, il compositore pu ragionare sia in termini contrappuntistici,


valutando lo svilupparsi simultaneo nel tempo dei flussi di grani (delle voci, come in polifonia),
sia in termini armonici, valutando quanto risulta dallemissione contemporanea dei flussi di grani.
La tecnica di Roads, detta Asynchronous Granular Synthesis (AGS, [22], [23], [24]), viene
introdotta da Roads stesso attraverso la seguente metafora: La AGS d al compositore un getto
spray di precisione per il suono, dove ogni punto nello spray un grano sonico. Secondo tale
metodologia, i grani vengono sparsi in modo probabilistico lungo una specifica durata di tempo
allinterno di regioni piane frequency-versus-time, dette cloud. Un cloud viene specificato dal
compositore dai seguenti sette parametri: istante di inizio e durata del cloud, durata di grano (che
pu essere costante, random, derivare da una curva, o variare in funzione della frequenza del
grano), densit dei grani nel cloud (numero di grani nellunit di tempo), le bande di frequenze
entro le quali sono comprese le frequenze dei grani, linviluppo dampiezza del cloud (non dei
grani), le forme donda dei grani, la dispersione spaziale dei grani nel cloud. Il cloud diventa ci
che per la musica tonale la nota: la nuova unit con cui il compositore lavora.
Avendo preso visione delle principali tecniche di composizione basate sulla sintesi granulare, nel
prossimo paragrafo introduciamo un nuovo metodo di organizzazione del processo compositivo
basato sulla sintesi granulare, che ha lo scopo di definire uno strumento di controllo di facile
utilizzo, e che non richiede una quantit di dati ingestibile.

1.4 GeoGraphy
GeoGraphy (o GeoGrafia) un sistema formale per il controllo algoritmico della composizione
elettroacustica basata sulla sintesi granulare. Esso stato definito da A. Valle e V. Lombardo in
[30].
GeoGraphy presenta due livelli: un primo livello (livello-1), che prevede una rappresentazione in
grafi nei quali i vertici rappresentano i grani e gli archi relazioni temporali tra gli stessi, ed un
secondo livello (livello-2) che distribuisce i grafi del primo livello in uno spazio di controllo.
Una composizione una traiettoria nello spazio di controllo, opportunamente interpretata per
controllare un insieme di parametri di rilevanza acustica e musicale.
Per dare una descrizione concettuale e immediata del sistema, utile ricorrere alla metafora dei
percussionisti: un grafo pu essere pensato come set di percussioni in cui ciascuna percussione
corrisponde ad un vertice del grafo stesso. Su ciascun set di percussioni (grafo) possono suonare
contemporaneamente pi percussionisti; lordine seguito dai batteristi nel suonare le percussioni
della batteria corrisponde ad un determinato percorso seguito attraverso gli archi del grafo.
Immaginiamo ora di porre un ascoltatore e diversi set di percussioni (grafi), e relativi percussionisti,
in una sala relativamente grande (spazio di controllo). Lascoltatore inizier a muoversi ad una certa
velocit, percorrendo una data traiettoria allinterno della sala mentre i percussionisti stanno
suonando. La composizione risultante pu essere pensata come quanto ascoltato dallattante nel
percorrere la traiettoria.
Questa strutturazione del sistema nei due livelli permette al compositore di concentrarsi, prima,
sulla microstruttura della composizione (sui singoli grani) e sulle relazioni tra i tempi di attacco di
gruppi di grani, definendo i grafi nel primo livello, e in un secondo tempo sulla macrostruttura della
stessa composizione, andando a distribuire i grafi e definendo una traiettoria nello spazio di
controllo.
Nel costruire i grafi, il compositore definisce quindi il materiale sonoro, anche complesso, che verr
utilizzato nella composizione. La disposizione dei grafi e la definizione di una traiettoria in uno
spazio sostanzialmente unoperazione di orchestrazione: il materiale sonoro di base generato dai
grafi viene filtrato, controllato e organizzato dal sistema sulla base della traiettoria definita e della
disposizione dei grafi nello spazio di controllo.
4

In Figura 2 data una rappresentazione grafica di una possibile configurazione:


Inizio

G1
G3

1
2
1

5
Fine

4
3

Ascoltatore

G2

G4

Figura 2: rappresentazione grafica di una possibile configurazione allinterno dello spazio di


controllo. In tale spazio sono stati disposti quattro grafi (G1, G2, G3, G4), i cui vertici sono stati
etichettati con numeri interi successivi. La traiettoria la sequenza di frecce che va dal punto Inizio
al punto Fine; essa viene percorsa dallascoltatore.

La struttura dei grafi in Figura 2 d immediatamente uninformazione sul tipo di materiale sonoro
generato dai grafi stessi: ad esempio, se consideriamo a livello-1 il primo grafo incontrato
dallattante nel percorrere la traiettoria (G1) siamo in grado di dire che esso generer un suono
ripetitivo, costituito da una sequenza di grani identici tra loro (si pensi ad un martello pneumatico, o
ad una erre tenuta), perch generati sempre e solo dallo stesso vertice 1. Se consideriamo invece
lo stesso grafo a livello-2, cio nel contesto della configurazione rappresentata in Figura 2, il suono
da esso generato non pi del tutto ripetitivo: infatti, sebbene il suono mantenga una base uniforme
e costante, la traiettoria produce un controllo diretto sui parametri dei grani costituenti il suono
stesso.
Se immaginiamo ad esempio che lintensit dei grani generati sia inversamente proporzionale alla
distanza tra il vertice e lascoltatore che percorre la traiettoria, allora risulta evidente che, a mano a
mano che lascoltatore prosegue nella navigazione della traiettoria, il suono va via via scemando,
dal momento che, in generale, lascoltatore si allontana dal vertice del grafo in questione.
Come da una configurazione possibile ricavare informazioni sia sul materiale sonoro di base
scelto (sulla microstruttura della composizione), sia sullorganizzazione di tale materiale allinterno
della composizione (sulla macrostruttura della composizione), cos da unidea musicale pi o meno
precisa possibile dedurre una configurazione (seppur approssimativa) che meglio delle altre
realizzi quellidea. Questa sorta di relazione biunivoca tra idea musicale e configurazione
allinterno dello spazio di controllo, non solo raggiunge lobbiettivo di facilitare il processo
compositivo basato sulla sintesi granulare, ma rappresenta per il compositore motivo di ispirazione
musicale.
Questa nuova tecnica di composizione basata sulla sintesi granulare possiede quindi una
interessante forza compositiva, e costituisce uno strumento di controllo di facile utilizzo.
5

1.5 Scopo della tesi


Lo scopo di questa tesi consiste nella realizzazione di un prototipo che implementi il sistema
GeoGraphy: tale prototipo dovr realizzare tutta la parte relativa al controllo, ovvero deve essere in
grado di generare uno score che contenga tutti i parametri dei singoli grani generati dal sistema. Lo
score generato andr in pasto ad un interprete, che si preoccuper di adattarlo rispetto alle esigenze
del modulo di sintesi adottato per lesecuzione della composizione generata. Il prototipo dovr
essere in grado anche di generare uno score adatto per Csound (linguaggio per la sintesi ed
elaborazione del suono), evitando cos linterpretazione dello score da parte di un interprete spefico
per Csound. La Figura 3 d una rappresentazione intuitiva del processo di elaborazione che subisce
lo spazio di controllo definito dallutente.

Control
Space

GeoGraphy

Score

Interprete

Score interpretato

Modulo di
Sintesi

Audio

Figura 3: Rappresentazione del processo di elaborazione dello spazio di controllo (Control Space):
GeoGraphy traduce il Control Space in uno Score (una partitura, sotto forma di sequenza di eventi
sonori); un Interprete si preoccupa di tradurre lo Score nella forma specifica per il Modulo di Sintesi, che
eseguir lo Score Interpretato, producendo il suono (Audio).

Lattivit di sviluppo seguir il modello a cascata di processo software: il motivo di questa scelta
risiede sia nella semplicit e linearit proprie di tale modello, sia nella caratteristica di abbondante
produzione di documentazione di cui gode il processo a cascata.
I successivi capitoli sono i documenti prodotti nelle seguenti attivit del processo software: analisi
del problema, object modeling, specifica del problema, progettazione orientata agli oggetti,
progettazione di dettaglio.

2Analisi di GeoGraphy
In questo capitolo definiamo tutte le entit coinvolte nel sistema GeoGraphy. Le definizioni date
sono frutto di unanalisi dettagliata di [30]. Ogni definizione accompagnata da unintroduzione
intuitiva, al fine di rendere pi facile comprensione la trattazione.
Useremo i seguenti insiemi numerici: linsieme N = {0, 1, 2, } dei numeri naturali; linsieme dei
numeri reali non strettamente positivi R+ = [0, +) . Indicheremo con linsieme vuoto,
con d(A, B) la distanza [(x1-x2)2 + (y1-y2)2] tra i due punti A = (x1, y1), B = (x2, y2)R2,
con |I| la cardinalit di I, dove I un qualche insieme, e con J \ I linsieme complementare di J in I
{xJ: xI}, dove I e J sono due insiemi. Il tempo sar dato in secondi, e lo spazio in metri.
Come gi accennato nel precedente capitolo introduttivo, GeoGraphy un sistema a due livelli per
il controllo algoritmico della composizione elettroacustica basata sulla sintesi granulare.
Nei seguenti paragrafi affrontiamo separatamente i due livelli del sistema.

2.1 Il Livello-1
Il Livello-1 fornisce il materiale sonoro di base al processo compositivo. Per rendere pi chiara
lidea, possiamo ricorrere al linguaggio metaforico, considerando una composizione come
una torta; il Livello-1 fornisce gli ingredienti necessari per cucinare la torta.
Ogni ingrediente sonoro fornito dal Livello-1 detto track, e presenta una struttura granulare:
cio una sequenza di grani, o meglio di eventi, cio unit di informazione acustica.
Anche se la distinzione tra grani ed eventi sar pi chiara quando si andr ad analizzare il secondo
livello, cerchiamo comunque di capire che tipo di differenza c tra grani ed eventi, e nel
contempo cerchiamo di chiarire la relazione tra track ed eventi. A questo scopo, riprendendo
la metafora culinaria, possiamo pensare alle track come ingredienti pulviscolari crudi
(zucchero, sale, farina, pepe, ecc); un evento come un singolo granello dellingrediente (un
granello di zucchero, di sale, di pepe, ecc.). Al secondo livello avverr la cottura e la mistura
di tali ingredienti (lesecuzione della ricetta). La cottura modifica gli ingredienti, rendendoli
commestibili. Analogamente, la generazione di una composizione a Livello-2 trasforma gli
eventi in grani: a differenza degli eventi, i grani contengono tutte le informazioni prodotte dal
sistema, sia a Livello-1, sia a Livello-2.
Un evento descritto da un certo insieme di informazioni, di parametri di rilevanza acustica e
musicale; il minimo insieme di parametri necessario per definire un evento composto dalle
seguenti quattro informazioni: il tempo di attacco dellevento (listante in cui levento viene
emesso), la durata dellevento, lampiezza donda dellevento, e la posizione stereofonica
dellevento.
In realt, questultimo parametro (detto anche pan) non necessario per definire un evento (ad
esempio, se si lavora con un unico speaker), ma dal momento che, come sar pi chiaro
quando presenteremo il Livello-2, concettualmente GeoGraphy organizza il materiale sonoro
fornito dal Livello-1 in uno spazio bidimensionale, risulta naturale aggiungere agli eventi
linformazione relativa alla posizione stereofonica degli stessi.
Diamo quindi le definizioni di evento e track.
2.1.1 Definizione 1: Evento
Sia mN, m4. Un evento e una tupla (p1, p2, , pm), dove:

p1R+ il tempo di attacco di e;


p2(0,+) la durata di e;
p3[0,1] l ampiezza di e;
p4[-1,1] il pan di e;
p5, , p m[0,1] .
2.1.2 Definizione 2: Track
Sia nN. Una track T una sequenza di n eventi <e1, e2, , en> tale che:
se 0 < i < j n ti tj ,
dove ti , tj il tempo di attacco dellevento ei , ej , rispettivamente.
La Figura 4 illustra due esempi di track che rispettano la definizione data sopra.

T1={ ,

ti

di+1

ei
di

, }

ei+1
ti+1

tempo

di+1

T2={ ,

ei
ti/ ti+1

ei+1

, }

tempo

di

Figura 4: Descrizione intuitiva di due track T1 , T2: nella prima levento ei+1 attacca (al tempo ti+1)
prima che levento ei abbia terminato la propria emissione. In T2 levento ei+1 attacca (al tempo ti+1)
nello stesso tempo di attacco (ti) dellevento ei. di e di+1 sono la durata di ei, ei+1, rispettivamente.

Vediamo ora come il Livello-1 genera le track. Per fare questo, tale livello si serve di grafi, detti
grain generator, in cui, intuitivamente, i vertici possono essere definiti come dei generatori
di eventi, mentre gli archi definiscono le relazioni temporali tra gli eventi generati dai
vertici.
Sui grain generator sono posti dei cosiddetti graph actant (attanti di grafo), che possiamo
immaginare come degli esserini che, quando raggiungono un vertice (attraversando un arco),
si preoccupano di attivare il vertice raggiunto, affinch questultimo generi un evento.
Nel suo navigare, un graph actant genera una track: quindi, il numero di track generate da un grain
generator pari al numero di graph actant posti nello stesso grain generator.
Definiamo ora tutte le entit contemplate in questa breve descrizione intuitiva del processo di
generazione delle track attuato a Livello-1; in seguito daremo una specifica formale di tale
processo.
2.1.3 Definizione 3: Grain Generator
Un grain generator G un (multi)grafo orientato, pesato e non necessariamente connesso, ovvero G
una quadrupla (V, E, w, A), dove:
8

V l insieme dei vertici di G;


E l insieme degli archi di G;
w la funzione peso di G;
A l insieme dei graph actant di G.
2.1.4 Definizione 4: Vertice
Sia G = (V, E, w, A) un grain generator.
Un vertice vV di G una coppia (m, ev-gen), dove:
mN, m4, il numero di parametri di v;
ev-gen il generatore di eventi di v: esso una funzione che ha come codominio linsieme degli
eventi con m parametri, e sul cui dominio non sono poste restrizioni.
Per comodit identifichiamo i vertici con etichette intere positive.
2.1.5 Definizione 5: Arco
Sia G = (V, E, w, A) un grain generator.
Un arco iE di G una coppia indiciata (u,v)i, dove u,vV, e iN l indice di i, in modo tale che
(u,v)i = (u,v)j i = j.
Se (u,v)i un arco di un grain genertor G, diciamo che (u,v)i orientato da u a v, che (u,v)i esce dal
vertice u ed entra nel vertice v; in generale diciamo che (u,v)i incidente su entrambi i
vertici u e v.
Diciamo che due archi (u, v)i e (w, t)j sono archi multipli tra loro u = w v = t, ovvero quando
i due archi sono incidenti su due stessi vertici e hanno medesimo orientamento.
Per definizione, un grain generator ammette quindi archi multipli tra i suoi vertici; in tal senso un
grain generator definibile come multigrafo.
Chiamiamo cappio qualunque arco del tipo (z,z)i, ovvero che esce ed entra in uno stesso vertice
(vedi il vertice 5 in Figura 5).
Ometteremo lindice i di un arco (u,v)i o quando si parla di un generico arco di G, o quando (u,v)i
lunico arco uscente da u ed entrante in v.

2.1.6 Definizione 6: Peso di un arco


Sia G = (V, E, w, A) un grain generator.
La funzione peso w di G una funzione w: (u, v)E (, ), dove:
una qualche funzione che restituisce l intervallo di percorrenza tR+ dellarco (u, v);
[0, 1] la probabilit di percorrenza dellarco (u, v) dal vertice u;
in quanto probabilit, soddisfa la seguente condizione:
2.1.6.2.1 la somma delle probabilit di percorrenza degli archi uscenti da uno stesso
vertice uguale a 1.
2.1.6.2.2 Chiameremo w((u, v)) peso dellarco (u, v).
Intuitivamente, il peso di un arco definisce due aspetti dellarco stesso: il tempo impiegato da un
graph actant (lesserino gi introdotto) nellattraversare larco (lo stesso aspetto pu
9

essere pensato come la lunghezza dellarco, posto che tutti i graph actant circolino nei
grain generator ad una data velocit costante fissata); la distribuzione di probabilit tra gli
archi uscenti da uno stesso vertice, usata dai graph actant per la selezione del prossimo
arco da attraversare.
Andando a incidere sulla navigazione dei graph actant, il peso degli archi incide in modo diretto sul
processo di generazione di track, dal momento che questultimo realizzato dal moto dei
graph actant allinterno dei grain generator: la topologia dei grain generator e il peso
degli archi degli stessi determina quindi il tipo di materiale sonoro che il compositore ha
a disposizione.
2.1.7 Definizione 7: Graph Actant
Sia G = (V, E, w, A) un grain generator.
Un graph actant gaiA un elemento indiciato (v0)i, dove:
v0V il vertice di partenza di gai;
iN l indice di gai, in modo tale che (v0)i = (v0)j i = j.
Intuitivamente, v0 definisce il vertice su cui inizialmente posto il graph actant, e dal quale
questultimo inizia a muoversi attraversando gli archi del grain generator a cui appartiene v 0.
E chiaro che, secondo quanto fin qua definito, i graph actant non sono ancora in grado di muoversi
allinterno di un grain generator: affinch questo sia supportato dalla nostra definizione formale del
sistema, occorrer introdurre una funzione di transizione, che definiremo quando andremo ad
analizzare il processo di generazione di track.
Analogamente a quanto detto per gli archi, ometteremo lindice i di un graph actant
(v0)i o quando si parla di un generico graph actant, o quando esso lunico ad avere v0 come vertice
di partenza.
Prima di analizzare il processo di generazione di track, diamo un esempio di grain generator.
2.1.8 Esempio di Grain Generator
La Figura 5 una rappresentazione grafica di un grain generator G = (V, E, w, A) con:
insieme di vertici V = {1, 2, 3, 4, 5} (i numeri sono le etichette dei vertici);
insieme di archi E = {(1, 2)0, (1, 2)1, (2, 2)0, (2, 2)1, (1, 3), (4, 3), (4, 4), (5, 5)};
funzione peso w, che diamo di seguito in formato tabellare:
iE
(, )

(1, 2)0

(1, 2)1

(1, 3)

(2, 2)0

(2, 2)1

(4, 3)

(4, 4)

(5, 5)

(.02, .2)

(.021, .7)

(0, .1)

(.0001, .01)

(.001, .99)

(0, .5)

(1, .5)

(.02, 1)

(le funzioni sono costanti in secondi);


insieme di graph actant A = {10, 11, 4, 5}.
2.1.9 Processo di generazione di track
Come gi accennato, a Livello-1 ogni grain generator genera un insieme di track.
Sia quindi G = (V, E, w, A) un grain generator, e linsieme di track da esso generato.
10

Ogni graph actant gaA, nel suo circolare allinterno di G, genera una ed una sola track: si ha
quindi che || = |A|, ovvero verranno generate tante track quanti sono i graph actant definiti
in G.
(0.0001, 0.01)
(0.02, 0.2)
0

0
1

(0.021, 0.7)

(0.001, 0.99)

(0, 0.1)

(1, 0.5)
4

(0.02, 1)

(0, 0.5)

Figura 5: rappresentazione grafica del grain-generator G sopra introdotto. Le etichette dei vertici sono poste in
grande allesterno dei vertici stessi. I graph actant sono rappresentati dai cerchiolini allinterno dei vertici:
quando necessario, in essi sono indicati gli indici degli stessi graph actant. Le coppie che etichettano gli archi
sono il peso degli archi stessi. I numeri in piccolo in prossimit dei punti da cui gli archi escono dai vertici
rappresentano lindice degli archi, e sono specificati solo se necessario. Si noti infine che il grain generator qui
rappresentato il grafo G3 in Figura 2.

Affinch i graph actant siano in grado di navigare dentro il grafo, definiamo la seguente funzione di
transizione:
La funzione next: AVR+ V determina le transizioni dei graph actant allinterno dei grain
generator: next(ga, v, t) restituisce il successivo vertice raggiunto dal graph actant gaA, che
al tempo tR+ posto nel vertice vV.
next(ga, v, t) seleziona in A uno tra gli archi uscenti da v, secondo la distribuzione di probabilit
definita dalle probabilit di percorrenza di tali archi ().
Possiamo ora descrivere il processo di generazione di track nel seguente modo:
Sia <e1, e2, , en> una track in , e gaA il corrispondente graph actant generatore della track;
si ha che:
e1 levento sonoro generato dal vertice v 0 (il vertice di partenza di ga) al tempo 0.
ei (2 i n) levento sonoro generato dal vertice v i = next(ga, vi-1, ti-1) al tempo
ti = ti-1 + tempo di percorrenza ( ) tra v i-1 e vi sullarco scelto,
dove: vi-1 il vertice generatore di ei-1;
ti-1 il tempo di attacco di ei-1.
Intuitivamente, durante il processo di generazione delle track di un grain generator G, ciascun graph
actant in G naviga tra i vertici di G (attraverso gli archi di G) iniziando il suo percorso dal vertice su
cui inizialmente posto (v0); il successivo vertice raggiunto determinato dalla funzione di
transizione next. Ogni vertice raggiunto da un graph actant genera un evento nello stesso istante in
cui esso raggiunto dal graph actant. La sequenza degli eventi generati dai vertici raggiunti da uno
stesso graph actant la track risultante dalla navigazione di G da parte del graph actant.
11

2.1.10 Conclusioni
Dalle definizioni date in questo paragrafo possiamo concludere che il Livello-1 un generatore
graph-based di track: esso fornisce il materiale sonoro di base al processo compositivo,
permettendo di definire i dettagli microstrutturali della composizione finale.

2.2 Il Livello-2
Il Livello-2 realizza il controllo dei parametri degli eventi generati a Livello-1, ovvero un sistema
che determina la definizione dei generatori di eventi dei vertici dei grain generator definiti a
Livello-1.
Di seguito definiamo tutte le entit appartenenti a tale livello, e infine descriveremo GeoGraphy a
livello operativo.
2.2.1

Definizione 8: Control Space

2.2.1.1 Un control space CS una quintupla (G, , , sa, T), dove:


G un insieme di grain generator;
la funzione posizione : V ( R+)2, dove V linsieme dei vertici dei grain generator in G.
(v) = (x, y) (R+)2 definisce la posizione (x, y) di v in CS, vV;
la funzione di avvio : A R+, dove A linsieme dei graph actant dei grain generator in G.
(ga) = t R+ definisce il tempo di avvio t di ga in CS, gaA;


sa lo space actant di CS;




T la traiettoria di CS.

Intuitivamente, un control space pu essere pensato come un piano nel quale vengono posti i grain
generator definiti a Livello-1, e nel quale pu essere definita una traiettoria (vedi le figure 7, 8 e
9).
2.2.2 Definizione 10: Traiettoria
Sia CS = (G, , , a, T) un control space. Sia nN.
Data una sequenza di n+1 punti <(x0, y0), (x1, y1), (x2, y2), , (x n, yn)>, la traiettoria T di CS
linsieme dei punti { ( x i + t(xi+1-x0), yi + t(yi+1-yi) )(R+)2: 0 i n-1, t[0, 1] }.
2.2.2.1 Intuitivamente, ponendo n 1, presa una sequenza <P0, P1, , Pn> di n+1 punti in un
piano (il control space), la corrispondente traiettoria il tracciato descritto dai segmenti
compresi tra i punti Pi e Pi+1.
2.2.2.2 Se n = 0, la traiettoria T composta dal solo punto (x0, y0): in tal caso T detta traiettoria
nulla.
Dal momento che, data una sequenza di punti, identificata una ed una sola traiettoria, per
comodit indicheremo una traiettoria con la corrispondente sequenza di punti.
2.2.3 Definizione 11: Space Actant
Sia CS = (G, , , sa, T) un control space. Sia T = <(x0, y0), (x1, y1), , (x n, yn)>, nN.
Lo space actant sa di CS una quadrupla (q0, v, q(t, v, T), r), dove:

12

q0(R+)2 la posizione iniziale di sa: q0 (x0, y0), cio la posizione iniziale dello space actant
coincide con il primo punto della traiettoria T.


vR+ la velocit di navigazione (o semplicemente velocit) di sa; v rispetta la seguente


condizione:
2.2.3.2.1 se T una traiettoria nulla v = 0.


q(t, T)(R+)2 la posizione attuale di sa, che dipende dallistante tR+, e da T, ed definita da:
q0 , se T una traiettoria nulla;
q(t, T) = (x, y)T, punto raggiunto da sa, allistante t e a velocit v, lungo la traiettoria T
a distanza vt da (x0, y0), se un tale (x, y) esiste;
indef., altrimenti;


r[0,+) il raggio di udibilit di sa.

Intuitivamente, nel control space, che immaginiamo come un piano, insieme ai grain generator e ad
una traiettoria, presente un ulteriore attante (oltre agli attanti di grafo presenti nei grain
generator posizionati nel control space): lo space actant, che possiamo immaginare come un
esserino in grado di muoversi lungo la traiettoria solo a velocit costante (v), e dotato di orecchie in
grado di sentire entro un certo raggio di udibilit (r).
2.2.4 Definizione 12: Angolo di orientamento di sa
Sia CS = (G, , , sa, T) un control space.
Supponiamo T = <P0, P1, , P n> non nulla, e consideriamo un istante di tempo t per cui la posizione
attuale q(t, T) di sa un punto del segmento Pi Pi+1, 0 i < n. (Per comodit indichiamo q(t,
T) con q, omettendo le variabili t e T)
Preso un qualunque vertice v di un qualche grain generator in G, l angolo di orientamento di sa
langolo positivo (t, (v)), che dipende dallistante di tempo t e dalla posizione (v) di v,
descritto dalla rotazione in senso antiorario del segmento q Pi+1, intorno a q, fino a
sovrapporsi al segmento q (v).
Se T una traiettoria nulla q(t, T) = (v), langolo di orientamento di sa (t, (v)) = 0, tR+.
La Figura 6 mostra il significato geometrico dellangolo di orientamento di sa, mostrando come
esso varia rispetto al verso del vettore spostamento t.
(v)

P0

Pi+1

P1
Pi

Figura 6: Significato geometrico dellangolo di orientamento di


sa.

Analogamente a quanto fatto nella precedente trattazione del Livello-1, facciamo qualche esempio
di grain generator, al fine di fissare parte delle definizioni fin qua date.
13

2.2.5 Esempi di control space


Di seguito sono dati tre esempi di control space. Ricordiamo che tutte le lunghezze sono date in
metri, e che il tempo dato in secondi.
La Figura 7 una rappresentazione grafica di un control space CS1 = (G, , , a, T) con:
insieme di grain generator G = {G}, dove G stato definito nellesempio di grain generator esposto
nel precedente paragrafo;
funzione posizione , che diamo di seguito in formato tabellare:
1
2
3
4
5
vV
(v) (1.5, 2) (3, 2) (1.5, 1) (3, 1) (4.5, 1.5)
(abbiamo identificato i vertici con le loro etichette);
funzione di avvio , che diamo di seguito in formato tabellare:

aA
(a)

10

11

2.1

1.5

space actant a = (q0 = (4.5, 2), v = 1 m/sec, q(t, T), r = 1)


traiettoria T = < (4.5, 2), (3.5, 1.5), (0.5, 1), (1.5, 2.5), (3, 3) >.
q4 = (3, 3)

2.5

q3 = (1.5, 1.5)

(0.0001, 0.01)

(0.02, 0.2)

(0.021, 0.7)

1.5

q0 = (4.5, 2)

(0.001, 0.99)

(0.02, 1)
5

(0, 0.1)

sa

q1 = (3.5, 1.5)

q2 = (0.5, 1)

(0, 0.5)

(1, 0.5)

0.5

( (4.5, 2), 1 m/s, q(t,T)=(3.25,1.375), r=1 )

0.5

1.5

2.5

3.5

4.5

Figura 7: Rappresentazione grafica del control space CS1 sopra introdotto. La traiettoria <q0, q1, q2, q3, q4>
viene percorsa dallo space actant sa, la cui posizione attuale q(t,T) = (3.25, 1.375). Il raggio di udibilit di sa
rappresentato dalla circonferenza in rosso.

La Figura 8 una rappresentazione grafica di un control space CS2 = (G, , , a, T) con:


insieme di grain generator G = {G}, dove G stato definito nellesempio di grain generator
esposto nel precedente paragrafo;
funzione posizione , che diamo di seguito in formato tabellare:
14

1
2
3
4
5
vV
(v) (0.5, 1) (1.5, 1) (2.5, 1) (3.5, 1) (4.5, 1)

(abbiamo identificato i

vertici con le loro etichette);


funzione di avvio costante a 0.
space actant a = (q0 = (0, 1), v = .045 m/sec, q(t, T), r = 0)
traiettoria T = < (0, 1), (4.5, 1) >.
2

1.5
(0.02, 0.2)

(0.0001, 0.01)

(1, 0.5)

sa

1
q0 = (2, 4.5)

(0.021, 0.7)

(0.001, 0.99)

(0.02, 1)

q1 = (4.5, 1)

(0, 0.5)

0.5
(0, 0.1)

((0,1), 0.045 m/s, q(t,v,T)=(3,1), r=0)


0

0.5

1.5

2.5

3.5

4.5

Figura 8: Rappresentazione grafica del control space CS2 sopra introdotto. La traiettoria composta da un
unico segmento di estremi q0=(2, 4.5), q1=(4.5, 1); essa viene percorsa dallo space actant sa, la cui
posizione attuale q(t,T) = (3, 1), e il cui raggio di udibilit nullo (r=0).

La Figura 9 una rappresentazione grafica di un control space C3 = (G, , , a, T) con:


insieme di grain generator G = {G}, dove G stato definito nellesempio di grain generator
esposto nel precedente paragrafo;
funzione posizione , che diamo di seguito in formato tabellare:
1
2
3
4
5
vV
(v) (0.5, 1) (1, 1.5) (1, 0.5) (1.5, 1) (2.5, 1)
(abbiamo identificato i vertici con le loro etichette);
funzione di avvio costante a 0.
space actant a = (q0 = (1, 1), v = 0 m/sec, q(t, T) = q0, r =1)

traiettoria T = .

2.3 La generazione dello score


Prima di esporre lesecuzione del sistema, occorre definire il prodotto finale generato da tale
esecuzione: lo score. Lo score per il Livello-2 ci che la track per il Livello-1; come la track, lo
score presenta una struttura granulare: cio una sequenza di grani. Un grano essenzialmente un
evento e al quale vengono aggiunte due informazioni: la distanza tra la posizione attuale dello space
actant allistante t e la posizione del vertice generante e, e langolo (t, (v)) di orientamento di sa
allistante t, dove t il tempo di attacco di e.
15

2
(0.0001, 0.01)

(0.001, 0.99)

0.
7)

(0
.0
21
,

(0
.0
2,
0.
2)

1.5

(1, 0.5)

SAct
sa

(0.02, 1)
,0

(0
,0
.5
)

(0
)
.1

0.5

(q0(1,1), v = 0, q(t,v,T)=(1,1), r=1)


0

0.5

1.5

2.5

Figura 9: Rappresentazione grafica del control space CS3 sopra introdotto. La traiettoria
nulla, pertanto lo space actant sa immobile. Il raggio di udibilit rappresentato dalla
circonferenza in rosso con centro in q0 = (1,1), e di raggio r = 1. Si noti che il vertice 5
posizionato al di fuori del raggio di udibilit.

2.3.1 Definizione 13: Grano


Sia CS = (G, , , a = (q0, v, q(t, v, T), r), T) un control space.
Sia V = VG , dove VG linsieme dei vertici del grain generator G. Sia un vertice v V.
GG

Sia un istante di tempo tR+.


Sia mN, m6.
Un grano g una tupla (p1, p2, , p m), dove:

16

p1R+ il tempo di attacco di g;




p2(0,+) la durata di g;


p3[0,1] l ampiezza di g;


p4[-1,1] il pan di g;


p5 = d(q(t, v, T), (v)) la distanza tra la posizione attuale di sa e la posizione del vertice v, che
ha generato il grano g;


p6 = (t, (v)) langolo di orientamento di sa;




p5, , p m[0,1] .

2.3.2 Definizione 14: Score


Sia nN. Uno score S una sequenza di n grani <g1, g2, , g n> tale che:
se 0 < i < j n ti tj ,
dove ti , tj il tempo di attacco del grano gi, gj, rispettivamente.
Vediamo ora intuitivamente come lesecuzione di un control space genera uno score.
Come gi detto, possiamo pensare un control space come un piano nel quale vengono distribuiti dei
grain generator e nel quale viene definita una traiettoria e uno space actant.
La configurazione scelta allinterno del control space determina per ogni istante di esecuzione uno
ed un solo controllo sui singoli parametri di ciascun evento (o meglio, grano) generato nello
stesso istante dal corrispondente vertice posizionato nel control space.
E chiaro che tale controllo sui parametri degli eventi determina gli stessi eventi: possiamo quindi
affermare che la configurazione scelta allinterno del control space determina univocamente
un generatore di eventi per ogni vertice posizionato nello stesso control space.
In questo senso il control space (ovvero il Livello-2) altro non che un contesto in cui vengono
immersi i grain generator che permette di definire in modo intuitivo e contestuale un
generatore di grani per ogni vertice in esso schierato.
2.3.3 Esecuzione del control space
Sia CS = (G, , , a, T) un control space.
Sia A = AG , dove AG linsieme dei graph actant del grain generator G.
GG

Sia V = VG , dove VG linsieme dei vertici del grain generator G.


GG

Sia S uno score vuoto (S = ).


L esecuzione di CS, avviata al tempo t0 = 0, avvia, a Livello-1, il processo di generazione di track,
ovvero ogni graph actant gaA, al tempo (ga), inizia a navigare sul grain generator a cui
appartiene; a Livello-2, lo space actant sa, ovvero sa = (q0, v, q(t, T), r), al tempo t0 = 0,
inizia a percorre la traiettoria T a velocit v, se T non una traiettoria nulla; se T una
traiettoria nulla, sa resta immobile in q0.
Il raggio di udibilit r di sa viene usato per attivare/disattivare il generatore di eventi ev-gen dei
vertici posizionati in CS: se ad un certo istante t un vertice v posizionato in CS in modo
tale che esso rientri nel raggio di udibilit r di sa (vedi il vertice 2 in Figura 7), allora il
generatore di eventi ev-gen di v attivo, cio, se allo stesso istante t il vertice v viene
attraversato da un qualche graph actant ga, v in grado di generare (via ev-gen) un evento.
Al contrario, se in un certo istante t un vertice v posizionato in modo tale che esso sia fuori
dal raggio di udibilit r di sa (vedi il vertice 1 in Figura 7), allora il generatore di eventi ev17

gen di v inattivo, ovvero, se allo stesso istante t il vertice v viene attraversato da un


qualche graph actant ga, v non pu generare alcun evento.
Per ogni istante di esecuzio t, possiamo quindi distinquere le seguenti due classi di vertici in V:
t = {vV | d(q(t, T), (v)) > r} l insieme dei vertici inattivi allistante t;


t = V \ t = {vV | d(q(t, T), (v)) r} l insieme dei vertici attivi allistante t;




2.3.3.3 Se v t, chiameremo t istante di attivazione di v, e v vertice attivo allistante t.


Inoltre, se un vertice v attivo in un certo intervallo di tempo, chiameremo intervallo di attivazione
di v tale intervallo.
2.3.3.4 Per mettere subito in pratica quanto fin qua detto, diciamo che se la traiettoria T nulla e
il punto in cui posizionato un certo vertice vV rientra nel raggio di udibilit r di sa
(cio,
d(q0, (v)) r) (vedi il vertice 1 in Figura 9), allora v sempre attivo durante lesecuzione
del control space, ovvero, t[0, +), v t, e [0, +) intervallo di attivazione di v.
Ma, se ad un certo istante t un vertice v attivo, come fa il generatore di eventi di v a generare un
evento? Questo equivale a chiedersi come sia effettivamente definita la funzione ev-gen.
ev-gen definita in termini di sotto-funzioni, dette generatori di parametro; ciascun generatore di
parametro si preoccupa di generare il valore di un singolo parametro dellevento da
generare.
ev-gen di un qualunque vertice v quindi cos definita:
ev-gen( ) = ( p1-gen( ), p2-gen( ), , pm-gen( ) ), dove m il numero di parametri di v.
Vediamo ora di definire i vari generatori di parametro:
Il generatore di parametro p1-gen( ), che genera il tempo di attacco dellevento da generare,
sempre la funzione identit id(t), dove t listante in cui ev-gen stata invocata da parte di
un graph actant, ovvero listante in cui il vertice a cui appartiene ev-gen viene attraversato
da un graph actant.
I generatori dei restanti parametri possono essere una tra le seguenti funzioni:
la funzione costante const( ) = c, dove c una costante appartenente al dominio del parametro
da gerare;


la funzione rand( ), detta funzione random che seleziona casualmente un valore allinterno del
dominio (che si suppone essere chiuso e limitato) del parametro da generare; dal momento che il
parametro di durata ha dominio illimitato (0, +), per tale parametro occorre poter restringere il
dominio ad un intervallo chiuso e limitato;


la funzione pan( ) = map




(t, (v)) langolo di orientamento di sa (vedi def. 12);




-sin( (t, (v)) ), detta funzione pan, dove:

map(x) = min + [(max min) / 2] (x + 1) la funzione che mappa x[-1, 1] nel dominio
chiuso e limitato del parametro da generare (anche qui, dal momento che il parametro di
durata ha dominio illimitato (0, +), per tale parametro occorre poter restringere il
dominio ad un intervallo chiuso e limitato);

la funzione dist-funct( d(q(t, T), (v)) ), detta funzione della distanza, una qualche funzione della
distanza tra la posizione attuale q(t, T) dell sa e la posizione (v) del vertice v su cui stata
invocata ev-gen.
18

Adesso per, come gi detto, il Livello-2 vede grani, non eventi: che fine fanno dunque gli
eventi generati a Livello-1 durante lesecuzione del control space?
Ad ogni evento e generato a Livello-1 viene applicata la funzione m(e) = ge, che trasforma e nel
corrispondente grano ge aggiungendo ad e le seguenti due informazioni:
la distanza d(q(t, T), (v)) tra la posizione attuale di sa e la posizione del vertice v che ha
generato e;


langolo (t, (v)) di orientamento di sa.




La funzione composta m

ev-gen( ) detta generatore di grani del vertice v.

A mano a mano che, durante lesecuzione di CS, vengono generati i grani, essi vengono inseriti
nello score S, che loutput dellesecuzione di CS.
Lesecuzione di CS termina o quando viene interrotta dallesterno, o quando sa ha percorso tutta la
traiettoria T, se T una traiettoria nulla.
2.3.4

Esempio di score

La Figura 10 raffigura uno score generato dal control space CS1 (vedi il primo esempio di control
space del paragrafo 2.2, e la Figura 7): in tale figura la freccia orizzontale rappresenta il
tempo, e per ciascun graph actant (indicato con letichetta del vertice di partenza)
rappresentata la corrispondente track, in cui ciascun evento un pallino al cui interno
indicata letichetta del vertice che ha generato levento stesso.

.021

10

.001

.0001

.001

.001

.001

11

.02

.02

.02

1.12

4
3

1.5

2.1

2.3

2.5

3.5

6.66

7.56 time

Figura 10: Rappresentazione di uno score: la freccia orizzontale rappresenta il tempo; per ciascun graph actant
specificata la track (rappresentata dalla corrispondente sequenza di pallini) generata durante lesecuzione del control
space CS1 in Figura 6; i grani dello score sono i pallini rossi, al cui interno specificata letichetta del vertice che ha
generato il grano. I pallini grigi sono i grani mancati, cio quelli scartati via raggio di udibilit. I grani posti su di
una stessa linea verticale (cio, sovrapposti verticalmente) sono generati nel medesimo istante (si vedano i grani 1 e
3 della track relativa al graph actant 1 1, e i grani 4 e 3 (emessi allistante 3.5) della track relativa al graph actant 4.

Ogni numero tra due eventi (pallini) successivi indica lintervallo di tempo che separa tali eventi.
Quando viene avviata lesecuzione del control space CS1, lunico graph actant che al primo istante
di esecuzione inizia il processo di generazione di track (cio a navigare nel grafo) quello
inizialmente posto nel vertice 5: dal momento che lo space actant sa ha raggio di udibilita r
= 1, per tutto il periodo di tempo in cui il vertice 5 rientra in tale raggio di udibilit (cio, il
tempo necessario a sa per percorrere il primo segmento della traiettoria), che va
19

approssimativamente dallistante 0 allistante 1.12, tale vertice attivo, cio in grado di


generare grani, che in Figura 10 sono rappresentati dai pallini rossi. Anche se il graph actant
5 continua a navigare, non appena il vertice 5 esce dal raggio di udibilit (dallistante 1.12 in
poi), esso diventa inattivo, cio non pu generare grani: tutti i pallini grigi in Figura 10
rappresentano gli eventi non generati al passsaggio di un graph actant sul vertice la cui
etichetta allinterno degli stessi pallini.
Senza entrare nel dettaglio dei percorsi seguiti dai singoli graph actant, lo score generato
dallesecuzione del control space CS1 linsieme dei grani (i pallini rossi in Figura 10)
generati durante la navigazione del grafo da parte di tutti graph actant.
2.3.5

Conclusioni

Dallanalisi svolta possiamo concludere che il Livello-2 un control space, cio un contesto nel
quale vengono immersi i grain generator definiti a Livello-1 che permette di definire in
modo intuitivo e contestuale un generatore di grani per ogni vertice in esso schierato.

2.4 Conclusioni generali


Lanalisi compiuta nel corso di questo capitolo ci ha permesso di capire il funzionamento del
sistema GeoGraphy entrando nel dettaglio delle singole entit coinvolte nei due livelli del
sistema stesso. Su questanalisi poggier tutto il successivo lavoro, a cominciare dallattivit
di modellazione orientata agli oggetti, esposta nel capitolo che segue.

20

3Object Oriented Analysis (Object Modeling)


In questo capitolo vengono identificate le classi nel dominio del problema, le loro relazioni, i loro
attributi, e i principali servizi che emergono dalla precedente analisi del problema, al fine di creare
un primo object model del sistema.
Di qui in avanti ogni object class identificata sar scritta in Arial, ogni attributo identificato sar
scritto in corsivo, ogni servizio identificato sar scritto in Garamond.
La notazione usata per gli object diagram in Figura 11 e Figura 12 data in [15]:98-107.

3.1 Livello-1
Dal momento che il generatore di eventi dei vertici viene definito precisamente solo a Livello-2,
ignoreremo la possibilit di generare track a Livello-1, e ci preoccuperemo del processo di
generazione di track nel prossimo paragrafo, quando andremo a modellare il Livello-2.
Identifichiamo nellordine gli oggetti, le strutture, gli attributi, le associazioni, i servizi.
3.1.1 Oggetti
Dallanalisi svolta nel precedente capitolo, a Livello-1 identifichiamo immediatamente le se guenti
object class: Level_1, GGen, Vertex, Edge, GAct, che modellano, rispettivamente, le seguenti
entit: Livello-1, grain generator, vertice, arco, e graph actant.
3.1.2

Strutture

Level_1 unaggregazione di pi GGen.


GGen unaggregazione di pi Vertex e GAct.
Vertex unaggregazione di zero o pi Edge, che sono gli Edge uscenti dal Vertex.
Edge contiene il Vertex in cui entra l Edge stesso.
GAct contiene il Vertex sul quale posto inizialmente il GAct stesso.

La struttura che intercorre tra le classi rappresentata dallobject diagram in Figura 8.


3.1.3

Attributi

Dal momento che occorre identificare i GGen, introduciamo lattributo name, che identificatore
univoco per i GGen contenuti in Level_1.
I Vertex sono invece identificati dalla loro etichetta label.
Lattributo numberOfOthersParams di Vertex mantiene il numero m-4, dove m il numero di
parametri del vertice, ovvero il numero di parametri esclusi il parametro di durata,
ampiezza, tempo di attacco, e pan.
Di qui in avanti chiameremo altro parametro un parametro che non sia la durata, lampiezza, il
tempo di attacco, o il pan.
Gli attributi identificati per Edge sono:
temporalDistance, che mantiene il tempo di percorrenza in secondi dell Edge, nel caso in cui
la funzione che restituisce l intervallo di percorrenza sia una funzione costante.
routeProbability, che mantiene la probabilit di percorrenza dell Edge.
Non identifichiamo alcun attributo per GAct e Level_1.

21

3.1.4

Associazioni

Oltre alle relazioni gi identificate, a Livello-1 non vi sono relazioni particolari tra le object class
fin qua identificate.
3.1.5

Servizi

Dal momento che, come gi detto, a Livello-1 ignoriamo la possibilit di generare track, gli unici
servizi fin qua identificabili sono quelli occur, cio quelli per creare, distruggere e
mantenere gli oggetti e i loro attributi, che diamo per impliciti.
Il modello fin qua identificato rappresentato dallobject diagram mostrato in Figura 11.

GAct
Level_1

GGen
name

Vertex
label
numberOfOthersParams

Edge
temporalDistance
routeProbability

Figura 11: Object diagram che rappresenta lobject-model del sistema a Livello-1.

3.2 Livello-2
Chiaramente, il modello costruito nel precedente paragrafo forma la base per il modello da costruire
per il Livello-2: modificheremo quindi lobject model identificato a Livello-1, in modo tale
che esso supporti lesecuzione del control space.
Identifichiamo nellordine gli oggetti, le strutture, gli attributi, le associazioni, i servizi.
3.2.1

Oggetti

Dalla precedente analisi svolta nel secondo capitolo, a Livello-2 identifichiamo immediatamente le
seguenti object class: ControlSpace, Trajectory, Grain, Score, e ActivationInterval, che
modellano, rispettivamente, le seguenti entit: control space, traiettoria, grano, score, e
intervallo di attivazione.
ControlSpace ingloba lobject class Level_1: infatti, dal momento che ignoriamo la possibilit di
generare track a Livello-1, definire un GGen a Livello-1 ha senso soltanto nel momento in
cui esso viene posto nel ControlSpace. Level_1 quindi eliminata dallobject model.

Dal momento che c uno stretto rapporto tra la traiettoria e lo space actant, Trajectory modella
entrambe tali due entit.
Modelliamo inoltre ciascun segmento della traiettoria con la classe ShiftingVector, che fornir tutte le
operazioni da compiere a livello di segmento (mentre Trajectory fornir tutte le operazioni da
compiere a livello di traiettoria e space actant).

22

Dalle definizioni di generatore di eventi ev-gen e di generatore di parametro, chiaro che per ogni
parametro pi (ad esclusione del tempo di attacco) degli eventi generati da un qualunque
Vertex, occorre poter definire il corrispondente generatore di parametro: affinch il modello
supporti i quattro tipi di generatori di parametro ( const( ), rand( ), pan( ), e dist-funct( ) ),
introduciamo le seguenti object class:
Parameter, che modella il generico parametro degli eventi generati dal Vertex;
Duration, Amplitude, e Pan, che modellano, rispettivamente, i parametri di durata, ampiezza, e

pan.

OtherParam, che modella un altro parametro (come gi detto, un parametro che non sia la

durata, lampiezza, il tempo di attacco, o il pan);

ParamGenerator, che modella il generico generatore di parametro;


RandFunct, PanFunct e DistFunct, che modellano, rispettivamente, i seguenti tre tipi di

generatore di parametro: rand( ), pan( ), e dist-funct( ); il tipo di generatore di parametro


costante ( const( ) ) verr modellato con un attributo (constantValue, vedi oltre);

Dal momento che al parametro tempo di attacco pu essere associata soltanto la funzione di
identit, risulta inutile per i nostri scopi modellare tale parametro con unobject class.
3.2.2

Strutture

ControlSpace unaggregazione di uno o pi GGen e una sola Trajectory.


Trajectory unaggregazione di zero o pi ShiftingVector.
Score unaggregazione di zero o pi Grain.
Parameter superclass per Duration, Amplitude, Pan, e OtherParam.
Vertex unaggregazione dei parametri degli eventi da esso generati, cio: Duration, Amplitude, Pan, e
zero o pi OtherParam.
Inoltre, Vertex unaggregazione di zero o pi ActivationInterval.
ParamGenerator superclass per RandFunct, PanFunct e DistFunct.
Parameter contiene un ParamGenerator.

La struttura che intercorre tra le classi rappresentata dallobject diagram in Figura 12.
3.2.3

Attributi

Dal momento che, come gi detto, lobject class Trajectory modella entrambe le entit traiettoria e
SAct, Trajectory ha gli attributi:
initialPoint, che mantiene la posizione iniziale dellSAct;
speed, che mantiene la velocit di navigazione dellSAct;
audibilityRadius, che mantiene il raggio di udibilit dellSAct;
ShiftingVector ha gli attributi head e tail, che mantengono, rispettivamente, il primo e lultimo punto

esterno del segmento di traittoria modellato, rispetto allordine in cui tali punti sono contenuti nella
traiettoria.
Un attributo da aggiungere a Vertex a Livello-2 vertexPosition, che mantiene la posizione del
Vertex nel ControlSpace.
Al fine di supportare il tipo di generatore di parametro costante, introduciamo lattributo
constantValue nellobject class Parameter.
Come espresso dalla definizione di funzione rand( ) e di funzione pan( ), occorre restringere il
dominio (0,+) del parametro durata in un intervallo chiuso e limitato I, nel caso in cui tale
23

parametro sia generato dalla funzione random o pan, appunto. Introduciamo quindi lattributo
domainRestriction alla classe Duration, che mantiene tale intervallo I.
Gli attributi di ActivationInterval sono firstInstant, lastInstant, rispettivamente per il minimo e il
massimo istante di attivazione dell ActivationInterval.
Affinch il modello supporti il caso cui il vertice attivo per ogni istante di esecuzione,
introduciamo lattributo alwaysActive a Vertex, un booleano che, se vero, indica che il Vertex
sempre attivo.
Aggiungiamo a GAct lattributo startTime che rappresenta il tempo di avvio dello stesso GAct a
partire dallinizio.
Ciascun Grain deve mantenere tutte le informazioni che definiscono un grano: aggiungiamo quindi i
seguenti attributi allobject-class Grain: attackInstant, durationValue, amplitudeValue, panValue,
distance, angle, e otherParamValues, che mantengono, rispettivamente, il tempo di attacco, la
durata, lampiezza, il pan, la distanza tra la posizione attuale dello space actant e la posizione del
vertice generante il grano, langolo e langolo di orientamento dello space actant (vedi la def. 12 a
pag. 13), i valori dei restanti parametri.
3.2.4

Associazioni

I vertici generano grani, quindi tra le istanze delle classi Vertex e Grain esiste una relazione,
unassociazione zero a molti, dal momento che un vertice pu generare zero o pi grani
durante lesecuzione del control space.
Inoltre, lo stato di attivit di un vertice dipende dalla traiettoria: esiste perci una relazione tra le
istanze della classe Vertex e la Trajectory: tale associazione chiaramente uno a molti, dal
momento che ogni vertice in relazione con la traiettoria.
Altre associazioni potranno essere identificate durante lidentificazione dei servizi, che segue.
3.2.5

Servizi

Eviteremo di specificare i servizi occur, cio quelli per creare, distruggere e mantenere gli oggetti
e i loro attributi, che saranno considerati impliciti.
Lobject class ControlSpace deve fornire un servizio per avviare lesecuzione del control space:
introciamo quindi il servizio startPerformance( ) a ControlSpace, che realizza appunto tale
funzionalit.
Affinch per ogni vertice di un grain generator caricato nel control space possano essere calcolati
tutti gli intervalli di attivazione, introduciamo il servizio computeVxActivationIntervals( ) alla
classe GGen. E chiaro che tale funzione dipende dallo stato della Trajectory. C quindi una
relazione tra le istanze della classe GGen e loggetto Trajectory: aggiungiamo al modello
unassociazione uno a molti (1:N) tra tali oggetti.
Il calcolo vero e proprio degli ActivationInterval dovr essere svolto dai singoli Vertex;
computeVxActivationIntervals( ) ha solo il compito di chiedere ad ogni Vertex di svolgere
tale calcolo: introduciamo quindi computeActivationIntervals( ) allinterfaccia della classe
Vertex, servizio che si preoccupa di calcolare tutti gli ActivationInterval del Vertex.
Ovviamente anche computeActivationIntervals( ) dipende dalla Trajectory, e tale relazione gi
stata modellata con lassociazione tra le istanze delle object class Vertex e Trajectory.
Affinch computeActivationIntervals( ) possa calcolare tutti gli intervalli di attivazione di un Vertex,
occorre:
sapere se lo space actant ha velocit di navigazione speed = 0: tale servizio, che chiamiamo
isImmovableSAct( ), chiaramente offerto da Trajectory;
24

verificare se un vertice sempre attivo o meno, nel caso in cui lo space actant abbia velocit
di
navigazione
speed
=
0:
anche
tale
servizio,
che
chiamiamo
isAudiblePointFromInitialPosition( ), offerto da Trajectory;
ottenere listante di tempo in cui lo space actant si trova in un dato punto della traiettoria
(altro non , che la funzione inversa della posizione attuale dello space actant): tale servizio,
che chiamiamo getInstantToPoint( ), offerto da Trajectory;
verificare se il Vertex attivo rispetto almeno uno dei punti di uno ShiftingVector (un
segmento della traiettoria): tale servizio, che chiamiamo isAudiblePoint( ), chiaramente
offerto dalla classe ShiftingVector;
ottenere i punti estremi del segmento appartenente ad uno ShiftingVector in cui il Vertex
attivo, se tale segmento esiste: tale servizio, che chiamiamo getActivationPoints( ), offerto
da ShiftingVector.
Una volta calcolati tutti gli ActivationInterval associati ad un Vertex, occorre poter verificare se in un
dato istante il Vertex attivo o meno: il servizio isActive( ) dellobject class Vertex fornisce tale
informazione.
Modelliamo il processo di generazione di track con il servizio startTrackGenerationProcess( ), fornito
dalla classe GAct. Durante tale processo occorre poter scegliere casualmente uno tra gli Edge uscenti
dal Vertex in cui si trova il GAct: tale operazione realizzata dal servizio chooseEdge( ), fornito dalla
classe Vertex.
Modelliamo il generatore di grani di un vertice con il servizio grainGenerator( ), fornito ovviamente
dalla classe Vertex. grainGenerator( ) si serve del servizio getValue( ), fornito da ParamGenerator, per
generare i singoli parametri del grano da generare.
Altri servizi che deve fornire Trajectory sono getDistance( ) e getAngle( ), che restituiscono
rispettivamente la distanza tra la posizione attuale dellSAct e la vertexPosition di un Vertex (si
ricordi che Trajectory modella anche lSAct), e langolo (per questultimo, vedi la definizione 12).
Di uno ShiftingVector occorre sapere la lunghezza, e se un dato punto appartiene o meno allo stesso
ShiftingVector: introduciamo quindi i servizi getLength( ) e isMyPoint( ) a ShiftingVector, che realizzano
queste due funzionalit.
Infine, lo Score deve effrire un servizio per inserire in esso un Grain, e un servizio per scrivere i
Grain in esso contenuti in un file. Tali servizi li chiamiamo insertGrain( ), e writeInTheScoreFile( ).
Lobject model risultante dallobject modeling in Figura 12.

ControlSpace
startPerformance ( )
GAct
startTime
startTrackGeneratorProcess ( )

Trajectory

GGen

25

audibilityRadius
isImmovableSAct ( )
isAudiblePointFromInitialPosition ( )
getInstantToPoint ( )
getDistance ( )
getAngle ( )

ShiftingVector
head
tail
isAudiblePoint ( )
getActivationPoints ( )
getLength ( )
isMyPoint ( )

Vertex
label
numberOfOthersParams
vertexPosition
alwaysActive
computeActivationIntervals ( )
isActive ( )
chooseEdge ( )
grainGenerator ( )

Grain
attackInstant
durationValue
amplitudeValue
panValue
distance
angle
otherParamValues

ActivationInterval
firstInstant
lastInstant

Score

Edge
temporalDistance
routeProbability

insertGrain ( )
writeInTheScoreFile ( )

Amplitude

Pan

Duration
domainRestriction

OtherParam

RandFunct

Parameter
constantValue
getParamValue ( )

PanFunct
ParamGenerator
getValue ( )

DistFunct

Figura 12: Object-diagram che rappresenta lobject-model del sistema GeoGraphy.

26

4Requirements Specification Document


Questo capitolo contiene il documento di specifica dei requisiti per il caso di studio proposto da
questa tesi.
Seguiremo lo standard IEEE per un documento di specifica dei requisiti (vedi [13] e [14], seppur
con qualche modifica.

4.1

Introduction

4.1.1

Purpose

Lo scopo di questo documento di descrivere i requisiti di un sistema per il controllo algoritmico


della composizione elettroacustica basata sulla sintesi granulare.
4.1.2

Definitions, Acronyms, Abbreviations

Chiamiamo GeoGraphy il suddetto sistema. Inoltre, vengono considerate tutte le definizioni date
nel capitolo.
4.1.3

Notational Conventions

Tutti i requisiti specificati in questo documento sono descritti in prosa, in una Backus Naur Form
(BNF) estesa, specificata in [4]:8-10 (adottiamo quella usata nellRFC 1945), o con Data Flow
Diagram (DFD), secondo la notazione data in [15]:88.

4.2 Overall Description


4.2.1

Product Perspective

GeoGraphy parte di un sistema pi grande, descritto dal diagramma di contesto in Figura 13.
Implementation
Boundary
Control Space File

User
Score FIle

User

*
Command Line

Grains
GeoGraphy

Audio
Grains

Interpreter

Interpreted Score

Synthesis
Module

Error Messages
GGen Files

User

Figura 13: Data Flow Diagram che descrive il flusso di dati tra le varie componenti del sistema di cui parte
GeoGraphy. Tutto ci che contenuto nellimplementation boundary (nel cerchio) dovr essere implementato.

27

Il formato degli input e output di GeoGraphy sono dati in (4.3.1). Il formato dei restanti flussi di
dati (Interpreted Score e Audio) non oggetto di questo documento, in quanto tali flussi sono al di fuori
dellimplementation boundary (che contiene la parte del sistema che deve essere implementata).
Come si pu vedere nel DFD in Figura 13, GeoGraphy si interfaccia con un modulo di sintesi
(Synthesis Module) per mezzo di un interprete (Interpreter). Linterprete il processo che si preoccupa
di tradurre loutput di GeoGraphy (Score File) nella forma specifica per il modulo di sintesi
(Interpreted Score), in modo tale che questultimo possa suonare lo Score generato da GeoGraphy.
Per questa implementazione non richiesto un interprete, ma la possibilit di generare
immediatamente uno score specifico per Csound (vedi [12] e [18]), evitando cos lelaborazione
dello Score File da parte dellinterprete per Csound.
4.2.2

Product Functions Overview

Il sistema permette allutente di definire graph generator e control space e di eseguire il control
space da lui stesso specificato via linea di comando. Tale esecuzione genera uno score.

4.3 Specific Requirements


4.3.1

Inputs and Outputs

Il sistema ha due tipi di file in input e produce due tipi di output. Il formato di tali input e output
di seguito descritto:
4.3.1.1 GGen File
E il file di input che contiene la definizione di un grain generator. Il suo formato il seguente:
GGen_File

= Vertexes
[Edges]
Gacts
*comment

Vertexes

= *comment
"Vertexes:" 1#vertex LWS ";"

vertex

= "(" label [LWS "," other-params] LWS ")"

label

= [LWS "label" LWS "="] LWS vertex-ID

other-params

= [LWS "other-params" LWS "="] LWS 1*DIGIT

Edges

= *comment
"Edges:" 1#(edge [weight])LWS

edge

= "(" LWS vertex-ID LWS "->" LWS vertex-ID LWS ")"

weight

= LWS "--> LWS "(" LWS route-interval LWS "," LWS


route-prob LWS ")"

route-interval

= interval | "rand"

interval

= decimal LWS [time-unit]


; se time-unit non specificato sono millisec

time-unit

= ([factor] "sec") | "min" | "h"

factor

= ( "deci" | "centi" | "milli" |


"micro" | "nano" | "pico" )

route-prob

= prob | "auto"

prob

= "1" | "0" ["." 1*DIGIT]

GActs

= *comment
"GActs:" 1#vx-gacts
LWS ";"

vx-gacts

= vertex-ID "<-" [gact-number]

";"

28

gact-number

= 1*DIGIT ["gact" ["s"]]

comment

= LWS ["//" *TEXT LWS]

vertex-ID

= 1*( ALPHA | DIGIT )

ALPHA

= UPALPHA | LOALPHA

UPALPHA

= <any US-ASCII uppercase letter "A".."Z">

LOALPHA

= <any US-ASCII lowercase letter "a".."z">

decimal

= 1*DIGIT ["." 1*DIGIT]

DIGIT

= ( "0" | "1" | "2" | "3" | "4" |


"5" | "6" | "7" | "8" | "9" )

TEXT

= <US-ASCII 32-126>

LWS

= *(NL|SP|HT)

SP

= <US-ASCII SP, space (32)>

NL

= <US-ASCII NL, linefeed (10)>

HT

= <US-ASCII HT, horizontal-tab (9)>

Il formato del data store Level-1 nel DFD in Figura 13 il seguente:


GGen Files = *GGen_File

Ogni GGen file risulta quindi essere composto da tre campi, descritti dalle regole Vertexes, Edges
(opzionale) e GActs.
Il primo di tali campi specifica linsieme dei vertici del grain generator specificato nel GGen-file.
Come si pu vedere dalla regola label, le etichette che indentificano i vertici possono essere anche
stringhe di caratteri (vedi vertex-ID). Ovviamente, in quanto identificatori, i vertex-ID devono
essere diversi tra loro. other-params specifica il numero di altri parametri associati al
corrispondente vertice (ricordiamo che chiamiamo altro parametro un parametro che non sia la
durata, lampiezza, il tempo di attacco, o il pan). Se per un vertice other-params non viene
specificato, il numero di altri parametri di quel vertice 0.
Il campo Edges specifica linsieme degli archi e la funzione peso del grain generator definito nel
GGen-file. I due vertex-ID specificati in edge devono essere tra quelli specificati nel campo
Vertexes.
weight specifica il peso dell edge corrispondente: route-interval specifica la funzione che
determina lintervallo di percorrenza, e route-prob specifica la probabilit di percorrenza.
Ovviamente, le route-prob dei vari weight devono soddisfare la condizione per la quale la somma
delle probabilit di percorrenza degli archi uscenti da uno stesso vertice uguale a 1.
In route-interval, se viene specificato un interval, la funzione che determina lintervallo di
percorrenza una funzione costante, mentre se viene specificato "rand", la stessa funzione la
funzione casuale con spazio di probabilit uniforme nellintervallo [0,1]. Queste sono le uniche due
funzioni per la determinazione dellintervallo di percorrenza supportate. Si noti che se in un
interval non viene specificato una time-unit, lunit di misura considerata sar il millisecondo.
In route-prob pu essere specificata una probabilit (vedi la regola prob), o pu essere specificato
"auto": nel secondo caso, la probabilit di percorrenza verr determinata in modo automatico sulla
base della condizione per la quale la somma delle probabilit di percorrenza degli archi uscenti da
uno stesso vertice uguale a 1.
Se weight non specificato per un qualche edge, il peso dell edge "(rand,auto)".
Il campo GActs specifica linsieme di graph actant del grain generator definito nel GGen-file:
ciascun vertex-ID contenuto in tale campo deve essere uno tra quelli specificati nel campo
Vertexes. gact-number specifica il numero di graph actant posti sul vertice vertex-ID
corrispondente; se gact-number non specificato, si ritiene gact-number = "1", mentre i vertex29

ID nel campo Vertexes non specificati nel campo GActs hanno gact-number = "0". Se ci sono
due o pi vx-gacts con medesimo vertex-ID, il numero di graph actant associati a quel vertice
uguale alla somma dei gact-number di tali vx-gacts.

Il seguente un esempio di GGen File, che specifica il graph generator in Figura 5:


//----------------- MyGGen ----------------- //
Vertexes:
(5)

(1, other-params = 3), ( 3 ) , ,


(2,0), (4 ),
;

// - - - - - - - - - - - - - - - - - - - - - //
edges:

,
,

(1->2) --> (0.02, 0.2),


( 1 ->2)-->(0.021 ,0.700)
, , ,(1->3) --> (0,auto),
(2->2) --> (0.0001, 0.01),
(2->2) --> (0.001, auto) ,
( 4 -> 3 ) --> (0,auto
)
( 4 -> 4) --> (1, auto)
(5 -> 5) --> (0.020 , auto);

// _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ //
GaCtS:
1<-, 1<- , 4<-1 GAct, 5<-;
// N.B.: sul vertice 1 sono stati posti 2 gact;
//
si poteva anche scrivere 1<-2.
/////////////////// EOF ///////////////////////

Tutti i GGen-file devono essere contenuti nella directory Level_1 interna allapplicazione.
4.3.1.2 Control Space File
E il file di input che contiene la definizione di un control-space. Il suo formato il seguente:
Control_Space_File= [ LWS "Csound" ]
GGen-Set
Positions
[Start-Times]
SAct
Generator-Defs
[Trajectory]
*comment
GGen-Set

= *comment
"GGen-set:" 1#(GGen-filename [ggen-number]) LWS ";"

GGen-filename

= filename

filename

= <UNIX/Windows filename>

ggen-number

= LWS 1*DIGIT

Positions

= *comment
"Vertex-positions:" 1*GGen-position LWS ";"

GGen-position

= *comment
LWS GGen-ID ":" 1#vertex-position ";"

GGen-ID

= GGen-filename [ggen-index]

ggen-index

= "_" 1*DIGIT

30

vertex-position

= vertex-ID LWS "-->" LWS point

Start-Times

= *comment
"Start-times:" 1*GGen-times LWS ";"

GGen-times

= *comment
LWS GGen-ID ":" 1#GAct-time ";"

GAct-time

= GAct-ID LWS "-->" LWS interval

GAct-ID

= vertex-ID [Gact-index]

Gact-index

= "_" 1*DIGIT

SAct

= *comment
"SAct:"
*comment initial-position LWS ","
*comment speed LWS ","
*comment audio-radius LWS ";"

initial-position = ["initial-position" LWS "=" LWS] point


speed

= ["speed" LWS "=" LWS] decimal [speed-unit]

speed-unit

= space-unit "/" "s"

space-unit

= ["K" | "c"] "m"

audio-radius

= ["audibility-radius" LWS "=" LWS] decimal [space-unit]

Generator-Defs

= *comment
"Generator-Defs:" 1*GGen-generators LWS ";"

GGen-generators

= *comment
LWS GGen-ID ":" 1*vertex-generator
LWS ";"

vertex-generator = *comment
LWS vertex-ID ":"
duration
amplitude
pan
*other-param
duration

= LWS "duration" LWS "=" LWS


( ( (pan-funct | rand-funct) domain-restrictn )
| dur-const | dist-funct ) LWS ";"

domain-restrictn = LWS [SP "domain" LWS "=" LWS]


"[" LWS interval LWS "," LWS interval LWS "]"
dur-const

= ["constant" LWS "=" LWS] interval

amplitude

= LWS "amplitude" LWS "=" LWS generator LWS ";"

pan

= LWS "pan" LWS "=" LWS generator LWS ";"

other-param = LWS other-param-ID LWS "=" LWS generator LWS ";"


other-param-ID

= ("other-param_" | "op_") other-param-index


; la numerazione degli other-param inizia da zero

other-param-index = 1*DIGIT
generator

= constant | pan-funct | rand-funct | dist-funct

constant

= ["constant" LWS "=" LWS] ["+"|"-"] decimal

pan-funct

= "pan-function"

rand-funct

= "random-function"

dist-funct

= 2#funct-couple

Trajectory

= *comment
"Trajectory:" 2#point ";"

point

= "(" LWS decimal [LWS space-unit] LWS ","


LWS decimal [LWS space-unit] LWS ")"

funct-couple

= "(" LWS X LWS "," LWS f(X) LWS ")"

31

= ( (decimal [LWS space-unit])|"audibility-radius"|"r" )

f(X)

= ( ["+"|"-"] decimal | interval )

Ogni Control Space file risulta quindi essere composto da sei campi, descritti dalle regole GGenSet, Positions, Start-Times (opzionale), SAct, Generator-Defs, e Trajectory (opzionale).
Prima di tali campi pu essere specificata la parola chiave "Csound", che avverte il sistema che
deve essere generato un Csound-score, cio uno score specifico per Csound, il cui formato dato
oltre.
Il campo GGen-Set specifica linsieme di grain generator del control space specificato dal Control
Space file. ggen-number specifica il numero di istanze del (tipo di) grain generator definito nel file
GGen-filename; se ggen-number non specificato, il grain generator verr istanziato una sola
volta, ovvero ggen-number = "1". Se viene ripetuto pi volte uno stesso GGen-filename, il
corrispondente ggen-number sar la somma dei ggen-number specificati nelle varie ripetizioni.
Prima di affrontare i restanti campi, diciamo che GGen-ID identifica una delle istanze di grain
generator contenute in GGen-Set: ggen-index specifica il numero dellistanza del grain generator
speficato nel file GGen-filename. Se il grain generator definito nel file "MyGGen" (vedi lesempio
di sopra) viene istanziato 2 volte in uno stesso control space, la prima istanza identificata dal
GGen-ID "MyGGen_0", la seconda da "MyGGen_1". Se ggen-index non viene specificato viene
considerata la prima istanza, ovvero ggen-index = "_0".
Il campo Positions specifica la funzione posizione del control space specificato dal Control Space
file. I GGen-ID specificati in 1*GGen-position devono riferirsi a tutti e solo i grain generator
istanziati nel control space (secondo quanto specificato nel campo GGen-Set). Ovviamente, occorre
specificare una ed una sola vertex-position per ogni vertice di ogni grain generator istanziato nel
control space.
Il campo Start-Times specifica la funzione di avvio del control space specificato dal Control
Space file. Se tale campo mancante, la funzione di avvio costante a 0. GAct-ID identifica i graph
actant in modo analogo a come GGen-ID identifica i grain generator istanziati in un control space. I
grain generator o i graph actant per i quali non stato specificato espressamente un tempo di avvio
avranno tempo di avvio uguale a 0.
Il campo SAct specifica lo space actant del control space specificato dal Control Space file: in
particolare, initial-position specifica la posizione iniziale dellSAct, audio-radius specifica il
raggio di udibilit dellSAct, e speed specifica la velocit di navigazione dellSact. Questultima
deve rispettare la condizione secondo la quale se la traiettoria nulla (cio, priva di vettori
spostamento), allora lSAct immobile (cio, ha velocit nulla).
Il campo Generator-Defs specifica la funzione di definizione dei generatori di eveni del control
space specificato dal Control Space file. I GGen-ID specificati in 1*GGen-generators devono
riferirsi a tutti e solo i grain generator istanziati nel control space (secondo quanto specificato nel
campo GGen-Set). In ciascun GGen-generators occorre specificare uno ed un solo vertexgenerator per ogni vertice di ciascun grain generator istanziato nel control space. vertexgenerator specifica il generatore di eventi del vertice identificato dal vertex-ID. In ciascun
vertex-generator, duration, amplitude, pan e *other-param specificano un generatore di
parametro rispettivamente per i parametri di durata, ampiezza, pan e i restanti parametri associati al
vertice. Questi ultimi (gli altri parametri) sono identificati da other-param-ID, e devono essere
specificati in ordine crescente rispetto all other-param-index (analogamente a ggen-index e
Gact-index, other-param-index parte da 0).
In domain-restrictn il primo interval deve essere minore o uguale al secondo interval.
In pan, se il generator di tipo constant, la costante specificata deve essere compresa in modo
non stretto tra -1 e 1; se il generator di tipo dist-funct, i valori acquistati da tale funzione
devono appartenere allintervallo [-1, 1].
32

In amplitude e in other-param, se il generator di tipo constant, la costante specificata deve


essere compresa in modo non stretto tra 0 e 1; se il generator di tipo dist-funct, i valori
acquistati da tale funzione devono appartenere allintervallo [0, 1].
Se allinizio del Control-Space file specificata la parola chiave "Csound", il primo other-param,
se esiste, viene usato per identificare lo strumento usato da Csound per produrre gli eventi generati
dal vertice a cui appartiene quel parametro; se il vertice privo di altri parametri (oltre al tempo di
attacco, alla durata, allampiezza e al pan), per ogni grano generato da quel vertice lo strumento
specificato nello score "i1". Se allinizio del Control-Space file specificata la parola chiave
"Csound", il generator specificato per "other-param_0" ( o "hp_0") deve quindi essere di tipo
costante (constant): se la costante specificata un numero decimale, ne verr considerata solo la
parte intera. Se allinizio del Control-Space file specificata la parola chiave "Csound", e il
generator specificato per "other-param_0" ( o "hp_0") non di tipo costante (constant), per
ogni grano generato da quel vertice, lo strumento specificato nello score "i1".
In dist-funct la prima funct-couple deve essere del tipo "(0," f(X)")" , e lultima functcouple deve essere del tipo "(audibility-radius," f(X)")". Inoltre, le funct-couple devono
essere diverse tra loro e in ordine crescente rispetto a X (il primo valore delle coppie).
Il seguente un esempio di Control Space File, che specifica il control space in Figura 7:
//----------------------------- MyCS ------------------------- //
ggen-set: MyGGen 1 ;
vertex-positions:
MyGGen_0:
// si poteva anche scrivere "MyGGen:"
1 --> (1.5,2), 2 --> (3,2),
3 --> (1.5,1), 4 --> (3,1),
, 5 --> (4.5,1.5);
start-times:
MyGGen:

sact:

1_0 --> 2 sec


1_1 --> 2.1sec
4_0 --> 1.5 sec
5 --> 0

initial-position = (4.5 m, 2 m),


speed = 1 m/s
audibility-radius = 1 m

generator-defs:
MyGGen:

1:
duration = pan-function domain=[1.618,1.618sec];
amplitude = random ;
pan = (0,0), (0.025 ,1), (0.05,0),
(0.075 ,-1), (0.1,0);
other-param_1 = random;
op2 = (0.0,0), (0.1cm,1) ;
op3 = pan ;
2:
duration = random [1.618,1.618sec];
amplitude = (0,1), (r,0) ;
pan = pan-function;
3:
duration = (0,1.618centisec), (r,1.618sec);
amplitude = constant = 0.1618;
pan = random;
4:
duration = 1.618 microsec;
amplitude = (0,0), (r,1) ;

33

pan = pan-function;

5:

duration = random [161.8,200];


amplitude = (0,1), (r,0) ;
pan = 0;

trajectory : (4.1,2), (3.5,1.5), (0.5,1), (1.5,2.5), (3,3), ;


///////////////////////////////// EOF
//////////////////////////////

Tutti i Control-Space file devono essere contenuti nella directory Level_2 interna allapplicazione.
4.3.1.3 Score File
E il file di output che contiene i grani generati dal sistema. Il suo formato il seguente:
Score File

= ( Generic-Score | Csound-Score )

Generic-Score = *generic-grain
Csound-Score

= *csound-grain

generic-grain = attack-time SP dur-value SP ampl-value SP pan-value SP


distance SP angle other-values NL
csound-grain

= instrument-ID SP attack-time SP dur-value SP ampl-value


SP pan-value SP distance SP angle *(SP other-value) NL

instrument-ID = "i" 1*DIGIT


; identifica lo strumento usato da Csound per emettere il
; grano
attack-time = decimal
dur-value

= decimal

ampl-value

= "1" | "0" ["." 1*DIGIT]

pan-value

= ["+"|"-"] ("1" | "0" ["." 1*DIGIT])

distance

= decimal

angle

= decimal

; angle 2*

other-values = *(SP other-value)


other-value = "1" | "0" ["." 1*DIGIT]

Uno Score File pu essere o un Generic-Score o un Csound-Score. In entrambi i casi, ciascuna


linea di testo descrive un singolo grano, e contiene una sequenza di valori decimali separati da uno
spazio, che specificano i parametri del grano descritto. Tali valori (attack-time, dur-value,
ampl-value, pan-value, distance, angle, e other-values) specificano, rispettivamente, il
tempo di attacco, la durata, lampiezza donda, il pan, la distanza tra la posizione attuale dello space
actant e la posizione del vertice generante il grano, langolo di orientamento dello space actant, gli
altri parametri. Si noti che nessun ordine imposto sulle linee di testo del file (sui grani).
Nello Score File di tipo Csound-Score, allinizio di ogni linea di testo aggiunto l instrumentID, che specifica lo strumento usato da Csound per emettere il grano descritto dalla linea di testo
stessa.
Il seguente un esempio di Score File, che specifica un possibile score (rappresentato in Figura 10)
generato dal control space in Figura 7 definito dal Control Space File MyCS (vedi il precedente
esempio di Control Space File):
0 0.1700 0.6537 0 0.500 0.791
0.020 0.1982 0.5720 0 0.473 1.032
0.020 0.1699 0.6641 0 0.519 3.275
1.423 0.0235 0.7754 -0.001 0.356 3.141

34

1.020 0.0099 0.6643 -1 0.519 3.275


...
10.467 0.0016 0.2071 -0.720 0.8 3.141
0.027 0.1611 0.6641 -1 0.519 3.275
32.001 0.0253 0.5740 0.725 0.475 1.032
30.986 0.0344 0.7754 -0.001 0.356 3.141

4.3.1.4 Error Messages


Come minimo, il sistema deve supportare i seguenti messaggi derrore (la numerazione data non
deve essere necessariamente seguita):
Error 1:Control-Space file filename does not exist
Error 2:Control-Space file filename has error
Error 2.1:syntax error in (row: 1*DIGIT, column: 1*DIGIT)
Error 2.2:GGen-set has error
Error 2.2.1:any grain generator has been declared into the GGen-Set
Error 2.3:vertex-positions has error
Error 2.3.1:not all the grain generators in the GGen-Set have been positioned in the field

Vertex-Positions

Error 2.3.2:the grain generator GGen-ID in the field Vertex-Positions doesn't refer to a

grain generator contained in the GGen-Set field

Error 2.3.3:the vertex vertex-ID doesn'tbelong to the grain generator GGen-ID

specified in the field Vertex-Positions

Error 2.3.4:not all the vertexes of the grain generator GGen-ID appear in the field Vertex-

Positions

Error 2.4:start-times has error


Error 2.4.1:the grain generator GGen-ID in the field Start-Times doesn'trefer to a grain

generator contained in the GGen-Set

Error 2.4.2:the graph actant Gact-ID doesn't belong to the grain generatorGGen-ID
Error 2.4.3:the graph actant Gact-ID reports to a not existent vertex in the grain
generator GGen-ID specified in the field Start-Times
Error 2.5:generator-defs has error
Error 2.5.1:not all the grain generators in the GGen-Set have been declared in the field

Generator-Defs

Error 2.5.2:the grain generator GGen-ID in the field Generator-Defs doesn'trefer to a

grain generator contained in the GGen-Set

Error 2.5.3:the vertex vertex-ID doesn'tbelong to the grain generator GGen-ID

specified in the field Generator-Defs

Error 2.5.4:not all the vertexes of the grain generator GGen-ID appear in the field

Generator-Defs

Error 2.5.5:the other-param other-param-ID specified in the field Generator-Defs


doesn't belong to the vertexvertex-ID of the grain generator GGen-ID
Error 2.5.6:in the filed Generator-Defs, a generator has not been defined for all the otherparams of the vertex vertex-ID of the grain generator GGen-ID

35

Error 2.5.7:the amplitude constant generator in (row: 1*DIGIT, column: 1*DIGIT) has to

be inclusive among 0 and 1

Error 2.5.8:the pan constant generator in (row: 1*DIGIT, column: 1*DIGIT) has to be

inclusive among -1 and 1

Error 2.5.9:the other-parameter generators must be define in increasing order in


comparison to their indexes: the other-parameter generator other-param-ID in (row:
1*DIGIT, column: 1*DIGIT) doesn't respect this order
Error 2.5.10:the other-parameter constant generator other-param-ID in (row: 1*DIGIT,
column: 1*DIGIT) has to be inclusive among 0 and 1
Error 2.5.11:the domain of the distance-functions is the closed and limited interval
[0,audibility-radius]: the x=1*DIGIT of the couple (x, y) specified in (row: 1*DIGIT,
column: 1*DIGIT) is out of such domain
Error 2.5.12:the couple (1*DIGIT, 1*DIGIT) specified in (row: 1*DIGIT, column:
1*DIGIT) is out of the distance function image-set
Error 2.5.13:the function couples (x,y) have to be in increasing order in comparison to x:
this error occur in (row: 1*DIGIT, column: 1*DIGIT)
Error 2.5.14:at least two couples must be specify for every distance function: this error
occur in (row: 1*DIGIT, column: 1*DIGIT) Ci sono almeno due coppie funct-point
Error 2.5.15:the first couple (x,y) of every distance function has to have x = 0: this error
occur in (row: 1*DIGIT, column: 1*DIGIT)
Error 2.5.16:the last couple (x,y) of every distance function has to have y = audibilityradius: this error occur in (row: 1*DIGIT, column: 1*DIGIT)
Error 2.5.17:the domain restriction specified in (row: 1*DIGIT, column: 1*DIGIT) is

wrong

Error 2.6:Trajectory has error


Error 2.6.1:the first point of the trajectory has to be equal to the initial position of the

sact

Error 2.6.2:if the trajectory exists, at least two points must be specifies for it
Error 3:the GGen file filename has error
Error 3.1:syntax error in the GGen file GGen-filename at (row: 1*DIGIT, column: 1*DIGIT)
Error 3.2:the field edges has error
Error 3.3:the probability 1*DIGIT specified in the GGen file GGen-filename at (row:
1*DIGIT, column: 1*DIGIT) is great of 1
Error 3.4:the sum of the probabilities of the arcs outgoing from the vertex vertex-ID in the
GGen file GGen-filename is great of 1
Error 3.5:the gact in GGen file GGen-filename at (row: 1*DIGIT, column: 1*DIGIT) has

been set in a vertex doesn't belong to the grain generator

Error 3.6:a grain generator cannot be defined devoid of gacts: such error occur in the GGen
file GGen-filename
Error 4:command error: the SAct is immovable. It is necessary to specify a performance-term

4.3.2

Functional Requirements

1. Generare uno score eseguendo il control space definito nel file specificato dallutente.
36

Input: Control Space File e uno o pi GGen File


Output: Score File
2. Deve essere verificata la validit dei dati nei file di input, controllando anche la consistenza
tra i graph-generator contenuti nel Control Space File e le loro definizioni contenute nei
rispettivi GGen File. Il sistema deve notificare allutente la presenza di input non corretti.
Qualunque input errato interrompe lesecuzione del sistema.
Input: Control Space File e uno o pi GGen File
Output: Error Messages
4.3.3

External Interface Requirements

4.3.3.1 User Interface: E richiesto soltanto un comando utente, il cui formato il seguente:
Command_Line

= "GoeGraphy" *SP CS-name *SP [performance-term]

CS-name
= filename
performance-term = interval ; se time-unit non specificato sono min
CS-name specifica il Control-Space file nel quale definito il control space che si vuole eseguire.
performance-term specifica la durata di tempo di tale esecuzione. Questultimo parametro

necessario se lSAct immobile.


Lo Score file generato avr lo stesso nome del Control Space file specificato (cio CS-name), e sar
contenuto nella directory Scores interna allapplicazione.
4.3.4

Design Contraints

4.3.4.1 Software Constraints


Il sistema deve girare sotto sistemi operativi UNIX-based e Windows.
4.3.4.2 Hardware Constraints
Nessun limite particolare stato imposto.

37

5Object Oriented Design


In questo capitolo effettuiamo la progettazione orientata agli oggetti del caso di studio proposto da
questa tesi. La metodologia di progettazione usata la OMT (Object Modeling Technique) [25].
I vari paragrafi del capitolo descrivono brevemente le varie fasi dellattivit di design: prima viene
discussa lapplicazione del processo di progettazione sul caso di studio, cio come viene creato il
progetto per il caso di studio, e poi data la progettazione di dettaglio, specificando gli algoritmi
concettuali o le formule per il calcolo delle principali funzioni delle principali classi identificate
nella fase di design. La specifica del progetto finale data nellappendice.

5.1 Object Modeling


Lobject model del sistema gi stato costruito in fase analisi (vedi il capitolo 2), ed rappresentato
in Figura 12.

5.2 Dynamic Modeling


Il nostro sistema non un sistema interattivo, quindi il dynamic modeling piuttosto lineare, e non
ci dice niente di nuovo sul comportamento dinamico del sistema, che gi supportato dallobject
model.
Lunico scenario normale quello in cui, per gli input dati, il sistema effettua la normale esecuzione
generando uno score. Tale scenario non rivela alcuna nuova operazione.
Ci sono pi scenari di eccezione, uno per ogni possibile errore nellinput. In ogni caso, ciascuno di
tali scenari mostra che il sistema deve dare in output un opportuno messaggio di errore. Come sar
pi chiaro durante il functional modeling, occorrer introdurre una nuova object-class al modello,
che si preoccupi di fare unanalisi sintattica e di validare i file di input.

5.3 Functional Modeling


Come specificato nel documento di specifica dei requisiti (capitolo 4), e come gi visto nel
diagramma di contesto in Figura 13, gli input principali del sistema sono: il Control-Space-file e i
GGen-file. A parte i messaggi derrore, loutput principale lo Score generato dallesecuzione del
control space descritto nel Control-Space file.
Il functional model del sistema rappresentato dal DFD in Figura 14. Per prima cosa viene fatta
unanalisi sintattica del Control Space File rispetto al formato definito per esso nel documento di
specifica dei requisiti (capitolo 4): tale funzionalit espressa dal data process Parsing Control Space
File. I dati contenuti nel Control Space File vengono quindi separati in tre flussi di dati: il primo
(rispetto allordine in cui compare nel Control Space File) GGen-Set, nel quale sappiamo esserci la
lista dei nomi dei GGen_File che descrivono i graph generator da caricare nel control space. Get
GGen Files recupera tali file (GGen_File 1 + GGen_File 2 + + GGen_File n) dal data store Level-1 (la
directory che contiene i GGen-file), rispetto a quanto specificato in GGen-Set. Parsing GGen File
verifica la correttezza sintattica di ciascun GGen_File rispetto alla grammatica data per i GGen-file
nel documento di specifica dei requisiti. Validate CS-File verifica la consistenza di ciascun GGen_File
con il secondo flusso uscente da Parsing Control Space File, Positions + Start-times + Generator-Defs +
audio-radius, e, sulla base di tali input, costruisce le strutture dati (Ggen_struct 1, , Ggen_struct n)
che mantengono le info che descrivono i graph generator da caricare nel control space, e dotate
delle informazioni date dai flussi Positions + Start-times + Generator-Defs. Il terzo flusso uscente da
Parsing Control Space File SAct+Trajectory: esso viene processato (da Build SAct and Trajectory) al
fine di costruire loggetto (Trajectory_obj) che mantiene lo space actant (descritto dallinput SAct) e
la traiettoria (descritta dallinput Trajectory). In modo analogo Build GGens and compute Activation
38

Intervals costruisce gli oggetti GGen_obj 1, , GGen_obj n, rispettivamente sulla base delle strutture
dati Ggen_struct 1, , Ggen_struct n in input; inoltre, sulla base dello stato delloggetto
Trajectory_obj, Build GGens and compute Activation Intervals calcola gli intervalli di attivazione di
ciascun vertice di ciascun GGen_obj. Lultimo processo, Perform Control-Space, avvia il processo di
generazione dei Grains a Livello-2, ovvero lesecuzione del control space: tale processo perdura fino
allo scadere del performance-term (input necessario se lSAct immobile), se tale input stato
fornito dallentit User (lutente). I Grains generati vengono memorizzati dal data store Score,

loutput del sistema.


Control Space File

User
Parsing
Control Space
File

SAct + Trajectory
Build SAct
and Trajectory

performance-term

Trajectory_obj
Positions +
Start-times +
Generator-Defs +
audio-radius

GGen-Set

*
Trajectory_obj

Perform
Control-Space
GGen_obj 1

GGen_File 1

GGen_File 1

Get
GGen Files

GGen_File 2

*
*

GGen_File n

Parsing
GGen File

GGen_File 2

*
GGen_File n

Validate CS-File

Ggen_struct 2

GGen_obj 2

Ggen_struct 1

Build Ggens
and compute
Activation
Intervals

Ggen_struct n

Grains

GGen_obj n

Score

GGen_File 1 +
GGen_File 2 +
+ GGen_File n
Level-1

Figura 14: Data flow diagram che rappresenta il functional model del sistema.

Il functional model fin qua descritto mostra, prima, come il Control-Space file e i vari GGen file
debbano essere analizzati singolarmente, poi, come debba essere verificata la consistenza tra il
Control-Space-file e i vari GGen-file. Come gi accennato nel dynamic modeling, aggiungiamo una
nuova object-class al modello che supporti tali funzionalit di controllo sugli input: tale classe la
chiamiamo Validator; essa offre quindi il servizio validateInputFiles( ), che realizza le funzionalit
espresse dai data process Parsing Control Space File, Get GGen Files, Parsing GGen File, e Validate CSFile.
Il functional model mostra anche la necessit di introdurre operazioni per la costruzione degli
oggetti: aggiungiamo quindi un servizio per tale funzionalit ad ogni classe che deve essere
costruita sulla base delle informazioni contenute nei file di input al sistema. Tali classi sono quindi
le seguenti: ControlSpace, Trajectory, ShiftingVector, GGen, Vertex, Edge, GAct, OtherParam, Pan,
Duration, Amplitude, DistFunct, e Grain. Il nome di tale servizio sar della forma buildclassName( ).
Linput di tale servizio varia al variare della classe che lo offre, ma in generale una opportuna
struttura dati intermedia, costruita dal Validator durante loperazione di validazione degli input.
Le operazioni per il calcolo degli intervalli di attivazione e per lesecuzione del control space sono
gi state valutate durante lobject modeling.
39

5.4 Implementation Concerns


Iniziamo dalla classe Validator: per essa occorrer definire una struttra dati che contenga tutte le
informazioni specificate sia nel Control Space file, sia nei vari GGen file. Tale struttura, che
chiamiamo CtrlSpace_File, specificata nellappendice, ed privata alloggetto Validator, cio non
accessibile direttamente da parte degli altri oggetti. Il servizio validateInputFiles( ) sopra introdotto,
riempie la struttura CtrlSpace_File man mano che va avanti nella lettura dei file, ma non restituisce la
struttura costruita, dal momento che essa sostanzialmente mantiene le informanzioni nello stesso
ordine in cui sono specificate nei file di input. Il servizio buildControlSpace( ) non si serve quindi
della struttura CtrlSpace_File per costruire il ControlSpace, ma si serve di unaltra struttura, che
chiamiamo CS_Struct, che mantiene le stesse info contenute in CtrlSpace_File in un ordine pi
agevole per buildControlSpace( ) (anche questa struttura specificata nellappendice). Aggiungiamo
quindi un altro servizio a Validator, getCSstruct( ), che restituisce al chiamante una CS_Struct. Le
informazioni in CtrlSpace_File non dovranno essere copiate in CS_Struct, ma si sfrutteranno i
puntatori, al fine di limitare i tempi di riordinamento e la memoria usata.
Ad esclusione dellaggregazione tra Score e Grain, e dellaggregazione tra Vertex e
ActivationInterval, implementiamo ciascuna relazione di aggregazione con molteplicit 0:N (o
1:N) con un vettore (allocato dinamicamente, ovviamente). A ciascuna classe contenente un tale
vettore occorre aggiungere un attributo per mantenere la lunghezza del vettore stesso. Inoltre, a tutte
le object-class che devono offrire un servizio per accedere ad un vettore in esse contenute,
aggiungiamo, oltre alloperazione di accesso al vettore, un operazione per resettare il puntatore al
vettore (spostato ogni volta che un oggetto cliente accede al vettore per mezzo delloperazione
accesso allo stesso vettore).
Lo Score viene invece implementato come una lista di grani.
Invece di modellare un singolo intervallo di attivazione con lobject-class ActivationInterval,
modelliamo linseme di intervalli di attivazione di un vertice con lobject-class
ActivationIntervals: c quindi unaggregazione, con
molteplicit 1:1, tra Vertex e
ActivationIntervals; ActivationIntervals mantiene dentro di se una lista (privata) di
intervalli di attivazione, che implementiamo con la struttura ActivationList (specificata
nellappendice).

5.5 Detailed Design


Di seguito sono specificati gli algoritmi concettuali o le formule per il calcolo delle principali
funzioni delle principali classi identificate nella fase di design. Gli algoritmi sono dati in Process
Design Language (PDL) [15]:337-340.

40

5.5.1

GAct

Algoritmo 1
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.

start(Trajectory, performanceTerm )
Vertex
Edge
Grain
Float

actualVertex := vertice su cui inizialmente posto il GAct ;


edge ;
grain ;
time := startTime ;

DO WHILE ( time < performanceTerm )


IF ( il vertice actualVertex attivo al tempo time ) THEN
grain := grano generato dal vertice vertex al tempo time;
aggiungi grain allo Score globale ;
edge := un arco a caso uscente da vertex secondo la distribuzione di probabilit ;
IF ( non c nessun arco che parte dal vertice vertex ) THEN esci ;
actualVertex := vertice verso cui diretto edge ;
incrementa time della temporalDistance del peso di edge ;
ENDDO
END

5.5.2 Shifting Vector


I parametri di isAudiblePoint( ) sono: un punto (x0,y0) e il valore dell audibilityRadius (attributo
della Trajectory).
isAudiblePoint( ) ritorna:

TRUE, se (x0,y0) un punto interno (bordo compreso) allintorno dello ShiftingVector


rappresentato in Figura 15;

FALSE, altrimenti.

audibilityRa

Punti udibili

Figura 15: Intorno dello ShiftingVector allinterno del


quale i punti sono udibili dallSAct.

41

In altri termini, isAudiblePoint( ) ritorna il valore della seguente espressione booleana:


(C audibilityRadius) [(x1x0x2) (y1y0y2)
( d((x0,y0),(x1,y1)) audibilityRadius )
( d((x0,y0),(x2,y2)) audibilityRadius )]
, dove (x0,y0) il punto preso in input, (x1,y1), (x2,y2) sono gli estremi dello
ShiftingVector (tail, head), d(P,Q) la distanza tra i punti P, Q, e C il numero definito di
seguito:

C =

ax0+by0+c/(a2+b2)
y0-y1 (= y0-y2)

,se y1y2
,se y1=y2

x0-x1 = x0-x2

,se x0=x1

dove a, b, c sono i coefficienti della retta passante per i punti tail e head.
getActivationPoints( ) ha come parametri:
un punto (x0,y0);

il valore dell audibilityRadius (attributo della Trajectory).

getListeningPoints( ) ritorna:
i punti estremi del segmento allinterno dello ShiftingVector in cui lSAct pu sentire i
grani eventualmente generati nel punto (x0,y0) (il punto in input), ovvero ritorna i punti o
il singolo punto di intersezione tra la retta passante per i punti tail, head (attributi dello
ShiftingVector) e la circonferenza di centro (x0,y0) e di raggio audibilityRadius (come
rappresentato in Figura 16), se tali/e punti/o esistono/esiste;

NULL, altrimenti.

audibilityRadius
(x0,y0)

(x2,y2)

(x1,y1)

Figura 16: Significato geometrico di quanto calcolato da


getListeningPoints( ) per ottenere i punti estremi del segmento
allinterno dello ShiftingVector nel quale lSAct pu sentire i
grani generati nel punto (x0,y0): nel caso in figura, tali punti
sono (x1,y1) e il punto head dello ShiftingVector.

42

getListeningPoints( ) deve quindi:


1) Risolvere il seguente sistema, ottenendo i punti o il punto di intersezione, se tali/e punti/o esistono/esiste:
(xx0)2+(yy0)2 = audibilityRadius2
ax+by+c = 0
dove a, b, c sono i coefficienti della retta passante per i punti tail e head; ovvero:
x2+y2+x+y+ = 0

dove :

ax+by+c = 0

= -2x0 ;
= -2y0 ;
= (x0)2+(y0)2(audibilityRadius)2 .

Le soluzioni del sistema sono le seguenti :

x1,2 = -(by1,2 +c)/a


y1,2 = [-(2bcab+a2) ]/2(a2+b2)

dove = (2bcab+a2)2-4(a2+b2)(c2-ac+a2).
Ovviamente,
se >0 ci sono due punti di intersezione (x1,y1), (x2,y2);
se =0 c un solo punto di intersezione (x1,y1);
se <0 non c nessun punto di intersezione, e quindi getListeningPoints( ) ritorna
NULL.
Verificare attraverso il servizio isMyPoint( ) offerto da ShiftingVector se il punto o i punti
determinati al passo precedente appartengono o meno allo stesso ShiftingVector. I casi possibili
sono presentati in Figura 17: saranno ritornati solo i punti in rosso.
getPointToLength( ) prende in input una lunghezza L, e ritorna:
il punto appartenente allo ShiftingVector e che dista L da tail dello stesso vettore, se L0 e
L minore o uguale alla lunghezza del vettore.
NULL, altrimenti.
Supponendo che L sia positivo e minore o uguale alla lunghezza dello ShiftingVector, per ottenere
il corretto risultato da ritornare, getPointToLength( ) deve:
1) risolvere il seguente sistema, il cui significato geometrico dato in Figura 18:

audibilityRadius

audibilityRadius
(x0,y0)

(x ,y )

(x2,y2)

(x0,y0)

(x ,y )

(x2,y2)

43

Caso 1

Caso 2

audibilityRadius
(x0,y0)

audibilityRadius
0

(x2,y2)

(x0,y0)

(x1,y1)

(x1,y1)

Caso 3

Caso 4

audibilityRadius
(x0,y0)

(x2,y2)

(x2,y2)

audibilityRadius
0

(x2,y2)

(x0,y0)

(x1,y1)

(x1,y1)

Caso 5

Caso 6

Figura 17: Possibili casi che la funzione getListeningPoints( ) deve valutare, nel caso
in cui i punti di intersezione calcolati dalla stessa sono due ((x1,y1), (x2,y2)).

(x2,y2)

L
(x0,y0)

(x1,y1)

Figura 18: Rappresentazione del significato geometrico del sistema risolto da


getPointToLength( ): i punti (x1,y1), (x2,y2) risultanti dal sistema sono i due
punti distanti L dal punto tail dello ShiftingVector e appartenenti alla retta che
passa per i due estremi dello stesso ShiftingVector.

(xx0)2+(yy0)2 = L2
aX+by+c = 0
44

dove a, b, c sono i coefficienti della retta passante per i punti tail e head; ovvero,
x2+y2+x+y+ = 0
ax+by+c = 0
dove :

= -2x0 ;
= -2y0 ;
= (x0)2+(y0)2(L)2 .

Le soluzioni del sistema sono le seguenti :


x1,2 = -(by1,2 +c)/a

y1,2 = [-(2bcab+a2) ]/2(a2+b2)


, dove = (2bcab+a2)2-4(a2+b2)(c2-ac+a2).
Ovviamente, il discriminante sempre e solo >0, perch, come si vede in Figura 18, la
retta ax+by+c=0 passa per il punto tail, che il centro della circonferenza
x2+y2+x+y+=0. Le soluzioni del sistema sono quindi sempre e solo due punti
(x1,y1), (x2,y2).
2) Ritornare:
(x1,y1), se (x1,y1) un punto dello ShiftingVector
(x2,y2), altrimenti.
isMyPoint( ) ha come parametro un punto (x0,y0), e ritorna:
TRUE, se (x0,y0) un punto appartenente allo ShiftingVector;

FALSE, altrimenti.

Per ottenere il corretto risultato da ritornare, isMyPoint( ) deve:


1. Verificare se il punto (x0,y0) in input appartiene alla retta passante per gli estremi dello
ShiftingVector, ovvero deve verificare se ax0+by0+c = 0, dove a, b, c sono i coefficienti
della retta passante per i punti tail e head.
2. Ritornare il valore della seguente espressione booleana:
Siano tail=(x1,y1), head=(x2,y2), e (x0,y0) il punto in input; lespressione da
valutare :
[(x1<x2)(y1y2)(x1x0x2)(y1y0y2)]
[(x1>x2)(y1y2)(x2x0x1)(y2y0y1)]
[(x1<x2)(y1y2)(x1x0x2)(y2y0y1)]
[(x1>x2)(y1y2)(x2x0x1)(y1y0y2)] .

45

5.5.3

Trajectory

Algoritmo 2
1.

2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.

getInstantToPoint( Point )

/* -----------------------------------------------------------------------------------------------------------------Post.: ritorna -1, se lSAct immobile o se point non appartiene alla traiettoria
ritorna il tempo che impiega l'SAct a raggiungere Point, altrimenti
------------------------------------------------------------------------------------------------------------------ */

INTEGER
FLOAT

i := 0 ;

length := 0;

IF ( lSAct immobile ) THEN return 1 ;


DO FOR ogni ShiftingVector della traiettoria
IF (Point non un punto dello ShiftingVector considerato)
incrementa length della lunghezza dello ShiftingVector considerato
ELSE
Esci dal FOR
ENDDO
IF ( hai valutato tutti gli ShiftingVector ) THEN return 1 ;
ELSE
END

length := length + lunghezza tra tail dell i-esimo ShiftingVector e Ponit ;


return length / speed ;

Algoritmo 3
1.
2.
3.
4.
5.
6.
7.
8.
9.

getSActActualPosition( instant )
FLOAT
SHIFTINGVECTOR s

IF ( lSAct immobile ) THEN return ( SActInitialPoint, NULL) ;


ELSE

10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.

totalPathLength, partialPathLength := 0

totalPathLength := lunghezza percorsa dallSAct tra listante di avvio e instant,


cio instant * speed ;
DO WHILE ( partialPathLength < totalPathLength )
incrementa partialPathLength della lunghezza del prossimo
ShiftingVector ;
ENDDO

s := ultimo ShiftingVector considerato


IF ( partialPathLength = totalPathLength ) THEN
return ( testa di s, s )

END

ELSE // partialPathLength > totalPathLength


return ( s.getPointToLength( totalPathLength +
(partialPathLength s.getLength( )) ), s );

Analizziamo ora getAngle( ). I suoi input sono: un istante di tempo t e un punto (x0,y0).

46

Attraverso la funzione getSActActualPosition( ) offerto dalla stessa Trajectory, si ricava il punto


(x1,y1) in cui lSAct allistante t.
Come si pu vedere in Figura 19, getAngle( ) ha quindi a disposizione i seguenti quattro punti:
1. (x0,y0), il punto in cui il vertice-attivo;
2. (x1,y1), il punto in cui lSAct;
3. (x2,y2), la coda del vettore-spostamento;
4. (x3,y3), la testa del vettore-spostamento.
Y

(x3,y3)
vertexPosition

(x0,y0)

(x1,y1)

SAct

(x2,y2)

Figura 19: rappresentazione grafica di una possibile configurazione sulla quale


calcolare langolo (definizione 12). D la distanza tra il punto in cui lSAct
e il punto (x0,y0) passato in input.
Sia (-/2,/2] langolo tra una generica retta t parallela al vettore-spostamento considerato e lasse delle ascisse; definito da:

arctg(m) ,se x2x3 (t non verticale)


/2

,se x2=x3 (t verticale)

dove m il coefficiente angolare della retta t, ovvero:

m = -[a/b] ,dove a=(y2-y3), b=(x3-x2).


(N.B.: per definizione di coefficiente angolare, m=tg())
Sia s la semiretta uscente dal punto (x1,y1), parallela allasse delle ascisse,
e che si estende nel verso positivo di tale asse.
Sia (0,2] langolo descritto in senso antiorario dalla semiretta s per sovrapporsi al segmento con estremi in (x1,y1),(x0,y0);
quindi cos definito:

arctg(m)
/2
+arctg(m)

+arctg(m)
(3/2)
2+arctg(m)
2

,se
,se
,se
,se
,se
,se
,se
,se

x0>x1
x0=x1
x0<x1
x0<x1
x0<x1
x0=x1
x0>x1
x0>x1

y0>y1
y0>y1
y0>y1
y0=y1
y0<y1
y0<y1
y0<y1
y0=y1

dove m il coefficiente angolare della retta passante per i punti


(x1,y1),(x0,y0), ovvero, m= -[(y1-y0)/(x1-x0)], con x1x0.

47

Definiamo quindi distinguendo i seguenti casi:


Se x2x3 y2<y3 (0,/2) 0<arctg(m)</2

, se

2-(-)

, se <

Se x2x3 y2>y3 (0,-/2) 0<arctg(m)<-/2

Se x2=x3

Se y2=y3

-(2+)

, se (2+)

, se <(2+)

=/2
-/2

, se

+(3/2)

, se <

, se <2

, se =2

=0
=

Se D=0 o lSAct immobile: in tal caso = 0.

48

5.5.4

Vertex

Algoritmo 4
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.

computeActivationIntervals ( Trajectory )
IF ( LSAct immobile ) THEN
IF ( il csPoint un punto udibile dallSAct ) THEN
alwaysActive := TRUE;
ELSE

DO FOR ogni shiftingVector contenuto nella Trajectory in input


IF ( il csPoint un punto udibile dallSAct almeno
in uno dei punti dello ShiftingVector considerato ) THEN

11.
12.

ottieni i punti estremi di attivazione


dal servizio getActivationPoints( ) dello ShiftingVector;

13.

trasforma attraverso il servizio getInstantToPoint( ) della Trajectory tali punti


negli istanti estremi dellintervallo di attivazione ;

14.
15.
16.
17.

inserisci lintervallo ottenuto nellactivationIntervals contenuto nel Vertex;


END

ENDDO

5.6 Conclusioni
In questo capitolo abbiamo visto la progettazione object oriented del caso di studio proposto da
questa tesi, adottando la metodologia di progettazione OMT (Object Modeling Technique) [25].
Nei vari paragrafi del capitolo sono state descritte brevemente le varie fasi dellattivit di design:
object modeling, dynamic modeling, functional modeling, implementation concerns, e detailed
design.

49

6Conclusioni
In questa tesi stato presentato un sistema formale (GeoGraphy) alternativo ai correnti approcci
alla composizione elettroacustica basata sulla sintesi granulare.
Rispetto alle tradizionali strategie per il controllo della sintesi granulare (vedi nellintroduzione
quelle proposte da Xenakis, Truax e Roads), GeoGraphy d una nuova prospettiva al processo di
composizione, andando a ricoprire i due principali approcci alla sintesi granulare, il note approach e
lo stochastic approach [30].
Attraverso i due livelli di Geography infatti possibile simulare entrambi gli approcci: il primo
livello permette di lavorare sugli oggetti sonori, realizzando un controllo sulla microstruttura,
nonch sulla ministruttura della composizione [32]; nel secondo livello, al contrario del primo, gi
insita una propria valenza formale a livello compositivo, pertanto esso definisce e realizza
chiaramente una strategia per il controllo della sintesi granulare.
Queste considerazioni, insieme alla forza compositiva, fanno di GeoGraphy unimplementazione
della sintesi granulare con un forte potere espressivo.
Per quanto riguarda lesperienza di lavoro di sviluppo del prototipo che implementa GeoGraphy, si
potuto osservare limportanza dellattivit di analisi, alla quale stata infatti dedicata la gran parte
del tempo. Nelle successive fasi (object modeling e progettazione) si cercato di modellare il
sistema, seguendo lapproccio orientato agli oggetti, con lo scopo di definire classi riutilizzabili in
una eventuale ulteriore esperienza di sviluppo: per fare questo, stata separata lelaborazione degli
input forniti dallutente dalle classi proprie di GeoGraphy (non della sua specifica
implementazione).

50

7Bibliografia
[1]

M. Bastiaans, Gabors expansion of a signals into Gaussian elementary signals,


Proceedings of the IEEE, 68: 538-539, 1980.

[2]

M. Bastiaans, On the sliding-window representation of signals, IEEE Transactions on


Acoustics, Speech, and Signal Processing, ASSP-33(4):868-873, 1985.

[3]

I. Beekman, Journal tenu par Issac Beekman de 1604 1634, four volumes, C. de Waard,
ed. 1953, The Hague, 1604-1634.

[4]

T. Berners-Lee, R. Fielding, H. Frystyk, Hypertext Transfer Protocol HTTP/1.0,


Request for Comments 1945, on-line: http://www.faqs.org/rfcs/rfc1945.html , May 1996.

[5]

P. Coad, E. Yourdon, Object-oriented analysis, Prentice Hall, Englewood Cliffs, New


Jersey, 1990.

[6]

P. Coad, E. Yourdon, Object-oriented design, Prentice Hall, Englewood Cliffs, New


Jersey, 1991.

[7]

E. Cohen, Quantifying Music, D. Reidel, Dordrecht, 1984.

[8]

T. H. Cormen, C. E. Leiserson, R. L. Rivest, Introduction to Algorithms, The MIT Press,


Cambridge (Mass.)-London, 2001.

[9]

M. A. Ellis, B. Stroustrup, The Annotated C++ References Manual, Addison-Wesley,


Reading, Massachusetts, 1990.

[10] D. Gabor, Theory of communication, Journal of the Institute of Electrical Engineers,


Part III, 93: 429-457, 1946.
[11] D. Gabor, Acoustical quanta and the theory of hearing, Nature, vol. 159, n. 1044: 591594, 1947.
[12] E. Giordani, Sintesi granulare per Csound, in R. Bianchini, A. Cipriani, Il Suono
Virtuale. Csound per PC e Mac. Teoria e Pratica, ConTempo, Roma, 1998.
[13] IEEE, Software Engineering Standards, IEEE Press, 1987.
[14] IEEE, IEEE Software Engineering Standards Collection, 1994 Edition, IEEE Press, 1994.
[15] P. Jalote, An Integrated Approach to Software Engineering, Second Edition, Springer,
New York, 1997.
[16] D. L. Jones, T. W. Parks, Generation and Combination of Grains for Music Synthesis,
Computer Music Journal, vol. 12, n. 2, 1988.
51

[17] B. W. Kernighan, D. M. Ritchie, The C Programming Language, Prentice Hall,


Englewood Cliffs, New Jersey, 1988.
[18] A. S.C. Lee, Granular Synthesis in Csound, in R. Boulanger, The Csound Book.
Perspectives in Software Synthesis, Sound Design, Signal Processing, and Programming,
The MIT Press, Cambridge (Mass.)-London, 1991.
[19] A. Moles, Information Theory and Esthetic Perception, University of Illinois Press,
Urbana, 1968.
[20] C. Roads, Introduction to Granular Synthesis, Computer Music Journal, vol. 12, n. 2,
1988.
[21] C. Roads, Granular Synthesis of Sound, in C. Roads, J. Strawn, Fondations of
Computer Music, The MIT Press, Cambridge (Mass.)-London, 1991.
[22] C. Roads, Asynchronous Granular Synthesis, in G. De Poli, A. Piccialli, C. Roads,
Representation of Musical Signals, The MIT Press, Cambridge (Mass.)-London, 1991.
[23] C. Roads, The computer music tutorial, The MIT Press, Cambridge (Mass.)-London,
1996.
[24] C. Roads, Microsound, The MIT Press, Cambridge (Mass.)-London, 2001.
[25] J. Rumbaugh et al. Object-Oriented Modeling and Desing, Prentice Hall, , Englewood
Cliffs, New Jersey, 1991.
[26] B. Stroustrup, The C++ Programming Language, Second Edition, Addison-Wesley,
Reading, Massachusetts, 1991.
[27] B. Truax, Real-time granulation of sampled sound with the DMX-1000, in J.
Beauchamp, Proceedings of the 1987 International Computer Music Conference,
International Computer Music Association, San Francisco, pp. 138-145, 1987.
[28] B. Truax, Real-time granular synthesis with a digital signal processing computer,
Computer Music Journal, vol. 12, n. 2, 1988.
[29] B. Truax, Composing with Real-Time Granular Synthesis, Perspective of New Music,
vol. 28, n. 2, 1990.
[30] A. Valle, V. Lombardo, A two-level method to control granular synthesis, Proceedings
of the XIV Colloquiumon Musical Informatics (XIV CIM), Firenze, 8-10.V.2003.
[31] N. Wiener, Spatial-temporal continuity, quantum theory, and music, in M. Capek, The
Concepts of Space and Time, D. Reidel, Boston, 1964.
[32] I. Xenakis, Formalized Music. Thought and Mathematics in Composition, Bloomington,
Indiana, 1971 (rev. ed. Pendragon Press, Stuyvesant (NY), 1991).
52

8Appendice
Di seguito data la specifica delle classi e di tutte le strutture dati identificate in fase di
progettazione (vedi capitolo 5). Tale specifica data in C++.
/* ----------------------------------------------------------------------------class_definitions.h:
definisce tutte le classi fin qua identificate, eccetto Validator.
----------------------------------------------------------------------------- */

#ifndef CLASS_DEFINITIONS_H
#define CLASS_DEFINITIONS_H
#include
#include
#include
#include
#include

<stdio.h>
<stdlib.h>
<string.h>
<math.h>
<stdarg.h>

#include "error_messages.h"
#include "cs_struct.h"

typedef struct activation_points


{
Point* first_point;
Point* last_point;
} Activation_Points;
typedef struct activation_instants
{
double first_instant;
double last_instant;
} Activation_Instants;
typedef struct interval *ActivationList;
typedef struct interval
{
Activation_Instants activationInterval;
ActivationList next;
} ActivationListNode;
class ShiftingVector {
friend class Trajectory;
public:
void buildSVector( Point head, Point tail );
bool isAudiblePoint( Point position, double audibility_rad );
void getActivationPoints( Activation_Points* &act_points,
Point point, double audibility_rad );
double getLength( );
bool isMyPoint( Point point );
Point* getPointToLength( double length );
double getLengthToPoint( Point point );
inline bool isVerticalSV( ) { return ( head.x == tail.x ); }
protected:
Point head, tail;

};

inline double distance( Point p1, Point p2 )


{ return sqrt( pow((p1.x - p2.x),2) + pow((p1.y - p2.y),2) ); }

class Trajectory {

53

public:
Trajectory( );
void buildTrajectory( Traj_Struct trajectory_struct );
inline bool isImmovableSAct( ) { return (sactSpeed == 0); }
bool isAudiblePointFromInitialPosition( Point position );
ShiftingVector* getNextShiftingVector( );
inline void resetSVectorPt( ) { sVectorPt = 0; }
inline double getSActAudibilityRadius( ) { return sactAudibilityRadius; }
double getInstantToPoint( Point point );
double getTotalTrajectoryNavigationTime( );
double getDistance( double instant, Point point );
double getAngle( double instant, Point point );
private:
Point sactInitialPosition;
double sactSpeed;
double sactAudibilityRadius;
unsigned long int numberOfShiftingVectors, sVectorPt;
ShiftingVector* shiftingVectors;
void getSActActualPosition( double instant, Point* &sactActualPos,
ShiftingVector* &sactActualSV );
inline double distance( Point p1, Point p2 )
{ return sqrt( pow((p1.x - p2.x), 2) + pow((p1.y - p2.y), 2) ); }

};

double stdAngle( Point point, Point sactActualPos, Point tail,


Point head );

typedef class Vertex *IngoingVertex;


class Edge {
public:
Edge( );
void buildEdge( IngoingVertex arrival_vertex, double temporal_distance,
double route_probability );
double getRouteProbability( );
double getTemporalDistance( );
IngoingVertex getIngoingVertex( );
private:
IngoingVertex ingoingVx;
double temporalDistance;
double routeProbability;
};
class Grain {
friend class Score;
public:
Grain( );
void buildGrain( double attack_instant, double duration, double amplitude,
double pan, double dist_value, double angle_value,
unsigned long int number_of_other_values, double* other_values );
private:
double attackInstant;
double durationValue;
double amplitudeValue;
double panValue;
double distance;
double angle;
unsigned long int numberOfOtherPams;
double* otherParamValues;
Grain* nextGrain;
};

class Score {
public:
void insertGrain( Grain* grain );
/* il grain viene inserito al fondo della lista */
void writeInTheScoreFile( char* ScoreFilename );
private:

54

};

Grain* headGrain, tailGrain;

class ParamGenerator {
public:
virtual double getValue( unsigned int noOfArgs, ... ) = 0;
};

class RandFunct : public ParamGenerator {


public:
double getValue( unsigned int noOfArgs, ... );
private:
double mapper( int value, double min, double max );
};

class PanFunct : public ParamGenerator {


public:
double getValue( unsigned int noOfArgs, ... );
private:
double mapper( double value, double min, double max );
};

class DistFunct : public ParamGenerator {


public:
DistFunct( );
void buildDistFunct( Dist_Funct* couples_list );
double getValue( unsigned int noOfArgs, ... );
private:
unsigned long int numberOfCouples;
Point* couples;
unsigned long int getNumberOfCouples( Dist_Funct* couples_list );
void maximumMinCouple( double x_value, Point &maximumMIN );
void minimumMaxCouple( double x_value, Point &minimumMAX );
};
class Parameter {
public:
virtual double getParamValue( double distance, double angle ) = 0;
protected:
Gen_Type generatorType;
ParamGenerator* paramGenerator;
double constantValue;
};
class Amplitude : public Parameter {
public:
Amplitude( );
void buildAmplitude( Ampl_Gen amplitude_definition );
double getParamValue( double distance, double angle );
};

class Duration : public Parameter {


public:
Duration( );
void buildDuration( Duration_Gen duration_definition );
double getParamValue( double distance, double angle );
private:
Domain_Restr* domainRestriction;
};
class Pan : public Parameter {
public:
Pan( );
void buildPan( Pan_Gen pan_definition );

55

};

double getParamValue( double distance, double angle );

class OtherParam : public Parameter {


public:
OtherParam( );
void buildOtherParam( Hpam_Gen amplitude_definition );
double getParamValue( double distance, double angle );
};
class ActivationIntervals {
public:
ActivationIntervals( );
void insertActInterval( Activation_Instants activation_instants );
/*
insertActInterval( ) garantisce che activationList contenga
Activation_Instants disgiunti tra loro */
bool isActivationInstant( double instant );
private:
ActivationList activationList;
ActivationListNode* getIntersectionNodeList
( Activation_Instants act_instants, ActivationList activList );
void insertIntervalInList
( Activation_Instants act_instants, ActivationList activList );
};

bool isAListMember( double instant, ActivationList activList );

class Vertex {
public:
Vertex( );
void buildVertex( Vx_Struct vertex_definition );
inline char* getLabel( ) { return label; }
inline unsigned long int getNumberOfEdges( ) { return numberOfEdges; }
void attachEdge( IngoingVertex arrival_vertex, double temporal_distance,
double route_probability );
inline void resetEdgePt( ) { edgePt = 0; }
void computeActivationIntervals( Trajectory trajectory );
bool isActive( double instant );
Grain* grainGenerator( double instant, Trajectory trajectory );
Edge* chooseEdge( );
private:
char* label;
Point vertexPosition;
Duration duration;
Amplitude amplitude;
Pan pan;
unsigned long int numberOfOtherParams;
OtherParam* OtherParams;
unsigned long int numberOfEdges, edgePt;
Edge* edges;
bool alwaysActive;
ActivationIntervals activationIntervals;
};

void deleteActivationPoints( Activation_Points* act_points );

class GAct {
public:
GAct( );
void buildGAct( Vertex* beginning_vertex, double start_time );
void startTrackGenerationProcess( Trajectory trajectory,
double performance_term );
private:
Vertex* beginningVertex;
double startTime;
};
class GGen {
public:

56

GGen( );
void buildGGen( GGen_Struct ggen_definition );
void computeVxActivationIntervals( Trajectory trajectory );
void startGActs( Trajectory trajectory, double performance_term );
private:
char* ggenName;
unsigned long int numberOfVertexes;
Vertex* vertexSet;
unsigned long int numberOfGActs;
GAct* gactSet;
Vertex* getVertex( char* vx_label );
};
class ControlSpace {
public:
ControlSpace( );
void buildControlSpace( char* CS_filename, double performance_term );
void startPerformance( );
private:
char* controlSpaceName;
double performanceTerm;
unsigned long int ggenSetCardinality;
GGen* ggenSet;
Trajectory trajectory;
};
#endif

57

/* ----------------------------------------------------------------------------ifiles_validator.h:
definisce tutte le classi fin qua identificate, eccetto Validator.
----------------------------------------------------------------------------- */
#ifndef IFILES_VALIDATOR_H
#define IFILES_VALIDATOR_H
#include "csf_struct.h"
#include "ggenf_struct.h"
#include "cs_struct.h"
typedef struct file_position {
unsigned long int row;
unsigned long int column;
} File_Position;
class Validator {
public:
Validator( );
~Validator( );
void validateInputFiles( char* cs_filename );
CS_Struct* getCSstruct( );
void destroyCSstruct( CS_Struct* cs_struct );
private:
/* ======= variabili d'istanza ======= */
CtrlSpace_File*
cs_file_struct;
char*
cs_file_string;
char*
cs_pt;
char*
ggen_file_name;
char*
ggen_file_string;
char*
gs_pt;
File_Position*
cs_file_position;
File_Position*
ggen_file_position;
/* ========= funzioni private ========= */
void ggen_set( );
void positions( );
void start_times( );
void sact( );
void generator_defs( );
void trajectory( );
void validateGGenFile( char* ggen_filename, GGen_File* ggen_file_struct );
void vertexes( Vertexes* vxs );
void edges( Edges** edges_pp );
void gacts( Vertexes* vxs_p );
void fill_field( char* c_1, char* c_2, char** str_pt );
/* ecc. ... */
/* In generale ci sar una funzione privata per ogni regola data in (4.3.1) */
};
#endif

58

/* ----------------------------------------------------------------------------csf_struct.h:
definisce la struttura CtrlSpace_File usata da Validator
----------------------------------------------------------------------------- */
#ifndef CSF_STRUCT_H
#define CSF_STRUCT_H
#include "ggenf_struct.h"
/* ---------------------------------------------------------GGen-Set
= *comment
"GGen-set:" 1#GGen-filename *SP field-term
GGen-filename
= filename
filename
= <UNIX/Windows filename>
---------------------------------------------------------- */
typedef struct ggens* Next_GGen;
typedef struct ggens
{
char*
unsigned long int
GGen_File
Next_GGen
} GGens;

ggen_name;
ggen_number;
ggen_file;
next, prev;

typedef struct ggen_set


{
GGens*
unsigned long int
} GGen_Set;

ggens;
ggens_number;

/* ---------------------------------------------------------------Positions
= *comment
"Vertex-positions:" 1*GGen-position
GGen-position

= *comment
*LWS GGen-filename ":" 1#vertex-position
*SP field-term

vertex-position

= vertex-ID *SP "-->" *SP point

point

= "(" *SP decimal [*SP space-unit] *SP ","


*SP decimal [*SP space-unit] *SP ")"
---------------------------------------------------------------- */
typedef struct Point
{
double x;
double y;
} Point;
typedef struct Vx_Position* Next_Vx_Pos;
typedef struct Vx_Position
{
char*
vx_ID;
Point
point;
Next_Vx_Pos next_vx, prev_vx;
} Vx_Position;
typedef struct GGen_Positions
{
char*
ggen_name;
unsigned long int ggen_index;
Vx_Position*
vx_pos;
unsigned long int vx_number;
} GGen_Positions;
typedef struct Position* Next_Pos;
typedef struct Position
{
GGen_Positions
Next_Pos
} Position;

ggen_poss;
next_pos, prev_pos;

typedef struct Positions


{

59

Position*
unsigned long int
} Positions;

posit;
ggens_number;

/* ----------------------------------------------------------------Start-Times
= *comment
"Start-times:" 1*GGen-times
GGen-times

= *comment
*LWS GGen-filename ":" 1#GAct-time
*SP field-term

GAct-time
= GAct-ID *SP "-->" *SP interval
GAct-ID
= vertex-ID ["_" 1*DIGIT]
----------------------------------------------------------------- */
typedef struct gact_id
{
char*
unsigned long int
} GAct_ID;

vx_ID;
index;

typedef struct gact_stime* Next_GAct;


typedef struct gact_stime
{
GAct_ID
gact_id;
double
stime;
Next_GAct
next_gact, prev_gact;
} GAct_Stime;
typedef struct ggen_stimes
{
char*
ggen_name;
unsigned long int ggen_index;
GAct_Stime*
gact_st;
} GGen_Stimes;
typedef struct start_times* Next_ST;
typedef struct start_times
{
GGen_Stimes ggen_sts;
Next_ST
next_st, prev_st;
} Start_Times;
/* --------------------------------------------------------------------SAct
= *comment
"SAct:"
*LWS initial-position *SP ","
*LWS speed *SP ","
*LWS audio-radius *SP field-term
initial-position

= ["initial-position" *SP "=" *SP] point

speed
speed-unit
space-unit

= ["speed" *SP "=" *SP] decimal [speed-unit]


= space-unit "/" "s"
= ["K" | "c"] "m"

audio-radius = ["audibility-radius" *SP "=" *SP] decimal [space-unit]


--------------------------------------------------------------------- */
typedef struct sact
{
Point init_pos;
double speed;
double audio_rad;
} SAct;
/* ----------------------------------------------------------------Generator-Defs
= *comment
"Generator-Defs:" 1*GGen-generators
GGen-generators

= *comment
*LWS GGen-filename ":" 1*vertex-generator

vertex-generator

= *comment
*LWS vertex-ID ":"
duration
amplitude

60

pan
*other-param
duration

= *LWS "duration" *SP "=" *SP


( ( (pan-funct | rand-funct) domain-restrictn )
| dur-const | dist-funct ) *SP ";"
domain-restrictn
= *SP [SP "domain" *SP "=" *SP]
"[" *SP interval *SP "," *SP interval *SP "]"
dur-const
amplitude

= ["constant" *SP "=" *SP] interval


= *LWS "amplitude" *SP "=" *SP generator *SP ";"

pan

= *LWS "pan" *SP "=" *SP generator *SP ";"

other-param

= *LWS other-param-ID *SP "=" *SP generator *SP ";"

other-param-ID

= ("other-param" | "hp") 1*DIGIT

generator
constant
pan-funct
rand-funct
dist-funct

=
=
=
=
=

funct-point

constant | pan-funct | rand-funct | dist-funct


["constant" *SP "=" *SP] ["+"|"-"] decimal
"pan-function"
"random-function"
2#funct-point

= "(" *SP ( (decimal [*SP space-unit])


| "audibility-radius" | "r" ) *SP ","
*SP (["+"|"-"] decimal | interval) *SP ")"

----------------------------------------------------------------- */
typedef struct dist_funct* Next_Couple;
typedef struct dist_funct
{
Point
couple;
Next_Couple next_couple, prev_couple;
} Dist_Funct;
typedef struct domain_restr
{
double min;
double max;
} Domain_Restr;
typedef union dur_gen
{
Domain_Restr domain;
double
constant;
Dist_Funct* dist_funct;
} Dur_Gen;
typedef union gen
{
double
Dist_Funct*
} Gen;

constant;
dist_funct;

typedef enum {constant_function, pan_function, rand_function, dist_function} Gen_Type;


typedef struct duration_gen
{
Gen_Type
gen_type;
Dur_Gen
gen;
} Duration_Gen;
typedef struct pam_gen
{
Gen_Type
gen_type;
Gen
gen;
} Pam_Gen;
typedef Pam_Gen Ampl_Gen;
typedef Pam_Gen Pan_Gen;
typedef struct hpam_gen* Next_Hpam;
typedef struct hpam_gen
{

61

Gen_Type
Gen
Next_Hpam
} Hpam_Gen;

gen_type;
gen;
next_hpam;

typedef struct vx_gdef* Next_Vx_Gdef;


typedef struct vx_gdef
{
char*
Duration_Gen
Ampl_Gen
Pan_Gen
Hpam_Gen*
unsigned long int
Next_Vx_Gdef
} Vx_Gdef;

vx_ID;
dur_gen;
ampl_gen;
pan_gen;
other_pam_gen;
Hpam_number;
next_vx, prev_vx;

typedef struct ggen_gdefs


{
char*
ggen_name;
unsigned long int ggen_index;
Vx_Gdef*
vx_gd;
unsigned long int vx_number;
} GGen_Gdefs;
typedef struct generator_def* Next_Def;
typedef struct generator_def
{
GGen_Gdefs
ggen_gds;
Next_Def
next_def, prev_def;
} Generator_Def;
typedef struct generator_defs
{
Generator_Def*
gen_defs;
unsigned long int ggens_number;
} Generator_Defs;
/* ------------------------------------------------------Trajectory
= *comment
"Trajectory:" 2#point *SP field-term
------------------------------------------------------- */
typedef struct traject* Next_Point;
typedef struct traject
{
Point
point;
Next_Point
next;
} Traject;
/* -------------------------Control_Space_File= GGen-Set
Positions
[Start-Times]
SAct
Generator-Defs
[Trajectory]
*comment
-------------------------- */
typedef struct ctrlspace_file
{
GGen_Set
ggen_set;
Positions
positions;
Start_Times*
start_times;
SAct
sact;
Generator_Defs
generator_defs;
Traject*
trajectory;
} CtrlSpace_File;

typedef enum {dur, ampl, pn, other} Pam_Type;


#endif

62

/* ----------------------------------------------------------------------------ggenf_struct.h:
definisce la struttura dati GGen_File (usata da Validator) che mantiene le info
di un GGen File
----------------------------------------------------------------------------- */
#ifndef GGENF_STRUCT_H
#define GGENF_STRUCT_H
/* ---------------------------------------------------Vertexes
= *comment
"Vertexes:" 1#vertex *SP field-term
vertex

= "(" label [*SP "," other-params] *SP ")"

label
other-params
vertex-ID
ALPHA
UPALPHA
LOALPHA

=
=
=
=
=
=

GActs

= *comment
"GActs:" 1#(vertex-ID "<-" [gact-number])
*SP field-term

[*SP "label" *SP "="] *SP vertex-ID


[*SP "other-params" *SP "="] *SP 1*DIGIT
1*( ALPHA | DIGIT )
UPALPHA | LOALPHA
<any US-ASCII uppercase letter "A".."Z">
<any US-ASCII lowercase letter "a".."z">

gact-number = 1*DIGIT ["gact" ["s"]]


---------------------------------------------------- */
typedef struct vertex_* Next_Vx;
typedef struct vertex_
{
char*
label;
unsigned long int other_pams;
unsigned long int gats;
Next_Vx
next_vx, prev_vx;
} Vertex_;
typedef struct vertexes
{
Vertex_*
unsigned long int
} Vertexes;

vx;
vx_number;

/* ----------------------------------------------------------------Edges
= *comment
"Edges:" 1#(edge [*SP "-->" *SP weight])*SP field-term
edge

= "(" *SP vertex-ID *SP "->" *SP vertex-ID *SP ")"

weight

= "[" *SP route-interval *SP "," *SP route-prob *SP "]"

route-interval

= interval | "rand"

interval
time-unit
factor

= decimal *SP [time-unit]


= ([factor] "sec") | "min" | "h"
= ( "deci" | "centi" | "milli" |
"micro" | "nano" | "pico" )

ruote-prob
= prob | "auto"
prob
= "1" | "0" ["." 1*DIGIT]
----------------------------------------------------------------- */
typedef struct weight
{
double route_interval;
double route_prob;
} Weight;

// -1 = "rand"
// -1 = "auto"

typedef struct edges* Next_Edge;


typedef struct edges
{
char*
from_vxID;
char*
to_vxID;
Weight
weight;
Next_Edge
next_edge, prev_edge;
} Edges;

63

/* ------------------GGen_File
= Vertexes
[Edges]
Gacts
*comment
------------------- */
typedef struct ggen_file
{
Vertexes
vertexes;
Edges*
edges;
} GGen_File;
#endif

64

/* ----------------------------------------------------------------------------cs_struct.h:
definisce la struttura dati CS_Struct ritornata dal servizio getCSstruct( )
offerto dalla classe Validator
----------------------------------------------------------------------------- */
#ifndef CS_STRUCT_H
#define CS_STRUCT_H
#include "csf_struct.h"
typedef struct generators_struct
{
Duration_Gen*
duration;
Ampl_Gen*
amplitude;
Pan_Gen*
pan;
Hpam_Gen*
hpams;
} Generators_Struct;
typedef struct edge_struct
{
char* to_vx;
double temporal_dist;
double route_prob;
} Edge_Struct;
typedef struct edges_struct
{
unsigned long int edges_number;
Edge_Struct*
edges_vector;
} Edges_Struct;
typedef struct vx_struct
{
char*
Point*
unsigned long int
Generators_Struct*
unsigned long int
double*
Edges_Struct

label;
position;
other_pam_number;
generators;
gact_number;
gacts_start_times_vector;
edges;

} Vx_Struct;
typedef struct ggen_struct
{
char*
ggen_name;
unsigned long int vx_number;
Vx_Struct*
vxs_vector;
unsigned long int gact_number;
} GGen_Struct;
typedef struct GGens_Struct
{
unsigned long int ggen_number;
GGen_Struct*
ggens_vector;
} GGens_Struct;
typedef struct traj_struct
{
Point*
sact_initial_position;
double
sact_speed;
double
sact_audibility_radius;
unsigned long int point_number;
Point**
points_vector;
} Traj_Struct;
typedef struct cs_struct
{
GGens_Struct ggens;
Traj_Struct trajectory;
} CS_Struct;

65

#endif

66