1

Android Soundpoolクラスはそのシンプルさが気に入っており、アプリで使用している標準のオーディオファイルでうまく機能します。ここで、SDカードのオーディオファイルを指定することで、ユーザーが特定のサウンドを指定できるようにしたいと思います。残念ながら、サウンドプールの制限に遭遇しました。サウンドファイルが大きすぎると、

AudioFlingerはトラックを作成できませんでした。ステータス:-12

応答。MediaPlayerの複雑さに再び入る前に、まだMediaPlayerに切り替える必要があるようです。Androidで利用できるオーディオライブラリがあるかどうかを尋ねたかったのですが、

  • さまざまなサウンドを再生するためのSoundpoolのシンプルさを備えています
  • ファイルのサイズに関してSoundpoolの制限はありません。

どうもありがとうございます。

マーティン

4

2 に答える 2

2

今のところ、MediaPlayerクラスで追加されたオーディオを再生する非常に単純なAudioPoolクラスを思いつきました。この実装は確かに成熟していませんが、少なくともこれに簡単にアプローチできる方法がいくつかわかるので、共有しようと思いました。このクラスで問題が発生した場合は、お知らせください。

使用法:

 AudioPool ap = new AudioPool();

 File root = Environment.getExternalStorageDirectory() ;

 int id1 = ap.addAudio(root + "/gong1.mp3");
 int id2 = ap.addAudio(root + "/gong2.mp3");
 int id3 = ap.addAudio(root + "/gong3.mp3"); 

 ap.playAudio(id1);
 ap.playAudio(id3);
 ap.playAudio(id3);
 ap.playAudio(id2);

続いてgong1->gong3->gong3->gong1を再生します。これは基本的に私が必要としているものなので、ここに残しておきます...

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.util.Log;

public class AudioPool {

static String TAG = "AudioPool";

MediaPlayer mPlayer;

int mAudioCounter;

int mCurrentId;

HashMap<Integer, String> mAudioMap;

LinkedList<Integer> mAudioQueue;

public AudioPool() {

    mAudioMap = new HashMap<Integer, String>();
    mAudioQueue = new LinkedList<Integer>();
    mAudioCounter = 0;

}

public int addAudio(String path) {
    Log.d(TAG, "adding audio " + path + " to the pool");

    if (mAudioMap.containsValue(path)) {
        return getAudioKey(path);
    }
    mAudioCounter++;
    mAudioMap.put(mAudioCounter, path);
    return mAudioCounter;
}

public boolean playAudio(int id) {

    if (mAudioMap.containsKey(id) == false) {
        return false;
    }

    if (mPlayer == null) {
        setupPlayer();
    }

    if (mPlayer.isPlaying() == false) {
        return prepareAndPlayAudioNow(id);
    } else {
        Log.d(TAG, "adding audio " + id + " to the audio queue");

        mAudioQueue.add(id);
    }
    return true;
}

public Integer[] getAudioIds() {
    return (Integer[]) mAudioMap.keySet().toArray(
            new Integer[mAudioMap.keySet().size()]);
}

public void releaseAudioPlayer() {
    if (mPlayer != null) {
        mPlayer.release();
        mPlayer = null;
    }
}


private boolean prepareAndPlayAudioNow(int id) {
    mCurrentId = id;
    try {
        Log.d(TAG, "playing audio " + id + " now");
        mPlayer.reset();
        mPlayer.setDataSource(mAudioMap.get(id));
        mPlayer.prepare();
        mPlayer.start();
        return true;
    } catch (Exception e) {
        Log.d(TAG, "problems playing audio " + e.getMessage());
        return false;
    }
}

private boolean playAudioAgainNow() {
    try {
        mPlayer.seekTo(0);
        mPlayer.start();
        return true;
    } catch (Exception e) {
        Log.d(TAG, "problems playing audio");
        return false;
    }
}

private void setupPlayer() {
    mPlayer = new MediaPlayer();
    mPlayer.setOnCompletionListener(new OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            audioDone();
        }
    });
}

private void audioDone() {

    if (mAudioQueue.size() > 0) {
        Log.d(TAG, mAudioQueue.size() + " audios in queue");
        int nextId = mAudioQueue.removeFirst();

        if (mCurrentId == nextId) {
            playAudioAgainNow();
        } else {
            prepareAndPlayAudioNow(nextId);
        }

    } else {
        releaseAudioPlayer();
    }
}

private int getAudioKey(String path) {
    for (Map.Entry<Integer, String> map : mAudioMap.entrySet()) {
        if (map.getValue().compareTo(path) == 0) {
            return map.getKey();
        }
    }
    return -1;
}

}
于 2012-10-09T11:39:26.953 に答える
0

解決策を提供してくれたdorjeduckに感謝しますが、彼のクラスはに基づいておりMediaPlayer、待ち時間が非常に長くなっています。どういう意味ですか?それはあなたがこれらを呼ぶときそれを意味します:

mPlayer.prepare();
mPlayer.start();

実際に音が聞こえると、遅延が非常に目立ちます。たとえば、あるトラックを再生してすぐに別のトラックを再生する必要がある場合、ハイエンドのハードウェアでも遅延が発生します。

再生する前にすべてのバイトをメモリにロードし、AudioTrackそのサウンドバイトを再生するために使用するソリューション。

ボンネットの下SoundPoolCompatで使用するものを書きました。AudioTrackカスタムを渡すことができbufferSize、そのバッファ内のすべてのデータがメモリにロードされ、SoundPoolのように小さなレイテンシで再生されます。それを超えるすべてのデータはbufferSizeオンデマンドでロードされます(これにより、と同様にレイテンシが追加されますMediaPlayer)。ApiSoundPoolはと非常によく似ており、Uriからサウンドをロードする機能(gdriveなど)も追加されています。そして、playOnce方法があります、ファイルが再生された後にすべてのリソースがアンロードされます。

implementation 'com.olekdia:sound-pool:3.0.2'

https://gitlab.com/olekdia/common/libraries/sound-pool

于 2019-11-12T07:50:58.280 に答える