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