背景:Android 2.3+ 引入 musicFx 應用,提供均衡器、低音增強、虛擬化等音效,設置持久化至 SharedPreferences。本文追蹤數據流向:UI → SharedPreferences → AudioEffect → AudioFlinger。
AudioEffect.setParameter() 寫入參數字節數組。android_media_AudioEffect.cpp → native_setParameter()。AudioEffect::setParameter() → mIEffect->command(EFFECT_CMD_SET_PARAM, ...)。IAudioFlinger::createEffect() 返回的 IEffect 代理。EffectModule 接收命令,更新內部參數結構。AudioMixer 在 process() 回調中,對每幀 PCM 數據應用 EffectChain(包含 Equalizer、BassBoost、Virtualizer 等)。// AudioEffect.java
public int setParameter(byte[] param, byte[] value) {
checkState("setParameter()");
return native_setParameter(param.length, param, value.length, value);
}
// android_media_AudioEffect.cpp
static jint android_media_AudioEffect_native_setParameter(JNIEnv*, jobject,
jint paramLen, jbyteArray param, jint valueLen, jbyteArray value) {
// ... 獲取 mIEffect (IEffect binder proxy)
return mIEffect->command(EFFECT_CMD_SET_PARAM, paramSize, paramBuf, &replySize, replyBuf);
}
// AudioFlinger/EffectModule.cpp
status_t EffectModule::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdCode == EFFECT_CMD_SET_PARAM) {
effect_param_t* p = (effect_param_t*)pCmdData;
memcpy(¶m_, p, sizeof(effect_param_t) + p->psize); // 更新參數
return NO_ERROR;
}
}
// 混音處理 AudioMixer.cpp
void AudioMixer::process(effect_buffer_t* in, effect_buffer_t* out) {
for (auto& chain : effectChains_) {
chain->process(in, out); // 依次應用各效果
}
}
僅作為**持久化存儲**,應用啟動時讀取並調用 AudioEffect.setParameter() 重新應用,**不在實時音頻路徑中**。
data/data/com.android.musicFx/shared_prefs/ XML → 重啟音樂播放 → 音效生效 → 證明讀取路徑正確。AudioEffect.setParameter 打印參數 → 觀察實時調整值 → 證明控制路徑正確。音效參數流向:**UI → SharedPreferences(持久化) → AudioEffect(JNI) → Binder IPC → AudioFlinger.EffectModule(參數存儲) → AudioMixer.EffectChain(實時處理) → 硬件**。理解此鏈路有助於自定義音效開發、音頻調試、性能分析。