Commit graph

3859 commits

Author SHA1 Message Date
Sanchayan Maity
b1e4799ea6 bluez5: Ensure codec_id comparison is against codec of right type
G722 codec id for ASHA is chosen arbitrarily to be different from
A2DP and BAP codec IDs. ASHA spec does not specify a codec ID like
A2DP/BAP.

In places where codec_id comparisons are done, ensure that the check
is done against the codec of the right type viz. A2DP/BAP/ASHA.
2025-01-09 14:51:50 +00:00
Sanchayan Maity
c7496c847f bluez5: asha/g722: bump media_codec version 2025-01-09 14:51:50 +00:00
Sanchayan Maity
e83f01a33b bluez5: Clean up ASHA implementation 2025-01-09 14:51:50 +00:00
Sanchayan Maity
13c026417b bluez5: Implement support for ASHA
ASHA is a Bluetooth specification for hearing aids.

For a high level overview of the ASHA Specification for BlueZ.
https://asymptotic.notion.site/ASHA-Spec-for-Bluez-61a46027fd46458d8235e14d6bedb2ce

The original specification in Android.
https://source.android.com/docs/core/connect/bluetooth/asha

Corresponding support in BlueZ.
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/profiles/audio/asha.c

This only implements handling of one side of a ASHA device
pair. Stereo support/handling of both "left" & "right" side
will follow later requiring work on clock synchronization
between the pair.
2025-01-09 14:51:50 +00:00
Sanchayan Maity
41d099a580 bluez5: Add G722 codec for ASHA
For documentation on ASHA, see
https://source.android.com/docs/core/connect/bluetooth/asha
2025-01-09 14:51:50 +00:00
Sanchayan Maity
6a5f2bbd1f bluez5: media-sink: Log need_flush in flush_buffer 2025-01-09 14:51:50 +00:00
Arun Raghavan
71e403bbdb spa: aec: Add support for webrtc-audio-processing-2 2025-01-09 12:06:58 +00:00
Wim Taymans
48416b32ad audioconvert: improve Buffer params
Make sure we only make the buffer for the follower larger when we
downsample because then we need to ask for more data from the follower
to fill up a quantum.

Never try to make the follower buffer smaller than the quantum limit.
The reason is that the graph rate could be decreased dynamically and
then we would end up with too small buffers.

See #4490
2025-01-09 11:30:02 +01:00
Wim Taymans
3a65472e9e audioconvert: add support for filter-graphs
Load multiple graphs with audioconvert.filter-graph.N where N is the
order where the graph is inserted/replaced. Run the graphs before the
channelmixer.

Graphs can be added and removed at runtime.
2025-01-07 13:20:31 +01:00
Wim Taymans
1f4e8b96c2 audioconvert: fix remap stages
Merge remap with convert to simplify some things.
2025-01-07 12:58:59 +01:00
Wim Taymans
c00df67c12 audioconvert: schedule work offline
Instead of recalculating what to do every cycle, we can prepare a
static schedule and just run that. We only need to reevaluate it when
something changes.
2025-01-07 12:58:55 +01:00
Wim Taymans
3fbf84f612 audioconvert: run resampler depending on direction
For input streams, first run the resampler and then the channelmix. This
ensures that the channelmix is run with the rate of the graph instead
of the rate of the input. This is nicer because rate and quantum align
with the graph and the sample accurate volume ramps will work as
intended.

For output streams, leave the resampler after the channelmix for the same
reasons.
2025-01-07 12:03:59 +01:00
Wim Taymans
3cf9ccf4a7 filter-graph: handle NULL in and out
We need to pass exactly n_inputs and n_outputs pointers to the process
function but make it possible to set some to NULL so that the data is
ignored.
2025-01-07 10:42:04 +01:00
Wim Taymans
49f48a5fda filter-graph: separate data and size for filter graph
Remove the chunk and add separate arrays with data and n_samples. This aligns
better with other methods and makes it possible to more easily reuse
arrays of pointers as input and output.
2025-01-07 10:38:32 +01:00
Wim Taymans
d6030adada filter-graph: optimize mix function a little
Make special cases for no and 1 gain value when mixing.
2025-01-07 09:40:45 +01:00
Wim Taymans
efa615945e filter-graph: rename some properties 2025-01-07 09:35:05 +01:00
Wim Taymans
9f9e962dd6 filter-graph: pass spa_pod in get_props 2025-01-07 09:31:48 +01:00
Wim Taymans
094a45a6f7 filter-graph: make it possible to set n_inputs/n_outputs in graph
So that the graph can be a self contained object.
2025-01-07 09:26:53 +01:00
Wim Taymans
e7d61a6fdf filter-graph: cleanup up port data
An input port has at most 1 link so we can avoid the loop and the
default port data. We can then also improve the logging and log
something when we set silence.
2025-01-07 09:24:56 +01:00
Wim Taymans
c5ae456b9e filter-graph: pass dict to activate functions
This makes it possible to expand it more later.
2025-01-07 09:23:23 +01:00
Pauli Virtanen
90f8b0e40b spa: acp: remove some strictly not necessary SplitPCM properties
Remove some api.alsa.split.* properties that the monitor script can
figure out itself.
2024-12-23 11:46:02 +02:00
Pauli Virtanen
dcccfcab7f spa: acp: get and emit UCM information for SplitPCM devices
When api.alsa.split-enable=true for ACP device, instruct UCM to not
use alsa-lib plugins for SplitPCM devices.

Grab the information from UCM for the intended channel remapping, and
add the splitting information to the nodes emitted.

Session manager can then look at that, and load nodes to do the channel
splitting.
2024-12-21 16:03:19 +02:00
Pauli Virtanen
7d7019d939 spa-acp-tool: parse properties with spa_json
Fixes crash in parsing properties due to access after end of string.
2024-12-21 16:03:19 +02:00
Niklas Carlsson
51e7ed3421 filter-chain: add sqrt plugin
To take the square root of the signal.
2024-12-20 17:58:08 +00:00
Niklas Carlsson
d7718dbcb7 filter-chain: add abs plugin
To calculate the absolute value of the signal.
2024-12-20 17:58:08 +00:00
Niklas Carlsson
7785f61677 audioconvert: align low-/highpass calculations
The current biquad calculations are based on RBJ's cookbook [1],
except for low-/highpass. Since the filter configuration is also
based on using the definition of Q, it makes sense to also align
the remaining calculations to use the same filter cookbook instead
of using resonance which doesn't result in the same coefficients
as when using Q.

[1] = https://www.w3.org/TR/audio-eq-cookbook/
2024-12-20 11:03:43 +01:00
Barnabás Pőcze
11e0492f79 spa: vulkan: simplify memcpy() call 2024-12-14 23:28:43 +01:00
Barnabás Pőcze
bedcbf3631 spa: filter-graph: builtin: pointer instead of copying 2024-12-14 23:28:43 +01:00
Pauli Virtanen
a4e2d9cbb0 bluez5: lc3: bump media_codec version 2024-12-14 10:57:23 +00:00
Pauli Virtanen
bf12fe6d8b bluez5: lc3: simplify parsing 2024-12-14 10:57:23 +00:00
Pauli Virtanen
8f1983d14c bluez5: lc3: fix log name conflict 2024-12-14 10:57:23 +00:00
Iulia Tanasescu
9a5b2d42f9 bluez5: Configure LC3 codec capabilities
Currently, the PipeWire daemon registers BlueZ LE Media Endpoints
with audio capabilities covering all settings defined in the BAP spec.
However, some scenarios might require the capabilities to be restricted
to specific configurations.

This adds a method to read LC3 codec specific capabilities from the
Wireplumber config file, and provide those settings when registering
Media Endpoint objects with BlueZ. If the values are not present in
the config file, all settings will be used by default.

Below is an example of how to set the LC3 capabilities in the config
file, to support the 16_2 setting from the BAP spec:

bluez5.bap-server-capabilities.rates = [16000]
bluez5.bap-server-capabilities.durations = [10]
bluez5.bap-server-capabilities.channels = [1, 2]
bluez5.bap-server-capabilities.framelen_min = 40
bluez5.bap-server-capabilities.framelen_max = 40
bluez5.bap-server-capabilities.max_frames = 2
2024-12-14 10:57:23 +00:00
Barnabás Pőcze
b5490954d0 spa: filter-graph: ladspa: add dl_lib dependency
The ladspa plugin uses `dlopen()`, etc. directly,
so add the `dl_lib` dependency. This is not necessary
in a new enough environment since newer glibc versions
have merged most things into libc.
2024-12-14 10:55:28 +00:00
Iulia Tanasescu
cb000ad3dc bluez5: Configure sync_factor
For a BAP Broadcast Source endpoint, the QoS sync_factor enables the user
to adjust the Periodic Advertising interval based on the ISO interval
configured for the stream:

PA_Interval = sync_factor * ISO_Interval

Currently, this value is hardcoded to 2. This commit makes the sync_factor
configurable in the Wireplumber config file, along with the other config
parameters for BIGs.
2024-12-14 10:54:38 +00:00
Wim Taymans
94e823ddad filter-graph: add dcblock and ramp plugins 2024-12-09 15:00:35 +01:00
Wim Taymans
df271d13f3 filter-chain: add ebur128 filter
The EBU R128 filter measures the signal and generates LUFS control
notifications for further processing.

It also adds a plugin that can convert LUFS to a gain (based on a target
LUFS).

Also add an example filter-chain to enable the EBU R128 measurement and
how to use the results to adjust the volume dynamically.

See #2286 #222 #2210
2024-12-09 11:31:33 +01:00
Wim Taymans
f0f9fbb009 filter-graph: activate nodes after linking
Don't activate the nodes while linking but make a last stage where all
the nodes are activated. This makes it possible to better set up the
nodes based on the port data.
2024-12-09 11:30:05 +01:00
Wim Taymans
1bead99daf filter-graph: handle nodes with only control
It's possible to make a node with only control and notify so don't error
out on those nodes.
2024-12-09 11:30:05 +01:00
Alper Nebi Yasak
507ec0b39a alsa-ucm: Set up hardware volumes again on duplicate port additions
While initializing ALSA cards with UCM, we call pa_alsa_ucm_add_port()
for each UCM device for each UCM verb. This checks if a port has been
already added by name and skips port initialization if it is already
done. Different UCM verbs can have devices with the same name, which
means their port names end up being the same. So, this port creation
step currently is only done for one UCM verb for both UCM devices.

Volume control setup is also part of this process. The UCM devices only
know about the volume mixer information from the UCM verb that they are
defined in, so the volume control setup is done for one UCM verb at a
time. Skipping this setup when a same-named port exists means only the
profiles belonging to the first initialized UCM verb have working
hardware volume control.

Move the volume control setup out of the port initialization block so
that we try to do it every time, therefore for every UCM verb. However,
check that we don't run it twice for the same UCM verb for a port.

In theory, the PlaybackVolume etc. value can be different per-verb
for the same device, so we can't simplify this code to a single volume
setup per port.

Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/840
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-07 18:32:48 +00:00
Pauli Virtanen
2d30ab94c2 bluez5: account for codec internal delay in latency values
Encoders and some decoders have additional internal latency that needs
to be accounted for.

This mostly matters for AAC (~40ms), as the other BT codecs have much
lower delays (~5ms).
2024-12-07 18:28:17 +00:00
Pauli Virtanen
1b3b577b8f bluez5: aac: work around devices setting multiple bits in caps
Airpods don't follow the specification and set multiple bits in AAC
object type, including the ELD bit, but actually want AAC-LC.  So check
the AOT in the right order.
2024-12-07 18:25:53 +00:00
Pauli Virtanen
2bf48487cb bluez5: handle A2DP inverted ClearConfiguration/SetConfiguration order
When in A2DP sink role and remote end switches codec, BlueZ nowadays
appears sometimes emit first SetConfiguration (creating new transport),
and then ClearConfiguration (removing old transport).

Handle this case: emit profiles_changed event always when transports
come/go.

Redefine profiles_changed() to take bitmask of profiles whose connection
status changed, so we don't need to emit two remove+add events.
2024-12-06 16:36:14 +02:00
Arun Raghavan
5cbf3654c7 spa: alsa: Add a NULL check before updating rate match
The RateMatch IO might be NULL for the driver, and trying to update rate
matching with state->rate_match crashes in this case.
2024-12-05 13:08:04 -05:00
Alper Nebi Yasak
35dbaa840b alsa-ucm: Set icon names for mappings as well
Commit 88bb0bd7cc ("alsa: Allow to augment ucm port properties") adds
icon properties for some common port names, so that GUIs can show a
relevant icon to help disambiguate devices. However, these still do not
show up in pavucontrol, because it shows icons based on mappings'
properties. Add the relevant property to mappings as well.

Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/839
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-04 20:42:03 +00:00
Alper Nebi Yasak
e726c5f6db alsa-ucm: Fix possible segfault from recursion due to too many devices
While trying to figure out device subsets that have aren't internally
contain conflicting devices, we walk through all possible subsets and
check each set if it satisfies ConflictingDevices/SupportedDevices
listed in UCM configuration. For a better user experience, we want to
skip subsets that are fully included in another valid subset we will
also generate.

The iterate_device_subsets() function that achieves the former is
intentionally in iterative form to avoid a stack overflow, since it will
walk through 2^n sets. However, the iterate_maximal_device_subsets()
function that skips incomplete sets is in recursive form, as I had
assumed tail-call optimization would take care of the potential problem.

Convert iterate_maximal_device_subsets() to an iterative form, because
the recursion seems to trigger a segfault with more than 16 devices on
PulseAudio. It doesn't seem to happen on PipeWire, but it's better to
not leave it to luck.

Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/838
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-04 20:40:16 +00:00
Wim Taymans
f3a7f2c28e filter-graph: use SPA_MAX instead of fmaxf
fmaxf is a function unless compiled with special flags.
2024-12-04 16:40:53 +01:00
Wim Taymans
dc76254d03 filter-graph: fix compilation 2024-12-04 16:38:16 +01:00
Wim Taymans
6e2f631230 filter-graph: handle NULL data
Because the max plugin is marked as SUPPORTS_NULL, the input and output
pointers can be NULL. Handle these cases. Also reindent with tabs (not 7
spaces).
2024-12-04 16:30:33 +01:00
Jonas Holmberg
7f80711158 filter-graph: Make builtin plugin compile 2024-12-04 14:05:57 +01:00
Torkel Niklasson
bfb5ae18d1 filter-chain: add max builtin plugin
add max which takes two inputs and output the max value of them. it can
e.g. be used to create the same sidechain input to two mono limiters.
2024-12-04 13:17:36 +01:00