View Issue Details

IDProjectCategoryView StatusLast Update
0010193ardourbugspublic2026-02-23 13:09
Reporterlina Assigned To 
PrioritynormalSeveritycrashReproducibilityalways
Status newResolutionopen 
PlatformGNUOSLinuxOS Version(any)
Product Version9.0 
Summary0010193: Export process cannot handle different freewheel buffer size (pipewire)
DescriptionWhen using PipeWire-JACK, the buffer size is normally configured automatically depending on which device is driving the graph. Since freewheel mode changes the driver to the freewheel driver, this can also change the buffer size.

The export code uses the current buffer size to configure the export process, before switching freewheel on. When freewheel is enabled, the JACK buffer size callback is called, but by then it's too late as the export is already configured for the old buffer size. When the process callback is called with a larger process buffer size, it causes everything to crash. On my system, freewheel seems to default to a 1024 quantum, while I use 256 for my audio interface.

A release build shows an export error dialog, then crashes with a double free() when it is dismissed (sometimes, by the time this happens memory corruption has happened so sometimes you don't even get the dialog).

A debug build crashes here:

ardour-9.0.110: ../libs/ardour/export_graph_builder.cc:174: ARDOUR::samplecnt_t ARDOUR::ExportGraphBuilder::process(ARDOUR::samplecnt_t, bool): Assertion `samples <= process_buffer_samples' failed.

With that variable bumped up to 1024, it instead crashes here:

ardour-9.0.110: ../libs/ardour/session_export.cc:382: void ARDOUR::Session::process_export_fw(ARDOUR::pframes_t): Assertion `0' failed.

With that code removed to allow the exception to propagate, this is what happens:

terminate called after throwing an instance of 'AudioGrapher::Exception'
  what(): Exception thrown by AudioGrapher::Interleaver<float>: Too many samples given to an input

A workaround is `pw-metadata -n settings 0 clock.force-quantum 256` (or whatever) to force the buffer size to be globally constant, even for freewheel. `PIPEWIRE_QUANTUM=256/48000 ardour9` also works (PIPEWIRE_LATENCY is not sufficient).
Steps To Reproduce1. Configure PipeWire to use a fixed buffer size for an audio device, for example,

.config/wireplumber/wireplumber.conf.d/92-alsa-props.conf:

monitor.alsa.rules = [
{
  matches = [ { "node.description" = "Device name here" } ]
  actions = {
    update-props = {
      api.alsa.period-size = 256,
      api.alsa.headroom = 256,
      api.alsa.disable-batch = false,
      device.profile = "pro-audio",
    }
  }
},
]

2. Attempt to export a project
Additional InformationIf this is not supposed to work / too hard to implement, then at least the situation should be handled gracefully with an error informing the user to force a constant quantum size, instead of segfaulting in release builds.
TagsNo tags attached.

Activities

x42

2026-02-20 11:44

administrator   ~0029925

This is a bug in pipewire's JACK emulation.
(the problem does not exist with jackd 1 or jackd 2).

Please report it to https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/ Thank you

lina

2026-02-20 11:48

reporter   ~0029926

JACK allows changing buffer sizes at runtime, right? Although the behavior is different to JACK1 and JACK2, I don't see why this would be considered a bug, since there's nothing strictly incorrect about what PipeWire is doing. In general, having a larger buffer size for freewheel seems like a good idea, since it would speed up the export by reducing process cycle overhead.

(aside: due to personal reasons I am uncomfortable reporting PipeWire bugs myself at this time, so if you believe it should be changed on the PipeWire side, would it be possible for you to file the bug?)

paul

2026-02-20 17:16

administrator   ~0029933

JACK1/JACK2 do allow buffer size changes (Ardour's Audio/MIDI setup dialog even specifically includes a widget to change it), but such changes are sent as callback-notifications to all clients, so that they can adjust to them. It appears that PW is not doing this when switching to freewheeling.

lina

2026-02-20 19:25

reporter   ~0029947

PipeWire is sending the notification, as I mentioned ("the JACK buffer size callback is called", I checked, Ardour is getting it). The issue is that Ardour assumes the buffer size does not change when enabling freewheeling, as it checks the buffer size when starting the export process and assumes it does not change later.

This can be seen here: https://github.com/Ardour/ardour/blob/8db31ef9b6f8d1700dc51989c9d2186d99550592/libs/ardour/export_graph_builder.cc#L162 (this gets constructed *before* enabling freewheeling, and this causes the first assert to fire). I haven't tracked down the AudioGrapher::Interleaver one later, but I assume it's the same deal, something that queries the buffer size on construction and then assumes it does not change later.

paul

2026-02-20 19:46

administrator   ~0029950

Ah, I see now.

so this is not so much a "bug" in PW, but a different behavior that is entirely legal but trips us up ... really, the export graph can't be built until the first process() call during a freewheel

not clear if PW ought to get itself in line with JACK1/2 behavior or if we should reengineer the whole export graph design to workaround their change ....

paul

2026-02-20 21:55

administrator   ~0029964

from OFTC #pipewire

<las> wtay, is there a reason that PW's JACK implementation changes buffer size when entering freewheel ? neither JACK1 nor JACK2 do this ...
<las> wtay, https://tracker.ardour.org/view.php?id=10193
<wtay> it should do what jack1/2 does, I would need to investigate how it happens

wtaymans

2026-02-23 11:13

reporter   ~0029983

I see what is happening. Configuring the device node with the wireplumber fragment does not give enough
information to the scheduler to propagate the buffer-size to the freewheel driver. I would suggest to add
node.force-quantum=256 to the node properties as well:

monitor.alsa.rules = [
{
  matches = [ { "node.description" = "Device name here" } ]
  actions = {
    update-props = {
      api.alsa.period-size = 256,
      api.alsa.headroom = 256,
      api.alsa.disable-batch = false,
      device.profile = "pro-audio",
       node.force-quantum = 256
    }
  }
},
]

This should likely be done automatically, I will look how this can be done but for now adding the extra property should work.

lina

2026-02-23 11:17

reporter   ~0029984

If PipeWire is intended to keep the buffer size in this case, it sounds like on the Ardour side there should just be better handling of this case to error out then. At least I'd like to see something that catches it in release builds, since technically correct (but unexpected) API behavior causing memory corruption is not great...

wtaymans

2026-02-23 12:25

reporter   ~0029985

> If PipeWire is intended to keep the buffer size in this case

I can imagine running the real-time graph with small buffers and then switch to a larger buffer when freewheeling so I'm a bit reluctant to remove this possibility to work
around a custom configuration issue.

There are 3 ways to handle the buffer size on PipeWire

1. An application specifies what it wants; the buffer size and if it can switch etc. PipeWire then selects the smallest buffer size that satisfies all apps. In general all applications should be able to deal with a buffer size they didn't suggest. You can do this with the in-app options or start the app with PIPEWIRE_QUANTUM/PIPEWIRE_LATENCY depending on how strong your suggestion is..
2. A driver specifies the buffer size. PipeWire will only use this suggestion when the driver is driving. When you switch to another driver (freewheel) the suggestion is no longer used. (this is what you do here and nothing else specifies a buffer-size so it switches to the default of 1024).
3. A global forced rate/buffer-size (with pw-metadata or hardcoding the config file)

In my mind, the most user friendly option is 1. where you use Ardour to configure the buffer size and that is what is used. This should also switch the devices (in pro-audio) to this period-size etc. When you stop Ardour, things go back to the defaults. Is there a reason to force the period-size on the node like you do?

lina

2026-02-23 13:09

reporter   ~0029986

I have a particular audio device (or two) that I use for proaudio stuff (with realtime monitoring which is the only case where latency matters), so to me it makes sense to set the buffer size there. That way I don't have to worry about different apps having different settings (for example, I also use carla for live production) and then I can also use Ardour to do non-realtime mixing on the go with the built-in headphones out, etc. The proaudio setup is only ever used docked/connected to AC, so there is no reason to worry about power efficiency. The only real downside is higher risk of xruns when doing non-proaudio use, but if the realtime setup works well enough that's not that big an issue...

There are also some apps (carla sometimes, certain plugins...) that choke on buffer size changes. That's a bug in those apps, but it helps if it's kept constant during normal use.

In a way, this mirrors how I used JACK1/2 before PipeWire: JACK would always drive my proaudio interface only, with a fixed default buffer size, and PulseAudio bridging into it for non-realtime apps; and PulseAudio would directly drive all other audio devices.

Issue History

Date Modified Username Field Change
2026-02-20 07:35 lina New Issue
2026-02-20 11:44 x42 Note Added: 0029925
2026-02-20 11:48 lina Note Added: 0029926
2026-02-20 17:16 paul Note Added: 0029933
2026-02-20 19:25 lina Note Added: 0029947
2026-02-20 19:46 paul Note Added: 0029950
2026-02-20 21:55 paul Note Added: 0029964
2026-02-23 11:13 wtaymans Note Added: 0029983
2026-02-23 11:17 lina Note Added: 0029984
2026-02-23 12:25 wtaymans Note Added: 0029985
2026-02-23 13:09 lina Note Added: 0029986