PreProcessing.cpp revision 29357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47
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>
27a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include "modules/interface/module_common_types.h"
28a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include "modules/audio_processing/main/interface/audio_processing.h"
29a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#include "speex/speex_resampler.h"
30a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
31a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
32a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
33a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// local definitions
34a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
35a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
36a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// maximum number of sessions
37a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#define PREPROC_NUM_SESSIONS 8
38a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
39a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// types of pre processing modules
40a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentenum preproc_id
41a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
42a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_AGC,        // Automatic Gain Control
43a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_AEC,        // Acoustic Echo Canceler
44a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_NS,         // Noise Suppressor
45a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_NUM_EFFECTS
46a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
47a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
48a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Session state
49a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentenum preproc_session_state {
50a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_SESSION_STATE_INIT,        // initialized
51a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_SESSION_STATE_CONFIG       // configuration received
52a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
53a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
54a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect/Preprocessor state
55a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentenum preproc_effect_state {
56a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_EFFECT_STATE_INIT,         // initialized
57a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_EFFECT_STATE_CREATED,      // webRTC engine created
58a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_EFFECT_STATE_CONFIG,       // configuration received/disabled
59a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PREPROC_EFFECT_STATE_ACTIVE        // active/enabled
60a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
61a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
62a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// handle on webRTC engine
63a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenttypedef void* preproc_fx_handle_t;
64a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
65a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenttypedef struct preproc_session_s preproc_session_t;
66a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenttypedef struct preproc_effect_s preproc_effect_t;
67a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenttypedef struct preproc_ops_s preproc_ops_t;
68a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
69a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
70a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Function pointer can be null if no action required.
71a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstruct preproc_ops_s {
72a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* create)(preproc_effect_t *fx);
73a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* init)(preproc_effect_t *fx);
74a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* reset)(preproc_effect_t *fx);
75a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    void (* enable)(preproc_effect_t *fx);
76a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    void (* disable)(preproc_effect_t *fx);
77a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* set_parameter)(preproc_effect_t *fx, void *param, void *value);
78a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* get_parameter)(preproc_effect_t *fx, void *param, size_t *size, void *value);
79a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int (* set_device)(preproc_effect_t *fx, uint32_t device);
80a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
81a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
82a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect context
83a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstruct preproc_effect_s {
84a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    const struct effect_interface_s *itfe;
85a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t procId;                // type of pre processor (enum preproc_id)
86a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t state;                 // current state (enum preproc_effect_state)
87a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_session_t *session;     // session the effect is on
88a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    const preproc_ops_t *ops;       // effect ops table
89a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_fx_handle_t engine;     // handle on webRTC engine
90a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
91a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
92a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Session context
93a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstruct preproc_session_s {
94a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session
95a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t state;                     // current state (enum preproc_session_state)
96a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int id;                             // audio session ID
97a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int io;                             // handle of input stream this session is on
98a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::AudioProcessing* apm;       // handle on webRTC audio processing module (APM)
99a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t apmFrameCount;               // buffer size for webRTC process (10 ms)
100a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t apmSamplingRate;           // webRTC APM sampling rate (8/16 or 32 kHz)
101a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t frameCount;                  // buffer size before input resampler ( <=> apmFrameCount)
102a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t samplingRate;              // sampling rate at effect process interface
103a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t inChannelCount;            // input channel count
104a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t outChannelCount;           // output channel count
105a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t createdMsk;                // bit field containing IDs of crested pre processors
106a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t enabledMsk;                // bit field containing IDs of enabled pre processors
107a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t processedMsk;              // bit field containing IDs of pre processors already
108a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                        // processed in current round
109a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::AudioFrame *procFrame;      // audio frame passed to webRTC AMP ProcessStream()
110a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int16_t *inBuf;                     // input buffer used when resampling
111a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t inBufSize;                   // input buffer size in frames
112a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t framesIn;                    // number of frames in input buffer
113a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    SpeexResamplerState *inResampler;   // handle on input speex resampler
114a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int16_t *outBuf;                    // output buffer used when resampling
115a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t outBufSize;                  // output buffer size in frames
116a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t framesOut;                   // number of frames in output buffer
117a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    SpeexResamplerState *outResampler;  // handle on output speex resampler
118a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t revChannelCount;           // number of channels on reverse stream
119a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t revEnabledMsk;             // bit field containing IDs of enabled pre processors
120a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                        // with reverse channel
121a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t revProcessedMsk;           // bit field containing IDs of pre processors with reverse
122a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                        // channel already processed in current round
123a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::AudioFrame *revFrame;       // audio frame passed to webRTC AMP AnalyzeReverseStream()
124a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int16_t *revBuf;                    // reverse channel input buffer
125a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t revBufSize;                  // reverse channel input buffer size
126a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t framesRev;                   // number of frames in reverse channel input buffer
127a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    SpeexResamplerState *revResampler;  // handle on reverse channel input speex resampler
128a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
129a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
130a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
131a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect descriptors
132a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
133a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
134a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
135a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// as the pre processing effects are not defined by OpenSL ES
136a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
137a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Automatic Gain Control
138a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const effect_descriptor_t sAgcDescriptor = {
139a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
140a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
141a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        EFFECT_CONTROL_API_VERSION,
142a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
143a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate CPU load
144a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate memory usage
145a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "Automatic Gain Control",
146a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "The Android Open Source Project"
147a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
148a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
149a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Acoustic Echo Cancellation
150a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const effect_descriptor_t sAecDescriptor = {
151a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
152a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
153a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        EFFECT_CONTROL_API_VERSION,
154a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
155a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate CPU load
156a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate memory usage
157a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "Acoustic Echo Canceler",
158a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "The Android Open Source Project"
159a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
160a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
161a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Noise suppression
162a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const effect_descriptor_t sNsDescriptor = {
163a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
164a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        { 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
165a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        EFFECT_CONTROL_API_VERSION,
166a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
167a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate CPU load
168a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        0, //FIXME indicate memory usage
169a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "Noise Suppression",
170a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        "The Android Open Source Project"
171a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
172a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
173a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
174a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = {
175a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sAgcDescriptor,
176a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sAecDescriptor,
177a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sNsDescriptor
178a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
179a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
180a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
181a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Helper functions
182a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
183a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
184a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentconst effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {
185a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        FX_IID_AGC,
186a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        FX_IID_AEC,
187a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        FX_IID_NS
188a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
189a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
190a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
191a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentconst effect_uuid_t * ProcIdToUuid(int procId)
192a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
193a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (procId >= PREPROC_NUM_EFFECTS) {
194a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return EFFECT_UUID_NULL;
195a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
196a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return sUuidToPreProcTable[procId];
197a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
198a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
199a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentuint32_t UuidToProcId(const effect_uuid_t * uuid)
200a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
201a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
202a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
203a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
204a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
205a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
206a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
207a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return i;
208a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
209a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
210a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentbool HasReverseStream(uint32_t procId)
211a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
212a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (procId == PREPROC_AEC) {
213a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return true;
214a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
215a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return false;
216a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
217a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
218a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
219a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
220a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Automatic Gain Control (AGC)
221a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
222a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
223a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const int kAgcDefaultTargetLevel = 0;
224a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const int kAgcDefaultCompGain = 90;
225a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const bool kAgcDefaultLimiter = true;
226a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
227a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  AgcInit (preproc_effect_t *effect)
228a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
2293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcInit");
230a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
231a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->set_mode(webrtc::GainControl::kFixedDigital);
232a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
233a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->set_compression_gain_db(kAgcDefaultCompGain);
234a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->enable_limiter(kAgcDefaultLimiter);
235a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
236a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
237a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
238a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  AgcCreate(preproc_effect_t *effect)
239a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
240a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = effect->session->apm->gain_control();
2413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcCreate got agc %p", agc);
242a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (agc == NULL) {
2435ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcCreate Error");
244a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENOMEM;
245a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
246a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->engine = static_cast<preproc_fx_handle_t>(agc);
247a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    AgcInit(effect);
248a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
249a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
250a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
251a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint AgcGetParameter(preproc_effect_t *effect,
252a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    void *pParam,
253a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    size_t *pValueSize,
254a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    void *pValue)
255a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
256a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
257a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t param = *(uint32_t *)pParam;
258a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    t_agc_settings *pProperties = (t_agc_settings *)pValue;
259a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
260a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
261a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
262a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_TARGET_LEVEL:
263a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_COMP_GAIN:
264a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (*pValueSize < sizeof(int16_t)) {
265a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *pValueSize = 0;
266a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
267a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
268a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
269a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_LIMITER_ENA:
270a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (*pValueSize < sizeof(bool)) {
271a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *pValueSize = 0;
272a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
273a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
274a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
275a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_PROPERTIES:
276a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (*pValueSize < sizeof(t_agc_settings)) {
277a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *pValueSize = 0;
278a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
279a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
280a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
281a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
282a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
2835ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcGetParameter() unknown param %08x", param);
284a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
285a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
286a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
287a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
288a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
289a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_TARGET_LEVEL:
290a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        *(int16_t *) pValue = (int16_t)(agc->target_level_dbfs() * -100);
2913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue);
292a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
293a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_COMP_GAIN:
294a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        *(int16_t *) pValue = (int16_t)(agc->compression_gain_db() * 100);
2953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue);
296a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
297a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_LIMITER_ENA:
298a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        *(bool *) pValue = (bool)agc->is_limiter_enabled();
2993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcGetParameter() limiter enabled %s",
300a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent             (*(int16_t *) pValue != 0) ? "true" : "false");
301a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
302a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_PROPERTIES:
303a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
304a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
305a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
306a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
307a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
3085ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcGetParameter() unknown param %d", param);
309a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
310a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
311a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
312a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
313a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
314a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
315a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint AgcSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
316a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
317a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
318a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t param = *(uint32_t *)pParam;
319a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    t_agc_settings *pProperties = (t_agc_settings *)pValue;
320a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
321a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
322a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
323a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_TARGET_LEVEL:
3243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue);
325a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->set_target_level_dbfs(-(*(int16_t *)pValue / 100));
326a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
327a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_COMP_GAIN:
3283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue);
329a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->set_compression_gain_db(*(int16_t *)pValue / 100);
330a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
331a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_LIMITER_ENA:
3323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false");
333a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->enable_limiter(*(bool *)pValue);
334a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
335a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AGC_PARAM_PROPERTIES:
3363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
337a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent             pProperties->targetLevel,
338a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent             pProperties->compGain,
339a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent             pProperties->limiterEnabled);
340a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
341a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (status != 0) break;
342a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->set_compression_gain_db(pProperties->compGain / 100);
343a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (status != 0) break;
344a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = agc->enable_limiter(pProperties->limiterEnabled);
345a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
346a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
3475ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
348a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
349a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
350a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
351a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
3523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcSetParameter() done status %d", status);
353a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
354a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
355a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
356a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
357a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid AgcEnable(preproc_effect_t *effect)
358a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
359a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
3603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcEnable agc %p", agc);
361a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->Enable(true);
362a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
363a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
364a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid AgcDisable(preproc_effect_t *effect)
365a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
3663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AgcDisable");
367a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
368a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    agc->Enable(false);
369a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
370a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
371a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
372a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const preproc_ops_t sAgcOps = {
373a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcCreate,
374a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcInit,
375a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL,
376a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcEnable,
377a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcDisable,
378a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcSetParameter,
379a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AgcGetParameter,
380a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL
381a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
382a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
383a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
384a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
385a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Acoustic Echo Canceler (AEC)
386a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
387a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
388a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
389a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        webrtc::EchoControlMobile::kEarpiece;
390a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const bool kAecDefaultComfortNoise = true;
391a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
392a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  AecInit (preproc_effect_t *effect)
393a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
3943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecInit");
395a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
396a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->set_routing_mode(kAecDefaultMode);
397a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->enable_comfort_noise(kAecDefaultComfortNoise);
398a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
399a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
400a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
401a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  AecCreate(preproc_effect_t *effect)
402a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
403a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = effect->session->apm->echo_control_mobile();
4043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecCreate got aec %p", aec);
405a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (aec == NULL) {
4065ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcCreate Error");
407a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENOMEM;
408a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
409a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->engine = static_cast<preproc_fx_handle_t>(aec);
410a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    AecInit (effect);
411a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
412a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
413a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
414a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint AecGetParameter(preproc_effect_t     *effect,
415a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    void              *pParam,
416a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    size_t            *pValueSize,
417a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    void              *pValue)
418a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
419a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
420a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t param = *(uint32_t *)pParam;
421a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
422a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (*pValueSize < sizeof(uint32_t)) {
423a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
424a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
425a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
426a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AEC_PARAM_ECHO_DELAY:
427a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AEC_PARAM_PROPERTIES:
428a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        *(uint32_t *)pValue = 1000 * effect->session->apm->stream_delay_ms();
4293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AecGetParameter() echo delay %d us", *(uint32_t *)pValue);
430a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
431a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
4325ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
433a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
434a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
435a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
436a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
437a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
438a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
439a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint AecSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
440a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
441a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
442a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t param = *(uint32_t *)pParam;
443a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t value = *(uint32_t *)pValue;
444a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
445a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (param) {
446a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AEC_PARAM_ECHO_DELAY:
447a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AEC_PARAM_PROPERTIES:
448a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = effect->session->apm->set_stream_delay_ms(value/1000);
4493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
450a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
451a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
4525ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
453a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = -EINVAL;
454a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
455a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
456a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
457a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
458a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
459a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid AecEnable(preproc_effect_t *effect)
460a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
461a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
4623856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecEnable aec %p", aec);
463a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->Enable(true);
464a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
465a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
466a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid AecDisable(preproc_effect_t *effect)
467a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
4683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecDisable");
469a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
470a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->Enable(false);
471a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
472a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
473a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint AecSetDevice(preproc_effect_t *effect, uint32_t device)
474a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
4753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AecSetDevice %08x", device);
476a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
477a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
478a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
479a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch(device) {
480a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AUDIO_DEVICE_OUT_EARPIECE:
481a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        mode = webrtc::EchoControlMobile::kEarpiece;
482a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
483a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AUDIO_DEVICE_OUT_SPEAKER:
484a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        mode = webrtc::EchoControlMobile::kSpeakerphone;
485a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
486a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AUDIO_DEVICE_OUT_WIRED_HEADSET:
487a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
488a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
489a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
490a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
491a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    aec->set_routing_mode(mode);
492a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
493a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
494a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
495a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const preproc_ops_t sAecOps = {
496a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecCreate,
497a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecInit,
498a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL,
499a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecEnable,
500a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecDisable,
501a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecSetParameter,
502a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecGetParameter,
503a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        AecSetDevice
504a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
505a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
506a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
507a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Noise Suppression (NS)
508a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
509a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
510a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
511a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
512a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  NsInit (preproc_effect_t *effect)
513a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
5143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("NsInit");
515a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
516a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    ns->set_level(kNsDefaultLevel);
517a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
518a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
519a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
520a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint  NsCreate(preproc_effect_t *effect)
521a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
522a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression();
5233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("NsCreate got ns %p", ns);
524a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (ns == NULL) {
5255ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("AgcCreate Error");
526a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENOMEM;
527a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
528a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->engine = static_cast<preproc_fx_handle_t>(ns);
529a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    NsInit (effect);
530a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
531a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
532a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
533a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint NsGetParameter(preproc_effect_t     *effect,
534a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   void              *pParam,
535a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   size_t            *pValueSize,
536a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   void              *pValue)
537a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
538a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
539a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
540a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
541a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
542a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
543a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
544a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
545a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
546a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
547a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
548a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid NsEnable(preproc_effect_t *effect)
549a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
550a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
5513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("NsEnable ns %p", ns);
552a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    ns->Enable(true);
553a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
554a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
555a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid NsDisable(preproc_effect_t *effect)
556a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
5573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("NsDisable");
558a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
559a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    ns->Enable(false);
560a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
561a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
562a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const preproc_ops_t sNsOps = {
563a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsCreate,
564a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsInit,
565a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL,
566a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsEnable,
567a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsDisable,
568a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsSetParameter,
569a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NsGetParameter,
570a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        NULL
571a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
572a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
573a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
574a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = {
575a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sAgcOps,
576a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sAecOps,
577a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        &sNsOps
578a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
579a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
580a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
581a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
582a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect functions
583a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
584a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
585a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled);
586a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
587a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentextern "C" const struct effect_interface_s sEffectInterface;
588a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentextern "C" const struct effect_interface_s sEffectInterfaceReverse;
589a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
590a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#define BAD_STATE_ABORT(from, to) \
591a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
592a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
593a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Effect_SetState(preproc_effect_t *effect, uint32_t state)
594a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
595a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
5963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
597a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch(state) {
598a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case PREPROC_EFFECT_STATE_INIT:
599a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        switch(effect->state) {
600a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_ACTIVE:
601a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            effect->ops->disable(effect);
602a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            Session_SetProcEnabled(effect->session, effect->procId, false);
603a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CONFIG:
604a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CREATED:
605a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_INIT:
606a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
607a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
608a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            BAD_STATE_ABORT(effect->state, state);
609a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
610a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
611a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case PREPROC_EFFECT_STATE_CREATED:
612a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        switch(effect->state) {
613a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_INIT:
614a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            status = effect->ops->create(effect);
615a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
616a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CREATED:
617a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_ACTIVE:
618a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CONFIG:
61929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Effect_SetState invalid transition");
620a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            status = -ENOSYS;
621a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
622a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
623a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            BAD_STATE_ABORT(effect->state, state);
624a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
625a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
626a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case PREPROC_EFFECT_STATE_CONFIG:
627a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        switch(effect->state) {
628a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_INIT:
62929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Effect_SetState invalid transition");
630a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            status = -ENOSYS;
631a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
632a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_ACTIVE:
633a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            effect->ops->disable(effect);
634a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            Session_SetProcEnabled(effect->session, effect->procId, false);
635a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
636a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CREATED:
637a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CONFIG:
638a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
639a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
640a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            BAD_STATE_ABORT(effect->state, state);
641a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
642a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
643a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    case PREPROC_EFFECT_STATE_ACTIVE:
644a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        switch(effect->state) {
645a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_INIT:
646a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CREATED:
647a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_ACTIVE:
64829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Effect_SetState invalid transition");
649a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            status = -ENOSYS;
650a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
651a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case PREPROC_EFFECT_STATE_CONFIG:
652a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            effect->ops->enable(effect);
653a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            Session_SetProcEnabled(effect->session, effect->procId, true);
654a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
655a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
656a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            BAD_STATE_ABORT(effect->state, state);
657a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
658a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        break;
659a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    default:
660a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        BAD_STATE_ABORT(effect->state, state);
661a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
662a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status == 0) {
663a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->state = state;
664a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
665a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
666a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
667a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
668a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Effect_Init(preproc_effect_t *effect, uint32_t procId)
669a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
670a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (HasReverseStream(procId)) {
671a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->itfe = &sEffectInterfaceReverse;
672a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
673a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->itfe = &sEffectInterface;
674a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
675a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->ops = sPreProcOps[procId];
676a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->procId = procId;
677a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->state = PREPROC_EFFECT_STATE_INIT;
678a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
679a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
680a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
681a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Effect_Create(preproc_effect_t *effect,
682a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent               preproc_session_t *session,
683a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent               effect_handle_t  *interface)
684a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
685a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    effect->session = session;
686a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    *interface = (effect_handle_t)&effect->itfe;
687a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
688a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
689a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
690a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Effect_Release(preproc_effect_t *effect)
691a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
692a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
693a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
694a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
695a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
696a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
697a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Session functions
698a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
699a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
700a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
701a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
702a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const int kPreprocDefaultSr = 16000;
703a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic const int kPreProcDefaultCnl = 1;
704a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
705a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Session_Init(preproc_session_t *session)
706a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
707a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
708a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
709a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
710a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->state = PREPROC_SESSION_STATE_INIT;
711a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->id = 0;
712a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->io = 0;
713a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->createdMsk = 0;
714a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->apm = NULL;
715a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
716a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = Effect_Init(&session->effects[i], i);
717a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
718a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
719a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
720a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
721a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
722a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentextern "C" int Session_CreateEffect(preproc_session_t *session,
723a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    int32_t procId,
724a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    effect_handle_t  *interface)
725a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
726a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = -ENOMEM;
727a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
7283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
729a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
730a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->createdMsk == 0) {
731a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apm = webrtc::AudioProcessing::Create(session->io);
732a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->apm == NULL) {
7335ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_CreateEffect could not get apm engine");
734a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            goto error;
735a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
736a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apm->set_sample_rate_hz(kPreprocDefaultSr);
737a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apm->set_num_channels(kPreProcDefaultCnl, kPreProcDefaultCnl);
738a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apm->set_num_reverse_channels(kPreProcDefaultCnl);
739a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->procFrame = new webrtc::AudioFrame();
740a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->procFrame == NULL) {
7415ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_CreateEffect could not allocate audio frame");
742a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            goto error;
743a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
744a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revFrame = new webrtc::AudioFrame();
745a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->revFrame == NULL) {
7465ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_CreateEffect could not allocate reverse audio frame");
747a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            goto error;
748a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
749a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmSamplingRate = kPreprocDefaultSr;
750a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmFrameCount = (kPreprocDefaultSr) / 100;
751a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->frameCount = session->apmFrameCount;
752a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->samplingRate = kPreprocDefaultSr;
753a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inChannelCount = kPreProcDefaultCnl;
754a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outChannelCount = kPreProcDefaultCnl;
755a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->procFrame->_frequencyInHz = kPreprocDefaultSr;
756a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->procFrame->_audioChannel = kPreProcDefaultCnl;
757a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revChannelCount = kPreProcDefaultCnl;
758a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revFrame->_frequencyInHz = kPreprocDefaultSr;
759a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revFrame->_audioChannel = kPreProcDefaultCnl;
760a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->enabledMsk = 0;
761a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->processedMsk = 0;
762a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revEnabledMsk = 0;
763a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revProcessedMsk = 0;
764a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inResampler = NULL;
765a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inBuf = NULL;
766a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inBufSize = 0;
767a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outResampler = NULL;
768a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outBuf = NULL;
769a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outBufSize = 0;
770a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revResampler = NULL;
771a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revBuf = NULL;
772a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revBufSize = 0;
773a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
774a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    status = Effect_Create(&session->effects[procId], session, interface);
775a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0) {
776a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        goto error;
777a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
7783856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_CreateEffect OK");
779a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->createdMsk |= (1<<procId);
780a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
781a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
782a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurenterror:
783a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->createdMsk == 0) {
784a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->revFrame;
785a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revFrame = NULL;
786a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->procFrame;
787a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->procFrame = NULL;
788a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        webrtc::AudioProcessing::Destroy(session->apm);
789a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apm = NULL;
790a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
791a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
792a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
793a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
794a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Session_ReleaseEffect(preproc_session_t *session,
795a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                          preproc_effect_t *fx)
796a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
7975ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block    ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
798a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->createdMsk &= ~(1<<fx->procId);
799a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->createdMsk == 0) {
800a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        webrtc::AudioProcessing::Destroy(session->apm);
801a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apm = NULL;
802a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->procFrame;
803a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->procFrame = NULL;
804a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->revFrame;
805a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revFrame = NULL;
806a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->inResampler != NULL) {
807a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->inResampler);
808a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->inResampler = NULL;
809a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
810a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->outResampler != NULL) {
811a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->outResampler);
812a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->outResampler = NULL;
813a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
814a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->revResampler != NULL) {
815a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->revResampler);
816a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->revResampler = NULL;
817a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
818a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->inBuf;
819a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inBuf = NULL;
820a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->outBuf;
821a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outBuf = NULL;
822a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        delete session->revBuf;
823a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revBuf = NULL;
824a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
825a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->io = 0;
826a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
827a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
828a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
829a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
830a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
831a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
832a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Session_SetConfig(preproc_session_t *session, effect_config_t *config)
833a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
834a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t sr;
835a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t inCnl = popcount(config->inputCfg.channels);
836a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t outCnl = popcount(config->outputCfg.channels);
837a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
838a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
839a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        config->inputCfg.format != config->outputCfg.format ||
840a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
841a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
842a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
843a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
8443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_SetConfig sr %d cnl %08x",
845a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent         config->inputCfg.samplingRate, config->inputCfg.channels);
846a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status;
847a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
848a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    // AEC implementation is limited to 16kHz
849a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
850a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmSamplingRate = 32000;
851a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else
852a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate >= 16000) {
853a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmSamplingRate = 16000;
854a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else if (config->inputCfg.samplingRate >= 8000) {
855a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->apmSamplingRate = 8000;
856a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
857a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    status = session->apm->set_sample_rate_hz(session->apmSamplingRate);
858a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0) {
859a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
860a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
861a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    status = session->apm->set_num_channels(inCnl, outCnl);
862a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0) {
863a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
864a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
865a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    status = session->apm->set_num_reverse_channels(inCnl);
866a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0) {
867a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
868a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
869a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
870a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->samplingRate = config->inputCfg.samplingRate;
871a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->apmFrameCount = session->apmSamplingRate / 100;
872a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->samplingRate == session->apmSamplingRate) {
873a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->frameCount = session->apmFrameCount;
874a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
875a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->frameCount = (session->apmFrameCount * session->samplingRate) /
876a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->apmSamplingRate  + 1;
877a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
878a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->inChannelCount = inCnl;
879a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->outChannelCount = outCnl;
880a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->procFrame->_audioChannel = inCnl;
881a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->procFrame->_frequencyInHz = session->apmSamplingRate;
882a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
883a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revChannelCount = inCnl;
884a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revFrame->_audioChannel = inCnl;
885a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revFrame->_frequencyInHz = session->apmSamplingRate;
886a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
887a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->inResampler != NULL) {
888a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        speex_resampler_destroy(session->inResampler);
889a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inResampler = NULL;
890a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
891a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->outResampler != NULL) {
892a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        speex_resampler_destroy(session->outResampler);
893a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outResampler = NULL;
894a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
895a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->revResampler != NULL) {
896a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        speex_resampler_destroy(session->revResampler);
897a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revResampler = NULL;
898a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
899a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->samplingRate != session->apmSamplingRate) {
900a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        int error;
901a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->inResampler = speex_resampler_init(session->inChannelCount,
902a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->samplingRate,
903a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->apmSamplingRate,
904a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    RESAMPLER_QUALITY,
905a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    &error);
906a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->inResampler == NULL) {
9075ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_SetConfig Cannot create speex resampler: %s",
908a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                 speex_resampler_strerror(error));
909a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
910a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
911a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->outResampler = speex_resampler_init(session->outChannelCount,
912a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->apmSamplingRate,
913a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->samplingRate,
914a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    RESAMPLER_QUALITY,
915a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    &error);
916a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->outResampler == NULL) {
9175ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_SetConfig Cannot create speex resampler: %s",
918a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                 speex_resampler_strerror(error));
919a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->inResampler);
920a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->inResampler = NULL;
921a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
922a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
923a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revResampler = speex_resampler_init(session->inChannelCount,
924a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->samplingRate,
925a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    session->apmSamplingRate,
926a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    RESAMPLER_QUALITY,
927a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                    &error);
928a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->revResampler == NULL) {
9295ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Session_SetConfig Cannot create speex resampler: %s",
930a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                 speex_resampler_strerror(error));
931a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->inResampler);
932a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->inResampler = NULL;
933a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            speex_resampler_destroy(session->outResampler);
934a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->outResampler = NULL;
935a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
936a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
937a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
938a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
939a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->state = PREPROC_SESSION_STATE_CONFIG;
940a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
941a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
942a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
9433d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurentvoid Session_GetConfig(preproc_session_t *session, effect_config_t *config)
9443d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent{
9453d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    memset(config, 0, sizeof(effect_config_t));
9463d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
9473d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
9483d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.channels = session->inChannelCount == 1 ?
9493d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                                    AUDIO_CHANNEL_IN_MONO : AUDIO_CHANNEL_IN_STEREO;
9503d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->outputCfg.channels = session->outChannelCount == 1 ?
9513d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                                    AUDIO_CHANNEL_IN_MONO : AUDIO_CHANNEL_IN_STEREO;
9523d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.mask = config->outputCfg.mask =
9533d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
9543d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent}
9553d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
956a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config)
957a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
958a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
959a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            config->inputCfg.format != config->outputCfg.format ||
960a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
961a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
962a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
963a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
9643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_SetReverseConfig sr %d cnl %08x",
965a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent         config->inputCfg.samplingRate, config->inputCfg.channels);
966a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
967a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session->state < PREPROC_SESSION_STATE_CONFIG) {
968a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENOSYS;
969a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
970a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (config->inputCfg.samplingRate != session->samplingRate ||
971a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
972a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
973a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
974a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t inCnl = popcount(config->inputCfg.channels);
975a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = session->apm->set_num_reverse_channels(inCnl);
976a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0) {
977a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
978a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
979a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revChannelCount = inCnl;
980a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revFrame->_audioChannel = inCnl;
981a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revFrame->_frequencyInHz = session->apmSamplingRate;
982a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
983a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
984a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
9853d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurentvoid Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config)
9863d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent{
9873d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    memset(config, 0, sizeof(effect_config_t));
9883d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
9893d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
9903d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.channels = config->outputCfg.channels =
9913d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            session->revChannelCount == 1 ? AUDIO_CHANNEL_IN_MONO : AUDIO_CHANNEL_IN_STEREO;
9923d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent    config->inputCfg.mask = config->outputCfg.mask =
9933d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
9943d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent}
9953d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
996a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentvoid Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled)
997a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
998a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (enabled) {
999a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if(session->enabledMsk == 0) {
1000a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn = 0;
1001a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inResampler != NULL) {
1002a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_reset_mem(session->inResampler);
1003a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1004a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesOut = 0;
1005a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->outResampler != NULL) {
1006a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_reset_mem(session->outResampler);
1007a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1008a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1009a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->enabledMsk |= (1 << procId);
1010a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (HasReverseStream(procId)) {
1011a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev = 0;
1012a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->revResampler != NULL) {
1013a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_reset_mem(session->revResampler);
1014a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1015a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->revEnabledMsk |= (1 << procId);
1016a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1017a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
1018a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->enabledMsk &= ~(1 << procId);
1019a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (HasReverseStream(procId)) {
1020a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->revEnabledMsk &= ~(1 << procId);
1021a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1022a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
10233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x",
1024a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent         procId, enabled, session->enabledMsk, session->revEnabledMsk);
1025a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->processedMsk = 0;
1026a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (HasReverseStream(procId)) {
1027a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revProcessedMsk = 0;
1028a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1029a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1030a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1031a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1032a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Bundle functions
1033a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1034a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1035a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic int sInitStatus = 1;
1036a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentstatic preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
1037a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1038a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentpreproc_session_t *PreProc_GetSession(int32_t procId, int32_t  sessionId, int32_t  ioId)
1039a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1040a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
1041a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int free = -1;
1042a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
1043a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (sSessions[i].io == ioId) {
1044a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (sSessions[i].createdMsk & (1 << procId)) {
1045a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return NULL;
1046a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1047a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return &sSessions[i];
1048a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1049a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1050a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
1051a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (sSessions[i].io == 0) {
1052a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            sSessions[i].id = sessionId;
1053a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            sSessions[i].io = ioId;
1054a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return &sSessions[i];
1055a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1056a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1057a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return NULL;
1058a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1059a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1060a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1061a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProc_Init() {
1062a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
1063a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status = 0;
1064a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1065a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (sInitStatus <= 0) {
1066a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return sInitStatus;
1067a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1068a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
1069a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        status = Session_Init(&sSessions[i]);
1070a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1071a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    sInitStatus = status;
1072a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return sInitStatus;
1073a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1074a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1075a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentconst effect_descriptor_t *PreProc_GetDescriptor(effect_uuid_t *uuid)
1076a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1077a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    size_t i;
1078a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
1079a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
1080a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return sDescriptors[i];
1081a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1082a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1083a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return NULL;
1084a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1085a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1086a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1087a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentextern "C" {
1088a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1089a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1090a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect Control Interface Implementation
1091a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1092a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1093a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingFx_Process(effect_handle_t     self,
1094a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            audio_buffer_t    *inBuffer,
1095a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            audio_buffer_t    *outBuffer)
1096a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1097a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t * effect = (preproc_effect_t *)self;
1098a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int    status = 0;
1099a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1100a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (effect == NULL){
11013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
1102a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1103a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1104a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_session_t * session = (preproc_session_t *)effect->session;
1105a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1106a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (inBuffer == NULL  || inBuffer->raw == NULL  ||
1107a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            outBuffer == NULL || outBuffer->raw == NULL){
11085ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("PreProcessingFx_Process() ERROR bad pointer");
1109a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1110a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1111a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1112a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->processedMsk |= (1<<effect->procId);
1113a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
11143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block//    ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
1115a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//         inBuffer->frameCount, session->enabledMsk, session->processedMsk);
1116a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1117a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
1118a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->session->processedMsk = 0;
1119a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        size_t framesRq = outBuffer->frameCount;
1120a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        size_t framesWr = 0;
1121a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->framesOut) {
1122a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->framesOut;
1123a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (outBuffer->frameCount < fr) {
1124a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = outBuffer->frameCount;
1125a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1126a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(outBuffer->s16,
1127a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                  session->outBuf,
1128a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                  fr * session->outChannelCount * sizeof(int16_t));
1129a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->outBuf,
1130a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                  session->outBuf + fr * session->outChannelCount,
1131a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                  (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
1132a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesOut -= fr;
1133a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            framesWr += fr;
1134a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1135a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        outBuffer->frameCount = framesWr;
1136a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (framesWr == framesRq) {
1137a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = 0;
1138a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return 0;
1139a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1140a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1141a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->inResampler != NULL) {
1142a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->frameCount - session->framesIn;
1143a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (inBuffer->frameCount < fr) {
1144a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = inBuffer->frameCount;
1145a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1146a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inBufSize < session->framesIn + fr) {
1147a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->inBufSize = session->framesIn + fr;
1148a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->inBuf = (int16_t *)realloc(session->inBuf,
1149a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                 session->inBufSize * session->inChannelCount * sizeof(int16_t));
1150a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1151a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->inBuf + session->framesIn * session->inChannelCount,
1152a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   inBuffer->s16,
1153a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   fr * session->inChannelCount * sizeof(int16_t));
1154a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1155a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn += fr;
1156a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = fr;
1157a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->framesIn < session->frameCount) {
1158a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return 0;
1159a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1160a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t frIn = session->framesIn;
1161a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t frOut = session->apmFrameCount;
1162a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inChannelCount == 1) {
1163a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_int(session->inResampler,
1164a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            0,
1165a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            session->inBuf,
1166a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            &frIn,
1167a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            session->procFrame->_payloadData,
1168a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            &frOut);
1169a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            } else {
1170a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_interleaved_int(session->inResampler,
1171a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        session->inBuf,
1172a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        &frIn,
1173a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        session->procFrame->_payloadData,
1174a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        &frOut);
1175a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1176a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->inBuf,
1177a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   session->inBuf + frIn * session->inChannelCount,
1178a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
1179a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn -= frIn;
1180a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } else {
1181a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->frameCount - session->framesIn;
1182a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (inBuffer->frameCount < fr) {
1183a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = inBuffer->frameCount;
1184a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1185a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->procFrame->_payloadData + session->framesIn * session->inChannelCount,
1186a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   inBuffer->s16,
1187a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   fr * session->inChannelCount * sizeof(int16_t));
1188a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn += fr;
1189a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = fr;
1190a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->framesIn < session->frameCount) {
1191a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return 0;
1192a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1193a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesIn = 0;
1194a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1195a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->procFrame->_payloadDataLengthInSamples =
1196a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->apmFrameCount * session->inChannelCount;
1197a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1198a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->session->apm->ProcessStream(session->procFrame);
1199a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1200a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->outBufSize < session->framesOut + session->frameCount) {
1201a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->outBufSize = session->framesOut + session->frameCount;
1202a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->outBuf = (int16_t *)realloc(session->outBuf,
1203a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                              session->outBufSize * session->outChannelCount * sizeof(int16_t));
1204a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1205a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1206a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->outResampler != NULL) {
1207a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t frIn = session->apmFrameCount;
1208a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t frOut = session->frameCount;
1209a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inChannelCount == 1) {
1210a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_int(session->outResampler,
1211a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    0,
1212a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    session->procFrame->_payloadData,
1213a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    &frIn,
1214a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    session->outBuf + session->framesOut * session->outChannelCount,
1215a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    &frOut);
1216a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            } else {
1217a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_interleaved_int(session->outResampler,
1218a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    session->procFrame->_payloadData,
1219a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    &frIn,
1220a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    session->outBuf + session->framesOut * session->outChannelCount,
1221a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                    &frOut);
1222a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1223a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesOut += frOut;
1224a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } else {
1225a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->outBuf + session->framesOut * session->outChannelCount,
1226a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   session->procFrame->_payloadData,
1227a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   session->frameCount * session->outChannelCount * sizeof(int16_t));
1228a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesOut += session->frameCount;
1229a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1230a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        size_t fr = session->framesOut;
1231a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (framesRq - framesWr < fr) {
1232a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            fr = framesRq - framesWr;
1233a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1234a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        memcpy(outBuffer->s16 + framesWr * session->outChannelCount,
1235a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent              session->outBuf,
1236a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent              fr * session->outChannelCount * sizeof(int16_t));
1237a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        memcpy(session->outBuf,
1238a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent              session->outBuf + fr * session->outChannelCount,
1239a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent              (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
1240a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->framesOut -= fr;
1241a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        outBuffer->frameCount += fr;
1242a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1243a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return 0;
1244a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
1245a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENODATA;
1246a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1247a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1248a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1249a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingFx_Command(effect_handle_t  self,
1250a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            uint32_t            cmdCode,
1251a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            uint32_t            cmdSize,
1252a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            void                *pCmdData,
1253a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            uint32_t            *replySize,
1254a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            void                *pReplyData)
1255a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1256a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t * effect = (preproc_effect_t *) self;
1257a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int retsize;
1258a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status;
1259a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1260a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (effect == NULL){
1261a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1262a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1263a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
12643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
1265a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1266a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    switch (cmdCode){
1267a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_INIT:
1268a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pReplyData == NULL || *replySize != sizeof(int)){
1269a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1270a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1271a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->init) {
1272a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                effect->ops->init(effect);
1273a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1274a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData = 0;
1275a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1276a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
12773d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent        case EFFECT_CMD_SET_CONFIG:
1278a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pCmdData    == NULL||
1279a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                cmdSize     != sizeof(effect_config_t)||
1280a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                pReplyData  == NULL||
1281a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                *replySize  != sizeof(int)){
12823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
12833d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                        "EFFECT_CMD_SET_CONFIG: ERROR");
1284a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1285a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1286a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData);
1287a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (*(int *)pReplyData != 0) {
1288a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                break;
1289a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1290a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
1291a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1292a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
12933d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent        case EFFECT_CMD_GET_CONFIG:
12943d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            if (pReplyData == NULL ||
12953d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                *replySize != sizeof(effect_config_t)) {
12963d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
12973d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                        "EFFECT_CMD_GET_CONFIG: ERROR");
12983d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                return -EINVAL;
12993d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            }
13003d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
13013d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            Session_GetConfig(effect->session, (effect_config_t *)pCmdData);
13023d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            break;
13033d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
13043d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent        case EFFECT_CMD_SET_CONFIG_REVERSE:
13053d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            if (pCmdData == NULL ||
13063d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                cmdSize != sizeof(effect_config_t) ||
13073d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                pReplyData == NULL ||
13083d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                *replySize != sizeof(int)) {
13093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
13103d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                        "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
1311a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1312a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1313a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData = Session_SetReverseConfig(effect->session,
1314a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                          (effect_config_t *)pCmdData);
1315a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (*(int *)pReplyData != 0) {
1316a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                break;
1317a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1318a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1319a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
13203d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent        case EFFECT_CMD_GET_CONFIG_REVERSE:
13213d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            if (pReplyData == NULL ||
13223d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                *replySize != sizeof(effect_config_t)){
13233d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                ALOGV("PreProcessingFx_Command cmdCode Case: "
13243d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                        "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
13253d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent                return -EINVAL;
13263d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            }
13273d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData);
13283d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent            break;
13293d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent
1330a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_RESET:
1331a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->reset) {
1332a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                effect->ops->reset(effect);
1333a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1334a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1335a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1336a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_GET_PARAM:{
1337a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pCmdData == NULL ||
1338a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    cmdSize < (int)sizeof(effect_param_t) ||
1339a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    pReplyData == NULL ||
1340a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    *replySize < (int)sizeof(effect_param_t)){
13413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
1342a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                        "EFFECT_CMD_GET_PARAM: ERROR");
1343a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1344a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1345a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            effect_param_t *p = (effect_param_t *)pCmdData;
1346a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1347a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
1348a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1349a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            p = (effect_param_t *)pReplyData;
1350a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1351a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
1352a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1353a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->get_parameter) {
1354a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                p->status = effect->ops->get_parameter(effect, p->data,
1355a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                       (size_t  *)&p->vsize,
1356a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                       p->data + voffset);
1357a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                *replySize = sizeof(effect_param_t) + voffset + p->vsize;
1358a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1359a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } break;
1360a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1361a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_PARAM:{
1362a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pCmdData == NULL||
1363a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    cmdSize < (int)sizeof(effect_param_t) ||
1364a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    pReplyData == NULL ||
1365a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                    *replySize != sizeof(int32_t)){
13663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
1367a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                        "EFFECT_CMD_SET_PARAM: ERROR");
1368a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1369a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1370a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            effect_param_t *p = (effect_param_t *) pCmdData;
1371a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1372a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (p->psize != sizeof(int32_t)){
13733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: "
1374a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                        "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
1375a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1376a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1377a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->set_parameter) {
1378a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                *(int *)pReplyData = effect->ops->set_parameter(effect,
1379a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                                (void *)p->data,
1380a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                                p->data + p->psize);
1381a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1382a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } break;
1383a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1384a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_ENABLE:
1385a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pReplyData == NULL || *replySize != sizeof(int)){
13863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
1387a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1388a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1389a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
1390a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1391a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1392a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_DISABLE:
1393a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pReplyData == NULL || *replySize != sizeof(int)){
13943856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
1395a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1396a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1397a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            *(int *)pReplyData  = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
1398a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1399a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1400a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_DEVICE:
1401a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_INPUT_DEVICE:
1402a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (pCmdData == NULL ||
1403a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                cmdSize != sizeof(uint32_t)) {
14043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
1405a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return -EINVAL;
1406a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1407a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1408a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (effect->ops->set_device) {
1409a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                effect->ops->set_device(effect, *(uint32_t *)pCmdData);
1410a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1411a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1412a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1413a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_VOLUME:
1414a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        case EFFECT_CMD_SET_AUDIO_MODE:
1415a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            break;
1416a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1417a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        default:
1418a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            return -EINVAL;
1419a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1420a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
1421a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1422a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1423a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1424a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingFx_GetDescriptor(effect_handle_t   self,
1425a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                  effect_descriptor_t *pDescriptor)
1426a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1427a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t * effect = (preproc_effect_t *) self;
1428a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1429a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (effect == NULL || pDescriptor == NULL) {
1430a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1431a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1432a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1433a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    memcpy(pDescriptor, sDescriptors[effect->procId], sizeof(effect_descriptor_t));
1434a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1435a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
1436a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1437a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1438a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingFx_ProcessReverse(effect_handle_t     self,
1439a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                   audio_buffer_t    *inBuffer,
1440a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                   audio_buffer_t    *outBuffer)
1441a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1442a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t * effect = (preproc_effect_t *)self;
1443a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int    status = 0;
1444a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1445a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (effect == NULL){
14465ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
1447a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1448a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1449a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_session_t * session = (preproc_session_t *)effect->session;
1450a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1451a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (inBuffer == NULL  || inBuffer->raw == NULL){
14525ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
1453a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1454a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1455a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1456a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session->revProcessedMsk |= (1<<effect->procId);
1457a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
14583856b090cd04ba5dd4a59a12430ed724d5995909Steve Block//    ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x",
1459a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//         inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
1460a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1461a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1462a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
1463a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->session->revProcessedMsk = 0;
1464a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        if (session->revResampler != NULL) {
1465a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->frameCount - session->framesRev;
1466a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (inBuffer->frameCount < fr) {
1467a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = inBuffer->frameCount;
1468a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1469a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->revBufSize < session->framesRev + fr) {
1470a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->revBufSize = session->framesRev + fr;
1471a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->revBuf = (int16_t *)realloc(session->revBuf,
1472a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                  session->revBufSize * session->inChannelCount * sizeof(int16_t));
1473a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1474a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->revBuf + session->framesRev * session->inChannelCount,
1475a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   inBuffer->s16,
1476a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   fr * session->inChannelCount * sizeof(int16_t));
1477a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1478a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev += fr;
1479a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = fr;
1480a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->framesRev < session->frameCount) {
1481a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return 0;
1482a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1483a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t frIn = session->framesRev;
1484a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t frOut = session->apmFrameCount;
1485a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->inChannelCount == 1) {
1486a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_int(session->revResampler,
1487a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            0,
1488a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            session->revBuf,
1489a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            &frIn,
1490a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            session->revFrame->_payloadData,
1491a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                            &frOut);
1492a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            } else {
1493a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                speex_resampler_process_interleaved_int(session->revResampler,
1494a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        session->revBuf,
1495a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        &frIn,
1496a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        session->revFrame->_payloadData,
1497a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                                        &frOut);
1498a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1499a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->revBuf,
1500a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   session->revBuf + frIn * session->inChannelCount,
1501a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
1502a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev -= frIn;
1503a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        } else {
1504a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            size_t fr = session->frameCount - session->framesRev;
1505a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (inBuffer->frameCount < fr) {
1506a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                fr = inBuffer->frameCount;
1507a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1508a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            memcpy(session->revFrame->_payloadData + session->framesRev * session->inChannelCount,
1509a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   inBuffer->s16,
1510a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                   fr * session->inChannelCount * sizeof(int16_t));
1511a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev += fr;
1512a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            inBuffer->frameCount = fr;
1513a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            if (session->framesRev < session->frameCount) {
1514a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                return 0;
1515a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            }
1516a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent            session->framesRev = 0;
1517a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        }
1518a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->revFrame->_payloadDataLengthInSamples =
1519a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                session->apmFrameCount * session->inChannelCount;
1520a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        effect->session->apm->AnalyzeReverseStream(session->revFrame);
1521a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return 0;
1522a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    } else {
1523a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -ENODATA;
1524a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1525a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1526a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1527a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1528a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// effect_handle_t interface implementation for effect
1529a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentconst struct effect_interface_s sEffectInterface = {
1530a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_Process,
1531a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_Command,
1532a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_GetDescriptor,
1533a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    NULL
1534a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
1535a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1536a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentconst struct effect_interface_s sEffectInterfaceReverse = {
1537a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_Process,
1538a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_Command,
1539a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_GetDescriptor,
1540a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    PreProcessingFx_ProcessReverse
1541a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
1542a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1543a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1544a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent// Effect Library Interface Implementation
1545a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent//------------------------------------------------------------------------------
1546a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1547a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingLib_QueryNumberEffects(uint32_t *pNumEffects)
1548a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1549a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (PreProc_Init() != 0) {
1550a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return sInitStatus;
1551a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1552a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (pNumEffects == NULL) {
1553a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1554a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1555a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    *pNumEffects = PREPROC_NUM_EFFECTS;
1556a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return sInitStatus;
1557a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1558a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1559a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
1560a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1561a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (PreProc_Init() != 0) {
1562a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return sInitStatus;
1563a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1564a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (index >= PREPROC_NUM_EFFECTS) {
1565a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1566a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1567a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    memcpy(pDescriptor, sDescriptors[index], sizeof(effect_descriptor_t));
1568a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
1569a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1570a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1571a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingLib_Create(effect_uuid_t       *uuid,
1572a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            int32_t             sessionId,
1573a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            int32_t             ioId,
1574a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                            effect_handle_t  *pInterface)
1575a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
15763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
1577a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1578a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status;
1579a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    const effect_descriptor_t *desc;
1580a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_session_t *session;
1581a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    uint32_t procId;
1582a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1583a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (PreProc_Init() != 0) {
1584a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return sInitStatus;
1585a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1586a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    desc =  PreProc_GetDescriptor(uuid);
1587a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (desc == NULL) {
15885ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
1589a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1590a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1591a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    procId = UuidToProcId(&desc->type);
1592a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1593a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    session = PreProc_GetSession(procId, sessionId, ioId);
1594a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (session == NULL) {
15955ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("EffectCreate: no more session available");
1596a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1597a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1598a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1599a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    status = Session_CreateEffect(session, procId, pInterface);
1600a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1601a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (status < 0 && session->createdMsk == 0) {
1602a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        session->io = 0;
1603a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1604a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return status;
1605a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1606a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1607a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingLib_Release(effect_handle_t interface)
1608a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent{
1609a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    int status;
16103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("EffectRelease start %p", interface);
1611a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (PreProc_Init() != 0) {
1612a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return sInitStatus;
1613a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1614a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1615a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    preproc_effect_t *fx = (preproc_effect_t *)interface;
1616a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1617a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (fx->session->io == 0) {
1618a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1619a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1620a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return Session_ReleaseEffect(fx->session, fx);
1621a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1622a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1623a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentint PreProcessingLib_GetDescriptor(effect_uuid_t       *uuid,
1624a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent                                   effect_descriptor_t *pDescriptor) {
1625a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1626a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (pDescriptor == NULL || uuid == NULL){
1627a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return -EINVAL;
1628a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1629a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1630a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid);
1631a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    if (desc == NULL) {
16323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("PreProcessingLib_GetDescriptor() not found");
1633a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent        return  -EINVAL;
1634a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    }
1635a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
16363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
1637a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1638a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
1639a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    return 0;
1640a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}
1641a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1642a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurentaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
1643a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    tag : AUDIO_EFFECT_LIBRARY_TAG,
1644a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    version : EFFECT_LIBRARY_API_VERSION,
1645a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    name : "Audio Preprocessing Library",
1646a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    implementor : "The Android Open Source Project",
1647a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    query_num_effects : PreProcessingLib_QueryNumberEffects,
1648a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    query_effect : PreProcessingLib_QueryEffect,
1649a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    create_effect : PreProcessingLib_Create,
1650a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    release_effect : PreProcessingLib_Release,
1651a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent    get_descriptor : PreProcessingLib_GetDescriptor
1652a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent};
1653a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent
1654a9390d4d571817cdb1d659b4b22b04130dc77a48Eric Laurent}; // extern "C"
1655