本例子使用Core Audio實現類似於微信的音頻對講功能,可以錄音和播放並且實現了聽筒模式和揚聲器模式的切換。錄音主要使用AVAudioRecorder類來實現錄音功能,播放則使用AVAudioPlayer類來實現播放音頻功能,揚聲器和聽筒模式的切換是通過設置AVAudioSession類的屬性值來實現切換效果。
- (void)viewDidLoad
{
[super viewDidLoad];
//創建錄音按鈕
UIButton* recorderB = [[[UIButton alloc]initWithFrame:CGRectMake(20, 220, 60, 40)]autorelease];
[recorderB setTitle:@"record" forState:UIControlStateNormal];
[recorderB setBackgroundColor:[UIColor grayColor]];
[recorderB addTarget:self action:@selector(prerecord:) forControlEvents:UIControlEventTouchDown];
[recorderB addTarget:self action:@selector(startrecord:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:recorderB];
//創建播放按鈕
UIButton* play = [[[UIButton alloc]initWithFrame:CGRectMake(230, 220, 60, 40)]autorelease];
[play setTitle:@"play" forState:UIControlStateNormal];
[play setBackgroundColor:[UIColor grayColor]];
[play addTarget:self action:@selector(play:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:play];
//創建聽筒模式和揚聲器模式切換按鈕
change = [[[UISwitch alloc]initWithFrame:CGRectMake(120, 225, 40, 40)]autorelease];
//默認設置爲沒有打開,則用聽筒模式
[change setOn:NO];
[change addTarget:self action:@selector(change:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:change];
}
//切換按鈕事件
-(void)change:(UISwitch*)sender{
NSLog(@"%@",NSStringFromSelector(_cmd));
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
if ([sender isOn]) {
//設置下揚聲器模式
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
}else{
//設置聽筒模式
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
}
[audioSession setActive:YES error:nil];
}
//錄音事件
-(void)record:(id)sender{
//獲取當前應用的AudioSession,每個應用都有自己唯一的聲頻會話
AVAudioSession * audioSession = [AVAudioSession sharedInstance];
NSError* error1;
//設置當前應用的聲頻會話爲錄音模式
/*
Use this category for background sounds such as rain, car engine noise, etc.
Mixes with other music.
AVF_EXPORT NSString *const AVAudioSessionCategoryAmbient;
Use this category for background sounds. Other music will stop playing. AVF_EXPORT NSString *const AVAudioSessionCategorySoloAmbient;
Use this category for music tracks.
AVF_EXPORT NSString *const AVAudioSessionCategoryPlayback;
Use this category when recording audio.
AVF_EXPORT NSString *const AVAudioSessionCategoryRecord;
Use this category when recording and playing back audio.
AVF_EXPORT NSString *const AVAudioSessionCategoryPlayAndRecord;
Use this category when using a hardware codec or signal processor while
not playing or recording audio.
AVF_EXPORT NSString *const AVAudioSessionCategoryAudioProcessing;
*/
[audioSession setCategory:AVAudioSessionCategoryRecord error: &error1];
//激活音頻會話
[audioSession setActive:YES error: &error1];
NSLog(@"record...");
//創建錄音的文件保存位置
NSString* filepath = [DOCUMENT_PATH stringByAppendingPathComponent:@"test.caf"];
url = [[NSURL fileURLWithPath:filepath]retain];
NSLog(@"path:%@",filepath);
//設置錄音的相關屬性
NSMutableDictionary *settings = [[NSMutableDictionary alloc] init];
//設置音頻格式
[settings
setValue:[NSNumber numberWithInteger:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
//設置採用率
[settings
setValue:[NSNumber numberWithFloat:44100.0f] forKey:AVSampleRateKey];
//設置頻道
[settings
setValue:[NSNumber numberWithInteger:2] forKey:AVNumberOfChannelsKey];
//設置錄音質量
[settings
setValue:[NSNumber numberWithInteger:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];
NSError* error;
recorder = [[AVAudioRecorder alloc]initWithURL:url settings:settings error:&error];
recorder.delegate = self;
//錄音準備,會爲建立錄音文件做好需要的準備
BOOL isrecord = [recorder prepareToRecord];
NSLog(@"isrecord:%d",isrecord);
//正式開始錄音
[recorder record];
NSLog(@"record begin...");
}
//手指離開點擊錄音按鈕的事件
-(void)startrecord:(id)sender{
NSLog(@"%@",NSStringFromSelector(_cmd));
NSTimeInterval now = [[NSDate date]timeIntervalSince1970];
//獲取長按錄音按鈕的時間
NSTimeInterval offset = now - starttime;
NSLog(@"offset:%f",offset);
//如果長按的時間少於1秒,則不錄音
if (offset<=1) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(record:) object:self];
}else{
//超過一秒,則完成錄音,停止繼續錄音
[self stoprecorder:recorder];
}
}
//手指點擊錄音按鈕時間
-(void)prerecord:(id)sender{
NSLog(@"%@",NSStringFromSelector(_cmd));
//獲取點擊的時間
starttime = [[NSDate date]timeIntervalSince1970];
NSLog(@"starttime:%f",starttime);
//點擊超過一秒後才正式錄音
[self performSelector:@selector(record:) withObject:self afterDelay:1];
}
//停止錄音的事件
-(void)stoprecorder:(AVAudioRecorder*)sender{
NSLog(@"%@",NSStringFromSelector(_cmd));
//判斷是否還在錄音,如果是就停止
if ([recorder isRecording]) {
[recorder stop];
}
}
//播放事件
-(void)play:(id)sender{
NSLog(@"%@",NSStringFromSelector(_cmd));
NSError* error;
NSLog(@"url:%@",url);
//通過AVAudioPlayer打開剛纔錄音的文件
AVAudioPlayer* player = [[AVAudioPlayer alloc]initWithData:[NSData dataWithContentsOfURL:url] error:&error];
//AVAudioPlayer預處理,爲需要播放做好準備
BOOL isplay = [player prepareToPlay];
NSLog(@"isplay:%d",isplay);
// player.volume = 1;
player.delegate = self;
//正式播放
[player play];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//錄音完成後的回調事件
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{
NSLog(@"%@",NSStringFromSelector(_cmd));
//錄音完成後關閉釋放資源
if ([recorder isRecording]) {
[recorder stop];
}
[recorder release];
//錄音的時候因爲設置的音頻會話是錄音模式,所以錄音完成後要把音頻會話設置回聽筒模式或者揚聲器模式,根據切換器的值判斷
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
if ([change isOn]) {
//揚聲器模式
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
}else{
//聽筒模式
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
}
[audioSession setActive:YES error:nil];
}
//錄音編碼出錯的回調
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error{
NSLog(@"%@",NSStringFromSelector(_cmd));
[recorder release];
}
//播放音頻完成後的回調
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
NSLog(@"%@",NSStringFromSelector(_cmd));
//成功播放完音頻後釋放資源
if ([player isPlaying]) {
[player stop];
}
[player release];
}
//音頻播放解碼出錯的回調
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error{
NSLog(@"%@",NSStringFromSelector(_cmd));
[player release];
}