关闭

iOS 录音功能的实现

标签: iosbuttonnullaudioios5interface
40727人阅读 评论(3) 收藏 举报
分类:

这两天也调了一下ios的录音,原文链接:http://www.iphoneam.com/blog/index.php?title=using-the-iphone-to-record-audio-a-guide&more=1&c=1&tb=1&pb=1

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


在工程内添加这两个framework

我这里给工程命名audio_text

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

  1. #import <UIKit/UIKit.h>  
  2. #import <AVFoundation/AVFoundation.h>  
  3. #import <CoreAudio/CoreAudioTypes.h>  
  4.   
  5. @interface audio_textViewController : UIViewController {  
  6.   
  7.     IBOutlet UIButton *bthStart;  
  8.     IBOutlet UIButton *bthPlay;  
  9.     IBOutlet UITextField *freq;  
  10.     IBOutlet UITextField *value;  
  11.     IBOutlet UIActivityIndicatorView *actSpinner;  
  12.     BOOL toggle;  
  13.       
  14.     //Variable setup for access in the class  
  15.     NSURL *recordedTmpFile;  
  16.     AVAudioRecorder *recorder;  
  17.     NSError *error;  
  18. }  
  19.   
  20. @property (nonatomic,retain)IBOutlet UIActivityIndicatorView *actSpinner;  
  21. @property (nonatomic,retain)IBOutlet UIButton *bthStart;  
  22. @property (nonatomic,retain)IBOutlet UIButton *bthPlay;  
  23.   
  24. -(IBAction)start_button_pressed;  
  25. -(IBAction)play_button_pressed;  
  26. @end  
audio_textViewController.m

  1. #import "audio_textViewController.h"  
  2.   
  3. @implementation audio_textViewController  
  4.   
  5.   
  6. - (void)viewDidLoad {  
  7.     [super viewDidLoad];  
  8.       
  9.     //Start the toggle in true mode.  
  10.     toggle = YES;  
  11.     bthPlay.hidden = YES;  
  12.       
  13.     //Instanciate an instance of the AVAudioSession object.  
  14.     AVAudioSession * audioSession = [AVAudioSession sharedInstance];  
  15.     //Setup the audioSession for playback and record.   
  16.     //We could just use record and then switch it to playback leter, but  
  17.     //since we are going to do both lets set it up once.  
  18.     [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: &error];  
  19.     //Activate the session  
  20.     [audioSession setActive:YES error: &error];  
  21.       
  22. }  
  23. /* 
  24. // The designated initializer. Override to perform setup that is required before the view is loaded. 
  25. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 
  26.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
  27.     if (self) { 
  28.         // Custom initialization 
  29.     } 
  30.     return self; 
  31. } 
  32. */  
  33.   
  34. /* 
  35. // Implement loadView to create a view hierarchy programmatically, without using a nib. 
  36. - (void)loadView { 
  37. } 
  38. */  
  39.   
  40.   
  41. /* 
  42. // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 
  43. - (void)viewDidLoad { 
  44.     [super viewDidLoad]; 
  45. } 
  46. */  
  47.   
  48.   
  49. /* 
  50. // Override to allow orientations other than the default portrait orientation. 
  51. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
  52.     // Return YES for supported orientations 
  53.     return (interfaceOrientation == UIInterfaceOrientationPortrait); 
  54. } 
  55. */  
  56.   
  57. - (IBAction)  start_button_pressed{  
  58.       
  59.     if(toggle)  
  60.     {  
  61.         toggle = NO;  
  62.         [actSpinner startAnimating];  
  63.         [bthStart setTitle:@"停" forState: UIControlStateNormal ];     
  64.         bthPlay.enabled = toggle;  
  65.         bthPlay.hidden = !toggle;  
  66.           
  67.         //Begin the recording session.  
  68.         //Error handling removed.  Please add to your own code.  
  69.           
  70.         //Setup the dictionary object with all the recording settings that this   
  71.         //Recording sessoin will use  
  72.         //Its not clear to me which of these are required and which are the bare minimum.  
  73.         //This is a good resource: http://www.totodotnet.net/tag/avaudiorecorder/  
  74.         NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init];  
  75.           
  76.         [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];  
  77.           
  78.         [recordSetting setValue:[NSNumber numberWithFloat:[freq.text floatValue]] forKey:AVSampleRateKey];   
  79.         [recordSetting setValue:[NSNumber numberWithInt: [value.text intValue]] forKey:AVNumberOfChannelsKey];  
  80.           
  81.         //Now that we have our settings we are going to instanciate an instance of our recorder instance.  
  82.         //Generate a temp file for use by the recording.  
  83.         //This sample was one I found online and seems to be a good choice for making a tmp file that  
  84.         //will not overwrite an existing one.  
  85.         //I know this is a mess of collapsed things into 1 call.  I can break it out if need be.  
  86.         recordedTmpFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: @"%.0f.%@", [NSDate timeIntervalSinceReferenceDate] * 1000.0, @"caf"]]];  
  87.         NSLog(@"Using File called: %@",recordedTmpFile);  
  88.         //Setup the recorder to use this file and record to it.  
  89.         recorder = [[ AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSetting error:&error];  
  90.         //Use the recorder to start the recording.  
  91.         //Im not sure why we set the delegate to self yet.    
  92.         //Found this in antother example, but Im fuzzy on this still.  
  93.         [recorder setDelegate:self];  
  94.         //We call this to start the recording process and initialize   
  95.         //the subsstems so that when we actually say "record" it starts right away.  
  96.         [recorder prepareToRecord];  
  97.         //Start the actual Recording  
  98.         [recorder record];  
  99.         //There is an optional method for doing the recording for a limited time see   
  100.         //[recorder recordForDuration:(NSTimeInterval) 10]  
  101.           
  102.     }  
  103.     else  
  104.     {  
  105.         toggle = YES;  
  106.         [actSpinner stopAnimating];  
  107.         [bthStart setTitle:@"开始录音" forState:UIControlStateNormal ];  
  108.         bthPlay.enabled = toggle;  
  109.         bthPlay.hidden = !toggle;  
  110.           
  111.         NSLog(@"Using File called: %@",recordedTmpFile);  
  112.         //Stop the recorder.  
  113.         [recorder stop];  
  114.     }  
  115. }  
  116.   
  117. - (void)didReceiveMemoryWarning {  
  118.     // Releases the view if it doesn't have a superview.  
  119.     [super didReceiveMemoryWarning];  
  120.       
  121.     // Release any cached data, images, etc that aren't in use.  
  122. }  
  123.   
  124. -(IBAction) play_button_pressed{  
  125.       
  126.     //The play button was pressed...   
  127.     //Setup the AVAudioPlayer to play the file that we just recorded.  
  128.     AVAudioPlayer * avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:recordedTmpFile error:&error];  
  129.     [avPlayer prepareToPlay];  
  130.     [avPlayer play];  
  131.       
  132. }  
  133.   
  134. - (void)viewDidUnload {  
  135.     // Release any retained subviews of the main view.  
  136.     // e.g. self.myOutlet = nil;  
  137.     //Clean up the temp file.  
  138.     NSFileManager * fm = [NSFileManager defaultManager];  
  139.     [fm removeItemAtPath:[recordedTmpFile path] error:&error];  
  140.     //Call the dealloc on the remaining objects.  
  141.     [recorder dealloc];  
  142.     recorder = nil;  
  143.     recordedTmpFile = nil;  
  144. }  
  145.   
  146.   
  147. - (void)dealloc {  
  148.     [super dealloc];  
  149. }  
  150.   
  151. @end  
最后在interface builder里面绘制好界面,如


设置下按键的属性


基本就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 = kAudioSessionCategory_PlayAndRecord;

    AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);


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


1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1526354次
    • 积分:14946
    • 等级:
    • 排名:第808名
    • 原创:165篇
    • 转载:198篇
    • 译文:1篇
    • 评论:175条
    最新评论