2017-02-11 106 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