带有约 300 个文件的音板 - 我使用啥方法播放短声音?

Posted

技术标签:

【中文标题】带有约 300 个文件的音板 - 我使用啥方法播放短声音?【英文标题】:Soundboard with ~300 files - what method to play short sounds do I use?带有约 300 个文件的音板 - 我使用什么方法播放短声音? 【发布时间】:2016-05-14 22:29:53 【问题描述】:

3 天前我开始玩 android Studio,现在我想为《守望先锋》英雄制作一个音板。 我为这 21 个英雄中的每一个选择了 15 个语音文件,所以它会超过 300 个语音文件。

对于每个英雄,我都有一个单独的活动,其中每个语音文件有 15 个按钮。

XML 文件都是按照我的喜好完成的。

我正在重新考虑的是我播放声音的方法。

首先,我对每种声音都使用了 MediaPlayer。但后来我读到 MediaPlayer 不适用于约 3 秒的声音,我应该使用 SoundPool。 MediaPlayer 运行良好,但如果我向一个按钮发送垃圾邮件,则会有一个巨大的(10 秒)延迟,直到我可以再次播放声音。 我想尝试 SoundPool 库,但每次我想播放声音时,它都会告诉我样本 1 尚未准备好。 不管我等多久,它永远不会完成加载。 我知道我可以添加一个 onLoadCompleteListener 但我必须分别为所有 315 个按钮执行此操作...

如你所见,我有点迷茫。

这是我的代码:(只有一个活动类,因为其他活动类仍在使用 MediaPlayer...

package eleumnoyce.newsoundboard;

import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import java.util.HashMap;

public class genji extends AppCompatActivity 

    @Override
    protected void onCreate(Bundle savedInstanceState)
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_genji);
    

    public void genjiClick(View v)  //genjiClick is the OnClick in my XML

        int afterthis = 1;


        SoundPool genjiPool;
        HashMap<Integer, Integer> genjiMap;
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
        genjiPool = new SoundPool(14, AudioManager.STREAM_MUSIC, 100);
        genjiMap = new HashMap<Integer, Integer>();

        genjiMap.put(afterthis, genjiPool.load(this, R.raw.genjiafterthis, 1));

        switch (v.getId()) 
            case R.id.genji1:  genjiPool.play(genjiMap.get(afterthis), 1, 1, 0, 0, 1);

            /*case R.id.genji2:
                mPlayer = MediaPlayer.create(this, R.raw.genjiasteadyblade);
                mPlayer.start();
                break;

            case R.id.genji3:
                mPlayer = MediaPlayer.create(this, R.raw.genjifatesmiles);
                mPlayer.start();
                break;

            case R.id.genji4:
                mPlayer = MediaPlayer.create(this, R.raw.genjiflowlike);
                mPlayer.start();
                break;

            case R.id.genji5:
                mPlayer = MediaPlayer.create(this, R.raw.genjiiamcertain);
                mPlayer.start();
                break;

            case R.id.genji6:
                mPlayer = MediaPlayer.create(this, R.raw.genjiinbalancefind);
                mPlayer.start();
                break;

            case R.id.genji7:
                mPlayer = MediaPlayer.create(this, R.raw.genjijustmystyle);
                mPlayer.start();
                break;

            case R.id.genji8:
                mPlayer = MediaPlayer.create(this, R.raw.genjijustsettingfoot);
                mPlayer.start();
                break;

            case R.id.genji9:
                mPlayer = MediaPlayer.create(this, R.raw.genjimeasuretwice);
                mPlayer.start();
                break;

            case R.id.genji10:
                mPlayer = MediaPlayer.create(this, R.raw.genjimybladeis);
                mPlayer.start();
                break;

            case R.id.genji11:
                mPlayer = MediaPlayer.create(this, R.raw.genjirevenge);
                mPlayer.start();
                break;

            case R.id.genji12:
                mPlayer = MediaPlayer.create(this, R.raw.genjisomehingfor);
                mPlayer.start();
                break;

            case R.id.genji13:
                mPlayer = MediaPlayer.create(this, R.raw.genjitheresnotime);
                mPlayer.start();
                break;

            case R.id.genji14:
                mPlayer = MediaPlayer.create(this, R.raw.genjitoknowyourself);
                mPlayer.start();
                break;*/
        
    

如果您想进一步帮助我:有没有更好、更优雅的方法来做到这一点?

【问题讨论】:

onCreate(或onStartonResume - 也不要忘记用相反的方法破坏它,例如onDestroy)构建音池,然后只播放来自点击处理程序中的现有池。这样它就有时间加载了。 您无需为 21 位英雄创建单独的活动。从你的“baseactivity”中,一个带有英雄名字的包被发送到你的“soundlistactivity”。 “soundlistactivity”检查包中的名称,并在所有具有相关文件的地方设置数据。 但是如果我在 onCreate 中创建它,我的 onClick 方法将不知道我所说的“genjiPool.play(somefile)”是什么意思,对吗? 【参考方案1】:

首先,如果您使用的是 wav 或类似的东西,请不要。使用 .ogg 文件与 SoundPool 一起玩。这会减少延迟并显着提高性能。

那么你应该拆分你的 315 个声音。每个 soundpool 对象应该负责大约 15-20 个声音。使用这种方法,您可以轻松加载 315 声音,但这可能会在一些旧设备上出现问题。

此外,由于 Android 的限制,您不能同时播放超过 24-25 个声音。 (参考:AudioFlinger could not create track. status: -12)

注意:您应该以这种格式使用 SoundPool:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
        AudioAttributes attributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA)
                .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();

        mSoundPool = new SoundPool.Builder().setAudioAttributes(attributes).setMaxStreams(6).build();
     else 
        mSoundPool = new SoundPool(6, AudioManager.STREAM_MUSIC, 0);
    

6是同时最大可播放声音数的流声音。

【讨论】:

以上是关于带有约 300 个文件的音板 - 我使用啥方法播放短声音?的主要内容,如果未能解决你的问题,请参考以下文章

Java音板 - 听起来不便携

使用存储文件夹播放 .mp3 UWP

iPhone:在通话期间在应用程序中调整播放音量

音板应用程序上的媒体播放器错误

使用原始文件在列表视图中添加图像视图

这个 XML 代码有啥问题? - 安卓工作室