【问题标题】:AVAudioPlayer sound not playingAVAudioPlayer 声音不播放
【发布时间】:2015-12-22 11:16:43
【问题描述】:

在 iOS 8/Xcode 6 中,我有一个包含音效的函数。多次更改代码后,它不再适用于 iOS 9。这是我尝试过的:

原文:

let bangSoundEffect = SKAction.playSoundFileNamed("Bang.mp3", waitForCompletion: false)
        runAction(bangSoundEffect)

其他尝试:

self.runAction(SKAction.playSoundFileNamed("Bang.mp3", waitForCompletion: false))

还有:

func playRocketExplosionSound(filename: String) {
            let url = NSBundle.mainBundle().URLForResource(
                filename, withExtension: nil)
            if (url == nil) {
                print("Could not find file: \(filename)")
                return }
            var error: NSError? = nil
            do {
                backgroundMusicPlayer =
                    try AVAudioPlayer(contentsOfURL: url!)
            } catch let error1 as NSError {
                error = error1
                backgroundMusicPlayer = nil
            }
            if backgroundMusicPlayer == nil {
                print("Could not create audio player: \(error!)")
                return}
            backgroundMusicPlayer.numberOfLoops = 1
            backgroundMusicPlayer.prepareToPlay()
            backgroundMusicPlayer.play() }



playRocketExplosionSound("Bang.mp3")

我正在拔头发。我在不同的场景中使用相同的代码来获得另一种音效,效果很好!!怎么了? 我注意到声音效果有时会在模拟器中开始播放,但它没有完成并抛出此错误:

2015-09-24 19:12:14.554 APPNAME[4982:270835] 19:12:14.553 ERROR:    177: timed out after 0.012s (735 736); mMajorChangePending=0

它在实际设备上根本不起作用。

有什么问题? :'(

【问题讨论】:

  • 我在这里提供了导致问题的完整功能:stackoverflow.com/questions/32723431/…
  • 不在模拟器中测试?
  • 它在实际设备上根本不起作用。
  • 很难说。通常在电子游戏中,对于这些声音,您希望避免任何有损压缩格式,因为它们需要时间来解码。你为什么不试着把“砰”的声音变成WAV?我从来没有见过用 MP3 播放短音的电子游戏。我很确定Apple可以硬件加速一个音轨的解码,但可能同时出现多个问题(WAV文件不需要解码)。如果这没有帮助,那么问题出在其他地方,也许 SK 在某些情况下会杀死声音。
  • 如果代码适用于其他声音,那么我会查看资源本身。删除它并重新添加它,确保将项目复制到目标组的文件夹中。

标签: ios sprite-kit swift2 ios9 xcode7


【解决方案1】:

损坏的数据文件 | AVAudioPlayer 超出范围


1.损坏的数据文件

这将确保您找到了文件:

    var backgroundMusicPlayer: AVAudioPlayer? = nil

    if let url = Bundle.main.url(
        forResource: "Bang", withExtension: "mp3") {
        do {
            try backgroundMusicPlayer = AVAudioPlayer(contentsOf: url)
            backgroundMusicPlayer!.play()
        } catch {}
    }
    return nil

2。 AVAudioPlayer 超出范围

play() 完成并返回之前,保留backgroundMusicPlayer 的变量不得超出范围。这通常通过使用类变量来实现:

var backgroundMusicPlayer: AVAudioPlayer? = nil

不要这样做:由于var audioPlayer 的本地范围,以下声音最多只能为outOfScopeDelay 播放。

let outOfScopeDelay = 0.5
do {
    var audioPlayer:AVAudioPlayer! // Incorrectly scoped variable
    try audioPlayer = AVAudioPlayer(contentsOf: audioRecorder.url)
    audioPlayer.play()
    Thread.sleep(forTimeInterval: outOfScopeDelay)
} catch {}

► 在GitHub 上查找此解决方案,在Swift Recipes 上查找更多详细信息。

【讨论】:

  • 那只会捕获错误,而不是找出原因,对吗?我正在寻找错误“错误:177:0.012s (735 736) 后超时;mMajorChangePending=0”的解释,以及如何防止它而不是仅仅捕捉它。谢谢!
  • 您是否确认您没有错误地将AVAudioPlayer 定义为范围?见stackoverflow.com/a/32827915/218152
【解决方案2】:

MP3 文件可能存在问题

问题很可能与您正在使用的MP3 文件有关。该代码适用于其他声音,这表明MP3 文件可能已损坏并且AVAudioPlayer 解码失败。您可以尝试重新编码此文件并查看问题是否仍然存在。或者,更好的是,将其转换为 WAV

使用 WAV

为游戏创建短音效时,一般的经验法则是使用WAV,除非你真的觉得你需要修剪脂肪。

一流的游戏追求一流的制作质量,因此他们录制和制作未压缩的资产24bit/48kHz。野心稍弱的标题可能会以16/44.1 录制和制作,这是CD 质量音频的官方标准。

这至少有两个好处。一是声音质量更好。第二个,CPU 不用解码文件就可以播放。

【讨论】:

  • 我不是 OP,但我确实添加了赏金...我从外部 Web 服务获取我的 mp3 作为 NSData,因此偶尔获取损坏的文件并不是不可能的.我没有切换格式的选项。关于这与错误消息“错误:177:0.012s (735 736) 后超时;mMajorChangePending=0”有何关系?
  • 我赞成这个答案。即使文件格式不是问题,调试的正确方法是通过一个示例尝试此路线。据我所知,这个特定的错误没有记录在任何地方,但它似乎与使用任何 API 播放声音的行为有关。我认为必须探索不同的路线,这在视频游戏编程中很明显(声音引擎的通道有限,并且有据可查的 Apple 限制:音频解码一次只能播放一个音轨)。
【解决方案3】:

试试这个:

dispatch_async(dispatch_get_main_queue(), {
                        (self.playRocketExplosionSound("Bang.mp3")
                        })

在 iOS 9 下在子线程中播放音频不再安全。

【讨论】:

  • 有趣,你能提供一个链接到支持这一点的文档吗?谢谢!
  • 问题是 APPLE 真的不知道他们的问题,所以我们都只是尝试从经验中解决问题,没有可用于该问题的文档。
  • 我不同意。 可以在后台播放。您只需将AVAudioPlayer 引用保持足够长的时间以使声音完成。
  • 我同意@SwiftArchitect。 AVAudioPlayer 的播放方法是异步的,但似乎可以在后台线程中正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
相关资源
最近更新 更多