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 "AudioEnhanceChainManager"
18 #endif
19 
20 #include "audio_enhance_chain_manager.h"
21 
22 #include "securec.h"
23 #include "audio_effect_log.h"
24 #include "audio_errors.h"
25 #include "audio_enhance_chain_adapter.h"
26 
27 using namespace OHOS::AudioStandard;
28 
29 namespace OHOS {
30 namespace AudioStandard {
31 
FindEnhanceLib(const std::string & enhance,const std::vector<std::shared_ptr<AudioEffectLibEntry>> & enhanceLibraryList,std::shared_ptr<AudioEffectLibEntry> & libEntry,std::string & libName)32 static int32_t FindEnhanceLib(const std::string &enhance,
33     const std::vector<std::shared_ptr<AudioEffectLibEntry>> &enhanceLibraryList,
34     std::shared_ptr<AudioEffectLibEntry> &libEntry, std::string &libName)
35 {
36     for (const std::shared_ptr<AudioEffectLibEntry> &lib : enhanceLibraryList) {
37         if (lib->libraryName == enhance) {
38             libName = lib->libraryName;
39             libEntry = lib;
40             return SUCCESS;
41         }
42     }
43     return ERROR;
44 }
45 
CheckValidEnhanceLibEntry(const std::shared_ptr<AudioEffectLibEntry> & libEntry,const std::string & enhance,const std::string & libName)46 static int32_t CheckValidEnhanceLibEntry(const std::shared_ptr<AudioEffectLibEntry> &libEntry,
47     const std::string &enhance, const std::string &libName)
48 {
49     CHECK_AND_RETURN_RET_LOG(libEntry, ERROR, "Enhance [%{public}s] in lib [%{public}s] is nullptr",
50         enhance.c_str(), libName.c_str());
51     CHECK_AND_RETURN_RET_LOG(libEntry->audioEffectLibHandle, ERROR,
52         "AudioEffectLibHandle of Enhance [%{public}s] in lib [%{public}s] is nullptr",
53         enhance.c_str(), libName.c_str());
54     CHECK_AND_RETURN_RET_LOG(libEntry->audioEffectLibHandle->createEffect, ERROR,
55         "CreateEffect function of Enhance [%{public}s] in lib [%{public}s] is nullptr",
56         enhance.c_str(), libName.c_str());
57     CHECK_AND_RETURN_RET_LOG(libEntry->audioEffectLibHandle->releaseEffect, ERROR,
58         "ReleaseEffect function of Enhance [%{public}s] in lib [%{public}s] is nullptr",
59         enhance.c_str(), libName.c_str());
60     return SUCCESS;
61 }
62 
AudioEnhanceChainManager()63 AudioEnhanceChainManager::AudioEnhanceChainManager()
64 {
65     sceneTypeToEnhanceChainMap_.clear();
66     sceneTypeToEnhanceChainCountMap_.clear();
67     sceneTypeAndModeToEnhanceChainNameMap_.clear();
68     enhanceChainToEnhancesMap_.clear();
69     enhanceToLibraryEntryMap_.clear();
70     enhanceToLibraryNameMap_.clear();
71     isInitialized_ = false;
72     upAndDownDevice_ = "";
73 }
74 
~AudioEnhanceChainManager()75 AudioEnhanceChainManager::~AudioEnhanceChainManager()
76 {
77     AUDIO_INFO_LOG("~AudioEnhanceChainManager destroy");
78 }
79 
GetInstance()80 AudioEnhanceChainManager *AudioEnhanceChainManager::GetInstance()
81 {
82     static AudioEnhanceChainManager audioEnhanceChainManager;
83     return &audioEnhanceChainManager;
84 }
85 
InitAudioEnhanceChainManager(std::vector<EffectChain> & enhanceChains,const EffectChainManagerParam & managerParam,std::vector<std::shared_ptr<AudioEffectLibEntry>> & enhanceLibraryList)86 void AudioEnhanceChainManager::InitAudioEnhanceChainManager(std::vector<EffectChain> &enhanceChains,
87     const EffectChainManagerParam &managerParam, std::vector<std::shared_ptr<AudioEffectLibEntry>> &enhanceLibraryList)
88 {
89     const std::unordered_map<std::string, std::string> &enhanceChainNameMap = managerParam.sceneTypeToChainNameMap;
90     std::lock_guard<std::mutex> lock(chainManagerMutex_);
91     std::set<std::string> enhanceSet;
92     for (EffectChain enhanceChain : enhanceChains) {
93         for (std::string enhance : enhanceChain.apply) {
94             enhanceSet.insert(enhance);
95         }
96     }
97     // Construct enhanceToLibraryEntryMap_ that stores libEntry for each effect name
98     std::shared_ptr<AudioEffectLibEntry> libEntry = nullptr;
99     std::string libName;
100     for (std::string enhance : enhanceSet) {
101         int32_t ret = FindEnhanceLib(enhance, enhanceLibraryList, libEntry, libName);
102         CHECK_AND_CONTINUE_LOG(ret != ERROR, "Couldn't find libEntry of effect %{public}s", enhance.c_str());
103         ret = CheckValidEnhanceLibEntry(libEntry, enhance, libName);
104         enhanceToLibraryEntryMap_[enhance] = libEntry;
105         enhanceToLibraryNameMap_[enhance] = libName;
106     }
107     // Construct enhanceChainToEnhancesMap_ that stores all effect names of each effect chain
108     for (EffectChain enhanceChain : enhanceChains) {
109         std::string key = enhanceChain.name;
110         std::vector<std::string> enhances;
111         for (std::string enhanceName : enhanceChain.apply) {
112             enhances.emplace_back(enhanceName);
113         }
114         enhanceChainToEnhancesMap_[key] = enhances;
115     }
116     // Construct sceneTypeAndModeToEnhanceChainNameMap_ that stores effectMode associated with the effectChainName
117     for (auto item = enhanceChainNameMap.begin(); item != enhanceChainNameMap.end(); item++) {
118         sceneTypeAndModeToEnhanceChainNameMap_[item->first] = item->second;
119     }
120     AUDIO_INFO_LOG("enhanceToLibraryEntryMap_ size %{public}zu \
121         enhanceToLibraryNameMap_ size %{public}zu \
122         sceneTypeAndModeToEnhanceChainNameMap_ size %{public}zu",
123         enhanceToLibraryEntryMap_.size(),
124         enhanceChainToEnhancesMap_.size(),
125         sceneTypeAndModeToEnhanceChainNameMap_.size());
126     isInitialized_ = true;
127 }
128 
CreateAudioEnhanceChainDynamic(const std::string & sceneType,const std::string & enhanceMode,const std::string & upAndDownDevice)129 int32_t AudioEnhanceChainManager::CreateAudioEnhanceChainDynamic(const std::string &sceneType,
130     const std::string &enhanceMode, const std::string &upAndDownDevice)
131 {
132     std::lock_guard<std::mutex> lock(chainManagerMutex_);
133     upAndDownDevice_ = upAndDownDevice;
134     std::string sceneTypeAndDeviceKey = sceneType + "_&_" + upAndDownDevice;
135     std::shared_ptr<AudioEnhanceChain> audioEnhanceChain = nullptr;
136     if (sceneTypeToEnhanceChainMap_.count(sceneTypeAndDeviceKey)) {
137         if (!sceneTypeToEnhanceChainCountMap_.count(sceneTypeAndDeviceKey) ||
138             sceneTypeToEnhanceChainCountMap_[sceneTypeAndDeviceKey] < 1) {
139             sceneTypeToEnhanceChainCountMap_.erase(sceneTypeAndDeviceKey);
140             sceneTypeToEnhanceChainMap_.erase(sceneTypeAndDeviceKey);
141             return ERROR;
142             }
143         sceneTypeToEnhanceChainCountMap_[sceneTypeAndDeviceKey]++;
144         return SUCCESS;
145     } else {
146         audioEnhanceChain = std::make_shared<AudioEnhanceChain>(sceneType);
147         sceneTypeToEnhanceChainMap_.insert(std::make_pair(sceneTypeAndDeviceKey, audioEnhanceChain));
148         if (!sceneTypeToEnhanceChainCountMap_.count(sceneTypeAndDeviceKey)) {
149             sceneTypeToEnhanceChainCountMap_.insert(std::make_pair(sceneTypeAndDeviceKey, 1));
150         } else {
151             sceneTypeToEnhanceChainCountMap_[sceneTypeAndDeviceKey] = 1;
152         }
153     }
154     if (SetAudioEnhanceChainDynamic(sceneType, enhanceMode, upAndDownDevice) != SUCCESS) {
155         return ERROR;
156     }
157     AUDIO_INFO_LOG("%{public}s create success", sceneTypeAndDeviceKey.c_str());
158     return SUCCESS;
159 }
160 
SetAudioEnhanceChainDynamic(const std::string & sceneType,const std::string & enhanceMode,const std::string & upAndDownDevice)161 int32_t AudioEnhanceChainManager::SetAudioEnhanceChainDynamic(const std::string &sceneType,
162     const std::string &enhanceMode, const std::string &upAndDownDevice)
163 {
164     std::string sceneTypeAndDeviceKey = sceneType + "_&_" + upAndDownDevice;
165     CHECK_AND_RETURN_RET_LOG(sceneTypeToEnhanceChainMap_.count(sceneTypeAndDeviceKey), ERROR,
166         "SceneType [%{public}s] does not exist, fail to set.", sceneTypeAndDeviceKey.c_str());
167 
168     std::shared_ptr<AudioEnhanceChain> audioEnhanceChain = sceneTypeToEnhanceChainMap_[sceneTypeAndDeviceKey];
169 
170     std::string enhanceChain;
171     std::string enhanceChainKey = sceneType + "_&_" + enhanceMode;
172     std::string enhanceNone = AUDIO_SUPPORTED_SCENE_MODES.find(EFFECT_NONE)->second;
173     if (!sceneTypeAndModeToEnhanceChainNameMap_.count(enhanceChainKey)) {
174         AUDIO_ERR_LOG("EnhanceChain key [%{public}s] does not exist, auto set to %{public}s",
175             enhanceChainKey.c_str(), enhanceNone.c_str());
176         enhanceChain = enhanceNone;
177     } else {
178         enhanceChain = sceneTypeAndModeToEnhanceChainNameMap_[enhanceChainKey];
179     }
180 
181     if (enhanceChain != enhanceNone && !enhanceChainToEnhancesMap_.count(enhanceChain)) {
182         AUDIO_ERR_LOG("EnhanceChain name [%{public}s] does not exist, auto set to %{public}s",
183             enhanceChain.c_str(), enhanceNone.c_str());
184             enhanceChain = enhanceNone;
185     }
186 
187     audioEnhanceChain->SetEnhanceMode(enhanceMode);
188     for (std::string enhance : enhanceChainToEnhancesMap_[enhanceChain]) {
189         AudioEffectHandle handle = nullptr;
190         AudioEffectDescriptor descriptor;
191         descriptor.libraryName = enhanceToLibraryNameMap_[enhance];
192         descriptor.effectName = enhance;
193 
194         AUDIO_INFO_LOG("libraryName: %{public}s effectName:%{public}s",
195             descriptor.libraryName.c_str(), descriptor.effectName.c_str());
196         int32_t ret = enhanceToLibraryEntryMap_[enhance]->audioEffectLibHandle->createEffect(descriptor, &handle);
197         CHECK_AND_CONTINUE_LOG(ret == 0, "EnhanceToLibraryEntryMap[%{public}s] createEffect fail",
198             enhance.c_str());
199         audioEnhanceChain->AddEnhanceHandle(handle, enhanceToLibraryEntryMap_[enhance]->audioEffectLibHandle);
200     }
201 
202     if (audioEnhanceChain->IsEmptyEnhanceHandles()) {
203         AUDIO_ERR_LOG("EnhanceChain is empty, copy bufIn to bufOut like EFFECT_NONE mode");
204         return ERROR;
205     }
206     return SUCCESS;
207 }
208 
ReleaseAudioEnhanceChainDynamic(const std::string & sceneType,const std::string & upAndDownDevice)209 int32_t AudioEnhanceChainManager::ReleaseAudioEnhanceChainDynamic(const std::string &sceneType,
210     const std::string &upAndDownDevice)
211 {
212     std::lock_guard<std::mutex> lock(chainManagerMutex_);
213     CHECK_AND_RETURN_RET_LOG(isInitialized_, ERROR, "has not been initialized");
214     CHECK_AND_RETURN_RET_LOG(sceneType != "", ERROR, "null sceneType");
215 
216     std::string sceneTypeAndDeviceKey = sceneType + "_&_" + upAndDownDevice;
217     if (!sceneTypeToEnhanceChainMap_.count(sceneTypeAndDeviceKey)) {
218         sceneTypeToEnhanceChainCountMap_.erase(sceneTypeAndDeviceKey);
219         return SUCCESS;
220     } else if (sceneTypeToEnhanceChainCountMap_.count(sceneTypeAndDeviceKey) &&
221         sceneTypeToEnhanceChainCountMap_[sceneTypeAndDeviceKey] > 1) {
222         sceneTypeToEnhanceChainCountMap_[sceneTypeAndDeviceKey]--;
223         return SUCCESS;
224     }
225     sceneTypeToEnhanceChainCountMap_.erase(sceneTypeAndDeviceKey);
226     sceneTypeToEnhanceChainMap_.erase(sceneTypeAndDeviceKey);
227     AUDIO_INFO_LOG("release %{public}s", sceneTypeAndDeviceKey.c_str());
228     return SUCCESS;
229 }
230 
ApplyAudioEnhanceChain(const std::string & sceneType,EnhanceBufferAttr * enhanceBufferAttr)231 int32_t AudioEnhanceChainManager::ApplyAudioEnhanceChain(const std::string &sceneType,
232     EnhanceBufferAttr *enhanceBufferAttr)
233 {
234     CHECK_AND_RETURN_RET_LOG(enhanceBufferAttr != nullptr, ERROR, "enhance buffer is null");
235     std::lock_guard<std::mutex> lock(chainManagerMutex_);
236     std::string sceneTypeAndDeviceKey = sceneType + "_&_" + GetUpAndDownDevice();
237     if (!sceneTypeToEnhanceChainMap_.count(sceneTypeAndDeviceKey)) {
238         uint32_t totalLen = enhanceBufferAttr->byteLenPerFrame * enhanceBufferAttr->outNum;
239         CHECK_AND_RETURN_RET_LOG(memcpy_s(enhanceBufferAttr->output, totalLen, enhanceBufferAttr->input,
240             totalLen) == 0, ERROR, "memcpy error in apply enhance");
241         AUDIO_ERR_LOG("Can not find %{public}s in sceneTypeToEnhanceChainMap_", sceneTypeAndDeviceKey.c_str());
242         return ERROR;
243     }
244     auto audioEnhanceChain = sceneTypeToEnhanceChainMap_[sceneTypeAndDeviceKey];
245     if (audioEnhanceChain->ApplyEnhanceChain(enhanceBufferAttr) != SUCCESS) {
246         AUDIO_ERR_LOG("Apply %{public}s failed.", sceneTypeAndDeviceKey.c_str());
247         return ERROR;
248     }
249     AUDIO_INFO_LOG("Apply %{public}s success", sceneTypeAndDeviceKey.c_str());
250     return SUCCESS;
251 }
252 
ExistAudioEnhanceChain(const std::string & sceneType)253 bool AudioEnhanceChainManager::ExistAudioEnhanceChain(const std::string &sceneType)
254 {
255     std::lock_guard<std::mutex> lock(chainManagerMutex_);
256     if (!isInitialized_) {
257         AUDIO_ERR_LOG("audioEnhanceChainManager has not been initialized.");
258         return false;
259     }
260     CHECK_AND_RETURN_RET(sceneType != "", false);
261     CHECK_AND_RETURN_RET_LOG(GetUpAndDownDevice() != "", false, "null device");
262 
263     std::string sceneTypeAndDeviceKey = sceneType + "_&_" + GetUpAndDownDevice();
264     if (!sceneTypeToEnhanceChainMap_.count(sceneTypeAndDeviceKey)) {
265         return false;
266     }
267     auto audioEnhanceChain = sceneTypeToEnhanceChainMap_[sceneTypeAndDeviceKey];
268     CHECK_AND_RETURN_RET_LOG(audioEnhanceChain != nullptr, false, "null sceneTypeToEnhanceChainMap_[%{public}s]",
269         sceneTypeAndDeviceKey.c_str());
270     return !audioEnhanceChain->IsEmptyEnhanceHandles();
271 }
272 
GetUpAndDownDevice()273 std::string AudioEnhanceChainManager::GetUpAndDownDevice()
274 {
275     return upAndDownDevice_;
276 }
277 
278 } // namespace AudioStandard
279 } // namespace OHOS