使用AVFoundation和AVAudioPlayerNode使用Xcode版本9.2(9C40b)播放声音并部署到iOS 11.2
问题在于,当您改变音量时,第一次播放声音时不会应用更改,还有其他奇怪的效果。
在Xcode中启动一个新项目,选择iOS Game,并提供任何名称。然后用:
替换GameScene.swift中的代码import SpriteKit
import GameplayKit
import AVFoundation
class GameScene: SKScene {
var entities = [GKEntity]()
var graphs = [String : GKGraph]()
let audioFilePlayer = AVAudioPlayerNode()
var audioFile:AVAudioFile! = nil
var audioFileBuffer:AVAudioPCMBuffer! = nil
override func sceneDidLoad() {
do {
let path = Bundle.main.path(forResource: "sound", ofType: "caf")!
let url = URL(fileURLWithPath: path)
audioFile = try AVAudioFile(forReading: url)
audioFileBuffer = AVAudioPCMBuffer(pcmFormat: audioFile.processingFormat, frameCapacity: UInt32(audioFile.length))
try audioFile.read(into: audioFileBuffer!)
audioEngine.attach(audioFilePlayer)
audioEngine.connect(audioFilePlayer, to: audioEngine.mainMixerNode, format: audioFileBuffer?.format)
try audioEngine.start()
}
catch {
print(error)
}
let playAction = SKAction.sequence([
SKAction.wait(forDuration: 3.0),
SKAction.run { self.play(volume: 1.0) },
SKAction.wait(forDuration: 1.0),
SKAction.run { self.play(volume: 1.0) },
SKAction.wait(forDuration: 1.0),
SKAction.run { self.play(volume: 0.0) },
SKAction.wait(forDuration: 1.0),
SKAction.run { self.play(volume: 0.0) },
SKAction.wait(forDuration: 1.0),
SKAction.run { self.play(volume: 1.0) },
SKAction.wait(forDuration: 1.0),
SKAction.run { self.play(volume: 1.0) },
])
self.run(playAction)
}
func play(volume:Float) {
print("playing at \(volume)")
audioFilePlayer.stop()
audioFilePlayer.volume = volume
audioFilePlayer.scheduleFile(audioFile, at: nil, completionHandler: nil)
audioFilePlayer.play()
}
}
为不良选项道歉......另外,将一个名为sound.caf的声音文件添加到项目中。
控制台输出为:
playing at 1.0
playing at 1.0
playing at 0.0
playing at 0.0
playing at 1.0
playing at 1.0
我希望听到:大声,响亮,没有,没有,大声,响亮。
我实际上是在听:大声,响亮,响亮,没有,柔软,响亮
('软'特别奇怪)
我也尝试用以下方法更改主音量:
audioEngine.mainMixerNode.outputVolume = volume
但声音是一样的。
在较旧的游戏中,过去常常使用OpenAL,但这需要Obj-C并且在桥接标题等方面非常混乱。而且,OpenAL据说不再受支持了。基于SKAction的音频无法处理大量快速重复的声音而没有毛刺和划痕(它是一个太空射击游戏......)在模拟器和设备上问题是相同的。任何帮助表示赞赏!
答案 0 :(得分:2)
好的,我找到了答案。音量变化需要在音量变化后重置,以便立即进行更改:
audioEngine.reset()
这个play()函数有效:
func play(volume:Float) {
print("playing at \(volume)")
audioFilePlayer.volume = volume
audioEngine.reset()
audioFilePlayer.stop()
audioFilePlayer.scheduleFile(audioFile, at: nil, completionHandler: nil)
audioFilePlayer.play()
}
答案 1 :(得分:0)
是的,如果其他人感兴趣,我也通过在输入源和engine.mainMixerNode之间添加AVAudioMixerNode来解决它