AV Foundation-音频播放

466 阅读2分钟

AVAudioSession

在应用程序与操作系统之间扮演中间人的角色。提供一种简单的方法使应用程序知道如何与iOS音频环境进行交互。

AVAudioSession可以通过分类控制一些音频行为:

分类 作用 是否支持混音 音频输入 音频输出
Ambient 游戏、效率 Y N Y
Solo Ambient(默认) 游戏、效率 N N Y
Playback 音频、视频播放器 可选 N Y
Record 录音机、音频捕捉 N Y N
Play and Record VoIP、语音聊天率 可选 Y Y
Audio Precessing 离线会话和处理 N N N
Multi-Route 使用外部硬件的高级A/V应用程序 N Y Y
  // 初始化session
   AVAudioSession *session = [AVAudioSession sharedInstance];
   NSError *error;
   
   if ([session setCategory:AVAudioSessionCategoryPlayback error:&error]) {
       NSLog(@"AudioSession setcategory error: %@", error);
   }
   
   if ([session setActive:YES error:&error]) {
       NSLog(@"AudioSession setActive error: %@", error);
   }

AVAudioPlayer

AVAudioPlayer 可以播放除网络音频、原始音频或者非常低的延时之外的所有情况

初始化:

- (AVAudioPlayer *)play{
    if(!_play){
        NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"guitar" withExtension:@"caf"];
        _play = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:NULL];
        _play.delegate = self;
        [_play prepareToPlay];

    }
    return _play;
}

方法:

  • play (播放)
  • pause (暂停)
  • stop (停止,和pause不同指出会清除prepareToPlay的配置)

属性:

  • volume: 音量
  • pan:声道
  • numberOfLoops: 循环次数 (-1无限循环)
  • rate: 播放速率(需要开启enableRate

后台播放

  1. session category 设置为AVAudioSessionCategoryPlayback
  2. info.plist 添加:Required background modes - App plays audio or streams audio/video using AirPlay

中断处理

音频播放过程中,会被电话、faceTime导致中断,系统中断时会发送`AVAudioSessionInterruptionNotification`通知。

注册通知:

NSNotificationCenter *nsnc = [NSNotificationCenter defaultCenter];
[nsnc addObserver:self
                 selector:@selector(handleInterrupt:) name:AVAudioSessionInterruptionNotification
                   object:[AVAudioSession sharedInstance]];

方法实现:

- (void)handleInterrupt:(NSNotification *)notification{
    NSDictionary *info = notification.userInfo;
    AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
    
    if (type == AVAudioSessionInterruptionTypeBegan) {
        // 中断开始(更新UI状态 暂停播放)
        
    }else{
        // 中断结束
        AVAudioSessionInterruptionOptions option = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
        
        if (option == AVAudioSessionInterruptionOptionShouldResume) {
            
            // 是否再次播放
        }
        
    }
}

Audio channel 处理

音频播放过程中,插入耳机等会导致播放渠道的更改。插入耳机,音频正常播放,但是Apple规定,耳机内播放的内容可能是隐私信息。因此,拔掉耳机,音频应该是暂停状态。整个过程系统会发送`AVAudioSessionRouteChangeNotification`通知,供应用处理。

注册通知:

NSNotificationCenter *nsnc = [NSNotificationCenter defaultCenter];
[nsnc addObserver:self
                 selector:@selector(handleRouteChange:)
                     name:AVAudioSessionRouteChangeNotification
                   object:[AVAudioSession sharedInstance]];

通知实现:

- (void)handleRouteChange:(NSNotification *)notification {

    NSDictionary *info = notification.userInfo;

    AVAudioSessionRouteChangeReason reason =
        [info[AVAudioSessionRouteChangeReasonKey] unsignedIntValue];

    if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
    // 耳机断开事件
    
        // 获取前一个channel信息
        AVAudioSessionRouteDescription *previousRoute =
            info[AVAudioSessionRouteChangePreviousRouteKey];

        AVAudioSessionPortDescription *previousOutput = previousRoute.outputs[0];
        NSString *portType = previousOutput.portType;

        if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {
            // 前一个channel输出是耳机类型,暂停播放
        }
    }
}