Skip to content

Communication UDP

pschatzmann edited this page Oct 22, 2026 · 1 revision

UDP sends audio as individual datagrams over WiFi (or any other network with an Arduino UDP implementation). It has the lowest overhead and latency of all network protocols, and it supports broadcast and multicast, so one sender can reach many receivers. But there is no flow control and no retransmission: lost packets are gone, and the sender must not send faster than the receiver plays. See Communication for the general considerations.

The UDPStream class

UDPStream (AudioTools/Communication/UDPStream.h) wraps an Arduino UDP object (by default a WiFiUDP) as a Stream, so you can use it as audio source and as audio sink. If you pass the SSID and password, it also connects to WiFi (on ESP32 it switches off WiFi power save).

Method Description
UDPStream(ssid, password), UDPStream(udp) constructors: log in to WiFi, or use your own UDP object (e.g. EthernetUDP)
begin(ip, port) send to this address and port (a broadcast address like 192.168.1.255 reaches all devices of the network)
begin(port) receive on this port; replies go to the sender of the last packet
beginMulticast(ip, port) receive from a multicast group
setTarget(ip, port) changes the target address
write() each call sends one datagram
readBytes(), available() read the received data

Each write() becomes one datagram, so keep the writes below the MTU (about 1400 bytes) - a StreamCopy with the default buffer size does that.

Sending

From communication-udp-send.ino: a generator delivers the data as fast as it can, so a Throttle limits the sending to the audio rate:

#include "AudioTools.h"
#include "AudioTools/Communication/UDPStream.h"

AudioInfo info(22000, 1, 16);
SineGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
UDPStream udp("ssid", "password");
Throttle throttle(udp);
IPAddress udpAddress(192, 168, 1, 255);  // broadcast
const int udpPort = 7000;
StreamCopy copier(throttle, sound);

void setup() {
  sineWave.begin(info, N_B4);
  udp.begin(udpAddress, udpPort);
  auto cfg = throttle.defaultConfig();
  cfg.copyFrom(info);
  throttle.begin(cfg);
}

void loop() { copier.copy(); }

A source that delivers at the audio rate by itself (I2S microphone, ADC) needs no Throttle.

Receiving

From communication-udp-receive.ino:

#include "AudioTools.h"
#include "AudioTools/Communication/UDPStream.h"

AudioInfo info(22000, 1, 16);
UDPStream udp("ssid", "password");
I2SStream out;
StreamCopy copier(out, udp);

void setup() {
  udp.begin(7000);
  auto config = out.defaultConfig(TX_MODE);
  config.copyFrom(info);
  config.buffer_size = 1024;
  config.buffer_count = 20;  // big buffer to absorb the jitter
  out.begin(config);
}

void loop() { copier.copy(); }

Things to consider

  • The audio format is not transmitted: sender and receiver must use the same sample rate, channels and bits per sample - or send an encoded format (e.g. ADPCM, see Encoding and Decoding of Audio) whose decoder can deal with it.
  • Compressed data: if a packet gets lost, a decoder must be able to resynchronize - use a codec with self-contained frames, and write one frame per datagram.
  • Clock drift: the clocks of sender and receiver differ slightly, so the receiver's buffer slowly runs over or empties. A big output buffer delays this; an AdaptiveResamplingStream compensates it (see Communication).
  • Lost packets: forward error correction (HammingFEC, ReedSolomonFEC) can repair corrupted data, but not replace a lost datagram. If you can't tolerate gaps, use TCP/IP.

For a standardized UDP audio protocol that also works with PC software (e.g. VoiceMeeter), see VBAN.

Clone this wiki locally