Audio笔记之EffectChain::process_l
来源:互联网 发布:java错误无法加载主类 编辑:程序博客网 时间:2024/06/03 17:30
// Must be called with EffectChain::mLock lockedvoid AudioFlinger::EffectChain::process_l(){ sp<ThreadBase> thread = mThread.promote(); if (thread == 0) { ALOGW("process_l(): cannot promote mixer thread"); return; } bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) || (mSessionId == AUDIO_SESSION_OUTPUT_STAGE); // never process effects when: // - on an OFFLOAD thread // - no more tracks are on the session and the effect tail has been rendered bool doProcess = (thread->type() != ThreadBase::OFFLOAD); //1、对于非全局effect,如果没有关联的track且tailBuffCount为0,则不使用音效 // 每次新增激活track,都会将tailBuffCount置为MaxCount,所以当激活track // 数量不为0时,tailBuffCount肯定大于0,因此当有激活track存在时,一定会 // 执行音效处理,如果没有激活track存在时,如果有关联的track,虽然调用了音效 // 处理,但实际上输入已经经过清理了,所以不影响输出 //2、对于全局effect,无需关系track状态,直接对MixBuff中的数据进行处理 if (!isGlobalSession) { bool tracksOnSession = (trackCnt() != 0); if (!tracksOnSession && mTailBufferCount == 0) { doProcess = false; } // 如果与effect关联的track都没有激活 if (activeTrackCnt() == 0) { // if no track is active and the effect tail has not been rendered, // the input buffer must be cleared here as the mixer process will not do it if (tracksOnSession || mTailBufferCount > 0) { clearInputBuffer_l(thread); if (mTailBufferCount > 0) { mTailBufferCount--; } } } } size_t size = mEffects.size(); if (doProcess) { for (size_t i = 0; i < size; i++) { mEffects[i]->process(); } } for (size_t i = 0; i < size; i++) { mEffects[i]->updateState(); }}void AudioFlinger::EffectModule::process(){ Mutex::Autolock _l(mLock); if (mState == DESTROYED || mEffectInterface == NULL || mConfig.inputCfg.buffer.raw == NULL || mConfig.outputCfg.buffer.raw == NULL) { return; } // 1、如果该effect可用,则调用effect engine进行数据处理,并将其写入输出 // 2、如果该effect不可用,且属于insert类型并处于Chain的尾端,则需要 // 将其输入填充到其输出,否则该Chain的数据无法送到mMixBuff中,如果 // effect不是在尾端,则其输入和输出相同,无需进行额外的填充 if (isProcessEnabled()) { // do 32 bit to 16 bit conversion for auxiliary effect input buffer if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { ditherAndClamp(mConfig.inputCfg.buffer.s32, mConfig.inputCfg.buffer.s32, mConfig.inputCfg.buffer.frameCount/2); } // do the actual processing in the effect engine int ret = (*mEffectInterface)->process(mEffectInterface, &mConfig.inputCfg.buffer, &mConfig.outputCfg.buffer); // force transition to IDLE state when engine is ready if (mState == STOPPED && ret == -ENODATA) { mDisableWaitCnt = 1; } // clear auxiliary effect input buffer for next accumulation if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { memset(mConfig.inputCfg.buffer.raw, 0, mConfig.inputCfg.buffer.frameCount*sizeof(int32_t)); } } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT && mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) { // If an insert effect is idle and input buffer is different from output buffer, // accumulate input onto output sp<EffectChain> chain = mChain.promote(); if (chain != 0 && chain->activeTrackCnt() != 0) { size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here int16_t *in = mConfig.inputCfg.buffer.s16; int16_t *out = mConfig.outputCfg.buffer.s16; for (size_t i = 0; i < frameCnt; i++) { out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]); } } }}bool AudioFlinger::EffectModule::isProcessEnabled() const{ if (mStatus != NO_ERROR) { return false; } switch (mState) { case RESTART: case ACTIVE: case STOPPING: case STOPPED: return true; case IDLE: case STARTING: case DESTROYED: default: return false; }}static inline int16_t clamp16(int32_t sample){ if ((sample>>15) ^ (sample>>31)) sample = 0x7FFF ^ (sample>>31); return sample;}void AudioFlinger::EffectModule::updateState() { Mutex::Autolock _l(mLock); switch (mState) { case RESTART: reset_l(); // FALL THROUGH case STARTING: // clear auxiliary effect input buffer for next accumulation if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { memset(mConfig.inputCfg.buffer.raw, 0, mConfig.inputCfg.buffer.frameCount*sizeof(int32_t)); } if (start_l() == NO_ERROR) { mState = ACTIVE; } else { mState = IDLE; } break; case STOPPING: if (stop_l() == NO_ERROR) { mDisableWaitCnt = mMaxDisableWaitCnt; } else { mDisableWaitCnt = 1; // will cause immediate transition to IDLE } mState = STOPPED; break; case STOPPED: // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the // turn off sequence. if (--mDisableWaitCnt == 0) { reset_l(); mState = IDLE; } break; default: //IDLE , ACTIVE, DESTROYED break; }}
0 0
- Audio笔记之EffectChain::process_l
- Audio笔记之AudioMixer
- Audio笔记之MixerThread
- Audio笔记之FastMixer
- Audio笔记之AudioTrack
- Audio笔记之AudioTrackThread
- Audio笔记之AudioEffect
- Audio笔记之SoftAAC2
- Audio笔记之ServiceManager
- Audio笔记之MixerThread
- Audio笔记之AudioMixer
- Audio笔记之AudioFlinger::createTrack
- Audio笔记之MixerThread::prepareTracks_l
- Audio笔记之Track::attachAuxEffect
- Audio笔记之AudioTrack::write
- Audio笔记之AudioTrack::play
- Audio笔记之PlaybackThread::threadLoop
- Audio笔记之MixerThread::threadLoop_mix
- Linux下的platform总线驱动(一)
- 《c程序设计语言》-3.2 字符串转换
- Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(四)
- asp.net网页消息提示框代码
- Linux下的platform总线驱动(二)
- Audio笔记之EffectChain::process_l
- Android_TextView属性
- Fixatdl
- Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(三)
- sencha里用html5实现类似combobox组件,可选可输入
- java mina FundTradeProtocolDecoder
- javascript中日期Date类的setMonth问题 多一个月
- PHP调用APNS服务发送提醒样例
- java mina FundTradeProtocolEncoder