blob: 4628190e0b8669350bb8f20c804311d6848f085d [file] [log] [blame]
/*
* 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.
*/
/* Equalizer implementation */
#include "sles_allinclusive.h"
// FIXME move to platform-specific configuration
#define MAX_EQ_PRESETS 3
static const struct EqualizerBand EqualizerBands[MAX_EQ_BANDS] = {
{1000, 1500, 2000},
{2000, 3000, 4000},
{4000, 5500, 7000},
{7000, 8000, 9000}
};
static const struct EqualizerPreset {
const char *mName;
SLmillibel mLevels[MAX_EQ_BANDS];
} EqualizerPresets[MAX_EQ_PRESETS] = {
{"Default", {0, 0, 0, 0}},
{"Bass", {500, 200, 100, 0}},
{"Treble", {0, 100, 200, 500}}
};
static SLresult IEqualizer_SetEnabled(SLEqualizerItf self, SLboolean enabled)
{
IEqualizer *this = (IEqualizer *) self;
interface_lock_poke(this);
this->mEnabled = enabled;
interface_unlock_poke(this);
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_IsEnabled(SLEqualizerItf self, SLboolean *pEnabled)
{
if (NULL == pEnabled)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
interface_lock_peek(this);
SLboolean enabled = this->mEnabled;
interface_unlock_peek(this);
*pEnabled = enabled;
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_GetNumberOfBands(SLEqualizerItf self, SLuint16 *pNumBands)
{
if (NULL == pNumBands)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
// Note: no lock, but OK because it is const
*pNumBands = this->mNumBands;
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_GetBandLevelRange(SLEqualizerItf self,
SLmillibel *pMin, SLmillibel *pMax)
{
if (NULL == pMin && NULL == pMax)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
// Note: no lock, but OK because it is const
if (NULL != pMin)
*pMin = this->mBandLevelRangeMin;
if (NULL != pMax)
*pMax = this->mBandLevelRangeMax;
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_SetBandLevel(SLEqualizerItf self, SLuint16 band, SLmillibel level)
{
IEqualizer *this = (IEqualizer *) self;
if (band >= this->mNumBands)
return SL_RESULT_PARAMETER_INVALID;
interface_lock_exclusive(this);
this->mLevels[band] = level;
this->mPreset = SL_EQUALIZER_UNDEFINED;
interface_unlock_exclusive(this);
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_GetBandLevel(SLEqualizerItf self, SLuint16 band,
SLmillibel *pLevel)
{
if (NULL == pLevel)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
if (band >= this->mNumBands)
return SL_RESULT_PARAMETER_INVALID;
interface_lock_peek(this);
SLmillibel level = this->mLevels[band];
interface_unlock_peek(this);
*pLevel = level;
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_GetCenterFreq(SLEqualizerItf self, SLuint16 band, SLmilliHertz *pCenter)
{
if (NULL == pCenter)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
if (band >= this->mNumBands)
return SL_RESULT_PARAMETER_INVALID;
// Note: no lock, but OK because it is const
*pCenter = this->mBands[band].mCenter;
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_GetBandFreqRange(SLEqualizerItf self, SLuint16 band,
SLmilliHertz *pMin, SLmilliHertz *pMax)
{
if (NULL == pMin && NULL == pMax)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
if (band >= this->mNumBands)
return SL_RESULT_PARAMETER_INVALID;
// 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;
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_GetBand(SLEqualizerItf self, SLmilliHertz frequency, SLuint16 *pBand)
{
if (NULL == pBand)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
// 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)
// assumes a small number of bands, so no need for a fancier algorithm
const struct EqualizerBand *band;
float floatFreq = (float) frequency;
float bestRatio = 0.0;
SLuint16 bestBand = SL_EQUALIZER_UNDEFINED;
for (band = this->mBands; band < &this->mBands[this->mNumBands]; ++band) {
if (!(band->mMin <= frequency && frequency <= band->mMax))
continue;
assert(band->mMin <= band->mCenter && band->mCenter <= band->mMax);
assert(band->mCenter != 0);
float ratio = frequency <= band->mCenter ?
floatFreq / band->mCenter : band->mCenter / floatFreq;
if (ratio > bestRatio) {
bestRatio = ratio;
bestBand = band - this->mBands;
}
}
*pBand = band - this->mBands;
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_GetCurrentPreset(SLEqualizerItf self,
SLuint16 *pPreset)
{
if (NULL == pPreset)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
interface_lock_shared(this);
SLuint16 preset = this->mPreset;
interface_unlock_shared(this);
*pPreset = preset;
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_UsePreset(SLEqualizerItf self, SLuint16 index)
{
IEqualizer *this = (IEqualizer *) self;
if (index >= this->mNumPresets)
return SL_RESULT_PARAMETER_INVALID;
interface_lock_exclusive(this);
SLuint16 band;
for (band = 0; band < this->mNumBands; ++band)
this->mLevels[band] = EqualizerPresets[index].mLevels[band];
this->mPreset = index;
interface_unlock_exclusive(this);
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_GetNumberOfPresets(SLEqualizerItf self,
SLuint16 *pNumPresets)
{
if (NULL == pNumPresets)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
// Note: no lock, but OK because it is const
*pNumPresets = this->mNumPresets;
return SL_RESULT_SUCCESS;
}
static SLresult IEqualizer_GetPresetName(SLEqualizerItf self, SLuint16 index,
const SLchar ** ppName)
{
if (NULL == ppName)
return SL_RESULT_PARAMETER_INVALID;
IEqualizer *this = (IEqualizer *) self;
if (index >= this->mNumPresets)
return SL_RESULT_PARAMETER_INVALID;
*ppName = (SLchar *) this->mPresets[index].mName;
return SL_RESULT_SUCCESS;
}
static const struct SLEqualizerItf_ IEqualizer_Itf = {
IEqualizer_SetEnabled,
IEqualizer_IsEnabled,
IEqualizer_GetNumberOfBands,
IEqualizer_GetBandLevelRange,
IEqualizer_SetBandLevel,
IEqualizer_GetBandLevel,
IEqualizer_GetCenterFreq,
IEqualizer_GetBandFreqRange,
IEqualizer_GetBand,
IEqualizer_GetCurrentPreset,
IEqualizer_UsePreset,
IEqualizer_GetNumberOfPresets,
IEqualizer_GetPresetName
};
void IEqualizer_init(void *self)
{
IEqualizer *this = (IEqualizer *) self;
this->mItf = &IEqualizer_Itf;
this->mEnabled = SL_BOOLEAN_FALSE;
this->mPreset = SL_EQUALIZER_UNDEFINED;
unsigned band;
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->mBands = EqualizerBands;
this->mPresets = EqualizerPresets;
this->mBandLevelRangeMin = 0;
this->mBandLevelRangeMax = 1000;
}