通过之前的分析,我们大致得出了回音消除是以一个音效库形式存在。因此我们需要对一个相对来说比较简单的音效库来进行分析。
列如配置表中的downmix
./frameworks/av/media/libeffects/data/audio_effects.conf
downmix {
path /system/lib/soundfx/libdownmix.so
}
我们通过定位找到具体源码位置如下
frameworks/av/media/libeffects/downmix/
我们首先简单的分析一下/frameworks/av/media/libeffects/downmix/EffectDownmix.h
文件
...
#include <audio_effects/effect_downmix.h>
...
int32_t DownmixLib_Create(const effect_uuid_t *uuid,int32_t sessionId,int32_t ioId,effect_handle_t *pHandle);
int32_t DownmixLib_Release(effect_handle_t handle);
int32_t DownmixLib_GetDescriptor(const effect_uuid_t *uuid,effect_descriptor_t *pDescriptor);
static int Downmix_Process(effect_handle_t self,audio_buffer_t *inBuffer,audio_buffer_t *outBuffer);
static int Downmix_Command(effect_handle_t self,uint32_t cmdCode,uint32_t cmdSize,void *pCmdData,uint32_t *replySize,void *pReplyData);
static int Downmix_GetDescriptor(effect_handle_t self,effect_descriptor_t *pDescriptor);
int Downmix_Init(downmix_module_t *pDwmModule);
int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init);
int Downmix_Reset(downmix_object_t *pDownmixer, bool init);
int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue);
int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t *pSize, void *pValue);
void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
bool Downmix_foldGeneric(
uint32_t mask, int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
...
#include <audio_effects/effect_downmix.h>
文件位于
./system/media/audio_effects/include/audio_effects/effect_downmix.h
#ifndef ANDROID_EFFECT_DOWNMIX_H_
#define ANDROID_EFFECT_DOWNMIX_H_
#include <hardware/audio_effect.h>
#if __cplusplus
extern "C" {
#endif
#define EFFECT_UIID_DOWNMIX__ { 0x381e49cc, 0xa858, 0x4aa2, 0x87f6, \
{ 0xe8, 0x38, 0x8e, 0x76, 0x01, 0xb2 } }
static const effect_uuid_t EFFECT_UIID_DOWNMIX_ = EFFECT_UIID_DOWNMIX__;
const effect_uuid_t * const EFFECT_UIID_DOWNMIX = &EFFECT_UIID_DOWNMIX_;
/* enumerated parameter settings for downmix effect */
typedef enum {
DOWNMIX_PARAM_TYPE
} downmix_params_t;
typedef enum {
DOWNMIX_TYPE_INVALID = -1,
// throw away the extra channels
DOWNMIX_TYPE_STRIP = 0,
// mix the extra channels with FL/FR
DOWNMIX_TYPE_FOLD = 1,
DOWNMIX_TYPE_CNT,
DOWNMIX_TYPE_LAST = DOWNMIX_TYPE_CNT - 1
} downmix_type_t;
#if __cplusplus
} // extern "C"
#endif
#endif /*ANDROID_EFFECT_DOWNMIX_H_*/
可见如果我们需要实现某一个音效我们需要导入./system/media/audio_effects/include/audio_effects/
下的某一个音效头文件。
接着我们再来研究
/frameworks/av/media/libeffects/downmix/EffectDownmix.c
...
audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
.tag = AUDIO_EFFECT_LIBRARY_TAG,
.version = EFFECT_LIBRARY_API_VERSION,
.name = "Downmix Library",
.implementor = "The Android Open Source Project",
.create_effect = DownmixLib_Create,
.release_effect = DownmixLib_Release,
.get_descriptor = DownmixLib_GetDescriptor,
};
// AOSP insert downmix UUID: 93f04452-e4fe-41cc-91f9-e475b6d1d69f
static const effect_descriptor_t gDownmixDescriptor = {
EFFECT_UIID_DOWNMIX__, //type
{0x93f04452, 0xe4fe, 0x41cc, 0x91f9, {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}}, // uuid
EFFECT_CONTROL_API_VERSION,
EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
0, //FIXME what value should be reported? // cpu load
0, //FIXME what value should be reported? // memory usage
"Multichannel Downmix To Stereo", // human readable effect name
"The Android Open Source Project" // human readable effect implementor name
};
...
因此我们可以得知音效库中再AUDIO_EFFECT_LIBRARY_INFO_SYM
中对方法进行映射使得服务启动后能够进行正确的调用,另外我们还需要注意一点的是gDownmixDescriptor中UUID的配置,理论上说应该与./frameworks/av/media/libeffects/data/audio_effects.conf
和/frameworks/base/media/java/android/media/audiofx/AudioEffect.java
UUID保存一致。