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