audio-audioflinger-应用音量到活跃流

好的,这是一个非常深入的问题。我们来详细分析 AudioFlinger 如何将应用设置的音量应用到活跃的音频流上。

  1. 整体音量应用流程

应用设置音量 → AudioManager → AudioService → AudioSystem → AudioFlinger

AudioPolicyService (音量曲线管理) → AudioFlinger (混音处理)

AudioFlinger::PlaybackThread → 应用音量 + 设备音量 + 主音量

AudioMixer → 音量应用 → 输出到HAL

  1. 详细源码调用流程

步骤1: 应用层设置音量

// 应用调用

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);

// frameworks/base/media/java/android/media/AudioManager.java

public void setStreamVolume(int streamType, int index, int flags) {

// 通过Binder调用AudioService

IAudioService service = getService();

service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName());

}

步骤2: AudioService处理

// frameworks/base/services/core/java/com/android/server/audio/AudioService.java

public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {

// 1. 权限检查和音量范围验证

ensureValidStreamType(streamType);

index = rescaleIndex(index, streamType);

复制代码
// 2. 获取对应流的音量控制器
VolumeStreamState streamState = mStreamStates[streamType];

// 3. 设置设备索引
int device = getDeviceForStream(streamType);
streamState.setIndex(index, device, callingPackage);

// 4. 通知AudioSystem
mAudioSystem.setStreamVolumeIndex(streamType, index, device);

// 5. 发送音量更新广播
sendBroadcastToAll(new Intent(AudioManager.VOLUME_CHANGED_ACTION));

}

步骤3: AudioSystem到AudioFlinger

// frameworks/av/media/libaudioclient/AudioSystem.cpp

status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value, audio_io_handle_t output) {

// 通过Binder调用AudioFlinger

const sp& af = AudioSystem::get_audio_flinger();

return af->setStreamVolume(stream, value, output);

}

步骤4: AudioFlinger接收音量设置

// frameworks/av/services/audioflinger/AudioFlinger.cpp

status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value, audio_io_handle_t output) {

// 1. 检查权限和参数有效性

if (!isStreamValid(stream)) return BAD_VALUE;

复制代码
// 2. 查找对应的播放线程
sp<PlaybackThread> thread = getPlaybackThread_l(output);
if (thread == 0) return BAD_VALUE;

// 3. 在线程中设置流音量
return thread->setStreamVolume(stream, value);

}

  1. PlaybackThread中的音量管理

PlaybackThread音量设置

// frameworks/av/services/audioflinger/Threads.cpp

status_t AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value) {

Mutex::Autolock _l(mLock);

复制代码
// 1. 存储流音量
mStreamTypes[stream].volume = value;

// 2. 立即应用到所有活跃的Track
for (size_t i = 0; i < mActiveTracks.size(); ++i) {
    sp<Track> track = mActiveTracks[i];
    if (track->streamType() == stream) {
        // 重新计算Track的音量
        track->setFinalVolume_l();
    }
}

// 3. 广播音量变化
broadcast_l();
return NO_ERROR;

}

Track音量计算

// frameworks/av/services/audioflinger/Tracks.cpp

void AudioFlinger::PlaybackThread::Track::setFinalVolume_l() {

// 1. 获取流类型音量

float streamVolume = mThread->mStreamTypes[mStreamType].volume;

复制代码
// 2. 获取主音量
float masterVolume = mThread->masterVolume();

// 3. 应用音频策略音量曲线
float volumeDb = AudioSystem::linearToLog(streamVolume * mVolume[0] * mVolume[1]);

// 4. 考虑静音状态
if (mThread->isStreamMuted(mStreamType)) {
    volumeDb = AUDIO_MIN_VOLUME;
}

// 5. 设置最终音量
mFinalVolume = AudioSystem::logToLinear(volumeDb) * masterVolume;

ALOGV("setFinalVolume_l: stream=%d, streamVol=%.3f, master=%.3f, final=%.3f",
      mStreamType, streamVolume, masterVolume, mFinalVolume);

}

  1. 混音时的音量应用

MixerThread处理

// frameworks/av/services/audioflinger/Threads.cpp - MixerThread

bool AudioFlinger::MixerThread::threadLoop() {

while (!exitPending()) {

// 1. 准备混音

processConfigEvents();

复制代码
    // 2. 准备活跃的Tracks
    prepareTracks_l(&tracks, &outputBuffer);
    
    // 3. 执行混音
    mAudioMixer->process();
    
    // 4. 输出到HAL
    threadLoop_write();
}
return false;

}

AudioMixer中的音量处理

// frameworks/av/services/audioflinger/AudioMixer.cpp

void AudioMixer::process() {

for (size_t i = 0; i < mActiveTracks.size(); ++i) {

int name = mActiveTracks[i];

track_t* track = &mTracks[name];

复制代码
    // 应用音量到每个Track
    if (track->needsVolume) {
        // 设置音量参数
        uint32_t vl = uint32_t(track->volume[0] * track->mFinalVolume * 0x1000);
        uint32_t vr = uint32_t(track->volume[1] * track->mFinalVolume * 0x1000);
        
        // 调用DSP处理函数应用音量
        track->hook(track, outputBuffer, numFrames);
    }
}

}

  1. 音量曲线和策略管理

AudioPolicyService参与

// frameworks/av/services/audiopolicy/AudioPolicyService.cpp

float AudioPolicyService::getStreamVolume(audio_stream_type_t stream,

audio_devices_t device,

audio_output_flags_t flags) {

// 1. 获取音量曲线

VolumeCurve curve = getVolumeCurve(stream, device);

复制代码
// 2. 应用音量曲线转换
float volumeDb = curve.mapVolume(mStreams[stream].getVolumeIndex());

// 3. 考虑安全音量限制
volumeDb = applyAllVolumes(volumeDb, stream, device);

return volumeDb;

}

音量曲线映射

// frameworks/av/services/audiopolicy/engine/VolumeCurve.cpp

float VolumeCurve::mapVolume(int index) const {

// 将音量索引转换为dB值

if (index <= mIndexMin) {

return mDbMin;

} else if (index >= mIndexMax) {

return mDbMax;

}

复制代码
// 线性或分段线性插值
float fraction = float(index - mIndexMin) / float(mIndexMax - mIndexMin);
return mDbMin + fraction * (mDbMax - mDbMin);

}

  1. 实时音量调整机制

淡入淡出处理

// frameworks/av/services/audioflinger/Tracks.cpp

void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right) {

sp thread = mThread.promote();

if (thread != 0) {

Mutex::Autolock _l(thread->mLock);

复制代码
    // 设置目标音量
    mVolume[0] = left;
    mVolume[1] = right;
    
    // 如果需要淡入淡出
    if (mFramesCount == 0) {
        // 立即设置
        mFinalVolume = calculateFinalVolume();
    } else {
        // 启动淡入淡出
        startVolumeRamp();
    }
}

}

void AudioFlinger::PlaybackThread::Track::startVolumeRamp() {

// 计算淡入淡出步长

uint32_t sampleRate = mSampleRate;

uint32_t rampFrames = uint32_t((mRampDuration * sampleRate) / 1000);

复制代码
if (rampFrames > 0) {
    mVolumeInc[0] = (mVolume[0] - mPrevVolume[0]) / rampFrames;
    mVolumeInc[1] = (mVolume[1] - mPrevVolume[1]) / rampFrames;
    mRampFrames = rampFrames;
}

}

  1. 多设备音量管理

设备特定音量

// frameworks/av/services/audioflinger/AudioFlinger.cpp

status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream,

float value, audio_io_handle_t output,

audio_devices_t device) {

// 1. 查找对应设备和输出的线程

sp thread = checkPlaybackThread_l(output);

if (thread == 0) return BAD_VALUE;

复制代码
// 2. 设置设备特定的音量
if (device == AUDIO_DEVICE_NONE) {
    device = thread->outDevice();
}

// 3. 存储设备音量
mStreams[stream].setVolume(device, value);

// 4. 应用到活跃流
return thread->setStreamVolume(stream, value, device);

}

  1. 关键设计特点

  2. 分层音量控制

应用音量 → 流音量 → 设备音量 → 主音量 → 最终音量

  1. 实时性保证

• 音量变化立即生效

• 淡入淡出避免爆音

• 锁保护确保线程安全

  1. 策略灵活性

• 可配置的音量曲线

• 设备特定的音量设置

• 安全音量限制

  1. 性能优化

• 预计算最终音量

• 向量化音量处理

• 最小化锁竞争

这个流程展示了Android音频系统如何高效、灵活地管理应用音量,确保多应用、多设备的音频混合能够正确应用各自的音量设置。

相关推荐
雪球Snowball10 分钟前
【Android关键流程】WMS的创建
android
我的offer在哪里13 分钟前
hdr格式视频的生成原理解析
音视频
我是阿亮啊17 分钟前
Android Handler 机制完全解析
android·handler·handler机制
STCNXPARM24 分钟前
Android camera子系统概述
android·图像处理·摄像头·车载
牛马11135 分钟前
flutter Riverpod 中的 overrideWith
android·java·flutter
小徐敲java38 分钟前
视频推流服务器与FFmpeg 安装配置
服务器·ffmpeg·音视频
2501_937193141 小时前
TV 电视影视大全:全终端流畅观影技术解析
android·源码·源代码管理·机顶盒
catchadmin1 小时前
PHP 现在可以零成本构建原生 iOS 和 Android 应用 NativePHP for Mobile v3 发布
android·ios·php
独自破碎E1 小时前
【回溯】二叉树的所有路径
android·java
安卓机器1 小时前
安卓玩机工具推荐------免root权限使用的 支持安卓4至安卓16系统的系统开源应用 推荐
android·反编译apk