zoukankan      html  css  js  c++  java
  • 【转载】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
  • 相关阅读:
    7--docker-compose详解
    6--容器数据卷,发布镜像,Docker小结
    5-- Dockerfile 搭建 博客系统
    4--Docker之Dockerfile镜像定制
    3--Docker网络 ; Docker图形化界面
    2--Docker容器相关命令
    1--docker介绍、安装; docker镜像相关命令
    2、函数的核心内容
    1、函数的基本使用
    7、文件操作方法
  • 原文地址:https://www.cnblogs.com/huangzizhu/p/5142703.html
Copyright © 2011-2022 走看看