一 音頻會(huì)話
音頻會(huì)話:音頻會(huì)話在應(yīng)用程序中扮演中間人的角色,可以通過(guò)音頻會(huì)話來(lái)控制音頻的操作
所有的應(yīng)用程序都有音頻會(huì)話,無(wú)論是否使用
-
音頻會(huì)話分類(
Category):
AVFoundaation定義了七種分類來(lái)描述應(yīng)用程序所使用的音頻行為
(O:可選,Y:支持, N: 不支持)
| 分類 | 作用 | 是否允許混音 | 音頻輸入 | 音頻輸出 |
|---|---|---|---|---|
| Ambient | 游戲,效率工具 | Y | N | Y |
| Solo Ambient(默認(rèn)) | 游戲,效率工具 | N | N | Y |
| PlayBack | 音視頻播放器 | O | N | Y |
| Record | 錄音機(jī),視頻捕捉 | O | Y | N |
| PlayAndRecord | VoIP,語(yǔ)言聊天 | O | Y | Y |
| Audio Progressing | 離線會(huì)話和處理 | N | N | N |
| Muti-Route | 使用外部硬件 | N | Y | Y |
- 設(shè)置音頻會(huì)話分類
//1. 取得音頻會(huì)話單例
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
//2. 設(shè)置音頻會(huì)話分類
if (![session setCategory:AVAudioSessionCategoryPlayback error:&error]) {
NSLog(@"設(shè)置音頻會(huì)話分類失敗%@",[error localizedDescription]);
}
//3. 激活會(huì)話
if([session setActive:YES error:&error]){
NSLog(@"音頻會(huì)話激活失敗%@",[error localizedDescription]);
}
- 使用
AVAudioPlayer播放音頻:AVAudioPlayer 只能播放本地文件
NSURL *filePath = [[NSBundle mainBundle]URLForResource:@"aaa" withExtension:@"mp3"];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:filePath error:nil];
if (audioPlayer) {
[audioPlayer prepareToPlay];//調(diào)用 play 方法的時(shí)候會(huì)自動(dòng)調(diào)用一次
}
[audioPlayer play];//開(kāi)始播放
[audioPlayer pause];//暫停
[audioPlayer stop];//停止
audioPlayer.pan = 0.0; // -1.0 ~ 1.0 立體聲播放
audioPlayer.volume = 0.5; //音量 0.0 ~ 1.0
audioPlayer.numberOfLoops = -1; //循環(huán)播放次數(shù),-1 無(wú)限輪播
pause和stop都會(huì)停止播放,再次調(diào)用play都會(huì)繼續(xù)播放,區(qū)別在于stop會(huì)撤銷prepareToPlay方法所做的設(shè)置,而pause不會(huì)
- 中斷處理
當(dāng)正在播放音頻的時(shí)候,有電話撥入會(huì)導(dǎo)致中斷,中斷發(fā)生的時(shí)候需要對(duì)相應(yīng)狀態(tài)做一些處理
- (void)audioInterruptionNotiSet {
NSNotificationCenter *notiCenter = [NSNotificationCenter defaultCenter];
[notiCenter addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
}
- (void)handleInterruption:(NSNotification *)noti {
NSDictionary *info = noti.userInfo;
AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if (type == AVAudioSessionInterruptionTypeBegan) {
//中斷開(kāi)始時(shí)的處理 正在播放的音頻停止 需要對(duì) UI 設(shè)置停止?fàn)顟B(tài)
}
if (type == AVAudioSessionInterruptionTypeEnded) {
// 中斷結(jié)束的時(shí)候處理, 因?yàn)橹袛嘟Y(jié)束后 原先停止的音頻不會(huì)自動(dòng)恢復(fù) 需要在結(jié)束的時(shí)候設(shè)置
}
}
- 路線改變的處理
iOS 設(shè)置上音頻輸出設(shè)備一般包括麥克風(fēng)和耳機(jī),麥克風(fēng)正在播放音頻的時(shí)候插入耳機(jī).音頻會(huì)改為耳機(jī)輸出,當(dāng)拔出耳機(jī)的時(shí)候,需要暫停音頻播放
- (void)audioRouteChangeNotiSet {
NSNotificationCenter *notiCenter = [NSNotificationCenter defaultCenter];
[notiCenter addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
}
- (void)handRountChange:(NSNotification *)noti {
NSDictionary *info = noti.userInfo;
AVAudioSessionRouteChangeReason reasion = [info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
if (reasion == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
// 當(dāng)輸出路徑改變的時(shí)候,舊有的路徑設(shè)備不可用 的時(shí)候做處理
AVAudioSessionRouteDescription *routeDescription = info[AVAudioSessionRouteChangePreviousRouteKey];
AVAudioSessionPortDescription *portDescription = routeDescription.outputs[0];
NSString *portType = portDescription.portType;
if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {
// 當(dāng)耳機(jī)不可用的時(shí)候,說(shuō)明是拔出耳機(jī) 此時(shí)需要做的處理
}
}
}
- 音頻錄制
音頻錄制需要設(shè)置音頻會(huì)話分類為Record或者PlayAndRecord,需要對(duì)音頻格式進(jìn)行正確設(shè)置匹配輸出文件的后綴名.
NSURL *filePath ; //輸出文件路徑,需指定后綴名
NSDictionary *recordSetting = @{
AVFormatIDKey : @(kAudioFormatMPEG4AAC),
AVSampleRateKey : @(22050.0f),
AVEncoderBitRateKey : @(16),
AVNumberOfChannelsKey : @(1),
AVVideoQualityKey : @(AVAudioQualityMedium)
};
NSError *error;
AVAudioRecorder *audioRecorder = [[AVAudioRecorder alloc]initWithURL:filePath settings:recordSetting error:&error];
[audioRecorder prepareToRecord];
[audioRecorder record];//開(kāi)始錄制
[audioRecorder stop];// 停止錄制
[audioRecorder pause];//暫停
//獲取音頻音量信息
audioRecorder.meteringEnabled = YES;
[audioRecorder updateMeters];
float avgpower = [audioRecorder averagePowerForChannel:0];
float peakpower = [audioRecorder peakPowerForChannel:0];