iOS功能开发涉及到音频处理时,最常见的时进行录音,以及音频文件的播放、停止播放等的操作。在开发中还要避免同一个音频文件,或不同音频文件之间的处理,比如说正在播放A音频时,可以停止播放A音频,也可以播放B音频时,停止播放A音频。在我的封装类中,已经对这方面做了处理。
音频开发注意事项
1、录音功能主要使用到"AVAudioRecorder"类
2、音频播放处理功能主要使用到"AVAudioPlayer"类
3、通过NSTimer处理音量显示
4、注意添加framework(AVFoundation.framework、AudioToolbox.framework)
5、只可以用来播放本地音频文件,即使是网络音频也是先下载到本地,然后再进行播放
1 主要代码
#import <Foundation/Foundation.h>
@interface AudioRecorder : NSObject
#pragma mark - 录音
/// 实例化单例
+ (AudioRecorder *)shareManager;
#pragma mark - 音频处理-录音
/// 开始录音
- (void)audioRecorderStartWithFilePath:(NSString *)filePath;
/// 停止录音
- (void)audioRecorderStop;
/// 录音时长
- (NSTimeInterval)durationAudioRecorderWithFilePath:(NSString *)filePath;
#pragma mark - 音频处理-播放/停止
/// 音频开始播放或停止
- (void)audioPlayWithFilePath:(NSString *)filePath;
/// 音频播放停止
- (void)audioStop;
@end
#import "AudioRecorder.h"// 导入录音头文件(注意添加framework:AVFoundation.framework、AudioToolbox.framework)#import <AudioToolbox/AudioToolbox.h>#import <AVFoundation/AVFoundation.h>#import "AppDelegate.h"@interface AudioRecorder () <AVAudioRecorderDelegate>@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; // 录音时长@property (nonatomic, strong) UIView *imgView; // 录音音量图像父视图@property (nonatomic, strong) UIImageView *audioRecorderVoiceImgView; // 录音音量图像@end@implementation AudioRecorder#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; } if (self.imgView) { self.imgView = nil; } if (self.audioRecorderVoiceImgView) { self.audioRecorderVoiceImgView = 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]; //录音音量显示 75*111 AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate; UIView *view = [delegate window]; self.imgView = [[UIView alloc] initWithFrame:CGRectMake((view.frame.size.width - 120) / 2, (view.frame.size.height - 120) / 2, 120, 120)]; [view addSubview:self.imgView]; [self.imgView.layer setCornerRadius:10.0]; [self.imgView.layer setBackgroundColor:[UIColor blackColor].CGColor]; [self.imgView setAlpha:0.8]; self.audioRecorderVoiceImgView = [[UIImageView alloc] initWithFrame:CGRectMake((self.imgView.frame.size.width - 60) / 2, (self.imgView.frame.size.height - 60 * 111 / 75) / 2, 60, 60 * 111 / 75)]; [self.imgView addSubview:self.audioRecorderVoiceImgView]; [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_01.png"]]; [self.audioRecorderVoiceImgView setBackgroundColor:[UIColor clearColor]]; // 设置定时检测 self.audioRecorderTimer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(detectionVoice) userInfo:nil repeats:YES]; } }}/// 录音音量显示- (void)detectionVoice{ // 刷新音量数据 [self.audioRecorder updateMeters]; // // 获取音量的平均值// [self.audioRecorder averagePowerForChannel:0];// // 音量的最大值// [self.audioRecorder peakPowerForChannel:0]; double lowPassResults = pow(10, (0.05 * [self.audioRecorder peakPowerForChannel:0])); if (0 < lowPassResults <= 0.06) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_01.png"]]; } else if (0.06 < lowPassResults <= 0.13) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_02.png"]]; } else if (0.13 < lowPassResults <= 0.20) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_03.png"]]; } else if (0.20 < lowPassResults <= 0.27) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_04.png"]]; } else if (0.27 < lowPassResults <= 0.34) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_05.png"]]; } else if (0.34 < lowPassResults <= 0.41) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_06.png"]]; } else if (0.41 < lowPassResults <= 0.48) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_07.png"]]; } else if (0.48 < lowPassResults <= 0.55) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_08.png"]]; } else if (0.55 < lowPassResults <= 0.62) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_09.png"]]; } else if (0.62 < lowPassResults <= 0.69) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_10.png"]]; } else if (0.69 < lowPassResults <= 0.76) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_11.png"]]; } else if (0.76 < lowPassResults <= 0.83) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_12.png"]]; } else if (0.83 < lowPassResults <= 0.9) { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_13.png"]]; } else { [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_14.png"]]; }}/// 停止录音- (void)audioRecorderStop{ if (self.audioRecorder) { if ([self.audioRecorder isRecording]) { // 获取录音时长 self.audioRecorderTime = [self.audioRecorder currentTime]; [self.audioRecorder stop]; // 停止录音后释放掉 self.audioRecorder = nil; } } // 移除音量图标 if (self.audioRecorderVoiceImgView) { [self.audioRecorderVoiceImgView setHidden:YES]; [self.audioRecorderVoiceImgView setImage:nil]; [self.audioRecorderVoiceImgView removeFromSuperview]; self.audioRecorderVoiceImgView = nil; [self.imgView removeFromSuperview]; self.imgView = 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]; /* NSString *currentName = [self getFileNameAndType:currentStr]; NSString *nextName = [self getFileNameAndType:filePath]; if ([currentName isEqualToString:nextName]) { if ([self.audioPlayer isPlaying]) { [self.audioPlayer stop]; self.audioPlayer = nil; } else { self.audioPlayer = nil; [self audioPlayerPlay:filePath]; } } else { [self audioPlayerStop]; [self audioPlayerPlay:filePath]; } */ // 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];}/// 音频播放器开始播放- (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]; 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; }}@end
2、使用
引入封装类头文件
#import "AudioRecorder.h"
// 开始录音
- (void)startRecorder
{
self.filePath = GetFilePathWithDate();
[[AudioRecorder shareManager] audioRecorderStartWithFilePath:self.filePath];
}
// 停止录音,并保存
- (void)saveRecorder
{
[[AudioRecorder shareManager] audioRecorderStop];
}
// 录音开始播放,或停止
- (void)playRecorder
{
[[AudioRecorder shareManager] audioPlayWithFilePath:self.filePath];
}
// 录音停止播放
- (void)stopRecorder
{
[[AudioRecorder shareManager] audioStop];
}