Fix issue 2667796: [Audio Effect Framework] Effect factory and libraries.

First effect factory and effect library API implementation.
Also added default effect libraries for reverb and equalizer effects.
These libraries are for functional test only and are not fine tuned with
regard to audio quality. They will probably be replaced by other implementations
before the release.

Change-Id: I6868f8612146ae282c64052765c61a52ec789ec8
diff --git a/include/media/AudioCommon.h b/include/media/AudioCommon.h
new file mode 100644
index 0000000..245d760
--- /dev/null
+++ b/include/media/AudioCommon.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 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_AUDIOCOMMON_H_
+#define ANDROID_AUDIOCOMMON_H_
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/////////////////////////////////////////////////
+//      Common definitions for PCM audio
+/////////////////////////////////////////////////
+
+
+// PCM Sample format
+enum audio_format_e {
+    PCM_FORMAT_S15 = 1,     // PCM signed 16 bits, must be 1 for backward compatibility
+    PCM_FORMAT_U8 = 2,      // PCM unsigned 8 bits, must be 2 for backward compatibility
+    PCM_FORMAT_S7_24        // signed 7.24 fixed point representation
+};
+
+// Channel mask definitions
+enum audio_channels_e {
+    CHANNEL_FRONT_LEFT = 0x4,                   // front left channel
+    CHANNEL_FRONT_RIGHT = 0x8,                  // front right channel
+    CHANNEL_FRONT_CENTER = 0x10,                // front center channel
+    CHANNEL_LOW_FREQUENCY = 0x20,               // low frequency channel
+    CHANNEL_BACK_LEFT = 0x40,                   // back left channel
+    CHANNEL_BACK_RIGHT = 0x80,                  // back right channel
+    CHANNEL_FRONT_LEFT_OF_CENTER = 0x100,       // front left of center channel
+    CHANNEL_FRONT_RIGHT_OF_CENTER = 0x200,      // front right of center channel
+    CHANNEL_BACK_CENTER = 0x400,                // back center channel
+    CHANNEL_MONO = CHANNEL_FRONT_LEFT,
+    CHANNEL_STEREO = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT),
+    CHANNEL_QUAD = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT),
+    CHANNEL_SURROUND = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER),
+    CHANNEL_5POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT),
+    CHANNEL_7POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT |
+            CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER),
+};
+
+// Render device definitions
+enum audio_device_e {
+    DEVICE_EARPIECE = 0x1,                      // earpiece
+    DEVICE_SPEAKER = 0x2,                       // speaker
+    DEVICE_WIRED_HEADSET = 0x4,                 // wired headset, with microphone
+    DEVICE_WIRED_HEADPHONE = 0x8,               // wired headphone, without microphone
+    DEVICE_BLUETOOTH_SCO = 0x10,                // generic bluetooth SCO
+    DEVICE_BLUETOOTH_SCO_HEADSET = 0x20,        // bluetooth SCO headset
+    DEVICE_BLUETOOTH_SCO_CARKIT = 0x40,         // bluetooth SCO car kit
+    DEVICE_BLUETOOTH_A2DP = 0x80,               // generic bluetooth A2DP
+    DEVICE_BLUETOOTH_A2DP_HEADPHONES = 0x100,   // bluetooth A2DP headphones
+    DEVICE_BLUETOOTH_A2DP_SPEAKER = 0x200,      // bluetooth A2DP speakers
+    DEVICE_AUX_DIGITAL = 0x400                  // digital output
+};
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_AUDIOCOMMON_H_*/
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index d0ccc505..9caef8f 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -20,6 +20,7 @@
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 #include <media/IAudioFlinger.h>
+#include <media/AudioCommon.h>
 
 namespace android {
 
@@ -50,8 +51,8 @@
 
     // Audio sub formats (see AudioSystem::audio_format).
     enum pcm_sub_format {
-        PCM_SUB_16_BIT          = 0x1, // must be 1 for backward compatibility
-        PCM_SUB_8_BIT           = 0x2, // must be 2 for backward compatibility
+        PCM_SUB_16_BIT          = PCM_FORMAT_S15, // must be 1 for backward compatibility
+        PCM_SUB_8_BIT           = PCM_FORMAT_U8, // must be 2 for backward compatibility
     };
 
     // MP3 sub format field definition : can use 11 LSBs in the same way as MP3 frame header to specify
@@ -103,26 +104,21 @@
     // Channel mask definitions must be kept in sync with JAVA values in /media/java/android/media/AudioFormat.java
     enum audio_channels {
         // output channels
-        CHANNEL_OUT_FRONT_LEFT = 0x4,
-        CHANNEL_OUT_FRONT_RIGHT = 0x8,
-        CHANNEL_OUT_FRONT_CENTER = 0x10,
-        CHANNEL_OUT_LOW_FREQUENCY = 0x20,
-        CHANNEL_OUT_BACK_LEFT = 0x40,
-        CHANNEL_OUT_BACK_RIGHT = 0x80,
-        CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100,
-        CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200,
-        CHANNEL_OUT_BACK_CENTER = 0x400,
-        CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT,
-        CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT),
-        CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
-                CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
-        CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
-                CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER),
-        CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
-                CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
-        CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
-                CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
-                CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
+        CHANNEL_OUT_FRONT_LEFT = CHANNEL_FRONT_LEFT,
+        CHANNEL_OUT_FRONT_RIGHT = CHANNEL_FRONT_RIGHT,
+        CHANNEL_OUT_FRONT_CENTER = CHANNEL_FRONT_CENTER,
+        CHANNEL_OUT_LOW_FREQUENCY = CHANNEL_LOW_FREQUENCY,
+        CHANNEL_OUT_BACK_LEFT = CHANNEL_BACK_LEFT,
+        CHANNEL_OUT_BACK_RIGHT = CHANNEL_BACK_RIGHT,
+        CHANNEL_OUT_FRONT_LEFT_OF_CENTER = CHANNEL_FRONT_LEFT_OF_CENTER,
+        CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = CHANNEL_FRONT_RIGHT_OF_CENTER,
+        CHANNEL_OUT_BACK_CENTER = CHANNEL_BACK_CENTER,
+        CHANNEL_OUT_MONO = CHANNEL_MONO,
+        CHANNEL_OUT_STEREO = CHANNEL_STEREO,
+        CHANNEL_OUT_QUAD = CHANNEL_QUAD,
+        CHANNEL_OUT_SURROUND = CHANNEL_SURROUND,
+        CHANNEL_OUT_5POINT1 = CHANNEL_5POINT1,
+        CHANNEL_OUT_7POINT1 = CHANNEL_7POINT1,
         CHANNEL_OUT_ALL = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
                 CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
                 CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | CHANNEL_OUT_BACK_CENTER),
@@ -240,17 +236,17 @@
 
     enum audio_devices {
         // output devices
-        DEVICE_OUT_EARPIECE = 0x1,
-        DEVICE_OUT_SPEAKER = 0x2,
-        DEVICE_OUT_WIRED_HEADSET = 0x4,
-        DEVICE_OUT_WIRED_HEADPHONE = 0x8,
-        DEVICE_OUT_BLUETOOTH_SCO = 0x10,
-        DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
-        DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
-        DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
-        DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
-        DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
-        DEVICE_OUT_AUX_DIGITAL = 0x400,
+        DEVICE_OUT_EARPIECE = DEVICE_EARPIECE,
+        DEVICE_OUT_SPEAKER = DEVICE_SPEAKER,
+        DEVICE_OUT_WIRED_HEADSET = DEVICE_WIRED_HEADSET,
+        DEVICE_OUT_WIRED_HEADPHONE = DEVICE_WIRED_HEADPHONE,
+        DEVICE_OUT_BLUETOOTH_SCO = DEVICE_BLUETOOTH_SCO,
+        DEVICE_OUT_BLUETOOTH_SCO_HEADSET = DEVICE_BLUETOOTH_SCO_HEADSET,
+        DEVICE_OUT_BLUETOOTH_SCO_CARKIT = DEVICE_BLUETOOTH_SCO_CARKIT,
+        DEVICE_OUT_BLUETOOTH_A2DP = DEVICE_BLUETOOTH_A2DP,
+        DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = DEVICE_BLUETOOTH_A2DP_HEADPHONES,
+        DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = DEVICE_BLUETOOTH_A2DP_SPEAKER,
+        DEVICE_OUT_AUX_DIGITAL = DEVICE_AUX_DIGITAL,
         DEVICE_OUT_DEFAULT = 0x8000,
         DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET |
                 DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
diff --git a/include/media/EffectApi.h b/include/media/EffectApi.h
new file mode 100644
index 0000000..a1bc3b82
--- /dev/null
+++ b/include/media/EffectApi.h
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2010 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_EFFECTAPI_H_
+#define ANDROID_EFFECTAPI_H_
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <media/AudioCommon.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/////////////////////////////////////////////////
+//      Effect control interface
+/////////////////////////////////////////////////
+
+// The effect control interface is exposed by each effect engine implementation. It consists of
+// a set of functions controlling the configuration, activation and process of the engine.
+// The functions are grouped in a structure of type effect_interface_s:
+//    struct effect_interface_s {
+//        effect_process_t process;
+//        effect_command_t command;
+//    };
+
+
+// effect_interface_t: Effect control interface handle.
+// The effect_interface_t serves two purposes regarding the implementation of the effect engine:
+// - 1 it is the address of a pointer to an effect_interface_s structure where the functions
+// of the effect control API for a particular effect are located.
+// - 2 it is the address of the context of a particular effect instance.
+// A typical implementation in the effect library would define a structure as follows:
+// struct effect_module_s {
+//        const struct effect_interface_s *itfe;
+//        effect_config_t config;
+//        effect_context_t context;
+// }
+// The implementation of EffectCreate() function would then allocate a structure of this
+// type and return its address as effect_interface_t
+typedef struct effect_interface_s **effect_interface_t;
+
+
+// Effect API version 1.0
+#define EFFECT_API_VERSION 0x0100 // Format 0xMMmm MM: Major version, mm: minor version
+
+// Maximum length of character strings in structures defines by this API.
+#define EFFECT_STRING_LEN_MAX 64
+
+//
+//--- Effect descriptor structure 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 effect_uuid_s {
+    uint32_t timeLow;
+    uint16_t timeMid;
+    uint16_t timeHiAndVersion;
+    uint16_t clockSeq;
+    uint8_t node[6];
+} effect_uuid_t;
+
+// NULL UUID definition (matches SL_IID_NULL_)
+#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } }
+static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER;
+const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_;
+const char * const 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 effect_descriptor_s {
+    effect_uuid_t type;     // UUID corresponding to the OpenSL ES interface implemented by this effect
+    effect_uuid_t uuid;     // UUID for this particular implementation
+    uint16_t apiVersion;    // Version of the effect API implemented: must match current EFFECT_API_VERSION
+    uint32_t flags;         // effect engine capabilities/requirements flags (see below)
+    char    name[EFFECT_STRING_LEN_MAX] ;   // human readable effect name
+    char    implementor[EFFECT_STRING_LEN_MAX] ;    // human readable effect implementor name
+} effect_descriptor_t;
+
+// definitions for flags field of effect descriptor.
+//  +---------------------------+-----------+-----------------------------------
+//  | description               | bits      | values
+//  +---------------------------+-----------+-----------------------------------
+//  | connection mode           | 0..1      | 0 insert: after track process
+//  |                           |           | 1 auxiliary: connect to track auxiliary
+//  |                           |           |  output and use send level
+//  |                           |           | 2 replace: replaces track process function;
+//  |                           |           |   must implement SRC, volume and mono to stereo.
+//  |                           |           | 3 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | insertion preference      | 2..4      | 0 none
+//  |                           |           | 1 first of the chain
+//  |                           |           | 2 last of the chain
+//  |                           |           | 3 exclusive (only effect in the insert chain)
+//  |                           |           | 4..7 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | Volume management         | 5..6      | 0 none
+//  |                           |           | 1 implements volume control
+//  |                           |           | 2..3 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | Device management         | 7..8      | 0 none
+//  |                           |           | 1 requires device updates
+//  |                           |           | 2..3 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | Sample input mode         | 9..10     | 0 direct: process() function or EFFECT_CMD_CONFIGURE
+//  |                           |           |   command must specify a buffer descriptor
+//  |                           |           | 1 provider: process() function uses the
+//  |                           |           |   bufferProvider indicated by the
+//  |                           |           |   EFFECT_CMD_CONFIGURE command to request input buffers.
+//  |                           |           | 2 both: both input modes are supported
+//  |                           |           | 3 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | Sample output mode        | 11..12    | 0 direct: process() function or EFFECT_CMD_CONFIGURE
+//  |                           |           |   command must specify a buffer descriptor
+//  |                           |           | 1 provider: process() function uses the
+//  |                           |           |   bufferProvider indicated by the
+//  |                           |           |   EFFECT_CMD_CONFIGURE command to request output buffers.
+//  |                           |           | 2 both: both output modes are supported
+//  |                           |           | 3 reserved
+//  +---------------------------+-----------+-----------------------------------
+
+// insert mode
+#define EFFECT_FLAG_TYPE_MASK           0x00000003
+#define EFFECT_FLAG_TYPE_INSERT         0x00000000
+#define EFFECT_FLAG_TYPE_AUXILIARY      0x00000001
+#define EFFECT_FLAG_TYPE_REPLACE        0x00000002
+
+// insert preference
+#define EFFECT_FLAG_INSERT_MASK         0x0000001C
+#define EFFECT_FLAG_INSERT_ANY          0x00000000
+#define EFFECT_FLAG_INSERT_FIRST        0x00000004
+#define EFFECT_FLAG_INSERT_LAST         0x00000008
+#define EFFECT_FLAG_INSERT_EXCLUSIVE    0x0000000C
+
+
+// volume control
+#define EFFECT_FLAG_VOLUME_MASK         0x00000060
+#define EFFECT_FLAG_VOLUME_CTRL         0x00000020
+#define EFFECT_FLAG_VOLUME_NONE         0x00000000
+
+// device control
+#define EFFECT_FLAG_DEVICE_MASK         0x00000180
+#define EFFECT_FLAG_DEVICE_IND          0x00000080
+#define EFFECT_FLAG_DEVICE_NONE         0x00000000
+
+// sample input modes
+#define EFFECT_FLAG_INPUT_MASK          0x00000600
+#define EFFECT_FLAG_INPUT_DIRECT        0x00000000
+#define EFFECT_FLAG_INPUT_PROVIDER      0x00000200
+#define EFFECT_FLAG_INPUT_BOTH          0x00000400
+
+// sample output modes
+#define EFFECT_FLAG_OUTPUT_MASK          0x00001800
+#define EFFECT_FLAG_OUTPUT_DIRECT        0x00000000
+#define EFFECT_FLAG_OUTPUT_PROVIDER      0x00000800
+#define EFFECT_FLAG_OUTPUT_BOTH          0x00001000
+
+// forward definition of type audio_buffer_t
+typedef struct audio_buffer_s audio_buffer_t;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       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 EFFECT_CMD_CONFIGURE command.
+//
+//    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:
+//          effect_interface_t: handle to the effect interface this function
+//              is called on.
+//          inBuffer:   buffer descriptor indicating where to read samples to process.
+//              If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command.
+//
+//          inBuffer:   buffer descriptor indicating where to write processed samples.
+//              If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command.
+//
+//    Output:
+//        returned value:    0 successful operation
+//                          -EINVAL invalid interface handle or
+//                                  invalid input/output buffer description
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_process_t)(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       command
+//
+//    Description:    Send a command and receive a response to/from effect engine.
+//
+//    Input:
+//          effect_interface_t: handle to the effect interface this function
+//              is called on.
+//          cmdCode:    command code: the command can be a standardized command defined in
+//              effect_command_e (see below) or a proprietary command.
+//          cmdSize:    size of command in bytes
+//          pCmdData:   pointer to command data
+//          pReplyData: pointer to reply data
+//
+//    Input/Output:
+//          replySize: 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 the this
+//              API specification. Status related to the execution of a particular command should be
+//              indicated as part of the reply field.
+//
+//          *pReplyData updated with command response
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_command_t)(effect_interface_t self, int32_t cmdCode, int32_t cmdSize, void *pCmdData, int32_t *replySize, void *pReplyData);
+
+
+// Effect control interface definition
+struct effect_interface_s {
+    effect_process_t process;
+    effect_command_t command;
+};
+
+
+//--- Standardized command codes for command function
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | description                    | command code                  | command format                | reply format
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Initialize effect engine:      | EFFECT_CMD_INIT               | size: 0                       | size: sizeof(int)
+//  |  All configurations return to  |                               | data: N/A                     | data: status
+//  |  default                       |                               |                               |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Apply new audio parameters     | EFFECT_CMD_CONFIGURE          | size: sizeof(effect_config_t) | size: sizeof(int)
+//  | configurations for input and   |                               | data: effect_config_t         | data: status
+//  | output buffers                 |                               |                               |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Reset effect engine: keep      | EFFECT_CMD_RESET              | size: 0                       | size: 0
+//  | configuration but reset state  |                               | data: N/A                     | data: N/A
+//  | and buffer content.            |                               |                               |
+//  | Called by the framework before |                               |                               |
+//  | enabling the effect            |                               |                               |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Enable the process             | EFFECT_CMD_ENABLE             | size: 0                       | size: sizeof(int)
+//  | Called by the framework before |                               | data: N/A                     | data: status
+//  | the first call to process()    |                               |                               |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Disable the process            | EFFECT_CMD_DISABLE            | size: 0                       | size: sizeof(int)
+//  | Called by the framework after  |                               | data: N/A                     | data: status
+//  | the last call to process()     |                               |                               |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Set a parameter and apply it   | EFFECT_CMD_SET_PARAM          | size: sizeof(effect_param_t)  | size: sizeof(int)
+//  | immediately                    |                               |       + size of param + value | data: status
+//  |                                |                               | data: effect_param_t          |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Set a parameter but apply it   | EFFECT_CMD_SET_PARAM_DEFERRED | size: sizeof(effect_param_t)  | size: 0
+//  | only when receiving command    |                               |       + size of param + value | data: N/A
+//  | EFFECT_CMD_SET_PARAM_COMMIT    |                               | data: effect_param_t          |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Apply all previously received  | EFFECT_CMD_SET_PARAM_COMMIT   | size: 0                       | size: sizeof(int)
+//  | EFFECT_CMD_SET_PARAM_DEFERRED  |                               | data: N/A                     | data: status
+//  | commands                       |                               |                               |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Get a parameter value          | EFFECT_CMD_GET_PARAM          | size: sizeof(effect_param_t)  | size: sizeof(effect_param_t)
+//  |                                |                               |       + size of param         |       + size of param + value
+//  |                                |                               | data: effect_param_t          | data: effect_param_t
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Set the rendering device the   | EFFECT_CMD_SET_DEVICE         | size: sizeof(uint32_t)        | size: 0
+//  | audio output path is connected |                               | data: audio_device_e          | data: N/A
+//  | to. See audio_device_e in      |                               |                               |
+//  | AudioCommon.h for device values|                               |                               |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | Set and get volume. Used by    | EFFECT_CMD_SET_VOLUME         | size: n * sizeof(uint32_t)    | size: n * sizeof(uint32_t)
+//  | audio framework to delegate    |                               | data: volume for each channel | data: volume for each channel
+//  | volume control to effect engine|                               | defined in effect_config_t in | defined in effect_config_t in
+//  | The engine must return the     |                               | 8.24 fixed point format       | 8.24 fixed point format
+//  | volume that should be applied  |                               |                               |
+//  | before the effect is processed |                               |                               |
+//  | The overall volume (the volume |                               |                               |
+//  | actually applied by the effect |                               |                               |
+//  | multiplied by the returned     |                               |                               |
+//  | value) should match the        |                               |                               |
+//  | requested value                |                               |                               |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+//  | All proprietary effect commands| EFFECT_CMD_FIRST_PROPRIETARY  |                               |
+//  | must use command codes above   |                               |                               |
+//  | this value. The size and format|                               |                               |
+//  | of command and response fields |                               |                               |
+//  | is free in this case.          |                               |                               |
+//  +--------------------------------+-------------------------------+-------------------------------+--------------------------
+
+
+enum effect_command_e {
+   EFFECT_CMD_INIT,                 // initialize effect engine
+   EFFECT_CMD_CONFIGURE,            // configure effect engine (see effect_config_t)
+   EFFECT_CMD_RESET,                // reset effect engine
+   EFFECT_CMD_ENABLE,               // enable effect process
+   EFFECT_CMD_DISABLE,              // disable effect process
+   EFFECT_CMD_SET_PARAM,            // set parameter immediately (see effect_param_t)
+   EFFECT_CMD_SET_PARAM_DEFERRED,   // set parameter deferred
+   EFFECT_CMD_SET_PARAM_COMMIT,     // commit previous set parameter deferred
+   EFFECT_CMD_GET_PARAM,            // get parameter
+   EFFECT_CMD_SET_DEVICE,           // set audio device (see audio_device_e in AudioCommon.h)
+   EFFECT_CMD_SET_VOLUME,           // set volume
+   EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
+};
+
+// 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_channels_e (AudioCommon.h) 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
+struct 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 inBuffer or outBuffer passed as argument is NULL
+// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_CONFIGURE
+// command did not specify an audio buffer.
+
+typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer);
+
+typedef struct buffer_provider_s {
+    buffer_function_t getBuffer;       // retrieve next buffer
+    buffer_function_t releaseBuffer;   // release used buffer
+    void       *cookie;                // for use by client of buffer provider functions
+} buffer_provider_t;
+
+// The 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 EFFECT_CMD_CONFIGURE command.
+typedef struct buffer_config_s {
+    audio_buffer_t  buffer;     // buffer for use by process() function is not passed explicitly
+    uint32_t   samplingRate;    // sampling rate
+    uint32_t   channels;        // channel mask (see audio_channels_e in AudioCommon.h)
+    buffer_provider_t bufferProvider;   // buffer provider
+    uint8_t    format;          // PCM format  (see audio_format_e in AudioCommon.h)
+    uint8_t    accessMode;      // read/write or accumulate in buffer (effect_buffer_access_e)
+    uint16_t   mask;            // indicates which of the above fields is valid
+} buffer_config_t;
+
+// values for "accessMode" field of buffer_config_t:
+//   overwrite, read only, accumulate (read/modify/write)
+enum effect_buffer_access_e {
+    EFFECT_BUFFER_ACCESS_WRITE,
+    EFFECT_BUFFER_ACCESS_READ,
+    EFFECT_BUFFER_ACCESS_ACCUMULATE
+
+};
+
+// 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 EFFECT_CMD_CONFIGURE command
+#define EFFECT_CONFIG_BUFFER    0x0001  // buffer field must be taken into account
+#define EFFECT_CONFIG_SMP_RATE  0x0002  // samplingRate field must be taken into account
+#define EFFECT_CONFIG_CHANNELS  0x0004  // channels field must be taken into account
+#define EFFECT_CONFIG_FORMAT    0x0008  // format field must be taken into account
+#define EFFECT_CONFIG_ACC_MODE  0x0010  // accessMode field must be taken into account
+#define EFFECT_CONFIG_PROVIDER  0x0020  // bufferProvider field must be taken into account
+#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | EFFECT_CONFIG_SMP_RATE | \
+                           EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT | \
+                           EFFECT_CONFIG_ACC_MODE | EFFECT_CONFIG_PROVIDER)
+
+// effect_config_s structure describes the format of the pCmdData argument of EFFECT_CMD_CONFIGURE command
+// to configure audio parameters and buffers for effect engine input and output.
+typedef struct effect_config_s {
+    buffer_config_t   inputCfg;
+    buffer_config_t   outputCfg;;
+} effect_config_t;
+
+// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM
+// command and pCmdData and pReplyData of 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 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
+} effect_param_t;
+
+
+/////////////////////////////////////////////////
+//      Effect library interface
+/////////////////////////////////////////////////
+
+// An effect library is required to implement and expose the following functions
+// to enable effect enumeration and instantiation. The name of these functions must be as
+// specified here as the effect framework will get the function address with dlsym():
+//
+// - effect_QueryNumberEffects_t EffectQueryNumberEffects;
+// - effect_QueryNextEffect_t EffectQueryNext;
+// - effect_CreateEffect_t EffectCreate;
+// - effect_ReleaseEffect_t EffectRelease;
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectQueryNumberEffects
+//
+//    Description:    Returns the number of different effect exposed by the
+//          library. Each effect must have a unique effect uuid (see
+//          effect_descriptor_t). This function together with EffectQueryNext()
+//          is used to enumerate all effects present in the library.
+//          Each time EffectQueryNumberEffects() is called, the library must
+//          reset the index of the effect descriptor returned by next call to
+//          EffectQueryNext() to restart enumeration from the beginning.
+//
+//    Input/Output:
+//          pNumEffects:    address where the number of effects should be returned.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     library failed to initialize
+//                          -EINVAL     invalid pNumEffects
+//        *pNumEffects:     updated with number of effects in library
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_QueryNumberEffects_t)(int32_t *pNumEffects);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectQueryNext
+//
+//    Description:    Returns a descriptor of the next available effect.
+//          See effect_descriptor_t for details on effect descriptors.
+//          This function together with EffectQueryNext() is used to enumerate all
+//          effects present in the library. The enumeration sequence is:
+//              EffectQueryNumberEffects(&num_effects);
+//              while (num_effects--)
+//                  EffectQueryNext();
+//
+//    Input/Output:
+//          pDescriptor:    address where to return the effect descriptor.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     library failed to initialize
+//                          -EINVAL     invalid pDescriptor
+//                          -ENOENT     no more effect available
+//        *pDescriptor:     updated with the effect descriptor.
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_QueryNextEffect_t)(effect_descriptor_t *pDescriptor);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectCreate
+//
+//    Description:    Creates an effect engine of the specified type 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:
+//          pEffectUuid:    pointer to the effect uuid.
+//
+//    Input/Output:
+//          pInterface:    address where to return the effect interface.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     library failed to initialize
+//                          -EINVAL     invalid pEffectUuid or pInterface
+//                          -ENOENT     No effect with this uuid found
+//        *pInterface:     updated with the effect interface handle.
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_CreateEffect_t)(effect_uuid_t *uuid, effect_interface_t *pInterface);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectRelease
+//
+//    Description:    Releases the effect engine whose handle is given as argument.
+//          All resources allocated to this particular instance of the effect are
+//          released.
+//
+//    Input:
+//          interface:    handle on the effect interface to be released.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     library failed to initialize
+//                          -EINVAL     invalid interface handle
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_ReleaseEffect_t)(effect_interface_t interface);
+
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTAPI_H_*/
diff --git a/include/media/EffectEqualizerApi.h b/include/media/EffectEqualizerApi.h
new file mode 100644
index 0000000..e3069d5
--- /dev/null
+++ b/include/media/EffectEqualizerApi.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 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_EFFECTEQUALIZERAPI_H_
+#define ANDROID_EFFECTEQUALIZERAPI_H_
+
+#include <media/EffectApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+//TODO replace by openSL ES include when available
+static const effect_uuid_t SL_IID_EQUALIZER_ = { 0x0bed4300, 0xddd6, 0x11db, 0x8f34, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_EQUALIZER = &SL_IID_EQUALIZER_;
+
+/* 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.
+} t_equalizer_params;
+
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTEQUALIZERAPI_H_*/
diff --git a/include/media/EffectFactoryApi.h b/include/media/EffectFactoryApi.h
new file mode 100644
index 0000000..8179c234
--- /dev/null
+++ b/include/media/EffectFactoryApi.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2010 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_EFFECTFACTORYAPI_H_
+#define ANDROID_EFFECTFACTORYAPI_H_
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <media/EffectApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/////////////////////////////////////////////////
+//      Effect factory interface
+/////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectQueryNumberEffects
+//
+//    Description:    Returns the number of different effect in all loaded libraries.
+//          Each effect must have a different effect uuid (see
+//          effect_descriptor_t). This function together with EffectQueryNext()
+//          is used to enumerate all effects present in all loaded libraries.
+//          Each time EffectQueryNumberEffects() is called, the factory must
+//          reset the index of the effect descriptor returned by next call to
+//          EffectQueryNext() to restart enumeration from the beginning.
+//
+//    Input/Output:
+//          pNumEffects:    address where the number of effects should be returned.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid pNumEffects
+//        *pNumEffects:     updated with number of effects in factory
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectQueryNumberEffects(int *pNumEffects);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectQueryNext
+//
+//    Description:    Returns a descriptor of the next available effect.
+//          See effect_descriptor_t for a details on effect descriptor.
+//          This function together with EffectQueryNext() is used to enumerate all
+//          effects present in all loaded libraries. The enumeration sequence is:
+//              EffectQueryNumberEffects(&num_effects);
+//              while (num_effects--)
+//                  EffectQueryNext();
+//
+//    Input/Output:
+//          pDescriptor:    address where to return the effect descriptor.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid pDescriptor
+//                          -ENOENT     no more effect available
+//        *pDescriptor:     updated with the effect descriptor.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectQueryNext(effect_descriptor_t *pDescriptor);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectCreate
+//
+//    Description:    Creates an effect engine of the specified type 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 handler on the effect control interface.
+//
+//    Input:
+//          pEffectUuid:    pointer to the effect uuid.
+//
+//    Input/Output:
+//          pInterface:    address where to return the effect interface.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid pEffectUuid or pInterface
+//                          -ENOENT     No effect with this uuid found
+//        *pInterface:     updated with the effect interface.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectCreate(effect_uuid_t *pEffectUuid, effect_interface_t *pInterface);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectRelease
+//
+//    Description:    Releases the effect engine whose handler is given as argument.
+//          All resources allocated to this particular instance of the effect are
+//          released.
+//
+//    Input:
+//          interface:    handler on the effect interface to be released.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid interface handler
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectRelease(effect_interface_t interface);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectLoadLibrary
+//
+//    Description:    Loads the effect library which path is given as first argument.
+//          This must be the full path of a dynamic library (.so) implementing one or
+//          more effect engines and exposing the effect library interface described in
+//          EffectApi.h. The function returns a handle on the library for used by
+//          further call to EffectUnloadLibrary() to unload the library.
+//
+//    Input:
+//          libPath:    full path of the dynamic library file in the file system.
+//
+//          handle:     address where to return the library handle
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     Effect factory not initialized or
+//                                      library could not be loaded or
+//                                      library does not implement required functions
+//                          -EINVAL     invalid libPath string or handle
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectLoadLibrary(const char *libPath, int *handle);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectUnloadLibrary
+//
+//    Description:  Unloads the effect library which handle is given as argument.
+//
+//    Input:
+//          handle: library handle
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     Effect factory not initialized
+//                          -ENOENT     invalid handle
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectUnloadLibrary(int handle);
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectGetDescriptor
+//
+//    Description:    Returns the descriptor of the effect which uuid is pointed
+//          to by first argument.
+//
+//    Input:
+//          pEffectUuid:    pointer to the effect uuid.
+//
+//    Input/Output:
+//          pDescriptor:    address where to return the effect descriptor.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid pEffectUuid or pDescriptor
+//                          -ENOENT     No effect with this uuid found
+//        *pDescriptor:     updated with the effect descriptor.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectGetDescriptor(effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptor);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectIsNullUuid
+//
+//    Description:    Helper function to compare effect uuid to EFFECT_UUID_NULL
+//
+//    Input:
+//          pEffectUuid: pointer to effect uuid to compare to EFFECT_UUID_NULL.
+//
+//    Output:
+//        returned value:    0 if uuid is different from EFFECT_UUID_NULL.
+//                           1 if uuid is equal to EFFECT_UUID_NULL.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectIsNullUuid(effect_uuid_t *pEffectUuid);
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTFACTORYAPI_H_*/
diff --git a/include/media/EffectReverbApi.h b/include/media/EffectReverbApi.h
new file mode 100644
index 0000000..6371adb
--- /dev/null
+++ b/include/media/EffectReverbApi.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 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_EFFECTREVERBAPI_H_
+#define ANDROID_EFFECTREVERBAPI_H_
+
+#include <media/EffectApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+// TODO: include OpenSLES_IID.h instead
+static const effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } };
+const effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_;
+
+static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_;
+
+/* enumerated parameter settings for Reverb effect */
+typedef enum
+{
+    REVERB_PARAM_BYPASS,
+    REVERB_PARAM_PRESET,
+    // 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
+} t_reverb_params;
+
+
+typedef enum
+{
+    REVERB_PRESET_LARGE_HALL,
+    REVERB_PRESET_HALL,
+    REVERB_PRESET_CHAMBER,
+    REVERB_PRESET_ROOM,
+} t_reverb_presets;
+
+//t_reverb_properties is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification.
+typedef struct s_reverb_properties {
+    int16_t roomLevel;
+    int16_t roomHFLevel;
+    int32_t decayTime;
+    int16_t decayHFRatio;
+    int16_t reflectionsLevel;
+    int32_t reflectionsDelay;
+    int32_t reverbDelay;
+    int16_t reverbLevel;
+    int16_t diffusion;
+    int16_t density;
+    int16_t padding;
+} t_reverb_properties;
+
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTREVERBAPI_H_*/
diff --git a/media/libeffects/Android.mk b/media/libeffects/Android.mk
new file mode 100644
index 0000000..ff21454
--- /dev/null
+++ b/media/libeffects/Android.mk
@@ -0,0 +1,90 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Effect factory library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	EffectsFactory.c
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_MODULE:= libeffects
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+# Default Reverb library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	EffectReverb.c.arm \
+	EffectsMath.c.arm
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libreverb
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+	$(call include-path-for, graphics corecg)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Default Equalizer library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	EffectsMath.c.arm \
+	EffectEqualizer.cpp \
+	AudioBiquadFilter.cpp.arm \
+	AudioCoefInterpolator.cpp.arm \
+	AudioPeakingFilter.cpp.arm \
+	AudioShelvingFilter.cpp.arm \
+	AudioEqualizer.cpp.arm
+
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libequalizer
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+	$(call include-path-for, graphics corecg)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/media/libeffects/AudioBiquadFilter.cpp b/media/libeffects/AudioBiquadFilter.cpp
new file mode 100644
index 0000000..72917a3
--- /dev/null
+++ b/media/libeffects/AudioBiquadFilter.cpp
@@ -0,0 +1,260 @@
+/* //device/servers/AudioFlinger/AudioBiquadFilter.cpp
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <string.h>
+#include <assert.h>
+
+#include "AudioBiquadFilter.h"
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+const audio_coef_t AudioBiquadFilter::IDENTITY_COEFS[AudioBiquadFilter::NUM_COEFS] = { AUDIO_COEF_ONE, 0, 0, 0, 0 };
+
+AudioBiquadFilter::AudioBiquadFilter(int nChannels, int sampleRate) {
+    configure(nChannels, sampleRate);
+    reset();
+}
+
+void AudioBiquadFilter::configure(int nChannels, int sampleRate) {
+    assert(nChannels > 0 && nChannels <= MAX_CHANNELS);
+    assert(sampleRate > 0);
+    mNumChannels  = nChannels;
+    mMaxDelta = static_cast<int64_t>(MAX_DELTA_PER_SEC)
+                * AUDIO_COEF_ONE
+                / sampleRate;
+    clear();
+}
+
+void AudioBiquadFilter::reset() {
+    memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs));
+    mCoefDirtyBits = 0;
+    setState(STATE_BYPASS);
+}
+
+void AudioBiquadFilter::clear() {
+    memset(mDelays, 0, sizeof(mDelays));
+}
+
+void AudioBiquadFilter::setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate) {
+    memcpy(mTargetCoefs, coefs, sizeof(mTargetCoefs));
+    if (mState & STATE_ENABLED_MASK) {
+        if (UNLIKELY(immediate)) {
+            memcpy(mCoefs, coefs, sizeof(mCoefs));
+            setState(STATE_NORMAL);
+        } else {
+            setState(STATE_TRANSITION_TO_NORMAL);
+        }
+    }
+}
+
+void AudioBiquadFilter::process(const audio_sample_t in[], audio_sample_t out[],
+                                int frameCount) {
+    (this->*mCurProcessFunc)(in, out, frameCount);
+}
+
+void AudioBiquadFilter::enable(bool immediate) {
+    if (UNLIKELY(immediate)) {
+        memcpy(mCoefs, mTargetCoefs, sizeof(mCoefs));
+        setState(STATE_NORMAL);
+    } else {
+        setState(STATE_TRANSITION_TO_NORMAL);
+    }
+}
+
+void AudioBiquadFilter::disable(bool immediate) {
+    if (UNLIKELY(immediate)) {
+        memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs));
+        setState(STATE_BYPASS);
+    } else {
+        setState(STATE_TRANSITION_TO_BYPASS);
+    }
+}
+
+void AudioBiquadFilter::setState(state_t state) {
+    switch (state) {
+    case STATE_BYPASS:
+      mCurProcessFunc = &AudioBiquadFilter::process_bypass;
+      break;
+    case STATE_TRANSITION_TO_BYPASS:
+      if (mNumChannels == 1) {
+        mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_mono;
+      } else {
+        mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_multi;
+      }
+      mCoefDirtyBits = (1 << NUM_COEFS) - 1;
+      break;
+    case STATE_TRANSITION_TO_NORMAL:
+      if (mNumChannels == 1) {
+        mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_mono;
+      } else {
+        mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_multi;
+      }
+      mCoefDirtyBits = (1 << NUM_COEFS) - 1;
+      break;
+    case STATE_NORMAL:
+      if (mNumChannels == 1) {
+        mCurProcessFunc = &AudioBiquadFilter::process_normal_mono;
+      } else {
+        mCurProcessFunc = &AudioBiquadFilter::process_normal_multi;
+      }
+      break;
+    }
+    mState = state;
+}
+
+bool AudioBiquadFilter::updateCoefs(const audio_coef_t coefs[NUM_COEFS],
+                                    int frameCount) {
+    int64_t maxDelta = mMaxDelta * frameCount;
+    for (int i = 0; i < NUM_COEFS; ++i) {
+        if (mCoefDirtyBits & (1<<i)) {
+            audio_coef_t diff = coefs[i] - mCoefs[i];
+            if (diff > maxDelta) {
+                mCoefs[i] += maxDelta;
+            } else if (diff < -maxDelta) {
+                mCoefs[i] -= maxDelta;
+            } else {
+                mCoefs[i] = coefs[i];
+                mCoefDirtyBits ^= (1<<i);
+            }
+        }
+    }
+    return mCoefDirtyBits == 0;
+}
+
+void AudioBiquadFilter::process_bypass(const audio_sample_t * in,
+                                       audio_sample_t * out,
+                                       int frameCount) {
+    // The common case is in-place processing, because this is what the EQ does.
+    if (UNLIKELY(in != out)) {
+        memcpy(out, in, frameCount * mNumChannels * sizeof(audio_sample_t));
+    }
+}
+
+void AudioBiquadFilter::process_normal_mono(const audio_sample_t * in,
+                                            audio_sample_t * out,
+                                            int frameCount) {
+    size_t nFrames = frameCount;
+    audio_sample_t x1 = mDelays[0][0];
+    audio_sample_t x2 = mDelays[0][1];
+    audio_sample_t y1 = mDelays[0][2];
+    audio_sample_t y2 = mDelays[0][3];
+    const audio_coef_t b0 = mCoefs[0];
+    const audio_coef_t b1 = mCoefs[1];
+    const audio_coef_t b2 = mCoefs[2];
+    const audio_coef_t a1 = mCoefs[3];
+    const audio_coef_t a2 = mCoefs[4];
+    while (nFrames-- > 0) {
+        audio_sample_t x0 = *(in++);
+        audio_coef_sample_acc_t acc;
+        acc = mul_coef_sample(b0, x0);
+        acc = mac_coef_sample(b1, x1, acc);
+        acc = mac_coef_sample(b2, x2, acc);
+        acc = mac_coef_sample(a1, y1, acc);
+        acc = mac_coef_sample(a2, y2, acc);
+        audio_sample_t y0 = coef_sample_acc_to_sample(acc);
+        y2 = y1;
+        y1 = y0;
+        x2 = x1;
+        x1 = x0;
+        (*out++) = y0;
+    }
+    mDelays[0][0] = x1;
+    mDelays[0][1] = x2;
+    mDelays[0][2] = y1;
+    mDelays[0][3] = y2;
+}
+
+void AudioBiquadFilter::process_transition_normal_mono(const audio_sample_t * in,
+                                                       audio_sample_t * out,
+                                                       int frameCount) {
+    if (updateCoefs(mTargetCoefs, frameCount)) {
+        setState(STATE_NORMAL);
+    }
+    process_normal_mono(in, out, frameCount);
+}
+
+void AudioBiquadFilter::process_transition_bypass_mono(const audio_sample_t * in,
+                                                       audio_sample_t * out,
+                                                       int frameCount)  {
+  if (updateCoefs(IDENTITY_COEFS, frameCount)) {
+      setState(STATE_NORMAL);
+  }
+  process_normal_mono(in, out, frameCount);
+}
+
+void AudioBiquadFilter::process_normal_multi(const audio_sample_t * in,
+                                             audio_sample_t * out,
+                                             int frameCount) {
+    const audio_coef_t b0 = mCoefs[0];
+    const audio_coef_t b1 = mCoefs[1];
+    const audio_coef_t b2 = mCoefs[2];
+    const audio_coef_t a1 = mCoefs[3];
+    const audio_coef_t a2 = mCoefs[4];
+    for (int ch = 0; ch < mNumChannels; ++ch) {
+        size_t nFrames = frameCount;
+        audio_sample_t x1 = mDelays[ch][0];
+        audio_sample_t x2 = mDelays[ch][1];
+        audio_sample_t y1 = mDelays[ch][2];
+        audio_sample_t y2 = mDelays[ch][3];
+        while (nFrames-- > 0) {
+            audio_sample_t x0 = *in;
+            audio_coef_sample_acc_t acc;
+            acc = mul_coef_sample(b0, x0);
+            acc = mac_coef_sample(b1, x1, acc);
+            acc = mac_coef_sample(b2, x2, acc);
+            acc = mac_coef_sample(a1, y1, acc);
+            acc = mac_coef_sample(a2, y2, acc);
+            audio_sample_t y0 = coef_sample_acc_to_sample(acc);
+            y2 = y1;
+            y1 = y0;
+            x2 = x1;
+            x1 = x0;
+            *out = y0;
+            in += mNumChannels;
+            out += mNumChannels;
+        }
+        mDelays[ch][0] = x1;
+        mDelays[ch][1] = x2;
+        mDelays[ch][2] = y1;
+        mDelays[ch][3] = y2;
+        in -= frameCount * mNumChannels - 1;
+        out -= frameCount * mNumChannels - 1;
+    }
+}
+
+void AudioBiquadFilter::process_transition_normal_multi(const audio_sample_t * in,
+                                                        audio_sample_t * out,
+                                                        int frameCount) {
+    if (updateCoefs(mTargetCoefs, frameCount)) {
+        setState(STATE_NORMAL);
+    }
+    process_normal_multi(in, out, frameCount);
+}
+
+void AudioBiquadFilter::process_transition_bypass_multi(const audio_sample_t * in,
+                                                        audio_sample_t * out,
+                                                        int frameCount)  {
+    if (updateCoefs(IDENTITY_COEFS, frameCount)) {
+        setState(STATE_NORMAL);
+    }
+    process_normal_multi(in, out, frameCount);
+}
+
+}
diff --git a/media/libeffects/AudioBiquadFilter.h b/media/libeffects/AudioBiquadFilter.h
new file mode 100644
index 0000000..2b0e2d6
--- /dev/null
+++ b/media/libeffects/AudioBiquadFilter.h
@@ -0,0 +1,180 @@
+/* //device/include/server/AudioFlinger/AudioBiquadFilter.h
+**
+** Copyright 2007, 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_BIQUAD_FILTER_H
+#define ANDROID_AUDIO_BIQUAD_FILTER_H
+
+#include "AudioCommon.h"
+
+namespace android {
+// A biquad filter.
+// Implements the recursion y[n]=a0*y[n-1]+a1*y[n-2]+b0*x[n]+b1*x[n-1]+b2*x[n-2]
+// (the a0 and a1 coefficients have an opposite sign to the common convention)
+// The filter works on fixed sized blocks of data (frameCount multi-channel
+// samples, as defined during construction). An arbitrary number of interlaced
+// channels is supported.
+// Filter can operate in an enabled (active) or disabled (bypassed) states.
+// A mechanism for suppression of artifacts caused by abrupt coefficient changes
+// is implemented: normally, when the enable(), disable() and setCoefs() methods
+// are called without the immediate flag set, the filter smoothly transitions
+// from its current state to the desired state.
+class AudioBiquadFilter {
+public:
+    // Max number of channels (can be changed here, and everything should work).
+    static const int MAX_CHANNELS = 2;
+    // Number of coefficients.
+    static const int NUM_COEFS = 5;
+
+    // Constructor.
+    // nChannels    Number of input/output channels.
+    // sampleRate   Sample rate, in Hz.
+    AudioBiquadFilter(int nChannels, int sampleRate);
+
+    // Reconfiguration of the filter. Implies clear().
+    // nChannels    Number of input/output channels.
+    // sampleRate   Sample rate, in Hz.
+    void configure(int nChannels, int sampleRate);
+
+    // Resets the internal state of the filter.
+    // Coefficients are reset to identity, state becomes disabled. This change
+    // happens immediately and might cause discontinuities in the output.
+    // Delay lines are not cleared.
+    void reset();
+
+    // Clears the delay lines.
+    // This change happens immediately and might cause discontinuities in the
+    // output.
+    void clear();
+
+    // Sets the coefficients.
+    // If called when filter is disabled, will have no immediate effect, but the
+    // new coefficients will be set and used next time the filter is enabled.
+    // coefs        The new coefficients.
+    // immediate    If true, transitions to new coefficients smoothly, without
+    //              introducing discontinuities in the output. Otherwise,
+    //              transitions immediately.
+    void setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate = false);
+
+    // Process a buffer of data. Always processes frameCount multi-channel
+    // samples. Processing can be done in-place, by passing the same buffer as
+    // both arguments.
+    // in           The input buffer. Should be of size frameCount * nChannels.
+    // out          The output buffer. Should be of size frameCount * nChannels.
+    // frameCount   Number of multi-channel samples to process.
+    void process(const audio_sample_t in[], audio_sample_t out[],
+                 int frameCount);
+
+    // Enables (activates) the filter.
+    // immediate    If true, transitions to new state smoothly, without
+    //              introducing discontinuities in the output. Otherwise,
+    //              transitions immediately.
+    void enable(bool immediate = false);
+
+    // Disables (bypasses) the filter.
+    // immediate    If true, transitions to new state smoothly, without
+    //              introducing discontinuities in the output. Otherwise,
+    //              transitions immediately.
+    void disable(bool immediate = false);
+
+private:
+    // A prototype of the actual processing function. Has the same semantics as
+    // the process() method.
+    typedef void (AudioBiquadFilter::*process_func)(const audio_sample_t[],
+                                                    audio_sample_t[],
+                                                    int frameCount);
+
+    // The maximum rate of coefficient change, measured in coefficient units per
+    // second.
+    static const audio_coef_t MAX_DELTA_PER_SEC = 2000;
+
+    // Coefficients of identity transformation.
+    static const audio_coef_t IDENTITY_COEFS[NUM_COEFS];
+
+    // Filter state.
+    enum state_t {
+        // Bypass.
+        STATE_BYPASS = 0x01,
+        // In the process of smooth transition to bypass state.
+        STATE_TRANSITION_TO_BYPASS = 0x02,
+        // In the process of smooth transition to normal (enabled) state.
+        STATE_TRANSITION_TO_NORMAL = 0x04,
+        // In normal (enabled) state.
+        STATE_NORMAL = 0x05,
+        // A bit-mask for determining whether the filter is enabled or disabled
+        // in the eyes of the client.
+        STATE_ENABLED_MASK = 0x04
+    };
+
+    // Number of channels.
+    int mNumChannels;
+    // Current state.
+    state_t mState;
+    // Maximum coefficient delta per sample.
+    audio_coef_t mMaxDelta;
+
+    // A bit-mask designating for which coefficients the current value is not
+    // necessarily identical to the target value (since we're in transition
+    // state).
+    uint32_t mCoefDirtyBits;
+    // The current coefficients.
+    audio_coef_t mCoefs[NUM_COEFS];
+    // The target coefficients. Will not be identical to mCoefs if we are in a
+    // transition state.
+    audio_coef_t mTargetCoefs[NUM_COEFS];
+
+    // The delay lines.
+    audio_sample_t mDelays[MAX_CHANNELS][4];
+
+    // Current processing function (determines according to current state and
+    // number of channels).
+    process_func mCurProcessFunc;
+
+    // Sets a new state. Updates the processing function accordingly, and sets
+    // the dirty bits if changing to a transition state.
+    void setState(state_t state);
+
+    // In a transition state, modifies the current coefs towards the passed
+    // coefs, while keeping a smooth change rate. Whenever a coef reaches its
+    // target value, the dirty bit is cleared. If all are clear, the function
+    // returns true, and we can then change to our target state.
+    bool updateCoefs(const audio_coef_t coefs[NUM_COEFS], int frameCount);
+
+    // Processing function when in disabled state.
+    void process_bypass(const audio_sample_t * in, audio_sample_t * out,
+                        int frameCount);
+    // Processing function when in normal state, mono.
+    void process_normal_mono(const audio_sample_t * in, audio_sample_t * out,
+                             int frameCount);
+    // Processing function when transitioning to normal state, mono.
+    void process_transition_normal_mono(const audio_sample_t * in,
+                                        audio_sample_t * out, int frameCount);
+    // Processing function when transitioning to bypass state, mono.
+    void process_transition_bypass_mono(const audio_sample_t * in,
+                                        audio_sample_t * out, int frameCount);
+    // Processing function when in normal state, multi-channel.
+    void process_normal_multi(const audio_sample_t * in, audio_sample_t * out,
+                              int frameCount);
+    // Processing function when transitioning to normal state, multi-channel.
+    void process_transition_normal_multi(const audio_sample_t * in,
+                                         audio_sample_t * out, int frameCount);
+    // Processing function when transitioning to bypass state, multi-channel.
+    void process_transition_bypass_multi(const audio_sample_t * in,
+                                         audio_sample_t * out, int frameCount);
+};
+}
+
+#endif // ANDROID_AUDIO_BIQUAD_FILTER_H
diff --git a/media/libeffects/AudioCoefInterpolator.cpp b/media/libeffects/AudioCoefInterpolator.cpp
new file mode 100644
index 0000000..05898c9
--- /dev/null
+++ b/media/libeffects/AudioCoefInterpolator.cpp
@@ -0,0 +1,84 @@
+/* //device/servers/AudioFlinger/AudioCoefInterpolator.cpp
+ **
+ ** Copyright 2008, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <string.h>
+#include "AudioCoefInterpolator.h"
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+AudioCoefInterpolator::AudioCoefInterpolator(size_t nInDims,
+                                             const size_t inDims[],
+                                             size_t nOutDims,
+                                             const audio_coef_t * table) {
+    mNumInDims = nInDims;
+    memcpy(mInDims, inDims, nInDims * sizeof(size_t));
+    mNumOutDims = nOutDims;
+    mTable = table;
+    // Initialize offsets array
+    size_t dim = nInDims - 1;
+    mInDimOffsets[nInDims - 1] = nOutDims;
+    while (dim-- > 0) {
+        mInDimOffsets[dim] = mInDimOffsets[dim + 1] * mInDims[dim + 1];
+    }
+}
+
+void AudioCoefInterpolator::getCoef(const int intCoord[], uint32_t fracCoord[],
+                                    audio_coef_t out[]) {
+    size_t index = 0;
+    size_t dim = mNumInDims;
+    while (dim-- > 0) {
+        if (UNLIKELY(intCoord[dim] < 0)) {
+            fracCoord[dim] = 0;
+        } else if (UNLIKELY(intCoord[dim] >= mInDims[dim] - 1)) {
+            fracCoord[dim] = 0;
+            index += mInDimOffsets[dim] * (mInDims[dim] - 1);
+        } else {
+            index += mInDimOffsets[dim] * intCoord[dim];
+        }
+    }
+    getCoefRecurse(index, fracCoord, out, 0);
+}
+
+void AudioCoefInterpolator::getCoefRecurse(size_t index,
+                                           const uint32_t fracCoord[],
+                                           audio_coef_t out[], size_t dim) {
+    if (dim == mNumInDims) {
+        memcpy(out, mTable + index, mNumOutDims * sizeof(audio_coef_t));
+    } else {
+        getCoefRecurse(index, fracCoord, out, dim + 1);
+        if (LIKELY(fracCoord != 0)) {
+           audio_coef_t tempCoef[MAX_OUT_DIMS];
+           getCoefRecurse(index + mInDimOffsets[dim], fracCoord, tempCoef,
+                           dim + 1);
+            size_t d = mNumOutDims;
+            while (d-- > 0) {
+                out[d] = interp(out[d], tempCoef[d], fracCoord[dim]);
+            }
+        }
+    }
+}
+
+audio_coef_t AudioCoefInterpolator::interp(audio_coef_t lo, audio_coef_t hi,
+                                           uint32_t frac) {
+    int64_t delta = static_cast<int64_t>(hi-lo) * frac;
+    return lo + static_cast<audio_coef_t> (delta >> 32);
+}
+
+}
diff --git a/media/libeffects/AudioCoefInterpolator.h b/media/libeffects/AudioCoefInterpolator.h
new file mode 100644
index 0000000..13e5697
--- /dev/null
+++ b/media/libeffects/AudioCoefInterpolator.h
@@ -0,0 +1,98 @@
+/* //device/include/server/AudioFlinger/AudioCoefInterpolator.h
+ **
+ ** Copyright 2007, 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_COEF_INTERPOLATOR_H
+#define ANDROID_AUDIO_COEF_INTERPOLATOR_H
+
+#include "AudioCommon.h"
+
+namespace android {
+
+// A helper class for linear interpolation of N-D -> M-D coefficient tables.
+// This class provides support for out-of-range indexes.
+// Details:
+// The purpose is efficient approximation of a N-dimensional vector to
+// M-dimensional function. The approximation is based on a table of output
+// values on a uniform grid of the input values. Values not on the grid are
+// linearly interpolated.
+// Access to values are done by specifying input values in table index units,
+// having an integer and a fractional part, e.g. retrieving a value from index
+// 1.4 will result in linear interpolation between index 1 and index 2.
+class AudioCoefInterpolator {
+public:
+    // Constructor.
+    // nInDims      Number of input dimensions (limited to MAX_IN_DIMS).
+    // inDims       An array of size nInDims with the size of the table on each
+    //              respective dimension.
+    // nOutDims     Number of output dimensions (limited to MAX_OUT_DIMS).
+    // table        The coefficient table. Should be of size:
+    //              inDims[0]*inDims[1]*...*inDims[nInDims-1]*nOutDims, where
+    //              func([i,j,k]) = table(i,j,k,:)
+    AudioCoefInterpolator(size_t nInDims, const size_t inDims[],
+                          size_t nOutDims, const audio_coef_t * table);
+
+    // Get the value of the approximated function at a given point.
+    // intCoord     The integer part of the input value. Should be an array of
+    //              size nInDims.
+    // fracCoord    The fractional part of the input value. Should be an array
+    //              of size nInDims. This value is in 32-bit precision.
+    // out          An array for the output value. Should be of size nOutDims.
+    void getCoef(const int intCoord[], uint32_t fracCoord[], audio_coef_t out[]);
+
+private:
+    // Maximum allowed number of input dimensions.
+    static const size_t MAX_IN_DIMS = 8;
+    // Maximum allowed number of output dimensions.
+    static const size_t MAX_OUT_DIMS = 8;
+
+    // Number of input dimensions.
+    size_t mNumInDims;
+    // Number of input dimensions.
+    size_t mInDims[MAX_IN_DIMS];
+    // The offset between two consecutive indexes of each dimension. This is in
+    // fact a cumulative product of mInDims (done in reverse).
+    size_t mInDimOffsets[MAX_IN_DIMS];
+    // Number of output dimensions.
+    size_t mNumOutDims;
+    // The coefficient table.
+    const audio_coef_t * mTable;
+
+    // A recursive function for getting an interpolated coefficient value.
+    // The recursion depth is the number of input dimensions.
+    // At each step, we fetch two interpolated values of the current dimension,
+    // by two recursive calls to this method for the next dimensions. We then
+    // linearly interpolate these values over the current dimension.
+    // index      The linear integer index of the value we need to interpolate.
+    // fracCoord  A vector of fractional coordinates for each of the input
+    //            dimensions.
+    // out        Where the output should be written. Needs to be of size
+    //            mNumOutDims.
+    // dim        The input dimensions we are currently interpolating. This
+    //            value will be increased on recursive calls.
+    void getCoefRecurse(size_t index, const uint32_t fracCoord[],
+                        audio_coef_t out[], size_t dim);
+
+    // Scalar interpolation of two data points.
+    // lo       The first data point.
+    // hi       The second data point.
+    // frac     A 32-bit fraction designating the weight of the second point.
+    static audio_coef_t interp(audio_coef_t lo, audio_coef_t hi, uint32_t frac);
+};
+
+}
+
+#endif // ANDROID_AUDIO_COEF_INTERPOLATOR_H
diff --git a/media/libeffects/AudioCommon.h b/media/libeffects/AudioCommon.h
new file mode 100644
index 0000000..12d2193
--- /dev/null
+++ b/media/libeffects/AudioCommon.h
@@ -0,0 +1,92 @@
+/* //device/include/server/AudioFlinger/AudioCommon.h
+**
+** Copyright 2009, 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_COMMON_H
+#define ANDROID_AUDIO_COMMON_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+namespace android {
+
+// Audio coefficient type.
+typedef int32_t audio_coef_t;
+// Audio sample type.
+typedef int32_t audio_sample_t;
+// Accumulator type for coef x sample.
+typedef int64_t audio_coef_sample_acc_t;
+
+// Number of fraction bits for audio coefficient.
+static const int AUDIO_COEF_PRECISION = 24;
+// Audio coefficient with the value of 1.0
+static const audio_coef_t AUDIO_COEF_ONE = 1 << AUDIO_COEF_PRECISION;
+// Audio coefficient with the value of 0.5
+static const audio_coef_t AUDIO_COEF_HALF = 1 << (AUDIO_COEF_PRECISION - 1);
+// Number of fraction bits for audio sample.
+static const int AUDIO_SAMPLE_PRECISION = 24;
+// Audio sample with the value of 1.0
+static const audio_sample_t AUDIO_SAMPLE_ONE = 1 << AUDIO_SAMPLE_PRECISION;
+
+// TODO: These are just temporary naive implementations of the necessary
+// arithmetic operations needed for the filter. They should be moved to a more
+// generic location and implemented more efficiently.
+
+// Multiply a sample by a coefficient to return an accumulator.
+inline audio_coef_sample_acc_t mul_coef_sample(audio_coef_t x, audio_sample_t y) {
+    return ((audio_coef_sample_acc_t) (x)) * y;
+}
+
+// Multiply and accumulate sample by a coefficient to return an accumulator.
+inline audio_coef_sample_acc_t mac_coef_sample(audio_coef_t x, audio_sample_t y, audio_coef_sample_acc_t acc) {
+    return acc + ((audio_coef_sample_acc_t) (x)) * y;
+}
+
+// Convert a sample-coefficient accumulator to a sample.
+inline audio_sample_t coef_sample_acc_to_sample(audio_coef_sample_acc_t acc) {
+    if (acc < 0) {
+        acc += AUDIO_COEF_ONE - 1;
+    }
+    return (audio_sample_t) (acc >> AUDIO_COEF_PRECISION);
+}
+
+// Convert a S15 sample to audio_sample_t
+inline audio_sample_t s15_to_audio_sample_t(int16_t s15) {
+    return audio_sample_t(s15) << 9;
+}
+
+// Convert a audio_sample_t sample to S15 (no clipping)
+inline int16_t audio_sample_t_to_s15(audio_sample_t sample) {
+    return int16_t((sample + (1 << 8)) >> 9);
+}
+
+// Convert a audio_sample_t sample to S15 (with clipping)
+inline int16_t audio_sample_t_to_s15_clip(audio_sample_t sample) {
+    // TODO: optimize for targets supporting this as an atomic operation.
+    if (__builtin_expect(sample >= (0x7FFF << 9), 0)) {
+        return 0x7FFF;
+    } else if (__builtin_expect(sample <= -(0x8000 << 9), 0)) {
+        return 0x8000;
+    } else {
+        return audio_sample_t_to_s15(sample);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+}
+
+#endif // ANDROID_AUDIO_COMMON_H
diff --git a/media/libeffects/AudioEqualizer.cpp b/media/libeffects/AudioEqualizer.cpp
new file mode 100644
index 0000000..44c9476
--- /dev/null
+++ b/media/libeffects/AudioEqualizer.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioEqualizer"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <new>
+#include <utils/Log.h>
+
+#include "AudioEqualizer.h"
+#include "AudioPeakingFilter.h"
+#include "AudioShelvingFilter.h"
+#include "EffectsMath.h"
+
+namespace android {
+
+size_t AudioEqualizer::GetInstanceSize(int nBands) {
+    assert(nBands >= 2);
+    return sizeof(AudioEqualizer) +
+           sizeof(AudioShelvingFilter) * 2 +
+           sizeof(AudioPeakingFilter) * (nBands - 2);
+}
+
+AudioEqualizer * AudioEqualizer::CreateInstance(void * pMem, int nBands,
+                                                int nChannels, int sampleRate,
+                                                const PresetConfig * presets,
+                                                int nPresets) {
+    LOGV("AudioEqualizer::CreateInstance(pMem=%p, nBands=%d, nChannels=%d, "
+         "sampleRate=%d, nPresets=%d)",
+         pMem, nBands, nChannels, sampleRate, nPresets);
+    assert(nBands >= 2);
+    bool ownMem = false;
+    if (pMem == NULL) {
+        pMem = malloc(GetInstanceSize(nBands));
+        if (pMem == NULL) {
+            return NULL;
+        }
+        ownMem = true;
+    }
+    return new (pMem) AudioEqualizer(pMem, nBands, nChannels, sampleRate,
+                                     ownMem, presets, nPresets);
+}
+
+void AudioEqualizer::configure(int nChannels, int sampleRate) {
+    LOGV("AudioEqualizer::configure(nChannels=%d, sampleRate=%d)", nChannels,
+         sampleRate);
+    mpLowShelf->configure(nChannels, sampleRate);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].configure(nChannels, sampleRate);
+    }
+    mpHighShelf->configure(nChannels, sampleRate);
+}
+
+void AudioEqualizer::clear() {
+    LOGV("AudioEqualizer::clear()");
+    mpLowShelf->clear();
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].clear();
+    }
+    mpHighShelf->clear();
+}
+
+void AudioEqualizer::free() {
+    LOGV("AudioEqualizer::free()");
+    if (mpMem != NULL) {
+        ::free(mpMem);
+    }
+}
+
+void AudioEqualizer::reset() {
+    LOGV("AudioEqualizer::reset()");
+    const int32_t bottom = Effects_log2(kMinFreq);
+    const int32_t top = Effects_log2(mSampleRate * 500);
+    const int32_t jump = (top - bottom) / (mNumPeaking + 2);
+    int32_t centerFreq = bottom + jump/2;
+
+    mpLowShelf->reset();
+    mpLowShelf->setFrequency(Effects_exp2(centerFreq));
+    centerFreq += jump;
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].reset();
+        mpPeakingFilters[i].setFrequency(Effects_exp2(centerFreq));
+        centerFreq += jump;
+    }
+    mpHighShelf->reset();
+    mpHighShelf->setFrequency(Effects_exp2(centerFreq));
+    commit(true);
+    mCurPreset = PRESET_CUSTOM;
+}
+
+void AudioEqualizer::setGain(int band, int32_t millibel) {
+    LOGV("AudioEqualizer::setGain(band=%d, millibel=%d)", band, millibel);
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        mpLowShelf->setGain(millibel);
+    } else if (band == mNumPeaking + 1) {
+        mpHighShelf->setGain(millibel);
+    } else {
+        mpPeakingFilters[band - 1].setGain(millibel);
+    }
+    mCurPreset = PRESET_CUSTOM;
+}
+
+void AudioEqualizer::setFrequency(int band, uint32_t millihertz) {
+    LOGV("AudioEqualizer::setFrequency(band=%d, millihertz=%d)", band,
+         millihertz);
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        mpLowShelf->setFrequency(millihertz);
+    } else if (band == mNumPeaking + 1) {
+        mpHighShelf->setFrequency(millihertz);
+    } else {
+        mpPeakingFilters[band - 1].setFrequency(millihertz);
+    }
+    mCurPreset = PRESET_CUSTOM;
+}
+
+void AudioEqualizer::setBandwidth(int band, uint32_t cents) {
+    LOGV("AudioEqualizer::setBandwidth(band=%d, cents=%d)", band, cents);
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band > 0 && band < mNumPeaking + 1) {
+        mpPeakingFilters[band - 1].setBandwidth(cents);
+        mCurPreset = PRESET_CUSTOM;
+    }
+}
+
+int32_t AudioEqualizer::getGain(int band) const {
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        return mpLowShelf->getGain();
+    } else if (band == mNumPeaking + 1) {
+        return mpHighShelf->getGain();
+    } else {
+        return mpPeakingFilters[band - 1].getGain();
+    }
+}
+
+uint32_t AudioEqualizer::getFrequency(int band) const {
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        return mpLowShelf->getFrequency();
+    } else if (band == mNumPeaking + 1) {
+        return mpHighShelf->getFrequency();
+    } else {
+        return mpPeakingFilters[band - 1].getFrequency();
+    }
+}
+
+uint32_t AudioEqualizer::getBandwidth(int band) const {
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0 || band == mNumPeaking + 1) {
+        return 0;
+    } else {
+        return mpPeakingFilters[band - 1].getBandwidth();
+    }
+}
+
+void AudioEqualizer::getBandRange(int band, uint32_t & low,
+                                  uint32_t & high) const {
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        low = 0;
+        high = mpLowShelf->getFrequency();
+    } else if (band == mNumPeaking + 1) {
+        low = mpHighShelf->getFrequency();
+        high = mSampleRate * 500;
+    } else {
+        mpPeakingFilters[band - 1].getBandRange(low, high);
+    }
+}
+
+const char * AudioEqualizer::getPresetName(int preset) const {
+    assert(preset < mNumPresets && preset >= PRESET_CUSTOM);
+    if (preset == PRESET_CUSTOM) {
+        return "Custom";
+    } else {
+        return mpPresets[preset].name;
+    }
+}
+
+int AudioEqualizer::getNumPresets() const {
+    return mNumPresets;
+}
+
+int AudioEqualizer::getPreset() const {
+    return mCurPreset;
+}
+
+void AudioEqualizer::setPreset(int preset) {
+    LOGV("AudioEqualizer::setPreset(preset=%d)", preset);
+    assert(preset < mNumPresets && preset >= 0);
+    const PresetConfig &presetCfg = mpPresets[preset];
+    for (int band = 0; band < (mNumPeaking + 2); ++band) {
+        const BandConfig & bandCfg = presetCfg.bandConfigs[band];
+        setGain(band, bandCfg.gain);
+        setFrequency(band, bandCfg.freq);
+        setBandwidth(band, bandCfg.bandwidth);
+    }
+    mCurPreset = preset;
+}
+
+void AudioEqualizer::commit(bool immediate) {
+    LOGV("AudioEqualizer::commit(immediate=%d)", immediate);
+    mpLowShelf->commit(immediate);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].commit(immediate);
+    }
+    mpHighShelf->commit(immediate);
+}
+
+void AudioEqualizer::process(const audio_sample_t * pIn,
+                             audio_sample_t * pOut,
+                             int frameCount) {
+//    LOGV("AudioEqualizer::process(frameCount=%d)", frameCount);
+    mpLowShelf->process(pIn, pOut, frameCount);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].process(pIn, pOut, frameCount);
+    }
+    mpHighShelf->process(pIn, pOut, frameCount);
+}
+
+void AudioEqualizer::enable(bool immediate) {
+    LOGV("AudioEqualizer::enable(immediate=%d)", immediate);
+    mpLowShelf->enable(immediate);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].enable(immediate);
+    }
+    mpHighShelf->enable(immediate);
+}
+
+void AudioEqualizer::disable(bool immediate) {
+    LOGV("AudioEqualizer::disable(immediate=%d)", immediate);
+    mpLowShelf->disable(immediate);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].disable(immediate);
+    }
+    mpHighShelf->disable(immediate);
+}
+
+int AudioEqualizer::getMostRelevantBand(uint32_t targetFreq) const {
+    // First, find the two bands that the target frequency is between.
+    uint32_t low = mpLowShelf->getFrequency();
+    if (targetFreq <= low) {
+        return 0;
+    }
+    uint32_t high = mpHighShelf->getFrequency();
+    if (targetFreq >= high) {
+        return mNumPeaking + 1;
+    }
+    int band = mNumPeaking;
+    for (int i = 0; i < mNumPeaking; ++i) {
+        uint32_t freq = mpPeakingFilters[i].getFrequency();
+        if (freq >= targetFreq) {
+            high = freq;
+            band = i;
+            break;
+        }
+        low = freq;
+    }
+    // Now, low is right below the target and high is right above. See which one
+    // is closer on a log scale.
+    low = Effects_log2(low);
+    high = Effects_log2(high);
+    targetFreq = Effects_log2(targetFreq);
+    if (high - targetFreq < targetFreq - low) {
+        return band + 1;
+    } else {
+        return band;
+    }
+}
+
+
+AudioEqualizer::AudioEqualizer(void * pMem, int nBands, int nChannels,
+                               int sampleRate, bool ownMem,
+                               const PresetConfig * presets, int nPresets)
+                               : mSampleRate(sampleRate)
+                               , mpPresets(presets)
+                               , mNumPresets(nPresets) {
+    assert(pMem != NULL);
+    assert(nPresets == 0 || nPresets > 0 && presets != NULL);
+    mpMem = ownMem ? pMem : NULL;
+
+    pMem = (char *) pMem + sizeof(AudioEqualizer);
+    mpLowShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kLowShelf,
+                                                nChannels, sampleRate);
+    pMem = (char *) pMem + sizeof(AudioShelvingFilter);
+    mpHighShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kHighShelf,
+                                                 nChannels, sampleRate);
+    pMem = (char *) pMem + sizeof(AudioShelvingFilter);
+    mNumPeaking = nBands - 2;
+    if (mNumPeaking > 0) {
+        mpPeakingFilters = reinterpret_cast<AudioPeakingFilter *>(pMem);
+        for (int i = 0; i < mNumPeaking; ++i) {
+            new (&mpPeakingFilters[i]) AudioPeakingFilter(nChannels,
+                                                          sampleRate);
+        }
+    }
+    reset();
+}
+
+}
diff --git a/media/libeffects/AudioEqualizer.h b/media/libeffects/AudioEqualizer.h
new file mode 100644
index 0000000..4028462
--- /dev/null
+++ b/media/libeffects/AudioEqualizer.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2009, 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 AUDIOEQUALIZER_H_
+#define AUDIOEQUALIZER_H_
+
+#include "AudioCommon.h"
+
+namespace android {
+
+class AudioShelvingFilter;
+class AudioPeakingFilter;
+
+// A parametric audio equalizer. Supports an arbitrary number of bands and
+// presets.
+// The EQ is composed of a low-shelf, zero or more peaking filters and a high
+// shelf, where each band has frequency and gain controls, and the peaking
+// filters have an additional bandwidth control.
+class AudioEqualizer {
+public:
+    // Configuration of a single band.
+    struct BandConfig {
+        // Gain in millibel.
+        int32_t gain;
+        // Frequency in millihertz.
+        uint32_t freq;
+        // Bandwidth in cents (ignored on shelving filters).
+        uint32_t bandwidth;
+    };
+
+    // Preset configuration.
+    struct PresetConfig {
+        // Human-readable name.
+        const char * name;
+        // An array of size nBands where each element is a configuration for the
+        // corresponding band.
+        const BandConfig * bandConfigs;
+    };
+
+    // This value is used when requesting current preset, and EQ is not using a
+    // preset.
+    static const int PRESET_CUSTOM = -1;
+
+    // Get the required memory size for an instance of this class.
+    // nBands   Number of bands required in the instance.
+    static size_t GetInstanceSize(int nBands);
+
+    // Create an instance of this class.
+    // If succeeds, a respective call is expected to freeInstance(), regardless
+    // of who owns the context memory.
+    // pMem         A memory buffer of at least the size returned by
+    //              GetInstanceSize(), where the instance context is to be
+    //              stored. If NULL, it will be automatically allocated (using
+    //              malloc).
+    // nBands       Number of bands. Must be >= 2.
+    // nChannels    Number of input/output channels (interlaced).
+    // sampleRate   The input/output sample rate, in Hz.
+    // presets      The presets configuration. May be NULL, but in that case the
+    //              client is required not to call preset-related functions.
+    //              This array is owned by the client and is not copied. It
+    //              must be kept valid by the client as long as the instance is
+    //              alive.
+    // nPresets     Number of elements in the presets array.
+    // returns      The instance if success. NULL if pMem is NULL and allocation
+    //              failed.
+    static AudioEqualizer * CreateInstance(void * pMem, int nBands,
+                                           int nChannels,
+                                           int sampleRate,
+                                           const PresetConfig * presets,
+                                           int nPresets);
+
+    // Reconfiguration of the filter. Changes input/output format, but does not
+    // alter current parameter values. Causes reset of the delay lines.
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    void configure(int nChannels, int sampleRate);
+
+    // Resets the filter parameters to the following values:
+    // frequency: 0
+    // gain: 0
+    // bandwidth: 1200 cents.
+    // It also disables the filter. Does not clear the delay lines.
+    void reset();
+
+    // Clears delay lines. Does not alter parameter values.
+    void clear();
+
+    // Frees the object. Will free the memory if the object owned it, i.e. if
+    // a NULL pointer was passed to CreateInstance as pMem.
+    void free();
+
+    // Sets gain value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // band     The band to set the gain for.
+    // millibel Gain value in millibel (1/100 of decibel).
+    void setGain(int band, int32_t millibel);
+
+    // Gets gain of a certain band. This is always the last value set (or
+    // default value after reset).
+    // band     The band to get the gain for.
+    // returns  Gain value in millibel (1/100 of decibel).
+    int32_t getGain(int band) const;
+
+    // Sets cutoff frequency value. Actual change will only take place upon
+    // commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // band       The band to set the frequency for.
+    // millihertz Frequency value in mHz.
+    void setFrequency(int band, uint32_t millihertz);
+
+    // Gets frequency of a certain band. This is always the last value set (or
+    // default value after reset).
+    // band     The band to get the frequency for.
+    // returns  Frequency value in mHz.
+    uint32_t getFrequency(int band) const;
+
+    // Sets bandwidth value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // If called on the first or last band, this call is ignored.
+    // band  The band to set the frequency for.
+    // cents Bandwidth value in cents (1/1200 octave).
+    void setBandwidth(int band, uint32_t cents);
+
+    // Gets bandwidth of a certain band. This is always the last value set (or
+    // default value after reset). For the first and last bands, 0 is always
+    // returned.
+    // band     The band to get the bandwidth for.
+    // returns  Bandwidth value in cents (1/1200 octave).
+    uint32_t getBandwidth(int band) const;
+
+    // Gets lower and upper boundaries of a band.
+    // For the low shelf, the low bound is 0 and the high bound is the band
+    // frequency.
+    // For the high shelf, the low bound is the band frequency and the high
+    // bound is Nyquist.
+    // For the peaking filters, they are the gain[dB]/2 points.
+    void getBandRange(int band, uint32_t & low, uint32_t & high) const;
+
+    // Gets a human-readable name for a preset ID. Will return "Custom" if
+    // PRESET_CUSTOM is passed.
+    // preset       The preset ID. Must be less than number of presets.
+    const char * getPresetName(int preset) const;
+
+    // Gets the number of presets.
+    int getNumPresets() const;
+
+    // Gets the currently set preset ID.
+    // Will return PRESET_CUSTOM in case the EQ parameters have been modified
+    // manually since a preset was set.
+    int getPreset() const;
+
+    // Sets the current preset by ID.
+    // All the band parameters will be overridden.
+    // Change will not be applied until commit() is called.
+    // preset       The preset ID. Must be less than number of presets.
+    //              PRESET_CUSTOM is NOT a valid value here.
+    void setPreset(int preset);
+
+    // Applies all parameter changes done to this point in time.
+    // If the filter is disabled, the new parameters will take place when it is
+    // enabled again. Does not introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly (ignored if filter is
+    // disabled).
+   void commit(bool immediate = false);
+
+    // Process a buffer of input data. The input and output should contain
+    // frameCount * nChannels interlaced samples. Processing can be done
+    // in-place, by passing the same buffer as both arguments.
+    // pIn          Input buffer.
+    // pOut         Output buffer.
+    // frameCount   Number of frames to produce on each call to process().
+    void process(const audio_sample_t * pIn, audio_sample_t * pOut,
+                 int frameCount);
+
+    // Enables the filter, so it would start processing input. Does not
+    // introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void enable(bool immediate = false);
+
+    // Disabled (bypasses) the filter. Does not introduce artifacts, unless
+    // immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void disable(bool immediate = false);
+
+    // Returns the band with the maximum influence on a given frequency.
+    // Result is unaffected by whether EQ is enabled or not, or by whether
+    // changes have been committed or not.
+    // targetFreq   The target frequency, in millihertz.
+    int getMostRelevantBand(uint32_t targetFreq) const;
+
+private:
+    // Bottom frequency, in mHz.
+    static const int kMinFreq = 20000;
+    // Sample rate, in Hz.
+    int mSampleRate;
+    // Number of peaking filters. Total number of bands is +2.
+    int mNumPeaking;
+    // Preset configurations.
+    const PresetConfig * mpPresets;
+    // Number of elements in mpPresets;
+    int mNumPresets;
+    // Current preset.
+    int mCurPreset;
+
+    // Memory space to free when instance is deleted, or NULL if no memory is
+    // owned.
+    void * mpMem;
+    // The low-shelving filter.
+    AudioShelvingFilter * mpLowShelf;
+    // The high-shelving filter.
+    AudioShelvingFilter * mpHighShelf;
+    // An array of size mNumPeaking of peaking filters.
+    AudioPeakingFilter * mpPeakingFilters;
+
+    // Constructor. Resets the filter (see reset()). Must call init() doing
+    // anything else.
+    // pMem       Memory buffer for bands.
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    // ownMem     Whether pMem is owned by me.
+    // presets      The presets configuration. May be NULL, but in that case the
+    //              client is required not to call preset-related functions.
+    //              This array is owned by the client and is not copied. It
+    //              must be kept valid by the client as long as the instance is
+    //              alive.
+    // nPresets     Number of elements in the presets array.
+    AudioEqualizer(void * pMem, int nBands, int nChannels, int sampleRate,
+                   bool ownMem, const PresetConfig * presets, int nPresets);
+};
+
+}
+
+#endif // AUDIOEQUALIZER_H_
diff --git a/media/libeffects/AudioFormatAdapter.h b/media/libeffects/AudioFormatAdapter.h
new file mode 100644
index 0000000..8aa5e65
--- /dev/null
+++ b/media/libeffects/AudioFormatAdapter.h
@@ -0,0 +1,184 @@
+/* /android/src/frameworks/base/media/libeffects/AudioFormatAdapter.h
+**
+** Copyright 2009, 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 AUDIOFORMATADAPTER_H_
+#define AUDIOFORMATADAPTER_H_
+
+#include <media/EffectApi.h>
+
+
+#define min(x,y) (((x) < (y)) ? (x) : (y))
+
+namespace android {
+
+// An adapter for an audio processor working on audio_sample_t samples with a
+// buffer override behavior to arbitrary sample formats and buffer behaviors.
+// The adapter may work on any processing class which has a processing function
+// with the following signature:
+// void process(const audio_sample_t * pIn,
+//              audio_sample_t * pOut,
+//              int frameCount);
+// It is assumed that the underlying processor works in S7.24 format and an
+// overwrite behavior.
+//
+// Usage is simple: just work with the processor normally, but instead of
+// calling its process() function directly, work with the process() function of
+// the adapter.
+// The adapter supports re-configuration to a different format on the fly.
+//
+// T        The processor class.
+// bufSize  The maximum number of samples (single channel) to process on a
+//          single call to the underlying processor. Setting this to a small
+//          number will save a little memory, but will cost function call
+//          overhead, resulting from multiple calls to the underlying process()
+//          per a single call to this class's process().
+template<class T, size_t bufSize>
+class AudioFormatAdapter {
+public:
+    // Configure the adapter.
+    // processor    The underlying audio processor.
+    // nChannels    Number of input and output channels. The adapter does not do
+    //              channel conversion - this parameter must be in sync with the
+    //              actual processor.
+    // pcmFormat    The desired input/output sample format.
+    // behavior     The desired behavior (overwrite or accumulate).
+    void configure(T & processor, int nChannels, uint8_t pcmFormat,
+                   uint32_t behavior) {
+        mpProcessor = &processor;
+        mNumChannels = nChannels;
+        mPcmFormat = pcmFormat;
+        mBehavior = behavior;
+        mMaxSamplesPerCall = bufSize / nChannels;
+    }
+
+    // Process a block of samples.
+    // pIn          A buffer of samples with the format specified on
+    //              configure().
+    // pOut         A buffer of samples with the format specified on
+    //              configure(). May be the same as pIn.
+    // numSamples   The number of multi-channel samples to process.
+    void process(const void * pIn, void * pOut, uint32_t numSamples) {
+        while (numSamples > 0) {
+            uint32_t numSamplesIter = min(numSamples, mMaxSamplesPerCall);
+            uint32_t nSamplesChannels = numSamplesIter * mNumChannels;
+            if (mPcmFormat == PCM_FORMAT_S7_24) {
+                if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) {
+                    mpProcessor->process(
+                        reinterpret_cast<const audio_sample_t *> (pIn),
+                        reinterpret_cast<audio_sample_t *> (pOut),
+                        numSamplesIter);
+                } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+                    mpProcessor->process(
+                        reinterpret_cast<const audio_sample_t *> (pIn),
+                        mBuffer, numSamplesIter);
+                    MixOutput(pOut, numSamplesIter);
+                } else {
+                    assert(false);
+                }
+                pIn = reinterpret_cast<const audio_sample_t *> (pIn)
+                        + nSamplesChannels;
+                pOut = reinterpret_cast<audio_sample_t *> (pOut)
+                        + nSamplesChannels;
+            } else {
+                ConvertInput(pIn, nSamplesChannels);
+                mpProcessor->process(mBuffer, mBuffer, numSamplesIter);
+                ConvertOutput(pOut, nSamplesChannels);
+            }
+            numSamples -= numSamplesIter;
+        }
+    }
+
+private:
+    // The underlying processor.
+    T * mpProcessor;
+    // The number of input/output channels.
+    int mNumChannels;
+    // The desired PCM format.
+    uint8_t mPcmFormat;
+    // The desired buffer behavior.
+    uint32_t mBehavior;
+    // An intermediate buffer for processing.
+    audio_sample_t mBuffer[bufSize];
+    // The buffer size, divided by the number of channels - represents the
+    // maximum number of multi-channel samples that can be stored in the
+    // intermediate buffer.
+    size_t mMaxSamplesPerCall;
+
+    // Converts a buffer of input samples to audio_sample_t format.
+    // Output is written to the intermediate buffer.
+    // pIn          The input buffer with the format designated in configure().
+    //              When function exist will point to the next unread input
+    //              sample.
+    // numSamples   The number of single-channel samples to process.
+    void ConvertInput(const void *& pIn, uint32_t numSamples) {
+        if (mPcmFormat == PCM_FORMAT_S15) {
+            const int16_t * pIn16 = reinterpret_cast<const int16_t *>(pIn);
+            audio_sample_t * pOut = mBuffer;
+            while (numSamples-- > 0) {
+                *(pOut++) = s15_to_audio_sample_t(*(pIn16++));
+            }
+            pIn = pIn16;
+        } else {
+            assert(false);
+        }
+    }
+
+    // Converts audio_sample_t samples from the intermediate buffer to the
+    // output buffer, converting to the desired format and buffer behavior.
+    // pOut         The buffer to write the output to.
+    //              When function exist will point to the next output sample.
+    // numSamples   The number of single-channel samples to process.
+    void ConvertOutput(void *& pOut, uint32_t numSamples) {
+        if (mPcmFormat == PCM_FORMAT_S15) {
+            const audio_sample_t * pIn = mBuffer;
+            int16_t * pOut16 = reinterpret_cast<int16_t *>(pOut);
+            if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) {
+                while (numSamples-- > 0) {
+                    *(pOut16++) = audio_sample_t_to_s15_clip(*(pIn++));
+                }
+            } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+                while (numSamples-- > 0) {
+                    *(pOut16++) += audio_sample_t_to_s15_clip(*(pIn++));
+                }
+            } else {
+                assert(false);
+            }
+            pOut = pOut16;
+        } else {
+            assert(false);
+        }
+    }
+
+    // Accumulate data from the intermediate buffer to the output. Output is
+    // assumed to be of audio_sample_t type.
+    // pOut         The buffer to mix the output to.
+    //              When function exist will point to the next output sample.
+    // numSamples   The number of single-channel samples to process.
+    void MixOutput(void *& pOut, uint32_t numSamples) {
+        const audio_sample_t * pIn = mBuffer;
+        audio_sample_t * pOut24 = reinterpret_cast<audio_sample_t *>(pOut);
+        numSamples *= mNumChannels;
+        while (numSamples-- > 0) {
+            *(pOut24++) += *(pIn++);
+        }
+        pOut = pOut24;
+    }
+};
+
+}
+
+#endif // AUDIOFORMATADAPTER_H_
diff --git a/media/libeffects/AudioHighShelfFilterCoef.inl b/media/libeffects/AudioHighShelfFilterCoef.inl
new file mode 100644
index 0000000..ebba139
--- /dev/null
+++ b/media/libeffects/AudioHighShelfFilterCoef.inl
@@ -0,0 +1,225 @@
+13679,
+21575,
+8921,
+32315056,
+-15582015,
+26172,
+37678,
+14797,
+31891096,
+-15192527,
+51020,
+64449,
+23945,
+31322988,
+-14685186,
+101817,
+106144,
+37744,
+30562882,
+-14031372,
+208996,
+162163,
+58536,
+29548538,
+-13201017,
+442996,
+207459,
+93300,
+28200792,
+-12167331,
+971423,
+128786,
+169690,
+26422744,
+-10915428,
+2200461,
+-465686,
+394986,
+24103317,
+-9455862,
+5119991,
+-2777199,
+1147245,
+21129473,
+-7842294,
+12120379,
+-10198160,
+3631544,
+17411837,
+-6188384,
+28834234,
+-31647135,
+11337795,
+12924960,
+-4672638,
+68037766,
+-88974388,
+33477255,
+7752680,
+-3516098,
+157369944,
+-232063160,
+92282129,
+2113926,
+-2925624,
+353720112,
+-567427144,
+237164112,
+-3659993,
+-3019871,
+769091151,
+-1309871949,
+570539430,
+-9202114,
+-3779302,
+66791,
+121706,
+55888,
+30571245,
+-14038415,
+120426,
+212178,
+94820,
+29559679,
+-13209886,
+217130,
+365165,
+157610,
+28215554,
+-12178243,
+391489,
+617016,
+255010,
+26442131,
+-10928431,
+705862,
+1015147,
+398457,
+24128430,
+-9470680,
+1272682,
+1605251,
+596102,
+21161334,
+-7858153,
+2294668,
+2386833,
+848523,
+17451072,
+-6203880,
+4137327,
+3198789,
+1155536,
+12971362,
+-4685798,
+7459675,
+3470266,
+1567219,
+7804818,
+-3524761,
+13449926,
+1738911,
+2347406,
+2169089,
+-2928116,
+24250455,
+-5211241,
+4358971,
+-3605298,
+-3015671,
+43724001,
+-23849570,
+9823315,
+-9151253,
+-3769277,
+78835150,
+-66542375,
+23686373,
+-14161143,
+-5040790,
+142141173,
+-156324261,
+56024234,
+-18451275,
+-6612656,
+256283057,
+-335606326,
+126341244,
+-21970004,
+-8270755,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
diff --git a/media/libeffects/AudioLowShelfFilterCoef.inl b/media/libeffects/AudioLowShelfFilterCoef.inl
new file mode 100644
index 0000000..b57deb4
--- /dev/null
+++ b/media/libeffects/AudioLowShelfFilterCoef.inl
@@ -0,0 +1,375 @@
+16212506,
+-32420574,
+16208068,
+32401411,
+-15662521,
+16356129,
+-32706246,
+16350118,
+32695525,
+-15939752,
+16464399,
+-32920670,
+16456274,
+32914686,
+-16149441,
+16546128,
+-33081289,
+16535165,
+33077955,
+-16307411,
+16608101,
+-33201422,
+16593328,
+33199569,
+-16426067,
+16655539,
+-33291174,
+16635647,
+33290147,
+-16514997,
+16692478,
+-33358171,
+16665715,
+33357608,
+-16581540,
+16722089,
+-33408149,
+16686099,
+33407850,
+-16631271,
+16746930,
+-33445409,
+16698549,
+33445267,
+-16668405,
+16769156,
+-33473168,
+16704138,
+33473133,
+-16696114,
+16790706,
+-33493827,
+16703348,
+33493886,
+-16716779,
+16813466,
+-33509166,
+16696111,
+33509342,
+-16732186,
+16839437,
+-33520498,
+16681802,
+33520852,
+-16743669,
+16870911,
+-33528765,
+16659191,
+33529424,
+-16752226,
+16910681,
+-33534607,
+16626337,
+33535807,
+-16758602,
+15667401,
+-31326224,
+15658825,
+31252161,
+-14623074,
+15945865,
+-31880007,
+15934146,
+31838205,
+-15144597,
+16157521,
+-32299091,
+16141578,
+32275604,
+-15545369,
+16318267,
+-32614903,
+16296651,
+32601755,
+-15850850,
+16440710,
+-32852157,
+16411473,
+32844820,
+-16082303,
+16534751,
+-33029985,
+16495281,
+33025910,
+-16256891,
+16608171,
+-33163043,
+16554957,
+33160803,
+-16388152,
+16667145,
+-33262468,
+16595477,
+33261275,
+-16486599,
+16716699,
+-33336671,
+16620252,
+33336105,
+-16560301,
+16761100,
+-33391976,
+16631379,
+33391836,
+-16615404,
+16804207,
+-33433103,
+16629806,
+33433341,
+-16656560,
+16849794,
+-33463551,
+16615399,
+33464251,
+-16687277,
+16901887,
+-33485857,
+16586933,
+33487271,
+-16710189,
+16965125,
+-33501781,
+16542000,
+33504415,
+-16727274,
+17045198,
+-33512384,
+16476824,
+33517183,
+-16740008,
+14635201,
+-29254376,
+14619184,
+28977711,
+-12753834,
+15157556,
+-30292825,
+15135285,
+30133938,
+-13674513,
+15561511,
+-31092298,
+15530817,
+31001860,
+-14405551,
+15872211,
+-31702342,
+15830187,
+31651218,
+-14976306,
+16111094,
+-32164834,
+16053843,
+32136101,
+-15416453,
+16295848,
+-32513802,
+16218140,
+32497757,
+-15752817,
+16440852,
+-32776179,
+16335665,
+32767326,
+-16008155,
+16557804,
+-32972907,
+16415715,
+32968179,
+-16201031,
+16656403,
+-33120052,
+16464758,
+33117802,
+-16346195,
+16745001,
+-33229805,
+16486810,
+33229247,
+-16455153,
+16831240,
+-33311306,
+16483692,
+33312252,
+-16536771,
+16922682,
+-33371278,
+16455145,
+33374070,
+-16597819,
+17027472,
+-33414465,
+16398818,
+33420110,
+-16643430,
+17155108,
+-33443875,
+16310110,
+33454398,
+-16677479,
+17317384,
+-33460760,
+16181887,
+33479933,
+-16702882,
+12792703,
+-25557388,
+12764716,
+24590507,
+-9747085,
+13706465,
+-27372621,
+13666215,
+26798296,
+-11169790,
+14439425,
+-28821830,
+14382518,
+28486469,
+-12380088,
+15018453,
+-29957273,
+14939030,
+29764018,
+-13373522,
+15472460,
+-30834757,
+15362688,
+30724568,
+-14168120,
+15828725,
+-31506123,
+15678118,
+31443928,
+-14791822,
+16111406,
+-32015988,
+15905901,
+31981391,
+-15274688,
+16341329,
+-32400984,
+16062061,
+32382398,
+-15644761,
+16536484,
+-32690238,
+16158133,
+32681354,
+-15926286,
+16712853,
+-32906337,
+16201432,
+32904128,
+-16139278,
+16885430,
+-33066336,
+16195306,
+33070090,
+-16299767,
+17069377,
+-33182599,
+16139282,
+33193711,
+-16420332,
+17281371,
+-33263294,
+16029039,
+33285785,
+-16510702,
+17541271,
+-33312390,
+15856243,
+33354359,
+-16578329,
+17874330,
+-33328902,
+15608287,
+33405430,
+-16628873,
+9881279,
+-19719268,
+9838084,
+16734303,
+-5927111,
+11264857,
+-22463447,
+11198784,
+20577584,
+-7572288,
+12460736,
+-24823046,
+12362697,
+23667359,
+-9201903,
+13459805,
+-26776851,
+13317799,
+26085683,
+-10691555,
+14276287,
+-28349256,
+14074406,
+27943899,
+-11978834,
+14936943,
+-29588248,
+14654011,
+29354533,
+-13047453,
+15473300,
+-30549299,
+15081036,
+30417203,
+-13909216,
+15917271,
+-31285788,
+15377817,
+31213972,
+-14589687,
+16299384,
+-31844320,
+15562006,
+31809683,
+-15118811,
+16648774,
+-32262999,
+15645414,
+32254329,
+-15525641,
+16994277,
+-32571090,
+15633607,
+32585895,
+-15835862,
+17366374,
+-32789019,
+15525801,
+32833003,
+-16070975,
+17799955,
+-32927834,
+15314895,
+33017107,
+-16248361,
+18338206,
+-32987318,
+14987686,
+33154246,
+-16381747,
+19038270,
+-32951545,
+14525592,
+33256392,
+-16481800,
diff --git a/media/libeffects/AudioPeakingFilter.cpp b/media/libeffects/AudioPeakingFilter.cpp
new file mode 100644
index 0000000..60fefe6
--- /dev/null
+++ b/media/libeffects/AudioPeakingFilter.cpp
@@ -0,0 +1,121 @@
+/* //device/include/server/AudioFlinger/AudioPeakingFilter.cpp
+ **
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "AudioPeakingFilter.h"
+#include "AudioCommon.h"
+#include "EffectsMath.h"
+
+#include <new>
+#include <assert.h>
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+// Format of the coefficient table:
+// kCoefTable[freq][gain][bw][coef]
+// freq - peak frequency, in octaves below Nyquist,from -9 to -1.
+// gain - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel.
+// bw   - bandwidth, starting at 1 cent, jumps of 1024, to 3073 cents.
+// coef - 0: b0
+//        1: b1
+//        2: b2
+//        3: -a1
+//        4: -a2
+static const size_t kInDims[3] = {9, 15, 4};
+static const audio_coef_t kCoefTable[9*15*4*5] = {
+#include "AudioPeakingFilterCoef.inl"
+};
+
+AudioCoefInterpolator AudioPeakingFilter::mCoefInterp(3, kInDims, 5, (const audio_coef_t*) kCoefTable);
+
+AudioPeakingFilter::AudioPeakingFilter(int nChannels, int sampleRate)
+        : mBiquad(nChannels, sampleRate) {
+    configure(nChannels, sampleRate);
+    reset();
+}
+
+void AudioPeakingFilter::configure(int nChannels, int sampleRate) {
+    mNiquistFreq = sampleRate * 500;
+    mFrequencyFactor = ((1ull) << 42) / mNiquistFreq;
+    mBiquad.configure(nChannels, sampleRate);
+    setFrequency(mNominalFrequency);
+    commit(true);
+}
+
+void AudioPeakingFilter::reset() {
+    setGain(0);
+    setFrequency(0);
+    setBandwidth(2400);
+    commit(true);
+}
+
+void AudioPeakingFilter::setFrequency(uint32_t millihertz) {
+    mNominalFrequency = millihertz;
+    if (UNLIKELY(millihertz > mNiquistFreq / 2)) {
+        millihertz = mNiquistFreq / 2;
+    }
+    uint32_t normFreq = static_cast<uint32_t>(
+            (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10);
+    if (LIKELY(normFreq > (1 << 23))) {
+        mFrequency = (Effects_log2(normFreq) - ((32-9) << 15)) << (FREQ_PRECISION_BITS - 15);
+    } else {
+        mFrequency = 0;
+    }
+}
+
+void AudioPeakingFilter::setGain(int32_t millibel) {
+    mGain = millibel + 9600;
+}
+
+void AudioPeakingFilter::setBandwidth(uint32_t cents) {
+    mBandwidth = cents - 1;
+}
+
+void AudioPeakingFilter::commit(bool immediate) {
+    audio_coef_t coefs[5];
+    int intCoord[3] = {
+        mFrequency >> FREQ_PRECISION_BITS,
+        mGain >> GAIN_PRECISION_BITS,
+        mBandwidth >> BANDWIDTH_PRECISION_BITS
+    };
+    uint32_t fracCoord[3] = {
+        mFrequency << (32 - FREQ_PRECISION_BITS),
+        static_cast<uint32_t>(mGain) << (32 - GAIN_PRECISION_BITS),
+        mBandwidth << (32 - BANDWIDTH_PRECISION_BITS)
+    };
+    mCoefInterp.getCoef(intCoord, fracCoord, coefs);
+    mBiquad.setCoefs(coefs, immediate);
+}
+
+void AudioPeakingFilter::getBandRange(uint32_t & low, uint32_t & high) const {
+    // Half bandwidth, in octaves, 15-bit precision
+    int32_t halfBW = (((mBandwidth + 1) / 2) << 15) / 1200;
+
+    low = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(-halfBW + (16 << 15))) >> 16);
+    if (UNLIKELY(halfBW >= (16 << 15))) {
+        high = mNiquistFreq;
+    } else {
+        high = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(halfBW + (16 << 15))) >> 16);
+        if (UNLIKELY(high > mNiquistFreq)) {
+            high = mNiquistFreq;
+        }
+    }
+}
+
+}
+
diff --git a/media/libeffects/AudioPeakingFilter.h b/media/libeffects/AudioPeakingFilter.h
new file mode 100644
index 0000000..d0f49c9
--- /dev/null
+++ b/media/libeffects/AudioPeakingFilter.h
@@ -0,0 +1,151 @@
+/* //device/include/server/AudioFlinger/AudioPeakingFilter.h
+**
+** Copyright 2009, 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_PEAKING_FILTER_H
+#define ANDROID_AUDIO_PEAKING_FILTER_H
+
+#include "AudioBiquadFilter.h"
+#include "AudioCoefInterpolator.h"
+
+namespace android {
+
+// A peaking audio filter, with unity skirt gain, and controllable peak
+// frequency, gain and bandwidth.
+// This filter is able to suppress introduce discontinuities and other artifacts
+// in the output, even when changing parameters abruptly.
+// Parameters can be set to any value - this class will make sure to clip them
+// when they are out of supported range.
+//
+// Implementation notes:
+// This class uses an underlying biquad filter whose parameters are determined
+// using a linear interpolation from a coefficient table, using a
+// AudioCoefInterpolator.
+// All is left for this class to do is mapping between high-level parameters to
+// fractional indices into the coefficient table.
+class AudioPeakingFilter {
+public:
+    // Constructor. Resets the filter (see reset()).
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    AudioPeakingFilter(int nChannels, int sampleRate);
+
+    // Reconfiguration of the filter. Changes input/output format, but does not
+    // alter current parameter values. Clears delay lines.
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    void configure(int nChannels, int sampleRate);
+
+    // Resets the filter parameters to the following values:
+    // frequency: 0
+    // gain: 0
+    // bandwidth: 1200 cents.
+    // It also disables the filter. Does not clear the delay lines.
+    void reset();
+
+    // Clears delay lines. Does not alter parameter values.
+    void clear() { mBiquad.clear(); }
+
+    // Sets gain value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // millibel Gain value in millibel (1/100 of decibel).
+    void setGain(int32_t millibel);
+
+    // Gets the gain, in millibel, as set.
+    int32_t getGain() const { return mGain - 9600; }
+
+    // Sets bandwidth value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // cents Bandwidth value in cents (1/1200 octave).
+    void setBandwidth(uint32_t cents);
+
+    // Gets the gain, in cents, as set.
+    uint32_t getBandwidth() const { return mBandwidth + 1; }
+
+    // Sets frequency value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // millihertz Frequency value in mHz.
+    void setFrequency(uint32_t millihertz);
+
+    // Gets the frequency, in mHz, as set.
+    uint32_t getFrequency() const { return mNominalFrequency; }
+
+    // Gets gain[dB]/2 points.
+    // Results in mHz, and are computed based on the nominal values set, not on
+    // possibly rounded or truncated actual values.
+    void getBandRange(uint32_t & low, uint32_t & high) const;
+
+    // Applies all parameter changes done to this point in time.
+    // If the filter is disabled, the new parameters will take place when it is
+    // enabled again. Does not introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly (ignored if filter is
+    // disabled).
+   void commit(bool immediate = false);
+
+    // Process a buffer of input data. The input and output should contain
+    // frameCount * nChannels interlaced samples. Processing can be done
+    // in-place, by passing the same buffer as both arguments.
+    // in           Input buffer.
+    // out          Output buffer.
+    // frameCount   Number of frames to produce.
+    void process(const audio_sample_t in[], audio_sample_t out[],
+                 int frameCount) { mBiquad.process(in, out, frameCount); }
+
+    // Enables the filter, so it would start processing input. Does not
+    // introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void enable(bool immediate = false) { mBiquad.enable(immediate); }
+
+    // Disabled (bypasses) the filter. Does not introduce artifacts, unless
+    // immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void disable(bool immediate = false) { mBiquad.disable(immediate); }
+
+private:
+    // Precision for the mFrequency member.
+    static const int FREQ_PRECISION_BITS = 26;
+    // Precision for the mGain member.
+    static const int GAIN_PRECISION_BITS = 10;
+    // Precision for the mBandwidth member.
+    static const int BANDWIDTH_PRECISION_BITS = 10;
+
+    // Nyquist, in mHz.
+    uint32_t mNiquistFreq;
+    // Fractional index into the gain dimension of the coef table in
+    // GAIN_PRECISION_BITS precision.
+    int32_t mGain;
+    // Fractional index into the bandwidth dimension of the coef table in
+    // BANDWIDTH_PRECISION_BITS precision.
+    uint32_t mBandwidth;
+    // Fractional index into the frequency dimension of the coef table in
+    // FREQ_PRECISION_BITS precision.
+    uint32_t mFrequency;
+    // Nominal value of frequency, as set.
+    uint32_t mNominalFrequency;
+    // 1/Nyquist[mHz], in 42-bit precision (very small).
+    // Used for scaling the frequency.
+    uint32_t mFrequencyFactor;
+
+    // A biquad filter, used for the actual processing.
+    AudioBiquadFilter mBiquad;
+    // A coefficient interpolator, used for mapping the high level parameters to
+    // the low-level biquad coefficients.
+    static AudioCoefInterpolator mCoefInterp;
+};
+
+}
+
+#endif // ANDROID_AUDIO_PEAKING_FILTER_H
diff --git a/media/libeffects/AudioPeakingFilterCoef.inl b/media/libeffects/AudioPeakingFilterCoef.inl
new file mode 100644
index 0000000..374c6e1
--- /dev/null
+++ b/media/libeffects/AudioPeakingFilterCoef.inl
@@ -0,0 +1,2700 @@
+16769751,
+-33538871,
+16769751,
+33538871,
+-16762286,
+11468083,
+-22935566,
+11467915,
+22935566,
+-6158781,
+8532673,
+-17064763,
+8532412,
+17064763,
+-287869,
+6567366,
+-13134160,
+6567042,
+13134160,
+3642808,
+16773075,
+-33545518,
+16773075,
+33545518,
+-16768934,
+13349658,
+-26698459,
+13349304,
+26698459,
+-9921746,
+10923581,
+-21846147,
+10922977,
+21846147,
+-5069342,
+9009390,
+-18017641,
+9008590,
+18017641,
+-1240764,
+16774919,
+-33549207,
+16774919,
+33549207,
+-16772622,
+14686150,
+-29371047,
+14685450,
+29371047,
+-12594384,
+12933736,
+-25865697,
+12932448,
+25865697,
+-9088968,
+11350364,
+-22698482,
+11348545,
+22698482,
+-5921693,
+16775943,
+-33551252,
+16775941,
+33551252,
+-16774668,
+15549746,
+-31097569,
+15548408,
+31097569,
+-14320938,
+14404163,
+-28805197,
+14401577,
+28805197,
+-12028524,
+13261978,
+-26519626,
+13258147,
+26519626,
+-9742909,
+16776511,
+-33552387,
+16776508,
+33552387,
+-16775803,
+16074349,
+-32145600,
+16071856,
+32145600,
+-15368989,
+15374244,
+-30742933,
+15369268,
+30742933,
+-13966296,
+14629431,
+-29250695,
+14621814,
+29250695,
+-12474030,
+16776826,
+-33553017,
+16776822,
+33553017,
+-16776432,
+16381548,
+-32757900,
+16376968,
+32757900,
+-15981300,
+15972161,
+-31934402,
+15962842,
+31934402,
+-15157787,
+15518882,
+-31022614,
+15504316,
+31022614,
+-14245982,
+16777003,
+-33553366,
+16776995,
+33553366,
+-16776781,
+16558315,
+-33107660,
+16549969,
+33107660,
+-16331067,
+16326848,
+-32635910,
+16309677,
+32635910,
+-15859308,
+16064456,
+-32101133,
+16037281,
+32101133,
+-15324521,
+16777103,
+-33553559,
+16777088,
+33553559,
+-16776975,
+16660325,
+-33304885,
+16645187,
+33304885,
+-16528296,
+16535200,
+-33038436,
+16503858,
+33038436,
+-16261842,
+16391425,
+-32732273,
+16341464,
+32732273,
+-15955673,
+16777162,
+-33553667,
+16777136,
+33553667,
+-16777082,
+16721651,
+-33415288,
+16694267,
+33415288,
+-16638701,
+16661761,
+-33265997,
+16604862,
+33265997,
+-16489407,
+16592417,
+-33093137,
+16501343,
+33093137,
+-16316544,
+16777203,
+-33553726,
+16777155,
+33553726,
+-16777142,
+16763466,
+-33476836,
+16714001,
+33476836,
+-16700251,
+16748588,
+-33393565,
+16645605,
+33393565,
+-16616978,
+16731288,
+-33296733,
+16566071,
+33296733,
+-16520144,
+16777238,
+-33553759,
+16777152,
+33553759,
+-16777175,
+16800489,
+-33511071,
+16711212,
+33511071,
+-16734485,
+16825723,
+-33464740,
+16639647,
+33464740,
+-16688154,
+16855137,
+-33410736,
+16556228,
+33410736,
+-16634149,
+16777282,
+-33553778,
+16777127,
+33553778,
+-16777193,
+16845889,
+-33530088,
+16684830,
+33530088,
+-16753503,
+16920437,
+-33504347,
+16584541,
+33504347,
+-16727762,
+17007449,
+-33474302,
+16467484,
+33474302,
+-16697716,
+16777349,
+-33553788,
+16777070,
+33553788,
+-16777203,
+16915880,
+-33540645,
+16625396,
+33540645,
+-16764060,
+17066504,
+-33526354,
+16460481,
+33526354,
+-16749769,
+17242444,
+-33509662,
+16267849,
+33509662,
+-16733077,
+16777464,
+-33553793,
+16776961,
+33553793,
+-16777209,
+17035487,
+-33546503,
+16511647,
+33546503,
+-16769918,
+17316137,
+-33538572,
+16223067,
+33538572,
+-16761988,
+17644089,
+-33529306,
+15885848,
+33529306,
+-16752721,
+16777668,
+-33553796,
+16776760,
+33553796,
+-16777212,
+17247484,
+-33549752,
+16302900,
+33549752,
+-16773168,
+17758603,
+-33545353,
+15787381,
+33545353,
+-16768768,
+18356007,
+-33540211,
+15184835,
+33540211,
+-16763626,
+16762293,
+-33522062,
+16762293,
+33522062,
+-16747370,
+8711405,
+-17421242,
+8711149,
+17421242,
+-645338,
+5721250,
+-11441288,
+5720900,
+11441288,
+5335066,
+4082836,
+-8164655,
+4082434,
+8164655,
+8611946,
+16768936,
+-33535347,
+16768936,
+33535347,
+-16760656,
+11085056,
+-22167856,
+11084469,
+22167856,
+-5392309,
+8098223,
+-16194333,
+8097329,
+16194333,
+581664,
+6158323,
+-12314623,
+6157228,
+12314623,
+4461665,
+16772623,
+-33542719,
+16772622,
+33542719,
+-16768029,
+13058634,
+-26114055,
+13057388,
+26114055,
+-9338806,
+10523211,
+-21042742,
+10521116,
+21042742,
+-4267110,
+8576560,
+-17149081,
+8573812,
+17149081,
+-373156,
+16774670,
+-33546810,
+16774667,
+33546810,
+-16772120,
+14489725,
+-28974776,
+14487233,
+28974776,
+-12199742,
+12619509,
+-25232587,
+12614979,
+25232587,
+-8457271,
+10965151,
+-21922319,
+10958818,
+21922319,
+-5146753,
+16775805,
+-33549079,
+16775800,
+33549079,
+-16774390,
+15428102,
+-30849095,
+15423317,
+30849095,
+-14074202,
+14188157,
+-28364996,
+14178975,
+28364996,
+-11589916,
+12969900,
+-25924346,
+12956398,
+25924346,
+-9149082,
+16776437,
+-33550338,
+16776428,
+33550338,
+-16775648,
+16004216,
+-31997074,
+15995268,
+31997074,
+-15222267,
+15241233,
+-30462393,
+15223454,
+30462393,
+-13687471,
+14437070,
+-28844880,
+14409982,
+28844880,
+-12069836,
+16776789,
+-33551036,
+16776773,
+33551036,
+-16776347,
+16345158,
+-32671383,
+16328685,
+32671383,
+-15896627,
+15900462,
+-31765104,
+15867034,
+31765104,
+-14990280,
+15410846,
+-30767279,
+15358750,
+30767279,
+-13992380,
+16776990,
+-33551423,
+16776960,
+33551423,
+-16776734,
+16545156,
+-33057769,
+16515103,
+33057769,
+-16283043,
+16300504,
+-32536823,
+16238769,
+32536823,
+-15762058,
+16024071,
+-31948201,
+15926537,
+31948201,
+-15173391,
+16777109,
+-33551638,
+16777056,
+33551638,
+-16776949,
+16666542,
+-33276035,
+16611999,
+33276035,
+-16501325,
+16548270,
+-32981225,
+16435439,
+32981225,
+-16206493,
+16412621,
+-32643103,
+16232940,
+32643103,
+-15868346,
+16777189,
+-33551757,
+16777094,
+33551757,
+-16777068,
+16749778,
+-33398338,
+16651075,
+33398338,
+-16623637,
+16720233,
+-33232976,
+16515245,
+33232976,
+-16458262,
+16686059,
+-33041706,
+16358135,
+33041706,
+-16266978,
+16777261,
+-33551823,
+16777089,
+33551823,
+-16777134,
+16823703,
+-33466559,
+16645376,
+33466559,
+-16691863,
+16873974,
+-33374267,
+16502806,
+33374267,
+-16599564,
+16932398,
+-33267006,
+16337114,
+33267006,
+-16492295,
+16777348,
+-33551860,
+16777038,
+33551860,
+-16777170,
+16914465,
+-33504517,
+16592574,
+33504517,
+-16729824,
+17063236,
+-33453150,
+16392432,
+33453150,
+-16678453,
+17236595,
+-33393293,
+16159213,
+33393293,
+-16618592,
+16777483,
+-33551880,
+16776924,
+33551880,
+-16777191,
+17054436,
+-33525606,
+16473695,
+33525606,
+-16750914,
+17355321,
+-33497061,
+16144262,
+33497061,
+-16722367,
+17706453,
+-33463749,
+15759816,
+33463749,
+-16689053,
+16777713,
+-33551891,
+16776705,
+33551891,
+-16777202,
+17293646,
+-33537314,
+16246194,
+33537314,
+-16762623,
+17854571,
+-33521465,
+15669419,
+33521465,
+-16746773,
+18509706,
+-33502954,
+14995772,
+33502954,
+-16728261,
+16778120,
+-33551898,
+16776304,
+33551898,
+-16777208,
+17717639,
+-33543811,
+15828698,
+33543811,
+-16769121,
+18739501,
+-33535016,
+14798040,
+33535016,
+-16760325,
+19933534,
+-33524738,
+13593729,
+33524738,
+-16750047,
+16747397,
+-33484705,
+16747396,
+33484705,
+-16717577,
+5883112,
+-11762335,
+5882767,
+11762335,
+5011337,
+3448701,
+-6894903,
+3448279,
+6894903,
+9880236,
+2324286,
+-4646714,
+2323828,
+4646714,
+12129102,
+16760665,
+-33511232,
+16760663,
+33511232,
+-16744112,
+8276984,
+-16548106,
+8276108,
+16548106,
+224124,
+5337400,
+-10670406,
+5336221,
+10670406,
+6103596,
+3771525,
+-7539439,
+3770185,
+7539439,
+9235506,
+16768033,
+-33525963,
+16768030,
+33525963,
+-16758848,
+10689564,
+-21370649,
+10687524,
+21370649,
+-4599872,
+7666068,
+-15324466,
+7663015,
+15324466,
+1448133,
+5761266,
+-11515371,
+5757575,
+11515371,
+5258376,
+16772124,
+-33534139,
+16772118,
+33534139,
+-16767026,
+12751423,
+-25490780,
+12747036,
+25490780,
+-8721243,
+10113942,
+-20214533,
+10106682,
+20214533,
+-3443407,
+8145025,
+-16275741,
+8135620,
+16275741,
+496571,
+16774395,
+-33538675,
+16774385,
+33538675,
+-16771564,
+14280137,
+-28542819,
+14271281,
+28542819,
+-11774202,
+12292391,
+-24561476,
+12276485,
+24561476,
+-7791660,
+10572949,
+-21117532,
+10550945,
+21117532,
+-4346678,
+16775657,
+-33541192,
+16775639,
+33541192,
+-16774081,
+15299683,
+-30573051,
+15282579,
+30573051,
+-13805046,
+13964251,
+-27887539,
+13931690,
+27887539,
+-11118724,
+12672686,
+-25290241,
+12625174,
+25290241,
+-8520644,
+16776363,
+-33542588,
+16776330,
+33542588,
+-16775477,
+15935196,
+-31828699,
+15903092,
+31828699,
+-15061072,
+15112356,
+-30152153,
+15048881,
+30152153,
+-13384021,
+14253857,
+-28402950,
+14157649,
+28402950,
+-11634291,
+16776763,
+-33543362,
+16776704,
+33543362,
+-16776252,
+16319830,
+-32570615,
+16260598,
+32570615,
+-15803212,
+15851783,
+-31574208,
+15731938,
+31574208,
+-14806505,
+15339614,
+-30483871,
+15153441,
+30483871,
+-13715838,
+16777001,
+-33543791,
+16776896,
+33543791,
+-16776681,
+16557673,
+-32997208,
+16449476,
+32997208,
+-16229933,
+16326977,
+-32422299,
+16105089,
+32422299,
+-15654851,
+16067244,
+-31775024,
+15717353,
+31775024,
+-15007381,
+16777163,
+-33544029,
+16776972,
+33544029,
+-16776919,
+16722590,
+-33238660,
+16526083,
+33238660,
+-16471458,
+16664322,
+-32912610,
+16258203,
+32912610,
+-16145310,
+16597629,
+-32539419,
+15951593,
+32539419,
+-15772007,
+16777306,
+-33544162,
+16776962,
+33544162,
+-16777051,
+16869955,
+-33374105,
+16514205,
+33374105,
+-16606944,
+16969714,
+-33190996,
+16231282,
+33190996,
+-16423780,
+17084972,
+-32979442,
+15904406,
+32979442,
+-16212162,
+16777480,
+-33544235,
+16776860,
+33544235,
+-16777125,
+17051328,
+-33449703,
+16408452,
+33449703,
+-16682565,
+17347583,
+-33347437,
+16009901,
+33347437,
+-16580267,
+17691668,
+-33228659,
+15547002,
+33228659,
+-16461454,
+16777750,
+-33544275,
+16776632,
+33544275,
+-16777165,
+17331222,
+-33491780,
+16170648,
+33491780,
+-16724654,
+17931550,
+-33434840,
+15513363,
+33434840,
+-16667697,
+18630855,
+-33368512,
+14747710,
+33368512,
+-16601349,
+16778210,
+-33544298,
+16776194,
+33544298,
+-16777188,
+17809628,
+-33515162,
+15715631,
+33515162,
+-16748043,
+18929991,
+-33483514,
+14563611,
+33483514,
+-16716385,
+20237212,
+-33446587,
+13219451,
+33446587,
+-16679448,
+16779025,
+-33544310,
+16775392,
+33544310,
+-16777200,
+18657612,
+-33528145,
+14880634,
+33528145,
+-16761030,
+20699844,
+-33510571,
+12820822,
+33510571,
+-16743451,
+23084863,
+-33490047,
+10415274,
+33490047,
+-16722921,
+16717684,
+-33395091,
+16717682,
+33395091,
+-16658149,
+3567009,
+-7125006,
+3566590,
+7125006,
+9643617,
+1921926,
+-3838751,
+1921455,
+3838751,
+12933835,
+1248662,
+-2493824,
+1248170,
+2493824,
+14280384,
+16744147,
+-33447952,
+16744143,
+33447952,
+-16711074,
+5493785,
+-10973174,
+5492622,
+10973174,
+5790808,
+3173694,
+-6338342,
+3172292,
+6338342,
+10431230,
+2124754,
+-4242881,
+2123244,
+4242881,
+12529218,
+16758861,
+-33477342,
+16758855,
+33477342,
+-16740500,
+7843885,
+-15665884,
+7840892,
+15665884,
+1092439,
+4968649,
+-9921376,
+4964692,
+9921376,
+6843875,
+3478437,
+-6944043,
+3473981,
+6944043,
+9824798,
+16767035,
+-33493665,
+16767024,
+33493665,
+-16756842,
+10284421,
+-20536999,
+10277346,
+20536999,
+-3784550,
+7240254,
+-14452686,
+7229862,
+14452686,
+2307100,
+5379798,
+-10734231,
+5367379,
+10734231,
+6030039,
+16771575,
+-33502725,
+16771555,
+33502725,
+-16765913,
+12431046,
+-24816749,
+12415632,
+24816749,
+-8069462,
+9702049,
+-19355664,
+9676957,
+19355664,
+-2601790,
+7722611,
+-15394544,
+7690499,
+15394544,
+1364106,
+16774099,
+-33507752,
+16774063,
+33507752,
+-16770946,
+14062583,
+-28059903,
+14031160,
+28059903,
+-11316527,
+11962999,
+-23841519,
+11907273,
+23841519,
+-7093056,
+10188929,
+-20277142,
+10112667,
+20277142,
+-3524380,
+16775510,
+-33510541,
+16775445,
+33510541,
+-16773738,
+15175102,
+-30252637,
+15114019,
+30252637,
+-13511905,
+13753207,
+-27358123,
+13637911,
+27358123,
+-10613901,
+12400971,
+-24605416,
+12234119,
+24605416,
+-7857874,
+16776310,
+-33512088,
+16776193,
+33512088,
+-16775287,
+15888242,
+-31623221,
+15773117,
+31623221,
+-14884143,
+15028972,
+-29795608,
+14802570,
+29795608,
+-13054325,
+14142237,
+-27909578,
+13801000,
+27909578,
+-11166021,
+16776787,
+-33512946,
+16776575,
+33512946,
+-16776146,
+16345172,
+-32438302,
+16132251,
+32438302,
+-15700207,
+15905856,
+-31344484,
+15476429,
+31344484,
+-14605069,
+15428324,
+-30155514,
+14763558,
+30155514,
+-13414665,
+16777110,
+-33513422,
+16776729,
+33513422,
+-16776623,
+16668950,
+-32908744,
+16279482,
+32908744,
+-16171216,
+16555594,
+-32275015,
+15758344,
+32275015,
+-15536722,
+16428465,
+-31564284,
+15173886,
+31564284,
+-14825134,
+16777395,
+-33513686,
+16776708,
+33513686,
+-16776887,
+16961758,
+-33175594,
+16253845,
+33175594,
+-16438387,
+17158212,
+-32815329,
+15696692,
+32815329,
+-16077688,
+17382578,
+-32403880,
+15060381,
+32403880,
+-15665743,
+16777745,
+-33513832,
+16776505,
+33513832,
+-16777033,
+17323903,
+-33325470,
+16041757,
+33325470,
+-16588444,
+17911332,
+-33122874,
+15251488,
+33122874,
+-16385604,
+18589203,
+-32889086,
+14339546,
+32889086,
+-16151534,
+16778283,
+-33513913,
+16776048,
+33513913,
+-16777115,
+17883505,
+-33409180,
+15565966,
+33409180,
+-16672255,
+19078451,
+-33295944,
+14257648,
+33295944,
+-16558883,
+20465440,
+-33164510,
+12739067,
+33164510,
+-16427290,
+16779203,
+-33513958,
+16775173,
+33513958,
+-16777160,
+18840265,
+-33455789,
+14655871,
+33455789,
+-16718921,
+21075121,
+-33392715,
+12357866,
+33392715,
+-16655771,
+23677621,
+-33319266,
+9681828,
+33319266,
+-16582233,
+16780834,
+-33513983,
+16773567,
+33513983,
+-16777185,
+20536227,
+-33481696,
+12985848,
+33481696,
+-16744859,
+24614855,
+-33446630,
+8872112,
+33446630,
+-16709751,
+29373075,
+-33405721,
+4072934,
+33405721,
+-16668793,
+16658572,
+-33156710,
+16658568,
+33156710,
+-16539925,
+1995694,
+-3971702,
+1995225,
+3971702,
+12786296,
+1019334,
+-2028355,
+1018835,
+2028355,
+14739047,
+648397,
+-1290041,
+647886,
+1290041,
+15480933,
+16711208,
+-33261470,
+16711201,
+33261470,
+-16645192,
+3284873,
+-6536727,
+3283483,
+6536727,
+10208860,
+1752746,
+-3487071,
+1751198,
+3487071,
+13273272,
+1134254,
+-2255981,
+1132642,
+2255981,
+14510319,
+16740546,
+-33319859,
+16740534,
+33319859,
+-16703864,
+5119019,
+-10184853,
+5115113,
+10184853,
+6543083,
+2916766,
+-5800820,
+2912122,
+5800820,
+10948329,
+1940950,
+-3858260,
+1935979,
+3858260,
+12900288,
+16756866,
+-33352332,
+16756844,
+33352332,
+-16736493,
+7416141,
+-14750709,
+7405941,
+14750709,
+1955134,
+4618132,
+-9178604,
+4604884,
+9178604,
+7554200,
+3205731,
+-6365873,
+3190944,
+6365873,
+10380541,
+16765937,
+-33370369,
+16765897,
+33370369,
+-16754618,
+9875714,
+-19631961,
+9851238,
+19631961,
+-2949736,
+6828874,
+-13556870,
+6793592,
+13556870,
+3154751,
+5021920,
+-9953987,
+4980230,
+9953987,
+6775066,
+16770983,
+-33380381,
+16770911,
+33380381,
+-16764679,
+12107731,
+-24045066,
+12053679,
+24045066,
+-7384194,
+9304697,
+-18433704,
+9218200,
+18433704,
+-1745681,
+7330173,
+-14480925,
+7220819,
+14480925,
+2226224,
+16773804,
+-33385937,
+16773674,
+33385937,
+-16770261,
+13857067,
+-27469883,
+13745731,
+27469883,
+-10825583,
+11667230,
+-23028209,
+11472403,
+23028209,
+-6362417,
+9861509,
+-19365642,
+9597835,
+19365642,
+-2682128,
+16775405,
+-33389019,
+16775170,
+33389019,
+-16773358,
+15094166,
+-29826057,
+14876207,
+29826057,
+-13193157,
+13629575,
+-26722225,
+13221948,
+26722225,
+-10074307,
+12261304,
+-23822520,
+11676482,
+23822520,
+-7160571,
+16776358,
+-33390729,
+16775935,
+33390729,
+-16775076,
+15939973,
+-31315809,
+15527360,
+31315809,
+-14690117,
+15140254,
+-29331850,
+14333520,
+29331850,
+-12696558,
+14324552,
+-27308240,
+13115821,
+27308240,
+-10663157,
+16777004,
+-33391677,
+16776241,
+33391677,
+-16776029,
+16564519,
+-32208051,
+15799374,
+32208051,
+-15586676,
+16349720,
+-31011538,
+14811870,
+31011538,
+-14384374,
+16117884,
+-29720119,
+13746038,
+29720119,
+-13086705,
+16777574,
+-33392203,
+16776199,
+33392203,
+-16776558,
+17142623,
+-32725183,
+15740903,
+32725183,
+-16106310,
+17523746,
+-32028793,
+14660021,
+32028793,
+-15406551,
+17949452,
+-31250941,
+13452699,
+31250941,
+-14624935,
+16778273,
+-33392495,
+16775794,
+33392495,
+-16776851,
+17864511,
+-33019221,
+15314476,
+33019221,
+-16401771,
+19019582,
+-32622294,
+13760557,
+32622294,
+-16002923,
+20335886,
+-32169961,
+11989731,
+32169961,
+-15548401,
+16779350,
+-33392657,
+16774879,
+33392657,
+-16777014,
+18982972,
+-33184592,
+14362186,
+33184592,
+-16567942,
+21350554,
+-32961046,
+11769976,
+32961046,
+-16343314,
+24079688,
+-32703362,
+8781912,
+32703362,
+-16084383,
+16781190,
+-33392746,
+16773130,
+33392746,
+-16777104,
+20896303,
+-33277026,
+12541737,
+33277026,
+-16660824,
+25343199,
+-33151977,
+7969185,
+33151977,
+-16535169,
+30502384,
+-33006896,
+2664219,
+33006896,
+-16389387,
+16784451,
+-33392796,
+16769918,
+33392796,
+-16777154,
+24288258,
+-33328516,
+9201520,
+33328516,
+-16712562,
+32423187,
+-33258828,
+996567,
+33258828,
+-16642538,
+41895320,
+-33177686,
+-8557101,
+33177686,
+-16561003,
+16541595,
+-32447498,
+16541587,
+32447498,
+-16305966,
+1060925,
+-2080590,
+1060426,
+2080590,
+14655865,
+525478,
+-1030256,
+524962,
+1030256,
+15726776,
+330321,
+-647437,
+329800,
+647437,
+16117095,
+16645717,
+-32651734,
+16645703,
+32651734,
+-16514203,
+1820789,
+-3570095,
+1819248,
+3570095,
+13137179,
+924575,
+-1812018,
+922942,
+1812018,
+14929699,
+586684,
+-1149186,
+585016,
+1149186,
+15605516,
+16704036,
+-32766121,
+16704011,
+32766121,
+-16630831,
+3020875,
+-5921138,
+3016266,
+5921138,
+10740076,
+1597573,
+-3128764,
+1592487,
+3128764,
+13587156,
+1030124,
+-2015487,
+1024848,
+2015487,
+14722244,
+16736565,
+-32829909,
+16736521,
+32829909,
+-16695869,
+4762013,
+-9328185,
+4748922,
+9328185,
+7266281,
+2679566,
+-5241091,
+2664205,
+5241091,
+11433446,
+1773912,
+-3463620,
+1757564,
+3463620,
+13245740,
+16754673,
+-32865395,
+16754593,
+32865395,
+-16732050,
+7001772,
+-13700468,
+6967104,
+13700468,
+2808340,
+4293363,
+-8378312,
+4249089,
+8378312,
+8234764,
+2960061,
+-5758307,
+2911058,
+5758307,
+10906097,
+16764756,
+-32885110,
+16764611,
+32885110,
+-16752151,
+9480188,
+-18513215,
+9395722,
+18513215,
+-2098694,
+6453693,
+-12542171,
+6334194,
+12542171,
+3989330,
+4710641,
+-9103264,
+4570966,
+9103264,
+7495609,
+16770393,
+-32896054,
+16770133,
+32896054,
+-16763310,
+11816276,
+-22992949,
+11627131,
+22992949,
+-6666191,
+8975726,
+-17314789,
+8678280,
+17314789,
+-876790,
+7032408,
+-13430164,
+6660869,
+13430164,
+3083940,
+16773593,
+-32902127,
+16773124,
+32902127,
+-16769502,
+13735615,
+-26557052,
+13341720,
+26557052,
+-10300120,
+11528165,
+-21946606,
+10848400,
+21946606,
+-5599349,
+9752563,
+-18238110,
+8842853,
+18238110,
+-1818200,
+16775499,
+-32905496,
+16774654,
+32905496,
+-16772937,
+15200588,
+-29054957,
+14423589,
+29054957,
+-12846961,
+13857004,
+-25769995,
+12417855,
+25769995,
+-9497643,
+12624453,
+-22756500,
+10577873,
+22756500,
+-6425111,
+16776792,
+-32907365,
+16775267,
+32907365,
+-16774843,
+16366344,
+-30654089,
+14888294,
+30654089,
+-14477422,
+15978753,
+-28526295,
+13106406,
+28526295,
+-12307942,
+15588057,
+-26381456,
+11310242,
+26381456,
+-10121083,
+16777933,
+-32908402,
+16775183,
+32908402,
+-16775900,
+17493802,
+-31619287,
+14744943,
+31619287,
+-15461529,
+18212414,
+-30325234,
+12706927,
+30325234,
+-14142124,
+18982725,
+-28938081,
+10522286,
+28938081,
+-12727795,
+16779330,
+-32908977,
+16774372,
+32908977,
+-16776486,
+18928041,
+-32181280,
+13883707,
+32181280,
+-16034532,
+21163118,
+-31424334,
+10876855,
+31424334,
+-15262757,
+23650871,
+-30581814,
+7530076,
+30581814,
+-14403731,
+16781484,
+-32909296,
+16772543,
+32909296,
+-16776811,
+21161996,
+-32501674,
+11976424,
+32501674,
+-16361204,
+25812009,
+-32068975,
+6885234,
+32068975,
+-15920027,
+31103385,
+-31576594,
+1091831,
+31576594,
+-15418000,
+16785164,
+-32909473,
+16769043,
+32909473,
+-16776991,
+24988064,
+-32682139,
+8334356,
+32682139,
+-16545204,
+33795794,
+-32438043,
+-722252,
+32438043,
+-16296325,
+43946128,
+-32156738,
+-11159403,
+32156738,
+-16009510,
+16791687,
+-32909571,
+16762620,
+32909571,
+-16777091,
+31772521,
+-32783096,
+1652834,
+32783096,
+-16648139,
+47961229,
+-32646423,
+-14675225,
+32646423,
+-16508788,
+66751682,
+-32487785,
+-33627423,
+32487785,
+-16347043,
+16312500,
+-30141556,
+16312485,
+30141556,
+-15847769,
+547598,
+-1011354,
+547084,
+1011354,
+15682534,
+266448,
+-491849,
+265925,
+491849,
+16244843,
+166111,
+-306446,
+165584,
+306446,
+16445521,
+16516262,
+-30518049,
+16516236,
+30518049,
+-16255282,
+962487,
+-1776938,
+960857,
+1776938,
+14853872,
+474742,
+-875656,
+473062,
+875656,
+15829413,
+297520,
+-548176,
+295821,
+548176,
+16183875,
+16631492,
+-30730944,
+16631443,
+30730944,
+-16485719,
+1660146,
+-3062870,
+1655081,
+3062870,
+13461989,
+838172,
+-1543806,
+832831,
+1543806,
+15106213,
+530135,
+-974532,
+524691,
+974532,
+15722390,
+16696110,
+-30850307,
+16696022,
+30850307,
+-16614916,
+2776642,
+-5116472,
+2761387,
+5116472,
+11239187,
+1456845,
+-2676477,
+1440152,
+2676477,
+13880219,
+936151,
+-1713835,
+918891,
+1713835,
+14922174,
+16732191,
+-30916910,
+16732031,
+30916910,
+-16687006,
+4430219,
+-8145523,
+4386431,
+8145523,
+7960566,
+2467715,
+-4512857,
+2416966,
+4512857,
+11892535,
+1628113,
+-2958725,
+1574387,
+2958725,
+13574716,
+16752314,
+-30953973,
+16752025,
+30953973,
+-16727123,
+6622193,
+-12127616,
+6504644,
+12127616,
+3650379,
+4016541,
+-7285135,
+3868831,
+7285135,
+8891843,
+2762675,
+-4954883,
+2600451,
+4954883,
+11414089,
+16763575,
+-30974568,
+16763055,
+30974568,
+-16749415,
+9150431,
+-16639142,
+8859646,
+16639142,
+-1232861,
+6182181,
+-11049974,
+5778225,
+11049974,
+4816810,
+4518629,
+-7917532,
+4051247,
+7917532,
+8207341,
+16769973,
+-30986002,
+16769034,
+30986002,
+-16761791,
+11676269,
+-20964630,
+11015683,
+20964630,
+-5914736,
+8893418,
+-15489638,
+7872446,
+15489638,
+11352,
+7041383,
+-11845939,
+5780568,
+11845939,
+3955265,
+16773783,
+-30992347,
+16772092,
+30992347,
+-16768659,
+13953280,
+-24496534,
+12561577,
+24496534,
+-9737641,
+11970921,
+-19931025,
+9602265,
+19931025,
+-4795970,
+10413172,
+-16343421,
+7276820,
+16343421,
+-912775,
+16776368,
+-30995868,
+16773318,
+30995868,
+-16772470,
+16007790,
+-27021343,
+13239901,
+27021343,
+-12470475,
+15365527,
+-23700024,
+10287194,
+23700024,
+-8875505,
+14785947,
+-20702857,
+7622664,
+20702857,
+-5631395,
+16778650,
+-30997821,
+16773150,
+30997821,
+-16774583,
+18157056,
+-28659649,
+12863925,
+28659649,
+-14243764,
+19443806,
+-26476950,
+9214638,
+26476950,
+-11881228,
+20728681,
+-24297433,
+5570671,
+24297433,
+-9522136,
+16781445,
+-30998904,
+16771527,
+30998904,
+-16775756,
+20988060,
+-29656921,
+11112361,
+29656921,
+-15323204,
+25187743,
+-28317150,
+5462520,
+28317150,
+-13873047,
+29672124,
+-26886556,
+-570326,
+26886556,
+-12324582,
+16785752,
+-30999505,
+16767870,
+30999505,
+-16776406,
+25444300,
+-30240545,
+7287830,
+30240545,
+-15954914,
+34434980,
+-29452472,
+-2555854,
+29452472,
+-15101910,
+44441242,
+-28575379,
+-13511474,
+28575379,
+-14152552,
+16793112,
+-30999838,
+16760871,
+30999838,
+-16776767,
+33095506,
+-30574250,
+-2177,
+30574250,
+-16316113,
+50408034,
+-30122291,
+-17803902,
+30122291,
+-15826917,
+70153765,
+-29606811,
+-38107583,
+29606811,
+-15268966,
+16806158,
+-31000023,
+16748025,
+31000023,
+-16776967,
+46670155,
+-30762526,
+-13373037,
+30762526,
+-16519902,
+78789544,
+-30507092,
+-45768905,
+30507092,
+-16243423,
+115942747,
+-30211627,
+-83241918,
+30211627,
+-15923613,
+15872835,
+-22447559,
+15872807,
+22447559,
+-14968426,
+277754,
+-392434,
+277231,
+392434,
+16222231,
+133061,
+-187804,
+132533,
+187804,
+16511622,
+81763,
+-115256,
+81233,
+115256,
+16614220,
+16263303,
+-22999746,
+16263250,
+22999746,
+-15749337,
+494605,
+-698290,
+492927,
+698290,
+15789685,
+238776,
+-336475,
+237071,
+336475,
+16301369,
+147228,
+-207000,
+145514,
+207000,
+16484473,
+16488278,
+-23317877,
+16488181,
+23317877,
+-16199242,
+872378,
+-1229961,
+867049,
+1229961,
+15037788,
+426889,
+-599839,
+421411,
+599839,
+15928916,
+264840,
+-370629,
+259308,
+370629,
+16253068,
+16615785,
+-23498145,
+16615609,
+23498145,
+-16454179,
+1513757,
+-2129016,
+1497126,
+2129016,
+13766333,
+758261,
+-1060001,
+740806,
+1060001,
+15278149,
+475551,
+-659971,
+457789,
+659971,
+15843875,
+16687407,
+-23599332,
+16687089,
+23599332,
+-16597280,
+2557116,
+-3580647,
+2506684,
+3580647,
+11713416,
+1332007,
+-1845009,
+1277230,
+1845009,
+14167979,
+851272,
+-1163942,
+794791,
+1163942,
+15131154,
+16727486,
+-23655830,
+16726910,
+23655830,
+-16677180,
+4144749,
+-5758163,
+3998523,
+5758163,
+8633944,
+2297803,
+-3131069,
+2130198,
+3131069,
+12349216,
+1516025,
+-2019070,
+1339371,
+2019070,
+13921820,
+16749957,
+-23687282,
+16748918,
+23687282,
+-16721660,
+6342807,
+-8688774,
+5944975,
+8688774,
+4489434,
+3855722,
+-5104454,
+3363066,
+5104454,
+9558428,
+2678286,
+-3407564,
+2140738,
+3407564,
+11958192,
+16762736,
+-23704762,
+16760861,
+23704762,
+-16746380,
+9059948,
+-12106014,
+8060542,
+12106014,
+-343274,
+6231959,
+-7847669,
+4866322,
+7847669,
+5678936,
+4678573,
+-5508603,
+3111768,
+5508603,
+8986875,
+16770353,
+-23714468,
+16766970,
+23714468,
+-16760107,
+12100768,
+-15483427,
+9796104,
+15483427,
+-5119656,
+9659401,
+-11180047,
+6151573,
+11180047,
+966242,
+8066003,
+-8371376,
+3772911,
+8371376,
+4938302,
+16775520,
+-23719855,
+16769420,
+23719855,
+-16767725,
+15410647,
+-18317794,
+10494626,
+18317794,
+-9128056,
+14477439,
+-14624233,
+6204350,
+14624233,
+-3904573,
+13754127,
+-11761419,
+2879032,
+11761419,
+144058,
+16780083,
+-23722844,
+16769084,
+23722844,
+-16771951,
+19348947,
+-20387735,
+9483664,
+20387735,
+-12055395,
+21467038,
+-17637855,
+3476656,
+17637855,
+-8166478,
+23369301,
+-15168181,
+-1918253,
+15168181,
+-4673832,
+16785673,
+-23724501,
+16765839,
+23724501,
+-16774296,
+24868547,
+-21750945,
+5891934,
+21750945,
+-13983265,
+32392543,
+-19913847,
+-4230110,
+19913847,
+-11385217,
+39938641,
+-18071353,
+-14381888,
+18071353,
+-8779537,
+16794288,
+-23725421,
+16758525,
+23725421,
+-16775596,
+33739025,
+-22588636,
+-1793870,
+22588636,
+-15167940,
+50727371,
+-21448926,
+-20394010,
+21448926,
+-13556146,
+69082218,
+-20217540,
+-40490298,
+20217540,
+-11814703,
+16809008,
+-23725931,
+16744526,
+23725931,
+-16776318,
+49053594,
+-23081666,
+-16411189,
+23081666,
+-15865189,
+82824296,
+-22406908,
+-51136143,
+22406908,
+-14910937,
+121049915,
+-21643138,
+-90441895,
+21643138,
+-13830803,
+16835099,
+-23726214,
+16718835,
+23726214,
+-16776718,
+76261468,
+-23364505,
+-43219068,
+23364505,
+-16265184,
+140080603,
+-22976059,
+-107587549,
+22976059,
+-15715838,
+214348557,
+-22524014,
+-182494791,
+22524014,
+-15076550,
+15060971,
+0,
+15060916,
+0,
+-13344671,
+137715,
+0,
+137188,
+0,
+16502313,
+62494,
+0,
+61964,
+0,
+16652757,
+35499,
+0,
+34969,
+0,
+16706748,
+15779939,
+0,
+15779837,
+0,
+-14782560,
+247059,
+0,
+245356,
+0,
+16284801,
+112726,
+0,
+111009,
+0,
+16553481,
+64282,
+0,
+62560,
+0,
+16650375,
+16209124,
+0,
+16208934,
+0,
+-15640842,
+441483,
+0,
+436010,
+0,
+15899723,
+203401,
+0,
+197848,
+0,
+16375967,
+116794,
+0,
+111212,
+0,
+16549211,
+16457433,
+0,
+16457085,
+0,
+-16137302,
+783510,
+0,
+766083,
+0,
+15227623,
+367229,
+0,
+349349,
+0,
+16060638,
+213457,
+0,
+195409,
+0,
+16368349,
+16598556,
+0,
+16597923,
+0,
+-16419263,
+1374332,
+0,
+1319705,
+0,
+14083179,
+663683,
+0,
+606536,
+0,
+15506996,
+394077,
+0,
+335974,
+0,
+16047166,
+16678051,
+0,
+16676903,
+0,
+-16577738,
+2365010,
+0,
+2198183,
+0,
+12214023,
+1201479,
+0,
+1021183,
+0,
+14554554,
+739666,
+0,
+554025,
+0,
+15483525,
+16722789,
+0,
+16720714,
+0,
+-16666287,
+3953214,
+0,
+3464275,
+0,
+9359728,
+2180807,
+0,
+1624291,
+0,
+12972118,
+1423936,
+0,
+838564,
+0,
+14514716,
+16748282,
+0,
+16744535,
+0,
+-16715601,
+6353786,
+0,
+5003926,
+0,
+5419504,
+3973108,
+0,
+2314944,
+0,
+10489165,
+2837511,
+0,
+1032284,
+0,
+12907421,
+16763496,
+0,
+16756735,
+0,
+-16743015,
+9775978,
+0,
+6325602,
+0,
+675636,
+7269959,
+0,
+2584558,
+0,
+6922698,
+5878520,
+0,
+507384,
+0,
+10391313,
+16773826,
+0,
+16761629,
+0,
+-16758239,
+14526462,
+0,
+6429723,
+0,
+-4178968,
+13351086,
+0,
+1026117,
+0,
+2400012,
+12566846,
+0,
+-2579306,
+0,
+6789676,
+16782950,
+0,
+16760954,
+0,
+-16766688,
+21346996,
+0,
+3817102,
+0,
+-8386881,
+24548257,
+0,
+-5261828,
+0,
+-2509212,
+27136746,
+0,
+-12602908,
+0,
+2243378,
+16794129,
+0,
+16754463,
+0,
+-16771376,
+31942756,
+0,
+-3625011,
+0,
+-11540529,
+45048673,
+0,
+-21256423,
+0,
+-7015034,
+57646140,
+0,
+-38203817,
+0,
+-2665107,
+16811358,
+0,
+16739835,
+0,
+-16773977,
+49676415,
+0,
+-19243342,
+0,
+-13655857,
+82339984,
+0,
+-55005915,
+0,
+-10556853,
+118287496,
+0,
+-94363999,
+0,
+-7146281,
+16840799,
+0,
+16711837,
+0,
+-16775419,
+80691383,
+0,
+-48942961,
+0,
+-14971206,
+149858505,
+0,
+-120064524,
+0,
+-13016765,
+233520652,
+0,
+-206090695,
+0,
+-10652741,
+16892981,
+0,
+16660455,
+0,
+-16776220,
+136000868,
+0,
+-103472696,
+0,
+-15750956,
+271801469,
+0,
+-240442250,
+0,
+-14582003,
+446309601,
+0,
+-416452524,
+0,
+-13079862,
diff --git a/media/libeffects/AudioShelvingFilter.cpp b/media/libeffects/AudioShelvingFilter.cpp
new file mode 100644
index 0000000..d8abbd2
--- /dev/null
+++ b/media/libeffects/AudioShelvingFilter.cpp
@@ -0,0 +1,109 @@
+/* /android/src/frameworks/base/libs/audioflinger/AudioShelvingFilter.cpp
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "AudioShelvingFilter.h"
+#include "AudioCommon.h"
+#include "EffectsMath.h"
+
+#include <new>
+#include <assert.h>
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+// Format of the coefficient tables:
+// kCoefTable[freq][gain][coef]
+// freq  - cutoff frequency, in octaves below Nyquist,from -10 to -6 in low
+//         shelf, -2 to 0 in high shelf.
+// gain  - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel.
+// coef - 0: b0
+//        1: b1
+//        2: b2
+//        3: -a1
+//        4: -a2
+static const size_t kHiInDims[2] = {3, 15};
+static const audio_coef_t kHiCoefTable[3*15*5] = {
+#include "AudioHighShelfFilterCoef.inl"
+};
+static const size_t kLoInDims[2] = {5, 15};
+static const audio_coef_t kLoCoefTable[5*15*5] = {
+#include "AudioLowShelfFilterCoef.inl"
+};
+
+AudioCoefInterpolator AudioShelvingFilter::mHiCoefInterp(2, kHiInDims, 5, (const audio_coef_t*) kHiCoefTable);
+AudioCoefInterpolator AudioShelvingFilter::mLoCoefInterp(2, kLoInDims, 5, (const audio_coef_t*) kLoCoefTable);
+
+AudioShelvingFilter::AudioShelvingFilter(ShelfType type, int nChannels,
+                                         int sampleRate)
+        : mBiquad(nChannels, sampleRate)
+        , mType(type) {
+    configure(nChannels, sampleRate);
+}
+
+void AudioShelvingFilter::configure(int nChannels, int sampleRate) {
+    mNiquistFreq = sampleRate * 500;
+    mFrequencyFactor = ((1ull) << 42) / mNiquistFreq;
+    mBiquad.configure(nChannels, sampleRate);
+    setFrequency(mNominalFrequency);
+    commit(true);
+}
+
+void AudioShelvingFilter::reset() {
+    setGain(0);
+    setFrequency(mType == kLowShelf ? 0 : mNiquistFreq);
+    commit(true);
+}
+
+void AudioShelvingFilter::setFrequency(uint32_t millihertz) {
+    mNominalFrequency = millihertz;
+    if (UNLIKELY(millihertz > mNiquistFreq / 2)) {
+        millihertz = mNiquistFreq / 2;
+    }
+    uint32_t normFreq = static_cast<uint32_t>(
+            (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10);
+    uint32_t log2minFreq = (mType == kLowShelf ? (32-10) : (32-2));
+    if (LIKELY(normFreq > (1U << log2minFreq))) {
+        mFrequency = (Effects_log2(normFreq) - (log2minFreq << 15)) << (FREQ_PRECISION_BITS - 15);
+    } else {
+        mFrequency = 0;
+    }
+}
+
+void AudioShelvingFilter::setGain(int32_t millibel) {
+    mGain = millibel + 9600;
+}
+
+void AudioShelvingFilter::commit(bool immediate) {
+    audio_coef_t coefs[5];
+    int intCoord[2] = {
+        mFrequency >> FREQ_PRECISION_BITS,
+        mGain >> GAIN_PRECISION_BITS
+    };
+    uint32_t fracCoord[2] = {
+        mFrequency << (32 - FREQ_PRECISION_BITS),
+        static_cast<uint32_t>(mGain) << (32 - GAIN_PRECISION_BITS)
+    };
+    if (mType == kHighShelf) {
+        mHiCoefInterp.getCoef(intCoord, fracCoord, coefs);
+    } else {
+        mLoCoefInterp.getCoef(intCoord, fracCoord, coefs);
+    }
+    mBiquad.setCoefs(coefs, immediate);
+}
+
+}
diff --git a/media/libeffects/AudioShelvingFilter.h b/media/libeffects/AudioShelvingFilter.h
new file mode 100644
index 0000000..f72d793
--- /dev/null
+++ b/media/libeffects/AudioShelvingFilter.h
@@ -0,0 +1,146 @@
+/* /android/src/frameworks/base/libs/audioflinger/AudioShelvingFilter.h
+**
+** Copyright 2009, 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 AUDIO_SHELVING_FILTER_H
+#define AUDIO_SHELVING_FILTER_H
+
+#include "AudioBiquadFilter.h"
+#include "AudioCoefInterpolator.h"
+
+namespace android {
+
+// A shelving audio filter, with unity skirt gain, and controllable cutoff
+// frequency and gain.
+// This filter is able to suppress introduce discontinuities and other artifacts
+// in the output, even when changing parameters abruptly.
+// Parameters can be set to any value - this class will make sure to clip them
+// when they are out of supported range.
+//
+// Implementation notes:
+// This class uses an underlying biquad filter whose parameters are determined
+// using a linear interpolation from a coefficient table, using a
+// AudioCoefInterpolator.
+// All is left for this class to do is mapping between high-level parameters to
+// fractional indices into the coefficient table.
+class AudioShelvingFilter {
+public:
+    // Shelf type
+    enum ShelfType {
+        kLowShelf,
+        kHighShelf
+    };
+
+    // Constructor. Resets the filter (see reset()).
+    // type       Type of the filter (high shelf or low shelf).
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    AudioShelvingFilter(ShelfType type, int nChannels, int sampleRate);
+
+    // Reconfiguration of the filter. Changes input/output format, but does not
+    // alter current parameter values. Clears delay lines.
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    void configure(int nChannels, int sampleRate);
+
+    // Resets the filter parameters to the following values:
+    // frequency: 0
+    // gain: 0
+    // It also disables the filter. Does not clear the delay lines.
+    void reset();
+
+    // Clears delay lines. Does not alter parameter values.
+    void clear() { mBiquad.clear(); }
+
+    // Sets gain value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // millibel Gain value in millibel (1/100 of decibel).
+    void setGain(int32_t millibel);
+
+    // Gets the gain, in millibel, as set.
+    int32_t getGain() const { return mGain - 9600; }
+
+    // Sets cutoff frequency value. Actual change will only take place upon
+    // commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // millihertz Frequency value in mHz.
+    void setFrequency(uint32_t millihertz);
+
+    // Gets the frequency, in mHz, as set.
+    uint32_t getFrequency() const { return mNominalFrequency; }
+
+    // Applies all parameter changes done to this point in time.
+    // If the filter is disabled, the new parameters will take place when it is
+    // enabled again. Does not introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly (ignored if filter is
+    // disabled).
+   void commit(bool immediate = false);
+
+    // Process a buffer of input data. The input and output should contain
+    // frameCount * nChannels interlaced samples. Processing can be done
+    // in-place, by passing the same buffer as both arguments.
+    // in   Input buffer.
+    // out  Output buffer.
+   // frameCount   Number of frames to produce.
+   void process(const audio_sample_t in[], audio_sample_t out[],
+                 int frameCount) { mBiquad.process(in, out, frameCount); }
+
+    // Enables the filter, so it would start processing input. Does not
+    // introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void enable(bool immediate = false) { mBiquad.enable(immediate); }
+
+    // Disabled (bypasses) the filter. Does not introduce artifacts, unless
+    // immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void disable(bool immediate = false) { mBiquad.disable(immediate); }
+
+private:
+    // Precision for the mFrequency member.
+    static const int FREQ_PRECISION_BITS = 26;
+    // Precision for the mGain member.
+    static const int GAIN_PRECISION_BITS = 10;
+
+    // Shelf type.
+    ShelfType mType;
+    // Nyquist, in mHz.
+    uint32_t mNiquistFreq;
+    // Fractional index into the gain dimension of the coef table in
+    // GAIN_PRECISION_BITS precision.
+    int32_t mGain;
+    // Fractional index into the frequency dimension of the coef table in
+    // FREQ_PRECISION_BITS precision.
+    uint32_t mFrequency;
+    // Nominal value of frequency, as set.
+    uint32_t mNominalFrequency;
+   // 1/Nyquist[mHz], in 42-bit precision (very small).
+    // Used for scaling the frequency.
+    uint32_t mFrequencyFactor;
+
+    // A biquad filter, used for the actual processing.
+    AudioBiquadFilter mBiquad;
+    // A coefficient interpolator, used for mapping the high level parameters to
+    // the low-level biquad coefficients. This one is used for the high shelf.
+    static AudioCoefInterpolator mHiCoefInterp;
+    // A coefficient interpolator, used for mapping the high level parameters to
+    // the low-level biquad coefficients. This one is used for the low shelf.
+    static AudioCoefInterpolator mLoCoefInterp;
+};
+
+}
+
+
+#endif // AUDIO_SHELVING_FILTER_H
diff --git a/media/libeffects/EffectEqualizer.cpp b/media/libeffects/EffectEqualizer.cpp
new file mode 100644
index 0000000..3a5da4d
--- /dev/null
+++ b/media/libeffects/EffectEqualizer.cpp
@@ -0,0 +1,605 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Equalizer"
+#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+//#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <new>
+#include "AudioEqualizer.h"
+#include "AudioBiquadFilter.h"
+#include "AudioFormatAdapter.h"
+#include <media/EffectEqualizerApi.h>
+
+// effect_interface_t interface implementation for equalizer effect
+extern "C" const struct effect_interface_s gEqualizerInterface;
+
+namespace android {
+namespace {
+
+// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b
+const effect_descriptor_t gEqualizerDescriptor = {
+        {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+        {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+        EFFECT_API_VERSION,
+        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
+        "Graphic Equalizer",
+        "Google Inc.",
+};
+static int gEffectIndex;
+
+/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
+const int kNumBands = 5;
+const uint32_t gFreqs[kNumBands] =      { 50000, 125000, 900000, 3200000, 6300000 };
+const uint32_t gBandwidths[kNumBands] = { 0,     3600,   3600,   2400,    0       };
+
+const AudioEqualizer::BandConfig gBandsClassic[kNumBands] = {
+    { 300,  gFreqs[0], gBandwidths[0] },
+    { 400,  gFreqs[1], gBandwidths[1] },
+    { 0,    gFreqs[2], gBandwidths[2] },
+    { 200,  gFreqs[3], gBandwidths[3] },
+    { -300, gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::BandConfig gBandsJazz[kNumBands] = {
+    { -600, gFreqs[0], gBandwidths[0] },
+    { 200,  gFreqs[1], gBandwidths[1] },
+    { 400,  gFreqs[2], gBandwidths[2] },
+    { -400, gFreqs[3], gBandwidths[3] },
+    { -600, gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::BandConfig gBandsPop[kNumBands] = {
+    { 400,  gFreqs[0], gBandwidths[0] },
+    { -400, gFreqs[1], gBandwidths[1] },
+    { 300,  gFreqs[2], gBandwidths[2] },
+    { -400, gFreqs[3], gBandwidths[3] },
+    { 600,  gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::BandConfig gBandsRock[kNumBands] = {
+    { 700,  gFreqs[0], gBandwidths[0] },
+    { 400,  gFreqs[1], gBandwidths[1] },
+    { -400, gFreqs[2], gBandwidths[2] },
+    { 400,  gFreqs[3], gBandwidths[3] },
+    { 200,  gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::PresetConfig gEqualizerPresets[] = {
+    { "Classic", gBandsClassic },
+    { "Jazz",    gBandsJazz    },
+    { "Pop",     gBandsPop     },
+    { "Rock",    gBandsRock    }
+};
+
+/////////////////// END EQ PRESETS /////////////////////////////////////////////
+
+static const size_t kBufferSize = 32;
+
+typedef AudioFormatAdapter<AudioEqualizer, kBufferSize> FormatAdapter;
+
+struct EqualizerContext {
+    const struct effect_interface_s *itfe;
+    effect_config_t config;
+    FormatAdapter adapter;
+    AudioEqualizer * pEqualizer;
+};
+
+
+//--- local function prototypes
+
+int Equalizer_init(EqualizerContext *pContext);
+int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig);
+int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue);
+int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
+
+
+//
+//--- Effect Library Interface Implementation
+//
+
+extern "C" int EffectQueryNumberEffects(int *pNumEffects) {
+    *pNumEffects = 1;
+    gEffectIndex = 0;
+    return 0;
+} /* end EffectQueryNumberEffects */
+
+extern "C" int EffectQueryNext(effect_descriptor_t *pDescriptor) {
+    if (pDescriptor == NULL) {
+        return -EINVAL;
+    }
+    if (gEffectIndex++ > 0) {
+        return -ENOENT;
+    }
+    memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
+    return 0;
+} /* end EffectQueryNext */
+
+extern "C" int EffectCreate(effect_uuid_t *uuid,
+        effect_interface_t *pInterface) {
+    int ret;
+    int i;
+
+    LOGV("EffectLibCreateEffect start");
+
+    if (pInterface == NULL || uuid == NULL) {
+        return -EINVAL;
+    }
+
+    if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
+        return -EINVAL;
+    }
+
+    EqualizerContext *pContext = new EqualizerContext;
+
+    pContext->itfe = &gEqualizerInterface;
+    pContext->pEqualizer = NULL;
+
+    ret = Equalizer_init(pContext);
+    if (ret < 0) {
+        LOGW("EffectLibCreateEffect() init failed");
+        delete pContext;
+        return ret;
+    }
+
+    *pInterface = (effect_interface_t)pContext;
+
+    LOGV("EffectLibCreateEffect %p", pContext);
+
+    return 0;
+
+} /* end EffectCreate */
+
+extern "C" int EffectRelease(effect_interface_t interface) {
+    EqualizerContext * pContext = (EqualizerContext *)interface;
+
+    LOGV("EffectLibReleaseEffect %p", interface);
+    if (pContext == NULL) {
+        return -EINVAL;
+    }
+
+    pContext->pEqualizer->free();
+    delete pContext;
+
+    return 0;
+} /* end EffectRelease */
+
+
+//
+//--- local functions
+//
+
+#define CHECK_ARG(cond) {                     \
+    if (!(cond)) {                            \
+        LOGV("Invalid argument: "#cond);      \
+        return -EINVAL;                       \
+    }                                         \
+}
+
+//----------------------------------------------------------------------------
+// Equalizer_configure()
+//----------------------------------------------------------------------------
+// Purpose: Set input and output audio configuration.
+//
+// Inputs:
+//  pContext:   effect engine context
+//  pConfig:    pointer to effect_config_t structure holding input and output
+//      configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig)
+{
+    LOGV("Equalizer_configure start");
+
+    CHECK_ARG(pContext != NULL);
+    CHECK_ARG(pConfig != NULL);
+
+    CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
+    CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
+    CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+    CHECK_ARG((pConfig->inputCfg.channels == CHANNEL_MONO) || (pConfig->inputCfg.channels == CHANNEL_STEREO));
+    CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
+              || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+    CHECK_ARG(pConfig->inputCfg.format == PCM_FORMAT_S7_24
+              || pConfig->inputCfg.format == PCM_FORMAT_S15);
+
+    int channelCount;
+    if (pConfig->inputCfg.channels == CHANNEL_MONO) {
+        channelCount = 1;
+    } else {
+        channelCount = 2;
+    }
+    CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
+
+    pContext->pEqualizer->configure(channelCount,
+                          pConfig->inputCfg.samplingRate);
+
+    pContext->adapter.configure(*pContext->pEqualizer, channelCount,
+                        pConfig->inputCfg.format,
+                        pConfig->outputCfg.accessMode);
+
+    return 0;
+}   // end Equalizer_configure
+
+
+//----------------------------------------------------------------------------
+// Equalizer_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration and creates
+//     AudioEqualizer instance.
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_init(EqualizerContext *pContext)
+{
+    int status;
+
+    LOGV("Equalizer_init start");
+
+    CHECK_ARG(pContext != NULL);
+
+    if (pContext->pEqualizer != NULL) {
+        pContext->pEqualizer->free();
+    }
+
+    pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+    pContext->config.inputCfg.channels = CHANNEL_STEREO;
+    pContext->config.inputCfg.format = PCM_FORMAT_S15;
+    pContext->config.inputCfg.samplingRate = 44100;
+    pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
+    pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+    pContext->config.inputCfg.bufferProvider.cookie = NULL;
+    pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+    pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+    pContext->config.outputCfg.channels = CHANNEL_STEREO;
+    pContext->config.outputCfg.format = PCM_FORMAT_S15;
+    pContext->config.outputCfg.samplingRate = 44100;
+    pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
+    pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+    pContext->config.outputCfg.bufferProvider.cookie = NULL;
+    pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+    pContext->pEqualizer = AudioEqualizer::CreateInstance(
+        NULL,
+        kNumBands,
+        AudioBiquadFilter::MAX_CHANNELS,
+        44100,
+        gEqualizerPresets,
+        ARRAY_SIZE(gEqualizerPresets));
+
+    for (int i = 0; i < kNumBands; ++i) {
+        pContext->pEqualizer->setFrequency(i, gFreqs[i]);
+        pContext->pEqualizer->setBandwidth(i, gBandwidths[i]);
+    }
+
+    pContext->pEqualizer->enable(true);
+
+    Equalizer_configure(pContext, &pContext->config);
+
+    return 0;
+}   // end Equalizer_init
+
+
+//----------------------------------------------------------------------------
+// Equalizer_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Equalizer parameter
+//
+// Inputs:
+//  pEqualizer       - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to variable to hold retrieved value
+//  pValueSize       - pointer to value size: maximum size as input
+//
+// Outputs:
+//  *pValue updated with parameter value
+//  *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue)
+{
+    int status = 0;
+    int32_t param = *pParam++;
+    int32_t param2;
+    char *name;
+
+    switch (param) {
+    case EQ_PARAM_NUM_BANDS:
+    case EQ_PARAM_CUR_PRESET:
+    case EQ_PARAM_GET_NUM_OF_PRESETS:
+        if (*pValueSize < sizeof(int16_t)) {
+            return -EINVAL;
+        }
+        *pValueSize = sizeof(int16_t);
+        break;
+
+    case EQ_PARAM_LEVEL_RANGE:
+    case EQ_PARAM_BAND_FREQ_RANGE:
+        if (*pValueSize < 2 * sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        *pValueSize = 2 * sizeof(int32_t);
+        break;
+    case EQ_PARAM_BAND_LEVEL:
+    case EQ_PARAM_GET_BAND:
+    case EQ_PARAM_CENTER_FREQ:
+        if (*pValueSize < sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        *pValueSize = sizeof(int32_t);
+        break;
+
+    case EQ_PARAM_GET_PRESET_NAME:
+        break;
+
+    default:
+        return -EINVAL;
+    }
+
+    switch (param) {
+    case EQ_PARAM_NUM_BANDS:
+        *(int16_t *)pValue = kNumBands;
+        LOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
+        break;
+
+    case EQ_PARAM_LEVEL_RANGE:
+        *(int32_t *)pValue = -9600;
+        *((int32_t *)pValue + 1) = 4800;
+        LOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d", *(int32_t *)pValue, *((int32_t *)pValue + 1));
+        break;
+
+    case EQ_PARAM_BAND_LEVEL:
+        param2 = *pParam;
+        if (param2 >= kNumBands) {
+            status = -EINVAL;
+            break;
+        }
+        *(int32_t *)pValue = pEqualizer->getGain(param2);
+        LOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", param2, *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_CENTER_FREQ:
+        param2 = *pParam;
+        if (param2 >= kNumBands) {
+            status = -EINVAL;
+            break;
+        }
+        *(int32_t *)pValue = pEqualizer->getFrequency(param2);
+        LOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d", param2, *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_BAND_FREQ_RANGE:
+        param2 = *pParam;
+        if (param2 >= kNumBands) {
+            status = -EINVAL;
+            break;
+        }
+        pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1));
+        LOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d", param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
+        break;
+
+    case EQ_PARAM_GET_BAND:
+        param2 = *pParam;
+        *(int32_t *)pValue = pEqualizer->getMostRelevantBand(param2);
+        LOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d", param2, *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_CUR_PRESET:
+        *(int16_t *)pValue = pEqualizer->getPreset();
+        LOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_GET_NUM_OF_PRESETS:
+        *(int16_t *)pValue = pEqualizer->getNumPresets();
+        LOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
+        break;
+
+    case EQ_PARAM_GET_PRESET_NAME:
+        param2 = *pParam;
+        if (param2 >= pEqualizer->getNumPresets()) {
+            status = -EINVAL;
+            break;
+        }
+        name = (char *)pValue;
+        strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1);
+        name[*pValueSize - 1] = 0;
+        *pValueSize = strlen(name) + 1;
+        LOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d", param2, gEqualizerPresets[param2].name, *pValueSize);
+        break;
+
+    default:
+        LOGV("Equalizer_getParameter() invalid param %d", param);
+        status = -EINVAL;
+        break;
+    }
+
+    return status;
+} // end Equalizer_getParameter
+
+
+//----------------------------------------------------------------------------
+// Equalizer_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Equalizer parameter
+//
+// Inputs:
+//  pEqualizer       - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to value
+//
+// Outputs:
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue)
+{
+    int status = 0;
+    int32_t preset;
+    int32_t band;
+    int32_t level;
+    int32_t param = *pParam++;
+
+
+    switch (param) {
+    case EQ_PARAM_CUR_PRESET:
+        preset = *(int16_t *)pValue;
+
+        LOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
+        if (preset >= pEqualizer->getNumPresets()) {
+            status = -EINVAL;
+            break;
+        }
+        pEqualizer->setPreset(preset);
+        pEqualizer->commit(true);
+        break;
+    case EQ_PARAM_BAND_LEVEL:
+        band =  *pParam;
+        level = *(int32_t *)pValue;
+        LOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
+        if (band >= kNumBands) {
+            status = -EINVAL;
+            break;
+        }
+        pEqualizer->setGain(band, level);
+        pEqualizer->commit(true);
+       break;
+    default:
+        LOGV("setParameter() invalid param %d", param);
+        break;
+    }
+
+    return status;
+} // end Equalizer_setParameter
+
+} // namespace
+} // namespace
+
+
+//
+//--- Effect Control Interface Implementation
+//
+
+extern "C" int Equalizer_process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
+
+    if (pContext == NULL) {
+        return -EINVAL;
+    }
+    if (inBuffer == NULL || inBuffer->raw == NULL ||
+        outBuffer == NULL || outBuffer->raw == NULL ||
+        inBuffer->frameCount != outBuffer->frameCount) {
+        return -EINVAL;
+    }
+
+    pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
+    return 0;
+}   // end Equalizer_process
+
+extern "C" int Equalizer_command(effect_interface_t self, int cmdCode, int cmdSize,
+        void *pCmdData, int *replySize, void *pReplyData) {
+
+    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
+    int retsize;
+
+    if (pContext == NULL) {
+        return -EINVAL;
+    }
+
+    android::AudioEqualizer * pEqualizer = pContext->pEqualizer;
+
+    LOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize);
+
+    switch (cmdCode) {
+    case EFFECT_CMD_INIT:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Equalizer_init(pContext);
+        break;
+    case EFFECT_CMD_CONFIGURE:
+        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+                || pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Equalizer_configure(pContext,
+                (effect_config_t *) pCmdData);
+        break;
+    case EFFECT_CMD_RESET:
+        Equalizer_configure(pContext, &pContext->config);
+        break;
+    case EFFECT_CMD_GET_PARAM: {
+        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+            pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
+            return -EINVAL;
+        }
+        effect_param_t *p = (effect_param_t *)pCmdData;
+        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+        p = (effect_param_t *)pReplyData;
+        int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+        p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize,
+                p->data + voffset);
+        *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+        LOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x",
+                *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
+                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
+                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t)));
+
+        } break;
+    case EFFECT_CMD_SET_PARAM: {
+        LOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
+        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+            pReplyData == NULL || *replySize != sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        effect_param_t *p = (effect_param_t *) pCmdData;
+        *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
+                p->data + p->psize);
+        } break;
+    default:
+        LOGW("Equalizer_command invalid command %d",cmdCode);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+// effect_interface_t interface implementation for equalizer effect
+const struct effect_interface_s gEqualizerInterface = {
+        Equalizer_process,
+        Equalizer_command
+};
+
+
diff --git a/media/libeffects/EffectReverb.c b/media/libeffects/EffectReverb.c
new file mode 100644
index 0000000..3181504
--- /dev/null
+++ b/media/libeffects/EffectReverb.c
@@ -0,0 +1,2034 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectReverb"
+//
+#define LOG_NDEBUG 0
+#include <cutils/log.h>
+
+#include <stdbool.h>
+#include "EffectReverb.h"
+#include "EffectsMath.h"
+
+static int gEffectIndex;
+
+// effect_interface_t interface implementation for reverb effect
+const struct effect_interface_s gReverbInterface = {
+        Reverb_Process,
+        Reverb_Command
+};
+
+// Google auxiliary environmental reverb UUID: 1f0ae2e0-4ef7-11df-bc09-0002a5d5c51b
+static const effect_descriptor_t gAuxEnvReverbDescriptor = {
+        {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
+        {0x1f0ae2e0, 0x4ef7, 0x11df, 0xbc09, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_AUXILIARY,
+        "Aux Environmental Reverb",
+        "Google Inc."
+};
+
+// Google insert environmental reverb UUID: aa476040-6342-11df-91a4-0002a5d5c51b
+static const effect_descriptor_t gInsertEnvReverbDescriptor = {
+        {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
+        {0xaa476040, 0x6342, 0x11df, 0x91a4, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+        "Insert Environmental reverb",
+        "Google Inc."
+};
+
+// Google auxiliary preset reverb UUID: 63909320-53a6-11df-bdbd-0002a5d5c51b
+static const effect_descriptor_t gAuxPresetReverbDescriptor = {
+        {0x47382d60, 0xddd8, 0x4763, 0x11db, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        {0x63909320, 0x53a6, 0x11df, 0xbdbd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_AUXILIARY,
+        "Aux Preset Reverb",
+        "Google Inc."
+};
+
+// Google insert preset reverb UUID: d93dc6a0-6342-11df-b128-0002a5d5c51b
+static const effect_descriptor_t gInsertPresetReverbDescriptor = {
+        {0x47382d60, 0xddd8, 0x4763, 0x11db, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        {0xd93dc6a0, 0x6342, 0x11df, 0xb128, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+        "Insert Preset Reverb",
+        "Google Inc."
+};
+
+// gDescriptors contains pointers to all defined effect descriptor in this library
+static const effect_descriptor_t * const gDescriptors[] = {
+        &gAuxEnvReverbDescriptor,
+        &gInsertEnvReverbDescriptor,
+        &gAuxPresetReverbDescriptor,
+        &gInsertPresetReverbDescriptor,
+        NULL
+};
+
+/*----------------------------------------------------------------------------
+ * Effect API implementation
+ *--------------------------------------------------------------------------*/
+
+/*--- Effect Library Interface Implementation ---*/
+
+int EffectQueryNumberEffects(int *pNumEffects) {
+    *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)
+            - 1;
+    gEffectIndex = 0;
+    return 0;
+}
+
+int EffectQueryNext(effect_descriptor_t *pDescriptor) {
+    if (pDescriptor == NULL) {
+        return -EINVAL;
+    }
+    if (gDescriptors[gEffectIndex] == NULL) {
+        return -ENOENT;
+    }
+    memcpy(pDescriptor, gDescriptors[gEffectIndex++],
+            sizeof(effect_descriptor_t));
+    return 0;
+}
+
+int EffectCreate(effect_uuid_t *uuid,
+        effect_interface_t *pInterface) {
+    int ret;
+    int i;
+    reverb_module_t *module;
+    const effect_descriptor_t *desc;
+    int aux = 0;
+    int preset = 0;
+
+    LOGV("EffectLibCreateEffect start");
+
+    if (pInterface == NULL || uuid == NULL) {
+        return -EINVAL;
+    }
+
+    for (i = 0; gDescriptors[i] != NULL; i++) {
+        desc = gDescriptors[i];
+        if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t))
+                == 0) {
+            break;
+        }
+    }
+
+    if (gDescriptors[i] == NULL) {
+        return -ENOENT;
+    }
+
+    module = malloc(sizeof(reverb_module_t));
+
+    module->itfe = &gReverbInterface;
+
+    if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
+        preset = 1;
+    }
+    if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+        aux = 1;
+    }
+    ret = Reverb_Init(module, aux, preset);
+    if (ret < 0) {
+        LOGW("EffectLibCreateEffect() init failed");
+        free(module);
+        return ret;
+    }
+
+    *pInterface = (effect_interface_t) module;
+
+    LOGV("EffectLibCreateEffect %p", module);
+
+    return 0;
+}
+
+int EffectRelease(effect_interface_t interface) {
+    reverb_module_t *pRvbModule = (reverb_module_t *)interface;
+
+    LOGV("EffectLibReleaseEffect %p", interface);
+    if (interface == NULL) {
+        return -EINVAL;
+    }
+
+    free(pRvbModule);
+    return 0;
+}
+
+
+/*--- Effect Control Interface Implementation ---*/
+
+static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+    reverb_object_t *pReverb;
+    int16_t *pSrc, *pDst;
+    reverb_module_t *pRvbModule = (reverb_module_t *)self;
+
+    if (pRvbModule == NULL) {
+        return -EINVAL;
+    }
+
+    if (inBuffer == NULL || inBuffer->raw == NULL ||
+        outBuffer == NULL || outBuffer->raw == NULL ||
+        inBuffer->frameCount != outBuffer->frameCount) {
+        return -EINVAL;
+    }
+
+    pReverb = (reverb_object_t*) &pRvbModule->context;
+
+    //if bypassed or the preset forces the signal to be completely dry
+    if (pReverb->m_bBypass) {
+        if (inBuffer->raw != outBuffer->raw && !pReverb->m_Aux) {
+            memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount * NUM_OUTPUT_CHANNELS * sizeof(int16_t));
+        }
+        return 0;
+    }
+
+    if (pReverb->m_nNextRoom != pReverb->m_nCurrentRoom) {
+        ReverbUpdateRoom(pReverb, true);
+    }
+
+    pSrc = inBuffer->s16;
+    pDst = outBuffer->s16;
+    size_t numSamples = outBuffer->frameCount;
+    while (numSamples) {
+        uint32_t processedSamples;
+        if (numSamples > (uint32_t) pReverb->m_nUpdatePeriodInSamples) {
+            processedSamples = (uint32_t) pReverb->m_nUpdatePeriodInSamples;
+        } else {
+            processedSamples = numSamples;
+        }
+
+        /* increment update counter */
+        pReverb->m_nUpdateCounter += (int16_t) processedSamples;
+        /* check if update counter needs to be reset */
+        if (pReverb->m_nUpdateCounter >= pReverb->m_nUpdatePeriodInSamples) {
+            /* update interval has elapsed, so reset counter */
+            pReverb->m_nUpdateCounter -= pReverb->m_nUpdatePeriodInSamples;
+            ReverbUpdateXfade(pReverb, pReverb->m_nUpdatePeriodInSamples);
+
+        } /* end if m_nUpdateCounter >= update interval */
+
+        Reverb(pReverb, processedSamples, pDst, pSrc);
+
+        numSamples -= processedSamples;
+        if (pReverb->m_Aux) {
+            pDst += processedSamples;
+        } else {
+            pSrc += processedSamples * NUM_OUTPUT_CHANNELS;
+        }
+    }
+
+    return 0;
+}
+
+static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize,
+        void *pCmdData, int *replySize, void *pReplyData) {
+    reverb_module_t *pRvbModule = (reverb_module_t *) self;
+    reverb_object_t *pReverb;
+    int retsize;
+
+    if (pRvbModule == NULL) {
+        return -EINVAL;
+    }
+
+    pReverb = (reverb_object_t*) &pRvbModule->context;
+
+    LOGV("Reverb_Command command %d cmdSize %d",cmdCode, cmdSize);
+
+    switch (cmdCode) {
+    case EFFECT_CMD_INIT:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Reverb_Init(pRvbModule, pReverb->m_Aux, pReverb->m_Preset);
+        break;
+    case EFFECT_CMD_CONFIGURE:
+        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+                || pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Reverb_Configure(pRvbModule,
+                (effect_config_t *)pCmdData, false);
+        break;
+    case EFFECT_CMD_RESET:
+        Reverb_Reset(pReverb, false);
+        break;
+    case EFFECT_CMD_GET_PARAM:
+        LOGV("Reverb_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p",pCmdData, *replySize, pReplyData);
+
+        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+            pReplyData == NULL || *replySize < (int) sizeof(effect_param_t)) {
+            return -EINVAL;
+        }
+        effect_param_t *rep = (effect_param_t *) pReplyData;
+        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t));
+        LOGV("Reverb_Command EFFECT_CMD_GET_PARAM param %d, replySize %d",*(int32_t *)rep->data, rep->vsize);
+        rep->status = Reverb_getParameter(pReverb, *(int32_t *)rep->data, &rep->vsize,
+                rep->data + sizeof(int32_t));
+        *replySize = sizeof(effect_param_t) + sizeof(int32_t) + rep->vsize;
+        break;
+    case EFFECT_CMD_SET_PARAM:
+        LOGV("Reverb_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
+                cmdSize, pCmdData, *replySize, pReplyData);
+        if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
+                || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        effect_param_t *cmd = (effect_param_t *) pCmdData;
+        *(int *)pReplyData = Reverb_setParameter(pReverb, *(int32_t *)cmd->data,
+                cmd->vsize, cmd->data + sizeof(int32_t));
+        break;
+    default:
+        LOGW("Reverb_Command invalid command %d",cmdCode);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Reverb internal functions
+ *--------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Reverb_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initialize reverb context and apply default parameters
+ *
+ * Inputs:
+ *  pRvbModule    - pointer to reverb effect module
+ *  aux           - indicates if the reverb is used as auxiliary (1) or insert (0)
+ *  preset        - indicates if the reverb is used in preset (1) or environmental (0) mode
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset) {
+    int ret;
+
+    LOGV("Reverb_Init module %p, aux: %d, preset: %d", pRvbModule,aux, preset);
+
+    memset(&pRvbModule->context, 0, sizeof(reverb_object_t));
+
+    pRvbModule->context.m_Aux = (uint16_t)aux;
+    pRvbModule->context.m_Preset = (uint16_t)preset;
+
+    pRvbModule->config.inputCfg.samplingRate = 44100;
+    if (aux) {
+        pRvbModule->config.inputCfg.channels = CHANNEL_MONO;
+    } else {
+        pRvbModule->config.inputCfg.channels = CHANNEL_STEREO;
+    }
+    pRvbModule->config.inputCfg.format = PCM_FORMAT_S15;
+    pRvbModule->config.inputCfg.bufferProvider.getBuffer = NULL;
+    pRvbModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+    pRvbModule->config.inputCfg.bufferProvider.cookie = NULL;
+    pRvbModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+    pRvbModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+    pRvbModule->config.outputCfg.samplingRate = 44100;
+    pRvbModule->config.outputCfg.channels = CHANNEL_STEREO;
+    pRvbModule->config.outputCfg.format = PCM_FORMAT_S15;
+    pRvbModule->config.outputCfg.bufferProvider.getBuffer = NULL;
+    pRvbModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+    pRvbModule->config.outputCfg.bufferProvider.cookie = NULL;
+    pRvbModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+    pRvbModule->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+    ret = Reverb_Configure(pRvbModule, &pRvbModule->config, true);
+    if (ret < 0) {
+        LOGV("Reverb_Init error %d on module %p", ret, pRvbModule);
+    }
+
+    return ret;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *  Set input and output audio configuration.
+ *
+ * Inputs:
+ *  pRvbModule    - pointer to reverb effect module
+ *  pConfig       - pointer to effect_config_t structure containing input
+ *              and output audio parameters configuration
+ *  init          - true if called from init function
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig,
+        bool init) {
+    reverb_object_t *pReverb = &pRvbModule->context;
+    int bufferSizeInSamples;
+    int updatePeriodInSamples;
+    int xfadePeriodInSamples;
+
+    // Check configuration compatibility with build options
+    if (pConfig->inputCfg.samplingRate
+        != pConfig->outputCfg.samplingRate
+        || pConfig->outputCfg.channels != OUTPUT_CHANNELS
+        || pConfig->inputCfg.format != PCM_FORMAT_S15
+        || pConfig->outputCfg.format != PCM_FORMAT_S15) {
+        LOGV("Reverb_Configure invalid config");
+        return -EINVAL;
+    }
+    if ((pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_MONO)) ||
+        (!pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_STEREO))) {
+        LOGV("Reverb_Configure invalid config");
+        return -EINVAL;
+    }
+
+    memcpy(&pRvbModule->config, pConfig, sizeof(effect_config_t));
+
+    pReverb->m_nSamplingRate = pRvbModule->config.outputCfg.samplingRate;
+
+    switch (pReverb->m_nSamplingRate) {
+    case 8000:
+        pReverb->m_nUpdatePeriodInBits = 5;
+        bufferSizeInSamples = 4096;
+        pReverb->m_nCosWT_5KHz = -23170;
+        break;
+    case 16000:
+        pReverb->m_nUpdatePeriodInBits = 6;
+        bufferSizeInSamples = 8192;
+        pReverb->m_nCosWT_5KHz = -12540;
+        break;
+    case 22050:
+        pReverb->m_nUpdatePeriodInBits = 7;
+        bufferSizeInSamples = 8192;
+        pReverb->m_nCosWT_5KHz = 4768;
+        break;
+    case 32000:
+        pReverb->m_nUpdatePeriodInBits = 7;
+        bufferSizeInSamples = 16384;
+        pReverb->m_nCosWT_5KHz = 18205;
+        break;
+    case 44100:
+        pReverb->m_nUpdatePeriodInBits = 8;
+        bufferSizeInSamples = 16384;
+        pReverb->m_nCosWT_5KHz = 24799;
+        break;
+    case 48000:
+        pReverb->m_nUpdatePeriodInBits = 8;
+        bufferSizeInSamples = 16384;
+        pReverb->m_nCosWT_5KHz = 25997;
+        break;
+    default:
+        LOGV("Reverb_Configure invalid sampling rate %d", pReverb->m_nSamplingRate);
+        return -EINVAL;
+    }
+
+    // Define a mask for circular addressing, so that array index
+    // can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1)
+    // The buffer size MUST be a power of two
+    pReverb->m_nBufferMask = (int32_t) (bufferSizeInSamples - 1);
+    /* reverb parameters are updated every 2^(pReverb->m_nUpdatePeriodInBits) samples */
+    updatePeriodInSamples = (int32_t) (0x1L << pReverb->m_nUpdatePeriodInBits);
+    /*
+     calculate the update counter by bitwise ANDING with this value to
+     generate a 2^n modulo value
+     */
+    pReverb->m_nUpdatePeriodInSamples = (int32_t) updatePeriodInSamples;
+
+    xfadePeriodInSamples = (int32_t) (REVERB_XFADE_PERIOD_IN_SECONDS
+            * (double) pReverb->m_nSamplingRate);
+
+    // set xfade parameters
+    pReverb->m_nPhaseIncrement
+            = (int16_t) (65536 / ((int16_t) xfadePeriodInSamples
+                    / (int16_t) updatePeriodInSamples));
+
+    if (init) {
+        ReverbReadInPresets(pReverb);
+
+        // for debugging purposes, allow noise generator
+        pReverb->m_bUseNoise = true;
+
+        // for debugging purposes, allow bypass
+        pReverb->m_bBypass = false;
+
+        pReverb->m_nNextRoom = 1;
+
+        pReverb->m_nNoise = (int16_t) 0xABCD;
+    }
+
+    Reverb_Reset(pReverb, init);
+
+    return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *  Reset internal states and clear delay lines.
+ *
+ * Inputs:
+ *  pReverb    - pointer to reverb context
+ *  init       - true if called from init function
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void Reverb_Reset(reverb_object_t *pReverb, bool init) {
+    int bufferSizeInSamples = (int32_t) (pReverb->m_nBufferMask + 1);
+    int maxApSamples;
+    int maxDelaySamples;
+    int maxEarlySamples;
+    int ap1In;
+    int delay0In;
+    int delay1In;
+    int32_t i;
+    uint16_t nOffset;
+
+    maxApSamples = ((int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16);
+    maxDelaySamples = ((int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
+            >> 16);
+    maxEarlySamples = ((int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
+            >> 16);
+
+    ap1In = (AP0_IN + maxApSamples + GUARD);
+    delay0In = (ap1In + maxApSamples + GUARD);
+    delay1In = (delay0In + maxDelaySamples + GUARD);
+    // Define the max offsets for the end points of each section
+    // i.e., we don't expect a given section's taps to go beyond
+    // the following limits
+
+    pReverb->m_nEarly0in = (delay1In + maxDelaySamples + GUARD);
+    pReverb->m_nEarly1in = (pReverb->m_nEarly0in + maxEarlySamples + GUARD);
+
+    pReverb->m_sAp0.m_zApIn = AP0_IN;
+
+    pReverb->m_zD0In = delay0In;
+
+    pReverb->m_sAp1.m_zApIn = ap1In;
+
+    pReverb->m_zD1In = delay1In;
+
+    pReverb->m_zOutLpfL = 0;
+    pReverb->m_zOutLpfR = 0;
+
+    pReverb->m_nRevFbkR = 0;
+    pReverb->m_nRevFbkL = 0;
+
+    // set base index into circular buffer
+    pReverb->m_nBaseIndex = 0;
+
+    // clear the reverb delay line
+    for (i = 0; i < bufferSizeInSamples; i++) {
+        pReverb->m_nDelayLine[i] = 0;
+    }
+
+    ReverbUpdateRoom(pReverb, init);
+
+    pReverb->m_nUpdateCounter = 0;
+
+    pReverb->m_nPhase = -32768;
+
+    pReverb->m_nSin = 0;
+    pReverb->m_nCos = 0;
+    pReverb->m_nSinIncrement = 0;
+    pReverb->m_nCosIncrement = 0;
+
+    // set delay tap lengths
+    nOffset = ReverbCalculateNoise(pReverb);
+
+    pReverb->m_zD1Cross = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
+            + nOffset;
+
+    nOffset = ReverbCalculateNoise(pReverb);
+
+    pReverb->m_zD0Cross = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
+            - nOffset;
+
+    nOffset = ReverbCalculateNoise(pReverb);
+
+    pReverb->m_zD0Self = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
+            - nOffset;
+
+    nOffset = ReverbCalculateNoise(pReverb);
+
+    pReverb->m_zD1Self = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
+            + nOffset;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_getParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Get a Reverb parameter
+ *
+ * Inputs:
+ *  pReverb       - handle to instance data
+ *  param         - parameter
+ *  pValue        - pointer to variable to hold retrieved value
+ *  pSize         - pointer to value size: maximum size as input
+ *
+ * Outputs:
+ *  *pValue updated with parameter value
+ *  *pSize updated with actual value size
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize,
+        void *pValue) {
+    int32_t *pValue32;
+    int16_t *pValue16;
+    t_reverb_properties *pProperties;
+    int32_t i;
+    int32_t temp;
+    int32_t temp2;
+    size_t size;
+
+    if (pReverb->m_Preset && param != REVERB_PARAM_PRESET) {
+        return -EINVAL;
+    }
+    if (!pReverb->m_Preset && param == REVERB_PARAM_PRESET) {
+        return -EINVAL;
+    }
+
+    switch (param) {
+    case REVERB_PARAM_ROOM_LEVEL:
+    case REVERB_PARAM_ROOM_HF_LEVEL:
+    case REVERB_PARAM_DECAY_HF_RATIO:
+    case REVERB_PARAM_REFLECTIONS_LEVEL:
+    case REVERB_PARAM_REVERB_LEVEL:
+    case REVERB_PARAM_DIFFUSION:
+    case REVERB_PARAM_DENSITY:
+        size = sizeof(int16_t);
+        break;
+
+    case REVERB_PARAM_BYPASS:
+    case REVERB_PARAM_PRESET:
+    case REVERB_PARAM_DECAY_TIME:
+    case REVERB_PARAM_REFLECTIONS_DELAY:
+    case REVERB_PARAM_REVERB_DELAY:
+        size = sizeof(int32_t);
+        break;
+
+    case REVERB_PARAM_PROPERTIES:
+        size = sizeof(t_reverb_properties);
+        break;
+
+    default:
+        return -EINVAL;
+    }
+
+    if (*pSize < size) {
+        return -EINVAL;
+    }
+    *pSize = size;
+    pValue32 = (int32_t *) pValue;
+    pValue16 = (int16_t *) pValue;
+    pProperties = (t_reverb_properties *) pValue;
+
+    switch (param) {
+    case REVERB_PARAM_BYPASS:
+        *(int32_t *) pValue = (int32_t) pReverb->m_bBypass;
+        break;
+    case REVERB_PARAM_PRESET:
+        *(int32_t *) pValue = (int8_t) pReverb->m_nCurrentRoom;
+        break;
+
+    case REVERB_PARAM_PROPERTIES:
+        pValue16 = &pProperties->roomLevel;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_ROOM_LEVEL:
+        // Convert m_nRoomLpfFwd to millibels
+        temp = (pReverb->m_nRoomLpfFwd << 15)
+                / (32767 - pReverb->m_nRoomLpfFbk);
+        *pValue16 = Effects_Linear16ToMillibels(temp);
+
+        LOGV("get REVERB_PARAM_ROOM_LEVEL %d, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", *pValue16, temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
+
+        if (param == REVERB_PARAM_ROOM_LEVEL) {
+            break;
+        }
+        pValue16 = &pProperties->roomHFLevel;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_ROOM_HF_LEVEL:
+        // The ratio between linear gain at 0Hz and at 5000Hz for the room low pass is:
+        // (1 + a1) / sqrt(a1^2 + 2*C*a1 + 1) where:
+        // - a1 is minus the LP feedback gain: -pReverb->m_nRoomLpfFbk
+        // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz
+
+        temp = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFbk);
+        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 %d", temp);
+        temp2 = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nCosWT_5KHz)
+                << 1;
+        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, 2 Cos a1 %d", temp2);
+        temp = 32767 + temp - temp2;
+        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 + 2 Cos a1 + 1 %d", temp);
+        temp = Effects_Sqrt(temp) * 181;
+        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, SQRT(a1^2 + 2 Cos a1 + 1) %d", temp);
+        temp = ((32767 - pReverb->m_nRoomLpfFbk) << 15) / temp;
+
+        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
+
+        *pValue16 = Effects_Linear16ToMillibels(temp);
+
+        if (param == REVERB_PARAM_ROOM_HF_LEVEL) {
+            break;
+        }
+        pValue32 = &pProperties->decayTime;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_DECAY_TIME:
+        // Calculate reverb feedback path gain
+        temp = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk);
+        temp = Effects_Linear16ToMillibels(temp);
+
+        // Calculate decay time: g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time
+        temp = (-6000 * pReverb->m_nLateDelay) / temp;
+
+        // Convert samples to ms
+        *pValue32 = (temp * 1000) / pReverb->m_nSamplingRate;
+
+        LOGV("get REVERB_PARAM_DECAY_TIME, samples %d, ms %d", temp, *pValue32);
+
+        if (param == REVERB_PARAM_DECAY_TIME) {
+            break;
+        }
+        pValue16 = &pProperties->decayHFRatio;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_DECAY_HF_RATIO:
+        // If r is the decay HF ratio  (r = REVERB_PARAM_DECAY_HF_RATIO/1000) we have:
+        //       DT_5000Hz = DT_0Hz * r
+        //  and  G_5000Hz = -6000 * d / DT_5000Hz and G_0Hz = -6000 * d / DT_0Hz in millibels so :
+        // r = G_0Hz/G_5000Hz in millibels
+        // The linear gain at 5000Hz is b0 / sqrt(a1^2 + 2*C*a1 + 1) where:
+        // - a1 is minus the LP feedback gain: -pReverb->m_nRvbLpfFbk
+        // - b0 is the LP forward gain: pReverb->m_nRvbLpfFwd
+        // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz
+        if (pReverb->m_nRvbLpfFbk == 0) {
+            *pValue16 = 1000;
+            LOGV("get REVERB_PARAM_DECAY_HF_RATIO, pReverb->m_nRvbLpfFbk == 0, ratio %d", *pValue16);
+        } else {
+            temp = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFbk);
+            temp2 = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nCosWT_5KHz)
+                    << 1;
+            temp = 32767 + temp - temp2;
+            temp = Effects_Sqrt(temp) * 181;
+            temp = (pReverb->m_nRvbLpfFwd << 15) / temp;
+            // The linear gain at 0Hz is b0 / (a1 + 1)
+            temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767
+                    - pReverb->m_nRvbLpfFbk);
+
+            temp = Effects_Linear16ToMillibels(temp);
+            temp2 = Effects_Linear16ToMillibels(temp2);
+            LOGV("get REVERB_PARAM_DECAY_HF_RATIO, gain 5KHz %d mB, gain DC %d mB", temp, temp2);
+
+            if (temp == 0)
+                temp = 1;
+            temp = (int16_t) ((1000 * temp2) / temp);
+            if (temp > 1000)
+                temp = 1000;
+
+            *pValue16 = temp;
+            LOGV("get REVERB_PARAM_DECAY_HF_RATIO, ratio %d", *pValue16);
+        }
+
+        if (param == REVERB_PARAM_DECAY_HF_RATIO) {
+            break;
+        }
+        pValue16 = &pProperties->reflectionsLevel;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_REFLECTIONS_LEVEL:
+        *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nEarlyGain);
+
+        LOGV("get REVERB_PARAM_REFLECTIONS_LEVEL, %d", *pValue16);
+        if (param == REVERB_PARAM_REFLECTIONS_LEVEL) {
+            break;
+        }
+        pValue32 = &pProperties->reflectionsDelay;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_REFLECTIONS_DELAY:
+        // convert samples to ms
+        *pValue32 = (pReverb->m_nEarlyDelay * 1000) / pReverb->m_nSamplingRate;
+
+        LOGV("get REVERB_PARAM_REFLECTIONS_DELAY, samples %d, ms %d", pReverb->m_nEarlyDelay, *pValue32);
+
+        if (param == REVERB_PARAM_REFLECTIONS_DELAY) {
+            break;
+        }
+        pValue16 = &pProperties->reverbLevel;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_REVERB_LEVEL:
+        // Convert linear gain to millibels
+        *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nLateGain << 2);
+
+        LOGV("get REVERB_PARAM_REVERB_LEVEL %d", *pValue16);
+
+        if (param == REVERB_PARAM_REVERB_LEVEL) {
+            break;
+        }
+        pValue32 = &pProperties->reverbDelay;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_REVERB_DELAY:
+        // convert samples to ms
+        *pValue32 = (pReverb->m_nLateDelay * 1000) / pReverb->m_nSamplingRate;
+
+        LOGV("get REVERB_PARAM_REVERB_DELAY, samples %d, ms %d", pReverb->m_nLateDelay, *pValue32);
+
+        if (param == REVERB_PARAM_REVERB_DELAY) {
+            break;
+        }
+        pValue16 = &pProperties->diffusion;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_DIFFUSION:
+        temp = (int16_t) ((1000 * (pReverb->m_sAp0.m_nApGain - AP0_GAIN_BASE))
+                / AP0_GAIN_RANGE);
+
+        if (temp < 0)
+            temp = 0;
+        if (temp > 1000)
+            temp = 1000;
+
+        *pValue16 = temp;
+        LOGV("get REVERB_PARAM_DIFFUSION, %d, AP0 gain %d", *pValue16, pReverb->m_sAp0.m_nApGain);
+
+        if (param == REVERB_PARAM_DIFFUSION) {
+            break;
+        }
+        pValue16 = &pProperties->density;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_DENSITY:
+        // Calculate AP delay in time units
+        temp = ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) << 16)
+                / pReverb->m_nSamplingRate;
+
+        temp = (int16_t) ((1000 * (temp - AP0_TIME_BASE)) / AP0_TIME_RANGE);
+
+        if (temp < 0)
+            temp = 0;
+        if (temp > 1000)
+            temp = 1000;
+
+        *pValue16 = temp;
+
+        LOGV("get REVERB_PARAM_DENSITY, %d, AP0 delay smps %d", *pValue16, pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn);
+        break;
+
+    default:
+        break;
+    }
+
+    LOGV("Reverb_getParameter, context %p, param %d, value %d",
+            pReverb, param, *(int *)pValue);
+
+    return 0;
+} /* end Reverb_getParameter */
+
+/*----------------------------------------------------------------------------
+ * Reverb_setParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set a Reverb parameter
+ *
+ * Inputs:
+ *  pReverb       - handle to instance data
+ *  param         - parameter
+ *  pValue        - pointer to parameter value
+ *  size          - value size
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size,
+        void *pValue) {
+    int32_t value32;
+    int16_t value16;
+    t_reverb_properties *pProperties;
+    int32_t i;
+    int32_t temp;
+    int32_t temp2;
+    reverb_preset_t *pPreset;
+    int maxSamples;
+    int32_t averageDelay;
+    size_t paramSize;
+
+    LOGV("Reverb_setParameter, context %p, param %d, value16 %d, value32 %d",
+            pReverb, param, *(int16_t *)pValue, *(int32_t *)pValue);
+
+    if (pReverb->m_Preset && param != REVERB_PARAM_PRESET) {
+        return -EINVAL;
+    }
+    if (!pReverb->m_Preset && param == REVERB_PARAM_PRESET) {
+        return -EINVAL;
+    }
+
+    switch (param) {
+    case REVERB_PARAM_ROOM_LEVEL:
+    case REVERB_PARAM_ROOM_HF_LEVEL:
+    case REVERB_PARAM_DECAY_HF_RATIO:
+    case REVERB_PARAM_REFLECTIONS_LEVEL:
+    case REVERB_PARAM_REVERB_LEVEL:
+    case REVERB_PARAM_DIFFUSION:
+    case REVERB_PARAM_DENSITY:
+        paramSize = sizeof(int16_t);
+        break;
+
+    case REVERB_PARAM_BYPASS:
+    case REVERB_PARAM_PRESET:
+    case REVERB_PARAM_DECAY_TIME:
+    case REVERB_PARAM_REFLECTIONS_DELAY:
+    case REVERB_PARAM_REVERB_DELAY:
+        paramSize = sizeof(int32_t);
+        break;
+
+    case REVERB_PARAM_PROPERTIES:
+        paramSize = sizeof(t_reverb_properties);
+        break;
+
+    default:
+        return -EINVAL;
+    }
+
+    if (size != paramSize) {
+        return -EINVAL;
+    }
+
+    if (paramSize == sizeof(int16_t)) {
+        value16 = *(int16_t *) pValue;
+    } else if (paramSize == sizeof(int32_t)) {
+        value32 = *(int32_t *) pValue;
+    } else {
+        pProperties = (t_reverb_properties *) pValue;
+    }
+
+    pPreset = &pReverb->m_sPreset.m_sPreset[pReverb->m_nCurrentRoom];
+
+    switch (param) {
+    case REVERB_PARAM_BYPASS:
+        pReverb->m_bBypass = (uint16_t)value32;
+        break;
+    case REVERB_PARAM_PRESET:
+        if (value32 != REVERB_PRESET_LARGE_HALL && value32
+                != REVERB_PRESET_HALL && value32 != REVERB_PRESET_CHAMBER
+                && value32 != REVERB_PRESET_ROOM)
+            return -EINVAL;
+        pReverb->m_nNextRoom = (int16_t) value32;
+        break;
+
+    case REVERB_PARAM_PROPERTIES:
+        value16 = pProperties->roomLevel;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_ROOM_LEVEL:
+        // Convert millibels to linear 16 bit signed => m_nRoomLpfFwd
+        if (value16 > 0)
+            return -EINVAL;
+
+        temp = Effects_MillibelsToLinear16(value16);
+
+        pReverb->m_nRoomLpfFwd
+                = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRoomLpfFbk));
+
+        LOGV("REVERB_PARAM_ROOM_LEVEL, gain %d, new m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
+        if (param == REVERB_PARAM_ROOM_LEVEL)
+            break;
+        value16 = pProperties->roomHFLevel;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_ROOM_HF_LEVEL:
+
+        // Limit to 0 , -40dB range because of low pass implementation
+        if (value16 > 0 || value16 < -4000)
+            return -EINVAL;
+        // Convert attenuation @ 5000H expressed in millibels to => m_nRoomLpfFbk
+        // m_nRoomLpfFbk is -a1 where a1 is the solution of:
+        // a1^2 + 2*(C-dG^2)/(1-dG^2)*a1 + 1 = 0 where:
+        // - C is cos(2*pi*5000/Fs) (pReverb->m_nCosWT_5KHz)
+        // - dG is G0/Gf (G0 is the linear gain at DC and Gf is the wanted gain at 5000Hz)
+
+        // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged
+        // while changing HF level
+        temp2 = (pReverb->m_nRoomLpfFwd << 15) / (32767
+                - pReverb->m_nRoomLpfFbk);
+        if (value16 == 0) {
+            pReverb->m_nRoomLpfFbk = 0;
+        } else {
+            int32_t dG2, b, delta;
+
+            // dG^2
+            temp = Effects_MillibelsToLinear16(value16);
+            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, HF gain %d", temp);
+            temp = (1 << 30) / temp;
+            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain %d", temp);
+            dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15);
+            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain ^ 2 %d", dG2);
+            // b = 2*(C-dG^2)/(1-dG^2)
+            b = (int32_t) ((((int64_t) 1 << (15 + 1))
+                    * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2))
+                    / ((int64_t) 32767 - (int64_t) dG2));
+
+            // delta = b^2 - 4
+            delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15
+                    + 2)));
+
+            LOGV_IF(delta > (1<<30), " delta overflow %d", delta);
+
+            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, dG2 %d, b %d, delta %d, m_nCosWT_5KHz %d", dG2, b, delta, pReverb->m_nCosWT_5KHz);
+            // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2
+            pReverb->m_nRoomLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1;
+        }
+        LOGV("REVERB_PARAM_ROOM_HF_LEVEL, olg DC gain %d new m_nRoomLpfFbk %d, old m_nRoomLpfFwd %d",
+                temp2, pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFwd);
+
+        pReverb->m_nRoomLpfFwd
+                = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRoomLpfFbk));
+        LOGV("REVERB_PARAM_ROOM_HF_LEVEL, new m_nRoomLpfFwd %d", pReverb->m_nRoomLpfFwd);
+
+        if (param == REVERB_PARAM_ROOM_HF_LEVEL)
+            break;
+        value32 = pProperties->decayTime;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_DECAY_TIME:
+
+        // Convert milliseconds to => m_nRvbLpfFwd (function of m_nRvbLpfFbk)
+        // convert ms to samples
+        value32 = (value32 * pReverb->m_nSamplingRate) / 1000;
+        // calculate valid decay time range as a function of current reverb delay and
+        // max feed back gain. Min value <=> -40dB in one pass, Max value <=> feedback gain = -1 dB
+        // Calculate attenuation for each round in late reverb given a total attenuation of -6000 millibels.
+        // g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time
+        averageDelay = pReverb->m_nLateDelay - pReverb->m_nMaxExcursion;
+        averageDelay += ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn)
+                + (pReverb->m_sAp1.m_zApOut - pReverb->m_sAp1.m_zApIn)) >> 1;
+
+        temp = (-6000 * averageDelay) / value32;
+        LOGV("REVERB_PARAM_DECAY_TIME, delay smps %d, DT smps %d, gain mB %d",averageDelay, value32, temp);
+        if (temp < -4000 || temp > -100)
+            return -EINVAL;
+
+        // calculate low pass gain by adding reverb input attenuation (pReverb->m_nLateGain) and substrating output
+        // xfade and sum gain (max +9dB)
+        temp -= Effects_Linear16ToMillibels(pReverb->m_nLateGain) + 900;
+        temp = Effects_MillibelsToLinear16(temp);
+
+        // DC gain (temp) = b0 / (1 + a1) = pReverb->m_nRvbLpfFwd / (32767 - pReverb->m_nRvbLpfFbk)
+        pReverb->m_nRvbLpfFwd
+                = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRvbLpfFbk));
+
+        LOGV("REVERB_PARAM_DECAY_TIME, gain %d, new m_nRvbLpfFwd %d, old m_nRvbLpfFbk %d, reverb gain %d", temp, pReverb->m_nRvbLpfFwd, pReverb->m_nRvbLpfFbk, Effects_Linear16ToMillibels(pReverb->m_nLateGain));
+
+        if (param == REVERB_PARAM_DECAY_TIME)
+            break;
+        value16 = pProperties->decayHFRatio;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_DECAY_HF_RATIO:
+
+        // We limit max value to 1000 because reverb filter is lowpass only
+        if (value16 < 100 || value16 > 1000)
+            return -EINVAL;
+        // Convert per mille to => m_nLpfFwd, m_nLpfFbk
+
+        // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged
+        // while changing HF level
+        temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk);
+
+        if (value16 == 1000) {
+            pReverb->m_nRvbLpfFbk = 0;
+        } else {
+            int32_t dG2, b, delta;
+
+            temp = Effects_Linear16ToMillibels(temp2);
+            // G_5000Hz = G_DC * (1000/REVERB_PARAM_DECAY_HF_RATIO) in millibels
+
+            value32 = ((int32_t) 1000 << 15) / (int32_t) value16;
+            LOGV("REVERB_PARAM_DECAY_HF_RATIO, DC gain %d, DC gain mB %d, 1000/R %d", temp2, temp, value32);
+
+            temp = (int32_t) (((int64_t) temp * (int64_t) value32) >> 15);
+
+            if (temp < -4000) {
+                LOGV("REVERB_PARAM_DECAY_HF_RATIO HF gain overflow %d mB", temp);
+                temp = -4000;
+            }
+
+            temp = Effects_MillibelsToLinear16(temp);
+            LOGV("REVERB_PARAM_DECAY_HF_RATIO, HF gain %d", temp);
+            // dG^2
+            temp = (temp2 << 15) / temp;
+            dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15);
+
+            // b = 2*(C-dG^2)/(1-dG^2)
+            b = (int32_t) ((((int64_t) 1 << (15 + 1))
+                    * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2))
+                    / ((int64_t) 32767 - (int64_t) dG2));
+
+            // delta = b^2 - 4
+            delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15
+                    + 2)));
+
+            // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2
+            pReverb->m_nRvbLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1;
+
+            LOGV("REVERB_PARAM_DECAY_HF_RATIO, dG2 %d, b %d, delta %d", dG2, b, delta);
+
+        }
+
+        LOGV("REVERB_PARAM_DECAY_HF_RATIO, gain %d, m_nRvbLpfFbk %d, m_nRvbLpfFwd %d", temp2, pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFwd);
+
+        pReverb->m_nRvbLpfFwd
+                = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRvbLpfFbk));
+
+        if (param == REVERB_PARAM_DECAY_HF_RATIO)
+            break;
+        value16 = pProperties->reflectionsLevel;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_REFLECTIONS_LEVEL:
+        // We limit max value to 0 because gain is limited to 0dB
+        if (value16 > 0 || value16 < -6000)
+            return -EINVAL;
+
+        // Convert millibels to linear 16 bit signed and recompute m_sEarlyL.m_nGain[i] and m_sEarlyR.m_nGain[i].
+        value16 = Effects_MillibelsToLinear16(value16);
+        for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+            pReverb->m_sEarlyL.m_nGain[i]
+                    = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],value16);
+            pReverb->m_sEarlyR.m_nGain[i]
+                    = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],value16);
+        }
+        pReverb->m_nEarlyGain = value16;
+        LOGV("REVERB_PARAM_REFLECTIONS_LEVEL, m_nEarlyGain %d", pReverb->m_nEarlyGain);
+
+        if (param == REVERB_PARAM_REFLECTIONS_LEVEL)
+            break;
+        value32 = pProperties->reflectionsDelay;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_REFLECTIONS_DELAY:
+        // We limit max value MAX_EARLY_TIME
+        // convert ms to time units
+        temp = (value32 * 65536) / 1000;
+        if (temp < 0 || temp > MAX_EARLY_TIME)
+            return -EINVAL;
+
+        maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
+                >> 16;
+        temp = (temp * pReverb->m_nSamplingRate) >> 16;
+        for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+            temp2 = temp + (((int32_t) pPreset->m_sEarlyL.m_zDelay[i]
+                    * pReverb->m_nSamplingRate) >> 16);
+            if (temp2 > maxSamples)
+                temp2 = maxSamples;
+            pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp2;
+            temp2 = temp + (((int32_t) pPreset->m_sEarlyR.m_zDelay[i]
+                    * pReverb->m_nSamplingRate) >> 16);
+            if (temp2 > maxSamples)
+                temp2 = maxSamples;
+            pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp2;
+        }
+        pReverb->m_nEarlyDelay = temp;
+
+        LOGV("REVERB_PARAM_REFLECTIONS_DELAY, m_nEarlyDelay smps %d max smp delay %d", pReverb->m_nEarlyDelay, maxSamples);
+
+        // Convert milliseconds to sample count => m_nEarlyDelay
+        if (param == REVERB_PARAM_REFLECTIONS_DELAY)
+            break;
+        value16 = pProperties->reverbLevel;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_REVERB_LEVEL:
+        // We limit max value to 0 because gain is limited to 0dB
+        if (value16 > 0 || value16 < -6000)
+            return -EINVAL;
+        // Convert millibels to linear 16 bits (gange 0 - 8191) => m_nLateGain.
+        pReverb->m_nLateGain = Effects_MillibelsToLinear16(value16) >> 2;
+
+        LOGV("REVERB_PARAM_REVERB_LEVEL, m_nLateGain %d", pReverb->m_nLateGain);
+
+        if (param == REVERB_PARAM_REVERB_LEVEL)
+            break;
+        value32 = pProperties->reverbDelay;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_REVERB_DELAY:
+        // We limit max value to MAX_DELAY_TIME
+        // convert ms to time units
+        temp = (value32 * 65536) / 1000;
+        if (temp < 0 || temp > MAX_DELAY_TIME)
+            return -EINVAL;
+
+        maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
+                >> 16;
+        temp = (temp * pReverb->m_nSamplingRate) >> 16;
+        if ((temp + pReverb->m_nMaxExcursion) > maxSamples) {
+            temp = maxSamples - pReverb->m_nMaxExcursion;
+        }
+        if (temp < pReverb->m_nMaxExcursion) {
+            temp = pReverb->m_nMaxExcursion;
+        }
+
+        temp -= pReverb->m_nLateDelay;
+        pReverb->m_nDelay0Out += temp;
+        pReverb->m_nDelay1Out += temp;
+        pReverb->m_nLateDelay += temp;
+
+        LOGV("REVERB_PARAM_REVERB_DELAY, m_nLateDelay smps %d max smp delay %d", pReverb->m_nLateDelay, maxSamples);
+
+        // Convert milliseconds to sample count => m_nDelay1Out + m_nMaxExcursion
+        if (param == REVERB_PARAM_REVERB_DELAY)
+            break;
+
+        value16 = pProperties->diffusion;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_DIFFUSION:
+        if (value16 < 0 || value16 > 1000)
+            return -EINVAL;
+
+        // Convert per mille to m_sAp0.m_nApGain, m_sAp1.m_nApGain
+        pReverb->m_sAp0.m_nApGain = AP0_GAIN_BASE + ((int32_t) value16
+                * AP0_GAIN_RANGE) / 1000;
+        pReverb->m_sAp1.m_nApGain = AP1_GAIN_BASE + ((int32_t) value16
+                * AP1_GAIN_RANGE) / 1000;
+
+        LOGV("REVERB_PARAM_DIFFUSION, m_sAp0.m_nApGain %d m_sAp1.m_nApGain %d", pReverb->m_sAp0.m_nApGain, pReverb->m_sAp1.m_nApGain);
+
+        if (param == REVERB_PARAM_DIFFUSION)
+            break;
+
+        value16 = pProperties->density;
+        /* FALL THROUGH */
+
+    case REVERB_PARAM_DENSITY:
+        if (value16 < 0 || value16 > 1000)
+            return -EINVAL;
+
+        // Convert per mille to m_sAp0.m_zApOut, m_sAp1.m_zApOut
+        maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16;
+
+        temp = AP0_TIME_BASE + ((int32_t) value16 * AP0_TIME_RANGE) / 1000;
+        /*lint -e{702} shift for performance */
+        temp = (temp * pReverb->m_nSamplingRate) >> 16;
+        if (temp > maxSamples)
+            temp = maxSamples;
+        pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp);
+
+        LOGV("REVERB_PARAM_DENSITY, Ap0 delay smps %d", temp);
+
+        temp = AP1_TIME_BASE + ((int32_t) value16 * AP1_TIME_RANGE) / 1000;
+        /*lint -e{702} shift for performance */
+        temp = (temp * pReverb->m_nSamplingRate) >> 16;
+        if (temp > maxSamples)
+            temp = maxSamples;
+        pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp);
+
+        LOGV("Ap1 delay smps %d", temp);
+
+        break;
+
+    default:
+        break;
+    }
+    return 0;
+} /* end Reverb_setParameter */
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateXfade
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the xfade parameters as required
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to write to buffer
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - xfade parameters will be changed
+ *
+ *----------------------------------------------------------------------------
+ */
+static int ReverbUpdateXfade(reverb_object_t *pReverb, int nNumSamplesToAdd) {
+    uint16_t nOffset;
+    int16_t tempCos;
+    int16_t tempSin;
+
+    if (pReverb->m_nXfadeCounter >= pReverb->m_nXfadeInterval) {
+        /* update interval has elapsed, so reset counter */
+        pReverb->m_nXfadeCounter = 0;
+
+        // Pin the sin,cos values to min / max values to ensure that the
+        // modulated taps' coefs are zero (thus no clicks)
+        if (pReverb->m_nPhaseIncrement > 0) {
+            // if phase increment > 0, then sin -> 1, cos -> 0
+            pReverb->m_nSin = 32767;
+            pReverb->m_nCos = 0;
+
+            // reset the phase to match the sin, cos values
+            pReverb->m_nPhase = 32767;
+
+            // modulate the cross taps because their tap coefs are zero
+            nOffset = ReverbCalculateNoise(pReverb);
+
+            pReverb->m_zD1Cross = pReverb->m_nDelay1Out
+                    - pReverb->m_nMaxExcursion + nOffset;
+
+            nOffset = ReverbCalculateNoise(pReverb);
+
+            pReverb->m_zD0Cross = pReverb->m_nDelay0Out
+                    - pReverb->m_nMaxExcursion - nOffset;
+        } else {
+            // if phase increment < 0, then sin -> 0, cos -> 1
+            pReverb->m_nSin = 0;
+            pReverb->m_nCos = 32767;
+
+            // reset the phase to match the sin, cos values
+            pReverb->m_nPhase = -32768;
+
+            // modulate the self taps because their tap coefs are zero
+            nOffset = ReverbCalculateNoise(pReverb);
+
+            pReverb->m_zD0Self = pReverb->m_nDelay0Out
+                    - pReverb->m_nMaxExcursion - nOffset;
+
+            nOffset = ReverbCalculateNoise(pReverb);
+
+            pReverb->m_zD1Self = pReverb->m_nDelay1Out
+                    - pReverb->m_nMaxExcursion + nOffset;
+
+        } // end if-else (pReverb->m_nPhaseIncrement > 0)
+
+        // Reverse the direction of the sin,cos so that the
+        // tap whose coef was previously increasing now decreases
+        // and vice versa
+        pReverb->m_nPhaseIncrement = -pReverb->m_nPhaseIncrement;
+
+    } // end if counter >= update interval
+
+    //compute what phase will be next time
+    pReverb->m_nPhase += pReverb->m_nPhaseIncrement;
+
+    //calculate what the new sin and cos need to reach by the next update
+    ReverbCalculateSinCos(pReverb->m_nPhase, &tempSin, &tempCos);
+
+    //calculate the per-sample increment required to get there by the next update
+    /*lint -e{702} shift for performance */
+    pReverb->m_nSinIncrement = (tempSin - pReverb->m_nSin)
+            >> pReverb->m_nUpdatePeriodInBits;
+
+    /*lint -e{702} shift for performance */
+    pReverb->m_nCosIncrement = (tempCos - pReverb->m_nCos)
+            >> pReverb->m_nUpdatePeriodInBits;
+
+    /* increment update counter */
+    pReverb->m_nXfadeCounter += (uint16_t) nNumSamplesToAdd;
+
+    return 0;
+
+} /* end ReverbUpdateXfade */
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateNoise
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a noise sample and limit its value
+ *
+ * Inputs:
+ * nMaxExcursion - noise value is limited to this value
+ * pnNoise - return new noise sample in this (not limited)
+ *
+ * Outputs:
+ * new limited noise value
+ *
+ * Side Effects:
+ * - *pnNoise noise value is updated
+ *
+ *----------------------------------------------------------------------------
+ */
+static uint16_t ReverbCalculateNoise(reverb_object_t *pReverb) {
+    int16_t nNoise = pReverb->m_nNoise;
+
+    // calculate new noise value
+    if (pReverb->m_bUseNoise) {
+        nNoise = (int16_t) (nNoise * 5 + 1);
+    } else {
+        nNoise = 0;
+    }
+
+    pReverb->m_nNoise = nNoise;
+    // return the limited noise value
+    return (pReverb->m_nMaxExcursion & nNoise);
+
+} /* end ReverbCalculateNoise */
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateSinCos
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a new sin and cosine value based on the given phase
+ *
+ * Inputs:
+ * nPhase   - phase angle
+ * pnSin    - input old value, output new value
+ * pnCos    - input old value, output new value
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * - *pnSin, *pnCos are updated
+ *
+ *----------------------------------------------------------------------------
+ */
+static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos) {
+    int32_t nTemp;
+    int32_t nNetAngle;
+
+    //  -1 <=  nPhase  < 1
+    // However, for the calculation, we need a value
+    // that ranges from -1/2 to +1/2, so divide the phase by 2
+    /*lint -e{702} shift for performance */
+    nNetAngle = nPhase >> 1;
+
+    /*
+     Implement the following
+     sin(x) = (2-4*c)*x^2 + c + x
+     cos(x) = (2-4*c)*x^2 + c - x
+
+     where  c = 1/sqrt(2)
+     using the a0 + x*(a1 + x*a2) approach
+     */
+
+    /* limit the input "angle" to be between -0.5 and +0.5 */
+    if (nNetAngle > EG1_HALF) {
+        nNetAngle = EG1_HALF;
+    } else if (nNetAngle < EG1_MINUS_HALF) {
+        nNetAngle = EG1_MINUS_HALF;
+    }
+
+    /* calculate sin */
+    nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
+    nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
+    *pnSin = (int16_t) SATURATE_EG1(nTemp);
+
+    /* calculate cos */
+    nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
+    nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
+    *pnCos = (int16_t) SATURATE_EG1(nTemp);
+
+    return 0;
+} /* end ReverbCalculateSinCos */
+
+/*----------------------------------------------------------------------------
+ * Reverb
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * apply reverb to the given signal
+ *
+ * Inputs:
+ * nNu
+ * pnSin    - input old value, output new value
+ * pnCos    - input old value, output new value
+ *
+ * Outputs:
+ * number of samples actually reverberated
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+static int Reverb(reverb_object_t *pReverb, int nNumSamplesToAdd,
+        short *pOutputBuffer, short *pInputBuffer) {
+    int32_t i;
+    int32_t nDelayOut0;
+    int32_t nDelayOut1;
+    uint16_t nBase;
+
+    uint32_t nAddr;
+    int32_t nTemp1;
+    int32_t nTemp2;
+    int32_t nApIn;
+    int32_t nApOut;
+
+    int32_t j;
+    int32_t nEarlyOut;
+
+    int32_t tempValue;
+
+    // get the base address
+    nBase = pReverb->m_nBaseIndex;
+
+    for (i = 0; i < nNumSamplesToAdd; i++) {
+        // ********** Left Allpass - start
+        nApIn = *pInputBuffer;
+        if (!pReverb->m_Aux) {
+            pInputBuffer++;
+        }
+        // store to early delay line
+        nAddr = CIRCULAR(nBase, pReverb->m_nEarly0in, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nApIn;
+
+        // left input = (left dry * m_nLateGain) + right feedback from previous period
+
+        nApIn = SATURATE(nApIn + pReverb->m_nRevFbkR);
+        nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain);
+
+        // fetch allpass delay line out
+        //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, pReverb->m_nBufferMask);
+        nAddr
+                = CIRCULAR(nBase, pReverb->m_sAp0.m_zApOut, pReverb->m_nBufferMask);
+        nDelayOut0 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate allpass feedforward; subtract the feedforward result
+        nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp0.m_nApGain);
+        nApOut = SATURATE(nDelayOut0 - nTemp1); // allpass output
+
+        // calculate allpass feedback; add the feedback result
+        nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp0.m_nApGain);
+        nTemp1 = SATURATE(nApIn + nTemp1);
+
+        // inject into allpass delay
+        nAddr
+                = CIRCULAR(nBase, pReverb->m_sAp0.m_zApIn, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nTemp1;
+
+        // inject allpass output into delay line
+        nAddr = CIRCULAR(nBase, pReverb->m_zD0In, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nApOut;
+
+        // ********** Left Allpass - end
+
+        // ********** Right Allpass - start
+        nApIn = (*pInputBuffer++);
+        // store to early delay line
+        nAddr = CIRCULAR(nBase, pReverb->m_nEarly1in, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nApIn;
+
+        // right input = (right dry * m_nLateGain) + left feedback from previous period
+        /*lint -e{702} use shift for performance */
+        nApIn = SATURATE(nApIn + pReverb->m_nRevFbkL);
+        nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain);
+
+        // fetch allpass delay line out
+        nAddr
+                = CIRCULAR(nBase, pReverb->m_sAp1.m_zApOut, pReverb->m_nBufferMask);
+        nDelayOut1 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate allpass feedforward; subtract the feedforward result
+        nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp1.m_nApGain);
+        nApOut = SATURATE(nDelayOut1 - nTemp1); // allpass output
+
+        // calculate allpass feedback; add the feedback result
+        nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp1.m_nApGain);
+        nTemp1 = SATURATE(nApIn + nTemp1);
+
+        // inject into allpass delay
+        nAddr
+                = CIRCULAR(nBase, pReverb->m_sAp1.m_zApIn, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nTemp1;
+
+        // inject allpass output into delay line
+        nAddr = CIRCULAR(nBase, pReverb->m_zD1In, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nApOut;
+
+        // ********** Right Allpass - end
+
+        // ********** D0 output - start
+        // fetch delay line self out
+        nAddr = CIRCULAR(nBase, pReverb->m_zD0Self, pReverb->m_nBufferMask);
+        nDelayOut0 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate delay line self out
+        nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nSin);
+
+        // fetch delay line cross out
+        nAddr = CIRCULAR(nBase, pReverb->m_zD1Cross, pReverb->m_nBufferMask);
+        nDelayOut0 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate delay line self out
+        nTemp2 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nCos);
+
+        // calculate unfiltered delay out
+        nDelayOut0 = SATURATE(nTemp1 + nTemp2);
+
+        // ********** D0 output - end
+
+        // ********** D1 output - start
+        // fetch delay line self out
+        nAddr = CIRCULAR(nBase, pReverb->m_zD1Self, pReverb->m_nBufferMask);
+        nDelayOut1 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate delay line self out
+        nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nSin);
+
+        // fetch delay line cross out
+        nAddr = CIRCULAR(nBase, pReverb->m_zD0Cross, pReverb->m_nBufferMask);
+        nDelayOut1 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate delay line self out
+        nTemp2 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nCos);
+
+        // calculate unfiltered delay out
+        nDelayOut1 = SATURATE(nTemp1 + nTemp2);
+
+        // ********** D1 output - end
+
+        // ********** mixer and feedback - start
+        // sum is fedback to right input (R + L)
+        nDelayOut0 = (short) SATURATE(nDelayOut0 + nDelayOut1);
+
+        // difference is feedback to left input (R - L)
+        /*lint -e{685} lint complains that it can't saturate negative */
+        nDelayOut1 = (short) SATURATE(nDelayOut1 - nDelayOut0);
+
+        // ********** mixer and feedback - end
+
+        // calculate lowpass filter (mixer scale factor included in LPF feedforward)
+        nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRvbLpfFwd);
+
+        nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkL, pReverb->m_nRvbLpfFbk);
+
+        // calculate filtered delay out and simultaneously update LPF state variable
+        // filtered delay output is stored in m_nRevFbkL
+        pReverb->m_nRevFbkL = (short) SATURATE(nTemp1 + nTemp2);
+
+        // calculate lowpass filter (mixer scale factor included in LPF feedforward)
+        nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRvbLpfFwd);
+
+        nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkR, pReverb->m_nRvbLpfFbk);
+
+        // calculate filtered delay out and simultaneously update LPF state variable
+        // filtered delay output is stored in m_nRevFbkR
+        pReverb->m_nRevFbkR = (short) SATURATE(nTemp1 + nTemp2);
+
+        // ********** start early reflection generator, left
+        //psEarly = &(pReverb->m_sEarlyL);
+
+
+        for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) {
+            // fetch delay line out
+            //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], pReverb->m_nBufferMask);
+            nAddr
+                    = CIRCULAR(nBase, pReverb->m_sEarlyL.m_zDelay[j], pReverb->m_nBufferMask);
+
+            nTemp1 = pReverb->m_nDelayLine[nAddr];
+
+            // calculate reflection
+            //nTemp1 = MULT_EG1_EG1(nDelayOut0, psEarly->m_nGain[j]);
+            nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyL.m_nGain[j]);
+
+            nDelayOut0 = SATURATE(nDelayOut0 + nTemp1);
+
+        } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+
+        // apply lowpass to early reflections and reverb output
+        //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nRvbLpfFwd);
+        nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRoomLpfFwd);
+
+        //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk);
+        nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfL, pReverb->m_nRoomLpfFbk);
+
+        // calculate filtered out and simultaneously update LPF state variable
+        // filtered output is stored in m_zOutLpfL
+        pReverb->m_zOutLpfL = (short) SATURATE(nTemp1 + nTemp2);
+
+        //sum with output buffer
+        tempValue = *pOutputBuffer;
+        *pOutputBuffer++ = (short) SATURATE(tempValue+pReverb->m_zOutLpfL);
+
+        // ********** end early reflection generator, left
+
+        // ********** start early reflection generator, right
+        //psEarly = &(pReverb->m_sEarlyR);
+
+        for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) {
+            // fetch delay line out
+            nAddr
+                    = CIRCULAR(nBase, pReverb->m_sEarlyR.m_zDelay[j], pReverb->m_nBufferMask);
+            nTemp1 = pReverb->m_nDelayLine[nAddr];
+
+            // calculate reflection
+            nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyR.m_nGain[j]);
+
+            nDelayOut1 = SATURATE(nDelayOut1 + nTemp1);
+
+        } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+
+        // apply lowpass to early reflections
+        nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRoomLpfFwd);
+
+        nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfR, pReverb->m_nRoomLpfFbk);
+
+        // calculate filtered out and simultaneously update LPF state variable
+        // filtered output is stored in m_zOutLpfR
+        pReverb->m_zOutLpfR = (short) SATURATE(nTemp1 + nTemp2);
+
+        //sum with output buffer
+        tempValue = *pOutputBuffer;
+        *pOutputBuffer++ = (short) SATURATE(tempValue + pReverb->m_zOutLpfR);
+
+        // ********** end early reflection generator, right
+
+        // decrement base addr for next sample period
+        nBase--;
+
+        pReverb->m_nSin += pReverb->m_nSinIncrement;
+        pReverb->m_nCos += pReverb->m_nCosIncrement;
+
+    } // end for (i=0; i < nNumSamplesToAdd; i++)
+
+    // store the most up to date version
+    pReverb->m_nBaseIndex = nBase;
+
+    return 0;
+} /* end Reverb */
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateRoom
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the room's preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - reverb paramters (fbk, fwd, etc) will be changed
+ * - m_nCurrentRoom := m_nNextRoom
+ *----------------------------------------------------------------------------
+ */
+static int ReverbUpdateRoom(reverb_object_t *pReverb, bool fullUpdate) {
+    int temp;
+    int i;
+    int maxSamples;
+    int earlyDelay;
+    int earlyGain;
+
+    reverb_preset_t *pPreset =
+            &pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom];
+
+    if (fullUpdate) {
+        pReverb->m_nRvbLpfFwd = pPreset->m_nRvbLpfFwd;
+        pReverb->m_nRvbLpfFbk = pPreset->m_nRvbLpfFbk;
+
+        pReverb->m_nEarlyGain = pPreset->m_nEarlyGain;
+        //stored as time based, convert to sample based
+        pReverb->m_nLateGain = pPreset->m_nLateGain;
+        pReverb->m_nRoomLpfFbk = pPreset->m_nRoomLpfFbk;
+        pReverb->m_nRoomLpfFwd = pPreset->m_nRoomLpfFwd;
+
+        // set the early reflections gains
+        earlyGain = pPreset->m_nEarlyGain;
+        for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+            pReverb->m_sEarlyL.m_nGain[i]
+                    = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],earlyGain);
+            pReverb->m_sEarlyR.m_nGain[i]
+                    = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],earlyGain);
+        }
+
+        pReverb->m_nMaxExcursion = pPreset->m_nMaxExcursion;
+
+        pReverb->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain;
+        pReverb->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain;
+
+        // set the early reflections delay
+        earlyDelay = ((int) pPreset->m_nEarlyDelay * pReverb->m_nSamplingRate)
+                >> 16;
+        pReverb->m_nEarlyDelay = earlyDelay;
+        maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
+                >> 16;
+        for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+            //stored as time based, convert to sample based
+            temp = earlyDelay + (((int) pPreset->m_sEarlyL.m_zDelay[i]
+                    * pReverb->m_nSamplingRate) >> 16);
+            if (temp > maxSamples)
+                temp = maxSamples;
+            pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp;
+            //stored as time based, convert to sample based
+            temp = earlyDelay + (((int) pPreset->m_sEarlyR.m_zDelay[i]
+                    * pReverb->m_nSamplingRate) >> 16);
+            if (temp > maxSamples)
+                temp = maxSamples;
+            pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp;
+        }
+
+        maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
+                >> 16;
+        //stored as time based, convert to sample based
+        /*lint -e{702} shift for performance */
+        temp = (pPreset->m_nLateDelay * pReverb->m_nSamplingRate) >> 16;
+        if ((temp + pReverb->m_nMaxExcursion) > maxSamples) {
+            temp = maxSamples - pReverb->m_nMaxExcursion;
+        }
+        temp -= pReverb->m_nLateDelay;
+        pReverb->m_nDelay0Out += temp;
+        pReverb->m_nDelay1Out += temp;
+        pReverb->m_nLateDelay += temp;
+
+        maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16;
+        //stored as time based, convert to absolute sample value
+        temp = pPreset->m_nAp0_ApOut;
+        /*lint -e{702} shift for performance */
+        temp = (temp * pReverb->m_nSamplingRate) >> 16;
+        if (temp > maxSamples)
+            temp = maxSamples;
+        pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp);
+
+        //stored as time based, convert to absolute sample value
+        temp = pPreset->m_nAp1_ApOut;
+        /*lint -e{702} shift for performance */
+        temp = (temp * pReverb->m_nSamplingRate) >> 16;
+        if (temp > maxSamples)
+            temp = maxSamples;
+        pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp);
+        //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut;
+    }
+
+    //stored as time based, convert to sample based
+    temp = pPreset->m_nXfadeInterval;
+    /*lint -e{702} shift for performance */
+    temp = (temp * pReverb->m_nSamplingRate) >> 16;
+    pReverb->m_nXfadeInterval = (uint16_t) temp;
+    //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval;
+    pReverb->m_nXfadeCounter = pReverb->m_nXfadeInterval + 1; // force update on first iteration
+
+
+    pReverb->m_nCurrentRoom = pReverb->m_nNextRoom;
+
+    return 0;
+
+} /* end ReverbUpdateRoom */
+
+/*----------------------------------------------------------------------------
+ * ReverbReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global reverb preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+ */
+static int ReverbReadInPresets(reverb_object_t *pReverb) {
+
+    int preset = 0;
+    int defaultPreset = 0;
+
+    //now init any remaining presets to defaults
+    for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++) {
+        reverb_preset_t *pPreset = &pReverb->m_sPreset.m_sPreset[defaultPreset];
+        if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE - 1) {
+            pPreset->m_nRvbLpfFbk = 8307;
+            pPreset->m_nRvbLpfFwd = 14768;
+            pPreset->m_nEarlyGain = 27690;
+            pPreset->m_nEarlyDelay = 1311;
+            pPreset->m_nLateGain = 8191;
+            pPreset->m_nLateDelay = 3932;
+            pPreset->m_nRoomLpfFbk = 3692;
+            pPreset->m_nRoomLpfFwd = 24569;
+            pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+            pPreset->m_sEarlyL.m_nGain[0] = 22152;
+            pPreset->m_sEarlyL.m_zDelay[1] = 2163;
+            pPreset->m_sEarlyL.m_nGain[1] = 17537;
+            pPreset->m_sEarlyL.m_zDelay[2] = 0;
+            pPreset->m_sEarlyL.m_nGain[2] = 14768;
+            pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+            pPreset->m_sEarlyL.m_nGain[3] = 14307;
+            pPreset->m_sEarlyL.m_zDelay[4] = 0;
+            pPreset->m_sEarlyL.m_nGain[4] = 13384;
+            pPreset->m_sEarlyR.m_zDelay[0] = 721;
+            pPreset->m_sEarlyR.m_nGain[0] = 20306;
+            pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+            pPreset->m_sEarlyR.m_nGain[1] = 17537;
+            pPreset->m_sEarlyR.m_zDelay[2] = 0;
+            pPreset->m_sEarlyR.m_nGain[2] = 14768;
+            pPreset->m_sEarlyR.m_zDelay[3] = 0;
+            pPreset->m_sEarlyR.m_nGain[3] = 16153;
+            pPreset->m_sEarlyR.m_zDelay[4] = 0;
+            pPreset->m_sEarlyR.m_nGain[4] = 13384;
+            pPreset->m_nMaxExcursion = 127;
+            pPreset->m_nXfadeInterval = 6388;
+            pPreset->m_nAp0_ApGain = 15691;
+            pPreset->m_nAp0_ApOut = 711;
+            pPreset->m_nAp1_ApGain = 16317;
+            pPreset->m_nAp1_ApOut = 1029;
+            pPreset->m_rfu4 = 0;
+            pPreset->m_rfu5 = 0;
+            pPreset->m_rfu6 = 0;
+            pPreset->m_rfu7 = 0;
+            pPreset->m_rfu8 = 0;
+            pPreset->m_rfu9 = 0;
+            pPreset->m_rfu10 = 0;
+        } else if (defaultPreset == 1) {
+            pPreset->m_nRvbLpfFbk = 6461;
+            pPreset->m_nRvbLpfFwd = 14307;
+            pPreset->m_nEarlyGain = 27690;
+            pPreset->m_nEarlyDelay = 1311;
+            pPreset->m_nLateGain = 8191;
+            pPreset->m_nLateDelay = 3932;
+            pPreset->m_nRoomLpfFbk = 3692;
+            pPreset->m_nRoomLpfFwd = 24569;
+            pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+            pPreset->m_sEarlyL.m_nGain[0] = 22152;
+            pPreset->m_sEarlyL.m_zDelay[1] = 1462;
+            pPreset->m_sEarlyL.m_nGain[1] = 17537;
+            pPreset->m_sEarlyL.m_zDelay[2] = 0;
+            pPreset->m_sEarlyL.m_nGain[2] = 14768;
+            pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+            pPreset->m_sEarlyL.m_nGain[3] = 14307;
+            pPreset->m_sEarlyL.m_zDelay[4] = 0;
+            pPreset->m_sEarlyL.m_nGain[4] = 13384;
+            pPreset->m_sEarlyR.m_zDelay[0] = 721;
+            pPreset->m_sEarlyR.m_nGain[0] = 20306;
+            pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+            pPreset->m_sEarlyR.m_nGain[1] = 17537;
+            pPreset->m_sEarlyR.m_zDelay[2] = 0;
+            pPreset->m_sEarlyR.m_nGain[2] = 14768;
+            pPreset->m_sEarlyR.m_zDelay[3] = 0;
+            pPreset->m_sEarlyR.m_nGain[3] = 16153;
+            pPreset->m_sEarlyR.m_zDelay[4] = 0;
+            pPreset->m_sEarlyR.m_nGain[4] = 13384;
+            pPreset->m_nMaxExcursion = 127;
+            pPreset->m_nXfadeInterval = 6391;
+            pPreset->m_nAp0_ApGain = 15230;
+            pPreset->m_nAp0_ApOut = 708;
+            pPreset->m_nAp1_ApGain = 15547;
+            pPreset->m_nAp1_ApOut = 1023;
+            pPreset->m_rfu4 = 0;
+            pPreset->m_rfu5 = 0;
+            pPreset->m_rfu6 = 0;
+            pPreset->m_rfu7 = 0;
+            pPreset->m_rfu8 = 0;
+            pPreset->m_rfu9 = 0;
+            pPreset->m_rfu10 = 0;
+        } else if (defaultPreset == 2) {
+            pPreset->m_nRvbLpfFbk = 5077;
+            pPreset->m_nRvbLpfFwd = 12922;
+            pPreset->m_nEarlyGain = 27690;
+            pPreset->m_nEarlyDelay = 1311;
+            pPreset->m_nLateGain = 8191;
+            pPreset->m_nLateDelay = 3932;
+            pPreset->m_nRoomLpfFbk = 3692;
+            pPreset->m_nRoomLpfFwd = 21703;
+            pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+            pPreset->m_sEarlyL.m_nGain[0] = 22152;
+            pPreset->m_sEarlyL.m_zDelay[1] = 1462;
+            pPreset->m_sEarlyL.m_nGain[1] = 17537;
+            pPreset->m_sEarlyL.m_zDelay[2] = 0;
+            pPreset->m_sEarlyL.m_nGain[2] = 14768;
+            pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+            pPreset->m_sEarlyL.m_nGain[3] = 14307;
+            pPreset->m_sEarlyL.m_zDelay[4] = 0;
+            pPreset->m_sEarlyL.m_nGain[4] = 13384;
+            pPreset->m_sEarlyR.m_zDelay[0] = 721;
+            pPreset->m_sEarlyR.m_nGain[0] = 20306;
+            pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+            pPreset->m_sEarlyR.m_nGain[1] = 17537;
+            pPreset->m_sEarlyR.m_zDelay[2] = 0;
+            pPreset->m_sEarlyR.m_nGain[2] = 14768;
+            pPreset->m_sEarlyR.m_zDelay[3] = 0;
+            pPreset->m_sEarlyR.m_nGain[3] = 16153;
+            pPreset->m_sEarlyR.m_zDelay[4] = 0;
+            pPreset->m_sEarlyR.m_nGain[4] = 13384;
+            pPreset->m_nMaxExcursion = 127;
+            pPreset->m_nXfadeInterval = 6449;
+            pPreset->m_nAp0_ApGain = 15691;
+            pPreset->m_nAp0_ApOut = 774;
+            pPreset->m_nAp1_ApGain = 16317;
+            pPreset->m_nAp1_ApOut = 1155;
+            pPreset->m_rfu4 = 0;
+            pPreset->m_rfu5 = 0;
+            pPreset->m_rfu6 = 0;
+            pPreset->m_rfu7 = 0;
+            pPreset->m_rfu8 = 0;
+            pPreset->m_rfu9 = 0;
+            pPreset->m_rfu10 = 0;
+        } else if (defaultPreset == 3) {
+            pPreset->m_nRvbLpfFbk = 5077;
+            pPreset->m_nRvbLpfFwd = 11076;
+            pPreset->m_nEarlyGain = 27690;
+            pPreset->m_nEarlyDelay = 1311;
+            pPreset->m_nLateGain = 8191;
+            pPreset->m_nLateDelay = 3932;
+            pPreset->m_nRoomLpfFbk = 3692;
+            pPreset->m_nRoomLpfFwd = 20474;
+            pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+            pPreset->m_sEarlyL.m_nGain[0] = 22152;
+            pPreset->m_sEarlyL.m_zDelay[1] = 1462;
+            pPreset->m_sEarlyL.m_nGain[1] = 17537;
+            pPreset->m_sEarlyL.m_zDelay[2] = 0;
+            pPreset->m_sEarlyL.m_nGain[2] = 14768;
+            pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+            pPreset->m_sEarlyL.m_nGain[3] = 14307;
+            pPreset->m_sEarlyL.m_zDelay[4] = 0;
+            pPreset->m_sEarlyL.m_nGain[4] = 13384;
+            pPreset->m_sEarlyR.m_zDelay[0] = 721;
+            pPreset->m_sEarlyR.m_nGain[0] = 20306;
+            pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+            pPreset->m_sEarlyR.m_nGain[1] = 17537;
+            pPreset->m_sEarlyR.m_zDelay[2] = 0;
+            pPreset->m_sEarlyR.m_nGain[2] = 14768;
+            pPreset->m_sEarlyR.m_zDelay[3] = 0;
+            pPreset->m_sEarlyR.m_nGain[3] = 16153;
+            pPreset->m_sEarlyR.m_zDelay[4] = 0;
+            pPreset->m_sEarlyR.m_nGain[4] = 13384;
+            pPreset->m_nMaxExcursion = 127;
+            pPreset->m_nXfadeInterval = 6470; //6483;
+            pPreset->m_nAp0_ApGain = 14768;
+            pPreset->m_nAp0_ApOut = 792;
+            pPreset->m_nAp1_ApGain = 14777;
+            pPreset->m_nAp1_ApOut = 1191;
+            pPreset->m_rfu4 = 0;
+            pPreset->m_rfu5 = 0;
+            pPreset->m_rfu6 = 0;
+            pPreset->m_rfu7 = 0;
+            pPreset->m_rfu8 = 0;
+            pPreset->m_rfu9 = 0;
+            pPreset->m_rfu10 = 0;
+        }
+    }
+
+    return 0;
+}
diff --git a/media/libeffects/EffectReverb.h b/media/libeffects/EffectReverb.h
new file mode 100644
index 0000000..cd14891
--- /dev/null
+++ b/media/libeffects/EffectReverb.h
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2008 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_EFFECTREVERB_H_
+#define ANDROID_EFFECTREVERB_H_
+
+#include <media/EffectReverbApi.h>
+
+
+/*------------------------------------
+ * defines
+ *------------------------------------
+*/
+
+/*
+CIRCULAR() calculates the array index using modulo arithmetic.
+The "trick" is that modulo arithmetic is simplified by masking
+the effective address where the mask is (2^n)-1. This only works
+if the buffer size is a power of two.
+*/
+#define CIRCULAR(base,offset,size) (uint32_t)(               \
+            (                                               \
+                ((int32_t)(base)) + ((int32_t)(offset))     \
+            )                                               \
+            & size                                          \
+                                            )
+
+#define NUM_OUTPUT_CHANNELS 2
+#define OUTPUT_CHANNELS CHANNEL_STEREO
+
+#define REVERB_BUFFER_SIZE_IN_SAMPLES_MAX   16384
+
+#define REVERB_MAX_ROOM_TYPE            4   // any room numbers larger than this are invalid
+#define REVERB_MAX_NUM_REFLECTIONS      5   // max num reflections per channel
+
+
+// xfade parameters
+#define REVERB_XFADE_PERIOD_IN_SECONDS      (double) (100.0 / 1000.0)        // xfade once every this many seconds
+
+
+/**********/
+/* the entire synth uses various flags in a bit field */
+
+/* if flag is set, synth reset has been requested */
+#define REVERB_FLAG_RESET_IS_REQUESTED          0x01    /* bit 0 */
+#define MASK_REVERB_RESET_IS_REQUESTED          0x01
+#define MASK_REVERB_RESET_IS_NOT_REQUESTED      (uint32_t)(~MASK_REVERB_RESET_IS_REQUESTED)
+
+/*
+by default, we always want to update ALL channel parameters
+when we reset the synth (e.g., during GM ON)
+*/
+#define DEFAULT_REVERB_FLAGS                    0x0
+
+/* coefficients for generating sin, cos */
+#define REVERB_PAN_G2   4294940151          /* -0.82842712474619 = 2 - 4/sqrt(2) */
+/*
+int32_t nPanG1 = +1.0 for sin
+int32_t nPanG1 = -1.0 for cos
+*/
+#define REVERB_PAN_G0   23170               /* 0.707106781186547 = 1/sqrt(2) */
+
+/*************************************************************/
+// define the input injection points
+#define GUARD               5                       // safety guard of this many samples
+
+#define MAX_AP_TIME         (int) ((20*65536)/1000)  // delay time in time units (65536th of sec)
+#define MAX_DELAY_TIME      (int) ((65*65536)/1000)  // delay time in time units
+#define MAX_EARLY_TIME      (int) ((65*65536)/1000)  // delay time in time units
+
+#define AP0_IN              0
+
+
+#define REVERB_DEFAULT_ROOM_NUMBER      1       // default preset number
+#define DEFAULT_AP0_GAIN                19400
+#define DEFAULT_AP1_GAIN                -19400
+
+#define REVERB_DEFAULT_WET              32767
+#define REVERB_DEFAULT_DRY              0
+
+#define REVERB_WET_MAX              32767
+#define REVERB_WET_MIN              0
+#define REVERB_DRY_MAX              32767
+#define REVERB_DRY_MIN              0
+
+// constants for reverb density
+// The density expressed in permilles changes the Allpass delay in a linear manner in the range defined by
+// AP0_TIME_BASE to AP0_TIME_BASE + AP0_TIME_RANGE
+#define AP0_TIME_BASE (int)((9*65536)/1000)
+#define AP0_TIME_RANGE (int)((4*65536)/1000)
+#define AP1_TIME_BASE (int)((12*65536)/1000)
+#define AP1_TIME_RANGE (int)((8*65536)/1000)
+
+// constants for reverb diffusion
+// The diffusion expressed in permilles changes the Allpass gain in a linear manner in the range defined by
+// AP0_GAIN_BASE to AP0_GAIN_BASE + AP0_GAIN_RANGE
+#define AP0_GAIN_BASE (int)(9830)
+#define AP0_GAIN_RANGE (int)(19660-9830)
+#define AP1_GAIN_BASE (int)(6553)
+#define AP1_GAIN_RANGE (int)(22936-6553)
+
+
+/* parameters for each allpass */
+typedef struct
+{
+    uint16_t             m_zApOut;       // delay offset for ap out
+
+    int16_t             m_nApGain;      // gain for ap
+
+    uint16_t             m_zApIn;        // delay offset for ap in
+
+} allpass_object_t;
+
+
+/* parameters for early reflections */
+typedef struct
+{
+    uint16_t            m_zDelay[REVERB_MAX_NUM_REFLECTIONS];   // delay offset for ap out
+
+    int16_t             m_nGain[REVERB_MAX_NUM_REFLECTIONS];    // gain for ap
+
+} early_reflection_object_t;
+
+//demo
+typedef struct
+{
+    int16_t             m_nRvbLpfFbk;
+    int16_t             m_nRvbLpfFwd;
+    int16_t             m_nRoomLpfFbk;
+    int16_t             m_nRoomLpfFwd;
+
+    int16_t             m_nEarlyGain;
+    int16_t             m_nEarlyDelay;
+    int16_t             m_nLateGain;
+    int16_t             m_nLateDelay;
+
+    early_reflection_object_t m_sEarlyL;
+    early_reflection_object_t m_sEarlyR;
+
+    uint16_t            m_nMaxExcursion; //28
+    int16_t             m_nXfadeInterval;
+
+    int16_t             m_nAp0_ApGain; //30
+    int16_t             m_nAp0_ApOut;
+    int16_t             m_nAp1_ApGain;
+    int16_t             m_nAp1_ApOut;
+    int16_t             m_nDiffusion;
+
+    int16_t             m_rfu4;
+    int16_t             m_rfu5;
+    int16_t             m_rfu6;
+    int16_t             m_rfu7;
+    int16_t             m_rfu8;
+    int16_t             m_rfu9;
+    int16_t             m_rfu10; //43
+
+} reverb_preset_t;
+
+typedef struct
+{
+    reverb_preset_t     m_sPreset[REVERB_MAX_ROOM_TYPE];    //array of presets
+
+} reverb_preset_bank_t;
+
+
+/* parameters for each reverb */
+typedef struct
+{
+    /* update counter keeps track of when synth params need updating */
+    /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */
+    int16_t             m_nUpdateCounter;
+
+    uint16_t             m_nBaseIndex;                                   // base index for circular buffer
+
+    // reverb delay line offsets, allpass parameters, etc:
+
+    short             m_nRevFbkR;              // combine feedback reverb right out with dry left in
+    short             m_zOutLpfL;              // left reverb output
+
+    allpass_object_t    m_sAp0;                     // allpass 0 (left channel)
+
+    uint16_t             m_zD0In;                    // delay offset for delay line D0 in
+
+    short             m_nRevFbkL;              // combine feedback reverb left out with dry right in
+    short             m_zOutLpfR;              // right reverb output
+
+    allpass_object_t    m_sAp1;                     // allpass 1 (right channel)
+
+    uint16_t             m_zD1In;                    // delay offset for delay line D1 in
+
+    // delay output taps, notice criss cross order
+    uint16_t             m_zD0Self;                  // self feeds forward d0 --> d0
+
+    uint16_t             m_zD1Cross;                 // cross feeds across d1 --> d0
+
+    uint16_t             m_zD1Self;                  // self feeds forward d1 --> d1
+
+    uint16_t             m_zD0Cross;                 // cross feeds across d0 --> d1
+
+    int16_t             m_nSin;                     // gain for self taps
+
+    int16_t             m_nCos;                     // gain for cross taps
+
+    int16_t             m_nSinIncrement;            // increment for gain
+
+    int16_t             m_nCosIncrement;            // increment for gain
+
+    int16_t             m_nRvbLpfFwd;                  // reverb feedback lpf forward gain (includes scaling for mixer)
+
+    int16_t             m_nRvbLpfFbk;                  // reverb feedback lpf feedback gain
+
+    int16_t             m_nRoomLpfFwd;                  // room lpf forward gain (includes scaling for mixer)
+
+    int16_t             m_nRoomLpfFbk;                  // room lpf feedback gain
+
+    uint16_t            m_nXfadeInterval;           // update/xfade after this many samples
+
+    uint16_t            m_nXfadeCounter;            // keep track of when to xfade
+
+    int16_t             m_nPhase;                   // -1 <= m_nPhase < 1
+                                                    // but during sin,cos calculations
+                                                    // use m_nPhase/2
+
+    int16_t             m_nPhaseIncrement;          // add this to m_nPhase each frame
+
+    int16_t             m_nNoise;                   // random noise sample
+
+    uint16_t            m_nMaxExcursion;            // the taps can excurse +/- this amount
+
+    uint16_t            m_bUseNoise;                // if TRUE, use noise as input signal
+
+    uint16_t            m_bBypass;                  // if TRUE, then bypass reverb and copy input to output
+
+    int16_t             m_nCurrentRoom;             // preset number for current room
+
+    int16_t             m_nNextRoom;                // preset number for next room
+
+    int16_t             m_nEarlyGain;               // gain for early (widen) signal
+    int16_t             m_nEarlyDelay;              // initial dealy for early (widen) signal
+    int16_t             m_nEarly0in;
+    int16_t             m_nEarly1in;
+    int16_t             m_nLateGain;               // gain for late reverb
+    int16_t             m_nLateDelay;
+
+    int16_t             m_nDiffusion;
+
+    early_reflection_object_t   m_sEarlyL;          // left channel early reflections
+    early_reflection_object_t   m_sEarlyR;          // right channel early reflections
+
+    short             m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES_MAX];    // one large delay line for all reverb elements
+
+    reverb_preset_t     pPreset;
+
+    reverb_preset_bank_t  m_sPreset;
+
+    //int8_t            preset;
+    uint32_t            m_nSamplingRate;
+    int32_t             m_nUpdatePeriodInBits;
+    int32_t             m_nBufferMask;
+    int32_t             m_nUpdatePeriodInSamples;
+    int32_t             m_nDelay0Out;
+    int32_t             m_nDelay1Out;
+    int16_t             m_nCosWT_5KHz;
+
+    uint16_t            m_Aux;                // if TRUE, is connected as auxiliary effect
+    uint16_t            m_Preset;             // if TRUE, expose preset revert interface
+
+} reverb_object_t;
+
+
+
+typedef struct reverb_module_s {
+    const struct effect_interface_s *itfe;
+    effect_config_t config;
+    reverb_object_t context;
+} reverb_module_t;
+
+/*------------------------------------
+ * Effect API
+ *------------------------------------
+*/
+int EffectQueryNumberEffects(int *pNumEffects);
+int EffectQueryNext(effect_descriptor_t *pDescriptor);
+int EffectCreate(effect_uuid_t *effectUID, effect_interface_t *pInterface);
+int EffectRelease(effect_interface_t interface);
+
+static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData);
+
+
+/*------------------------------------
+ * internal functions
+ *------------------------------------
+*/
+
+int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset);
+int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig, bool init);
+void Reverb_Reset(reverb_object_t *pReverb, bool init);
+
+int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, size_t size, void *pValue);
+int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, void *pValue);
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateXfade
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the xfade parameters as required
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to write to buffer
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - xfade parameters will be changed
+ *
+ *----------------------------------------------------------------------------
+*/
+static int ReverbUpdateXfade(reverb_object_t* pReverbData, int nNumSamplesToAdd);
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateNoise
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a noise sample and limit its value
+ *
+ * Inputs:
+ * Pointer to reverb context
+ *
+ * Outputs:
+ * new limited noise value
+ *
+ * Side Effects:
+ * - pReverbData->m_nNoise value is updated
+ *
+ *----------------------------------------------------------------------------
+*/
+static uint16_t ReverbCalculateNoise(reverb_object_t *pReverbData);
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateSinCos
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a new sin and cosine value based on the given phase
+ *
+ * Inputs:
+ * nPhase   - phase angle
+ * pnSin    - input old value, output new value
+ * pnCos    - input old value, output new value
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * - *pnSin, *pnCos are updated
+ *
+ *----------------------------------------------------------------------------
+*/
+static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos);
+
+/*----------------------------------------------------------------------------
+ * Reverb
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * apply reverb to the given signal
+ *
+ * Inputs:
+ * nNu
+ * pnSin    - input old value, output new value
+ * pnCos    - input old value, output new value
+ *
+ * Outputs:
+ * number of samples actually reverberated
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static int Reverb(reverb_object_t* pReverbData, int nNumSamplesToAdd, short *pOutputBuffer, short *pInputBuffer);
+
+/*----------------------------------------------------------------------------
+ * ReverbReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global reverb preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static int ReverbReadInPresets(reverb_object_t* pReverbData);
+
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateRoom
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the room's preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - reverb paramters (fbk, fwd, etc) will be changed
+ * - m_nCurrentRoom := m_nNextRoom
+ *----------------------------------------------------------------------------
+*/
+static int ReverbUpdateRoom(reverb_object_t* pReverbData, bool fullUpdate);
+
+
+static int ReverbComputeConstants(reverb_object_t *pReverbData, uint32_t samplingRate);
+
+#endif /*ANDROID_EFFECTREVERB_H_*/
diff --git a/media/libeffects/EffectsFactory.c b/media/libeffects/EffectsFactory.c
new file mode 100644
index 0000000..07c4d80
--- /dev/null
+++ b/media/libeffects/EffectsFactory.c
@@ -0,0 +1,602 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsFactory"
+//#define LOG_NDEBUG 0
+
+#include "EffectsFactory.h"
+#include <dlfcn.h>
+
+
+static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
+static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
+static pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER; // controls access to gLibraryList
+static list_elem_t *gCurLib;    // current library in enumeration process
+static list_elem_t *gCurEffect; // current effect in enumeration process
+
+static const char * const gEffectLibPath = "/system/lib/soundfx"; // path to built-in effect libraries
+static int gInitDone; // true is global initialization has been preformed
+
+/////////////////////////////////////////////////
+//      Local functions prototypes
+/////////////////////////////////////////////////
+
+static int init();
+static int loadLibrary(const char *libPath, int *handle);
+static int unloadLibrary(int handle);
+static int numEffectModules();
+static int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc);
+static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len);
+
+/////////////////////////////////////////////////
+//      Effect Control Interface functions
+/////////////////////////////////////////////////
+
+int Effect_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    effect_entry_t *fx = (effect_entry_t *)self;
+    pthread_mutex_lock(&gLibLock);
+    if (fx->lib == NULL) {
+        pthread_mutex_unlock(&gLibLock);
+        return -EPIPE;
+    }
+    pthread_mutex_lock(&fx->lib->lock);
+    pthread_mutex_unlock(&gLibLock);
+
+    ret = (*fx->subItfe)->process(fx->subItfe, inBuffer, outBuffer);
+    pthread_mutex_unlock(&fx->lib->lock);
+    return ret;
+}
+
+int Effect_Command(effect_interface_t self, int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    effect_entry_t *fx = (effect_entry_t *)self;
+    pthread_mutex_lock(&gLibLock);
+    if (fx->lib == NULL) {
+        pthread_mutex_unlock(&gLibLock);
+        return -EPIPE;
+    }
+    pthread_mutex_lock(&fx->lib->lock);
+    pthread_mutex_unlock(&gLibLock);
+
+    ret = (*fx->subItfe)->command(fx->subItfe, cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+    pthread_mutex_unlock(&fx->lib->lock);
+    return ret;
+}
+
+const struct effect_interface_s gInterface = {
+        Effect_Process,
+        Effect_Command
+};
+
+/////////////////////////////////////////////////
+//      Effect Factory Interface functions
+/////////////////////////////////////////////////
+
+int EffectQueryNumberEffects(int *pNumEffects)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (pNumEffects == NULL) {
+        return -EINVAL;
+    }
+
+    pthread_mutex_lock(&gLibLock);
+    *pNumEffects = numEffectModules();
+    pthread_mutex_unlock(&gLibLock);
+    LOGV("EffectQueryNumberEffects(): %d", *pNumEffects);
+    return ret;
+}
+
+int EffectQueryNext(effect_descriptor_t *pDescriptor)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (pDescriptor == NULL) {
+        return -EINVAL;
+    }
+
+    pthread_mutex_lock(&gLibLock);
+    ret = -ENOENT;
+    while (gCurLib) {
+        if (gCurEffect) {
+            memcpy(pDescriptor, gCurEffect->object, sizeof(effect_descriptor_t));
+            gCurEffect = gCurEffect->next;
+            ret = 0;
+            break;
+        } else {
+            gCurLib = gCurLib->next;
+            gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
+        }
+    }
+    char str[256];
+    dumpEffectDescriptor(pDescriptor, str, 256);
+    LOGV("EffectQueryNext() desc:%s", str);
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectGetDescriptor(effect_uuid_t *uuid, effect_descriptor_t *pDescriptor)
+{
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (pDescriptor == NULL || uuid == NULL) {
+        return -EINVAL;
+    }
+    pthread_mutex_lock(&gLibLock);
+    ret = findEffect(uuid, &l, &d);
+    if (ret == 0) {
+        memcpy(pDescriptor, d, sizeof(effect_descriptor_t));
+    }
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectCreate(effect_uuid_t *uuid, effect_interface_t *pInterface)
+{
+    list_elem_t *e = gLibraryList;
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+    effect_interface_t itfe;
+    effect_entry_t *fx;
+    int found = 0;
+    int ret;
+
+    if (uuid == NULL || pInterface == NULL) {
+        return -EINVAL;
+    }
+
+    LOGV("EffectCreate() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+            uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
+            uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2],
+            uuid->node[3],uuid->node[4],uuid->node[5]);
+
+    ret = init();
+
+    if (ret < 0) {
+        LOGW("EffectCreate() init error: %d", ret);
+        return ret;
+    }
+
+    pthread_mutex_lock(&gLibLock);
+
+    ret = findEffect(uuid, &l, &d);
+    if (ret < 0){
+        goto exit;
+    }
+
+    // create effect in library
+    ret = l->createFx(uuid, &itfe);
+    if (ret < 0) {
+        LOGW("EffectCreate() library %s: could not create fx %s", l->path, d->name);
+        goto exit;
+    }
+
+    // add entry to effect list
+    fx = (effect_entry_t *)malloc(sizeof(effect_entry_t));
+    fx->subItfe = itfe;
+    fx->itfe = (struct effect_interface_s *)&gInterface;
+    fx->lib = l;
+
+    e = (list_elem_t *)malloc(sizeof(list_elem_t));
+    e->object = fx;
+    e->next = gEffectList;
+    gEffectList = e;
+
+    *pInterface = (effect_interface_t)fx;
+
+    LOGV("EffectCreate() created entry %p with sub itfe %p in library %s", *pInterface, itfe, l->path);
+
+exit:
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectRelease(effect_interface_t interface)
+{
+    effect_entry_t *fx;
+    list_elem_t *e1;
+    list_elem_t *e2;
+
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+
+    // remove effect from effect list
+    pthread_mutex_lock(&gLibLock);
+    e1 = gEffectList;
+    e2 = NULL;
+    while (e1) {
+        if (e1->object == interface) {
+            if (e2) {
+                e2->next = e1->next;
+            } else {
+                gEffectList = e1->next;
+            }
+            fx = (effect_entry_t *)e1->object;
+            free(e1);
+            break;
+        }
+        e2 = e1;
+        e1 = e1->next;
+    }
+    if (e1 == NULL) {
+        ret = -ENOENT;
+        goto exit;
+    }
+
+    // release effect in library
+    if (fx->lib == NULL) {
+        LOGW("EffectRelease() fx %p library already unloaded", interface);
+    } else {
+        pthread_mutex_lock(&fx->lib->lock);
+        fx->lib->releaseFx(fx->subItfe);
+        pthread_mutex_unlock(&fx->lib->lock);
+    }
+    free(fx);
+
+exit:
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectLoadLibrary(const char *libPath, int *handle)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (libPath == NULL || strnlen(libPath, PATH_MAX) >= PATH_MAX) {
+        return -EINVAL;
+    }
+    return loadLibrary(libPath, handle);
+}
+
+int EffectUnloadLibrary(int handle)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+
+    return unloadLibrary(handle);
+}
+
+int EffectIsNullUuid(effect_uuid_t *uuid)
+{
+    if (memcmp(uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t))) {
+        return 0;
+    }
+    return 1;
+}
+
+/////////////////////////////////////////////////
+//      Local functions
+/////////////////////////////////////////////////
+
+int init() {
+    struct dirent *ent;
+    DIR *dir = NULL;
+    char libpath[PATH_MAX];
+    int hdl;
+
+    if (gInitDone) {
+        return 0;
+    }
+
+    pthread_mutex_init(&gLibLock, NULL);
+
+    // load built-in libraries
+    dir = opendir(gEffectLibPath);
+    if (dir == NULL) {
+        return -ENODEV;
+    }
+    while ((ent = readdir(dir)) != NULL) {
+        LOGV("init() reading file %s", ent->d_name);
+        if ((strlen(ent->d_name) < 3) ||
+            strncmp(ent->d_name, "lib", 3) != 0 ||
+            strncmp(ent->d_name + strlen(ent->d_name) - 3, ".so", 3) != 0) {
+            continue;
+        }
+        strcpy(libpath, gEffectLibPath);
+        strcat(libpath, "/");
+        strcat(libpath, ent->d_name);
+        if (loadLibrary(libpath, &hdl) < 0) {
+            LOGW("init() failed to load library %s",libpath);
+        }
+    }
+    closedir(dir);
+
+    gInitDone = 1;
+    LOGV("init() done");
+    return 0;
+}
+
+
+int loadLibrary(const char *libPath, int *handle)
+{
+    void *hdl;
+    effect_QueryNumberEffects_t queryNumFx;
+    effect_QueryNextEffect_t queryFx;
+    effect_CreateEffect_t createFx;
+    effect_ReleaseEffect_t releaseFx;
+    int numFx;
+    int fx;
+    int ret;
+    list_elem_t *e, *descHead = NULL;
+    lib_entry_t *l;
+
+    if (handle == NULL) {
+        return -EINVAL;
+    }
+
+    *handle = 0;
+
+    hdl = dlopen(libPath, RTLD_NOW);
+    if (hdl == 0) {
+        LOGW("could open lib %s", libPath);
+        return -ENODEV;
+    }
+
+    // Check functions availability
+    queryNumFx = (effect_QueryNumberEffects_t)dlsym(hdl, "EffectQueryNumberEffects");
+    if (queryNumFx == NULL) {
+        LOGW("could not get EffectQueryNumberEffects from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+    queryFx = (effect_QueryNextEffect_t)dlsym(hdl, "EffectQueryNext");
+    if (queryFx == NULL) {
+        LOGW("could not get EffectQueryNext from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+    createFx = (effect_CreateEffect_t)dlsym(hdl, "EffectCreate");
+    if (createFx == NULL) {
+        LOGW("could not get EffectCreate from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+    releaseFx = (effect_ReleaseEffect_t)dlsym(hdl, "EffectRelease");
+    if (releaseFx == NULL) {
+        LOGW("could not get EffectRelease from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+
+    // load effect descriptors
+    ret = queryNumFx(&numFx);
+    if (ret) {
+        goto error;
+    }
+
+    for (fx = 0; fx < numFx; fx++) {
+        effect_descriptor_t *d = malloc(sizeof(effect_descriptor_t));
+        if (d == NULL) {
+            ret = -ENOMEM;
+            goto error;
+        }
+        ret = queryFx(d);
+        if (ret == 0) {
+#if (LOG_NDEBUG==0)
+            char s[256];
+            dumpEffectDescriptor(d, s, 256);
+            LOGV("loadLibrary() read descriptor %p:%s",d, s);
+#endif
+            if (d->apiVersion != EFFECT_API_VERSION) {
+                LOGW("Bad API version %04x on lib %s", d->apiVersion, libPath);
+                free(d);
+                continue;
+            }
+            e = malloc(sizeof(list_elem_t));
+            if (e == NULL) {
+                free(d);
+                ret = -ENOMEM;
+                goto error;
+            }
+            e->object = d;
+            e->next = descHead;
+            descHead = e;
+        } else {
+            LOGW("Error querying effect # %d on lib %s", fx, libPath);
+        }
+    }
+    // add entry for library in gLibraryList
+    l = malloc(sizeof(lib_entry_t));
+    l->handle = hdl;
+    strncpy(l->path, libPath, PATH_MAX);
+    l->createFx = createFx;
+    l->releaseFx = releaseFx;
+    l->effects = descHead;
+    pthread_mutex_init(&l->lock, NULL);
+
+    e = malloc(sizeof(list_elem_t));
+    pthread_mutex_lock(&gLibLock);
+    e->next = gLibraryList;
+    e->object = l;
+    gLibraryList = e;
+    pthread_mutex_unlock(&gLibLock);
+    LOGV("loadLibrary() linked library %p", l);
+
+    *handle = (int)hdl;
+
+    return 0;
+
+error:
+    LOGW("loadLibrary() error: %d on lib: %s", ret, libPath);
+    while (descHead) {
+        free(descHead->object);
+        e = descHead->next;
+        free(descHead);
+        descHead = e;;
+    }
+    dlclose(hdl);
+    return ret;
+}
+
+int unloadLibrary(int handle)
+{
+    void *hdl;
+    int ret;
+    list_elem_t *el1, *el2;
+    lib_entry_t *l;
+    effect_entry_t *fx;
+
+    pthread_mutex_lock(&gLibLock);
+    el1 = gLibraryList;
+    el2 = NULL;
+    while (el1) {
+        l = (lib_entry_t *)el1->object;
+        if (handle == (int)l->handle) {
+            if (el2) {
+                el2->next = el1->next;
+            } else {
+                gLibraryList = el1->next;
+            }
+            free(el1);
+            break;
+        }
+        el2 = el1;
+        el1 = el1->next;
+    }
+    pthread_mutex_unlock(&gLibLock);
+    if (el1 == NULL) {
+        return -ENOENT;
+    }
+
+    // clear effect descriptor list
+    el1 = l->effects;
+    while (el1) {
+        free(el1->object);
+        el2 = el1->next;
+        free(el1);
+        el1 = el2;
+    }
+
+    // disable all effects from this library
+    pthread_mutex_lock(&l->lock);
+    el1 = gEffectList;
+    while (el1) {
+        fx = (effect_entry_t *)el1->object;
+        if (fx->lib == l) {
+            fx->lib = NULL;
+        }
+        el1 = el1->next;
+    }
+    pthread_mutex_unlock(&l->lock);
+
+    dlclose(l->handle);
+    free(l);
+    return 0;
+}
+
+
+
+int numEffectModules() {
+    list_elem_t *e = gLibraryList;
+    int cnt = 0;
+
+    // Reset pointers for EffectQueryNext()
+    gCurLib = e;
+    if (e) {
+        gCurEffect = ((lib_entry_t *)e->object)->effects;
+    }
+    while (e) {
+        lib_entry_t *l = (lib_entry_t *)e->object;
+        list_elem_t *efx = l->effects;
+        while (efx) {
+            cnt++;
+            efx = efx->next;
+        }
+        e = e->next;
+    }
+    return cnt;
+}
+
+int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc)
+{
+    list_elem_t *e = gLibraryList;
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+    int found = 0;
+    int ret = 0;
+
+    while (e && !found) {
+        l = (lib_entry_t *)e->object;
+        list_elem_t *efx = l->effects;
+        while (efx) {
+            d = (effect_descriptor_t *)efx->object;
+            if (memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
+                found = 1;
+                break;
+            }
+            efx = efx->next;
+        }
+        e = e->next;
+    }
+    if (!found) {
+        LOGV("findEffect() effect not found");
+        ret = -ENOENT;
+    } else {
+        LOGV("findEffect() found effect: %s in lib %s", d->name, l->path);
+        *lib = l;
+        *desc = d;
+    }
+
+    return ret;
+}
+
+void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len) {
+    char s[256];
+
+    snprintf(str, len, "\nEffect Descriptor %p:\n", desc);
+    sprintf(s, "- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+            desc->uuid.timeLow, desc->uuid.timeMid, desc->uuid.timeHiAndVersion,
+            desc->uuid.clockSeq, desc->uuid.node[0], desc->uuid.node[1],desc->uuid.node[2],
+            desc->uuid.node[3],desc->uuid.node[4],desc->uuid.node[5]);
+    strncat(str, s, len);
+    sprintf(s, "- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+                desc->type.timeLow, desc->type.timeMid, desc->type.timeHiAndVersion,
+                desc->type.clockSeq, desc->type.node[0], desc->type.node[1],desc->type.node[2],
+                desc->type.node[3],desc->type.node[4],desc->type.node[5]);
+    strncat(str, s, len);
+    sprintf(s, "- apiVersion: %04X\n- flags: %08X\n",
+            desc->apiVersion, desc->flags);
+    strncat(str, s, len);
+    sprintf(s, "- name: %s\n", desc->name);
+    strncat(str, s, len);
+    sprintf(s, "- implementor: %s\n", desc->implementor);
+    strncat(str, s, len);
+}
+
diff --git a/media/libeffects/EffectsFactory.h b/media/libeffects/EffectsFactory.h
new file mode 100644
index 0000000..17ad3f0
--- /dev/null
+++ b/media/libeffects/EffectsFactory.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 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_EFFECTSFACTORY_H_
+#define ANDROID_EFFECTSFACTORY_H_
+
+#include <cutils/log.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <media/EffectFactoryApi.h>
+
+
+#if __cplusplus
+extern "C" {
+#endif
+
+typedef struct list_elem_s {
+    void *object;
+    struct list_elem_s *next;
+} list_elem_t;
+
+typedef struct lib_entry_s {
+    char path[PATH_MAX];
+    void *handle;
+    effect_CreateEffect_t createFx;
+    effect_ReleaseEffect_t releaseFx;
+    list_elem_t *effects; //list of effect_descriptor_t
+    pthread_mutex_t lock;
+} lib_entry_t;
+
+typedef struct effect_entry_s {
+    struct effect_interface_s *itfe;
+    effect_interface_t subItfe;
+    lib_entry_t *lib;
+} effect_entry_t;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTSFACTORY_H_*/
diff --git a/media/libeffects/EffectsMath.c b/media/libeffects/EffectsMath.c
new file mode 100644
index 0000000..41ec662
--- /dev/null
+++ b/media/libeffects/EffectsMath.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "EFFECTSMATH"
+//#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <assert.h>
+
+#include "EffectsMath.h"
+
+// gLogTab contains pre-calculated values of log2(1 + ai5*2^-1 + ai4*2^-2 + ai3*2^-3 + ai2*2^-4 + ai1*2^-5 + ai0*2^-6)
+// for integers in the range 0 to 63 (i = ai5*2^5 + ai4*2^4 + ai3*2^3 + ai2*2^2 + ai1*2^1 + ai0*2^0)
+// It is used for a better than piece wise approximation of lin to log2 conversion
+
+static const uint16_t gLogTab[] =
+{
+    0, 733, 1455, 2166,
+    2866, 3556, 4236, 4907,
+    5568, 6220, 6863, 7498,
+    8124, 8742, 9352, 9954,
+    10549, 11136, 11716, 12289,
+    12855, 13415, 13968, 14514,
+    15055, 15589, 16117, 16639,
+    17156, 17667, 18173, 18673,
+    19168, 19658, 20143, 20623,
+    21098, 21568, 22034, 22495,
+    22952, 23404, 23852, 24296,
+    24736, 25172, 25604, 26031,
+    26455, 26876, 27292, 27705,
+    28114, 28520, 28922, 29321,
+    29717, 30109, 30498, 30884,
+    31267, 31647, 32024, 32397,
+    32768
+};
+
+int32_t Effects_log2(uint32_t x) {
+    int32_t exp = 31 - __builtin_clz(x);
+    uint32_t segStart = x >> (exp - 6);
+    uint32_t i = segStart & 0x3F;
+    int32_t log = (int32_t)gLogTab[i];
+    int32_t logEnd = (int32_t)gLogTab[i+1];
+    segStart <<= exp - 6;
+
+    return (exp << 15) + log + (((x - segStart) * (logEnd - log)) >> (exp - 6));
+}
+
+// gExpTab[i] = (2^(i>>6)) << 22
+static const uint32_t gExpTab[] = {
+            4194304, 4239977, 4286147, 4332820,
+            4380002, 4427697, 4475911, 4524651,
+            4573921, 4623728, 4674077, 4724974,
+            4776426, 4828438, 4881016, 4934167,
+            4987896, 5042211, 5097117, 5152621,
+            5208729, 5265449, 5322786, 5380747,
+            5439339, 5498570, 5558445, 5618973,
+            5680159, 5742012, 5804539, 5867746,
+            5931642, 5996233, 6061528, 6127533,
+            6194258, 6261709, 6329894, 6398822,
+            6468501, 6538938, 6610143, 6682122,
+            6754886, 6828442, 6902799, 6977965,
+            7053950, 7130763, 7208412, 7286906,
+            7366255, 7446469, 7527555, 7609525,
+            7692387, 7776152, 7860829, 7946428,
+            8032959, 8120432, 8208857, 8298246,
+            8388608
+};
+
+
+uint32_t Effects_exp2(int32_t x) {
+    int32_t i = x >> 15;
+    assert(i < 32);
+    x &= (1 << 15) - 1;
+    int32_t j = x >> 9;
+    x &= (1 << 9) - 1;
+    uint32_t exp = gExpTab[j];
+    uint32_t expEnd = gExpTab[j+1];
+
+    return ((exp << 9) + (expEnd - exp) * x) >> (31 - i);
+}
+
+
+int16_t Effects_MillibelsToLinear16 (int32_t nGain)
+{
+    nGain = ((nGain + MB_TO_LIN_K1) << 15 ) / MB_TO_LIN_K2;
+    uint32_t exp2 = Effects_exp2(nGain);
+
+    if (exp2 > 32767) exp2 = 32767;
+
+    return (int16_t)exp2;
+}
+
+
+int16_t Effects_Linear16ToMillibels (int32_t nGain)
+{
+    return (int16_t)(((MB_TO_LIN_K2*Effects_log2(nGain))>>15)-MB_TO_LIN_K1);
+}
+
+
+int32_t Effects_Sqrt(int32_t in)
+{
+    int32_t tmp;
+    int32_t out = 0;
+    int32_t i;
+    int32_t j;
+
+
+    if (in == 0) return 0;
+
+    if (in >= 0x10000000)
+    {
+        out = 0x4000;
+        in -= 0x10000000;
+    }
+
+    j = 32 - __builtin_clz(in);
+
+    if (j & 1) j++;
+    j >>= 1;
+
+    for (i = j; i > 0; i--) {
+        tmp = (out << i) + (1 << ((i - 1)*2));
+        if (in >= tmp)
+        {
+            out += 1 << (i-1);
+            in -= tmp;
+        }
+    }
+
+    return out;
+}
+
diff --git a/media/libeffects/EffectsMath.h b/media/libeffects/EffectsMath.h
new file mode 100644
index 0000000..2a44399
--- /dev/null
+++ b/media/libeffects/EffectsMath.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2008 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_EFFECTSMATH_H_
+#define ANDROID_EFFECTSMATH_H_
+
+#include <stdint.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/** coefs for pan, generates sin, cos */
+#define COEFF_PAN_G2    -27146    /* -0.82842712474619 = 2 - 4/sqrt(2) */
+#define COEFF_PAN_G0    23170     /* 0.707106781186547 = 1/sqrt(2) */
+
+/*
+coefficients for approximating
+2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3
+where x is a int.frac number representing number of octaves.
+Actually, we approximate only the 2^(frac) using the power series
+and implement the 2^(int) as a shift, so that
+2^x == 2^(int.frac) == 2^(int) * 2^(fract)
+    == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int)
+
+The gn2toX.. were generated using a best fit for a 3rd
+order polynomial, instead of taking the coefficients from
+a truncated Taylor (or Maclaurin?) series.
+*/
+
+#define GN2_TO_X0    32768    /*    1                    */
+#define GN2_TO_X1    22833    /*    0.696807861328125    */
+#define GN2_TO_X2    7344    /*    0.22412109375        */
+#define GN2_TO_X3    2588    /*    0.0789794921875        */
+
+/*----------------------------------------------------------------------------
+ * Fixed Point Math
+ *----------------------------------------------------------------------------
+ * These macros are used for fixed point multiplies. If the processor
+ * supports fixed point multiplies, replace these macros with inline
+ * assembly code to improve performance.
+ *----------------------------------------------------------------------------
+*/
+
+/* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */
+#define FMUL_15x15(a,b) \
+    /*lint -e(704) <avoid multiply for performance>*/ \
+    (((int32_t)(a) * (int32_t)(b)) >> 15)
+
+/* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */
+#define FMUL_7x7(a,b) \
+    /*lint -e(704) <avoid multiply for performance>*/ \
+    (((int32_t)(a) * (int32_t)(b) ) << 1)
+
+/* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */
+#define FMUL_8x8(a,b) \
+    /*lint -e(704) <avoid multiply for performance>*/ \
+    (((int32_t)(a) * (int32_t)(b) ) >> 1)
+
+/* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */
+#define FMUL_8x15(a,b) \
+    /*lint -e(704) <avoid divide for performance>*/ \
+    (((int32_t)((a) << 7) * (int32_t)(b)) >> 15)
+
+/* macros for fractional phase accumulator */
+/*
+Note: changed the _U32 to _I32 on 03/14/02. This should not
+affect the phase calculations, and should allow us to reuse these
+macros for other audio sample related math.
+*/
+#define HARDWARE_BIT_WIDTH        32
+
+#define NUM_PHASE_INT_BITS        1
+#define NUM_PHASE_FRAC_BITS       15
+
+#define PHASE_FRAC_MASK           (uint32_t) ((0x1L << NUM_PHASE_FRAC_BITS) -1)
+
+#define GET_PHASE_INT_PART(x)     (uint32_t)((uint32_t)(x) >> NUM_PHASE_FRAC_BITS)
+#define GET_PHASE_FRAC_PART(x)    (uint32_t)((uint32_t)(x) & PHASE_FRAC_MASK)
+
+#define DEFAULT_PHASE_FRAC        0
+#define DEFAULT_PHASE_INT         0
+
+/*
+Linear interpolation calculates:
+output = (1-frac) * sample[n] + (frac) * sample[n+1]
+
+where conceptually    0 <= frac < 1
+
+For a fixed point implementation, frac is actually an integer value
+with an implied binary point one position to the left. The value of
+one (unity) is given by PHASE_ONE
+one half and one quarter are useful for 4-point linear interp.
+*/
+#define PHASE_ONE                (int32_t) (0x1L << NUM_PHASE_FRAC_BITS)
+
+/*
+ Multiply the signed audio sample by the unsigned fraction.
+-  a is the signed audio sample
+-  b is the unsigned fraction (cast to signed int as long as coef
+    uses (n-1) or less bits, where n == hardware bit width)
+*/
+#define MULT_AUDIO_COEF(audio,coef)         /*lint -e704 <avoid divide for performance>*/ \
+            (int32_t)(                                    \
+            (                                            \
+                ((int32_t)(audio)) * ((int32_t)(coef))    \
+            )                                            \
+            >> NUM_PHASE_FRAC_BITS                        \
+                                        )                \
+                                        /* lint +704 <restore checking>*/
+
+/* wet / dry calculation macros */
+#define NUM_WET_DRY_FRAC_BITS       7    // 15
+#define NUM_WET_DRY_INT_BITS        9    // 1
+
+/* define a 1.0 */
+#define WET_DRY_ONE                 (int32_t) ((0x1L << NUM_WET_DRY_FRAC_BITS))
+#define WET_DRY_MINUS_ONE           (int32_t) (~WET_DRY_ONE)
+#define WET_DRY_FULL_SCALE          (int32_t) (WET_DRY_ONE - 1)
+
+#define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) <avoid divide for performance>*/ \
+            (int32_t)(                                        \
+            (                                                \
+                ((int32_t)(audio)) * ((int32_t)(coef))        \
+            )                                                \
+            >> NUM_WET_DRY_FRAC_BITS                        \
+                                                     )
+
+/* Envelope 1 (EG1) calculation macros */
+#define    NUM_EG1_INT_BITS          1
+#define NUM_EG1_FRAC_BITS            15
+
+/* the max positive gain used in the synth for EG1 */
+/* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas
+converter, otherwise, the values we read from the .eas file are bogus. */
+#define SYNTH_FULL_SCALE_EG1_GAIN    (int32_t) ((0x1L << NUM_EG1_FRAC_BITS) -1)
+
+/* define a 1.0 */
+#define EG1_ONE                      (int32_t) ((0x1L << NUM_EG1_FRAC_BITS))
+#define EG1_MINUS_ONE                (int32_t) (~SYNTH_FULL_SCALE_EG1_GAIN)
+
+#define EG1_HALF                     (int32_t) (EG1_ONE/2)
+#define EG1_MINUS_HALF               (int32_t) (EG1_MINUS_ONE/2)
+
+/*
+We implement the EG1 using a linear gain value, which means that the
+attack segment is handled by incrementing (adding) the linear gain.
+However, EG1 treats the Decay, Sustain, and Release differently than
+the Attack portion. For Decay, Sustain, and Release, the gain is
+linear on dB scale, which is equivalent to exponential damping on
+a linear scale. Because we use a linear gain for EG1, we implement
+the Decay and Release as multiplication (instead of incrementing
+as we did for the attack segment).
+Therefore, we need the following macro to implement the multiplication
+(i.e., exponential damping) during the Decay and Release segments of
+the EG1
+*/
+#define MULT_EG1_EG1(gain,damping)        /*lint -e(704) <avoid divide for performance>*/ \
+            (int32_t)(                                        \
+            (                                                \
+                ((int32_t)(gain)) * ((int32_t)(damping))    \
+            )                                                \
+            >> NUM_EG1_FRAC_BITS                            \
+                                        )
+
+// Use the following macro specifically for the filter, when multiplying
+// the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow
+// in certain conditions because we store b1 as a 1.15 value.
+// Instead, we could store b1 as b1p (b1' == b1 "prime") where
+// b1p == b1/2, thus ensuring no potential overflow for b1p because
+// 0 <= |b1p| < 1
+// However, during the filter calculation, we must account for the fact
+// that we are using b1p instead of b1, and thereby multiply by
+// an extra factor of 2. Rather than multiply by an extra factor of 2,
+// we can instead shift the result right by one less, hence the
+// modified shift right value of (NUM_EG1_FRAC_BITS -1)
+#define MULT_EG1_EG1_X2(gain,damping)         /*lint -e(702) <avoid divide for performance>*/ \
+            (int32_t)(                                        \
+            (                                                \
+                ((int32_t)(gain)) * ((int32_t)(damping))    \
+            )                                                \
+            >> (NUM_EG1_FRAC_BITS -1)                        \
+                                        )
+
+#define SATURATE_EG1(x)        /*lint -e{734} saturation operation */                \
+    ((int32_t)(x) > SYNTH_FULL_SCALE_EG1_GAIN)    ? (SYNTH_FULL_SCALE_EG1_GAIN) :    \
+    ((int32_t)(x) < EG1_MINUS_ONE)                ? (EG1_MINUS_ONE) :    (x);
+
+
+/* use "digital cents" == "dents" instead of cents */
+/* we coudl re-use the phase frac macros, but if we do,
+we must change the phase macros to cast to _I32 instead of _U32,
+because using a _U32 cast causes problems when shifting the exponent
+for the 2^x calculation, because right shift a negative values MUST
+be sign extended, or else the 2^x calculation is wrong */
+
+/* use "digital cents" == "dents" instead of cents */
+#define NUM_DENTS_FRAC_BITS        12
+#define NUM_DENTS_INT_BITS         (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS)
+
+#define DENTS_FRAC_MASK            (int32_t) ((0x1L << NUM_DENTS_FRAC_BITS) -1)
+
+#define GET_DENTS_INT_PART(x)        /*lint -e(704) <avoid divide for performance>*/    \
+                            (int32_t)((int32_t)(x) >> NUM_DENTS_FRAC_BITS)
+
+#define GET_DENTS_FRAC_PART(x)     (int32_t)((int32_t)(x) & DENTS_FRAC_MASK)
+
+#define DENTS_ONE                  (int32_t) (0x1L << NUM_DENTS_FRAC_BITS)
+
+/* use CENTS_TO_DENTS to convert a value in cents to dents */
+#define CENTS_TO_DENTS (int32_t) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L)                            \
+
+
+/*
+For gain, the LFO generates a value that modulates in terms
+of dB. However, we use a linear gain value, so we must convert
+the LFO value in dB to a linear gain. Normally, we would use
+linear gain = 10^x, where x = LFO value in dB / 20.
+Instead, we implement 10^x using our 2^x approximation.
+because
+
+  10^x = 2^(log2(10^x)) = 2^(x * log2(10))
+
+so we need to multiply by log2(10) which is just a constant.
+Ah, but just wait -- our 2^x actually doesn't exactly implement
+2^x, but it actually assumes that the input is in cents, and within
+the 2^x approximation converts its input from cents to octaves
+by dividing its input by 1200.
+
+So, in order to convert the LFO gain value in dB to something
+that our existing 2^x approximation can use, multiply the LFO gain
+by log2(10) * 1200 / 20
+
+The divide by 20 helps convert dB to linear gain, and we might
+as well incorporate that operation into this conversion.
+Of course, we need to keep some fractional bits, so multiply
+the constant by NUM_EG1_FRAC_BITS
+*/
+
+/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */
+#if 0
+#define    DOUBLE_LOG2_10    (double) (3.32192809488736)    /* log2(10) */
+
+#define    DOUBLE_LFO_GAIN_TO_CENTS    (double)                \
+    (                                                        \
+                (DOUBLE_LOG2_10) *                            \
+                1200.0    /                                    \
+                20.0                                        \
+    )
+
+#define    LFO_GAIN_TO_CENTS    (int32_t)                        \
+    (                                                        \
+                DOUBLE_LFO_GAIN_TO_CENTS *                    \
+                (0x1L << NUM_EG1_FRAC_BITS)                    \
+    )
+#endif
+
+#define LFO_GAIN_TO_CENTS (int32_t) (1671981156L >> (23 - NUM_EG1_FRAC_BITS))
+
+
+#define MULT_DENTS_COEF(dents,coef)     /*lint -e704 <avoid divide for performance>*/    \
+            (int32_t)(                                    \
+            (                                            \
+                ((int32_t)(dents)) * ((int32_t)(coef))    \
+            )                                            \
+            >> NUM_DENTS_FRAC_BITS                        \
+                                        )                \
+                                        /* lint +e704 <restore checking>*/
+
+
+/* we use 16-bits in the PC per audio sample */
+#define BITS_PER_AUDIO_SAMPLE    16
+
+/* we define 1 as 1.0 - 1 LSbit */
+#define DISTORTION_ONE           (int32_t)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1)
+#define DISTORTION_MINUS_ONE     (int32_t)(~DISTORTION_ONE)
+
+/* drive coef is given as int.frac */
+#define NUM_DRIVE_COEF_INT_BITS  1
+#define NUM_DRIVE_COEF_FRAC_BITS 4
+
+#define MULT_AUDIO_DRIVE(audio,drive)         /*lint -e(702) <avoid divide for performance>*/ \
+            (int32_t)    (                                \
+            (                                            \
+                ((int32_t)(audio)) * ((int32_t)(drive))    \
+            )                                            \
+            >> NUM_DRIVE_COEF_FRAC_BITS                    \
+                                                )
+
+#define MULT_AUDIO_AUDIO(audio1,audio2)         /*lint -e(702) <avoid divide for performance>*/ \
+            (int32_t)    (                                    \
+            (                                                \
+                ((int32_t)(audio1)) * ((int32_t)(audio2))    \
+            )                                                \
+            >> (BITS_PER_AUDIO_SAMPLE-1)                    \
+                                                    )
+
+#define SATURATE(x)                                                            \
+    ((((int32_t)(x)) > DISTORTION_ONE)        ? (DISTORTION_ONE) :            \
+    (((int32_t)(x)) < DISTORTION_MINUS_ONE)    ? (DISTORTION_MINUS_ONE) :    ((int32_t)(x)));
+
+
+/*----------------------------------------------------------------------------
+ * Effects_log2()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Fixed-point log2 function.
+ *
+ * Inputs:
+ * Input is interpreted as an integer (should not be 0).
+ *
+ * Outputs:
+ * Output is in 15-bit precision.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+int32_t Effects_log2(uint32_t x);
+
+/*----------------------------------------------------------------------------
+ * Effects_exp2()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Fixed-point radix-2 exponent.
+ *
+ * Inputs:
+ * Input is in 15-bit precision. Must be non-negative and less than 32.
+ *
+ * Outputs:
+ * Output is an integer.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+uint32_t Effects_exp2(int32_t x);
+
+/*----------------------------------------------------------------------------
+ * Effects_MillibelsToLinear16()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform gain in millibels to linear gain multiplier:
+ *
+ * mB = 2000*log(lin/32767)
+ *    => lin = 2^((mB+2000*log(32767))/2000*log(2))
+ *    => lin = Effects_exp2(((mB + K1) << 15) / K2)
+ * with:
+ *    K1 = 2000*log(32767) and K2 = 2000*log(2)
+ *
+ * Inputs:
+ * nGain - log scale value in millibels.
+ *
+ * Outputs:
+ * Returns a 16-bit linear value approximately equal to 2^(nGain/1024)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+#define MB_TO_LIN_K1 9031
+#define MB_TO_LIN_K2 602
+int16_t Effects_MillibelsToLinear16 (int32_t nGain);
+
+/*----------------------------------------------------------------------------
+ * Effects_Linear16ToMillibels()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform linear gain multiplier to millibels
+ *  mB = 2000*log(lin/32767)
+ *     = 2000*log(2)*log2(lin)-2000*log(32767)
+ *    => mB = K1*Effects_log2(lin) + K2
+ * with:
+ *    K1 = 2000*log(2) and K2 = -2000*log(32767)
+ *
+ * Inputs:
+ * nGain - linear multiplier ranging form 0 to 32767 (corresponding to [0 1] gain range).
+ *
+ * Outputs:
+ * Returns a 16-bit log value expressed in milllibels.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+int16_t Effects_Linear16ToMillibels (int32_t nGain);
+
+/*----------------------------------------------------------------------------
+ * Effects_Sqrt()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the square root of the argument given.
+ *
+ * Inputs:
+ * in - positive number in the range 0 - 2^28
+ *
+ * Outputs:
+ * Returned value: square root of in.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+int32_t Effects_Sqrt(int32_t in);
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+#endif /*ANDROID_EFFECTSMATH_H_*/
+