• Welcome to ASR. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

ScreamRouter

netham45

New Member
Joined
Mar 25, 2025
Messages
3
Likes
9
Hey! I have been working on this project for about a year now. It's a many sources to many sinks audio routing solution.

Here's the site I made for it

For stream receivers there are currently:
* I also added some sleep and power management to this to make it more suitable for battery operation. I use an ESP32S3 + Apple USB to 3.5mm DAC with a 2000mAh battery for my headphones and it's small enough I can stick it on the headband with a magnet.

For stream senders there are currently:



On a technical level, the way the audio router works is:

  1. The configuration manager solves groupings/routing and builds a map of real sources per real sink
  2. For each source->sink route, a conversion process is started to convert it to the proper audio format for the output (channel mixing, equalizer, volume, sample rate, bit depth)
  3. For each sink, a mixer is created. This mixer takes all of the source inputs and mixes them together, outputs PCM to Scream and outputs MP3 frames to the Python backend to be served as MP3s over FastAPI.
More technical Info

The goal of this was to have a dynamic multi-threaded approach that could use multiple cores and doesn't bog down under many sources/sinks. I haven't tested anything this large but I'd really like to see it tried for like a whole building audio system, I think it'd work.

You can see all of the repos on my Github



I have tried to make the UI as convenient to use as possible. The UI is a React-based UI running with a FastAPI/Python configuration manager and a C backend for audio processing.

There is an option to add a VNC server for each source that can be remote controlled through noVNC from the web interface.

There's a Home Assistant component for managing it, too

There is also a Windows Desktop App that adds an icon to the notification area next to the volume control and pops up a slide-out mini control for the system, and can open the full view. This app is C# so it may work on Linux with Mono too but this is as of now untested.

It's got Milkdrop visualizations using Butterchurn



Please let me know if anyone tries it or has any issues, I'd like to hear about it.
 
From a quick skim I can't see anything about keeping clocks in sync. Did I miss it?
 
From a quick skim I can't see anything about keeping clocks in sync. Did I miss it?
  • time_sync: Enable/disable time synchronization NOTE: Not yet implemented (boolean)
  • time_sync_delay: Additional buffer time in milliseconds NOTE: Not yet implemented
Overall very interesting. I have a read for tonight.
 
  • time_sync: Enable/disable time synchronization NOTE: Not yet implemented (boolean)
  • time_sync_delay: Additional buffer time in milliseconds NOTE: Not yet implemented
Overall very interesting. I have a read for tonight.
Hey, that's actually just a placeholder setting right now, I don't have syncing itself implemented. That should be the only placeholder setting though, everything else is implemented. I thought I had actually noted that wasn't implemented yet wherever it was mentioned.

What I'm planning on doing for synchronization is set up an NTP server clients can regularly sync to to get accurate clocks and put a timestamp on each packet of when it should be played, adjusted based off the delay setting there. The client will buffer until it's internal clock tells it it's time to send a packet then play it.

As it is clients only have a couple tens of ms of delay compared to each other but that's more than enough to be audible.
 
If I can guess @somebodyelse was aiming at the clock syncing among input and output device clocks. Syncing to NTP/PTP is typically syncing streams rendered on multiple devices - syncing to central network time. But every local audio device has its own clock at which it produces/consumes samples which needs to be aligned somehow.
 
Yes - for example if there was a Pi in each speaker of a stereo or multichannel setup would they stay in sync, or slowly drift apart because there's nothing to keep their clocks in step? I'm especially interested in something that would work for wireless connections where PTP is apparently even worse than NTP. The only things I've found so far use proprietary libs to use internals of specific manufacturers' BT chips.
 
My plan for keeping device RTCs in line was to just do an NTP query every minute or so from every receiver. If you mean the clocks going to the DACs themselves I don't see how that's possible to sync using a mix of spdif, usb, and whatever else.

I hadn't really considered per-speaker receiver for multi-speaker setups, to be honest. I can put some thought into that though. I was thinking more keeping separate rooms/areas in sync to avoid the stadium effect and driving a full stereo from each receiver. The first thing popping into mind is to use IR transcievers to sync a clock pulse up between multiple RPis in a room but that obviously has limitations.
 
Yes - for example if there was a Pi in each speaker of a stereo or multichannel setup would they stay in sync, or slowly drift apart because there's nothing to keep their clocks in step? I'm especially interested in something that would work for wireless connections where PTP is apparently even worse than NTP. The only things I've found so far use proprietary libs to use internals of specific manufacturers' BT chips.
If the thing, in the end, comes down to a manufacturer-specific hardware internal feature, then we are still miles away from perfection...
 
If you mean the clocks going to the DACs themselves I don't see how that's possible to sync using a mix of spdif, usb, and whatever else.
IIUC that's a crucial part of a universal audio router capable of routing audio between various inputs and outputs. E.g. passing BT audio (clock master 1) to USB audio output (clock master 2), while mixing with SPDIF input (clock master 3). It requires low-latency adaptive resampling (ASRC), controlled by carefully tracking rate differences.

E.g. Pipewire does it, it even supports tweaking device clocks where available instead of costly resampling (alsa loopback and USB gadget supported). The latest version added PTP syncing to its RTP source, allowing to synchronize multiple network renderers (while being able to adaptively resample for their local output clocks). Pipewire developers focus on efficiency too, important for embedded use cases. To be honest, IMO that's the path for the future in linux audio routers.

Nevertheless hats off to your very interesting project, huge great work!
 
If the thing, in the end, comes down to a manufacturer-specific hardware internal feature, then we are still miles away from perfection...
Back in 2017 the WiFi Alliance announced Certified TimeSync which in theory means they can use FTM hardware timestamps for PTP. In practice I haven't seen anything that does it. I've seen reports that linux drivers and tools expose the range-finding part but not the underlying time details. With luck that will change, or already has and I've missed it. It's not clear from the Avnu paper below whether they were using stock linuxptp (ptp4l) and iwlwifi, or a patched version.
https://avnu.org/wp-content/uploads...ions-with-Wi-FI-white-paper-v1.0-approved.pdf

Bluetooth LE Audio includes sync for separate speakers, but seems to keep its time sync internal. Most low power radio protocols like LoRa use some form of time sync so they can power off the radio then wake at the right time for the next contact, but the time generally isn't exposed by the APIs.
 
JFTR, DAC timing sync was discussed here earlier today.
Side note, I think all you need to do in order to slightly vary playback speed is to vary nominal input sample rate at the ASRC until long-term buffer health is happy. The result is arguably best saved as the next default for the device in question in order to avoid having to do it all over again.
 
Last edited:
That was timing sync for different clock domains on the same computer, but I suppose at the receiving end that's effectively what you're looking at. PipeWire does something similar to MacOS. From https://docs.pipewire.org/page_man_pipewire-props_7.html#props__scheduling_properties
clock.name # string
The name of the clock. This name is auto generated from the card index and stream direction. Devices with the same clock name will not use a resampler to align the clocks. This can be used to link devices together with a shared word clock.

In Pro Audio mode, nodes from the same device are assumed to have the same clock and no resampling will happen when linked together. So, linking a capture port to a playback port will not use any adaptive resampling in Pro Audio mode.

In Non Pro Audio profile, no such assumption is made and adaptive resampling is done in all cases by default. This can also be disabled by setting the same clock.name on the nodes.
More details from a 2023 presentation:
https://embedded-recipes.org/2023/w...o-systems-Philip-Dylan-Gleonec-compressed.pdf
Some sink/source types can or must use PTP synchronised clocks.
 
@somebodyelse : Thanks for linking that presentation. It was where I got the info from that PW was ready for embedded use :)

Support for HW DSP in modern SoCs is a very interesting (future) feature, offloading ASRC to HW would greatly relieve the CPU, provided the DSP computational quality is acceptable. Of course doing DSP on the CPU gives much more control.

Overall I believe PW is on the right track to enable linux in complex embedded audio installations.
 
Back
Top Bottom