Why BLE Audio?
Classic Bluetooth has been carrying audio for years using A2DP and HFP. These profiles work, but they have real problems — audio goes one way at a time on HFP, latency is inconsistent, and multiple devices cannot listen to the same stream simultaneously without vendor tricks.
BLE Audio was introduced in Bluetooth 5.2 to fix all of this. It uses isochronous channels — a new transport type in the BLE Link Layer — to carry time-synchronized audio. The codec changes too: instead of SBC or AAC, BLE Audio uses LC3, which delivers better quality at lower bitrates.
The Basic Audio Profile (BAP) is the foundation of BLE Audio. It defines how devices advertise audio capabilities, how streams are set up and torn down, and how broadcast audio works. Every higher-level BLE Audio profile — like CAP, TMAP, HAP — builds on top of BAP.
Key Terms in This Post
Where Does BAP Sit in the Stack?
BAP sits at the profile layer and uses three GATT services below it. Understanding this stack is critical before you touch any code.
| Higher Profiles (CAP, TMAP, HAP, AICS …) | ||
| Basic Audio Profile (BAP) | ||
| PACS Published Audio Capabilities Service |
ASCS Audio Stream Control Service |
BASS Broadcast Audio Scan Service |
| GATT | GAP | ||
| L2CAP | LL (CIS / BIS Isochronous) | ||
| BLE Physical Layer (1M / 2M PHY) | ||
The three services each have a specific job:
The Six BAP Roles
BAP defines six roles split into two groups: Unicast roles (connection-based, point-to-point) and Broadcast roles (connectionless, one-to-many).
Unicast Roles
This is the headset, earbuds, or speaker — the device that exposes its audio capabilities over GATT. It implements PACS Server and ASCS Server.
It advertises using Extended Advertising PDUs (connectable). It accepts CIS establishment from the Unicast Client. It can be an Audio Sink (receives audio), an Audio Source (microphone), or both at the same time.
This is the phone, laptop, or media player — the device that scans for Unicast Servers, reads their GATT characteristics, and drives the entire stream setup procedure.
It creates the CIG (Connected Isochronous Group) and CIS (Connected Isochronous Stream) using HCI commands. It writes to the ASE Control Point on the server to move ASEs through their states.
| Unicast Client (Phone / Laptop) |
LE ACL + CIS
⟵⟶
Audio Data
|
Unicast Server (Earbuds / Headset) |
Broadcast Roles
Transmits audio to anyone who wants to receive it — like a radio station. Uses BIG (Broadcast Isochronous Group) and BIS (Broadcast Isochronous Stream). No connection needed. Advertises stream parameters using Extended Advertising and Periodic Advertising.
Scans for broadcast audio and synchronizes to a BIG to receive audio. Think of a pair of wireless speakers in a gym. It exposes a PACS Server so others can learn its capabilities. Every Broadcast Sink must also implement the Scan Delegator role.
The “helper” role. A phone acts as a Broadcast Assistant when it scans for broadcast sources on behalf of a headset (the Scan Delegator) that cannot scan on its own to save power.
It connects to the Scan Delegator over LE ACL and writes broadcast source information to its BASS. It can also deliver the Broadcast_Code needed to decrypt encrypted streams.
Co-located with a Broadcast Sink, this role delegates scanning to a Broadcast Assistant. It exposes a BASS Server. It sends solicitation requests (Extended Advertising) to attract a nearby Broadcast Assistant. Once an Assistant connects and writes broadcast source info, the Scan Delegator can synchronize to the BIS.
Broadcast Topology Example
| Broadcast Source (TV / Laptop) |
BIS (BIG)
⟶
Broadcast
|
|
LE ACL
⟵⟶
|
|
Which Services Does Each Role Need?
The table below shows which GATT service role is mandatory (M), optional (O), or excluded (X) for each BAP role.
| Service Role | Unicast Server | Unicast Client | Broadcast Source | Broadcast Sink | Scan Delegator | Broadcast Assistant |
|---|---|---|---|---|---|---|
| ASCS Client | X | M | X | X | X | X |
| ASCS Server | M | X | X | X | X | X |
| PACS Client | X | M | X | X | X | O |
| PACS Server | M | X | X | M | X | X |
| BASS Client | X | X | X | X | X | M |
| BASS Server | X | X | X | X | M | X |
CIS vs BIS — The Two Isochronous Channels
Used in unicast audio. Requires an LE ACL connection first. Bidirectional (can carry audio both ways in one CIS). The Unicast Client creates a CIG (group of CISes) and establishes CISes to the Unicast Server.
Used in broadcast audio. No connection required. Unidirectional (Source → Sinks only). Multiple Sinks can receive the same BIS simultaneously. The Broadcast Source creates a BIG (group of BISes).
BlueZ — Discovering BAP Capabilities
In BlueZ, you can explore BAP-capable devices using bluetoothctl. When a Unicast Server connects, its PACS and ASCS characteristics show up as media endpoints.
# Start bluetoothctl and scan for BLE Audio devices $ bluetoothctl [bluetooth]# power on [bluetooth]# scan on # After a device is found and paired, connect to it [bluetooth]# connect AA:BB:CC:DD:EE:FF # List all media endpoints exposed by the connected device # BAP devices expose endpoints via the MediaEndpoint1 D-Bus interface [bluetooth]# list-attributes AA:BB:CC:DD:EE:FF # You should see PACS UUIDs such as: # 00002bc9-0000-1000-8000-00805f9b34fb (Sink PAC) # 00002bcb-0000-1000-8000-00805f9b34fb (Sink Audio Locations) # 00002bcf-0000-1000-8000-00805f9b34fb (Available Audio Contexts) # 00002bce-0000-1000-8000-00805f9b34fb (Supported Audio Contexts) # Read the Sink PAC to see what codec settings are advertised [bluetooth]# attribute-info 00002bc9-0000-1000-8000-00805f9b34fb [bluetooth]# read 00002bc9-0000-1000-8000-00805f9b34fb
/* C: List endpoints via BlueZ D-Bus (conceptual) */ /* BlueZ registers BAP endpoints at /org/bluez/hciX/dev_XX_XX/sepY */ #include <glib.h> #include <gio/gio.h> void list_media_endpoints(GDBusConnection *conn, const char *device_path) { GVariant *result; GError *error = NULL; /* Call GetManagedObjects on org.bluez to get all objects */ result = g_dbus_connection_call_sync( conn, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); /* Filter objects implementing org.bluez.MediaEndpoint1 */ /* Each endpoint has codec, capabilities, and channel info */ }
Next: LC3 Codec & QoS Configurations
In Part 2 we cover the LC3 codec, what the codec setting names like 16_2_1 mean, and how QoS parameters are chosen for low-latency vs high-reliability audio.
