AES67 on Linux

The AES67 linux Daemon is a Linux implementation of the AES67 interoperability standard used to distribute and synchronize real time audio over Ethernet. It contains the Ravenna AES-67 ALSA driver kernel module as a submodule.

Setup

Let's consider the following setup:

Our goal is threefold:

  • Achieve PTP-based sychronization between devices
  • Send audio stream from (A) to (B)
  • Send audio stream from (B) to (A)

For general information, consider the Ravenna practical guide.

Configuration

AES67 linux daemon

We have packaged and built this linux daemon which can be installed via sudo apt install elak-spl-aes67 from our debian repo. It is configured via the /etc/elak-spl/aes67-daemon.conf file in json format and started with sudo service elak-spl-aes67 start.

The most relevant configuration settings are the following:

{
  "interface_name": "eth0",
  "custom_node_id": "ELAK-SPL AES67 daemon",
  "http_port": 8080,
  "playout_delay": 1024,
  "sample_rate": 48000,
  "tic_frame_size_at_1fs": 48,
  ...
}

The parameter http_port defines the port with which the interface can be reached, e.g., linux AES67 settings

Various settings can be adjusted there and are written back to the configuration file.

For AES67 compatability, tic_frame_size_at_1fs needs to be 48, sample_rate needs to be 48000, and ptp_dscp should be 46 (high priority).

The playout_delay parameter a global reception buffer size (therefore also latency) in sample frames.

MacOS Merging RAVENNA/AES67 VAD

The basic settings of the Merging AES67 driver are reachable through the system settings Merging RAVENNA/AES67 panel.

We operate in RAV/AES67 mode, Latency set to 48 and Sample Rate to 48000.

Merging AES67 settings

The IP can be seen from the chosen network interface. In our case, the browser interface is reachable via http://192.168.0.13:9090:

Merging AES67 settings

Like with the linux driver, a global Safety Playout Delay (@1FS) can be set.

PTP

AES67 needs UDP-based PTP with specific parameters. We run a PTP master clock on the linux machine with PTP packets broadcasted both to interfaces eth0 (providing hardware timestamping) and lo (loopback):

debix@imx8mpevk:~/$ sudo ptp4l -m -A -4 -S -i eth0 -i lo --dscp_event=46 --dscp_general=34 --domainNumber=0 --logAnnounceInterval=1 --logSyncInterval=-3 --logMinDelayReqInterval=0 --logMinPdelayReqInterval=0 --announceReceiptTimeout=3 --priority1=128 --priority2=128
ptp4l[424590.688]: ioctl SIOCETHTOOL failed: Operation not supported
ptp4l[424590.690]: port 1 (eth0): INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[424590.691]: port 2 (lo): INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[424590.691]: port 0 (/var/run/ptp4l): INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[424590.692]: port 0 (/var/run/ptp4lro): INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[424590.692]: Switched to /dev/ptp0 as PTP clock
ptp4l[424597.234]: port 2 (lo): LISTENING to MASTER on ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
ptp4l[424597.234]: selected local clock 100723.fffe.6de8bc as best master
ptp4l[424597.234]: port 2 (lo): assuming the grand master role
ptp4l[424598.273]: port 1 (eth0): LISTENING to MASTER on ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
ptp4l[424598.273]: port 1 (eth0): assuming the grand master role
ptp4l[424598.273]: port 2 (lo): assuming the grand master role

The --dscp_event=46 parameter guarantees high-priority transport of the PTP packets (in case of capable network infrastructure), --logSyncInterval=-3 results in a higher frequency of sync messages and therefore faster locking.

The linux AES daemon locks to PTP: linux AES67 PTP

Audio streaming from Linux to Mac

On the source machine, we define a stream source (stereo, in this case) in the web interface:

linux AES67 source

Connections are always made at the receiver. Thus, on the destination machine's web interface, we define a respective stream sink. We can use the dropdown list for the Source which is broadcasted on the network:

Merging AES67 sink

Testing using noise

A simple pink noise stereo test signal generated on the source machine with speaker-test -c 2 -D hw:RAVENNA -F S32_LE can be captured on the destination machine from the Merging RA Coreaudio interface.

Audio streaming from Mac to Linux

On the source machine, we define a stream source (stereo, in this case) in the web interface:

Merging AES67 source

On the destination machine's web interface, we define a respective stream sink. By checking the Use SDP box, we can select from broadcasted SDP definitions. In our case, the mDNS options doesn't work, but the SAP option does.

Linux AES67 sink

Playing received sound on other ALSA device

Sound played on the source machine over the Merging RA Coreaudio interface can be redirected to another ALSA audio interface es8316audio:

sudo nice -n -30 alsaloop -c 2 -r 48000 -t 2000 -f S16_LE -C hw:RAVENNA -P hw:es8316audio

Mixer settings for es8316audio are as follows:

amixer -c es8316audio cset name='DAC Playback Volume' 160  # fine grained volume
amixer -c es8316audio cset name='HP Playback Volume' 3     # 12dB steps
amixer -c es8316audio cset name='HPMixer Gain' 10          # coarse amplification
amixer -c es8316audio cset name='Left Hp mixer Left DAC Switch' on
amixer -c es8316audio cset name='Left Hp mixer Right DAC Switch' on

Audio processing using jack audio

Alternatively, received audio can be processed or redirected on the destination machine using jack.

We start the jack server on the playback device es8316audio which obviously only works in 16-bit mode (therefore option -S).

debix@imx8mpevk:~$ jackd -R -d alsa -P -o 2 -p 32 -n 3 -d hw:es8316audio -S 
jackdmp 1.9.20
Copyright 2001-2005 Paul Davis and others.
Copyright 2004-2016 Grame.
Copyright 2016-2021 Filipe Coelho.
jackdmp comes with ABSOLUTELY NO WARRANTY
This is free software, and you are welcome to redistribute it
under certain conditions; see the file COPYING for details
JACK server starting in realtime mode with priority 10
self-connect-mode is "Don't restrict self connect requests"
audio_reservation_init
Acquire audio card Audio0
creating alsa driver ... hw:es8316audio|-|32|3|48000|0|2|nomon|swmeter|-|16bit
configuring for 48000Hz, period = 32 frames (0.7 ms), buffer = 3 periods
ALSA: final selected sample format for playback: 16bit little-endian
ALSA: use 3 periods for playback

Connect the AES67 device with

alsa_in -d hw:RAVENNA -c 2 -p 48 -n 16 -r 48000

and connect it to the jack graph (and therefore the ALSA output device) with

jack_connect alsa_in:capture_1 system:playback_1
jack_connect alsa_in:capture_2 system:playback_2

TODO: Achieving more robustness and lower latencies

Software: VLAN and QoS

Hardware: managed switches

pipewire AES67

https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/AES67

node-based AES67

https://github.com/philhartung/aes67-sender