Home | History | Annotate | Download | only in lvpp
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "VideoEditorBGAudioProcessing"
     19 #include <utils/Log.h>
     20 #include "VideoEditorBGAudioProcessing.h"
     21 
     22 namespace android {
     23 
     24 VideoEditorBGAudioProcessing::VideoEditorBGAudioProcessing() {
     25     ALOGV("Constructor");
     26 
     27     mAudVolArrIndex = 0;
     28     mDoDucking = 0;
     29     mDucking_enable = 0;
     30     mDucking_lowVolume = 0;
     31     mDucking_threshold = 0;
     32     mDuckingFactor = 0;
     33 
     34     mBTVolLevel = 0;
     35     mPTVolLevel = 0;
     36 
     37     mIsSSRCneeded = 0;
     38     mChannelConversion = 0;
     39 
     40     mBTFormat = MONO_16_BIT;
     41 
     42     mInSampleRate = 8000;
     43     mOutSampleRate = 16000;
     44     mPTChannelCount = 2;
     45     mBTChannelCount = 1;
     46 }
     47 
     48 M4OSA_Int32 VideoEditorBGAudioProcessing::mixAndDuck(
     49         void *primaryTrackBuffer,
     50         void *backgroundTrackBuffer,
     51         void *outBuffer) {
     52 
     53     ALOGV("mixAndDuck: track buffers (primary: 0x%x and background: 0x%x) "
     54             "and out buffer 0x%x",
     55             primaryTrackBuffer, backgroundTrackBuffer, outBuffer);
     56 
     57     M4AM_Buffer16* pPrimaryTrack   = (M4AM_Buffer16*)primaryTrackBuffer;
     58     M4AM_Buffer16* pBackgroundTrack = (M4AM_Buffer16*)backgroundTrackBuffer;
     59     M4AM_Buffer16* pMixedOutBuffer  = (M4AM_Buffer16*)outBuffer;
     60 
     61     // Output size if same as PT size
     62     pMixedOutBuffer->m_bufferSize = pPrimaryTrack->m_bufferSize;
     63 
     64     // Before mixing, we need to have only PT as out buffer
     65     memcpy((void *)pMixedOutBuffer->m_dataAddress,
     66         (void *)pPrimaryTrack->m_dataAddress, pMixedOutBuffer->m_bufferSize);
     67 
     68     // Initialize ducking variables
     69     // Initially contains the input primary track
     70     M4OSA_Int16 *pPTMdata2 = (M4OSA_Int16*)pMixedOutBuffer->m_dataAddress;
     71 
     72     // Contains BG track processed data(like channel conversion etc..
     73     M4OSA_Int16 *pBTMdata1 = (M4OSA_Int16*) pBackgroundTrack->m_dataAddress;
     74 
     75     // Since we need to give sample count and not buffer size
     76     M4OSA_UInt32 uiPCMsize = pMixedOutBuffer->m_bufferSize / 2 ;
     77 
     78     if ((mDucking_enable) && (mPTVolLevel != 0.0)) {
     79         M4OSA_Int32 peakDbValue = 0;
     80         M4OSA_Int32 previousDbValue = 0;
     81         M4OSA_Int16 *pPCM16Sample = (M4OSA_Int16*)pPrimaryTrack->m_dataAddress;
     82         const size_t n = pPrimaryTrack->m_bufferSize / sizeof(M4OSA_Int16);
     83 
     84         for (size_t loopIndex = 0; loopIndex < n; ++loopIndex) {
     85             if (pPCM16Sample[loopIndex] >= 0) {
     86                 peakDbValue = previousDbValue > pPCM16Sample[loopIndex] ?
     87                         previousDbValue : pPCM16Sample[loopIndex];
     88                 previousDbValue = peakDbValue;
     89             } else {
     90                 peakDbValue = previousDbValue > -pPCM16Sample[loopIndex] ?
     91                         previousDbValue: -pPCM16Sample[loopIndex];
     92                 previousDbValue = peakDbValue;
     93             }
     94         }
     95 
     96         mAudioVolumeArray[mAudVolArrIndex] = getDecibelSound(peakDbValue);
     97 
     98         // Check for threshold is done after kProcessingWindowSize cycles
     99         if (mAudVolArrIndex >= kProcessingWindowSize - 1) {
    100             mDoDucking = isThresholdBreached(
    101                     mAudioVolumeArray, mAudVolArrIndex, mDucking_threshold);
    102 
    103             mAudVolArrIndex = 0;
    104         } else {
    105             mAudVolArrIndex++;
    106         }
    107 
    108         //
    109         // Below logic controls the mixing weightage
    110         // for Background and Primary Tracks
    111         // for the duration of window under analysis,
    112         // to give fade-out for Background and fade-in for primary
    113         // Current fading factor is distributed in equal range over
    114         // the defined window size.
    115         // For a window size = 25
    116         // (500 ms (window under analysis) / 20 ms (sample duration))
    117         //
    118 
    119         if (mDoDucking) {
    120             if (mDuckingFactor > mDucking_lowVolume) {
    121                 // FADE OUT BG Track
    122                 // Increment ducking factor in total steps in factor
    123                 // of low volume steps to reach low volume level
    124                 mDuckingFactor -= mDucking_lowVolume;
    125             } else {
    126                 mDuckingFactor = mDucking_lowVolume;
    127             }
    128         } else {
    129             if (mDuckingFactor < 1.0 ) {
    130                 // FADE IN BG Track
    131                 // Increment ducking factor in total steps of
    132                 // low volume factor to reach orig.volume level
    133                 mDuckingFactor += mDucking_lowVolume;
    134             } else {
    135                 mDuckingFactor = 1.0;
    136             }
    137         }
    138     } // end if - mDucking_enable
    139 
    140 
    141     // Mixing logic
    142     ALOGV("Out of Ducking analysis uiPCMsize %d %f %f",
    143             mDoDucking, mDuckingFactor, mBTVolLevel);
    144     while (uiPCMsize-- > 0) {
    145 
    146         // Set vol factor for BT and PT
    147         *pBTMdata1 = (M4OSA_Int16)(*pBTMdata1*mBTVolLevel);
    148         *pPTMdata2 = (M4OSA_Int16)(*pPTMdata2*mPTVolLevel);
    149 
    150         // Mix the two samples
    151         if (mDoDucking) {
    152 
    153             // Duck the BG track to ducking factor value before mixing
    154             *pBTMdata1 = (M4OSA_Int16)((*pBTMdata1)*(mDuckingFactor));
    155 
    156             // mix as normal case
    157             *pBTMdata1 = (M4OSA_Int16)(*pBTMdata1 /2 + *pPTMdata2 /2);
    158         } else {
    159 
    160             *pBTMdata1 = (M4OSA_Int16)((*pBTMdata1)*(mDuckingFactor));
    161             *pBTMdata1 = (M4OSA_Int16)(*pBTMdata1 /2 + *pPTMdata2 /2);
    162         }
    163 
    164         M4OSA_Int32 temp;
    165         if (*pBTMdata1 < 0) {
    166             temp = -(*pBTMdata1) * 2; // bring to original Amplitude level
    167 
    168             if (temp > 32767) {
    169                 *pBTMdata1 = -32766; // less then max allowed value
    170             } else {
    171                 *pBTMdata1 = (M4OSA_Int16)(-temp);
    172             }
    173         } else {
    174             temp = (*pBTMdata1) * 2; // bring to original Amplitude level
    175             if ( temp > 32768) {
    176                 *pBTMdata1 = 32767; // less than max allowed value
    177             } else {
    178                 *pBTMdata1 = (M4OSA_Int16)temp;
    179             }
    180         }
    181 
    182         pBTMdata1++;
    183         pPTMdata2++;
    184     }
    185 
    186     memcpy((void *)pMixedOutBuffer->m_dataAddress,
    187         (void *)pBackgroundTrack->m_dataAddress,
    188         pBackgroundTrack->m_bufferSize);
    189 
    190     ALOGV("mixAndDuck: X");
    191     return M4NO_ERROR;
    192 }
    193 
    194 M4OSA_Int32 VideoEditorBGAudioProcessing::calculateOutResampleBufSize() {
    195 
    196     // This already takes care of channel count in mBTBuffer.m_bufferSize
    197     return (mOutSampleRate / mInSampleRate) * mBTBuffer.m_bufferSize;
    198 }
    199 
    200 void VideoEditorBGAudioProcessing::setMixParams(
    201         const AudioMixSettings& setting) {
    202     ALOGV("setMixParams");
    203 
    204     mDucking_enable       = setting.lvInDucking_enable;
    205     mDucking_lowVolume    = setting.lvInDucking_lowVolume;
    206     mDucking_threshold    = setting.lvInDucking_threshold;
    207     mPTVolLevel           = setting.lvPTVolLevel;
    208     mBTVolLevel           = setting.lvBTVolLevel ;
    209     mBTChannelCount       = setting.lvBTChannelCount;
    210     mPTChannelCount       = setting.lvPTChannelCount;
    211     mBTFormat             = setting.lvBTFormat;
    212     mInSampleRate         = setting.lvInSampleRate;
    213     mOutSampleRate        = setting.lvOutSampleRate;
    214 
    215     // Reset the following params to default values
    216     mAudVolArrIndex       = 0;
    217     mDoDucking            = 0;
    218     mDuckingFactor        = 1.0;
    219 
    220     ALOGV("ducking enable 0x%x lowVolume %f threshold %d "
    221             "fPTVolLevel %f BTVolLevel %f",
    222             mDucking_enable, mDucking_lowVolume, mDucking_threshold,
    223             mPTVolLevel, mPTVolLevel);
    224 
    225     // Decides if SSRC support is needed for this mixing
    226     mIsSSRCneeded = (setting.lvInSampleRate != setting.lvOutSampleRate);
    227     if (setting.lvBTChannelCount != setting.lvPTChannelCount){
    228         if (setting.lvBTChannelCount == 2){
    229             mChannelConversion = 1; // convert to MONO
    230         } else {
    231             mChannelConversion = 2; // Convert to STEREO
    232         }
    233     } else {
    234         mChannelConversion = 0;
    235     }
    236 }
    237 
    238 // Fast way to compute 10 * log(value)
    239 M4OSA_Int32 VideoEditorBGAudioProcessing::getDecibelSound(M4OSA_UInt32 value) {
    240     ALOGV("getDecibelSound: %ld", value);
    241 
    242     if (value <= 0 || value > 0x8000) {
    243         return 0;
    244     } else if (value > 0x4000) { // 32768
    245         return 90;
    246     } else if (value > 0x2000) { // 16384
    247         return 84;
    248     } else if (value > 0x1000) { // 8192
    249         return 78;
    250     } else if (value > 0x0800) { // 4028
    251         return 72;
    252     } else if (value > 0x0400) { // 2048
    253         return 66;
    254     } else if (value > 0x0200) { // 1024
    255         return 60;
    256     } else if (value > 0x0100) { // 512
    257         return 54;
    258     } else if (value > 0x0080) { // 256
    259         return 48;
    260     } else if (value > 0x0040) { // 128
    261         return 42;
    262     } else if (value > 0x0020) { // 64
    263         return 36;
    264     } else if (value > 0x0010) { // 32
    265         return 30;
    266     } else if (value > 0x0008) { // 16
    267         return 24;
    268     } else if (value > 0x0007) { // 8
    269         return 24;
    270     } else if (value > 0x0003) { // 4
    271         return 18;
    272     } else if (value > 0x0001) { // 2
    273         return 12;
    274     } else  { // 1
    275         return 6;
    276     }
    277 }
    278 
    279 M4OSA_Bool VideoEditorBGAudioProcessing::isThresholdBreached(
    280         M4OSA_Int32* averageValue,
    281         M4OSA_Int32 storeCount,
    282         M4OSA_Int32 thresholdValue) {
    283 
    284     ALOGV("isThresholdBreached");
    285 
    286     int totalValue = 0;
    287     for (int i = 0; i < storeCount; ++i) {
    288         totalValue += averageValue[i];
    289     }
    290     return (totalValue / storeCount > thresholdValue);
    291 }
    292 
    293 }//namespace android
    294