Android(安卓)Audio代码分析23 - attachAuxEffect函数
16lz
2022-06-15
今天来看看如何将AudioEffect与AudioTrack关联起来。
*****************************************源码*************************************************
**********************************************************************************************
源码路径:
frameworks\base\media\tests\mediaframeworktest\src\com\android\mediaframeworktest\functional\MediaAudioEffectTest.java
#######################说明################################
###########################################################
&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
attachAuxEffect最终会将effect 的in buffer赋值给track对象的auxBuffer。
setAuxEffectSendLevel会将send level保存到audio_track_cblk_t对象中。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
*****************************************源码*************************************************
//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 heldsp<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 voidandroid_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对象中。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
更多相关文章
- Android(安卓)EditText得到焦点失去焦点处理方法
- 2.20 android连接wifi,解决mWifiManager.addNetwork(info)=-1
- 代码讲解Android(安卓)Scroller、VelocityTracker
- Android(安卓)GPS获得经纬度并得到该坐标精确地址
- 《Android系统学习》第十章:Android消息处理、消息循环和消息队列
- Android(安卓)服务(本地服务示例)(二)
- Android(安卓)Audio代码分析23 - attachAuxEffect函数
- 【笔记】android捕获触摸事件
- 箭头函数的基础使用