blob: 2049f08f654e89e39797196be642fd893c4e2061 [file] [log] [blame]
/*
* 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