blob: ea0258a1d18b87caed138f87ecf62de3398431d1 [file] [log] [blame]
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -08001/*
2 * Copyright (C) 2015 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
jiabin9ccb28b2019-07-31 09:59:09 -070017#define LOG_TAG "AudioGain"
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -080018//#define LOG_NDEBUG 0
19
20//#define VERY_VERBOSE_LOGGING
21#ifdef VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
26
jiabin49e69a12019-10-15 16:04:13 -070027#include <algorithm>
28
jiabin9ccb28b2019-07-31 09:59:09 -070029#include <android-base/stringprintf.h>
30#include <media/AudioGain.h>
François Gaffiead3183e2015-03-18 16:55:35 +010031#include <utils/Log.h>
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -080032
33#include <math.h>
34
35namespace android {
36
Mikhail Naganov866c77d2021-07-30 15:11:35 -070037AudioGain::AudioGain(int index, bool isInput)
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -080038{
39 mIndex = index;
Mikhail Naganov866c77d2021-07-30 15:11:35 -070040 mIsInput = isInput;
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -080041 memset(&mGain, 0, sizeof(struct audio_gain));
42}
43
44void AudioGain::getDefaultConfig(struct audio_gain_config *config)
45{
46 config->index = mIndex;
47 config->mode = mGain.mode;
48 config->channel_mask = mGain.channel_mask;
49 if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
50 config->values[0] = mGain.default_value;
51 } else {
Mikhail Naganov866c77d2021-07-30 15:11:35 -070052 const uint32_t numValues = mIsInput ?
53 audio_channel_count_from_in_mask(mGain.channel_mask) :
54 audio_channel_count_from_out_mask(mGain.channel_mask);
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -080055 for (size_t i = 0; i < numValues; i++) {
56 config->values[i] = mGain.default_value;
57 }
58 }
59 if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
60 config->ramp_duration_ms = mGain.min_ramp_ms;
61 }
62}
63
64status_t AudioGain::checkConfig(const struct audio_gain_config *config)
65{
66 if ((config->mode & ~mGain.mode) != 0) {
67 return BAD_VALUE;
68 }
69 if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
70 if ((config->values[0] < mGain.min_value) ||
71 (config->values[0] > mGain.max_value)) {
72 return BAD_VALUE;
73 }
74 } else {
75 if ((config->channel_mask & ~mGain.channel_mask) != 0) {
76 return BAD_VALUE;
77 }
Mikhail Naganov866c77d2021-07-30 15:11:35 -070078 const uint32_t numValues = mIsInput ?
79 audio_channel_count_from_in_mask(config->channel_mask) :
80 audio_channel_count_from_out_mask(config->channel_mask);
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -080081 for (size_t i = 0; i < numValues; i++) {
82 if ((config->values[i] < mGain.min_value) ||
83 (config->values[i] > mGain.max_value)) {
84 return BAD_VALUE;
85 }
86 }
87 }
88 if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
89 if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
90 (config->ramp_duration_ms > mGain.max_ramp_ms)) {
91 return BAD_VALUE;
92 }
93 }
94 return NO_ERROR;
95}
96
jiabin9ccb28b2019-07-31 09:59:09 -070097void AudioGain::dump(std::string *dst, int spaces, int index) const
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -080098{
jiabin9ccb28b2019-07-31 09:59:09 -070099 dst->append(base::StringPrintf("%*sGain %d:\n", spaces, "", index+1));
100 dst->append(base::StringPrintf("%*s- mode: %08x\n", spaces, "", mGain.mode));
101 dst->append(base::StringPrintf("%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask));
102 dst->append(base::StringPrintf("%*s- min_value: %d mB\n", spaces, "", mGain.min_value));
103 dst->append(base::StringPrintf("%*s- max_value: %d mB\n", spaces, "", mGain.max_value));
104 dst->append(base::StringPrintf("%*s- default_value: %d mB\n", spaces, "", mGain.default_value));
105 dst->append(base::StringPrintf("%*s- step_value: %d mB\n", spaces, "", mGain.step_value));
106 dst->append(base::StringPrintf("%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms));
107 dst->append(base::StringPrintf("%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms));
Jean-Michel Trivi56ec4ff2015-01-23 16:45:18 -0800108}
109
jiabin49e69a12019-10-15 16:04:13 -0700110bool AudioGain::equals(const sp<AudioGain>& other) const
111{
112 return other != nullptr &&
Mikhail Naganov866c77d2021-07-30 15:11:35 -0700113 mIsInput == other->mIsInput &&
jiabin49e69a12019-10-15 16:04:13 -0700114 mUseForVolume == other->mUseForVolume &&
115 // Compare audio gain
116 mGain.mode == other->mGain.mode &&
117 mGain.channel_mask == other->mGain.channel_mask &&
118 mGain.min_value == other->mGain.min_value &&
119 mGain.max_value == other->mGain.max_value &&
120 mGain.default_value == other->mGain.default_value &&
121 mGain.step_value == other->mGain.step_value &&
122 mGain.min_ramp_ms == other->mGain.min_ramp_ms &&
123 mGain.max_ramp_ms == other->mGain.max_ramp_ms;
124}
125
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800126status_t AudioGain::writeToParcel(android::Parcel *parcel) const {
127 media::AudioGain parcelable;
128 return writeToParcelable(&parcelable)
129 ?: parcelable.writeToParcel(parcel);
jiabin84e43c72019-07-31 17:23:17 -0700130}
131
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800132status_t AudioGain::writeToParcelable(media::AudioGain* parcelable) const {
133 parcelable->index = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mIndex));
Mikhail Naganov866c77d2021-07-30 15:11:35 -0700134 parcelable->isInput = mIsInput;
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800135 parcelable->useForVolume = mUseForVolume;
Ytai Ben-Tsvi0cf92652020-11-23 13:23:00 -0800136 parcelable->mode = VALUE_OR_RETURN_STATUS(
Andy Hung973638a2020-12-08 20:47:45 -0800137 legacy2aidl_audio_gain_mode_t_int32_t_mask(mGain.mode));
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800138 parcelable->channelMask = VALUE_OR_RETURN_STATUS(
Mikhail Naganovde3fa182021-07-30 15:06:42 -0700139 legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
Mikhail Naganov866c77d2021-07-30 15:11:35 -0700140 mGain.channel_mask, mIsInput));
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800141 parcelable->minValue = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.min_value));
142 parcelable->maxValue = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.max_value));
143 parcelable->defaultValue = VALUE_OR_RETURN_STATUS(
144 convertIntegral<int32_t>(mGain.default_value));
145 parcelable->stepValue = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.step_value));
146 parcelable->minRampMs = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.min_ramp_ms));
147 parcelable->maxRampMs = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(mGain.max_ramp_ms));
148 return OK;
149}
150
151status_t AudioGain::readFromParcel(const android::Parcel *parcel) {
152 media::AudioGain parcelable;
153 return parcelable.readFromParcel(parcel)
154 ?: readFromParcelable(parcelable);
155}
156
157status_t AudioGain::readFromParcelable(const media::AudioGain& parcelable) {
158 mIndex = VALUE_OR_RETURN_STATUS(convertIntegral<int>(parcelable.index));
Mikhail Naganov866c77d2021-07-30 15:11:35 -0700159 mIsInput = parcelable.isInput;
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800160 mUseForVolume = parcelable.useForVolume;
Ytai Ben-Tsvi0cf92652020-11-23 13:23:00 -0800161 mGain.mode = VALUE_OR_RETURN_STATUS(
162 aidl2legacy_int32_t_audio_gain_mode_t_mask(parcelable.mode));
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800163 mGain.channel_mask = VALUE_OR_RETURN_STATUS(
Mikhail Naganovde3fa182021-07-30 15:06:42 -0700164 aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
Mikhail Naganov866c77d2021-07-30 15:11:35 -0700165 parcelable.channelMask, parcelable.isInput));
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800166 mGain.min_value = VALUE_OR_RETURN_STATUS(convertIntegral<int>(parcelable.minValue));
167 mGain.max_value = VALUE_OR_RETURN_STATUS(convertIntegral<int>(parcelable.maxValue));
168 mGain.default_value = VALUE_OR_RETURN_STATUS(convertIntegral<int>(parcelable.defaultValue));
169 mGain.step_value = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(parcelable.stepValue));
170 mGain.min_ramp_ms = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(parcelable.minRampMs));
171 mGain.max_ramp_ms = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(parcelable.maxRampMs));
172 return OK;
jiabin84e43c72019-07-31 17:23:17 -0700173}
174
jiabin49e69a12019-10-15 16:04:13 -0700175bool AudioGains::equals(const AudioGains &other) const
176{
177 return std::equal(begin(), end(), other.begin(), other.end(),
178 [](const sp<AudioGain>& left, const sp<AudioGain>& right) {
179 return left->equals(right);
180 });
181}
182
jiabin84e43c72019-07-31 17:23:17 -0700183status_t AudioGains::writeToParcel(android::Parcel *parcel) const {
184 status_t status = NO_ERROR;
jiabin17058fa2019-10-08 17:33:38 -0700185 if ((status = parcel->writeVectorSize(*this)) != NO_ERROR) return status;
jiabin84e43c72019-07-31 17:23:17 -0700186 for (const auto &audioGain : *this) {
187 if ((status = parcel->writeParcelable(*audioGain)) != NO_ERROR) {
188 break;
189 }
190 }
191 return status;
192}
193
194status_t AudioGains::readFromParcel(const android::Parcel *parcel) {
195 status_t status = NO_ERROR;
jiabin17058fa2019-10-08 17:33:38 -0700196 this->clear();
197 if ((status = parcel->resizeOutVector(this)) != NO_ERROR) return status;
198 for (size_t i = 0; i < this->size(); i++) {
199 this->at(i) = new AudioGain(0, false);
200 if ((status = parcel->readParcelable(this->at(i).get())) != NO_ERROR) {
jiabin84e43c72019-07-31 17:23:17 -0700201 this->clear();
202 break;
203 }
jiabin84e43c72019-07-31 17:23:17 -0700204 }
205 return status;
206}
207
Ytai Ben-Tsvi50e016a2020-11-12 14:26:12 -0800208ConversionResult<sp<AudioGain>>
209aidl2legacy_AudioGain(const media::AudioGain& aidl) {
210 sp<AudioGain> legacy = new AudioGain(0, false);
211 status_t status = legacy->readFromParcelable(aidl);
212 if (status != OK) {
213 return base::unexpected(status);
214 }
215 return legacy;
216}
217
218ConversionResult<media::AudioGain>
219legacy2aidl_AudioGain(const sp<AudioGain>& legacy) {
220 media::AudioGain aidl;
221 status_t status = legacy->writeToParcelable(&aidl);
222 if (status != OK) {
223 return base::unexpected(status);
224 }
225 return aidl;
226}
227
228ConversionResult<AudioGains>
229aidl2legacy_AudioGains(const std::vector<media::AudioGain>& aidl) {
230 return convertContainer<AudioGains>(aidl, aidl2legacy_AudioGain);
231}
232
233ConversionResult<std::vector<media::AudioGain>>
234legacy2aidl_AudioGains(const AudioGains& legacy) {
235 return convertContainer<std::vector<media::AudioGain>>(legacy, legacy2aidl_AudioGain);
236}
237
Mikhail Naganov1b2a7942017-12-08 10:18:09 -0800238} // namespace android