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