Syntax of the audio policy configuration file

Audio policy configuration files have a specific syntax.

The following sections are valid:

[audio_type] section

The order that you define your audio types using the [audio_type] section defines when one audio stream ducks another. For each audio_type section, you must use the following key-value pairs to describe the audio type. Every required key must be defined in the audio type section with valid values.
CAUTION:
If you leave any of the required key-value pairs out of an [audio_type] section, the file is invalid and io-audio fails to start.
Below are the required key-value pairs for each audio type you define:
Key: (Required) name
A string that specifies the name of the audio type. For example, phone or ringtone.
Key: (Required) prio
The priority directive of the audio type defined as a String value. These are the valid values:
  • same — the audio type has the same priority as previous audio type. If all the audio_types have the prio key set to same, then all audio types are at the same priority (including the first entry). An entry needs to define prio=decr for the priority to change.
  • decr — the priority of the audio type is one lower than the previously defined audio type.

    The first entry you define has the highest priority and forces any lower priority audio streams to duck (lower their volume).

Key: (Required) duck_same_prio_policy
The ducking policy applied to audio types of the same priority, defined as a String value. You cannot have different policies configured for audio types with the same priority. These are the valid values:
  • last_wins — The last added stream ducks previously added audio streams with the same priority.
  • first_wins — The first added stream ducks other audio streams with the same priority.
  • mix — The added audio stream ducks all or specific channels of other streams with the same priority. When you use this policy for audio types with the same priority, those streams are ducked according to the duck_same_prio_percent setting. If there are multiple ducking settings are applied, then the strictest (lowest ducking volume) configuration applies. For more information on duck_same_prio_policy and duck_same_prio_percent, see Understanding the mix policy when using multiple audio types with the same priority.”
    Note: All audio types with the same priority level and that have duck_same_prio_policy=mix must have the same values set for the duck_lower_prio_percent.
CAUTION:
Don't set duck_same_prio_policy to mix if you want to use enable preemption_by_same. If you do, io-audio fails to start.
Key: (Required) duck_same_prio_percent
Integer or String:Integer
The ducking percentage to apply to audio types with the same priority. The value can be specified as either an Integer, which specifies a single percentage value, or multiple, comma-delimited String:Integer key-value pairs, which specify values for multiple channels from 0 to 7.

A single value (between 0 or 100) specifies the percentage to reduce the volume by for active streams at the same priority level, for all channels. For example, if you specify duck_same_prio_percent=50, it means adjust to 50% of current volume level. To configure no ducking, either specify 100 or the string noducking. To understand what happens when multiple percentages are applied, see the Understanding the mix policy with multiple audio types with the same priority section.

To specify percentage values for multiple channels, use the following syntax to specify the channel and the percentage to duck, which delimits each channel with a comma (,):

chX:ducking_percentage, chX:ducking_percentage

where X represents the channel number.

It's important to mention that if you don't specify a percentage for an active channel, ducking defaults to 100 (or no ducking).

For example, the following entry specifies that channel 0 adjusts to 50% of its volume level and channel 1 adjusts to 80% of its volume level. Because no value is specified for channel 2, ducking isn't applied to it:
duck_same_prio_percent=ch0:50,ch1:80
Key: (Required) duck_lower_prio_percent
Integer or String:Integer
The ducking percentage to apply to audio types with a lower priority. Specify one of the following values:
  • An Integer between 0 and 100, which specifies the percentage to reduce the volume by for active streams of the same priority level, for all channels. For example, a value of 50 (duck_lower_prio_percent=50) means adjust to 50% of the current volume level. To configure no ducking, either specify 100 or the string noducking.
  • Multiple, comma delimited String:Integer key-value pairs, which specify a percentage value for one or more specific channels from 0 to 7.

    Use the following syntax, which delimits each channel with a comma (,):

    chX:ducking_percentage, chX:ducking_percentage

    where X represents the channel number.

    It's important to mention that if you don't specify a percentage for an active channel, ducking defaults to 100 (or no ducking).

    For example, the following specifies that channel 0 adjusts to 50% of its volume level and channel 1 adjusts to 80% of its volume level. Because no value is specified for channel 2, ducking isn't applied to it (effectively 100):

    duck_same_prio_percent=ch0:50,ch1:80

Key: (Optional) preemptable
String (true, true:suspend, or false)
(Optional) This key specifies whether the audio type can be preempted by audio concurrency management. The default behavior when this key isn't specified is false. You can specify one of the following values for this key:
  • false — Indicates to audio concurrency management that this audio stream can't be preempted. However, you can still explicitly call APIs to transition to the PAUSED state.

    It's important to remember that when the audio stream is ducked to zero (that is, muted), the audio stream remains in the RUNNING (SND_PCM_STATUS_RUNNING) state.

  • true — Indicates to audio concurrency management that the audio type can preempted. The behavior when the preemption ends depends on the value of the transient key for the audio type that imposes a ducking policy. If transient is set to true for the preempting audio stream, then the preempted audio stream moves to the SUSPENDED state when preemption occurs and transitions back to its previous state when the preemption ends (no longer ducked to zero). If transient is false for the preempting audio stream, then the preempted audio stream transitions to the SUSPENDED state but transitions to the PAUSED state when the preemption ends. Because your audio stream is in the PAUSED state, you must call snd_pcm_*_resume() to resume playing.
  • true:suspend — Indicates to audio concurrency management that the audio type can be preempted, but is limited to transitioning to the SUSPENDED state and then back to its original state. It's important to mention that audio concurrency management won't transition the audio stream to the PAUSED state. This setting is useful for audio types where you don't want to call snd_pcm_*_resume() to resume playing the audio stream.
Key: (Optional) transient
Boolean (true or false)
(Optional) This key specifies the state that audio concurrency management moves a preempted audio type to when a preemption ends:
  • true — This audio type can cause a preemptable audio type to move to the SUSPENDED state and when the preemption ends, the preempted audio stream transitions back to its original state.
  • false — This audio type can cause a preemptable audio type to move to the SUSPENDED state and when preemption ends, it moves to the PAUSED state. This means that you must call snd_pcm_*_resume() to resume playing the audio stream.

    It's important to mention that when this key is set to false, but the preemptable key is set to true:suspend, the audio stream that was preempted moves back to its original state when preemption is lifted (no longer ducked to zero).

Note: Audio types of the same priority level and with the duck_same_prio_policy set to mix must have the same setting for this key, otherwise an error occurs when loading the audio policy configuration file.

(Optional) [vol_ramp] section

This section permits you to define volume ramping for audio concurrency management scenarios based on specific names. The name and duration are required key-value pairs, and profile is optional. If you don't define ramping for an audio concurrency management scenario, the default duration is 20 milliseconds with a linear volume ramp (i.e., 100:100).

For each volume ramp ([vol_ramp]) section, you can use the following key-value pairs to describe the audio type.

Key: (Required) name
String(ducking, pause_resume, volume_mute)
This is a profile name that represents the scenario when ramping occurs. You can use one of these predefined names:
  • ducking — This name corresponds to any changes that are made due to ducking policies being used.
  • pause_resume — This name corresponds when the audio stream is paused or resumed using API calls.
  • volume_mute — This corresponds to when volume changes are made, including muting using the mixer. You can override this behavior using API calls (e.g., snd_mixer_group_write() and the change_duration member in the snd_mixer_group_t). If API calls don't specify the duration, it's treated as a zero, and the duration configured for this scenario is used for volume ramping.
Key: (Required) duration
Integer
This number represents the number of milliseconds to ramp to the specified volume, called ramp duration. This is the time it takes for the sum of all ramp segments to complete. For ducking and pause_resume scenarios, this parameter indicates the duration to complete ramping. The value specified here is used if the duration isn't specified
Key: (Optional) profile
Integer:Integer(sample percentage, volume increase percentage)
When specified, the number of sample pairs (comma-delimited pairs) represents the number of ramp segments. Each ramp segment indicates a percentage of the sample (duration) and the percentage of the volume delta. The sum of the percentage values for the ramp samples and volume increment values must equal to 100.
For example:
profile=20:10,60:80,20:10
In the example above, there are three ramp segments, which create a non-linear volume ramp. The segments mean:
  • For the first 20% of the sample (duration), increase the volume by 10% of the volume delta.
  • For the next 60% of the sample, increase the volume by 80% of the volume delta.
  • For the remaining 20% of the sample, increase to the remaining volume delta.
Notice that the sum of the percentage samples(duration) values (20 + 60 + 20) is 100; likewise, the sum of percentage values to increment the volume by (10 + 80 + 10) is also 100.

Example of an audio policy configuration file

[audio_type] # section defining an audio type
name=voice                                  # Audio type name string
prio=same                                   # Priority directive of the audio type,
                                            # possible value is "same" or "decr"
duck_same_prio_policy=last_wins             # Ducking policy of the same priority type,
                                            # Possible values are "last_wins", 
                                            # "first_wins", or "mix"
duck_same_prio_percent=0                    # Ducking percentage applied to same
                                            # priority audio types
duck_lower_prio_percent=0                   # Ducking percentage applied to lower
                                            # priority audio types
transient=false                             # Cause lower preemptable types to suspend

[audio_type]
name=ringtone
prio=decr                                   # Priority of the audio type is decreased
                                            # by one from previous audio type
duck_same_prio_policy=last_wins             # Last active audio stream that can duck
                                            # previous audio streams of same priority
duck_same_prio_percent=50                   # all channels of active streams at the
                                            # same priority level are ducked to 50 percent
duck_lower_prio_percent=50                  # all channels of active streams at lower
                                            # priority levels are ducked to 50 percent

[audio_type]
name=nav
prio=decr
duck_same_prio_policy=last_wins
duck_same_prio_percent=ch0:50,ch1:100       # Channel/Voice 0 ducked to 50 percent,
                                            # Channel/Voice 1 remains at 100 percent
duck_lower_prio_percent=ch0:50,ch1:100      # Ducking values will default to 100
                                            # (no ducking) for channels not listed

[audio_type]
name=tts_front
prio=decr
duck_same_prio_policy=last_wins
duck_same_prio_percent=80
duck_lower_prio_percent=80

[audio_type]
name=tts_back
prio=same                                   # Priority of the audio type is the
                                            # same as the previously defined type
duck_same_prio_policy=last_wins
duck_same_prio_percent=0
duck_lower_prio_percent=50

# To allow games and media to play concurrently, define the game type one above
# media with duck_lower_prio_percent=100/noducking
# Note: This means that if there are other lower priority types
#defined they will also not be ducked by the game type.

[audio_type]
name=game
prio=decr
duck_same_prio_policy=mix                   # Mix audio streams at same priority with
                                            # the below ducking configuration
duck_same_prio_percent=100                  # 100 percent
duck_lower_prio_percent=noducking
preemptable=true:suspend                    # Suspend only if preempted or ducked to 0
# Live media is not pausable, 
# so preemption is not enabled
[audio_type]
name=live_multimedia
prio=decr
duck_same_prio_policy=last_wins
duck_same_prio_percent=0
duck_lower_prio_percent=70


# The only difference between the live_multimedia and multimedia types
# is that multimedia can be paused so that preemption is enabled
[audio_type]
name=multimedia
prio=same
duck_same_prio_policy=last_wins
duck_same_prio_percent=0
duck_lower_prio_percent=70
preemptable=true                             #pause or suspend when preempted

[audio_type]
name=default
prio=decr
duck_same_prio_policy=mix                   # Mix audio streams at same priority
                                            # with the below ducking configuration
duck_same_prio_percent=100                  # 100 percent of volume (no ducking)
duck_lower_prio_percent=noducking
preemptable=true:suspend                    # Audio stream is suspended when
                                            # ducked to 0 percent by higher priority
                                            # types
[vol_ramp]
name=volume_mute                            # When mixer API calls are made,
                                            # such as snd_pcm_mixer_write(),
duration=20                                 # ramp in the span of 20 milliseconds
profile=20:10,60:80,20:10                   # Three linear segments are defined:
                                            # Segment 1 specifies 20% of the duration
                                            # and increases the volume by 10% of the
                                            # volume ramp. Segment 2 specifies 60% of
                                            # the duration and 80% of the volume
                                            # increase. Segment 3 specifies the
                                            # remaining 20% duration and to increase
                                            # the volume by the remaining 10%.

[vol_ramp]
name=pause_resume                           # Whenever the user calls snd_pcm_*_resume() or
                                            # snd_pcm_*_pause()
duration=30                                 # duration of 30 milliseconds
                                            # No profile key-value is specified, so
                                            # it's a linear ramp

[vol_ramp]
name=ducking                                # When ducking policies and preemption is used
duration=60                                 # Ramp time is 60 milliseconds