Preguntas frecuentes sobre el audio web

En los últimos meses, la API de Web Audio de WebKit se convirtió en una plataforma atractiva para los juegos y las aplicaciones de audio en la Web. A medida que los desarrolladores se familiarizan con el proceso, escucho preguntas similares que surgen repetidamente. El objetivo de esta actualización rápida es abordar algunas de las preguntas frecuentes para que tu experiencia con la API de Web Audio sea más placentera.

P.: Ayuda, no puedo emitir sonidos.

R: Si eres nuevo en la API de Web Audio, consulta el instructivo para comenzar o la receta de Eric para reproducir audio según la interacción del usuario.

P.: ¿Cuántos contextos de audio debo tener?

R.: Por lo general, debes incluir una etiqueta AudioContext por página, y un solo contexto de audio puede admitir muchos nodos conectados a él. Si bien puedes incluir varios AudioContexts en una sola página, esto puede generar un éxito de rendimiento.

P.: Tengo un AudioBufferSourceNode que acabo de reproducir con noteOn(). Quiero volver a reproducirlo, pero noteOn() no hace nada. Ayuda,

R.: Una vez que termina la reproducción de un nodo de origen, no puede reproducir más. Para volver a reproducir el búfer subyacente, debes crear un nuevo AudioBufferSourceNode y llamar a noteOn().

Aunque volver a crear el nodo fuente puede parecer ineficiente, estos nodos están muy optimizados para este patrón. Además, si mantienes un handle para AudioBuffer, no necesitas realizar otra solicitud al activo para que vuelva a reproducir el mismo sonido. Si necesitas repetir este patrón, encapsula la reproducción con una función auxiliar simple, como playSound(buffer).

P.: Cuando se reproduce un sonido, ¿por qué hay que crear un nuevo nodo fuente cada vez?

R.: La idea de esta arquitectura es separar el recurso de audio del estado de reproducción. En una analogía con el tocadiscos, los búferes son análogos a los registros y las fuentes a los cabezales de reproducción. Debido a que muchas aplicaciones involucran varias versiones del mismo búfer que se reproducen simultáneamente, este patrón es esencial.

P.: ¿Cómo puedo procesar el sonido de las etiquetas audio y video?

R: MediaElementAudioSourceNode está en proceso. Cuando esté disponible, funcionará de la siguiente manera (se agregará un efecto de filtro a una muestra que se reproduce mediante la etiqueta de audio):

<audio src="sounds/sample.wav" controls>
var audioElement = document.querySelector('audio');
var mediaSourceNode = context.createMediaElementSource(audioElement);
mediaSourceNode.connect(filter);
filter.connect(context.destination);

El seguimiento de esta función se realiza en este informe. Ten en cuenta que, en esta configuración, no es necesario llamar a mediaSourceNode.noteOn(), ya que la etiqueta de audio controla la reproducción.

P.: ¿Cuándo puedo escuchar el sonido de un micrófono?

R: La parte de entrada de audio se implementará como parte de WebRTC mediante getUserMedia y estará disponible como un nodo fuente especial en la API de Web Audio. Funcionará junto con createMediaElementSource.

P.: ¿Cómo puedo verificar cuando terminó de jugar un dispositivo AudioSourceNode?

R: Actualmente, debes usar un temporizador de JavaScript, ya que la API de Web Audio no admite esta funcionalidad. El siguiente fragmento del instructivo Cómo comenzar a utilizar la API de Web Audio es un ejemplo de esto en acción:

// Assume source and buffer are previously defined.
source.noteOn(0);
var timer = setTimeout(function() {
    console.log('playback finished');
}, buffer.duration * 1000);

Hay un error abierto para que la API de Web Audio implemente una devolución de llamada más precisa.

P.: Los sonidos de carga hacen que se bloquee todo el subproceso de IU y la IU deja de responder. ¡Ayuda!**

R.: Se usa la API de decodeAudioData para la carga asíncrona a fin de evitar bloquear el subproceso principal. Consulta este ejemplo.

P.: ¿Se puede usar la API de Web Audio para procesar sonidos más rápido que en tiempo real?

R.: Sí, estamos trabajando para encontrar una solución. Mantente en contacto.

P.: Creé una app increíble con la API de Web Audio, pero cada vez que la pestaña en la que se está ejecutando se ejecuta en segundo plano, ¡suena muy extraño!

R: Probablemente se debe a que estás usando setTimeouts, que se comportan de manera diferente si la página se ejecuta en segundo plano. En el futuro, la API de Web Audio podrá devolver la llamada en momentos específicos mediante el temporizador interno del audio web (atributo context.currentTime). Para obtener más información, consulta esta solicitud de función.

En general, te recomendamos detener la reproducción cuando la app pase a segundo plano. Puedes detectar cuándo una página pasa a segundo plano con la API de visibilidad de páginas.

P.: ¿Cómo puedo cambiar el tono de un sonido con la API de Web Audio?

A: Cambiar el playbackRate en el nodo de origen

P.: ¿Puedo cambiar de tono sin cambiar la velocidad?

R: La API de Web Audio podría tener un PitchNode en el contexto de audio, pero es difícil de implementar. Esto se debe a que en la comunidad de audio no existe un algoritmo directo de cambio de tono. Las técnicas conocidas crean artefactos, especialmente en casos en los que el cambio de tono es grande. Hay dos tipos de enfoques para abordar este problema:

  • Algoritmos de dominio temporal, que causan artefactos de eco de segmentos repetidos.
  • Técnicas de dominio de frecuencia, que causan artefactos de sonido reverberantes.

Si bien no hay un nodo nativo para realizar estas técnicas, puedes hacerlo con un JavaScriptAudioNode. Este fragmento de código puede servir como punto de partida.

P.: ¿Cómo puedo crear un objeto AudioContext con la tasa de muestreo que elija?

R.: Por el momento, no hay asistencia para esto, pero lo estamos investigando. Consulta esta solicitud de función.

Si tienes más preguntas, no dudes en hacerlas en StackOverflow con la etiqueta web-audio.