ゲーム全体で使用したい.wavファイルがあります。現在、ゲームの各アクティビティのonCreate()
にサウンドを読み込んでいます。
soundCount = soundpool.load(this,R.raw.count, 1);
アクティビティが開始されると、サウンドが再生されます。
soundpool.play(soundCount, 0.9f, 0.9f, 1, -1, 1f);
問題はときどきエラーが発生する"sample x not ready"
。ゲームの開始時に.wavファイルを一度ロードしてメモリに保持し、後でゲーム全体で使用することはできますか?または、サウンドの読み込みが完了するまで1〜2秒待つことはできますか?
SoundPool.setOnLoadCompleteListener
経由でリスナーを追加して、終了するまで待つ必要があります。
私のプロジェクトはAndroid 1.5と互換性があり、setOnLoadCompleteListenerを使用できなかったため、サウンドの再生を遅延させることを解決しました。私のソースコードは次のとおりです。
playSound_Delayed(soundId, 100);
//(..)
private void playSound_Delayed (final int soundId, final long millisec) {
// TIMER
final Handler mHandler = new Handler();
final Runnable mDelayedTimeTask = new Runnable() {
int counter = 0;
public void run() {
counter++;
if (counter == 1) {
boolean ret = mHandler.postDelayed(this, millisec);
if (ret==false) Log.w("playSound_Delayed", "mHandler.postAtTime FAILED!");
} else {
playSound(soundId);
}
}
};
mDelayedTimeTask.run();
}
可能な場合はsetOnLoadCompleteListenerを使用する必要があります。そうでない場合は、whileループを「play」への呼び出しにラップします。何かのようなもの:
int waitLimit = 1000;
int waitCounter = 0;
int throttle = 10;
while(soundPool.play(soundId, 1.f, 1.f, 1, 0, 1.f) == 0 && waitCounter < waitLimit)
{waitCounter++; SystemClock.sleep(throttle);}
これにより、10ms間隔で「再生」が1000回再試行されます。もちろん、これは非UIスレッドで実行する必要があり、まだ理想的ではありません。しかし、任意の時間待機してプールの準備ができることを期待するよりも少し強力かもしれません。
これは間違いなくあなたのために働くでしょう!
public void playWavFile() {
Thread streamThread = new Thread(new Runnable() {
@Override
public void run() {
SoundPool soundPool;
final int wav;
String path = "/mnt/sdcard/AudioRecorder/record.wav";
soundPool = new SoundPool(5,AudioManager.STREAM_MUSIC, 0);
wav = soundPool.load(path, 1);
soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
// TODO Auto-generated method stub
soundPool.play(wav,100, 100, 0, 0, 1f);
}
});
}
});
streamThread.start();
}
SoundPoolライブラリはMediaPlayerサービスを使用して、オーディオを生の16ビットPCMモノラルまたはステレオストリームにデコードします。これは、単にStreamの準備と呼ばれ、サウンドファイルのサイズによっては時間がかかります。そして、そのプロセスが終了する前にサウンドを再生しようとすると、「sample x not ready」エラーが発生します。
これには2つの解決策があります
そして、それを再生します。この条件に例外はありません。または、アプリケーションは、try-catchなしではクラッシュしません。
private SoundPool soundPool;
private int my_sound;
boolean loaded = false;
//コンストラクタ内
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
my_sound = soundPool.load(this, R.raw.blast_sound, 1);
soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
public void onLoadComplete(SoundPool soundPool, int sampleId,int status) {
loaded = true;
}
});
//次に、サウンドを再生する場所に次のように入力します
if (loaded) {
soundPool.play(my_sound, 0.9f, 0.9f, 1, 0, 1f);
}
単純なdo-while cicleの問題で解決しました。 play()メソッドは、成功した場合はゼロ以外のstreamIDを返し、失敗した場合はゼロを返します。したがって、戻り値を確認するだけで十分です。
int streamID = -1;
do {
streamID = soundPool.play(soundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
} while(streamID==0);
これはクレイジーに聞こえますが、すぐにサウンドを再生しないでください。アプリに数秒かけてSoundPoolを初期化します。私のアプリでは、これがまさに問題でした。約3秒の偽の「読み込み」画面を追加したところ、すべてが機能しました。 (サウンドをプリロードする必要すらありませんでした。)