Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

dantastic

macrumors 6502a
Original poster
Jan 21, 2011
572
678
I've a timer and at the end of it an alarm.

The alarm sits in a function like this:

Code:
- (void) soundAlarm {
	[alarmTimer invalidate];
	alarmTimer = nil;
	SystemSoundID sound;
	AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"ALARM" ofType:@"WAV"]], &sound);
	AudioServicesPlaySystemSound (sound); 	
}

The first time the alarm sounds it's off by 0.5 sec or so. Any subsequent call to this function and there is no delay.

I have tried to put the
Code:
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"ALARM" ofType:@"WAV"]], &sound);
In the initialization code and just call the PlaySound from my function but the result is the same.

In the function above though, I'm not retaining anything so I should have to create the sound every time, no?

I can accept a delay, but why is there no delay the second & 3rd time I sound the alarm?

Is there any way of making this a bit more consistent? Perhaps playing the sound in the initialization code but in mute, can I do that?
 
The NSTimer has a delay the first time an instance is called. You could do a self performSelector in your viewDidLoad to get that first fire out of the way. There would be a random alarm sound though.

Where are you firing the timer from? Button? viewDidLoad?

You could probably do some kind of switch case statement where case 1 is
Code:
[alarmTimer invalidate];
	alarmTimer = nil;
and all other cases are
Code:
SystemSoundID sound;
	AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"ALARM" ofType:@"WAV"]], &sound);
	AudioServicesPlaySystemSound (sound); 
[alarmTimer invalidate];
	alarmTimer = nil;
 
So it's the timer firing that's causing this.

I'm firing from a button with this when the button is pressed
Code:
alarmTimer = [NSTimer scheduledTimerWithTimeInterval:(countdownSeconds) 
				target:self selector:@selector(soundAlarm) userInfo:nil repeats:NO];

The first time I press the button there's a 0.5 delay. any subsequent press and there's no delay.

Could I do a
Code:
alarmTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 
				target:self selector:@selector(doNothingFunction) userInfo:nil repeats:NO];
in my viewDidLoad? you think that would cure the lag? :D
 
Yeah that might work.

To make sure the timer is the reason for the delay put a NSLog at the end of your timer and see if it shows on the console after a delay.

If you are firing from a button push IBAction then put the code to play the sound in that method, not at the end of the timer... unless you mean that there is a delay after ( countdownSeconds ) ?

If the delay is after the countdownSeconds a hacky fix could be...
Code:
-(void)viewDidLoad{
    alarmTimer = [NSTimer scheduledTimerWithTimeInterval:.02 
				target:self selector:@selector(soundAlarm) userInfo:nil repeats:NO];
}
 -(void)soundAlarm{
   switch(){
     case1://no sound
break; 
     case2://sound
break; 
     case3://sound... this could work unless you fire the method a bizillion times 
break; 
      default:
    break; 
}
}

but I'd try the (doNothingFunction) first.

Nick
 
Is there any way of making this a bit more consistent? Perhaps playing the sound in the initialization code but in mute, can I do that?
Yeah, I've experienced something similar with the sound playing a bit delayed the first time. Even if you create the system sound earlier, there seems to be a hitch the first time it's played. Turning down the volume while playing the sound during init seems to be a plausible workaround. You should try it out.
 
I've done some more testing now.

1) Added some NSLogging. The timer is actually firing accurately enough. It's the sound playing that is delayed the first time.

2) I did set the timer to fire against a 'doNothing' function in my viewDidLoad but as expected with the result from test 1 that didn't do anything at all.

I suspect Apple won't be cool about me fiddling with the volume up and down in my app so I need to find a way of playing this without it being played. on the iPhone, is there something like /dev/null I can use to play my sound to or how would I go about playing it?
 
I see.

The delay occurs the first time with AudioServicesPlaySystemSound. In that case, create a short soundless audio track to play in your viewDidLoad. This will get that first fire out of the way silently. :cool:
 
I see.

The delay occurs the first time with AudioServicesPlaySystemSound. In that case, create a short soundless audio track to play in your viewDidLoad. This will get that first fire out of the way silently. :cool:

Aaah! Good thinking 99!

Code:
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"SILENCE" ofType:@"WAV"]], &alarm); 
	AudioServicesPlaySystemSound (alarm); 
	AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"ALARM" ofType:@"WAV"]], &alarm);

Playing one sec of silence in the viewDidLoad solved it. sneaky!

:D
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.