android_Effect.cpp revision f5fce95f98037ea4ab341b416c82444af595313d
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//-----------------------------------------------------------------------------
226bool android_fx_initEffectDescriptor(const SLInterfaceID effectId,
227        effect_descriptor_t* fxDescrLoc) {
228    uint32_t numEffects = 0;
229    effect_descriptor_t descriptor;
230    bool foundEffect = false;
231
232    // any effects?
233    android::status_t res = android::AudioEffect::queryNumberEffects(&numEffects);
234    if (android::NO_ERROR != res) {
235        SL_LOGE("unable to find any effects.");
236        goto effectError;
237    }
238
239    // request effect in the effects?
240    for (uint32_t i=0 ; i < numEffects ; i++) {
241        res = android::AudioEffect::queryEffect(i, &descriptor);
242        if ((android::NO_ERROR == res) &&
243                (0 == memcmp(effectId, &descriptor.type, sizeof(effect_uuid_t)))) {
244            SL_LOGV("found effect %d %s", i, descriptor.name);
245            foundEffect = true;
246            break;
247        }
248    }
249    if (foundEffect) {
250        memcpy(fxDescrLoc, &descriptor, sizeof(effect_descriptor_t));
251    } else {
252        SL_LOGE("unable to find an implementation for the requested effect.");
253        goto effectError;
254    }
255
256    return true;
257
258effectError:
259    // the requested effect wasn't found
260    memset(fxDescrLoc, 0, sizeof(effect_descriptor_t));
261
262    return false;
263}
264
265//-----------------------------------------------------------------------------
266SLresult android_genericFx_queryNumEffects(SLuint32 *pNumSupportedAudioEffects) {
267
268    if (NULL == pNumSupportedAudioEffects) {
269        return SL_RESULT_PARAMETER_INVALID;
270    }
271
272    android::status_t status =
273            android::AudioEffect::queryNumberEffects((uint32_t*)pNumSupportedAudioEffects);
274
275    SLresult result = SL_RESULT_SUCCESS;
276    switch(status) {
277        case android::NO_ERROR:
278            result = SL_RESULT_SUCCESS;
279            break;
280        case android::PERMISSION_DENIED:
281            result = SL_RESULT_PERMISSION_DENIED;
282            break;
283        case android::NO_INIT:
284            result = SL_RESULT_RESOURCE_ERROR;
285            break;
286        case android::BAD_VALUE:
287            result = SL_RESULT_PARAMETER_INVALID;
288            break;
289        default:
290            result = SL_RESULT_INTERNAL_ERROR;
291            SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
292            break;
293    }
294    return result;
295}
296
297
298//-----------------------------------------------------------------------------
299SLresult android_genericFx_queryEffect(SLuint32 index, SLInterfaceID *pAudioEffectId) {
300
301    if (NULL == pAudioEffectId) {
302        return SL_RESULT_PARAMETER_INVALID;
303    }
304
305    effect_descriptor_t descriptor;
306    android::status_t status =
307                android::AudioEffect::queryEffect(index, &descriptor);
308
309    SLresult result = SL_RESULT_SUCCESS;
310    switch(status) {
311        case android::NO_ERROR:
312            // FIXME this function will move to an engine interface where we will store the
313            //       audio effect IDs and we only return references to those, as SLInterfaceID
314            //       is a pointer to the struct where a uuid is stored.
315            //*pAudioEffectId = some global reference to where we keep a copy of the effect uuid
316            result = SL_RESULT_SUCCESS;
317            break;
318        case android::PERMISSION_DENIED:
319            result = SL_RESULT_PERMISSION_DENIED;
320            break;
321        case android::NO_INIT:
322        case android::INVALID_OPERATION:
323            result = SL_RESULT_RESOURCE_ERROR;
324            break;
325        case android::BAD_VALUE:
326            result = SL_RESULT_PARAMETER_INVALID;
327            break;
328        default:
329            result = SL_RESULT_INTERNAL_ERROR;
330            SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
331            break;
332    }
333    return result;
334}
335
336
337//-----------------------------------------------------------------------------
338SLresult android_genericFx_createEffect(int sessionId, SLInterfaceID pUuid, void **ppAudioEffect) {
339
340    android::AudioEffect* af = NULL;
341    SLresult result = SL_RESULT_SUCCESS;
342
343    af = new android::AudioEffect(
344            NULL, // not using type to create effect
345            (const effect_uuid_t*)pUuid,
346            0,// priority
347            0,// effect callback
348            0,// callback data
349            sessionId,
350            0 );// output
351    android::status_t status = af->initCheck();
352
353    if (android::NO_ERROR != status) {
354        SL_LOGE("AudioEffect initCheck() returned %d", status);
355        result = SL_RESULT_RESOURCE_ERROR;
356    }
357
358    *ppAudioEffect = af;
359    return result;
360}
361
362
363//-----------------------------------------------------------------------------
364SLresult android_genericFx_releaseEffect(void *pAudioEffect) {
365
366    if (NULL != pAudioEffect) {
367        delete ((android::AudioEffect*)pAudioEffect);
368        return SL_RESULT_SUCCESS;
369    } else {
370        return SL_RESULT_PARAMETER_INVALID;
371    }
372}
373
374
375//-----------------------------------------------------------------------------
376SLresult android_genericFx_setEnabled(void *pAudioEffect, SLboolean enabled) {
377
378    if (NULL == pAudioEffect) {
379        return SL_RESULT_PARAMETER_INVALID;
380    }
381
382    android::status_t status =
383            ((android::AudioEffect*)pAudioEffect)->setEnabled(SL_BOOLEAN_TRUE == enabled);
384
385    return android_fx_statusToResult(status);
386}
387
388
389//-----------------------------------------------------------------------------
390SLresult android_genericFx_isEnabled(void *pAudioEffect, SLboolean *pEnabled) {
391
392    if (NULL == pAudioEffect) {
393        *pEnabled = SL_BOOLEAN_FALSE;
394        return SL_RESULT_PARAMETER_INVALID;
395    }
396
397    *pEnabled =
398           ((android::AudioEffect*)pAudioEffect)->getEnabled() ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE;
399
400    return SL_RESULT_SUCCESS;
401}
402
403
404//-----------------------------------------------------------------------------
405SLresult android_genericFx_sendCommand(void *pAudioEffect, SLuint32 command, SLuint32 commandSize,
406        void* pCommand, SLuint32 *replySize, void *pReply) {
407
408    if (NULL == pAudioEffect) {
409        return SL_RESULT_PARAMETER_INVALID;
410    }
411
412    android::status_t status = ((android::AudioEffect*)pAudioEffect)->command(
413            (uint32_t) command,
414            (uint32_t) commandSize,
415            pCommand,
416            (uint32_t*)replySize,
417            pReply);
418
419    if (android::BAD_VALUE == status) {
420        return SL_RESULT_PARAMETER_INVALID;
421    }
422    return SL_RESULT_SUCCESS;
423}
424
425
426