Skip to content

local audio: allow to select bitrate/depth from gui#3738

Closed
vingerha wants to merge 1 commit into
music-assistant:devfrom
vingerha:local-audio-allow_rate/depth-select
Closed

local audio: allow to select bitrate/depth from gui#3738
vingerha wants to merge 1 commit into
music-assistant:devfrom
vingerha:local-audio-allow_rate/depth-select

Conversation

@vingerha

@vingerha vingerha commented Apr 19, 2026

Copy link
Copy Markdown

background/context:
I would like to stream locallly via HDMI, which is connected to my (Denon) receiver, from my ubuntu laptop 24.04
There is a mismatch between what MASS sends out and what HDMI handles, i.e. 44.1k vs. 48k. There are manual workarounds but they require docker volumes/updates and a lot of knowledge, not for the ordinary user.
This PR proposes to be able to select the bitrate and bitdepth via the GUI, in line with other providers.
Notes:

  • although it works for me, it may lack things (see below)
  • aside the rate/depth, maybe the buffer needs to be addressed too, let me know

Disclaimer: I lack an overall architectural view of MASS so this may be out of tune :)

image

@vingerha

Copy link
Copy Markdown
Author

PS, no clue how I can set the label

@marcelveldt

Copy link
Copy Markdown
Member

First of all great to see you getting involved with the codebase, thanks!
Let's see if there is still a need for this PR after this PR is merged: #3724

Comment on lines +918 to +919
if self.player_id.startswith(BRIDGE_PREFIX):
entries.append(create_sample_rates_config_entry(max_sample_rate=192000, max_bit_depth=24))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This config entry should not be needed because Sendspin has a different way of handling this.
The sample rate config entry basically only exists for HTTP based players

@vingerha vingerha Apr 23, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After spending a bit more time on 3724, I believe I now understand this comment.... but kindly confirm.
In case of local_audio using sendpin, the sample_rates has to come from the device at the moment of registration. If this is true then it is quite a challenge to not oversample all the time. Example: my HDMI can go from 48k to 192k and I would then 'hard'-config my device at 192k so I can benefit if/where needed (ignoring the audibility topic :) ). My idea(l) approach would then be to retrieve the capabilities of the hdmi device (e.g. allowed_rates in pipewire.conf) and then match that with the source (file) rate, get the closest match, and stream with that 'matched' rate.
If this is the direction it should be heading then I will close this PR ... any further chat we could do on discord if/where needed :)

EDIT: just realised that I have only been looking at pulse and alsa on my ubuntu 24.04 so far but if the OS is mac or windows or ?? android ?? ...what then? Does that require windows/macos-specific integration then alike 3724?
EDIT2: it is not easy to get the (OS configured) supported rates from the devices, and this again goes in favor of allowing the local_audio devices to be configured in MA.... but I do (!) admit (!) that I am still learning so maybe I miss things :)

@vingerha vingerha Apr 26, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding, I played around a bit as to come to a solution mathcinh device-supported rates vs. source (file) rate.
My laptop has :

  • analog audio, currently limited to 48k (pw setting)
  • hdmi , 48k > 192k
  • usb to dac, up to 768k
    Step 1, and this also related to this PR, detect capabilites
    A bit (well) of code changes in the 3724 pulse stuff (which is fixed at 48k), and it can detect all these devices and use them when streaming. ...not without issues though and I am questioning (you) where to add limits....i.e. add limits even if the hardware can go beyond. Should MA have a max-rate or should it be limited by the settings in pw/alsa or should it be a configuratle option in sendpsin (although you stated this is not the right type of device (no http)

@marcelveldt marcelveldt marked this pull request as draft April 19, 2026 22:39
@marcelveldt

Copy link
Copy Markdown
Member

Marking as draft so we can first see if #3724 already handles this

@iVolt1

iVolt1 commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

First of all great to see you getting involved with the codebase, thanks! Let's see if there is still a need for this PR after this PR is merged: #3724

It seems to work here with PR #3724 on HDMI as expected and sounds fine. The modifications to /etc/pulse/daemon.conf may need to be reapplied when rebooting or the hassio_audio container is restarted in order to have the higher sample rate and bit depth. I don't if/when persistent daemon.conf settings will be possible.

image

@vingerha

vingerha commented Apr 20, 2026

Copy link
Copy Markdown
Author

Marking as draft so we can first see if #3724 already handles this

"This' as bing able to properly stream to HDMI in general,or ?
...note that my PR is able to stream to alsa devices, no additional software is being introduced as this was my goal.
Atm I am a bit unsure how alsa/pulse/pipe work on quality. A search on the net states alsa to be best also for keeping the proper channels but not sure what 'best' means in real life :)

EDIT: I will await your feedback whether or not I should continue with above suggestion and further testing

@vingerha

vingerha commented Apr 20, 2026

Copy link
Copy Markdown
Author

@marcelveldt
A bit of further investigation into pipewire learns that it is interesting to not fully block the port.
I did a quick test, installed libasound2-plugins in the container and added this to its config

  -v /run/user/1000/pulse:/run/user/1000/pulse \
  -e PULSE_SERVER=unix:/run/user/1000/pulse/native \

And with that I see the pulse/pipe devices of my laptop, I can (with this PR) modify the rate/depth and play nicely too
Repeating that I am not a specialist but it seemed rather simple to add

@vingerha

Copy link
Copy Markdown
Author

First of all great to see you getting involved with the codebase, thanks! Let's see if there is still a need for this PR after this PR is merged: #3724

It seems to work here with PR #3724 on HDMI as expected and sounds fine. The modifications to /etc/pulse/daemon.conf may need to be reapplied when rebooting or the hassio_audio container is restarted in order to have the higher sample rate and bit depth. I don't if/when persistent daemon.conf settings will be possible.

Hi, I may have misread your comment, did you add (part of) my PR to yours and tested that? I ran your PR (container-installed pulseaudio-utils) and this seems fixed to 48k/32b.

@iVolt1

iVolt1 commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

First of all great to see you getting involved with the codebase, thanks! Let's see if there is still a need for this PR after this PR is merged: #3724

It seems to work here with PR #3724 on HDMI as expected and sounds fine. The modifications to /etc/pulse/daemon.conf may need to be reapplied when rebooting or the hassio_audio container is restarted in order to have the higher sample rate and bit depth. I don't if/when persistent daemon.conf settings will be possible.

Hi, I may have misread your comment, did you add (part of) my PR to yours and tested that? I ran your PR (container-installed pulseaudio-utils) and this seems fixed to 48k/32b.

I did not add anything from your PR to PR #3724. PR #3724 alters the local_audio provider so that it finds all pulse audio sinks and creates sendspin players for them. The current local_audio provider only creates a sink only for the default pulse audio sink chosen in the MA addon/app configuration. The idea is that sendspin sinks are created automatically on the pulse audio level which is built into MA and does not require any additional user configuration. I would rather not be configuring things at the alsa level if possible. This approach should continue to work even if HA audio eventually moves to pipewire.

Altering /etc/pulse/daemon.conf in the hassio-audio container is all that is needed get at least a 96000 sample rate and 32 bit format where supported by the DAC. I have used a wide variety of DACs and they all are able to obtain their best sample rate and bit depth with the daemon.conf configuration. Eventually there will be a way to keep these conguration changes persistent across container restarts.

default-sample-format = s32le
default-sample-rate = 96000
; alternate-sample-rate = 48000

hassio-audio:/# pactl list sinks short
0 alsa_output.usb-AudioQuest_AudioQuest_DragonFly_Black_v1.5_AQDFBL0120005724-00.analog-stereo module-alsa-card.c s24le 2ch 96000Hz RUNNING
1 alsa_output.pci-0000_03_00.0.analog-surround-71 module-alsa-card.c s32le 8ch 96000Hz RUNNING
2 alsa_output.usb-C-Media_Electronics_Inc._USB2.0_High-Speed_True_HD_Audio-00.iec958-stereo module-alsa-card.c s32le 2ch 96000Hz RUNNING
3 alsa_output.usb-0d8c_Generic_USB_Audio_Device-00.iec958-stereo module-alsa-card.c s16le 2ch 48000Hz RUNNING
4 alsa_output.pci-0000_07_00.6.iec958-stereo module-alsa-card.c s32le 2ch 96000Hz RUNNING
38 AudioQuest_DragonFly_Black_v15_front_stereo module-remap-sink.c s24le 2ch 96000Hz IDLE
39 Creative_X_Fi_rear_stereo module-remap-sink.c s32le 2ch 96000Hz RUNNING
40 Creative_X_Fi_side_stereo module-remap-sink.c s32le 2ch 96000Hz RUNNING
41 Creative_X_Fi_front_stereo module-remap-sink.c s32le 2ch 96000Hz IDLE
42 Creative_X_Fi_center_sub module-remap-sink.c s32le 2ch 96000Hz IDLE
43 USB20_High_Speed_True_HD_Audio_iec958_stereo module-remap-sink.c s32le 2ch 96000Hz IDLE
44 Generic_USB_Audio_Device_iec958_stereo module-remap-sink.c s16le 2ch 48000Hz IDLE
45 HD_Audio_Generic_iec958_stereo module-remap-sink.c s32le 2ch 96000Hz IDLE
hassio-audio:/#

Does this answer your question or provide the solution you were looking for?

@vingerha

Copy link
Copy Markdown
Author

I did not add anything from your PR to PR #3724. PR #3724 alters the local_audio provider so that it finds all pulse audio sinks and creates sendspin players for them. The current local_audio provider only creates a sink only for the default pulse audio sink chosen in the MA addon/app configuration. The idea is that sendspin sinks are created automatically on the pulse audio level which is built into MA and does not require any additional user configuration. I would rather not be configuring things at the alsa level if possible. This approach should continue to work even if HA audio eventually moves to pipewire.

Altering /etc/pulse/daemon.conf in the hassio-audio container is all that is needed get at least a 96000 sample rate and 32 bit format where supported by the DAC. I have used a wide variety of DACs and they all are able to obtain their best sample rate and bit depth with the daemon.conf configuration. Eventually there will be a way to keep these conguration changes persistent across container restarts.

OK, thanks so from what I read it is a fixed rate ... and that is exactly what my PR tries to change, I have local audio from 32k mp3 to beyond 192k and I would like to play these at-a minimum at their original rate, limited only by the HDMI device rate. To be able to select the device capabilitities is a must imo, there will be devices that can only handle 44.1 and others that can go way beyond and the user should be able to decide. Note that I do not want to enter in discussions whether or not this is audible, that is a whole different rabbit hole and not my point :).
All in all your PR works, aside the fixed rate it however only shows one pulse device where my PR shows a few more (using libasound2-plugins)...minor thing ...just as fyi

So, I may need re-do my PR after yours goes live (unless you add gui-level rate-selection too ??), and only when I know/understand what MASS is aiming to support :)

@iVolt1

iVolt1 commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Rather than a fixed sample rate pulse audio setting, I would say it is more of a maximum fixed rate and pulse audio from what I have seen far will pick the best sample rate a DAC supports up to the rate configured in a pulse audio conf. I changed the config to handle handle 192k sample rates and it works and I can hear audio with the exception of  '32      HD_Audio_Generic_iec958_stereo  module-remap-sink.c     s32le 2ch 192000Hz      IDLE' which is attached to an oldish Yamaha soundbar that can only handle up to 96k sample rate.  96k sample rate is good enough for me and most people and it does upconvert 44100 with less degradation than the HA pulse audio 48k sample rate default.

Maybe my PR will do what you are looking for or your PR may add something new. Perhaps with persistent HA pulse audio configurations, per output sample rate and bit depth could be specified. This would help with my Yamaha soundbar 96k sample rate limitation.

 default-sample-format = s32le
 default-sample-rate = 192000
; alternate-sample-rate = 48000
; default-sample-channels = 2
; default-channel-map = front-left,front-right

; default-fragments = 4
; default-fragment-size-msec = 25

; enable-deferred-volume = yes
; deferred-volume-safety-margin-usec = 8000
; deferred-volume-extra-delay-usec = 0
hassio-audio:/# exit
exit
➜  ~ pactl list sinks short
0       alsa_output.usb-AudioQuest_AudioQuest_DragonFly_Black_v1.5_AQDFBL0120005724-00.analog-stereo    module-alsa-card.c      s24le 2ch 96000Hz       RUNNING
1       alsa_output.pci-0000_03_00.0.analog-surround-71 module-alsa-card.c      s32le 8ch 192000Hz      RUNNING
2       alsa_output.usb-C-Media_Electronics_Inc._USB2.0_High-Speed_True_HD_Audio-00.iec958-stereo       module-alsa-card.c      s32le 2ch 192000Hz      RUNNING
3       alsa_output.usb-0d8c_Generic_USB_Audio_Device-00.iec958-stereo  module-alsa-card.c      s16le 2ch 48000Hz       RUNNING
4       alsa_output.pci-0000_07_00.6.iec958-stereo      module-alsa-card.c      s32le 2ch 192000Hz      RUNNING
33      AudioQuest_DragonFly_Black_v15_front_stereo     module-remap-sink.c     s24le 2ch 96000Hz       IDLE
34      Creative_X_Fi_rear_stereo       module-remap-sink.c     s32le 2ch 192000Hz      RUNNING
35      Creative_X_Fi_side_stereo       module-remap-sink.c     s32le 2ch 192000Hz      RUNNING
36      Creative_X_Fi_front_stereo      module-remap-sink.c     s32le 2ch 192000Hz      RUNNING
37      Creative_X_Fi_center_sub        module-remap-sink.c     s32le 2ch 192000Hz      RUNNING
38      USB20_High_Speed_True_HD_Audio_iec958_stereo    module-remap-sink.c     s32le 2ch 192000Hz      IDLE
39      Generic_USB_Audio_Device_iec958_stereo  module-remap-sink.c     s16le 2ch 48000Hz       IDLE
40      HD_Audio_Generic_iec958_stereo  module-remap-sink.c     s32le 2ch 192000Hz      RUNNING
➜  ~ 
image

@vingerha

Copy link
Copy Markdown
Author

Rather than a fixed sample rate pulse audio setting, I would say it is more of a maximum fixed rate and pulse audio from what I have seen far will pick the best sample rate a DAC supports up to the rate configured in a pulse audio conf. I changed the config to handle handle 192k sample rates and it works and I can hear audio with the exception of  '32      HD_Audio_Generic_iec958_stereo  module-remap-sink.c     s32le 2ch 192000Hz      IDLE' which is attached to an oldish Yamaha soundbar that can only handle up to 96k sample rate.  96k sample rate is good enough for me and most people and it does upconvert 44100 with less degradation than the HA pulse audio 48k sample rate default.

Maybe my PR will do what you are looking for or your PR may add something new. Perhaps with persistent HA pulse audio configurations, per output sample rate and bit depth could be specified. This would help with my Yamaha soundbar 96k sample rate limitation.

Do note my last comment, there should not be a discussion on what you or me or anyone else thinks is 'good enough'. Any solution limiting the user's choice based on opinions, especially when there are more options, is not good ... by default. If the device can play hihger rates and if the user wants/believes/dreams/etc. to need that, then why not? The only limitations I understand is when MASS has architectural limits, e.g. streaming to MPD is limited to mp3 due to the continuous stream setup.

I will try to see tomorrow how I can make by system pick a best rate.

Final comment, the ideal setup is not the best rate of the device but the next-best-rate based on the source. E.g. if 32k mp3 is played then no need to upsample to 192k if that is the best rate the device can handle... this is a different challenge though. .... and with that, my PR has more issues to tackle :)

@vingerha

Copy link
Copy Markdown
Author

cancelling as deviates too much from the required non-manually-configured setup

@vingerha vingerha closed this Apr 30, 2026
@vingerha vingerha deleted the local-audio-allow_rate/depth-select branch April 30, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants