【问题标题】:How to create and play a sound or audio queue in Android如何在 Android 中创建和播放声音或音频队列
【发布时间】:2013-07-05 08:49:06
【问题描述】:

我有许多简短的音频片段,应该以最小的延迟顺序播放。

如何有效地排队这些声音?

【问题讨论】:

标签: android audio


【解决方案1】:

我可以通过两种方式看到它的工作原理:使用 MediaPlayerSoundPool

媒体播放器

您可以使用MediaPlayer.OnCompletionListener 结合文件列表来简单地监听完成并播放下一个文件。总的来说,这很好用,我用它播放非常短的片段(

声音池

另一种方法是使用SoundPool 类结合处理程序来简单地提前排队播放事件。这假设您知道每个剪辑的长度,但根据格式您应该能够找到它。

您选择哪种解决方案取决于多种因素:文件数量、文件长度、格式、从何处获取文件、列表的固定或可变程度等。

我个人会选择MediaPlayer,因为这更容易实现并且可能满足您的需求。

【讨论】:

  • 我的剪辑最长只有几秒钟。那我先试试MediaPlayer。
  • 目前看来 MediaPlayer 方法已经足够好了。谢谢!
  • 很高兴听到这个消息!你以后总是可以让它变得更复杂:)
【解决方案2】:

一种方法是将它们连接成一个音频文件,然后为其创建一个 MediaPlayer 并设置一个 OnSeekCompleteListener。以您喜欢的顺序查找 tern 中的每个片段,然后在 onSeekComplete() 中播放它们。时间不准确,而且 MediaPlayer 使用起来很敏感,所以它可能不是你的最佳选择,但对我的目的来说已经足够了。

这是我的代码:

private MediaPlayer MP = new MediaPlayer();

@Override
public void onCreate(Bundle savedInstanceState) {
    //...

    FileDescriptor fd = getResources().openRawResourceFd(R.raw.pronounciations).getFileDescriptor();
    try {
        setVolumeControlStream(AudioManager.STREAM_MUSIC); // Lets the user control the volume.
        MP.setDataSource(fd);
        MP.setLooping(false);
        MP.prepare();
        MP.start(); // HACK! Some playing seems required before seeking will work.
        Thread.sleep(60); // Really need something like MediaPlayer.bufferFully().
        MP.pause();
        MP.setOnErrorListener(new OnErrorListener() {
            public boolean onError(MediaPlayer mp, int what, int extra) {
                return false;
            }
        });
        MP.setOnSeekCompleteListener(new OnSeekCompleteListener() {
            public void onSeekComplete(MediaPlayer mp) {
                // The clip is queued up and read to play.
                // I needed to do this in a background thread for UI purposes.
                // You may not need to.
                new Thread() {
                    @Override
                    public void run() {
                        MP.start();
                        try {
                            Thread.sleep(soundRanges[curWordID][1]);
                        } catch(InterruptedException e) {}
                        MP.pause();
                    }
                }.start();
            }
        });
    } catch(Throwable t) {}
}

private void playCurrentWord() {
    if(soundRanges != null && !MP.isPlaying() && !silentMode) {
        try {
            MP.seekTo(soundRanges[curWordID][0]);
        }
        catch(Throwable t) {}
    }
}

您可能需要使用外部声音编辑工具连接您的剪辑。我使用 Audacity 查找和编辑保存在文件中的剪辑开头和长度。

soundRanges[curWordID][0] 是声音文件中剪辑开头的偏移量,soundRanges[curWordID][1] 是它的长度。

【讨论】:

  • 你能详细说明一下这个方法吗?你在内存中连接这个吗?我还没有找到支持从内存播放的 API,它总是需要某种文件描述符。
  • 好的,我编辑添加了相关的代码片段,但看起来你已经有了一个不需要串联的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-26
  • 1970-01-01
  • 2022-11-22
  • 1970-01-01
  • 1970-01-01
  • 2014-07-25
相关资源
最近更新 更多