LE Audio: Broadcast Audio Streams
Chapter 8 — BIG, BIS, BASE, BASS, Commanders and how they all connect
What you will learn
What Is Broadcast Audio in LE Audio?
Classic Bluetooth audio always works one-to-one. One phone, one set of headphones. They pair, connect, and audio flows between just those two devices. LE Audio changes this with Broadcast, which lets one device transmit audio to any number of receivers at the same time — with no pairing needed.
Think of FM radio. The station transmits. Anyone with a receiver in range can tune in without registering or connecting to the station. LE Audio Broadcast works the same way, except it is digital, uses LC3 audio compression, and supports features FM never could — like encrypted private streams and smart remote control via Commanders.
The broadcast topology originally came from hearing loop (telecoil) systems used in public venues. But LE Audio’s version is far more powerful: it handles multiple simultaneous streams, supports different languages in the same broadcast, encrypts audio for private use, and lets a phone or remote act as a smart controller for your earbuds.
The Three Things Broadcast Needs to Do
Broadcast in LE Audio is split into three separate functions. Different devices implement different subsets of these:
| 1. Transmitting The Broadcast Source sends audio out over BIS channels grouped inside a BIG. It does not know or care who is listening. | 2. Finding A Broadcast Assistant (part of a Commander) scans for available streams, filters them by what the receiver can handle, and hands the info to the receiver’s earbuds or hearing aids. | 3. Receiving The Broadcast Sink (Acceptor) scans, locks on to the BIG, picks a BIS, decodes LC3, applies Presentation Delay, and renders audio. It can do this alone or with a Broadcast Assistant’s help. |
In most real products all three happen together, but the specs keep them separate so each device only has to implement what it needs. A PA amplifier in an auditorium only needs the Transmit function. A hearing aid only needs the Receive function. A phone typically handles all three.
Setting Up a Broadcast Source
A Broadcast Source is the device that puts audio on air. A TV, a phone sharing audio, or a PA system all fit this role. Unlike a unicast Central device, the Broadcast Source does not need any receivers to be present. It just transmits. The Host application inside the device gives the Controller all the configuration it needs, and the Controller handles the rest.
State Machine — Three States
|
IDLE
|
→ |
CONFIGURED
|
→ |
STREAMING
|
|||
|
|||||||
Transitions between states use HCI commands. Unlike unicast (where both sides negotiate), the Broadcast Source does all of this unilaterally — no handshakes with any receiver.
BAP defines six procedures for these transitions (configuration, establishment, disable, metadata update, release, reconfiguration). CAP simplifies them into five grouped procedures: Broadcast Audio Start, Update, Stop, Reception Start, and Reception Stop.
BASE — What the Receiver Reads to Know What Is Available
The BASE (Basic Audio Stream Endpoint) is a data structure packed into the Periodic Advertisement by the Broadcast Source. Every receiver reads the BASE to find out: how many audio streams are available, what codec is used, what quality, and what the content is (music, speech, which channel, which language, etc.).
BASE has three nested levels:
| LEVEL 1 — BIG-wide parameters (applies to all streams) Presentation Delay | Number of Subgroups |
|||
| LEVEL 2 — Subgroup 0 Num_BIS | Codec_ID (LC3) | Codec Config | Metadata e.g. Language: English, Context: Media |
LEVEL 2 — Subgroup 1 Num_BIS | Codec_ID (LC3) | Codec Config | Metadata e.g. Language: Spanish, Context: Media |
||
| LEVEL 3 BIS[0][0] Index: 0x01 Left Channel |
LEVEL 3 BIS[0][1] Index: 0x02 Right Channel |
LEVEL 3 BIS[1][0] Index: 0x03 Left Channel |
LEVEL 3 BIS[1][1] Index: 0x04 Right Channel |
The rule for which level to use:
- Different languages or different parental ratings → separate subgroups (Level 2 entries). There is no other way to express this difference.
- Different audio quality of the same content → separate BIS entries at Level 3 within the same subgroup (e.g., one BIS at 48 kHz, one at 24 kHz).
- Typical stereo stream → one subgroup, two BISes (Left at index 1, Right at index 2). That is all most real products need.
BASE Parameters Table
| Level | Parameter | Size | What it means |
|---|---|---|---|
| 1 (BIG) | Basic Audio Announcement UUID | 2 B | Fixed value 0x1852 — marks this advertisement as a broadcast audio source |
| 1 | Presentation Delay | 3 B | Time in µs between packet arrival and audio output. Range 0 to 16.7 s. |
| 1 | Num_Subgroups | 1 B | How many subgroups exist in this BIG |
| 2 (Subgroup) | Num_BIS[i] | 1 B | Number of BIS channels in this subgroup |
| 2 | Codec_ID[i] | 5 B | Codec for this subgroup. 0x06 = LC3 (standard LE Audio codec). |
| 2 | Codec_Specific_Configuration[i] | Varies | Sampling rate, frame duration, bitrate, audio channel allocation |
| 2 | Metadata[i] | Varies | Language, parental rating, Streaming_Audio_Contexts (CAP requires this field) |
| 3 (BIS) | BIS_index[i[k]] | 1 B | Unique BIS number within the BIG. Starts at 1. |
| 3 | Codec_Specific_Configuration[i[k]] | Varies | Per-BIS codec override. Used when BISes in the same subgroup differ in quality. |
Creating the BIG — LE_Create_BIG HCI Command
Once the BASE is assembled, the Host sends LE_Create_BIG to the Controller. This command schedules all the BIS channels and starts the isochronous broadcast. The key parameters:
| Parameter | Purpose |
|---|---|
BIG_Handle |
Host-set identifier for this BIG |
Advertising_Handle |
Links this BIG to the Extended Advertising set already running |
Num_BIS |
Total number of BIS channels to create |
SDU_Interval |
Time between audio packets in µs (e.g., 10000 = 10 ms per LC3 frame) |
Max_SDU |
Maximum payload bytes per packet — must accommodate the largest BIS in the BIG |
PHY |
0 = 1 Mbps, 1 = 2 Mbps (preferred for audio), 2 = LE Coded |
Packing |
0 = Sequential, 1 = Interleaved. Controller treats this as a preference, not a mandate. |
RTN |
Requested retransmission count. Controller uses this as a hint. |
Encryption |
0 = unencrypted, 1 = encrypt with Broadcast_Code |
Broadcast_Code |
16-byte encryption key. Set to all-zeros for unencrypted streams. |
How the Advertising Chain Works
A Broadcast Source runs three layers of advertising simultaneously. A receiver scans through all three layers to get everything it needs before locking on to the audio:
| ADV_EXT_IND — Primary Advertisement Contains: Advertiser Address, SID (Advertising Set ID), AuxPtr pointing down to secondary |
| ↓ AuxPtr |
| AUX_ADV_IND — Secondary Advertisement Contains: Broadcast Audio Announcement Service UUID, Broadcast_ID (3 bytes), SyncInfo for PA |
| ↓ SyncInfo |
| AUX_SYNC_IND — Periodic Advertisement Contains: Basic Audio Announcement UUID, BASE (codec config, subgroups, BIS indices), BIGInfo in ACAD |
| ↓ BIGInfo (hopping sequence, anchor points) |
| BIS Isochronous Data Channels Actual LC3-encoded audio PDUs transmitting at SDU_Interval (e.g., every 10 ms) |
BlueZ Code: Creating a BIG Using ISO Sockets
Linux kernel 5.14+ supports Broadcast Isochronous Streams via ISO sockets in BlueZ. A connect() call on a bound ISO socket triggers LE_Create_BIG inside the kernel automatically:
/*
* broadcast_source.c
* Minimal Broadcast Source: creates a BIG with one BIS using BlueZ ISO socket API.
* Build: gcc -o bcast_src broadcast_source.c -lbluetooth
* Run as root: ./bcast_src
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/iso.h>
/* LC3 at 16 kHz, 10 ms frame, 32 kbps = 40 bytes per SDU */
#define LC3_SDU_SIZE 40
#define SDU_INTERVAL 10000 /* 10 ms in microseconds */
int main(void)
{
int sk, ret;
struct sockaddr_iso src = {0}, dst = {0};
struct bt_iso_qos qos = {0};
uint8_t frame[LC3_SDU_SIZE] = {0};
/* 1. Create an ISO socket for BIS (broadcast) */
sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_ISO);
if (sk < 0) { perror("socket"); return 1; }
/* 2. Bind to default local adapter */
src.iso_family = AF_BLUETOOTH;
src.iso_bdaddr_type = BDADDR_LE_PUBLIC;
bacpy(&src.iso_bdaddr, BDADDR_ANY);
ret = bind(sk, (struct sockaddr *)&src, sizeof(src));
if (ret < 0) { perror("bind"); goto fail; }
/* 3. Set BIG / BIS QoS parameters */
qos.bcast.big = BT_ISO_QOS_BIG_UNSET; /* kernel assigns */
qos.bcast.bis = BT_ISO_QOS_BIS_UNSET; /* kernel assigns */
qos.bcast.packing = 0x00; /* Sequential */
qos.bcast.framing = 0x00; /* Unframed */
qos.bcast.encryption = 0x00; /* No encryption */
memset(qos.bcast.bcode, 0, sizeof(qos.bcast.bcode));
/* TX path parameters (LE Audio 16_2 preset) */
qos.bcast.out.phy = 0x02; /* 2 Mbps */
qos.bcast.out.sdu = LC3_SDU_SIZE;
qos.bcast.out.interval = SDU_INTERVAL;
qos.bcast.out.latency = 10; /* ms */
qos.bcast.out.rtn = 2; /* retransmissions */
ret = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, sizeof(qos));
if (ret < 0) { perror("setsockopt BT_ISO_QOS"); goto fail; }
/* 4. Connect: triggers LE_Create_BIG inside BlueZ kernel stack.
* iso_bdaddr_type = BDADDR_BREDR signals broadcast mode.
* iso_num_bis / iso_bis[] choose which BIS indices to create. */
dst.iso_family = AF_BLUETOOTH;
dst.iso_bdaddr_type = BDADDR_BREDR; /* broadcast flag */
bacpy(&dst.iso_bdaddr, BDADDR_ANY);
dst.iso_bc_sid = 0x00;
dst.iso_num_bis = 1;
dst.iso_bis[0] = 0x01; /* BIS index 1 (Left channel) */
ret = connect(sk, (struct sockaddr *)&dst, sizeof(dst));
if (ret < 0) { perror("connect (BIG create)"); goto fail; }
printf("BIG created — sending audio frames\n");
/* 5. Write LC3-encoded audio frames (here we send silence) */
for (int i = 0; i < 500; i++) { /* 500 frames = 5 seconds */
/* In a real application: lc3_encode(pcm_buf, frame, LC3_SDU_SIZE) */
ret = write(sk, frame, LC3_SDU_SIZE);
if (ret < 0) { perror("write"); break; }
usleep(SDU_INTERVAL); /* pace to SDU interval */
}
printf("Done — releasing BIG\n");
close(sk);
return 0;
fail:
close(sk);
return 1;
}
Receiving a Broadcast Audio Stream
A Broadcast Sink scans for Extended Advertisements that carry the Broadcast Audio Announcement Service UUID. When it finds one it reads through the advertising chain, gets the BASE and BIGInfo from the Periodic Advertisement, picks the right BIS, and locks on.
The Four-Step Reception Flow
| 1 | Scan for Extended Advertisements — filter on Broadcast Audio Announcement UUID and a valid Broadcast_ID. Also check profile-specific UUIDs (e.g., Public Broadcast Profile) to narrow down relevant streams. |
| 2 | Sync to Periodic Advertising (PA) — use SyncInfo from the AUX_ADV_IND to lock on to the AUX_SYNC_IND train. Read the BASE and BIGInfo from it. Now the Sink knows every stream’s codec, format, and channel layout. |
| 3 | Choose which BIS to receive — match codec config, Audio Location (Left/Right), Context Type, and language against what this device supports. The Acceptor makes this decision autonomously (or it is told by a Commander via BIS_Sync). |
| 4 | Sync to BIG and receive audio — use BIGInfo (hopping sequence + BIS Anchor Points) to lock on to the right BIS. Set up the audio data path. Apply the Presentation Delay so left and right earbuds render audio at the exact same moment. |
BlueZ Code: Scanning and Syncing to a BIS
/*
* broadcast_sink.c
* Connects to a known Broadcast Source and receives BIS audio via ISO sockets.
* BlueZ kernel ISO socket API (kernel 5.14+).
* Build: gcc -o bcast_sink broadcast_sink.c -lbluetooth
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/iso.h>
#define MAX_SDU 200
int main(void)
{
int sk, ret;
struct sockaddr_iso src = {0}, bsrc = {0};
uint8_t buf[MAX_SDU];
ssize_t n;
/* 1. Open ISO socket */
sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_ISO);
if (sk < 0) { perror("socket"); return 1; }
/* 2. Bind to local adapter */
src.iso_family = AF_BLUETOOTH;
src.iso_bdaddr_type = BDADDR_LE_PUBLIC;
bacpy(&src.iso_bdaddr, BDADDR_ANY);
ret = bind(sk, (struct sockaddr *)&src, sizeof(src));
if (ret < 0) { perror("bind"); goto fail; }
/*
* 3. Connect to the Broadcast Source.
* iso_bdaddr = address of the Broadcast Source device
* iso_bdaddr_type = BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM
* iso_bc_sid = SID from ADV_EXT_IND (Advertising Set ID)
* iso_num_bis = how many BIS we want to receive
* iso_bis[] = BIS index values from the BASE
*
* The kernel handles PA sync and BIG sync internally.
* On success, the socket is ready to receive audio frames.
*/
bsrc.iso_family = AF_BLUETOOTH;
bsrc.iso_bdaddr_type = BDADDR_LE_PUBLIC;
str2ba("AA:BB:CC:DD:EE:FF", &bsrc.iso_bdaddr); /* source address */
bsrc.iso_bc_sid = 0x00; /* SID from the primary advertisement */
bsrc.iso_num_bis = 2; /* receive stereo: Left + Right */
bsrc.iso_bis[0] = 0x01; /* BIS index 1 = Left channel */
bsrc.iso_bis[1] = 0x02; /* BIS index 2 = Right channel */
ret = connect(sk, (struct sockaddr *)&bsrc, sizeof(bsrc));
if (ret < 0) { perror("connect (BIG sync)"); goto fail; }
printf("Synced to BIG — receiving audio\n");
/* 4. Read incoming LC3 frames and pass to decoder */
while ((n = read(sk, buf, sizeof(buf))) > 0) {
/*
* Each read() returns one SDU (one LC3 frame per BIS).
* Pass to LC3 decoder:
* lc3_decode(decoder, buf, n, pcm_out, stride);
* Then write pcm_out to ALSA / audio pipeline.
*/
printf("Rx %zd bytes | pass to LC3 decoder\n", n);
}
close(sk);
return 0;
fail:
close(sk);
return 1;
}
BASS — Broadcast Audio Scan Service
A Broadcast Sink can find and receive streams on its own — but that is not a good user experience. A small earbud with no screen needs to independently pick from potentially dozens of broadcast streams nearby. That is impractical. BASS solves this.
BASS is a GATT service that lives inside the Broadcast Sink (the Acceptor). It exposes the Sink’s current state — what streams it knows about, which one it is receiving, whether it needs an encryption key — so a separate device (a phone, a remote, a smartwatch acting as a Commander) can read and control it over a regular ACL connection.
The Two BASS Characteristics
| Characteristic | Properties | Count | What it does |
|---|---|---|---|
| Broadcast Audio Scan Control Point | Write, Write w/o response | One | Commander writes here to give the Acceptor instructions: add or remove a source, change BIS_Sync, provide an encryption key |
| Broadcast Receive State | Read, Notify | One or more | Acceptor reports its current status — which BIG it is synced to, which BIS channels are active, encryption state, current metadata. One instance per BIG the Acceptor can receive simultaneously. |
Control Point Operation Codes
| Opcode | Operation | What happens |
|---|---|---|
| 0x00 | Remote Scan Stopped | Assistant reports it has stopped scanning on the Acceptor’s behalf |
| 0x01 | Remote Scan Started | Assistant reports it is now scanning. Acceptor may stop its own scanning to save power. |
| 0x02 | Add Source | Commander tells Acceptor about a Broadcast Source (address, SID, Broadcast_ID) and which BIS channels to receive (BIS_Sync bitmap) |
| 0x03 | Modify Source | Update an existing source entry. Setting BIS_Sync = 0 stops that stream; setting it = 1 starts it again. |
| 0x04 | Set Broadcast Code | Deliver the 16-byte decryption key for an encrypted BIG along with its Source_ID |
| 0x05 | Remove Source | Delete the source record entirely. Acceptor stops receiving that BIG. |
BIS_Sync — The Most Important Field
BIS_Sync is a 4-byte (32-bit) bitmap sent from the Commander to the Acceptor in the Add Source or Modify Source operations. Each bit position corresponds to a BIS index:
| Bit 0 | Bit 1 | Bit 2 | Bit 3 | Bit 4 | … | Bit 31 |
|---|---|---|---|---|---|---|
| BIS index 1 e.g. Left CH |
BIS index 2 e.g. Right CH |
BIS index 3 | BIS index 4 | BIS index 5 | … | BIS index 32 |
| Set a bit to 1 to receive that BIS. Set to 0 to skip it. BIS_Sync is per-subgroup: only bits from one subgroup should be set at a time (you pick English or Spanish, not both). 0xFFFFFFFF = “no preference” — Acceptor decides which BIS to use. |
||||||
Broadcast Receive State — What the Acceptor Reports Back
| Field | Size | Meaning |
|---|---|---|
| Source_ID | 1 B | Acceptor-assigned local ID for this source record. Not shared with the other earbud — both assign their own. |
| Source_Address + SID + Broadcast_ID | 8 B + 1 B + 3 B | Identifies the Broadcast Source this record refers to |
| PA_Sync_State | 1 B | 0x00=Not synced, 0x01=SyncInfo needed (request to Commander), 0x02=Synced, 0x03=Failed, 0x04=No PAST |
| BIG_Encryption | 1 B | 0x00=No encryption, 0x01=Code needed, 0x02=Decrypting, 0x03=Wrong key (Bad_Code) |
| BIS_Sync_State[i] | 4 B | Same bitmap as BIS_Sync, but showing current state — which BIS channels the Acceptor is actively receiving right now |
| Metadata[i] | Varies | Current Level 2 metadata (audio context, language, etc.) the Acceptor has for this stream |
Commanders — The Smart Remote for Broadcast
Without a Commander, a user with two earbuds would have to manually navigate each earbud’s minimal interface to select a stream, and handling encrypted streams would be nearly impossible. A Commander solves this by acting as a central control point — like a smart TV remote that also knows how to find radio stations and quietly pass the decryption keys to your earbuds.
| COMMANDER (e.g., Phone App or Dedicated Remote) | ACL Link | ACCEPTOR (e.g., Earbud / Hearing Aid) |
|---|---|---|
| Broadcast Assistant Scans for streams. Reads BASE and filters by Acceptor capabilities. Presents list to user. Writes Add Source to BASS. |
⇄ | Scan Delegator (BASS) Solicits Broadcast Assistants. Hosts BASS characteristics. Receives source info and BIS_Sync commands from Commander. |
| CSIP Set Coordinator Discovers all members of a Coordinated Set (e.g., left + right earbud) and sends commands to all of them. |
⇄ | CSIP Set Member Identifies itself as part of a Coordinated Set. Commander uses this to find the matching earbud. |
| VCP Volume Controller Controls volume on each Acceptor in the set. |
⇄ | VCP Volume Renderer + PACS Renders volume. PACS exposes codec capabilities so Commander filters streams by what this device can decode. |
| Broadcast_Code Manager Holds or fetches the decryption key. Sends it via opcode 0x04 (Set Broadcast Code) when Acceptor requests it. |
⇄ | Broadcast Sink Does the actual BIG / BIS sync and LC3 decoding. Reports sync status and encryption state via Broadcast Receive State notifications. |
Scan Delegator — How the Acceptor Solicits Help
The Scan Delegator role lives inside the Broadcast Sink. Its only job is to find Broadcast Assistants and hand them the scanning work. It does this by sending a Solicitation Request — an Extended Advertisement containing the BASS Service UUID. Any Broadcast Assistant that sees it can connect and take over.
Remote Broadcast Scanning — The Full Setup Flow
| Broadcast Assistant (Phone) | Action / Message | Broadcast Sink (Earbud Pair) |
|---|---|---|
| ← Solicitation (AUX_EXT_IND + BASS UUID) | Earbud 1 sends solicitation request | |
| Responds, initiates ACL connect | ACL Connect → | |
| Discovers Coordinated Set membership via CSIP | Read CSIS characteristics → | Earbud 1 reports it is in a set with Earbud 2 |
| Finds and connects to Earbud 2 | ACL Connect → Earbud 2 | |
| Reads PACS on both earbuds — now knows what codecs, locations, and context types they support | Read PACS (both earbuds) → | |
| Reads current BASS Receive States; subscribes to notifications | Discover BASS, Read Receive States → | |
| Starts scanning for Broadcast Sources that match both earbuds’ capabilities | Write Scan Control Point: 0x01 (Scan Started) → | Both earbuds may now stop their own scanning |
| User picks a stream from the list on the phone screen | Write Scan Control Point: 0x02 (Add Source + BIS_Sync) → | Both earbuds receive source identity and sync instruction |
| ← Notify Receive State (PA_Sync=0x02, BIS_Sync active) | Both earbuds notify success — audio flowing |
A Broadcast Assistant can also use PAST (Periodic Advertising Sync Transfer) to hand the PA sync directly to each earbud, instead of making the earbud scan for the periodic advertisement itself. This is faster and more power-efficient — the process is called Scan Offloading.
Broadcast_Codes — Encrypted Private Streams
A Broadcast Source can encrypt its audio using a 16-byte Broadcast_Code. Without this key, a receiver can lock on to the BIG but cannot decode the audio — it hears nothing. This creates a software boundary around the broadcast: only people or devices with the code can listen.
Encryption lifetimes vary widely by use case:
| Use Case | Code Lifetime |
|---|---|
| Coffee shop background music | Permanent — the code stays the same indefinitely |
| Hotel room TV | Per stay — changes when the guest checks out |
| Personal TV at home | Per power cycle — refreshes at each boot so visitors cannot keep the code |
| Phone audio sharing | Per session — brand new code each time you share |
How the Code Gets to the Acceptor
When an Acceptor locks on to an encrypted BIG, it cannot decrypt the audio. It sets BIG_Encryption = 0x01 in its Broadcast Receive State and sends a notification to all connected Broadcast Assistants — essentially asking “does anyone have the key?”
Any Assistant that has the code can respond by writing opcode 0x04 (Set Broadcast Code) to the Scan Control Point with the 16-byte key and the Source_ID. If the Acceptor previously had a wrong key, it sets BIG_Encryption = 0x03 and includes the bad key in the Bad_Code field so Assistants do not waste time re-sending the same wrong key.
Presentation Delay in Broadcast
In unicast, both sides negotiate the Presentation Delay. In broadcast, the Source picks a value and puts it in the BASE. Receivers must use it or fall back to a default. This matters because left and right earbuds need to render audio at exactly the same moment.
| Profile / Rule | Minimum Supported Delay | Notes |
|---|---|---|
| BAP | 40 ms | All Broadcast Receivers must support at least 40 ms. Safe default for Sources. |
| TMAP / HAP | 20 ms | Acceptors qualifying to TMAP or HAP must support 20 ms. Better choice for live audio (lower latency). |
| Fallback rule | 40 ms | If a Source sets a delay that is too low or too high for the Acceptor’s buffers, the Acceptor should fall back to 40 ms to stay in sync with the other earbud. |
Handover Between Unicast and Broadcast
CAP defines two procedures to switch the same audio content between unicast and broadcast without an audible gap. A real-world example: you are listening to TV over a unicast connection, then a friend arrives and you want to share the audio. The TV switches to broadcast mode. Both of you now receive over BIS channels.
Two important rules govern this handover:
- The Streaming Context Types and CCID list from the original unicast stream carry over to the broadcast stream. The original listener keeps full playback control (pause, fast-forward, volume) because the ACL link stays up.
- Friends who join the broadcast only get the audio. They do not inherit control because they never had the unicast connection.
Summary — Key Terms at a Glance
| Term | One-line explanation |
|---|---|
| BIG | Broadcast Isochronous Group — the top-level container for all BIS audio channels from one Source |
| BIS | Broadcast Isochronous Stream — one audio channel inside a BIG (e.g., Left or Right) |
| BASE | Data structure in the Periodic Advertisement: codec, subgroups, BIS indices, metadata — everything a receiver needs to pick a stream |
| BIGInfo | Timing and hopping information in the PA’s ACAD field. Receiver uses this to find BIS Anchor Points. |
| Broadcast_ID | 3-byte random ID for a BIG. Lives in AUX_ADV_IND. Static for the BIG’s lifetime. |
| SID | Advertising Set ID. Lives in ADV_EXT_IND. Does not change between power cycles. Identifies the advertising set. |
| Source_ID | Local ID assigned by the Acceptor. Not shared. Left and right earbuds have different Source_IDs for the same BIG. |
| BASS | GATT service inside the Acceptor. Exposes stream state and receives instructions from Broadcast Assistants. |
| BIS_Sync | 4-byte bitmap from Commander to Acceptor selecting which BIS channels to receive. One subgroup at a time only. |
| Broadcast Assistant | Scans for Broadcast Sources on behalf of the Acceptor and writes source info to BASS |
| Scan Delegator | Role in the Acceptor. Solicits Broadcast Assistants using Extended Advertising containing the BASS UUID. |
| Commander | Device combining Broadcast Assistant + CSIP Set Coordinator + VCP Volume Controller. Acts as the user’s remote control. |
| PAST | Periodic Advertising Sync Transfer. Lets the Broadcast Assistant give the Acceptor direct PA sync without re-scanning. Called Scan Offloading. |
| Broadcast_Code | 16-byte key for encrypting a BIG. Delivered via BASS opcode 0x04 or out-of-band. Lifetime varies by application. |
Continue the LE Audio Series
This post covered Chapter 8 — Broadcast Audio Streams. The series continues with Volume Control Profile, Hearing Access Profile, and Media Control.
