iOS语音开发--Core Audio

一,参考

Apple devleop Document:Core Audio Essentials
Audio Session Programming Guide(https://developer.apple.com/library/content/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/Introduction/Introduction.html)

二,架构层次

CoreAudio的API分为三层:
CoreAudio的三层API

底层跟硬件打交道;中间层包括了数据格式转换,读写磁盘,分析流;上层包括了一些包含底层特征的精简接口。

三,框架

AudioToolbox.framework:包括音频session相关。
AudioUnit.framework:让应用与音频插件配合工作。
AVFoundation.framework:提供AVAudioPlayer–精简的的音频播放接口。
CoreAudio.framework:提供Core Audio中用的数据类型。

四,具体处理

Callback函数:跟Core Audio交互
Audio Session:与Core Audio交互
应用与iOS之间的媒介,使用之前需要考虑:
1,应用想要如何处理电话等中断。
2,想要将本应用的声音与其他应用的混合,还是让他们静音?
3,应用如何处理声音路由变化–用户拔插耳机时。

audio sesison interface提供的特征

1,激活AudioSession
中断:抑制和激活
程序启动时默认是激活状态,电话进来后进入抑制状态,如果不进行激活,音乐无法在电话结束后继续播放。
检查是否有其他声音在播放
可以在app delegate的applicationDidBecomeActive:中检查session.secondaryAudioShouldBeSilencedHint,也可以订阅这个类型的变化情况(AVAudioSessionSilenceSecondaryAudioHintNotification)、

2,配置Session
音频会话的默认行为:
1,支持声音播放,但不支持声音录制。
2,当用户将铃声/静音开关置为静音时,声音被静音。
3,用户通过睡眠/苏醒按钮进行锁屏时,声音被静音。
4,当声音开始后,其他音频被静音。

AudioSessionCategoryBehavior
说明:
Category决定了音频的行为,主要行为有:
- 中断其他非混合的音频。
- 被手机侧面的静音开关静音。
- 支持音频输入。
- 支持音频输出。
最好在会话被音质后在改变category或者会话属性,这样做可以阻止音频系统进行不必要的重新配置。
SDK详细说明:
AVAudioSessionCategoryAmbient:背景声音,例如雨声、汽车引擎声等,跟其他声音混合。
AVAudioSessionCategorySoloAmbient:背景声音。会停掉其他音乐。
AVAudioSessionCategoryPlayback:音乐播放。
AVAudioSessionCategoryRecord:录音。
AVAudioSessionCategoryPlayAndRecord:录音和音乐播放。
AVAudioSessionCategoryAudioProcessing:当使用硬件编解码器或信号处理器时,请使用此类别。
不播放或录制音频。
AVAudioSessionCategoryMultiRoute:需要自定义可用的音频设备以及内置的声音硬件时使用。

Modes and associated categories
说明:
除了Category还可以通过Mode,进一步精确音频的行为:
AVAudioSessionModeDefault:通用
AVAudioSessionModeVoiceChat:只在AVAudioSessionCategoryPlayAndRecord可用,适合VoIP应用。使得音频路径只为VoIP输出。
AVAudioSessionModeGameChat:只在AVAudioSessionCategoryPlayAndRecord可用。由Game Kit设定,不要直接设定。
AVAudioSessionModeVideoRecording:AVAudioSessionCategoryPlayAndRecord或者AVAudioSessionCategoryRecord时可用。修改音频路由选项,并可进行适当的系统提供的信号处理。
AVAudioSessionModeMeasurement:适用于希望尽量减少系统提供信号影响的应用程序输入和/或输出音频信号的处理。
AVAudioSessionModeMoviePlayback:对电影回放场景进行适当的输出信号处理。目前仅适用于内置扬声器播放时。
AVAudioSessionModeVideoChat:>=iOS7.0 只在kAudioSessionCategory_PlayAndRecord可用。减少允许的音频数量仅适用于视频聊天应用程序的路由。可以进行适当的系统提供的信号处理。
AVAudioSessionModeSpokenAudio:>=iOS9.0 如果其他应用(如导航应用程序)播放语音音频提示时,适用于希望暂停(通过音频会话中断)而不是躲避。使用此应用程序的示例是播客播放器和音频书。

3,中断处理
中断发生时,需要保存状态和环境,更新用户画面;
中断结束时,需要恢复状态和环境,更新用户画面,重新激活会话

观察中断

NotificationCenter.default.addObserver(self,
                                           selector: #selector(handleInterruption),
                                           name: .AVAudioSessionInterruption,
                                           object: AVAudioSession.sharedInstance())
func handleInterruption(_ notification: Notification) {
    guard let info = notification.userInfo,
        let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
        let type = AVAudioSessionInterruptionType(rawValue: typeValue) else {
            return
    }
    if type == .began {
        // Interruption began, take appropriate actions (save state, update user interface)
    }
    else if type == .ended {
        guard let optionsValue =
            userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else {
                return
        }
        let options = AVAudioSessionInterruptionOptions(rawValue: optionsValue)
        if options.contains(.shouldResume) {
            // Interruption Ended - playback should resume
        }
    }
}

4,路径变化

func setupNotifications() {
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(handleRouteChange),
                                           name: .AVAudioSessionRouteChange,
                                           object: AVAudioSession.sharedInstance())
}
func handleRouteChange(notification: NSNotification) {
    guard let userInfo = notification.userInfo,
        let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
        let reason = AVAudioSessionRouteChangeReason(rawValue:reasonValue) else {
            return
    }
    switch reason {
    case .newDeviceAvailable:
        let session = AVAudioSession.sharedInstance()
        for output in session.currentRoute.outputs where output.portType == AVAudioSessionPortHeadphones {
            headphonesConnected = true
        }
    case .oldDeviceUnavailable:
        if let previousRoute =
            userInfo[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription {
            for output in previousRoute.outputs where output.portType == AVAudioSessionPortHeadphones {
                headphonesConnected = false
            }
        }
    default: ()
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值