Pulseaudio Crossover Rack - multi-way crossover design & implementation with linux

Good catch, Jürgen. I would not think the timer-based scheduling could timeshift individual channels of one stream, I would assume all channels would be delayed at once. Yet IRQ-based scheduling fixed the problem. Do you have any tip for a bug in PA in this regard? That's very interesting.

I had to dig a little to find it again. It's still just a suspicion that this might be the underlying cause (please also read the bug report contained in the source:
Code:
/* Called from I/O thread context */
static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
    struct userdata *u;

    pa_sink_input_assert_ref(i);
    pa_assert_se(u = i->userdata);

    /* FIXME: Too small max_rewind:
     * [url=https://bugs.freedesktop.org/show_bug.cgi?id=53709]53709 – Filter sinks (and sources?) have too small max_rewind[/url] */
    pa_memblockq_set_maxrewind(u->memblockq, nbytes);
    pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
}
 
Ok.

Example of using 2 frd overlays. I have a measured response exported from my crossover designing app. I want to tweak that result, and aim for a non-flat target. So I need to see the starting response and the target response (the starting response will combine with the filters, but the target response just sits there as a fixed overlay).

2 examples of saving frds. To take back to my crossover designing app. And when I have too many EQ plugins and want to simplify the setup but need to save the result to use as a target on the new set.

OK, please open an issue @ gitlab, so I won't forget this request.

Overlays will be worked on in any case, as measurement support moves on.
 
Jürgen, please do you have any experience with capturing from one soundcard (module-alsa-source) and playing the incoming data (after your processing) to another soundcard (module-alsa-sink) with independent clock? The module-combine-sink adaptively resamples only between several sinks, I could not find any solution for adaptively resampling between source - sink.

I am asking because Charlie Laub with me have made the usb-audio gadget linux driver work in windows, which turns RPi4 (with USB OTG port) into a regular USB sound device (playback only for now, any samplerate, any number of channels). This allows building an "intelligent" USB soundcard with any processing running in linux on RPi. Data from the USB gadget are available on RPi as a virtual alsa capture soundcard (listed in arecord -l).

But the capture soundcard (source) is timed by the USB controller of the host (adaptive mode), whereas the playback (sink) is timed by the output soundcard - two clock domains to synchronize. The correct way would be making the usb-gadget proper async soundcard, but that is quite a major complication.

Thanks for any info.

Unfortunately I don't :whazzat:

I asked a very similar question already on the mailing list, no reply at the time. I suggest you ask yourself and keep us posted. I could setup a small test bed with my two soundcards on the laptop for you though, capture device would be an ASUS Xonar U5, adaptive mode, playback the internal Intel HD Audio. Would that help you? Btw "pacmd list sinks" lists the used resampling method, maybe in this case the loopback module would take care of the resampling?

Btw. very interesting news on the usb audio gadget driver and the concept of the "intelligent soundcard".
 
Thanks. The module-loopback does indeed drop/insert samples automatically pulseaudio/module-loopback.c at master * pulseaudio/pulseaudio * GitHub . A rudimentary method, but OK for non-critical purposes. But you do not use this module in your setup, right?

A proper adaptive resampling like in module rtp would be much better :) pulseaudio/module-rtp-recv.c at master * pulseaudio/pulseaudio * GitHub


Testing the current situation would definitely help, with your code used, without the resampling module-loopback. But detecting the buffer inconsistencies may be a bit complicated since they may occur scarcely (usually the clock freqs will differ only very little).
 
I think you read the code a bit wrong ;)

There's a comment near the end of the function:
/* Drop or insert samples if fast_adjust_threshold_msec was specified and the latency difference is too large. */

You disregarded the if. If fast_adjust_threshold_msec is not specified, the early return doesn't catch and the rest of the function calculates the adjusted sample rate and sets it on the sink input, so the following sink can resample accordingly. At least that's how I read it at a glance.
 
diyAudio Moderator
Joined 2008
Paid Member
I just want to say that I'm having a lot of fun with this. I'm hoping I can take it further.

My measurement and crossover designing tools are on a different system and I dual boot to them. This has been setting limits but I'm holding out for better.

I don't know whether a USB card is close in timing to an onboard card. I started using it today and results are promising.
 
You disregarded the if. If fast_adjust_threshold_msec is not specified, the early return doesn't catch and the rest of the function calculates the adjusted sample rate and sets it on the sink input, so the following sink can resample accordingly. At least that's how I read it at a glance.

You are absolutely right. That is great news. But only for module-loopback users :) Is there any way to use such code (calculating and setting current rate to the stream, letting PA resample automatically) in your project?
 
Unfortunately I do not see the method pa_sink_input_set_rate used for adaptive resampling in any standard PA input module, only in loopback, combine, and echo-cancel.

Actually adaptive resampling is only ever needed in case of loopback or combine, where the hardware clocks of the source and sink (in case of loopback) or the two sinks (in case of combine) may differ slightly over time. So that's why there is only code in these modules. This way using two soundcards with different clocks (not adaptive) should also work with PaXoverRack as the splitter is modeled by a module-combine-sink internally.

You are absolutely right. That is great news. But only for module-loopback users :) Is there any way to use such code (calculating and setting current rate to the stream, letting PA resample automatically) in your project?

If you use a different sample rate in your player than the one that pulseaudio runs at it will always resample accordingly but this doesn't need to be adaptive, instead it is performed with a fixed resampling ratio, for example playing a 44.1kHz file while pa runs at 96kHz. After all the player (source) is synced to the sink input's clock. This happens completely transparently, the only thing to configure is the resampler to be used internally. I set it to soxr-vhq (vhq being very high quality), though I have to admit that I don't hear any difference to speex-float-2, which is the not-very-high-quality default resampler.

Btw speaking of "using such code in my project" is probably a tad incorrect (;)), after all the hard work is all done by pulseaudio itself, I'm just configuring a bunch of pulseaudio modules and then persisting their config in the default.pa file.
 
Actually adaptive resampling is only ever needed in case of loopback or combine, where the hardware clocks of the source and sink (in case of loopback) or the two sinks (in case of combine) may differ slightly over time.

What if your source is timed to another clock? Recording from a second soundcard, USB-audio gadget (OTG) output, incoming SPDIF signal, etc.?
 
Modules

You can specify both the source and the sink which you want to connect. source would then be your capture device, i.e. a soundcard with SPDIF input or the gadget. Sink would then be PaXoverRack.Input, it's always named the same.

EDIT: Please note that the statement setting up the loopback module must come after all the stuff that PaXoverRack sets up.
 
Last edited:
Well, I've been playing music in JRiver from local files, streaming from the NAS, Streaming via DLNA as well as streaming bluetooth from my phone to Lubuntu for the past hour without a glitch. It looks like adding the tsched=0 did the trick!

I love your PaXoverRack software!
Thanks again Tfive


Unfortunately, something that I noticed with the new tsched=0 setting, when PulseAudio has been sitting idle for a couple minutes and then I play audio, regardless of the input source, the audio begins with the output channels completely out of sync, and slowly syncs up. It takes about 40s but once it locks up it stays locked until the next time it sits idle for a few minutes.

This is happening with the Atomic Pi running Lubuntu
 
We'll have to deal with workarounds in the time it takes to debug the issue with pulseaudio and ladspa sinks etc...

Meanwhile you can try commenting the line "load-module module-suspend-on-idle" in the default.pa to prevent pulseaudio to suspend your soundcard sinks. I suspect this will prevent the issue after idle.

Please chime and confirm the bug here: (!)
Playback heavily out of sync with ASUS Xonar U5 and U7 without tsched=0 (#651) * Issues * PulseAudio / pulseaudio * GitLab
Please also share your configuration there.
 
We'll have to deal with workarounds in the time it takes to debug the issue with pulseaudio and ladspa sinks etc...

Meanwhile you can try commenting the line "load-module module-suspend-on-idle" in the default.pa to prevent pulseaudio to suspend your soundcard sinks. I suspect this will prevent the issue after idle.

Please chime and confirm the bug here: (!)
Playback heavily out of sync with ASUS Xonar U5 and U7 without tsched=0 (#651) * Issues * PulseAudio / pulseaudio * GitLab
Please also share your configuration there.

That thread is closed now. I'm about to read through it all the same.

Thanks again Tfive
 
It's not reopened as of now, because I failed to meet the debugging requirements of the PA developer a few months back. I'm trying to come up with a minimal case to reproduce this issue, which is not at all trivial. There are a lot of variables involved: sample format, sample rate, number of ladspa plugins, number of splitters (modeled as combine-sink modules) etc...

It would certainly help if you just commented and told them you are affected, too! There can still be comments on "closed" issues. Expect it to be reopened soon, as I will do a whole lot of boresome debugging setup tomorrow :/

I'm off to bed soon though doday... Hopefully.