2013-09-25 4 views
13

Android에서 게임을 개발 중이며 매우 귀찮고 찾기 힘든 버그를 발견했습니다. 문제는 SoundPool을 사용하여 사운드를 재생할 때 실제로 연주하는 사운드를 반복 할 수 있다는 것입니다. 이 경우 문제는 "실행 단계"소리입니다. 이 소리는 주인공이 실행 중일 때 아주 빨리 그리고 지속적으로 (약 400ms 주위에) 실행됩니다.Android의 여러 기기에서 정확한 시간에 소리를 재생하는 방법

이제 일반 (너무 강력하지 않은) 기기에서 사운드를 재생할 때. Samsung SII의 사운드는 500ms 번으로 재생됩니다. 그러나 다른 기기 (삼성 SIV, 삼성 SIII)에서 동일한 코드를 실행하면 소리가 두 배 또는 세 배 빨라집니다.

장치 하드웨어 사양이 강력 할수록 더 빨리 재생됩니다. 일부 장치에서는 매우 빠른 속도로 재생되므로 단단한 연속 사운드를 거의들을 수 있습니다. 나는 사운드 재생 사이의 특정 시간대에 특정 비율을 설정하는 기술을 찾고 있었지만 제대로 작동하지 않으며 문제가 남아 있습니다. 누구든지 SoundPool, MediaPlayer 또는 Android의 다른 소리 제어 API를 사용하여 문제를 해결하는 방법을 알고 있습니까?

+0

해결책을 찾았습니까? 그렇다면 공유하십시오! – lelloman

+0

질문을 +1하면 어쩌면 더 많은 사람들이 그것에주의를 기울일 것입니다 ... –

+1

두 번 이상 upvote 수 없습니다 – lelloman

답변

0

AudioTrack을 사용하면 연속적인 PCM 스트림을 재생할 수 있습니다. 소리가 들리는 간격에 대해 확신 할 수있는 스트림을 전달하기 때문입니다. 단점은 사운드를 처음 시작할 때 약간의 지연이 될 수 있지만 최소 버퍼 크기에 달려 있으며 안드로이드 버전과 장치에 달려 있다고 생각합니다. 내 은하 s2 android 4.1에서 약 20ms였습니다.
이이 옵션이 될 수 있다고 생각하면 나는 몇 가지 코드

1

에게 단지 루프 또는 발자취 같은 뭔가 일정한 간격을 사용의 문제점을 게시 할 수 있습니다 당신은 소리와 영상의 가능한 디커플링을 가지고있다. 사운드가 지연되거나 속도가 빨라지거나 영상이 지연되거나 속도가 빨라지면 지연을 동적으로 자동 조정해야합니다. 이미이 문제가 이미 있습니다.

더 좋은 해결책은 소리를내는 소리 (이 경우 발을 내려 놓음)를 트리거해야하는 정확한 이벤트에 트리거를 놓는 것입니다. 그러면 사운드가 재생됩니다. 즉, 여러 발자국 소리와 같은 여러 사운드 소스가있는 경우 올바른 간격으로 사운드를 수동으로 시작할 필요가 없습니다.

+0

이 방법은 큰 차이가 있습니다. 사건은 내가 소리를 내고 싶을 때마다 하나의 사건으로 계산 될 수 있습니다. 예를 들어, 자동 건 (authomatic gun)은 트리거하기위한 하나의 사건이며, 소리는 특정 시간 간격으로 반복되어야합니다 ... –

+0

자동 총소리가 들리면 루프가 더 좋습니다. 자동 러너 게임이나 Myst 스타일의 어드벤처 게임을 제외하고는 루핑 사운드가 좋지 않습니다. 사운드를 항상 발자국과 결합시키기 때문에이를 발자국과 연결하는 것이 좋습니다. 나는 그것을 항상 반복한다고 말하지 않았다. – Nzall

0

Galaxy Nexus 및 Nexus S에서 문제를 재현 할 수없는 것 같습니다. 해결 되었습니까? 아니면 당신이 다르게 무슨 일을하는지 보여줄 수 : 문제는 이산 소리 사이의 간격을 제어 할 것입니다

SoundPool soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100); 
Integer sound1 = soundPool.load(this, R.raw.file1, 1); 
Integer sound2 = soundPool.load(this, R.raw.file2, 1); 
playSound(sound1); 

public void playSound(int sound) { 
    AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 
    float volume = mgr.getStreamVolume(AudioManager.STREAM_MUSIC) 
      /mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 
    soundPool.play(sound, volume, volume, 1, -1, 1.0f); 
} 
+0

아무것도 아니에요, 이전 장치로 테스트 해 보겠습니다. 한 사운드와 다음 사운드 사이의 간격에 큰 차이가 있음을 알게 될 것입니다. 서로간에 더 큰 지연이있을 것입니다. 정확히 동일한 코드입니다. ... –

0

경우,이 작업을 수행하는 가장 쉬운 방법은 핸들러입니다.

기본적으로 비동기 프로세스 인 사운드 재생을 시작합니다. 그런 다음 핸들러를 사용하여 앞으로 언젠가는 다음 사운드를 재생하도록 메시지를 예약합니다. 시행 착오를 거쳐야 정상적으로 작동하지만, 모든 장치에서 이전 사운드가 출력 된 후 동일한 간격으로 사운드가 시작됩니다.

여기 내가 설명하는 것을 설명하는 코드가 있습니다.

private void playNextSound() { 
    if (mRunning) { 
     // Get the first item 
     SoundSequenceItem item = currentSequence.getNextSequenceItem(); 
     if (item == null) { 
      Message msg = handler.obtainMessage(SEQUENCE_COMPLETE_MSG); 
      handler.sendMessage(msg); 
      return; 
     } 
     // Play the sound 
     int iSoundResId = item.getSoundResId(); 
     if (iSoundResId != -1) { 
      player.playSoundNow(soundResId); 
     } 

     // schedule a message to advance to next item after duration 
     Message msg = handler.obtainMessage(NEXT_ITEM_MSG); 
     handler.sendMessageDelayed(msg, item.getDuration()); 
    } 
} 

하고 SoundSequenceItem 그냥 사운드 파일 자원을 가진 간단한 클래스가 될 수 :

handler = new Handler() { 

     /* (non-Javadoc) 
     * @see android.os.Handler#handleMessage(android.os.Message) 
     */ 
     @Override 
     public void handleMessage(Message msg) { 
      if (msg.what == NEXT_ITEM_MSG) { 
       playNextSound(); 
      } 
      else if (msg.what == SEQUENCE_COMPLETE_MSG) { 
       // notify a listener 
       listener.onSoundComplete() 
      } 
     } 
    }; 

그런 다음이 같은 playNextSound를 작성할 수 : 여기

당신이 사용할 수있는 핸들러 구현 이드와 기간.

public void onSoundComplete() { 
    if (character.isRunning()) { 
     currentSequence.addSequenceItem(new SoundSequenceItem(R.id.footsteps,500); 
     playNextSound(); 
    } 
} 

을 또는 당신은 계속 같은 소리를 재생하는 playNextSound을 수정할 수 있습니다 : 당신이 소리를 계속 연주 할 경우 문자는이 같은 일을 할 수있는 이동된다. 광산은 다른 소리를 순차적으로 연주 할 수 있도록이 방법으로 작성되었습니다.

+0

나는 수작업으로 ThreadPools/Scheduler/Monitor 및 심지어 핸들러와 같은 여러 가지 방법으로 생각해 왔지만 수동으로 처리하면 문제가되지 않을 것이라고 원어민 전화를 찾고 있습니다. API에있는 기존 항목을 찾고 있습니다. –

0

소리와 같은 것을 사용하는 앱을 개발하는 데 많은 문제가있었습니다. SoundPool은 버그에 영향을 받기 때문에 SoundPool을 사용하지 말고 SoundPool로 반복되는 사운드는 4.3 이상의 장치에서는 작동하지 않습니다. this open issue, at AOSP - Issue tracker을 참조하십시오. 나는이 솔루션이 네이티브로 돌아가서 OpenSL ES와 유사한 라이브러리를 사용한다고 생각합니다.