网络上用于游戏和 VR的音频!

图片由史蒂夫·哈维Unsplash上提供

提示、技巧和入门

音频是为 Web 上的游戏和虚拟现实体验添加重要主题和沉浸感的基本方式。添加音频并不难,还能为用户带来美妙的体验。Freesound 之类的资源可以让你更轻松地找到 Creative Commons 音效和音乐,从而帮助你积累相关经验。

我最近创建了一个轻松的 VR 体验,它利用 3D 空间音频来制作通过程序生成的音乐。本文涵盖了我在创建该音频时学到的一些东西。

XR锦鲤花园

一个美丽的 VR 花园,伴随着宁静的音乐。用耳机聆听以获得完整效果。

在网络播放音频最根本的办法就是通过HTML<audio> 元素。这能带来很多好处,例如能够在音频流入时播放。所以当你有很长的背景音乐曲目或环境声音循环时,它很适合你。

提示 1. 不要使用 MP3 来循环播放音频

这是播放一些循环背景声音的 HTML 代码:

<audio loop preload id="bgsound">
   <source src="assets/ambient/loop.ogg" type="audio/ogg" />
   <source src="assets/ambient/loop.mp3" type="audio/mpeg" />
</audio>

注意,音频元素接受多个 来自不同源的元素,例如<picture> 。MP3 具有相当好的压缩性能并且支持广泛,那为什么我们不能只使用 MP3 呢?

MP3 不应该用于循环音频,因为标题信息经常被误读为几毫秒没有声音。这对于 MP3 播放器来说还好,当播放下一首歌曲时,静音部分无法识别,但如果你循环播放,就会产生一些环境噪音,那么几毫秒的无声对听众来说非常刺耳。

OGG 格式也非常好,没有这个问题,但 Apple 设备不行。所以在这种情况下我们会返回使用 MP3。这虽然会产生更糟的效果,但也不失为一种办法。

使用 WAV 的替代方案虽不会有静音问题,但文件大小可能会大 10 倍!!使其成为一种不适合需要快速启动的 Web 格式。

Tip 2. 不要使用自动播放的音频;让用户打开音频。

不要使用自动播放音频,这可能看起来违反常规,因为如果我们向游戏添加音频,我们都希望默认打开音频。

从用户的角度来看,人们对他们是否想要自动播放音频感到非常困惑:

Jo 在 Twitter 上进行的一项民意调查,询问场景应该如何处理音频

最重要的是,某些浏览器(例如 Chrome)将完全阻止音频自动播放,直到用户事件触发音频播放为止。使用阻止自动播放音频的浏览器的最佳方法是使用利用 HTML、CSS 和一些 JavaScript 创建的音频切换开关:

1_8U1wq3VFKBHVBAdSGTifmg

切换按钮

HTML 是一个复选框和标签:

<input type="checkbox" id="canaudio" />
<label for="canaudio">Toggle Audio</label>

CSS 可用于隐藏标签文本,但如果声音被禁用,则显示音频静音符号,如果正在播放音频,则显示扬声器符号。

#canaudio {
  opacity: 0;
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}
label[for="canaudio"] {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  background: #0004;
  padding: 1.5rem;
  border-radius: 50%;
  border: 2px solid transparent;
  width: 3rem;
  height: 3rem;
  text-align: center;
  font-size: 0;
  color: white;
}
#canaudio:focus + label[for="canaudio"] {
  border: 2px solid white;
}
label[for="canaudio"]::before {
  content: "🔇\FE0E";
  font-size: 3rem;
  line-height: 3rem;
}
#canaudio:checked + label[for="canaudio"]::before {
  content: "🔊\FE0E";
}

然后我们侦听此复选框上的事件以开始播放音频元素:

// Ensure the #canaudio element is not checked as some browsers
// Will remember it's state
window.canaudio.checked = false;
window.canaudio.addEventListener('change', function () {
 if (this.checked) {
  window.bgsound.play();
  // initialise the spatial audio
  audioInit();
} else {
  window.bgsound.pause();
 }
});

提示 3. 添加网络中的空间音频并不像你想象中的那么难

网络长期以来一直通过WebAudio PannerNode支持 3D 音频,并且可以通过 Web Audio API 和定位音频的 panner 节点播放你的声音片段。

这非常有效,但可能达不到游戏开发者或发烧友的期望,但 Google 的一个名为Resonance Audio的库在简洁的 API 中提供了高质量的空间声音。

这就是我在最近的 VR 体验XRGarden 中使用的内容。它会在水面上随机点弹奏钢琴音符,并伴随着涟漪效应。

第一步是添加共振库脚本:

<script src="https://cdn.jsdelivr.net/npm/resonance-audio/build/resonance-audio.min.js"></script>

下一步是创建音频内容来播放,因为 Chrome 不允许在没有音频的情况下创建音频内容,我们必须点击事件,因此,我们将使用取消静音按钮来触发:

let hasInit = false;
function audioInit() {
  if (hasInit) return;
  hasInit = true;
  // Create an AudioContext
  const audioContext = new AudioContext();
  const resonanceAudioScene = new ResonanceAudio(audioContext);
  resonanceAudioScene.output.connect(audioContext.destination);
}

如果你的游戏或体验是在房间内进行的,你可以设置房间的大小和墙壁/地板/天花板的材料,以从每个表面获得准确的混响。具体可以在此处获取可用材料的完整列表:https : //resonance-audio.github.io/resonance-audio/reference/web/Utils.html#.ROOM_MATERIAL_COEFFICIENTS

const roomDimensions = {
  width: 3.1,
  height: 2.5,
  depth: 3.4,
};
const roomMaterials = {
  left: 'brick-bare',
  right: 'curtain-heavy',
  front: 'marble',
  back: 'glass-thin',
  // Room floor
  down: 'grass',
  // Room ceiling
  up: 'transparent',
};
resonanceAudioScene.setRoomProperties(roomDimensions, roomMaterials);

你还需要将听者位置与摄像机位置同步,以便根据用户的视角,判断声音来自正确的位置。

此代码示例适用于流行的 WebGL 库THREE.js,我们计算出相机方向,并使用它来设置 listenerOrientation,然后我们从相机位置设置 listenerPosition。

const tempForwardVector = new Vector3();
const tempUpVector = new Vector3();
function onRender() {
  tempForwardVector.set(0, 0, -1);
  tempForwardVector.applyQuaternion(camera.quaternion);
  tempUpVector.set(0, 1, 0);
  tempUpVector.applyQuaternion(camera.quaternion);
  resonanceAudioScene.setListenerOrientation(
    tempForwardVector.x,
    tempForwardVector.y,
    tempForwardVector.z,
    tempUpVector.x,
    tempUpVector.y,
    tempUpVector.z
  );
  resonanceAudioScene.setListenerPosition(
    camera.position.x,
    camera.position.y,
    camera.position.z
  );
};

每次渲染帧时都需要调用它,以保持听者位置和方向与相机位置同步。

要从某个位置播放声音,你首先需要加载它:

const audioElement = document.createElement("audio");
audioElement.src = filename;
const audioElementSource = audioContext.createMediaElementSource(
   audioElement
);
const source = resonanceAudioScene.createSource();
audioElementSource.connect(source.input);

当你准备好播放时, 你可以设置位置并开始播放:

source.setPosition(position.x, position.y, position.z);
audioElement.play();

这是我在演示中用于处理位置音频的代码,我创建了一个小类来处理所有不同音符的播放,这可使代码保持整洁:

AdaRoseCannon/xrgarden

通过在 GitHub 上创建帐户为 AdaRoseCannon/xrgarden 开发做出贡献。

github.com

我希望这可以帮助你通过音频打造引人入胜的网络体验。对于我的 VR 场景,我同时使用了通用背景音频和位置音频。另一种选择是让我所有的环境声音也都在空间上定位。我可以把鸟放在天空中,昆虫在头顶飞来飞去,从用户下方泼水,这将是改善体验的好方法。

原文作者 Ada Rose Cannon
原文链接 https://medium.com/samsung-internet-dev/audio-on-the-web-for-games-and-vr-efcd523a3d58

推荐阅读
相关专栏
音视频杂谈
158 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。