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

时间:2021-10-01 05:52:23

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


Demo下载地址


音频开发注意事项

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

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

3、通过NSTimer处理音量显示

4、注意添加framework(AVFoundation.frameworkAudioToolbox.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];
}