https://d226lax1qjow5r.cloudfront.net/blog/blogposts/experience-spatial-audio-with-vonage-video/spatial-audio_video-api-1.png

Experimenta el Audio Espacial con Vonage Video API

Publicado el November 16, 2021

Tiempo de lectura: 5 minutos

Introducción

La forma en que consumimos audio en nuestros móviles, ordenadores de sobremesa y otros dispositivos está cambiando, y la pandemia ha influido definitivamente en nuestro modelo de consumo. Una palabra de moda que está rondando el audio es "audio espacial". Este artículo te mostrará cómo crear una experiencia de audio espacial utilizando las API de Video de Vonage y el SDK de Resonance en navegadores web.

¿Tienes curiosidad por saber cómo sería la experiencia de audio espacial? Vea nuestra demostración de muestra a continuación y utilice auriculares para ver el vídeo.

Un poco de historia del audio

Antes de hablar del audio espacial/audio 3D, hablemos de los canales de audio y de sus diferencias.

Mono

El audio mono (significa uno) es un audio monocanal en el que el audio reproducido en el auricular derecho es el mismo audio reproducido en el auricular izquierdo. Cada sonido se dispersa uniformemente en ambos auriculares.

Estéreo

El audio estéreo es un audio de dos canales en el que se oyen sonidos diferentes en el auricular derecho y en el izquierdo. Puedes distinguir el sonido de una guitarra en el auricular derecho y el de unos pasos en el izquierdo.

Sonido envolvente

Se han realizado trabajos propios sobre cómo se mezcla y reproduce el audio. El audio mono y/o estéreo se mezcla para el número de altavoces y subwoofers de la configuración de audio (5.1, 7.1, etc., que equivale a 5 altavoces y 1 subwoofer o 7 altavoces y 1 subwoofer) y se reproduce a través de todos los altavoces y subwoofers para crear una sensación de sonido envolvente.

Binaural

Se trata de una versión mejorada del estéreo en la que la grabación requiere dos micrófonos omnidireccionales. Cuando se reproduce este audio, oyes los sonidos como si estuvieras físicamente presente en el lugar.

Audio espacial

El audio espacial te permite situar el audio en cualquier lugar de un espacio tridimensional. Esto significa que no sólo puedes distinguir las fuentes de sonido entre izquierda y derecha, sino también entre arriba, abajo, delante y detrás. El audio espacial engaña al cerebro humano retrasando el momento en que el audio llega a nuestros oídos izquierdo y derecho y utilizando frecuencias más altas y más bajas. El crecimiento de la realidad virtual ha impulsado la popularidad del audio espacial.

¿Debería preocuparle el audio espacial?

Fatiga por videoconferencia - El audio de las videoconferencias produce una experiencia auditiva poco natural, ya que todo el audio procede del mismo altavoz y a la misma distancia. Este paisaje sonoro sintético es diferente de una experiencia auditiva real en la que el sonido es posicional, direccional y esférico. El audio espacial puede recrear una experiencia auditiva real situando el sonido en un espacio tridimensional.

Espacios de RA y RV - El audio espacial produce una experiencia inmersiva en los espacios AR/VR. El audio desempeña un papel fundamental en los espacios de realidad aumentada y realidad virtual, al igual que los efectos visuales y las acciones.

Creación de aplicaciones sociales - Las aplicaciones de audio/vídeo en directo han introducido el audio espacial para hacer las conversaciones más atractivas e interactivas.

Experiencia de audio espacial con las API de Video de Vonage y el SDK Resonance

Nuestro genial ingeniero de soluciones para clientes Rajkiran Talusani ha creado una guía "CÓMO" para crear una experiencia de audio espacial con Vonage Video SDK y Resonance SDK. Sigue las instrucciones a continuación.

Requisitos

¿Necesito algún hardware especial?

No, sólo necesitas unos auriculares estéreo o un dispositivo compatible para reproducir el audio. No necesitas un micrófono especial para este ejemplo concreto.

Configuración inicial

Resonance audio nos permite situar al oyente en una posición específica del espacio tridimensional identificada por las coordenadas x,y y z. A continuación, puedes colocar cualquier número de fuentes de audio en diferentes posiciones y Resonance audio mezclaría los flujos de audio para que suene como si estuvieras en un espacio físico.

Spatial Audio - Virtual Room ExampleSpatial Audio - Virtual Room Example

El primer paso es crear un AudioContext y un nodo Gain para controlar el volumen de audio de Resonance

audioContext = new AudioContext();
  resonanceGain = audioContext.createGain();

A continuación, defina una habitación en 3D y los materiales de sus paredes

let roomDimensions = {
  width: roomWidth,
  height: roomHeight,
  depth: roomDepth,
  };
  
  let roomMaterials = {
  left: 'uniform',
  right: 'uniform',
  up: 'uniform',
  down: 'uniform',
  front: 'uniform',
  back: 'uniform'
  };

Para conocer todos los tipos de material de pared disponibles, puede consultar la documentación de Resonance audio.

A continuación, creamos una instancia de Resonance Audio y la conectamos al audioContext a través de resonanceGain. Además, establecer la posición inicial del oyente en el centro de la habitación (0,0,0)

resonanceAudioScene = new ResonanceAudio(audioContext,{
  ambisonicOrder: 1
  });
  
  resonanceAudioScene.output.connect(resonanceGain);
  resonanceGain.connect(audioContext.destination);
  resonanceAudioScene.setRoomProperties(roomDimensions, roomMaterials);
  resonanceAudioScene.setListenerPosition(0, 0, 0);

Conectar a los abonados a Resonance Audio

A continuación, cada vez que se añade un abonado a la sesión, conectamos la salida del abonado a Resonance audio.

function connectVideoToResonanceAudio(subscriber,x=1,y=0,z=1) {
  if(!isSupported)
  return;
  let subscriberId = subscriber.id;
  subscriber.setAudioVolume(0);
  
  console.log("Adding streamId="+subscriber.stream.id+" to the
  map");
  // find the video element 
  var videoElem = subscriber.element.querySelector('video');
  if(videoElem == undefined){
  console.log("Video Element null in connectVideoToResonanceAudio. Something terribly wrong");
  return;
  }
  
  let audioElementSource =
  audioContext.createMediaStreamSource(videoElem.srcObject);
  let source = resonanceAudioScene.createSource();
  audioElementSource.connect(source.input);
  source.setPosition(x, y, z);
  resonanceSources\[subscriberId] = source;
  }

Tenga en cuenta que hemos ajustado el volumen del abonado a 0 porque no queremos escuchar el audio del abonado directamente. En su lugar, enrutamos el audio del suscriptor a través de Resonance.

En primer lugar, buscamos el elemento video del suscriptor y, a continuación, obtenemos el flujo de audio del suscriptor mediante videoElem.srcObject, que devuelve un MediStream. A continuación, creamos una "Resonance audio source" y conectamos el flujo de audio del suscriptor a esta fuente. Puedes establecer la posición inicial de la fuente del suscriptor en un valor por defecto. Cambiaremos esto más tarde cuando el diseño esté finalizado o redimensionado.

Asignar posiciones de origen a abonados

Cada vez que añada un nuevo abonado a la maqueta o ésta cambie de tamaño, deberá reasignar las posiciones de origen en función de la posición relativa del abonado en la maqueta.

Cada participante puede tener su propio diseño.

En este fragmento, situamos al oyente en el centro de la esfera y, a continuación, colocamos a los abonados alrededor del borde de la media esfera (aproximadamente).

  function adjustAudioSourcePositions(streams, numSpeakersVisible, layoutDiv){\
  // find the center point of the video layout in pixels 
  let layoutRect = document.getElementById(layoutDiv).getBoundingClientRect();
  let layoutCenterX = layoutRect.left + (layoutRect.width/2);
  let layoutCenterZ = layoutRect.top + (layoutRect.height/2);
  // convert pixels to room dimensions in meters
  let scaleX = roomWidth/layoutRect.width;
  let scaleZ = roomHeight/layoutRect.height;
  for(i=0;i<numSpeakersVisible && i <streams.length;i++){
  /* for each subscriber, get the bounding box and find the center relative to
  the center of layoutContainer */
  let subscriberRect =
  document.getElementById(streams\[i].subscriber.id).getBoundingClientRect();
  let subscriberCenterX = subscriberRect.left + (subscriberRect.width/2);
  let subscriberCenterZ = subscriberRect.top + (subscriberRect.height/2);
  
  let relativeX = (subscriberCenterX - layoutCenterX)*scaleX;
  let relativeZ = (subscriberCenterZ - layoutCenterZ)*scaleZ;
  /* lets keep people closer to the center of screen further away on Y axis, so
  it should be like people sitting in half spherical shape */
  let Y = 2 * (1 - (Math.abs(relativeX)/(roomWidth/2)));
  setSourcePosition(streams\[i].subscriber.id,relativeX,Y,relativeZ);
  }
  }

Cambio entre espacial y mono

Si quieres activar el modo espacial, todo lo que tienes que hacer es establecer el valor de ganancia resonanceGain en 1 y establecer el volumen de todos los abonados en 0. Del mismo modo, para activar el modo mono, establece el volumen de todos los abonados en 50 y el valor de ganancia resonanceGain en 0.

  function changeMode(mode){
  if(!isSupported)
  return;
  if(mode == MODE_SPATIAL){
  console.log("mode is spatial now");
  resonanceGain.gain.value=1;
  setSubscribersVolume(0);
  }
  else if(mode == MODE_NONE){
  console.log("mode is mono now");
  resonanceGain.gain.value=0;
  setSubscribersVolume(50);
  }
  }
  
  
  function setSubscribersVolume(vol){
  if(!isSupported)
  return;
  for (var streamId in subscriberMap) {
  subscriberMap\[streamId].setAudioVolume(vol);
  }
  }

Compatibilidad con navegadores

Aunque todos los navegadores deberían ser compatibles, hemos encontrado algunos problemas durante las pruebas. Firefox funciona como era de esperar, pero hemos descubierto que Chrome no activa la cancelación de eco cuando el audio se enruta a través de WebAudio (error de Chrome). Esto significa que si alguno de los participantes no lleva auriculares, puede crear una mala experiencia de audio para todos. La solución para este problema es enrutar el audio procesado a través de una conexión loopback peer y conectarse a un elemento de audio.

Arréglalo abajo:

function fixChrome687574(loopbackDestination, audioContext,
  resonanceGainNode,audioEl){
  const outboundPeerConnection = new RTCPeerConnection();
  const inboundPeerConnection = new RTCPeerConnection();
  const onError = e => {
    console.error("RTCPeerConnection loopback initialization error", e);
  };
  outboundPeerConnection.addEventListener("icecandidate", e => {
  inboundPeerConnection.addIceCandidate(e.candidate).catch(onError);
  });
  inboundPeerConnection.addEventListener("icecandidate", e => {
  outboundPeerConnection.addIceCandidate(e.candidate).catch(onError);
  });
  inboundPeerConnection.addEventListener("track", e => {
  audioEl.srcObject = e.streams[0];
  });
  resonanceGainNode.connect(loopbackDestination);
  loopbackDestination.stream.getTracks().forEach(track => {
  outboundPeerConnection.addTrack(track, loopbackDestination.stream);
  });
  outboundPeerConnection.createOffer().then(offer => {
  outboundPeerConnection.setLocalDescription(offer).catch(onError);
  
  inboundPeerConnection
  .setRemoteDescription(offer)
  .then(() => {
  inboundPeerConnection
  .createAnswer()
  .then(answer => {
  answer.sdp = answer.sdp.replace('useinbandfec=1', 'useinbandfec=1', 'stereo=1');
  inboundPeerConnection.setLocalDescription(answer).catch(onError);
  outboundPeerConnection.setRemoteDescription(answer).catch(onError);
  })
  .catch(onError);
  })
  .catch(onError);
  });
  }

Safari (14.1.2) también introduce algunos problemas de audio, pero 15.x parece funcionar bien.

Mejoras futuras

Aunque hemos colocado las fuentes de sonido en el espacio tridimensional, son fuentes puntuales: emiten sonido en todas direcciones. Como mejora futura, puedes hacerlas fuentes direccionales, de modo que cada abonado emita sonidos sólo en la dirección del oyente.

Conclusión

Hoy, construimos una experiencia de audio espacial usando las API de Video de Vonage y el SDK de Resonance al posicionar a los suscriptores en diferentes partes de una sala virtual. Ahora puedes divertirte más en las reuniones virtuales habilitando el audio espacial. Consulta el código fuente completo si te animas a construir esto por tu cuenta.

Compartir:

https://a.storyblok.com/f/270183/400x400/e204f1b8c6/binoy-chemmagate.png
Binoy ChemmagateGerente en Vonage

Binoy Chemmagate es un jefe de producto de los servicios de IA de Vonage con más de 10 años en el sector de las TIC, especializado en API de IA generativa y plataformas de IA conversacional de bajo código. Residente en Londres, en su tiempo libre disfruta asesorando a futuros jefes de producto.