Android Audio代码分析20 - queryEffects函数

今天开始看看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。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值