Wednesday 7 November 2012

Simple Audio Application


Get Started

Create a new View-based project in XCode. Name the project “Bickboxx”.
Download this zip file and unzip it. These are all the sounds, images, and icons you need for Bickboxx. Drag all these files to the Resources. Hat tip to John Ellenich for the graphics/sounds.
You need to copy the item to the project’s directory, so put a check mark next to “Copy items into destination group’s folder (if needed).” Your settings should look similar to this. Click Add.

Adding the background image in Interface Builder

Double-clickBickboxxViewController.xibto open it in Interface Builder. Drag an Image View (UIImageView) from the Library to the View window. This will act as a placement holder for our background image.
Bring up the Attributes Inspector. Set the Image toBackground.png.

Creating the Button in Interface Builder

Drag a Round Rect Button (UIButton) to the View.
Bring up the Attributes Inspector. We don’t want the button to look like an ugly white rectangle. Set the Type to Custom.
Further down the Attributes Inspector, set the button’s state to Normal (or Default State Configuration depending on your version of Xcode). This is what the button looks like when it’s not doing anything.
Set the button’s Image to B Inactive.png. You need to resize the button in the View to make sure the “B” button is fully shown.
Now, change the button’s state to Highlighted (or Highlighted State Configuration depending on your version of Xcode). This is what the button looks like when it’s pressed down.
Set the button’s Image to B Active.png.
Drag another Round Rect Button (UIButton) to the View and repeat this section for the letters “E”, “A”, and “T”. Your View should now look like this:
Close Interface Builder for now.
Build and Go to make sure everything is still working. Touch the buttons, and they should light up.

Adding the Sounds Code

We have an interface that doesn’t do anything. Let’s fix that. The audio framework we need isn’t added by default. We have to add the AudioToolbox framework.
Control+Click the Frameworks folder on the left. Go to Add → Existing Frameworks…
Select theAudioToolbox.framework from/System/Library/Frameworks.
Click OK and add it to the project.
Open BickboxxViewController.h and add this code to it.
01#import <UIKit/UIKit.h>
02#import <AudioToolbox/AudioServices.h>
03 
04@interface BickboxxViewController : UIViewController {
05    CFURLRef        bNoteFileURLRef;
06    SystemSoundID    bNoteFileObject;
07    CFURLRef        eNoteFileURLRef;
08    SystemSoundID    eNoteFileObject;
09    CFURLRef        aNoteFileURLRef;
10    SystemSoundID    aNoteFileObject;
11    CFURLRef        tNoteFileURLRef;
12    SystemSoundID    tNoteFileObject;
13}
14 
15@property (readwrite)    CFURLRef        bNoteFileURLRef;
16@property (readonly)    SystemSoundID    bNoteFileObject;
17@property (readwrite)    CFURLRef        eNoteFileURLRef;
18@property (readonly)    SystemSoundID    eNoteFileObject;
19@property (readwrite)    CFURLRef        aNoteFileURLRef;
20@property (readonly)    SystemSoundID    aNoteFileObject;
21@property (readwrite)    CFURLRef        tNoteFileURLRef;
22@property (readonly)    SystemSoundID    tNoteFileObject;
23 
24@end
At the top, we’re referencingAudioServices.h from the AudioToolbox framework we imported earlier.
Below that is the declaration of properties for four sounds for the “B”, “E”, “A” and “T” buttons.
bNoteFileURLRef is the file location reference for thebNoteFileObject. This is the sound the “B” button will make.
These are the properties for the “E”, “A” and “T” sounds as well.

The BickboxxViewController.m File

OpenBickboxxViewController.m. We need to synthesize the getters/setters for our properties.
You can do this by adding this after@implementation BickBoxxViewController:
1@synthesize bNoteFileURLRef, bNoteFileObject, eNoteFileURLRef,
2eNoteFileObject, aNoteFileURLRef, aNoteFileObject,
3tNoteFileURLRef, tNoteFileObject;

Changing the viewDidLoad Method

Locate the viewDidLoad method. It will be commented out. You want to uncomment it to activate it.
The viewDidLoad method gets called after all the UI components are created. This is a good place for any startup code you need your app to perform. In this case, we’ll need to set our properties to the correct sounds.
The first thing we need to do in viewDidLoad is get the main bundle for the app. The main bundle allows you to use a folder hierarchy to organize and locate many types of application resources including images, sounds, localized strings, and executable code.
After [super viewDidLoad];, add this code to get the main bundle for the app.
1// Get the main bundle for the app
2CFBundleRef mainBundle;
3mainBundle = CFBundleGetMainBundle ();
To build the sound for the “B” button, we need to get the path of the sound file we want to play. The name of the sound file is B.aifc. This is the code to get the URL to the found file to play. Put this code after the code where you get the main bundle.
1// Get the URL to the sound file to play
2bNoteFileURLRef  =    CFBundleCopyResourceURL (
3                                             mainBundle,
4                                             CFSTR ("B"),
5                                             CFSTR ("aifc"),
6                                             NULL
7                                             );
Note that valid system sound packages are .wav.aif and .caf files.
Now that we have bNoteFileURLRef set we can associate the sound file with the system sound object bNoteFileObject. The AudioServicesPlaySystemSound function lets you very simply play short sound files.
Add this code after the code that gets the sound file URL.
1// Create a system sound object representing the sound file
2AudioServicesCreateSystemSoundID (bNoteFileURLRef, &bNoteFileObject);
We finished loading up the sound for the “B” button. We’ll need to load up the sounds for the “E”, “A” and “T” buttons.
Try to code this part yourself. If you get stuck, the viewDidLoad method should look like this when you’re done.
01// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
02- (void)viewDidLoad {
03    [super viewDidLoad];
04 
05    // Get the main bundle for the app
06    CFBundleRef mainBundle;
07    mainBundle = CFBundleGetMainBundle ();
08 
09    // Get the URL to the sound file to play
10    bNoteFileURLRef  =    CFBundleCopyResourceURL (
11                                                 mainBundle,
12                                                 CFSTR ("B"),
13                                                 CFSTR ("aifc"),
14                                                 NULL
15                                                 );
16 
17    // Create a system sound object representing the sound file
18    AudioServicesCreateSystemSoundID (bNoteFileURLRef, &bNoteFileObject);
19 
20    // Get the URL to the sound file to play
21    eNoteFileURLRef  =    CFBundleCopyResourceURL (
22                                                 mainBundle,
23                                                 CFSTR ("E"),
24                                                 CFSTR ("aifc"),
25                                                 NULL
26                                                 );
27 
28    // Create a system sound object representing the sound file
29    AudioServicesCreateSystemSoundID (eNoteFileURLRef, &eNoteFileObject);
30 
31    // Get the URL to the sound file to play
32    aNoteFileURLRef  =    CFBundleCopyResourceURL (
33                                                 mainBundle,
34                                                 CFSTR ("A"),
35                                                 CFSTR ("aifc"),
36                                                 NULL
37                                                 );
38    // Create a system sound object representing the sound file
39    AudioServicesCreateSystemSoundID (aNoteFileURLRef, &aNoteFileObject);
40 
41    // Get the URL to the sound file to play
42    tNoteFileURLRef  =    CFBundleCopyResourceURL (
43                                                 mainBundle,
44                                                 CFSTR ("T"),
45                                                 CFSTR ("aifc"),
46                                                 NULL
47                                                 );
48 
49    // Create a system sound object representing the sound file
50    AudioServicesCreateSystemSoundID (tNoteFileURLRef, &tNoteFileObject);
51}

Creating Our IBActions

Our BEAT buttons need to be associated with IBActions to make them do something. First, let’s declare the methods. Open BickboxxViewController.h and add this code before the @end line.
1- (IBAction)bSound:(id)sender;
2- (IBAction)eSound:(id)sender;
3- (IBAction)aSound:(id)sender;
4- (IBAction)tSound:(id)sender;
Your BickboxxViewController.h should now look like:
01#import <UIKit/UIKit.h>
02#import <AudioToolbox/AudioServices.h>
03 
04@interface BickBoxxViewController : UIViewController {
05    CFURLRef        bNoteFileURLRef;
06    SystemSoundID    bNoteFileObject;
07    CFURLRef        eNoteFileURLRef;
08    SystemSoundID    eNoteFileObject;
09    CFURLRef        aNoteFileURLRef;
10    SystemSoundID    aNoteFileObject;
11    CFURLRef        tNoteFileURLRef;
12    SystemSoundID    tNoteFileObject;
13}
14 
15@property (readwrite)    CFURLRef        bNoteFileURLRef;
16@property (readonly)    SystemSoundID    bNoteFileObject;
17@property (readwrite)    CFURLRef        eNoteFileURLRef;
18@property (readonly)    SystemSoundID    eNoteFileObject;
19@property (readwrite)    CFURLRef        aNoteFileURLRef;
20@property (readonly)    SystemSoundID    aNoteFileObject;
21@property (readwrite)    CFURLRef        tNoteFileURLRef;
22@property (readonly)    SystemSoundID    tNoteFileObject;
23 
24// The new code you added
25- (IBAction)bSound:(id)sender;
26- (IBAction)eSound:(id)sender;
27- (IBAction)aSound:(id)sender;
28- (IBAction)tSound:(id)sender;
29 
30@end
Close the file and open BickboxxViewController.m. Add the implementation to make the IBAction methods make the appropriate system sounds by invoking theAudioServicesPlaySystemSound method.
To play the “B” sound, the implemented method should make a call toAudioServicesPlaySystemSound and use the bNoteFileObject we created above. Add this after the property synthesis code:
1- (IBAction)bSound:(id)sender {
2AudioServicesPlaySystemSound (self.bNoteFileObject);
3}
Add similar implementations for the “E”, “A” and “T” sounds as well.
For reference, the top of BickboxxViewController.m should look like:
01#import "BickBoxxViewController.h"
02 
03@implementation BickBoxxViewController
04 
05@synthesize bNoteFileURLRef, bNoteFileObject, eNoteFileURLRef,
06eNoteFileObject, aNoteFileURLRef, aNoteFileObject,
07tNoteFileURLRef, tNoteFileObject;
08 
09- (IBAction)bSound:(id)sender {
10    AudioServicesPlaySystemSound (self.bNoteFileObject);
11}
12 
13- (IBAction)eSound:(id)sender {
14    AudioServicesPlaySystemSound (self.eNoteFileObject);
15}
16 
17- (IBAction)aSound:(id)sender {
18    AudioServicesPlaySystemSound (self.aNoteFileObject);
19}
20 
21- (IBAction)tSound:(id)sender {
22    AudioServicesPlaySystemSound (self.tNoteFileObject);
23}
For the last piece of code, we need to clean up our mess so we don’t have memory leaks. At the bottom of BickboxxViewController.m, add these lines to your dealloc method:
01- (void)dealloc {
02    [super dealloc];
03    AudioServicesDisposeSystemSoundID (self.bNoteFileObject);
04    AudioServicesDisposeSystemSoundID (self.eNoteFileObject);
05    AudioServicesDisposeSystemSoundID (self.aNoteFileObject);
06    AudioServicesDisposeSystemSoundID (self.tNoteFileObject);
07    CFRelease (bNoteFileURLRef);
08    CFRelease (eNoteFileURLRef);
09    CFRelease (aNoteFileURLRef);
10    CFRelease (tNoteFileURLRef);
11}
We’re done coding. Build and Go the project to make sure nothing is on fire. Your buttons won’t make any sounds yet. We’ll need to link our code to our interface.

Linking the buttons to the code in Interface Builder

Now that our code is done, we can link our buttons to our code. We’ll start with the “B” button link it with the bsound method. To do this, open up BickboxxViewController.xib.
Control+Click on the File’s Owner object so we can link our “B” button to our bsound.
Drag from the bSound in File’s Owner to the “B” button in the View.
An overlay should pop up. Choose Touch Down. The normal default is to execute the action when the finger is lifted from the button. We don’t want that. Soundboards don’t work that way. This will call the bSoundIBAction method when the button is pressed down.
Do this linking with the rest of the buttons. When you’re done, Control+Clicking File’s owner should look like this.

No comments:

Post a Comment