blob: 0c12aac79d2f467bd4b5b4e7d6c99bace76fea9c [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
Mark Salyzyndb43b342014-04-04 14:47:28 -070017#include <inttypes.h>
18
James Dong3bd45592012-01-20 19:28:01 -080019//#define LOG_NDEBUG 0
Chih-Chung Chang99698662011-06-30 14:21:38 +080020#define LOG_TAG "VideoEditorBGAudioProcessing"
21#include <utils/Log.h>
22#include "VideoEditorBGAudioProcessing.h"
23
24namespace android {
25
26VideoEditorBGAudioProcessing::VideoEditorBGAudioProcessing() {
James Dong3bd45592012-01-20 19:28:01 -080027 ALOGV("Constructor");
Chih-Chung Chang99698662011-06-30 14:21:38 +080028
29 mAudVolArrIndex = 0;
30 mDoDucking = 0;
31 mDucking_enable = 0;
32 mDucking_lowVolume = 0;
33 mDucking_threshold = 0;
34 mDuckingFactor = 0;
35
36 mBTVolLevel = 0;
37 mPTVolLevel = 0;
38
39 mIsSSRCneeded = 0;
40 mChannelConversion = 0;
41
42 mBTFormat = MONO_16_BIT;
43
44 mInSampleRate = 8000;
45 mOutSampleRate = 16000;
46 mPTChannelCount = 2;
47 mBTChannelCount = 1;
48}
49
James Dong3bd45592012-01-20 19:28:01 -080050M4OSA_Int32 VideoEditorBGAudioProcessing::mixAndDuck(
51 void *primaryTrackBuffer,
52 void *backgroundTrackBuffer,
53 void *outBuffer) {
Chih-Chung Chang99698662011-06-30 14:21:38 +080054
Mark Salyzyndb43b342014-04-04 14:47:28 -070055 ALOGV("mixAndDuck: track buffers (primary: %p and background: %p) "
56 "and out buffer %p",
James Dong3bd45592012-01-20 19:28:01 -080057 primaryTrackBuffer, backgroundTrackBuffer, outBuffer);
Chih-Chung Chang99698662011-06-30 14:21:38 +080058
James Dong3bd45592012-01-20 19:28:01 -080059 M4AM_Buffer16* pPrimaryTrack = (M4AM_Buffer16*)primaryTrackBuffer;
60 M4AM_Buffer16* pBackgroundTrack = (M4AM_Buffer16*)backgroundTrackBuffer;
61 M4AM_Buffer16* pMixedOutBuffer = (M4AM_Buffer16*)outBuffer;
Chih-Chung Chang99698662011-06-30 14:21:38 +080062
63 // Output size if same as PT size
64 pMixedOutBuffer->m_bufferSize = pPrimaryTrack->m_bufferSize;
65
66 // Before mixing, we need to have only PT as out buffer
67 memcpy((void *)pMixedOutBuffer->m_dataAddress,
68 (void *)pPrimaryTrack->m_dataAddress, pMixedOutBuffer->m_bufferSize);
69
James Dong3bd45592012-01-20 19:28:01 -080070 // Initialize ducking variables
Chih-Chung Chang99698662011-06-30 14:21:38 +080071 // Initially contains the input primary track
James Dong3bd45592012-01-20 19:28:01 -080072 M4OSA_Int16 *pPTMdata2 = (M4OSA_Int16*)pMixedOutBuffer->m_dataAddress;
73
Chih-Chung Chang99698662011-06-30 14:21:38 +080074 // Contains BG track processed data(like channel conversion etc..
James Dong3bd45592012-01-20 19:28:01 -080075 M4OSA_Int16 *pBTMdata1 = (M4OSA_Int16*) pBackgroundTrack->m_dataAddress;
Chih-Chung Chang99698662011-06-30 14:21:38 +080076
77 // Since we need to give sample count and not buffer size
James Dong3bd45592012-01-20 19:28:01 -080078 M4OSA_UInt32 uiPCMsize = pMixedOutBuffer->m_bufferSize / 2 ;
Chih-Chung Chang99698662011-06-30 14:21:38 +080079
80 if ((mDucking_enable) && (mPTVolLevel != 0.0)) {
James Dong3bd45592012-01-20 19:28:01 -080081 M4OSA_Int32 peakDbValue = 0;
82 M4OSA_Int32 previousDbValue = 0;
83 M4OSA_Int16 *pPCM16Sample = (M4OSA_Int16*)pPrimaryTrack->m_dataAddress;
84 const size_t n = pPrimaryTrack->m_bufferSize / sizeof(M4OSA_Int16);
Chih-Chung Chang99698662011-06-30 14:21:38 +080085
James Dong3bd45592012-01-20 19:28:01 -080086 for (size_t loopIndex = 0; loopIndex < n; ++loopIndex) {
Chih-Chung Chang99698662011-06-30 14:21:38 +080087 if (pPCM16Sample[loopIndex] >= 0) {
88 peakDbValue = previousDbValue > pPCM16Sample[loopIndex] ?
89 previousDbValue : pPCM16Sample[loopIndex];
90 previousDbValue = peakDbValue;
91 } else {
92 peakDbValue = previousDbValue > -pPCM16Sample[loopIndex] ?
93 previousDbValue: -pPCM16Sample[loopIndex];
94 previousDbValue = peakDbValue;
95 }
Chih-Chung Chang99698662011-06-30 14:21:38 +080096 }
97
98 mAudioVolumeArray[mAudVolArrIndex] = getDecibelSound(peakDbValue);
99
James Dong3bd45592012-01-20 19:28:01 -0800100 // Check for threshold is done after kProcessingWindowSize cycles
101 if (mAudVolArrIndex >= kProcessingWindowSize - 1) {
102 mDoDucking = isThresholdBreached(
103 mAudioVolumeArray, mAudVolArrIndex, mDucking_threshold);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800104
Chih-Chung Chang99698662011-06-30 14:21:38 +0800105 mAudVolArrIndex = 0;
106 } else {
107 mAudVolArrIndex++;
108 }
109
110 //
111 // Below logic controls the mixing weightage
112 // for Background and Primary Tracks
113 // for the duration of window under analysis,
114 // to give fade-out for Background and fade-in for primary
115 // Current fading factor is distributed in equal range over
116 // the defined window size.
117 // For a window size = 25
118 // (500 ms (window under analysis) / 20 ms (sample duration))
119 //
120
121 if (mDoDucking) {
122 if (mDuckingFactor > mDucking_lowVolume) {
123 // FADE OUT BG Track
124 // Increment ducking factor in total steps in factor
125 // of low volume steps to reach low volume level
James Dong3bd45592012-01-20 19:28:01 -0800126 mDuckingFactor -= mDucking_lowVolume;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800127 } else {
128 mDuckingFactor = mDucking_lowVolume;
129 }
130 } else {
131 if (mDuckingFactor < 1.0 ) {
132 // FADE IN BG Track
133 // Increment ducking factor in total steps of
134 // low volume factor to reach orig.volume level
James Dong3bd45592012-01-20 19:28:01 -0800135 mDuckingFactor += mDucking_lowVolume;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800136 } else {
137 mDuckingFactor = 1.0;
138 }
139 }
140 } // end if - mDucking_enable
141
142
James Dong3bd45592012-01-20 19:28:01 -0800143 // Mixing logic
144 ALOGV("Out of Ducking analysis uiPCMsize %d %f %f",
145 mDoDucking, mDuckingFactor, mBTVolLevel);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800146 while (uiPCMsize-- > 0) {
147
Chih-Chung Chang99698662011-06-30 14:21:38 +0800148 // Set vol factor for BT and PT
149 *pBTMdata1 = (M4OSA_Int16)(*pBTMdata1*mBTVolLevel);
150 *pPTMdata2 = (M4OSA_Int16)(*pPTMdata2*mPTVolLevel);
151
152 // Mix the two samples
153 if (mDoDucking) {
154
155 // Duck the BG track to ducking factor value before mixing
156 *pBTMdata1 = (M4OSA_Int16)((*pBTMdata1)*(mDuckingFactor));
157
158 // mix as normal case
159 *pBTMdata1 = (M4OSA_Int16)(*pBTMdata1 /2 + *pPTMdata2 /2);
160 } else {
161
162 *pBTMdata1 = (M4OSA_Int16)((*pBTMdata1)*(mDuckingFactor));
163 *pBTMdata1 = (M4OSA_Int16)(*pBTMdata1 /2 + *pPTMdata2 /2);
164 }
165
James Dong3bd45592012-01-20 19:28:01 -0800166 M4OSA_Int32 temp;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800167 if (*pBTMdata1 < 0) {
168 temp = -(*pBTMdata1) * 2; // bring to original Amplitude level
169
170 if (temp > 32767) {
171 *pBTMdata1 = -32766; // less then max allowed value
172 } else {
173 *pBTMdata1 = (M4OSA_Int16)(-temp);
174 }
175 } else {
176 temp = (*pBTMdata1) * 2; // bring to original Amplitude level
177 if ( temp > 32768) {
178 *pBTMdata1 = 32767; // less than max allowed value
179 } else {
180 *pBTMdata1 = (M4OSA_Int16)temp;
181 }
182 }
183
184 pBTMdata1++;
185 pPTMdata2++;
186 }
James Dong3bd45592012-01-20 19:28:01 -0800187
Chih-Chung Chang99698662011-06-30 14:21:38 +0800188 memcpy((void *)pMixedOutBuffer->m_dataAddress,
189 (void *)pBackgroundTrack->m_dataAddress,
190 pBackgroundTrack->m_bufferSize);
191
James Dong3bd45592012-01-20 19:28:01 -0800192 ALOGV("mixAndDuck: X");
193 return M4NO_ERROR;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800194}
195
196M4OSA_Int32 VideoEditorBGAudioProcessing::calculateOutResampleBufSize() {
197
198 // This already takes care of channel count in mBTBuffer.m_bufferSize
199 return (mOutSampleRate / mInSampleRate) * mBTBuffer.m_bufferSize;
200}
201
James Dong3bd45592012-01-20 19:28:01 -0800202void VideoEditorBGAudioProcessing::setMixParams(
203 const AudioMixSettings& setting) {
204 ALOGV("setMixParams");
Chih-Chung Chang99698662011-06-30 14:21:38 +0800205
James Dong3bd45592012-01-20 19:28:01 -0800206 mDucking_enable = setting.lvInDucking_enable;
207 mDucking_lowVolume = setting.lvInDucking_lowVolume;
208 mDucking_threshold = setting.lvInDucking_threshold;
209 mPTVolLevel = setting.lvPTVolLevel;
210 mBTVolLevel = setting.lvBTVolLevel ;
211 mBTChannelCount = setting.lvBTChannelCount;
212 mPTChannelCount = setting.lvPTChannelCount;
213 mBTFormat = setting.lvBTFormat;
214 mInSampleRate = setting.lvInSampleRate;
215 mOutSampleRate = setting.lvOutSampleRate;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800216
James Dong3bd45592012-01-20 19:28:01 -0800217 // Reset the following params to default values
Chih-Chung Chang99698662011-06-30 14:21:38 +0800218 mAudVolArrIndex = 0;
219 mDoDucking = 0;
James Dong3bd45592012-01-20 19:28:01 -0800220 mDuckingFactor = 1.0;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800221
Mark Salyzyndb43b342014-04-04 14:47:28 -0700222 ALOGV("ducking enable 0x%x lowVolume %f threshold %" PRIu32 " "
James Dong3bd45592012-01-20 19:28:01 -0800223 "fPTVolLevel %f BTVolLevel %f",
224 mDucking_enable, mDucking_lowVolume, mDucking_threshold,
225 mPTVolLevel, mPTVolLevel);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800226
James Dong3bd45592012-01-20 19:28:01 -0800227 // Decides if SSRC support is needed for this mixing
228 mIsSSRCneeded = (setting.lvInSampleRate != setting.lvOutSampleRate);
229 if (setting.lvBTChannelCount != setting.lvPTChannelCount){
230 if (setting.lvBTChannelCount == 2){
231 mChannelConversion = 1; // convert to MONO
Chih-Chung Chang99698662011-06-30 14:21:38 +0800232 } else {
James Dong3bd45592012-01-20 19:28:01 -0800233 mChannelConversion = 2; // Convert to STEREO
Chih-Chung Chang99698662011-06-30 14:21:38 +0800234 }
235 } else {
James Dong3bd45592012-01-20 19:28:01 -0800236 mChannelConversion = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800237 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800238}
239
Chih-Chung Chang99698662011-06-30 14:21:38 +0800240// Fast way to compute 10 * log(value)
241M4OSA_Int32 VideoEditorBGAudioProcessing::getDecibelSound(M4OSA_UInt32 value) {
James Dong3bd45592012-01-20 19:28:01 -0800242 ALOGV("getDecibelSound: %ld", value);
243
Chih-Chung Chang99698662011-06-30 14:21:38 +0800244 if (value <= 0 || value > 0x8000) {
245 return 0;
246 } else if (value > 0x4000) { // 32768
247 return 90;
248 } else if (value > 0x2000) { // 16384
249 return 84;
250 } else if (value > 0x1000) { // 8192
251 return 78;
252 } else if (value > 0x0800) { // 4028
253 return 72;
254 } else if (value > 0x0400) { // 2048
255 return 66;
256 } else if (value > 0x0200) { // 1024
257 return 60;
258 } else if (value > 0x0100) { // 512
259 return 54;
260 } else if (value > 0x0080) { // 256
261 return 48;
262 } else if (value > 0x0040) { // 128
263 return 42;
264 } else if (value > 0x0020) { // 64
265 return 36;
266 } else if (value > 0x0010) { // 32
267 return 30;
268 } else if (value > 0x0008) { // 16
269 return 24;
270 } else if (value > 0x0007) { // 8
271 return 24;
272 } else if (value > 0x0003) { // 4
273 return 18;
274 } else if (value > 0x0001) { // 2
275 return 12;
276 } else { // 1
277 return 6;
278 }
279}
280
281M4OSA_Bool VideoEditorBGAudioProcessing::isThresholdBreached(
282 M4OSA_Int32* averageValue,
283 M4OSA_Int32 storeCount,
284 M4OSA_Int32 thresholdValue) {
285
James Dong3bd45592012-01-20 19:28:01 -0800286 ALOGV("isThresholdBreached");
287
Chih-Chung Chang99698662011-06-30 14:21:38 +0800288 int totalValue = 0;
289 for (int i = 0; i < storeCount; ++i) {
290 totalValue += averageValue[i];
291 }
292 return (totalValue / storeCount > thresholdValue);
293}
294
295}//namespace android