Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve ALSA PCM plugin compatibility on a2dp-sink, hfp-hf and hsp-hs #745

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/spellcheck-wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ CRC
CTL
CTLs
CVSD
ADC
DRC
ELD
eSCO
Expand Down Expand Up @@ -113,6 +114,7 @@ renderer
scalable
signedness
stdin
sys
syslog
tmp
tty
Expand Down Expand Up @@ -211,6 +213,7 @@ hfphf
hspag
hsphs
HUP
HWCOMPAT
ioplug
IPHONEACCEV
jas
Expand Down
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ unreleased
- channel map and volume control for surround sound (5.1, 7.1) audio
- native A2DP volume control by default (dropped --a2dp-volume option)
- fix configuration for Android 13 A2DP Opus codec
- improved ALSA PCM support for A2DP-sink, HFP-HF and HSP-HS

bluez-alsa v4.3.1 (2024-08-30)
==============================
Expand Down
77 changes: 64 additions & 13 deletions doc/bluealsa-plugins.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ bluealsa-plugins
Bluetooth Audio ALSA Plugins
----------------------------

:Date: August 2024
:Date: December 2024
:Manual section: 7
:Manual group: Miscellaneous
:Version: $VERSION$
Expand Down Expand Up @@ -104,6 +104,14 @@ PCM Parameters
special value **unchanged** which causes the PCM to use its existing
softvol value. The default value is **unchanged**.

HWCOMPAT
Modifies the behavior of the plugin on ``a2dp-sink``, ``hfp-hf`` and
``hsp-hs`` nodes in order to align better with the behaviour of the ALSA
``hw`` plugin. This is a string option which takes the values **none**,
**busy** or **silence**.
See `Transport acquisition`_ in the **NOTES** section below for more
information.

DELAY
An integer number which is added to the reported delay (latency) value in
order to manually adjust the audio synchronization. It is not normally
Expand All @@ -129,6 +137,7 @@ own configuration (e.g. in ~/.asoundrc.conf) for example:
defaults.bluealsa.codec "cvsd"
defaults.bluealsa.volume "50+"
defaults.bluealsa.softvol off
defaults.bluealsa.hwcompat "silence"
defaults.bluealsa.delay 5000
defaults.bluealsa.service "org.bluealsa.source"

Expand All @@ -141,11 +150,11 @@ Positional Parameters
ALSA permits arguments to be given as positional parameters as an alternative
to explicitly naming them. When using positional parameters it is important
that the values are given in the correct sequence - *DEV*, *PROFILE*, *CODEC*,
*VOL*, *SOFTVOL*, *DELAY*, *SRV*. For example:
*VOL*, *SOFTVOL*, *HWCOMPAT*, *DELAY*, *SRV*. For example:

::

bluealsa:01:23:45:67:89:AB,a2dp,unchanged,unchanged,unchanged,0,org.bluealsa
bluealsa:01:23:45:67:89:AB,a2dp,unchanged,unchanged,unchanged,none,0,org.bluealsa

When using positional parameters defaults can only be implied at the end of the
id string, so
Expand Down Expand Up @@ -178,6 +187,7 @@ configuration node has the following fields:
[codec STR] # Preferred codec
[volume STR] # Initial volume for this PCM
[softvol BOOLEAN] # Enable/disable BlueALSA's software volume
[hwcompat STR] # HW compatibility mode (none, busy or silence)
[delay INT] # Extra delay (frames) to be reported (default 0)
[service STR] # DBus name of service (default org.bluealsa)
}
Expand Down Expand Up @@ -559,22 +569,63 @@ only the HFP-AG node can change the HFP codec.
Transport acquisition
---------------------

The audio connection of a profile is not established immediately that a device
connects. The A2DP source device, or HFP/HSP gateway device, must first
"acquire" the profile transport.
The audio connection of a Bluetooth profile is not established immediately that
a device connects. The A2DP source device, or HFP/HSP gateway device, must
first "acquire" the profile transport.

When the BlueALSA PCM plugin is used on a source A2DP or gateway HFP/HSP node,
then **bluealsad(8)** will automatically acquire the transport and begin audio
transfer when the plugin starts the PCM.

When used on an A2DP sink or HFP/HSP HF/HS node then **bluealsad(8)** must wait
for the remote device to acquire the transport. During this waiting time the
PCM plugin behaves as if the device "clock" is stopped, it does not generate
any poll() events, and the application will be blocked when writing or reading
to/from the PCM. For applications playing audio from a file or recording audio
to a file this is not normally an issue; but when streaming between some other
device and a BlueALSA device this may lead to very large latency (delay) or
trigger underruns or overruns in the other device.
for the remote device to acquire the transport. The ALSA PCM plugin state model
does not define any state that can be directly mapped to this situation, so
the BlueALSA PCM plugin offers a choice of behaviors to suit various
application requirements. The choice is selected using the parameter
**hwcompat** (**HWCOMPAT** argument to the pre-defined `bluealsa` PCM) which
takes one of the following values:

- none

The streams are presented exactly as handled by Bluetooth. No adjustments
are made to align the PCM more to expected ALSA behavior. While waiting for
the transport to be acquired the PCM plugin behaves as if the device
timer is stopped; it does not generate any poll() events, and the
application will be blocked when writing or reading to/from the PCM. For
applications playing audio from a file or recording audio to a file this is
not normally an issue and has the advantage that the played or captured
stream does not contain any frames of silence artificially inserted by the
plugin. However when streaming between some other device and a
BlueALSA device this may lead to very large latency (delay) or trigger
underruns or overruns in the other device. Capture streams may also have
brief interruptions caused by Bluetooth radio link interference. Some
applications, particularly ones which attempt to manage latency such as
``alsaloop(1)``, may become unstable in this situation.

- busy

Causes snd_pcm_open() to return immediately with error code **-EBUSY**
("Device or resource busy") on A2DP sink, HFP-HF and HSP-HS nodes if the
transport is not yet acquired. This is analogous to a ``hw`` device PCM
that is temporarily unavailable (for example because it is in use by some
other application). With this option the plugin also stops the
PCM stream and enters the **SND_PCM_STATE_DISCONNECTED** state if the
remote device releases the transport while in use, which is analogous to a
removable ``hw`` device being unplugged. If a capture stream is interrupted
by temporary Bluetooth link instability then the plugin simply blocks
temporarily, which may cause issues for some applications as noted for the
**none** value above.

- silence

Inserts silence for capture streams, or simply drops frames for playback
streams, whenever the transport is not acquired. Short intervals of silence
may also be inserted into capture streams if there is a break in the
incoming stream (for example as a result Bluetooth link instability). By
this means a continuous stream is maintained as far as the application is
concerned. This is analogous to a soundcard device with no speakers or
microphone plugged in: only silence is captured and playback succeeds but
produces no sound.

PCM drain and non-blocking operation
------------------------------------
Expand Down
12 changes: 11 additions & 1 deletion src/asound/20-bluealsa.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ defaults.bluealsa.volume "unchanged"
# By default do not modify the software volume state
# when a PCM is opened.
defaults.bluealsa.softvol "unchanged"
# By default on a2dp-sink and AG nodes ignore transport acquisition state.
defaults.bluealsa.hwcompat "none"
# If Bluetooth sink device (e.g. headphones) supports
# A2DP v1.3 or later it will report delay by itself,
# so there is no need to set the delay manually.
Expand Down Expand Up @@ -82,7 +84,7 @@ ctl.bluealsa {
}

pcm.bluealsa {
@args [ DEV PROFILE CODEC VOL SOFTVOL DELAY SRV ]
@args [ DEV PROFILE CODEC VOL SOFTVOL HWCOMPAT DELAY SRV ]
@args.DEV {
type string
default {
Expand Down Expand Up @@ -118,6 +120,13 @@ pcm.bluealsa {
name defaults.bluealsa.softvol
}
}
@args.HWCOMPAT {
type string
default {
@func refer
name defaults.bluealsa.hwcompat
}
}
@args.DELAY {
type integer
default {
Expand All @@ -140,6 +149,7 @@ pcm.bluealsa {
codec $CODEC
volume $VOL
softvol $SOFTVOL
hwcompat $HWCOMPAT
delay $DELAY
service $SRV
}
Expand Down
Loading
Loading