Hi,
I'm building a simple bpm / metronome app.
Most of it is working fine, but I'm having a hard time getting my click sounds to play in time.
I am using an NSTimer to trigger my sounds at the BPM interval.
I even put the NSTimer on a separate GCD queue, but still the sounds are sometimes (not always) out of sync.
I think I have it narrowed down to the interval value of my NSTimer.
Could it be that NSTimer is having a hard time rounding my interval value ?
Specifically, when I set my interval at 0.441 (which is 136 BPM), then playback is not consistent.
Code:
dispatch_async(myQueue, ^(void) {
myTimer = [[NSTimer alloc] initWithFireDate:[NSDate date]
interval:frequency
target:self
selector:@selector(timerTask:)
userInfo:nil
repeats:YES];
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runloop addTimer:myTimer forMode: NSDefaultRunLoopMode];
[myTimer release];
[runloop run];
Code:
- (void)timerTask:(NSTimer *)aTimer
{
if(!soundIsMuted) {
//play clickSound
AudioServicesPlaySystemSound (self.oneFileObject);
}
// set button to highlight for blinking in tempo
[tapButton setImage:[UIImage imageNamed:@"button-highlight.png"] forState:UIControlStateNormal];
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(changeButtonBack:) userInfo:nil repeats:NO];
}
The above is what I'm using now, the interval frequency is set by buttontaps (but at the moment I'm hardcoding the value to test).
The NSTimer is calling my audio and button flashing code.
I have already gone from AVFoundation to AudioToolbox as I thought I didn't need the overhead to play very small sound fragments.
To be clear, everything works, but the sounds are sometimes not in tempo.
It is also not the case that the NSTimer might not keep up, if I set it's interval to 0.3 (= 200 BPM) the clicksounds are perfectly in tempo, and this is faster than 0.441, so speed seems not to be an issue.
This is why I believe it might be a rounding factor ?
I also need this level of precision (3 digits after comma) because :
134 BPM = 0.447 s
135 BPM = 0.444 s
136 BPM = 0.441 s
Is there a better way to tackle this ?