Phase 06 - Lesson 01

Fundamentos de Audio — Formas de Onda, Muestreo, Transformada de Fourier

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

Las formas de onda son la señal cruda. Los espectrogramas son la representación. Las características mel son la forma amigable para ML. Todo pipeline moderno de ASR y TTS recorre esta escalera, y el primer peldaño es entender el muestreo y Fourier.

Tipo: Aprender Lenguajes: Python Prerrequisitos: Fase 1 · 06 (Vectores y Matrices), Fase 1 · 14 (Distribuciones de Probabilidad) Tiempo: ~45 minutos

El Problema

Un micrófono produce una señal de presión-versus-tiempo. Tu red neuronal consume tensores. Entre ambos hay una pila de convenciones que, cuando se violan, producen errores silenciosos: el modelo entrena bien pero el WER se duplica, o el TTS entrega un siseo, o un sistema de clonación de voz memoriza el micrófono en lugar del hablante.

Todo error en sistemas de habla se remonta a una de tres preguntas:

  1. ¿A qué frecuencia de muestreo se grabaron los datos, y qué espera el modelo?
  2. ¿La señal tiene aliasing?
  3. ¿Estás operando sobre muestras crudas o sobre una representación en frecuencia?

Acierta en esto y el resto de la Fase 6 se vuelve manejable. Falla en esto y hasta Whisper-Large-v4 produce basura.

El Concepto

Forma de onda, muestreo, DFT y bins de frecuencia visualizados

Forma de onda. Un arreglo unidimensional de floats en [-1.0, 1.0]. Indexado por número de muestra. Para convertir a segundos, divide por la frecuencia de muestreo: t = n / sr. Un clip de 10 segundos a 16 kHz es un arreglo de 160.000 floats.

Frecuencia de muestreo (sr). Cuántas muestras por segundo. Frecuencias comunes en 2026:

Frecuencia Uso
8 kHz Telefonía, VOIP heredado. Nyquist en 4 kHz mata las consonantes. Evítalo para ASR.
16 kHz Estándar de ASR. Whisper, Parakeet y SeamlessM4T v2 consumen 16 kHz.
22,05 kHz Entrenamiento de vocoder TTS para modelos más antiguos.
24 kHz TTS moderno (Kokoro, F5-TTS, xTTS v2).
44,1 kHz Audio de CD, música.
48 kHz Cine, audio profesional, TTS de alta fidelidad (VALL-E 2, NaturalSpeech 3).

Nyquist-Shannon. Una frecuencia de muestreo sr puede representar de forma inequívoca frecuencias hasta sr/2. El límite sr/2 es la frecuencia de Nyquist. La energía por encima de Nyquist sufre aliasing — se pliega hacia frecuencias más bajas — y corrompe la señal. Aplica siempre un filtro pasa-bajos antes de reducir la frecuencia de muestreo.

Profundidad de bits. PCM de 16 bits (int16 con signo, rango ±32.767) es el formato universal de intercambio. 24 bits para música, float de 32 bits para DSP interno. Bibliotecas como soundfile leen int16 pero exponen arreglos float32 en [-1, 1].

Transformada de Fourier. Cualquier señal finita es una suma de sinusoides en frecuencias diferentes. La Transformada Discreta de Fourier (DFT) calcula, para N muestras, N coeficientes complejos — uno por bin de frecuencia. El bin k mapea a la frecuencia k · sr / N Hz. La magnitud es la amplitud en esa frecuencia, el ángulo es la fase.

FFT. Fast Fourier Transform: un algoritmo O(N log N) para la DFT cuando N es una potencia de 2. Toda biblioteca de audio usa FFT por debajo. Una FFT de 1024 muestras a 16 kHz entrega 512 bins de frecuencia útiles que abarcan de 0 a 8 kHz con resolución de 15,6 Hz.

Enmarcado + ventana. No aplicamos FFT a un clip entero. Lo cortamos en frames superpuestos (típicamente 25 ms con salto de 10 ms), multiplicamos cada frame por una función de ventana (Hann, Hamming) para eliminar discontinuidades de borde, y luego aplicamos FFT a cada frame. Esta es la Transformada de Fourier de Tiempo Corto (STFT). La Lección 02 retoma desde aquí.

Constrúyelo

Paso 1: lee un clip y grafica la forma de onda

code/main.py usa solo el módulo wave de la stdlib para mantener la demostración libre de dependencias. En producción usarás soundfile o torchaudio.load (ambos devuelven tuplas (waveform, sr)):

import soundfile as sf
waveform, sr = sf.read("clip.wav", dtype="float32")  # shape (T,), sr=int

Paso 2: sintetiza una onda senoidal desde primeros principios

import math

def sine(freq_hz, sr, seconds, amp=0.5):
    n = int(sr * seconds)
    return [amp * math.sin(2 * math.pi * freq_hz * i / sr) for i in range(n)]

Una senoide de 440 Hz (la de concierto) a 16 kHz durante 1 segundo son 16.000 floats. Escribe con wave.open(..., "wb") usando codificación PCM de 16 bits.

Paso 3: calcula la DFT a mano

def dft(x):
    N = len(x)
    out = []
    for k in range(N):
        re = sum(x[n] * math.cos(-2 * math.pi * k * n / N) for n in range(N))
        im = sum(x[n] * math.sin(-2 * math.pi * k * n / N) for n in range(N))
        out.append((re, im))
    return out

O(N²) — adecuado para N=256 para confirmar la corrección, inútil para audio real. El código real llama a numpy.fft.rfft o torch.fft.rfft.

Paso 4: encuentra la frecuencia dominante

El índice del pico de magnitud k_star mapea a la frecuencia k_star * sr / N. Ejecutar esto en la senoide de 440 Hz debería devolver un pico en el bin 440 * N / sr.

Paso 5: demuestra el aliasing

Muestrea una senoide de 7 kHz a 10 kHz (Nyquist = 5 kHz). El tono de 7 kHz está por encima de Nyquist y se pliega a 10 − 7 = 3 kHz. El pico de la FFT aparece en 3 kHz. Esta es la demostración clásica de aliasing y la razón por la que todo DAC/ADC viene con un filtro pasa-bajos de pared de ladrillos.

Úsalo

La pila que realmente vas a desplegar en 2026:

Tarea Biblioteca Por qué
Leer/escribir WAV/FLAC/OGG soundfile (wrapper de libsndfile) La más rápida, estable, devuelve float32.
Remuestrear torchaudio.transforms.Resample o librosa.resample Anti-aliasing correcto incorporado.
STFT / Mel torchaudio o librosa Amigable con GPU; ecosistema PyTorch.
Streaming en tiempo real sounddevice o pyaudio Bindings PortAudio multiplataforma.
Inspeccionar un archivo ffprobe o soxi CLI, rápida, reporta sr/canales/códec.

Regla de decisión: iguala la frecuencia de muestreo antes de igualar cualquier otra cosa. Whisper espera 16 kHz mono float32. Pásale 44,1 kHz estéreo y obtendrás basura que parece un error del modelo.

Entrégalo

Guárdalo como outputs/skill-audio-loader.md. La skill te ayuda a verificar que la entrada de audio coincida con las expectativas del modelo posterior y a remuestrear correctamente cuando no es así.

Ejercicios

  1. Fácil. Sintetiza una mezcla de 1 segundo de 220 Hz + 440 Hz + 880 Hz a 16 kHz. Ejecuta la DFT. Confirma tres picos en los bins esperados.
  2. Medio. Graba un WAV de 3 segundos de tu voz a 48 kHz. Reduce el muestreo a 16 kHz usando torchaudio.transforms.Resample (con anti-aliasing), luego a 16 kHz usando diezmado ingenuo (una muestra de cada tres). Aplica FFT a ambos. ¿Dónde aparece el aliasing?
  3. Difícil. Construye la STFT desde cero usando solo math y la DFT del Paso 3. Tamaño de frame 400, salto 160, ventana de Hann. Grafica las magnitudes con matplotlib.pyplot.imshow. Este es el espectrograma de la Lección 02.

Términos Clave

Término Lo que la gente dice Lo que realmente significa
Frecuencia de muestreo Cuántas muestras por segundo Frecuencia en Hz a la que el ADC mide la señal.
Nyquist La frecuencia máxima que puedes representar sr/2; la energía por encima sufre aliasing hacia abajo.
Profundidad de bits Resolución de cada muestra int16 = 65.536 niveles; float32 = precisión de 24 bits en [-1, 1].
DFT La transformada de Fourier para secuencias N muestras → N coeficientes de frecuencia complejos.
FFT La DFT rápida Algoritmo O(N log N) que requiere N = potencia de 2.
Bin Columna de frecuencia k · sr / N Hz; resolución = sr / N.
STFT Espectrograma por debajo FFT enmarcada y con ventana a lo largo del tiempo.
Aliasing Fantasmas extraños de frecuencia Energía por encima de Nyquist reflejándose hacia bins más bajos.

Lecturas Adicionales

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).