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     switch(device) {
    521     case AUDIO_DEVICE_OUT_EARPIECE:
    522         mode = webrtc::EchoControlMobile::kEarpiece;
    523         break;
    524     case AUDIO_DEVICE_OUT_SPEAKER:
    525         mode = webrtc::EchoControlMobile::kSpeakerphone;
    526         break;
    527     case AUDIO_DEVICE_OUT_WIRED_HEADSET:
    528     case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
    529     default:
    530         break;
    531     }
    532     aec->set_routing_mode(mode);
    533     return 0;
    534 }
    535 
    536 static const preproc_ops_t sAecOps = {
    537         AecCreate,
    538         AecInit,
    539         NULL,
    540         AecEnable,
    541         AecDisable,
    542         AecSetParameter,
    543         AecGetParameter,
    544         AecSetDevice
    545 };
    546 
    547 //------------------------------------------------------------------------------
    548 // Noise Suppression (NS)
    549 //------------------------------------------------------------------------------
    550 
    551 static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
    552 
    553 int  NsInit (preproc_effect_t *effect)
    554 {
    555     ALOGV("NsInit");
    556     webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
    557     ns->set_level(kNsDefaultLevel);
    558     return 0;
    559 }
    560 
    561 int  NsCreate(preproc_effect_t *effect)
    562 {
    563     webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression();
    564     ALOGV("NsCreate got ns %p", ns);
    565     if (ns == NULL) {
    566         ALOGW("AgcCreate Error");
    567         return -ENOMEM;
    568     }
    569     effect->engine = static_cast<preproc_fx_handle_t>(ns);
    570     NsInit (effect);
    571     return 0;
    572 }
    573 
    574 int NsGetParameter(preproc_effect_t     *effect,
    575                    void              *pParam,
    576                    size_t            *pValueSize,
    577                    void              *pValue)
    578 {
    579     int status = 0;
    580     return status;
    581 }
    582 
    583 int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
    584 {
    585     int status = 0;
    586     return status;
    587 }
    588 
    589 void NsEnable(preproc_effect_t *effect)
    590 {
    591     webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
    592     ALOGV("NsEnable ns %p", ns);
    593     ns->Enable(true);
    594 }
    595 
    596 void NsDisable(preproc_effect_t *effect)
    597 {
    598     ALOGV("NsDisable");
    599     webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
    600     ns->Enable(false);
    601 }
    602 
    603 static const preproc_ops_t sNsOps = {
    604         NsCreate,
    605         NsInit,
    606         NULL,
    607         NsEnable,
    608         NsDisable,
    609         NsSetParameter,
    610         NsGetParameter,
    611         NULL
    612 };
    613 
    614 
    615 static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = {
    616         &sAgcOps,
    617         &sAecOps,
    618         &sNsOps
    619 };
    620 
    621 
    622 //------------------------------------------------------------------------------
    623 // Effect functions
    624 //------------------------------------------------------------------------------
    625 
    626 void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled);
    627 
    628 extern "C" const struct effect_interface_s sEffectInterface;
    629 extern "C" const struct effect_interface_s sEffectInterfaceReverse;
    630 
    631 #define BAD_STATE_ABORT(from, to) \
    632         LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
    633 
    634 int Effect_SetState(preproc_effect_t *effect, uint32_t state)
    635 {
    636     int status = 0;
    637     ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
    638     switch(state) {
    639     case PREPROC_EFFECT_STATE_INIT:
    640         switch(effect->state) {
    641         case PREPROC_EFFECT_STATE_ACTIVE:
    642             effect->ops->disable(effect);
    643             Session_SetProcEnabled(effect->session, effect->procId, false);
    644         case PREPROC_EFFECT_STATE_CONFIG:
    645         case PREPROC_EFFECT_STATE_CREATED:
    646         case PREPROC_EFFECT_STATE_INIT:
    647             break;
    648         default:
    649             BAD_STATE_ABORT(effect->state, state);
    650         }
    651         break;
    652     case PREPROC_EFFECT_STATE_CREATED:
    653         switch(effect->state) {
    654         case PREPROC_EFFECT_STATE_INIT:
    655             status = effect->ops->create(effect);
    656             break;
    657         case PREPROC_EFFECT_STATE_CREATED:
    658         case PREPROC_EFFECT_STATE_ACTIVE:
    659         case PREPROC_EFFECT_STATE_CONFIG:
    660             ALOGE("Effect_SetState invalid transition");
    661             status = -ENOSYS;
    662             break;
    663         default:
    664             BAD_STATE_ABORT(effect->state, state);
    665         }
    666         break;
    667     case PREPROC_EFFECT_STATE_CONFIG:
    668         switch(effect->state) {
    669         case PREPROC_EFFECT_STATE_INIT:
    670             ALOGE("Effect_SetState invalid transition");
    671             status = -ENOSYS;
    672             break;
    673         case PREPROC_EFFECT_STATE_ACTIVE:
    674             effect->ops->disable(effect);
    675             Session_SetProcEnabled(effect->session, effect->procId, false);
    676             break;
    677         case PREPROC_EFFECT_STATE_CREATED:
    678         case PREPROC_EFFECT_STATE_CONFIG:
    679             break;
    680         default:
    681             BAD_STATE_ABORT(effect->state, state);
    682         }
    683         break;
    684     case PREPROC_EFFECT_STATE_ACTIVE:
    685         switch(effect->state) {
    686         case PREPROC_EFFECT_STATE_INIT:
    687         case PREPROC_EFFECT_STATE_CREATED:
    688             ALOGE("Effect_SetState invalid transition");
    689             status = -ENOSYS;
    690             break;
    691         case PREPROC_EFFECT_STATE_ACTIVE:
    692             // enabling an already enabled effect is just ignored
    693             break;
    694         case PREPROC_EFFECT_STATE_CONFIG:
    695             effect->ops->enable(effect);
    696             Session_SetProcEnabled(effect->session, effect->procId, true);
    697             break;
    698         default:
    699             BAD_STATE_ABORT(effect->state, state);
    700         }
    701         break;
    702     default:
    703         BAD_STATE_ABORT(effect->state, state);
    704     }
    705     if (status == 0) {
    706         effect->state = state;
    707     }
    708     return status;
    709 }
    710 
    711 int Effect_Init(preproc_effect_t *effect, uint32_t procId)
    712 {
    713     if (HasReverseStream(procId)) {
    714         effect->itfe = &sEffectInterfaceReverse;
    715     } else {
    716         effect->itfe = &sEffectInterface;
    717     }
    718     effect->ops = sPreProcOps[procId];
    719     effect->procId = procId;
    720     effect->state = PREPROC_EFFECT_STATE_INIT;
    721     return 0;
    722 }
    723 
    724 int Effect_Create(preproc_effect_t *effect,
    725                preproc_session_t *session,
    726                effect_handle_t  *interface)
    727 {
    728     effect->session = session;
    729     *interface = (effect_handle_t)&effect->itfe;
    730     return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
    731 }
    732 
    733 int Effect_Release(preproc_effect_t *effect)
    734 {
    735     return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
    736 }
    737 
    738 
    739 //------------------------------------------------------------------------------
    740 // Session functions
    741 //------------------------------------------------------------------------------
    742 
    743 #define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
    744 
    745 static const int kPreprocDefaultSr = 16000;
    746 static const int kPreProcDefaultCnl = 1;
    747 
    748 int Session_Init(preproc_session_t *session)
    749 {
    750     size_t i;
    751     int status = 0;
    752 
    753     session->state = PREPROC_SESSION_STATE_INIT;
    754     session->id = 0;
    755     session->io = 0;
    756     session->createdMsk = 0;
    757     session->apm = NULL;
    758     for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
    759         status = Effect_Init(&session->effects[i], i);
    760     }
    761     return status;
    762 }
    763 
    764 
    765 extern "C" int Session_CreateEffect(preproc_session_t *session,
    766                                     int32_t procId,
    767                                     effect_handle_t  *interface)
    768 {
    769     int status = -ENOMEM;
    770 
    771     ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
    772 
    773     if (session->createdMsk == 0) {
    774         session->apm = webrtc::AudioProcessing::Create(session->io);
    775         if (session->apm == NULL) {
    776             ALOGW("Session_CreateEffect could not get apm engine");
    777             goto error;
    778         }
    779         session->apm->set_sample_rate_hz(kPreprocDefaultSr);
    780         session->apm->set_num_channels(kPreProcDefaultCnl, kPreProcDefaultCnl);
    781         session->apm->set_num_reverse_channels(kPreProcDefaultCnl);
    782         session->procFrame = new webrtc::AudioFrame();
    783         if (session->procFrame == NULL) {
    784             ALOGW("Session_CreateEffect could not allocate audio frame");
    785             goto error;
    786         }
    787         session->revFrame = new webrtc::AudioFrame();
    788         if (session->revFrame == NULL) {
    789             ALOGW("Session_CreateEffect could not allocate reverse audio frame");
    790             goto error;
    791         }
    792         session->apmSamplingRate = kPreprocDefaultSr;
    793         session->apmFrameCount = (kPreprocDefaultSr) / 100;
    794         session->frameCount = session->apmFrameCount;
    795         session->samplingRate = kPreprocDefaultSr;
    796         session->inChannelCount = kPreProcDefaultCnl;
    797         session->outChannelCount = kPreProcDefaultCnl;
    798         session->procFrame->_frequencyInHz = kPreprocDefaultSr;
    799         session->procFrame->_audioChannel = kPreProcDefaultCnl;
    800         session->revChannelCount = kPreProcDefaultCnl;
    801         session->revFrame->_frequencyInHz = kPreprocDefaultSr;
    802         session->revFrame->_audioChannel = kPreProcDefaultCnl;
    803         session->enabledMsk = 0;
    804         session->processedMsk = 0;
    805         session->revEnabledMsk = 0;
    806         session->revProcessedMsk = 0;
    807         session->inResampler = NULL;
    808         session->inBuf = NULL;
    809         session->inBufSize = 0;
    810         session->outResampler = NULL;
    811         session->outBuf = NULL;
    812         session->outBufSize = 0;
    813         session->revResampler = NULL;
    814         session->revBuf = NULL;
    815         session->revBufSize = 0;
    816     }
    817     status = Effect_Create(&session->effects[procId], session, interface);
    818     if (status < 0) {
    819         goto error;
    820     }
    821     ALOGV("Session_CreateEffect OK");
    822     session->createdMsk |= (1<<procId);
    823     return status;
    824 
    825 error:
    826     if (session->createdMsk == 0) {
    827         delete session->revFrame;
    828         session->revFrame = NULL;
    829         delete session->procFrame;
    830         session->procFrame = NULL;
    831         webrtc::AudioProcessing::Destroy(session->apm);
    832         session->apm = NULL;
    833     }
    834     return status;
    835 }
    836 
    837 int Session_ReleaseEffect(preproc_session_t *session,
    838                           preproc_effect_t *fx)
    839 {
    840     ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
    841     session->createdMsk &= ~(1<<fx->procId);
    842     if (session->createdMsk == 0) {
    843         webrtc::AudioProcessing::Destroy(session->apm);
    844         session->apm = NULL;
    845         delete session->procFrame;
    846         session->procFrame = NULL;
    847         delete session->revFrame;
    848         session->revFrame = NULL;
    849         if (session->inResampler != NULL) {
    850             speex_resampler_destroy(session->inResampler);
    851             session->inResampler = NULL;
    852         }
    853         if (session->outResampler != NULL) {
    854             speex_resampler_destroy(session->outResampler);
    855             session->outResampler = NULL;
    856         }
    857         if (session->revResampler != NULL) {
    858             speex_resampler_destroy(session->revResampler);
    859             session->revResampler = NULL;
    860         }
    861         delete session->inBuf;
    862         session->inBuf = NULL;
    863         delete session->outBuf;
    864         session->outBuf = NULL;
    865         delete session->revBuf;
    866         session->revBuf = NULL;
    867 
    868         session->io = 0;
    869     }
    870 
    871     return 0;
    872 }
    873 
    874 
    875 int Session_SetConfig(preproc_session_t *session, effect_config_t *config)
    876 {
    877     uint32_t sr;
    878     uint32_t inCnl = popcount(config->inputCfg.channels);
    879     uint32_t outCnl = popcount(config->outputCfg.channels);
    880 
    881     if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
    882         config->inputCfg.format != config->outputCfg.format ||
    883         config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
    884         return -EINVAL;
    885     }
    886 
    887     ALOGV("Session_SetConfig sr %d cnl %08x",
    888          config->inputCfg.samplingRate, config->inputCfg.channels);
    889     int status;
    890 
    891     // if at least one process is enabled, do not accept configuration changes
    892     if (session->enabledMsk) {
    893         if (session->samplingRate != config->inputCfg.samplingRate ||
    894                 session->inChannelCount != inCnl ||
    895                 session->outChannelCount != outCnl) {
    896             return -ENOSYS;
    897         } else {
    898             return 0;
    899         }
    900     }
    901 
    902     // AEC implementation is limited to 16kHz
    903     if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
    904         session->apmSamplingRate = 32000;
    905     } else
    906     if (config->inputCfg.samplingRate >= 16000) {
    907         session->apmSamplingRate = 16000;
    908     } else if (config->inputCfg.samplingRate >= 8000) {
    909         session->apmSamplingRate = 8000;
    910     }
    911     status = session->apm->set_sample_rate_hz(session->apmSamplingRate);
    912     if (status < 0) {
    913         return -EINVAL;
    914     }
    915     status = session->apm->set_num_channels(inCnl, outCnl);
    916     if (status < 0) {
    917         return -EINVAL;
    918     }
    919     status = session->apm->set_num_reverse_channels(inCnl);
    920     if (status < 0) {
    921         return -EINVAL;
    922     }
    923 
    924     session->samplingRate = config->inputCfg.samplingRate;
    925     session->apmFrameCount = session->apmSamplingRate / 100;
    926     if (session->samplingRate == session->apmSamplingRate) {
    927         session->frameCount = session->apmFrameCount;
    928     } else {
    929         session->frameCount = (session->apmFrameCount * session->samplingRate) /
    930                 session->apmSamplingRate  + 1;
    931     }
    932     session->inChannelCount = inCnl;
    933     session->outChannelCount = outCnl;
    934     session->procFrame->_audioChannel = inCnl;
    935     session->procFrame->_frequencyInHz = session->apmSamplingRate;
    936 
    937     session->revChannelCount = inCnl;
    938     session->revFrame->_audioChannel = inCnl;
    939     session->revFrame->_frequencyInHz = session->apmSamplingRate;
    940 
    941     // force process buffer reallocation
    942     session->inBufSize = 0;
    943     session->outBufSize = 0;
    944     session->framesIn = 0;
    945     session->framesOut = 0;
    946 
    947 
    948     if (session->inResampler != NULL) {
    949         speex_resampler_destroy(session->inResampler);
    950         session->inResampler = NULL;
    951     }
    952     if (session->outResampler != NULL) {
    953         speex_resampler_destroy(session->outResampler);
    954         session->outResampler = NULL;
    955     }
    956     if (session->revResampler != NULL) {
    957         speex_resampler_destroy(session->revResampler);
    958         session->revResampler = NULL;
    959     }
    960     if (session->samplingRate != session->apmSamplingRate) {
    961         int error;
    962         session->inResampler = speex_resampler_init(session->inChannelCount,
    963                                                     session->samplingRate,
    964                                                     session->apmSamplingRate,
    965                                                     RESAMPLER_QUALITY,
    966                                                     &error);
    967         if (session->inResampler == NULL) {
    968             ALOGW("Session_SetConfig Cannot create speex resampler: %s",
    969                  speex_resampler_strerror(error));
    970             return -EINVAL;
    971         }
    972         session->outResampler = speex_resampler_init(session->outChannelCount,
    973                                                     session->apmSamplingRate,
    974                                                     session->samplingRate,
    975                                                     RESAMPLER_QUALITY,
    976                                                     &error);
    977         if (session->outResampler == NULL) {
    978             ALOGW("Session_SetConfig Cannot create speex resampler: %s",
    979                  speex_resampler_strerror(error));
    980             speex_resampler_destroy(session->inResampler);
    981             session->inResampler = NULL;
    982             return -EINVAL;
    983         }
    984         session->revResampler = speex_resampler_init(session->inChannelCount,
    985                                                     session->samplingRate,
    986                                                     session->apmSamplingRate,
    987                                                     RESAMPLER_QUALITY,
    988                                                     &error);
    989         if (session->revResampler == NULL) {
    990             ALOGW("Session_SetConfig Cannot create speex resampler: %s",
    991                  speex_resampler_strerror(error));
    992             speex_resampler_destroy(session->inResampler);
    993             session->inResampler = NULL;
    994             speex_resampler_destroy(session->outResampler);
    995             session->outResampler = NULL;
    996             return -EINVAL;
    997         }
    998     }
    999 
   1000     session->state = PREPROC_SESSION_STATE_CONFIG;
   1001     return 0;
   1002 }
   1003 
   1004 void Session_GetConfig(preproc_session_t *session, effect_config_t *config)
   1005 {
   1006     memset(config, 0, sizeof(effect_config_t));
   1007     config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
   1008     config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
   1009     config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount);
   1010     // "out" doesn't mean output device, so this is the correct API to convert channel count to mask
   1011     config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount);
   1012     config->inputCfg.mask = config->outputCfg.mask =
   1013             (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
   1014 }
   1015 
   1016 int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config)
   1017 {
   1018     if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
   1019             config->inputCfg.format != config->outputCfg.format ||
   1020             config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
   1021         return -EINVAL;
   1022     }
   1023 
   1024     ALOGV("Session_SetReverseConfig sr %d cnl %08x",
   1025          config->inputCfg.samplingRate, config->inputCfg.channels);
   1026 
   1027     if (session->state < PREPROC_SESSION_STATE_CONFIG) {
   1028         return -ENOSYS;
   1029     }
   1030     if (config->inputCfg.samplingRate != session->samplingRate ||
   1031             config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
   1032         return -EINVAL;
   1033     }
   1034     uint32_t inCnl = popcount(config->inputCfg.channels);
   1035     int status = session->apm->set_num_reverse_channels(inCnl);
   1036     if (status < 0) {
   1037         return -EINVAL;
   1038     }
   1039     session->revChannelCount = inCnl;
   1040     session->revFrame->_audioChannel = inCnl;
   1041     session->revFrame->_frequencyInHz = session->apmSamplingRate;
   1042     // force process buffer reallocation
   1043     session->revBufSize = 0;
   1044     session->framesRev = 0;
   1045 
   1046     return 0;
   1047 }
   1048 
   1049 void Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config)
   1050 {
   1051     memset(config, 0, sizeof(effect_config_t));
   1052     config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
   1053     config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
   1054     config->inputCfg.channels = config->outputCfg.channels =
   1055             audio_channel_in_mask_from_count(session->revChannelCount);
   1056     config->inputCfg.mask = config->outputCfg.mask =
   1057             (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
   1058 }
   1059 
   1060 void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled)
   1061 {
   1062     if (enabled) {
   1063         if(session->enabledMsk == 0) {
   1064             session->framesIn = 0;
   1065             if (session->inResampler != NULL) {
   1066                 speex_resampler_reset_mem(session->inResampler);
   1067             }
   1068             session->framesOut = 0;
   1069             if (session->outResampler != NULL) {
   1070                 speex_resampler_reset_mem(session->outResampler);
   1071             }
   1072         }
   1073         session->enabledMsk |= (1 << procId);
   1074         if (HasReverseStream(procId)) {
   1075             session->framesRev = 0;
   1076             if (session->revResampler != NULL) {
   1077                 speex_resampler_reset_mem(session->revResampler);
   1078             }
   1079             session->revEnabledMsk |= (1 << procId);
   1080         }
   1081     } else {
   1082         session->enabledMsk &= ~(1 << procId);
   1083         if (HasReverseStream(procId)) {
   1084             session->revEnabledMsk &= ~(1 << procId);
   1085         }
   1086     }
   1087     ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x",
   1088          procId, enabled, session->enabledMsk, session->revEnabledMsk);
   1089     session->processedMsk = 0;
   1090     if (HasReverseStream(procId)) {
   1091         session->revProcessedMsk = 0;
   1092     }
   1093 }
   1094 
   1095 //------------------------------------------------------------------------------
   1096 // Bundle functions
   1097 //------------------------------------------------------------------------------
   1098 
   1099 static int sInitStatus = 1;
   1100 static preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
   1101 
   1102 preproc_session_t *PreProc_GetSession(int32_t procId, int32_t  sessionId, int32_t  ioId)
   1103 {
   1104     size_t i;
   1105     int free = -1;
   1106     for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
   1107         if (sSessions[i].io == ioId) {
   1108             if (sSessions[i].createdMsk & (1 << procId)) {
   1109                 return NULL;
   1110             }
   1111             return &sSessions[i];
   1112         }
   1113     }
   1114     for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
   1115         if (sSessions[i].io == 0) {
   1116             sSessions[i].id = sessionId;
   1117             sSessions[i].io = ioId;
   1118             return &sSessions[i];
   1119         }
   1120     }
   1121     return NULL;
   1122 }
   1123 
   1124 
   1125 int PreProc_Init() {
   1126     size_t i;
   1127     int status = 0;
   1128 
   1129     if (sInitStatus <= 0) {
   1130         return sInitStatus;
   1131     }
   1132     for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
   1133         status = Session_Init(&sSessions[i]);
   1134     }
   1135     sInitStatus = status;
   1136     return sInitStatus;
   1137 }
   1138 
   1139 const effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid)
   1140 {
   1141     size_t i;
   1142     for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
   1143         if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
   1144             return sDescriptors[i];
   1145         }
   1146     }
   1147     return NULL;
   1148 }
   1149 
   1150 
   1151 extern "C" {
   1152 
   1153 //------------------------------------------------------------------------------
   1154 // Effect Control Interface Implementation
   1155 //------------------------------------------------------------------------------
   1156 
   1157 int PreProcessingFx_Process(effect_handle_t     self,
   1158                             audio_buffer_t    *inBuffer,
   1159                             audio_buffer_t    *outBuffer)
   1160 {
   1161     preproc_effect_t * effect = (preproc_effect_t *)self;
   1162     int    status = 0;
   1163 
   1164     if (effect == NULL){
   1165         ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
   1166         return -EINVAL;
   1167     }
   1168     preproc_session_t * session = (preproc_session_t *)effect->session;
   1169 
   1170     if (inBuffer == NULL  || inBuffer->raw == NULL  ||
   1171             outBuffer == NULL || outBuffer->raw == NULL){
   1172         ALOGW("PreProcessingFx_Process() ERROR bad pointer");
   1173         return -EINVAL;
   1174     }
   1175 
   1176     session->processedMsk |= (1<<effect->procId);
   1177 
   1178 //    ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
   1179 //         inBuffer->frameCount, session->enabledMsk, session->processedMsk);
   1180 
   1181     if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
   1182         effect->session->processedMsk = 0;
   1183         size_t framesRq = outBuffer->frameCount;
   1184         size_t framesWr = 0;
   1185         if (session->framesOut) {
   1186             size_t fr = session->framesOut;
   1187             if (outBuffer->frameCount < fr) {
   1188                 fr = outBuffer->frameCount;
   1189             }
   1190             memcpy(outBuffer->s16,
   1191                   session->outBuf,
   1192                   fr * session->outChannelCount * sizeof(int16_t));
   1193             memcpy(session->outBuf,
   1194                   session->outBuf + fr * session->outChannelCount,
   1195                   (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
   1196             session->framesOut -= fr;
   1197             framesWr += fr;
   1198         }
   1199         outBuffer->frameCount = framesWr;
   1200         if (framesWr == framesRq) {
   1201             inBuffer->frameCount = 0;
   1202             return 0;
   1203         }
   1204 
   1205         if (session->inResampler != NULL) {
   1206             size_t fr = session->frameCount - session->framesIn;
   1207             if (inBuffer->frameCount < fr) {
   1208                 fr = inBuffer->frameCount;
   1209             }
   1210             if (session->inBufSize < session->framesIn + fr) {
   1211                 session->inBufSize = session->framesIn + fr;
   1212                 session->inBuf = (int16_t *)realloc(session->inBuf,
   1213                                  session->inBufSize * session->inChannelCount * sizeof(int16_t));
   1214             }
   1215             memcpy(session->inBuf + session->framesIn * session->inChannelCount,
   1216                    inBuffer->s16,
   1217                    fr * session->inChannelCount * sizeof(int16_t));
   1218 #ifdef DUAL_MIC_TEST
   1219             pthread_mutex_lock(&gPcmDumpLock);
   1220             if (gPcmDumpFh != NULL) {
   1221                 fwrite(inBuffer->raw,
   1222                        fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
   1223             }
   1224             pthread_mutex_unlock(&gPcmDumpLock);
   1225 #endif
   1226 
   1227             session->framesIn += fr;
   1228             inBuffer->frameCount = fr;
   1229             if (session->framesIn < session->frameCount) {
   1230                 return 0;
   1231             }
   1232             size_t frIn = session->framesIn;
   1233             size_t frOut = session->apmFrameCount;
   1234             if (session->inChannelCount == 1) {
   1235                 speex_resampler_process_int(session->inResampler,
   1236                                             0,
   1237                                             session->inBuf,
   1238                                             &frIn,
   1239                                             session->procFrame->_payloadData,
   1240                                             &frOut);
   1241             } else {
   1242                 speex_resampler_process_interleaved_int(session->inResampler,
   1243                                                         session->inBuf,
   1244                                                         &frIn,
   1245                                                         session->procFrame->_payloadData,
   1246                                                         &frOut);
   1247             }
   1248             memcpy(session->inBuf,
   1249                    session->inBuf + frIn * session->inChannelCount,
   1250                    (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
   1251             session->framesIn -= frIn;
   1252         } else {
   1253             size_t fr = session->frameCount - session->framesIn;
   1254             if (inBuffer->frameCount < fr) {
   1255                 fr = inBuffer->frameCount;
   1256             }
   1257             memcpy(session->procFrame->_payloadData + session->framesIn * session->inChannelCount,
   1258                    inBuffer->s16,
   1259                    fr * session->inChannelCount * sizeof(int16_t));
   1260 
   1261 #ifdef DUAL_MIC_TEST
   1262             pthread_mutex_lock(&gPcmDumpLock);
   1263             if (gPcmDumpFh != NULL) {
   1264                 fwrite(inBuffer->raw,
   1265                        fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
   1266             }
   1267             pthread_mutex_unlock(&gPcmDumpLock);
   1268 #endif
   1269 
   1270             session->framesIn += fr;
   1271             inBuffer->frameCount = fr;
   1272             if (session->framesIn < session->frameCount) {
   1273                 return 0;
   1274             }
   1275             session->framesIn = 0;
   1276         }
   1277         session->procFrame->_payloadDataLengthInSamples =
   1278                 session->apmFrameCount * session->inChannelCount;
   1279 
   1280         effect->session->apm->ProcessStream(session->procFrame);
   1281 
   1282         if (session->outBufSize < session->framesOut + session->frameCount) {
   1283             session->outBufSize = session->framesOut + session->frameCount;
   1284             session->outBuf = (int16_t *)realloc(session->outBuf,
   1285                               session->outBufSize * session->outChannelCount * sizeof(int16_t));
   1286         }
   1287 
   1288         if (session->outResampler != NULL) {
   1289             size_t frIn = session->apmFrameCount;
   1290             size_t frOut = session->frameCount;
   1291             if (session->inChannelCount == 1) {
   1292                 speex_resampler_process_int(session->outResampler,
   1293                                     0,
   1294                                     session->procFrame->_payloadData,
   1295                                     &frIn,
   1296                                     session->outBuf + session->framesOut * session->outChannelCount,
   1297                                     &frOut);
   1298             } else {
   1299                 speex_resampler_process_interleaved_int(session->outResampler,
   1300                                     session->procFrame->_payloadData,
   1301                                     &frIn,
   1302                                     session->outBuf + session->framesOut * session->outChannelCount,
   1303                                     &frOut);
   1304             }
   1305             session->framesOut += frOut;
   1306         } else {
   1307             memcpy(session->outBuf + session->framesOut * session->outChannelCount,
   1308                    session->procFrame->_payloadData,
   1309                    session->frameCount * session->outChannelCount * sizeof(int16_t));
   1310             session->framesOut += session->frameCount;
   1311         }
   1312         size_t fr = session->framesOut;
   1313         if (framesRq - framesWr < fr) {
   1314             fr = framesRq - framesWr;
   1315         }
   1316         memcpy(outBuffer->s16 + framesWr * session->outChannelCount,
   1317               session->outBuf,
   1318               fr * session->outChannelCount * sizeof(int16_t));
   1319         memcpy(session->outBuf,
   1320               session->outBuf + fr * session->outChannelCount,
   1321               (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
   1322         session->framesOut -= fr;
   1323         outBuffer->frameCount += fr;
   1324 
   1325         return 0;
   1326     } else {
   1327         return -ENODATA;
   1328     }
   1329 }
   1330 
   1331 int PreProcessingFx_Command(effect_handle_t  self,
   1332                             uint32_t            cmdCode,
   1333                             uint32_t            cmdSize,
   1334                             void                *pCmdData,
   1335                             uint32_t            *replySize,
   1336                             void                *pReplyData)
   1337 {
   1338     preproc_effect_t * effect = (preproc_effect_t *) self;
   1339     int retsize;
   1340     int status;
   1341 
   1342     if (effect == NULL){
   1343         return -EINVAL;
   1344     }
   1345 
   1346     //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
   1347 
   1348     switch (cmdCode){
   1349         case EFFECT_CMD_INIT:
   1350             if (pReplyData == NULL || *replySize != sizeof(int)){
   1351                 return -EINVAL;
   1352             }
   1353             if (effect->ops->init) {
   1354                 effect->ops->init(effect);
   1355             }
   1356             *(int *)pReplyData = 0;
   1357             break;
   1358 
   1359         case EFFECT_CMD_SET_CONFIG: {
   1360             if (pCmdData    == NULL||
   1361                 cmdSize     != sizeof(effect_config_t)||
   1362                 pReplyData  == NULL||
   1363                 *replySize  != sizeof(int)){
   1364                 ALOGV("PreProcessingFx_Command cmdCode Case: "
   1365                         "EFFECT_CMD_SET_CONFIG: ERROR");
   1366                 return -EINVAL;
   1367             }
   1368 #ifdef DUAL_MIC_TEST
   1369             // make sure that the config command is accepted by making as if all effects were
   1370             // disabled: this is OK for functional tests
   1371             uint32_t enabledMsk = effect->session->enabledMsk;
   1372             if (gDualMicEnabled) {
   1373                 effect->session->enabledMsk = 0;
   1374             }
   1375 #endif
   1376             *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData);
   1377 #ifdef DUAL_MIC_TEST
   1378             if (gDualMicEnabled) {
   1379                 effect->session->enabledMsk = enabledMsk;
   1380             }
   1381 #endif
   1382             if (*(int *)pReplyData != 0) {
   1383                 break;
   1384             }
   1385             if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
   1386                 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
   1387             }
   1388             } break;
   1389 
   1390         case EFFECT_CMD_GET_CONFIG:
   1391             if (pReplyData == NULL ||
   1392                 *replySize != sizeof(effect_config_t)) {
   1393                 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
   1394                         "EFFECT_CMD_GET_CONFIG: ERROR");
   1395                 return -EINVAL;
   1396             }
   1397 
   1398             Session_GetConfig(effect->session, (effect_config_t *)pReplyData);
   1399             break;
   1400 
   1401         case EFFECT_CMD_SET_CONFIG_REVERSE:
   1402             if (pCmdData == NULL ||
   1403                 cmdSize != sizeof(effect_config_t) ||
   1404                 pReplyData == NULL ||
   1405                 *replySize != sizeof(int)) {
   1406                 ALOGV("PreProcessingFx_Command cmdCode Case: "
   1407                         "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
   1408                 return -EINVAL;
   1409             }
   1410             *(int *)pReplyData = Session_SetReverseConfig(effect->session,
   1411                                                           (effect_config_t *)pCmdData);
   1412             if (*(int *)pReplyData != 0) {
   1413                 break;
   1414             }
   1415             break;
   1416 
   1417         case EFFECT_CMD_GET_CONFIG_REVERSE:
   1418             if (pReplyData == NULL ||
   1419                 *replySize != sizeof(effect_config_t)){
   1420                 ALOGV("PreProcessingFx_Command cmdCode Case: "
   1421                         "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
   1422                 return -EINVAL;
   1423             }
   1424             Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData);
   1425             break;
   1426 
   1427         case EFFECT_CMD_RESET:
   1428             if (effect->ops->reset) {
   1429                 effect->ops->reset(effect);
   1430             }
   1431             break;
   1432 
   1433         case EFFECT_CMD_GET_PARAM:{
   1434             if (pCmdData == NULL ||
   1435                     cmdSize < (int)sizeof(effect_param_t) ||
   1436                     pReplyData == NULL ||
   1437                     *replySize < (int)sizeof(effect_param_t)){
   1438                 ALOGV("PreProcessingFx_Command cmdCode Case: "
   1439                         "EFFECT_CMD_GET_PARAM: ERROR");
   1440                 return -EINVAL;
   1441             }
   1442             effect_param_t *p = (effect_param_t *)pCmdData;
   1443 
   1444             memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
   1445 
   1446             p = (effect_param_t *)pReplyData;
   1447 
   1448             int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
   1449 
   1450             if (effect->ops->get_parameter) {
   1451                 p->status = effect->ops->get_parameter(effect, p->data,
   1452                                                        (size_t  *)&p->vsize,
   1453                                                        p->data + voffset);
   1454                 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
   1455             }
   1456         } break;
   1457 
   1458         case EFFECT_CMD_SET_PARAM:{
   1459             if (pCmdData == NULL||
   1460                     cmdSize < (int)sizeof(effect_param_t) ||
   1461                     pReplyData == NULL ||
   1462                     *replySize != sizeof(int32_t)){
   1463                 ALOGV("PreProcessingFx_Command cmdCode Case: "
   1464                         "EFFECT_CMD_SET_PARAM: ERROR");
   1465                 return -EINVAL;
   1466             }
   1467             effect_param_t *p = (effect_param_t *) pCmdData;
   1468 
   1469             if (p->psize != sizeof(int32_t)){
   1470                 ALOGV("PreProcessingFx_Command cmdCode Case: "
   1471                         "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
   1472                 return -EINVAL;
   1473             }
   1474             if (effect->ops->set_parameter) {
   1475                 *(int *)pReplyData = effect->ops->set_parameter(effect,
   1476                                                                 (void *)p->data,
   1477                                                                 p->data + p->psize);
   1478             }
   1479         } break;
   1480 
   1481         case EFFECT_CMD_ENABLE:
   1482             if (pReplyData == NULL || *replySize != sizeof(int)){
   1483                 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
   1484                 return -EINVAL;
   1485             }
   1486             *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
   1487             break;
   1488 
   1489         case EFFECT_CMD_DISABLE:
   1490             if (pReplyData == NULL || *replySize != sizeof(int)){
   1491                 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
   1492                 return -EINVAL;
   1493             }
   1494             *(int *)pReplyData  = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
   1495             break;
   1496 
   1497         case EFFECT_CMD_SET_DEVICE:
   1498         case EFFECT_CMD_SET_INPUT_DEVICE:
   1499             if (pCmdData == NULL ||
   1500                 cmdSize != sizeof(uint32_t)) {
   1501                 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
   1502                 return -EINVAL;
   1503             }
   1504 
   1505             if (effect->ops->set_device) {
   1506                 effect->ops->set_device(effect, *(uint32_t *)pCmdData);
   1507             }
   1508             break;
   1509 
   1510         case EFFECT_CMD_SET_VOLUME:
   1511         case EFFECT_CMD_SET_AUDIO_MODE:
   1512             break;
   1513 
   1514 #ifdef DUAL_MIC_TEST
   1515         ///// test commands start
   1516         case PREPROC_CMD_DUAL_MIC_ENABLE: {
   1517             if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
   1518                     pReplyData == NULL || replySize == NULL) {
   1519                 ALOGE("PreProcessingFx_Command cmdCode Case: "
   1520                         "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
   1521                 *replySize = 0;
   1522                 return -EINVAL;
   1523             }
   1524             gDualMicEnabled = *(bool *)pCmdData;
   1525             if (gDualMicEnabled) {
   1526                 effect->aux_channels_on = sHasAuxChannels[effect->procId];
   1527             } else {
   1528                 effect->aux_channels_on = false;
   1529             }
   1530             effect->cur_channel_config = (effect->session->inChannelCount == 1) ?
   1531                     CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
   1532 
   1533             ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled");
   1534             *replySize = sizeof(int);
   1535             *(int *)pReplyData = 0;
   1536             } break;
   1537         case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: {
   1538             if (pCmdData == NULL|| pReplyData == NULL || replySize == NULL) {
   1539                 ALOGE("PreProcessingFx_Command cmdCode Case: "
   1540                         "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
   1541                 *replySize = 0;
   1542                 return -EINVAL;
   1543             }
   1544             pthread_mutex_lock(&gPcmDumpLock);
   1545             if (gPcmDumpFh != NULL) {
   1546                 fclose(gPcmDumpFh);
   1547                 gPcmDumpFh = NULL;
   1548             }
   1549             char *path = strndup((char *)pCmdData, cmdSize);
   1550             gPcmDumpFh = fopen((char *)path, "wb");
   1551             pthread_mutex_unlock(&gPcmDumpLock);
   1552             ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p",
   1553                   path, gPcmDumpFh);
   1554             ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno));
   1555             free(path);
   1556             *replySize = sizeof(int);
   1557             *(int *)pReplyData = 0;
   1558             } break;
   1559         case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: {
   1560             if (pReplyData == NULL || replySize == NULL) {
   1561                 ALOGE("PreProcessingFx_Command cmdCode Case: "
   1562                         "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
   1563                 *replySize = 0;
   1564                 return -EINVAL;
   1565             }
   1566             pthread_mutex_lock(&gPcmDumpLock);
   1567             if (gPcmDumpFh != NULL) {
   1568                 fclose(gPcmDumpFh);
   1569                 gPcmDumpFh = NULL;
   1570             }
   1571             pthread_mutex_unlock(&gPcmDumpLock);
   1572             ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP");
   1573             *replySize = sizeof(int);
   1574             *(int *)pReplyData = 0;
   1575             } break;
   1576         ///// test commands end
   1577 
   1578         case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: {
   1579             if(!gDualMicEnabled) {
   1580                 return -EINVAL;
   1581             }
   1582             if (pCmdData == NULL|| cmdSize != 2 * sizeof(uint32_t) ||
   1583                     pReplyData == NULL || replySize == NULL) {
   1584                 ALOGE("PreProcessingFx_Command cmdCode Case: "
   1585                         "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
   1586                 *replySize = 0;
   1587                 return -EINVAL;
   1588             }
   1589             if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS ||
   1590                   !effect->aux_channels_on) {
   1591                 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by"
   1592                         " fx %d", effect->procId);
   1593                 *(uint32_t *)pReplyData = -ENOSYS;
   1594                 *replySize = sizeof(uint32_t);
   1595                 break;
   1596             }
   1597             size_t num_configs = *((uint32_t *)pCmdData + 1);
   1598             if (*replySize < (2 * sizeof(uint32_t) +
   1599                               num_configs * sizeof(channel_config_t))) {
   1600                 *replySize = 0;
   1601                 return -EINVAL;
   1602             }
   1603 
   1604             *((uint32_t *)pReplyData + 1) = CHANNEL_CFG_CNT;
   1605             if (num_configs < CHANNEL_CFG_CNT ||
   1606                     *replySize < (2 * sizeof(uint32_t) +
   1607                                      CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
   1608                 *(uint32_t *)pReplyData = -ENOMEM;
   1609             } else {
   1610                 num_configs = CHANNEL_CFG_CNT;
   1611                 *(uint32_t *)pReplyData = 0;
   1612             }
   1613             ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d",
   1614                   num_configs);
   1615 
   1616             *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t);
   1617             *((uint32_t *)pReplyData + 1) = num_configs;
   1618             memcpy((uint32_t *)pReplyData + 2, &sDualMicConfigs, num_configs * sizeof(channel_config_t));
   1619             } break;
   1620         case EFFECT_CMD_GET_FEATURE_CONFIG:
   1621             if(!gDualMicEnabled) {
   1622                 return -EINVAL;
   1623             }
   1624             if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
   1625                     pReplyData == NULL || replySize == NULL ||
   1626                     *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
   1627                 ALOGE("PreProcessingFx_Command cmdCode Case: "
   1628                         "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
   1629                 return -EINVAL;
   1630             }
   1631             if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
   1632                 *(uint32_t *)pReplyData = -ENOSYS;
   1633                 *replySize = sizeof(uint32_t);
   1634                 break;
   1635             }
   1636             ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG");
   1637             *(uint32_t *)pReplyData = 0;
   1638             *replySize = sizeof(uint32_t) + sizeof(channel_config_t);
   1639             memcpy((uint32_t *)pReplyData + 1,
   1640                    &sDualMicConfigs[effect->cur_channel_config],
   1641                    sizeof(channel_config_t));
   1642             break;
   1643         case EFFECT_CMD_SET_FEATURE_CONFIG: {
   1644             ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: "
   1645                     "gDualMicEnabled %d effect->aux_channels_on %d",
   1646                   gDualMicEnabled, effect->aux_channels_on);
   1647             if(!gDualMicEnabled) {
   1648                 return -EINVAL;
   1649             }
   1650             if (pCmdData == NULL|| cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
   1651                     pReplyData == NULL || replySize == NULL ||
   1652                     *replySize < sizeof(uint32_t)) {
   1653                 ALOGE("PreProcessingFx_Command cmdCode Case: "
   1654                         "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
   1655                         "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
   1656                         pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
   1657                 return -EINVAL;
   1658             }
   1659             *replySize = sizeof(uint32_t);
   1660             if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
   1661                 *(uint32_t *)pReplyData = -ENOSYS;
   1662                 ALOGV("PreProcessingFx_Command cmdCode Case: "
   1663                                         "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
   1664                                         "CmdData %d effect->aux_channels_on %d",
   1665                                         *(uint32_t *)pCmdData, effect->aux_channels_on);
   1666                 break;
   1667             }
   1668             size_t i;
   1669             for (i = 0; i < CHANNEL_CFG_CNT;i++) {
   1670                 if (memcmp((uint32_t *)pCmdData + 1,
   1671                            &sDualMicConfigs[i], sizeof(channel_config_t)) == 0) {
   1672                     break;
   1673                 }
   1674             }
   1675             if (i == CHANNEL_CFG_CNT) {
   1676                 *(uint32_t *)pReplyData = -EINVAL;
   1677                 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config"
   1678                         "[%08x].[%08x]", *((uint32_t *)pCmdData + 1), *((uint32_t *)pCmdData + 2));
   1679             } else {
   1680                 effect->cur_channel_config = i;
   1681                 *(uint32_t *)pReplyData = 0;
   1682                 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config"
   1683                         "[%08x].[%08x]", sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
   1684             }
   1685             } break;
   1686 #endif
   1687         default:
   1688             return -EINVAL;
   1689     }
   1690     return 0;
   1691 }
   1692 
   1693 
   1694 int PreProcessingFx_GetDescriptor(effect_handle_t   self,
   1695                                   effect_descriptor_t *pDescriptor)
   1696 {
   1697     preproc_effect_t * effect = (preproc_effect_t *) self;
   1698 
   1699     if (effect == NULL || pDescriptor == NULL) {
   1700         return -EINVAL;
   1701     }
   1702 
   1703     memcpy(pDescriptor, sDescriptors[effect->procId], sizeof(effect_descriptor_t));
   1704 
   1705     return 0;
   1706 }
   1707 
   1708 int PreProcessingFx_ProcessReverse(effect_handle_t     self,
   1709                                    audio_buffer_t    *inBuffer,
   1710                                    audio_buffer_t    *outBuffer)
   1711 {
   1712     preproc_effect_t * effect = (preproc_effect_t *)self;
   1713     int    status = 0;
   1714 
   1715     if (effect == NULL){
   1716         ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
   1717         return -EINVAL;
   1718     }
   1719     preproc_session_t * session = (preproc_session_t *)effect->session;
   1720 
   1721     if (inBuffer == NULL  || inBuffer->raw == NULL){
   1722         ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
   1723         return -EINVAL;
   1724     }
   1725 
   1726     session->revProcessedMsk |= (1<<effect->procId);
   1727 
   1728 //    ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x",
   1729 //         inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
   1730 
   1731 
   1732     if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
   1733         effect->session->revProcessedMsk = 0;
   1734         if (session->revResampler != NULL) {
   1735             size_t fr = session->frameCount - session->framesRev;
   1736             if (inBuffer->frameCount < fr) {
   1737                 fr = inBuffer->frameCount;
   1738             }
   1739             if (session->revBufSize < session->framesRev + fr) {
   1740                 session->revBufSize = session->framesRev + fr;
   1741                 session->revBuf = (int16_t *)realloc(session->revBuf,
   1742                                   session->revBufSize * session->inChannelCount * sizeof(int16_t));
   1743             }
   1744             memcpy(session->revBuf + session->framesRev * session->inChannelCount,
   1745                    inBuffer->s16,
   1746                    fr * session->inChannelCount * sizeof(int16_t));
   1747 
   1748             session->framesRev += fr;
   1749             inBuffer->frameCount = fr;
   1750             if (session->framesRev < session->frameCount) {
   1751                 return 0;
   1752             }
   1753             size_t frIn = session->framesRev;
   1754             size_t frOut = session->apmFrameCount;
   1755             if (session->inChannelCount == 1) {
   1756                 speex_resampler_process_int(session->revResampler,
   1757                                             0,
   1758                                             session->revBuf,
   1759                                             &frIn,
   1760                                             session->revFrame->_payloadData,
   1761                                             &frOut);
   1762             } else {
   1763                 speex_resampler_process_interleaved_int(session->revResampler,
   1764                                                         session->revBuf,
   1765                                                         &frIn,
   1766                                                         session->revFrame->_payloadData,
   1767                                                         &frOut);
   1768             }
   1769             memcpy(session->revBuf,
   1770                    session->revBuf + frIn * session->inChannelCount,
   1771                    (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
   1772             session->framesRev -= frIn;
   1773         } else {
   1774             size_t fr = session->frameCount - session->framesRev;
   1775             if (inBuffer->frameCount < fr) {
   1776                 fr = inBuffer->frameCount;
   1777             }
   1778             memcpy(session->revFrame->_payloadData + session->framesRev * session->inChannelCount,
   1779                    inBuffer->s16,
   1780                    fr * session->inChannelCount * sizeof(int16_t));
   1781             session->framesRev += fr;
   1782             inBuffer->frameCount = fr;
   1783             if (session->framesRev < session->frameCount) {
   1784                 return 0;
   1785             }
   1786             session->framesRev = 0;
   1787         }
   1788         session->revFrame->_payloadDataLengthInSamples =
   1789                 session->apmFrameCount * session->inChannelCount;
   1790         effect->session->apm->AnalyzeReverseStream(session->revFrame);
   1791         return 0;
   1792     } else {
   1793         return -ENODATA;
   1794     }
   1795 }
   1796 
   1797 
   1798 // effect_handle_t interface implementation for effect
   1799 const struct effect_interface_s sEffectInterface = {
   1800     PreProcessingFx_Process,
   1801     PreProcessingFx_Command,
   1802     PreProcessingFx_GetDescriptor,
   1803     NULL
   1804 };
   1805 
   1806 const struct effect_interface_s sEffectInterfaceReverse = {
   1807     PreProcessingFx_Process,
   1808     PreProcessingFx_Command,
   1809     PreProcessingFx_GetDescriptor,
   1810     PreProcessingFx_ProcessReverse
   1811 };
   1812 
   1813 //------------------------------------------------------------------------------
   1814 // Effect Library Interface Implementation
   1815 //------------------------------------------------------------------------------
   1816 
   1817 int PreProcessingLib_QueryNumberEffects(uint32_t *pNumEffects)
   1818 {
   1819     if (PreProc_Init() != 0) {
   1820         return sInitStatus;
   1821     }
   1822     if (pNumEffects == NULL) {
   1823         return -EINVAL;
   1824     }
   1825     *pNumEffects = PREPROC_NUM_EFFECTS;
   1826     return sInitStatus;
   1827 }
   1828 
   1829 int PreProcessingLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
   1830 {
   1831     if (PreProc_Init() != 0) {
   1832         return sInitStatus;
   1833     }
   1834     if (index >= PREPROC_NUM_EFFECTS) {
   1835         return -EINVAL;
   1836     }
   1837     memcpy(pDescriptor, sDescriptors[index], sizeof(effect_descriptor_t));
   1838     return 0;
   1839 }
   1840 
   1841 int PreProcessingLib_Create(const effect_uuid_t *uuid,
   1842                             int32_t             sessionId,
   1843                             int32_t             ioId,
   1844                             effect_handle_t  *pInterface)
   1845 {
   1846     ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
   1847 
   1848     int status;
   1849     const effect_descriptor_t *desc;
   1850     preproc_session_t *session;
   1851     uint32_t procId;
   1852 
   1853     if (PreProc_Init() != 0) {
   1854         return sInitStatus;
   1855     }
   1856     desc =  PreProc_GetDescriptor(uuid);
   1857     if (desc == NULL) {
   1858         ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
   1859         return -EINVAL;
   1860     }
   1861     procId = UuidToProcId(&desc->type);
   1862 
   1863     session = PreProc_GetSession(procId, sessionId, ioId);
   1864     if (session == NULL) {
   1865         ALOGW("EffectCreate: no more session available");
   1866         return -EINVAL;
   1867     }
   1868 
   1869     status = Session_CreateEffect(session, procId, pInterface);
   1870 
   1871     if (status < 0 && session->createdMsk == 0) {
   1872         session->io = 0;
   1873     }
   1874     return status;
   1875 }
   1876 
   1877 int PreProcessingLib_Release(effect_handle_t interface)
   1878 {
   1879     int status;
   1880     ALOGV("EffectRelease start %p", interface);
   1881     if (PreProc_Init() != 0) {
   1882         return sInitStatus;
   1883     }
   1884 
   1885     preproc_effect_t *fx = (preproc_effect_t *)interface;
   1886 
   1887     if (fx->session->io == 0) {
   1888         return -EINVAL;
   1889     }
   1890     return Session_ReleaseEffect(fx->session, fx);
   1891 }
   1892 
   1893 int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid,
   1894                                    effect_descriptor_t *pDescriptor) {
   1895 
   1896     if (pDescriptor == NULL || uuid == NULL){
   1897         return -EINVAL;
   1898     }
   1899 
   1900     const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid);
   1901     if (desc == NULL) {
   1902         ALOGV("PreProcessingLib_GetDescriptor() not found");
   1903         return  -EINVAL;
   1904     }
   1905 
   1906     ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
   1907 
   1908     memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
   1909     return 0;
   1910 }
   1911 
   1912 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
   1913     tag : AUDIO_EFFECT_LIBRARY_TAG,
   1914     version : EFFECT_LIBRARY_API_VERSION,
   1915     name : "Audio Preprocessing Library",
   1916     implementor : "The Android Open Source Project",
   1917     query_num_effects : PreProcessingLib_QueryNumberEffects,
   1918     query_effect : PreProcessingLib_QueryEffect,
   1919     create_effect : PreProcessingLib_Create,
   1920     release_effect : PreProcessingLib_Release,
   1921     get_descriptor : PreProcessingLib_GetDescriptor
   1922 };
   1923 
   1924 }; // extern "C"
   1925