EMAudioPlayerHelper.mm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //
  2. // EMAudioPlayerHelper.m
  3. // ChatDemo-UI3.0
  4. //
  5. // Created by XieYajie on 2019/1/29.
  6. // Copyright © 2019 XieYajie. All rights reserved.
  7. //
  8. #import <AVFoundation/AVFoundation.h>
  9. #import "EMAudioPlayerHelper.h"
  10. #import "amrFileCodec.h"
  11. static EMAudioPlayerHelper *playerHelper = nil;
  12. @interface EMAudioPlayerHelper()<AVAudioPlayerDelegate>
  13. @property (nonatomic, strong) NSString *playingPath;
  14. @property (nonatomic, strong) AVAudioPlayer *player;
  15. @property (nonatomic, copy) void (^playerFinished)(NSError *error);
  16. @end
  17. @implementation EMAudioPlayerHelper
  18. + (instancetype)sharedHelper
  19. {
  20. static dispatch_once_t onceToken;
  21. dispatch_once(&onceToken, ^{
  22. playerHelper = [[EMAudioPlayerHelper alloc] init];
  23. });
  24. return playerHelper;
  25. }
  26. - (instancetype)init
  27. {
  28. self = [super init];
  29. if (self) {
  30. }
  31. return self;
  32. }
  33. - (void)dealloc
  34. {
  35. [self stopPlayer];
  36. }
  37. #pragma mark - AVAudioPlayerDelegate
  38. - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
  39. successfully:(BOOL)flag
  40. {
  41. if (self.playerFinished) {
  42. self.playerFinished(nil);
  43. }
  44. self.playerFinished = nil;
  45. if (_player) {
  46. _player.delegate = nil;
  47. _player = nil;
  48. }
  49. }
  50. - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player
  51. error:(NSError *)error
  52. {
  53. if (self.playerFinished) {
  54. NSError *error = [NSError errorWithDomain:@"播放失败!" code:-1 userInfo:nil];
  55. self.playerFinished(error);
  56. }
  57. self.playerFinished = nil;
  58. if (_player) {
  59. _player.delegate = nil;
  60. _player = nil;
  61. }
  62. }
  63. #pragma mark - Private
  64. + (int)isMP3File:(NSString *)aFilePath
  65. {
  66. const char *filePath = [aFilePath cStringUsingEncoding:NSASCIIStringEncoding];
  67. return isMP3File(filePath);
  68. }
  69. + (int)amrToWav:(NSString*)aAmrPath wavSavePath:(NSString*)aWavPath
  70. {
  71. if (EM_DecodeAMRFileToWAVEFile([aAmrPath cStringUsingEncoding:NSASCIIStringEncoding], [aWavPath cStringUsingEncoding:NSASCIIStringEncoding]))
  72. return 0; // success
  73. return 1; // failed
  74. }
  75. - (NSString *)_convertAudioFile:(NSString *)aPath
  76. {
  77. if ([[aPath pathExtension] isEqualToString:@"mp3"]) {
  78. return aPath;
  79. }
  80. NSString *retPath = [[aPath stringByDeletingPathExtension] stringByAppendingPathExtension:@"wav"];
  81. do {
  82. NSFileManager *fileManager = [NSFileManager defaultManager];
  83. if ([fileManager fileExistsAtPath:retPath]) {
  84. break;
  85. }
  86. if ([EMAudioPlayerHelper isMP3File:retPath]) {
  87. retPath = aPath;
  88. break;
  89. }
  90. [EMAudioPlayerHelper amrToWav:aPath wavSavePath:retPath];
  91. if (![fileManager fileExistsAtPath:retPath]) {
  92. retPath = nil;
  93. }
  94. } while (0);
  95. return retPath;
  96. }
  97. #pragma mark - Public
  98. - (void)startPlayerWithPath:(NSString *)aPath
  99. model:(id)aModel
  100. AVAudioSessionCategory:(AVAudioSessionCategory)playCategory
  101. completion:(void(^)(NSError *error))aCompleton
  102. {
  103. NSError *error = nil;
  104. do {
  105. NSFileManager *fm = [NSFileManager defaultManager];
  106. if (![fm fileExistsAtPath:aPath]) {
  107. error = [NSError errorWithDomain:@"文件路径不存在" code:-1 userInfo:nil];
  108. break;
  109. }
  110. if (self.player && self.player.isPlaying && [self.playingPath isEqualToString:aPath]) {
  111. break;
  112. } else {
  113. [self stopPlayer];
  114. }
  115. aPath = [self _convertAudioFile:aPath];
  116. if ([aPath length] == 0) {
  117. error = [NSError errorWithDomain:@"转换音频格式失败" code:-1 userInfo:nil];
  118. break;
  119. }
  120. self.model = aModel;
  121. NSURL *wavUrl = [[NSURL alloc] initFileURLWithPath:aPath];
  122. self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:wavUrl error:&error];
  123. if (error || !self.player) {
  124. self.player = nil;
  125. error = [NSError errorWithDomain:@"初始化AVAudioPlayer失败" code:-1 userInfo:nil];
  126. break;
  127. }
  128. self.playingPath = aPath;
  129. [self setPlayerFinished:aCompleton];
  130. self.player.delegate = self;
  131. BOOL ret = [self.player prepareToPlay];
  132. if (ret) {
  133. AVAudioSession *audioSession = [AVAudioSession sharedInstance];
  134. [audioSession setCategory:playCategory error:&error];
  135. if (error) {
  136. break;
  137. }
  138. }
  139. ret = [self.player play];
  140. if (!ret) {
  141. [self stopPlayer];
  142. error = [NSError errorWithDomain:@"AVAudioPlayer播放失败" code:-1 userInfo:nil];
  143. }
  144. } while (0);
  145. if (error) {
  146. if (aCompleton) {
  147. aCompleton(error);
  148. }
  149. }
  150. }
  151. - (void)stopPlayer
  152. {
  153. if(_player) {
  154. _player.delegate = nil;
  155. [_player stop];
  156. _player = nil;
  157. }
  158. self.playingPath = nil;
  159. self.playerFinished = nil;
  160. }
  161. @end