Sonidos de notas musicales en el piano

Este es un teclado emulado (¡un sintetizador!) que abarca tres octavas musicales (C3-B5).

Inténtalo, pulsa cualquier tecla con el ratón, o utiliza las teclas de tu teclado como se indica en la pantalla!

(Si no oyes nada, prueba a usar Google Chrome o actualiza tu navegador a la versión más reciente. Los dispositivos móviles aún no son del todo compatibles.)

Este teclado funciona generando datos de archivos de audio Waveform de forma dinámica, convirtiéndolos en un dataURI codificado en base64, y reproduciéndolos posteriormente mediante el elemento de audio HTML5 desde el navegador web.

Básicamente, estamos usando las matemáticas para hacer sonidos. Hurra. Esto se diferencia de otros pianos HTML5 en que no utiliza archivos de audio pregrabados, y en que es un poco más refinado.

¿Así que realmente quieres entrar en detalles? Bueno, en primer lugar, la creación de la forma de onda es bastante simple (es sólo una onda sinusoidal, y tenemos una función Math.sin() en JS!), y toda la información que necesita sobre el embalaje de los datos de audio de forma de onda y la creación de la dataURI se puede encontrar aquí, con muchas gracias a sk89q. Voy a asumir una comprensión básica de Javascript en este breve paseo, no dude en enviarme un correo electrónico si tiene alguna pregunta o inquietud!

Desgraciadamente, todo lo que se obtiene al crear una onda sinusoidal es un tono plano extremadamente soso (y para ser franco, molesto).

Los instrumentos musicales reales crean notas completas y vivas. Nosotros queremos emularlo. ¿Cómo podemos hacerlo?

Bueno, gracias a la Universidad de Salford – Manchester por esta bonita página. Voy a proporcionar a los menos inclinados a las matemáticas un poco de paseo, para que puedan visualizar lo que estamos haciendo en cada paso.

Paso 1. Entender tu onda sinusoidal.

De acuerdo, así que has copiado y pegado el código de la página de sk89q arriba y tienes tu onda sinusoidal basada en la frecuencia de la nota que quieres producir. En realidad, lo que tienes es un montón de texto que genera programáticamente los puntos de datos para una onda sinusoidal. Mamma mia!

El periodo es la cantidad de tiempo (t) que tarda una oscilación completa de tu onda. La frecuencia, medida en Hz (la unidad 1/s) es la cantidad de oscilaciones que realiza tu onda por segundo. Estoy seguro de que la mayoría de vosotros habéis tomado alguna clase de física, así que evitaré dar lecciones, pero básicamente todo sonido no es más que un «zumbido», o una vibración en el aire. Cuanto más rápido sea este zumbido (mayor frecuencia, más oscilaciones por segundo, menor periodo), mayor será el tono de la nota.

A partir del código que he esbozado más arriba, acabamos con una forma de onda que tiene este aspecto (gracias a Wikipedia por esta imagen):

Un periodo es cada dos conjuntos de líneas de puntos verticales. Esta onda es la que está haciendo nuestro tono plano y feo, y queremos cambiarla. Imagina que esto continúa un par de cientos de veces, fluctuando entre volumen y +volumen (las líneas de puntos horizontales superior e inferior, es decir, la amplitud de la onda).

Entonces, ¿qué podemos hacer?

Paso 2. Transformar tu onda sinusoidal.

Ahora podemos utilizar el maravilloso mundo de las matemáticas (omg!) para ayudarnos. Queremos transformar nuestra función sinusoidal, definida anteriormente, en algo un poco más. real. Algo que escucharías en el mundo natural. Entonces, ¿cómo crea el sonido un instrumento real? (Crédito de la imagen.)

Bueno, tenemos unas cuantas etapas. Durante el ataque, estás punteando/golpeando una cuerda (en el caso de un piano) o inicializando la oscilación que producirá tu sonido. Hay un poco de decaimiento, luego una retención, en caso de que decidas mantener la oscilación, y finalmente una liberación (y posterior muerte de la señal). Ahora, vamos a olvidarnos de la retención y la liberación en este momento, y simplificar nuestro teclado en sólo un ataque y posterior decadencia. Básicamente, lo que queremos hacer es empezar con la Amplitud de nuestra onda sinusoidal al 0%, llevarla a un pico del 100% en un tiempo muy corto (¡el ataque en un piano es extremadamente rápido!) y luego decaer. Esto lo conseguimos con lo que yo llamo un amortiguador.

Primero, el ataque:

Lo que estamos haciendo aquí es establecer nuestro tiempo de ataque en 0,002s (¡2ms!) y aumentar linealmente el volumen (amplitud de la onda) desde el inicio de la onda hasta que llegamos al final del ataque (de nuevo, los 2ms). i es nuestra variable de contador, que indica nuestra posición actual en la forma de onda. Aunque esto puede ser apenas perceptible para una persona normal, aumentar el tiempo de ataque incluso a 0,02s (20ms) tiene graves consecuencias en tu sonido.

A continuación, la decadencia:

¡Woo! Esto es un montón de cosas. Logaritmos y exponentes ¡oh! Lo que estamos haciendo aquí es primero establecer un amortiguador, que no es más que una función matemática que crea un número mayor a frecuencias más altas. Te habrás dado cuenta de que si tocas una nota baja en tu piano, se mantiene durante mucho más tiempo que una nota alta. Quiero emular eso, y esto es un «hack» para aproximarlo sin simular realmente cuerdas artificiales y hacer física real. ¿La última línea en la parte inferior? Sólo dice que queremos que decaiga hacia 0, de forma polinómica en función del valor de nuestro amortiguador.

Nota que curVol contiene ahora nuestra Amplitud modificada (amortiguada). Lo aplicaremos a la onda con todo lo demás en el siguiente paso.

La razón por la que usamos un logaritmo es que las frecuencias de las notas escalan exponencialmente (cada nota es el doble de la frecuencia de la que está por debajo en la octava) y no queremos del todo una duplicación.
Los resultados que mejor suenan son los que obtuve con este algoritmo después de juguetear un rato. Aquí tienes otros dos con los que puedes jugar:

Paso 3. Añadir ruido.

Muy bien. Hemos creado la base para modificar nuestra forma de onda y darle algo de vida. Sin embargo, todavía va a sonar extremadamente, extremadamente robótica. Así que ahora vamos a hacer dos cosas. Primero vamos a añadir ruido a nuestra señal, y luego vamos a modularla de nuevo a la señal portadora para normalizarla de nuevo dentro del rango que nos gustaría.

Lo que tenemos aquí es base(), nuestra función que genera nuestra onda. Si no le damos un valor, nos devuelve nuestra onda básica. Si le damos un valor, desplaza la onda en 0,5*x períodos. Ten en cuenta que cualquier múltiplo de 2 aquí dará un período superpuesto y sólo nos dará nuestra forma de onda inicial. La idea es que puedes crear una onda desfasada con la misma frecuencia que interferirá con tu forma de onda básica y la «deformará», eliminando el tono «perfecto», o plano de la misma.

La matriz mod[] contiene funciones de modulación de frecuencia, puede utilizarlas como desee, pero aplique siempre mod[0] al final – contiene su onda portadora, y actúa como una forma de normalizar toda la interferencia que crea al combinar y modular otras formas de onda.

Nuestra forma de onda final es una combinación modulada de nuestra forma de onda inicial que interfiere con dos versiones «más silenciosas» de sí misma, una con una amplitud del 75% y otra con una amplitud del 10%, ambas ligeramente desfasadas con respecto a su progenitora.

Por último, multiplicamos curVol, nuestra amplitud amortiguada, por nuestra forma de onda final para terminar de crear nuestra nota.

Paso 4. Salida

Toma tus datos, codifícalos en base64, establece los datos de origen de un objeto HTML5 Audio a tu dataURI recién generado y ¡reproduce! Voilà, una nota musical. Espero que entiendas lo básico de lo que estamos haciendo con nuestras formas de onda aquí 🙂

Addendum 1. Otros instrumentos, y la síntesis de cuerdas Karplus-Strong

Así que, desde que creé inicialmente esta página, he implementado un número de instrumentos diferentes. El órgano es muy parecido al piano, aunque con un ataque más extendido. El EDM es simplemente una versión altamente modulada del piano con un poco de resonancia armónica añadida. La guitarra acústica, sin embargo, es un juego completamente diferente.

El sonido de «cuerda pulsada» se genera mediante lo que se denomina síntesis de cuerda Karplus-Strong. En pocas palabras, creas un búfer del tamaño de tu periodo (basado en tu tasa de muestreo y frecuencia). Este búfer contiene ruido, básicamente alterna (al azar) entre una amplitud de +1 y -1. La salida de este búfer se realiza repetidamente para dar a tu nota su tono debido a su periodicidad. Sin embargo, cada vez que haces un bucle a través del búfer de «ruido», promedias cada punto del búfer con el inmediatamente anterior, filtrándolo efectivamente. Esto hace que la señal decaiga con el tiempo y «suaviza» la forma de onda inicialmente caótica. Puedes leer más sobre el algoritmo Karplus-Strong en la Facultad de Música de Columbia, o en el blog de Hasen el Judy.

Gracias por tu visita, espero que lo hayas disfrutado

Gracias especialmente a Hasen el Judy por los consejos sobre el uso del algoritmo de síntesis de cuerdas Karplus-Strong para emular instrumentos de cuerda pulsada