ShortSoundPlayer: A simple, short sound player class
July 31, 2009 Filed in: Geekery
My first iPhone app, Bon Mot!, was the result of a collaboration with Bill Cochran. Bill came up with the idea for the game, recorded the audio and created the graphics with a little help from his son, Ian, who created the sky background. Having a collaborator was great because it let me focus exclusively on programming the app. Well, maybe not exclusively. There was also starting a company. And building its web site. Still, it would have been a long haul without Bill's help. Thanks hombre!
Like most games, Bon Mot has a bunch of sound effects that augment the game play. Initally we considered having ambient background sounds, but we ditched that idea early on, figuring most people would rather listen to their own music while they play.
Without the need for continuous background audio in Bon Mot, I "simply" needed to play a bunch of short sound clips, all of them 30 seconds or less. Additionally I wanted to let our users turn down the volume of the game's sounds so they could better hear their music. If you're wondering why I put "simply" in quotes, well... you'll see.
The first stop in my hunt for audio code was Apple's Metronome sample. Metronome is a beautiful little app that behaves just like an old-school, mechanical metronome with a swinging, weighted arm. At that time, Metronome used Apple's System Sound Services to play its "tick" and "tock" sounds (Note: since the release of iPhone OS 3.0, Metronome has been updated to use AVAudioPlayer instead). Although Apple's documentation warns against using System Sound Services to play things like game sounds, I couldn't help notice that Apple's engineers were doing this very thing in Metronome. More importantly, it was clear that System Sound Services was by far the simplest audio API for the iPhone. I love simple.
It was a snap to get Bon Mot's sound clips playing with System Sound Services. There was just one hitch. SSS offered no control over the output volume of the sounds it played. I was determined to let our users turn down the game sounds so they could better hear their music. Apart from the volume issue though, my task appeared to be complete in less than a day of work. Sweet! I decided to ignore the volume thing for the time being. Sometimes these things have a way of fixing themselves.
Weeks passed with no magic fix. We sent out our first beta version to everyone we knew with an iPhone. The app was feature complete with one exception. The "Quiet" setting for Bon Mot's Game Sounds preference needed to be implemented and System Sound Services, while performing perfectly in every other way, refused to let me turn down the volume. Ignoring the problem hadn't fixed it and it was time for me to come up with a Plan B.
Plan B was Apple's promising, new (at the time) AVAudioPlayer class. Without laboring the details, AVAudioPlayer turned out to be a major headache. My understanding is that the iPhone OS 3.0 version of AVAudioPlayer is much improved. However, if you need to target iPhone OS 2.x or earlier, then I recommend you avoid AVAudioPlayer. I wasted a solid day or two trying to get it to work reliably, and I'm reasonably certain that the problems lay within AVAudioPlayer, not in my use of it. A bit of Googling confirmed that before iPhone OS 3.0, AVAudioPlayer was long on promise and short on delivery. Time to find a Plan C.
Plan C was Apple's mature but complicated Audio Queue Services API. I hate complicated. I had been avoiding Audio Queue Services because I could see the complexity oozing from its pores. But AQS had been around. Lots of code had been built upon it. It was no newcomer like AVAudioPlayer and was clearly up to the task of playing my sounds, letting me control the volume, and a ton of other stuff I didn't need.
I took a deep breath, rolled up my sleeves and dove into AQS with the goal of creating a super simple wrapper around it so the rest of my code would never need to know the gnarlyness that lay within. What I came up with is ShortSoundPlayer, a class that lets you play sounds that are small enough to fit entirely in RAM. This last bit is important. ShortSoundPlayer is not meant for playing long sounds that must be buffered a piece at a time. However, if all you need to play is short sound clips (say, 30 seconds or less), then ShortSoundPlayer is worth a look. It's simple. And you can control the dang volume!
There is one little caveat to be aware of. I routinely blend Objective-C and C++ in my code, which has led me to use the .mm extension for all of my source files. If you prefer to avoid C++, then you may want to rename ShortSoundPlayer.mm to be ShortSoundPlayer.m before adding it to your Xcode project. This because this particular class doesn't use C++.
If you find any bugs, or make improvements to ShortSoundPlayer... please, Please, PLEASE post a comment and let me know!
Like most games, Bon Mot has a bunch of sound effects that augment the game play. Initally we considered having ambient background sounds, but we ditched that idea early on, figuring most people would rather listen to their own music while they play.
Without the need for continuous background audio in Bon Mot, I "simply" needed to play a bunch of short sound clips, all of them 30 seconds or less. Additionally I wanted to let our users turn down the volume of the game's sounds so they could better hear their music. If you're wondering why I put "simply" in quotes, well... you'll see.
The first stop in my hunt for audio code was Apple's Metronome sample. Metronome is a beautiful little app that behaves just like an old-school, mechanical metronome with a swinging, weighted arm. At that time, Metronome used Apple's System Sound Services to play its "tick" and "tock" sounds (Note: since the release of iPhone OS 3.0, Metronome has been updated to use AVAudioPlayer instead). Although Apple's documentation warns against using System Sound Services to play things like game sounds, I couldn't help notice that Apple's engineers were doing this very thing in Metronome. More importantly, it was clear that System Sound Services was by far the simplest audio API for the iPhone. I love simple.

Weeks passed with no magic fix. We sent out our first beta version to everyone we knew with an iPhone. The app was feature complete with one exception. The "Quiet" setting for Bon Mot's Game Sounds preference needed to be implemented and System Sound Services, while performing perfectly in every other way, refused to let me turn down the volume. Ignoring the problem hadn't fixed it and it was time for me to come up with a Plan B.
Plan B was Apple's promising, new (at the time) AVAudioPlayer class. Without laboring the details, AVAudioPlayer turned out to be a major headache. My understanding is that the iPhone OS 3.0 version of AVAudioPlayer is much improved. However, if you need to target iPhone OS 2.x or earlier, then I recommend you avoid AVAudioPlayer. I wasted a solid day or two trying to get it to work reliably, and I'm reasonably certain that the problems lay within AVAudioPlayer, not in my use of it. A bit of Googling confirmed that before iPhone OS 3.0, AVAudioPlayer was long on promise and short on delivery. Time to find a Plan C.
Plan C was Apple's mature but complicated Audio Queue Services API. I hate complicated. I had been avoiding Audio Queue Services because I could see the complexity oozing from its pores. But AQS had been around. Lots of code had been built upon it. It was no newcomer like AVAudioPlayer and was clearly up to the task of playing my sounds, letting me control the volume, and a ton of other stuff I didn't need.
I took a deep breath, rolled up my sleeves and dove into AQS with the goal of creating a super simple wrapper around it so the rest of my code would never need to know the gnarlyness that lay within. What I came up with is ShortSoundPlayer, a class that lets you play sounds that are small enough to fit entirely in RAM. This last bit is important. ShortSoundPlayer is not meant for playing long sounds that must be buffered a piece at a time. However, if all you need to play is short sound clips (say, 30 seconds or less), then ShortSoundPlayer is worth a look. It's simple. And you can control the dang volume!
@interface ShortSoundPlayer : NSObjectInstead of getting long winded describing the implementation, I'll just zip it up and post it here: ShortSoundPlayer.zip. Hopefully you'll find that the code speaks for itself. If not, post a comment and let me know.
{
NSString* _fileName;
NSString* _filePath;
float _volume;
bool _isPlaying;
AudioQueueRef _queue;
AudioQueueBufferRef _buffer;
}
@property (nonatomic, readonly) NSString* fileName;
@property (nonatomic, readonly) NSString* filePath;
@property (nonatomic, assign) float volume; // 0.0 = silent, 1.0 = max volume.
@property (assign) bool isPlaying;
- (id) initWithContentsOfFile: (NSString*) path;
- (BOOL) prepareToPlay; // Optional. Happens automatically on play. YES = success.
- (BOOL) play; // Sound is played asynchronously. YES = success.
@end
There is one little caveat to be aware of. I routinely blend Objective-C and C++ in my code, which has led me to use the .mm extension for all of my source files. If you prefer to avoid C++, then you may want to rename ShortSoundPlayer.mm to be ShortSoundPlayer.m before adding it to your Xcode project. This because this particular class doesn't use C++.
If you find any bugs, or make improvements to ShortSoundPlayer... please, Please, PLEASE post a comment and let me know!
0 Comments
Welcome to the blog MacNeil
July 30, 2009 Filed in: First Post
Hello and welcome to my first ever blog -- the blog MacNeil. If you'd like to learn more about me, here are links to my tiny company, personal website, LinkedIn page, and résumé.
The blog's name comes from my distant ancestors who were members of the Clan MacNeil, from the island of Barra off the western coast of Scotland. I have yet to visit Scotland, but my lovely wife Meg and I are saving our pennies and hoping to travel there soon.
To start out, this blog will be a place for me to share programming experience and code with the iPhone developer community. There have been many occasions when a useful piece of information in someone's blog helped get me over a programming hurdle. Now that I have one iPhone app under my belt and I'm well into app number two, I have some code and insights of my own to give back. So, my first few posts will be resuable code and tips for iPhone developers. From there, I'm not sure where I'll take it. Maybe some music chatter? I don't have a drop of musical ability, but I inherited a great of love of music from my dad, who has the largest collection of LP's (and CD's) of anyone I've met. Ever. We're talking more music than your typical public library.
Now that I've brought up music, there is something that's been on my mind. It's a music history "what if." I've been wondering how history would have unfolded if David Byrne and Billy Joel had crossed paths in a New York bar during their formative years? What if they had hit it off and started a band?
Have you ever heard someone say, "They could be the next Beatles." It's generous praise to be sure, though it also seems like the kiss of death for a band when music critics start putting it in print. Squeeze and Oasis come to mind. Those bands were doing fine until they got saddled with the "next Beatles" moniker. This got me wondering whether the whole idea of "the next Beatles" is a false premise. Maybe there can be no such thing? But then... what about the Police? (Similar to the Beatles, especially with the evolution/reinvention thing, but too quick to self-desctruct.) What about U2? (More like the Stones, hot and cold and built to last.) So I've been thinking about the individual musical styles of John Lennon and Paul McCartney and the chemistry that took place between them. Song credits on Beatles albums always say, "Lennon/McCartney," but it's not hard to tell which songs are Paul's (Hey Jude), which are John's (Across The Universe), and which bounce back and forth between the two of them (Happiness Is A Warm Gun or A Day In The Life). When I listen to their solo work and think about how it relates it to the music they made together, it all gets so dang fascinating that Meg ends up grabbing my shoulders and yelling, "Snap out of it dude!"
So what's the point? I guess it's just this. The solo work of David Byrne, Billy Joel, John Lennon, and Paul McCartney has some distinct parallels. A couple Brits and a couple Americans an ocean and almost a decade apart, but with the same basic chemistry. Try imagining a music history in which the Beatles never happened -- just solo Lennon and solo McCartney. Or better yet, imagine that you could sit a 21 year-old Billy Joel next to an 18-year old David Byrne sometime in the early Seventies, shortly after the Beatles broke up. Just try not to say something dumb like, "You guys could be the next Beatles."
But enough with the hypothetical hogwash. Music is for later. First it's all about code, gadgets and geekery.
So... welcome again to the blog MacNeil. If you find anything useful, or have any thoughts, suggestions or whatever, please post a comment! I'd love to hear from you.
The blog's name comes from my distant ancestors who were members of the Clan MacNeil, from the island of Barra off the western coast of Scotland. I have yet to visit Scotland, but my lovely wife Meg and I are saving our pennies and hoping to travel there soon.
To start out, this blog will be a place for me to share programming experience and code with the iPhone developer community. There have been many occasions when a useful piece of information in someone's blog helped get me over a programming hurdle. Now that I have one iPhone app under my belt and I'm well into app number two, I have some code and insights of my own to give back. So, my first few posts will be resuable code and tips for iPhone developers. From there, I'm not sure where I'll take it. Maybe some music chatter? I don't have a drop of musical ability, but I inherited a great of love of music from my dad, who has the largest collection of LP's (and CD's) of anyone I've met. Ever. We're talking more music than your typical public library.
Now that I've brought up music, there is something that's been on my mind. It's a music history "what if." I've been wondering how history would have unfolded if David Byrne and Billy Joel had crossed paths in a New York bar during their formative years? What if they had hit it off and started a band?
Have you ever heard someone say, "They could be the next Beatles." It's generous praise to be sure, though it also seems like the kiss of death for a band when music critics start putting it in print. Squeeze and Oasis come to mind. Those bands were doing fine until they got saddled with the "next Beatles" moniker. This got me wondering whether the whole idea of "the next Beatles" is a false premise. Maybe there can be no such thing? But then... what about the Police? (Similar to the Beatles, especially with the evolution/reinvention thing, but too quick to self-desctruct.) What about U2? (More like the Stones, hot and cold and built to last.) So I've been thinking about the individual musical styles of John Lennon and Paul McCartney and the chemistry that took place between them. Song credits on Beatles albums always say, "Lennon/McCartney," but it's not hard to tell which songs are Paul's (Hey Jude), which are John's (Across The Universe), and which bounce back and forth between the two of them (Happiness Is A Warm Gun or A Day In The Life). When I listen to their solo work and think about how it relates it to the music they made together, it all gets so dang fascinating that Meg ends up grabbing my shoulders and yelling, "Snap out of it dude!"
So what's the point? I guess it's just this. The solo work of David Byrne, Billy Joel, John Lennon, and Paul McCartney has some distinct parallels. A couple Brits and a couple Americans an ocean and almost a decade apart, but with the same basic chemistry. Try imagining a music history in which the Beatles never happened -- just solo Lennon and solo McCartney. Or better yet, imagine that you could sit a 21 year-old Billy Joel next to an 18-year old David Byrne sometime in the early Seventies, shortly after the Beatles broke up. Just try not to say something dumb like, "You guys could be the next Beatles."
But enough with the hypothetical hogwash. Music is for later. First it's all about code, gadgets and geekery.
So... welcome again to the blog MacNeil. If you find anything useful, or have any thoughts, suggestions or whatever, please post a comment! I'd love to hear from you.

