Thursday, February 3, 2011

Using the iPhone to Record Audio. A guide to the steps required to get it working in the SDK

Today my experiment is going to be learning how to use the iPhone SDK to record and play back audio.

To begin all I want to do is have a button that starts and stops the recording and another button that will play back the recorded sound.

Sounds simple enough. Here is a small screen shot of the finished result.

The classes that we are using for this project are : AVAudioSession, AVAudioRecorder and AVAudioPlayer

These can be located in the AVFoundation framework.

It took some work to figure out exactly how to add the AVFoundation framework to the iPhone project. If you dont do this you will get linker errors when you try to compile the project. You will also want to add the CoreAudio.Framework. Some of the constants are defined in the headers in this framework.

From your XCode interface you are going to select the Frameworks folder, ctl>click and choose ADD and then select Existing Frameworks… Then choose both the CoreAudio.Framework and the AVFoundation.Framework

The AVFoundation framework was not originally available in my selections and it took me some work to actually locate the proper folder where the framework was located. I ended up using the search tool to find the proper location for the framework.

Once You have added the framework you then need to #Import the headers into your project.

The 2 headers you need to #import into your controller.h are:

AVFoundation.h
CoreAudioTypes.h

This gives you access to the class and allows the linker to properly find everything to build the binaries properly.

Also in the class definition for the controller class you will need to be sure that you are implementing the AVAudioRecorder delegate methods. That looks like this:

@interface record_audio_testViewController : UIViewController

{


I have a couple member variables that I use in a couple of places and those are also defined here…


//Variables setup for access in the class:
NSURL * recordedTmpFile;
AVAudioRecorder * recorder;
NSError * error;


Here is a screen shot of the controller.h file for reference:

Now that we have the basics set for the class, lets start to work on the meat of getting recording to with with AVAudioRecorder

In my -(void)ViewDidLoad you will see where I set up the Audio session. You have to do this to let the iPhone OS know that your application is going to handle audio and what kind of session it will be. There is a larger discussion around this, but for this example I am using the Play and Record session type.

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];

//Start the toggle in true mode.
toggle = YES;
btnPlay.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];

}

See the screen shot for reference:

Here we have the AVAudioRecorder in action. When the button is pressed we instantiate an instance with settings that tell the recorder what kind of audio file to make.

This is a little squished… I will work on this to make things easier in the future.


//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:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 2] 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]

We are loading up the audio into a temp file that we are then saving on the device. Later on we are going to use this same file to play back the audio when the button is pressed:

This is the example from the play_button_pressed code:

//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];

Armed with these basics you should be able to get Sound recording and playback working on your iPhone pretty easily.

In this sample I have removed the error handling so it is easier to read, so remember to add back in your error handling when you put this code into action.

Questions? Please feel free to send them along.

To download the entire sample project for AVAudioSession with source code

Click Here

No comments:

Post a Comment