• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
VideoEditorBGAudioProcessing()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 
mixAndDuck(void * primaryTrackBuffer,void * backgroundTrackBuffer,void * outBuffer)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 
calculateOutResampleBufSize()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 
setMixParams(const AudioMixSettings & setting)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)
getDecibelSound(M4OSA_UInt32 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 
isThresholdBreached(M4OSA_Int32 * averageValue,M4OSA_Int32 storeCount,M4OSA_Int32 thresholdValue)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