2013-09-25 15 views
13

Zajmuję się tworzeniem gier na Androida i natknąłem się na bardzo denerwujący, trudny do znalezienia błąd. Problem polega na tym, że kiedy używasz SoundPool do odtwarzania twoich dźwięków, możesz zapętlić dowolny dźwięk, który grasz. W tym przypadku problemem jest dźwięk "uruchomionych kroków"; ten dźwięk jest wykonywany dość szybko i stale (około 400ms), gdy główna postać jest uruchomiona.Jak odtwarzać dźwięki w określonych odstępach czasu na różnych urządzeniach w Androidzie

Teraz podczas odtwarzania dźwięku na zwykłym (nie tak silnym) urządzeniu, np. Samsung SII, dźwięk odtwarzany jest co 500ms - jeśli jednak uruchomię ten sam kod na innym urządzeniu (powiedzmy Samsung SIV, Samsung SIII), dźwięk będzie odtwarzany dwa razy lub nawet trzy razy szybciej.

Wygląda na to, że im mocniejsze są specyfikacje sprzętu, tym szybciej gra. Na niektórych urządzeniach gra tak szybko, że niemal słyszysz jeden ciągły ciągły dźwięk. Szukałem technik, które wyznaczyłyby określony stosunek w okresie czasu pomiędzy odgrywaniem dźwięku, ale nie działa on prawidłowo, a problem pozostaje. Czy ktoś wie, jak to naprawić, korzystając z SoundPool, MediaPlayer lub innego kontrolera dźwięku kontrolującego Androida?

+0

znalazłeś rozwiązanie? jeśli tak, proszę podziel się nim !! – lelloman

+0

Ciągle go nie szukam, jeśli dajesz +1 temu zadaniu, może więcej ludzi będzie na to zwracać uwagę ... –

+1

Nie mogę przegłosować więcej niż raz – lelloman

Odpowiedz

0

Możesz użyć AudioTrack, aby odtwarzać ciągły strumień danych PCM, ponieważ możesz przekazać strumień, aby mieć pewność co do odstępu między dźwiękami. wadą może być niewielkie opóźnienie przy pierwszym uruchomieniu dźwięku, ale zależy to od minimalnego rozmiaru bufora, i to zależy, jak sądzę, od wersji Android i urządzenia. Na mojej galaxy s2 android 4.1 było około 20 ms.
Jeśli uważasz, że to może być opcja, mogę opublikować kod:

1

Problem z zapętleniem lub regularnym interwałem dla czegoś podobnego do kroków polega na możliwym oddzieleniu dźwięku i wizualizacji. Jeśli Twój dźwięk ulegnie opóźnieniu lub przyspieszy, albo efekty wizualne zostaną opóźnione lub przyspieszone, będziesz musiał dostosować się do tego opóźnienia dynamicznie i automatycznie. Masz już tę kwestię tutaj:

Lepszym rozwiązaniem byłoby umieszczenie spustu na dokładnym zdarzeniu, które powinno wyzwalać dźwięk (w tym przypadku, gdy stopa jest opuszczona), które następnie odtwarza dźwięk. Oznacza to również, że jeśli masz wiele źródeł dźwięku (jak wiele kroków), nie musisz ręcznie uruchamiać dźwięku z odpowiednim interwałem.

+0

To podejście ma ogromną lukę, ponieważ nie wszystkie Przypadki mogą się liczyć z jednym zdarzeniem za każdym razem, gdy chcę, aby dźwięk "np. automatyczna broń" był pojedynczym zdarzeniem, które ma być wyzwalane, a dźwięk musi zapętlać się w określonych odstępach czasu, aż palec zostanie zwolniony z pistoletu ... –

+0

dostałem automatyczny dźwięk pistoletu, pętla jest lepsza, tak, ale jeśli nie wykonujesz gry autorunner lub przygodowej gry w stylu Myst, pętla dźwięku to zły pomysł. Lepiej połączyć go ze śladami, ponieważ w ten sposób dźwięk jest zawsze sprzężony ze śladami. Nie mówiłem, żeby cały czas pętać. – Nzall

0

Nie mogę skopiować problemu na Galaxy Nexus i Nexus S, czy to znaczy, że to naprawiłem? A może można pokazać, co robisz inaczej to:

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

Nic, robię dokładnie to, testuj starym urządzeniem, a zauważysz ogromną różnicę w przepaści między jednym dźwiękiem a następnym, będzie to miało większe opóźnienie między sobą, to dokładnie ten sam kod, który mam ... –

0

Jeśli problem jest to, że chcesz kontrolować odstęp pomiędzy dyskretnymi dźwiękami, najprostszym sposobem na to jest za pomocą uchwytu.

Zasadniczo rozpoczyna się odtwarzanie dźwięku, co jest procesem asynchronicznym. Następnie korzystasz z programu obsługi, aby zaplanować wiadomość, aby odtworzyć następny dźwięk w przyszłości. Wykonanie próby i błędu zajmie trochę czasu, ale będziesz mieć pewność, że dźwięk zacznie się w tym samym przedziale po poprzednim dźwięku na każdym urządzeniu.

Oto kod ilustrujący to, o czym mówię.

Oto implementacja obsługi można użyć:

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

Następnie można napisać playNextSound tak:

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

a SoundSequenceItem może być tylko prosta klasa, która posiada zasób plik dźwiękowy id i czas trwania. Jeśli chcesz zachować odtwarzanie dźwięku podczas postać porusza mógłby zrobić coś takiego:

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

Albo można modyfikować playNextSound stale odtwarzać ten sam dźwięk. Mój napisany jest w ten sposób, aby móc odtwarzać różne dźwięki w sekwencji.

+0

Pomyślałem na kilka sposobów, aby zrobić to ręcznie, jak ThreadPools/Scheduler/Monitor, a nawet obsługi, jednak szukam natywnego połączenia jako odpowiedzi, robienie tego ręcznie nie byłoby problemem jestem po prostu szukasz czegoś istniejącego w API –

0

Miałem wiele problemów z tworzeniem aplikacji, które używały dźwięków i tym podobnych. Nie sugerowałbym korzystania z SoundPool, ponieważ ma on wpływ na błędy, a także należy pamiętać, że zapętlanie dźwięków za pomocą SoundPool nie będzie działać na urządzeniach, które są 4.3 i wyższe, patrz this open issue, at AOSP - Issue tracker. Myślę, że rozwiązaniem jest natywność i korzystanie z OpenSL ES o podobnych bibliotekach.

Powiązane problemy