Trouble with latency (compensation) and pipewire

Hello dear community,

I recently have got a new audio interface with a microphone and want to start to record some tracks. I have tried to do so in Audacity first but when I saw Ardour in a video, I thought this could be a much better solution. Until… Well I have tried to set up Ardour for days now. I tried JACK, ALSA, pipewire. Independent of this choice, it still segfaults sometimes, doesn’t play sound, etc. Lots and lots of trouble. Most of it I could solve by now. But not the latency compensation. It seems to do whatever it wants. Later more about that.

My setup: I am running an up-to-date Arch linux (6.1.4-arch1-1) with an AMD Ryzen 7 1700 CPU, having an onboard sound card (Mainboard Asus Prime X370-PRO) and a Focusrite Scarlett 4i4 audio interface. I currently use the 4i4 for recording, my mic is connected to it, and the on-board sound card via optical wires to my amplifier for output to some loudspeakers. I read, that it might be a bad idea, to use two different sound cards and on-board sound cards in general, but the 4i4 doesn’t have optical output. My headphones will arrive soon, there is currently a delay, so I am stuck with the speakers for now. I am fine with it in general - and so is Audacity (with pipewire), after manually setting up latency compensation. So I can get a pretty fixed latency that can be corrected for in other tools.

Also, I installed the realtime package, added my user account to the “audio” and “realtime” group. And I set the CPU governor to performance, disabled multithreading, did not run any other software during my tests. Not using the realtime kernel.

So, now to my experimentation with ardour (Ardour 7.2.0) and the latency problems: I tried ALSA directly, JACK and pipewire. I recorded the metronome clicks and compared the start of the peaks of the recordings to the bars. With JACK2 only, I couldn’t really get rid of xruns, even with big buffer sizes (1024, 2048). I didn’t bother too much, because I wanted to try pipewire anyways. The first few tries were, if I remember correctly, spot-on. But because of the xruns, I decided to switch to PW. With PW, I got rid of kind of all xruns, even with a much smaller buffer size (down to 128)! Impressive. But then there are constant delays or latencies. I tried to fiddle with the PW configs, including ~/.config/pipewire/jack.conf. I locked quantums, specified the quantum to, for testing purposes, 512/48000. I also tried to set node.latency there, to no avail.

I couldn’t find a solution to this for days, so I decided to try the alternatives (again…): ALSA and JACK2. Both of these show a strange similar behavior at the moment. The first recording of the metronome is still delayed, like not (enough) compensated. But if I record multiple tracks after one another, the delay becomes smaller and smaller. At some point, the latency is “corrected” perfectly but… It continues to get smaller and smaller with time, so it ends up being over compensated, the record was BEFORE the bar after that. It’s the same with both, ALSA and JACK. So, after not even getting it to a constant offset, I decided to switch back to pipewire (which seems to be a nicer way of dealing with sound nowadays anyways).

I would be happy to be able to just record with proper latency compensation, also if I had to use ALSA or JACK, but preferably pipewire. Because Audacity has no issues at all, after manually setting up the latency correction, I am wondering - how can I configure this in Ardour? Or should I setup the configuration in pipewire(-jack) to be heeded by Ardour? It really seems to be an Ardour issue, but is it? Or should I check with the pipewire folks (too)?

Thanks in advance, if you need more details, please let me know. I am new to this audio world, but not new to Linux :slight_smile: I can also provide logs, configs, or whatever is necessary.

Cheers!

1 Like

Last I checked pipewire’s JACK backend does not report correct port latencies.

To calibrate systemic latency please with pipewire, please see How does PipeWire perform with Ardour? - #12 by x42

Anyway, for pro-audio use, sidestepping pipewire is likely your best option, still.

Pipewire likely lies to you. It can run any client at a small buffersize while the actual audio callback has a much longer latency. Check the actual hardware device settings.

1 Like

Wow, that looks promising - I just quickly tried to manually set the ProcessLatency for my speakers and it was immediately taken account for by ardour! Thanks!

So… Neither Audacity nor ardour complain (nor any other tools), nor do I hear any cracks, so it at least feels good. If it’s true what you say, how can the xruns be hidden so well?

Oh dear, I did not hope to hear that, because JACK and ALSA both were much worse out-of-the-box experiences than pipewire… As I said, not even constant latencies, many xruns, audible as cracks, etc. To be honest, I didn’t look into it that much yet, because I thought pipewire can be an elegant solution for this. So you recommend, I should try to get JACK and/or ALSA running instead?

Since pipewire uses ALSA under the hood it can only perform worse compared to Ardour using ALSA directly.

The likely explanation is that you configured Ardour/ALSA with too low a buffersize, or that you do not have configured your system to allow Ardour to use realtime permissions.

Check what pipewire uses. The following script lists all soundcards, their current settings and applications using them:

cd /tmp && wget https://community.ardour.org/files/adevices.sh && bash ./adevices.sh

Yeah, I’m aware of that, I was surprised, too.

Neat script! If the reported period_size is what I called the buffer size it looks to me like pipewire uses what it should. If it is indeed the buffer_size instead, then you were right, they are reported to be much bigger. But then I am wondering - wouldn’t these buffer sizes introduce a very noticeable delay of around .66s? I can’t hear this.

========================================
Part I: ALSA
Advanced Linux Sound Architecture Driver Version k6.1.4-arch1-1.

Card 0 (USB):
  * Playback Device 0 (USB Audio):
    - Subdevice 0 (hw:USB,0,0):
      closed

  * Recording Device 0 (USB Audio):
    - Subdevice 0 (hw:USB,0,0):
      used by: pipewire (PID 2100)
      access: MMAP_INTERLEAVED
      format: S32_LE
      subformat: STD
      channels: 6
      rate: 48000 (48000/1)
      period_size: 512
      buffer_size: 32768

 *SNIP*

Card 2 (Generic):
  * Playback Device 0 (ALC1220 Analog):
    - Subdevice 0 (hw:Generic,0,0):
      closed

  * Playback Device 1 (ALC1220 Digital):
    - Subdevice 0 (hw:Generic,1,0):
      used by: pipewire (PID 2100)
      access: MMAP_INTERLEAVED
      format: S32_LE
      subformat: STD
      channels: 2
      rate: 48000 (48000/1)
      period_size: 1024
      buffer_size: 32768

 *SNIP*

========================================
Part II: jack processes

The key here is the buffer size. With a period size of 512, Ardour would use a buffer size of 1024. Pipewire is using a buffer size 32 times larger.

So pipewire is using the equivalent of the jackd arguments -p 512 -n 64?

Yes, correct. These settings are basically: small period size, huge buffer. Low input latency, strong protection against xruns. Then you use a DLL to estimate where the read/write “pointers” are, and allow low-latency apps to write close to them, reducing effective output latency.

1 Like

Thanks, good to know! In this context, what does DLL mean?
Coming back later to this topic, gotta lot to do.

1 Like

“DLL” is an acronym for Delay Locked Loop, which is a design/algorithm for accurately estimating the time on of one clock when you can only sample it periodically.

1 Like