java虚拟机堆栈帧
by Berrak Nil
由Berrak Nil
A-Frame is a web framework for building virtual reality experiences. Ever since its introduction in late 2015, it quickly became a favorite among artists and creators of all backgrounds who want to experiment with WebXR.
A-Frame是用于构建虚拟现实体验的Web框架。 自2015年末推出以来,它很快就成为了想尝试WebXR的各种背景的艺术家和创作者的最爱 。
I am a creative coder with a background in audio. Diving into the sonic possibilities of this new platform was a very exciting and rewarding journey. Most of my A-Frame experience was confined to standard desktop and smartphone environments and not VR. I am sharing my findings. I want to create a sort of an unofficial manual on how to implement, use and create audio in A-Frame. In this first part, we will take a look at how to use A-Frame’s out of the box audio capabilities.
我是一位具有音频背景的创意编码员。 深入了解这个新平台的声音是非常激动人心的旅程。 我大部分的A-Frame体验都限于标准台式机和智能手机环境,而不是VR。 我正在分享我的发现。 我想创建一种关于如何在A-Frame中实现,使用和创建音频的非官方手册。 在第一部分中,我们将看一下如何使用A-Frame的开箱即用音频功能。
Prerequisites
先决条件
This write-up assumes you have some experience with A-Frame. You don’t have to be an expert on it but knowing how the basics work will make following this tutorial easier. If you haven’t had a chance to check it out yet, you can start here.
本文假设您对A-Frame有一定的经验。 您不必一定是专家,但是了解基础知识如何工作将使本教程的学习变得更加容易。 如果您还没有机会进行检查,可以从此处开始。
A-Frame is a framework based on Three.js. The sound component it provides is a wrapper around the Three.js positional audio component (or non-positional depending on what we choose, but more on that later), which uses the Web Audio API.
A-Frame是一个基于Three.js的框架。 它提供的声音组件是Three.js 位置音频组件 (或根据我们选择的内容为非位置组件 ,但以后会更多)的包装 ,该组件使用Web Audio API 。
This means we get things like positional audio, volume control and audio playback out of the box, as soon as we use an A-Frame sound component.
这意味着,一旦使用A帧声音组件,我们便可以立即获得诸如定位音频,音量控制和音频回放之类的功能。
But how do we add this component to our scenes and provide audio feedback to user interactions and/or create a soundscape?
但是,如何将这个组件添加到场景中,并为用户交互提供音频反馈和/或创建音景 ?
To demonstrate this I created an A-Frame project from scratch. It is based on user interactions with a desktop computer. (i.e. to use with a mouse and a keyboard). The principles should transfer to other types of controls for the most part.
为了证明这一点,我从头开始创建了一个A-Frame项目。 它基于用户与台式计算机的交互。 (即与鼠标和键盘一起使用)。 原则应在大多数情况下转移到其他类型的控件。
You have the option to either start with a fresh copy of the project [Glitch][GitHub] — with no sounds attached to it — and follow along while implementing the provided sounds yourself. Or you can check out the finished version [Glitch][GitHub] and follow along by reading the code.
您可以选择从项目[ Glitch ] [ GitHub ]的新副本开始(不附带任何声音),然后继续自己实现提供的声音。 或者,您可以签出完成的版本[ Glitch ] [ GitHub ],然后阅读代码。
Before we start the audio implementation process, let’s take a look at our scene. We have several 3D models here (courtesy of Google Poly). Our kitchen is a complete model by itself. Items like the espresso machine, radio, the frying pan and the egg on top of it are separate models that are added to the scene on top of the kitchen.
在开始音频实现过程之前,让我们看一下我们的场景。 这里有几个3D模型(由Google Poly提供 )。 我们的厨房本身就是一个完整的模型。 浓缩咖啡机 , 收音机 , 平底锅和煎蛋上面的物品是单独的模型,已添加到厨房顶部。
Now let’s see the methods we can use to add sounds to this scene.
现在,让我们看看可用于向该场景添加声音的方法。
User interaction sounds are usually one-shot sounds. This means they are short samples that play once when triggered. They are not continuous or looped like environment audio or music. Which means we need to find a way to put an audio file on our scene and then trigger it when our user interacts with that object. (e.g. clicks the mouse button, hovers over it etc.).
用户交互声音通常是单发声音。 这意味着它们是简短的样本,被触发后仅播放一次。 它们不像环境音频或音乐那样连续或循环。 这意味着我们需要找到一种方法将音频文件放到场景中,然后在用户与该对象交互时触发它。 (例如,单击鼠标按钮,将鼠标悬停在其上等)。
To trigger a sound on user interaction, we can:
要触发用户交互的声音,我们可以:
Put a sound on a primitive, like a box geometry
将声音放到基本形状上,例如盒子的几何形状
So let’s go through our options one by one and see the use cases for each one.
因此,让我们逐一浏览选项,并查看每个选项的用例。
Who doesn’t want to start the day with a fresh cup of espresso? (If that’s not you, feel free to grab a tea model from here and go with that instead.)
谁不想以一杯新鲜的咖啡开始新的一天? (如果不是您,请随时从这里获取茶模型并改为使用它。)
I would say half of the satisfaction of having that caffeine boost is the sound our beloved espresso machine makes. To make sure our scene provides that aural feedback, we implement a sound that will respond to user interaction.
我想说,提高咖啡因的满意度的一半是我们心爱的意式浓缩咖啡机发出的声音。 为了确保我们的场景提供听觉反馈,我们实现了一种声音,该声音将响应用户交互。
First let’s take a look at how our espresso machine works under the hood
首先让我们看一下我们的意式浓缩咖啡机如何在引擎盖下工作
We start by loading our model with the A-Frame loader. Then we set the position, rotation and scale of the model within the scene, by using the named properties.
我们首先使用A帧加载器加载模型。 然后,我们使用命名的属性在场景中设置模型的位置,旋转和比例。
Our model is referenced by the id “#coffeeMaker”, instead of the relative path of the file. All the models for this project is registered in the Asset Management System beforehand.
我们的模型由ID“ #coffeeMaker”引用,而不是文件的相对路径。 该项目的所有模型都已预先在资产管理系统中注册。
Easiest way to add a sound to our espresso machine is by adding the sound component to it by using it as an HTML attribute on the object.
向我们的意式浓缩咖啡机添加声音的最简单方法是,通过将声音组件用作对象HTML属性,向其中添加声音组件。
We reference our sound by using the asset management system again, and setting the volume of it to 1. This means it will be heard at 100%. Now for the most important part, we set the “on” property of the sound to the “click” value. This means when a user clicks on this object, the sound will be triggered.
我们通过再次使用资产管理系统并将声音的音量设置为1来引用声音。这意味着可以100%听到声音。 现在,对于最重要的部分,我们将声音的“ on”属性设置为“ click”值。 这意味着当用户单击该对象时,将触发声音。
We don’t use the autoplay or loop properties here as this is a one-shot that depends on user interaction. We leave the positional property as “on” by default. Otherwise we would hear the sound at the same volume level at all times, no matter how distant we are from the object. Sound wouldn’t have any panning and would always play exactly where we are, instead of to the left, right or behind us depending on our position relative to the object.
我们此处不使用自动播放或循环属性,因为这是一键式操作,取决于用户的交互作用。 默认情况下,我们将positional属性保留为“ on”。 否则,无论我们与物体有多远,我们都将始终听到相同音量的声音。 声音不会有任何平移,并且会始终精确地播放我们所处的位置,而不是根据我们相对于对象的位置而向左,向右或向后播放。
NOTE: Positional sounds like these should be rendered mono to make the spatial cognition of the sound easier, while background music or audio ambiances that are not positional preferably should be rendered stereo.
注意:应该将此类位置声音呈现为单声道,以使声音的空间认知更容易,而位置不佳的背景音乐或音频环境最好呈现为立体声。
Now it’s your turn, go ahead and implement the provided frying egg sound to the egg model, which is placed on top of the frying pan. For a challenge, you can also try to use a few additional sound properties of your choosing. Go around the scene after putting the egg sound in place and test your implementation to see if it sounds realistic (or unrealistic if that’s what you are going for!)
现在轮到您了,继续并将提供的煎蛋声音应用于放置在煎锅顶部的蛋模型。 对于挑战,您还可以尝试使用您选择的一些其他声音属性 。 将鸡蛋声音放到适当的地方后,到现场四处走走,并测试您的实现,看它是否听起来逼真(如果那是您想要的,则不现实!)
Did you do it?
你做了吗?
Great!
大!
Your code for the egg model now should look approximately like this (with your desired properties and values)
现在,您的egg模型代码应大致如下所示(具有所需的属性和值)
So we can add our sounds to the models by simply adding them as an HTML attribute. What if we want to put a sound to an object that is already part of a bigger model and not a separate entity by itself?
因此,我们可以通过简单地将声音添加为HTML属性来将声音添加到模型中。 如果我们想对已经是更大模型的一部分而不是单独实体的对象发出声音该怎么办?
Let’s say we want to add a sound to the red bottle on the right, which should make it sound like we are picking it up when we click on it.
假设我们要在右侧的红色瓶子中添加声音,这听起来像是我们在单击它时将其拾起。
If we put the sound on the kitchen model like we did with the smaller models, it would mean that the sound would trigger no matter where we clicked on the model itself, instead of only on the bottle like we want.
如果像在较小的模型上那样在厨房模型上放置声音,则意味着无论在模型本身上单击什么,声音都将触发,而不是像我们想要的那样仅在瓶子上触发。
We can solve this problem by using a geometry which we can click on, aligning it to where the bottle is, and adding the sound property to it.
我们可以通过使用可以单击的几何形状来解决此问题,将其与瓶子的位置对齐,然后向其中添加声音属性。
For the next steps I highly recommend that you start creating and positioning objects inside your scene right in the browser by using the A-Frame Inspector. You can then copy and use this code instead of guesswork as to where your object should be positioned.
对于后续步骤,我强烈建议您使用A-Frame检查器在浏览器中立即在场景内创建和定位对象。 然后,您可以复制并使用此代码,而不用猜测要放置对象的位置。
Let’s start by creating a geometry primitive on our scene, a cylinder should work well given our bottle’s shape.
让我们从在场景中创建几何图元开始,考虑到瓶子的形状,圆柱体应该可以很好地工作。
Now scale and position this cylinder by using the A-Frame inspector. It can cover our bottle and respond to user interaction on the correct spot.
现在,使用A型框架检查器缩放并定位此圆柱体。 它可以覆盖我们的瓶子,并在正确的位置响应用户交互。
NOTE: If you add this geometry inside the model, it would enable you to move or rotate the parent model and preserve the correct position of everything inside.
注意:如果在模型内部添加此几何图形,则可以移动或旋转父模型并保留内部所有对象的正确位置。
You can paste the code you copied from the inspector and just move the scale, position and rotation values inside the <a-cylinder>.
您可以粘贴从检查器复制的代码,然后仅在<a-cylinder>内移动比例,位置和旋转值。
Make sure to bring down the opacity of the material to 0, so our bottle can stay visible inside the cylinder geometry. As a final step, add the provided bottle sound to the object, like you did before with the espresso machine and the egg.
确保将材质的不透明度降低到0,这样我们的瓶子就可以在圆柱体几何体内保持可见。 最后,像之前使用义式咖啡机和鸡蛋一样,将提供的瓶子声音添加到对象中。
Now your cylinder code should look like this…
现在您的圆柱体代码应如下所示……
…and respond to user interaction correctly.
…并正确响应用户交互。
<a-sound> is a primitive wrapper around the A-Frame sound component and allows us to use audio without attaching it to anything else on the scene. However if we want to trigger this sound on interaction, we still need a type of geometry which will allow us to interact with this object.
<a-sou nd>是围绕A-Frame声音组件的原始包装,它使我们能够使用音频而不将其附加到场景中的任何其他物体上。 但是,如果我们想在交互时触发这种声音,我们仍然需要一种允许我们与该对象交互的几何类型。
We can put this geometry on anywhere else on the scene. (think of a user interface menu button which will trigger a non-positional sound). Or we can put it directly on to <a-sound> and then position it on top of the object we want to hear audio feedback from.
我们可以将此几何图形放置在场景中的其他任何位置。 (以用户界面菜单按钮为例,它将触发非定位声音)。 或者,我们可以将其直接放在<a-sound>上,然后将其放置在我们想听到音频反馈的对象上。
Which means to add a sound to our toaster, we can do the reverse of what we just did and create an <a-sound> component and attach a clickable geometry to it.
这意味着要向我们的烤面包机添加声音,我们可以做与我们刚才相反的操作,并创建一个<a-sound>组件并将一个可单击的几何体附加到该组件。
We saw a couple of the ways we can use to implement sounds that respond to user interactions. But what about sounds that don’t require the user to do anything to play? These are sounds that go through the scene from beginning to end, to create atmosphere, mood, a sense of place?
我们看到了可用于实现响应用户交互的声音的几种方法。 但是,不需要用户做任何演奏的声音又如何呢? 这些声音从头到尾贯穿整个场景,从而营造出氛围,氛围和地方感吗?
If we take a look at our kitchen, we can see that there is a big fridge to the left, which is dead silent right now. Not to mention, whether we are consciously aware of it or not, almost all the environments we occupy (unless they are an anechoic chamber) have something called a presence or a room tone.
如果我们看一下厨房,我们可以看到左边有一台大冰箱,现在冰箱已经安静了。 更不用说,无论我们是否有意识地意识到它,我们所占据的几乎所有环境(除非它们是消声室 )都具有某种存在感或房间音调 。
Electric hums, machinery, air conditioning units and alike create the room tone with or without us adding on top of it acoustically. So, to reflect that, our choice should be an ongoing. In this case a looping sound which is present throughout our scene.
电动嗡嗡声,机械设备,空调装置等都可以在我们添加或不添加声音的情况下营造出房间的音调。 因此,为了反映这一点,我们的选择应该是一个持续的过程。 在这种情况下,整个场景中都会出现循环声音。
NOTE: .mp3 format by its nature does not loop seamlessly in most platforms, there’s always a very short gap between loops which breaks the audio consistency, and therefore for looping sounds other formats like .wav or .ogg should be used.
注意:.mp3格式本质上不能在大多数平台上无缝循环,因此循环之间总是存在很短的间隔,这会破坏音频的一致性,因此,要循环播放声音,应使用.wav或.ogg之类的其他格式。
Now let’s add the provided room tone to our scene. We have several options depending on what type of A-Frame project we are working on. If we have only one room-as is the case here-we can put our room tone directly to our <a-scene>. Or if we have several rooms in our scene with different characteristics, we can put the room tone in to a plane geometry which could act as the ground. Or in an <a-sound> object which we can put in the center of the room. In all cases we have to make sure our room tone is not positional, as opposed to all the other sounds we used previously on this project.
现在,将提供的房间色调添加到场景中。 根据我们正在处理的A-Frame项目类型,我们有几种选择。 如果我们只有一个房间(如这里的情况),则可以将房间音调直接添加到我们的<a-scene>中。 或者,如果场景中有多个具有不同特征的房间,则可以将房间色调放到可以用作地面的平面几何形状中。 或者在我们可以放置在房间中央的<a-sound>对象中。 在所有情况下,我们都必须确保房间的声音与我们之前在该项目中使用的所有其他声音不同,并且位置不正确。
Given that we are only working with a single room/environment in here, we can put our room tone directly into the scene itself. We set the positional property to false, to make sure sound is heard equally throughout the room.
鉴于我们仅在此处使用单个房间/环境,因此我们可以将房间色调直接放入场景本身。 我们将positional属性设置为false,以确保在整个房间内均等地听到声音。
We also set the autoplay property to true since we don’t need user interaction to hear the room tone.
我们也将autoplay属性设置为true,因为我们不需要用户交互即可听到房间的声音。
NOTE: Audio autoplay in most browsers either already require or will require user interaction to start. Which means to automatically play sounds like background music or ambient audio you need to use a menu screen or a mute/unmute button or something alike to enable audio autoplay.
注意:大多数浏览器中的音频自动播放可能已经要求或将需要用户交互才能开始。 这意味着要自动播放诸如背景音乐或环境音频之类的声音,您需要使用菜单屏幕或静音/取消静音按钮或类似功能来启用音频自动播放。
For the final piece of our audio puzzle, let’s add some music to our scene. We can either choose to add this as diegetic music that’s coming from the radio in our scene, or as extra-diegetic music which is non-existent in the virtual world we created, but specifically for the user/viewer/player who is experiencing and controlling this virtual world.
对于音频难题的最后一部分,让我们为场景添加一些音乐。 我们既可以选择将其添加为场景中收音机中的恶性音乐,也可以将其添加为我们创建的虚拟世界中不存在的超消化性音乐,但专门针对正在体验和观看音乐的用户/观看者/播放器控制这个虚拟世界。
To do the latter, we would need to put our music either onto our camera (<a-camera>) or to our first-person character (if that is an option) and make sure the audio is non-positional. In this scene I chose to go with the former and put the music to the radio model as a source inside the virtual world.
为此,我们需要将音乐放到相机(<a-camera>)或第一人称角色(如果可以的话)上,并确保音频不定位。 在此场景中,我选择与前者一起使用,并将音乐作为虚拟世界中的来源放置到广播模型中。
We can add the provided music track (composed by yours truly) to our radio model just like we added all the sounds up to this point.
我们可以将提供的音乐曲目(由您本人真正组成)添加到我们的广播模型中,就像我们添加到此为止的所有声音一样。
Our music plays whenever we click on the radio, but what if we want to pause it and then play it again?
每当我们单击广播时,我们的音乐都会播放,但是如果我们想暂停然后再次播放,该怎么办?
To have this functionality we need to write a custom A-Frame component. Then add that component as an HTML attribute to any object we want to add that functionality to, just like we added the “sound” component to our models before.
要具有此功能,我们需要编写一个自定义A框架组件。 然后将该组件作为HTML属性添加到要向其添加功能的任何对象,就像我们之前在模型中添加“声音”组件一样。
You can either write your A-Frame components inline, or write it in an external JavaScript file and then link to it from the html, like I did for this project.
您可以内联编写A-Frame组件,也可以将其编写在外部JavaScript文件中,然后从html链接到它,就像我对此项目所做的那样。
Now we have an audio-toggle component that enables us to play and pause the sound we are hearing. It also allows us to change the autoplay ability via the “playing” property.
现在,我们有了一个音频切换组件,使我们能够播放和暂停正在听到的声音。 它还允许我们通过“播放”属性更改自动播放功能。
And that’s it! We have an A-Frame scene with music, environment sounds and interactive audio.
就是这样! 我们有一个A-Frame场景,其中包含音乐,环境声音和交互式音频。
In the next part we will take a look at how to integrate Tone.js to an A-Frame project and writing more custom components with advanced audio functionality.
在下一部分中,我们将研究如何将Tone.js集成到A-Frame项目中以及如何编写更多具有高级音频功能的自定义组件。
Thanks for reading!
谢谢阅读!
翻译自: https://www.freecodecamp.org/news/a-primer-on-a-frame-audio-52dd56e54876/
java虚拟机堆栈帧