1 /*
2 * Copyright (C) 2014 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 /* Automatic Gain Control implementation */
18 #include "sles_allinclusive.h"
19
20 #include <media/EffectsFactoryApi.h>
21
22 #include <audio_effects/effect_agc.h>
23
24 /**
25 * returns true if this interface is not associated with an initialized AGC effect
26 */
NO_AUTOGAIN(IAndroidAutomaticGainControl * v)27 static inline bool NO_AUTOGAIN(IAndroidAutomaticGainControl* v) {
28 return (v->mAGCEffect == 0);
29 }
30
IAndroidAutomaticGainControl_SetEnabled(SLAndroidAutomaticGainControlItf self,SLboolean enabled)31 SLresult IAndroidAutomaticGainControl_SetEnabled(SLAndroidAutomaticGainControlItf self, SLboolean enabled)
32 {
33 SL_ENTER_INTERFACE
34
35 IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
36 interface_lock_exclusive(thiz);
37 thiz->mEnabled = (SLboolean) enabled;
38 if (NO_AUTOGAIN(thiz)) {
39 result = SL_RESULT_CONTROL_LOST;
40 } else {
41 android::status_t status = thiz->mAGCEffect->setEnabled((bool) thiz->mEnabled);
42 result = android_fx_statusToResult(status);
43 }
44 interface_unlock_exclusive(thiz);
45
46 SL_LEAVE_INTERFACE
47 }
48
IAndroidAutomaticGainControl_IsEnabled(SLAndroidAutomaticGainControlItf self,SLboolean * pEnabled)49 SLresult IAndroidAutomaticGainControl_IsEnabled(SLAndroidAutomaticGainControlItf self, SLboolean *pEnabled)
50 {
51 SL_ENTER_INTERFACE
52
53 if (NULL == pEnabled) {
54 result = SL_RESULT_PARAMETER_INVALID;
55 } else {
56 IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
57 interface_lock_exclusive(thiz);
58 SLboolean enabled = thiz->mEnabled;
59 if (NO_AUTOGAIN(thiz)) {
60 result = SL_RESULT_CONTROL_LOST;
61 } else {
62 *pEnabled = (SLboolean) thiz->mAGCEffect->getEnabled();
63 result = SL_RESULT_SUCCESS;
64 }
65 interface_unlock_exclusive(thiz);
66 }
67 SL_LEAVE_INTERFACE
68 }
69
IAndroidAutomaticGainControl_IsAvailable(SLAndroidAutomaticGainControlItf self,SLboolean * pEnabled)70 SLresult IAndroidAutomaticGainControl_IsAvailable(SLAndroidAutomaticGainControlItf self,
71 SLboolean *pEnabled)
72 {
73 SL_ENTER_INTERFACE
74
75 *pEnabled = false;
76
77 uint32_t numEffects = 0;
78 int ret = EffectQueryNumberEffects(&numEffects);
79 if (ret != 0) {
80 ALOGE("IAndroidAutomaticGainControl_IsAvailable() error %d querying number of effects",
81 ret);
82 result = SL_RESULT_FEATURE_UNSUPPORTED;
83 } else {
84 ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
85
86 effect_descriptor_t fxDesc;
87 for (uint32_t i = 0 ; i < numEffects ; i++) {
88 if (EffectQueryEffect(i, &fxDesc) == 0) {
89 ALOGV("effect %d is called %s", i, fxDesc.name);
90 if (memcmp(&fxDesc.type, SL_IID_ANDROIDAUTOMATICGAINCONTROL,
91 sizeof(effect_uuid_t)) == 0) {
92 ALOGI("found effect \"%s\" from %s", fxDesc.name, fxDesc.implementor);
93 *pEnabled = true;
94 break;
95 }
96 }
97 }
98 result = SL_RESULT_SUCCESS;
99 }
100 SL_LEAVE_INTERFACE
101 }
102
103 static const struct SLAndroidAutomaticGainControlItf_ IAndroidAutomaticGainControl_Itf = {
104 IAndroidAutomaticGainControl_SetEnabled,
105 IAndroidAutomaticGainControl_IsEnabled,
106 IAndroidAutomaticGainControl_IsAvailable
107 };
108
IAndroidAutomaticGainControl_init(void * self)109 void IAndroidAutomaticGainControl_init(void *self)
110 {
111 IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
112 thiz->mItf = &IAndroidAutomaticGainControl_Itf;
113 thiz->mEnabled = SL_BOOLEAN_FALSE;
114 memset(&thiz->mAGCDescriptor, 0, sizeof(effect_descriptor_t));
115 // placement new (explicit constructor)
116 (void) new (&thiz->mAGCEffect) android::sp<android::AudioEffect>();
117 }
118
IAndroidAutomaticGainControl_deinit(void * self)119 void IAndroidAutomaticGainControl_deinit(void *self)
120 {
121 IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
122 // explicit destructor
123 thiz->mAGCEffect.~sp();
124 }
125
IAndroidAutomaticGainControl_Expose(void * self)126 bool IAndroidAutomaticGainControl_Expose(void *self)
127 {
128 IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
129 if (!android_fx_initEffectDescriptor(SL_IID_ANDROIDAUTOMATICGAINCONTROL,
130 &thiz->mAGCDescriptor)) {
131 SL_LOGE("Automatic Gain Control initialization failed.");
132 return false;
133 }
134 return true;
135 }
136