最近在做一个音乐相关的项目,接触到了SoundPool,使用其来播放音乐。
SoundPool 顾名思义是声音的池子。看看下面SoundPool官方文档的解释:
The SoundPool class manages and plays audio resources for applications.
A SoundPool is a collection of samples that can be loaded into memory
from a resource inside the APK or from a file in the file system.
为什么他们要用SoundPool 而不用MediaPlayer? 它们有什么区别呢?
为了以后就不用对着英文翻译,就把整个SoundPool文档翻译了一下:
除了低延迟播放之外,SoundPool还可以管理一次渲染的音频流数量。当构建SoundPool对象时,maxStreams参数设置可从此单个SoundPool一次播放的最大流数。 SoundPool跟踪活动流的数量。如果超过了最大数量的数据流,SoundPool会根据优先级自动停止先前播放的数据流,然后根据该优先级按年龄自动停止。限制数据流的最大数量有助于限制CPU负载,并减少混音会影响视觉效果或UI性能的可能性。
声音可以通过设置非零循环值来循环。值为-1会导致声音永久循环。在这种情况下,应用程序必须显式调用stop()函数来停止声音。任何其他非零值将导致声音重复指定的次数,例如,值为3会导致声音总共播放4次。
播放速率也可以改变。 1.0的播放速率会导致声音以其原始频率播放(如果需要,重新采样至硬件输出频率)。 2.0的播放速率会使声音以原始频率的两倍播放,0.5的播放速度会使其以原始频率的一半播放。播放速率范围是0.5到2.0。
优先级从低到高,即数字越大,优先级越高。当创建SoundPool时,对play()的调用会导致活动流的数量超过maxStreams参数所设置的值时使用优先级。在这种情况下,流分配器将停止最低优先级的流。如果有多个具有相同低优先级的流,它将选择最旧的流停止。在新流的优先级低于所有活动流的情况下,新的声音将不会播放,并且play()函数将返回0的流ID。
让我们来看一个典型的用例:一个游戏包含多个层次的游戏。对于每个级别,都有一组只有该级别使用的独特声音。在这种情况下,游戏逻辑应该在第一级加载时创建一个新的SoundPool对象。关卡数据本身可能包含此关卡使用的声音列表。加载逻辑遍历调用相应SoundPool.load()函数的声音列表。这通常应该在流程的早期完成,以便在需要播放之前有时间将音频解压为原始PCM格式。
一旦声音加载并开始播放,应用程序可以通过调用SoundPool.play()来触发声音。播放流可以暂停或恢复,应用程序还可以通过实时调整播放速率来改变音高,以获得多普勒效应或综合效果。
请注意,由于流可因资源限制而停止,因此streamID是对流的特定实例的引用。如果流停止以允许播放更高优先级的流,则流不再有效。但是,应用程序可以无错地调用streamID上的方法。这可能有助于简化程序逻辑,因为应用程序不需要关注流生命周期。
在我们的例子中,当玩家完成关卡时,游戏逻辑应该调用SoundPool.release()来释放所有正在使用的本地资源,然后将SoundPool参考设置为null。如果玩家开始另一个关卡,则会创建一个新的SoundPool,声音会被载入,然后重新开始播放。
从SoundPool文档中,以及小白对MediaPlayer 之前的简单使用,总结了亮点:
soundPool 相比MediaPlayer 播放延时更低;
soundPool 适用于播放声音短促的音乐文件(10s以内的)
支持多个音频同时播放
SoundPool (int maxStreams, int streamType, int srcQuality)
//maxStreams 设置soundpool对象的并发流的最大数量
//streamType 设置流的类型,一般为STREAM_MUSIC
//srcQuality 采样转换率的质量 现在没有什么效果 0 设为默认
但在上面的构造方法在api 21 被废弃了。API 21 以后使用SoundPool.Builder创建soundpool对象实例:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
mSoundPool = new SoundPool.Builder()
.setMaxStreams(maxSteams)
.build();
} else {
mSoundPool = new SoundPool(maxSteams, AudioManager.STREAM_MUSIC, 0);
}
加载音频文件
与MediaPlayer相同 SoundPool 加载音频文件有多种方式
注意:切忌使用文件名相同,格式名不同的文件example.mp3 ,example.wav
int load(Context context, int resId, int priority)
int load(String path, int priority)
int load(AssetFileDescriptor afd, int priority)
int load(FileDescriptor fd, long offset, long length, int priority)
上述方法加载音频返回一个sound ID. 这个ID就是用来播放对应加载音乐文件以及相应操作的标识。
控制播放等一些其他设置
stop(int streamID)
pause(int streamID)
resume(int streamID)
release()
setLoop(int streamID, int loop)
setPriority(int streamID, int priority)
setRate(int streamID, float rate)
setVolume(int streamID, float leftVolume, float rightVolume)
unload(int soundID)
autoPause()
autoResume()
监听
setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener)
SoundPool 使用起来还是很简单的。还是想总结一下做个笔记。
每天都有进步。