AES67 Audio Teensy 4.1

Droptopz

Member
The 4.1 is a awesome development board. I have put together a AES67 Audio-over-IP implemented on the Teensy 4.1.
Thank you to everyone for the Teensy creation and community.
Awesome library's that made this possible.
"https://github.com/ssilverman/QNEthernet/tree/ieee1588-2"
"https://github.com/IMS-AS-LUH/t41-ptp"
"https://github.com/alex6679/teensy-4-usbAudio"
"https://github.com/CptLemming/teensy-aes67 - this is what got me started on my implementation"

 
This is great! Thanks for your work on this. I can't find where the audio PLL syncs to PTP in the code - could you point me to it?

Compile Issue: I had compile errors about a missing file in QNEthernet (/src/lwip/priv/tcp_priv.h), but replacing it with the one from the standard library fixed it.

My Setup: I've updated the code to work with 24-bit audio (3 bytes per sample). Currently I'm streaming from a PC using a Python script with FFmpeg - no hardware PTP master. I'm hearing occasional crackles and pops due to jitter. A couple of thoughts/questions, I'm pretty new to AES67.

Jitter Buffer / Playout Delay: What are your thoughts on implementing a jitter buffer with a user-definable playout delay? For example, the user could set 5ms on all devices, and each receiver would add this offset to the RTP packet timestamp before playout.

Fallback for Non-PTP Sources: How about a fallback mode for when there's no PTP clock present? (Not AES67 compliant, I know.) The idea would be to maintain a target buffer level - if it gets too full, drop one sample; if too empty, repeat one sample. At 48kHz, slipping one sample per second would be inaudible.
 
great to see it being used and adapted. The PLL sync code it in the main sketch file at the end starting a 256ish. It does use the I2S packet sample count to align the PTP and the audio PLL. You may need to modify it for your application since your using 24-bit audio or you might not be using the I2S at all.

Shawn recently updated the IEEE1588-2 branch on his git and it works if you make a few changes. Mainly the setPacketDiffServ() is called different and EthernetIEEE1588.offsetTimer is not a function in that branch but it is really just a combination of the read and write timer functions.

For my application I wanted minimal delay but a jitter/playout delay sounds like a great addition. I know the Magewell AES67 pro convert device I used to test with had an adjustable Rx buffer level from 0-15ms.

The fallback sound good also it might help smooth out some of the timing differences in non ptp sources.

Since your using 24-bit audio are you using the teensy audio library?
 
I see it now, not sure how I missed that! How does this work with AudioPlayQueue, as to the best of my knowledge, this is a buffer that there is then no precise control of when it plays out of here? I have also looked at creating audio library objects AES67In and AES67Out that can be connected directly to mixers/I2S outputs etc to completely avoid having to go through the play queue. I have put a jitter buffer in, and also integrated SAP/SDP stream discovery and connection.

I really need to get my hands on an AES67/Dante interface to do more testing and help further the implementation, the Magewell unit looks like a good option for AES67 only. As I am currently getting limited tracking down problems by not knowing if the fault is with my source rather than the receiving side.

I am running USB audio at 24bit with the modified multi-channel library, however after reading more into how the library functions I now realise there is no benefit to this as all the internal objects will downsample it to 16bit anyway.

I'll let you know once I get my hands on an interface and make any more progress!
 
I don't really do anything different with the PlayQueue. In slave mode only, I use the number of I2S samples collected (I2SSampleCount) and compare it with the time elapsed according to the PTP clock * SAMPLERATE, and uses a PI controller to correct the audio PLL frequency by adjusting the CCM_ANALOG_PLL_AUDIO_NUM register.

Yea I thought about doing the audio library objects also, kind of like the palmerr Ethernet Audio https://github.com/palmerr23/EtherAudio https://forum.pjrc.com/index.php?threads/ethernet-audio-library.75876/. I just haven't had time or the drive to do so.

I really wanted to stay with in the functionality of the audio library that is why I stayed with the 16bit, and most AES67 devices are configurable for L16 and L24. There is a interesting audio library fork that uses 32 bit floats. https://github.com/chipaudette/OpenAudio_ArduinoLibrary

This is a decent device that I have done some testing with a while back. It will do Dante and AES67.

This company has some interesting AES67 devices also.

Lawo has some really nice software with AES67 slave capabilities. They have a free trail that has no limit but does add white noise to the audio after 15 minutes. I have tested with the R3lay Virtual Patch bay a good bit.

This is great for just checking/monitoring streams.
 
Back
Top