Search code examples
androidaudioandroid-mediaplayersoundpool

Soundpool or MediaPlayer ? - Android


I am so confused of those two classes.

I have a problem that I have 1000 of .wav files, it depends on user to load different sounds.

as well as, user can play many sounds in a row, like 4 sounds sequentially.

so which should I use? SoundPool is better for wav files but it is not good that it loads and keep the files loaded.

any recommendation for this situation?


Solution

  • I have done it on my way using MediaPlayer, Thanks for @blipinsk, After i read this answer StackOverFlow suggested by him in the comment above.

    My files are a bit larger that SoundPool can tolerate, as well as, I want to play many files sequentially. Which i had to implement it myself using threads in SoundPool. On the contrary, It is ready in MediaPlayer using OnCompletionListener. So that, I used MediaPlayer.

    Actually i tried SoundPool with threads, it works but since it does not support large media files, i used Media Player.

    I wrote this class which wrap the MediaPlayer to run a playList, you can add to the playlist and the media player will run them one after another. so here is the class:

    import android.media.MediaPlayer;
    import android.os.Environment;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingQueue;
    
    /**
     * Created by MBH on 01.08.2015.
     */
    public class THSafeListMediaPlayer {
        private static final String TAG_DEBUG = "MBH";
        private String PATH_OF_SOUND_FILES; // I use it because i will put all sound clips in one folder
        // , then i will pass the name of the folder only.
        private LinkedBlockingQueue<String> playList;
        private MediaPlayer mediaPlayer; // The media player to play the sounds, even in background
        private ExecutorService executorService; // For making sure there is only one thread at a time
        // adding to the queue
        private boolean isPaused = false;
        private int pausedPosition = -1;
    
        /**
         * Constructor will take care of initializing all the important variables
         */
        public THSafeListMediaPlayer() {
            // initializing the variables
            executorService = Executors.newSingleThreadExecutor();
            playList = new LinkedBlockingQueue<>();
            mediaPlayer = new MediaPlayer();
            PATH_OF_SOUND_FILES = Environment.getExternalStorageDirectory().getPath() + "/mbh/sounds/";
        }
    
        /**
         * It will only add file to the PlayList
         *
         * @param fileName: The file name
         */
        public void addFile(String fileName) {
            // you may add executorService here for safer threads adding here
            // here i use offer, because it is thread safe
            playList.offer(fileName);
        }
    
        /**
         * It will add file and play the last add file and continue to the play list
         *
         * @param fileName: the file name, playing the soundtrack will start from this file
         */
        public void addFileAndPlay(final String fileName) {
            // For MultiThreaded
    //        executorService.submit(new Runnable() {
    //            @Override
    //            public void run() {
    //                playList.offer(fileName);
    //                if (!mediaPlayer.isPlaying())
    //                    play(playList.poll());
    //            }
    //        });
            // For single threaded
            playList.offer(fileName);
            if (!mediaPlayer.isPlaying())
                play(playList.poll());
        }
    
        /**
         * Start playing the play list if there is files in the playlist
         *
         * @return: True if playing successfully done, otherwise, false;
         */
        public boolean play() {
            if (mediaPlayer != null) {
                if (!mediaPlayer.isPlaying()) {
                    if (isPaused) {
                        mediaPlayer.seekTo(pausedPosition);
                        mediaPlayer.start();
                        pausedPosition = -1;
                        isPaused = false;
                        return true;
                    } else if (!playList.isEmpty()) {
                        play(playList.poll());
                        return true;
                    }
                }
            }
            return false;
        }
    
        /**
         * Pause the current played track, if there is track playing
         */
        public void pause() {
            if(isPaused)
                return;
            if (mediaPlayer != null) {
                if (mediaPlayer.isPlaying()) {
                    mediaPlayer.pause();
                    pausedPosition = mediaPlayer.getCurrentPosition();
                    isPaused = true;
                }
            }
        }
    
        /**
         * it will play the given file, when it finishes, or fails, it will play the next from the list
         *
         * @param fileName: the file name to start playing from it
         */
        private void play(String fileName) {
            if (mediaPlayer != null) {
                if (!mediaPlayer.isPlaying()) {
                    try {
                        mediaPlayer.reset();
                        mediaPlayer.setDataSource(fileName);
                        mediaPlayer.prepare();
                        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                            @Override
                            public void onCompletion(MediaPlayer mp) {
                                playNextSoundTrack();
                            }
                        });
                        mediaPlayer.start();
                    } catch (Exception e) {
                        // TODO: Remove this error checking before publishin
    
                        // If the current file is not found, play the next track if there is
                        playNextSoundTrack();
                    }
                }
            }
        }
    
        /**
         * this function will be called recursively to play the next track
         */
        private void playNextSoundTrack() {
            if (playList.size() != 0) {
                play(playList.poll());
            }
        }
    
    
    }
    

    I struggled for a while with it. I hope it will help others.

    NOTE: I used LinkedBlockingQueue to keep the playList tracks in it, because it is implemented to be thread safe.

    If you want to use this class in threads, i suggest you to use the executorService if u will use it in multithreaded app.