Skip to content

Desktop Build

pschatzmann edited this page Oct 25, 2026 · 6 revisions

This project can be compiled and run on Linux and macOS using CMake. The build uses the arduino-audio-tools Arduino emulator to run Arduino sketches as native desktop executables.

Prerequisites

  • CMake 3.22+
  • A C++ compiler with C++11 support (GCC or Clang)
  • Git (dependencies are fetched automatically)

On Linux (Debian/Ubuntu):

sudo apt install cmake g++ git

On macOS:

brew install cmake

Build

mkdir build
cd build
cmake ..
make

If the arduino-audio-tools library is located next to this library (e.g. in the Arduino libraries folder), it is used, so that desktop and Arduino builds use the same version (disable with -DAOO_USE_LOCAL_AUDIO_TOOLS=OFF). A local Arduino Emulator can be used with -DFETCHCONTENT_SOURCE_DIR_ARDUINO_EMULATOR=<path>. All other dependencies are fetched automatically via CMake FetchContent (use -DFETCHCONTENT_UPDATES_DISCONNECTED=OFF to update a fetched copy):

  • arduino-audio-tools — audio processing library and Arduino emulator
  • arduino-libopus — Opus codec (for the sender and receiver examples)
  • codec-helix — MP3 and AAC decoder for the file input of the command line tool
  • miniaudio.h — to play the audio on the desktop with a MiniAudioStream (downloaded at configure time)

Build Targets

The build produces the following executables:

Target Location Description
aoo-sender examples/aoo-sender/ Sends audio over UDP with Opus encoding
aoo-receiver examples/aoo-receiver/ Receives audio and prints it as CSV
aoo-receiver-task examples/aoo-receiver-task/ Same as aoo-receiver, using AOOReceiverTask (message processing on its own task/thread)
protocol examples/tests/protocols/ Protocol message tests
log-messages examples/tests/log-messages/ Logging tests
loopback examples/tests/loopback/ Sender to receiver loopback test
unit-tests examples/tests/unit-tests/ Automated unit and sender/receiver integration tests
regression-tests examples/tests/regression-tests/ Automated tests for defects found in code reviews
stream-test examples/tests/stream-test/ Sends or receives a sine over UDP with settings from environment variables, reports statistics
interop examples/tests/interop/ Interoperability test with the official aoo library (see below)
aoo-tool tools/ The aoo command line tool (see below)

Build a single target:

make aoo-sender

Command Line Tool

The aoo tool (build/tools/aoo) sends and receives audio from the command line: e.g. to test a microcontroller, to play the audio of a microcontroller on the PC or to exchange audio with the official aoo library (Pure Data, SuperCollider, the official examples).

aoo send [options]      # send audio to an AOO receiver
aoo receive [options]   # receive audio from AOO senders

The input of the sender is a sine wave (--input sine:440), the microphone (--input mic), an audio file (--input music.mp3: MP3, AAC or WAV, the format is detected from the data and decoded with the DecoderHelix) or raw 16 bit PCM from stdin (--input -). Files are sent in their own format (converted to 16 bits): with Opus, sample rates which are not supported by Opus (8, 12, 16, 24 and 48 kHz) are resampled to the closest supported rate, e.g. 44.1 kHz to 48 kHz; the sine and the microphone use that rate directly. The receiver writes to the speaker (--output speaker), a WAV file, a CSV file or raw 16 bit PCM to stdout (--output -). Generators, files and stdin are sent in real time; the receiver statistics are printed at the end (every second with --verbose).

Option Command Description
-p, --port N both local UDP port (send: 9998, receive: 9999)
-i, --id N both source id (send) or sink id (receive) [1]
-r, --rate N, -c, --channels N both audio format [48000, 2]
-t, --time SECONDS both stop after the indicated time [Ctrl-C or end of the input]
-v, --verbose, --log LEVEL both statistics every second, log level (error, warning, info, debug)
--volume FACTOR both linear volume, e.g. 0.5 halves the amplitude, values > 1 amplify (the samples are clipped) [1.0]
-H, --host IP, -P, --remote-port N, -s, --sink N send the receiver [127.0.0.1, 9999, 1]
--input SOURCE send sine[:FREQUENCY], mic, an MP3, AAC or WAV file, or - for raw 16 bit PCM from stdin [sine:440]
-C, --codec NAME send pcm or opus [pcm]; with Opus unsupported sample rates are resampled
-b, --block N send pcm: frames per block [256], opus: frame size in ms (10, 20, 40, 60) [20]
-R, --redundancy N send send each block N times [1]
--packet-size N send max. size of a data packet, bigger blocks are split [960], see Packet Size and MTU
--output TARGET receive speaker, a WAV or CSV file, or - for raw 16 bit PCM to stdout [speaker]
-d, --buffer-depth N receive blocks to buffer [10]
--resend N, --no-adaptive, --task receive resend requests per lost block (0 = off) [1], no adaptive resampling, receive in a separate task

Examples:

# play the audio of an ESP32 which sends to this PC
./tools/aoo receive --output speaker
# send Opus to a microcontroller with the IP 192.168.1.33
./tools/aoo send --host 192.168.1.33 --codec opus --input music.mp3
# record 60 seconds and print the statistics every second
./tools/aoo receive --output out.wav --time 60 --verbose
# play an MP3 file on a microcontroller with half the volume
./tools/aoo send --host 192.168.1.33 --codec opus --volume 0.5 --input music.mp3
# play with another program
./tools/aoo receive --output - | aplay -f S16_LE -r 48000 -c 2

When sender and receiver run on the same PC they need different ports, e.g. aoo receive -p 19999 and aoo send -P 19999.

Automated Tests

The tests are registered with CTest. After building, run them from the build directory:

make protocol loopback unit-tests regression-tests
ctest --output-on-failure                # all tests
ctest -L unit                            # protocols, loopback and unit tests
ctest -L regression                      # regression tests only
AOO_TEST_FILTER=Multi ./examples/tests/regression-tests/regression-tests  # tests whose name contains "Multi"

unit-tests and regression-tests connect AOOSender and AOOReceiver through an in-memory, packet-preserving transport (AOOStreamPipe in examples/tests/test-support/AOOTestSupport.h), so no network or audio device is needed. Packet loss can be simulated with a drop filter. Each test executable returns a non-zero exit code when a test fails.

The same sketches can also be compiled with the Arduino IDE or arduino-cli. The results are printed to the serial console. examples/tests/receiver-stats analyzes a received sine on a microcontroller and prints statistics every 10 seconds.

Interoperability with the official aoo library

With -DAOO_BUILD_INTEROP_TESTS=ON the official aoo library is fetched from git.iem.at (without Opus) and the interop test checks both directions over UDP on localhost: an official source sending to an arduino-aoo receiver and an arduino-aoo sender sending to an official sink. The duration can be changed with AOO_INTEROP_SECONDS (default 3):

cmake -DAOO_BUILD_INTEROP_TESTS=ON ..
make
ctest -L interop --output-on-failure

Streaming tests

stream-test sends or receives a 440 Hz sine with the settings from environment variables (see the comment at the top of the sketch), e.g.:

AOO_MODE=receive AOO_PORT=9999 AOO_CODEC=opus AOO_CSV=out.csv ./examples/tests/stream-test/stream-test &
AOO_MODE=send AOO_CODEC=opus AOO_PORT=9998 AOO_REMOTE_PORT=9999 AOO_REDUNDANCY=2 ./examples/tests/stream-test/stream-test

Preprocessor Defines

Desktop builds automatically define:

  • ARDUINO — enables Arduino API compatibility
  • IS_DESKTOP — signals desktop environment (for platform-specific code paths)
  • DEFINE_MAIN — the Arduino emulator provides main()

Running

After building, run the examples from the build directory:

./examples/aoo-sender/aoo-sender
./examples/aoo-receiver/aoo-receiver

Clone this wiki locally