Three.js进阶之音频处理与展示

news2025/6/6 21:18:03

引擎在对音频处理提供了丰富的接口,本文展示两个音频处理示例。

一、声音可视化

Three.js中的声音可视化是以视觉为核心,以音乐为载体,为音乐提供直观的视觉呈现。通过对音乐数据的分析并结合开发需求,能实现酷炫的视觉效果。在本节案例中,16个长方体跟随音乐的律动在y轴方向上进行缩放,效果如图12-13所示。

(1)加载音频文件,然后创建音频加载对象、音频监听对象和创建音频对象,接下来获取音乐数据,根据此数组长度创建长方体,然后进行画面的渲染,具体代码如下。

1      var file;                                               //文件对象
2      var fileUrl;                                            //文件链接
3      ......//此省略了初始化场景中相关变量的代码,读者可自行查看随书源代码
4       function fileChange() 
5         file=document.getElementById("importFile").files[0]; //获取文件
6         fileUrl=URL.createObjectURL(file);                    //创建文件链接
7         document.getElementById("WebGL-output").style.display="block";
                  //将渲染所用的div进行显示
8         document.getElementById("label1").style.display="none"; //隐藏打开文件的标签
9         addAudio();                                              //加载音频文件
10     }
11    ......//此处省略了初始化场景的相关方法,读者可自行查看随书源代码
12      function addAudio() {
13        var audioLoder=new THREE.AudioLoader();                //创建音频加载
14        var listener = new THREE.AudioListener();              //创建音频监听
15        var audio = new THREE.Audio( listener );               //创建音频对象
16        audioLoder.load(fileUrl, function (audioBuffer ) {     //加载音频
17             audio.setBuffer( audioBuffer );                    //设置音频数据
18             audio.setLoop( true );                             //音频循环
19             audio.play();                                       //音频播放
20        });
21        analyser = new THREE.AudioAnalyser( audio, fftSize ); //音频数据分析
22        misicDataArray=analyser.data;                          //指定音乐数组中的数据
23        for (var i=0; i<fftSize*0.5; i++){
24             tempGeometry[i]=new THREE.BoxGeometry( 12, misicDataArray[i]/4 ,12);
                      //创建长方体
25             material=new THREE.MeshPhongMaterial({color: getColor()});
                      //创建随机颜色的材质
26             mesh[i]=new THREE.Mesh(tempGeometry[i], material) ; //创建物体
27             mesh[i].position.x=20*i-160;                       //指定物体的 x坐标
28             mesh[i].castShadow=true;                           //接受阴影
29             mesh[i].rotation.y= Math.PI/4;                     //指定绕 y轴旋转的角度
30             scene.add(mesh[i]);                                //将物体添加进场景
31        }
32        renderScene();                                          //进行渲染
33     }

❑ 第1~10行的功能为获取音频文件,创建文件链接和加载音频文件。当我们打开音频文件的时候,会调用fileChange方法,获取音频文件并创建链接,然后将渲染用div显示,隐藏打开音频文件时的提示信息。
❑ 第12~31行的功能为创建音频加载对象,音频加载监听以及音频对象,然后加载音频并对音频对象进行数据设置和播放设置,对音频进行分析,
(2)介绍渲染场景的方法。在此方法中主要通过更新音乐数据来更新物体在y轴上的缩放比例以及请求绘制下一帧画面,具体的代码如下。

 1    function renderScene() {                           //渲染场景的方法
        2        analyser.getFrequencyData();                   //更新音乐数据
        3        misicDataArray=analyser.data;                  //更新音乐数据
        4        for (var i=0; i<fftSize*0.5; i++){          //更改物体在 y轴上的缩放比例
        5             if(misicDataArray[i]/4==0){                //如果数据大小为0
        6                 misicDataArray[i]=4; }                  //数据大小为4
        7             mesh[i].scale.y=misicDataArray[i]/4;      //更新物体 y轴的缩放比例
        8             mesh[i].position.y=0;                      //指定物体的 y坐标为0
        9        }
        10       renderer.render( scene, camera );              //渲染场景
        11       requestAnimationFrame(renderScene);            //请求重新绘制场景
        12   }

        在渲染场景的方法中,主要是通过更新音乐数据来更新物体在y轴上的缩放比例,从而实现物体随音乐律动来改变高度的功能。然后进行场景渲染,并请求重新绘制场景。

二、 声音与距离

        游戏音效是游戏中的重要组成部分,其最大功用就是烘托气氛、表达情感,给玩家营造出身临其境的游戏环境。Three.js引擎能够很好地处理游戏中的声音,并且能够根据摄像机位置与物体位置之间的距离来确定声音的大小。

         本案例中乒乓球运动后弹起的时候会发出声音。声音随着摄像机位置与乒乓球位置间距离的改变而改变,距离变小声音增大,距离变大声音减小,这真实地模拟出现实世界的情况。案例的具体实现过程。
(1)单击界面之后对象加载音频及创建监听,然后进行场景的初始化(包括初始化场景中的基本组件,向场景中添加物体和光照,添加鼠标控制以及添加窗口变化监听),最后隐藏提示信息标签,
具体实现代码如下:

        1        var flag=true;                                       //单击标志位
        2        var audioLoader;                                     //音频加载对象
        3        var listener;                                        //音频监听
        4        ......//此处省略了其他变量的声明,请读者自行查阅随书源代码
        5        document.addEventListener("mousedown", function (){ //窗口单击监听
        6             if(flag){                                        //如果可以进行单击
        7                 audioLoader = new THREE.AudioLoader();     //创建音频加载对象
        8                 listener = new THREE.AudioListener();      //创建音频监听对象
        9                 init();                                      //初始化界面
        10                 document.getElementById("tip").hidden=true; //隐藏提示信息
        11                 flag=false;
        12             }});
        13     function init() {                                     //初始化界面
        14        initScene();                                      //初始化场景的基本组件
        15             addMesh();                                        //添加物体
        16             addLight();                                       //添加光照
        17             addControls();                                    //添加鼠标控制
        18             document.getElementById("WebGL-output").appendChild(renderer.domElement);
        19             window.addEventListener( 'resize', onWindowResize, false ); //窗口变化监听
        20        }
        21        function initScene(){                                //初始化场景
        22             scene = new THREE.Scene();                       //新建场景
        23             renderer = new THREE.WebGLRenderer({ antialias: true } );
                      //新建渲染器并关闭默认抗锯齿
        24             renderer.setClearColor(new THREE.Color(0x000000));    //设置背景颜色
        25             renderer.setSize(window.innerWidth, window.innerHeight);
                      //设置渲染窗口的大小
        26             renderer.shadowMap.enable=true;                       //设置接受阴影
        27             renderer.shadowMap.type = THREE.PCFSoftShadowMap;    //设置阴影类型
        28             camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.inner
                      Height, 0.1, 1000);
        29             camera.position.z =20;                                //摄像机位置的 z坐标
        30             camera.position.y =15;                                //摄像机位置的 y坐标
        31             camera.add(listener);                                 //添加音频监听
        32             camera.lookAt(new THREE.Vector3());                   //摄像机观察目标点
        33        }

        ❑ 第1~12行中的代码声明了程序中的变量,包括音频加载对象、音频加载监听和单击标志位等,注册窗口单击监听。进入界面,单击当前窗口,触发单击事件。接下来创建音频加载对象和音频监听对象,并进行界面的初始化以及隐藏提示信息。
        ❑ 第13~20行的功能为初始化场景中的基本组件、添加物体,光照和鼠标控制,以及注册窗口变化监听并将渲染结果添加到网页元素中。其中添加光照和鼠标控制的代码与前面案例的相似,在此不再赘述。
        ❑ 第21~33行为初始化场景,创建摄像机、场景以及渲染器对象,设置摄像机的位置及观察目标的位置,并添加音频监听和设置阴影及阴影类型。在此方法中,最重要的就是给摄像机添加音频监听,这是模拟真实声音效果的前提。
        单击界面之后才能进入场景,这是为了应对Google Chrome浏览器禁止声音自动播放策略的,我们只需与网页进行交互,便可以播放声音。
(2)看一下添加物体及加载音频方法的核心部分,包括加载音频,创建位置音频对象,设置音频数据,设置音频音量的大小和向场景中添加乒乓球。此外还有渲染场景的方法,此方法主要控制小球的运动以及在小球弹起时播放声音,
具体代码如下:

 1    function addMesh(){                                          //添加物体及加载音频
        2        ......//此处省略了向场景中添加乒乓球台模型的代码,读者可自行查阅随书源代码
        3        audioLoader.load( 'music/ping_pong.mp3', function ( buffer ){  //加载音频
        4             var ballGeometry = new THREE.SphereGeometry(0.5,20,20);    //创建球体
        5             var ballMaterial = new THREE.MeshLambertMaterial({color:0xffffff});
                      //创建材质
        6             ball=new THREE.Mesh(ballGeometry, ballMaterial);             //创建网格对象
        7             ball.position.x = -10;                                       //球体的 x坐标
        8             ball.position.y = 8.2;                                       //球体的 y坐标
        9             ball.position.z = 0;                                         //球体的 z坐标
        10            ball.castShadow=true;                                        //球体投射阴影
        11             var audio = new THREE.PositionalAudio( listener );    //创建位置音频
        12             audio.setBuffer( buffer );                      //设置音频数据
        13             audio.setVolume(10);                            //设置音频的音量
        14             tempy=ball.position.y;                          //记录当前时刻球体的 y坐标
        15             ball.userData.flag=false;                       //自定义播放标志位
        16             ball.add( audio );                              //向球体添加音频
        17             scene.add(ball); });                             //向场景添加球体
        18        }
        19    function renderScene() {                                //渲染场景的方法
        20             requestAnimationFrame(renderScene);             //请求绘制下一帧画面

21          render();                                        //调用实际渲染场景的方法
  22        }
  23    function render() {                                      //实际渲染场景的方法
        24             temp+=0.03;                                      //增加球体运动角度
        25             tempy=ball.position.y;                          //记录当前时刻球体的 y坐标
        26             ball.position.y=8.2+4*Math.abs(Math.sin(temp)); //改变球体的 y坐标
        27             ball.position.x=10*Math.cos(temp);              //改变球体的 x坐标
        28             var audio = ball.children[ 0 ];                 //获取音频对象
    29             if(ball.position.y<tempy){                      //如果球体 y坐标小于记录的
                      球体 y坐标
        30                 ball.userData.flag=true; }                   //播放标志位为true
        31             else{ if(ball.userData.flag){                   //如果可以播放音频
        32                     audio.play();                           //播放音频
        33                     ball.userData.flag=false;               //播放标志位为false
        34                 }}
        35             renderer.render( scene, camera );               //进行场景渲染
        36        }

❑ 第3~18行的代码为加载音频,创建球体网格对象,设置球体的相关属性,创建位置音频对象,设置音频数据和向球体添加音频以及向场景中添加球体。通过向球体添加音频,可将音频对象和球体关联起来。通过改变播放标志位,可以控制音频播放。
❑ 第19~36行的代码为对场景进行渲染。在实际渲染场景的方法中,在当前球体的y坐标大于改变位置后球体的y坐标值时,物体处于下落状态,播放标志位为true。反之,物体处于上升状态,音频播放一次,播放标志位为false。这可避免重复播放。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2402126.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

兼容老设备!EtherNet/IP转DeviceNet网关解决储能产线通讯难题

在新能源行业飞速发展的当下&#xff0c;工业自动化水平的高低直接影响着企业的生产效率与产品质量。JH-EIP-DVN疆鸿智能ETHERNET/IP和DEVICENET作为工业领域常用的通信协议&#xff0c;它们之间的转换应用在新能源生产线上发挥着关键作用。本文重点探讨ETHERNETIP从站转DEVICE…

LabVIEW自感现象远程实验平台

LabVIEW开发自感现象远程实验平台&#xff0c;通过整合 NI数据采集设备、菲尼克斯&#xff08;Phoenix Contact&#xff09;继电器模块及罗技&#xff08;Logitech&#xff09;高清摄像头&#xff0c;实现远程数据采集、仪器控制与实时监控三大核心功能。平台突破传统实验装置局…

Python----目标检测(《YOLOv3:AnIncrementalImprovement》和YOLO-V3的原理与网络结构)

一、《YOLOv3:AnIncrementalImprovement》 1.1、基本信息 标题&#xff1a;YOLOv3: An Incremental Improvement 作者&#xff1a;Joseph Redmon, Ali Farhadi 机构&#xff1a;华盛顿大学&#xff08;University of Washington&#xff09; 发表时间&#xff1a;2018年 代…

算法篇 八大排序(冒泡 插入 选择 堆 希尔 快排 归并 计数)

目录 引言 1.冒泡排序 思路 代码实现 2.选择排序 思路 代码实现&#xff08;存在易错点&#xff09; 3.插入排序 思路 代码实现 4.希尔排序 思路 代码实现 5.堆排序 思路 代码实现 6.快速排序&#xff08;快排&#xff09; 一.三路划分 思路 代码实现 二.自…

音视频之视频压缩编码的基本原理

系列文章&#xff1a; 1、音视频之视频压缩技术及数字视频综述 2、音视频之视频压缩编码的基本原理 一、预测编码&#xff1a; 1、预测编码的基本概念&#xff1a; 预测法是最简单、实用的视频压缩编码方法&#xff0c;经过压缩编码后传输的并不是像素本身的取样值&#xff0…

IDEA 包分层显示设置

方法一&#xff08;用的IntelliJ IDEA 2024.1.4版本&#xff09;&#xff1a; 找到项目视图设置入口&#xff1a;在左侧Project&#xff08;项目&#xff09;面板的顶部&#xff0c;有个三个点...的按钮 &#xff0c;点击它。 进入树形外观配置&#xff1a;在弹出的菜单中&…

深度学习和神经网络 卷积神经网络CNN

1.什么是卷积神经网络 一种前馈神经网络&#xff1b;受生物学感受野的机制提出专门处理网格结构数据的深度学习模型 核心特点&#xff1a;通过卷积操作自动提取空间局部特征&#xff08;如纹理、边缘&#xff09;&#xff0c;显著降低参数量 2.CNN的三个结构特征 局部连接&a…

PlayWright | 初识微软出品的 WEB 应用自动化测试框架

Playwright是微软大厂背书的跨平台 WEB 应用自动化测试框架&#xff0c;支持多开发语言&#xff08;TypeScript、JavaScript、.Net、Python、Java&#xff09;及多浏览器&#xff08;Chromium、WebKit、Firefox&#xff09;&#xff0c;同时支持移动端测试。 安装 playwright …

Mac电脑_钥匙串操作选项变灰的情况下如何删除?

Mac电脑_钥匙串操作选项变灰的情况下如何删除&#xff1f; 这时候 可以使用相关的终端命令进行操作。 下面附加文章《Mac电脑_钥匙串操作的终端命令》。 《Mac电脑_钥匙串操作的终端命令》 &#xff08;来源&#xff1a;百度~百度AI 发布时间&#xff1a;2025-06&#xff09;…

2025前端微服务 - 无界 的实战应用

遇饮酒时须饮酒&#xff0c;得高歌处且高歌 文章目录 什么是前端微服务主流框架概述无界 - 腾讯乾坤 - 阿里Micro-app Vue3项目引用⑴. 项目依赖安装⑵. main.ts 文件配置⑶. 路由配置⑷. 页面设置 隐藏子应用菜单及顶部信息栏子应用样式冲突问题虚拟路由⑴. 路由⑵. 页面 跨域…

【设计模式-4.8】行为型——中介者模式

说明&#xff1a;本文介绍行为型设计模式之一的中介者模式 定义 中介者模式&#xff08;Mediator Pattern&#xff09;又叫作调节者模式或调停者模式。用一个中介对象封装一系列对象交互&#xff0c;中介者使各对象不需要显式地互相作用&#xff0c;从而使其耦合松散&#xf…

行列式的性质

1 行列式使用如下性质定义 1&#xff09;单位矩阵行列式值为 1&#xff0c; &#xff0c;对于任意单位矩阵均成立&#xff1b; 2&#xff09;当矩阵交换一行后&#xff0c;行列式值改变符号&#xff0c;如置换矩阵的行列式值为 &#xff08;根据行交换次数决定&#xff09;&…

联软NSPM自动化策略管理 助力上交所加速国产化替代提升运维效率

在金融行业核心基础设施国产化浪潮与网络安全强监管的双重背景下&#xff0c;上海证券交易所&#xff08;以下简称“上交所”&#xff09;积极拥抱变革&#xff0c;携手长期合作伙伴联软科技&#xff0c;成功部署了联软安全策略管理系统&#xff08;NSPM&#xff09;。该项目不…

Flask + ECharts+MYSQL物联网数字化大屏

基于Flask+ECharts的物联网数字化大屏系统,包含中国地图实时数据更新功能。这个系统模拟了物联网设备在全国范围内的分布和运行状况,并实时更新数据。 一、系统架构设计 技术栈 后端:Flask(轻量级路由+API支持) 前端:ECharts(地图+动态图表)、WebSocket(实时更新)…

数据库系统概论(十六)数据库安全性(安全标准,控制,视图机制,审计与数据加密)

数据库系统概论&#xff08;十六&#xff09;数据库安全性 前言一、数据库安全性1. 什么是数据库安全性&#xff1f;2. 为何会存在安全问题&#xff1f; 二、安全标准的发展1. 早期的“开拓者”&#xff1a;TCSEC标准2. 走向国际统一&#xff1a;CC标准3. TCSEC和CC标准有什么不…

vue3从入门到精通(基础+进阶+案例)

Vue是什么&#xff1f; 渐进式JavaScript框架&#xff0c;易学易用&#xff0c;性能出色&#xff0c;适用场景丰富的Web前端框架 为什么要学习Vue Vue是目前前端最火的框架之一 Vue是目前企业技术栈中要求的知识点 Vue可以提升开发体验 。。。 Vue简介 Vue(发音为/vju/,…

【Linux 学习计划】-- 系统中进程是如何调度的(内核进程调度队列)

目录 回顾进程优先级与进程调度的引入 内核runqueue图例 关于queue[140]前100个位置 | 实时进程与分时进程 遍历需要调度的进程与bitmap的引入 active、expired指针 结语 回顾进程优先级与进程调度的引入 在我们之前的学习中&#xff0c;我们是有学习过进程优先级这个概…

C#、VB.net——如何设置窗体应用程序的外边框不可拉伸

以Visual studio 2015为例&#xff0c;具体操作如下&#xff1a; 1、将窗体的“FormBorderStyle”属性值修改为“FixedSingle”&#xff1a; 2、点击“格式”——“锁定控件”&#xff1a; 这样生成的程序边框即可固定住&#xff0c;无法拉伸。

基于SpringBoot的房屋租赁系统的设计与实现(thymeleaf+MySQL)

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

Spring Boot统一功能处理深度解析

第一章&#xff1a;为什么需要统一功能处理&#xff1f; 想象你正在开发一个电商系统&#xff0c;包含用户管理、商品管理、订单管理等模块。每个模块都需要&#xff1a; 用户身份验证操作日志记录异常统一处理数据格式标准化 如果每个模块都单独实现这些功能&#xff1a; …