You are on page 1of 60

SVEUILITE U ZAGREBU

FAKULTET ELEKTROTEHNIKE I RAUNARSTVA

DIPLOMSKI RAD br. 1780

Koritenje zvuka u Java aplikacijama


Nenad Peanac

Zagreb, travanj 2015.

Sadraj
1.

Uvod...........................................................................................................1

2.

Opis koritenih tehnologija.........................................................................3


2.1.

Programski jezik Java.............................................................................3

2.1.1.

Razvoj jezika i njegova namjena.....................................................3

2.1.2.

Java danas......................................................................................4

2.1.3.

Zvuna podrka...............................................................................4

2.2.

Java Sound API......................................................................................5

2.2.1.

Koncept, namjena i performanse....................................................5

2.2.2.

Funkcionalnost.................................................................................6

2.2.3.

Digitalni zapis zvuka........................................................................7

2.2.4.

Format zvunog zapisa...................................................................8

2.2.5.

Format zvune datoteke..................................................................8

2.2.6.

Zvuna konfiguracija........................................................................9

2.2.7.

MIDI protokol..................................................................................11

2.2.8.

Dizajn i programska struktura MIDI modula..................................13

2.2.9.

Koritenje MIDI modula.................................................................16

2.3.

Swing....................................................................................................20

2.3.1.

Razvoj i namjena...........................................................................20

2.3.2.

Arhitektura.....................................................................................20

3.

Opis aplikacije..........................................................................................25
3.1.

Koncept, namjena i dizajn.....................................................................25

3.2.

Glavni modul.........................................................................................26

3.2.1.

Glavni izbornik...............................................................................26

3.2.2.

Preglednik instrumenata................................................................30

3.3.

Glavni sekvencer..................................................................................32

3.4.

Sporedni sekvencer..............................................................................34

3.5.

Kontrolni modul.....................................................................................37

4.

Programska izvedba aplikacije.................................................................38


4.1.

Pregled i organizacija koda...................................................................38

4.1.1.

Klase grafikog suelja..................................................................38

4.1.2.

Zvune klase..................................................................................40

4.1.3.

Pomone klase..............................................................................40

4.2.

Implementacija zvunog sustava..........................................................41

4.2.1.

Klasa SynthesizerWrapper............................................................41
iii

4.2.2.
4.3.

Klasa SequencerWrapper.............................................................43

Implementacija grafikog suelja..........................................................46

4.3.1.

Izvedba glavnog modula................................................................47

4.3.2.

Izvedba osnovnog sekvencerskog modula...................................50

4.3.3.

Izvedba glavnog sekvencerskog modula......................................55

4.3.4.

Izvedba sporednog sekvencerskog modula..................................60

4.3.5.

Izvedba kontrolnog modula...........................................................64

5.

Literatura...................................................................................................66

6.

Zakljuak...................................................................................................67

iv

Uvod

1. Uvod
Digitalno zapisivanje, reprodukcija i obrada zvuka u dananje vrijeme ine
osnovnu studijsku tehnologiju za rukovanje zvunim zapisima. Napretkom
raunalne tehnologije, u 90-tim godinama 20. stoljea digitalna obrada zvuka se
ubrzano razvila, te preuzela veinski udio u zastupljenosti na svjetskom tritu nad
analognim tehnologijama.
Prvi praktini ureaj za snimanje i reprodukciju zvunog zapisa izumio i
patentirao je Thomas Edison 1878. godine. [1] Bio je to mehaniki ureaj nazvan
fonografski cilindar. Radio je na principu igle koja je bila privrena na
membranu, ije je vibracije prenosila na votani cilindar. Ureaj je brzo usavren i
rasprostranjen irom svijeta. Ovim izumom ovjeku je prvi put dana mogunost da
uhvati i spremi zvuk, te ga reproducira po elji. Snimanjem zvuka, distribucijom i
prodajom zvunih zapisa zapoeta je nova, brzo rastua grana industrije. Do
1910. godine snimljeno je i rasprodano nekoliko milijuna naslova. Ureaj je uskoro
zamijenjen gramofonom, kojeg je izumio Emile Berliner 1887. godine [2], a
industrija se nastavila sve bre razvijati. Mehaniki proces snimanja zvuka ubrzo
je zamijenjen elektrinim.
Analogno snimanje zvuka zapoeli su 1920-tih godina inenjeri amerike tvrtke
Bell Telephone Laboratories usavravanjem ureaja nazvanog mikrofon, kojeg je
takoer izumio Emile Berliner 1876. godine. Tvrtka je izum otkupila za potrebe
telefonske industrije. Analogni proces snimanja zvuka upotpunjen je izumom
magnetofona njemake tvrtke AEG 1935. godine. 1948. godine ameriki izumitelj
Les Paul izumio je viekanalni magnetofon [3] koji je postao glavni alat za
studijsko snimanje i montau zvuka sve do 90-tih godina 20. stoljea, kada je
zamijenjen raunalima. Ovim izumom postalo je mogue napredno manipuliranje
slijedom zvunih zapisa, spajanje zvunih dionica i kreiranje zvunih sekvenci.
Digitalno zapisivanje zvuka postalo je mogue tek 60-tih godina dvadesetog
stoljea. Proces pretvorbe analognog zvunog signala u digitalni oblik pod
nazivom PCM (eng. Pulse-Code Modulation) prvi je istraio i patentirao britanski
znanstvenik Alec Reeves jo 1937. godine. Nakon objave njegovog rada amerika
tvrtka Bell Telephone Laboratories poela je raditi na implementaciji procesa.
1957. godine njihov inenjer Max Mathews razvio je sustav za snimanje zvuka uz
pomo raunala. Od 1970. godine na tritu su se pojavili viekanalni digitalni
snimai zvuka tvrtki Denon, Mitsubishi i Soundstream koji su koristili PCM
tehnologiju zapisivanja. Digitalni zapisi spremali su se i dalje na magnetske trake,
a najpoznatiji tip takvog medija bile su DAT (eng. Digital Audio Tape) trake, esto
koritene u studijske svrhe.
70-tih godina 20. stoljea na tritu su se takoer poeli pojavljivati elektroniki
instrumenti, kao to su sintesajzeri i sekvenceri. 80-tih godina takvi ureaji inili su
standardnu opremu glazbenih studija. Uskoro, u zvuna studija su poela ulaziti i
raunala, koja su se spajala sa klavijaturama i ostalim elektronikim
komponentama koritenjem MIDI tehnologije (eng. Musical Instrument Digital
Interface). [4] Ova tehnologija predstavljena je 1983. godine i uvela je u upotrebu
industrijski standardiziran protokol za povezivanje, kontrolu i sinkroniziranje
elektronikih ureaja koji se odrao do danas. Protokol je definiran na nain da
1

Uvod

ureaji meu sobom izmjenjuju MIDI poruke, koje sadre instrukcije za izvoenje
operacija koje ureaji trebaju obaviti.
Poetkom 90-tih godina za zapisivanje zvuka su se poeli koristiti raunalni tvrdi
diskovi. Zvuk se u poetku spremao u sirovim AIFF ili WAV formatima, a kasnije su
uvedeni komprimirani formati kao to su MP3, WMA i OGG. Nakon to su
raunalni tvrdi diskovi dostigli dovoljne veliine, a procesori dovoljne brzine,
otvorila se mogunost za efikasno spremanje i rukovanje sa velikim zvunim
zapisima. Ubrzo, raunala su postala osnovni alat svakog glazbenog studija.
Dananji profesionalni programski alati kao to su Cubase, Protools, Logic, Acid,
Nuendo ili Sonar korisniku nude funkcionalnosti cijelog glazbenog studija u jednoj
aplikaciji, koja se uz prikladnu zvunu podrku moe koristiti na prosjenom
korisnikom osobnom raunalu. Takvi programi rezultat su dugogodinjeg razvoja i
napisani su u programskim jezicima C i C++. Od nedavno, napretkom i
optimizacijom programskog jezika Java, uz koritenje Java Sound API biblioteke,
postalo je mogue razvijati sline prenosive aplikacije prihvatljivih performansi.

Opis koritenih tehnologija

2. Opis koritenih tehnologija


2.1. Programski jezik Java
2.1.1. Razvoj jezika i njegova namjena
Programski jezik Java osmiljen je u tvrtci Sun Microsystems poetkom 90-tih
godina prolog stoljea. Razvoj jezika poeo je 1990. godine kao Stealth project
(eng. nevidljivi, prikriveni projekt), poslije nazvan Green project (eng. zeleni projekt),
a vodili su ga Bill Joy, Patrick Naughton, Mike Sheridan i James Gosling. U poetku,
Java je bila poznata pod nazivom Oak (eng. hrast) [5], koji joj je dao Gosling prema
starom hrastu koji je rastao u dvoritu ispred prozora njegove radne sobe. Od tog
naziva kasnije se ipak odustalo zbog problema oko autorskih prava, nakon ega je
usvojeno ime Java. Cilj Sun-ovog tajnog projekta bio je predvianje smjera razvoja
raunarske znanosti i smiljanje naina kako ga uhvatiti.
Budunost se oekivala u vidu nastavka minijaturizacije raunalnih komponenti i
postupnom proirenju raunarske znanosti na podruje ve postojeih elektronikih
ureaja, kao to su npr. kuanski aparati. Poetna ideja projekta bila je povezivanje
mnotva elektronikih naprava sa jednim centralnim ureajem, nalik daljinskom
upravljau, odnosno gledano openito, izgradnja sustava koji e omoguiti mreno
povezivanje i meusobnu komunikaciju velikog broja razliitih elektronikih ureaja.
Da bi to postalo mogue, trebalo je razviti novi hardver, nai prikladni programski
jezik, te dizajnirati i realizirati operacijski sustav sa grafikim sueljem, pristupaan
korisniku. Odlueno je da niti jedan programski jezik do tada, pa ni C++ ne
zadovoljava potrebne uvjete za razvoj takvog sustava, te se poelo raditi na novom
jeziku, Oak-u.
Zahtjevi koje je taj novi jezik trebao ispuniti bili su:

jednostavnost (jezik treba biti iroko rasprostranjen, pa zato ne smije biti


suvie sloen),

pouzdanost (blokiranje i ponovno pokretanje elektronikih ureaja su


nedopustivi),

sigurnost (mrena komunikacija mora biti zatiena),


prenosivost (jezik je potrebno izvoditi na razliitim ureajima, pa mora biti
vieplatformski).
Tri godine nakon poetka projekta, predstavljen je ureaj *7 koji je bio prethodnik
dananjih PDA ureaja. On je unato svom revolucionarnom dizajnu doivio
neuspjeh na tritu, jer je bilo prerano za takav tip tehnologije.
Nakon poetnog neuspjeha, Javu se probalo iskoristiti za potrebe kabelske
televizije, no tamo je takoer doivjela neuspjeh pred ve postojeim sustavom.
Pojavom Interneta, u Sun-u su shvatili da je Java po svojim karakteristikama savren
izbor za izradu web aplikacija.
Java je prilagoena novoj primjeni i slubeno izdana 1995. godine. Omoguila je
izradu dinamikih web stranica i sloenih web aplikacija, neovisno o platformi na
3

Opis koritenih tehnologija

kojoj se izvodi, te je vrlo brzo postala sveprisutna na Internetu. Idui korak bio je
ulazak na trite mobilnih telefona to se takoer pokazalo uspjenim.

2.1.2. Java danas


Statistike kau [6] da otprilike 4.5 milijuna programera trenutno radi u Javi, da je
vrijednost poslova obavljenih upotrebom Java tehnologija oko 100 milijardi dolara
godinje, da se trite igara na mobilnim telefonima procjenjuje na oko 3 milijarde
dolara, te da 70% planiranih beinih aplikacija koristi Javu.
Budui da je namijenjena svijetu Interneta i multimedijskoj upotrebi, Java od svojih
najranijih verzija sadri podrku za zvuk, u obliku biblioteke pod nazivom Java Sound
API, uz koju je potom dodana i podrka za video i 3D grafiku.

2.1.3. Zvuna podrka


U verziji Jave 1.02 u jezik je uvedena biblioteka Java Sound API. Koritenjem
prvih verzija te biblioteke bilo mogue reproducirati tek jednostavne 8 kHz zvukove
zapisane u AU formatu, no situacija se bitno izmijenila u verziji 1.2 kad je u Javinu
zvunu podrku uvrten HeadSpace Audio Engine tvrtke Beatnik Corporation. [7] Uz
upotrebu istih suelja, programerima je dana mogunost koritenja AU, WAV, AIFF,
MIDI, i RMF zvukova. Iako je kvaliteta zvuka poboljana do CD kvalitete, (do
frekvencije uzorkovanja od 44 kHz), nije postojao nain programske kontrole kao to
je pauziranje i nastavljanje reprodukcije zvuka, prikazivanje trenutnog poloaja ili
dobivanje obavijesti da je reprodukcija gotova. Java Sound API pruao je
programerima tek osnovnu funkcionalnost.
U verziji Jave 1.3 ti nedostatci su ispravljeni. Do verzije 1.5 uklonjeno je dosta
greaka i implementirane su nove, optimizirane osnovne funkcije napisane u C-u.
Time je omoguena brza i efikasna podrka za razvoj programa koji zahtijevaju
kratak odziv od zvunog sustava i namijenjeni su obavljanju velikog broja sloenih
zvunih operacija koje se trebaju izvravati u realnom vremenu.
U trenutnoj verziji Jave 1.6, Java Sound API je stabilna i zaokruena cjelina,
namijenjena visokom stupnju kontrole nad zvukom i upotrebi u bilo kakvoj vrsti
multimedijskih aplikacija, od jednostavnih korisnikih programa do zahtjevnih
profesionalnih sustava.

2.2. Java Sound API


2.2.1. Koncept, namjena i performanse
Java Sound API je programski okvir niske razine koji prua mogunosti za
neposredno kontroliranje i obradu ulaznih i izlaznih zvunih zapisa u audio ili u MIDI
formatu. Osim to nudi izravnu kontrolu nad zvukom, Java Sound API je dizajniran sa
ciljem pruanja proirivosti i fleksibilnosti.
Java Sound API prua najnii mogui nivo kontrole nad zvukom na Java platformi.
Dijelovi API-ja su mehanizmi preko kojih je mogue programski pristupiti ili rukovati
sistemskim resursima kao to su audio mikseri, MIDI sintesajzeri i ostali MIDI ureaji,
itai, snimai, pretvornici zvunih zapisa i slino. Java Sound API ne sadri
sofisticirane zvune editore ili grafike alate, ali prua mogunosti na osnovu kojih se
4

Opis koritenih tehnologija

takvi programi mogu izgraditi. API naglaava kontrolu zvuka na niskom nivou nad
onom koju korisnici tipino oekuju.
U Javi takoer postoje API-ji viih razina koji sadre elemente usko vezane uz
zvune operacije. Jedan od takvih je JMF (eng. Java Media Framework), dostupan
kao standardna ekspanzija Java platforme. JMF predstavlja ujedinjenu arhitekturu,
komunikacijski protokol i programsko suelje za snimanje i reprodukciju audio i video
zapisa. Na ovaj nain programerima se nudi jednostavna osnova za izgradnju
programa za reprodukciju multimedijskih sadraja. S druge strane, ako je potrebno
izgraditi sofisticiraniju aplikaciju sa naprednijim opcijama kao to su reprodukcija
segmentiranih ili velikih zvunih zapisa, upotreba audio efekata ili manipulacija nad
MIDI zapisom, Java Sound API nudi primjereniji pristup zbog veeg nivoa kontrole.
Java Sound API sastavljen je iz skupa brzih, optimiranih osnovnih funkcija
napisanih u C/C++ kodu. Takve funkcije piu se u proizvoljnom jeziku i provode se u
binarni kod spreman za izvoenje na ciljanoj platformi. Na taj nain se zaobilazi
interpretiranje meukoda i eliminira mogue kanjenje unutar JVM-a (eng. Java
Virtual Machine), te izravno pristupa resursima sustava na niskoj razini (eng. Low
level programing). Tako su na Windowsima osnovne funkcije napisane i prevedene
uz pomo Direct Sound-a, a na Linuxu uz pomo ALSA-e. Ovakav pristup
upotrijebljen je radi ubrzanja rada Java Sound API-ja, a dobivene performanse su u
rangu sa klasinim C/C++ kodom. Vrijeme uitavanja aplikacije takoer je skraeno u
odnosu na obian Java kod jer su sve funkcije za upravljanje zvukom unaprijed
prevedene, pa se kanjenje uglavnom odnosi na ostale Java klase, kao to su npr.
klase grafikog suelja, klase za mrenu komunikaciju i slino [8].
Mogunosti i performanse Java Sound API-ja dobro demonstrira mnotvo
besplatnih aplikacija dostupnih na Internetu [9].

2.2.2. Funkcionalnost
Java Sound API sastoji se od dva funkcionalno odvojena modula. Jedan prua
audio, a drugi MIDI podrku. Svaki modul podran je unutar svog paketa:

javax.sound.sampled - paket specificira suelja za snimanje, mijeanje i


reprodukciju snimljenog zvuka,

javax.sound.midi - paket specificira suelja za MIDI sintezu, rukovanje MIDI


sekvencama i upravljanje MIDI dogaajima.

Osim ova dva paketa, Java Sound API jo ine paketi javax.sound.sampled.spi i
javax.sound.midi.spi koji sadre servise, tj. apstraktne klase i suelja preko kojih je
mogue uvesti dodatne komponente i funkcionalnosti unutar API-ja.

2.2.3. Digitalni zapis zvuka


Paket javax.sound.sampled prua mogunosti za upravljanje digitalno zapisanim
zvukom, koji se unutar Java Sound API-ja naziva uzorkovani zvuk (eng. sampled).
Pod tim nazivom se podrazumijeva bilo kakav tip digitalnog zapisanog zvuka. Uzorci
zvuka predstavljaju uzastopne slike zvunog signala. Kad se zvuk zapisuje u
analognom obliku, koristi se mikrofon, koji zvune valove pretvara u analogne
elektrine signale valnog oblika. Kad se zvuk prebacuje iz analognog zapisa u
digitalni, koristi se AD (analogno-digitalno) sklopovlje koje elektrine signale pretvara

Opis koritenih tehnologija

u digitalne informacije postupkom uzorkovanja. Postupak [9] je ilustriran na slijedeoj


slici:

Slika 1. Uzorkovanje zvunog signala


Zvuni se signal uzorkuje na nain da se u skladu sa odabranom frekvencijom
uzorkovanja periodiki zapisuje slika zvunog signala, tj. iznos amplitude elektrinog
vala kojim je predstavljen zvuk. Na gornjoj slici, plavim su tokicama oznaene
vrijednosti zvunog signala predstavljenog crvenom krivuljom u trenutcima
uzorkovanja. to je frekvencija uzorkovanja vea, to e zapis zvuka biti vjerniji. Ako
koristimo dananju CD kvalitetu zapisa zvuka, sa frekvencijom od 44 100 Hz, to
znai da 44 100 puta u sekundi zapisujemo vrijednost zvunog signala.
Osim frekvencije uzorkovanja, za kvalitetu zapisa zvuka je bitna jo i kvantizacija,
tj. rezolucija zvunog zapisa koja odreuje broj bitova kojima se zapisuje iznos
amplitude zvuka. to je iznos kvantizacije vei, kvaliteta zapisa je bolja. Danas se
zvuk veinom zapisuje sa 16, 24 i 32 bita.
Java Sound API generalno razlikuje dvije vrste formata zvunih podataka. Prvu
vrstu predstavlja format koji se koristi za zvune zapise, a drugu format kojim se
zapisuju zvune datoteke.

2.2.4. Format zvunog zapisa


Ovaj format sadri podatke koji predstavljaju atribute promatranog zvunog
zapisa. Unutar API-ja predstavlja se objektom tipa AudioFormat koji sadri podatke o:

tehnici kodiranja (esto PCM),

broju kanala (1 za mono, 2 za stereo, ili vie za viekanalni zapis kao


surround 5.1),

frekvenciji uzorkovanja (eng. sample rate),

kvantizaciji,
6

Opis koritenih tehnologija

frekvenciji prikaza (eng. frame rate),

veliini prozora, u bajtovima (eng. frame size) ovdje se izraz prozor


odnosi na koliinu informacija svih zvunih kanala koji ine promatrani zvuk
u danom trenutku, izraen u bajtovima,

poretku bajtova (big endian / little endian).

2.2.5. Format zvune datoteke


Dok prethodni oblik formata direktno opisuje zapis zvuka, ovaj format specificira
strukturu datoteke u koju se takvi podaci spremaju. Osim zvunih podataka, u
zvunim datotekama se esto nalaze i druge informacije kao npr. podaci o autoru,
atributi zapisa, kao to su trajanje, vrsta kodiranja i slino. Takvi dodatni podaci
obino se zapisuju u zaglavljima zvunih datoteka.
Java Sound API format zapisa zvune datoteke predstavlja objektom tipa
AudioFileFormat koji sadri:

tip datoteke (WAVE, AIFF itd.),

duinu datoteke izraenu u bajtovima,

duinu datoteke izraenu u prozorima,

prethodno opisani AudioFormat objekt sa atributima zvuka.

2.2.6. Zvuna konfiguracija


Da bismo mogli iskoristiti dani zvuni zapis unutar nekog sustava, potreban nam je
zvuni ureaj koji moemo upotrijebiti za upravljanje sa zvukom. U Java Sound APIju svaki zvuni ureaj predstavljen je mikserom. Programski mikser je koncept koji
potjee iz koncepta audio miksera.
Svrha miksera je upravljanje s jednim ili vie tokova zvunih ulaza, te jednim ili
vie tokova zvunih izlaza podataka. Programski mikser esto predstavlja
implementaciju suelja ureaja kao to je zvuna kartica. Svaki ulaz i izlaz na
zvunoj kartici predstavljeni su ulaznim i izlaznim prikljukom na njenom mikseru.
Audio mikser ima kanale ili linije signala, pri emu svaka linija predstavlja tok jednog
zvunog signala (obino stereo signal). U svaki kanal dakle ide jedan izvor zvuka,
kao to je npr. mikrofon, gitara, bubanj, gramofon itd. Svaki kanal ima potenciometre,
rotacijske i klizne, preko kojih je mogue podesiti nivo i filtriranje zvuka, dodati efekte
kao to je npr. reverb efekt, koji daje prostornost zvuku.
Svrha audio miksera je spajanje vie ulaznih zvunih signala u jedan ili vie
izlaznih, koji se onda preko izlaznih prikljuaka mogu slati u ureaje za snimanje i
reprodukciju zvuka. Mikser je dakle sredinja komponenta svake audio konfiguracije.
U Java Sound API-ju se, analogno tome, svakom zvunom konfiguracijom upravlja
pomou jednog ili vie miksera.
Primjer audio miksera prikazan je na slijedeoj slici:

Opis koritenih tehnologija

Slika 2. Primjer audio miksera


Java Sound API dizajniran je na nain koji ne pretpostavlja predefiniranu zvunu
konfiguraciju i doputa proizvoljan broj razliitih audio komponenti unutar sustava.
Podrane su uobiajene operacije za rukovanje sa ulaznim i izlaznim zvunim
signalima kao i mijeanje viestrukih tokova zvuka. Primjer jedne tipine zvune
konfiguracije prikazan je na slijedeoj slici:

Slika 3. Primjer zvune konfiguracije

Opis koritenih tehnologija

Primjer pokazuje sustav sa zvunom karticom koja ima vie ulaza i vie izlaza, dok
je mikser izveden softverski. Izvori zvuka su programi, mrea, sintesajzer, datoteke
sa zvunim zapisom, mikrofon itd. Sav zvuk iz izvora dolazi do miksera gdje se spaja
u jedan tok informacija (eng. stream) koji se preko izlaza moe predati ureajima za
reprodukciju.

2.2.7. MIDI protokol


MIDI standard definira komunikacijski protokol za razne elektronike glazbene
ureaje, kao to su elektrine klavijature i osobna raunala. MIDI informacije mogu
se prenositi kablovima meu ureajima i spremati u standardne datoteke.
Standard je prvenstveno bio zamiljen za prijenos nota meu sintesajzerima.
Pojavom osobnih raunala proiren je u svrhu povezivanja instrumenata sa
raunalima. MIDI specifikacija sastoji se od hardverskog i softverskog dijela.
Hardverski dio uglavnom opisuje mehanizme i prikljuke za povezivanje ureaja, dok
softverski dio ini veinu specifikacije, budui da dananja raunala raspolau i vie
nego dovoljnom procesorskom moi za izvedbu softverskih sintesajzera i
sekvencera.
Unutar Java Sound API-ja MIDI standard opisan je javax.sound.midi paketom.
Ovaj paket omoguava upravljanje MIDI dogaajima i reprodukciju zvuka na temelju
tih dogaaja. Dok semplirani zvuk sadri direktan prikaz zvuka, MIDI je format zapisa
koji sadri instrukcije prema kojima se neki zvuk moe sintetizirati. Takav format ne
opisuje direktno sam zvuk ve dogaaje koji utjeu na proces stvaranja zvuka koji se
generira u sintesajzeru. Takvi dogaaji su npr. pritisci tipaka, okretanje
potenciometara, pritiskanje gumba i slino.
MIDI dogaaji ne moraju biti izvedeni na vanjskim ureajima, ve mogu biti i
softverski generirani te spremljeni u datoteku. Programi koji stvaranju, generiraju i
ureuju takve MIDI datoteke zovu se sekvenceri. Sintesajzeri koji iz takvog zapisa
generiraju zvuk mogu biti vanjski ureaji, programi ili ipovi na zvunoj kartici. Osim
same reprodukcije, sintesajzeri esto imaju podrku za razne efekte. Zvune kartice
esto imaju ulazne i izlazne prikljuke preko kojih se mogu povezivati sa vanjskim
MIDI ureajima.
Funkcionalnost MIDI zapisa ilustrirana je MIDI konfiguracijom na slijedeoj slici:

Slika 4. Primjer MIDI konfiguracije

Opis koritenih tehnologija

Primjer pokazuje aplikaciju koja priprema glazbenu reprodukciju iz MIDI datoteke


spremljene na tvrdom disku (na lijevoj strani slike). Standardni MIDI zapis ita se u
softverskom sekvenceru, koji alje MIDI poruke vanjskom sintesajzeru koji potom
reproducira zvuk, ili programskom sintesajzeru koji koristi bazu datoteka sa
instrukcijama za generiranje zvukova poznatih instrumenata.
Kao to se vidi na slici, MIDI poruke unutar sustava imaju vremenske oznake, po
kojima ih programski sintesajzer izvodi. One se moraju ukloniti prije slanja vanjskom
sintesajzeru, te mu se moraju poslati u oznaenim trenucima. Ova razlika izmeu
MIDI poruka unutar raunalnog sustava i vanjskih MIDI komponenti postoji zbog toga
to standard u vrijeme svog nastanka (1984-te godine) nije bio razvijen za raunala
nego je naknadno prilagoen takvoj upotrebi.
Zbog toga se MIDI specifikacija dijeli na 2 dijela:

MIDI 1.0 - protokol za povezivanje MIDI komponenti. Odnosi se na


originalni standard, razvijen za komunikaciju meu sintesajzerima.

Standardne MIDI datoteke - proirenje standarda, ukljuuje podrku za


spremanje MIDI zapisa u datoteke

2.2.7.1. MIDI 1.0


U MIDI specifikaciji 1.0 podaci su predstavljeni MIDI porukama. Vrste poruka
meusobno se razlikuju po prvom bajtu poruke. Taj bajt zove se statusni bajt, a
oznaen je jedinicom na mjestu najznaajnijeg bita. Nakon njega slijede bajtovi
poruke.
MIDI poruke se obino koriste kanalno. Svaki kanal se pridjeljuje pojedinom
instrumentu tako da se ureaj namjesti da reagira samo na poruke poslane na
odreenom kanalu. Za takvu komunikaciju imamo kanalne MIDI poruke, koje imaju
statusni bajt takav da se u prva etiri bita nalazi zapis kanala, a u druga etiri bita
vrsta poruke. Npr. dvije najee koritene vrste MIDI poruka su Note On i Note Off
za sviranje i prestanak sviranja odreene note. Ovakve poruke obino koriste dva
podatkovna bajta, jedan koji odreuje visinu note i drugi koji odreuje jainu kojom je
nota odsvirana.
Ova osnovna verzija MIDI specifikacije dizajnirana je za prijenos MIDI informacija
izmeu komponenti u realnom vremenu. To znai da se MIDI porukama ne pridodaju
nikakve vremenske oznake, ve se akcije zapisane u porukama izvode odmah po
primitku poruke.
2.2.7.2. Standardne MIDI datoteke
Standardne MIDI datoteke proiruju osnovni MIDI protokol i dodaju mu mogunost
pohrane MIDI informacija. Takve datoteke zapravo sadre MIDI dogaaje. MIDI
dogaaj je MIDI poruka sa dodanom vremenskom oznakom koja odreuje vrijeme
izvoenja te poruke. Niz takvih dogaaja naziva se sekvencom.
Standardna MIDI datoteka organizirana je u trake. Svaka traka sadri slijed nota
za odreeni instrument. Moemo rei da MIDI datoteka sadri sekvence MIDI
dogaaja za pojedine instrumente.

10

Opis koritenih tehnologija

2.2.8. Dizajn i programska struktura MIDI modula


MIDI modul Java Sound API-ja dizajniran je sa ciljem potpune podrke MIDI
standarda, te jednostavnog upravljanja MIDI ureajima. Programska implementacija
se stoga svodi na simuliranje standardom specificiranih MIDI komponenti.
2.2.8.1. MIDI poruke
MIDI poruke predstavljene su apstraktnom klasom MidiMessage. Ta klasa
predstavlja osnovnu, vremenski neoznaenu MIDI poruku u skladu sa specifikacijom
1.0. Takoer moe sadravati poruku definiranu proirenom MIDI specifikacijom ali
bez vremenske oznake.
Klasa MidiMessage ima tri podklase:

ShortMessages - su najee koritene poruke. Nakon statusnog bajta


slijede dva podatkovna.

SysexMessages - su posebne poruke vezane uz sustav. Mogu imati puno


podatkovnih bajtova i obino ih definira proizvoa sustava.

MetaMessages - su vrsta poruka koja se zapisuje u MIDI datoteke. Sadre


tekst pjesama, podatke o tempu i slino, koje imaju znaenje za sekvencer
ali ne i sintesajzer.

2.2.8.2. MIDI dogaaji, sekvence i trake


MIDI dogaaji sadre MIDI poruke i vremenske informacije o njihovom izvoenju,
te se zapisuju u MIDI datoteke. Programski gledano, MIDI dogaaj predstavljen je
klasom MidiEvent , koja je omota oko klase poruke i njene instance mogue je
zapisivati u standardne MIDI datoteke. Metode klase omoguavaju nam itanje i
postavljanje vremenskih informacija te dobavljanje osnovne MIDI poruke. Njeno
postavljanje mogue je samo za vrijeme konstrukcije dogaaja.
Niz MIDI dogaaja ini traku, koja odgovara zapisu sviranja jednog instrumenta.
Niz traka ini sekvencu. Programski, sekvence i trake predstavljene su klasama
Track i Sequence. Njihove instance mogue je stvoriti itanjem iz datoteke ili
koritenjem konstruktora. Klase MidiEvent, Track i Sequence ine hijerarhiju u smislu
vlasnitva, ali ne i nasljeivanja, jer su sve izvedene iz klase java.lang.Object.
2.2.8.3. MIDI ureaji
MIDI ureaji unutar Java Sound API-ja predstavljeni su MidiDevice sueljem.
Objekti koji implementiraju ovo suelje imaju mogunost komunikacije sa drugim
takvim objektima odnosno MIDI ureajima. Takav objekt moe biti implementiran
softverski ili kao suelje prema MIDI podrci nekog hardverskog ureaja kao to je
zvuna kartica ili eksterni sintesajzer. Suelje prua funkcionalnosti za otvaranje i
zatvaranje ureaja, kao i funkcionalnosti tipinih ulaznih i izlaznih MIDI prikljuaka,
kao to je slanje i primanje MIDI poruka. Ureaji specijalizirane namjene kao to su
sintesajzeri i sekvenceri imaju na raspolaganju njegova podsuelja Sythesizer i
Sequencer. Suelje takoer sadri unutarnju klasu MidiDevice.Info u kojoj se nalaze
tekstualne informacije o ureaju.
2.2.8.4. Odailjai i primatelji
Ovi objekti slue za odailjanje i primanje MIDI poruka. Odailjai moraju
implementirati Transmitter suelje a primatelji Receiver suelje. MIDI ureaj alje ili
11

Opis koritenih tehnologija

prima poruke preko jednog ili vie takvih objekata, pri emu se kae da on te objekte
posjeduje. Svaki odailja moe biti spojen na jednog primatelja odjednom, i
suprotno. Ako elimo da nam ureaj alje poruke prema vie primatelja odjednom,
onda mora posjedovati vie odailjaa pri emu je svaki spojen sa svojim
primateljem.
2.2.8.5. Sekvenceri
Sekvencer je ureaj za snimanje i reprodukciju sekvenci MIDI dogaaja. Posjeduje
odailjae i primatelje, jer mora slati poruke ostalim ureajima kao to su sintesajzeri
ili izlazni MIDI prikljuci, te ih primati prilikom zapisivanja u MIDI datoteke. Sekvencer
je u API-ju predstavljen objektom koji implementira Sequencer suelje. U odnosu na
svoje nadsuelje MidiDevice, ovo suelje definira dodatne metode za osnovne
mogunosti sekvenciranja, kao to su uitavanje sekvenci iz MIDI datoteka,
postavljanje tempa izvoenja i sinkroniziranje ostalih ureaja. Programi preko suelja
takoer mogu registrirati objekte sluae, koji se obavjetavaju o izvravanju
odabranih funkcija sekvencera.
2.2.8.6. Sintisajzeri
Sintesajzer je ureaj za generiranje zvuka. To je jedini objekt u MIDI paketu Java
Sound API-ja koji generira zvuk. Sintesajzer kontrolira 16 MIDI kanala. Kanali su
instance klase koja implementira MidiChannel suelje. Zvuk se moe generirati
direktno, koritenjem metoda ovih objekata ili slanjem poruka sintesajzeru, koji onda
prema njima generira zvukove. Poruke su ei nain upotrebe. Sintesajzer ih prima
od sekvencera ili preko ulaznog porta. Osim informacija iz MIDI poruka, npr. o visini i
jaini note, sintesajzer mora znati kako uope generirati traeni zvuk, da bi ga mogao
interpretirati na traeni nain. Ova vrsta informacija predstavljena je Instrumentom.
Svaki instrument sadri skup instrukcija u prema kojima sintesajzer generira odreeni
zvuk. Instrumenti su ugraeni u sintesajzer ili mu se dodaju u obliku kolekcije
instrumenata (eng. soundbank).

2.2.9. Koritenje MIDI modula


U nastavku je ilustrirano koritenje MIDI modula na primjerima operacija koje se u
aplikacijama najee izvode.
2.2.9.1. Ispitivanje i zauzimanje dostupnih MIDI ureaja
Pristupanje MIDI ureajima u Java Sound API-ju izvodi se preko klase
MidiSystem, koja predstavlja sredinji objekt za upravljanje MIDI sustavom. Klasa
sadri statike metode kojima se mogu ispitati i dobaviti raspoloivi MIDI ureaji,
sistemske implementacije suelja kao to su Sequencer i Synthesizer,
implementacije eksternih suelja primatelja i odailjaa, informacije o podranim
MIDI datotekama itd. Dohvat raspoloivih ureaja obavlja se upotrebom metode:
static MidiDevice.Info[] getMidiDeviceInfo()
Metoda vraa polje MidiDevice.Info objekata koji sadre informacije o pojedinom
MIDI ureaju, kao to su ime klase, mogunosti i tekstualni opis.
Dohvat odabranog ureaja izvodi se metodom:
static MidiDevice getMidiDevice(MidiDevice.Info info)

12

Opis koritenih tehnologija

Osim odabira konkretnog ureaja, mogue je koristiti i podrazumijevane (eng.


default) MIDI ureaje. U tu svrhu koristimo slijedee metode:

static Sequencer getSequencer(),

static Synthesizer getSynthesizer(),

static Receiver getReceiver(),

static Transmitter getTransmitter().

Prije koritenja, MIDI ureaje je potrebno rezervirati upotrebom metode open():


if (!(device.isOpen())) {
try {
device.open();
} catch (MidiUnavailableException e) {
// obrada iznimke
}
}

Nakon to je ureaj rezerviran, potrebno ga je povezati sa drugim ureajima radi


ostvarivanja komunikacije. Nakon to su potrebne operacije obavljene, ureaj se
zatvara metodom close().
2.2.9.2. Odailjanje i primanje MIDI poruka
Povezivanje dva MIDI ureaja izvodi se spajanjem odailjaa jednog ureaja sa
primateljem drugog. Povezivanje se uvijek obavlja na strani odailjaa. Odailja
sadri metode za ispitivanje i postavljanje primatelja. Kad se primatelj postavi, znai
da je izmeu njih uspostavljena MIDI veza. Odailja alje poruke primatelju koristei
njegove metode. Preko tih metoda primatelj prima poruke od drugih objekata. Oba
objekta sadre metode za zatvaranje veze, nakon ega postaju dostupni za stvaranje
veza sa drugim ureajima.
U slijedeem primjeru prikazano je povezivanje sekvencera i sintesajzera:
// deklariranje referenci
Sequencer seq;
Transmitter seqTrans;
Synthesizer synth;
Receiver synthRcvr;
try {
//dohvat pretpostavljenog sekvencera
seq = MidiSystem.getSequencer();
seqTrans = seq.getTransmitter();
// dohvat pretpostavljenog sintisajzera
synth = MidiSystem.getSynthesizer();
synthRcvr = synth.getReceiver();
// povezivanje odasiljaa i primatelja
seqTrans.setReceiver(synthRcvr);
} catch (MidiUnavailableException e) {
13

Opis koritenih tehnologija


// obrada iznimke
}

Nakon upotrebe, sve primatelje i odailjae potrebno je zatvoriti pozivanjem


njihove close() metode. Svaki MIDI ureaj sadri metodu istog potpisa, koja ga
zatvara skupa sa njegovim primateljima i odailjaima.
MIDI poruke je mogue slati i programski, bez upotrebe odailjaa. Ovakav je
postupak koristan kod programa koji generiraju MIDI poruke npr. iz MIDI tipkovnice
sa ekrana i alju ih sintesajzeru koji potom proizvodi zvuk. Potrebno je instancirati
praznu poruku iz klase ShortMessage i popuniti je koritenjem metode:
void setMessage(int command, int channel, int data1, int data2)
Nakon toga poruku je potrebno poslati primatelju koristei njegovu metodu:
void send(MidiMessage message, long timeStamp)
Argument timeStamp je interna veliina koja se koristi za ispravljanje i
sinkronizaciju latencije kod MIDI poruka do koje moe doi zbog npr. kanjenja u
operativnom sustavu ili u mrenom prometu. Predstavlja vrijeme u mikrosekundama
od otvaranja ureaja koji sadri primatelja kojem pripada koritena metoda send().
Ako se ne koristi, pridruuje joj se vrijednost -1.
Ovakvo slanje poruke ilustrira slijedei kod:
// stvaranje prazne poruke
ShortMessage myMsg = new ShortMessage();
// sviranje note C5 (60), umjereno glasno (jaina = 90).
myMsg.setMessage(ShortMessage.NOTE_ON, 0, 60, 90);
// vremenske oznake se ne koriste
long timeStamp = -1;
// dohvat primatelja
Receiver rcvr = MidiSystem.getReceiver();
// slanje poruke
rcvr.send(myMsg, timeStamp);

2.2.9.3. Uitavanje, izvoenje i snimanje MIDI sekvenci


MIDI zapisi pohranjuju se u obliku sekvenci MIDI dogaaja. Za upravljanje MIDI
sekvencama koristi se sekvencer. Pomou njega se mogu izvoditi, ureivati i snimati
MIDI sekvence. Sekvencer u tu svrhu obino sadri primatelje i odailjae.
Primateljima se koristi pri snimanju, a odailjaima pri slanju MIDI zapisa ureajima
za izvoenje.
Dohvat i otvaranje sekvencera prikazani su slijedeim programskim odsjekom:
// dohvat podrazumijevanog sekvencera
Sequencer sequencer;
sequencer = MidiSystem.getSequencer();
// provjera
14

Opis koritenih tehnologija


if (sequencer == null) {
// greska, ne postoji sekvencer ...
} else
sequencer.open();
}

Sekvencu se moe dobaviti iz MIDI datoteke, mogue ju je stvoriti runo, ili iz


dobivenih MIDI poruka. Uitavanje sekvence iz datoteke moe se obaviti na slijedei
nain:
try {
// otvaranje datoteke
File myMidiFile = new File("seq1.mid");
// uitavanje MIDI datoteke u sekvencu
Sequence mySeq = MidiSystem.getSequence(myMidiFile);
// postavljanje sekvence
sequencer.setSequence(mySeq);

}
catch (Exception e) {
// obrada iznimke
}

Nakon uitavanja sekvence, upravljanje njezinim izvoenjem obavlja se


koritenjem slijedeih metoda:

void start(),

void stop(),

void getMicrosecondPosition(long microsecond),

void setMicrosecondPosition(long microsecond),

public void getTempoInBPM(float bpm),

public void setTempoInBPM(float bpm).

Izvoenje sekvenci mogue je sinkronizirati sa drugim MIDI ureajima. Na


sekvencer je takoer mogue prikljuiti i objekte sluae, koji se obavjetavaju pri
izvoenju registriranih dogaaja.

2.3. Swing
2.3.1. Razvoj i namjena
Swing je biblioteka za izradu grafikih suelja u sklopu programskog jezika Java.
Biblioteka ini dio Sun-ovog paketa grafikih komponenti pod nazivom JFC (eng.
Java Foundation Classes) u kojem su jo bibliteke AWT i Java 2D. Swing je prvi
razvila tvrtka Netscape Communications Corporation pod nazivom IFC (eng. Internet
Foundation Classes) krajem 1996. godine. Godinu dana poslije tvrtka Sun
Microsystems odluila je ukljuiti biblioteku IFC kao standardni dio jezika Java.
15

Opis koritenih tehnologija

Swing je nasljednik AWT biblioteke, izgraen na njenim komponentama u cilju


otklanjanja AWT-ovih nedostataka, koji su uglavnom bili vezani za preveliku ovisnost
o grafikim sueljima platforme. Swing-ove komponente se prikazuju preko Java 2D
biblioteke, koristei pritom AWT-ove mehanizme komunikacije sa platformom. Na taj
nain je postignuta udaljenost od platformskog koda, te mogunost kreiranja
sofisticiranijih grafikih komponenti u odnosu na AWT. Swing osim toga prua i
mogunost odabira grafikih tema (eng. Look And Feel), koje se mogu jednostavno
kreirati i mijenjati. Ovaj mehanizam omoguava Swing-ovim komponentama da
emuliraju izgled komponenti platforme na kojoj se izvode, ili da namjerno izgledaju
drugaije.

2.3.2. Arhitektura
Swing je platformski nezavisan MVC (eng. Model View Controller) okvir za izradu
grafikih suelja u programskom jeziku Java. [11] Izveden je kao jednodretveni
programski model sa slijedeim karakteristikama:

Platformska nezavisnost - Swing je platformski nezavisan jer kreira i


iscrtava vizualne komponente neovisno o platformskim komponentama,
koristei Javinu 2D grafiku biblioteku. AWT je za razliku od Swing-a gradio
grafika suelja od ve postojeih sistemskih komponenti, tako to ih je
pozivao kroz sistemski API.

Komponenta orijentacija - Swing je okvir temeljen na komponentama, tj.


objektima koji prate dobro poznate/specificirane karakteristine uzorke
ponaanja. Te komponente asinkrono generiraju dogaaje, imaju
ograniena svojstva i odgovaraju na dobro poznat skup naredbi
karakteristian za svaku komponentu. Swing-ove komponente su osim toga
i u skladu sa Java Beans konvencijom.

Prilagodljivost - sve komponente u Swing-u sadravaju vizualne modele,


koje je mogue prilagoditi korisnikim potrebama. Vizualni izgled
komponenti odreuje se kompozicijom standardnih grafikih elemenata kao
to su okviri prozora, klizai, ukrasi itd. Korisnik programski moe zadati
grafike elemente, boje, prozirnosti i slino, ovisno o svojstvima pojedine
komponente. Komponenta prema korisnikovu odabiru konfigurira prikladne
klase za prikazivanje (eng. renderer) takvih komponenti. Takoer je
mogue implementirati korisnike klase za prikaz, te na taj nain kreirati
jedinstvene grafike komponente.
Na slijedeoj slici prikazane su
implementacijama prikaza elija:

JTable komponente sa razliitim

16

Opis koritenih tehnologija

Slika 5. JTable komponente sa razliitim implementacijama prikaza elija

Proirivost - Swing predstavlja programski okvir vrlo razdijeljene arhitekture,


koja doputa korisniku implementaciju velikog broja suelja temeljnih
komponenti. Korisnici mogu izmijeniti postojee komponente i njihove
funkcionalnosti ili ih nadograditi.

Okvir lake kategorije (eng. Lightweight) - konfigurabilnost je rezultat


izbora da se ne koriste grafiki elementi samog operativnog sustava, ve
se prikazivanje komponenti izvodi preko Java 2D biblioteke. Na ovaj nain,
okvir ima vie slobode pri prikazivanju svojih komponenti i moe ih
prikazivati na bilo koji nain, bez ogranienja koja se mogu nametati zbog
odabira platforme. Ipak, jezgra svake komponente je AWT-ov Container.
To je osnovna klasa u AWT okviru koju nasljeuju sve Swing-ove klase. Na
ovaj nain Swing se prikljuuje na platformske procese, kao to su
preslikavanja ekrana, praenje pokreta mia i slino, te preko njih
komunicira sa sustavom.
Swing dakle nadograuje semantiku i prikaz platformskih komponenti sa
vlastitom semantikom i vizualizacijom. Npr. kad se pozove metoda paint()
definirana u svakom AWT-ovom Container-u, a time i u svakoj Swing-ovoj
komponenti, ona se potom prikazuje koristei Javine grafike mehanizme,
neovisno o platformi. Osim vizualizacije, nadogradnja se odnosi i na
mehanizam upravljanja dogaajima koji koriste komponente. Swing koristi
sloeniji model upravljanja od AWT-a meu komponentama, koji se tek na
kraju povezuje sa sustavom kroz AWT-ov model.

Konfigurabilnost - Swing jako ovisi o mehanizmima izvoenja. Ta ovisnost i


indirektni uzorci izvoenja omoguavaju mu trenutno reagiranje na
promjene u konfiguraciji. Aplikacije napisane u Swing-u tako npr. mogu
mijenjati grafike teme za vrijeme izvoenja. Osim toga, mogue je kreirati
17

Opis koritenih tehnologija

korisnike teme, koje ne mijenjaju bitno ostatak aplikacijskog koda i lako se


dodaju.
Primjeri nekoliko komercijalnih grafikih tema prikazani su na slijedeoj slici:

Slika 6. Komercijalne grafike teme za Swing

Slabo vezan / MVC okvir - Swing je biblioteka koja se velikim dijelom


oslanja na MVC arhitekturu. Taj tip arhitekture konceptualno razdvaja
podatke predstavljene korisniku od suelja preko kojeg su mu podaci
prezentirani. Zbog toga veina komponenti sadri modele specificirane u
obliku suelja, pri emu su u svim konkretnim komponentama sadrane
njihove podrazumijevane implementacije. Programer moe koristiti
podrazumijevane implementacije ili implementirati vlastite.

Modeli su odgovorni za pruanje dogaaja i konceptualnih svojstava precizno


definiranih sueljem za odreenu komponentu. Osim toga, modeli takoer pruaju i
programski nain prikljuivanja sluaa dogaaja na komponentama. Dogaaji koji
se pri tom oslukuju su usko vezani uz model i preko njega se interpretiraju
odgovarajuoj komponenti.
Za prikaz komponenti su odgovorne klase za prikazivanje. Implementiranjem
vlastitih klasa za prikaz komponente ili nasljeivanjem postojeih moemo joj
izmijeniti izgled i dio funkcionalnosti. Npr. moemo implementirati tablicu tipa JTable
koja u svojim elijama sadri slike umjesto teksta.
Funkcionalnost komponenti pruaju editorske klase. Npr. ako nam elije tablice
sadre objekte tipa JButton koritenjem editorske klase moemo specificirati

18

Opis koritenih tehnologija

ponaanje koje komponenta treba izvoditi prilikom klika na eliju, kao to je prikaz
dijaloga ili mijenjanje boje elije ili slino.
Na slijedeoj slici prikazana je Sun-ova Swing Demo aplikacija, u kojoj su
demonstrirane neke od vizualnih mogunosti Swing-a u kombinaciji sa Java 2D
bibliotekom, pod grafikim temama Windows i Motif:

Slika 7. Swing Demo aplikacija

19

Opis aplikacije

3. Opis aplikacije
3.1. Koncept, namjena i dizajn
Aplikacija izraena u okviru ovog diplomskog rada predstavlja grafiki MIDI
sekvencer, namijenjen izgradnji jednostavnih i sloenih MIDI sekvenci, te
spremanju u MIDI datoteke. Grafiko suelje aplikacije prikazano je na slijedeoj
slici:

Slika 8. Grafiko suelje aplikacije


Aplikacija se sastoji od etiri modula:

Glavni modul predstavlja glavni prozor aplikacije i sadri sve ostale


module,

Glavni sekvencer (Sequencer) - slui za izgradnju sloenih sekvenci,

Sporedni sekvencer (Loop Tool) - slui za izgradnju jednostavnih


sekvenci (eng. loop),

Kontrolni modul (Mixer) - upravlja iznosom glasnoe i reverba svih


raspoloivih MIDI kanala.

Podjela aplikacije na module odraz je njihove funkcionalnosti i programske


implementacije. Glavni i sporedni sekvencer su sline strukture, i ine zasebne
cjeline, pa su stoga programski implementirani kao podklase osnovnog
sekvencera. Kontrolni modul je po funkcionalnosti takoer zasebna cjelina, pa je
ovakva podjela najprimjerenija za preglednu organizaciju programskog koda, te
vizualnu preglednost aplikacije.

20

Opis aplikacije

3.2. Glavni modul


Glavni modul predstavlja osnovni modul aplikacije u kojem se nalaze glavni
prozor i izbornik aplikacije, preglednik instrumenata Explorer i ostali moduli,
Sequencer, LoopTool i Mixer. U ovom odjeljku opisani su glavni izbornik i
preglednik instrumenata, jer ine neposredni dio glavnog modula, dok su ostali
moduli zbog svoje izdvojenosti opisani u zasebnim odjeljcima.

3.2.1.Glavni izbornik
Glavni izbornik aplikacije sastoji se od tri podizbornika: File, Midi i Help.
3.2.1.1. Podizbornik File
Podizbornik File nudi osnovne operacije za upravljanje radom tj. projektima:

New - operacija postavlja program u poetno stanje.

Open - pokree se izbornik za odabir datoteke, prikazan na slijedeoj


slici:

Slika 9. Izbornik za otvaranje datoteke


Ukoliko se uita nepodrani oblik datoteke korisnik se obavjetava
porukom o pogreci:

Slika 10. Prikaz pogreke pri otvaranju datoteke

21

Opis aplikacije

Save - operacija pokree izbornik za spremanje trenutnog projekta u


datoteku. Ime i ekstenzija su proizvoljni. Predloena je upotreba jqs
ekstenzije. Izbornik za spremanje datoteke prikazan je na slijedeoj slici:

Slika 11. Izbornik za spremanje datoteke


Podaci se spremaju u tekstualnu XML datoteku. Ovaj oblik zapisa se
standardno koristi za serijalizaciju Swing objekata od verzije Jave 1.5.
Ukoliko doe do greke prilikom spremanja datoteke, korisniku se
prikazuje poruka o pogreci:

Slika 12. Prikaz pogreke pri spremanju datoteke

Quit - operacija vri zatvaranje aplikacije.

3.2.1.2. Podizbornik MIDI


Podizbornik MIDI nudi dvije operacije

Change Soundbank - operacija pokree izbornik za odabir datoteke sa


kolekcijom zvukova (eng. Soundbank) za Java sintesajzer, prikazan na
slijedeoj slici:

22

Opis aplikacije

Slika 13. Izbornik za odabir kolekcije zvukova


Kolekcija zvukova za Java sintesajzer obino je spremljena u datoteci sa
gm ekstenzijom, u GM (General MIDI) formatu. Uz aplikaciju dolazi
Javina podrazumijevana kolekcija zvukova, u najkvalitetnijoj verziji, koja
se uitava pri pokretanju programa, neovisno o trenutno instaliranoj
podrazumijevanoj kolekciji unutar aktivnog JRE-a (Java Runtime
Environment). Korisnike kolekcije zvukova u navedenom formatu
mogue je kreirati upotrebom komercijalnog programa Beatnik editor
tvrtke Beatnik, koja je dizajnirala Java Sound API.
Ukoliko doe do pogreke pri uitavanju kolekcije, korisnik se o tome
obavjetava slijedeom porukom:

Slika 14. Prikaz pogreke pri odabiru kolekcije zvukova


Render MIDI File - operacija pokree izbornik za spremanje datoteke sa
MIDI zapisom. Datoteke sa MIDI zapisom su u standardnom SMF (eng.
Standard Midi File) formatu, koji je propisala udruga MIDI Manufacturers
Association [12]. Taj format je
prepoznatljiv na svim raunalnim
platformama i MIDI sustavima. Podrazumijevana ekstenzija takvih
datoteka je MID, ali je mogue koristiti proizvoljnu. Izbornik je prikazan
na slijedeoj slici:

23

Opis aplikacije

Slika 15. Izbornik za spremanje MIDI zapisa


Ako prilikom izvravanja operacije doe do pogreke, korisnik se
obavjetava slijedeom porukom:

Slika 16. Prikaz pogreke pri spremanju MIDI zapisa


3.2.1.3. Podizbornik Help
Podizbornik Help nudi operaciju About koja prikazuje dijalog sa informacijama o
autoru i aplikaciji:

24

Opis aplikacije

Slika 17.Prikaz informacija o autoru i aplikaciji

3.2.2. Preglednik instrumenata


Preglednik instrumenata slui za odabir raspoloivih instrumenata iz uitane
kolekcije. Svaki od instrumenata mogue je presluati koritenjem kontrola za
pregled na dnu preglednika, te odabrati za koritenje u sekvencerima.
Preglednik je prikazan na slijedeoj slici:

Slika 18. Preglednik instrumenata


Za presluavanje eljenog instrumenta potrebno je odabrati jedan od 16
moguih MIDI kanala sintesajzera na kojem e se taj instrument odsvirati. Kanal
00 je podrazumijevani kanal za pregled instrumenata, dok je kanal 09 potrebno
odabrati ukoliko elimo presluavati perkusije. U MIDI standardu taj kanal se
naziva perkusijski kanal. Kod svih ostalih MIDI kanala se nakon odabira
instrumenta na njemu sviraju razliite note odabranog instrumenta. Posebnost
perkusijskog kanala je u tome to se na njemu svaka nota odsvira kao razliiti
perkusijski instrument. Instrumenti perkusijskog kanala odreeni su MIDI
standardom udruge MIDI Manufacters Association.
Instrumenti su organizirani u skupine pod nazivom bank. Svaka skupina sadri
po 128 instrumenata. Kod podrazumijevane kolekcije zvukova, u skupini Bank 0
nalaze se osnovni instrumenti, dok je skupina Bank 1 namijenjena za
presluavanje perkusija. Ona zapravo sadri popis perkusija na razliitim notama
25

Opis aplikacije

tog kanala. Nakon uitavanja u sevencere, perkusijskim instrumentima treba


dodijeliti perkusijski kanal. Ova operacija ne izvrava se automatski, jer korisnike
kolekcije zvukova ne moraju biti organizirane na ovaj nain.
Aplikacija je napisana na nain da radi sa podrazumijevanim softverskim
sintesajzerom, koji koristi resurse zvune kartice sustava. Implementacija je
takva, jer veina osobnih raunala ima jednu zvunu karticu, dakle jedan
raspoloivi sintesajzer. Preglednik koristi posebnu instancu sekvencera i mogue
ga je koristiti u isto vrijeme sa glavnim i sporednim sekvencerom, ali pri tome je
potrebno uzeti u obzir da se MIDI poruke koje dolaze sa sva tri sekvencera izvode
na jednom sintesajzeru. Budui da sintesajzer nakon primitka poruke za promjenu
instrumenta na kanalu sve daljnje note na tom kanalu svira sa odabranim
instrumentom, svaki razliiti instrument koji nije perkusija treba imati svoj posebni
kanal. Isto tako, kanal za presluavanje instrumenta bi trebalo koristiti samo za tu
svrhu.
Za odabir eljenog instrumenta mogue se koristiti strelicama za navigaciju, a
za presluavanje je mogue koristiti tipke na tastaturi:

Enter odabir instrumenta i uitavanje u sekvencere (dvostruki klik


miem obavlja istu operaciju),

Space presluavanje instrumenta,

Backspace zaustavljanje presluavanja.

3.3. Glavni sekvencer


Glavni sekvencer koristi se za izgradnju sloenih sekvenci. Sloena sekvenca
predstavlja sekvencu jednostavnih sekvenci. Jednostavne sekvence se grade u
sporednom sekvenceru.
Svaki instrument koji se uita iz preglednika u glavni sekvencer, automatski se
odabire u sporednom sekvenceru, dok mu se u glavnom dodjeljuje traka unutar
glavne sekvence. U njemu se gradi jednostavna sekvenca, koja se koristi kao
osnovni element sloene sekvence. Svaka traka slui za pohranu niza
jednostavnih sekvenci, koje se sviraju na odabranom instrumentu, u odabrano
vrijeme, sa odreenim brojem ponavljanja.
Glavni sekvencer prikazan je na slijedeoj slici:

26

Opis aplikacije

Slika 19. Glavni sekvencer


Osnovni dijelovi glavnog sekvencera su alatne trake i tablice, predoene na
prethodnoj slici:

Kontrole za sviranje - obavljaju operacije sviranja i zaustavljanja


sekvence, te sviranja sa ponavljanjem. Sviranje se pokree uz
automatsku izgradnju sekvence. Ukoliko je sviranje u tijeku gumb za
sviranje slui kao pauza, dok gumb za zaustavljanje uvijek vraa
sekvencer na poetak sekvence.

Spremanje sekvence - izvodi se na nain da se sve popunjene elije iz


desne tablice zapisuju kao jednostavne sekvence u glavnu sekvencu.
Prilikom editiranja tablice, potrebno je spremiti sekvencu da bi promjene
mogle nastupiti.

Tempo - se zadaje brojem otkucaja u minuti. Pri tome otkucaj oznaava


etvrtinsku notu. Tempo se nakon odabira automatski postavlja u oba
sekvencera.

Broj ponavljanja - ukupno trajanje glavne sekvence odreeno je brojem


ponavljanja jednostavnih sekvenci, tj. brojem stupaca desne tablice.
Ukoliko se odabere manji broj stupaca od trenutnog, podaci u stupcima
koji se uklanjaju se odbacuju. U suprotnome se dodaju prazni stupci.

Kontrola glasnoe - upravlja glasnoom cijele aplikacije. Raspon


glasnoe svih kanala sintesajzera se odreuje prema rasponu ove
kontrole.

Trake / Instrumenti - lijeva tablica sekvencera sadri imena pojedinih


traka sekvence. Odabirom elije u sporedni sekvencer se uitavaju
spremljeni podaci za pripadnu traku, kao to su ime, instrument, kanal i
27

Opis aplikacije

note koje ine njenu jednostavnu sekvencu. Poetna imena traka se


odreuju prema instrumentima koji su dodijeljeni pojedinim trakama pri
uitavanju iz preglednika. Dvostrukim klikom na eliju tablice ta imena se
mogu mijenjati prema elji. Pritiskom tipke Delete traka se uklanja iz
tablice.

Oznake jednostavnih sekvenci - prema njima se grade trake za pojedine


instrumente na prethodno opisan nain.

3.4. Sporedni sekvencer


Sporedni sekvencer slui za izgradnju jednostavnih sekvenci. Jednostavna
sekvenca gradi se koritenjem dugih i kratkih nota. Kratke note predstavljaju
etvrtinke i oznaavaju se jednom svijetlo plavom elijom, dok se duge note mogu
protezati kroz proizvoljan broj elija i oznaene su tamno plavom bojom. Duge
note obino se koriste za instrumente, a kratke za perkusije.
Jednostavne sekvence slue za izgradnju traka u glavnom sekvenceru. Kao to
su note graevni elementi jednostavnih sekvenci, tako su jednostavne sekvence
graevni elementi sloenih sekvenci. Jednostavne sekvence imaju proizvoljnu
duljinu od n*16 stupaca, jer je sekvencer namijenjen izradi najee koritenih
sekvenci zapisanih u 4/4 taktu.
Sve jednostavne sekvence su jednake duljine, to znai da se mijenjanjem
duine jednostavne sekvence mijenjaju sve jednostavne sekvence u projektu.
Duina sekvence obino se odreuje na poetku pisanja sekvence i iznosi 16, 32,
64 ili 128 stupaca. Ukoliko se ne eli koristiti ponavljanje sekvenci moe se
jednostavno odabrati vea duina za jednostavnu sekvencu, koja onda preuzima
ulogu sloene i ispunjava se notama.
Sporedni sekvencer prikazan je na slijedeoj slici:

28

Opis aplikacije

Slika 20. Sporedni sekvencer


Osnovni elementi sporednog sekvencera su alatne trake i tablice prikazane na
prethodnoj slici:

Kontrole za sviranje - obavljaju operacije sviranja i zaustavljanja


sekvence, te sviranja sa ponavljanjem. Sviranje se pokree uz
automatsku izgradnju sekvence. Ukoliko je sviranje u tijeku gumb za
sviranje slui kao pauza, dok gumb za zaustavljanje uvijek vraa
sekvencer na poetak sekvence.

Spremanje sekvence - izvodi se na nain da se sve popunjene elije iz


desne tablice zapisuju u jednostavnu sekvencu. Prilikom editiranja
tablice, potrebno je spremiti sekvencu da bi promjene mogle nastupiti.

Odabir trake - svaka jednostavna sekvenca gradi jednu traku sloene


sekvence, na nain da se svira na odabranim mjestima, odabrani broj
puta. Nakon odabira trake, u sporedni sekvencer se uitavaju njene
postavke kao to su instrument, MIDI kanal na kojem se instrument svira
i glasnoa trake.

MIDI kanal - odreuje na kojem e se kanalu sintesajzera svirati


odabrana traka, tj. instrument koji joj je pridruen. Kanal automatski
ostaje sauvan nakon promijene.

Duljina sekvence - sve jednostavne sekvence imaju istu duljinu odreene


ovim parametrom. Ako se duljina sekvence povea, tablica se ispunjava
praznim elijama. U suprotnom, sve note iza granice duljine nove
sekvence se odbacuju.

Kontrola glasnoe slui odreivanju iznosa glasnoe sekvenc.


Vrijednost se sprema odmah nakon promijene.

Visine nota - pokazuju mogue visine nota s kojima se gradi jednostavna


sekvenca. Raspon raspoloivih nota se prostire na 10 oktava. Srednja
nota u tom rasponu je C5.

Duga nota - oznaka za instrumente koji proizvode tonove proizvoljnog


trajanja. Poetak note odreuje se prvom, a kraj zadnjom tamno plavom
elijom na istoj visini.

Kratka nota - obino se koristi za perkusije ili kratke tonove.

3.5. Kontrolni modul


Kontrolni modul prikazan je na slijedeoj slici:

29

Opis aplikacije

Slika 21. Kontrolni modul


Kontrolni modul se koristi za podeavanje iznosa glasnoe i reverba svih
raspoloivih MIDI kanala.
Reverb je zvuna pojava koja se dogaa pri generiranju zvuka u prostoru.
Nakon to se prestane proizvoditi zvuk, ovisno o prostoru u kojem se zvuk
rasprostire, dolazi do stvaranja raznih odjeka, zbog kojih se zvuk uje jo neko
vrijeme, ali mu intenzitet brzo opada. Efekt reverba se moe jasno primijetiti kad
se zvuk proizvodi npr. u tunelu, katedralama, peinama i slino. Razlikuje se od
obine jeke po tome to se sastoji od mnotva manjih i brzih odjeka, koji se ne
mogu jasno razaznati. Efekt pridonosi prostornosti zvuka. Odsvirane note se ne
odsijecaju naglo pri prestanku trajanja, ako se pri tom koristi reverb.

30

Programska izvedba aplikacije

4. Programska izvedba aplikacije


4.1. Pregled i organizacija koda
Kod aplikacije raspodijeljen je u tri osnovna paketa:

hr.fer.npecanac.diplomski.gui - paket sadri klase koje grade grafiko


suelje aplikacije,

hr.fer.npecanac.diplomski.sound - paket sadri klase koje ine zvune


komponente aplikacije,

hr.fer.npecanac.diplomski.utility - paket sadri pomone klase.

4.1.1. Klase grafikog suelja


Klasni dijagram paketa sa klasama za izradu grafikog suelja prikazan je na
iduoj slici:

Slika 22. Klase grafikog suelja

31

Programska izvedba aplikacije

Znaenje isprekidanih linija na slici je slijedee:

Crvene linije oznaavaju nasljeivanje i pokazuju u smjeru nadklase,

Smee linije oznaavaju instanciranje klase i pokazuju u smjeru klase


koja se instancira,

Zelene linije oznaavaju referenciranje meu klasama.

Grafiko suelje sastoji se od etiri osnovne klase, koje predstavljaju etiri


prethodno opisana modula:

MainGUI - glavna i najvea klasa, predstavlja glavni modul iz kojeg se


pokree aplikacija,

SequencerGUI - glavni sekvencer,

LoopToolGUI - sporedni sekvencer,

MixerGUI - kontrolni modul.

Ostale klase prikazane na dijagramu pruaju funkcionalnosti koje se koriste u


osnovnim klasama:

BasicSequencerGUI - klasa predstavlja sekvencersku nadklasu iz koje


se izvode klase glavnog i sporednog sekvencera. Sadri sve zajednike
funkcionalnosti oba sekvencera.

TrackProperties - klasa se koristi kao uzorak za spremanje podataka o


svojstvima traka iz glavnog sekvencera. Predstavlja sloeni tip podatka
koji sadri ime trake, oznaku instrumenta koji se svira na toj traci, MIDI
kanal, glasnou trake i jednostavnu sekvencu koja se na toj traci izvodi.

TableCellColorEditorSequencer - klasa predstavlja prilagoeni editor


elija za glavni sekvencer. U njoj se definira ponaanje tablice u sluaju
odabira elije, tj. nain bojanja.

TableCellColorEditorLoopTool - klasa predstavlja prilagoeni editor elija


za sporedni sekvencer.

TableCellColorRenderer - klasa odreuje prilagoeni nain prikaza elija


tablice. Preko nje se definira prikaz boja u elijama, oznaavanje svakog
etvrtog stupca, oznaavanje trenutno aktivnog stupca, prikazivanje
editiranih elija i slino.

TableModelSequencer - klasa definira prilagoeni tablini model za


desnu tablicu sekvencera. Preko modela se rukuje sa zaglavljem tablice,
odreuju joj se dimenzije, koriteni oblici selektiranja i slino.

4.1.2. Zvune klase


Aplikacija koristi dvije zvune klase koje se koriste kao omotai oko klasa
sekvencera i sintesajzera Java Sound API-ja:

32

Programska izvedba aplikacije

SequencerWrapper - klasa se koristi kao omota oko implementacije


sekvencera Java Sound API-ja. Omoguava direktno sviranje jedne note
danog instrumenta bez potrebe za izgradnjom sekvence (koristi se u
pregledniku instrumenata), definira metodu za izgradnju MIDI dogaaja i
njihov zapis u trake, te se brine o popunjavanju sekvence metaporukama koje generiraju meta-dogaaje, preko kojih se u grafikom
suelju prati i oznaava trenutna pozicija u sekvenci.

SynthesizerWrapper - klasa se koristi kao omota oko implementacije


sintisajzera Java Sound API-ja. Implemetira metode za uitavanje
kolekcija instrumenata iz datoteke, za pristup raspoloivim
instrumentima te za postavljanje i itanje iznosa reverba i glasnoe MIDI
kanala.

4.1.3. Pomone klase


U paketu sa pomonim klasama nalazi se klasa LocalDir koja slui za dohvat
reference i imena direktorija u kojem je aplikacija pokrenuta.

4.2. Implementacija zvunog sustava


Zvuni sustav implementiran je kroz prethodno opisane klase omotae oko
sekvencera i sintesajzera Java Sound API-ja. Omotai se koriste u svrhu
proirivanja funkcionalnosti dostupnih zvunih klasa. Koritenje nasljeivanja u
ovu svrhu bi bio loginiji pristup, meutim to nije mogue, jer su Sequencer i
Synthesizer suelja definirana u okviru API-ja, dok su objekti koji ih implementiraju
izvedeni u platformskom kodu i ne moe ih se direktno nasljeivati. Nasljeivanje
je mogue jedino u sluaju vlastite implementacije tih suelja.

4.2.1. Klasa SynthesizerWrapper


Klasa predstavlja omota oko implemetacije suelja Synthesizer u Java Sound
API-ju. Sadri slijedee lanske varijable:

Synthesizer m_Synthesizer - implementacija suelja Synthesizer,

Instrument[] m_Instruments - polje raspoloivih instrumenata,

MidiChannel[] m_Channels - polje raspoloivih MIDI kanala,

SoundBank m_SoundBank - referenca na kolekciju instrumenata.

U konstruktoru klase obavlja se dohvat sistemske implementacije suelja


Synthesizer i uitavanje kolekcije instrumenata iz datoteke priloene uz aplikaciju.
Ukoliko datoteka ne postoji, pokuava se uitati podrazumijevana kolekcija iz JREa, ako postoji. U sluaju neuspjeha neke od operacija dolazi do iznimke.
Kod konstruktora prikazan je u slijedeem ispisu:
public SynthesizerWrapper (File p_SoundBankFile) {
// instanciranje sintisajzera
try {
m_Synthesizer = MidiSystem.getSynthesizer();
33

Programska izvedba aplikacije


}
catch (Exception ex) {
throw new RuntimeException(
"Unable to instantiate a Synthesizer!");
}
// otvaranje sintisajzera
try {
m_Synthesizer.open();
}
catch (Exception ex) {
throw new RuntimeException(
"Unable to open the a Synthesizer!");
}
// dohvat MIDI kanala
m_Channels = m_Synthesizer.getChannels();
// uitavanje kolekcije zvukova iz datoteke
if (p_SoundBankFile != null) {
try {
loadSoundbankFromFile(p_SoundBankFile);
}
catch (Exception e) {

// ako dode do iznimke,


// pokusava se uitati sistemska kolekcija (jre)
m_Soundbank = m_Synthesizer.getDefaultSoundbank();
e.printStackTrace();
}

// konstruktoru nije predana datoteka sa kolekcijom


// slijedi uitavanje sistemske kolekcije zvukova (jre)
else {
m_Soundbank = m_Synthesizer.getDefaultSoundbank();
// provjera
if (m_Soundbank != null)
{
// dohvat liste raspoloivih instrumenata
m_Instruments =
m_Synthesizer.getAvailableInstruments();
// provjera
if (m_Instruments == null){
throw new RuntimeException(
"No instruments available!");
}
// uitavanje instrumenata
m_Synthesizer.loadAllInstruments(m_Soundbank);
}
else {

}
}

throw new RuntimeException(


"Unable to get a default soundbank!");

34

Programska izvedba aplikacije

Klasa sadri slijedee javne metode:

boolean isOpen() - metoda vraa status sintesajzera,

Patch getPatch(int p_InstIndex) - metoda vraa Patch objekt za predani


indeks instrumenta,

Instrument getInstrument(int p_InstIndex) - metoda za predani indeks


vraa odgovarajuci Instrument,

MidiChannel getChannel(int channel) - metoda za dohvat pojedinog


kanala sintesajzera,

close() - metoda zatvara sintesajzer i otpusta sistemske resurse,

Int getInstrumentsCount() - metoda vraa broj raspoloivih instrumenata,

void loadSoundbankFromFile(File p_SoundbankFile) - metoda uitava


kolekciju zvukova iz datoteke,

void setChannelVolume(int p_Channel, int p_Volume) - metoda postavlja


iznos glasnoe pojedinog MIDI kanala,

void setChannelReverb(int p_Channel, int p_Reverb) - metoda postavlja


iznos reverba pojedinog MIDI kanala.

4.2.2. Klasa SequencerWrapper


Klasa predstavlja omota oko implemetacije suelja Sequencer u Java Sound
API-ju. Sadri slijedee lanske varijable:

SynthesizerWrapper m_SynthesizerWrapper
omota sintesajzera,

Sequencer m_Sequencer - implementacija suelja Sequencer,

Sequence m_Sequence - zvuna sekvenca,

Track m_MetaTrack - traka sa meta-podacima za oznaavanje pozicije u


sekvenci,

int m_SequencePPQ - trajanje etvrtinke,

boolean m_Looping - oznaka ponavljanja sekvence.

- referenca na

U konstruktoru klase se obavlja dohvat sistemske implementacije suelja


Sequencer, postavljanje osnovnih parametara sekvencera te spajanje sa
omotaem sintesajzera. U sluaju neuspjeha neke od operacija dolazi do iznimke.
Kod konstruktora prikazan je u slijedeem ispisu:
public SequencerWrapper(SynthesizerWrapper p_SynthesizerWrapper,
int p_SequencePPQ) {
// provjera parametara
if (p_SequencePPQ < 1 || p_SequencePPQ > 1000)
throw new RuntimeException(
"Unable to instantiate SequencerWrapper! Wrong PPQ!);

35

Programska izvedba aplikacije


// provjera dostupnosti sintisajzera
if (p_SynthesizerWrapper == null || !p_SynthesizerWrapper.isOpen())
throw new RuntimeException(
"Unable to instantiate SequencerWrapper!
Synthesizer is not available!");
// instanciranje sekvencera
try {
m_Sequencer = MidiSystem.getSequencer(false);
}
catch (Exception ex) {
throw new RuntimeException(
"Unable to instantiate Sequencer!");
}
// postavljanje reference na sintisajzer
m_SynthesizerWrapper = p_SynthesizerWrapper;
// otvaranje sekvencera
try {
m_Sequencer.open();
// povezivanje sa sintisajzerom
m_Sequencer.getTransmitter().setReceiver(
m_SynthesizerWrapper.getSynthesizer().getReceiver());
}
catch (Exception ex) {
throw new RuntimeException(
"Unable to open Sequencer!");
}
// postavljanje trajanja cetrvrtinke
setSequencePPQ(m_SequencePPQ);
try {

m_Sequence = new Sequence(Sequence.PPQ, m_SequencePPQ);


}
catch (Exception e) {
e.printStackTrace();
}
}

Klasa sadri slijedee javne metode:

void PlayMidiInstrumentPreview (int p_InstIndex, int p_Channel, int


p_Note, int p_Velocity ) - metoda svira notu C5 odabranog instrumenta,
na odabranom kanalu, uz zadanu jainu,

void PlayMidiNoteOnChanell (int p_InstIndex, int p_Channel, int p_Note,


int p_Velocity) - metoda svira notu C5 odabranog instrumenta, na
odabranom kanalu, uz zadanu jainu, direktno preko sintesajzera, tj. bez
koritenja sekvencera,

void createMidiEvent (int p_MidiCommand, int p_Channel, int p_Note,


long p_Tick, int p_Velocity) - metoda kreira MIDI poruku klase
ShortMessage i zamata je u MidiEvent,

void createAndWriteMidiEvent (int p_MidiCommand, int p_Channel, int


p_Note, long p_Tick, int p_Velocity, Track p_Track) - metoda kreira MIDI
36

Programska izvedba aplikacije

poruku klase ShortMessage, zamata je u MidiEvent i upisuje u danu


traku,

void stop () - metoda zaustavlja sviranje (bez vraanja na poetak


sekvence),

void start (long p_TickPosition) - metoda postavlja sekvencu i kree od


zadane pozicije,

void resume() - metoda nastavlja sviranje u trenutnoj sekvenci od


trenutne pozicije (ako je to mogue),

void addMetaEventListener(MetaEventListener p_Listener) - metoda


sekvenceru dodaje slusa meta-dogaaja,

void createMetaTrack() - metoda sekvenci dodaje traku sa dogaajima


na svakom tiku,

Byte[] convertInt2Bytes(int p_IntValue) - metoda pretvara tip int u niz


bajtova,

int convertBytes2Int(byte [] p_ByteArray) - metoda niz bajtova pretvara u


tip int,

boolean isRunning() - metoda vraa status sekvencera,

void clearSequence() - metoda brie sekvencu.

4.3. Implementacija grafikog suelja


Grafiko suelje aplikacije sastavljeno je iz etiri osnovna grafika modula.
Svaki modul predstavljen je svojom vizualnom klasom, dizajniranom koritenjem
dodatka Visual Editor u sklopu programske okoline Eclipse [14] .
Struktura koda vizualnih klasa prikazana je slijedeim uzorkom:
// trenutni paket
// uvoz koritenih klasa
public class ImeKlase {
// konstante
// lanske varijable
// vizualne komponente
// konstruktor
// glavna inicijalizacijska metoda
// inicijalizacijske metode vizualnih komponenti
// get / set metode
// javne metode
// privatne metode
// pomone klase
}
37

Programska izvedba aplikacije

Sve klase napisane su u skladu sa JavaBeans konvencijom. [15] U odnosu na


standardne Java klase, jedina bitna razlika u strukturi koda vizualnih klasa je
glavna inicijalizacijska metoda, koja se pokree iz konstruktora. Ta metoda
inicijalizira modul i pokree inicijalizacijske metode svih njegovih vizualnih
komponenti.

4.3.1. Izvedba glavnog modula


Glavni modul predstavljen je klasom MainGUI. Ova klasa predstavlja glavnu i
najveu klasu aplikacije, te definira njezinu osnovnu grafiku strukturu, na koju se
nadovezuju ostali moduli. Pri pokretanju aplikacije obavlja inicijalizaciju i
povezivanje ostalih grafikih modula i zvunog sustava.
Klasa sadri slijedee lanske varijable:

SequencerWrapper m_Sequencer,

SequencerWrapper m_LoopTool,

SequencerWrapper m_PreviewPlayer,

SynthesizerWrapper m_Synthesizer.

Prve tri varijable su reference na omotae oko sekvencera za preglednik


instrumenata, te glavni i sporedni sekvencerski modul. Sekvenceri se instanciraju
u glavnom modulu pri inicijalizaciji zvunog sustava, a potom se dodijeljuju
odgovarajuim modulima i meusobno povezuju. etvrta varijabla je referenca na
omota oko sintesajzera, koja se instancira i povezuje u istoj metodi. Ostale
lanske varijable ine vizualne komponente, meu kojima su i klase ostala 3
modula. Klase modula se u glavnom modulu nazivaju jPanelSequencer,
jPanelLoopTool i jPanelMixer, jer se sve izvode iz JPanel klase i ine dio
hijerarhije vizualnih JavaBean klasa glavnog modula.
Pokretanje aplikacije izvodi se iz statike metode main() glavnog modula.
Metoda je prikazana na slijedeem ispisu:
public static void main(String[] args) {
// metoda za pokretanje Swing aplikacije
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// instanciranje glavnog modula
MainGUI application = new MainGUI();
// prikaz glavnog prozora
application.getJFrame().setVisible(true);
try {

// inicijalizacija zvunog sustava


application.initializeSoundSystem();
// inicijalizacija grafikog suelja
Application.connectGUIModules();
38

Programska izvedba aplikacije


catch(Exception ex){
// hvatanje i prikazivanje iznimke
JOptionPane.showMessageDialog(
null, ex.getMessage(),"Exception info:",
JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
}

Za pokretanje Swing aplikacija unutar glavne metode koristi se metoda:


void static SwingUtilities.invokeLater (Runnable mainClass).
Ova metoda slui za pokretanje klase nakon zavretka obavljanja svih dogaaja
u grafikom suelju. Na taj nain se aplikacija pokree tek nakon to su sve
komponente obavile inicijalizaciju i spremne su za prikazivanje.
Glavna inicijalizacijska metoda klase je metoda:
JFrame getJFrame()
U ovoj metodi obavlja se konfiguriranje glavnog prozora aplikacije, te njegovih
komponenti. Nakon prikaza glavnog prozora prvo se inicijalizira zvuni sustav, a
potom se grafiki moduli povezuju sa zvunim komponentama i meusobno.
Inicijalizacija zvunog sustava obavlja se metodom:
private void initializeSoundSystem().
Kod metode prikazan je u slijedeem ispisu:
private void initializeSoundSystem() {
// dohvat lokalnog direktorija
LocalDir localDir = new LocalDir();
m_LocalDir = localDir.getLocalDirRef();
// instanciranje sintisajzera sa kolekcijom zvukova iz datoteke
String fileName = localDir.getLocalDirName();
fileName = fileName + "/" + "soundbanks" +
"/" + "soundbank-deluxe.gm";
File soundBankfile = new File(fileName);
m_Synthesizer = new SynthesizerWrapper(soundBankfile);
// instanciranje sekvencera i povezivanje sa sintisajzerom
m_Sequencer = new SequencerWrapper(m_Synthesizer, 4);
m_LoopTool = new SequencerWrapper(m_Synthesizer, 4);
m_PreviewPlayer = new SequencerWrapper(m_Synthesizer, 4);
}

Metoda instancira sintesajzer sa podrazumijevanom kolekcijom instrumenata, a


potom instancira sekvencere, predajui im sintesajzer kao argument. Povezivanje
se obavlja u konstruktorima sekvencera.

39

Programska izvedba aplikacije

Meusobno povezivanje grafikih modula i spajanje sa zvunim modulima


obavlja metoda:
void connectGUIModules ().
Ova metoda predstavlja sredinju toku aplikacije u kojoj se obavljaju spajanja
svih klasa. Spajanje se izvodi postavljanjem referenci u klasama, analogno
studijskom spajanju hardverskih komponenti. Osim spajanja klasa, na poetku
funkcije se obavlja i uitavanje dostupnih instrumenata u preglednik.
Kod metode prikazan je u slijedeem ispisu:
private void connectGUIModules () {
/* Explorer */
loadInstrumentsToExplorer();
/* Sequencer */
// povezivanje SequencerGUI - SequencerWrapper
jPanelSequencer.setSequencer(m_Sequencer);
// povezivanje Sequencer GUI - MixerGUI
jPanelSequencer.setMixerGUI(jPanelMixer);
/* LoopTool */
// povezivanje LoopToolGUI - SequencerWrapper
jPanelLoopTool.setSequencer(m_LoopTool);
// povezivanje LoopToolGUI - MixerGUI
jPanelLoopTool.setMixerGUI(jPanelMixer);
/* LoopTool - Sequencer */
// povezivanje SequencerGUI - LoopToolGUI
jPanelSequencer.setLoopToolGUI(jPanelLoopTool);
// povezivanje LoopToolGUI SequencerGUI
jPanelLoopTool.setSequencerGUI(jPanelSequencer);
/* Mixer */
// povezivanje MixerGUI - SynthesizerWrapper
jPanelMixer.setSynthesizer(m_Synthesizer);
// povezivanje Mixer - LoopToolGUI
jPanelMixer.setLoopToolGUI(jPanelLoopTool);

4.3.2. Izvedba osnovnog sekvencerskog modula


Osnovni sekvencerski modul ini klasa BasicSequencerGUI. Ova klasa
predstavlja osnovnu vizualnu klasu iz koje se izvode glavni i sporedni sekvencer.
Klasa proiruje osnovnu kontejnersku klasu JPanel funkcionalnostima zajednikim
za oba sekvencera, kao to su sluai na kontrolama za sviranje, metode za
upravljanje dimenzijama desne tablice, klase za bojanje elija, metoda za
upravljanje oznakom trenutne pozicije u sekvenci i slino. Na taj nain, sve
modifikacije zajednikih funkcionalnosti izvode se na jednom mjestu.
Klasa sadri slijedee lanske varijable:

int m_TableRightColumnCount,
40

Programska izvedba aplikacije

int m_TablesRowCount,

int m_TableRowHeight,

int m_TableLeftColumnWidth,

int m_TableRightColumnWidth,

int m_ActiveColumn,

Vector<TrackProperties> m_trackProperties,

SequencerWrapper m_Sequencer,

MainGUI m_MainGUI.

Prvih pet varijabli definiraju svojstva tablica sekvencera kao to su broj stupaca
i redaka tablica, te visina i irina elija. Varijabla m_ActiveColumn oznaava
osvijetljeni stupac, tj. trenutnu poziciju u sekvenci. Kolekcija m_trackProperties
koristi se za spremanje svojstava pojedinih traka iz glavne sekvence. Sastoji se od
niza TrackProperties objekata. Zadnje dvije varijable su reference na sekvencer i
glavni modul aplikacije.
Ostale lanske varijable ine vizualne komponente podijeljene na skupinu
privatnih i skupinu zatienih komponenti. Prva skupina se koristi samo u okviru
ove klase, dok se druga skupina koristi izravno u izvedenim klasama.
Klasa sadri etiri konstruktora:

BasicSequencerGUI (),

BasicSequencerGUI (int p_RowCount, int p_ColumnCount),

BasicSequencerGUI (int p_RowCount, int p_ColumnCount,


p_MainGUI, SequencerWrapper p_SequencerGUI),

BasicSequencerGUI (int p_RowCount, int p_ColumnCount, MainGUI


p_MainGUI, SequencerWrapper p_SequencerGUI, String
p_TableLeftTitle).

MainGUI

Osnovni konstruktor koristi konstruktor nadklase JPanel, te nakon njega


pokree inicijalizacijsku metodu initialize(). Ostali konstruktori sadre opcionalne
parametre, koji se takoer mogu postaviti koritenjem javnih metoda za
postavljanje lanskih variabli (eng. geter). Inicijalizacijska metoda prikazana je u
slijedeem ispisu:
private void initialize() {
// postavljanje vizualnih parametara klase
this.setSize(800, 200);
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.setPreferredSize(new Dimension(300, 30));
this.add(getJPanelTop());
this.add(Box.createRigidArea(new Dimension(0,1)));
this.add(getJScrollPane());
// Slusai
41

Programska izvedba aplikacije


// slusa promjena na kontrolama za sviranje - play / pause
jButtonPlayPause.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
if (getSequencer().isRunning()) {
// pauza (stop() izvodi samo zaustavljanje,
// bez vraanja na poetak)
getSequencer().stop();
}
else {
// metoda za nadogradnju
listenerPlay(false, true, getActiveColumn());
}
}
});
// slusa promjena na kontrolama za sviranje - play looped // pause
jButtonPlayPauseLooped.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
if (getSequencer().isRunning()) {
getSequencer().stop();
}
else {
// metoda za nadogradnju
listenerPlay(true, true, getActiveColumn());

}
}
});
// slusa na playback kontrolama - stop
jButtonStop.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// javna metoda
stopPlayBack();
}
});
// osvjetljavanje prve kolone
setPlayingColumn(0);
}

Metoda prvo postavlja vizualne parametre klase, potom registrira sluae i na


kraju osvjetljava prvi stupac desne tablice.
Sluai su izvedeni kao anonimne unutarnje klase koje pokreu javne metode
klase ili metode oznaene kao metode za nadogradnju. Te metode implementirane
su u klasi praznim tijelima, jer su namijene implementaciji u nadklasama. Potpis tih
metoda zapoinje sufiksom listener (eng. slua). Sluai na kontrolama za
sviranje i sviranje s ponavljanjem izvedeni su takvim metodama jer se proces
izgradnje sekvenci prije sviranja razlikuje u glavnom i sporednom sekvenceru.
Zaustavljanje je jednako, pa je taj slua izveden javnom metodom, zajednikom
za oba sekvencera.
Klasa sadri slijedee javne metode:

void stopPlayBack() - metoda zaustavlja sviranje sekvence i postavlja


poetnu poziciju,

42

Programska izvedba aplikacije

void clearSequence() - metoda isti sekvencu tj. brie sve zvune


zapise,

int getBarCount() - metoda vraa broj stupaca desne tablice,

void setHeaderTableRight() - metoda postavljanja zaglavlja desne tablice


(ispisuje vremensku liniju),

void setHeaderTableLeft(String p_HeaderLeftTable) - metoda postavlja


zaglavlje lijeve tablice (komponente),

void repaintTables(boolean p_RepaintLeft, boolean, p_RepaintRight)


metoda osvjeava tablice,

Vector getTableRightColumnIdentifiers() - metoda postavlja zaglavlja


stupaca desne tablice,

void setVisibleToolbars(boolean p_Playback, boolean p_Track, boolean


p_Channel, boolean p_BPM, boolean p_Bars, boolean p_Volume) metoda odreduje vidljive alatne trake,

void setBPM (Double p_bpm) - metoda postavlja tempo u BPM-ima (eng.


Beats per minute),

Double getBPM() - metoda dohvaa tempo u BPM-ima,

void setBarCounterOptions(int p_Value, int p_Min, int p_Max, int p_Step)


- metoda namjeta opcije na brojau stupaca,

void setChannelList(String[] p_Channels) - metoda postavlja popis


kanala u izbornik za odabir kanala,

void setRenderer(TableCellEditor p_TEditor) - metoda postavlja


podrazumijevanu klasu za prikaz elija,

void setPlayingColumn(int p_Column) - metoda oznaava zadani stupac


u tablici,

void highlightColumn(int p_Column, boolean p_HLightOn) - metoda


oznaava ili ponitava oznaavanje odabranog stupca.

Izvedene klase nadograuju slijedee zatiene metode, koje se pozivaju iz


sluakih anonimnih klasa vizualnih komponenti, implementiranih na nain
prikazan u inicijalizacijskoj metodi klase:

void listenerMetaEventFired(MetaMessage event) - metoda koja se


pokree pri generiranju meta dogaaja na sekvenceru,

void listenerSetBarCount(int p_BarCount) - metoda se pokree kod


promijene veliine sekvence,

void listenerVolumeStateChanged() - metoda koja se pokree pri


promijeni vrijednosti glasnoe,

void listenerTableSelectedCellChanged(Jtable m_table, int p_SelRow, int


p_SelColumn) - metoda koja se pokree pri promjeni selekcije u tablici,

43

Programska izvedba aplikacije

void listenerPlay(boolean p_Loop, boolean store, long p_TickPosition) metoda koja pokree sviranje sekvence,

void listenerStoreTrack() - metoda koja pohranjuje podatke iz tablice i


gradi zvunu sekvencu.

Klasa osnovnog sekvencerskog modula sadri dvije pomone klase:

SelectionListener - klasa se koristi za upravljanje selekcijom nad


tablicom. Predstavlja sluaku klasu koja se registrira nad tablicom,
dohvaa poziciju selektirane elije tablice, te pokree vanjsku metodu za
nadogradnju koja izvodi potrebne operacije nad elijom, ovisno o
potrebama sekvencera.

TColors - klasa sadri konstante koje predstavljaju boje desne tablice u


RGB zapisu (Red Green Blue). Na ovaj nain, nijanse bojanja se mogu
izmijeniti jednostavnim mijenjanjem vrijednosti zadanih konstanti.

4.3.3. Izvedba glavnog sekvencerskog modula


Klasa glavnog sekvencerskog modula izvedena je iz prethodno opisane klase
osnovnog sekvencerskog modula. Ova klasa upravlja izgradnjom i sviranjem
glavne sekvence.
Klasa sadri slijedee lanske varijable:

boolean m_Loading - zastavica koja oznaava uitavanje podataka i


onemoguava sluake klase,

LoopToolGUI m_LoopToolGUI - referenca na sporedni sekvencerski


modul,

MixerGUI m_MixerGUI - referenca na kontrolni modul,

int m_LoopToolBarCount - duina sekvence sporednog sekvencerskog


modula.

Konstruktori su izvedeni kao kod osnovnog modula, pa imamo jedan osnovni i


tri opcionalna konstruktora sa dodatnim parametrima:

SequencerGUI(),

SequencerGUI(int p_RowCount, int p_ColumnCount),

SequencerGUI(int p_RowCount, int p_ColumnCount, MainGUI


p_MainGUI, SequencerWrapper p_SequencerGUI),

SequencerGUI(int p_RowCount, int p_ColumnCount, MainGUI


p_MainGUI, SequencerWrapper p_SequencerGUI, String p_TableLTitle).

Inicijalizacijska metoda klase prikazana je slijedeim ispisom:


private void initialize(){
// postavljanje prikazivaa elija za desnu tablicu
44

Programska izvedba aplikacije


setRenderer(new TableCellColorEditorSequencer());
// postavljanje vidljivih alatnih traka
setVisibleToolbars(true, false, false, true, true, true);
// namjetanje brojaa stupaca
setBarCounterOptions(16, 16, 999, 1);
// inicijalizacija popisa traka
setTrackProperties(new Vector<TrackProperties>());
// sprijeavanje podrazumijevane akcije pritiskom na "delete"
turnOffDefaultAction(jTableLeft, "DELETE");
// postavljanje glavne aplikacijske kontrole glasnoe
setMasterVolume(127);
// dodavanje slusaa promjena na kontrolu glasnoe
jSliderVolume.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if (m_MixerGUI != null) {
m_MixerGUI.setGain(jSliderVolume.getValue());
}
}
});
// dodavanje sluaa za uklanjanje traka na lijevu tablicu
jTableLeft.addKeyListener(new KeyListener(){
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
if(e.getKeyChar() == KeyEvent.VK_DELETE)
{
int index = jTableLeft.getSelectedRow();
if(index != -1) removeTrackFromTable(index);
}
}
public void keyTyped(KeyEvent e) {
}
});
// dodavanje sluaca promjena na lijevu tablicu
// slusac vrsi sinhronizaciju kolekcija popisa traka
// izmedu sekvencera i looptoola
jDefaultTableModelLeft.addTableModelListener(
new TableModelListener(){
public void tableChanged(TableModelEvent e) {
if (!isLoading()) {
int index = e.getLastRow();
switch(e.getType()){
case TableModelEvent.INSERT:
break;
case TableModelEvent.DELETE:
if(index != 0)
index--;
break;
case TableModelEvent.UPDATE:
String tName = (String)jDefaultTableModelLeft.getValueAt(index, 0);
try {
45

Programska izvedba aplikacije


// provjera da li traka postoji
if ( index <
setTrackProperties().size()) {
// update u kolekciji
getTrackProperties().get(index).setTrack(tName);
}
}
catch (Exception ex)
{}
break;
default:
return;
}
synchronizeWithloopTool(index);
}
}
});
}

Inicijalizacijska metoda organizirana je na isti nain kao u klasi osnovnog


sekvencerskog modula. Prvo se konfigurira modul, pa se dodaju sluai. Pri
konfiguraciji modula, zadaje se prilagoeni editor elija, odabiru se vidljive alatne
trake koje koristi ovaj sekvencer, namjeta se poetni broj stupaca tablice,
inicijalizira se kolekcija sa svojstvima traka, namjeta poetni nivo glasnoe
aplikacije i ukida funkcionalnost nad tablicom pri koritenju Delete tipke. Ova
funkcionalnost se potom mijenja koritenjem sluaa, i slui brisanju odabranih
traka.
Modulu se dodaje slua koji reagira na promjenu traka u tablicama, te koji
usklauje podatke o trakama izmeu glavnog i sporednog sekvencera. Slua na
kontroli glasnoe se koristi za kontrolu ukupne glasnoe cijele aplikacije, i preko
njega je glavni sekvencer povezan sa kontrolnim modulom. Promjena ukupne
glasnoe nije vidljiva na kontrolama kontrolnog modula, jer se sve vrijednosti
kontrola skaliraju prema njenoj trenutnoj vrijednosti.
Klasa sadri slijedee javne metode:

void addTrackToTable(Instrument p_Instrument) - metoda obavlja


dodavanje instrumenata u tablicu i popunjavanje kolekcije sa svojstvima
traka,

void removeTrackFromTable(int p_Index) - metoda uklanja traku iz


tablice,

void addEmptyRowsToTables(int p_AddedRowsCount) - dodavanje


praznih redaka u tablice,

void setBarCount(int p_BarCount) - metoda postavlja broj stupaca u


tablici,

void synchronizeWithloopTool(int p_Index) - metoda sinkronizira


kolekciju svojstava traka sa sporednim sekvencerom,

int getMasterVolume() - metoda dohvaa iznos glasnoe svih kanala,

46

Programska izvedba aplikacije

void setMasterVolume(int p_VolumeValue) - metoda postavlja iznos


glasnoe svih kanala,

void clearLeftTable() - metoda isti lijevu tablicu,

void clearRightTable() - metoda isti desnu tablicu,

void rebuildLeftTable() - metoda gradi lijevu tablicu sa podacima iz


kolekcije svostava traka,

void storeTrack() - metoda ispoetka gradi sve trake i konstruira novu


sekvencu,

void play(boolean p_Loop, boolean p_Store, long p_TickPosition)


-metoda za stvaranje i sviranje sekvence iz tablice.

Klasa nadograuje slijedee metode iz osnovnog sekvencera:

void listenerTableSelectedCellChanged(JTable p_table, int p_selRow, int


p_selColumn) - metoda se pokree kad se u nekoj od tablica promijeni
odabrana elija,

void listenerMetaEventFired(MetaMessage p_Event) - metoda se


pokree pri generiranju meta dogaaja na sekvenceru, tj pri promijeni
pozicije u sekvenci,

void listenerPlay(boolean p_Loop, boolean p_Store, long p_TickPosition)


- metoda koja pokree sviranje sekvence,

void listenerStoreTrack() - metoda pokree gradnju sekvence iz kolekcije


sa svojstvima svih traka.

Zadnje tri metode usko su vezane uz proces izgradnje i sviranja sekvence.


Druga metoda reagira na promjenu pozicije u sekvenci i brine se za oznaavanje
trenutnog stupca u desnoj tablici sekvencera. Trea i etvrta metoda pokreu
metode preko kojih se ostvaruje mehanizam sviranja sekvence:

public void storeTrack() - metoda gradi sekvencu traku po traku, koristei


podatke iz kolekcije svojstava traka. Koristi se slijedeom privatnom
metodom za izgradnju uzorka sa jednostavnom sekvencom koji se
potom ponavlja na oznaenim mjestima u tablici tj. u sekvenci.

private void createTemplate(Track p_Track, int p_IndexTrack) - metoda


stvara uzorak sa jednostavnom sekvencom za odabranu traku, sa
podacima iz m_TrackProperties kolekcije.

public void play(boolean p_Loop, boolean p_Store, long p_TickPosition)


- metoda za stvaranje i sviranje sekvence iz tablice. Pokree metodu za
gradnju sekvence ako je to zadano prvim parametrom i izvodi sekvencu
od zatraene pozicije.

4.3.4. Izvedba sporednog sekvencerskog modula


Klasa sporednog sekvencerskog modula izvedena je iz prethodno opisane
klase osnovnog sekvencerskog modula. Ova klasa upravlja izgradnjom i sviranjem
sporedne sekvence.
47

Programska izvedba aplikacije

Klasa sadri slijedee konstante:

int c_NoteCodeCount - konstanta definira broj raspoloivih nota,

String[] c_NoteList - popis naziva svih nota,

String[] c_Channels - popis raspoloivih MIDI kanala.

Klasa sadri slijedee lanske varijable:

Hashtable<String, Integer> m_NoteTable - tablica kodova nota,

SequencerGUI m_SequencerGUI - referenca na glavni sekvencerski


modul,

MixerGUI m_MixerGUI - referenca na kontrolni modul,

TrackSelector m_TrackSelector - slua selekcije traka (prilkom


promijene aktivne trake pokree metodu za uitavanje njenih podataka).

Konstruktori su implementirani na isti nain kao i u glavnom sekvenceru, pa


imamo jedan osnovni i tri opcionalna konstruktora:

LoopToolGUI(),

LoopToolGUI(int p_ColumnCount),

LoopToolGUI(int p_ColumnCount, MainGUI p_MainGUI,


SequencerWrapper p_SequencerGUI),

LoopToolGUI(int p_ColumnCount, MainGUI p_MainGUI,


SequencerWrapper p_SequencerGUI, String p_TableLTitle).

Inicijalizacijska metoda prikazana je slijedeim ispisom:


private void initialize(){
// postavljanje prikazivaa desne tablice
setRenderer(new TableCellColorEditorLoopTool());
// namjetanje osnovne mjere loopa (4/4 mjera)
// 16 stupaca cini trajanje cijele note,
// tako da je 1 stupac zapravo esnaestinka
setBarCounterOptions(16, 16, 999, 16);
// postavljanje vidljivih alatnih traka
setVisibleToolbars(true, true, true, false, true, true);
// fiksiranje broja redaka lijeve tablice prema popisu nota
setTablesRowCount(c_NoteCodeCount);
// namijetanje fiksnih dimenzija
this.setSize(new Dimension(800, 200));
// inicijalizacija popisa nota
for (int i = 0; i < c_NoteCodeCount; i++) {
m_NoteTable.put(c_NoteList[c_NoteCodeCount-1-i], i);
jDefaultTableModelLeft.setValueAt(
c_NoteList[c_NoteCodeCount-1-i], i, 0);
48

Programska izvedba aplikacije


}
// popunjavanje popisa kanala
setChannelList(c_Channels);
// Slusai
// slusa za uitavanje trake nakon promjene veliine sekvenci
jButtonBar.addActionListener(new ActionListener() {
// ucitavanje trake iz m_TrackProperties
public void actionPerformed(ActionEvent e) {
// uitavanje podataka za odabranu traku
loadTrackData();
}
});
// slusa promjena pri selektiranju traka
m_TrackSelector = new TrackSelector();
jComboBoxTrack.addActionListener(m_TrackSelector);
// slusa promjena pri selektiranju kanala
// novi kanal zapisuje se u TrackProperties objekt
jComboBoxTrackChannel.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
JComboBox cbChannel = (JComboBox)e.getSource();
// odreivanje indeksa novog kanala
int indexChannel = cbChannel.getSelectedIndex();
// indeks trake koja je na tom kanalu
int indexTrack = jComboBoxTrack.getSelectedIndex();
if (indexTrack != -1)
{
TrackProperties tp = getTrackProperties().get(
indexTrack);
tp.setChannel(indexChannel);
// zapisivanje novog kanala
getTrackProperties().set(indexTrack, tp);
// namjetanje glasnoe kanala prema MixerGUI-ju
if (m_MixerGUI != null) {
jSliderVolume.setValue(
m_MixerGUI.getVolumeValue(indexChannel)
);
}
}
}
});
}

Inicijalizacijska metoda organizirana je na isti nain kao u klasi glavnog


sekvencerskog modula. Modul se konfigurira na slian nain, a potom mu se
dodaju sluai.
Pri konfiguraciji modula, zadaje se prilagoeni editor elija, konfiguriraju se
postavke jednostavne sekvence, odabiru se vidljive alatne trake, namjeta se
poetni broj stupaca tablice, prema popisu nota se fiksira i popunjava lijeva tablica,
prilagoavaju joj se dimenzije modula, te se izrauje popis dostupnih MIDI kanala.
Sekvenceru se dodaju sluai koji pri promjeni odabrane trake ili kanala
uitavaju i spremaju potrebne podatke.
49

Programska izvedba aplikacije

Klasa sadri slijedee javne metode:

void connectLoopToolWithSequencer() - metoda za spajanje sa glavnim


sekvencerom,

void clearRightTable() - metoda isti desnu tablicu,

void clearTrackComboBox() - metoda isti izbornik za trake,

void setVerticalScrollbar(int p_PercentOfMaximum) - metoda programski


namjeta vertikalni kliza,

void synchronizeTrackProperties(Vector<TrackProperties>
p_TrackProperties) - metoda postavlja kolekciju svojstava i modificira
popis traka u izborniku,

void setTrack(int p_Index) - metoda selektira traku iz izbornika i uitava


njenu sekvencu u sekvencer,

void setBarCount(int p_BarCount) - metoda postavlja broj stupaca u


desnoj tablici sekvencera,

void rebuildAllTracks() - metoda gradi sve trake iz kolekcije sa svojstvima


traka,

void storeTrack(int p_IndexTrack) - metoda pohranjuje podatke iz tablice


i ponovno gradi sekvencu, te je zapisuje u kolekciju sa svojstvima traka,

void play(boolean p_Loop, boolean p_Store, long p_TickPosition) metoda za stvaranje i sviranje sekvence prema podacima iz tablice.
Klasa nadograuje slijedee metode iz osnovnog sekvencera:

void listenerPlay(boolean p_Loop, boolean p_Store, long p_TickPosition)


- metoda pokree sviranje sekvence,

void listenerStoreTrack() - metoda pokree izgradnju sekvence i pohranu


podataka u kolekciju sa svojstvima traka.

Mehanizam izgradnje, sviranja i spremanja sekvence je slian prethodno


opisanom mehanizmu kod glavnog sekvencera. Razlika je u tome to se ovdje ne
gradi uzorak jer tablica sadri jednostavnu sekvencu koja se direktno interpretira u
notni zapis. Nakon izgradnje, podaci se spremaju u kolekciju sa svojstvima traka,
te se iz nje uitavaju u sekvencer pri eventualnom odabiru trake, ili se iz njih gradi
sekvenca u glavnom sekvenceru.

4.3.5. Izvedba kontrolnog modula


Kontrolni modul implementiran je klasom koja proiruje osnovnu kontejnersku
klasu JPanel. Klasa modula vri funkciju upravljanja iznosima glasnoe i reverba
svih dostupnih MIDI kanala i povezana je sa svim ostalim modulima.
Klasa sadri slijedee lanske varijable:

int m_Gain - maksimalna vrijednost glasnoe, ija se vrijednost odreuje


kontrolom glasnoe u glavnom sekvenceru,

SynthesizerWrapper m_Synthesizer - referenca na omota sintesajzera,


50

Programska izvedba aplikacije

LoopToolGUI m_LoopToolGU - referenca na sporedni sekvencer.

Konstruktor klase je jednostavan, koristi se konstruktorom nadklase JPanel i


pokree inicijalizacijsku metodu, koja obavlja jednostavno konfiguriranje i
dodavanje komponenti u kontejner pokreui pritom njihove inicijalizacijske
metode.
Klasa sadri slijedee javne metode:

void setVolumeValue(int volValue, int chNum) - metoda za programsko


postavljanje vrijednosti glasnoe pojedinog kanala,

int getVolumeValue(int chNum) - metoda za programsko dohvaanje


vrijednosti glasnoe pojedinog kanala,

void setGain(int p_Gain) - metoda za postavljanje glasnoe svih kanala


prema vrijednosti ukupne glasnoe aplikacije,

void setReverbValue(int revValue, int chNum) - metoda za programsko


postavljanje vrijednosti reverba pojedinog kanala,

int getReverbValue(int chNum) - metoda za programsko dohvaanje


vrijednosti volumena pojedinog kanala.

51

Zakljuak

5. Zakljuak
Aplikacija izraena u okviru ovog diplomskog rada predstavlja primjer izgradnje
sloenog zvunog sustava koritenjem Java Sound API-ja i Swing-a. Iz pokazanog
se moe zakljuiti da se upotrebom navedenih biblioteka mogu graditi korisne,
efikasne i prilagodljive zvune aplikacije namijenjene koritenju na razliitim
raunalnim platformama, prijenosnim ureajima, te na internetu, u obliku apleta
ugraenih u web stranice.
Efikasnost ovakvih aplikacija je manja u odnosu na ekvivalentne aplikacije u
jezicima kao to su C ili C++. Manjak efikasnosti uzrokuju klase unutar jezika Java
koje se odnose na grafika suelja, kolekcije, operacije s nizovima i slino. Taj
manjak efikasnosti je sa zadnjom verzijom Jave 1.6 optimizacijom jezika sveden
na minimum i ne predstavlja bitnu prepreku u odabiru tehnologije za razvoj
ovakvih aplikacija. Java Sound API zbog koritenja strojnog koda nudi
performanse jednake aplikacijama pisanim u C-u, jer su te funkcije ve prevedene
i optimizirane za platforme na kojima se kod izvodi.
Kod pisanja komercijalnih aplikacija treba ipak uzeti u obzir nekoliko dodatnih
injenica. Komercijalne aplikacije moraju pruati besprijekornu funkcionalnost te
fleksibilna i atraktivna korisnika suelja. Zvune aplikacije vee sloenosti esto
zahtijevaju drugaije grafike komponente od tipinih komponenti dostupnih u
veini grafikih biblioteka. Npr. tablice koritene za MIDI sekvence u aplikaciji
predstavljaju ogranienje u pozicioniranju nota u glazbenim sekvencama. Zbog
toga bi u svrhu izgradnje profesionalnog proizvoda trebalo izgraditi grafiku
kontrolu koja dozvoljava pozicioniranje nota na proizvoljnim mjestima u sekvenci,
uz mogunost lakog pozicioniranja na mjestima odreenima odabranim tempom
sekvence koju prua tablini pristup. Izgradnju takve kontrole mogue je izvesti
koritenjem Java 2D biblioteke, koja vrlo dobro funkcionira u kombinaciji sa
Swing-om. Izgradnja takvih kontrola ipak predstavlja poprilino sloen programski
pothvat, pogotovo u sluaju aplikacija koje se ne ograniavaju samo na MIDI
tehnologiju, ve trebaju pruati i mogunost sviranja WAV zapisa.
Osim sloenosti koju za aplikaciju predstavljaju same zvune operacije, treba
uzeti u obzir i injenicu da na tritu ve postoje slini profesionalni proizvodi koji
korisnicima osim razraene funkcionalnosti pruaju i atraktivna suelja, u
potpunosti izraena od prilagoenih, dizajnerskih grafikih komponenti.
Iz svega navedenog moe se zakljuiti, da odabir Jave kao jezika za izradu
zvunih aplikacija prua najvie pogodnosti u smislu prenosivosti aplikacije, tj.
mogunosti koritenja na raznim platformama i u sklopu web aplikacija. Ubrzanje
koje se dobiva zbog koritenja irokog skupa Java biblioteka dolazi do izraaja
kod manje sloenih aplikacija, dok se kod poveanja sloenosti ta prednost bitno
smanjuje.

52

Popis oznaka i kratica

6. Popis oznaka i kratica


MIDI

Musical Instrument Digital Interface

API

Application Programming Interface

AWT

Abstract Toolkit Widget

JMF

Java Media Framework

MVC

Model View Controller

JVM

Java Virtual Machine

GM

General MIDI

JRE

Java Runtime Environment

SMF

Standard MIDI Files

RGB

Red Green Blue

53

Popis slika

7. Popis slika
Slika 1. Uzorkovanje zvunog signala..................................................................7
Slika 2. Primjer audio miksera..............................................................................9
Slika 3. Primjer zvune konfiguracije..................................................................10
Slika 4. Primjer MIDI koniguracije.......................................................................12
Slika 5. JTable komponente sa razliitim implementacijama prikaza elija.......21
Slika 6. Komercijalne "Synthetica" teme za Swing.............................................22
Slika 7. Prikaz Sun-ove Demo aplikacije............................................................24
Slika 8. Grafiko suelje aplikacije.....................................................................25
Slika 9. Prikaz pogreke pri otvaranju datoteke.................................................26
Slika 10. Izbornik za otvaranje datoteke.............................................................27
Slika 11. Izbornik za spremanje datoteke...........................................................27
Slika 12. Prikaz pogreke pri spremanju datoteke.............................................28
Slika 13. Izbornik za odabir kolekcije zvukova...................................................28
Slika 14. Prikaz pogreke pri odabiru kolekcije zvukova....................................29
Slika 15. Izbornik za spremanje MIDI zapisa.....................................................29
Slika 16. Prikaz pogreke pri spremanju MIDI zapisa........................................30
Slika 17.Prikaz informacija o autoru i aplikaciji...................................................30
Slika 18. Preglednik instrumenata......................................................................31
Slika 19. Glavni sekvencer.................................................................................33
Slika 20. Sporedni sekvencer.............................................................................35
Slika 21. Kontrolni modul....................................................................................37
Slika 22. Klase grafikog suelja........................................................................38

54

Literatura

8. Literatura
[1]

Wikipedia, Sound recording,


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

[2]

Wikipedia, History of sound recording,


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

[3]

Wikipedia, Digital audio, http://en.wikipedia.org/wiki/Digital_audio

[4]

Wikipedia, Midi, http://en.wikipedia.org/wiki/Midi

[5]

Earline Gilley, A brief history of Java,


http://java.about.com/od/historyofjava/a/historyofjava.htm

[6]

The Financial Express, The 10-year story - Java and the networked
world, 2005, http://www.financialexpress.com/old/fe_full_story.php?
content_id=86910

[7]

Dan Becker, Understanding and using Java MIDI Audio,


http://www.ibm.com/developerworks/library/it/it-0801art38/

[8]

J.P. Lewis and Ulrich Newmann, Performance of Java versus C++,


http://www.idiom.com/~zilla/Computer/javaCbenchmark.html

[9]

Java Sound Resources,


http://www.jsresources.org/examples/

[10] Sun Microsystems, Java Sound Programmer Guide, 2002


[11] Amy Fowler, A Swing Architecture Overview,
http://java.sun.com/products/jfc/tsc/articles/architecture/
[12] MIDI Manufacters Association, Standard MIDI Files,
[13] http://www.midi.org/about-midi/abtmidi2.shtml
[14] Eclipse foundation, About the Eclipse Foundation,
http://www.eclipse.org/org/
[15] Sun Microsystems, The Java Tutorials, Lesson: JavaBeans Concepts,
http://java.sun.com/docs/books/tutorial/javabeans/whatis/index.html

55

Saetak

9. Saetak
Tema ovog diplomskog rada je izrada programskog Midi sekvencera
koritenjem Java Sound API biblioteka u sklopu programskog jezika Java. Rad je
zamiljen kao proirenje jednog dijela aplikacije Java Sound Demo tvrtke Sun
Microsystems. Cilj ovog rada je prikaz zvunih mogunosti programskog jezika
Java u kombinaciji sa osnovnim grafikim sueljem izvedenim koritenjem Java
Swing biblioteka.
Rad pokazuje kako se koritenjem navedenih biblioteka mogu izgraditi
prenosive i sloene zvune aplikacije koje po svojim performansama ne zaostaju
puno za ekvivalentnim aplikacijama pisanim u jezicima kao to su C ili C++.

56

You might also like