Skip to content

Communication TCP IP

pschatzmann edited this page Oct 22, 2026 · 1 revision

TCP/IP is the simplest way to transmit audio reliably between two devices: the data arrives completely and in order, and TCP's flow control automatically adapts the sender to the speed of the receiver. You don't need any special class: Arduino's WiFiClient (or EthernetClient) is already a Stream, so it can be used directly as audio source or audio sink. See Communication for the general considerations.

Flow control: no throttling needed

Over TCP the sender can't overrun the receiver. If the receiver plays the audio via I2S, its writes block as soon as the I2S buffer is full, so it reads from the connection only at the playback rate; the TCP window fills up, and TCP slows the sender down to exactly that rate. So unlike UDP, a sender that produces data as fast as it can (a generator, a file) needs no Throttle.

The price: a lost packet is retransmitted, which delays the data. Over a weak WiFi connection this shows as short interruptions rather than as lost audio - give the receiver enough buffer (e.g. a bigger I2S buffer) to bridge them.

Sending

From communication-ip-send.ino: the sender connects to the receiver as TCP client:

#include "AudioTools.h"
#include <WiFi.h>

AudioInfo info(16000, 1, 16);
SineGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
WiFiClient client;
StreamCopy copier(client, sound, 256);
const char *receiver = "192.168.1.33";  // IP of the receiver
uint16_t port = 8000;

void setup() {
  WiFi.begin("ssid", "password");
  while (WiFi.status() != WL_CONNECTED) delay(500);
  WiFi.setSleep(false);     // no WiFi power save
  client.setNoDelay(true);  // send small packets immediately
  sineWave.begin(info, N_B4);
}

void loop() {
  // (re)connect if necessary
  while (!client.connected() && !client.connect(receiver, port)) delay(5000);
  copier.copy();
}

Receiving

From communication-ip-receive.ino: the receiver is the TCP server and plays what it receives:

#include "AudioTools.h"
#include <WiFi.h>

AudioInfo info(16000, 1, 16);
WiFiServer server(8000);
WiFiClient client;
I2SStream out;
StreamCopy copier(out, client);

void setup() {
  WiFi.begin("ssid", "password");
  while (WiFi.status() != WL_CONNECTED) delay(500);
  WiFi.setSleep(false);
  server.begin();
  auto config = out.defaultConfig(TX_MODE);
  config.copyFrom(info);
  out.begin(config);
}

void loop() {
  if (!client) client = server.available();  // wait for the sender
  if (client.connected()) {
    copier.copy();
  } else {
    delay(100);
  }
}

communication-ip-receive_measure.ino writes to a MeasuringStream instead, which reports the received bytes per second - a good way to check what your network can deliver.

Things to consider

  • The audio format is not transmitted: sender and receiver must agree on it - or transmit a format with a header (e.g. WAV via WAVEncoder/WAVDecoder) or a codec (see Encoding and Decoding of Audio) to reduce the bandwidth.
  • WiFi power save: switch it off with WiFi.setSleep(false) - it delays and throttles the data considerably.
  • Clock drift: since the receiver controls the rate, there are no buffer overflows; but the sender's source may run at its own clock (e.g. an I2S microphone), and then the sender's buffer slowly fills up or empties. See Communication.
  • Several receivers: a TCP connection has exactly one receiver. To serve several, use an HTTP Server or UDP broadcast.

Clone this wiki locally