首页 > 解决方案 > SoundPool 加载缓慢并且在 MotionEvent 中很奇怪

问题描述

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

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

我当前的代码:


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();
    }

}


标签: javaandroidmulti-touchsoundpoolmotionevent

解决方案


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

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

创建一个单独的类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();
    }
}

推荐阅读