【iOS ARKit】播放3D音频

2024-03-26 05:52
文章标签 音频 3d ios 播放 arkit

本文主要是介绍【iOS ARKit】播放3D音频,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

3D音频

       在前面系列中,我们了解如何定位追踪用户(实际是定位用户的移动设备)的位置与方向,然后通过摄像机的投影矩阵将虚拟物体投影到用户移动设备屏幕。如果用户移动了,则通过VIO 和 IMU更新用户的位置与方向信息,更新投影矩阵,这样就可以把虚拟物体固定在空间的某点上(这个点就是锚点),从而达到以假乱真的视觉体验。

      3D音效处理的目的是让用户进一步相信AR 应用虚拟生成的数字世界是真实的,营造沉浸的AR体验。事实上,3D音效在电影、电视、电子游戏中被广泛应用,但在AR 场景中,3D声音的处理有其特别之处,类似于电影采用的技术并不能很好地解决 AR中3D音效的问题。

     在电影院中,观众的位置是固定的,因此可以通过在影院的四周都加装上音响设备,通过设计不同位置音响设备上声音的大小和延迟,就能给观众营造逼真的3D 声音效果。经过大量的研究与努力,人们根据人耳的结构与声音的传播特性开发出了很多技术,可以只用两个音响或者耳机就能模拟出3D音效,这种技术叫双耳声(Binaural Sound),它的技术原理如图11-2所示。

在图11-2中,从声源发出来的声音会直接传播到左耳和右耳,但因为左耳离声源近,所以声音会先到达左耳再到达右耳,由于在传播过程中的衰减,左耳听到的声音要比右耳大,这是直接的声音信号,大脑会接收到两只耳朵传过来的信号。同时,从声源发出的声音也会被周围的物体反射,这些反射与直接信号相比有一定的延迟并且音量更小,这些是间接的声音信号。大脑会采集到直接信号与所有的间接信号并比较从左耳与右耳采集的信号,经过分析计算,从而达到定位声源的效果。在了解大脑的工作模式后,就可以通过算法控制两个音响或者耳机的音量与延迟来达到模拟3D声源的效果,让大脑产生出虚拟的3D声场效果。

3D声场原理

      3D声场,也称为三维音频、虚拟3D音频、双耳音频等,它是根据人耳对声音信号的感知特性,使用信号处理的方法对到达两耳的声音信号进行模拟,以重建复杂的空间声场。

      通俗地说就是把耳朵以外的世界看作一个系统,对任意一个声音源,在耳膜处接收到信号后,三维声场重建就是把两个耳朵接收到的声音尽可能准确地模拟出来,让人产生听到三维音频的感觉。

      如前所述,当人耳在接收到声源发出的声音时,人的耳廓、耳道、头盖骨、肩部等对声波的折射、绕射和衍射及鼓膜接收到的信息会被大脑所接收,大脑通过经验对声音的方位进行判断。与大脑工作原理类似,在计算机中通过信号处理的数学方法,构建头部相关传输函数(HeadRelated Transfer Functions, HRTF),根据多组的滤波器计算人耳接收到的声源的“位置信息”。

    目前3D声场重建技术口冬比校成戴们不时加送之上术都假设用户是静止的(或者说与用户位置无关),而在 AR应用中,情况却有很大不同,AR应用的用户是随时移动的,这意味着用户周围的3D声音也需要调整,这一特殊情况导致目前的3D声场重建技术在AR应用时失效。

RealityKit 中的 3D 音效

      ARKit 通过世界跟踪功能定位声源位置,然后根据用户与声源的相对位置和方向自动混音,将3D音频技术带人 AR中。在 AR场景中放置一个声源,当用户接近或远离时,声音音量大小会自动增加或减弱,当用户围绕声源旋转时,声音也会呈现沉浸式的3D效果。在 RealityKit 中,使用3D音效的典型代码如代码如下所示,稍后我们将对代码进行详细解析。

//
//  Audio3DView.swift
//  ARKitDeamo
//
//  Created by zhaoquan du on 2024/3/22.
//import SwiftUI
import ARKit
import RealityKit
import Combinestruct Audio3DView: View {var body: some View {Audio3DViewContainer().navigationTitle("3D音频").edgesIgnoringSafeArea(.all)}
}struct Audio3DViewContainer:UIViewRepresentable {func makeUIView(context: Context) -> some ARView {let arView = ARView(frame: .zero)let config = ARWorldTrackingConfiguration()config.planeDetection = .horizontal//createPlane(arView: arView)arView.session.run(config)arView.createAudioPlane()return arView}func updateUIView(_ uiView: UIViewType, context: Context) {}static var audioEvent : Cancellable!func createPlane(arView:ARView){let planAnchor = AnchorEntity(plane: .horizontal)let boxMesh = MeshResource.generateBox(size: 0.2)let boxMaterial = SimpleMaterial(color: .red, isMetallic: true)let boxEntity = ModelEntity(mesh: boxMesh, materials: [boxMaterial])guard  let audio = try? AudioFileResource.load(named: "fox.mp3",in: .main, inputMode: .spatial,loadingStrategy: .preload,shouldLoop: false) else {return}let audioControler = boxEntity.prepareAudio(audio)audioControler.play()boxEntity.generateCollisionShapes(recursive: false)planAnchor.addChild(boxEntity)arView.scene.addAnchor(planAnchor)arView.installGestures(for: boxEntity)Audio3DViewContainer.audioEvent = arView.scene.subscribe(to: AudioEvents.PlaybackCompleted.self) { event inprint("音频播放完毕")}}
}
var audioEvent : Cancellable!
extension ARView{func createAudioPlane(){do{let planeAnchor = AnchorEntity(plane:.horizontal)let boxMesh = MeshResource.generateBox(size: 0.2)let boxMaterial = SimpleMaterial(color:.red,isMetallic: true)let boxEntity = ModelEntity(mesh:boxMesh,materials:[boxMaterial])let audio = try AudioFileResource.load(named:"fox.mp3",in:.main,inputMode: .spatial,loadingStrategy: .preload,shouldLoop: false)boxEntity.playAudio(audio)let audioController = boxEntity.prepareAudio(audio)audioController.play()boxEntity.generateCollisionShapes(recursive: false)planeAnchor.addChild(boxEntity)self.scene.addAnchor(planeAnchor)self.installGestures(.all,for:boxEntity)audioEvent = self.scene.subscribe(to: AudioEvents.PlaybackCompleted.self){ event inprint("音频播放完毕")}}catch{print("Error Loading audio file")}}
}#Preview {Audio3DView()
}

     编译运行 AR 应用,使用耳机(注意耳机上的左右耳塞勿戴反,一般会标有I.和 R字样)或者双通道音响体验3D音效,在检测到的平面放置虛拟立方体对象后,移动手机或者旋转手机朝向,体验在 AR场景中声源定位的效果。

从代码清单 11-3中我们可以看出,在 RealityKit 中使用3D音频分为3步:

(1) 加载音频。

(2)设置音频播放参数。

(3)将音频放置到 AR 场景中并播放。

下面我们针对这3个步骤进行详细学习。在 RealityKit 中使用音频,必须将音频加载为 AudioResource(或者其子类 AudioFileResource)类型对象才能正确播放,通常使用 AudioFileResource 类将音频从文件系统或者 URL 加载到内存中,该类有4个方法,可以同步/异步从文件/URL 中加载音频,如表11-2所示。

表 11-2 AudioFileResource 类加载音频方法

方法

描述

load (named: String, in: Bundle?,inputMode: AudioResource. InputMode,loadingStrategy: AudioFileResource. LoadingStrategy,shouldLoop: Bool)—>

AudioFileResource

同步从程序 Bundle 中加载音频

loadAsync(named: String,in: Bundle?, inputMode: AudioResource. InputMode,loadingStrategy: AudioFileResource. LoadingStrategy,shouldLoop: Bool)—>

LoadRequest < AudioFileResource >

异步从程序 Bundle 中加载音频

load ( contentsOf: URL, withName: String?, inputMode: AudioResource.

InputMode,loadingStrategy: AudioFileResource. LoadingStrategy,shouldLoop:

Bool) -> AudioFileResource

同步从 URL 中加载音频

load Async(contentsOf: URL, withName: String?, inputMode: AudioResource.

InputMode,loadingStrategy: AudioFileResource. LoadingStrategy,shouldLoop:

Bool) -> LoadRequest < AudioFileResource >

异步从 URL 中加载音频

       在 RealityKit 中加载音频与加载模型一样,每一种同步加载方法都有对应的异步加载方法。加载方法中的参数因加载方法不同而不同,基本的参数及其意义如表11-3所示。

表11-3 加载音频方法中各参数的意义

描述

方法

named

从 Bundle 中加载时文件路径与名称

contentsOf

从 URL 中加载时的 URL 地址

withName

从 URL 中加载时的音频名称

in

从程序 Bundle 中加载时音频所在 Bundle 名称

shouldLoop

布尔值,是否循环播放

loadingStrategy

AudioFileResource. LoadingStrategy 枚举类型,指定加载音频时的策略,共有两个枚举值:preload

(预加载音频,在使用之前将音频加载到内存中)、stream(流媒体编码,边加载边播放)。通常在使用时,preload 适合短小、内存占用少,播放频度高的音频,而 stream适合较长、播放频度低的音频

inputMode

AudioResource. InputMode 枚举类型,指定3D音频类型,共有3个枚举值:nonSpatial(不使用3D音效)、spatial(使用空间音效)、ambient(环境音效,声音不会随距离发生音量变化,但声音可以反映方向变化,如用户围绕声源转动时,音效会发生变化)

      在加载音频完成后,可以通过实体对象的 prepareAudio(_:)方法获取一个 AudioPlaybackController 类型的音频控制器,利用该控制器可以使用其 play()、pause()、stop()方法控制音频的播放,可以通过isPlaying 属性获取音频的播放状态,还可以设置音频的播放增益(gain)、速度(speed)、混音(reverb SendL.evel),及衰減(fade()方法)和音频播放完后的回调(completionHandler),可以满足音频使用的各类个性化需求。

     通常在 AR中使用3D,音频,需要将音频绑定到实体对象(Entity)上,当实体对象放置在场景中时,实体对象所在的空间位置即为声源位置,RealityKit 会根据用户设备所在空间位置与声源位置进行3D音效模拟,营造沉浸式的声场效果。

     利用 AudioPlaybackController 类可以很方便地控制音频的播放,而且可以重复地进行暂停、播放等操作,但如果只需要一次性地播放,也可以不使用该类,而直接使用boxEntity. playAudio(audio),这种方法更简洁,当音频播放完后即结束,特别适合3D物体音效模拟,如子弹击中柽物时的音频播放。

     在使用 AudioPlaybackController 类控制音频播放时,可以通过其 completionHandler 属性设置音频播放完后的回调函数。除此之外,也可以通过订阅 AudioEvents 事件进行后续处理,目前,音频只有一个AudioEvents. PlaybackCompleted 事件,即音频播放完毕事件。

     在订阅 AudioEvents事件时有两点需要注意,一是保存事件订阅的引用,不然无法捕获事件,具体可参阅第2章相关内容:三是只有当 shouldLoop 设置为 false(即不循环播放)时,才会触发 AudioEvents.PlaybackCompleted 事件。

这篇关于【iOS ARKit】播放3D音频的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/847479

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

SAM2POINT:以zero-shot且快速的方式将任何 3D 视频分割为视频

摘要 我们介绍 SAM2POINT,这是一种采用 Segment Anything Model 2 (SAM 2) 进行零样本和快速 3D 分割的初步探索。 SAM2POINT 将任何 3D 数据解释为一系列多向视频,并利用 SAM 2 进行 3D 空间分割,无需进一步训练或 2D-3D 投影。 我们的框架支持各种提示类型,包括 3D 点、框和掩模,并且可以泛化到不同的场景,例如 3D 对象、室

一款支持同一个屏幕界面同时播放多个视频的视频播放软件

GridPlayer 是一款基于 VLC 的免费开源跨平台多视频同步播放工具,支持在一块屏幕上同时播放多个视频。其主要功能包括: 多视频播放:用户可以在一个窗口中同时播放任意数量的视频,数量仅受硬件性能限制。支持多种格式和流媒体:GridPlayer 支持所有由 VLC 支持的视频格式以及流媒体 URL(如 m3u8 链接)。自定义网格布局:用户可以配置播放器的网格布局,以适应不同的观看需求。硬

模具要不要建设3D打印中心

随着3D打印技术的日益成熟与广泛应用,模具企业迎来了自建3D打印中心的热潮。这一举措不仅为企业带来了前所未有的发展机遇,同时也伴随着一系列需要克服的挑战,如何看待企业引进增材制造,小编为您全面分析。 机遇篇: 加速产品创新:3D打印技术如同一把钥匙,为模具企业解锁了快速迭代产品设计的可能。企业能够迅速将创意转化为实体模型,缩短产品从设计到市场的周期,抢占市场先机。 强化定制化服务:面

UniApp实现漂亮的音乐歌词滚动播放效果

在现代的音乐播放应用中,歌词的展示和滚动播放已经成为了一个非常常见的功能。今天,我们将通过UniApp来实现一个漂亮的歌词滚动播放功能。我们将使用UniApp提供的组件和API来完成这个任务。 页面结构 在页面的模板部分,我们需要创建一个音频播放器和歌词展示区域。使用<scroll-view>组件来实现歌词的滚动效果。 <template><view class="audio-co