【问题标题】:Playing sounds in iPhone games - slowdowns在 iPhone 游戏中播放声音 - 减速
【发布时间】:2010-10-11 02:41:52
【问题描述】:

我正在使用 AVAudioPlayer 在我的应用程序的单独线程上播放声音 FX。现在我的应用程序相当简单,我有一个 UIScrollView 用于滚动背景,还有几个 CALayer 代表一个简单的横向卷轴类型游戏中的玩家和敌人(想想马里奥或功夫之类的)......我可以左右移动播放器,视图可以适当地滚动而没有问题。我有一个正在播放音效的“攻击”按钮……而且很多时候,当我播放音效时,我在图形上遇到了一点麻烦。这只是使用 Quartz 在 iPhone 上的课程吗?有没有什么方法可以在不开始研究 OpenGL 的情况下让它执行得更顺畅一些?

【问题讨论】:

    标签: iphone cocoa-touch


    【解决方案1】:

    使用 NSData dataWithContentsOfMappedFile 代替 dataWithContentsOfFile。

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

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

    【讨论】:

      【解决方案2】:

      你是如何播放声音的?如果我猜测一下,每次播放声音时,操作系统实际上都是从磁盘加载它并播放它。

      更新:

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

      【讨论】:

        【解决方案3】:

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

        player.volume = 0.0;
        [player play];
        [player pause];
        player.volume = 1.0;
        

        当需要播放声音时,我只是 [player play];。然后,每个更新周期我都会遍历所有活动声音并捕捉即将结束的声音并将它们倒回而不是让它们过期 - 这避免了从头开始声音的开销和减慢。此处的示例在声音结束后 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 音量播放然后暂停 - 它听不见,但似乎起到了准备声音的作用。

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            【解决方案5】:

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

            我的声音播放方法如下:

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

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

            【讨论】:

              【解决方案6】:

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

              /* 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 类别。

              【讨论】:

                【解决方案7】:

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

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

                【讨论】:

                • AudioServicesPlaySystemSound 没有单独的音量控制。我本来就是这样弄的,没有卡顿。
                • 为 fx 提供单独的音量控制真的很值得。大多数人只是想让它们打开或关闭
                • 当然,这取决于应用程序。我正在模拟一个球相互反弹 - 我希望每次击球的音量与击球的速度成正比。
                • 啊,那我陪你
                【解决方案8】:

                感谢我正在工作的一个项目,我已经调查了几天。我在我的代码中添加了一些自制的配置文件,发现播放声音的调用导致了我的 OpenGL 游戏中的帧速率问题。根据我的发现,我为您提供了一些建议:

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

                2. 为您的音效使用 OpenAL。

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

                4. 使用听起来还不错的最低位深度。您实际上并不需要 128 kbps - 很多事情您都可以使用 20 kbps。较低的比特率 = 更少的处理 = 更快的声音。

                如果我发现任何其他有用的东西,我会告诉你的!祝你好运!

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2010-11-02
                  • 2011-08-01
                  • 2010-09-19
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-07-25
                  相关资源
                  最近更新 更多