Blog Projects
Student in IT & Web develop{design}er
Beatbox App on iPad - Part Two

Beatbox App on iPad - Part Two

The final part of the tutorial to make a fun app on iOS

On the first part of this tutorial I was showing you how to make the interface and the navigation of our beatbox app. So now in this second and final part, I’ll show you how to implement functionalities. These functionalities are :

  • Saving a name on each button
  • Play a sound when user touch a button in playing mode
  • Record a sound when user touch a button in recording mode

Button’s Name

To save names, we will use the NSUserDefaults Class. To do so, add this attribute in the PadButtonViewController.h, inside the interface brackets:

NSUserDefaults *def;

And in the initWithNibName:bundle: method in the .m file add this line:

def = [NSUserDefaults standardUserDefaults];

Now that we have an instance of NSUserDefaults we can save an object with a corresponding key. This have to be done when the user type something in the text field, and our method changePadName can perform that task. So put this code inside :

[pad setTitle:textField.text forState:UIControlStateNormal];
[def setObject:textField.text forKey:[NSString stringWithFormat:@"pad-%d", identifier]];
[def synchronize];

To have that name set when the app start put this line in the viewDidLoad method:

[pad setTitle:[def objectForKey:[NSString stringWithFormat:@"pad-%d", identifier]] forState:UIControlStateNormal];

And we are done with the button’s name!


Audio

Now that the big part! To do some playing/recording we will use the AVFoundation and the CoreAudio Frameworks. To include these framework in the project, click on the project name and add theme in the «Link Binaries With Libraries» list.

Window to add frameworks in the project

We can now import these frameworks in PadButtonViewController.h file:

#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>

As this controller will be the recorder's delegate, we have to change our @interface like this :

@interface PadButtonViewController : UIViewController <avaudiorecorderdelegate> {

And inside the interface brackets:

NSURL *file;
NSError *error;
AVAudioPlayer *player;
AVAudioRecorder *recorder;
BOOL hasRecordDone;

After the bracket add these methods:

- (void)configAudio;
- (void)configPlayer;
- (void)configRecorder;
- (void)startRecording;
- (void)stopRecording;
- (void)startPlaying;
- (void)stopPlaying;

Then in the initWithNibName:bundle: method add this:

hasRecordDone = NO;

To use the hardware, we need to create the good session. In the changeState method (PadViewController.m), after the for loop add this:

if (theSwitch.on) {
        NSError *error;
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setActive:NO error: &error];
        [audioSession setCategory:AVAudioSessionCategoryRecord error:&error];
        [audioSession setActive:YES error: &error];
    }else {
        NSError *error;
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setActive:NO error: &error];
        [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
        [audioSession setActive:YES error: &error];
}

We actually need to set the session at the start of the app too, so in viewDidLoad add :

NSError *error;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
[audioSession setActive:YES error: &error];

As you can see we are using some NSError, but we will not handle errors in this tutorial.
Now return in the PadButtonController.m file and to configure the audio add this code:

//We set here the name of the audio file that we will use
- (void)configAudio
{
    file = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat: @"padsound-%d", identifier]]];
	[file retain];
    
    [self configPlayer]; //by default we configure the player
}

- (void)configPlayer
{
    if(player != nil)
    {
        [player release];
        player = nil;
    }
    
    player = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:&error];
    player.numberOfLoops = -1;
    [player prepareToPlay];
}

- (void)configRecorder
{
    if(recorder != nil)
    {
        [recorder release];
        recorder = nil;
    }
    
    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];
    
    recorder = [[ AVAudioRecorder alloc] initWithURL:file settings:recordSetting error:&error];
    [recorder setDelegate:self];
    [recorder prepareToRecord];
    
    [recordSetting release];
}

In the dealloc method add this:

- (void)dealloc
{
    [recorder release];
    [player release];
    
    [super dealloc];
}

The configAudio method need to be call at the execution, but we need the identifier attribute to be set before, so we override the setIdentifier method to automatically call the configAudio method:

- (void)setIdentifier:(int)value
{
    identifier = value; 
    [self configAudio];
}

Now add this code to perform de recording and the playing:

- (void)startRecording
{
    if (hasRecordDone == NO) [self configRecorder];
    hasRecordDone = YES;
    [recorder record];
}

- (void)stopRecording
{
    [recorder stop];
}

- (void)startPlaying
{
    [player play];
}

- (void)stopPlaying
{
    [player stop];
    player.currentTime = 0;
}

In the setRecordingMode method, in the else (after the Playing color) add this:

if(hasRecordDone) [self configPlayer];
hasRecordDone = NO;

Now we just need to call these method when the user touch the button, and change the button's color so the user know what's happening:

- (IBAction)touchDown
{
    if(file == nil) [self configAudio];
    if (recordingMode)
    {
        [self startRecording];
        pad.backgroundColor = [UIColor orangeColor];
    }
    else
    {
        [self startPlaying];
        pad.backgroundColor = [UIColor blueColor];
    }
}

- (IBAction)touchUp
{
    if (recordingMode)
    {
        [self stopRecording];
        pad.backgroundColor = [UIColor redColor];
    }
    else
    {
        [self stopPlaying];
        pad.backgroundColor = [UIColor colorWithWhite:0.25 alpha:1];
    }
}

Conclusion

Making this app learned me a lot on the iOS SDK and I hope this little tutorial learned you something too.
I'll soon try to put this app on the App Store.

Posted on July 31, 2011


Add a Comment

Add a Comment
Full Name
Email
Message