J2ME v kostce - jak na zvuk II
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
.
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.
// 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.
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 (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.
<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.
// 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.
/*
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 hrajeSOUND_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∞nSOUND_UNINITIALIZED
- zvukovß ukßzka se nep°ehrßvß a navφc u₧ byly uvoln∞ny vÜechny pot°ebnΘ zdroje volßnφm metodyrelease()
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