En los últimos meses, la API de Web Audio de WebKit se convirtió en una plataforma atractiva para juegos y aplicaciones de audio en la Web. A medida que los desarrolladores se familiarizan con él, escucho que surgen preguntas similares repetidamente. Esta breve actualización es un intento de abordar algunas de las preguntas más frecuentes para que tu experiencia con la API de Web Audio sea más agradable.
P.: Ayuda, no puedo hacer sonidos.
R.: Si no conoces 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 debería tener?
R.: Por lo general, debes incluir un AudioContext por página, y un solo contexto de audio puede admitir muchos nodos conectados a él. Aunque puedes incluir varios objetos AudioContext en una sola página, esto puede afectar el rendimiento.
P.: Tengo un AudioBufferSourceNode que acabo de reproducir con noteOn() y quiero volver a reproducirlo, pero noteOn() no hace nada. ¡Ayuda!
R.: Una vez que un nodo fuente termina de reproducirse, no puede reproducirse más. Para volver a reproducir el búfer subyacente, debes crear un nuevo AudioBufferSourceNode y llamar a noteOn().
Si bien volver a crear el nodo fuente puede parecer ineficiente, los nodos fuente están muy optimizados para este patrón. Además, si mantienes un identificador en AudioBuffer, no necesitas realizar otra solicitud al recurso para volver 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é es necesario crear un nodo fuente nuevo cada vez?
R.: La idea de esta arquitectura es desacoplar el recurso de audio del estado de reproducción. Si tomamos la analogía de un tocadiscos, los búferes son análogos a los discos y las fuentes a los cabezales de reproducción. Dado que muchas aplicaciones implican la reproducción simultánea de varias versiones del mismo búfer, este patrón es esencial.
P.: ¿Cómo puedo procesar el sonido de las etiquetas audio y video?
R.: MediaElementAudioSourceNode está en desarrollo. Cuando esté disponible, funcionará de la siguiente manera (agregando un efecto de filtro a una muestra que se reproduce a través de 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);
Se hace un seguimiento de esta función en este crbug. 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 obtener sonido de un micrófono?
R.: La parte de entrada de audio se implementará como parte de WebRTC con getUserMedia y estará disponible como un nodo fuente especial en la API de Web Audio. Funcionará en conjunto con createMediaElementSource.
P.: ¿Cómo puedo verificar cuándo terminó de reproducirse un AudioSourceNode?
R.: Actualmente, debes usar un temporizador de JavaScript, ya que la API de Web Audio no admite esta funcionalidad. El siguiente fragmento del tutorial para comenzar a usar 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.: La carga de sonidos hace que se bloquee todo el subproceso de la IU y que esta deje de responder. ¡Ayuda!**
R.: Usa la API de decodeAudioData para la carga asíncrona y evita 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í, se está trabajando en una solución. Manténte actualizado.
P.: Creé una aplicación increíble con la API de Web Audio, pero cada vez que la pestaña en la que se ejecuta pasa a segundo plano, los sonidos se vuelven extraños.
R.: Es probable que se deba a que usas setTimeouts, que se comporta de manera diferente si la página se ejecuta en segundo plano. En el futuro, la API de Web Audio podrá realizar devoluciones de llamada en momentos específicos con el temporizador interno de Web Audio (atributo context.currentTime). Para obtener más información, consulta esta solicitud de función.
En general, puede ser una buena idea detener la reproducción cuando la app pasa a segundo plano. Puedes detectar cuándo una página pasa a segundo plano con la API de Page Visibility.
P.: ¿Cómo puedo cambiar el tono de un sonido con la API de Web Audio?
R.: Cambia el playbackRate en el nodo de origen.
P.: ¿Puedo cambiar el tono sin cambiar la velocidad?
R.: La API de Web Audio podría tener un PitchNode en el contexto de audio, pero esto es difícil de implementar. Esto se debe a que no existe un algoritmo sencillo de cambio de tono en la comunidad de audio. Las técnicas conocidas crean artefactos, especialmente en los casos en que el cambio de tono es grande. Existen dos tipos de enfoques para abordar este problema:
- Algoritmos de dominio de tiempo, que provocan artefactos de ecos de segmentos repetidos
- Técnicas de dominio de frecuencia, que causan artefactos de sonido reverberantes
Aunque 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 AudioContext con la frecuencia de muestreo que elija?
R.: Por el momento, no se admite esta función, pero estamos investigando la posibilidad de implementarla. Consulta esta solicitud de función.
Si tienes más preguntas, no dudes en hacerlas en Stack Overflow con la etiqueta web-audio.