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"
2063c002ab68761be0eace98f28320d8eb2f3f7695Jean-Michel Trivi#ifdef ANDROID
215639df9d17ff8ae0ab83f1a31187a284044689d7Mikhail Naganov#include <system/audio_effects/effect_equalizer.h>
2263c002ab68761be0eace98f28320d8eb2f3f7695Jean-Michel Trivi#endif
23a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
243a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten#define MAX_EQ_PRESETS 3
253a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten
26faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
273a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic const struct EqualizerBand EqualizerBands[MAX_EQ_BANDS] = {
280b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    {1000, 1500, 2000},
290b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    {2000, 3000, 4000},
300b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    {4000, 5500, 7000},
310b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    {7000, 8000, 9000}
320b167267bda99b68346045ccab14e810121d5de4Glenn Kasten};
330b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
343a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic const struct EqualizerPreset {
353a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    const char *mName;
363a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    SLmillibel mLevels[MAX_EQ_BANDS];
373a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten} EqualizerPresets[MAX_EQ_PRESETS] = {
383a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    {"Default", {0, 0, 0, 0}},
393a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    {"Bass", {500, 200, 100, 0}},
403a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    {"Treble", {0, 100, 200, 500}}
410b167267bda99b68346045ccab14e810121d5de4Glenn Kasten};
424be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
430b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
44ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
45faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if defined(ANDROID)
46cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi/**
47cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi * returns true if this interface is not associated with an initialized Equalizer effect
48cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi */
49cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivistatic inline bool NO_EQ(IEqualizer* v) {
50cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi    return (v->mEqEffect == 0);
51cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi}
52768edbc2a8e7f197548cf1141689dd237d19c455Glenn Kasten#endif
53cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi
54cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi
55a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic SLresult IEqualizer_SetEnabled(SLEqualizerItf self, SLboolean enabled)
56a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
57ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
58ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
59bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IEqualizer *thiz = (IEqualizer *) self;
60bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_lock_exclusive(thiz);
61bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mEnabled = (SLboolean) enabled;
62faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
63ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    result = SL_RESULT_SUCCESS;
644be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#else
65bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    if (NO_EQ(thiz)) {
66cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi        result = SL_RESULT_CONTROL_LOST;
674be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    } else {
68cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi        android::status_t status =
69bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                thiz->mEqEffect->setEnabled((bool) thiz->mEnabled);
70cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi        result = android_fx_statusToResult(status);
714be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    }
724be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
73bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_unlock_exclusive(thiz);
74ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
75ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
76a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
77a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
78ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
79a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic SLresult IEqualizer_IsEnabled(SLEqualizerItf self, SLboolean *pEnabled)
80a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
81ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
82ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
8322ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten    if (NULL == pEnabled) {
8422ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
8522ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten    } else {
8622ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
8722ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        interface_lock_exclusive(thiz);
88faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten #if !defined(ANDROID)
8962496886cb4620c09bc5df0de70a883319616c25Aurimas Liutikas        SLboolean enabled = thiz->mEnabled;
9022ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        *pEnabled = enabled;
9122ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        result = SL_RESULT_SUCCESS;
92a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten #else
9322ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        if (NO_EQ(thiz)) {
9422ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten            result = SL_RESULT_CONTROL_LOST;
9522ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        } else {
9622ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten            *pEnabled = (SLboolean) thiz->mEqEffect->getEnabled();
9722ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten            result = SL_RESULT_SUCCESS;
9822ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        }
99a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten #endif
10022ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        interface_unlock_exclusive(thiz);
10122ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten    }
102cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi
103cfe5b1c6f0b65499d9aed2cf4b2a7e805fb02758Jean-Michel Trivi      SL_LEAVE_INTERFACE
104a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
105a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
106ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1073a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IEqualizer_GetNumberOfBands(SLEqualizerItf self, SLuint16 *pNumBands)
108a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
109ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pNumBands) {
112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
114bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // Note: no lock, but OK because it is const
116bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        *pNumBands = thiz->mNumBands;
117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
119ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
121a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
122a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
123ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
124e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEqualizer_GetBandLevelRange(SLEqualizerItf self, SLmillibel *pMin,
125e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel *pMax)
126a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
129ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pMin && NULL == pMax) {
130ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
131ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
132bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
133ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // Note: no lock, but OK because it is const
134ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL != pMin)
135bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            *pMin = thiz->mBandLevelRangeMin;
136ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL != pMax)
137bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            *pMax = thiz->mBandLevelRangeMax;
138ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
139ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
140ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
141ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
142a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
143a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
144ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1453a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IEqualizer_SetBandLevel(SLEqualizerItf self, SLuint16 band, SLmillibel level)
146a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
147ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
148ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
149bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IEqualizer *thiz = (IEqualizer *) self;
150bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    if (!(thiz->mBandLevelRangeMin <= level && level <= thiz->mBandLevelRangeMax) ||
151bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            (band >= thiz->mNumBands)) {
152ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
153ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
154bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_lock_exclusive(thiz);
155faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
156bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mLevels[band] = level;
157bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mPreset = SL_EQUALIZER_UNDEFINED;
158ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
1594be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#else
160bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (NO_EQ(thiz)) {
1617e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            result = SL_RESULT_CONTROL_LOST;
1627e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi        } else {
1639cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            android::status_t status =
164bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                android_eq_setParam(thiz->mEqEffect, EQ_PARAM_BAND_LEVEL, band, &level);
1659cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            result = android_fx_statusToResult(status);
1669cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi        }
1674be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
168bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_unlock_exclusive(thiz);
169ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
170ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
171ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
172a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
173a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
174ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
175d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEqualizer_GetBandLevel(SLEqualizerItf self, SLuint16 band, SLmillibel *pLevel)
176a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
177ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
178ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
179ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pLevel) {
180ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
181ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
182bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
183ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // const, no lock needed
184bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (band >= thiz->mNumBands) {
185ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
186ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
1879cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            SLmillibel level = 0;
188bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            interface_lock_shared(thiz);
189faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
190bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            level = thiz->mLevels[band];
191ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
1924be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#else
193bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            if (NO_EQ(thiz)) {
1947e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi                result = SL_RESULT_CONTROL_LOST;
1957e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            } else {
1969cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi                android::status_t status =
197bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                    android_eq_getParam(thiz->mEqEffect, EQ_PARAM_BAND_LEVEL, band, &level);
1989cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi                result = android_fx_statusToResult(status);
1999cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            }
2004be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
201bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            interface_unlock_shared(thiz);
2024be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi            *pLevel = level;
203ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
204ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
205ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
206ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
207a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
208a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
209ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
2103a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IEqualizer_GetCenterFreq(SLEqualizerItf self, SLuint16 band, SLmilliHertz *pCenter)
211a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
212ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
213ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
214ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pCenter) {
215ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
216ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
217bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
218bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (band >= thiz->mNumBands) {
219ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
221faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
222ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // Note: no lock, but OK because it is const
223bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            *pCenter = thiz->mBands[band].mCenter;
224ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
2254be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#else
2269cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            SLmilliHertz center = 0;
227bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            interface_lock_shared(thiz);
228bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            if (NO_EQ(thiz)) {
2297e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi                result = SL_RESULT_CONTROL_LOST;
2307e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            } else {
2319cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi                android::status_t status =
232bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                    android_eq_getParam(thiz->mEqEffect, EQ_PARAM_CENTER_FREQ, band, &center);
2339cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi                result = android_fx_statusToResult(status);
2349cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            }
235bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            interface_unlock_shared(thiz);
2364be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi            *pCenter = center;
2374be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
238ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
239ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
240ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
241ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
242a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
243a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
245a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic SLresult IEqualizer_GetBandFreqRange(SLEqualizerItf self, SLuint16 band,
246a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    SLmilliHertz *pMin, SLmilliHertz *pMax)
247a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
248ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pMin && NULL == pMax) {
251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
252ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
253bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
254bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (band >= thiz->mNumBands) {
255ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
256ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
257faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
258ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // Note: no lock, but OK because it is const
259ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            if (NULL != pMin)
260bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                *pMin = thiz->mBands[band].mMin;
261ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            if (NULL != pMax)
262bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                *pMax = thiz->mBands[band].mMax;
263ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
2644be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#else
2659cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            SLmilliHertz range[2] = {0, 0}; // SLmilliHertz is SLuint32
266bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            interface_lock_shared(thiz);
267bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            if (NO_EQ(thiz)) {
2687e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi                result = SL_RESULT_CONTROL_LOST;
2697e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            } else {
2709cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi                android::status_t status =
271bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                    android_eq_getParam(thiz->mEqEffect, EQ_PARAM_BAND_FREQ_RANGE, band, range);
2729cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi                result = android_fx_statusToResult(status);
2739cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            }
274bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            interface_unlock_shared(thiz);
2754be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi            if (NULL != pMin) {
2764be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi                *pMin = range[0];
2774be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi            }
2784be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi            if (NULL != pMax) {
2794be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi                *pMax = range[1];
2804be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi            }
2814be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
282ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
283ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
284ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
285ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
286a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
287a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
2893a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IEqualizer_GetBand(SLEqualizerItf self, SLmilliHertz frequency, SLuint16 *pBand)
290a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
292ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
293ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pBand) {
294ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
295ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
296bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
297faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
298ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // search for band whose center frequency has the closest ratio to 1.0
299ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // assumes bands are unsorted (a pessimistic assumption)
300ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // assumes bands can overlap (a pessimistic assumption)
301ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // assumes a small number of bands, so no need for a fancier algorithm
302ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        const struct EqualizerBand *band;
303ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        float floatFreq = (float) frequency;
304ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        float bestRatio = 0.0;
305ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLuint16 bestBand = SL_EQUALIZER_UNDEFINED;
306bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        for (band = thiz->mBands; band < &thiz->mBands[thiz->mNumBands]; ++band) {
307ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            if (!(band->mMin <= frequency && frequency <= band->mMax))
308ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                continue;
309ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(band->mMin <= band->mCenter && band->mCenter <= band->mMax);
310ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(band->mCenter != 0);
311ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            float ratio = frequency <= band->mCenter ?
312ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                floatFreq / band->mCenter : band->mCenter / floatFreq;
313ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            if (ratio > bestRatio) {
314ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                bestRatio = ratio;
315bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                bestBand = band - thiz->mBands;
316ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            }
317a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten        }
3187c3fe21525e62f24acc9d391f9d396ce2d7e57acGlenn Kasten        *pBand = bestBand;
319ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
3204be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#else
3219cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi        uint16_t band = 0;
322bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_lock_shared(thiz);
323bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (NO_EQ(thiz)) {
3247e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            result = SL_RESULT_CONTROL_LOST;
3257e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi        } else {
3269cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            android::status_t status =
327bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                android_eq_getParam(thiz->mEqEffect, EQ_PARAM_GET_BAND, frequency, &band);
3289cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            result = android_fx_statusToResult(status);
3299cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi        }
330bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_unlock_shared(thiz);
3314be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        *pBand = (SLuint16)band;
3324be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
333a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    }
334ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
335ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
336a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
337a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
338ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
339d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEqualizer_GetCurrentPreset(SLEqualizerItf self, SLuint16 *pPreset)
340a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
341ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
342ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
343ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pPreset) {
344ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
345ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
346bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
347bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_lock_shared(thiz);
348faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
349bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        SLuint16 preset = thiz->mPreset;
350bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_unlock_shared(thiz);
351ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *pPreset = preset;
352ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
3534be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#else
3549cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi        uint16_t preset = 0;
355bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (NO_EQ(thiz)) {
3567e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            result = SL_RESULT_CONTROL_LOST;
3577e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi        } else {
3589cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            android::status_t status =
359bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                    android_eq_getParam(thiz->mEqEffect, EQ_PARAM_CUR_PRESET, 0, &preset);
3609cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            result = android_fx_statusToResult(status);
3619cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi        }
362bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_unlock_shared(thiz);
3639cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi
364a6585530d8cf92658042c001b6a27fc397c62b9fGlenn Kasten        *pPreset = (SLuint16) preset;
3654be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
3664be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
367ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
368ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
369ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
370a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
371a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
372ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
373a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic SLresult IEqualizer_UsePreset(SLEqualizerItf self, SLuint16 index)
374a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
375ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
376a7b79e766ec6d95e9236168c27461c2ebaef4659Glenn Kasten    SL_LOGV("Equalizer::UsePreset index=%u", index);
377ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
378bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IEqualizer *thiz = (IEqualizer *) self;
379bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    if (index >= thiz->mNumPresets) {
380ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
381ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
382bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_lock_exclusive(thiz);
383faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
384ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLuint16 band;
385bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        for (band = 0; band < thiz->mNumBands; ++band)
386bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            thiz->mLevels[band] = EqualizerPresets[index].mLevels[band];
387bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mPreset = index;
388bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_unlock_exclusive(thiz);
389ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
3904be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#else
391bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (NO_EQ(thiz)) {
3927e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            result = SL_RESULT_CONTROL_LOST;
3937e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi        } else {
3949cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            android::status_t status =
395bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                android_eq_setParam(thiz->mEqEffect, EQ_PARAM_CUR_PRESET, 0, &index);
3969cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi            result = android_fx_statusToResult(status);
3979cd3c9e7a2395647b92c32f33c06cf9fd546b22fJean-Michel Trivi        }
398bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_unlock_shared(thiz);
3994be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
400ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
401ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
402ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
403a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
404a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
405ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
406d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEqualizer_GetNumberOfPresets(SLEqualizerItf self, SLuint16 *pNumPresets)
407a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
408ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
409ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
410ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pNumPresets) {
411ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
412ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
413bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
414ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        // Note: no lock, but OK because it is const
415bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        *pNumPresets = thiz->mNumPresets;
4167e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi
417ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
418ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
419ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
420ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
421a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
422a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
423ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
424e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEqualizer_GetPresetName(SLEqualizerItf self, SLuint16 index, const SLchar **ppName)
425a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
426ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
427ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
428ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == ppName) {
429ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
430ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
431bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IEqualizer *thiz = (IEqualizer *) self;
432faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
433bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (index >= thiz->mNumPresets) {
434ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
435ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
436bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            *ppName = (SLchar *) thiz->mPresets[index].mName;
437ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
438ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
4394be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#else
440bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (index >= thiz->mNumPresets) {
4414be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi            result = SL_RESULT_PARAMETER_INVALID;
4424be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        } else {
4437e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            // FIXME query preset name rather than retrieve it from the engine.
4447e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            //       In SL ES 1.0.1, the strings must exist for the lifetime of the engine.
4457e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            //       Starting in 1.1, this will change and we don't need to hold onto the strings
4467e01bc6208fb5b4a2a0019d67bf74373f8ee9428Jean-Michel Trivi            //       for so long as they will copied into application space.
447bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            *ppName = (SLchar *) thiz->mThis->mEngine->mEqPresetNames[index];
4484be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi            result = SL_RESULT_SUCCESS;
4494be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        }
4504be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
451ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
452ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
453ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
454a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
455a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
456ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
457a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const struct SLEqualizerItf_ IEqualizer_Itf = {
458a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_SetEnabled,
459a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_IsEnabled,
460a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetNumberOfBands,
461a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetBandLevelRange,
462a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_SetBandLevel,
463a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetBandLevel,
464a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetCenterFreq,
465a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetBandFreqRange,
466a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetBand,
467a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetCurrentPreset,
468a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_UsePreset,
469a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetNumberOfPresets,
470a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten    IEqualizer_GetPresetName
471a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten};
472a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten
473a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenvoid IEqualizer_init(void *self)
474a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten{
475bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IEqualizer *thiz = (IEqualizer *) self;
476bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mItf = &IEqualizer_Itf;
477bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mEnabled = SL_BOOLEAN_FALSE;
478bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mPreset = SL_EQUALIZER_UNDEFINED;
479a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#if 0 < MAX_EQ_BANDS
4800b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    unsigned band;
4813a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    for (band = 0; band < MAX_EQ_BANDS; ++band)
482bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mLevels[band] = 0;
4834b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten#endif
4843a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    // const fields
485bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mNumPresets = 0;
486bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mNumBands = 0;
487faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if !defined(ANDROID)
488bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mBands = EqualizerBands;
489bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mPresets = EqualizerPresets;
4904be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
491bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mBandLevelRangeMin = 0;
492bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mBandLevelRangeMax = 0;
493faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if defined(ANDROID)
494bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    memset(&thiz->mEqDescriptor, 0, sizeof(effect_descriptor_t));
495a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    // placement new (explicit constructor)
496bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    (void) new (&thiz->mEqEffect) android::sp<android::AudioEffect>();
497a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#endif
498a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten}
4994be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
500a9a70a4451545034c9263dd55b181f2912534c37Glenn Kastenvoid IEqualizer_deinit(void *self)
501a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten{
502faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if defined(ANDROID)
503bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IEqualizer *thiz = (IEqualizer *) self;
504a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    // explicit destructor
505bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mEqEffect.~sp();
506a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#endif
507a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten}
5084be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
509a9a70a4451545034c9263dd55b181f2912534c37Glenn Kastenbool IEqualizer_Expose(void *self)
510a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten{
511faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if defined(ANDROID)
512bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IEqualizer *thiz = (IEqualizer *) self;
513bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    if (!android_fx_initEffectDescriptor(SL_IID_EQUALIZER, &thiz->mEqDescriptor)) {
514a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten        SL_LOGE("Equalizer initialization failed");
515bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mNumPresets = 0;
516bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mNumBands = 0;
517bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mBandLevelRangeMin = 0;
518bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mBandLevelRangeMax = 0;
519a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten        return false;
520f5fce95f98037ea4ab341b416c82444af595313dJean-Michel Trivi    }
5214be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif
522a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten    return true;
523a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten}
524