Add pre-processing support to dragon hal and enable multi-mic noise suppression
Change-Id: I31753f336ff293f966a6b61fd51acb1e4379950d
diff --git a/audio/hal/Android.mk b/audio/hal/Android.mk
index 808e150..4501ea5 100644
--- a/audio/hal/Android.mk
+++ b/audio/hal/Android.mk
@@ -41,7 +41,6 @@
$(call include-path-for, audio-route) \
$(call include-path-for, audio-effects)
-
LOCAL_MODULE := audio.primary.dragon
LOCAL_MODULE_RELATIVE_PATH := hw
diff --git a/audio/hal/audio_hw.c b/audio/hal/audio_hw.c
index 13bad7c..188d33e 100644
--- a/audio/hal/audio_hw.c
+++ b/audio/hal/audio_hw.c
@@ -859,8 +859,158 @@
static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames);
static int do_in_standby_l(struct stream_in *in);
+static audio_format_t in_get_format(const struct audio_stream *stream);
-#define MAX_NUM_CHANNEL_CONFIGS 10
+#ifdef PREPROCESSING_ENABLED
+static int get_command_status(int status, int fct_status, uint32_t cmd_status) {
+ if (fct_status != 0)
+ status = fct_status;
+ else if (cmd_status != 0)
+ status = cmd_status;
+ return status;
+}
+
+static uint32_t in_get_aux_channels(struct stream_in *in)
+{
+ if (in->num_preprocessors == 0)
+ return 0;
+
+ /* do not enable quad mic configurations when capturing from other
+ * microphones than main */
+ if (!(in->devices & AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN))
+ return 0;
+
+ return AUDIO_CHANNEL_INDEX_MASK_4;
+}
+
+static int in_configure_effect_channels(effect_handle_t effect,
+ channel_config_t *channel_config)
+{
+ int status = 0;
+ int fct_status;
+ int32_t cmd_status;
+ uint32_t reply_size;
+ effect_config_t config;
+ uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
+
+ ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
+ channel_config->main_channels,
+ channel_config->aux_channels);
+
+ config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
+ config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
+ reply_size = sizeof(effect_config_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_GET_CONFIG,
+ 0,
+ NULL,
+ &reply_size,
+ &config);
+ if (fct_status != 0) {
+ ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
+ return fct_status;
+ }
+
+ config.inputCfg.channels = channel_config->aux_channels;
+ config.outputCfg.channels = config.inputCfg.channels;
+ reply_size = sizeof(uint32_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_SET_CONFIG,
+ sizeof(effect_config_t),
+ &config,
+ &reply_size,
+ &cmd_status);
+ status = get_command_status(status, fct_status, cmd_status);
+ if (status != 0) {
+ ALOGE("in_configure_effect_channels(): EFFECT_CMD_SET_CONFIG failed");
+ return status;
+ }
+
+ /* some implementations need to be re-enabled after a config change */
+ reply_size = sizeof(uint32_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_ENABLE,
+ 0,
+ NULL,
+ &reply_size,
+ &cmd_status);
+ status = get_command_status(status, fct_status, cmd_status);
+ if (status != 0) {
+ ALOGE("in_configure_effect_channels(): EFFECT_CMD_ENABLE failed");
+ return status;
+ }
+
+ return status;
+}
+
+static int in_reconfigure_channels(struct stream_in *in,
+ effect_handle_t effect,
+ channel_config_t *channel_config,
+ bool config_changed) {
+
+ int status = 0;
+
+ ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
+ config_changed, effect);
+
+ /* if config changed, reconfigure all previously added effects */
+ if (config_changed) {
+ int i;
+ ALOGV("%s: config_changed (%d)", __func__, config_changed);
+ for (i = 0; i < in->num_preprocessors; i++) {
+ int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
+ channel_config);
+ ALOGV("%s: in_configure_effect_channels i=(%d), [main_channel,aux_channel]=[%d|%d], status=%d",
+ __func__, i, channel_config->main_channels, channel_config->aux_channels, cur_status);
+ if (cur_status != 0) {
+ ALOGV("in_reconfigure_channels(): error %d configuring effect "
+ "%d with channels: [%04x][%04x]",
+ cur_status,
+ i,
+ channel_config->main_channels,
+ channel_config->aux_channels);
+ status = cur_status;
+ }
+ }
+ } else if (effect != NULL && channel_config->aux_channels) {
+ /* if aux channels config did not change but aux channels are present,
+ * we still need to configure the effect being added */
+ status = in_configure_effect_channels(effect, channel_config);
+ }
+ return status;
+}
+
+static void in_update_aux_channels(struct stream_in *in,
+ effect_handle_t effect)
+{
+ uint32_t aux_channels;
+ channel_config_t channel_config;
+ int status;
+
+ aux_channels = in_get_aux_channels(in);
+
+ channel_config.main_channels = in->main_channels;
+ channel_config.aux_channels = aux_channels;
+ status = in_reconfigure_channels(in,
+ effect,
+ &channel_config,
+ (aux_channels != in->aux_channels));
+
+ if (status != 0) {
+ ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
+ /* resetting aux channels configuration */
+ aux_channels = 0;
+ channel_config.aux_channels = 0;
+ in_reconfigure_channels(in, effect, &channel_config, true);
+ }
+ ALOGV("%s: aux_channels=%d, in->aux_channels_changed=%d", __func__, aux_channels, in->aux_channels_changed);
+ if (in->aux_channels != aux_channels) {
+ in->aux_channels_changed = true;
+ in->aux_channels = aux_channels;
+ do_in_standby_l(in);
+ }
+}
+#endif
/* This function reads PCM data and:
* - resample if needed
@@ -870,10 +1020,15 @@
static ssize_t read_and_process_frames(struct audio_stream_in *stream, void* buffer, ssize_t frames_num)
{
struct stream_in *in = (struct stream_in *)stream;
- ssize_t frames_rd = 0; /* Number of frames actually read */
+ ssize_t frames_wr = 0; /* Number of frames actually read */
size_t bytes_per_sample = audio_bytes_per_sample(stream->common.get_format(&stream->common));
- void *proc_buf_in = buffer;
-
+ void *proc_buf_out = buffer;
+#ifdef PREPROCESSING_ENABLED
+ audio_buffer_t in_buf;
+ audio_buffer_t out_buf;
+ int i;
+ bool has_processing = in->num_preprocessors != 0;
+#endif
/* Additional channels might be added on top of main_channels:
* - aux_channels (by processing effects)
* - extra channels due to HW limitations
@@ -882,30 +1037,110 @@
size_t src_channels = in->config.channels;
size_t dst_channels = audio_channel_count_from_in_mask(in->main_channels);
bool channel_remapping_needed = (dst_channels != src_channels);
+ size_t src_buffer_size = frames_num * src_channels * bytes_per_sample;
- /* No processing effects attached */
- if (channel_remapping_needed) {
- size_t src_buffer_size = frames_num * src_channels * bytes_per_sample;
+#ifdef PREPROCESSING_ENABLED
+ if (has_processing) {
+ /* since all the processing below is done in frames and using the config.channels
+ * as the number of channels, no changes is required in case aux_channels are present */
+ while (frames_wr < frames_num) {
+ /* first reload enough frames at the end of process input buffer */
+ if (in->proc_buf_frames < (size_t)frames_num) {
+ ssize_t frames_rd;
+ if (in->proc_buf_size < (size_t)frames_num) {
+ in->proc_buf_size = (size_t)frames_num;
+ in->proc_buf_in = realloc(in->proc_buf_in, src_buffer_size);
+ ALOG_ASSERT((in->proc_buf_in != NULL),
+ "process_frames() failed to reallocate proc_buf_in");
+ if (channel_remapping_needed) {
+ in->proc_buf_out = realloc(in->proc_buf_out, src_buffer_size);
+ ALOG_ASSERT((in->proc_buf_out != NULL),
+ "process_frames() failed to reallocate proc_buf_out");
+ proc_buf_out = in->proc_buf_out;
+ }
+ }
+ frames_rd = read_frames(in,
+ in->proc_buf_in +
+ in->proc_buf_frames * src_channels * bytes_per_sample,
+ frames_num - in->proc_buf_frames);
+ if (frames_rd < 0) {
+ /* Return error code */
+ frames_wr = frames_rd;
+ break;
+ }
+ in->proc_buf_frames += frames_rd;
+ }
- /* With additional channels, we cannot use original buffer */
- if (in->proc_buf_size < src_buffer_size) {
- in->proc_buf_size = src_buffer_size;
- in->proc_buf_in = realloc(in->proc_buf_in, src_buffer_size);
- ALOG_ASSERT((in->proc_buf_in != NULL),
- "process_frames() failed to reallocate proc_buf_in");
+ /* in_buf.frameCount and out_buf.frameCount indicate respectively
+ * the maximum number of frames to be consumed and produced by process() */
+ in_buf.frameCount = in->proc_buf_frames;
+ in_buf.s16 = in->proc_buf_in;
+ out_buf.frameCount = frames_num - frames_wr;
+ out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
+
+ /* FIXME: this works because of current pre processing library implementation that
+ * does the actual process only when the last enabled effect process is called.
+ * The generic solution is to have an output buffer for each effect and pass it as
+ * input to the next.
+ */
+ for (i = 0; i < in->num_preprocessors; i++) {
+ (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
+ &in_buf,
+ &out_buf);
+ }
+
+ /* process() has updated the number of frames consumed and produced in
+ * in_buf.frameCount and out_buf.frameCount respectively
+ * move remaining frames to the beginning of in->proc_buf_in */
+ in->proc_buf_frames -= in_buf.frameCount;
+
+ if (in->proc_buf_frames) {
+ memcpy(in->proc_buf_in,
+ in->proc_buf_in + in_buf.frameCount * src_channels * bytes_per_sample,
+ in->proc_buf_frames * in->config.channels * audio_bytes_per_sample(in_get_format(in)));
+ }
+
+ /* if not enough frames were passed to process(), read more and retry. */
+ if (out_buf.frameCount == 0) {
+ ALOGW("No frames produced by preproc");
+ continue;
+ }
+
+ if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames_num) {
+ frames_wr += out_buf.frameCount;
+ } else {
+ /* The effect does not comply to the API. In theory, we should never end up here! */
+ ALOGE("preprocessing produced too many frames: %d + %zd > %d !",
+ (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames_num);
+ frames_wr = frames_num;
+ }
}
- proc_buf_in = in->proc_buf_in;
}
- frames_rd = read_frames(in, proc_buf_in, frames_num);
- ALOG_ASSERT(frames_rd <= frames_num, "read more frames than requested");
+ else
+#endif //PREPROCESSING_ENABLED
+ {
+ /* No processing effects attached */
+ if (channel_remapping_needed) {
+ /* With additional channels, we cannot use original buffer */
+ if (in->proc_buf_size < src_buffer_size) {
+ in->proc_buf_size = src_buffer_size;
+ in->proc_buf_out = realloc(in->proc_buf_out, src_buffer_size);
+ ALOG_ASSERT((in->proc_buf_out != NULL),
+ "process_frames() failed to reallocate proc_buf_out");
+ }
+ proc_buf_out = in->proc_buf_out;
+ }
+ frames_wr = read_frames(in, proc_buf_out, frames_num);
+ ALOG_ASSERT(frames_wr <= frames_num, "read more frames than requested");
+ }
if (channel_remapping_needed) {
- size_t ret = adjust_channels(proc_buf_in, src_channels, buffer, dst_channels,
- bytes_per_sample, frames_rd * src_channels * bytes_per_sample);
- ALOG_ASSERT(ret == (frames_rd * dst_channels * bytes_per_sample));
+ size_t ret = adjust_channels(proc_buf_out, src_channels, buffer, dst_channels,
+ bytes_per_sample, frames_wr * src_channels * bytes_per_sample);
+ ALOG_ASSERT(ret == (frames_wr * dst_channels * bytes_per_sample));
}
- return frames_rd;
+ return frames_wr;
}
static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
@@ -1125,6 +1360,13 @@
}
in->config = pcm_profile->config;
+#ifdef PREPROCESSING_ENABLED
+ if (in->aux_channels_changed) {
+ in->config.channels = audio_channel_count_from_in_mask(in->aux_channels);
+ recreate_resampler = true;
+ }
+#endif
+
if (in->requested_rate != in->config.rate) {
recreate_resampler = true;
}
@@ -1185,6 +1427,9 @@
/* force read and proc buffer reallocation in case of frame size or
* channel count change */
+#ifdef PREPROCESSING_ENABLED
+ in->proc_buf_frames = 0;
+#endif
in->proc_buf_size = 0;
in->read_buf_size = 0;
in->read_buf_frames = 0;
@@ -1640,6 +1885,9 @@
bool do_standby = false;
struct pcm_device *pcm_device;
struct pcm_device_profile *pcm_profile;
+#ifdef PREPROCESSING_ENABLED
+ struct stream_in *in = NULL; /* if non-NULL, then force input to standby */
+#endif
ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s out->devices(%d) adev->mode(%d)",
__func__, out->usecase, use_case_table[out->usecase], kvpairs, out->devices, adev->mode);
@@ -1650,6 +1898,18 @@
pthread_mutex_lock(&adev->lock_inputs);
lock_output_stream(out);
pthread_mutex_lock(&adev->lock);
+#ifdef PREPROCESSING_ENABLED
+ if (((int)out->devices != val) && (val != 0) && (!out->standby) &&
+ (out->usecase == USECASE_AUDIO_PLAYBACK)) {
+ /* reset active input:
+ * - to attach the echo reference
+ * - because a change in output device may change mic settings */
+ if (adev->active_input && (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
+ adev->active_input->source == AUDIO_SOURCE_MIC)) {
+ in = adev->active_input;
+ }
+ }
+#endif
if (val != 0) {
out->devices = val;
@@ -1689,6 +1949,17 @@
}
pthread_mutex_unlock(&adev->lock);
pthread_mutex_unlock(&out->lock);
+#ifdef PREPROCESSING_ENABLED
+ if (in) {
+ /* The lock on adev->lock_inputs prevents input stream from being closed */
+ lock_input_stream(in);
+ pthread_mutex_lock(&adev->lock);
+ LOG_ALWAYS_FATAL_IF(in != adev->active_input);
+ do_in_standby_l(in);
+ pthread_mutex_unlock(&adev->lock);
+ pthread_mutex_unlock(&in->lock);
+ }
+#endif
pthread_mutex_unlock(&adev->lock_inputs);
}
@@ -1793,18 +2064,51 @@
size_t frames_wr = 0, frames_rq = 0;
unsigned char *data = NULL;
struct pcm_config config;
+#ifdef PREPROCESSING_ENABLED
+ size_t in_frames = bytes / frame_size;
+ size_t out_frames = in_frames;
+ struct stream_in *in = NULL;
+#endif
lock_output_stream(out);
if (out->standby) {
+#ifdef PREPROCESSING_ENABLED
+ pthread_mutex_unlock(&out->lock);
+ /* Prevent input stream from being closed */
+ pthread_mutex_lock(&adev->lock_inputs);
+ lock_output_stream(out);
+ if (!out->standby) {
+ pthread_mutex_unlock(&adev->lock_inputs);
+ goto false_alarm;
+ }
+#endif
pthread_mutex_lock(&adev->lock);
ret = start_output_stream(out);
if (ret != 0) {
pthread_mutex_unlock(&adev->lock);
+#ifdef PREPROCESSING_ENABLED
+ pthread_mutex_unlock(&adev->lock_inputs);
+#endif
goto exit;
}
out->standby = false;
+#ifdef PREPROCESSING_ENABLED
+ /* A change in output device may change the microphone selection */
+ if (adev->active_input &&
+ (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
+ adev->active_input->source == AUDIO_SOURCE_MIC)) {
+ in = adev->active_input;
+ ALOGV("%s: enter: force_input_standby true", __func__);
+ }
+#endif
pthread_mutex_unlock(&adev->lock);
+#ifdef PREPROCESSING_ENABLED
+ if (!in) {
+ /* Leave mutex locked iff in != NULL */
+ pthread_mutex_unlock(&adev->lock_inputs);
+ }
+#endif
}
false_alarm:
@@ -1894,6 +2198,20 @@
out_get_sample_rate(&out->stream.common));
}
+#ifdef PREPROCESSING_ENABLED
+ if (in) {
+ /* The lock on adev->lock_inputs prevents input stream from being closed */
+ lock_input_stream(in);
+ pthread_mutex_lock(&adev->lock);
+ LOG_ALWAYS_FATAL_IF(in != adev->active_input);
+ do_in_standby_l(in);
+ pthread_mutex_unlock(&adev->lock);
+ pthread_mutex_unlock(&in->lock);
+ /* This mutex was left locked iff in != NULL */
+ pthread_mutex_unlock(&adev->lock_inputs);
+ }
+#endif
+
return bytes;
}
@@ -2268,6 +2586,97 @@
return 0;
}
+static int add_remove_audio_effect(const struct audio_stream *stream,
+ effect_handle_t effect,
+ bool enable)
+{
+ struct stream_in *in = (struct stream_in *)stream;
+ struct audio_device *adev = in->dev;
+ int status = 0;
+ effect_descriptor_t desc;
+#ifdef PREPROCESSING_ENABLED
+ int i;
+#endif
+ status = (*effect)->get_descriptor(effect, &desc);
+ if (status != 0)
+ return status;
+
+ ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
+
+ pthread_mutex_lock(&adev->lock_inputs);
+ lock_input_stream(in);
+ pthread_mutex_lock(&in->dev->lock);
+#ifndef PREPROCESSING_ENABLED
+ if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
+ in->enable_aec != enable &&
+ (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
+ in->enable_aec = enable;
+ if (!in->standby)
+ select_devices(in->dev, in->usecase);
+ }
+#else
+ if (enable) {
+ if (in->num_preprocessors >= MAX_PREPROCESSORS) {
+ status = -ENOSYS;
+ goto exit;
+ }
+ in->preprocessors[in->num_preprocessors].effect_itfe = effect;
+ in->num_preprocessors ++;
+ /* check compatibility between main channel supported and possible auxiliary channels */
+ in_update_aux_channels(in, effect);//wesley crash
+ in->aux_channels_changed = true;
+ } else {
+ /* if ( enable == false ) */
+ if (in->num_preprocessors <= 0) {
+ status = -ENOSYS;
+ goto exit;
+ }
+ status = -EINVAL;
+ for (i = 0; i < in->num_preprocessors && status != 0; i++) {
+ if ( in->preprocessors[i].effect_itfe == effect ) {
+ ALOGV("add_remove_audio_effect found fx at index %d", i);
+ free(in->preprocessors[i].channel_configs);
+ in->num_preprocessors--;
+ memcpy(in->preprocessors + i,
+ in->preprocessors + i + 1,
+ (in->num_preprocessors - i) * sizeof(in->preprocessors[0]));
+ memset(in->preprocessors + in->num_preprocessors,
+ 0,
+ sizeof(in->preprocessors[0]));
+ status = 0;
+ }
+ }
+ if (status != 0)
+ goto exit;
+ in->aux_channels_changed = false;
+ ALOGV("%s: enable(%d), in->aux_channels_changed(%d)",
+ __func__, enable, in->aux_channels_changed);
+ }
+ ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
+
+exit:
+#endif
+ ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
+ pthread_mutex_unlock(&in->dev->lock);
+ pthread_mutex_unlock(&in->lock);
+ pthread_mutex_unlock(&adev->lock_inputs);
+ return status;
+}
+
+static int in_add_audio_effect(const struct audio_stream *stream,
+ effect_handle_t effect)
+{
+ ALOGV("%s: effect %p", __func__, effect);
+ return add_remove_audio_effect(stream, effect, true /* enabled */);
+}
+
+static int in_remove_audio_effect(const struct audio_stream *stream,
+ effect_handle_t effect)
+{
+ ALOGV("%s: effect %p", __func__, effect);
+ return add_remove_audio_effect(stream, effect, false /* disabled */);
+}
+
static int adev_open_output_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
@@ -2641,6 +3050,8 @@
in->stream.common.dump = in_dump;
in->stream.common.set_parameters = in_set_parameters;
in->stream.common.get_parameters = in_get_parameters;
+ in->stream.common.add_audio_effect = in_add_audio_effect;
+ in->stream.common.remove_audio_effect = in_remove_audio_effect;
in->stream.set_gain = in_set_gain;
in->stream.read = in_read;
in->stream.get_input_frames_lost = in_get_input_frames_lost;
@@ -2685,7 +3096,28 @@
pthread_mutex_lock(&adev->lock_inputs);
in_standby_l(in);
- free(in->proc_buf_in);
+ free(in->proc_buf_out);
+
+#ifdef PREPROCESSING_ENABLED
+ int i;
+
+ for (i=0; i<in->num_preprocessors; i++) {
+ free(in->preprocessors[i].channel_configs);
+ }
+
+ if (in->read_buf) {
+ free(in->read_buf);
+ }
+
+ if (in->proc_buf_in) {
+ free(in->proc_buf_in);
+ }
+
+ if (in->resampler) {
+ release_resampler(in->resampler);
+ }
+#endif
+
free(stream);
pthread_mutex_unlock(&adev->lock_inputs);
diff --git a/audio/hal/audio_hw.h b/audio/hal/audio_hw.h
index 4aa361e..0d88fb1 100644
--- a/audio/hal/audio_hw.h
+++ b/audio/hal/audio_hw.h
@@ -25,12 +25,23 @@
#include <audio_utils/resampler.h>
#include <audio_route/audio_route.h>
+#define PREPROCESSING_ENABLED
+
#define SOUND_TRIGGER_HAL_LIBRARY_PATH "/system/lib/hw/sound_trigger.primary.dragon.so"
/* Retry for delay in FW loading*/
#define RETRY_NUMBER 10
#define RETRY_US 500000
+#ifdef PREPROCESSING_ENABLED
+#define MAX_PREPROCESSORS 3
+struct effect_info_s {
+ effect_handle_t effect_itfe;
+ size_t num_channel_configs;
+ channel_config_t *channel_configs;
+};
+#endif
+
#define TTY_MODE_OFF 1
#define TTY_MODE_FULL 2
#define TTY_MODE_VCO 4
@@ -258,9 +269,20 @@
size_t read_buf_size;
size_t read_buf_frames;
- void *proc_buf_in;
+ void *proc_buf_out;
size_t proc_buf_size;
+#ifdef PREPROCESSING_ENABLED
+ void *proc_buf_in;
+ size_t proc_buf_frames;
+
+ int num_preprocessors;
+ struct effect_info_s preprocessors[MAX_PREPROCESSORS];
+
+ bool aux_channels_changed;
+ uint32_t aux_channels;
+#endif
+
struct audio_device* dev;
};
diff --git a/audio_effects.conf b/audio_effects.conf
new file mode 100644
index 0000000..5b0b948
--- /dev/null
+++ b/audio_effects.conf
@@ -0,0 +1,204 @@
+# List of effect libraries to load. Each library element must contain a "path" element
+# giving the full path of the library .so file.
+# libraries {
+# <lib name> {
+# path <lib path>
+# }
+# }
+libraries {
+# This is a proxy library that will be an abstraction for
+# the HW and SW effects
+
+ #proxy {
+ #path /system/lib/soundfx/libeffectproxy.so
+ #}
+
+# This is the SW implementation library of the effect
+ #libSW {
+ #path /system/lib/soundfx/libswwrapper.so
+ #}
+
+# This is the HW implementation library for the effect
+ #libHW {
+ #path /system/lib/soundfx/libhwwrapper.so
+ #}
+
+ bundle {
+ path /system/lib/soundfx/libbundlewrapper.so
+ }
+ reverb {
+ path /system/lib/soundfx/libreverbwrapper.so
+ }
+ visualizer {
+ path /system/lib/soundfx/libvisualizer.so
+ }
+ downmix {
+ path /system/lib/soundfx/libdownmix.so
+ }
+ loudness_enhancer {
+ path /system/lib/soundfx/libldnhncr.so
+ }
+ pre_processing {
+ path /system/lib/soundfx/libaudiopreprocessing.so
+ }
+}
+
+# Default pre-processing library. Add to audio_effect.conf "libraries" section if
+# audio HAL implements support for default software audio pre-processing effects
+#
+# pre_processing {
+# path /system/lib/soundfx/libaudiopreprocessing.so
+# }
+
+# list of effects to load. Each effect element must contain a "library" and a "uuid" element.
+# The value of the "library" element must correspond to the name of one library element in the
+# "libraries" element.
+# The name of the effect element is indicative, only the value of the "uuid" element
+# designates the effect.
+# The uuid is the implementation specific UUID as specified by the effect vendor. This is not the
+# generic effect type UUID.
+# effects {
+# <fx name> {
+# library <lib name>
+# uuid <effect uuid>
+# }
+# ...
+# }
+
+effects {
+
+# additions for the proxy implementation
+# Proxy implementation
+ #effectname {
+ #library proxy
+ #uuid xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+ # SW implemetation of the effect. Added as a node under the proxy to
+ # indicate this as a sub effect.
+ #libsw {
+ #library libSW
+ #uuid yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
+ #} End of SW effect
+
+ # HW implementation of the effect. Added as a node under the proxy to
+ # indicate this as a sub effect.
+ #libhw {
+ #library libHW
+ #uuid zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz
+ #}End of HW effect
+ #} End of effect proxy
+
+ bassboost {
+ library bundle
+ uuid 8631f300-72e2-11df-b57e-0002a5d5c51b
+ }
+ virtualizer {
+ library bundle
+ uuid 1d4033c0-8557-11df-9f2d-0002a5d5c51b
+ }
+ equalizer {
+ library bundle
+ uuid ce772f20-847d-11df-bb17-0002a5d5c51b
+ }
+ volume {
+ library bundle
+ uuid 119341a0-8469-11df-81f9-0002a5d5c51b
+ }
+ reverb_env_aux {
+ library reverb
+ uuid 4a387fc0-8ab3-11df-8bad-0002a5d5c51b
+ }
+ reverb_env_ins {
+ library reverb
+ uuid c7a511a0-a3bb-11df-860e-0002a5d5c51b
+ }
+ reverb_pre_aux {
+ library reverb
+ uuid f29a1400-a3bb-11df-8ddc-0002a5d5c51b
+ }
+ reverb_pre_ins {
+ library reverb
+ uuid 172cdf00-a3bc-11df-a72f-0002a5d5c51b
+ }
+ visualizer {
+ library visualizer
+ uuid d069d9e0-8329-11df-9168-0002a5d5c51b
+ }
+ downmix {
+ library downmix
+ uuid 93f04452-e4fe-41cc-91f9-e475b6d1d69f
+ }
+ loudness_enhancer {
+ library loudness_enhancer
+ uuid fa415329-2034-4bea-b5dc-5b381c8d1e2c
+ }
+ ns {
+ library pre_processing
+ uuid c06c8400-8e06-11e0-9cb6-0002a5d5c51b
+ }
+}
+
+# Default pre-processing effects. Add to audio_effect.conf "effects" section if
+# audio HAL implements support for them.
+#
+# agc {
+# library pre_processing
+# uuid aa8130e0-66fc-11e0-bad0-0002a5d5c51b
+# }
+# aec {
+# library pre_processing
+# uuid bb392ec0-8d4d-11e0-a896-0002a5d5c51b
+# }
+# ns {
+# library pre_processing
+# uuid c06c8400-8e06-11e0-9cb6-0002a5d5c51b
+# }
+
+# Audio preprocessor configurations.
+# The pre processor configuration consists in a list of elements each describing
+# pre processor settings for a given input source. Valid input source names are:
+# "mic", "camcorder", "voice_recognition", "voice_communication"
+# Each input source element contains a list of effects elements. The name of the effect
+# element must be the name of one of the effects in the "effects" list of the file.
+# Each effect element may optionally contain a list of parameters and their
+# default value to apply when the pre processor effect is created.
+# A parameter is defined by a "param" element and a "value" element. Each of these elements
+# consists in one or more elements specifying a type followed by a value.
+# The types defined are: "int", "short", "float", "bool" and "string"
+# When both "param" and "value" are a single int, a simple form is allowed where just
+# the param and value pair is present in the parameter description
+# pre_processing {
+# <input source name> {
+# <fx name> {
+# <param 1 name> {
+# param {
+# int|short|float|bool|string <value>
+# [ int|short|float|bool|string <value> ]
+# ...
+# }
+# value {
+# int|short|float|bool|string <value>
+# [ int|short|float|bool|string <value> ]
+# ...
+# }
+# }
+# <param 2 name > {<param> <value>}
+# ...
+# }
+# ...
+# }
+# ...
+# }
+
+#pre_processing {
+# voice_communication {
+# ns {
+# type {2 1} #NS_PARAM_TYPE=NS_TYPE_MULTI_CHANNEL
+# level {0 0} #NS_PARAM_LEVEL=NS_LEVEL_LOW
+# }
+# }
+#}
+
+#
+# TODO: add default audio pre processor configurations after debug and tuning phase
+#
diff --git a/device.mk b/device.mk
index 5373720..f3cd93d 100644
--- a/device.mk
+++ b/device.mk
@@ -111,6 +111,9 @@
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/enctune.conf:system/etc/enctune.conf
+PRODUCT_COPY_FILES += \
+ device/google/dragon/audio_effects.conf:system/etc/audio_effects.conf
+
PRODUCT_AAPT_CONFIG := normal large xlarge hdpi xhdpi xxhdpi
PRODUCT_AAPT_PREF_CONFIG := xhdpi