Android游戲音效實現
1. 游戲音效SoundPool
游 戲中會根據不同的動作 , 產生各種音效 , 這些音效的特點是短暫(叫聲,爆炸聲可能持續不到一秒) , 重復(一個文件不斷重復播放) , 并且同時播放(比如打怪時怪的叫聲 , 和技能釋放的聲音需要同時播放) , 即時(技能用處之后聲音馬上隨著玩家操作發出,不能有延遲).
MediaPlayer會占用大量的系統資源 , 并且不能同時播放 , 并且無法實現即時音效 , 這里引入了一個新的類 -- SoundPool , 這個類完全滿足上面提出的四點要求 , 可以無延時播放游戲中的短暫音效 .
2. 相關API介紹
(1) SoundPool
構造方法 : SoundPool(int maxStreams, int streamType, int srcQuality) ;
參數解析 :
maxStream : 該參數是定義最多能同時播放的多少音效 .
streamType : 該參數定義音頻類型 , 游戲中一般設置為AudioManager.STREAM_MUSIC .
srcQuality : 該參數用來設置音頻質量 , 這個參數目前沒有作用 , 這里設置為 0;
加載音頻文件方法 : int load(Context context, int resId, int priority);
參數解析 :
context : 上下文對象;
resId : 要加載的資源文件 , 即R.raw.music...
priority : 優先級別 , 這里沒有作用 , 設置為1.
播放音效方法 : int play(int soundId, float leftVolume, float rightVolume, int priority, int loop, float rate);
參數解析 :
soundId : 這個id不是資源id , 指的是利用load方法加載資源文件返回的id值 , 這個要區別清楚.
leftVolume : 左聲道的音量 , 這個音量是一個 0 ~ 1的數 , 這個小數是當前音量/最大音量的結果;
rightVolume : 右聲道的音量 , 這個音量與左聲道的音量是同一種音量;
priority : 優先級參數 , 0為最低, 這里設置為1;
loop : 音效循環的次數 , 0為不循環 , -1為永遠循環;
rate : 音效回放的速度 , 這個值是在0.5~2.0f之間 , 1f是正常速度;
暫停音效播放方法 : pause(int streamId);
參數streamId : 這個參數是play()方法執行完之后的返回值 , 這個返回值是正在播放的音效的一個標識 , 對正在播放的音效進行操作的時候 , 就需要這個標識來對其進行操作;
通知音效播放方法 : stop(int streamId) , 這個參數與上面的pause()方法中的streamId參數是一個效果.
(2)AudioManager
獲取方法 : AudioManager對象時系統服務, 可以通過調用上下文對象的getSystemService(Context.AUDIO_SERVICE)獲取 , 注意獲取到之后 , 需要將對象墻磚為AudioManager對象才可以使用.
eg : AudioManager audioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
利用AudioManager獲取當前音量的方法 : float currVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
利用AudioManager獲取當前系統最大音量方法 : float maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
使用這兩個音量就可以計算出運行SoundPool音效的音量 , 當前音量 / 系統最大音量 , 結果就是soundPool.play()方法中需要傳入的音量 ;
3. 程序代碼 public class MainActivity extends Activity implements OnClickListener {
private SoundPool soundPool;
private HashMap<Integer, Integer> hashMap;
private int currStreamId;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initSoundPool();
}
private void initSoundPool() {
soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
hashMap = new HashMap<Integer, Integer>();
hashMap.put(1, soundPool.load(getApplicationContext(), R.raw.musictest, 1));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_play:
play(1, 0);
Toast.makeText(getApplicationContext(), "播放即時音效", Toast.LENGTH_LONG).show();
break;
case R.id.bt_stop:
soundPool.stop(currStreamId);
Toast.makeText(getApplicationContext(), "暫停播放", Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
private void play(int sound, int loop) {
AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
float currVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float volume = currVolume / maxVolume;
currStreamId = soundPool.play(hashMap.get(sound), volume, volume, 1, loop, 1.0f);
System.out.println(currStreamId);
}
} </pre></span></h1>
4. 程序的注意點
- 音效文件需要放在res的raw下.
- SoundPool播放的音效要小于7秒 , 否則會出現加載失敗的現象;
- 在Android平臺上使用的即時文件越小越好 , 必要的時候可以降低采樣頻率或者將立體聲改為單聲道;
private SoundPool soundPool;
private HashMap<Integer, Integer> hashMap;
private int currStreamId;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initSoundPool();
}
private void initSoundPool() {
soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
hashMap = new HashMap<Integer, Integer>();
hashMap.put(1, soundPool.load(getApplicationContext(), R.raw.musictest, 1));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_play:
play(1, 0);
Toast.makeText(getApplicationContext(), "播放即時音效", Toast.LENGTH_LONG).show();
break;
case R.id.bt_stop:
soundPool.stop(currStreamId);
Toast.makeText(getApplicationContext(), "暫停播放", Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
private void play(int sound, int loop) {
AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
float currVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float volume = currVolume / maxVolume;
currStreamId = soundPool.play(hashMap.get(sound), volume, volume, 1, loop, 1.0f);
System.out.println(currStreamId);
}
} </pre></span></h1>