天天看点

IPhone之AVAudioRecorder 录音

#import   需要引入

//获取document目录的路径

- (nsstring*) documentspath {

 if (! _documentspath) {

  nsarray *searchpaths =

   nssearchpathfordirectoriesindomains

   (nsdocumentdirectory, nsuserdomainmask, yes);

  _documentspath = [searchpaths objectatindex: 0];

  [_documentspath retain];

 }

 return _documentspath;

}

//(document目录的路径)

 nsstring *destinationstring = [[self documentspath]

   stringbyappendingpathcomponent:filenamefield.text];

 nsurl *destinationurl = [nsurl fileurlwithpath: destinationstring];

//初始化avaudiorecorder

 nserror *recordersetuperror = nil;

 avaudiorecorder audiorecorder = [[avaudiorecorder alloc] initwithurl:destinationurl

   settings:recordsettings error:&recordersetuperror]; 

 [recordsettings release];

第二个参数  settings是一个容纳键值对的nsdictionary有四种一般的键

1:一般的音频设置

2:线性pcm设置

3:编码器设置

4:采样率转换设置

nsmutabledictionary  需要加入五个设置值(线性pcm)

nsmutabledictionary *recordsettings =

  [[nsmutabledictionary alloc] initwithcapacity:10];

  //1 id号

  [recordsettings setobject:

   [nsnumber numberwithint: kaudioformatlinearpcm] forkey: avformatidkey];

  float samplerate =

   [pcmsettingsviewcontroller.sampleratefield.text floatvalue];

  //2 采样率

   [nsnumber numberwithfloat:samplerate] forkey: avsampleratekey];

  //3 通道的数目

   [nsnumber numberwithint:

    (pcmsettingsviewcontroller.stereoswitch.on ? 2 : 1)]

   forkey:avnumberofchannelskey];

  int bitdepth =

   [pcmsettingsviewcontroller.sampledepthfield.text intvalue];

  //4 采样位数  默认 16

   [nsnumber numberwithint:bitdepth] forkey:avlinearpcmbitdepthkey];

  //5

   [nsnumber numberwithbool:

     pcmsettingsviewcontroller.bigendianswitch.on]

    forkey:avlinearpcmisbigendiankey];

  //6 采样信号是整数还是浮点数

     pcmsettingsviewcontroller.floatingsamplesswitch.on]

    forkey:avlinearpcmisfloatkey];

avaudiorecorder成功创建后,使用他非常直接.它的三个基本方法如下

-(void) startrecording {

 [audiorecorder record];

-(void) pauserecording {

 [audiorecorder pause];

 recordpausebutton.selected = no;

-(void) stoprecording {

 [audiorecorder stop];

这里ios的录音功能主要依靠avfoundation.framework与coreaudio.framework来实现

IPhone之AVAudioRecorder 录音

在工程内添加这两个framework

我这里给工程命名audio_text

在生成的audio_textviewcontroller.h里的代码如下

#import   

@interface audio_textviewcontroller : uiviewcontroller {  

    iboutlet uibutton *bthstart;  

    iboutlet uibutton *bthplay;  

    iboutlet uitextfield *freq;  

    iboutlet uitextfield *value;  

    iboutlet uiactivityindicatorview *actspinner;  

    bool toggle;  

    //variable setup for access in the class  

    nsurl *recordedtmpfile;  

    avaudiorecorder *recorder;  

    nserror *error;  

}  

@property (nonatomic,retain)iboutlet uiactivityindicatorview *actspinner;  

@property (nonatomic,retain)iboutlet uibutton *bthstart;  

@property (nonatomic,retain)iboutlet uibutton *bthplay;  

-(ibaction)start_button_pressed;  

-(ibaction)play_button_pressed;  

@end  

audio_textviewcontroller.m

#import "audio_textviewcontroller.h"  

@implementation audio_textviewcontroller  

- (void)viewdidload {  

    [super viewdidload];  

    //start the toggle in true mode.  

    toggle = yes;  

    bthplay.hidden = yes;  

    //instanciate an instance of the avaudiosession object.  

    avaudiosession * audiosession = [avaudiosession sharedinstance];  

    //setup the audiosession for playback and record.   

    //we could just use record and then switch it to playback leter, but  

    //since we are going to do both lets set it up once.  

    [audiosession setcategory:avaudiosessioncategoryplayandrecord error: &error];  

    //activate the session  

    [audiosession setactive:yes error: &error];  

- (ibaction)  start_button_pressed{  

    if(toggle)  

    {  

        toggle = no;  

        [actspinner startanimating];  

        [bthstart settitle:@"停" forstate: uicontrolstatenormal ];     

        bthplay.enabled = toggle;  

        bthplay.hidden = !toggle;  

        //begin the recording session.  

        //error handling removed.  please add to your own code.  

        //setup the dictionary object with all the recording settings that this   

        //recording sessoin will use  

        //its not clear to me which of these are required and which are the bare minimum.  

        //this is a good resource: http://www.totodotnet.net/tag/avaudiorecorder/  

        nsmutabledictionary* recordsetting = [[nsmutabledictionary alloc] init];  

        [recordsetting setvalue :[nsnumber numberwithint:kaudioformatappleima4] forkey:avformatidkey];  

        [recordsetting setvalue:[nsnumber numberwithfloat:[freq.text floatvalue]] forkey:avsampleratekey];   

        [recordsetting setvalue:[nsnumber numberwithint: [value.text intvalue]] forkey:avnumberofchannelskey];  

        //now that we have our settings we are going to instanciate an instance of our recorder instance.  

        //generate a temp file for use by the recording.  

        //this sample was one i found online and seems to be a good choice for making a tmp file that  

        //will not overwrite an existing one.  

        //i know this is a mess of collapsed things into 1 call.  i can break it out if need be.  

        recordedtmpfile = [nsurl fileurlwithpath:[nstemporarydirectory() stringbyappendingpathcomponent: [nsstring stringwithformat: @"%.0f.%@", [nsdate timeintervalsincereferencedate] * 1000.0, @"caf"]]];  

        nslog(@"using file called: %@",recordedtmpfile);  

        //setup the recorder to use this file and record to it.  

        recorder = [[ avaudiorecorder alloc] initwithurl:recordedtmpfile settings:recordsetting error:&error];  

        //use the recorder to start the recording.  

        //im not sure why we set the delegate to self yet.    

        //found this in antother example, but im fuzzy on this still.  

        [recorder setdelegate:self];  

        //we call this to start the recording process and initialize   

        //the subsstems so that when we actually say "record" it starts right away.  

        [recorder preparetorecord];  

        //start the actual recording  

        [recorder record];  

        //there is an optional method for doing the recording for a limited time see   

        //[recorder recordforduration:(nstimeinterval) 10]  

    }  

    else  

        toggle = yes;  

        [actspinner stopanimating];  

        [bthstart settitle:@"开始录音" forstate:uicontrolstatenormal ];  

        //stop the recorder.  

        [recorder stop];  

- (void)didreceivememorywarning {  

    // releases the view if it doesn't have a superview.  

    [super didreceivememorywarning];  

    // release any cached data, images, etc that aren't in use.  

-(ibaction) play_button_pressed{  

    //the play button was pressed...   

    //setup the avaudioplayer to play the file that we just recorded.  

    avaudioplayer * avplayer = [[avaudioplayer alloc] initwithcontentsofurl:recordedtmpfile error:&error];  

    [avplayer preparetoplay];  

    [avplayer play];  

- (void)viewdidunload {  

    // release any retained subviews of the main view.  

    // e.g. self.myoutlet = nil;  

    //clean up the temp file.  

    nsfilemanager * fm = [nsfilemanager defaultmanager];  

    [fm removeitematpath:[recordedtmpfile path] error:&error];  

    //call the dealloc on the remaining objects.  

    [recorder dealloc];  

    recorder = nil;  

    recordedtmpfile = nil;  

- (void)dealloc {  

    [super dealloc];  

最后在interface builder里面绘制好界面,如

IPhone之AVAudioRecorder 录音

设置下按键的属性

IPhone之AVAudioRecorder 录音

基本就ok了,可以开始录音了。

bug解决

但是大家要注意一个貌似是ios5.0之后引入的bug,就是当你录制音频的时候启动时间往往会比较慢,大概需要3--5秒的时间吧,这种现象尤其在播放的时候立刻切换到录制的时候非常明显。

具体的原因我也不是很清楚,感觉应该是更底层的一些bug。目前我的解决方案是这样的。

1.在音频队列的初始化方法中加入代码

osstatus error = audiosessioninitialize(null, null, null, null);

        uint32 category

= kaudiosessioncategory_playandrecord;

error = audiosessionsetproperty(kaudiosessionproperty_audiocategory, sizeof(category),

&category);

audiosessionaddpropertylistener(kaudiosessionproperty_audioroutechange, null, self);

uint32 inputavailable = 0;

uint32 size = sizeof(inputavailable);

audiosessiongetproperty(kaudiosessionproperty_audioinputavailable, &size, &inputavailable);

audiosessionaddpropertylistener(kaudiosessionproperty_audioinputavailable, null, self);

        audiosessionsetactive(true); 

2.在录制声音开始的时候先把播放声音stop,加入

    uint32 category

    audiosessionsetproperty(kaudiosessionproperty_audiocategory, sizeof(category),

这样做应该会让你的录制启动速度显著加快的。

上一篇: AVAudioSession
下一篇: ScrollView分析