• 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     default:
535         break;
536     }
537     aec->set_routing_mode(mode);
538     return 0;
539 }
540 
541 static const preproc_ops_t sAecOps = {
542         AecCreate,
543         AecInit,
544         NULL,
545         AecEnable,
546         AecDisable,
547         AecSetParameter,
548         AecGetParameter,
549         AecSetDevice
550 };
551 
552 //------------------------------------------------------------------------------
553 // Noise Suppression (NS)
554 //------------------------------------------------------------------------------
555 
556 static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
557 
NsInit(preproc_effect_t * effect)558 int  NsInit (preproc_effect_t *effect)
559 {
560     ALOGV("NsInit");
561     webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
562     ns->set_level(kNsDefaultLevel);
563     webrtc::Config config;
564     std::vector<webrtc::Point> geometry;
565     // TODO(aluebs): Make the geometry settable.
566     geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f));
567     geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f));
568     geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f));
569     geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f));
570     // The geometry needs to be set with Beamforming enabled.
571     config.Set<webrtc::Beamforming>(
572             new webrtc::Beamforming(true, geometry));
573     effect->session->apm->SetExtraOptions(config);
574     config.Set<webrtc::Beamforming>(
575             new webrtc::Beamforming(false, geometry));
576     effect->session->apm->SetExtraOptions(config);
577     effect->type = NS_TYPE_SINGLE_CHANNEL;
578     return 0;
579 }
580 
NsCreate(preproc_effect_t * effect)581 int  NsCreate(preproc_effect_t *effect)
582 {
583     webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression();
584     ALOGV("NsCreate got ns %p", ns);
585     if (ns == NULL) {
586         ALOGW("AgcCreate Error");
587         return -ENOMEM;
588     }
589     effect->engine = static_cast<preproc_fx_handle_t>(ns);
590     NsInit (effect);
591     return 0;
592 }
593 
NsGetParameter(preproc_effect_t * effect __unused,void * pParam __unused,uint32_t * pValueSize __unused,void * pValue __unused)594 int NsGetParameter(preproc_effect_t  *effect __unused,
595                    void              *pParam __unused,
596                    uint32_t          *pValueSize __unused,
597                    void              *pValue __unused)
598 {
599     int status = 0;
600     return status;
601 }
602 
NsSetParameter(preproc_effect_t * effect,void * pParam,void * pValue)603 int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
604 {
605     int status = 0;
606     webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
607     uint32_t param = *(uint32_t *)pParam;
608     uint32_t value = *(uint32_t *)pValue;
609     switch(param) {
610         case NS_PARAM_LEVEL:
611             ns->set_level((webrtc::NoiseSuppression::Level)value);
612             ALOGV("NsSetParameter() level %d", value);
613             break;
614         case NS_PARAM_TYPE:
615         {
616             webrtc::Config config;
617             std::vector<webrtc::Point> geometry;
618             bool is_beamforming_enabled =
619                     value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled();
620             config.Set<webrtc::Beamforming>(
621                     new webrtc::Beamforming(is_beamforming_enabled, geometry));
622             effect->session->apm->SetExtraOptions(config);
623             effect->type = value;
624             ALOGV("NsSetParameter() type %d", value);
625             break;
626         }
627         default:
628             ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
629             status = -EINVAL;
630     }
631 
632     return status;
633 }
634 
NsEnable(preproc_effect_t * effect)635 void NsEnable(preproc_effect_t *effect)
636 {
637     webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
638     ALOGV("NsEnable ns %p", ns);
639     ns->Enable(true);
640     if (effect->type == NS_TYPE_MULTI_CHANNEL) {
641         webrtc::Config config;
642         std::vector<webrtc::Point> geometry;
643         config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
644         effect->session->apm->SetExtraOptions(config);
645     }
646 }
647 
NsDisable(preproc_effect_t * effect)648 void NsDisable(preproc_effect_t *effect)
649 {
650     ALOGV("NsDisable");
651     webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
652     ns->Enable(false);
653     webrtc::Config config;
654     std::vector<webrtc::Point> geometry;
655     config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
656     effect->session->apm->SetExtraOptions(config);
657 }
658 
659 static const preproc_ops_t sNsOps = {
660         NsCreate,
661         NsInit,
662         NULL,
663         NsEnable,
664         NsDisable,
665         NsSetParameter,
666         NsGetParameter,
667         NULL
668 };
669 
670 
671 static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = {
672         &sAgcOps,
673         &sAecOps,
674         &sNsOps
675 };
676 
677 
678 //------------------------------------------------------------------------------
679 // Effect functions
680 //------------------------------------------------------------------------------
681 
682 void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled);
683 
684 extern "C" const struct effect_interface_s sEffectInterface;
685 extern "C" const struct effect_interface_s sEffectInterfaceReverse;
686 
687 #define BAD_STATE_ABORT(from, to) \
688         LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
689 
Effect_SetState(preproc_effect_t * effect,uint32_t state)690 int Effect_SetState(preproc_effect_t *effect, uint32_t state)
691 {
692     int status = 0;
693     ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
694     switch(state) {
695     case PREPROC_EFFECT_STATE_INIT:
696         switch(effect->state) {
697         case PREPROC_EFFECT_STATE_ACTIVE:
698             effect->ops->disable(effect);
699             Session_SetProcEnabled(effect->session, effect->procId, false);
700         case PREPROC_EFFECT_STATE_CONFIG:
701         case PREPROC_EFFECT_STATE_CREATED:
702         case PREPROC_EFFECT_STATE_INIT:
703             break;
704         default:
705             BAD_STATE_ABORT(effect->state, state);
706         }
707         break;
708     case PREPROC_EFFECT_STATE_CREATED:
709         switch(effect->state) {
710         case PREPROC_EFFECT_STATE_INIT:
711             status = effect->ops->create(effect);
712             break;
713         case PREPROC_EFFECT_STATE_CREATED:
714         case PREPROC_EFFECT_STATE_ACTIVE:
715         case PREPROC_EFFECT_STATE_CONFIG:
716             ALOGE("Effect_SetState invalid transition");
717             status = -ENOSYS;
718             break;
719         default:
720             BAD_STATE_ABORT(effect->state, state);
721         }
722         break;
723     case PREPROC_EFFECT_STATE_CONFIG:
724         switch(effect->state) {
725         case PREPROC_EFFECT_STATE_INIT:
726             ALOGE("Effect_SetState invalid transition");
727             status = -ENOSYS;
728             break;
729         case PREPROC_EFFECT_STATE_ACTIVE:
730             effect->ops->disable(effect);
731             Session_SetProcEnabled(effect->session, effect->procId, false);
732             break;
733         case PREPROC_EFFECT_STATE_CREATED:
734         case PREPROC_EFFECT_STATE_CONFIG:
735             break;
736         default:
737             BAD_STATE_ABORT(effect->state, state);
738         }
739         break;
740     case PREPROC_EFFECT_STATE_ACTIVE:
741         switch(effect->state) {
742         case PREPROC_EFFECT_STATE_INIT:
743         case PREPROC_EFFECT_STATE_CREATED:
744             ALOGE("Effect_SetState invalid transition");
745             status = -ENOSYS;
746             break;
747         case PREPROC_EFFECT_STATE_ACTIVE:
748             // enabling an already enabled effect is just ignored
749             break;
750         case PREPROC_EFFECT_STATE_CONFIG:
751             effect->ops->enable(effect);
752             Session_SetProcEnabled(effect->session, effect->procId, true);
753             break;
754         default:
755             BAD_STATE_ABORT(effect->state, state);
756         }
757         break;
758     default:
759         BAD_STATE_ABORT(effect->state, state);
760     }
761     if (status == 0) {
762         effect->state = state;
763     }
764     return status;
765 }
766 
Effect_Init(preproc_effect_t * effect,uint32_t procId)767 int Effect_Init(preproc_effect_t *effect, uint32_t procId)
768 {
769     if (HasReverseStream(procId)) {
770         effect->itfe = &sEffectInterfaceReverse;
771     } else {
772         effect->itfe = &sEffectInterface;
773     }
774     effect->ops = sPreProcOps[procId];
775     effect->procId = procId;
776     effect->state = PREPROC_EFFECT_STATE_INIT;
777     return 0;
778 }
779 
Effect_Create(preproc_effect_t * effect,preproc_session_t * session,effect_handle_t * interface)780 int Effect_Create(preproc_effect_t *effect,
781                preproc_session_t *session,
782                effect_handle_t  *interface)
783 {
784     effect->session = session;
785     *interface = (effect_handle_t)&effect->itfe;
786     return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
787 }
788 
Effect_Release(preproc_effect_t * effect)789 int Effect_Release(preproc_effect_t *effect)
790 {
791     return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
792 }
793 
794 
795 //------------------------------------------------------------------------------
796 // Session functions
797 //------------------------------------------------------------------------------
798 
799 #define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
800 
801 static const int kPreprocDefaultSr = 16000;
802 static const int kPreProcDefaultCnl = 1;
803 
Session_Init(preproc_session_t * session)804 int Session_Init(preproc_session_t *session)
805 {
806     size_t i;
807     int status = 0;
808 
809     session->state = PREPROC_SESSION_STATE_INIT;
810     session->id = 0;
811     session->io = 0;
812     session->createdMsk = 0;
813     session->apm = NULL;
814     for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
815         status = Effect_Init(&session->effects[i], i);
816     }
817     return status;
818 }
819 
820 
Session_CreateEffect(preproc_session_t * session,int32_t procId,effect_handle_t * interface)821 extern "C" int Session_CreateEffect(preproc_session_t *session,
822                                     int32_t procId,
823                                     effect_handle_t  *interface)
824 {
825     int status = -ENOMEM;
826 
827     ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
828 
829     if (session->createdMsk == 0) {
830         session->apm = webrtc::AudioProcessing::Create();
831         if (session->apm == NULL) {
832             ALOGW("Session_CreateEffect could not get apm engine");
833             goto error;
834         }
835         const webrtc::ProcessingConfig processing_config = {
836             {{kPreprocDefaultSr, kPreProcDefaultCnl},
837              {kPreprocDefaultSr, kPreProcDefaultCnl},
838              {kPreprocDefaultSr, kPreProcDefaultCnl},
839              {kPreprocDefaultSr, kPreProcDefaultCnl}}};
840         session->apm->Initialize(processing_config);
841         session->procFrame = new webrtc::AudioFrame();
842         if (session->procFrame == NULL) {
843             ALOGW("Session_CreateEffect could not allocate audio frame");
844             goto error;
845         }
846         session->revFrame = new webrtc::AudioFrame();
847         if (session->revFrame == NULL) {
848             ALOGW("Session_CreateEffect could not allocate reverse audio frame");
849             goto error;
850         }
851         session->apmSamplingRate = kPreprocDefaultSr;
852         session->apmFrameCount = (kPreprocDefaultSr) / 100;
853         session->frameCount = session->apmFrameCount;
854         session->samplingRate = kPreprocDefaultSr;
855         session->inChannelCount = kPreProcDefaultCnl;
856         session->outChannelCount = kPreProcDefaultCnl;
857         session->procFrame->sample_rate_hz_ = kPreprocDefaultSr;
858         session->procFrame->num_channels_ = kPreProcDefaultCnl;
859         session->revChannelCount = kPreProcDefaultCnl;
860         session->revFrame->sample_rate_hz_ = kPreprocDefaultSr;
861         session->revFrame->num_channels_ = kPreProcDefaultCnl;
862         session->enabledMsk = 0;
863         session->processedMsk = 0;
864         session->revEnabledMsk = 0;
865         session->revProcessedMsk = 0;
866         session->inResampler = NULL;
867         session->inBuf = NULL;
868         session->inBufSize = 0;
869         session->outResampler = NULL;
870         session->outBuf = NULL;
871         session->outBufSize = 0;
872         session->revResampler = NULL;
873         session->revBuf = NULL;
874         session->revBufSize = 0;
875     }
876     status = Effect_Create(&session->effects[procId], session, interface);
877     if (status < 0) {
878         goto error;
879     }
880     ALOGV("Session_CreateEffect OK");
881     session->createdMsk |= (1<<procId);
882     return status;
883 
884 error:
885     if (session->createdMsk == 0) {
886         delete session->revFrame;
887         session->revFrame = NULL;
888         delete session->procFrame;
889         session->procFrame = NULL;
890         delete session->apm;
891         session->apm = NULL;
892     }
893     return status;
894 }
895 
Session_ReleaseEffect(preproc_session_t * session,preproc_effect_t * fx)896 int Session_ReleaseEffect(preproc_session_t *session,
897                           preproc_effect_t *fx)
898 {
899     ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
900     session->createdMsk &= ~(1<<fx->procId);
901     if (session->createdMsk == 0) {
902         delete session->apm;
903         session->apm = NULL;
904         delete session->procFrame;
905         session->procFrame = NULL;
906         delete session->revFrame;
907         session->revFrame = NULL;
908         if (session->inResampler != NULL) {
909             speex_resampler_destroy(session->inResampler);
910             session->inResampler = NULL;
911         }
912         if (session->outResampler != NULL) {
913             speex_resampler_destroy(session->outResampler);
914             session->outResampler = NULL;
915         }
916         if (session->revResampler != NULL) {
917             speex_resampler_destroy(session->revResampler);
918             session->revResampler = NULL;
919         }
920         delete session->inBuf;
921         session->inBuf = NULL;
922         delete session->outBuf;
923         session->outBuf = NULL;
924         delete session->revBuf;
925         session->revBuf = NULL;
926 
927         session->io = 0;
928     }
929 
930     return 0;
931 }
932 
933 
Session_SetConfig(preproc_session_t * session,effect_config_t * config)934 int Session_SetConfig(preproc_session_t *session, effect_config_t *config)
935 {
936     uint32_t sr;
937     uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
938     uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
939 
940     if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
941         config->inputCfg.format != config->outputCfg.format ||
942         config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
943         return -EINVAL;
944     }
945 
946     ALOGV("Session_SetConfig sr %d cnl %08x",
947          config->inputCfg.samplingRate, config->inputCfg.channels);
948     int status;
949 
950     // AEC implementation is limited to 16kHz
951     if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
952         session->apmSamplingRate = 32000;
953     } else
954     if (config->inputCfg.samplingRate >= 16000) {
955         session->apmSamplingRate = 16000;
956     } else if (config->inputCfg.samplingRate >= 8000) {
957         session->apmSamplingRate = 8000;
958     }
959 
960     const webrtc::ProcessingConfig processing_config = {
961       {{static_cast<int>(session->apmSamplingRate), inCnl},
962        {static_cast<int>(session->apmSamplingRate), outCnl},
963        {static_cast<int>(session->apmSamplingRate), inCnl},
964        {static_cast<int>(session->apmSamplingRate), inCnl}}};
965     status = session->apm->Initialize(processing_config);
966     if (status < 0) {
967         return -EINVAL;
968     }
969 
970     session->samplingRate = config->inputCfg.samplingRate;
971     session->apmFrameCount = session->apmSamplingRate / 100;
972     if (session->samplingRate == session->apmSamplingRate) {
973         session->frameCount = session->apmFrameCount;
974     } else {
975         session->frameCount = (session->apmFrameCount * session->samplingRate) /
976                 session->apmSamplingRate  + 1;
977     }
978     session->inChannelCount = inCnl;
979     session->outChannelCount = outCnl;
980     session->procFrame->num_channels_ = inCnl;
981     session->procFrame->sample_rate_hz_ = session->apmSamplingRate;
982 
983     session->revChannelCount = inCnl;
984     session->revFrame->num_channels_ = inCnl;
985     session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
986 
987     // force process buffer reallocation
988     session->inBufSize = 0;
989     session->outBufSize = 0;
990     session->framesIn = 0;
991     session->framesOut = 0;
992 
993 
994     if (session->inResampler != NULL) {
995         speex_resampler_destroy(session->inResampler);
996         session->inResampler = NULL;
997     }
998     if (session->outResampler != NULL) {
999         speex_resampler_destroy(session->outResampler);
1000         session->outResampler = NULL;
1001     }
1002     if (session->revResampler != NULL) {
1003         speex_resampler_destroy(session->revResampler);
1004         session->revResampler = NULL;
1005     }
1006     if (session->samplingRate != session->apmSamplingRate) {
1007         int error;
1008         session->inResampler = speex_resampler_init(session->inChannelCount,
1009                                                     session->samplingRate,
1010                                                     session->apmSamplingRate,
1011                                                     RESAMPLER_QUALITY,
1012                                                     &error);
1013         if (session->inResampler == NULL) {
1014             ALOGW("Session_SetConfig Cannot create speex resampler: %s",
1015                  speex_resampler_strerror(error));
1016             return -EINVAL;
1017         }
1018         session->outResampler = speex_resampler_init(session->outChannelCount,
1019                                                     session->apmSamplingRate,
1020                                                     session->samplingRate,
1021                                                     RESAMPLER_QUALITY,
1022                                                     &error);
1023         if (session->outResampler == NULL) {
1024             ALOGW("Session_SetConfig Cannot create speex resampler: %s",
1025                  speex_resampler_strerror(error));
1026             speex_resampler_destroy(session->inResampler);
1027             session->inResampler = NULL;
1028             return -EINVAL;
1029         }
1030         session->revResampler = speex_resampler_init(session->inChannelCount,
1031                                                     session->samplingRate,
1032                                                     session->apmSamplingRate,
1033                                                     RESAMPLER_QUALITY,
1034                                                     &error);
1035         if (session->revResampler == NULL) {
1036             ALOGW("Session_SetConfig Cannot create speex resampler: %s",
1037                  speex_resampler_strerror(error));
1038             speex_resampler_destroy(session->inResampler);
1039             session->inResampler = NULL;
1040             speex_resampler_destroy(session->outResampler);
1041             session->outResampler = NULL;
1042             return -EINVAL;
1043         }
1044     }
1045 
1046     session->state = PREPROC_SESSION_STATE_CONFIG;
1047     return 0;
1048 }
1049 
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     int free = -1;
1157     for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
1158         if (sSessions[i].io == ioId) {
1159             if (sSessions[i].createdMsk & (1 << procId)) {
1160                 return NULL;
1161             }
1162             return &sSessions[i];
1163         }
1164     }
1165     for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
1166         if (sSessions[i].io == 0) {
1167             sSessions[i].id = sessionId;
1168             sSessions[i].io = ioId;
1169             return &sSessions[i];
1170         }
1171     }
1172     return NULL;
1173 }
1174 
1175 
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     int    status = 0;
1214 
1215     if (effect == NULL){
1216         ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
1217         return -EINVAL;
1218     }
1219     preproc_session_t * session = (preproc_session_t *)effect->session;
1220 
1221     if (inBuffer == NULL  || inBuffer->raw == NULL  ||
1222             outBuffer == NULL || outBuffer->raw == NULL){
1223         ALOGW("PreProcessingFx_Process() ERROR bad pointer");
1224         return -EINVAL;
1225     }
1226 
1227     session->processedMsk |= (1<<effect->procId);
1228 
1229 //    ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
1230 //         inBuffer->frameCount, session->enabledMsk, session->processedMsk);
1231 
1232     if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
1233         effect->session->processedMsk = 0;
1234         size_t framesRq = outBuffer->frameCount;
1235         size_t framesWr = 0;
1236         if (session->framesOut) {
1237             size_t fr = session->framesOut;
1238             if (outBuffer->frameCount < fr) {
1239                 fr = outBuffer->frameCount;
1240             }
1241             memcpy(outBuffer->s16,
1242                   session->outBuf,
1243                   fr * session->outChannelCount * sizeof(int16_t));
1244             memcpy(session->outBuf,
1245                   session->outBuf + fr * session->outChannelCount,
1246                   (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
1247             session->framesOut -= fr;
1248             framesWr += fr;
1249         }
1250         outBuffer->frameCount = framesWr;
1251         if (framesWr == framesRq) {
1252             inBuffer->frameCount = 0;
1253             return 0;
1254         }
1255 
1256         if (session->inResampler != NULL) {
1257             size_t fr = session->frameCount - session->framesIn;
1258             if (inBuffer->frameCount < fr) {
1259                 fr = inBuffer->frameCount;
1260             }
1261             if (session->inBufSize < session->framesIn + fr) {
1262                 int16_t *buf;
1263                 session->inBufSize = session->framesIn + fr;
1264                 buf = (int16_t *)realloc(session->inBuf,
1265                                  session->inBufSize * session->inChannelCount * sizeof(int16_t));
1266                 if (buf == NULL) {
1267                     session->framesIn = 0;
1268                     free(session->inBuf);
1269                     session->inBuf = NULL;
1270                     return -ENOMEM;
1271                 }
1272                 session->inBuf = buf;
1273             }
1274             memcpy(session->inBuf + session->framesIn * session->inChannelCount,
1275                    inBuffer->s16,
1276                    fr * session->inChannelCount * sizeof(int16_t));
1277 #ifdef DUAL_MIC_TEST
1278             pthread_mutex_lock(&gPcmDumpLock);
1279             if (gPcmDumpFh != NULL) {
1280                 fwrite(inBuffer->raw,
1281                        fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
1282             }
1283             pthread_mutex_unlock(&gPcmDumpLock);
1284 #endif
1285 
1286             session->framesIn += fr;
1287             inBuffer->frameCount = fr;
1288             if (session->framesIn < session->frameCount) {
1289                 return 0;
1290             }
1291             spx_uint32_t frIn = session->framesIn;
1292             spx_uint32_t frOut = session->apmFrameCount;
1293             if (session->inChannelCount == 1) {
1294                 speex_resampler_process_int(session->inResampler,
1295                                             0,
1296                                             session->inBuf,
1297                                             &frIn,
1298                                             session->procFrame->data_,
1299                                             &frOut);
1300             } else {
1301                 speex_resampler_process_interleaved_int(session->inResampler,
1302                                                         session->inBuf,
1303                                                         &frIn,
1304                                                         session->procFrame->data_,
1305                                                         &frOut);
1306             }
1307             memcpy(session->inBuf,
1308                    session->inBuf + frIn * session->inChannelCount,
1309                    (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
1310             session->framesIn -= frIn;
1311         } else {
1312             size_t fr = session->frameCount - session->framesIn;
1313             if (inBuffer->frameCount < fr) {
1314                 fr = inBuffer->frameCount;
1315             }
1316             memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount,
1317                    inBuffer->s16,
1318                    fr * session->inChannelCount * sizeof(int16_t));
1319 
1320 #ifdef DUAL_MIC_TEST
1321             pthread_mutex_lock(&gPcmDumpLock);
1322             if (gPcmDumpFh != NULL) {
1323                 fwrite(inBuffer->raw,
1324                        fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
1325             }
1326             pthread_mutex_unlock(&gPcmDumpLock);
1327 #endif
1328 
1329             session->framesIn += fr;
1330             inBuffer->frameCount = fr;
1331             if (session->framesIn < session->frameCount) {
1332                 return 0;
1333             }
1334             session->framesIn = 0;
1335         }
1336         session->procFrame->samples_per_channel_ = session->apmFrameCount;
1337 
1338         effect->session->apm->ProcessStream(session->procFrame);
1339 
1340         if (session->outBufSize < session->framesOut + session->frameCount) {
1341             int16_t *buf;
1342             session->outBufSize = session->framesOut + session->frameCount;
1343             buf = (int16_t *)realloc(session->outBuf,
1344                              session->outBufSize * session->outChannelCount * sizeof(int16_t));
1345             if (buf == NULL) {
1346                 session->framesOut = 0;
1347                 free(session->outBuf);
1348                 session->outBuf = NULL;
1349                 return -ENOMEM;
1350             }
1351             session->outBuf = buf;
1352         }
1353 
1354         if (session->outResampler != NULL) {
1355             spx_uint32_t frIn = session->apmFrameCount;
1356             spx_uint32_t frOut = session->frameCount;
1357             if (session->inChannelCount == 1) {
1358                 speex_resampler_process_int(session->outResampler,
1359                                     0,
1360                                     session->procFrame->data_,
1361                                     &frIn,
1362                                     session->outBuf + session->framesOut * session->outChannelCount,
1363                                     &frOut);
1364             } else {
1365                 speex_resampler_process_interleaved_int(session->outResampler,
1366                                     session->procFrame->data_,
1367                                     &frIn,
1368                                     session->outBuf + session->framesOut * session->outChannelCount,
1369                                     &frOut);
1370             }
1371             session->framesOut += frOut;
1372         } else {
1373             memcpy(session->outBuf + session->framesOut * session->outChannelCount,
1374                    session->procFrame->data_,
1375                    session->frameCount * session->outChannelCount * sizeof(int16_t));
1376             session->framesOut += session->frameCount;
1377         }
1378         size_t fr = session->framesOut;
1379         if (framesRq - framesWr < fr) {
1380             fr = framesRq - framesWr;
1381         }
1382         memcpy(outBuffer->s16 + framesWr * session->outChannelCount,
1383               session->outBuf,
1384               fr * session->outChannelCount * sizeof(int16_t));
1385         memcpy(session->outBuf,
1386               session->outBuf + fr * session->outChannelCount,
1387               (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
1388         session->framesOut -= fr;
1389         outBuffer->frameCount += fr;
1390 
1391         return 0;
1392     } else {
1393         return -ENODATA;
1394     }
1395 }
1396 
PreProcessingFx_Command(effect_handle_t self,uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * replySize,void * pReplyData)1397 int PreProcessingFx_Command(effect_handle_t  self,
1398                             uint32_t            cmdCode,
1399                             uint32_t            cmdSize,
1400                             void                *pCmdData,
1401                             uint32_t            *replySize,
1402                             void                *pReplyData)
1403 {
1404     preproc_effect_t * effect = (preproc_effect_t *) self;
1405     int retsize;
1406     int status;
1407 
1408     if (effect == NULL){
1409         return -EINVAL;
1410     }
1411 
1412     //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
1413 
1414     switch (cmdCode){
1415         case EFFECT_CMD_INIT:
1416             if (pReplyData == NULL || *replySize != sizeof(int)){
1417                 return -EINVAL;
1418             }
1419             if (effect->ops->init) {
1420                 effect->ops->init(effect);
1421             }
1422             *(int *)pReplyData = 0;
1423             break;
1424 
1425         case EFFECT_CMD_SET_CONFIG: {
1426             if (pCmdData    == NULL||
1427                 cmdSize     != sizeof(effect_config_t)||
1428                 pReplyData  == NULL||
1429                 *replySize  != sizeof(int)){
1430                 ALOGV("PreProcessingFx_Command cmdCode Case: "
1431                         "EFFECT_CMD_SET_CONFIG: ERROR");
1432                 return -EINVAL;
1433             }
1434 #ifdef DUAL_MIC_TEST
1435             // make sure that the config command is accepted by making as if all effects were
1436             // disabled: this is OK for functional tests
1437             uint32_t enabledMsk = effect->session->enabledMsk;
1438             if (gDualMicEnabled) {
1439                 effect->session->enabledMsk = 0;
1440             }
1441 #endif
1442             *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData);
1443 #ifdef DUAL_MIC_TEST
1444             if (gDualMicEnabled) {
1445                 effect->session->enabledMsk = enabledMsk;
1446             }
1447 #endif
1448             if (*(int *)pReplyData != 0) {
1449                 break;
1450             }
1451             if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
1452                 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
1453             }
1454             } break;
1455 
1456         case EFFECT_CMD_GET_CONFIG:
1457             if (pReplyData == NULL ||
1458                 *replySize != sizeof(effect_config_t)) {
1459                 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
1460                         "EFFECT_CMD_GET_CONFIG: ERROR");
1461                 return -EINVAL;
1462             }
1463 
1464             Session_GetConfig(effect->session, (effect_config_t *)pReplyData);
1465             break;
1466 
1467         case EFFECT_CMD_SET_CONFIG_REVERSE:
1468             if (pCmdData == NULL ||
1469                 cmdSize != sizeof(effect_config_t) ||
1470                 pReplyData == NULL ||
1471                 *replySize != sizeof(int)) {
1472                 ALOGV("PreProcessingFx_Command cmdCode Case: "
1473                         "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
1474                 return -EINVAL;
1475             }
1476             *(int *)pReplyData = Session_SetReverseConfig(effect->session,
1477                                                           (effect_config_t *)pCmdData);
1478             if (*(int *)pReplyData != 0) {
1479                 break;
1480             }
1481             break;
1482 
1483         case EFFECT_CMD_GET_CONFIG_REVERSE:
1484             if (pReplyData == NULL ||
1485                 *replySize != sizeof(effect_config_t)){
1486                 ALOGV("PreProcessingFx_Command cmdCode Case: "
1487                         "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
1488                 return -EINVAL;
1489             }
1490             Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData);
1491             break;
1492 
1493         case EFFECT_CMD_RESET:
1494             if (effect->ops->reset) {
1495                 effect->ops->reset(effect);
1496             }
1497             break;
1498 
1499         case EFFECT_CMD_GET_PARAM: {
1500             effect_param_t *p = (effect_param_t *)pCmdData;
1501 
1502             if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
1503                     cmdSize < (sizeof(effect_param_t) + p->psize) ||
1504                     pReplyData == NULL || replySize == NULL ||
1505                     *replySize < (sizeof(effect_param_t) + p->psize)){
1506                 ALOGV("PreProcessingFx_Command cmdCode Case: "
1507                         "EFFECT_CMD_GET_PARAM: ERROR");
1508                 return -EINVAL;
1509             }
1510 
1511             memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
1512 
1513             p = (effect_param_t *)pReplyData;
1514 
1515             int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
1516 
1517             if (effect->ops->get_parameter) {
1518                 p->status = effect->ops->get_parameter(effect, p->data,
1519                                                        &p->vsize,
1520                                                        p->data + voffset);
1521                 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
1522             }
1523         } break;
1524 
1525         case EFFECT_CMD_SET_PARAM:{
1526             if (pCmdData == NULL||
1527                     cmdSize < sizeof(effect_param_t) ||
1528                     pReplyData == NULL || replySize == NULL ||
1529                     *replySize != sizeof(int32_t)){
1530                 ALOGV("PreProcessingFx_Command cmdCode Case: "
1531                         "EFFECT_CMD_SET_PARAM: ERROR");
1532                 return -EINVAL;
1533             }
1534             effect_param_t *p = (effect_param_t *) pCmdData;
1535 
1536             if (p->psize != sizeof(int32_t)){
1537                 ALOGV("PreProcessingFx_Command cmdCode Case: "
1538                         "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
1539                 return -EINVAL;
1540             }
1541             if (effect->ops->set_parameter) {
1542                 *(int *)pReplyData = effect->ops->set_parameter(effect,
1543                                                                 (void *)p->data,
1544                                                                 p->data + p->psize);
1545             }
1546         } break;
1547 
1548         case EFFECT_CMD_ENABLE:
1549             if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){
1550                 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
1551                 return -EINVAL;
1552             }
1553             *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
1554             break;
1555 
1556         case EFFECT_CMD_DISABLE:
1557             if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){
1558                 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
1559                 return -EINVAL;
1560             }
1561             *(int *)pReplyData  = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
1562             break;
1563 
1564         case EFFECT_CMD_SET_DEVICE:
1565         case EFFECT_CMD_SET_INPUT_DEVICE:
1566             if (pCmdData == NULL ||
1567                 cmdSize != sizeof(uint32_t)) {
1568                 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
1569                 return -EINVAL;
1570             }
1571 
1572             if (effect->ops->set_device) {
1573                 effect->ops->set_device(effect, *(uint32_t *)pCmdData);
1574             }
1575             break;
1576 
1577         case EFFECT_CMD_SET_VOLUME:
1578         case EFFECT_CMD_SET_AUDIO_MODE:
1579             break;
1580 
1581 #ifdef DUAL_MIC_TEST
1582         ///// test commands start
1583         case PREPROC_CMD_DUAL_MIC_ENABLE: {
1584             if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
1585                     pReplyData == NULL || replySize == NULL) {
1586                 ALOGE("PreProcessingFx_Command cmdCode Case: "
1587                         "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
1588                 *replySize = 0;
1589                 return -EINVAL;
1590             }
1591             gDualMicEnabled = *(bool *)pCmdData;
1592             if (gDualMicEnabled) {
1593                 effect->aux_channels_on = sHasAuxChannels[effect->procId];
1594             } else {
1595                 effect->aux_channels_on = false;
1596             }
1597             effect->cur_channel_config = (effect->session->inChannelCount == 1) ?
1598                     CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
1599 
1600             ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled");
1601             *replySize = sizeof(int);
1602             *(int *)pReplyData = 0;
1603             } break;
1604         case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: {
1605             if (pCmdData == NULL|| pReplyData == NULL || replySize == NULL) {
1606                 ALOGE("PreProcessingFx_Command cmdCode Case: "
1607                         "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
1608                 *replySize = 0;
1609                 return -EINVAL;
1610             }
1611             pthread_mutex_lock(&gPcmDumpLock);
1612             if (gPcmDumpFh != NULL) {
1613                 fclose(gPcmDumpFh);
1614                 gPcmDumpFh = NULL;
1615             }
1616             char *path = strndup((char *)pCmdData, cmdSize);
1617             gPcmDumpFh = fopen((char *)path, "wb");
1618             pthread_mutex_unlock(&gPcmDumpLock);
1619             ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p",
1620                   path, gPcmDumpFh);
1621             ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno));
1622             free(path);
1623             *replySize = sizeof(int);
1624             *(int *)pReplyData = 0;
1625             } break;
1626         case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: {
1627             if (pReplyData == NULL || replySize == NULL) {
1628                 ALOGE("PreProcessingFx_Command cmdCode Case: "
1629                         "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
1630                 *replySize = 0;
1631                 return -EINVAL;
1632             }
1633             pthread_mutex_lock(&gPcmDumpLock);
1634             if (gPcmDumpFh != NULL) {
1635                 fclose(gPcmDumpFh);
1636                 gPcmDumpFh = NULL;
1637             }
1638             pthread_mutex_unlock(&gPcmDumpLock);
1639             ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP");
1640             *replySize = sizeof(int);
1641             *(int *)pReplyData = 0;
1642             } break;
1643         ///// test commands end
1644 
1645         case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: {
1646             if(!gDualMicEnabled) {
1647                 return -EINVAL;
1648             }
1649             if (pCmdData == NULL|| cmdSize != 2 * sizeof(uint32_t) ||
1650                     pReplyData == NULL || replySize == NULL) {
1651                 ALOGE("PreProcessingFx_Command cmdCode Case: "
1652                         "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
1653                 *replySize = 0;
1654                 return -EINVAL;
1655             }
1656             if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS ||
1657                   !effect->aux_channels_on) {
1658                 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by"
1659                         " fx %d", effect->procId);
1660                 *(uint32_t *)pReplyData = -ENOSYS;
1661                 *replySize = sizeof(uint32_t);
1662                 break;
1663             }
1664             size_t num_configs = *((uint32_t *)pCmdData + 1);
1665             if (*replySize < (2 * sizeof(uint32_t) +
1666                               num_configs * sizeof(channel_config_t))) {
1667                 *replySize = 0;
1668                 return -EINVAL;
1669             }
1670 
1671             *((uint32_t *)pReplyData + 1) = CHANNEL_CFG_CNT;
1672             if (num_configs < CHANNEL_CFG_CNT ||
1673                     *replySize < (2 * sizeof(uint32_t) +
1674                                      CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
1675                 *(uint32_t *)pReplyData = -ENOMEM;
1676             } else {
1677                 num_configs = CHANNEL_CFG_CNT;
1678                 *(uint32_t *)pReplyData = 0;
1679             }
1680             ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d",
1681                   num_configs);
1682 
1683             *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t);
1684             *((uint32_t *)pReplyData + 1) = num_configs;
1685             memcpy((uint32_t *)pReplyData + 2, &sDualMicConfigs, num_configs * sizeof(channel_config_t));
1686             } break;
1687         case EFFECT_CMD_GET_FEATURE_CONFIG:
1688             if(!gDualMicEnabled) {
1689                 return -EINVAL;
1690             }
1691             if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
1692                     pReplyData == NULL || replySize == NULL ||
1693                     *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
1694                 ALOGE("PreProcessingFx_Command cmdCode Case: "
1695                         "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
1696                 return -EINVAL;
1697             }
1698             if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
1699                 *(uint32_t *)pReplyData = -ENOSYS;
1700                 *replySize = sizeof(uint32_t);
1701                 break;
1702             }
1703             ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG");
1704             *(uint32_t *)pReplyData = 0;
1705             *replySize = sizeof(uint32_t) + sizeof(channel_config_t);
1706             memcpy((uint32_t *)pReplyData + 1,
1707                    &sDualMicConfigs[effect->cur_channel_config],
1708                    sizeof(channel_config_t));
1709             break;
1710         case EFFECT_CMD_SET_FEATURE_CONFIG: {
1711             ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: "
1712                     "gDualMicEnabled %d effect->aux_channels_on %d",
1713                   gDualMicEnabled, effect->aux_channels_on);
1714             if(!gDualMicEnabled) {
1715                 return -EINVAL;
1716             }
1717             if (pCmdData == NULL|| cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
1718                     pReplyData == NULL || replySize == NULL ||
1719                     *replySize < sizeof(uint32_t)) {
1720                 ALOGE("PreProcessingFx_Command cmdCode Case: "
1721                         "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
1722                         "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
1723                         pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
1724                 return -EINVAL;
1725             }
1726             *replySize = sizeof(uint32_t);
1727             if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
1728                 *(uint32_t *)pReplyData = -ENOSYS;
1729                 ALOGV("PreProcessingFx_Command cmdCode Case: "
1730                                         "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
1731                                         "CmdData %d effect->aux_channels_on %d",
1732                                         *(uint32_t *)pCmdData, effect->aux_channels_on);
1733                 break;
1734             }
1735             size_t i;
1736             for (i = 0; i < CHANNEL_CFG_CNT;i++) {
1737                 if (memcmp((uint32_t *)pCmdData + 1,
1738                            &sDualMicConfigs[i], sizeof(channel_config_t)) == 0) {
1739                     break;
1740                 }
1741             }
1742             if (i == CHANNEL_CFG_CNT) {
1743                 *(uint32_t *)pReplyData = -EINVAL;
1744                 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config"
1745                         "[%08x].[%08x]", *((uint32_t *)pCmdData + 1), *((uint32_t *)pCmdData + 2));
1746             } else {
1747                 effect->cur_channel_config = i;
1748                 *(uint32_t *)pReplyData = 0;
1749                 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config"
1750                         "[%08x].[%08x]", sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
1751             }
1752             } break;
1753 #endif
1754         default:
1755             return -EINVAL;
1756     }
1757     return 0;
1758 }
1759 
1760 
PreProcessingFx_GetDescriptor(effect_handle_t self,effect_descriptor_t * pDescriptor)1761 int PreProcessingFx_GetDescriptor(effect_handle_t   self,
1762                                   effect_descriptor_t *pDescriptor)
1763 {
1764     preproc_effect_t * effect = (preproc_effect_t *) self;
1765 
1766     if (effect == NULL || pDescriptor == NULL) {
1767         return -EINVAL;
1768     }
1769 
1770     *pDescriptor = *sDescriptors[effect->procId];
1771 
1772     return 0;
1773 }
1774 
PreProcessingFx_ProcessReverse(effect_handle_t self,audio_buffer_t * inBuffer,audio_buffer_t * outBuffer __unused)1775 int PreProcessingFx_ProcessReverse(effect_handle_t     self,
1776                                    audio_buffer_t    *inBuffer,
1777                                    audio_buffer_t    *outBuffer __unused)
1778 {
1779     preproc_effect_t * effect = (preproc_effect_t *)self;
1780     int    status = 0;
1781 
1782     if (effect == NULL){
1783         ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
1784         return -EINVAL;
1785     }
1786     preproc_session_t * session = (preproc_session_t *)effect->session;
1787 
1788     if (inBuffer == NULL  || inBuffer->raw == NULL){
1789         ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
1790         return -EINVAL;
1791     }
1792 
1793     session->revProcessedMsk |= (1<<effect->procId);
1794 
1795 //    ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x",
1796 //         inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
1797 
1798 
1799     if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
1800         effect->session->revProcessedMsk = 0;
1801         if (session->revResampler != NULL) {
1802             size_t fr = session->frameCount - session->framesRev;
1803             if (inBuffer->frameCount < fr) {
1804                 fr = inBuffer->frameCount;
1805             }
1806             if (session->revBufSize < session->framesRev + fr) {
1807                 int16_t *buf;
1808                 session->revBufSize = session->framesRev + fr;
1809                 buf = (int16_t *)realloc(session->revBuf,
1810                                  session->revBufSize * session->inChannelCount * sizeof(int16_t));
1811                 if (buf == NULL) {
1812                     session->framesRev = 0;
1813                     free(session->revBuf);
1814                     session->revBuf = NULL;
1815                     return -ENOMEM;
1816                 }
1817                 session->revBuf = buf;
1818             }
1819             memcpy(session->revBuf + session->framesRev * session->inChannelCount,
1820                    inBuffer->s16,
1821                    fr * session->inChannelCount * sizeof(int16_t));
1822 
1823             session->framesRev += fr;
1824             inBuffer->frameCount = fr;
1825             if (session->framesRev < session->frameCount) {
1826                 return 0;
1827             }
1828             spx_uint32_t frIn = session->framesRev;
1829             spx_uint32_t frOut = session->apmFrameCount;
1830             if (session->inChannelCount == 1) {
1831                 speex_resampler_process_int(session->revResampler,
1832                                             0,
1833                                             session->revBuf,
1834                                             &frIn,
1835                                             session->revFrame->data_,
1836                                             &frOut);
1837             } else {
1838                 speex_resampler_process_interleaved_int(session->revResampler,
1839                                                         session->revBuf,
1840                                                         &frIn,
1841                                                         session->revFrame->data_,
1842                                                         &frOut);
1843             }
1844             memcpy(session->revBuf,
1845                    session->revBuf + frIn * session->inChannelCount,
1846                    (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
1847             session->framesRev -= frIn;
1848         } else {
1849             size_t fr = session->frameCount - session->framesRev;
1850             if (inBuffer->frameCount < fr) {
1851                 fr = inBuffer->frameCount;
1852             }
1853             memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount,
1854                    inBuffer->s16,
1855                    fr * session->inChannelCount * sizeof(int16_t));
1856             session->framesRev += fr;
1857             inBuffer->frameCount = fr;
1858             if (session->framesRev < session->frameCount) {
1859                 return 0;
1860             }
1861             session->framesRev = 0;
1862         }
1863         session->revFrame->samples_per_channel_ = session->apmFrameCount;
1864         effect->session->apm->AnalyzeReverseStream(session->revFrame);
1865         return 0;
1866     } else {
1867         return -ENODATA;
1868     }
1869 }
1870 
1871 
1872 // effect_handle_t interface implementation for effect
1873 const struct effect_interface_s sEffectInterface = {
1874     PreProcessingFx_Process,
1875     PreProcessingFx_Command,
1876     PreProcessingFx_GetDescriptor,
1877     NULL
1878 };
1879 
1880 const struct effect_interface_s sEffectInterfaceReverse = {
1881     PreProcessingFx_Process,
1882     PreProcessingFx_Command,
1883     PreProcessingFx_GetDescriptor,
1884     PreProcessingFx_ProcessReverse
1885 };
1886 
1887 //------------------------------------------------------------------------------
1888 // Effect Library Interface Implementation
1889 //------------------------------------------------------------------------------
1890 
PreProcessingLib_Create(const effect_uuid_t * uuid,int32_t sessionId,int32_t ioId,effect_handle_t * pInterface)1891 int PreProcessingLib_Create(const effect_uuid_t *uuid,
1892                             int32_t             sessionId,
1893                             int32_t             ioId,
1894                             effect_handle_t  *pInterface)
1895 {
1896     ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
1897 
1898     int status;
1899     const effect_descriptor_t *desc;
1900     preproc_session_t *session;
1901     uint32_t procId;
1902 
1903     if (PreProc_Init() != 0) {
1904         return sInitStatus;
1905     }
1906     desc =  PreProc_GetDescriptor(uuid);
1907     if (desc == NULL) {
1908         ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
1909         return -EINVAL;
1910     }
1911     procId = UuidToProcId(&desc->type);
1912 
1913     session = PreProc_GetSession(procId, sessionId, ioId);
1914     if (session == NULL) {
1915         ALOGW("EffectCreate: no more session available");
1916         return -EINVAL;
1917     }
1918 
1919     status = Session_CreateEffect(session, procId, pInterface);
1920 
1921     if (status < 0 && session->createdMsk == 0) {
1922         session->io = 0;
1923     }
1924     return status;
1925 }
1926 
PreProcessingLib_Release(effect_handle_t interface)1927 int PreProcessingLib_Release(effect_handle_t interface)
1928 {
1929     int status;
1930     ALOGV("EffectRelease start %p", interface);
1931     if (PreProc_Init() != 0) {
1932         return sInitStatus;
1933     }
1934 
1935     preproc_effect_t *fx = (preproc_effect_t *)interface;
1936 
1937     if (fx->session->io == 0) {
1938         return -EINVAL;
1939     }
1940     return Session_ReleaseEffect(fx->session, fx);
1941 }
1942 
PreProcessingLib_GetDescriptor(const effect_uuid_t * uuid,effect_descriptor_t * pDescriptor)1943 int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid,
1944                                    effect_descriptor_t *pDescriptor) {
1945 
1946     if (pDescriptor == NULL || uuid == NULL){
1947         return -EINVAL;
1948     }
1949 
1950     const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid);
1951     if (desc == NULL) {
1952         ALOGV("PreProcessingLib_GetDescriptor() not found");
1953         return  -EINVAL;
1954     }
1955 
1956     ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
1957 
1958     *pDescriptor = *desc;
1959     return 0;
1960 }
1961 
1962 // This is the only symbol that needs to be exported
1963 __attribute__ ((visibility ("default")))
1964 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
1965     .tag = AUDIO_EFFECT_LIBRARY_TAG,
1966     .version = EFFECT_LIBRARY_API_VERSION,
1967     .name = "Audio Preprocessing Library",
1968     .implementor = "The Android Open Source Project",
1969     .create_effect = PreProcessingLib_Create,
1970     .release_effect = PreProcessingLib_Release,
1971     .get_descriptor = PreProcessingLib_GetDescriptor
1972 };
1973 
1974 }; // extern "C"
1975