audio: remove effects and tests
* See [1] and [2] for reference and comments. [1]:346a56239e[2]:765b1a3a3d
This commit is contained in:
@@ -202,94 +202,6 @@ cc_binary {
|
||||
installable: false, //installed in apex com.android.hardware.audio
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "audio_policy_config_xml_converter_tests",
|
||||
vendor_available: true,
|
||||
defaults: [
|
||||
"latest_android_media_audio_common_types_ndk_static",
|
||||
"latest_android_hardware_audio_core_ndk_static",
|
||||
],
|
||||
shared_libs: [
|
||||
"libaudio_aidl_conversion_common_ndk",
|
||||
"libaudioaidlcommon",
|
||||
"libaudioutils",
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"libmedia_helper",
|
||||
"libstagefright_foundation",
|
||||
"libutils",
|
||||
"libxml2",
|
||||
],
|
||||
header_libs: [
|
||||
"libaudio_system_headers",
|
||||
"libaudioaidl_headers",
|
||||
"libxsdc-utils",
|
||||
],
|
||||
generated_sources: [
|
||||
"audio_policy_configuration_aidl_default",
|
||||
"audio_policy_engine_configuration_aidl_default",
|
||||
],
|
||||
generated_headers: [
|
||||
"audio_policy_configuration_aidl_default",
|
||||
"audio_policy_engine_configuration_aidl_default",
|
||||
],
|
||||
srcs: [
|
||||
"AudioPolicyConfigXmlConverter.cpp",
|
||||
"tests/AudioPolicyConfigXmlConverterTest.cpp",
|
||||
],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
"-Wthread-safety",
|
||||
"-DBACKEND_NDK",
|
||||
],
|
||||
test_suites: ["general-tests"],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "audio_alsa_utils_tests",
|
||||
vendor_available: true,
|
||||
defaults: [
|
||||
"latest_android_media_audio_common_types_ndk_static",
|
||||
"latest_android_hardware_audio_core_ndk_static",
|
||||
],
|
||||
static_libs: [
|
||||
"libalsautilsv2",
|
||||
"libtinyalsav2",
|
||||
],
|
||||
shared_libs: [
|
||||
"libaudio_aidl_conversion_common_ndk",
|
||||
"libaudioaidlcommon",
|
||||
"libaudioutils",
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"libmedia_helper",
|
||||
"libstagefright_foundation",
|
||||
"libutils",
|
||||
],
|
||||
header_libs: [
|
||||
"libaudio_system_headers",
|
||||
"libaudioaidl_headers",
|
||||
],
|
||||
srcs: [
|
||||
"alsa/Utils.cpp",
|
||||
"tests/AlsaUtilsTest.cpp",
|
||||
],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
"-Wthread-safety",
|
||||
"-DBACKEND_NDK",
|
||||
],
|
||||
test_suites: ["general-tests"],
|
||||
}
|
||||
|
||||
cc_defaults {
|
||||
name: "aidlaudioeffectservice_defaults",
|
||||
defaults: [
|
||||
@@ -324,15 +236,6 @@ cc_defaults {
|
||||
],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "effectCommonFile",
|
||||
srcs: [
|
||||
"EffectContext.cpp",
|
||||
"EffectThread.cpp",
|
||||
"EffectImpl.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.audio.effect.service-aidl.example",
|
||||
relative_install_path: "hw",
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
||||
#define LOG_TAG "AHAL_AcousticEchoCancelerSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "AcousticEchoCancelerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::AcousticEchoCancelerSw;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidAcousticEchoCancelerSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::Range;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidAcousticEchoCancelerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<AcousticEchoCancelerSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidAcousticEchoCancelerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = AcousticEchoCancelerSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string AcousticEchoCancelerSw::kEffectName = "AcousticEchoCancelerSw";
|
||||
|
||||
const std::vector<Range::AcousticEchoCancelerRange> AcousticEchoCancelerSw::kRanges = {
|
||||
MAKE_RANGE(AcousticEchoCanceler, echoDelayUs, 0, 500),
|
||||
/* mobile mode not supported, and not settable */
|
||||
MAKE_RANGE(AcousticEchoCanceler, mobileMode, false, false)};
|
||||
|
||||
const Capability AcousticEchoCancelerSw::kCapability = {.range = AcousticEchoCancelerSw::kRanges};
|
||||
|
||||
const Descriptor AcousticEchoCancelerSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidAcousticEchoCanceler(),
|
||||
.uuid = getEffectImplUuidAcousticEchoCancelerSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::PRE_PROC,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::NONE},
|
||||
.name = AcousticEchoCancelerSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = AcousticEchoCancelerSw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus AcousticEchoCancelerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AcousticEchoCancelerSw::setParameterSpecific(
|
||||
const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::acousticEchoCanceler != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& param = specific.get<Parameter::Specific::acousticEchoCanceler>();
|
||||
RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
|
||||
auto tag = param.getTag();
|
||||
switch (tag) {
|
||||
case AcousticEchoCanceler::echoDelayUs: {
|
||||
RETURN_IF(mContext->setEchoDelay(param.get<AcousticEchoCanceler::echoDelayUs>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "echoDelayNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case AcousticEchoCanceler::mobileMode: {
|
||||
RETURN_IF(true == param.get<AcousticEchoCanceler::mobileMode>(), EX_ILLEGAL_ARGUMENT,
|
||||
"SettingmobileModeSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AcousticEchoCancelerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::acousticEchoCancelerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto specificId = id.get<Parameter::Id::acousticEchoCancelerTag>();
|
||||
auto specificIdTag = specificId.getTag();
|
||||
switch (specificIdTag) {
|
||||
case AcousticEchoCanceler::Id::commonTag:
|
||||
return getParameterAcousticEchoCanceler(
|
||||
specificId.get<AcousticEchoCanceler::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AcousticEchoCancelerSw::getParameterAcousticEchoCanceler(
|
||||
const AcousticEchoCanceler::Tag& tag, Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
AcousticEchoCanceler param;
|
||||
switch (tag) {
|
||||
case AcousticEchoCanceler::echoDelayUs: {
|
||||
param.set<AcousticEchoCanceler::echoDelayUs>(mContext->getEchoDelay());
|
||||
break;
|
||||
}
|
||||
case AcousticEchoCanceler::mobileMode: {
|
||||
param.set<AcousticEchoCanceler::mobileMode>(false);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::acousticEchoCanceler>(param);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> AcousticEchoCancelerSw::createContext(
|
||||
const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<AcousticEchoCancelerSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode AcousticEchoCancelerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status AcousticEchoCancelerSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode AcousticEchoCancelerSwContext::setEchoDelay(int echoDelayUs) {
|
||||
mEchoDelayUs = echoDelayUs;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <aidl/android/hardware/audio/effect/Range.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class AcousticEchoCancelerSwContext final : public EffectContext {
|
||||
public:
|
||||
AcousticEchoCancelerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setEchoDelay(int echoDelayUs);
|
||||
int getEchoDelay() const { return mEchoDelayUs; }
|
||||
|
||||
private:
|
||||
int mEchoDelayUs = 0;
|
||||
};
|
||||
|
||||
class AcousticEchoCancelerSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
AcousticEchoCancelerSw() { LOG(DEBUG) << __func__; }
|
||||
~AcousticEchoCancelerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
std::string getEffectName() override { return kEffectName; };
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
|
||||
|
||||
private:
|
||||
static const std::vector<Range::AcousticEchoCancelerRange> kRanges;
|
||||
std::shared_ptr<AcousticEchoCancelerSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
ndk::ScopedAStatus getParameterAcousticEchoCanceler(const AcousticEchoCanceler::Tag& tag,
|
||||
Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libaecsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"AcousticEchoCancelerSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -21,28 +21,6 @@ apex {
|
||||
"android.hardware.audio.service-aidl.example",
|
||||
"android.hardware.audio.effect.service-aidl.example",
|
||||
],
|
||||
native_shared_libs: [
|
||||
"libaecsw",
|
||||
"libagc1sw",
|
||||
"libagc2sw",
|
||||
"libbassboostsw",
|
||||
"libbundleaidl",
|
||||
"libdownmixaidl",
|
||||
"libdynamicsprocessingaidl",
|
||||
"libenvreverbsw",
|
||||
"libequalizersw",
|
||||
"libextensioneffect",
|
||||
"libhapticgeneratoraidl",
|
||||
"libloudnessenhanceraidl",
|
||||
"libnssw",
|
||||
"libpreprocessingaidl",
|
||||
"libpresetreverbsw",
|
||||
"libreverbaidl",
|
||||
"libspatializersw",
|
||||
"libvirtualizersw",
|
||||
"libvisualizeraidl",
|
||||
"libvolumesw",
|
||||
],
|
||||
prebuilts: [
|
||||
"android.hardware.audio.service-aidl.example.rc",
|
||||
"android.hardware.audio.service-aidl.xml",
|
||||
|
||||
@@ -28,27 +28,6 @@
|
||||
name of a library .so file on the target device.
|
||||
-->
|
||||
<libraries>
|
||||
<library name="aecsw" path="libaecsw.so"/>
|
||||
<library name="agc1sw" path="libagc1sw.so"/>
|
||||
<library name="agc2sw" path="libagc2sw.so"/>
|
||||
<library name="bassboostsw" path="libbassboostsw.so"/>
|
||||
<library name="bundle" path="libbundleaidl.so"/>
|
||||
<library name="downmix" path="libdownmixaidl.so"/>
|
||||
<library name="dynamics_processing" path="libdynamicsprocessingaidl.so"/>
|
||||
<library name="equalizersw" path="libequalizersw.so"/>
|
||||
<library name="erasersw" path="liberasersw.so"/>
|
||||
<library name="haptic_generator" path="libhapticgeneratoraidl.so"/>
|
||||
<library name="loudness_enhancer" path="libloudnessenhanceraidl.so"/>
|
||||
<library name="nssw" path="libnssw.so"/>
|
||||
<library name="env_reverbsw" path="libenvreverbsw.so"/>
|
||||
<library name="pre_processing" path="libpreprocessingaidl.so"/>
|
||||
<library name="preset_reverbsw" path="libpresetreverbsw.so"/>
|
||||
<library name="reverb" path="libreverbaidl.so"/>
|
||||
<library name="virtualizersw" path="libvirtualizersw.so"/>
|
||||
<library name="visualizer" path="libvisualizeraidl.so"/>
|
||||
<library name="volumesw" path="libvolumesw.so"/>
|
||||
<library name="extensioneffect" path="libextensioneffect.so"/>
|
||||
<library name="spatializersw" path="libspatializersw.so"/>
|
||||
</libraries>
|
||||
|
||||
<!-- list of effects to load.
|
||||
@@ -72,33 +51,8 @@
|
||||
-->
|
||||
|
||||
<effects>
|
||||
<effect name="automatic_gain_control_v2" library="pre_processing" uuid="89f38e65-d4d2-4d64-ad0e-2b3e799ea886"/>
|
||||
<effect name="bassboost" library="bundle" uuid="8631f300-72e2-11df-b57e-0002a5d5c51b"/>
|
||||
<effect name="downmix" library="downmix" uuid="93f04452-e4fe-41cc-91f9-e475b6d1d69f"/>
|
||||
<effect name="dynamics_processing" library="dynamics_processing" uuid="e0e6539b-1781-7261-676f-6d7573696340"/>
|
||||
<effect name="eraser" library="erasersw" uuid="fa81ab46-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="haptic_generator" library="haptic_generator" uuid="97c4acd1-8b82-4f2f-832e-c2fe5d7a9931"/>
|
||||
<effect name="loudness_enhancer" library="loudness_enhancer" uuid="fa415329-2034-4bea-b5dc-5b381c8d1e2c"/>
|
||||
<effect name="reverb_env_aux" library="reverb" uuid="4a387fc0-8ab3-11df-8bad-0002a5d5c51b"/>
|
||||
<effect name="reverb_env_ins" library="reverb" uuid="c7a511a0-a3bb-11df-860e-0002a5d5c51b"/>
|
||||
<effect name="reverb_pre_aux" library="reverb" uuid="f29a1400-a3bb-11df-8ddc-0002a5d5c51b"/>
|
||||
<effect name="reverb_pre_ins" library="reverb" uuid="172cdf00-a3bc-11df-a72f-0002a5d5c51b"/>
|
||||
<effect name="virtualizer" library="bundle" uuid="1d4033c0-8557-11df-9f2d-0002a5d5c51b"/>
|
||||
<effect name="visualizer" library="visualizer" uuid="d069d9e0-8329-11df-9168-0002a5d5c51b"/>
|
||||
<effect name="volume" library="bundle" uuid="119341a0-8469-11df-81f9-0002a5d5c51b"/>
|
||||
<effect name="equalizer" library="bundle" uuid="ce772f20-847d-11df-bb17-0002a5d5c51b"/>
|
||||
<effect name="extension_effect" library="extensioneffect" uuid="fa81dd00-588b-11ed-9b6a-0242ac120002" type="fa81de0e-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="acoustic_echo_canceler" library="pre_processing" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
|
||||
<effect name="noise_suppression" library="pre_processing" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
|
||||
</effects>
|
||||
|
||||
<preprocess>
|
||||
<stream type="voice_communication">
|
||||
<apply effect="acoustic_echo_canceler"/>
|
||||
<apply effect="noise_suppression"/>
|
||||
</stream>
|
||||
</preprocess>
|
||||
|
||||
<!-- Audio pre processor configurations.
|
||||
The pre processor configuration is described in a "preprocess" element and consists in a
|
||||
list of elements each describing pre processor settings for a given use case or "stream".
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libagc1sw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"AutomaticGainControlV1Sw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AHAL_AutomaticGainControlV1Sw"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "AutomaticGainControlV1Sw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::AutomaticGainControlV1Sw;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidAutomaticGainControlV1Sw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidAutomaticGainControlV1;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidAutomaticGainControlV1Sw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<AutomaticGainControlV1Sw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidAutomaticGainControlV1Sw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = AutomaticGainControlV1Sw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string AutomaticGainControlV1Sw::kEffectName = "AutomaticGainControlV1Sw";
|
||||
|
||||
const std::vector<Range::AutomaticGainControlV1Range> AutomaticGainControlV1Sw::kRanges = {
|
||||
MAKE_RANGE(AutomaticGainControlV1, targetPeakLevelDbFs, -3100, 0),
|
||||
MAKE_RANGE(AutomaticGainControlV1, maxCompressionGainDb, 0, 9000)};
|
||||
|
||||
const Capability AutomaticGainControlV1Sw::kCapability = {
|
||||
.range = AutomaticGainControlV1Sw::kRanges};
|
||||
|
||||
const Descriptor AutomaticGainControlV1Sw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidAutomaticGainControlV1(),
|
||||
.uuid = getEffectImplUuidAutomaticGainControlV1Sw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = AutomaticGainControlV1Sw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = AutomaticGainControlV1Sw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus AutomaticGainControlV1Sw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AutomaticGainControlV1Sw::setParameterSpecific(
|
||||
const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::automaticGainControlV1 != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& param = specific.get<Parameter::Specific::automaticGainControlV1>();
|
||||
RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
auto tag = param.getTag();
|
||||
switch (tag) {
|
||||
case AutomaticGainControlV1::targetPeakLevelDbFs: {
|
||||
RETURN_IF(mContext->setTargetPeakLevel(
|
||||
param.get<AutomaticGainControlV1::targetPeakLevelDbFs>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "targetPeakLevelNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case AutomaticGainControlV1::maxCompressionGainDb: {
|
||||
RETURN_IF(mContext->setMaxCompressionGain(
|
||||
param.get<AutomaticGainControlV1::maxCompressionGainDb>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "maxCompressionGainNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case AutomaticGainControlV1::enableLimiter: {
|
||||
RETURN_IF(
|
||||
mContext->setEnableLimiter(
|
||||
param.get<AutomaticGainControlV1::enableLimiter>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "enableLimiterNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AutomaticGainControlV1Sw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::automaticGainControlV1Tag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto specificId = id.get<Parameter::Id::automaticGainControlV1Tag>();
|
||||
auto specificIdTag = specificId.getTag();
|
||||
switch (specificIdTag) {
|
||||
case AutomaticGainControlV1::Id::commonTag:
|
||||
return getParameterAutomaticGainControlV1(
|
||||
specificId.get<AutomaticGainControlV1::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AutomaticGainControlV1Sw::getParameterAutomaticGainControlV1(
|
||||
const AutomaticGainControlV1::Tag& tag, Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
AutomaticGainControlV1 param;
|
||||
switch (tag) {
|
||||
case AutomaticGainControlV1::targetPeakLevelDbFs: {
|
||||
param.set<AutomaticGainControlV1::targetPeakLevelDbFs>(mContext->getTargetPeakLevel());
|
||||
break;
|
||||
}
|
||||
case AutomaticGainControlV1::maxCompressionGainDb: {
|
||||
param.set<AutomaticGainControlV1::maxCompressionGainDb>(
|
||||
mContext->getMaxCompressionGain());
|
||||
break;
|
||||
}
|
||||
case AutomaticGainControlV1::enableLimiter: {
|
||||
param.set<AutomaticGainControlV1::enableLimiter>(mContext->getEnableLimiter());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::automaticGainControlV1>(param);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> AutomaticGainControlV1Sw::createContext(
|
||||
const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext =
|
||||
std::make_shared<AutomaticGainControlV1SwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode AutomaticGainControlV1Sw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status AutomaticGainControlV1Sw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode AutomaticGainControlV1SwContext::setTargetPeakLevel(int targetPeakLevel) {
|
||||
mTargetPeakLevel = targetPeakLevel;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
int AutomaticGainControlV1SwContext::getTargetPeakLevel() {
|
||||
return mTargetPeakLevel;
|
||||
}
|
||||
|
||||
RetCode AutomaticGainControlV1SwContext::setMaxCompressionGain(int maxCompressionGain) {
|
||||
mMaxCompressionGain = maxCompressionGain;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
int AutomaticGainControlV1SwContext::getMaxCompressionGain() {
|
||||
return mMaxCompressionGain;
|
||||
}
|
||||
|
||||
RetCode AutomaticGainControlV1SwContext::setEnableLimiter(bool enableLimiter) {
|
||||
mEnableLimiter = enableLimiter;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
bool AutomaticGainControlV1SwContext::getEnableLimiter() {
|
||||
return mEnableLimiter;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class AutomaticGainControlV1SwContext final : public EffectContext {
|
||||
public:
|
||||
AutomaticGainControlV1SwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setTargetPeakLevel(int targetPeakLevel);
|
||||
int getTargetPeakLevel();
|
||||
RetCode setMaxCompressionGain(int maxCompressionGainDb);
|
||||
int getMaxCompressionGain();
|
||||
RetCode setEnableLimiter(bool enableLimiter);
|
||||
bool getEnableLimiter();
|
||||
|
||||
private:
|
||||
int mTargetPeakLevel = 0;
|
||||
int mMaxCompressionGain = 0;
|
||||
bool mEnableLimiter = false;
|
||||
};
|
||||
|
||||
class AutomaticGainControlV1Sw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const bool kStrengthSupported;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
AutomaticGainControlV1Sw() { LOG(DEBUG) << __func__; }
|
||||
~AutomaticGainControlV1Sw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
std::string getEffectName() override { return kEffectName; };
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
private:
|
||||
static const std::vector<Range::AutomaticGainControlV1Range> kRanges;
|
||||
std::shared_ptr<AutomaticGainControlV1SwContext> mContext GUARDED_BY(mImplMutex);
|
||||
ndk::ScopedAStatus getParameterAutomaticGainControlV1(const AutomaticGainControlV1::Tag& tag,
|
||||
Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libagc2sw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"AutomaticGainControlV2Sw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#define LOG_TAG "AHAL_AutomaticGainControlV2Sw"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "AutomaticGainControlV2Sw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::AutomaticGainControlV2Sw;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidAutomaticGainControlV2Sw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidAutomaticGainControlV2;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidAutomaticGainControlV2Sw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<AutomaticGainControlV2Sw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidAutomaticGainControlV2Sw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = AutomaticGainControlV2Sw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string AutomaticGainControlV2Sw::kEffectName = "AutomaticGainControlV2Sw";
|
||||
|
||||
const std::vector<Range::AutomaticGainControlV2Range> AutomaticGainControlV2Sw::kRanges = {
|
||||
MAKE_RANGE(AutomaticGainControlV2, fixedDigitalGainMb, 0, 50000),
|
||||
MAKE_RANGE(AutomaticGainControlV2, saturationMarginMb, 0, 10000)};
|
||||
|
||||
const Capability AutomaticGainControlV2Sw::kCapability = {
|
||||
.range = AutomaticGainControlV2Sw::kRanges};
|
||||
|
||||
const Descriptor AutomaticGainControlV2Sw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidAutomaticGainControlV2(),
|
||||
.uuid = getEffectImplUuidAutomaticGainControlV2Sw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = AutomaticGainControlV2Sw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = AutomaticGainControlV2Sw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus AutomaticGainControlV2Sw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AutomaticGainControlV2Sw::setParameterSpecific(
|
||||
const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::automaticGainControlV2 != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& param = specific.get<Parameter::Specific::automaticGainControlV2>();
|
||||
RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
auto tag = param.getTag();
|
||||
switch (tag) {
|
||||
case AutomaticGainControlV2::fixedDigitalGainMb: {
|
||||
RETURN_IF(mContext->setDigitalGain(
|
||||
param.get<AutomaticGainControlV2::fixedDigitalGainMb>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "digitalGainNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case AutomaticGainControlV2::levelEstimator: {
|
||||
RETURN_IF(mContext->setLevelEstimator(
|
||||
param.get<AutomaticGainControlV2::levelEstimator>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "levelEstimatorNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case AutomaticGainControlV2::saturationMarginMb: {
|
||||
RETURN_IF(mContext->setSaturationMargin(
|
||||
param.get<AutomaticGainControlV2::saturationMarginMb>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "saturationMarginNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV2TagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AutomaticGainControlV2Sw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::automaticGainControlV2Tag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto specificId = id.get<Parameter::Id::automaticGainControlV2Tag>();
|
||||
auto specificIdTag = specificId.getTag();
|
||||
switch (specificIdTag) {
|
||||
case AutomaticGainControlV2::Id::commonTag:
|
||||
return getParameterAutomaticGainControlV2(
|
||||
specificId.get<AutomaticGainControlV2::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV2TagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus AutomaticGainControlV2Sw::getParameterAutomaticGainControlV2(
|
||||
const AutomaticGainControlV2::Tag& tag, Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
AutomaticGainControlV2 param;
|
||||
switch (tag) {
|
||||
case AutomaticGainControlV2::fixedDigitalGainMb: {
|
||||
param.set<AutomaticGainControlV2::fixedDigitalGainMb>(mContext->getDigitalGain());
|
||||
break;
|
||||
}
|
||||
case AutomaticGainControlV2::levelEstimator: {
|
||||
param.set<AutomaticGainControlV2::levelEstimator>(mContext->getLevelEstimator());
|
||||
break;
|
||||
}
|
||||
case AutomaticGainControlV2::saturationMarginMb: {
|
||||
param.set<AutomaticGainControlV2::saturationMarginMb>(mContext->getSaturationMargin());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV2TagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::automaticGainControlV2>(param);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> AutomaticGainControlV2Sw::createContext(
|
||||
const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext =
|
||||
std::make_shared<AutomaticGainControlV2SwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode AutomaticGainControlV2Sw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status AutomaticGainControlV2Sw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode AutomaticGainControlV2SwContext::setDigitalGain(int gain) {
|
||||
mDigitalGain = gain;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
int AutomaticGainControlV2SwContext::getDigitalGain() {
|
||||
return mDigitalGain;
|
||||
}
|
||||
|
||||
RetCode AutomaticGainControlV2SwContext::setLevelEstimator(
|
||||
AutomaticGainControlV2::LevelEstimator levelEstimator) {
|
||||
mLevelEstimator = levelEstimator;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
AutomaticGainControlV2::LevelEstimator AutomaticGainControlV2SwContext::getLevelEstimator() {
|
||||
return mLevelEstimator;
|
||||
}
|
||||
|
||||
RetCode AutomaticGainControlV2SwContext::setSaturationMargin(int margin) {
|
||||
mSaturationMargin = margin;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
int AutomaticGainControlV2SwContext::getSaturationMargin() {
|
||||
return mSaturationMargin;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class AutomaticGainControlV2SwContext final : public EffectContext {
|
||||
public:
|
||||
AutomaticGainControlV2SwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setDigitalGain(int gain);
|
||||
int getDigitalGain();
|
||||
RetCode setLevelEstimator(AutomaticGainControlV2::LevelEstimator levelEstimator);
|
||||
AutomaticGainControlV2::LevelEstimator getLevelEstimator();
|
||||
RetCode setSaturationMargin(int margin);
|
||||
int getSaturationMargin();
|
||||
|
||||
private:
|
||||
int mDigitalGain = 0;
|
||||
AutomaticGainControlV2::LevelEstimator mLevelEstimator =
|
||||
AutomaticGainControlV2::LevelEstimator::RMS;
|
||||
int mSaturationMargin = 0;
|
||||
};
|
||||
|
||||
class AutomaticGainControlV2Sw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const bool kStrengthSupported;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
AutomaticGainControlV2Sw() { LOG(DEBUG) << __func__; }
|
||||
~AutomaticGainControlV2Sw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
std::string getEffectName() override { return kEffectName; };
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
private:
|
||||
static const std::vector<Range::AutomaticGainControlV2Range> kRanges;
|
||||
std::shared_ptr<AutomaticGainControlV2SwContext> mContext GUARDED_BY(mImplMutex);
|
||||
ndk::ScopedAStatus getParameterAutomaticGainControlV2(const AutomaticGainControlV2::Tag& tag,
|
||||
Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libbassboostsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"BassBoostSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
#define LOG_TAG "AHAL_BassBoostSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "BassBoostSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::BassBoostSw;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidBassBoostProxy;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidBassBoostSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidBassBoostSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<BassBoostSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidBassBoostSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = BassBoostSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string BassBoostSw::kEffectName = "BassBoostSw";
|
||||
|
||||
const std::vector<Range::BassBoostRange> BassBoostSw::kRanges = {
|
||||
MAKE_RANGE(BassBoost, strengthPm, 0, 1000)};
|
||||
const Capability BassBoostSw::kCapability = {.range = {BassBoostSw::kRanges}};
|
||||
const Descriptor BassBoostSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidBassBoost(),
|
||||
.uuid = getEffectImplUuidBassBoostSw()},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = BassBoostSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = BassBoostSw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus BassBoostSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus BassBoostSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::bassBoost != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& bbParam = specific.get<Parameter::Specific::bassBoost>();
|
||||
RETURN_IF(!inRange(bbParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
auto tag = bbParam.getTag();
|
||||
|
||||
switch (tag) {
|
||||
case BassBoost::strengthPm: {
|
||||
const auto strength = bbParam.get<BassBoost::strengthPm>();
|
||||
RETURN_IF(mContext->setBbStrengthPm(strength) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT,
|
||||
"strengthPmNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"BassBoostTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus BassBoostSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::bassBoostTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto bbId = id.get<Parameter::Id::bassBoostTag>();
|
||||
auto bbIdTag = bbId.getTag();
|
||||
switch (bbIdTag) {
|
||||
case BassBoost::Id::commonTag:
|
||||
return getParameterBassBoost(bbId.get<BassBoost::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"BassBoostTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus BassBoostSw::getParameterBassBoost(const BassBoost::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
BassBoost bbParam;
|
||||
switch (tag) {
|
||||
case BassBoost::strengthPm: {
|
||||
bbParam.set<BassBoost::strengthPm>(mContext->getBbStrengthPm());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"BassBoostTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::bassBoost>(bbParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> BassBoostSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<BassBoostSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode BassBoostSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status BassBoostSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode BassBoostSwContext::setBbStrengthPm(int strength) {
|
||||
mStrength = strength;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class BassBoostSwContext final : public EffectContext {
|
||||
public:
|
||||
BassBoostSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setBbStrengthPm(int strength);
|
||||
int getBbStrengthPm() const { return mStrength; }
|
||||
|
||||
private:
|
||||
int mStrength = 0;
|
||||
};
|
||||
|
||||
class BassBoostSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
BassBoostSw() { LOG(DEBUG) << __func__; }
|
||||
~BassBoostSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
std::string getEffectName() override { return kEffectName; };
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
private:
|
||||
static const std::vector<Range::BassBoostRange> kRanges;
|
||||
std::shared_ptr<BassBoostSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Tag& tag,
|
||||
Parameter::Specific* specific) REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libdownmixsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"DownmixSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
#define LOG_TAG "AHAL_DownmixSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "DownmixSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::DownmixSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidDownmixSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDownmixSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<DownmixSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDownmixSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = DownmixSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string DownmixSw::kEffectName = "DownmixSw";
|
||||
const Descriptor DownmixSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidDownmix(),
|
||||
.uuid = getEffectImplUuidDownmixSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = kEffectName,
|
||||
.implementor = "The Android Open Source Project"}};
|
||||
|
||||
ndk::ScopedAStatus DownmixSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus DownmixSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::downmix != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& dmParam = specific.get<Parameter::Specific::downmix>();
|
||||
auto tag = dmParam.getTag();
|
||||
|
||||
switch (tag) {
|
||||
case Downmix::type: {
|
||||
RETURN_IF(mContext->setDmType(dmParam.get<Downmix::type>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setTypeFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"DownmixTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus DownmixSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::downmixTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto dmId = id.get<Parameter::Id::downmixTag>();
|
||||
auto dmIdTag = dmId.getTag();
|
||||
switch (dmIdTag) {
|
||||
case Downmix::Id::commonTag:
|
||||
return getParameterDownmix(dmId.get<Downmix::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"DownmixTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus DownmixSw::getParameterDownmix(const Downmix::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
Downmix dmParam;
|
||||
switch (tag) {
|
||||
case Downmix::type: {
|
||||
dmParam.set<Downmix::type>(mContext->getDmType());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"DownmixTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::downmix>(dmParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> DownmixSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<DownmixSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode DownmixSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status DownmixSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class DownmixSwContext final : public EffectContext {
|
||||
public:
|
||||
DownmixSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setDmType(Downmix::Type type) {
|
||||
// TODO : Add implementation to apply new type
|
||||
mType = type;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
Downmix::Type getDmType() const { return mType; }
|
||||
|
||||
private:
|
||||
Downmix::Type mType = Downmix::Type::STRIP;
|
||||
};
|
||||
|
||||
class DownmixSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
DownmixSw() { LOG(DEBUG) << __func__; }
|
||||
~DownmixSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
std::string getEffectName() override { return kEffectName; };
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int sample)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<DownmixSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
|
||||
ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libdynamicsprocessingsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"DynamicsProcessingSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
@@ -1,523 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
#define LOG_TAG "AHAL_DynamicsProcessingSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "DynamicsProcessingSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::DynamicsProcessingSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidDynamicsProcessingSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDynamicsProcessingSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<DynamicsProcessingSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDynamicsProcessingSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = DynamicsProcessingSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string DynamicsProcessingSw::kEffectName = "DynamicsProcessingSw";
|
||||
const DynamicsProcessing::EqBandConfig DynamicsProcessingSw::kEqBandConfigMin =
|
||||
DynamicsProcessing::EqBandConfig({.channel = 0,
|
||||
.band = 0,
|
||||
.enable = false,
|
||||
.cutoffFrequencyHz = 220,
|
||||
.gainDb = std::numeric_limits<float>::min()});
|
||||
const DynamicsProcessing::EqBandConfig DynamicsProcessingSw::kEqBandConfigMax =
|
||||
DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
|
||||
.band = std::numeric_limits<int>::max(),
|
||||
.enable = true,
|
||||
.cutoffFrequencyHz = 20000,
|
||||
.gainDb = std::numeric_limits<float>::max()});
|
||||
const Range::DynamicsProcessingRange DynamicsProcessingSw::kPreEqBandRange = {
|
||||
.min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
|
||||
{DynamicsProcessingSw::kEqBandConfigMin}),
|
||||
.max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
|
||||
{DynamicsProcessingSw::kEqBandConfigMax})};
|
||||
const Range::DynamicsProcessingRange DynamicsProcessingSw::kPostEqBandRange = {
|
||||
.min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
|
||||
{DynamicsProcessingSw::kEqBandConfigMin}),
|
||||
.max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
|
||||
{DynamicsProcessingSw::kEqBandConfigMax})};
|
||||
|
||||
const std::vector<Range::DynamicsProcessingRange> DynamicsProcessingSw::kRanges = {
|
||||
DynamicsProcessingSw::kPreEqBandRange, DynamicsProcessingSw::kPostEqBandRange};
|
||||
const Capability DynamicsProcessingSw::kCapability = {.range = DynamicsProcessingSw::kRanges};
|
||||
|
||||
const Descriptor DynamicsProcessingSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidDynamicsProcessing(),
|
||||
.uuid = getEffectImplUuidDynamicsProcessingSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::POST_PROC,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = DynamicsProcessingSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = DynamicsProcessingSw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus DynamicsProcessingSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus DynamicsProcessingSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
LOG(INFO) << __func__ << specific.toString();
|
||||
auto& dpParam = specific.get<Parameter::Specific::dynamicsProcessing>();
|
||||
auto tag = dpParam.getTag();
|
||||
switch (tag) {
|
||||
case DynamicsProcessing::engineArchitecture: {
|
||||
RETURN_IF(mContext->setEngineArchitecture(
|
||||
dpParam.get<DynamicsProcessing::engineArchitecture>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setEngineArchitectureFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case DynamicsProcessing::preEq: {
|
||||
RETURN_IF(mContext->setPreEqChannelCfgs(dpParam.get<DynamicsProcessing::preEq>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setPreEqChannelCfgsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case DynamicsProcessing::postEq: {
|
||||
RETURN_IF(mContext->setPostEqChannelCfgs(dpParam.get<DynamicsProcessing::postEq>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setPostEqChannelCfgsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case DynamicsProcessing::mbc: {
|
||||
RETURN_IF(mContext->setMbcChannelCfgs(dpParam.get<DynamicsProcessing::mbc>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setMbcChannelCfgsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case DynamicsProcessing::preEqBand: {
|
||||
RETURN_IF(mContext->setPreEqBandCfgs(dpParam.get<DynamicsProcessing::preEqBand>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setPreEqBandCfgsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case DynamicsProcessing::postEqBand: {
|
||||
RETURN_IF(mContext->setPostEqBandCfgs(dpParam.get<DynamicsProcessing::postEqBand>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setPostEqBandCfgsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case DynamicsProcessing::mbcBand: {
|
||||
RETURN_IF(mContext->setMbcBandCfgs(dpParam.get<DynamicsProcessing::mbcBand>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setMbcBandCfgsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case DynamicsProcessing::limiter: {
|
||||
RETURN_IF(mContext->setLimiterCfgs(dpParam.get<DynamicsProcessing::limiter>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "limiterCfgsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case DynamicsProcessing::inputGain: {
|
||||
RETURN_IF(mContext->setInputGainCfgs(dpParam.get<DynamicsProcessing::inputGain>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "inputGainCfgFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case DynamicsProcessing::vendor: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus DynamicsProcessingSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::dynamicsProcessingTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto dpId = id.get<Parameter::Id::dynamicsProcessingTag>();
|
||||
auto dpIdTag = dpId.getTag();
|
||||
switch (dpIdTag) {
|
||||
case DynamicsProcessing::Id::commonTag:
|
||||
return getParameterDynamicsProcessing(dpId.get<DynamicsProcessing::Id::commonTag>(),
|
||||
specific);
|
||||
case DynamicsProcessing::Id::vendorExtensionTag:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(dpIdTag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus DynamicsProcessingSw::getParameterDynamicsProcessing(
|
||||
const DynamicsProcessing::Tag& tag, Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
DynamicsProcessing dpParam;
|
||||
switch (tag) {
|
||||
case DynamicsProcessing::Tag::engineArchitecture: {
|
||||
dpParam.set<DynamicsProcessing::engineArchitecture>(mContext->getEngineArchitecture());
|
||||
break;
|
||||
}
|
||||
case DynamicsProcessing::Tag::preEq: {
|
||||
dpParam.set<DynamicsProcessing::preEq>(mContext->getPreEqChannelCfgs());
|
||||
break;
|
||||
}
|
||||
case DynamicsProcessing::Tag::postEq: {
|
||||
dpParam.set<DynamicsProcessing::postEq>(mContext->getPostEqChannelCfgs());
|
||||
break;
|
||||
}
|
||||
case DynamicsProcessing::Tag::mbc: {
|
||||
dpParam.set<DynamicsProcessing::mbc>(mContext->getMbcChannelCfgs());
|
||||
break;
|
||||
}
|
||||
case DynamicsProcessing::Tag::preEqBand: {
|
||||
dpParam.set<DynamicsProcessing::preEqBand>(mContext->getPreEqBandCfgs());
|
||||
break;
|
||||
}
|
||||
case DynamicsProcessing::Tag::postEqBand: {
|
||||
dpParam.set<DynamicsProcessing::postEqBand>(mContext->getPostEqBandCfgs());
|
||||
break;
|
||||
}
|
||||
case DynamicsProcessing::Tag::mbcBand: {
|
||||
dpParam.set<DynamicsProcessing::mbcBand>(mContext->getMbcBandCfgs());
|
||||
break;
|
||||
}
|
||||
case DynamicsProcessing::Tag::limiter: {
|
||||
dpParam.set<DynamicsProcessing::limiter>(mContext->getLimiterCfgs());
|
||||
break;
|
||||
}
|
||||
case DynamicsProcessing::Tag::inputGain: {
|
||||
dpParam.set<DynamicsProcessing::inputGain>(mContext->getInputGainCfgs());
|
||||
break;
|
||||
}
|
||||
case DynamicsProcessing::vendor: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "DynamicsProcessingTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::dynamicsProcessing>(dpParam);
|
||||
LOG(INFO) << __func__ << specific->toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> DynamicsProcessingSw::createContext(
|
||||
const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<DynamicsProcessingSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status DynamicsProcessingSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setCommon(const Parameter::Common& common) {
|
||||
if (auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
mCommon = common;
|
||||
mChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
|
||||
common.input.base.channelMask);
|
||||
resizeChannels();
|
||||
resizeBands();
|
||||
LOG(INFO) << __func__ << mCommon.toString();
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setEngineArchitecture(
|
||||
const DynamicsProcessing::EngineArchitecture& cfg) {
|
||||
RETURN_VALUE_IF(!validateEngineConfig(cfg), RetCode::ERROR_ILLEGAL_PARAMETER,
|
||||
"illegalEngineConfig");
|
||||
|
||||
if (mEngineSettings == cfg) {
|
||||
LOG(INFO) << __func__ << " not change in engine, do nothing";
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
mEngineSettings = cfg;
|
||||
resizeBands();
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setChannelCfgs(
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& cfgs,
|
||||
std::vector<DynamicsProcessing::ChannelConfig>& targetCfgs,
|
||||
const DynamicsProcessing::StageEnablement& stage) {
|
||||
RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
|
||||
|
||||
RetCode ret = RetCode::SUCCESS;
|
||||
std::unordered_set<int> channelSet;
|
||||
for (auto& cfg : cfgs) {
|
||||
if (cfg.channel < 0 || (size_t)cfg.channel >= mChannelCount) {
|
||||
LOG(ERROR) << __func__ << " skip illegal channel config " << cfg.toString();
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
continue;
|
||||
}
|
||||
if (0 != channelSet.count(cfg.channel)) {
|
||||
LOG(WARNING) << __func__ << " duplicated channel " << cfg.channel;
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
} else {
|
||||
channelSet.insert(cfg.channel);
|
||||
}
|
||||
targetCfgs[cfg.channel] = cfg;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setPreEqChannelCfgs(
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
|
||||
return setChannelCfgs(cfgs, mPreEqChCfgs, mEngineSettings.preEqStage);
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setPostEqChannelCfgs(
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
|
||||
return setChannelCfgs(cfgs, mPostEqChCfgs, mEngineSettings.postEqStage);
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setMbcChannelCfgs(
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& cfgs) {
|
||||
return setChannelCfgs(cfgs, mMbcChCfgs, mEngineSettings.mbcStage);
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setEqBandCfgs(
|
||||
const std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
|
||||
std::vector<DynamicsProcessing::EqBandConfig>& targetCfgs,
|
||||
const DynamicsProcessing::StageEnablement& stage,
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
|
||||
RETURN_VALUE_IF(!stage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER, "eqStageNotInUse");
|
||||
|
||||
RetCode ret = RetCode::SUCCESS;
|
||||
std::set<std::pair<int /* channel */, int /* band */>> bandSet;
|
||||
|
||||
for (auto& cfg : cfgs) {
|
||||
if (0 != bandSet.count({cfg.channel, cfg.band})) {
|
||||
LOG(WARNING) << __func__ << " duplicated band " << cfg.toString();
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
} else {
|
||||
bandSet.insert({cfg.channel, cfg.band});
|
||||
}
|
||||
if (!validateEqBandConfig(cfg, mChannelCount, stage.bandCount, channelConfig)) {
|
||||
LOG(WARNING) << __func__ << " skip invalid band " << cfg.toString();
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
continue;
|
||||
}
|
||||
targetCfgs[cfg.channel * stage.bandCount + cfg.band] = cfg;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setPreEqBandCfgs(
|
||||
const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
|
||||
return setEqBandCfgs(cfgs, mPreEqChBands, mEngineSettings.preEqStage, mPreEqChCfgs);
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setPostEqBandCfgs(
|
||||
const std::vector<DynamicsProcessing::EqBandConfig>& cfgs) {
|
||||
return setEqBandCfgs(cfgs, mPostEqChBands, mEngineSettings.postEqStage, mPostEqChCfgs);
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setMbcBandCfgs(
|
||||
const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs) {
|
||||
RETURN_VALUE_IF(!mEngineSettings.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
|
||||
"mbcNotInUse");
|
||||
|
||||
RetCode ret = RetCode::SUCCESS;
|
||||
std::set<std::pair<int /* channel */, int /* band */>> bandSet;
|
||||
|
||||
int bandCount = mEngineSettings.mbcStage.bandCount;
|
||||
std::vector<bool> filled(mChannelCount * bandCount, false);
|
||||
for (auto& it : cfgs) {
|
||||
if (0 != bandSet.count({it.channel, it.band})) {
|
||||
LOG(WARNING) << __func__ << " duplicated band " << it.toString();
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
} else {
|
||||
bandSet.insert({it.channel, it.band});
|
||||
}
|
||||
if (!validateMbcBandConfig(it, mChannelCount, mEngineSettings.mbcStage.bandCount,
|
||||
mMbcChCfgs)) {
|
||||
LOG(WARNING) << __func__ << " skip invalid band " << it.toString();
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
continue;
|
||||
}
|
||||
mMbcChBands[it.channel * bandCount + it.band] = it;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setLimiterCfgs(
|
||||
const std::vector<DynamicsProcessing::LimiterConfig>& cfgs) {
|
||||
RETURN_VALUE_IF(!mEngineSettings.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
|
||||
"limiterNotInUse");
|
||||
|
||||
RetCode ret = RetCode::SUCCESS;
|
||||
std::unordered_set<int> channelSet;
|
||||
|
||||
for (auto& it : cfgs) {
|
||||
if (0 != channelSet.count(it.channel)) {
|
||||
LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
} else {
|
||||
channelSet.insert(it.channel);
|
||||
}
|
||||
if (!validateLimiterConfig(it, mChannelCount)) {
|
||||
LOG(WARNING) << __func__ << " skip invalid limiter " << it.toString();
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
continue;
|
||||
}
|
||||
mLimiterCfgs[it.channel] = it;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DynamicsProcessingSwContext::resizeChannels() {
|
||||
if (mPreEqChCfgs.size() != mChannelCount) {
|
||||
mPreEqChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
|
||||
}
|
||||
if (mPostEqChCfgs.size() != mChannelCount) {
|
||||
mPostEqChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
|
||||
}
|
||||
if (mMbcChCfgs.size() != mChannelCount) {
|
||||
mMbcChCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
|
||||
}
|
||||
if (mLimiterCfgs.size() != mChannelCount) {
|
||||
mLimiterCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
|
||||
}
|
||||
if (mInputGainCfgs.size() != mChannelCount) {
|
||||
mInputGainCfgs.resize(mChannelCount, {.channel = kInvalidChannelId});
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicsProcessingSwContext::resizeBands() {
|
||||
if (mPreEqChBands.size() != (size_t)(mChannelCount * mEngineSettings.preEqStage.bandCount)) {
|
||||
mPreEqChBands.resize(mChannelCount * mEngineSettings.preEqStage.bandCount,
|
||||
{.channel = kInvalidChannelId});
|
||||
}
|
||||
if (mPostEqChBands.size() != (size_t)(mChannelCount * mEngineSettings.postEqStage.bandCount)) {
|
||||
mPostEqChBands.resize(mChannelCount * mEngineSettings.postEqStage.bandCount,
|
||||
{.channel = kInvalidChannelId});
|
||||
}
|
||||
if (mMbcChBands.size() != (size_t)(mChannelCount * mEngineSettings.mbcStage.bandCount)) {
|
||||
mMbcChBands.resize(mChannelCount * mEngineSettings.mbcStage.bandCount,
|
||||
{.channel = kInvalidChannelId});
|
||||
}
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSwContext::setInputGainCfgs(
|
||||
const std::vector<DynamicsProcessing::InputGain>& cfgs) {
|
||||
for (const auto& cfg : cfgs) {
|
||||
RETURN_VALUE_IF(cfg.channel < 0 || (size_t)cfg.channel >= mChannelCount,
|
||||
RetCode::ERROR_ILLEGAL_PARAMETER, "invalidChannel");
|
||||
mInputGainCfgs[cfg.channel] = cfg;
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
std::vector<DynamicsProcessing::InputGain> DynamicsProcessingSwContext::getInputGainCfgs() {
|
||||
std::vector<DynamicsProcessing::InputGain> ret;
|
||||
std::copy_if(mInputGainCfgs.begin(), mInputGainCfgs.end(), std::back_inserter(ret),
|
||||
[&](const auto& gain) { return gain.channel != kInvalidChannelId; });
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DynamicsProcessingSwContext::validateStageEnablement(
|
||||
const DynamicsProcessing::StageEnablement& enablement) {
|
||||
return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
|
||||
}
|
||||
|
||||
bool DynamicsProcessingSwContext::validateEngineConfig(
|
||||
const DynamicsProcessing::EngineArchitecture& engine) {
|
||||
return engine.preferredProcessingDurationMs >= 0 &&
|
||||
validateStageEnablement(engine.preEqStage) &&
|
||||
validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
|
||||
}
|
||||
|
||||
bool DynamicsProcessingSwContext::validateEqBandConfig(
|
||||
const DynamicsProcessing::EqBandConfig& band, int maxChannel, int maxBand,
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
|
||||
return band.channel >= 0 && band.channel < maxChannel &&
|
||||
(size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
|
||||
band.band >= 0 && band.band < maxBand;
|
||||
}
|
||||
|
||||
bool DynamicsProcessingSwContext::validateMbcBandConfig(
|
||||
const DynamicsProcessing::MbcBandConfig& band, int maxChannel, int maxBand,
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig) {
|
||||
return band.channel >= 0 && band.channel < maxChannel &&
|
||||
(size_t)band.channel < channelConfig.size() && channelConfig[band.channel].enable &&
|
||||
band.band >= 0 && band.band < maxBand && band.attackTimeMs >= 0 &&
|
||||
band.releaseTimeMs >= 0 && band.ratio >= 0 && band.thresholdDb <= 0 &&
|
||||
band.kneeWidthDb <= 0 && band.noiseGateThresholdDb <= 0 && band.expanderRatio >= 0;
|
||||
}
|
||||
|
||||
bool DynamicsProcessingSwContext::validateLimiterConfig(
|
||||
const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
|
||||
return limiter.channel >= 0 && limiter.channel < maxChannel && limiter.attackTimeMs >= 0 &&
|
||||
limiter.releaseTimeMs >= 0 && limiter.ratio >= 0 && limiter.thresholdDb <= 0;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <Utils.h>
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class DynamicsProcessingSwContext final : public EffectContext {
|
||||
public:
|
||||
DynamicsProcessingSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common),
|
||||
mChannelCount(::aidl::android::hardware::audio::common::getChannelCount(
|
||||
common.input.base.channelMask)),
|
||||
mPreEqChCfgs(mChannelCount, {.channel = kInvalidChannelId}),
|
||||
mPostEqChCfgs(mChannelCount, {.channel = kInvalidChannelId}),
|
||||
mMbcChCfgs(mChannelCount, {.channel = kInvalidChannelId}),
|
||||
mLimiterCfgs(mChannelCount, {.channel = kInvalidChannelId}) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
// utils
|
||||
RetCode setChannelCfgs(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs,
|
||||
std::vector<DynamicsProcessing::ChannelConfig>& targetCfgs,
|
||||
const DynamicsProcessing::StageEnablement& engineSetting);
|
||||
|
||||
RetCode setEqBandCfgs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
|
||||
std::vector<DynamicsProcessing::EqBandConfig>& targetCfgs,
|
||||
const DynamicsProcessing::StageEnablement& stage,
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig);
|
||||
|
||||
// set params
|
||||
RetCode setCommon(const Parameter::Common& common) override;
|
||||
RetCode setEngineArchitecture(const DynamicsProcessing::EngineArchitecture& cfg);
|
||||
RetCode setPreEqChannelCfgs(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs);
|
||||
RetCode setPostEqChannelCfgs(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs);
|
||||
RetCode setMbcChannelCfgs(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs);
|
||||
RetCode setPreEqBandCfgs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
|
||||
RetCode setPostEqBandCfgs(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs);
|
||||
RetCode setMbcBandCfgs(const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs);
|
||||
RetCode setLimiterCfgs(const std::vector<DynamicsProcessing::LimiterConfig>& cfgs);
|
||||
RetCode setInputGainCfgs(const std::vector<DynamicsProcessing::InputGain>& cfgs);
|
||||
|
||||
// get params
|
||||
DynamicsProcessing::EngineArchitecture getEngineArchitecture() { return mEngineSettings; }
|
||||
std::vector<DynamicsProcessing::ChannelConfig> getPreEqChannelCfgs() { return mPreEqChCfgs; }
|
||||
std::vector<DynamicsProcessing::ChannelConfig> getPostEqChannelCfgs() { return mPostEqChCfgs; }
|
||||
std::vector<DynamicsProcessing::ChannelConfig> getMbcChannelCfgs() { return mMbcChCfgs; }
|
||||
std::vector<DynamicsProcessing::EqBandConfig> getPreEqBandCfgs() { return mPreEqChBands; }
|
||||
std::vector<DynamicsProcessing::EqBandConfig> getPostEqBandCfgs() { return mPostEqChBands; }
|
||||
std::vector<DynamicsProcessing::MbcBandConfig> getMbcBandCfgs() { return mMbcChBands; }
|
||||
std::vector<DynamicsProcessing::LimiterConfig> getLimiterCfgs() { return mLimiterCfgs; }
|
||||
std::vector<DynamicsProcessing::InputGain> getInputGainCfgs();
|
||||
|
||||
private:
|
||||
static constexpr int32_t kInvalidChannelId = -1;
|
||||
size_t mChannelCount = 0;
|
||||
DynamicsProcessing::EngineArchitecture mEngineSettings;
|
||||
// Channel config vector with size of mChannelCount
|
||||
std::vector<DynamicsProcessing::ChannelConfig> mPreEqChCfgs;
|
||||
std::vector<DynamicsProcessing::ChannelConfig> mPostEqChCfgs;
|
||||
std::vector<DynamicsProcessing::ChannelConfig> mMbcChCfgs;
|
||||
std::vector<DynamicsProcessing::LimiterConfig> mLimiterCfgs;
|
||||
std::vector<DynamicsProcessing::InputGain> mInputGainCfgs;
|
||||
// Band config vector with size of mChannelCount * bandCount
|
||||
std::vector<DynamicsProcessing::EqBandConfig> mPreEqChBands;
|
||||
std::vector<DynamicsProcessing::EqBandConfig> mPostEqChBands;
|
||||
std::vector<DynamicsProcessing::MbcBandConfig> mMbcChBands;
|
||||
bool validateStageEnablement(const DynamicsProcessing::StageEnablement& enablement);
|
||||
bool validateEngineConfig(const DynamicsProcessing::EngineArchitecture& engine);
|
||||
bool validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band, int maxChannel,
|
||||
int maxBand,
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig);
|
||||
bool validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band, int maxChannel,
|
||||
int maxBand,
|
||||
const std::vector<DynamicsProcessing::ChannelConfig>& channelConfig);
|
||||
bool validateLimiterConfig(const DynamicsProcessing::LimiterConfig& limiter, int maxChannel);
|
||||
void resizeChannels();
|
||||
void resizeBands();
|
||||
}; // DynamicsProcessingSwContext
|
||||
|
||||
class DynamicsProcessingSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
DynamicsProcessingSw() { LOG(DEBUG) << __func__; }
|
||||
~DynamicsProcessingSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
std::string getEffectName() override { return kEffectName; };
|
||||
|
||||
private:
|
||||
static const DynamicsProcessing::EqBandConfig kEqBandConfigMin;
|
||||
static const DynamicsProcessing::EqBandConfig kEqBandConfigMax;
|
||||
static const Range::DynamicsProcessingRange kPreEqBandRange;
|
||||
static const Range::DynamicsProcessingRange kPostEqBandRange;
|
||||
static const std::vector<Range::DynamicsProcessingRange> kRanges;
|
||||
std::shared_ptr<DynamicsProcessingSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
|
||||
Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
|
||||
}; // DynamicsProcessingSw
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libenvreverbsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"EnvReverbSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <unordered_set>
|
||||
|
||||
#define LOG_TAG "AHAL_EnvReverbSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "EnvReverbSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::EnvReverbSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidEnvReverbSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEnvReverbSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<EnvReverbSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEnvReverbSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = EnvReverbSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string EnvReverbSw::kEffectName = "EnvReverbSw";
|
||||
|
||||
const std::vector<Range::EnvironmentalReverbRange> EnvReverbSw::kRanges = {
|
||||
MAKE_RANGE(EnvironmentalReverb, roomLevelMb, -6000, 0),
|
||||
MAKE_RANGE(EnvironmentalReverb, roomHfLevelMb, -4000, 0),
|
||||
MAKE_RANGE(EnvironmentalReverb, decayTimeMs, 0, 7000),
|
||||
MAKE_RANGE(EnvironmentalReverb, decayHfRatioPm, 100, 2000),
|
||||
MAKE_RANGE(EnvironmentalReverb, reflectionsLevelMb, -6000, 0),
|
||||
MAKE_RANGE(EnvironmentalReverb, reflectionsDelayMs, 0, 65),
|
||||
MAKE_RANGE(EnvironmentalReverb, levelMb, -6000, 0),
|
||||
MAKE_RANGE(EnvironmentalReverb, delayMs, 0, 65),
|
||||
MAKE_RANGE(EnvironmentalReverb, diffusionPm, 0, 1000),
|
||||
MAKE_RANGE(EnvironmentalReverb, densityPm, 0, 1000)};
|
||||
|
||||
const Capability EnvReverbSw::kCapability = {
|
||||
.range = Range::make<Range::environmentalReverb>(EnvReverbSw::kRanges)};
|
||||
|
||||
const Descriptor EnvReverbSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidEnvReverb(),
|
||||
.uuid = getEffectImplUuidEnvReverbSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = EnvReverbSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = EnvReverbSw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus EnvReverbSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EnvReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::environmentalReverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
|
||||
auto& erParam = specific.get<Parameter::Specific::environmentalReverb>();
|
||||
RETURN_IF(!inRange(erParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
auto tag = erParam.getTag();
|
||||
switch (tag) {
|
||||
case EnvironmentalReverb::roomLevelMb: {
|
||||
RETURN_IF(mContext->setErRoomLevel(erParam.get<EnvironmentalReverb::roomLevelMb>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setRoomLevelFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::roomHfLevelMb: {
|
||||
RETURN_IF(
|
||||
mContext->setErRoomHfLevel(erParam.get<EnvironmentalReverb::roomHfLevelMb>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setRoomHfLevelFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::decayTimeMs: {
|
||||
RETURN_IF(mContext->setErDecayTime(erParam.get<EnvironmentalReverb::decayTimeMs>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setDecayTimeFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::decayHfRatioPm: {
|
||||
RETURN_IF(
|
||||
mContext->setErDecayHfRatio(
|
||||
erParam.get<EnvironmentalReverb::decayHfRatioPm>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::reflectionsLevelMb: {
|
||||
RETURN_IF(mContext->setErReflectionsLevel(
|
||||
erParam.get<EnvironmentalReverb::reflectionsLevelMb>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setReflectionsLevelFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::reflectionsDelayMs: {
|
||||
RETURN_IF(mContext->setErReflectionsDelay(
|
||||
erParam.get<EnvironmentalReverb::reflectionsDelayMs>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setReflectionsDelayFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::levelMb: {
|
||||
RETURN_IF(mContext->setErLevel(erParam.get<EnvironmentalReverb::levelMb>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setLevelFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::delayMs: {
|
||||
RETURN_IF(mContext->setErDelay(erParam.get<EnvironmentalReverb::delayMs>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setDelayFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::diffusionPm: {
|
||||
RETURN_IF(mContext->setErDiffusion(erParam.get<EnvironmentalReverb::diffusionPm>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setDiffusionFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::densityPm: {
|
||||
RETURN_IF(mContext->setErDensity(erParam.get<EnvironmentalReverb::densityPm>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setDensityFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case EnvironmentalReverb::bypass: {
|
||||
RETURN_IF(mContext->setErBypass(erParam.get<EnvironmentalReverb::bypass>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setBypassFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EnvReverbSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::environmentalReverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto erId = id.get<Parameter::Id::environmentalReverbTag>();
|
||||
auto erIdTag = erId.getTag();
|
||||
switch (erIdTag) {
|
||||
case EnvironmentalReverb::Id::commonTag:
|
||||
return getParameterEnvironmentalReverb(erId.get<EnvironmentalReverb::Id::commonTag>(),
|
||||
specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(erIdTag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EnvReverbSw::getParameterEnvironmentalReverb(const EnvironmentalReverb::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
EnvironmentalReverb erParam;
|
||||
switch (tag) {
|
||||
case EnvironmentalReverb::roomLevelMb: {
|
||||
erParam.set<EnvironmentalReverb::roomLevelMb>(mContext->getErRoomLevel());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::roomHfLevelMb: {
|
||||
erParam.set<EnvironmentalReverb::roomHfLevelMb>(mContext->getErRoomHfLevel());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::decayTimeMs: {
|
||||
erParam.set<EnvironmentalReverb::decayTimeMs>(mContext->getErDecayTime());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::decayHfRatioPm: {
|
||||
erParam.set<EnvironmentalReverb::decayHfRatioPm>(mContext->getErDecayHfRatio());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::reflectionsLevelMb: {
|
||||
erParam.set<EnvironmentalReverb::reflectionsLevelMb>(mContext->getErReflectionsLevel());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::reflectionsDelayMs: {
|
||||
erParam.set<EnvironmentalReverb::reflectionsDelayMs>(mContext->getErReflectionsDelay());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::levelMb: {
|
||||
erParam.set<EnvironmentalReverb::levelMb>(mContext->getErLevel());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::delayMs: {
|
||||
erParam.set<EnvironmentalReverb::delayMs>(mContext->getErDelay());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::diffusionPm: {
|
||||
erParam.set<EnvironmentalReverb::diffusionPm>(mContext->getErDiffusion());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::densityPm: {
|
||||
erParam.set<EnvironmentalReverb::densityPm>(mContext->getErDensity());
|
||||
break;
|
||||
}
|
||||
case EnvironmentalReverb::bypass: {
|
||||
erParam.set<EnvironmentalReverb::bypass>(mContext->getErBypass());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::environmentalReverb>(erParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> EnvReverbSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<EnvReverbSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode EnvReverbSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status EnvReverbSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode EnvReverbSwContext::setErRoomLevel(int roomLevel) {
|
||||
mRoomLevel = roomLevel;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode EnvReverbSwContext::setErRoomHfLevel(int roomHfLevel) {
|
||||
mRoomHfLevel = roomHfLevel;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode EnvReverbSwContext::setErDecayTime(int decayTime) {
|
||||
mDecayTime = decayTime;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode EnvReverbSwContext::setErDecayHfRatio(int decayHfRatio) {
|
||||
mDecayHfRatio = decayHfRatio;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode EnvReverbSwContext::setErLevel(int level) {
|
||||
mLevel = level;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode EnvReverbSwContext::setErDelay(int delay) {
|
||||
mDelay = delay;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode EnvReverbSwContext::setErDiffusion(int diffusion) {
|
||||
mDiffusion = diffusion;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode EnvReverbSwContext::setErDensity(int density) {
|
||||
mDensity = density;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class EnvReverbSwContext final : public EffectContext {
|
||||
public:
|
||||
EnvReverbSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setErRoomLevel(int roomLevel);
|
||||
int getErRoomLevel() const { return mRoomLevel; }
|
||||
|
||||
RetCode setErRoomHfLevel(int roomHfLevel);
|
||||
int getErRoomHfLevel() const { return mRoomHfLevel; }
|
||||
|
||||
RetCode setErDecayTime(int decayTime);
|
||||
int getErDecayTime() const { return mDecayTime; }
|
||||
|
||||
RetCode setErDecayHfRatio(int decayHfRatio);
|
||||
int getErDecayHfRatio() const { return mDecayHfRatio; }
|
||||
|
||||
RetCode setErLevel(int level);
|
||||
int getErLevel() const { return mLevel; }
|
||||
|
||||
RetCode setErDelay(int delay);
|
||||
int getErDelay() const { return mDelay; }
|
||||
|
||||
RetCode setErDiffusion(int diffusion);
|
||||
int getErDiffusion() const { return mDiffusion; }
|
||||
|
||||
RetCode setErDensity(int density);
|
||||
int getErDensity() const { return mDensity; }
|
||||
|
||||
RetCode setErBypass(bool bypass) {
|
||||
mBypass = bypass;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
bool getErBypass() const { return mBypass; }
|
||||
|
||||
RetCode setErReflectionsDelay(int delay) {
|
||||
mReflectionsDelayMs = delay;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
bool getErReflectionsDelay() const { return mReflectionsDelayMs; }
|
||||
|
||||
RetCode setErReflectionsLevel(int level) {
|
||||
mReflectionsLevelMb = level;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
bool getErReflectionsLevel() const { return mReflectionsLevelMb; }
|
||||
|
||||
private:
|
||||
int mRoomLevel = -6000; // Default room level
|
||||
int mRoomHfLevel = 0; // Default room hf level
|
||||
int mDecayTime = 1000; // Default decay time
|
||||
int mDecayHfRatio = 500; // Default decay hf ratio
|
||||
int mLevel = -6000; // Default level
|
||||
int mDelay = 40; // Default delay
|
||||
int mReflectionsLevelMb = 0;
|
||||
int mReflectionsDelayMs = 0;
|
||||
int mDiffusion = 1000; // Default diffusion
|
||||
int mDensity = 1000; // Default density
|
||||
bool mBypass = false; // Default bypass
|
||||
};
|
||||
|
||||
class EnvReverbSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
EnvReverbSw() { LOG(DEBUG) << __func__; }
|
||||
~EnvReverbSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
|
||||
std::string getEffectName() override { return kEffectName; }
|
||||
|
||||
private:
|
||||
static const std::vector<Range::EnvironmentalReverbRange> kRanges;
|
||||
std::shared_ptr<EnvReverbSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
ndk::ScopedAStatus getParameterEnvironmentalReverb(const EnvironmentalReverb::Tag& tag,
|
||||
Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libequalizersw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"EqualizerSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
#define LOG_TAG "AHAL_EqualizerSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "EqualizerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::EqualizerSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidEqualizerSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEqualizerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<EqualizerSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEqualizerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = EqualizerSw::kDesc;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string EqualizerSw::kEffectName = "EqualizerSw";
|
||||
|
||||
const std::vector<Equalizer::BandFrequency> EqualizerSw::kBandFrequency = {{0, 30000, 120000},
|
||||
{1, 120001, 460000},
|
||||
{2, 460001, 1800000},
|
||||
{3, 1800001, 7000000},
|
||||
{4, 7000001, 20000000}};
|
||||
const std::vector<Equalizer::Preset> EqualizerSw::kPresets = {
|
||||
{0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
|
||||
{5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
|
||||
|
||||
/**
|
||||
* Use the same min and max to build a capability represented by Range.
|
||||
*/
|
||||
const std::vector<Range::EqualizerRange> EqualizerSw::kRanges = {
|
||||
MAKE_RANGE(Equalizer, preset, 0, EqualizerSw::kPresets.size() - 1),
|
||||
MAKE_RANGE(Equalizer, bandLevels,
|
||||
std::vector<Equalizer::BandLevel>{
|
||||
Equalizer::BandLevel({.index = 0, .levelMb = -15})},
|
||||
std::vector<Equalizer::BandLevel>{Equalizer::BandLevel(
|
||||
{.index = EqualizerSwContext::kMaxBandNumber - 1, .levelMb = 15})}),
|
||||
/* capability definition */
|
||||
MAKE_RANGE(Equalizer, bandFrequencies, EqualizerSw::kBandFrequency,
|
||||
EqualizerSw::kBandFrequency),
|
||||
MAKE_RANGE(Equalizer, presets, EqualizerSw::kPresets, EqualizerSw::kPresets),
|
||||
/* centerFreqMh is get only, set invalid range min > max */
|
||||
MAKE_RANGE(Equalizer, centerFreqMh, std::vector<int>({1}), std::vector<int>({0}))};
|
||||
|
||||
const Capability EqualizerSw::kEqCap = {.range = EqualizerSw::kRanges};
|
||||
const Descriptor EqualizerSw::kDesc = {.common = {.id = {.type = getEffectTypeUuidEqualizer(),
|
||||
.uuid = getEffectImplUuidEqualizerSw()},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = EqualizerSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = EqualizerSw::kEqCap};
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDesc.toString();
|
||||
*_aidl_return = kDesc;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::equalizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& eqParam = specific.get<Parameter::Specific::equalizer>();
|
||||
RETURN_IF(!inRange(eqParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
auto tag = eqParam.getTag();
|
||||
switch (tag) {
|
||||
case Equalizer::preset: {
|
||||
RETURN_IF(mContext->setEqPreset(eqParam.get<Equalizer::preset>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Equalizer::bandLevels: {
|
||||
RETURN_IF(mContext->setEqBandLevels(eqParam.get<Equalizer::bandLevels>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"EqTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
LOG(ERROR) << __func__ << " unsupported eq param tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"ParamNotSupported");
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::equalizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto eqId = id.get<Parameter::Id::equalizerTag>();
|
||||
auto eqIdTag = eqId.getTag();
|
||||
switch (eqIdTag) {
|
||||
case Equalizer::Id::commonTag:
|
||||
return getParameterEqualizer(eqId.get<Equalizer::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " tag " << toString(eqIdTag) << " not supported";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"EqualizerTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::getParameterEqualizer(const Equalizer::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
Equalizer eqParam;
|
||||
switch (tag) {
|
||||
case Equalizer::bandLevels: {
|
||||
eqParam.set<Equalizer::bandLevels>(mContext->getEqBandLevels());
|
||||
break;
|
||||
}
|
||||
case Equalizer::preset: {
|
||||
eqParam.set<Equalizer::preset>(mContext->getEqPreset());
|
||||
break;
|
||||
}
|
||||
case Equalizer::centerFreqMh: {
|
||||
eqParam.set<Equalizer::centerFreqMh>(mContext->getCenterFreqs());
|
||||
break;
|
||||
}
|
||||
case Equalizer::bandFrequencies: {
|
||||
eqParam.set<Equalizer::bandFrequencies>(kBandFrequency);
|
||||
break;
|
||||
}
|
||||
case Equalizer::presets: {
|
||||
eqParam.set<Equalizer::presets>(kPresets);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"unsupportedTag");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::equalizer>(eqParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> EqualizerSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<EqualizerSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode EqualizerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status EqualizerSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class EqualizerSwContext final : public EffectContext {
|
||||
public:
|
||||
EqualizerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setEqPreset(const int& presetIdx) {
|
||||
if (presetIdx < 0 || presetIdx >= kMaxPresetNumber) {
|
||||
return RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
mPreset = presetIdx;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
int getEqPreset() { return mPreset; }
|
||||
|
||||
RetCode setEqBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels) {
|
||||
if (bandLevels.size() > kMaxBandNumber) {
|
||||
LOG(ERROR) << __func__ << " return because size exceed " << kMaxBandNumber;
|
||||
return RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
RetCode ret = RetCode::SUCCESS;
|
||||
for (auto& it : bandLevels) {
|
||||
if (it.index >= kMaxBandNumber || it.index < 0) {
|
||||
LOG(ERROR) << __func__ << " index illegal, skip: " << it.index << " - "
|
||||
<< it.levelMb;
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
} else {
|
||||
mBandLevels[it.index] = it.levelMb;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Equalizer::BandLevel> getEqBandLevels() {
|
||||
std::vector<Equalizer::BandLevel> bandLevels;
|
||||
for (int i = 0; i < kMaxBandNumber; i++) {
|
||||
bandLevels.push_back({i, mBandLevels[i]});
|
||||
}
|
||||
return bandLevels;
|
||||
}
|
||||
|
||||
std::vector<int> getCenterFreqs() {
|
||||
return {std::begin(kPresetsFrequencies), std::end(kPresetsFrequencies)};
|
||||
}
|
||||
static const int kMaxBandNumber = 5;
|
||||
static const int kMaxPresetNumber = 10;
|
||||
static const int kCustomPreset = -1;
|
||||
|
||||
private:
|
||||
static constexpr std::array<uint16_t, kMaxBandNumber> kPresetsFrequencies = {60, 230, 910, 3600,
|
||||
14000};
|
||||
// preset band level
|
||||
int mPreset = kCustomPreset;
|
||||
int32_t mBandLevels[kMaxBandNumber] = {3, 0, 0, 0, 3};
|
||||
|
||||
// Add equalizer specific context for processing here
|
||||
};
|
||||
|
||||
class EqualizerSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kEqCap;
|
||||
static const Descriptor kDesc;
|
||||
|
||||
EqualizerSw() { LOG(DEBUG) << __func__; }
|
||||
~EqualizerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
std::string getEffectName() override { return kEffectName; }
|
||||
|
||||
private:
|
||||
static const std::vector<Equalizer::BandFrequency> kBandFrequency;
|
||||
static const std::vector<Equalizer::Preset> kPresets;
|
||||
static const std::vector<Range::EqualizerRange> kRanges;
|
||||
ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
|
||||
Parameter::Specific* specific) REQUIRES(mImplMutex);
|
||||
std::shared_ptr<EqualizerSwContext> mContext;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "liberasersw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"Eraser.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AHAL_Eraser"
|
||||
|
||||
#include "Eraser.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
using aidl::android::hardware::audio::common::getChannelCount;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::EraserSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidEraserSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidEraser;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioChannelLayout;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEraserSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (!instanceSpp) {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
*instanceSpp = ndk::SharedRefBase::make<EraserSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEraserSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = EraserSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string EraserSw::kEffectName = "EraserSw";
|
||||
const Descriptor EraserSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidEraser(), .uuid = getEffectImplUuidEraserSw()},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.hwAcceleratorMode = Flags::HardwareAccelerator::NONE},
|
||||
.name = EraserSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"}};
|
||||
|
||||
ndk::ScopedAStatus EraserSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EraserSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::eraser != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& param = specific.get<Parameter::Specific::eraser>();
|
||||
return mContext->setParam(param.getTag(), param);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EraserSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::eraserTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto eraserId = id.get<Parameter::Id::eraserTag>();
|
||||
auto eraserTag = eraserId.getTag();
|
||||
switch (eraserTag) {
|
||||
case Eraser::Id::commonTag: {
|
||||
auto specificTag = eraserId.get<Eraser::Id::commonTag>();
|
||||
std::optional<Eraser> param = mContext->getParam(specificTag);
|
||||
if (!param.has_value()) {
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"EraserTagNotSupported");
|
||||
}
|
||||
specific->set<Parameter::Specific::eraser>(param.value());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"EraserTagNotSupported");
|
||||
}
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> EraserSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<EraserSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode EraserSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
EraserSw::~EraserSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EraserSw::command(CommandId command) {
|
||||
std::lock_guard lg(mImplMutex);
|
||||
RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen");
|
||||
|
||||
switch (command) {
|
||||
case CommandId::START:
|
||||
RETURN_OK_IF(mState == State::PROCESSING);
|
||||
mState = State::PROCESSING;
|
||||
mContext->enable();
|
||||
startThread();
|
||||
RETURN_IF(notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
|
||||
"notifyEventFlagNotEmptyFailed");
|
||||
break;
|
||||
case CommandId::STOP:
|
||||
RETURN_OK_IF(mState == State::IDLE || mState == State::DRAINING);
|
||||
if (mVersion < kDrainSupportedVersion) {
|
||||
mState = State::IDLE;
|
||||
stopThread();
|
||||
mContext->disable();
|
||||
} else {
|
||||
mState = State::DRAINING;
|
||||
startDraining();
|
||||
mContext->startDraining();
|
||||
}
|
||||
RETURN_IF(notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
|
||||
"notifyEventFlagNotEmptyFailed");
|
||||
break;
|
||||
case CommandId::RESET:
|
||||
mState = State::IDLE;
|
||||
RETURN_IF(notifyEventFlag(mDataMqNotEmptyEf) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
|
||||
"notifyEventFlagNotEmptyFailed");
|
||||
stopThread();
|
||||
mImplContext->disable();
|
||||
mImplContext->reset();
|
||||
mImplContext->resetBuffer();
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << getEffectNameWithVersion() << __func__ << " instance still processing";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"CommandIdNotSupported");
|
||||
}
|
||||
LOG(VERBOSE) << getEffectNameWithVersion() << __func__
|
||||
<< " transfer to state: " << toString(mState);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status EraserSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
RETURN_VALUE_IF(!mContext, (IEffect::Status{EX_NULL_POINTER, 0, 0}), "nullContext");
|
||||
IEffect::Status procStatus{STATUS_NOT_ENOUGH_DATA, 0, 0};
|
||||
procStatus = mContext->process(in, out, samples);
|
||||
if (mState == State::DRAINING && procStatus.status == STATUS_NOT_ENOUGH_DATA) {
|
||||
drainingComplete_l();
|
||||
}
|
||||
|
||||
return procStatus;
|
||||
}
|
||||
|
||||
void EraserSw::drainingComplete_l() {
|
||||
if (mState != State::DRAINING) return;
|
||||
|
||||
LOG(DEBUG) << getEffectNameWithVersion() << __func__;
|
||||
finishDraining();
|
||||
mState = State::IDLE;
|
||||
}
|
||||
|
||||
EraserSwContext::EraserSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
EraserSwContext::~EraserSwContext() {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
template <typename TAG>
|
||||
std::optional<Eraser> EraserSwContext::getParam(TAG tag) {
|
||||
if (mParamsMap.find(tag) != mParamsMap.end()) {
|
||||
return mParamsMap.at(tag);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename TAG>
|
||||
ndk::ScopedAStatus EraserSwContext::setParam(TAG tag, Eraser eraser) {
|
||||
mParamsMap[tag] = eraser;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
IEffect::Status EraserSwContext::process(float* in, float* out, int samples) {
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
IEffect::Status procStatus = {EX_ILLEGAL_ARGUMENT, 0, 0};
|
||||
const auto inputChannelCount = getChannelCount(mCommon.input.base.channelMask);
|
||||
const auto outputChannelCount = getChannelCount(mCommon.output.base.channelMask);
|
||||
if (inputChannelCount < outputChannelCount) {
|
||||
LOG(ERROR) << __func__ << " invalid channel count, in: " << inputChannelCount
|
||||
<< " out: " << outputChannelCount;
|
||||
return procStatus;
|
||||
}
|
||||
|
||||
if (samples <= 0 || 0 != samples % inputChannelCount) {
|
||||
LOG(ERROR) << __func__ << " invalid samples: " << samples;
|
||||
return procStatus;
|
||||
}
|
||||
|
||||
const int iFrames = samples / inputChannelCount;
|
||||
const float gainPerSample = 1.f / iFrames;
|
||||
for (int i = 0; i < iFrames; i++) {
|
||||
if (isDraining()) {
|
||||
const float gain = (iFrames - i - 1) * gainPerSample;
|
||||
for (size_t c = 0; c < outputChannelCount; c++) {
|
||||
out[c] = in[c] * gain;
|
||||
}
|
||||
} else {
|
||||
std::memcpy(out, in, outputChannelCount * sizeof(float));
|
||||
}
|
||||
|
||||
in += inputChannelCount;
|
||||
out += outputChannelCount;
|
||||
}
|
||||
|
||||
// drain for one cycle
|
||||
if (isDraining()) {
|
||||
procStatus.status = STATUS_NOT_ENOUGH_DATA;
|
||||
finishDraining();
|
||||
} else {
|
||||
procStatus.status = STATUS_OK;
|
||||
}
|
||||
procStatus.fmqConsumed = static_cast<int32_t>(iFrames * inputChannelCount);
|
||||
procStatus.fmqProduced = static_cast<int32_t>(iFrames * outputChannelCount);
|
||||
|
||||
return procStatus;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect-impl/EffectContext.h"
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class EraserSwContext final : public EffectContext {
|
||||
public:
|
||||
EraserSwContext(int statusDepth, const Parameter::Common& common);
|
||||
~EraserSwContext() final;
|
||||
|
||||
template <typename TAG>
|
||||
std::optional<Eraser> getParam(TAG tag);
|
||||
template <typename TAG>
|
||||
ndk::ScopedAStatus setParam(TAG tag, Eraser eraser);
|
||||
|
||||
IEffect::Status process(float* in, float* out, int samples);
|
||||
|
||||
private:
|
||||
std::unordered_map<Eraser::Tag, Eraser> mParamsMap;
|
||||
};
|
||||
|
||||
class EraserSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
~EraserSw() final;
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) final;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) final;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) final;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) final;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) final;
|
||||
|
||||
std::string getEffectName() final { return kEffectName; };
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) final;
|
||||
|
||||
ndk::ScopedAStatus command(CommandId command) final;
|
||||
void drainingComplete_l() REQUIRES(mImplMutex);
|
||||
|
||||
private:
|
||||
static const std::vector<Range::SpatializerRange> kRanges;
|
||||
std::shared_ptr<EraserSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libextensioneffect",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"ExtensionEffect.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
|
||||
#define LOG_TAG "AHAL_ExtensionEffect"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "ExtensionEffect.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::DefaultExtension;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::ExtensionEffect;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidExtension;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidExtension;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::Range;
|
||||
using aidl::android::hardware::audio::effect::VendorExtension;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidExtension()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<ExtensionEffect>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidExtension()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = ExtensionEffect::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string ExtensionEffect::kEffectName = "ExtensionEffectExample";
|
||||
|
||||
const Descriptor ExtensionEffect::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidExtension(),
|
||||
.uuid = getEffectImplUuidExtension(),
|
||||
.proxy = std::nullopt},
|
||||
.name = ExtensionEffect::kEffectName,
|
||||
.implementor = "The Android Open Source Project"}};
|
||||
|
||||
ndk::ScopedAStatus ExtensionEffect::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus ExtensionEffect::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::vendorEffect != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& vendorEffect = specific.get<Parameter::Specific::vendorEffect>();
|
||||
std::optional<DefaultExtension> defaultExt;
|
||||
RETURN_IF(STATUS_OK != vendorEffect.extension.getParcelable(&defaultExt), EX_ILLEGAL_ARGUMENT,
|
||||
"getParcelableFailed");
|
||||
RETURN_IF(!defaultExt.has_value(), EX_ILLEGAL_ARGUMENT, "parcelableNull");
|
||||
RETURN_IF(mContext->setParams(defaultExt->bytes) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT,
|
||||
"paramNotSupported");
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus ExtensionEffect::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::vendorEffectTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto extensionId = id.get<Parameter::Id::vendorEffectTag>();
|
||||
std::optional<DefaultExtension> defaultIdExt;
|
||||
RETURN_IF(STATUS_OK != extensionId.extension.getParcelable(&defaultIdExt), EX_ILLEGAL_ARGUMENT,
|
||||
"getIdParcelableFailed");
|
||||
RETURN_IF(!defaultIdExt.has_value(), EX_ILLEGAL_ARGUMENT, "parcelableIdNull");
|
||||
|
||||
VendorExtension extension;
|
||||
DefaultExtension defaultExt;
|
||||
defaultExt.bytes = mContext->getParams(defaultIdExt->bytes);
|
||||
RETURN_IF(STATUS_OK != extension.extension.setParcelable(defaultExt), EX_ILLEGAL_ARGUMENT,
|
||||
"setParcelableFailed");
|
||||
specific->set<Parameter::Specific::vendorEffect>(extension);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> ExtensionEffect::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<ExtensionEffectContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode ExtensionEffect::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status ExtensionEffect::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class ExtensionEffectContext final : public EffectContext {
|
||||
public:
|
||||
ExtensionEffectContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setParams(const std::vector<uint8_t>& params) {
|
||||
mParams = params;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
std::vector<uint8_t> getParams(std::vector<uint8_t> id __unused) const { return mParams; }
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> mParams;
|
||||
};
|
||||
|
||||
class ExtensionEffect final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
ExtensionEffect() { LOG(DEBUG) << __func__; }
|
||||
~ExtensionEffect() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
std::string getEffectName() override { return kEffectName; };
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ExtensionEffectContext> mContext GUARDED_BY(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libhapticgeneratorsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"HapticGeneratorSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
#define LOG_TAG "AHAL_HapticGeneratorSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "HapticGeneratorSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidHapticGeneratorSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator;
|
||||
using aidl::android::hardware::audio::effect::HapticGeneratorSw;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidHapticGeneratorSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<HapticGeneratorSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidHapticGeneratorSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = HapticGeneratorSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string HapticGeneratorSw::kEffectName = "HapticGeneratorSw";
|
||||
/* Effect descriptor */
|
||||
const Descriptor HapticGeneratorSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidHapticGenerator(),
|
||||
.uuid = getEffectImplUuidHapticGeneratorSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = HapticGeneratorSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"}};
|
||||
|
||||
ndk::ScopedAStatus HapticGeneratorSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HapticGeneratorSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& hgParam = specific.get<Parameter::Specific::hapticGenerator>();
|
||||
auto tag = hgParam.getTag();
|
||||
|
||||
switch (tag) {
|
||||
case HapticGenerator::hapticScales: {
|
||||
RETURN_IF(mContext->setHgHapticScales(hgParam.get<HapticGenerator::hapticScales>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "HapticScaleNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case HapticGenerator::vibratorInfo: {
|
||||
RETURN_IF(mContext->setHgVibratorInformation(
|
||||
hgParam.get<HapticGenerator::vibratorInfo>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "VibratorInfoNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HapticGeneratorSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::hapticGeneratorTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto hgId = id.get<Parameter::Id::hapticGeneratorTag>();
|
||||
auto hgIdTag = hgId.getTag();
|
||||
switch (hgIdTag) {
|
||||
case HapticGenerator::Id::commonTag:
|
||||
return getParameterHapticGenerator(hgId.get<HapticGenerator::Id::commonTag>(),
|
||||
specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HapticGeneratorSw::getParameterHapticGenerator(const HapticGenerator::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
HapticGenerator hgParam;
|
||||
switch (tag) {
|
||||
case HapticGenerator::hapticScales: {
|
||||
hgParam.set<HapticGenerator::hapticScales>(mContext->getHgHapticScales());
|
||||
break;
|
||||
}
|
||||
case HapticGenerator::vibratorInfo: {
|
||||
hgParam.set<HapticGenerator::vibratorInfo>(mContext->getHgVibratorInformation());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::hapticGenerator>(hgParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> HapticGeneratorSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<HapticGeneratorSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode HapticGeneratorSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status HapticGeneratorSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode HapticGeneratorSwContext::setHgHapticScales(
|
||||
const std::vector<HapticGenerator::HapticScale>& hapticScales) {
|
||||
// Assume any audio track ID is valid
|
||||
for (auto& it : hapticScales) {
|
||||
mHapticScales[it.id] = it;
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
std::vector<HapticGenerator::HapticScale> HapticGeneratorSwContext::getHgHapticScales() const {
|
||||
std::vector<HapticGenerator::HapticScale> result;
|
||||
std::transform(mHapticScales.begin(), mHapticScales.end(), std::back_inserter(result),
|
||||
[](auto& scaleIt) { return scaleIt.second; });
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class HapticGeneratorSwContext final : public EffectContext {
|
||||
public:
|
||||
HapticGeneratorSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale>& hapticScales);
|
||||
std::vector<HapticGenerator::HapticScale> getHgHapticScales() const;
|
||||
|
||||
RetCode setHgVibratorInformation(const HapticGenerator::VibratorInformation& vibratorInfo) {
|
||||
// All float values are valid for resonantFrequencyHz, qFactor, maxAmplitude
|
||||
mVibratorInformation = vibratorInfo;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
HapticGenerator::VibratorInformation getHgVibratorInformation() const {
|
||||
return mVibratorInformation;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr float DEFAULT_RESONANT_FREQUENCY = 150.0f;
|
||||
static constexpr float DEFAULT_Q_FACTOR = 1.0f;
|
||||
static constexpr float DEFAULT_MAX_AMPLITUDE = 0.0f;
|
||||
std::map<int /* trackID */, HapticGenerator::HapticScale> mHapticScales;
|
||||
HapticGenerator::VibratorInformation mVibratorInformation = {
|
||||
DEFAULT_RESONANT_FREQUENCY, DEFAULT_Q_FACTOR, DEFAULT_MAX_AMPLITUDE};
|
||||
};
|
||||
|
||||
class HapticGeneratorSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Descriptor kDescriptor;
|
||||
HapticGeneratorSw() { LOG(DEBUG) << __func__; }
|
||||
~HapticGeneratorSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
std::string getEffectName() override { return kEffectName; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<HapticGeneratorSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
|
||||
ndk::ScopedAStatus getParameterHapticGenerator(const HapticGenerator::Tag& tag,
|
||||
Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libloudnessenhancersw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"LoudnessEnhancerSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
#define LOG_TAG "AHAL_LoudnessEnhancerSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "LoudnessEnhancerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidLoudnessEnhancerSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::LoudnessEnhancerSw;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidLoudnessEnhancerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<LoudnessEnhancerSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidLoudnessEnhancerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = LoudnessEnhancerSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string LoudnessEnhancerSw::kEffectName = "LoudnessEnhancerSw";
|
||||
const Descriptor LoudnessEnhancerSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidLoudnessEnhancer(),
|
||||
.uuid = getEffectImplUuidLoudnessEnhancerSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = LoudnessEnhancerSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"}};
|
||||
|
||||
ndk::ScopedAStatus LoudnessEnhancerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus LoudnessEnhancerSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::loudnessEnhancer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& leParam = specific.get<Parameter::Specific::loudnessEnhancer>();
|
||||
auto tag = leParam.getTag();
|
||||
|
||||
switch (tag) {
|
||||
case LoudnessEnhancer::gainMb: {
|
||||
RETURN_IF(mContext->setLeGainMb(leParam.get<LoudnessEnhancer::gainMb>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setGainMbFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus LoudnessEnhancerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::loudnessEnhancerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto leId = id.get<Parameter::Id::loudnessEnhancerTag>();
|
||||
auto leIdTag = leId.getTag();
|
||||
switch (leIdTag) {
|
||||
case LoudnessEnhancer::Id::commonTag:
|
||||
return getParameterLoudnessEnhancer(leId.get<LoudnessEnhancer::Id::commonTag>(),
|
||||
specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(leIdTag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus LoudnessEnhancerSw::getParameterLoudnessEnhancer(
|
||||
const LoudnessEnhancer::Tag& tag, Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
LoudnessEnhancer leParam;
|
||||
switch (tag) {
|
||||
case LoudnessEnhancer::gainMb: {
|
||||
leParam.set<LoudnessEnhancer::gainMb>(mContext->getLeGainMb());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::loudnessEnhancer>(leParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> LoudnessEnhancerSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<LoudnessEnhancerSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode LoudnessEnhancerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status LoudnessEnhancerSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class LoudnessEnhancerSwContext final : public EffectContext {
|
||||
public:
|
||||
LoudnessEnhancerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setLeGainMb(int gainMb) {
|
||||
// TODO : Add implementation to apply new gain
|
||||
mGainMb = gainMb;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
int getLeGainMb() const { return mGainMb; }
|
||||
|
||||
private:
|
||||
int mGainMb = 0; // Default Gain
|
||||
};
|
||||
|
||||
class LoudnessEnhancerSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Descriptor kDescriptor;
|
||||
LoudnessEnhancerSw() { LOG(DEBUG) << __func__; }
|
||||
~LoudnessEnhancerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
std::string getEffectName() override { return kEffectName; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<LoudnessEnhancerSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
|
||||
Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libnssw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"NoiseSuppressionSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#define LOG_TAG "AHAL_NoiseSuppressionSw"
|
||||
|
||||
#define LOG_TAG "AHAL_NoiseSuppressionSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "NoiseSuppressionSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidNoiseSuppressionSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::NoiseSuppressionSw;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidNoiseSuppressionSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<NoiseSuppressionSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidNoiseSuppressionSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = NoiseSuppressionSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string NoiseSuppressionSw::kEffectName = "NoiseSuppressionSw";
|
||||
const Descriptor NoiseSuppressionSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidNoiseSuppression(),
|
||||
.uuid = getEffectImplUuidNoiseSuppressionSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::PRE_PROC,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::NONE},
|
||||
.name = NoiseSuppressionSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"}};
|
||||
|
||||
ndk::ScopedAStatus NoiseSuppressionSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus NoiseSuppressionSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::noiseSuppression != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& param = specific.get<Parameter::Specific::noiseSuppression>();
|
||||
auto tag = param.getTag();
|
||||
|
||||
switch (tag) {
|
||||
case NoiseSuppression::level: {
|
||||
RETURN_IF(mContext->setLevel(param.get<NoiseSuppression::level>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "levelNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case NoiseSuppression::type: {
|
||||
RETURN_IF(mContext->setType(param.get<NoiseSuppression::type>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "typeNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case NoiseSuppression::vendor: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus NoiseSuppressionSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::noiseSuppressionTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto specificId = id.get<Parameter::Id::noiseSuppressionTag>();
|
||||
auto specificIdTag = specificId.getTag();
|
||||
switch (specificIdTag) {
|
||||
case NoiseSuppression::Id::commonTag:
|
||||
return getParameterNoiseSuppression(specificId.get<NoiseSuppression::Id::commonTag>(),
|
||||
specific);
|
||||
case NoiseSuppression::Id::vendorExtensionTag: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus NoiseSuppressionSw::getParameterNoiseSuppression(
|
||||
const NoiseSuppression::Tag& tag, Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
NoiseSuppression param;
|
||||
switch (tag) {
|
||||
case NoiseSuppression::level: {
|
||||
param.set<NoiseSuppression::level>(mContext->getLevel());
|
||||
break;
|
||||
}
|
||||
case NoiseSuppression::type: {
|
||||
param.set<NoiseSuppression::type>(mContext->getType());
|
||||
break;
|
||||
}
|
||||
case NoiseSuppression::vendor: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::noiseSuppression>(param);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> NoiseSuppressionSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<NoiseSuppressionSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode NoiseSuppressionSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status NoiseSuppressionSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode NoiseSuppressionSwContext::setLevel(NoiseSuppression::Level level) {
|
||||
mLevel = level;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
NoiseSuppression::Level NoiseSuppressionSwContext::getLevel() {
|
||||
return mLevel;
|
||||
}
|
||||
|
||||
RetCode NoiseSuppressionSwContext::setType(NoiseSuppression::Type type) {
|
||||
mType = type;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class NoiseSuppressionSwContext final : public EffectContext {
|
||||
public:
|
||||
NoiseSuppressionSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setLevel(NoiseSuppression::Level level);
|
||||
NoiseSuppression::Level getLevel();
|
||||
RetCode setType(NoiseSuppression::Type type);
|
||||
NoiseSuppression::Type getType() { return mType; }
|
||||
|
||||
private:
|
||||
NoiseSuppression::Level mLevel = NoiseSuppression::Level::LOW;
|
||||
NoiseSuppression::Type mType = NoiseSuppression::Type::SINGLE_CHANNEL;
|
||||
};
|
||||
|
||||
class NoiseSuppressionSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const bool kStrengthSupported;
|
||||
static const Descriptor kDescriptor;
|
||||
NoiseSuppressionSw() { LOG(DEBUG) << __func__; }
|
||||
~NoiseSuppressionSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
std::string getEffectName() override { return kEffectName; };
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<NoiseSuppressionSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
ndk::ScopedAStatus getParameterNoiseSuppression(const NoiseSuppression::Tag& tag,
|
||||
Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libpresetreverbsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"PresetReverbSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
#define LOG_TAG "AHAL_PresetReverbSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_enums.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "PresetReverbSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidPresetReverbSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::PresetReverbSw;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidPresetReverbSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<PresetReverbSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidPresetReverbSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = PresetReverbSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string PresetReverbSw::kEffectName = "PresetReverbSw";
|
||||
|
||||
const std::vector<PresetReverb::Presets> PresetReverbSw::kSupportedPresets{
|
||||
ndk::enum_range<PresetReverb::Presets>().begin(),
|
||||
ndk::enum_range<PresetReverb::Presets>().end()};
|
||||
|
||||
const std::vector<Range::PresetReverbRange> PresetReverbSw::kRanges = {
|
||||
MAKE_RANGE(PresetReverb, supportedPresets, PresetReverbSw::kSupportedPresets,
|
||||
PresetReverbSw::kSupportedPresets)};
|
||||
|
||||
const Capability PresetReverbSw::kCapability = {
|
||||
.range = Range::make<Range::presetReverb>(PresetReverbSw::kRanges)};
|
||||
|
||||
const Descriptor PresetReverbSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidPresetReverb(),
|
||||
.uuid = getEffectImplUuidPresetReverbSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = PresetReverbSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = PresetReverbSw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus PresetReverbSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus PresetReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::presetReverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& prParam = specific.get<Parameter::Specific::presetReverb>();
|
||||
RETURN_IF(!inRange(prParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
auto tag = prParam.getTag();
|
||||
|
||||
switch (tag) {
|
||||
case PresetReverb::preset: {
|
||||
RETURN_IF(
|
||||
mContext->setPRPreset(prParam.get<PresetReverb::preset>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setPresetFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"PresetReverbTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus PresetReverbSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::presetReverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto prId = id.get<Parameter::Id::presetReverbTag>();
|
||||
auto prIdTag = prId.getTag();
|
||||
switch (prIdTag) {
|
||||
case PresetReverb::Id::commonTag:
|
||||
return getParameterPresetReverb(prId.get<PresetReverb::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"PresetReverbTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus PresetReverbSw::getParameterPresetReverb(const PresetReverb::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
PresetReverb prParam;
|
||||
switch (tag) {
|
||||
case PresetReverb::preset: {
|
||||
prParam.set<PresetReverb::preset>(mContext->getPRPreset());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"PresetReverbTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::presetReverb>(prParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> PresetReverbSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<PresetReverbSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode PresetReverbSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status PresetReverbSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class PresetReverbSwContext final : public EffectContext {
|
||||
public:
|
||||
PresetReverbSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
RetCode setPRPreset(PresetReverb::Presets preset) {
|
||||
// TODO : Add implementation to modify Presets
|
||||
mPreset = preset;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
PresetReverb::Presets getPRPreset() const { return mPreset; }
|
||||
|
||||
private:
|
||||
PresetReverb::Presets mPreset = PresetReverb::Presets::NONE;
|
||||
};
|
||||
|
||||
class PresetReverbSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const std::vector<PresetReverb::Presets> kSupportedPresets;
|
||||
static const std::vector<Range::PresetReverbRange> kRanges;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
PresetReverbSw() { LOG(DEBUG) << __func__; }
|
||||
~PresetReverbSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
std::string getEffectName() override { return kEffectName; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<PresetReverbSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
|
||||
ndk::ScopedAStatus getParameterPresetReverb(const PresetReverb::Tag& tag,
|
||||
Parameter::Specific* specific) REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libspatializersw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"SpatializerSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AHAL_SpatializerSw"
|
||||
|
||||
#include "SpatializerSw.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
using aidl::android::hardware::audio::common::getChannelCount;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidSpatializerSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::SpatializerSw;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioChannelLayout;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
using aidl::android::media::audio::common::HeadTracking;
|
||||
using aidl::android::media::audio::common::Spatialization;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidSpatializerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (!instanceSpp) {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
*instanceSpp = ndk::SharedRefBase::make<SpatializerSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidSpatializerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = SpatializerSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string SpatializerSw::kEffectName = "SpatializerSw";
|
||||
|
||||
const AudioChannelLayout kSupportedChannelMask =
|
||||
AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
|
||||
AudioChannelLayout::LAYOUT_5POINT1);
|
||||
const std::vector<Range::SpatializerRange> SpatializerSw::kRanges = {
|
||||
MAKE_RANGE(Spatializer, supportedChannelLayout, {kSupportedChannelMask},
|
||||
{kSupportedChannelMask}),
|
||||
MAKE_RANGE(Spatializer, spatializationLevel, Spatialization::Level::NONE,
|
||||
Spatialization::Level::BED_PLUS_OBJECTS),
|
||||
MAKE_RANGE(Spatializer, spatializationMode, Spatialization::Mode::BINAURAL,
|
||||
Spatialization::Mode::TRANSAURAL),
|
||||
MAKE_RANGE(Spatializer, headTrackingSensorId, std::numeric_limits<int>::min(),
|
||||
std::numeric_limits<int>::max()),
|
||||
MAKE_RANGE(Spatializer, headTrackingMode, HeadTracking::Mode::OTHER,
|
||||
HeadTracking::Mode::RELATIVE_SCREEN),
|
||||
MAKE_RANGE(Spatializer, headTrackingConnectionMode,
|
||||
HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED,
|
||||
HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_TUNNEL)};
|
||||
const Capability SpatializerSw::kCapability = {.range = {SpatializerSw::kRanges}};
|
||||
const Descriptor SpatializerSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidSpatializer(),
|
||||
.uuid = getEffectImplUuidSpatializerSw()},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.hwAcceleratorMode = Flags::HardwareAccelerator::NONE},
|
||||
.name = SpatializerSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = SpatializerSw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus SpatializerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus SpatializerSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::spatializer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& param = specific.get<Parameter::Specific::spatializer>();
|
||||
RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
|
||||
return mContext->setParam(param.getTag(), param);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus SpatializerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::spatializerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto spatializerId = id.get<Parameter::Id::spatializerTag>();
|
||||
auto spatializerTag = spatializerId.getTag();
|
||||
switch (spatializerTag) {
|
||||
case Spatializer::Id::commonTag: {
|
||||
auto specificTag = spatializerId.get<Spatializer::Id::commonTag>();
|
||||
std::optional<Spatializer> param = mContext->getParam(specificTag);
|
||||
if (!param.has_value()) {
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
|
||||
EX_ILLEGAL_ARGUMENT, "SpatializerTagNotSupported");
|
||||
}
|
||||
specific->set<Parameter::Specific::spatializer>(param.value());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"SpatializerTagNotSupported");
|
||||
}
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> SpatializerSw::createContext(const Parameter::Common& common) {
|
||||
if (common.input.base.channelMask != kSupportedChannelMask) {
|
||||
LOG(ERROR) << __func__
|
||||
<< " channelMask not supported: " << common.input.base.channelMask.toString();
|
||||
return nullptr;
|
||||
}
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<SpatializerSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode SpatializerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
SpatializerSw::~SpatializerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status SpatializerSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
RETURN_VALUE_IF(!mContext, (IEffect::Status{EX_NULL_POINTER, 0, 0}), "nullContext");
|
||||
return mContext->process(in, out, samples);
|
||||
}
|
||||
|
||||
SpatializerSwContext::SpatializerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
SpatializerSwContext::~SpatializerSwContext() {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
template <typename TAG>
|
||||
std::optional<Spatializer> SpatializerSwContext::getParam(TAG tag) {
|
||||
if (mParamsMap.find(tag) != mParamsMap.end()) {
|
||||
return mParamsMap.at(tag);
|
||||
}
|
||||
if (tag == Spatializer::supportedChannelLayout) {
|
||||
return Spatializer::make<Spatializer::supportedChannelLayout>(
|
||||
{AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
|
||||
AudioChannelLayout::LAYOUT_5POINT1)});
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename TAG>
|
||||
ndk::ScopedAStatus SpatializerSwContext::setParam(TAG tag, Spatializer spatializer) {
|
||||
RETURN_IF(tag == Spatializer::supportedChannelLayout, EX_ILLEGAL_ARGUMENT,
|
||||
"supportedChannelLayoutGetOnly");
|
||||
|
||||
mParamsMap[tag] = spatializer;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
IEffect::Status SpatializerSwContext::process(float* in, float* out, int samples) {
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
IEffect::Status status = {EX_ILLEGAL_ARGUMENT, 0, 0};
|
||||
|
||||
const auto inputChannelCount = getChannelCount(mCommon.input.base.channelMask);
|
||||
const auto outputChannelCount = getChannelCount(mCommon.output.base.channelMask);
|
||||
if (outputChannelCount < 2 || inputChannelCount < outputChannelCount) {
|
||||
LOG(ERROR) << __func__ << " invalid channel count, in: " << inputChannelCount
|
||||
<< " out: " << outputChannelCount;
|
||||
return status;
|
||||
}
|
||||
|
||||
int iFrames = samples / inputChannelCount;
|
||||
for (int i = 0; i < iFrames; i++) {
|
||||
std::memcpy(out, in, outputChannelCount);
|
||||
in += inputChannelCount;
|
||||
out += outputChannelCount;
|
||||
}
|
||||
return {STATUS_OK, static_cast<int32_t>(iFrames * inputChannelCount),
|
||||
static_cast<int32_t>(iFrames * outputChannelCount)};
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect-impl/EffectContext.h"
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class SpatializerSwContext final : public EffectContext {
|
||||
public:
|
||||
SpatializerSwContext(int statusDepth, const Parameter::Common& common);
|
||||
~SpatializerSwContext();
|
||||
|
||||
template <typename TAG>
|
||||
std::optional<Spatializer> getParam(TAG tag);
|
||||
template <typename TAG>
|
||||
ndk::ScopedAStatus setParam(TAG tag, Spatializer spatializer);
|
||||
|
||||
IEffect::Status process(float* in, float* out, int samples);
|
||||
|
||||
private:
|
||||
std::unordered_map<Spatializer::Tag, Spatializer> mParamsMap;
|
||||
};
|
||||
|
||||
class SpatializerSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
~SpatializerSw();
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
std::string getEffectName() override { return kEffectName; };
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
private:
|
||||
static const std::vector<Range::SpatializerRange> kRanges;
|
||||
std::shared_ptr<SpatializerSwContext> mContext GUARDED_BY(mImplMutex) = nullptr;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,253 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AlsaUtilsTest"
|
||||
|
||||
#include <alsa/Utils.h>
|
||||
#include <android-base/macros.h>
|
||||
#include <audio_utils/primitives.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <log/log.h>
|
||||
|
||||
extern "C" {
|
||||
#include <tinyalsa/pcm.h>
|
||||
}
|
||||
|
||||
namespace alsa = ::aidl::android::hardware::audio::core::alsa;
|
||||
|
||||
namespace {
|
||||
|
||||
const static constexpr float kInt16tTolerance = 4;
|
||||
const static constexpr float kIntTolerance = 1;
|
||||
const static constexpr float kFloatTolerance = 1e-4;
|
||||
const static constexpr float kUnityGain = 1;
|
||||
const static constexpr int32_t kInt24Min = -(1 << 23);
|
||||
const static constexpr int32_t kInt24Max = (1 << 23) - 1;
|
||||
const static constexpr float kFloatMin = -1;
|
||||
const static constexpr float kFloatMax = 1;
|
||||
const static int32_t kQ8_23Min = 0x80000000;
|
||||
const static int32_t kQ8_23Max = 0x7FFFFFFF;
|
||||
const static std::vector<int16_t> kInt16Buffer = {10000, 100, 0, INT16_MAX,
|
||||
INT16_MIN, -2500, 1000, -5800};
|
||||
const static std::vector<float> kFloatBuffer = {0.5, -0.6, kFloatMin, 0.01, kFloatMax, 0.0};
|
||||
const static std::vector<int32_t> kInt32Buffer = {100, 0, 8000, INT32_MAX, INT32_MIN, -300};
|
||||
const static std::vector<int32_t> kQ8_23Buffer = {
|
||||
kQ8_23Min, kQ8_23Max, 0x00000000, 0x00000001, 0x00400000, static_cast<int32_t>(0xFFD33333)};
|
||||
const static std::vector<int32_t> kInt24Buffer = {200, 10, -100, 0, kInt24Min, kInt24Max};
|
||||
|
||||
template <typename T>
|
||||
void* CopyToBuffer(int& bytesToTransfer, std::vector<T>& destBuffer,
|
||||
const std::vector<T>& srcBuffer) {
|
||||
bytesToTransfer = srcBuffer.size() * sizeof(T);
|
||||
destBuffer = srcBuffer;
|
||||
return destBuffer.data();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void VerifyTypedBufferResults(const std::vector<T>& bufferWithGain, const std::vector<T>& srcBuffer,
|
||||
float gain, float tolerance) {
|
||||
for (size_t i = 0; i < srcBuffer.size(); i++) {
|
||||
EXPECT_NEAR(srcBuffer[i] * gain, static_cast<float>(bufferWithGain[i]), tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void VerifyTypedBufferResultsWithClamp(const std::vector<T>& bufferWithGain,
|
||||
const std::vector<T>& srcBuffer, float gain, float tolerance,
|
||||
T minValue, T maxValue) {
|
||||
for (size_t i = 0; i < srcBuffer.size(); i++) {
|
||||
float expectedResult = std::clamp(srcBuffer[i] * gain, static_cast<float>(minValue),
|
||||
static_cast<float>(maxValue));
|
||||
EXPECT_NEAR(expectedResult, static_cast<float>(bufferWithGain[i]), tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
using ApplyGainTestParameters = std::tuple<pcm_format, int, float>;
|
||||
enum { INDEX_PCM_FORMAT, INDEX_CHANNEL_COUNT, INDEX_GAIN };
|
||||
|
||||
class ApplyGainTest : public ::testing::TestWithParam<ApplyGainTestParameters> {
|
||||
protected:
|
||||
void SetUp() override;
|
||||
void VerifyBufferResult(const pcm_format pcmFormat, const float gain);
|
||||
void VerifyBufferResultWithClamp(const pcm_format pcmFormat, const float gain);
|
||||
|
||||
pcm_format mPcmFormat;
|
||||
int mBufferSizeBytes;
|
||||
void* mBuffer;
|
||||
|
||||
private:
|
||||
std::vector<int16_t> mInt16BufferToConvert;
|
||||
std::vector<float> mFloatBufferToConvert;
|
||||
std::vector<int32_t> mInt32BufferToConvert;
|
||||
std::vector<int32_t> mQ8_23BufferToConvert;
|
||||
std::vector<int32_t> mInt24BufferToConvert;
|
||||
};
|
||||
|
||||
void ApplyGainTest::SetUp() {
|
||||
mPcmFormat = std::get<INDEX_PCM_FORMAT>(GetParam());
|
||||
switch (mPcmFormat) {
|
||||
case PCM_FORMAT_S16_LE:
|
||||
mBuffer = CopyToBuffer(mBufferSizeBytes, mInt16BufferToConvert, kInt16Buffer);
|
||||
break;
|
||||
case PCM_FORMAT_FLOAT_LE:
|
||||
mBuffer = CopyToBuffer(mBufferSizeBytes, mFloatBufferToConvert, kFloatBuffer);
|
||||
break;
|
||||
case PCM_FORMAT_S32_LE:
|
||||
mBuffer = CopyToBuffer(mBufferSizeBytes, mInt32BufferToConvert, kInt32Buffer);
|
||||
break;
|
||||
case PCM_FORMAT_S24_LE:
|
||||
mBuffer = CopyToBuffer(mBufferSizeBytes, mQ8_23BufferToConvert, kQ8_23Buffer);
|
||||
break;
|
||||
case PCM_FORMAT_S24_3LE: {
|
||||
std::vector<int32_t> original32BitBuffer(kInt24Buffer.begin(), kInt24Buffer.end());
|
||||
for (auto& val : original32BitBuffer) {
|
||||
val <<= 8;
|
||||
}
|
||||
mInt24BufferToConvert = std::vector<int32_t>(kInt24Buffer.size());
|
||||
mBufferSizeBytes = kInt24Buffer.size() * 3 * sizeof(uint8_t);
|
||||
memcpy_to_p24_from_i32(reinterpret_cast<uint8_t*>(mInt24BufferToConvert.data()),
|
||||
original32BitBuffer.data(), kInt24Buffer.size());
|
||||
mBuffer = mInt24BufferToConvert.data();
|
||||
} break;
|
||||
default:
|
||||
FAIL() << "Unsupported pcm format: " << mPcmFormat;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyGainTest::VerifyBufferResult(const pcm_format pcmFormat, const float gain) {
|
||||
switch (pcmFormat) {
|
||||
case PCM_FORMAT_S16_LE:
|
||||
VerifyTypedBufferResults(mInt16BufferToConvert, kInt16Buffer, gain, kInt16tTolerance);
|
||||
break;
|
||||
case PCM_FORMAT_FLOAT_LE:
|
||||
VerifyTypedBufferResults(mFloatBufferToConvert, kFloatBuffer, gain, kFloatTolerance);
|
||||
break;
|
||||
case PCM_FORMAT_S32_LE:
|
||||
VerifyTypedBufferResults(mInt32BufferToConvert, kInt32Buffer, gain, kIntTolerance);
|
||||
break;
|
||||
case PCM_FORMAT_S24_LE: {
|
||||
for (size_t i = 0; i < kQ8_23Buffer.size(); i++) {
|
||||
EXPECT_NEAR(float_from_q8_23(kQ8_23Buffer[i]) * gain,
|
||||
static_cast<float>(float_from_q8_23(mQ8_23BufferToConvert[i])),
|
||||
kFloatTolerance);
|
||||
}
|
||||
} break;
|
||||
case PCM_FORMAT_S24_3LE: {
|
||||
size_t bufferSize = kInt24Buffer.size();
|
||||
std::vector<int32_t> result32BitBuffer(bufferSize);
|
||||
memcpy_to_i32_from_p24(result32BitBuffer.data(),
|
||||
reinterpret_cast<uint8_t*>(mInt24BufferToConvert.data()),
|
||||
bufferSize);
|
||||
for (size_t i = 0; i < bufferSize; i++) {
|
||||
EXPECT_NEAR(kInt24Buffer[i] * gain, result32BitBuffer[i] >> 8, kIntTolerance);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyGainTest::VerifyBufferResultWithClamp(const pcm_format pcmFormat, const float gain) {
|
||||
switch (pcmFormat) {
|
||||
case PCM_FORMAT_S16_LE:
|
||||
VerifyTypedBufferResultsWithClamp(mInt16BufferToConvert, kInt16Buffer, gain,
|
||||
kInt16tTolerance, static_cast<int16_t>(INT16_MIN),
|
||||
static_cast<int16_t>(INT16_MAX));
|
||||
break;
|
||||
case PCM_FORMAT_FLOAT_LE:
|
||||
VerifyTypedBufferResultsWithClamp(mFloatBufferToConvert, kFloatBuffer, gain,
|
||||
kFloatTolerance, kFloatMin, kFloatMax);
|
||||
break;
|
||||
case PCM_FORMAT_S32_LE:
|
||||
VerifyTypedBufferResultsWithClamp(mInt32BufferToConvert, kInt32Buffer, gain,
|
||||
kIntTolerance, INT32_MIN, INT32_MAX);
|
||||
break;
|
||||
case PCM_FORMAT_S24_LE: {
|
||||
for (size_t i = 0; i < kQ8_23Buffer.size(); i++) {
|
||||
float expectedResult =
|
||||
std::clamp(float_from_q8_23(kQ8_23Buffer[i]) * gain,
|
||||
float_from_q8_23(kQ8_23Min), float_from_q8_23(kQ8_23Max));
|
||||
EXPECT_NEAR(expectedResult,
|
||||
static_cast<float>(float_from_q8_23(mQ8_23BufferToConvert[i])),
|
||||
kFloatTolerance);
|
||||
}
|
||||
} break;
|
||||
case PCM_FORMAT_S24_3LE: {
|
||||
size_t bufferSize = kInt24Buffer.size();
|
||||
std::vector<int32_t> result32BitBuffer(bufferSize);
|
||||
memcpy_to_i32_from_p24(result32BitBuffer.data(),
|
||||
reinterpret_cast<uint8_t*>(mInt24BufferToConvert.data()),
|
||||
bufferSize);
|
||||
for (size_t i = 0; i < bufferSize; i++) {
|
||||
result32BitBuffer[i] >>= 8;
|
||||
}
|
||||
VerifyTypedBufferResultsWithClamp(result32BitBuffer, kInt24Buffer, gain, kIntTolerance,
|
||||
kInt24Min, kInt24Max);
|
||||
} break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(ApplyGainTest, ApplyGain) {
|
||||
float gain = std::get<INDEX_GAIN>(GetParam());
|
||||
int channelCount = std::get<INDEX_CHANNEL_COUNT>(GetParam());
|
||||
|
||||
alsa::applyGain(mBuffer, gain, mBufferSizeBytes, mPcmFormat, channelCount);
|
||||
|
||||
if (gain <= kUnityGain) {
|
||||
VerifyBufferResult(mPcmFormat, gain);
|
||||
} else {
|
||||
VerifyBufferResultWithClamp(mPcmFormat, gain);
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetApplyGainTestName(const testing::TestParamInfo<ApplyGainTestParameters>& info) {
|
||||
std::string testNameStr;
|
||||
switch (std::get<INDEX_PCM_FORMAT>(info.param)) {
|
||||
case PCM_FORMAT_S16_LE:
|
||||
testNameStr = "S16_LE";
|
||||
break;
|
||||
case PCM_FORMAT_FLOAT_LE:
|
||||
testNameStr = "Float_LE";
|
||||
break;
|
||||
case PCM_FORMAT_S32_LE:
|
||||
testNameStr = "S32_LE";
|
||||
break;
|
||||
case PCM_FORMAT_S24_LE:
|
||||
testNameStr = "S24_LE";
|
||||
break;
|
||||
case PCM_FORMAT_S24_3LE:
|
||||
testNameStr = "S24_3LE";
|
||||
break;
|
||||
default:
|
||||
testNameStr = "UnsupportedPcmFormat";
|
||||
break;
|
||||
}
|
||||
testNameStr += std::get<INDEX_CHANNEL_COUNT>(info.param) == 1 ? "_Mono_" : "_Stereo_";
|
||||
testNameStr += std::get<INDEX_GAIN>(info.param) <= kUnityGain ? "WithoutClamp" : "WithClamp";
|
||||
return testNameStr;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(PerPcmFormat, ApplyGainTest,
|
||||
testing::Combine(testing::Values(PCM_FORMAT_S16_LE, PCM_FORMAT_FLOAT_LE,
|
||||
PCM_FORMAT_S32_LE, PCM_FORMAT_S24_LE,
|
||||
PCM_FORMAT_S24_3LE),
|
||||
testing::Values(1, 2), testing::Values(0.6f, 1.5f)),
|
||||
GetApplyGainTestName);
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// #include <memory>
|
||||
// #include <string>
|
||||
// #include <vector>
|
||||
|
||||
#include <android-base/macros.h>
|
||||
#include <gtest/gtest.h>
|
||||
#define LOG_TAG "AudioPolicyConfigXmlConverterTest"
|
||||
#include <log/log.h>
|
||||
|
||||
#include <core-impl/AudioPolicyConfigXmlConverter.h>
|
||||
#include <media/AidlConversionCppNdk.h>
|
||||
|
||||
using aidl::android::hardware::audio::core::internal::AudioPolicyConfigXmlConverter;
|
||||
using aidl::android::media::audio::common::AudioFormatDescription;
|
||||
|
||||
namespace {
|
||||
|
||||
void ValidateAudioFormatDescription(const AudioFormatDescription& format) {
|
||||
auto conv = ::aidl::android::aidl2legacy_AudioFormatDescription_audio_format_t(format);
|
||||
ASSERT_TRUE(conv.ok()) << format.toString();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(AudioPolicyConfigXmlConverterTest, DefaultSurroundSoundConfigIsValid) {
|
||||
auto config = AudioPolicyConfigXmlConverter::getDefaultSurroundSoundConfig();
|
||||
for (const auto& family : config.formatFamilies) {
|
||||
EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(family.primaryFormat));
|
||||
SCOPED_TRACE(family.primaryFormat.toString());
|
||||
for (const auto& sub : family.subFormats) {
|
||||
EXPECT_NO_FATAL_FAILURE(ValidateAudioFormatDescription(sub));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libvirtualizersw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"VirtualizerSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
|
||||
#define LOG_TAG "AHAL_VirtualizerSw"
|
||||
#include <Utils.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "VirtualizerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidVirtualizerSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::hardware::audio::effect::VirtualizerSw;
|
||||
using aidl::android::media::audio::common::AudioChannelLayout;
|
||||
using aidl::android::media::audio::common::AudioDeviceDescription;
|
||||
using aidl::android::media::audio::common::AudioDeviceType;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVirtualizerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<VirtualizerSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVirtualizerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = VirtualizerSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string VirtualizerSw::kEffectName = "VirtualizerSw";
|
||||
|
||||
const std::vector<Range::VirtualizerRange> VirtualizerSw::kRanges = {
|
||||
MAKE_RANGE(Virtualizer, strengthPm, 0, 1000),
|
||||
/* speakerAngle is get-only, set min > max */
|
||||
MAKE_RANGE(Virtualizer, speakerAngles, {Virtualizer::ChannelAngle({.channel = 1})},
|
||||
{Virtualizer::ChannelAngle({.channel = 0})})};
|
||||
|
||||
const Capability VirtualizerSw::kCapability = {
|
||||
.range = Range::make<Range::virtualizer>(VirtualizerSw::kRanges)};
|
||||
|
||||
const Descriptor VirtualizerSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidVirtualizer(),
|
||||
.uuid = getEffectImplUuidVirtualizerSw()},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = VirtualizerSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = VirtualizerSw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus VirtualizerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VirtualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::virtualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
|
||||
auto& vrParam = specific.get<Parameter::Specific::virtualizer>();
|
||||
RETURN_IF(!inRange(vrParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
auto tag = vrParam.getTag();
|
||||
|
||||
switch (tag) {
|
||||
case Virtualizer::strengthPm: {
|
||||
RETURN_IF(mContext->setVrStrength(vrParam.get<Virtualizer::strengthPm>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setStrengthPmFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Virtualizer::device: {
|
||||
RETURN_IF(mContext->setForcedDevice(vrParam.get<Virtualizer::device>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Virtualizer::speakerAngles:
|
||||
FALLTHROUGH_INTENDED;
|
||||
case Virtualizer::vendor: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"VirtualizerTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VirtualizerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::virtualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto vrId = id.get<Parameter::Id::virtualizerTag>();
|
||||
auto vrIdTag = vrId.getTag();
|
||||
switch (vrIdTag) {
|
||||
case Virtualizer::Id::commonTag:
|
||||
return getParameterVirtualizer(vrId.get<Virtualizer::Id::commonTag>(), specific);
|
||||
case Virtualizer::Id::speakerAnglesPayload:
|
||||
return getSpeakerAngles(vrId.get<Virtualizer::Id::speakerAnglesPayload>(), specific);
|
||||
case Virtualizer::Id::vendorExtensionTag: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"VirtualizerTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VirtualizerSw::getParameterVirtualizer(const Virtualizer::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
Virtualizer vrParam;
|
||||
switch (tag) {
|
||||
case Virtualizer::strengthPm: {
|
||||
vrParam.set<Virtualizer::strengthPm>(mContext->getVrStrength());
|
||||
break;
|
||||
}
|
||||
case Virtualizer::device: {
|
||||
vrParam.set<Virtualizer::device>(mContext->getForcedDevice());
|
||||
break;
|
||||
}
|
||||
case Virtualizer::speakerAngles:
|
||||
FALLTHROUGH_INTENDED;
|
||||
case Virtualizer::vendor: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"VirtualizerTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::virtualizer>(vrParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VirtualizerSw::getSpeakerAngles(const Virtualizer::SpeakerAnglesPayload payload,
|
||||
Parameter::Specific* specific) {
|
||||
std::vector<Virtualizer::ChannelAngle> angles;
|
||||
const auto chNum = ::aidl::android::hardware::audio::common::getChannelCount(payload.layout);
|
||||
if (chNum == 1) {
|
||||
angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
|
||||
.azimuthDegree = 0,
|
||||
.elevationDegree = 0}};
|
||||
} else if (chNum == 2) {
|
||||
angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
|
||||
.azimuthDegree = -90,
|
||||
.elevationDegree = 0},
|
||||
{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_RIGHT,
|
||||
.azimuthDegree = 90,
|
||||
.elevationDegree = 0}};
|
||||
} else {
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"supportUpTo2Ch");
|
||||
}
|
||||
|
||||
Virtualizer param = Virtualizer::make<Virtualizer::speakerAngles>(angles);
|
||||
specific->set<Parameter::Specific::virtualizer>(param);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> VirtualizerSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<VirtualizerSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode VirtualizerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status VirtualizerSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode VirtualizerSwContext::setVrStrength(int strength) {
|
||||
mStrength = strength;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class VirtualizerSwContext final : public EffectContext {
|
||||
public:
|
||||
VirtualizerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
RetCode setVrStrength(int strength);
|
||||
int getVrStrength() const { return mStrength; }
|
||||
RetCode setForcedDevice(
|
||||
const ::aidl::android::media::audio::common::AudioDeviceDescription& device) {
|
||||
mForceDevice = device;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
aidl::android::media::audio::common::AudioDeviceDescription getForcedDevice() const {
|
||||
return mForceDevice;
|
||||
}
|
||||
|
||||
private:
|
||||
int mStrength = 0;
|
||||
::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice;
|
||||
};
|
||||
|
||||
class VirtualizerSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
VirtualizerSw() { LOG(DEBUG) << __func__; }
|
||||
~VirtualizerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
|
||||
std::string getEffectName() override { return kEffectName; }
|
||||
|
||||
private:
|
||||
static const std::vector<Range::VirtualizerRange> kRanges;
|
||||
std::shared_ptr<VirtualizerSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
|
||||
ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Tag& tag,
|
||||
Parameter::Specific* specific) REQUIRES(mImplMutex);
|
||||
ndk::ScopedAStatus getSpeakerAngles(const Virtualizer::SpeakerAnglesPayload payload,
|
||||
Parameter::Specific* specific) REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libvisualizersw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"VisualizerSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AHAL_VisualizerSw"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "VisualizerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidVisualizerSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::hardware::audio::effect::VisualizerSw;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVisualizerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<VisualizerSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVisualizerSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = VisualizerSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string VisualizerSw::kEffectName = "VisualizerSw";
|
||||
|
||||
/* capabilities */
|
||||
const std::vector<Range::VisualizerRange> VisualizerSw::kRanges = {
|
||||
MAKE_RANGE(Visualizer, latencyMs, 0, VisualizerSwContext::kMaxLatencyMs),
|
||||
MAKE_RANGE(Visualizer, captureSamples, VisualizerSwContext::kMinCaptureSize,
|
||||
VisualizerSwContext::kMaxCaptureSize)};
|
||||
|
||||
const Capability VisualizerSw::kCapability = {
|
||||
.range = Range::make<Range::visualizer>(VisualizerSw::kRanges)};
|
||||
|
||||
const Descriptor VisualizerSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidVisualizer(),
|
||||
.uuid = getEffectImplUuidVisualizerSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::NONE},
|
||||
.name = VisualizerSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = VisualizerSw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus VisualizerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VisualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
|
||||
auto& vsParam = specific.get<Parameter::Specific::visualizer>();
|
||||
RETURN_IF(!inRange(vsParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
auto tag = vsParam.getTag();
|
||||
|
||||
switch (tag) {
|
||||
case Visualizer::captureSamples: {
|
||||
RETURN_IF(mContext->setVsCaptureSize(vsParam.get<Visualizer::captureSamples>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setCaptureSizeFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Visualizer::scalingMode: {
|
||||
RETURN_IF(mContext->setVsScalingMode(vsParam.get<Visualizer::scalingMode>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setScalingModeFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Visualizer::measurementMode: {
|
||||
RETURN_IF(mContext->setVsMeasurementMode(vsParam.get<Visualizer::measurementMode>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Visualizer::latencyMs: {
|
||||
RETURN_IF(mContext->setVsLatency(vsParam.get<Visualizer::latencyMs>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"VisualizerTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VisualizerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto vsId = id.get<Parameter::Id::visualizerTag>();
|
||||
auto vsIdTag = vsId.getTag();
|
||||
switch (vsIdTag) {
|
||||
case Visualizer::Id::commonTag:
|
||||
return getParameterVisualizer(vsId.get<Visualizer::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"VisualizerTagNotSupported");
|
||||
}
|
||||
}
|
||||
ndk::ScopedAStatus VisualizerSw::getParameterVisualizer(const Visualizer::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
Visualizer vsParam;
|
||||
switch (tag) {
|
||||
case Visualizer::captureSamples: {
|
||||
vsParam.set<Visualizer::captureSamples>(mContext->getVsCaptureSize());
|
||||
break;
|
||||
}
|
||||
case Visualizer::scalingMode: {
|
||||
vsParam.set<Visualizer::scalingMode>(mContext->getVsScalingMode());
|
||||
break;
|
||||
}
|
||||
case Visualizer::measurementMode: {
|
||||
vsParam.set<Visualizer::measurementMode>(mContext->getVsMeasurementMode());
|
||||
break;
|
||||
}
|
||||
case Visualizer::measurement: {
|
||||
vsParam.set<Visualizer::measurement>(mContext->getVsMeasurement());
|
||||
break;
|
||||
}
|
||||
case Visualizer::captureSampleBuffer: {
|
||||
vsParam.set<Visualizer::captureSampleBuffer>(mContext->getVsCaptureSampleBuffer());
|
||||
break;
|
||||
}
|
||||
case Visualizer::latencyMs: {
|
||||
vsParam.set<Visualizer::latencyMs>(mContext->getVsLatency());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"VisualizerTagNotSupported");
|
||||
}
|
||||
}
|
||||
specific->set<Parameter::Specific::visualizer>(vsParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> VisualizerSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<VisualizerSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode VisualizerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status VisualizerSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode VisualizerSwContext::setVsCaptureSize(int captureSize) {
|
||||
mCaptureSize = captureSize;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode VisualizerSwContext::setVsScalingMode(Visualizer::ScalingMode scalingMode) {
|
||||
mScalingMode = scalingMode;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode VisualizerSwContext::setVsMeasurementMode(Visualizer::MeasurementMode measurementMode) {
|
||||
mMeasurementMode = measurementMode;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode VisualizerSwContext::setVsLatency(int latency) {
|
||||
mLatency = latency;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <system/audio_effects/effect_visualizer.h>
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class VisualizerSwContext final : public EffectContext {
|
||||
public:
|
||||
// need align the min/max capture size to VISUALIZER_CAPTURE_SIZE_MIN and
|
||||
// VISUALIZER_CAPTURE_SIZE_MAX because of limitation in audio_utils fixedfft.
|
||||
static constexpr int32_t kMinCaptureSize = VISUALIZER_CAPTURE_SIZE_MIN;
|
||||
static constexpr int32_t kMaxCaptureSize = VISUALIZER_CAPTURE_SIZE_MAX;
|
||||
static constexpr int32_t kMaxLatencyMs = 3000;
|
||||
VisualizerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
mCaptureSampleBuffer.resize(kMaxCaptureSize);
|
||||
fill(mCaptureSampleBuffer.begin(), mCaptureSampleBuffer.end(), 0x80);
|
||||
}
|
||||
|
||||
RetCode setVsCaptureSize(int captureSize);
|
||||
int getVsCaptureSize() const { return mCaptureSize; }
|
||||
|
||||
RetCode setVsScalingMode(Visualizer::ScalingMode scalingMode);
|
||||
Visualizer::ScalingMode getVsScalingMode() const { return mScalingMode; }
|
||||
|
||||
RetCode setVsMeasurementMode(Visualizer::MeasurementMode measurementMode);
|
||||
Visualizer::MeasurementMode getVsMeasurementMode() const { return mMeasurementMode; }
|
||||
|
||||
RetCode setVsLatency(int latency);
|
||||
int getVsLatency() const { return mLatency; }
|
||||
|
||||
Visualizer::Measurement getVsMeasurement() const { return mMeasurement; }
|
||||
std::vector<uint8_t> getVsCaptureSampleBuffer() const { return mCaptureSampleBuffer; }
|
||||
|
||||
private:
|
||||
int mCaptureSize = kMaxCaptureSize;
|
||||
Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
|
||||
Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
|
||||
int mLatency = 0;
|
||||
const Visualizer::Measurement mMeasurement = {0, 0};
|
||||
std::vector<uint8_t> mCaptureSampleBuffer;
|
||||
};
|
||||
|
||||
class VisualizerSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
VisualizerSw() { LOG(DEBUG) << __func__; }
|
||||
~VisualizerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
std::string getEffectName() override { return kEffectName; }
|
||||
|
||||
private:
|
||||
static const std::vector<Range::VisualizerRange> kRanges;
|
||||
std::shared_ptr<VisualizerSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
|
||||
Parameter::Specific* specific) REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
default_team: "trendy_team_android_media_audio_framework",
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libvolumesw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"VolumeSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
relative_install_path: "soundfx",
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default:__subpackages__",
|
||||
],
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
#define LOG_TAG "AHAL_VolumeSw"
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <system/audio_effects/effect_uuid.h>
|
||||
|
||||
#include "VolumeSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::getEffectImplUuidVolumeSw;
|
||||
using aidl::android::hardware::audio::effect::getEffectTypeUuidVolume;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::hardware::audio::effect::VolumeSw;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVolumeSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<VolumeSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVolumeSw()) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
*_aidl_return = VolumeSw::kDescriptor;
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
const std::string VolumeSw::kEffectName = "VolumeSw";
|
||||
|
||||
const std::vector<Range::VolumeRange> VolumeSw::kRanges = {MAKE_RANGE(Volume, levelDb, -9600, 0)};
|
||||
|
||||
const Capability VolumeSw::kCapability = {.range = Range::make<Range::volume>(VolumeSw::kRanges)};
|
||||
|
||||
const Descriptor VolumeSw::kDescriptor = {
|
||||
.common = {.id = {.type = getEffectTypeUuidVolume(),
|
||||
.uuid = getEffectImplUuidVolumeSw(),
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = VolumeSw::kEffectName,
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = VolumeSw::kCapability};
|
||||
|
||||
ndk::ScopedAStatus VolumeSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VolumeSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::volume != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
|
||||
auto& volParam = specific.get<Parameter::Specific::volume>();
|
||||
RETURN_IF(!inRange(volParam, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
|
||||
auto tag = volParam.getTag();
|
||||
|
||||
switch (tag) {
|
||||
case Volume::levelDb: {
|
||||
RETURN_IF(mContext->setVolLevel(volParam.get<Volume::levelDb>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "LevelNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Volume::mute: {
|
||||
RETURN_IF(mContext->setVolMute(volParam.get<Volume::mute>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "MuteNotSupported");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"VolumeTagNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VolumeSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::volumeTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto volId = id.get<Parameter::Id::volumeTag>();
|
||||
auto volIdTag = volId.getTag();
|
||||
switch (volIdTag) {
|
||||
case Volume::Id::commonTag:
|
||||
return getParameterVolume(volId.get<Volume::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"VolumeTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VolumeSw::getParameterVolume(const Volume::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
Volume volParam;
|
||||
switch (tag) {
|
||||
case Volume::levelDb: {
|
||||
volParam.set<Volume::levelDb>(mContext->getVolLevel());
|
||||
break;
|
||||
}
|
||||
case Volume::mute: {
|
||||
volParam.set<Volume::mute>(mContext->getVolMute());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"VolumeTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
specific->set<Parameter::Specific::volume>(volParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> VolumeSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
} else {
|
||||
mContext = std::make_shared<VolumeSwContext>(1 /* statusFmqDepth */, common);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode VolumeSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status VolumeSw::effectProcessImpl(float* in, float* out, int samples) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
|
||||
for (int i = 0; i < samples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, samples, samples};
|
||||
}
|
||||
|
||||
RetCode VolumeSwContext::setVolLevel(int level) {
|
||||
mLevel = level;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
RetCode VolumeSwContext::setVolMute(bool mute) {
|
||||
// TODO : Add implementation to modify mute
|
||||
mMute = mute;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class VolumeSwContext final : public EffectContext {
|
||||
public:
|
||||
VolumeSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setVolLevel(int level);
|
||||
|
||||
int getVolLevel() const { return mLevel; }
|
||||
|
||||
RetCode setVolMute(bool mute);
|
||||
|
||||
bool getVolMute() const { return mMute; }
|
||||
|
||||
private:
|
||||
int mLevel = 0;
|
||||
bool mMute = false;
|
||||
};
|
||||
|
||||
class VolumeSw final : public EffectImpl {
|
||||
public:
|
||||
static const std::string kEffectName;
|
||||
static const Capability kCapability;
|
||||
static const Descriptor kDescriptor;
|
||||
VolumeSw() { LOG(DEBUG) << __func__; }
|
||||
~VolumeSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex) override;
|
||||
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
|
||||
REQUIRES(mImplMutex) override;
|
||||
RetCode releaseContext() REQUIRES(mImplMutex) override;
|
||||
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
|
||||
REQUIRES(mImplMutex) override;
|
||||
std::string getEffectName() override { return kEffectName; }
|
||||
|
||||
private:
|
||||
static const std::vector<Range::VolumeRange> kRanges;
|
||||
std::shared_ptr<VolumeSwContext> mContext GUARDED_BY(mImplMutex);
|
||||
|
||||
ndk::ScopedAStatus getParameterVolume(const Volume::Tag& tag, Parameter::Specific* specific)
|
||||
REQUIRES(mImplMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
Reference in New Issue
Block a user