小節(jié) 4.8播放音樂Playing Music
Although background
music isn't found in every game you play, it can play an important role in a
game. Music can set the mood—for example, an action game could play fast-paced
music, while slower music might be better suited for a game that requires more
thought.
譯:雖然并不是每個(gè)游戲都有背景音樂,但背景音樂在游戲中的作用非常重要。音樂可以調(diào)動情緒,如動作游戲可以播放快節(jié)奏的背景音樂而智力游戲更適合慢節(jié)奏的背景音樂。
Also, music can
change the player's emotions toward elements of the game. Is the music happy?
Or is it dramatic? Happy music might be better suited for the easier levels,
such as the first few levels of a game. Dramatic music could be played for the
more difficult levels, such as when the player is fighting a powerful bad guy.
譯:此外,音樂還可以改變玩家對游戲元素的情感,音樂是歡快的嗎?是激烈的嗎?輕松歡快的音樂更適合簡單的關(guān)卡,如游戲的前幾個(gè)關(guān)卡。而激烈的音樂可以再高難度關(guān)卡播放,如當(dāng)玩家正在和強(qiáng)大的壞蛋戰(zhàn)斗時(shí)。
When you've decided
on the type of music you want, the next step is to figure out where the music
comes from. Nope, it doesn't come from those voices in your head. Instead,
games typically play music in one of three ways:
譯:當(dāng)你已經(jīng)確定想要的音樂類型以后,下一步就要解決的是音樂的來源。不要懷疑,絕不是來自你腦袋里想到的聲音。游戲通常使用以下三種音樂中的一種:
·
Streaming
music from an audio track on a CD // 來自光盤音頻磁道中的音樂流;
·
Playing
compressed music such as MP3 or Ogg Vorbis
//播放MP3 或Ogg Vorbis之類的被壓縮過的音樂;
·
Playing
MIDI music // 播放MIDI(迷笛)音樂。
播放CD音頻 Playing CD Audio
Some CD-ROM games
have plain old Red Book Audio (the standard audio CD format) right on the CD.
The benefit here is you get great-quality sound and it's easy to implement:
Just tell the sound card to start playing the CD, without any other involvement
from the game. The other cool aspect is that players can slip the game CD into
their audio CD player and groove to the game's tracks.
譯:一些 CD-ROM游戲(光盤游戲)光盤中包含了符合紅皮書標(biāo)準(zhǔn)(標(biāo)準(zhǔn)CD音頻格式)的舊式音頻,好處是音樂的音質(zhì)好,而且容易實(shí)現(xiàn):只要讓聲卡開始播放光盤,而不必讓游戲參與任何工作。另一個(gè)好處是玩家可以將游戲光盤放進(jìn)音頻光盤播放器中,刻錄游戲的音軌。
Unfortunately, CD
audio takes up a lot of space, typically around 30MB for a three-minute song.
If you have four three-minute songs, that's 120MB of space that could be used
for more graphics or bigger levels. In addition, the Java Sound implementation
doesn't support playback from a CD, so this option is out for you.
譯:但是,CD音頻占用空間比較大,通常時(shí)長三分鐘的歌曲要39 MB。如果游戲中需要使用四個(gè)時(shí)長三分鐘的歌曲,則會占用120MB的空間,而這些被占用的空間本來可以用于更多的圖形和較大的游戲關(guān)卡。另外。Java Sound實(shí)現(xiàn)不支持播放CD音頻,因此無法選擇CD音頻。
播放MP3與Vorbis / Playing
MP3 and Ogg Vorbis
The second option is
compressed music. MP3 and Ogg Vorbis formats are much smaller than that for CD
audio, typically around 3MB for a three-minute song, and have near-CD quality.
They've become increasingly more popular in games.
譯:第二個(gè)選項(xiàng)是壓縮音樂。MP3和 Ogg
Vorbis格式比CD音頻小的多,通常三分鐘歌曲只有3MB左右,而且音質(zhì)接近CD,在游戲中越來越普及。
The drawback here is
that decoding MP3 or Ogg Vorbis files takes quite a chunk of processor power.
Sound cards can't play compressed music directly, so the music is decoded while
it's played. This means the extra processor use can interfere with other parts
of your game. On faster, modern machines, the decoding won't be noticeable, but
on slower, older machines, the decoding could take 20% to 40% of the processor
or more. That could make other parts of the game, such as animation, seem slow
or jerky.
譯:壓縮音樂的缺點(diǎn)在于編碼 MP3和Ogg Vorbis文件需要占用大量處理器資源。聲卡不能直接播放壓縮音樂,因此要邊播放邊解碼。過多的處理器資源被占用可能會影響游戲的其他部分的運(yùn)行。在現(xiàn)代高速計(jì)算機(jī)上,解碼的影響并不明顯,但在老式低速計(jì)算機(jī)上,解碼占用處理器資源高達(dá)的20%到40%,甚至更多。這就有可能使游戲其他部分看起來運(yùn)行緩慢或閃爍,比如動畫。
If the processor
time doesn't matter to your game, you'll need to get an MP3 or Ogg Vorbis Java
decoder. Java Zoom, at www.javazoom.net, has both. This site provides a plug-in
through Java's Service Provider Interface that enables you to get an AudioInputStream that decodes an MP3 or Ogg Vorbis stream.
Just include the necessary .jar file, and be sure to convert the AudioInputStream, like so:
譯:如果對你的游戲來說處理器不是問題,那么你還需要獲得 MP3和Ogg Vorbis的解碼器。在java Zoom網(wǎng)站上(網(wǎng)址 www.javazoom.net)你可以獲得這兩個(gè)解碼器。該站點(diǎn)提供基于Java's Service Provider Interface 編寫的插件,通過它可以獲得解碼MP3或OGG Vorbis流得到的AudioInputStream 。你只需要將必要的.Jar文件包含到你的應(yīng)用中,并確保將AudioInputStream進(jìn)行如下轉(zhuǎn)換:
名詞解釋:Service Provider Interface(服務(wù)提供商接口),滿足某種服務(wù)標(biāo)準(zhǔn)的供應(yīng)商提供的符合該標(biāo)準(zhǔn)的應(yīng)用程序接口,SPI應(yīng)該和該服務(wù)的API標(biāo)準(zhǔn)是兼容的,應(yīng)用程序一般應(yīng)該是基于API編寫,除非是SPI中包含API中沒有提供的功能而又必須使用。
// create the format used for playback
// (uncompressed, 44100Hz, 16-bit, mono, signed)
//創(chuàng)建播放采用的格式( 未壓縮,44100Hz,16位,單聲道,帶符號,以little-endian字節(jié)順序存儲單個(gè)樣本中的數(shù)據(jù))
AudioFormat playbackFormat =
new AudioFormat(44100, 16, 1, true, false);
// open the source file //打開源文件
AudioInputStream source =
AudioSystem.getAudioInputStream(new File("music.ogg"));
// convert to playback format //轉(zhuǎn)換成變成播放格式
source = AudioSystem.getAudioInputStream(playbackFormat, source);
Also, be sure not to
load the samples into memory. A compressed sound file might take up only 1MB
for each minute of music, but the uncompressed samples would take 10MB for each
minute. Instead, play any large sounds directly from the AudioInputStream, which streams the sound from disk.
譯:壓縮聲音文件每分鐘可能只有1MB,但解壓縮后的樣本則可能高達(dá)10MB。因此,一定不要把樣本裝載到內(nèi)存中。相反,我們直接通過 AudioInputStream播放從磁盤打開的大體積聲音。
But which one should
your game use, MP3 or Ogg Vorbis? Although MP3 is incredibly popular, Ogg
Vorbis is license-free and claims better sound quality. The people playing your
game won't notice or care, so go with whichever one suits your needs better. You
can find more information on Ogg Vorbis at www.xiph.org/ogg/vorbis.
Also, be sure to look into MP3 licensing issues at www.mp3licensing.com.
譯:那么我們在游戲中選MP3還是Ogg
Vorbis呢?盡管MP3已經(jīng)越來越普及,但是Ogg
Vorbis是無需可證的,而且音質(zhì)更好。由于玩家不在乎音樂的格式,所以你可以選擇更符合游戲需求的。你可以在www.xiph.org/ogg/vorbis 找到關(guān)于Ogg
vorbis 的更多信息。在www.mp3licensing.com可以了解MP3許可證的信息。
播放MIDI音樂 Playing MIDI Music
Finally, there's MIDI music. MIDI music
isn't sampled music like other sound formats; instead, it works more like a
composer's sheet music, giving instructions on which note to play on each
instrument. The audio system synthesizes to each note according to the pitch,
instrument, and volume, among other parameters.
譯:最后我們來了解MIDI音樂。MIDI音樂不是樣本音樂那樣的聲音格式,而是類似與作曲家的樂譜,通過指令指示樂器播放什么音符。音頻系統(tǒng)會根據(jù)音調(diào),樂器,音高和其他參數(shù)平,合成每個(gè)音符。
Because MIDI files
contain instructions instead of samples, MIDI
files are very small compared to sampled sound formats and are often measured
in kilobytes rather than megabytes.
譯:因?yàn)?/span>MIDI文件包含指令而不是樣本,因此比采樣聲音格式小的多,其大小通常都是以KB單位,而不是MB。
Because the music is
synthesized, the quality might not be as high as that of sampled music. Some
instruments won't sound realistic, or the music might sound a little too
mechanical. A creative musician can usually mask the deficiencies of MIDI music, however.
譯:因?yàn)?/span>MIDI音樂是人工合成的,通常它的音質(zhì)不如采樣音樂。一些樂器聽起來不夠逼真,可能聽起來有點(diǎn)兒過于機(jī)械。然而又創(chuàng)造力的音樂家通常能夠掩蓋MIDI音樂的缺陷。
The Java Sound API
synthesizes MIDI music through the use of a
soundbank, which is a collection of instruments. Unfortunately, although the
Java SDK includes a soundbank, the Java runtime does not. If a soundbank isn't
found, the hardware MIDI port, which has
unreliable timing in Java Sound, is used. For this reason, it's recommended to
use a soundban1k.
譯:Java
Sound API 通過聲音樂隊(duì)(sound bank 程序模擬的一組樂器)合成MIDI音樂。不幸的是雖然Java SDK中包含聲音樂隊(duì),而Java運(yùn)行時(shí)環(huán)境卻不包含。如果找不到聲音樂隊(duì),則會使用硬件MIDI端口,它的定時(shí)功能不穩(wěn)定。所以,建議使用聲音樂隊(duì)。
The Java SDK
includes a minimal-quality soundbank, and you can download higher-quality
soundbanks from http://java.sun.com/products/java-media/sound/soundbanks.html
and include them with your game.
譯:Java SDK中的聲音樂隊(duì)效果很差,你可以到http://java.sun.com/products/java-media/sound/soundbanks.html下載高質(zhì)量的聲音樂隊(duì)并將其包含在你的游戲中。
The Java Sound API
provides MIDI sound capabilities in the javax.sound.midi package. To play MIDI
music, you need two objects in this package: Sequence and Sequencer. A Sequence object contains the MIDI data, and a Sequencer sends a Sequence to the MIDI synthesizer. Here's an example of playing a MIDI file:
譯:Java Sound API 在java.soundbaks.midi包中提供了MIDI聲音功能。要播放MIDI樂音,需要這個(gè)包中的2個(gè)對象:Sequence和Sequencer。Sequence對象包含MIDI數(shù)據(jù)。而Sequencer能將一個(gè)Sequence發(fā)送到MIDI合成器中。下面是播放MIDI音樂的例子:
// open the midi file // 打開midi文件
Sequence sequence = MidiSystem.getSequence(new File(filename));
// open the sequencer //打打開序例化器
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
// play the midi sequence //播放midi序例
sequencer.setSequence(sequence);
sequencer.start();
By default, the Sequencer plays a Sequence once and
then stops. But in a game, you usually want to loop the music. To loop a Sequence, you need to be notified when the music is done
playing and start the Sequencer again.
譯:默認(rèn)情況下,Sequencer播放Sequence一次,然后停止。但游戲中通常需要循環(huán)播放音樂。要循環(huán)Sequence,就要在音樂播放完畢時(shí)重新啟動Sequencer。
An example of how to
loop music is in the MidiPlayer class in Listing
4.11. It implements the MetaEventListener interface, which notifies the class when
the Sequence is done playing via the end-of-track
message.
譯:清單4.11的MidiPlayer類是循環(huán)播放音樂的例子。它實(shí)現(xiàn)MetaEventListener接口,通過軌道末尾消息通知音樂播放已經(jīng)完畢了。
清單
Listing 4.11 MidiPlayer.java
package com.brackeen.javagamebook.sound;
import java.io.File;
import java.io.IOException;
import javax.sound.midi.*;
public class MidiPlayer implements MetaEventListener {
// Midi meta event //Midi事件
public static final int END_OF_TRACK_MESSAGE = 47;
private Sequencer sequencer;
private boolean loop;
private boolean paused;
/**
Creates a new MidiPlayer object.//創(chuàng)建一個(gè)新的MidiPlayer對象
*/
public MidiPlayer() {
try {
sequencer = MidiSystem.getSequencer();
sequencer.open();
sequencer.addMetaEventListener(this);
}
catch ( MidiUnavailableException ex) {
sequencer = null;
}
}
/**
Loads a sequence from the file system. Returns null if
an error occurs. 從文件系統(tǒng)中載入序例,當(dāng)發(fā)生錯(cuò)誤時(shí)返回null
*/
public Sequence getSequence(String filename) {
try {
return MidiSystem.getSequence(new File(filename));
}
catch (InvalidMidiDataException ex) {
ex.printStackTrace();
return null;
}
catch (IOException ex) {
ex.printStackTrace();
return null;
}
}
/**
Plays a sequence, optionally looping. This method returns
immediately. The sequence is not played if it is invalid.
播放sequence ,可以循環(huán)或不循環(huán)。這個(gè)方法立即返回。不可用的sequence將不會被播放
*/
public void play(Sequence sequence, boolean loop) {
if (sequencer != null && sequence != null) {
try {
sequencer.setSequence(sequence);
sequencer.start();
this.loop = loop;
}
catch (InvalidMidiDataException ex) {
ex.printStackTrace();
}
}
}
/**
This method is called by the sound system when a meta
event occurs. In this case, when the end-of-track meta
event is received, the sequence is restarted if
looping is on.
發(fā)生元事件時(shí),這個(gè)方法將被聲音系統(tǒng)調(diào)用。當(dāng)收到軌道末尾元事件時(shí),如果處于循環(huán)播放模式,則sequence重新啟動。
*/
public void meta(MetaMessage event) {
if (event.getType() == END_OF_TRACK_MESSAGE) {
if (sequencer != null && sequencer.isOpen() && loop) {
sequencer.start();
}
}
}
/**
停止sequencer,將其復(fù)位為0
Stops the sequencer and resets its position to 0.
*/
public void stop() {
if (sequencer != null && sequencer.isOpen()) {
sequencer.stop();
sequencer.setMicrosecondPosition(0);
}
}
/**
Closes the sequencer. //關(guān)閉sequencer
*/
public void close() {
if (sequencer != null && sequencer.isOpen()) {
sequencer.close();
}
}
/**
Gets the sequencer. //獲得sequencer
*/
public Sequencer getSequencer() {
return sequencer;
}
/**
Sets the paused state. Music may not immediately pause.
設(shè)置暫停狀態(tài),音樂不一定立即停止
*/
public void setPaused(boolean paused) {
if (this.paused != paused && sequencer != null) {
this.paused = paused;
if (paused) {
sequencer.stop();
}
else {
sequencer.start();
}
}
}
/**
Returns the paused state. //返回暫停狀態(tài)
*/
public boolean isPaused() {
return paused;
}
}
MidiPlayer also provides methods for opening Sequences and pausing the music. To pause, MidiPlayer calls the stop() method of the Sequencer object, which stops the Sequence without resetting its position. Calling start() resumes the paused sequence. All this happens in MidiPlayer's setPaused() method.
譯:MidiPlayer還提供打開Sequence
和暫停播放音樂的方法。要暫停音樂,MidiPlayer調(diào)用Sequencer對象的stop()方法,在不復(fù)位的情況下停止播放Sequence 。調(diào)用Start()方法則繼續(xù)播放暫停的sequence 。這一切都在MidiPlayer的setPaused()方法中實(shí)現(xiàn)。
創(chuàng)建自適應(yīng)的音樂Creating Adaptive Music
Now that you can
play MIDI music, let's discuss one of its
advantages: easy implementation of adaptive music. Adaptive
music is music that changes based on the state of the game. For instance,
if the player is battling a large number of enemies, the music might be fast
and loud. Conversely, the music might be quiet when the player is walking
around exploring rooms alone.
譯:現(xiàn)在你能夠播放MIDI音樂了,接著讓我們來討論一下MIDI音樂的一個(gè)優(yōu)點(diǎn):很容易實(shí)現(xiàn)自適應(yīng)的音樂。自適應(yīng)音樂是根據(jù)游戲狀態(tài)自動改變的音樂。如玩家正在與大量的敵人戰(zhàn)斗,則音樂可能快速而激烈,相反,當(dāng)玩家單獨(dú)在房屋中搜索時(shí),音樂聲會非常小。
The change in music
could happen at any time—for example, the player could be strolling along one
second, and then 100 robots could be trying to kill him the next. So, changing
the music smoothly can be a challenge.
譯:音樂的改變可能隨時(shí)發(fā)生,例如玩家前一秒可能還沒有遇到一個(gè)敵人,后一秒突然有100個(gè)機(jī)器人要?dú)⑺R虼耍胍交馗淖円魳肥且粋€(gè)很大的挑戰(zhàn)。
You can adapt songs
to the game state in two ways:
譯:可以用2種方法在游戲狀態(tài)中適配音樂:
·
Change
songs 改變歌曲;
·
Modify
the song currently playing 修改當(dāng)前播放的歌曲。
Because the actions
of a player can change at any time, changing songs is a more difficult task.
The change can't be abrupt, or it will be distracting. Songs can be designed so
that they have "change points" to signify places where a song change
can occur.
譯:由于玩家的動作可能隨時(shí)改變,因此實(shí)時(shí)改變歌曲是一個(gè)非常困難的任務(wù)。音樂的改變不能太突然,否則會分散注意力。歌曲可以被設(shè)計(jì)包含一些 “變化點(diǎn)”,以指示一首歌曲在哪里可以發(fā)生改變。
Also, songs need to
transition smoothly. To do this, the first song can fade out while the next
song is fading in. Also, while the first song is fading out, its tempo could
change to match the tempo of the next song.
譯:歌曲需要平滑地過度。為此,當(dāng)切換音樂時(shí)可以讓前一首歌逐漸退出,后一首歌逐漸進(jìn)入。另外,在前一首歌逐漸退出時(shí),其速度可以漸變成后一首歌的速度。
Or, you could just
take the easy way out and insert a sound of a scratching phonograph needle。
譯:或者,你可以簡單地取出和插入一個(gè)聲音的一個(gè)刻痕留聲機(jī)針。(這句翻不成,在網(wǎng)上翻譯的,高手幫著看看)
The second option is
to simply modify the exiting song. You can do this by changing the tempo or
volume, or adding another instrument to it.
譯:第二個(gè)選擇是簡單地修正在退出的歌曲。你可以改變歌曲的速度或音量,或添加另一個(gè)樂器到歌曲中。
Adding or taking
away an instrument is easy to do with MIDI
sequences. MIDI music is typically organized
into tracks, with each track playing a specific instrument. For instance, there
might be one track for guitar, one for keyboards, and so on.
譯:MIDI sequence很容易添加和移除樂器。MIDI音樂通常由多音軌組成,每一個(gè)音軌演奏特定的樂器。例如,可以有一個(gè)吉他音軌,一個(gè)鍵盤音軌等。
You can mute or
unmute a track with one method:
譯:可以調(diào)用一個(gè)方法開啟或關(guān)閉某個(gè)音軌的聲音:
sequencer.setTrackMute(trackNum, true);
Here, trackNum is an integer representing the track number you want
to mute. If you don't know what track belongs to what instrument in your MIDI file, you might have to experiment by muting each
track, one by one.
譯:其中參數(shù)trackNum是整型,表示要靜音的音軌號。如果不知道MIDI文件中那個(gè)音軌屬與那個(gè)樂器,你可以將所有音軌一個(gè)一個(gè)地靜音,來通過實(shí)驗(yàn)辨別。
Listing 4.12 MidiTest.java
import java.io.File;
import java.io.IOException;
import javax.sound.midi.*;
import com.brackeen.javagamebook.sound.MidiPlayer;
/**
An example that plays a Midi sequence. First, the sequence
is played once with track 1 turned off. Then the sequence is
played once with track 1 turned on. Track 1 is the drum track
in the example midi file.
一個(gè)播放 MIDI sequence 的例子。首先,sequence 在音軌1被關(guān)閉的情況下被播放了一次。然后,sequence 在音軌1被打開的情況下被播放了一次。音軌1是樣例文件的鼓樂音軌。
*/
public class MidiTest implements MetaEventListener {
// The drum track in the example Midi file 鼓樂音軌
private static final int DRUM_TRACK = 1;
public static void main(String[] args) {
new MidiTest().run();
}
private MidiPlayer player;
public void run() {
player = new MidiPlayer();
// load a sequence 加載 sequence
Sequence sequence =
player.getSequence("../sounds/music.midi");
// play the sequence 播放 sequence
player.play(sequence, true);
// turn off the drums 關(guān)閉 鼓
System.out.println("Playing (without drums)...");
Sequencer sequencer = player.getSequencer();
sequencer.setTrackMute(DRUM_TRACK, true);
sequencer.addMetaEventListener(this);
}
/**
This method is called by the sound system when a meta
event occurs. In this case, when the end-of-track meta
event is received, the drum track is turned on.
當(dāng)一個(gè)元事件發(fā)生時(shí)聲音系統(tǒng)會調(diào)用該方法。當(dāng)收到音軌末尾元事件,鼓樂音軌被打開。
*/
public void meta(MetaMessage event) {
if (event.getType() == MidiPlayer.END_OF_TRACK_MESSAGE) {
Sequencer sequencer = player.getSequencer();
if (sequencer.getTrackMute(DRUM_TRACK)) {
// turn on the drum track 打開鼓樂音軌
System.out.println("Turning on drums...");
sequencer.setTrackMute(DRUM_TRACK, false);
}
else {
// close the sequencer and exit 關(guān)閉 sequencer 并退出虛擬機(jī)
System.out.println("Exiting...");
player.close();
System.exit(0);
}
}
}
}
Just like when you
play sampled sound, you must explicitly exit the VM when you're done. MidiTest exits the VM when it receives the second end-of-track
message.
譯:就像你播放樣本音樂一樣,你必須在播放完畢時(shí)明確地退出虛擬機(jī)。MidiTest 在收到第二個(gè)音軌末尾消息時(shí)退出虛擬機(jī)。
總結(jié)Summary
In this chapter, you
learned the basics of sound, sound filters, and music. You made real-time echo
and psuedo-3D filters, and you created a cool sound manager to handle game
sound effects. You also made some adaptive music and learned how to play back
MP3 and Ogg Vorbis sound files. Combining this knowledge with graphics and
interactivity from the previous chapters, you're ready to create your own game.
譯:在本章中,你學(xué)習(xí)了聲音基礎(chǔ)、聲音過濾器和播放音樂的相關(guān)知識,創(chuàng)建了實(shí)時(shí)回響過濾器和偽-3D過濾器,還創(chuàng)建了一個(gè)很酷的聲音管理器用于處理游戲聲效。你也創(chuàng)建了一些自適應(yīng)音樂并學(xué)習(xí)了如何播放MP3 和 Ogg
Vorbis 音頻文件。將這些知識結(jié)合前面章節(jié)學(xué)習(xí)的圖形和交互性知識,你已經(jīng)做好準(zhǔn)備,可以開始創(chuàng)建自己的游戲了。
學(xué)軟件開發(fā),到蜂鳥科技!
超強(qiáng)的師資力量 、完善的課程體系 、超低的培訓(xùn)價(jià)格 、真實(shí)的企業(yè)項(xiàng)目。
網(wǎng)址:www.ntcsoft.com
電話:0371-63839606
鄭州軟件開發(fā)興趣小組群:38236716
posted on 2010-11-27 01:37
whistler 閱讀(925)
評論(0) 編輯 收藏