本例子使用Core Audio实现类似于微信的音频对讲功能,可以录音和播放并且实现了听筒模式和扬声器模式的切换。录音主要使用AVAudioRecorder类来实现录音功能,播放则使用AVAudioPlayer类来实现播放音频功能,扬声器和听筒模式的切换是通过设置AVAudioSession类的属性值来实现切换效果。

- (void)viewDidLoad
{
    [super viewDidLoad];
    //创建录音按钮
    UIButton* recorderB = [[[UIButton alloc]initWithFrame:CGRectMake(20, 220, 60, 40)]autorelease];
    [recorderB setTitle:@"record" forState:UIControlStateNormal];
    [recorderB setBackgroundColor:[UIColor grayColor]];
    [recorderB addTarget:self action:@selector(prerecord:) forControlEvents:UIControlEventTouchDown];
    [recorderB addTarget:self action:@selector(startrecord:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:recorderB];
    
    //创建播放按钮
    UIButton* play = [[[UIButton alloc]initWithFrame:CGRectMake(230, 220, 60, 40)]autorelease];
    [play setTitle:@"play" forState:UIControlStateNormal];
    [play setBackgroundColor:[UIColor grayColor]];
    [play addTarget:self action:@selector(play:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:play];
    
    //创建听筒模式和扬声器模式切换按钮
    change = [[[UISwitch alloc]initWithFrame:CGRectMake(120, 225, 40, 40)]autorelease];
    //默认设置为没有打开,则用听筒模式
    [change setOn:NO];
    [change addTarget:self action:@selector(change:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:change];
    
}

//切换按钮事件
-(void)change:(UISwitch*)sender{
    NSLog(@"%@",NSStringFromSelector(_cmd));
     //录音的时候因为设置的音频会话是录音模式,所以录音完成后要把音频会话设置回听筒模式或者扬声器模式,根据切换器的值判断,kAudioSessionOverrideAudioRoute_None为听筒模式,kAudioSessionOverrideAudioRoute_Speaker为扬声器模式
    UInt32 audioRouteOverride = ![sender isOn] ?kAudioSessionOverrideAudioRoute_None:kAudioSessionOverrideAudioRoute_Speaker;
    AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession setActive:YES error:nil];
}

//录音事件
-(void)record:(id)sender{
        //获取当前应用的AudioSession,每个应用都有自己唯一的声频会话
        AVAudioSession * audioSession = [AVAudioSession sharedInstance];
        NSError* error1;
        //设置当前应用的声频会话为录音模式
        /*
        Use this category for background sounds such as rain, car engine noise, etc.
         Mixes with other music.
         
         AVF_EXPORT NSString *const AVAudioSessionCategoryAmbient;
         
         Use this category for background sounds.  Other music will stop playing.     AVF_EXPORT NSString *const AVAudioSessionCategorySoloAmbient;
         
         Use this category for music tracks.
         
         AVF_EXPORT NSString *const AVAudioSessionCategoryPlayback;
         
         Use this category when recording audio.
         
         AVF_EXPORT NSString *const AVAudioSessionCategoryRecord;
         
         Use this category when recording and playing back audio.
         
         AVF_EXPORT NSString *const AVAudioSessionCategoryPlayAndRecord;
         
         Use this category when using a hardware codec or signal processor while
         not playing or recording audio.
         
         AVF_EXPORT NSString *const AVAudioSessionCategoryAudioProcessing;
         */
        [audioSession setCategory:AVAudioSessionCategoryRecord error: &error1];
        //激活音频会话
        [audioSession setActive:YES error: &error1];
        NSLog(@"record...");
        //创建录音的文件保存位置
        NSString* filepath = [DOCUMENT_PATH stringByAppendingPathComponent:@"test.caf"];
        url = [[NSURL fileURLWithPath:filepath]retain];
        NSLog(@"path:%@",filepath);
        //设置录音的相关属性
        NSMutableDictionary *settings = [[NSMutableDictionary alloc] init];
        //设置音频格式
        [settings
         setValue:[NSNumber numberWithInteger:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
        //设置采用率
        [settings
         setValue:[NSNumber numberWithFloat:44100.0f] forKey:AVSampleRateKey];
        //设置频道
        [settings
         setValue:[NSNumber numberWithInteger:2] forKey:AVNumberOfChannelsKey];
        //设置录音质量
        [settings
         setValue:[NSNumber numberWithInteger:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];
        NSError* error;
        recorder = [[AVAudioRecorder alloc]initWithURL:url settings:settings error:&error];
        recorder.delegate = self;
        //录音准备,会为建立录音文件做好需要的准备
        BOOL isrecord = [recorder prepareToRecord];
        NSLog(@"isrecord:%d",isrecord);
        //正式开始录音
        [recorder record];
        NSLog(@"record begin...");

}
//手指离开点击录音按钮的事件
-(void)startrecord:(id)sender{

NSLog(@"%@",NSStringFromSelector(_cmd));
    NSTimeInterval now = [[NSDate date]timeIntervalSince1970];
    //获取长按录音按钮的时间
    NSTimeInterval offset = now - starttime;
    NSLog(@"offset:%f",offset);
    //如果长按的时间少于1秒,则不录音
    if (offset<=1) {
        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(record:) object:self];
    }else{
        //超过一秒,则完成录音,停止继续录音
        [self stoprecorder:recorder];
    }
}
//手指点击录音按钮时间
-(void)prerecord:(id)sender{
    NSLog(@"%@",NSStringFromSelector(_cmd));
    //获取点击的时间
    starttime = [[NSDate date]timeIntervalSince1970];
    NSLog(@"starttime:%f",starttime);
    //点击超过一秒后才正式录音
    [self performSelector:@selector(record:) withObject:self afterDelay:1];
}

//停止录音的事件
-(void)stoprecorder:(AVAudioRecorder*)sender{
    NSLog(@"%@",NSStringFromSelector(_cmd));
    //判断是否还在录音,如果是就停止
    if ([recorder isRecording]) {
        [recorder stop];
    }
   
}
//播放事件
-(void)play:(id)sender{
   
    NSLog(@"%@",NSStringFromSelector(_cmd));
    NSError* error;
    NSLog(@"url:%@",url);
    //通过AVAudioPlayer打开刚才录音的文件
    AVAudioPlayer* player = [[AVAudioPlayer alloc]initWithData:[NSData dataWithContentsOfURL:url] error:&error];
    //AVAudioPlayer预处理,为需要播放做好准备
    BOOL isplay = [player prepareToPlay];
    NSLog(@"isplay:%d",isplay);
  //  player.volume = 1;
    player.delegate = self;
    //正式播放
    [player play];
}
- (void)didReceiveMemoryWarning
{
    
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
//录音完成后的回调事件
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{
    NSLog(@"%@",NSStringFromSelector(_cmd));
    //录音完成后关闭释放资源
    if ([recorder isRecording]) {
        [recorder stop];
    }
    [recorder release];
    //录音的时候因为设置的音频会话是录音模式,所以录音完成后要把音频会话设置回听筒模式或者扬声器模式,根据切换器的值判断,kAudioSessionOverrideAudioRoute_None为听筒模式,kAudioSessionOverrideAudioRoute_Speaker为扬声器模式
    UInt32 audioRouteOverride = ![change isOn] ?kAudioSessionOverrideAudioRoute_None:kAudioSessionOverrideAudioRoute_Speaker;
    AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    //类别要AVAudioSessionCategoryPlayAndRecord,才有效
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    [audioSession setActive:YES error:nil];
    
}

//录音编码出错的回调
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error{
    NSLog(@"%@",NSStringFromSelector(_cmd));
    [recorder release];
}
//播放音频完成后的回调
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
     NSLog(@"%@",NSStringFromSelector(_cmd));
    //成功播放完音频后释放资源
    if ([player isPlaying]) {
        [player stop];
    }
    [player release];
}

//音频播放解码出错的回调
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error{
 NSLog(@"%@",NSStringFromSelector(_cmd));
    [player release];
}

CoreAudio实现录音播音和扬声器听筒模式的切换的更多相关文章

  1. Android5.0版本之后切换听筒模式

    5.0以前Android听筒模式和扬声器模式这样就管用 扬声器://关闭麦克风  mAudioManager.setMicrophoneMute(false);  // 打开扬声器  mAudioMa ...

  2. CentOS下命令行和桌面模式的切换方法(转载)

    桌面模式和命令行模式的切换方法 用编辑器打开 /etc/inittab 文件(这里用的是vi,你可以选择你喜欢的): #vi /etc/inittab 打开效果图如下: 桌面模式    : 把光标所在 ...

  3. RENIX板卡V2-100G系列工作模式速率切换——网络测试仪实操

    本文主要介绍了RENIX板卡V2-100G系列工作模式速率切换相关操作.全文分为五部分内容.文章开头对V2-100G系列板卡进行了概述,之后分别详细介绍了100G工作模式.40G工作模式.25G工作模 ...

  4. virtaulbox视图模式常用切换

    virtaulbox发现菜单不见,如何切换视图模式呢? 很简单,通过快捷键主机(host)键 Host+F                                          换到全屏模 ...

  5. DGbroker三种保护模式的切换

    1.三种保护模式 – Maximum protection 在Maximum protection下, 可以保证从库和主库数据完全一样,做到zero data loss.事务同时在主从两边提交完成,才 ...

  6. IIS32位,64位模式下切换

    一.32位模式 1.cscript %systemdrive%\inetpub\adminscripts\adsutil.vbs set w3svc/appPools/enable32bitappon ...

  7. Oracle数据库归档模式的切换及其相关操作详解

    SQL> shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL> ...

  8. Linux中图形界面和文本模式相互切换

    1.默认开机进入文本模式 如果想让开机自动进纯文本模式, 修改/etc/inittab 找到其中的 id:5:initdefault: 这行指示启动时的运行级是5,也就是图形模式 改成3就是文本模式了 ...

  9. 使用exchange普通表模式被切换到分区表

    随着数据库的不断增长的数据量.有些表需要转换的普通堆表分区表模式. 有几种不同的方式来执行此操作,如出口数据表,区表再导入数据到分区表:使用EXCHANGE PARTITION方式来转换为分区表以及使 ...

随机推荐

  1. Jvm内存区域和GC

    运行时数据区域 线程私有 程序计数器 正在执行的字节码指令的地址(native方法时为undefined) Java虚拟机栈 存储栈帧(局部变量表,操作数栈,动态链接,方法出口)OOM,StackOv ...

  2. 浅谈Comparable与Comparator的区别

    平时进行自定义排序一直使用实现Comparable接口,一段时间后操作的时候居然发现有了个Comparator接口 上网差了些资料,总结笔记一下. 基本原理就是比较,底层是二叉树 比如是3,6,5,1 ...

  3. APPKIT打造稳定、灵活、高效的运营配置平台

    一.背景 美团App.大众点评App都是重运营的应用.对于App里运营资源.基础配置,需要根据城市.版本.平台.渠道等不同的维度进行运营管理.如何在版本快速迭代过程中,保持运营资源能够被高效.稳定和灵 ...

  4. MCI:移动持续集成在大众点评的实践

    一.背景 美团是全球最大的互联网+生活服务平台,为3.2亿活跃用户和500多万的优质商户提供一个连接线上与线下的电子商务服务.秉承“帮大家吃得更好,生活更好”的使命,我们的业务覆盖了超过200个品类和 ...

  5. UNP学习总结(一)

    本文主要为对UNP第五章部分内容的实验和总结. UNP第五章对一个echo服务器和客户端在各种连接状态下的表现做了详细的分析,包括了: 正常启动和终止: accept返回前连接中止: 服务器进程终止: ...

  6. Django MiddleWare初识

    一.Django 中间件介绍 中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件组件都负责做一些特定 ...

  7. android 注册广播接受者

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 动态注册 静态注册 动态注册是 通过java代码,注册. 静态注册 是xml清单文件中 ...

  8. 【UOJ #221】【NOI 2016】循环之美

    http://uoj.ac/problem/221 因为\(a\)和\(b\)不互质时,\(\frac ab=\frac{\frac a{(a,b)}}{\frac b{(a,b)}}\),所以只用求 ...

  9. vijos p1876 bfs+map

    题意: Xiaodao是一位喜欢参加ACM比赛的孩子. 所谓ACM比赛, 是一种团队比赛. 每一次比赛, 每队需要由恰好三位选手组成. 现在, Xiaodao希望组建一支新的队伍, 在这之前, 他需要 ...

  10. hdoj 5182 PM2.5 排序

    PM2.5 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Descr ...