123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- //
- // AudioRecorder.m
- // mask
- //
- // Created by 翟玉磊 on 2019/1/3.
- // Copyright © 2019 翟玉磊. All rights reserved.
- //
- #import "AudioRecorder.h"
- // 导入录音头文件(注意添加framework:AVFoundation.framework、AudioToolbox.framework)
- #import <AudioToolbox/AudioToolbox.h>
- #import <AVFoundation/AVFoundation.h>
- #import "NSTimer+Weak.h"
- @interface AudioRecorder () <AVAudioRecorderDelegate, AVAudioPlayerDelegate>
- @property (nonatomic, strong) NSTimer *audioRecorderTimer; // 录音音量计时器
- @property (nonatomic, strong) NSMutableDictionary *audioRecorderSetting; // 录音设置
- @property (nonatomic, strong) AVAudioRecorder *audioRecorder; // 录音
- @property (nonatomic, strong) AVAudioPlayer *audioPlayer; // 播放
- @property (nonatomic, assign) double audioRecorderTime; // 录音时长
- @end
- @implementation AudioRecorder
- /// 录音文件保存路径
- NSString *GetFilePathWithDate()
- {
- NSDate *currentDate = [NSDate date];
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- [dateFormatter setDateFormat:@"YYYYMMddHHmmss"];
- NSString *filePath = [dateFormatter stringFromDate:currentDate];
- filePath = [NSString stringWithFormat:@"%@.aac", filePath];
-
- NSString *tmpPath = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp"];
-
- filePath = [tmpPath stringByAppendingFormat:@"/%@",filePath];
-
- return filePath;
- }
- /// 获取文件名(包含后缀,如:xxx.acc;不包含文件类型,如xxx)
- NSString *GetFileNameWithFilePath(NSString *filePath, BOOL hasFileType)
- {
- NSString *fileName = [filePath stringByDeletingLastPathComponent];
- if (hasFileType)
- {
- fileName = [filePath lastPathComponent];
- }
- return fileName;
- }
- /// 获取文件大小
- long long GetFileSizeWithFilePath(NSString *filePath)
- {
- BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
- if (isExist)
- {
- NSDictionary *fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
- long long fileSize = fileDict.fileSize;
- return fileSize;
- }
-
- return 0.0;
- }
- /// 删除文件
- void DeleteFileWithFilePath(NSString *filePath)
- {
- BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
- if (isExist)
- {
- [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
- }
- }
- #pragma mark - 实例化
- - (instancetype)init
- {
- self = [super init];
-
- if (self)
- {
- // 参数设置 格式、采样率、录音通道、线性采样位数、录音质量
- self.audioRecorderSetting = [NSMutableDictionary dictionary];
- [self.audioRecorderSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
- [self.audioRecorderSetting setValue:[NSNumber numberWithInt:11025] forKey:AVSampleRateKey];
- [self.audioRecorderSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
- [self.audioRecorderSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
- [self.audioRecorderSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];
- }
-
- return self;
- }
- /// 录音单例
- + (AudioRecorder *)shareManager
- {
- static AudioRecorder *staticAudioRecorde;
- static dispatch_once_t once;
- dispatch_once(&once, ^{
- staticAudioRecorde = [[self alloc] init];
- });
-
- return staticAudioRecorde;
- }
- // 内存释放
- - (void)dealloc
- {
- // 内存释放前先停止录音,或音频播放
- [self audioStop];
- [self audioRecorderStop];
-
- // 内存释放
- if (self.audioRecorderTime)
- {
- [self.audioRecorderTimer invalidate];
- self.audioRecorderTimer = nil;
- }
-
- if (self.audioRecorderSetting)
- {
- self.audioRecorderSetting = nil;
- }
-
- if (self.audioRecorder)
- {
- self.audioRecorder = nil;
- }
-
- if (self.audioPlayer)
- {
- self.audioPlayer = nil;
- }
- }
- #pragma mark - 音频处理-录音
- /// 开始录音
- - (void)audioRecorderStartWithFilePath:(NSString *)filePath
- {
- // 生成录音文件
- NSURL *urlAudioRecorder = [NSURL fileURLWithPath:filePath];
- self.audioRecorder = [[AVAudioRecorder alloc] initWithURL:urlAudioRecorder settings:self.audioRecorderSetting error:nil];
-
- // 开启音量检测
- [self.audioRecorder setMeteringEnabled:YES];
- [self.audioRecorder setDelegate:self];
-
- if (self.audioRecorder)
- {
- // 录音时设置audioSession属性,否则不兼容Ios7
- AVAudioSession *recordSession = [AVAudioSession sharedInstance];
- [recordSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
- [recordSession setActive:YES error:nil];
-
- if ([self.audioRecorder prepareToRecord])
- {
- [self.audioRecorder record];
-
- // 设置定时检测
- WeakSelf
- self.audioRecorderTimer = [NSTimer scheduledTimerWithTimeInterval:0 event:^(NSTimer * _Nonnull timer) {
- [weakSelf detectionVoice];
- }];
- }
- }
- }
- /// 录音音量显示
- - (void)detectionVoice
- {
- // 刷新音量数据
- [self.audioRecorder updateMeters];
-
- // // 获取音量的平均值
- // [self.audioRecorder averagePowerForChannel:0];
- // // 音量的最大值
- // [self.audioRecorder peakPowerForChannel:0];
-
- double lowPassResults = pow(10, (0.05 * [self.audioRecorder peakPowerForChannel:0]));
- double currentTime = self.audioRecorder.currentTime;
- // NSLog(@"lowPassResults:%.2f", lowPassResults);
-
- if (self.detectionVoiceBlock) {
- self.detectionVoiceBlock(lowPassResults, currentTime);
- }
- }
- /// 停止录音
- - (void)audioRecorderStop
- {
- if (self.audioRecorder)
- {
- if ([self.audioRecorder isRecording])
- {
- // 获取录音时长
- self.audioRecorderTime = [self.audioRecorder currentTime];
- [self.audioRecorder stop];
-
- // 停止录音后释放掉
- self.audioRecorder = nil;
- }
- }
-
- // 释放计时器
- [self.audioRecorderTimer invalidate];
- self.audioRecorderTimer = nil;
- }
- /// 根据录音文件获取录音时长
- - (NSTimeInterval)durationAudioRecorderWithFilePath:(NSString *)filePath
- {
- NSURL *urlFile = [NSURL fileURLWithPath:filePath];
- self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:urlFile error:nil];
- NSTimeInterval time = self.audioPlayer.duration;
- self.audioPlayer = nil;
- return time;
- }
- #pragma mark - 音频处理-播放/停止
- /// 音频开始播放或停止
- - (void)audioPlayWithFilePath:(NSString *)filePath
- {
- if (self.audioPlayer)
- {
- // 判断当前与下一个是否相同
- // 相同时,点击时要么播放,要么停止
- // 不相同时,点击时停止播放当前的,开始播放下一个
- NSString *currentStr = [self.audioPlayer.url relativeString];
-
- // currentStr包含字符"file://location/",通过判断filePath是否为currentPath的子串,是则相同,否则不同
- NSRange range = [currentStr rangeOfString:filePath];
- if (range.location != NSNotFound)
- {
- if ([self.audioPlayer isPlaying])
- {
- [self.audioPlayer stop];
- self.audioPlayer = nil;
- }
- else
- {
- self.audioPlayer = nil;
- [self audioPlayerPlay:filePath];
- }
- }
- else
- {
- [self audioPlayerStop];
- [self audioPlayerPlay:filePath];
- }
- }
- else
- {
- [self audioPlayerPlay:filePath];
- }
-
- }
- /// 音频播放停止
- - (void)audioStop
- {
- [self audioPlayerStop];
- }
- - (BOOL)playing {
- return self.audioPlayer.playing;
- }
- /// 音频播放器开始播放
- - (void)audioPlayerPlay:(NSString *)filePath
- {
- // 判断将要播放文件是否存在
- BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
- if (!isExist)
- {
- return;
- }
-
- NSURL *urlFile = [NSURL fileURLWithPath:filePath];
- self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:urlFile error:nil];
- self.audioPlayer.delegate = self;
- if (self.audioPlayer)
- {
- if ([self.audioPlayer prepareToPlay])
- {
- // 播放时,设置喇叭播放否则音量很小
- AVAudioSession *playSession = [AVAudioSession sharedInstance];
- [playSession setCategory:AVAudioSessionCategoryPlayback error:nil];
- [playSession setActive:YES error:nil];
-
- [self.audioPlayer play];
- }
- }
- }
- /// 音频播放器停止播放
- - (void)audioPlayerStop
- {
- if (self.audioPlayer)
- {
- if ([self.audioPlayer isPlaying])
- {
- [self.audioPlayer stop];
- }
-
- self.audioPlayer = nil;
- }
-
- if (self.playerFinished) {
- self.playerFinished();
- }
- }
- - (void)clear {
- if (_audioRecorderTimer) {
- [_audioRecorderTimer invalidate];
- _audioRecorderTimer = nil;
- }
- if (_audioRecorder) {
- [_audioRecorder stop];
- _audioRecorder = nil;
- }
- if (_audioPlayer) {
- [_audioPlayer stop];
- _audioPlayer = nil;
- }
- }
- #pragma mark - AVAudioPlayerDelegate
- /// 播放完成时调用的方法 (代理里的方法),需要设置代理才可以调用
- - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
-
- [self audioPlayerStop];
- }
- @end
|