2017-02-11 109 views
2

声音在游戏中播放,但似乎无法通过AVAudioPlayer获得任何输出,令人头疼。最初这是作为一个班级设置的,但是当它不起作用时,我尝试对声音输出进行硬编码,以检查是否存在问题。它仍然没有工作,我尝试了几个不同的文件,以排除有问题的音频文件或格式。正在检索URL,但音频播放器似乎只是输出没有声音。通过SKAction播放声音但不通过AVAudioPlayer

我已阅读了一些关于类似问题的线索,并且弄清楚了系统声音设置,但没有任何区别。有人建议模拟器在某些情况下不能输出声音,但我不认为这是这种情况。

let myFile = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("gong", ofType: "wav")!) 
    print ("URL data: \(myFile)") 
    do{ 
     let audioPlayer = try AVAudioPlayer(contentsOfURL:myFile) 
     audioPlayer.prepareToPlay() 
     audioPlayer.play()  
    }catch { 
     print("Error playing sound") 
    } 

然而,这起罚款:

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

我需要AVAudioPlayer的功能我希望能够启动,停止和控制声音的音量,因为它循环。我使用XCode 7.3.1和Swift 2.2。

任何想法?

非常感谢, 千瓦

+0

你导入AVFoundation的权利? – Pierce

+0

是的。我想我已经解决了。我需要在AVAudioPlayer的一个范围内创建一个实例,这个范围是持久的,所以它不会被自动垃圾收集删除。另外,我认为prepareToPlay命令没有时间在执行play命令之前将文件加载到内存中,并且播放器也超出了范围,并且在退出调用代码块时几乎立即收集它。结果:没有机会玩。我将创建一个类,使用prepareToPlay将所有声音预加载到init()阶段的内存中,以便可以立即调用它们。谢谢 – Kwangle

+0

这就是我想说的,我从来没有使用'prepareToPlay'方法,并且我被告知通常没有必要。 – Pierce

回答

1

谈到斯威夫特2,我想你应该尝试不同的方法来获得的网址:

import AVFoundation 

func playMusic(filename: String) { 
    let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 
    if (url == nil) { 
     print("Could not find file: \(filename)") 
     return 
    } 
    do { backgroundMusicPlayer = try AVAudioPlayer(contentsOfURL: url!, fileTypeHint: nil) } 
    catch let error as NSError { print(error.description) } 
    if let player = backgroundMusicPlayer { 
     player.volume = 1 
     player.numberOfLoops = -1 
     player.prepareToPlay() 
     player.play() 
    } 
} 
0

我想补充一个答案,可以帮助我。 AVAudioPlayerplay()方法是异步的,所以我居然发现播放声音文件,而无需经历滞后第一次它的加载到内存中的最佳方式是通过调用其异步:

SWIFT 2

import AVFoundation 

var audioPlayer: AVAudioPlayer? 

init() { 

    let soundURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("FileName", ofType: "wav")!) 
    if let soundURL = soundURL { 

     do { 
      self.audioPlayer = try AVAudioPlayer(contentsOfURL: soundURL) 
     } catch let error as NSError { 
      print(error.description) 
     } 
    } else { 
     // Handle situation where URL isn't found 
     print("Sound file URL not found") 
    } 

} 

func playSound() { 
    guard let audioPlayer = audioPlayer else { return } 
    // Now we can play the sound asynchronously - which will eliminate any lag upon initial play 
    let qualityOfServiceClass = QOS_CLASS_BACKGROUND 
    let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0) 
    dispatch_async(backgroundQueue, { 
     audioPlayer.play() 
    }) 

} 

SWIFT 3

import AVFoundation 

var audioPlayer: AVAudioPlayer? 

init() { 

    let soundURL = URL(fileURLWithPath: Bundle.main.path(forResource: "FileName", ofType: "wav")!) 
    if let soundURL = soundURL { 

     do { 
      self.audioPlayer = try AVAudioPlayer(contentsOf: soundURL) 
     } catch let error { 
      print(error.description) 
     } 
    } else { 
     // Handle situation where URL isn't found 
     print("Sound file URL not found") 
    } 

} 

func playSound() { 
    guard let audioPlayer = audioPlayer else { return } 
    // Now we can play the sound asynchronously - which will eliminate any lag upon initial play 
    DispatchQueue.global().async { 
     audioPlayer.play() 
    } 

} 

的这个想法是将某种SoundManager类中的CLA进入你的模型。我通常创建一个类似这样的类,它为我的应用程序需要的每个声音都有一个AVAudioPlayer,我可以在加载ViewController时对其进行实例化 - 它将初始化个别的音频播放器,方法是自己的init()方法。然后我可以使用我自己的播放方法播放每个文件。如果您有一堆不同的声音,它也可以帮助使用enum来组织不同的文件,并且有一个自定义的play()方法可以播放作为请求传入的文件。

+0

谢谢皮尔斯。我最终做了与此非常相似的事情。我创建了一个AVAudioPlayer对象的字典,其中声音文件的文件名作为关键字。一种方法通过作为参数传递的文件名来对准播放器,并且它们立即播放。唯一的问题是每个声音都有一个AVAudioPlayer,所以你不能同时播放同一个声音的多个实例。当第二个播放电话在播放时仍然播放时,我通过将声音重置为开始来改善这种情况。在大多数情况下听起来很完美。希望这是有用的,谢谢大家。 – Kwangle