A música acústica e os sinais digitais compartilham um princípio elementar estabelecido por Jean-Baptiste Joseph Fourier no início do século XIX: qualquer onda periódica pode ser aproximada pela soma ponderada de funções senoidais e cossenoidais.
Essa fundamentação matemática foi o alicerce do meu Trabalho de Conclusão de Curso em Matemática na UFRRJ e deu origem ao projeto MusicaPython.
1. A Formulação Trigonométrica
Seja uma função periódica $f(t)$ com período $T > 0$ e frequência fundamental $f_0 = \frac{1}{T}$. Sob as condições de Dirichlet, sua representação em Série de Fourier é dada por:
$$f(t) = a_0 + \sum_{n=1}^{\infty} \left[ a_n \cos\left(2\pi n f_0 t\right) + b_n \sin\left(2\pi n f_0 t\right) \right]$$Onde os coeficientes de Fourier medem a intensidade de cada harmônico $n$:
$$a_n = \frac{2}{T} \int_{0}^{T} f(t) \cos(2\pi n f_0 t) \, dt, \quad b_n = \frac{2}{T} \int_{0}^{T} f(t) \sin(2\pi n f_0 t) \, dt$$2. Amostragem Digital e Síntese Aditiva
Para sintetizar áudio digitalmente em um computador, discretizamos a variável contínua de tempo $t$ para instantes amostrados $t_k = \frac{k}{F_s}$, onde $F_s$ é a taxa de amostragem padrão (geralmente $44.100\text{ Hz}$):
$$x[k] = \sum_{n=1}^{N} A_n \sin\left( 2\pi n f_0 \frac{k}{F_s} + \phi_n \right)$$3. Implementação Prática em Python
Com poucas linhas de código utilizando apenas bibliotecas científicas de Python, podemos gerar uma nota musical rica em harmônicos e exportá-la diretamente para um arquivo WAV:
import numpy as np
import wave
import struct
def sintetizar_nota(frequencia=440.0, duracao=2.0, taxa_amostragem=44100):
t = np.linspace(0, duracao, int(taxa_amostragem * duracao), endpoint=False)
# Síntese aditiva: Fundamental + harmônicos com decaimento exponencial
sinal = (1.00 * np.sin(2 * np.pi * 1 * frequencia * t) +
0.50 * np.sin(2 * np.pi * 2 * frequencia * t) +
0.25 * np.sin(2 * np.pi * 3 * frequencia * t) +
0.12 * np.sin(2 * np.pi * 4 * frequencia * t))
# Envelope ADSR simplificado (fade-out para evitar estalos)
envelope = np.linspace(1.0, 0.05, len(sinal))
sinal = sinal * envelope
# Normalização para áudio de 16 bits (-32767 a +32767)
sinal_normalizado = (sinal / np.max(np.abs(sinal)) * 32767).astype(np.int16)
with wave.open("nota_la440.wav", "w") as wav_file:
wav_file.setnchannels(1) # Mono
wav_file.setsampwidth(2) # 2 bytes por amostra (16 bits)
wav_file.setframerate(taxa_amostragem)
wav_file.writeframes(sinal_normalizado.tobytes())
print("Áudio sintetizado com sucesso: nota_la440.wav")
if __name__ == "__main__":
sintetizar_nota()
4. Conclusão e Próximos Passos
A transição da dedução analítica das integrais de Fourier para a sua realização programática em Python ilustra a essência da modelagem matemática e computacional: formular fenômenos físicos com rigor e transformá-los em ferramentas interativas reais.