Audio e JSR 135
Gestione dell’audio (suoni e toni) in MIDP 2.0 (e qualche MIDP 1.0 🙂 )
Introduzione e un po’ di storia.
In questo articolo mi occuperò di spiegare come far suonare il nostro cellulare con le librerie JSR135. Vedremo come sia possibile affrontare la cosa in MIDP2.0 e in MIDP1.0.
Alla prima versione di MIDP, cioè la 1.0, non c’e’ una vera e standard gestione dell’audio. In MIDP 1.0 infatti la gestione dell’audio era lasciata alla casa produttrice del telefono, che forniva un set di api proprietarie per utilizzare l’audio. In pratica una volta fatta la midlet per farla suonare occorrevano comunque le librerie per il cellulare dedicate.
Nokia quindi ha le sue, siemens ha le sue etc etc. Questo portava il programmatore a dover riscrivere ogni volta la gestione dell’audio in MIDP 1.0 per adattarle al cellulare su cui doveva fare il porting della midlet. Finalmente a metà del 2003 nacque uno standard per la gestione dell’audio e non solo.
Nacque la JSR135 che non solo permetteva una gestione dell’audio, ma si occupava anche delle risorse multimediali in generale del cellulare. Infatti con essa è possibile riprodurre filmati, utilizzare un eventuale fotocamera per le proprie applicazioni etc. Noi ci occuperemo solo dell’audio in questo articolo.
Overview su JSR135
JSR135 è presente anche in alcuni cellulari MIDP 1.0 ad esempio alcuni cellulari Sony Ericsson , nonostante siano MIDP 1.0 , la implementano. I siemens anche quelli MIDP 1.0 hanno una specie di JSR135 che però implementa api proprietarie. In pratica i metodi e il funzionamento sono gli stessi di JSR 135 ma c’e’ da importare le librerie siemens.
Nei cellulari MIDP 2.0 invece , JSR135 è di default. Scriverete la classe una volta e questa state certi che se la casa ha implementato correttamente l’API non vi deluderà. JSR 135 permette di suonare diversi formati tra cui:
- Wave
- Au
- Mp3
- Midi
- Toni
Queste sono solo alcune, ogni cellulare implementa le sue specifiche. Per sapere che formato suona il cellulare dovrete cercare nella documentazione della casa le specifiche del cellulare che indicano che tipi di file sono supportati.
Solitamente si trovano dei pdf nel sito della casa produttrice ben documentati che trattano tutte le specifiche del cellulare comprese quelle riguardanti JSR135. Diciamo che JSR135 possiamo dividerlo in 2 categorie anche se poi non sono molto diverse tra loro. La prima è quella dei toni e la seconda è quella dei file audio in generale.
Player Life Cycle
Il player è la classe principale che ci permette di suonare. Ha 5 fasi:
- UNREALIZED
- REALIZED
- PREFETCHED
- STARTED
- CLOSED
Inizialmente il player quando verrà dichiarato si troverà in UNREALIZED.
Il player passa da UNREALIZED a REALIZED quando localizza il percorso del file ( che può essere nel filesystem, ma può anche essere su un server) che verrà riprodotto. Una volta che il player è in REALIZED non si può più tornare in UNREALIZED a meno che non venga deallocato il player.
La fase PREFETCHED consente al player di copiare in memoria il file da riprodurre e di creare le circostanze necessarie alla riproduzione. Quando un player viene stoppato con il metodo stop, il player si troverà in PREFETCHED. Una volta che abbiamo passato lo stato di PREFETCHED possiamo finalmente passare alla fase STARTED e riprodurre il nostro file con il metodo start
Lo stato CLOSED permette di chiudere il player e liberare le risorse del player, questo non ci consentirà più far funzionare il player a meno di reinstanziarlo nuovamente.
Suoniamo i toni…
Bene è il momento di iniziare a far suonare qualcosa al cellulare , cominciamo dai toni. Iniziamo con suonare un tono solamente:
1 2 3 4 5 6 |
public void singleTone (){ try { Manager.playTone(110, 1000, 127); //nota, durata,volume }catch (Exception e){} } |
La nota è calcolata secondo una formula
1 2 |
SEMITONE_CONST = 17.31234049066755 = 1/(ln(2^(1/12))) note = ln(freq/8.176)*SEMITONE_CONST |
Quindi la nota A = MIDI note 69 (0x45) = 440 Hz. Ma potete trovare un elenco delle note qui:
http://www.wmlscript.it/j2me/midp20_01.asp
La durata e’ espressa in millisecondi e il volume va da 0 a 127 (valore max). Ora vediamo come suonare più toni assieme . Di seguito come dovrebbe essere fatta la sequenza:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
byte tempo = 30; // settiamo il tempo byte d = 8; // 8 note byte C4 = ToneControl.C4; //i suoni che useremo byte D4 = (byte)(C4 + 2); // i suoni che useremo byte E4 = (byte)(C4 + 4); // i suoni che useremo byte G4 = (byte)(C4 + 7); // i suoni che useremo byte rest = ToneControl.SILENCE; // silenzio byte[] mySequence = { ToneControl.VERSION, 1, // versione 1 ToneControl.TEMPO, tempo, // impostiamo il tempo ToneControl.BLOCK_START, 0, //definiamo un blocco come un ritornello //che potrà essere riutilizzato E4,d, D4,d, C4,d, E4,d, // contenuto del blocco E4,d, E4,d, E4,d, rest,d, ToneControl.BLOCK_END, 0, // fine blocco ToneControl.PLAY_BLOCK, 0, // suoniamo il blocco 0 D4,d, D4,d, D4,d, rest,d, // suoniamo altri E4,d, G4,d, G4,d, rest,d, //toni esterni al blocco 0 ToneControl.PLAY_BLOCK, 0, // ripetiamo il blocco 0 D4,d, D4,d, E4,d, D4,d, C4,d // altri toni }; |
Direi che è abbastanza chiaro. Utile anche i blocchi che permettono di ottimizzare lo spazio e non dover riscrivere parti riutilizzabili. Ora per suonarlo vediamo il metodo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public void playASequence(){ try{ Player p = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR); //diciamo al player che deve suonare una sequenza di toni p.realize(); //prepariamo il player a passare in realize ToneControl c = (ToneControl)p.getControl("ToneControl"); //creiamo un oggetto ToneControl che useremo per suonare i toni c.setSequence(mySequence); //gli passiamo la sequenza p.start(); //suoniamo :) } catch (Exception e) { System.out.println("ok errore in PlayASequence: "+e); } } |
… e i file audio
Bene ora vediamo come sia possibile suonare un file audio:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public void playSound (){ try { InputStream in = getClass().getResourceAsStream("/1.wav"); //passiamo il file che deve essere in res Player p = Manager.createPlayer(in, "audio/x-wav"); //creiamo il player passandogli l'inputstream e il tipo di file p.realize(); //passiamo a realize p.prefetch();//e a prefetch p.start(); //suoniamo il file }catch (Exception e) { System.out.println ("Errore in playSound"+e); //in caso di eccezione ... } } |
Direi che i commenti spiegano da soli come funziona il tutto.
Abbiamo suonato un wav ma si possono benissimo suonare midi mp3 etc basta che il cell nelle specifiche proprie jsr135 lo permetta. Se volete per esempio suonare un midi dovrete cambiare ovviamente il file e il parametro di createPlayer in:
1 |
audio/midi |
Di seguito un elenco dei diversi content-type preso dalla documentazione
- Wave audio files:
audio/x-wav
- AU audio files:
audio/basic
- MP3 audio files:
audio/mpeg
- MIDI files:
audio/midi
- Tone sequences:
audio/x-tone-seq
Conclusioni
Direi che per ora sull’audio ci fermiamo qui. Ovviamente vi sono altri metodi nella documentazione ad esempio il metodo stop o altri metodi per esempio per il controllo del volume. Lascio a voi scoprirli. Nel prossimo articolo mi occuperò di gestione della tastiera e di come visualizzare e ottimizzare le immagini per preservare il prezioso spazio che abbiamo a disposizione…
Vi lascio il mio sito dove troverete anche alcune mie midlet opensource da cui potrete imparare volendo qualcosa 🙂
http://dega1999.altervista.org/j2me/
e qualche link su j2me
http://dega1999.altervista.org/j2me/link.html