Android Audio代码分析23 - attachAuxEffect函数
来源:互联网 发布:爱思唯尔数据库英文 编辑:程序博客网 时间:2024/05/22 12:34
今天来看看如何将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 Audio代码分析23 - attachAuxEffect函数
- Android Audio代码分析2 - 函数getMinBufferSize
- Android Audio代码分析5 - 函数getAudioSessionId
- Android Audio代码分析16 - testPlaybackHeadPositionAfterPause函数
- Android Audio代码分析17 - setvolume函数
- Android Audio代码分析18 - setSampleRate函数
- Android Audio代码分析19 - setPosition函数
- Android Audio代码分析20 - queryEffects函数
- Audio笔记之Track::attachAuxEffect
- Android Audio代码分析26 - Audio Strategy
- Android Audio代码分析 - Audio Strategy
- Android Audio 代码分析- Audio Strategy
- Android Audio代码分析8 - AudioHardwareALSA::openOutputStream函数
- Android Audio代码分析9 - AudioTrack::write函数
- Android Audio代码分析10 - audio_track_cblk_t::framesReady函数
- Android Audio代码分析11 - AudioStreamOutALSA::write函数
- Android Audio代码分析13 - AudioTrack::getPosition函数
- Android Audio代码分析22 - AudioEffect::getEnabled函数
- 竞赛试题
- 随意注释掉代码的代码猴子。
- 关于联合体union的详细解释
- 算法设计
- 结构体的大小
- Android Audio代码分析23 - attachAuxEffect函数
- jquery表单验证实例 非常好
- Java/JSP中文乱码问题
- Servlet文件下载
- 3DS Max建模 植物的触碰效果
- epo.c
- EditText输入字符控制(二)
- C#语法
- 链表逆序