14

私は Android でゲームを開発していますが、非常に厄介で見つけにくいバグに遭遇しました。問題は、 を使用SoundPoolしてサウンドを再生しているときに、実際に再生中のサウンドをループできることです。この場合、問題は「実行中のステップ」の音です。400msこのサウンドは、主人公が走っているときに非常に高速かつ継続的に (約) 実行されます。

Samsung SII などの通常の (それほど強力ではない) デバイスでサウンドを再生すると、サウンドは毎回再生され500msますが、別のデバイス (たとえば、Samsung SIV、Samsung SIII) でまったく同じコードを実行すると、サウンドが再生されます。 2 倍、さらには 3 倍速くなります。

デバイスのハードウェアスペックが強力なほど、再生が速くなるようです。一部のデバイスでは、非常に高速に再生され、1 つの連続したサウンドがほとんど聞こえます。サウンド再生間の時間間隔に特定の比率を設定する手法を探していましたが、適切に機能せず、問題が残ります。SoundPoolMediaPlayer、または Android のその他のサウンド制御 API を使用して、それを修正する方法を知っている人はいますか?

4

5 に答える 5

1

AudioTrackを使用して、PCM データの連続ストリームを再生することができます。これは、サウンド間の間隔を確認できるストリームを渡すためです。マイナス面は、最初にサウンドを開始するときに少し遅れる可能性がありますが、それは最小バッファサイズに依存し、Android のバージョンとデバイスに依存すると思います。私のgalaxy s2 android 4.1では、約20msでした。
これがオプションになると思われる場合は、いくつかのコードを投稿できます

于 2013-09-25T17:37:09.427 に答える
0

サウンドなどを使用するアプリの開発には、多くの問題がありました。バグの影響があるため、SoundPool を使用することはお勧めしません。また、SoundPool を使用したサウンドのループは、4.3 以降のデバイスでは機能しないことに注意してください。AOSP - Issue tracker で、この未解決の問題を参照してください。解決策は、ネイティブになり、OpenSL ES o 同様のライブラリを使用することだと思います。

于 2013-12-30T19:03:22.233 に答える
0

問題が個別のサウンド間の間隔を制御することである場合、これを行う最も簡単な方法はハンドラーを使用することです。

基本的に、非同期プロセスであるサウンドの再生を開始します。次に、ハンドラーを使用してメッセージをスケジュールし、将来のある時点で次のサウンドを再生します。正しく設定するには試行錯誤が必要ですが、すべてのデバイスで前のサウンドの後に同じ間隔でサウンドが開始されることが保証されます。

ここに、私が話していることを説明するためのコードをいくつか示します。

使用できるハンドラーの実装を次に示します。

    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 を記述できます。

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 は、サウンド ファイルのリソース ID と持続時間を持つ単純なクラスにすることもできます。キャラクターが動いている間もサウンドを再生し続けたい場合は、次のようにすることができます。

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

または、playNextSound を変更して、同じサウンドを継続的に再生することもできます。私はこのように書かれており、異なるサウンドを順番に再生できるようになっています。

于 2013-10-16T19:26:28.030 に答える
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);
}
于 2013-10-16T18:42:19.980 に答える