ARKit – Spatial Audio 几乎不会随距离改变音量

Posted

技术标签:

【中文标题】ARKit – Spatial Audio 几乎不会随距离改变音量【英文标题】:ARKit – Spatial Audio barely changes the volume over distance 【发布时间】:2020-01-22 10:47:22 【问题描述】:

我创建了一个 SCNNode 并向其添加了音频。

这是一个单声道音频。一切都设置正确。

它作为空间音频工作,这不是问题。

问题在于,当我靠近或远离时,它几乎不会改变音量。我知道如果我离得很远,它会发生变化,但这与 Apple 在这里展示的完全不同:

https://youtu.be/d9kb1LfNNU4?t=23

我发现其他一些游戏的音量真的会从一步距离开始变化。

用我的,一步你甚至无法判断音量发生了变化。您至少需要 4 个步骤。

有人知道为什么吗?

代码如下:

SCNNode *audioNode = [[SCNNode alloc] init];
SCNAudiosource *audioSource = [[SCNAudioSource alloc] initWithFileNamed:audioFileName];
audioSource.loops = YES;
[audioSource load];
audioSource.volume = 0.05; // <-- i used different values. won't change much either
audioSource.positional = YES;
//audioSource.shouldStream = NO; // <-- makes no difference
[audioNode addAudioPlayer:[SCNAudioPlayer audioPlayerWithSource:audioSource]];

[audioNode runAction:[SCNAction playAudioSource:audioSource waitForCompletion:NO] completionHandler:nil];
[massNode addChildNode:audioNode];

也许节点的规模?

整个场景大约有 4 英尺大小。

当我添加一个对象时,我通常将其缩放到 0.005(否则它会变得太大)。 但我也尝试使用 .scn 文件中已经具有正确大小的文件。

它不应该影响任何东西,因为结果是一个咖啡桌大小的场景,我可以看到物体。

【问题讨论】:

【参考方案1】:

更新

这是控制声音衰减的工作代码(适用于 iOS 和 macOS):

import AVFoundation
import ARKit

class ViewController: UIViewController, AVAudioMixing 

    @IBOutlet var sceneView: SCNView!
    // @IBOutlet var sceneView: ARSCNView!
    
    func destination(forMixer mixer: AVAudioNode,
                                bus: AVAudioNodeBus) -> AVAudioMixingDestination? 
        return nil
    
    var volume: Float = 0.0
    var pan: Float = 0.0
    
    var sourceMode: AVAudio3DMixingSourceMode = .bypass
    var pointSourceInHeadMode: AVAudio3DMixingPointSourceInHeadMode = .bypass
    
    var renderingAlgorithm = AVAudio3DMixingRenderingAlgorithm.sphericalHead
    var rate: Float = 1.2
    var reverbBlend: Float = 40.0
    var obstruction: Float = -100.0
    var occlusion: Float = -100.0
    var position = AVAudio3DPoint(x: 0, y: 0, z: 10)
    let audioNode = SCNNode()
    
    override func viewDidLoad() 
        super.viewDidLoad()
        let myScene = SCNScene()
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(0, 0, 0)
        myScene.rootNode.addChildNode(cameraNode)
        
        // let sceneView = view as! SCNView
        sceneView.scene = myScene
        sceneView.backgroundColor = UIColor.orange
        
        let myPath = Bundle.main.path(forResource: "Mono_Audio", ofType: "mp3")           
        let myURL = URL(fileURLWithPath: myPath!)
        let mySource = SCNAudioSource(url: myURL)!
        mySource.loops = true
        mySource.isPositional = true           // Positional Audio
        mySource.shouldStream = false          // FALSE for Positional Audio
        mySource.volume = volume
        mySource.reverbBlend = reverbBlend
        mySource.rate = rate

        mySource.load()
        
        let player = SCNAudioPlayer(source: mySource)
        let sphere: SCNGeometry = SCNSphere(radius: 0.1)
        let sphereNode = SCNNode(geometry: sphere)
        sphereNode.addChildNode(audioNode)
        myScene.rootNode.addChildNode(sphereNode)
        audioNode.addAudioPlayer(player)            

        sceneView.audioEnvironmentNode.distanceAttenuationParameters.maximumDistance = 2
        sceneView.audioEnvironmentNode.distanceAttenuationParameters.referenceDistance = 0.1   
        sceneView.audioEnvironmentNode.renderingAlgorithm = .auto

        // sceneView.audioEnvironmentNode.reverbParameters.enable = true
        // sceneView.audioEnvironmentNode.reverbParameters.loadFactoryReverbPreset(.plate)
        
        let hither = SCNAction.moveBy(x: 0, y: 0, z: 1, duration: 2)
        let thither = SCNAction.moveBy(x: 0, y: 0, z: -1, duration: 2)
        
        let sequence = SCNAction.sequence([hither, thither])
        let loop = SCNAction.repeatForever(sequence)
        sphereNode.runAction(loop) 
    

而且,是的,您完全正确——有一些强制性设置。

但有7个

使用AVAudioMixing 协议及其存根(属性和方法)。

使用MONO 音频文件。

使用source.isPositional = true

使用source.shouldStream = false

maximumDistance 值分配给distanceAttenuationParameters 属性。

referenceDistance 值分配给distanceAttenuationParameters 属性。

mySource.load() 的位置在您的代码中非常重要。

P.S. If the aforementioned tips didn't help you, then use additional instance properties to make your sound even quieter using a graph, obstacles and orientation of implicit listener:

var rolloffFactor: Float  get set       // attenuation's graph, default = 1 

var obstruction: Float  get set         // default = 0.0

var occlusion: Float  get set           // default = 0.0

var listenerAngularOrientation: AVAudio3DAngularOrientation  get set  //(0,0,0)

如果你用 Objective-C 编写它肯定会工作

在此示例中,audioNodelistener 的距离为 1 米。

【讨论】:

很明显,我使用的值无关紧要,它们没有效果..衰减是一样的.. 是的,没有任何区别。就像我之前说的,它可以工作,但您至少需要 4 米才能注意到音量的任何降低,这与默认 Spatial Audio 设置相同。我想要一些可以在 1 米 = 1 内将音量降低到接近零的东西。 人做到了!!.. 太棒了。我发现的一件事是,如果您使用超出其精度(不接受)的数字,例如 referenceDistance = 0.01;它将重置为默认值(没有任何警告)并且它会起作用,但就像我之前所说的那样......而且你永远不知道实际出了什么问题。 是的 :/ 我认为这不是关于 PURPOSE 的文件.. 真的.. 我在山谷里有一些朋友以前与苹果合作过.. 他曾经告诉我大公司过去是如何利用的获得其他所有东西都无法获得的文档.. 这样他们就可以在任何人有时间和金钱赶上他们之前制作出最好的游戏 尝试使用代码看看声音体验如何,但遇到了一些麻烦。出现致命错误:打开 Optional 值时意外发现 nil。参考 myURL【参考方案2】:

如果以上答案似乎都不起作用,请尝试以下代码:

sceneView.audioEnvironmentNode.reverbParameters.enable = true

如果这些似乎都无法正常工作,或者如果您想获得最佳性能,那么有一个名为 level 的属性,您可以在其中设置代码的空间级别。

sceneView.audioEnvironmentNode.reverbParameters.level = 40

(reverbParameters 的级别范围在 -40 到 40 个参数之间)

【讨论】:

以上是关于ARKit – Spatial Audio 几乎不会随距离改变音量的主要内容,如果未能解决你的问题,请参考以下文章

为 ARKit 请求 3D 模型的指南

Easy Audio Mixer 2.0 for Mac 共享版 – 易用的音频混音编辑工具

ARKit从入门到精通-ARKit捕捉平地

ARKit 如何在没有跟踪时暂停视频

通过Swift设置ARKit方向

ARKit 初体验