How does JACK deal with audio resampling?
Please consider this as a feature request for your wiki. I would like to know what happens when I feed 192KHz JACK server with 48KHz audio stream from a GStreamer application. Which component does the resampling? Can it be compared to PulseAudio's approach of universal resampling through a user defined method? I use JACK because it provides much more reliable audio output than standalone PulseAudio, especially when I start to push the latencies down and sample rates up. So far I have observed that the music player that I use does consume quite a lot of CPU ( 6% vs 3% when played through PulseAudio), so it seems to me that JACK resamples client-side. Is that right? Can I control it in any way? I am asking those questions because I am pursuing the ideal configuration of JACK-supported PulseAudio setup for general use in non-professional computing. I am aware that I can hardly call it "audiophile" as this term implies purity, where I am upsampling everything to maximum. If my card gives me support for 192KHz, I want to use it fully. I am the kind of person that pushes his system to its limits for the fun of it. That and I also found that the high-sampled audio has some "undescribable quality" to it which I like more. As far as I know, right now I have a choice of:
- PulseAudio does all processing by itself (which I can control freely) and feeds the result to JACK which handles the actual output with reliability superior to PulseAudio's.
- Where it is possible, bypass PulseAudio entirely by feeding JACK directly, but lose all control beyond the initial server configuration. So I know that it plays the way it is told to, but have no idea how it is done. I started to worry about it because I have isolated a CPU core for exclusive use by pulseaudio and jackdbus, but if the resampling is client-side, then I will have to keep using taskset to move the applications too.
The application does the resampling. In your case gstreamer. Every jack client is responsible to provide data at the rate that jackd is running.
Jack gets its clock from the soundcard (more specifically from the soundcard's oscillator or soundcard's clock source). All jack applications sharing the jack server run at that sample-rate.
Jack does not do any DSP at all, it only provides a realtime-safe mechanism to pass data around (and jack itself does not even care what that data is - the only exception where jack does some processing is mixing port-buffers). For advanced uses (e.g synchronizing two soundcards) the jack API provides elaborate means to query the clock, time and jitter, but jack cannot make decisions what the best approach for resampling/synchronization is. Only the application can do that. jack itself only provides information and mechanisms but does not take action by itself.
Using taskset to tweak applications per process is not the correct approach. JACK calls into the clients (pull architecture) and asks for audio-data on regular basis (soundcard IRQ). That thread is elevated (realtime priority) and the jack-process callback inside the application inherits that. The application process itself (GUI, disk-i/o, etc which you can control with taskset) should remain as low priority as possible and be decoupled by a lock-free ringbuffer from the audio-callback. Unless you really know what you're doing, reserving cores for specific processes or threads will usually result in worse behavior.
PS. If you had enough fun pushing your system to the limit, check out https://xiph.org/~xiphmont/demo/neil-young.html
I'll leave this open as a reminder. Some better presentation of the basic concepts of JACK is already a TODO.