Android音频之SoundPool

Android提供了两种不同的框架来处理音频,分别是:

SoundPool

和MediaPlayer主要用来播放一些长音频不同,SoundPool一般用来处理一些短的但是带有重叠,回放等特效的音频。这是因为SoundPool带有一个音频缓冲区,可以很方便的支持音频的回放、快放和慢放。

使用SoundPool的基本步骤

测试SoundPool

我在测试过程中发现不能播放大于1M的音频文件,所以这里使用一个900K的sound.wav做测试。在点击Play后,音乐将重复播放5次(mySP.play(soundId, 1f, 1f, 1, 5, rate)中的第5个参数指定),每重复点击Play按钮,音乐会降低一半速率播放(mySP.play(soundId, 1f, 1f, 1, 5, rate)中的第6个参数指定)。测试程序同时最大可以叠加10个音频(SoundPool(10, AudioManager.STREAM_MUSIC, 0)中的第1个参数指定)。

public class AudioExamplesSP extends Activity {

	static float rate = 2f;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		Button playButton = (Button) findViewById(R.id.play_pause);
		final SoundPool mySP = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
		final int soundId = mySP.load(this, R.raw.sound, 1);

		playButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				rate = rate / 2;
				mySP.play(soundId, 1f, 1f, 1, 5, rate);
			}
		});
	}
}

可能的问题

如果在播放中出现下面的错误:

sample 1 not READY

原因是SoundPool需要自己在后台启动一个线程来做音频回放,当调用SoundPool.load()加载资源后立即调用SoundPool.play()进行播放的时候,有可能出现资源加载未完成的情况,在这种情况下就可能出现上面的错误。解决的方法如下:

int sid = 0;
for(int i = 0; i < 1000; i++) {
    if(sid == 0) {
	try {
	    rate = rate / 2;
	    sid = mySP.play(soundId, 1f, 1f, 1, 5, rate);
	    Thread.sleep(1);
	} catch(InterruptedException e) {
	    e.printStackTrace();
	}
    } else {
	    break;
    }
}

为SoundPool设置OnLoadCompleteListener:这个监听器需要Android2.2以上才能使用。例如:

mySP.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
			
	@Override
	public void onLoadComplete(SoundPool arg0, int arg1, int arg2) {
		mySP.play(soundId, 1f, 1f, 1, 5, rate);
	}
});