在iPhone游戏中播放声音-减速

在iPhone游戏中播放声音-减速,iphone,cocoa-touch,Iphone,Cocoa Touch,我正在使用AVAudioPlayer在我的应用程序中的一个单独线程上播放声音效果。现在我的应用程序相当简单,我有一个用于滚动背景的UIScrollView,还有几个Calayer,在一个简单的侧滚式游戏中代表一个玩家和一个敌人(想想马里奥、功夫等等)…我可以左右移动玩家,视图可以适当滚动,没有问题。我有一个正在播放音效的“攻击”按钮……很多时候,当我播放音效时,我会遇到一点小问题,图形化的。这是不是iPhone上使用石英课程的标准?有没有什么方法可以让它在不开始研究OpenGL的情况下执行得更流

我正在使用AVAudioPlayer在我的应用程序中的一个单独线程上播放声音效果。现在我的应用程序相当简单,我有一个用于滚动背景的UIScrollView,还有几个Calayer,在一个简单的侧滚式游戏中代表一个玩家和一个敌人(想想马里奥、功夫等等)…我可以左右移动玩家,视图可以适当滚动,没有问题。我有一个正在播放音效的“攻击”按钮……很多时候,当我播放音效时,我会遇到一点小问题,图形化的。这是不是iPhone上使用石英课程的标准?有没有什么方法可以让它在不开始研究OpenGL的情况下执行得更流畅一些?

您是如何播放声音的?如果我要猜测的话,每次播放声音时,操作系统实际上是从磁盘加载声音并播放它

更新:

好的,你真的不需要创建一个新的线程来播放声音。仅此一项就可能导致游戏中出现口吃,这也是多余的-AVAudioPlayer播放方法是异步的-它会立即返回,而不会在声音结束时返回。

(使用答案而不是长度注释,这样我就可以显示代码):

我的声音播放方法如下:

- (void)playSoundThreaded:(id)soundPlayer
{
  if(soundPlayer == nil)
    return;

  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  [(AVAudioPlayer*)soundPlayer play];
  [pool release];
}

- (void)playSound:(AVAudioPlayer*)player
{
  if(player == nil)
    return;

  [NSThread detachNewThreadSelector:@selector(playSoundThreaded:)
    toTarget:self withObject:(id)player];
}
fxPlayer = [[AVAudioPlayer alloc] initWithData:
  [NSData dataWithContentsOfFile:
    [[NSBundle mainBundle] pathForResource:@"voicehiya" ofType:@"caf"]] error:NULL];
声音加载如下:

- (void)playSoundThreaded:(id)soundPlayer
{
  if(soundPlayer == nil)
    return;

  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  [(AVAudioPlayer*)soundPlayer play];
  [pool release];
}

- (void)playSound:(AVAudioPlayer*)player
{
  if(player == nil)
    return;

  [NSThread detachNewThreadSelector:@selector(playSoundThreaded:)
    toTarget:self withObject:(id)player];
}
fxPlayer = [[AVAudioPlayer alloc] initWithData:
  [NSData dataWithContentsOfFile:
    [[NSBundle mainBundle] pathForResource:@"voicehiya" ofType:@"caf"]] error:NULL];

我们已经知道每次都会从磁盘重新加载声音…但不知道为什么会这样或如何防止它。

使用NSData DATA WITH CONTENTS OFMAPPEDFILE而不是DATA WITH CONTENTS OFFILE

另外,AVAudioPlayer处理自己的线程,您不需要创建线程。[AVAudioPlayer play]在开始播放后返回,而不是在播放结束后返回


当你不再需要AVAudioPlayer时,不要忘记释放它。例如,如果你只想播放一次声音,请实现AudioPlayerDifinishPlaying:successfully:委派并在其中释放它。

我认为线程过于复杂化了你的播放器。试试这个:

/* setup the sound player */
AVAudioPlayer *player1=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL     fileURLWithPath:audioFilePath] error:NULL];
player1.numberOfLoops = 0;
player1.volume=1.0f;
[player1 prepareToPlay];
然后播放声音就变成了

[player play];

别忘了正确设置AudioSession类别。

我也有同样的减速问题。为了解决这个问题,我首先在音量0时播放并暂停声音-这比prepareToPlay效果更好,因为prepareToPlay似乎仍然会导致速度减慢:

player.volume = 0.0;
[player play];
[player pause];
player.volume = 1.0;
当需要播放声音时,我只是[播放];。然后,在每个更新周期中,我都会循环播放所有活动的声音,捕捉即将结束的声音并回放它们,而不是让它们过期-这避免了从头开始播放声音的开销和速度降低。此处的示例在声音结束后1/15秒停止声音:

for ({each player in active sounds})
{
  if ((player.duration - player.currentTime) <= (1.0/15.0))
  {
    [player pause];
    player.currentTime = 0.0;
  }
}
({活动声音中的每个播放器})的

{

如果((player.duration-player.currentTime)为什么不使用AudioServicesPlaySystemSound?这非常适合音效


我在我的游戏(vConqr)中使用它,它也是基于UIScrollView的,有许多其他视图(因此所有视图都有自己的CALayer),它不会显著影响性能。

一开始也有同样的问题。根据文档,您需要称为“prepareToPlay”每次声音播放完毕。采用AVAudioPlayerDelegate协议并添加以下方法即可完成此操作

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    [player prepareToPlay];
}

多亏了我在工作中的一个项目,我已经对此进行了几天的调查。我在代码中添加了一些自制的评测,发现播放声音的调用导致了我的OpenGL游戏中的帧速率问题。根据我的发现,我为您提出了一些建议:

  • 使用AVAudioPlayer播放mp3作为背景音乐

  • 使用OpenAL获得声音效果

  • 对于声音效果,请使用apple的音频转换器命令行工具将声音转换为.caf格式。这是一种未压缩的格式,在将声音发送到声卡之前不需要CPU将声音解压缩到内存中。它可以直接运行,节省您的时间。可以找到使用该工具的说明。(滚动到页面的最底部)

  • 使用听起来仍然很好的最低位深度。你不需要128 kbps,你可能可以在很多事情上不需要20 kbps。更低的比特率=更少的处理=更快的声音


  • 如果我找到其他有用的东西,我会告诉你的!祝你好运!

    AudioServicesPlaySystemSound没有单独的音量控制。我最初是这样做的,它没有口吃。让fx单独的音量控制真的值得吗?大多数人只是想让它们打开或关闭,当然这取决于应用程序。我是在一个相互弹起的球的模拟中工作-我希望每次撞击的体积与撞击的速度成比例。啊,在这种情况下,我支持你