[GH-ISSUE #199] 5.1 and 7.1 surround issues #130

Closed
opened 2026-10-15 12:56:54 +00:00 by bsakaguchi · 14 comments
Owner

Originally created by @clevelandcs on GitHub (Apr 30, 2025).
Original GitHub issue: https://github.com/games-on-whales/wolf/issues/199

Hi,

Similar to #188 after following the quick start guide everything seems to work for the most part. But until Steam fully comes up there's a odd constant buzzing feedback sound. Then the steam startup sounds play and are very distorted, in any game the feedback and distortion goes away except there's another kind of feedback that is louder than game audio I guess the best description would be kind of like the sound of bubbles popping.

For the server side I followed the LXC unprivileged guide using the community scripts docker template.
Hardware specs:
AMD Epyc 7C13
RTX 4060Ti 16GB Driver Version: 570.144
512GB on host 32GB assigned to LXC

Client:
Arch Linux 6.14.3-2-cachyos
AMD 7840U with 780M
64GB 5600 MHz
Moonlight flatpak 6.1.0
pipewire 1.4.2

wolf_logs.txt

audio_feedback_recording

I have previously used Sunshine on a Windows 10 host on KVM on the same machine with GPU passthrough without audio issues but with much worse game performance so I would LOVE to get this audio issue resolved. Thank you so much for creating this project!

Originally created by @clevelandcs on GitHub (Apr 30, 2025). Original GitHub issue: https://github.com/games-on-whales/wolf/issues/199 Hi, Similar to #188 after following the quick start guide everything seems to work for the most part. But until Steam fully comes up there's a odd constant buzzing feedback sound. Then the steam startup sounds play and are very distorted, in any game the feedback and distortion goes away except there's another kind of feedback that is louder than game audio I guess the best description would be kind of like the sound of bubbles popping. For the server side I followed the LXC unprivileged guide using the community scripts docker template. Hardware specs: AMD Epyc 7C13 RTX 4060Ti 16GB Driver Version: 570.144 512GB on host 32GB assigned to LXC Client: Arch Linux 6.14.3-2-cachyos AMD 7840U with 780M 64GB 5600 MHz Moonlight flatpak 6.1.0 pipewire 1.4.2 [wolf_logs.txt](https://github.com/user-attachments/files/19970585/wolf_logs.txt) [audio_feedback_recording](https://github.com/user-attachments/assets/dd635cc6-78de-45c0-854d-929228c46f49) I have previously used Sunshine on a Windows 10 host on KVM on the same machine with GPU passthrough without audio issues but with much worse game performance so I would LOVE to get this audio issue resolved. Thank you so much for creating this project!
bsakaguchi 2026-10-15 12:56:54 +00:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@ABeltramo commented on GitHub (Apr 30, 2025):

You have a few warnings related to audio in your logs, seems that Moonlight is asking for 7.1 can you try forcing it to Stereo and see if that fixes the issue?
Also, could you try running a stream from another device like your phone just to make sure that it's not something client side?

<!-- gh-comment-id:2842560171 --> @ABeltramo commented on GitHub (Apr 30, 2025): You have a few warnings related to audio in your logs, seems that Moonlight is asking for 7.1 can you try forcing it to Stereo and see if that fixes the issue? Also, could you try running a stream from another device like your phone just to make sure that it's not something client side?
Author
Owner

@corsjune commented on GitHub (May 3, 2025):

I get this with both a both linux mint 22.1 moonlight client and a Google TV client. No problems on Stereo but when trying surround sound, I have the buzz when starting and the sound is distorted just as described above(tried Steam and Firefox).

<!-- gh-comment-id:2848826256 --> @corsjune commented on GitHub (May 3, 2025): I get this with both a both linux mint 22.1 moonlight client and a Google TV client. No problems on Stereo but when trying surround sound, I have the buzz when starting and the sound is distorted just as described above(tried Steam and Firefox).
Author
Owner

@corsjune commented on GitHub (May 4, 2025):

To followup, I noticed these errors in the log when the client was set to 5.1 Surround:

ay 03 19:48:18 TheBox systemd-wolf[215457]: 23:48:18.604991776 DEBUG | Starting audio pipeline:
May 03 19:48:18 TheBox systemd-wolf[215457]: interpipesrc listen-to=11932517098611438130_audio is-live=true stream-sync=restart-ts max-bytes=0 max-buffers=3 block=false !
May 03 19:48:18 TheBox systemd-wolf[215457]: queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert !
May 03 19:48:18 TheBox systemd-wolf[215457]: opusenc bitrate=256000 bitrate-type=cbr frame-size=5 bandwidth=fullband audio-type=restricted-lowdelay max-payload-size=1400 !
May 03 19:48:18 TheBox systemd-wolf[215457]: rtpmoonlightpay_audio name=moonlight_pay packet_duration=5 encrypt=true aes_key="EA4EBC3D9BB95BFF655284470F70577C" aes_iv="1718160330" ! appsink sync=false name=wolf_udp_sink
May 03 19:48:18 TheBox systemd-wolf[215457]: 23:48:18.605772445 DEBUG | Setting up wolf_udp_sink

May 03 19:48:20 TheBox systemd-wolf[215457]: 0:56:03.827259178 1 0x720bec003ad0 WARN basesrc gstbasesrc.c:4255:gst_base_src_push_segment: segment format mismatched, ignore
May 03 19:48:20 TheBox systemd-wolf[215457]: 0:56:03.827506628 1 0x720bec003110 WARN opusenc gstopusenc.c:510:gst_opus_enc_find_channel_position_in_vorbis_order: Channel position 6 is not representable in Vorbis order
May 03 19:48:20 TheBox systemd-wolf[215457]: 0:56:03.827519328 1 0x720bec003110 WARN opusenc gstopusenc.c:510:gst_opus_enc_find_channel_position_in_vorbis_order: Channel position 7 is not representable in Vorbis order

My takeaway from asking Claude AI, some issue where the mapping of channels for 7.1/5.1 surround occurs in the opus encoder in Gstreamer?

If I change the the default_audio_params in config.toml to :

[gstreamer.audio]
default_audio_params = 'queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert ! audioresample ! audio/x-raw,channels=6,channel-mask=(bitmask)0x3f'

It seems to work with 5.1 for the client.

<!-- gh-comment-id:2848897826 --> @corsjune commented on GitHub (May 4, 2025): To followup, I noticed these errors in the log when the client was set to 5.1 Surround: ay 03 19:48:18 TheBox systemd-wolf[215457]: 23:48:18.604991776 DEBUG | Starting audio pipeline: May 03 19:48:18 TheBox systemd-wolf[215457]: interpipesrc listen-to=11932517098611438130_audio is-live=true stream-sync=restart-ts max-bytes=0 max-buffers=3 block=false ! May 03 19:48:18 TheBox systemd-wolf[215457]: queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert ! May 03 19:48:18 TheBox systemd-wolf[215457]: opusenc bitrate=256000 bitrate-type=cbr frame-size=5 bandwidth=fullband audio-type=restricted-lowdelay max-payload-size=1400 ! May 03 19:48:18 TheBox systemd-wolf[215457]: rtpmoonlightpay_audio name=moonlight_pay packet_duration=5 encrypt=true aes_key="EA4EBC3D9BB95BFF655284470F70577C" aes_iv="1718160330" ! appsink sync=false name=wolf_udp_sink May 03 19:48:18 TheBox systemd-wolf[215457]: 23:48:18.605772445 DEBUG | Setting up wolf_udp_sink May 03 19:48:20 TheBox systemd-wolf[215457]: 0:56:03.827259178 1 0x720bec003ad0 WARN basesrc gstbasesrc.c:4255:gst_base_src_push_segment:<interpipesrc9> segment format mismatched, ignore May 03 19:48:20 TheBox systemd-wolf[215457]: 0:56:03.827506628 1 0x720bec003110 WARN opusenc gstopusenc.c:510:gst_opus_enc_find_channel_position_in_vorbis_order:<opusenc4> Channel position 6 is not representable in Vorbis order May 03 19:48:20 TheBox systemd-wolf[215457]: 0:56:03.827519328 1 0x720bec003110 WARN opusenc gstopusenc.c:510:gst_opus_enc_find_channel_position_in_vorbis_order:<opusenc4> Channel position 7 is not representable in Vorbis order My takeaway from asking Claude AI, some issue where the mapping of channels for 7.1/5.1 surround occurs in the opus encoder in Gstreamer? If I change the the default_audio_params in config.toml to : [gstreamer.audio] default_audio_params = 'queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert ! audioresample ! audio/x-raw,channels=6,channel-mask=(bitmask)0x3f' It seems to work with 5.1 for the client.
Author
Owner

@ABeltramo commented on GitHub (May 4, 2025):

Thanks for all the details, ideally we should update the producer here github.com/games-on-whales/wolf@1a6327d6e2/src/moonlight-server/streaming/streaming.cpp (L133-L140)

We already pass the channel count, so I guess the only thing missing from your changes is channel-mask=(bitmask)0x3f which I'm not sure what it means. I wonder if this is some recent change in Gstreamer, from a quick look at the docs

channel-mask, GST_TYPE_BITMASK: Mandatory for more than 2 channels Bitmask of channel positions present. May be omitted for mono and stereo. May be set to 0 to denote that the channels are unpositioned.

I'll look into it..

<!-- gh-comment-id:2849085447 --> @ABeltramo commented on GitHub (May 4, 2025): Thanks for all the details, ideally we should update the producer here https://github.com/games-on-whales/wolf/blob/1a6327d6e251d808581b825edaf5ed81967ff3f0/src/moonlight-server/streaming/streaming.cpp#L133-L140 We already pass the channel count, so I guess the only thing missing from your changes is `channel-mask=(bitmask)0x3f` which I'm not sure what it means. I wonder if this is some recent change in Gstreamer, from a quick look at the [docs](https://gstreamer.freedesktop.org/documentation/additional/design/mediatype-audio-raw.html?gi-language=c) > **channel-mask**, GST_TYPE_BITMASK: Mandatory for more than 2 channels Bitmask of channel positions present. May be omitted for mono and stereo. May be set to 0 to denote that the channels are unpositioned. I'll look into it..
Author
Owner

@corsjune commented on GitHub (May 4, 2025):

I personally dont have much insights into it, but from the conversation with Claude Ai, the channel-mask is a binary pattern that references the channels defined here

https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/subprojects/gst-plugins-base/gst-libs/gst/audio/audio-channels.h?ref_type=heads

Here is the entire AI convo from start shared..

https://claude.ai/share/fd607d07-aeb1-40b4-bac6-6c68fefe8b53

<!-- gh-comment-id:2849413311 --> @corsjune commented on GitHub (May 4, 2025): I personally dont have much insights into it, but from the conversation with Claude Ai, the channel-mask is a binary pattern that references the channels defined here https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/subprojects/gst-plugins-base/gst-libs/gst/audio/audio-channels.h?ref_type=heads Here is the entire AI convo from start shared.. https://claude.ai/share/fd607d07-aeb1-40b4-bac6-6c68fefe8b53
Author
Owner

@Gylfkxjyjdll commented on GitHub (Jun 10, 2025):

If you set „opusenc bitrate=1280000“ in the config.toml, you will get sound in 7.1. However, it is very metallic. I believe the second problem then has something to do with sampling.

edit: never mind. its not reproducible

<!-- gh-comment-id:2959246262 --> @Gylfkxjyjdll commented on GitHub (Jun 10, 2025): If you set „opusenc bitrate=1280000“ in the config.toml, you will get sound in 7.1. However, it is very metallic. I believe the second problem then has something to do with sampling. edit: never mind. its not reproducible
Author
Owner

@rkkoszewski commented on GitHub (Aug 13, 2025):

Alright I did some tests, and for me too the "default_audio_params = 'queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert ! audioresample ! audio/x-raw,channels=6,channel-mask=(bitmask)0x3f'" has improved the 5.1 output a lot. The artifacts and ducking/loudness is gone. The LFE, left, center and right speaker works also perfect, but the rear speakers are not working for me (But this might be related to the speaker layout set on my PC, will need more testing with this). I tried setting the back speakers to be the side speakers instead of the back speakers (In case this was the issue), but that just brought back the artifacts and all the previous issues and didn't fix the rear speakers not working. I will test with another Sound Card and I'll report back in a moment.

In the meantime here is a quick GStreamer Mask Calculator that I built and can be found here: https://gstreamerchannelmaskcalculator.static.domains/

EDIT: Tested with another Audio Card (Creative X-Fi 5.1), this time plugging in headphones into the output, and I have the same but more detailed results. So Center works fine, Front left appears in the physical Front right speaker. Nothing comes out in the Front right appears in both of the physical rear speakers, and with the headphones I noticed that the LFE speaker has the same distortion and high frequency hissing, which was not audible in my physical subwoffer as that speaker was filtering out high frequencies.

THOUGHTS: Could the issue be in the OPUS encoder side? Perhaps the "layout, G_TYPE_STRING: Mandatory. The layout of channels within a buffer. Possible values are "interleaved" (for LRLRLRLR) and "non-interleaved" (LLLLRRRR)" needs to also be specified to match what the OPUS encoder expects.

EDIT 2:
Perhaps we could make use of the "gst_audio_channel_get_fallback_mask" which as per the documentation "This function returns a reasonable fallback channel-mask and should be called as a last resort when the specific channel map is unknown." https://gstreamer.freedesktop.org/documentation/audio/gstaudiochannels.html?gi-language=c

<!-- gh-comment-id:3185478648 --> @rkkoszewski commented on GitHub (Aug 13, 2025): Alright I did some tests, and for me too the "default_audio_params = 'queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert ! audioresample ! audio/x-raw,channels=6,channel-mask=(bitmask)0x3f'" has improved the 5.1 output a lot. The artifacts and ducking/loudness is gone. The LFE, left, center and right speaker works also perfect, but the rear speakers are not working for me (But this might be related to the speaker layout set on my PC, will need more testing with this). I tried setting the back speakers to be the side speakers instead of the back speakers (In case this was the issue), but that just brought back the artifacts and all the previous issues and didn't fix the rear speakers not working. I will test with another Sound Card and I'll report back in a moment. In the meantime here is a quick GStreamer Mask Calculator that I built and can be found here: https://gstreamerchannelmaskcalculator.static.domains/ EDIT: Tested with another Audio Card (Creative X-Fi 5.1), this time plugging in headphones into the output, and I have the same but more detailed results. So Center works fine, Front left appears in the physical Front right speaker. Nothing comes out in the Front right appears in both of the physical rear speakers, and with the headphones I noticed that the LFE speaker has the same distortion and high frequency hissing, which was not audible in my physical subwoffer as that speaker was filtering out high frequencies. THOUGHTS: Could the issue be in the OPUS encoder side? Perhaps the "layout, G_TYPE_STRING: Mandatory. The layout of channels within a buffer. Possible values are "interleaved" (for LRLRLRLR) and "non-interleaved" (LLLLRRRR)" needs to also be specified to match what the OPUS encoder expects. EDIT 2: Perhaps we could make use of the "gst_audio_channel_get_fallback_mask" which as per the documentation "This function returns a reasonable fallback channel-mask and should be called as a last resort when the specific channel map is unknown." https://gstreamer.freedesktop.org/documentation/audio/gstaudiochannels.html?gi-language=c
Author
Owner

@Gylfkxjyjdll commented on GitHub (Aug 24, 2025):

with this information i coud make 7.1 work
queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert ! resample !audio/x-raw,channels=8,channel-mask=(bitmask)0xc3f

but i have first to start moonlight with 5.1, and then change the settings to 7.1
if i start steam from moonlight direct with 7.1, i dont have any audio.

mask are from here: https://github.com/DolbyLaboratories/gst-home-audio

<!-- gh-comment-id:3218047914 --> @Gylfkxjyjdll commented on GitHub (Aug 24, 2025): with this information i coud make 7.1 work `queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert ! resample !audio/x-raw,channels=8,channel-mask=(bitmask)0xc3f` but i have first to start moonlight with 5.1, and then change the settings to 7.1 if i start steam from moonlight direct with 7.1, i dont have any audio. mask are from here: https://github.com/DolbyLaboratories/gst-home-audio
Author
Owner

@Gylfkxjyjdll commented on GitHub (Sep 14, 2025):

i think, there are several issues with the audio transcoding pipeline.
First one has to do with the initialization with the 7.1. but i wont focus here on this.

if we change the output to 'queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert ! audioresample ! audio/x-raw,channels=6,channel-mask=(bitmask)0x3f'" then the backspeaker are to quiet compared to to front speakers. maybe in the pipeline the back speakers get muted, so the next step was to find out, if a caps in the pipeline does this muting or if there is somewhere a different problem.

but befor this, i wanted to test the speakers with

gst-launch-1.0 audiotestsrc num-buffers=100 ! audio/x-raw,channels=6,rate=48000,format=S16LE ! autoaudiosink , if all speakers are equal loud.

without audio/x-raw,channels=6,channel-mask=(bitmask)0x3f'there is a sampling error, and because of this, there is this "deep hum" (sorry google translate, i dont know how to translate this word from german).
and another problem, i think is, that the channel layout from opus and the input signal are different.

https://datatracker.ietf.org/doc/html/rfc7845.html#section-5.1.1.2

6 channels: 5.1 surround (front left, front center, front right,
      rear left, rear right, LFE).

according to chatgpt, the default channel mapping from pulsewire is "FL,FR,FC,LFE,RL,RR"

So, i tried to map the channels manual:

[gstreamer.audio] default_audio_params = 'queue max-size-buffers=3 leaky=downstream ! audioconvert ! audioresample ! audio/x-raw,channels=6,channel-map="FL,FR,FC,LFE,RL,RR"! queue' default_opus_encoder = 'opusenc bitrate={bitrate} bitrate-type=cbr frame-size={packet_duration} bandwidth=fullband audio-type=restricted-lowdelay max-payload-size=1400' default_sink = '''rtpmoonlightpay_audio name=moonlight_pay packet_duration={packet_duration} encrypt={encrypt} aes_key="{aes_key}" aes_iv="{aes_iv}" ! appsink name=wolf_udp_sink''' default_source = 'interpipesrc listen-to={session_id}_audio is-live=true stream-sync=restart-ts max-bytes=0 max-buffers=3 block=false'
with this, i get the best ressult. but i got the problem, that when the audio is direct behind, sometimes you wont hear it.

is there a possibility to send the "raw pcm" or flac signal? i tried it with changing it in the config.xml but ended up with no audio.

next step is maybe to reduce the latency and cpu overhead in the transcoding pipeline.

<!-- gh-comment-id:3289378395 --> @Gylfkxjyjdll commented on GitHub (Sep 14, 2025): i think, there are several issues with the audio transcoding pipeline. First one has to do with the initialization with the 7.1. but i wont focus here on this. if we change the output to 'queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert ! audioresample ! audio/x-raw,channels=6,channel-mask=(bitmask)0x3f'" then the backspeaker are to quiet compared to to front speakers. maybe in the pipeline the back speakers get muted, so the next step was to find out, if a caps in the pipeline does this muting or if there is somewhere a different problem. but befor this, i wanted to test the speakers with `gst-launch-1.0 audiotestsrc num-buffers=100 ! audio/x-raw,channels=6,rate=48000,format=S16LE ! autoaudiosink` , if all speakers are equal loud. without `audio/x-raw,channels=6,channel-mask=(bitmask)0x3f'`there is a sampling error, and because of this, there is this "deep hum" (sorry google translate, i dont know how to translate this word from german). and another problem, i think is, that the channel layout from opus and the input signal are different. https://datatracker.ietf.org/doc/html/rfc7845.html#section-5.1.1.2 ``` 6 channels: 5.1 surround (front left, front center, front right, rear left, rear right, LFE). ``` according to chatgpt, the default channel mapping from pulsewire is "FL,FR,FC,LFE,RL,RR" So, i tried to map the channels manual: ` [gstreamer.audio] default_audio_params = 'queue max-size-buffers=3 leaky=downstream ! audioconvert ! audioresample ! audio/x-raw,channels=6,channel-map="FL,FR,FC,LFE,RL,RR"! queue' default_opus_encoder = 'opusenc bitrate={bitrate} bitrate-type=cbr frame-size={packet_duration} bandwidth=fullband audio-type=restricted-lowdelay max-payload-size=1400' default_sink = '''rtpmoonlightpay_audio name=moonlight_pay packet_duration={packet_duration} encrypt={encrypt} aes_key="{aes_key}" aes_iv="{aes_iv}" ! appsink name=wolf_udp_sink''' default_source = 'interpipesrc listen-to={session_id}_audio is-live=true stream-sync=restart-ts max-bytes=0 max-buffers=3 block=false' ` with this, i get the best ressult. but i got the problem, that when the audio is direct behind, sometimes you wont hear it. is there a possibility to send the "raw pcm" or flac signal? i tried it with changing it in the config.xml but ended up with no audio. next step is maybe to reduce the latency and cpu overhead in the transcoding pipeline.
Author
Owner

@rkkoszewski commented on GitHub (Sep 14, 2025):

Really nice findings @Gylfkxjyjdll !

The effect in the rear speakers that you are describing sound a lot like "phase cancellation" (2 audio of opposite phases that overlap each other and cancel each other out). I've also experienced some speaker channels overlapping in a single speaker when it keeping with 5.1. I'll experiment with your findings once I find some spare time.

The audio format limitation (OPUS) is a Moonlight/Nvidia stream limitation. I've seen discussions of having lossless audio or 5.1 AC3 audio support for Sunshine/Moonlight, and that it's currently not supported (Which as I understood was due to the Nvidia streaming protocol being designed for OPUS and other formats needing adjustments to the streaming protocol).

<!-- gh-comment-id:3289399669 --> @rkkoszewski commented on GitHub (Sep 14, 2025): Really nice findings @Gylfkxjyjdll ! The effect in the rear speakers that you are describing sound a lot like "phase cancellation" (2 audio of opposite phases that overlap each other and cancel each other out). I've also experienced some speaker channels overlapping in a single speaker when it keeping with 5.1. I'll experiment with your findings once I find some spare time. The audio format limitation (OPUS) is a Moonlight/Nvidia stream limitation. I've seen discussions of having lossless audio or 5.1 AC3 audio support for Sunshine/Moonlight, and that it's currently not supported (Which as I understood was due to the Nvidia streaming protocol being designed for OPUS and other formats needing adjustments to the streaming protocol).
Author
Owner

@ABeltramo commented on GitHub (Sep 14, 2025):

Thanks for all the details @Gylfkxjyjdll I think you are missing one other essential bit into the mix: PulseAudio.

We create virtual audio sinks on demand based on what Moonlight requests and so starting a pipeline in 5.1 and then changing just the moonlight setting to 7.1 will most likely not update the actual audio sink meaning that the running apps will see and use a 5.1 sink.. The actual configuration used by Wolf is the following:

github.com/games-on-whales/wolf@d2a5c35bf6/src/moonlight-server/state/data-structures.hpp (L169-L203)

Whilst for Moonlight we advertise the following:

github.com/games-on-whales/wolf@d2a5c35bf6/src/moonlight-server/rtsp/commands.hpp (L56-L81)

To make things more complicated I don't actually own a surround system, so this is how I've developed it originally 😅
Over time, I've added some little fixes here or there in that mapping depending on user reports, but I wonder now if this is also tied to different Moonlight clients interpreting these exchanged values differently..

<!-- gh-comment-id:3289831443 --> @ABeltramo commented on GitHub (Sep 14, 2025): Thanks for all the details @Gylfkxjyjdll I think you are missing one other essential bit into the mix: PulseAudio. We create virtual audio sinks on demand based on what Moonlight requests and so starting a pipeline in 5.1 and then changing just the moonlight setting to 7.1 will most likely not update the actual audio sink meaning that the running apps will see and use a 5.1 sink.. The actual configuration used by Wolf is the following: https://github.com/games-on-whales/wolf/blob/d2a5c35bf66374292745e00571fb91f2f995a8ab/src/moonlight-server/state/data-structures.hpp#L169-L203 Whilst for Moonlight we advertise the following: https://github.com/games-on-whales/wolf/blob/d2a5c35bf66374292745e00571fb91f2f995a8ab/src/moonlight-server/rtsp/commands.hpp#L56-L81 To make things more complicated I don't actually own a surround system, so [this is how I've developed it originally](https://abeltra.me/blog/virtual-surround/) 😅 Over time, I've added some little fixes here or there in that mapping depending on user reports, but I wonder now if this is also tied to different Moonlight clients interpreting these exchanged values differently..
Author
Owner

@Gylfkxjyjdll commented on GitHub (Sep 15, 2025):

After thinking about this, i think there are two separate problems.

  1. The Opus Encoding Pipeline. With the work-around doesn't explain the problem with "no audio direct from behind". As @rkkoszewski says "phase cancellation". But somehow i don't think so 🤷‍♂️
    Does the caps "audioconvert" and "audioresample" drops the channel mapping? I need to dive deeper into this.
    (layout=interleaved)

  2. As the Test shows, all speaker works as expected, even with the encoding Pipeline. So, the problem must be somewhere before? The pulse-audio/pipewire config? I will investigate the virtual sink next.

<!-- gh-comment-id:3290763183 --> @Gylfkxjyjdll commented on GitHub (Sep 15, 2025): After thinking about this, i think there are two separate problems. 1. The Opus Encoding Pipeline. With the work-around doesn't explain the problem with "no audio direct from behind". As @rkkoszewski says "phase cancellation". But somehow i don't think so 🤷‍♂️ Does the caps "audioconvert" and "audioresample" drops the channel mapping? I need to dive deeper into this. (layout=interleaved) 2. As the Test shows, all speaker works as expected, even with the encoding Pipeline. So, the problem must be somewhere before? The pulse-audio/pipewire config? I will investigate the virtual sink next.
Author
Owner

@Gylfkxjyjdll commented on GitHub (Sep 15, 2025):

okay, this is interesting:

root@14d56f51a2ce:~# pactl list source-outputs
Source Output #0
	Driver: protocol-native.c
	Owner Module: 0
	Client: 1
	Source: 1
	Sample Specification: s16le 6ch 48000Hz
	Channel Map: **front-left,front-left-of-center,front-center,front-right,front-right-of-center,rear-center**
	Format: pcm, format.sample_format = "\"s16le\""  format.rate = "48000"  format.channels = "6"  **format.channel_map = "\"front-left,front-left-of-center,front-center,front-right,front-right-of-center,rear-center\""**
	Corked: no
	Mute: no
	Volume: front-left: 65536 / 100% / 0.00 dB,   front-left-of-center: 65536 / 100% / 0.00 dB,   front-center: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB,   front-right-of-center: 65536 / 100% / 0.00 dB,   rear-center: 65536 / 100% / 0.00 dB
	        balance 0.00

it records 4 front speakers..

but the virtual device has the right channel mapping:

root@14d56f51a2ce:~# pactl list sources | grep -E 'Name:|Description:|Channel Map:|module:'
	Name: virtual_sink_13639488168020456786.monitor
	Description: Monitor of Null Output
	Channel Map: front-left,front-right, front

edit: i think i have to look into how the capture-sink is created. but tbh i dont know where to start =/
edit2: sunshine adds the channel_map to the audio_sink,.. i'll try this.
https://github.com/loki-47-6F-64/sunshine/blob/master/sunshine/platform/linux/audio.cpp

<!-- gh-comment-id:3292825935 --> @Gylfkxjyjdll commented on GitHub (Sep 15, 2025): okay, this is interesting: ``` root@14d56f51a2ce:~# pactl list source-outputs Source Output #0 Driver: protocol-native.c Owner Module: 0 Client: 1 Source: 1 Sample Specification: s16le 6ch 48000Hz Channel Map: **front-left,front-left-of-center,front-center,front-right,front-right-of-center,rear-center** Format: pcm, format.sample_format = "\"s16le\"" format.rate = "48000" format.channels = "6" **format.channel_map = "\"front-left,front-left-of-center,front-center,front-right,front-right-of-center,rear-center\""** Corked: no Mute: no Volume: front-left: 65536 / 100% / 0.00 dB, front-left-of-center: 65536 / 100% / 0.00 dB, front-center: 65536 / 100% / 0.00 dB, front-right: 65536 / 100% / 0.00 dB, front-right-of-center: 65536 / 100% / 0.00 dB, rear-center: 65536 / 100% / 0.00 dB balance 0.00 ``` it records 4 front speakers.. but the virtual device has the right channel mapping: ``` root@14d56f51a2ce:~# pactl list sources | grep -E 'Name:|Description:|Channel Map:|module:' Name: virtual_sink_13639488168020456786.monitor Description: Monitor of Null Output Channel Map: front-left,front-right, front ``` edit: i think i have to look into how the capture-sink is created. but tbh i dont know where to start =/ edit2: sunshine adds the channel_map to the audio_sink,.. i'll try this. https://github.com/loki-47-6F-64/sunshine/blob/master/sunshine/platform/linux/audio.cpp
Author
Owner

@Gylfkxjyjdll commented on GitHub (Sep 17, 2025):

okay i hardcoded

void start_audio_producer(std::size_t session_id,
                          const std::shared_ptr<events::EventBusType> &event_bus,
                          int channel_count,
                          const std::string &sink_name,
                          const std::string &server_name) {
  auto pipeline = fmt::format("pulsesrc device=\"{sink_name}\" server=\"{server_name}\" ! " //
                              "audio/x-raw, channels=6,channel-mask=(bitmask)0x3f, rate=48000 ! "             //
                              "queue leaky=downstream max-size-buffers=3 ! "                //
                              "interpipesink name=\"{session_id}_audio\" sync=true async=false max-buffers=3",
                              fmt::arg("session_id", session_id),
                              fmt::arg("channels", channel_count),
                              fmt::arg("sink_name", sink_name),
                              fmt::arg("server_name", server_name));
  logs::log(logs::debug, "[GSTREAMER] Starting audio producer: {}", pipeline);

and rebuild and

root@cdd46bb9cfe5:~# pactl list source-outputs
Source Output #0
	Driver: protocol-native.c
	Owner Module: 0
	Client: 1
	Source: 1
	Sample Specification: s16le 6ch 48000Hz
	Channel Map: front-left,front-right,front-center,lfe,rear-left,rear-right
	Format: pcm, format.sample_format = "\"s16le\""  format.rate = "48000"  format.channels = "6"  format.channel_map = "\"front-left,front-right,front-center,lfe,rear-left,rear-right\""
	Corked: no
	Mute: no
	Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB,   front-center: 65536 / 100% / 0.00 dB,   lfe: 65536 / 100% / 0.00 dB,   rear-left: 65536 / 100% / 0.00 dB,   rear-right: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 0 usec
	Source Latency: 0 usec
	Resample method: n/a
	Properties:
		media.name = "Record Stream"
		application.name = "wolf"
		native-protocol.peer = "UNIX socket client"
		native-protocol.version = "35"
		application.process.id = "1"
		application.process.user = "root"
		application.process.host = "archimonde"
		application.process.binary = "wolf"
		application.language = "C"
		application.process.machine_id = "4a76e9c58bab47708371572456149530"

and looks like 5.1 sound is correct. will try with 7.1

edit:

void start_audio_producer(std::size_t session_id,
                          const std::shared_ptr<events::EventBusType> &event_bus,
                          int channel_count,
                          const std::string &sink_name,
                          const std::string &server_name) {
  auto pipeline = fmt::format("pulsesrc device=\"{sink_name}\" server=\"{server_name}\" ! " //
                              "audio/x-raw, channels=8,channel-mask=(bitmask)0xc3f, rate=48000 ! "             //
                              "queue leaky=downstream max-size-buffers=3 ! "                //
                              "interpipesink name=\"{session_id}_audio\" sync=true async=false max-buffers=3",
                              fmt::arg("session_id", session_id),
                              fmt::arg("channels", channel_count),
                              fmt::arg("sink_name", sink_name),
                              fmt::arg("server_name", server_name));
  logs::log(logs::debug, "[GSTREAMER] Starting audio producer: {}", pipeline);

7.1 works too 😁 but will testing a bit

<!-- gh-comment-id:3303518706 --> @Gylfkxjyjdll commented on GitHub (Sep 17, 2025): okay i hardcoded ``` void start_audio_producer(std::size_t session_id, const std::shared_ptr<events::EventBusType> &event_bus, int channel_count, const std::string &sink_name, const std::string &server_name) { auto pipeline = fmt::format("pulsesrc device=\"{sink_name}\" server=\"{server_name}\" ! " // "audio/x-raw, channels=6,channel-mask=(bitmask)0x3f, rate=48000 ! " // "queue leaky=downstream max-size-buffers=3 ! " // "interpipesink name=\"{session_id}_audio\" sync=true async=false max-buffers=3", fmt::arg("session_id", session_id), fmt::arg("channels", channel_count), fmt::arg("sink_name", sink_name), fmt::arg("server_name", server_name)); logs::log(logs::debug, "[GSTREAMER] Starting audio producer: {}", pipeline); ``` and rebuild and ``` root@cdd46bb9cfe5:~# pactl list source-outputs Source Output #0 Driver: protocol-native.c Owner Module: 0 Client: 1 Source: 1 Sample Specification: s16le 6ch 48000Hz Channel Map: front-left,front-right,front-center,lfe,rear-left,rear-right Format: pcm, format.sample_format = "\"s16le\"" format.rate = "48000" format.channels = "6" format.channel_map = "\"front-left,front-right,front-center,lfe,rear-left,rear-right\"" Corked: no Mute: no Volume: front-left: 65536 / 100% / 0.00 dB, front-right: 65536 / 100% / 0.00 dB, front-center: 65536 / 100% / 0.00 dB, lfe: 65536 / 100% / 0.00 dB, rear-left: 65536 / 100% / 0.00 dB, rear-right: 65536 / 100% / 0.00 dB balance 0.00 Buffer Latency: 0 usec Source Latency: 0 usec Resample method: n/a Properties: media.name = "Record Stream" application.name = "wolf" native-protocol.peer = "UNIX socket client" native-protocol.version = "35" application.process.id = "1" application.process.user = "root" application.process.host = "archimonde" application.process.binary = "wolf" application.language = "C" application.process.machine_id = "4a76e9c58bab47708371572456149530" ``` and looks like 5.1 sound is correct. will try with 7.1 edit: ``` void start_audio_producer(std::size_t session_id, const std::shared_ptr<events::EventBusType> &event_bus, int channel_count, const std::string &sink_name, const std::string &server_name) { auto pipeline = fmt::format("pulsesrc device=\"{sink_name}\" server=\"{server_name}\" ! " // "audio/x-raw, channels=8,channel-mask=(bitmask)0xc3f, rate=48000 ! " // "queue leaky=downstream max-size-buffers=3 ! " // "interpipesink name=\"{session_id}_audio\" sync=true async=false max-buffers=3", fmt::arg("session_id", session_id), fmt::arg("channels", channel_count), fmt::arg("sink_name", sink_name), fmt::arg("server_name", server_name)); logs::log(logs::debug, "[GSTREAMER] Starting audio producer: {}", pipeline); ``` 7.1 works too 😁 but will testing a bit
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/wolf#130
No description provided.