OSDN Git Service

Use the AudioEffect framework to implement SLEqualizerItf.
authorJean-Michel Trivi <jmtrivi@google.com>
Fri, 9 Jul 2010 20:35:02 +0000 (13:35 -0700)
committerJean-Michel Trivi <jmtrivi@google.com>
Thu, 15 Jul 2010 17:51:30 +0000 (10:51 -0700)
EQ presets are stored in the engine because they need to be
available during the duration of the application, not just
during the life of the AudioPlayer that uses EQ.
Change-Id: Ib55ce32b54a4dca134831a87bc5bd2ae8c111035

opensles/libopensles/Android.mk
opensles/libopensles/CEngine.c
opensles/libopensles/IEngine.c
opensles/libopensles/IEqualizer.c
opensles/libopensles/android_Effect.cpp [new file with mode: 0644]
opensles/libopensles/android_Effect.h [new file with mode: 0644]
opensles/libopensles/sles_allinclusive.h
opensles/libopensles/sles_to_android.cpp

index 6fc2549..63f96cb 100644 (file)
@@ -38,6 +38,7 @@ LOCAL_SRC_FILES:=                     \
         sles.c                        \
         sles_to_android.cpp           \
         android_SfPlayer.cpp          \
+        android_Effect.cpp            \
         sync.c                        \
         IID_to_MPH.c                  \
         ThreadPool.c                  \
index cb48a70..f1556f4 100644 (file)
@@ -49,9 +49,22 @@ void CEngine_Destroy(void *self)
 {
     CEngine *this = (CEngine *) self;
     this->mEngine.mShutdown = SL_BOOLEAN_TRUE;
+#ifdef ANDROID
+    // free effect data
+    //   free EQ data
+    if ((0 < this->mEngine.mEqNumPresets) && (NULL != this->mEngine.mEqPresetNames)) {
+        for(uint32_t i = 0 ; i < this->mEngine.mEqNumPresets ; i++) {
+            if (NULL != this->mEngine.mEqPresetNames[i]) {
+                delete [] this->mEngine.mEqPresetNames[i];
+            }
+        }
+        delete [] this->mEngine.mEqPresetNames;
+    }
+#endif
     while (!this->mEngine.mShutdownAck)
         pthread_cond_wait(&this->mEngine.mShutdownCond, &this->mObject.mMutex);
     object_unlock_exclusive(&this->mObject);
     (void) pthread_join(this->mSyncThread, (void **) NULL);
     ThreadPool_deinit(&this->mEngine.mThreadPool);
+
 }
index 04410cf..feff833 100644 (file)
@@ -582,4 +582,8 @@ void IEngine_init(void *self)
     int ok;
     ok = pthread_cond_init(&this->mShutdownCond, (const pthread_condattr_t *) NULL);
     assert(0 == ok);
+#ifdef ANDROID
+    this->mEqNumPresets = 0;
+    this->mEqPresetNames = NULL;
+#endif
 }
index 6c8122a..90d5467 100644 (file)
@@ -22,6 +22,8 @@
 
 #define MAX_EQ_PRESETS 3
 
+#ifndef ANDROID
+// FIXME needs to be defined in a platform-dependent manner
 static const struct EqualizerBand EqualizerBands[MAX_EQ_BANDS] = {
     {1000, 1500, 2000},
     {2000, 3000, 4000},
@@ -37,6 +39,7 @@ static const struct EqualizerPreset {
     {"Bass", {500, 200, 100, 0}},
     {"Treble", {0, 100, 200, 500}}
 };
+#endif
 
 
 static SLresult IEqualizer_SetEnabled(SLEqualizerItf self, SLboolean enabled)
@@ -44,10 +47,23 @@ static SLresult IEqualizer_SetEnabled(SLEqualizerItf self, SLboolean enabled)
     SL_ENTER_INTERFACE
 
     IEqualizer *this = (IEqualizer *) self;
-    interface_lock_poke(this);
+    interface_lock_exclusive(this);
     this->mEnabled = SL_BOOLEAN_FALSE != enabled; // normalize
-    interface_unlock_poke(this);
+#ifndef ANDROID
     result = SL_RESULT_SUCCESS;
+#else
+    bool fxEnabled = this->mEqEffect->getEnabled();
+    // the audio effect framework will return an error if you set the same "enabled" state as
+    // the one the effect is currently in, so we only act on state changes
+    if (fxEnabled != (enabled == SL_BOOLEAN_TRUE)) {
+        // state change
+        android::status_t status = this->mEqEffect->setEnabled(this->mEnabled == SL_BOOLEAN_TRUE);
+        result = android_fx_statusToResult(status);
+    } else {
+        result = SL_RESULT_SUCCESS;
+    }
+#endif
+    interface_unlock_exclusive(this);
 
     SL_LEAVE_INTERFACE
 }
@@ -61,11 +77,17 @@ static SLresult IEqualizer_IsEnabled(SLEqualizerItf self, SLboolean *pEnabled)
         result = SL_RESULT_PARAMETER_INVALID;
     } else {
         IEqualizer *this = (IEqualizer *) self;
-        interface_lock_peek(this);
+        interface_lock_shared(this);
         SLboolean enabled = this->mEnabled;
-        interface_unlock_peek(this);
+        interface_unlock_shared(this);
+#ifndef ANDROID
         *pEnabled = enabled;
         result = SL_RESULT_SUCCESS;
+#else
+        bool fxEnabled = this->mEqEffect->getEnabled();
+        *pEnabled = fxEnabled ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE;
+        result = SL_RESULT_SUCCESS;
+#endif
     }
 
     SL_LEAVE_INTERFACE
@@ -116,14 +138,20 @@ static SLresult IEqualizer_SetBandLevel(SLEqualizerItf self, SLuint16 band, SLmi
 
     IEqualizer *this = (IEqualizer *) self;
     if (!(this->mBandLevelRangeMin <= level && level <= this->mBandLevelRangeMax) ||
-        (band >= this->mNumBands)) {
+            (band >= this->mNumBands)) {
         result = SL_RESULT_PARAMETER_INVALID;
     } else {
         interface_lock_exclusive(this);
+#ifndef ANDROID
         this->mLevels[band] = level;
         this->mPreset = SL_EQUALIZER_UNDEFINED;
-        interface_unlock_exclusive(this);
         result = SL_RESULT_SUCCESS;
+#else
+        android::status_t status =
+                android_eq_setParam(this->mEqEffect, EQ_PARAM_BAND_LEVEL, band, &level);
+        result = android_fx_statusToResult(status);
+#endif
+        interface_unlock_exclusive(this);
     }
 
     SL_LEAVE_INTERFACE
@@ -142,11 +170,18 @@ static SLresult IEqualizer_GetBandLevel(SLEqualizerItf self, SLuint16 band, SLmi
         if (band >= this->mNumBands) {
             result = SL_RESULT_PARAMETER_INVALID;
         } else {
-            interface_lock_peek(this);
-            SLmillibel level = this->mLevels[band];
-            interface_unlock_peek(this);
-            *pLevel = level;
+            SLmillibel level;
+            interface_lock_shared(this);
+#ifndef ANDROID
+            level = this->mLevels[band];
             result = SL_RESULT_SUCCESS;
+#else
+            android::status_t status =
+                    android_eq_getParam(this->mEqEffect, EQ_PARAM_BAND_LEVEL, band, &level);
+            result = android_fx_statusToResult(status);
+#endif
+            interface_unlock_shared(this);
+            *pLevel = level;
         }
     }
 
@@ -165,9 +200,19 @@ static SLresult IEqualizer_GetCenterFreq(SLEqualizerItf self, SLuint16 band, SLm
         if (band >= this->mNumBands) {
             result = SL_RESULT_PARAMETER_INVALID;
         } else {
+#ifndef ANDROID
             // Note: no lock, but OK because it is const
             *pCenter = this->mBands[band].mCenter;
             result = SL_RESULT_SUCCESS;
+#else
+            SLmilliHertz center;
+            interface_lock_shared(this);
+            android::status_t status =
+                    android_eq_getParam(this->mEqEffect, EQ_PARAM_CENTER_FREQ, band, &center);
+            interface_unlock_shared(this);
+            result = android_fx_statusToResult(status);
+            *pCenter = center;
+#endif
         }
     }
 
@@ -187,12 +232,27 @@ static SLresult IEqualizer_GetBandFreqRange(SLEqualizerItf self, SLuint16 band,
         if (band >= this->mNumBands) {
             result = SL_RESULT_PARAMETER_INVALID;
         } else {
+#ifndef ANDROID
             // Note: no lock, but OK because it is const
             if (NULL != pMin)
                 *pMin = this->mBands[band].mMin;
             if (NULL != pMax)
                 *pMax = this->mBands[band].mMax;
             result = SL_RESULT_SUCCESS;
+#else
+            SLmilliHertz range[2]; // SLmilliHertz is SLuint32
+            interface_lock_shared(this);
+            android::status_t status =
+                    android_eq_getParam(this->mEqEffect, EQ_PARAM_BAND_FREQ_RANGE, band, range);
+            interface_unlock_shared(this);
+            result = android_fx_statusToResult(status);
+            if (NULL != pMin) {
+                *pMin = range[0];
+            }
+            if (NULL != pMax) {
+                *pMax = range[1];
+            }
+#endif
         }
     }
 
@@ -208,6 +268,7 @@ static SLresult IEqualizer_GetBand(SLEqualizerItf self, SLmilliHertz frequency,
         result = SL_RESULT_PARAMETER_INVALID;
     } else {
         IEqualizer *this = (IEqualizer *) self;
+#ifndef ANDROID
         // search for band whose center frequency has the closest ratio to 1.0
         // assumes bands are unsorted (a pessimistic assumption)
         // assumes bands can overlap (a pessimistic assumption)
@@ -230,6 +291,15 @@ static SLresult IEqualizer_GetBand(SLEqualizerItf self, SLmilliHertz frequency,
         }
         *pBand = band - this->mBands;
         result = SL_RESULT_SUCCESS;
+#else
+        uint32_t band;
+        interface_lock_shared(this);
+        android::status_t status =
+            android_eq_getParam(this->mEqEffect, EQ_PARAM_GET_BAND, frequency, &band);
+        interface_unlock_shared(this);
+        result = android_fx_statusToResult(status);
+        *pBand = (SLuint16)band;
+#endif
     }
 
     SL_LEAVE_INTERFACE
@@ -245,10 +315,24 @@ static SLresult IEqualizer_GetCurrentPreset(SLEqualizerItf self, SLuint16 *pPres
     } else {
         IEqualizer *this = (IEqualizer *) self;
         interface_lock_shared(this);
+#ifndef ANDROID
         SLuint16 preset = this->mPreset;
         interface_unlock_shared(this);
         *pPreset = preset;
         result = SL_RESULT_SUCCESS;
+#else
+        int32_t preset;
+        android::status_t status =
+                android_eq_getParam(this->mEqEffect, EQ_PARAM_CUR_PRESET, 0, &preset);
+        interface_unlock_shared(this);
+        result = android_fx_statusToResult(status);
+        if (preset < 0) {
+            *pPreset = SL_EQUALIZER_UNDEFINED;
+        } else {
+            *pPreset = (SLuint16) preset;
+        }
+#endif
+
     }
 
     SL_LEAVE_INTERFACE
@@ -264,12 +348,20 @@ static SLresult IEqualizer_UsePreset(SLEqualizerItf self, SLuint16 index)
         result = SL_RESULT_PARAMETER_INVALID;
     } else {
         interface_lock_exclusive(this);
+#ifndef ANDROID
         SLuint16 band;
         for (band = 0; band < this->mNumBands; ++band)
             this->mLevels[band] = EqualizerPresets[index].mLevels[band];
         this->mPreset = index;
         interface_unlock_exclusive(this);
         result = SL_RESULT_SUCCESS;
+#else
+        int32_t preset = index;
+        android::status_t status =
+                android_eq_setParam(this->mEqEffect, EQ_PARAM_CUR_PRESET, 0, &preset);
+        interface_unlock_shared(this);
+        result = android_fx_statusToResult(status);
+#endif
     }
 
     SL_LEAVE_INTERFACE
@@ -285,7 +377,11 @@ static SLresult IEqualizer_GetNumberOfPresets(SLEqualizerItf self, SLuint16 *pNu
     } else {
         IEqualizer *this = (IEqualizer *) self;
         // Note: no lock, but OK because it is const
+#ifndef ANDROID
         *pNumPresets = this->mNumPresets;
+#else
+        *pNumPresets = this->mThis->mEngine->mEqNumPresets;
+#endif
         result = SL_RESULT_SUCCESS;
     }
 
@@ -301,12 +397,23 @@ static SLresult IEqualizer_GetPresetName(SLEqualizerItf self, SLuint16 index, co
         result = SL_RESULT_PARAMETER_INVALID;
     } else {
         IEqualizer *this = (IEqualizer *) self;
+#ifndef ANDROID
         if (index >= this->mNumPresets) {
             result = SL_RESULT_PARAMETER_INVALID;
         } else {
             *ppName = (SLchar *) this->mPresets[index].mName;
             result = SL_RESULT_SUCCESS;
         }
+#else
+        if (index >= this->mThis->mEngine->mEqNumPresets) {
+            result = SL_RESULT_PARAMETER_INVALID;
+        } else {
+            // FIXME This gives the application access to the library memory space and is
+            //  identified as a security issue. This is being addressed by the OpenSL ES WG
+            *ppName = (SLchar *) this->mThis->mEngine->mEqPresetNames[index];
+            result = SL_RESULT_SUCCESS;
+        }
+#endif
     }
 
     SL_LEAVE_INTERFACE
@@ -339,10 +446,50 @@ void IEqualizer_init(void *self)
     for (band = 0; band < MAX_EQ_BANDS; ++band)
         this->mLevels[band] = 0;
     // const fields
-    this->mNumPresets = MAX_EQ_PRESETS;
-    this->mNumBands = MAX_EQ_BANDS;
+    this->mNumPresets = 0;
+    this->mNumBands = 0;
+#ifndef ANDROID
     this->mBands = EqualizerBands;
     this->mPresets = EqualizerPresets;
+#endif
+    this->mBandLevelRangeMin = 0;
+    this->mBandLevelRangeMax = 0;
+
+#ifdef ANDROID
+    // Initialize the EQ settings based on the platform effect, if available
+    uint32_t numEffects = 0;
+    effect_descriptor_t descriptor;
+    bool foundEq = false;
+    //   any effects?
+    android::status_t res = android::AudioEffect::queryNumberEffects(&numEffects);
+    if (android::NO_ERROR != res) {
+        SL_LOGE("IEqualizer_init: unable to find any effects.");
+        goto effectError;
+    }
+    //   EQ in the effects?
+    for (uint32_t i=0 ; i < numEffects ; i++) {
+        res = android::AudioEffect::queryEffect(i, &descriptor);
+        if ((android::NO_ERROR == res) &&
+                (0 == memcmp(SL_IID_EQUALIZER, &descriptor.type, sizeof(effect_uuid_t)))) {
+            SL_LOGV("found effect %d %s", i, descriptor.name);
+            foundEq = true;
+            break;
+        }
+    }
+    if (foundEq) {
+        memcpy(&this->mEqDescriptor, &descriptor, sizeof(effect_descriptor_t));
+    } else {
+        SL_LOGE("IEqualizer_init: unable to find an EQ implementation.");
+        goto effectError;
+    }
+
+    return;
+
+effectError:
+    this->mNumPresets = 0;
+    this->mNumBands = 0;
     this->mBandLevelRangeMin = 0;
-    this->mBandLevelRangeMax = 1000;
+    this->mBandLevelRangeMax = 0;
+    memset(&this->mEqDescriptor, 0, sizeof(effect_descriptor_t));
+#endif
 }
diff --git a/opensles/libopensles/android_Effect.cpp b/opensles/libopensles/android_Effect.cpp
new file mode 100644 (file)
index 0000000..3996709
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "sles_allinclusive.h"
+#include "math.h"
+#include "utils/RefBase.h"
+
+
+static const int EQUALIZER_PARAM_SIZE_MAX = sizeof(effect_param_t) + 2 * sizeof(int32_t)
+        + EFFECT_STRING_LEN_MAX;
+
+
+//-----------------------------------------------------------------------------
+uint32_t eq_paramSize(int32_t param)
+{
+    uint32_t size;
+
+    switch (param) {
+    case EQ_PARAM_NUM_BANDS:
+    case EQ_PARAM_LEVEL_RANGE:
+    case EQ_PARAM_CUR_PRESET:
+    case EQ_PARAM_GET_NUM_OF_PRESETS:
+        size = sizeof(int32_t);
+        break;
+    case EQ_PARAM_BAND_LEVEL:
+    case EQ_PARAM_CENTER_FREQ:
+    case EQ_PARAM_BAND_FREQ_RANGE:
+    case EQ_PARAM_GET_BAND:
+    case EQ_PARAM_GET_PRESET_NAME:
+        size = 2 * sizeof(int32_t);
+        break;
+    default:
+        size = 2 * sizeof(int32_t);
+        SL_LOGE("Trying to use an unknown EQ parameter %d", param);
+        break;
+    }
+    return size;
+}
+
+uint32_t eq_valueSize(int32_t param)
+{
+    uint32_t size;
+
+    switch (param) {
+    case EQ_PARAM_NUM_BANDS:
+    case EQ_PARAM_CUR_PRESET:
+    case EQ_PARAM_GET_NUM_OF_PRESETS:
+        size = sizeof(int16_t);
+        break;
+    case EQ_PARAM_BAND_LEVEL:
+    case EQ_PARAM_GET_BAND:
+    case EQ_PARAM_CENTER_FREQ:
+        size = sizeof(int32_t);
+        break;
+    case EQ_PARAM_LEVEL_RANGE:
+    case EQ_PARAM_BAND_FREQ_RANGE:
+        size = 2 * sizeof(int32_t);
+        break;
+    case EQ_PARAM_GET_PRESET_NAME:
+        size = EFFECT_STRING_LEN_MAX;
+        break;
+    default:
+        size = sizeof(int32_t);
+        SL_LOGE("Trying to access an unknown EQ parameter %d", param);
+        break;
+    }
+    return size;
+}
+
+
+//-----------------------------------------------------------------------------
+android::status_t android_eq_getParam(android::sp<android::AudioEffect> pFx,
+        int32_t param, int32_t param2, void *pValue)
+{
+     android::status_t status;
+     uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1];
+     effect_param_t *p = (effect_param_t *)buf32;
+
+     p->psize = eq_paramSize(param);
+     *(int32_t *)p->data = param;
+     if (p->psize == 2 * sizeof(int32_t)) {
+         *((int32_t *)p->data + 1) = param2;
+     }
+     p->vsize = eq_valueSize(param);
+     status = pFx->getParameter(p);
+     if (android::NO_ERROR == status) {
+         status = p->status;
+         if (android::NO_ERROR == status) {
+             memcpy(pValue, p->data + p->psize, p->vsize);
+         }
+     }
+
+     return status;
+ }
+
+
+//-----------------------------------------------------------------------------
+android::status_t android_eq_setParam(android::sp<android::AudioEffect> pFx,
+        int32_t param, int32_t param2, void *pValue)
+{
+    android::status_t status;
+    uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1];
+    effect_param_t *p = (effect_param_t *)buf32;
+
+    p->psize = eq_paramSize(param);
+    *(int32_t *)p->data = param;
+    if (p->psize == 2 * sizeof(int32_t)) {
+        *((int32_t *)p->data + 1) = param2;
+    }
+    p->vsize = eq_valueSize(param);
+    memcpy(p->data + p->psize, pValue, p->vsize);
+    status = pFx->setParameter(p);
+    if (android::NO_ERROR == status) {
+        status = p->status;
+    }
+
+    return status;
+}
+
+
+//-----------------------------------------------------------------------------
+void android_eq_init(int sessionId, CAudioPlayer* ap) {
+    SL_LOGV("android_initEq on session %d", sessionId);
+
+    ap->mEqualizer.mEqEffect = new android::AudioEffect(
+            &ap->mEqualizer.mEqDescriptor.type,//(const effect_uuid_t*)SL_IID_EQUALIZER,//
+            &ap->mEqualizer.mEqDescriptor.uuid,
+            0,// priority
+            0,// effect callback
+            0,// callback data
+            sessionId,// session ID
+            0 );// output
+    android::status_t status = ap->mEqualizer.mEqEffect->initCheck();
+    if (android::NO_ERROR != status) {
+        SL_LOGE("EQ initCheck() returned %d", status);
+        return;
+    }
+
+    // initialize number of bands, band level range
+    uint32_t num = 0;
+    if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect,
+            EQ_PARAM_NUM_BANDS, 0, &num)) {
+        ap->mEqualizer.mNumBands = num;
+    }
+    int32_t range[2] = {0, 0};
+    if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect,
+            EQ_PARAM_LEVEL_RANGE, 0, range)) {
+        ap->mEqualizer.mBandLevelRangeMin = range[0];
+        ap->mEqualizer.mBandLevelRangeMax = range[1];
+    }
+
+    SL_LOGV(" EQ init: num presets = %u, band range=[%d %d]mB", num, range[0], range[1]);
+
+    // initialize preset number and names, store in IEngine
+    uint32_t numPresets = 0;
+    if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect,
+            EQ_PARAM_GET_NUM_OF_PRESETS, 0, &numPresets)) {
+        ap->mObject.mEngine->mEqNumPresets = numPresets;
+    }
+    char name[EFFECT_STRING_LEN_MAX];
+    if ((0 < numPresets) && (NULL == ap->mObject.mEngine->mEqPresetNames)) {
+        ap->mObject.mEngine->mEqPresetNames = (char **)new char *[numPresets];
+        for(uint32_t i = 0 ; i < numPresets ; i++) {
+            if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect,
+                    EQ_PARAM_GET_PRESET_NAME, i, name)) {
+                ap->mObject.mEngine->mEqPresetNames[i] = new char[strlen(name) + 1];
+                strcpy(ap->mObject.mEngine->mEqPresetNames[i], name);
+                SL_LOGV(" EQ init: presets = %u is %s", i, ap->mObject.mEngine->mEqPresetNames[i]);
+            }
+
+        }
+    }
+#if 0
+    // configure the EQ so it can easily be heard, for test only
+    uint32_t freq = 1977;
+    uint32_t frange[2];
+    int32_t value = ap->mEqualizer.mBandLevelRangeMin;
+    for(int32_t i=0 ; i< ap->mEqualizer.mNumBands ; i++) {
+        android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, i, &value);
+        // display EQ characteristics
+        android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_CENTER_FREQ, i, &freq);
+        android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_FREQ_RANGE, i, frange);
+        SL_LOGV(" EQ init: band %d = %d - %d - %dHz\n", i, frange[0]/1000, freq/1000,
+                frange[1]/1000);
+    }
+    value = ap->mEqualizer.mBandLevelRangeMax;
+    if (ap->mEqualizer.mNumBands > 2) {
+        android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 2, &value);
+    }
+    if (ap->mEqualizer.mNumBands > 3) {
+        android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 3, &value);
+    }
+
+    ap->mEqualizer.mEqEffect->setEnabled(true);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+SLresult android_fx_statusToResult(android::status_t status) {
+
+    if ((android::INVALID_OPERATION == status) || (android::DEAD_OBJECT == status)) {
+        return SL_RESULT_CONTROL_LOST;
+    } else {
+        return SL_RESULT_SUCCESS;
+    }
+}
+
diff --git a/opensles/libopensles/android_Effect.h b/opensles/libopensles/android_Effect.h
new file mode 100644 (file)
index 0000000..77ca60a
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+extern void android_eq_init(int sessionId, CAudioPlayer* ap);
+
+extern android::status_t android_eq_setParam(android::sp<android::AudioEffect> pFx,
+        int32_t param, int32_t param2, void *pValue);
+
+extern android::status_t android_eq_getParam(android::sp<android::AudioEffect> pFx,
+        int32_t param, int32_t param2, void *pValue);
+
+extern SLresult android_fx_statusToResult(android::status_t status);
index 79aaa14..086be66 100644 (file)
@@ -49,10 +49,14 @@ typedef struct COutputMix_struct COutputMix;
 #include "media/AudioSystem.h"
 #include "media/AudioTrack.h"
 #include "media/mediaplayer.h"
+#include "media/AudioEffect.h"
+#include "media/EffectApi.h"
+#include "media/EffectEqualizerApi.h"
 #include <utils/String8.h>
 #define ANDROID_SL_MILLIBEL_MAX 0
 #include <binder/ProcessState.h>
 #include "android_SfPlayer.h"
+#include "android_Effect.h"
 #endif
 
 #define STEREO_CHANNELS 2
@@ -474,6 +478,10 @@ typedef struct Engine_interface {
     SLboolean mShutdownAck;
     pthread_cond_t mShutdownCond;
     ThreadPool mThreadPool; // for asynchronous operations
+#ifdef ANDROID
+    SLuint32 mEqNumPresets;
+    char** mEqPresetNames;
+#endif
 } IEngine;
 
 typedef struct {
@@ -497,7 +505,11 @@ struct EqualizerBand {
     SLmilliHertz mMax;
 };
 
+#ifdef ANDROID
+#define MAX_EQ_BANDS 0
+#else
 #define MAX_EQ_BANDS 4  // compile-time limit, runtime limit may be smaller
+#endif
 
 typedef struct {
     const struct SLEqualizerItf_ *mItf;
@@ -512,6 +524,10 @@ typedef struct {
     const struct EqualizerPreset *mPresets;
     SLmillibel mBandLevelRangeMin;
     SLmillibel mBandLevelRangeMax;
+#ifdef ANDROID
+    effect_descriptor_t mEqDescriptor;
+    android::sp<android::AudioEffect> mEqEffect;
+#endif
 } IEqualizer;
 
 #define MAX_LED_COUNT 32
index 63f8d41..8c1320d 100644 (file)
@@ -736,6 +736,18 @@ SLresult sles_to_android_audioPlayerRealize(CAudioPlayer *pAudioPlayer, SLboolea
         result = SL_RESULT_CONTENT_UNSUPPORTED;
     }
 
+    int sessionId = pAudioPlayer->mAudioTrack->getSessionId();
+    // initialize EQ
+    // FIXME use a table of effect descriptors when adding support for more effects
+    if (memcmp(SL_IID_EQUALIZER, &pAudioPlayer->mEqualizer.mEqDescriptor.type,
+            sizeof(effect_uuid_t)) == 0) {
+                android_eq_init(sessionId, pAudioPlayer);
+    }
+    // initialize BassBoost
+    // initialize PresetReverb
+    // initialize EnvironmentalReverb + EffectSend
+    // initialize Virtualizer
+
     return result;
 }
 
@@ -755,6 +767,7 @@ SLresult sles_to_android_audioPlayerSetStreamType_l(CAudioPlayer *pAudioPlayer,
     }
 
     int format =  pAudioPlayer->mAudioTrack->format();
+    int sessionId = pAudioPlayer->mAudioTrack->getSessionId();
     uint32_t sr = sles_to_android_sampleRate(pAudioPlayer->mSampleRateMilliHz);
 
     pAudioPlayer->mAudioTrack->stop();
@@ -771,7 +784,8 @@ SLresult sles_to_android_audioPlayerSetStreamType_l(CAudioPlayer *pAudioPlayer,
                     pAudioPlayer->mAndroidObjType == MEDIAPLAYER ?  // callback
                             android_uriAudioTrackCallback : android_pullAudioTrackCallback,
                     (void *) pAudioPlayer,                          // user
-                    0);  // FIXME find appropriate frame count      // notificationFrame
+                    0,   // FIXME find appropriate frame count      // notificationFrame
+                    sessionId);
     if (pAudioPlayer->mAndroidObjType == MEDIAPLAYER) {
         pAudioPlayer->mSfPlayer->useAudioTrack(pAudioPlayer->mAudioTrack);
     }
@@ -818,6 +832,8 @@ SLresult sles_to_android_audioPlayerDestroy(CAudioPlayer *pAudioPlayer) {
 
     pAudioPlayer->mAndroidObjType = INVALID_TYPE;
 
+    pAudioPlayer->mEqualizer.mEqEffect.clear();
+
     return result;
 }