美文网首页
Core Audio

Core Audio

作者: 蚂蚁_a | 来源:发表于2020-10-22 14:45 被阅读0次

    Core Audio

    Core Audio 编程接口分层(官方文档

    The three API layers of Core Audio.png
    Low-Level Services

    I/O Kit:与硬件驱动交互
    Audio HAL:音频硬件抽象层,使API调用与实际硬件相分离
    Core MIDI:为MIDI流和设备提供软件抽象工作层
    Host Time Services:访问硬件时钟

    Mid-Level Services

    Audio Convert Services:负责音频数据格式的转换
    Audio File Services:负责音频数据读写
    Audio Unit Services 和 Audio Processing Graph Services 使应用程序可以使用数字信号处理(DSP)插件,例如均衡器和混频器
    Core Audio Clock Services:用于音频和MIDI同步以及时间格式管理
    Audio File Stream Services:创建可以解析流的应用程序,负责流解析,对音频进行解码

    High-Level Services

    AVAudioPlayer:高级接口,可以完成整个音频播放的过程
    Audio Queue Services:录制、播放、暂停、循环、同步音频
    Extended Audio File Services:Audio File Services 和 Audio Converter services的结合体
    OpenAL:游戏音频

    Audio Session

    官方文档 Audio Session Programming Guide

    Audio Session
    概览

    我们可以使用 AVAudioSession 实例与应用程序的音频会话进行交互

    • 配置音频会话类别和模式,告诉系统使用音频的方式
    • 激活音频会话使设置的类别和模式配置生效
    • 订阅并响应音频会话通知,例如音频中断和路由更改
    • 执行高级别的音频设备配置,例如采样率,I/O缓冲持续时间和通道数

    1、配置 Audio Session

    let session = AVAudioSession.sharedInstance()
    do {
        try session.setCategory(AVAudioSession.Category.playback,
                                mode: AVAudioSession.Mode.moviePlayback,
                                options: [])
    } catch {
        print("Failed to set the audio session category and mode: \(error.localizedDescription)")
    }
    

    Category 设置应用基本音频行为,可以通过mode进一步设置这些行为;
    如IP语音(VoIP)使用AVAudioSessionCategoryPlayAndRecord,mode设置为AVAudioSessionModeVoiceChat,此模式可确保通过系统提供的信号处理来优化语音信号

    某些Category通过会话上设置一个或多个Category选项来支持覆盖默认行为,如AVAudioSessionCategoryPlayback类别的默认行为会在激活会话时中断其他系统音频,如果您希望音频与其他系统音频混合,则可以通过AVAudioSessionCategoryOptionMixWithOthers在会话上设置选项来覆盖此行为

    Category 通过铃声/静音开关或锁屏是否需要静音 是否中断不可以混合的音频 支持录音和播放
    AVAudioSessionCategoryAmbient Yes NO Output only
    AVAudioSessionCategorySoloAmbient (Default) Yes YES Output only
    AVAudioSessionCategoryPlayback NO Yes by default; no by using override switch Output only
    AVAudioSessionCategoryRecord No (recording continues with screen locked) YES Input only
    AVAudioSessionCategoryPlayAndRecord No Yes by default; no by using override switch Input and output
    AVAudioSessionCategoryMultiRoute No YES Input and output

    大多数应用在启动时只需要设置一次Category,但可以根据需要更改Category,可以在音频会话处于激活状态进行更改,最好在更改Category或者其他会话属性前停用音频会话,停用会话的同时进行这些更改可以防止音频系统不必要的重新配置

    枚举mode

    Mode identifiers Compatible categories
    AVAudioSessionModeDefault All
    AVAudioSessionModeMoviePlayback AVAudioSessionCategoryPlayback
    AVAudioSessionModeVideoRecording AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord
    AVAudioSessionModeVoiceChat AVAudioSessionCategoryPlayAndRecord
    AVAudioSessionModeGameChat AVAudioSessionCategoryPlayAndRecord
    AVAudioSessionModeVideoChat AVAudioSessionCategoryPlayAndRecord
    AVAudioSessionModeSpokenAudio AVAudioSessionCategoryPlayback
    AVAudioSessionModeMeasurement AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback

    Audio Session 默认行为

    • 支持音频播放,但不允许录音
    • iOS中,将"铃声/静音"开关设置为静音模式会使应用播放的任何音频静音
    • iOS中,将设备锁定时,应用程序的音频将静音
    • 当你的应用播放音频时,其他任何背景音频(如音乐应用正在播放的音频)都将静音
    多路由Category扩展

    多路由Category使应用程序可以使用所有连接的输出端口,而不仅仅使用最后的使用端口,例如,你正在通过HDMI输出路径收听音频并插入耳机,则你的应用将继续通过HDMI输出路径输出音频,同时还通过耳机播放音频

    还可以将不同的音频流发送到不同的输出路由,例如,应用可以将一个音频发送到左耳机,将另一个音频发送到右耳机,将第三个音频流发送到HDMI路由


    WeChat6e2e4a5f3e2491240d752ccda4a7a321.png

    有效输出路径组合

    • USB和耳机
    • HDMI和耳机
    • LineOut和耳机

    注:仅当未连接任何其他输出端口(USB,HDMI,LineOut)时,才可以使用内置扬声器

    选择AirPlay的Category和mode

    仅特定Category和mode支持AirPlay,以下类别通知支持AirPlay的镜像和非镜像版本

    • AVAudioSessionCategorySoloAmbient
    • AVAudioSessionCategoryAmbient
    • AVAudioSessionCategoryPlayback
      AVAudioSessionCategoryPlayAndRecord 类别和以下mode仅支持AirPlay镜像版本
    • AVAudioSessionModeDefault
    • AVAudioSessionModeVideoChat
    • AVAudioSessionModeGameChat

    从iOS 10开始,您可以通过使用选项AVAudioSessionCategoryPlayAndRecord激活会话来启用使用类别时的非镜像AirPlay输出AVAudioSessionCategoryOptionAllowAirPlay

    背景音频

    Capabilities 打开 Background Modes 的 Audio,AirPlay,and Picture in Picture

    2、激活 Audio Session

    let session = AVAudioSession.sharedInstance()
    do {
        //1)configure your audio session category, options, and mode
        //2)active your audio session to enable your custom configuration
        try session.setActive(true)
    } catch {
        print("Unable to active audio session: \(error.localizedDescription)")
    }
    

    使用AVFoundation对象(AVPlayer,AVAudioRecoder)播放或录制音频时,系统会在中断结束时重新激活音频会话,但是如果注册了通知消息并显式重新激活音频会话,则可以验证重新激活成功,还可以更新应用程序的状态和用户界面

    检测是否正在播放其他音频
    func setupNotification() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(handleSecondaryAudio(notification:)),
                                               name: AVAudioSession.silenceSecondaryAudioHintNotification,
                                               object: AVAudioSession.sharedInstance())
    }
    
    @objc func handleSecondaryAudio(notification: Notification) {
        guard let userinfo = notification.userInfo ,
              let typeValue = userinfo[AVAudioSessionSilenceSecondaryAudioHintTypeKey] as? UInt,
              let type = AVAudioSession.SilenceSecondaryAudioHintType(rawValue: typeValue) else {
            return
        }
        if type == .begin {
            //其他应用音频开始播放 - 将辅助音频静音
        } else {
            //其他应用音频停止播放 - 重新启动辅助音频
        }
    }
    
    响应中断

    中断生命周期


    音频会话中断
    1. 应用处于活跃状态,正在播放音频
    2. FaceTime请求到达,系统激活FaceTime的音频会话
    3. 系统将停用你的音频会话,此时你的应用播放停止
    4. 系统发布通知,通知你的会话已被停用
    5. 你的应用处理通知,如更新界面保存停止播放点继续播放所需的信息
    6. 如果用户取消中断(忽略FaceTime请求),系统发送通知我们应用中断结束
    7. 你的应用处理中断结束操作,如更新界面重新激活音频会话并恢复播放
    8. 如果没有6的中断,而是接听了电话,你的应用将被暂停
    • 音频中断处理
      中断开始后:保存状态和上下文,更新用户界面
      中断结束后:恢复状态和上下文,更新用户界面,重新激活音频会话

    • 观察音频中断

    func registerForNotification() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption(notification:)),
                                               name: AVAudioSession.interruptionNotification,
                                               object: AVAudioSession.sharedInstance())
    }
    
    @objc func handleInterruption(notification: Notification) {
        guard let userinfo = notification.userInfo,
              let typeValue = userinfo[AVAudioSessionInterruptionTypeKey] as? UInt,
              let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
            return
        }
        if type == .began {
            //中断开始 采取适当措施(保存状态更新界面)
        } else if type == .ended {
            guard let optionsValue = userinfo[AVAudioSessionInterruptionOptionKey] as? UInt else {
                return
            }
            let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
            if options.contains(.shouldResume) {
                //中断结束 恢复播放
            }
        }
    }
    
    响应路由变更

    当用户插入或拔出耳机时,系统会自动更改音频硬件路由


    WeChat576df2dfbada51373b956952a4f49a1c.png

    你的应用启动后,系统会首先确定音频路由,应用运行时,它将继续监听活动路由

    录制期间,用户可以插入和拔出耳机,作为响应,系统发送包含更改原因和先前路由的路由更改通知,应用停止录制

    • 观察音频路由变更
    func setupNotification() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleRouteChange(notification:)),
                                               name: AVAudioSession.routeChangeNotification,
                                               object: AVAudioSession.sharedInstance())
    }
    
    @objc func handleRouteChange(notification: Notification) {
        guard let userinfo = notification.userInfo,
              let reasonValue = userinfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
              let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else {
            return
        }
        switch reason {
        case .newDeviceAvailable:
            print("处理可用新设备")
        case .oldDeviceUnavailable:
            print("处理旧设备")
        default:
            ()
        }
    }
    

    当有新设备时,可以查询音频会话currentRoute属性,返回AVAudioSessionRouteDescription对象,其中列出了音频会话的所有输入和输出

    如果路由更改原因是原因AVAudioSessionRouteChangeReasonOldDeviceUnavailable,则媒体播放应用应暂停播放,但如果原因是,则不应暂停播放AVAudioSessionRouteChangeReasonOverride

    配置设备硬件

    设置 首选采样率 首选I/O缓冲区持续时间
    High value 示例:48Hz +高音质 -大文件或缓冲区大小 示例:500ms +较少的文件访问 -更长的延迟
    Low value 示例:8Hz +大文件或缓冲区大小 -低音频质量 示例:5ms +低延迟 -频繁的文件访问

    如果音频质量在你应用中非常重要,并且文件或缓冲区的大小不是主要问题,则可以指定高采样率的首选项

    默认音频I/O缓存持续时间(44.1kHz约0.02s)为大多数应用提供了足够的响应速度,可以对延迟有严格要求的应用(如现场乐器监控)设置较低的I/O持续时间,但对大多数应用,无需修改此设置

    //Category and mode
    let session = AVAudioSession.sharedInstance()
    do {
        try session.setCategory(.record, mode: .default, options: [])
    } catch {
        print("Unable to set Category: \(error.localizedDescription)")
    }
    //Set preferred sample rate
    do {
        try session.setPreferredSampleRate(44_100)
    } catch {
        print("Unable to set preferred sample rate \(error.localizedDescription)")
    }
    //Set preferred I/O buffer duration
    do {
        try session.setPreferredIOBufferDuration(0.005)
    } catch {
        print("Unable to set preferred I/O bufferr duration \(error.localizedDescription)")
    }
    //Active the audio session
    do {
        try session.setActive(true)
    } catch {
        print("Unable to active session \(error.localizedDescription)")
    }
    
    选择和配置麦克风
    • 设置首选输入
      要发现内置或已连接的输入端口,使用音频会话的availableInputs属性,返回一个AVAudioSessionPortDescription对象数组,这些对象描述设备的可用输入端口,可用通过端口protType属性标识端口,要设置首选输入端口(内置麦克风,有线麦克风,USB输入等)使用音频会话的setPreferredInput:error:方法

    • 设置首选数据源
      某些端口(如内置麦克风和某些USB附件)支持数据源,可用通过查询端口描述的DataSource属性发现可用数据源。
      对于内置麦克风,返回的数据源描述对象代表每个单独的麦克风,不同设备的内置麦克风返回不同的值。如iPhone4iPhone4s有两个麦克风:底部和顶部
      可通过数据源描述的location属性(上部下部)和orientation属性(正面背面)的组合来标识各个内置麦克风,使用setPreferredDataSource:error:方法设置首选数据源AVAudioSessionPortDescription

    • 设置首选极性图案
      某些iOS设备支持为某些内置麦克风配置麦克风极性模式,麦克风的极性模式定义了其对声音相对于声源方向的灵敏度
      supportedPolarPatterns数据源描述对象的属性返回可用模式。此属性返回数据源支持的极性图案的数组,例如心形或全向,或者nil在没有可用的可选图案时返回。如果数据源具有许多受支持的极性图案,则可以使用数据源描述的[setPreferredPolarPattern:error:方法来设置首选的极性图案

    相关文章

      网友评论

          本文标题:Core Audio

          本文链接:https://www.haomeiwen.com/subject/yiqdmktx.html