Documentation and policy for custom ALSA configurations (user or plugin)

Hi

Could Volumio’s use of ALSA in Volumio 3 please be documented for people who wish to use custom configurations. Also, if it is not possible to stop ALSA customisations from plugins overwriting or excluding other ALSA customisations then could there please be a documented policy for how a well-behaved plugin (or user customisation) should avoid this.

Thanks

Adrian.

1 Like

Could Volumio’s use of ALSA in Volumio 3 please be documented for people who wish to use custom configurations.

This is on the list of things to do before the changes go out in beta.

Hi timothyjward

That is great! Thanks for letting me know.

Adrian.

The main plugin changes in Volumio 3 are now documented. There are lifecycle changes and ALSA contribution changes

1 Like

Thanks for the heads up and links!

Adrian.

Was this resolved?
Copilot suggests creating a custom ALSA config file in :
/data/alsa/user-asound.conf

However the sheer confidence in Copilot’s suggestion is not matched with any change. I have tried to create a custom downsampling of only 192kHz and 176.4Khz files to their 96 and 88.2 kHz equivalents (leaving lower sampling rate files to pass through at native spec) but has not worked.

Not sure if it is the file location or just a Copilot hallucination.

This was the suggested ALSA config

# ============================================================
# Conditional resampling for Volumio (HiFiBerry Digi+ Pro)
# Card 2, Device 0  →  hw:2,0
#
# - 44.1 → 44.1 (passthrough)
# - 88.2 → 88.2 (passthrough)
# - 176.4 → 88.2
# - 48 → 48 (passthrough)
# - 96 → 96 (passthrough)
# - 192 → 96
# ============================================================

pcm.!default volumio_conditional

pcm.volumio_conditional {
    type plug
    slave.pcm "family_selector"
}

pcm.family_selector {
    type route
    slave.pcm "rate_family_router"
}

pcm.rate_family_router {
    type plug
    slave.pcm {
        pcm "rate_family_logic"
        channels 2
    }
}

# ============================================================
# Passthrough devices
# ============================================================

pcm.rate_441_passthrough {
    type plug
    slave.pcm "hw:2,0"
}

pcm.rate_882_passthrough {
    type plug
    slave.pcm "hw:2,0"
}

pcm.rate_48_passthrough {
    type plug
    slave.pcm "hw:2,0"
}

pcm.rate_96_passthrough {
    type plug
    slave.pcm "hw:2,0"
}

# ============================================================
# Downsampling rules
# ============================================================

pcm.rate_1764_down {
    type plug
    slave.pcm {
        type rate
        slave {
            pcm "hw:2,0"
            rate 88200
        }
        converter "samplerate_best"
    }
}

pcm.rate_192_down {
    type plug
    slave.pcm {
        type rate
        slave {
            pcm "hw:2,0"
            rate 96000
        }
        converter "samplerate_best"
    }
}

# ============================================================
# Fallback resampler (for anything unexpected)
# ============================================================

pcm.final_resampler {
    type plug
    slave.pcm {
        type rate
        slave {
            pcm "hw:2,0"
            rate 96000
        }
        converter "samplerate_best"
    }
}

# ============================================================
# Conditional routing logic
# ============================================================

pcm.rate_family_logic {
    type route
    slave.pcm {
        @func concat
        strings [
            "rate_"
            {
                @func iif
                cond { @func compare values [ { @func sample_rate } 44100 ] }
                then "441_passthrough"
                else {
                    @func iif
                    cond { @func compare values [ { @func sample_rate } 48000 ] }
                    then "48_passthrough"
                    else {
                        @func iif
                        cond { @func compare values [ { @func sample_rate } 88200 ] }
                        then "882_passthrough"
                        else {
                            @func iif
                            cond { @func compare values [ { @func sample_rate } 96000 ] }
                            then "96_passthrough"
                            else {
                                @func iif
                                cond { @func compare values [ { @func sample_rate } 176400 ] }
                                then "1764_down"
                                else {
                                    @func iif
                                    cond { @func compare values [ { @func sample_rate } 192000 ] }
                                    then "192_down"
                                    else "final_resampler"
                                }
                            }
                        }
                    }
                }
            }
        ]
    }
}

I can confirm it is not the good way of doing this in volumio.
Search the how-to write a plugin,
I can’t tell you more now. .

I did search how to write this as a Volumio plugin and used Copilot to help write it and teach me how to install, but it did not work.

So it is beyond my skill set in computing.