【iOS】音楽を止めずに効果音を同時に再生するには

iOSでは音を再生する時の選択肢として MediaPlayer Farmework と AVFoundation Frameworkの2種類があります。

今回はこれらの組み合わせで多重再生ができないかどうかを調べてみました。

AVAudioPlayer + AVAudioPlayerで同時再生

AVAudioPlayerでは音を同時再生することができます。
この際注意点としてファイル形式は一般的な.mp3や.3gpだと同時再生ができません。同時再生が必要な場合は.caf形式というApple独自の形式に変換する必要があります。

MP3などから caf ファイルへの変換はMacならターミナルから簡単にできます。

 $ afconvert -f caff -d 0 "元ファイル.mp3" "新しいファイル.caf"; 

再生はこんな感じです。mp3からcafに変えるだけですね。

 
@implementation MySoundPlayer {
    AVAudioPlayer* _player;
}
- (void) playSounds{
    // music.caf を再生
    [self playSoundWithFile: @"music" ofType: @"caf"]; 
    // sound.caf を同時再生
    [self playSoundWithFile: @"sound" ofType: @"car"]; }
- (void) playSoundWithFile:(NSString*)file ofType:(NSString*) type {
    NSString* path = [[NSBundle mainBundle] pathForResource:file ofType:type];
    NSURL* url = [NSURL fileURLWithPath:path];
    _player =[ [AVAudioPlayer alloc] initWithContentsOfURL:url error:nil ];
    [_player prepareToPlay];
    [_player play];
    }
@end

MPMusicPlayerPlayer + MPMusicPlayerPlayerで同時再生

MPMusicPlayerPlayerは同時再生に対応していません。残念。

MPMusicPlayerPlayer + AVAudioPlayerで同時再生

MPMusicPlayerPlayer同士の同時再生には対応していない、ならAVAudioPlayerとの組み合わせはどうなのか?

ということで試行錯誤した結果、対応しているようです。

そのままだと後ろの音が消えてしまい、同時再生できません。

ところが、以下のコードをAppDelegate.mに入れると…

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

あら不思議。これだけで後ろの音が消えず、同時に再生できるようになります。

このようにしておくと、iOS標準の音楽アプリが鳴っていても音を同時再生することができます。

なぜAppDelegateにこのようなコードを入れると同時再生できるのかというと、音楽再生時にはオーディオセッションカテゴリというアプリ内共通の音設定があり、標準では単曲再生するため、MPMusicPlayerで再生された曲を止めてしまいます。

これをAppDelegateで同時再生可能なカテゴリに変更することで、アプリ内でいつ音を再生しても、後ろの音楽を止めずに再生することができるようになる、というわけです。

詳しくは「
iOS オーディオセッションプログラミングガイド(pdf)
」の「カテゴリの種類」の項目が参考になります。

他にも「
iPodライブラリアクセスガイド(pdf)
」、「
AV Foundationプログラミングガイド(pdf)
」もiOSでの音楽再生の理解に役立ちます。

AVAudioPlayerとMPMusicPlayerで音を同時再生するのにこんなに悩むとは…。