J2ME v kostce – jak na zvuk 1.

6. dubna 2004

Ve standardním MIDP 1.0 byste podporu zvuku hledali marně. Co s tím, pokud přesto chcete uživatele svých her obšťastnit úchvatnými a nezapomenutelnými zvuky, bez nichž by to prostě nebylo ono? Chtě nechtě budete muset nejspíš použít proprietární API výrobců telefonů. V tomto článku vás seznámím s částí Mobile Multimedia API, týkající se zvuku.

Mobile Media API

Knihovna Mobile Media API (MMAPI – JSR-135) rozšiřuje J2ME o práci s multimédii, například audiem a videem. Podmnožina MMAPI, zabývající se zvukem, je součástí MIDP 2.0, ale vyskytuje se i na nezanedbatelném množství telefonů, které implementují pouze MIDP 1.0. Jak tvrdí přehled telefonů s J2ME přímo u Sunu, jde o novější telefony od firem Nokia a Sony Ericsson. MMAPI se vyskytuje i na některých telefonech značky Siemens (nejspíš na všech kromě starších modelů jako SL45i, M50, MT50), jenom s tou fintou, že se odpovídající třídy nenacházejí v balících javax.microedition.media a javax.microedition.media.control, ale v balících com.siemens.mp.media a com.siemens.mp.media.control.

Základní třídou MMAPI je třída javax.microedition.media.Manager. Tato třída dle zadaných parametrů vytvoří instanci rozhraní javax.microedition.media.Player, která slouží k přehrávání zvukových souborů nebo jednohlasých sekvencí tónů. Nastavení třídy typu javax.microedition.media.Player se dále může ovlivňovat třídami typu javax.microedition.media.Control.

Architektura MMAPI
Architektura MMAPI

Manager

Třída Manager umí vytvořit instanci třídy Player ze vstupního proudu nebo na základě zadaného URI. První metoda je určena k přehrávání zvukových souborů uložených v JARu a její použití je následující:

try {
    // otevření zvukového souboru v JARu
    InputStream is = getClass()
        .getResourceAsStream(„music.wav“);
    // vytvoření instance třídy Player,
    // která umí přehrát onen zvukový soubor
    Player p = Manager.createPlayer(is, „audio/x-wav“);
    // nastavení počtu opakování záznamu
    p.setLoopCount(13);
    // spuštění přehrávání
    p.start();
} catch (IOException ioe) {
    // nastal problém se čtením proudu
} catch (MediaException me) {
    // Player požadovaného typu nelze vytvořit
}

Pokud se v JARu zvukový soubor nenachází, zkončí běh předchozího kódu výjimkou NullPointerException, protože v tom případě vrátí metoda getResourceAsStream("music.wav") hodnotu null.

Nachází-li se zvukový soubor mimo JAR soubor aplikace, je potřeba k jeho přehrání použít metodu Manager.createPlayer(String URI). URI je definováno schématem:

<protokol>:<podrobnosti závislé na protokolu>

Příklady URI:

http://www.mujserver.cz/moje.mp3
ftp://nejaky.ftp.server.com/cizi.wav

Povinně podporované typy zvukových souborů jsou v MIDP 2.0 „WAV (audio/x-wav)“ a „MIDI (audio/midi)“, nejlepší je zjistit si na každém telefonu seznam všech podporovaných typů metodou getSupportedContentTypes(String protokol). Zavolá-li se s parametrem null, vrátí podporované typy bez ohledu na protokol. Například telefony Sony Ericsson umějí přehrávat „MIDI (audio/midi)“, „AMR (audio/amr)“ a „iMelody (audio/imelody)“.

Na přehrání jednoho tónu má třída Manager metodu playTone(int vyska, int delka, int hlasitost). Výška tónu je číslo od 0 do 127, přičemž tónu c1 odpovídá hodnota 60 a dále vždy hodnoty lišící se o 1 odpovídají notám lišícím se o půltón.

Player

Rozhraní Player slouží k přehrávání zvukových dat. Během svého životního cyklu se může ocitnout v několika stavech:

Nerealizovaný stav

V tomto stavu se Player nachází po svém vytvoření. Protože nemá ještě dostatek informací o zvukových datech, nelze v tomto stavu volat metody:

  • getContentType()
  • setMediaTime()
  • getControls()
  • getControl()

Do následujícího stavu přejde Player zavoláním metody realize(). Jsou-li například zvuková data umístěna na serveru, jsou v průběhu realizace stažena na mobilní telefon.

Realizovaný stav

Zvuková zařízení se ještě nealokují, aby zbytečně nebyla blokována. Do následujícího stavu se přejde metodou prefetch().

Připravený stav

Přechod z připraveného do běžícího stavu by měl trvat minimum času, proto v připraveném stavu už jsou alokována zvuková zařízení a zásobníky naplněny zvukovými daty, je-li to potřeba. Do následujícího stavu se přejde metodou start(). Po ukončení svého běhu se Player opět vrátí do připraveného stavu.

Běžící stav

V běžícím stavu Player přehrává zvuková data. V tomto stavu není už možné nastavovat počet opakování zvuku metodou setLoopCount().

Ukončený stav

Do ukončeného stavu přejde Player z jakéhokoli stavu voláním metody close(). V tomto stavu uvolní všechny zdroje a nedá se už dále použít.

Player - stavy
Player – životní cyklus

Obrázek ukazuje celý životní cyklus objektu typu Player. Pro lepší přehlednost z něj byly vypuštěny některé šipky. Je-li Player v nerealizovaném stavu a zavolá se metoda prefetch() nebo start(), automaticky je zavolána jako jejich součást metoda realize(). Je-li Player v realizovaném stavu a zavolá se na něm metoda start(), automaticky je zavolána jako její součást metoda prefetch().

Události

Potřebujeme-li dostávat informace o změnách stavu třídy typu Player, je potřeba implementovat rozhraní PlayerListener, které obsahuje pouze jednu metodu playerUpdate(Player player, String typUdalosti, Object data), a dále si posluchače zaregistrovat metodou addPlayerListener(PlayerListener posluchac). Všechny typy událostí, které posluchač může dostávat, obsahuje rozhraní PlayerListener jako statické proměnné. Chceme-li, aby po celou dobu spuštění aplikace hrála na pozadí dokola jedna skladba a nastavení vysokého počtu opakování skladby se nám nezdá jako dostatečně vhodná metoda, můžeme si zaregistrovat posluchače a při odchycení události END_OF_MEDIA volat na třídu typu Player metodu start().

Control

Rozhraní Control neobsahuje žádné metody společné pro ovladače zvuku, slouží pouze jako předek, ze kterého musí být všechny odvozeny. V MIDP 2.0 jsou definována v balíku javax.microedition.media.control dvě rozhraní, rozšiřující Control, a to VolumeControl a ToneControl.

VolumeControl

Rozhraní VolumeControl slouží poze k nastavení hlasitosti zvuku. Hlasitost může nabývat hodnotu od 0 do 100. Hodnota 0 odpovídá vypnutému zvuku a 100 nejvyšší možné hlasitosti.

// získání ovladače hlasitosti, podle dokumentace není-li
// použitý název třídy absolutní, předpokládá se,
// že je z balíku javax.microedition.media.control
VolumeControl volume = (VolumeControl)
          player.getControl(„VolumeControl“);
// nastavení hlasitosti na nejvyšší možnou hodnotu
volume.setLevel(100);

ToneControl

Rozhraní ToneControl slouží k přehrávání jednohlasých sekvencí tónů. Toto rozhraní není obsaženo v telefonech značky Siemens. Pokud už máme sekvenci tónů vytvořenou, přehraje se takto:

    // sekvence tónů jako pole bytů
byte[] mySequence = …
try {
    // vytvoření třídy typu Player na přehrávání sekvencí tónů
    Player mp = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
    // přechod do realizovaného stavu
    mp.realize();
    // získání ovladače typu ToneControl
    ToneControl c = (ToneControl)
        mp.getControl(„ToneControl“);
    // nastavení skevence tónů
    c.setSequence(mySequence);
    // spuštění přehrávání
    mp.start();
} catch (Exception ex) {
    // zpracování výjimky
}

Úplná definice formátu sekvence tónů je poněkud delší, proto ji uvádím v externím souboru.

Poznámka k MIDP 2.0

Pokud vás blíže zajímá MIDP 2.0, je právě v tisku český překlad knihy J2ME v kostce, kterou vydává Grada. Tato kniha bude obsahovat také mou přílohu, zabývající se právě MIDP 2.0.

Odkazy, zdroje

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *