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

时间:2009-03-03 20:09:48

标签: iphone cocoa-touch

我正在使用AVAudioPlayer在我的应用中的单独线程上播放声音效果。现在我的应用程序相当简单,我有一个滚动背景的UIScrollView,以及一个代表玩家和一个简单的侧卷轴类型游戏中的敌人的CALayers(想想马里奥或功夫或诸如此类的东西)...我可以左右移动播放器,视图滚动适当,没有任何问题。我有一个“攻击”按钮正在播放声音效果......很多时候,当我播放声音效果时,我会有点故障,图形化。这对于使用Quartz的iPhone上的课程来说是否相同?如果没有开始研究OpenGL,有没有办法让这个表现得更顺畅?

8 个答案:

答案 0 :(得分:4)

使用NSData dataWithContentsOfMappedFile而不是dataWithContentsOfFile。

AVAudioPlayer也处理它自己的线程,你不需要创建一个。 [AVAudioPlayer play]在开始播放后返回,而不是在播放完毕后返回。

不要忘记在不再需要它时释放你的AVAudioPlayer,例如,如果你只想播放声音,请实现audioPlayerDidFinishPlaying:成功:委托并在那里发布它。

答案 1 :(得分:2)

你是怎么播放声音的?如果我猜一下,那就是每次播放声音时,操作系统实际上是从磁盘加载它以及播放它。

<强>更新

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

答案 2 :(得分:2)

我在减速方面遇到了同样的问题。为了解决这个问题,我首先在第0卷加载时播放并暂停声音 - 这比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;
  }
}

现在它准备好进行下一场比赛了。似乎工作正常!

更新:原来我第一次播放声音时仍然有一些停顿。我认为以零音量播放它实际上并没有做任何事情,但是我把它改为播放0.0001音量然后暂停 - 它听不见但似乎做了预备声音的工作。

答案 3 :(得分:2)

起初有同样的问题。根据每次声音播放完成后需要调用“prepareToPlay”的文档。采用AVAudioPlayerDelegate协议并添加以下方法即可。

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

答案 4 :(得分:1)

(使用答案而不是评论长度,因此我可以显示代码):

我的声音播放方法如下:

- (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];

我们有一些暗示每次都会从磁盘重新加载声音......但不知道为什么会这样或者如何防止它。

答案 5 :(得分:1)

我认为线程让你的播放器变得复杂。试试这个:

/* setup the sound player */
AVAudioPlayer *player1=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL     fileURLWithPath:audioFilePath] error:NULL];
player1.numberOfLoops = 0;
player1.volume=1.0f;
[player1 prepareToPlay];

然后playSound变为

[player play];

并且不要忘记也正确设置了AudioSession类别。

答案 6 :(得分:1)

为什么不直接使用AudioServicesPlaySystemSound?这非常适合音效。

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

答案 7 :(得分:0)

由于我在工作的一个项目,我现在已经调查了几天了。我在我的代码中添加了一些自制的分析,发现在我的OpenGL游戏中,播放声音的调用导致帧速率问题。根据我发现的内容,我得到了一些建议:

  1. 使用播放mp3的AVAudioPlayer作为背景音乐。

  2. 使用OpenAL获得音效。

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

  4. 使用仍然听起来不错的最低位深度。你真的不需要128 kbps - 你很可能会因为很多东西而逃脱20。较低的比特率=较少的处理=较快的声音。

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