sound enquiry

Discussion in 'iPhone/iPad Programming' started by chhoda, Nov 14, 2009.

  1. macrumors 6502

    Joined:
    Oct 25, 2008
    #1
    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
    Code:
    
    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
    
     
  2. macrumors newbie

    Joined:
    Sep 14, 2009
    #2
    Just a tip to help others help you. Edit your post put place "code" flags around your code. Like so:
    Code:
    //insert code in between flags
    
    I did that by typing (code) and (/code)-but replace the parenthesis( "(",")" ) with brackets ( "[","]" ).
     
  3. thread starter macrumors 6502

    Joined:
    Oct 25, 2008
    #3
    Thanks a lot for the suggestion, somehow in stress(distress rather) ;) I overlooked it
     
  4. macrumors regular

    xsmasher

    Joined:
    Jul 18, 2008
    #4
    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].
     
  5. thread starter macrumors 6502

    Joined:
    Oct 25, 2008
    #5
    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
     
  6. macrumors regular

    xsmasher

    Joined:
    Jul 18, 2008
    #6
    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.
     

Share This Page