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音频系统如何高效、灵活地管理应用音量,确保多应用、多设备的音频混合能够正确应用各自的音量设置。

相关推荐
赏金术士7 小时前
Kotlin 习题集 · 高级篇
android·开发语言·kotlin
潜创微科技8 小时前
IT9201+IT66021:便携 KVM 一站式方案,音视控三合一免驱即插即用
嵌入式硬件·音视频
问心无愧05139 小时前
ctf show web 入门42
android·前端·android studio
没什么本事10 小时前
关于C# panel 添加lable问题 -- 明确X和Y 位置错误
android·java·c#
音视频牛哥11 小时前
大牛直播SDK(SmartMediaKit)鸿蒙NEXT RTSP/RTMP低延迟播放器集成与实践指南
音视频·harmonyos·大牛直播sdk·鸿蒙rtmp播放器·鸿蒙rtsp播放器·鸿蒙next rtsp播放器·鸿蒙next rtmp播放器
REDcker13 小时前
Android HWASan 详解:硬件标记原理、Clang 启用与排障实践
android·linux·debug·编译·clang·asan·hwasan
2501_9159090614 小时前
全面解析前端开发中常用的浏览器调试工具及其使用场景
android·ios·小程序·https·uni-app·iphone·webview
angerdream14 小时前
Android手把手编写儿童手机远程监控App之SQLite详解2
android
-SOLO-14 小时前
Python 爬取小红书 文章标题和内容 仅供学习
android·python·学习
ooseabiscuit15 小时前
Laravel5
android·php·laravel