Образец Soundpool не готов
У меня есть файл.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 секунды, пока закончится загрузка звука?
8 ответов
Вам нужно будет дождаться его завершения, добавив слушателя через 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);}
это будет повторять "воспроизведение" 1000 раз с интервалом 10 мс. это, конечно, должно выполняться в потоке, не являющемся пользовательским интерфейсом, и все еще не является идеальным. но, может быть, немного сильнее, чем ждать произвольное время и ожидать готовности бассейна.
Я решил проблему с простым делом пока. Метод play() возвращает ненулевой streamID в случае успеха, ноль в случае неудачи. Итак, достаточно проверить возвращаемое значение.
int streamID = -1;
do {
streamID = soundPool.play(soundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
} while(streamID==0);
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);
}
Это будет работать для вас определенно!
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".
Есть два решения для этого
- реализовать setOnLoadCompleteListener или
- ждать произвольное количество времени, чтобы подготовка закончилась
и затем воспроизведите его. Обратите внимание, что для этого условия не существует исключений, или приложение не падает без каких-либо try-catch
Это звучит безумно, но не играйте сразу. Дайте приложению пару секунд для инициализации SoundPool. В моем приложении это была именно проблема; Я добавил фальшивый "загрузочный" экран ~3 секунды, и тогда все заработало. (Мне даже не нужно было предварительно загружать звуки.)