Fancy Rat Studios

  • Home
  • Games
  • About

05
Feb
2010

Fun with cocosDenshion and Audio Metering [Update]

Lam

For those of you that have gotten a chance to use CocosDenshion, it is the sound engine written by Steve Oldmeadow.
It’s great since loading audio effects and music for us was quite a task beforehand.

Here’s a little demo of what we are going to make in this article shown running on the iPhone simulator.

Well today what we’ll look at is the CDAudioManager class of the CocosDenshion package itself and see if we can produce some neat effects to spice up our games.

Let’s understand CDAudioManager a bit by looking at the comments in the source.

/** CDAudioManager is a wrapper around AVAudioPlayer.
 CDAudioManager is basically a thin wrapper around an AVAudioPlayer object used for playing
 background music and a CDSoundEngine object used for playing sound effects. It manages the
 audio session for you deals with audio session interruption. It is fairly low level and it
 is expected you have some understanding of the underlying technologies. For example, for
 many use cases regarding background music it is expected you will work directly with the
 backgroundMusic AVAudioPlayer which is exposed as a property.

 Requirements:
 - Firmware: OS 2.2 or greater
 - Files: CDAudioManager.*, CocosDenshion.*
 - Frameworks: OpenAL, AudioToolbox, AVFoundation
 @since v0.8
 */

Since it’s a wrapper around AVAudioPlayer we have some functionality for obtaining data that you can use for playback-level metering.

The methods to use for level metering are:

  • the meteringEnabled property
  • -(void)updateMeters
  • -(float)averagePowerForChannel:(NSUInteger)channelNumber
  • -(float)peakPowerForChannel:(NSUInteger)channelNumber

Since we’re just quickly setting up some background audio, let’s do this as simple as possible by using SimpleAudioEngine.

Accessing CDAudioManager

SimpleAudioEngine (as of this post) won’t give us direct access to the audio manager for our background music so let’s quickly add a get method to return the audio manager.

SimpleAudioEngine.m

-(CDAudioManager*)audioManager
{
	return am;
}

Update: The alternative for accessing is through the sharedInstance of audio manager and I’ve now reworked the code to use that instead. So now you don’t need to modify SimpleAudioEngine anymore.

We needed access to CDAudioManager so we can get access to AVAudioPlayer to access metering methods. We do this below:

Updated for performance by weak referencing the AVAudioPlayer instance into a class variable.

audioPlayer_ = [[SimpleAudioEngine sharedEngine] audioManager].backgroundMusic;
audioPlayer_.meteringEnabled = YES;

Well we have enabled metering but what we now need to do is call updateMeters every time we need
to get meter level values. Cocos2D has functionality for scheduling timers so we set that up and call updateMeters.

-(void)tick:(ccTime) dt
{
	[audioPlayer_ updateMeters];
}

While still in the loop where we update our meter, we can now get values for the average and peak power of our background music.

-(void)tick:(ccTime) dt
{
	[audioPlayer_ updateMeters];
	double peakPowerForChannel = 0.f, avgPowerForChannel = 0.f;

	for(ushort i = 0; i < audioPlayer_.numberOfChannels; ++i){
		//	convert the -160 to 0 dB to [0..1] range
		peakPowerForChannel = pow(10, (0.05 * [audioPlayer_ peakPowerForChannel:i]));
		avgPowerForChannel = pow(10, (0.05 * [audioPlayer_ averagePowerForChannel:i]));

		filteredPeak_[i] = filterSmooth_ * peakPowerForChannel + (1.0 - filterSmooth_) * filteredPeak_[i];
		filteredAverage_[i] = filterSmooth_ * avgPowerForChannel + (1.0 - filterSmooth_) * filteredAverage_[i];
	}
}

What I’ve done is set all this up in the class AudioVisualization which will handle all the background audio metering for you. You access the class through the sharedAV method which returns a shared singleton instance.

All you need to do is add your delegate with the method:

-(void)addDelegate:(id<AudioVisualizationProtocol>)delegate forChannel:(ushort)channel;

The forChannel argument specifies the channel you want to meter for your background music. If it is mono then just set it to 0.

Now you just need to implement one of the AudioVisualizationProtocol’s to receive level values for your delegate.

-(void)avAvgPowerLevelDidChange:(float)level channel:(ushort)aChannel;

That’s pretty much it! Hope you find this as cool as I did when I figured it out.

Just download the example demo file below to try it out.


Download the XCode Demo

This demo uses the fast, easy and open source cocos2d framework.
CocosDenshion is the sound engine for the cocos2d framework if you didn’t know that from reading this whole post =/.

You can leave a response, or trackback from your own site.

8 Conversations

  1. Terrance says:
    February 5, 2010 at 11:23 pm

    I plan to make a demo video to help show what the demo code can do, stay tuned.

  2. Dance, cocos2d, dance | cocos2d for iPhone says:
    February 11, 2010 at 8:17 pm

    [...] can read the article here: Fun with CocosDenshion and audio metering And you can download the test project from here: [...]

  3. George Sealy says:
    February 11, 2010 at 9:43 pm

    Nicely written and very useful! Thanks for the tutorial.

  4. Awesome Fun Music-Synced Animation With Video And Code | iPhone Development Tutorials and Programming Tips says:
    February 13, 2010 at 12:54 am

    [...] The full tutorial and code can be found here: Fun with cocosDenshion and Audio Metering [...]

  5. John From Berkeley » links for 2010-02-26 says:
    February 26, 2010 at 5:38 pm

    [...] Fun with cocosDenshion and Audio Metering [Update] | Fancy Rat Studios (tags: music iphone animation programming tutorials opensource) [...]

  6. Weekly Digest for March 16th says:
    March 16, 2010 at 5:31 am

    [...] Fun with cocosDenshion and Audio Metering [Update] | Fancy Rat Studios [...]

  7. Alex says:
    June 3, 2010 at 4:45 pm

    Is there away to select a sound from the iTunes music library rather than embedded song?

  8. Lam says:
    June 3, 2010 at 6:47 pm

    As of right now the way to play music off of the devices library is through the MPMediaPickerController. It’s quite an easy class to setup and get music running. Unfortunately the class does not connect itself with the AVAudioFoundation class which is what we’re using to run the metering code in this post but it if that’s not what you’re looking for then that is the best solution.

Converse

Click here to cancel reply.

Games

  • Mini Games

Community

  • About
  • Contact

Sitemap

  • Blog
  • RSS FeedSubscribe in a reader
  • XHTML Strict 1.0

Fancy Rat Studios is proudly powered by WordPress 2.9.2

Background image courtesy of robertvitulano

© 2010 Fancy Rat Studios. All Rights Reserved.