



Este trabalho apresenta um laboratório experimental utilizando um microcontrolador ESP32 configurado como um microfone de rede capaz de capturar áudio analógico, convertê-lo para o domínio digital e transmiti-lo por meio de protocolos de transporte de mídia. O fluxo de áudio é enviado para um gateway responsável por receber os pacotes e redistribuí-los para múltiplos clientes.
Além da implementação do sistema, o experimento inclui a análise do tráfego de rede, permitindo observar diretamente a estrutura dos pacotes e o fluxo de dados entre os dispositivos envolvidos.
O objetivo do trabalho não é propor uma solução definitiva para sistemas de áudio em rede, mas sim apresentar uma plataforma didática e simplificada que permita investigar, em escala reduzida, os princípios fundamentais presentes em arquiteturas profissionais de distribuição de áudio digital.
Sistemas de áudio em rede são atualmente utilizados em diversas aplicações, como sistemas de intercomunicação, monitoramento remoto e distribuição de áudio em instalações profissionais, como estúdios, emissoras de rádio e ambientes corporativos. Nesse contexto, soluções consolidadas da indústria, como o padrão aberto AES67 e tecnologias proprietárias como Dante, permitem a transmissão de múltiplos canais de áudio com baixa latência e alta sincronização entre dispositivos.
Apesar da ampla adoção dessas tecnologias, a compreensão prática do funcionamento interno de sistemas AoIP pode ser complexa. Muitas das soluções comerciais disponíveis são implementadas em equipamentos dedicados ou em plataformas fechadas, o que dificulta a observação direta de aspectos fundamentais do processo de transmissão, como a captura do sinal analógico, a digitalização, o encapsulamento em pacotes de rede e o comportamento do tráfego de dados durante a comunicação.
Diante desse cenário, torna-se relevante desenvolver abordagens experimentais que permitam explorar esses conceitos de forma acessível e observável. Ambientes de laboratório que utilizem dispositivos de baixo custo e ferramentas de análise de rede podem facilitar a compreensão da arquitetura e do fluxo de dados envolvidos na transmissão de áudio em rede.
Audio over IP (AoIP) refere-se à transmissão de sinais de áudio digital através de redes baseadas no protocolo IP. Diferentemente de sistemas tradicionais de distribuição de áudio, nos quais os sinais são transportados por cabos analógicos dedicados, sistemas AoIP utilizam infraestrutura de rede de dados para transportar o áudio em forma de pacotes digitais.
Essa abordagem permite maior flexibilidade na distribuição do sinal, possibilitando que múltiplos dispositivos compartilhem fluxos de áudio através da mesma rede. Além disso, arquiteturas baseadas em rede facilitam a expansão do sistema, a integração entre equipamentos e a distribuição do áudio para diferentes locais sem a necessidade de conexões físicas dedicadas para cada canal.
Áudio analógico: representação contínua do sinal sonoro no domínio elétrico, normalmente gerado por dispositivos como microfones ou captadores. Esse tipo de sinal varia continuamente ao longo do tempo e é tradicionalmente transportado por cabos analógicos diretamente entre os equipamentos.
Áudio digital: representação discreta do sinal analógico por meio de amostras numéricas obtidas através do processo de conversão analógico-digital. Essa representação permite que o áudio seja armazenado, processado e transmitido utilizando sistemas computacionais.
A diferença entre essas duas formas de representação pode ser compreendida a partir do processo de conversão analógico-digital (A/D), no qual o sinal contínuo é inicialmente amostrado em intervalos regulares de tempo e, em seguida, cada amostra é quantizada em valores numéricos discretos.

Na transmissão em rede, os dados digitais são organizados em pacotes e enviados por meio de protocolos de comunicação baseados em redes IP. Cada pacote carrega uma parte do fluxo de áudio, juntamente com informações de controle que permitem ao receptor reconstituir corretamente o sinal original. Para que essa comunicação ocorra de forma eficiente, alguns fatores de desempenho são fundamentais.
A latência corresponde ao tempo total entre a captura do áudio em um dispositivo e sua reprodução no destino, sendo um parâmetro crítico em aplicações em tempo real.
O jitter à variação no tempo de chegada dos pacotes sucessivos. Como os dados podem percorrer caminhos distintos na rede ou sofrer atrasos variáveis, torna-se necessário o uso de buffers e mecanismos de compensação no receptor para garantir uma reprodução contínua e estável.
A qualidade do sinal recebido está diretamente relacionada à perda de pacotes. Em redes que não garantem entrega confiável, parte dos dados pode não chegar ao destino, causando interrupções ou distorções no áudio reproduzido.
Por fim, a largura de banda disponível na rede determina a quantidade de dados que pode ser transmitida por unidade de tempo. Como fluxos de áudio digital podem exigir taxas elevadas, especialmente em aplicações multicanal ou de alta fidelidade, é essencial considerar a capacidade da rede no projeto de sistemas de áudio sobre IP (AoIP).
A transmissão de áudio em redes IP depende de protocolos de comunicação responsáveis por transportar os dados entre os dispositivos participantes do sistema. No experimento apresentado neste trabalho, o fluxo de áudio é transmitido utilizando o protocolo UDP como camada de transporte, enquanto o encapsulamento dos dados de áudio é realizado pelo protocolo RTP.
O User Datagram Protocol (UDP) é um protocolo de transporte caracterizado por sua simplicidade e baixa sobrecarga, pois realiza o envio de datagramas sem estabelecer uma sessão formal entre os dispositivos e sem garantir a entrega dos pacotes. A prioridade está na continuidade do fluxo de dados e na redução da latência, mesmo que eventualmente alguns pacotes sejam perdidos durante a transmissão.
O Real-time Transport Protocol (RTP) é um protocolo desenvolvido especificamente para o transporte de fluxos de mídia em tempo real sobre redes IP, normalmente utilizado em conjunto com o UDP para transportar dados de áudio ou vídeo em aplicações de comunicação multimídia, adicionando informações de controle aos dados de áudio transmitidos pela rede.
Cada pacote RTP contém um cabeçalho com campos que auxiliam o receptor a interpretar corretamente o fluxo de mídia. Com esses dados, o receptor pode reorganizar pacotes que chegaram fora de ordem, compensar variações no tempo de chegada e reproduzir o áudio de forma contínua e sincronizada.

A comunicação em redes de computadores é frequentemente descrita utilizando o modelo OSI, que organiza as funções de comunicação em camadas hierárquicas. Cada camada é responsável por um conjunto específico de operações, desde a transmissão física dos dados até o processamento das aplicações.
No experimento apresentado neste trabalho, apenas algumas dessas camadas são diretamente relevantes para a transmissão do fluxo de áudio.

O dispositivo transmissor é responsável por capturar o áudio analógico, convertê-lo em dados digitais e enviá-lo pela rede utilizando o protocolo RTP sobre UDP.
A arquitetura do firmware foi organizada em módulos independentes responsáveis pela captura do áudio e pela transmissão na rede. Essa divisão facilita a compreensão do fluxo de dados e a manutenção do código.

O microfone utilizado é um microfone eletreto com circuito amplificador. O sinal produzido pelo microfone é um sinal analógico de baixa amplitude que precisa ser amplificado antes de ser convertido pelo microcontrolador.
O ESP32 possui conversores analógico-digitais (ADC) de 12 bits integrados, permitindo a digitalização direta do sinal de áudio. No sistema implementado, o sinal do microfone é conectado ao pino GPIO 34, correspondente ao canal ADC1_CHANNEL_6.
O uso de um microcontrolador com Wi-Fi integrado permite que a transmissão seja realizada diretamente pela rede local, sem necessidade de hardware adicional para comunicação.
O processo de digitalização do áudio consiste em amostrar o sinal analógico em intervalos regulares e armazenar essas amostras em um buffer de memória. Essas amostras representam a forma de onda do sinal ao longo do tempo e permitem que o áudio seja manipulado e transmitido digitalmente.
No arquivo principal do programa (projeto_esp32.ino), define-se o tamanho do buffer de áudio que será utilizado para armazenar temporariamente as amostras capturadas antes da transmissão pela rede.
int16_t buffer[256]; int valordobuffer = 256;
A taxa de amostragem (SAMPLE_RATE) é definida no módulo responsável pela captura de áudio (audio_capture). Esse módulo controla o intervalo entre as leituras do conversor analógico-digital (ADC) do ESP32, determinando quantas amostras do sinal de áudio serão coletadas por segundo.
#define SAMPLE_RATE 16000
Esse valor indica que o sistema realiza 16000 leituras do ADC por segundo, gerando a sequência de amostras que representa o sinal de áudio digitalizado, porém a taxa de amostragem pode ser ajustada conforme a aplicação. Valores mais altos permitem representar o sinal de áudio com maior fidelidade, porém aumentam o volume de dados gerados e, consequentemente, a quantidade de dados transmitidos pela rede.
Os parâmetros de rede são definidos no módulo responsável pela transmissão (wifi_stream). Nesse arquivo são configuradas as informações necessárias para que o ESP32 se conecte à rede e envie os pacotes de áudio ao dispositivo receptor.
#define WIFI_SSID "MinhaRede" #define WIFI_PASSWORD "minhasenha" const IPAddress destIP(192,168,0,100);
Dessa forma, o firmware pode ser facilmente adaptado para diferentes experimentos de transmissão de áudio em rede, permitindo variar parâmetros como latência, taxa de dados e topologia de comunicação.
O pacote enviado pela rede é composto por Cabeçalho RTP (12 bytes) e Payload contendo as amostras de áudio. Inicialmente, o firmware cria um buffer que armazenará todo o pacote a ser transmitido com o tamanho calculado somando o cabeçalho RTP com o tamanho do bloco de áudio capturado.
Em seguida, o cabeçalho RTP é preenchido com os valores necessários para o controle do fluxo de mídia. Entre esses campos estão o número de sequência, que permite ao receptor detectar perda ou reordenação de pacotes, o timestamp, que indica a posição temporal do bloco de áudio dentro do fluxo contínuo, e SSRC (Synchronization Source), que identifica a origem do fluxo RTP, sendo especialmente relevante em cenários com múltiplos transmissores.
Após a montagem do cabeçalho, o bloco de áudio armazenado no buffer é copiado para a área de payload do pacote RTP. O pacote completo é então transmitido pela rede utilizando o protocolo UDP.
Por fim, os campos de controle do RTP são atualizados para o próximo pacote: o número de sequência é incrementado e o timestamp avança de acordo com o número de amostras transmitidas.
void wifi_stream_send(int16_t *buffer, int samples) {
// ------------------------------------------------
// 1. Criação do pacote RTP (header + áudio)
// ------------------------------------------------
uint8_t packet[12 + samples * sizeof(int16_t)];
// ------------------------------------------------
// 2. Montagem do cabeçalho RTP (12 bytes)
// ------------------------------------------------
packet[0] = 0x80; // Versão RTP
packet[1] = 96; // Payload type
// Número de sequência (identifica ordem dos pacotes)
packet[2] = rtp_seq >> 8;
packet[3] = rtp_seq & 0xFF;
// Timestamp RTP (posição temporal do áudio)
packet[4] = (rtp_timestamp >> 24) & 0xFF;
packet[5] = (rtp_timestamp >> 16) & 0xFF;
packet[6] = (rtp_timestamp >> 8) & 0xFF;
packet[7] = rtp_timestamp & 0xFF;
// SSRC (identificador da fonte RTP)
packet[8] = (rtp_ssrc >> 24) & 0xFF;
packet[9] = (rtp_ssrc >> 16) & 0xFF;
packet[10] = (rtp_ssrc >> 8) & 0xFF;
packet[11] = rtp_ssrc & 0xFF;
// ------------------------------------------------
// 3. Inserção do payload de áudio
// ------------------------------------------------
memcpy(packet + 12, buffer, samples * sizeof(int16_t));
// ------------------------------------------------
// 4. Envio do pacote RTP encapsulado em UDP
// ------------------------------------------------
udp.beginPacket(destIP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
// ------------------------------------------------
// 5. Atualização dos parâmetros RTP
// ------------------------------------------------
rtp_seq++; // próximo pacote
rtp_timestamp += samples; // avanço temporal do áudio
}
Para compreender o funcionamento geral do transmissor, basta observar o fluxo implementado no programa principal. O firmware executa continuamente a função de captura de um bloco de amostras de áudio e o envio desse bloco pela rede.
O buffer de áudio é preenchido pelo módulo de captura e, em seguida, transmitido pelo módulo responsável pela comunicação de rede.
void loop()
{
audio_capture_read(buffer,256); // captura bloco de áudio
wifi_stream_send(buffer,256); // envia bloco pela rede (RTP/UDP)
}
Para permitir a verificação prática do sistema desenvolvido com o ESP32, foi utilizado um gateway simples em Python responsável apenas por receber o fluxo RTP transmitido pelo dispositivo e reproduzi-lo localmente.
O objetivo desse programa não é implementar um sistema completo de áudio em rede, mas apenas fornecer uma forma rápida de validar o funcionamento do transmissor durante os testes.
Ao iniciar o script, o programa:
Na inicialização, o script lista os dispositivos de áudio disponíveis no sistema e permite selecionar manualmente qual deles será utilizado para reprodução e durante a execução pode exibir no terminal informações simples de monitoramento do áudio recebido.

import socket
import numpy as np
import sounddevice as sd
import threading
ENABLE_MONITOR = True # Ativar monitoramento de pico/média do buffer (True/False)
# -----------------------------
# Configurações UDP e áudio
# -----------------------------
UDP_PORT = 5004 # Porta, deve ser a mesma do envio RTP
SAMPLE_RATE = 16000 # Hz, deve ser o mesmo do envio RTP
BLOCK_SIZE = 256 # 256 amostras = 16 ms a 16 kHz
BUFFER_BLOCKS = 16 # ~256 ms de buffer
# -----------------------------
# Buffer circular
# -----------------------------
audio_buffer = np.zeros(BLOCK_SIZE * BUFFER_BLOCKS, dtype=np.int16)
write_idx = 0
read_idx = 0
lock = threading.Lock()
# -----------------------------
# Thread de recebimento UDP
# -----------------------------
def udp_receive():
global write_idx
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", UDP_PORT))
print(f"Escutando RTP UDP :{UDP_PORT}")
while True:
data, addr = sock.recvfrom(2048)
if len(data) < 12:
continue
payload = data[12:] # remove header RTP
samples = np.frombuffer(payload, dtype=np.int16)
if len(samples) != BLOCK_SIZE:
continue
with lock:
end = write_idx + BLOCK_SIZE
if end < len(audio_buffer):
audio_buffer[write_idx:end] = samples
else:
part1 = len(audio_buffer) - write_idx
audio_buffer[write_idx:] = samples[:part1]
audio_buffer[:BLOCK_SIZE - part1] = samples[part1:]
write_idx = (write_idx + BLOCK_SIZE) % len(audio_buffer)
# -----------------------------
# Callback de áudio
# -----------------------------
def audio_callback(outdata, frames, time, status):
global read_idx
with lock:
available = (write_idx - read_idx) % len(audio_buffer)
if available < frames:
outdata[:] = np.zeros((frames, 1), dtype=np.int16)
return
end = read_idx + frames
if end < len(audio_buffer):
outdata[:] = audio_buffer[read_idx:end].reshape(-1, 1)
else:
part1 = len(audio_buffer) - read_idx
outdata[:part1] = audio_buffer[read_idx:].reshape(-1, 1)
outdata[part1:] = audio_buffer[:frames-part1].reshape(-1, 1)
read_idx = (read_idx + frames) % len(audio_buffer)
# -----------------------------
# Seleção de dispositivo
# -----------------------------
print("Dispositivos de saída disponíveis:")
devices = sd.query_devices()
output_devices = [d for d in devices if d['max_output_channels'] > 0]
for i, d in enumerate(output_devices):
print(f"{i}: {d['name']} ({d['hostapi']})")
while True:
try:
dev_index = int(input("Escolha o dispositivo de saída pelo número: "))
if 0 <= dev_index < len(output_devices):
break
else:
print("Número inválido, tente novamente.")
except ValueError:
print("Digite um número válido.")
devicenum = output_devices[dev_index]['index']
print(f"Usando dispositivo: {output_devices[dev_index]['name']}")
# -----------------------------
# Thread de rede
# -----------------------------
threading.Thread(target=udp_receive, daemon=True).start()
# -----------------------------
# Stream de áudio
# -----------------------------
stream = sd.OutputStream(
samplerate=SAMPLE_RATE,
channels=1,
dtype="int16",
blocksize=BLOCK_SIZE,
callback=audio_callback,
device=devicenum
)
stream.start()
print("Player iniciado. Ctrl+C para sair.")
# -----------------------------
# Função de monitoramento
# -----------------------------
def monitor_audio(interval=1.0):
"""Exibe pico e média do buffer a cada intervalo (segundos)."""
while True:
if ENABLE_MONITOR:
with lock:
buf_snapshot = audio_buffer.copy()
peak = np.max(np.abs(buf_snapshot))
avg = np.mean(np.abs(buf_snapshot))
print(f"Pico: {peak} | Média: {int(avg)}")
stop_event.wait(interval)
# -----------------------------
# Loop principal leve
# -----------------------------
stop_event = threading.Event()
threading.Thread(target=monitor_audio, daemon=True).start()
try:
stop_event.wait() # espera infinita sem consumir CPU
except KeyboardInterrupt:
stop_event.set()
stream.stop()
stream.close()
print("Player encerrado.")
Para facilitar a redistribuição do áudio recebido pelo gateway para outros dispositivos da rede, foi utilizado o software Audio Relay, que permite facilmente transmitir o áudio capturado em um computador para outros clientes conectados na mesma rede.
No sistema utilizado nos experimentos, o áudio reproduzido pelo gateway foi redirecionado para um dispositivo virtual criado pelo BlackHole, que atua como uma interface de áudio interna no sistema operacional.
https://existential.audio/blackhole/Dessa forma, o fluxo de áudio segue o seguinte caminho:
ESP32 → Python → BlackHole → Audio Relay → clientes na rede
Sistemas de áudio em rede podem ser organizados segundo diferentes arquiteturas, dependendo da forma como os fluxos de áudio são distribuídos entre os dispositivos participantes.
Uma das estruturas mais simples consiste no modelo fonte–destino, no qual um dispositivo transmissor envia o fluxo de áudio diretamente para um único receptor através da rede.
Em sistemas mais complexos, assim como neste projeto, se utiliza uma arquitetura baseada em distribuição para múltiplos clientes, na qual um dispositivo transmissor envia o fluxo para um ponto intermediário responsável por redistribuir o áudio para diversos receptores.

Para esse projeto, você irá precisar dos seguintes componentes:
No diagrama apresentado, desenvolvido na plataforma Wokwi, um potenciômetro foi utilizado para representar o comportamento do módulo de microfone analógico no sistema.
MAIN.INO
#include "audio_capture.h"
#include "wifi_stream.h"
int16_t buffer[256];
int valordobuffer = 256;
void setup()
{
Serial.begin(115200);
audio_capture_init();
wifi_stream_init();
}
void loop()
{
audio_capture_read(buffer,valordobuffer);
wifi_stream_send(buffer,valordobuffer);
}
AUDIO_CAPTURE.H
#pragma once #include <stdint.h> void audio_capture_init(); int audio_capture_read(int16_t *buffer, int samples);AUDIO_CAPTURE.CPP
#include "audio_capture.h"
#include <Arduino.h>
#include <driver/adc.h>
// Taxa de amostragem do sistema de áudio (16 kHz)
// Deve ser a mesma utilizada pelo gateway receptor
#define SAMPLE_RATE 16000 // ===== Hz, O MESMO QUE NO GATEWAY =====
// Período entre amostras em microssegundos
// 1 segundo = 1.000.000 µs
#define SAMPLE_PERIOD (1000000 / SAMPLE_RATE)
// Variável que armazena o instante da próxima amostragem
static uint32_t next_sample;
// Variáveis usadas no processamento do sinal
// dc: estimativa do offset DC do ADC
// hp_y e hp_x_prev: estados do filtro passa-alta
static float dc = 2048;
static float hp_y = 0;
static float hp_x_prev = 0;
// Inicialização do sistema de captura de áudio
void audio_capture_init()
{
// Configura resolução do ADC para 12 bits
adc1_config_width(ADC_WIDTH_BIT_12);
// Configura atenuação do canal ADC
// ADC1_CHANNEL_6 corresponde ao GPIO34 no ESP32
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); // ===== GPIO 34 =====
// Inicializa o temporizador de amostragem
next_sample = micros();
}
// Função que captura um bloco de amostras de áudio
// buffer: ponteiro para o vetor onde os samples serão armazenados
// samples: número de amostras a capturar
int audio_capture_read(int16_t *buffer, int samples)
{
for(int i=0;i<samples;i++)
{
// Aguarda até o instante programado da próxima amostragem
// Isso garante uma taxa de amostragem estável
while(micros() < next_sample);
// Agenda o instante da próxima amostra
next_sample += SAMPLE_PERIOD;
// Lê o valor bruto do ADC
int raw = adc1_get_raw(ADC1_CHANNEL_6);
// ===== Remoção de offset DC =====
// Calcula lentamente a média do sinal (filtro passa-baixa)
dc = dc * 0.999 + raw * 0.001;
// Remove o componente DC do sinal
float audio = raw - dc;
// ===== Filtro passa-alta simples =====
// Reduz ruídos de baixa frequência e variações lentas
float alpha = 0.98;
hp_y = alpha * (hp_y + audio - hp_x_prev);
// Armazena a última entrada do filtro
hp_x_prev = audio;
// Converte o valor filtrado para 16 bits
// e grava no buffer de saída
buffer[i] = (int16_t)hp_y;
}
// Retorna o número de amostras capturadas
return samples;
}
WIFI_STREAM.H
#pragma once #include <stdint.h> void wifi_stream_init(); void wifi_stream_send(int16_t *buffer, int samples);WIFI_STREAM.CPP
#include "wifi_stream.h"
#include <WiFi.h>
#include <WiFiUdp.h>
#include <string.h>
// Credenciais da rede Wi-Fi utilizada pelo experimento
#define WIFI_SSID "SUA_REDE"
#define WIFI_PASSWORD "SUA_SENHA"
// Endereço IP do gateway que receberá o fluxo de áudio
#define ipgateway 192,168,0,100 // ===== IP DO GATEWAY =====
// Porta UDP utilizada para o envio dos pacotes RTP
#define UDP_PORT 5004 // ===== PORTA DO GATEWAY =====
// ===== Variáveis de controle do protocolo RTP =====
// Número de sequência do pacote RTP
// Incrementado a cada pacote transmitido
static uint16_t rtp_seq = 0;
// Timestamp RTP
// Representa a posição temporal das amostras no fluxo de áudio
static uint32_t rtp_timestamp = 0;
// Identificador da fonte RTP (SSRC)
// Permite identificar a origem do fluxo dentro da sessão
static const uint32_t rtp_ssrc = 0x12345678;
// Endereço IP de destino (gateway)
IPAddress destIP(ipgateway);
// Objeto responsável pela comunicação UDP
WiFiUDP udp;
// Inicializa a conexão Wi-Fi e prepara o envio UDP
void wifi_stream_init() {
Serial.print("Conectando Wi-Fi...");
// Coloca o ESP32 em modo estação (cliente da rede)
WiFi.mode(WIFI_STA);
// Inicia a conexão com a rede configurada
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
// Aguarda até que a conexão seja estabelecida
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Informa no terminal que a conexão foi concluída
Serial.println("Conectado!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
// Inicializa o socket UDP local
udp.begin(UDP_PORT);
}
// Envia um bloco de amostras de áudio através de RTP/UDP
// buffer: vetor contendo as amostras capturadas
// samples: quantidade de amostras presentes no buffer
void wifi_stream_send(int16_t *buffer, int samples) {
// Cria um pacote contendo:
// 12 bytes de cabeçalho RTP + dados de áudio
uint8_t packet[12 + samples * sizeof(int16_t)];
// ===== Construção do cabeçalho RTP =====
// Byte 0
// 0x80 = versão RTP 2, sem padding, sem extensão
packet[0] = 0x80;
// Byte 1
// Payload type 96 (tipo dinâmico comum para áudio)
packet[1] = 96;
// Número de sequência (16 bits)
packet[2] = rtp_seq >> 8;
packet[3] = rtp_seq & 0xFF;
// Timestamp RTP (32 bits)
packet[4] = (rtp_timestamp >> 24) & 0xFF;
packet[5] = (rtp_timestamp >> 16) & 0xFF;
packet[6] = (rtp_timestamp >> 8) & 0xFF;
packet[7] = rtp_timestamp & 0xFF;
// Identificador da fonte (SSRC)
packet[8] = (rtp_ssrc >> 24) & 0xFF;
packet[9] = (rtp_ssrc >> 16) & 0xFF;
packet[10] = (rtp_ssrc >> 8) & 0xFF;
packet[11] = rtp_ssrc & 0xFF;
// ===== Inserção dos dados de áudio =====
// Copia o conteúdo do buffer de amostras para o pacote
// logo após o cabeçalho RTP
memcpy(packet + 12, buffer, samples * sizeof(int16_t));
// ===== Envio do pacote pela rede =====
// Inicia o pacote UDP com destino ao gateway
udp.beginPacket(destIP, UDP_PORT);
// Escreve o pacote completo (RTP + áudio)
udp.write(packet, sizeof(packet));
// Finaliza e envia o pacote
udp.endPacket();
// ===== Atualização dos campos RTP =====
// Incrementa o número de sequência do pacote
rtp_seq++;
// Avança o timestamp de acordo com o número de amostras enviadas
rtp_timestamp += samples;
} Para analisar o comportamento do sistema de transmissão de áudio em rede foi utilizada a ferramenta Wireshark, um software de código aberto desenvolvido e mantido pela Wireshark Foundation, utilizado em atividades de diagnóstico de rede, análise de protocolos, ensino e pesquisa em engenharia de redes.
Essa ferramenta foi utilizada para observar o tráfego gerado pelo sistema experimental de transmissão de áudio, permitindo identificar as características dos pacotes enviados pelo dispositivo transmissor e analisar o comportamento temporal do fluxo de dados.
Na interface do software, cada linha da tabela representa um pacote de dados capturado na rede. As colunas exibidas fornecem informações importantes para a análise do fluxo de comunicação entre os dispositivos.
Na captura utilizada neste experimento foram destacados dois fluxos principais de comunicação: o fluxo de entrada de áudio no gateway, correspondente aos pacotes enviados pelo dispositivo transmissor, e o fluxo de saída de áudio, correspondente à redistribuição do áudio para os dispositivos clientes conectados ao sistema.

A partir da identificação do fluxo de áudio na captura de rede, foi realizada a análise dos tempos de chegada dos pacotes transmitidos pelo sistema. Essa análise foi baseada na coluna Time do Wireshark, que permite observar o instante em que cada pacote foi capturado e, consequentemente, calcular os intervalos entre transmissões sucessivas.
Essas variações caracterizam o fenômeno conhecido como jitter, que corresponde à flutuação temporal na chegada dos pacotes em relação ao comportamento ideal esperado. Mesmo que o transmissor mantenha uma taxa de envio aproximadamente constante, fatores como o processamento da pilha de rede, o agendamento de tarefas do sistema e o próprio comportamento do meio de transmissão podem introduzir pequenas diferenças entre os tempos observados.
A análise das capturas evidencia que os pacotes apresentam **variações leves** no intervalo de chegada, alternando entre **atrasos** e **adiantamentos** em relação ao período esperado. Apesar disso, o comportamento geral do **fluxo se mantém estável**, sem perdas significativas ou variações abruptas que comprometam a continuidade da transmissão.

Embora o sistema apresente variações na chegada dos pacotes, essas flutuações não causam interrupções perceptíveis no áudio devido ao uso de um buffer circular no receptor, que armazena temporariamente os dados e desacopla a recepção da rede da reprodução, garantindo consumo contínuo em taxa constante.
Dessa forma, pequenas antecipações ou atrasos na chegada dos pacotes são absorvidos e mantém uma fila contínua de dados disponíveis para reprodução. Esse mecanismo garante estabilidade ao fluxo de áudio, evitando interrupções mesmo na presença de jitter na rede.
Em sistemas baseados em User Datagram Protocol, esse tipo de abordagem é essencial, uma vez que o protocolo não possui mecanismos nativos de controle de ordem ou retransmissão.

Este trabalho apresentou a implementação e análise de um ambiente experimental de Audio over IP (AoIP) baseado em um microcontrolador ESP32 atuando como transmissor de áudio em rede, um gateway intermediário em Python e ferramentas de monitoramento de tráfego. A partir dessa estrutura, foi possível reproduzir, em escala reduzida, a captura e digitalização do sinal, empacotamento em RTP e transmissão via UDP, os principais elementos presentes em sistemas profissionais de distribuição de áudio digital
Os resultados obtidos por meio da análise do tráfego de rede demonstraram o comportamento esperado de um fluxo de mídia em tempo real, com presença de pequenas variações temporais entre pacotes (jitter), mitigadas pelo uso de buffers no receptor. Dessa forma, o sistema manteve a continuidade da reprodução mesmo diante das limitações inerentes ao transporte não confiável do UDP, evidenciando a importância de mecanismos de buffering e sincronização em arquiteturas de áudio em rede.
TANENBAUM, Andrew S.; WETHERALL, David J. Redes de Comp. https://www-usr.inf.ufsm.br/~rose/Tanenbaum.pdf
RICHARDSON, Mark. Getting Started with ESP32. https://docs.espressif.com/projects/esp-idf/en/latest/esp32/
IETF. RFC 3550 - RTP: A Transport Protocol for Real-Time Applications. https://www.rfc-editor.org/rfc/rfc3550
IETF. RFC 768 - User Datagram Protocol (UDP). https://www.rfc-editor.org/rfc/rfc768
WIRESHARK FOUNDATION. Wireshark User Guide and Documentation. https://www.wireshark.org/docs/
AUDACITY TEAM. Digital Audio Concepts and PCM Representation. https://manual.audacityteam.org/
BLACKHOLE AUDIO. BlackHole Virtual Audio Driver Documentation. https://existential.audio/blackhole/
AUDIO RELAY. Audio Relay - Wireless Audio Streaming Application. https://audiorelay.net/
|
Este trabalho apresenta um laboratório experimental utilizando um microcontrolador ESP32 configurado como um microfone de rede capaz de capturar áudio analógico, convertê-lo para o domínio digital e transmiti-lo por meio de protocolos de transporte de mídia.
Encontre tudo na Loja Eletrogate com frete grátis para compras acima de R$ 200