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