irpas技术客

Babylon.js 深入 - 第 2 章 - 声音(1)_能带孩子会做饭

irpas 6729

Babylon.js 深入 - 第 2 章 - 声音(1) 声音

Babylon.js 声音引擎基于 Web Audio 规范,要使用它,您需要使用与 Web Audio 兼容的浏览器。声音引擎提供环境、空间和定向声音。

如何播放声音和音乐

Babylon.js 声音引擎基于 Web Audio 规范。我们决定不对音频标签或其他机制提供兼容。因此,要使用我们的声音引擎,您需要使用与 Web Audio 兼容的浏览器。尽管如此,如果你在不兼容的浏览器上使用它,它不会影响我们引擎的其余部分,它只会不播放任何声音。

声音引擎提供环境声音、空间声音和定向声音。它可以通过代码或加载 .babylon 文件来创建。正如您将看到的,它遵循和引擎其余部分一样的简单而强大的设计理念。

支持的声音格式和浏览器的声音格式一样。通常至少是 .mp3 和 .wav。

创建环境声音或音乐

这是创建作为环境(非空间化)播放的声音或音乐的代码:

// 加载声音并在准备好后自动播放 var music = new BABYLON.Sound("Music", "music.wav", scene, null, { loop: true, autoplay: true }); 第 1 个参数:声音的名称。第 2 个参数:要加载的声音的 URL。第 3 个参数:附加声音的场景。第 4 个参数:一旦声音准备好播放,函数就会被回调,我们稍后会看到。第 5 个参数:一个 JSON 对象,提供我们将详细介绍的各种选项。但是您已经可以理解所提供的 2 个选项的意思。

简单的音乐播放的示例:

示例链接

示例代码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Babylon.js sample code</title> <!-- Babylon.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> <script src="https://assets.babylonjs.com/generated/Assets.js"></script> <script src="https://preview.babylonjs.com/ammo.js"></script> <script src="https://preview.babylonjs.com/cannon.js"></script> <script src="https://preview.babylonjs.com/Oimo.js"></script> <script src="https://preview.babylonjs.com/earcut.min.js"></script> <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; touch-action: none; } </style> </head> <body> <canvas id="renderCanvas"></canvas> <script> var canvas = document.getElementById("renderCanvas"); var startRenderLoop = function (engine, canvas) { engine.runRenderLoop(function () { if (sceneToRender && sceneToRender.activeCamera) { sceneToRender.render(); } }); } var engine = null; var scene = null; var sceneToRender = null; var createDefaultEngine = function () { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false }); }; var createScene = function () { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, 0), scene); // 加载声音,准备好后自动播放 var music = new BABYLON.Sound("Violons", "./violons11.wav", scene, null, { loop: true, autoplay: true }); return scene; }; window.initFunction = async function () { var asyncEngineCreation = async function () { try { return createDefaultEngine(); } catch (e) { console.log( "the available createEngine function failed. Creating the default engine instead" ); return createDefaultEngine(); } } window.engine = await asyncEngineCreation(); if (!engine) throw 'engine should not be null.'; startRenderLoop(engine, canvas); window.scene = createScene(); }; initFunction().then(() => { sceneToRender = scene }); // Resize window.addEventListener("resize", function () { engine.resize(); }); </script> </body> </html> 处理准备播放回调函数

使用 URL 调用 BABYLON.Sound() 构造函数会生成 2 个阶段:

.wav 或 .mp3 文件是使用异步 XHR 从您的网络服务器加载的。一旦加载,声音就会被网络音频异步解码。如果成功,它将触发您提供的回调函数。

这是一个示例代码:

var music = new BABYLON.Sound("Music", "music.wav", scene, function () { // 声音已下载和解码 music.play(); });

此代码从 Web 服务器加载 music.wav 文件,对其进行解码并使用 play() 函数在回调函数中播放一次。如果没有传递参数,play() 函数会立即播放声音。您可以提供 number 类型的参数使其在 x 秒后播放。

加载和使用回调播放声音的示例:

示例链接

示例代码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Babylon.js sample code</title> <!-- Babylon.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> <script src="https://assets.babylonjs.com/generated/Assets.js"></script> <script src="https://preview.babylonjs.com/ammo.js"></script> <script src="https://preview.babylonjs.com/cannon.js"></script> <script src="https://preview.babylonjs.com/Oimo.js"></script> <script src="https://preview.babylonjs.com/earcut.min.js"></script> <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; touch-action: none; } </style> </head> <body> <canvas id="renderCanvas"></canvas> <script> var canvas = document.getElementById("renderCanvas"); var startRenderLoop = function (engine, canvas) { engine.runRenderLoop(function () { if (sceneToRender && sceneToRender.activeCamera) { sceneToRender.render(); } }); } var engine = null; var scene = null; var sceneToRender = null; var createDefaultEngine = function () { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false }); }; var createScene = function () { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, 0), scene); var music = new BABYLON.Sound("Violons", "./violons11.wav", scene, function () { // 声音已下载和解码 music.play(); } ); return scene; }; window.initFunction = async function () { var asyncEngineCreation = async function () { try { return createDefaultEngine(); } catch (e) { console.log( "the available createEngine function failed. Creating the default engine instead" ); return createDefaultEngine(); } } window.engine = await asyncEngineCreation(); if (!engine) throw 'engine should not be null.'; startRenderLoop(engine, canvas); window.scene = createScene(); }; initFunction().then(() => { sceneToRender = scene }); // Resize window.addEventListener("resize", function () { engine.resize(); }); </script> </body> </html> 在鼠标单击或按键时播放声音

如果您左键单击或按空格键,此示例代码会播放枪声:

var gunshot = new BABYLON.Sound("gunshot", "./gunshot.wav", scene); window.addEventListener("mousedown", function (evt) { // 左键点击开火 if (evt.button === 0) { gunshot.play(); } }); window.addEventListener("keydown", function (evt) { // 按空格键开火 if (evt.keyCode === 32) { gunshot.play(); } });

通过交互播放声音的示例:

示例链接

示例代码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Babylon.js sample code</title> <!-- Babylon.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> <script src="https://assets.babylonjs.com/generated/Assets.js"></script> <script src="https://preview.babylonjs.com/ammo.js"></script> <script src="https://preview.babylonjs.com/cannon.js"></script> <script src="https://preview.babylonjs.com/Oimo.js"></script> <script src="https://preview.babylonjs.com/earcut.min.js"></script> <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; touch-action: none; } </style> </head> <body> <canvas id="renderCanvas"></canvas> <script> var canvas = document.getElementById("renderCanvas"); var startRenderLoop = function (engine, canvas) { engine.runRenderLoop(function () { if (sceneToRender && sceneToRender.activeCamera) { sceneToRender.render(); } }); } var engine = null; var scene = null; var sceneToRender = null; var createDefaultEngine = function () { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false }); }; var createScene = function () { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, 0), scene); var gunshot = new BABYLON.Sound("gunshot", "./gunshot.wav", scene); window.addEventListener("mousedown", function (evt) { // 左击开火 if (evt.button === 0) { gunshot.play(); } }); window.addEventListener("keydown", function (evt) { // 按空格键开火 if (evt.keyCode === 32) { gunshot.play(); } }); return scene; }; window.initFunction = async function () { var asyncEngineCreation = async function () { try { return createDefaultEngine(); } catch (e) { console.log( "the available createEngine function failed. Creating the default engine instead" ); return createDefaultEngine(); } } window.engine = await asyncEngineCreation(); if (!engine) throw 'engine should not be null.'; startRenderLoop(engine, canvas); window.scene = createScene(); }; initFunction().then(() => { sceneToRender = scene }); // Resize window.addEventListener("resize", function () { engine.resize(); }); </script> </body> </html> 一些基本属性

您可以通过设置选项对象的 volume 或通过 setVolume() 函数设置声音的音量。您可以以相同的方式设置播放速率。

通过 onended 事件,您还可以在声音播放完毕时收到通知。

这是一个混合所有这些的简单示例代码:

var volume = 0.1; var playbackRate = 0.5; var gunshot = new BABYLON.Sound("Gunshot", "./gunshot-1.wav", scene, null, { playbackRate: playbackRate, volume: volume }); gunshot.onended = function () { if (volume < 1) { volume += 0.1; gunshot.setVolume(volume); } playbackRate += 0.1; gunshot.setPlaybackRate(playbackRate); };

声音首先使用 0.5 的播放率和 0.1 的音量创建。每次播放声音时,都会调用 onended 函数,并且音量和播放速率会增加。

除了设置特定声音的音量,您还可以使用音频引擎的 setGlobalVolume() 函数设置 Babylon.js 播放的所有声音的全局音量。

BABYLON.Engine.audioEngine.setGlobalVolume(0.5); 播放声音精灵

声音精灵是声音文件的一部分。您可以通过定义偏移量和时长(以秒为单位)在创建声音时定义声音精灵:

var soundSprite = new BABYLON.Sound( "Violons", "./6sounds.mp3", scene, null, { loop: true, autoplay: true, length: 9.200, offset: 14.000 } );

播放声音精灵1的示例:

示例链接

示例代码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Babylon.js sample code</title> <!-- Babylon.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> <script src="https://assets.babylonjs.com/generated/Assets.js"></script> <script src="https://preview.babylonjs.com/ammo.js"></script> <script src="https://preview.babylonjs.com/cannon.js"></script> <script src="https://preview.babylonjs.com/Oimo.js"></script> <script src="https://preview.babylonjs.com/earcut.min.js"></script> <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; touch-action: none; } </style> </head> <body> <canvas id="renderCanvas"></canvas> <script> var canvas = document.getElementById("renderCanvas"); var startRenderLoop = function (engine, canvas) { engine.runRenderLoop(function () { if (sceneToRender && sceneToRender.activeCamera) { sceneToRender.render(); } }); } var engine = null; var scene = null; var sceneToRender = null; var createDefaultEngine = function () { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false }); }; var createScene = function () { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, 0), scene); var soundSprite = new BABYLON.Sound("Violons", "./6sounds.mp3", scene, null, { loop: true, autoplay: true, length: 9.200, offset: 14.000 }); return scene; }; window.initFunction = async function () { var asyncEngineCreation = async function () { try { return createDefaultEngine(); } catch (e) { console.log( "the available createEngine function failed. Creating the default engine instead" ); return createDefaultEngine(); } } window.engine = await asyncEngineCreation(); if (!engine) throw 'engine should not be null.'; startRenderLoop(engine, canvas); window.scene = createScene(); }; initFunction().then(() => { sceneToRender = scene }); // Resize window.addEventListener("resize", function () { engine.resize(); }); </script> </body> </html>

播放声音精灵2的示例:

示例链接

示例代码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Babylon.js sample code</title> <!-- Babylon.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> <script src="https://assets.babylonjs.com/generated/Assets.js"></script> <script src="https://preview.babylonjs.com/ammo.js"></script> <script src="https://preview.babylonjs.com/cannon.js"></script> <script src="https://preview.babylonjs.com/Oimo.js"></script> <script src="https://preview.babylonjs.com/earcut.min.js"></script> <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; touch-action: none; } </style> </head> <body> <canvas id="renderCanvas"></canvas> <script> var canvas = document.getElementById("renderCanvas"); var startRenderLoop = function (engine, canvas) { engine.runRenderLoop(function () { if (sceneToRender && sceneToRender.activeCamera) { sceneToRender.render(); } }); } var engine = null; var scene = null; var sceneToRender = null; var createDefaultEngine = function () { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false }); }; var createScene = function () { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, 0), scene); // 加载声音文件,设置参数和播放结束时的回调函数 var theSounds = new BABYLON.Sound("allSounds", "./6sounds.mp3", scene, null, { autoplay: false }); // 播放声音时设置为 1 var isPlaying = 0; // 声音文件中六个声音的开始和长度 var soundArray = [ [0.0, 5.000], [5.100, 6.600], [12.000, 1.600], [14.000, 9.200], [23.000, 7.900], [31.000, 2.800], ]; // 播放结束时运行的函数 theSounds.onended = function () { isPlaying = 0; console.log("not playing"); }; // 结束声音文件加载和设置 // 创建一个简单的两个按钮 UI 来播放所有声音和播放随机声音 var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI"); var UiPanel = new BABYLON.GUI.StackPanel(); UiPanel.width = "220px"; UiPanel.fontSize = "14px"; UiPanel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER; UiPanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER; advancedTexture.addControl(UiPanel); var button = BABYLON.GUI.Button.CreateSimpleButton("but1", "Play All Sounds"); button.paddingTop = "10px"; button.width = "150px"; button.height = "50px"; button.color = "white"; button.background = "green"; button.onPointerDownObservable.add(() => { if (isPlaying === 0) { isPlaying = 1 theSounds.play(); } }); UiPanel.addControl(button); var button1 = BABYLON.GUI.Button.CreateSimpleButton("but2", "Play Random Sound"); button1.paddingTop = "10px"; button1.width = "150px"; button1.height = "50px"; button1.color = "white"; button1.background = "green"; button1.onPointerDownObservable.add(() => { if (isPlaying === 0) { isPlaying = 1; // 创建随机数 0->5 var aRand0 = Math.floor(Math.random() * 6); theSounds.play(0, soundArray[aRand0][0], soundArray[aRand0][1]); } }); UiPanel.addControl(button1); // 结束 ui 创建和播放功能 return scene; }; window.initFunction = async function () { var asyncEngineCreation = async function () { try { return createDefaultEngine(); } catch (e) { console.log( "the available createEngine function failed. Creating the default engine instead" ); return createDefaultEngine(); } } window.engine = await asyncEngineCreation(); if (!engine) throw 'engine should not be null.'; startRenderLoop(engine, canvas); window.scene = createScene(); }; initFunction().then(() => { sceneToRender = scene }); // Resize window.addEventListener("resize", function () { engine.resize(); }); </script> </body> </html> 同时播放多个声音并同步

为此,只有在确定所有声音都准备好播放时,您才需要对所有声音调用 play() 方法。

var music1 = new BABYLON.Sound( "Violons11", "./violons11.wav", scene, soundReady, { loop: true } ); var music2 = new BABYLON.Sound( "Violons18", "./violons18.wav", scene, soundReady, { loop: true } ); var music3 = new BABYLON.Sound( "Cellolong", "./cellolong.wav", scene, soundReady, { loop: true } ); var soundsReady = 0; function soundReady() { soundsReady++; if (soundsReady === 3) { music1.play(); music2.play(); music3.play(); } }

一起播放声音的示例:

示例链接

示例代码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Babylon.js sample code</title> <!-- Babylon.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> <script src="https://assets.babylonjs.com/generated/Assets.js"></script> <script src="https://preview.babylonjs.com/ammo.js"></script> <script src="https://preview.babylonjs.com/cannon.js"></script> <script src="https://preview.babylonjs.com/Oimo.js"></script> <script src="https://preview.babylonjs.com/earcut.min.js"></script> <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; touch-action: none; } </style> </head> <body> <canvas id="renderCanvas"></canvas> <script> var canvas = document.getElementById("renderCanvas"); var startRenderLoop = function (engine, canvas) { engine.runRenderLoop(function () { if (sceneToRender && sceneToRender.activeCamera) { sceneToRender.render(); } }); } var engine = null; var scene = null; var sceneToRender = null; var createDefaultEngine = function () { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false }); }; var createScene = function () { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, 0), scene); var music1 = new BABYLON.Sound("Violons11", "./violons11.wav", scene, soundReady, { loop: true }); var music2 = new BABYLON.Sound("Violons18", "./violons18.wav", scene, soundReady, { loop: true }); var music3 = new BABYLON.Sound("Cellolong", "./cellolong.wav", scene, soundReady, { loop: true }); var soundsReady = 0; function soundReady() { soundsReady++; if (soundsReady === 3) { music1.play(); music2.play(); music3.play(); } } return scene; }; window.initFunction = async function () { var asyncEngineCreation = async function () { try { return createDefaultEngine(); } catch (e) { console.log( "the available createEngine function failed. Creating the default engine instead" ); return createDefaultEngine(); } } window.engine = await asyncEngineCreation(); if (!engine) throw 'engine should not be null.'; startRenderLoop(engine, canvas); window.scene = createScene(); }; initFunction().then(() => { sceneToRender = scene }); // Resize window.addEventListener("resize", function () { engine.resize(); }); </script> </body> </html> 从 ArrayBuffer 加载声音

如果您使用自己提供的 ArrayBuffer 调用构造函数,则可以绕过第一阶段(嵌入 XHR 请求)。

这是一个演示它的示例代码:

var gunshotFromAB; loadArrayBufferFromURL("./gunshot.wav"); function loadArrayBufferFromURL(urlToSound) { var request = new XMLHttpRequest(); request.open("GET", urlToSound, true); request.responseType = "arraybuffer"; request.onreadystatechange = function () { if (request.readyState == 4) { if (request.status == 200) { gunshotFromAB = new BABYLON.Sound( "FromArrayBuffer", request.response, scene, soundReadyToBePlayed ); } } }; request.send(null); } function soundReadyToBePlayed() { gunshotFromAB.play(); }

从 ArrayBuffer 加载声音的示例:

示例链接

示例代码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Babylon.js sample code</title> <!-- Babylon.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> <script src="https://assets.babylonjs.com/generated/Assets.js"></script> <script src="https://preview.babylonjs.com/ammo.js"></script> <script src="https://preview.babylonjs.com/cannon.js"></script> <script src="https://preview.babylonjs.com/Oimo.js"></script> <script src="https://preview.babylonjs.com/earcut.min.js"></script> <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; touch-action: none; } </style> </head> <body> <canvas id="renderCanvas"></canvas> <script> var canvas = document.getElementById("renderCanvas"); var startRenderLoop = function (engine, canvas) { engine.runRenderLoop(function () { if (sceneToRender && sceneToRender.activeCamera) { sceneToRender.render(); } }); } var engine = null; var scene = null; var sceneToRender = null; var createDefaultEngine = function () { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false }); }; var createScene = function () { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, 0), scene); var gunshotFromAB; loadArrayBufferFromURL("./gunshot.wav"); function loadArrayBufferFromURL(urlToSound) { var request = new XMLHttpRequest(); request.open('GET', urlToSound, true); request.responseType = "arraybuffer"; request.onreadystatechange = function () { if (request.readyState == 4) { if (request.status == 200) { gunshotFromAB = new BABYLON.Sound("FromArrayBuffer", request.response, scene, soundReadyToBePlayed); } } }; request.send(null); } function soundReadyToBePlayed() { gunshotFromAB.play(); } return scene; }; window.initFunction = async function () { var asyncEngineCreation = async function () { try { return createDefaultEngine(); } catch (e) { console.log( "the available createEngine function failed. Creating the default engine instead" ); return createDefaultEngine(); } } window.engine = await asyncEngineCreation(); if (!engine) throw 'engine should not be null.'; startRenderLoop(engine, canvas); window.scene = createScene(); }; initFunction().then(() => { sceneToRender = scene }); // Resize window.addEventListener("resize", function () { engine.resize(); }); </script> </body> </html>

从麦克风加载声音的示例:

示例链接

示例代码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Babylon.js sample code</title> <!-- Babylon.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> <script src="https://assets.babylonjs.com/generated/Assets.js"></script> <script src="https://preview.babylonjs.com/ammo.js"></script> <script src="https://preview.babylonjs.com/cannon.js"></script> <script src="https://preview.babylonjs.com/Oimo.js"></script> <script src="https://preview.babylonjs.com/earcut.min.js"></script> <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; touch-action: none; } </style> </head> <body> <canvas id="renderCanvas"></canvas> <script> var canvas = document.getElementById("renderCanvas"); var startRenderLoop = function (engine, canvas) { engine.runRenderLoop(function () { if (sceneToRender && sceneToRender.activeCamera) { sceneToRender.render(); } }); } var engine = null; var scene = null; var sceneToRender = null; var createDefaultEngine = function () { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false }); }; var createScene = function () { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene); camera.setTarget(BABYLON.Vector3.Zero()); camera.attachControl(canvas, true); var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene); light.intensity = 0.7; var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene); const constraints = window.constraints = { audio: true, video: false }; function handleSuccess(stream) { const audioTracks = stream.getAudioTracks(); console.log('Got stream with constraints:', constraints); console.log('Using audio device: ' + audioTracks[0].label); stream.oninactive = function () { console.log('Stream ended'); }; // 使变量可用于浏览器控制台 window.stream = stream; var bjsSound = new BABYLON.Sound("mic", stream, scene); bjsSound.attachToMesh(sphere); bjsSound.play(); } function handleError(error) { console.log('navigator.getUserMedia error: ', error); } navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError); return scene; }; window.initFunction = async function () { var asyncEngineCreation = async function () { try { return createDefaultEngine(); } catch (e) { console.log( "the available createEngine function failed. Creating the default engine instead" ); return createDefaultEngine(); } } window.engine = await asyncEngineCreation(); if (!engine) throw 'engine should not be null.'; startRenderLoop(engine, canvas); window.scene = createScene(); }; initFunction().then(() => { sceneToRender = scene }); // Resize window.addEventListener("resize", function () { engine.resize(); }); </script> </body> </html> 使用 Assets Manager 加载声音

资产管理器非常有用,因为它为您提供了一些很棒的功能,例如:加载屏幕。

var music1, music2, music3; // Assets manager var assetsManager = new BABYLON.AssetsManager(scene); var binaryTask = assetsManager.addBinaryFileTask( "Violons18 task", "./violons18.wav" ); binaryTask.onSuccess = function (task) { music1 = new BABYLON.Sound("Violons18", task.data, scene, soundReady, { loop: true }); }; var binaryTask2 = assetsManager.addBinaryFileTask( "Violons11 task", "./violons11.wav" ); binaryTask2.onSuccess = function (task) { music2 = new BABYLON.Sound("Violons11", task.data, scene, soundReady, { loop: true }); }; var binaryTask3 = assetsManager.addBinaryFileTask( "Cello task", "./cellolong.wav" ); binaryTask3.onSuccess = function (task) { music3 = new BABYLON.Sound("Cello", task.data, scene, soundReady, { loop: true }); }; var soundsReady = 0; function soundReady() { soundsReady++; if (soundsReady === 3) { music1.play(); music2.play(); music3.play(); } } assetsManager.load();

使用 Asset Manager 加载声音的示例:

示例链接

示例代码:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Babylon.js sample code</title> <!-- Babylon.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script> <script src="https://assets.babylonjs.com/generated/Assets.js"></script> <script src="https://preview.babylonjs.com/ammo.js"></script> <script src="https://preview.babylonjs.com/cannon.js"></script> <script src="https://preview.babylonjs.com/Oimo.js"></script> <script src="https://preview.babylonjs.com/earcut.min.js"></script> <script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script> <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script> <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; touch-action: none; } </style> </head> <body> <canvas id="renderCanvas"></canvas> <script> var canvas = document.getElementById("renderCanvas"); var startRenderLoop = function (engine, canvas) { engine.runRenderLoop(function () { if (sceneToRender && sceneToRender.activeCamera) { sceneToRender.render(); } }); } var engine = null; var scene = null; var sceneToRender = null; var createDefaultEngine = function () { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false }); }; var createScene = function () { var scene = new BABYLON.Scene(engine); var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, 0), scene); var music1, music2, music3; // Assets manager var assetsManager = new BABYLON.AssetsManager(scene); var binaryTask = assetsManager.addBinaryFileTask("Violons18 task", "./violons18.wav"); binaryTask.onSuccess = function (task) { music1 = new BABYLON.Sound("Violons18", task.data, scene, soundReady, { loop: true }); } var binaryTask2 = assetsManager.addBinaryFileTask("Violons11 task", "./violons11.wav"); binaryTask2.onSuccess = function (task) { music2 = new BABYLON.Sound("Violons11", task.data, scene, soundReady, { loop: true }); } var binaryTask3 = assetsManager.addBinaryFileTask("Cello task", "./cellolong.wav"); binaryTask3.onSuccess = function (task) { music3 = new BABYLON.Sound("Cello", task.data, scene, soundReady, { loop: true }); } var soundsReady = 0; function soundReady() { soundsReady++; if (soundsReady === 3) { music1.play(); music2.play(); music3.play(); } } assetsManager.load(); return scene; }; window.initFunction = async function () { var asyncEngineCreation = async function () { try { return createDefaultEngine(); } catch (e) { console.log( "the available createEngine function failed. Creating the default engine instead" ); return createDefaultEngine(); } } window.engine = await asyncEngineCreation(); if (!engine) throw 'engine should not be null.'; startRenderLoop(engine, canvas); window.scene = createScene(); }; initFunction().then(() => { sceneToRender = scene }); // Resize window.addEventListener("resize", function () { engine.resize(); }); </script> </body> </html>


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Babylonjs #深入 # #2 # #声音1