You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

323 lines
12 KiB

//
// 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 <UIKit/UIKit.h>
#import "XHVoiceRecordHelper.h"
#import "XHMacro.h"
//#import "SVProgressHUD.h"
#import "JLAuthorizationManager.h"
#import "myHelper.h"
@interface XHVoiceRecordHelper () <AVAudioRecorderDelegate> {
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(self.currentTimeInterval);
}
});
}
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);
}
});
NSLog(@"----%f",self.currentTimeInterval);
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