Repository navigation
Communication TCP IP
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.
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.
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();
}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.
-
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.