【Xcode】効果音と多重再生とSFSpeechRecognizer(音声認識)

作成中のアプリで使おうと思って調べたメモです。

サウンドの再生方法


調べてみると、下記の2つの方法があって、それぞれ用途によって総称されているフレームワークが違っている。

・AudioToolBoxを使う方法(効果音等短い音)
・AVFoundationを使う方法(BGM等長い音やループ)

【参考】
Objective-C:音楽(BGM)や効果音(SE)等のサウンド再生方法 | siro:chro
アプリ開発ブログ(仮): 効果音を鳴らす
【Xcode】アプリ内のボタンに効果音を付ける! | iDEACLOUD/dev

BGMと効果音を併用する際の問題点


効果音はAudioToolBox、BGMはAVFoundationで鳴らせばいいのかと思って、効果音をAudioToolBoxで組み込んで、テスト中にミュージックアプリで音楽流しながら、効果音を鳴らしたら音楽がフェードアウトしてしまった。で、調べてみたら、どうもAudioToolBoxとAVFoundationの併用に問題があるらしいことが発覚。

以下のリンクによれば、AudioToolBoxで音を鳴らすと、AVFoundationの方はフェードアウトしてしまうらしい。
なので、効果音もAVFoundationで再生することにする。

【参考】
BGMを鳴らしながら効果音再生するときの落とし穴 – iOSアプリ開発まとめWiki – アットウィキ

多重再生するための設定


更に調べてみると、多重再生させるには、以下の2つが必要とのこと。

・音声ファイルを .caf形式にする
・AVAudioSessionのカテゴリを変更する

.cafとは、Core Audio File の拡張子で、iOSおよびOS Xのネイティブのオーディオファイルフォーマットらしいです。

ターミナルから以下のコマンドで変換できます(例:sound_ok.m4a を sound_ok.caf に変換)

afconvert -f caff -d 0 sound_ok.m4a sound_ok.caf

※変換したところ、ファイルサイズは【107KB】>>【54KB】になりました。

また、AVAudioSessionのカテゴリは、デフォルトではオーディオ再生中にアプリを起動するとオーディオが停止(AVAudioSessionCategorySoloAmbient)するようになっているので、どちらも鳴らせるように設定を変更します。Objective-Cだと、AppDelegate.m にこんな感じに書きます。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // バックグラウンドでの音の再生を許可
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
    return YES;
}

【参考】
Swift:AVAudioSession アプリのバックグラウンドで音楽を再生する | siro:chro
iPhoneアプリ開発のためのサウンドフォーマットまとめ | ぱーくん plus idea
Core Audioの概要【PDF】
【iOS】音楽を止めずに効果音を同時に再生するには|てくめも@ecoop.net

SFSpeechRecognizer(音声認識)で効果音が再生されない問題


SFSpeechRecognizer(音声認識)を使ったアプリに効果音を組み込んでみたら、SFSpeechRecognizerを使って音声認識した後に、効果音が鳴らなくなった。

結果的には、SFSpeechRecognizerを使って音声認識を実行した後に、もう一度AVAudioSessionのカテゴリを変更してやることで解決しました。Objective-Cだと、こんな感じ。

// バックグラウンドでの音の再生を許可(AppDelegateで設定しているが、speechRecognizer使用後に再度設定しないと、音が鳴らない)
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];

SFSpeechRecognizer自体はここでは触れないので、下記リンクを参照して下さい。要は、SFSpeechRecognizerを使う際にAVAudioSessionのカテゴリを録音用に変更(AVAudioSessionCategoryRecord)しているので、それを戻さないと音が鳴らないということです。

【参考】
[iOS 10] SFSpeechRecognizerで音声認識を試してみた | Developers.IO