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 #undef LOG_TAG
17 #define LOG_TAG "AudioEnhanceChain"
18
19 #include "audio_enhance_chain.h"
20
21 #include <chrono>
22
23 #include "securec.h"
24 #include "audio_effect_log.h"
25 #include "audio_errors.h"
26 #include "audio_utils.h"
27 #include "volume_tools.h"
28
29 namespace OHOS {
30 namespace AudioStandard {
31 namespace {
32 const uint32_t BITLENGTH = 8;
33 const uint32_t MILLISECOND = 1000;
34 const uint32_t DEFAULT_FRAMELENGTH = 20;
35 const uint32_t DEFAULT_SAMPLE_RATE = 48000;
36 const uint32_t DEFAULT_FORMAT = 2;
37 const uint32_t DEFAULT_MICNUM = 2;
38 const uint32_t DEFAULT_ECOFF_CH = 0;
39 const uint32_t DEFAULT_MICREFOFF_CH = 0;
40 const uint32_t DEFAULT_ECON_CH = 2;
41 const uint32_t DEFAULT_MICREFON_CH = 4;
42 const uint32_t BYTE_SIZE_SAMPLE_U8 = 1;
43 const uint32_t BYTE_SIZE_SAMPLE_S16 = 2;
44 const uint32_t BYTE_SIZE_SAMPLE_S24 = 3;
45 const uint32_t BYTE_SIZE_SAMPLE_S32 = 4;
46 const uint32_t DEFAULT_DEVICE_TYPE_CH = 4;
47 const std::string DEFAULT_DEVICE_TYPE = "DEVICE_TYPE_MIC";
48
49 const std::vector<std::string> NEED_EC_SCENE = {
50 "SCENE_VOIP_UP",
51 "SCENE_PRE_ENHANCE",
52 "SCENE_RECOGNITION",
53 };
54
55 const std::vector<std::string> NEED_MICREF_SCENE = {
56 "SCENE_VOIP_UP",
57 "SCENE_RECORD",
58 };
59
60 const std::map<uint32_t, AudioSampleFormat> FORMAT_CONVERT_MAP = {
61 {BYTE_SIZE_SAMPLE_U8, SAMPLE_U8},
62 {BYTE_SIZE_SAMPLE_S16, SAMPLE_S16LE},
63 {BYTE_SIZE_SAMPLE_S24, SAMPLE_S24LE},
64 {BYTE_SIZE_SAMPLE_S32, SAMPLE_S32LE},
65 };
66
ConvertFormat(uint32_t format)67 AudioSampleFormat ConvertFormat(uint32_t format)
68 {
69 auto item = FORMAT_CONVERT_MAP.find(format);
70 if (item != FORMAT_CONVERT_MAP.end()) {
71 return item->second;
72 }
73 return INVALID_WIDTH;
74 }
75 } // namespace
76
AudioEnhanceChain(uint64_t chainId,const std::string & scene,ScenePriority scenePriority,const AudioEnhanceParamAdapter & algoParam,const AudioEnhanceDeviceAttr & deviceAttr)77 AudioEnhanceChain::AudioEnhanceChain(uint64_t chainId, const std::string &scene, ScenePriority scenePriority,
78 const AudioEnhanceParamAdapter &algoParam, const AudioEnhanceDeviceAttr &deviceAttr)
79 : chainId_(chainId), sceneType_(scene), scenePriority_(scenePriority), algoParam_(algoParam)
80 {
81 deviceAttr_ = deviceAttr;
82 if (deviceAttr_.micChannels == 1) {
83 deviceAttr_.micChannels = DEFAULT_MICNUM;
84 }
85
86 InitAudioEnhanceChain();
87 }
88
InitAudioEnhanceChain()89 void AudioEnhanceChain::InitAudioEnhanceChain()
90 {
91 if ((algoParam_.preDevice == DEFAULT_DEVICE_TYPE) && (deviceAttr_.micChannels != DEFAULT_DEVICE_TYPE_CH)) {
92 AUDIO_WARNING_LOG("mic channel[%{public}d] is set to 4", deviceAttr_.micChannels);
93 deviceAttr_.micChannels = DEFAULT_DEVICE_TYPE_CH;
94 }
95
96 algoSupportedConfig_ = {DEFAULT_FRAMELENGTH, DEFAULT_SAMPLE_RATE, DEFAULT_FORMAT * BITLENGTH,
97 deviceAttr_.micChannels, DEFAULT_ECOFF_CH, DEFAULT_MICREFOFF_CH, deviceAttr_.micChannels};
98
99 uint32_t byteLenPerFrame = DEFAULT_FRAMELENGTH * (DEFAULT_SAMPLE_RATE / MILLISECOND) * DEFAULT_FORMAT;
100 algoAttr_ = {DEFAULT_FORMAT, deviceAttr_.micChannels, byteLenPerFrame};
101
102 if (count(NEED_EC_SCENE.begin(), NEED_EC_SCENE.end(), sceneType_)) {
103 needEcFlag_ = true;
104 algoSupportedConfig_.ecNum = DEFAULT_ECON_CH;
105 algoAttr_.batchLen = deviceAttr_.micChannels + algoSupportedConfig_.ecNum;
106 enhanceBuf_.ecBuffer.resize(deviceAttr_.ecChannels * byteLenPerFrame);
107 }
108
109 if (count(NEED_MICREF_SCENE.begin(), NEED_MICREF_SCENE.end(), sceneType_)) {
110 needMicRefFlag_ = true;
111 algoSupportedConfig_.micRefNum = DEFAULT_MICREFON_CH;
112 algoAttr_.batchLen += algoSupportedConfig_.micRefNum;
113 enhanceBuf_.micRefBuffer.resize(deviceAttr_.micRefChannels * byteLenPerFrame);
114 }
115
116 enhanceBuf_.micBuffer.resize(deviceAttr_.micChannels * byteLenPerFrame);
117 outputCache_.resize(deviceAttr_.micChannels * byteLenPerFrame);
118 algoCache_.input.resize(algoAttr_.byteLenPerFrame * algoAttr_.batchLen);
119 algoCache_.output.resize(algoAttr_.byteLenPerFrame * deviceAttr_.micChannels);
120 AUDIO_INFO_LOG("micNum: %{public}u ecNum: %{public}u micRefNum: %{public}u outNum: %{public}u"
121 " byteLenPerFrame: %{public}u inputsize:%{public}zu outputsize:%{public}zu",
122 algoSupportedConfig_.micNum, algoSupportedConfig_.ecNum, algoSupportedConfig_.micRefNum,
123 algoSupportedConfig_.outNum, byteLenPerFrame, algoCache_.input.size(), algoCache_.output.size());
124
125 traceTagIn_ = sceneType_ + "_IN";
126 traceTagOut_ = sceneType_ + "_OUT";
127 dfxStreamInfo_ = { static_cast<AudioSamplingRate>(DEFAULT_SAMPLE_RATE), AudioEncodingType::ENCODING_PCM,
128 ConvertFormat(DEFAULT_FORMAT), static_cast<AudioChannel>(deviceAttr_.micChannels) };
129 std::string dumpFileInName = "Enhance_" + sceneType_ + "_" + GetTime() + "_In_" +
130 std::to_string(algoSupportedConfig_.ecNum) + "Ec_" + std::to_string(algoSupportedConfig_.micNum) + "Mic_" +
131 std::to_string(algoSupportedConfig_.micRefNum) + "MicRef.pcm";
132 std::string dumpFileOutName = "Enhance_" + sceneType_ + "_" + GetTime() + "_Out.pcm";
133 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, dumpFileInName, &dumpFileIn_);
134 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, dumpFileOutName, &dumpFileOut_);
135 }
136
~AudioEnhanceChain()137 AudioEnhanceChain::~AudioEnhanceChain()
138 {
139 threadHandler_ = nullptr;
140 ReleaseAllEnhanceModule();
141 DumpFileUtil::CloseDumpFile(&dumpFileIn_);
142 DumpFileUtil::CloseDumpFile(&dumpFileOut_);
143 }
144
ReleaseAllEnhanceModule()145 void AudioEnhanceChain::ReleaseAllEnhanceModule()
146 {
147 for (auto &module : enhanceModules_) {
148 if (module.libHandle != nullptr) {
149 module.libHandle->releaseEffect(module.enhanceHandle);
150 }
151 }
152 enhanceModules_.clear();
153 }
154
SetThreadHandler(const std::shared_ptr<ThreadHandler> & threadHandler)155 int32_t AudioEnhanceChain::SetThreadHandler(const std::shared_ptr<ThreadHandler> &threadHandler)
156 {
157 if (threadHandler == nullptr) {
158 AUDIO_ERR_LOG("threadHandler is null");
159 return ERROR;
160 }
161
162 threadHandler_ = threadHandler;
163 return SUCCESS;
164 }
165
ScheduleAudioTask(const ThreadHandler::Task & task)166 void AudioEnhanceChain::ScheduleAudioTask(const ThreadHandler::Task &task)
167 {
168 if (threadHandler_ != nullptr) {
169 threadHandler_->PostTask(task);
170 } else {
171 task();
172 }
173 }
174
ProcessSetInputDevice(const std::string & inputDevice,const std::string & deviceName)175 int32_t AudioEnhanceChain::ProcessSetInputDevice(const std::string &inputDevice, const std::string &deviceName)
176 {
177 if (inputDevice == algoParam_.preDevice) {
178 AUDIO_INFO_LOG("the current device does not need to be updated");
179 return SUCCESS;
180 }
181 algoParam_.preDevice = inputDevice;
182 algoParam_.preDeviceName = deviceName;
183 AUDIO_INFO_LOG("update input device %{public}s name %{public}s", inputDevice.c_str(), deviceName.c_str());
184 AudioEffectTransInfo cmdInfo = {};
185 AudioEffectTransInfo replyInfo = {};
186 for (const auto &module : enhanceModules_) {
187 auto setParaCmdRet = SetEnhanceParamToHandle(module.enhanceHandle);
188 CHECK_AND_RETURN_RET_LOG(setParaCmdRet == SUCCESS, ERROR,
189 "[%{public}s] effect EFFECT_CMD_SET_PARAM fail", sceneType_.c_str());
190 auto initCmdRet = (*module.enhanceHandle)->command(module.enhanceHandle, EFFECT_CMD_INIT, &cmdInfo, &replyInfo);
191 CHECK_AND_RETURN_RET_LOG(initCmdRet == 0, ERROR,
192 "[%{public}s] effect EFFECT_CMD_INIT fail", sceneType_.c_str());
193 }
194
195 return SUCCESS;
196 }
197
SetInputDevice(const std::string & inputDevice,const std::string & deviceName)198 int32_t AudioEnhanceChain::SetInputDevice(const std::string &inputDevice, const std::string &deviceName)
199 {
200 if (inputDevice.size() == 0) {
201 return SUCCESS;
202 }
203
204 auto task = [self = weak_from_this(), inputDevice, deviceName]() {
205 if (auto chain = self.lock(); chain != nullptr) {
206 chain->ProcessSetInputDevice(inputDevice, deviceName);
207 }
208 };
209
210 ScheduleAudioTask(task);
211
212 return SUCCESS;
213 }
214
ProcessSetFoldState(uint32_t foldState)215 int32_t AudioEnhanceChain::ProcessSetFoldState(uint32_t foldState)
216 {
217 if (foldState == algoParam_.foldState) {
218 AUDIO_INFO_LOG("no need update fold state %{public}u", foldState);
219 return SUCCESS;
220 }
221 algoParam_.foldState = foldState;
222 AUDIO_INFO_LOG("update fold state %{public}u", foldState);
223
224 AudioEffectTransInfo cmdInfo = {};
225 AudioEffectTransInfo replyInfo = {};
226 for (const auto &module : enhanceModules_) {
227 auto setParaCmdRet = SetEnhanceParamToHandle(module.enhanceHandle);
228 CHECK_AND_RETURN_RET_LOG(setParaCmdRet == SUCCESS, ERROR,
229 "[%{public}s] effect EFFECT_CMD_SET_PARAM fail", sceneType_.c_str());
230 auto initCmdRet = (*module.enhanceHandle)->command(module.enhanceHandle, EFFECT_CMD_INIT, &cmdInfo, &replyInfo);
231 CHECK_AND_RETURN_RET_LOG(initCmdRet == 0, ERROR,
232 "[%{public}s] effect EFFECT_CMD_INIT fail", sceneType_.c_str());
233 }
234
235 return SUCCESS;
236 }
237
SetFoldState(uint32_t foldState)238 int32_t AudioEnhanceChain::SetFoldState(uint32_t foldState)
239 {
240 auto task = [self = weak_from_this(), foldState]() {
241 if (auto chain = self.lock(); chain != nullptr) {
242 chain->ProcessSetFoldState(foldState);
243 }
244 };
245
246 ScheduleAudioTask(task);
247
248 return SUCCESS;
249 }
250
ProcessSetEnhanceParam(bool mute,uint32_t systemVol)251 int32_t AudioEnhanceChain::ProcessSetEnhanceParam(bool mute, uint32_t systemVol)
252 {
253 algoParam_.muteInfo = mute;
254 algoParam_.volumeInfo = systemVol;
255
256 AudioEffectTransInfo cmdInfo = {};
257 AudioEffectTransInfo replyInfo = {};
258 for (const auto &module : enhanceModules_) {
259 auto setParaCmdRet = SetEnhanceParamToHandle(module.enhanceHandle);
260 CHECK_AND_RETURN_RET_LOG(setParaCmdRet == SUCCESS, ERROR,
261 "[%{public}s] effect EFFECT_CMD_SET_PARAM fail", sceneType_.c_str());
262 auto initCmdRet = (*module.enhanceHandle)->command(module.enhanceHandle, EFFECT_CMD_INIT, &cmdInfo, &replyInfo);
263 CHECK_AND_RETURN_RET_LOG(initCmdRet == SUCCESS, ERROR,
264 "[%{public}s] effect EFFECT_CMD_INIT fail", sceneType_.c_str());
265 }
266
267 return SUCCESS;
268 }
269
SetEnhanceParam(bool mute,uint32_t systemVol)270 int32_t AudioEnhanceChain::SetEnhanceParam(bool mute, uint32_t systemVol)
271 {
272 auto task = [self = weak_from_this(), mute, systemVol]() {
273 if (auto chain = self.lock(); chain != nullptr) {
274 chain->ProcessSetEnhanceParam(mute, systemVol);
275 }
276 };
277
278 ScheduleAudioTask(task);
279
280 return SUCCESS;
281 }
282
SetEnhanceParamToHandle(AudioEffectHandle handle)283 int32_t AudioEnhanceChain::SetEnhanceParamToHandle(AudioEffectHandle handle)
284 {
285 AudioEffectTransInfo cmdInfo = {};
286 AudioEffectTransInfo replyInfo = {};
287 AudioEnhanceParam setParam = {algoParam_.muteInfo, algoParam_.volumeInfo, algoParam_.foldState,
288 algoParam_.preDevice.c_str(), algoParam_.postDevice.c_str(), algoParam_.sceneType.c_str(),
289 algoParam_.preDeviceName.c_str()};
290 cmdInfo.data = static_cast<void *>(&setParam);
291 cmdInfo.size = sizeof(setParam);
292 return (*handle)->command(handle, EFFECT_CMD_SET_PARAM, &cmdInfo, &replyInfo);
293 }
294
InitSingleEnhanceModule(AudioEffectHandle enhanceHandle,const std::string & enhanceProp)295 int32_t AudioEnhanceChain::InitSingleEnhanceModule(AudioEffectHandle enhanceHandle, const std::string &enhanceProp)
296 {
297 int32_t ret = ERROR;
298 AudioEffectTransInfo cmdInfo = {};
299 AudioEffectTransInfo replyInfo = {};
300
301 uint32_t maxSampleRate = DEFAULT_SAMPLE_RATE;
302 replyInfo.data = &maxSampleRate;
303 replyInfo.size = sizeof(maxSampleRate);
304 ret = (*enhanceHandle)->command(enhanceHandle, EFFECT_CMD_GET_CONFIG, &cmdInfo, &replyInfo);
305 if (ret != SUCCESS) {
306 AUDIO_ERR_LOG("get algo maxSampleRate failed!");
307 }
308 if (algoSupportedConfig_.sampleRate != maxSampleRate) {
309 algoSupportedConfig_.sampleRate = maxSampleRate;
310 uint32_t byteLenPerFrame = DEFAULT_FRAMELENGTH * (maxSampleRate / MILLISECOND) *
311 DEFAULT_FORMAT;
312 algoAttr_.byteLenPerFrame = byteLenPerFrame;
313
314 algoCache_.input.resize(algoAttr_.byteLenPerFrame * algoAttr_.batchLen);
315 algoCache_.output.resize(algoAttr_.byteLenPerFrame * deviceAttr_.micChannels);
316 AUDIO_INFO_LOG("algorate: %{public}u byteLenPerFrame: %{public}u inputsize:%{public}zu outputsize:%{public}zu",
317 maxSampleRate, byteLenPerFrame, algoCache_.input.size(), algoCache_.output.size());
318 }
319
320 cmdInfo.data = static_cast<void *>(&algoSupportedConfig_);
321 cmdInfo.size = sizeof(algoSupportedConfig_);
322
323 ret = (*enhanceHandle)->command(enhanceHandle, EFFECT_CMD_SET_CONFIG, &cmdInfo, &replyInfo);
324 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERROR, "[%{public}s], either one of libs EFFECT_CMD_SET_CONFIG fail",
325 sceneType_.c_str());
326
327 CHECK_AND_RETURN_RET_LOG(SetEnhanceParamToHandle(enhanceHandle) == SUCCESS, ERROR,
328 "[%{public}s] EFFECT_CMD_SET_PARAM fail", sceneType_.c_str());
329
330 CHECK_AND_RETURN_RET_LOG(SetPropertyToHandle(enhanceHandle, enhanceProp) == SUCCESS, ERROR,
331 "[%{public}s] EFFECT_CMD_SET_PROPERTY fail", sceneType_.c_str());
332
333 ret = (*enhanceHandle)->command(enhanceHandle, EFFECT_CMD_INIT, &cmdInfo, &replyInfo);
334 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERROR, "[%{public}s], either one of libs EFFECT_CMD_INIT fail",
335 sceneType_.c_str());
336
337 return SUCCESS;
338 }
339
ProcessCreateAllEnhanceModule(const std::vector<EnhanceModulePara> & moduleParas)340 int32_t AudioEnhanceChain::ProcessCreateAllEnhanceModule(const std::vector<EnhanceModulePara> &moduleParas)
341 {
342 for (const auto ¶ : moduleParas) {
343 AudioEffectDescriptor descriptor = { para.libName, para.enhanceName };
344 AUDIO_INFO_LOG("libName: %{public}s enhanceName:%{public}s", para.libName.c_str(), para.enhanceName.c_str());
345 AudioEffectHandle enhanceHandle = nullptr;
346 int32_t ret = para.libHandle->createEffect(descriptor, &enhanceHandle);
347 CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "create effect: %{public}s fail", para.enhanceName.c_str());
348 CHECK_AND_RETURN_RET_LOG(enhanceHandle != nullptr, ERROR, "enhanceHandle is null");
349
350 int32_t initSingleModuleRet = InitSingleEnhanceModule(enhanceHandle, para.enhanceProp);
351 if (initSingleModuleRet != SUCCESS) {
352 AUDIO_ERR_LOG("init enhance: %{public}s fail", para.enhanceName.c_str());
353 para.libHandle->releaseEffect(enhanceHandle);
354 return ERROR;
355 }
356
357 EnhanceModule module = { para.enhanceName, enhanceHandle, para.libHandle };
358 enhanceModules_.emplace_back(module);
359 }
360
361 {
362 std::lock_guard<std::mutex> lock(chainMutex_);
363 chainIsReady_ = true;
364 }
365
366 return SUCCESS;
367 }
368
CreateAllEnhanceModule(const std::vector<EnhanceModulePara> & moduleParas)369 int32_t AudioEnhanceChain::CreateAllEnhanceModule(const std::vector<EnhanceModulePara> &moduleParas)
370 {
371 for (const auto ¶ : moduleParas) {
372 if (para.libHandle == nullptr || para.libHandle->createEffect == nullptr ||
373 para.libHandle->releaseEffect == nullptr) {
374 AUDIO_ERR_LOG("enhance: %{public}s interface is null", para.enhanceName.c_str());
375 return ERROR;
376 }
377 }
378
379 auto task = [self = weak_from_this(), moduleParas]() {
380 if (auto chain = self.lock(); chain != nullptr) {
381 chain->ProcessCreateAllEnhanceModule(moduleParas);
382 }
383 };
384
385 ScheduleAudioTask(task);
386
387 return SUCCESS;
388 }
389
IsEmptyEnhanceHandles()390 bool AudioEnhanceChain::IsEmptyEnhanceHandles()
391 {
392 return enhanceModules_.empty();
393 }
394
GetAlgoConfig(AudioBufferConfig & micConfig,AudioBufferConfig & ecConfig,AudioBufferConfig & micRefConfig)395 void AudioEnhanceChain::GetAlgoConfig(AudioBufferConfig &micConfig, AudioBufferConfig &ecConfig,
396 AudioBufferConfig &micRefConfig)
397 {
398 uint8_t configDataformat = static_cast<uint8_t>(algoSupportedConfig_.dataFormat);
399 micConfig.samplingRate = algoSupportedConfig_.sampleRate;
400 micConfig.channels = algoSupportedConfig_.micNum;
401 micConfig.format = configDataformat;
402
403 if (needEcFlag_) {
404 ecConfig.samplingRate = algoSupportedConfig_.sampleRate;
405 ecConfig.channels = algoSupportedConfig_.ecNum;
406 ecConfig.format = configDataformat;
407 }
408 if (needMicRefFlag_) {
409 micRefConfig.samplingRate = algoSupportedConfig_.sampleRate;
410 micRefConfig.channels = algoSupportedConfig_.micRefNum;
411 micRefConfig.format = configDataformat;
412 }
413 return;
414 }
415
GetChainId(void) const416 uint64_t AudioEnhanceChain::GetChainId(void) const
417 {
418 return chainId_;
419 }
420
GetScenePriority(void) const421 ScenePriority AudioEnhanceChain::GetScenePriority(void) const
422 {
423 return scenePriority_;
424 }
425
DeinterleaverData(uint8_t * src,uint32_t channel,uint8_t * dst,uint32_t dstLen)426 int32_t AudioEnhanceChain::DeinterleaverData(uint8_t *src, uint32_t channel, uint8_t *dst, uint32_t dstLen)
427 {
428 uint32_t srcIdx = 0;
429 uint32_t frameCount = algoAttr_.byteLenPerFrame / algoAttr_.bitDepth;
430 for (uint32_t i = 0; i < frameCount; ++i) {
431 for (uint32_t j = 0; j < channel; ++j) {
432 uint32_t dstIdx = j * algoAttr_.byteLenPerFrame + i * algoAttr_.bitDepth;
433 auto memcpyRet = memcpy_s(dst + dstIdx, dstLen - srcIdx, &src[srcIdx], algoAttr_.bitDepth);
434 CHECK_AND_RETURN_RET_LOG(memcpyRet == EOK, ERROR, "memcpy in deinterleaver error");
435 srcIdx += algoAttr_.bitDepth;
436 }
437 }
438 return SUCCESS;
439 }
440
ProcessSetEnhanceProperty(const std::string & enhance,const std::string & property)441 int32_t AudioEnhanceChain::ProcessSetEnhanceProperty(const std::string &enhance, const std::string &property)
442 {
443 AudioEffectTransInfo cmdInfo = {};
444 AudioEffectTransInfo replyInfo = {};
445 for (const auto &module : enhanceModules_) {
446 if (module.enhanceName != enhance) {
447 continue;
448 }
449 auto setPropCmdRet = SetPropertyToHandle(module.enhanceHandle, property);
450 CHECK_AND_RETURN_RET_LOG(setPropCmdRet == SUCCESS, ERROR,
451 "[%{public}s] %{public}s effect EFFECT_CMD_SET_PROPERTY fail", sceneType_.c_str(), enhance.c_str());
452 auto initCmdRet = (*module.enhanceHandle)->command(module.enhanceHandle, EFFECT_CMD_INIT, &cmdInfo, &replyInfo);
453 CHECK_AND_RETURN_RET_LOG(initCmdRet == SUCCESS, ERROR,
454 "[%{public}s] %{public}s effect EFFECT_CMD_INIT fail", sceneType_.c_str(), enhance.c_str());
455 }
456
457 return SUCCESS;
458 }
459
SetEnhanceProperty(const std::string & enhance,const std::string & property)460 int32_t AudioEnhanceChain::SetEnhanceProperty(const std::string &enhance, const std::string &property)
461 {
462 auto task = [self = weak_from_this(), enhance, property]() {
463 if (auto chain = self.lock(); chain != nullptr) {
464 chain->ProcessSetEnhanceProperty(enhance, property);
465 }
466 };
467
468 ScheduleAudioTask(task);
469
470 return SUCCESS;
471 }
472
SetPropertyToHandle(AudioEffectHandle handle,const std::string & property)473 int32_t AudioEnhanceChain::SetPropertyToHandle(AudioEffectHandle handle, const std::string &property)
474 {
475 int32_t replyData = 0;
476 const char *propCstr = property.c_str();
477 AudioEffectTransInfo cmdInfo = {sizeof(const char *), reinterpret_cast<void*>(&propCstr)};
478 AudioEffectTransInfo replyInfo = {sizeof(int32_t), &replyData};
479 return (*handle)->command(handle, EFFECT_CMD_SET_PROPERTY, &cmdInfo, &replyInfo);
480 }
481
CacheChainInputData(const EnhanceTransBuffer & transBuf)482 int32_t AudioEnhanceChain::CacheChainInputData(const EnhanceTransBuffer &transBuf)
483 {
484 if (transBuf.ecData != nullptr && transBuf.ecDataLen == enhanceBuf_.ecBuffer.size()) {
485 auto memcpyEcRet = memcpy_s(enhanceBuf_.ecBuffer.data(), enhanceBuf_.ecBuffer.size(),
486 transBuf.ecData, transBuf.ecDataLen);
487 CHECK_AND_RETURN_RET_LOG(memcpyEcRet == EOK, ERROR, "cache ec data fail");
488 }
489
490 if (transBuf.micData != nullptr && transBuf.micDataLen == enhanceBuf_.micBuffer.size()) {
491 auto memcpyMicRet = memcpy_s(enhanceBuf_.micBuffer.data(), enhanceBuf_.micBuffer.size(),
492 transBuf.micData, transBuf.micDataLen);
493 CHECK_AND_RETURN_RET_LOG(memcpyMicRet == EOK, ERROR, "cache mic data fail");
494 }
495
496 if (transBuf.micRefData != nullptr && transBuf.micRefDataLen == enhanceBuf_.micRefBuffer.size()) {
497 auto memcpyMIcRefRet = memcpy_s(enhanceBuf_.micRefBuffer.data(), enhanceBuf_.micRefBuffer.size(),
498 transBuf.micRefData, transBuf.micRefDataLen);
499 CHECK_AND_RETURN_RET_LOG(memcpyMIcRefRet == EOK, ERROR, "cache micRef data fail");
500 }
501
502 hasTask_ = true;
503
504 return SUCCESS;
505 }
506
GetOutputDataFromChain(void * buf,size_t bufSize)507 int32_t AudioEnhanceChain::GetOutputDataFromChain(void *buf, size_t bufSize)
508 {
509 CHECK_AND_RETURN_RET_LOG(buf != nullptr, ERROR, "buf is null");
510 CHECK_AND_RETURN_RET_LOG(bufSize != 0, ERROR, "bufSize is 0");
511
512 std::lock_guard<std::mutex> lock(chainMutex_);
513 auto memcpyRet = memcpy_s(buf, bufSize, outputCache_.data(), outputCache_.size());
514 CHECK_AND_RETURN_RET_LOG(memcpyRet == EOK, ERROR, "memcpy chain out data fail");
515
516 return SUCCESS;
517 }
518
WriteChainOutputData(void * buf,size_t bufSize)519 int32_t AudioEnhanceChain::WriteChainOutputData(void *buf, size_t bufSize)
520 {
521 CHECK_AND_RETURN_RET_LOG(buf != nullptr, ERROR, "buf is null");
522 CHECK_AND_RETURN_RET_LOG(bufSize != 0, ERROR, "bufSize is 0");
523
524 auto memcpyRet = memcpy_s(outputCache_.data(), outputCache_.size(), buf, bufSize);
525 CHECK_AND_RETURN_RET_LOG(memcpyRet == EOK, ERROR, "write chain out data fail");
526
527 return SUCCESS;
528 }
529
PrepareChainInputData(void)530 int32_t AudioEnhanceChain::PrepareChainInputData(void)
531 {
532 int32_t ret = 0;
533 uint32_t ecIdx = 0;
534 uint32_t micIdx = algoAttr_.byteLenPerFrame * algoSupportedConfig_.ecNum;
535 uint32_t micRefIdx = micIdx + algoAttr_.byteLenPerFrame * algoSupportedConfig_.micNum;
536 auto enhanceBufLen = enhanceBuf_.ecBuffer.size() + enhanceBuf_.micBuffer.size() + enhanceBuf_.micRefBuffer.size();
537 CHECK_AND_RETURN_RET_LOG(enhanceBufLen <= algoCache_.input.size(), ERROR, "input cache insufficient");
538
539 if (enhanceBuf_.ecBuffer.size() != 0) {
540 ret = DeinterleaverData(enhanceBuf_.ecBuffer.data(), deviceAttr_.ecChannels,
541 &algoCache_.input[ecIdx], enhanceBuf_.ecBuffer.size());
542 CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "deinterleaver ec data fail");
543 }
544
545 if (enhanceBuf_.micBuffer.size() != 0) {
546 BufferDesc bufferIn = { enhanceBuf_.micBuffer.data(), enhanceBuf_.micBuffer.size(),
547 enhanceBuf_.micBuffer.size() };
548 VolumeTools::DfxOperation(bufferIn, dfxStreamInfo_, traceTagIn_, volumeDataCountIn_);
549 ret = DeinterleaverData(enhanceBuf_.micBuffer.data(), deviceAttr_.micChannels,
550 &algoCache_.input[micIdx], enhanceBuf_.micBuffer.size());
551 CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "deinterleaver mic data fail");
552 }
553
554 if (enhanceBuf_.micRefBuffer.size() != 0) {
555 ret = DeinterleaverData(enhanceBuf_.micRefBuffer.data(), deviceAttr_.micRefChannels,
556 &algoCache_.input[micRefIdx], enhanceBuf_.micRefBuffer.size());
557 CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "deinterleaver micRef data fail");
558 }
559
560 return SUCCESS;
561 }
562
ProcessApplyEnhanceChain(void)563 int32_t AudioEnhanceChain::ProcessApplyEnhanceChain(void)
564 {
565 Trace trace("ProcessCapData");
566
567 {
568 std::lock_guard<std::mutex> lock(chainMutex_);
569 CHECK_AND_RETURN_RET(hasTask_ == true, ERROR);
570 if (PrepareChainInputData() != SUCCESS || enhanceModules_.empty()) {
571 WriteChainOutputData(enhanceBuf_.micBuffer.data(), enhanceBuf_.micBuffer.size());
572 return SUCCESS;
573 }
574 hasTask_ = false;
575 }
576
577 AudioBuffer audioBufIn = { .frameLength = algoCache_.input.size(), .raw = algoCache_.input.data() };
578 AudioBuffer audioBufOut = { .frameLength = algoCache_.output.size(), .raw = algoCache_.output.data() };
579 DumpFileUtil::WriteDumpFile(dumpFileIn_, algoCache_.input.data(), algoCache_.input.size());
580
581 for (const auto &module : enhanceModules_) {
582 int32_t ret = (*module.enhanceHandle)->process(module.enhanceHandle, &audioBufIn, &audioBufOut);
583 CHECK_AND_CONTINUE_LOG(ret == 0, "module: [%{public}s] process fail", module.enhanceName.c_str());
584 }
585
586 DumpFileUtil::WriteDumpFile(dumpFileOut_, algoCache_.output.data(), algoCache_.output.size());
587 BufferDesc bufferOut = { algoCache_.output.data(), algoCache_.output.size(), algoCache_.output.size() };
588 VolumeTools::DfxOperation(bufferOut, dfxStreamInfo_, traceTagOut_, volumeDataCountOut_);
589
590 {
591 std::lock_guard<std::mutex> lock(chainMutex_);
592 WriteChainOutputData(audioBufOut.raw, audioBufOut.frameLength);
593 }
594
595 return SUCCESS;
596 }
597
ApplyEnhanceChain(const EnhanceTransBuffer & transBuf)598 int32_t AudioEnhanceChain::ApplyEnhanceChain(const EnhanceTransBuffer &transBuf)
599 {
600 {
601 std::lock_guard<std::mutex> lock(chainMutex_);
602 if (chainIsReady_) {
603 auto cacheChainInputDataRet = CacheChainInputData(transBuf);
604 CHECK_AND_RETURN_RET_LOG(cacheChainInputDataRet == SUCCESS, ERROR, "cache chain input data fail");
605 } else {
606 AUDIO_INFO_LOG("chain is not ready, passthrough data");
607 WriteChainOutputData(transBuf.micData, transBuf.micDataLen);
608 return SUCCESS;
609 }
610 }
611
612 auto task = [self = weak_from_this()]() {
613 if (auto chain = self.lock(); chain != nullptr) {
614 chain->ProcessApplyEnhanceChain();
615 }
616 };
617
618 ScheduleAudioTask(task);
619
620 return SUCCESS;
621 }
622
ProcessInitCommand(void)623 int32_t AudioEnhanceChain::ProcessInitCommand(void)
624 {
625 AudioEffectTransInfo cmdInfo = {};
626 AudioEffectTransInfo replyInfo = {};
627 for (const auto &module : enhanceModules_) {
628 auto initCmdRet = (*module.enhanceHandle)->command(module.enhanceHandle, EFFECT_CMD_INIT, &cmdInfo, &replyInfo);
629 CHECK_AND_RETURN_RET_LOG(initCmdRet == SUCCESS, ERROR,
630 "[%{public}s] effect EFFECT_CMD_INIT fail", sceneType_.c_str());
631 }
632
633 return SUCCESS;
634 }
635
InitCommand()636 int32_t AudioEnhanceChain::InitCommand()
637 {
638 auto task = [self = weak_from_this()]() {
639 if (auto chain = self.lock(); chain != nullptr) {
640 chain->ProcessInitCommand();
641 }
642 };
643
644 ScheduleAudioTask(task);
645
646 return SUCCESS;
647 }
648 } // namespace AudioStandard
649 } // namespace OHOS