美文网首页
Android 使用 SoundPool 播放音乐

Android 使用 SoundPool 播放音乐

作者: gaookey | 来源:发表于2022-02-21 12:09 被阅读0次
    image.png

    MediaPlayer 存在如下缺点:

    • 资源占用量较高,延迟时间较长。
    • 不支持多个音频同时播放。

    除使用 MediaPlayer 播放音频之外,Android 还提供了 SoundPool 来播放音效,SoundPool 使用音效池的概念来管理多个短促的音效,例如它可以开始就加载20个音效,以后在程序中按音效的 ID 进行播放。

    SoundPool 主要用于播放一些较短的声音片段,与 MediaPlayer 相比,SoundPool 的优势在于 CPU 资源占用量低和反应延迟小。另外,SoundPool 还支持自行设置声音的品质、音量、播放比率等参数。

    Android 系统 SoundPool 提供了一个 Builder 内部类,该内部类专门用于创建 SoundPool

    一旦得到了 SoundPool 对象之后,接下来就可调用 SoundPool 的多个重裁的 load() 方法来加载声音了。SoundPool 提供了如下 4 个 Load() 方法。

    int load(Context context, int resId, int priority)resId 所对应的资源加载声音。
    int load(FileDescriptor fd, long offset, long length, int priority) 加载 fd 所对应的文件中从 offset 开始、长度为 length 的声音。
    int load(AssetFileDescriptor afd, int priority)afd 所对应的文件中加载声音。
    int load(String path, int priority)path 对应的文件去加载声音。

    上面 4 个方法中都有一个 priority 参数,该参数目前还没有任何作用,Andtroid 建议将该参数设为 1,保持和未来的兼容性。
    上面 4 个方法加载声音之后,都会返回该声音的 ID,以后程序就可以通过该声音的 ID 来播放指定声音了:

    int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) 该方法的第一个参数指定播放哪个声音;leftVolumerightVolume 指定左、右的音量;priority 指定播放声音的优先级,数值越大,优先级越高;loop 指定是否循环,0 为不循环,-1 为循环;rate 指定播放的比率,数值可从 0.5 到 2,1 为正常比率。

    public class MainActivity extends AppCompatActivity {
       // 定义一个SoundPool
       private SoundPool soundPool;
       private HashMap<Integer, Integer> soundMap = new HashMap<>();
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
           Button bombBn = findViewById(R.id.bomb);
           Button shotBn = findViewById(R.id.shot);
           Button arrowBn = findViewById(R.id.arrow);
           AudioAttributes attr = new AudioAttributes.Builder().setUsage(
                           AudioAttributes.USAGE_GAME) // 设置音效使用场景
                   // 设置音效的类型
                   .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
           soundPool = new SoundPool.Builder().setAudioAttributes(attr) // 设置音效池的属性
                   .setMaxStreams(10) // 设置最多可容纳10个音频流
                   .build();  // ①
           // 使用load方法加载指定的音频文件,并返回所加载的音频ID
           // 此处使用HashMap来管理这些音频流
           soundMap.put(1, soundPool.load(this, R.raw.bomb, 1));  // ②
           soundMap.put(2, soundPool.load(this, R.raw.shot, 1));
           soundMap.put(3, soundPool.load(this, R.raw.arrow, 1));
           // 定义一个按钮的单击监听器
           View.OnClickListener listener = source -> {
               int sourceId = source.getId();
    
               // 判断哪个按钮被单击
               if (sourceId == R.id.bomb) {
                   soundPool.play(soundMap.get(1), 1f, 1f, 0, 0, 1f);  // ③
               } else if (sourceId == R.id.shot) {
                   soundPool.play(soundMap.get(2), 1f, 1f, 0, 0, 1f);
               } else if (sourceId == R.id.arrow) {
                   soundPool.play(soundMap.get(3), 1f, 1f, 0, 0, 1f);
               }
           };
           bombBn.setOnClickListener(listener);
           shotBn.setOnClickListener(listener);
           arrowBn.setOnClickListener(listener);
       }
    }
    

    SoundPool 虽然可以一次性加载多个声音,但由于内存限制,因此应该避免使用 SoundPool 来播放歌曲或者做游戏背景音乐,只有那些短促、密集的声音才考虑使用 SoundPool 进行播放。虽然 SoundPoolMediaPlayer 的效率好,但也不是绝对不存在延迟问题,尤其在那些性能不太好的手机中,SoundPool 的延迟问题会更严重。

    摘抄至《疯狂Android讲义(第4版)》

    相关文章

      网友评论

          本文标题:Android 使用 SoundPool 播放音乐

          本文链接:https://www.haomeiwen.com/subject/xmkglrtx.html