SoundPoolで効果音を鳴らす


MediaPlayerで音楽を再生するという記事がありましたが、今回はSoundPoolを使った方法を説明します。

オーディオファイルを再生するという点ではMediaPlayerもSoundPoolも同じですが、SoundPoolの特徴として1つのインスタンスで複数の音声を再生することができます。また、先にメモリにロードしておいて音声を鳴らすので遅延が少ないことも特徴です。ゲームなどで、再生時間が短い効果音を再生するときに使います。

それでは続きで説明して行きます。

再生する音声ファイル

再生可能な形式はWAVE形式(リニアPCM)、oggです。MP3でも再生できる端末があるようですがこの2つの形式のどちら化にしていた方が無難です。(XperiaではMP3が再生できないという情報があります)

オーディオファイルはリソースからでもローカルファイルからでも読み込み可能です。リソースの場合はres/raw以下に配置します。

loadメソッド

音声を鳴らすにはまずオーディオファイルを読み込む必要があります。冒頭でも書いた通り、先に読み込んでおき、音声を鳴らすことになります。多くのファイルを読み込んでメモリが圧迫されないように注意する必要があります。

また、読み込みは非同期で行われるため、loadメソッド直後に再生しようとすると再生できない場合があります。loadメソッド自体はすぐに応答を返すので要注意です。

Android2.2(API8)からは読み込み完了を知る手段(setOnLoadCompleteListenerでリスナを登録)もあります。

それでは音声ファイルを読み込んでみましょう。
まずはSoundPoolインスタンスを生成します。
コンストラクタは下記の通りです。

SoundPool(int maxStreams, int streamType, int srcQuality)
  • maxStreams:プールする最大の数
  • streamType:Streamのタイプ(通常はSTREAM_MUSICを利用する)
  • srcQuality:サンプリングレートのクオリティ(デフォルトは0)

(サンプルでは1つのファイルしか読み込みませんが)ここでは5つまでファイルをプールできるようにします。

soundPool_ = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);

次に読み込み完了通知を受け取るためにsetOnLoadCompleteListenerでリスナを登録します。API8からのメソッドなので要注意です。Android2.2以前の場合は省略してください。もちろんAndroid2.2の場合でも不要であれば登録する必要ありません。
今回は読み込み完了時にToastを表示するだけですが、読み込み完了フラグを用意して、そのフラグを見て後続の処理を判断するという方法も有効だと思います。

       soundPool_.setOnLoadCompleteListener(new OnLoadCompleteListener() {
    	   @Override
    	   public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
    		   if (0 == status) {
    			   Toast.makeText(getApplicationContext(), "LoadComplete", Toast.LENGTH_LONG).show();
    		   }
    	   }
       });

そしてloadメソッドで読み込みます。

public int load (Context context, int resId, int priority)

第3引数のプライオリティは現在は利用されていないようですが、ドキュメントには将来の互換性のため1を指定するように記述されています。
戻り値にはIDが返ってくるのでメンバに保存しておきます。このIDを指定して音声を再生します。複数のオーディオファイルをプールする場合にはこのIDで識別することになります。

soundId_ = soundPool_.load(this, R.raw.sound, 1);

ローカルファイルの場合は

public int load (String path, int priority)

第1引数にパスを指定します。

再生

再生するときにはplayメソッドを使います。

public final int play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
  • sooundID:再生したいファイルをloadした時の戻り値
  • leftVolume,rightVolume:左右のスピーカーからの再生音量。(0.0〜1.0)
  • priority:プライオリティ(0が一番優先度が高い)
  • loop:ループ回数(-1の場合は無限にループ、0の場合はループしない)
  • rate:再生速度(0.5〜2.0:0.5倍から2倍の速度まで設定できる)

以下は音量は最大、ループせずに等倍速で再生させる指示です。

soundPool_.play(soundId_, 1.0F, 1.0F, 0, 0, 1.0F);

SoundPoolの解放

使い終わったらreleaseメソッドでSoundPoolを解放する必要があります。

soundPool_.release();

アプリケーションによっても異なりますがonResumeでインスタンスの生成&loadして、onPauseでreleaseすると間違いありません。

また、アプリケーションの一部でしか使わない音声などをずっとloadしたままにしておくのはメモリ管理上好ましくありません。その場合はsoundIDを指定してunLoadすることができます。必要に応じて利用してください。

public final boolean unload (int soundID)
2 Comments