Looking for a good not expensive streamer

RPi3B with its flaky USB controller and USB-ethernet bridge does not seem like a good choice in 2021 for a reliable network streamer feeding a USB2 DAC with bInterval=1, i.e. expecting data in every 125us microframe. Also when Jan may likely want to try out the high-rez samplerates (384/768kHz) his rather expensive DAC supports.
 
All my devices that are non RPi don't care much about what DAC is connected either. Maybe that is what the customer pays for?!

Do you really believe that your proprietary streamer vendors have written custom USB-audio drivers? Your devices support what the snd-usb-audio module supported at the version of the linux kernel used in your device firmware. Most use ancient version 4.4 kernel because that's the most common production kernel for non-rpi arm devices being developed for android.
 
The streamer image https://ifi-audio.com/wp-content/uploads/2021/05/ZEN-Stream_-Pcb_011.jpg clearly reads CORE 3328 JD4, i.e. Core-3328-JD4 Quad-core 64-bit Core Board . The official Rockchip kernel for RK3328 is 4.4 Rockchip Kernel - Rockchip open source Document . The t-firefly offers linux SDK - I did not download the multiple 3GB files to build the image. But the download page og that t-firefly module Firefly | Make technology more simple , Make life more intellingent. also offers Ubuntu 18.08 for rk3328 arm64 which is kernel 4.4, as expected Running Docker on roc-rk3328-cc — Your Destination for Single Board Computers .
 
Jan: the kernel contains the drivers. Actually quite a lot of presumably UAC2-compliant devices need a special quirk in the linux usb-audio driver to work properly. In windows - they need a vendor-specific driver and are not supported by the stock windows UAC2 driver out of the box (or if they are, their support has been added to the MS UAC2 driver in some later windows updates, just like to the linux driver in later kernel versions).

I am not saying your RME soundcard is not supported by the 4.4 kernel but it's a question which needs to be raised, IMO much more important than some discussion about high or low jitter or "design for audio" when you have a proper USB async device and all you need is proper driver and reliable and stable hardware from the audio-quality POW (I am not talking about software usability/GUI/user experience).
 
Sure, but what happens if you have a bad or old kernel? Do you get jitter, dropouts, uneven freq response? I really would like to understand how it all hangs together.

Forget about jitter, it's simply not a thing with modern USB audio devices (the clock is independent from the streamer output; the clock is created inside your ADI DAC, see my earlier explanation).

It's more a question of getting the digital data from the source (your hard drive, a local server, or the internet) through the streamer and to the USB input of your DAC. Either the data gets through, or it does not. The data will not be modified (resulting in uneven frequency response or such).

A very old kernel may not work with a very new USB audio device, but this is rather uncommon. A more common thing would be that an older kernel may cause glitches/dropouts with some new/niche USB devices. For example, older kernels (pre 5.10) would cause a minor glitch if I'd run a very long test tone on my RTX 6001 audio analyzer. Kernel 5.10 and later versions fixed this.

These things apply to any streamer running on a Linux system. I'd guess that's the majority of all streamers out there.
 
The UAC2 driver receives data from the application stack in batches (called period in linux alsa and windows wasapi). IFI Zen Streamer uses Volumio which uses MPD for playback. The default period time of mpd is 5.8ms for 48kHz stream. That is MPD will copy 5.8ms of audio data to the driver every 5.8ms.

When the UAC2 driver receives the data, it splits the data into 125us fragments, adds control bits to create a proper isochronous packet, and copies the packet to appropriate location of RAM for the USB-core driver to add proper USB2 microframe bits (every microframe can contain packets for more devices connected to the bus through a USB hub, e.g. flash drive or USB keyboard).

This part of memory is already used by the USB controller which reads it via DMA and sends to the USB devices. Reading (and writing of incoming data) is timed the USB controller internal clock (standalone PCIe USB controllers have typically 12MHz crystal, USB controllers integrated in ARM SoCs are timed by the SoC clock providers, all hardware-based, no software timing).

So the samples get sent to the soundcard every 125us (because the ADI device specifies bInterval=1 in its USB configuration sent to the host). Your USB DAC is isochronous asynchronous. It has a short FIFO which the incoming samples are written to (clocked by the 125us microframes, i.e. by the USB controller hardware clock). The samples from the FIFO are clocked out by precise clock of your device which also generates master clock to your AK4490 DAC chip.

Because no clocks in the real world run at exactly the same pace, the FIFO would eventually over/underflow (just like all the RPi add-on reclocking FIFOs do BTW). To avoid that an asynchronous mode device monitors the level of the FIFO fill and sends a message back to the USB host telling what number of frames should ideally be in every USB packet (basically a very precise floating-point value). The ADI soundcard sends an explicit feedback through a dedicated USB endpoint, one feedback message every 1 ms. The USB-core driver on the host passes the message to the USB-audio driver which finely adjusts the number of frames so that the requested exact number of samples is being passed to the device, on average over longer time.

On the host the whole playback chain is timed by pace of samples consumption by the driver. When the driver consumes the period-time of data, it tells the application to send another period-time of data. In the mean time the writing thread of the application is sleeping /being blocked by the kernel call.

The driver uses at least two periods of data (one being consumed by the USB controller/PCI soundcard, the other being filled by the application). E.g. ASIO uses exactly two periods. But linux alsa (and e.g. windows WASAPI) can pre-fill many more periods, to make the transfer more robust and reliable (at the expense of the overall playback latency, of course). The overall time used by the driver is called buffer time and default value if MPD is 500ms.That means there are 500ms of data sent to the driver in advance before they are needed by the device, and in the 6ms batches continuously adding new samples.

Now where is the room for some "software jitter"?. The engineers in the 80s (?) when the audio chain was designed were not stupid to time the DA conversion by software.

Back to the question about wrong driver - the device feedback can have a wrong format, being ignored -> causing the device FIFO under/overflow -> glitch. Enumeration problems (requiring some timeouts, vendor-specific pre-configuration), non-standard numbering of endpoints (again enumeration/features problem). Correct clock-setup problem in the device (wrong playback speed). Always either no sound, or wrong speed, or glitchy, or occasional glitches. No problem with increased jitter But these problems can be fixed only by modifying the kernel snd-usb-audio module, e.g. by using a newer kernel.
 
Last edited:
Administrator
Joined 2004
Paid Member
I know what you mean -- once I went through that I realised it's actually a lot easier than I thought. I'd say it's less effort than reading this thread from the start, ordering an iFi, fight with the iFi, and cope with the frustration.

I'll second that, bootable micro SD card with the operating software installed on it, RPI4, box and PSU. About 10 minutes of assembly, plugging things in, and waiting for the RPI4 to finish configuring itself. (Roon Core with Ropieee running on the end points.)
 
  • Like
Reactions: 1 user
As of the Matthias'es RTX6001 analyzer - it is a duplex device which always captures and plays back at the same time, ADC/DAC controlled by single clock. Its XMOS controller is programmed to use another feedback method allowed by the UAC2 standard - implicit feedback. Its USB configuration marks its incoming endpoint as a source of implicit feedback information. In this case the host USB-audio driver does not receive the required average sample size from some number being sent through a special feedback channel, but simply makes the size of outgoing packets equal to the sizes of the incoming packets. If one incoming packet is one audio frame larger, the driver fills one outgoing packet to be one audio frame larger too. That way the incoming stream precisely controls the pace of the outgoing stream.

Every 125us microframe the XMOS sends all data it has received into its TX FIFO from the ADC (the incoming rate clocked by the common ADC/DAC clock). That way the ADC clock controls the pace at which the USB host sends samples for the DAC, being clocked by the same clock.

The problem in the linux usb-audio driver was that it did not support implicit feedback for any devices, just for whitelisted models. Therefore the outgoing stream was not paced by the incoming stream and the RX FIFO in the XMOS overflew/underflew, creating a glitch which ruined longer REW averaging measurements. The piece I was using glitched every 10 seconds, the piece of Matthias glitched I think every minute or so. Simply the clocks were different. A trivial addition of the RTX6001 USB ids to that list fixed the problem, again requiring installation of the new module (through new kernel version). The current linux version already supports the implicit feedback for any device, without the need for any whitelist. BTW the windows UAC2 driver does not support the implicit feedback at all (but states the fact in its documentation, at least that).
 
Last edited:
Disabled Account
Joined 2002
SPDIF is not so bad I see. No kernel trouble either.

FWIW My 50 Euro Cubox-i with Volumio 2.875 has no issue at all via USB. Never bothered to check kernels. Isn’t this all a little exxagerated!?

A RPi 3B is flaky so Jan and I must buy RPi 4 to avoid all the trouble? I am started to get worried by all the information. I just plugged out all my devices.
 
Last edited:
AX tech editor
Joined 2002
Paid Member
The UAC2 driver [very clear detailed explanation ] a newer kernel.

Thanks Pavel, I understand this flow. One remaining question. I get the handshake between the streamer and the USB client to avoid buffer over/underrun. But *someone* needs to set the overall pace; we don't want the music to end before of after the composer planned it. How is the whole thing synchronized to the real time of the song?

Jan
 
Jan: The only element actually timing the chain (as it should be) is the precise crystal clock of your ADI DAC. You are right every soundcard will finish the musical piece at a different moment but considering the crystal precision the milliseconds are most likely not a problem :) In studios some master clock is distributed to individual devices, making the whole large complex chain run synchronously. Or adaptive asynchronous resampling to merge two clock domains must be used but that is a different story.
 
Last edited:
Well, your soundcard can use clock from an incoming SPDIF/ADAT stream, so technically you can use some ADAT source with GPS (atomic-originated) clock, e.g. this one accepts GPS clock Brainstorm DCD-8 Master Clock Distripalyzer - Discontinued :)

The USB UAC2 is very complex and some details are not standardized properly (leading to avoidable non-compatibilities) but IMO the basic flow of the async isochronous mode is designed logically and reasonably.
 
Last edited:
Jan: The only element actually timing the chain (as it should be) is the precise crystal clock of your ADI DAC. You are right every soundcard will finish the musical piece at a different moment but considering the crystal precision the milliseconds are most likely not a problem :) In studios some master clock is distributed to individual devices, making the whole large complex chain run synchronously. Or adaptive asynchronous resampling to merge two clock domains must be used but that is a different story.

Thanks for the info.

My question specifically to you is...

UAC2 does not include a sample clock, i.e. an "audio data" clock. So, what times the chain is the USB section (XMOS) clock. Data is stored in a buffer, and then the second, low noise D/A's section clock actually reclocks the stored data, based on the rate information specified in the UAC2 preamble. In other words, all USB DAC's already re-clock the data. So, the precise cristal clock inside the ADI DAC that you are referring, will reclock the sored/buffered data - NOT the USB data transfer rate clock.

Now, If I am correct - what would be the benefit of that same master clock distributed to all devices in a studio? How is this ensuring that the actual data "draw" from a buffer (in each DAC device in a studio) will start, and then stop at the same time???
 
UAC2 does not include a sample clock, i.e. an "audio data" clock. So, what times the chain is the USB section (XMOS) clock.

USB is a serial transfer using packets of data (called frames/microframes in USB, packets in networking). The frame start time is determined by the USB host controller. For outgoing frames every 125us (USB highspeed) the controller sends out the Start Of Frame (SOF) packet, followed by the data packets for the individual devices on the bus (simplified). The device responds with a confirmation packet. For incoming stream the controller sends the SOF, followed by data-in request, and the device responds with a packet filled with captured data. The SOF packets are always sent (= timed) by the host controller.

The UAC2 device stores the data received from the host (timed by the host) into its FIFO.

Now the UAC2 device can use three modes:

In adaptive mode the device generates output bitclock for the DAC via PLL controlled by the FIFO fill level. The author of the PLL loop in PCM2702 wrote a great story about the struggle https://www.thewelltemperedcomputer.com/Lib/Hitoshi Kondoh story.pdf. The PLLed clock is by principle synchronous to the incoming data rate. PLLed clock means potentially worse jitter than direct clock - here are are talking about the final DAC clock where the jitter does matter (unless digital adaptive asynchronous resampling is used like optionally in ES90x8 chips).

In async explicit-feedback mode the FIFO is clocked out by the DAC clock independent of the USB host clock, the device monitors the FIFO fill level, and keeps telling the host side what the average number of samples per frame to send.

In async implicit-feedback mode the FIFO is clocked out by the DAC clock independent of the USB host clock, and the host keeps adjusting the number of samples in the frame based on pace of the incoming samples (duplex ADC+DAC with single clock).


In other words, all USB DAC's already re-clock the data. So, the precise cristal clock inside the ADI DAC that you are referring, will reclock the sored/buffered data - NOT the USB data transfer rate clock.

The word "reclocking" is a bit dangerous, IMO, especially in the "audiophilespeak". Digital devices (and softwares too) are full of FIFOs. For a fixed length FIFO to not over/underflow, the IN and OUT data rates must be synchronized somehow. In adaptive mode the OUT clock is generated from the IN clock. In async mode the OUT clock is fixed (DAC clock), IN clock is fixed (USB host controller clock), but the amount of samples in IN packet differs, controlled by the OUT clock, making the IN data rate synchronized to the OUT rate.

The XMOS may have another clock for its internal operation but that's irrelevant to the data flow. Also the DAC clocks reading the XMOS FIFO can be generated by the XMOS itself, where a part of the XMOS is pre-programmed to work as the DAC clock generator, instead of using an external clock generator. But that's just a technical solution of what device generates the DAC/ADC clock.

Now, If I am correct - what would be the benefit of that same master clock distributed to all devices in a studio? How is this ensuring that the actual data "draw" from a buffer (in each DAC device in a studio) will start, and then stop at the same time???

The distributed master clock goes to PLL in every device in the studio to create the device's final DAC/ADC clock. As a result the pace at which samples are generated/consumed is synchronized for all the devices and the realtime streams are synchronous. They may (and typically do) have different latencies (time shift) but the latency diff is constant, does not increase/decrease as would be the case for independent clocks. Sometimes it's important, sometimes not, depending on requirements. I have read that good recording studios have their master clock synced to GPS to make sure their recordings have correct length, i.e. what Jan talked about.
 
Last edited: