iOS开发技术图像音频flutter

iOS AVAudioSession 详解

2021-07-09  本文已影响0人  新生代农民工No1

AVAudioSession

简要说说AVAudioSession,AVAudioSession是苹果用来管理App对音频硬件(I / O)的资源使用;比如说:

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

AVAudioSession 激活

/* 设置为激活或者失活。激活音频会话是一个同步(阻塞)操作 */
- (BOOL)setActive:(BOOL)active 
        error:(NSError * _Nullable *)outError;
/* 调用该方法 通知中断的应用程序中断已经结束,它可以恢复播放,仅在会话停用时有效
 active:NO
 options:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation  */
- (BOOL)setActive:(BOOL)active withOptions:(AVAudioSessionSetActiveOptions)options error:(NSError **)outError;

AVAudioSession 硬件设置

/* 首选硬件采样率 */
- (BOOL)setPreferredSampleRate:(double)sampleRate error:(NSError **)outError
/* 首选的硬件IO缓冲区持续时间(以秒为单位) */
- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration error:(NSError **)outError
// 输入通道数
- (BOOL)setPreferredInputNumberOfChannels:(NSInteger)count error:(NSError **)outError
// 输出通道数
- (BOOL)setPreferredOutputNumberOfChannels:(NSInteger)count error:(NSError **)outError
// 设置立体声方向
- (BOOL)setPreferredInputOrientation:(AVAudioStereoOrientation)orientation error:(NSError **)outError
// 使用此方法可临时覆盖内置扬声器的输出
- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride error:(NSError **)outError
设置音频输出方式

当iPhone接入多个外部设备时,AudioSeesion将遵循last-in wins原则(后入为主),即声音将被导向到最后接入的设备。在没有接入任何设备时,一般情况下声音会默认从扬声器发出,但有一个例外:在使用AVAudioSessionCategoryPlayAndRecord这种category下,听筒成为默认的输出设备。
如果需要改变扬声器的输出,有以下几种方式:

区别参照苹果文档

AVAudioSessionCategory

在AVAudioSession中可以设置Category和Option,每一种Category都对应是否支持以下几种能力:

Category Play Record MixWithOther Silenced
AVAudioSessionCategoryAmbient
AVAudioSessionCategorySoloAmbient
AVAudioSessionCategoryPlayback 可选,默认❌
AVAudioSessionCategoryRecord
AVAudioSessionCategoryPlayAndRecord 可选,默认❌
AVAudioSessionCategoryAudioProcessing
AVAudioSessionCategoryMultiRoute
/* set session category */
- (BOOL)setCategory:(AVAudioSessionCategory)category error:(NSError **)outError API_AVAILABLE(ios(3.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
/* set session category with options */
- (BOOL)setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(6.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
/* set session category and mode with options */
- (BOOL)setCategory:(AVAudioSessionCategory)category mode:(AVAudioSessionMode)mode options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0)) API_UNAVAILABLE(macos);
/* set session category, mode, routing sharing policy, and options */
- (BOOL)setCategory:(AVAudioSessionCategory)category mode:(AVAudioSessionMode)mode routeSharingPolicy:(AVAudioSessionRouteSharingPolicy)policy options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(11.0), tvos(11.0), watchos(5.0)) API_UNAVAILABLE(macos);

注意:设置category要考虑设置失败的情况

AVAudioSessionMode

AVAudioSessionMode Category Scene
AVAudioSessionModeDefault All 默认
AVAudioSessionModeVoiceChat AVAudioSessionCategoryPlayAndRecord VoIP (语音通话)
AVAudioSessionModeGameChat AVAudioSessionCategoryPlayAndRecord 游戏模式
AVAudioSessionModeVideoRecording AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayAndRecord 适用于使用摄像头采集视频的应用
AVAudioSessionModeMeasurement AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayAndRecord 最小化系统
AVAudioSessionModeMoviePlayback AVAudioSessionCategoryPlayback 视频播放
AVAudioSessionModeVideoChat AVAudioSessionCategoryPlayback、AVAudioSessionCategoryPlayAndRecord 视频通话
AVAudioSessionModeSpokenAudio AVAudioSessionCategorySoloAmbient、AVAudioSessionCategoryPlayback、AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryMultiRoute 有声读物
AVAudioSessionModeVoicePrompt - 语音提示

AVAudioSessionCategoryOptions

AVAudioSessionCategoryOption Function Describe Supports Category
AVAudioSessionCategoryOptionMixWithOthers 支持混音 AVAudioSessionCategoryPlayback AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionDuckOthers 降低其他应用的音量 AVAudioSessionCategoryPlayback AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionAllowBluetooth 支持蓝牙音频输入 AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayAndRecord
AVAudioSessionCategoryOptionDefaultToSpeaker 设置默认输出到扬声器 AVAudioSessionCategoryPlayAndRecord
AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers 音频播放过程中,支持中断其他应用 AVAudioSessionCategoryPlayback AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryMultiRoute
AVAudioSessionCategoryOptionAllowBluetoothA2DP 支持立体声蓝牙 AVAudioSessionCategoryAmbient AVAudioSessionCategorySoloAmbient AVAudioSessionCategoryPlayback AVAudioSessionCategoryPlayAndRecord
AVAudioSessionCategoryOptionAllowAirPlay 支持远程AirPlay AVAudioSessionCategoryPlayAndRecord

注意: 如果应用中使用到MPNowPlayingInfoCenter,最好避免设置AVAudioSessionCategoryOptionMixWithOthers;因为一旦设置了这个值之后,那么MPNowPlayingInfoCenter就不能正常显示信息

AVAudioSessionRouteSharingPolicy

路由策略:

AVAudioSessionNotification

AVAudioSession有以下多个通知来提示用户事件;

AVAudioSessionInterruptionNotification

当App内音频被中断,系统会将AudioSession置为失活状态,音频也会因此立即停止。当一个别的App的AudioSession被激活并且它的类别未设置与系统类别或你应用程序类别混合时,中断就会发生。你的应用程序在收到中断通知后应该保存当时的状态,以及更新用户界面等相关操作。通过注册AVAudioSessionInterruptionNotification通知,可以处理中断的开始和结束。

/* keys for AVAudioSessionInterruptionNotification */
/* Value is an NSNumber representing an AVAudioSessionInterruptionType */
AVAudioSessionInterruptionTypeKey
typedef NS_ENUM(NSUInteger, AVAudioSessionInterruptionType)
{
    AVAudioSessionInterruptionTypeBegan = 1,  /* the system has interrupted your audio session */
    AVAudioSessionInterruptionTypeEnded = 0,  /* the interruption has ended */
};
  
/* Only present for end interruption events.  Value is of type AVAudioSessionInterruptionOptions.*/
AVAudioSessionInterruptionOptionKey
typedef NS_OPTIONS(NSUInteger, AVAudioSessionInterruptionOptions)
{
    AVAudioSessionInterruptionOptionShouldResume = 1
};

提示:这里的通知的中断开始和中断结束不一定都会出现(苹果文档中有提到)

AVAudioSessionRouteChangeNotification

当用户连接或者断开音频输入,输出设备时(插拔耳机、或者蓝牙耳机的断开、连接),音频线路发生变更,通过注册AVAudioSessionRouteChangeNotification通知,可以在音频线路发生变更时做出相应处理。

/* keys for AVAudioSessionRouteChangeNotification */
/* value is an NSNumber representing an AVAudioSessionRouteChangeReason */
AVAudioSessionRouteChangeReasonKey
typedef NS_ENUM(NSUInteger, AVAudioSessionRouteChangeReason)
{
    AVAudioSessionRouteChangeReasonUnknown = 0,
    AVAudioSessionRouteChangeReasonNewDeviceAvailable = 1,  //设备可用(耳机插好)
    AVAudioSessionRouteChangeReasonOldDeviceUnavailable = 2, //设备不可用(耳机被拔下)
    AVAudioSessionRouteChangeReasonCategoryChange = 3, //  设置的分类被改变
    AVAudioSessionRouteChangeReasonOverride = 4,            //  路由被覆盖
    AVAudioSessionRouteChangeReasonWakeFromSleep = 6,  // 设备被激活
    AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory = 7, //当前类别没有路由时返回
    AVAudioSessionRouteChangeReasonRouteConfigurationChange = 8 // added in iOS 7
};

AVAudioSessionSilenceSecondaryAudioHintNotification

当来自其他应用的主音频启动,或者停止时,通过注册AVAudioSessionSilenceSecondaryAudioHintNotification通知,前台应用可以作为启动或者禁用次要音频的提示;

/* keys for AVAudioSessionSilenceSecondaryAudioHintNotification */
/* value is an NSNumber representing an AVAudioSessionSilenceSecondaryAudioHintType */
AVAudioSessionSilenceSecondaryAudioHintTypeKey 
typedef NS_ENUM(NSUInteger, AVAudioSessionSilenceSecondaryAudioHintType)
{
    AVAudioSessionSilenceSecondaryAudioHintTypeBegin = 1,  /* the system is indicating that another application's primary audio has started */
    AVAudioSessionSilenceSecondaryAudioHintTypeEnd = 0,    /* the system is indicating that another application's primary audio has stopped */
};

AVAudioSession 常用音频建议

使用AVAudioSessionCategoryRecordAVAudioSessionCategoryPlayAndRecordAVAudioSessionCategoryPlayback类别的APP,苹果建议的准则如下:

AVAudioSession 声音常用处理

[[AudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:0 error:&error];
[[AudioSession sharedInstance] setActive:YES error:&error];
[[AudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
/* start */ 
[[AudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionDuckOthers error:&error];

/* end */ 
[[AudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
[[AudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];

参考文档

上一篇 下一篇

猜你喜欢

热点阅读