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