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 #define LOG_TAG "LoudnessEnhancerContext"
18
19 #include <Utils.h>
20
21 #include "LoudnessEnhancerContext.h"
22
23 namespace aidl::android::hardware::audio::effect {
24
LoudnessEnhancerContext(int statusDepth,const Parameter::Common & common)25 LoudnessEnhancerContext::LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common)
26 : EffectContext(statusDepth, common) {
27 init_params();
28 }
29
enable()30 RetCode LoudnessEnhancerContext::enable() {
31 if (mState != LOUDNESS_ENHANCER_STATE_INITIALIZED) {
32 return RetCode::ERROR_EFFECT_LIB_ERROR;
33 }
34 mState = LOUDNESS_ENHANCER_STATE_ACTIVE;
35 return RetCode::SUCCESS;
36 }
37
disable()38 RetCode LoudnessEnhancerContext::disable() {
39 if (mState != LOUDNESS_ENHANCER_STATE_ACTIVE) {
40 return RetCode::ERROR_EFFECT_LIB_ERROR;
41 }
42 mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
43 return RetCode::SUCCESS;
44 }
45
reset()46 void LoudnessEnhancerContext::reset() {
47 float targetAmp = pow(10, mGain / 2000.0f); // mB to linear amplification
48 if (mCompressor != nullptr) {
49 // Get samplingRate from input
50 mCompressor->Initialize(targetAmp, mCommon.input.base.sampleRate);
51 }
52 }
53
setLeGain(int gainMb)54 RetCode LoudnessEnhancerContext::setLeGain(int gainMb) {
55 mGain = gainMb;
56 reset(); // apply parameter update
57 return RetCode::SUCCESS;
58 }
59
process(float * in,float * out,int samples)60 IEffect::Status LoudnessEnhancerContext::process(float* in, float* out, int samples) {
61 IEffect::Status status = {EX_NULL_POINTER, 0, 0};
62 RETURN_VALUE_IF(!in, status, "nullInput");
63 RETURN_VALUE_IF(!out, status, "nullOutput");
64 status = {EX_ILLEGAL_STATE, 0, 0};
65 RETURN_VALUE_IF(getInputFrameSize() != getOutputFrameSize(), status, "FrameSizeMismatch");
66 auto frameSize = getInputFrameSize();
67 RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
68
69 status = {STATUS_INVALID_OPERATION, 0, 0};
70 RETURN_VALUE_IF(mState != LOUDNESS_ENHANCER_STATE_ACTIVE, status, "stateNotActive");
71
72 // PcmType is always expected to be Float 32 bit.
73 constexpr float scale = 1 << 15; // power of 2 is lossless conversion to int16_t range
74 constexpr float inverseScale = 1.f / scale;
75 const float inputAmp = pow(10, mGain / 2000.0f) * scale;
76 float leftSample, rightSample;
77
78 if (mCompressor != nullptr) {
79 for (int inIdx = 0; inIdx < samples; inIdx += 2) {
80 // makeup gain is applied on the input of the compressor
81 leftSample = inputAmp * in[inIdx];
82 rightSample = inputAmp * in[inIdx + 1];
83 mCompressor->Compress(&leftSample, &rightSample);
84 in[inIdx] = leftSample * inverseScale;
85 in[inIdx + 1] = rightSample * inverseScale;
86 }
87 } else {
88 for (int inIdx = 0; inIdx < samples; inIdx += 2) {
89 leftSample = inputAmp * in[inIdx];
90 rightSample = inputAmp * in[inIdx + 1];
91 in[inIdx] = leftSample * inverseScale;
92 in[inIdx + 1] = rightSample * inverseScale;
93 }
94 }
95 bool accumulate = false;
96 if (in != out) {
97 for (int i = 0; i < samples; i++) {
98 if (accumulate) {
99 out[i] += in[i];
100 } else {
101 out[i] = in[i];
102 }
103 }
104 }
105 return {STATUS_OK, samples, samples};
106 }
107
init_params()108 void LoudnessEnhancerContext::init_params() {
109 int channelCount = ::aidl::android::hardware::audio::common::getChannelCount(
110 mCommon.input.base.channelMask);
111 LOG_ALWAYS_FATAL_IF(channelCount != 2, "channel count %d not supported", channelCount);
112
113 mGain = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
114 float targetAmp = pow(10, mGain / 2000.0f); // mB to linear amplification
115 LOG(VERBOSE) << __func__ << "Target gain = " << mGain << "mB <=> factor = " << targetAmp;
116
117 mCompressor = std::make_unique<le_fx::AdaptiveDynamicRangeCompression>();
118 mCompressor->Initialize(targetAmp, mCommon.input.base.sampleRate);
119 mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
120 }
121
122 } // namespace aidl::android::hardware::audio::effect
123