| /* | |
| * Copyright (C) 2011 NXP Software | |
| * Copyright (C) 2011 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #define LOG_NDEBUG 1 | |
| #define LOG_TAG "VideoEditorBGAudioProcessing" | |
| #include <utils/Log.h> | |
| #include "VideoEditorBGAudioProcessing.h" | |
| namespace android { | |
| VideoEditorBGAudioProcessing ::VideoEditorBGAudioProcessing() { | |
| LOGV("VideoEditorBGAudioProcessing:: Construct VideoEditorBGAudioProcessing "); | |
| VideoEditorBGAudioProcessing::mAudVolArrIndex = 0; | |
| VideoEditorBGAudioProcessing::mDoDucking = 0; | |
| VideoEditorBGAudioProcessing::mDucking_enable = 0; | |
| VideoEditorBGAudioProcessing::mDucking_lowVolume = 0; | |
| VideoEditorBGAudioProcessing::mDucking_threshold = 0; | |
| VideoEditorBGAudioProcessing::mDuckingFactor = 0; | |
| VideoEditorBGAudioProcessing::mBTVolLevel = 0; | |
| VideoEditorBGAudioProcessing::mPTVolLevel = 0; | |
| VideoEditorBGAudioProcessing::mIsSSRCneeded = 0; | |
| VideoEditorBGAudioProcessing::mChannelConversion = 0; | |
| VideoEditorBGAudioProcessing::mBTFormat = MONO_16_BIT; | |
| VideoEditorBGAudioProcessing::mInSampleRate = 8000; | |
| VideoEditorBGAudioProcessing::mOutSampleRate = 16000; | |
| VideoEditorBGAudioProcessing::mPTChannelCount = 2; | |
| VideoEditorBGAudioProcessing::mBTChannelCount = 1; | |
| } | |
| M4OSA_Int32 VideoEditorBGAudioProcessing::veProcessAudioMixNDuck( | |
| void *pPTBuffer, void *pBTBuffer, void *pOutBuffer) { | |
| M4AM_Buffer* pPrimaryTrack = (M4AM_Buffer*)pPTBuffer; | |
| M4AM_Buffer* pBackgroundTrack = (M4AM_Buffer*)pBTBuffer; | |
| M4AM_Buffer* pMixedOutBuffer = (M4AM_Buffer*)pOutBuffer; | |
| LOGV("VideoEditorBGAudioProcessing::lvProcessAudioMixNDuck \ | |
| pPTBuffer 0x%x pBTBuffer 0x%x pOutBuffer 0x%x", pPTBuffer, | |
| pBTBuffer, pOutBuffer); | |
| M4OSA_ERR result = M4NO_ERROR; | |
| M4OSA_Int16 *pBTMdata1; | |
| M4OSA_Int16 *pPTMdata2; | |
| M4OSA_UInt32 uiPCMsize; | |
| // Ducking variable | |
| M4OSA_UInt16 loopIndex = 0; | |
| M4OSA_Int16 *pPCM16Sample = M4OSA_NULL; | |
| M4OSA_Int32 peakDbValue = 0; | |
| M4OSA_Int32 previousDbValue = 0; | |
| M4OSA_UInt32 i; | |
| // Output size if same as PT size | |
| pMixedOutBuffer->m_bufferSize = pPrimaryTrack->m_bufferSize; | |
| // Before mixing, we need to have only PT as out buffer | |
| M4OSA_memcpy((M4OSA_MemAddr8)pMixedOutBuffer->m_dataAddress, | |
| (M4OSA_MemAddr8)pPrimaryTrack->m_dataAddress, pMixedOutBuffer->m_bufferSize); | |
| // Initially contains the input primary track | |
| pPTMdata2 = (M4OSA_Int16*)pMixedOutBuffer->m_dataAddress; | |
| // Contains BG track processed data(like channel conversion etc.. | |
| pBTMdata1 = (M4OSA_Int16*) pBackgroundTrack->m_dataAddress; | |
| // Since we need to give sample count and not buffer size | |
| uiPCMsize = pMixedOutBuffer->m_bufferSize/2 ; | |
| if((this->mDucking_enable) && (this->mPTVolLevel != 0.0)) { | |
| // LOGI("VideoEditorBGAudioProcessing:: In Ducking analysis "); | |
| loopIndex = 0; | |
| peakDbValue = 0; | |
| previousDbValue = peakDbValue; | |
| pPCM16Sample = (M4OSA_Int16*)pPrimaryTrack->m_dataAddress; | |
| while( loopIndex < pPrimaryTrack->m_bufferSize/sizeof(M4OSA_Int16)) | |
| { | |
| if (pPCM16Sample[loopIndex] >= 0){ | |
| peakDbValue = previousDbValue > pPCM16Sample[loopIndex] ? | |
| previousDbValue : pPCM16Sample[loopIndex]; | |
| previousDbValue = peakDbValue; | |
| }else{ | |
| peakDbValue = previousDbValue > -pPCM16Sample[loopIndex] ? | |
| previousDbValue: -pPCM16Sample[loopIndex]; | |
| previousDbValue = peakDbValue; | |
| } | |
| loopIndex++; | |
| } | |
| this->mAudioVolumeArray[this->mAudVolArrIndex] = | |
| getDecibelSound(peakDbValue); | |
| LOGV("VideoEditorBGAudioProcessing:: getDecibelSound %d", | |
| this->mAudioVolumeArray[this->mAudVolArrIndex]); | |
| // WINDOW_SIZE is 10 by default | |
| // Check for threshold is done after 10 cycles | |
| if ( this->mAudVolArrIndex >= WINDOW_SIZE -1) { | |
| this->mDoDucking = isThresholdBreached(this->mAudioVolumeArray, | |
| this->mAudVolArrIndex,this->mDucking_threshold ); | |
| this->mAudVolArrIndex = 0; | |
| } else { | |
| this->mAudVolArrIndex++; | |
| } | |
| // | |
| // Below logic controls the mixing weightage | |
| // for Background and Primary Tracks | |
| // for the duration of window under analysis, | |
| // to give fade-out for Background and fade-in for primary | |
| // Current fading factor is distributed in equal range over | |
| // the defined window size. | |
| // For a window size = 25 | |
| // (500 ms (window under analysis) / 20 ms (sample duration)) | |
| // | |
| if(this->mDoDucking){ | |
| if ( this->mDuckingFactor > this->mDucking_lowVolume) { | |
| // FADE OUT BG Track | |
| // Increment ducking factor in total steps in factor | |
| // of low volume steps to reach low volume level | |
| this->mDuckingFactor -= (this->mDucking_lowVolume); | |
| } | |
| else { | |
| this->mDuckingFactor = this->mDucking_lowVolume; | |
| } | |
| } else { | |
| if ( this->mDuckingFactor < 1.0 ){ | |
| // FADE IN BG Track | |
| // Increment ducking factor in total steps of | |
| // low volume factor to reach orig.volume level | |
| this->mDuckingFactor += (this->mDucking_lowVolume); | |
| } | |
| else{ | |
| this->mDuckingFactor = 1.0; | |
| } | |
| } | |
| } // end if - mDucking_enable | |
| // Mixing Logic | |
| LOGV("VideoEditorBGAudioProcessing:: Out of Ducking analysis uiPCMsize\ | |
| %d %f %f", this->mDoDucking, this->mDuckingFactor,this->mBTVolLevel); | |
| while(uiPCMsize-->0) { | |
| M4OSA_Int32 temp; | |
| // Set vol factor for BT and PT | |
| *pBTMdata1 = (M4OSA_Int16)(*pBTMdata1*this->mBTVolLevel); | |
| *pPTMdata2 = (M4OSA_Int16)(*pPTMdata2*this->mPTVolLevel); | |
| // Mix the two samples | |
| if ( this->mDoDucking) { | |
| // Duck the BG track to ducking factor value before mixing | |
| *pBTMdata1 = (M4OSA_Int16)((*pBTMdata1)*(this->mDuckingFactor)); | |
| // mix as normal case | |
| *pBTMdata1 = (M4OSA_Int16)(*pBTMdata1 /2 + *pPTMdata2 /2); | |
| } | |
| else { | |
| *pBTMdata1 = (M4OSA_Int16)((*pBTMdata1)*(this->mDuckingFactor)); | |
| *pBTMdata1 = (M4OSA_Int16)(*pBTMdata1 /2 + *pPTMdata2 /2); | |
| } | |
| if ( *pBTMdata1 < 0) { | |
| temp = -(*pBTMdata1) * 2; // bring to original Amplitude level | |
| if ( temp > 32767) { | |
| *pBTMdata1 = -32766; // less then max allowed value | |
| } | |
| else{ | |
| *pBTMdata1 = (M4OSA_Int16)(-temp); | |
| } | |
| } | |
| else { | |
| temp = (*pBTMdata1) * 2; // bring to original Amplitude level | |
| if ( temp > 32768) { | |
| *pBTMdata1 = 32767; // less than max allowed value | |
| } | |
| else { | |
| *pBTMdata1 = (M4OSA_Int16)temp; | |
| } | |
| } | |
| pBTMdata1++; | |
| pPTMdata2++; | |
| } | |
| //LOGV("VideoEditorBGAudioProcessing:: Copy final out "); | |
| M4OSA_memcpy((M4OSA_MemAddr8)pMixedOutBuffer->m_dataAddress, | |
| (M4OSA_MemAddr8)pBackgroundTrack->m_dataAddress, | |
| pBackgroundTrack->m_bufferSize); | |
| LOGV("VideoEditorBGAudioProcessing::lvProcessAudioMixNDuck EXIT"); | |
| return result; | |
| } | |
| VideoEditorBGAudioProcessing:: ~VideoEditorBGAudioProcessing() { | |
| //free(VideoEditorBGAudioProcessing:: pTempBuffer); | |
| } | |
| M4OSA_Int32 VideoEditorBGAudioProcessing::calculateOutResampleBufSize() { | |
| M4OSA_Int32 bufSize =0; | |
| // This already takes care of channel count in mBTBuffer.m_bufferSize | |
| bufSize = (this->mOutSampleRate/this->mInSampleRate)*this->mBTBuffer.m_bufferSize; | |
| return bufSize; | |
| } | |
| void VideoEditorBGAudioProcessing ::veSetAudioProcessingParams( | |
| veAudMixSettings gInputParams) { | |
| LOGV("VideoEditorBGAudioProcessing:: ENTER lvSetAudioProcessingParams "); | |
| this->mDucking_enable = gInputParams.lvInDucking_enable; | |
| this->mDucking_lowVolume = gInputParams.lvInDucking_lowVolume; | |
| this->mDucking_threshold = gInputParams.lvInDucking_threshold; | |
| this->mPTVolLevel = gInputParams.lvPTVolLevel; | |
| this->mBTVolLevel = gInputParams.lvBTVolLevel ; | |
| this->mBTChannelCount = gInputParams.lvBTChannelCount; | |
| this->mPTChannelCount = gInputParams.lvPTChannelCount; | |
| this->mBTFormat = gInputParams.lvBTFormat; | |
| this->mInSampleRate = gInputParams.lvInSampleRate; | |
| this->mOutSampleRate = gInputParams.lvOutSampleRate; | |
| this->mAudVolArrIndex = 0; | |
| this->mDoDucking = 0; | |
| this->mDuckingFactor = 1.0; // default | |
| LOGV("VideoEditorBGAudioProcessing:: ducking_enable 0x%x \ | |
| ducking_lowVolume %f ducking_threshold %d fPTVolLevel %f BTVolLevel %f", | |
| this->mDucking_enable, this->mDucking_lowVolume, this->mDucking_threshold, | |
| this->mPTVolLevel, this->mPTVolLevel); | |
| // Following logc decides if SSRC support is needed for this mixing | |
| if ( gInputParams.lvInSampleRate != gInputParams.lvOutSampleRate){ | |
| this->mIsSSRCneeded = 1; | |
| }else{ | |
| this->mIsSSRCneeded = 0; | |
| } | |
| if( gInputParams.lvBTChannelCount != gInputParams.lvPTChannelCount){ | |
| if (gInputParams.lvBTChannelCount == 2){ | |
| this->mChannelConversion = 1; // convert to MONO | |
| }else{ | |
| this->mChannelConversion = 2; // Convert to STEREO | |
| } | |
| }else{ | |
| this->mChannelConversion = 0; | |
| } | |
| LOGV("VideoEditorBGAudioProcessing:: EXIT veSetAudioProcessingParams "); | |
| } | |
| M4OSA_Int32 VideoEditorBGAudioProcessing:: getDecibelSound(M4OSA_UInt32 value) { | |
| int dbSound = 1; | |
| if (value == 0) return 0; | |
| if (value > 0x4000 && value <= 0x8000) // 32768 | |
| dbSound = 90; | |
| else if (value > 0x2000 && value <= 0x4000) // 16384 | |
| dbSound = 84; | |
| else if (value > 0x1000 && value <= 0x2000) // 8192 | |
| dbSound = 78; | |
| else if (value > 0x0800 && value <= 0x1000) // 4028 | |
| dbSound = 72; | |
| else if (value > 0x0400 && value <= 0x0800) // 2048 | |
| dbSound = 66; | |
| else if (value > 0x0200 && value <= 0x0400) // 1024 | |
| dbSound = 60; | |
| else if (value > 0x0100 && value <= 0x0200) // 512 | |
| dbSound = 54; | |
| else if (value > 0x0080 && value <= 0x0100) // 256 | |
| dbSound = 48; | |
| else if (value > 0x0040 && value <= 0x0080) // 128 | |
| dbSound = 42; | |
| else if (value > 0x0020 && value <= 0x0040) // 64 | |
| dbSound = 36; | |
| else if (value > 0x0010 && value <= 0x0020) // 32 | |
| dbSound = 30; | |
| else if (value > 0x0008 && value <= 0x0010) //16 | |
| dbSound = 24; | |
| else if (value > 0x0007 && value <= 0x0008) //8 | |
| dbSound = 24; | |
| else if (value > 0x0003 && value <= 0x0007) // 4 | |
| dbSound = 18; | |
| else if (value > 0x0001 && value <= 0x0003) //2 | |
| dbSound = 12; | |
| else if (value > 0x000 && value <= 0x0001) // 1 | |
| dbSound = 6; | |
| else | |
| dbSound = 0; | |
| return dbSound; | |
| } | |
| M4OSA_Bool VideoEditorBGAudioProcessing:: isThresholdBreached( | |
| M4OSA_Int32* averageValue, M4OSA_Int32 storeCount, | |
| M4OSA_Int32 thresholdValue) { | |
| M4OSA_Bool result = 0; | |
| int i; | |
| int finalValue = 0; | |
| for (i=0; i< storeCount;i++) | |
| finalValue += averageValue[i]; | |
| finalValue = finalValue/storeCount; | |
| //printf ("<%d > \t ", finalValue); | |
| if (finalValue > thresholdValue) | |
| result = M4OSA_TRUE; | |
| else | |
| result = M4OSA_FALSE; | |
| return result; | |
| } | |
| }//namespace android |