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