1 /*
2 * Copyright (C) 2012 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 <errno.h>
18 #include <fcntl.h>
19
20 #define LOG_TAG "eS305VoiceProcessing"
21 //#define LOG_NDEBUG 0
22 #include <cutils/log.h>
23
24 #include "eS305VoiceProcessing.h"
25 #include <audio_effects/effect_aec.h>
26 #include <audio_effects/effect_ns.h>
27 #include <audio_effects/effect_agc.h>
28
29 extern "C" {
30
31 //------------------------------------------------------------------------------
32 // local definitions
33 //------------------------------------------------------------------------------
34
35 // number of sessions this effect bundle can be used for
36 #define ADNC_PFX_NUM_SESSION 8
37
38 // types of pre processing modules
39 enum adnc_pfx_id
40 {
41 PFX_ID_AEC = 0, // Acoustic Echo Cancellation
42 PFX_ID_NS, // Noise Suppression
43 PFX_ID_AGC, // Automatic Gain Control
44 PFX_ID_CNT
45 };
46
47 // Session state
48 enum adnc_pfx_session_state {
49 PFX_SESSION_STATE_INIT, // initialized
50 PFX_SESSION_STATE_CONFIG // configuration received
51 };
52
53 // Effect/Preprocessor state
54 enum adnc_pfx_effect_state {
55 PFX_EFFECT_STATE_INIT, // initialized
56 PFX_EFFECT_STATE_CREATED, // effect created
57 PFX_EFFECT_STATE_CONFIG, // configuration received/disabled
58 PFX_EFFECT_STATE_ACTIVE // active/enabled
59 };
60
61 typedef struct adnc_pfx_session_s adnc_pfx_session_t;
62 typedef struct adnc_pfx_effect_s adnc_pfx_effect_t;
63 typedef struct adnc_pfx_ops_s adnc_pfx_ops_t;
64
65 // Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
66 // Function pointer can be null if no action required.
67 struct adnc_pfx_ops_s {
68 int (* create)(adnc_pfx_effect_t *fx);
69 int (* init)(adnc_pfx_effect_t *fx);
70 int (* reset)(adnc_pfx_effect_t *fx);
71 void (* enable)(adnc_pfx_effect_t *fx);
72 void (* disable)(adnc_pfx_effect_t *fx);
73 int (* set_parameter)(adnc_pfx_effect_t *fx, void *param, void *value);
74 int (* get_parameter)(adnc_pfx_effect_t *fx, void *param, size_t *size, void *value);
75 int (* set_device)(adnc_pfx_effect_t *fx, uint32_t device);
76 };
77
78 // Effect context
79 struct adnc_pfx_effect_s {
80 const struct effect_interface_s *itfe;
81 uint32_t procId; // type of pre processor (enum adnc_pfx_id)
82 uint32_t state; // current state (enum adnc_pfx_effect_state)
83 adnc_pfx_session_t *session; // session the effect is on
84 const adnc_pfx_ops_t *ops; // effect ops table
85 };
86
87 // Session context
88 struct adnc_pfx_session_s {
89 uint32_t state; // current state (enum adnc_pfx_session_state)
90 audio_source_t audioSource;
91 // FIXME not used, delete?
92 //int audioSessionId; // audio session ID
93 int ioHandle; // handle of input stream this session is on
94 uint32_t createdMsk; // bit field containing IDs of created pre processors
95 uint32_t activeMsk; // bit field containing IDs of pre processors currently active
96 struct adnc_pfx_effect_s effects[PFX_ID_CNT]; // effects in this session
97
98 // effect settings
99 // none controllable from public API here
100 };
101
102 //-----------------------------------------
103 // forward declarations
104 //-----------------------------------------
105 int Adnc_SetNoiseSuppressionInt_l(bool);
106 int Adnc_SetAutomaticGainControlInt_l(bool);
107 int Adnc_SetEchoCancellationInt_l(bool);
108 int Adnc_ReevaluateUsageInt_l(audio_io_handle_t);
109 int Adnc_SleepInt_l();
110
111 //------------------------------------------------------------------------------
112 // eS305 control
113 //------------------------------------------------------------------------------
114 #define ES305_SYSFS_PATH "/sys/class/i2c-dev/i2c-4/device/4-003e/"
115 #define ES305_VOICE_PROCESSING_PATH ES305_SYSFS_PATH "voice_processing"
116 #define ES305_PRESET_PATH ES305_SYSFS_PATH "preset"
117 #define ES305_TX_NS_LEVEL_PATH ES305_SYSFS_PATH "tx_ns_level"
118 #define ES305_TX_AGC_ENABLE_PATH ES305_SYSFS_PATH "tx_agc_enable"
119 #define ES305_AEC_ENABLE_PATH ES305_SYSFS_PATH "aec_enable"
120 #define ES305_SLEEP_PATH ES305_SYSFS_PATH "sleep"
121
122 enum eS305_controls {
123 ES305_CTRL_VOICE_PROCESSING = 0,
124 ES305_CTRL_PRESET,
125 ES305_CTRL_TX_NS_LEVEL,
126 ES305_CTRL_TX_AGC_ENABLE,
127 ES305_CTRL_AEC_ENABLE,
128 ES305_CTRL_SLEEP,
129 ES305_NUM_CTRL
130 };
131
132 struct eS305_ctrl_s {
133 int fd[ES305_NUM_CTRL];
134 int current_preset;
135 int requested_preset;
136 int ioHandle;
137 };
138 typedef struct eS305_ctrl_s eS305_ctrl_t;
139
140 static eS305_ctrl_t eS305_ctrl = {
141 { -1/*vp*/, -1/*preset*/, -1/*ns*/, -1/*agc*/, -1/*aec*/, -1/*sleep*/},
142 ES305_PRESET_OFF /*current_preset*/,
143 ES305_PRESET_INIT /*requested_preset, an invalid preset, different from current_preset*/,
144 ES305_IO_HANDLE_NONE
145 };
146
147 //------------------------------------------------------------------------------
148 // Effect descriptors
149 //------------------------------------------------------------------------------
150
151 // UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
152 // as the pre processing effects are not defined by OpenSL ES
153
154 // Acoustic Echo Cancellation
155 static const effect_descriptor_t aec_descriptor = {
156 FX_IID_AEC_, // type
157 { 0xfd90ff00, 0x0b55, 0x11e2, 0x892e, { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }, // uuid
158 EFFECT_CONTROL_API_VERSION,
159 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
160 0, //FIXME indicate CPU load
161 0, //FIXME indicate memory usage
162 "Acoustic Echo Canceler",
163 "Audience"
164 };
165
166 // Noise suppression
167 static const effect_descriptor_t ns_descriptor = {
168 FX_IID_NS_, // type
169 { 0x08fa98b0, 0x0b56, 0x11e2, 0x892e, { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }, // uuid
170 EFFECT_CONTROL_API_VERSION,
171 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
172 0, //FIXME indicate CPU load
173 0, //FIXME indicate memory usage
174 "Noise Suppression",
175 "Audience"
176 };
177
178 // Automatic Gain Control
179 static const effect_descriptor_t agc_descriptor = {
180 FX_IID_AGC_, // type
181 { 0xe9e87eb0, 0x0b55, 0x11e2, 0x892e, { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }, // 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 "Audience"
188 };
189
190 static const effect_descriptor_t *adnc_pfx_descriptors[PFX_ID_CNT] = {
191 &aec_descriptor,
192 &ns_descriptor,
193 &agc_descriptor
194 };
195
196
197 //------------------------------------------------------------------------------
198 // Helper functions
199 //------------------------------------------------------------------------------
200 static const effect_uuid_t * const sAdncUuidTable[PFX_ID_CNT] = {
201 FX_IID_AEC,
202 FX_IID_NS,
203 FX_IID_AGC
204 };
205
Adnc_ProcIdToUuid(int procId)206 const effect_uuid_t * Adnc_ProcIdToUuid(int procId)
207 {
208 if (procId >= PFX_ID_CNT) {
209 return EFFECT_UUID_NULL;
210 }
211 return sAdncUuidTable[procId];
212 }
213
Adnc_UuidToProcId(const effect_uuid_t * uuid)214 uint32_t Adnc_UuidToProcId(const effect_uuid_t * uuid)
215 {
216 size_t i;
217 for (i = 0; i < PFX_ID_CNT; i++) {
218 if (memcmp(uuid, sAdncUuidTable[i], sizeof(*uuid)) == 0) {
219 break;
220 }
221 }
222 return i;
223 }
224
225
226 //------------------------------------------------------------------------------
227 // Acoustic Echo Canceler (AEC)
228 //------------------------------------------------------------------------------
aec_init(adnc_pfx_effect_t * effect)229 int aec_init (adnc_pfx_effect_t *effect)
230 {
231 ALOGV("aec_init [noop]");
232 return 0;
233 }
234
aec_create(adnc_pfx_effect_t * effect)235 int aec_create(adnc_pfx_effect_t *effect)
236 {
237 ALOGV("aec_create [noop]");
238 return aec_init (effect);
239 }
240
aec_reset(adnc_pfx_effect_t * effect)241 int aec_reset(adnc_pfx_effect_t *effect)
242 {
243 ALOGV("aec_reset [noop]");
244 return 0;
245 }
246
aec_get_parameter(adnc_pfx_effect_t * effect,void * pParam,size_t * pValueSize,void * pValue)247 int aec_get_parameter(adnc_pfx_effect_t *effect,
248 void *pParam,
249 size_t *pValueSize,
250 void *pValue)
251 {
252 int status = 0;
253 uint32_t param = *(uint32_t *)pParam;
254
255 if (*pValueSize < sizeof(uint32_t)) {
256 return -EINVAL;
257 }
258 /* NOT SUPPORTED
259 switch (param) {
260 case AEC_PARAM_ECHO_DELAY:
261 case AEC_PARAM_PROPERTIES:
262 break;
263 default:
264 ALOGW("aec_get_parameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
265 status = -EINVAL;
266 break;
267 }
268 return status;
269 */
270 return -EINVAL;
271 }
272
aec_set_parameter(adnc_pfx_effect_t * effect,void * pParam,void * pValue)273 int aec_set_parameter (adnc_pfx_effect_t *effect, void *pParam, void *pValue)
274 {
275 int status = 0;
276 uint32_t param = *(uint32_t *)pParam;
277 uint32_t value = *(uint32_t *)pValue;
278
279 /* NOT SUPPORTED
280 switch (param) {
281 case AEC_PARAM_ECHO_DELAY:
282 case AEC_PARAM_PROPERTIES:
283 ALOGV("aec_setParameter() echo delay %d us, status %d", value, status);
284 break;
285 default:
286 ALOGW("aec_setParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
287 status = -EINVAL;
288 break;
289 }
290 */
291 return status;
292 }
293
aec_enable(adnc_pfx_effect_t * effect)294 void aec_enable(adnc_pfx_effect_t *effect)
295 {
296 ALOGV("aec_enable [noop]");
297 }
298
aec_disable(adnc_pfx_effect_t * effect)299 void aec_disable(adnc_pfx_effect_t *effect)
300 {
301 ALOGV("aec_disable [noop]");
302 }
303
aec_set_device(adnc_pfx_effect_t * effect,uint32_t device)304 int aec_set_device(adnc_pfx_effect_t *effect, uint32_t device)
305 {
306 ALOGV("aec_set_device(device=%08x) [noop]", device);
307
308 /*
309 switch(device) {
310 case AUDIO_DEVICE_OUT_EARPIECE:
311 break;
312 case AUDIO_DEVICE_OUT_SPEAKER:
313 break;
314 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
315 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
316 default:
317 break;
318 }
319 */
320
321 return 0;
322 }
323
324 static const adnc_pfx_ops_t aec_ops = {
325 aec_create,
326 aec_init,
327 aec_reset,
328 aec_enable,
329 aec_disable,
330 aec_set_parameter,
331 aec_get_parameter,
332 aec_set_device,
333 };
334
335
336 //------------------------------------------------------------------------------
337 // Noise Suppression (NS)
338 //------------------------------------------------------------------------------
ns_init(adnc_pfx_effect_t * effect)339 int ns_init (adnc_pfx_effect_t *effect)
340 {
341 ALOGV("ns_init [noop]");
342
343 return 0;
344 }
345
ns_create(adnc_pfx_effect_t * effect)346 int ns_create(adnc_pfx_effect_t *effect)
347 {
348 ALOGV("ns_create %p", effect);
349
350 return ns_init (effect);
351 }
352
ns_get_parameter(adnc_pfx_effect_t * effect,void * pParam,size_t * pValueSize,void * pValue)353 int ns_get_parameter(adnc_pfx_effect_t *effect,
354 void *pParam,
355 size_t *pValueSize,
356 void *pValue)
357 {
358 int status = 0;
359 return status;
360 }
361
ns_set_parameter(adnc_pfx_effect_t * effect,void * pParam,void * pValue)362 int ns_set_parameter(adnc_pfx_effect_t *effect, void *pParam, void *pValue)
363 {
364 int status = 0;
365 return status;
366 }
367
ns_enable(adnc_pfx_effect_t * effect)368 void ns_enable(adnc_pfx_effect_t *effect)
369 {
370 ALOGV("ns_enable [noop]");
371 }
372
ns_disable(adnc_pfx_effect_t * effect)373 void ns_disable(adnc_pfx_effect_t *effect)
374 {
375 ALOGV("ns_disable [noop]");
376 }
377
378 static const adnc_pfx_ops_t ns_ops = {
379 ns_create,
380 ns_init,
381 NULL,
382 ns_enable,
383 ns_disable,
384 ns_set_parameter,
385 ns_get_parameter,
386 NULL,
387 };
388
389
390 //------------------------------------------------------------------------------
391 // Automatic Gain Control (AGC)
392 //------------------------------------------------------------------------------
agc_init(adnc_pfx_effect_t * effect)393 int agc_init (adnc_pfx_effect_t *effect)
394 {
395 ALOGV("agc_init [noop]");
396
397 return 0;
398 }
399
agc_create(adnc_pfx_effect_t * effect)400 int agc_create(adnc_pfx_effect_t *effect)
401 {
402 ALOGV("agc_create %p", effect);
403
404 return agc_init (effect);
405 }
406
agc_get_parameter(adnc_pfx_effect_t * effect,void * pParam,size_t * pValueSize,void * pValue)407 int agc_get_parameter(adnc_pfx_effect_t *effect,
408 void *pParam,
409 size_t *pValueSize,
410 void *pValue)
411 {
412 int status = 0;
413 return status;
414 }
415
agc_set_parameter(adnc_pfx_effect_t * effect,void * pParam,void * pValue)416 int agc_set_parameter(adnc_pfx_effect_t *effect, void *pParam, void *pValue)
417 {
418 int status = 0;
419 return status;
420 }
421
agc_enable(adnc_pfx_effect_t * effect)422 void agc_enable(adnc_pfx_effect_t *effect)
423 {
424 ALOGV("agc_enable [noop]");
425 }
426
agc_disable(adnc_pfx_effect_t * effect)427 void agc_disable(adnc_pfx_effect_t *effect)
428 {
429 ALOGV("agc_disable [noop]");
430 }
431
432 static const adnc_pfx_ops_t agc_ops = {
433 agc_create,
434 agc_init,
435 NULL,
436 agc_enable,
437 agc_disable,
438 agc_set_parameter,
439 agc_get_parameter,
440 NULL,
441 };
442
443 //------------------------------------------------------------------------------
444 //
445 //------------------------------------------------------------------------------
446 static const adnc_pfx_ops_t *sPreProcOps[PFX_ID_CNT] = {
447 &aec_ops,
448 &ns_ops,
449 &agc_ops
450 };
451
452 //------------------------------------------------------------------------------
453 // Pre-processing effect functions
454 //------------------------------------------------------------------------------
455 extern const struct effect_interface_s sEffectInterface;
456
457 #define BAD_STATE_ABORT(from, to) \
458 LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
459
460 void AdncSession_SetProcEnabled(adnc_pfx_session_t *session, uint32_t procId, bool enabled);
461
AdncPreProFx_SetState(adnc_pfx_effect_t * effect,uint32_t state)462 int AdncPreProFx_SetState(adnc_pfx_effect_t *effect, uint32_t state)
463 {
464 int status = 0;
465 ALOGV("AdncPreProFx_SetState procId %d, new %d old %d", effect->procId, state, effect->state);
466 switch(state) {
467 case PFX_EFFECT_STATE_INIT:
468 switch(effect->state) {
469 case PFX_EFFECT_STATE_ACTIVE:
470 effect->ops->disable(effect);
471 AdncSession_SetProcEnabled(effect->session, effect->procId, false);
472 case PFX_EFFECT_STATE_CONFIG:
473 case PFX_EFFECT_STATE_CREATED:
474 case PFX_EFFECT_STATE_INIT:
475 break;
476 default:
477 BAD_STATE_ABORT(effect->state, state);
478 }
479 break;
480 case PFX_EFFECT_STATE_CREATED:
481 switch(effect->state) {
482 case PFX_EFFECT_STATE_INIT:
483 status = effect->ops->create(effect);
484 break;
485 case PFX_EFFECT_STATE_CREATED:
486 case PFX_EFFECT_STATE_ACTIVE:
487 case PFX_EFFECT_STATE_CONFIG:
488 ALOGE("Effect_SetState invalid transition");
489 status = -ENOSYS;
490 break;
491 default:
492 BAD_STATE_ABORT(effect->state, state);
493 }
494 break;
495 case PFX_EFFECT_STATE_CONFIG:
496 switch(effect->state) {
497 case PFX_EFFECT_STATE_INIT:
498 ALOGE("Effect_SetState invalid transition");
499 status = -ENOSYS;
500 break;
501 case PFX_EFFECT_STATE_ACTIVE:
502 effect->ops->disable(effect);
503 AdncSession_SetProcEnabled(effect->session, effect->procId, false);
504 break;
505 case PFX_EFFECT_STATE_CREATED:
506 case PFX_EFFECT_STATE_CONFIG:
507 break;
508 default:
509 BAD_STATE_ABORT(effect->state, state);
510 }
511 break;
512 case PFX_EFFECT_STATE_ACTIVE:
513 switch(effect->state) {
514 case PFX_EFFECT_STATE_INIT:
515 case PFX_EFFECT_STATE_CREATED:
516 ALOGE("Effect_SetState invalid transition");
517 status = -ENOSYS;
518 break;
519 case PFX_EFFECT_STATE_ACTIVE:
520 // enabling an already enabled effect is just ignored
521 break;
522 case PFX_EFFECT_STATE_CONFIG:
523 effect->ops->enable(effect);
524 AdncSession_SetProcEnabled(effect->session, effect->procId, true);
525 break;
526 default:
527 BAD_STATE_ABORT(effect->state, state);
528 }
529 break;
530 default:
531 BAD_STATE_ABORT(effect->state, state);
532 }
533 if (status == 0) {
534 effect->state = state;
535 }
536 return status;
537 }
538
AdncPreProFx_Init(adnc_pfx_effect_t * effect,uint32_t procId)539 int AdncPreProFx_Init(adnc_pfx_effect_t *effect, uint32_t procId)
540 {
541 ALOGV(" AdncPreProFx_Init(procId=%d)", procId);
542 effect->itfe = &sEffectInterface;
543 effect->ops = sPreProcOps[procId];
544 effect->procId = procId;
545 effect->state = PFX_EFFECT_STATE_INIT;
546 return 0;
547 }
548
AdncPreProFx_Create(adnc_pfx_effect_t * effect,adnc_pfx_session_t * session,effect_handle_t * interface)549 int AdncPreProFx_Create(adnc_pfx_effect_t *effect,
550 adnc_pfx_session_t *session,
551 effect_handle_t *interface)
552 {
553 ALOGV(" AdncPreProFx_Create(effect=%p)", effect);
554 effect->session = session;
555 *interface = (effect_handle_t)&effect->itfe;
556 return AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_CREATED);
557 }
558
AdncPreProFx_Release(adnc_pfx_effect_t * effect)559 int AdncPreProFx_Release(adnc_pfx_effect_t *effect)
560 {
561 return AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_INIT);
562 }
563
564
565 //------------------------------------------------------------------------------
566 // Session functions
567 //------------------------------------------------------------------------------
568 /*
569 * Initialize a session context.
570 * Must be called with a lock on sAdncBundleLock.
571 */
AdncSession_Init_l(adnc_pfx_session_t * session)572 int AdncSession_Init_l(adnc_pfx_session_t *session)
573 {
574 ALOGV("AdncSession_Init()");
575 size_t i;
576 int status = 0;
577
578 session->state = PFX_SESSION_STATE_INIT;
579 session->audioSource = AUDIO_SOURCE_DEFAULT;
580 //session->audioSessionId = ES305_SESSION_ID_NONE; // FIXME not used delete?
581 session->ioHandle = ES305_IO_HANDLE_NONE;
582 session->createdMsk = 0;
583 session->activeMsk = 0;
584 // initialize each effect for this session context
585 for (i = 0; i < PFX_ID_CNT && status == 0; i++) {
586 status = AdncPreProFx_Init(&session->effects[i], i);
587 }
588 return status;
589 }
590
591 /*
592 * Must be called with a lock on sAdncBundleLock.
593 */
AdncSession_CreateEffect_l(adnc_pfx_session_t * session,int32_t procId,effect_handle_t * interface)594 int AdncSession_CreateEffect_l(adnc_pfx_session_t *session,
595 int32_t procId,
596 effect_handle_t *interface)
597 {
598 int status = -ENOMEM;
599 ALOGV("AdncSession_CreateEffect handle=%d procId %d, old createdMsk %08x",
600 session->ioHandle, procId, session->createdMsk);
601
602 status = AdncPreProFx_Create(&session->effects[procId], session, interface);
603 if (status >= 0) {
604 ALOGV(" AdncSession_CreateEffect OK");
605 session->createdMsk |= (1 << procId);
606 }
607 return status;
608 }
609
AdncSession_SetConfig(adnc_pfx_session_t * session,effect_config_t * config)610 int AdncSession_SetConfig(adnc_pfx_session_t *session, effect_config_t *config)
611 {
612 ALOGV("AdncSession_SetConfig [noop]");
613 return 0;
614 }
615
AdncSession_GetConfig(adnc_pfx_session_t * session,effect_config_t * config)616 void AdncSession_GetConfig(adnc_pfx_session_t *session, effect_config_t *config)
617 {
618 ALOGV("AdncSession_GetConfig [noop]");
619 }
620
AdncSession_SetReverseConfig(adnc_pfx_session_t * session,effect_config_t * config)621 int AdncSession_SetReverseConfig(adnc_pfx_session_t *session, effect_config_t *config)
622 {
623 ALOGV("AdncSession_SetReverseConfig [noop]");
624 return 0;
625 }
626
AdncSession_GetReverseConfig(adnc_pfx_session_t * session,effect_config_t * config)627 void AdncSession_GetReverseConfig(adnc_pfx_session_t *session, effect_config_t *config)
628 {
629 ALOGV("AdncSession_GetReverseConfig [noop]");
630 }
631
AdncSession_SetProcEnabled(adnc_pfx_session_t * session,uint32_t procId,bool enabled)632 void AdncSession_SetProcEnabled(adnc_pfx_session_t *session, uint32_t procId, bool enabled)
633 {
634 ALOGV("AdncSession_SetProcEnabled [noop] proc %d, enabled %d", procId, enabled);
635 //no need to reevaluate session settings, if recording is currently ongoing, we'll reevaluate
636 // through eS305_AddEffect()
637 }
638
AdncSession_SetSource(adnc_pfx_session_t * session,audio_source_t source)639 int AdncSession_SetSource(adnc_pfx_session_t *session, audio_source_t source)
640 {
641 session->audioSource = source;
642 return 0;
643 }
644
645 //------------------------------------------------------------------------------
646 // Bundle functions
647 //------------------------------------------------------------------------------
648 #define ADNC_BUNDLE_NO_INIT 1
649 static int sAdncBundleInitStatus = ADNC_BUNDLE_NO_INIT;
650 static adnc_pfx_session_t sAdncSessions[ADNC_PFX_NUM_SESSION];
651 static pthread_mutex_t sAdncBundleLock;
652
653 /* Returns a session context for the given IO handle
654 * Returns an existing session context if the IO handle matches, initializes a new one otherwise.
655 * Returns NULL if no more session contexts are available
656 * Must be called with a lock on sAdncBundleLock
657 */
AdncBundle_GetSession_l(int32_t procId,int32_t sessionId,int32_t ioId)658 adnc_pfx_session_t *AdncBundle_GetSession_l(int32_t procId, int32_t sessionId, int32_t ioId)
659 {
660 size_t i;
661 for (i = 0; i < ADNC_PFX_NUM_SESSION; i++) {
662 if (sAdncSessions[i].ioHandle == ioId) {
663 return &sAdncSessions[i];
664 }
665 }
666 for (i = 0; i < ADNC_PFX_NUM_SESSION; i++) {
667 if (sAdncSessions[i].ioHandle == ES305_IO_HANDLE_NONE) {
668 //sAdncSessions[i].audioSessionId = sessionId; // FIXME not used delete?
669 sAdncSessions[i].ioHandle = ioId;
670 return &sAdncSessions[i];
671 }
672 }
673 ALOGV("AdncBundle_GetSession_l");
674 return NULL;
675 }
676
677 /*
678 * Must be called with a lock on sAdncBundleLock.
679 */
AdncBundle_Init_l()680 int AdncBundle_Init_l() {
681 size_t i;
682 int status = 0;
683
684 if (sAdncBundleInitStatus <= 0) {
685 return sAdncBundleInitStatus;
686 }
687 // initialize all the session contexts that this bundle supports
688 for (i = 0; i < ADNC_PFX_NUM_SESSION && status == 0; i++) {
689 status = AdncSession_Init_l(&sAdncSessions[i]);
690 }
691 sAdncBundleInitStatus = status;
692 return sAdncBundleInitStatus;
693 }
694
695 /*
696 * Must be called with a lock on sAdncBundleLock.
697 */
AdncBundle_Release_l()698 int AdncBundle_Release_l() {
699 ALOGV("AdncBundle_Release_l()");
700
701 Adnc_SleepInt_l();
702
703 for (int i = 0 ; i < ES305_NUM_CTRL ; i++) {
704 if (eS305_ctrl.fd[i] >= 0) {
705 close(eS305_ctrl.fd[i]);
706 }
707 eS305_ctrl.fd[i] = -1;
708 }
709 return 0;
710 }
711
AdncBundle_GetDescriptor(const effect_uuid_t * uuid)712 const effect_descriptor_t *AdncBundle_GetDescriptor(const effect_uuid_t *uuid)
713 {
714 size_t i;
715 for (i = 0; i < PFX_ID_CNT; i++) {
716 if (memcmp(&adnc_pfx_descriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
717 return adnc_pfx_descriptors[i];
718 }
719 }
720 return NULL;
721 }
722
723 /*
724 * Debug only: display session contexts
725 */
AdncBundle_logv_dumpSessions()726 void AdncBundle_logv_dumpSessions() {
727 ALOGV("Sessions:");
728 for (int i=0 ; i<ADNC_PFX_NUM_SESSION ; i++) {
729 ALOGV(" session %d handle=%d cre=%2x act=%2x",
730 i, sAdncSessions[i].ioHandle, sAdncSessions[i].createdMsk, sAdncSessions[i].activeMsk);
731 }
732 }
733
734 //------------------------------------------------------------------------------
735 // Effect Control Interface Implementation
736 //------------------------------------------------------------------------------
AdncVoiceProcessingFx_Command(effect_handle_t self,uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * replySize,void * pReplyData)737 int AdncVoiceProcessingFx_Command(effect_handle_t self,
738 uint32_t cmdCode,
739 uint32_t cmdSize,
740 void *pCmdData,
741 uint32_t *replySize,
742 void *pReplyData)
743 {
744 adnc_pfx_effect_t * effect = (adnc_pfx_effect_t *) self;
745 int retsize;
746 int status;
747
748 if (effect == NULL){
749 return -EINVAL;
750 }
751
752 ALOGV("AdncVoiceProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
753
754 switch (cmdCode){
755 case EFFECT_CMD_INIT:
756 if (pReplyData == NULL || *replySize != sizeof(int)){
757 return -EINVAL;
758 }
759 if (effect->ops->init) {
760 effect->ops->init(effect);
761 }
762 *(int *)pReplyData = 0;
763 break;
764
765 case EFFECT_CMD_SET_CONFIG: {
766 if (pCmdData == NULL||
767 cmdSize != sizeof(effect_config_t)||
768 pReplyData == NULL||
769 *replySize != sizeof(int)){
770 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
771 "EFFECT_CMD_SET_CONFIG: ERROR");
772 return -EINVAL;
773 }
774
775 *(int *)pReplyData = AdncSession_SetConfig(effect->session, (effect_config_t *)pCmdData);
776
777 if (*(int *)pReplyData != 0) {
778 break;
779 }
780 if (effect->state != PFX_EFFECT_STATE_ACTIVE) {
781 *(int *)pReplyData = AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_CONFIG);
782 }
783 } break;
784
785 case EFFECT_CMD_GET_CONFIG:
786 if (pReplyData == NULL ||
787 *replySize != sizeof(effect_config_t)) {
788 ALOGV("\tLVM_ERROR : AdncVoiceProcessingFx_Command cmdCode Case: "
789 "EFFECT_CMD_GET_CONFIG: ERROR");
790 return -EINVAL;
791 }
792
793 AdncSession_GetConfig(effect->session, (effect_config_t *)pReplyData);
794 break;
795
796 case EFFECT_CMD_SET_CONFIG_REVERSE:
797 if (pCmdData == NULL ||
798 cmdSize != sizeof(effect_config_t) ||
799 pReplyData == NULL ||
800 *replySize != sizeof(int)) {
801 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
802 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
803 return -EINVAL;
804 }
805 *(int *)pReplyData = AdncSession_SetReverseConfig(effect->session,
806 (effect_config_t *)pCmdData);
807 if (*(int *)pReplyData != 0) {
808 break;
809 }
810 break;
811
812 case EFFECT_CMD_GET_CONFIG_REVERSE:
813 if (pReplyData == NULL ||
814 *replySize != sizeof(effect_config_t)){
815 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
816 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
817 return -EINVAL;
818 }
819 AdncSession_GetReverseConfig(effect->session, (effect_config_t *)pCmdData);
820 break;
821
822 case EFFECT_CMD_RESET:
823 if (effect->ops->reset) {
824 effect->ops->reset(effect);
825 }
826 break;
827
828 case EFFECT_CMD_GET_PARAM:{
829 if (pCmdData == NULL ||
830 cmdSize < (int)sizeof(effect_param_t) ||
831 pReplyData == NULL ||
832 *replySize < (int)sizeof(effect_param_t)){
833 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
834 "EFFECT_CMD_GET_PARAM: ERROR");
835 return -EINVAL;
836 }
837 effect_param_t *p = (effect_param_t *)pCmdData;
838
839 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
840
841 p = (effect_param_t *)pReplyData;
842
843 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
844
845 if (effect->ops->get_parameter) {
846 p->status = effect->ops->get_parameter(effect, p->data,
847 (size_t *)&p->vsize,
848 p->data + voffset);
849 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
850 }
851 } break;
852
853 case EFFECT_CMD_SET_PARAM:{
854 if (pCmdData == NULL||
855 cmdSize < (int)sizeof(effect_param_t) ||
856 pReplyData == NULL ||
857 *replySize != sizeof(int32_t)){
858 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
859 "EFFECT_CMD_SET_PARAM: ERROR");
860 return -EINVAL;
861 }
862 effect_param_t *p = (effect_param_t *) pCmdData;
863
864 if (p->psize != sizeof(int32_t)){
865 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
866 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
867 return -EINVAL;
868 }
869 if (effect->ops->set_parameter) {
870 *(int *)pReplyData = effect->ops->set_parameter(effect,
871 (void *)p->data,
872 p->data + p->psize);
873 }
874 } break;
875
876 case EFFECT_CMD_ENABLE:
877 if (pReplyData == NULL || *replySize != sizeof(int)){
878 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
879 return -EINVAL;
880 }
881 *(int *)pReplyData = AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_ACTIVE);
882 break;
883
884 case EFFECT_CMD_DISABLE:
885 if (pReplyData == NULL || *replySize != sizeof(int)){
886 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
887 return -EINVAL;
888 }
889 *(int *)pReplyData = AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_CONFIG);
890 break;
891
892 case EFFECT_CMD_SET_DEVICE:
893 case EFFECT_CMD_SET_INPUT_DEVICE:
894 if (pCmdData == NULL ||
895 cmdSize != sizeof(uint32_t)) {
896 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
897 return -EINVAL;
898 }
899
900 if (effect->ops->set_device) {
901 effect->ops->set_device(effect, *(uint32_t *)pCmdData);
902 }
903 break;
904
905 case EFFECT_CMD_SET_VOLUME:
906 case EFFECT_CMD_SET_AUDIO_MODE:
907 case EFFECT_CMD_SET_FEATURE_CONFIG:
908 break;
909
910 case EFFECT_CMD_SET_AUDIO_SOURCE:
911 if (pCmdData == NULL ||
912 cmdSize != sizeof(uint32_t)) {
913 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_AUDIO_SOURCE: ERROR");
914 return -EINVAL;
915 }
916 return AdncSession_SetSource(effect->session, (audio_source_t) *(uint32_t *)pCmdData);
917 break;
918
919 default:
920 return -EINVAL;
921 }
922 return 0;
923 }
924
925
AdncVoiceProcessingFx_GetDescriptor(effect_handle_t self,effect_descriptor_t * pDescriptor)926 int AdncVoiceProcessingFx_GetDescriptor(effect_handle_t self,
927 effect_descriptor_t *pDescriptor)
928 {
929 adnc_pfx_effect_t * effect = (adnc_pfx_effect_t *) self;
930
931 if (effect == NULL || pDescriptor == NULL) {
932 return -EINVAL;
933 }
934
935 memcpy(pDescriptor, adnc_pfx_descriptors[effect->procId], sizeof(effect_descriptor_t));
936
937 return 0;
938 }
939
940
941 // effect_handle_t interface implementation for effect
942 const struct effect_interface_s sEffectInterface = {
943 NULL, /* Process */
944 AdncVoiceProcessingFx_Command,
945 AdncVoiceProcessingFx_GetDescriptor,
946 NULL
947 };
948 //------------------------------------------------------------------------------
949 // Effect Library Interface Implementation
950 //------------------------------------------------------------------------------
adnc_query_number_effects(uint32_t * pNumEffects)951 int adnc_query_number_effects(uint32_t *pNumEffects)
952 {
953 if (pNumEffects == NULL) {
954 return -EINVAL;
955 }
956 *pNumEffects = PFX_ID_CNT;
957 return sAdncBundleInitStatus;
958 }
959
adnc_query_effect(uint32_t index,effect_descriptor_t * pDescriptor)960 int adnc_query_effect(uint32_t index, effect_descriptor_t *pDescriptor)
961 {
962 int status = 0;
963
964 pthread_mutex_lock(&sAdncBundleLock);
965
966 if (AdncBundle_Init_l() != 0) {
967 status = sAdncBundleInitStatus;
968 goto exit;
969 }
970 if (index >= PFX_ID_CNT) {
971 status = -EINVAL;
972 goto exit;
973 }
974 memcpy(pDescriptor, adnc_pfx_descriptors[index], sizeof(effect_descriptor_t));
975
976 exit:
977 pthread_mutex_unlock(&sAdncBundleLock);
978 return status;
979 }
980
adnc_create(const effect_uuid_t * uuid,int32_t sessionId,int32_t ioId,effect_handle_t * pInterface)981 int adnc_create(const effect_uuid_t *uuid,
982 int32_t sessionId,
983 int32_t ioId,
984 effect_handle_t *pInterface)
985 {
986 ALOGV("adnc_create: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
987
988 int status = 0;
989 const effect_descriptor_t *desc;
990 adnc_pfx_session_t *session;
991 uint32_t procId;
992
993 pthread_mutex_lock(&sAdncBundleLock);
994
995 if (AdncBundle_Init_l() != 0) {
996 status = sAdncBundleInitStatus;
997 goto exit;
998 }
999
1000 desc = AdncBundle_GetDescriptor(uuid);
1001 if (desc == NULL) {
1002 ALOGW(" adnc_create: fx not found uuid: %08x", uuid->timeLow);
1003 status = -EINVAL;
1004 goto exit;
1005 }
1006 procId = Adnc_UuidToProcId(&desc->type);
1007
1008 session = AdncBundle_GetSession_l(procId, sessionId, ioId);
1009 if (session == NULL) {
1010 ALOGW(" adnc_create: no more session available");
1011 status = -EINVAL;
1012 goto exit;
1013 }
1014
1015 status = AdncSession_CreateEffect_l(session, procId, pInterface);
1016
1017 if (status < 0 && session->createdMsk == 0) {
1018 session->ioHandle = ES305_IO_HANDLE_NONE;
1019 }
1020
1021 exit:
1022 pthread_mutex_unlock(&sAdncBundleLock);
1023 return status;
1024 }
1025
adnc_release(effect_handle_t interface)1026 int adnc_release(effect_handle_t interface)
1027 {
1028 int i, status = 0;
1029 ALOGV("adnc_release %p", interface);
1030
1031 // the effect handle comes from the effect framework, ok to cast
1032 const adnc_pfx_effect_t * fx = (adnc_pfx_effect_t *) interface;
1033
1034 const uint32_t removalMsk = ~(1 << fx->procId);
1035
1036 pthread_mutex_lock(&sAdncBundleLock);
1037
1038 if (AdncBundle_Init_l() != 0) {
1039 status = sAdncBundleInitStatus;
1040 goto exit;
1041 }
1042
1043 if (fx->session->ioHandle == 0) {
1044 status = -EINVAL;
1045 goto exit;
1046 }
1047
1048 // effect is released, flag it as inactive and not created
1049 fx->session->createdMsk &= removalMsk;
1050 fx->session->activeMsk &= removalMsk;
1051
1052 // configuration has changed, reevaluate
1053 status = Adnc_ReevaluateUsageInt_l(fx->session->ioHandle);
1054 // not checking the return status here: if there was an error,
1055 // we still need to free the session and wouldn't exit here
1056
1057 // free session if it has no more effects
1058 if (fx->session->createdMsk == 0) {
1059 ALOGV(" resetting session on handle %d after effect release", fx->session->ioHandle);
1060 const int statusInit = AdncSession_Init_l(fx->session);
1061 if (status == 0) {
1062 status = statusInit;
1063 }
1064 }
1065
1066 exit:
1067 pthread_mutex_unlock(&sAdncBundleLock);
1068 return status;
1069 }
1070
adnc_get_descriptor(const effect_uuid_t * uuid,effect_descriptor_t * pDescriptor)1071 int adnc_get_descriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) {
1072 if (pDescriptor == NULL || uuid == NULL){
1073 ALOGV("adnc_get_descriptor() invalid params");
1074 return -EINVAL;
1075 }
1076
1077 const effect_descriptor_t *desc = AdncBundle_GetDescriptor(uuid);
1078 if (desc == NULL) {
1079 ALOGV("adnc_get_descriptor() not found");
1080 return -EINVAL;
1081 }
1082
1083 ALOGV("adnc_get_descriptor() got fx %s", desc->name);
1084
1085 memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
1086 return 0;
1087 }
1088
1089 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
1090 tag : AUDIO_EFFECT_LIBRARY_TAG,
1091 version : EFFECT_LIBRARY_API_VERSION,
1092 name : "Audience Voice Preprocessing Library",
1093 implementor : "The Android Open Source Project",
1094 query_num_effects : adnc_query_number_effects,
1095 query_effect : adnc_query_effect,
1096 create_effect : adnc_create,
1097 release_effect : adnc_release,
1098 get_descriptor : adnc_get_descriptor
1099 };
1100
1101 //-------------------------------------------------------
1102 // eS305 control interface
1103 //-------------------------------------------------------
Adnc_SetAutomaticGainControlInt_l(bool agc_on)1104 int Adnc_SetAutomaticGainControlInt_l(bool agc_on)
1105 {
1106 ALOGV("Adnc_SetAutomaticGainControlInt_l(%d)", agc_on);
1107
1108 if (eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] < 0) {
1109 ALOGV(" opening eS305 path for agc");
1110 eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] = open(ES305_TX_AGC_ENABLE_PATH, O_RDWR);
1111 if (eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] < 0) {
1112 ALOGE(" Cannot open eS305 path for agc: %s", strerror(errno));
1113 return -ENODEV;
1114 }
1115 }
1116
1117 if (agc_on) {
1118 write(eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE], ES305_AGC_ON, strlen(ES305_AGC_ON));
1119 } else {
1120 write(eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE], ES305_AEC_OFF, strlen(ES305_AGC_OFF));
1121 }
1122 return 0;
1123 }
1124
Adnc_SetEchoCancellationInt_l(bool aec_on)1125 int Adnc_SetEchoCancellationInt_l(bool aec_on)
1126 {
1127 ALOGV("Adnc_SetEchoCancellationInt_l(%d)", aec_on);
1128
1129 if (eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] < 0) {
1130 ALOGV(" opening eS305 path for aec");
1131 eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] = open(ES305_AEC_ENABLE_PATH, O_RDWR);
1132 if (eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] < 0) {
1133 ALOGE(" Cannot open eS305 path for aec: %s", strerror(errno));
1134 return -ENODEV;
1135 }
1136 }
1137
1138 if (aec_on) {
1139 write(eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE], ES305_AEC_ON, strlen(ES305_AEC_ON));
1140 } else {
1141 write(eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE], ES305_AEC_OFF, strlen(ES305_AEC_OFF));
1142 }
1143 return 0;
1144 }
1145
Adnc_SetNoiseSuppressionInt_l(bool ns_on)1146 int Adnc_SetNoiseSuppressionInt_l(bool ns_on)
1147 {
1148 ALOGV("Adnc_SetNoiseSuppressionInt(%d)", ns_on);
1149
1150 if (eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] < 0) {
1151 ALOGV(" opening eS305 path for ns");
1152 eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] = open(ES305_TX_NS_LEVEL_PATH, O_RDWR);
1153 if (eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] < 0) {
1154 ALOGE(" Cannot open eS305 path for ns: %s", strerror(errno));
1155 return -ENODEV;
1156 }
1157 }
1158
1159 if (ns_on) {
1160 if (eS305_ctrl.requested_preset == ES305_PRESET_ASRA_HANDHELD) {
1161 ALOGV(" setting ns to %s", ES305_NS_VOICE_REC_HANDHELD_ON);
1162 write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL],
1163 ES305_NS_VOICE_REC_HANDHELD_ON, strlen(ES305_NS_VOICE_REC_HANDHELD_ON));
1164 } else if ((eS305_ctrl.requested_preset == ES305_PRESET_ASRA_DESKTOP)
1165 || (eS305_ctrl.requested_preset == ES305_PRESET_ASRA_HEADSET)) {
1166 ALOGV(" setting ns to %s", ES305_NS_VOICE_REC_SINGLE_MIC_ON);
1167 write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL],
1168 ES305_NS_VOICE_REC_SINGLE_MIC_ON, strlen(ES305_NS_VOICE_REC_SINGLE_MIC_ON));
1169 } else {
1170 ALOGV(" setting ns to %s", ES305_NS_DEFAULT_ON);
1171 write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL],
1172 ES305_NS_DEFAULT_ON, strlen(ES305_NS_DEFAULT_ON));
1173 }
1174 } else {
1175 ALOGV(" setting ns to %s", ES305_NS_OFF);
1176 write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL], ES305_NS_OFF, strlen(ES305_NS_OFF));
1177 }
1178 return 0;
1179 }
1180
Adnc_SetVoiceProcessingInt_l(bool vp_on)1181 int Adnc_SetVoiceProcessingInt_l(bool vp_on)
1182 {
1183 if (eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] < 0) {
1184 ALOGV(" opening eS305 path for VP");
1185 eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] = open(ES305_VOICE_PROCESSING_PATH, O_RDWR);
1186 if (eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] < 0) {
1187 ALOGE(" cannot open eS305 path for VP: %s", strerror(errno));
1188 return -ENODEV;
1189 }
1190 }
1191 if (vp_on) {
1192 write(eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING], ES305_ON, strlen(ES305_ON));
1193 } else {
1194 write(eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING], ES305_OFF, strlen(ES305_OFF));
1195 }
1196 return 0;
1197 }
1198
1199 /*
1200 * Put the eS305 to sleep
1201 * Post condition when no error: eS305_ctrl.current_preset == ES305_PRESET_OFF
1202 */
Adnc_SleepInt_l()1203 int Adnc_SleepInt_l()
1204 {
1205 if (eS305_ctrl.current_preset == ES305_PRESET_OFF) {
1206 return 0;
1207 }
1208
1209 ALOGV(" Adnc_SleepInt()_l setting VP off + sleep 1");
1210
1211 Adnc_SetVoiceProcessingInt_l(false /*vp_on*/);
1212
1213 ALOGV(" Adnc_SetSleepInt_l");
1214 if (eS305_ctrl.fd[ES305_CTRL_SLEEP] < 0) {
1215 ALOGV(" opening eS305 path for sleep");
1216 eS305_ctrl.fd[ES305_CTRL_SLEEP] = open(ES305_SLEEP_PATH, O_RDWR);
1217 if (eS305_ctrl.fd[ES305_CTRL_SLEEP] < 0) {
1218 ALOGE(" cannot open eS305 path for sleep: %s", strerror(errno));
1219 return -ENODEV;
1220 }
1221 }
1222
1223 write(eS305_ctrl.fd[ES305_CTRL_SLEEP], ES305_ON, strlen(ES305_ON));
1224
1225 eS305_ctrl.current_preset = ES305_PRESET_OFF;
1226
1227 return 0;
1228 }
1229
1230 /*
1231 * Apply the eS305_ctrl.requested_preset preset after turning VP on
1232 * Post condition when no error: eS305_ctrl.current_preset == eS305_ctrl.requested_preset
1233 */
Adnc_ApplyPresetInt_l()1234 int Adnc_ApplyPresetInt_l()
1235 {
1236 ALOGV("Adnc_ApplyPresetInt() current_preset=%d, requested_preset=%d",
1237 eS305_ctrl.current_preset, eS305_ctrl.requested_preset);
1238
1239 if (eS305_ctrl.requested_preset == eS305_ctrl.current_preset) {
1240 ALOGV(" nothing to do, preset %d is current", eS305_ctrl.requested_preset);
1241 return 0;
1242 }
1243
1244 // preset off implies going to sleep
1245 if (eS305_ctrl.requested_preset == ES305_PRESET_OFF) {
1246 return Adnc_SleepInt_l();
1247 }
1248
1249 // voice processing must be on before setting the preset
1250 if ((eS305_ctrl.current_preset == ES305_PRESET_OFF)
1251 || (eS305_ctrl.current_preset == ES305_PRESET_INIT)) {
1252 const int status = Adnc_SetVoiceProcessingInt_l(true /*vp_on*/);
1253 if (status != 0) {
1254 return status;
1255 }
1256 }
1257
1258 if (eS305_ctrl.fd[ES305_CTRL_PRESET] < 0) {
1259 ALOGV(" opening eS305 path for PRESET");
1260 eS305_ctrl.fd[ES305_CTRL_PRESET] = open(ES305_PRESET_PATH, O_RDWR);
1261 }
1262 if (eS305_ctrl.fd[ES305_CTRL_PRESET] < 0) {
1263 ALOGE(" Cannot open eS305 path for PRESET: %s", strerror(errno));
1264 return -ENODEV;
1265 }
1266
1267 char str[8];
1268 sprintf(str, "%d", eS305_ctrl.requested_preset);
1269 write(eS305_ctrl.fd[ES305_CTRL_PRESET], str, strlen(str));
1270
1271 eS305_ctrl.current_preset = eS305_ctrl.requested_preset;
1272
1273 return 0;
1274 }
1275
1276
1277 /*
1278 * Apply the settings of given the session context
1279 */
Adnc_ApplySettingsFromSessionContextInt_l(adnc_pfx_session_t * session)1280 int Adnc_ApplySettingsFromSessionContextInt_l(adnc_pfx_session_t * session)
1281 {
1282 ALOGV("Adnc_ApplySettingsFromSessionContextInt_l cre=%2x ac=%2x handle=%d",
1283 session->createdMsk, session->activeMsk, session->ioHandle);
1284 int status = 0;
1285
1286 if (session->ioHandle != eS305_ctrl.ioHandle) {
1287 return status;
1288 }
1289
1290 // NS: special case of noise suppression, always reset according to effect state
1291 // as default desirable value might differ from the preset
1292 const bool ns_on = ((session->activeMsk & (1 << PFX_ID_NS)) != 0);
1293 status = Adnc_SetNoiseSuppressionInt_l(ns_on /*ns_on*/);
1294
1295 // AEC
1296 if ((session->createdMsk & (1 << PFX_ID_AEC)) /* the effect has been created */
1297 && (session->activeMsk & (1 << PFX_ID_AEC))) /* the effect is active */
1298 {
1299 Adnc_SetEchoCancellationInt_l(true /*aec_on*/);
1300 }
1301
1302 // AGC
1303 if ((session->createdMsk & (1 << PFX_ID_AGC)) /* the effect has been created */
1304 && (session->activeMsk & (1 << PFX_ID_AGC))) /* the effect is active */
1305 {
1306 Adnc_SetAutomaticGainControlInt_l(true /*agc_on*/);
1307 }
1308
1309 return status;
1310 }
1311
1312 /*
1313 * Return a value between 0 and ADNC_PFX_NUM_SESSION-1 if a session context has the given handle,
1314 * -1 if the handle isn't in handled by one of the sessions.
1315 * Must be called with a lock on sAdncBundleLock
1316 */
Adnc_SessionNumberForHandle_l(audio_io_handle_t handle)1317 int Adnc_SessionNumberForHandle_l(audio_io_handle_t handle)
1318 {
1319 for (int i = 0 ; i < ADNC_PFX_NUM_SESSION ; i++) {
1320 if (sAdncSessions[i].ioHandle == handle) {
1321 return i;
1322 }
1323 }
1324 return -1;
1325 }
1326
1327
1328 /*
1329 * Apply the settings of the session matching the given IO handle.
1330 * Must be called with a lock on sAdncBundleLock
1331 */
Adnc_ApplySettingsForHandleInt_l(audio_io_handle_t handle)1332 int Adnc_ApplySettingsForHandleInt_l(audio_io_handle_t handle)
1333 {
1334 ALOGV(" Adnc_ApplySettingsForHandleInt_l(handle=%d)", handle);
1335 // indicates whether this effect bundle currently has a session context for this IO handle
1336 bool hasSession = false;
1337 int status = 0;
1338 int i;
1339
1340 if (sAdncBundleInitStatus != 0) {
1341 // This assumes that the default config of the eS305 after setting a preset
1342 // is the correct configuration.
1343 ALOGV(" no effect settings to apply for IO handle %d, no effect bundle", handle);
1344 return status;
1345 }
1346
1347 const int sessionId = Adnc_SessionNumberForHandle_l(handle);
1348 if (sessionId >= 0) {
1349 ALOGV(" applying settings from session num %d", sessionId);
1350 status = Adnc_ApplySettingsFromSessionContextInt_l( &sAdncSessions[sessionId] );
1351 }
1352 else {
1353 ALOGV(" no session found for handle %d", handle);
1354 }
1355
1356 return status;
1357 }
1358
1359 /*
1360 * Reevaluate the usage of the eS305 based on the given IO handle.
1361 * Must be called with a lock on sAdncBundleLock
1362 */
Adnc_ReevaluateUsageInt_l(audio_io_handle_t handle)1363 int Adnc_ReevaluateUsageInt_l(audio_io_handle_t handle)
1364 {
1365 ALOGV(" Adnc_ReevaluateUsageInt_l(handle=%d) current_preset=%d requested_preset=%d",
1366 handle, eS305_ctrl.current_preset, eS305_ctrl.requested_preset);
1367 int status = 0;
1368 if ((eS305_ctrl.requested_preset == ES305_PRESET_OFF) || (handle == ES305_IO_HANDLE_NONE)) {
1369 status = Adnc_SleepInt_l();
1370 } else {
1371 const int sessionId = Adnc_SessionNumberForHandle_l(handle);
1372 if (sessionId >= 0) {
1373 // recording active, use the preset only if there is an effect,
1374 // reset preset to off otherwise
1375 if (sAdncSessions[sessionId].activeMsk != 0) {
1376 status = Adnc_ApplyPresetInt_l();
1377 if (status == 0) {
1378 //apply the settings of the session associated with the handle (if any)
1379 status = Adnc_ApplySettingsForHandleInt_l(handle);
1380 }
1381 } else {
1382 status = Adnc_SleepInt_l();
1383 }
1384 }
1385 }
1386 return status;
1387 }
1388
1389
1390 //-------------------------------------------------------
1391 // eS305 public control interface from HAL
1392 //-------------------------------------------------------
eS305_UsePreset(int preset)1393 int eS305_UsePreset(int preset)
1394 {
1395 ALOGV("eS305_UsePreset(%d) current=%d handle=%d",
1396 preset, eS305_ctrl.current_preset, eS305_ctrl.ioHandle);
1397
1398 int status = 0;
1399
1400 pthread_mutex_lock(&sAdncBundleLock);
1401
1402 //if (preset != -1) { AdncBundle_logv_dumpSessions(); }
1403
1404 // allow preset transition from any preset to any other during recording,
1405 // except from one ASRA preset to another
1406 if (eS305_ctrl.ioHandle != ES305_IO_HANDLE_NONE) {
1407 switch(eS305_ctrl.current_preset) {
1408 case ES305_PRESET_ASRA_HANDHELD:
1409 case ES305_PRESET_ASRA_DESKTOP:
1410 case ES305_PRESET_ASRA_HEADSET:
1411 switch(preset) {
1412 case ES305_PRESET_ASRA_HANDHELD:
1413 case ES305_PRESET_ASRA_DESKTOP:
1414 case ES305_PRESET_ASRA_HEADSET:
1415 ALOGV(" not switching from ASRA preset %d to %d during voice recognition",
1416 eS305_ctrl.current_preset, preset);
1417 status = -EINVAL;
1418 goto exit;
1419 default:
1420 // transitioning from ASRA to non-ASRA: valid
1421 break;
1422 }
1423 break;
1424 default:
1425 // transitioning from non-ASRA: valid
1426 break;
1427 }
1428 }
1429
1430 eS305_ctrl.requested_preset = preset;
1431
1432 status = AdncBundle_Init_l();
1433 if (status != 0) {
1434 ALOGE(" error applying preset, bundle failed to initialize");
1435 goto exit;
1436 }
1437
1438 status = Adnc_ReevaluateUsageInt_l(eS305_ctrl.ioHandle);
1439
1440 exit:
1441 pthread_mutex_unlock(&sAdncBundleLock);
1442 return status;
1443 }
1444
1445
eS305_SetActiveIoHandle(audio_io_handle_t handle)1446 int eS305_SetActiveIoHandle(audio_io_handle_t handle)
1447 {
1448 ALOGV("eS305_SetActiveIoHandle(%d)", handle);
1449
1450 pthread_mutex_lock(&sAdncBundleLock);
1451
1452 int status = AdncBundle_Init_l();
1453 if (status != 0) {
1454 ALOGE(" error setting active handle, bundle failed to initialize");
1455 pthread_mutex_unlock(&sAdncBundleLock);
1456 return status;
1457 }
1458
1459 status = Adnc_ReevaluateUsageInt_l(handle);
1460
1461 if (status == 0) {
1462 eS305_ctrl.ioHandle = handle;
1463 } else {
1464 ALOGE(" failed to update for new handle %d (current preset = %d)",
1465 handle, eS305_ctrl.current_preset);
1466 }
1467
1468 pthread_mutex_unlock(&sAdncBundleLock);
1469
1470 return status;
1471 }
1472
1473
eS305_AddEffect(effect_descriptor_t * descr,audio_io_handle_t handle)1474 int eS305_AddEffect(effect_descriptor_t * descr, audio_io_handle_t handle)
1475 {
1476 ALOGV("eS305_AddEffect(handle=%d)", handle);
1477
1478 pthread_mutex_lock(&sAdncBundleLock);
1479
1480 int status = AdncBundle_Init_l();
1481 if (status != 0) {
1482 ALOGE(" error setting adding effect, bundle failed to initialize");
1483 pthread_mutex_unlock(&sAdncBundleLock);
1484 return status;
1485 }
1486
1487 if (descr == NULL){
1488 ALOGV(" eS305_AddEffect() ERROR effect descriptor is NULL");
1489 pthread_mutex_unlock(&sAdncBundleLock);
1490 return -EINVAL;
1491 }
1492
1493 uint32_t procId = Adnc_UuidToProcId(&descr->type);
1494
1495 adnc_pfx_session_t * session = AdncBundle_GetSession_l(
1496 procId, ES305_SESSION_ID_NONE, handle/*ioId*/);
1497
1498 if (session != NULL) {
1499 // mark the effect as active
1500 session->activeMsk |= (1 << procId);
1501
1502 // update settings if necessary
1503 Adnc_ReevaluateUsageInt_l(session->ioHandle);
1504 }
1505
1506 pthread_mutex_unlock(&sAdncBundleLock);
1507
1508 return status;
1509 }
1510
1511
eS305_RemoveEffect(effect_descriptor_t * descr,audio_io_handle_t handle)1512 int eS305_RemoveEffect(effect_descriptor_t * descr, audio_io_handle_t handle)
1513 {
1514 ALOGV("eS305_RemoveEffect()");
1515
1516 pthread_mutex_lock(&sAdncBundleLock);
1517
1518 int status = AdncBundle_Init_l();
1519 if (status != 0) {
1520 ALOGE(" error setting removing effect, bundle failed to initialize");
1521 pthread_mutex_unlock(&sAdncBundleLock);
1522 return status;
1523 }
1524
1525 if (descr == NULL){
1526 ALOGV(" eS305_AddEffect() ERROR effect descriptor is NULL");
1527 pthread_mutex_unlock(&sAdncBundleLock);
1528 return -EINVAL;
1529 }
1530
1531 uint32_t procId = Adnc_UuidToProcId(&descr->type);
1532
1533 adnc_pfx_session_t * session = AdncBundle_GetSession_l(
1534 procId, ES305_SESSION_ID_NONE, handle/*ioId*/);
1535
1536 if (session != NULL) {
1537 // mark the effect as inactive
1538 session->activeMsk &= ~(1 << procId);
1539
1540 // update settings if necessary
1541 Adnc_ReevaluateUsageInt_l(session->ioHandle);
1542 }
1543
1544 pthread_mutex_unlock(&sAdncBundleLock);
1545
1546 return status;
1547 }
1548
1549
eS305_Release()1550 int eS305_Release() {
1551 ALOGV("eS305_Release()");
1552
1553 pthread_mutex_lock(&sAdncBundleLock);
1554
1555 AdncBundle_Release_l();
1556
1557 pthread_mutex_unlock(&sAdncBundleLock);
1558
1559 return 0;
1560 }
1561
1562 } // extern "C"
1563