// // XHVoiceRecordHelper.m // MessageDisplayExample // // Created by HUAJIE-1 on 14-5-13. // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved. // #import #import "XHVoiceRecordHelper.h" #import "XHMacro.h" #import "SVProgressHUD.h" #import "JLAuthorizationManager.h" #import "myHelper.h" @interface XHVoiceRecordHelper () { NSTimer *_timer; BOOL _isPause; #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE UIBackgroundTaskIdentifier _backgroundIdentifier; #endif } @property (nonatomic, copy, readwrite) NSString *recordPath; @property (nonatomic, readwrite) NSTimeInterval currentTimeInterval; @end @implementation XHVoiceRecordHelper - (id)init { self = [super init]; if (self) { self.maxRecordTime = kVoiceRecorderTotalTime; self.recordDuration = @(0); #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE _backgroundIdentifier = UIBackgroundTaskInvalid; #endif } return self; } - (void)dealloc { [self stopRecord]; self.recordPath = nil; [self stopBackgroundTask]; } - (void)startBackgroundTask { [self stopBackgroundTask]; #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE _backgroundIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [self stopBackgroundTask]; }]; #endif } - (void)stopBackgroundTask { #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE if (_backgroundIdentifier != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:_backgroundIdentifier]; _backgroundIdentifier = UIBackgroundTaskInvalid; } #endif } - (void)resetTimer { if (!_timer) return; if (_timer) { [_timer invalidate]; _timer = nil; } } - (void)cancelRecording { if (!_recorder) return; if (self.recorder.isRecording) { [self.recorder stop]; } self.recorder = nil; } - (void)stopRecord { [self cancelRecording]; [self resetTimer]; } - (BOOL)canRecord { __block BOOL bCanRecord = NO; JLAuthorizationManager *jlManager = [JLAuthorizationManager defaultManager]; [jlManager JL_requestAuthorizationWithAuthorizationType:JLAuthorizationTypeAudio authorizedHandler:^{ bCanRecord = YES; } unAuthorizedHandler:^{}]; return bCanRecord; } - (void)prepareRecordingWithPath:(NSString *)path prepareRecorderCompletion:(XHPrepareRecorderCompletion)prepareRecorderCompletion { WEAKSELF JLAuthorizationManager *jlManager = [JLAuthorizationManager defaultManager]; [jlManager JL_requestAuthorizationWithAuthorizationType:JLAuthorizationTypeAudio authorizedHandler:nil unAuthorizedHandler:^{ LGAlertView *alertView = [[LGAlertView alloc] initWithTitle:[NSString stringWithFormat:@"请为%@打开麦克风权限",APPName] message:nil style:LGAlertViewStyleAlert buttonTitles:@[@"确定"] cancelButtonTitle:@"取消" destructiveButtonTitle:nil actionHandler:^(LGAlertView *alertView, NSString *title, NSUInteger index) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; } cancelHandler:^(LGAlertView *alertView) { } destructiveHandler:nil]; [alertView showAnimated:YES completionHandler:nil]; }]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ _isPause = NO; NSError *error = nil; AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&error]; if(error) { DLog(@"audioSession: %@ %ld %@", [error domain], (long)[error code], [[error userInfo] description]); return; } error = nil; [audioSession setActive:YES error:&error]; if(error) { DLog(@"audioSession: %@ %ld %@", [error domain], (long)[error code], [[error userInfo] description]); return; } //MARK: 设置录音设置 NSDictionary * recordSetting = @{ AVSampleRateKey:[NSNumber numberWithFloat:8000.0], //采样率 AVFormatIDKey:[NSNumber numberWithInt:kAudioFormatLinearPCM], AVLinearPCMBitDepthKey:[NSNumber numberWithInt:16],//采样位数 默认 16 AVNumberOfChannelsKey:[NSNumber numberWithInt:2],//通道的数目 AVEncoderBitRateKey:[NSNumber numberWithFloat:128000], // [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey]; // [recordSetting setValue:[NSNumber numberWithFloat:16000.0] forKey:AVSampleRateKey]; // [recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey]; // AVEncoderAudioQualityKey: [NSNumber numberWithInt: AVAudioQualityMax],//音频编码质量 AVEncoderAudioQualityKey: [NSNumber numberWithInt: AVAudioQualityHigh],//音频编码质量 }; // MARK: 乐家守护录音设置参数 NSDictionary *recordSetting2 = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithFloat: 8000.0],AVSampleRateKey, //采样率 [NSNumber numberWithInt: kAudioFormatLinearPCM],AVFormatIDKey, [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,//采样位数 默认 16 [NSNumber numberWithInt: 1], AVNumberOfChannelsKey,//通道的数目 // [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,//大端还是小端 是内存的组织方式 // [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,//采样信号是整数还是浮点数 // [NSNumber numberWithInt: AVAudioQualityMedium],AVEncoderAudioQualityKey,//音频编码质量 nil]; if (weakSelf) { STRONGSELF strongSelf.recordPath = path; error = nil; if (strongSelf.recorder) { [strongSelf cancelRecording]; } else { strongSelf.recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:strongSelf.recordPath] settings:recordSetting2 error:&error]; strongSelf.recorder.delegate = strongSelf; [strongSelf.recorder prepareToRecord]; strongSelf.recorder.meteringEnabled = YES; [strongSelf.recorder recordForDuration:(NSTimeInterval) 160]; [strongSelf startBackgroundTask]; } if(error) { DLog(@"audioSession: %@ %ld %@", [error domain], (long)[error code], [[error userInfo] description]); return; } dispatch_async(dispatch_get_main_queue(), ^{ //上層如果傳會來說已經取消了, 那這邊就做原先取消的動作 if (!prepareRecorderCompletion()) { [strongSelf cancelledDeleteWithCompletion:^{ }]; } }); } }); } - (void)startRecordingWithStartRecorderCompletion:(XHStartRecorderCompletion)startRecorderCompletion { if ([_recorder record]) { [self resetTimer]; _timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateMeters) userInfo:nil repeats:YES]; if (startRecorderCompletion) dispatch_async(dispatch_get_main_queue(), ^{ startRecorderCompletion(); }); } } - (void)resumeRecordingWithResumeRecorderCompletion:(XHResumeRecorderCompletion)resumeRecorderCompletion { _isPause = NO; if (_recorder) { if ([_recorder record]) { dispatch_async(dispatch_get_main_queue(), resumeRecorderCompletion); } } } - (void)pauseRecordingWithPauseRecorderCompletion:(XHPauseRecorderCompletion)pauseRecorderCompletion { _isPause = YES; if (_recorder) { [_recorder pause]; } if (!_recorder.isRecording) dispatch_async(dispatch_get_main_queue(), pauseRecorderCompletion); } - (void)stopRecordingWithStopRecorderCompletion:(XHStopRecorderCompletion)stopRecorderCompletion { _isPause = NO; [self stopBackgroundTask]; [self stopRecord]; [self getVoiceDuration:_recordPath]; dispatch_async(dispatch_get_main_queue(), stopRecorderCompletion); } - (void)cancelledDeleteWithCompletion:(XHCancellRecorderDeleteFileCompletion)cancelledDeleteCompletion { _isPause = NO; [self stopBackgroundTask]; [self stopRecord]; if (self.recordPath) { // 删除目录下的文件 NSFileManager *fileManeger = [NSFileManager defaultManager]; if ([fileManeger fileExistsAtPath:self.recordPath]) { NSError *error = nil; [fileManeger removeItemAtPath:self.recordPath error:&error]; if (error) { DLog(@"error :%@", error.description); } dispatch_async(dispatch_get_main_queue(), ^{ cancelledDeleteCompletion(error); }); } else { dispatch_async(dispatch_get_main_queue(), ^{ cancelledDeleteCompletion(nil); }); } } else { dispatch_async(dispatch_get_main_queue(), ^{ cancelledDeleteCompletion(nil); }); } } - (void)updateMeters { if (!_recorder) return; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [_recorder updateMeters]; self.currentTimeInterval = _recorder.currentTime; if (!_isPause) { float progress = self.currentTimeInterval / self.maxRecordTime * 1.0; dispatch_async(dispatch_get_main_queue(), ^{ if (_recordProgress) { _recordProgress(progress); } }); } float peakPower = [_recorder averagePowerForChannel:0]; double ALPHA = 0.015; double peakPowerForChannel = pow(10, (ALPHA * peakPower)); dispatch_async(dispatch_get_main_queue(), ^{ // 更新扬声器 if (_peakPowerForChannel) { _peakPowerForChannel(peakPowerForChannel); } }); if (self.currentTimeInterval > self.maxRecordTime) { [self stopRecord]; dispatch_async(dispatch_get_main_queue(), ^{ _maxTimeStopRecorderCompletion(); }); } }); } - (void)getVoiceDuration:(NSString*)recordPath { NSError *error = nil; AVAudioPlayer *play = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:recordPath] error:&error]; if (error) { DLog(@"recordPath:%@ error:%@", recordPath, error); self.recordDuration = @(0); } else { DLog(@"时长:%f", play.duration); self.recordDuration = @(play.duration); } } @end