音声を再生するアプリを作成した際に考えた事、
エラー、等をまとめました。
このブログにあるスニペットは実行可能なプロジェクトとしてgithubに置いてあります。
どのFrameworkを採択するか?
cocoaは音声を再生するのに様々なFrameworkを提供してくれています。
どれを選ぶかは、以下のAppleの記事の「Choose the right technology for your needs:」
を参考にすると良いでしょう。
Audio & Video Starting Point
僕は今回AudioToolBoxを選択しました。
音声の再生、停止、曲のループをする所まで書きたいと思います。
Audio Toolbox Framework Reference
注意点としては、以下があります。
・30秒を超える音声ファイルは再生出来ない
・音量調整、再生位置指定、ループ(※1)等が出来ない
・.caf、.aiff、.wavのみ対応(mp3は不可)
※1、コールバックで制御する事で可能
実装
まず、AudioToolBox.frameworkを追加します。
(追加の方法は割愛。)
コードでの実装は以下の様になります。
SystemSoundID soundId = UINT32_MAX; // 1
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[[NSBundle mainBundle] URLForResource:@"fanfare" withExtension:@"wav"], &soundId); // 2
AudioServicesPlaySystemSound(soundId); // 3
1. SystemSoundID型の変数を用意する(再生する音声一つに付き一つの変数が必要です)
2. AudioServicesCreateSystemSoundIDで1で用意した変数を初期化する
3. AudioServicesPlaySystemSoundで2で初期化したSystemSoundIDの変数を指定して音声を再生
1〜3をまとめると以下の様な記述となります。
ARC対応
※2の箇所は本来であれば
AudioServicesCreateSystemSoundID([[NSBundle mainBundle] URLForResource:@"fanfare" withExtension:@"wav"], &soundId);
で良いのですが、ARCですと
Implicit conversion of Objective-C pointer type 'NSURL *' to C pointer type 'CFURLRef' (aka 'const struct __CFURL *') requires a bridged cast
と言うエラーが出るので上記の様にブリッジキャストをしています。
停止
Appleが提唱している方法ではありませんが、以下の一行で可能です。
AudioServicesDisposeSystemSoundID(soundId);
ループ
AudioServicesAddSystemSoundCompletionメソッドにより、再生完了のコールバックメソッドを指定出来ます。
soundIdの初期化をした後に指定します。
AudioServicesAddSystemSoundCompletion(soundId, NULL, NULL, completionBlock, (__bridge void *)self);
ここでもCへ渡すためにブリッジキャストを行います。
これを行う事でコールバックメソッドへ自インスタンスの情報を渡す事が出来ます。
コールバックメソッドは以下の様に実装します。
void completionBlock(SystemSoundID soundId, void *clientData) {
ViewController *viewController = (__bridge ViewController *)clientData;
if(soundId == viewController.fanfareSoundId) {
AudioServicesPlaySystemSound(soundId);
return;
}
return;
};
インターフェースで分かると思いますが、
第一引数のsoundIdには再生が終了したsoundId、
第二引数には呼び出しもとのインスタンスが入ります。
誰かのお役に立てば。
コメント