Tech & Programming/모바일(Android, Flutter)

Soundpool 재생이 안되는 경우 해결방법 (Soundpool.load 딜레이)

소스코드 요리사 2018. 8. 18. 07:06

토이프로젝트로 마켓에 출시했던 '어린이 낱말카드' (2017/11/29 - [Toy Project] - 어린이 낱말카드) 에 낱말카드로 할 수 있는 게임기능을 넣어달라는 요청이 있어 최근에 개발을 했습니다. 낱말카드 중 하나의 텍스트를 보여주고, 4가지 낱말카드 이미지 중 텍스트에 해당하는 이미지를 찾는 게임입니다.

이 때 이미지를 터치하게 되면 효과음이 나도록 하기 위해서 SoundPool을 이용해서 구현하였습니다. 간단한 거니까 당연히 되겠지하며 테스트를 했는데, 효과음이 나지 않았습니다.


확인을 해보니 아래와 같은 문제가 있었습니다.


현상

아래와 같은 코드로 SoundPool을 사용하였으나, 제대로 효과음이 나지 않음.

디버깅으로 breakpoint를 걸어 한줄씩 실행 시 효과음이 발생함.

  
    public void playAnswerClickSound(Context context, int soundRes) {
        SoundPool soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0 );
        int sound =  soundPool.load(context, soundRes, 1);
        soundPool.play(sound,1,1,1,0,1);
    }


원인

Soundpool의 play 호출 시에 아직 raw 데이터가 load 되지 않아 발생.


해결방법

1.  API 레벨 8부터 추가된 setOnLoadCompleteListener 를 이용하는 방법

    setOnLoadCompleteListener 에 리스너를 등록해 load가 완료되는 시점에 play를 호출하는 방법이 있습니다.


2.  for, while 반복문과 sleep을 적절히 이용해 정상리턴(0) 가 나올 때까지 딜레이를 주는 방법


3. static을 이용해 호출 시점보다 이전에 resource data를 load 해두는 방법


저는 3번째 방법을 사용했습니다.

아래와 같이 싱글턴으로 효과음 호출 클래스(AnswerClickSound)를 만들고, 낱말 카드게임으로 들어가는 메뉴에서 getInstance() 하여 load 되도록 하고, 실제로 효과음이 play 되어야 하는 곳에서는 AnswerClickSoud.getInstance(context).playWrongAnswerSound() 를 호출하여 play만 하도록 하였습니다.


  
public class AnswerClickSound {

    private static AnswerClickSound mAnsewerClickSound;
    private int mRightAnswerSound;
    private int mWrongAnswerSound;
    private SoundPool mSoundPool;

    private AnswerClickSound(Context context) {
        mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0 );
        mRightAnswerSound =  mSoundPool.load(context, R.raw.ok_sound, 1);
        mWrongAnswerSound =  mSoundPool.load(context, R.raw.fail_sound, 1);
    }

    public static AnswerClickSound getInstance(Context context) {
        if(mAnsewerClickSound == null)
            mAnsewerClickSound = new AnswerClickSound(context);

        return mAnsewerClickSound;
    }

    public void playWrongAnswerSound() {
        mSoundPool.play(mWrongAnswerSound,1,1,1,0,1);
    }

    public void playRightAnswerSound() {
        mSoundPool.play(mRightAnswerSound,1,1,1,0,1);
    }

}   




혹시, soundpool 을 사용하였는데, 효과음이 나지 않는 분들이 있다면 이 글을 참조하셔서 데이터 load의 딜레이도 확인 한번 해 보시길 바랍니다.