Minimal ejemplo generación audio C
En el ejemplo siguiente genera un seno 1000k Hz puro en formato RAW. A una velocidad de muestreo de 44,1 kHz, que tendrá una duración de 4 segundos:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(void) {
FILE *f;
const double PI2 = 2 * acos(-1.0);
const double SAMPLE_FREQ = 44100;
const unsigned int NSAMPLES = 4 * SAMPLE_FREQ;
uint16_t ampl;
uint8_t bytes[2];
unsigned int t;
f = fopen("out.raw", "wb");
for (t = 0; t < NSAMPLES; ++t) {
ampl = UINT16_MAX * 0.5 * (1.0 + sin(PI2 * t * 1000.0/SAMPLE_FREQ));
bytes[0] = ampl >> 8;
bytes[1] = ampl & 8;
fwrite(bytes, 2, sizeof(uint8_t), f);
}
fclose(f);
return EXIT_SUCCESS;
}
Juega con:
sudo apt-get install ffmpeg
ffplay -autoexit -f u16be -ar 44100 -ac 1 out.raw
parámetros que se describen en: https://superuser.com/a/1063230/128124
probado en Ubuntu 15.10. Más fun examples on GitHub, incluido un simple sintetizador Canon.
Física
audio se codifica como un número único para cada momento en el tiempo. Compárelo con un video, que necesita ANCHURA * ALTURA números por momento en el tiempo.
Este número se convierte después en el desplazamiento lineal de la diaphragm de su altavoz:
| /
|/
|-/
| | A I R
|-\
| \
| \
<-> displacement
| /
| /
|---/
| | A I R
|---\
| \
| \
<---> displacement
| /
| /
|-----/
| | A I R
|-----\
| \
| \
<-----> displacement
El desplazamiento empuja el aire hacia atrás y hacia adelante, creando diferencias de presión, que viajan a través del aire como P-waves.
Sólo el desplazamiento es importante: una señal constante, aunque sea máxima, no produce ningún sonido: el diafragma simplemente permanece en una posición fija.
El sampling frequency determina qué tan rápido deben realizarse los desplazamientos.
44,1kHz es una frecuencia de muestreo común porque los humanos pueden escuchar hasta 20kHz y debido a Nyquist–Shannon sampling theorem.
La frecuencia de muestreo es análoga a la FPS para video, aunque tiene un valor mucho más alto en comparación con la gama de 25 (cine) - 144 (monitores de juegos hardcore) que comúnmente vemos para video.
Formatos
.raw
es un formato subespecificada que contiene sólo los bytes de amplitud, y no hay metadatos.
Tenemos que pasar algunos parámetros de metadatos en la línea de comandos como la frecuencia de muestreo porque el formato no contiene esa información.
También hay otros formatos sin comprimir que contienen todos los metadatos necesarios, p. .wav
, ver: WAV File Synthesis From Scratch - C
En la práctica, sin embargo, la mayoría de la gente se ocupa exclusivamente de formatos comprimidos, lo que hace que los archivos/la transmisión sean mucho más pequeños. Algunos de esos formatos tienen en cuenta las características del oído humano para comprimir aún más el audio de una manera con pérdida.
Biología
los seres humanos perciben el sonido sobre todo por su descomposición frecuencia (También conocido como Fourier transform).
Creo que esto se debe a que el oído interno tiene partes que resuenan a diferentes frecuencias (confirmación TODO).
Por lo tanto, al sintetizar música, pensamos más en términos de sumar frecuencias en lugar de puntos en el tiempo. Esto se ilustra in this example.
Esto lleva a pensar en términos de un vector 1D entre 20Hz y 20kHz para cada punto en el tiempo.
La transformación matemática de Fourier pierde la noción de tiempo, por lo que lo que hacemos al sintetizar es tomar grupos de puntos, y sumar las frecuencias para ese grupo, y tomar la transformada de Fourier allí.
Afortunadamente, la transformada de Fourier es lineal, por lo que podemos simplemente sumar y normalizar los desplazamientos directamente.
El tamaño de cada grupo de puntos conduce a una compensación de precisión de frecuencia de tiempo, mediada por las mismas matemáticas que Heisenberg's uncertainty principle.
Wavelets puede ser una descripción matemática más precisa de esta descripción de tiempo-frecuencia intermediaria.
Muy buena explicación, gracias! –
Técnicamente hablando, es un conjunto de mediciones de amplitud. Simplemente sucede que la mayoría de los ADCs usan voltaje para representar la amplitud. –
@SteveKuo técnicamente hablando, eso es correcto, pero parece que agregar eso de cualquier manera significativa complicaría el problema en gran medida. Y dado que este no es un sitio de ingeniería eléctrica ... – derobert