【问题标题】:AVAudioPlayerNode volume change is not applied immediatelyAVAudioPlayerNode 音量变化不会立即应用
【发布时间】:2020-12-12 21:55:09
【问题描述】:

使用 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 的音频无法处理大量快速重复的声音而不会出现故障和划痕(这是一款太空射击游戏……)模拟器和设备上的问题是相同的。任何帮助表示赞赏!

【问题讨论】:

    标签: ios swift sprite-kit


    【解决方案1】:

    好的,我找到了答案。音量更改后需要重置 AudioEngine 以使更改立即生效:

    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()
        }
    

    【讨论】:

    • 如果我错了,请纠正我,但您也可以只设置audioFilePlayer.volume 而无需触摸reset, stop, or play,输出音量应立即更改。
    • 我的经验是,仅更改音量并不会更改音量,除非您还进行了重置...这可能在新版本中已更改,现在它可能会起作用。如果有,您应该添加一个答案。
    • 2020年播放过程中仍然无法调整播放器节点的音量,Swift 5。停止播放,重置,调整音量,然后重新启动不是解决方案......但是,我做到了寻找替代方案。通过此链接了解如何在播放期间进行调整。我需要调整均衡器设置。也许使用 AVAudioEQ 的 globalGain 方法可以帮助你。 hackingwithswift.com/example-code/media/…
    • @SouthernYankee65 你能分享一下解决方案吗?
    • 不幸的是,我放弃了使用 AVAudioEngine 和使用节点的方法。但我认为当我采用这种方法时,我使用 AVAudioUnitEQ 上的 globalGain 方法通过计时器执行淡入淡出。抱歉,我无法提供更多帮助。
    【解决方案2】:

    是的,如果其他人有兴趣,我还通过在输入源和 engine.mainMixerNode 之间添加一个 AVAudioMixerNode 来解决它

    【讨论】:

      猜你喜欢
      • 2016-01-17
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 2022-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多