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