Как предварительно загрузить SCNAudioSource, чтобы предотвратить задержку при первом воспроизведении звука? - PullRequest
1 голос
/ 29 января 2020

Не должно быть лагов, потому что я настраиваю и предварительно загружаю каждый звук в viewDidLoad() перед воспроизведением.

class GameViewController: UIViewController {

    private var sounds = [String: SCNAudioSource]()

    override func viewDidLoad() {
        super.viewDidLoad()

        loadAllSounds()
    }

}

extension GameViewController {

    private func loadSound(name: String, path: String) {
        if let sound = SCNAudioSource(fileNamed: path) {
            sound.isPositional = false
            sound.volume = 0.8
            sound.shouldStream = false

            // Loads audio data from the source and prepares it for playing
            sound.load()

            sounds[name] = sound
        }
    }

    private func loadAllSounds() {
        loadSound(name: "Whoosh", path: "whoosh.wav")
        loadSound(name: "Pop", path: "pop.wav")
        loadSound(name: "Slide", path: "slide.wav")
    }

}

Для воспроизведения звуков у меня есть функция playSound(). Эта функция вызывается в зависимости от событий в игре. Например, когда игрок прыгает. Таким образом, задержка возникает только при первом воспроизведении каждого звука.

private func playSound(withName name: String, atNode node: SCNNode) {
    let playAudio = SCNAction.playAudio(sounds[name]!, waitForCompletion: false)
    node.runAction(playAudio)
}

Похоже, SCNAudioSource.load () не загружает и не подготавливает звуки. Либо я делаю что-то не так.

Буду рад любой помощи. Спасибо!

1 Ответ

2 голосов
/ 22 февраля 2020

У меня была такая же проблема при работе с SCNAction.playAudio () в SceneKit. После нескольких дней игры с моим звуковым файлом (изменение кода c, битрейт и т. Д. c.) Я проанализировал проблему, используя инструменты, и пришел к выводу, что SceneKit будет инициализировать свой Audio-Engine только тогда, когда вы скажете ему воспроизвести звук. Я знаю, что это не очень хорошее решение, но я не мог найти более элегантное:

static func prepareSoundEngine(rootNode: SCNNode) {
    let sound = SCNAudioSource(named: "init.mp3")!
    sound.load()
    let player = SCNAudioPlayer(source: sound)

    player.didFinishPlayback = {
        rootNode.removeAudioPlayer(player)
    }

    rootNode.addAudioPlayer(player)
}

'init.mp3' - это полностью пустой звуковой файл длиной в одну секунду. Посетите эту страницу GitHub, чтобы загрузить такой файл: https://github.com/anars/blank-audio

Затем я вызываю эту функцию, как только моя сцена становится видимой, и каждый SCNAction.playSound () будет воспроизводиться без задержки.

...