您好,登錄后才能下訂單哦!
小編給大家分享一下iOS如何使用音頻處理框架The Amazing Audio Engine實現音頻錄制播放,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
首先看一下效果圖:
下面貼上核心控制器代碼:
#import "ViewController.h" #import <AVFoundation/AVFoundation.h> #import "HWProgressHUD.h" #import "UIImage+HW.h" #import "AERecorder.h" #import "HWRecordingDrawView.h" #define KMainW [UIScreen mainScreen].bounds.size.width #define KMainH [UIScreen mainScreen].bounds.size.height @interface ViewController () @property (nonatomic, strong) AERecorder *recorder; @property (nonatomic, strong) AEAudioController *audioController; @property (nonatomic, strong) AEAudioFilePlayer *player; @property (nonatomic, strong) AEAudioFilePlayer *backgroundPlayer; @property (nonatomic, strong) NSTimer *timer; @property (nonatomic, strong) NSMutableArray *soundSource; @property (nonatomic, weak) HWRecordingDrawView *recordingDrawView; @property (nonatomic, weak) UILabel *recLabel; @property (nonatomic, weak) UILabel *recordTimeLabel; @property (nonatomic, weak) UILabel *playTimeLabel; @property (nonatomic, weak) UIButton *auditionBtn; @property (nonatomic, weak) UIButton *recordBtn; @property (nonatomic, weak) UISlider *slider; @property (nonatomic, copy) NSString *path; @end @implementation ViewController - (AEAudioController *)audioController { if (!_audioController) { _audioController = [[AEAudioController alloc] initWithAudioDescription:[AEAudioController nonInterleavedFloatStereoAudioDescription] inputEnabled:YES]; _audioController.preferredBufferDuration = 0.005; _audioController.useMeasurementMode = YES; } return _audioController; } - (NSMutableArray *)soundSource { if (!_soundSource) { _soundSource = [NSMutableArray array]; } return _soundSource; } - (void)viewDidLoad { [super viewDidLoad]; [self creatControl]; } - (void)creatControl { CGFloat marginX = 30.0f; //音頻視圖 HWRecordingDrawView *recordingDrawView = [[HWRecordingDrawView alloc] initWithFrame:CGRectMake(marginX, 80, KMainW - marginX * 2, 100)]; [self.view addSubview:recordingDrawView]; _recordingDrawView = recordingDrawView; //REC UILabel *recLabel = [[UILabel alloc] initWithFrame:CGRectMake(marginX, CGRectGetMaxY(recordingDrawView.frame) + 20, 80, 40)]; recLabel.text = @"REC"; recLabel.textColor = [UIColor redColor]; [self.view addSubview:recLabel]; _recLabel = recLabel; //錄制時間 UILabel *recordTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(recLabel.frame) + 20, CGRectGetMinY(recLabel.frame), 150, 40)]; recordTimeLabel.text = @"錄制時長:00:00"; [self.view addSubview:recordTimeLabel]; _recordTimeLabel = recordTimeLabel; //播放時間 UILabel *playTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMinX(recordTimeLabel.frame), CGRectGetMaxY(recordTimeLabel.frame), 150, 40)]; playTimeLabel.text = @"播放時長:00:00"; playTimeLabel.hidden = YES; [self.view addSubview:playTimeLabel]; _playTimeLabel = playTimeLabel; //配樂按鈕 NSArray *titleArray = @[@"無配樂", @"夏天", @"陽光海灣"]; CGFloat btnW = 80.0f; CGFloat padding = (KMainW - marginX * 2 - btnW * titleArray.count) / (titleArray.count - 1); for (int i = 0; i < titleArray.count; i++) { CGFloat btnX = marginX + (btnW + padding) * i; UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(btnX, CGRectGetMaxY(playTimeLabel.frame) + 20, btnW, btnW)]; [btn setTitle:titleArray[i] forState:UIControlStateNormal]; btn.layer.cornerRadius = btnW * 0.5; btn.layer.masksToBounds = YES; [btn setBackgroundImage:[UIImage imageWithColor:[UIColor grayColor]] forState:UIControlStateNormal]; [btn setBackgroundImage:[UIImage imageWithColor:[UIColor orangeColor]] forState:UIControlStateSelected]; if (i == 0) btn.selected = YES; btn.tag = 100 + i; [btn addTarget:self action:@selector(changeBackgroundMusic:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; } //配樂音量 UILabel *backgroundLabel = [[UILabel alloc] initWithFrame:CGRectMake(marginX + 10, CGRectGetMaxY(playTimeLabel.frame) + 120, 80, 40)]; backgroundLabel.text = @"配樂音量"; [self.view addSubview:backgroundLabel]; //配樂音量 UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(CGRectGetMaxX(backgroundLabel.frame) + 10, CGRectGetMinY(backgroundLabel.frame), 210, 40)]; slider.value = 0.4f; [slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:slider]; _slider = slider; //試聽按鈕 UIButton *auditionBtn = [[UIButton alloc] initWithFrame:CGRectMake(marginX, KMainH - 150, 120, 80)]; auditionBtn.hidden = YES; auditionBtn.backgroundColor = [UIColor blackColor]; [auditionBtn setTitle:@"試聽" forState:UIControlStateNormal]; [auditionBtn setTitle:@"停止" forState:UIControlStateSelected]; [auditionBtn addTarget:self action:@selector(auditionBtnOnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:auditionBtn]; _auditionBtn = auditionBtn; //錄音按鈕 UIButton *recordBtn = [[UIButton alloc] initWithFrame:CGRectMake(KMainW - marginX - 120, KMainH - 150, 120, 80)]; recordBtn.backgroundColor = [UIColor blackColor]; [recordBtn setTitle:@"開始" forState:UIControlStateNormal]; [recordBtn setTitle:@"暫停" forState:UIControlStateSelected]; [recordBtn addTarget:self action:@selector(recordBtnOnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:recordBtn]; _recordBtn = recordBtn; } //配樂按鈕點擊事件 - (void)changeBackgroundMusic:(UIButton *)btn { //更新選中狀態 for (int i = 0; i < 3; i++) { UIButton *button = (UIButton *)[self.view viewWithTag:100 + i]; button.selected = NO; } btn.selected = YES; //移除之前配樂 if (_backgroundPlayer) { [_audioController removeChannels:@[_backgroundPlayer]]; _backgroundPlayer = nil; } NSURL *url; if (btn.tag == 100) { return; }else if (btn.tag == 101) { url = [[NSBundle mainBundle]URLForResource:@"夏天.mp3" withExtension:nil]; }else if (btn.tag == 102) { url = [[NSBundle mainBundle]URLForResource:@"陽光海灣.mp3" withExtension:nil]; } [self.audioController start:NULL]; NSError *AVerror = NULL; _backgroundPlayer = [AEAudioFilePlayer audioFilePlayerWithURL:url error:&AVerror]; _backgroundPlayer.volume = _slider.value; _backgroundPlayer.loop = YES; if (!_backgroundPlayer) { [[[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Couldn't start playback: %@", [AVerror localizedDescription]] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show]; return; } //放完移除 _backgroundPlayer.removeUponFinish = YES; __weak ViewController *weakSelf = self; _backgroundPlayer.completionBlock = ^{ weakSelf.backgroundPlayer = nil; }; [_audioController addChannels:@[_backgroundPlayer]]; } //配樂音量slider滑動事件 - (void)sliderValueChanged:(UISlider *)slider { if (_backgroundPlayer) _backgroundPlayer.volume = slider.value; } //錄音按鈕點擊事件 - (void)recordBtnOnClick:(UIButton *)btn { [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) { if (granted) { //用戶同意獲取麥克風 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ btn.selected = !btn.selected; if (btn.selected) { [self startRecord]; }else { [self finishRecord]; } }); }else { //用戶不同意獲取麥克風 [HWProgressHUD showMessage:@"需要訪問您的麥克風,請在“設置-隱私-麥克風”中允許訪問。" duration:3.f]; } }]; } //開始錄音 - (void)startRecord { _auditionBtn.hidden = YES; [self.audioController start:NULL]; _recorder = [[AERecorder alloc] initWithAudioController:_audioController]; _path = [self getPath]; NSError *error = NULL; if ( ![_recorder beginRecordingToFileAtPath:_path fileType:kAudioFileM4AType error:&error] ) { [[[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Couldn't start recording: %@", [error localizedDescription]] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show]; _recorder = nil; return; } [self.soundSource removeAllObjects]; [self removeTimer]; [self addRecordTimer]; [_audioController addOutputReceiver:_recorder]; [_audioController addInputReceiver:_recorder]; } //結束錄音 - (void)finishRecord { _auditionBtn.hidden = NO; _recLabel.hidden = NO; [self removeTimer]; [_recorder finishRecording]; [_audioController removeOutputReceiver:_recorder]; [_audioController removeInputReceiver:_recorder]; _recorder = nil; } //添加錄音定時器 - (void)addRecordTimer { self.timer = [NSTimer scheduledTimerWithTimeInterval:.2f target:self selector:@selector(recordTimerAction) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; } //錄音定時器事件 - (void)recordTimerAction { //獲取音頻 [CATransaction begin]; [CATransaction setDisableActions:YES]; Float32 inputAvg, inputPeak, outputAvg, outputPeak; [_audioController inputAveragePowerLevel:&inputAvg peakHoldLevel:&inputPeak]; [_audioController outputAveragePowerLevel:&outputAvg peakHoldLevel:&outputPeak]; [self.soundSource insertObject:[NSNumber numberWithFloat:(inputPeak + 18) * 2.8] atIndex:0]; [CATransaction commit]; _recordingDrawView.pointArray = _soundSource; //REC閃動 _recLabel.hidden = (int)[self.recorder currentTime] % 2 == 1 ? YES : NO; //錄音時間 NSString *str = [self strWithTime:[self.recorder currentTime] interval:0.5f]; if ([str intValue] < 0) str = @"錄制時長:00:00"; [self.recordTimeLabel setText:[NSString stringWithFormat:@"錄制時長:%@", str]]; } //移除定時器 - (void)removeTimer { [self.timer invalidate]; self.timer = nil; } //試聽按鈕點擊事件 - (void)auditionBtnOnClick:(UIButton *)btn { btn.selected = !btn.selected; if (btn.selected) { [self playRecord]; }else { [self stopPlayRecord]; } } //播放錄音 - (void)playRecord { //更新界面 _recordBtn.hidden = YES; [_playTimeLabel setText:@"播放時長:00:00"]; _playTimeLabel.hidden = NO; //取消背景音樂 [self changeBackgroundMusic:(UIButton *)[self.view viewWithTag:100]]; if (![[NSFileManager defaultManager] fileExistsAtPath:_path]) return; NSError *error = nil; _player = [AEAudioFilePlayer audioFilePlayerWithURL:[NSURL fileURLWithPath:_path] error:&error]; if (!_player) { [[[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Couldn't start playback: %@", [error localizedDescription]] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show]; return; } [self addPlayTimer]; _player.removeUponFinish = YES; __weak ViewController *weakSelf = self; _player.completionBlock = ^{ weakSelf.player = nil; weakSelf.auditionBtn.selected = NO; [weakSelf stopPlayRecord]; }; [self.audioController start:NULL]; [self.audioController addChannels:@[_player]]; } //停止播放錄音 - (void)stopPlayRecord { _recordBtn.hidden = NO; _playTimeLabel.hidden = YES; [self removeTimer]; if (_player) [_audioController removeChannels:@[_player]]; } //添加播放定時器 - (void)addPlayTimer { self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(playTimerAction) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; } //播放定時器事件 - (void)playTimerAction { //播放時間 NSString *str = [self strWithTime:[_player currentTime] interval:1.f]; if ([str intValue] < 0) str = @"播放時長:00:00"; [_playTimeLabel setText:[NSString stringWithFormat:@"播放時長:%@", str]]; } //錄制音頻沙盒路徑 - (NSString *)getPath { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"YYYYMMddhhmmss"]; NSString *recordName = [NSString stringWithFormat:@"%@.wav", [formatter stringFromDate:[NSDate date]]]; NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:recordName]; return path; } //時長長度轉時間字符串 - (NSString *)strWithTime:(double)time interval:(CGFloat)interval { int minute = (time * interval) / 60; int second = (int)(time * interval) % 60; return [NSString stringWithFormat:@"%02d:%02d", minute, second]; } @end
看完了這篇文章,相信你對“iOS如何使用音頻處理框架The Amazing Audio Engine實現音頻錄制播放”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。