一、概述

用户可能插上耳机、电话可能打来、alarm可能开始响起来。确实,音频环境是非常复杂的。iOS让你通过audio session api让你使用很少的代码来响应这些系统请求。



1、一个Audio Session封装了一组Audio行为


在启动时,应用程序将自动获得一个单例audio Session。



2、Categories代表Audio Roles


最主要的表示audio意图的机制就是设置audio Session category。一个Category是一个key,标识一系列audio行为。通过设置Category,你指示你的audio在屏幕锁定时是否应该继续,你是否想iPod audio与你的audio一同播放,等等。


六个audio Session Category,同一套override和modifier开关,让你个性化audio 行为。不同的Category支持播放、录音、播放与录音,和offline audio 处理。当系统知道了你的app的audio role,这让你可以适当的访问硬件资源。系统还保证设备上的其他audio具有相同的行为;例如,如果你需要iPod audio静音,it is。



3、代理支持中断处理


audio中断是你的应用的audio Session的去激活--它立即停止你的audio。中断发生于一个内置的应用程序的audio Session,并且这个audio Session的Category不能和你的audio Session混合在一起。(也就是说内置的应用的audio Session优先级更高)。当你的audio Session变得不活跃时,系统发送了一个“你被中断了”消息,你可以利用这个消息来保存状态,更新用户界面,等等。


要处理中断,需要实现AV Foundation框架提供的Objective-C中断代理方法。写你的beginInterruption和endInterruption方法来确保最小化破坏,最大化恢复。



4、回调支持Audio Route Change Handling(音频输出变更处理?)


例如插入耳机时,写一个C 回调函数,并注册其到你的Audio Session。



二、Audio Session Basics


阅读这个章节来学习Audio Session能解决什么问题。


1、为什么iOS需要管理Audio?


在你早上去上班的地铁上,你解锁了你的iPhone然后开始听podcast的一段插曲,从内置的扬声器播放。然后你的同座人皱眉了,你只好插上耳机,然后声音转到耳机输出,并且使用你的耳机之前使用的音量开始播放。或许了开始了一个数独游戏,它播放自己的音效,podcast的输出和游戏声音效果混合在了一起。又过了一会,podcast渐渐安静了,因为一个alarm声音响起并且一个alert出现了。你取消了alert。然后podcast渐渐恢复并继续播放。你的数独游戏的声音也继续工作。


一个Audio Session使你能提供无缝的Audio体验。实际上,任何使用AV Foundation Framework,Audio Queue Services,OpenAL,或I/O audio unit的应用都必须使用audio Session Programming Interface来满足Apple的推荐规范。



2、什么是Audio Session?


一个Audio Session是用来配置Audio行为。在启动时,应用程序将自动获得一个单例audio Session。你配置它来表现你的Audio意图,例如:


1)你是否打算混合你的应用的声音和其他应用(例如iPod)的声音,或你是否打算静音其他的Audio?


2)你想你的应用如何响应Audio中断,例如Clock Alarm?


3)当用户插入或拔出耳机时,你的应用要如何响应?


除了你播放的声音效果,Audio Session的配置影响所有的Audio活动---在你的应用运行过程中。你可以查询Audio Session来发现设备的硬件特性---例如声道数(channel count)、采样率(sample rate)、和音频输入的可用性(availability of audio unit)。


你可以显式地激活和去激活你的Audio Session。要播放声音,或录制,Audio Session必须是Active的。系统还可以去激活你的Audio Session--例如当电话来到时或一个alarm响起时,系统会这么做。 这样的去激活被称为Audio Session的中断(Interruption)。Audio session APIs提供了方法来响应中断和从中断中恢复。



3、什么是Audio Session Category?


一个Category是一个key,表示一组Audio行为。通过设置Category,你指示你的audio在屏幕锁定时是否应该继续,你是否想iPod audio与你的audio一同播放,等等。


每个Audio Session Category为下面的行为指定了一各特定的yes和no的值:


1)Allows mixing:如果是yes,其他应用的audio可以在你播放声音时继续播放。


2)Silenced by the Silent switch and by screen locking:如果是yes,当用户切换到静音和屏幕锁定时,你的audio也静音。


3)Supports audio input:如果yes,允许录音


4)Supports audio output:如果yes,允许播放



大多数应用只需要设置一次Category即可,在启动时。这就是说,你可以按照你的需要来更改Category,而且不用贯你的audio Session是否active。如果你的Session是不活跃的,你的Category request在你的Session active时被发送。如果你的Session已经是活跃的,你的Category request就立即呗发送。



4、Audio Session 默认的行为:


一个Audio Session带来了一些默认行为。尤其是:


1)播放是启用的,录音是禁用的。


2)如果用户设置了静音,那么你的Audio也会被静音。


3)手机锁定时,你的Audio被静音。


4)当你的Audio 开始时,设备上的其他Audio--例如iPod Audio正在播放---被静音。



这些行为被封装进AVAudioSessionCategorySoloAmbient Category--默认的Category。


你的Audio Session在应用启动时自动被激活。这允许你播放(录制,如果设置了其他支持录音的Category)。然而,依赖默认的激活是冒险的。例如,如果一个IPhone响铃了,并且用户忽略了这个电话--让你的应用运行--那么你的Audio可能不再播放。



5、为什么默认的Audio Session 通常不是你想要的?


1)如果你需要在屏幕锁定后继续播放声音,使用AVAudioSessionCategoryPlayback Category。


2)如果你需要混合其他应用的Audio,使用AVAudioSessionCategoryAmbient Category。


3)要在中断后继续播放,需要编写中断方法或写一个Audio Session 回调函数来允许你的应用自动继续播放或允许用户手动恢复播放。



6、系统如何解决Audio Demands的竞争?


可以把iPhone想像成一个机场,应用为客机,系统的服务为指挥塔。你的应用发布Audio request并陈述他的希望的优先级,但最终在跑道上的发生的鉴权来自于系统。你通过Audio Session与指挥塔通信。如图所示:


 


第一步:应用请求Core Audio要激活Audio Session。


第二步:系统考虑激活请求列表。尤其地,他考虑你指定给Audio Session的Category。图示中的Category要求其他应用的Audio静音。


第三步\第四步:系统去激活iPod应用的Audio Session,停止其Audio的播放。


第五步:系统激活你的应用的Audio Session,然后播放可以开始了。



系统遵循“the phone always wins”原则。没有应用,不管它多么尽力地要求优先级,可以战胜phone。当一个电话来到时,用户获得通知并且你的应用被中断--不管什么Audio Operation正在进行,而且不管你设置了什么Category。


为了确保你的Audio不被这些中断(例如电话和Clock alarm)破坏,用户必须调到飞行模式。另一个原则是:”用户,而不是应用,在控制设备“。例如,没有代码的方式来让Clock Alarm静音。要阻止一个Alarm破坏录音,用户必须取消alarm。类似的,也没有代码的方式来设置硬件播放音量。用户总是使用设备侧面的音量按钮来控制硬件音量。



7、两个Audio Session APIs:


1)AVAudioSession类,在AVAudioSession Class Reference中描述。提供了一个Objective-C界面,和其他Objective-C代码协同工作很好。这个API提供访问一组Audio Session的特色。


AVAudioSession有两个关键优势。


第一个优势:当你使用它获得Audio Session的共享实例时,Session被隐式的初始化,使用C API,没有这个初始化。 


第二个优势:你可以使用简单的代理方法来处理audio中断和硬件配置的更改(例如采样率和声道数量的改变)


2)Audio Session Services,在Audio Session Services Reference中描述,是一个C API,提供对Audio Session的所有基本和高级特色的访问。


你需要使用这个API来处理Audio硬件route changes的更改(例如插入耳机),和修改Audio Session Category的默认行为。例如,kAudioSessionProperty_OverrideAudioRoute属性允许你switch playback from the receiver to the speaker---当正在使用“play and record” audio Session Category。这个API还提供了回调函数机制来处理中断。



8、使用 Audio Session APIs开发:


使用模拟器,你不能:


1)调用一个中断


2)更改设置中的静音模式。


3)模拟屏幕锁定


4)模拟耳机的插入


5)查询Audio route信息或测试Audio Session Category行为


6)测试Audio mixing行为--就是说,播放你的Audio的同时播放其他应用的Audio(例如iPod)



要测试你的Audio Session代码的行为,你需要在设备上运行。对于某些使用模拟器时的开发技巧,查阅"Running Your App in the Simulator"。



三、Configuring Your Audio Session:配置你的Audio Session:


1、初始化Audio Session:


在你的应用启动后,系统会自动给你一个Audio Session对象。在使用Session工作前,你必须初始化它。你如何初始化它取决于你想如何处理Audio中断:


1)如果使用AV Foundation框架来管理中断,使用隐式初始化,在你获得一个AVAudioSession对象时,Session就被自动初始化了。如下所示:


AVAudioSession *session=[AVAudioSession sharedInstance];


在你使用AVAudioSession累的中断代理方法来处理Audio中断,或使用AVAudioPlayer和AVAudioRecorder累的代理方法,苹果推荐使用隐式初始化。


2)或者,你可以写一个C 回调函数来处理Audio中断。你必须使用显式初始化Audio Session,使用函数AudioSessionInitialize。一般,你应该在你的应用的main Controller类的初始化方法里初始化Audio Session。



2、激活和去激活Audio Session:


系统在你的应用启动时,自动激活你的Audio Session。但是Apple建议你显式激活你的Session---一般在viewDidLoad方法中。这给你一个机会来测试激活是否成功。同样的,当更改你的Audio Session的active和inactive状态时,检查其来确保调用成功。如果系统拒绝激活你的额Session,你就需要写代码来处理。


系统会在 时钟或日历 alarm或电话来临时 使你的Audio Session无效。当用户取消了alarm或忽略了来电,系统允许你的Session重新被激活。

苹果推荐你使用AVAudioSessionDelegate来实现对中断和恢复的处理。


大多数应用程序不需要显式 无效他们的Audio Session。重要的例外包括VoIP应用的录音应用。


1)VoIP应用,话费大量时间在后台运行,应该确保其Session在应用处理一个call时是活动的。在后台,表示正在准备接听一个电话,VoIP应用的Audio Session应该不是活跃的。


2)使用录音Category的应用应该确保其Audio Session在录音过程中是活跃的。在录音之前和录音停止之后,确保你的Session是不活跃的。或者说,如果你的录音应用还支持播放,那么你应该在没有录音时切换到Playback Category来允许播放。



3、选择最好的Category:


iOS有6个Audio Session Category:


3个用来播放


1个用来录音


1一个支持播放和录音--不需要同时发生,如果需要也是可以的。


1个用来offline Audio processing


要选择最好的Category,考虑下面的因素:


1)最好的Category是最接近支持你的需要的。你想播放、录制,还是两者都做,还是只是指向offline Audio processing?


2)你要播放的Audio对于你的应用来说是必要的还是次要的?如果是必要的,最好的Category就是在Ring/Silent切换到silent时支持播放。如果是次要的,就选择在Ring/Silent切换到silent时你的Audio也静音的Category。


3)在你的应用启动时是否其他的应用(例如iPod audio)正在播放音乐?在启动中检查这个是你能进行分支处理。例如,一个游戏应用可能选择一个Category配置来允许iPod Audio继续播放--如果它已经开始播放了,否则选择一个不同的Category配置来支持内置的app soundtrack。



下面介绍Categories:第一个Category允许其他Audio继续播放;其余的Categories指示你想其他的Audio在你的Audio Session活跃时停止播放。然而,你可以自定义非混合”Playback“和”Play and record“Categories来允许混合。


1)AVAudioSessionCategoryAmbient或kAudioSessionCategory_AmbientSound----允许混合Audio、静音时静音


2)AVAudioSessionCategorySoloAmbient或kAudioSessionCategory_SoloAmbientSound--这是默认的Category,不允许混合


3)AVAudioSessionCategoryPlayback和kAudioSessionCategory_MediaPlayback--静音时不静音


4)AVAudioSessionCategoryRecord或kAudioSessionCategory_RecordAudio--不允许混合


5)AVAudioSessionCategoryPlayAndRecord或kAudioSessionCategory_PlayAndRecord--用在聊天的应用中


6)AVAudioSessionCategoryAudioProcessing或kAudioSessionCategory_AudioProcessing--来执行离线audio处理,而不播放或录音。



通过audio Session的kAudioSessionProperty_OtherAudioIsPlaying属性来在应用启动时检查其他应用的audio有没有正在播放。



4、Category是如何影响encoding和decoding的?


在iOS中,你可以encode未压缩的音频到一组压缩格式。你也可以decode这些格式来播放。


硬件相关的编码器只有在你配置你的audio Session为静音其他audio时才可用。



5、设置和更改audio Session Category:


6、微调Category:


基于Category,你可以:


1)允许其他audio混合你的audio


2)更改audio output route从Receiver到speaker


3)允许bluetooth audio Input


4)制定其他audio在你的audio播放时 其应该减少音量。



你可以覆盖AVAudioSessionCategoryPlayback的non-mixing特性或AVAudioSessionCategoryPlayAndRecord的特性。来执行override,应用kAudioSessionProperty_OverrideCategoryMixWIthOthers属性到你的audio Session。



应用kAudioSessionProerty_OtherMixableAudioShouldDuck属性到你的audio Session。



四、处理Audio中断


1、音频中断处理技术:


有两种技术来响应中断:


1)使用AV Foundation框架提供的Objective-C中断代理方法。在大多数情形下,这个技术是简单而且好用的。


2)使用Audio Session Services使用的C-Based中断回调函数。这需要你 通过使用一个显式Audio Session初始化调用来注册你的回调函数到Audio Session。



使用哪种技术取决于你使用哪种Audio技术和你使用Audio的用途--播放、录制、Audio格式转换、读取流音频包、等等。一般来说,你需要确保最小化的中断破坏,和最大可能的恢复。


下面列出了中断时产生的事件的顺序,当使用AVAudioPlayer或AVAudioRecorder对象时,一些步骤自动被系统处理。


1)在中断开始后:


a)检查是否支持恢复音频过程。


b)保存状态和context


c)更新用户界面



2)在中断结束后:


a)恢复state和context


b)重新激活Audio Session


c)更新用户界面



下面列出了各种技术如何处理Audio中断。


1)使用AV Foundation Framework:AVAudioPlayer和AVAudioRecorder类提供了代理方法来处理中断的开始和结束。


2)使用Audio Queue Services,I/O Audio unit:使用这些技术让你的应用能控制处理中断。你需要负责保存播放或录音位置和重新激活你的Audio Session。实现AVAudioSession中断代理方法或写一个中断监听回调函数。


3)使用OpenAL:当你使用OpenAL播放时,实现AVAudioSession中断代理方法或写一个中断监听回调函数。就像试用Audio Queue Services一样,但是需要在代码里添加管理OpenAL context的代码。


4)使用System Sound Services:System Sound Services播放的声音会在中断开始的时候静音。它们可以在中断结束后自动恢复播放。应用不能控制这种技术的播放的中断行为。



2、中断生命周期:


下图显示了事件发生的顺序。




3、使用代理方法处理中断:

AVAudioSession 类提供了代理方法,在AVAudioSessionDelegate协议中指定,来响应中断。你可以实现这些方法来响应中断而不管你使用的是哪种技术:

1)beginInterruption:在你的AudioSession被中断后调用。

2)endInterruption:在你的Audio Session中断结束后被调用。如果没有使用AVAudioPlayer或AVAudioRecorder对象(她们会自动重新激活Audio Session),你需要显式重新激活你的Audio Session。


AVAudiorecorer和AVAudioPlayer类提供了它们自己的代理方法来响应中断:

1)audioPlayerBeiginInterruption:

2)audioPlayerEndInterruption:

3)audioRecorderBeginInterruption:

4)audioRecorderEndInterruption:


AVAudioRecorder和AVAudioPlayer在中断时自动暂停。你不需要保存录音和播放位置--除非你想保存它们另作他用。另外,系统自动重新激活audio Session,这让你可以在中断结束后恢复播放和录音。


4、试用一个C 回调函数来处理中断:

如果你选择一个C-language来处理中断,按照AudioSessionInterruptionListener原型来写一个自己的监听回调函数。

当系统调用你的回调时,他发送两个值:一个是你初始化Audio Session时指定的数据的引用,另一个是指示中断状态的常量。下面列出了AudioSessionInterruptionListener回调的原型:

typedef void (*AudioSessionInterruptionListener) (

   void *inClientData,

   UInt32 inInterruptionState

);

有两个中断状态:

1)kAudioSessionBeginInterruption:

2)kAudioSessionEndInterruption:


4、OpenAL和Audio Interruptions:

实现AVAudioSession代理方法。在中断开始后,设置OpenAL的contex为NULL,在中断结束后,设置OpenAL的context为之前的状态。


5、硬件相关的编码器和Audio Interruption:


五、处理Audio Hardware route Changes:


下图列出了不同的route Changes发生于播放和录音时的事件发生的顺序。


 


1、响应Audio Hardware route Changes:


有3部分来配置你的应用响应route Changes:


1)实现route change时要被调用的方法。


2)实现一个属性Listener回调函数,来响应route changes并使用第一步写好的函数。


3)注册回调函数到Audio Session上。


callback原型为AudioSessionPropertyListener,如下例所示:


void MyPropertyListener(


 void  *inClientData,


 AudioSesssionPropertyID inID,


 UInt32  inDataSize,


 const void *inData


);


对于一个route change事件,系统发送kAudioSessionProperty_AudioRouteChanges在inID参数。


inData参数包含一个CFDictionaryRef对象,用来描述:


1)为什么route changed?


2)上一个route是什么?


这个字典的key在Audio Route Change Dictionary Keys中描述。route changed的原因通过kAudioSession_AudioRouteChangeKey_Reason键来获得,这个键在Audio Session Route Change Reasons中描述。上一个route通过键kAudioSession_AudioRouteChangeKey_OldRoute键来获得,其值为一个字符串,例如”Headphone“或”Speaker“。



提供给回调函数的信息一般足够你决定采取什么动作。例如,如果route change的原因是kAudioSessionRouteChangeReason_OldDeviceUnavailable和前一个route是Headphone,你就知道用户指示拔出了耳机。如果你还需要指导什么是新的route,那么在你的回调函数中调用AudioSessionGetProperty函数获得kAudioSessionProperty_AudioRoute属性的值。



在IOS中有一种Audio route change的原因是kAudioSessionRouteChangeReason_CategoryChange。显然如果你只想处理耳机的插入和拔出,那就应该忽略这种类型的route change。



六、设备硬件的优化:


通过使用Audio Session的属性,你可以在运行时优化你的设备硬件的Audio行为。这让你的代码可以采用设备的特性。


Audio Session属性机制允许你:


1)指定优先的硬件设置 采样率和I/O buffer duration。


2)查询很多硬件特性,包括输入和输出的延迟、输入和输出的channel计数‘硬件采样率’硬件音量设置 和是否音频输入可用。


3)写回调函数来响应属性更改事件。


最常使用的属性更改事件是route changes。你还可以写回调函数来监听硬件输出音量的更改、音频输入的可用性更改。



1、指定优先的硬件设置:


1)优先的采样率:例如44.1khz和8khz,越高则标识更高的音频质量和更大的文件尺寸


2)优先的I/O buffer duration:例如500mS和5mS,越高则标识更少的硬盘访问和更长的延迟。


根据你的应用的需要设置相应的采样率和I/O buffer duration。


要设置硬件Preferences,使用AudioSessionSetProperty函数,使用kAudioSessionProperty_PreferredHardwareSampleRate和kAudioSessionProperty_PreferredHardwareIOBufferDuration属性标识符。


重要提示:虽然你可以在Audio Session初始化后,安全地在任何时间指定硬件Preferences,但是最好的体验是在Session 不活跃时就设置好。在你设置好Hardware Preferences之后,激活Audio Session,然后查询其获得实际的值。这最后的一步非常重要,因为系统可能不能提供你请求的东西。



2、查询硬件特性:


你的Audio Session可以告诉你许多设备硬件特性。这些特性可以在运行时更改。例如,在用户插入耳机后,采样率可能你会发生改变。有些特性的更改有回调函数可以监听。对于其他属性,可以直接查询。


重要提示:要获得有意义的硬件特性,需要确保你的Audio Session已经被初始化并且是活跃的。


一些很游泳的Audio Session硬件属性如下所示:


1)kAudioSesssionProperty_CurrentHardwareSampleRate:这个属性没有回调函数。


2)kAudioSessionProperty_CurrentHardwareOutputVolume:设备音量


3)kAudioSessionProperty_CurrentHardwareOutputLatency:输出延迟,没有回调函数


4)kAudioSessionProperty_AudioInputAvailable:使用这个属性来确定是否可以录音。


全部的Audio Session Property在Audio Session Services Reference中描述,在Audio Session Services Property Identifiers枚举中。



3、响应属性更改事件:



七、使用Movies和iPod Music工作


Movie Player使你能播放电影--通过文件或网络流。Music Player使你能播放用户的iPod Library中的音频内容。要使用这些对象,你必须考虑它们的Audio Session特性。


1)Music Player(MPMusicPlayerController类的实例)总是使用一个系统提供的Audio Session


2)Movie Player(MPMoviePlayerController类的实例)默认使用你的应用的Audio Session,但是你可以配置其使用系统提供的Audio Session。


重要提示:在IOS3.1.3之前,一个Movie Player总是使用系统提供的Audio Session。要在IOS3.2之后也获得相同的行为,你需要设置Movie Player的useApplicationAudioSession属性为NO。



1、使用Music Player工作:


要播放用户的iPod Library中的音频和你自己的声音,你必须试用一个所谓的可混合的Category。有两个方法来配置Audio Session为可混合的:


1)使用AVAudioSessionCategoryAmbient


2)使用可混合的Category override Property  kAudioSessionProperty_OverrideCategoryMixWithOthers,来使非可混合的Playback Category变得可混合。



因为你使用了一个可混合的Category,因此你不能访问硬件编码器来播放和录音。


系统自动为Music Player处理Route changes和中断。你不能影响这个内置的行为。如果已经正确配置了你的Audio Session,那么你可以信赖Music Player处理插入耳机、alarm响起或电话来到事件。


你可以配置你的Audio Session,当你的Application播放时,Music Player的sound声音变小。



2、使用Movie Players工作


默认地,Movie Player共享你的应用的Audio Session。也可以通过设置起useApplicationAudioSession属性为NO,来使用系统提供的Audio Session。


使用Movie Player时,配置Audio Session


1)播放电影时让所有其他音频都静音:


     a)如果你的应用不自己播放音频,那就不需要配置Audio Session。


     b)如果你的应用播放音频,配置一个Audio Session并且根据你是否想混合iPod和其他Audio来设置你的Audio Session的可混合性。


     c)在任何一种情形下,告诉Movie Player使用其自己的Audio Session:myMoviePlayer.useApplicationAudioSession=NO;


2)Movie和Application Audio mix,但是其他Audio,包括iPod,都被静音了。


    a)配置一个Audio Session,使用非可混合的Category。


    b)设置Movie Player的Audio Session使用应用的AudioSession:myMoviePlayer.useApplicationAudioSession=YES;


3)所有的音频都混合:


    a)配置Audio Session为可混合的Category。


    b)设置Movie Player的Audio Session使用应用的AudioSession:myMoviePlayer.useApplicationAudioSession=YES;



八、Audio Session Cookbook


1、初始化一个Audio Session:


如果使用AV Foundation代理方法来处理Audio 中断,你可以隐式初始化AudioSession。


如果使用C-based回调函数来处理Audio 中断。需要显式初始化Audio Session,使用AudioSessionInitialize函数。并注册中断处理回调函数。


例子,初始化一个Session和注册一个中断回调


AudioSessionInitialize ( 

    NULL,                            // 1 

    NULL,                            // 2 

    interruptionListenerCallback,    // 3 

    userData                         // 4 

); 

1)第一个参数为NULL,标识使用默认的(main)run loop 

2)第二个参数为NULL,标识使用Default run loop mode 

3)第三个参数为中断处理回调函数 

4)第四个参数为传递给回调函数的数据。 



2、激活和去激活Audio Session 

激活Audio Session: 

NSError *activationError = nil; 

[[AVAudioSession sharedInstance] setActive: YES error: &activationError]; 

//去激活就是传递参数No给 setActive 


//C-based函数来激活、去激活AudioSession 

OSStatus activationResult=NULL; 

result=AudioSessionSetActivie(true);//or false 


3、设置Category: 

Objective-C界面 使用setCategory:error: 

NSError *setCategoryError = nil; 

[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: &setCategoryError]; 

if (setCategoryError) { /* handle the error condition */ } 


C-based界面 使用Audio Session Services的 

UInt32 sessionCategory = kAudioSessionCategory_AmbientSound;    // 1 

  

AudioSessionSetProperty ( 

    kAudioSessionProperty_AudioCategory,                        // 2 

    sizeof (sessionCategory),                                   // 3 

    &sessionCategory                                            // 4 

); 

1)第一步:声明一个新的UInt32类型的变量并初始化其为Category标识符。 

2)第二步:设置AudioSession的Category属性。 

3)第三步:属性值的尺寸 

4)第四步:你想要设置的SessionCategory。 


4、在应用启动时检查其他Audio是否正在播放: 

UInt32 otherAudioIsPlaying;                                   // 1 

UInt32 propertySize = sizeof (otherAudioIsPlaying); 

  

AudioSessionGetProperty (                                     // 2 

    kAudioSessionProperty_OtherAudioIsPlaying, 

    &propertySize, 

    &otherAudioIsPlaying 

); 

  

if (otherAudioIsPlaying) {                                    // 3 

    [[AVAudioSession sharedInstance]  setCategory: AVAudioSessionCategoryAmbient  error: nil]; 

} else { 

    [[AVAudioSession sharedInstance]   setCategory: AVAudioSessionCategorySoloAmbient  error: nil]; 

}



1)定义一个变量来准备存储Audio Session的kAudioSessionProperty_OtherAudioIsPlaying属性的值


2)获得kAudioSessionProperty_OtherAudioIsPlaying的值,并将其指定给otherAudioIsPlaying变量。


3)设置不同的Category。



5、修改Playback mixing behavior:


两个在一般情况下静音其他Audio的播放Category,可以被修改为支持混合。它们是AVAudioSessionCategoryPlayback和AVAudioSessionCategory_PlayAndRecord。要允许混合,你需要设置一个特定的Audio Session Property:


OSStatus propertySetError = 0; 

UInt32 allowMixing = true; 

  

propertySetError = AudioSessionSetProperty ( 

                       kAudioSessionProperty_OverrideCategoryMixWithOthers,  // 1 

                       sizeof (allowMixing),                                 // 2 

                       &allowMixing                                          // 3 

                   ); 

1)你想设Audio Session的属性的标识符 或者叫做键。 

2)值的长度 

3)要设置的属性值 

在设置完之后要检查是否设置成功或失败,并且作出适当的响应。 


6、确保在屏幕锁定时Audio继续播放: 

你需要设置合适的Category。如果你使用Audio unit来播放,你可能还需要配置Audio Units。 

你不能依赖默认的Audio Session,AVAudioSessionCategorySoloAmbient。 

使用AVAudioSessionCategoryPlayback Category。 


7、配置Audio Unit,在屏幕锁定时继续播放 

8、优化最小化的Power Consumption: 

你需要调整你正在使用的Audio Unit的kAudioProperty_MaximumFramesPerSlice属性的值。 

默认地,系统调用I/O unit的render 回调,使用一个slice size 1024 frames。 

设置一个Audio unit的Maximum-frames-per-slice Property 

UInt32 maximumFramesPerSlice = 4096; 

  

AudioUnitSetProperty ( 

    mixerUnit, 

    kAudioUnitProperty_MaximumFramesPerSlice, 

    kAudioUnitScope_Global, 

    0,                        // global scope always uses element 0 

    &maximumFramesPerSlice, 

    sizeof (maximumFramesPerSlice) 

); 


9、Optimizing for Low Latency: 

10、重定向Output Audio: 

有两个方法: 

1)使用一个Category routing Override。 

2)更改默认的Output route。在下次设置Category之前这会一直生效。 


下面显示了使用Category routing Override的例子,在执行这段代码之前,你需要设置Audio Session Category为AVAudioSessionCategoryRecord: 

UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;  // 1 

  

AudioSessionSetProperty ( 

    kAudioSessionProperty_OverrideAudioRoute,                         // 2 

    sizeof (audioRouteOverride),                                      // 3 

    &audioRouteOverride                                               // 4 

); 

1)定义重定向输出音频的标识符 

2)要修改的属性的键 

3)属性值的长度 

4)属性值 


下面的例子是修改默认的Output Audio route: 

UInt32 doChangeDefaultRoute = 1; 

  

AudioSessionSetProperty ( 

    kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, 

    sizeof (doChangeDefaultRoute), 

    &doChangeDefaultRoute 

); 


11、支持Bluetooth Audio Input: 

// First, set an audio session category that allows input. Use the 

//    AVAudioSessionCategoryRecord or the equivalent kAudioSessionCategory_Record 

//    category, or the AVAudioSessionCategoryPlayAndRecord or the equivalent 

//    kAudioSessionCategory_PlayAndRecord category. Then proceed as shown here: 

  

UInt32 allowBluetoothInput = 1; 

  

AudioSessionSetProperty ( 

    kAudioSessionProperty_OverrideCategoryEnableBluetoothInput, 

    sizeof (allowBluetoothInput), 

    &allowBluetoothInput 

); 


12、响应Audio Session的中断: 

i)使用AVAudioSessionDelegate: 

- (void) beginInterruption { 

    if (playing) { 

        playing = NO; 

        interruptedWhilePlaying = YES; 

        [self updateUserInterface]; 

    } 

} 

  

NSError *activationError = nil; 

- (void) endInterruption { 

    if (interruptedWhilePlaying) { 

        [[AVAudioSession sharedInstance] setActive: YES error: &activationError]; 

        [player play]; 

        playing = YES; 

        interruptedWhilePlaying = NO; 

        [self updateUserInterface]; 

    } 

} 


ii)AVAudioPlayer的中断代理: 

- (void) audioPlayerBeginInterruption: (AVAudioPlayer *) player { 

    if (playing) { 

        playing = NO; 

        interruptedOnPlayback = YES; 

        [self updateUserInterface]; 

    } 

} 


- (void) audioPlayerEndInterruption: (AVAudioPlayer *) player { 

    if (interruptedOnPlayback) { 

        [player prepareToPlay]; 

        [player play]; 

        playing = YES; 

        interruptedOnPlayback = NO; 

    } 

}


iii)定义中断方法:


一个中断方法的例子:


- (void) resumePlayback { 

    UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;  // 1 

    AudioSessionSetProperty (                                      // 2 

        kAudioSessionProperty_AudioCategory,                       // 3 

        sizeof (sessionCategory),                                  // 4 

        &sessionCategory                                           // 5 

    ); 

    AudioSessionSetActive (true);                                  // 6 

    [self.audioPlayer resume];                                     // 7 

} 


1)定义一个Category标识符 

2)设置Audio Session的属性 

3)设置Audio Session的Category属性 

4)属性值的长度 

5)属性值 

6)重新激活Audio Session 

7)调用AudioPlayer的resume方法。 


iv)定义一个中断监听回调函数: 

void interruptionListenerCallback ( 

    void    *inUserData,                                                // 1 

    UInt32  interruptionState                                           // 2 

) { 

    AudioViewController *controller = (AudioViewController *) inUserData;                             // 3 

  

    if (interruptionState == kAudioSessionBeginInterruption) {          // 4 

        if (controller.audioRecorder) { 

            [controller recordOrStop: (id) controller];                 // 5 

        } else if (controller.audioPlayer) { 

            [controller pausePlayback];                                 // 6 

            controller.interruptedOnPlayback = YES;                     // 7 

        } 

    } else if ((interruptionState == kAudioSessionEndInterruption) && controller.interruptedOnPlayback) { // 8 

        [controller resumePlayback]; 

        controller.interruptedOnPlayback = NO; 

    } 

}


v)注册中断回调到Audio Session:



13、使用OpenAL时响应中断: