Use SoundPool to play sound effects (Duang~)


Introduction to this section:

Chapter 9 brings you multimedia development in Android. It is not so much multimedia development as multimedia related APIs. Let’s talk about the use of multimedia in actual development: taking pictures, recording, playing music, playing videos...

Well, okay, that seems to be it, right, for example To play music, we just call MediaPlayer and find the music file, Then call the play method to play... Of course, the real multimedia development is another field, audio and video encoding and decoding, I can only look up and wait for now, if only we knew how to call these APIs! By the way, we still need to popularize Android multimedia Some common sense about frameworks:

On Android, the default multimedia framework (multimedia framework) is OpenCore. The advantage of OpenCore is that it takes into account both It is cross-platform portable and has been verified by many parties, so it is relatively stable; but its disadvantage is that it is too large and complex. It takes a lot of time to maintain. Starting from Android 2.0, Google introduced Stagefright with a slightly simpler architecture. Of course, it did not completely abandon OpenCore. It mainly made an OMX layer, which is just a support for OpenCore. The omx-component part is referenced. There was a tendency to gradually replace OpenCORE, but in August this year I discovered A Stagefright vulnerability that allows remote code execution by exploiting a specially crafted MMS message.

This vulnerability affects Android 2.2 and newer versions, and has a relatively weak impact on Android 4.1 and newer versions. 1.jpg无义利 (I don’t even know what JB is talking about), um, okay, science popularization is over... It’s good to know these things!

By the way, this multimedia framework is located in the Media Framework of the third layer of the Android architecture (Libraries)! In addition, if you want to know what types of audio and video data the Android multimedia framework supports, please see the official documentation:

Supported Media Formats

You can click hereMedia and CameraThen look at the following document:

2.png

Well, there was too much nonsense at the beginning, and I almost forgot that today’s protagonist is SoundPool. As the title says, SoundPool is generally used Play intensive, rapid and short-lived sound effects, such as special effects: Duang~, which are often used in games. You can also add them to your The APP adds this sound effect. For example, when Kugou Music is played, "Hello, Kugou" is played. In fact, this idea is quite good. Indirectly let the user know the current volume of the player, otherwise as soon as the user plays the song, a small apple suddenly appears, attracting nearby It would be bad if Auntie dances, right? In addition to adding it in the music player, you can also add it in an ordinary APP, such as receiving push notifications. message or new chat message, and then play the prompt sound, such as the new version of the super curriculum, add this thing, and receive push notifications The message will play a short "table" sound! The SoundPool object can be viewed as a resource that can be imported from the APK Or load a sample collection of files from the file system. It utilizes the MediaPlayer service to decode the audio into a raw 16-bit PCM stream. This feature allows applications to perform stream compression without having to endure the CPU load and latency caused by decompression while playing audio. SoundPool uses the concept of Sound Effect Pool to manage multiple playback streams. If the maximum number of streams is exceeded, SoundPool will automatically stop the previously played stream based on priority. In addition, SoundPool also supports setting the sound quality, Volume, playback ratio and other parameters. Okay, without further ado, let’s start this section: Official API document: SoundPool


1. Related method introduction:


1) Construction method:

SoundPool(int maxStreams, int streamType, int srcQuality) The parameters are in order:

  • ①Specify how many sounds are supported and the maximum number of streams allowed to exist simultaneously in the SoundPool object.
  • ②Specify the sound type. The stream type can be divided into STREAM_VOICE_CALL, STREAM_SYSTEM,STREAM_RING,STREAM_MUSIC and STREAM_ALARMFour types. Defined in AudioManager.
  • ③Specify the sound quality (sampling rate conversion quality), usually set directly to 0!

The above construction method can be used in lower versions, but this construction method is obsolete after API 21 (Android 5.0)! When using a SoundPool.Builder, if we want to instantiate SoundPool, we only need to call:

SoundPool.Builder spb = new SoundPool.Builder();
spb.setMaxStreams(10);
spb.setAudioAttributes(null);    //转换音频格式
SoundPool sp = spb.build();      //创建SoundPool对象

If you want to use the above code, the TargetSDK version must be set to be greater than or equal to 21! And if the minSDK version is less than 21 The following reminder will appear:

3.png


2) Introduction to common methods:


Load sound resources:

  • load(Context context, int resId, int priority)
  • load(String path, int priority)
  • load(FileDescriptor fd, long offset, long length, int priority)
  • load(AssetFileDescriptor afd, int priority) The above methods will all return a sound ID. Later we can use this ID to play the specified sound

Parameter introduction:

  • context: context
  • resId: resource id
  • priority: a useless parameter, it is recommended to set it to 1 to maintain compatibility with the future
  • path: file path
  • FileDescriptor: It seems to be a stream, I don’t know about this
  • AssetFileDescriptor: Read a resource file from the asset directory, usage: AssetFileDescriptor descriptor = assetManager.openFd("biaobiao.mp3 ");

Playback control

play(int soundID, float leftVolume , float rightVolume, int priority, int loop, float rate)

The parameters are in order:

  • soundID: the sound ID number returned by Load()
  • leftVolume: Left channel volume setting
  • rightVolume: Right channel volume setting
  • priority: Specify the priority of playing sound. The higher the value, the greater the priority.
  • loop: Specify whether to loop: -1 means infinite loop, 0 means no loop, other values ​​indicate the number of times to be played repeatedly
  • rate: Specify the playback rate: a playback rate of 1.0 can make the sound according to its original frequency, and the playback rate of 2.0 can make the sound according to its Playback at twice the original frequency. If it is a playback rate of 0.5, the playback rate is half the original frequency. The playback rate ranges from 0.5 to 2.0.

Resource release:

You can call the release() method to release the memory occupied by all SoundPool objects and resources, of course also based on the sound ID to release!


3. Usage code example:

Run the rendering :

4.png

When When you click the button, it will "Duang". Here are two load methods demonstrated, namely raw and assets!

Key code

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button btn_play1;
    private Button btn_play2;
    private Button btn_play3;
    private Button btn_play4;
    private Button btn_play5;
    private Button btn_release;
    private AssetManager aManager;
    private SoundPool mSoundPool = null;
    private HashMap soundID = new HashMap();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        aManager = getAssets();
        try {
            initSP();
        } catch (Exception e) {
            e.printStackTrace();
        }
        bindViews();
    }

    private void bindViews() {
        btn_play1 = (Button) findViewById(R.id.btn_play1);
        btn_play2 = (Button) findViewById(R.id.btn_play2);
        btn_play3 = (Button) findViewById(R.id.btn_play3);
        btn_play4 = (Button) findViewById(R.id.btn_play4);
        btn_play5 = (Button) findViewById(R.id.btn_play5);
        btn_release = (Button) findViewById(R.id.btn_release);

        btn_play1.setOnClickListener(this);
        btn_play2.setOnClickListener(this);
        btn_play3.setOnClickListener(this);
        btn_play4.setOnClickListener(this);
        btn_play5.setOnClickListener(this);
        btn_release.setOnClickListener(this);

    }

    private void initSP() throws Exception{
        //设置最多可容纳5个音频流,音频的品质为5
        mSoundPool = new SoundPool(5, AudioManager.STREAM_SYSTEM, 5);
        soundID.put(1, mSoundPool.load(this, R.raw.duang, 1));
        soundID.put(2 , mSoundPool.load(getAssets().openFd("biaobiao.mp3") , 1));  //需要捕获IO异常
        soundID.put(3, mSoundPool.load(this, R.raw.duang, 1));
        soundID.put(4, mSoundPool.load(this, R.raw.duang, 1));
        soundID.put(5, mSoundPool.load(this, R.raw.duang, 1));
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_play1:
                mSoundPool.play(soundID.get(1), 1, 1, 0, 0, 1);
                break;
            case R.id.btn_play2:
                mSoundPool.play(soundID.get(2), 1, 1, 0, 0, 1);
                break;
            case R.id.btn_play3:
                mSoundPool.play(soundID.get(3), 1, 1, 0, 0, 1);
                break;
            case R.id.btn_play4:
                mSoundPool.play(soundID.get(4), 1, 1, 0, 0, 1);
                break;
            case R.id.btn_play5:
                mSoundPool.play(soundID.get(5), 1, 1, 0, 0, 1);
                break;
            case R.id.btn_release:
                mSoundPool.release();   //回收SoundPool资源
                break;
        }
    }
}

The code is very simple, and if you click the last button If so, the SoundPool will be released, and then other buttons It won’t be Duang~


4.OnLoadCompleteListener monitors whether the sound file has been loaded

Well, this is something I thought of temporarily. I will write another article after I finish it. Suddenly I remembered that the usage is very simple, we can Add OnLoadCompleteListener to the above code, and then override the onLoadComplete() method , and finally set this thing for the SoundPool object!

mSoundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
    @Override
    public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
        Toast.makeText(MainActivity.this,"加特技准备完毕~",Toast.LENGTH_SHORT).show();
    }
});

5. Sample code download:

SoundPoolDemo.zip


Summary of this section:

Okay, this section will give you some common sense about Andorid multimedia, and teach you how to add sound effects to your APP. It can be achieved through a simple SoundPool. What are you waiting for? Add this thing to your application to make your application Duang~

5.gif

, use it with the Demo Better~