IEqualizer.cpp revision e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037
1a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten/*
2a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * Copyright (C) 2010 The Android Open Source Project
3a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten *
4a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * you may not use this file except in compliance with the License.
6a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * You may obtain a copy of the License at
7a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten *
8a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten *
10a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * Unless required by applicable law or agreed to in writing, software
11a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * See the License for the specific language governing permissions and
14a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten * limitations under the License.
15a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten */
16a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
17a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten/* Equalizer implementation */
18a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
19a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten#include "sles_allinclusive.h"
20a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
213a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten// FIXME move to platform-specific configuration
220b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
233a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten#define MAX_EQ_PRESETS 3
243a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten
253a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic const struct EqualizerBand EqualizerBands[MAX_EQ_BANDS] = {
260b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    {1000, 1500, 2000},
270b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    {2000, 3000, 4000},
280b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    {4000, 5500, 7000},
290b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    {7000, 8000, 9000}
300b167267bda99b68346045ccab14e810121d5de4Glenn Kasten};
310b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
323a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic const struct EqualizerPreset {
333a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    const char *mName;
343a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    SLmillibel mLevels[MAX_EQ_BANDS];
353a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten} EqualizerPresets[MAX_EQ_PRESETS] = {
363a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    {"Default", {0, 0, 0, 0}},
373a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    {"Bass", {500, 200, 100, 0}},
383a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    {"Treble", {0, 100, 200, 500}}
390b167267bda99b68346045ccab14e810121d5de4Glenn Kasten};
400b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
41a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic SLresult IEqualizer_SetEnabled(SLEqualizerItf self, SLboolean enabled)
42a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
43a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
44a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    interface_lock_poke(this);
45d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    this->mEnabled = SL_BOOLEAN_FALSE != enabled; // normalize
46a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    interface_unlock_poke(this);
47a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
48a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
49a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
50a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic SLresult IEqualizer_IsEnabled(SLEqualizerItf self, SLboolean *pEnabled)
51a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
52a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == pEnabled)
53a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
54a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
55a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    interface_lock_peek(this);
56a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    SLboolean enabled = this->mEnabled;
57a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    interface_unlock_peek(this);
58a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    *pEnabled = enabled;
59a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
60a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
61a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
623a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IEqualizer_GetNumberOfBands(SLEqualizerItf self, SLuint16 *pNumBands)
63a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
64a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == pNumBands)
65a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
66a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
67a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    // Note: no lock, but OK because it is const
68a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    *pNumBands = this->mNumBands;
69a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
70a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
71a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
72e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEqualizer_GetBandLevelRange(SLEqualizerItf self, SLmillibel *pMin,
73e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel *pMax)
74a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
75a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == pMin && NULL == pMax)
76a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
77a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
78a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    // Note: no lock, but OK because it is const
79a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL != pMin)
800b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        *pMin = this->mBandLevelRangeMin;
81a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL != pMax)
820b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        *pMax = this->mBandLevelRangeMax;
83a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
84a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
85a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
863a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IEqualizer_SetBandLevel(SLEqualizerItf self, SLuint16 band, SLmillibel level)
87a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
88a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
89d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    if (!(this->mBandLevelRangeMin <= level && level <= this->mBandLevelRangeMax))
90d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
91a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (band >= this->mNumBands)
92a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
930b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_lock_exclusive(this);
94a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    this->mLevels[band] = level;
950b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mPreset = SL_EQUALIZER_UNDEFINED;
960b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_unlock_exclusive(this);
97a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
98a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
99a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
100d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEqualizer_GetBandLevel(SLEqualizerItf self, SLuint16 band, SLmillibel *pLevel)
101a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
102a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == pLevel)
103a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
104a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
105a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (band >= this->mNumBands)
106a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
107a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    interface_lock_peek(this);
108a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    SLmillibel level = this->mLevels[band];
109a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    interface_unlock_peek(this);
110a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    *pLevel = level;
111a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
112a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
113a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
1143a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IEqualizer_GetCenterFreq(SLEqualizerItf self, SLuint16 band, SLmilliHertz *pCenter)
115a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
116a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == pCenter)
117a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
118a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
119a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (band >= this->mNumBands)
120a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
121a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    // Note: no lock, but OK because it is const
122a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    *pCenter = this->mBands[band].mCenter;
123a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
124a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
125a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
126a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic SLresult IEqualizer_GetBandFreqRange(SLEqualizerItf self, SLuint16 band,
127a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    SLmilliHertz *pMin, SLmilliHertz *pMax)
128a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
129a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == pMin && NULL == pMax)
130a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
131a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
132a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (band >= this->mNumBands)
133a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
134a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    // Note: no lock, but OK because it is const
135a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL != pMin)
136a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        *pMin = this->mBands[band].mMin;
137a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL != pMax)
138a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        *pMax = this->mBands[band].mMax;
139a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
140a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
141a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
1423a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IEqualizer_GetBand(SLEqualizerItf self, SLmilliHertz frequency, SLuint16 *pBand)
143a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
144a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == pBand)
145a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
146a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
147a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    // search for band whose center frequency has the closest ratio to 1.0
148a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    // assumes bands are unsorted (a pessimistic assumption)
149a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    // assumes bands can overlap (a pessimistic assumption)
150a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    // assumes a small number of bands, so no need for a fancier algorithm
151a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    const struct EqualizerBand *band;
152a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    float floatFreq = (float) frequency;
153a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    float bestRatio = 0.0;
154a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    SLuint16 bestBand = SL_EQUALIZER_UNDEFINED;
155a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    for (band = this->mBands; band < &this->mBands[this->mNumBands]; ++band) {
156a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        if (!(band->mMin <= frequency && frequency <= band->mMax))
157a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten            continue;
158a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        assert(band->mMin <= band->mCenter && band->mCenter <= band->mMax);
159a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        assert(band->mCenter != 0);
160a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        float ratio = frequency <= band->mCenter ?
161a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten            floatFreq / band->mCenter : band->mCenter / floatFreq;
162a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        if (ratio > bestRatio) {
163a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten            bestRatio = ratio;
164a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten            bestBand = band - this->mBands;
165a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        }
166a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    }
167a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    *pBand = band - this->mBands;
168a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
169a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
170a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
171d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEqualizer_GetCurrentPreset(SLEqualizerItf self, SLuint16 *pPreset)
172a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
173a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == pPreset)
174a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
175a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
1760b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_lock_shared(this);
1770b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    SLuint16 preset = this->mPreset;
1780b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_unlock_shared(this);
1790b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    *pPreset = preset;
180a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
181a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
182a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
183a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic SLresult IEqualizer_UsePreset(SLEqualizerItf self, SLuint16 index)
184a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
185a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
186a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (index >= this->mNumPresets)
187a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
1880b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_lock_exclusive(this);
1890b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    SLuint16 band;
1900b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    for (band = 0; band < this->mNumBands; ++band)
1910b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        this->mLevels[band] = EqualizerPresets[index].mLevels[band];
192a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    this->mPreset = index;
1930b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_unlock_exclusive(this);
194a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
195a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
196a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
197d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEqualizer_GetNumberOfPresets(SLEqualizerItf self, SLuint16 *pNumPresets)
198a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
199a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == pNumPresets)
200a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
201a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
202a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    // Note: no lock, but OK because it is const
203a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    *pNumPresets = this->mNumPresets;
204a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
205a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
206a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
207e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEqualizer_GetPresetName(SLEqualizerItf self, SLuint16 index, const SLchar **ppName)
208a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
209a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (NULL == ppName)
210a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
211a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
212a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    if (index >= this->mNumPresets)
213a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
2143a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    *ppName = (SLchar *) this->mPresets[index].mName;
215a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    return SL_RESULT_SUCCESS;
216a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
217a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
218a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const struct SLEqualizerItf_ IEqualizer_Itf = {
219a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_SetEnabled,
220a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_IsEnabled,
221a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetNumberOfBands,
222a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetBandLevelRange,
223a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_SetBandLevel,
224a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetBandLevel,
225a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetCenterFreq,
226a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetBandFreqRange,
227a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetBand,
228a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetCurrentPreset,
229a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_UsePreset,
230a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetNumberOfPresets,
231a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetPresetName
232a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten};
233a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
234a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenvoid IEqualizer_init(void *self)
235a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
236a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer *this = (IEqualizer *) self;
237a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    this->mItf = &IEqualizer_Itf;
238a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    this->mEnabled = SL_BOOLEAN_FALSE;
2393a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    this->mPreset = SL_EQUALIZER_UNDEFINED;
2400b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    unsigned band;
2413a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    for (band = 0; band < MAX_EQ_BANDS; ++band)
2420b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        this->mLevels[band] = 0;
2433a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    // const fields
2443a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    this->mNumPresets = MAX_EQ_PRESETS;
2453a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    this->mNumBands = MAX_EQ_BANDS;
2463a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    this->mBands = EqualizerBands;
2473a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    this->mPresets = EqualizerPresets;
2483a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    this->mBandLevelRangeMin = 0;
2493a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    this->mBandLevelRangeMax = 1000;
250a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
251