PDA

View Full Version : sound enquiry




chhoda
Nov 14, 2009, 06:59 AM
in my application I am using 3 sounds, short [8kb, 28kb, 260kb wav files]

I need both of them played quite frequently. So I wrote a singleton class
and initialised all the sounds to SystemSoundID member variables on first init. Then i keep playing them instead of creating SystemSoundID every time.

Now my question is am I leaking here ?

I need to dispose these soundids, on the destruction, especially means when application ends, what would that place be ?

or should I always create SystemSoundID and dispose them by implementing a playFinished callback ?

2 of these sounds are for almost any event in my app so are being used frequently. I think every time creating SystemSoundID and disposing them would be a performance issue.

thanks in advance
CH


static MySoundClass *mySharedInstance = nil;

@implementation MySoundClass

- (void) playSound:int stype {
SystemSoundID sid = 0;

switch (stype) {
case 1:
sid = oneSoundId;
break;
case 2:
sid = twoSoundId;
break;
case 3:
sid = threeSoundId;
break;
}

// Use audio services to play the sound
AudioServicesPlaySystemSound(sid);
}

- (SystemSoundID) createSoundId:(NSString *)file {
//Get the filename of the sound file:
NSString *path = [NSString stringWithFormat:@"%@/%@",
[[NSBundle mainBundle] resourcePath],
file];

//declare a system sound id
SystemSoundID soundID = 0;

//Get a URL for the sound file
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];

//Use audio sevices to create the sound
OSStatus error = AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
if (error != kAudioServicesNoError)
NSLog(@"Error creating sound %@", file);

return soundID;
}


- (id) init {
self = [super init];
if (self != nil) {
tapSoundId = [self createSoundId:@"one.wav"];
shuffledSoundId = [self createSoundId:@"two.wav"];
finishedSoundId = [self createSoundId:@"three.wav"];
}
return self;
}

+ (AMUtility *)sharedInstance {
@synchronized(self) {
if (nil == mySharedInstance) {
[[self alloc] init]; // assignment not done here
}
}
return mySharedInstance;
}


+ (id)allocWithZone:(NSZone *)zone {
@synchronized(self) {
if (nil == mySharedInstance) {
mySharedInstance = [super allocWithZone:zone];
return mySharedInstance; // assignment and return on first allocation
}
}
return nil; // on subsequent allocation attempts return nil
}

- (id)copyWithZone:(NSZone *)zone
{
return self;
}

- (id)retain {
return self;
}

- (unsigned)retainCount {
return UINT_MAX; // denotes an object that cannot be released
}

- (void)release {
//do nothing
}

- (id)autorelease {
return self;
}

@end



Stunner
Nov 14, 2009, 07:39 AM
Just a tip to help others help you. Edit your post put place "code" flags around your code. Like so:

//insert code in between flags

I did that by typing (code) and (/code)-but replace the parenthesis( "(",")" ) with brackets ( "[","]" ).

chhoda
Nov 14, 2009, 10:07 AM
Thanks a lot for the suggestion, somehow in stress(distress rather) ;) I overlooked it

xsmasher
Nov 14, 2009, 10:52 AM
What you are doing is fine - you can use the same soundID repeatedly, and it's probably a good idea for common sounds as you said.

When your app closes all memory gets reclaimed, so you will not see a leak. If you wanted to be textbook-correct, you should write a "dealloc" method to call AudioServicesDisposeSystemSoundID on all of your sounds, and then calls [super dealloc].

chhoda
Nov 15, 2009, 12:44 AM
thats the problem, i wrote a -(void) dealloc method, and put a breakpoint in there. when i exit the app it is not hit ! especially in this singleton class !

CH

xsmasher
Nov 15, 2009, 10:46 AM
Your dealloc won't automatically get run when the app closes - for most objects it won't run until everyone who alloc'd or retained the object releases it. For a singleton the dealloc will never be run unless you call it yourself, or you create a destroySingleton method that releases the shared instance and sets it to nil.