1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef LOG_TAG
17 #define LOG_TAG "AudioEnhanceChain"
18 #endif
19 
20 #include "audio_enhance_chain.h"
21 
22 #include <chrono>
23 
24 #include "securec.h"
25 #include "audio_effect_log.h"
26 #include "audio_errors.h"
27 
28 namespace OHOS {
29 namespace AudioStandard {
30 constexpr uint32_t MAX_BATCH_LEN = 20; // Number of input channel, ec(8) + onBoardMic(4) + headsetMic(2) + buffer(6)
31 constexpr uint32_t MAX_BYTE_LEN_PER_FRAME = 19200;
32 constexpr uint32_t MAX_BIT_DEPTH = 8;
33 
GetOneFrameInputData(EnhanceBufferAttr * enhanceBufferAttr,std::vector<uint8_t> & input,uint32_t inputLen)34 static int32_t GetOneFrameInputData(EnhanceBufferAttr *enhanceBufferAttr, std::vector<uint8_t> &input,
35     uint32_t inputLen)
36 {
37     CHECK_AND_RETURN_RET_LOG(enhanceBufferAttr->bitDepth != 0 &&
38         enhanceBufferAttr->bitDepth < MAX_BIT_DEPTH, ERROR, "bitDepth is invalid");
39     CHECK_AND_RETURN_RET_LOG(enhanceBufferAttr->byteLenPerFrame != 0 &&
40         enhanceBufferAttr->byteLenPerFrame < MAX_BYTE_LEN_PER_FRAME, ERROR, "byteLenPerFrame is out of range");
41     CHECK_AND_RETURN_RET_LOG(enhanceBufferAttr->batchLen != 0 &&
42         enhanceBufferAttr->batchLen < MAX_BATCH_LEN, ERROR, "batchLen is out of range");
43 
44     input.reserve(inputLen);
45     std::vector<std::vector<uint8_t>> cache;
46     if (enhanceBufferAttr->batchLen > 0) {
47         cache.resize(enhanceBufferAttr->batchLen);
48     }
49     for (auto &it : cache) {
50         it.resize(enhanceBufferAttr->byteLenPerFrame);
51     }
52 
53     int32_t ret = 0;
54     // ref channel
55     for (uint32_t j = 0; j < enhanceBufferAttr->refNum; ++j) {
56         ret = memset_s(cache[j].data(), cache[j].size(), 0, cache[j].size());
57         CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "memset error in ref channel memcpy");
58     }
59     uint32_t index = 0;
60     for (uint32_t i = 0; i < enhanceBufferAttr->byteLenPerFrame / enhanceBufferAttr->bitDepth; ++i) {
61         // mic channel
62         for (uint32_t j = enhanceBufferAttr->refNum; j < enhanceBufferAttr->batchLen; ++j) {
63             ret = memcpy_s(&cache[j][i * enhanceBufferAttr->bitDepth], enhanceBufferAttr->bitDepth,
64                 enhanceBufferAttr->input + index, enhanceBufferAttr->bitDepth);
65             CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "memcpy error in mic channel memcpy");
66             index += enhanceBufferAttr->bitDepth;
67         }
68     }
69     for (uint32_t i = 0; i < enhanceBufferAttr->batchLen; ++i) {
70         input.insert(input.end(), cache[i].begin(), cache[i].end());
71     }
72     return SUCCESS;
73 }
74 
AudioEnhanceChain(const std::string & scene)75 AudioEnhanceChain::AudioEnhanceChain(const std::string &scene)
76 {
77     setConfigFlag_ = false;
78     sceneType_ = scene;
79     enhanceMode_ = "EFFECT_DEFAULT";
80 }
81 
~AudioEnhanceChain()82 AudioEnhanceChain::~AudioEnhanceChain()
83 {
84     ReleaseEnhanceChain();
85 }
86 
SetEnhanceMode(const std::string & mode)87 void AudioEnhanceChain::SetEnhanceMode(const std::string &mode)
88 {
89     enhanceMode_ = mode;
90 }
91 
ReleaseEnhanceChain()92 void AudioEnhanceChain::ReleaseEnhanceChain()
93 {
94     for (uint32_t i = 0; i < standByEnhanceHandles_.size() && i < enhanceLibHandles_.size(); i++) {
95         if (!enhanceLibHandles_[i]) {
96             continue;
97         }
98         if (!standByEnhanceHandles_[i]) {
99             continue;
100         }
101         if (!enhanceLibHandles_[i]->releaseEffect) {
102             continue;
103         }
104         enhanceLibHandles_[i]->releaseEffect(standByEnhanceHandles_[i]);
105     }
106     standByEnhanceHandles_.clear();
107     enhanceLibHandles_.clear();
108 }
109 
AddEnhanceHandle(AudioEffectHandle handle,AudioEffectLibrary * libHandle)110 void AudioEnhanceChain::AddEnhanceHandle(AudioEffectHandle handle, AudioEffectLibrary *libHandle)
111 {
112     std::lock_guard<std::mutex> lock(chainMutex_);
113     int32_t ret = 0;
114     AudioEffectTransInfo cmdInfo = {};
115     AudioEffectTransInfo replyInfo = {};
116 
117     ret = (*handle)->command(handle, EFFECT_CMD_INIT, &cmdInfo, &replyInfo);
118     CHECK_AND_RETURN_LOG(ret == 0, "[%{public}s] with [%{public}s], either one of libs EFFECT_CMD_INIT fail",
119         sceneType_.c_str(), enhanceMode_.c_str());
120 
121     standByEnhanceHandles_.emplace_back(handle);
122     enhanceLibHandles_.emplace_back(libHandle);
123 }
124 
SetHandleConfig(AudioEffectHandle handle,DataDescription desc)125 void AudioEnhanceChain::SetHandleConfig(AudioEffectHandle handle, DataDescription desc)
126 {
127     int32_t ret = 0;
128     AudioEffectTransInfo cmdInfo = {};
129     AudioEffectTransInfo replyInfo = {};
130     cmdInfo.data = static_cast<void *>(&desc);
131     cmdInfo.size = sizeof(desc);
132 
133     ret = (*handle)->command(handle, EFFECT_CMD_SET_CONFIG, &cmdInfo, &replyInfo);
134     CHECK_AND_RETURN_LOG(ret == 0, "[%{publc}s] with mode [%{public}s], either one of libs \
135         EFFECT_CMD_SET_CONFIG fai", sceneType_.c_str(), enhanceMode_.c_str());
136     setConfigFlag_ = true;
137 }
138 
ApplyEnhanceChain(EnhanceBufferAttr * enhanceBufferAttr)139 int32_t AudioEnhanceChain::ApplyEnhanceChain(EnhanceBufferAttr *enhanceBufferAttr)
140 {
141     CHECK_AND_RETURN_RET_LOG(enhanceBufferAttr != nullptr, ERROR, "enhance buffer is null");
142 
143     enhanceBufferAttr->refNum = REF_CHANNEL_NUM_MAP.find(sceneType_)->second;
144     enhanceBufferAttr->batchLen = enhanceBufferAttr->refNum + enhanceBufferAttr->micNum;
145     uint32_t inputLen = enhanceBufferAttr->byteLenPerFrame * enhanceBufferAttr->batchLen;
146     uint32_t outputLen = enhanceBufferAttr->byteLenPerFrame * enhanceBufferAttr->outNum;
147     std::vector<uint8_t> input;
148     std::vector<uint8_t> output;
149     output.resize(outputLen);
150 
151     if (IsEmptyEnhanceHandles()) {
152         AUDIO_ERR_LOG("audioEnhanceChain->standByEnhanceHandles is empty");
153         CHECK_AND_RETURN_RET_LOG(memcpy_s(enhanceBufferAttr->output, outputLen, enhanceBufferAttr->input,
154             outputLen) == 0, ERROR, "memcpy error in IsEmptyEnhanceHandles");
155         return ERROR;
156     }
157     if (GetOneFrameInputData(enhanceBufferAttr, input, inputLen) != SUCCESS) {
158         AUDIO_ERR_LOG("GetOneFrameInputData failed");
159         CHECK_AND_RETURN_RET_LOG(memcpy_s(enhanceBufferAttr->output, outputLen, enhanceBufferAttr->input,
160             outputLen) == 0, ERROR, "memcpy error in GetOneFrameInputData");
161         return ERROR;
162     }
163     AudioBuffer audioBufIn_ = {};
164     AudioBuffer audioBufOut_ = {};
165     audioBufIn_.frameLength = inputLen;
166     audioBufOut_.frameLength = outputLen;
167     audioBufIn_.raw = static_cast<void *>(input.data());
168     audioBufOut_.raw = static_cast<void *>(output.data());
169 
170     {
171         std::lock_guard<std::mutex> lock(chainMutex_);
172         for (AudioEffectHandle handle : standByEnhanceHandles_) {
173             int32_t ret = 0;
174             if (!setConfigFlag_) {
175                 DataDescription desc = DataDescription(enhanceBufferAttr->frameLength, enhanceBufferAttr->sampleRate,
176                     enhanceBufferAttr->dataFormat, enhanceBufferAttr->micNum, enhanceBufferAttr->refNum,
177                     enhanceBufferAttr->outNum);
178                 SetHandleConfig(handle, desc);
179             }
180             ret = (*handle)->process(handle, &audioBufIn_, &audioBufOut_);
181             CHECK_AND_CONTINUE_LOG(ret == 0, "[%{publc}s] with mode [%{public}s], either one of libs process fail",
182                 sceneType_.c_str(), enhanceMode_.c_str());
183         }
184         CHECK_AND_RETURN_RET_LOG(memcpy_s(enhanceBufferAttr->output, outputLen, audioBufOut_.raw, outputLen) == 0,
185             ERROR, "memcpy error in audioBufOut_ to enhanceBufferAttr->output");
186         return SUCCESS;
187     }
188 }
189 
IsEmptyEnhanceHandles()190 bool AudioEnhanceChain::IsEmptyEnhanceHandles()
191 {
192     std::lock_guard<std::mutex> lock(chainMutex_);
193     return standByEnhanceHandles_.size() == 0;
194 }
195 
196 } // namespace AudioStandard
197 } // namespace OHOS