読者です 読者をやめる 読者になる 読者になる

むずかしいことはわかりません

いろいろ書いてるみたいな

表示優先作るつもりが…SoundPoolの話

表示の話はどこへやら。なぜか、音の方を先に実装してみたりして。
現状のソース。

import java.io.IOException;
import java.util.HashMap;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;

public class SoundEffect {
	public static final int SP_MAX_CHANNELS = 5;

	public static MediaPlayer mp = null;
	public static SoundPool   sp = null;
	public HashMap<Integer,Integer> spMap;
	public HashMap<Integer,Integer> bgmMap;

	private Context spContext;
	private static boolean loopBGM;

	public SoundEffect(Context context) {
		spContext = context;

		sp = new SoundPool (SP_MAX_CHANNELS + 20, AudioManager.STREAM_MUSIC, 100 );
		mp = null;
		spMap = new HashMap<Integer, Integer>();
	}

	public void loadSoundData ( int soundNo, int resourceId ) {
		if ( sp != null ) {
			spMap.put(soundNo, sp.load(spContext, resourceId, 1));

			Game1.sendLog("SoundEffect", "sp loaded SoundID:"+spMap.get(soundNo));
		}
	}

	public void playSound ( int soundNo) {
		AudioManager mgr    = (AudioManager)spContext.getSystemService(Context.AUDIO_SERVICE);
		float currentVolume = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
		float maxVolume     = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
		float localVolume   = currentVolume / maxVolume;

		Game1.sendLog("SoundEffect", "currentVolume:"+currentVolume);
		Game1.sendLog("SoundEffect", "maxVolume:"+maxVolume);
		Game1.sendLog("SoundEffect", "localVolume:"+localVolume);

		sp.play(spMap.get(soundNo), localVolume, localVolume, 1, 0, 1.0f);
	}

	public void playBGM ( int resourceId, boolean flag ) {
		if ( mp != null ) {
			mp.stop();
			mp.reset();
		}

		mp = MediaPlayer.create(spContext, resourceId);
		mp.setLooping(loopBGM = flag);

		try {
			mp.prepare();
		} catch (IllegalStateException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
		mp.start();
	}

	public static void pauseBGM() {
		Game1.sendLog("SoundEffect", "pauseBGM");
		if ( mp != null && mp.isPlaying() ) {
			mp.pause();
			Game1.sendLog("SoundEffect", "BGM stop");
		}
	}

	public static void resumeBGM() {
		Game1.sendLog("SoundEffect", "resumeBGM");
		if ( mp != null && loopBGM == true ) {
			mp.start();
			Game1.sendLog("SoundEffect", "BGM restart");
		}
	}
}

SoundPoolを使えばいいじゃん。っていう話は

Playing sound FX for a game : http://www.androidsnippets.org/snippets/8/
[android-developers] Trouble with SoundPool:
http://www.mail-archive.com/android-developers@googlegroups.com/msg11858.html

なんかがぐぐると出てくるのでその辺参考になる記事とかトラブルに関する情報も出てるんで見てもらえば。

この関数でもloadSoundDataした直後にplaySoundすると「Sound 1 not READY」みたいなエラーは出てたんでその辺のタイミングは調べる必要があります。

一時停止、再開の処理を追加しといてやれば、電話機用としてはいいかなーって考えてそこらへん追加しときました。
この部分であと必要になるとすれば、

  • ボリューム処理
    • 別途、SEとBGMのボリュームを設定できるようにする
    • ループ関連の処理をイベントで処理するとか。
  • 切り替え、停止処理

この辺ですかね。今はバチッと止めて、すぐに次再生になってるので。