blob: aeb42eb4f2ba066cb83874886f64c0282384034d
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | #include <fcntl.h> |
5 | #include <malloc.h> |
6 | #include <unistd.h> |
7 | #include <pthread.h> |
8 | #include <sys/stat.h> |
9 | #include <android/log.h> |
10 | #include <sys/prctl.h> |
11 | |
12 | #include "audio_android_effect.h" |
13 | |
14 | #define msleep(x) usleep(x*1000) |
15 | |
16 | #define INVALID_EQ_FORCED_GAIN (0x7FFFFFFF) |
17 | |
18 | #define LOG_TAG "CAndroidEffect" |
19 | #include "CTvLog.h" |
20 | |
21 | using namespace android; |
22 | |
23 | // For some special cases, we want some band of the EQ to be forced to a specific |
24 | // gain. When the value in this array is not invalid, the gain of the corresponding |
25 | // band will be forced to this value. |
26 | CAndroidEffect::CAndroidEffect() |
27 | { |
28 | mplpAudioEffectSrs = NULL; |
29 | mplpAudioEffectEq = NULL; |
30 | mTrackerSessionId = 0; |
31 | } |
32 | |
33 | CAndroidEffect::~CAndroidEffect() |
34 | { |
35 | } |
36 | |
37 | static void audioEffectCallback(int32_t event, void *user, void *info) |
38 | { |
39 | LOGD("[%s:%d]", __FUNCTION__, __LINE__); |
40 | } |
41 | |
42 | void CAndroidEffect::FreeAudioEffect(AudioEffect **pEffect) |
43 | { |
44 | if ((*pEffect) != NULL) { |
45 | (*pEffect)->setEnabled(false); |
46 | delete (*pEffect); |
47 | (*pEffect) = NULL; |
48 | } |
49 | } |
50 | |
51 | void CAndroidEffect::initAudioEffect(AudioEffect **pEffect, |
52 | const effect_uuid_t *const pEffectType, |
53 | const effect_uuid_t *const pEffectUuid, int sessionId) |
54 | { |
55 | if (NULL != (*pEffect)) { |
56 | LOGE("[%s:%d] AudioEffect is not NULL. Free it first.\n", __FUNCTION__, |
57 | __LINE__); |
58 | FreeAudioEffect(pEffect); |
59 | } |
60 | |
61 | status_t status; |
62 | |
63 | (*pEffect) = new AudioEffect(); |
64 | if (NULL == (*pEffect)) { |
65 | LOGE("[%s:%d] Failed to create audio effect.\n", __FUNCTION__, |
66 | __LINE__); |
67 | goto err_exit; |
68 | } |
69 | |
70 | status = (*pEffect)->set(pEffectType, //type |
71 | pEffectUuid, //uuid |
72 | 0, //priority |
73 | audioEffectCallback, //cbf |
74 | NULL, //user |
75 | sessionId, //sessionId |
76 | 0 // default output device |
77 | ); |
78 | |
79 | if (NO_ERROR != status) { |
80 | LOGE("[%s:%d] Failed to set audio effect parameters.\n", __FUNCTION__, |
81 | __LINE__); |
82 | goto err_exit; |
83 | } |
84 | |
85 | status = (*pEffect)->initCheck(); |
86 | if (NO_ERROR != status) { |
87 | LOGE("[%s:%d] Failed to init audio effect.\n", __FUNCTION__, __LINE__); |
88 | goto err_exit; |
89 | } |
90 | |
91 | status = (*pEffect)->setEnabled(true); |
92 | if (NO_ERROR != status) { |
93 | LOGE("[%s:%d] Failed to enable audio effect.\n", __FUNCTION__, |
94 | __LINE__); |
95 | goto err_exit; |
96 | } |
97 | |
98 | return; |
99 | |
100 | err_exit: |
101 | if (NULL != (*pEffect)) { |
102 | delete (*pEffect); |
103 | (*pEffect) = NULL; |
104 | } |
105 | } |
106 | |
107 | int CAndroidEffect::setSrsParameterInt(tshd_srs_param_t param, unsigned value) |
108 | { |
109 | if (NULL == mplpAudioEffectSrs) { |
110 | return -1; |
111 | } |
112 | |
113 | status_t status; |
114 | effect_param_t *pParam = (effect_param_t *) malloc( |
115 | sizeof(effect_param_t) + sizeof(unsigned) + sizeof(unsigned)); |
116 | if (NULL == pParam) { |
117 | LOGE("[%s:%d]Failed to allocate memory!\n", __FUNCTION__, __LINE__); |
118 | return -1; |
119 | } |
120 | pParam->status = 0; |
121 | pParam->psize = sizeof(unsigned); |
122 | pParam->vsize = sizeof(unsigned); |
123 | *(unsigned *) (&pParam->data[0]) = (unsigned) param; |
124 | *(unsigned *) (&pParam->data[sizeof(unsigned)]) = value; |
125 | status = mplpAudioEffectSrs->setParameter(pParam); |
126 | if (NO_ERROR != status) { |
127 | LOGE("[%s:%d]Failed to set parameter:%d!\n", __FUNCTION__, __LINE__, |
128 | param); |
129 | free(pParam); |
130 | return -1; |
131 | } else { |
132 | free(pParam); |
133 | return 0; |
134 | } |
135 | } |
136 | |
137 | int CAndroidEffect::getSrsParameterInt(tshd_srs_param_t param, unsigned *value) |
138 | { |
139 | if (NULL == mplpAudioEffectSrs) { |
140 | return -1; |
141 | } |
142 | |
143 | status_t status; |
144 | effect_param_t *pParam = (effect_param_t *) malloc( |
145 | sizeof(effect_param_t) + sizeof(unsigned) + sizeof(unsigned)); |
146 | if (NULL == pParam) { |
147 | LOGE("[%s:%d]Failed to allocate memory!\n", __FUNCTION__, __LINE__); |
148 | return -1; |
149 | } |
150 | pParam->status = 0; |
151 | pParam->psize = sizeof(unsigned); |
152 | pParam->vsize = sizeof(unsigned); |
153 | *(unsigned *) (&pParam->data[0]) = (unsigned) param; |
154 | status = mplpAudioEffectSrs->getParameter(pParam); |
155 | if (NO_ERROR != status) { |
156 | LOGE("[%s:%d]Failed to get parameter:%d!\n", __FUNCTION__, __LINE__, |
157 | param); |
158 | *value = 0; |
159 | free(pParam); |
160 | return -1; |
161 | } else { |
162 | *value = *(unsigned *) (&pParam->data[sizeof(unsigned)]); |
163 | free(pParam); |
164 | return 0; |
165 | } |
166 | } |
167 | |
168 | int CAndroidEffect::setSrsParameterFloat(tshd_srs_param_t param, float value) |
169 | { |
170 | if (NULL == mplpAudioEffectSrs) { |
171 | return -1; |
172 | } |
173 | |
174 | status_t status; |
175 | effect_param_t *pParam = (effect_param_t *) malloc( |
176 | sizeof(effect_param_t) + sizeof(unsigned) + sizeof(float)); |
177 | if (NULL == pParam) { |
178 | LOGE("[%s:%d]Failed to allocate memory!\n", __FUNCTION__, __LINE__); |
179 | return -1; |
180 | } |
181 | pParam->status = 0; |
182 | pParam->psize = sizeof(unsigned); |
183 | pParam->vsize = sizeof(float); |
184 | *(unsigned *) (&pParam->data[0]) = (unsigned) param; |
185 | *(float *) (&pParam->data[sizeof(unsigned)]) = value; |
186 | status = mplpAudioEffectSrs->setParameter(pParam); |
187 | if (NO_ERROR != status) { |
188 | LOGE("[%s:%d]Failed to set parameter:%d!\n", __FUNCTION__, __LINE__, |
189 | param); |
190 | free(pParam); |
191 | return -1; |
192 | } else { |
193 | free(pParam); |
194 | return 0; |
195 | } |
196 | } |
197 | |
198 | int CAndroidEffect::getSrsParameterFloat(tshd_srs_param_t param, float *value) |
199 | { |
200 | if (NULL == mplpAudioEffectSrs) { |
201 | return -1; |
202 | } |
203 | |
204 | status_t status; |
205 | effect_param_t *pParam = (effect_param_t *) malloc( |
206 | sizeof(effect_param_t) + sizeof(unsigned) + sizeof(float)); |
207 | if (NULL == pParam) { |
208 | LOGE("[%s:%d]Failed to allocate memory!\n", __FUNCTION__, __LINE__); |
209 | return -1; |
210 | } |
211 | pParam->status = 0; |
212 | pParam->psize = sizeof(unsigned); |
213 | pParam->vsize = sizeof(float); |
214 | *(unsigned *) (&pParam->data[0]) = (unsigned) param; |
215 | status = mplpAudioEffectSrs->getParameter(pParam); |
216 | if (NO_ERROR != status) { |
217 | LOGE("[%s:%d]Failed to set parameter:%d!\n", __FUNCTION__, __LINE__, |
218 | param); |
219 | *value = 0.0f; |
220 | free(pParam); |
221 | return -1; |
222 | } else { |
223 | *value = *(float *) (&pParam->data[sizeof(unsigned)]); |
224 | free(pParam); |
225 | return 0; |
226 | } |
227 | } |
228 | |
229 | int CAndroidEffect::amAndroidSetSrsParameterInt(tshd_srs_param_t param, unsigned value) |
230 | { |
231 | return setSrsParameterInt(param, value); |
232 | } |
233 | |
234 | int CAndroidEffect::amAndroidGetSrsParameterInt(tshd_srs_param_t param, |
235 | unsigned *value) |
236 | { |
237 | return getSrsParameterInt(param, value); |
238 | } |
239 | |
240 | int CAndroidEffect::amAndroidSetSrsParameterFloat(tshd_srs_param_t param, float value) |
241 | { |
242 | return setSrsParameterFloat(param, value); |
243 | } |
244 | |
245 | int CAndroidEffect::amAndroidGetSrsParameterFloat(tshd_srs_param_t param, float *value) |
246 | { |
247 | return getSrsParameterFloat(param, value); |
248 | } |
249 | |
250 | int CAndroidEffect::amAndroidNewSRSAudioEffect(void) |
251 | { |
252 | if ((NULL == mplpAudioEffectSrs) && (GetAudioSRSModuleDisableCFG() == 0)) { |
253 | initAudioEffect(&mplpAudioEffectSrs, NULL, SL_IID_SRS, |
254 | mTrackerSessionId); |
255 | if (NULL == mplpAudioEffectSrs) { |
256 | LOGE("[%s:%d] Failed to create audio effect SRS!\n", __FUNCTION__, |
257 | __LINE__); |
258 | return -1; |
259 | } |
260 | } |
261 | |
262 | return 0; |
263 | } |
264 | |
265 | int CAndroidEffect::amAndroidNewEQAudioEffect(void) |
266 | { |
267 | if ((NULL == mplpAudioEffectEq) && (GetAudioEqModuleDisableCFG() == 0)) { |
268 | if (GetAudioEqUsingAndroidCFG()) { |
269 | initAudioEffect(&mplpAudioEffectEq, SL_IID_EQUALIZER, NULL, |
270 | mTrackerSessionId); |
271 | } else { |
272 | initAudioEffect(&mplpAudioEffectEq, NULL, SL_IID_HPEQ, |
273 | mTrackerSessionId); |
274 | } |
275 | |
276 | if (NULL == mplpAudioEffectEq) { |
277 | LOGE("[%s:%d] Failed to create audio effect EQ(android:%d)!\n", |
278 | __FUNCTION__, __LINE__, GetAudioEqUsingAndroidCFG()); |
279 | return -1; |
280 | } else { |
281 | // Init all forced gains to be invalid. |
282 | for (int i = 0; i < EQ_BAND_COUNT; i++) { |
283 | gEqForcedGain[i] = INVALID_EQ_FORCED_GAIN; |
284 | } |
285 | getEqGain(gEqUserSetGain, EQ_BAND_COUNT); |
286 | LOGD( |
287 | "[%s:%d] Audio effect EQ(android:%d) was created successfully!\n", |
288 | __FUNCTION__, __LINE__, GetAudioEqUsingAndroidCFG()); |
289 | } |
290 | } |
291 | |
292 | return 0; |
293 | } |
294 | |
295 | int CAndroidEffect::amAndroidNewAudioEffects(void) |
296 | { |
297 | int tmp_ret = 0; |
298 | |
299 | tmp_ret |= amAndroidNewSRSAudioEffect(); |
300 | tmp_ret |= amAndroidNewEQAudioEffect(); |
301 | |
302 | return tmp_ret; |
303 | } |
304 | |
305 | void CAndroidEffect::amAndroidFreeAudioEffects(void) |
306 | { |
307 | { |
308 | FreeAudioEffect(&mplpAudioEffectEq); |
309 | FreeAudioEffect(&mplpAudioEffectSrs); |
310 | |
311 | if (mTrackerSessionId != 0) { |
312 | AudioSystem::releaseAudioSessionId(mTrackerSessionId, -1); |
313 | mTrackerSessionId = 0; |
314 | } |
315 | } |
316 | } |
317 | |
318 | int CAndroidEffect::amAndroidGetAudioSessionId(void) |
319 | { |
320 | return mTrackerSessionId; |
321 | } |
322 | |
323 | int CAndroidEffect::amAndroidSetSRSSurroundSwitch(int switch_val) |
324 | { |
325 | return amAndroidSetSrsParameterInt(SRS_PARAM_SURROUND_ENABLE, |
326 | (unsigned) switch_val); |
327 | } |
328 | |
329 | int CAndroidEffect::amAndroidSetSRSSurroundGain(int gain_val) |
330 | { |
331 | return amAndroidSetSrsParameterFloat(SRS_PARAM_SURROUND_GAIN, |
332 | (float) gain_val / 100.0f); |
333 | } |
334 | |
335 | int CAndroidEffect::amAndroidSetSRSTrubassSwitch(int switch_val) |
336 | { |
337 | return amAndroidSetSrsParameterInt(SRS_PARAM_TRUEBASS_ENABLE, |
338 | (unsigned) switch_val); |
339 | } |
340 | |
341 | int CAndroidEffect::amAndroidSetSRSTrubassGain(int gain_val) |
342 | { |
343 | return amAndroidSetSrsParameterFloat(SRS_PARAM_TRUEBASS_GAIN, |
344 | (float) gain_val / 100.0f); |
345 | } |
346 | |
347 | int CAndroidEffect::amAndroidSetSRSDialogClaritySwitch(int switch_val) |
348 | { |
349 | return amAndroidSetSrsParameterInt(SRS_PARAM_DIALOGCLARITY_ENABLE, |
350 | (unsigned) switch_val); |
351 | } |
352 | |
353 | int CAndroidEffect::amAndroidSetSRSDialogClarityGain(int gain_val) |
354 | { |
355 | return amAndroidSetSrsParameterFloat(SRS_PARAM_DIALOGCLARTY_GAIN, |
356 | (float) gain_val / 100.0f); |
357 | } |
358 | |
359 | int CAndroidEffect::amAndroidSetSRSDefinitionGain(int gain_val) |
360 | { |
361 | return amAndroidSetSrsParameterFloat(SRS_PARAM_DEFINITION_GAIN, |
362 | (float) gain_val / 100.0f); |
363 | } |
364 | |
365 | int CAndroidEffect::amAndroidSetSRSTrubassSpeakerSize(int tmp_val) |
366 | { |
367 | int tmp_buf[8] = { 40, 60, 100, 150, 200, 250, 300, 400 }; |
368 | int set_val = 40; |
369 | |
370 | if (tmp_val >= 0 && tmp_val < sizeof(tmp_buf)) { |
371 | set_val = tmp_buf[tmp_val]; |
372 | } |
373 | |
374 | return amAndroidSetSrsParameterInt(SRS_PARAM_TRUEBASS_SPKER_SIZE, set_val); |
375 | } |
376 | |
377 | int CAndroidEffect::setEqGain(const int gain_val_buf[], int band_count) |
378 | { |
379 | if (NULL == mplpAudioEffectEq) { |
380 | LOGE("[%s:%d]\n", __FUNCTION__, __LINE__); |
381 | return -1; |
382 | } |
383 | |
384 | status_t status; |
385 | int i; |
386 | int gain; |
387 | effect_param_t *pParam; |
388 | int bAndroidEq = GetAudioEqUsingAndroidCFG(); |
389 | |
390 | if (bAndroidEq) { |
391 | pParam = (effect_param_t *) malloc( |
392 | sizeof(effect_param_t) + sizeof(int) + sizeof(int) |
393 | + sizeof(short)); |
394 | } else { |
395 | pParam = (effect_param_t *) malloc( |
396 | sizeof(effect_param_t) + sizeof(int) + sizeof(int)); |
397 | } |
398 | |
399 | if (NULL == pParam) { |
400 | LOGE("[%s:%d]Failed to allocate memory!\n", __FUNCTION__, __LINE__); |
401 | return -1; |
402 | } |
403 | |
404 | for (i = 0; i < band_count; i++) { |
405 | if (gEqForcedGain[i] != INVALID_EQ_FORCED_GAIN) { |
406 | gain = gEqForcedGain[i]; |
407 | } else { |
408 | gain = gain_val_buf[i]; |
409 | } |
410 | |
411 | if (bAndroidEq) { |
412 | pParam->status = 0; |
413 | pParam->psize = sizeof(int) * 2; |
414 | pParam->vsize = sizeof(short); |
415 | *(int *) (&pParam->data[0]) = EQ_PARAM_BAND_LEVEL; |
416 | *(int *) (&pParam->data[sizeof(int)]) = i; |
417 | *(short *) (&pParam->data[sizeof(int) * 2]) = (short) gain; |
418 | } else { |
419 | pParam->status = 0; |
420 | pParam->psize = sizeof(int); |
421 | pParam->vsize = sizeof(int); |
422 | *(int *) (&pParam->data[0]) = i; |
423 | *(int *) (&pParam->data[sizeof(int)]) = gain; |
424 | } |
425 | |
426 | status = mplpAudioEffectEq->setParameter(pParam); |
427 | if (NO_ERROR != status) { |
428 | LOGE("[%s:%d]Failed to set parameter:%d!\n", __FUNCTION__, __LINE__, |
429 | i); |
430 | free(pParam); |
431 | return -1; |
432 | } |
433 | } |
434 | |
435 | free(pParam); |
436 | return 0; |
437 | } |
438 | |
439 | int CAndroidEffect::getEqGain(int gain_val_buf[], int band_count) |
440 | { |
441 | if (NULL == mplpAudioEffectEq) { |
442 | return -1; |
443 | } |
444 | |
445 | status_t status; |
446 | effect_param_t *pParam; |
447 | int bAndroidEq = GetAudioEqUsingAndroidCFG(); |
448 | |
449 | if (bAndroidEq) { |
450 | pParam = (effect_param_t *) malloc( |
451 | sizeof(effect_param_t) + sizeof(int) + sizeof(int) |
452 | + sizeof(short)); |
453 | } else { |
454 | pParam = (effect_param_t *) malloc( |
455 | sizeof(effect_param_t) + sizeof(int) + sizeof(int)); |
456 | } |
457 | |
458 | if (NULL == pParam) { |
459 | LOGE("[%s:%d]Failed to allocate memory!\n", __FUNCTION__, __LINE__); |
460 | return -1; |
461 | } |
462 | |
463 | for (int i = 0; i < EQ_BAND_COUNT; i++) { |
464 | if (gEqForcedGain[i] != INVALID_EQ_FORCED_GAIN) { |
465 | gain_val_buf[i] = gEqUserSetGain[i]; |
466 | } else { |
467 | if (bAndroidEq) { |
468 | pParam->status = 0; |
469 | pParam->psize = sizeof(int) * 2; |
470 | pParam->vsize = sizeof(short); |
471 | *(int *) (&pParam->data[0]) = EQ_PARAM_BAND_LEVEL; |
472 | *(int *) (&pParam->data[sizeof(int)]) = i; |
473 | } else { |
474 | pParam->status = 0; |
475 | pParam->psize = sizeof(int); |
476 | pParam->vsize = sizeof(int); |
477 | *(int *) (&pParam->data[0]) = i; |
478 | } |
479 | status = mplpAudioEffectEq->getParameter(pParam); |
480 | if (NO_ERROR != status) { |
481 | LOGE("[%s:%d]Failed to set parameter:%d!\n", __FUNCTION__, |
482 | __LINE__, i); |
483 | free(pParam); |
484 | return -1; |
485 | } |
486 | |
487 | if (bAndroidEq) { |
488 | gain_val_buf[i] = *(short *) (&pParam->data[sizeof(int) * 2]); |
489 | } else { |
490 | gain_val_buf[i] = *(int *) (&pParam->data[sizeof(int)]); |
491 | } |
492 | } |
493 | } |
494 | |
495 | free(pParam); |
496 | return 0; |
497 | } |
498 | |
499 | int CAndroidEffect::amAndroidSetEQGain(const int gain_val_buf[], int band_count) |
500 | { |
501 | int i; |
502 | int gain_factor = 1; |
503 | |
504 | if (band_count > EQ_BAND_COUNT) { |
505 | band_count = EQ_BAND_COUNT; |
506 | } |
507 | |
508 | // convert dB to 100th dB for android EQ |
509 | if (GetAudioEqUsingAndroidCFG()) { |
510 | gain_factor = 100; |
511 | } |
512 | |
513 | // store the gains set by the user, and convert it to the internal representation. |
514 | for (i = 0; i < band_count; i++) { |
515 | gEqUserSetGain[i] = gain_val_buf[i] * gain_factor; |
516 | } |
517 | |
518 | return setEqGain(gEqUserSetGain, band_count); |
519 | } |
520 | |
521 | int CAndroidEffect::amAndroidGetEQGain(int gain_val_buf[], int band_count) |
522 | { |
523 | int i; |
524 | int ret; |
525 | |
526 | if (band_count > EQ_BAND_COUNT) { |
527 | band_count = EQ_BAND_COUNT; |
528 | } |
529 | |
530 | ret = getEqGain(gain_val_buf, band_count); |
531 | |
532 | // convert 100th dB to dB for android EQ |
533 | if (GetAudioEqUsingAndroidCFG()) { |
534 | for (i = 0; i < band_count; i++) { |
535 | gain_val_buf[i] /= 100; |
536 | } |
537 | } |
538 | |
539 | return ret; |
540 | } |
541 | |
542 | int CAndroidEffect::amAndroidSetEQEnable(int enabled) |
543 | { |
544 | if (NULL == mplpAudioEffectEq) { |
545 | return -1; |
546 | } |
547 | |
548 | if (NO_ERROR != mplpAudioEffectEq->setEnabled(enabled)) { |
549 | return -1; |
550 | } else { |
551 | return 0; |
552 | } |
553 | } |
554 | |
555 | int CAndroidEffect::amAndroidGetEQEnabled() |
556 | { |
557 | if (NULL == mplpAudioEffectEq) { |
558 | return 0; |
559 | } |
560 | |
561 | if (mplpAudioEffectEq->getEnabled()) { |
562 | return 1; |
563 | } else { |
564 | return 0; |
565 | } |
566 | } |
567 | |
568 | int CAndroidEffect::amAndroidForceEQGain(int band, int gain) |
569 | { |
570 | if (band >= EQ_BAND_COUNT) { |
571 | LOGE("[%s:%d] band(%d) is out of bound!\n", __FUNCTION__, __LINE__, |
572 | band); |
573 | return -1; |
574 | } else { |
575 | if (GetAudioEqUsingAndroidCFG() && (gain != INVALID_EQ_FORCED_GAIN)) { |
576 | gEqForcedGain[band] = gain * 100; |
577 | } else { |
578 | gEqForcedGain[band] = gain; |
579 | } |
580 | |
581 | // reset the EQ bands to take effect of the forced one. |
582 | if (setEqGain(gEqUserSetGain, EQ_BAND_COUNT) != 0) { |
583 | LOGE("[%s:%d]Failed to reset EQ gain!\n", __FUNCTION__, __LINE__); |
584 | return -1; |
585 | } |
586 | |
587 | LOGD("[%s:%d] band(%d) is forced to %d!\n", __FUNCTION__, __LINE__, |
588 | band, gain); |
589 | return 0; |
590 | } |
591 | } |
592 |