Hatena::Groupiphone-dev

Ni chicha, ni limona - 平均から抜けられない僕

2009-12-22

[Core Audio][AudioSession] スリープ中のオーディオの挙動について 02:09  [Core Audio][AudioSession] スリープ中のオーディオの挙動について - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [Core Audio][AudioSession] スリープ中のオーディオの挙動について - Ni chicha, ni limona - 平均から抜けられない僕  [Core Audio][AudioSession] スリープ中のオーディオの挙動について - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

拙作アプリMetronome PRO」のバージョンアップ版では「スリープ中もサウンドを鳴らせるようにする」という機能を追加する予定です。

ポケットに入れたままリズムを聴きたい、という要望に応えるためです。


そこでAudioSessionのkAudioSessionProperty_AudioCategoryに、従来は《kAudioSessionCategory_AmbientSound》を指定していたのを、スリープ中でもサウンドを再生できる《kAudioSessionCategory_MediaPlayback》に変更して、テストしてみました。

しかしこれだけだとスリープモードに入った途端、音がぶつ切りのようになってテンポもめちゃくちゃに揺れる現象が出るようになってしまいました。

自慢のテンポ精度も台無しです。


「うーんこれはなぜだろう?」と思って色々調べたところ、どうやらAudioSessionで入出力バッファの長さを指定していない場合、スリープモードの間はオーディオ処理の実行間隔が4倍になってしまうことが分かりました。


以下のソース:

	UInt32 size = sizeof(Float64);
	Float64 rate;
	AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &size, &rate);
	size = sizeof(Float32);
	Float32 curDuration,vol;
	AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &size, &curDuration);

	NSLog(@"rate:%f currentDuration:%f (->%f)\n", rate, curDuration, rate*curDuration);

を通常状態とスリープ状態とで出力してみると、

# 通常状態
hogehoge[XXX:XXX] rate:44100.000000 currentDuration:0.023220 (->1024.002)

#スリープ状態
hogehoge[XXX:XXX] rate:44100.000000 currentDuration: 0.092880 (->4095.999925)

というように、処理を行う間隔が4倍になっていました。これによってバッファがあふれてしまうのか、今回の現象である音がちぎれたりテンポが狂ったりする状況に陥っていたようです。

スリープ中まで同じ動作をさせていたら電池がすぐになくなってしまいますから、まあ妥当な動作だと思います。


けれども私は困ります。ということで対策を調べたら実は簡単で、アプリの中で《kAudioSessionProperty_PreferredHardwareSampleRate》を使い何かしらの値を設定するだけで良いことが分かりました。これによってスリープに入ったときも同じ実行間隔が維持されるようになります。

(言い換えると通常状態と同じ動作をしてくれるわけで、つまり普通のスリープ時より電池を食うことになりますので、むやみに使わないよう注意が必要かと思います)


以下はサンプルコードです。これを初期処理のところにでも入れてあげれば大丈夫です。


	Float32 curDuration = 0.023220;
	AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(Float32), &curDuration);

スリープに入ったときも音をきちんと維持したい」とお思いの方はぜひ試してみてください。

ちなみに

今回の調査には、書籍「iPhone Core Audioプログラミング*1が非常に参考になりました。


  「iPhone Core Audioプログラミング


スリープ中の〜」という直球な話題こそ触れていませんでしたが、上記ソースで使っているAudioSessionSetPropertyの使い方が丁寧に書いてあったため、応用で情報を得られました。

iPhoneで音と付き合う方なら、やっぱり一番のおすすめ本です。


言い忘れていた一番大事なこと

上記の本もそうですが、調査の際には同書の著者である永野氏にTwitterで色々と質問・相談させてもらいました。

ですので、今回の調査は同氏に色々と助けられたことになります。本当にありがとうございました。

*1Amazonインスタントストアへのリンクです