Controlador de sonido JavaScript

En este artículo vamos crear nuestro propio controlador de sonido JavaScript para cargar sonidos y reproducirlos en nuestras aplicaciones y videojuegos web. El control del sonido en el desarrollo de juegos y aplicaciones interactivas es fundamental para dar mayor realismo a la interacción del usuario con el software.

El sonido es un aspecto que suele pasar desapercibido pero que resulta importantísimo para guiar al usuario en sus acciones. Un simple «bip» al pulsar un botón, un efecto sonoro de colisión, una explosión o un chirriar de una puerta son efectos sonoros que, sin ellos, las acciones visuales de la pantalla quedarían vacías.

JavaScript proporciona un objeto AUDIO como controlador de sonido, sin embargo, tiene limitaciones que debemos solucionar. En este artículo vamos a crear un controlador de sonido JavaScript mediante una clase que podrá ser instanciada en nuestras aplicaciones. Esta clase nos permitirá controlar el sonido de manera que podamos cargar, reproducir, detener, pausar o repetir todos los sonidos necesarios durante la ejecución del programa.

Clase para controlar el sonido

Nuestra clase audioClass, consiste en una implementación elegante y eficiente para controlar el sonido con JavaScript. Además de utilizar las propiedades nativas del objeto AUDIO de JavaScript, vamos a añadirle unas cuantas funciones adicionales que vamos a necesitar en nuestros juegos y aplicaciones. Veamos cómo funciona y qué funciones ofrece nuestro controlador de sonido JavaScript:

class audioClass {
  constructor() { 
    this.item = [];
    this.library = [];
  }
  get(sonido) {
    return this.library[sonido];
  }  
  stopAll() {
    for(let sonido in this.library) this.stop(sonido);
  }
  allReady() {
    for(let sonido in this.library) {
      if (this.library[sonido].readyState != 4) return false;
    }
    return true;
  }  
  load(sonido, url, volume, loop) {
    this.library[sonido] = new Audio(url);
    if (loop != undefined) this.library[sonido].loop = loop;    
    if (volume != undefined) this.library[sonido].volume = volume;
  }
  volume(sonido, value) {
    this.library[sonido].volume = value;
  }
  loop(sonido, value) {
    this.library[sonido].loop = value;
  }
  play(sonido) {
    this.library[sonido].play();
  }
  pause(sonido) {
    this.library[sonido].pause();
  } 
  stop(sonido) {
    this.library[sonido].pause();
    this.library[sonido].currentTime = 0;
  }
  restart(sonido) {
    this.stop(sonido);
    this.play(sonido);  
  }  
  clone(sonido, delay) {
    if (!this.library[sonido].time) this.library[sonido].time = Date.now() - delay;
    if (Date.now() - this.library[sonido].time < delay) return;
    this.library[sonido].time = Date.now(); 
    this.item.push(this.library[sonido].cloneNode());
    this.item[this.item.length-1].volume = this.library[sonido].volume;   
    this.item[this.item.length-1].loop = this.library[sonido].loop;   
    this.item[this.item.length-1].play();    
    for(let i=0; i<this.item.length; i++) {
      if (this.item[i].ended) this.item.splice(i, 1);
    }
  }
}

Codigo del controlador de sonido

Con nuestra clase audioClass en JavaScript estamos preparados para gestionar una biblioteca de sonidos, permitiendo cargar, reproducir, pausar, detener, ajustar el volumen y clonar sonidos. Vamos a explicar cada una de las funciones de nuestro controlador de sonido JavaScript:

  • Constructor: Se crean 2 Arrays que serviran para trabajar con los sonidos. En (item) se almacena las instancias clonadas de los sonidos para permitir múltiples reproducciones simultáneas. El Array (library) actúa como biblioteca de sonidos, almacenando los objetos Audio que cargamos.
  • get(sonido): Devuelve el objeto AUDIO de la biblioteca correspondiente al parámetro (sonido) proporcionado. Este parámetro es el nombre que le hemos dado al sonido al cargarlo.
  • stopAll(): Detiene la reproducción de todos los sonidos en la biblioteca. Es útil para detenerlo todo independientemente de los sonidos que tengamos activados.
  • allReady(): Verifica si todos los sonidos en la biblioteca están listos para reproducirse. Devuelve true si todos los sonidos están listos cuando su (readyState es 4), false en caso contrario.
  • load(sonido, url, volume, loop): Esta función carga un nuevo sonido en la biblioteca desde una URL y opcionalmente ajusta su volumen y si debe reproducirse en bucle.
    • sonido: Nombre del sonido en la biblioteca.
    • url: URL del archivo de audio.
    • volume: Volumen inicial del sonido.
    • loop: Booleano indicando si el sonido debe repetirse en bucle.
  • volume(sonido, value): Ajusta el volumen del sonido especificado por sus parámetros.
    • sonido: Nombre del sonido en la biblioteca.
    • value: Nuevo valor de volumen de 0.00 a 1.00
  • loop(sonido, value): Configura si el sonido debe repetirse en bucle en base a sus parámetros:
    • sonido: Nombre del sonido en la biblioteca.
    • value: Booleano indicando si debe repetirse en bucle.
  • play(sonido): Reproduce el nombre del (sonido) especificado en nuestra biblioteca de sonidos
  • pause(sonido): Pausa la reproducción del (sonido) especificado en nuestra biblioteca de sonidos.
  • stop(sonido): Detiene la reproducción del (sonido) especificado en nuestra biblioteca de sonidos y reinicia su tiempo a cero.
  • restart(sonido): Reinicia la reproducción del (sonido) especificado en nuestra biblioteca de sonidos desde el principio.
  • clone(sonido, delay): Esta función clona el (sonido) especificado en nuestra biblioteca de sonidos para permitir múltiples reproducciones simultáneas con un retraso mínimo (delay) entre cada clon. Su funcionamiento es el siguiente:
    • Si el sonido especificado no tiene una propiedad (time), se inicializa con el tiempo actual menos el (delay). Esto asegura que el primer clon pueda ser creado de inmediato.
    • Comprueba si el tiempo transcurrido desde la última clonación es menor que el (delay) especificado. Si es así, sale de la función, evitando la clonación prematura del sonido.
    • Actualiza la propiedad (time) del sonido al tiempo actual para marcar el momento en que se realizó la clonación.
    • Crea una copia (clon) del nodo de audio original y lo agrega al array (item), que almacena todos los clones.
    • Establece el volumen del clon para que coincida con el del sonido original.
    • Establece la propiedad (loop) del clon para que coincida con la del sonido original.
    • Inicia la reproducción del clon del sonido.
    • Recorre el array (item) y elimina los sonidos clonados que han terminado de reproducirse (ended es true). Esto evita que el array crezca indefinidamente con sonidos finalizados.

Uso del controlador de sonido JavaScript

Supongamos que tienes un sonido de disparo que necesitas reproducir cada vez que el jugador presiona el botón de disparo. Con la función clone(), puedes asegurarte de que cada disparo suene claramente, incluso si se disparan muy rápidamente uno tras otro. Si no clonáramos el sonido estaríamos iniciando cada vez el mismo sonido obteniendo un resultado muy malo.

En esta clase puedes añadir más funcionalidades a gusto de cada uno, en mi caso, he programado lo que habitualmente necesito en mis videojuegos. Lo interesante del controlador de sonido es ver cómo a partir del objeto nativo AUDIO de JavaScript, podemos controlar los sonidos a nuestro antojo.

Con la clase audioClass obtenemos una interfaz robusta para manejar una biblioteca de sonidos en una aplicación JavaScript, con funciones para cargar, reproducir, pausar, detener, ajustar el volumen, reiniciar, y clonar sonidos. Esto es especialmente útil en aplicaciones interactivas como videojuegos donde el control preciso y la eficiencia en la gestión de audio son cruciales.

Si estás interesado en la creación de videojuegos en JavaScript también te puede intersar el artículo sobre cómo controlar el teclado con JavaScript.

¡ Espero que este artículo sea de vuestro interés !

Deja un comentario