docs: update ALSA documentation

This commit is contained in:
George Kiagiadakis 2024-02-14 15:57:36 +02:00
parent 89b9218031
commit 4dc7317010
2 changed files with 353 additions and 343 deletions

View file

@ -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 <config_features>` 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 = "<sound_card_name>"
}
]
actions = {
update-props = {
# Apply all the desired device settings here.
api.alsa.use-acp = true
}
}
}
{
matches = [
# This matches the needed node.
{
node.name = "<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 <node-id> 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 <node-id> Props '{ iec958Codecs : [ PCM ] }'`` to modify
the codecs at runtime.
:Type: array of strings (example: ``[ "PCM", "DTS", "AC3", "EAC3", "TrueHD", "DTS-HD" ]``)

View file

@ -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