android_Effect.cpp revision b3b757daa7d162b6f66590d917c1f84f3ba73c70
1/*
2 * Copyright (C) 2010 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
18#include "sles_allinclusive.h"
19#include "math.h"
20#include "utils/RefBase.h"
21
22
23static const int EQUALIZER_PARAM_SIZE_MAX = sizeof(effect_param_t) + 2 * sizeof(int32_t)
24        + EFFECT_STRING_LEN_MAX;
25
26
27//-----------------------------------------------------------------------------
28uint32_t eq_paramSize(int32_t param)
29{
30    uint32_t size;
31
32    switch (param) {
33    case EQ_PARAM_NUM_BANDS:
34    case EQ_PARAM_LEVEL_RANGE:
35    case EQ_PARAM_CUR_PRESET:
36    case EQ_PARAM_GET_NUM_OF_PRESETS:
37        size = sizeof(int32_t);
38        break;
39    case EQ_PARAM_BAND_LEVEL:
40    case EQ_PARAM_CENTER_FREQ:
41    case EQ_PARAM_BAND_FREQ_RANGE:
42    case EQ_PARAM_GET_BAND:
43    case EQ_PARAM_GET_PRESET_NAME:
44        size = 2 * sizeof(int32_t);
45        break;
46    default:
47        size = 2 * sizeof(int32_t);
48        SL_LOGE("Trying to use an unknown EQ parameter %d", param);
49        break;
50    }
51    return size;
52}
53
54uint32_t eq_valueSize(int32_t param)
55{
56    uint32_t size;
57
58    switch (param) {
59    case EQ_PARAM_NUM_BANDS:
60    case EQ_PARAM_CUR_PRESET:
61    case EQ_PARAM_GET_NUM_OF_PRESETS:
62    case EQ_PARAM_BAND_LEVEL:
63    case EQ_PARAM_GET_BAND:
64        size = sizeof(int16_t);
65        break;
66    case EQ_PARAM_LEVEL_RANGE:
67        size = 2 * sizeof(int16_t);
68        break;
69    case EQ_PARAM_CENTER_FREQ:
70        size = sizeof(int32_t);
71        break;
72    case EQ_PARAM_BAND_FREQ_RANGE:
73        size = 2 * sizeof(int32_t);
74        break;
75    case EQ_PARAM_GET_PRESET_NAME:
76        size = EFFECT_STRING_LEN_MAX;
77        break;
78    default:
79        size = sizeof(int32_t);
80        SL_LOGE("Trying to access an unknown EQ parameter %d", param);
81        break;
82    }
83    return size;
84}
85
86
87//-----------------------------------------------------------------------------
88android::status_t android_eq_getParam(android::sp<android::AudioEffect> pFx,
89        int32_t param, int32_t param2, void *pValue)
90{
91     android::status_t status;
92     uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1];
93     effect_param_t *p = (effect_param_t *)buf32;
94
95     p->psize = eq_paramSize(param);
96     *(int32_t *)p->data = param;
97     if (p->psize == 2 * sizeof(int32_t)) {
98         *((int32_t *)p->data + 1) = param2;
99     }
100     p->vsize = eq_valueSize(param);
101     status = pFx->getParameter(p);
102     if (android::NO_ERROR == status) {
103         status = p->status;
104         if (android::NO_ERROR == status) {
105             memcpy(pValue, p->data + p->psize, p->vsize);
106         }
107     }
108
109     return status;
110 }
111
112
113//-----------------------------------------------------------------------------
114android::status_t android_eq_setParam(android::sp<android::AudioEffect> pFx,
115        int32_t param, int32_t param2, void *pValue)
116{
117    android::status_t status;
118    uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1];
119    effect_param_t *p = (effect_param_t *)buf32;
120
121    p->psize = eq_paramSize(param);
122    *(int32_t *)p->data = param;
123    if (p->psize == 2 * sizeof(int32_t)) {
124        *((int32_t *)p->data + 1) = param2;
125    }
126    p->vsize = eq_valueSize(param);
127    memcpy(p->data + p->psize, pValue, p->vsize);
128    status = pFx->setParameter(p);
129    if (android::NO_ERROR == status) {
130        status = p->status;
131    }
132
133    return status;
134}
135
136
137//-----------------------------------------------------------------------------
138void android_eq_init(int sessionId, CAudioPlayer* ap) {
139    SL_LOGV("android_initEq on session %d", sessionId);
140
141    ap->mEqualizer.mEqEffect = new android::AudioEffect(
142            &ap->mEqualizer.mEqDescriptor.type,//(const effect_uuid_t*)SL_IID_EQUALIZER,//
143            &ap->mEqualizer.mEqDescriptor.uuid,
144            0,// priority
145            0,// effect callback
146            0,// callback data
147            sessionId,// session ID
148            0 );// output
149    android::status_t status = ap->mEqualizer.mEqEffect->initCheck();
150    if (android::NO_ERROR != status) {
151        SL_LOGE("EQ initCheck() returned %d", status);
152        return;
153    }
154
155    // initialize number of bands, band level range
156    uint16_t num = 0;
157    if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect,
158            EQ_PARAM_NUM_BANDS, 0, &num)) {
159        ap->mEqualizer.mNumBands = num;
160    }
161    int16_t range[2] = {0, 0};
162    if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect,
163            EQ_PARAM_LEVEL_RANGE, 0, range)) {
164        ap->mEqualizer.mBandLevelRangeMin = range[0];
165        ap->mEqualizer.mBandLevelRangeMax = range[1];
166    }
167
168    SL_LOGV(" EQ init: num presets = %u, band range=[%d %d]mB", num, range[0], range[1]);
169
170    // initialize preset number and names, store in IEngine
171    uint16_t numPresets = 0;
172    if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect,
173            EQ_PARAM_GET_NUM_OF_PRESETS, 0, &numPresets)) {
174        ap->mObject.mEngine->mEqNumPresets = numPresets;
175    }
176    char name[EFFECT_STRING_LEN_MAX];
177    if ((0 < numPresets) && (NULL == ap->mObject.mEngine->mEqPresetNames)) {
178        ap->mObject.mEngine->mEqPresetNames = (char **)new char *[numPresets];
179        for(uint32_t i = 0 ; i < numPresets ; i++) {
180            if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect,
181                    EQ_PARAM_GET_PRESET_NAME, i, name)) {
182                ap->mObject.mEngine->mEqPresetNames[i] = new char[strlen(name) + 1];
183                strcpy(ap->mObject.mEngine->mEqPresetNames[i], name);
184                SL_LOGV(" EQ init: presets = %u is %s", i, ap->mObject.mEngine->mEqPresetNames[i]);
185            }
186
187        }
188    }
189#if 0
190    // configure the EQ so it can easily be heard, for test only
191    uint32_t freq = 1977;
192    uint32_t frange[2];
193    int16_t value = ap->mEqualizer.mBandLevelRangeMin;
194    for(int32_t i=0 ; i< ap->mEqualizer.mNumBands ; i++) {
195        android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, i, &value);
196        // display EQ characteristics
197        android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_CENTER_FREQ, i, &freq);
198        android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_FREQ_RANGE, i, frange);
199        SL_LOGV(" EQ init: band %d = %d - %d - %dHz", i, frange[0]/1000, freq/1000,
200                frange[1]/1000);
201    }
202    value = ap->mEqualizer.mBandLevelRangeMax;
203    if (ap->mEqualizer.mNumBands > 2) {
204        android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 2, &value);
205    }
206    if (ap->mEqualizer.mNumBands > 3) {
207        android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 3, &value);
208    }
209
210    ap->mEqualizer.mEqEffect->setEnabled(true);
211#endif
212}
213
214//-----------------------------------------------------------------------------
215SLresult android_fx_statusToResult(android::status_t status) {
216
217    if ((android::INVALID_OPERATION == status) || (android::DEAD_OBJECT == status)) {
218        return SL_RESULT_CONTROL_LOST;
219    } else {
220        return SL_RESULT_SUCCESS;
221    }
222}
223
224
225//-----------------------------------------------------------------------------
226SLresult android_genericFx_queryNumEffects(SLuint32 *pNumSupportedAudioEffects) {
227
228    if (NULL == pNumSupportedAudioEffects) {
229        return SL_RESULT_PARAMETER_INVALID;
230    }
231
232    android::status_t status =
233            android::AudioEffect::queryNumberEffects((uint32_t*)pNumSupportedAudioEffects);
234
235    SLresult result = SL_RESULT_SUCCESS;
236    switch(status) {
237        case android::NO_ERROR:
238            result = SL_RESULT_SUCCESS;
239            break;
240        case android::PERMISSION_DENIED:
241            result = SL_RESULT_PERMISSION_DENIED;
242            break;
243        case android::NO_INIT:
244            result = SL_RESULT_RESOURCE_ERROR;
245            break;
246        case android::BAD_VALUE:
247            result = SL_RESULT_PARAMETER_INVALID;
248            break;
249        default:
250            result = SL_RESULT_INTERNAL_ERROR;
251            SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
252            break;
253    }
254    return result;
255}
256
257
258//-----------------------------------------------------------------------------
259SLresult android_genericFx_queryEffect(SLuint32 index, SLInterfaceID *pAudioEffectId) {
260
261    if (NULL == pAudioEffectId) {
262        return SL_RESULT_PARAMETER_INVALID;
263    }
264
265    effect_descriptor_t descriptor;
266    android::status_t status =
267                android::AudioEffect::queryEffect(index, &descriptor);
268
269    SLresult result = SL_RESULT_SUCCESS;
270    switch(status) {
271        case android::NO_ERROR:
272            // FIXME this function will move to an engine interface where we will store the
273            //       audio effect IDs and we only return references to those, as SLInterfaceID
274            //       is a pointer to the struct where a uuid is stored.
275            //*pAudioEffectId = some global reference to where we keep a copy of the effect uuid
276            result = SL_RESULT_SUCCESS;
277            break;
278        case android::PERMISSION_DENIED:
279            result = SL_RESULT_PERMISSION_DENIED;
280            break;
281        case android::NO_INIT:
282        case android::INVALID_OPERATION:
283            result = SL_RESULT_RESOURCE_ERROR;
284            break;
285        case android::BAD_VALUE:
286            result = SL_RESULT_PARAMETER_INVALID;
287            break;
288        default:
289            result = SL_RESULT_INTERNAL_ERROR;
290            SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
291            break;
292    }
293    return result;
294}
295
296
297//-----------------------------------------------------------------------------
298SLresult android_genericFx_createEffect(int sessionId, SLInterfaceID pUuid, void **ppAudioEffect) {
299
300    android::AudioEffect* af = NULL;
301    SLresult result = SL_RESULT_SUCCESS;
302
303    af = new android::AudioEffect(
304            NULL, // not using type to create effect
305            (const effect_uuid_t*)pUuid,
306            0,// priority
307            0,// effect callback
308            0,// callback data
309            sessionId,
310            0 );// output
311    android::status_t status = af->initCheck();
312
313    if (android::NO_ERROR != status) {
314        SL_LOGE("AudioEffect initCheck() returned %d", status);
315        result = SL_RESULT_RESOURCE_ERROR;
316    }
317
318    *ppAudioEffect = af;
319    return result;
320}
321
322
323//-----------------------------------------------------------------------------
324SLresult android_genericFx_releaseEffect(void *pAudioEffect) {
325
326    if (NULL != pAudioEffect) {
327        delete ((android::AudioEffect*)pAudioEffect);
328        return SL_RESULT_SUCCESS;
329    } else {
330        return SL_RESULT_PARAMETER_INVALID;
331    }
332}
333
334
335//-----------------------------------------------------------------------------
336SLresult android_genericFx_setEnabled(void *pAudioEffect, SLboolean enabled) {
337
338    if (NULL == pAudioEffect) {
339        return SL_RESULT_PARAMETER_INVALID;
340    }
341
342    android::status_t status =
343            ((android::AudioEffect*)pAudioEffect)->setEnabled(SL_BOOLEAN_TRUE == enabled);
344
345    // the effect framework will return an error if the requested state is the same as the previous,
346    // this prevents us from returning an error when the effect cannot be controlled. We're
347    // therefore returning success regardless of the status code.
348    return SL_RESULT_SUCCESS;
349}
350
351
352//-----------------------------------------------------------------------------
353SLresult android_genericFx_isEnabled(void *pAudioEffect, SLboolean *pEnabled) {
354
355    if (NULL == pAudioEffect) {
356        *pEnabled = SL_BOOLEAN_FALSE;
357        return SL_RESULT_PARAMETER_INVALID;
358    }
359
360    *pEnabled =
361           ((android::AudioEffect*)pAudioEffect)->getEnabled() ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE;
362
363    return SL_RESULT_SUCCESS;
364}
365
366
367//-----------------------------------------------------------------------------
368SLresult android_genericFx_sendCommand(void *pAudioEffect, SLuint32 command, SLuint32 commandSize,
369        void* pCommand, SLuint32 *replySize, void *pReply) {
370
371    if (NULL == pAudioEffect) {
372        return SL_RESULT_PARAMETER_INVALID;
373    }
374
375    // FIXME update size casts when framework moves from int32_t to uint32_t
376    android::status_t status = ((android::AudioEffect*)pAudioEffect)->command(
377            (int32_t) command,
378            (int32_t) commandSize,
379            pCommand,
380            (uint32_t*)replySize,
381            pReply);
382
383    if (android::BAD_VALUE == status) {
384        return SL_RESULT_PARAMETER_INVALID;
385    }
386    return SL_RESULT_SUCCESS;
387}
388
389
390