iOS中音频的录制与播放(本地音频文件的播放)

iOS功能开发涉及到音频处理时,最常见的时进行录音,以及音频文件的播放、停止播放等的操作。在开发中还要避免同一个音频文件,或不同音频文件之间的处理,比如说正在播放A音频时,可以停止播放A音频,也可以播放B音频时,停止播放A音频。在我的封装类中,已经对这方面做了处理。


Demo下载地址


音频开发注意事项

1、录音功能主要使用到"AVAudioRecorder"类

2、音频播放处理功能主要使用到"AVAudioPlayer"类

3、通过NSTimer处理音量显示

4、注意添加framework(AVFoundation.frameworkAudioToolbox.framework

5、只可以用来播放本地音频文件,即使是网络音频也是先下载到本地,然后再进行播放


1 主要代码

#import 

@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 
#import 
#import "AppDelegate.h"

@interface AudioRecorder () 

@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];
}


你可能感兴趣的:(iOS,多媒体,音频,录音,多媒体)