From 1f5702ed2239c79b701aa8cc3c675798b34a9656 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Fri, 9 Jul 2010 13:35:02 -0700 Subject: [PATCH] Use the AudioEffect framework to implement SLEqualizerItf. 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 | 1 + opensles/libopensles/CEngine.c | 13 ++ opensles/libopensles/IEngine.c | 4 + opensles/libopensles/IEqualizer.c | 173 ++++++++++++++++++++++-- opensles/libopensles/android_Effect.cpp | 221 +++++++++++++++++++++++++++++++ opensles/libopensles/android_Effect.h | 26 ++++ opensles/libopensles/sles_allinclusive.h | 16 +++ opensles/libopensles/sles_to_android.cpp | 18 ++- 8 files changed, 458 insertions(+), 14 deletions(-) create mode 100644 opensles/libopensles/android_Effect.cpp create mode 100644 opensles/libopensles/android_Effect.h diff --git a/opensles/libopensles/Android.mk b/opensles/libopensles/Android.mk index 6fc2549b..63f96cbd 100644 --- a/opensles/libopensles/Android.mk +++ b/opensles/libopensles/Android.mk @@ -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 \ diff --git a/opensles/libopensles/CEngine.c b/opensles/libopensles/CEngine.c index cb48a701..f1556f42 100644 --- a/opensles/libopensles/CEngine.c +++ b/opensles/libopensles/CEngine.c @@ -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); + } diff --git a/opensles/libopensles/IEngine.c b/opensles/libopensles/IEngine.c index 04410cf4..feff8339 100644 --- a/opensles/libopensles/IEngine.c +++ b/opensles/libopensles/IEngine.c @@ -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 } diff --git a/opensles/libopensles/IEqualizer.c b/opensles/libopensles/IEqualizer.c index 6c8122a2..90d5467a 100644 --- a/opensles/libopensles/IEqualizer.c +++ b/opensles/libopensles/IEqualizer.c @@ -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, ¢er); + 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 index 00000000..3996709b --- /dev/null +++ b/opensles/libopensles/android_Effect.cpp @@ -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 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 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 index 00000000..77ca60a5 --- /dev/null +++ b/opensles/libopensles/android_Effect.h @@ -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 pFx, + int32_t param, int32_t param2, void *pValue); + +extern android::status_t android_eq_getParam(android::sp pFx, + int32_t param, int32_t param2, void *pValue); + +extern SLresult android_fx_statusToResult(android::status_t status); diff --git a/opensles/libopensles/sles_allinclusive.h b/opensles/libopensles/sles_allinclusive.h index 79aaa144..086be66b 100644 --- a/opensles/libopensles/sles_allinclusive.h +++ b/opensles/libopensles/sles_allinclusive.h @@ -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 #define ANDROID_SL_MILLIBEL_MAX 0 #include #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 mEqEffect; +#endif } IEqualizer; #define MAX_LED_COUNT 32 diff --git a/opensles/libopensles/sles_to_android.cpp b/opensles/libopensles/sles_to_android.cpp index 63f8d412..8c1320d6 100644 --- a/opensles/libopensles/sles_to_android.cpp +++ b/opensles/libopensles/sles_to_android.cpp @@ -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; } -- 2.11.0