ARKit - Spatial Audio едва меняет громкость на расстоянии - PullRequest
1 голос
/ 22 сентября 2019

Я создал SCNNode и добавил к нему аудио.

Это монофонический звук.Все настроено правильно.

Он работает как Spatial Audio, это не проблема.

Проблема в том, что когда я подхожу ближе или далеко, он едва меняет громкость.Я знаю, что это изменится, если я уйду очень-очень далеко, но это не похоже на то, что 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 Ответ

1 голос
/ 22 сентября 2019

Обновлено .

Вот рабочий код для управления затуханием звука (работает в iOS и macOS):

import AVFoundation
import SceneKit
import ARKit

@available(iOS 13.0, *)
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

        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)

        mySource.load()

        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 .

В этом примере расстояниеaudioNode на расстоянии 1 метра от listener.

...