本当に没入型メタバース経験をつくる方法 - WebオーディオAPIによる空間オーディオの実装


バトルロワイヤルのようなメタバースと3 Dゲームの増加に伴い,仮想環境での没入型オーディオ体験の需要は急速に高まっている.空間的なオーディオは、ユーザーが仮想シーンでそれらの周りの音源の位置と距離を知覚することができます技術は、迅速に没入型仮想体験を作成するの重要な部分になっています.
没入型オーディオ経験のためのこの急速に成長している要求に応じて、私たちは、Zgocloud ExpressウェブSDK(V . 10.0以降)に、近接音声モジュールを加えました.そして、それは以下の特徴を提供します:

  • 近接音声チャット:ユーザーが特定の近接の中から他のユーザーの声を聞くことができる仮想空間チャットのチャットのフォームと、リスナーと音源の間の距離に応じて音の変化の音量.

  • 空間オーディオ:仮想空間内のユーザは、実世界の音を聞くときに、音源の位置と距離を感知することができる.

  • チームボイスチャット:ユーザーがチームに参加することができますし、チームのみのモード(ユーザーの声は、同じチーム内の他のユーザーによって聞くことができる)と誰もがモード(ユーザーの声は、部屋のみんなに聞くことができる)の間で切り替えることができます彼らが望むように.
  • この記事では、Webブラウザで提供されるWebオーディオAPIを使用して、空間的なオーディオエフェクトを実装する方法について説明します.ここにシンプルspatial audio demo page 我々は、WebオーディオAPIを使用して作った.
  • をクリックして再生ボタンを音楽を再生を開始します.
  • をクリックしてオン/オフ空間のオーディオボタンをオンまたはオフに空間オーディオ効果をオンにします.
  • 空間のオーディオ効果がオンになっているときは、音楽はあなたの頭の周りを移動している聞くことができます.
  • ​ (空間のオーディオ効果を体験するには、ステレオヘッドフォンやスピーカーを使用する必要があります.)
    わかりました.もっと詳しく説明しましょう.

    WebオーディオAPI入門
    WebオーディオAPIは、多くの異なるオーディオ操作に使用することができます.例えば、<audio> ウェブ上でオーディオを再生するタグ.加えて、オーディオ音量調整、オーディオミキシング、およびオーディオの空間化などの他のオーディオ処理機能を提供します.
    WebオーディオAPIを使用すると、オーディオコンテキスト内のオーディオ操作を実行することができますモジュールのルーティングを許可するように設計されています.基本的なオーディオ操作は、オーディオルーティンググラフを形成するために一緒にリンクされているオーディオノードで行われます.非常に基本的なオーディオルーティンググラフは次のようになります.

    グラフでは、入力、エフェクト、および宛先モジュールは3ですAudioNode オーディオソース、中間処理モジュールおよびオーディオ宛先を表すS.
    簡単なオーディオ処理ワークフローの基本的な手順について説明します.

    オーディオコンテキストを作成する
    // Create audio context
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    const audioCtx = new AudioContext();
    
    AudioContext オーディオモジュールは、オーディオモジュールから一緒にリンクされて構築されたAudioNode . それは、それが含むノードの作成および各々のノードの音声処理の実行を制御する中央処理装置である.

    作成されたオーディオコンテキスト内のソースノードとエフェクトノードを作成します.
    // Creat a SourceNode for decoding the audio source provided in the <audio> tag
    const audioEl = document.querySelector('audio');
    const sourceNode = audioCtx.createMediaElementSource(audioEl);
    // Create a GainNode for controlling the audio volume
    const gainNode = audioCtx.createGain();
    

    ソースノードをエフェクトノードに接続する
    ソースノードの呼び出しconnect 指定したエフェクトノードに接続するメソッドです.
    sourceNode.connect(gainNode);
    

    エフェクトノードをオーディオコンテキストの宛先に接続します
    エフェクトノードの呼び出しconnect オーディオコンテキストの宛先に処理されたオーディオを送信する方法.この例では、宛先ノードaudioCtx.destination 現在使用中のスピーカーを表します.
    gainNode.connect(audioCtx.destination);
    

    エフェクトノードのプロパティを変更してオーディオ出力を変更します.
    // Put the audio on mute
    gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
    

    WebオーディオAPIを使用した空間オーディオ効果の実装
    さて、WebオーディオAPIを使用して空間的オーディオエフェクトを実装する方法を見てみましょう.
    基本的に、オーディオソースに空間的なオーディオエフェクトを追加するには、次の2つのインターフェイスを組み合わせて使用する必要があります.AudioListener : 仮想3 D空間内のユニークなリスナーを表します.オーディオコンテキストのリスナーインスタンスをAudioContext.listener プロパティ.PannerNode : 仮想3 D空間内のオーディオソースを表します.を呼び出すことができますnew メソッドまたはAudioContext.createPanner() 作成するメソッドPannerNode .
    以下に設定する方法について説明しますAudioListenerPannerNode あなたが望むオーディオの空間化効果を達成する.

    1 .セットアップAudioListenerAudioListener オーディオ空間化で使用されるオーディオシーンを聴くユニークな人の位置と向きを説明します.エーPannerNode リスナーに対してオーディオソースの位置を記述するために使用できます.
    の次の3つのプロパティAudioListener 右のデカルト座標系の位置を定義します.
  • positionX : リスナーの水平位置を表します.デフォルト値は0 .
  • positionY : リスナーの垂直位置を表します.デフォルト値は0 .
  • positionZ : リスナーの前後の位置を表します.デフォルト値は0 .
  • // Set the listener's position
    const listener = audioCtx.listener;
    listener.positionX = camera.position.x;
    listener.positionY = camera.position.y;
    listener.positionZ = camera.position.z;
    

    次の3つのプロパティは、位置の値として同じ右手デカルト座標系でリスナーの前方方向の位置を定義しますpositionX , positionY , and positionZ ):
  • forwardX : リスナーの前方方向の水平位置を表します.デフォルト値は0 .
  • forwardY : リスナーの前方方向の垂直位置を表します.デフォルト値は0 .
  • forwardZ : リスナーの前方方向の前後の位置を表します.デフォルト値は-1 .
  • 次の3つのプロパティは、位置の値として同じ右手のデカルト座標系でリスナーの先頭の位置を定義しますpositionX , positionY , and positionZ ):upX : リスナーの先頭の水平位置を表します.デフォルト値は1 .upY : リスナーの先頭の垂直位置を表します.デフォルト値は0 .upZ : リスナーの先頭の縦(前後)の位置を表します.デフォルト値は0 .
    これらの2つのオリエンテーション媒介者をセットアップすることによって、リスナの耳のポジションは、空間音声効果をつくるために決定されることができる.

    2 .設定PannerNodeエーPannerNode 右方向デカルト座標を有する3 Dオーディオ空間のオーディオソース信号の位置および動きを記述するオーディオ処理モジュールである.それは、電流源に対するその位置およびオリエンテーションを使用している音声源シグナルを空間化するAudioListenerAudioContext .
    以下は、一般的に使用されるPannerNode :
  • panningModel : 三次元空間でオーディオを配置するために使用する空間化アルゴリズムを決定する列挙値.デフォルト値はequalpower , 等電力パンニングアルゴリズムの表現このプロパティを設定することをお勧めしますHRTF , これは、より高い品質のステレオ出力をレンダリングすることを意味しますequalpower .
  • positionX/positionY/positionZ : 右デカルト座標系のオーディオの水平/垂直/縦(前後)の位置.
  • orientationX/orientationY/orientationZ : 右の直交座標系のオーディオソースのベクトルの水平/垂直/縦(前後)の位置.
  • coneInnerAngle : 二重の値は、体積の減少のない円錐の内側の角度を表します.デフォルト値は360 .
  • rolloffFactor : ソースがリスナーから離れて移動するとき、ボリュームがどれくらい速く減少するかについて説明している倍の値.デフォルト値は1 .
  • distanceModel : リスナーから離れて移動するときに、オーディオソースの音量を減らすために使用するアルゴリズムを決定する列挙値.デフォルト値はinverse .

  • オーディオパンニング効果の実装
    次のコードのスニペットでは、オーディオがパンを頭の周りを移動しているようなリスナーを感じるオーディオパンニング効果を実現する方法を示します.これは、単にPannerNode 音楽が演奏されている間.
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Web Audio</title>
    </head>
    
    <body>
      <audio loop autoplay crossorigin="anonymous"
        src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/858/outfoxing.mp3"></audio>
      <button onclick="startPlay()">Play</button>
      <button onclick="spatialize()">Turn On/Off Spatialization</button>
      <span>Sound effect status:</span><span id="status">Off</span>
      <script>
        // Set up the initial position of the audio source
        const audioPosition = [0, 0, 1]
        // Create an audio context
        const AudioContext = window.AudioContext || window.webkitAudioContext;
        const audioCtx = new AudioContext();
        // Set up an AudioListener
        const listener = audioCtx.listener;
        listener.positionX.value = 0;
        listener.positionY.value = 0;
        listener.positionZ.value = 0;
        listener.forwardX.value = 0;
        listener.forwardY.value = 0;
        listener.forwardZ.value = -1;
    
        // Create a source node for the source audio provided in the <audio> tag
        const audioEl = document.querySelector('audio');
        // Create an effect node for processing the source audio
        const sourceNode = audioCtx.createMediaElementSource(audioEl);
        // Create a PannerNode and set up its properties
        const pannerNode = new PannerNode(audioCtx, {
          panningModel: "HRTF",  // The spatialization algorithm to be used to position audio.
          distanceModel: "linear",  // The algorithm to be used to reduce the volume of the audio source as it moves away from the listener. 
          rolloffFactor: 1,  // How quickly the volume is reduced as the source moves away from the listener. 
          coneInnerAngle: 360, // The angle of a cone inside of which there will be no volume reduction.
          positionX: audioPosition[0],
          positionY: audioPosition[1],
          positionZ: audioPosition[2],
          maxDistance: 10000,
        });
        // Connect the source node directly to the destination node 
        sourceNode.connect(audioCtx.destination);
    
        // Change audio source's position values on the X, Y, Z axes to make it move around the listener. 
        function autoMove(axis, interval, step = 100, maxDistance = 1000) {
          let isAdd = true
          const positionAxisMap = ["positionX", "positionY", "positionZ"]
          setInterval(() => {
            if (isAdd && audioPosition[axis] >= maxDistance) {
              isAdd = false;
            } else if (!isAdd && audioPosition[axis] <= -maxDistance) {
              isAdd = true;
            }
            if (isAdd) {
              audioPosition[axis] += step;
            } else {
              audioPosition[axis] -= step;
            }
            pannerNode[positionAxisMap[axis]].value = audioPosition[axis]
            console.log('audioPosition', audioPosition);
          }, interval)
    
        }
        // Move back and forth on the X-axis between -1000 and 1000
        autoMove(0, 100, 100, 1000)
        // Move back and forth on the Z-axis between -1000 and 1000
        autoMove(2, 200, 100, 1000)
        // Move back and forth on the Y-axis between -100 and 100
        autoMove(1, 400, 10, 100)
    
        // Start playing the music
        function startPlay() {
          audioCtx.resume();
          // Put the audio on mute.
          audioEl.play();
        }
    
        // Turn off 3D sound effect
        let isSpatialized = false
        function spatialize() {
          isSpatialized = !isSpatialized
          document.querySelector("#status").innerText = isSpatialized ? "On" : "Off"
          if (isSpatialized) {
            sourceNode.disconnect();
            sourceNode.connect(pannerNode);
            // Connect the Panner node to the destination node
            pannerNode.connect(audioCtx.destination);
          } else {
            sourceNode.disconnect();
            sourceNode.connect(audioCtx.destination);
          }
        }
    </script>
    </body>
    
    </html>
    

    結論
    本論文では、WEB Audio APIの基礎的な紹介を行い、その効果を利用した空間音響効果(聴取者の頭部の周りの音)を実装する方法について述べるAudioListener and PannerNode インタフェース
    オーディオの空間化に加えて、WebオーディオAPIは、他の多くの強力なオーディオ処理機能を備えています.詳細については、チェックアウトすることができますWeb Audio API documentation on MDN .
    Zegocloud Express SDKの近接音声モジュールについての詳細はrelated developer documentation on ZEGOCLOUD website .
    訪問ZEGOCLOUD website あなたがリアルタイムのオーディオとビデオで構築できるものについての詳細を学ぶために!