diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | hal/audio_hw.h | 8 | ||||
-rw-r--r-- | post_proc/Makefile.am | 34 | ||||
-rw-r--r-- | qahw_api/Android.mk | 10 | ||||
-rw-r--r-- | qahw_api/Makefile.am | 12 | ||||
-rw-r--r-- | qahw_api/inc/qahw_effect_api.h | 839 | ||||
-rw-r--r-- | qahw_api/inc/qahw_effect_bassboost.h | 51 | ||||
-rw-r--r-- | qahw_api/inc/qahw_effect_environmentalreverb.h | 81 | ||||
-rw-r--r-- | qahw_api/inc/qahw_effect_equalizer.h | 84 | ||||
-rw-r--r-- | qahw_api/inc/qahw_effect_presetreverb.h | 67 | ||||
-rw-r--r-- | qahw_api/inc/qahw_effect_virtualizer.h | 86 | ||||
-rw-r--r-- | qahw_api/inc/qahw_effect_visualizer.h | 79 | ||||
-rw-r--r-- | qahw_api/src/qahw_effect.c | 321 | ||||
-rw-r--r-- | qahw_api/test/Makefile.am | 3 | ||||
-rw-r--r-- | qahw_api/test/qahw_effect_test.c | 231 | ||||
-rw-r--r-- | qahw_api/test/qahw_effect_test.h | 73 | ||||
-rw-r--r-- | qahw_api/test/qahw_playback_test.c | 81 |
18 files changed, 2052 insertions, 13 deletions
diff --git a/Makefile.am b/Makefile.am index 299385d4..ebde009d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = hal +SUBDIRS = hal post_proc if QAHW_SUPPORT SUBDIRS += qahw_api qahw_api/test diff --git a/configure.ac b/configure.ac index 188bf15c..ed81b41b 100644 --- a/configure.ac +++ b/configure.ac @@ -101,10 +101,13 @@ AM_CONDITIONAL([WMA_SUPPORT], [test x$AUDIO_FEATURE_ENABLED_EXTN_WMA_DECODER = x AM_CONDITIONAL([COMPRESS_INPUT], [test x$AUDIO_FEATURE_ENABLED_COMPRESS_INPUT = xtrue]) AM_CONDITIONAL([AUDIO_HW_EXTN_API], [test x$BOARD_SUPPORTS_QAHW = xtrue]) AM_CONDITIONAL([AFE_PROXY], [test x$AUDIO_FEATURE_ENABLED_PROXY_DEVICE = xtrue]) +AM_CONDITIONAL([HW_ACC_EFFECT], [test x$AUDIO_FEATURE_ENABLED_HW_ACCELERATED_EFFECTS = xtrue]) +AM_CONDITIONAL([AUDIOSPHERE], [test x$AUDIO_FEATURE_ENABLED_AUDIOSPHERE = xtrue]) AC_CONFIG_FILES([ \ Makefile \ hal/Makefile \ + post_proc/Makefile \ qahw_api/Makefile \ qahw_api/test/Makefile ]) diff --git a/hal/audio_hw.h b/hal/audio_hw.h index 38ac5473..3986abf1 100644 --- a/hal/audio_hw.h +++ b/hal/audio_hw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * Not a contribution. * * Copyright (C) 2013 The Android Open Source Project @@ -49,9 +49,15 @@ #include "voice.h" #include "audio_hw_extn_api.h" +#if LINUX_ENABLED +#define VISUALIZER_LIBRARY_PATH "/usr/lib/libqcomvisualizer.so" +#define OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH "/usr/lib/libqcompostprocbundle.so" +#define ADM_LIBRARY_PATH "/usr/lib/libadm.so" +#else #define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so" #define OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH "/system/lib/soundfx/libqcompostprocbundle.so" #define ADM_LIBRARY_PATH "/system/vendor/lib/libadm.so" +#endif /* Flags used to initialize acdb_settings variable that goes to ACDB library */ #define NONE_FLAG 0x00000000 diff --git a/post_proc/Makefile.am b/post_proc/Makefile.am new file mode 100644 index 00000000..e161f8d9 --- /dev/null +++ b/post_proc/Makefile.am @@ -0,0 +1,34 @@ +AM_CFLAGS = -I ${WORKSPACE}/external/tinyalsa/include \ + -I ${WORKSPACE}/system/media/audio_effects/include + +c_sources = bundle.c \ + equalizer.c \ + bass_boost.c \ + virtualizer.c \ + reverb.c \ + effect_api.c \ + effect_util.c + +if AFE_PROXY +AM_CFLAGS += -DAFE_PROXY_ENABLED +endif + +if HW_ACC_EFFECT +AM_CFLAGS += -DHW_ACCELERATED_EFFECTS +c_sources += hw_accelerator.c +endif + +if AUDIOSPHERE +AM_CFLAGS += -DAUDIOSPHERE_ENABLED +c_sources += asphere.c +endif + +library_include_HEADERS = $(h_sources) +library_includedir = $(includedir) + +lib_LTLIBRARIES = libqcompostprocbundle.la +libqcompostprocbundle_la_SOURCES = $(c_sources) +libqcompostprocbundle_la_LIBADD = $(GLIB_LIBS) -llog -lcutils -ltinyalsa -ldl +libqcompostprocbundle_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) +libqcompostprocbundle_la_CFLAGS += -D__unused=__attribute__\(\(__unused__\)\) +libqcompostprocbundle_la_LDFLAGS = -module -shared -avoid-version diff --git a/qahw_api/Android.mk b/qahw_api/Android.mk index 98e1a389..1886262d 100644 --- a/qahw_api/Android.mk +++ b/qahw_api/Android.mk @@ -12,7 +12,8 @@ LOCAL_MODULE_OWNER := qti LOCAL_C_INCLUDES := $(libqahw-inc) LOCAL_SRC_FILES := \ - src/qahw.c + src/qahw.c \ + src/qahw_effect.c LOCAL_SHARED_LIBRARIES := \ liblog \ @@ -23,6 +24,13 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_COPY_HEADERS_TO := mm-audio/qahw_api/inc LOCAL_COPY_HEADERS := inc/qahw_api.h LOCAL_COPY_HEADERS += inc/qahw_defs.h +LOCAL_COPY_HEADERS += inc/qahw_effect_api.h +LOCAL_COPY_HEADERS += inc/qahw_effect_bassboost.h +LOCAL_COPY_HEADERS += inc/qahw_effect_environmentalreverb.h +LOCAL_COPY_HEADERS += inc/qahw_effect_equalizer.h +LOCAL_COPY_HEADERS += inc/qahw_effect_presetreverb.h +LOCAL_COPY_HEADERS += inc/qahw_effect_virtualizer.h +LOCAL_COPY_HEADERS += inc/qahw_effect_visualizer.h LOCAL_PRELINK_MODULE := false diff --git a/qahw_api/Makefile.am b/qahw_api/Makefile.am index 78b34c4e..a2139d98 100644 --- a/qahw_api/Makefile.am +++ b/qahw_api/Makefile.am @@ -1,13 +1,21 @@ AM_CFLAGS = -I $(top_srcdir)/qahw_api/inc h_sources = inc/qahw_api.h \ - inc/qahw_defs.h + inc/qahw_defs.h \ + inc/qahw_effect_api.h \ + inc/qahw_effect_bassboost.h \ + inc/qahw_effect_environmentalreverb.h \ + inc/qahw_effect_equalizer.h \ + inc/qahw_effect_presetreverb.h \ + inc/qahw_effect_virtualizer.h \ + inc/qahw_effect_visualizer.h library_include_HEADERS = $(h_sources) library_includedir = $(includedir)/mm-audio/qahw_api/inc lib_LTLIBRARIES = libqahw.la -libqahw_la_SOURCES = src/qahw.c +libqahw_la_SOURCES = src/qahw.c \ + src/qahw_effect.c libqahw_la_CFLAGS = $(AM_CFLAGS) -include stddef.h libqahw_la_CFLAGS += -D__unused=__attribute__\(\(__unused__\)\) libqahw_la_LIBADD = -llog -lcutils -lhardware diff --git a/qahw_api/inc/qahw_effect_api.h b/qahw_api/inc/qahw_effect_api.h new file mode 100644 index 00000000..a6fbcc2c --- /dev/null +++ b/qahw_api/inc/qahw_effect_api.h @@ -0,0 +1,839 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2011 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. + */ + + +#ifndef ANDROID_AUDIO_QAHW_EFFECT_H +#define ANDROID_AUDIO_QAHW_EFFECT_H + +#include <errno.h> +#include <stdint.h> +#include <strings.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <cutils/bitops.h> + +#include <system/audio.h> + +#include "qahw_api.h" + +__BEGIN_DECLS + +#define QAHW_EFFECT_API_VERSION_0_0 QAHW_MAKE_API_VERSION(0, 0) +#define QAHW_EFFECT_API_VERSION_MIN QAHW_EFFECT_API_VERSION_0_0 + +///////////////////////////////////////////////// +// Common Definitions +///////////////////////////////////////////////// + +// +//--- Effect descriptor structure qahw_effect_descriptor_t +// + +// Unique effect ID (can be generated from the following site: +// http://www.itu.int/ITU-T/asn1/uuid.html) +// This format is used for both "type" and "uuid" fields of the effect descriptor structure. +// - When used for effect type and the engine is implementing and effect corresponding to a standard +// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface. +// - When used as uuid, it should be a unique UUID for this particular implementation. +typedef struct qahw_effect_uuid_s { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint16_t clockSeq; + uint8_t node[6]; +} qahw_effect_uuid_t; + +// Maximum length of character strings in structures defines by this API. +#define QAHW_EFFECT_STRING_LEN_MAX 64 + +// NULL UUID definition (matches SL_IID_NULL_) +#define QAHW_EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \ + { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } } +static const qahw_effect_uuid_t QAHW_EFFECT_UUID_NULL_ = QAHW_EFFECT_UUID_INITIALIZER; +static const qahw_effect_uuid_t * const QAHW_EFFECT_UUID_NULL = &QAHW_EFFECT_UUID_NULL_; +static const char * const QAHW_EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210"; + + +// The effect descriptor contains necessary information to facilitate the enumeration of the effect +// engines present in a library. +typedef struct qahw_effect_descriptor_s { + qahw_effect_uuid_t type; // UUID of to the OpenSL ES interface implemented by this effect + qahw_effect_uuid_t uuid; // UUID for this particular implementation + uint32_t apiVersion; // Version of the effect control API implemented + uint32_t flags; // effect engine capabilities/requirements flags (see below) + uint16_t cpuLoad; // CPU load indication (see below) + uint16_t memoryUsage; // Data Memory usage (see below) + char name[QAHW_EFFECT_STRING_LEN_MAX]; // human readable effect name + char implementor[QAHW_EFFECT_STRING_LEN_MAX]; // human readable effect implementor name +} qahw_effect_descriptor_t; + +#define QAHW_EFFECT_MAKE_API_VERSION(M, m) (((M)<<16) | ((m) & 0xFFFF)) +#define QAHW_EFFECT_API_VERSION_MAJOR(v) ((v)>>16) +#define QAHW_EFFECT_API_VERSION_MINOR(v) ((m) & 0xFFFF) + + +///////////////////////////////////////////////// +// Effect control interface +///////////////////////////////////////////////// + +// Effect control interface version 2.0 +#define QAHW_EFFECT_CONTROL_API_VERSION QAHW_EFFECT_MAKE_API_VERSION(2,0) + +typedef void* qahw_effect_handle_t; + + +// Forward definition of type qahw_audio_buffer_t +typedef struct qahw_audio_buffer_s qahw_audio_buffer_t; + + +// +//--- Standardized command codes for command() function +// +enum qahw_effect_command_e { + QAHW_EFFECT_CMD_INIT, // initialize effect engine + QAHW_EFFECT_CMD_SET_CONFIG, // configure effect engine (see effect_config_t) + QAHW_EFFECT_CMD_RESET, // reset effect engine + QAHW_EFFECT_CMD_ENABLE, // enable effect process + QAHW_EFFECT_CMD_DISABLE, // disable effect process + QAHW_EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t) + QAHW_EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred + QAHW_EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred + QAHW_EFFECT_CMD_GET_PARAM, // get parameter + QAHW_EFFECT_CMD_SET_DEVICE, // set audio device (see audio.h, audio_devices_t) + QAHW_EFFECT_CMD_SET_VOLUME, // set volume + QAHW_EFFECT_CMD_SET_AUDIO_MODE, // set the audio mode (normal, ring, ...) + QAHW_EFFECT_CMD_SET_CONFIG_REVERSE, // configure effect engine reverse stream(see effect_config_t) + QAHW_EFFECT_CMD_SET_INPUT_DEVICE, // set capture device (see audio.h, audio_devices_t) + QAHW_EFFECT_CMD_GET_CONFIG, // read effect engine configuration + QAHW_EFFECT_CMD_GET_CONFIG_REVERSE, // read configure effect engine reverse stream configuration + QAHW_EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,// get all supported configurations for a feature. + QAHW_EFFECT_CMD_GET_FEATURE_CONFIG, // get current feature configuration + QAHW_EFFECT_CMD_SET_FEATURE_CONFIG, // set current feature configuration + QAHW_EFFECT_CMD_SET_AUDIO_SOURCE, // set the audio source (see audio.h, audio_source_t) + QAHW_EFFECT_CMD_OFFLOAD, // set if effect thread is an offload one, + // send the ioHandle of the effect thread + QAHW_EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code +}; + +//================================================================================================== +// command: QAHW_EFFECT_CMD_INIT +//-------------------------------------------------------------------------------------------------- +// description: +// Initialize effect engine: All configurations return to default +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Apply new audio parameters configurations for input and output buffers +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: QAHW_EFFECT_CMD_RESET +//-------------------------------------------------------------------------------------------------- +// description: +// Reset the effect engine. Keep configuration but resets state and buffer content +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: QAHW_EFFECT_CMD_ENABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Enable the process. Called by the framework before the first call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: QAHW_EFFECT_CMD_DISABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Disable the process. Called by the framework after the last call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter and apply it immediately +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_PARAM_DEFERRED +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter but apply it only when receiving QAHW_EFFECT_CMD_SET_PARAM_COMMIT command +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_PARAM_COMMIT +//-------------------------------------------------------------------------------------------------- +// description: +// Apply all previously received QAHW_EFFECT_CMD_SET_PARAM_DEFERRED commands +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: QAHW_EFFECT_CMD_GET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Get a parameter value +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param +// data: effect_param_t + param +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_DEVICE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the rendering device the audio output path is connected to. See audio.h, audio_devices_t +// for device values. +// The effect implementation must set QAHW_EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this +// command when the device changes +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_VOLUME +//-------------------------------------------------------------------------------------------------- +// description: +// Set and get volume. Used by audio framework to delegate volume control to effect engine. +// The effect implementation must set QAHW_EFFECT_FLAG_VOLUME_IND or QAHW_EFFECT_FLAG_VOLUME_CTRL flag in +// its descriptor to receive this command before every call to process() function +// If QAHW_EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must return +// the volume that should be applied before the effect is processed. The overall volume (the volume +// actually applied by the effect engine multiplied by the returned value) should match the value +// indicated in the command. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: n * sizeof(uint32_t) +// data: volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: n * sizeof(uint32_t) / 0 +// data: - if QAHW_EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor: +// volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +// - if QAHW_EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor: +// N/A +// It is legal to receive a null pointer as pReplyData in which case the effect framework has +// delegated volume control to another effect +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_AUDIO_MODE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the audio mode. The effect implementation must set QAHW_EFFECT_FLAG_AUDIO_MODE_IND flag in its +// descriptor to receive this command when the audio mode changes. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: audio_mode_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_CONFIG_REVERSE +//-------------------------------------------------------------------------------------------------- +// description: +// Apply new audio parameters configurations for input and output buffers of reverse stream. +// An example of reverse stream is the echo reference supplied to an Acoustic Echo Canceler. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_INPUT_DEVICE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the capture device the audio input path is connected to. See audio.h, audio_devices_t +// for device values. +// The effect implementation must set QAHW_EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this +// command when the device changes +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: QAHW_EFFECT_CMD_GET_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Read audio parameters configurations for input and output buffers +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//================================================================================================== +// command: QAHW_EFFECT_CMD_GET_CONFIG_REVERSE +//-------------------------------------------------------------------------------------------------- +// description: +// Read audio parameters configurations for input and output buffers of reverse stream +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//================================================================================================== +// command: QAHW_EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS +//-------------------------------------------------------------------------------------------------- +// description: +// Queries for supported configurations for a particular feature (e.g. get the supported +// combinations of main and auxiliary channels for a noise suppressor). +// The command parameter is the feature identifier (See effect_feature_e for a list of defined +// features) followed by the maximum number of configuration descriptor to return. +// The reply is composed of: +// - status (uint32_t): +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +// - -ENOMEM if the feature is supported but the total number of supported configurations +// exceeds the maximum number indicated by the caller. +// - total number of supported configurations (uint32_t) +// - an array of configuration descriptors. +// The actual number of descriptors returned must not exceed the maximum number indicated by +// the caller. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 2 x sizeof(uint32_t) +// data: effect_feature_e + maximum number of configurations to return +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 2 x sizeof(uint32_t) + n x sizeof (<config descriptor>) +// data: status + total number of configurations supported + array of n config descriptors +//================================================================================================== +// command: QAHW_EFFECT_CMD_GET_FEATURE_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Retrieves current configuration for a given feature. +// The reply status is: +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: effect_feature_e +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) + sizeof (<config descriptor>) +// data: status + config descriptor +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_FEATURE_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Sets current configuration for a given feature. +// The reply status is: +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +// - -EINVAL if the configuration is invalid +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) + sizeof (<config descriptor>) +// data: effect_feature_e + config descriptor +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) +// data: status +//================================================================================================== +// command: QAHW_EFFECT_CMD_SET_AUDIO_SOURCE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the audio source the capture path is configured for (Camcorder, voice recognition...). +// See audio.h, audio_source_t for values. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: QAHW_EFFECT_CMD_OFFLOAD +//-------------------------------------------------------------------------------------------------- +// description: +// 1.indicate if the playback thread the effect is attached to is offloaded or not +// 2.update the io handle of the playback thread the effect is attached to +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_offload_param_t) +// data: effect_offload_param_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// command: QAHW_EFFECT_CMD_FIRST_PROPRIETARY +//-------------------------------------------------------------------------------------------------- +// description: +// All proprietary effect commands must use command codes above this value. The size and format of +// command and response fields is free in this case +//================================================================================================== + + +// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t +// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with +// regard to the channel mask definition in audio.h, audio_channel_mask_t e.g : +// Stereo: left, right +// 5 point 1: front left, front right, front center, low frequency, back left, back right +// The buffer size is expressed in frame count, a frame being composed of samples for all +// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by +// definition +struct qahw_audio_buffer_s { + size_t frameCount; // number of frames in buffer + union { + void* raw; // raw pointer to start of buffer + int32_t* s32; // pointer to signed 32 bit data at start of buffer + int16_t* s16; // pointer to signed 16 bit data at start of buffer + uint8_t* u8; // pointer to unsigned 8 bit data at start of buffer + }; +}; + +// The buffer_provider_s structure contains functions that can be used +// by the effect engine process() function to query and release input +// or output audio buffer. +// The getBuffer() function is called to retrieve a buffer where data +// should read from or written to by process() function. +// The releaseBuffer() function MUST be called when the buffer retrieved +// with getBuffer() is not needed anymore. +// The process function should use the buffer provider mechanism to retrieve +// input or output buffer if the in_buffer or out_buffer passed as argument is NULL +// and the buffer configuration (buffer_config_t) given by the QAHW_EFFECT_CMD_SET_CONFIG +// command did not specify an audio buffer. + +typedef int32_t (* qahw_buffer_function_t)(void *cookie, qahw_audio_buffer_t *buffer); + +typedef struct qahw_buffer_provider_s { + qahw_buffer_function_t getBuffer; // retrieve next buffer + qahw_buffer_function_t releaseBuffer; // release used buffer + void *cookie; // for use by client of buffer provider functions +} qahw_buffer_provider_t; + + +// The qahw_buffer_config_s structure specifies the input or output audio format +// to be used by the effect engine. It is part of the effect_config_t +// structure that defines both input and output buffer configurations and is +// passed by the QAHW_EFFECT_CMD_SET_CONFIG or QAHW_EFFECT_CMD_SET_CONFIG_REVERSE command. +typedef struct qahw_buffer_config_s { + qahw_audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly + uint32_t samplingRate; // sampling rate + uint32_t channels; // channel mask (see audio_channel_mask_t in audio.h) + qahw_buffer_provider_t bufferProvider; // buffer provider + uint8_t format; // Audio format (see audio_format_t in audio.h) + uint8_t accessMode; // read/write or accumulate in buffer (qahw_effect_buffer_access_e) + uint16_t mask; // indicates which of the above fields is valid +} qahw_buffer_config_t; + +// Values for "accessMode" field of buffer_config_t: +// overwrite, read only, accumulate (read/modify/write) +enum qahw_effect_buffer_access_e { + QAHW_EFFECT_BUFFER_ACCESS_WRITE, + QAHW_EFFECT_BUFFER_ACCESS_READ, + QAHW_EFFECT_BUFFER_ACCESS_ACCUMULATE + +}; + +// feature identifiers for QAHW_EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS command +enum qahw_effect_feature_e { + QAHW_EFFECT_FEATURE_AUX_CHANNELS, // supports auxiliary channels (e.g. dual mic noise suppressor) + QAHW_EFFECT_FEATURE_CNT +}; + +// QAHW_EFFECT_FEATURE_AUX_CHANNELS feature configuration descriptor. Describe a combination +// of main and auxiliary channels supported +typedef struct qahw_channel_config_s { + audio_channel_mask_t main_channels; // channel mask for main channels + audio_channel_mask_t aux_channels; // channel mask for auxiliary channels +} qahw_channel_config_t; + + +// Values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field +// in buffer_config_t must be taken into account when executing the QAHW_EFFECT_CMD_SET_CONFIG command +#define QAHW_EFFECT_CONFIG_BUFFER 0x0001 // buffer field must be taken into account +#define QAHW_EFFECT_CONFIG_SMP_RATE 0x0002 // samplingRate field must be taken into account +#define QAHW_EFFECT_CONFIG_CHANNELS 0x0004 // channels field must be taken into account +#define QAHW_EFFECT_CONFIG_FORMAT 0x0008 // format field must be taken into account +#define QAHW_EFFECT_CONFIG_ACC_MODE 0x0010 // accessMode field must be taken into account +#define QAHW_EFFECT_CONFIG_PROVIDER 0x0020 // bufferProvider field must be taken into account +#define QAHW_EFFECT_CONFIG_ALL (QAHW_EFFECT_CONFIG_BUFFER | QAHW_EFFECT_CONFIG_SMP_RATE | \ + QAHW_EFFECT_CONFIG_CHANNELS | QAHW_EFFECT_CONFIG_FORMAT | \ + QAHW_EFFECT_CONFIG_ACC_MODE | QAHW_EFFECT_CONFIG_PROVIDER) + + +// effect_config_s structure describes the format of the pCmdData argument of QAHW_EFFECT_CMD_SET_CONFIG +// command to configure audio parameters and buffers for effect engine input and output. +typedef struct qahw_effect_config_s { + qahw_buffer_config_t input_cfg; + qahw_buffer_config_t output_cfg; +} qahw_effect_config_t; + + +// effect_param_s structure describes the format of the pCmdData argument of QAHW_EFFECT_CMD_SET_PARAM +// command and pCmdData and pReplyData of QAHW_EFFECT_CMD_GET_PARAM command. +// psize and vsize represent the actual size of parameter and value. +// +// NOTE: the start of value field inside the data field is always on a 32 bit boundary: +// +// +-----------+ +// | status | sizeof(int) +// +-----------+ +// | psize | sizeof(int) +// +-----------+ +// | vsize | sizeof(int) +// +-----------+ +// | | | | +// ~ parameter ~ > psize | +// | | | > ((psize - 1)/sizeof(int) + 1) * sizeof(int) +// +-----------+ | +// | padding | | +// +-----------+ +// | | | +// ~ value ~ > vsize +// | | | +// +-----------+ + +typedef struct qahw_effect_param_s { + int32_t status; // Transaction status (unused for command, used for reply) + uint32_t psize; // Parameter size + uint32_t vsize; // Value size + char data[]; // Start of Parameter + Value data +} qahw_effect_param_t; + +// structure used by QAHW_EFFECT_CMD_OFFLOAD command +typedef struct qahw_effect_offload_param_s { + bool isOffload; // true if the playback thread the effect is attached to is offloaded + int ioHandle; // io handle of the playback thread the effect is attached to +} qahw_effect_offload_param_t; + + +///////////////////////////////////////////////// +// Effect library interface +///////////////////////////////////////////////// + +// Effect library interface version 3.0 +// Note that EffectsFactory.c only checks the major version component, so changes to the minor +// number can only be used for fully backwards compatible changes +#define QAHW_EFFECT_LIBRARY_API_VERSION QAHW_EFFECT_MAKE_API_VERSION(3, 0) + +typedef void* qahw_effect_lib_handle_t; + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: qahw_effect_load_library +// +// Description: Loads an effect library +// +// Input: +// lib_name: Effect library name. +// +// Output: +// returned value: NULL if fails to load library. +// valid effect library handle +// +//////////////////////////////////////////////////////////////////////////////// +qahw_effect_lib_handle_t qahw_effect_load_library(const char *lib_name); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: qahw_effect_unload_library +// +// Description: Unload the audio effect library +// +// Input: +// handle: Effect library handle. +// +// Output: +// returned value: 0 successful operation. +// -EINVAL invalid effect library handle +// +//////////////////////////////////////////////////////////////////////////////// +int32_t qahw_effect_unload_library(qahw_effect_lib_handle_t handle); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: qahw_effect_create +// +// Description: Creates an effect engine of the specified implementation uuid and +// returns an effect control interface on this engine. The function will allocate the +// resources for an instance of the requested effect engine and return +// a handle on the effect control interface. +// +// Input: +// handle: handle on the effect library. +// uuid: pointer to the effect uuid. +// sessionId: audio session to which this effect instance will be attached. +// All effects created with the same session ID are connected in series +// and process the same signal stream. Knowing that two effects are part +// of the same effect chain can help the library implement some kind of +// optimizations. +// io_handle: identifies the output or input stream this effect is directed to in +// audio HAL. +// For future use especially with tunneled HW accelerated effects +// +// Input/Output: +// effect_handle: address where to return the effect interface handle. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid pEffectUuid or effect_handle +// -ENOENT no effect with this uuid found +// *effect_handle: updated with the effect interface handle. +// +//////////////////////////////////////////////////////////////////////////////// +int32_t qahw_effect_create(qahw_effect_lib_handle_t handle, + const qahw_effect_uuid_t *uuid, + int32_t io_handle, + qahw_effect_handle_t *effect_handle); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: qahw_effect_release +// +// Description: Releases the effect engine whose handle is given as argument. +// All resources allocated to this particular instance of the effect are +// released. +// +// Input: +// handle: handle on the effect library. +// effect_handle: handle on the effect interface to be released. +// +// Output: +// returned value: 0 successful operation. +// -EINVAL invalid interface handle +// +//////////////////////////////////////////////////////////////////////////////// +int32_t qahw_effect_release(qahw_effect_lib_handle_t handle, + qahw_effect_handle_t effect_handle); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: qahw_effect_get_descriptor +// +// Description: Returns the descriptor of the effect engine which implementation UUID is +// given as argument. +// +// Input/Output: +// handle: handle on the effect library. +// uuid: pointer to the effect uuid. +// effect_desc: address where to return the effect descriptor. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid effect_desc or uuid +// *effect_desc: updated with the effect descriptor. +// +//////////////////////////////////////////////////////////////////////////////// +int32_t qahw_effect_get_descriptor(qahw_effect_lib_handle_t handle, + const qahw_effect_uuid_t *uuid, + qahw_effect_descriptor_t *effect_desc); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: qahw_effect_get_version +// +// Description: Get version of IOT effect APIs. +// +// Output: +// returned value: version number +// +//////////////////////////////////////////////////////////////////////////////// +int32_t qahw_effect_get_version(); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: qahw_effect_process +// +// Description: Effect process function. Takes input samples as specified +// (count and location) in input buffer descriptor and output processed +// samples as specified in output buffer descriptor. If the buffer descriptor +// is not specified the function must use either the buffer or the +// buffer provider function installed by the QAHW_EFFECT_CMD_SET_CONFIG command. +// The effect framework will call the process() function after the QAHW_EFFECT_CMD_ENABLE +// command is received and until the QAHW_EFFECT_CMD_DISABLE is received. When the engine +// receives the QAHW_EFFECT_CMD_DISABLE command it should turn off the effect gracefully +// and when done indicate that it is OK to stop calling the process() function by +// returning the -ENODATA status. +// +// NOTE: the process() function implementation should be "real-time safe" that is +// it should not perform blocking calls: malloc/free, sleep, read/write/open/close, +// pthread_cond_wait/pthread_mutex_lock... +// +// Input: +// self: handle to the effect interface this function is called on. +// in_buffer: buffer descriptor indicating where to read samples to process. +// If NULL, use the configuration passed by QAHW_EFFECT_CMD_SET_CONFIG command. +// out_buffer: buffer descriptor indicating where to write processed samples. +// If NULL, use the configuration passed by QAHW_EFFECT_CMD_SET_CONFIG command. +// +// Output: +// returned value: 0 successful operation +// -ENODATA the engine has finished the disable phase and the framework +// can stop calling process() +// -EINVAL invalid interface handle or +// invalid input/output buffer description +//////////////////////////////////////////////////////////////////////////////// +int32_t qahw_effect_process(qahw_effect_handle_t self, + qahw_audio_buffer_t *in_buffer, + qahw_audio_buffer_t *out_buffer); +//////////////////////////////////////////////////////////////////////////////// +// +// Function: qahw_effect_command +// +// Description: Send a command and receive a response to/from effect engine. +// +// Input: +// self: handle to the effect interface this function is called on. +// cmd_code: command code: the command can be a standardized command defined in +// qahw_effect_command_e (see below) or a proprietary command. +// cmd_size: size of command in bytes +// cmd_data: pointer to command data +// reply_data: pointer to reply data +// +// Input/Output: +// reply_size: maximum size of reply data as input +// actual size of reply data as output +// +// Output: +// returned value: 0 successful operation +// -EINVAL invalid interface handle or +// invalid command/reply size or format according to +// command code +// The return code should be restricted to indicate problems related to this API +// specification. Status related to the execution of a particular command should be +// indicated as part of the reply field. +// +// *reply_data updated with command response +// +//////////////////////////////////////////////////////////////////////////////// +int32_t qahw_effect_command(qahw_effect_handle_t self, + uint32_t cmd_code, + uint32_t cmd_size, + void *cmd_data, + uint32_t *reply_size, + void *reply_data); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: qahw_effect_process_reverse +// +// Description: Process reverse stream function. This function is used to pass +// a reference stream to the effect engine. If the engine does not need a reference +// stream, this function pointer can be set to NULL. +// This function would typically implemented by an Echo Canceler. +// +// Input: +// self: handle to the effect interface this function is called on. +// in_buffer: buffer descriptor indicating where to read samples to process. +// If NULL, use the configuration passed by +// QAHW_EFFECT_CMD_SET_CONFIG_REVERSE command. +// +// out_buffer: buffer descriptor indicating where to write processed samples. +// If NULL, use the configuration passed by +// QAHW_EFFECT_CMD_SET_CONFIG_REVERSE command. +// If the buffer and buffer provider in the configuration received by +// QAHW_EFFECT_CMD_SET_CONFIG_REVERSE are also NULL, do not return modified reverse +// stream data +// +// Output: +// returned value: 0 successful operation +// -ENODATA the engine has finished the disable phase and the framework +// can stop calling process_reverse() +// -EINVAL invalid interface handle or +// invalid input/output buffer description +//////////////////////////////////////////////////////////////////////////////// +int32_t qahw_effect_process_reverse(qahw_effect_handle_t self, + qahw_audio_buffer_t *in_buffer, + qahw_audio_buffer_t *out_buffer); + + +__END_DECLS + +#endif // ANDROID_AUDIO_QAHW_EFFECT_H diff --git a/qahw_api/inc/qahw_effect_bassboost.h b/qahw_api/inc/qahw_effect_bassboost.h new file mode 100644 index 00000000..376c4a73 --- /dev/null +++ b/qahw_api/inc/qahw_effect_bassboost.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2011 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. + */ + +#ifndef QAHW_EFFECT_BASSBOOST_H_ +#define QAHW_EFFECT_BASSBOOST_H_ + +#include <qahw_effect_api.h> + +#if __cplusplus +extern "C" { +#endif + +#define QAHW_EFFECT_BASSBOOST_LIBRARY "libqcompostprocbundle.so" + +static const qahw_effect_uuid_t SL_IID_BASSBOOST_ = { 0x0634f220, 0xddd4, 0x11db, 0xa0fc, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_BASSBOOST = &SL_IID_BASSBOOST_; + +static const qahw_effect_uuid_t SL_IID_BASSBOOST_UUID_ = { 0x2c4a8c24, 0x1581, 0x487f, 0x94f6, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_BASSBOOST_UUID = &SL_IID_BASSBOOST_UUID_; + +/* enumerated parameter settings for BassBoost effect */ +typedef enum +{ + BASSBOOST_PARAM_STRENGTH_SUPPORTED, + BASSBOOST_PARAM_STRENGTH +} qahw_bassboost_params; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*QAHW_EFFECT_BASSBOOST_H_*/ diff --git a/qahw_api/inc/qahw_effect_environmentalreverb.h b/qahw_api/inc/qahw_effect_environmentalreverb.h new file mode 100644 index 00000000..9e36ccfe --- /dev/null +++ b/qahw_api/inc/qahw_effect_environmentalreverb.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2011 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. + */ + +#ifndef QAHW_EFFECT_ENVIRONMENTALREVERB_H_ +#define QAHW_EFFECT_ENVIRONMENTALREVERB_H_ + +#include <qahw_effect_api.h> + +#if __cplusplus +extern "C" { +#endif + +#define QAHW_EFFECT_ENV_REVERB_LIBRARY "libqcompostprocbundle.so" + +static const qahw_effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, + { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } }; +const qahw_effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_; + +static const qahw_effect_uuid_t SL_IID_INS_ENVIRONMENTALREVERB_UUID_ = { 0xeb64ea04, 0x973b, 0x43d2, 0x8f5e, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_INS_ENVIRONMENTALREVERB_UUID = &SL_IID_INS_ENVIRONMENTALREVERB_UUID_; + +static const qahw_effect_uuid_t SL_IID_AUX_ENVIRONMENTALREVERB_UUID_ = { 0x79a18026, 0x18fd, 0x4185, 0x8233, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_AUX_ENVIRONMENTALREVERB_UUID = &SL_IID_AUX_ENVIRONMENTALREVERB_UUID_; + +/* enumerated parameter settings for environmental reverb effect */ +typedef enum +{ + // Parameters below are as defined in OpenSL ES specification for environmental reverb interface + REVERB_PARAM_ROOM_LEVEL, // in millibels, range -6000 to 0 + REVERB_PARAM_ROOM_HF_LEVEL, // in millibels, range -4000 to 0 + REVERB_PARAM_DECAY_TIME, // in milliseconds, range 100 to 20000 + REVERB_PARAM_DECAY_HF_RATIO, // in permilles, range 100 to 1000 + REVERB_PARAM_REFLECTIONS_LEVEL, // in millibels, range -6000 to 0 + REVERB_PARAM_REFLECTIONS_DELAY, // in milliseconds, range 0 to 65 + REVERB_PARAM_REVERB_LEVEL, // in millibels, range -6000 to 0 + REVERB_PARAM_REVERB_DELAY, // in milliseconds, range 0 to 65 + REVERB_PARAM_DIFFUSION, // in permilles, range 0 to 1000 + REVERB_PARAM_DENSITY, // in permilles, range 0 to 1000 + REVERB_PARAM_PROPERTIES, + REVERB_PARAM_BYPASS +} qahw_env_reverb_params; + +//t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification. +typedef struct s_reverb_settings { + int16_t roomLevel; + int16_t roomHFLevel; + uint32_t decayTime; + int16_t decayHFRatio; + int16_t reflectionsLevel; + uint32_t reflectionsDelay; + int16_t reverbLevel; + uint32_t reverbDelay; + int16_t diffusion; + int16_t density; +} __attribute__((packed)) qahw_reverb_settings; + + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*QAHW_EFFECT_ENVIRONMENTALREVERB_H_*/ diff --git a/qahw_api/inc/qahw_effect_equalizer.h b/qahw_api/inc/qahw_effect_equalizer.h new file mode 100644 index 00000000..029ea7e2 --- /dev/null +++ b/qahw_api/inc/qahw_effect_equalizer.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2011 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. + */ + +#ifndef QAHW_EFFECT_EQUALIZER_H_ +#define QAHW_EFFECT_EQUALIZER_H_ + +#include <qahw_effect_api.h> + +#if __cplusplus +extern "C" { +#endif + +#define QAHW_EFFECT_EQUALIZER_LIBRARY "libqcompostprocbundle.so" + +static const qahw_effect_uuid_t SL_IID_EQUALIZER_ = { 0x0bed4300, 0xddd6, 0x11db, 0x8f34, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_EQUALIZER = &SL_IID_EQUALIZER_; + +static const qahw_effect_uuid_t SL_IID_EQUALIZER_UUID_ = { 0xa0dac280, 0x401c, 0x11e3, 0x9379, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_EQUALIZER_UUID = &SL_IID_EQUALIZER_UUID_; + +/* enumerated parameters for Equalizer effect */ +typedef enum +{ + EQ_PARAM_NUM_BANDS, // Gets the number of frequency bands that the equalizer + // supports. + EQ_PARAM_LEVEL_RANGE, // Returns the minimum and maximum band levels supported. + EQ_PARAM_BAND_LEVEL, // Gets/Sets the gain set for the given equalizer band. + EQ_PARAM_CENTER_FREQ, // Gets the center frequency of the given band. + EQ_PARAM_BAND_FREQ_RANGE, // Gets the frequency range of the given frequency band. + EQ_PARAM_GET_BAND, // Gets the band that has the most effect on the given + // frequency. + EQ_PARAM_CUR_PRESET, // Gets/Sets the current preset. + EQ_PARAM_GET_NUM_OF_PRESETS, // Gets the total number of presets the equalizer supports. + EQ_PARAM_GET_PRESET_NAME, // Gets the preset name based on the index. + EQ_PARAM_PROPERTIES // Gets/Sets all parameters at a time. +} qahw_equalizer_params; + +enum +{ + EQ_PRESET_NORMAL = 0, + EQ_PRESET_CLASSICAL, + EQ_PRESET_DANCE, + EQ_PRESET_FLAT, + EQ_PRESET_FOLK, + EQ_PRESET_HEAVY_METAL, + EQ_PRESET_HIPHOP, + EQ_PRESET_JAZZ, + EQ_PRESET_POP, + EQ_PRESET_ROCK, + EQ_PRESET_FX_BOOSTER, + EQ_PRESET_MAX_NUM, +}; + +//t_equalizer_settings groups all current equalizer setting for backup and restore. +typedef struct s_equalizer_settings { + uint16_t curPreset; + uint16_t numBands; + uint16_t bandLevels[]; +} qahw_equalizer_settings; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*QAHW_EFFECT_EQUALIZER_H_*/ diff --git a/qahw_api/inc/qahw_effect_presetreverb.h b/qahw_api/inc/qahw_effect_presetreverb.h new file mode 100644 index 00000000..169d40b1 --- /dev/null +++ b/qahw_api/inc/qahw_effect_presetreverb.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2011 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. + */ + +#ifndef QAHW_EFFECT_PRESETREVERB_H_ +#define QAHW_EFFECT_PRESETREVERB_H_ + +#include <qahw_effect_api.h> + +#if __cplusplus +extern "C" { +#endif + +#define QAHW_EFFECT_PRESET_REVERB_LIBRARY "libqcompostprocbundle.so" + +static const qahw_effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_; + +static const qahw_effect_uuid_t SL_IID_INS_PRESETREVERB_ = { 0xaa2bebf6, 0x47cf, 0x4613, 0x9bca, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_INS_PRESETREVERB = &SL_IID_INS_PRESETREVERB_; + +static const qahw_effect_uuid_t SL_IID_AUX_PRESETREVERB_ = { 0x6987be09, 0xb142, 0x4b41, 0x9056, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_AUX_PRESETREVERB = &SL_IID_AUX_PRESETREVERB_; + +/* enumerated parameter settings for preset reverb effect */ +typedef enum +{ + REVERB_PARAM_PRESET +} qahw_preset_reverb_params; + + +typedef enum +{ + REVERB_PRESET_NONE, + REVERB_PRESET_SMALLROOM, + REVERB_PRESET_MEDIUMROOM, + REVERB_PRESET_LARGEROOM, + REVERB_PRESET_MEDIUMHALL, + REVERB_PRESET_LARGEHALL, + REVERB_PRESET_PLATE, + REVERB_PRESET_LAST = REVERB_PRESET_PLATE +} qahw_reverb_presets; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*QAHW_EFFECT_PRESETREVERB_H_*/ diff --git a/qahw_api/inc/qahw_effect_virtualizer.h b/qahw_api/inc/qahw_effect_virtualizer.h new file mode 100644 index 00000000..138b850a --- /dev/null +++ b/qahw_api/inc/qahw_effect_virtualizer.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2011 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. + */ + +#ifndef QAHW_EFFECT_VIRTUALIZER_H_ +#define QAHW_EFFECT_VIRTUALIZER_H_ + +#include <qahw_effect_api.h> + +#if __cplusplus +extern "C" { +#endif + +#define QAHW_EFFECT_VIRTUALIZER_LIBRARY "libqcompostprocbundle.so" + +static const qahw_effect_uuid_t SL_IID_VIRTUALIZER_ = { 0x37cc2c00, 0xdddd, 0x11db, 0x8577, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_VIRTUALIZER = &SL_IID_VIRTUALIZER_; + +static const qahw_effect_uuid_t SL_IID_VIRTUALIZER_UUID_ = { 0x509a4498, 0x561a, 0x4bea, 0xb3b1, + { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_VIRTUALIZER_UUID = &SL_IID_VIRTUALIZER_UUID_; + +/* enumerated parameter settings for virtualizer effect */ +/* to keep in sync with frameworks/base/media/java/android/media/audiofx/Virtualizer.java */ +typedef enum +{ + VIRTUALIZER_PARAM_STRENGTH_SUPPORTED, + VIRTUALIZER_PARAM_STRENGTH, + // used with EFFECT_CMD_GET_PARAM + // format: + // parameters int32_t VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES + // audio_channel_mask_t input channel mask + // audio_devices_t audio output device + // output int32_t* an array of length 3 * the number of channels in the mask + // where entries are the succession of the channel mask + // of each speaker (i.e. a single bit is selected in the + // channel mask) followed by the azimuth and the + // elevation angles. + // status int -EINVAL if configuration is not supported or invalid or not forcing + // 0 if configuration is supported and the mode is forced + // notes: + // - all angles are expressed in degrees and are relative to the listener, + // - for azimuth: 0 is the direction the listener faces, 180 is behind the listener, and + // -90 is to her/his left, + // - for elevation: 0 is the horizontal plane, +90 is above the listener, -90 is below. + VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES, + // used with EFFECT_CMD_SET_PARAM + // format: + // parameters int32_t VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE + // audio_devices_t audio output device + // status int -EINVAL if the device is not supported or invalid + // 0 if the device is supported and the mode is forced, or forcing + // was disabled for the AUDIO_DEVICE_NONE audio device. + VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE, + // used with EFFECT_CMD_GET_PARAM + // format: + // parameters int32_t VIRTUALIZER_PARAM_VIRTUALIZATION_MODE + // output audio_device_t audio device reflecting the current virtualization mode, + // AUDIO_DEVICE_NONE when not virtualizing + // status int -EINVAL if an error occurred + // 0 if the output value is successfully retrieved + VIRTUALIZER_PARAM_VIRTUALIZATION_MODE +} qahw_virtualizer_params; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*QAHW_EFFECT_VIRTUALIZER_H_*/ diff --git a/qahw_api/inc/qahw_effect_visualizer.h b/qahw_api/inc/qahw_effect_visualizer.h new file mode 100644 index 00000000..ce79bab9 --- /dev/null +++ b/qahw_api/inc/qahw_effect_visualizer.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2011 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. + */ + +#ifndef QAHW_EFFECT_VISUALIZER_H_ +#define QAHW_EFFECT_VISUALIZER_H_ + +#include <qahw_effect_api.h> + +#if __cplusplus +extern "C" { +#endif + +#define QAHW_EFFECT_VISUALIZER_LIBRARY "libqcomvisualizer.so" + +static const qahw_effect_uuid_t SL_IID_VISUALIZATION_ = + { 0xe46b26a0, 0xdddd, 0x11db, 0x8afd, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_VISUALIZATION = &SL_IID_VISUALIZATION_; + +static const qahw_effect_uuid_t SL_IID_VISUALIZATION_UUID_ = + { 0x7a8044a0, 0x1a71, 0x11e3, 0xa184, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const qahw_effect_uuid_t * const SL_IID_VISUALIZATION_UUID = &SL_IID_VISUALIZATION_UUID_; + +#define VISUALIZER_CAPTURE_SIZE_MAX 1024 // maximum capture size in samples +#define VISUALIZER_CAPTURE_SIZE_MIN 128 // minimum capture size in samples + +// to keep in sync with frameworks/base/media/java/android/media/audiofx/Visualizer.java +#define VISUALIZER_SCALING_MODE_NORMALIZED 0 +#define VISUALIZER_SCALING_MODE_AS_PLAYED 1 + +#define MEASUREMENT_MODE_NONE 0x0 +#define MEASUREMENT_MODE_PEAK_RMS 0x1 + +#define MEASUREMENT_IDX_PEAK 0 +#define MEASUREMENT_IDX_RMS 1 + +/* enumerated parameters for Visualizer effect */ +typedef enum +{ + VISUALIZER_PARAM_CAPTURE_SIZE, // Sets the number PCM samples in the capture. + VISUALIZER_PARAM_SCALING_MODE, // Sets the way the captured data is scaled + VISUALIZER_PARAM_LATENCY, // Informs the visualizer about the downstream latency + VISUALIZER_PARAM_MEASUREMENT_MODE, // Sets which measurements are to be made +} qahw_visualizer_params; + +/* commands */ +typedef enum +{ + VISUALIZER_CMD_CAPTURE = QAHW_EFFECT_CMD_FIRST_PROPRIETARY, // Gets the latest PCM capture. + VISUALIZER_CMD_MEASURE, // Gets the current measurements +} qahw_visualizer_cmds; + +// VISUALIZER_CMD_CAPTURE retrieves the latest PCM snapshot captured by the visualizer engine. +// It returns the number of samples specified by VISUALIZER_PARAM_CAPTURE_SIZE +// in 8 bit unsigned format (0 = 0x80) + +// VISUALIZER_CMD_MEASURE retrieves the lastest measurements as int32_t saved in the +// MEASUREMENT_IDX_* array index order. + +#if __cplusplus +} // extern "C" +#endif + +#endif /*QAHW_EFFECT_VISUALIZER_H_*/ diff --git a/qahw_api/src/qahw_effect.c b/qahw_api/src/qahw_effect.c new file mode 100644 index 00000000..cf7b3fd3 --- /dev/null +++ b/qahw_api/src/qahw_effect.c @@ -0,0 +1,321 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define LOG_TAG "qahw_effect" +//#define LOG_NDEBUG 0 +#define LOG_NDDEBUG 0 + +#include <cutils/list.h> +#include <dlfcn.h> +#include <utils/Log.h> +#include <hardware/audio.h> +#include <hardware/audio_effect.h> +#include <stdlib.h> + +#include "qahw_effect_api.h" + +// The current effect API version. +#define QAHW_EFFECT_API_VERSION_CURRENT QAHW_EFFECT_API_VERSION_0_0 +#define PATH_MAX 4096 + +typedef struct { + char lib_path[PATH_MAX]; + pthread_mutex_t lock; + uint32_t ref_count; + audio_effect_library_t *desc; + void *handle; + struct listnode lib_list; +} qahw_effect_lib_t; + +// list of loaded effect libraries +static struct listnode effect_libraries_list; +static int effect_libraries_count = 0; +static pthread_mutex_t effect_libraries_lock = PTHREAD_MUTEX_INITIALIZER; + +qahw_effect_lib_t *get_qahw_effect_lib_by_name(const char *lib_path) { + struct listnode *node = NULL; + qahw_effect_lib_t *effect_lib = NULL, *effect_lib_temp = NULL; + + if (lib_path == NULL) + goto exit; + + list_for_each(node, &effect_libraries_list) { + effect_lib_temp = node_to_item(node, qahw_effect_lib_t, lib_list); + if(!strncmp(lib_path, effect_lib_temp->lib_path, PATH_MAX)) { + effect_lib = effect_lib_temp; + break; + } + } +exit: + return effect_lib; +} + + +qahw_effect_lib_t *get_qahw_effect_lib_by_desc(qahw_effect_lib_handle_t handle) { + struct listnode *node = NULL; + qahw_effect_lib_t *effect_lib = NULL, *effect_lib_temp = NULL; + + if (handle == NULL) + goto exit; + + list_for_each(node, &effect_libraries_list) { + effect_lib_temp = node_to_item(node, qahw_effect_lib_t, lib_list); + if (effect_lib_temp->desc == (audio_effect_library_t *)handle) { + effect_lib = effect_lib_temp; + break; + } + } +exit: + return effect_lib; +} + + +qahw_effect_lib_handle_t qahw_effect_load_library(const char *lib_path) { + audio_effect_library_t *desc; + qahw_effect_lib_t *qahw_effect_lib; + void *handle; + + if (strlen(lib_path) >= PATH_MAX -1) { + ALOGE("%s: effect libraries path too long", __func__); + return NULL; + } + + /* return existing lib handler if already loaded */ + pthread_mutex_lock(&effect_libraries_lock); + if (effect_libraries_count > 0) { + qahw_effect_lib = get_qahw_effect_lib_by_name(lib_path); + if (qahw_effect_lib != NULL) { + desc = qahw_effect_lib->desc; + pthread_mutex_lock(&qahw_effect_lib->lock); + qahw_effect_lib->ref_count++; + pthread_mutex_unlock(&qahw_effect_lib->lock); + goto done; + } + } + + handle = dlopen(lib_path, RTLD_NOW); + if (handle == NULL) { + ALOGE("%s: failed to dlopen lib %s", __func__, lib_path); + goto error; + } + + desc = (audio_effect_library_t *)dlsym(handle, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR); + if (desc == NULL) { + ALOGE("%s: could not find symbol %s", __func__, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR); + goto error; + } + + if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) { + ALOGE("%s: bad tag %08x in lib info struct", __func__, desc->tag); + goto error; + } + + if (EFFECT_API_VERSION_MAJOR(desc->version) != + EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) { + ALOGE("%s: bad lib version %08x", __func__, desc->version); + goto error; + } + + qahw_effect_lib = (qahw_effect_lib_t *)calloc(1, sizeof(qahw_effect_lib_t)); + if (qahw_effect_lib == NULL) { + ALOGE("%s: calloc failed", __func__); + goto error; + } + + if (!effect_libraries_count) + list_init(&effect_libraries_list); + effect_libraries_count++; + + /* init and load effect lib into global list */ + strlcpy(qahw_effect_lib->lib_path, lib_path, PATH_MAX); + pthread_mutex_init(&qahw_effect_lib->lock, (const pthread_mutexattr_t *) NULL); + qahw_effect_lib->ref_count = 1; + qahw_effect_lib->desc = desc; + qahw_effect_lib->handle = handle; + + list_add_tail(&effect_libraries_list, &qahw_effect_lib->lib_list); + +done: + pthread_mutex_unlock(&effect_libraries_lock); + return (qahw_effect_lib_handle_t)desc; + +error: + if (handle != NULL) + dlclose(handle); + + pthread_mutex_unlock(&effect_libraries_lock); + return NULL; +} + + +int32_t qahw_effect_unload_library(qahw_effect_lib_handle_t handle) { + qahw_effect_lib_t *qahw_effect_lib; + + pthread_mutex_lock(&effect_libraries_lock); + if (effect_libraries_count <= 0) { + ALOGW("%s: no valid libraries loaded", __func__); + pthread_mutex_unlock(&effect_libraries_lock); + return -EINVAL; + } + + qahw_effect_lib = get_qahw_effect_lib_by_desc(handle); + if (qahw_effect_lib == NULL) { + ALOGW("%s: effect lib handle(%p) not in loaded queue", __func__, (void *)handle); + pthread_mutex_unlock(&effect_libraries_lock); + return -EINVAL; + } + + pthread_mutex_lock(&qahw_effect_lib->lock); + qahw_effect_lib->ref_count--; + if (qahw_effect_lib->ref_count > 0) { + ALOGW("%s: skip unloading effect lib, ref count %d", __func__, qahw_effect_lib->ref_count); + pthread_mutex_unlock(&qahw_effect_lib->lock); + goto done; + } + + if (qahw_effect_lib->handle) + dlclose(qahw_effect_lib->handle); + effect_libraries_count--; + list_remove(&qahw_effect_lib->lib_list); + pthread_mutex_unlock(&qahw_effect_lib->lock); + pthread_mutex_destroy(&qahw_effect_lib->lock); + free(qahw_effect_lib); + +done: + pthread_mutex_unlock(&effect_libraries_lock); + return 0; +} + + +int32_t qahw_effect_create(qahw_effect_lib_handle_t handle, + const qahw_effect_uuid_t *uuid, + int32_t io_handle, + qahw_effect_handle_t *effect_handle) { + int32_t rc = -EINVAL; + audio_effect_library_t *desc = (audio_effect_library_t *)handle; + + if (desc != NULL) { + rc = desc->create_effect((const effect_uuid_t *)uuid, 0, io_handle, + (effect_handle_t *)effect_handle); + } + + return rc; +} + + +int32_t qahw_effect_release(qahw_effect_lib_handle_t handle, + qahw_effect_handle_t effect_handle) { + int32_t rc = -EINVAL; + audio_effect_library_t *desc = (audio_effect_library_t *)handle; + + if (desc != NULL) { + rc = desc->release_effect((effect_handle_t)effect_handle); + } + + return rc; +} + + +int32_t qahw_effect_get_descriptor(qahw_effect_lib_handle_t handle, + const qahw_effect_uuid_t *uuid, + qahw_effect_descriptor_t *effect_desc) { + int32_t rc = -EINVAL; + audio_effect_library_t *desc = (audio_effect_library_t *)handle; + + if (desc != NULL) { + rc = desc->get_descriptor((const effect_uuid_t *)uuid, (effect_descriptor_t *)effect_desc); + } + + return rc; +} + + +int32_t qahw_effect_get_version() { + return QAHW_EFFECT_API_VERSION_CURRENT; +} + + +int32_t qahw_effect_process(qahw_effect_handle_t self, + qahw_audio_buffer_t *in_buffer, + qahw_audio_buffer_t *out_buffer) { + int32_t rc = -EINVAL; + struct effect_interface_s *itfe; + + if (self) { + itfe = *((struct effect_interface_s **)self); + if (itfe) { + rc = itfe->process((effect_handle_t)self, + (audio_buffer_t *)in_buffer, + (audio_buffer_t *)out_buffer); + } + } + + return rc; +} + + +int32_t qahw_effect_command(qahw_effect_handle_t self, + uint32_t cmd_code, + uint32_t cmd_size, + void *cmd_data, + uint32_t *reply_size, + void *reply_data) { + int32_t rc = -EINVAL; + struct effect_interface_s *itfe; + + if (self) { + itfe = *((struct effect_interface_s **)self); + if (itfe) { + rc = itfe->command((effect_handle_t)self, cmd_code, cmd_size, + cmd_data, reply_size, reply_data); + } + } + + return rc; +} + + +int32_t qahw_effect_process_reverse(qahw_effect_handle_t self, + qahw_audio_buffer_t *in_buffer, + qahw_audio_buffer_t *out_buffer) { + int32_t rc = -EINVAL; + struct effect_interface_s *itfe; + + if (self) { + itfe = *((struct effect_interface_s **)self); + if (itfe) { + rc = itfe->process_reverse((effect_handle_t)self, + (audio_buffer_t *)in_buffer, + (audio_buffer_t *)out_buffer); + } + } + + return rc; +} + diff --git a/qahw_api/test/Makefile.am b/qahw_api/test/Makefile.am index c269557a..46a2ee7e 100644 --- a/qahw_api/test/Makefile.am +++ b/qahw_api/test/Makefile.am @@ -3,7 +3,8 @@ bin_PROGRAMS = hal_play_test PLAY_CPPFLAGS = -Wno-sign-compare PLAY_INCLUDES = -I $(top_srcdir)/qahw_api/inc -hal_play_test_SOURCES = qahw_playback_test.c +hal_play_test_SOURCES = qahw_playback_test.c \ + qahw_effect_test.c hal_play_test_CPPFLAGS = $(PLAY_CPPFLAGS) $(PLAY_INCLUDES) hal_play_test_CPPFLAGS += -D__unused=__attribute__\(\(__unused__\)\) hal_play_test_LDADD = -lutils ../libqahw.la diff --git a/qahw_api/test/qahw_effect_test.c b/qahw_api/test/qahw_effect_test.c new file mode 100644 index 00000000..d9ce81ee --- /dev/null +++ b/qahw_api/test/qahw_effect_test.c @@ -0,0 +1,231 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* effect test to be applied on HAL layer */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "qahw_api.h" +#include "qahw_defs.h" +#include "qahw_effect_api.h" +#include "qahw_effect_bassboost.h" +#include "qahw_effect_environmentalreverb.h" +#include "qahw_effect_equalizer.h" +#include "qahw_effect_presetreverb.h" +#include "qahw_effect_virtualizer.h" +#include "qahw_effect_visualizer.h" + +#include "qahw_effect_test.h" + +thread_func_t effect_thread_funcs[EFFECT_NUM] = { + &bassboost_thread_func, + &virtualizer_thread_func, + &equalizer_thread_func, + &visualizer_thread_func, + &reverb_thread_func, +}; + +const char * effect_str[EFFECT_NUM] = { + "bassboost", + "virtualizer", + "equalizer", + "visualizer", + "reverb", +}; + +void *bassboost_thread_func(void* data) { +} + +void *virtualizer_thread_func(void* data) { +} + +void *equalizer_thread_func(void* data) { + thread_data_t *thr_ctxt = (thread_data_t *)data; + qahw_effect_lib_handle_t lib_handle; + qahw_effect_handle_t effect_handle; + qahw_effect_descriptor_t effect_desc; + int32_t rc; + int reply_data; + uint32_t reply_size = sizeof(int); + uint32_t size = (sizeof(qahw_effect_param_t) + 2 * sizeof(int32_t)); + uint32_t buf32[size]; + qahw_effect_param_t *param = (qahw_effect_param_t *)buf32; + uint32_t preset = EQ_PRESET_NORMAL; + + pthread_mutex_lock(&thr_ctxt->mutex); + while(!thr_ctxt->exit) { + // suspend thread till signaled + fprintf(stdout, "suspend effect thread\n"); + pthread_cond_wait(&thr_ctxt->loop_cond, &thr_ctxt->mutex); + fprintf(stdout, "awake effect thread\n"); + + switch(thr_ctxt->cmd) { + case(EFFECT_LOAD_LIB): + lib_handle = qahw_effect_load_library(QAHW_EFFECT_EQUALIZER_LIBRARY); + break; + case(EFFECT_GET_DESC): + rc = qahw_effect_get_descriptor(lib_handle, SL_IID_EQUALIZER_UUID, &effect_desc); + if (rc != 0) { + fprintf(stderr, "effect_get_descriptor() returns %d\n", rc); + } + break; + case(EFFECT_CREATE): + rc = qahw_effect_create(lib_handle, SL_IID_EQUALIZER_UUID, + thr_ctxt->io_handle, &effect_handle); + if (rc != 0) { + fprintf(stderr, "effect_create() returns %d\n", rc); + } + break; + case(EFFECT_CMD): + if ((thr_ctxt->cmd_code == QAHW_EFFECT_CMD_ENABLE) || + (thr_ctxt->cmd_code == QAHW_EFFECT_CMD_DISABLE)) { + thr_ctxt->reply_size = (uint32_t *)&reply_size; + thr_ctxt->reply_data = (void *)&reply_data; + } else if (thr_ctxt->cmd_code == QAHW_EFFECT_CMD_SET_PARAM) { + param->psize = sizeof(int32_t); + *(int32_t *)param->data = EQ_PARAM_CUR_PRESET; + param->vsize = sizeof(int32_t); + memcpy((param->data + param->psize), &preset, param->vsize); + + thr_ctxt->reply_size = (uint32_t *)&reply_size; + thr_ctxt->reply_data = (void *)&reply_data; + thr_ctxt->cmd_size = size; + thr_ctxt->cmd_data = param; + preset = (preset + 1) % EQ_PRESET_MAX_NUM; // enumerate through all EQ presets + } + rc = qahw_effect_command(effect_handle, thr_ctxt->cmd_code, + thr_ctxt->cmd_size, thr_ctxt->cmd_data, + thr_ctxt->reply_size, thr_ctxt->reply_data); + if (rc != 0) { + fprintf(stderr, "effect_command() returns %d\n", rc); + } + break; + case(EFFECT_PROC): + //qahw_effect_process(); + break; + case(EFFECT_RELEASE): + rc = qahw_effect_release(lib_handle, effect_handle); + if (rc != 0) { + fprintf(stderr, "effect_release() returns %d\n", rc); + } + break; + case(EFFECT_UNLOAD_LIB): + rc = qahw_effect_unload_library(lib_handle); + if (rc != 0) { + fprintf(stderr, "effect_unload_library() returns %d\n", rc); + } + break; + } + } + pthread_mutex_unlock(&thr_ctxt->mutex); + + return NULL; +} + +void *visualizer_thread_func(void* data) { +} + +void *reverb_thread_func(void* data) { +} + +thread_data_t *create_effect_thread(thread_func_t func_ptr) { + int result; + + thread_data_t *ethread_data = (thread_data_t *)calloc(1, sizeof(thread_data_t)); + ethread_data->exit = false; + + pthread_attr_init(ðread_data->attr); + pthread_attr_setdetachstate(ðread_data->attr, PTHREAD_CREATE_JOINABLE); + pthread_mutex_init(ðread_data->mutex, NULL); + if (pthread_cond_init(ðread_data->loop_cond, NULL) != 0) { + fprintf(stderr, "pthread_cond_init fails\n"); + return NULL; + } + // create effect thread + result = pthread_create(ðread_data->effect_thread, ðread_data->attr, + func_ptr, ethread_data); + + if (result < 0) { + fprintf(stderr, "Could not create effect thread!\n"); + return NULL; + } + + return ethread_data; +} + +void effect_thread_command(thread_data_t *ethread_data, + int cmd, uint32_t cmd_code, + uint32_t cmd_size, void *cmd_data) { + if (ethread_data == NULL) { + fprintf(stderr, "invalid thread data\n"); + return; + } + + // leave interval to let thread consume the previous cond signal + usleep(500000); + + pthread_mutex_lock(ðread_data->mutex); + ethread_data->cmd = cmd; + if (cmd_code >= 0) { + ethread_data->cmd_code = cmd_code; + ethread_data->cmd_size = cmd_size; + ethread_data->cmd_data = cmd_data; + } + pthread_mutex_unlock(ðread_data->mutex); + pthread_cond_signal(ðread_data->loop_cond); + + return; +} + +void destroy_effect_thread(thread_data_t *ethread_data) { + int result; + + if (ethread_data == NULL) { + fprintf(stderr, "invalid thread data\n"); + return; + } + + pthread_mutex_lock(ðread_data->mutex); + ethread_data->exit = true; + pthread_mutex_unlock(ðread_data->mutex); + pthread_cond_signal(ðread_data->loop_cond); + + result = pthread_join(ethread_data->effect_thread, NULL); + if (result < 0) { + fprintf(stderr, "Fail to join effect thread!\n"); + return; + } + pthread_mutex_destroy(ðread_data->mutex); + pthread_cond_destroy(ðread_data->loop_cond); + + return; +} diff --git a/qahw_api/test/qahw_effect_test.h b/qahw_api/test/qahw_effect_test.h new file mode 100644 index 00000000..ffb48eae --- /dev/null +++ b/qahw_api/test/qahw_effect_test.h @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <pthread.h> + +#define EFFECT_NUM 5 +typedef void* (*thread_func_t)(void *); +extern thread_func_t effect_thread_funcs[EFFECT_NUM]; + +void *bassboost_thread_func(void*); // thread main of bassboost effect +void *virtualizer_thread_func(void*); // thread main of virtualizer effect +void *equalizer_thread_func(void*); // thread main of equalizer effect +void *visualizer_thread_func(void*); // thread main of visualizer effect +void *reverb_thread_func(void*); // thread main of reverb effect + +typedef struct thread_data { + pthread_t effect_thread; + pthread_attr_t attr; + pthread_mutex_t mutex; + pthread_cond_t loop_cond; + audio_io_handle_t io_handle; + bool exit; + int cmd; + uint32_t cmd_code; + uint32_t cmd_size; + void *cmd_data; + uint32_t *reply_size; + void *reply_data; +} thread_data_t; + +extern thread_data_t *create_effect_thread(thread_func_t); +extern void effect_thread_command(thread_data_t *, int, uint32_t, uint32_t, void *); +extern void destroy_effect_thread(thread_data_t *); + +extern const char *effect_str[EFFECT_NUM]; + +enum { + EFFECT_LOAD_LIB = 1, + EFFECT_GET_DESC, + EFFECT_CREATE, + EFFECT_CMD, + EFFECT_PROC, + EFFECT_RELEASE, + EFFECT_UNLOAD_LIB, + EFFECT_EXIT +}; + diff --git a/qahw_api/test/qahw_playback_test.c b/qahw_api/test/qahw_playback_test.c index 86244e8b..d539ce2f 100644 --- a/qahw_api/test/qahw_playback_test.c +++ b/qahw_api/test/qahw_playback_test.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2015 The Android Open Source Project * @@ -27,6 +27,8 @@ #include <time.h> #include "qahw_api.h" #include "qahw_defs.h" +#include "qahw_effect_api.h" +#include "qahw_effect_test.h" #define nullptr NULL @@ -43,6 +45,8 @@ #define FORMAT_PCM 1 +static thread_data_t *ethread_data = NULL; + struct wav_header { uint32_t riff_id; uint32_t riff_sz; @@ -377,6 +381,11 @@ int play_file(qahw_stream_handle_t* out_handle, FILE* in_file, bytes_remaining -= bytes_written; fprintf(log_file, "bytes_written %zd, bytes_remaining %zd\n", bytes_written, bytes_remaining); + + // set eq preset + if (ethread_data) { + effect_thread_command(ethread_data, EFFECT_CMD, QAHW_EFFECT_CMD_SET_PARAM, 0, NULL); + } } return rc; @@ -552,6 +561,8 @@ void usage() { printf(" -k --kpi-mode - Required for Latency KPI measurement\n"); printf(" file path is not used here as file playback is not done in this mode\n"); printf(" file path and other file specific options would be ignored in this mode.\n\n"); + printf(" -e --effect-type <effect type> - Effect used for test\n"); + printf(" 0:bassboost 1:virtualizer 2:equalizer 3:visualizer 4:reverb others:null"); printf(" \n Examples \n"); printf(" hal_play_test -f /etc/Anukoledenadu.wav -> plays Wav stream with default params\n\n"); printf(" hal_play_test -f /etc/MateRani.mp3 -t 2 -d 2 -v 0.01 -r 44100 -c 2 \n"); @@ -591,6 +602,10 @@ void usage() { printf(" ->avg_bit_rate,sample_rate,wma_bit_per_sample,wma_block_align\n"); printf(" ->wma_channel_mask,wma_encode_option,wma_format_tag\n"); printf(" hal_play_test -K -F 4 -> Measure latency KPIs for low latency output\n\n"); + printf(" hal_play_test /etc//Moto_320kbps.mp3 -t 2 -d 2 -v 0.1 -r 44100 -c 2 -e 2\n"); + printf(" -> plays MP3 stream(-t = 2) on speaker device(-d = 2)\n"); + printf(" -> 2 channels and 44100 sample rate\n\n"); + printf(" -> sound effect equalizer enabled\n\n"); } int main(int argc, char* argv[]) { @@ -639,12 +654,15 @@ int main(int argc, char* argv[]) { {"kvpairs", required_argument, 0, 'k'}, {"flags", required_argument, 0, 'F'}, {"kpi-mode", no_argument, 0, 'K'}, + {"effect-path", required_argument, 0, 'e'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; int opt = 0; int option_index = 0; + int effect_index = -1; + thread_func_t ethread_func = NULL; proxy_params.hdr.riff_id = ID_RIFF; proxy_params.hdr.riff_sz = 0; proxy_params.hdr.riff_fmt = ID_WAVE; @@ -660,7 +678,7 @@ int main(int argc, char* argv[]) { proxy_params.hdr.data_sz = 0; while ((opt = getopt_long(argc, argv, - "-f:r:c:b:d:v:l:t:a:w:k:D:KF:h", + "-f:r:c:b:d:v:l:t:a:w:k:D:KF:e:h", long_options, &option_index)) != -1) { switch (opt) { @@ -714,6 +732,14 @@ int main(int argc, char* argv[]) { case 'F': flags = atoll(optarg); flags_set = true; + case 'e': + effect_index = atoi(optarg); + if (effect_index < 0 || effect_index >= EFFECT_NUM) { + fprintf(stderr, "Invalid effect type %d\n", effect_index); + effect_index = -1; + } else { + ethread_func = effect_thread_funcs[effect_index]; + } break; case 'h': usage(); @@ -754,6 +780,9 @@ int main(int argc, char* argv[]) { if (output_device & AUDIO_DEVICE_OUT_ALL_A2DP) fprintf(stdout, "Saving pcm data to file: %s\n", proxy_params.acp.file_name); + if (effect_index != -1) + fprintf(stdout, "Effect type:%s\n", effect_str[effect_index]); + fprintf(stdout, "Starting audio hal tests.\n"); qahw_mod_handle = qahw_load_module(mod_name); @@ -776,6 +805,7 @@ int main(int argc, char* argv[]) { if (!flags_set) flags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING; + flags |= AUDIO_OUTPUT_FLAG_DIRECT; switch (filetype) { case FILE_WAV: @@ -919,16 +949,53 @@ int main(int argc, char* argv[]) { if (!rc) proxy_thread_active = true; } + + // create effect thread, use thread_data to transfer command + if (ethread_func) + ethread_data = create_effect_thread(ethread_func); + + if (ethread_data) { + // load effect module + effect_thread_command(ethread_data, EFFECT_LOAD_LIB, -1, 0, NULL); + + // get effect desc + effect_thread_command(ethread_data, EFFECT_GET_DESC, -1, 0, NULL); + + // create effect + ethread_data->io_handle = handle; + effect_thread_command(ethread_data, EFFECT_CREATE, -1, 0, NULL); + + // enable effect + effect_thread_command(ethread_data, EFFECT_CMD, QAHW_EFFECT_CMD_ENABLE, 0, NULL); + } + play_file(out_handle, file_stream, (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)); + if (ethread_data) { + // disable effect + effect_thread_command(ethread_data, EFFECT_CMD, QAHW_EFFECT_CMD_DISABLE, 0, NULL); + + // release effect + effect_thread_command(ethread_data, EFFECT_RELEASE, -1, 0, NULL); + + // unload effect module + effect_thread_command(ethread_data, EFFECT_UNLOAD_LIB, -1, 0, NULL); + + // destroy effect thread + destroy_effect_thread(ethread_data); + + free(ethread_data); + ethread_data = NULL; + } + if (proxy_thread_active) { - /* - * DSP gives drain ack for last buffer which will close proxy thread before - * app reads last buffer. So add sleep before exiting proxy thread to read - * last buffer of data. This is not a calculated value. - */ + /* + * DSP gives drain ack for last buffer which will close proxy thread before + * app reads last buffer. So add sleep before exiting proxy thread to read + * last buffer of data. This is not a calculated value. + */ usleep(500000); proxy_params.acp.thread_exit = true; fprintf(log_file, "wait for proxy thread exit\n"); |