Breaking the 25ms Barrier with Audio Injector Stereo

I received a few Audio Injector Stereo boards this week and started testing I received a few Audio Injector Stereo boards this week from Amazon. Today, I plugged them into two Raspberry Pi model 4’s running the same Raspbian image (stock kernel, not real-time) that I used for my previous tests. A simple Audacity loopback cable test gave me a low 4ms measurement using a 2ms buffer (lower buffer sizes caused too many dropouts).

I used a stereo RCA cable to create a line-level loopback on one of Audio Injectors, and the built-in mic on the other to capture sound for a few more round-trip JackTrip tests. Here are the results:

Client DevicesRemote ServerLatencyBandwidth
Sabrent USB (48k, 128fpp)LAN (<1ms ping)42ms890Kbps
Audio Injector (48k, 128fpp)LAN (<1ms ping)37ms890Kbps
Sabrent USB (48k, 128fpp)EC2 (6-7ms ping)57ms890Kbps
Audio Injector (48k, 128fpp)EC2 (6-7ms ping)47ms890Kbps
Audio Injector (48k, 256fpp)EC2 (6-7ms ping)76ms890Kbps
Sabrent USB (48k, 256fpp)EC2 (6-7ms ping)79ms890Kbps
Audio Injector (96k, 128fpp)EC2 (6-7ms ping)27ms1.75Mbps
Audio Injector (96k, 256fpp)EC2 (6-7ms ping)37ms1.62Mbps
Audio Injector Stereo Test Results

Note that this test performs two round-trips over my network connection:

  • Pi #1: ADC on the first Pi to capture the audio
  • Pi #1: Send over network to server
  • Pi #2: Receive over network from server
  • Pi #2: DAC to output audio
  • Pi #2: ADC to capture audio
  • Pi #2: Send over network back to server
  • Pi #1: Receive over network back from server

The bold results above represent the first successful tests I’ve been able to perform below the 25ms threshold. For a full round trip, I would ideally include two ADC and two DAC conversions, but this seemed like a good enough place to start.

The Sabrent USB devices max out at 48k, but the Audio Injectors can handle 96k. Arguably, 96k is a bit overkill for our purposes, and likely not worth the 2x bandwidth cost, but it does enable significantly lower latencies. It may be a worthwhile tradeoff since 1.7Mbps is not a big deal for most Internet connections.

I was able to get an incredible 27ms round-trip measurement (roughly 14ms one-way!) using 96k with 128 frames per period. I was seeing 20-40 dropouts logged per minute on the server, but other than some occasional pops it still sounded great. 96k with 256 frames per second cut the dropouts roughly in half, at the cost of only 10ms (5ms one-way).

I also took this opportunity to measure bandwidth and CPU usage for the clients and servers. The bandwidth measurements above are one-way traffic; each client had roughly the same ingress and egress. The server’s bandwidth was simply a multiple of the number of clients (in this case 2).

Both client and server load average for all tests was between 0.2 to 0.3 (20-30% of 1 CPU core). Note that clients also had X and a few GUI apps (Terminal, etc.) running. The clients have tons of extra CPU capacity, and I wouldn’t expect load to change at all since all the mixing is performed on the server.

For the server, I was encouraged to see that JackTrip was doing a good job balancing the load out across several threads:

PR NI VIRT RES %CPU %MEM TIME+ COMMAND
20 0 743996 119708 6.0 6.0 0:21.33 UdpDataProtocol
20 0 743996 119708 6.0 6.0 0:13.36 UdpDataProtocol
-6 0 743996 119708 2.0 6.0 0:07.82 Thread (pooled)
-11 0 173048 24464 1.7 1.2 0:07.19 jackd
20 0 743996 119708 1.3 6.0 0:03.13 UdpDataProtocol
-6 0 743996 119708 1.3 6.0 0:03.67 Thread (pooled)
20 0 743996 119708 1.0 6.0 0:03.93 UdpDataProtocol

My hope is that this will allow JackTrip to scale linearly across CPU cores, as the number of clients grow. If so, one should be able to handle 72 concurrent clients, or a full choral group practice or performance, using a 24-core server with 63-126 Mbps ingress & egress.

Now for some bad news.. First, the JackTrip build I’m using (admittedly a pre-release beta) isn’t very stable. Actually, it needs more investigation to pinpoint the root cause, but either it or Jack crashed and dumped cores several times during my testing. It’s likely going to take some work to harden all this enough to handle a full practice or performance.

Second, the Audio Injector boards do not seem to have functional inputs for external microphones. The RCA and 3.5mm jacks are intended for line-level input. The volume input knob controls some amplification but it doesn’t have nearly enough oomph to bring a mic up to a usable level. The boards do have a mic boost feature, but it seems to only be usable for the embedded mic. Enabling it has no effect on the levels for any of the input jacks.

I dug around the Audio Injector support forum, hoping I was just missing something. All I found were unanswered posts from people who failed to get external mics to work. But I really like everything else about these boards, which are a steal at $22. The next least expensive HAT I can find in stock these days is the HifiBerry DAC+ ADC at $50, and a good external mic and cable costs another $30+. Audio Injector’s embedded microphone does sound pretty good, so I’m now thinking it may be best to just roll with it.

Leave a Reply