El reloj interno de Web Audio Api
Al crear una nueva instancia del objeto AudioContext
, el reloj interno de Web Audio Api se pone en marcha. Para leer el valor del reloj interno utilizamos la propiedad currentTime
del AudioContext
:
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
. . . . . . . .
console.log(audioCtx.currentTime);
Podemos utilizar la propiedad currentTime
del AudioContext
para programar eventos, como por ejemplo parar un oscilador después de un segundo:
oscilador.stop(audioCtx.currentTime + 1);
oscilador.stop(audioCtx.currentTime + 1);
function crearOscilador(){
oscilador = audioCtx.createOscillator();
oscilador.type = "triangle";
oscilador.frequency.value = 73;
oscilador.connect(audioCtx.destination);
// inicia el oscilador
oscilador.start(audioCtx.currentTime);
// para el oscilador después de un segundo
oscilador.stop(audioCtx.currentTime + 1);
}
Vea este ejemplo en codepen.io
El reloj interno y los parámetros audio
Hay un grupo de métodos de Web Audio Api que permiten manipular el valor de las propiedades del audio en tiempo: setValueAtTime, linearRampToValueAtTime, exponentialRampToValueAtTime, setTargetAtTime, y setValueCurveAtTime.
Recordatorio: los nodos de ganancia
Los nodos de ganancia ( gain nodes ) son nodos audio que permiten ajustar el volumen del sonido. Veamos como:
// crea un nuevo contexto audio
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function crearOscilador(){
// crea un nuevo oscilador
oscilador = audioCtx.createOscillator();
// crea un nodo de ganancia
gain = audioCtx.createGain();
// establece el valor inicial del volumen del sonido
gain.gain.value = .5;
// establece el tipo de oscilador
oscilador.type = "triangle";
// y el valor de la frecuencia
oscilador.frequency.value = 73;
// conecta el oscilador con el nodo de ganancia
oscilador.connect(gain);
// y la ganancia con el dispositivo de destino
gain.connect(audioCtx.destination);
// inicia el oscilador
oscilador.start(audioCtx.currentTime);
// para el oscilador después de un segundo
oscilador.stop(audioCtx.currentTime + 1);
}
document.body.addEventListener("click", crearOscilador, false);
Vea este ejemplo en codepen
En lugar de establecer el valor de la ganancia como en el ejemplo anterior, podemos utilizar uno de los métodos de Web Audio Api que permiten manipular el valor de las propiedades del audio en tiempo:
El método setValueAtTime
El método setValueAtTime
permite programar el cambio repentino del valor un parámetro audio en un momento dado. El método setValueAtTime
toma dos argumentos: el nuevo valor del parámetro audio, y el momento cuando el cambio ocurre.
parametroAudio.setValueAtTime(valor, momento)
En el siguiente ejemplo el valor inicial del volumen es 3, pero baja después de 0.5 segundos a 0.25.
gain.gain.value = 3; gain.gain.setValueAtTime(0.25, audioCtx.currentTime + 0.5);
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function crearOscilador(){
oscilador = audioCtx.createOscillator();
// crea un nodo de ganancia
gain = audioCtx.createGain();
// el valor inicial del volumen es 3
gain.gain.value = 3;
// pero baja después de 0.5 segundos a .25
gain.gain.setValueAtTime(0.25, audioCtx.currentTime + .5)
// establece el tipo de oscilador
oscilador.type = "triangle";
// y el valor de la frecuencia
oscilador.frequency.value = 73;
// conecta el oscilador con el nodo de ganancia
oscilador.connect(gain);
// y la ganancia con el dispositivo de destino
gain.connect(audioCtx.destination);
// inicia el oscilador
oscilador.start(audioCtx.currentTime);
// para el oscilador después de dos segundos
oscilador.stop(audioCtx.currentTime + 2);
}
document.body.addEventListener("click", crearOscilador, false);
Vea este ejemplo comentado en codepen
El método linearRampToValueAtTime
El método linearRampToValueAtTime
permite programar el cambio gradual del valor un parámetro audio hacia un valor dado. La transformación es lineal.
El método linearRampToValueAtTime
toma dos argumentos: el nuevo valor del parámetro audio y el momento final de la transformación:
parametroAudio.linearRampToValueAtTime (valor, momentoFinal)
En el siguiente ejemplo el volumen baja gradualmente a 0. La transformación dura 1 segundo.
gain.gain.linearRampToValueAtTime(0, audioCtx.currentTime + 1);
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function crearOscilador(){
oscilador = audioCtx.createOscillator();
// crea un nodo de ganancia
gain = audioCtx.createGain();
// establece el valor inicial del volumen
gain.gain.value = 2;
// el volumen baja gradualmente a 0. La transformación dura 1 segundo.
gain.gain.linearRampToValueAtTime(0, audioCtx.currentTime + 1);
// establece el tipo de oscilador
oscilador.type = "triangle";
// y el valor de la frecuencia
oscilador.frequency.value = 73;
// conecta el oscilador con el nodo de ganancia
oscilador.connect(gain);
// y la ganancia con el dispositivo de destino
gain.connect(audioCtx.destination);
// inicia el oscilador
oscilador.start(audioCtx.currentTime);
// para el oscilador después de un segundo
oscilador.stop(audioCtx.currentTime + 1);
}
document.body.addEventListener("click", crearOscilador, false);
Vea este ejemplo comentado en codepen
El método exponentialRampToValueAtTime
El método exponentialRampToValueAtTime
permite programar el cambio exponencial del valor un parámetro audio hacia un valor dado. La transformación es exponencial.
El método exponentialRampToValueAtTime
toma dos argumentos: el nuevo valor del parámetro audio y el momento final de la transformación:
parametroAudio.exponentialRampToValueAtTime (valor, momentoFinal);
En el siguiente ejemplo el volumen baja exponencialmente a 0.01. La transformación dura 1 segundo.
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 1);
¡OJO! El valor final del parámetro audio tiene que ser un número positivo ( en este caso 0.01 ). Un valor final igual a 0 da error ( invalid o illegal ).
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function crearOscilador(){
oscilador = audioCtx.createOscillator();
// crea un nodo de ganancia
gain = audioCtx.createGain();
// establece el valor inicial del volumen
gain.gain.value = 2;
// el volumen baja exponencialmente a 0.01. La transformación dura 1 segundo.
// ¡OJO! El valor final del parámetro audio tiene que ser un número positivo ( en este caso 0.01 ). Un valor final igual a 0 da error!
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 1);
// establece el tipo de oscilador
oscilador.type = "triangle";
// y el valor de la frecuencia
oscilador.frequency.value = 73;
// conecta el oscilador con el nodo de ganancia
oscilador.connect(gain);
// y la ganancia con el dispositivo de destino
gain.connect(audioCtx.destination);
// inicia el oscilador
oscilador.start(audioCtx.currentTime);
// para el oscilador después de un segundo
oscilador.stop(audioCtx.currentTime + 1);
}
document.body.addEventListener("click", crearOscilador, false);
Vea este ejemplo comentado en codepen
El método setTargetAtTime
El método setTargetAtTime
permite programar el cambio exponencial del valor un parámetro audio y toma 3 argumentos:
parametroAudio.setTargetAtTime( valorFinal, cuandoEmpieza, constanteDeTiempo );
Donde:
valorFinal
: representa el valor final del parámetro audio.
cuandoEmpieza
: representa el momento en el cual empieza la transición.
constanteDeTiempo
: determina la duración de la transición exponencial. Como más grande, más tiempo dura la transición. Si este último parámetro es 0 el cambio es repentino.
En el siguiente ejemplo el volumen del sonido baja exponencialmente a 0. La transición empieza después de 0.5 segundos.
gain.gain.setTargetAtTime(0, audioCtx.currentTime + 0.5, 0.3);
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function crearOscilador(){
oscilador = audioCtx.createOscillator();
// crea un nodo de ganancia
gain = audioCtx.createGain();
// establece el valor inicial del volumen
gain.gain.value = 2;
// el volumen del sonido baja gradualmente a 0.
// la transición empieza después de 0.5 segundos
// el último parámetro determina la duración de la transición exponencial. Como más grande, más tiempo dura la transición. Si este último parámetro es 0 el cambio es repentino.
gain.gain.setTargetAtTime(0, audioCtx.currentTime + 0.5, .3);
// establece el tipo de oscilador
oscilador.type = "triangle";
// y el valor de la frecuencia
oscilador.frequency.value = 73;
// conecta el oscilador con el nodo de ganancia
oscilador.connect(gain);
// y la ganancia con el dispositivo de destino
gain.connect(audioCtx.destination);
// inicia el oscilador
oscilador.start(audioCtx.currentTime);
// para el oscilador después de dos segundos
oscilador.stop(audioCtx.currentTime + 2);
}
document.body.addEventListener("click", crearOscilador, false);
Vea este ejemplo comentado en codepen
El método setValueCurveAtTime
El método setValueCurveAtTime
permite programar la transición entre varios valores utilizando Float32Array, un iterable muy parecido a un array de números decimales ( float number ) de 32 bits, y toma tres argumentos:
parametroAudio.setValueCurveAtTime(valores, cuandoEmpieza, duración)
En el siguiente ejemplo el volumen del sonido varía entre los valores definidos utilizando un Float32Array
. El "array" de los valores tiene 7 elementos.
let valores = new Float32Array(7); valores[0] = 1; valores[1] = 1.5; valores[2] = 2; valores[3] = 1.5; valores[4] = 1; valores[5] = 0.5; valores[6] = 0;
La transición empieza en el primer momento ( audioCtx.currentTime
) y dura un segundo (1
)
gain.gain.setValueCurveAtTime(valores, audioCtx.currentTime, 1);
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
// crea el "array" de los valores
let valores = new Float32Array(7);
valores[0] = 1;
valores[1] = 1.5;
valores[2] = 2;
valores[3] = 1.5;
valores[4] = 1;
valores[5] = 0.5;
valores[6] = 0;
function crearOscilador(){
oscilador = audioCtx.createOscillator();
// crea un nodo de ganancia
gain = audioCtx.createGain();
// el volumen del sonido varía entre los valores definidos utilizando un Float32Array
gain.gain.setValueCurveAtTime(valores, audioCtx.currentTime, 1);
// establece el tipo de oscilador
oscilador.type = "triangle";
// y el valor de la frecuencia
oscilador.frequency.value = 73;
// conecta el oscilador con el nodo de ganancia
oscilador.connect(gain);
// y la ganancia con el dispositivo de destino
gain.connect(audioCtx.destination);
// inicia el oscilador
oscilador.start(audioCtx.currentTime);
// para el oscilador después de dos segundos
oscilador.stop(audioCtx.currentTime + 1);
}
document.body.addEventListener("click", crearOscilador, false);
Vea este ejemplo en codepen
Lea más acerca de Uint8Array y otros arrays parecidos: JavaScript typed arrays
Vea también este ejemplo comentado que crea una especie de xilófono, que toca al pasar con el ratón por encima de los botones.