Este es el primero de una serie de tutoriales en los que crearemos un motor de audio basado en sintetizador que puede generar sonidos para juegos de estilo retro. El motor de audio generará todos los sonidos en tiempo de ejecución sin la necesidad de dependencias externas, como archivos MP3 o WAV. El resultado final será una biblioteca funcional que se puede colocar sin esfuerzo en tus juegos.
Antes de que podamos comenzar a crear el motor de audio, hay algunas cosas que tendremos que entender; Estas incluyen las formas de onda que el motor de audio utilizará para generar los sonidos audibles, y cómo las ondas de sonido se almacenan y se representan en forma digital..
El lenguaje de programación utilizado en este tutorial es ActionScript 3.0, pero las técnicas y conceptos utilizados pueden traducirse fácilmente a cualquier otro lenguaje de programación que ofrezca una API de sonido de bajo nivel..
Debe asegurarse de tener instalado Flash Player 11.4 o superior para su navegador si desea usar los ejemplos interactivos de este tutorial..
El motor de audio que crearemos utilizará cuatro formas de onda básicas (también conocidas como periódico formas de onda, debido a que sus formas básicas se repiten periódicamente), todas las cuales son extremadamente comunes en los sintetizadores analógicos y digitales. Cada forma de onda tiene su propia característica audible única.
Las siguientes secciones proporcionan una representación visual de cada forma de onda, un ejemplo audible de cada forma de onda y el código requerido para generar cada forma de onda como una matriz de datos de muestra..
La onda de pulso produce un sonido agudo y armónico..
Para generar una matriz de valores (en el rango de -1.0 a 1.0) que representan una onda de pulso, podemos usar el siguiente código, donde norte
es el número de valores necesarios para rellenar la matriz, una
es la matriz, y pag
es la posición normalizada dentro de la forma de onda:
var i: int = 0; var n: int = 100; var p: Número; mientras yo < n ) p = i / n; a[i] = p < 0.5 ? 1.0 : -1.0; i ++;
La onda de diente de sierra produce un sonido agudo y áspero..
Para generar una matriz de valores (en el rango de -1.0 a 1.0) que representan una onda de diente de sierra podemos usar el siguiente código, donde norte
es el número de valores necesarios para rellenar la matriz, una
es la matriz, y pag
es la posición normalizada dentro de la forma de onda:
var i: int = 0; var n: int = 100; var p: Número; mientras yo < n ) p = i / n; a[i] = p < 0.5 ? p * 2.0 : p * 2.0 - 2.0; i ++;
La onda sinusoidal produce un sonido suave y puro..
Para generar una matriz de valores (en el rango de -1.0 a 1.0) que representan una onda sinusoidal, podemos usar el siguiente código, donde norte
es el número de valores necesarios para rellenar la matriz, una
es la matriz, y pag
es la posición normalizada dentro de la forma de onda:
var i: int = 0; var n: int = 100; var p: Número; mientras yo < n ) p = i / n; a[i] = Math.sin( p * 2.0 * Math.PI ); i ++;
La onda triangular produce un sonido suave y armónico..
Para generar una matriz de valores (en el rango de -1.0 a 1.0) que representan una onda triangular, podemos usar el siguiente código, donde norte
es el número de valores necesarios para rellenar la matriz, una
es la matriz, y pag
es la posición normalizada dentro de la forma de onda:
var i: int = 0; var n: int = 100; var p: Número; mientras yo < n ) p = i / n; a[i] = p < 0.25 ? p * 4.0 : p < 0.75 ? 2.0 - p * 4.0 : p * 4.0 - 4.0; i ++;
Aquí hay una versión ampliada de la línea 6:
si p < 0.25) a[i] = p * 4.0; else if (p < 0.75) a[i] = 2.0 - (p * 4.0); else a[i] = (p * 4.0) - 4.0;
Dos propiedades importantes de una onda sonora son las amplitud y frecuencia de la forma de onda: estos dictan el volumen y tono del sonido, respectivamente. La amplitud es simplemente el valor máximo absoluto de la forma de onda, y la frecuencia es el número de veces que se repite la forma de onda por segundo, que normalmente se mide en hercios (Hz).
La siguiente imagen es una instantánea de 200 milisegundos de una forma de onda en diente de sierra con una amplitud de 0.5 y una frecuencia de 20 hertz:
Para darle una idea de cómo la frecuencia de una forma de onda se relaciona directamente con el tono del sonido audible, una forma de onda con una frecuencia de 440 hertz producirá el mismo tono que la nota A4 estándar (A central) en un piano de concierto moderno. Con esa frecuencia en mente, podemos calcular la frecuencia de cualquier nota usando el siguiente código:
f = Math.pow (2, n / 12) * 440.0;
los norte
La variable en ese código es el número de notas desde A4 (centro A) a la nota que nos interesa. Por ejemplo, para encontrar la frecuencia de A5, una octava por encima de A4, estableceremos el valor de norte
a 12
porque A5 es 12 notas por encima de A4. Para encontrar la frecuencia de E2 estableceríamos el valor de norte
a -5
porque E2 es de 5 notas por debajo de A4. También podemos hacer lo contrario y encontrar una nota (relativa a A4) para una frecuencia determinada:
n = Math.round (12.0 * Math.log (f / 440.0) * Math.LOG2E);
La razón por la que estos cálculos funcionan es porque las frecuencias de las notas son logarítmicas: multiplicar una frecuencia por dos mueve una nota hasta una octava, mientras que dividir una frecuencia por dos mueve una nota hacia abajo una octava.
En el mundo digital, las ondas de sonido deben almacenarse como datos binarios, y la forma común de hacerlo es tomar instantáneas periódicas (o muestras) de una onda de sonido. El número de muestras de onda que se toman para cada segundo de la duración de un sonido se conoce como frecuencia de muestreo, por lo tanto, un sonido con una frecuencia de muestreo de 44100 contendrá 44100 muestras de onda (por canal) por cada segundo de la duración del sonido.
La siguiente imagen muestra cómo se puede muestrear una onda de sonido:
Las manchas blancas en esa imagen representan los puntos de amplitud de la onda que se muestrean y almacenan en un formato digital. Puede pensar en esto como en la resolución de una imagen de mapa de bits: cuantos más píxeles contiene una imagen de mapa de bits, más información visual puede contener y más información resulta en archivos más grandes (ignorar la compresión de archivos por ahora). Lo mismo ocurre con los sonidos digitales: cuantas más muestras de onda contenga un archivo de sonido, más precisa será la onda de sonido reconstruida..
Además de tener una frecuencia de muestreo, los sonidos digitales también tienen un velocidad de bits que se mide en bits por segundo. La velocidad de bits determina cuántos bits binarios se utilizan para almacenar cada muestra de onda. Esto es similar al número de bits utilizados para almacenar información ARGB para cada píxel en una imagen de mapa de bits. Por ejemplo, un sonido con una frecuencia de muestreo de 44100 y una velocidad de bits de 705600 estaría almacenando cada una de sus muestras de onda como un valor de 16 bits, y podemos calcularlo fácilmente utilizando el siguiente código:
bitsPerSample = bitRate / sampleRate;
Aquí hay un ejemplo de trabajo usando los valores mencionados anteriormente:
traza (705600/44100); // "dieciséis"
Comprender qué son las muestras de sonido es lo más importante aquí; El motor de audio que crearemos tendrá que generar y manipular muestras de sonido en bruto..
Una cosa más que debemos tener en cuenta antes de comenzar a programar el motor de audio son moduladores, que son extremadamente comunes tanto en sintetizadores analógicos como digitales. Un modulador es esencialmente solo una forma de onda estándar, pero en lugar de usarse para producir un sonido, se usan comúnmente para modular una o más propiedades de una forma de onda audible (por ejemplo, su amplitud o frecuencia).
Tomar vibrato, por ejemplo. El vibrato es un cambio regular de tono pulsante. Para producir ese efecto utilizando un modulador, puede configurar la forma de onda del modulador en una onda sinusoidal y establecer la frecuencia del modulador en algún lugar alrededor de 8 hertzios. Si luego conectara ese modulador a la frecuencia de una forma de onda audible, el resultado sería un efecto de vibrato: el modulador aumentaría y disminuiría suavemente la frecuencia (tono) de la forma de onda audible ocho veces por segundo..
El motor de audio que crearemos te permitirá conectar moduladores a tus sonidos para que puedas producir una gran cantidad de efectos diferentes..
En el siguiente tutorial, crearemos el código central para el motor de audio y haremos que todo funcione. Síganos en Twitter, Facebook o Google+ para mantenerse al día con las últimas publicaciones..