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