一、音频采集基础
1.1 音频采集流程
音频采集是RTC的起点,采集质量直接决定最终通话效果。
完整采集链路:
关键参数:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 采样率 | 48kHz | 全带音频,支持所有频段 |
| 位深 | 16bit | CD音质,动态范围96dB |
| 声道数 | 单声道 | 语音场景,节省带宽 |
| 帧长 | 10ms/20ms | 平衡延迟与效率 |
1.2 麦克风选择与配置
麦克风类型:
- 驻极体麦克风:成本低,灵敏度一般
- MEMS麦克风:体积小,性能好,移动端主流
- 电容麦克风:灵敏度高,专业场景
Android配置示例:
AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.VOICE_COMMUNICATION, // 通信场景优化
48000, // 采样率
AudioFormat.CHANNEL_IN_MONO, // 单声道
AudioFormat.ENCODING_PCM_16BIT, // 16位
bufferSize // 缓冲区大小
);
iOS配置示例:
let audioSession = AVAudioSession.sharedInstance()
try audioSession.setCategory(.playAndRecord, mode: .voiceChat)
try audioSession.setPreferredSampleRate(48000)
try audioSession.setPreferredIOBufferDuration(0.02) // 20ms
1.3 音频源选择策略
Android AudioSource选择:
| 类型 | 适用场景 | 特点 |
|---|---|---|
| DEFAULT | 通用 | 系统默认 |
| MIC | 录音 | 原始麦克风 |
| VOICE_UPLINK | 通话上行 | 需要权限 |
| VOICE_DOWNLINK | 通话下行 | 需要权限 |
| VOICE_CALL | 双向通话 | 需要权限 |
| VOICE_COMMUNICATION | VoIP通信 | 推荐,已做通信优化 |
| CAMCORDER | 摄像 | 摄像场景 |
iOS AVAudioSessionMode选择:
| 模式 | 适用场景 |
|---|---|
| default | 通用 |
| voiceChat | VoIP通话,推荐 |
| videoChat | 视频通话 |
| gameChat | 游戏语音 |
| measurement | 测量,最小处理 |
二、音频预处理:3A算法
2.1 回声消除(AEC/AECM)
问题场景:
用户A说话 → 扬声器播放 → 麦克风采集 → 发送给用户B → 用户B听到回声
AEC原理:
远端参考信号(扬声器播放) → 自适应滤波器 → 估计回声 → 从采集信号中减去
WebRTC AEC实现:
- 频域自适应滤波(FDAF)
- 延迟估计与对齐
- 双讲检测(双方同时说话)
- 非线性处理(残余回声抑制)
关键参数:
// AEC配置
struct AecConfig {
int nlp_mode; // 非线性处理模式
int skew_mode; // 抖动处理
int metrics_mode; // 指标输出
int delay_logging_mode; // 延迟日志
};
延迟对齐的重要性:
延迟估计不准 → 滤波器失效 → 回声消除失败
常见延迟来源:
- 硬件延迟:5-50ms
- 系统延迟:10-100ms
- 缓冲延迟:可配置
2.2 噪声抑制(NS/ANS)
噪声类型:
- 稳态噪声:风扇、空调、白噪声
- 非稳态噪声:键盘、敲门、狗叫
- 混响:房间反射
WebRTC NS算法:
- 基于统计模型的噪声估计
- 频域处理,分频段抑制
- 语音存在概率估计
- 过抑制与欠抑制平衡
噪声抑制级别:
enum NsLevel {
kNsVeryLow = 0, // 轻噪声环境
kNsLow = 1, // 低噪声
kNsModerate = 2, // 中等噪声
kNsHigh = 3, // 高噪声
kNsVeryHigh = 4 // 极高噪声
};
效果评估:
| 指标 | 说明 | 目标 |
|---|---|---|
| 噪声抑制量 | 降低多少dB | >20dB |
| 语音失真 | 处理后语音质量 | PESQ > 3.5 |
| 计算复杂度 | CPU占用 | <5% |
2.3 自动增益控制(AGC)
问题场景:
- 用户说话声音忽大忽小
- 不同用户音量差异大
- 麦克风灵敏度不同
AGC原理:
WebRTC AGC模式:
enum AgcMode {
kAgcUnchanged = 0, // 不变
kAgcAdaptiveAnalog = 1, // 模拟自适应(调整硬件增益)
kAgcAdaptiveDigital = 2, // 数字自适应(软件增益)
kAgcFixedDigital = 3 // 固定数字增益
};
关键参数:
struct AgcConfig {
int target_level_dbfs; // 目标电平,推荐-3
int compression_gain_db; // 压缩增益,推荐9
int limiter_enable; // 限幅器,推荐开启
};
数字AGC vs 模拟AGC:
| 维度 | 数字AGC | 模拟AGC |
|---|---|---|
| 实现方式 | 软件增益 | 硬件增益 |
| 动态范围 | 有限 | 更大 |
| 噪声放大 | 会放大噪声 | 不放大噪声 |
| 兼容性 | 好 | 依赖硬件 |
2.4 语音检测(VAD)
作用:
- 判断当前是否有人说话
- 节省带宽(静音时不发送)
- 辅助其他算法(如AGC只在有语音时调整)
WebRTC VAD实现:
// VAD实例
VadInst* vad = WebRtcVad_Create();
WebRtcVad_Init(vad);
WebRtcVad_set_mode(vad, kVadAggressive); // 激进模式
// 检测
int result = WebRtcVad_Process(vad, 48000, audio_frame, frame_size);
// result: 1 = 语音, 0 = 噪声
VAD模式:
| 模式 | 灵敏度 | 误检率 | 漏检率 |
|---|---|---|---|
| 质量模式 | 低 | 高 | 低 |
| 低激进 | 中 | 中 | 中 |
| 中激进 | 中高 | 低 | 中 |
| 高激进 | 高 | 低 | 高 |
三、高级音频处理
3.1 混响抑制
问题: 房间反射导致声音"空旷"、"有回音"
混响模型:
y(t) = x(t) + Σ h(i) * x(t-i) // h为房间冲激响应
处理方法:
- 声学回声消除(AEC):已包含部分混响处理
- 专用去混响:估计房间响应并反卷积
- 频域处理:衰减高频混响成分
WebRTC中的处理:
AEC的非线性处理(NLP)会抑制残余混响。
3.2 多麦克风处理
波束成形(Beamforming):
利用多个麦克风的空间信息,增强特定方向的声音。
麦克风阵列 → 延迟补偿 → 加权求和 → 波束成形输出
常见阵列形式:
- 线性阵列:一维,水平方向增强
- 圆形阵列:二维,全向增强
- 球形阵列:三维,空间增强
移动端应用:
现代手机多配备双麦克风,可用于:
- 噪声参考(一个主麦克风,一个噪声参考)
- 空间滤波
- 更好的AEC效果
3.3 3A处理顺序
WebRTC标准处理链:
采集音频 → AEC → AGC → NS → VAD → 输出
为什么这个顺序?
- AEC最先:需要原始信号,避免其他处理影响
- AGC次之:在干净信号上调整增益
- NS再次:最后抑制噪声,避免影响AEC参考
- VAD最后:在处理后判断语音
四、平台差异与适配
4.1 Android平台
AudioRecord延迟优化:
// 使用低延迟配置
AudioRecord record = new AudioRecord(
MediaRecorder.AudioSource.VOICE_COMMUNICATION,
48000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minBufferSize
);
// 设置性能模式(API 26+)
if (Build.VERSION.SDK_INT >= 26) {
AudioRecord.Builder builder = new AudioRecord.Builder()
.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION)
.setAudioFormat(new AudioFormat.Builder()
.setSampleRate(48000)
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setChannelMask(AudioFormat.CHANNEL_IN_MONO)
.build())
.setBufferSizeInBytes(minBufferSize)
.setPerformanceMode(AudioRecord.PERFORMANCE_MODE_LOW_LATENCY);
}
硬件AEC支持检测:
// 检查是否支持硬件AEC
AcousticEchoCanceler aec = AcousticEchoCanceler.create(audioSessionId);
if (aec != null) {
// 使用硬件AEC
aec.setEnabled(true);
} else {
// 使用软件AEC
}
4.2 iOS平台
AVAudioSession配置:
let session = AVAudioSession.sharedInstance()
// 设置类别和模式
try session.setCategory(.playAndRecord,
mode: .voiceChat,
options: [.allowBluetooth, .defaultToSpeaker])
// 设置首选采样率
try session.setPreferredSampleRate(48000)
// 设置首选IO缓冲区(影响延迟)
try session.setPreferredIOBufferDuration(0.01) // 10ms
// 激活会话
try session.setActive(true)
Voice Processing IO(推荐):
// 使用Voice Processing IO,内置AEC/AGC/NS
let audioUnit = AudioUnit(
componentDescription: AudioComponentDescription(
componentType: kAudioUnitType_Output,
componentSubType: kAudioUnitSubType_VoiceProcessingIO,
...
)
)
4.3 平台差异对比
| 维度 | Android | iOS |
|---|---|---|
| 硬件AEC | 部分设备支持 | VoiceProcessingIO内置 |
| 延迟 | 20-100ms | 5-20ms |
| 3A质量 | 需软件实现 | 系统提供高质量实现 |
| 权限 | RECORD_AUDIO | NSMicrophoneUsageDescription |
| 后台采集 | 需前台服务 | 需后台模式配置 |
五、音频处理效果评估
5.1 主观评估
MOS(Mean Opinion Score):
| 分数 | 质量 | 描述 |
|---|---|---|
| 5 | 优 | 无感知失真 |
| 4 | 良 | 有轻微失真但不烦人 |
| 3 | 中 | 有失真,轻微烦人 |
| 2 | 差 | 失真烦人 |
| 1 | 劣 | 极度失真,无法通信 |
5.2 客观评估
PESQ(Perceptual Evaluation of Speech Quality):
- 范围:-0.5 到 4.5
- 需要原始参考信号
- 适用于窄带(8kHz)和宽带(16kHz)
POLQA(Perceptual Objective Listening Quality Analysis):
- PESQ的升级版
- 支持超宽带(48kHz)
- 考虑延迟影响
VISQOL:
- Google开源的质量评估工具
- 支持全带音频
- 无需原始参考(非侵入式)
5.3 实时监控指标
采集质量监控:
struct AudioCaptureStats {
int sample_rate; // 实际采样率
int num_channels; // 声道数
float audio_level; // 音频电平(dBFS)
float noise_level; // 噪声电平
float snr; // 信噪比
bool voice_detected; // 是否检测到语音
int64_t total_samples; // 总采样数
int underrun_count; // 欠载次数
};
六、本章小结
音频采集与处理是语音质量的第一道关卡。本章我们深入探讨了:
- 采集基础:采样率、位深、声道配置
- 3A算法:AEC、ANS、AGC、VAD的原理与实现
- 高级处理:混响抑制、多麦克风、处理顺序
- 平台适配:Android/iOS的差异与优化
- 效果评估:主观MOS与客观PESQ/POLQA
下一章,我们将进入音频编码环节,探讨如何在保证质量的前提下高效压缩音频数据。