android audio代码分析,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)}.

*

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.

*

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 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<: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<: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 effect = getEffect_l(AudioSystem::SESSION_OUTPUT_MIX, EffectId);

+++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::getEffect_l+++++++++++++++++++++++++++++++++++

sp<:effectmodule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)

{

sp effect;

// 先得到chain

sp chain = getEffectChain_l(sessionId);

++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::getEffectChain_l++++++++++++++++++++++++++++++++++++

sp<:effectchain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId)

{

sp 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<:effectmodule> AudioFlinger::EffectChain::getEffectFromId_l(int id)

{

sp 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.

*

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.

*

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对象中。

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

摘自:江风的专栏

http://www.dengb.com/Androidjc/542929.htmlwww.dengb.comtruehttp://www.dengb.com/Androidjc/542929.htmlTechArticle今天来看看如何将AudioEffect与AudioTrack关联起来。 *****************************************源码************************************************* //Test case 1.7: te...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值