1 /*
2 * Copyright (C) 2022 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 #include <cstddef>
18 #include <cstdio>
19
20 #define LOG_TAG "BundleContext"
21 #include <android-base/logging.h>
22 #include <audio_utils/power.h>
23 #include <Utils.h>
24
25 #include "BundleContext.h"
26 #include "BundleTypes.h"
27 #include "math.h"
28
29 namespace aidl::android::hardware::audio::effect {
30
31 using ::aidl::android::media::audio::common::AudioChannelLayout;
32 using ::aidl::android::media::audio::common::AudioDeviceDescription;
33 using ::aidl::android::media::audio::common::AudioDeviceType;
34
init()35 RetCode BundleContext::init() {
36 std::lock_guard lg(mMutex);
37 // init with pre-defined preset NORMAL
38 for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
39 mBandGainMdB[i] = lvm::kSoftPresets[0 /* normal */][i] * 100;
40 }
41
42 // allocate lvm instance
43 LVM_ReturnStatus_en status;
44 LVM_InstParams_t params = {.BufferMode = LVM_UNMANAGED_BUFFERS,
45 .MaxBlockSize = lvm::MAX_CALL_SIZE,
46 .EQNB_NumBands = lvm::MAX_NUM_BANDS,
47 .PSA_Included = LVM_PSA_ON};
48 status = LVM_GetInstanceHandle(&mInstance, ¶ms);
49 GOTO_IF_LVM_ERROR(status, deinit, "LVM_GetInstanceHandleFailed");
50
51 // set control
52 LVM_ControlParams_t controlParams;
53 initControlParameter(controlParams);
54 status = LVM_SetControlParameters(mInstance, &controlParams);
55 GOTO_IF_LVM_ERROR(status, deinit, "LVM_SetControlParametersFailed");
56
57 /* Set the headroom parameters */
58 LVM_HeadroomParams_t headroomParams;
59 initHeadroomParameter(headroomParams);
60 status = LVM_SetHeadroomParams(mInstance, &headroomParams);
61 GOTO_IF_LVM_ERROR(status, deinit, "LVM_SetHeadroomParamsFailed");
62
63 return RetCode::SUCCESS;
64
65 deinit:
66 deInit();
67 return RetCode::ERROR_EFFECT_LIB_ERROR;
68 }
69
deInit()70 void BundleContext::deInit() {
71 std::lock_guard lg(mMutex);
72 if (mInstance) {
73 LVM_DelInstanceHandle(&mInstance);
74 mInstance = nullptr;
75 }
76 }
77
enable()78 RetCode BundleContext::enable() {
79 if (mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
80 // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due to
81 // their nature.
82 bool tempDisabled = false;
83 switch (mType) {
84 case lvm::BundleEffectType::EQUALIZER:
85 LOG(DEBUG) << __func__ << " enable bundle EQ";
86 if (mSamplesToExitCountEq <= 0) mNumberEffectsEnabled++;
87 mSamplesToExitCountEq = (mSamplesPerSecond * 0.1);
88 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
89 break;
90 case lvm::BundleEffectType::BASS_BOOST:
91 LOG(DEBUG) << __func__ << " enable bundle BB";
92 if (mSamplesToExitCountBb <= 0) mNumberEffectsEnabled++;
93 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
94 mSamplesToExitCountBb = (mSamplesPerSecond * 0.1);
95 tempDisabled = mBassTempDisabled;
96 break;
97 case lvm::BundleEffectType::VIRTUALIZER:
98 LOG(DEBUG) << __func__ << " enable bundle VR";
99 if (mSamplesToExitCountVirt <= 0) mNumberEffectsEnabled++;
100 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
101 mSamplesToExitCountVirt = (mSamplesPerSecond * 0.1);
102 tempDisabled = mVirtualizerTempDisabled;
103 break;
104 case lvm::BundleEffectType::VOLUME:
105 LOG(DEBUG) << __func__ << " enable bundle VOL";
106 if ((mEffectInDrain & (1 << int(lvm::BundleEffectType::VOLUME))) == 0)
107 mNumberEffectsEnabled++;
108 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
109 break;
110 }
111 mEnabled = true;
112 return (tempDisabled ? RetCode::SUCCESS : enableOperatingMode());
113 }
114
enableOperatingMode()115 RetCode BundleContext::enableOperatingMode() {
116 LVM_ControlParams_t params;
117 {
118 std::lock_guard lg(mMutex);
119 RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
120 RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
121 switch (mType) {
122 case lvm::BundleEffectType::EQUALIZER:
123 LOG(DEBUG) << __func__ << " enable bundle EQ";
124 params.EQNB_OperatingMode = LVM_EQNB_ON;
125 break;
126 case lvm::BundleEffectType::BASS_BOOST:
127 LOG(DEBUG) << __func__ << " enable bundle BB";
128 params.BE_OperatingMode = LVM_BE_ON;
129 break;
130 case lvm::BundleEffectType::VIRTUALIZER:
131 LOG(DEBUG) << __func__ << " enable bundle VR";
132 params.VirtualizerOperatingMode = LVM_MODE_ON;
133 break;
134 case lvm::BundleEffectType::VOLUME:
135 LOG(DEBUG) << __func__ << " enable bundle VOL";
136 break;
137 }
138 RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
139 RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
140 }
141 return limitLevel();
142 }
143
disable()144 RetCode BundleContext::disable() {
145 if (!mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
146 switch (mType) {
147 case lvm::BundleEffectType::EQUALIZER:
148 LOG(DEBUG) << __func__ << " disable bundle EQ";
149 mEffectInDrain |= 1 << int(lvm::BundleEffectType::EQUALIZER);
150 break;
151 case lvm::BundleEffectType::BASS_BOOST:
152 LOG(DEBUG) << __func__ << " disable bundle BB";
153 mEffectInDrain |= 1 << int(lvm::BundleEffectType::BASS_BOOST);
154 break;
155 case lvm::BundleEffectType::VIRTUALIZER:
156 LOG(DEBUG) << __func__ << " disable bundle VR";
157 mEffectInDrain |= 1 << int(lvm::BundleEffectType::VIRTUALIZER);
158 break;
159 case lvm::BundleEffectType::VOLUME:
160 LOG(DEBUG) << __func__ << " disable bundle VOL";
161 mEffectInDrain |= 1 << int(lvm::BundleEffectType::VOLUME);
162 break;
163 }
164 mEnabled = false;
165 return disableOperatingMode();
166 }
167
disableOperatingMode()168 RetCode BundleContext::disableOperatingMode() {
169 LVM_ControlParams_t params;
170 {
171 std::lock_guard lg(mMutex);
172 RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
173 RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
174 switch (mType) {
175 case lvm::BundleEffectType::EQUALIZER:
176 LOG(DEBUG) << __func__ << " disable bundle EQ";
177 params.EQNB_OperatingMode = LVM_EQNB_OFF;
178 break;
179 case lvm::BundleEffectType::BASS_BOOST:
180 LOG(DEBUG) << __func__ << " disable bundle BB";
181 params.BE_OperatingMode = LVM_BE_OFF;
182 break;
183 case lvm::BundleEffectType::VIRTUALIZER:
184 LOG(DEBUG) << __func__ << " disable bundle VR";
185 params.VirtualizerOperatingMode = LVM_MODE_OFF;
186 break;
187 case lvm::BundleEffectType::VOLUME:
188 LOG(DEBUG) << __func__ << " disable bundle VOL";
189 break;
190 }
191 RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
192 RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
193 }
194 mEnabled = false;
195 return limitLevel();
196 }
197
limitLevel()198 RetCode BundleContext::limitLevel() {
199 int gainCorrection = 0;
200 // Count the energy contribution per band for EQ and BassBoost only if they are active.
201 float energyContribution = 0;
202 float energyCross = 0;
203 float energyBassBoost = 0;
204 float crossCorrection = 0;
205 LVM_ControlParams_t params;
206 {
207 std::lock_guard lg(mMutex);
208 RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
209 RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
210
211 bool eqEnabled = params.EQNB_OperatingMode == LVM_EQNB_ON;
212 bool bbEnabled = params.BE_OperatingMode == LVM_BE_ON;
213 bool viEnabled = params.VirtualizerOperatingMode == LVM_MODE_ON;
214
215 if (eqEnabled) {
216 for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
217 float bandFactor = mBandGainMdB[i] / 1500.0;
218 float bandCoefficient = lvm::kBandEnergyCoefficient[i];
219 float bandEnergy = bandFactor * bandCoefficient * bandCoefficient;
220 if (bandEnergy > 0) energyContribution += bandEnergy;
221 }
222
223 // cross EQ coefficients
224 float bandFactorSum = 0;
225 for (int i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) {
226 float bandFactor1 = mBandGainMdB[i] / 1500.0;
227 float bandFactor2 = mBandGainMdB[i + 1] / 1500.0;
228
229 if (bandFactor1 > 0 && bandFactor2 > 0) {
230 float crossEnergy =
231 bandFactor1 * bandFactor2 * lvm::kBandEnergyCrossCoefficient[i];
232 bandFactorSum += bandFactor1 * bandFactor2;
233
234 if (crossEnergy > 0) energyCross += crossEnergy;
235 }
236 }
237 bandFactorSum -= 1.0;
238 if (bandFactorSum > 0) crossCorrection = bandFactorSum * 0.7;
239 }
240 // BassBoost contribution
241 if (bbEnabled) {
242 float boostFactor = mBassStrengthSaved / 1000.0;
243 float boostCoefficient = lvm::kBassBoostEnergyCoefficient;
244
245 energyContribution += boostFactor * boostCoefficient * boostCoefficient;
246
247 if (eqEnabled) {
248 for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
249 float bandFactor = mBandGainMdB[i] / 1500.0;
250 float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i];
251 float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient;
252 if (bandEnergy > 0) energyBassBoost += bandEnergy;
253 }
254 }
255 }
256 // Virtualizer contribution
257 if (viEnabled) {
258 energyContribution += lvm::kVirtualizerContribution * lvm::kVirtualizerContribution;
259 }
260
261 double totalEnergyEstimation =
262 sqrt(energyContribution + energyCross + energyBassBoost) - crossCorrection;
263 LOG(INFO) << " TOTAL energy estimation: " << totalEnergyEstimation << " dB";
264
265 // roundoff
266 int maxLevelRound = (int)(totalEnergyEstimation + 0.99);
267 if (maxLevelRound + mVolume > 0) {
268 gainCorrection = maxLevelRound + mVolume;
269 }
270
271 params.VC_EffectLevel = mVolume - gainCorrection;
272 if (params.VC_EffectLevel < -96) {
273 params.VC_EffectLevel = -96;
274 }
275 LOG(INFO) << "\tVol: " << mVolume << ", GainCorrection: " << gainCorrection
276 << ", Actual vol: " << params.VC_EffectLevel;
277
278 /* Activate the initial settings */
279 RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
280 RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
281
282 if (mFirstVolume) {
283 RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetVolumeNoSmoothing(mInstance, ¶ms),
284 RetCode::ERROR_EFFECT_LIB_ERROR, " setVolumeNoSmoothingFailed");
285 LOG(INFO) << "\tLVM_VOLUME: Disabling Smoothing for first volume change to remove "
286 "spikes/clicks";
287 mFirstVolume = false;
288 }
289 }
290
291 return RetCode::SUCCESS;
292 }
293
isDeviceSupportedBassBoost(const std::vector<aidl::android::media::audio::common::AudioDeviceDescription> & devices)294 bool BundleContext::isDeviceSupportedBassBoost(
295 const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
296 for (const auto& device : devices) {
297 if (device != AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER, ""} &&
298 device != AudioDeviceDescription{AudioDeviceType::OUT_CARKIT,
299 AudioDeviceDescription::CONNECTION_BT_SCO} &&
300 device != AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER,
301 AudioDeviceDescription::CONNECTION_BT_A2DP}) {
302 return false;
303 }
304 }
305 return true;
306 }
307
isDeviceSupportedVirtualizer(const std::vector<aidl::android::media::audio::common::AudioDeviceDescription> & devices)308 bool BundleContext::isDeviceSupportedVirtualizer(
309 const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
310 for (const auto& device : devices) {
311 if (device != AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
312 AudioDeviceDescription::CONNECTION_ANALOG} &&
313 device != AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
314 AudioDeviceDescription::CONNECTION_ANALOG} &&
315 device != AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
316 AudioDeviceDescription::CONNECTION_BT_A2DP} &&
317 device != AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
318 AudioDeviceDescription::CONNECTION_USB}) {
319 return false;
320 }
321 }
322 return true;
323 }
324
isConfigSupportedVirtualizer(size_t channelCount,const AudioDeviceDescription & device)325 bool BundleContext::isConfigSupportedVirtualizer(size_t channelCount,
326 const AudioDeviceDescription& device) {
327 return (channelCount >= 1 && channelCount <= FCC_2) && isDeviceSupportedVirtualizer({device});
328 }
329
setOutputDevice(const std::vector<aidl::android::media::audio::common::AudioDeviceDescription> & devices)330 RetCode BundleContext::setOutputDevice(
331 const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
332 mOutputDevice = devices;
333 switch (mType) {
334 case lvm::BundleEffectType::BASS_BOOST:
335 if (!isDeviceSupportedBassBoost(devices)) {
336 // If a device doesn't support bass boost, the effect must be temporarily disabled.
337 // The effect must still report its original state as this can only be changed by
338 // the start/stop commands.
339 if (mEnabled) {
340 disableOperatingMode();
341 }
342 mBassTempDisabled = true;
343 } else {
344 // If a device supports bass boost and the effect has been temporarily disabled
345 // previously then re-enable it
346 if (!mEnabled) {
347 enableOperatingMode();
348 }
349 mBassTempDisabled = false;
350 }
351 break;
352 case lvm::BundleEffectType::VIRTUALIZER:
353 if (!isDeviceSupportedVirtualizer(devices)) {
354 if (mEnabled) {
355 disableOperatingMode();
356 }
357 mVirtualizerTempDisabled = true;
358 } else {
359 if (!mEnabled) {
360 enableOperatingMode();
361 }
362 mVirtualizerTempDisabled = false;
363 }
364 break;
365 default:
366 break;
367 }
368 return RetCode::SUCCESS;
369 }
370
LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const371 LVM_INT16 BundleContext::LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const {
372 LVM_INT16 db_fix;
373 LVM_INT16 Shift;
374 LVM_INT16 SmallRemainder;
375 LVM_UINT32 Remainder = (LVM_UINT32)Lin_fix;
376
377 /* Count leading bits, 1 cycle in assembly*/
378 for (Shift = 0; Shift < 32; Shift++) {
379 if ((Remainder & 0x80000000U) != 0) {
380 break;
381 }
382 Remainder = Remainder << 1;
383 }
384
385 /*
386 * Based on the approximation equation (for Q11.4 format):
387 *
388 * dB = -96 * Shift + 16 * (8 * Remainder - 2 * Remainder^2)
389 */
390 db_fix = (LVM_INT16)(-96 * Shift); /* Six dB steps in Q11.4 format*/
391 SmallRemainder = (LVM_INT16)((Remainder & 0x7fffffff) >> 24);
392 db_fix = (LVM_INT16)(db_fix + SmallRemainder);
393 SmallRemainder = (LVM_INT16)(SmallRemainder * SmallRemainder);
394 db_fix = (LVM_INT16)(db_fix - (LVM_INT16)((LVM_UINT16)SmallRemainder >> 9));
395
396 /* Correct for small offset */
397 db_fix = (LVM_INT16)(db_fix - 5);
398
399 return db_fix;
400 }
401
402 /* static */
VolToDb(float vol)403 float BundleContext::VolToDb(float vol) {
404 float dB = audio_utils_power_from_amplitude(vol);
405 return std::max(dB, -96.f);
406 }
407
setVolumeStereo(const Parameter::VolumeStereo & volume)408 RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) {
409 LVM_ControlParams_t params;
410 LVM_ReturnStatus_en status = LVM_SUCCESS;
411
412 // Convert volume to dB
413 float leftdB = VolToDb(volume.left);
414 float rightdB = VolToDb(volume.right);
415
416 float maxdB = std::max(leftdB, rightdB);
417 float pandB = rightdB - leftdB;
418 setVolumeLevel(maxdB);
419 LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB;
420
421 {
422 std::lock_guard lg(mMutex);
423 RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
424 RetCode::ERROR_EFFECT_LIB_ERROR, "");
425 params.VC_Balance = pandB;
426
427 RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
428 RetCode::ERROR_EFFECT_LIB_ERROR, "");
429 }
430 mVolumeStereo = volume;
431 return RetCode::SUCCESS;
432 }
433
setEqualizerPreset(const std::size_t presetIdx)434 RetCode BundleContext::setEqualizerPreset(const std::size_t presetIdx) {
435 if (presetIdx < 0 || presetIdx >= lvm::MAX_NUM_PRESETS) {
436 return RetCode::ERROR_ILLEGAL_PARAMETER;
437 }
438
439 std::vector<Equalizer::BandLevel> bandLevels;
440 bandLevels.reserve(lvm::MAX_NUM_BANDS);
441 for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
442 bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i),
443 lvm::kSoftPresets[presetIdx][i] * 100});
444 }
445
446 RetCode ret = updateControlParameter(bandLevels);
447 if (RetCode::SUCCESS == ret) {
448 mCurPresetIdx = presetIdx;
449 LOG(INFO) << __func__ << " success with " << presetIdx;
450 } else {
451 LOG(ERROR) << __func__ << " failed to setPreset " << presetIdx;
452 }
453 return ret;
454 }
455
setEqualizerBandLevels(const std::vector<Equalizer::BandLevel> & bandLevels)456 RetCode BundleContext::setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels) {
457 RETURN_VALUE_IF(bandLevels.size() > lvm::MAX_NUM_BANDS || bandLevels.empty(),
458 RetCode::ERROR_ILLEGAL_PARAMETER, "sizeExceedMax");
459 RetCode ret = updateControlParameter(bandLevels);
460 if (RetCode::SUCCESS == ret) {
461 mCurPresetIdx = lvm::PRESET_CUSTOM;
462 LOG(INFO) << __func__ << " succeed with " << ::android::internal::ToString(bandLevels);
463 } else {
464 LOG(ERROR) << __func__ << " failed with " << ::android::internal::ToString(bandLevels);
465 }
466 return ret;
467 }
468
getEqualizerBandLevels() const469 std::vector<Equalizer::BandLevel> BundleContext::getEqualizerBandLevels() const {
470 std::vector<Equalizer::BandLevel> bandLevels;
471 bandLevels.reserve(lvm::MAX_NUM_BANDS);
472 for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
473 bandLevels.emplace_back(
474 Equalizer::BandLevel{static_cast<int32_t>(i), mBandGainMdB[i]});
475 }
476 return bandLevels;
477 }
478
getEqualizerCenterFreqs()479 std::vector<int32_t> BundleContext::getEqualizerCenterFreqs() {
480 std::vector<int32_t> freqs;
481
482 LVM_ControlParams_t params;
483 {
484 std::lock_guard lg(mMutex);
485 /* Get the current settings */
486 RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms), freqs,
487 " getControlParamFailed");
488 for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
489 freqs.push_back((int32_t)params.pEQNB_BandDefinition[i].Frequency * 1000);
490 }
491 }
492
493 return freqs;
494 }
495
isBandLevelIndexInRange(const std::vector<Equalizer::BandLevel> & bandLevels) const496 bool BundleContext::isBandLevelIndexInRange(
497 const std::vector<Equalizer::BandLevel>& bandLevels) const {
498 const auto [min, max] =
499 std::minmax_element(bandLevels.begin(), bandLevels.end(),
500 [](const auto& a, const auto& b) { return a.index < b.index; });
501 return min->index >= 0 && max->index < lvm::MAX_NUM_BANDS;
502 }
503
updateControlParameter(const std::vector<Equalizer::BandLevel> & bandLevels)504 RetCode BundleContext::updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels) {
505 RETURN_VALUE_IF(!isBandLevelIndexInRange(bandLevels), RetCode::ERROR_ILLEGAL_PARAMETER,
506 "indexOutOfRange");
507
508 std::array<int, lvm::MAX_NUM_BANDS> tempLevel(mBandGainMdB);
509 for (const auto& it : bandLevels) {
510 tempLevel[it.index] = it.levelMb;
511 }
512
513 LVM_ControlParams_t params;
514 {
515 std::lock_guard lg(mMutex);
516 RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
517 RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
518
519 for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
520 params.pEQNB_BandDefinition[i].Frequency = lvm::kPresetsFrequencies[i];
521 params.pEQNB_BandDefinition[i].QFactor = lvm::kPresetsQFactors[i];
522 params.pEQNB_BandDefinition[i].Gain =
523 tempLevel[i] > 0 ? (tempLevel[i] + 50) / 100 : (tempLevel[i] - 50) / 100;
524 }
525
526 RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
527 RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
528 }
529 mBandGainMdB = tempLevel;
530 LOG(DEBUG) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGainMdB)
531 << "mdB";
532
533 return RetCode::SUCCESS;
534 }
535
setBassBoostStrength(int strength)536 RetCode BundleContext::setBassBoostStrength(int strength) {
537 // Update Control Parameter
538 LVM_ControlParams_t params;
539 {
540 std::lock_guard lg(mMutex);
541 RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
542 RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
543
544 params.BE_EffectLevel = (LVM_INT16)((15 * strength) / 1000);
545 params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
546
547 RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
548 RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
549 }
550 mBassStrengthSaved = strength;
551 LOG(INFO) << __func__ << " success with strength " << strength;
552 return limitLevel();
553 }
554
setVolumeLevel(float level)555 RetCode BundleContext::setVolumeLevel(float level) {
556 if (mMuteEnabled) {
557 mLevelSaved = level;
558 } else {
559 mVolume = level;
560 }
561 LOG(INFO) << __func__ << " success with level " << level;
562 return limitLevel();
563 }
564
getVolumeLevel() const565 float BundleContext::getVolumeLevel() const {
566 return (mMuteEnabled ? mLevelSaved : mVolume);
567 }
568
setVolumeMute(bool mute)569 RetCode BundleContext::setVolumeMute(bool mute) {
570 mMuteEnabled = mute;
571 if (mMuteEnabled) {
572 mLevelSaved = mVolume;
573 mVolume = -96;
574 } else {
575 mVolume = mLevelSaved;
576 }
577 return limitLevel();
578 }
579
setVirtualizerStrength(int strength)580 RetCode BundleContext::setVirtualizerStrength(int strength) {
581 // Update Control Parameter
582 LVM_ControlParams_t params;
583 {
584 std::lock_guard lg(mMutex);
585 RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, ¶ms),
586 RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
587
588 params.CS_EffectLevel = ((strength * 32767) / 1000);
589
590 RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms),
591 RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
592 }
593
594 mVirtStrengthSaved = strength;
595 LOG(INFO) << __func__ << " success with strength " << strength;
596 return limitLevel();
597 }
598
599
setForcedDevice(const::aidl::android::media::audio::common::AudioDeviceDescription & device)600 RetCode BundleContext::setForcedDevice(
601 const ::aidl::android::media::audio::common::AudioDeviceDescription& device) {
602 RETURN_VALUE_IF(true != isDeviceSupportedVirtualizer({device}), RetCode::ERROR_EFFECT_LIB_ERROR,
603 " deviceNotSupportVirtualizer");
604 mForceDevice = device;
605 return RetCode::SUCCESS;
606 }
607
initControlParameter(LVM_ControlParams_t & params) const608 void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
609 /* General parameters */
610 params.OperatingMode = LVM_MODE_ON;
611 params.SampleRate = LVM_FS_44100;
612 params.SourceFormat = LVM_STEREO;
613 params.SpeakerType = LVM_HEADPHONES;
614
615 /* Concert Sound parameters */
616 params.VirtualizerOperatingMode = LVM_MODE_OFF;
617 params.VirtualizerType = LVM_CONCERTSOUND;
618 params.VirtualizerReverbLevel = 100;
619 params.CS_EffectLevel = LVM_CS_EFFECT_NONE;
620
621 params.EQNB_OperatingMode = LVM_EQNB_OFF;
622 params.EQNB_NBands = lvm::MAX_NUM_BANDS;
623 params.pEQNB_BandDefinition = getDefaultEqualizerBandDefs();
624
625 /* Volume Control parameters */
626 params.VC_EffectLevel = 0;
627 params.VC_Balance = 0;
628
629 /* Treble Enhancement parameters */
630 params.TE_OperatingMode = LVM_TE_OFF;
631 params.TE_EffectLevel = 0;
632
633 /* PSA Control parameters */
634 params.PSA_Enable = LVM_PSA_OFF;
635 params.PSA_PeakDecayRate = (LVM_PSA_DecaySpeed_en)0;
636
637 /* Bass Enhancement parameters */
638 params.BE_OperatingMode = LVM_BE_OFF;
639 params.BE_EffectLevel = 0;
640 params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
641 params.BE_HPF = LVM_BE_HPF_ON;
642
643 /* PSA Control parameters */
644 params.PSA_Enable = LVM_PSA_OFF;
645 params.PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
646
647 /* TE Control parameters */
648 params.TE_OperatingMode = LVM_TE_OFF;
649 params.TE_EffectLevel = 0;
650
651 params.NrChannels = audio_channel_count_from_out_mask(AUDIO_CHANNEL_OUT_STEREO);
652 params.ChMask = AUDIO_CHANNEL_OUT_STEREO;
653 params.SourceFormat = LVM_STEREO;
654 }
655
initHeadroomParameter(LVM_HeadroomParams_t & params) const656 void BundleContext::initHeadroomParameter(LVM_HeadroomParams_t& params) const {
657 params.pHeadroomDefinition = getDefaultEqualizerHeadroomBanDefs();
658 params.NHeadroomBands = 2;
659 params.Headroom_OperatingMode = LVM_HEADROOM_OFF;
660 }
661
getDefaultEqualizerBandDefs()662 LVM_EQNB_BandDef_t *BundleContext::getDefaultEqualizerBandDefs() {
663 static LVM_EQNB_BandDef_t* BandDefs = []() {
664 static LVM_EQNB_BandDef_t tempDefs[lvm::MAX_NUM_BANDS];
665 /* N-Band Equaliser parameters */
666 for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
667 tempDefs[i].Frequency = lvm::kPresetsFrequencies[i];
668 tempDefs[i].QFactor = lvm::kPresetsQFactors[i];
669 tempDefs[i].Gain = lvm::kSoftPresets[0/* normal */][i];
670 }
671 return tempDefs;
672 }();
673
674 return BandDefs;
675 }
676
getDefaultEqualizerHeadroomBanDefs()677 LVM_HeadroomBandDef_t *BundleContext::getDefaultEqualizerHeadroomBanDefs() {
678 static LVM_HeadroomBandDef_t HeadroomBandDef[LVM_HEADROOM_MAX_NBANDS] = {
679 {
680 .Limit_Low = 20,
681 .Limit_High = 4999,
682 .Headroom_Offset = 0,
683 },
684 {
685 .Limit_Low = 5000,
686 .Limit_High = 24000,
687 .Headroom_Offset = 0,
688 },
689 };
690 return HeadroomBandDef;
691 }
692
getSpeakerAngles(const Virtualizer::SpeakerAnglesPayload payload)693 std::vector<Virtualizer::ChannelAngle> BundleContext::getSpeakerAngles(
694 const Virtualizer::SpeakerAnglesPayload payload) {
695 std::vector<Virtualizer::ChannelAngle> angles;
696 auto chCount = ::aidl::android::hardware::audio::common::getChannelCount(payload.layout);
697 RETURN_VALUE_IF(!isConfigSupportedVirtualizer(chCount, payload.device), angles,
698 "payloadNotSupported");
699
700 if (chCount == 1) {
701 angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
702 .azimuthDegree = 0,
703 .elevationDegree = 0}};
704 } else {
705 angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
706 .azimuthDegree = -90,
707 .elevationDegree = 0},
708 {.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_RIGHT,
709 .azimuthDegree = 90,
710 .elevationDegree = 0}};
711 }
712 return angles;
713 }
714
lvmProcess(float * in,float * out,int samples)715 IEffect::Status BundleContext::lvmProcess(float* in, float* out, int samples) {
716 IEffect::Status status = {EX_NULL_POINTER, 0, 0};
717 RETURN_VALUE_IF(!in, status, "nullInput");
718 RETURN_VALUE_IF(!out, status, "nullOutput");
719 status = {EX_ILLEGAL_STATE, 0, 0};
720 int64_t inputFrameCount = getCommon().input.frameCount;
721 int64_t outputFrameCount = getCommon().output.frameCount;
722 RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
723 int isDataAvailable = true;
724
725 auto frameSize = getInputFrameSize();
726 RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
727
728 LOG(DEBUG) << __func__ << " start processing";
729 if ((mEffectProcessCalled & 1 << int(mType)) != 0) {
730 const int undrainedEffects = mEffectInDrain & ~mEffectProcessCalled;
731 if ((undrainedEffects & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
732 LOG(DEBUG) << "Draining EQUALIZER";
733 mSamplesToExitCountEq = 0;
734 --mNumberEffectsEnabled;
735 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
736 }
737 if ((undrainedEffects & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
738 LOG(DEBUG) << "Draining BASS_BOOST";
739 mSamplesToExitCountBb = 0;
740 --mNumberEffectsEnabled;
741 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
742 }
743 if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
744 LOG(DEBUG) << "Draining VIRTUALIZER";
745 mSamplesToExitCountVirt = 0;
746 --mNumberEffectsEnabled;
747 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
748 }
749 if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
750 LOG(DEBUG) << "Draining VOLUME";
751 --mNumberEffectsEnabled;
752 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
753 }
754 }
755 mEffectProcessCalled |= 1 << int(mType);
756 if (!mEnabled) {
757 switch (mType) {
758 case lvm::BundleEffectType::EQUALIZER:
759 if (mSamplesToExitCountEq > 0) {
760 mSamplesToExitCountEq -= samples;
761 }
762 if (mSamplesToExitCountEq <= 0) {
763 isDataAvailable = false;
764 if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
765 mNumberEffectsEnabled--;
766 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
767 }
768 LOG(DEBUG) << "Effect_process() this is the last frame for EQUALIZER";
769 }
770 break;
771 case lvm::BundleEffectType::BASS_BOOST:
772 if (mSamplesToExitCountBb > 0) {
773 mSamplesToExitCountBb -= samples;
774 }
775 if (mSamplesToExitCountBb <= 0) {
776 isDataAvailable = false;
777 if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
778 mNumberEffectsEnabled--;
779 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
780 }
781 LOG(DEBUG) << "Effect_process() this is the last frame for BASS_BOOST";
782 }
783 break;
784 case lvm::BundleEffectType::VIRTUALIZER:
785 if (mSamplesToExitCountVirt > 0) {
786 mSamplesToExitCountVirt -= samples;
787 }
788 if (mSamplesToExitCountVirt <= 0) {
789 isDataAvailable = false;
790 if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
791 mNumberEffectsEnabled--;
792 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
793 }
794 LOG(DEBUG) << "Effect_process() this is the last frame for VIRTUALIZER";
795 }
796 break;
797 case lvm::BundleEffectType::VOLUME:
798 isDataAvailable = false;
799 if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
800 mNumberEffectsEnabled--;
801 mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
802 }
803 LOG(DEBUG) << "Effect_process() LVM_VOLUME Effect is not enabled";
804 break;
805 }
806 }
807 if (isDataAvailable) {
808 mNumberEffectsCalled++;
809 }
810 bool accumulate = false;
811 if (mNumberEffectsCalled >= mNumberEffectsEnabled) {
812 // We expect the # effects called to be equal to # effects enabled in sequence (including
813 // draining effects). Warn if this is not the case due to inconsistent calls.
814 ALOGW_IF(mNumberEffectsCalled > mNumberEffectsEnabled,
815 "%s Number of effects called %d is greater than number of effects enabled %d",
816 __func__, mNumberEffectsCalled, mNumberEffectsEnabled);
817 mEffectProcessCalled = 0; // reset our consistency check.
818 if (!isDataAvailable) {
819 LOG(DEBUG) << "Effect_process() processing last frame";
820 }
821 mNumberEffectsCalled = 0;
822 LVM_UINT16 frames = samples * sizeof(float) / frameSize;
823 float* outTmp = (accumulate ? getWorkBuffer() : out);
824 /* Process the samples */
825 LVM_ReturnStatus_en lvmStatus;
826 {
827 std::lock_guard lg(mMutex);
828 lvmStatus = LVM_Process(mInstance, in, outTmp, frames, 0);
829 if (lvmStatus != LVM_SUCCESS) {
830 LOG(ERROR) << __func__ << lvmStatus;
831 return {EX_UNSUPPORTED_OPERATION, 0, 0};
832 }
833 if (accumulate) {
834 for (int i = 0; i < samples; i++) {
835 out[i] += outTmp[i];
836 }
837 }
838 }
839 } else {
840 for (int i = 0; i < samples; i++) {
841 if (accumulate) {
842 out[i] += in[i];
843 } else {
844 out[i] = in[i];
845 }
846 }
847 }
848 LOG(DEBUG) << __func__ << " done processing";
849 return {STATUS_OK, samples, samples};
850 }
851
852 } // namespace aidl::android::hardware::audio::effect
853