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

別の音楽アプリで音楽を聞きながら、ゲームをしたいの考察

 現在、ゲーム中の効果音に対して

  • AudioManager.STREAM_MUSIC

で音量の調整等をしているのですけど、
これだと

  • 音楽プレイヤーの音がゲームのボリュームに引きづられるで嬉しくない

みたいなクレームがPlayコメントに。。。。

 これにたいして相談した処

って形で教えてもらったのですが

をみると、

  1. AudioFocusを取得して自分以外の音を止める
  2. AudioFocusが取得されたのを検知して自分の音量を下げる

って利用方法みたいで、

 ようは

  • 電話がかかってきた時にゲームの音量を小さくする

等には使えると思うのですがそれ以外ではちょっと意味合い違うかなと*1

で調べていくと別の音量を使えばいいという形に到達してしまうみたい。



  • AudioManager. STREAM_MUSIC => AudioManager. STREAM_ALARM

を使う形で検討してみる


音量制御に関しては

int streamType = AudioManager.STREAM_ALARM;
audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
org_musicVol = audio.getStreamVolume(streamType);
set_musicVol = PrefUtil.get_int("set_musicVol", -1);
if (set_musicVol == -1) {
	// 最大音量の1/4を閾値にする
	int sep_musicVol = audio.getStreamMaxVolume(streamType) / 4;
	set_musicVol = org_musicVol;
	if (sep_musicVol > org_musicVol){
		//音が小さすぎたらとりあえず1/3ぐらいにセット
		set_musicVol = audio.getStreamMaxVolume(streamType) * / 3;
	}
}
//音量変更
audio.setStreamVolume(streamType, set_musicVol, 0);

//ボタン制御ボリュームを指定の音源に変える
setVolumeControlStream(streamType); 
@Override
protected void onDestroy() {
	if (audio == null) audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
	// 最新の値取得
	set_musicVol = audio.getStreamVolume(streamType);
	PrefUtil.put_int("set_musicVol", set_musicVol);
	//音量を戻す
	audio.setStreamVolume(streamType, org_musicVol, 0);

でいける感じ。



MediaPlayer)
MediaPlayerは上記の例の場合で*2

mp = MediaPlayer.create(this, R.raw.bgm);
mp.setAudioStreamType(AudioManager.STREAM_ALARM);//これを追加
mp.setLooping(true);
mp.start();

訂正追記)
実は MediaPlayer.create(Context,resID) が setAudioStreamTypeが動かない*3な状況が発覚したので再調査。

private MediaPlayer mp = null;
public void load_bgm(int resID, float volume, boolean loop_f) {
	reset_bgm();

	try {
		Uri uri = Uri.parse("android.resource://" + context.getPackageName() +"/" + resID);
		mp = new MediaPlayer();
		mp.setDataSource(context, uri);
		//mp = MediaPlayer.create(context, resID);
		mp.setVolume(volume, volume);
		mp.setLooping(loop_f);
		mp.setAudioStreamType(AudioManager.STREAM_ALARM); 
	} catch (Exception e) {
		LogUtil.error(TAG, "load_bgm", e);
	}
}

private void reset_bgm() {
	if (mp == null)return;
	try{
		mp.stop();
		mp.reset();
	} catch (Exception e) {
		LogUtil.error(TAG, "release_bgm", e);
	}
	mp = null;
}

な形にすればOK。

の話。

追記2)
 端末によりSD/ローカル にある音声ファイル がsetDataSourceに指定してもサイズで再生できない事があるらしい。

で対策として以下な話となる

  1. Android Audio Streaming | Ballard Hack
  2. android - Audio stream buffering - Stack Overflow

でも
一つ目は target 8以下ではduplicatedなんだよな。
二つ目は ローカルでSocket鯖を自前で作って疑似ストリーミング受信できる形にしてしまおうって話

あたりだと APIで回避されてたりするのかしら。。。(汗



SoundPool)

//soundPool = new SoundPool(SE_MAX, AudioManager.STREAM_MUSIC, 0);
//=>
soundPool = new SoundPool(SE_MAX, AudioManager.STREAM_ALARM, 0);

検索してると下記のような情報も出てくるけど

の記述の

AudioManager::setMode(AudioManager.MODE_IN_CALL);

で制御ってどこらへんに関わってくるのだろう?
うーん。奥が深い。

SonyAndroid Warkman SDK だと複数音に重低音エフェクトとか
かけられるらしいんだけど、ココらへんに関しても調べてみたいなーという感じです

の 外部Bluetoothスピーカ 等でも鳴らしてみたいけど

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

な対応は要るんだろうな−(汗
権限表示が要らないIOSがすごく羨ましい。。。*4

他には

が有るみたいですけど、単に効果音とかだと使わないかも。
音ゲーとか作るときなんでしょうか・・・・(汗

備考)
AudioTrackは正直使えないです。。

現場で使える〔逆引き+実践〕 Androidプログラミングテクニック

現場で使える〔逆引き+実践〕 Androidプログラミングテクニック

のサンプルを試してみたんだけど、空きメモリが少なくとも50MB以上無いと

audiotrack obtainbuffer() track disabled restarting
ってエラーが出てその音声に関しては作成できない=>音ならない状況な状況。

試しに差し替えてみたのは

のピアノ音声・・。うーんですわね。。(苦笑




TTSの話のメモ)
TTSも音源リソースの設定ができる。
これ2系だと audio.setStreamVolume で動いてる機種があって見落としてたんですが
4系後半だとTTS用の音源が分かれているようで明示的に指定しないと駄目。

	mTts.setSpeechRate(1.0f);// しゃべる速さ(遅い<=>速い)
	mTts.setPitch(1.0f);// 声の音程(低い<=>高い)
	HashMap<String, String> params = new HashMap<String, String>();
	params.put(TextToSpeech.Engine.KEY_PARAM_VOLUME, String.valueOf(1.0));
	params.put(TextToSpeech.Engine.KEY_PARAM_PAN, String.valueOf(0.0));
	params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_ALARM));//☆
	mTts.speak(ttsText, TextToSpeech.QUEUE_FLUSH, params);

みたいな形で☆のパラメータを明示的に追加。

の話



マナーモードの対応)
最近一部のマナーモードが設定できない機種で誤爆したのでメモ

	public boolean isCanPlaySnd() {
		if (audio == null) audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
		int mode = audio.getRingerMode();
		switch (mode) {
			case AudioManager.RINGER_MODE_SILENT:
			case AudioManager.RINGER_MODE_VIBRATE:
				//Xoom判定
		    		if( "MOTO".equals(Build.BRAND) && "MZ604".equals(Build.MODEL) ){
					int vol = audio.getStreamVolume(AudioManager.STREAM_ALARM); 
		    			if(vol>0)break;
		    		}
		    		//Nexus7判定
				if (Build.BRAND.equals("google") && Build.MODEL.equals("Nexus 7")) {
					int vol = audio.getStreamVolume(AudioManager.STREAM_ALARM); 
		    			if(vol>0)break;
		    		}
				
				// マナーモードなので何もしない
				boolean bPlugged = headsetStateReceiver.isPlugged();
				if (bPlugged) break; // イヤフォンの場合は鳴らす
				return false;
				// break;
			default:
				break;
		}
		return true;
	}

ようは
マナーモードが設定できない機種 で
AudioManager.STREAM_MUSIC で 0に設定されてると
getRingerMode()で AudioManager.RINGER_MODE_SILENT が飛んでくるというアホ仕様。
普通にマナーモードが設定できる機種は問題ないみたい。うーん。なんだかね。。。(汗





波形とか表示のメモ)



参考)

*1:対応しておいたほうが確かにいいけど、基本効果音しか使ってないので、うーんな面も確かにある

*2:実はこれは動いていなかった><

*3:タイミングによりエラーに成ってBGM自体もならなく鳴ることも<汗

*4:初期リリース時の権限以降は変えるとユーザクレームが来るとのこと=>めんどい らしい