swift - 3D Positional Audio – 沿 Y 轴和 Z 轴移动 SCNAudioPlayer
问题描述
使用 SceneKit,我可以在 x 轴上从左向右移动 audioNode,但在 y 和 z 轴上移动时遇到问题。我戴着耳机,所以我可以听到双耳(3d 音频)效果。我也在 MacOS 上运行它。
我的测试代码如下。有人可以让我知道我错过了什么吗?我会很感激的!
import Cocoa
import SceneKit
class ViewController: NSViewController {
@IBOutlet weak var sceneView: SCNView!
override func viewDidLoad() {
super.viewDidLoad()
let path = Bundle.main.path(forResource: "Sounds/Test.mp3",
ofType: nil)
let url = URL(fileURLWithPath: path!)
let source = SCNAudioSource(url:url)!
source.loops = true
source.shouldStream = false
source.isPositional = true
source.load()
let player = SCNAudioPlayer(source: source)
let box = SCNBox(width: 100.0,
height: 100.0,
length: 100.0,
chamferRadius: 100.0)
let boxNode = SCNNode(geometry: box)
let audioNode = SCNNode()
boxNode.addChildNode(audioNode)
let scene = SCNScene()
scene.rootNode.addChildNode(boxNode)
sceneView.scene = scene
audioNode.addAudioPlayer(player)
let avm = player.audioNode as! AVAudioMixing
avm.volume = 1.0
let up = SCNAction.moveBy(x: 0, y: 100, z: 0, duration: 5)
let down = SCNAction.moveBy(x: 0, y: -100, z: 0, duration: 5)
let sequence = SCNAction.sequence([up, down])
let loop = SCNAction.repeatForever(sequence)
boxNode.runAction(loop)
// Do any additional setup after loading the view.
}
}
解决方案
更新。
您正在转换player.audioNode
toAVAudioMixing
协议:
let avm = player.audioNode as! AVAudioMixing
但不是它,你必须将它转换为一个类。代码如下所示:
let avm = player.audioNode as? AVAudioEnvironmentNode
任何符合
AVAudioMixing
协议的节点(例如,AVAudioPlayerNode
)都可以在此环境中充当源。环境具有隐含的listener
. 通过控制听者的位置和方向,应用程序控制用户体验虚拟世界的方式。该节点还定义了距离衰减和混响的属性,有助于表征环境。
并考虑到!
只有与环境节点具有单声道连接格式的输入才会被空间化。
If the input is stereo, the audio is passed through without being spatialized
. 不支持具有两个以上通道的连接格式的输入。
而且,当然,您需要实现AVAudio3DMixing协议。
这是一个工作代码:
import SceneKit
import AVFoundation
class ViewController: NSViewController, AVAudio3DMixing {
// YOU NEED MONO AUDIO !!!
var renderingAlgorithm = AVAudio3DMixingRenderingAlgorithm.sphericalHead
var rate: Float = 0.0
var reverbBlend: Float = 0.5
var obstruction: Float = -100.0
var occlusion: Float = -100.0
var position: AVAudio3DPoint = AVAudio3DPoint(x: 0, y: 0, z: -100)
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene()
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.camera?.zFar = 200
cameraNode.position = SCNVector3(x: 0, y: 0, z: 40)
scene.rootNode.addChildNode(cameraNode)
let sceneView = self.view as! SCNView
sceneView.scene = scene
sceneView.backgroundColor = NSColor.black
sceneView.autoenablesDefaultLighting = true
let path = Bundle.main.path(forResource: "Test_Mono", ofType: "mp3")
let url = URL(fileURLWithPath: path!)
let source = SCNAudioSource(url: url)!
source.loops = true
source.shouldStream = false // MUST BE FALSE
source.isPositional = true
source.load()
let player = SCNAudioPlayer(source: source)
let audioNode = SCNNode()
let box = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0.2)
let boxNode = SCNNode(geometry: box)
boxNode.addChildNode(audioNode)
scene.rootNode.addChildNode(boxNode)
audioNode.addAudioPlayer(player)
let avm = player.audioNode as? AVAudioEnvironmentNode
avm?.reverbBlend = reverbBlend
avm?.renderingAlgorithm = renderingAlgorithm
avm?.occlusion = occlusion
avm?.obstruction = obstruction
let up = SCNAction.moveBy(x: 0, y: 0, z: 70, duration: 5)
let down = SCNAction.moveBy(x: 0, y: 0, z: -70 , duration: 5)
let sequence = SCNAction.sequence([up, down])
let loop = SCNAction.repeatForever(sequence)
boxNode.runAction(loop)
avm?.position = AVAudio3DPoint(
x: Float(boxNode.position.x),
y: Float(boxNode.position.y),
z: Float(boxNode.position.z))
}
}
推荐阅读
- java - 获取 @Autowired 的 ClassCastException
- excel - 复制不带 0 的数据范围或使用公式的空单元格
- amazon-web-services - 无法使用 ansible 访问 aws 中的特定 kms 密钥
- java - 当 JAVA_HOME 指向 JRE 时,Javafx Shaded Jar 不工作
- python - 从 Google Drive 加载 .h5 模型时出错
- sql - dbeaver 内联 where 查询
- c# - 读取和替换存储在 C# 中不同项目位置的 web.config 中特定标记的值
- c# - 将参数从视图传递到控制器
- javascript - HTML CSS JavaScript - 自动高度 RWD
- android - 致命信号 4 (SIGILL),代码 1 (ILL_ILLOPC),tid 11821 (Chrome_InProcRe) 中的故障地址 0xc654f6c6,android xwalk webview 中的 pid 11615 (com.OffZone)