J2ME v kostce – jak na zvuk 2.

9. června 2004

V předchozím článku jste se seznámili s částí Mobile Multimedia API (MMAPI) týkající se zvuku, tentokrát budeme pokračovat přehledem práce se zvukem u API firmy Nokia.

Nokia UI API

API obsahující obsluhu zvuku se jmenuje Nokia UI API. Toto API by měly umět všechny telefony značky Nokia. Některé už ovšem obsahují navic i MMAPI, kterým jsem se zabývala v předchozím článku. MMAPI má více možností než Nokia UI API, ale které API zvolit záleží také na tom, na kterých všech telefonech má aplikace fungovat.

Použití třídy Sound z balíku com.nokia.mid.sound je celkem jednoduché. Tato třída umožňuje zahrát tón dané frekvence a délky, nebo přehrát melodii ve formátu WAV nebo RTPL (ringing tone programming language), což je formát vyzvánění. Protože ne každý telefon umí přehrát WAV a navíc je zvukový soubor ve formátu WAV obvykle hodně velký, je lepší používat formát RTPL, i když umožňuje hraní pouze jednohlasé melodie. Jaké formáty telefon umí přehrát, zjistíte metodou Sound.getSupportedFormats.

// získání podporovaných formátů
int[] types = Sound.getSupportedFormats();
for(int i=0; i<types.length; i++){
    if(types[i]==Sound.FORMAT_WAV){
    // podporuje formát WAV
    } else if (types[i]==Sound.FORMAT_TONE){
    // podporuje formát RTPL
    }
}

Trochu nepraktické je, že jen některé emulátory přehrávají zvuk a občas i když jej přehrávají, je výsledek odlišný od toho, co je posléze slyšet z telefonu. Proto se při testování zvuku nespoléhejte pouze na výsledek dosažený v emulátoru.

Přehrání jednoho tónu

Telefony se mohou lišit tím, jaké tóny jsou schopny zahrát. Některé telefony mohou zvládat pouze frekvence odpovídající konkrétním tónům ze stupnice a při pokusu nastavit jinou frekvenci vyhodí IllegalArgumentException. Tóny a jejich frekvence najdete v připojeném přehledu.

Pokud chcete zahrát tón delší než dvě vteřiny, může se telefon rozhodnout vám nevyhovět, a to tak, že nezahraje požadovaný tón, ale ani nevyhodí žádnou výjimku.

// Vytvoření instance třídy Sound s danou
// frekvencí tónu v Hz a délkou tónu v milisekundách.
// Tohle je konkrétně 2 vteřiny trvající komorní A

Sound sound = new Sound(440, 2000);
// Přehrání tónu 1x
sound.play(1);
// Nastavení dalšího tónu k přehrání
sound.init(880, 1000);

Přehrání melodie

FORMAT_TONE

Pro přehrání melodie potřebujeme zvuková data předat třídě Sound jako pole bajtů. Při použití formátu Sound.FORMAT_TONE je nejjednodušší mít toto pole bajtů přímo v nějaké třídě. Dávat zvuková data do zvláštních souborů se může vyplatit, je-li potřeba zvuk vyměnit bez kompilace aplikace.

// Pole bajtů s melodií v RTPL
byte[] data = {
     (byte)0x02, (byte)0x4a, (byte)0x3a, (byte)0x40,
     (byte)0x04, (byte)0x00, (byte)0x03, (byte)0x28,
     (byte)0x00
};
// Vytvoření instance třídy Sound
Sound sound = new Sound(data, Sound.FORMAT_TONE);
// Přehrání tónu 1x
sound.play(1);

Definice syntaxe RTPL je snad ještě méně přehledná než definice syntaxe sekvence tónů pro MMAPI z předchozího článku. Lze ji nalézt ve specifikaci Smart Messaging Specification. Naštěstí není potřeba se syntaxí RTPL vlastnoručně prokousat. Nokia Developer’s Suite 2.0 for J2ME obsahuje konvertor pro převod zvuku na pole bajtů ve správném formátu.

Audio Konvertor
Audio konvertor (plná velikost, cca 40 kB)

  • Vstupní formáty:
    • MIDI – netřeba představovat
    • RTXML – XML formát vyzvánění (ringing tone)
  • Výstupní formáty:
    • OTA – výstup pro OTA stahování vyzvánění
    • pole bajtů – formát pro vložení do Javového kódu (tento formát vás bude asi nejvíc zajímat)
    • RTXML – XML formát vyzvánění (ringing tone), tento formát se může hodit, máte-li melodii v MIDI formátu a chcete-li ji ještě upravit

Formát RTXML je velmi jednoduchý a hodí se na psaní vlastních melodií, pokud umíte noty. Bohužel jsem k tomuto formátu nenašla žádné dtd, takže pokud budete chtít napsat nějakou komplikovanější melodii a nebudete v hledání specifikace RTXML úspěšnější, nezbyde vám, než použít nějaký jiný editor melodie a pak se zpětně podívat, jak se to dalo napsat přímo v RTXML.

<!– První tři tóny písničky Ovčáci čtveráci –>
<ringing-tone name=““>
   <!– loop-value je počet opakování melodie –>
   <pattern id=“A“ loop-value=“0″>
      <!– tempo melodie –>
      <tempo value=“100″/>
      <!– definuje výšku not, které za tímto elementem následují,
      např. je-li hodnota 1, pak následující noty
      leží v první oktávě ap. –>

      <scale value=“1″/>
      <!– čtvrťová nota G1 –>
      <note value=“G“ duration=“1/4″/>
      <!– čtvrťová nota H1 (v anglicky mluvících
      zemích nazývají notu H písmenem B) –>

      <note value=“B“ duration=“1/4″/>
      <!– následující noty jsou z druhé oktávy –>
      <scale value=“2″/>
      <!– půlová nota D2 –>
      <note value=“D“ duration=“1/2″/>
   </pattern>
</ringing-tone>

Délky not mohou být pouze zlomky mocnin dvojky, největší možná délka je 1. K notě lze přidat atribut specifier=".", který notu prodlužuje o polovinu její délky.

FORMAT_WAV

Pro přehrávání zvuku ve formátu WAV je nejsnadnější mít tento zvuk v samostatném souboru. Formát WAV je elektronickou verzí libovolného audio záznamu, takže s ním jde vytvořit komplexnější zvuky než pomocí tónového formátu. Jak jsem však uvedla dříve, jsou zvukové soubory v tomto formátu obvykle příliš velké, takže v mobilních aplikacích jej lze použít pouze pro kratičké zvukové vzorky.

try{
   // otevření vstupního proudu ze souboru 1.wav,
   // který je umístěn v koření JAR souboru

   InputStream is =
      this.getClass().getResourceAsStream(„/1.wav“);
   byte[] b = new byte[500];
   // načtení maximálně 500 bajtů ze vstupního proudu
   // do pole b

   int i = is.read(b);
   // je-li i==500, je možné, že zvukový soubor nebyl načtený celý
   // a čtení je potřeba opakovat v nějakém cyklu …

   Sound sound = new Sound(b, Sound.FORMAT_WAV);
   sound.play(1);
} catch (Exception e){
   e.printStackTrace();
}

Další možnosti NokiaUI API

Nastavení hlasitosti

Hlasitost zvuku se nastavuje metodou setGain(int hlasitost). Parametr „hlasitost“ je číslo od 0 do 255, přičemž 0 znamená ticho a 255 největší možnou hlasitost, kterou zařízení dokáže dosáhnout.

Metoda getGain() vrací aktuální nastavenou hlasitost. Pokud ještě nebyla volána metoda setGain(int hlasitost), může se stát, že implementace Javy není schopna zjistit aktuální hlasitost. V tom případě vrátí volání metody getGain() hodnotu -1.

Zároveň hrané zvuky

Někdy se v aplikaci může hodit přehrávat více zvuků zároveň, například u hry běží na pozadí stále dokola jedna melodie, do které občas zazní speciální zvukový efekt. Kolik zvuků konkrétní telefon umí přehrát, lze zjistit voláním metody static int getConcurrentSoundCount(int typMedia). Pokud telefon neumí zároveň přehrávat více než jednu melodii, je nejjistější před přehráním speciálního efektu zastavit melodii na pozadí metodou stop(), přehrát speciální efekt a po jeho skončení (zjistí se pomocí zaregistrovaného posluchače) opět pokračovat v přehrávání melodie na pozadí metodou resume().

Posluchač zvukových událostí

Pro práci se zvukem se může hodit vědět, v jakém stavu se jaká zvuková ukázka nachází. Pokud například chceme v aplikaci na pozadí neustále pouštět dokola jednu zvukovou ukázku, zaregistrujeme si na ni posluchače a při skončení jejího přehrávání ji spustíme znovu. Posluchače si vytvoříme implementací rozhraní SoundListener a zaregistrujeme metodou setSoundListener(SoundListener posluchac). Jeden zvuk může mít nastaveného pouze jednoho posluchače, což ovšem ničemu nevadí. Naopak jeden posluchač může dělat posluchače všem zvukům, které v aplikaci používáme.

public class MySoundListener implements SoundListener{
   /*
      sound – instance třídy Sound, kde nastala událost
      event – událost, která nastala
   */
   public void soundStateChanged(Sound sound, int event) {
      // zde se provede obsluha události
   }
}

Události, které mohou nastat, definuje třída Sound jako konstanty:

  • SOUND_PLAYING – zvuková ukázka hraje
  • SOUND_STOPPED – přehrávání zvukové ukázky je zastaveno, v tomto stavu se zvuk nachází po jeho vytvoření, dokud ještě nebyl spuštěn
  • SOUND_UNINITIALIZED – zvuková ukázka se nepřehrává a navíc už byly uvolněny všechny potřebné zdroje voláním metody release()

Pokud už zvuk nebude dále používán, měly by se alokované zdroje uvolnit voláním metody release()

Odkazy, zdroje

  • J2ME Wireless Toolkit 2.1 – MIDP 2.0 emulátor od firmy Sun
  • Forum Nokia – informace o telefonech značky Nokia, emulátory jednotlivých telefonů a prostředí Nokia Developer’s Suite

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 *