QMAudioRecorder.m 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. //
  2. // QMAudioRecorder.m
  3. // IMSDK-OC
  4. //
  5. // Created by haochongfeng on 2017/8/10.
  6. // Copyright © 2017年 HCF. All rights reserved.
  7. //
  8. #import "QMAudioRecorder.h"
  9. @interface QMAudioRecorder()<AVAudioRecorderDelegate>
  10. @property (nonatomic, strong) AVAudioRecorder *audioRecorder;
  11. @property (nonatomic, copy) NSString *recordFileName;
  12. @property (nonatomic, copy) NSString *recordFilePath;
  13. @property (nonatomic, assign) NSTimeInterval recordDuration;
  14. @property (nonatomic, assign) NSTimeInterval maxDuration;
  15. @property (nonatomic, strong) NSDictionary *recordSet;
  16. @property (nonatomic, weak) id<QMAudioRecorderDelegate> delegate;
  17. @property (nonatomic, strong) NSTimer *timer;
  18. @property (nonatomic, assign) BOOL isRecording;
  19. @property (nonatomic, assign) BOOL isCancel;
  20. @end
  21. @implementation QMAudioRecorder
  22. static QMAudioRecorder * instance = nil;
  23. + (QMAudioRecorder *)sharedInstance {
  24. static dispatch_once_t onceToken;
  25. dispatch_once(&onceToken, ^{
  26. instance = [[self alloc] init];
  27. });
  28. return instance;
  29. }
  30. + (id)allocWithZone:(struct _NSZone *)zone {
  31. static dispatch_once_t onceToken;
  32. dispatch_once(&onceToken, ^{
  33. instance = [super allocWithZone:zone];
  34. });
  35. return instance;
  36. }
  37. - (instancetype)init {
  38. self = [super init];
  39. if (self) {
  40. NSDictionary * recordSettings = @{
  41. AVFormatIDKey : [NSNumber numberWithUnsignedInt:kAudioFormatLinearPCM],
  42. AVSampleRateKey : [NSNumber numberWithFloat:8000],
  43. AVLinearPCMBitDepthKey : [NSNumber numberWithInt:16],
  44. AVNumberOfChannelsKey : [NSNumber numberWithInt:2]
  45. };
  46. self.recordSet = recordSettings;
  47. }
  48. return self;
  49. }
  50. - (void)startAudioRecord:(NSString *)fileName maxDuration:(NSTimeInterval)duration delegate:(id<QMAudioRecorderDelegate>)delegate {
  51. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
  52. [[AVAudioSession sharedInstance] setActive:YES error:nil];
  53. self.isCancel = false;
  54. self.delegate = delegate;
  55. self.recordDuration = 0.0;
  56. if ([fileName isEqualToString:@""]) {
  57. [self.delegate audioRecorderCancel];
  58. return;
  59. }
  60. self.maxDuration = duration;
  61. self.recordFileName = fileName;
  62. self.recordFilePath = [NSString stringWithFormat:@"%@/%@/%@",NSHomeDirectory(),@"Documents",fileName];
  63. if (![NSURL URLWithString:self.recordFilePath]) {
  64. return;
  65. }
  66. NSError *error = nil;
  67. self.audioRecorder = [[AVAudioRecorder alloc] initWithURL:[NSURL URLWithString:self.recordFilePath] settings:self.recordSet error:&error];
  68. self.audioRecorder.delegate = self;
  69. if (error) {
  70. [self.delegate audioRecorderCancel];
  71. return;
  72. }
  73. [self.audioRecorder setMeteringEnabled:YES];
  74. [self.audioRecorder prepareToRecord];
  75. [self createTimer];
  76. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  77. if ([self.audioRecorder recordForDuration:duration]) {
  78. [self.delegate audioRecorderStart];
  79. }else {
  80. [self cancelAudioRecord];
  81. return;
  82. }
  83. });
  84. }
  85. - (void)stopAudioRecord {
  86. self.isCancel = false;
  87. if (self.audioRecorder) {
  88. [self.audioRecorder stop];
  89. }
  90. [self removeTimer];
  91. }
  92. - (void)cancelAudioRecord {
  93. self.isCancel = true;
  94. if (self.audioRecorder) {
  95. [self.audioRecorder stop];
  96. [self.audioRecorder deleteRecording];
  97. }
  98. [self removeTimer];
  99. if (self.delegate) {
  100. [self.delegate audioRecorderCancel];
  101. }
  102. }
  103. - (void)createTimer {
  104. [self removeTimer];
  105. self.timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
  106. [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
  107. }
  108. - (void)timerAction:(NSTimer *)timer {
  109. if (self.delegate && self.audioRecorder) {
  110. if (self.recordDuration > 50) {
  111. if (self.audioRecorder.currentTime != 0) {
  112. self.recordDuration = self.audioRecorder.currentTime;
  113. }
  114. }else {
  115. self.recordDuration = self.audioRecorder.currentTime;
  116. }
  117. [self.delegate audioRecorderChangeInTimer:[self peakPower] total:[self totalTime]];
  118. }
  119. }
  120. - (void)removeTimer {
  121. if (self.timer) {
  122. [self.timer invalidate];
  123. self.timer = nil;
  124. }
  125. }
  126. - (float)peakPower {
  127. [self.audioRecorder updateMeters];
  128. return self.audioRecorder ? [self.audioRecorder peakPowerForChannel:0] : 0;
  129. }
  130. - (int)totalTime {
  131. return (int)(self.recordDuration*10)%10 > 6 ? (int)self.recordDuration + 1 : (int)self.recordDuration;
  132. }
  133. // MARK: - 代理方法
  134. - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error {
  135. }
  136. - (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag {
  137. if (self.isCancel) {
  138. NSString *filePath = [NSString stringWithFormat:@"%@/%@/%@",NSHomeDirectory(),@"Documents",self.recordFileName];
  139. NSFileManager *fileManger = [NSFileManager defaultManager];
  140. if ([fileManger fileExistsAtPath:filePath]) {
  141. [fileManger removeItemAtPath:filePath error:nil];
  142. }
  143. return;
  144. }
  145. if (self.recordDuration >= 1) {
  146. [self.delegate audioRecorderCompletion:self.recordFileName duration:[NSString stringWithFormat:@"%d", [self totalTime]]];
  147. [self removeTimer];
  148. }else {
  149. [self.delegate audioRecorderFail];
  150. }
  151. }
  152. @end