JFugue

API Java per programmare la musicadi

La libreria che andiamo a presentare consente di riprodurre musica attraverso il linguaggio di programmazione Java. Questo avviene passando le note musicali, sottoforma di stringhe come parametro dell'oggetto 'Player'.
Inoltre è possibile scegliere lo strumento da utilizzare, creare ritmi e molto altro ancora. Una volta creata la melodia, sarà possibile salvarla in formato MIDI e usarla a nostro piacimento.

Introduzione

Vi è mai capitato di avere una melodia in testa, di voler provare a suonarla senza saper suonare strumenti musicali? Volete creare un sottofondo musicale per la vostra applicazione, per il sito internet, o per il gioco, ma non sapete come fare? Siete nel posto giusto! Se conoscete qualche nozione di programmazione e (e magari qualche rudimento di teoria musicale) da oggi grazie a JFugue lo potete fare tutto ciò!

Prepariamo l'ambiente di lavoro

Innanzi tutto scarichiamo la libreria dal suo sito ufficiale [1]: dalla pagina principale effettuaiamo il download dell'ultima versione di JFugue (al momento della pubblicazione di questo articolo si tratta della 4.0.3). Nella pagina dei Download troviamo i file sorgenti, la documentazione e le versioni precedenti della libreria. In particolare, il file che ci interessa è jfugue-4.0.3.jar. Provando a scaricare il file, potreste trovarlo in formato in ZIP; nessun problema: una volta scaricato rinominatelo in JAR e funzionerà tutto in maniera perfetta. Scarichiamo questo file e copiamolo nella nostra cartella  di lavoro. Adesso è tutto pronto per iniziare ad usare la nostra API musicale.

La nostra prima composizione

Creiamo un oggetto di tipo Player e creiamo una nuova istanza, in questo modo:

Player player = new Player();

Scriviamo la nostra melodia sotto forma di stringa e passiamola come parametro al metodo play:

// Scala Musicale
String melodia = "C D E F G A B";
player.play(melodia);

Bene: se avete sentito una scala musicale, abbiamo creato la nostra melodia. Semplice no? Notate bene che le note sono scritte secondo lo standard anglosassone (fatto abbastanza scontato per chi si occupi in qualche modo di musica e informatica). Nella tabella 1 sono riportate le corrispondenze con la notazione italiana.

Tabella 1 - Denominazione delle note e della pausa nello standard italiano e in quello anglosassone. La lettera maiuscola ci servirà per indicare quale nota suonare.

Durata delle note

Adesso che abbiamo rotto il ghiaccio con JFugue, proviamo a scrivere una melodia complessa cercando di dare anche una durata alle note. La durata di ogni nota, infatti segue dei principi ben precisi: la durata viene contata non tanto in termini assoluti (millisecondi etc.) ma in termini relativi alla "misura" o "battuta" e alle altre note (intero, quarto, ottavo etc.). La tabella 2 mostra un riassunto di questo concetto di teoria musicale.

Tabella 2 - La durata delle note in riferimento alla battuta di 4/4. La lettera minuscola tra parentesi ci servirà per indicare la durata della nota.

Un'altra considerazione da fare è quella della altezza del suono da utilizzare. La stessa nota, per esempio un DO, può essere più grave o più acuta a seconda della ottava cui appartiene (vedi lo schema in [4]). Per definire una nota, quindi, dobbiamo anche scegliere un'ottava da 0-10 e mettere questo numero accanto alla nota musicale e prima del tempo di battuta: in pratica, facendo riferimento a quanto detto fin qui, per scrivere una nota, dobbiamo usare uno schema composto da "lettera nota + numero ottava + lettera di durata"), per esempio in questo modo:

C4w

che significa "un DO appartenente alla 4a ottava e che dura una intera battuta (semibreve)". Vediamo un esempio di codice:

// ESEMPIO: "Ding ding dong"
Player player = new Player();
String melodia = "C5q G4q C5h",
player.play(melodia); [1]

Stabiliamo il tempo

In musica, il tempo indica quanto velocemente un brano deve essere suonato: in pratica indica la "velocità complessiva" del brano. Spesso è la prima cosa che viene specificata all'inizio della "Stringa Musicale" che andiamo a scrivere. Esso viene descritto come T[tempo] dove al posto di "tempo" dobbiamo mettere il tempo desiderato. Per scegliere un tempo possiamo vedere la tabella 3, in cui i diversi tempi sono anche riferiti ai BPM ("beats per minute").

Tabella 3 - Intervalli di tempo in JFugue, con riferimento ai BPM.

Ecco alcuni esempi, in cui si vede come sia possibile scegliere o il nome del tempo (Allegro, Andante etc.) oppure indicare direttamente i BPM.

player.play("T[Allegro] V0 I0 G6q A5q V1 A5q G6q");
player.play("T120 V0 I[Piano] G5q G5q V9 [Hand_Clap]q Rq");
// T[Allegro] e T120 sono la stessa cosa

Accordi e inversioni

Se la melodia è il susseguirsi di singole note, l'armonia consiste nel suonare contemporaneamente diverse note distinte fra loro secondo precisi intervalli: si tratta degli accordi. Nella nostra tradizione musicale, la maggior parte delle opere musicali scritte si basano proprio su accordi. Nella tabella 4 è riportato il nome JFugue corrispondente per tutti gli accordi musicali.

Tabella 4 - Le tipologie di accordi e la loro denominazione in JFugue.

La stringa accordo deve essere composta dal nome della nota, l'accordo, la tonalità della scala e la durata, come avviene nell'esempio qui sotto

Player player = new Player();
player.play("Cmaj5q F#min2h Bbmin13^^^");

Notate bene che ad esempio, l'accordo Cmaj può essere scritto come C+E+G. Avrete sicuramente notato, in quanto appena scritto, la nota Bbmin13^^^. Questa nota presenta la particolarità "^". Questo carattere indica che la nota viene suonata con 3 inversioni di accordo.

Legature fra note

In una partitura, un legame che collega due note della stessa altezza indica che le due note sono suonate come se fossero una nota sola, con la durata complessiva pari alla somma delle durate delle note legate. Si parla di legature di valore. A cosa possono servire? In JFugue le legature possono anche essere utilizzate per collegare le note e creare una durata combinata che altrimenti non potrebbe essere indicata con le normali lettere di durata: per esempio una "half note" più una croma. La figura 1 riporta un esempio.

Figura 1 - Esempio di legature e "traduzione" in JFugue.

Gruppi irregolari e terzine

I "gruppi irregolari" sono gruppi di note la cui durata non si conforma alla naturale suddivisione ritmica del brano musicale. Nella notazione tradizionale sono caratterizzate da un numero scritto sopra la loro legatura. Le terzine sono un caso particolare di gruppi irregolari in cui ci sono 3 note nel gruppo: in pratica, nel tempo in cui dovrebbero essere suonate 2 note, ne vengono invece suonate 3. Le terzine sono i gruppi irregolari più comuni, ma ne sono possibili anche altri. JFugue consente di rendere i gruppi irregolari con il simbolo di asterisco seguito da il numero di note effettivamente suonate, i due punti e la durata effettiva: le terzine vengono pertanto indicate come "*3:2", le quintine come "*5:4". Ecco un esempio di codice:

// Queste due righe di codice sono equivalenti
player.play("Eq* Fq* Gq*");
player.play("Eq*3:2 Fq*3:2 Gq*3:2");
// 5 note suonate in un tempo di durata 4
player.play("Ci*5:4 Ei*5:4 Gi*5:4 Ei*5:4 Gi:5*4");

L'uso dei Pattern

L'utilizzo dell'oggetto Pattern in JFugue può risultare molto importante se si utilizza più volte uno stesso frammento di brano. Pattern consente di memorizzare una melodia e di richiamarla nel codice ogni qualvolta ci faccia comodo. Ma vediamolo in dettaglio:

//Brano 1
Pattern pattern1 = new Pattern("C5q D5q E5q C5q");
//Brano 2
Pattern pattern2 = new Pattern("E5q F5q G5h");
//Brano 3
Pattern pattern3 = new Pattern("G5i A5i G5i F5i E5q C5q");
//Brano 4
Pattern pattern4 = new Pattern("C5q G4q C5h");
// Mettiamo tutti i pattern insieme
Pattern song = new Pattern();
song.add(pattern1, 2); // aggiungiamo pattern1' a 'song' 2 volte
song.add(pattern2, 2); // aggiungiamo pattern2' a 'song' 2 volte
song.add(pattern3, 2); // aggiungiamo pattern3' a 'song' 2 volte
song.add(pattern4, 2); // aggiungiamo pattern4' a 'song' 2 volte
// Ascoltiamo
Player player = new Player();
player.play(song);

Nell'esempio abbiamo creato 4 Pattern diversi, poi abbiamo creato il Pattern "song" e gli abbiamo aggiunto 2 volte ogni Pattern che avevamo creato. Infine abbiamo passato il Pattern finale chiamato "song" al metodo play di player. Mandando in esecuzione il codice dovreste ascoltare una canzone a voi familiare!

Sento le voci!

Nell'esempio precedente avrete sicuramente riconosciuto il celebre "Fra' Martino, campanaro..." Adesso riscriviamo il brano aggiungendo le cosiddette voci. Le voci servono a creare delle melodie sovrapposte tra di loro, come avviene per esempio nei cori e controcori. Sicuramente capirete meglio vedendo il codice e ascoltando la melodia rispetto alla precedente.

// Pattern doppia pausa
Pattern doubleMeasureRest = new Pattern("Rw Rw");
// Prima voce
Pattern round1 = new Pattern("V0");
round1.add(song);
// Seconda voce
Pattern round2 = new Pattern("V1");
round2.add(doubleMeasureRest);
round2.add(song);
// Terza voce
Pattern round3 = new Pattern("V2");
round3.add(doubleMeasureRest, 2);
round3.add(song);
// Mettiamo le voci insieme
Pattern roundSong = new Pattern();
roundSong.add(round1);
roundSong.add(round2);
roundSong.add(round3);
// Suoniamo!
player.play(roundSong);

Ritmi e percussioni

La libreria JFugue ci permette di creare anche dei "Ritmi" di sottofondo alla nostra melodia musicale: questo avviene creando una nuova istanza dell'oggetto Rhythm.

Rhythm rhythm = new Rhythm();

Ogni ritmo può avere uno o più livelli di percussioni che vengono emesse sotto la melodia. Perche' più livelli? Pensate a una batteria, in cui contemporaneamente l'esecutore suona la cassa con un piede, l'hi-hat con un altro, un piatto con un braccio e un tamburo con un altro.

Per scrivere il ritmo di un livello, usiamo questa tecnica: assegniamo ad ogni strumento componente le percussioni un simbolo: per esempio, un simbolo per la cassa ("bass drum"), un simbolo per il rullante ("acoustic snare") e così via. Successivamente, effettueremo una sostituzione in cui specifichiamo il rapporto tra simbolo e percussione. In tal modo, dovremo semplicemente pensare a scrivere un ritmo di percussioni con i simboli, per esempio "ooO' ooO' ooO' OOO'", dove la lettera minuscolo (o) potrebbe rappresentare uno snare drum, la maiuscola (O) una bass drum, e l'apostrofo (') un hi-hat. Ecco l'esempio:

rhythm.setLayer(1, "O..oO...O..oOO..");
rhythm.setLayer(2, "..*...*...*...*.");
rhythm.setLayer(3, "^^^^^^^^^^^^^^^^");
rhythm.setLayer(4, "...............!");
rhythm.addSubstitution('O', "[BASS_DRUM]i");
rhythm.addSubstitution('o', "Rs [BASS_DRUM]s");
rhythm.addSubstitution('*', "[ACOUSTIC_SNARE]i");
rhythm.addSubstitution('^', "[PEDAL_HI_HAT]s Rs");
rhythm.addSubstitution('!', "[CRASH_CYMBAL_1]s Rs");
rhythm.addSubstitution('.', "Ri"); 
// creo il pattern per il ritmo
Pattern pattern = rhythm.getPattern();
// ripeto il ritmo quattro volte
pattern.repeat(4);
// Suona!
Player player = new Player();
player.play(pattern);

Che ve ne pare? Non sentite un suono elettrizzante? Non vi piace? Allora date un'occhiata alle percussioni nella tabella 5 e provate voi a creare il vostro ritmo!

Tabella 5 - Valori e denominazione delle percussioni in JFugue.

Strumenti musicali

Adesso che avete avuto una panoramica di tutte le funzionalità di JFugue possiamo cambiare il nostro pianoforte, strumento utilizzato di default, con un bel piano elettrico, oppure con una chitarra o un flauto: avete solo l'imbarazzo della scelta! Vediamo in dettaglio un esempio:

player.play("I[Piano] C5q D5q I[Flute] G5q F5q");

Ovviamente se volete cambiare strumento musicale, basta cambiare la stringa tra le parentesi quadre, facendo riferimento alla tabella 6.

Tabella 6 -  L'intera gamma degli strumenti e la denominazione in JFugue.

Creiamo il file MIDI

Dopo che ci siamo sbizzarriti con la fantasia a creare la nostra melodia, salviamola per farla ascoltare ai nostri amici, per creare dei file karaoke o perchè no, per usarla come suoneria per il nostro cellulare! A tal fine, creeremo un file MIDI, un formato standard [4] che viene letto da moltissimi dispositivi, software e hardware.

// melodia = stringa contenente le note          
//C:\melodia.midi = path di destinazione del file midi
player.saveMidi(melodia, "C:\melodia.mid");

Non ci resta che mandare in esecuzione il programma e verificare se il nostro file è stato salvato. Clicchiamo infine su "melodia.mid" con il nostro player musicale predefinito di sistema per ascoltare la nostra melodia

Conclusione

Nel nostro viaggio all'interno della programmazione musicale tramite il linguaggio Java abbiamo scoperto l'API Java JFugue, libreria per creare e suonare musica. Abbiamo introdotto alcuni riferimenti alla teoria musicale per provare a comporre la nostra prima melodia. Con JFugue possiamo suonare musica, accordi, spartiti e mettere in sottofondo il ritmo percussivo che più ci piace. Infine possiamo salvare la nostra melodia in formato MIDI. Tutto in maniera semplice: basta solo conoscere un po' di teoria musicale e il gioco è fatto.

Sul sito della libreria creata dal prolifico David Koelle [3] sono presenti anche delle informazioni riguardanti JFugue con l'utilizzo di NetBeans e LilyPond uno strumento open source per scrivere musica con JFugue. Inoltre è presente anche un'area di scambio musicale, dove ogni autore può pubblicare la propria composizione.

Questa è una delle poche librerie Java che esistono che permette di comporre musica a un livello non elementare. Non è molto conosciuta, quindi spero che questo contributo possa spingere la comunità di sviluppatori Java a conoscere questa importante risorsa, a diffonderla e, perche' no, magari anche a migliorarla! Sul sito [5], infatti, è presente la "lista dei desideri" in cui sono riportate tutte le funzionalità da implementare in futuro: dategli un'occhiata e, se la musica e la programmazione vi appassionano, allora potete contribuire sicuramente!

Riferimenti

[1] JFugue. Java API for Music Programming 2002-2010

http://www.jfugue.org/

 

[2] David Koelle, The Complete Guide to JFugue 2008

http://www.jfugue.org/book.html

 

[3] David Koelle è l'inventore di JFugue nonche' sviluppatore di altri progetti

http://www.davekoelle.com

 

[4] Il protocollo MIDI, voce "Musical Instrument Digital Interface" su Wikipedia

http://it.wikipedia.org/wiki/Musical_Instrument_Digital_Interface

 

[5] La wishlist sul sito di JFugue

http://www.jfugue.org/wishlist.html

 

[6] La voce JFugue su Wikipedia

http://en.wikipedia.org/wiki/JFugue

 

Condividi

Pubblicato nel numero
158 gennaio 2011
Yuri Cervoni si è laureato alla facoltà di Ingegneria Informatica dell’Università “La Sapienza” di Roma nel maggio 2009 con la tesi: “Implementazione e realizzazione di un metodo per l’animazione dell’algoritmo di Dijkstra”. Dall’Aprile 2009, prima come stagista e poi come sviluppatore software, lavora nella Società degli Studi di Settore. Nel…
Ti potrebbe interessare anche