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