Skip to content

Communication VBAN

pschatzmann edited this page Oct 22, 2026 · 1 revision

VBAN is a simple protocol for audio over UDP, defined by VB-Audio for its VoiceMeeter mixer. Each packet carries a small header with the stream name and the audio format, so - unlike plain UDP - the receiver knows the format, and you can exchange audio with VoiceMeeter, VBAN apps on mobile phones and other devices. See Communication for the general considerations.

The VBANStream class

VBANStream (AudioTools/Communication/VBANStream.h) is an audio source (RX_MODE) and audio sink (TX_MODE). It is supported on the ESP32 with WiFi. The configuration (VBANConfig) contains the audio format and:

Field Description
ssid, password WiFi login
stream_name name of the VBAN stream (e.g. "Stream1"): a receiver only accepts the stream with its name
udp_port default 6980
target_ip receiver; {0,0,0,0} broadcasts
throttle_active set to true if the source delivers faster than real time (generator, file)
throttle_correction_us fine tuning of the throttle against overflows/underruns
max_write_size maximum size of one write
rx_buffer_count receive buffers
device_name, manufacturer_name, application_name, ... reply to VBAN discovery (PING), so that VoiceMeeter identifies the device

Sending

From streams-generator-vban.ino:

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

AudioInfo info(44100, 2, 16);
SineGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
VBANStream out;
StreamCopy copier(out, sound, 2048);  // 44100 stereo needs 2048

void setup(void) {
  auto cfg = out.defaultConfig(TX_MODE);
  cfg.copyFrom(info);
  cfg.ssid = "ssid";
  cfg.password = "password";
  cfg.stream_name = "Stream1";
  cfg.target_ip = IPAddress{192, 168, 1, 37};  // the PC with VoiceMeeter
  cfg.throttle_active = true;  // the generator is faster than real time
  if (!out.begin(cfg)) stop();
  sineWave.begin(info, N_B4);
}

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

In VoiceMeeter open the VBAN dialog and activate an incoming stream with the same name and the IP of the microcontroller.

Receiving

From streams-vban-audiokit.ino: plays a stream from VoiceMeeter (or a VBAN app) on an AudioKit:

#include "AudioTools.h"
#include "AudioTools/Communication/VBANStream.h"
#include "AudioTools/AudioLibs/AudioBoardStream.h"

AudioBoardStream out(AudioKitEs8388V1);  // or I2SStream
VBANStream in;
StreamCopy copier(out, in);

void setup(void) {
  auto cfg_out = out.defaultConfig(TX_MODE);
  if (!out.begin(cfg_out)) stop();
  in.addNotifyAudioChange(out);  // the output follows the format of the stream

  auto cfg_in = in.defaultConfig(RX_MODE);
  cfg_in.ssid = "ssid";
  cfg_in.password = "password";
  cfg_in.stream_name = "Talkie";  // name of the outgoing stream in VoiceMeeter
  if (!in.begin(cfg_in)) stop();
}

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

Since the format is in every packet, addNotifyAudioChange() lets the output adapt to it automatically.

More examples: streams-audiokit-vban sends the microphone of an AudioKit, player-sdmmc-vban plays MP3 files from an SD card to VBAN.

Things to consider

  • 16 bit PCM only: VBANStream sends 16 bit PCM and accepts only 16 bit PCM - the audio is uncompressed, so mind the bandwidth: 44.1 kHz stereo needs about 1.4 Mbit/s.
  • UDP: lost packets are not repeated, and the clocks of sender and receiver differ slightly - see UDP.
  • Throttling: a source that delivers at the audio rate (microphone, I2S) needs no throttle; a generator or file does (throttle_active).

Clone this wiki locally