ALSA project - the C library reference

PCM (digital audio) plugins

PCM plugins extends functionality and features of PCM devices. The plugins take care about various sample conversions, sample copying among channels and so on.

# Slave definition

The slave plugin can be specified directly with a string or the definition can be entered inside a compound configuration node. Some restrictions can be also specified (like static rate or count of channels).

pcm_slave.NAME {
pcm STR # PCM name
# or
pcm { } # PCM definition
format STR # Format or "unchanged"
channels INT # Count of channels or "unchanged" string
rate INT # Rate in Hz or "unchanged" string
period_time INT # Period time in us or "unchanged" string
buffer_time INT # Buffer time in us or "unchanged" string
}

Example:

pcm_slave.slave_rate44100Hz {
pcm "hw:0,0"
rate 44100
}
pcm.rate44100Hz {
type plug
slave slave_rate44100Hz
}

The equivalent configuration (in one compound):

pcm.rate44100Hz {
type plug
slave {
pcm "hw:0,0"
rate 44100
}
}

# Plugin: hw

This plugin communicates directly with the ALSA kernel driver. It is a raw communication without any conversions. The emulation of mmap access can be optionally enabled, but expect worse latency in the case.

The nonblock option specifies whether the device is opened in a non-blocking manner. Note that the blocking behavior for read/write access won't be changed by this option. This influences only on the blocking behavior at opening the device. If you would like to keep the compatibility with the older ALSA stuff, turn this option off.

pcm.name {
type hw # Kernel PCM
card INT/STR # Card name (string) or number (integer)
[device INT] # Device number (default 0)
[subdevice INT] # Subdevice number (default -1: first available)
[sync_ptr_ioctl BOOL] # Use SYNC_PTR ioctl rather than the direct mmap access for control structures
[nonblock BOOL] # Force non-blocking open mode
[format STR] # Restrict only to the given format
[channels INT] # Restrict only to the given channels
[rate INT] # Restrict only to the given rate
or [rate [INT INT]] # Restrict only to the given rate range (min max)
[chmap MAP] # Override channel maps; MAP is a string array
}

## Function reference

- snd_pcm_hw_open()
- _snd_pcm_hw_open()

# Plugin: mmap_emul

pcm.name {
type mmap_emul
slave PCM
}

## Function reference

- _snd_pcm_hw_open()

# Plugin: shm

This plugin communicates with aserver via shared memory. It is a raw communication without any conversions, but it can be expected worse performance.

pcm.name {
type shm # Shared memory PCM
server STR # Server name
pcm STR # PCM name
}

## Function reference

- snd_pcm_shm_open()
- _snd_pcm_shm_open()

# Plugin: Null

This plugin discards contents of a PCM stream or creates a stream with zero samples.

Note: This implementation uses devices /dev/null (playback, must be writable) and /dev/full (capture, must be readable).

pcm.name {
type null # Null PCM
[chmap MAP] # Provide channel maps; MAP is a string array
}

## Function reference

- snd_pcm_null_open()
- _snd_pcm_null_open()

# Plugin: copy

This plugin copies samples from master copy PCM to given slave PCM. The channel count, format and rate must match for both of them.

pcm.name {
type copy # Copy PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
}
}

## Function reference

- snd_pcm_copy_open()
- _snd_pcm_copy_open()

# Plugin: linear

This plugin converts linear samples from master linear conversion PCM to given slave PCM. The channel count, format and rate must match for both of them.

pcm.name {
type linear # Linear conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
format STR # Slave format
}
}

## Function reference

- snd_pcm_linear_open()
- _snd_pcm_linear_open()

# Plugin: linear<->float

This plugin converts linear to float samples and float to linear samples from master linear<->float conversion PCM to given slave PCM. The channel count, format and rate must match for both of them.

pcm.name {
type lfloat # Linear<->Float conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
format STR # Slave format
}
}

## Function reference

- snd_pcm_lfloat_open()
- _snd_pcm_lfloat_open()

# Plugin: Mu-Law

This plugin converts Mu-Law samples to linear or linear to Mu-Law samples from master Mu-Law conversion PCM to given slave PCM. The channel count, format and rate must match for both of them.

pcm.name {
type mulaw # Mu-Law conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
format STR # Slave format
}
}

## Function reference

- snd_pcm_mulaw_open()
- _snd_pcm_mulaw_open()

# Plugin: A-Law

This plugin converts A-Law samples to linear or linear to A-Law samples from master A-Law conversion PCM to given slave PCM. The channel count, format and rate must match for both of them.

pcm.name {
type alaw # A-Law conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
format STR # Slave format
}
}

## Function reference

- snd_pcm_alaw_open()
- _snd_pcm_alaw_open()

# Plugin: Ima-ADPCM

This plugin converts Ima-ADPCM samples to linear or linear to Ima-ADPCM samples from master Ima-ADPCM conversion PCM to given slave PCM. The channel count, format and rate must match for both of them.

pcm.name {
type adpcm # Ima-ADPCM conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
format STR # Slave format
}
}

## Function reference

- snd_pcm_adpcm_open()
- _snd_pcm_adpcm_open()

# Plugin: Route & Volume

This plugin converts channels and applies volume during the conversion. The format and rate must match for both of them.

SCHANNEL can be a channel name instead of a number (e g FL, LFE). If so, a matching channel map will be selected for the slave.

pcm.name {
type route # Route & Volume conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
[format STR] # Slave format
[channels INT] # Slave channels
}
ttable { # Transfer table (bi-dimensional compound of cchannels * schannels numbers)
CCHANNEL {
SCHANNEL REAL # route value (0.0 - 1.0)
}
}
[chmap MAP] # Override channel maps; MAP is a string array
}

## Function reference

- snd_pcm_route_open()
- _snd_pcm_route_open()

# Plugin: Rate

This plugin converts a stream rate. The input and output formats must be linear.

pcm.name {
type rate # Rate PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
rate INT # Slave rate
[format STR] # Slave format
}
converter STR # optional
# or
converter [ STR1 STR2 ... ] # optional
# Converter type, default is taken from
# defaults.pcm.rate_converter
# or
converter { # optional
name STR # Convertor type
xxx yyy # optional convertor-specific configuration
}
}

## Function reference

- snd_pcm_rate_open()
- _snd_pcm_rate_open()

# Automatic conversion plugin

This plugin converts channels, rate and format on request.

pcm.name {
type plug # Automatic conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
[format STR] # Slave format (default nearest) or "unchanged"
[channels INT] # Slave channels (default nearest) or "unchanged"
[rate INT] # Slave rate (default nearest) or "unchanged"
}
route_policy STR # route policy for automatic ttable generation
# STR can be 'default', 'average', 'copy', 'duplicate'
# average: result is average of input channels
# copy: only first channels are copied to destination
# duplicate: duplicate first set of channels
# default: copy policy, except for mono capture - sum
ttable { # Transfer table (bi-dimensional compound of cchannels * schannels numbers)
CCHANNEL {
SCHANNEL REAL # route value (0.0 - 1.0)
}
}
rate_converter STR # type of rate converter
# or
rate_converter [ STR1 STR2 ... ]
# type of rate converter
# default value is taken from defaults.pcm.rate_converter
}

## Function reference

- snd_pcm_plug_open()
- _snd_pcm_plug_open()

# Plugin: File

This plugin stores contents of a PCM stream to file or pipes the stream to a command, and optionally uses an existing file as an input data source (i.e., "virtual mic")

pcm.name {
type file # File PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
}
file STR # Output filename (or shell command the stream
# will be piped to if STR starts with the pipe
# char).
# STR can contain format keys, replaced by
# real values corresponding to the stream:
# %r rate (replaced with: 48000)
# %c channels (replaced with: 2)
# %b bits per sample (replaced with: 16)
# %f sample format string
# (replaced with: S16_LE)
# %% replaced with %
or
file INT # Output file descriptor number
infile STR # Input filename - only raw format
or
infile INT # Input file descriptor number
[format STR] # File format ("raw" or "wav")
[perm INT] # Output file permission (octal, def. 0600)
}

## Function reference

- snd_pcm_file_open()
- _snd_pcm_file_open()

# Plugin: Multiple streams to One

This plugin converts multiple streams to one.

pcm.name {
type multi # Multiple streams conversion PCM
slaves { # Slaves definition
ID STR # Slave PCM name
# or
ID {
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
channels INT # Slave channels
}
}
bindings { # Bindings table
N {
slave STR # Slave key
channel INT # Slave channel
}
}
[master INT] # Define the master slave
}

For example, to bind two PCM streams with two-channel stereo (hw:0,0 and hw:0,1) as one 4-channel stereo PCM stream, define like this:

pcm.quad {
type multi
slaves.a.pcm "hw:0,0"
slaves.a.channels 2
slaves.b.pcm "hw:0,1"
slaves.b.channels 2
bindings.0.slave a
bindings.0.channel 0
bindings.1.slave a
bindings.1.channel 1
bindings.2.slave b
bindings.2.channel 0
bindings.3.slave b
bindings.3.channel 1
}

Note that the resultant pcm "quad" is not in the interleaved format but in the "complex" format. Hence, it's not accessible by applications which can handle only the interleaved (or the non-interleaved) format. In such a case, wrap this PCM with route or plug plugin.

pcm.quad2 {
type route
slave.pcm "quad"
ttable.0.0 1
ttable.1.1 1
ttable.2.2 1
ttable.3.3 1
}

## Function reference

- snd_pcm_multi_open()
- _snd_pcm_multi_open()

# Plugin: Share

This plugin allows sharing of multiple channels with more clients. The access to each channel is exlusive (samples are not mixed together). It means, if the channel zero is used with first client, the channel cannot be used with second one. If you are looking for a mixing plugin, use the dmix plugin.

The difference from dshare plugin is that share plugin requires the server program "aserver", while dshare plugin doesn't need the explicit server but access to the shared buffer.

pcm.name {
type share # Share PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
[format STR] # Slave format
[channels INT] # Slave channels
[rate INT] # Slave rate
[period_time INT] # Slave period time in us
[buffer_time INT] # Slave buffer time in us
}
bindings {
N INT # Slave channel INT for client channel N
}
}

## Function reference

- snd_pcm_share_open()
- _snd_pcm_share_open()

# Plugin: hooks

This plugin is used to call some 'hook' function when this plugin is opened, modified or closed. Typically, it is used to change control values for a certain state specially for the PCM (see the example below).

# Hook arguments definition
hook_args.NAME {
... # Arbitrary arguments
}
# PCM hook type
pcm_hook_type.NAME {
[lib STR] # Library file (default libasound.so)
[install STR] # Install function (default _snd_pcm_hook_NAME_install)
}
# PCM hook definition
pcm_hook.NAME {
type STR # PCM Hook type (see pcm_hook_type)
[args STR] # Arguments for install function (see hook_args)
# or
[args { }] # Arguments for install function
}
# PCM hook plugin
pcm.NAME {
type hooks # PCM with hooks
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
}
hooks {
ID STR # Hook name (see pcm_hook)
# or
ID { } # Hook definition (see pcm_hook)
}
}

Example:

hooks.0 {
type ctl_elems
hook_args [
{
name "Wave Surround Playback Volume"
preserve true
lock true
optional true
value [ 0 0 ]
}
{
name "EMU10K1 PCM Send Volume"
index { @func private_pcm_subdevice }
lock true
value [ 0 0 0 0 0 0 255 0 0 0 0 255 ]
}
]
}

Here, the controls "Wave Surround Playback Volume" and "EMU10K1 PCM Send Volume" are set to the given values when this pcm is accessed. Since these controls take multi-dimensional values, the `value` field is written as an array. When `preserve` is true, the old values are saved and restored when the pcm is closed. The `lock` means that the control is locked during this pcm is opened, and cannot be changed by others. When `optional` is set, no error is returned but ignored even if the specified control doesn't exist.

## Function reference

- The function ctl_elems - _snd_pcm_hook_ctl_elems_install() - installs CTL settings described by given configuration.
- snd_pcm_hooks_open()
- _snd_pcm_hooks_open()

# Plugin: dmix

This plugin provides direct mixing of multiple streams. The resolution for 32-bit mixing is only 24-bit. The low significant byte is filled with zeros. The extra 8 bits are used for the saturation.

pcm.name {
type dmix # Direct mix
ipc_key INT # unique IPC key
ipc_key_add_uid BOOL # add current uid to unique IPC key
ipc_perm INT # IPC permissions (octal, default 0600)
hw_ptr_alignment STR # Slave application and hw pointer alignment type
# STR can be one of the below strings :
# no (or off)
# roundup
# rounddown
# auto (default)
tstamp_type STR # timestamp type
# STR can be one of the below strings :
# default, gettimeofday, monotonic, monotonic_raw
slave STR
# or
slave { # Slave definition
pcm STR # slave PCM name
# or
pcm { } # slave PCM definition
format STR # format definition
rate INT # rate definition
channels INT
period_time INT # in usec
# or
period_size INT # in frames
buffer_time INT # in usec
# or
buffer_size INT # in frames
periods INT # when buffer_size or buffer_time is not specified
}
bindings { # note: this is client independent!!!
N INT # maps slave channel to client channel N
}
slowptr BOOL # slow but more precise pointer updates
}

`ipc_key` specfies the unique IPC key in integer. This number must be unique for each different dmix definition, since the shared memory is created with this key number. When `ipc_key_add_uid` is set true, the uid value is added to the value set in `ipc_key`. This will avoid the confliction of the same IPC key with different users concurrently.

`hw_ptr_alignment` specifies slave application and hw pointer alignment type. By default hw_ptr_alignment is auto. Below are the possible configurations:

- no: minimal latency with minimal frames dropped at startup. But wakeup of application (return from snd_pcm_wait() or poll()) can take up to 2 * period.
- roundup: It is guaranteed that all frames will be played at startup. But the latency will increase upto period-1 frames.
- rounddown: It is guaranteed that a wakeup will happen for each period and frames can be written from application. But on startup upto period-1 frames will be dropped.
- auto: Selects the best approach depending on the used period and buffer size. If the application buffer size is < 2 * application period, "roundup" will be selected to avoid under runs. If the slave_period is < 10ms we could expect that there are low latency requirements. Therefore "rounddown" will be chosen to avoid long wakeup times. Such wakeup delay could otherwise end up with Xruns in case of a dependency to another sound device (e.g. forwarding of microphone to speaker). Else "no" will be chosen.

Note that the dmix plugin itself supports only a single configuration. That is, it supports only the fixed rate (default 48000), format (`S16`), channels (2), and period_time (125000). For using other configuration, you have to set the value explicitly in the slave PCM definition. The rate, format and channels can be covered by an additional plug plugin, but there is only one base configuration, anyway.

An example configuration for setting 44100 Hz, `S32_LE` format as the slave PCM of "hw:0" is like below:

pcm.dmix_44 {
type dmix
ipc_key 321456 # any unique value
ipc_key_add_uid true
slave {
pcm "hw:0"
format S32_LE
rate 44100
}
}

You can hear 48000 Hz samples still using this dmix pcm via plug plugin like:

% aplay -Dplug:dmix_44 foo_48k.wav

For using the dmix plugin for OSS emulation device, you have to set the period and the buffer sizes in power of two. For example,

pcm.dmixoss {
type dmix
ipc_key 321456 # any unique value
ipc_key_add_uid true
slave {
pcm "hw:0"
period_time 0
period_size 1024 # must be power of 2
buffer_size 8192 # ditto
}
}

`period_time 0` must be set, too, for resetting the default value. In the case of soundcards with multi-channel IO, adding the bindings would help

pcm.dmixoss {
...
bindings {
0 0 # map from 0 to 0
1 1 # map from 1 to 1
}
}

so that only the first two channels are used by dmix. Also, note that ICE1712 have the limited buffer size, 5513 frames (corresponding to 640 kB). In this case, reduce the buffer_size to 4096.

## Function reference

- snd_pcm_dmix_open()
- _snd_pcm_dmix_open()

# Plugin: dshare

This plugin provides sharing channels. Unlike share plugin, this plugin doesn't need the explicit server program but accesses the shared buffer concurrently from each client as well as dmix and dsnoop plugins do. The parameters below are almost identical with these plugins.

pcm.name {
type dshare # Direct sharing
ipc_key INT # unique IPC key
ipc_key_add_uid BOOL # add current uid to unique IPC key
ipc_perm INT # IPC permissions (octal, default 0600)
hw_ptr_alignment STR # Slave application and hw pointer alignment type
# STR can be one of the below strings :
# no (or off)
# roundup
# rounddown
# auto (default)
tstamp_type STR # timestamp type
# STR can be one of the below strings :
# default, gettimeofday, monotonic, monotonic_raw
slave STR
# or
slave { # Slave definition
pcm STR # slave PCM name
# or
pcm { } # slave PCM definition
format STR # format definition
rate INT # rate definition
channels INT
period_time INT # in usec
# or
period_size INT # in frames
buffer_time INT # in usec
# or
buffer_size INT # in frames
periods INT # when buffer_size or buffer_time is not specified
}
bindings { # note: this is client independent!!!
N INT # maps slave channel to client channel N
}
slowptr BOOL # slow but more precise pointer updates
}

`hw_ptr_alignment` specifies slave application and hw pointer alignment type. By default hw_ptr_alignment is auto. Below are the possible configurations:

- no: minimal latency with minimal frames dropped at startup. But wakeup of application (return from snd_pcm_wait() or poll()) can take up to 2 * period.
- roundup: It is guaranteed that all frames will be played at startup. But the latency will increase upto period-1 frames.
- rounddown: It is guaranteed that a wakeup will happen for each period and frames can be written from application. But on startup upto period-1 frames will be dropped.
- auto: Selects the best approach depending on the used period and buffer size. If the application buffer size is < 2 * application period, "roundup" will be selected to avoid under runs. If the slave_period is < 10ms we could expect that there are low latency requirements. Therefore "rounddown" will be chosen to avoid long wakeup times. Such wakeup delay could otherwise end up with Xruns in case of a dependency to another sound device (e.g. forwarding of microphone to speaker). Else "no" will be chosen.

## Function reference

- snd_pcm_dshare_open()
- _snd_pcm_dshare_open()

# Plugin: dsnoop

This plugin splits one capture stream to more. It works the reverse way of dmix plugin, reading the shared capture buffer from many clients concurrently. The meaning of parameters below are almost identical with dmix plugin.

pcm.name {
type dsnoop # Direct snoop
ipc_key INT # unique IPC key
ipc_key_add_uid BOOL # add current uid to unique IPC key
ipc_perm INT # IPC permissions (octal, default 0600)
hw_ptr_alignment STR # Slave application and hw pointer alignment type
# STR can be one of the below strings :
# no (or off)
# roundup
# rounddown
# auto (default)
tstamp_type STR # timestamp type
# STR can be one of the below strings :
# default, gettimeofday, monotonic, monotonic_raw
slave STR
# or
slave { # Slave definition
pcm STR # slave PCM name
# or
pcm { } # slave PCM definition
format STR # format definition
rate INT # rate definition
channels INT
period_time INT # in usec
# or
period_size INT # in frames
buffer_time INT # in usec
# or
buffer_size INT # in frames
periods INT # when buffer_size or buffer_time is not specified
}
bindings { # note: this is client independent!!!
N INT # maps slave channel to client channel N
}
slowptr BOOL # slow but more precise pointer updates
}

`hw_ptr_alignment` specifies slave application and hw pointer alignment type. By default hw_ptr_alignment is auto. Below are the possible configurations:

- no: minimal latency with minimal frames dropped at startup. But wakeup of application (return from snd_pcm_wait() or poll()) can take up to 2 * period.
- roundup: It is guaranteed that all frames will be played at startup. But the latency will increase upto period-1 frames.
- rounddown: It is guaranteed that a wakeup will happen for each period and frames can be written from application. But on startup upto period-1 frames will be dropped.
- auto: Selects the best approach depending on the used period and buffer size. If the application buffer size is < 2 * application period, "roundup" will be selected to avoid over runs. If the slave_period is < 10ms we could expect that there are low latency requirements. Therefore "rounddown" will be chosen to avoid long wakeup times. Else "no" will be chosen.

## Function reference

- snd_pcm_dsnoop_open()
- _snd_pcm_dsnoop_open()

# Plugin: LADSPA <-> ALSA

This plugin allows to apply a set of LADPSA plugins. The input and output format is always SND_PCM_FORMAT_FLOAT (note: this type can be either little or big-endian depending on architecture).

The policy duplicate means that there must be only one binding definition for channel zero. This definition is automatically duplicated for all channels. If the LADSPA plugin has multiple audio inputs or outputs the policy duplicate is automatically switched to policy none.

The plugin serialization works as expected. You can eventually use more channels (inputs / outputs) inside the LADPSA plugin chain than processed in the ALSA plugin chain. If ALSA channel does not exist for given LADSPA input audio port, zero samples are given to this LADSPA port. On the output side (ALSA next plugin input), the valid channels are checked, too. If specific ALSA channel does not exist, the LADSPA output port is connected to a dummy sample area.

Instances of LADSPA plugins are created dynamically.

pcm.name {
type ladspa # ALSA<->LADSPA PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
}
[channels INT] # count input channels (input to LADSPA plugin chain)
[path STR] # Path (directory) with LADSPA plugins
plugins | # Definition for both directions
playback_plugins | # Definition for playback direction
capture_plugins { # Definition for capture direction
N { # Configuration for LADPSA plugin N
[id INT] # LADSPA plugin ID (for example 1043)
[label STR] # LADSPA plugin label (for example 'delay_5s')
[filename STR] # Full filename of .so library with LADSPA plugin code
[policy STR] # Policy can be 'none' or 'duplicate'
input | output {
bindings {
C INT or STR # C - channel, INT - audio port index, STR - audio port name
}
controls {
# valid only in the input block
I INT or REAL # I - control port index, INT or REAL - control value
# or
STR INT or REAL # STR - control port name, INT or REAL - control value
}
}
}
}
}

## Function reference

- snd_pcm_ladspa_open()
- _snd_pcm_ladspa_open()

# Plugin: asym

This plugin is a combination of playback and capture PCM streams. Slave PCMs can be defined asymmetrically for both directions.

pcm.name {
type asym # Asym PCM
playback STR # Playback slave name
# or
playback { # Playback slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
}
capture STR # Capture slave name
# or
capture { # Capture slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
}
}

For example, you can combine a dmix plugin and a dsnoop plugin as as a single PCM for playback and capture directions, respectively.

pcm.duplex {
type asym
playback.pcm "dmix"
capture.pcm "dsnoop"
}

By defining only a single direction, the resultant PCM becomes half-duplex.

## Function reference

- _snd_pcm_asym_open()

# Plugin: IEC958

This plugin converts 32bit IEC958 subframe samples to linear, or linear to 32bit IEC958 subframe samples.

pcm.name {
type iec958 # IEC958 subframe conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
}
[status status-bytes] # IEC958 status bits (given in byte array)
# IEC958 preamble bits definitions
# B/M/W or Z/X/Y, B = block start, M = even subframe, W = odd subframe
# As default, Z = 0x08, Y = 0x04, X = 0x02
[preamble.z or preamble.b val]
[preamble.x or preamble.m val]
[preamble.y or preamble.w val]
[hdmi_mode true]
}

When `hdmi_mode` is true, 8-channel compressed data is formatted as 4 contiguous frames of a single IEC958 stream as required by the HDMI HBR specification.

## Function reference

- snd_pcm_iec958_open()
- _snd_pcm_iec958_open()

# Plugin: Soft Volume

This plugin applies the software volume attenuation. The format, rate and channels must match for both of source and destination.

When the control is stereo (count=2), the channels are assumed to be either mono, 2.0, 2.1, 4.0, 4.1, 5.1 or 7.1.

If the control already exists and it's a system control (i.e. no user-defined control), the plugin simply passes its slave without any changes.

pcm.name {
type softvol # Soft Volume conversion PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
[format STR] # Slave format
}
control {
name STR # control element id string
[card STR] # control card index
[iface STR] # interface of the element
[index INT] # index of the element
[device INT] # device number of the element
[subdevice INT] # subdevice number of the element
[count INT] # control channels 1 or 2 (default: 2)
}
[min_dB REAL] # minimal dB value (default: -51.0)
[max_dB REAL] # maximal dB value (default: 0.0)
[resolution INT] # resolution (default: 256)
# resolution = 2 means a mute switch
}

## Function reference

- snd_pcm_softvol_open()
- _snd_pcm_softvol_open()

# Plugin: Empty

This plugin just redirects the PCM stream to another plugin.

pcm.name {
type empty # Null PCM
slave STR # Slave name
# or
slave { # Slave definition
pcm STR # Slave PCM name
# or
pcm { } # Slave PCM definition
[format STR] # Slave format
[channels INT] # Slave channels
}
}

## Function reference

- _snd_pcm_empty_open()