roc-streaming / roc-pulse

Roc Toolkit modules for PulseAudio.
https://roc-streaming.org
GNU Lesser General Public License v2.1
8 stars 2 forks source link

Pulseaudio sending config does not honor sample rate #14

Closed Kaspi314 closed 6 months ago

Kaspi314 commented 4 years ago

When sending from pulse audio (Ubuntu 20 LTS Desktop) with resampling in PA Daemon config to 48000hz 2channel f16, setting is not honored or configurable for the PA module and it will not connect to Raspberry Pi ALSA session.

With 44100hz there is an inability for the resampler to keep up even on LOW with the Pi 4:

`22:01:05.473 [dbg] roc_packet: router: detected new stream: source=1807046489 flags=0x8u

22:01:05.473 [dbg] roc_audio: depacketizer: ts=320 loss_ratio=0.00000

22:01:05.513 [dbg] roc_packet: router: detected new stream: source=0 flags=0x10u

22:01:05.593 [dbg] roc_audio: watchdog: status: bbbbbbbbbbbbbbbbbbbb

22:01:05.663 [dbg] roc_packet: delayed reader: initial queue: delay=8820 queue=8961 packets=29

22:01:05.663 [dbg] roc_fec: fec reader: update payload size: next_esi=0 cur_size=0 new_size=1248

22:01:05.663 [dbg] roc_fec: fec reader: update source block size: cur_sblen=0 cur_rblen=0 new_sblen=20

22:01:05.663 [dbg] roc_audio: depacketizer: got first packet: zero_samples=8960

22:01:05.663 [dbg] roc_audio: latency monitor: latency=8641 target=8820 fe=1.00000 trim_fe=1.00000 adj_fe=0.91875

22:01:05.703 [dbg] roc_fec: fec reader: repair queue: dropped=10

22:01:05.703 [dbg] roc_fec: fec reader: got first packet in a block, start decoding: n_packets_before=7 sbn=31405

22:01:05.703 [dbg] roc_fec: fec reader: update repair block size: cur_sblen=20 cur_rblen=0 new_rblen=235

22:01:05.743 [dbg] roc_audio: watchdog: status: bbbbbbbb............

22:01:10.673 [dbg] roc_audio: latency monitor: latency=9085 target=8820 fe=1.00000 trim_fe=1.00000 adj_fe=0.91875

22:01:15.673 [dbg] roc_audio: latency monitor: latency=9231 target=8820 fe=1.00002 trim_fe=1.00002 adj_fe=0.91877 `

gavv commented 3 years ago

@Kaspi314 Hi, thanks for report.

Currently roc always sends 44100 via network. In 0.2 we'll add RTSP support, which will allow us to negotiate sample rate on fly and send any rate you need.

And yes, builtin roc resampler is too slow on some hardware. But in develop branch, we've added support for speex resampler, which is now used by default. Most likely, it will work good for you, so I recommend to try develop branch. Note that the command-line syntax was changed a bit in develop.

Another approach would be to stay on master branch and configure dmix to do resampling from 44100 to 48000 instead of roc. But in this case you'll also loose clock drift compensation in roc, which relies on resampler.

gavv commented 3 years ago

Let's keep this issue open until we'll add an option to pulseaudio modules to specify custom sample rate to use over network.

berglh commented 2 years ago

@Kaspi314 I'm not sure if this will work, but perhaps one option could be to use the new roc-pulse modules. I needed to use these roc-pulse modules for PA 15.0 in Ubuntu 21.10, as the build method for PulseAudio has changed and the roc-toolkit was successfully building from the PA source. Then, feasibly, one could edit the module source code with your desired transmission settings. At this stage I'm still not seeing any RTSP support, so perhaps the following would give you at least a set sample spec that suits your needs.

Edit: I had a diff here for modifying the configuration, but I have to say, I'm only getting static over the roc-modules, so unless I figure this out, I'm going to say we can only wait for RTSP support.

Edit 2: So, it turns out the sample rate 48000 does work if you retain the 32-bit sample format, here's the diff:

diff --git a/src/module-roc-sink-input.c b/src/module-roc-sink-input.c
index b1e6e25..f396202 100644
--- a/src/module-roc-sink-input.c
+++ b/src/module-roc-sink-input.c
@@ -159,7 +159,7 @@ int pa__init(pa_module* m) {
     /* prepare sample spec and channel map used in this sink */
     pa_sample_spec sample_spec;
     sample_spec.format = PA_SAMPLE_FLOAT32LE;
-    sample_spec.rate = 44100;
+    sample_spec.rate = 48000;
     sample_spec.channels = 2;

     pa_channel_map channel_map;
@@ -213,7 +213,7 @@ int pa__init(pa_module* m) {
     roc_receiver_config receiver_config;
     memset(&receiver_config, 0, sizeof(receiver_config));

-    receiver_config.frame_sample_rate = 44100;
+    receiver_config.frame_sample_rate = 48000;
     receiver_config.frame_channels = ROC_CHANNEL_SET_STEREO;
     receiver_config.frame_encoding = ROC_FRAME_ENCODING_PCM_FLOAT;

diff --git a/src/module-roc-sink.c b/src/module-roc-sink.c
index 208c47d..98829e7 100644
--- a/src/module-roc-sink.c
+++ b/src/module-roc-sink.c
@@ -220,7 +220,7 @@ int pa__init(pa_module* m) {
     /* prepare sample spec and channel map used in this sink */
     pa_sample_spec sample_spec;
     sample_spec.format = PA_SAMPLE_FLOAT32LE;
-    sample_spec.rate = 44100;
+    sample_spec.rate = 48000;
     sample_spec.channels = 2;

     pa_channel_map channel_map;
@@ -267,7 +267,7 @@ int pa__init(pa_module* m) {
     roc_sender_config sender_config;
     memset(&sender_config, 0, sizeof(sender_config));

-    sender_config.frame_sample_rate = 44100;
+    sender_config.frame_sample_rate = 48000;
     sender_config.frame_channels = ROC_CHANNEL_SET_STEREO;
     sender_config.frame_encoding = ROC_FRAME_ENCODING_PCM_FLOAT;

Example Output:

$ pactl list sink-inputs
Sink Input #0
    Driver: roc_receiver
    Owner Module: 25
    Client: n/a
    Sink: 1
    Sample Specification: float32le 2ch 48000Hz
    Channel Map: front-left,front-right
    Format: pcm, format.sample_format = "\"float32le\""  format.rate = "48000"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
    Corked: no
    Mute: no
    Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
           balance 0.00
    Buffer Latency: 0 usec
    Sink Latency: 46931 usec
    Resample method: copy
    Properties:
        media.name = "Roc Receiver"
        module-stream-restore.id = "sink-input-by-media-name:Roc Receiver"
gavv commented 6 months ago

It's now possible to configure both network encoding and local sink/sink-input encoding. See parameters tables in README, in particular packet_encoding_xxx, sink_xxx, and sink_input_xxx parameters.

If local and network encodings do not match, roc will perform conversion.

Currently there is only limited set of formats and channel layouts, more to be added in future releases.

I'm closing the issue, but feel free to reopen if needed.