Skip to content

Plug-And-Play OpenAL / AVFoundation Sound Engine For iPhone Apps

I recently found a great sound engine for iPhone applications that is pretty much plug-and-play.

OpenAL lets you play multiple sounds at once

This sound engine was written by Alex Restrepo under a creative commons attribution-share alike licence, so you are free to use it so long as you attribute the code to the author and if you change it and share it you must do so under the same license.

I have corrected one small mistake (a semi-colon where it should not have been) and also edited the formatting of the code to my personal preference. You can get an Xcode example project that uses the sound engine here. If you just want the sound engine itself you can get it here.

If you look at the example project you will see how easy this sound engine is to use. It provides simple methods for playing and managing background music and for playing sound effects on top. These classes use AVFoundation to play the background music and OpenAL to play other sounds on top. I am not informed enough about either of these to know what advantages or disadvantages this may offer but will look into it and possibly do a pure OpenAL version.

To add the sound engine to your own project just add the class files included in SoundEngine.zip to your project. Also be sure to add the OpenAL.framework, AVFoundation.framework and the AudioToolbox.framework otherwise you will get a host of strange errors.

You have the option of using the CMOpenALSoundManager as a singleton. If you do use it as a singleton (you can do this by setting USE_AS_SINGLETON to 1 at the top of CMOpenALSoundManager.h) you just need to initialize it somewhere in your code with:

[[CMOpenALSoundManager sharedCMOpenALSoundManager] init];

You also need to enumerate the tags for your sounds (ideally somewhere that every class that needs them will have access to them):

enum mySoundIds {
BUTTONSOUND1
        BUTTONSOUND2
        SUCCESSSOUND
        ERRORSOUND
};

You can then add your sound effects by passing an array of sound file names like so:

[CMOpenALSoundManager sharedCMOpenALSoundManager].soundFileNames = mySoundFileNamesArray;

To access your sound manager from anywhere in your project make sure you have included the CMOpenSoundManager header file and then reference the sound manager with:

[CMOpenALSoundManager sharedCMOpenALSoundManager]

Here is an example of playing some background music and then playing a sound effect:

[[CMOpenALSoundManager sharedCMOpenALSoundManager] playBackgroundMusic:@"backgroundLoop.m4a"];
[[CMOpenALSoundManager sharedCMOpenALSoundManager] playSoundWithID:BUTTONSOUND1];

One thing that I am not satisfied about with this system is the need for the enumeration. The reason being that you need to know which order the sounds are going to be loaded so that the correct sounds match the correct enum value. A better way in my opinion would be to use NSString keys, so that when you load a sound, you also pass a key. This is the approach taken in the code on the gethacktes.net blog, which is another great resource for OpenAL on the iPhone. Doing it this way allows you to lazy load sounds in any order. If I make that change I will be sure to post it here.

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter

Xcode Script For Creating Properties From Instance Variables For UIViewController

One of my favourite blogs on the net is Matt Gallagher’s Cocoa with Love. Today I was investigating ways to speed up my workflow in Xcode and I found a great mixed Perl and AppleScript script already written by Matt a couple of years ago.

A fantastic resource for Cocoa, Objective-C and programming in general

The script called PropertyFromInstanceVariable had already been added to by a couple of other people, Yung-Luen Lan & Mike Schrag and Pierre Bernard and I have now shaped it for my own specific needs, and possibly yours too.

The tedium I was trying to eliminate was the process of creating Objective-C properties from instance variables and doing basic memory management on them. This is a repetitive process that seems more appropriate to hand off to the machine.

Matt’s script allows you to take an instance variable defined in your interface file and automatically create a property for it, synthesize the property in the implementation, add a release statement and set the property to NULL in the dealloc method.

For example, running the script on this:

NSString *myString;

would automatically create this in the interface:

@property (nonatomic, retain) NSString *myString;

this at the top of the implementation:

@synthesize myString;

and adds these two lines to the dealloc method:

[myString release];
myString = NULL;

Because this script was written before the viewDidUnload method had been added to the UIViewController class it didn’t make use of the viewDidUnload method. I wanted to update it to set the retaining references to subviews in the view hierarchy to nil. These reference properties may have been set through IBOutlets when loading a nib or programmatically in the loadView method.

I have now modified the script to reflect my own coding habits. It still creates the property, synthesizes it and adds a release to the dealloc method, but if the class is a subclass of UIViewController then this is placed in viewDidUnload like so:

self.myString = nil;

This script can be run on multiple instance variables at once and greatly cuts down on the time it takes to set up a new class. Instructions on installing the script can be found here.

You can get my fork of the script on github.

NOTE: I have updated to script and edited this post to reflect those changes. All links are to the most recent version.

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter

c74: iPhone/iPod Touch Max 5 External

Just downloaded a new app that allows you to create custom Max 5 interfaces on your iPhone or iPod Touch.  This looks to me like a great creative tool and the best touch software option on a mobile platform for users of Cycling ’74’s MaxMSP. c74 is integrated with Max 5, so you will need to be a Max 5 owner to use it.

From the nr74website:

c74 is an iPhone / iPod Touch app that let’s you connect your device with Cycling ’74’s Max/MSP 5.

The massive improvement over existing interface layout apps is that the layout is dynamically controlled by Max. Therefore we can have the interface adapt to the tasks it has to perform in real-time.

In order to connect this app to Max please download the free external from : http://www.nr74.org/c74/c74.zip(requires osx 10.5 or higher !)

Custom controller interfaces are built straight from within Max, presets can be stored etc. The external features some nice attributes for receiving accelerometer, GPS, compass, shake gesture and proximity data.

Please note : the c74 app won’t run on 1st gen iPods

Please note : the c74 external requires osx 10.5 or higher

Looking forward to playing with this. Nice work n74!

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter

Online JSON Validator

I was creating some JSON data with PHP to pass to an iPhone app today and I found a great online JSON validation tool: JSONLint: The JSON Validator.

The JSON Validator

Just plunk your JSON string into the window and press the validate button. Voila, not only are you told if your JSON string is valid but it also arranges your JSON data in an easily readable hierarchy. The JSON Validator was made and shared by the good folks at lab.ac9.com.Thank you arc90!

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter

When To Use self.myObject Instead Of myObject In iPhone Programming

I have seen a lot of confusion on the topic of when and why to reference an object using self.myObject versus just plain myObject. It took me a while to understand this myself, and please, if I am mistaken in my explanation, set me right, but here it is as I understand it.

Apparently some people don't like Objective-C

If you reference an object in your implementation that you declared in your header with @property and then used @synthesize in your implementation to automatically create getter and setter methods for the object, then using self.myObject  = newObject will call the setter and references to self.myObject will call the getter. As far as I know, if you are just referencing your object you don’t need to use the getter unless you are trying to distinguish from an object with the same name. When you assign your object however, the distinction becomes very important because everywhere you write:

self.myObject = newObject;

you are actually sending the message:

[self setMyObject:newObject];

which under the hood looks like:

objc_msgSend(self, @selector(setMyObject:), newObject);

The consequence of using self.myObject in this way is that myObject will use whatever retain property you set in the @property declaration. So if you set up myObject like so:

@property (nonatomic, retain) MyObjectClass *myObject;

then the value of myObject will be retained even after newObject has been deallocated.

If instead you had assigned myObject like this:

myObject = newObject;

then myObject is just the same as newObject. Therefore if newObject is deallocated then myObject will be pointing to a meaningless memory address. Probably not what you want.

So, here is an example:

.h file
...
UIView *myUIView;
...
@property (nonatomic, retain) UIView *myUIView;
...

.m file

...
@synthesize myUIView;
...
// Get frame:
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];

// Set up myUIView:
UIView *tempUIView = [[UIView alloc] initWithFrame:applicationFrame];
tempUIView.backgroundColor = [UIColor blackColor];
self.myUIView = tempUIView;
[tempUIView release];
...

At this point in the code myUIView is now set up and ready to use. Because I used the setter to assign myUIView it is unaffected when I release tempUIView. If I had forgotten to use self.myUIView for the assignment then I would be unable to use myUIView later in the program.

Hope that clears things up for some of you. Please comment if I have something wrong or if you can help make things even clearer.

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter

Aluminum Faceplate For SparkFun Button Arduinome Arrives!

Just received some aluminum faceplates for my arduinome that I got through a group buy organized by @z15 on the monome community forum. (Thanks!)

Arduinome dual panel faceplate design

These aluminum panels are each 5 mm thick which leaves about 2 mm of the SparkFun buttons exposed. My initial test of the faceplate has resulted in a lot of the buttons getting stuck, though most of them not enough to actually make contact. I think that with some time put into smoothing out the button holes and edges that this will provide great button mashing action.

Here is another view:

Arduinome with aluminum faceplate

and another:

Arduinome money shot

I just can’t get enough glory shots of blinky button grids!

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter

iPhone Camera Overlay App With Custom Button Example

There seems to be a lot of interest recently in making apps that use a camera view with an overlay for augmented reality or what some might call pseudo-augmented reality applications (because often these apps just layer an image or data on a camera view). I wasn’t satisfied with the few examples I found on the topic so I decided to try one myself. I will endeavour to make it as clear as I can and show you how to make a custom button while I am at it, but I do assume a basic knowledge of Objective-C and iPhone app development in Xcode.

OverlayViewTester screenshot

OverlayViewTester screenshot

So first I will describe the OverlayViewTester app. Basically it just overlays some cool looking red selection braces on a camera view and has a button that when pressed performs a ’scan’ for two seconds and lets you know by adding a “Scanning…” label at the top of the screen during that time. So really it does nothing, but it looks good and is a good first step to making a more fun and interesting interactive camera overlay app.

To get started download the source code from GitHub. Next I will go through the files in the project and present the juicy bits. Consult the source code you downloaded for the full meal deal.

OverlayViewTesterApDelegate

Taking a look at the project we start with a typical app delegate, OverlayViewTesterAppDelegate which loads the OverlayViewController. Nothing monumental there so I won’t bother reproducing it here.

OverlayViewController

Now on to the OverlayViewController where we create the camera view.

In the interface, OverlayViewController.h: we define some constants:

// Transform values for full screen support:
#define CAMERA_TRANSFORM_X 1
#define CAMERA_TRANSFORM_Y 1.12412

// iPhone screen dimensions:
#define SCREEN_WIDTH  320
#define SCREEN_HEIGTH 480

In the implementation, OverlayViewController.m there is a bit of a GOTCHA. The line

[self presentModalViewController:picker animated:YES];

must be called in viewDidAppear: not in a viewDidLoad: method. Here it is:

- (void) viewDidAppear:(BOOL)animated {
    OverlayView *overlay = [[OverlayView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGTH)];

    // Create a new image picker instance:
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];

    // Set the image picker source:
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;

    // Hide the controls:
    picker.showsCameraControls = NO;
    picker.navigationBarHidden = YES;

    // Make camera view full screen:
    picker.wantsFullScreenLayout = YES;
    picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, CAMERA_TRANSFORM_X, CAMERA_TRANSFORM_Y);

    // Insert the overlay:
    picker.cameraOverlayView = overlay;

    // Show the picker:
    [self presentModalViewController:picker animated:YES];
    [picker release];

    [super viewDidAppear:YES];
}

I think the comments make it clear what is going on there.

OverlayView

Next lets look at the custom subclass of UIView called OverlayView. This is where we actually create our overlay.

In the interface, OverlayView.h we declare two new methods:

- (void)scanButtonTouchUpInside;
- (void)clearLabel:(UILabel *)label;

Here are the important parts of the implementation, OverlayView.m:

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Clear the background of the overlay:
	self.opaque = NO;
	self.backgroundColor = [UIColor clearColor];

	// Load the image to show in the overlay:
	UIImage *overlayGraphic = [UIImage imageNamed:@"overlaygraphic.png"];
	UIImageView *overlayGraphicView = [[UIImageView alloc] initWithImage:overlayGraphic];
	overlayGraphicView.frame = CGRectMake(30, 100, 260, 200);
	[self addSubview:overlayGraphicView];
	[overlayGraphicView release];

	ScanButton *scanButton = [[ScanButton alloc] initWithFrame:CGRectMake(130, 320, 60, 30)];

	// Add a target action for the button:
	[scanButton addTarget:self action:@selector(scanButtonTouchUpInside) forControlEvents:UIControlEventTouchUpInside];
	[self addSubview:scanButton];
    }
    return self;
}

- (void) scanButtonTouchUpInside {
    UILabel *scanningLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 50, 120, 30)];
    scanningLabel.backgroundColor = [UIColor clearColor];
    scanningLabel.font = [UIFont fontWithName:@"Courier" size: 18.0];
    scanningLabel.textColor = [UIColor redColor];
    scanningLabel.text = @"Scanning...";

    [self addSubview:scanningLabel];

    [self performSelector:@selector(clearLabel:) withObject:scanningLabel afterDelay:2];

    [scanningLabel release];
}

- (void)clearLabel:(UILabel *)label {
    label.text = @"";
}

Notice that we have used an instance of ScanButton which we will get to next. When the ScanButton detects a UIControlEventTouchUpInside it calls the scanButtonTouchUpInside method which places a label on the screen for 2 seconds.

ScanButton

So finally we are left with our ScanButton. You might think that for a custom button we would subclass UIButton, but unless you really want to use the UIBUtton method setTitle:ForState it is recommended that you subclass UIControl. It will save you a world of hurt.

Here is the interface, ScanButton.h:

#import <Foundation/Foundation.h>

@interface ScanButton : UIControl {
}

- (void)buttonPressed;

@end

I put the buttonPressed method in here for future use. It is meant to be used to change things related to the button itself and not the actions associated with the button in the OverlayViewController. You could for example use it to have the button’s image or state or both toggle.

Last but not least we have the implementation, ScanButton.m:

#import "ScanButton.h"

@implementation ScanButton

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
	// Set button image:
	UIImageView *buttonImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 60, 30)];
	buttonImage.image = [UIImage imageNamed:@"scanbutton.png"];

	[self addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside]; // for future use

        [self addSubview:buttonImage];
    }
    return self;
}

- (void)buttonPressed {
    // TODO: Could toggle a button state and/or image
}

@end

So there you have it. A custom camera overlay and a custom button. I hope that with this code you will be well on your way to writing much more useful, interesting and creative apps than this example. Happy coding!

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter

Look Ma, No Loops! A Monome In The Hands Of A Master

I just had to share this brilliant little monome performance piece by edison. It really makes me want to finish my monome clone which is complete but for a case. Sure wish machinecollective were still making their beautiful cases.

edison – tonka truck from edison on Vimeo.

edison describes this piece on his Vimeo page as:

“all one shot sounds…
no loops running….
64 buttons
64 noises….
shot on 2 HD cameras, 720p, 1 live take…..
with audio captured right to camera…..”

Rad.

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter

Field Recording: Underwater Earthquake

This is an epic underwater recording of the 2004 Indian Ocean earthquake that occurred at 00:58:53 UTC on December 26, 2004, with an epicentre off the west coast of Sumatra, Indonesia. The quake itself is known by the scientific community as the Sumatra-Andaman earthquake.

I did not record this myself, I found it shortly after the quake on a scientific site about the earthquake. I recommend you listen to it LOUD. It is truly a humbling sound. Enjoy.

Tsunami Earthquake by musicalgeometry

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter

Change Your Company Name In XCode

If you want your own company name to be automatically included in your XCode source files instead of this:

//
//  helloworld.m
//  helloworld
//
//  Created by John Smith on 24/10/09.
//  Copyright __MyCompanyName__ 2009. All rights reserved.
//

then it is time to open up your Terminal app.

Terminal 2

OSX Terminal app

You will find it at ~/Applications/Utilities/Terminal.app.

Enter the following in the open terminal (replacing the company name with yours):

defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{"ORGANIZATIONNAME" = "Smith Incorporated";}'

Now when you create new source files in XCode you will see this:

//
//  helloworld.m
//  helloworld
//
//  Created by John Smith on 24/10/09.
//  Copyright Smith Incorporated 2009. All rights reserved.
//

Much better.

  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Technorati
  • LinkedIn
  • RSS
  • Slashdot
  • Twitter