iOS音频开发之音频录制与播放

1.录音

录音使用的对象是AVAudioRecorder对象,其录音步骤分为一下几个步骤:
(1)初始化一个全局会话AVAudioSession,并设置会话种类:[_session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
(2)//激活全局会话:[_session setActive:YES error:nil];
(3)指定音频存储路径
(4)设置录音相关参数并初始化录音器对象AVAudioRecorder
(5)设置录音缓冲并开始录制:[_recoder prepareToRecord], [_recoder record];
其实现代码如下:

///录音/取消/完成
- (void)recordAction:(UIButton *)sender {
    if (sender.tag == 132343 ) {
        //取消 删除录制的音频
        _timeLabel.text = @"00:00:00";
        if (_recordButtons[1].selected) {
            _recordButtons[1].selected = NO;
            [_timer invalidate];
            _timer = nil;
        }
        NSFileManager *manager = [NSFileManager defaultManager];
        if ([manager  fileExistsAtPath:_filePath]) {
            //删除路径下的录音文件
            BOOL isDeleteSucess = [manager removeItemAtPath:_filePath error:nil];
            if (isDeleteSucess) {
                iToastMsg(@"请重新录制!");
            }
        } else {
            iToastMsg(@"未录制音频!");
        }
    }else if (sender.tag ==132344 ) {
        //录音或者暂停
        sender.selected = ! sender.selected;
        if (sender.selected) {
            iToastMsg(@"开始录音!!!");
            //初始化全局会话
            _session = [AVAudioSession sharedInstance];
            NSError *sessionError;
            //设置会话种类
            [_session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
            //激活全局会话
            if (_session) {
                [_session setActive:YES error:nil];
            }
            //时间戳
            NSDateFormatter *nameforamt = [NSDateFormatter new];
            [nameforamt setDateFormat:kDateFormat_yyyyMdHms];
            NSString *dateStr = [ nameforamt stringFromDate:[NSDate date]];
            //指定音频存储路径
            _filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.wav",dateStr]];
            DLog(@"path = %@",_filePath);
            _recoderUrl = [NSURL fileURLWithPath:_filePath];
            //设置录音参数
            NSDictionary *recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
                                           [NSNumber numberWithFloat: 8000.0],AVSampleRateKey,
                                           [NSNumber numberWithInt: kAudioFormatLinearPCM],AVFormatIDKey,
                                           [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
                                           [NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
                                           [NSNumber numberWithInt:AVAudioQualityMax],AVEncoderAudioQualityKey,
                                           nil];
            NSError *initError;
            //初始化录音器
            _recoder = [[AVAudioRecorder alloc] initWithURL:_recoderUrl
                                                   settings:recordSetting
                                                      error:&initError];
            if (_recoder) {
                _recoder.meteringEnabled = YES;
                //开始录音
                [_recoder prepareToRecord];
                [_recoder record];
                __block NSInteger hour = 0;
                __block NSInteger minute = 0;
                //定时器计算录音时长
                _timer = [NSTimer scheduledTimerWithTimeInterval:1
                                                         repeats:YES
                                                           block:^(NSTimer * _Nonnull timer) {
                                                               _seconds ++;
                                                               if (_seconds>60) {
                                                                   minute ++;
                                                                   _seconds = 0;
                                                               }
                                                               if (minute>60) {
                                                                   minute = 0;
                                                                   hour ++;
                                                               }
                                                               NSString *secondstr= [NSString stringWithFormat:@"%@%zd" ,_seconds< 10 ? @"0":@"" ,_seconds];
                                                               NSString *minuteStr= [NSString stringWithFormat:@"%@%zd" ,minute< 10 ? @"0":@"" ,minute];
                                                               NSString *hourStr= [NSString stringWithFormat:@"%@%zd" ,hour< 10 ? @"0":@"" ,hour];
                                                               _timeLabel.text = [NSString stringWithFormat:@"%@:%@:%@",hourStr,minuteStr,secondstr];
                                                           }];
                [[NSRunLoop currentRunLoop]  addTimer:_timer forMode:NSRunLoopCommonModes];
            } else {
                iToastMsg([initError description]);
            }
        } else {
            iToastMsg(@"停止录音!!!");
            if ([_recoder isRecording]) {
                [_recoder stop];
            }
            _totalTimeLabel.text = _timeLabel.text;
            NSFileManager *manager = [NSFileManager defaultManager];
            //计算文件大小
            if ([manager fileExistsAtPath:_filePath]){
                NSString *tipStr = [NSString stringWithFormat:@"录了 %@,文件大小为 %.2fMB",_timeLabel.text,[[manager attributesOfItemAtPath:_filePath error:nil] fileSize]/1024.0/1024.0];
                iToastMsg(tipStr);
            }
            //销毁定时器
            if ([_timer isValid]) {
                [_timer invalidate];
                _timer = nil;
            }
        }
    }
}

2.播放

这里实现播放音频的对象是AVAudioPlayer,值的注意的是这里的AVAudioPlayer音频播放器只能播放本地文件,并且是一次性加载所有的音频数据.这里不做网络流媒体的边下载边实现播放的功能,播放本地的音频文件相对简单,其实现代码如下所示:

    NSError *error;
    _player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:_filePath] error:&error];
    //设置代理
    _player.delegate = self;
- (void)playOrPause:(UIButton *)sender {
    if (!_filePath.length) {
        iToastMsg(@"未录制音频!");
        return ;
    }
    if ([_timer isValid]) {
        iToastMsg(@"正在录制!");
        return;
    }
    sender.selected = !sender.selected;
    if (sender.selected) {
        //播放
        [_player play];
        //定时器计算播放进度
        [NSTimer scheduledTimerWithTimeInterval:0.01
                                        repeats:YES
                                          block:^(NSTimer * _Nonnull timer) {
                                              NSTimeInterval currentTime = _player.currentTime;
                                              NSInteger hour = currentTime / 3600;
                                              NSInteger minute = currentTime / 60;
                                              NSInteger second = ((NSInteger) currentTime) %60;
                                              NSString *secondstr= [NSString stringWithFormat:@"%@%zd" ,second< 10 ? @"0":@"" ,second];
                                              NSString *minuteStr= [NSString stringWithFormat:@"%@%zd" ,minute< 10 ? @"0":@"" ,minute];
                                              NSString *hourStr= [NSString stringWithFormat:@"%@%zd" ,hour< 10 ? @"0":@"" ,hour];
                                              _playCurrentTimeLabel.text = [NSString stringWithFormat:@"%@:%@:%@",hourStr,minuteStr,secondstr];
                                              float floatValue = currentTime/_seconds;
                                              [_progressView setProgress:floatValue animated:YES];
                                          }];
    } else {
        //暂停
        if ([_player isPlaying]) {
            [_player pause];
        }
    }
}

//清除缓存
- (void)deleteCaches {
    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSFileManager *manager = [NSFileManager defaultManager];
    NSArray *paths = [manager contentsOfDirectoryAtPath:documentPath error:nil];
    //删除音频文件
    for (int i = 0; i < paths.count; i ++) {
        NSString *subPath  = paths[i];
        if ([subPath rangeOfString:@"wav"].length) {
            if ([manager  isDeletableFileAtPath:subPath]) {
                [manager  removeItemAtPath:subPath error:nil];
            }
        }
    }
}
#pragma mark --AVAudioPlayerDelegate
//监听播放完成
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    iToastMsg(@"播放完成");
    _playButton.selected = NO;
}

其效果如下所示:


录音与播放.png

如果您觉着本文对您有帮助的话,请动用您宝贵的双手点个赞!谢谢!
作者---------mrChan1234

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容