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