AIDL effect: Add all aosp effects default implementation
Bug: 238913361
Test: atest VtsHalAudioEffectTargetTest
atest VtsHalAudioEffectFactoryTargetTest
atest VtsHalEqualizerTargetTest
Change-Id: I6825ba77ae0707f97e852f0faa52ce3486ba2af5
diff --git a/audio/aidl/default/include/effect-impl/EffectContext.h b/audio/aidl/default/include/effect-impl/EffectContext.h
index 36492ec..f608e12 100644
--- a/audio/aidl/default/include/effect-impl/EffectContext.h
+++ b/audio/aidl/default/include/effect-impl/EffectContext.h
@@ -15,6 +15,10 @@
*/
#pragma once
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <utils/Log.h>
+#include <cstddef>
#include <cstdint>
#include <memory>
#include <utility>
@@ -22,6 +26,7 @@
#include <aidl/android/hardware/audio/effect/BnEffect.h>
#include <fmq/AidlMessageQueue.h>
+#include "EffectTypes.h"
namespace aidl::android::hardware::audio::effect {
@@ -31,35 +36,122 @@
IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
StatusMQ;
typedef ::android::AidlMessageQueue<
- int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
DataMQ;
- EffectContext(size_t statusDepth, size_t inBufferSize, size_t outBufferSize) {
+ EffectContext(size_t statusDepth, const Parameter::Common& common) {
+ mSessionId = common.session;
+ auto& input = common.input;
+ auto& output = common.output;
+
+ LOG_ALWAYS_FATAL_IF(
+ input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT,
+ "inputFormatNotFloat");
+ LOG_ALWAYS_FATAL_IF(output.base.format.pcm !=
+ aidl::android::media::audio::common::PcmType::FLOAT_32_BIT,
+ "outputFormatNotFloat");
+ mInputFrameSize = ::android::hardware::audio::common::getFrameSizeInBytes(
+ input.base.format, input.base.channelMask);
+ mOutputFrameSize = ::android::hardware::audio::common::getFrameSizeInBytes(
+ output.base.format, output.base.channelMask);
+ // in/outBuffer size in float (FMQ data format defined for DataMQ)
+ size_t inBufferSizeInFloat = input.frameCount * mInputFrameSize / sizeof(float);
+ size_t outBufferSizeInFloat = output.frameCount * mOutputFrameSize / sizeof(float);
+
mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
- mInputMQ = std::make_shared<DataMQ>(inBufferSize);
- mOutputMQ = std::make_shared<DataMQ>(outBufferSize);
+ mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat);
+ mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat);
if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
LOG(ERROR) << __func__ << " created invalid FMQ";
}
- mWorkBuffer.reserve(std::max(inBufferSize, outBufferSize));
- };
+ mWorkBuffer.reserve(std::max(inBufferSizeInFloat, outBufferSizeInFloat));
+ }
+ virtual ~EffectContext() {}
- std::shared_ptr<StatusMQ> getStatusFmq() { return mStatusMQ; };
- std::shared_ptr<DataMQ> getInputDataFmq() { return mInputMQ; };
- std::shared_ptr<DataMQ> getOutputDataFmq() { return mOutputMQ; };
+ std::shared_ptr<StatusMQ> getStatusFmq() { return mStatusMQ; }
+ std::shared_ptr<DataMQ> getInputDataFmq() { return mInputMQ; }
+ std::shared_ptr<DataMQ> getOutputDataFmq() { return mOutputMQ; }
- int8_t* getWorkBuffer() { return static_cast<int8_t*>(mWorkBuffer.data()); };
+ float* getWorkBuffer() { return static_cast<float*>(mWorkBuffer.data()); }
// TODO: update with actual available size
- size_t availableToRead() { return mWorkBuffer.capacity(); };
- size_t availableToWrite() { return mWorkBuffer.capacity(); };
+ size_t availableToRead() { return mWorkBuffer.capacity(); }
+ size_t availableToWrite() { return mWorkBuffer.capacity(); }
+
+ // reset buffer status by abandon all data and status in FMQ
+ void resetBuffer() {
+ auto buffer = getWorkBuffer();
+ std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
+ mInputMQ->read(buffer, mInputMQ->availableToRead());
+ mOutputMQ->read(buffer, mOutputMQ->availableToRead());
+ mStatusMQ->read(status.data(), mStatusMQ->availableToRead());
+ }
+
+ void dupeFmq(IEffect::OpenEffectReturn* effectRet) {
+ if (effectRet) {
+ effectRet->statusMQ = getStatusFmq()->dupeDesc();
+ effectRet->inputDataMQ = getInputDataFmq()->dupeDesc();
+ effectRet->outputDataMQ = getOutputDataFmq()->dupeDesc();
+ }
+ }
+ size_t getInputFrameSize() { return mInputFrameSize; }
+ size_t getOutputFrameSize() { return mOutputFrameSize; }
+ int getSessionId() { return mSessionId; }
+
+ virtual RetCode setOutputDevice(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device) {
+ mOutputDevice = device;
+ return RetCode::SUCCESS;
+ }
+ virtual aidl::android::media::audio::common::AudioDeviceDescription getOutputDevice() {
+ return mOutputDevice;
+ }
+
+ virtual RetCode setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) {
+ mMode = mode;
+ return RetCode::SUCCESS;
+ }
+ virtual aidl::android::media::audio::common::AudioMode getAudioMode() { return mMode; }
+
+ virtual RetCode setAudioSource(const aidl::android::media::audio::common::AudioSource& source) {
+ mSource = source;
+ return RetCode::SUCCESS;
+ }
+ virtual aidl::android::media::audio::common::AudioSource getAudioSource() { return mSource; }
+
+ virtual RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
+ mVolumeStereo = volumeStereo;
+ return RetCode::SUCCESS;
+ }
+ virtual Parameter::VolumeStereo getVolumeStereo() { return mVolumeStereo; }
+
+ virtual RetCode setCommon(const Parameter::Common& common) {
+ mCommon = common;
+ LOG(ERROR) << __func__ << mCommon.toString();
+ return RetCode::SUCCESS;
+ }
+ virtual Parameter::Common getCommon() {
+ LOG(ERROR) << __func__ << mCommon.toString();
+ return mCommon;
+ }
+
+ protected:
+ // common parameters
+ int mSessionId = INVALID_AUDIO_SESSION_ID;
+ size_t mInputFrameSize, mOutputFrameSize;
+ Parameter::Common mCommon;
+ aidl::android::media::audio::common::AudioDeviceDescription mOutputDevice;
+ aidl::android::media::audio::common::AudioMode mMode;
+ aidl::android::media::audio::common::AudioSource mSource;
+ Parameter::VolumeStereo mVolumeStereo;
private:
+ // fmq and buffers
std::shared_ptr<StatusMQ> mStatusMQ;
std::shared_ptr<DataMQ> mInputMQ;
std::shared_ptr<DataMQ> mOutputMQ;
// TODO handle effect process input and output
// work buffer set by effect instances, the access and update are in same thread
- std::vector<int8_t> mWorkBuffer;
+ std::vector<float> mWorkBuffer;
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectImpl.h b/audio/aidl/default/include/effect-impl/EffectImpl.h
new file mode 100644
index 0000000..cb395b7
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectImpl.h
@@ -0,0 +1,86 @@
+/*
+ * 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 <mutex>
+
+#include "EffectTypes.h"
+#include "effect-impl/EffectContext.h"
+#include "effect-impl/EffectTypes.h"
+#include "effect-impl/EffectWorker.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectImpl : public BnEffect, public EffectWorker {
+ public:
+ EffectImpl() { LOG(DEBUG) << __func__; }
+ ~EffectImpl() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ /**
+ * Each effect implementation CAN override these methods if necessary
+ * If you would like implement IEffect::open completely, override EffectImpl::open(), if you
+ * want to keep most of EffectImpl logic but have a little customize, try override openImpl().
+ * openImpl() will be called at the beginning of EffectImpl::open() without lock protection.
+ *
+ * Same for closeImpl().
+ */
+ virtual ndk::ScopedAStatus open(const Parameter::Common& common,
+ const std::optional<Parameter::Specific>& specific,
+ OpenEffectReturn* ret) override;
+ virtual ndk::ScopedAStatus close() override;
+ virtual ndk::ScopedAStatus command(CommandId id) override;
+ virtual ndk::ScopedAStatus commandStart() { return ndk::ScopedAStatus::ok(); }
+ virtual ndk::ScopedAStatus commandStop() { return ndk::ScopedAStatus::ok(); }
+ virtual ndk::ScopedAStatus commandReset() { return ndk::ScopedAStatus::ok(); }
+
+ virtual ndk::ScopedAStatus getState(State* state) override;
+ virtual ndk::ScopedAStatus setParameter(const Parameter& param) override;
+ virtual ndk::ScopedAStatus getParameter(const Parameter::Id& id, Parameter* param) override;
+ virtual IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
+ virtual ndk::ScopedAStatus setParameterCommon(const Parameter& param);
+ virtual ndk::ScopedAStatus getParameterCommon(const Parameter::Tag& tag, Parameter* param);
+
+ /* Methods MUST be implemented by each effect instances */
+ virtual ndk::ScopedAStatus getDescriptor(Descriptor* desc) = 0;
+ virtual ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) = 0;
+ virtual ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) = 0;
+ virtual std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) = 0;
+ virtual RetCode releaseContext() = 0;
+
+ protected:
+ /*
+ * Lock is required if effectProcessImpl (which is running in an independent thread) needs to
+ * access state and parameters.
+ */
+ std::mutex mMutex;
+ State mState GUARDED_BY(mMutex) = State::INIT;
+
+ IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
+
+ private:
+ void cleanUp();
+ std::shared_ptr<EffectContext> mContext GUARDED_BY(mMutex);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectTypes.h b/audio/aidl/default/include/effect-impl/EffectTypes.h
index 46cfc0c..edce26b 100644
--- a/audio/aidl/default/include/effect-impl/EffectTypes.h
+++ b/audio/aidl/default/include/effect-impl/EffectTypes.h
@@ -18,6 +18,19 @@
#include <ostream>
#include <string>
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+typedef binder_exception_t (*EffectCreateFunctor)(
+ const ::aidl::android::media::audio::common::AudioUuid*,
+ std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>*);
+typedef binder_exception_t (*EffectDestroyFunctor)(
+ const std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>&);
+
+struct effect_dl_interface_s {
+ EffectCreateFunctor createEffectFunc;
+ EffectDestroyFunctor destroyEffectFunc;
+};
+
namespace aidl::android::hardware::audio::effect {
enum class RetCode {
@@ -26,9 +39,12 @@
ERROR_THREAD, /* Effect thread error */
ERROR_NULL_POINTER, /* NULL pointer */
ERROR_ALIGNMENT_ERROR, /* Memory alignment error */
- ERROR_BLOCK_SIZE_EXCEED /* Maximum block size exceeded */
+ ERROR_BLOCK_SIZE_EXCEED, /* Maximum block size exceeded */
+ ERROR_EFFECT_LIB_ERROR
};
+static const int INVALID_AUDIO_SESSION_ID = -1;
+
inline std::ostream& operator<<(std::ostream& out, const RetCode& code) {
switch (code) {
case RetCode::SUCCESS:
@@ -43,9 +59,46 @@
return out << "ERROR_ALIGNMENT_ERROR";
case RetCode::ERROR_BLOCK_SIZE_EXCEED:
return out << "ERROR_BLOCK_SIZE_EXCEED";
+ case RetCode::ERROR_EFFECT_LIB_ERROR:
+ return out << "ERROR_EFFECT_LIB_ERROR";
}
return out << "EnumError: " << code;
}
+#define RETURN_IF_ASTATUS_NOT_OK(status, message) \
+ do { \
+ const ::ndk::ScopedAStatus curr_status = (status); \
+ if (!curr_status.isOk()) { \
+ LOG(ERROR) << __func__ << ":" << __LINE__ \
+ << "return with status: " << curr_status.getDescription() << (message); \
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage( \
+ curr_status.getExceptionCode(), (message)); \
+ } \
+ } while (0)
+
+#define RETURN_IF(expr, exception, message) \
+ do { \
+ if (expr) { \
+ LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr " << #expr; \
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage((exception), (message)); \
+ } \
+ } while (0)
+
+#define RETURN_OK_IF(expr) \
+ do { \
+ if (expr) { \
+ LOG(INFO) << __func__ << ":" << __LINE__ << " return with expr " << #expr; \
+ return ndk::ScopedAStatus::ok(); \
+ } \
+ } while (0)
+
+#define RETURN_VALUE_IF(expr, ret, log) \
+ do { \
+ if (expr) { \
+ LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr " << #expr << (log); \
+ return ret; \
+ } \
+ } while (0)
+
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
index 48b7137..767cf6c 100644
--- a/audio/aidl/default/include/effect-impl/EffectUUID.h
+++ b/audio/aidl/default/include/effect-impl/EffectUUID.h
@@ -46,11 +46,124 @@
0xbb17,
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-// Visualizer type UUID.
-static const AudioUuid VisualizerTypeUUID = {static_cast<int32_t>(0x1d4033c0),
- 0x8557,
- 0x11df,
- 0x9f2d,
- {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// Equalizer bundle implementation UUID.
+static const AudioUuid EqualizerBundleImplUUID = {static_cast<int32_t>(0xce772f20),
+ 0x847d,
+ 0x11df,
+ 0xbb17,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
+// fa8184a4-588b-11ed-9b6a-0242ac120002
+static const AudioUuid BassBoostTypeUUID = {static_cast<int32_t>(0xfa8184a4),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa8181f2-588b-11ed-9b6a-0242ac120002
+static const AudioUuid BassBoostSwImplUUID = {static_cast<int32_t>(0xfa8181f2),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa81862a-588b-11ed-9b6a-0242ac120002
+static const AudioUuid DownmixTypeUUID = {static_cast<int32_t>(0xfa81862a),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa8187ba-588b-11ed-9b6a-0242ac120002
+static const AudioUuid DownmixSwImplUUID = {static_cast<int32_t>(0xfa8187ba),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa818954-588b-11ed-9b6a-0242ac120002
+static const AudioUuid DynamicsProcessingTypeUUID = {static_cast<int32_t>(0xfa818954),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa818d78-588b-11ed-9b6a-0242ac120002
+static const AudioUuid DynamicsProcessingSwImplUUID = {static_cast<int32_t>(0xfa818d78),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa818f62-588b-11ed-9b6a-0242ac120002
+static const AudioUuid HapticGeneratorTypeUUID = {static_cast<int32_t>(0xfa818f62),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa819110-588b-11ed-9b6a-0242ac120002
+static const AudioUuid HapticGeneratorSwImplUUID = {static_cast<int32_t>(0xfa819110),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+
+// fa8194a8-588b-11ed-9b6a-0242ac120002
+static const AudioUuid LoudnessEnhancerTypeUUID = {static_cast<int32_t>(0xfa8194a8),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa819610-588b-11ed-9b6a-0242ac120002
+static const AudioUuid LoudnessEnhancerSwImplUUID = {static_cast<int32_t>(0xfa819610),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa819886-588b-11ed-9b6a-0242ac120002
+static const AudioUuid ReverbTypeUUID = {static_cast<int32_t>(0xfa819886),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa8199c6-588b-11ed-9b6a-0242ac120002
+static const AudioUuid ReverbSwImplUUID = {static_cast<int32_t>(0xfa8199c6),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+
+// fa819af2-588b-11ed-9b6a-0242ac120002
+static const AudioUuid VirtualizerTypeUUID = {static_cast<int32_t>(0xfa819af2),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa819d86-588b-11ed-9b6a-0242ac120002
+static const AudioUuid VirtualizerSwImplUUID = {static_cast<int32_t>(0xfa819d86),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+
+// fa819f3e-588b-11ed-9b6a-0242ac120002
+static const AudioUuid VisualizerTypeUUID = {static_cast<int32_t>(0xfa819f3e),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa81a0f6-588b-11ed-9b6a-0242ac120002
+static const AudioUuid VisualizerSwImplUUID = {static_cast<int32_t>(0xfa81a0f6),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+
+// fa81a2b8-588b-11ed-9b6a-0242ac120002
+static const AudioUuid VolumeTypeUUID = {static_cast<int32_t>(0xfa81a2b8),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa81a718-588b-11ed-9b6a-0242ac120002
+static const AudioUuid VolumeSwImplUUID = {static_cast<int32_t>(0xfa81a718),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectWorker.h b/audio/aidl/default/include/effect-impl/EffectWorker.h
index 0fe69ff..a297937 100644
--- a/audio/aidl/default/include/effect-impl/EffectWorker.h
+++ b/audio/aidl/default/include/effect-impl/EffectWorker.h
@@ -36,34 +36,33 @@
// handle FMQ and call effect implemented virtual function
void process() override {
- if (!mContext) {
- LOG(ERROR) << __func__ << " invalid context!";
- return;
- }
+ RETURN_VALUE_IF(!mContext, void(), "nullContext");
std::shared_ptr<EffectContext::StatusMQ> statusMQ = mContext->getStatusFmq();
std::shared_ptr<EffectContext::DataMQ> inputMQ = mContext->getInputDataFmq();
std::shared_ptr<EffectContext::DataMQ> outputMQ = mContext->getOutputDataFmq();
// Only this worker will read from input data MQ and write to output data MQ.
- auto readSize = inputMQ->availableToRead(), writeSize = outputMQ->availableToWrite();
- if (readSize && writeSize) {
- LOG(DEBUG) << __func__ << " available to read " << readSize << " available to write "
- << writeSize;
+ auto readSamples = inputMQ->availableToRead(), writeSamples = outputMQ->availableToWrite();
+ if (readSamples && writeSamples) {
+ auto processSamples = std::min(readSamples, writeSamples);
+ LOG(DEBUG) << __func__ << " available to read " << readSamples << " available to write "
+ << writeSamples << " process " << processSamples;
+
auto buffer = mContext->getWorkBuffer();
- inputMQ->read(buffer, readSize);
- IEffect::Status status = effectProcessImpl();
- writeSize = std::min((int32_t)writeSize, status.fmqByteProduced);
- outputMQ->write(buffer, writeSize);
+ inputMQ->read(buffer, processSamples);
+
+ IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
+ outputMQ->write(buffer, status.fmqProduced);
statusMQ->writeBlocking(&status, 1);
- LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqByteConsumed
- << " produced " << status.fmqByteProduced;
+ LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqConsumed
+ << " produced " << status.fmqProduced;
} else {
// TODO: maybe add some sleep here to avoid busy waiting
}
}
// must implement by each effect implementation
- virtual IEffect::Status effectProcessImpl() = 0;
+ virtual IEffect::Status effectProcessImpl(float* in, float* out, int processSamples) = 0;
private:
// make sure the context only set once.
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
index 6195d8a..d50bd63 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -34,12 +34,14 @@
*
* @param in_type Type UUID.
* @param in_instance Instance UUID.
+ * @param in_proxy Proxy UUID.
* @param out_descriptor List of identities .
* @return ndk::ScopedAStatus
*/
ndk::ScopedAStatus queryEffects(
const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_type,
const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_instance,
+ const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_proxy,
std::vector<Descriptor::Identity>* out_descriptor) override;
/**
@@ -79,16 +81,9 @@
// List of effect descriptors supported by the devices.
std::vector<Descriptor::Identity> mIdentityList;
- typedef binder_exception_t (*EffectCreateFunctor)(std::shared_ptr<IEffect>*);
- typedef binder_exception_t (*EffectDestroyFunctor)(const std::shared_ptr<IEffect>&);
- struct effect_interface_s {
- EffectCreateFunctor createEffectFunc;
- EffectDestroyFunctor destroyEffectFunc;
- };
-
std::map<aidl::android::media::audio::common::AudioUuid /* implementationUUID */,
std::pair<std::unique_ptr<void, std::function<void(void*)>> /* dlHandle */,
- std::unique_ptr<struct effect_interface_s>>>
+ std::unique_ptr<struct effect_dl_interface_s>>>
mEffectLibMap;
std::map<std::weak_ptr<IEffect>, aidl::android::media::audio::common::AudioUuid,
std::owner_less<>>
@@ -96,5 +91,10 @@
ndk::ScopedAStatus destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle);
void cleanupEffectMap();
+ void openEffectLibrary(
+ const ::aidl::android::media::audio::common::AudioUuid& type,
+ const ::aidl::android::media::audio::common::AudioUuid& impl,
+ const std::optional<::aidl::android::media::audio::common::AudioUuid>& proxy,
+ const std::string& libName);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/equalizer-impl/EqualizerSw.h b/audio/aidl/default/include/equalizer-impl/EqualizerSw.h
index aa3a727..dad03e1 100644
--- a/audio/aidl/default/include/equalizer-impl/EqualizerSw.h
+++ b/audio/aidl/default/include/equalizer-impl/EqualizerSw.h
@@ -21,85 +21,104 @@
#include <cstdlib>
#include <memory>
-#include "effect-impl/EffectContext.h"
-#include "effect-impl/EffectTypes.h"
+#include "effect-impl/EffectImpl.h"
#include "effect-impl/EffectUUID.h"
-#include "effect-impl/EffectWorker.h"
namespace aidl::android::hardware::audio::effect {
class EqualizerSwContext : public EffectContext {
public:
- EqualizerSwContext(int statusDepth, int inBufferSize, int outBufferSize)
- : EffectContext(statusDepth, inBufferSize, outBufferSize) {
+ EqualizerSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
LOG(DEBUG) << __func__;
}
+ RetCode setEqPreset(const int& presetIdx) {
+ if (presetIdx < 0 || presetIdx >= NUM_OF_PRESETS) {
+ 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() > NUM_OF_BANDS) {
+ LOG(ERROR) << __func__ << " return because size exceed " << NUM_OF_BANDS;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ RetCode ret = RetCode::SUCCESS;
+ for (auto& it : bandLevels) {
+ if (it.index >= NUM_OF_BANDS || it.index < 0) {
+ LOG(ERROR) << __func__ << " index illegal, skip: " << it.index << " - "
+ << it.levelMb;
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ mBandLevels[it.index] = it.levelMb;
+ }
+ return ret;
+ }
+
+ std::vector<Equalizer::BandLevel> getEqBandLevels() {
+ std::vector<Equalizer::BandLevel> bandLevels;
+ for (int i = 0; i < NUM_OF_BANDS; i++) {
+ bandLevels.push_back({i, mBandLevels[i]});
+ }
+ return bandLevels;
+ }
+
private:
+ static const int NUM_OF_BANDS = 5;
+ static const int NUM_OF_PRESETS = 10;
+ static const int PRESET_CUSTOM = -1;
+ // preset band level
+ int mPreset = PRESET_CUSTOM;
+ int32_t mBandLevels[NUM_OF_BANDS] = {3, 0, 0, 0, 3};
+
// Add equalizer specific context for processing here
};
-class EqualizerSw : public BnEffect, EffectWorker {
+class EqualizerSw : public EffectImpl {
public:
- EqualizerSw() {
- Equalizer::Capability eqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets};
- mDesc.capability.set<Capability::equalizer>(eqCap);
- LOG(DEBUG) << __func__;
- };
+ EqualizerSw() { LOG(DEBUG) << __func__; }
~EqualizerSw() {
- cleanUp();
LOG(DEBUG) << __func__;
- };
- ndk::ScopedAStatus open(const Parameter::Common& common, const Parameter::Specific& specific,
- OpenEffectReturn* _aidl_return) override;
- ndk::ScopedAStatus close() override;
+ releaseContext();
+ }
+
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
-
- ndk::ScopedAStatus getState(State* _aidl_return) override;
- ndk::ScopedAStatus command(CommandId in_commandId) override;
- ndk::ScopedAStatus setParameter(const Parameter& in_param) override;
- ndk::ScopedAStatus getParameter(const Parameter::Id& in_paramId,
- Parameter* _aidl_return) override;
-
- IEffect::Status effectProcessImpl() override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
private:
- // Effect descriptor.
- Descriptor mDesc = {.common = {.id = {.type = EqualizerTypeUUID, .uuid = EqualizerSwImplUUID}}};
-
- // Parameters.
- Parameter::Common mCommonParam;
- Equalizer mEqualizerParam; // TODO: the equalizer parameter needs to update
-
- // Instance state INIT by default.
- State mState = State::INIT;
-
- int mPreset = PRESET_CUSTOM; // the current preset
+ std::shared_ptr<EqualizerSwContext> mContext;
+ /* capabilities */
const std::vector<Equalizer::BandFrequency> mBandFrequency = {{0, 30000, 120000},
{1, 120001, 460000},
{2, 460001, 1800000},
{3, 1800001, 7000000},
{4, 7000001, 20000000}};
- // preset band level
- std::vector<Equalizer::BandLevel> mBandLevels = {{0, 3}, {1, 0}, {2, 0}, {3, 0}, {4, 3}};
// presets supported by the device
const std::vector<Equalizer::Preset> mPresets = {
{0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
{5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
- static const int NUM_OF_BANDS = 5;
- static const int NUM_OF_PRESETS = 10;
- static const int PRESET_CUSTOM = -1;
- // Equalizer worker context
- std::shared_ptr<EqualizerSwContext> mContext;
+ const Equalizer::Capability kEqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets};
+ // Effect descriptor.
+ const Descriptor kDesc = {.common = {.id = {.type = EqualizerTypeUUID,
+ .uuid = EqualizerSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "EqualizerSw"},
+ .capability = Capability::make<Capability::equalizer>(kEqCap)};
- ndk::ScopedAStatus setCommonParameter(const Parameter::Common& common_param);
- ndk::ScopedAStatus setSpecificParameter(const Parameter::Specific& specific);
- ndk::ScopedAStatus getSpecificParameter(Parameter::Specific::Id id,
- Parameter::Specific* specific);
-
- void cleanUp();
-
- IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
+ ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
+ Parameter::Specific* specific);
};
} // namespace aidl::android::hardware::audio::effect