1 /*
2 * Copyright (C) 2023 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 #include <algorithm>
18 #include <limits.h>
19 #include <unordered_set>
20
21 #define LOG_TAG "EffectReverb"
22
23 #include <audio_effects/effect_bassboost.h>
24 #include <audio_effects/effect_equalizer.h>
25 #include <audio_effects/effect_virtualizer.h>
26 #include <android-base/logging.h>
27 #include <fmq/AidlMessageQueue.h>
28 #include <Utils.h>
29
30 #include "EffectReverb.h"
31 #include "ReverbTypes.h"
32
33 using aidl::android::hardware::audio::effect::Descriptor;
34 using aidl::android::hardware::audio::effect::EffectReverb;
35 using aidl::android::hardware::audio::effect::getEffectImplUuidAuxEnvReverb;
36 using aidl::android::hardware::audio::effect::getEffectImplUuidAuxPresetReverb;
37 using aidl::android::hardware::audio::effect::getEffectImplUuidInsertEnvReverb;
38 using aidl::android::hardware::audio::effect::getEffectImplUuidInsertPresetReverb;
39 using aidl::android::hardware::audio::effect::IEffect;
40 using aidl::android::hardware::audio::effect::State;
41 using aidl::android::media::audio::common::AudioUuid;
42
isReverbUuidSupported(const AudioUuid * uuid)43 bool isReverbUuidSupported(const AudioUuid* uuid) {
44 return (*uuid == getEffectImplUuidAuxEnvReverb() ||
45 *uuid == getEffectImplUuidAuxPresetReverb() ||
46 *uuid == getEffectImplUuidInsertEnvReverb() ||
47 *uuid == getEffectImplUuidInsertPresetReverb());
48 }
49
createEffect(const AudioUuid * uuid,std::shared_ptr<IEffect> * instanceSpp)50 extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
51 std::shared_ptr<IEffect>* instanceSpp) {
52 if (uuid == nullptr || !isReverbUuidSupported(uuid)) {
53 LOG(ERROR) << __func__ << "uuid not supported";
54 return EX_ILLEGAL_ARGUMENT;
55 }
56 if (instanceSpp) {
57 *instanceSpp = ndk::SharedRefBase::make<EffectReverb>(*uuid);
58 return EX_NONE;
59 } else {
60 LOG(ERROR) << __func__ << " invalid input parameter!";
61 return EX_ILLEGAL_ARGUMENT;
62 }
63 }
64
queryEffect(const AudioUuid * in_impl_uuid,Descriptor * _aidl_return)65 extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
66 if (*in_impl_uuid == getEffectImplUuidAuxEnvReverb()) {
67 *_aidl_return = aidl::android::hardware::audio::effect::lvm::kAuxEnvReverbDesc;
68 } else if (*in_impl_uuid == getEffectImplUuidInsertEnvReverb()) {
69 *_aidl_return = aidl::android::hardware::audio::effect::lvm::kInsertEnvReverbDesc;
70 } else if (*in_impl_uuid == getEffectImplUuidAuxPresetReverb()) {
71 *_aidl_return = aidl::android::hardware::audio::effect::lvm::kAuxPresetReverbDesc;
72 } else if (*in_impl_uuid == getEffectImplUuidInsertPresetReverb()) {
73 *_aidl_return = aidl::android::hardware::audio::effect::lvm::kInsertPresetReverbDesc;
74 } else {
75 LOG(ERROR) << __func__ << "uuid not supported";
76 return EX_ILLEGAL_ARGUMENT;
77 }
78 return EX_NONE;
79 }
80
81 namespace aidl::android::hardware::audio::effect {
82
EffectReverb(const AudioUuid & uuid)83 EffectReverb::EffectReverb(const AudioUuid& uuid) {
84 if (uuid == getEffectImplUuidAuxEnvReverb()) {
85 mType = lvm::ReverbEffectType::AUX_ENV;
86 mDescriptor = &lvm::kAuxEnvReverbDesc;
87 mEffectName = &lvm::kAuxEnvReverbEffectName;
88 } else if (uuid == getEffectImplUuidInsertEnvReverb()) {
89 mType = lvm::ReverbEffectType::INSERT_ENV;
90 mDescriptor = &lvm::kInsertEnvReverbDesc;
91 mEffectName = &lvm::kInsertEnvReverbEffectName;
92 } else if (uuid == getEffectImplUuidAuxPresetReverb()) {
93 mType = lvm::ReverbEffectType::AUX_PRESET;
94 mDescriptor = &lvm::kAuxPresetReverbDesc;
95 mEffectName = &lvm::kAuxPresetReverbEffectName;
96 } else if (uuid == getEffectImplUuidInsertPresetReverb()) {
97 mType = lvm::ReverbEffectType::INSERT_PRESET;
98 mDescriptor = &lvm::kInsertPresetReverbDesc;
99 mEffectName = &lvm::kInsertPresetReverbEffectName;
100 } else {
101 LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
102 }
103 }
104
~EffectReverb()105 EffectReverb::~EffectReverb() {
106 cleanUp();
107 }
108
getDescriptor(Descriptor * _aidl_return)109 ndk::ScopedAStatus EffectReverb::getDescriptor(Descriptor* _aidl_return) {
110 RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
111 *_aidl_return = *mDescriptor;
112 return ndk::ScopedAStatus::ok();
113 }
114
setParameterSpecific(const Parameter::Specific & specific)115 ndk::ScopedAStatus EffectReverb::setParameterSpecific(const Parameter::Specific& specific) {
116 LOG(VERBOSE) << __func__ << " specific " << specific.toString();
117 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
118
119 auto tag = specific.getTag();
120 switch (tag) {
121 case Parameter::Specific::presetReverb:
122 return setParameterPresetReverb(specific);
123 case Parameter::Specific::environmentalReverb:
124 return setParameterEnvironmentalReverb(specific);
125 default:
126 LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
127 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
128 "specificParamNotSupported");
129 }
130 }
131
setParameterPresetReverb(const Parameter::Specific & specific)132 ndk::ScopedAStatus EffectReverb::setParameterPresetReverb(const Parameter::Specific& specific) {
133 auto& prParam = specific.get<Parameter::Specific::presetReverb>();
134 RETURN_IF(!inRange(prParam, lvm::kPresetReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
135 auto tag = prParam.getTag();
136
137 switch (tag) {
138 case PresetReverb::preset: {
139 RETURN_IF(mContext->setPresetReverbPreset(prParam.get<PresetReverb::preset>()) !=
140 RetCode::SUCCESS,
141 EX_ILLEGAL_ARGUMENT, "setPresetFailed");
142 return ndk::ScopedAStatus::ok();
143 }
144 default: {
145 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
146 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
147 "PresetReverbTagNotSupported");
148 }
149 }
150 }
151
setParameterEnvironmentalReverb(const Parameter::Specific & specific)152 ndk::ScopedAStatus EffectReverb::setParameterEnvironmentalReverb(
153 const Parameter::Specific& specific) {
154 auto& erParam = specific.get<Parameter::Specific::environmentalReverb>();
155 RETURN_IF(!inRange(erParam, lvm::kEnvReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
156 auto tag = erParam.getTag();
157
158 switch (tag) {
159 case EnvironmentalReverb::roomLevelMb: {
160 RETURN_IF(mContext->setEnvironmentalReverbRoomLevel(
161 erParam.get<EnvironmentalReverb::roomLevelMb>()) != RetCode::SUCCESS,
162 EX_ILLEGAL_ARGUMENT, "setRoomLevelFailed");
163 return ndk::ScopedAStatus::ok();
164 }
165 case EnvironmentalReverb::roomHfLevelMb: {
166 RETURN_IF(
167 mContext->setEnvironmentalReverbRoomHfLevel(
168 erParam.get<EnvironmentalReverb::roomHfLevelMb>()) != RetCode::SUCCESS,
169 EX_ILLEGAL_ARGUMENT, "setRoomHfLevelFailed");
170 return ndk::ScopedAStatus::ok();
171 }
172 case EnvironmentalReverb::decayTimeMs: {
173 RETURN_IF(mContext->setEnvironmentalReverbDecayTime(
174 erParam.get<EnvironmentalReverb::decayTimeMs>()) != RetCode::SUCCESS,
175 EX_ILLEGAL_ARGUMENT, "setDecayTimeFailed");
176 return ndk::ScopedAStatus::ok();
177 }
178 case EnvironmentalReverb::decayHfRatioPm: {
179 RETURN_IF(
180 mContext->setEnvironmentalReverbDecayHfRatio(
181 erParam.get<EnvironmentalReverb::decayHfRatioPm>()) != RetCode::SUCCESS,
182 EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
183 return ndk::ScopedAStatus::ok();
184 }
185 case EnvironmentalReverb::reflectionsLevelMb: {
186 RETURN_IF(mContext->setReflectionsLevel(
187 erParam.get<EnvironmentalReverb::reflectionsLevelMb>()) !=
188 RetCode::SUCCESS,
189 EX_ILLEGAL_ARGUMENT, "setReflectionsLevelFailed");
190 return ndk::ScopedAStatus::ok();
191 }
192 case EnvironmentalReverb::reflectionsDelayMs: {
193 RETURN_IF(mContext->setReflectionsDelay(
194 erParam.get<EnvironmentalReverb::reflectionsDelayMs>()) !=
195 RetCode::SUCCESS,
196 EX_ILLEGAL_ARGUMENT, "setReflectionsDelayFailed");
197 return ndk::ScopedAStatus::ok();
198 }
199 case EnvironmentalReverb::levelMb: {
200 RETURN_IF(mContext->setEnvironmentalReverbLevel(
201 erParam.get<EnvironmentalReverb::levelMb>()) != RetCode::SUCCESS,
202 EX_ILLEGAL_ARGUMENT, "setLevelFailed");
203 return ndk::ScopedAStatus::ok();
204 }
205 case EnvironmentalReverb::delayMs: {
206 RETURN_IF(mContext->setEnvironmentalReverbDelay(
207 erParam.get<EnvironmentalReverb::delayMs>()) != RetCode::SUCCESS,
208 EX_ILLEGAL_ARGUMENT, "setDelayFailed");
209 return ndk::ScopedAStatus::ok();
210 }
211 case EnvironmentalReverb::diffusionPm: {
212 RETURN_IF(mContext->setEnvironmentalReverbDiffusion(
213 erParam.get<EnvironmentalReverb::diffusionPm>()) != RetCode::SUCCESS,
214 EX_ILLEGAL_ARGUMENT, "setDiffusionFailed");
215 return ndk::ScopedAStatus::ok();
216 }
217 case EnvironmentalReverb::densityPm: {
218 RETURN_IF(mContext->setEnvironmentalReverbDensity(
219 erParam.get<EnvironmentalReverb::densityPm>()) != RetCode::SUCCESS,
220 EX_ILLEGAL_ARGUMENT, "setDensityFailed");
221 return ndk::ScopedAStatus::ok();
222 }
223 case EnvironmentalReverb::bypass: {
224 RETURN_IF(mContext->setEnvironmentalReverbBypass(
225 erParam.get<EnvironmentalReverb::bypass>()) != RetCode::SUCCESS,
226 EX_ILLEGAL_ARGUMENT, "setBypassFailed");
227 return ndk::ScopedAStatus::ok();
228 }
229 default: {
230 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
231 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
232 EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
233 }
234 }
235 }
236
getParameterSpecific(const Parameter::Id & id,Parameter::Specific * specific)237 ndk::ScopedAStatus EffectReverb::getParameterSpecific(const Parameter::Id& id,
238 Parameter::Specific* specific) {
239 RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
240 auto tag = id.getTag();
241
242 switch (tag) {
243 case Parameter::Id::presetReverbTag:
244 return getParameterPresetReverb(id.get<Parameter::Id::presetReverbTag>(), specific);
245 case Parameter::Id::environmentalReverbTag:
246 return getParameterEnvironmentalReverb(id.get<Parameter::Id::environmentalReverbTag>(),
247 specific);
248 default:
249 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
250 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
251 "wrongIdTag");
252 }
253 }
254
getParameterPresetReverb(const PresetReverb::Id & id,Parameter::Specific * specific)255 ndk::ScopedAStatus EffectReverb::getParameterPresetReverb(const PresetReverb::Id& id,
256 Parameter::Specific* specific) {
257 RETURN_IF(id.getTag() != PresetReverb::Id::commonTag, EX_ILLEGAL_ARGUMENT,
258 "PresetReverbTagNotSupported");
259 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
260 PresetReverb prParam;
261 auto tag = id.get<PresetReverb::Id::commonTag>();
262 switch (tag) {
263 case PresetReverb::preset: {
264 prParam.set<PresetReverb::preset>(mContext->getPresetReverbPreset());
265 break;
266 }
267 default: {
268 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
269 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
270 "PresetReverbTagNotSupported");
271 }
272 }
273
274 specific->set<Parameter::Specific::presetReverb>(prParam);
275 return ndk::ScopedAStatus::ok();
276 }
277
getParameterEnvironmentalReverb(const EnvironmentalReverb::Id & id,Parameter::Specific * specific)278 ndk::ScopedAStatus EffectReverb::getParameterEnvironmentalReverb(const EnvironmentalReverb::Id& id,
279 Parameter::Specific* specific) {
280 RETURN_IF(id.getTag() != EnvironmentalReverb::Id::commonTag, EX_ILLEGAL_ARGUMENT,
281 "EnvironmentalReverbTagNotSupported");
282 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
283 EnvironmentalReverb erParam;
284
285 auto tag = id.get<EnvironmentalReverb::Id::commonTag>();
286 switch (tag) {
287 case EnvironmentalReverb::roomLevelMb: {
288 erParam.set<EnvironmentalReverb::roomLevelMb>(
289 mContext->getEnvironmentalReverbRoomLevel());
290 break;
291 }
292 case EnvironmentalReverb::roomHfLevelMb: {
293 erParam.set<EnvironmentalReverb::roomHfLevelMb>(
294 mContext->getEnvironmentalReverbRoomHfLevel());
295 break;
296 }
297 case EnvironmentalReverb::decayTimeMs: {
298 erParam.set<EnvironmentalReverb::decayTimeMs>(
299 mContext->getEnvironmentalReverbDecayTime());
300 break;
301 }
302 case EnvironmentalReverb::decayHfRatioPm: {
303 erParam.set<EnvironmentalReverb::decayHfRatioPm>(
304 mContext->getEnvironmentalReverbDecayHfRatio());
305 break;
306 }
307 case EnvironmentalReverb::reflectionsLevelMb: {
308 erParam.set<EnvironmentalReverb::reflectionsLevelMb>(mContext->getReflectionsLevel());
309 break;
310 }
311 case EnvironmentalReverb::reflectionsDelayMs: {
312 erParam.set<EnvironmentalReverb::reflectionsDelayMs>(mContext->getReflectionsDelay());
313 break;
314 }
315 case EnvironmentalReverb::levelMb: {
316 erParam.set<EnvironmentalReverb::levelMb>(mContext->getEnvironmentalReverbLevel());
317 break;
318 }
319 case EnvironmentalReverb::delayMs: {
320 erParam.set<EnvironmentalReverb::delayMs>(mContext->getEnvironmentalReverbDelay());
321 break;
322 }
323 case EnvironmentalReverb::diffusionPm: {
324 erParam.set<EnvironmentalReverb::diffusionPm>(
325 mContext->getEnvironmentalReverbDiffusion());
326 break;
327 }
328 case EnvironmentalReverb::densityPm: {
329 erParam.set<EnvironmentalReverb::densityPm>(mContext->getEnvironmentalReverbDensity());
330 break;
331 }
332 case EnvironmentalReverb::bypass: {
333 erParam.set<EnvironmentalReverb::bypass>(mContext->getEnvironmentalReverbBypass());
334 break;
335 }
336 default: {
337 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
338 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
339 EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
340 }
341 }
342
343 specific->set<Parameter::Specific::environmentalReverb>(erParam);
344 return ndk::ScopedAStatus::ok();
345 }
346
createContext(const Parameter::Common & common)347 std::shared_ptr<EffectContext> EffectReverb::createContext(const Parameter::Common& common) {
348 if (mContext) {
349 LOG(DEBUG) << __func__ << " context already exist";
350 } else {
351 mContext = std::make_shared<ReverbContext>(1 /* statusFmqDepth */, common, mType);
352 }
353
354 return mContext;
355 }
356
releaseContext()357 RetCode EffectReverb::releaseContext() {
358 if (mContext) {
359 mContext.reset();
360 }
361 return RetCode::SUCCESS;
362 }
363
commandImpl(CommandId command)364 ndk::ScopedAStatus EffectReverb::commandImpl(CommandId command) {
365 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
366 switch (command) {
367 case CommandId::START:
368 mContext->enable();
369 break;
370 case CommandId::STOP:
371 mContext->disable();
372 break;
373 case CommandId::RESET:
374 mContext->disable();
375 mContext->resetBuffer();
376 break;
377 default:
378 LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
379 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
380 "commandIdNotSupported");
381 }
382 return ndk::ScopedAStatus::ok();
383 }
384
385 // Processing method running in EffectWorker thread.
effectProcessImpl(float * in,float * out,int sampleToProcess)386 IEffect::Status EffectReverb::effectProcessImpl(float* in, float* out, int sampleToProcess) {
387 IEffect::Status status = {EX_NULL_POINTER, 0, 0};
388 RETURN_VALUE_IF(!mContext, status, "nullContext");
389 return mContext->process(in, out, sampleToProcess);
390 }
391
392 } // namespace aidl::android::hardware::audio::effect
393