您的位置:首页 > 产品设计 > UI/UE

Android Audio代码分析20 - queryEffects函数

2011-10-20 17:35 399 查看
今天开始看看AudioEffect相关的接口。

这个类,之前有看过。不过当时只是从类的定义出发,了解了一下基本的内容。

这次从测试代码使用的接口出发,逐步撕开AudioEffect的面纱。

*****************************************源码*************************************************
//Test case 0.0: test queryEffects() and available effects
@LargeTest
public void test0_0QueryEffects() throws Exception {

AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();

assertTrue("test0_0QueryEffects: number of effects < 4: "+desc.length, (desc.length >= 4));

boolean hasEQ = false;
boolean hasBassBoost = false;
boolean hasVirtualizer = false;
boolean hasEnvReverb = false;

for (int i = 0; i < desc.length; i++) {
if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) {
hasEQ = true;
} if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)) {
hasBassBoost = true;
} else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) {
hasVirtualizer = true;
}
else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_ENV_REVERB)) {
hasEnvReverb = true;
}
}
assertTrue("test0_0QueryEffects: equalizer not found", hasEQ);
assertTrue("test0_0QueryEffects: bass boost not found", hasBassBoost);
assertTrue("test0_0QueryEffects: virtualizer not found", hasVirtualizer);
assertTrue("test0_0QueryEffects: environmental reverb not found", hasEnvReverb);
}


**********************************************************************************************

源码路径:

frameworks\base\media\tests\mediaframeworktest\src\com\android\mediaframeworktest\functional\MediaAudioEffectTest.java

#######################说明################################
//Test case 0.0: test queryEffects() and available effects
@LargeTest
public void test0_0QueryEffects() throws Exception {

AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
// ++++++++++++++++++++++++++++Descriptor++++++++++++++++++++++++++++++++++++
/**
* The effect descriptor contains information on a particular effect implemented in the
* audio framework:<br>
* <ul>
*  <li>type: UUID corresponding to the OpenSL ES interface implemented by this effect</li>
*  <li>uuid: UUID for this particular implementation</li>
*  <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li>
*  <li>name: human readable effect name</li>
*  <li>implementor: human readable effect implementor name</li>
* </ul>
* The method {@link #queryEffects()} returns an array of Descriptors to facilitate effects
* enumeration.
*/
public static class Descriptor {

public Descriptor() {
}

public Descriptor(String type, String uuid, String connectMode,
String name, String implementor) {
this.type = UUID.fromString(type);
this.uuid = UUID.fromString(uuid);
this.connectMode = connectMode;
this.name = name;
this.implementor = implementor;
}

/**
*  Indicates the generic type of the effect (Equalizer, Bass boost ...). The UUID
*  corresponds to the OpenSL ES Interface ID for this type of effect.
*/
public UUID type;
/**
*  Indicates the particular implementation of the effect in that type. Several effects
*  can have the same type but this uuid is unique to a given implementation.
*/
// 上次看AudioEffect类的时候,对type和uuid的区别还不是很清楚
// 看了这儿的注释,就比较清楚了
public UUID uuid;
/**
*  Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary
*  category {@link #EFFECT_AUXILIARY}. Insert effects (Typically an Equalizer) are applied
*  to the entire audio source and usually not shared by several sources. Auxiliary effects
*  (typically a reverberator) are applied to part of the signal (wet) and the effect output
*  is added to the original signal (dry).
*/
public String connectMode;
/**
* Human readable effect name
*/
public String name;
/**
* Human readable effect implementor name
*/
public String implementor;
};
// ----------------------------Descriptor------------------------------------
// ++++++++++++++++++++++++++++queryEffects++++++++++++++++++++++++++++++++++++
/**
* Query all effects available on the platform. Returns an array of
* {@link android.media.audiofx.AudioEffect.Descriptor} objects
*
* @throws IllegalStateException
*/

static public Descriptor[] queryEffects() {
return (Descriptor[]) native_query_effects();
// +++++++++++++++++++++++++++android_media_AudioEffect_native_queryEffects+++++++++++++++++++++++++++++++++++++
static jobjectArray
android_media_AudioEffect_native_queryEffects(JNIEnv *env, jclass clazz)
{
effect_descriptor_t desc;
char str[EFFECT_STRING_LEN_MAX];
uint32_t numEffects;
uint32_t i = 0;
jstring jdescType;
jstring jdescUuid;
jstring jdescConnect;
jstring jdescName;
jstring jdescImplementor;
jobject jdesc;

AudioEffect::queryNumberEffects(&numEffects);
// ++++++++++++++++++++++++++++AudioEffect::queryNumberEffects++++++++++++++++++++++++++++++++++++
status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->queryNumberEffects(numEffects);
// ++++++++++++++++++++++++++++AudioFlinger::queryNumberEffects++++++++++++++++++++++++++++++++++++
status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects)
{
Mutex::Autolock _l(mLock);
return EffectQueryNumberEffects(numEffects);
// ++++++++++++++++++++++++++EffectQueryNumberEffects++++++++++++++++++++++++++++++++++++++
// 函数EffectQueryNumberEffects定义的地方比较多。
// 我们使用的应该是下面这个文件中的:
// frameworks\base\media\libeffects\factory\

int EffectQueryNumberEffects(uint32_t *pNumEffects)
{
int ret = init();
if (ret < 0) {
return ret;
}
if (pNumEffects == NULL) {
return -EINVAL;
}

pthread_mutex_lock(&gLibLock);
// gNumEffects在函数updateNumEffects中有对其赋值
*pNumEffects = gNumEffects;
// ++++++++++++++++++++++++++++++updateNumEffects++++++++++++++++++++++++++++++++++
uint32_t updateNumEffects() {
list_elem_t *e;
uint32_t cnt = 0;

resetEffectEnumeration();
// ++++++++++++++++++++++++++++++resetEffectEnumeration++++++++++++++++++++++++++++++++++
void resetEffectEnumeration()
{
gCurLib = gLibraryList;
gCurEffect = NULL;
if (gCurLib) {
gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
}
gCurEffectIdx = 0;
}
// ------------------------------resetEffectEnumeration----------------------------------

// 函数EffectCreate和函数loadLibrary会向gLibraryList中添加成员
// 函数EffectRelease和函数unloadLibrary会删除gLibraryList中的成员
e = gLibraryList;
// +++++++++++++++++++++++++++++++EffectCreate+++++++++++++++++++++++++++++++++
int EffectCreate(effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_interface_t *pInterface)
{
list_elem_t *e = gLibraryList;
lib_entry_t *l = NULL;
effect_descriptor_t *d = NULL;
effect_interface_t itfe;
effect_entry_t *fx;
int found = 0;
int ret;

if (uuid == NULL || pInterface == NULL) {
return -EINVAL;
}

LOGV("EffectCreate() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2],
uuid->node[3],uuid->node[4],uuid->node[5]);

ret = init();
// ++++++++++++++++++++++++++++init++++++++++++++++++++++++++++++++++++
int init() {
struct dirent *ent;
DIR *dir = NULL;
char libpath[PATH_MAX];
int hdl;

// 避免重复初始化
if (gInitDone) {
return 0;
}

pthread_mutex_init(&gLibLock, NULL);

// load built-in libraries
// const char * const gEffectLibPath = "/system/lib/soundfx"; // path to built-in effect libraries
dir = opendir(gEffectLibPath);
if (dir == NULL) {
return -ENODEV;
}
while ((ent = readdir(dir)) != NULL) {
LOGV("init() reading file %s", ent->d_name);
if ((strlen(ent->d_name) < 3) ||
strncmp(ent->d_name, "lib", 3) != 0 ||
strncmp(ent->d_name + strlen(ent->d_name) - 3, ".so", 3) != 0) {
continue;
}
strcpy(libpath, gEffectLibPath);
strcat(libpath, "/");
strcat(libpath, ent->d_name);
// loadlibrary会向gLibraryList中添加成员
// 也就是说,在初始化阶段,会将built-in的effect libraries打开并添加到gLibraryList中
if (loadLibrary(libpath, &hdl) < 0) {
LOGW("init() failed to load library %s",libpath);
}
}
closedir(dir);
// 更新effects的个数
updateNumEffects();
gInitDone = 1;
LOGV("init() done");
return 0;
}
// ----------------------------init------------------------------------

if (ret < 0) {
LOGW("EffectCreate() init error: %d", ret);
return ret;
}

pthread_mutex_lock(&gLibLock);

// 根据uuid寻找对应的effect lib
// 若没有找到,则说明对应的effect lib不存在,也就没办法创建effect
// 如找到了,则使用对应的effect lib创建effect
ret = findEffect(uuid, &l, &d);
if (ret < 0){
goto exit;
}
// ++++++++++++++++++++++++++++++findEffect++++++++++++++++++++++++++++++++++
int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc)
{
list_elem_t *e = gLibraryList;
lib_entry_t *l = NULL;
effect_descriptor_t *d = NULL;
int found = 0;
int ret = 0;

while (e && !found) {
l = (lib_entry_t *)e->object;
list_elem_t *efx = l->effects;
while (efx) {
d = (effect_descriptor_t *)efx->object;
if (memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
found = 1;
break;
}
efx = efx->next;
}
e = e->next;
}
if (!found) {
LOGV("findEffect() effect not found");
ret = -ENOENT;
} else {
LOGV("findEffect() found effect: %s in lib %s", d->name, l->path);
*lib = l;
*desc = d;
}

return ret;
}
// ------------------------------findEffect----------------------------------

// create effect in library
// createFx的赋值是中loadLibrary函数中完成:createFx = (effect_CreateEffect_t)dlsym(hdl, "EffectCreate");
ret = l->createFx(uuid, sessionId, ioId, &itfe);
if (ret != 0) {
LOGW("EffectCreate() library %s: could not create fx %s, error %d", l->path, d->name, ret);
goto exit;
}
// +++++++++++++++++++++++++++EffectReverb EffectCreate+++++++++++++++++++++++++++++++++++++
我们看看EffectReverb中的EffectCreate函数。

int EffectCreate(effect_uuid_t *uuid,
int32_t sessionId,
int32_t ioId,
effect_interface_t *pInterface) {
int ret;
int i;
reverb_module_t *module;
const effect_descriptor_t *desc;
int aux = 0;
int preset = 0;

LOGV("EffectLibCreateEffect start");

if (pInterface == NULL || uuid == NULL) {
return -EINVAL;
}

for (i = 0; gDescriptors[i] != NULL; i++) {
desc = gDescriptors[i];
if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t))
== 0) {
break;
}
}

if (gDescriptors[i] == NULL) {
return -ENOENT;
}

module = malloc(sizeof(reverb_module_t));

module->itfe = &gReverbInterface;
// ++++++++++++++++++++++++++++++++gReverbInterface++++++++++++++++++++++++++++++++
// effect_interface_t interface implementation for reverb effect
const struct effect_interface_s gReverbInterface = {
Reverb_Process,
Reverb_Command
};
// --------------------------------gReverbInterface--------------------------------

module->context.mState = REVERB_STATE_UNINITIALIZED;

if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
preset = 1;
}
// ++++++++++++++++++++++++++++++++SL_IID_PRESETREVERB++++++++++++++++++++++++++++++++
#ifndef OPENSL_ES_H_
static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_;
#endif //OPENSL_ES_H_
// --------------------------------SL_IID_PRESETREVERB--------------------------------
if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
aux = 1;
}
ret = Reverb_Init(module, aux, preset);
if (ret < 0) {
LOGW("EffectLibCreateEffect() init failed");
free(module);
return ret;
}
// +++++++++++++++++++++++++++++Reverb_Init+++++++++++++++++++++++++++++++++++
/*----------------------------------------------------------------------------
* Reverb_Init()
*----------------------------------------------------------------------------
* Purpose:
* Initialize reverb context and apply default parameters
*
* Inputs:
*  pRvbModule    - pointer to reverb effect module
*  aux           - indicates if the reverb is used as auxiliary (1) or insert (0)
*  preset        - indicates if the reverb is used in preset (1) or environmental (0) mode
*
* Outputs:
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/

int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset) {
int ret;

LOGV("Reverb_Init module %p, aux: %d, preset: %d", pRvbModule,aux, preset);

memset(&pRvbModule->context, 0, sizeof(reverb_object_t));

pRvbModule->context.m_Aux = (uint16_t)aux;
pRvbModule->context.m_Preset = (uint16_t)preset;

pRvbModule->config.inputCfg.samplingRate = 44100;
if (aux) {
pRvbModule->config.inputCfg.channels = CHANNEL_MONO;
} else {
pRvbModule->config.inputCfg.channels = CHANNEL_STEREO;
}
pRvbModule->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
pRvbModule->config.inputCfg.bufferProvider.getBuffer = NULL;
pRvbModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
pRvbModule->config.inputCfg.bufferProvider.cookie = NULL;
pRvbModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
pRvbModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
pRvbModule->config.outputCfg.samplingRate = 44100;
pRvbModule->config.outputCfg.channels = CHANNEL_STEREO;
pRvbModule->config.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
pRvbModule->config.outputCfg.bufferProvider.getBuffer = NULL;
pRvbModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
pRvbModule->config.outputCfg.bufferProvider.cookie = NULL;
pRvbModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
pRvbModule->config.outputCfg.mask = EFFECT_CONFIG_ALL;

ret = Reverb_Configure(pRvbModule, &pRvbModule->config, true);
if (ret < 0) {
LOGV("Reverb_Init error %d on module %p", ret, pRvbModule);
}
// +++++++++++++++++++++++++Reverb_Configure+++++++++++++++++++++++++++++++++++++++
/*----------------------------------------------------------------------------
* Reverb_Init()
*----------------------------------------------------------------------------
* Purpose:
*  Set input and output audio configuration.
*
* Inputs:
*  pRvbModule    - pointer to reverb effect module
*  pConfig       - pointer to effect_config_t structure containing input
*              and output audio parameters configuration
*  init          - true if called from init function
* Outputs:
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/

int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig,
bool init) {
reverb_object_t *pReverb = &pRvbModule->context;
int bufferSizeInSamples;
int updatePeriodInSamples;
int xfadePeriodInSamples;

// Check configuration compatibility with build options
if (pConfig->inputCfg.samplingRate
!= pConfig->outputCfg.samplingRate
|| pConfig->outputCfg.channels != OUTPUT_CHANNELS
|| pConfig->inputCfg.format != SAMPLE_FORMAT_PCM_S15
|| pConfig->outputCfg.format != SAMPLE_FORMAT_PCM_S15) {
LOGV("Reverb_Configure invalid config");
return -EINVAL;
}
if ((pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_MONO)) ||
(!pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_STEREO))) {
LOGV("Reverb_Configure invalid config");
return -EINVAL;
}

memcpy(&pRvbModule->config, pConfig, sizeof(effect_config_t));

pReverb->m_nSamplingRate = pRvbModule->config.outputCfg.samplingRate;

switch (pReverb->m_nSamplingRate) {
case 8000:
pReverb->m_nUpdatePeriodInBits = 5;
bufferSizeInSamples = 4096;
pReverb->m_nCosWT_5KHz = -23170;
break;
case 16000:
pReverb->m_nUpdatePeriodInBits = 6;
bufferSizeInSamples = 8192;
pReverb->m_nCosWT_5KHz = -12540;
break;
case 22050:
pReverb->m_nUpdatePeriodInBits = 7;
bufferSizeInSamples = 8192;
pReverb->m_nCosWT_5KHz = 4768;
break;
case 32000:
pReverb->m_nUpdatePeriodInBits = 7;
bufferSizeInSamples = 16384;
pReverb->m_nCosWT_5KHz = 18205;
break;
case 44100:
pReverb->m_nUpdatePeriodInBits = 8;
bufferSizeInSamples = 16384;
pReverb->m_nCosWT_5KHz = 24799;
break;
case 48000:
pReverb->m_nUpdatePeriodInBits = 8;
bufferSizeInSamples = 16384;
pReverb->m_nCosWT_5KHz = 25997;
break;
default:
LOGV("Reverb_Configure invalid sampling rate %d", pReverb->m_nSamplingRate);
return -EINVAL;
}

// Define a mask for circular addressing, so that array index
// can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1)
// The buffer size MUST be a power of two
pReverb->m_nBufferMask = (int32_t) (bufferSizeInSamples - 1);
/* reverb parameters are updated every 2^(pReverb->m_nUpdatePeriodInBits) samples */
updatePeriodInSamples = (int32_t) (0x1L << pReverb->m_nUpdatePeriodInBits);
/*
calculate the update counter by bitwise ANDING with this value to
generate a 2^n modulo value
*/
pReverb->m_nUpdatePeriodInSamples = (int32_t) updatePeriodInSamples;

xfadePeriodInSamples = (int32_t) (REVERB_XFADE_PERIOD_IN_SECONDS
* (double) pReverb->m_nSamplingRate);

// set xfade parameters
pReverb->m_nPhaseIncrement
= (int16_t) (65536 / ((int16_t) xfadePeriodInSamples
/ (int16_t) updatePeriodInSamples));

if (init) {
ReverbReadInPresets(pReverb);
// +++++++++++++++++++++++++++++ReverbReadInPresets+++++++++++++++++++++++++++++++++++
// 函数内容没有太多要介绍的,只列出其注释。

/*----------------------------------------------------------------------------
* ReverbReadInPresets()
*----------------------------------------------------------------------------
* Purpose: sets global reverb preset bank to defaults
*
* Inputs:
*
* Outputs:
*
*----------------------------------------------------------------------------
*/
// -----------------------------ReverbReadInPresets-----------------------------------

// for debugging purposes, allow noise generator
pReverb->m_bUseNoise = true;

// for debugging purposes, allow bypass
pReverb->m_bBypass = 0;

pReverb->m_nNextRoom = 1;

pReverb->m_nNoise = (int16_t) 0xABCD;
}

Reverb_Reset(pReverb, init);
// +++++++++++++++++++++++++++++Reverb_Reset+++++++++++++++++++++++++++++++++++
/*----------------------------------------------------------------------------
* Reverb_Reset()
*----------------------------------------------------------------------------
* Purpose:
*  Reset internal states and clear delay lines.
*
* Inputs:
*  pReverb    - pointer to reverb context
*  init       - true if called from init function
*
* Outputs:
*
* Side Effects:
*
*----------------------------------------------------------------------------
*/

void Reverb_Reset(reverb_object_t *pReverb, bool init) {
int bufferSizeInSamples = (int32_t) (pReverb->m_nBufferMask + 1);
int maxApSamples;
int maxDelaySamples;
int maxEarlySamples;
int ap1In;
int delay0In;
int delay1In;
int32_t i;
uint16_t nOffset;

maxApSamples = ((int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16);
maxDelaySamples = ((int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
>> 16);
maxEarlySamples = ((int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
>> 16);

ap1In = (AP0_IN + maxApSamples + GUARD);
delay0In = (ap1In + maxApSamples + GUARD);
delay1In = (delay0In + maxDelaySamples + GUARD);
// Define the max offsets for the end points of each section
// i.e., we don't expect a given section's taps to go beyond
// the following limits

pReverb->m_nEarly0in = (delay1In + maxDelaySamples + GUARD);
pReverb->m_nEarly1in = (pReverb->m_nEarly0in + maxEarlySamples + GUARD);

pReverb->m_sAp0.m_zApIn = AP0_IN;

pReverb->m_zD0In = delay0In;

pReverb->m_sAp1.m_zApIn = ap1In;

pReverb->m_zD1In = delay1In;

pReverb->m_zOutLpfL = 0;
pReverb->m_zOutLpfR = 0;

pReverb->m_nRevFbkR = 0;
pReverb->m_nRevFbkL = 0;

// set base index into circular buffer
pReverb->m_nBaseIndex = 0;

// clear the reverb delay line
for (i = 0; i < bufferSizeInSamples; i++) {
pReverb->m_nDelayLine[i] = 0;
}

ReverbUpdateRoom(pReverb, init);
// +++++++++++++++++++++++++++++++ReverbUpdateRoom+++++++++++++++++++++++++++++++++
/*----------------------------------------------------------------------------
* ReverbUpdateRoom
*----------------------------------------------------------------------------
* Purpose:
* Update the room's preset parameters as required
*
* Inputs:
*
* Outputs:
*
*
* Side Effects:
* - reverb paramters (fbk, fwd, etc) will be changed
* - m_nCurrentRoom := m_nNextRoom
*----------------------------------------------------------------------------
*/
static int ReverbUpdateRoom(reverb_object_t *pReverb, bool fullUpdate) {
int temp;
int i;
int maxSamples;
int earlyDelay;
int earlyGain;

reverb_preset_t *pPreset =
&pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom];

if (fullUpdate) {
pReverb->m_nRvbLpfFwd = pPreset->m_nRvbLpfFwd;
pReverb->m_nRvbLpfFbk = pPreset->m_nRvbLpfFbk;

pReverb->m_nEarlyGain = pPreset->m_nEarlyGain;
//stored as time based, convert to sample based
pReverb->m_nLateGain = pPreset->m_nLateGain;
pReverb->m_nRoomLpfFbk = pPreset->m_nRoomLpfFbk;
pReverb->m_nRoomLpfFwd = pPreset->m_nRoomLpfFwd;

// set the early reflections gains
earlyGain = pPreset->m_nEarlyGain;
for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
pReverb->m_sEarlyL.m_nGain[i]
= MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],earlyGain);
pReverb->m_sEarlyR.m_nGain[i]
= MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],earlyGain);
}

pReverb->m_nMaxExcursion = pPreset->m_nMaxExcursion;

pReverb->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain;
pReverb->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain;

// set the early reflections delay
earlyDelay = ((int) pPreset->m_nEarlyDelay * pReverb->m_nSamplingRate)
>> 16;
pReverb->m_nEarlyDelay = earlyDelay;
maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
>> 16;
for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
//stored as time based, convert to sample based
temp = earlyDelay + (((int) pPreset->m_sEarlyL.m_zDelay[i]
* pReverb->m_nSamplingRate) >> 16);
if (temp > maxSamples)
temp = maxSamples;
pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp;
//stored as time based, convert to sample based
temp = earlyDelay + (((int) pPreset->m_sEarlyR.m_zDelay[i]
* pReverb->m_nSamplingRate) >> 16);
if (temp > maxSamples)
temp = maxSamples;
pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp;
}

maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
>> 16;
//stored as time based, convert to sample based
/*lint -e{702} shift for performance */
temp = (pPreset->m_nLateDelay * pReverb->m_nSamplingRate) >> 16;
if ((temp + pReverb->m_nMaxExcursion) > maxSamples) {
temp = maxSamples - pReverb->m_nMaxExcursion;
}
temp -= pReverb->m_nLateDelay;
pReverb->m_nDelay0Out += temp;
pReverb->m_nDelay1Out += temp;
pReverb->m_nLateDelay += temp;

maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16;
//stored as time based, convert to absolute sample value
temp = pPreset->m_nAp0_ApOut;
/*lint -e{702} shift for performance */
temp = (temp * pReverb->m_nSamplingRate) >> 16;
if (temp > maxSamples)
temp = maxSamples;
pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp);

//stored as time based, convert to absolute sample value
temp = pPreset->m_nAp1_ApOut;
/*lint -e{702} shift for performance */
temp = (temp * pReverb->m_nSamplingRate) >> 16;
if (temp > maxSamples)
temp = maxSamples;
pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp);
//gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut;
}

//stored as time based, convert to sample based
temp = pPreset->m_nXfadeInterval;
/*lint -e{702} shift for performance */
temp = (temp * pReverb->m_nSamplingRate) >> 16;
pReverb->m_nXfadeInterval = (uint16_t) temp;
//gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval;
pReverb->m_nXfadeCounter = pReverb->m_nXfadeInterval + 1; // force update on first iteration

pReverb->m_nCurrentRoom = pReverb->m_nNextRoom;

return 0;

} /* end ReverbUpdateRoom */
// -------------------------------ReverbUpdateRoom---------------------------------

pReverb->m_nUpdateCounter = 0;

pReverb->m_nPhase = -32768;

pReverb->m_nSin = 0;
pReverb->m_nCos = 0;
pReverb->m_nSinIncrement = 0;
pReverb->m_nCosIncrement = 0;

// set delay tap lengths
nOffset = ReverbCalculateNoise(pReverb);
// ++++++++++++++++++++++++++++ReverbCalculateNoise++++++++++++++++++++++++++++++++++++
/*----------------------------------------------------------------------------
* ReverbCalculateNoise
*----------------------------------------------------------------------------
* Purpose:
* Calculate a noise sample and limit its value
*
* Inputs:
* nMaxExcursion - noise value is limited to this value
* pnNoise - return new noise sample in this (not limited)
*
* Outputs:
* new limited noise value
*
* Side Effects:
* - *pnNoise noise value is updated
*
*----------------------------------------------------------------------------
*/
static uint16_t ReverbCalculateNoise(reverb_object_t *pReverb) {
int16_t nNoise = pReverb->m_nNoise;

// calculate new noise value
if (pReverb->m_bUseNoise) {
nNoise = (int16_t) (nNoise * 5 + 1);
} else {
nNoise = 0;
}

pReverb->m_nNoise = nNoise;
// return the limited noise value
return (pReverb->m_nMaxExcursion & nNoise);

} /* end ReverbCalculateNoise */
// ----------------------------ReverbCalculateNoise------------------------------------

pReverb->m_zD1Cross = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
+ nOffset;

nOffset = ReverbCalculateNoise(pReverb);

pReverb->m_zD0Cross = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
- nOffset;

nOffset = ReverbCalculateNoise(pReverb);

pReverb->m_zD0Self = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
- nOffset;

nOffset = ReverbCalculateNoise(pReverb);

pReverb->m_zD1Self = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
+ nOffset;
}
// -----------------------------Reverb_Reset-----------------------------------

return 0;
}
// -------------------------Reverb_Configure---------------------------------------

return ret;
}
// -----------------------------Reverb_Init-----------------------------------

*pInterface = (effect_interface_t) module;

module->context.mState = REVERB_STATE_INITIALIZED;

LOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));

return 0;
}
// ---------------------------EffectReverb EffectCreate-------------------------------------

// add entry to effect list
fx = (effect_entry_t *)malloc(sizeof(effect_entry_t));
fx->subItfe = itfe;
fx->itfe = (struct effect_interface_s *)&gInterface;
fx->lib = l;

e = (list_elem_t *)malloc(sizeof(list_elem_t));
e->object = fx;
e->next = gEffectList;
gEffectList = e;

*pInterface = (effect_interface_t)fx;

LOGV("EffectCreate() created entry %p with sub itfe %p in library %s", *pInterface, itfe, l->path);

exit:
pthread_mutex_unlock(&gLibLock);
return ret;
}
// -------------------------------EffectCreate---------------------------------
// ++++++++++++++++++++++++++++++loadLibrary++++++++++++++++++++++++++++++++++
int loadLibrary(const char *libPath, int *handle)
{
void *hdl;
effect_QueryNumberEffects_t queryNumFx;
effect_QueryEffect_t queryFx;
effect_CreateEffect_t createFx;
effect_ReleaseEffect_t releaseFx;
uint32_t numFx;
uint32_t fx;
int ret;
list_elem_t *e, *descHead = NULL;
lib_entry_t *l;

if (handle == NULL) {
return -EINVAL;
}

*handle = 0;

hdl = dlopen(libPath, RTLD_NOW);
if (hdl == 0) {
LOGW("could open lib %s", libPath);
return -ENODEV;
}

// Check functions availability
queryNumFx = (effect_QueryNumberEffects_t)dlsym(hdl, "EffectQueryNumberEffects");
if (queryNumFx == NULL) {
LOGW("could not get EffectQueryNumberEffects from lib %s", libPath);
ret = -ENODEV;
goto error;
}
queryFx = (effect_QueryEffect_t)dlsym(hdl, "EffectQueryEffect");
if (queryFx == NULL) {
LOGW("could not get EffectQueryEffect from lib %s", libPath);
ret = -ENODEV;
goto error;
}
createFx = (effect_CreateEffect_t)dlsym(hdl, "EffectCreate");
if (createFx == NULL) {
LOGW("could not get EffectCreate from lib %s", libPath);
ret = -ENODEV;
goto error;
}
releaseFx = (effect_ReleaseEffect_t)dlsym(hdl, "EffectRelease");
if (releaseFx == NULL) {
LOGW("could not get EffectRelease from lib %s", libPath);
ret = -ENODEV;
goto error;
}

// load effect descriptors
ret = queryNumFx(&numFx);
if (ret) {
goto error;
}

for (fx = 0; fx < numFx; fx++) {
effect_descriptor_t *d = malloc(sizeof(effect_descriptor_t));
if (d == NULL) {
ret = -ENOMEM;
goto error;
}
ret = queryFx(fx, d);
if (ret == 0) {
#if (LOG_NDEBUG==0)
char s[256];
dumpEffectDescriptor(d, s, 256);
LOGV("loadLibrary() read descriptor %p:%s",d, s);
#endif
if (d->apiVersion != EFFECT_API_VERSION) {
LOGW("Bad API version %04x on lib %s", d->apiVersion, libPath);
free(d);
continue;
}
e = malloc(sizeof(list_elem_t));
if (e == NULL) {
free(d);
ret = -ENOMEM;
goto error;
}
e->object = d;
e->next = descHead;
descHead = e;
} else {
LOGW("Error querying effect # %d on lib %s", fx, libPath);
}
}

pthread_mutex_lock(&gLibLock);

// add entry for library in gLibraryList
l = malloc(sizeof(lib_entry_t));
l->id = ++gNextLibId;
l->handle = hdl;
strncpy(l->path, libPath, PATH_MAX);
l->createFx = createFx;
l->releaseFx = releaseFx;
l->effects = descHead;
pthread_mutex_init(&l->lock, NULL);

e = malloc(sizeof(list_elem_t));
e->next = gLibraryList;
e->object = l;
gLibraryList = e;
pthread_mutex_unlock(&gLibLock);
LOGV("loadLibrary() linked library %p", l);

*handle = l->id;

return 0;

error:
LOGW("loadLibrary() error: %d on lib: %s", ret, libPath);
while (descHead) {
free(descHead->object);
e = descHead->next;
free(descHead);
descHead = e;;
}
dlclose(hdl);
return ret;
}

// 我们已经知道,init函数中有调用loadLibrary,另外,EffectLoadLibrary中也有调用loadLibrary函数。
// ++++++++++++++++++++++++++++++EffectLoadLibrary++++++++++++++++++++++++++++++++++
int EffectLoadLibrary(const char *libPath, int *handle)
{
int ret = init();
if (ret < 0) {
return ret;
}
if (libPath == NULL) {
return -EINVAL;
}

ret = loadLibrary(libPath, handle);
updateNumEffects();
return ret;
}

// 函数AudioFlinger::loadEffectLibrary中调用了函数EffectLoadLibrary
// +++++++++++++++++++++++++++++AudioFlinger::loadEffectLibrary+++++++++++++++++++++++++++++++++++
status_t AudioFlinger::loadEffectLibrary(const char *libPath, int *handle)
{
// check calling permissions
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
// only allow libraries loaded from /system/lib/soundfx for now
if (strncmp(gEffectLibPath, libPath, strlen(gEffectLibPath)) != 0) {
return PERMISSION_DENIED;
}

Mutex::Autolock _l(mLock);
return EffectLoadLibrary(libPath, handle);
}
// -----------------------------AudioFlinger::loadEffectLibrary-----------------------------------
// ------------------------------EffectLoadLibrary----------------------------------
// ------------------------------loadLibrary----------------------------------
// +++++++++++++++++++++++++++++EffectRelease+++++++++++++++++++++++++++++++++++
int EffectRelease(effect_interface_t interface)
{
effect_entry_t *fx;
list_elem_t *e1;
list_elem_t *e2;

int ret = init();
if (ret < 0) {
return ret;
}

// remove effect from effect list
pthread_mutex_lock(&gLibLock);
e1 = gEffectList;
e2 = NULL;
while (e1) {
if (e1->object == interface) {
if (e2) {
e2->next = e1->next;
} else {
gEffectList = e1->next;
}
fx = (effect_entry_t *)e1->object;
free(e1);
break;
}
e2 = e1;
e1 = e1->next;
}
if (e1 == NULL) {
ret = -ENOENT;
goto exit;
}

// release effect in library
if (fx->lib == NULL) {
LOGW("EffectRelease() fx %p library already unloaded", interface);
} else {
pthread_mutex_lock(&fx->lib->lock);
fx->lib->releaseFx(fx->subItfe);
pthread_mutex_unlock(&fx->lib->lock);
}
free(fx);

exit:
pthread_mutex_unlock(&gLibLock);
return ret;
}
// -----------------------------EffectRelease-----------------------------------
// +++++++++++++++++++++++++++++unloadLibrary+++++++++++++++++++++++++++++++++++
int unloadLibrary(int handle)
{
void *hdl;
int ret;
list_elem_t *el1, *el2;
lib_entry_t *l;
effect_entry_t *fx;

pthread_mutex_lock(&gLibLock);
el1 = gLibraryList;
el2 = NULL;
while (el1) {
l = (lib_entry_t *)el1->object;
if (handle == l->id) {
if (el2) {
el2->next = el1->next;
} else {
gLibraryList = el1->next;
}
free(el1);
break;
}
el2 = el1;
el1 = el1->next;
}
pthread_mutex_unlock(&gLibLock);
if (el1 == NULL) {
return -ENOENT;
}

// clear effect descriptor list
el1 = l->effects;
while (el1) {
free(el1->object);
el2 = el1->next;
free(el1);
el1 = el2;
}

// disable all effects from this library
pthread_mutex_lock(&l->lock);

el1 = gEffectList;
while (el1) {
fx = (effect_entry_t *)el1->object;
if (fx->lib == l) {
fx->lib = NULL;
}
el1 = el1->next;
}
pthread_mutex_unlock(&l->lock);

dlclose(l->handle);
free(l);
return 0;
}

// 函数EffectUnloadLibrary调用了unloadLibrary函数。
// +++++++++++++++++++++++++++++EffectUnloadLibrary+++++++++++++++++++++++++++++++++++
int EffectUnloadLibrary(int handle)
{
int ret = init();
if (ret < 0) {
return ret;
}

ret = unloadLibrary(handle);
updateNumEffects();
return ret;
}

// 函数AudioFlinger::unloadEffectLibrary中有调用了EffectUnloadLibrary函数。
// +++++++++++++++++++++++++++++AudioFlinger::unloadEffectLibrary+++++++++++++++++++++++++++++++++++
status_t AudioFlinger::unloadEffectLibrary(int handle)
{
// check calling permissions
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}

Mutex::Autolock _l(mLock);
return EffectUnloadLibrary(handle);
}
// -----------------------------AudioFlinger::unloadEffectLibrary-----------------------------------
// -----------------------------EffectUnloadLibrary-----------------------------------
// -----------------------------unloadLibrary-----------------------------------
while (e) {
lib_entry_t *l = (lib_entry_t *)e->object;
list_elem_t *efx = l->effects;
while (efx) {
cnt++;
efx = efx->next;
}
e = e->next;
}
gNumEffects = cnt;
gCanQueryEffect = 0;
return cnt;
}
// ------------------------------updateNumEffects----------------------------------
gCanQueryEffect = 1;
pthread_mutex_unlock(&gLibLock);
LOGV("EffectQueryNumberEffects(): %d", *pNumEffects);
return ret;
}
// --------------------------EffectQueryNumberEffects--------------------------------------
}
// ----------------------------AudioFlinger::queryNumberEffects------------------------------------
}
// ----------------------------AudioEffect::queryNumberEffects------------------------------------
jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL);
if (ret == NULL) {
return ret;
}

LOGV("queryEffects() numEffects: %d", numEffects);

for (i = 0; i < numEffects; i++) {
if (AudioEffect::queryEffect(i, &desc) != NO_ERROR) {
goto queryEffects_failure;
}
// +++++++++++++++++++++++++++++++AudioEffect::queryEffect+++++++++++++++++++++++++++++++++
status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->queryEffect(index, descriptor);
// +++++++++++++++++++++++++++++++AudioFlinger::queryEffect+++++++++++++++++++++++++++++++++
status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
{
Mutex::Autolock _l(mLock);
return EffectQueryEffect(index, descriptor);
// +++++++++++++++++++++++++++++EffectQueryEffect+++++++++++++++++++++++++++++++++++
int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
{
int ret = init();
if (ret < 0) {
return ret;
}
if (pDescriptor == NULL ||
index >= gNumEffects) {
return -EINVAL;
}
if (gCanQueryEffect == 0) {
return -ENOSYS;
}

pthread_mutex_lock(&gLibLock);
ret = -ENOENT;
if (index < gCurEffectIdx) {
resetEffectEnumeration();
// +++++++++++++++++++++++++++++++resetEffectEnumeration+++++++++++++++++++++++++++++++++
void resetEffectEnumeration()
{
gCurLib = gLibraryList;
gCurEffect = NULL;
if (gCurLib) {
gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
}
gCurEffectIdx = 0;
}
// -------------------------------resetEffectEnumeration---------------------------------
}
while (gCurLib) {
if (gCurEffect) {
if (index == gCurEffectIdx) {
memcpy(pDescriptor, gCurEffect->object, sizeof(effect_descriptor_t));
ret = 0;
break;
} else {
gCurEffect = gCurEffect->next;
gCurEffectIdx++;
}
} else {
gCurLib = gCurLib->next;
gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
}
}

#if (LOG_NDEBUG == 0)
char str[256];
dumpEffectDescriptor(pDescriptor, str, 256);
LOGV("EffectQueryEffect() desc:%s", str);
#endif
pthread_mutex_unlock(&gLibLock);
return ret;
}
// ------------------------------EffectQueryEffect----------------------------------
}
// -------------------------------AudioFlinger::queryEffect---------------------------------
}
// -------------------------------AudioEffect::queryEffect---------------------------------

AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX);
jdescType = env->NewStringUTF(str);

AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX);
jdescUuid = env->NewStringUTF(str);

if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
jdescConnect = env->NewStringUTF("Auxiliary");
} else {
jdescConnect = env->NewStringUTF("Insert");
}

jdescName = env->NewStringUTF(desc.name);
jdescImplementor = env->NewStringUTF(desc.implementor);

jdesc = env->NewObject(fields.clazzDesc,
fields.midDescCstor,
jdescType,
jdescUuid,
jdescConnect,
jdescName,
jdescImplementor);
env->DeleteLocalRef(jdescType);
env->DeleteLocalRef(jdescUuid);
env->DeleteLocalRef(jdescConnect);
env->DeleteLocalRef(jdescName);
env->DeleteLocalRef(jdescImplementor);
if (jdesc == NULL) {
LOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
goto queryEffects_failure;
}

env->SetObjectArrayElement(ret, i, jdesc);
}

return ret;

queryEffects_failure:

if (ret != NULL) {
env->DeleteLocalRef(ret);
}
return NULL;

}
// ---------------------------android_media_AudioEffect_native_queryEffects-------------------------------------
}
// ----------------------------queryEffects------------------------------------

assertTrue("test0_0QueryEffects: number of effects < 4: "+desc.length, (desc.length >= 4));

boolean hasEQ = false;
boolean hasBassBoost = false;
boolean hasVirtualizer = false;
boolean hasEnvReverb = false;

for (int i = 0; i < desc.length; i++) {
if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) {
hasEQ = true;
} if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)) {
hasBassBoost = true;
} else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) {
hasVirtualizer = true;
}
else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_ENV_REVERB)) {
hasEnvReverb = true;
}
}
assertTrue("test0_0QueryEffects: equalizer not found", hasEQ);
assertTrue("test0_0QueryEffects: bass boost not found", hasBassBoost);
assertTrue("test0_0QueryEffects: virtualizer not found", hasVirtualizer);
assertTrue("test0_0QueryEffects: environmental reverb not found", hasEnvReverb);
}


###########################################################

&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

queryEffects返回effect 列表中所有effect的描述。

通过函数EffectQueryNumberEffects可以取到effect列表中包含的effect的个数。

中EffectFactory的init函数中,会将build-in的effect lib添加到effect列表。

可以通过EffectLoadLibrary加载新的effect lib。

也可以通过EffectUnloadLibrary卸载已加载的effect lib。

可以通过函数EffectCreate创建effect。

也可以通过函数EffectRelease删除effect。

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息