看名字的话SoundPool就是一个声音池,里面存放了一系列的声音资源可供随时使用。优点如下:
上面是优点,看了之后缺点也很明显空间换时间那就是耗内存
第一种,通过SoundPool推荐通过 SoundPool.Builder 来创建对象,比较推荐这种方式
mSoundPool = new SoundPool.Builder()
.setMaxStreams(NUM_SOUNDPOOL_CHANNELS) //传入最多播放音频数量
.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setInternalLegacyStreamType(AudioManager.STREAM_MUSIC) //设置合适的流类型
.build())// 构造一个AudioAttributes,里面封装了音频的各种描述属性(后面还会讲到)
.build();
第二种,直接通过public的构造方法创建
/**
* 第一个参数:int maxStreams:SoundPool对象的最大并发流数
* 第二个参数:int streamType:AudioManager中描述的音频流类型
*第三个参数:int srcQuality:采样率转换器的质量。 目前没有效果。 使用0作为默认值。
*/
mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
看起来是两种方法,但是实际都会调用到SoundPool的native_setup
SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes)
{
//根据传入的参数初始化多个SoundChanel,最多32个
mChannelPool = new SoundChannel[mMaxChannels];
for (int i = 0; i < mMaxChannels; ++i) {
mChannelPool[i].init(this);
mChannels.push_back(&mChannelPool[i]);
}
// start decode thread //开始一个解码的线程
startThreads();
}
SoundPoolThread 跑起来之后就等着Load资源文件
int SoundPoolThread::run() {
ALOGV("run");
for (;;) {
SoundPoolMsg msg = read();
ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
switch (msg.mMessageType) {
case SoundPoolMsg::KILL:
ALOGV("goodbye");
return NO_ERROR;
case SoundPoolMsg::LOAD_SAMPLE:
doLoadSample(msg.mData);
break;
default:
ALOGW("run: Unrecognized message %d\n",
msg.mMessageType);
break;
}
}
}
可以通过四种途径来记载一个音频资源:
在AudioService中,按键音用的 int load(String path, int priority) 这种方式,我们就看下这种方式吧。
public int load(String path, int priority) {
int id = 0;
try {
File f = new File(path);
ParcelFileDescriptor fd = ParcelFileDescriptor.open(f,
ParcelFileDescriptor.MODE_READ_ONLY);
if (fd != null) {
id = _load(fd.getFileDescriptor(), 0, f.length