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 <aidl/android/hardware/audio/effect/DynamicsProcessing.h>
18 #include <aidl/android/hardware/audio/effect/Range.h>
19
20 #include "EffectRangeSpecific.h"
21 #include "effect-impl/EffectRange.h"
22
23 namespace aidl::android::hardware::audio::effect {
24
25 namespace DynamicsProcessingRanges {
26
isInputGainConfigInRange(const std::vector<DynamicsProcessing::InputGain> & cfgs,const DynamicsProcessing::InputGain & min,const DynamicsProcessing::InputGain & max)27 static bool isInputGainConfigInRange(const std::vector<DynamicsProcessing::InputGain>& cfgs,
28 const DynamicsProcessing::InputGain& min,
29 const DynamicsProcessing::InputGain& max) {
30 auto func = [](const DynamicsProcessing::InputGain& arg) {
31 return std::make_tuple(arg.channel, arg.gainDb);
32 };
33 return isTupleInRange(cfgs, min, max, func);
34 }
35
isLimiterConfigInRange(const std::vector<DynamicsProcessing::LimiterConfig> & cfgs,const DynamicsProcessing::LimiterConfig & min,const DynamicsProcessing::LimiterConfig & max)36 static bool isLimiterConfigInRange(const std::vector<DynamicsProcessing::LimiterConfig>& cfgs,
37 const DynamicsProcessing::LimiterConfig& min,
38 const DynamicsProcessing::LimiterConfig& max) {
39 auto func = [](const DynamicsProcessing::LimiterConfig& arg) {
40 return std::make_tuple(arg.channel, arg.enable, arg.linkGroup, arg.attackTimeMs,
41 arg.releaseTimeMs, arg.ratio, arg.thresholdDb, arg.postGainDb);
42 };
43 return isTupleInRange(cfgs, min, max, func);
44 }
45
isMbcBandConfigInRange(const std::vector<DynamicsProcessing::MbcBandConfig> & cfgs,const DynamicsProcessing::MbcBandConfig & min,const DynamicsProcessing::MbcBandConfig & max)46 static bool isMbcBandConfigInRange(const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs,
47 const DynamicsProcessing::MbcBandConfig& min,
48 const DynamicsProcessing::MbcBandConfig& max) {
49 auto func = [](const DynamicsProcessing::MbcBandConfig& arg) {
50 return std::make_tuple(arg.channel, arg.band, arg.enable, arg.cutoffFrequencyHz,
51 arg.attackTimeMs, arg.releaseTimeMs, arg.ratio, arg.thresholdDb,
52 arg.kneeWidthDb, arg.noiseGateThresholdDb, arg.expanderRatio,
53 arg.preGainDb, arg.postGainDb);
54 };
55 return isTupleInRange(cfgs, min, max, func);
56 }
57
isEqBandConfigInRange(const std::vector<DynamicsProcessing::EqBandConfig> & cfgs,const DynamicsProcessing::EqBandConfig & min,const DynamicsProcessing::EqBandConfig & max)58 static bool isEqBandConfigInRange(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
59 const DynamicsProcessing::EqBandConfig& min,
60 const DynamicsProcessing::EqBandConfig& max) {
61 auto func = [](const DynamicsProcessing::EqBandConfig& arg) {
62 return std::make_tuple(arg.channel, arg.band, arg.enable, arg.cutoffFrequencyHz,
63 arg.gainDb);
64 };
65 return isTupleInRange(cfgs, min, max, func);
66 }
67
isChannelConfigInRange(const std::vector<DynamicsProcessing::ChannelConfig> & cfgs,const DynamicsProcessing::ChannelConfig & min,const DynamicsProcessing::ChannelConfig & max)68 static bool isChannelConfigInRange(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs,
69 const DynamicsProcessing::ChannelConfig& min,
70 const DynamicsProcessing::ChannelConfig& max) {
71 auto func = [](const DynamicsProcessing::ChannelConfig& arg) {
72 return std::make_tuple(arg.channel, arg.enable);
73 };
74 return isTupleInRange(cfgs, min, max, func);
75 }
76
isEngineConfigInRange(const DynamicsProcessing::EngineArchitecture & cfg,const DynamicsProcessing::EngineArchitecture & min,const DynamicsProcessing::EngineArchitecture & max)77 static bool isEngineConfigInRange(const DynamicsProcessing::EngineArchitecture& cfg,
78 const DynamicsProcessing::EngineArchitecture& min,
79 const DynamicsProcessing::EngineArchitecture& max) {
80 auto func = [](const DynamicsProcessing::EngineArchitecture& arg) {
81 return std::make_tuple(arg.resolutionPreference, arg.preferredProcessingDurationMs,
82 arg.preEqStage.inUse, arg.preEqStage.bandCount,
83 arg.postEqStage.inUse, arg.postEqStage.bandCount, arg.mbcStage.inUse,
84 arg.mbcStage.bandCount, arg.limiterInUse);
85 };
86 return isTupleInRange(func(cfg), func(min), func(max));
87 }
88
locateMinMaxForTag(DynamicsProcessing::Tag tag,const std::vector<Range::DynamicsProcessingRange> & ranges)89 static int locateMinMaxForTag(DynamicsProcessing::Tag tag,
90 const std::vector<Range::DynamicsProcessingRange>& ranges) {
91 for (int i = 0; i < (int)ranges.size(); i++) {
92 if (tag == ranges[i].min.getTag() && tag == ranges[i].max.getTag()) {
93 return i;
94 }
95 }
96 return -1;
97 }
98
isParamInRange(const DynamicsProcessing & dp,const std::vector<Range::DynamicsProcessingRange> & ranges)99 bool isParamInRange(const DynamicsProcessing& dp,
100 const std::vector<Range::DynamicsProcessingRange>& ranges) {
101 auto tag = dp.getTag();
102 int i = locateMinMaxForTag(tag, ranges);
103 if (i == -1) return true;
104
105 switch (tag) {
106 case DynamicsProcessing::engineArchitecture: {
107 return isEngineConfigInRange(
108 dp.get<DynamicsProcessing::engineArchitecture>(),
109 ranges[i].min.get<DynamicsProcessing::engineArchitecture>(),
110 ranges[i].max.get<DynamicsProcessing::engineArchitecture>());
111 }
112 case DynamicsProcessing::preEq: {
113 return isChannelConfigInRange(dp.get<DynamicsProcessing::preEq>(),
114 ranges[i].min.get<DynamicsProcessing::preEq>()[0],
115 ranges[i].max.get<DynamicsProcessing::preEq>()[0]);
116 }
117 case DynamicsProcessing::postEq: {
118 return isChannelConfigInRange(dp.get<DynamicsProcessing::postEq>(),
119 ranges[i].min.get<DynamicsProcessing::postEq>()[0],
120 ranges[i].max.get<DynamicsProcessing::postEq>()[0]);
121 }
122 case DynamicsProcessing::mbc: {
123 return isChannelConfigInRange(dp.get<DynamicsProcessing::mbc>(),
124 ranges[i].min.get<DynamicsProcessing::mbc>()[0],
125 ranges[i].max.get<DynamicsProcessing::mbc>()[0]);
126 }
127 case DynamicsProcessing::preEqBand: {
128 return isEqBandConfigInRange(dp.get<DynamicsProcessing::preEqBand>(),
129 ranges[i].min.get<DynamicsProcessing::preEqBand>()[0],
130 ranges[i].max.get<DynamicsProcessing::preEqBand>()[0]);
131 }
132 case DynamicsProcessing::postEqBand: {
133 return isEqBandConfigInRange(dp.get<DynamicsProcessing::postEqBand>(),
134 ranges[i].min.get<DynamicsProcessing::postEqBand>()[0],
135 ranges[i].max.get<DynamicsProcessing::postEqBand>()[0]);
136 }
137 case DynamicsProcessing::mbcBand: {
138 return isMbcBandConfigInRange(dp.get<DynamicsProcessing::mbcBand>(),
139 ranges[i].min.get<DynamicsProcessing::mbcBand>()[0],
140 ranges[i].max.get<DynamicsProcessing::mbcBand>()[0]);
141 }
142 case DynamicsProcessing::limiter: {
143 return isLimiterConfigInRange(dp.get<DynamicsProcessing::limiter>(),
144 ranges[i].min.get<DynamicsProcessing::limiter>()[0],
145 ranges[i].max.get<DynamicsProcessing::limiter>()[0]);
146 }
147 case DynamicsProcessing::inputGain: {
148 return isInputGainConfigInRange(dp.get<DynamicsProcessing::inputGain>(),
149 ranges[i].min.get<DynamicsProcessing::inputGain>()[0],
150 ranges[i].max.get<DynamicsProcessing::inputGain>()[0]);
151 }
152 default: {
153 return true;
154 }
155 }
156 return true;
157 }
158
159 } // namespace DynamicsProcessingRanges
160
161 } // namespace aidl::android::hardware::audio::effect