235 lines
7.1 KiB
Objective-C
235 lines
7.1 KiB
Objective-C
//
|
||
// Copyright 1999-2015 MyApp
|
||
//
|
||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
// you may not use this file except in compliance with the License.
|
||
// You may obtain a copy of the License at
|
||
//
|
||
// http://www.apache.org/licenses/LICENSE-2.0
|
||
//
|
||
// Unless required by applicable law or agreed to in writing, software
|
||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
// See the License for the specific language governing permissions and
|
||
// limitations under the License.
|
||
//
|
||
|
||
#import "MTAudioManager.h"
|
||
#import <AVFoundation/AVFoundation.h>
|
||
#import "NSTimer+BlocksKit.h"
|
||
#import "DDAudioManager.h"
|
||
|
||
@interface MTAudioManager()<AVAudioPlayerDelegate>
|
||
|
||
@property (nonatomic, strong) AVAudioSession *session;
|
||
@property (nonatomic, strong) NSURL *recordFileURL;
|
||
@property (nonatomic, copy) NSString *recordUrlKey;
|
||
@property (nonatomic, copy) didPlayFinish finishBlock;
|
||
@property (nonatomic, strong) NSTimer *recordProgressTimer;
|
||
|
||
@end
|
||
|
||
@implementation MTAudioManager
|
||
|
||
+ (instancetype)sharedInstance
|
||
{
|
||
static MTAudioManager *instance = nil;
|
||
static dispatch_once_t onceToken;
|
||
dispatch_once(&onceToken, ^{
|
||
instance = [[MTAudioManager alloc] init];
|
||
});
|
||
return instance;
|
||
}
|
||
|
||
- (instancetype)init
|
||
{
|
||
self = [super init];
|
||
if(self)
|
||
{
|
||
[self activeAudioSession];
|
||
}
|
||
return self;
|
||
}
|
||
|
||
- (void)activeAudioSession
|
||
{
|
||
self.session = [AVAudioSession sharedInstance];
|
||
NSError *sessionError = nil;
|
||
[self.session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:&sessionError];
|
||
|
||
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
|
||
#pragma clang diagnostic push
|
||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||
AudioSessionSetProperty (
|
||
kAudioSessionProperty_OverrideAudioRoute,
|
||
sizeof (audioRouteOverride),
|
||
&audioRouteOverride
|
||
);
|
||
#pragma clang diagnostic pop
|
||
if(!self.session)
|
||
{
|
||
NSLog(@"Error creating session: %@", [sessionError description]);
|
||
}
|
||
else
|
||
{
|
||
[self.session setActive:YES error:nil];
|
||
}
|
||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
|
||
}
|
||
|
||
- (void)playWithData:(NSData *)data finish:(void (^)(void))didFinish;
|
||
{
|
||
[self stopPlay];
|
||
|
||
self.finishBlock = didFinish;
|
||
if (self.player) {
|
||
if (self.player.isPlaying) {
|
||
[self.player stop];
|
||
}
|
||
|
||
self.player.delegate = nil;
|
||
self.player = nil;
|
||
}
|
||
|
||
NSError *playerError = nil;
|
||
self.player = [[AVAudioPlayer alloc] initWithData:data error:&playerError];
|
||
if (self.player)
|
||
{
|
||
self.player.delegate = self;
|
||
[self.player play];
|
||
}
|
||
else
|
||
{
|
||
NSLog(@"Error creating player: %@", [playerError description]);
|
||
}
|
||
}
|
||
|
||
- (void)stopPlay
|
||
{
|
||
|
||
if (self.player)
|
||
{
|
||
if (self.player.isPlaying)
|
||
{
|
||
[self.player stop];
|
||
}
|
||
|
||
self.player.delegate = nil;
|
||
self.player = nil;
|
||
|
||
// 恢复其他app音频播放
|
||
// [[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
|
||
|
||
if (self.finishBlock)
|
||
{
|
||
self.finishBlock();
|
||
self.finishBlock = nil;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
- (BOOL)initRecord
|
||
{
|
||
[self activeAudioSession];
|
||
|
||
//录音设置
|
||
NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc]init];
|
||
//设置录音格式 AVFormatIDKey==kAudioFormatLinearPCM
|
||
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
|
||
//设置录音采样率(Hz) 如:AVSampleRateKey==8000/44100/96000(影响音频的质量)
|
||
[recordSetting setValue:[NSNumber numberWithFloat:16000.0] forKey:AVSampleRateKey]; //调低采样率,防止小程序播放不支持
|
||
//录音通道数 1 或 2
|
||
[recordSetting setValue:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
|
||
//线性采样位数 8、16、24、32
|
||
[recordSetting setValue:[NSNumber numberWithInt:8] forKey:AVLinearPCMBitDepthKey]; //设置最小8位,防止小程序播放不支持
|
||
//录音的质量
|
||
[recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];
|
||
|
||
|
||
NSTimeInterval timeInterval = [[NSDate date] timeIntervalSince1970];
|
||
NSString *strUrl = [NSString stringWithFormat:@"%@/%f.m4a", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject], timeInterval];
|
||
NSURL *url = [NSURL fileURLWithPath:strUrl];
|
||
self.recordUrlKey = strUrl;
|
||
|
||
NSError *error;
|
||
//初始化
|
||
_recorder = [[AVAudioRecorder alloc]initWithURL:url settings:recordSetting error:&error];
|
||
//开启音量检测
|
||
self.recorder.meteringEnabled = YES;
|
||
|
||
if ([self.recorder prepareToRecord]){
|
||
return YES;
|
||
}
|
||
return NO;
|
||
}
|
||
|
||
- (BOOL)startRecord
|
||
{
|
||
BOOL succees = [self.recorder record];
|
||
|
||
if (succees) {
|
||
|
||
__weak MTAudioManager * weakSelf = self;
|
||
NSTimer *timer = [NSTimer bk_scheduleTimerWithTimeInterval:0.1 repeats:YES usingBlock:^(NSTimer * _Nonnull timer) {
|
||
if ([weakSelf.recordDelegate respondsToSelector:@selector(audioManager:audioPath:recordingProgress:)]) {
|
||
[weakSelf.recordDelegate audioManager:weakSelf audioPath:weakSelf.recordUrlKey recordingProgress:[weakSelf recordTime]];
|
||
}
|
||
}];
|
||
self.recordProgressTimer = timer;
|
||
}
|
||
return succees;
|
||
}
|
||
|
||
- (void)stopRecord
|
||
{
|
||
NSTimeInterval duration = self.recorder.currentTime;
|
||
[self.recorder stop];
|
||
|
||
// 恢复其他app音频播放
|
||
// [[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
|
||
|
||
[self.recordProgressTimer invalidate];
|
||
self.recordProgressTimer = nil;
|
||
if ([self.recordDelegate respondsToSelector:@selector(audioManagerDidStopedRecord:audioPath:duration:)]) {
|
||
[self.recordDelegate audioManagerDidStopedRecord:self audioPath:self.recordUrlKey duration:round(duration)];
|
||
}
|
||
}
|
||
|
||
- (CGFloat)peakPowerMeter
|
||
{
|
||
return 0.5;
|
||
}
|
||
|
||
- (NSTimeInterval)recordTime
|
||
{
|
||
return (self.recorder.currentTime);
|
||
}
|
||
|
||
- (void)handleInterruption:(NSNotification *)noti
|
||
{
|
||
;
|
||
}
|
||
#pragma mark - AVAudioPlayerDelegate
|
||
|
||
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
|
||
{
|
||
// 恢复其他app音频播放
|
||
// [[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
|
||
|
||
if (self.finishBlock)
|
||
{
|
||
self.finishBlock();
|
||
self.finishBlock = nil;
|
||
}
|
||
}
|
||
|
||
|
||
/* if an error occurs while encoding it will be reported to the delegate. */
|
||
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError * __nullable)error
|
||
{
|
||
;
|
||
}
|
||
|
||
@end
|