VideoEditorBGAudioProcessing.cpp revision 3bd45591402b94ed4481ea0ee0a9140840979c84
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
22namespace android {
23
24VideoEditorBGAudioProcessing::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
48M4OSA_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
194M4OSA_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
200void 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)
239M4OSA_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
279M4OSA_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