How to play sound at precise moments on iPhone?
I'm working on creating a simple metronome on the iPhone. What the app does right now is to run a timer, entering the timer's function every 1/1000th of second. Then it checks the current time vs time of starting the app (I'm using CACurrentMediaTime()
function).
CFTimeInterval currentTime = CACurrentMediaTime();
if (self.beatingStartTime == 0) {
self.beatingStartTime = currentTime;
}
if ( (currentTime - self.beatingStartTime) >= self.timeIntevalBetweenTicks * self.internalTimerCounter ) {
self.internalTimerCounter ++;
// ...
}
If there is a good moment to play audio, the code using OpenAL to play it gets fired.
Basicly that's it. I checked the sounds played when running both in simulator as well as on 2 devices (iPad and jailbroken iPhone 3GS) and there is a problem - when I recorded the sound and reviewed the waveform in Reaper
software, some sounds play a bit too late, and some of them - bit too early (even I could understand the "too late" part, I don't really get how it can play earlier then it should - since the app checks the number of seconds every time, it basicl开发者_开发百科y can't be ealier then specified time - yet it is, according to my recods).
At the same time there are some metronome apps that are known for being "rock-solid" when it comes to timing, so I guess there is a way. I just wonder what I'm missing...
edit: Changing timer call from 1/1000th second to, for example 1/100th doesn't help.
edit 2: When I switched from timer to threads (and I put the thread to sleep for specified time) I still get a strange behavior. The tempo moves around and while I could understand a little lag and playing some sounds too late, the problem is some of them do play too early - it means time distance between 2 beats is less then the time that should pass.
The diffrence is about 3%, which translates to about 10-15 miliseconds, which is quite a lot for me. Anyone got an idea why the sound can play earlier? I tried it both on iPhone simulator and on iPad actual device, and my only guess is there's something wrong with the timer - CACurrentMediaTime()
returning more seconds that it should. Is it even possible?
Try using an NSSound, and load it up as an instance variable and don't release it unless your metronome isn't running. Delays can be caused by loading the file into memory on the loop. The other thing to consider is that a metronome probably doesn't need to poll every 1/1000th of a second. If you do it less often, you're less likely to saturate the CPU and you might get more consistent results.
Lastly, check out how Apple's demo works: http://developer.apple.com/library/ios/#samplecode/Metronome/Introduction/Intro.html
Might give you a better idea how to accomplish what you're trying to do :)
What you want is COCOS DENSHION which is a simple reliable easy to use sound library, that we have found solves all problems.
I (just personally) don't like "Cocos2D" but you can just take and use CocosDenshion.
Secondly -- 1000th of a second is ridiculous for a timer. Just totally forget it.
Thirdly -- AVAudioPlayer is worthless as you found.
Note - "ObjectAL" is a new, perhaps better, alternative
to CocosDenshion. Check it out.
精彩评论