3. Javan ääniohjelmointi
1.1.
java.applet java.applet
2.
2.
javax.sound.sampled javax.sound.sampled
3.1. java.applet
tarjoaa yleisen, yksinkertaisen ja tarjoaa yleisen, yksinkertaisen ja laitteistoriippumattoman äänipalvelun laitteistoriippumattoman äänipalvelun
käytettävissä: käytettävissä:
appleteissa (JDK 1.0) appleteissa (JDK 1.0)
sovelluksissa (JDK 1.2) sovelluksissa (JDK 1.2)
tukee ääniformaatteja AIFF, AU, WAV, tukee ääniformaatteja AIFF, AU, WAV, MIDI, RMF
MIDI, RMF
Applet-luokan äänimetodeja
void void play(URL play( URL url) url)
void void play(URL play( URL url, String url, String name)
name)
AudioClip AudioClip getAudioClip( getAudioClip(URL URL url) url)
AudioClip AudioClip getAudioClip( getAudioClip(URL URL url,
url, String String name) name)
static static AudioClip AudioClip newAudioClip(
newAudioClip(URL URL url) url)
Muita esille tulevia Applet- metodeja
void void init() init()
void void start() start()
void void stop() stop()
URL URL getCodeBase() getCodeBase()
void void showStatus(String showStatus( String msg) msg)
String String getParameter( getParameter(String String name)
name)
AudioClip-rajapinta
metodit yksittäistoistoon, silmukointiin ja metodit yksittäistoistoon, silmukointiin ja pysäyttämiseen
pysäyttämiseen interface
interface AudioClip AudioClip { { public void
public void play(); play();
public void
public void loop(); loop();
public void
public void stop(); stop();
} }
URL-luokka
sijaitsee pakkauksessa java.net sijaitsee pakkauksessa java.net
getCodeBase- getCodeBase -metodilla saadaan appletin metodilla saadaan appletin perusosoite, johon lisätään äänitiedoston perusosoite, johon lisätään äänitiedoston nimi nimi
osoite luodaan URL osoite luodaan URL- -luokan konstruktorilla luokan konstruktorilla
publicpublic URL(URL(StringString spec)spec) throws
throws MalformedURLExceptionMalformedURLException
poikkeus on käsiteltävä poikkeus on käsiteltävä
SimpleAudioApplet.java 1(3)
import
import java.applet.*;java.applet.*;
import
import java.net.*;java.net.*;
public class
public class SimpleAudioAppletSimpleAudioApplet extends
extends AppletApplet{{ private
private AudioClipAudioClip sound = nullsound = null;;
SimpleAudioApplet.java 2(3)
public void
public void init()init(){{ try
try{{
URLURL ssff = new= new URL(getCodeBase() URL(getCodeBase() + "
+ "soundsound.wav");.wav");
sound = getAudioClip(
sound = getAudioClip(sfsf););
}} catchcatch (MalformedURLException(MalformedURLException e)e) {{ showStatus("Cannot load the showStatus("Cannot load the ""
+ + "audio file.");"audio file.");
} } // try// try } // init()} // init()
SimpleAudioApplet.java 3(3)
public void
public void start()start() {{ ifif (sound != (sound != nullnull) )
sound.play();
sound.play();
}} // start()// start() }} // class// class
SimpleAudioApplet.html
...
...
<applet
<applet
codecode="SimpleAudioApplet.class"="SimpleAudioApplet.class"
width
width=300 =300 heightheight=300=300>>
Your browser doesn't Your browser doesn't support applets.
support applets.
</applet>
</applet>
...
Appletin elinkaari
applettiolio luodaanapplettiolio luodaan
appletti alustetaan kutsumalla appletti alustetaan kutsumalla initinit--metodiametodia
appletin suoritus aloitetaan kutsumalla appletin suoritus aloitetaan kutsumalla startstart-- metodia
metodia
jos appletista poistutaan (esim. vaihdetaan sivua, jos appletista poistutaan (esim. vaihdetaan sivua, minimoidaan selain), kutsutaan
minimoidaan selain), kutsutaan stopstop--metodiametodia
kun applettiin palataan takaisin, kutsutaan kun applettiin palataan takaisin, kutsutaan startstart-- metodia
metodia
BackgroundMusicApplet.java 1(2)
public void
public void init()init() {{ String
String namename == getParameter("BG_MUSICgetParameter("BG_MUSIC");");
trytry {{ String
String base = getCodeBase() +base = getCodeBase() + "snd/";"snd/";
s
soundound = getAudioClip(= getAudioClip(newnew
URL(base +URL(base + name));name));
}
} catchcatch ((MalformedURLExceptionMalformedURLException e)e) {{ showStatus("Cannot load audio file showStatus("Cannot load audio file ””
+ + namename + "."); + ".");
BackgroundMusicApplet.java 2(2)
public void
public void start() {start() { ifif (sound != null(sound != null) )
sound.loop();
sound.loop();
} } // start()// start() public void
public void stop()stop() {{ ifif (sound != (sound != nullnull) )
sound.stop();
sound.stop();
}
} // stop()// stop()
BackgroundMusicApplet.html
...
<applet
<applet
codecode="BackgroundMusicApplet.class"="BackgroundMusicApplet.class"
width
width=300 =300 heightheight=300=300>>
<param
<param namename="BG_MUSIC"="BG_MUSIC"
value
value="muzak.wav"="muzak.wav">>
Your browser doesn't Your browser doesn't support applets.
support applets.
</applet
</applet>>
...
...
Säikeistä
jos äänitiedostot ovat pitkiä, niiden jos äänitiedostot ovat pitkiä, niiden
lataaminen kannattaa siirtää taustalle omaan lataaminen kannattaa siirtää taustalle omaan säikeeseen
säikeeseen
→ → appletti voi aloittaa suorituksensa heti, eikä appletti voi aloittaa suorituksensa heti, eikä sen tarvitse odottaa äänitiedostojen
sen tarvitse odottaa äänitiedostojen latautumista
latautumista
säieolio periytyy joko säieolio periytyy joko Thread Thread- -luokasta tai luokasta tai se toteuttaa
se toteuttaa Runnable Runnable- -rajapinnan rajapinnan
AudioApplet.java 1(6)
base = getCodeBase() + "sounds/";
base = getCodeBase() + "sounds/";
for
for ((intint i = 0; i < sounds.length; i++)i = 0; i < sounds.length; i++){{ String
String fileName = getParameter("SOUND"fileName = getParameter("SOUND"
+ i);
+ i);
ifif (fileName != null(fileName != null)) {{ AudioLoader
AudioLoader audioLoader = audioLoader =
newnew AudioLoaderAudioLoader(fileName, i);(fileName, i);
audioLoader.start();
audioLoader.start();
} // if} // if
AudioApplet.java 2(6)
forfor ((intint i = 0; i < sounds.length; i++)i = 0; i < sounds.length; i++) {{ Button
Button button = button =
newnew Button("Sound " + i);Button("Sound " + i);
button.addActionListener(
button.addActionListener(
newnew ButtonPressButtonPress(i));(i));
add(button);
add(button);
} } // for// for
AudioApplet.java 3(6)
public void
public void stop()stop() {{
forfor (int(int i = 0; i < sounds.length; i++)i = 0; i < sounds.length; i++) ifif (sounds[i] != (sounds[i] != nullnull))
sounds[i].stop();
sounds[i].stop();
}} // stop()// stop()
AudioApplet.java 4(6)
private class
private class AudioLoader AudioLoader extends
extends ThreadThread {{ private
private StringString fileName;fileName;
private int private int finger;finger;
public
public AudioLoaderAudioLoader((StringString n, n, intint f)f) {{ setDaemon(
setDaemon(truetrue););
fileName = n;
fileName = n;
finger = f;
finger = f;
} // constructor} // constructor
AudioApplet.java 5(6)
public void
public void run()run() {{ trytry {{
sounds[finger] = getAudioClip(
sounds[finger] = getAudioClip(
newnew URLURL(base + fileName));(base + fileName));
}} catchcatch (MalformedURLException(MalformedURLException e)e) {{ showStatus("Cannot load file "
showStatus("Cannot load file "
+ fileName + ".");
+ fileName + ".");
}} // try// try }
} // run()// run() }} // class// class
AudioApplet.java 6(6)
private class
private class ButtonPressButtonPress implements
implementsActionListenerActionListener{{ private int
private int soundNumber;soundNumber;
public
public ButtonPressButtonPress((intints)s) {{ soundNumber = s;
soundNumber = s;
} // constructor} // constructor public void
public void actionPerformed(actionPerformed(ActionEventActionEvente)e){{ AudioClip
AudioClipsound = sounds[soundNumber];sound = sounds[soundNumber];
ifif(sound != null(sound != null) sound.play();) sound.play();
}}// actionPerformed()// actionPerformed() }
}// class// class
AudioApplet.html
...
<applet
<applet codecode="AudioApplet.class"="AudioApplet.class"
width
width=500 =500 heightheight=100=100>>
<param
<param namename="SOUND0" ="SOUND0" valuevalue="="musicmusic0.wav"0.wav">>
<param
<param namename="SOUND1" ="SOUND1" valuevalue="="musicmusic1.wav"1.wav">>
<param
<param namename="SOUND2" ="SOUND2" valuevalue="="musicmusic2.wav"2.wav">>
...
<param
<param namename="SOUND5" ="SOUND5" valuevalue="="musicmusic5.wav"5.wav">>
Your browser doesn't support applets.
Your browser doesn't support applets.
</applet>
</applet>
...
...
Jar-tiedostot
useista luokkatiedostoista koostuvat appletit useista luokkatiedostoista koostuvat appletit on syytä koota yhdeksi jar
on syytä koota yhdeksi jar- -tiedostoksi tiedostoksi
→ → vä v ältet ltetää ään useiden pienten tiedostojen n useiden pienten tiedostojen lataaminen
lataaminen
esim. esim.
jar cvf AudioApplet.jar *.class jar cvf AudioApplet.jar *.class
JarredAudioApplet.html
...
<applet
<applet codecode="AudioApplet.class"="AudioApplet.class"
archive
archive="AudioApplet.jar" ="AudioApplet.jar"
width
width=500 =500 heightheight=100=100>>
<param
<param namename="SOUND0" ="SOUND0" valuevalue="="musicmusic0.wav"0.wav">>
...
...
<param
<param namename="SOUND5" ="SOUND5" valuevalue="="musicmusic5.wav"5.wav">>
Your browser doesn't support applets.
Your browser doesn't support applets.
Applet-metodien käyttö sovelluksissa
staattinen metodi staattinen metodi newAudioClip newAudioClip palauttaa
palauttaa AudioClip AudioClip- -olion olion
huom. parametriksi annetaan URL huom. parametriksi annetaan URL- -olio olio eikä esim. tiedostokahva
eikä esim. tiedostokahva
vinkki: sovelluksen oletushakemiston vinkki: sovelluksen oletushakemiston polun saa metodikutsulla
polun saa metodikutsulla
SystemSystem.getProperty("user.dir").getProperty("user.dir")
saatua saatua AudioClip AudioClip- -oliota voidaan käyttää oliota voidaan käyttää normaalisti
normaalisti
AudioApplication.java 1(3)
public class
public class AudioApplicationAudioApplication {{ public static void
public static void main(
main(StringString[] args)[] args) {{ AudioClip
AudioClip[] sounds = [] sounds =
newnew AudioClipAudioClip[args.length];[args.length];
String
String base = "file:" +base = "file:" + System
System.getProperty("user.dir") + "/";.getProperty("user.dir") + "/";
AudioApplication.java 2(3)
forfor ((intint i = 0; i < args.length; i++)i = 0; i < args.length; i++) {{ try
try {{
sounds[i] =
sounds[i] = AppletApplet.newAudioClip(.newAudioClip(
newnew URL(base + args[i]));URL(base + args[i]));
}
} catchcatch (MalformedURLException(MalformedURLException e) {e) { throw new
throw new RuntimeExceptionRuntimeException((
"Cannot load audio file "
"Cannot load audio file "
+ args[i] + ".");
+ args[i] + ".");
} // try} // try } } // for// for
AudioApplication.java 3(3)
for for ((intint i = 0; i = 0;
i < sounds.length; i++) i < sounds.length; i++) {{ sounds[i].loop();
sounds[i].loop();
}} // for// for }} // main()// main() }} // class// class
3.2. javax.sound.sampled
mukana JDKmukana JDK--versiosta 1.3 alkaenversiosta 1.3 alkaen
tarjoaa matalan tason liittymän alustan tarjoaa matalan tason liittymän alustan äänilaitteistoon (myös havainnointi) äänilaitteistoon (myös havainnointi)
pyrkii silti olemaan alustariippumaton ja pyrkii silti olemaan alustariippumaton ja yleistettävissä oleva rakennelma yleistettävissä oleva rakennelma
mahdollistaa äänisignaalinmahdollistaa äänisignaalin
vastaanottamisen (esim. äänitys)vastaanottamisen (esim. äänitys)
käsittelyn (esim. vahvistus tai kaiunta)käsittelyn (esim. vahvistus tai kaiunta)
toistamisentoistamisen
Pakkaukset
javax.sound.sampledjavax.sound.sampled
rajapintoja ja luokkia samplatun äänisignaalin rajapintoja ja luokkia samplatun äänisignaalin tallennukseen, muokkaamiseen ja toistoon tallennukseen, muokkaamiseen ja toistoon
javax.sound.midijavax.sound.midi
rajapintoja ja luokkia MIDI-rajapintoja ja luokkia MIDI-käyttöönkäyttöön
javax.sound.sampled.spijavax.sound.sampled.spi
javax.sound.midi.spijavax.sound.midi.spi
ulkopuolisille palveluntarjoajille (service ulkopuolisille palveluntarjoajille (service providers
providers) tarkoitettuja apuluokkia) tarkoitettuja apuluokkia
Piirteitä
pähkinänkuoressa: äänidataa sisältävien tavujen pähkinänkuoressa: äänidataa sisältävien tavujen lukua, kirjoitusta ja operointia
lukua, kirjoitusta ja operointia
liittymät syöttöliittymät syöttö--(esim. mikrofoni tai tiedosto) ja (esim. mikrofoni tai tiedosto) ja tuloslaitteisiin (esim. kaiutin tai tiedosto) tuloslaitteisiin (esim. kaiutin tai tiedosto)
äänidatan puskurointi (esim. reaaliaikainen äänidatan puskurointi (esim. reaaliaikainen äänivirta)
äänivirta)
äänisignaaleiden yhdistäminenäänisignaaleiden yhdistäminen
käyttäjän komennot: aloita, pysäytä, jatka, lopetakäyttäjän komennot: aloita, pysäytä, jatka, lopeta
Äänidatan käsittelytavat
puskuroitu (bufferedpuskuroitu (buffered))
virta (streamingvirta (streaming): reaaliaikaisen äänidatan ): reaaliaikaisen äänidatan käsittelyä
käsittelyä
operoitava (esim. äänitettävä tai käsiteltävä) operoitava (esim. äänitettävä tai käsiteltävä) tavuja likimain samassa tahdissa kuin missä tavuja likimain samassa tahdissa kuin missä niitä lähetetään
niitä lähetetään
puskuroimaton (unbufferedpuskuroimaton (unbuffered))
äänidata sijaitsee (kokonaisuudessaan) äänidata sijaitsee (kokonaisuudessaan) muistissa
muistissa
monipuolisempi toisto: silmukointi, monipuolisempi toisto: silmukointi, aloituspaikan valinta
aloituspaikan valinta
Äänidatan formaatit 1(2)
dataformaatti dataformaatti
kertoo kuinka sarja tavuja eli ”raaka” kertoo kuinka sarja tavuja eli ”raaka”
samplattu äänidata pitää tulkita samplattu äänidata pitää tulkita
AudioFormat- AudioFormat -luokka luokka
tiedostoformaatti tiedostoformaatti
määrittelee äänitiedoston rakenteen määrittelee äänitiedoston rakenteen
AudioFileFormat- AudioFileFormat -luokka luokka
Äänidatan formaatit 2(2)
vaikka tarjolla on metodeja vaikka tarjolla on metodeja
erilaisten ääniformaattien muuttamiseen erilaisten ääniformaattien muuttamiseen
yleisten tiedostoformaattien lukemiseen yleisten tiedostoformaattien lukemiseen ja tallentamiseen
ja tallentamiseen
kyse ei silti ole kaikenkattavasta kyse ei silti ole kaikenkattavasta äänityökalusta
äänityökalusta
palveluntarjoajilta tukea ja täydennystä palveluntarjoajilta tukea ja täydennystä valikoimaan
valikoimaan
AudioFormat-luokka
koodaustekniikka (esim. PCM, akoodaustekniikka (esim. PCM, a--law tai law tai µµ--lawlaw))
kanavien määrä (1 = mono, 2 = stereo jne.)kanavien määrä (1 = mono, 2 = stereo jne.)
samplaustaajuussamplaustaajuus
kvantisointitaso (so. käytettyjen bittien määrä)kvantisointitaso (so. käytettyjen bittien määrä)
kehystaajuus (kehystaajuus (frame rateframe rate))
kehys (framekehys (frame) = kaikki tiettyyn hetkeen ) = kaikki tiettyyn hetkeen kuuluva data; (esim. kanavien nykyiset kuuluva data; (esim. kanavien nykyiset näytearvot)
näytearvot)
AudioFileFormat-luokka
tiedostotyyppi (esim. WAVE, AIFF) tiedostotyyppi (esim. WAVE, AIFF)
tiedoston pituus tavuina tiedoston pituus tavuina
äänidatan pituus kehyksinä äänidatan pituus kehyksinä
AudioFormat- AudioFormat -olio, joka määrittelee olio, joka määrittelee
tiedoston sisältämän äänidatan muodon
tiedoston sisältämän äänidatan muodon
Java Sound -perusosat
äänijärjestelmä: äänijärjestelmä: AudioSystem AudioSystem
mikseri: mikseri: Mixer Mixer
linja: linja: Line Line
portti: portti: Port Port
Perusrakenne
lähdelinjat kohdelinjat
lähdelinjat kohdelinjat mikserit
Line Line AudioSystem
AudioSystem
Mixer Mixer
Analogia: miksauspöytä
tulosignaalin säätö tulosignaalin säätö
taajuuskorjaus taajuuskorjaus
kaiunnan lähtö kaiunnan lähtö panorointi panorointi vahvistus vahvistus
tulosignaalit
tulosignaalit lähtösignaalilähtösignaali
lähtösignaalin lähtösignaalin vahvistus vahvistus kaiunta
kaiunta-- laite laite
kaiunnan kaiunnan paluu paluu
Äänijärjestelmä (audio system)
kokoaa yhteen kaikki laitteiston ja kokoaa yhteen kaikki laitteiston ja ohjelmiston tarjoamat äänipalvelut:
ohjelmiston tarjoamat äänipalvelut:
mikserit mikserit
linjat linjat
portit portit
äänivirrat äänivirrat
tiedostoformaatit tiedostoformaatit