1 /*
2 * Copyright (C) 2022 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 <cstddef>
19 #include <unordered_set>
20
21 #define LOG_TAG "AHAL_EnvReverbSw"
22 #include <android-base/logging.h>
23 #include <fmq/AidlMessageQueue.h>
24 #include <system/audio_effects/effect_uuid.h>
25
26 #include "EnvReverbSw.h"
27
28 using aidl::android::hardware::audio::effect::Descriptor;
29 using aidl::android::hardware::audio::effect::EnvReverbSw;
30 using aidl::android::hardware::audio::effect::getEffectImplUuidEnvReverbSw;
31 using aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb;
32 using aidl::android::hardware::audio::effect::IEffect;
33 using aidl::android::hardware::audio::effect::State;
34 using aidl::android::media::audio::common::AudioUuid;
35
createEffect(const AudioUuid * in_impl_uuid,std::shared_ptr<IEffect> * instanceSpp)36 extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
37 std::shared_ptr<IEffect>* instanceSpp) {
38 if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEnvReverbSw()) {
39 LOG(ERROR) << __func__ << "uuid not supported";
40 return EX_ILLEGAL_ARGUMENT;
41 }
42 if (instanceSpp) {
43 *instanceSpp = ndk::SharedRefBase::make<EnvReverbSw>();
44 LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
45 return EX_NONE;
46 } else {
47 LOG(ERROR) << __func__ << " invalid input parameter!";
48 return EX_ILLEGAL_ARGUMENT;
49 }
50 }
51
queryEffect(const AudioUuid * in_impl_uuid,Descriptor * _aidl_return)52 extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
53 if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEnvReverbSw()) {
54 LOG(ERROR) << __func__ << "uuid not supported";
55 return EX_ILLEGAL_ARGUMENT;
56 }
57 *_aidl_return = EnvReverbSw::kDescriptor;
58 return EX_NONE;
59 }
60
61 namespace aidl::android::hardware::audio::effect {
62
63 const std::string EnvReverbSw::kEffectName = "EnvReverbSw";
64
65 const std::vector<Range::EnvironmentalReverbRange> EnvReverbSw::kRanges = {
66 MAKE_RANGE(EnvironmentalReverb, roomLevelMb, -6000, 0),
67 MAKE_RANGE(EnvironmentalReverb, roomHfLevelMb, -4000, 0),
68 MAKE_RANGE(EnvironmentalReverb, decayTimeMs, 0, 7000),
69 MAKE_RANGE(EnvironmentalReverb, decayHfRatioPm, 100, 2000),
70 MAKE_RANGE(EnvironmentalReverb, reflectionsLevelMb, -6000, 0),
71 MAKE_RANGE(EnvironmentalReverb, reflectionsDelayMs, 0, 65),
72 MAKE_RANGE(EnvironmentalReverb, levelMb, -6000, 0),
73 MAKE_RANGE(EnvironmentalReverb, delayMs, 0, 65),
74 MAKE_RANGE(EnvironmentalReverb, diffusionPm, 0, 1000),
75 MAKE_RANGE(EnvironmentalReverb, densityPm, 0, 1000)};
76
77 const Capability EnvReverbSw::kCapability = {
78 .range = Range::make<Range::environmentalReverb>(EnvReverbSw::kRanges)};
79
80 const Descriptor EnvReverbSw::kDescriptor = {
81 .common = {.id = {.type = getEffectTypeUuidEnvReverb(),
82 .uuid = getEffectImplUuidEnvReverbSw(),
83 .proxy = std::nullopt},
84 .flags = {.type = Flags::Type::INSERT,
85 .insert = Flags::Insert::FIRST,
86 .volume = Flags::Volume::CTRL},
87 .name = EnvReverbSw::kEffectName,
88 .implementor = "The Android Open Source Project"},
89 .capability = EnvReverbSw::kCapability};
90
getDescriptor(Descriptor * _aidl_return)91 ndk::ScopedAStatus EnvReverbSw::getDescriptor(Descriptor* _aidl_return) {
92 LOG(DEBUG) << __func__ << kDescriptor.toString();
93 *_aidl_return = kDescriptor;
94 return ndk::ScopedAStatus::ok();
95 }
96
setParameterSpecific(const Parameter::Specific & specific)97 ndk::ScopedAStatus EnvReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
98 RETURN_IF(Parameter::Specific::environmentalReverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
99 "EffectNotSupported");
100
101 auto& erParam = specific.get<Parameter::Specific::environmentalReverb>();
102 RETURN_IF(!inRange(erParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
103 auto tag = erParam.getTag();
104 switch (tag) {
105 case EnvironmentalReverb::roomLevelMb: {
106 RETURN_IF(mContext->setErRoomLevel(erParam.get<EnvironmentalReverb::roomLevelMb>()) !=
107 RetCode::SUCCESS,
108 EX_ILLEGAL_ARGUMENT, "setRoomLevelFailed");
109 return ndk::ScopedAStatus::ok();
110 }
111 case EnvironmentalReverb::roomHfLevelMb: {
112 RETURN_IF(
113 mContext->setErRoomHfLevel(erParam.get<EnvironmentalReverb::roomHfLevelMb>()) !=
114 RetCode::SUCCESS,
115 EX_ILLEGAL_ARGUMENT, "setRoomHfLevelFailed");
116 return ndk::ScopedAStatus::ok();
117 }
118 case EnvironmentalReverb::decayTimeMs: {
119 RETURN_IF(mContext->setErDecayTime(erParam.get<EnvironmentalReverb::decayTimeMs>()) !=
120 RetCode::SUCCESS,
121 EX_ILLEGAL_ARGUMENT, "setDecayTimeFailed");
122 return ndk::ScopedAStatus::ok();
123 }
124 case EnvironmentalReverb::decayHfRatioPm: {
125 RETURN_IF(
126 mContext->setErDecayHfRatio(
127 erParam.get<EnvironmentalReverb::decayHfRatioPm>()) != RetCode::SUCCESS,
128 EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
129 return ndk::ScopedAStatus::ok();
130 }
131 case EnvironmentalReverb::reflectionsLevelMb: {
132 RETURN_IF(mContext->setErReflectionsLevel(
133 erParam.get<EnvironmentalReverb::reflectionsLevelMb>()) !=
134 RetCode::SUCCESS,
135 EX_ILLEGAL_ARGUMENT, "setReflectionsLevelFailed");
136 return ndk::ScopedAStatus::ok();
137 }
138 case EnvironmentalReverb::reflectionsDelayMs: {
139 RETURN_IF(mContext->setErReflectionsDelay(
140 erParam.get<EnvironmentalReverb::reflectionsDelayMs>()) !=
141 RetCode::SUCCESS,
142 EX_ILLEGAL_ARGUMENT, "setReflectionsDelayFailed");
143 return ndk::ScopedAStatus::ok();
144 }
145 case EnvironmentalReverb::levelMb: {
146 RETURN_IF(mContext->setErLevel(erParam.get<EnvironmentalReverb::levelMb>()) !=
147 RetCode::SUCCESS,
148 EX_ILLEGAL_ARGUMENT, "setLevelFailed");
149 return ndk::ScopedAStatus::ok();
150 }
151 case EnvironmentalReverb::delayMs: {
152 RETURN_IF(mContext->setErDelay(erParam.get<EnvironmentalReverb::delayMs>()) !=
153 RetCode::SUCCESS,
154 EX_ILLEGAL_ARGUMENT, "setDelayFailed");
155 return ndk::ScopedAStatus::ok();
156 }
157 case EnvironmentalReverb::diffusionPm: {
158 RETURN_IF(mContext->setErDiffusion(erParam.get<EnvironmentalReverb::diffusionPm>()) !=
159 RetCode::SUCCESS,
160 EX_ILLEGAL_ARGUMENT, "setDiffusionFailed");
161 return ndk::ScopedAStatus::ok();
162 }
163 case EnvironmentalReverb::densityPm: {
164 RETURN_IF(mContext->setErDensity(erParam.get<EnvironmentalReverb::densityPm>()) !=
165 RetCode::SUCCESS,
166 EX_ILLEGAL_ARGUMENT, "setDensityFailed");
167 return ndk::ScopedAStatus::ok();
168 }
169 case EnvironmentalReverb::bypass: {
170 RETURN_IF(mContext->setErBypass(erParam.get<EnvironmentalReverb::bypass>()) !=
171 RetCode::SUCCESS,
172 EX_ILLEGAL_ARGUMENT, "setBypassFailed");
173 return ndk::ScopedAStatus::ok();
174 }
175 default: {
176 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
177 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
178 EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
179 }
180 }
181 }
182
getParameterSpecific(const Parameter::Id & id,Parameter::Specific * specific)183 ndk::ScopedAStatus EnvReverbSw::getParameterSpecific(const Parameter::Id& id,
184 Parameter::Specific* specific) {
185 auto tag = id.getTag();
186 RETURN_IF(Parameter::Id::environmentalReverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
187 auto erId = id.get<Parameter::Id::environmentalReverbTag>();
188 auto erIdTag = erId.getTag();
189 switch (erIdTag) {
190 case EnvironmentalReverb::Id::commonTag:
191 return getParameterEnvironmentalReverb(erId.get<EnvironmentalReverb::Id::commonTag>(),
192 specific);
193 default:
194 LOG(ERROR) << __func__ << " unsupported tag: " << toString(erIdTag);
195 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
196 EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
197 }
198 }
199
getParameterEnvironmentalReverb(const EnvironmentalReverb::Tag & tag,Parameter::Specific * specific)200 ndk::ScopedAStatus EnvReverbSw::getParameterEnvironmentalReverb(const EnvironmentalReverb::Tag& tag,
201 Parameter::Specific* specific) {
202 RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
203 EnvironmentalReverb erParam;
204 switch (tag) {
205 case EnvironmentalReverb::roomLevelMb: {
206 erParam.set<EnvironmentalReverb::roomLevelMb>(mContext->getErRoomLevel());
207 break;
208 }
209 case EnvironmentalReverb::roomHfLevelMb: {
210 erParam.set<EnvironmentalReverb::roomHfLevelMb>(mContext->getErRoomHfLevel());
211 break;
212 }
213 case EnvironmentalReverb::decayTimeMs: {
214 erParam.set<EnvironmentalReverb::decayTimeMs>(mContext->getErDecayTime());
215 break;
216 }
217 case EnvironmentalReverb::decayHfRatioPm: {
218 erParam.set<EnvironmentalReverb::decayHfRatioPm>(mContext->getErDecayHfRatio());
219 break;
220 }
221 case EnvironmentalReverb::reflectionsLevelMb: {
222 erParam.set<EnvironmentalReverb::reflectionsLevelMb>(mContext->getErReflectionsLevel());
223 break;
224 }
225 case EnvironmentalReverb::reflectionsDelayMs: {
226 erParam.set<EnvironmentalReverb::reflectionsDelayMs>(mContext->getErReflectionsDelay());
227 break;
228 }
229 case EnvironmentalReverb::levelMb: {
230 erParam.set<EnvironmentalReverb::levelMb>(mContext->getErLevel());
231 break;
232 }
233 case EnvironmentalReverb::delayMs: {
234 erParam.set<EnvironmentalReverb::delayMs>(mContext->getErDelay());
235 break;
236 }
237 case EnvironmentalReverb::diffusionPm: {
238 erParam.set<EnvironmentalReverb::diffusionPm>(mContext->getErDiffusion());
239 break;
240 }
241 case EnvironmentalReverb::densityPm: {
242 erParam.set<EnvironmentalReverb::densityPm>(mContext->getErDensity());
243 break;
244 }
245 case EnvironmentalReverb::bypass: {
246 erParam.set<EnvironmentalReverb::bypass>(mContext->getErBypass());
247 break;
248 }
249 default: {
250 LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
251 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
252 EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
253 }
254 }
255
256 specific->set<Parameter::Specific::environmentalReverb>(erParam);
257 return ndk::ScopedAStatus::ok();
258 }
259
createContext(const Parameter::Common & common)260 std::shared_ptr<EffectContext> EnvReverbSw::createContext(const Parameter::Common& common) {
261 if (mContext) {
262 LOG(DEBUG) << __func__ << " context already exist";
263 } else {
264 mContext = std::make_shared<EnvReverbSwContext>(1 /* statusFmqDepth */, common);
265 }
266
267 return mContext;
268 }
269
getContext()270 std::shared_ptr<EffectContext> EnvReverbSw::getContext() {
271 return mContext;
272 }
273
releaseContext()274 RetCode EnvReverbSw::releaseContext() {
275 if (mContext) {
276 mContext.reset();
277 }
278 return RetCode::SUCCESS;
279 }
280
281 // Processing method running in EffectWorker thread.
effectProcessImpl(float * in,float * out,int samples)282 IEffect::Status EnvReverbSw::effectProcessImpl(float* in, float* out, int samples) {
283 // TODO: get data buffer and process.
284 LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
285 for (int i = 0; i < samples; i++) {
286 *out++ = *in++;
287 }
288 return {STATUS_OK, samples, samples};
289 }
290
setErRoomLevel(int roomLevel)291 RetCode EnvReverbSwContext::setErRoomLevel(int roomLevel) {
292 mRoomLevel = roomLevel;
293 return RetCode::SUCCESS;
294 }
295
setErRoomHfLevel(int roomHfLevel)296 RetCode EnvReverbSwContext::setErRoomHfLevel(int roomHfLevel) {
297 mRoomHfLevel = roomHfLevel;
298 return RetCode::SUCCESS;
299 }
300
setErDecayTime(int decayTime)301 RetCode EnvReverbSwContext::setErDecayTime(int decayTime) {
302 mDecayTime = decayTime;
303 return RetCode::SUCCESS;
304 }
305
setErDecayHfRatio(int decayHfRatio)306 RetCode EnvReverbSwContext::setErDecayHfRatio(int decayHfRatio) {
307 mDecayHfRatio = decayHfRatio;
308 return RetCode::SUCCESS;
309 }
310
setErLevel(int level)311 RetCode EnvReverbSwContext::setErLevel(int level) {
312 mLevel = level;
313 return RetCode::SUCCESS;
314 }
315
setErDelay(int delay)316 RetCode EnvReverbSwContext::setErDelay(int delay) {
317 mDelay = delay;
318 return RetCode::SUCCESS;
319 }
320
setErDiffusion(int diffusion)321 RetCode EnvReverbSwContext::setErDiffusion(int diffusion) {
322 mDiffusion = diffusion;
323 return RetCode::SUCCESS;
324 }
325
setErDensity(int density)326 RetCode EnvReverbSwContext::setErDensity(int density) {
327 mDensity = density;
328 return RetCode::SUCCESS;
329 }
330
331 } // namespace aidl::android::hardware::audio::effect
332