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