您的当前位置:首页正文

Android P SoundPool简介

2024-11-29 来源:个人技术集锦

简介

看名字的话SoundPool就是一个声音池,里面存放了一系列的声音资源可供随时使用。优点如下:

  • 适合短且对反应速度要求比较高、也就是要求低延时的情况(游戏音效或按键声等),文件大小一般控制在几十K到几百K,最好不超过1M
  • SoundPool与MediaPlayer不同的地方就是SoundPool可以同时播放多个声音
  • 将音频从文件系统加载进内存后就一直在内存上托管着不释放。并为每个音频生成一个索引号,以后每次需要播放时就直接顺着这个索引号找到已经位于内存中的音频进行解码并播放即可

上面是优点,看了之后缺点也很明显空间换时间那就是耗内存

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;
        }
    }
}

SoundPool load

可以通过四种途径来记载一个音频资源:

在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
显示全文