android_Effect.cpp revision 262059f71a68edc5e510427c63f5f1623d3672a8
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("android_eq_init on 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    object_lock_exclusive(&ieq->mThis->mEngine->mObject);
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    object_unlock_exclusive(&ieq->mThis->mEngine->mObject);
309
310}
311
312
313//-----------------------------------------------------------------------------
314void android_virt_init(int sessionId, IVirtualizer* ivi) {
315    SL_LOGV("android_virt_init on session %d", sessionId);
316
317    if (!android_fx_initEffectObj(sessionId, ivi->mVirtualizerEffect,
318            &ivi->mVirtualizerDescriptor.type)) {
319        SL_LOGE("Virtualizer effect initialization failed");
320        return;
321    }
322
323    // initialize strength
324    int16_t strength;
325    if (android::NO_ERROR == android_virt_getParam(ivi->mVirtualizerEffect,
326            VIRTUALIZER_PARAM_STRENGTH, &strength)) {
327        ivi->mStrength = (SLpermille) strength;
328    }
329}
330
331//-----------------------------------------------------------------------------
332android::status_t android_virt_setParam(android::sp<android::AudioEffect> pFx,
333        int32_t param, void *pValue) {
334
335    return android_fx_setParam(pFx, param, VIRTUALIZER_PARAM_SIZE_MAX,
336            pValue, virt_valueSize(param));
337}
338
339//-----------------------------------------------------------------------------
340android::status_t android_virt_getParam(android::sp<android::AudioEffect> pFx,
341        int32_t param, void *pValue) {
342
343    return android_fx_getParam(pFx, param, VIRTUALIZER_PARAM_SIZE_MAX,
344            pValue, virt_valueSize(param));
345}
346
347
348//-----------------------------------------------------------------------------
349void android_prev_init(IPresetReverb* ipr) {
350    SL_LOGV("session is implicitly %d (aux effect)", android::AudioSystem::SESSION_OUTPUT_MIX);
351
352    if (!android_fx_initEffectObj(android::AudioSystem::SESSION_OUTPUT_MIX /*sessionId*/,
353            ipr->mPresetReverbEffect, &ipr->mPresetReverbDescriptor.type)) {
354        SL_LOGE("PresetReverb effect initialization failed");
355        return;
356    }
357
358    // initialize preset
359    uint16_t preset;
360    if (android::NO_ERROR == android_prev_getPreset(ipr->mPresetReverbEffect, &preset)) {
361        ipr->mPreset = preset;
362        // enable the effect is it has a effective preset loaded
363        ipr->mPresetReverbEffect->setEnabled(SL_REVERBPRESET_NONE != preset);
364    }
365}
366
367//-----------------------------------------------------------------------------
368android::status_t android_prev_setPreset(android::sp<android::AudioEffect> pFx, uint16_t preset) {
369    android::status_t status = android_fx_setParam(pFx, REVERB_PARAM_PRESET, sizeof(uint16_t),
370            &preset, sizeof(uint16_t));
371    // enable the effect if the preset is different from SL_REVERBPRESET_NONE
372    pFx->setEnabled(SL_REVERBPRESET_NONE != preset);
373    return status;
374}
375
376//-----------------------------------------------------------------------------
377android::status_t android_prev_getPreset(android::sp<android::AudioEffect> pFx, uint16_t* preset) {
378    return android_fx_getParam(pFx, REVERB_PARAM_PRESET, sizeof(uint16_t), preset,
379            sizeof(uint16_t));
380}
381
382
383//-----------------------------------------------------------------------------
384void android_erev_init(IEnvironmentalReverb* ier) {
385    SL_LOGV("session is implicitly %d (aux effect)", android::AudioSystem::SESSION_OUTPUT_MIX);
386
387    if (!android_fx_initEffectObj(android::AudioSystem::SESSION_OUTPUT_MIX /*sessionId*/,
388            ier->mEnvironmentalReverbEffect, &ier->mEnvironmentalReverbDescriptor.type)) {
389        SL_LOGE("EnvironmentalReverb effect initialization failed");
390        return;
391    }
392
393    // enable env reverb: other SL ES effects have an explicit SetEnabled() function, and the
394    //  preset reverb state depends on the selected preset.
395    ier->mEnvironmentalReverbEffect->setEnabled(true);
396
397    // initialize reverb properties
398    SLEnvironmentalReverbSettings properties;
399    if (android::NO_ERROR == android_erev_getParam(ier->mEnvironmentalReverbEffect,
400            REVERB_PARAM_PROPERTIES, &properties)) {
401        ier->mProperties = properties;
402    }
403}
404
405//-----------------------------------------------------------------------------
406android::status_t android_erev_setParam(android::sp<android::AudioEffect> pFx,
407        int32_t param, void *pValue) {
408
409    // given the size difference between a single reverb property and the whole set of reverb
410    // properties, select which max size to pass to avoid allocating too much memory
411    if (param == REVERB_PARAM_PROPERTIES) {
412        return android_fx_setParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_ALL,
413                pValue, erev_valueSize(param));
414    } else {
415        return android_fx_setParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_SINGLE,
416                pValue, erev_valueSize(param));
417    }
418}
419
420//-----------------------------------------------------------------------------
421android::status_t android_erev_getParam(android::sp<android::AudioEffect> pFx,
422        int32_t param, void *pValue) {
423
424    // given the size difference between a single reverb property and the whole set of reverb
425    // properties, select which max size to pass to avoid allocating too much memory
426    if (param == REVERB_PARAM_PROPERTIES) {
427        return android_fx_getParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_ALL,
428                pValue, erev_valueSize(param));
429    } else {
430        return android_fx_getParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_SINGLE,
431                pValue, erev_valueSize(param));
432    }
433}
434
435
436//-----------------------------------------------------------------------------
437android::status_t android_fxSend_attach(CAudioPlayer* ap, bool attach,
438        android::sp<android::AudioEffect> pFx, SLmillibel sendLevel) {
439
440    if (pFx == 0) {
441        return android::INVALID_OPERATION;
442    }
443
444    if (NULL == ap->mAudioTrack) {
445        // the player doesn't have an AudioTrack at the moment, so store this info to use it
446        // when the AudioTrack becomes available
447        if (attach) {
448            ap->mAuxEffect = pFx;
449        } else {
450            ap->mAuxEffect.clear();
451        }
452        // we keep track of the send level, independently of the current audio player level
453        ap->mAuxSendLevel = sendLevel - ap->mVolume.mLevel;
454        return android::NO_ERROR;
455    }
456
457    if (attach) {
458        android::status_t status = ap->mAudioTrack->attachAuxEffect(pFx->id());
459        //SL_LOGV("attachAuxEffect(%d) returned %d", pFx->id(), status);
460        if (android::NO_ERROR == status) {
461            status =
462                ap->mAudioTrack->setAuxEffectSendLevel( sles_to_android_amplification(sendLevel) );
463        }
464        return status;
465    } else {
466        return ap->mAudioTrack->attachAuxEffect(0);
467    }
468}
469
470//-----------------------------------------------------------------------------
471/**
472 * pre-condition:
473 *    ap != NULL
474 *    ap->mOutputMix != NULL
475 */
476SLresult android_fxSend_attachToAux(CAudioPlayer* ap, SLInterfaceID pUuid, SLboolean attach,
477        SLmillibel sendLevel) {
478    COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
479    ssize_t index = outputMix->mAndroidEffect.mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
480
481    if (0 > index) {
482        SL_LOGE("invalid effect ID: no such effect attached to the OutputMix");
483        return SL_RESULT_PARAMETER_INVALID;
484    }
485
486    android::AudioEffect* pFx = outputMix->mAndroidEffect.mEffects->valueAt(index);
487    if (NULL == pFx) {
488        return SL_RESULT_RESOURCE_ERROR;
489    }
490    if (android::NO_ERROR == android_fxSend_attach( ap, (bool) attach, pFx, sendLevel) ) {
491        return SL_RESULT_SUCCESS;
492    } else {
493        return SL_RESULT_RESOURCE_ERROR;
494    }
495
496}
497
498//-----------------------------------------------------------------------------
499android::status_t android_fxSend_setSendLevel(CAudioPlayer* ap, SLmillibel sendLevel) {
500    // we keep track of the send level, independently of the current audio player level
501    ap->mAuxSendLevel = sendLevel - ap->mVolume.mLevel;
502
503    if (NULL == ap->mAudioTrack) {
504        return android::NO_ERROR;
505    }
506
507    return ap->mAudioTrack->setAuxEffectSendLevel( sles_to_android_amplification(sendLevel) );
508}
509
510//-----------------------------------------------------------------------------
511android::status_t android_fx_setParam(android::sp<android::AudioEffect> pFx,
512        int32_t param, uint32_t paramSizeMax, void *pValue, uint32_t valueSize)
513{
514
515    android::status_t status;
516    uint32_t buf32[(paramSizeMax - 1) / sizeof(uint32_t) + 1];
517    effect_param_t *p = (effect_param_t *)buf32;
518
519    p->psize = sizeof(int32_t);
520    *(int32_t *)p->data = param;
521    p->vsize = valueSize;
522    memcpy(p->data + p->psize, pValue, p->vsize);
523    status = pFx->setParameter(p);
524    if (android::NO_ERROR == status) {
525        status = p->status;
526    }
527    return status;
528}
529
530
531//-----------------------------------------------------------------------------
532android::status_t android_fx_getParam(android::sp<android::AudioEffect> pFx,
533        int32_t param, uint32_t paramSizeMax, void *pValue, uint32_t valueSize)
534{
535    android::status_t status;
536    uint32_t buf32[(paramSizeMax - 1) / sizeof(uint32_t) + 1];
537    effect_param_t *p = (effect_param_t *)buf32;
538
539    p->psize = sizeof(int32_t);
540    *(int32_t *)p->data = param;
541    p->vsize = valueSize;
542    status = pFx->getParameter(p);
543    if (android::NO_ERROR == status) {
544        status = p->status;
545        if (android::NO_ERROR == status) {
546            memcpy(pValue, p->data + p->psize, p->vsize);
547        }
548    }
549
550    return status;
551}
552
553
554//-----------------------------------------------------------------------------
555SLresult android_fx_statusToResult(android::status_t status) {
556
557    if ((android::INVALID_OPERATION == status) || (android::DEAD_OBJECT == status)) {
558        return SL_RESULT_CONTROL_LOST;
559    } else {
560        return SL_RESULT_SUCCESS;
561    }
562}
563
564
565//-----------------------------------------------------------------------------
566bool android_fx_initEffectObj(int sessionId, android::sp<android::AudioEffect>& effect,
567        const effect_uuid_t *type) {
568    //SL_LOGV("android_fx_initEffectObj on session %d", sessionId);
569
570    effect = new android::AudioEffect(type, EFFECT_UUID_NULL,
571            0,// priority
572            0,// effect callback
573            0,// callback data
574            sessionId,// session ID
575            0 );// output
576
577    android::status_t status = effect->initCheck();
578    if (android::NO_ERROR != status) {
579        effect.clear();
580        SL_LOGE("Effect initCheck() returned %d", status);
581        return false;
582    }
583
584    return true;
585}
586
587
588//-----------------------------------------------------------------------------
589bool android_fx_initEffectDescriptor(const SLInterfaceID effectId,
590        effect_descriptor_t* fxDescrLoc) {
591    uint32_t numEffects = 0;
592    effect_descriptor_t descriptor;
593    bool foundEffect = false;
594
595    // any effects?
596    android::status_t res = android::AudioEffect::queryNumberEffects(&numEffects);
597    if (android::NO_ERROR != res) {
598        SL_LOGE("unable to find any effects.");
599        goto effectError;
600    }
601
602    // request effect in the effects?
603    for (uint32_t i=0 ; i < numEffects ; i++) {
604        res = android::AudioEffect::queryEffect(i, &descriptor);
605        if ((android::NO_ERROR == res) &&
606                (0 == memcmp(effectId, &descriptor.type, sizeof(effect_uuid_t)))) {
607            SL_LOGV("found effect %d %s", i, descriptor.name);
608            foundEffect = true;
609            break;
610        }
611    }
612    if (foundEffect) {
613        memcpy(fxDescrLoc, &descriptor, sizeof(effect_descriptor_t));
614    } else {
615        SL_LOGE("unable to find an implementation for the requested effect.");
616        goto effectError;
617    }
618
619    return true;
620
621effectError:
622    // the requested effect wasn't found
623    memset(fxDescrLoc, 0, sizeof(effect_descriptor_t));
624
625    return false;
626}
627
628//-----------------------------------------------------------------------------
629SLresult android_genericFx_queryNumEffects(SLuint32 *pNumSupportedAudioEffects) {
630
631    if (NULL == pNumSupportedAudioEffects) {
632        return SL_RESULT_PARAMETER_INVALID;
633    }
634
635    android::status_t status =
636            android::AudioEffect::queryNumberEffects((uint32_t*)pNumSupportedAudioEffects);
637
638    SLresult result = SL_RESULT_SUCCESS;
639    switch(status) {
640        case android::NO_ERROR:
641            result = SL_RESULT_SUCCESS;
642            break;
643        case android::PERMISSION_DENIED:
644            result = SL_RESULT_PERMISSION_DENIED;
645            break;
646        case android::NO_INIT:
647            result = SL_RESULT_RESOURCE_ERROR;
648            break;
649        case android::BAD_VALUE:
650            result = SL_RESULT_PARAMETER_INVALID;
651            break;
652        default:
653            result = SL_RESULT_INTERNAL_ERROR;
654            SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
655            break;
656    }
657    return result;
658}
659
660
661//-----------------------------------------------------------------------------
662SLresult android_genericFx_queryEffect(SLuint32 index, effect_descriptor_t* pDescriptor) {
663
664    if (NULL == pDescriptor) {
665        return SL_RESULT_PARAMETER_INVALID;
666    }
667
668    android::status_t status =
669                android::AudioEffect::queryEffect(index, pDescriptor);
670
671    SLresult result = SL_RESULT_SUCCESS;
672    if (android::NO_ERROR != status) {
673        switch(status) {
674        case android::PERMISSION_DENIED:
675            result = SL_RESULT_PERMISSION_DENIED;
676            break;
677        case android::NO_INIT:
678        case android::INVALID_OPERATION:
679            result = SL_RESULT_RESOURCE_ERROR;
680            break;
681        case android::BAD_VALUE:
682            result = SL_RESULT_PARAMETER_INVALID;
683            break;
684        default:
685            result = SL_RESULT_INTERNAL_ERROR;
686            SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
687            break;
688        }
689        // an error occurred, reset the effect descriptor
690        memset(pDescriptor, 0, sizeof(effect_descriptor_t));
691    }
692
693    return result;
694}
695
696
697//-----------------------------------------------------------------------------
698SLresult android_genericFx_createEffect(IAndroidEffect* iae, SLInterfaceID pUuid, int sessionId) {
699
700    SLresult result = SL_RESULT_SUCCESS;
701
702    // does this effect already exist?
703    if (0 <= iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid))) {
704        return result;
705    }
706
707    // create new effect
708    android::AudioEffect* pFx = new android::AudioEffect(
709            NULL, // not using type to create effect
710            (const effect_uuid_t*)pUuid,
711            0,// priority
712            0,// effect callback
713            0,// callback data
714            sessionId,
715            0 );// output
716
717    // verify effect was successfully created before storing it
718    android::status_t status = pFx->initCheck();
719    if (android::NO_ERROR != status) {
720        SL_LOGE("AudioEffect initCheck() returned %d, effect will not be stored", status);
721        delete pFx;
722        result = SL_RESULT_RESOURCE_ERROR;
723    } else {
724        SL_LOGV("AudioEffect successfully created on session %d", sessionId);
725        iae->mEffects->add(KEY_FROM_GUID(pUuid), pFx);
726    }
727
728    return result;
729}
730
731
732//-----------------------------------------------------------------------------
733SLresult android_genericFx_releaseEffect(IAndroidEffect* iae, SLInterfaceID pUuid) {
734
735    ssize_t index = iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
736
737    if (0 > index) {
738        return SL_RESULT_PARAMETER_INVALID;
739    } else {
740        android::AudioEffect* pFx = iae->mEffects->valueAt(index);
741        delete pFx;
742        iae->mEffects->removeItem(index);
743        return SL_RESULT_SUCCESS;
744    }
745}
746
747
748//-----------------------------------------------------------------------------
749SLresult android_genericFx_setEnabled(IAndroidEffect* iae, SLInterfaceID pUuid, SLboolean enabled) {
750
751    ssize_t index = iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
752
753    if (0 > index) {
754        return SL_RESULT_PARAMETER_INVALID;
755    } else {
756        android::AudioEffect* pFx = iae->mEffects->valueAt(index);
757        android::status_t status = pFx->setEnabled(SL_BOOLEAN_TRUE == enabled);
758        return android_fx_statusToResult(status);
759    }
760}
761
762
763//-----------------------------------------------------------------------------
764SLresult android_genericFx_isEnabled(IAndroidEffect* iae, SLInterfaceID pUuid, SLboolean *pEnabled)
765{
766    ssize_t index = iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
767
768    if (0 > index) {
769        return SL_RESULT_PARAMETER_INVALID;
770    } else {
771        android::AudioEffect* pFx = iae->mEffects->valueAt(index);
772        *pEnabled = (SLboolean) pFx->getEnabled();
773        return SL_RESULT_SUCCESS;
774    }
775}
776
777
778//-----------------------------------------------------------------------------
779SLresult android_genericFx_sendCommand(IAndroidEffect* iae, SLInterfaceID pUuid,
780        SLuint32 command, SLuint32 commandSize, void* pCommandData,
781        SLuint32 *replySize, void *pReplyData) {
782
783    ssize_t index = iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
784
785    if (0 > index) {
786        return SL_RESULT_PARAMETER_INVALID;
787    } else {
788        android::AudioEffect* pFx = iae->mEffects->valueAt(index);
789        android::status_t status = pFx->command(
790                (uint32_t) command,
791                (uint32_t) commandSize,
792                pCommandData,
793                (uint32_t*)replySize,
794                pReplyData);
795        if (android::BAD_VALUE == status) {
796                return SL_RESULT_PARAMETER_INVALID;
797        } else {
798            return SL_RESULT_SUCCESS;
799        }
800    }
801}
802
803//-----------------------------------------------------------------------------
804/**
805 * returns true if the given effect id is present in the AndroidEffect interface
806 */
807bool android_genericFx_hasEffect(IAndroidEffect* iae, SLInterfaceID pUuid) {
808    return( 0 <= iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid)));
809}
810