android - Soundpool 或 MediaPlayer ? - 安卓

标签 android audio android-mediaplayer soundpool

我对这两个类(class)感到很困惑。

我有一个问题,我有 1000 个 .wav 文件,它取决于用户加载不同的声音。

此外,用户可以连续播放多个声音,例如顺序播放 4 个声音。

那么我应该使用哪个? SoundPool对于 wav 文件更好,但它加载并保持文件加载并不好。

对这种情况有什么建议吗?

最佳答案

我在途中使用 MediaPlayer 完成了它,感谢@blipinsk,在我阅读此答案后StackOverFlow他在上面的评论中建议。

我的文件有点大,SoundPool 可以容忍,而且我想按顺序播放许多文件。我必须自己使用 SoundPool 中的线程来实现它。相反,它在 MediaPlayer 中使用 OnCompletionListener 准备就绪。因此,我使用了 MediaPlayer。

实际上我用线程尝试了 SoundPool,它可以工作,但由于它不支持大型媒体文件,所以我使用了媒体播放器。

我写了这个类,它包装了 MediaPlayer 来运行一个播放列表,你可以添加到播放列表中,媒体播放器会一个接一个地运行它们。所以这是类(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());
        }
    }


}

我挣扎了一会儿。我希望它会帮助别人。

注意:我用了 LinkedBlockingQueue 将播放列表轨道保留在其中,因为它被实现为线程安全的。

如果你想在线程中使用这个类,我建议你使用 executorService如果您将在多线程应用程序中使用它。

关于android - Soundpool 或 MediaPlayer ? - 安卓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31720205/

相关文章:

java - 无需切换即可处理 View 的 ID

Android 通过蓝牙将文件/数据从应用程序发送到 PC/打印机/扫描仪/其他设备

python - 使用 Python 从 wav 文件创建振幅列表

audio - 将多个输入 channel 组合到一个输出 channel 音频直播

android - Media Session Compat 未在 Pre-Lollipop 上显示锁屏控件

android - 我可以在我的 list 中添加多个接收者吗?

c# - 同时播放三种声音C#

android - 无法在对话框中使用 android MediaPlayer 播放声音?

java - 自定义流媒体实现

android - 使用 Galaxy S4 在 onActivityResult 时应用程序崩溃