Phase 06 - Lesson 01
Fundamentos de Áudio — Formas de Onda, Amostragem, Transformada de Fourier
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
Formas de onda são o sinal bruto. Espectrogramas são a representação. Os atributos mel são a forma amigável para ML. Todo pipeline moderno de ASR e TTS sobe essa escada, e o primeiro degrau é entender amostragem e Fourier.
Tipo: Aprender Linguagens: Python Pré-requisitos: Fase 1 · 06 (Vetores e Matrizes), Fase 1 · 14 (Distribuições de Probabilidade) Tempo: ~45 minutos
O Problema
Um microfone produz um sinal de pressão-versus-tempo. Sua rede neural consome tensores. Entre eles há uma pilha de convenções que, quando violadas, produzem bugs silenciosos: o modelo treina bem mas o WER dobra, ou o TTS entrega um chiado, ou um sistema de clonagem de voz memoriza o microfone em vez do locutor.
Todo bug em sistemas de fala remonta a uma de três perguntas:
- Em qual taxa de amostragem os dados foram gravados, e o que o modelo espera?
- O sinal está com aliasing?
- Você está operando sobre amostras brutas ou sobre uma representação em frequência?
Acerte isso e o resto da Fase 6 fica tratável. Erre isso e até o Whisper-Large-v4 produz lixo.
O Conceito
Forma de onda. Um array unidimensional de floats em [-1.0, 1.0]. Indexado por número de amostra. Para converter para segundos, divida pela taxa de amostragem: t = n / sr. Um clipe de 10 segundos a 16 kHz é um array de 160.000 floats.
Taxa de amostragem (sr). Quantas amostras por segundo. Taxas comuns em 2026:
| Taxa | Uso |
|---|---|
| 8 kHz | Telefonia, VOIP legado. Nyquist em 4 kHz mata as consoantes. Evite para ASR. |
| 16 kHz | Padrão de ASR. Whisper, Parakeet e SeamlessM4T v2 consomem 16 kHz. |
| 22,05 kHz | Treinamento de vocoder TTS para modelos mais antigos. |
| 24 kHz | TTS moderno (Kokoro, F5-TTS, xTTS v2). |
| 44,1 kHz | Áudio de CD, música. |
| 48 kHz | Cinema, áudio profissional, TTS de alta fidelidade (VALL-E 2, NaturalSpeech 3). |
Nyquist-Shannon. Uma taxa de amostragem sr pode representar de forma inequívoca frequências até sr/2. O limite sr/2 é a frequência de Nyquist. Energia acima de Nyquist sofre aliasing — é dobrada para frequências mais baixas — e corrompe o sinal. Sempre aplique um filtro passa-baixas antes de reduzir a taxa de amostragem.
Profundidade de bits. PCM de 16 bits (int16 com sinal, faixa ±32.767) é o formato universal de troca. 24 bits para música, float de 32 bits para DSP interno. Bibliotecas como soundfile leem int16 mas expõem arrays float32 em [-1, 1].
Transformada de Fourier. Qualquer sinal finito é uma soma de senoides em frequências diferentes. A Transformada Discreta de Fourier (DFT) calcula, para N amostras, N coeficientes complexos — um por bin de frequência. O bin k mapeia para a frequência k · sr / N Hz. A magnitude é a amplitude naquela frequência, o ângulo é a fase.
FFT. Fast Fourier Transform: um algoritmo O(N log N) para a DFT quando N é uma potência de 2. Toda biblioteca de áudio usa FFT por baixo dos panos. Uma FFT de 1024 amostras a 16 kHz fornece 512 bins de frequência úteis abrangendo de 0 a 8 kHz com resolução de 15,6 Hz.
Janelamento + janela. Não aplicamos FFT a um clipe inteiro. Nós o cortamos em frames sobrepostos (tipicamente 25 ms com salto de 10 ms), multiplicamos cada frame por uma função de janela (Hann, Hamming) para eliminar descontinuidades de borda, e então aplicamos FFT a cada frame. Isto é a Transformada de Fourier de Curto Tempo (STFT). A Lição 02 continua a partir daqui.
Construa
Passo 1: leia um clipe e plote a forma de onda
code/main.py usa apenas o módulo wave da stdlib para manter a demonstração livre de dependências. Em produção você usará soundfile ou torchaudio.load (ambos retornam tuplas (waveform, sr)):
import soundfile as sf
waveform, sr = sf.read("clip.wav", dtype="float32") # shape (T,), sr=int
Passo 2: sintetize uma onda senoidal a partir de princípios fundamentais
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)]
Uma senoide de 440 Hz (lá de concerto) a 16 kHz por 1 segundo são 16.000 floats. Escreva com wave.open(..., "wb") usando codificação PCM de 16 bits.
Passo 3: calcule a DFT à mão
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²) — adequado para N=256 para confirmar a correção, inútil para áudio real. O código real chama numpy.fft.rfft ou torch.fft.rfft.
Passo 4: encontre a frequência dominante
O índice de pico de magnitude k_star mapeia para a frequência k_star * sr / N. Executar isso na senoide de 440 Hz deve retornar um pico no bin 440 * N / sr.
Passo 5: demonstre o aliasing
Amostre uma senoide de 7 kHz a 10 kHz (Nyquist = 5 kHz). O tom de 7 kHz está acima de Nyquist e dobra para 10 − 7 = 3 kHz. O pico da FFT aparece em 3 kHz. Esta é a demonstração clássica de aliasing e a razão pela qual todo DAC/ADC vem com um filtro passa-baixas de parede de tijolos.
Use
A pilha que você de fato vai colocar em produção em 2026:
| Tarefa | Biblioteca | Por quê |
|---|---|---|
| Ler/escrever WAV/FLAC/OGG | soundfile (wrapper de libsndfile) |
Mais rápida, estável, retorna float32. |
| Reamostrar | torchaudio.transforms.Resample ou librosa.resample |
Anti-aliasing correto embutido. |
| STFT / Mel | torchaudio ou librosa |
Amigável a GPU; ecossistema PyTorch. |
| Streaming em tempo real | sounddevice ou pyaudio |
Bindings PortAudio multiplataforma. |
| Inspecionar um arquivo | ffprobe ou soxi |
CLI, rápida, reporta sr/canais/codec. |
Regra de decisão: case a taxa de amostragem antes de casar qualquer outra coisa. O Whisper espera 16 kHz mono float32. Passe a ele 44,1 kHz estéreo e você obterá lixo que parece um bug do modelo.
Entregue
Salve como outputs/skill-audio-loader.md. A skill ajuda você a verificar se a entrada de áudio corresponde às expectativas do modelo a jusante e a reamostrar corretamente quando não corresponde.
Exercícios
- Fácil. Sintetize uma mistura de 1 segundo de 220 Hz + 440 Hz + 880 Hz a 16 kHz. Execute a DFT. Confirme três picos nos bins esperados.
- Médio. Grave um WAV de 3 segundos da sua voz a 48 kHz. Reduza a amostragem para 16 kHz usando
torchaudio.transforms.Resample(com anti-aliasing), depois para 16 kHz usando decimação ingênua (uma amostra a cada três). Aplique FFT em ambos. Onde aparece o aliasing? - Difícil. Construa a STFT do zero usando apenas
mathe a DFT do Passo 3. Tamanho de frame 400, salto 160, janela de Hann. Plote as magnitudes commatplotlib.pyplot.imshow. Este é o espectrograma da Lição 02.
Termos-Chave
| Termo | O que as pessoas dizem | O que de fato significa |
|---|---|---|
| Taxa de amostragem | Quantas amostras por segundo | Frequência em Hz na qual o ADC mede o sinal. |
| Nyquist | A frequência máxima que você pode representar | sr/2; energia acima dela sofre aliasing para baixo. |
| Profundidade de bits | Resolução de cada amostra | int16 = 65.536 níveis; float32 = precisão de 24 bits em [-1, 1]. |
| DFT | A transformada de Fourier para sequências | N amostras → N coeficientes de frequência complexos. |
| FFT | A DFT rápida | Algoritmo O(N log N) que requer N = potência de 2. |
| Bin | Coluna de frequência | k · sr / N Hz; resolução = sr / N. |
| STFT | Espectrograma por baixo dos panos | FFT janelada em frames ao longo do tempo. |
| Aliasing | Fantasmas estranhos de frequência | Energia acima de Nyquist espelhando-se para bins mais baixos. |
Leitura Adicional
- Shannon (1949). Communication in the Presence of Noise — o artigo por trás do teorema da amostragem.
- Smith — The Scientist and Engineer's Guide to Digital Signal Processing — livro-texto de DSP gratuito e canônico.
- docs do librosa — introdução ao áudio — passo a passo prático com código.
- Heinrich Kuttruff — Room Acoustics (6ª ed.) — referência para entender por que o áudio do mundo real não é uma senoide limpa.
- Steve Eddins — FFT Interpretation notebook — intuição de bins de frequência esclarecida em 10 minutos.