美文网首页
AVFoundation-播放和录制音频

AVFoundation-播放和录制音频

作者: 亡灵诅咒 | 来源:发表于2019-11-12 22:14 被阅读0次

目标

学习AVAudioPlayer和AVAudioRecorder类来实现音频播放及录制功能

理解音频会话

iOS默认音频会话的预配置

  • 激活了音频播放,但是音频录制未激活
  • 当用户切换响铃/静音开关到“静音”模式时,应用程序播放的所有音频都会消失
  • 当设备显示解锁屏幕时,应用程序的音频处于静音状态
  • 当应用程序播放音频时,所有后台播放的音频都会处于静音状态

音频会话分类

屏幕快照 2019-11-12 下午10.05.39.png
  • 上述分类提供满足大部分需求的常见行为,如果需要更加复杂的功能,其中一些分类通过使用options和modes方法进一步自定义开发

    • options让开发者使用一些附加行为(如Playback分类允许输出音频和背景声音混合)
    • modes可以通过引入被定制的行为进一步对分类进行修改以满足特殊需求

配置音频会话

  • 音频会话在应用程序的生命周期中是可以修改的,但通常只配置一次,就是在应用程序启动时
  • 通过设置合适的分类,可为音频的播放指定需要的音频会话,其中定制一些行为
    //配置音频会话
    AVAudioSession *session = [AVAudioSession sharedInstance];
    NSError *error = nil;
    if ([session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]) {
        NSLog(@"AVAudioSession setCategory error = %@",error.userInfo);
    }
    
    if ([session setActive:YES error:&error]) {
        NSLog(@"AVAudioSession setActive error = %@",error.userInfo);
    }
    

AVAudioPlayer播放音频

  • 初始化AVAudioPlayer(使用包含播放音频的内存版本的NSData,或本地音频文件的NSURL)
  • 建议调用其prepareToPlay方法,这样会取得需要的音频硬件并预加载Audio Queue的缓冲区,降低调用play方法和听到声音输出之间的延时
  • 通过pause和stop方法停止的音频都会继续播放,主要区别在底层处理上(stop方法会撤销调用prepareToPlay时所作的设置,而pause方法则不会)
  • 指定位置播放:currentTime
  • 修改播放器的音量:volume
  • 修改播放器的pan值: -1.0(极左), 1.0(极右),默认0.0居中
  • 调整播放率rate:iOS5加入,范围(0.5 - 2.0)半速-2倍速。前提条件需要设置enableRate属性
  • 无缝循环numberOfLoops:大于0可实现n次循环,-1无限循环(音频循环可以是未压缩的线性PCM音频,也可以是AAC之类的压缩格式音频。但是MP3格式音频要实现循环的目的通常需要使用特殊工具处理,建议使用AAC或AppleLossless格式循环)
-(void)adjustPan:(float)pan{
    self.player.pan = pan;
}

-(void)adjustVolume:(float)volume{
    self.player.volume = volume;
}

- (void)adjustRate:(float)rate{
    self.player.rate = rate;
}

-(AVAudioPlayer *)playerWithFile:(NSString *)file{
    NSURL *fileUrl = [NSURL fileURLWithPath:file];
    NSError *error = nil;
    
    AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:fileUrl error:&error];
    if (player) {
        //无限循环
        player.numberOfLoops = -1;
        player.delegate = self;
        //循序修改倍速
        player.enableRate = YES;
        [player prepareToPlay];
    }else{
        if ([self.delegate respondsToSelector:@selector(DKAudioPlayerManagerDidFailedWithError:target:)]) {
            [self.delegate DKAudioPlayerManagerDidFailedWithError:error target:self];
        }
    }
    return player;
}

音频会话通知

  • 中断通知AVAudioSessionInterruptionNotification,在通知响应函数中可以通过userInfo字典获取重要信息,就可以通过AVAudioSessionInterruptionTypeKey的值来确定中断类型,来标识中断开始或结束,做出响应处理

  • 线路改变通知AVAudioSessionRouteChangeNotification,在iOS设备上添加或移除音频输入、输出线路时,会发生线路改变。

    • userInfo字典中通过AVAudioSessionRouteChangeReasonKey来获取中断原因。

    • userInfo字典中通过AVAudioSessionRouteChangePreviousRouteKey字典来获取线路描述对象。

      • 线路描述对象整合了一个inputs和outputs的输入输出数组,数组中都是AVAudioSessionPortDescription实例对象,用于描述不同的I/O接口属性
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeRate:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeRate:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
通知处理
    NSDictionary *userInfo = noti.userInfo;
    //AVAudioSessionInterruptionTypeKey 确认系统中断类型
    //来电、QQ微信语音、其他音乐软件暂停
    AVAudioSessionInterruptionType reason = [userInfo[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
    
    //中断开始
    if (reason == AVAudioSessionInterruptionTypeBegan) {
        if (self.isPlaying) {
            [self stop];
            if ([self.delegate respondsToSelector:@selector(DKAudioPlayerManagerPlayBackStoppedWithTarget:)]) {
                [self.delegate DKAudioPlayerManagerPlayBackStoppedWithTarget:self];
            }
        }
    }else if (reason == AVAudioSessionInterruptionTypeEnded){
        //中断结束
        if (!self.isPlaying) {
            [self play];
            if ([self.delegate respondsToSelector:@selector(DKAudioPlayerManagerPlayBackBeginWithTarget:)]) {
                [self.delegate DKAudioPlayerManagerPlayBackBeginWithTarget:self];
            }
        }
    }
通知处理
    
    //线路切换监听
    AVAudioSessionRouteChangeReason reason1 = [userInfo[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
    //旧音频设备中断原因
    if (reason1 == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
        //线路描述信息
        AVAudioSessionRouteDescription *previousRoute = userInfo[AVAudioSessionRouteChangePreviousRouteKey];
        //第一个输出接口并判断是否是耳机接口
        AVAudioSessionPortDescription *previousOutput = previousRoute.outputs[0];
        NSString *portType = previousOutput.portType;
        if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {
            [self stop];
            //输出到有线耳机
            if ([self.delegate respondsToSelector:@selector(DKAudioPlayerManagerPlayBackStoppedWithTarget:)]) {
                [self.delegate DKAudioPlayerManagerPlayBackStoppedWithTarget:self];
            }
        }
    }

AVAudioRecorder录制音频

初始化AVAudioRecorder实例(1.用于表示音频流写入文件的本地URL,2.包含用于配置录音会话健值信息的字典,3.用于捕获初始化阶段各种错误饿NSError指针)
prepareToPlay,这个方法执行底层Audio Queue初始化的必要过程。该方法还在URL参数指定的位置创建一个文件,将录制启动时的延迟降到最低
音频格式(指定的音频格式一定要和URL参数定义的文件类型兼容)

  • kAudioFormatLinearPCM
  • kAudioFormatMPEG4AAC
  • kAudioFormatAppleLossless
  • kAudioFormatAppleIMA4
  • kAudioFormatilBC
  • kAudioFormatULaw
    采样率
  • AVSampleRateKey定义录音器的采样率。采样率定义了对输入的模拟音频信号每一秒的采样数。对音频的质量以及最终文件大小起到重要作用。尽量使用标准的采样率(8000、16000、22050、44100)
    通道数
  • AVNumberOfChannelsKey用于定义记录音频内容的通道数。1意味着使用单声道,2意味着立体声录制。
    指定格式的键
  • 处理Linear PCM或压缩音频格式时,可以定义一些其他指定格式的键
    配置音频会话
  • AVAudioSessionCategoryPlayAndRecord这个分类既可以录音有需要对外播放
    currentTime属性,因为该属性不可见,所以无法使用KVO来监听
初始化

-(instancetype)init{
    if (self = [super init]) {

        NSURL *url = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"memo.caf"]];
        NSDictionary *settings = @{
                                   AVFormatIDKey: @(kAudioFormatAppleIMA4),
                                   AVSampleRateKey:@441000.0f,
                                   AVNumberOfChannelsKey:@1,
                                   AVEncoderBitDepthHintKey:@16,
                                   AVEncoderAudioQualityKey:@(AVAudioQualityMedium)
                                   };
        NSError *error = nil;
        self.recorder = [[AVAudioRecorder alloc]initWithURL:url settings:settings error:&error];
        if (self.recorder) {
            self.recorder.delegate = self;
            self.recorder.meteringEnabled = YES;
            [self.recorder prepareToRecord];
        }else{
            if (self.delegate && [self.delegate respondsToSelector:@selector(DKAudioRecorderManagerDidFailedWithError:)]) {
                [self.delegate DKAudioRecorderManagerDidFailedWithError:error];
            }
        }
    }
    return self;
}

Audio Metering

可以读取音频的平均分贝(averagePowerForChannel:)和峰值分贝(peakPowerForChannel:),[-160dB, 0db] 最小/禁音分贝-- 最大分贝
在读取之前需要设置录音器的meteringEnabled属性才支持对音频进行测量

相关文章

  • AVFoundation-播放和录制音频

    1 音频会话 1.1 分类 category iOS 利用音频会话(audio session)实现可管理的音频环...

  • AVFoundation-播放和录制音频

    目标 学习AVAudioPlayer和AVAudioRecorder类来实现音频播放及录制功能 理解音频会话 iO...

  • AVFoundation框架 (二) 音频播放

    播放和录制音频 学习使用AVAudioPlayer和AVAudioRecorder类的实现音频播放和录制功能. 1...

  • iOS相关 | swift 录音和播放本地音频,播放流音频

    音频录制和本地音频播放:/*音频录制和播放类*/ 使用时根据单例调用方式调用即可:AudioRecordManag...

  • 音频

    音频的 播放 和 录制

  • 音频录制和播放

    在做产品需求的时候,音频录制播放,然后多条语音的播放和进度效果遇到了一些bug花费了些时间,希望对遇到的小伙伴有帮...

  • 播放和录制音频

    1理解音频会话。 所有的iOS应用程序都具有音频会话,无论其是否使用。默认音频会话来自以下一些配置:1.激活了音频...

  • 二、播放和录制音频

    理解音频会话 音频会话在应用程序和操作系统之间扮演着中间人的角色。意思就是开发者可以利用音频会话与iOS音频环境交...

  • AVFoundation播放和录制音频

    官方文档的摘要部分一开始就提到了AVAudioPlayer.AVAudioRecorder.这两个类 There ...

  • iOS播放和录制音频

    音频会话分类 AV Foundation 定义了 7 种分类来描述应用程序所使用的音频行为。 配置音频会话 使用A...

网友评论

      本文标题:AVFoundation-播放和录制音频

      本文链接:https://www.haomeiwen.com/subject/cxlcictx.html