Tutorial Wwise en Español - Parte IV: Posicionamiento y Panorama
/Note for my english readers: Sorry this article is not in your language but I wanted to write something for the spanish speaking community since there aren’t many resources on game audio in my native tongue. If I see that there is demand, I would be happy to translate this into english although most of the content can be found in Audiokinetic’s official resources.
Bienvenidos a la cuarta parte. En esta entrega, vamos a tratar unos de los temas que quizás es más diferente en el audio interactivo y supone un cambio de paradigma respecto al audio lineal. Se trata del posicionamiento y panorama de los sonidos de nuestro juego.
Si lo piensas, en los medios lineales como cine o música, la perspectiva sonora siempre es la misma. Si decides que una guitarra va a estar ligeramente a la derecha en el panorama, esta será su posición para todos los oyentes (siempre y cuando sus altavoces o auriculares estén correctamente configurados).
En cambio, en videojuegos tenemos muchas veces el caso de un personaje que anda libremente por un entorno 2D o 3D. ¿Cómo sabemos entonces de donde tendría que venir el sonido si el personaje no para de moverse?
Listeners & Emitters
Es por esto que los juegos usan estos dos conceptos que paso a explicarte. Por un lado, los listeners (“escuchadores”) son objetos que usa el motor de juego para determinar cuál es el punto en el espacio del juego que está recibiendo el audio. Son como unas orejas o micrófonos virtuales que van a recoger el sonido del entorno. Habitualmente el listener se coloca justo en la cámara que representa la visión del personaje, al menos en juegos en primera persona. Para juegos en tercera persona, es posible situar el listener en el propio modelo del personaje o bien el la cámara que estarás algo más atrás, esto depende del juego en concreto y su estilo.
Por otro lado, los emitters (“emisores”) hacen justo lo que te estás imaginando: hacer de puntos de propagación de un sonido en el motor del juego. En términos de Wwise, se suelen asociar concretamente con un evento. No todos los eventos usan un emitter pero normalmente todos los emitter conectan con uno o más eventos.
¿Por qué es esto útil? Porque el juego está constantemente calculando la distancia en 3 las coordenadas entre todos los emitters y el listener (que sólo suele ser uno). Esta distancia es transmitida desde el juego hasta Wwise en tiempo real.
Como diseñadores, nosotros no podemos controlar este constante flujo de información entre emitters y listeners pero sí que podemos determinar cómo estos datos vas a afectar a cada objeto para que, por ejemplo, un sonido se siga oyendo pese a estar bastante lejos (por que quizás es importante).
A tener en cuenta
Antes de entrar en harina es importante que tengas en cuenta que Wwise cambió en 2018 la forma en la que entiende y configura el posicionamiento y panorama. Lógicamente, yo voy a explicarlo de la nueva forma pero ten en cuenta que si encuentras información anterior a 2018 es posible que no se aplique a versiones más modernas de Wwise.
En todo caso, y para ayudar a los que quizás ya hayan usado Wwise antes y estén usando este tutorial como refresco, a medida que nos encontremos con algunas de estas diferencias conceptuales, mencionaré cómo se entendían antes y cómo se entienden ahora. Puedes encontrar la info completa sobre este cambio en este artículo oficial (en inglés).
ShareSets & Attenuations
De la misma manera que en la entrega anterior introducimos los GameSyncs, vamos ahora a utilizar la siguiente pestaña que la Designer Layout nos ofrece: “ShareSets”. En general, los ShareSets son un conjunto de configuraciones que cómo su propio nombre indica, se pueden compartir entre distintos elementos de nuestro proyecto. A diferencia de los GameSyncs, que conectan directamente con distintas variables del propio juego, los ShareSets funcionan internamente en Wwise en respuesta a diferentes condiciones y estados en el juego.
Uno de estos ShareSets se llama “Attenuation” y nos permite determinar cómo la distancia entre un listener y un emitter controla el volumen del sonido además de otros parámetros (como el pitch, un filtro paso alto o un ecualizador completo). En otras palabras, nos permite personalizar las curvas de atenuación de cada sonido para que podamos determinar cómo de rápido cae el nivel sonoro de un emisor a medida que nos alejamos de él en el entorno 3D.
Creemos entonces una curva de atenuación para Cube. Puedes continuar con el proyecto de Wwise que deberías tener de la parte anterior de este tutorial.
Desde el Layout Designer, selecciona la pestaña ¨ShareSets¨ y crea una nueva curva de atenución. En principio, puedes llamarla como quieras como por ejemplo, “atenuacion_objetos”.
Introducir un sonido en el espacio 3D
Vamos a poner en funcionamiento esta curva creando nuestro primer sonido con posicionamiento en el espacio 3D. Anteriormente, Wwise llamaba a estos sonidos simplemente ”3D” pero esto ya no es exactamente el caso. Explicaré un poco más sobre esto en breve.
Por ahora, necesitamos considerar qué sonido debería tener un posicionamiento fijo. Si lo piensas, desde la perspectiva del propio jugador, no hemos necesitado hacer esto hasta ahora por que los sonidos que hemos usado anteriormente, como pasos o la escopeta siempre iban a sonar en el mismo sitio con respecto al jugador. En otras palabras, son sonidos cuyo punto de origen se mueve con el jugador por lo que el emitter y el listener nunca se acercan ni se alejan entre sí, o dicho de otra manera su distancia relativa se mantiene constante.
¿Pero qué ocurre si necesitamos que un sonido tenga su propio posicionamiento independiente del jugador? Anteriormente, Wwise llamaba a estos sonidos “3D” pero son actualmente denominados “listener relative”. Es decir, estos son los sonidos en los que el listener y el emitter pueden acercarse o alejarse, tienen un posicionamiento relativo.
Veámoslo en acción. Vamos a introducir un sonido para el teletransportador que hay en Cube. Buscamos un sonido constante que indique al jugador dónde va a poder encontrar estos portales. Puedes usar este sonido o cualquiera de tu librería. Importa el sonido en un SFX Object y llámalo cómo quieras.
El sonido que te enlazo lo grabé yo mismo con un micrófono que registra campos electro magnéticos y usé un microondas como fuente. Si lo utilizas, vas a necesitar ir al Source Editor (doble click en el nombre del propio archivo de audio importado, no el SFX Object). Una vez en el editor, debes elegir un área del sonido que te guste y limitar el sonido a esa área usado los cuadrados blancos de la zona inferior. Luego, en el “Sound Property Editor” debes poner el sonido en loop y yo he ajustado un poco el volumen y pitch. Juega un poco con todos los parámetros hasta obtener algo que te guste.
Una vez listo, verás una pestaña llamada “Positioning” en el Property Editor. Aquí es donde vamos a poder determinar cómo se comportará el lugar de origen del sonido. Debes tener en cuenta que nosotros desde Wwise no podemos colocar un sonido en el espacio 3D del juego, es decir, no controlamos donde está el emisor, sólo podemos recibir información de este y decidir qué hacer con ella.
Es el equipo de programación y diseño los encargados de colocar el emitter en su lugar correcto, en este caso donde haya portales teletransportadores. Como decía antes, lo que sí es nuestro trabajo es detemrinar cómo esta distancia va a afectar al sonido.
Usando la pestaña de posicionamiento
Veamos qué opciones nos ofrece esta pestaña, voy de arriba a abajo. Para empezar, verás que podemos elegir qué porcentaje de sonido queremos enviar al canal central en una configuración surround. Esto por ahora no nos atañe pero es bueno que sepas que esto se puede controlar aquí.
A continuación, “Speaker Panning” nos permite decidir cómo va se va a dictar el posicionamiento de un determinado sonido. La opción por defecto, “Direct Assignment” va a obtener la posición del sonido de la relación entre el emitter y el listener, luego esta es la opción que nos interesa para un sonido 3D. Por otro lado, “Balance-Fade” va a ignorar cualquier emitter y listener y podremos determinar de qué lugar del campo estéreo o surround queremos que provenga nuestro sonido. Como podrás comprender esto sólo va a ser aplicable a sonidos cuya posición no cambia con el movimiento del jugador, es decir, los sonidos que tradicionalmente se han llamado “2D”. Veremos más tarde cómo funcionan estos sonidos.
“Listener Relative Routing” puede ser algo confuso. En general, necesitas que esta opción esté activa para casi todos los sonidos de tu juego ya que así te aseguras de que Wwise tenga en cuenta donde está el emitter y el listener a la hora de calcular todo lo relacionado al sonido. Hay situaciones en las que quizás necesites desactivar esta opción pero por ahora la podemos dejar tal cual casi en todos los casos.
“3D Spatialization” es donde podemos realmente decidir que nuestro sonido sea 3D. Por defecto, vemos “None” que implicaría que no hay ningún tipo de posicionamiento 3D. Esta es la mejor opción para elementos cuyos emitters no se mueven con respecto al listener (jugador) como por ejemplo la música no diegética del juego, el sonido ambiente o los pasos.
En nuestro caso, y para el sonido del teletransporte, sí que queremos posicionamiento 3D por lo que vamos a seleccionar “Position + Orientation”. Esto significa que Wwise no sólo tendrá en cuenta la distancia entre la posición del emitter y del listener sino también su orientación, es decir si el jugador está mirando hacia el portal, en la dirección contraria o cualquier estado intermedio.
La siguiente opción, “Speaker Panning / 3D Spatialzation Mix” nos permite combinar ambas opciones, es decir, nos da un crossfade entre el sonido posicionado en 3D dentro del motor de juego y uno cuyo origen viene determinado por la asociación a un determinado lugar en el campo estéreo o surround. Esta opción puede ser útil cuando un sonido es muy importante y no queremos que se pierda en la mezcla incluso cuando el jugador está muy lejos de la fuente del sonido.
Y ya hemos llegado al lugar donde podemos definir qué curva de atenuación queremos usar. Como puedes ver, podemos seleccionar “Attenuation” si queremos que nuestro sonido caiga en volumen a medida que el jugador se aleja del emisor. Como podrás imaginar, esto es lo que queremos que pase para la mayoría de los objetos del entorno 3D.
Ajustando nuestra curva de atenuación
Lo primero que necesitamos es hacer click en el icono con flechas y elegir la curva que creamos antes, “atenuación_objetos”. Una vez hecho esto, haz click en “Edit…” para configurar la curva.
La pantalla que encontramos aquí quizás te suene de cuando vimos los RTPC en la entrega anterior. De hecho, es básicamente la misma con la diferencia de que el parámetro que se controla es siempre la distancia entre el emisor y el listener y esto no se puede cambiar.
Puedes empezar por reproducir el sonido y cambiar la distancia con la bandera del gráfico. Cómo puedes ver, el nivel cae a medida que nos alejamos pero ¿cómo sabemos cuánto cambio es mucho o es poco? Para ello debemos tener en mente cómo funcionan las unidades de distancia en nuestro juego. Esto depende de cada caso, pero en Cube una unidad equivale a unos 0.25 metros aproximadamente. Esto te puede dar una idea aproximada pero la mejor manera es quizás probar en el propio juego hasta encontrar una curva que funcione. Esto no sólo implica que la sensación de distancia sea realista sino también que sea útil respecto a cómo funciona el juego. Es decir, si es vital para el jugador poder oír los teletransportadores para guiarse por el mapa en medio de una batalla, quizás nos convenga que el nivel no caiga demasiado rápido al alejarse de ellos.
Otro concepto importante a tener en cuenta es la distancia máxima, que puedes ver en la parte central dercha de esta ventana. Esta será la distancia a la que nuestro objeto ya no se escucha, es decir el nivel cae a cero. Es importante ajustar este valor bien por que nos va a dictar la escala de nuestra curva. En nuestro caso 50 es un buen valor ya que representaría unos 12.5 metros.
Ahora podemos alterar nuestra curva hasta encontrar una que nos suene bien a medida que alteramos la distancia. Muchas veces es una buena idea que el nivel no siempre igual de rápido sino más rápido al principio de forma que sólo oigamos el máximo nivel cuando estemos realmente cerca. Por supuesto, no hay reglas fijas en esto y experimentando es cómo puedes encontrar los valores que funcionan en cada caso.
Algo que también puedes probar es hacer que el filtro paso bajos también reaccione con la distancia de forma que perdamos parte de los agudos cuando nos alejamos del sonido. Esto es una buena forma de imitar lo que ocurre en la realidad, donde el aire puede absorber parte de estos agudos si el sonido recorre una cierta distancia.
Algo a tener en cuenta es que es posible que una vez ya tengamos nuestras curvas listas, más tarde durante el desarrollo del juego, cambie la escala que estábamos usando en las distancias y ahora nuestra curva es demasiado corta y larga. No es necesario re-hacer la curva a mano. Basta con cambiar la distancia máxima (por ejemplo cámbiala de vuelta a 100) para que la curva se re-escale.
Una vez listas nuestras curvas de distancia (y recuerda que luego las probaremos en el juego para poder hacer más ajustes) nos queda determinar cómo el ángulo de incidencia va a alterar el sonido. Para ello activamos el cono de atenuación (“Cone Attenuation”) y vemos que en el gráfico circular aparecen 3 zonas con distintos tonos de gris. Cuánto más oscuro es el gris, mayor es el ángulo entre emisor y listener siendo 180 el máximo, es decir en este caso el emisor (teletransporte) está detrás del listener (jugador). Puedes cambiar cómo de amplias o estrechas son estas tres zonas con los controles “Inner angle” y “Outer angle”.
Algo muy a tener en cuenta es que quizás pienses que en el gráfico el centro representa el listener (jugador) pero es justo al contrario, lo cual puede ser bastante confuso. El centro representa al emisor (que estaría estático en este gráfico) y el círculo blanco que podemos mover sería el listener (jugador), de forma que la línea dorada que sale de él nos dice hacia donde mira. Si intentas mover este círculo blanco verás cómo el ángulo y también la distancia afectan al sonido pero date cuenta de que no se está vambiando el panorama. Es decir si colocas el jugador a la derecha del emisor vas a poder oir cómo la distancia y el ángulo cambia el sonido pero el sonido no vendrá de la izquierda (que es donde estará el emisor). En otras palabras, este gráfico llamado “Attenuation Preview” es eso, una previsualización de la atenuación, no del panorama.
Ahora que tenemos claro cómo funciona, vamos a configurar el “Cone Attenuation”. El valor “Max attenuation” nos dirá cuánto cae el nivel cuando el jugador está totalmente detrás del emisor, es decir a 180º. -6dB es el valor por defecto y nos servirá por ahora pero puedes probrar otros. Por otro lado, también podemos usar el ángulo para afectar a un filtro paso alto y uno paso bajos. Prueba a añandir 20 como valor en el filtro paso bajos y escucha el resultado a medida que mueves el círculo blanco que representa al jugador. Verás cómo manteniendo la misma distancia pero cambiando el ángulo, el sonido se amortigua y cae en volumen cuando está detrás lo cual de nuevo imita a lo que ocurre en la vida real.
Probando el sonido del teletransporte
A estas alturas ya sabes lo que necesitamos hacer para integrar un sonido nuevo en el juego. Tenemos ya el SFX Object configurado y listo pero aún nos falta el evento. Crea un evento llamado “Emitter_Teleport” y añádele una acción que reproduzca el sonido que acabamos de crear. Si tienes dudas, consulta entregas anteriores de esta serie.
Ahora sólo queda que añadas el evento al SoundBank (dentro del layout SoundBank) y generes un nuevo banco. Prueba ahora cómo el sonido se comporta cuando te alejas y te acercas. Intenta también ponerte de espaldas al portal para ver cómo eso afecta al sonido. Si vuelves a Wwise para ajustar la curva de automatización, recuerda que debes crear de nuevo el banco para oír los cambios.
¿Por qué usar curvas?
Quería remarcar que cuando hemos configurado la atenuación del teletransporte, no estábamos realmente cambiando los parámetros del SFX Object ni del evento si no de la curva de atenuación en sí que puedes encontrar en la pestaña “SharedSets”. Esto es tremendamente útil por que cuando continuemos trabajando en el juego podremos aplicar la misma curva a otros objetos como una cascada, una radio o un frigorífico. En general, nos servirá para cualquier elemento que queramos que tenga una curva similar.
Y si necesitamos que algún otro objeto tenga una curva de atenuación diferente (como por ejemplo con una caída en nivel más acusada) no tenemos más que crear una curva nueva y aplicarla a los elementos que deseemos.
Speaker Panning (antes conocidos como sonidos 2D)
Ya hemos aprendido a trabajar con sonidos que poseen un emitter situado en el entorno 3D del juego. Esto es muy útil pero no siempre queremos que un sonido provenga de un punto concreto. El ambiente o la música pueden ser ejemplos de eventos sonoros que no tendrán un emitter concreto sino que su lugar en el panorama surround se definirá de una forma similar a cómo lo hacemos en un DAW tradicional.
Wwise llama a este método de trabajo “Speaker Panning”, dando a entender que lo único que definimos es de qué altavoz o altavoces del entorno surround o estéreo provendrá nuestro sonido. Vamos a poner esto en práctica con un ambiente para nuestro juego. Crea dos nuevos SFX Object con este y este sonido u otros que prefieras.
Vamos a usar ambos sonidos para crear un ambiente general. Ve al primero de los sonidos y haz click en la pestaña “Positioning”. Debemos asegurarnos que “3D Spatialization” está configurado como “None” ya que no queremos ningún tipo de posicionamiento 3D del sonido. En “Speaker Panning” vemos que la opción por defecto es “Direct Assignement”. Esto significa que el sonido va a quedar posicionado según se determine mediante la relación emitter-listener.
Si en cambio eliges “Balance-Fade” verás que podemos hacer click en “Edit” para abrir una ventana donde podemos panear el sonido de una forma similar a cómo haríamos en un DAW. Como ejemplo, digamos que paneamos este sonido ligeramente a la izquierda como en la ilustración y un poco hacia atrás. Haz algo similar con el segundo sonido pero esta vez colócalo hacia la derecha.
Una vez listo, necesitamos un evento para disparar este ambiente que hemos creado. Podemos usar el evento “Map_Loaded” que creamos en la parte III. Re-construye la build y prueba el resultado. Quizás tengas que ajustar niveles un poco para equlibrarlo todo.
Ahora que tenemos un ambiente básico podríamos añadir algunos elementos que sí estén posicionados alrededor del jugador, en 3D. Por ejemplo, podríamos tener algunos pájaros. ¿Pero cómo podemos hacer esto si no hay emitters para los pájaros en el juego?
3D con posicion automatizada
Si vuelves a nuestro SFX Object del teletransportador y haces click en la pestaña ¨Positioning”, verás que nos hemos dejado una sección al final llamada “3D Position”. Aquí vemos que se nos ofrecen 3 opciones:
Emitter: Esto significa que la posición del sonido viene definida por el propio juego, es decir, donde el juego tenga posicionado el emitter. Esta es la configuración por defecto y la usarás en la mayoría de casos.
Emitter with Automation: Wwise va a usar la posición del emitter y luego además le va a aplicar una cierta variación o movimento que nosotros configuremos. Útil cuando quieres darle algo de movimiento y randomización a ciertos sonidos puntuales.
Listener with Automation: En este caso, Wwise va a ignorar al emisor (si es que lo hay) y simplemente usará la posición del listener. Esto es muy útil para sonidos que no están posicionados en el entorno 3D del juego (luego, no tienen emitter) y queremos que provengan de distintos lugares alrededor dle jugador.
Vamos a probar a usar esto para que nuestro sonido ambiente tenga más variedad e inmersión. Descarga este sonido y añádelo como SFX Object. Puedes también usar cualquier otro sonido pero asegúrate de que está aislado más o menos bien del ambiente en el que se grabó. Ahora ve al “Source Editor” y elige alguno de los sonidos. Usa los fades para que entrada y salida del sonido sea algo más suave.
Una vez listo, duplica este Sfx Object y repite la misma operación pero usando un graznido diferente. Intenta tener 3-4 diferentes. Una vez listo empaqueta estos objetos en un random container seleccionando todos y haciendo click en “New Parent - Randon Container”.
Vamos ahora al random container y tenemos que configurarlo para que actúe de la forma que deseamos. Esto te va a servir para repasar algunos concepto y quizás aprender alguno nuevo. Primero, vamos a encargarnos de que cada vez que se dispare nuestro container, este aparezca en un lugar al azar alrededor del jugador. Una de las maneras en las que podemos hacer esto es mediante la automatización 3D que comentamos previamente. Ve a la pestaña “Positioning” (dentro del random container).
Debemos definir la “3D Spatialization” como “Position” y la “3D Position” como “Listener with automation” ya que queremos que el sonido se distribuya en disintos lugares alrededor del jugador. Una vez hecho esto, hacemos click en “Automation”. Verás que puedes crear una serie de posibles caminos (“paths”), que el sonido seguirá tras ser disparado, pudiendo elegir entre ellos al azar. Crea unos 4-5 “paths” diferentes y haz que cada uno tenga un lugar diferente alrededor del jugador. Estos pueden ser simples puntos o líneas por las que el sonido se moverá durante su duración. También puedes alterar la altura del sonido (eje Z) para que los sonidos provengan de arriba u abajo pero en nuestro caso no es necesario.
Verás que debajo de la lista de “paths” aparece una sección llamada “Random Range”. Esta nos permite añadir cierta randomización a las coordenadas de nuestro sonido en los ejes que ves. Prueba a poner un poco en cada uno de tus “paths”. Left/Right es la que notarás más. En la sección “Play Type”, escoge “Random” y “Pick new path when sound starts” para que cada vez que un nuevo sonido sea llamado, este use un path diferente al azar.
Por último, nos queda definir cuándo queremos que nuestros pájaros se oigan. Fíjate en la configuaración que he usado en la imagen inferior. El “Initial Delay” me ayuda a que el sonido no suene nada más inciar la partida pero además he randomizado esos 3 segundos de delay para que puedan ser -1 o + 6 segundos. Esto quiere decir que cada vez que iniciemos el juego, el primer pájaro sonará entre el segundo 2 y el 9 lo cual nos da una buena variabilidad.
Por otro lado, he elegido un “Play Mode” continuo, con la opción “Loop” activada. Esto es por que queremos que nunca se dejen de oir pájaros durante toda la partida. El problema de esto es que estarían constantemente sonando por lo que necesitamos usar una “Transition” de tipo “Delay”. Con esto conseguimos que al menos haya 5 segundos entre un sonido y otro. Como puedes ver, yo además he randomizado este delay para que pueda ser entre 2 y 11 segundos.
Con toda esta configuración, conseguimos que los pájaros suenen con una frecuencia randomizada pero controlable y cada que suenen aparezcan en un lugar diferente del entorno estéreo/surround.
Ya sólo nos quedaría añadir este contenedor al evento que estamos usando para el ambiente, re-construir y probar el resultado en Cube. Te animo a que pruebes distintos ajustes hasta encontrar la que te guste.
Sumario
En esta tercera parte, hemos visto todo lo relacionado a panorama y posicionamiento. Si tienes dudas o cualquier problema, puedes escribirme a contactme [ arroba ] javierzumer.com. Mientras tanto, dejo por aquí un glosario con todos los conceptos que he ido introduciendo en esta parte. !Hasta la próxima!
Listener: Objeto que vive en el motor de juego (no en Wwise) y define donde es el punto de escucha para el jugador.
Emitter: Objeto que también vive en el motor de juego y que funciona como el emisor de un determinado evento sonoro.
ShareSet: Pestaña en el Layout Designer que agrupa varios objetos que son compartidos entre los diversos elementos de nuestro proyecto de Wwise.
Attenuation: Tipo de ShareSet que nos permite aplicar una curva de atenuación a cualquier objeto de nuestro proyecto. Esto nos permite controlar cómo la distancia entre su emitter asociado y el listener afecta a distintos parámetros sonoros.
Pestaña Positioning: Dentro de la ventana “Property Editor” donde podemos modificar todos los parámetros relacionados con un determinado objeto, esta pestaña todo lo que concierne a panorama y posicionamiento.
Speaker Panning: Dentro de la pestaña de posicionamiento, esta opción nos deja elegir entre:
Direct Assignment: La posición de un sonido se calcula a través de la distancia entre emitter y listener. (sonido 3D)
Balance-Fade: Se ignoran emitters y listeners y la posición se puede determinar como un balance entre los distintos canales del campo estéreo o surround. (sonido 2D)
3D Position: Opción que nos permite posicionamientos avanzados y automatizables que pueden depender del emiter o del listener.