diff --git a/docs/rst/daemon/configuration/alsa.rst b/docs/rst/daemon/configuration/alsa.rst index cf00019c..b310b2c1 100644 --- a/docs/rst/daemon/configuration/alsa.rst +++ b/docs/rst/daemon/configuration/alsa.rst @@ -3,384 +3,410 @@ ALSA configuration ================== -Modifying the default configuration -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +One of the components of WirePlumber is the ALSA monitor. This monitor is +responsible for creating PipeWire devices and nodes for all the ALSA cards that +are available on the system. It also manages the configuration of these devices. -ALSA devices are created and managed by the session manager with the *alsa.lua* -monitor script. In the default configuration, this script is loaded by -``wireplumber.conf.d/alsa.conf``, which also specifies its settings and -rules. +The ALSA monitor is enabled by default and can be disabled using the +``monitor.alsa`` :ref:`feature ` in the configuration file. -* *Settings* - - Example: - - .. code-block:: - - wireplumber.settings = { - alsa_monitor.alsa.jack-device = true - alsa_monitor.alsa.reserve = true - } - - The above example will configure the ALSA monitor to not enable the JACK - device, and do ALSA device reservation using the mentioned DBus interface. - - A list of valid settings are: - - .. code-block:: - - alsa_monitor.alsa.jack-device = true - - Creates a JACK device if set to ``true``. This is not enabled by default - because it requires that the PipeWire JACK replacement libraries are not used - by the session manager, in order to be able to connect to the real JACK - server. - - .. code-block:: - - alsa_monitor.alsa.reserve = true - - Reserve ALSA devices via *org.freedesktop.ReserveDevice1* on D-Bus. - - .. code-block:: - - alsa_monitor.alsa.reserve-priority = -20 - - The used ALSA device reservation priority. - - .. code-block:: - - alsa_monitor.alsa.reserve-application-name = WirePlumber - - The used ALSA device reservation application name. - - -* *rules* - - Example: - - .. code-block:: - - wireplumber.settings = { - alsa_monitor = [ - { - matches = [ - { - # This matches the needed sound card. - device.name = "" - } - ] - actions = { - update-props = { - # Apply all the desired device settings here. - api.alsa.use-acp = true - } - } - } - { - matches = [ - # This matches the needed node. - { - node.name = "" - } - ] - actions = { - # Apply all the desired node specific settings here. - update-props = { - node.nick = "My Node" - priority.driver = 100 - session.suspend-timeout-seconds = 5 - } - } - } - ] - } - -Device settings -^^^^^^^^^^^^^^^^^ - -All the possible settings that you can apply to devices and nodes of the -ALSA monitor are described here. - -PipeWire devices correspond to the ALSA cards. -The following settings can be configured on devices created by the monitor: - -.. code-block:: - - api.alsa.use-acp = true - -Use the ACP (alsa card profile) code to manage the device. This will probe the -device and configure the available profiles, ports and mixer settings. The -code to do this is taken directly from PulseAudio and provides devices that -look and feel exactly like the PulseAudio devices. - -.. code-block:: - - api.alsa.use-ucm = true - -By default, the UCM configuration is used when it is available for your device. -With this option you can disable this and use the ACP profiles instead. - -.. code-block:: - - api.alsa.soft-mixer = false - -Setting this option to true will disable the hardware mixer for volume control -and mute. All volume handling will then use software volume and mute, leaving -the hardware mixer untouched. The hardware mixer will still be used to mute -unused audio paths in the device. - -.. code-block:: - - api.alsa.ignore-dB = false - -Setting this option to true will ignore the decibel setting configured by the -driver. Use this when the driver reports wrong settings. - -.. code-block:: - - device.profile-set = "profileset-name" - -This option can be used to select a custom profile set name for the device. -Usually this is configured in Udev rules but it can also be specified here. - -.. code-block:: - - device.profile = "default profile name" - -The default active profile name. - -.. code-block:: - - api.acp.auto-profile = false - -Automatically select the best profile for the device. Normally this option is -disabled because the session manager will manage the profile of the device. -The session manager can save and load previously selected profiles. Enable -this if your session manager does not handle this feature. - -.. code-block:: - - api.acp.auto-port = false - -Automatically select the highest priority port that is available. This is by -default disabled because the session manager handles the task of selecting and -restoring ports. It can, for example, restore previously saved volumes. Enable -this here when the session manager does not handle port restore. - -.. code-block:: lua - - ["api.acp.probe-rate"] = 48000 - -Sets the samplerate used for probing the ALSA devices and collecting the profiles -and ports. - -.. code-block:: lua - - ["api.acp.pro-channels"] = 64 - -Sets the number of channels to use when probing the Pro Audio profile. Normally, -the maximum amount of channels will be used but with this setting this can be -reduced, which can make it possible to use other samplerates on some devices. - -Some of the other settings that might be configured on devices: - -.. code-block:: - - device.nick = "My Device", - device.description = "My Device" - -``device.description`` will show up in most apps when a device name is shown. - -Node Settings -^^^^^^^^^^^^^^^ - -Nodes are sinks or sources in the PipeWire graph. They correspond to the ALSA -devices. In addition to the generic stream node configuration options, there are -some alsa specific options as well: - -.. code-block:: - - priority.driver = 2000 - -This configures the node driver priority. Nodes with higher priority will be -used as a driver in the graph. Other nodes with lower priority will have to -resample to the driver node when they are joined in the same graph. The default -value is set based on some heuristics. - -.. code-block:: - - priority.session = 1200 - -This configures the priority of the node when selecting a default node. -Higher priority nodes will be more likely candidates as a default node. +The monitor, as with all device monitors, is implemented as a SPA plugin and is +part of PipeWire. WirePlumber merely loads the plugin and lets it do its work. +The plugin then monitors UDev and creates device and node objects for all the +ALSA cards that are available on the system. .. note:: - By default, sources have a ``priority.session`` value around 1600-2000 and - sinks have a value around 600-1000. If you are increasing the priority of a - sink, it is **not advised** to use a value higher than 1500, as it may cause - a sink's monitor to be selected as a default source. + One thing worth remembering here is that in ALSA, a "card" represents a + physical sound controller device, and a "device" is a logical access point + that represents a set of inputs and/or outputs that are part of the card. In + PipeWire, a "device" is the direct equivalent of an ALSA "card" and a "node" + is almost equivalent (close, but not quite) of an ALSA "device". + +Properties +---------- + +The ALSA monitor SPA plugin (``api.alsa.enum.udev``) supports properties that +can be used to configure it when it is loaded. These properties can be set in +the ``monitor.alsa.properties`` section of the WirePlumber configuration file. + +Example: .. code-block:: - node.pause-on-idle = false + monitor.alsa.properties = { + alsa.use-acp = true + } -Pause-on-idle will stop the node when nothing is linked to it anymore. -This is by default false because some devices cause a pop when they are -opened/closed. The node will, normally, pause and suspend after a timeout -(see suspend-node.lua). +.. describe:: alsa.use-acp + + A boolean that controls whether the ACP (alsa card profile) code is to be + the default manager of the device. This will probe the device and configure + the available profiles, ports and mixer settings. The code to do this is + taken directly from PulseAudio and provides devices that look and feel + exactly like the PulseAudio devices. + +Rules +----- + +When device and node objects are created by the ALSA monitor, they can be +configured using rules. These rules allow matching the existing properties of +these objects and updating them with new values. This is the main way of +configuring ALSA device settings. + +These rules can be set in the ``monitor.alsa.rules`` section of the WirePlumber +configuration file. + +Example: .. code-block:: - session.suspend-timeout-seconds = 5 -- 0 disables suspend + monitor.alsa.rules = [ + { + matches = [ + { + # This matches the value of the 'device.name' property of the device. + device.name = "~alsa_card.*" + } + ] + actions = { + update-props = { + # Apply all the desired device settings here. + api.alsa.use-acp = true + } + } + } + { + matches = [ + # This matches the value of the 'node.name' property of the node. + { + node.name = "~alsa_output.*" + } + ] + actions = { + # Apply all the desired node specific settings here. + update-props = { + node.nick = "My Node" + priority.driver = 100 + session.suspend-timeout-seconds = 5 + } + } + } + ] -This option configures a different suspend timeout on the node. -By default this is 5 seconds. For some devices (HiFi amplifiers, for example) -it might make sense to set a higher timeout because they might require some -time to restart after being idle. +Device properties +^^^^^^^^^^^^^^^^^ -A value of 0 disables suspend for a node and will leave the ALSA device busy. -The device can then manually be suspended with ``pactl suspend-sink|source``. +The following properties can be configured on devices created by the monitor: -**The following properties can be used to configure the format used by the -ALSA device:** +.. describe:: api.alsa.use-acp -.. code-block:: + Use the ACP (alsa card profile) code to manage this device. This will probe + the device and configure the available profiles, ports and mixer settings. + The code to do this is taken directly from PulseAudio and provides devices + that look and feel exactly like the PulseAudio devices. - audio.format = "S16LE" + :Default value: ``true`` + :Type: boolean -By default, PipeWire will use a 32 bits sample format but a different format -can be set here. +.. describe:: api.alsa.use-ucm -The Audio rate of a device can be set here: + When ACP is enabled and a UCM configuration is available for a device, by + default it is used instead of the ACP profiles. This option allows you to + disable this and use the ACP profiles instead. -.. code-block:: + This option does nothing if ``api.alsa.use-acp`` is set to ``false``. - audio.rate = 44100 + :Default value: ``true`` + :Type: boolean -By default, the ALSA device will be configured with the same samplerate as the -global graph. If this is not supported, or a custom values is set here, -resampling will be used to match the graph rate. +.. describe:: api.alsa.soft-mixer -.. code-block:: + Setting this option to ``true`` will disable the hardware mixer for volume + control and mute. All volume handling will then use software volume and mute, + leaving the hardware mixer untouched. The hardware mixer will still be used + to mute unused audio paths in the device. - audio.channels = 2 - audio.position = "FL,FR" + :Type: boolean -By default the channels and their position are determined by the selected -Device profile. You can override this setting here and optionally swap or -reconfigure the channel positions. +.. describe:: api.alsa.ignore-dB -.. code-block:: + Setting this option to ``true`` will ignore the decibel setting configured by + the driver. Use this when the driver reports wrong settings. - api.alsa.use-chmap = false + :Type: boolean -Use the channel map as reported by the driver. This is disabled by default -because it is often wrong and the ACP code handles this better. +.. describe:: device.profile-set -.. code-block:: + This option can be used to select a custom ACP profile-set name for the + device. This can be configured in UDev rules, but it can also be specified + here. The default is to use "default.conf". - api.alsa.disable-mmap = true + :Type: string -PipeWire will by default access the memory of the device using mmap. -This can be disabled and force the usage of the slower read and write access -modes in case the mmap support of the device is not working properly. +.. describe:: device.profile -.. code-block:: + The initial active profile name. The default is to start from the "Off" + profile and then let WirePlumber select the best profile based on its + policy. - channelmix.normalize = true + :Type: string -Makes sure that during such mixing & resampling original 0 dB level is -preserved, so nothing sounds wildly quieter/louder. +.. describe:: api.acp.auto-profile -.. code-block:: + Automatically select the best profile for the device. Normally this option is + disabled because WirePlumber will manage the profile of the device. + WirePlumber can save and load previously selected profiles. Enable this in + custom configurations where the relevant WirePlumber components are disabled. - channelmix.mix-lfe = true + :Type: boolean -Creates "center" channel for X.0 recordings from front stereo on X.1 setups and -pushes some low-frequency/bass from "center" from X.1 recordings into front -stereo on X.0 setups. +.. describe:: api.acp.auto-port -.. code-block:: + Automatically select the highest priority port that is available ("port" is a + PulseAudio/ACP term, the equivalent of a "Route" in PipeWire). This is by + default disabled because WirePlumber handles the task of selecting and + restoring Routes. Enable this in custom configurations where the relevant + WirePlumber components are disabled. - monitor.channel-volumes = false + :Type: boolean -By default, the volume of the sink/source does not influence the volume on the -monitor ports. Set this option to true to change this. PulseAudio has -inconsistent behaviour regarding this option, it applies channel-volumes only -when the sink/source is using software volumes. +.. describe:: api.acp.probe-rate + + Sets the samplerate used for probing the ALSA devices and collecting the + profiles and ports. + + :Type: integer + +.. describe:: api.acp.pro-channels + + Sets the number of channels to use when probing the "Pro Audio" profile. + Normally, the maximum amount of channels will be used but with this setting + this can be reduced, which can make it possible to use other samplerates on + some devices. + + :Type: integer + +Some of the other properties that can be configured on devices: + +.. describe:: device.nick + + A short name for the device. + +.. describe:: device.description + + A longer, user-friendly name of the device. This will show up in most + user interfaces as the device's name. + +Node properties +^^^^^^^^^^^^^^^ + +The following properties can be configured on nodes created by the monitor: + +.. describe:: priority.driver + + This configures the node driver priority. Nodes with higher priority will be + used as a driver in the graph. Other nodes with lower priority will have to + resample to the driver node when they are joined in the same graph. The + default value is set based on some heuristics. + + :Type: integer + +.. describe:: priority.session + + This configures the priority of the node when selecting a default node + (default sink/source as a link target for streams). Higher priority nodes + will be more likely candidates for becoming the default node. + + :Type: integer + + .. note:: + + By default, sources have a ``priority.session`` value around 1600-2000 and + sinks have a value around 600-1000. If you are increasing the priority of + a sink, it is **not advised** to use a value higher than 1500, as it may + cause a sink's monitor to be selected as the default source. + +.. describe:: node.pause-on-idle + + Pause the node when nothing is linked to it anymore. This is by default false + because some devices make a "pop" sound when they are opened/closed. + The node will normally pause and suspend after a timeout (see below). + + :Type: boolean + +.. describe:: session.suspend-timeout-seconds + + This option configures a different suspend timeout on the node. By default + this is ``5`` seconds. For some devices (HiFi amplifiers, for example) it + might make sense to set a higher timeout because they might require some time + to restart after being idle. + + A value of ``0`` disables suspend for a node and will leave the ALSA device + busy. The device can then be manually suspended with + ``pactl suspend-sink|source``. + + :Type: integer + +.. describe:: audio.format + + The sample format of the device. By default, PipeWire will use a 32 bits + sample format but a different format can be set here. + + :Type: string (``"S16LE"``, ``"S32LE"``, ``"F32LE"``, ...) + +.. describe:: audio.rate + + The sample rate of the device. By default, the ALSA device will be configured + with the same samplerate as the global graph. If this is not supported, or a + custom value is set here, resampling will be used to match the graph rate. + + :Type: integer + +.. describe:: audio.channels + + The number of channels of the device. By default the channels and their + position are determined by the selected device profile. You can override + this setting here. + + :Type: integer + +.. describe:: audio.position + + The position of the channels. By default the number of channels and their + position are determined by the selected device profile. You can override + this setting here and optionally swap or reconfigure the channel positions. + + :Type: array of strings (example: ``["FL", "FR", "LFE", "FC", "RL", "RR"]``) + +.. describe:: api.alsa.use-chmap + + Use the channel map as reported by the driver. This is disabled by default + because it is often wrong and the ACP code handles this better. + + :Type: boolean + +.. describe:: api.alsa.disable-mmap + + Disable the use of mmap for the ALSA device. By default, PipeWire will access + the memory of the device using mmap. This can be disabled and force the usage + of the slower read and write access modes, in case the mmap support of the + device is not working properly. + + :Type: boolean + +.. describe:: channelmix.normalize + + Normalize the channel volumes when mixing & resampling, making sure that the + original 0 dB level is preserved so that nothing sounds wildly + quieter/louder. This is disabled by default. + + :Type: boolean + +.. describe:: channelmix.mix-lfe + + Creates a "center" channel for X.0 recordings from the front stereo on X.1 + setups and pushes some low-frequency/bass from the "center" of X.1 recordings + into the front stereo on X.0 setups. This is disabled by default. + + :Type: boolean + +.. describe:: monitor.channel-volumes + + By default, the volume of the sink/source does not influence the volume on + the monitor ports. Set this option to true to change this. PulseAudio has + inconsistent behaviour regarding this option, it applies channel-volumes only + when the sink/source is using software volumes. + + :Type: boolean ALSA buffer properties -^^^^^^^^^^^^^^^^^^^^^^ +...................... -PipeWire uses a timer to consume and produce samples to/from ALSA devices. -After every timeout, it queries the device hardware pointers of the device and -uses this information to set a new timeout. See also this example program. +PipeWire by default uses a timer to consume and produce samples to/from ALSA +devices. After every timeout, it queries the hardware pointers of the device and +uses this information to set a new timeout. This works well for most devices, +but there is a class of devices, so called "batch" devices, that need extra +buffering and timing tweaks to work properly. This is because batch devices only +get their hardware pointers updated after each hardware interrupt. When the +hardware interrupt frequency and the timer frequency are aligned, it is possible +for the hardware pointers to be updated just after the timer has expired, +resulting in sometimes wrong timing information being returned by the query. In +contrast, non-batch devices get pointer updates independent of the interrupt. -By default, PipeWire handles ALSA batch devices differently from non-batch -devices. Batch devices only get their hardware pointers updated after each -hardware interrupt. Non-batch devices get updates independent of the interrupt. This means that for batch devices we need to set the interrupt at a sufficiently -high frequency (at the cost of CPU usage) while for non-batch devices we want to -set the interrupt frequency as low as possible (to save CPU). +high frequency, at the cost of CPU usage, while for non-batch devices we want to +set the interrupt frequency as low as possible to save CPU. For batch devices +we also need to take the extra buffering into account caused by the delayed +updates of the hardware pointers. -For batch devices we also need to take the extra buffering into account caused -by the delayed updates of the hardware pointers. +.. note:: -Most USB devices are batch devices and will be handled as such by PipeWire by -default. + Most USB devices are batch devices and will be handled as such by PipeWire by + default. There are 2 tunable parameters to control the buffering and timeouts in a -device +device: -.. code-block:: +.. describe:: api.alsa.period-size - api.alsa.period-size = 1024 + This sets the device interrupt to every period-size samples for non-batch + devices and to half of this for batch devices. For batch devices, the other + half of the period-size is used as extra buffering to compensate for the + delayed update. So, for batch devices, there is an additional period-size/2 + delay. It makes sense to lower the period-size for batch devices to reduce + this delay. -This sets the device interrupt to every period-size samples for non-batch -devices and to half of this for batch devices. For batch devices, the other -half of the period-size is used as extra buffering to compensate for the delayed -update. So, for batch devices, there is an additional period-size/2 delay. -It makes sense to lower the period-size for batch devices to reduce this delay. + :Type: integer (samples) -.. code-block:: +.. describe:: api.alsa.headroom - api.alsa.headroom = 0 + This adds extra delay between the hardware pointers and software pointers. + In most cases this can be set to 0. For very bad devices or emulated devices + (like in a VM) it might be necessary to increase the headroom value. + + :Type: integer (samples) + +.. describe:: api.alsa.period-num + + This configures the number of periods in the hardware buffer, which controls + its size. Note that this is multiplied by the period of the device to + determine the size, so for batch devices, the total buffer size is + effectively period-num * period-size/2. + + :Type: integer -This adds extra delay between the hardware pointers and software pointers. -In most cases this can be set to 0. For very bad devices or emulated devices -(like in a VM) it might be necessary to increase the headroom value. In summary, this is the overview of buffering and timings: +============== ============================================ ========================================== +Property Batch Non-Batch +============== ============================================ ========================================== +IRQ Frequency api.alsa.period-size/2 api.alsa.period-size +Extra Delay api.alsa.headroom + api.alsa.period-size/2 api.alsa.headroom +Buffer Size api.alsa.period-num * api.alsa.period-size/2 api.alsa.period-num * api.alsa.period-size +============== ============================================ ========================================== - ============== ========================================== ========= - Property Batch Non-Batch - ============== ========================================== ========= - IRQ Frequency api.alsa.period-size/2 api.alsa.period-size - Extra Delay api.alsa.headroom + api.alsa.period-size/2 api.alsa.headroom - ============== ========================================== ========= +Finally, it is possible to disable the batch device tweaks with: -It is possible to disable the batch device tweaks with: +.. describe:: api.alsa.disable-batch -.. code-block:: + This disables the batch device tweaks. It removes the extra delay added of + period-size/2 if the device can support this. For batch devices it is also a + good idea to lower the period-size (and increase the IRQ frequency) to get + smaller batch updates and lower latency. - api.alsa.disable-batch"] = true - -It removes the extra delay added of period-size/2 if the device can support this. -For batch devices it is also a good idea to lower the period-size -(and increase the IRQ frequency) to get smaller batch updates and lower latency. + :Type: boolean ALSA extra latency properties -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +............................. Extra internal delay in the DAC and ADC converters of the device itself can be set with the ``latency.internal.*`` properties: .. code-block:: - latency.internal.rate"] = 256 - latency.internal.ns"] = 0 + latency.internal.rate = 256 + latency.internal.ns = 0 You can configure a latency in samples (relative to rate with ``latency.internal.rate``) or in nanoseconds (``latency.internal.ns``). @@ -419,44 +445,28 @@ Set the internal latency to 256 samples: remote 0 port 76 changed Startup tweaks -^^^^^^^^^^^^^^ +.............. -Some devices need some time before they can report accurate hardware pointer -positions. In those cases, an extra start delay can be added that is used to -compensate for this startup delay: +.. describe:: api.alsa.start-delay -.. code-block:: + Some devices need some time before they can report accurate hardware pointer + positions. In those cases, an extra start delay can be added to compensate + for this startup delay. This sets the startup delay in samples. The default + is 0. - ["api.alsa.start-delay"] = 0 - -It is unsure when this tunable should be used. + :Type: integer (samples) IEC958 (S/PDIF) passthrough -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +........................... -S/PDIF passthrough will only be enabled when the accepted codecs are configured -on the ALSA device. +.. describe:: iec958.codecs -This can be done in 3 different ways: + S/PDIF passthrough will only be enabled when the accepted codecs are configured + on the ALSA device. This can be done by setting the list of supported codecs + on this property. - 1. Use pavucontrol and toggle the codecs in the output advanced section. + Note that it is possible to also configure this property at runtime, either + with tools like pavucontrol or with the ``pw-cli`` tool, like this: + ``pw-cli s Props '{ iec958Codecs : [ PCM ] }'`` - 2. Modify the ``["iec958.codecs"]`` node property to contain supported codecs. - - Example ``~/.config/wireplumber/main.lua.d/51-alsa-spdif.lua``: - - .. code-block:: lua - - table.insert (alsa_monitor.rules, { - matches = { - { - { "node.name", "matches", "alsa_output.*" }, - }, - }, - apply_properties = { - ["iec958.codecs"] = "[ PCM DTS AC3 EAC3 TrueHD DTS-HD ]", - } - }) - - 3. Use ``pw-cli s Props '{ iec958Codecs : [ PCM ] }'`` to modify - the codecs at runtime. + :Type: array of strings (example: ``[ "PCM", "DTS", "AC3", "EAC3", "TrueHD", "DTS-HD" ]``) diff --git a/src/config/wireplumber.conf.d.examples/alsa.conf b/src/config/wireplumber.conf.d.examples/alsa.conf index 1f96c8eb..0024d00b 100644 --- a/src/config/wireplumber.conf.d.examples/alsa.conf +++ b/src/config/wireplumber.conf.d.examples/alsa.conf @@ -133,8 +133,8 @@ monitor.alsa.rules = [ # audio.channels = 2 # audio.format = "S16LE" # audio.rate = 44100 - # audio.allowed-rates = "32000,96000" - # audio.position = "FLFR" + # audio.allowed-rates = [32000, 96000] + # audio.position = [FL, FR] # api.alsa.period-size = 1024 # api.alsa.period-num = 2 # api.alsa.headroom = 0