android_Effect.cpp revision 00667fcca51d62236b538e6857b7e6b923453569
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
26static const int BASSBOOST_PARAM_SIZE_MAX = sizeof(effect_param_t) + 2 * sizeof(int32_t);
27
28static const int VIRTUALIZER_PARAM_SIZE_MAX = sizeof(effect_param_t) + 2 * sizeof(int32_t);
29
30static const int ENVREVERB_PARAM_SIZE_MAX_SINGLE = sizeof(effect_param_t) + 2 * sizeof(int32_t);
31
32static const int ENVREVERB_PARAM_SIZE_MAX_ALL = sizeof(effect_param_t) + sizeof(int32_t)
33        + sizeof(s_reverb_settings);
34
35static inline SLuint32 KEY_FROM_GUID(SLInterfaceID pUuid) {
36    return pUuid->time_low;
37}
38
39
40//-----------------------------------------------------------------------------
41uint32_t eq_paramSize(int32_t param) {
42    uint32_t size;
43
44    switch (param) {
45    case EQ_PARAM_NUM_BANDS:
46    case EQ_PARAM_LEVEL_RANGE:
47    case EQ_PARAM_CUR_PRESET:
48    case EQ_PARAM_GET_NUM_OF_PRESETS:
49        size = sizeof(int32_t);
50        break;
51    case EQ_PARAM_BAND_LEVEL:
52    case EQ_PARAM_CENTER_FREQ:
53    case EQ_PARAM_BAND_FREQ_RANGE:
54    case EQ_PARAM_GET_BAND:
55    case EQ_PARAM_GET_PRESET_NAME:
56        size = 2 * sizeof(int32_t);
57        break;
58    default:
59        size = 2 * sizeof(int32_t);
60        SL_LOGE("Trying to use an unknown EQ parameter %d", param);
61        break;
62    }
63    return size;
64}
65
66uint32_t eq_valueSize(int32_t param) {
67    uint32_t size;
68
69    switch (param) {
70    case EQ_PARAM_NUM_BANDS:
71    case EQ_PARAM_CUR_PRESET:
72    case EQ_PARAM_GET_NUM_OF_PRESETS:
73    case EQ_PARAM_BAND_LEVEL:
74    case EQ_PARAM_GET_BAND:
75        size = sizeof(int16_t);
76        break;
77    case EQ_PARAM_LEVEL_RANGE:
78        size = 2 * sizeof(int16_t);
79        break;
80    case EQ_PARAM_CENTER_FREQ:
81        size = sizeof(int32_t);
82        break;
83    case EQ_PARAM_BAND_FREQ_RANGE:
84        size = 2 * sizeof(int32_t);
85        break;
86    case EQ_PARAM_GET_PRESET_NAME:
87        size = EFFECT_STRING_LEN_MAX;
88        break;
89    default:
90        size = sizeof(int32_t);
91        SL_LOGE("Trying to access an unknown EQ parameter %d", param);
92        break;
93    }
94    return size;
95}
96
97//-----------------------------------------------------------------------------
98/**
99 * returns the size in bytes of the value of each bass boost parameter
100 */
101uint32_t bb_valueSize(int32_t param) {
102    uint32_t size;
103
104    switch (param) {
105    case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
106        size = sizeof(int32_t);
107        break;
108    case BASSBOOST_PARAM_STRENGTH:
109        size = sizeof(int16_t);
110        break;
111    default:
112        size = sizeof(int32_t);
113        SL_LOGE("Trying to access an unknown BassBoost parameter %d", param);
114        break;
115    }
116
117    return size;
118}
119
120//-----------------------------------------------------------------------------
121/**
122 * returns the size in bytes of the value of each virtualizer parameter
123 */
124uint32_t virt_valueSize(int32_t param) {
125    uint32_t size;
126
127    switch (param) {
128    case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
129        size = sizeof(int32_t);
130        break;
131    case VIRTUALIZER_PARAM_STRENGTH:
132        size = sizeof(int16_t);
133        break;
134    default:
135        size = sizeof(int32_t);
136        SL_LOGE("Trying to access an unknown Virtualizer parameter %d", param);
137        break;
138    }
139
140    return size;
141}
142
143//-----------------------------------------------------------------------------
144/**
145 * returns the size in bytes of the value of each environmental reverb parameter
146 */
147uint32_t erev_valueSize(int32_t param) {
148    uint32_t size;
149
150    switch (param) {
151    case REVERB_PARAM_ROOM_LEVEL:
152    case REVERB_PARAM_ROOM_HF_LEVEL:
153    case REVERB_PARAM_REFLECTIONS_LEVEL:
154    case REVERB_PARAM_REVERB_LEVEL:
155        size = sizeof(int16_t); // millibel
156        break;
157    case REVERB_PARAM_DECAY_TIME:
158    case REVERB_PARAM_REFLECTIONS_DELAY:
159    case REVERB_PARAM_REVERB_DELAY:
160        size = sizeof(uint32_t); // milliseconds
161        break;
162    case REVERB_PARAM_DECAY_HF_RATIO:
163    case REVERB_PARAM_DIFFUSION:
164    case REVERB_PARAM_DENSITY:
165        size = sizeof(int16_t); // permille
166        break;
167    case REVERB_PARAM_PROPERTIES:
168        size = sizeof(s_reverb_settings); // struct of all reverb properties
169        break;
170    default:
171        size = sizeof(int32_t);
172        SL_LOGE("Trying to access an unknown Environmental Reverb parameter %d", param);
173        break;
174    }
175
176    return size;
177}
178
179//-----------------------------------------------------------------------------
180android::status_t android_eq_getParam(android::sp<android::AudioEffect> pFx,
181        int32_t param, int32_t param2, void *pValue)
182{
183     android::status_t status;
184     uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1];
185     effect_param_t *p = (effect_param_t *)buf32;
186
187     p->psize = eq_paramSize(param);
188     *(int32_t *)p->data = param;
189     if (p->psize == 2 * sizeof(int32_t)) {
190         *((int32_t *)p->data + 1) = param2;
191     }
192     p->vsize = eq_valueSize(param);
193     status = pFx->getParameter(p);
194     if (android::NO_ERROR == status) {
195         status = p->status;
196         if (android::NO_ERROR == status) {
197             memcpy(pValue, p->data + p->psize, p->vsize);
198         }
199     }
200
201     return status;
202 }
203
204
205//-----------------------------------------------------------------------------
206android::status_t android_eq_setParam(android::sp<android::AudioEffect> pFx,
207        int32_t param, int32_t param2, void *pValue)
208{
209    android::status_t status;
210    uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1];
211    effect_param_t *p = (effect_param_t *)buf32;
212
213    p->psize = eq_paramSize(param);
214    *(int32_t *)p->data = param;
215    if (p->psize == 2 * sizeof(int32_t)) {
216        *((int32_t *)p->data + 1) = param2;
217    }
218    p->vsize = eq_valueSize(param);
219    memcpy(p->data + p->psize, pValue, p->vsize);
220    status = pFx->setParameter(p);
221    if (android::NO_ERROR == status) {
222        status = p->status;
223    }
224
225    return status;
226}
227
228//-----------------------------------------------------------------------------
229android::status_t android_bb_setParam(android::sp<android::AudioEffect> pFx,
230        int32_t param, void *pValue) {
231
232    return android_fx_setParam(pFx, param, BASSBOOST_PARAM_SIZE_MAX,
233            pValue, bb_valueSize(param));
234}
235
236//-----------------------------------------------------------------------------
237android::status_t android_bb_getParam(android::sp<android::AudioEffect> pFx,
238        int32_t param, void *pValue) {
239
240    return android_fx_getParam(pFx, param, BASSBOOST_PARAM_SIZE_MAX,
241            pValue, bb_valueSize(param));
242}
243
244//-----------------------------------------------------------------------------
245void android_bb_init(int sessionId, IBassBoost* ibb) {
246    SL_LOGV("session %d", sessionId);
247
248    if (!android_fx_initEffectObj(sessionId, ibb->mBassBoostEffect,
249            &ibb->mBassBoostDescriptor.type))
250    {
251        SL_LOGE("BassBoost effect initialization failed");
252        return;
253    }
254
255    // initialize strength
256    int16_t strength;
257    if (android::NO_ERROR == android_bb_getParam(ibb->mBassBoostEffect,
258            BASSBOOST_PARAM_STRENGTH, &strength)) {
259        ibb->mStrength = (SLpermille) strength;
260    }
261}
262
263
264//-----------------------------------------------------------------------------
265void android_eq_init(int sessionId, IEqualizer* ieq) {
266    SL_LOGV("session %d", sessionId);
267
268    if (!android_fx_initEffectObj(sessionId, ieq->mEqEffect, &ieq->mEqDescriptor.type)) {
269        SL_LOGE("Equalizer effect initialization failed");
270        return;
271    }
272
273    // initialize number of bands, band level range, and number of presets
274    uint16_t num = 0;
275    if (android::NO_ERROR == android_eq_getParam(ieq->mEqEffect, EQ_PARAM_NUM_BANDS, 0, &num)) {
276        ieq->mNumBands = num;
277    }
278    int16_t range[2] = {0, 0};
279    if (android::NO_ERROR == android_eq_getParam(ieq->mEqEffect, EQ_PARAM_LEVEL_RANGE, 0, range)) {
280        ieq->mBandLevelRangeMin = range[0];
281        ieq->mBandLevelRangeMax = range[1];
282    }
283
284    SL_LOGV(" EQ init: num bands = %u, band range=[%d %d]mB", num, range[0], range[1]);
285
286    // FIXME don't store presets names, they can be queried each time they're needed
287    // initialize preset number and names, store in IEngine
288    uint16_t numPresets = 0;
289    if (android::NO_ERROR == android_eq_getParam(ieq->mEqEffect,
290            EQ_PARAM_GET_NUM_OF_PRESETS, 0, &numPresets)) {
291        ieq->mThis->mEngine->mEqNumPresets = numPresets;
292        ieq->mNumPresets = numPresets;
293    }
294
295    interface_lock_exclusive(ieq->mThis->mEngine);
296    char name[EFFECT_STRING_LEN_MAX];
297    if ((0 < numPresets) && (NULL == ieq->mThis->mEngine->mEqPresetNames)) {
298        ieq->mThis->mEngine->mEqPresetNames = (char **)new char *[numPresets];
299        for(uint32_t i = 0 ; i < numPresets ; i++) {
300            if (android::NO_ERROR == android_eq_getParam(ieq->mEqEffect,
301                    EQ_PARAM_GET_PRESET_NAME, i, name)) {
302                ieq->mThis->mEngine->mEqPresetNames[i] = new char[strlen(name) + 1];
303                strcpy(ieq->mThis->mEngine->mEqPresetNames[i], name);
304                SL_LOGV(" EQ init: presets = %u is %s", i, ieq->mThis->mEngine->mEqPresetNames[i]);
305            }
306        }
307    }
308    interface_unlock_exclusive(ieq->mThis->mEngine);
309
310#if 0
311    // configure the EQ so it can easily be heard, for test only
312    uint32_t freq = 1977;
313    uint32_t frange[2];
314    int16_t value = ap->mEqualizer.mBandLevelRangeMin;
315    for(int32_t i=0 ; i< ap->mEqualizer.mNumBands ; i++) {
316        android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, i, &value);
317        // display EQ characteristics
318        android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_CENTER_FREQ, i, &freq);
319        android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_FREQ_RANGE, i, frange);
320        SL_LOGV(" EQ init: band %d = %d - %d - %dHz", i, frange[0]/1000, freq/1000,
321                frange[1]/1000);
322    }
323    value = ap->mEqualizer.mBandLevelRangeMax;
324    if (ap->mEqualizer.mNumBands > 2) {
325        android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 2, &value);
326    }
327    if (ap->mEqualizer.mNumBands > 3) {
328        android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 3, &value);
329    }
330
331    ap->mEqualizer.mEqEffect->setEnabled(true);
332#endif
333}
334
335
336//-----------------------------------------------------------------------------
337void android_virt_init(int sessionId, IVirtualizer* ivi) {
338    SL_LOGV("session %d", sessionId);
339
340    if (!android_fx_initEffectObj(sessionId, ivi->mVirtualizerEffect,
341            &ivi->mVirtualizerDescriptor.type)) {
342        SL_LOGE("Virtualizer effect initialization failed");
343        return;
344    }
345
346    // initialize strength
347    int16_t strength;
348    if (android::NO_ERROR == android_virt_getParam(ivi->mVirtualizerEffect,
349            VIRTUALIZER_PARAM_STRENGTH, &strength)) {
350        ivi->mStrength = (SLpermille) strength;
351    }
352}
353
354//-----------------------------------------------------------------------------
355android::status_t android_virt_setParam(android::sp<android::AudioEffect> pFx,
356        int32_t param, void *pValue) {
357
358    return android_fx_setParam(pFx, param, VIRTUALIZER_PARAM_SIZE_MAX,
359            pValue, virt_valueSize(param));
360}
361
362//-----------------------------------------------------------------------------
363android::status_t android_virt_getParam(android::sp<android::AudioEffect> pFx,
364        int32_t param, void *pValue) {
365
366    return android_fx_getParam(pFx, param, VIRTUALIZER_PARAM_SIZE_MAX,
367            pValue, virt_valueSize(param));
368}
369
370
371//-----------------------------------------------------------------------------
372void android_prev_init(IPresetReverb* ipr) {
373    SL_LOGV("session is implicitly %d (aux effect)", android::AudioSystem::SESSION_OUTPUT_MIX);
374
375    if (!android_fx_initEffectObj(android::AudioSystem::SESSION_OUTPUT_MIX /*sessionId*/,
376            ipr->mPresetReverbEffect, &ipr->mPresetReverbDescriptor.type)) {
377        SL_LOGE("PresetReverb effect initialization failed");
378        return;
379    }
380
381    // initialize preset
382    uint16_t preset;
383    if (android::NO_ERROR == android_prev_getPreset(ipr->mPresetReverbEffect, &preset)) {
384        ipr->mPreset = preset;
385        // enable the effect is it has a effective preset loaded
386        ipr->mPresetReverbEffect->setEnabled(SL_REVERBPRESET_NONE != preset);
387    }
388}
389
390//-----------------------------------------------------------------------------
391android::status_t android_prev_setPreset(android::sp<android::AudioEffect> pFx, uint16_t preset) {
392    android::status_t status = android_fx_setParam(pFx, REVERB_PARAM_PRESET, sizeof(uint16_t),
393            &preset, sizeof(uint16_t));
394    // enable the effect if the preset is different from SL_REVERBPRESET_NONE
395    pFx->setEnabled(SL_REVERBPRESET_NONE != preset);
396    return status;
397}
398
399//-----------------------------------------------------------------------------
400android::status_t android_prev_getPreset(android::sp<android::AudioEffect> pFx, uint16_t* preset) {
401    return android_fx_getParam(pFx, REVERB_PARAM_PRESET, sizeof(uint16_t), preset,
402            sizeof(uint16_t));
403}
404
405
406//-----------------------------------------------------------------------------
407void android_erev_init(IEnvironmentalReverb* ier) {
408    SL_LOGV("session is implicitly %d (aux effect)", android::AudioSystem::SESSION_OUTPUT_MIX);
409
410    if (!android_fx_initEffectObj(android::AudioSystem::SESSION_OUTPUT_MIX /*sessionId*/,
411            ier->mEnvironmentalReverbEffect, &ier->mEnvironmentalReverbDescriptor.type)) {
412        SL_LOGE("EnvironmentalReverb effect initialization failed");
413        return;
414    }
415
416    // enable env reverb: other SL ES effects have an explicit SetEnabled() function, and the
417    //  preset reverb state depends on the selected preset.
418    ier->mEnvironmentalReverbEffect->setEnabled(true);
419
420    // initialize reverb properties
421    SLEnvironmentalReverbSettings properties;
422    if (android::NO_ERROR == android_erev_getParam(ier->mEnvironmentalReverbEffect,
423            REVERB_PARAM_PROPERTIES, &properties)) {
424        ier->mProperties = properties;
425    }
426}
427
428//-----------------------------------------------------------------------------
429android::status_t android_erev_setParam(android::sp<android::AudioEffect> pFx,
430        int32_t param, void *pValue) {
431
432    // given the size difference between a single reverb property and the whole set of reverb
433    // properties, select which max size to pass to avoid allocating too much memory
434    if (param == REVERB_PARAM_PROPERTIES) {
435        return android_fx_setParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_ALL,
436                pValue, erev_valueSize(param));
437    } else {
438        return android_fx_setParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_SINGLE,
439                pValue, erev_valueSize(param));
440    }
441}
442
443//-----------------------------------------------------------------------------
444android::status_t android_erev_getParam(android::sp<android::AudioEffect> pFx,
445        int32_t param, void *pValue) {
446
447    // given the size difference between a single reverb property and the whole set of reverb
448    // properties, select which max size to pass to avoid allocating too much memory
449    if (param == REVERB_PARAM_PROPERTIES) {
450        return android_fx_getParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_ALL,
451                pValue, erev_valueSize(param));
452    } else {
453        return android_fx_getParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_SINGLE,
454                pValue, erev_valueSize(param));
455    }
456}
457
458
459//-----------------------------------------------------------------------------
460android::status_t android_fxSend_attach(CAudioPlayer* ap, bool attach,
461        android::sp<android::AudioEffect> pFx, SLmillibel sendLevel) {
462
463    if ((NULL == ap->mAudioTrack) || (pFx == 0)) {
464        return android::INVALID_OPERATION;
465    }
466
467    if (attach) {
468        android::status_t status = ap->mAudioTrack->attachAuxEffect(pFx->id());
469        //SL_LOGV("attachAuxEffect(%d) returned %d", pFx->id(), status);
470        if (android::NO_ERROR == status) {
471            status =
472                ap->mAudioTrack->setAuxEffectSendLevel( sles_to_android_amplification(sendLevel) );
473        }
474        return status;
475    } else {
476        return ap->mAudioTrack->attachAuxEffect(0);
477    }
478}
479
480//-----------------------------------------------------------------------------
481android::status_t android_fxSend_setSendLevel(CAudioPlayer* ap, SLmillibel sendLevel) {
482    if (NULL == ap->mAudioTrack) {
483        return android::INVALID_OPERATION;
484    }
485
486    return ap->mAudioTrack->setAuxEffectSendLevel( sles_to_android_amplification(sendLevel) );
487}
488
489//-----------------------------------------------------------------------------
490android::status_t android_fx_setParam(android::sp<android::AudioEffect> pFx,
491        int32_t param, uint32_t paramSizeMax, void *pValue, uint32_t valueSize)
492{
493
494    android::status_t status;
495    uint32_t buf32[(paramSizeMax - 1) / sizeof(uint32_t) + 1];
496    effect_param_t *p = (effect_param_t *)buf32;
497
498    p->psize = sizeof(int32_t);
499    *(int32_t *)p->data = param;
500    p->vsize = valueSize;
501    memcpy(p->data + p->psize, pValue, p->vsize);
502    status = pFx->setParameter(p);
503    if (android::NO_ERROR == status) {
504        status = p->status;
505    }
506    return status;
507}
508
509
510//-----------------------------------------------------------------------------
511android::status_t android_fx_getParam(android::sp<android::AudioEffect> pFx,
512        int32_t param, uint32_t paramSizeMax, void *pValue, uint32_t valueSize)
513{
514    android::status_t status;
515    uint32_t buf32[(paramSizeMax - 1) / sizeof(uint32_t) + 1];
516    effect_param_t *p = (effect_param_t *)buf32;
517
518    p->psize = sizeof(int32_t);
519    *(int32_t *)p->data = param;
520    p->vsize = valueSize;
521    status = pFx->getParameter(p);
522    if (android::NO_ERROR == status) {
523        status = p->status;
524        if (android::NO_ERROR == status) {
525            memcpy(pValue, p->data + p->psize, p->vsize);
526        }
527    }
528
529    return status;
530}
531
532
533//-----------------------------------------------------------------------------
534SLresult android_fx_statusToResult(android::status_t status) {
535
536    if ((android::INVALID_OPERATION == status) || (android::DEAD_OBJECT == status)) {
537        return SL_RESULT_CONTROL_LOST;
538    } else {
539        return SL_RESULT_SUCCESS;
540    }
541}
542
543
544//-----------------------------------------------------------------------------
545bool android_fx_initEffectObj(int sessionId, android::sp<android::AudioEffect>& effect,
546        const effect_uuid_t *type) {
547    SL_LOGV("session %d", sessionId);
548
549    effect = new android::AudioEffect(type, EFFECT_UUID_NULL,
550            0,// priority
551            0,// effect callback
552            0,// callback data
553            sessionId,// session ID
554            0 );// output
555
556    android::status_t status = effect->initCheck();
557    if (android::NO_ERROR != status) {
558        effect.clear();
559        SL_LOGE("Effect initCheck() returned %d", status);
560        return false;
561    }
562
563    return true;
564}
565
566
567//-----------------------------------------------------------------------------
568bool android_fx_initEffectDescriptor(const SLInterfaceID effectId,
569        effect_descriptor_t* fxDescrLoc) {
570    uint32_t numEffects = 0;
571    effect_descriptor_t descriptor;
572    bool foundEffect = false;
573
574    // any effects?
575    android::status_t res = android::AudioEffect::queryNumberEffects(&numEffects);
576    if (android::NO_ERROR != res) {
577        SL_LOGE("unable to find any effects.");
578        goto effectError;
579    }
580
581    // request effect in the effects?
582    for (uint32_t i=0 ; i < numEffects ; i++) {
583        res = android::AudioEffect::queryEffect(i, &descriptor);
584        if ((android::NO_ERROR == res) &&
585                (0 == memcmp(effectId, &descriptor.type, sizeof(effect_uuid_t)))) {
586            SL_LOGV("found effect %d %s", i, descriptor.name);
587            foundEffect = true;
588            break;
589        }
590    }
591    if (foundEffect) {
592        memcpy(fxDescrLoc, &descriptor, sizeof(effect_descriptor_t));
593    } else {
594        SL_LOGE("unable to find an implementation for the requested effect.");
595        goto effectError;
596    }
597
598    return true;
599
600effectError:
601    // the requested effect wasn't found
602    memset(fxDescrLoc, 0, sizeof(effect_descriptor_t));
603
604    return false;
605}
606
607//-----------------------------------------------------------------------------
608SLresult android_genericFx_queryNumEffects(SLuint32 *pNumSupportedAudioEffects) {
609
610    if (NULL == pNumSupportedAudioEffects) {
611        return SL_RESULT_PARAMETER_INVALID;
612    }
613
614    android::status_t status =
615            android::AudioEffect::queryNumberEffects((uint32_t*)pNumSupportedAudioEffects);
616
617    SLresult result = SL_RESULT_SUCCESS;
618    switch(status) {
619        case android::NO_ERROR:
620            result = SL_RESULT_SUCCESS;
621            break;
622        case android::PERMISSION_DENIED:
623            result = SL_RESULT_PERMISSION_DENIED;
624            break;
625        case android::NO_INIT:
626            result = SL_RESULT_RESOURCE_ERROR;
627            break;
628        case android::BAD_VALUE:
629            result = SL_RESULT_PARAMETER_INVALID;
630            break;
631        default:
632            result = SL_RESULT_INTERNAL_ERROR;
633            SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
634            break;
635    }
636    return result;
637}
638
639
640//-----------------------------------------------------------------------------
641SLresult android_genericFx_queryEffect(SLuint32 index, effect_descriptor_t* pDescriptor) {
642
643    if (NULL == pDescriptor) {
644        return SL_RESULT_PARAMETER_INVALID;
645    }
646
647    android::status_t status =
648                android::AudioEffect::queryEffect(index, pDescriptor);
649
650    SLresult result = SL_RESULT_SUCCESS;
651    if (android::NO_ERROR != status) {
652        switch(status) {
653        case android::PERMISSION_DENIED:
654            result = SL_RESULT_PERMISSION_DENIED;
655            break;
656        case android::NO_INIT:
657        case android::INVALID_OPERATION:
658            result = SL_RESULT_RESOURCE_ERROR;
659            break;
660        case android::BAD_VALUE:
661            result = SL_RESULT_PARAMETER_INVALID;
662            break;
663        default:
664            result = SL_RESULT_INTERNAL_ERROR;
665            SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
666            break;
667        }
668        // an error occurred, reset the effect descriptor
669        memset(pDescriptor, 0, sizeof(effect_descriptor_t));
670    }
671
672    return result;
673}
674
675
676//-----------------------------------------------------------------------------
677SLresult android_genericFx_createEffect(IAndroidEffect* iae, SLInterfaceID pUuid, int sessionId) {
678
679    SLresult result = SL_RESULT_SUCCESS;
680
681    // does this effect already exist?
682    if (0 <= iae->mEffects.indexOfKey(KEY_FROM_GUID(pUuid))) {
683        return result;
684    }
685
686    // create new effect
687    android::AudioEffect* pFx = new android::AudioEffect(
688            NULL, // not using type to create effect
689            (const effect_uuid_t*)pUuid,
690            0,// priority
691            0,// effect callback
692            0,// callback data
693            sessionId,
694            0 );// output
695
696    // verify effect was successfully created before storing it
697    android::status_t status = pFx->initCheck();
698    if (android::NO_ERROR != status) {
699        SL_LOGE("AudioEffect initCheck() returned %d, effect will not be stored", status);
700        delete pFx;
701        result = SL_RESULT_RESOURCE_ERROR;
702    } else {
703        SL_LOGV("AudioEffect successfully created on session %d", sessionId);
704        iae->mEffects.add(KEY_FROM_GUID(pUuid), pFx);
705    }
706
707    return result;
708}
709
710
711//-----------------------------------------------------------------------------
712SLresult android_genericFx_releaseEffect(IAndroidEffect* iae, SLInterfaceID pUuid) {
713
714    ssize_t index = iae->mEffects.indexOfKey(KEY_FROM_GUID(pUuid));
715
716    if (0 > index) {
717        return SL_RESULT_PARAMETER_INVALID;
718    } else {
719        android::AudioEffect* pFx = iae->mEffects.valueAt(index);
720        delete pFx;
721        iae->mEffects.removeItem(index);
722        return SL_RESULT_SUCCESS;
723    }
724}
725
726
727//-----------------------------------------------------------------------------
728SLresult android_genericFx_setEnabled(IAndroidEffect* iae, SLInterfaceID pUuid, SLboolean enabled) {
729
730    ssize_t index = iae->mEffects.indexOfKey(KEY_FROM_GUID(pUuid));
731
732    if (0 > index) {
733        return SL_RESULT_PARAMETER_INVALID;
734    } else {
735        android::AudioEffect* pFx = iae->mEffects.valueAt(index);
736        android::status_t status = pFx->setEnabled(SL_BOOLEAN_TRUE == enabled);
737        return android_fx_statusToResult(status);
738    }
739}
740
741
742//-----------------------------------------------------------------------------
743SLresult android_genericFx_isEnabled(IAndroidEffect* iae, SLInterfaceID pUuid, SLboolean *pEnabled)
744{
745    ssize_t index = iae->mEffects.indexOfKey(KEY_FROM_GUID(pUuid));
746
747    if (0 > index) {
748        return SL_RESULT_PARAMETER_INVALID;
749    } else {
750        android::AudioEffect* pFx = iae->mEffects.valueAt(index);
751        *pEnabled = (SLboolean) pFx->getEnabled();
752        return SL_RESULT_SUCCESS;
753    }
754}
755
756
757//-----------------------------------------------------------------------------
758SLresult android_genericFx_sendCommand(IAndroidEffect* iae, SLInterfaceID pUuid,
759        SLuint32 command, SLuint32 commandSize, void* pCommandData,
760        SLuint32 *replySize, void *pReplyData) {
761
762    ssize_t index = iae->mEffects.indexOfKey(KEY_FROM_GUID(pUuid));
763
764    if (0 > index) {
765        return SL_RESULT_PARAMETER_INVALID;
766    } else {
767        android::AudioEffect* pFx = iae->mEffects.valueAt(index);
768        android::status_t status = pFx->command(
769                (uint32_t) command,
770                (uint32_t) commandSize,
771                pCommandData,
772                (uint32_t*)replySize,
773                pReplyData);
774        if (android::BAD_VALUE == status) {
775                return SL_RESULT_PARAMETER_INVALID;
776        } else {
777            return SL_RESULT_SUCCESS;
778        }
779    }
780}
781
782
783