1a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent/*
2a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent * Copyright (C) 2011 The Android Open Source Project
3a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent *
4a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
5a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent * you may not use this file except in compliance with the License.
6a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent * You may obtain a copy of the License at
7a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent *
8a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
9a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent *
10a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent * Unless required by applicable law or agreed to in writing, software
11a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
12a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent * See the License for the specific language governing permissions and
14a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent * limitations under the License.
15a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent */
16a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
17a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include <stdlib.h>
18a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include <string.h>
19a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#define LOG_TAG "PreProcessing"
20a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//#define LOG_NDEBUG 0
21a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include <utils/Log.h>
22a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include <utils/Timers.h>
23a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include <hardware/audio_effect.h>
24a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include <audio_effects/effect_aec.h>
25a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include <audio_effects/effect_agc.h>
26a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include <audio_effects/effect_ns.h>
275387696d25bc710f8cd0e6d08079e2aa8d6c1417Eric Laurent#include <module_common_types.h>
285387696d25bc710f8cd0e6d08079e2aa8d6c1417Eric Laurent#include <audio_processing.h>
29a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include "speex/speex_resampler.h"
30a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
313f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent// undefine to perform multi channels API functional tests
323f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent//#define DUAL_MIC_TEST
33a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
34a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
35a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// local definitions
36a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
37a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
38a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// maximum number of sessions
39a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#define PREPROC_NUM_SESSIONS 8
40a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
41a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// types of pre processing modules
42a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentenum preproc_id
43a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
44a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_AGC,        // Automatic Gain Control
45a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_AEC,        // Acoustic Echo Canceler
46a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_NS,         // Noise Suppressor
47a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_NUM_EFFECTS
48a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
49a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
50a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Session state
51a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentenum preproc_session_state {
52a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_SESSION_STATE_INIT,        // initialized
53a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_SESSION_STATE_CONFIG       // configuration received
54a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
55a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
56a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect/Preprocessor state
57a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentenum preproc_effect_state {
58a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_EFFECT_STATE_INIT,         // initialized
59a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_EFFECT_STATE_CREATED,      // webRTC engine created
60a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_EFFECT_STATE_CONFIG,       // configuration received/disabled
61a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_EFFECT_STATE_ACTIVE        // active/enabled
62a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
63a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
64a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// handle on webRTC engine
65a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenttypedef void* preproc_fx_handle_t;
66a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
67a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenttypedef struct preproc_session_s preproc_session_t;
68a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenttypedef struct preproc_effect_s preproc_effect_t;
69a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenttypedef struct preproc_ops_s preproc_ops_t;
70a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
71a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
72a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Function pointer can be null if no action required.
73a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstruct preproc_ops_s {
74a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* create)(preproc_effect_t *fx);
75a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* init)(preproc_effect_t *fx);
76a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* reset)(preproc_effect_t *fx);
77a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    void (* enable)(preproc_effect_t *fx);
78a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    void (* disable)(preproc_effect_t *fx);
79a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* set_parameter)(preproc_effect_t *fx, void *param, void *value);
80b302bd5d288be2d3363b80053ca2392560b00b25Ashok Bhat    int (* get_parameter)(preproc_effect_t *fx, void *param, uint32_t *size, void *value);
81a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* set_device)(preproc_effect_t *fx, uint32_t device);
82a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
83a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
84a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect context
85a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstruct preproc_effect_s {
86a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    const struct effect_interface_s *itfe;
87a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t procId;                // type of pre processor (enum preproc_id)
88a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t state;                 // current state (enum preproc_effect_state)
89a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_session_t *session;     // session the effect is on
90a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    const preproc_ops_t *ops;       // effect ops table
91a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_fx_handle_t engine;     // handle on webRTC engine
92766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    uint32_t type;                  // subtype of effect
933f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#ifdef DUAL_MIC_TEST
943f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    bool aux_channels_on;           // support auxiliary channels
953f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    size_t cur_channel_config;      // current auciliary channel configuration
963f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#endif
97a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
98a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
99a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Session context
100a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstruct preproc_session_s {
101a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session
102a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t state;                     // current state (enum preproc_session_state)
103a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int id;                             // audio session ID
104a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int io;                             // handle of input stream this session is on
105a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::AudioProcessing* apm;       // handle on webRTC audio processing module (APM)
106a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t apmFrameCount;               // buffer size for webRTC process (10 ms)
107a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t apmSamplingRate;           // webRTC APM sampling rate (8/16 or 32 kHz)
108a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t frameCount;                  // buffer size before input resampler ( <=> apmFrameCount)
109a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t samplingRate;              // sampling rate at effect process interface
110a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t inChannelCount;            // input channel count
111a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t outChannelCount;           // output channel count
112a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t createdMsk;                // bit field containing IDs of crested pre processors
113a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t enabledMsk;                // bit field containing IDs of enabled pre processors
114a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t processedMsk;              // bit field containing IDs of pre processors already
115a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                        // processed in current round
116a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::AudioFrame *procFrame;      // audio frame passed to webRTC AMP ProcessStream()
117a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int16_t *inBuf;                     // input buffer used when resampling
118a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t inBufSize;                   // input buffer size in frames
119a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t framesIn;                    // number of frames in input buffer
120a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    SpeexResamplerState *inResampler;   // handle on input speex resampler
121a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int16_t *outBuf;                    // output buffer used when resampling
122a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t outBufSize;                  // output buffer size in frames
123a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t framesOut;                   // number of frames in output buffer
124a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    SpeexResamplerState *outResampler;  // handle on output speex resampler
125a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t revChannelCount;           // number of channels on reverse stream
126a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t revEnabledMsk;             // bit field containing IDs of enabled pre processors
127a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                        // with reverse channel
128a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t revProcessedMsk;           // bit field containing IDs of pre processors with reverse
129a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                        // channel already processed in current round
130a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::AudioFrame *revFrame;       // audio frame passed to webRTC AMP AnalyzeReverseStream()
131a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int16_t *revBuf;                    // reverse channel input buffer
132a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t revBufSize;                  // reverse channel input buffer size
133a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t framesRev;                   // number of frames in reverse channel input buffer
134a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    SpeexResamplerState *revResampler;  // handle on reverse channel input speex resampler
135a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
136a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1373f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#ifdef DUAL_MIC_TEST
1383f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurentenum {
1393f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode
1403f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    PREPROC_CMD_DUAL_MIC_PCM_DUMP_START,                        // start pcm capture
1413f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP                          // stop pcm capture
1423f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent};
1433f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
1443f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurentenum {
1453f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    CHANNEL_CFG_MONO,
1463f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    CHANNEL_CFG_STEREO,
1473f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    CHANNEL_CFG_MONO_AUX,
1483f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    CHANNEL_CFG_STEREO_AUX,
1493f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    CHANNEL_CFG_CNT,
1503f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    CHANNEL_CFG_FIRST_AUX = CHANNEL_CFG_MONO_AUX,
1513f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent};
1523f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
1533f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurentconst channel_config_t sDualMicConfigs[CHANNEL_CFG_CNT] = {
1543f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        {AUDIO_CHANNEL_IN_MONO , 0},
1553f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        {AUDIO_CHANNEL_IN_STEREO , 0},
1563f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        {AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
1573f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        {AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
1583f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent};
1593f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
1603f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurentbool sHasAuxChannels[PREPROC_NUM_EFFECTS] = {
1613f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        false,   // PREPROC_AGC
1623f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        true,   // PREPROC_AEC
1633f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        true,   // PREPROC_NS
1643f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent};
1653f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
1663f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurentbool gDualMicEnabled;
1673f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric LaurentFILE *gPcmDumpFh;
1683f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurentstatic pthread_mutex_t gPcmDumpLock = PTHREAD_MUTEX_INITIALIZER;
1693f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#endif
1703f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
1713f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
172a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
173a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect descriptors
174a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
175a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
176a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
177a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// as the pre processing effects are not defined by OpenSL ES
178a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
179a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Automatic Gain Control
180a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const effect_descriptor_t sAgcDescriptor = {
181a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
182a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
183a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        EFFECT_CONTROL_API_VERSION,
184a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
185a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate CPU load
186a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate memory usage
187a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "Automatic Gain Control",
188a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "The Android Open Source Project"
189a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
190a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
191a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Acoustic Echo Cancellation
192a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const effect_descriptor_t sAecDescriptor = {
193a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
194a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
195a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        EFFECT_CONTROL_API_VERSION,
196a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
197a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate CPU load
198a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate memory usage
199a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "Acoustic Echo Canceler",
200a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "The Android Open Source Project"
201a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
202a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
203a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Noise suppression
204a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const effect_descriptor_t sNsDescriptor = {
205a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
206a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
207a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        EFFECT_CONTROL_API_VERSION,
208a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
209a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate CPU load
210a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate memory usage
211a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "Noise Suppression",
212a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "The Android Open Source Project"
213a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
214a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
215a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
216a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = {
217a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sAgcDescriptor,
218a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sAecDescriptor,
219a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sNsDescriptor
220a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
221a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
222a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
223a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Helper functions
224a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
225a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
226a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentconst effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {
227a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        FX_IID_AGC,
228a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        FX_IID_AEC,
229a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        FX_IID_NS
230a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
231a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
232a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
233a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentconst effect_uuid_t * ProcIdToUuid(int procId)
234a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
235a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (procId >= PREPROC_NUM_EFFECTS) {
236a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return EFFECT_UUID_NULL;
237a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
238a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return sUuidToPreProcTable[procId];
239a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
240a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
241a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentuint32_t UuidToProcId(const effect_uuid_t * uuid)
242a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
243a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
244a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
245a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
246a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
247a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
248a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
249a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return i;
250a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
251a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
252a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentbool HasReverseStream(uint32_t procId)
253a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
254a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (procId == PREPROC_AEC) {
255a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return true;
256a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
257a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return false;
258a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
259a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
260a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
261a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
262a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Automatic Gain Control (AGC)
263a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
264a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
2655387696d25bc710f8cd0e6d08079e2aa8d6c1417Eric Laurentstatic const int kAgcDefaultTargetLevel = 3;
2665387696d25bc710f8cd0e6d08079e2aa8d6c1417Eric Laurentstatic const int kAgcDefaultCompGain = 9;
267a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const bool kAgcDefaultLimiter = true;
268a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
269a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  AgcInit (preproc_effect_t *effect)
270a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
2713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcInit");
272a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
273a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->set_mode(webrtc::GainControl::kFixedDigital);
274a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
275a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->set_compression_gain_db(kAgcDefaultCompGain);
276a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->enable_limiter(kAgcDefaultLimiter);
277a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
278a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
279a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
280a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  AgcCreate(preproc_effect_t *effect)
281a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
282a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = effect->session->apm->gain_control();
2833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcCreate got agc %p", agc);
284a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (agc == NULL) {
2855ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcCreate Error");
286a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENOMEM;
287a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
288a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->engine = static_cast<preproc_fx_handle_t>(agc);
289a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    AgcInit(effect);
290a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
291a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
292a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
293a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint AgcGetParameter(preproc_effect_t *effect,
294a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    void *pParam,
295b302bd5d288be2d3363b80053ca2392560b00b25Ashok Bhat                    uint32_t *pValueSize,
296a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    void *pValue)
297a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
298a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
299a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t param = *(uint32_t *)pParam;
300a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    t_agc_settings *pProperties = (t_agc_settings *)pValue;
301a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
302a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
303a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
304a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_TARGET_LEVEL:
305a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_COMP_GAIN:
306a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (*pValueSize < sizeof(int16_t)) {
307a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *pValueSize = 0;
308a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
309a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
310a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
311a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_LIMITER_ENA:
312a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (*pValueSize < sizeof(bool)) {
313a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *pValueSize = 0;
314a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
315a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
316a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
317a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_PROPERTIES:
318a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (*pValueSize < sizeof(t_agc_settings)) {
319a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *pValueSize = 0;
320a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
321a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
322a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
323a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
324a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
3255ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcGetParameter() unknown param %08x", param);
326a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
327a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
328a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
329a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
330a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
331a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_TARGET_LEVEL:
332a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        *(int16_t *) pValue = (int16_t)(agc->target_level_dbfs() * -100);
3333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue);
334a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
335a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_COMP_GAIN:
336a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        *(int16_t *) pValue = (int16_t)(agc->compression_gain_db() * 100);
3373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue);
338a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
339a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_LIMITER_ENA:
340a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        *(bool *) pValue = (bool)agc->is_limiter_enabled();
3413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcGetParameter() limiter enabled %s",
342a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent             (*(int16_t *) pValue != 0) ? "true" : "false");
343a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
344a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_PROPERTIES:
345a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
346a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
347a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
348a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
349a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
3505ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcGetParameter() unknown param %d", param);
351a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
352a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
353a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
354a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
355a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
356a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
357a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint AgcSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
358a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
359a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
360a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t param = *(uint32_t *)pParam;
361a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    t_agc_settings *pProperties = (t_agc_settings *)pValue;
362a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
363a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
364a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
365a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_TARGET_LEVEL:
3663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue);
367a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->set_target_level_dbfs(-(*(int16_t *)pValue / 100));
368a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
369a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_COMP_GAIN:
3703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue);
371a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->set_compression_gain_db(*(int16_t *)pValue / 100);
372a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
373a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_LIMITER_ENA:
3743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false");
375a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->enable_limiter(*(bool *)pValue);
376a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
377a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_PROPERTIES:
3783856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
379a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent             pProperties->targetLevel,
380a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent             pProperties->compGain,
381a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent             pProperties->limiterEnabled);
382a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
383a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (status != 0) break;
384a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->set_compression_gain_db(pProperties->compGain / 100);
385a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (status != 0) break;
386a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->enable_limiter(pProperties->limiterEnabled);
387a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
388a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
3895ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
390a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
391a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
392a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
393a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
3943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcSetParameter() done status %d", status);
395a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
396a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
397a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
398a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
399a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid AgcEnable(preproc_effect_t *effect)
400a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
401a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
4023856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcEnable agc %p", agc);
403a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->Enable(true);
404a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
405a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
406a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid AgcDisable(preproc_effect_t *effect)
407a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
4083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcDisable");
409a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
410a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->Enable(false);
411a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
412a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
413a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
414a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const preproc_ops_t sAgcOps = {
415a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcCreate,
416a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcInit,
417a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL,
418a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcEnable,
419a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcDisable,
420a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcSetParameter,
421a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcGetParameter,
422a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL
423a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
424a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
425a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
426a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
427a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Acoustic Echo Canceler (AEC)
428a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
429a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
430a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
431a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        webrtc::EchoControlMobile::kEarpiece;
432a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const bool kAecDefaultComfortNoise = true;
433a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
434a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  AecInit (preproc_effect_t *effect)
435a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
4363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecInit");
437a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
438a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->set_routing_mode(kAecDefaultMode);
439a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->enable_comfort_noise(kAecDefaultComfortNoise);
440a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
441a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
442a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
443a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  AecCreate(preproc_effect_t *effect)
444a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
445a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = effect->session->apm->echo_control_mobile();
4463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecCreate got aec %p", aec);
447a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (aec == NULL) {
4485ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcCreate Error");
449a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENOMEM;
450a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
451a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->engine = static_cast<preproc_fx_handle_t>(aec);
452a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    AecInit (effect);
453a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
454a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
455a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
456b302bd5d288be2d3363b80053ca2392560b00b25Ashok Bhatint AecGetParameter(preproc_effect_t  *effect,
457a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    void              *pParam,
458b302bd5d288be2d3363b80053ca2392560b00b25Ashok Bhat                    uint32_t          *pValueSize,
459a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    void              *pValue)
460a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
461a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
462a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t param = *(uint32_t *)pParam;
463a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
464a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (*pValueSize < sizeof(uint32_t)) {
465a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
466a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
467a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
468a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AEC_PARAM_ECHO_DELAY:
469a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AEC_PARAM_PROPERTIES:
470a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        *(uint32_t *)pValue = 1000 * effect->session->apm->stream_delay_ms();
4713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AecGetParameter() echo delay %d us", *(uint32_t *)pValue);
472a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
473a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
4745ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
475a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
476a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
477a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
478a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
479a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
480a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
481a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint AecSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
482a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
483a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
484a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t param = *(uint32_t *)pParam;
485a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t value = *(uint32_t *)pValue;
486a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
487a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
488a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AEC_PARAM_ECHO_DELAY:
489a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AEC_PARAM_PROPERTIES:
490a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = effect->session->apm->set_stream_delay_ms(value/1000);
4913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
492a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
493a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
4945ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
495a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
496a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
497a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
498a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
499a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
500a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
501a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid AecEnable(preproc_effect_t *effect)
502a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
503a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
5043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecEnable aec %p", aec);
505a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->Enable(true);
506a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
507a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
508a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid AecDisable(preproc_effect_t *effect)
509a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
5103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecDisable");
511a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
512a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->Enable(false);
513a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
514a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
515a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint AecSetDevice(preproc_effect_t *effect, uint32_t device)
516a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
5173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecSetDevice %08x", device);
518a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
519a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
520a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
5218895925e38d2521607fd2010f3f3b14ecd15962cEric Laurent    if (audio_is_input_device(device)) {
5228895925e38d2521607fd2010f3f3b14ecd15962cEric Laurent        return 0;
5238895925e38d2521607fd2010f3f3b14ecd15962cEric Laurent    }
5248895925e38d2521607fd2010f3f3b14ecd15962cEric Laurent
525a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch(device) {
526a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AUDIO_DEVICE_OUT_EARPIECE:
527a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        mode = webrtc::EchoControlMobile::kEarpiece;
528a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
529a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AUDIO_DEVICE_OUT_SPEAKER:
530a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        mode = webrtc::EchoControlMobile::kSpeakerphone;
531a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
532a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AUDIO_DEVICE_OUT_WIRED_HEADSET:
533a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
534904d632a24db8f94de83e44f7179d1c0af022b03Eric Laurent    case AUDIO_DEVICE_OUT_USB_HEADSET:
535a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
536a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
537a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
538a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->set_routing_mode(mode);
539a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
540a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
541a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
542a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const preproc_ops_t sAecOps = {
543a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecCreate,
544a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecInit,
545a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL,
546a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecEnable,
547a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecDisable,
548a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecSetParameter,
549a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecGetParameter,
550a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecSetDevice
551a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
552a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
553a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
554a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Noise Suppression (NS)
555a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
556a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
557a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
558a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
559a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  NsInit (preproc_effect_t *effect)
560a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
5613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("NsInit");
562a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
563a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    ns->set_level(kNsDefaultLevel);
564766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    webrtc::Config config;
565766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    std::vector<webrtc::Point> geometry;
566766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    // TODO(aluebs): Make the geometry settable.
567766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f));
568766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f));
569766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f));
570766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f));
571766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    // The geometry needs to be set with Beamforming enabled.
572766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    config.Set<webrtc::Beamforming>(
573766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            new webrtc::Beamforming(true, geometry));
574766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    effect->session->apm->SetExtraOptions(config);
575766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    config.Set<webrtc::Beamforming>(
576766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            new webrtc::Beamforming(false, geometry));
577766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    effect->session->apm->SetExtraOptions(config);
578766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    effect->type = NS_TYPE_SINGLE_CHANNEL;
579a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
580a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
581a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
582a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  NsCreate(preproc_effect_t *effect)
583a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
584a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression();
5853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("NsCreate got ns %p", ns);
586a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (ns == NULL) {
5875ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcCreate Error");
588a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENOMEM;
589a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
590a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->engine = static_cast<preproc_fx_handle_t>(ns);
591a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    NsInit (effect);
592a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
593a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
594a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
5950f714a464d2425afe00d6450535e763131b40844Eric Laurentint NsGetParameter(preproc_effect_t  *effect __unused,
5960f714a464d2425afe00d6450535e763131b40844Eric Laurent                   void              *pParam __unused,
5970f714a464d2425afe00d6450535e763131b40844Eric Laurent                   uint32_t          *pValueSize __unused,
5980f714a464d2425afe00d6450535e763131b40844Eric Laurent                   void              *pValue __unused)
599a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
600a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
601a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
602a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
603a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
604766bf734984a0d5765980f8bd154d111de08ec19Alex Luebsint NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
605a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
606a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
607766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
608766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    uint32_t param = *(uint32_t *)pParam;
609766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    uint32_t value = *(uint32_t *)pValue;
610766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    switch(param) {
611766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        case NS_PARAM_LEVEL:
612766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            ns->set_level((webrtc::NoiseSuppression::Level)value);
613766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            ALOGV("NsSetParameter() level %d", value);
614766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            break;
615766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        case NS_PARAM_TYPE:
616766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        {
617766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            webrtc::Config config;
618766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            std::vector<webrtc::Point> geometry;
619766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            bool is_beamforming_enabled =
620766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs                    value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled();
621766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            config.Set<webrtc::Beamforming>(
622766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs                    new webrtc::Beamforming(is_beamforming_enabled, geometry));
623766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            effect->session->apm->SetExtraOptions(config);
624766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            effect->type = value;
625766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            ALOGV("NsSetParameter() type %d", value);
626766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            break;
627766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        }
628766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        default:
629766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
630766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs            status = -EINVAL;
631766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    }
632766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs
633a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
634a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
635a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
636a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid NsEnable(preproc_effect_t *effect)
637a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
638a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
6393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("NsEnable ns %p", ns);
640a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    ns->Enable(true);
641766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    if (effect->type == NS_TYPE_MULTI_CHANNEL) {
642766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        webrtc::Config config;
643766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        std::vector<webrtc::Point> geometry;
644766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
645766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        effect->session->apm->SetExtraOptions(config);
646766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    }
647a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
648a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
649a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid NsDisable(preproc_effect_t *effect)
650a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
6513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("NsDisable");
652a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
653a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    ns->Enable(false);
654766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    webrtc::Config config;
655766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    std::vector<webrtc::Point> geometry;
656766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
657766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs    effect->session->apm->SetExtraOptions(config);
658a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
659a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
660a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const preproc_ops_t sNsOps = {
661a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsCreate,
662a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsInit,
663a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL,
664a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsEnable,
665a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsDisable,
666a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsSetParameter,
667a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsGetParameter,
668a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL
669a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
670a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
671a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
672a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = {
673a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sAgcOps,
674a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sAecOps,
675a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sNsOps
676a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
677a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
678a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
679a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
680a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect functions
681a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
682a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
683a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled);
684a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
685a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentextern "C" const struct effect_interface_s sEffectInterface;
686a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentextern "C" const struct effect_interface_s sEffectInterfaceReverse;
687a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
688a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#define BAD_STATE_ABORT(from, to) \
689a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
690a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
691a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Effect_SetState(preproc_effect_t *effect, uint32_t state)
692a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
693a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
6943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
695a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch(state) {
696a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case PREPROC_EFFECT_STATE_INIT:
697a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        switch(effect->state) {
698a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_ACTIVE:
699a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            effect->ops->disable(effect);
700a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            Session_SetProcEnabled(effect->session, effect->procId, false);
701a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CONFIG:
702a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CREATED:
703a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_INIT:
704a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
705a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
706a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            BAD_STATE_ABORT(effect->state, state);
707a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
708a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
709a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case PREPROC_EFFECT_STATE_CREATED:
710a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        switch(effect->state) {
711a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_INIT:
712a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            status = effect->ops->create(effect);
713a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
714a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CREATED:
715a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_ACTIVE:
716a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CONFIG:
71729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Effect_SetState invalid transition");
718a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            status = -ENOSYS;
719a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
720a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
721a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            BAD_STATE_ABORT(effect->state, state);
722a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
723a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
724a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case PREPROC_EFFECT_STATE_CONFIG:
725a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        switch(effect->state) {
726a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_INIT:
72729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Effect_SetState invalid transition");
728a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            status = -ENOSYS;
729a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
730a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_ACTIVE:
731a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            effect->ops->disable(effect);
732a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            Session_SetProcEnabled(effect->session, effect->procId, false);
733a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
734a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CREATED:
735a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CONFIG:
736a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
737a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
738a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            BAD_STATE_ABORT(effect->state, state);
739a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
740a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
741a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case PREPROC_EFFECT_STATE_ACTIVE:
742a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        switch(effect->state) {
743a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_INIT:
744a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CREATED:
74529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Effect_SetState invalid transition");
746a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            status = -ENOSYS;
747a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
7483f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        case PREPROC_EFFECT_STATE_ACTIVE:
7493f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            // enabling an already enabled effect is just ignored
7503f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            break;
751a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CONFIG:
752a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            effect->ops->enable(effect);
753a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            Session_SetProcEnabled(effect->session, effect->procId, true);
754a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
755a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
756a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            BAD_STATE_ABORT(effect->state, state);
757a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
758a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
759a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
760a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        BAD_STATE_ABORT(effect->state, state);
761a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
762a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status == 0) {
763a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->state = state;
764a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
765a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
766a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
767a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
768a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Effect_Init(preproc_effect_t *effect, uint32_t procId)
769a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
770a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (HasReverseStream(procId)) {
771a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->itfe = &sEffectInterfaceReverse;
772a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
773a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->itfe = &sEffectInterface;
774a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
775a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->ops = sPreProcOps[procId];
776a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->procId = procId;
777a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->state = PREPROC_EFFECT_STATE_INIT;
778a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
779a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
780a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
781a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Effect_Create(preproc_effect_t *effect,
782a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent               preproc_session_t *session,
783a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent               effect_handle_t  *interface)
784a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
785a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->session = session;
786a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    *interface = (effect_handle_t)&effect->itfe;
787a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
788a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
789a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
790a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Effect_Release(preproc_effect_t *effect)
791a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
792a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
793a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
794a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
795a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
796a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
797a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Session functions
798a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
799a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
800a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
801a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
802a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const int kPreprocDefaultSr = 16000;
803a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const int kPreProcDefaultCnl = 1;
804a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
805a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Session_Init(preproc_session_t *session)
806a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
807a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
808a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
809a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
810a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->state = PREPROC_SESSION_STATE_INIT;
811a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->id = 0;
812a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->io = 0;
813a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->createdMsk = 0;
814a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->apm = NULL;
815a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
816a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = Effect_Init(&session->effects[i], i);
817a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
818a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
819a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
820a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
821a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
822a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentextern "C" int Session_CreateEffect(preproc_session_t *session,
823a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    int32_t procId,
824a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    effect_handle_t  *interface)
825a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
826a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = -ENOMEM;
827a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
8283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
829a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
830a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->createdMsk == 0) {
8319718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs        session->apm = webrtc::AudioProcessing::Create();
832a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->apm == NULL) {
8335ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_CreateEffect could not get apm engine");
834a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            goto error;
835a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
8369718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs        const webrtc::ProcessingConfig processing_config = {
8379718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs            {{kPreprocDefaultSr, kPreProcDefaultCnl},
8389718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs             {kPreprocDefaultSr, kPreProcDefaultCnl},
8399718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs             {kPreprocDefaultSr, kPreProcDefaultCnl},
8409718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs             {kPreprocDefaultSr, kPreProcDefaultCnl}}};
8419718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs        session->apm->Initialize(processing_config);
842a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->procFrame = new webrtc::AudioFrame();
843a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->procFrame == NULL) {
8445ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_CreateEffect could not allocate audio frame");
845a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            goto error;
846a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
847a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revFrame = new webrtc::AudioFrame();
848a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->revFrame == NULL) {
8495ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_CreateEffect could not allocate reverse audio frame");
850a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            goto error;
851a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
852a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmSamplingRate = kPreprocDefaultSr;
853a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmFrameCount = (kPreprocDefaultSr) / 100;
854a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->frameCount = session->apmFrameCount;
855a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->samplingRate = kPreprocDefaultSr;
856a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inChannelCount = kPreProcDefaultCnl;
857a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outChannelCount = kPreProcDefaultCnl;
858de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh        session->procFrame->sample_rate_hz_ = kPreprocDefaultSr;
859de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh        session->procFrame->num_channels_ = kPreProcDefaultCnl;
860a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revChannelCount = kPreProcDefaultCnl;
861de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh        session->revFrame->sample_rate_hz_ = kPreprocDefaultSr;
862de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh        session->revFrame->num_channels_ = kPreProcDefaultCnl;
863a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->enabledMsk = 0;
864a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->processedMsk = 0;
865a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revEnabledMsk = 0;
866a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revProcessedMsk = 0;
867a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inResampler = NULL;
868a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inBuf = NULL;
869a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inBufSize = 0;
870a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outResampler = NULL;
871a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outBuf = NULL;
872a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outBufSize = 0;
873a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revResampler = NULL;
874a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revBuf = NULL;
875a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revBufSize = 0;
876a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
877a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    status = Effect_Create(&session->effects[procId], session, interface);
878a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0) {
879a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        goto error;
880a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
8813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_CreateEffect OK");
882a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->createdMsk |= (1<<procId);
883a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
884a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
885a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenterror:
886a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->createdMsk == 0) {
887a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->revFrame;
888a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revFrame = NULL;
889a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->procFrame;
890a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->procFrame = NULL;
8919718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs        delete session->apm;
892a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apm = NULL;
893a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
894a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
895a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
896a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
897a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Session_ReleaseEffect(preproc_session_t *session,
898a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                          preproc_effect_t *fx)
899a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
9005ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block    ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
901a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->createdMsk &= ~(1<<fx->procId);
902a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->createdMsk == 0) {
9039718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs        delete session->apm;
904a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apm = NULL;
905a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->procFrame;
906a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->procFrame = NULL;
907a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->revFrame;
908a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revFrame = NULL;
909a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->inResampler != NULL) {
910a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->inResampler);
911a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->inResampler = NULL;
912a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
913a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->outResampler != NULL) {
914a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->outResampler);
915a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->outResampler = NULL;
916a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
917a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->revResampler != NULL) {
918a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->revResampler);
919a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->revResampler = NULL;
920a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
921a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->inBuf;
922a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inBuf = NULL;
923a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->outBuf;
924a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outBuf = NULL;
925a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->revBuf;
926a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revBuf = NULL;
927a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
928a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->io = 0;
929a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
930a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
931a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
932a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
933a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
934a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
935a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Session_SetConfig(preproc_session_t *session, effect_config_t *config)
936a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
9373f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs    uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
9383f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs    uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
939a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
940a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
941a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        config->inputCfg.format != config->outputCfg.format ||
942a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
943a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
944a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
945a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
9463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_SetConfig sr %d cnl %08x",
947a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent         config->inputCfg.samplingRate, config->inputCfg.channels);
948a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status;
949a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
950a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    // AEC implementation is limited to 16kHz
951a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
952a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmSamplingRate = 32000;
953a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else
954a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate >= 16000) {
955a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmSamplingRate = 16000;
956a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else if (config->inputCfg.samplingRate >= 8000) {
957a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmSamplingRate = 8000;
958a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
9599718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs
9609718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs    const webrtc::ProcessingConfig processing_config = {
9613f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs      {{static_cast<int>(session->apmSamplingRate), inCnl},
9623f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs       {static_cast<int>(session->apmSamplingRate), outCnl},
9633f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs       {static_cast<int>(session->apmSamplingRate), inCnl},
9643f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs       {static_cast<int>(session->apmSamplingRate), inCnl}}};
9659718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs    status = session->apm->Initialize(processing_config);
966a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0) {
967a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
968a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
969a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
970a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->samplingRate = config->inputCfg.samplingRate;
971a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->apmFrameCount = session->apmSamplingRate / 100;
972a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->samplingRate == session->apmSamplingRate) {
973a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->frameCount = session->apmFrameCount;
974a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
975a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->frameCount = (session->apmFrameCount * session->samplingRate) /
976a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->apmSamplingRate  + 1;
977a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
978a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->inChannelCount = inCnl;
979a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->outChannelCount = outCnl;
980de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh    session->procFrame->num_channels_ = inCnl;
981de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh    session->procFrame->sample_rate_hz_ = session->apmSamplingRate;
982a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
983a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revChannelCount = inCnl;
984de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh    session->revFrame->num_channels_ = inCnl;
985de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh    session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
986a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
9873f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    // force process buffer reallocation
9883f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    session->inBufSize = 0;
9893f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    session->outBufSize = 0;
9903f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    session->framesIn = 0;
9913f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    session->framesOut = 0;
9923f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
9933f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
994a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->inResampler != NULL) {
995a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        speex_resampler_destroy(session->inResampler);
996a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inResampler = NULL;
997a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
998a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->outResampler != NULL) {
999a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        speex_resampler_destroy(session->outResampler);
1000a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outResampler = NULL;
1001a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1002a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->revResampler != NULL) {
1003a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        speex_resampler_destroy(session->revResampler);
1004a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revResampler = NULL;
1005a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1006a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->samplingRate != session->apmSamplingRate) {
1007a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        int error;
1008a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inResampler = speex_resampler_init(session->inChannelCount,
1009a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->samplingRate,
1010a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->apmSamplingRate,
1011a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    RESAMPLER_QUALITY,
1012a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    &error);
1013a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->inResampler == NULL) {
10145ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_SetConfig Cannot create speex resampler: %s",
1015a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                 speex_resampler_strerror(error));
1016a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
1017a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1018a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outResampler = speex_resampler_init(session->outChannelCount,
1019a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->apmSamplingRate,
1020a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->samplingRate,
1021a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    RESAMPLER_QUALITY,
1022a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    &error);
1023a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->outResampler == NULL) {
10245ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_SetConfig Cannot create speex resampler: %s",
1025a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                 speex_resampler_strerror(error));
1026a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->inResampler);
1027a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->inResampler = NULL;
1028a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
1029a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1030a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revResampler = speex_resampler_init(session->inChannelCount,
1031a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->samplingRate,
1032a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->apmSamplingRate,
1033a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    RESAMPLER_QUALITY,
1034a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    &error);
1035a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->revResampler == NULL) {
10365ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_SetConfig Cannot create speex resampler: %s",
1037a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                 speex_resampler_strerror(error));
1038a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->inResampler);
1039a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->inResampler = NULL;
1040a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->outResampler);
1041a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->outResampler = NULL;
1042a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
1043a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1044a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1045a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1046a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->state = PREPROC_SESSION_STATE_CONFIG;
1047a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
1048a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1049a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
10503d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurentvoid Session_GetConfig(preproc_session_t *session, effect_config_t *config)
10513d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent{
10523d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    memset(config, 0, sizeof(effect_config_t));
10533d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
10543d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1055ab334fd351ae5a0e18903da123d63e565b536874Glenn Kasten    config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount);
1056ab334fd351ae5a0e18903da123d63e565b536874Glenn Kasten    // "out" doesn't mean output device, so this is the correct API to convert channel count to mask
1057ab334fd351ae5a0e18903da123d63e565b536874Glenn Kasten    config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount);
10583d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.mask = config->outputCfg.mask =
10593d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
10603d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent}
10613d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
1062a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config)
1063a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1064a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
1065a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            config->inputCfg.format != config->outputCfg.format ||
1066a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
1067a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1068a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1069a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
10703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_SetReverseConfig sr %d cnl %08x",
1071a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent         config->inputCfg.samplingRate, config->inputCfg.channels);
1072a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1073a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->state < PREPROC_SESSION_STATE_CONFIG) {
1074a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENOSYS;
1075a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1076a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate != session->samplingRate ||
1077a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
1078a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1079a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1080e541269be94f3a1072932d51537905b120ef4733Andy Hung    uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
10819718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs    const webrtc::ProcessingConfig processing_config = {
10823f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs       {{static_cast<int>(session->apmSamplingRate), session->inChannelCount},
10833f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs        {static_cast<int>(session->apmSamplingRate), session->outChannelCount},
10843f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs        {static_cast<int>(session->apmSamplingRate), inCnl},
10853f11ef01574219f323a7f9ee4216d610733df50fAlex Luebs        {static_cast<int>(session->apmSamplingRate), inCnl}}};
10869718b7d9cba77c739269462ac57d43cc6ae69134Alex Luebs    int status = session->apm->Initialize(processing_config);
1087a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0) {
1088a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1089a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1090a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revChannelCount = inCnl;
1091de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh    session->revFrame->num_channels_ = inCnl;
1092de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh    session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
10933f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    // force process buffer reallocation
10943f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    session->revBufSize = 0;
10953f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent    session->framesRev = 0;
10963f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
1097a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
1098a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1099a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
11003d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurentvoid Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config)
11013d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent{
11023d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    memset(config, 0, sizeof(effect_config_t));
11033d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
11043d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
11053d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.channels = config->outputCfg.channels =
1106ab334fd351ae5a0e18903da123d63e565b536874Glenn Kasten            audio_channel_in_mask_from_count(session->revChannelCount);
11073d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.mask = config->outputCfg.mask =
11083d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
11093d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent}
11103d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
1111a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled)
1112a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1113a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (enabled) {
1114a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if(session->enabledMsk == 0) {
1115a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn = 0;
1116a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inResampler != NULL) {
1117a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_reset_mem(session->inResampler);
1118a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1119a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesOut = 0;
1120a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->outResampler != NULL) {
1121a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_reset_mem(session->outResampler);
1122a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1123a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1124a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->enabledMsk |= (1 << procId);
1125a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (HasReverseStream(procId)) {
1126a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev = 0;
1127a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->revResampler != NULL) {
1128a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_reset_mem(session->revResampler);
1129a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1130a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->revEnabledMsk |= (1 << procId);
1131a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1132a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
1133a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->enabledMsk &= ~(1 << procId);
1134a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (HasReverseStream(procId)) {
1135a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->revEnabledMsk &= ~(1 << procId);
1136a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1137a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
11383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x",
1139a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent         procId, enabled, session->enabledMsk, session->revEnabledMsk);
1140a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->processedMsk = 0;
1141a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (HasReverseStream(procId)) {
1142a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revProcessedMsk = 0;
1143a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1144a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1145a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1146a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1147a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Bundle functions
1148a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1149a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1150a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic int sInitStatus = 1;
1151a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
1152a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1153a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentpreproc_session_t *PreProc_GetSession(int32_t procId, int32_t  sessionId, int32_t  ioId)
1154a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1155a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
1156a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
1157a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (sSessions[i].io == ioId) {
1158a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (sSessions[i].createdMsk & (1 << procId)) {
1159a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return NULL;
1160a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1161a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return &sSessions[i];
1162a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1163a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1164a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
1165a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (sSessions[i].io == 0) {
1166a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            sSessions[i].id = sessionId;
1167a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            sSessions[i].io = ioId;
1168a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return &sSessions[i];
1169a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1170a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1171a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return NULL;
1172a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1173a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1174a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1175a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProc_Init() {
1176a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
1177a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
1178a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1179a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (sInitStatus <= 0) {
1180a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return sInitStatus;
1181a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1182a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
1183a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = Session_Init(&sSessions[i]);
1184a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1185a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    sInitStatus = status;
1186a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return sInitStatus;
1187a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1188a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
11895e92a7861196ddae14638d4b7a63fc4892b7ef59Glenn Kastenconst effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid)
1190a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1191a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
1192a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
1193a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
1194a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return sDescriptors[i];
1195a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1196a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1197a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return NULL;
1198a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1199a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1200a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1201a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentextern "C" {
1202a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1203a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1204a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect Control Interface Implementation
1205a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1206a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1207a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingFx_Process(effect_handle_t     self,
1208a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            audio_buffer_t    *inBuffer,
1209a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            audio_buffer_t    *outBuffer)
1210a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1211a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t * effect = (preproc_effect_t *)self;
1212a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1213a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (effect == NULL){
12143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
1215a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1216a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1217a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_session_t * session = (preproc_session_t *)effect->session;
1218a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1219a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (inBuffer == NULL  || inBuffer->raw == NULL  ||
1220a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            outBuffer == NULL || outBuffer->raw == NULL){
12215ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("PreProcessingFx_Process() ERROR bad pointer");
1222a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1223a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1224a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1225a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->processedMsk |= (1<<effect->procId);
1226a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
12273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block//    ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
1228a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//         inBuffer->frameCount, session->enabledMsk, session->processedMsk);
1229a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1230a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
1231a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->session->processedMsk = 0;
1232a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        size_t framesRq = outBuffer->frameCount;
1233a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        size_t framesWr = 0;
1234a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->framesOut) {
1235a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->framesOut;
1236a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (outBuffer->frameCount < fr) {
1237a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = outBuffer->frameCount;
1238a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1239a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(outBuffer->s16,
1240a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                  session->outBuf,
1241a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                  fr * session->outChannelCount * sizeof(int16_t));
1242a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->outBuf,
1243a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                  session->outBuf + fr * session->outChannelCount,
1244a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                  (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
1245a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesOut -= fr;
1246a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            framesWr += fr;
1247a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1248a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        outBuffer->frameCount = framesWr;
1249a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (framesWr == framesRq) {
1250a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = 0;
1251a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return 0;
1252a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1253a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1254a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->inResampler != NULL) {
1255a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->frameCount - session->framesIn;
1256a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (inBuffer->frameCount < fr) {
1257a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = inBuffer->frameCount;
1258a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1259a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inBufSize < session->framesIn + fr) {
1260679650f008a6dee59d89238fab17edd208a1878eEric Laurent                int16_t *buf;
1261a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->inBufSize = session->framesIn + fr;
1262679650f008a6dee59d89238fab17edd208a1878eEric Laurent                buf = (int16_t *)realloc(session->inBuf,
1263a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                 session->inBufSize * session->inChannelCount * sizeof(int16_t));
1264679650f008a6dee59d89238fab17edd208a1878eEric Laurent                if (buf == NULL) {
1265679650f008a6dee59d89238fab17edd208a1878eEric Laurent                    session->framesIn = 0;
1266679650f008a6dee59d89238fab17edd208a1878eEric Laurent                    free(session->inBuf);
1267679650f008a6dee59d89238fab17edd208a1878eEric Laurent                    session->inBuf = NULL;
1268679650f008a6dee59d89238fab17edd208a1878eEric Laurent                    return -ENOMEM;
1269679650f008a6dee59d89238fab17edd208a1878eEric Laurent                }
1270679650f008a6dee59d89238fab17edd208a1878eEric Laurent                session->inBuf = buf;
1271a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1272a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->inBuf + session->framesIn * session->inChannelCount,
1273a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   inBuffer->s16,
1274a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   fr * session->inChannelCount * sizeof(int16_t));
12753f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#ifdef DUAL_MIC_TEST
12763f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            pthread_mutex_lock(&gPcmDumpLock);
12773f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (gPcmDumpFh != NULL) {
12783f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                fwrite(inBuffer->raw,
12793f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                       fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
12803f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
12813f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            pthread_mutex_unlock(&gPcmDumpLock);
12823f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#endif
1283a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1284a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn += fr;
1285a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = fr;
1286a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->framesIn < session->frameCount) {
1287a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return 0;
1288a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1289377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            spx_uint32_t frIn = session->framesIn;
1290377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            spx_uint32_t frOut = session->apmFrameCount;
1291a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inChannelCount == 1) {
1292a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_int(session->inResampler,
1293a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            0,
1294a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            session->inBuf,
1295a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            &frIn,
1296de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh                                            session->procFrame->data_,
1297a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            &frOut);
1298a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            } else {
1299a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_interleaved_int(session->inResampler,
1300a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        session->inBuf,
1301a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        &frIn,
1302de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh                                                        session->procFrame->data_,
1303a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        &frOut);
1304a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1305a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->inBuf,
1306a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   session->inBuf + frIn * session->inChannelCount,
1307a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
1308a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn -= frIn;
1309a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } else {
1310a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->frameCount - session->framesIn;
1311a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (inBuffer->frameCount < fr) {
1312a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = inBuffer->frameCount;
1313a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1314de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh            memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount,
1315a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   inBuffer->s16,
1316a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   fr * session->inChannelCount * sizeof(int16_t));
13173f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
13183f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#ifdef DUAL_MIC_TEST
13193f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            pthread_mutex_lock(&gPcmDumpLock);
13203f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (gPcmDumpFh != NULL) {
13213f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                fwrite(inBuffer->raw,
13223f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                       fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
13233f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
13243f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            pthread_mutex_unlock(&gPcmDumpLock);
13253f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#endif
13263f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
1327a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn += fr;
1328a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = fr;
1329a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->framesIn < session->frameCount) {
1330a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return 0;
1331a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1332a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn = 0;
1333a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1334766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        session->procFrame->samples_per_channel_ = session->apmFrameCount;
1335a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1336a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->session->apm->ProcessStream(session->procFrame);
1337a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1338a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->outBufSize < session->framesOut + session->frameCount) {
1339679650f008a6dee59d89238fab17edd208a1878eEric Laurent            int16_t *buf;
1340a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->outBufSize = session->framesOut + session->frameCount;
1341679650f008a6dee59d89238fab17edd208a1878eEric Laurent            buf = (int16_t *)realloc(session->outBuf,
1342679650f008a6dee59d89238fab17edd208a1878eEric Laurent                             session->outBufSize * session->outChannelCount * sizeof(int16_t));
1343679650f008a6dee59d89238fab17edd208a1878eEric Laurent            if (buf == NULL) {
1344679650f008a6dee59d89238fab17edd208a1878eEric Laurent                session->framesOut = 0;
1345679650f008a6dee59d89238fab17edd208a1878eEric Laurent                free(session->outBuf);
1346679650f008a6dee59d89238fab17edd208a1878eEric Laurent                session->outBuf = NULL;
1347679650f008a6dee59d89238fab17edd208a1878eEric Laurent                return -ENOMEM;
1348679650f008a6dee59d89238fab17edd208a1878eEric Laurent            }
1349679650f008a6dee59d89238fab17edd208a1878eEric Laurent            session->outBuf = buf;
1350a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1351a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1352a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->outResampler != NULL) {
1353377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            spx_uint32_t frIn = session->apmFrameCount;
1354377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            spx_uint32_t frOut = session->frameCount;
1355a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inChannelCount == 1) {
1356a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_int(session->outResampler,
1357a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    0,
1358de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh                                    session->procFrame->data_,
1359a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    &frIn,
1360a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    session->outBuf + session->framesOut * session->outChannelCount,
1361a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    &frOut);
1362a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            } else {
1363a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_interleaved_int(session->outResampler,
1364de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh                                    session->procFrame->data_,
1365a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    &frIn,
1366a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    session->outBuf + session->framesOut * session->outChannelCount,
1367a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    &frOut);
1368a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1369a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesOut += frOut;
1370a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } else {
1371a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->outBuf + session->framesOut * session->outChannelCount,
1372de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh                   session->procFrame->data_,
1373a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   session->frameCount * session->outChannelCount * sizeof(int16_t));
1374a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesOut += session->frameCount;
1375a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1376a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        size_t fr = session->framesOut;
1377a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (framesRq - framesWr < fr) {
1378a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            fr = framesRq - framesWr;
1379a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1380a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        memcpy(outBuffer->s16 + framesWr * session->outChannelCount,
1381a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent              session->outBuf,
1382a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent              fr * session->outChannelCount * sizeof(int16_t));
1383a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        memcpy(session->outBuf,
1384a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent              session->outBuf + fr * session->outChannelCount,
1385a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent              (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
1386a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->framesOut -= fr;
1387a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        outBuffer->frameCount += fr;
1388a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1389a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return 0;
1390a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
1391a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENODATA;
1392a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1393a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1394a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1395a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingFx_Command(effect_handle_t  self,
1396a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            uint32_t            cmdCode,
1397a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            uint32_t            cmdSize,
1398a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            void                *pCmdData,
1399a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            uint32_t            *replySize,
1400a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            void                *pReplyData)
1401a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1402a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t * effect = (preproc_effect_t *) self;
1403a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1404a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (effect == NULL){
1405a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1406a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1407a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
14083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
1409a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1410a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (cmdCode){
1411a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_INIT:
1412a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pReplyData == NULL || *replySize != sizeof(int)){
1413a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1414a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1415a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->init) {
1416a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                effect->ops->init(effect);
1417a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1418a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData = 0;
1419a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1420a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
14213f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        case EFFECT_CMD_SET_CONFIG: {
1422a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pCmdData    == NULL||
1423a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                cmdSize     != sizeof(effect_config_t)||
1424a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                pReplyData  == NULL||
1425a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                *replySize  != sizeof(int)){
14263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
14273d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                        "EFFECT_CMD_SET_CONFIG: ERROR");
1428a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1429a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
14303f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#ifdef DUAL_MIC_TEST
14313f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            // make sure that the config command is accepted by making as if all effects were
14323f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            // disabled: this is OK for functional tests
14333f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            uint32_t enabledMsk = effect->session->enabledMsk;
14343f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (gDualMicEnabled) {
14353f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                effect->session->enabledMsk = 0;
14363f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
14373f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#endif
1438a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData);
14393f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#ifdef DUAL_MIC_TEST
14403f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (gDualMicEnabled) {
14413f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                effect->session->enabledMsk = enabledMsk;
14423f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
14433f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#endif
1444a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (*(int *)pReplyData != 0) {
1445a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                break;
1446a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
144776533e94500e5d221ec4a1a5d9c97ea3d75860e4Eric Laurent            if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
144876533e94500e5d221ec4a1a5d9c97ea3d75860e4Eric Laurent                *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
144976533e94500e5d221ec4a1a5d9c97ea3d75860e4Eric Laurent            }
14503f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            } break;
1451a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
14523d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent        case EFFECT_CMD_GET_CONFIG:
14533d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            if (pReplyData == NULL ||
14543d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                *replySize != sizeof(effect_config_t)) {
14553d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
14563d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                        "EFFECT_CMD_GET_CONFIG: ERROR");
14573d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                return -EINVAL;
14583d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            }
14593d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
146094fef38613962c983c46ab0b97c58f5373412d2dEric Laurent            Session_GetConfig(effect->session, (effect_config_t *)pReplyData);
14613d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            break;
14623d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
14633d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent        case EFFECT_CMD_SET_CONFIG_REVERSE:
14643d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            if (pCmdData == NULL ||
14653d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                cmdSize != sizeof(effect_config_t) ||
14663d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                pReplyData == NULL ||
14673d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                *replySize != sizeof(int)) {
14683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
14693d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                        "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
1470a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1471a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1472a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData = Session_SetReverseConfig(effect->session,
1473a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                          (effect_config_t *)pCmdData);
1474a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (*(int *)pReplyData != 0) {
1475a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                break;
1476a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1477a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1478a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
14793d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent        case EFFECT_CMD_GET_CONFIG_REVERSE:
14803d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            if (pReplyData == NULL ||
14813d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                *replySize != sizeof(effect_config_t)){
14823d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                ALOGV("PreProcessingFx_Command cmdCode Case: "
14833d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                        "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
14843d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                return -EINVAL;
14853d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            }
14863d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData);
14873d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            break;
14883d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
1489a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_RESET:
1490a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->reset) {
1491a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                effect->ops->reset(effect);
1492a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1493a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1494a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
14950f714a464d2425afe00d6450535e763131b40844Eric Laurent        case EFFECT_CMD_GET_PARAM: {
14960f714a464d2425afe00d6450535e763131b40844Eric Laurent            effect_param_t *p = (effect_param_t *)pCmdData;
14970f714a464d2425afe00d6450535e763131b40844Eric Laurent
14980f714a464d2425afe00d6450535e763131b40844Eric Laurent            if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
14990f714a464d2425afe00d6450535e763131b40844Eric Laurent                    cmdSize < (sizeof(effect_param_t) + p->psize) ||
15000f714a464d2425afe00d6450535e763131b40844Eric Laurent                    pReplyData == NULL || replySize == NULL ||
15010f714a464d2425afe00d6450535e763131b40844Eric Laurent                    *replySize < (sizeof(effect_param_t) + p->psize)){
15023856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
1503a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                        "EFFECT_CMD_GET_PARAM: ERROR");
1504a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1505a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1506a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1507a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
1508a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1509a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            p = (effect_param_t *)pReplyData;
1510a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1511a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
1512a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1513a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->get_parameter) {
1514a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                p->status = effect->ops->get_parameter(effect, p->data,
1515b302bd5d288be2d3363b80053ca2392560b00b25Ashok Bhat                                                       &p->vsize,
1516a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                       p->data + voffset);
1517a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                *replySize = sizeof(effect_param_t) + voffset + p->vsize;
1518a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1519a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } break;
1520a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1521a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_PARAM:{
1522a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pCmdData == NULL||
15230f714a464d2425afe00d6450535e763131b40844Eric Laurent                    cmdSize < sizeof(effect_param_t) ||
15240f714a464d2425afe00d6450535e763131b40844Eric Laurent                    pReplyData == NULL || replySize == NULL ||
1525a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    *replySize != sizeof(int32_t)){
15263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
1527a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                        "EFFECT_CMD_SET_PARAM: ERROR");
1528a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1529a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1530a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            effect_param_t *p = (effect_param_t *) pCmdData;
1531a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1532a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (p->psize != sizeof(int32_t)){
15333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
1534a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                        "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
1535a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1536a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1537a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->set_parameter) {
1538a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                *(int *)pReplyData = effect->ops->set_parameter(effect,
1539a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                                (void *)p->data,
1540a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                                p->data + p->psize);
1541a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1542a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } break;
1543a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1544a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_ENABLE:
15450f714a464d2425afe00d6450535e763131b40844Eric Laurent            if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){
15463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
1547a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1548a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1549a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
1550a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1551a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1552a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_DISABLE:
15530f714a464d2425afe00d6450535e763131b40844Eric Laurent            if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){
15543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
1555a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1556a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1557a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData  = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
1558a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1559a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1560a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_DEVICE:
1561a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_INPUT_DEVICE:
1562a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pCmdData == NULL ||
1563a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                cmdSize != sizeof(uint32_t)) {
15643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
1565a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1566a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1567a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1568a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->set_device) {
1569a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                effect->ops->set_device(effect, *(uint32_t *)pCmdData);
1570a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1571a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1572a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1573a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_VOLUME:
1574a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_AUDIO_MODE:
1575a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1576a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
15773f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#ifdef DUAL_MIC_TEST
15783f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        ///// test commands start
15793f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        case PREPROC_CMD_DUAL_MIC_ENABLE: {
15803f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
15813f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    pReplyData == NULL || replySize == NULL) {
15823f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGE("PreProcessingFx_Command cmdCode Case: "
15833f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
15843f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *replySize = 0;
15853f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
15863f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
15873f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            gDualMicEnabled = *(bool *)pCmdData;
15883f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (gDualMicEnabled) {
15893f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                effect->aux_channels_on = sHasAuxChannels[effect->procId];
15903f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            } else {
15913f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                effect->aux_channels_on = false;
15923f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
15933f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            effect->cur_channel_config = (effect->session->inChannelCount == 1) ?
15943f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
15953f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
15963f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled");
15973f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *replySize = sizeof(int);
15983f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *(int *)pReplyData = 0;
15993f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            } break;
16003f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: {
16013f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (pCmdData == NULL|| pReplyData == NULL || replySize == NULL) {
16023f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGE("PreProcessingFx_Command cmdCode Case: "
16033f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
16043f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *replySize = 0;
16053f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
16063f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16073f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            pthread_mutex_lock(&gPcmDumpLock);
16083f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (gPcmDumpFh != NULL) {
16093f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                fclose(gPcmDumpFh);
16103f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                gPcmDumpFh = NULL;
16113f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16123f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            char *path = strndup((char *)pCmdData, cmdSize);
16133f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            gPcmDumpFh = fopen((char *)path, "wb");
16143f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            pthread_mutex_unlock(&gPcmDumpLock);
16153f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p",
16163f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                  path, gPcmDumpFh);
16173f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno));
16183f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            free(path);
16193f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *replySize = sizeof(int);
16203f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *(int *)pReplyData = 0;
16213f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            } break;
16223f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: {
16233f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (pReplyData == NULL || replySize == NULL) {
16243f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGE("PreProcessingFx_Command cmdCode Case: "
16253f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
16263f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *replySize = 0;
16273f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
16283f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16293f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            pthread_mutex_lock(&gPcmDumpLock);
16303f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (gPcmDumpFh != NULL) {
16313f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                fclose(gPcmDumpFh);
16323f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                gPcmDumpFh = NULL;
16333f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16343f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            pthread_mutex_unlock(&gPcmDumpLock);
16353f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP");
16363f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *replySize = sizeof(int);
16373f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *(int *)pReplyData = 0;
16383f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            } break;
16393f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        ///// test commands end
16403f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
16413f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: {
16423f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if(!gDualMicEnabled) {
16433f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
16443f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16453f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (pCmdData == NULL|| cmdSize != 2 * sizeof(uint32_t) ||
16463f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    pReplyData == NULL || replySize == NULL) {
16473f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGE("PreProcessingFx_Command cmdCode Case: "
16483f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
16493f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *replySize = 0;
16503f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
16513f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16523f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS ||
16533f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                  !effect->aux_channels_on) {
16543f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by"
16553f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        " fx %d", effect->procId);
16563f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *(uint32_t *)pReplyData = -ENOSYS;
16573f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *replySize = sizeof(uint32_t);
16583f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                break;
16593f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16603f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            size_t num_configs = *((uint32_t *)pCmdData + 1);
16613f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (*replySize < (2 * sizeof(uint32_t) +
16623f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                              num_configs * sizeof(channel_config_t))) {
16633f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *replySize = 0;
16643f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
16653f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16663f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
16673f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *((uint32_t *)pReplyData + 1) = CHANNEL_CFG_CNT;
16683f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (num_configs < CHANNEL_CFG_CNT ||
16693f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    *replySize < (2 * sizeof(uint32_t) +
16703f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                                     CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
16713f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *(uint32_t *)pReplyData = -ENOMEM;
16723f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            } else {
16733f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                num_configs = CHANNEL_CFG_CNT;
16743f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *(uint32_t *)pReplyData = 0;
16753f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16763f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d",
16773f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                  num_configs);
16783f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent
16793f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t);
16803f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *((uint32_t *)pReplyData + 1) = num_configs;
16813f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            memcpy((uint32_t *)pReplyData + 2, &sDualMicConfigs, num_configs * sizeof(channel_config_t));
16823f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            } break;
16833f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        case EFFECT_CMD_GET_FEATURE_CONFIG:
16843f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if(!gDualMicEnabled) {
16853f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
16863f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16873f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
16883f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    pReplyData == NULL || replySize == NULL ||
16893f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
16903f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGE("PreProcessingFx_Command cmdCode Case: "
16913f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
16923f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
16933f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16943f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
16953f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *(uint32_t *)pReplyData = -ENOSYS;
16963f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *replySize = sizeof(uint32_t);
16973f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                break;
16983f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
16993f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG");
17003f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *(uint32_t *)pReplyData = 0;
17013f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *replySize = sizeof(uint32_t) + sizeof(channel_config_t);
17023f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            memcpy((uint32_t *)pReplyData + 1,
17033f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                   &sDualMicConfigs[effect->cur_channel_config],
17043f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                   sizeof(channel_config_t));
17053f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            break;
17063f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent        case EFFECT_CMD_SET_FEATURE_CONFIG: {
17073f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: "
17083f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    "gDualMicEnabled %d effect->aux_channels_on %d",
17093f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                  gDualMicEnabled, effect->aux_channels_on);
17103f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if(!gDualMicEnabled) {
17113f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
17123f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
17133f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (pCmdData == NULL|| cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
17143f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    pReplyData == NULL || replySize == NULL ||
17153f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    *replySize < sizeof(uint32_t)) {
17163f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGE("PreProcessingFx_Command cmdCode Case: "
17173f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
17183f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
17193f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
17203f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                return -EINVAL;
17213f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
17223f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            *replySize = sizeof(uint32_t);
17233f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
17243f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *(uint32_t *)pReplyData = -ENOSYS;
17253f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGV("PreProcessingFx_Command cmdCode Case: "
17263f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                                        "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
17273f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                                        "CmdData %d effect->aux_channels_on %d",
17283f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                                        *(uint32_t *)pCmdData, effect->aux_channels_on);
17293f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                break;
17303f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
17313f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            size_t i;
17323f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            for (i = 0; i < CHANNEL_CFG_CNT;i++) {
17333f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                if (memcmp((uint32_t *)pCmdData + 1,
17343f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                           &sDualMicConfigs[i], sizeof(channel_config_t)) == 0) {
17353f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                    break;
17363f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                }
17373f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
17383f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            if (i == CHANNEL_CFG_CNT) {
17393f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *(uint32_t *)pReplyData = -EINVAL;
17403f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config"
17413f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        "[%08x].[%08x]", *((uint32_t *)pCmdData + 1), *((uint32_t *)pCmdData + 2));
17423f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            } else {
17433f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                effect->cur_channel_config = i;
17443f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                *(uint32_t *)pReplyData = 0;
17453f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config"
17463f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent                        "[%08x].[%08x]", sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
17473f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            }
17483f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent            } break;
17493f9c84c0a5af83fceb8669390e2d71b75ec7b550Eric Laurent#endif
1750a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
1751a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
1752a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1753a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
1754a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1755a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1756a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1757a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingFx_GetDescriptor(effect_handle_t   self,
1758a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                  effect_descriptor_t *pDescriptor)
1759a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1760a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t * effect = (preproc_effect_t *) self;
1761a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1762a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (effect == NULL || pDescriptor == NULL) {
1763a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1764a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1765a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1766a189a6883ee55cf62da1d7bf5bf5a8ab501938a4Glenn Kasten    *pDescriptor = *sDescriptors[effect->procId];
1767a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1768a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
1769a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1770a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1771a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingFx_ProcessReverse(effect_handle_t     self,
1772a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                   audio_buffer_t    *inBuffer,
17730f714a464d2425afe00d6450535e763131b40844Eric Laurent                                   audio_buffer_t    *outBuffer __unused)
1774a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1775a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t * effect = (preproc_effect_t *)self;
1776a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1777a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (effect == NULL){
17785ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
1779a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1780a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1781a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_session_t * session = (preproc_session_t *)effect->session;
1782a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1783a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (inBuffer == NULL  || inBuffer->raw == NULL){
17845ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
1785a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1786a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1787a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1788a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revProcessedMsk |= (1<<effect->procId);
1789a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
17903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block//    ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x",
1791a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//         inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
1792a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1793a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1794a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
1795a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->session->revProcessedMsk = 0;
1796a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->revResampler != NULL) {
1797a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->frameCount - session->framesRev;
1798a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (inBuffer->frameCount < fr) {
1799a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = inBuffer->frameCount;
1800a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1801a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->revBufSize < session->framesRev + fr) {
1802679650f008a6dee59d89238fab17edd208a1878eEric Laurent                int16_t *buf;
1803a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->revBufSize = session->framesRev + fr;
1804679650f008a6dee59d89238fab17edd208a1878eEric Laurent                buf = (int16_t *)realloc(session->revBuf,
1805679650f008a6dee59d89238fab17edd208a1878eEric Laurent                                 session->revBufSize * session->inChannelCount * sizeof(int16_t));
1806679650f008a6dee59d89238fab17edd208a1878eEric Laurent                if (buf == NULL) {
1807679650f008a6dee59d89238fab17edd208a1878eEric Laurent                    session->framesRev = 0;
1808679650f008a6dee59d89238fab17edd208a1878eEric Laurent                    free(session->revBuf);
1809679650f008a6dee59d89238fab17edd208a1878eEric Laurent                    session->revBuf = NULL;
1810679650f008a6dee59d89238fab17edd208a1878eEric Laurent                    return -ENOMEM;
1811679650f008a6dee59d89238fab17edd208a1878eEric Laurent                }
1812679650f008a6dee59d89238fab17edd208a1878eEric Laurent                session->revBuf = buf;
1813a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1814a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->revBuf + session->framesRev * session->inChannelCount,
1815a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   inBuffer->s16,
1816a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   fr * session->inChannelCount * sizeof(int16_t));
1817a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1818a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev += fr;
1819a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = fr;
1820a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->framesRev < session->frameCount) {
1821a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return 0;
1822a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1823377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            spx_uint32_t frIn = session->framesRev;
1824377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT            spx_uint32_t frOut = session->apmFrameCount;
1825a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inChannelCount == 1) {
1826a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_int(session->revResampler,
1827a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            0,
1828a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            session->revBuf,
1829a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            &frIn,
1830de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh                                            session->revFrame->data_,
1831a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            &frOut);
1832a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            } else {
1833a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_interleaved_int(session->revResampler,
1834a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        session->revBuf,
1835a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        &frIn,
1836de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh                                                        session->revFrame->data_,
1837a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        &frOut);
1838a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1839a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->revBuf,
1840a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   session->revBuf + frIn * session->inChannelCount,
1841a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
1842a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev -= frIn;
1843a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } else {
1844a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->frameCount - session->framesRev;
1845a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (inBuffer->frameCount < fr) {
1846a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = inBuffer->frameCount;
1847a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1848de7fa31668bd90dba80ff2c0c462492fed873c3dChih-Hung Hsieh            memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount,
1849a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   inBuffer->s16,
1850a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   fr * session->inChannelCount * sizeof(int16_t));
1851a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev += fr;
1852a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = fr;
1853a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->framesRev < session->frameCount) {
1854a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return 0;
1855a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1856a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev = 0;
1857a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1858766bf734984a0d5765980f8bd154d111de08ec19Alex Luebs        session->revFrame->samples_per_channel_ = session->apmFrameCount;
1859a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->session->apm->AnalyzeReverseStream(session->revFrame);
1860a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return 0;
1861a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
1862a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENODATA;
1863a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1864a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1865a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1866a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1867a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// effect_handle_t interface implementation for effect
1868a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentconst struct effect_interface_s sEffectInterface = {
1869a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_Process,
1870a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_Command,
1871a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_GetDescriptor,
1872a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    NULL
1873a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
1874a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1875a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentconst struct effect_interface_s sEffectInterfaceReverse = {
1876a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_Process,
1877a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_Command,
1878a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_GetDescriptor,
1879a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_ProcessReverse
1880a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
1881a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1882a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1883a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect Library Interface Implementation
1884a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1885a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
18865e92a7861196ddae14638d4b7a63fc4892b7ef59Glenn Kastenint PreProcessingLib_Create(const effect_uuid_t *uuid,
1887a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            int32_t             sessionId,
1888a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            int32_t             ioId,
1889a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            effect_handle_t  *pInterface)
1890a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
18913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
1892a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1893a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status;
1894a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    const effect_descriptor_t *desc;
1895a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_session_t *session;
1896a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t procId;
1897a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1898a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (PreProc_Init() != 0) {
1899a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return sInitStatus;
1900a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1901a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    desc =  PreProc_GetDescriptor(uuid);
1902a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (desc == NULL) {
19035ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
1904a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1905a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1906a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    procId = UuidToProcId(&desc->type);
1907a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1908a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session = PreProc_GetSession(procId, sessionId, ioId);
1909a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session == NULL) {
19105ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("EffectCreate: no more session available");
1911a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1912a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1913a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1914a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    status = Session_CreateEffect(session, procId, pInterface);
1915a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1916a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0 && session->createdMsk == 0) {
1917a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->io = 0;
1918a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1919a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
1920a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1921a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1922a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingLib_Release(effect_handle_t interface)
1923a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
19243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("EffectRelease start %p", interface);
1925a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (PreProc_Init() != 0) {
1926a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return sInitStatus;
1927a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1928a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1929a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t *fx = (preproc_effect_t *)interface;
1930a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1931a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (fx->session->io == 0) {
1932a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1933a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1934a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return Session_ReleaseEffect(fx->session, fx);
1935a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1936a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
19375e92a7861196ddae14638d4b7a63fc4892b7ef59Glenn Kastenint PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid,
1938a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                   effect_descriptor_t *pDescriptor) {
1939a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1940a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (pDescriptor == NULL || uuid == NULL){
1941a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1942a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1943a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1944a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid);
1945a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (desc == NULL) {
19463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("PreProcessingLib_GetDescriptor() not found");
1947a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return  -EINVAL;
1948a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1949a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
19503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
1951a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1952a189a6883ee55cf62da1d7bf5bf5a8ab501938a4Glenn Kasten    *pDescriptor = *desc;
1953a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
1954a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1955a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
19567f16b197c76fbae9399242f055a7ee16dcd0fd6dMarco Nelissen// This is the only symbol that needs to be exported
19577f16b197c76fbae9399242f055a7ee16dcd0fd6dMarco Nelissen__attribute__ ((visibility ("default")))
1958a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
1959c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev    .tag = AUDIO_EFFECT_LIBRARY_TAG,
1960c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev    .version = EFFECT_LIBRARY_API_VERSION,
1961c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev    .name = "Audio Preprocessing Library",
1962c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev    .implementor = "The Android Open Source Project",
1963c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev    .create_effect = PreProcessingLib_Create,
1964c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev    .release_effect = PreProcessingLib_Release,
1965c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev    .get_descriptor = PreProcessingLib_GetDescriptor
1966a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
1967a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1968a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}; // extern "C"
1969