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对象中。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值