156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi/*
256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Copyright (C) 2015 The Android Open Source Project
356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * you may not use this file except in compliance with the License.
656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * You may obtain a copy of the License at
756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
1056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * See the License for the specific language governing permissions and
1456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * limitations under the License.
1556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi */
1656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
1798cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie#define LOG_TAG "APM::AudioGain"
1856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi//#define LOG_NDEBUG 0
1956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
2056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi//#define VERY_VERBOSE_LOGGING
2156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#ifdef VERY_VERBOSE_LOGGING
2256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#define ALOGVV ALOGV
2356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#else
2456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#define ALOGVV(a...) do { } while(0)
2556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#endif
2656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
2798cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie#include "AudioGain.h"
28ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include <utils/Log.h>
29ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include <utils/String8.h>
3056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
3156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#include <math.h>
3256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
3356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivinamespace android {
3456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
3556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel TriviAudioGain::AudioGain(int index, bool useInChannelMask)
3656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
3756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mIndex = index;
3856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mUseInChannelMask = useInChannelMask;
3956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    memset(&mGain, 0, sizeof(struct audio_gain));
4056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
4156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
4256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioGain::getDefaultConfig(struct audio_gain_config *config)
4356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
4456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    config->index = mIndex;
4556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    config->mode = mGain.mode;
4656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    config->channel_mask = mGain.channel_mask;
4756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
4856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        config->values[0] = mGain.default_value;
4956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
5056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        uint32_t numValues;
5156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mUseInChannelMask) {
5256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            numValues = audio_channel_count_from_in_mask(mGain.channel_mask);
5356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else {
5456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            numValues = audio_channel_count_from_out_mask(mGain.channel_mask);
5556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
5656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < numValues; i++) {
5756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            config->values[i] = mGain.default_value;
5856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
5956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
6056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
6156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        config->ramp_duration_ms = mGain.min_ramp_ms;
6256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
6356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
6456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
6556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t AudioGain::checkConfig(const struct audio_gain_config *config)
6656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
6756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if ((config->mode & ~mGain.mode) != 0) {
6856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return BAD_VALUE;
6956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
7056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
7156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((config->values[0] < mGain.min_value) ||
7256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    (config->values[0] > mGain.max_value)) {
7356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return BAD_VALUE;
7456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
7556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    } else {
7656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((config->channel_mask & ~mGain.channel_mask) != 0) {
7756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return BAD_VALUE;
7856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
7956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        uint32_t numValues;
8056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if (mUseInChannelMask) {
8156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            numValues = audio_channel_count_from_in_mask(config->channel_mask);
8256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        } else {
8356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            numValues = audio_channel_count_from_out_mask(config->channel_mask);
8456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
8556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < numValues; i++) {
8656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            if ((config->values[i] < mGain.min_value) ||
8756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    (config->values[i] > mGain.max_value)) {
8856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                return BAD_VALUE;
8956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            }
9056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
9156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
9256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
9356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
9456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi                    (config->ramp_duration_ms > mGain.max_ramp_ms)) {
9556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            return BAD_VALUE;
9656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
9756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
9856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return NO_ERROR;
9956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
10056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid AudioGain::dump(int fd, int spaces, int index) const
10256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
10356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    const size_t SIZE = 256;
10456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    char buffer[SIZE];
10556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    String8 result;
10656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1);
10856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
10956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode);
11056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
11156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask);
11256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
11356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value);
11456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
11556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value);
11656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
11756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value);
11856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
11956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value);
12056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
12156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms);
12256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
12356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms);
12456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
12556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
12656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    write(fd, result.string(), result.size());
12756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
12856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
12956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}; // namespace android
130