SoundPool使用上の注意点
SoundPoolはAndroid APIに含まれる音声再生ライブラリのひとつで、ファイルをロード時にデコードしておくので、再生時にほとんど遅延が生じないため、効果音の再生などに向いている。
典型的な使い方
onCreate()などの初期化処理でファイルをload()しておき、効果音を鳴らしたいイベントが発生したときにplay()する。
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); context = this.getApplicationContext(); soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0); soundIds = new int[soundResouces.length]; for (int i=0; i<soundResouces.length; i++) { soundIds[i] = soundPool.load(context, soundResouces[i], 1); } playButton = (Button)findViewById(R.id.PlayButton); playButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { if (index >= soundIds.length) { index = 0; } Log.v(TAG, "index = " + index); soundPool.play(soundIds[index++], 1.0f, 1.0f, 1, 0, 1); } }); }
使用上の注意
デコードに時間がかかる
load()は非同期ですぐに返ってくるが、デコードがネイティブのスレッドで動作している。
デコードが終わったかどうか分からないのですぐload()直後にplay()を呼ぶと、デコードが終わってなく再生されない時がある
public void onClick(View v) { int soundId = soundPool.load(context, R.raw.bashi2, 1); soundPool.play(soundId, 1.0f, 1.0f, 1, 0, 1); }
再生されなかった場合、LogCatにwarningがでる。
WARN/SoundPool(32232): sample 11 not READY
API Level 8からはロードの終了通知を受け取れるようになった。
public void setOnLoadCompleteListener (SoundPool.OnLoadCompleteListener listener)
256個の壁
load()で返ってくるidは0からインクリメントされていくが、ネイティブでのメモリ管理領域の都合上idの数は256個まで。257個めをload()しようとするとエラーになる。
ERROR/SoundPool(2693): Unable to load sample: (null)
unload()してもload()で取得できるidの再利用はされない。idをクリアするには
soundPool.release()
をして一度全部まっさらな状態にするしかない。
10秒の壁
SoundPoolで再生出来るのは10秒までっぽい。
HW依存のような気もするが、NexusOne/GDD/Emulatorのどれでも10秒以上だと途切れてしまうのでSW的な制限があるのかもしれない。
(Thank @tomorrowkey @hyoromo)
ネイティブヒープの圧迫
load()された音声データはデコードされた状態でメモリ上に保存されるので、メモリをかなり消費する。
しかもjavaのヒープではなく、ネイティブのヒープとられるので、onLowMemory()が来たりせずに固まったり、落ちたりする。
大きいファイルをload()しようとすると
ERROR/AudioCache(51): Heap size overflow! req size: 1052672, max size: 1048576
というLogがでるが、java側には通知されず、処理もそのまま走ってる様子。
Native側のメモリの状況なんて端末スペックやシステムの状態で全然変わってくるので、できるだけload()するファイルの総量は小さくして、スペックの低い端末で動作確認するくらいしかなさそう。
動作確認したときのコードをgithubに上げました。