SoundPool 加载缓慢,MotionEvent 很奇怪

Posted

技术标签:

【中文标题】SoundPool 加载缓慢,MotionEvent 很奇怪【英文标题】:SoundPool loads slowly and is weird with MotionEvent 【发布时间】:2020-09-13 18:39:30 【问题描述】:

嗨! 我对编程很陌生,我遇到了一些关于 SoundPool 的问题。 我正在尝试构建一个简单的钢琴应用程序,但尚未找到解决方案。我使用的音频文件是 midi (.mid)

我的代码当前存在的问题:

音频文件加载速度很慢,我必须等待几秒钟才能让 SOUND_12 准备好。 如果我只用一根手指,它可以正常工作,但是当我添加另一根手指时,第一根手指/声音会卡住。

我当前的代码:


public class MainActivityPiano extends AppCompatActivity 

    //all soundIDs
    public static final int SOUND_1 = 1;
    public static final int SOUND_2 = 2;

    SoundPool mSoundPool;
    HashMap<Integer, Integer> mSoundMap;

    static int streamID;

    @Override
    protected void onStart() 
        super.onStart();
        
        mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
        mSoundMap = new HashMap<Integer, Integer>();

        if(mSoundPool != null)
            mSoundMap.put(SOUND_1, mSoundPool.load(this, R.raw.piano_tone1, 1));
            mSoundMap.put(SOUND_2, mSoundPool.load(this, R.raw.piano_tone2, 1));
            //at least twelve different sound files have to be loaded...
        

        //play buttons and/or piano keys
        Button pianoKey1 = this.findViewById(R.id.piano_key1);
        Button pianoKey2 = this.findViewById(R.id.piano_key2);
        //...

        //play buttons and/or pianokeys
        pianoKey1.setOnTouchListener(new View.OnTouchListener() 
            public boolean onTouch(View view, MotionEvent motionEvent) 
                return playSound(SOUND_1, motionEvent, view);
            
        );
        pianoKey2.setOnTouchListener(new View.OnTouchListener() 
            public boolean onTouch(View view, MotionEvent motionEvent) 
                return playSound(SOUND_2, motionEvent, view);
            
        );
        //...
    

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

    public boolean playSound(int sound, MotionEvent m, View v) 

        switch (m.getAction()) 
            case MotionEvent.ACTION_DOWN:
                streamID = mSoundPool.play(sound, 1, 1, 1, 0, 1.0f);
                break;

            case MotionEvent.ACTION_CANCEL:;
                mSoundPool.stop(streamID);

                break;
            case MotionEvent.ACTION_UP:
                mSoundPool.stop(streamID);

                break;
            case MotionEvent.ACTION_MOVE:

        
        return true;
    

    @Override
    protected void onPause() 
        mSoundPool.autoPause();
        super.onPause();
    




【问题讨论】:

【参考方案1】:

您可能希望预加载声音,然后通过引用它们的 id 来播放它们。

short[] 数组将包含您传递给 getSound()fileNames 中相应文件的 ID

创建一个单独的类Sound.java: 在您的 Main Activity 中,您可以创建一个 Sound 对象并在 onCreate() 中加载一次声音并使用它们的 id 播放它们。

public class Sound 
    private static SoundPool soundPool;
    
    public short[] getSound(Activity activity, String...fileNames) 
        soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
        short[] ids = new short[fileNames.length];
        activity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
        try 
            AssetManager assetManager = activity.getAssets();
            for(int i = 0; i < fileNames.length; i++) 
                AssetFileDescriptor descriptor = assetManager.openFd(fileNames[i]);
                ids[i] = (short) soundPool.load(descriptor, 1);
            
         catch(IOException e) 
            //
        
        return ids;
    
    
    public void playSound(short id, float rV, float lV) 
        if(id != -1) 
            soundPool.play(id, rV, lV, 0, 0, 1);
        
    
    
    public void pauseSound() 
        soundPool.autoPause();
       

    
    public void releaseSound() 
        soundPool.release();
    

【讨论】:

太棒了!谢谢,但我如何处理多点触控而不让声音卡住?

以上是关于SoundPool 加载缓慢,MotionEvent 很奇怪的主要内容,如果未能解决你的问题,请参考以下文章

有效地为 SoundPool 加载声音(全局 SoundPool?)

SoundPool.load() 是不是设计为异步加载?

SoundPool 加载失败

Android - 使用变量加载到 SoundPool。

加载文件时Android Soundpool错误

如何在 soundPool (Android) 中逐渐加载声音?