blob: e24fcf43213a4ab1e8f7a5e58b9f3b3f2cb3d767 [file] [log] [blame]
Chih-Chung Chang99698662011-06-30 14:21:38 +08001/*
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
James Dong3bd45592012-01-20 19:28:01 -080017//#define LOG_NDEBUG 0
Chih-Chung Chang99698662011-06-30 14:21:38 +080018#define LOG_TAG "VideoEditorBGAudioProcessing"
19#include <utils/Log.h>
20#include "VideoEditorBGAudioProcessing.h"
21
22namespace android {
23
24VideoEditorBGAudioProcessing::VideoEditorBGAudioProcessing() {
James Dong3bd45592012-01-20 19:28:01 -080025 ALOGV("Constructor");
Chih-Chung Chang99698662011-06-30 14:21:38 +080026
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
James Dong3bd45592012-01-20 19:28:01 -080048M4OSA_Int32 VideoEditorBGAudioProcessing::mixAndDuck(
49 void *primaryTrackBuffer,
50 void *backgroundTrackBuffer,
51 void *outBuffer) {
Chih-Chung Chang99698662011-06-30 14:21:38 +080052
James Dong3bd45592012-01-20 19:28:01 -080053 ALOGV("mixAndDuck: track buffers (primary: 0x%x and background: 0x%x) "
54 "and out buffer 0x%x",
55 primaryTrackBuffer, backgroundTrackBuffer, outBuffer);
Chih-Chung Chang99698662011-06-30 14:21:38 +080056
James Dong3bd45592012-01-20 19:28:01 -080057 M4AM_Buffer16* pPrimaryTrack = (M4AM_Buffer16*)primaryTrackBuffer;
58 M4AM_Buffer16* pBackgroundTrack = (M4AM_Buffer16*)backgroundTrackBuffer;
59 M4AM_Buffer16* pMixedOutBuffer = (M4AM_Buffer16*)outBuffer;
Chih-Chung Chang99698662011-06-30 14:21:38 +080060
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
James Dong3bd45592012-01-20 19:28:01 -080068 // Initialize ducking variables
Chih-Chung Chang99698662011-06-30 14:21:38 +080069 // Initially contains the input primary track
James Dong3bd45592012-01-20 19:28:01 -080070 M4OSA_Int16 *pPTMdata2 = (M4OSA_Int16*)pMixedOutBuffer->m_dataAddress;
71
Chih-Chung Chang99698662011-06-30 14:21:38 +080072 // Contains BG track processed data(like channel conversion etc..
James Dong3bd45592012-01-20 19:28:01 -080073 M4OSA_Int16 *pBTMdata1 = (M4OSA_Int16*) pBackgroundTrack->m_dataAddress;
Chih-Chung Chang99698662011-06-30 14:21:38 +080074
75 // Since we need to give sample count and not buffer size
James Dong3bd45592012-01-20 19:28:01 -080076 M4OSA_UInt32 uiPCMsize = pMixedOutBuffer->m_bufferSize / 2 ;
Chih-Chung Chang99698662011-06-30 14:21:38 +080077
78 if ((mDucking_enable) && (mPTVolLevel != 0.0)) {
James Dong3bd45592012-01-20 19:28:01 -080079 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);
Chih-Chung Chang99698662011-06-30 14:21:38 +080083
James Dong3bd45592012-01-20 19:28:01 -080084 for (size_t loopIndex = 0; loopIndex < n; ++loopIndex) {
Chih-Chung Chang99698662011-06-30 14:21:38 +080085 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 }
Chih-Chung Chang99698662011-06-30 14:21:38 +080094 }
95
96 mAudioVolumeArray[mAudVolArrIndex] = getDecibelSound(peakDbValue);
97
James Dong3bd45592012-01-20 19:28:01 -080098 // Check for threshold is done after kProcessingWindowSize cycles
99 if (mAudVolArrIndex >= kProcessingWindowSize - 1) {
100 mDoDucking = isThresholdBreached(
101 mAudioVolumeArray, mAudVolArrIndex, mDucking_threshold);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800102
Chih-Chung Chang99698662011-06-30 14:21:38 +0800103 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
James Dong3bd45592012-01-20 19:28:01 -0800124 mDuckingFactor -= mDucking_lowVolume;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800125 } 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
James Dong3bd45592012-01-20 19:28:01 -0800133 mDuckingFactor += mDucking_lowVolume;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800134 } else {
135 mDuckingFactor = 1.0;
136 }
137 }
138 } // end if - mDucking_enable
139
140
James Dong3bd45592012-01-20 19:28:01 -0800141 // Mixing logic
142 ALOGV("Out of Ducking analysis uiPCMsize %d %f %f",
143 mDoDucking, mDuckingFactor, mBTVolLevel);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800144 while (uiPCMsize-- > 0) {
145
Chih-Chung Chang99698662011-06-30 14:21:38 +0800146 // 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
James Dong3bd45592012-01-20 19:28:01 -0800164 M4OSA_Int32 temp;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800165 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 }
James Dong3bd45592012-01-20 19:28:01 -0800185
Chih-Chung Chang99698662011-06-30 14:21:38 +0800186 memcpy((void *)pMixedOutBuffer->m_dataAddress,
187 (void *)pBackgroundTrack->m_dataAddress,
188 pBackgroundTrack->m_bufferSize);
189
James Dong3bd45592012-01-20 19:28:01 -0800190 ALOGV("mixAndDuck: X");
191 return M4NO_ERROR;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800192}
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
James Dong3bd45592012-01-20 19:28:01 -0800200void VideoEditorBGAudioProcessing::setMixParams(
201 const AudioMixSettings& setting) {
202 ALOGV("setMixParams");
Chih-Chung Chang99698662011-06-30 14:21:38 +0800203
James Dong3bd45592012-01-20 19:28:01 -0800204 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;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800214
James Dong3bd45592012-01-20 19:28:01 -0800215 // Reset the following params to default values
Chih-Chung Chang99698662011-06-30 14:21:38 +0800216 mAudVolArrIndex = 0;
217 mDoDucking = 0;
James Dong3bd45592012-01-20 19:28:01 -0800218 mDuckingFactor = 1.0;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800219
James Dong3bd45592012-01-20 19:28:01 -0800220 ALOGV("ducking enable 0x%x lowVolume %f threshold %d "
221 "fPTVolLevel %f BTVolLevel %f",
222 mDucking_enable, mDucking_lowVolume, mDucking_threshold,
223 mPTVolLevel, mPTVolLevel);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800224
James Dong3bd45592012-01-20 19:28:01 -0800225 // 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
Chih-Chung Chang99698662011-06-30 14:21:38 +0800230 } else {
James Dong3bd45592012-01-20 19:28:01 -0800231 mChannelConversion = 2; // Convert to STEREO
Chih-Chung Chang99698662011-06-30 14:21:38 +0800232 }
233 } else {
James Dong3bd45592012-01-20 19:28:01 -0800234 mChannelConversion = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800235 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800236}
237
Chih-Chung Chang99698662011-06-30 14:21:38 +0800238// Fast way to compute 10 * log(value)
239M4OSA_Int32 VideoEditorBGAudioProcessing::getDecibelSound(M4OSA_UInt32 value) {
James Dong3bd45592012-01-20 19:28:01 -0800240 ALOGV("getDecibelSound: %ld", value);
241
Chih-Chung Chang99698662011-06-30 14:21:38 +0800242 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
James Dong3bd45592012-01-20 19:28:01 -0800284 ALOGV("isThresholdBreached");
285
Chih-Chung Chang99698662011-06-30 14:21:38 +0800286 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