在不同 iOS 设备上同步声音的问题
我创建了一个音乐应用程序,当物体与网格边缘碰撞时,它会播放 9 种声音之一。这在模拟器上绝对完美,但在第四代设备上不太同步,在 iPhone 3g 上完全不同步。
我所说的不同步是指混响每 0.2 秒发生一次,以匹配网格移动的速度,并且由于设备上的混响不同时发生,因此声音听起来不正确。另外,通过查看 iPhone 3g,您可以看出网格绝对不会每 0.2 秒重新绘制一次 - 它要慢得多。
这是基本代码:
- (void)startTime {
[musicTimer setFireDate:[NSDate distantFuture]];
musicTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01
target: self
selector: @selector(checkTime)
userInfo: nil
repeats: YES];
}
- (void)checkTime {
float timeSince = [[NSDate date] timeIntervalSinceDate:lastPlayed];
if(timeSince >= 0.2){
[self repositionBlocks];
}
}
- (void)repositionBlocks {
//Check which sounds need to play and call the play function on each of them
//The following line would play the sound if a collision occurred
Sound *sound = [[Sound alloc] init];
[sound play:@"01.wav"];
[sound release];
[self redrawGrid]; //Redraws the grid with the new positions
[lastPlayed release];
lastPlayed = [[NSDate date] retain];
}
这是我的 Sound 类中的播放函数
- (void)play:(NSString *)soundFile {
NSString *path;
NSString *fileName = [NSString stringWithFormat:@"/%@", soundFile];
path = [NSString stringWithFormat:@"%@%@", [[NSBundle mainBundle] resourcePath], fileName];
SystemSoundID soundID;
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
AudioServicesPlaySystemSound(soundID);
[filePath release];
}
如果有人可以帮助解决这个问题,我将非常感激
谢谢
编辑: 我已经做了一些测试并将其范围缩小到NSTimer 的问题,在模拟器上它每 0.2 秒触发一次,但在设备上它每 0.4 - 0.6 秒触发一次。我在互联网上搜索过,有很多关于 NSTimers 如何不准确且不应该用于此目的的信息,但我找不到任何替代方案。
I have created a music app that plays one of 9 sounds when an object collides with the edge of a grid. This works absolutely flawlessly on the simulator but does not quite sync up on 4th gen devices and is completely out of sync on the iPhone 3g.
By out of sync I mean that the reverb happens every 0.2 seconds to match the speed of the grid movement and because the reverb isn't at the same time on the device the sounds don't sound right. Also from looking at the iPhone 3g you can tell that the grid definitely isn't redrawing every 0.2 seconds - it is much slower.
Here is the basic code:
- (void)startTime {
[musicTimer setFireDate:[NSDate distantFuture]];
musicTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01
target: self
selector: @selector(checkTime)
userInfo: nil
repeats: YES];
}
- (void)checkTime {
float timeSince = [[NSDate date] timeIntervalSinceDate:lastPlayed];
if(timeSince >= 0.2){
[self repositionBlocks];
}
}
- (void)repositionBlocks {
//Check which sounds need to play and call the play function on each of them
//The following line would play the sound if a collision occurred
Sound *sound = [[Sound alloc] init];
[sound play:@"01.wav"];
[sound release];
[self redrawGrid]; //Redraws the grid with the new positions
[lastPlayed release];
lastPlayed = [[NSDate date] retain];
}
Here is the play function inside my Sound class
- (void)play:(NSString *)soundFile {
NSString *path;
NSString *fileName = [NSString stringWithFormat:@"/%@", soundFile];
path = [NSString stringWithFormat:@"%@%@", [[NSBundle mainBundle] resourcePath], fileName];
SystemSoundID soundID;
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
AudioServicesPlaySystemSound(soundID);
[filePath release];
}
If anyone could help at all with this issue I would be extremely grateful
Thanks
EDIT: I have done some tests and narrowed it down to a problem with the NSTimer, on the simulator it triggers every 0.2 seconds but on the device it triggers every 0.4 - 0.6 seconds. I have searched on the internet and there is lots of information about how NSTimers are not accurate and shouldn't be used for this but I can't find any kind of alternative.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用 CADisplayLink 设置帧速率;它比使用 NSTimer 准确得多。
您还可以尝试使用 AVAudioPlayer 缓存声音 - 在加载应用程序或屏幕期间,对每个缓存的声音调用prepareToPlay,然后当您稍后调用播放时,它应该立即播放,没有延迟。 AVAudioPlayer 处理缓存声音或从存储中传输声音等。
Use CADisplayLink to set your framerate; it is far more accurate than using an NSTimer.
You might also try caching your sounds by using AVAudioPlayer - during loading of the app or screen, call prepareToPlay on each cached sound, then when you call play later it should playback instantly with no delay. The AVAudioPlayer handles caching the sounds or streaming them from storage, etc.