Ticket #593 (closed enhancement: fixed)

Opened 3 years ago

Last modified 2 years ago

How to modify pacat to route source to sink with minimum latency

Reported by: knightk Owned by: lennart
Milestone: 0.9.16 Component: clients
Keywords: Cc:

Description (last modified by coling) (diff)

I'm capturing stereo analog audio at rate=44100, format=s16le channels=2 using module-alsa-source. I'm sinking out to USB at rate=44100, format=s16le, channels=2 using module-alsa-sink.

pacat -r --format=s16le --rate=44100 --channels=2 | pacat -p --format=s16le --rate=44100 --channels=2

is working but the latency is 1-2 seconds and a lot of packets are dropped.

I want to modify pacat to route source to sink internally without piping.

Can anyone confirm that my approach is OK, which is as follows:-

  1. in main() comment out stdio_event = mainloop_api->io_new (because I don't want the daemon to poll stdin/stdout callbacks.
  2. in context_state_callback() create both sink_stream and source_stream but only callback on the source_stream. Set up attr so that prebuf is 0 and call pa_stream_trigger(sink_stream, stream_trigger_complet_cb, NULL) [for immediate playback], then connect for both source and sink streams.
  3. When source_callback is called pa_stream_peek(source_stream, &data, &length) then pa_stream_write(sink_stream, data, length, PA_SEEK_RELATIVE).

I'm unsure about using zero_copy i.e. data points to captured packet in the source buffer. Am I transferring from the source buffer to the sink buffer?

Change History

Changed 3 years ago by Rudd-O

patches, man. patches or a git tree, to see what you're doing. that way w can examine your work in detail.

Changed 3 years ago by coling

  • description modified (diff)

To be honest I wouldnt' take this approach at all. pacat is a toy, a testing tool and what you are trying to do is quite hard core.

I would create a new pulseaudio module that can be loaded with source= and sink= arguments that does this active passthrough. The module would be able to handle things much nicer.

In addition, as the clocks of your input and output devices will vary, you need to have some kind of active logic in the loop to do some resampling. This is non-trivial code, but a similar set of code exists already in module-combine. It also has to deal with devices with varying clocks and does on-the-fly resampling.

I strongly believe that a module is the right approach here, not a modification to pacat.

I am currently working on a GUI that will allow the definition of various modules to load, so if you created this module, I'll happily add GUI support for defining such "passthroughs".

Changed 3 years ago by coling

I meant also to say that this is being requested more and more often these days so I really encourage you to do it :) Writing a module is not that hard really and while I'm not an expert I'd be happy to offer any advice I can. Just come on IRC :)

Changed 2 years ago by lennart

  • milestone set to 0.9.16

We now have "module-loopback" which can connect a sink and a source directly and inside the server. This is much more useful to allow low latencies.

Changed 2 years ago by coling

  • status changed from new to closed
  • resolution set to fixed

As this is in git master which will become 0.9.16, I think the ticket can be closed? Any reason to keep it open Lennart?

Note: See TracTickets for help on using tickets.