iOS开发之音频播放、录音

iOS的音频播放可以分为短音频播放(例如:音效等点缀音频)和长音频播放(例:音乐等主音频)。前者不需要对进度、循环等进行控制,而后者需要精确的控制。在iOS中播放这两种音频分别使用AudioToolbox.framework和AVFoundation.framework来完成。

短音频音效

AudioToolbox.framework是一套基于C语言的框架,使用它来播放音效其本质是将短音频注册到系统声音服务(System Sound Service)。System Sound Service是一种简单、底层的声音播放服务,但是它本身也存在着一些限制:

  • No longer than 30 seconds in duration(播放时间小于30s)
  • In linear PCM or IMA4 (IMA/ADPCM) format(数据必须是pcm或者ima4格式的)
  • Packaged in a .caf.aif, or .wav file(音频文件必须打包成.caf,.aif,.wav文件)

使用System Sound Service 播放音效的步骤如下(封装成一个播放短音频的工具类):

+ (void)initialize {
    // 加载所有音频文件
    // 1.遍历所有的plane.bundle的所有的音频文件
    NSFileManager *manage = [NSFileManager defaultManager];

    // 2.获了plane.bundle的路径
    NSString *planePath   = [[NSBundle mainBundle] pathForResource:@"plane.bundle" ofType:nil];

    NSArray *contents     = [manage contentsOfDirectoryAtPath:planePath error:nil];

    // 3.遍历里面的mp3文件,创建SystemSoundID;
    NSMutableDictionary *soundDictM = [NSMutableDictionary dictionary];

    for (NSString *soundName in contents) {
        // 音频的URL
        NSString *soundUrlPath = [planePath stringByAppendingPathComponent:soundName];

        NSURL *soundUrl       = [NSURL fileURLWithPath:soundUrlPath];

        SystemSoundID soundID;

        // 创建声音
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundUrl, &soundID);

        soundDictM[soundName] = @(soundID);
    }
    soundDict = soundDictM;
}

- (void)playShortSoundWithName:(NSString *)soundName {
    // 播放声音
    AudioServicesPlaySystemSound([soundDict[soundName] unsignedIntValue]);
}

长音频播放(使用AVFoundation.framework的AVAudioPlayer实现)

AVAudioPlayer的使用就比较简单了:

  1. 初始化AVAudioPlayer对象,此时通常指定本地文件路径。
  2. 设置播放器的属性,例如重复次数、音量大小等。
  3. 调用play方法播放.
属性 说明
@property(readonly, getter=isPlaying) BOOL playing 是否正在播放,只读
@property(readonly) NSUInteger numberOfChannels 音频声道数,只读
@property(readonly) NSTimeInterval duration 音频时长
@property(readonly) NSURL *url 音频文件路径,只读
@property(readonly) NSData *data 音频数据,只读
@property float pan 立体声平衡,如果为-1.0则完全左声道,如果0.0则左右声道平衡,如果为1.0则完全为右声道
@property float volume 音量大小,范围0-1.0
@property BOOL enableRate 是否允许改变播放速率
@property float rate 播放速率,范围0.5-2.0,如果为1.0则正常播放,如果要修改播放速率则必须设置enableRate为YES
@property NSTimeInterval currentTime 当前播放时长
@property(readonly) NSTimeInterval deviceCurrentTime 输出设备播放音频的时间,注意如果播放中被暂停此时间也会继续累加
@property NSInteger numberOfLoops 循环播放次数,如果为0则不循环,如果小于0则无限循环,大于0则表示循环次数
@property(readonly) NSDictionary *settings 音频播放设置信息,只读
@property(getter=isMeteringEnabled) BOOL meteringEnabled 是否启用音频测量,默认为NO,一旦启用音频测量可以通过updateMeters方法更新测量值
对象方法 说明
- (instancetype)initWithContentsOfURL:(NSURL *)url error:(NSError **)outError 使用文件URL初始化播放器,注意这个URL不能是HTTP URL,AVAudioPlayer不支持加载网络媒体流,只能播放本地文件
- (instancetype)initWithData:(NSData *)data error:(NSError **)outError 使用NSData初始化播放器,注意使用此方法时必须文件格式和文件后缀一致,否则出错,所以相比此方法更推荐使用上述方法或- (instancetype)initWithData:(NSData *)data fileTypeHint:(NSString *)utiString error:(NSError **)outError方法进行初始化
- (BOOL)prepareToPlay; 加载音频文件到缓冲区,注意即使在播放之前音频文件没有加载到缓冲区程序也会隐式调用此方法。
- (BOOL)play; 播放音频文件
- (BOOL)playAtTime:(NSTimeInterval)time 在指定的时间开始播放音频
- (void)pause; 暂停播放
- (void)stop; 停止播放
- (void)updateMeters 更新音频测量值,注意如果要更新音频测量值必须设置meteringEnabled为YES,通过音频测量值可以即时获得音频分贝等信息
- (float)peakPowerForChannel:(NSUInteger)channelNumber;  获得指定声道的分贝峰值,注意如果要获得分贝峰值必须在此之前调用updateMeters方法
- (float)averagePowerForChannel:(NSUInteger)channelNumber 获得指定声道的分贝平均值,注意如果要获得分贝平均值必须在此之前调用updateMeters方法
@property(nonatomic, copy) NSArray *channelAssignments 获得或设置播放声道
代理方法 说明
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag 音频播放完成
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error 音频解码发生错误

下面就使用AVAudioPlayer实现一个简单播放器,在这个播放器中实现了播放、暂停、显示播放进度功能,当然例如调节音量、设置循环模式、甚至是声波图像(通过分析音频分贝值)等功能都可以实现,这里就不再一一演示。界面效果如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

}

- (IBAction)stop:(id)sender {
    /**
     *  Stops playback and undoes the setup needed for playback.
     */
    [_player stop];

    // 自己指定播放的时间
    _player.currentTime = 0;
}

- (IBAction)start:(id)sender {
    // 获取mp3路径
    NSURL *mp3Url = [[NSBundle mainBundle] URLForResource:@"bbqne.mp3" withExtension:nil];

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _player            = [[AVAudioPlayer alloc] initWithContentsOfURL:mp3Url error:nil];

        /**
         *  A Boolean value that specifies whether playback rate adjustment is enabled for an audio player.
         */
        _player.enableRate = YES;

        /**
         *  Prepares the audio player for playback by preloading its buffers.
         */
        [_player prepareToPlay];

        // 这里不能加全局断点,不然会崩
        /**
         *  The number of times a sound will return to the beginning, upon reaching the end, to repeat playback.
         */
        _player.numberOfLoops    = MAXFLOAT;

        _player.delegate         = self;

        _displayLink             = [CADisplayLink displayLinkWithTarget:self
                                                               selector:@selector(playMusic)];

        [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];

        AVAudioSession *session  = [AVAudioSession sharedInstance];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(handleInterruption:)
                                                     name:AVAudioSessionInterruptionNotification
                                                   object:session];

        _timeSlider.maximumValue = _player.duration;
    });

    /**
     *  Plays a sound asynchronously.
     */
    [_player play];

}
/**
 *  改变进度条
 */
- (void)playMusic {
    _timeSlider.value = _player.currentTime;

    int sec           = _timeSlider.value;

    _timeLabel.text   = [NSString stringWithFormat:@"%02d",sec];

    [_player updateMeters];

    double lowPassResults = pow(10, (0.05 * [self.player peakPowerForChannel:0]));

    float result  = 10 * (float)lowPassResults;

    NSLog(@"%.2f",result);
}

- (void)handleInterruption:(NSNotification *)noti {
    // 处理中断事件
    NSLog(@"处理中断事件");
}

- (IBAction)pause:(id)sender {
    /**
     *  Pauses playback; sound remains ready to resume playback from where it left off.
     */
    [_player pause];
}

/**
 *  指定当前播放的时间
 */
- (IBAction)timeChanged:(UISlider *)sender {
    _player.currentTime = sender.value;
}

/**
 *  改变播放速度
 */
- (IBAction)rateChange:(UISlider *)sender {
    _player.rate = sender.value;
}

/**
 *  改变播放音量
 */
- (IBAction)volunmChanged:(UISlider *)sender {
    _player.volume = sender.value;
}

录音

在AVFoundation框架中还要一个AVAudioRecorder类专门处理录音操作,它同样支持多种音频格式。与AVAudioPlayer类似,你完全可以将它看成是一个录音机控制类,下面是常用的属性和方法:

@property(readonly, getter=isRecording) BOOL recording; 是否正在录音,只读
@property(readonly) NSURL *url 录音文件地址,只读
@property(readonly) NSDictionary *settings 录音文件设置,只读
@property(readonly) NSTimeInterval currentTime 录音时长,只读,注意仅仅在录音状态可用
@property(readonly) NSTimeInterval deviceCurrentTime 输入设置的时间长度,只读,注意此属性一直可访问
@property(getter=isMeteringEnabled) BOOL meteringEnabled; 是否启用录音测量,如果启用录音测量可以获得录音分贝等数据信息
@property(nonatomic, copy) NSArray *channelAssignments 当前录音的通道
对象方法 说明
- (instancetype)initWithURL:(NSURL *)url settings:(NSDictionary *)settings error:(NSError **)outError 录音机对象初始化方法,注意其中的url必须是本地文件url,settings是录音格式、编码等设置
- (BOOL)prepareToRecord 准备录音,主要用于创建缓冲区,如果不手动调用,在调用record录音时也会自动调用
- (BOOL)record 开始录音
- (BOOL)recordAtTime:(NSTimeInterval)time 在指定的时间开始录音,一般用于录音暂停再恢复录音
- (BOOL)recordForDuration:(NSTimeInterval) duration 按指定的时长开始录音
- (BOOL)recordAtTime:(NSTimeInterval)time forDuration:(NSTimeInterval) duration 在指定的时间开始录音,并指定录音时长
- (void)pause; 暂停录音
- (void)stop; 停止录音
- (BOOL)deleteRecording; 删除录音,注意要删除录音此时录音机必须处于停止状态
- (void)updateMeters; 更新测量数据,注意只有meteringEnabled为YES此方法才可用
- (float)peakPowerForChannel:(NSUInteger)channelNumber; 指定通道的测量峰值,注意只有调用完updateMeters才有值
- (float)averagePowerForChannel:(NSUInteger)channelNumber 指定通道的测量平均值,注意只有调用完updateMeters才有值
代理方法 说明
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag 完成录音
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error

程序的构建主要分为以下几步:

  1. 设置音频会话类型为AVAudioSessionCategoryPlayAndRecord,因为程序中牵扯到录音和播放操作。
  2. 创建录音机AVAudioRecorder,指定录音保存的路径并且设置录音属性,注意对于一般的录音文件要求的采样率、位数并不高,需要适当设置以保证录音文件的大小和效果。
  3. 设置录音机代理以便在录音完成后播放录音,打开录音测量保证能够实时获得录音时的声音强度。(注意声音强度范围-160到0,0代表最大输入)
  4. 创建音频播放器AVAudioPlayer,用于在录音完成之后播放录音。
  5. 创建一个定时器以便实时刷新录音测量值并更新录音强度到UIProgressView中显示。
  6. 添加录音、暂停、恢复、停止操作,需要注意录音的恢复操作其实是有音频会话管理的,恢复时只要再次调用record方法即可,无需手动管理恢复时间等。

下面是主要代码

时间: 2024-10-24 04:09:36

iOS开发之音频播放、录音的相关文章

iOS开发系列--音频播放、录音、视频播放、拍照、视频录制

iOS开发系列--音频播放.录音.视频播放.拍照.视频录制 转载:http://www.cnblogs.com/kenshincui/p/4186022.html#avFoundationCamera --iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操作都提供了多套API.在今天的文章中将会对这些内容进行一一介绍: 音频 音

iOS开发系列--音频播放、录音、

音频 在iOS中音频播放从形式上可以分为音效播放和音乐播放.前者主要指的是一些短音频播放,通常作为点缀音频,对于这类音频不需要进行进度.循环等控制.后者指的是一些较长的音频,通常是主音频,对于这些音频的播放通常需要进行精确的控制.在iOS中播放两类音频分别使用AudioToolbox.framework和AVFoundation.framework来完成音效和音乐播放. 音效 AudioToolbox.framework是一套基于C语言的框架,使用它来播放音效其本质是将短音频注册到系统声音服务(

iOS开发之 音频播放

音频播放 1.介绍 - 功能介绍 用于播放比较长的音频.说明.音乐 ,使用到的是AVFoundation - 框架介绍 * AVAudioPlayer * 初始化: 注意 : (3)必须声明全局变量的音乐播放对象.或者是属性的音乐播放对象  才可以播放 (4)在退出播放页面的时候 一定要把播放对象置空  同时把delegate置空 导入框架:#import <AVFoundation/AVFoundation.h> 声明全局变量 @interface ViewController ()<

iOS开发—音乐的播放

iOS开发—音乐的播放 一.简单说明 音乐播放用到一个叫做AVAudioPlayer的类,这个类可以用于播放手机本地的音乐文件. 注意: (1)该类(AVAudioPlayer)只能用于播放本地音频. (2)时间比较短的(称之为音效)使用AudioServicesCreateSystemSoundID来创建,而本地时间较长(称之为音乐)使用AVAudioPlayer类. 二.代码示例 AVAudioPlayer类依赖于AVFoundation框架,因此使用该类必须先导入AVFoundation框

ios简单的音频播放

由于之前没有做过音频类的项目, 所以这次自己写了一个音频的小Demo能实现暂停播放循环等功能. 直接看代码: // 我使用的AVAudioPlayer, 首先先导入库文件, 写上头文件,签上代理 #import "ViewController.h" #import <AVFoundation/AVFoundation.h> typedef NS_ENUM(NSInteger, playStatus){ // 这个枚举用来控制暂停和播放的切换 playStatusNo, pl

OCiOS开发:音频播放器 AVAudioPlayer

简单介绍 AVAudioPlayer音频播放器可以提供简单的音频播放功能.其头文件包括在AVFoudation.framework中. AVAudioPlayer未提供可视化界面,须要通过其提供的播放控制接口自行实现. AVAudioPlayer仅能播放本地音频文件,并支持以下格式文件:.mp3..m4a..wav..caf..aif?. 经常用法 初始化方法 // 1.NSURL 它仅仅能从file://格式的URL装入音频数据,不支持流式音频及HTTP流和网络流. - (id)initWit

IOS开发之音频--录音

前言:本篇介绍录音. 内容大纲: 1.录音应用场景. 2.录音功能实现. 3.概念补充. 4.开发经验. 正文: 1.录音应用场景 ① 语言聊天:在即时通讯APP中,例如即时通讯APP中,例如微信.QQ等等,都有语音发送功能. ②语音备忘录:录一段音频,来记录某件事情. 2.录音功能实现 ①导入AVFoundation框架 一些多媒体的处理,基本都使用这个框架. ②使用AVAudioRecorder进行录音 <1>创建录音文件存放路径 <2>设置录音附件设置项(#import &l

iOS开发之音频口通信-通过方波来收发数据

之前做过的项目有需要通过音频口通信用方波来收发数据,由于这方面的资料比较少,下面就介绍下其原理,希望能给大家帮助. 一. 音频通信简介大家应该都知道支付宝声波支付和拉卡拉吧,它们都是利用手机的音频口(手机耳机口)来实现全双工的通信(手机与设备之间的双向通信).其优点是低成本,编码芯片成本低,手机的 3.5mm 通信接口广泛. 二. 市场应用支付宝声波支付手机刷卡器皮肤检测仪检测如甲醛.气压.温度.湿度等等心率.血压等等....................... 三. 通信原理手机上用的耳机大

iOS开发——WAVE音频文件解析

WAV文件也分了好几类,相应的非数据信息存储在文件的头部,下面简单的提一下,然后在最后重点介绍44字节的那种,一般用的都是这个. 1.8KHz采样.16比特量化的线性PCM语音信号的WAVE文件头格式表(共44字节) 偏移地址  字节数  数据类型   内容  文件头定义为 00H   4   char     "RIFF"  char riff_id[4]="RIFF"   04H   4   long   文件总长-8     long int size0=文总