Volume 体系全解:从 VCP 到 AICS 的音量控制
在无线音频的世界里,一场静默却深刻的革命正在进行。
它,就是LE Audio。
这不仅仅是一次技术迭代,而是从底层重新定义声音如何被创造、传输和体验的范式转移。其复杂性令人敬畏——它并非单一技术,而是一套精密的生态系统:全新的LC3编解码器以超凡效率重塑音质与功耗的平衡,多重串流音频让真无线立体声达到前所未有的稳定与同步,而音频广播功能则打破了“一对一”连接的百年窠臼,让声音如电台般自由播撒。
然而,正是这种复杂性,构成了我们必须深入学习它的不可辩驳的理由。未来的声音图景将由它绘制:从下一代真无线耳机、无障碍助听设备到公共场所的沉浸式音频导览、多语言广播,乃至元宇宙中清晰无缝的语音交互。不了解LE Audio,将意味着在即将到来的音频浪潮中失去对话的基石。
这不仅仅关乎技术本身,更关乎我们如何连接彼此,如何感知世界。让我们共同开启这段探索之旅,揭开LE Audio的复杂面纱,看清它为何必将成为未来数年里,每一个科技从业者、音频爱好者乃至普通用户都无法忽视的关键命题。
接下来的系列文章,我们将逐步拆解这座精妙的技术大厦。
同时我也录制了一系列的Le audio视频,有兴趣的可以咨询,我会带领你们入门Le audio!翻过大山,眼下皆是风景!!!
------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------
目录
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: 音量调节没反应?
检查点:
- VCS 是否发现成功?
- Change Counter 是否匹配?
- 是否有其他设备在控制?
Q2: 左右耳音量不同步?
解决方案:
- 使用 CSIP 协调集锁定
- 使用 CAP Commander 统一控制
- 检查 Change Counter 同步
Q3: 麦克风增益调节范围?
注意:
- 增益范围由设备定义(AICS Gain Properties)
- 可能是 -20dB ~ +20dB
- 也可能是 0 ~ 100(抽象值)
- 需要读取 Gain Properties 确定范围
总结
VCP 三层控制
|
层级 |
服务 |
控制对象 |
范围 |
|
主音量 |
VCS |
整个设备 |
0-255 |
|
音量偏移 |
VOCS |
每个输出 |
-255 ~ +255 |
|
输入增益 |
AICS |
每个输入 |
设备定义 |
关键概念
- Change Counter: 状态同步机制
- Volume Rendering: 实际执行音量调节的设备
- Ordered Access: 协调集音量同步
- Gain Mode: 手动/自动增益控制
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)