Obsah
1. Pohled pod kapotu JVM – přehrávání hudby s využitím knihovny SDLJava
2. Velikost bufferů a formát samplů
5. Demonstrační příklad SDLTest62 – přehrání skladby uložené ve formátu MIDI
7. Demonstrační příklad SDLTest63 – přehrání skladby uložené ve formátu Ogg Vorbis
9. Demonstrační příklad SDLTest64 – přehrání skladby uložené ve formátu MOD
10. Demonstrační příklad SDLTest65 – jednoduchý hudební přehrávač
11. Repositář se zdrojovými kódy všech čtyř dnešních demonstračních příkladů
1. Pohled pod kapotu JVM – přehrávání hudby s využitím knihovny SDLJava
V předchozí části tohoto seriálu jsme se ve stručnosti seznámili s možnostmi, které programátorům knihovna SDLJava nabízí v oblasti přehrávání zvuků i hudby a při mixování jednotlivých zvukových zdrojů. Celý zvukový subsystém knihovny SDLJava je z hlediska programátora implementován v balíčcích sdljava.audio a sdljava.mixer, přičemž se v současné verzi knihovny SDLJava naprostá většina použitelných metod a funkcí nachází ve třídách dostupných v balíčku sdljava.mixer, zejména ve třídě sdljava.mixer.SDLMixer. S využitím této třídy je možné jednoduše přehrávat hudbu či zvuky, nastavovat hlasitost jednotlivých zvukových kanálů, automaticky zajistit postupné snížení hlasitosti, aplikovat další zvukové filtry na přehrávaný zvuk atd. Možnosti nabízené touto třídou jsou skutečně velké, ovšem samotné rozhraní (dostupné metody a atributy) zůstává velmi jednoduché, o čemž se ostatně přesvědčíme v navazujících kapitolách.
Inicializace zvukového subsystému v knihovně SDLJava se provádí ve dvou krocích. Nejprve je nutné zvukový subsystém povolit při volání metody SDLMain.init(), a to například následujícím způsobem:
SDLMain.init(SDLMain.SDL_INIT_AUDIO);
Ve skutečnosti však většina aplikací vyžaduje současné použití většího množství subsystémů nabízených knihovnou SDLJava. Řešení je velmi jednoduché – postačí vhodným způsobem sloučit konstanty reprezentující jednotlivé subsystémy, a to buď bitovým operátorem OR nebo prostým součtem konstant:
SDLMain.init(SDLMain.SDL_INIT_VIDEO | SDLMain.SDL_INIT_AUDIO);
Následně se přes metodu SDLMixer.openAudio(frequency, format, channels, chunksize) provede konfigurace zvukového subsystému. Význam jednotlivých hodnot předávaných této metodě si vysvětlíme v navazující kapitole.
2. Velikost bufferů a formát samplů
Prvním parametrem metody SDLMixer.openAudio() je vzorkovací frekvence použitá při mixování i přehrávání. Naprostá většina zvukových čipů v současných počítačích by měla zvládat „CD-kvalitu“ a tedy i vzorkovací frekvenci 44100 samplů za sekundu.
Při inicializaci zvukového subsystému je taktéž nutné zvolit formát zvukových vzorků (samplů), který je interně používán při mixování jednotlivých zvukových kanálů i při mixování hudby. V současné verzi knihovny SDLJava je možné si vybrat mezi osmibitovými vzorky či vzorky šestnáctibitovými, které samozřejmě produkují zvuk s vyšší dynamikou (teoreticky až 96dB) oproti osmibitovým vzorkům (až 48dB). Volit lze taktéž formát jednotlivých samplů – se znaménkem (signed) či bez znaménka (unsigned) a u šestnáctibitových vzorků i uspořádání bajtů v šestnáctibitovém slovu. V následující tabulce jsou vypsány všechny podporované formáty zvukových vzorků (samplů):
# | Konstanta | Bitů/vzorek | Formát |
---|---|---|---|
1 | SDLMixer.AUDIO_S8 | 8 | se znaménkem |
2 | SDLMixer.AUDIO_U8 | 8 | bez znaménka |
3 | SDLMixer.AUDIO_S16 | 16 | se znaménkem, little endian, nativní pořadí bajtů |
4 | SDLMixer.AUDIO_U16 | 16 | se znaménkem, big endian, nativní pořadí bajtů |
5 | SDLMixer.AUDIO_S16LSB | 16 | se znaménkem, little endian |
6 | SDLMixer.AUDIO_S16MSB | 16 | se znaménkem, big endian |
7 | SDLMixer.AUDIO_S16SYS | 16 | se znaménkem, nativní (podle použitého CPU) |
8 | SDLMixer.AUDIO_U16LSB | 16 | bez znaménka, little endian |
9 | SDLMixer.AUDIO_U16MSB | 16 | bez znaménka, big endian |
10 | SDLMixer.AUDIO_U16SYS | 16 | bez znaménka, nativní (podle použitého CPU) |
Poznámka: v knihovně SDL 2.0 jsou podporovány i další formáty vzorků, ovšem knihovna SDLJava je postavena na SDL 1.2, takže tyto další formáty zde nelze využít.
Ve třetím parametru se uvádí počet výstupních kanálů, tj. například 1 pro mono výstup a 2 pro stereo výstup. Důležitý je poslední parametr, v němž se udává velikost bufferu použitého zvukovým subsystémem. Příliš malá velikost bufferu může vést ke slyšitelným cvakáním při přehrávání, příliš velké buffery na druhou stranu neumožňují měnit přehrávané zvuky tak rychle, jak si to může vyžádat například programovaná hra. My v demonstračních příkladech používáme hodnotu 4096, která je vhodná především při přehrávání hudby – tento buffer je dostatečně velký na to, aby ani na pomalejších počítačích nedocházelo k poruchám při přehrávání.
3. Formáty hudebních souborů
Knihovna SDLJava podporuje při přehrávání hudby poměrně velké množství různých hudebních a zvukových formátů, které jsou vypsány v následující tabulce:
# | Typ (koncovka souboru) | Popis |
---|---|---|
1 | .wav | zvukové vzorky uložené ve formátu WAVE/RIFF |
2 | .voc | zvukové vzorky uložené ve formátu VOC |
3 | .mod | Amiga moduly a odvozené formáty (viz též osmou kapitolu) |
4 | .xm | Amiga moduly a odvozené formáty (viz též osmou kapitolu) |
5 | .s3m | Amiga moduly a odvozené formáty (viz též osmou kapitolu) |
6 | .669, | Amiga moduly a odvozené formáty (viz též osmou kapitolu) |
7 | .it | Amiga moduly a odvozené formáty (viz též osmou kapitolu) |
8 | .midi | Hudební formát MIDI, viz též čtvrtou kapitolu |
9 | .ogg | Zvukový/hudební formát Ogg Vorbis |
V případě ručně provedené konfigurace je možná i podpora formátu .mp3 a FLAC, to již však vyžaduje instalaci příslušných nativních knihoven, které však nemusí být vždy dostupné.
Pro úspěšné spuštění dnešních čtyř demonstračních příkladů je nutné mít v pracovním adresáři uloženu čtveřici hudebních souborů (formát MIDI, Ogg Vorbis a Amiga MOD), které je možné získat s využitím následující trojice skriptů (soubory je samozřejmě možné z uvedených URL stáhnout i přes prohlížeč WWW). Většinu skladeb pravděpodobně čtenáři budou znát.
Stažení dvojice souborů Für_Elise.mid a Duke Nukem 3D – Grabbag (Theme from Duke Nukem 3D).mid:
wget http://upload.wikimedia.org/wikipedia/commons/d/da/Für_Elise.mid wget "http://www.midiarchive.co.uk/files/Games/Duke%20Nukem%203D/Duke%20Nukem%203D%20-%20Grabbag%20(Theme%20from%20Duke%20Nukem%203D).mid"
Stažení souboru Toccata_et_Fugue_BWV565.ogg:
wget http://upload.wikimedia.org/wikipedia/commons/b/be/Toccata_et_Fugue_BWV565.ogg
Stažení souboru aquarius.mod:
wget -O mod.zip http://modarchive.org/data/downloads.php?moduleid=96202#aquarius.mod unzip mod.zip
4. Hudební formát MIDI
Knihovna SDLJava umožňuje mj. přehrávat hudbu uloženou ve formátu MIDI, přesněji řečeno ve formátu specifikovaném ve standardu General MIDI neboli zkráceně GM. Ve stručnosti se dá říci, že General MIDI v některých oblastech upřesňuje (a zpřísňuje) původní normu MIDI. Například všechna zařízení, která se označují jako GM-compatible, musí dokázat současně přehrát minimálně 24 tónů, tj. mají čtyřiadvacetihlasou polyfonii, přičemž minimálně 16 tónů je melodických spolu s osmi bicími. Tato zařízení také musí podporovat všech šestnáct hudebních kanálů, přičemž kanál číslo 10 je rezervován pro bicí nástroje. Taktéž jsou v této normě přesně určena čísla hudebních nástrojů, která se nastavují pomocí zprávy Program Change. U GM-compatible zařízení je tedy jisté, že nástroj číslo jedna bude vždy hrát jako klavír atd.
Ve standardu General MIDI je kromě dalších požadavků specifikován i formát souborů označovaných zkratkou SMF, neboli Standard MIDI File. Jedná se o binární soubory, které mají většinou příponu .mid; u některých rozšířených verzí se však koncovka může lišit. Tyto soubory se díky své poměrně jednoduché struktuře, úspornému záznamu hudby a otevřenosti formátu hojně rozšířily, a to jak mezi hudebníky (mnohé klávesy například obsahují disketovou jednotku nebo USB rozhraní, ze kterých je možné SMF soubory přehrávat), tak i mezi majiteli osobních počítačů. V souborech typu SMF může být uložena buď jedna hudební stopa, nebo – v případě použití většího množství hudebních nástrojů – větší množství stop.
Hudba přitom není uložena ve formě digitalizovaného a popř. komprimovaného zvuku, jak je tomu například v případě formátu WAVE (RIFF), Ogg Vorbis či MP3, ale jako posloupnost takzvaných událostí (events), což jsou ve svém principu takzvané MIDI zprávy doplněné o časovou značku tak, aby bylo možné přesně zaznamenat i začátek a konec přehrávání určitého tónu nebo celého akordu. Vzhledem k tomu, že každá událost je uložená pouze v několika bajtech, bývají soubory SMF/MIDI velmi malé – celá několikaminutová skladba se může zapsat do souboru majícího velikost jen několik málo kilobajtů.
Ve standardu jsou popsány tři typy (subformáty) souborů SMF, které jsou označovány jako Type-0, Type-1 a Type-2. V minulosti se velmi často používal typ 0, jehož interní struktura je nejjednodušší (obsahuje totiž jen jednu hudební stopu), ovšem například záznam vícehlasé hudby musí být řešen pomocí triku. Dnes se můžeme často setkat s typem 1, jehož přednost spočívá v možnosti použití většího množství hudebních stop (1 až 65535), přičemž události pro každý hudební nástroj jsou uloženy v samostatné stopě. Typ 2 se prozatím příliš nerozšířil. Z tohoto důvodu bude další popis zaměřen především na subformáty Type-0 a Type-1. Před podrobnějším popisem interní struktury souborů SMF si připomeňme, že v General MIDI jsou přesně stanovena čísla pro jednotlivé typy hudebních nástrojů (viz zpráva typu Program Change) a desátý kanál je vyhrazen pro bicí (perkusní) nástroje, u nichž se většinou nezaznamenává výška jimi generovaného zvuku (přehrávaná nota).
Vlastní zvuky hudebních nástrojů v souborech SMF uloženy nejsou, což představuje poměrně velký rozdíl oproti formátům typu MOD (Amiga Module) či XM, v nichž jsou uloženy jak hudební stopy, tak i samply nástrojů či jiných zvuků (u SMF se o přehrávání stará samotné cílové hudební zařízení, které musí zvuky všech nástrojů přehrát – jak praví norma – „s dostatečnou kvalitou“). Následuje výpis jednotlivých skupin hudebních nástrojů tak, jak jsou popsány v General MIDI (tato čísla ostatně najdete i na mnoha „klávesách“):
Číslo programu/nástroje | Skupina nástrojů |
---|---|
01 – 08 | klavíry |
09 – 16 | laděné bicí |
17 – 24 | varhany |
25 – 32 | kytary |
33 – 40 | basové zvuky |
41 – 48 | smyčce |
49 – 56 | ansáblové zvuky |
57 – 64 | žestě |
65 – 72 | plátkové |
73 – 80 | píšťaly |
81 – 88 | elektronické sólové zvuky |
89 – 96 | elektronické doprovodné zvuky |
97 – 104 | elektronické zvukové efekty |
105 – 112 | etnické |
113 – 120 | perkusní |
121 – 128 | zvukové efekty |
Soubory SMF na svém začátku obsahují hlavičku, po které následují data jednotlivých hudebních stop s ukončovací značkou. Každá část souboru (hlavička, stopa) začíná čtyřmi bajty, které lze chápat jako čtyři ASCII znaky textu (v tomto ohledu se SMF přibližuje například populárnímu grafickému formátu PNG, v němž jednotlivé chunky taktéž začínají čtveřicí ASCII znaků). Ostatní data jsou většinou uložena v binární podobě, přičemž hodnoty, které se kvůli svému maximálnímu rozsahu nevejdou do jednoho bajtu, jsou uloženy systémem nižší bajt–vyšší bajt (totéž platí i v případě, že je hodnota uložena na čtyřech bajtech). Hlavička obsahuje základní informace o souboru SMF, především jeho typ (viz předchozí odstavce), počet hudebních stop a základní rychlost přehrávání. Délka hlavičky je u standardních souborů rovna čtrnácti bajtům s následujícím významem:
Offset | Délka (bajty) | Význam |
---|---|---|
00 | 4 | ASCII text ‚MThd‘ – MIDI header |
04 | 4 | délka zbytku hlavičky, pro standardní soubory je zde hodnota 6 |
08 | 2 | typ (subformát) SMF souboru – 0000=Type-0, 0001=Type-1 |
10 | 2 | počet stop, 1 až 65535 (pro subformát 1) |
12 | 2 | rychlost přehrávání hudby (počet tiků na přehrání čtvrťové noty; čím vyšší hodnota, tím rychleji se hudba přehrává) |
Následuje ukázka formátu hlavičky skutečného (dosti známého) souboru DukeNukem_Level1.mid uloženého ve formátu SMF:
Offset | Obsah (hexa) | Význam |
---|---|---|
00 | 4d 54 68 64 | ASCII text ‚MThd‘ – MIDI header |
04 | 00 00 00 06 | délka zbytku hlavičky je rovna šesti bajtům |
08 | 00 01 | typ souboru = Type-1 |
10 | 00 0d | počet stop je roven třinácti |
12 | 00 90 | rychlost přehrávání hudby je nastavena na 0×90 (0×80 odpovídá čtvrtinové notě) |
Ihned po hlavičce souboru SMF následují hudební data, tj. informace o jednotlivých hudebních stopách, přičemž každá hudební stopa začíná čtveřicí bajtů s hodnotami 0×4D, 0×54, 0×72 a 0×6B, což odpovídá ASCII znakům „MTrk“ – MIDI track. Jak jsme si již řekli v úvodních odstavcích, je hudba zaznamenána ve formě takzvaných událostí (events), přičemž každá událost odpovídá MIDI zprávě doplněné o časovou značku. Nejjednodušší události mají délku čtyři bajty, přičemž v prvním bajtu je zaznamenána časová značka, po níž následuje klasická tříbajtová MIDI zpráva. Pokud například budeme chtít postupně přehrát tři noty C, D a E, postačuje použít tři události odpovídající zprávám Note On, za nimiž budou následovat tři zprávy Note Off – viz následující fragment obsahu SMF souboru:
Bajty v souboru | Událost | Význam |
---|---|---|
00 90 3C 60 | Note On | Začne se přehrávat nota C, rychlost náběhu je rovna 0×60 |
7F 90 3E 60 | Note On | Začne se přehrávat nota D, rychlost náběhu je rovna 0×60 |
7F 90 40 60 | Note On | Začne se přehrávat nota E, rychlost náběhu je rovna 0×60 |
7F 80 3C 00 | Note Off | Konec přehrávání noty C |
00 80 3E 00 | Note Off | Konec přehrávání noty D |
00 80 40 00 | Note Off | Konec přehrávání noty E |
Každá událost začíná časovou značkou. Nejedná se o absolutně zapsaný čas, ale o časový rozdíl mezi okamžikem poslední události a události, která právě začíná probíhat (počet tiků trvání jedné čtvrťové noty je uložen v hlavičce). Například pokud potřebujeme přehrávat tóny v pravidelném rytmu, tj. jednotlivé noty mají zaznít po 00, 10, 20, 30, 40 a 50 časových jednotkách, budou mít časové značky hodnoty 00, 10, 10, 10, 10, 10, protože 10–0=10, 20–10=10, 30–20=10 atd. Hodnota 00 značí nulovou pauzu, tj. dvě nebo více událostí mohou proběhnout přesně v tom samém časovém okamžiku. V případě, že je časový rozdíl reprezentován hodnotu menší než 0×7f (127 dekadicky), je situace velmi jednoduchá – časová značka má délku jednoho bajtu, který je zapsán jako první bajt dané události.
Ovšem ve skutečnosti je někdy nutné zadávat i mnohem delší časové rozdíly. Ty se ukládají do většího počtu bajtů (počet bajtů je proměnlivý od jednoho do čtyř), přičemž všechny bajty kromě posledního mají hodnotu větší než 0×7f (127 dekadicky), protože je u nich uměle nastaven nejvyšší bit a pouze do posledního bajtu je zapsána hodnota menší než 0×7f. Maximální čas, který lze tímto způsobem reprezentovat, lze uložit jako sekvenci bajtů 0×ff 0×ff 0×ff 0×7f. Při překódování na hexadecimální číslo dojdeme k hodnotě 0×0fffffff (nesmíme zapomenout na to, že se v souborech SMF nejdříve ukládá bajt s nejnižší váhou), což v desítkové číselné soustavě odpovídá 228=268435456. Příklad záznamu některých hodnot časových značek:
Ukládaná hodnota (desítkově) | Sekvence bajtů (hex) |
---|---|
1 | 01 |
127 | 7f |
128 | 81 00 |
129 | 81 01 |
255 | 81 7f |
256 | 82 00 |
Literatura zabývající se problematikou MIDI a General MIDI:
- Arnell, Billy. „McScope: System.“ Music, Computers, and Software,
April 1988: 58–60. Conger, Jim. C Programming for MIDI.
Redwood City: M & T Books, 1988. - Cooper, Jim. „Mind Over MIDI: Information Sources and System-exclusive Data Formats.“,
Keyboard October, 1986: 110–111. - Enders, Bernd and Wolfgang Klemme. MIDI and Sound Book for the Atari ST.
Redwood City: M & T Books, 1989. - Matzkin, Jonathan. „A MIDI Musical Offering.“
PC Magazine 29 Nov. 1988: 229+. - Peters, Constantine. „Reading up on MIDI for the Novice and the Pro.“
PC Magazine 29 Nov. 1988: 258. - Basic MIDI, Paul White,
Sanctuary Publishing Ltd, London 1999.
ISBN 1 86074 262 9 - A Beginner's Guide to MIDI,
R A Penfold, Babani Publishing Ltd,
London 1993. ISBN 0 85934 331 6 - MIDI for Organists,
C E Pykett
5. Demonstrační příklad SDLTest62 – přehrání skladby uložené ve formátu MIDI
Jak je patrné z popisu formátů souborů SMF/Midi, kterým jsme se zabývali v předchozí kapitole, musí být interní struktura přehrávače těchto souborů poměrně komplikovaná a navíc musí mít přehrávač k dispozici zvuky všech podporovaných hudebních nástrojů, ať již v podobě jednotlivých samplů či v knihovně parametrů předávaných například audio čipu s podporou FM syntézy (sound bank). Pokud se však podíváme do zdrojového kódu dnešního prvního demonstračního příkladu pojmenovaného SDLTest62, uvidíme, je při použití knihovny SDLJava je řešení velice jednoduché a krátké – pouze nám postačí inicializovat zvukový subsystém, nastavit velikost bufferů a formát samplů a posléze je již možné přehrát hudbu a testovat ukončení přehrávání následující sekvencí příkazů:
// nacteni hudby z externiho souboru MixMusic music = SDLMixer.loadMUS(MUSIC_FILE); // prehrani hudby SDLMixer.playMusic(music, -1); // musime pockat na ukonceni prehravani while (SDLMixer.playingMusic()) { SDLTimer.delay(100); }
Podívejme se nyní na úplný zdrojový kód dnešního prvního demonstračního příkladu:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.SDLTimer; import sdljava.mixer.SDLMixer; import sdljava.mixer.MixMusic; /** * Sedesaty druhy demonstracni priklad vyuzivajici knihovnu SDLjava. * * Prehrani hudebniho souboru MIDI s vyuzitim audio subsystmu knihovny SDLJava. * * @author Pavel Tisnovsky */ public class SDLTest62 { /** * Jmeno souboru obsahujiciho hudbu. */ private static final String MUSIC_FILE = "Für_Elise.mid"; /** * Prehrani hudby. */ public static void playMusic() throws SDLException, InterruptedException { // nastaveni vlastnosti zvukoveho subsystemu i vybranych zvukovych kanalu SDLMixer.openAudio(44100, SDLMixer.AUDIO_S16, 1, 1024); SDLMixer.volumeMusic(100); // nacteni hudby z externiho souboru MixMusic music = SDLMixer.loadMUS(MUSIC_FILE); // prehrani hudby SDLMixer.playMusic(music, -1); // musime pockat na ukonceni prehravani while (SDLMixer.playingMusic()) { SDLTimer.delay(100); } } /** * Spusteni sedesateho druheho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_AUDIO); // prehrani hudby playMusic(); } catch (Exception e) { e.printStackTrace(); } finally { SDLMain.quit(); } } }
Skript pro překlad tohoto demonstračního příkladu na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest62.java
Dávkový soubor pro překlad tohoto demonstračního příkladu na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest62.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest62
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest62
6. Zvukový formát Ogg Vorbis
Dalším zvukovým (a současně i hudebním) formátem podporovaným knihovnou SDLJava je Vorbis. Jedná se o ztrátový zvukový formát, který (minimálně v open source světě) postupně nahrazuje formát MP3, jenž je pro některé aplikace nevhodný (například pro mluvené slovo či pro přenos po kanálu s větší pravděpodobností vzniku chyb). Předností formátu Vorbis je mj. i licence BSD, pod níž je referenční implementace uvolněna (s MP3 mohou být z tohoto pohledu problémy, viz například http://www.chillingeffects.org/patent/notice.cgi?NoticeID=464). Zvukový formát Vorbis se většinou nepoužívá samostatně, ale ve spojení s kontejnerem Ogg; právě kvůli tomu se setkáme s označením Ogg Vorbis (nebo též pouze Ogg podle koncovky souborů, což je však nepřesné, neboť Ogg je skutečně pouze kontejnerem, který obaluje datové bloky různých typů – ztrátové i neztrátové audio, ztrátové i neztrátové video i text či titulky).
7. Demonstrační příklad SDLTest63 – přehrání skladby uložené ve formátu Ogg Vorbis
V demonstračním příkladu nazvaném SDLTest63 je ukázáno, že přehrání hudební skladby uložené ve formátu Ogg Vorbis je stejně snadné jako přehrání skladby uložené ve formátu (General)MIDI. Liší se pouze jméno souboru se skladbou; o všechny další operace, které již v tomto případě jsou velmi komplikované, se automaticky postará zvukový subsystém knihovny SDLJava a nativní knihovny, které jsou z SDLJava volány. Povšimněte si, že samplovací frekvence a formát vzorků specifikovaný při inicializaci zvukového subsystému nemusí odpovídat a mnohdy taktéž neodpovídá formátu použitém přímo v souborech typu Ogg Vorbis:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.SDLTimer; import sdljava.mixer.SDLMixer; import sdljava.mixer.MixMusic; /** * Sedesaty treti demonstracni priklad vyuzivajici knihovnu SDLjava. * * Prehrani hudebniho souboru Ogg Vorbis s vyuzitim audio subsystmu knihovny SDLJava. * * @author Pavel Tisnovsky */ public class SDLTest63 { /** * Jmeno souboru obsahujiciho hudbu. */ private static final String MUSIC_FILE = "Toccata_et_Fugue_BWV565.ogg"; /** * Prehrani hudby. */ public static void playMusic() throws SDLException, InterruptedException { // nastaveni vlastnosti zvukoveho subsystemu i vybranych zvukovych kanalu SDLMixer.openAudio(44100, SDLMixer.AUDIO_S16, 1, 1024); SDLMixer.volumeMusic(100); // nacteni hudby z externiho souboru MixMusic music = SDLMixer.loadMUS(MUSIC_FILE); // prehrani hudby SDLMixer.playMusic(music, -1); // musime pockat na ukonceni prehravani while (SDLMixer.playingMusic()) { SDLTimer.delay(100); } } /** * Spusteni sedesateho tretiho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_AUDIO); // prehrani hudby playMusic(); } catch (Exception e) { e.printStackTrace(); } finally { SDLMain.quit(); } } }
Skript pro překlad tohoto demonstračního příkladu na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest63.java
Dávkový soubor pro překlad tohoto demonstračního příkladu na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest63.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest63
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest63
8. Hudební formát Amiga MOD
Dalším hudebním formátem, s nímž může knihovna SDLJava pracovat, jsou takzvané moduly, které byly vyvinuty na slavných osobních mikropočítačích Amiga. Tyto počítače totiž obsahovaly zvukový čip Paula, jenž dokázal v základním nastavení pracovat se čtyřmi zvukovými kanály, u nichž bylo možné měnit frekvenci přehrávání osmibitových samplů. Poměrně záhy po rozšíření počítačů Amiga vznikly aplikace nazvané trackery, které této vlastnosti Pauly důsledně využívaly. Pomocí trackerů bylo (či spíše doposud je) možné vytvořit hudbu složenou ze samplů, které se přehrávají s různou frekvencí na základě údajů uložených ve čtyřech hudebních stopách – jedná se vlastně o obdobu notové osnovy, ovšem zapisovanou ve formě tabulky s 64 řádky a původně čtyřmi sloupci (každý sloupec odpovídá jednomu hudebnímu kanálu).
V každém řádku je možné do sloupce zapsat notu a oktávu (tj. výšku či frekvenci přehrávaného tónu), číslo nástroje (tomu odpovídá zvolený sampl, přesněji více samplů může v některých trackerech být přiřazeno jednomu nástroji v závislosti na výšce tónu), hlasitost a příznak, zda se má současně provést i nějaký zvukový efekt. Tabulka s výše popsanými 64 řádky se nazývá pattern, přičemž celá hudební skladba může být složena z libovolného množství patternů.
Soubory, do kterých se skladby vytvořené pomocí trackerů ukládají, se nazývají moduly. Původní moduly se čtyřmi stopami, patternem dlouhým 64 řádků a osmibitovými samply (mohlo jich být maximálně 31) byly vytvářeny programem ProTracker – jím vytvářené soubory mají příponu .mod a i dnes se s nimi můžeme poměrně často setkat (v našich končinách byl populární například modul mrazik.mod). Formát modulů je poměrně jednoduchý – v souboru jsou uloženy jak jednotlivé samply hudebních nástrojů (u původních modulů v nekomprimované podobě), tak i jména samplů, jednotlivé patterny (tabulky) a další důležité informace, například rychlost posunu mezi řádky patternu (tato rychlost odpovídá tempu skladby a lze ji během přehrávání měnit, čehož se často využívalo).
Společně s dalším rozšiřováním možností trackerů se postupně měnil a rozšiřoval i formát souborů, i když jejich základní struktura zůstala zachována. Především se zvyšoval počet zvukových kanálů z původních čtyř přes osm kanálů (Octalyzer) až na 32 kanálů ve formátu podporovaném ScreamTrackerem (soubory s příponou .stm a .s3m). Některé formáty také dokázaly ukládat samply hudebních nástrojů v komprimované podobě, používat šestnáctibitové samply, samply se smyčkou (loop) atd. Již zmíněný ScreamTracker (vytvořený mimo jiné známou demo skupinou Future Crew) dokonce dokázal do samplované hudby přimíchat hudbu generovanou pomocí FM syntézy (syntéza zvuku s využitím frekvenční a fázové modulace podporovaná některými zvukovými čipy). FastTracker II (od konkurenční skupiny Triton) naproti tomu podporoval „obousměrnou“ smyčku, kdy se sampl po dosažení konce smyčky střídavě přehrával v přímém směru a posléze odzadu apod.
Hudební moduly se staly jak mezi autory hudby, tak i mezi posluchači velice populární, především díky poměrně velké kvalitě přehrávané hudby a rozumné velikosti souborů – většina skladeb se bez problémů dala nahrát na jedinou disketu (880 kB v případě Amigy) a později stáhnout z Internetu i s využitím pomalého modemu. Vzhledem ke stále velké popularitě modulů a jejich relativně jednoduchému formátu (navíc nezatíženému patenty) není divu, že pro velkou část dnešních multimediálních přehrávačů existují pluginy, které dokážou alespoň ty nejrozšířenější typy modulů (.mod, .stm, .s3m) přehrát. Jedná se jak o přehrávače pro Linux (XMMS, Audacious), tak i pro Microsoft Windows (WinAmp). Kromě toho je možné použít i specializované přehrávače, například multiplatformní MikMod for Java (odvozený od původního MikModu napsaného v ANSI C). Není tedy divu, že podpora pro moduly je dostupná i v knihovně SDL a přeneseně i v knihovně SDLJava.
9. Demonstrační příklad SDLTest64 – přehrání skladby uložené ve formátu MOD
Přehrání hudebních souborů uložených ve formátu Amiga MOD je stejně jednoduché, jako v případě již zmíněných formátů MIDI a Ogg Vorbis. Samotné zahájení přehrávání je shodné, liší se jen funkce setMusicPosition() pro změnu pozice v přehrávaném souboru (rewind). U souborů typu MOD je této funkci předáno číslo odpovídající patternu (viz též předchozí kapitola), zatímco například u souborů Ogg Vorbis předávaná hodnota odpovídá počtu sekund (či jejich desetin) počítaných od začátku přehrávání. Podívejme se nyní na zdrojový kód demonstračního příkladu pojmenovaného SDLTest64, který načte a posléze přehraje hudební soubor aquarius.mod, jenž lze nalézt na adrese http://modarchive.org/data/downloads.php?moduleid=96202#aquarius.mod:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.SDLTimer; import sdljava.mixer.SDLMixer; import sdljava.mixer.MixMusic; /** * Sedesaty ctvrty demonstracni priklad vyuzivajici knihovnu SDLjava. * * Prehrani hudebniho souboru MOD s vyuzitim audio subsystmu knihovny SDLJava. * * @author Pavel Tisnovsky */ public class SDLTest64 { /** * Jmeno souboru obsahujiciho hudbu. */ private static final String MUSIC_FILE = "aquarius.mod"; /** * Prehrani hudby. */ public static void playMusic() throws SDLException, InterruptedException { // nastaveni vlastnosti zvukoveho subsystemu i vybranych zvukovych kanalu SDLMixer.openAudio(44100, SDLMixer.AUDIO_S16, 1, 1024); SDLMixer.volumeMusic(100); // nacteni hudby z externiho souboru MixMusic music = SDLMixer.loadMUS(MUSIC_FILE); // prehrani hudby SDLMixer.playMusic(music, -1); // musime pockat na ukonceni prehravani while (SDLMixer.playingMusic()) { SDLTimer.delay(100); } } /** * Spusteni sedesateho ctvrteho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_AUDIO); // prehrani hudby playMusic(); } catch (Exception e) { e.printStackTrace(); } finally { SDLMain.quit(); } } }
Skript pro překlad tohoto demonstračního příkladu na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest64.java
Dávkový soubor pro překlad tohoto demonstračního příkladu na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest64.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest64
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest64
10. Demonstrační příklad SDLTest65 – jednoduchý hudební přehrávač
Poslední demonstrační příklad pojmenovaný SDLTest65 je ze všech čtyř dnešních příkladů nejdelší. Jedná se totiž o jednoduchý hudební přehrávač ovládaný z klávesnice, který kromě přehrávání hudby dokáže měnit hlasitost (klávesy + a -), zastavit a spustit hudbu (klávesa C, převzato z legendárního WinAMPu) a aplikovat efekty fade in a fade out (klávesy I a O). Při stisku klávesy Q nebo Esc program nejdříve ztišší hudbu a následně se korektně ukončí. Aby bylo možné používat klávesnici, musí aplikace vytvořit okno, které následně získá fokus. I uzavření okna vede ke korektnímu ukončení aplikace (opět s efektem fade out). Podívejme se nyní na celý zdrojový kód tohoto demonstračního příkladu:
import sdljava.SDLMain; import sdljava.SDLException; import sdljava.SDLTimer; import sdljava.event.SDLEvent; import sdljava.event.SDLKeyboardEvent; import sdljava.event.SDLKey; import sdljava.event.SDLQuitEvent; import sdljava.mixer.SDLMixer; import sdljava.mixer.MixMusic; import sdljava.video.SDLSurface; import sdljava.video.SDLVideo; import sdljava.video.SDLRect; import sdljava.x.swig.SDLPressedState; /** * Sedesaty paty demonstracni priklad vyuzivajici knihovnu SDLjava. * * Primitivni hudebni prehravac. * * @author Pavel Tisnovsky */ public class SDLTest65 { /** * Horizontalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_WIDTH = 320; /** * Vertikalni rozliseni vybraneho grafickeho rezimu ci okna. */ private static final int GFX_HEIGHT = 240; /** * Bitova hloubka vybraneho grafickeho rezimu. * (0 znamena automaticky vyber, ovsem lze samozrejme pouzit * i hodnoty 8, 16, 24 ci 32, podle vlastnosti graficke karty) */ private static final int GFX_BPP = 0; /** * Jmeno souboru obsahujiciho hudbu. */ private static final String MUSIC_FILE = "aquarius.mod"; /** * Objekt reprezentujici prehravanou hudbu. */ private static MixMusic music = null; /** * Hlasitost hudby. */ private static int musicVolume = 100; /** * Inicializace grafickeho rezimu ci otevreni okna pro vykreslovani. */ private static SDLSurface initVideo() throws SDLException { final long flags = SDLVideo.SDL_DOUBLEBUF; return SDLVideo.setVideoMode(GFX_WIDTH, GFX_HEIGHT, GFX_BPP, flags); } /** * Zahajeni prehrani hudby. */ public static void startPlayingMusic() throws SDLException, InterruptedException { // nastaveni vlastnosti zvukoveho subsystemu i vybranych zvukovych kanalu SDLMixer.openAudio(44100, SDLMixer.AUDIO_S16, 1, 1024); SDLMixer.volumeMusic(musicVolume); // nacteni hudby z externiho souboru music = SDLMixer.loadMUS(MUSIC_FILE); // prehrani hudby SDLMixer.playMusic(music, -1); } /** * Efekt fade out s cekanim na ukonceni efektu. */ private static void fadeOutAndWait() throws SDLException, InterruptedException { SDLMixer.fadeOutMusic(1000); SDLTimer.delay(1200); } /** * Smycka pro zpracovani udalosti. */ private static void eventLoop() throws SDLException, InterruptedException { while (true) { // precist udalost z fronty SDLEvent event = SDLEvent.waitEvent(); // vyskok ze smycky pro zpracovani udalosti pri vyskytu // udalosti typu SDLQuitEvent if (event instanceof SDLQuitEvent) { fadeOutAndWait(); SDLMixer.haltMusic(); return; } // stisk ci pusteni klavesy if (event instanceof SDLKeyboardEvent) { // pretypovani final SDLKeyboardEvent keyEvent = (SDLKeyboardEvent)event; // symbol/kod klavesy final int symbol = keyEvent.getSym(); if (keyEvent.getState() == SDLPressedState.PRESSED) { switch (symbol) { case SDLKey.SDLK_ESCAPE: // klavesa ESC ukonci program fadeOutAndWait(); SDLMixer.haltMusic(); return; case SDLKey.SDLK_i: // efekt fade in SDLMixer.fadeInMusic(music, 1, 1000); break; case SDLKey.SDLK_o: // efekt fade out SDLMixer.fadeOutMusic(1000); break; case SDLKey.SDLK_PLUS: // zvyseni hlasitosti case SDLKey.SDLK_KP_PLUS: musicVolume += 10; SDLMixer.volumeMusic(musicVolume); break; case SDLKey.SDLK_MINUS: // snizeni hlasitosti case SDLKey.SDLK_KP_MINUS: musicVolume -= 10; SDLMixer.volumeMusic(musicVolume); break; case SDLKey.SDLK_c: // pause/unpause if (SDLMixer.pausedMusic()) { SDLMixer.resumeMusic(); } else { SDLMixer.pauseMusic(); } break; default: break; } } } } } /** * Vykresleni sceny na obrazovku ci do okna aplikace. * * @param screen * framebuffer */ private static void drawOnScreen(SDLSurface screen) throws SDLException { // nutno volat i v pripade, ze neni pouzit double buffering screen.updateRect(); screen.flip(); } /** * Spusteni sedesateho pateho demonstracniho prikladu. */ public static void main(String[] args) { try { // inicializace knihovny SDLJava SDLMain.init(SDLMain.SDL_INIT_VIDEO | SDLMain.SDL_INIT_AUDIO); // inicializace grafickeho rezimu ci otevreni okna pro vykreslovani final SDLSurface screen = initVideo(); // spusteni prehrani hudby startPlayingMusic(); // smycka pro zpracovani udalosti eventLoop(); } catch (Exception e) { e.printStackTrace(); } finally { // musime obnovit puvodni graficky rezim // i v tom pripade, ze nastane nejaka vyjimka SDLMain.quit(); } } }
Skript pro překlad tohoto demonstračního příkladu na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib javac -cp $SDL_JAVA_LIBS/sdljava.jar SDLTest65.java
Dávkový soubor pro překlad tohoto demonstračního příkladu na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib javac -cp %SDL_JAVA_LIBS%\sdljava.jar SDLTest65.java
Skript pro spuštění na Linuxu:
#!/bin/sh SDL_JAVA_LIBS=./sdljava-0.9.1/lib java -cp .:$SDL_JAVA_LIBS/sdljava.jar -Djava.library.path=$SDL_JAVA_LIBS SDLTest65
Dávkový soubor pro spuštění na Windows:
set SDL_JAVA_LIBS=.\sdljava-0.9.1\lib java -cp .;%SDL_JAVA_LIBS%\sdljava.jar -Djava.library.path=%SDL_JAVA_LIBS% SDLTest65
11. Repositář se zdrojovými kódy všech čtyř dnešních demonstračních příkladů
Všechny čtyři dnes popsané demonstrační příklady byly společně s podpůrnými skripty určenými pro jejich překlad a následné spuštění uloženy do Mercurial repositáře dostupného na adrese http://icedtea.classpath.org/people/ptisnovs/jvm-tools/. Podobně jako tomu bylo i v předchozích několika dílech tohoto seriálu, i ke dnešním příkladům jsou přiloženy skripty využitelné pro jejich překlad a spuštění. Navíc byly přidány i skripty využitelné ve Windows:
Nesmíme zapomenout ani na trojici skriptů sloužících pro získání hudebních souborů ve formátech MIDI, Ogg Vorbis i Amiga MOD:
# | Zdrojový soubor/skript | Umístění souboru v repositáři |
---|---|---|
1 | get_midi_music_file.sh | http://icedtea.classpath.org/people/ptisnovs/jvm-tools/file/6e3a62f10066/sdljava/scripts/get_midi_music_file.sh |
2 | get_mod_music.file.sh | http://icedtea.classpath.org/people/ptisnovs/jvm-tools/file/d6723b3c49bd/sdljava/scripts/get_mod_music.file.sh |
3 | get_ogg_music_file.sh | http://icedtea.classpath.org/people/ptisnovs/jvm-tools/file/d6723b3c49bd/sdljava/scripts/get_ogg_music_file.sh |
12. Odkazy na Internetu
- Musical Instrument Digital Interface,
http://en.wikipedia.org/wiki/Musical_Instrument_Digital_Interface - A MIDI Pedalboard Encode,
http://www.pykett.org.uk/a_midi_pedalboard_encoder.htm - MIDI Note Number, Frequency Table,
http://tonalsoft.com/pub/news/pitch-bend.aspx - Note names, MIDI numbers and frequencies,
http://www.phys.unsw.edu.au/jw/notes.html - The MIDI Specification,
http://www.gweep.net/~prefect/eng/reference/protocol/midispec.html - Essentials of the MIDI protocol,
http://ccrma.stanford.edu/~craig/articles/linuxmidi/misc/essenmidi.html - General MIDI,
http://en.wikipedia.org/wiki/General_MIDI - Obecné MIDI (General MIDI),
http://www-kiv.zcu.cz/~herout/html_sbo/midi/5.html - Custom Chips: Paula
http://www.amiga-hardware.com/showhardware.cgi?HARDID=1460 - Big Book of Amiga Hardware
http://www.amiga-resistance.info/bboahfaq/ - Amiga Hardware Database
http://amiga.resource.cx/ - ExoticA
http://www.exotica.org.uk/wiki/Main_Page - The absolute basics of Amiga audio
http://www.sufo.estates.co.uk/amiga/amimus.html - Wikipedia: Tracker
http://en.wikipedia.org/wiki/Tracker - Wikipedia: Trackers
http://en.wikipedia.org/wiki/Trackers - Ultimate Soundtracker
http://en.wikipedia.org/wiki/Ultimate_Soundtracker - Protracker
http://en.wikipedia.org/wiki/ProTracker - Impulse Tracker
http://en.wikipedia.org/wiki/Impulse_Tracker - Scream Tracker
http://en.wikipedia.org/wiki/ScreamTracker - MikMod for Java
http://jmikmod.berlios.de/ - List of audio trackers
http://en.wikipedia.org/wiki/List_of_audio_trackers - Wikipedia: Module File
http://en.wikipedia.org/wiki/Module_file - Wikipedia: Chiptune
http://en.wikipedia.org/wiki/Chiptune - SDL_mixer 2.0
http://www.libsdl.org/projects/SDL_mixer/ - SDLJava: package sdljava.ttf
http://sdljava.sourceforge.net/docs/api/sdljava/ttf/package-summary.html#package_description - SDLJava: class sdljava.ttf.SDLTTF
http://sdljava.sourceforge.net/docs/api/sdljava/ttf/SDLTTF.html - SDLJava: class sdljava.ttf.SDLTrueTypeFont
http://sdljava.sourceforge.net/docs/api/sdljava/ttf/SDLTrueTypeFont.html - SDL_ttf Documentation
http://www.libsdl.org/projects/SDL_ttf/docs/ - SDL_ttf 2.0 (není prozatím součástí SDLJava)
http://www.libsdl.org/projects/SDL_ttf/ - SDL_ttf doc
http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_frame.html - SDL 1.2 Documentation: SDL_Surface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsurface.html - SDL 1.2 Documentation: SDL_PixelFormat
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlpixelformat.html - SDL 1.2 Documentation: SDL_LockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdllocksurface.html - SDL 1.2 Documentation: SDL_UnlockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlunlocksurface.html - SDL 1.2 Documentation: SDL_LoadBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlloadbmp.html - SDL 1.2 Documentation: SDL_SaveBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsavebmp.html - SDL 1.2 Documentation: SDL_BlitSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlblitsurface.html - SDL 1.2 Documentation: SDL_VideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlvideoinfo.html - SDL 1.2 Documentation: SDL_GetVideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlgetvideoinfo.html - glDrawArrays
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArrays.xml - glDrawElements
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElements.xml - glDrawArraysInstanced
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArraysInstanced.xml - glDrawElementsInstanced
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElementsInstanced.xml - Root.cz: Seriál Grafická knihovna OpenGL
http://www.root.cz/serialy/graficka-knihovna-opengl/ - Root.cz: Seriál Tvorba přenositelných grafických aplikací využívajících knihovnu GLUT
http://www.root.cz/serialy/tvorba-prenositelnych-grafickych-aplikaci-vyuzivajicich-knihovnu-glut/ - Best Practices for Working with Vertex Data
https://developer.apple.com/library/ios/documentation/3ddrawing/conceptual/opengles_programmingguide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html - Class BufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/image/BufferStrategy.html - Class Graphics
http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Graphics.html - Double Buffering and Page Flipping
http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html - BufferStrategy and BufferCapabilities
http://docs.oracle.com/javase/tutorial/extra/fullscreen/bufferstrategy.html - Java:Tutorials:Double Buffering
http://content.gpwiki.org/index.php/Java:Tutorials:Double_Buffering - Double buffer in standard Java AWT
http://www.codeproject.com/Articles/2136/Double-buffer-in-standard-Java-AWT - Java 2D: Hardware Accelerating – Part 1 – Volatile Images
http://www.javalobby.org/forums/thread.jspa?threadID=16840&tstart=0 - Java 2D: Hardware Accelerating – Part 2 – Buffer Strategies
http://www.javalobby.org/java/forums/t16867.html - How does paintComponent work?
http://stackoverflow.com/questions/15544549/how-does-paintcomponent-work - A Swing Architecture Overview
http://www.oracle.com/technetwork/java/architecture-142923.html - Class javax.swing.JComponent
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html - Class java.awt.Component
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html - Class java.awt.Component.BltBufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.BltBufferStrategy.html - Class java.awt.Component.FlipBufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.FlipBufferStrategy.html - Metoda java.awt.Component.isDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html#isDoubleBuffered() - Metoda javax.swing.JComponent.isDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#isDoubleBuffered() - Metoda javax.swing.JComponent.setDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#setDoubleBuffered(boolean) - Javadoc – třída GraphicsDevice
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsDevice.html - Javadoc – třída GraphicsEnvironment
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsEnvironment.html - Javadoc – třída GraphicsConfiguration
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsConfiguration.html - Javadoc – třída DisplayMode
http://docs.oracle.com/javase/7/docs/api/java/awt/DisplayMode.html - Lesson: Full-Screen Exclusive Mode API
http://docs.oracle.com/javase/tutorial/extra/fullscreen/ - Full-Screen Exclusive Mode
http://docs.oracle.com/javase/tutorial/extra/fullscreen/exclusivemode.html - Display Mode
http://docs.oracle.com/javase/tutorial/extra/fullscreen/displaymode.html - Using the Full-Screen Exclusive Mode API in Java
http://www.developer.com/java/other/article.php/3609776/Using-the-Full-Screen-Exclusive-Mode-API-in-Java.htm - Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
http://www.mobilefish.com/tutorials/java/java_quickguide_jvm_instruction_set.html - The JVM Instruction Set
http://mpdeboer.home.xs4all.nl/scriptie/node14.html - MultiMedia eXtensions
http://softpixel.com/~cwright/programming/simd/mmx.phpi - SSE (Streaming SIMD Extentions)
http://www.songho.ca/misc/sse/sse.html - Timothy A. Chagnon: SSE and SSE2
http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf - Intel corporation: Extending the Worldr's Most Popular Processor Architecture
http://download.intel.com/technology/architecture/new-instructions-paper.pdf - SIMD architectures:
http://arstechnica.com/old/content/2000/03/simd.ars/ - GC safe-point (or safepoint) and safe-region
http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html - Safepoints in HotSpot JVM
http://blog.ragozin.info/2012/10/safepoints-in-hotspot-jvm.html - Java theory and practice: Synchronization optimizations in Mustang
http://www.ibm.com/developerworks/java/library/j-jtp10185/ - How to build hsdis
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/tip/src/share/tools/hsdis/README - Java SE 6 Performance White Paper
http://www.oracle.com/technetwork/java/6-performance-137236.html - Lukas Stadler's Blog
http://classparser.blogspot.cz/2010/03/hsdis-i386dll.html - How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
http://dropzone.nfshost.com/hsdis.htm - PrintAssembly
https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly - The Java Virtual Machine Specification: 3.14. Synchronization
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.14 - The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4 - The Java Virtual Machine Specification: 17.4. Memory Model
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4 - The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7 - Open Source ByteCode Libraries in Java
http://java-source.net/open-source/bytecode-libraries - ASM Home page
http://asm.ow2.org/ - Seznam nástrojů využívajících projekt ASM
http://asm.ow2.org/users.html - ObjectWeb ASM (Wikipedia)
http://en.wikipedia.org/wiki/ObjectWeb_ASM - Java Bytecode BCEL vs ASM
http://james.onegoodcookie.com/2005/10/26/java-bytecode-bcel-vs-asm/ - BCEL Home page
http://commons.apache.org/bcel/ - Byte Code Engineering Library (před verzí 5.0)
http://bcel.sourceforge.net/ - Byte Code Engineering Library (verze >= 5.0)
http://commons.apache.org/proper/commons-bcel/ - BCEL Manual
http://commons.apache.org/bcel/manual.html - Byte Code Engineering Library (Wikipedia)
http://en.wikipedia.org/wiki/BCEL - BCEL Tutorial
http://www.smfsupport.com/support/java/bcel-tutorial!/ - Bytecode Engineering
http://book.chinaunix.net/special/ebook/Core_Java2_Volume2AF/0131118269/ch13lev1sec6.html - Bytecode Outline plugin for Eclipse (screenshoty + info)
http://asm.ow2.org/eclipse/index.html - Javassist
http://www.jboss.org/javassist/ - Byteman
http://www.jboss.org/byteman - Java programming dynamics, Part 7: Bytecode engineering with BCEL
http://www.ibm.com/developerworks/java/library/j-dyn0414/ - The JavaTM Virtual Machine Specification, Second Edition
http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html - The class File Format
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html - javap – The Java Class File Disassembler
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/javap.html - javap-java-1.6.0-openjdk(1) – Linux man page
http://linux.die.net/man/1/javap-java-1.6.0-openjdk - Using javap
http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_javap.html - Examine class files with the javap command
http://www.techrepublic.com/article/examine-class-files-with-the-javap-command/5815354 - aspectj (Eclipse)
http://www.eclipse.org/aspectj/ - Aspect-oriented programming (Wikipedia)
http://en.wikipedia.org/wiki/Aspect_oriented_programming - AspectJ (Wikipedia)
http://en.wikipedia.org/wiki/AspectJ - EMMA: a free Java code coverage tool
http://emma.sourceforge.net/ - Cobertura
http://cobertura.sourceforge.net/ - jclasslib bytecode viewer
http://www.ej-technologies.com/products/jclasslib/overview.html