Repository navigation
Desktop Build
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.
- 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++ gitOn macOS:
brew install cmakemkdir build
cd build
cmake ..
makeIf 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)
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-senderThe 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 sendersThe 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 2When sender and receiver run on the same PC they need different ports, e.g. aoo receive -p 19999 and aoo send -P 19999.
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.
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-failurestream-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-testDesktop builds automatically define:
-
ARDUINO— enables Arduino API compatibility -
IS_DESKTOP— signals desktop environment (for platform-specific code paths) -
DEFINE_MAIN— the Arduino emulator providesmain()
After building, run the examples from the build directory:
./examples/aoo-sender/aoo-sender
./examples/aoo-receiver/aoo-receiver