在无线音频的世界里,一场静默却深刻的革命正在进行。

它,就是LE Audio。

这不仅仅是一次技术迭代,而是从底层重新定义声音如何被创造、传输和体验的范式转移。其复杂性令人敬畏——它并非单一技术,而是一套精密的生态系统:全新的LC3编解码器以超凡效率重塑音质与功耗的平衡,多重串流音频让真无线立体声达到前所未有的稳定与同步,而音频广播功能则打破了“一对一”连接的百年窠臼,让声音如电台般自由播撒。

然而,正是这种复杂性,构成了我们必须深入学习它的不可辩驳的理由。未来的声音图景将由它绘制:从下一代真无线耳机、无障碍助听设备到公共场所的沉浸式音频导览、多语言广播,乃至元宇宙中清晰无缝的语音交互。不了解LE Audio,将意味着在即将到来的音频浪潮中失去对话的基石。

这不仅仅关乎技术本身,更关乎我们如何连接彼此,如何感知世界。让我们共同开启这段探索之旅,揭开LE Audio的复杂面纱,看清它为何必将成为未来数年里,每一个科技从业者、音频爱好者乃至普通用户都无法忽视的关键命题。

接下来的系列文章,我们将逐步拆解这座精妙的技术大厦。

同时我也录制了一系列的Le audio视频,有兴趣的可以咨询,我会带领你们入门Le audio!翻过大山,眼下皆是风景!!!

------------------------------------------------------------------------------------------------------------------------------------------

视频链接:https://item.taobao.com/item.htm?id=1001969040805&mi_id=000032T4qZX9WZoRwX6YbxlNUaZOfOI6XoxDx0jxsfnwlEc&spm=a21xtw.29178619.0.0

---------------------------------------------------------------------------------------------------------------------------------

目录

  1. LE Audio 音量体系概览
  2. VCS:主音量控制
  3. VOCS:音量偏移控制
  4. AICS:音频输入控制
  5. VCP 角色与流程
  6. 多设备音量同步
  7. 实战代码示例

LE Audio 音量体系概览

三层音量控制架构

┌─────────────────────────────────────────────────────────┐
│  第一层: 主音量控制 (VCS)                                 │
│  ├─ Volume Setting: 0-255                               │
│  ├─ Mute State: Unmuted/Muted/Disabled                  │
│  └─ 作用于整个设备                                       │
├─────────────────────────────────────────────────────────┤
│  第二层: 音量偏移 (VOCS)                                  │
│  ├─ Volume Offset: -255 ~ +255                          │
│  ├─ 独立控制每个输出                                      │
│  └─ 可用于平衡多扬声器                                    │
├─────────────────────────────────────────────────────────┤
│  第三层: 输入增益 (AICS)                                  │
│  ├─ Gain Setting: 根据设备定义                          │
│  ├─ Gain Mode: Manual/Automatic                         │
│  └─ 控制麦克风输入增益                                   │
└─────────────────────────────────────────────────────────┘

Profile 关系

VCP (Volume Control Profile)
├── VCS (Volume Control Service)
│   ├── Volume State (Volume Setting + Mute + Change Counter)
│   ├── Volume Flags (Persisted, etc.)
│   └── Volume Control Point
│
├── VOCS (Volume Offset Control Service) × N
│   ├── Volume Offset State
│   ├── Audio Location
│   └── Volume Offset Control Point
│
└── AICS (Audio Input Control Service) × N
    ├── Audio Input State (Gain + Mute + Mode)
    ├── Gain Setting Properties
    ├── Audio Input Type
    └── Audio Input Control Point

VCS:主音量控制

Volume State 结构

typedef struct {
    uint8_t volume_setting;      // 0-255, 255 = 100%
    uint8_t mute;                // 0=Not Muted, 1=Muted, 2=Disabled
    uint8_t change_counter;      // 状态同步计数器
} vcs_volume_state_t;

Volume Setting

值范围: 0 - 255

常用参考值:
  0   = 静音
  64  = 25%
  128 = 50%
  192 = 75%
  255 = 100%

注意: 实际音量曲线由设备实现决定,可能是线性或对数

Mute 状态

typedef enum {
    MUTE_NOT_MUTED  = 0x00,  // 未静音
    MUTE_MUTED      = 0x01,  // 已静音
    MUTE_DISABLED   = 0x02,  // 静音功能被禁用
} vcs_mute_t;

Volume Control Point 操作

typedef enum {
    VCS_OP_RELATIVE_VOLUME_DOWN = 0x00,           // 音量减一步
    VCS_OP_RELATIVE_VOLUME_UP = 0x01,             // 音量增一步
    VCS_OP_UNMUTE_RELATIVE_VOLUME_DOWN = 0x02,    // 解除静音并减
    VCS_OP_UNMUTE_RELATIVE_VOLUME_UP = 0x03,      // 解除静音并增
    VCS_OP_SET_ABSOLUTE_VOLUME = 0x04,            // 设置绝对音量
    VCS_OP_UNMUTE = 0x05,                         // 解除静音
    VCS_OP_MUTE = 0x06,                           // 静音
} vcs_control_op_t;

Volume Flags

typedef struct {
    uint8_t volume_setting_persisted : 1;  // 音量是否持久化
    uint8_t reserved : 7;
} vcs_volume_flags_t;

VOCS:音量偏移控制

为什么需要 VOCS?

场景: 多扬声器系统

场景: 家庭影院

        ┌─────────────────────────────────────┐
        │            手机 (Controller)         │
        │            Volume = 80%              │
        └──────────────────┬──────────────────┘
                           │
           ┌───────────────┼───────────────┐
           ↓               ↓               ↓
      ┌─────────┐    ┌─────────┐    ┌─────────┐
      │ 左前置   │    │ 中置    │    │ 右前置   │
      │ +0dB    │    │ +2dB    │    │ +0dB    │
      └─────────┘    └─────────┘    └─────────┘
      
      每个扬声器可以独立调节偏移量
      实现声场平衡

Volume Offset State

typedef struct {
    int16_t volume_offset;       // -255 ~ +255
    uint8_t change_counter;
} vocs_offset_state_t;

// 偏移量解释
// -255 = -100% 相对偏移
//    0 = 无偏移
// +255 = +100% 相对偏移

// 实际音量 = 主音量 + 偏移量(设备实现相关)

Audio Location

typedef enum {
    AUDIO_LOCATION_FRONT_LEFT      = 0x00000001,
    AUDIO_LOCATION_FRONT_RIGHT     = 0x00000002,
    AUDIO_LOCATION_FRONT_CENTER    = 0x00000004,
    AUDIO_LOCATION_LOW_FREQ_EFFECT = 0x00000008,
    AUDIO_LOCATION_BACK_LEFT       = 0x00000010,
    AUDIO_LOCATION_BACK_RIGHT      = 0x00000020,
    AUDIO_LOCATION_SIDE_LEFT       = 0x00000400,
    AUDIO_LOCATION_SIDE_RIGHT      = 0x00000800,
    // ... 更多位置定义
} audio_location_t;

Audio Output Description

// 用户可读的输出描述
// 例如: "Left Speaker", "Right Earbud", "Subwoofer"
char output_description[64];

AICS:音频输入控制

输入类型 (Audio Input Type)

typedef enum {
    AICS_INPUT_TYPE_UNSPECIFIED = 0x00,
    AICS_INPUT_TYPE_BLUETOOTH = 0x01,       // 蓝牙输入
    AICS_INPUT_TYPE_MICROPHONE = 0x02,      // 麦克风
    AICS_INPUT_TYPE_AUXILIARY = 0x03,       // 辅助输入
    AICS_INPUT_TYPE_LOCAL = 0x04,           // 本地输入
    // 0x05-0xFE: Reserved
    // 0xFF: RFU
} aics_input_type_t;

Audio Input State

typedef struct {
    int8_t  gain_setting;        // 增益值(设备定义范围)
    uint8_t mute;                // 0=Not Muted, 1=Muted, 2=Disabled
    uint8_t gain_mode;           // 0=Manual, 1=Automatic
    uint8_t change_counter;
} aics_input_state_t;

Gain Setting Properties

typedef struct {
    uint8_t gain_units;          // 增益单位 (0.1dB, 1dB, etc.)
    int8_t  gain_setting_min;    // 最小增益
    int8_t  gain_setting_max;    // 最大增益
} aics_gain_properties_t;

// 示例配置
// Units: 1 dB
// Min: -20 dB
// Max: +20 dB
// Range: 41 steps (0.5dB per step in some devices)

Gain Mode

typedef enum {
    GAIN_MODE_MANUAL = 0x00,      // 手动增益
    GAIN_MODE_AUTOMATIC = 0x01,   // AGC 自动增益控制
} aics_gain_mode_t;

Audio Input Control Point

typedef enum {
    AICS_OP_SET_GAIN_SETTING = 0x01,
    AICS_OP_UNMUTE = 0x02,
    AICS_OP_MUTE = 0x03,
    AICS_OP_SET_MANUAL_MODE = 0x04,
    AICS_OP_SET_AUTOMATIC_MODE = 0x05,
} aics_control_op_t;

// Set Gain Setting 参数
typedef struct {
    uint8_t change_counter;
    int8_t  gain_setting;
} aics_set_gain_param_t;

VCP 角色与流程

角色定义

┌─────────────────────────────────────────┐
│           Volume Renderer               │
│           (音量渲染器)                   │
│  ├─ 耳机、音箱、助听器                   │
│  ├─ 实现 VCS/VOCS/AICS Server           │
│  └─ 实际执行音量调节                     │
└─────────────────────────────────────────┘
                    ▲
                    │ GATT Read/Write/Notify
                    │
┌─────────────────────────────────────────┐
│          Volume Controller              │
│          (音量控制器)                    │
│  ├─ 手机、平板、电视                     │
│  ├─ 实现 VCS/VOCS/AICS Client           │
│  └─ 发送音量控制命令                     │
└─────────────────────────────────────────┘

发现流程

Volume Controller                    Volume Renderer
        │                                   │
        │─── Discover VCS ────────────────▶│
        │◄──────────── Success ────────────│
        │                                   │
        │─── Read Volume State ───────────▶│
        │◄────────── Volume=128, Mute=0 ───│
        │                                   │
        │─── Subscribe Volume State ──────▶│
        │◄────────── Notification Enabled ─│
        │                                   │
        │─── Discover VOCS (instances) ───▶│
        │◄────────── VOCS 0, 1, 2 found ───│
        │                                   │
        │─── Read VOCS State ─────────────▶│
        │◄────────── Offset=0, Location=L ─│
        │                                   │
        │─── Discover AICS (instances) ───▶│
        │◄────────── AICS 0, 1 found ──────│
        │                                   │
        │─── Read AICS State ─────────────▶│
        │◄────────── Gain=10, Mute=0 ──────│

音量控制流程

【设置绝对音量】

Controller                           Renderer
   │                                     │
   │─── Write Volume Control Point ───▶│
   │     OP: Set Absolute Volume        │
   │     Volume: 192 (75%)              │
   │◄─────────── Success ──────────────│
   │                                     │
   │◄────────── Notify: Volume=192 ────│  State changed
   │                                     │
   │  实际音量调节到 75%                │

【相对音量调节】

Controller                           Renderer
   │                                     │
   │─── Write Volume Control Point ───▶│
   │     OP: Relative Volume Up         │
   │◄─────────── Success ──────────────│
   │                                     │
   │◄────────── Notify: Volume=200 ────│
   │                                     │

【静音控制】

Controller                           Renderer
   │                                     │
   │─── Write Volume Control Point ───▶│
   │     OP: Mute                       │
   │◄─────────── Success ──────────────│
   │                                     │
   │◄────────── Notify: Mute=1 ────────│
   │                                     │
   │  设备静音                           │

多设备音量同步

场景:TWS 耳机音量同步

问题: 调节左耳音量,右耳如何同步?

方案1: CSIP Ordered Access
┌─────────┐                  ┌─────────┐
│  手机    │                  │  左耳    │
│ (CAP    │                  │ (Set    │
│Commander)│                  │Member 1)│
└────┬────┘                  └─────────┘
     │                              │
     │─── Lock Set ────────────────▶│
     │                              │
     │─── Set Volume (Ordered) ────▶│──┐
     │                              │  │
     │◄────────── Success ──────────│  │
     │                              │  │
     │─── Set Volume (Ordered) ───────┼──▶┌─────────┐
     │                              │  │  │  右耳    │
     │◄────────── Success ─────────────┘  │ (Set    │
     │                                  │  │Member 2)│
     │─── Unlock Set ────────────────────▶└─────────┘
     │                                  │
     └──────────────────────────────────┘

方案2: CAP Acceptor
┌─────────┐                  ┌─────────┐
│  左耳    │◄─── 音量调节 ─────│  手机    │
│ (CAP    │                  │ (CAP    │
│Acceptor)│◄─── 同步命令 ─────│Commander)│
└────┬────┘                  └────┬────┘
     │                            │
     └──────── 同步 ─────────────▶└────────▶┌─────────┐
                                            │  右耳    │
                                            │ (CAP    │
                                            │Acceptor) │
                                            └─────────┘

Change Counter 同步

TWS 左右耳音量同步机制:

1. 手机设置左耳音量 = 128
   - 左耳 Volume State Notify (Counter=5)
   
2. 手机设置右耳音量 = 128
   - 右耳 Volume State Notify (Counter=5)
   
3. 如果左右耳 Change Counter 不一致
   - 表示有设备未同步
   - 需要重新读取状态

实战代码示例

初始化 VCP

#include "vcp.h"

static vcp_callbacks_t vcp_cbs = {
    .discover_complete = on_vcp_discovered,
    .volume_state_changed = on_volume_changed,
    .offset_changed = on_offset_changed,
    .gain_changed = on_gain_changed,
};

void vcp_init(void)
{
    int err = vcp_init(&vcp_cbs);
    if (err) {
        printf("VCP init failed: %d\n", err);
        return;
    }
}

发现音量服务

void discover_volume_service(bap_conn_handle_t conn)
{
    vcp_handle_t vcp;
    
    int err = vcp_discover(conn, &vcp, on_vcp_discovered, NULL);
    if (err) {
        printf("VCP discover failed: %d\n", err);
        return;
    }
}

void on_vcp_discovered(vcp_handle_t vcp, int err, void *user_data)
{
    if (err) {
        printf("VCP discovery failed\n");
        return;
    }
    
    printf("VCP discovered\n");
    
    // 读取当前音量状态
    vcs_volume_state_t state;
    vcp_get_volume_state(vcp, &state);
    
    printf("Current volume: %d, Mute: %d\n", 
           state.volume_setting, state.mute);
}

设置音量

void set_volume(vcp_handle_t vcp, uint8_t volume)
{
    int err = vcp_set_absolute_volume(vcp, volume, 
                                       on_volume_set, NULL);
    if (err) {
        printf("Set volume failed: %d\n", err);
        return;
    }
}

void on_volume_set(int err, void *user_data)
{
    if (err) {
        printf("Volume set failed\n");
    } else {
        printf("Volume set successfully\n");
    }
}

void on_volume_changed(vcp_handle_t vcp, 
                       const vcs_volume_state_t *state,
                       void *user_data)
{
    printf("Volume changed: %d, Mute: %d\n",
           state->volume_setting, state->mute);
    
    // 更新 UI
    ui_update_volume(state->volume_setting);
}

设置音量偏移

void set_output_volume(vcp_handle_t vcp, 
                       uint8_t output_id, 
                       int16_t offset)
{
    int err = vcp_set_volume_offset(vcp, output_id, offset,
                                     on_offset_set, NULL);
    if (err) {
        printf("Set offset failed: %d\n", err);
    }
}

void on_offset_changed(vcp_handle_t vcp, uint8_t output_id,
                       int16_t offset, void *user_data)
{
    printf("Output %d offset changed: %d\n", output_id, offset);
}

输入增益控制

void set_microphone_gain(vcp_handle_t vcp,
                         uint8_t input_id,
                         int8_t gain)
{
    int err = vcp_set_input_gain(vcp, input_id, gain,
                                  on_gain_set, NULL);
    if (err) {
        printf("Set gain failed: %d\n", err);
    }
}

void mute_microphone(vcp_handle_t vcp, uint8_t input_id)
{
    int err = vcp_set_input_mute(vcp, input_id, true,
                                  on_mute_set, NULL);
    if (err) {
        printf("Mute failed: %d\n", err);
    }
}

void on_gain_changed(vcp_handle_t vcp, uint8_t input_id,
                     int8_t gain, void *user_data)
{
    printf("Input %d gain changed: %d dB\n", input_id, gain);
}

常见问题

Q1: 音量调节没反应?

检查点:

  1. VCS 是否发现成功?
  2. Change Counter 是否匹配?
  3. 是否有其他设备在控制?

Q2: 左右耳音量不同步?

解决方案:

  1. 使用 CSIP 协调集锁定
  2. 使用 CAP Commander 统一控制
  3. 检查 Change Counter 同步

Q3: 麦克风增益调节范围?

注意:

  • 增益范围由设备定义(AICS Gain Properties)
  • 可能是 -20dB ~ +20dB
  • 也可能是 0 ~ 100(抽象值)
  • 需要读取 Gain Properties 确定范围

总结

VCP 三层控制

层级

服务

控制对象

范围

主音量

VCS

整个设备

0-255

音量偏移

VOCS

每个输出

-255 ~ +255

输入增益

AICS

每个输入

设备定义

关键概念

  1. Change Counter: 状态同步机制
  2. Volume Rendering: 实际执行音量调节的设备
  3. Ordered Access: 协调集音量同步
  4. Gain Mode: 手动/自动增益控制
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐