Android Audio代码分析23 - attachAuxEffect函数

今天来看看如何将AudioEffect与AudioTrack关联起来。


*****************************************源码*************************************************
    //Test case 1.7: test auxiliary effect attachement on AudioTrack
    @LargeTest
    public void test1_7AuxiliaryOnAudioTrack() throws Exception {
        boolean result = false;
        String msg = "test1_7AuxiliaryOnAudioTrack()";


        try {
            AudioTrack track = new AudioTrack(
                                        AudioManager.STREAM_MUSIC,
                                        44100,
                                        AudioFormat.CHANNEL_OUT_MONO,
                                        AudioFormat.ENCODING_PCM_16BIT,
                                        AudioTrack.getMinBufferSize(44100,
                                                                    AudioFormat.CHANNEL_OUT_MONO,
                                                                    AudioFormat.ENCODING_PCM_16BIT),
                                                                    AudioTrack.MODE_STREAM);
            assertNotNull(msg + ": could not create AudioTrack", track);
            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB,
                    AudioEffect.EFFECT_TYPE_NULL,
                    0,
                    0);


            track.attachAuxEffect(effect.getId());
            track.setAuxEffectSendLevel(1.0f);
            result = true;
            effect.release();
            track.release();
        } catch (IllegalArgumentException e) {
            msg = msg.concat(": Equalizer not found");
            loge(msg, ": Equalizer not found");
        } catch (UnsupportedOperationException e) {
            msg = msg.concat(": Effect library not loaded");
            loge(msg, ": Effect library not loaded");
        }
        assertTrue(msg, result);
    }

**********************************************************************************************
源码路径:
frameworks\base\media\tests\mediaframeworktest\src\com\android\mediaframeworktest\functional\MediaAudioEffectTest.java


#######################说明################################
    //Test case 1.7: test auxiliary effect attachement on AudioTrack
    @LargeTest
    public void test1_7AuxiliaryOnAudioTrack() throws Exception {
        boolean result = false;
        String msg = "test1_7AuxiliaryOnAudioTrack()";


        try {
            AudioTrack track = new AudioTrack(
                                        AudioManager.STREAM_MUSIC,
                                        44100,
                                        AudioFormat.CHANNEL_OUT_MONO,
                                        AudioFormat.ENCODING_PCM_16BIT,
                                        AudioTrack.getMinBufferSize(44100,
                                                                    AudioFormat.CHANNEL_OUT_MONO,
                                                                    AudioFormat.ENCODING_PCM_16BIT),
                                                                    AudioTrack.MODE_STREAM);
            assertNotNull(msg + ": could not create AudioTrack", track);
            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB,
                    AudioEffect.EFFECT_TYPE_NULL,
                    0,
                    0);


// 此处getId获取的是调用JNI接口native_setup时得到的
            track.attachAuxEffect(effect.getId());
// +++++++++++++++++++++++++++++attachAuxEffect+++++++++++++++++++++++++++++++++++
    /**
     * Attaches an auxiliary effect to the audio track. A typical auxiliary
     * effect is a reverberation effect which can be applied on any sound source
     * that directs a certain amount of its energy to this effect. This amount
     * is defined by setAuxEffectSendLevel().
     * {@see #setAuxEffectSendLevel(float)}.
     * <p>After creating an auxiliary effect (e.g.
     * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with
     * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling
     * this method to attach the audio track to the effect.
     * <p>To detach the effect from the audio track, call this method with a
     * null effect id.
     *
     * @param effectId system wide unique id of the effect to attach
     * @return error code or success, see {@link #SUCCESS},
     *    {@link #ERROR_INVALID_OPERATION}, {@link #ERROR_BAD_VALUE}
     */
    public int attachAuxEffect(int effectId) {
        if (mState != STATE_INITIALIZED) {
            return ERROR_INVALID_OPERATION;
        }
        return native_attachAuxEffect(effectId);
// ++++++++++++++++++++++++++++android_media_AudioTrack_attachAuxEffect++++++++++++++++++++++++++++++++++++
static jint android_media_AudioTrack_attachAuxEffect(JNIEnv *env,  jobject thiz,
        jint effectId) {


    AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
                thiz, javaAudioTrackFields.nativeTrackInJavaObj);


    if (lpTrack) {
        return android_media_translateErrorCode( lpTrack->attachAuxEffect(effectId) );
// ++++++++++++++++++++++++++++++AudioTrack::attachAuxEffect++++++++++++++++++++++++++++++++++
status_t AudioTrack::attachAuxEffect(int effectId)
{
    LOGV("attachAuxEffect(%d)", effectId);
// mAudioTrack在函数AudioTrack::createTrack中被赋值,其最终指向的其实是一个TrackHandle对象
    status_t status = mAudioTrack->attachAuxEffect(effectId);
// ++++++++++++++++++++++++++++++AudioFlinger::TrackHandle::attachAuxEffect++++++++++++++++++++++++++++++++++
status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
{
    return mTrack->attachAuxEffect(EffectId);
// ++++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::Track::attachAuxEffect++++++++++++++++++++++++++++++++++
status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
{
    status_t status = DEAD_OBJECT;
    sp<ThreadBase> thread = mThread.promote();
    if (thread != 0) {
       PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
       status = playbackThread->attachAuxEffect(this, EffectId);
// ++++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::attachAuxEffect++++++++++++++++++++++++++++++++++
status_t AudioFlinger::PlaybackThread::attachAuxEffect(
        const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
{
    Mutex::Autolock _l(mLock);
    return attachAuxEffect_l(track, EffectId);
// +++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::attachAuxEffect_l+++++++++++++++++++++++++++++++++++
status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
        const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
{
    status_t status = NO_ERROR;


// 如果EffectId为0,其实是清楚effect
    if (EffectId == 0) {
        track->setAuxBuffer(0, NULL);
// +++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::Track::setAuxBuffer+++++++++++++++++++++++++++++++++++
void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
{
// 函数AudioFlinger::PlaybackThread::detachAuxEffect_l中调用了函数AudioFlinger::PlaybackThread::Track::auxEffectId来得到mAuxEffectId
    mAuxEffectId = EffectId;
// 函数AudioFlinger::MixerThread::prepareTracks_l中会调用函数AudioFlinger::PlaybackThread::Track::auxBuffer获取mAuxBuffer
//            mAudioMixer->setParameter(
//                AudioMixer::TRACK,
//                AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
    mAuxBuffer = buffer;
}
// -----------------------------AudioFlinger::PlaybackThread::Track::setAuxBuffer-----------------------------------
    } else {
        // Auxiliary effects are always in audio session AudioSystem::SESSION_OUTPUT_MIX
        sp<EffectModule> effect = getEffect_l(AudioSystem::SESSION_OUTPUT_MIX, EffectId);
// +++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::getEffect_l+++++++++++++++++++++++++++++++++++
sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)
{
    sp<EffectModule> effect;


// 先得到chain
    sp<EffectChain> chain = getEffectChain_l(sessionId);
// ++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::getEffectChain_l++++++++++++++++++++++++++++++++++++
sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId)
{
    sp<EffectChain> chain;


    size_t size = mEffectChains.size();
    for (size_t i = 0; i < size; i++) {
        if (mEffectChains[i]->sessionId() == sessionId) {
// 函数AudioFlinger::PlaybackThread::addEffectChain_l会向mEffectChains添加成员
// 函数AudioFlinger::PlaybackThread::createEffect_l和AudioFlinger::PlaybackThread::addEffect_l中,
// 会判断指定session Id对应的effect chain是否存在,若不存在,创建一个,并调用mEffectChains添加到mEffectChains中
            chain = mEffectChains[i];
            break;
        }
    }
    return chain;
}
// ----------------------------AudioFlinger::PlaybackThread::getEffectChain_l------------------------------------
    if (chain != 0) {
// 再根据effect Id从chain上得到effect
        effect = chain->getEffectFromId_l(effectId);
// +++++++++++++++++++++++++++AudioFlinger::EffectChain::getEffectFromId_l+++++++++++++++++++++++++++++++++++++
// getEffectFromId_l() must be called with PlaybackThread::mLock held
sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
{
    sp<EffectModule> effect;
    size_t size = mEffects.size();


    for (size_t i = 0; i < size; i++) {
        // by convention, return first effect if id provided is 0 (0 is never a valid id)
        if (id == 0 || mEffects[i]->id() == id) {
// 函数AudioFlinger::EffectChain::addEffect_l会向mEffects中添加effect
// 函数AudioFlinger::PlaybackThread::createEffect_l和AudioFlinger::PlaybackThread::addEffect_l中,
// 会调用函数AudioFlinger::EffectChain::addEffect_l
            effect = mEffects[i];
            break;
        }
    }
    return effect;
}
// ---------------------------AudioFlinger::EffectChain::getEffectFromId_l-------------------------------------
    }
    return effect;
}
// -----------------------------AudioFlinger::PlaybackThread::getEffect_l-----------------------------------
        if (effect != 0) {
            if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
                track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
            } else {
                status = INVALID_OPERATION;
            }
        } else {
            status = BAD_VALUE;
        }
    }
    return status;
}
// -----------------------------AudioFlinger::PlaybackThread::attachAuxEffect_l-----------------------------------
}
// ------------------------------AudioFlinger::PlaybackThread::attachAuxEffect----------------------------------
    }
    return status;
}
// ------------------------------AudioFlinger::PlaybackThread::Track::attachAuxEffect----------------------------------
}
// ------------------------------AudioFlinger::TrackHandle::attachAuxEffect----------------------------------
    if (status == NO_ERROR) {
        mAuxEffectId = effectId;
    }
    return status;
}
// ------------------------------AudioTrack::attachAuxEffect----------------------------------
    } else {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioTrack pointer for attachAuxEffect()");
        return AUDIOTRACK_ERROR;
    }
}
// ----------------------------android_media_AudioTrack_attachAuxEffect------------------------------------
    }
// -----------------------------attachAuxEffect-----------------------------------
            track.setAuxEffectSendLevel(1.0f);
// +++++++++++++++++++++++++++++++setAuxEffectSendLevel+++++++++++++++++++++++++++++++++
    /**
     * Sets the send level of the audio track to the attached auxiliary effect
     * {@see #attachAuxEffect(int)}. The level value range is 0 to 1.0.
     * <p>By default the send level is 0, so even if an effect is attached to the player
     * this method must be called for the effect to be applied.
     * <p>Note that the passed level value is a raw scalar. UI controls should be scaled
     * logarithmically: the gain applied by audio framework ranges from -72dB to 0dB,
     * so an appropriate conversion from linear UI input x to level is:
     * x == 0 -> level = 0
     * 0 < x <= R -> level = 10^(72*(x-R)/20/R)
     *
     * @param level send level scalar
     * @return error code or success, see {@link #SUCCESS},
     *    {@link #ERROR_INVALID_OPERATION}
     */
    public int setAuxEffectSendLevel(float level) {
        if (mState != STATE_INITIALIZED) {
            return ERROR_INVALID_OPERATION;
        }
        // clamp the level
        if (level < getMinVolume()) {
            level = getMinVolume();
        }
        if (level > getMaxVolume()) {
            level = getMaxVolume();
        }
        native_setAuxEffectSendLevel(level);
// ++++++++++++++++++++++++++++++android_media_AudioTrack_setAuxEffectSendLevel++++++++++++++++++++++++++++++++++
static void
android_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level )
{
    AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
        thiz, javaAudioTrackFields.nativeTrackInJavaObj);
    if (lpTrack == NULL ) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()");
        return;
    }


    lpTrack->setAuxEffectSendLevel(level);
// +++++++++++++++++++++++++++++AudioTrack::setAuxEffectSendLevel+++++++++++++++++++++++++++++++++++
status_t AudioTrack::setAuxEffectSendLevel(float level)
{
    LOGV("setAuxEffectSendLevel(%f)", level);
    if (level > 1.0f) {
        return BAD_VALUE;
    }


    mSendLevel = level;


// 函数AudioFlinger::MixerThread::prepareTracks_l中有使用mCblk->sendLevel
// va = (uint32_t)(v * cblk->sendLevel);
// aux = int16_t(va);
// mAudioMixer->setParameter(param, AudioMixer::AUXLEVEL, (void *)aux);
    mCblk->sendLevel = uint16_t(level * 0x1000);


    return NO_ERROR;
}
// -----------------------------AudioTrack::setAuxEffectSendLevel-----------------------------------
}
// ------------------------------android_media_AudioTrack_setAuxEffectSendLevel----------------------------------
        return SUCCESS;
    }
// -------------------------------setAuxEffectSendLevel---------------------------------
            result = true;
            effect.release();
            track.release();
        } catch (IllegalArgumentException e) {
            msg = msg.concat(": Equalizer not found");
            loge(msg, ": Equalizer not found");
        } catch (UnsupportedOperationException e) {
            msg = msg.concat(": Effect library not loaded");
            loge(msg, ": Effect library not loaded");
        }
        assertTrue(msg, result);
    }

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


&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
attachAuxEffect最终会将effect 的in buffer赋值给track对象的auxBuffer。
setAuxEffectSendLevel会将send level保存到audio_track_cblk_t对象中。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值