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