Audio笔记之AudioEffect

本文详细介绍了Android中AudioEffect的使用,包括全局和非全局类型的效果与音轨的关联,以及创建和查找效果的过程。重点讲解了如何根据sessionId和effect的类型确定其所在线程,以及如何在正确的位置创建和移动效果。
摘要由CSDN通过智能技术生成
//总结一下effect和track的关联:
//1、全局类型的effect和track的创建无关,可以根据固定的规则查找线程,然后构造effect
//   当需要使用时,可以根据全局sessionId进行查找,然后将其移到track所在的线程
//2、非全局类型的effect
//   2.1、先有effect时,如果没有找到sessionId对应的track或者effect所在的线程,
//        表示该track没有建立,默认在第一个线程中创建effect,当创建track之后,
//        将根据sessionId查找到该effect所在的Chain,然后将其移到track所在的线程
//   2.2、已有track时,再创建effec比较简单,会根据track的sessionId找到track所在的线程,
//        然后在该线程中创建effect

//补充:根据采样率、流类型等参数可以确定track所在的线程,而根据track生成的sessionId
//      可以确定effect所在的线程,由此可以看出一般来说都是先有track,对应的effect
//      当然全局性的effect除外

// 支持的effect类型
#define EFFECT_FLAG_TYPE_INSERT         (0 << EFFECT_FLAG_TYPE_SHIFT)
#define EFFECT_FLAG_TYPE_AUXILIARY      (1 << EFFECT_FLAG_TYPE_SHIFT)
#define EFFECT_FLAG_TYPE_REPLACE        (2 << EFFECT_FLAG_TYPE_SHIFT)
#define EFFECT_FLAG_TYPE_PRE_PROC       (3 << EFFECT_FLAG_TYPE_SHIFT)
#define EFFECT_FLAG_TYPE_POST_PROC      (4 << EFFECT_FLAG_TYPE_SHIFT)

/*参数type是要创建的effect的类型。标准的类型已经在AudioEffect类中定义了,可以直接使用
  若要使用其他的类型,需要提供OpenSLES interface ID,并且在平台中存在该类型
  若指定的类型不存在,则会抛出IllegalArgumentException异常
  若type为EFFECT_TYPE_NULL,则只会根据uuid来选择effect
  参数uuid用于指定一个特定effect的实现。
  若uuid为EFFECT_TYPE_NULL,则只会根据type来选择effect
  参数priority是优先级,会根据优先级来判断effect engine的控制权
  参数audioSession,相同audioSession ID的AudioTrack和MediaPlayer共享Audio Effect
*/

public AudioEffect(UUID type, UUID uuid, int priority, int audioSession)
            throws IllegalArgumentException, UnsupportedOperationException,
            RuntimeException {
        int[] id = new int[1];
        Descriptor[] desc = new Descriptor[1];
        // native initialization
        int initResult = native_setup(new WeakReference<AudioEffect>(this),
                type.toString(), uuid.toString(), priority, audioSession, id,
                desc);
        ....
        mId = id[0];
        mDescriptor = desc[0];
        synchronized (mStateLock) {
            mState = STATE_INITIALIZED;
        }
}

static jint
android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
        jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId, jobjectArray javadesc)
{
    ALOGV("android_media_AudioEffect_native_setup");
    ....

    // create the native AudioEffect object
    // 在index为0的线程中创建effect对象
    lpAudioEffect = new AudioEffect(typeStr,
                                    uuidStr,
                                    priority,
                                    effectCallback,
                                    &lpJniStorage->mCallbackData,
                                    sessionId,
                                    0);

    lStatus = translateError(lpAudioEffect->initCheck());
    if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) {
        ALOGE("AudioEffect initCheck failed %d", lStatus);
        goto setup_failure;
    }
    ....

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

setup_failure:

    return lStatus;
}
AudioEffect::AudioEffect(const char *typeStr,
                const char *uuidStr,
                int32_t priority,
                effect_callback_t cbf,
                void* user,
                int sessionId,
                audio_io_handle_t io
                )
    : mStatus(NO_INIT)
{
    ....

    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io);
}

status_t AudioEffect::set(const effect_uuid_t *type,
                const effect_uuid_t *uuid,
                int32_t priority,
                effect_callback_t cbf,
                void* user,
                int sessionId,
                audio_io_handle_t io)
{
    sp<IEffect> iEffect;
    sp<IMemory> cblk;
    int enabled;
    .....
    mPriority = priority;
    mCbf = cbf;
    mUserData = user;
    mSessionId = sessionId;

    // 构造effect的描述对象,UUID和TYPE的默认值为EFFECT_UUID_NULL

    // 如果都是默认值,则构造effect对象失败
    memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
    mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL);
    mDescriptor.uuid = *(uuid != NULL ? uuid : EFFECT_UUID_NULL);

    mIEffectClient = new EffectClient(this);
    //构造Effect之后返回EffectHandle
    iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor,
            mIEffectClient, priority, io, mSessionId, &mStatus, &mId, &enabled);

    if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
        ALOGE("set(): AudioFlinger could no
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值