HiFi 音频产品 Android 软件架构之总体设计
第一部分:Android 音频系统全景与 HiFi 架构概览
1.1 核心内容
-
Android 音频系统架构概览 (Audio Framework → HAL → Driver)
-
HiFi 音频系统的核心需求:低延迟、高采样率、bit-perfect 输出、多通道支持
-
整体架构设计:AudioFlinger → AudioPolicy → AudioFlinger → Audio HAL → Kernel
1.2 流程图
[Android 应用层] ├── 音乐播放器 (ExoPlayer) → AudioTrack / AudioRecord ├── 流媒体播放 (HLS/MPD) → MediaPlayer / MediaCodec ├── 录音应用 (Recorder) → AudioRecord └── 音频处理 (AudioProcessor) → Effect ↓ [Android Framework 层] ├── AudioFlinger (核心服务) → 音频流管理、混音、路由 ├── AudioPolicy → 设备策略、路由策略 ├── AudioMixer → 混音器 (Downmix, Resample) └── AudioEffect → 音频效果 (EQ, Reverb, Compressor) ↓ [Android HAL 层] ├── Audio HAL → 音频硬件抽象接口 ├── TinyALSA → 用户空间 ALSA 封装 └── Audio HAL 实现 (Vendor) → 具体音频硬件适配 ↓ [Linux Kernel 层] ├── ALSA Core → 音频核心层 ├── ASoc (ALSA SoC) → 嵌入式音频驱动框架 ├── I2S/SPDIF/USB 控制器 → 音频数据接口 └── DMA → 数据传输 ↓ [HiFi 硬件设备] ├── USB Audio DAC → USB 音频解码器 ├── I2S DAC → I2S 音频解码器 ├── SPDIF (同轴/光纤) → 数字音频接口 └── 网络音频 (RTP/RTSP) → 网络音频流
1.3 软件设计模式树形分析
Android HiFi 音频架构设计模式 ├── 工厂模式 (Factory Pattern) │ ├── AudioTrack/AudioRecord 的创建 │ ├── AudioEffect 实例创建 │ └── Audio HAL 客户端创建 ├── 适配器模式 (Adapter Pattern) │ ├── AudioFlinger 适配 AudioPolicy │ ├── Audio HAL 适配具体硬件 │ └── TinyALSA 适配 ALSA 接口 ├── 策略模式 (Strategy Pattern) │ ├── AudioPolicy 选择路由策略 │ ├── AudioMixer 混音策略 │ └── AudioFlinger 线程策略 ├── 观察者模式 (Observer Pattern) │ ├── AudioFlinger 观察音频流变化 │ └── AudioPolicy 观察设备变化 ├── 状态模式 (State Pattern) │ └── AudioFlinger 线程状态 (停止/运行/暂停) └── 模板方法模式 (Template Method Pattern) ├── AudioFlinger 音频流处理流程 └── Audio HAL open/close 流程
1.4 核心数据结构
/**
* @struct AudioFlingerConfig
* @brief AudioFlinger 全局配置结构。
*/
struct AudioFlingerConfig {
uint32_t sample_rate; /**< 全局采样率 (Hz) */
uint32_t frame_size; /**< 帧大小 (字节) */
uint32_t buffer_size; /**< 缓冲区大小 (帧数) */
uint32_t latency_us; /**< 目标延迟 (微秒) */
uint32_t period_size; /**< 周期大小 (帧数) */
uint32_t period_count; /**< 周期数量 */
bool force_16bit; /**< 是否强制 16 位 */
bool force_48k; /**< 是否强制 48kHz */
bool allow_bit_perfect; /**< 是否允许 bit-perfect 输出 */
bool support_dsd; /**< 是否支持 DSD */
bool support_hdmi; /**< 是否支持 HDMI 音频 */
bool support_spdif; /**< 是否支持 SPDIF */
bool support_usb_audio; /**< 是否支持 USB 音频 */
};
/**
* @struct HiFiAudioContext
* @brief HiFi 音频全局上下文。
*/
struct HiFiAudioContext {
AudioFlinger *flinger; /**< AudioFlinger 实例 */
AudioPolicy *policy; /**< AudioPolicy 实例 */
AudioMixer *mixer; /**< 混音器实例 */
AudioEffectChain *effect_chain; /**< 效果链 */
AudioHAL *hal; /**< Audio HAL 实例 */
TinyALSA *tinyalsa; /**< TinyALSA 实例 */
sp<AudioTrack> *track; /**< AudioTrack 实例 */
sp<AudioRecord> *record; /**< AudioRecord 实例 */
Mutex lock; /**< 互斥锁 */
Condition cond; /**< 条件变量 */
bool is_initialized; /**< 是否已初始化 */
bool is_running; /**< 是否运行 */
};
1.5 核心代码框架
#include <system/audio.h>
#include <media/AudioFlinger.h>
#include <media/AudioPolicy.h>
#include <media/AudioMixer.h>
#include <hardware/audio.h>
#include <tinyalsa/asoundlib.h>
class HiFiAudioSystem {
public:
HiFiAudioSystem();
~HiFiAudioSystem();
/**
* @brief 初始化 HiFi 音频系统。
*/
int init(const HiFiAudioContext &config);
/**
* @brief 启动音频播放。
*/
int start_playback();
/**
* @brief 停止音频播放。
*/
int stop_playback();
/**
* @brief 切换输出设备。
*/
int switch_output_device(audio_devices_t device);
/**
* @brief 设置 bit-perfect 模式。
*/
int set_bit_perfect_mode(bool enable);
/**
* @brief 设置 DSD 支持。
*/
int set_dsd_mode(bool enable);
private:
sp<AudioFlinger> flinger;
sp<AudioPolicy> policy;
sp<AudioMixer> mixer;
sp<AudioEffectChain> effect_chain;
sp<AudioHAL> hal;
sp<TinyALSA> tinyalsa;
sp<AudioTrack> track;
sp<AudioRecord> record;
Mutex lock;
Condition cond;
bool initialized;
bool running;
bool bit_perfect_mode;
bool dsd_mode;
};
1.6 HiFi 音频系统设计核心难点
1.6.1 延迟与性能的平衡
现象:降低延迟导致 CPU 负载增加,音质受损。
核心矛盾:延迟与缓冲区大小成反比。缓冲区小,延迟低,但周期频繁,CPU 负载高。缓冲区大,延迟高,但性能好。
调试方法:
-
使用
sched_setscheduler提升音频线程优先级。 -
调整
AudioFlinger的period_size和period_count。 -
监控
latency_us与buffer_size的关系。
1.6.2 Bit-perfect 输出挑战
现象:即使使用 raw 模式,音频数据仍被处理。
核心矛盾:Android 系统默认对音频数据进行重采样、格式转换和混音,破坏 bit-perfect。
解决方法:
-
在
AudioPolicy中禁用系统重采样。 -
使用
raw模式跳过 AudioMixer。 -
确保 HAL 层不进行任何数据处理。
1.6.3 多声道与高采样率
现象:设备支持 192kHz/24bit,但系统只能输出 48kHz/16bit。
核心矛盾:Android 默认使用 48kHz/16bit 作为标准格式。
解决方法:
-
在
AudioPolicy中配置支持的采样率和格式。 -
在
AudioFlinger中关闭自动重采样。 -
在 HAL 层实现直通传输。
1.6.4 多输出设备切换
现象:从 USB DAC 切换到 I2S DAC 时,音频中断或出现爆音。
核心矛盾:设备切换需要重新配置路由和缓冲区。
解决方法:
-
在
AudioPolicy中实现设备切换的平滑过渡。 -
在
AudioFlinger中暂停/恢复音频流。 -
在 HAL 层实现设备热切换。
第二部分 AudioFlinger 核心实现
2.1 AudioFlinger 概述
AudioFlinger 是 Android 音频系统的核心服务,负责管理所有音频流、混音、线程调度和设备路由。对于 HiFi 音频产品,理解 AudioFlinger 的内部机制是优化延迟、确保 bit-perfect 输出和实现高采样率支持的关键。
2.1.1 AudioFlinger 架构
[AudioPolicy] ←→ [AudioFlinger] ←→ [Audio HAL] ↓ ↓ ↓ [路由策略] [音频流管理] [硬件访问] [设备选择] [混音器] [设备路由] [音量控制] [效果处理] [采样率转换] [格式转换] [线程调度] [DMA 传输]
2.1.2 AudioFlinger 核心组件
+---------------------------------------------+ | AudioFlinger (系统服务) | | ├── 主线程 (Main Thread) | | │ ├── 音频流管理 | | │ ├── 设备状态管理 | | │ └── 音频策略交互 | | ├── 播放线程 (Playback Thread) | | │ ├── AudioTrack 管理 | | │ ├── 混音器 (AudioMixer) | | │ ├── 效果处理 (Effect Processor) | | │ └── HAL 输出 (HAL Output) | | ├── 录制线程 (Record Thread) | | │ ├── AudioRecord 管理 | | │ ├── HAL 输入 (HAL Input) | | │ └── 效果处理 (Effect Processor) | | ├── 离线线程 (Offline Thread) | | │ └── 批量处理 (Batch Processing) | | └── 控制线程 (Control Thread) | | └── 设备切换 (Device Switching) | +---------------------------------------------+
2.2 核心数据结构
2.2.1 AudioFlinger 核心结构
/**
* @class AudioFlinger
* @brief Android 音频核心服务,管理所有音频流和设备。
*/
class AudioFlinger {
public:
/**
* @brief 创建 AudioTrack 实例。
* @param config 音频流配置
* @return AudioTrack 实例指针
*/
sp<AudioTrack> createTrack(const AudioTrackConfig &config);
/**
* @brief 创建 AudioRecord 实例。
* @param config 音频录制配置
* @return AudioRecord 实例指针
*/
sp<AudioRecord> createRecord(const AudioRecordConfig &config);
/**
* @brief 打开输出设备。
* @param device 设备类型
* @param config 输出配置
* @return 输出句柄
*/
audio_io_handle_t openOutput(audio_devices_t device, const AudioOutputConfig &config);
/**
* @brief 关闭输出设备。
* @param output 输出句柄
* @return 0 成功,负数错误
*/
int closeOutput(audio_io_handle_t output);
/**
* @brief 设置音频流音量。
* @param track AudioTrack 实例
* @param volume 音量 (0-1)
* @return 0 成功,负数错误
*/
int setVolume(const sp<AudioTrack> &track, float volume);
/**
* @brief 暂停音频流。
* @param track AudioTrack 实例
* @return 0 成功,负数错误
*/
int pauseTrack(const sp<AudioTrack> &track);
/**
* @brief 恢复音频流。
* @param track AudioTrack 实例
* @return 0 成功,负数错误
*/
int resumeTrack(const sp<AudioTrack> &track);
/**
* @brief 停止音频流。
* @param track AudioTrack 实例
* @return 0 成功,负数错误
*/
int stopTrack(const sp<AudioTrack> &track);
/**
* @brief 设置音频流延时。
* @param track AudioTrack 实例
* @param delay_us 延时 (微秒)
* @return 0 成功,负数错误
*/
int setDelay(const sp<AudioTrack> &track, uint32_t delay_us);
private:
struct AudioThread {
enum Type {
PLAYBACK_THREAD = 0,
RECORD_THREAD,
OFFLOAD_THREAD,
CONTROL_THREAD
} type; /**< 线程类型 */
sp<AudioMixer> mixer; /**< 混音器 */
sp<AudioHAL> hal; /**< HAL 接口 */
sp<AudioEffectProcessor> effect; /**< 效果处理器 */
Mutex lock; /**< 互斥锁 */
Condition cond; /**< 条件变量 */
bool is_running; /**< 是否运行 */
uint32_t sample_rate; /**< 采样率 */
uint32_t frame_size; /**< 帧大小 */
uint32_t buffer_size; /**< 缓冲区大小 */
uint32_t latency_us; /**< 延迟 (微秒) */
};
std::map<audio_io_handle_t, sp<AudioThread>> mThreads;
std::map<sp<AudioTrack>, audio_io_handle_t> mTrackMap;
std::map<sp<AudioRecord>, audio_io_handle_t> mRecordMap;
Mutex mLock;
Condition mCond;
sp<AudioPolicy> mPolicy;
sp<AudioHAL> mHal;
AudioConfig mConfig;
};
2.2.2 播放线程结构
/**
* @struct PlaybackThread
* @brief AudioFlinger 播放线程,管理音频输出。
*/
struct PlaybackThread : public AudioThread {
sp<AudioMixer> mixer; /**< 混音器 */
sp<AudioHAL> hal; /**< HAL 接口 */
sp<AudioEffectProcessor> effect; /**< 效果处理器 */
sp<AudioTrack> track; /**< 当前 Active Track */
std::vector<sp<AudioTrack>> active_tracks; /**< 活动 Track 列表 */
std::vector<sp<AudioTrack>> pending_tracks; /**< 待处理 Track 列表 */
Mutex lock; /**< 互斥锁 */
Condition cond; /**< 条件变量 */
bool is_running; /**< 是否运行 */
uint32_t sample_rate; /**< 采样率 */
uint32_t frame_size; /**< 帧大小 */
uint32_t buffer_size; /**< 缓冲区大小 */
uint32_t period_size; /**< 周期大小 */
uint32_t period_count; /**< 周期数量 */
uint32_t latency_us; /**< 目标延迟 (微秒) */
uint32_t actual_latency_us; /**< 实际延迟 (微秒) */
bool bit_perfect_mode; /**< 是否 bit-perfect 模式 */
bool dsd_mode; /**< 是否 DSD 模式 */
bool resample_enabled; /**< 是否启用重采样 */
bool downmix_enabled; /**< 是否启用下混 */
bool volume_ramp_enabled; /**< 是否启用音量渐变 */
bool effect_enabled; /**< 是否启用效果 */
float volume; /**< 当前音量 */
float left_volume; /**< 左声道音量 */
float right_volume; /**< 右声道音量 */
audio_devices_t device; /**< 输出设备 */
audio_format_t format; /**< 音频格式 */
audio_channel_mask_t channel_mask; /**< 通道掩码 */
};
2.2.3 混音器配置结构
/**
* @struct AudioMixerConfig
* @brief 混音器配置结构。
*/
struct AudioMixerConfig {
uint32_t sample_rate; /**< 采样率 */
uint32_t frame_size; /**< 帧大小 */
uint32_t buffer_size; /**< 缓冲区大小 */
uint32_t period_size; /**< 周期大小 */
uint32_t period_count; /**< 周期数量 */
bool resample_enabled; /**< 是否启用重采样 */
bool downmix_enabled; /**< 是否启用下混 */
bool volume_ramp_enabled; /**< 是否启用音量渐变 */
bool effect_enabled; /**< 是否启用效果 */
audio_format_t format; /**< 音频格式 */
audio_channel_mask_t channel_mask; /**< 通道掩码 */
audio_devices_t device; /**< 输出设备 */
};
2.3 核心代码实现
2.3.1 AudioFlinger 主循环
#include <media/AudioFlinger.h>
#include <media/AudioMixer.h>
#include <hardware/audio.h>
/**
* @brief AudioFlinger 主循环线程。
*/
void AudioFlinger::mainLoop()
{
sp<PlaybackThread> playback_thread;
sp<AudioMixer> mixer;
sp<AudioHAL> hal;
// 1. 打开输出设备
audio_io_handle_t output = openOutput(AUDIO_DEVICE_OUT_DEFAULT, mConfig);
if (output < 0) {
LOGE("Failed to open output device");
return;
}
// 2. 创建播放线程
playback_thread = sp<PlaybackThread>(new PlaybackThread());
if (!playback_thread) {
LOGE("Failed to create playback thread");
closeOutput(output);
return;
}
// 3. 创建混音器
mixer = sp<AudioMixer>(new AudioMixer());
if (!mixer) {
LOGE("Failed to create mixer");
closeOutput(output);
return;
}
// 4. 初始化 HAL
hal = sp<AudioHAL>(new AudioHAL());
if (hal->open(output) < 0) {
LOGE("Failed to open HAL");
closeOutput(output);
return;
}
// 5. 配置混音器
mixer->setSampleRate(mConfig.sample_rate);
mixer->setFormat(mConfig.format);
mixer->setChannelMask(mConfig.channel_mask);
mixer->setVolume(1.0f, 1.0f);
mixer->setMixerConfig(mConfig);
// 6. 启动播放线程
playback_thread->mixer = mixer;
playback_thread->hal = hal;
playback_thread->is_running = true;
playback_thread->run();
// 7. 等待停止
waitForStop();
}
/**
* @brief AudioFlinger 播放线程循环。
*/
void PlaybackThread::run()
{
while (is_running) {
// 1. 等待音频数据
if (active_tracks.empty()) {
usleep(period_size * 1000 / sample_rate);
continue;
}
// 2. 混音处理
mixer->mix(active_tracks, buffer, buffer_size);
// 3. 效果处理
if (effect_enabled && effect) {
effect->process(buffer, buffer_size);
}
// 4. 写入 HAL
hal->write(buffer, buffer_size);
// 5. 更新状态
updateLatency();
updateVolume();
}
}
2.3.2 音频流管理
/**
* @brief 创建 AudioTrack 并注册到 AudioFlinger。
* @param config AudioTrack 配置
* @return AudioTrack 实例指针
*/
sp<AudioTrack> AudioFlinger::createTrack(const AudioTrackConfig &config)
{
sp<AudioTrack> track = new AudioTrack();
if (!track) {
return nullptr;
}
// 1. 初始化 AudioTrack
if (track->init(config) < 0) {
return nullptr;
}
// 2. 检查设备是否支持
if (!isDeviceSupported(config.device)) {
return nullptr;
}
// 3. 检查格式是否支持
if (!isFormatSupported(config.format)) {
return nullptr;
}
// 4. 检查采样率是否支持
if (!isSampleRateSupported(config.sample_rate)) {
return nullptr;
}
// 5. 添加到活动列表
{
AutoMutex _l(mLock);
mTrackMap[track] = config.output;
if (!mThreads[config.output]) {
// 创建播放线程
mThreads[config.output] = createPlaybackThread(config);
}
mThreads[config.output]->active_tracks.push_back(track);
}
return track;
}
/**
* @brief 停止音频流并释放资源。
* @param track AudioTrack 实例
*/
void AudioFlinger::destroyTrack(const sp<AudioTrack> &track)
{
if (!track) {
return;
}
// 1. 从活动列表移除
{
AutoMutex _l(mLock);
audio_io_handle_t output = mTrackMap[track];
if (mThreads[output]) {
mThreads[output]->active_tracks.erase(track);
}
mTrackMap.erase(track);
}
// 2. 停止 AudioTrack
track->stop();
track->destroy();
}
2.3.3 混音器实现
/**
* @brief 混音器核心实现。
*/
class AudioMixer : public RefBase {
public:
/**
* @brief 混音处理。
* @param tracks 待混音的 Track 列表
* @param buffer 输出缓冲区
* @param buffer_size 缓冲区大小 (字节)
*/
void mix(const std::vector<sp<AudioTrack>> &tracks,
void *buffer,
size_t buffer_size)
{
// 1. 清零缓冲区
memset(buffer, 0, buffer_size);
// 2. 检查是否有 Track
if (tracks.empty()) {
return;
}
// 3. 遍历所有 Track
for (const auto &track : tracks) {
if (!track || !track->isActive()) {
continue;
}
// 4. 读取音频数据
void *track_buffer = track->read(buffer_size);
if (!track_buffer) {
continue;
}
// 5. 格式转换 (如果需要)
if (track->format() != mConfig.format) {
track_buffer = convertFormat(track_buffer, track->format(), mConfig.format);
}
// 6. 采样率转换 (如果需要)
if (track->sampleRate() != mConfig.sample_rate) {
track_buffer = resample(track_buffer, track->sampleRate(), mConfig.sample_rate);
}
// 7. 混音
mixChannels(track_buffer, buffer, buffer_size, track->volume());
}
}
private:
/**
* @brief 通道混音处理。
*/
void mixChannels(const void *src,
void *dst,
size_t size,
float volume)
{
const int16_t *s = (const int16_t *)src;
int16_t *d = (int16_t *)dst;
size_t frames = size / sizeof(int16_t);
float vol = volume;
for (size_t i = 0; i < frames; i++) {
d[i] = (int16_t)(s[i] * vol);
}
}
AudioMixerConfig mConfig;
};
2.3.4 AudioTrack 实现
/**
* @brief AudioTrack 核心实现。
*/
class AudioTrack : public RefBase {
public:
/**
* @brief 初始化 AudioTrack。
* @param config AudioTrack 配置
* @return 0 成功,负数错误
*/
int init(const AudioTrackConfig &config)
{
mConfig = config;
mState = STATE_STOPPED;
mVolume = 1.0f;
mFrameCount = 0;
mBuffer = nullptr;
// 1. 分配缓冲区
mBuffer = malloc(config.buffer_size);
if (!mBuffer) {
return -ENOMEM;
}
return 0;
}
/**
* @brief 销毁 AudioTrack。
*/
void destroy()
{
if (mBuffer) {
free(mBuffer);
mBuffer = nullptr;
}
mState = STATE_DESTROYED;
}
/**
* @brief 写入音频数据。
* @param data 音频数据
* @param size 数据大小 (字节)
* @return 实际写入字节数
*/
size_t write(const void *data, size_t size)
{
if (!data || size == 0) {
return 0;
}
if (mState != STATE_RUNNING) {
return 0;
}
// 1. 复制数据到缓冲区
size_t write_size = size > mConfig.buffer_size ? mConfig.buffer_size : size;
memcpy(mBuffer, data, write_size);
mFrameCount += write_size / mConfig.frame_size;
// 2. 通知 AudioFlinger 数据就绪
if (mListener) {
mListener->onBufferReady();
}
return write_size;
}
/**
* @brief 读取音频数据。
* @param size 请求大小 (字节)
* @return 数据指针,失败返回 nullptr
*/
void *read(size_t size)
{
if (mState != STATE_RUNNING) {
return nullptr;
}
return mBuffer;
}
/**
* @brief 开始播放。
* @return 0 成功,负数错误
*/
int start()
{
mState = STATE_RUNNING;
return 0;
}
/**
* @brief 停止播放。
* @return 0 成功,负数错误
*/
int stop()
{
mState = STATE_STOPPED;
return 0;
}
private:
AudioTrackConfig mConfig;
void *mBuffer;
size_t mFrameCount;
float mVolume;
int mState;
sp<AudioTrackListener> mListener;
};
2.3.5 Bit-perfect 模式支持
/**
* @brief 设置 Bit-perfect 模式。
* @param enable 是否启用
* @return 0 成功,负数错误
*/
int PlaybackThread::setBitPerfectMode(bool enable)
{
if (bit_perfect_mode == enable) {
return 0;
}
// 1. 检查设备是否支持
if (enable && !hal->isBitPerfectSupported()) {
LOGE("Bit-perfect mode not supported by HAL");
return -ENOTSUPP;
}
// 2. 启用/禁用混音器
if (enable) {
// 禁用混音器,直接输出
mixer->setEnabled(false);
hal->setFormat(format);
hal->setSampleRate(sample_rate);
hal->setChannelMask(channel_mask);
} else {
// 启用混音器
mixer->setEnabled(true);
mixer->setFormat(mConfig.format);
mixer->setSampleRate(mConfig.sample_rate);
mixer->setChannelMask(mConfig.channel_mask);
}
bit_perfect_mode = enable;
return 0;
}
2.3.6 DSD 模式支持
/**
* @brief 设置 DSD 模式。
* @param enable 是否启用
* @return 0 成功,负数错误
*/
int PlaybackThread::setDSDMode(bool enable)
{
if (dsd_mode == enable) {
return 0;
}
// 1. 检查设备是否支持
if (enable && !hal->isDSDSupported()) {
LOGE("DSD mode not supported by HAL");
return -ENOTSUPP;
}
// 2. 启用/禁用 DSD 模式
if (enable) {
hal->setFormat(AUDIO_FORMAT_DSD);
hal->setSampleRate(DSD_SAMPLE_RATE);
hal->setChannelMask(AUDIO_CHANNEL_IN_STEREO);
bit_perfect_mode = true; // DSD 必须启用 bit-perfect
} else {
hal->setFormat(mConfig.format);
hal->setSampleRate(mConfig.sample_rate);
hal->setChannelMask(mConfig.channel_mask);
bit_perfect_mode = false;
}
dsd_mode = enable;
return 0;
}
2.4 软件设计模式树形分析
AudioFlinger 设计模式 ├── 工厂模式 (Factory Pattern) │ ├── createTrack():创建 AudioTrack 实例 │ ├── createRecord():创建 AudioRecord 实例 │ └── openOutput():创建输出设备句柄 ├── 适配器模式 (Adapter Pattern) │ ├── AudioHAL:适配不同音频硬件 │ └── AudioMixer:适配不同音频格式和采样率 ├── 策略模式 (Strategy Pattern) │ ├── AudioMixer:混音策略 │ ├── PlaybackThread:播放线程策略 │ └── Bit-perfect 模式:是否启用混音器 ├── 观察者模式 (Observer Pattern) │ ├── AudioTrackListener:观察 Track 状态变化 │ └── AudioFlinger 观察音频流状态 ├── 状态模式 (State Pattern) │ ├── AudioTrack 状态 (STOPPED/RUNNING/PAUSED/DESTROYED) │ └── PlaybackThread 状态 (STOPPED/RUNNING) └── 单例模式 (Singleton Pattern) └── AudioFlinger:系统全局唯一实例
2.5 AudioFlinger 调试核心难点
2.5.1 延迟优化
现象:音频播放延迟过高,影响实时性。
原因:
-
缓冲区设置过大。
-
线程优先级不足。
-
混音器处理耗时。
解决方法:
-
减小
period_size和period_count。 -
提升 AudioFlinger 线程优先级。
-
优化混音器算法。
2.5.2 Bit-perfect 输出
现象:即使启用 bit-perfect,音频数据仍被处理。
原因:
-
AudioPolicy 中启用了重采样。
-
AudioMixer 被强制启用。
-
HAL 层进行了格式转换。
解决方法:
-
在 AudioPolicy 中禁用自动重采样。
-
在 AudioFlinger 中强制禁用混音器。
-
确保 HAL 层直通传输。
2.5.3 DSD 支持
现象:DSD 格式无法播放或播放异常。
原因:
-
HAL 层不支持 DSD 格式。
-
AudioFlinger 未正确配置 DSD 模式。
-
DSD 数据包大小不匹配。
解决方法:
-
确认 HAL 层支持 DSD。
-
在 AudioFlinger 中设置 DSD 模式。
-
调整 DSD 数据包大小。
2.5.4 线程死锁
现象:系统响应缓慢,音频卡顿。
原因:
-
AudioFlinger 主线程阻塞。
-
设备切换时锁竞争。
-
缓冲区不足。
解决方法:
-
使用
Trace跟踪线程状态。 -
优化锁粒度。
-
调整缓冲区大小。
2.6 与其他模块的协同
| 模块 | 协同方式 | 调试关键点 |
|---|---|---|
| AudioPolicy | 提供路由策略和设备选择 | 策略配置、设备切换 |
| AudioHAL | 提供硬件访问接口 | 格式支持、延迟控制 |
| AudioMixer | 混音和格式转换 | 混音质量、CPU 占用 |
| AudioTrack/AudioRecord | 音频数据传输 | 缓冲区管理、延迟控制 |
| System Server | 服务启动和管理 | 启动顺序、权限控制 |
| 用户空间 | 通过 JNI 调用 AudioFlinger | JNI 接口、权限控制 |
第三部分 AudioPolicy 与设备路由策略
3.1 AudioPolicy 概述
AudioPolicy 是 Android 音频系统中负责路由决策的核心组件。它决定了音频流从哪个设备输出、从哪个设备输入,以及不同音频流之间的优先级和策略。对于 HiFi 音频产品,AudioPolicy 的配置直接影响设备切换、采样率匹配、多通道输出等关键功能。
3.1.1 AudioPolicy 架构
[AudioFlinger] ←→ [AudioPolicy] ←→ [AudioPolicyManager] ↓ ↓ ↓ [音频流请求] [路由策略] [设备管理] [设备切换] [音量策略] [热插拔处理] [格式协商] [优先级策略] [电源管理]
3.1.2 AudioPolicy 核心组件
+---------------------------------------------+ | AudioPolicy (系统服务) | | ├── 路由策略 (Routing Strategy) | | │ ├── 设备选择 (Device Selection) | | │ ├── 路由规则 (Routing Rules) | | │ └── 优先级管理 (Priority Management) | | ├── 设备管理 (Device Management) | | │ ├── 设备注册 (Device Registration) | | │ ├── 设备状态 (Device State) | | │ ├── 热插拔处理 (Hotplug Handling) | | │ └── 设备配置 (Device Configuration) | | ├── 音量策略 (Volume Strategy) | | │ ├── 音量曲线 (Volume Curve) | | │ ├── 音量限制 (Volume Limit) | | │ └── 音量同步 (Volume Sync) | | └── 格式策略 (Format Strategy) | | ├── 格式协商 (Format Negotiation) | | ├── 采样率匹配 (Sample Rate Matching) | | └── 格式转换 (Format Conversion) | +---------------------------------------------+
3.2 核心数据结构
3.2.1 AudioPolicy 核心结构
/**
* @class AudioPolicy
* @brief 音频策略核心类,管理设备路由和音频策略。
*/
class AudioPolicy {
public:
/**
* @brief 获取设备路由策略。
* @param stream 流类型
* @param session_id 会话 ID
* @return 路由策略实例
*/
sp<RoutingStrategy> getRoutingStrategy(audio_stream_type_t stream, int session_id);
/**
* @brief 注册音频设备。
* @param device 设备描述符
* @return 0 成功,负数错误
*/
int registerDevice(const AudioDeviceDescriptor &device);
/**
* @brief 注销音频设备。
* @param device_id 设备 ID
* @return 0 成功,负数错误
*/
int unregisterDevice(audio_device_id_t device_id);
/**
* @brief 设置音量策略。
* @param stream 流类型
* @param volume 音量 (0-1)
* @param device 设备类型
* @return 0 成功,负数错误
*/
int setVolume(audio_stream_type_t stream, float volume, audio_devices_t device);
/**
* @brief 获取设备格式支持。
* @param device 设备类型
* @param format 格式
* @return true 支持,false 不支持
*/
bool isFormatSupported(audio_devices_t device, audio_format_t format);
/**
* @brief 获取设备采样率支持。
* @param device 设备类型
* @param rate 采样率
* @return true 支持,false 不支持
*/
bool isSampleRateSupported(audio_devices_t device, uint32_t rate);
/**
* @brief 获取最佳输出设备。
* @param stream 流类型
* @param session_id 会话 ID
* @return 最佳输出设备类型
*/
audio_devices_t getBestOutputDevice(audio_stream_type_t stream, int session_id);
/**
* @brief 获取最佳输入设备。
* @param stream 流类型
* @param session_id 会话 ID
* @return 最佳输入设备类型
*/
audio_devices_t getBestInputDevice(audio_stream_type_t stream, int session_id);
/**
* @brief 动态更新路由策略。
* @param rules 新路由规则
* @return 0 成功,负数错误
*/
int updateRoutingRules(const std::vector<RoutingRule> &rules);
private:
struct PolicyConfig {
std::map<audio_stream_type_t, RoutingStrategy> routing_strategies;
std::map<audio_devices_t, DeviceConfig> device_configs;
std::map<audio_stream_type_t, VolumeStrategy> volume_strategies;
std::map<audio_stream_type_t, FormatStrategy> format_strategies;
std::vector<RoutingRule> custom_rules;
} mPolicyConfig;
struct DeviceConfig {
audio_devices_t type;
std::string name;
std::vector<audio_format_t> supported_formats;
std::vector<uint32_t> supported_sample_rates;
uint32_t max_channels;
uint32_t latency_us;
uint32_t buffer_size;
bool is_active;
bool is_available;
bool is_hifi;
bool is_bit_perfect;
} mDeviceConfig;
Mutex mLock;
Condition mCond;
sp<AudioFlinger> mFlinger;
sp<AudioHAL> mHal;
sp<AudioPolicyManager> mManager;
};
3.2.2 路由策略结构
/**
* @struct RoutingStrategy
* @brief 路由策略配置结构。
*/
struct RoutingStrategy {
audio_stream_type_t stream; /**< 流类型 */
std::vector<audio_devices_t> preferred_devices; /**< 首选设备列表 */
std::vector<audio_devices_t> backup_devices; /**< 备用设备列表 */
std::vector<RoutingRule> rules; /**< 自定义路由规则 */
uint32_t priority; /**< 优先级 */
bool force_device; /**< 是否强制设备 */
bool allow_multi_device; /**< 是否允许多设备 */
bool allow_priority_preemption; /**< 是否允许优先级抢占 */
bool auto_route; /**< 是否自动路由 */
bool dynamic_route; /**< 是否动态路由 */
};
/**
* @struct RoutingRule
* @brief 自定义路由规则结构。
*/
struct RoutingRule {
enum RuleType {
RULE_DEVICE_AVAILABLE = 0,
RULE_DEVICE_PREFERRED,
RULE_DEVICE_EXCLUSIVE,
RULE_STREAM_PRIORITY,
RULE_SESSION_PRIORITY,
RULE_FORMAT_MATCH,
RULE_SAMPLE_RATE_MATCH
} type; /**< 规则类型 */
audio_devices_t device; /**< 设备类型 */
audio_stream_type_t stream; /**< 流类型 */
uint32_t priority; /**< 优先级 */
uint32_t session_id; /**< 会话 ID */
bool enable; /**< 是否启用 */
bool exclusive; /**< 是否独占 */
std::string condition; /**< 条件表达式 */
};
3.2.3 设备配置结构
/**
* @struct DeviceConfig
* @brief 设备配置结构。
*/
struct DeviceConfig {
audio_devices_t type; /**< 设备类型 */
std::string name; /**< 设备名称 */
uint32_t id; /**< 设备 ID */
uint32_t flags; /**< 设备标志 */
std::vector<audio_format_t> supported_formats; /**< 支持格式列表 */
std::vector<uint32_t> supported_sample_rates; /**< 支持采样率列表 */
uint32_t max_channels; /**< 最大通道数 */
uint32_t max_sample_rate; /**< 最大采样率 */
uint32_t min_sample_rate; /**< 最小采样率 */
uint32_t latency_us; /**< 延迟 (微秒) */
uint32_t buffer_size; /**< 缓冲区大小 */
uint32_t period_size; /**< 周期大小 */
uint32_t period_count; /**< 周期数量 */
bool is_hifi; /**< 是否 HiFi 设备 */
bool is_bit_perfect; /**< 是否 Bit-perfect */
bool is_active; /**< 是否活动 */
bool is_available; /**< 是否可用 */
bool is_removable; /**< 是否可移除 */
bool is_hotpluggable; /**< 是否热插拔 */
bool supports_raw; /**< 是否支持 RAW 模式 */
bool supports_dsd; /**< 是否支持 DSD */
bool supports_float; /**< 是否支持浮点 */
bool supports_multi_channel; /**< 是否支持多通道 */
};
3.3 核心代码实现
3.3.1 AudioPolicy 初始化
#include <media/AudioPolicy.h>
#include <media/AudioPolicyManager.h>
#include <hardware/audio.h>
/**
* @brief AudioPolicy 初始化函数。
*/
int AudioPolicy::init()
{
// 1. 加载默认配置
if (loadDefaultPolicyConfig() < 0) {
LOGE("Failed to load default policy config");
return -EINVAL;
}
// 2. 注册默认设备
AudioDeviceDescriptor default_output(
AUDIO_DEVICE_OUT_DEFAULT,
"default_output",
AUDIO_FORMAT_PCM_16_BIT,
48000,
2,
1024
);
registerDevice(default_output);
AudioDeviceDescriptor default_input(
AUDIO_DEVICE_IN_DEFAULT,
"default_input",
AUDIO_FORMAT_PCM_16_BIT,
48000,
1,
1024
);
registerDevice(default_input);
// 3. 加载自定义规则
if (loadCustomRoutingRules() < 0) {
LOGE("Failed to load custom routing rules");
return -EINVAL;
}
// 4. 初始化设备状态
updateDeviceState();
// 5. 初始化音量策略
initVolumeStrategy();
// 6. 初始化格式策略
initFormatStrategy();
return 0;
}
/**
* @brief 加载默认策略配置。
*/
int AudioPolicy::loadDefaultPolicyConfig()
{
// 1. 配置默认路由策略
mPolicyConfig.routing_strategies[AUDIO_STREAM_MUSIC] = {
AUDIO_STREAM_MUSIC,
{AUDIO_DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_HEADPHONE},
{AUDIO_DEVICE_OUT_DEFAULT},
{},
10,
false,
false,
false,
true,
true
};
// 2. 配置默认设备
mPolicyConfig.device_configs[AUDIO_DEVICE_OUT_SPEAKER] = {
AUDIO_DEVICE_OUT_SPEAKER,
"speaker",
1,
0,
{AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_24_BIT, AUDIO_FORMAT_PCM_32_BIT},
{44100, 48000, 88200, 96000, 176400, 192000},
8,
192000,
44100,
10000,
4096,
1024,
4,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false
};
return 0;
}
3.3.2 设备路由决策
/**
* @brief 获取最佳输出设备。
* @param stream 流类型
* @param session_id 会话 ID
* @return 最佳输出设备类型
*/
audio_devices_t AudioPolicy::getBestOutputDevice(audio_stream_type_t stream, int session_id)
{
AudioDeviceConfig preferred_device;
AudioDeviceConfig backup_device;
int max_priority = -1;
// 1. 获取流类型的路由策略
if (mPolicyConfig.routing_strategies.find(stream) == mPolicyConfig.routing_strategies.end()) {
return AUDIO_DEVICE_OUT_DEFAULT;
}
RoutingStrategy &strategy = mPolicyConfig.routing_strategies[stream];
// 2. 遍历首选设备
for (audio_devices_t device : strategy.preferred_devices) {
if (!isDeviceAvailable(device)) {
continue;
}
// 检查格式支持
AudioFormatMatch format_match = checkFormatSupport(device, stream);
if (format_match == FORMAT_MATCH_BIT_PERFECT) {
// Bit-perfect 匹配,立即返回
return device;
} else if (format_match == FORMAT_MATCH_NORMAL) {
// 普通匹配,记录
if (strategy.priority > max_priority) {
max_priority = strategy.priority;
preferred_device = mPolicyConfig.device_configs[device];
}
}
}
// 3. 如果有匹配的设备,返回
if (max_priority >= 0) {
return preferred_device.type;
}
// 4. 遍历备用设备
for (audio_devices_t device : strategy.backup_devices) {
if (!isDeviceAvailable(device)) {
continue;
}
if (checkFormatSupport(device, stream) != FORMAT_MATCH_NONE) {
backup_device = mPolicyConfig.device_configs[device];
break;
}
}
// 5. 如果有备用设备,返回
if (backup_device.type != AUDIO_DEVICE_OUT_DEFAULT) {
return backup_device.type;
}
// 6. 返回默认设备
return AUDIO_DEVICE_OUT_DEFAULT;
}
/**
* @brief 检查设备格式支持。
* @param device 设备类型
* @param stream 流类型
* @return 格式匹配级别
*/
AudioFormatMatch AudioPolicy::checkFormatSupport(audio_devices_t device, audio_stream_type_t stream)
{
if (mPolicyConfig.device_configs.find(device) == mPolicyConfig.device_configs.end()) {
return FORMAT_MATCH_NONE;
}
DeviceConfig &config = mPolicyConfig.device_configs[device];
// 1. 获取流格式
audio_format_t stream_format = getStreamFormat(stream);
uint32_t stream_sample_rate = getStreamSampleRate(stream);
uint32_t stream_channels = getStreamChannels(stream);
// 2. 检查格式支持
bool format_supported = false;
for (audio_format_t fmt : config.supported_formats) {
if (fmt == stream_format) {
format_supported = true;
break;
}
}
if (!format_supported) {
return FORMAT_MATCH_NONE;
}
// 3. 检查采样率支持
bool sample_rate_supported = false;
for (uint32_t rate : config.supported_sample_rates) {
if (rate == stream_sample_rate) {
sample_rate_supported = true;
break;
}
}
if (!sample_rate_supported) {
return FORMAT_MATCH_NONE;
}
// 4. 检查通道数支持
if (stream_channels > config.max_channels) {
return FORMAT_MATCH_NONE;
}
// 5. 检查 Bit-perfect 能力
if (config.is_bit_perfect &&
config.supports_raw &&
stream_format == config.supported_formats[0]) {
return FORMAT_MATCH_BIT_PERFECT;
}
return FORMAT_MATCH_NORMAL;
}
3.3.3 动态路由规则更新
/**
* @brief 动态更新路由规则。
* @param rules 新路由规则
* @return 0 成功,负数错误
*/
int AudioPolicy::updateRoutingRules(const std::vector<RoutingRule> &rules)
{
AutoMutex _l(mLock);
// 1. 验证规则
for (const auto &rule : rules) {
if (!validateRoutingRule(rule)) {
LOGE("Invalid routing rule");
return -EINVAL;
}
}
// 2. 更新规则
mPolicyConfig.custom_rules.clear();
mPolicyConfig.custom_rules = rules;
// 3. 重新计算路由
recalculateRouting();
// 4. 通知 AudioFlinger
mFlinger->updateRouting(rules);
return 0;
}
/**
* @brief 验证路由规则。
* @param rule 路由规则
* @return true 有效,false 无效
*/
bool AudioPolicy::validateRoutingRule(const RoutingRule &rule)
{
// 1. 检查设备类型
if (rule.device != AUDIO_DEVICE_OUT_DEFAULT &&
mPolicyConfig.device_configs.find(rule.device) == mPolicyConfig.device_configs.end()) {
return false;
}
// 2. 检查流类型
if (rule.stream != AUDIO_STREAM_MUSIC &&
rule.stream != AUDIO_STREAM_SYSTEM &&
rule.stream != AUDIO_STREAM_VOICE_CALL) {
return false;
}
// 3. 检查优先级
if (rule.priority < 0 || rule.priority > 100) {
return false;
}
// 4. 检查会话 ID
if (rule.session_id < 0) {
return false;
}
return true;
}
/**
* @brief 重新计算路由。
*/
void AudioPolicy::recalculateRouting()
{
// 1. 清除旧路由表
mRouteTable.clear();
// 2. 应用自定义规则
for (const auto &rule : mPolicyConfig.custom_rules) {
if (!rule.enable) {
continue;
}
if (rule.condition.empty()) {
// 无条件规则
mRouteTable[rule.device] = rule;
} else {
// 条件规则
if (evaluateCondition(rule.condition)) {
mRouteTable[rule.device] = rule;
}
}
}
// 3. 通知设备状态变化
for (const auto &entry : mRouteTable) {
mFlinger->onDeviceRouteChanged(entry.first, entry.second);
}
}
3.3.4 USB 音频设备热插拔处理
/**
* @brief 处理 USB 音频设备插入事件。
* @param device_path 设备路径
* @return 0 成功,负数错误
*/
int AudioPolicy::onUSBDevicePlugged(const char *device_path)
{
AutoMutex _l(mLock);
// 1. 扫描设备能力
AudioDeviceDescriptor device;
if (scanUSBDevice(device_path, device) < 0) {
LOGE("Failed to scan USB device");
return -ENODEV;
}
// 2. 检查设备是否已注册
for (const auto &config : mPolicyConfig.device_configs) {
if (config.second.name == device.name) {
// 已注册,更新状态
mPolicyConfig.device_configs[device.type].is_available = true;
mPolicyConfig.device_configs[device.type].is_active = true;
return 0;
}
}
// 3. 注册新设备
mPolicyConfig.device_configs[device.type] = {
device.type,
device.name,
++mPolicyConfig.device_count,
device.flags,
device.formats,
device.sample_rates,
device.max_channels,
device.max_sample_rate,
device.min_sample_rate,
device.latency_us,
device.buffer_size,
device.period_size,
device.period_count,
true, // is_hifi
true, // is_bit_perfect
true, // is_active
true, // is_available
true, // is_removable
true, // is_hotpluggable
true, // supports_raw
false, // supports_dsd
false, // supports_float
device.max_channels > 2 // supports_multi_channel
};
// 4. 触发路由重新计算
recalculateRouting();
return 0;
}
/**
* @brief 处理 USB 音频设备移除事件。
* @param device_path 设备路径
* @return 0 成功,负数错误
*/
int AudioPolicy::onUSBDeviceUnplugged(const char *device_path)
{
AutoMutex _l(mLock);
// 1. 查找设备
for (auto &config : mPolicyConfig.device_configs) {
if (config.second.name == device_path) {
// 2. 更新设备状态
config.second.is_available = false;
config.second.is_active = false;
// 3. 如果设备是活动的,切换路由
if (config.second.is_active) {
audio_devices_t new_device = getBestOutputDevice(AUDIO_STREAM_MUSIC, 0);
mFlinger->switchOutputDevice(new_device);
}
// 4. 触发路由重新计算
recalculateRouting();
break;
}
}
return 0;
}
3.3.5 音量策略实现
/**
* @brief 设置音量策略。
* @param stream 流类型
* @param volume 音量 (0-1)
* @param device 设备类型
* @return 0 成功,负数错误
*/
int AudioPolicy::setVolume(audio_stream_type_t stream, float volume, audio_devices_t device)
{
AutoMutex _l(mLock);
// 1. 检查音量范围
if (volume < 0.0f || volume > 1.0f) {
LOGE("Invalid volume value");
return -EINVAL;
}
// 2. 获取音量曲线
if (mPolicyConfig.volume_strategies.find(stream) == mPolicyConfig.volume_strategies.end()) {
return -ENOTSUPP;
}
VolumeStrategy &strategy = mPolicyConfig.volume_strategies[stream];
// 3. 应用音量曲线
float mapped_volume = strategy.applyCurve(volume);
// 4. 应用音量限制
if (strategy.has_limit && mapped_volume > strategy.max_volume) {
mapped_volume = strategy.max_volume;
}
// 5. 应用设备特定音量
if (device != AUDIO_DEVICE_OUT_DEFAULT) {
if (mPolicyConfig.device_configs.find(device) == mPolicyConfig.device_configs.end()) {
return -ENODEV;
}
DeviceConfig &device_config = mPolicyConfig.device_configs[device];
if (device_config.has_custom_volume) {
mapped_volume = device_config.applyCustomVolume(mapped_volume);
}
}
// 6. 更新音量
mVolumeCache[stream][device] = mapped_volume;
// 7. 通知 AudioFlinger
mFlinger->setVolume(stream, mapped_volume, device);
return 0;
}
3.3.6 格式策略实现
/**
* @brief 检查设备格式支持。
* @param device 设备类型
* @param format 格式
* @return true 支持,false 不支持
*/
bool AudioPolicy::isFormatSupported(audio_devices_t device, audio_format_t format)
{
if (mPolicyConfig.device_configs.find(device) == mPolicyConfig.device_configs.end()) {
return false;
}
DeviceConfig &config = mPolicyConfig.device_configs[device];
for (audio_format_t fmt : config.supported_formats) {
if (fmt == format) {
return true;
}
}
return false;
}
/**
* @brief 检查设备采样率支持。
* @param device 设备类型
* @param rate 采样率
* @return true 支持,false 不支持
*/
bool AudioPolicy::isSampleRateSupported(audio_devices_t device, uint32_t rate)
{
if (mPolicyConfig.device_configs.find(device) == mPolicyConfig.device_configs.end()) {
return false;
}
DeviceConfig &config = mPolicyConfig.device_configs[device];
for (uint32_t sample_rate : config.supported_sample_rates) {
if (sample_rate == rate) {
return true;
}
}
return false;
}
3.4 软件设计模式树形分析
AudioPolicy 设计模式 ├── 工厂模式 (Factory Pattern) │ ├── getRoutingStrategy():创建路由策略实例 │ └── registerDevice():创建设备配置实例 ├── 适配器模式 (Adapter Pattern) │ ├── AudioPolicyManager:适配不同策略管理器 │ └── AudioPolicy 适配 AudioFlinger ├── 策略模式 (Strategy Pattern) │ ├── RoutingStrategy:路由选择策略 │ ├── VolumeStrategy:音量控制策略 │ └── FormatStrategy:格式支持策略 ├── 观察者模式 (Observer Pattern) │ ├── onUSBDevicePlugged():观察设备插入事件 │ └── onUSBDeviceUnplugged():观察设备移除事件 ├── 状态模式 (State Pattern) │ └── 设备状态 (UNKNOWN/AVAILABLE/ACTIVE/INACTIVE) └── 单例模式 (Singleton Pattern) └── AudioPolicy:系统全局唯一实例
3.5 AudioPolicy 调试核心难点
3.5.1 设备切换延迟
现象:USB DAC 插入后,音频流切换延迟超过 500ms。
原因:
-
设备检测延迟。
-
路由重新计算耗时。
-
HAL 设备切换耗时。
解决方法:
-
优化设备检测流程。
-
提前缓存路由规则。
-
使用异步设备切换。
3.5.2 格式不匹配导致播放失败
现象:设备支持 192kHz/24bit,但播放 44.1kHz/16bit 时失败。
原因:
-
设备格式支持列表不完整。
-
采样率匹配算法错误。
-
HAL 层格式转换失败。
解决方法:
-
完善设备格式支持列表。
-
优化采样率匹配算法。
-
启用 HAL 层格式转换。
3.5.3 音量控制异常
现象:音量调节不线性,或音量突变。
原因:
-
音量曲线配置错误。
-
音量同步问题。
-
设备音量限制不匹配。
解决方法:
-
校准音量曲线。
-
优化音量同步机制。
-
同步设备音量限制。
3.6 与其他模块的协同
| 模块 | 协同方式 | 调试关键点 |
|---|---|---|
| AudioFlinger | 提供路由决策和执行 | 设备切换、格式协商 |
| AudioHAL | 提供设备能力查询 | 格式支持、采样率支持 |
| AudioPolicyManager | 管理策略配置 | 规则验证、配置加载 |
| 系统服务 | 热插拔事件通知 | 设备状态、事件分发 |
| 用户空间 | 策略配置和调试 | 规则配置、状态查询 |
第四部分 AudioTrack 与 AudioRecord 实现
4.1 AudioTrack 与 AudioRecord 概述
AudioTrack 和 AudioRecord 是 Android 音频框架中面向应用层的最核心 API。AudioTrack 负责音频播放,AudioRecord 负责音频录制。对于 HiFi 音频产品,正确配置和使用这两个 API 是实现高采样率、bit-perfect 输出和低延迟播放的关键。
4.1.1 AudioTrack 与 AudioRecord 架构
[应用层] ├── [Java] AudioTrack/AudioRecord └── [Native] android_media_AudioTrack.cpp ↓ [JNI 层] └── JNI 调用 ↓ [Native 层] ├── AudioTrack 核心 (libaudioflinger) └── AudioRecord 核心 (libaudioflinger) ↓ [AudioFlinger 服务] └── AudioFlinger 处理 ↓ [Audio HAL] └── 音频硬件访问
4.1.2 AudioTrack 与 AudioRecord 生命周期
[AudioTrack 生命周期] ↓ [new AudioTrack()] → [配置参数] → [set()] → [write()] → [start()] → [播放中] → [stop()] → [release()] ↑ ↑ ↑ ↑ ↓ [配置检查] [缓冲区分配] [数据写入] [状态切换] [播放完成] [AudioRecord 生命周期] ↓ [new AudioRecord()] → [配置参数] → [set()] → [startRecording()] → [录制中] → [stop()] → [release()] ↑ ↑ ↑ ↑ ↓ [配置检查] [缓冲区分配] [开始录制] [数据读取] [录制完成]
4.2 核心数据结构
4.2.1 AudioTrack 核心结构
/**
* @class AudioTrack
* @brief 用于音频播放的核心类。
*/
class AudioTrack {
public:
/**
* @brief 创建 AudioTrack 实例。
* @param config 音频流配置
* @param callback 数据回调
* @param user_data 用户数据
* @return AudioTrack 实例指针
*/
static sp<AudioTrack> create(const AudioTrackConfig &config,
AudioTrackCallback *callback,
void *user_data);
/**
* @brief 写入音频数据。
* @param data 音频数据
* @param size 数据大小 (字节)
* @param blocking 是否阻塞
* @return 实际写入字节数
*/
size_t write(const void *data, size_t size, bool blocking = true);
/**
* @brief 开始播放。
* @return 0 成功,负数错误
*/
int start();
/**
* @brief 停止播放。
* @return 0 成功,负数错误
*/
int stop();
/**
* @brief 暂停播放。
* @return 0 成功,负数错误
*/
int pause();
/**
* @brief 恢复播放。
* @return 0 成功,负数错误
*/
int resume();
/**
* @brief 释放 AudioTrack 资源。
*/
void release();
/**
* @brief 获取当前播放位置。
* @return 播放位置 (帧数)
*/
uint32_t getPosition();
/**
* @brief 获取当前延迟。
* @return 延迟 (微秒)
*/
uint32_t getLatency();
/**
* @brief 设置音量。
* @param left_volume 左声道音量 (0-1)
* @param right_volume 右声道音量 (0-1)
* @return 0 成功,负数错误
*/
int setVolume(float left_volume, float right_volume);
private:
AudioTrackConfig mConfig; /**< 音频配置 */
sp<AudioFlinger> mFlinger; /**< AudioFlinger 服务 */
audio_io_handle_t mOutput; /**< 输出句柄 */
void *mBuffer; /**< 播放缓冲区 */
size_t mBufferSize; /**< 缓冲区大小 */
size_t mFrameSize; /**< 帧大小 */
uint32_t mSampleRate; /**< 采样率 */
audio_format_t mFormat; /**< 音频格式 */
audio_channel_mask_t mChannelMask; /**< 通道掩码 */
uint32_t mPosition; /**< 当前播放位置 */
uint32_t mLatency; /**< 延迟 */
AudioTrackCallback *mCallback; /**< 回调 */
void *mUserData; /**< 用户数据 */
Mutex mLock; /**< 互斥锁 */
Condition mCond; /**< 条件变量 */
enum State {
STATE_STOPPED,
STATE_RUNNING,
STATE_PAUSED,
STATE_RELEASED
} mState; /**< 播放状态 */
};
4.2.2 AudioRecord 核心结构
/**
* @class AudioRecord
* @brief 用于音频录制的核心类。
*/
class AudioRecord {
public:
/**
* @brief 创建 AudioRecord 实例。
* @param config 音频录制配置
* @param callback 数据回调
* @param user_data 用户数据
* @return AudioRecord 实例指针
*/
static sp<AudioRecord> create(const AudioRecordConfig &config,
AudioRecordCallback *callback,
void *user_data);
/**
* @brief 读取音频数据。
* @param data 数据缓冲区
* @param size 请求大小 (字节)
* @param blocking 是否阻塞
* @return 实际读取字节数
*/
size_t read(void *data, size_t size, bool blocking = true);
/**
* @brief 开始录制。
* @return 0 成功,负数错误
*/
int start();
/**
* @brief 停止录制。
* @return 0 成功,负数错误
*/
int stop();
/**
* @brief 释放 AudioRecord 资源。
*/
void release();
/**
* @brief 获取当前录制位置。
* @return 录制位置 (帧数)
*/
uint32_t getPosition();
/**
* @brief 获取当前延迟。
* @return 延迟 (微秒)
*/
uint32_t getLatency();
private:
AudioRecordConfig mConfig; /**< 录制配置 */
sp<AudioFlinger> mFlinger; /**< AudioFlinger 服务 */
audio_io_handle_t mInput; /**< 输入句柄 */
void *mBuffer; /**< 录制缓冲区 */
size_t mBufferSize; /**< 缓冲区大小 */
size_t mFrameSize; /**< 帧大小 */
uint32_t mSampleRate; /**< 采样率 */
audio_format_t mFormat; /**< 音频格式 */
audio_channel_mask_t mChannelMask; /**< 通道掩码 */
uint32_t mPosition; /**< 当前录制位置 */
uint32_t mLatency; /**< 延迟 */
AudioRecordCallback *mCallback; /**< 回调 */
void *mUserData; /**< 用户数据 */
Mutex mLock; /**< 互斥锁 */
Condition mCond; /**< 条件变量 */
enum State {
STATE_STOPPED,
STATE_RUNNING,
STATE_RELEASED
} mState; /**< 录制状态 */
};
4.2.3 AudioTrack 配置结构
/**
* @struct AudioTrackConfig
* @brief AudioTrack 配置结构。
*/
struct AudioTrackConfig {
uint32_t sample_rate; /**< 采样率 */
audio_format_t format; /**< 音频格式 */
audio_channel_mask_t channel_mask; /**< 通道掩码 */
uint32_t buffer_size; /**< 缓冲区大小 (帧数) */
uint32_t period_size; /**< 周期大小 (帧数) */
uint32_t period_count; /**< 周期数量 */
audio_output_flags_t flags; /**< 输出标志 */
audio_devices_t device; /**< 输出设备 */
uint32_t session_id; /**< 会话 ID */
bool is_raw; /**< 是否 RAW 模式 */
bool is_bit_perfect; /**< 是否 Bit-perfect */
bool is_dsd; /**< 是否 DSD 模式 */
bool is_multi_channel; /**< 是否多通道 */
bool is_low_latency; /**< 是否低延迟 */
bool is_offloaded; /**< 是否卸载播放 */
};
4.3 核心代码实现
4.3.1 AudioTrack 创建与配置
#include <media/AudioTrack.h>
#include <media/AudioFlinger.h>
#include <system/audio.h>
/**
* @brief 创建 AudioTrack 实例。
* @param config 音频流配置
* @param callback 数据回调
* @param user_data 用户数据
* @return AudioTrack 实例指针
*/
sp<AudioTrack> AudioTrack::create(const AudioTrackConfig &config,
AudioTrackCallback *callback,
void *user_data)
{
sp<AudioTrack> track = new AudioTrack();
if (!track) {
LOGE("Failed to allocate AudioTrack");
return nullptr;
}
// 1. 保存配置
track->mConfig = config;
track->mCallback = callback;
track->mUserData = user_data;
track->mState = STATE_STOPPED;
track->mPosition = 0;
track->mLatency = 0;
// 2. 获取 AudioFlinger 服务
track->mFlinger = AudioFlinger::getInstance();
if (!track->mFlinger) {
LOGE("Failed to get AudioFlinger service");
return nullptr;
}
// 3. 打开输出设备
track->mOutput = track->mFlinger->openOutput(config.device, config);
if (track->mOutput < 0) {
LOGE("Failed to open output device");
return nullptr;
}
// 4. 分配缓冲区
track->mBufferSize = config.buffer_size * config.period_count * config.period_size;
track->mBuffer = malloc(track->mBufferSize);
if (!track->mBuffer) {
LOGE("Failed to allocate buffer");
track->mFlinger->closeOutput(track->mOutput);
return nullptr;
}
// 5. 计算帧大小
track->mFrameSize = audio_bytes_per_sample(config.format) *
audio_channel_count_from_mask(config.channel_mask);
if (track->mFrameSize == 0) {
LOGE("Failed to calculate frame size");
free(track->mBuffer);
track->mFlinger->closeOutput(track->mOutput);
return nullptr;
}
return track;
}
/**
* @brief 配置 AudioTrack 的格式和采样率。
* @param format 音频格式
* @param sample_rate 采样率
* @param channel_mask 通道掩码
* @return 0 成功,负数错误
*/
int AudioTrack::setFormat(audio_format_t format,
uint32_t sample_rate,
audio_channel_mask_t channel_mask)
{
AutoMutex _l(mLock);
// 1. 检查格式支持
if (!mFlinger->isFormatSupported(mOutput, format)) {
LOGE("Format not supported");
return -ENOTSUPP;
}
// 2. 检查采样率支持
if (!mFlinger->isSampleRateSupported(mOutput, sample_rate)) {
LOGE("Sample rate not supported");
return -ENOTSUPP;
}
// 3. 配置新的格式
mConfig.format = format;
mConfig.sample_rate = sample_rate;
mConfig.channel_mask = channel_mask;
mFrameSize = audio_bytes_per_sample(format) *
audio_channel_count_from_mask(channel_mask);
// 4. 通知 AudioFlinger
mFlinger->setFormat(mOutput, format, sample_rate, channel_mask);
return 0;
}
4.3.2 AudioTrack 数据写入
/**
* @brief 写入音频数据。
* @param data 音频数据
* @param size 数据大小 (字节)
* @param blocking 是否阻塞
* @return 实际写入字节数
*/
size_t AudioTrack::write(const void *data, size_t size, bool blocking)
{
AutoMutex _l(mLock);
if (mState != STATE_RUNNING) {
LOGE("AudioTrack not running");
return 0;
}
if (!data || size == 0) {
return 0;
}
// 1. 检查数据大小
if (size > mBufferSize) {
size = mBufferSize;
}
// 2. 复制数据到缓冲区
memcpy(mBuffer, data, size);
// 3. 提交到 AudioFlinger
size_t written = mFlinger->write(mOutput, mBuffer, size, blocking);
if (written > 0) {
mPosition += written / mFrameSize;
}
return written;
}
/**
* @brief 非阻塞写入数据。
* @param data 音频数据
* @param size 数据大小 (字节)
* @return 实际写入字节数
*/
size_t AudioTrack::writeNonBlocking(const void *data, size_t size)
{
return write(data, size, false);
}
/**
* @brief 异步写入数据 (回调模式)。
* @param data 音频数据
* @param size 数据大小 (字节)
* @return 0 成功,负数错误
*/
int AudioTrack::writeAsync(const void *data, size_t size)
{
if (mCallback) {
mCallback->onDataReady(data, size, mUserData);
return 0;
}
return -EINVAL;
}
4.3.3 AudioTrack 启动与停止
/**
* @brief 开始播放。
* @return 0 成功,负数错误
*/
int AudioTrack::start()
{
AutoMutex _l(mLock);
if (mState == STATE_RUNNING) {
return 0;
}
if (mState == STATE_RELEASED) {
LOGE("AudioTrack already released");
return -EINVAL;
}
// 1. 通知 AudioFlinger
int result = mFlinger->start(mOutput);
if (result < 0) {
LOGE("Failed to start playback");
return result;
}
// 2. 更新状态
mState = STATE_RUNNING;
return 0;
}
/**
* @brief 停止播放。
* @return 0 成功,负数错误
*/
int AudioTrack::stop()
{
AutoMutex _l(mLock);
if (mState == STATE_STOPPED) {
return 0;
}
// 1. 通知 AudioFlinger
int result = mFlinger->stop(mOutput);
if (result < 0) {
LOGE("Failed to stop playback");
return result;
}
// 2. 更新状态
mState = STATE_STOPPED;
return 0;
}
/**
* @brief 暂停播放。
* @return 0 成功,负数错误
*/
int AudioTrack::pause()
{
AutoMutex _l(mLock);
if (mState != STATE_RUNNING) {
return -EINVAL;
}
// 1. 通知 AudioFlinger
int result = mFlinger->pause(mOutput);
if (result < 0) {
LOGE("Failed to pause playback");
return result;
}
// 2. 更新状态
mState = STATE_PAUSED;
return 0;
}
/**
* @brief 恢复播放。
* @return 0 成功,负数错误
*/
int AudioTrack::resume()
{
AutoMutex _l(mLock);
if (mState != STATE_PAUSED) {
return -EINVAL;
}
// 1. 通知 AudioFlinger
int result = mFlinger->resume(mOutput);
if (result < 0) {
LOGE("Failed to resume playback");
return result;
}
// 2. 更新状态
mState = STATE_RUNNING;
return 0;
}
4.3.4 AudioRecord 数据读取
/**
* @brief 读取音频数据。
* @param data 数据缓冲区
* @param size 请求大小 (字节)
* @param blocking 是否阻塞
* @return 实际读取字节数
*/
size_t AudioRecord::read(void *data, size_t size, bool blocking)
{
AutoMutex _l(mLock);
if (mState != STATE_RUNNING) {
LOGE("AudioRecord not running");
return 0;
}
if (!data || size == 0) {
return 0;
}
// 1. 检查数据大小
if (size > mBufferSize) {
size = mBufferSize;
}
// 2. 从 AudioFlinger 读取数据
size_t read = mFlinger->read(mInput, data, size, blocking);
if (read > 0) {
mPosition += read / mFrameSize;
}
return read;
}
/**
* @brief 非阻塞读取数据。
* @param data 数据缓冲区
* @param size 请求大小 (字节)
* @return 实际读取字节数
*/
size_t AudioRecord::readNonBlocking(void *data, size_t size)
{
return read(data, size, false);
}
4.3.5 Bit-perfect 模式支持
/**
* @brief 设置 Bit-perfect 模式。
* @param enable 是否启用
* @return 0 成功,负数错误
*/
int AudioTrack::setBitPerfectMode(bool enable)
{
AutoMutex _l(mLock);
if (mState == STATE_RELEASED) {
return -EINVAL;
}
// 1. 检查设备是否支持
if (enable && !mFlinger->isBitPerfectSupported(mOutput)) {
LOGE("Bit-perfect mode not supported");
return -ENOTSUPP;
}
// 2. 更新配置
mConfig.is_bit_perfect = enable;
if (enable) {
mConfig.flags |= AUDIO_OUTPUT_FLAG_RAW;
} else {
mConfig.flags &= ~AUDIO_OUTPUT_FLAG_RAW;
}
// 3. 通知 AudioFlinger
mFlinger->setBitPerfectMode(mOutput, enable);
return 0;
}
/**
* @brief 设置 DSD 模式。
* @param enable 是否启用
* @return 0 成功,负数错误
*/
int AudioTrack::setDSDMode(bool enable)
{
AutoMutex _l(mLock);
if (mState == STATE_RELEASED) {
return -EINVAL;
}
// 1. 检查设备是否支持
if (enable && !mFlinger->isDSDSupported(mOutput)) {
LOGE("DSD mode not supported");
return -ENOTSUPP;
}
// 2. 更新配置
mConfig.is_dsd = enable;
if (enable) {
mConfig.format = AUDIO_FORMAT_DSD;
mConfig.flags |= AUDIO_OUTPUT_FLAG_DSD;
}
// 3. 通知 AudioFlinger
mFlinger->setDSDMode(mOutput, enable);
return 0;
}
4.3.6 延迟控制
/**
* @brief 获取当前延迟。
* @return 延迟 (微秒)
*/
uint32_t AudioTrack::getLatency()
{
AutoMutex _l(mLock);
if (mState == STATE_RELEASED) {
return 0;
}
// 从 AudioFlinger 获取延迟
mLatency = mFlinger->getLatency(mOutput);
return mLatency;
}
/**
* @brief 设置延迟目标。
* @param latency_us 目标延迟 (微秒)
* @return 0 成功,负数错误
*/
int AudioTrack::setLatencyTarget(uint32_t latency_us)
{
AutoMutex _l(mLock);
if (mState == STATE_RELEASED) {
return -EINVAL;
}
// 1. 检查延迟范围
if (latency_us < 1000 || latency_us > 100000) {
LOGE("Invalid latency target");
return -EINVAL;
}
// 2. 计算缓冲区大小
uint32_t period_size = latency_us * mConfig.sample_rate / 1000000;
uint32_t buffer_size = period_size * mConfig.period_count;
// 3. 调整缓冲区大小
if (buffer_size > mBufferSize) {
// 重新分配缓冲区
free(mBuffer);
mBufferSize = buffer_size;
mBuffer = malloc(mBufferSize);
if (!mBuffer) {
LOGE("Failed to allocate buffer");
return -ENOMEM;
}
}
// 4. 通知 AudioFlinger
mFlinger->setLatency(mOutput, latency_us);
mLatency = latency_us;
return 0;
}
4.4 软件设计模式树形分析
AudioTrack/AudioRecord 设计模式 ├── 工厂模式 (Factory Pattern) │ ├── AudioTrack::create():创建 AudioTrack 实例 │ └── AudioRecord::create():创建 AudioRecord 实例 ├── 适配器模式 (Adapter Pattern) │ ├── AudioTrack 适配 AudioFlinger 接口 │ └── AudioRecord 适配 AudioFlinger 接口 ├── 策略模式 (Strategy Pattern) │ ├── write():数据写入策略 │ ├── read():数据读取策略 │ └── Bit-perfect 模式:是否启用 RAW 模式 ├── 观察者模式 (Observer Pattern) │ └── AudioTrackCallback:观察数据就绪事件 ├── 状态模式 (State Pattern) │ ├── AudioTrack 状态 (STOPPED/RUNNING/PAUSED/RELEASED) │ └── AudioRecord 状态 (STOPPED/RUNNING/RELEASED) └── 模板方法模式 (Template Method Pattern) ├── AudioTrack::write():定义了数据写入的标准流程 └── AudioRecord::read():定义了数据读取的标准流程
4.5 AudioTrack/AudioRecord 调试核心难点
4.5.1 延迟优化
现象:音频播放延迟过高,影响实时性。
原因:
-
缓冲区设置过大。
-
数据写入阻塞。
-
AudioFlinger 处理延迟。
解决方法:
-
减小缓冲区大小和周期大小。
-
使用非阻塞写入模式。
-
提升 AudioFlinger 线程优先级。
4.5.2 Bit-perfect 输出失败
现象:启用 bit-perfect 模式后,音频仍被处理。
原因:
-
AudioFlinger 未正确配置。
-
HAL 层进行了格式转换。
-
音频策略启用了重采样。
解决方法:
-
在 AudioFlinger 中强制禁用混音器。
-
确保 HAL 层直通传输。
-
在 AudioPolicy 中禁用自动重采样。
4.5.3 DSD 播放异常
现象:DSD 格式无法播放或播放异常。
原因:
-
AudioFlinger 不支持 DSD 格式。
-
HAL 层 DSD 支持不完整。
-
DSD 数据包大小不匹配。
解决方法:
-
确认 AudioFlinger 支持 DSD。
-
检查 HAL 层 DSD 支持。
-
调整 DSD 数据包大小。
4.5.4 多声道支持
现象:5.1 或 7.1 声道无法播放。
原因:
-
设备不支持多声道。
-
AudioFlinger 下混。
-
声道映射错误。
解决方法:
-
确认设备支持多声道。
-
禁用 AudioFlinger 下混。
-
正确配置声道映射。
4.6 与其他模块的协同
| 模块 | 协同方式 | 调试关键点 |
|---|---|---|
| AudioFlinger | 提供音频流管理和设备路由 | 延迟控制、格式支持 |
| AudioPolicy | 提供设备路由策略 | 设备选择、格式协商 |
| Audio HAL | 提供硬件访问接口 | 格式支持、延迟控制 |
| Java 层 | 通过 JNI 调用 AudioTrack | JNI 接口、权限控制 |
| 应用层 | 通过 AudioTrack API 播放 | 缓冲区管理、延迟控制 |
| 用户空间 | 配置 AudioTrack 参数 | 采样率、格式、通道数 |
第五部分 AudioEffect 与音频处理链
5.1 AudioEffect 概述
AudioEffect 是 Android 音频框架中用于音频信号处理的核心组件,它允许在音频流上应用各种效果,如均衡器 (EQ)、混响 (Reverb)、压缩器 (Compressor)、立体声扩展等。对于 HiFi 音频产品,理解 AudioEffect 的内部机制对于实现 bit-perfect 输出、优化延迟和控制 CPU 负载至关重要。
5.1.1 AudioEffect 架构
[应用层] ├── [Java] AudioEffect 类 └── [Native] android_media_AudioEffect.cpp ↓ [JNI 层] └── JNI 调用 ↓ [Native 层] ├── AudioEffect 核心 (libaudioflinger) ├── AudioEffectChain 管理器 └── 效果处理器 (Effect Processor) ↓ [AudioFlinger 服务] └── AudioEffect 处理线程 ↓ [Audio HAL] └── 效果数据输出
5.1.2 效果处理链
[音频源] → [AudioFlinger] → [Effect Chain 1] → [Effect Chain 2] → ... → [Effect Chain N] → [Audio HAL] ↓ ↓ ↓ ↓ ↓ [输入数据] [效果 1 处理] [效果 2 处理] [效果 N 处理] [输出数据]
5.2 核心数据结构
5.2.1 AudioEffect 核心结构
/**
* @class AudioEffect
* @brief 用于音频效果处理的核心类。
*/
class AudioEffect {
public:
/**
* @brief 创建 AudioEffect 实例。
* @param config 效果配置
* @param callback 效果回调
* @param user_data 用户数据
* @return AudioEffect 实例指针
*/
static sp<AudioEffect> create(const AudioEffectConfig &config,
AudioEffectCallback *callback,
void *user_data);
/**
* @brief 获取效果 ID。
* @return 效果 ID
*/
uint32_t getId() const { return mId; }
/**
* @brief 处理音频数据。
* @param input 输入数据
* @param output 输出数据
* @param size 数据大小 (字节)
* @return 0 成功,负数错误
*/
int process(const void *input, void *output, size_t size);
/**
* @brief 启用效果。
* @param enable 是否启用
* @return 0 成功,负数错误
*/
int setEnabled(bool enable);
/**
* @brief 获取效果是否启用。
* @return true 启用,false 禁用
*/
bool isEnabled() const { return mEnabled; }
/**
* @brief 设置效果参数。
* @param param 参数 ID
* @param value 参数值
* @return 0 成功,负数错误
*/
int setParameter(uint32_t param, float value);
/**
* @brief 获取效果参数。
* @param param 参数 ID
* @return 参数值
*/
float getParameter(uint32_t param);
/**
* @brief 重置效果。
* @return 0 成功,负数错误
*/
int reset();
/**
* @brief 释放效果资源。
*/
void release();
private:
uint32_t mId; /**< 效果 ID */
AudioEffectConfig mConfig; /**< 效果配置 */
bool mEnabled; /**< 是否启用 */
void *mEffectHandle; /**< 效果句柄 */
size_t mInputBufferSize; /**< 输入缓冲区大小 */
size_t mOutputBufferSize; /**< 输出缓冲区大小 */
void *mInputBuffer; /**< 输入缓冲区 */
void *mOutputBuffer; /**< 输出缓冲区 */
AudioEffectCallback *mCallback; /**< 回调 */
void *mUserData; /**< 用户数据 */
Mutex mLock; /**< 互斥锁 */
Condition mCond; /**< 条件变量 */
uint32_t mLatency; /**< 处理延迟 (微秒) */
uint32_t mCpuUsage; /**< CPU 使用率 */
enum State {
STATE_INITIALIZED,
STATE_RUNNING,
STATE_RELEASED
} mState; /**< 效果状态 */
};
5.2.2 AudioEffectChain 结构
/**
* @class AudioEffectChain
* @brief 音频效果链管理类。
*/
class AudioEffectChain {
public:
/**
* @brief 创建 AudioEffectChain 实例。
* @return AudioEffectChain 实例指针
*/
static sp<AudioEffectChain> create();
/**
* @brief 添加效果到链尾。
* @param effect 效果实例
* @return 0 成功,负数错误
*/
int addEffect(const sp<AudioEffect> &effect);
/**
* @brief 从链中移除效果。
* @param effect_id 效果 ID
* @return 0 成功,负数错误
*/
int removeEffect(uint32_t effect_id);
/**
* @brief 处理链中所有效果。
* @param input 输入数据
* @param output 输出数据
* @param size 数据大小 (字节)
* @return 0 成功,负数错误
*/
int process(const void *input, void *output, size_t size);
/**
* @brief 启用/禁用链中所有效果。
* @param enable 是否启用
* @return 0 成功,负数错误
*/
int setEnabled(bool enable);
/**
* @brief 获取链中效果数量。
* @return 效果数量
*/
size_t getEffectCount() const { return mEffects.size(); }
/**
* @brief 重置链中所有效果。
* @return 0 成功,负数错误
*/
int reset();
private:
std::vector<sp<AudioEffect>> mEffects; /**< 效果列表 */
Mutex mLock; /**< 互斥锁 */
Condition mCond; /**< 条件变量 */
bool mEnabled; /**< 是否启用 */
uint32_t mLatency; /**< 总延迟 (微秒) */
uint32_t mCpuUsage; /**< 总 CPU 使用率 */
};
5.2.3 AudioEffect 配置结构
/**
* @struct AudioEffectConfig
* @brief AudioEffect 配置结构。
*/
struct AudioEffectConfig {
uint32_t id; /**< 效果 ID */
uint32_t type; /**< 效果类型 (EQ/REVERB/COMPRESSOR) */
uint32_t sample_rate; /**< 采样率 */
audio_format_t format; /**< 音频格式 */
audio_channel_mask_t channel_mask; /**< 通道掩码 */
uint32_t buffer_size; /**< 缓冲区大小 (帧数) */
uint32_t latency_us; /**< 延迟 (微秒) */
float cpu_usage; /**< CPU 使用率 */
bool is_enabled; /**< 是否启用 */
bool is_required; /**< 是否必需 */
bool is_bit_perfect; /**< 是否 Bit-perfect */
bool is_offload; /**< 是否卸载 */
std::vector<EffectParameter> parameters; /**< 参数列表 */
std::string name; /**< 效果名称 */
std::string description; /**< 效果描述 */
};
5.3 核心代码实现
5.3.1 AudioEffect 创建与配置
#include <media/AudioEffect.h>
#include <media/AudioFlinger.h>
#include <system/audio_effect.h>
/**
* @brief 创建 AudioEffect 实例。
* @param config 效果配置
* @param callback 效果回调
* @param user_data 用户数据
* @return AudioEffect 实例指针
*/
sp<AudioEffect> AudioEffect::create(const AudioEffectConfig &config,
AudioEffectCallback *callback,
void *user_data)
{
sp<AudioEffect> effect = new AudioEffect();
if (!effect) {
LOGE("Failed to allocate AudioEffect");
return nullptr;
}
// 1. 保存配置
effect->mConfig = config;
effect->mCallback = callback;
effect->mUserData = user_data;
effect->mState = STATE_INITIALIZED;
effect->mId = config.id;
effect->mEnabled = config.is_enabled;
effect->mLatency = config.latency_us;
// 2. 分配缓冲区
effect->mInputBufferSize = config.buffer_size * audio_bytes_per_sample(config.format) *
audio_channel_count_from_mask(config.channel_mask);
effect->mOutputBufferSize = effect->mInputBufferSize;
effect->mInputBuffer = malloc(effect->mInputBufferSize);
effect->mOutputBuffer = malloc(effect->mOutputBufferSize);
if (!effect->mInputBuffer || !effect->mOutputBuffer) {
LOGE("Failed to allocate buffers");
free(effect->mInputBuffer);
free(effect->mOutputBuffer);
return nullptr;
}
// 3. 创建效果句柄
effect->mEffectHandle = AudioEffectFlinger::createEffect(config);
if (!effect->mEffectHandle) {
LOGE("Failed to create effect handle");
free(effect->mInputBuffer);
free(effect->mOutputBuffer);
return nullptr;
}
// 4. 注册到 AudioFlinger
AudioFlinger::getInstance()->registerEffect(effect);
return effect;
}
/**
* @brief 效果配置参数。
* @param param 参数 ID
* @param value 参数值
* @return 0 成功,负数错误
*/
int AudioEffect::setParameter(uint32_t param, float value)
{
AutoMutex _l(mLock);
if (mState == STATE_RELEASED) {
return -EINVAL;
}
// 1. 获取参数范围
float min_val = 0.0f, max_val = 1.0f;
if (mConfig.type == EFFECT_TYPE_EQ) {
min_val = -12.0f;
max_val = 12.0f;
}
// 2. 检查参数范围
if (value < min_val || value > max_val) {
LOGE("Parameter value out of range");
return -EINVAL;
}
// 3. 应用参数
AudioEffectFlinger::setParameter(mEffectHandle, param, value);
return 0;
}
5.3.2 AudioEffect 处理链
/**
* @brief 创建 AudioEffectChain 实例。
* @return AudioEffectChain 实例指针
*/
sp<AudioEffectChain> AudioEffectChain::create()
{
sp<AudioEffectChain> chain = new AudioEffectChain();
if (!chain) {
return nullptr;
}
chain->mEnabled = true;
chain->mLatency = 0;
chain->mCpuUsage = 0;
return chain;
}
/**
* @brief 添加效果到链尾。
* @param effect 效果实例
* @return 0 成功,负数错误
*/
int AudioEffectChain::addEffect(const sp<AudioEffect> &effect)
{
AutoMutex _l(mLock);
if (!effect) {
return -EINVAL;
}
// 1. 检查效果是否已在链中
for (const auto &existing : mEffects) {
if (existing->getId() == effect->getId()) {
LOGE("Effect already in chain");
return -EEXIST;
}
}
// 2. 添加到链尾
mEffects.push_back(effect);
// 3. 更新总延迟和 CPU 使用率
mLatency += effect->getLatency();
mCpuUsage += effect->getCpuUsage();
return 0;
}
/**
* @brief 从链中移除效果。
* @param effect_id 效果 ID
* @return 0 成功,负数错误
*/
int AudioEffectChain::removeEffect(uint32_t effect_id)
{
AutoMutex _l(mLock);
for (auto it = mEffects.begin(); it != mEffects.end(); ++it) {
if ((*it)->getId() == effect_id) {
// 更新总延迟和 CPU 使用率
mLatency -= (*it)->getLatency();
mCpuUsage -= (*it)->getCpuUsage();
mEffects.erase(it);
return 0;
}
}
return -ENOENT;
}
/**
* @brief 处理链中所有效果。
* @param input 输入数据
* @param output 输出数据
* @param size 数据大小 (字节)
* @return 0 成功,负数错误
*/
int AudioEffectChain::process(const void *input, void *output, size_t size)
{
AutoMutex _l(mLock);
if (!mEnabled) {
// 链被禁用,直接拷贝
memcpy(output, input, size);
return 0;
}
// 1. 检查是否有效果
if (mEffects.empty()) {
memcpy(output, input, size);
return 0;
}
// 2. 逐级处理
const void *current_input = input;
void *current_output = output;
size_t current_size = size;
for (size_t i = 0; i < mEffects.size(); i++) {
const auto &effect = mEffects[i];
if (!effect->isEnabled()) {
continue;
}
// 如果是最后一个效果,直接输出到 output
if (i == mEffects.size() - 1) {
effect->process(current_input, output, current_size);
break;
}
// 中间效果,处理到临时缓冲区
if (current_input == input && current_output == output) {
// 第一次处理,使用效果自己的缓冲区
effect->process(current_input, effect->getOutputBuffer(), current_size);
current_input = effect->getOutputBuffer();
current_output = output;
} else {
// 后续处理,交替使用缓冲区
effect->process(current_input, effect->getOutputBuffer(), current_size);
current_input = effect->getOutputBuffer();
}
}
return 0;
}
5.3.3 均衡器 (EQ) 实现
/**
* @class EqualizerEffect
* @brief 均衡器效果实现。
*/
class EqualizerEffect : public AudioEffect {
public:
/**
* @brief 创建均衡器效果。
* @param config 效果配置
* @param callback 回调
* @param user_data 用户数据
* @return EqualizerEffect 实例指针
*/
static sp<EqualizerEffect> create(const AudioEffectConfig &config,
AudioEffectCallback *callback,
void *user_data)
{
sp<EqualizerEffect> effect = new EqualizerEffect();
if (!effect) {
return nullptr;
}
effect->init(config, callback, user_data);
effect->mConfig.type = EFFECT_TYPE_EQ;
effect->mConfig.name = "Equalizer";
effect->mConfig.description = "Multi-band Equalizer";
// 初始化均衡器参数
effect->mBandCount = config.parameters.size() > 0 ? config.parameters[0].value_int : 5;
effect->mGains.resize(effect->mBandCount, 0.0f);
effect->mFrequencies.resize(effect->mBandCount, 0);
// 设置默认频率
if (effect->mBandCount == 5) {
effect->mFrequencies = {60, 230, 910, 3600, 14000};
}
return effect;
}
/**
* @brief 处理音频数据 (EQ 实现)。
* @param input 输入数据
* @param output 输出数据
* @param size 数据大小 (字节)
* @return 0 成功,负数错误
*/
int process(const void *input, void *output, size_t size) override
{
if (!mEnabled) {
memcpy(output, input, size);
return 0;
}
// 1. 检查输入和输出
if (!input || !output) {
return -EINVAL;
}
// 2. 执行 EQ 处理
// 实际 EQ 算法会使用多个滤波器, 此处简化
const float *in = (const float *)input;
float *out = (float *)output;
size_t frame_count = size / (mConfig.frame_size * mConfig.channel_count);
// 简单实现:按频段增益处理
for (size_t i = 0; i < frame_count; i++) {
for (size_t ch = 0; ch < mConfig.channel_count; ch++) {
float sample = in[i * mConfig.channel_count + ch];
// 应用 EQ 增益
for (size_t band = 0; band < mBandCount; band++) {
// 实际实现会使用 IIR/FIR 滤波器
// 此处仅作增益缩放演示
float gain_factor = pow(10.0f, mGains[band] / 20.0f);
sample *= gain_factor;
}
out[i * mConfig.channel_count + ch] = sample;
}
}
return 0;
}
/**
* @brief 设置频段增益。
* @param band_index 频段索引
* @param gain 增益 (dB)
* @return 0 成功,负数错误
*/
int setBandGain(int band_index, float gain)
{
if (band_index < 0 || band_index >= mBandCount) {
return -EINVAL;
}
if (gain < -12.0f || gain > 12.0f) {
return -EINVAL;
}
mGains[band_index] = gain;
return 0;
}
private:
int mBandCount; /**< 频段数量 */
std::vector<float> mGains; /**< 各频段增益 (dB) */
std::vector<int> mFrequencies; /**< 各频段中心频率 (Hz) */
};
5.3.4 混响 (Reverb) 实现
/**
* @class ReverbEffect
* @brief 混响效果实现。
*/
class ReverbEffect : public AudioEffect {
public:
/**
* @brief 创建混响效果。
* @param config 效果配置
* @param callback 回调
* @param user_data 用户数据
* @return ReverbEffect 实例指针
*/
static sp<ReverbEffect> create(const AudioEffectConfig &config,
AudioEffectCallback *callback,
void *user_data)
{
sp<ReverbEffect> effect = new ReverbEffect();
if (!effect) {
return nullptr;
}
effect->init(config, callback, user_data);
effect->mConfig.type = EFFECT_TYPE_REVERB;
effect->mConfig.name = "Reverb";
effect->mConfig.description = "Hall Reverb";
// 初始化混响参数
effect->mRoomSize = 100; // 房间大小 (0-100)
effect->mReverbTime = 2.0f; // 混响时间 (秒)
effect->mDamping = 0.5f; // 阻尼系数
effect->mWetDryMix = 0.3f; // 干湿混合
return effect;
}
/**
* @brief 处理音频数据 (混响实现)。
* @param input 输入数据
* @param output 输出数据
* @param size 数据大小 (字节)
* @return 0 成功,负数错误
*/
int process(const void *input, void *output, size_t size) override
{
if (!mEnabled) {
memcpy(output, input, size);
return 0;
}
// 实际混响算法使用延迟线, 此处简化为简单的滤波处理
const float *in = (const float *)input;
float *out = (float *)output;
size_t frame_count = size / (mConfig.frame_size * mConfig.channel_count);
// 模拟混响处理
for (size_t i = 0; i < frame_count; i++) {
for (size_t ch = 0; ch < mConfig.channel_count; ch++) {
float sample = in[i * mConfig.channel_count + ch];
// 简化的混响模拟
float wet = sample * mWetDryMix;
float dry = sample * (1.0f - mWetDryMix);
out[i * mConfig.channel_count + ch] = dry + wet * 0.5f;
}
}
return 0;
}
/**
* @brief 设置混响时间。
* @param time 混响时间 (秒)
* @return 0 成功,负数错误
*/
int setReverbTime(float time)
{
if (time < 0.1f || time > 10.0f) {
return -EINVAL;
}
mReverbTime = time;
return 0;
}
private:
float mRoomSize; /**< 房间大小 (0-100) */
float mReverbTime; /**< 混响时间 (秒) */
float mDamping; /**< 阻尼系数 */
float mWetDryMix; /**< 干湿混合 */
};
5.3.5 Bit-perfect 模式绕过效果
/**
* @brief 设置 Bit-perfect 模式。
* @param enable 是否启用
* @return 0 成功,负数错误
*/
int AudioEffectChain::setBitPerfectMode(bool enable)
{
AutoMutex _l(mLock);
// 1. Bit-perfect 模式下,禁用所有效果
if (enable) {
for (auto &effect : mEffects) {
effect->setEnabled(false);
}
mEnabled = false;
return 0;
}
// 2. 恢复效果启用状态
mEnabled = true;
for (auto &effect : mEffects) {
effect->setEnabled(effect->getConfig().is_enabled);
}
return 0;
}
/**
* @brief 检查效果链是否支持 Bit-perfect。
* @return true 支持,false 不支持
*/
bool AudioEffectChain::isBitPerfectSupported() const
{
// 1. 如果有任何效果启用,则不是 Bit-perfect
for (const auto &effect : mEffects) {
if (effect->isEnabled()) {
return false;
}
}
return true;
}
5.3.6 延迟测量与 CPU 监控
/**
* @brief 测量效果链延迟。
* @return 延迟 (微秒)
*/
uint32_t AudioEffectChain::measureLatency()
{
AutoMutex _l(mLock);
uint32_t total_latency = 0;
for (const auto &effect : mEffects) {
total_latency += effect->getLatency();
}
mLatency = total_latency;
return total_latency;
}
/**
* @brief 监控 CPU 使用率。
* @return CPU 使用率 (0-100)
*/
float AudioEffectChain::getCpuUsage()
{
AutoMutex _l(mLock);
uint32_t total_cpu = 0;
for (const auto &effect : mEffects) {
total_cpu += effect->getCpuUsage();
}
mCpuUsage = total_cpu;
return mCpuUsage;
}
/**
* @brief 效果处理性能统计。
*/
void AudioEffect::recordProcessingTime(uint64_t start_us, uint64_t end_us)
{
AutoMutex _l(mLock);
uint64_t delta = end_us - start_us;
mProcessingTime.addSample(delta);
mCpuUsage = (float)mProcessingTime.getAverage() / 10000.0f;
}
5.4 软件设计模式树形分析
AudioEffect 设计模式 ├── 工厂模式 (Factory Pattern) │ ├── AudioEffect::create():创建效果实例 │ └── AudioEffectChain::create():创建效果链 ├── 责任链模式 (Chain of Responsibility Pattern) │ └── AudioEffectChain:按顺序处理多个效果 ├── 策略模式 (Strategy Pattern) │ ├── EqualizerEffect:EQ 处理策略 │ ├── ReverbEffect:混响处理策略 │ └── Bit-perfect 模式:绕过效果策略 ├── 观察者模式 (Observer Pattern) │ └── AudioEffectCallback:观察处理完成事件 ├── 状态模式 (State Pattern) │ ├── AudioEffect 状态 (INITIALIZED/RUNNING/RELEASED) │ └── AudioEffectChain 状态 (启用/禁用) └── 装饰器模式 (Decorator Pattern) └── AudioEffectChain:装饰效果处理
5.5 AudioEffect 调试核心难点
5.5.1 处理延迟
现象:启用效果后,音频延迟显著增加。
原因:
-
每个效果的处理延迟累积。
-
缓冲区大小设置不当。
-
效果算法复杂度高。
解决方法:
-
检查效果链延迟。
-
优化效果算法。
-
使用低延迟效果算法。
5.5.2 性能瓶颈
现象:启用效果后,CPU 使用率飙升。
原因:
-
效果算法复杂。
-
处理频率高。
-
缓冲区太小。
解决方法:
-
简化效果算法。
-
降低处理频率。
-
增加缓冲区大小。
5.5.3 Bit-perfect 冲突
现象:启用 bit-perfect 模式后,效果仍然生效。
原因:
-
AudioFlinger 未正确禁用效果。
-
HAL 层效果未完全绕过。
-
配置错误。
解决方法:
-
在 AudioFlinger 中强制禁用效果。
-
在 HAL 层实现直通模式。
-
检查 Bit-perfect 配置。
5.6 与其他模块的协同
| 模块 | 协同方式 | 调试关键点 |
|---|---|---|
| AudioFlinger | 管理效果链和处理 | 延迟控制、CPU 监控 |
| AudioPolicy | 配置效果策略 | 效果启用、Bit-perfect 模式 |
| Audio HAL | 处理效果数据输出 | 延迟、格式支持 |
| 应用层 | 通过 AudioEffect API 控制 | 参数配置、状态管理 |
| 用户空间 | 效果参数配置和调试 | 参数范围、响应时间 |
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)