【转载】iOS麦克风录制音频并保存成mp3文件的Demo

转自 tusm 写的一个录屏Demo,在此贴下Demo的源代码方便使用

使用的是AVFoundation 录制后麦克风输入的音频,录制结束后将数据转成了mp3格式并保存成文件

//
//  ViewController.m
//  AudioDemo
//
//  Created by tusm on 15/2/14.
//  Copyright (c) 2015年 tusm. All rights reserved.
//

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "lame.h"

#define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
#define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
#define NAVBAR_HEIGHT 40

#define TITLE_X (SCREEN_WIDTH/2-SCREEN_WIDTH/10)
#define TITLE_Y (1.5*NAVBAR_HEIGHT)
#define TITLE_WIDTH (SCREEN_WIDTH/5)
#define TITLE_HEIGHT NAVBAR_HEIGHT

#define RECORDBAR_X (SCREEN_WIDTH/2-SCREEN_WIDTH/4)
#define RECORDBAR_Y (TITLE_Y+TITLE_HEIGHT+NAVBAR_HEIGHT/2)
#define RECORDBAR_WIDTH (SCREEN_WIDTH/2)

#define TIME_X (SCREEN_WIDTH/2-SCREEN_WIDTH/8)
#define TIME_Y (RECORDBAR_Y+NAVBAR_HEIGHT)
#define TIME_WIDTH (SCREEN_WIDTH/4)
#define TIME_HEIGHT NAVBAR_HEIGHT

#define RECORDBUTTON_X (SCREEN_WIDTH/2-SCREEN_WIDTH/6)
#define RECORDBUTTON_Y (TIME_Y+TIME_HEIGHT+NAVBAR_HEIGHT/2)
#define RECORDBUTTON_WIDTH (SCREEN_WIDTH/3)
#define RECORDBUTTON_HEIGHT RECORDBUTTON_WIDTH

#define PLAYBUTTON_X (SCREEN_WIDTH/2-SCREEN_WIDTH/8)
#define PLAYBUTTON_Y (TIME_Y+2*TIME_HEIGHT)
#define PLAYBUTTON_WIDTH SCREEN_WIDTH/4
#define PLAYBUTTON_HEIGHT PLAYBUTTON_WIDTH

#define RECORE_BUTTON_TAG 1010
#define NEW_PLAY_BUTTON_TAG 1011
#define PAUSE_PLAY_BUTTON_TAG 1012
#define FINISH_BUTTON_TAG 1013
#define RECORDAGAIN_BUTTON_TAG 1014
#define PAUSE_BUTTON_TAG 1015

@implementation ViewController
{
    UILabel* recordTitleLabel;
    UISlider* progressView;
    UILabel* timeLabel;
    UIButton* recordButton;
    UILabel* recordLabel;

    NSTimer* timer;
    int recordTime;
    int playTime;
    int playDuration;
    int second;
    int minute;

    UIButton* playButton;
    UIButton* finishButton;
    UIButton* pauseButton;
    UIButton* recordAgainButton;

    UILabel* playLabel;
    UILabel* finishLabel;
    UILabel* pauseLabel;
    UILabel* recordAgainLabel;

    AVAudioRecorder *audioRecorder;
    AVAudioPlayer *audioPlayer;
    AVAudioSession * audioSession;

    NSURL* recordUrl;
    NSURL* mp3FilePath;
    NSURL* audioFileSavePath;
}

- (void)viewDidLoad {
    [self initializeUI];
}

- (void)initializeUI {
    playButton = [[UIButton alloc] initWithFrame:CGRectMake(PLAYBUTTON_X, PLAYBUTTON_Y, PLAYBUTTON_WIDTH, PLAYBUTTON_HEIGHT)];
    [playButton setImage:[UIImage imageNamed:@"play_button.png"] forState:UIControlStateNormal];
    playButton.tag = NEW_PLAY_BUTTON_TAG;
    [playButton addTarget:self action:@selector(clickOnButton:) forControlEvents:UIControlEventTouchUpInside];

    playLabel = [[UILabel alloc] initWithFrame:CGRectMake(PLAYBUTTON_X, PLAYBUTTON_Y+PLAYBUTTON_HEIGHT, PLAYBUTTON_WIDTH, NAVBAR_HEIGHT)];
    [playLabel setText:@"播放"];
    [playLabel setTextAlignment:NSTextAlignmentCenter];

    pauseButton = [[UIButton alloc] initWithFrame:CGRectMake(PLAYBUTTON_X, PLAYBUTTON_Y, PLAYBUTTON_WIDTH, PLAYBUTTON_HEIGHT)];
    [pauseButton setImage:[UIImage imageNamed:@"pause_button.png"] forState:UIControlStateNormal];
    pauseButton.tag = PAUSE_BUTTON_TAG;
    [pauseButton addTarget:self action:@selector(clickOnButton:) forControlEvents:UIControlEventTouchUpInside];

    pauseLabel = [[UILabel alloc] initWithFrame:CGRectMake(PLAYBUTTON_X, PLAYBUTTON_Y+PLAYBUTTON_HEIGHT, PLAYBUTTON_WIDTH, NAVBAR_HEIGHT)];
    [pauseLabel setText:@"暂停"];
    [pauseLabel setTextAlignment:NSTextAlignmentCenter];

    finishButton = [[UIButton alloc] initWithFrame:CGRectMake(PLAYBUTTON_X-PLAYBUTTON_WIDTH-10, PLAYBUTTON_Y, PLAYBUTTON_WIDTH, PLAYBUTTON_HEIGHT)];
    [finishButton setImage:[UIImage imageNamed:@"finish_button.png"] forState:UIControlStateNormal];
    finishButton.tag = FINISH_BUTTON_TAG;
    [finishButton addTarget:self action:@selector(clickOnButton:) forControlEvents:UIControlEventTouchUpInside];

    finishLabel = [[UILabel alloc] initWithFrame:CGRectMake(PLAYBUTTON_X-PLAYBUTTON_WIDTH-10, PLAYBUTTON_Y+PLAYBUTTON_HEIGHT, PLAYBUTTON_WIDTH, NAVBAR_HEIGHT)];
    [finishLabel setText:@"完成"];
    [finishLabel setTextAlignment:NSTextAlignmentCenter];

    recordAgainButton = [[UIButton alloc] initWithFrame:CGRectMake(PLAYBUTTON_X+PLAYBUTTON_WIDTH+10, PLAYBUTTON_Y, PLAYBUTTON_WIDTH, PLAYBUTTON_HEIGHT)];
    [recordAgainButton setImage:[UIImage imageNamed:@"record_again_button.png"] forState:UIControlStateNormal];
    recordAgainButton.tag = RECORDAGAIN_BUTTON_TAG;
    [recordAgainButton addTarget:self action:@selector(clickOnButton:) forControlEvents:UIControlEventTouchUpInside];

    recordAgainLabel = [[UILabel alloc] initWithFrame:CGRectMake(PLAYBUTTON_X+PLAYBUTTON_WIDTH+10, PLAYBUTTON_Y+PLAYBUTTON_HEIGHT, PLAYBUTTON_WIDTH, NAVBAR_HEIGHT)];
    [recordAgainLabel setText:@"重新录制"];
    [recordAgainLabel setTextAlignment:NSTextAlignmentCenter];

    recordTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(TITLE_X, TITLE_Y, SCREEN_WIDTH, TITLE_HEIGHT)];
    [recordTitleLabel setText:@"录制语音"];

    progressView = [[UISlider alloc] initWithFrame:CGRectMake(RECORDBAR_X, RECORDBAR_Y, RECORDBAR_WIDTH, 20)];
    [progressView setThumbImage:[UIImage imageNamed:@"one.png"] forState:UIControlStateNormal];
    progressView.value = 0;
    progressView.userInteractionEnabled = NO;

    timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(TIME_X, TIME_Y, TIME_WIDTH, TIME_HEIGHT)];
    [timeLabel setText:@"00:00"];
    [timeLabel setFont:[UIFont systemFontOfSize:32]];
    [timeLabel setTextColor:[UIColor blackColor]];

    recordButton = [[UIButton alloc] initWithFrame:CGRectMake(RECORDBUTTON_X, RECORDBUTTON_Y, RECORDBUTTON_WIDTH, RECORDBUTTON_HEIGHT)];
    recordButton.tag = RECORE_BUTTON_TAG;
    [recordButton addTarget:self action:@selector(clickOnButton:) forControlEvents:UIControlEventTouchUpInside];
    [recordButton setImage:[UIImage imageNamed:@"record_button.png"] forState:UIControlStateNormal];

    recordLabel = [[UILabel alloc] initWithFrame:CGRectMake(RECORDBUTTON_X, RECORDBUTTON_Y+RECORDBUTTON_HEIGHT, RECORDBUTTON_WIDTH, NAVBAR_HEIGHT/2)];
    [recordLabel setText:@"点击开始"];
    [recordLabel setTextAlignment:NSTextAlignmentCenter];

    //录音设置
    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
    //设置录音格式  AVFormatIDKey==kAudioFormatLinearPCM
    [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
    //设置录音采样率(Hz) 如:AVSampleRateKey==8000/44100/96000(影响音频的质量), 采样率必须要设为11025才能使转化成mp3格式后不会失真
    [recordSetting setValue:[NSNumber numberWithFloat:11025.0] forKey:AVSampleRateKey];
    //录音通道数  1 或 2 ,要转换成mp3格式必须为双通道
    [recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
    //线性采样位数  8、16、24、32
    [recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    //录音的质量
    [recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];

    //存储录音文件 (临时文件夹)
    recordUrl = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingString:@"selfRecord.caf"]];

    //初始化
    audioRecorder = [[AVAudioRecorder alloc] initWithURL:recordUrl settings:recordSetting error:nil];
    //开启音量检测
    audioRecorder.meteringEnabled = YES;
    audioRecorder.delegate = self;

    [self.view addSubview:recordTitleLabel];
    [self.view addSubview:progressView];
    [self.view addSubview:timeLabel];
    [self.view addSubview:recordButton];
    [self.view addSubview:recordLabel];
}

- (void)transformCAFToMP3 {
    mp3FilePath = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingString:@"myselfRecord.mp3"]];

    @try {
        int read, write;

        FILE *pcm = fopen([[recordUrl absoluteString] cStringUsingEncoding:1], "rb");   //source 被转换的音频文件位置
        fseek(pcm, 4*1024, SEEK_CUR);                                                   //skip file header
        FILE *mp3 = fopen([[mp3FilePath absoluteString] cStringUsingEncoding:1], "wb"); //output 输出生成的Mp3文件位置

        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE*2];
        unsigned char mp3_buffer[MP3_SIZE];

        lame_t lame = lame_init();
        lame_set_in_samplerate(lame, 11025.0);
        lame_set_VBR(lame, vbr_default);
        lame_init_params(lame);

        do {
            read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
            if (read == 0)
                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            else
                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);

            fwrite(mp3_buffer, write, 1, mp3);

        } while (read != 0);

        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
    }
    @catch (NSException *exception) {
        NSLog(@"%@",[exception description]);
    }
    @finally {
        audioFileSavePath = mp3FilePath;
        NSLog(@"MP3生成成功: %@",audioFileSavePath);
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"mp3转化成功!" message:nil delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }
}

- (void)clickOnButton:(UIButton*)sender {
    audioSession = [AVAudioSession sharedInstance];//得到AVAudioSession单例对象
    switch (sender.tag) {
        case RECORE_BUTTON_TAG:{
            if (![audioRecorder isRecording]) {
                [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];//设置类别,表示该应用同时支持播放和录音
                [audioSession setActive:YES error:nil];//启动音频会话管理,此时会阻断后台音乐的播放.

                [audioRecorder prepareToRecord];
                [audioRecorder peakPowerForChannel:0.0];
                [audioRecorder record];
                recordTime = 0;

                [self recordTimeStart];
                [recordButton setImage:[UIImage imageNamed:@"recording_button.png"] forState:UIControlStateNormal];
                [recordLabel setText:@"点击结束"];
            }
            else{
                [audioRecorder stop];                          //录音停止
                [audioSession setActive:NO error:nil];         //一定要在录音停止以后再关闭音频会话管理(否则会报错),此时会延续后台音乐播放
                [timer invalidate];                            //timer失效
                [timeLabel setText:@"00:00"];                  //时间显示复位
                [progressView setValue:0 animated:YES];        //进度条复位

                [recordButton removeFromSuperview];
                [recordLabel removeFromSuperview];
                [self.view addSubview:playButton];
                [self.view addSubview:finishButton];
                [self.view addSubview:recordAgainButton];
                [self.view addSubview:playLabel];
                [self.view addSubview:finishLabel];
                [self.view addSubview:recordAgainLabel];
            }
        }
            break;
        case NEW_PLAY_BUTTON_TAG:{
            [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
            [audioSession setActive:YES error:nil];

            if (mp3FilePath != nil) {
                audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:mp3FilePath error:nil];
            }
            else if (recordUrl != nil){
                audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:recordUrl error:nil];
            }

            [audioPlayer prepareToPlay];
            audioPlayer.volume = 1;
            [audioPlayer play];

            [playButton removeFromSuperview];
            [playLabel removeFromSuperview];
            [self.view addSubview:pauseButton];
            [self.view addSubview:pauseLabel];

            playDuration = (int)audioPlayer.duration;
            NSLog(@"音频时长为:%i",playDuration);
            playTime = 0;
            [self audioPlayTimeStart];
        }
            break;
        case PAUSE_PLAY_BUTTON_TAG:{
            [audioSession setActive:YES error:nil];

            [audioPlayer play];

            [playButton removeFromSuperview];
            [playLabel removeFromSuperview];
            [self.view addSubview:pauseButton];
            [self.view addSubview:pauseLabel];
        }
            break;
        case PAUSE_BUTTON_TAG:{
            [audioPlayer pause];
            [audioSession setActive:NO error:nil];

            playButton.tag = PAUSE_PLAY_BUTTON_TAG;
            [pauseButton removeFromSuperview];
            [pauseLabel removeFromSuperview];
            [self.view addSubview:playButton];
            [self.view addSubview:playLabel];
        }
            break;
        case FINISH_BUTTON_TAG:{
            [self transformCAFToMP3];
        }
            break;
        case RECORDAGAIN_BUTTON_TAG:{
            [audioPlayer stop];
            [audioRecorder stop];
            [audioSession setActive:NO error:nil];

            [timer invalidate];
            progressView.value = 0;
            [timeLabel setText:@"00:00"];
            recordTime = 0;
            playTime = 0;

            [playButton removeFromSuperview];
            [pauseButton removeFromSuperview];
            [finishButton removeFromSuperview];
            [recordAgainButton removeFromSuperview];
            [playLabel removeFromSuperview];
            [pauseLabel removeFromSuperview];
            [finishLabel removeFromSuperview];
            [recordAgainLabel removeFromSuperview];

            [self.view addSubview:recordButton];
            [self.view addSubview:recordLabel];
            [recordButton setImage:[UIImage imageNamed:@"record_button.png"] forState:UIControlStateNormal];
            [recordLabel setText:@"点击开始"];
        }
            break;
        default:
            break;
    }
}

- (void)recordTimeStart {
    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(recordTimeTick) userInfo:nil repeats:YES];
}

- (void)recordTimeTick {
    recordTime += 1;
    [progressView setValue:(float)recordTime/30.0 animated:YES];
    if (recordTime == 30) {
        recordTime = 0;
        [audioRecorder stop];
        [[AVAudioSession sharedInstance] setActive:NO error:nil];
        [timer invalidate];
        [timeLabel setText:@"00:00"];
        [progressView setValue:0.0 animated:YES];

        [recordButton removeFromSuperview];
        [recordLabel removeFromSuperview];
        [self.view addSubview:playButton];
        [self.view addSubview:finishButton];
        [self.view addSubview:recordAgainButton];
        [self.view addSubview:playLabel];
        [self.view addSubview:finishLabel];
        [self.view addSubview:recordAgainLabel];
        return;
    }
    [self updateAudioRecordTime];
}

- (void)updateAudioRecordTime {
    minute = recordTime/60.0;
    second = recordTime-minute*60;

    [timeLabel setText:[NSString stringWithFormat:@"%02d:%02d",minute,second]];
}

- (void)audioPlayTimeStart {
    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(playTimeTick) userInfo:nil repeats:YES];
}

- (void)playTimeTick {
    if (playDuration == playTime) {
        playTime = 0;
        [audioPlayer stop];
        [[AVAudioSession sharedInstance] setActive:NO error:nil];

        [pauseButton removeFromSuperview];
        [pauseLabel removeFromSuperview];
        [self.view addSubview:playButton];
        [self.view addSubview:playLabel];

        playButton.tag = NEW_PLAY_BUTTON_TAG;

        [timeLabel setText:@"00:00"];
        [timer invalidate];
        progressView.value = 0;
        return;
    }
    if (![audioPlayer isPlaying]) {
        return;
    }
    playTime += 1;
    [progressView setValue:(float)playTime/(float)playDuration animated:YES];
    [self updateAudioPlayTime];
}

- (void)updateAudioPlayTime {
    minute = playTime/60.0;
    second = playTime-minute*60;

    [timeLabel setText:[NSString stringWithFormat:@"%02d:%02d",minute,second]];
}

//AVAudioRecorderDelegate方法
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    [audioSession setActive:NO error:nil];

    playTime = 0;

    [pauseButton removeFromSuperview];
    [pauseLabel removeFromSuperview];
    [self.view addSubview:playButton];
    [self.view addSubview:playLabel];

    playButton.tag = NEW_PLAY_BUTTON_TAG;

    [timeLabel setText:@"00:00"];
    [timer invalidate];
    progressView.value = 0;
}

@end
时间: 2024-11-01 10:33:52

【转载】iOS麦克风录制音频并保存成mp3文件的Demo的相关文章

怎样将M4A音频格式转换成MP3格式

因为MP3音频格式应用的广泛性,所以很多时候我们都需要将不同的音频格式转换成MP3格式的,那么如果我们需要将M4A音频格式转换成MP3格式,我们应该怎样进行实现呢?下面我们就一起来看一下吧. 操作步骤: 步骤一:先在电脑上准备好需要进行转换的M4A音频文件,因为音频文件的转换我们需要通过电脑来进行实现. 步骤二:音频文件准备好后,我们就可以通过电脑浏览器搜索迅捷PDF在线转换器,来帮助我们对音频文件进行转换了. 步骤三:进入到在线转换器页面后,在页面上方有一排的功能选项导航,我们需要从音视频转换

Swift iOS实现把PCM语音转成MP3格式

最近折腾了swift的语音录制识别和转码,这块还是比较坑的,由于语音识别的准确度实测大概也就80%左右,所以还是需要上传录音文件啊.首先是用讯飞语音SDK实现语音录制和识别(语音听写),第一个坑是讯飞SDK只录制了PCM格式的文件,这个文件是原始格式,默认比较大,另外播放器支持也不好,因此需要先把它转成mp3,本来考虑使用系统的AudioConverter转aac格式,不过aac好像不能在浏览器上播放.转成mp3需要lame库支持,注意国内网搜到的lame.a库不支持64位,所以现在不能用了.还

ObjectARX2010 学习笔记001:在新数据库中创建直线并将此数据库保存成DWG文件

static void swtArxProject5createLine(void) { // Add your code for command swtArxProject5.createLine here //创建新的CAD数据库 AcDbDatabase *pDb=new AcDbDatabase(); //定义块表指针 AcDbBlockTable *pBlkTbl; //获取块表 pDb->getSymbolTable(pBlkTbl,AcDb::kForRead); //定义块表记录

IOS开发—图片压缩/解压成Zip文件

图片压缩/解压成Zip文件 本文介绍如何将图片压缩成Zip文件,首先需要下载第三方库ZipArchive 并导入项目中. ZipArchive 库地址:https://github.com/mattconnolly/ZipArchive 一.文档结构: 二.准备工作: 1.框架导入: 2.ZipArchive.m文件使用非ARC机制 三.代码示例: // // ViewController.m // UnzipImgDemo // // Created byLotheve on 15/4/10.

Android -- 几种保存成jpeg文件的形式

//1.采用NV21格式 YuvImage类进行保存 效率很高 String fileName = "IMG_" + String.valueOf(index) + ".jpg"; File sdRoot = Environment.getExternalStorageDirectory(); String dir = "/picture/"; File mkDir = new File(sdRoot, dir); if (!mkDir.exis

python文件目录遍历保存成xml文件代码

Linux服务器有CentOS.Fedora等,都预先安装了Python,版本从2.4到2.5不等,而Windows类型的服务器也多数安装了Python,因此只要在本机写好一个脚本,上传到对应机器,在运行时修改参数即可. Python操作文件和文件夹使用的是os库,下面的代码中主要用到了几个函数: os.listdir:列出目录下的文件和文件夹 os.path.join:拼接得到一个文件/文件夹的全路径 os.path.isfile:判断是否是文件 os.path.splitext:从名称中取出

InputStream流保存成图片文件

public void saveBit(InputStream inStream) throws IOException{ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); //创建一个Buffer字符串 byte[] buffer = new byte[1024]; //每次读取的字符串长度,如果为-1,代表全部读取完毕 int len = 0; //使用一个输入流从buffer里把数据读取出来 while( (len

SQLServer数据库表架构和数据保存成sql文件

一.先在你的mssql数据库中点击“数据库–>任务–>生成脚本” 二.然后我们会看到有“生成和发布脚本”窗口 下一步 三.选择要编写脚本的数据库对象,全部导出选第一个,如果你想导出部分数据勾选    第二个 四.然后在出现的”高级”按钮 五.最后对要 ”要编写脚本的数据的类型”对应:”架构和数据” 就导出成功了.

iOS平台上音频编码成aac

小程之前介绍解码aac时,曾经使用了fadd,并且有提到,如果想编码成aac格式,可以使用facc.fdk-aac等,但使用fdk-aac等编码方式,都是软编码,在cpu的消耗上会明显大于硬件编码. 硬编码的优势是可以用硬件芯片集成的功能,高速且低功耗地完成编码任务. 在iOS平台,也提供了硬编码的能力,APP开发时只需要调用相应的SDK接口就可以了. 这个SDK接口就是AudioConverter. 本文介绍iOS平台上,如何调用AudioConverter来完成aac的硬编码. 从名字来看,