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